Help generation: add the ability to generate an image from inlined Scilab code
[scilab.git] / scilab / modules / helptools / src / java / org / scilab / modules / helptools / HTMLDocbookTagConverter.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2010 - Calixte DENIZET
4  *
5  * This file must be used under the terms of the CeCILL.
6  * This source file is licensed as described in the file COPYING, which
7  * you should have received as part of this distribution.  The terms
8  * are also available at
9  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12
13 package org.scilab.modules.helptools;
14
15 import java.io.File;
16 import java.io.IOException;
17 import java.net.URI;
18 import java.net.URISyntaxException;
19 import java.util.Date;
20 import java.util.Map;
21 import java.util.Stack;
22 import java.util.regex.Pattern;
23
24 import org.xml.sax.SAXException;
25
26 import org.scilab.modules.helptools.image.ImageConverter;
27 import org.scilab.modules.helptools.image.LaTeXImageConverter;
28 import org.scilab.modules.helptools.image.MathMLImageConverter;
29 import org.scilab.modules.helptools.image.ScilabImageConverter;
30 import org.scilab.modules.helptools.image.SVGImageConverter;
31 import org.scilab.modules.helptools.scilab.ScilabLexer;
32 import org.scilab.modules.helptools.scilab.HTMLScilabCodeHandler;
33 import org.scilab.modules.helptools.scilab.AbstractScilabCodeHandler;
34 import org.scilab.modules.helptools.XML.XMLLexer;
35 import org.scilab.modules.helptools.XML.HTMLXMLCodeHandler;
36 import org.scilab.modules.helptools.c.CLexer;
37 import org.scilab.modules.helptools.c.HTMLCCodeHandler;
38 import org.scilab.modules.helptools.java.JavaLexer;
39 import org.scilab.modules.localization.Messages;
40
41 /**
42  * Class to convert DocBook to HTML
43  * @author Calixte DENIZET
44  */
45 public class HTMLDocbookTagConverter extends DocbookTagConverter implements TemplateFiller {
46
47     private static final String SCILAB_URI = "http://www.scilab.org";
48     private static final String LATEXBASENAME = "Equation_LaTeX_";
49     private static final String VERSION = Messages.gettext("Version");
50     private static final String DESCRIPTION = Messages.gettext("Description");
51
52     private StringBuilder buffer = new StringBuilder(8192);
53     private int latexCompt;
54     private String imageDir;
55     private String outName;
56     private String urlBase;
57     private boolean linkToTheWeb;
58     private boolean hasExamples;
59     private int warnings;
60     private int nbFiles;
61
62     protected Map<String, String> mapId;
63     protected Map<String, String> tocitem;
64     protected HTMLDocbookLinkResolver.TreeId tree;
65     protected Map<String, HTMLDocbookLinkResolver.TreeId> mapTreeId;
66     protected Map<String, String> mapIdPurpose;
67
68     protected TemplateHandler templateHandler;
69
70     protected ScilabLexer scilabLexer;
71     protected XMLLexer xmlLexer;
72     protected CLexer cLexer;
73     protected JavaLexer javaLexer;
74
75     protected String bookTitle = "";
76     protected String partTitle = "";
77     protected String chapterTitle = "";
78     protected String sectionTitle = "";
79     protected String fileSubtitle = "";
80
81     protected String refpurpose = "";
82     protected String refname = "";
83     protected String version;
84     protected String appendToProgramListing;
85     protected String appendForExecToProgramListing;
86     protected String prependToProgramListing;
87     protected String currentId;
88     protected String indexFilename = "index" /*UUID.randomUUID().toString()*/ + ".html";
89
90     protected boolean isToolbox;
91
92     /**
93      * Constructor
94      * @param inName the name of the input stream
95      * @param outName the output directory
96      * @param primConf the file containing the primitives of Scilab
97      * @param macroConf the file containing the macros of Scilab
98      * @param template the template to use
99      * @param version the version
100      * @param imageDir the image directory (relative to outName)
101      * @param isToolbox is true when compile a toolbox' help
102      * @param urlBase the base url for external link
103      */
104     public HTMLDocbookTagConverter(String inName, String outName, String[] primConf, String[] macroConf, String template, String version, String imageDir, boolean isToolbox, String urlBase) throws IOException, SAXException {
105         super(inName);
106
107         this.version = version;
108         this.imageDir = imageDir;
109         this.outName = outName + File.separator;
110         HTMLDocbookLinkResolver resolver = new HTMLDocbookLinkResolver(inName);
111         mapId = resolver.getMapId();
112         tocitem = resolver.getToc();
113         tree = resolver.getTree();
114         mapTreeId = resolver.getMapTreeId();
115         mapIdPurpose = resolver.getMapIdPurpose();
116         scilabLexer = new ScilabLexer(primConf, macroConf);
117         this.urlBase = urlBase;
118         this.linkToTheWeb = urlBase != null && !urlBase.equals("scilab://");
119         this.isToolbox = isToolbox;
120         if (isToolbox) {// we generate a toolbox's help
121             HTMLScilabCodeHandler.setLinkWriter(new AbstractScilabCodeHandler.LinkWriter() {
122                 public String getLink(String id) {
123                     if (id.length() > 0 && id.charAt(0) == '%') {
124                         id = id.replace("%", "percent");
125                     }
126                     String link = mapId.get(id);
127                     if (link == null) {
128                         return HTMLDocbookTagConverter.this.urlBase + id;
129                     } else {
130                         return link;
131                     }
132                 }
133             });
134         } else {// we generate Scilab's help
135             HTMLScilabCodeHandler.setLinkWriter(new AbstractScilabCodeHandler.LinkWriter() {
136                 public String getLink(String id) {
137                     if (id.length() > 0 && id.charAt(0) == '%') {
138                         id = id.replace("%", "percent");
139                     }
140                     return mapId.get(id);
141                 }
142             });
143         }
144
145         xmlLexer = new XMLLexer();
146         cLexer = new CLexer();
147         javaLexer = new JavaLexer();
148         File tpl = new File(template);
149         templateHandler = new TemplateHandler(this, tpl);
150         ImageConverter.registerExternalImageConverter(LaTeXImageConverter.getInstance());
151         ImageConverter.registerExternalImageConverter(MathMLImageConverter.getInstance());
152         ImageConverter.registerExternalImageConverter(SVGImageConverter.getInstance());
153         ImageConverter.registerExternalImageConverter(ScilabImageConverter.getInstance());
154     }
155
156     /**
157      * @return the buffer used
158      */
159     public StringBuilder getBuffer() {
160         return buffer;
161     }
162
163     /**
164      * @param tag the tag name
165      * @param contents the contents to enclose between opening and closing tags
166      */
167     public String encloseContents(final String tag, final String contents) {
168         buffer.setLength(0);
169         buffer.append("<");
170         buffer.append(tag);
171         buffer.append(">");
172         if (contents != null) {
173             buffer.append(contents);
174         }
175         buffer.append("</");
176         buffer.append(tag);
177         buffer.append(">");
178
179         return buffer.toString();
180     }
181
182     /**
183      * @param tag the tag name
184      * @param attrs the attributes {attr1, value1, attr2, value2, ...}
185      * @param contents the contents to enclose between opening and closing tags
186      */
187     public String encloseContents(final String tag, final String[] attrs, final String contents) {
188         buffer.setLength(0);
189         buffer.append("<");
190         buffer.append(tag);
191         if (attrs != null) {
192             for (int i = 0; i < attrs.length; i += 2) {
193                 buffer.append(" ");
194                 buffer.append(attrs[i]);
195                 buffer.append("=\"");
196                 buffer.append(attrs[i + 1]);
197                 buffer.append("\"");
198             }
199         }
200
201         buffer.append(">");
202         if (contents != null) {
203             buffer.append(contents);
204         }
205         buffer.append("</");
206         buffer.append(tag);
207         buffer.append(">");
208
209         return buffer.toString();
210     }
211
212     /**
213      * @param tag the tag name
214      * @param clazz the css class name
215      * @param contents the contents to enclose between opening and closing tags
216      */
217     public String encloseContents(final String tag, final String clazz, final String contents) {
218         buffer.setLength(0);
219         buffer.append("<");
220         buffer.append(tag);
221         buffer.append(" class=\"");
222         buffer.append(clazz);
223         buffer.append("\">");
224         if (contents != null) {
225             buffer.append(contents);
226         }
227         buffer.append("</");
228         buffer.append(tag);
229         buffer.append(">");
230
231         return buffer.toString();
232     }
233
234     /**
235      * {@inheritDoc}
236      */
237     public boolean isEscapable(final String tagName, final String uri) {
238         return !"latex".equals(tagName) && !"screen".equals(tagName) && !"programlisting".equals(tagName) && !"synopsis".equals(tagName) && !(uri.equals(SCILAB_URI) && tagName.equals("image"));
239     }
240
241     /**
242      * {@inheritDoc}
243      */
244     public boolean isTrimable(final String tagName) {
245         return !"screen".equals(tagName) && !"programlisting".equals(tagName) && !"synopsis".equals(tagName);
246     }
247
248     /**
249      * @param fileName the file to create
250      * @param subtitle the subtitle of the file
251      * @param contents the contents of the file
252      */
253     public void createHTMLFile(final String id, final String fileName, final String subtitle, final String contents) {
254         if (!hasError) {
255             fileSubtitle = subtitle;
256             nbFiles++;
257             templateHandler.generateFileFromTemplate(outName + fileName, id, contents);
258         }
259     }
260
261     /**
262      * {@inheritDoc}
263      */
264     public String makeTitle(final String id) {
265         if (refname.length() > 0) {
266             return tocitem.get(id);
267         }
268
269         return "";
270     }
271
272     /**
273      * {@inheritDoc}
274      */
275     public String makeSubtitle(final String id) {
276         return fileSubtitle;
277     }
278
279     /**
280      * {@inheritDoc}
281      */
282     public String makePrevious(final String id) {
283         buffer.setLength(0);
284         buffer.append("<span class=\"previous\">");
285         HTMLDocbookLinkResolver.TreeId leaf = mapTreeId.get(id);
286         if (leaf == null) {
287             return "";
288         }
289         HTMLDocbookLinkResolver.TreeId prev = leaf.getPrevious();
290         if (prev.parent != null) {
291             buffer.append("<a href=\"");
292             buffer.append(mapId.get(prev.id));
293             buffer.append("\">&lt;&lt; ");
294             buffer.append(tocitem.get(prev.id));
295             buffer.append("</a></span>\n");
296
297             return buffer.toString();
298         }
299
300         return "";
301     }
302
303     /**
304      * {@inheritDoc}
305      */
306     public String makePath(final String id) {
307         buffer.setLength(0);
308         buffer.append("<span class=\"path\">");
309         HTMLDocbookLinkResolver.TreeId leaf = mapTreeId.get(id);
310         if (leaf == null) {
311             return "";
312         }
313         String str = tocitem.get(id);
314         leaf = leaf.parent;
315         while (leaf != null && !leaf.isRoot()) {
316             str = "<a href=\"" + mapId.get(leaf.id) + "\">" + tocitem.get(leaf.id) + "</a> &gt; " + str;
317             leaf = leaf.parent;
318         }
319
320         str = "<a href=\"" + indexFilename  + "\">" + bookTitle + "</a> &gt;&gt; " + str;
321         buffer.append(str);
322         buffer.append("</span>\n");
323
324         return buffer.toString();
325     }
326
327     /**
328      * {@inheritDoc}
329      */
330     public String makeTop(final String id) {
331         buffer.setLength(0);
332         buffer.append("<span class=\"top\">");
333         HTMLDocbookLinkResolver.TreeId leaf = mapTreeId.get(id);
334         if (leaf == null) {
335             return "";
336         }
337
338         leaf = leaf.parent;
339         if (leaf != null) {
340             buffer.append("<a href=\"");
341             if (!leaf.isRoot()) {
342                 buffer.append(mapId.get(leaf.id));
343                 buffer.append("\">");
344                 buffer.append(tocitem.get(leaf.id));
345             } else {
346                 buffer.append(indexFilename);
347                 buffer.append("\">");
348                 buffer.append(bookTitle);
349             }
350             buffer.append("</a></span>\n");
351         } else {
352             return "";
353         }
354
355         return buffer.toString();
356     }
357
358     /**
359      * {@inheritDoc}
360      */
361     public String makeNext(final String id) {
362         buffer.setLength(0);
363         buffer.append("<span class=\"next\">");
364         HTMLDocbookLinkResolver.TreeId leaf = mapTreeId.get(id);
365         if (leaf == null) {
366             return "";
367         }
368         HTMLDocbookLinkResolver.TreeId next = leaf.getNext();
369         if (next != null) {
370             buffer.append("<a href=\"");
371             buffer.append(mapId.get(next.id));
372             buffer.append("\">");
373             buffer.append(tocitem.get(next.id));
374             buffer.append(" &gt;&gt;</a></span>\n");
375
376             return buffer.toString();
377         }
378
379         return "";
380     }
381
382     /**
383      * {@inheritDoc}
384      */
385     public String makeStart(final String id) {
386         buffer.setLength(0);
387         buffer.append("<span class=\"start\">");
388         buffer.append("<a href=\"");
389         buffer.append(indexFilename);
390         buffer.append("\">");
391         buffer.append(bookTitle);
392         buffer.append("</a></span>\n");
393
394         return buffer.toString();
395     }
396
397     /**
398      * {@inheritDoc}
399      */
400     public String makeTocList(final String id) {
401         buffer.setLength(0);
402         HTMLDocbookLinkResolver.TreeId leaf = mapTreeId.get(id);
403         if (leaf == null) {
404             return "";
405         }
406
407         HTMLDocbookLinkResolver.TreeId parent = leaf.parent;
408         buffer.append("<ul class=\"toc\">\n");
409         String str = "";
410         while (parent != null && !parent.isRoot()) {
411             str = "<li class=\"parent\"><a href=\"" + mapId.get(parent.id) + "\">" + tocitem.get(parent.id) + "</a></li>\n" + str;
412             parent = parent.parent;
413         }
414         buffer.append("<li class=\"root\"><a href=\"");
415         buffer.append(indexFilename);
416         buffer.append("\">");
417         buffer.append(bookTitle);
418         buffer.append("</a></li>\n");
419         buffer.append(str);
420
421         parent = leaf.parent;
422
423         for (HTMLDocbookLinkResolver.TreeId c : parent.children) {
424             if (c == leaf) {
425                 buffer.append("<li class=\"list-active\"><a href=\"");
426             } else {
427                 buffer.append("<li><a href=\"");
428             }
429             buffer.append(mapId.get(c.id));
430             buffer.append("\">");
431             buffer.append(tocitem.get(c.id));
432             buffer.append("</a></li>\n");
433         }
434         buffer.append("</ul>\n");
435
436         return buffer.toString();
437     }
438
439     /**
440      * {@inheritDoc}
441      */
442     public String makeLastModified(final String id) {
443         buffer.setLength(0);
444         try {
445             buffer.append("<span class=\"lastmodified\">");
446             buffer.append(new Date(new File(new URI(currentFileName)).lastModified()).toString());
447             buffer.append("</span>\n");
448         } catch (URISyntaxException e) {
449             e.printStackTrace();
450         }
451         return buffer.toString();
452     }
453
454     /**
455      * {@inheritDoc}
456      */
457     public String makeGenerationDate(final String id) {
458         buffer.setLength(0);
459         buffer.append("<span class=\"generationdate\">");
460         buffer.append(new Date(System.currentTimeMillis()).toString());
461         buffer.append("</span>\n");
462
463         return buffer.toString();
464     }
465
466     /**
467      * {@inheritDoc}
468      */
469     public String makeVersion(final String id) {
470         buffer.setLength(0);
471         buffer.append("<span class=\"version\">");
472         buffer.append(version);
473         buffer.append("</span>\n");
474
475         return buffer.toString();
476     }
477
478     /**
479      * Handle a refentry
480      * @param attributes the tag attributes
481      * @param contents the tag contents
482      * @return the HTML code
483      * @throws SAXEception if an error is encountered
484      */
485     public String handleRefentry(final Map<String, String> attributes, final String contents) throws SAXException {
486         String id = attributes.get("id");
487         if (id != null) {
488             currentId = id;
489         }
490         String fileName = mapId.get(currentId);
491         createHTMLFile(currentId, fileName, refpurpose, contents);
492         if (!hasExamples) {
493             warnings++;
494             //System.err.println("Warning (should be fixed): no example in " + currentFileName);
495         } else {
496             hasExamples = false;
497         }
498         String rp = encloseContents("span", "refentry-description", refpurpose);
499         String str = encloseContents("li", encloseContents("a", new String[] {"href", fileName, "class", "refentry"}, currentId) + " &#8212; " + rp);
500         refpurpose = "";
501         refname = "";
502         currentId = null;
503
504         return str;
505     }
506
507     /**
508      * Handle a section
509      * @param attributes the tag attributes
510      * @param contents the tag contents
511      * @return the HTML code
512      * @throws SAXEception if an error is encountered
513      */
514     public String handleSection(final Map<String, String> attributes, final String contents) throws SAXException {
515         String fileName = attributes.get("id") + ".html";
516         String str = encloseContents("ul", "list-refentry", contents);
517         String title = encloseContents("h3", "title-section", sectionTitle);
518         createHTMLFile(attributes.get("id"), fileName, sectionTitle, title + "\n" + str);
519
520         str = encloseContents("li", encloseContents("a", new String[] {"href", fileName, "class", "section"}, sectionTitle) + "\n" + str);
521         sectionTitle = "";
522
523         return str;
524     }
525
526     /**
527      * Handle a book
528      * @param attributes the tag attributes
529      * @param contents the tag contents
530      * @return the HTML code
531      * @throws SAXEception if an error is encountered
532      */
533     public String handleBook(final Map<String, String> attributes, final String contents) throws SAXException {
534         String str = encloseContents("ul", "list-part", contents);
535         String btitle;
536         if (bookTitle.trim().equalsIgnoreCase("Scilab")) {
537             btitle = version;
538         } else {
539             btitle = bookTitle;
540         }
541         String title = encloseContents("h3", "book-title", btitle);
542         createHTMLFile("index", indexFilename, btitle, title + "\n" + str);
543
544         if (warnings != 0) {
545             System.err.println("Total files without example: " + warnings);
546             System.err.println("Total generated html files: " + nbFiles);
547         }
548
549         return encloseContents("li", encloseContents("a", new String[] {"href", indexFilename, "class", "part"}, bookTitle) + "\n" + str);
550     }
551
552     /**
553      * Handle a part
554      * @param attributes the tag attributes
555      * @param contents the tag contents
556      * @return the HTML code
557      * @throws SAXEception if an error is encountered
558      */
559     public String handlePart(final Map<String, String> attributes, final String contents) throws SAXException {
560         String fileName = attributes.get("id") + ".html";
561         String str = encloseContents("ul", "list-chapter", contents);
562         String title = encloseContents("h3", "title-part", partTitle);
563         createHTMLFile(attributes.get("id"), fileName, partTitle, title + "\n" + str);
564
565         str = encloseContents("li", encloseContents("a", new String[] {"href", fileName, "class", "part"}, partTitle) + "\n" + str);
566         partTitle = "";
567
568         return str;
569     }
570
571     /**
572      * Handle a chapter
573      * @param attributes the tag attributes
574      * @param contents the tag contents
575      * @return the HTML code
576      * @throws SAXEception if an error is encountered
577      */
578     public String handleChapter(final Map<String, String> attributes, final String contents) throws SAXException {
579         String fileName = attributes.get("id") + ".html";
580         String str = encloseContents("ul", "list-refentry", contents);
581         String title = encloseContents("h3", "title-chapter", chapterTitle);
582         createHTMLFile(attributes.get("id"), fileName, chapterTitle, title + "\n" + str);
583
584         str = encloseContents("li", encloseContents("a", new String[] {"href", fileName, "class", "chapter"}, chapterTitle) + "\n" + str);
585         chapterTitle = "";
586
587         return str;
588     }
589
590     // partiellement merdique car le style de title depend du noeud pere.
591     /**
592      * Handle a title
593      * @param attributes the tag attributes
594      * @param contents the tag contents
595      * @return the HTML code
596      * @throws SAXEception if an error is encountered
597      */
598     public String handleTitle(final Map<String, String> attributes, final String contents) throws SAXException {
599         String clazz = "title";
600         String parent = getParentTagName();
601         if (parent.equals("chapter")) {
602             chapterTitle = contents;
603         } else if (parent.equals("part")) {
604             partTitle = contents;
605         } else if (parent.equals("info")) {
606             bookTitle = contents;
607         } else if (parent.equals("section")) {
608             sectionTitle = contents;
609         } else if (parent.equals("refsection") && Pattern.matches("^[ \\t]*ex[ea]mpl[eo].*", contents.toLowerCase())) {
610             hasExamples = true;
611             return encloseContents("h3", clazz, contents);
612         } else {
613             return encloseContents("h3", clazz, contents);
614         }
615
616         return null;
617     }
618
619     /**
620      * Handle a para
621      * @param attributes the tag attributes
622      * @param contents the tag contents
623      * @return the HTML code
624      * @throws SAXEception if an error is encountered
625      */
626     public String handlePara(final Map<String, String> attributes, final String contents) throws SAXException {
627         return encloseContents("p", "para", contents);
628     }
629
630     /**
631      * Handle a literal
632      * @param attributes the tag attributes
633      * @param contents the tag contents
634      * @return the HTML code
635      * @throws SAXEception if an error is encountered
636      */
637     public String handleLiteral(final Map<String, String> attributes, final String contents) throws SAXException {
638         return encloseContents("code", "literal", contents);
639     }
640
641     /**
642      * Handle a refnamediv
643      * @param attributes the tag attributes
644      * @param contents the tag contents
645      * @return the HTML code
646      * @throws SAXEception if an error is encountered
647      */
648     public String handleRefnamediv(final Map<String, String> attributes, final String contents) throws SAXException {
649         String id = attributes.get("id");
650         if (id != null) {
651             currentId = id;
652         }
653
654         return encloseContents("div", "refnamediv", contents);
655     }
656
657     /**
658      * Handle a refname
659      * @param attributes the tag attributes
660      * @param contents the tag contents
661      * @return the HTML code
662      * @throws SAXEception if an error is encountered
663      */
664     public String handleRefname(final Map<String, String> attributes, final String contents) throws SAXException {
665         refname = contents;
666         return encloseContents("h1", "refname", contents);
667     }
668
669     /**
670      * Handle a refpurpose
671      * @param attributes the tag attributes
672      * @param contents the tag contents
673      * @return the HTML code
674      * @throws SAXEception if an error is encountered
675      */
676     public String handleRefpurpose(final Map<String, String> attributes, final String contents) throws SAXException {
677         refpurpose = contents;
678         return encloseContents("p", "refpurpose", contents);
679     }
680
681     /**
682      * Handle a refsynopsisdiv
683      * @param attributes the tag attributes
684      * @param contents the tag contents
685      * @return the HTML code
686      * @throws SAXEception if an error is encountered
687      */
688     public String handleRefsynopsisdiv(final Map<String, String> attributes, final String contents) throws SAXException {
689         String id = attributes.get("id");
690         if (id != null) {
691             return "<a name=\"" + id + "\"></a>" + encloseContents("div", "refsynopsisdiv", contents);
692         } else {
693             return encloseContents("div", "refsynopsisdiv", contents);
694         }
695     }
696
697     /**
698      * Handle a synopsis
699      * @param attributes the tag attributes
700      * @param contents the tag contents
701      * @return the HTML code
702      * @throws SAXEception if an error is encountered
703      */
704     public String handleSynopsis(final Map<String, String> attributes, final String contents) throws SAXException {
705         String id = attributes.get("id");
706         String str = encloseContents("div", "synopsis", encloseContents("pre", SynopsisLexer.convert(refname, contents)));
707         if (id != null) {
708             return "<a name=\"" + id + "\"></a>" + str;
709         } else {
710             return str;
711         }
712     }
713
714     /**
715      * Handle a info
716      * @param attributes the tag attributes
717      * @param contents the tag contents
718      * @return the HTML code
719      * @throws SAXEception if an error is encountered
720      */
721     public String handleInfo(final Map<String, String> attributes, final String contents) throws SAXException {
722         String id = attributes.get("id");
723         if (id != null) {
724             return "<a name=\"" + id + "\"></a>" + encloseContents("div", "info", contents);
725         } else {
726             return encloseContents("div", "info", contents);
727         }
728     }
729
730     /**
731      * Handle a refsection
732      * @param attributes the tag attributes
733      * @param contents the tag contents
734      * @return the HTML code
735      * @throws SAXEception if an error is encountered
736      */
737     public String handleRefsection(final Map<String, String> attributes, final String contents) throws SAXException {
738         String id = attributes.get("id");
739         if (id != null) {
740             return "<a name=\"" + id + "\"></a>" + encloseContents("div", "refsection", contents);
741         } else {
742             return encloseContents("div", "refsection", contents);
743         }
744     }
745
746     /**
747      * Handle a progamlisting
748      * @param attributes the tag attributes
749      * @param contents the tag contents
750      * @return the HTML code
751      * @throws SAXEception if an error is encountered
752      */
753     public String handleProgramlisting(final Map<String, String> attributes, final String contents) throws SAXException {
754         String id = attributes.get("id");
755         String role = attributes.get("role");
756         String str;
757         if (role == null) {
758             String code = encloseContents("pre", "scilabcode", scilabLexer.convert(HTMLScilabCodeHandler.getInstance(refname, currentFileName), contents));
759             if (prependToProgramListing != null) {
760                 code = prependToProgramListing + code;
761             }
762             if (appendToProgramListing != null) {
763                 code += appendToProgramListing;
764             }
765             str = encloseContents("div", "programlisting", code);
766         } else {
767             if (role.equals("xml")) {
768                 str = encloseContents("div", "programlisting", encloseContents("pre", "xmlcode", xmlLexer.convert(HTMLXMLCodeHandler.getInstance(), contents)));
769             } else if (role.equals("c") || role.equals("cpp") || role.equals("code_gateway")) {
770                 str = encloseContents("div", "programlisting", encloseContents("pre", "ccode", cLexer.convert(HTMLCCodeHandler.getInstance(), contents)));
771             } else if (role.equals("java")) {
772                 str = encloseContents("div", "programlisting", encloseContents("pre", "ccode", javaLexer.convert(HTMLCCodeHandler.getInstance(), contents)));
773             } else if (role.equals("exec")) {
774                 String code = encloseContents("pre", "scilabcode", scilabLexer.convert(HTMLScilabCodeHandler.getInstance(refname, currentFileName), contents));
775                 if (prependToProgramListing != null) {
776                     code = prependToProgramListing + code;
777                 }
778                 if (appendForExecToProgramListing != null) {
779                     code += appendForExecToProgramListing;
780                 }
781                 str = encloseContents("div", "programlisting", code);
782             } else if (role.equals("no-scilab-exec")) {
783                 String code = encloseContents("pre", "scilabcode", scilabLexer.convert(HTMLScilabCodeHandler.getInstance(refname, currentFileName), contents));
784                 str = encloseContents("div", "programlisting", code);
785             } else {
786                 String code = encloseContents("pre", "scilabcode", scilabLexer.convert(HTMLScilabCodeHandler.getInstance(refname, currentFileName), contents));
787                 if (prependToProgramListing != null) {
788                     code = prependToProgramListing + code;
789                 }
790                 if (appendToProgramListing != null) {
791                     code += appendToProgramListing;
792                 }
793                 str = encloseContents("div", "programlisting", code);
794             }
795         }
796         if (id != null) {
797             return "<a name=\"" + id + "\"></a>" + str;
798         } else {
799             return str;
800         }
801     }
802
803     /**
804      * Handle a screen
805      * @param attributes the tag attributes
806      * @param contents the tag contents
807      * @return the HTML code
808      * @throws SAXEception if an error is encountered
809      */
810     public String handleScreen(final Map<String, String> attributes, final String contents) throws SAXException {
811         String id = attributes.get("id");
812         String str = encloseContents("div", "screen", encloseContents("pre", contents));
813         if (id != null) {
814             return "<a name=\"" + id + "\"></a>" + str;
815         } else {
816             return str;
817         }
818     }
819
820     /**
821      * Handle a pubdate
822      * @param attributes the tag attributes
823      * @param contents the tag contents
824      * @return the HTML code
825      * @throws SAXEception if an error is encountered
826      */
827     public String handlePubdate(final Map<String, String> attributes, final String contents) throws SAXException {
828         return null;
829     }
830
831     /**
832      * Handle a simplelist
833      * @param attributes the tag attributes
834      * @param contents the tag contents
835      * @return the HTML code
836      * @throws SAXEception if an error is encountered
837      */
838     public String handleSimplelist(final Map<String, String> attributes, final String contents) throws SAXException {
839         String style = "itemizedlist";
840
841         return encloseContents("ul", style, contents);
842     }
843
844     /**
845      * Handle a member
846      * @param attributes the tag attributes
847      * @param contents the tag contents
848      * @return the HTML code
849      * @throws SAXEception if an error is encountered
850      */
851     public String handleMember(final Map<String, String> attributes, final String contents) throws SAXException {
852         return encloseContents("li", "member", contents);
853     }
854
855     /**
856      * Handle a link
857      * @param attributes the tag attributes
858      * @param contents the tag contents
859      * @return the HTML code
860      * @throws SAXEception if an error is encountered
861      */
862     public String handleLink(final Map<String, String> attributes, final String contents) throws SAXException {
863         String link = attributes.get("linkend");
864         if (link == null) {
865             throw new SAXException("No linkend attribute in tag link");
866         }
867
868         String type = attributes.get("type");
869         String id;
870         if (type != null && type.equals("scilab")) {
871             id = resolvScilabLink(link);
872         } else if (type != null && type.equals("remote")) {
873             id = makeRemoteLink(link);
874         } else {
875             id = mapId.get(link);
876         }
877
878         if (id == null) {
879             warnings++;
880             System.err.println("Warning (should be fixed): invalid internal link to " + link + " in " + currentFileName + "\nat line " + locator.getLineNumber());
881             return null;
882         }
883
884         Stack<DocbookElement> stack = getStack();
885         int s = stack.size();
886         if (s >= 3) {
887             DocbookElement elem = stack.get(s - 3);
888             if (elem.getName().equals("refsection")) {
889                 String role = elem.getAttributes().get("role");
890                 if (role != null && role.equals("see also")) {
891                     String purpose = mapIdPurpose.get(link);
892                     if (purpose != null) {
893                         return encloseContents("a", new String[] {"href", id, "class", "link"}, contents) + " &#8212; " + purpose;
894                     } else {
895                         return encloseContents("a", new String[] {"href", id, "class", "link"}, contents);
896                     }
897                 }
898             }
899         }
900
901         return encloseContents("a", new String[] {"href", id, "class", "link"}, contents);
902     }
903
904     /**
905      * Rewrite a link when its type is "scilab"
906      * @param link the link
907      * @return the modified link with protocol scilab:// for example
908      */
909     protected String resolvScilabLink(String link) {
910         int pos = link.indexOf("/");
911         if (pos == -1) {
912             return null;
913         }
914         String first = link.substring(0, pos);
915         String second = link.substring(pos + 1);
916         String[] toks = first.split("\\.");
917         if (toks == null || toks.length != 2) {
918             return null;
919         }
920
921         if (!linkToTheWeb) {
922             return urlBase + link;
923         } else {
924             if (toks[0].equals("scilab") && toks[1].equals("help")) {
925                 return urlBase + second + ".html";
926             } else {
927                 return "#";
928             }
929         }
930     }
931
932     /**
933      * Make a remote link
934      * @param link the link
935      * @return the good link
936      */
937     protected String makeRemoteLink(String link) {
938         return link;
939     }
940
941     /**
942      * Handle an ulink
943      * @param attributes the tag attributes
944      * @param contents the tag contents
945      * @return the HTML code
946      * @throws SAXEception if an error is encountered
947      */
948     public String handleUlink(final Map<String, String> attributes, final String contents) throws SAXException {
949         String link = attributes.get("url");
950         if (link == null) {
951             throw new SAXException("No url attribute in tag ulink");
952         }
953
954         return encloseContents("a", new String[] {"href", link, "class", "ulink"}, contents);
955     }
956
957     /**
958      * Handle a xref
959      * @param attributes the tag attributes
960      * @param contents the tag contents
961      * @return the HTML code
962      * @throws SAXEception if an error is encountered
963      */
964     public String handleXref(final Map<String, String> attributes, final String contents) throws SAXException {
965         String link = attributes.get("linkend");
966         if (link == null) {
967             throw new SAXException("No linkend attribute in tag link");
968         }
969
970         String id = mapId.get(link);
971         if (id == null) {
972             warnings++;
973             System.err.println("Warning (should be fixed): invalid internal link to " + link + " in " + currentFileName + "\nat line " + locator.getLineNumber());
974             return null;
975         }
976
977         return encloseContents("a", new String[] {"href", id, "class", "xref"}, contents);
978     }
979
980     /**
981      * Handle a latex (not really a docbook tag...)
982      * @param attributes the tag attributes
983      * @param contents the tag contents
984      * @return the HTML code
985      * @throws SAXEception if an error is encountered
986      */
987     public String handleLatex(final Map<String, String> attributes, final String contents) throws SAXException {
988         File f = new File(outName + imageDir, LATEXBASENAME + (latexCompt++) + ".png");
989         String parent = getParentTagName();
990         if (parent.equals("para") && !attributes.containsKey("style")) {
991             attributes.put("style", "text");
992         }
993         String fs = attributes.get("fontsize");
994         if (fs == null) {
995             attributes.put("fontsize", "16");
996         }
997         return ImageConverter.getImageByCode(currentFileName, contents, attributes, "image/latex", f, imageDir + "/" + f.getName());
998     }
999
1000     /**
1001      * Handle a term
1002      * @param attributes the tag attributes
1003      * @param contents the tag contents
1004      * @return the HTML code
1005      * @throws SAXEception if an error is encountered
1006      */
1007     public String handleTerm(final Map<String, String> attributes, final String contents) throws SAXException {
1008         String id = attributes.get("id");
1009         if (id != null) {
1010             return "<a name=\"" + id + "\"></a>" + encloseContents("span", "term", contents);
1011         } else {
1012             return encloseContents("span", "term", contents);
1013         }
1014     }
1015
1016     /**
1017      * Handle a listitem
1018      * @param attributes the tag attributes
1019      * @param contents the tag contents
1020      * @return the HTML code
1021      * @throws SAXEception if an error is encountered
1022      */
1023     public String handleListitem(final Map<String, String> attributes, final String contents) throws SAXException {
1024         String parent = getParentTagName();
1025         if (parent.equals("varlistentry")) {
1026             return encloseContents("dd", contents);
1027         }
1028         return encloseContents("li", contents);
1029     }
1030
1031     /**
1032      * Handle a varlistentry
1033      * @param attributes the tag attributes
1034      * @param contents the tag contents
1035      * @return the HTML code
1036      * @throws SAXEception if an error is encountered
1037      */
1038     public String handleVarlistentry(final Map<String, String> attributes, final String contents) throws SAXException {
1039         return encloseContents("dt", contents);
1040     }
1041
1042     /**
1043      * Handle a variablelist
1044      * @param attributes the tag attributes
1045      * @param contents the tag contents
1046      * @return the HTML code
1047      * @throws SAXEception if an error is encountered
1048      */
1049     public String handleVariablelist(final Map<String, String> attributes, final String contents) throws SAXException {
1050         return encloseContents("dl", contents);
1051     }
1052
1053     /**
1054      * Handle an itemizedlist
1055      * @param attributes the tag attributes
1056      * @param contents the tag contents
1057      * @return the HTML code
1058      * @throws SAXEception if an error is encountered
1059      */
1060     public String handleItemizedlist(final Map<String, String> attributes, final String contents) throws SAXException {
1061         String id = attributes.get("id");
1062         if (id != null) {
1063             return "<a name=\"" + id + "\"></a>" + encloseContents("ul", "itemizedlist", contents);
1064         } else {
1065             return encloseContents("ul", "itemizedlist", contents);
1066         }
1067     }
1068
1069     /**
1070      * Handle an emphasis
1071      * @param attributes the tag attributes
1072      * @param contents the tag contents
1073      * @return the HTML code
1074      * @throws SAXEception if an error is encountered
1075      */
1076     public String handleEmphasis(final Map<String, String> attributes, final String contents) throws SAXException {
1077         String role = attributes.get("role");
1078         if (role != null) {
1079             if (role.equals("bold")) {
1080                 return encloseContents("b", contents);
1081             }
1082             if (role.equals("italic")) {
1083                 return encloseContents("i", contents);
1084             }
1085         }
1086
1087         return encloseContents("em", contents);
1088     }
1089
1090     /**
1091      * Handle a tr
1092      * @param attributes the tag attributes
1093      * @param contents the tag contents
1094      * @return the HTML code
1095      * @throws SAXEception if an error is encountered
1096      */
1097     public String handleTr(final Map<String, String> attributes, final String contents) throws SAXException {
1098         return encloseContents("tr", contents);
1099     }
1100
1101     /**
1102      * Handle a td
1103      * @param attributes the tag attributes
1104      * @param contents the tag contents
1105      * @return the HTML code
1106      * @throws SAXEception if an error is encountered
1107      */
1108     public String handleTd(final Map<String, String> attributes, final String contents) throws SAXException {
1109         String align = attributes.get("align");
1110         if (align == null) {
1111             return encloseContents("td", new String[] {"align", align}, contents);
1112         }
1113         return encloseContents("td", contents);
1114     }
1115
1116     /**
1117      * Handle an informaltable
1118      * @param attributes the tag attributes
1119      * @param contents the tag contents
1120      * @return the HTML code
1121      * @throws SAXEception if an error is encountered
1122      */
1123     public String handleInformaltable(final Map<String, String> attributes, final String contents) throws SAXException {
1124         String id = attributes.get("id");
1125         String border = attributes.get("border");
1126         if (border == null) {
1127             border = "";
1128         }
1129         String cellpadding = attributes.get("cellpadding");
1130         if (cellpadding == null) {
1131             cellpadding = "";
1132         }
1133         String width = attributes.get("width");
1134         if (width == null) {
1135             width = "";
1136         }
1137         if (id != null) {
1138             return "<a name=\"" + id + "\"></a>" + encloseContents("table", new String[] {"class", "informaltable", "border", border, "cellpadding", cellpadding, "width", width}, contents);
1139         } else {
1140             return encloseContents("table", new String[] {"class", "informaltable", "border", border, "cellpadding", cellpadding, "width", width}, contents);
1141         }
1142     }
1143
1144     /**
1145      * Handle an imagedata
1146      * @param attributes the tag attributes
1147      * @param contents the tag contents
1148      * @return the HTML code
1149      * @throws SAXEception if an error is encountered
1150      */
1151     public String handleImagedata(final Map<String, String> attributes, final String contents) throws SAXException {
1152         String fileref = attributes.get("fileref");
1153         if (fileref == null) {
1154             if (contents == null || contents.length() == 0) {
1155                 throw new SAXException("No fileref attribute or no data in tag imagedata");
1156             }
1157
1158             return contents;
1159         }
1160
1161         try {
1162             String path = new File(new URI(currentFileName)).getParent();
1163             if (!ImageConverter.imageExists(path, fileref)) {
1164                 throw new SAXException("The given fileref is not on an existing image file:\n" + fileref);
1165             }
1166
1167             return ImageConverter.getImageByFile(attributes, path, fileref, outName, imageDir);
1168         }  catch (URISyntaxException e) {
1169             System.err.println(e);
1170         }
1171
1172         return null;
1173     }
1174
1175     /**
1176      * Handle an imageobject
1177      * @param attributes the tag attributes
1178      * @param contents the tag contents
1179      * @return the HTML code
1180      * @throws SAXEception if an error is encountered
1181      */
1182     public String handleImageobject(final Map<String, String> attributes, final String contents) throws SAXException {
1183         return contents;
1184     }
1185
1186     /**
1187      * Handle an inlinemediaobject
1188      * @param attributes the tag attributes
1189      * @param contents the tag contents
1190      * @return the HTML code
1191      * @throws SAXEception if an error is encountered
1192      */
1193     public String handleInlinemediaobject(final Map<String, String> attributes, final String contents) throws SAXException {
1194         return encloseContents("span", contents);
1195     }
1196
1197     /**
1198      * Handle a screenshot
1199      * @param attributes the tag attributes
1200      * @param contents the tag contents
1201      * @return the HTML code
1202      * @throws SAXEception if an error is encountered
1203      */
1204     public String handleScreenshot(final Map<String, String> attributes, final String contents) throws SAXException {
1205         String id = attributes.get("id");
1206         if (id != null) {
1207             return "<a name=\"" + id + "\"></a>" + encloseContents("div", "screenshot", contents);
1208         } else {
1209             return encloseContents("div", "screenshot", contents);
1210         }
1211     }
1212
1213     /**
1214      * Handle a mediaobject
1215      * @param attributes the tag attributes
1216      * @param contents the tag contents
1217      * @return the HTML code
1218      * @throws SAXEception if an error is encountered
1219      */
1220     public String handleMediaobject(final Map<String, String> attributes, final String contents) throws SAXException {
1221         String id = attributes.get("id");
1222         String c = contents.replaceFirst("top:([0-9]+)px;", "");
1223         if (id != null) {
1224             return "<a name=\"" + id + "\"></a>" + encloseContents("div", "mediaobject", c);
1225         } else {
1226             return encloseContents("div", "mediaobject", c);
1227         }
1228     }
1229
1230     /**
1231      * Handle an informalequation
1232      * @param attributes the tag attributes
1233      * @param contents the tag contents
1234      * @return the HTML code
1235      * @throws SAXEception if an error is encountered
1236      */
1237     public String handleInformalequation(final Map<String, String> attributes, final String contents) throws SAXException {
1238         String id = attributes.get("id");
1239         if (id != null) {
1240             return "<a name=\"" + id + "\"></a>" + encloseContents("div", "informalequation", contents);
1241         } else {
1242             return encloseContents("div", "informalequation", contents);
1243         }
1244     }
1245
1246     /**
1247      * Handle an orderedlist
1248      * @param attributes the tag attributes
1249      * @param contents the tag contents
1250      * @return the HTML code
1251      * @throws SAXEception if an error is encountered
1252      */
1253     public String handleOrderedlist(final Map<String, String> attributes, final String contents) throws SAXException {
1254         String numeration = "1";
1255         String numAttr = attributes.get("numeration");
1256         if (numAttr != null) {
1257             if (numAttr.equals("loweralpha")) {
1258                 numeration = "a";
1259             } else if (numAttr.equals("upperalpha")) {
1260                 numeration = "A";
1261             } else if (numAttr.equals("lowerroman")) {
1262                 numeration = "i";
1263             } else if (numAttr.equals("upperroman")) {
1264                 numeration = "I";
1265             }
1266         }
1267
1268         String id = attributes.get("id");
1269         if (id != null) {
1270             return "<a name=\"" + id + "\"></a>" + encloseContents("ol", new String[] {"type", numeration}, contents);
1271         } else {
1272             return encloseContents("ol", new String[] {"type", numeration}, contents);
1273         }
1274     }
1275
1276     /**
1277      * Handle a subscript
1278      * @param attributes the tag attributes
1279      * @param contents the tag contents
1280      * @return the HTML code
1281      * @throws SAXEception if an error is encountered
1282      */
1283     public String handleSubscript(final Map<String, String> attributes, final String contents) throws SAXException {
1284         return encloseContents("sub", contents);
1285     }
1286
1287     /**
1288      * Handle a superscript
1289      * @param attributes the tag attributes
1290      * @param contents the tag contents
1291      * @return the HTML code
1292      * @throws SAXEception if an error is encountered
1293      */
1294     public String handleSuperscript(final Map<String, String> attributes, final String contents) throws SAXException {
1295         return encloseContents("sup", contents);
1296     }
1297
1298     /**
1299      * Handle a replaceable
1300      * @param attributes the tag attributes
1301      * @param contents the tag contents
1302      * @return the HTML code
1303      * @throws SAXEception if an error is encountered
1304      */
1305     public String handleReplaceable(final Map<String, String> attributes, final String contents) throws SAXException {
1306         return encloseContents("span", "replaceable", contents);
1307     }
1308
1309     /**
1310      * Handle a question
1311      * @param attributes the tag attributes
1312      * @param contents the tag contents
1313      * @return the HTML code
1314      * @throws SAXEception if an error is encountered
1315      */
1316     public String handleQuestion(final Map<String, String> attributes, final String contents) throws SAXException {
1317         return encloseContents("dt", encloseContents("strong", contents));
1318     }
1319
1320     /**
1321      * Handle an answer
1322      * @param attributes the tag attributes
1323      * @param contents the tag contents
1324      * @return the HTML code
1325      * @throws SAXEception if an error is encountered
1326      */
1327     public String handleAnswer(final Map<String, String> attributes, final String contents) throws SAXException {
1328         return encloseContents("dd", contents);
1329     }
1330
1331     /**
1332      * Handle a qandaentry
1333      * @param attributes the tag attributes
1334      * @param contents the tag contents
1335      * @return the HTML code
1336      * @throws SAXEception if an error is encountered
1337      */
1338     public String handleQandaentry(final Map<String, String> attributes, final String contents) throws SAXException {
1339         return encloseContents("dl", contents);
1340     }
1341
1342     /**
1343      * Handle a qandaset
1344      * @param attributes the tag attributes
1345      * @param contents the tag contents
1346      * @return the HTML code
1347      * @throws SAXEception if an error is encountered
1348      */
1349     public String handleQandaset(final Map<String, String> attributes, final String contents) throws SAXException {
1350         return encloseContents("div", "qandaset", contents);
1351     }
1352
1353     /**
1354      * Handle a caption
1355      * @param attributes the tag attributes
1356      * @param contents the tag contents
1357      * @return the HTML code
1358      * @throws SAXEception if an error is encountered
1359      */
1360     public String handleCaption(final Map<String, String> attributes, final String contents) throws SAXException {
1361         return encloseContents("caption", encloseContents("b", contents));
1362     }
1363
1364     /**
1365      * Handle a tbody
1366      * @param attributes the tag attributes
1367      * @param contents the tag contents
1368      * @return the HTML code
1369      * @throws SAXEception if an error is encountered
1370      */
1371     public String handleTbody(final Map<String, String> attributes, final String contents) throws SAXException {
1372         return encloseContents("tbody", "tbody", contents);
1373     }
1374
1375     /**
1376      * Handle a table
1377      * @param attributes the tag attributes
1378      * @param contents the tag contents
1379      * @return the HTML code
1380      * @throws SAXEception if an error is encountered
1381      */
1382     public String handleTable(final Map<String, String> attributes, final String contents) throws SAXException {
1383         String id = attributes.get("id");
1384         if (id != null) {
1385             return "<a name=\"" + id + "\"></a>" + encloseContents("table", "doctable", contents);
1386         } else {
1387             return encloseContents("table", "doctable", contents);
1388         }
1389     }
1390
1391     /**
1392      * Handle a surname
1393      * @param attributes the tag attributes
1394      * @param contents the tag contents
1395      * @return the HTML code
1396      * @throws SAXEception if an error is encountered
1397      */
1398     public String handleSurname(final Map<String, String> attributes, final String contents) throws SAXException {
1399         return encloseContents("span", "surname", contents);
1400     }
1401
1402     /**
1403      * Handle a firstname
1404      * @param attributes the tag attributes
1405      * @param contents the tag contents
1406      * @return the HTML code
1407      * @throws SAXEception if an error is encountered
1408      */
1409     public String handleFirstname(final Map<String, String> attributes, final String contents) throws SAXException {
1410         return encloseContents("span", "firstname", contents);
1411     }
1412
1413     /**
1414      * Handle a bibliomset
1415      * @param attributes the tag attributes
1416      * @param contents the tag contents
1417      * @return the HTML code
1418      * @throws SAXEception if an error is encountered
1419      */
1420     public String handleBibliomset(final Map<String, String> attributes, final String contents) throws SAXException {
1421         String id = attributes.get("id");
1422         if (id != null) {
1423             return "<a name=\"" + id + "\"></a>" + encloseContents("div", "bibliomset", contents);
1424         } else {
1425             return encloseContents("div", "bibliomset", contents);
1426         }
1427     }
1428
1429     /**
1430      * Handle a bibliomixed
1431      * @param attributes the tag attributes
1432      * @param contents the tag contents
1433      * @return the HTML code
1434      * @throws SAXEception if an error is encountered
1435      */
1436     public String handleBibliomixed(final Map<String, String> attributes, final String contents) throws SAXException {
1437         String id = attributes.get("id");
1438         if (id != null) {
1439             return "<a name=\"" + id + "\"></a>" + encloseContents("div", "bibliomixed", contents);
1440         } else {
1441             return encloseContents("div", "bibliomixed", contents);
1442         }
1443     }
1444
1445     /**
1446      * Handle a th
1447      * @param attributes the tag attributes
1448      * @param contents the tag contents
1449      * @return the HTML code
1450      * @throws SAXEception if an error is encountered
1451      */
1452     public String handleTh(final Map<String, String> attributes, final String contents) throws SAXException {
1453         return encloseContents("th", contents);
1454     }
1455
1456     /**
1457      * Handle a revhistory
1458      * @param attributes the tag attributes
1459      * @param contents the tag contents
1460      * @return the HTML code
1461      * @throws SAXEception if an error is encountered
1462      */
1463     public String handleRevhistory(final Map<String, String> attributes, final String contents) throws SAXException {
1464         String id = attributes.get("id");
1465         String str = "<table class=\"revhistory\"><tr class=\"title\"><td>" + VERSION + "</td><td>" + DESCRIPTION + "</td></tr>" + contents + "</table>";
1466         if (id != null) {
1467             return "<a name=\"" + id + "\"></a>" + str;
1468         } else {
1469             return str;
1470         }
1471     }
1472
1473     /**
1474      * Handle a revision
1475      * @param attributes the tag attributes
1476      * @param contents the tag contents
1477      * @return the HTML code
1478      * @throws SAXEception if an error is encountered
1479      */
1480     public String handleRevision(final Map<String, String> attributes, final String contents) throws SAXException {
1481         return encloseContents("tr", contents);
1482     }
1483
1484     /**
1485      * Handle a revnumber
1486      * @param attributes the tag attributes
1487      * @param contents the tag contents
1488      * @return the HTML code
1489      * @throws SAXEception if an error is encountered
1490      */
1491     public String handleRevnumber(final Map<String, String> attributes, final String contents) throws SAXException {
1492         return encloseContents("td", "revnumber", contents);
1493     }
1494
1495     /**
1496      * Handle a revremark
1497      * @param attributes the tag attributes
1498      * @param contents the tag contents
1499      * @return the HTML code
1500      * @throws SAXEception if an error is encountered
1501      */
1502     public String handleRevremark(final Map<String, String> attributes, final String contents) throws SAXException {
1503         return encloseContents("td", "revremark", contents);
1504     }
1505
1506     /**
1507      * Handle a revdescription
1508      * @param attributes the tag attributes
1509      * @param contents the tag contents
1510      * @return the HTML code
1511      * @throws SAXEception if an error is encountered
1512      */
1513     public String handleRevdescription(final Map<String, String> attributes, final String contents) throws SAXException {
1514         return encloseContents("td", "revdescription", contents);
1515     }
1516
1517     /**
1518      * Handle a note
1519      * @param attributes the tag attributes
1520      * @param contents the tag contents
1521      * @return the HTML code
1522      * @throws SAXEception if an error is encountered
1523      */
1524     public String handleNote(final Map<String, String> attributes, final String contents) throws SAXException {
1525         String id = attributes.get("id");
1526         String code = "<table><tr><td valign=\"top\"><img src=\"ScilabNote.png\"/></td><td valign=\"top\">" + encloseContents("div", "note", contents) + "</tr></table>";
1527         if (id != null) {
1528             return "<a name=\"" + id + "\"></a>" + code;
1529         } else {
1530             return code;
1531         }
1532     }
1533
1534     /**
1535      * Handle a warning
1536      * @param attributes the tag attributes
1537      * @param contents the tag contents
1538      * @return the HTML code
1539      * @throws SAXEception if an error is encountered
1540      */
1541     public String handleWarning(final Map<String, String> attributes, final String contents) throws SAXException {
1542         String id = attributes.get("id");
1543         String code = "<table><tr><td valign=\"top\"><img src=\"ScilabWarning.png\"/></td><td valign=\"top\">" + encloseContents("div", "warning", contents) + "</tr></table>";
1544         if (id != null) {
1545             return "<a name=\"" + id + "\"></a>" + code;
1546         } else {
1547             return code;
1548         }
1549     }
1550
1551     /**
1552      * Handle a caution
1553      * @param attributes the tag attributes
1554      * @param contents the tag contents
1555      * @return the HTML code
1556      * @throws SAXEception if an error is encountered
1557      */
1558     public String handleCaution(final Map<String, String> attributes, final String contents) throws SAXException {
1559         String id = attributes.get("id");
1560         String code = "<table><tr><td valign=\"top\"><img src=\"ScilabCaution.png\"/></td><td valign=\"top\">" + encloseContents("div", "caution", contents) + "</tr></table>";
1561         if (id != null) {
1562             return "<a name=\"" + id + "\"></a>" + code;
1563         } else {
1564             return code;
1565         }
1566     }
1567
1568     /**
1569      * Handle a tip
1570      * @param attributes the tag attributes
1571      * @param contents the tag contents
1572      * @return the HTML code
1573      * @throws SAXEception if an error is encountered
1574      */
1575     public String handleTip(final Map<String, String> attributes, final String contents) throws SAXException {
1576         String id = attributes.get("id");
1577         String code = "<table><tr><td valign=\"top\"><img src=\"ScilabTip.png\"/></td><td valign=\"top\">" + encloseContents("div", "tip", contents) + "</tr></table>";
1578         if (id != null) {
1579             return "<a name=\"" + id + "\"></a>" + code;
1580         } else {
1581             return code;
1582         }
1583     }
1584
1585     /**
1586      * Handle a important
1587      * @param attributes the tag attributes
1588      * @param contents the tag contents
1589      * @return the HTML code
1590      * @throws SAXEception if an error is encountered
1591      */
1592     public String handleImportant(final Map<String, String> attributes, final String contents) throws SAXException {
1593         String id = attributes.get("id");
1594         String code = "<table><tr><td valign=\"top\"><img src=\"ScilabImportant.png\"/></td><td valign=\"top\">" + encloseContents("div", "important", contents) + "</tr></table>";
1595         if (id != null) {
1596             return "<a name=\"" + id + "\"></a>" + code;
1597         } else {
1598             return code;
1599         }
1600     }
1601 }