57a9641943a720a06c203e39bb1331e2a423bd84
[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  * Copyright (C) 2016 - 2018 - Samuel GOUGEON
5  *
6  * Copyright (C) 2012 - 2016 - Scilab Enterprises
7  *
8  * This file is hereby licensed under the terms of the GNU GPL v2.0,
9  * pursuant to article 5.3.4 of the CeCILL v.2.1.
10  * This file was originally licensed under the terms of the CeCILL v2.1,
11  * and continues to be available under such terms.
12  * For more information, see the COPYING file which you should have received
13  * along with this program.
14  *
15  */
16
17 package org.scilab.modules.helptools;
18
19 import java.io.File;
20 import java.io.IOException;
21 import java.net.URI;
22 import java.net.URISyntaxException;
23 import java.util.Date;
24 import java.util.Map;
25 import java.util.Stack;
26 import java.util.regex.Pattern;
27
28 import org.scilab.modules.commons.ScilabCommonsUtils;
29 import org.scilab.modules.helptools.XML.HTMLXMLCodeHandler;
30 import org.scilab.modules.helptools.XML.XMLLexer;
31 import org.scilab.modules.helptools.c.CLexer;
32 import org.scilab.modules.helptools.c.HTMLCCodeHandler;
33 import org.scilab.modules.helptools.external.HTMLMathMLHandler;
34 import org.scilab.modules.helptools.external.HTMLSVGHandler;
35 import org.scilab.modules.helptools.external.HTMLScilabHandler;
36 import org.scilab.modules.helptools.image.Image;
37 import org.scilab.modules.helptools.image.ImageConverter;
38 import org.scilab.modules.helptools.java.JavaLexer;
39 import org.scilab.modules.helptools.scilab.AbstractScilabCodeHandler;
40 import org.scilab.modules.helptools.scilab.HTMLScilabCodeHandler;
41 import org.scilab.modules.helptools.scilab.ScilabLexer;
42 import org.scilab.modules.localization.Messages;
43 import org.xml.sax.InputSource;
44 import org.xml.sax.SAXException;
45
46 /**
47  * Class to convert DocBook to HTML
48  * @author Calixte DENIZET
49  */
50 public class HTMLDocbookTagConverter extends DocbookTagConverter implements TemplateFiller {
51
52     public static enum GenerationType { WEB, JAVAHELP, CHM, HTML };
53
54     private static final String SCILAB_URI = "http://www.scilab.org";
55     private static final String LATEXBASENAME = "_LaTeX_";
56     private static final String VERSION = Messages.gettext("Version");
57     private static final String DESCRIPTION = Messages.gettext("Description");
58
59     private final StringBuilder buffer = new StringBuilder(8192);
60     private int latexCompt = 1;
61     private boolean hasExamples;
62     private int warnings;
63     private int nbFiles;
64
65     private final String imageDir;
66     protected String urlBase;
67     protected boolean linkToTheWeb;
68     protected final String outName;
69     protected String outImages;
70
71     protected final Map<String, String> mapId;
72     protected final Map<String, String> tocitem;
73     protected final HTMLDocbookLinkResolver.TreeId tree;
74     protected final Map<String, HTMLDocbookLinkResolver.TreeId> mapTreeId;
75     protected final Map<String, String> mapIdPurpose;
76     protected final Map<String, String> mapIdRefname;
77
78     protected final TemplateHandler templateHandler;
79
80     protected final ScilabLexer scilabLexer;
81     protected final XMLLexer xmlLexer;
82     protected final CLexer cLexer;
83     protected final JavaLexer javaLexer;
84
85     protected String bookTitle = "";
86     protected String partTitle = "";
87     protected String chapterTitle = "";
88     protected String sectionTitle = "";
89     protected String fileSubtitle = "";
90
91     protected String refpurpose = "";
92     protected String refname = "";
93     protected String version;
94     protected String appendToProgramListing;
95     protected String appendForExecToProgramListing;
96     protected String prependToProgramListing;
97     protected String currentId;
98     protected String indexFilename = "index" /*UUID.randomUUID().toString()*/ + ".html";
99     protected final String language;
100
101     protected final boolean isToolbox;
102     protected final Backend type;
103
104     /**
105      * Constructor
106      * @param inName the name of the input stream
107      * @param sciDocMain provide useful doc generation properties
108      * @param imgConvert the shared image converter for all generation
109      */
110     public HTMLDocbookTagConverter(String inName, SciDocMain sciDocMain, ImageConverter imgConvert) throws IOException, SAXException {
111         super(inName, imgConvert);
112
113         this.version = sciDocMain.getConf().getVersion();
114         this.imageDir = sciDocMain.getImagedir();
115         this.outName = sciDocMain.getOutputDirectory() + File.separator;
116         this.outImages = this.outName;
117
118         imgConvert.setDocbookTagConverter(this);
119         HTMLDocbookLinkResolver resolver = new HTMLDocbookLinkResolver(inName);
120
121         mapId = resolver.getMapId();
122         tocitem = resolver.getToc();
123         tree = resolver.getTree();
124         mapTreeId = resolver.getMapTreeId();
125         mapIdPurpose = resolver.getMapIdPurpose();
126         mapIdRefname = resolver.getMapIdRefname();
127
128         this.isToolbox = sciDocMain.isToolbox();
129         this.language = sciDocMain.getLanguage();
130         this.type = sciDocMain.getFormat();
131
132         if (isToolbox) {
133             urlBase = sciDocMain.getConf().getWebSiteURL() + language + "/";
134             linkToTheWeb = true;
135         } else {
136             urlBase = null;
137             linkToTheWeb = false;
138         }
139
140         if (isToolbox) {// we generate a toolbox's help
141             HTMLScilabCodeHandler.setLinkWriter(new AbstractScilabCodeHandler.LinkWriter() {
142                 public String getLink(String id) {
143                     if (id.length() > 0 && id.charAt(0) == '%') {
144                         id = id.replace("%", "percent");
145                     }
146                     String link = mapId.get(id);
147                     if (link == null) {
148                         return HTMLDocbookTagConverter.this.urlBase + id;
149                     } else {
150                         return link;
151                     }
152                 }
153             });
154         } else {// we generate Scilab's help
155             HTMLScilabCodeHandler.setLinkWriter(new AbstractScilabCodeHandler.LinkWriter() {
156                 public String getLink(String id) {
157                     if (id.length() > 0 && id.charAt(0) == '%') {
158                         id = id.replace("%", "percent");
159                     }
160                     return mapId.get(id);
161                 }
162             });
163         }
164
165         scilabLexer = new ScilabLexer(sciDocMain.getConf().getBuiltins(), sciDocMain.getConf().getMacros());
166         xmlLexer = new XMLLexer();
167         cLexer = new CLexer();
168         javaLexer = new JavaLexer();
169
170         final String template = sciDocMain.getConf().getTemplate(sciDocMain.getFormat().toString().toLowerCase());
171         File tpl = new File(template);
172         if (!tpl.isFile()) {
173             final String msg = "Could not find template document: " + template;
174             System.err.println(msg);
175             throw new RuntimeException();
176         }
177         templateHandler = new TemplateHandler(this, tpl, language);
178     }
179
180     public static boolean containsCJK(CharSequence seq) {
181         if (seq == null) {
182             return false;
183         }
184
185         for (int i = 0; i < seq.length(); i++) {
186             Character.UnicodeBlock block = Character.UnicodeBlock.of(seq.charAt(i));
187             if (block == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
188                     || block == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
189                     || block == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B
190                     || block == Character.UnicodeBlock.CJK_COMPATIBILITY_FORMS
191                     || block == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
192                     || block == Character.UnicodeBlock.CJK_RADICALS_SUPPLEMENT
193                     || block == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
194                     || block == Character.UnicodeBlock.ENCLOSED_CJK_LETTERS_AND_MONTHS) {
195                 return true;
196             }
197         }
198
199         return false;
200     }
201
202     public static boolean containsCyrillic(CharSequence seq) {
203         if (seq == null) {
204             return false;
205         }
206
207         for (int i = 0; i < seq.length(); i++) {
208             Character.UnicodeBlock block = Character.UnicodeBlock.of(seq.charAt(i));
209             if (block == Character.UnicodeBlock.CYRILLIC || block == Character.UnicodeBlock.CYRILLIC_SUPPLEMENTARY) {
210                 return true;
211             }
212         }
213
214         return false;
215     }
216
217     /**
218      * Replace special chars
219      */
220     public static final String replaceEntity(final String str) {
221         return str.replaceAll("&", "&amp;").replaceAll("<", "&#0060;").replaceAll(">", "&#0062;").replaceAll("\"", "&#0034;").replaceAll("\'", "&#0039;");
222     }
223
224     /**
225      * Get the type of the generation
226      * @return the generation type
227      */
228     public final Backend getGenerationType() {
229         return type;
230     }
231
232     public String getLanguage() {
233         return language;
234     }
235
236     @Override
237     public void registerAllExternalXMLHandlers() {
238         super.registerAllExternalXMLHandlers();
239
240         registerExternalXMLHandler(new HTMLMathMLHandler(outImages, imageDir));
241         registerExternalXMLHandler(new HTMLSVGHandler(outImages, imageDir));
242         registerExternalXMLHandler(new HTMLScilabHandler(outImages, imageDir));
243     }
244
245     @Override
246     public void install() {
247         super.install();
248
249         ScilabCommonsUtils.copyFile(new File(SCI + "/modules/helptools/data/css/scilab_code.css"), new File(outName + "/scilab_code.css"));
250         ScilabCommonsUtils.copyFile(new File(SCI + "/modules/helptools/data/css/xml_code.css"), new File(outName + "/xml_code.css"));
251         ScilabCommonsUtils.copyFile(new File(SCI + "/modules/helptools/data/css/c_code.css"), new File(outName + "/c_code.css"));
252         ScilabCommonsUtils.copyFile(new File(SCI + "/modules/helptools/data/css/style.css"), new File(outName + "/style.css"));
253     }
254
255     /**
256      * @return the buffer used
257      */
258     public StringBuilder getBuffer() {
259         return buffer;
260     }
261
262     /**
263      * @param tag the tag name
264      * @param contents the contents to enclose between opening and closing tags
265      */
266     public String encloseContents(final String tag, final String contents) {
267         buffer.setLength(0);
268         buffer.append("<");
269         buffer.append(tag);
270         buffer.append(">");
271         if (contents != null) {
272             buffer.append(contents);
273         }
274         buffer.append("</");
275         buffer.append(tag);
276         buffer.append(">");
277
278         return buffer.toString();
279     }
280
281     /**
282      * @param tag the tag name
283      * @param attrs the attributes {attr1, value1, attr2, value2, ...}
284      * @param contents the contents to enclose between opening and closing tags
285      */
286     public String encloseContents(final String tag, final String[] attrs, final String contents) {
287         buffer.setLength(0);
288         buffer.append("<");
289         buffer.append(tag);
290         if (attrs != null) {
291             for (int i = 0; i < attrs.length; i += 2) {
292                 if (attrs[i + 1] != null && !attrs[i + 1].isEmpty()) {
293                     buffer.append(" ");
294                     buffer.append(attrs[i]);
295                     buffer.append("=\"");
296                     buffer.append(attrs[i + 1]);
297                     buffer.append("\"");
298                 }
299             }
300         }
301
302         buffer.append(">");
303         if (contents != null) {
304             buffer.append(contents);
305         }
306         buffer.append("</");
307         buffer.append(tag);
308         buffer.append(">");
309
310         return buffer.toString();
311     }
312
313     /**
314      * @param tag the tag name
315      * @param clazz the css class name
316      * @param contents the contents to enclose between opening and closing tags
317      */
318     public String encloseContents(final String tag, final String clazz, final String contents) {
319         buffer.setLength(0);
320         buffer.append("<");
321         buffer.append(tag);
322         buffer.append(" class=\"");
323         buffer.append(clazz);
324         buffer.append("\">");
325         if (contents != null) {
326             buffer.append(contents);
327         }
328         buffer.append("</");
329         buffer.append(tag);
330         buffer.append(">");
331
332         return buffer.toString();
333     }
334
335     /**
336      * {@inheritDoc}
337      */
338     public boolean isEscapable(final String tagName, final String uri) {
339         return !"latex".equals(tagName) && !"screen".equals(tagName) && !"programlisting".equals(tagName) && !"code".equals(tagName) && !"synopsis".equals(tagName) && !(uri.equals(SCILAB_URI) && tagName.equals("image"));
340     }
341
342     /**
343      * {@inheritDoc}
344      */
345     public boolean isTrimable(final String tagName) {
346         return !"screen".equals(tagName) && !"programlisting".equals(tagName) && !"code".equals(tagName) && !"synopsis".equals(tagName);
347     }
348
349     /**
350      * @param fileName the file to create
351      * @param subtitle the subtitle of the file
352      * @param contents the contents of the file
353      */
354     public void createHTMLFile(final String id, final String fileName, final String subtitle, final String contents) {
355         if (!hasError) {
356             fileSubtitle = subtitle;
357             nbFiles++;
358             templateHandler.generateFileFromTemplate(outName + fileName, id, contents);
359         }
360     }
361
362
363
364     /**
365      * @param code the code to translate
366      * @param img image information
367      * @param fileName the filename
368      * @param attrs the attribute of the image
369      * @return the HTML code to insert the image
370      */
371     public String generateCode(Image img, String fileName, Map<String, String> attrs, final String tooltipString) {
372         String style = attrs.get("style");
373         String top = "";
374         boolean display = style != null && style.equals("display");
375
376         if (!display) {
377             top = "top:" + img.descent + "px;";
378         }
379
380         String alignAttr = attrs.get("align");
381         String align = "";
382         String div = "div";
383         if (alignAttr != null) {
384             align = " style=\'text-align:" + alignAttr + "\'";
385         } else if (display) {
386             align = " style=\'text-align:center\'";
387         } else {
388             div = "span";
389         }
390
391         return "<" + div + align + "><img src=\'" + fileName + "\' style=\'position:relative;" + top  + "width:" + img.width + "px;height:" + img.height + "px\'/></" + div + ">";
392     }
393
394     /**
395      * {@inheritDoc}
396      */
397     public String makeTitle(final String id) {
398         if (refname.length() > 0) {
399             return tocitem.get(id);
400         }
401
402         return "";
403     }
404
405     /**
406      * {@inheritDoc}
407      */
408     public String makeSubtitle(final String id) {
409         return fileSubtitle;
410     }
411
412     /**
413      * {@inheritDoc}
414      */
415     public String makePrevious(final String id) {
416         buffer.setLength(0);
417         buffer.append("<span class=\"previous\">");
418         HTMLDocbookLinkResolver.TreeId leaf = mapTreeId.get(id);
419         if (leaf == null) {
420             return "";
421         }
422         HTMLDocbookLinkResolver.TreeId prev = leaf.getPrevious();
423         if (prev.parent != null) {
424             buffer.append("<a href=\"");
425             buffer.append(mapId.get(prev.id));
426             buffer.append("\">&lt;&lt; ");
427             buffer.append(tocitem.get(prev.id));
428             buffer.append("</a></span>\n");
429
430             return buffer.toString();
431         }
432
433         return "";
434     }
435
436     /**
437      * {@inheritDoc}
438      */
439     public String makePath(final String id) {
440         buffer.setLength(0);
441         buffer.append("<span class=\"path\" dir=\"ltr\">");
442         HTMLDocbookLinkResolver.TreeId leaf = mapTreeId.get(id);
443         if (leaf == null) {
444             return "";
445         }
446         String str = tocitem.get(id);
447         leaf = leaf.parent;
448         while (leaf != null && !leaf.isRoot()) {
449             str = "<a href=\"" + mapId.get(leaf.id) + "\">" + tocitem.get(leaf.id) + "</a> &gt; " + str;
450             leaf = leaf.parent;
451         }
452
453         str = "<a href=\"" + indexFilename  + "\">" + bookTitle + "</a> &gt;&gt; " + str;
454         buffer.append(str);
455         buffer.append("</span>\n");
456
457         return buffer.toString();
458     }
459
460     /**
461      * {@inheritDoc}
462      */
463     public String makeTop(final String id) {
464         buffer.setLength(0);
465         buffer.append("<span class=\"top\">");
466         HTMLDocbookLinkResolver.TreeId leaf = mapTreeId.get(id);
467         if (leaf == null) {
468             return "";
469         }
470
471         leaf = leaf.parent;
472         if (leaf != null) {
473             buffer.append("<a href=\"");
474             if (!leaf.isRoot()) {
475                 buffer.append(mapId.get(leaf.id));
476                 buffer.append("\">");
477                 buffer.append(tocitem.get(leaf.id));
478             } else {
479                 buffer.append(indexFilename);
480                 buffer.append("\">");
481                 buffer.append(bookTitle);
482             }
483             buffer.append("</a></span>\n");
484         } else {
485             return "";
486         }
487
488         return buffer.toString();
489     }
490
491     /**
492      * {@inheritDoc}
493      */
494     public String makeNext(final String id) {
495         buffer.setLength(0);
496         buffer.append("<span class=\"next\">");
497         HTMLDocbookLinkResolver.TreeId leaf = mapTreeId.get(id);
498         if (leaf == null) {
499             return "";
500         }
501         HTMLDocbookLinkResolver.TreeId next = leaf.getNext();
502         if (next != null) {
503             buffer.append("<a href=\"");
504             buffer.append(mapId.get(next.id));
505             buffer.append("\">");
506             buffer.append(tocitem.get(next.id));
507             buffer.append(" &gt;&gt;</a></span>\n");
508
509             return buffer.toString();
510         }
511
512         return "";
513     }
514
515     /**
516      * {@inheritDoc}
517      */
518     public String makeStart(final String id) {
519         buffer.setLength(0);
520         buffer.append("<span class=\"start\">");
521         buffer.append("<a href=\"");
522         buffer.append(indexFilename);
523         buffer.append("\">");
524         buffer.append(bookTitle);
525         buffer.append("</a></span>\n");
526
527         return buffer.toString();
528     }
529
530     /**
531      * {@inheritDoc}
532      */
533     public String makeTocList(final String id) {
534         buffer.setLength(0);
535         HTMLDocbookLinkResolver.TreeId leaf = mapTreeId.get(id);
536         if (leaf == null) {
537             return "";
538         }
539
540         HTMLDocbookLinkResolver.TreeId parent = leaf.parent;
541         buffer.append("<ul class=\"toc\">\n");
542         String str = "";
543         while (parent != null && !parent.isRoot()) {
544             str = "<li class=\"parent\"><a href=\"" + mapId.get(parent.id) + "\">" + tocitem.get(parent.id) + "</a></li>\n" + str;
545             parent = parent.parent;
546         }
547         buffer.append("<li class=\"root\"><a href=\"");
548         buffer.append(indexFilename);
549         buffer.append("\">");
550         buffer.append(bookTitle);
551         buffer.append("</a></li>\n");
552         buffer.append(str);
553
554         parent = leaf.parent;
555
556         for (HTMLDocbookLinkResolver.TreeId c : parent.children) {
557             if (c == leaf) {
558                 buffer.append("<li class=\"list-active\"><a href=\"");
559             } else {
560                 buffer.append("<li><a href=\"");
561             }
562             buffer.append(mapId.get(c.id));
563             buffer.append("\">");
564             buffer.append(tocitem.get(c.id));
565             buffer.append("</a></li>\n");
566         }
567         buffer.append("</ul>\n");
568
569         return buffer.toString();
570     }
571
572     /**
573      * {@inheritDoc}
574      */
575     public String makeLastModified(final String id) {
576         buffer.setLength(0);
577         try {
578             buffer.append("<span class=\"lastmodified\">");
579             buffer.append(new Date(new File(new URI(currentFileName)).lastModified()).toString());
580             buffer.append("</span>\n");
581         } catch (URISyntaxException e) {
582             e.printStackTrace();
583         }
584         return buffer.toString();
585     }
586
587     /**
588      * {@inheritDoc}
589      */
590     public String makeGenerationDate(final String id) {
591         buffer.setLength(0);
592         buffer.append("<span class=\"generationdate\">");
593         buffer.append(new Date(System.currentTimeMillis()).toString());
594         buffer.append("</span>\n");
595
596         return buffer.toString();
597     }
598
599     /**
600      * {@inheritDoc}
601      */
602     public String makeVersion(final String id) {
603         buffer.setLength(0);
604         buffer.append("<span class=\"version\">");
605         buffer.append(version);
606         buffer.append("</span>\n");
607
608         return buffer.toString();
609     }
610
611     private boolean isLinkedImage() {
612         Stack<DocbookElement> stack = getStack();
613         return stack.size() >= 3 && stack.get(stack.size() - 3).getName().equals("link");
614     }
615
616     @Override
617     public String generateImageCode(String code, String fileName, Map<String, String> attrs) {
618         String alignAttr = attrs.get("align");
619         boolean addDiv = getGenerationType() != Backend.JAVAHELP || !isLinkedImage();
620         final StringBuilder buffer = new StringBuilder(128);
621         if (addDiv && alignAttr != null) {
622             buffer.append("<div style=\'text-align:").append(alignAttr).append("\'>");
623         }
624         buffer.append("<img src=\'").append(fileName).append("\'/>");
625         if (addDiv && alignAttr != null) {
626             buffer.append("</div>");
627         }
628
629         if (getGenerationType() == Backend.WEB) {
630             /* Prepare the code for the html inclusion */
631             code = convertCode(code);
632             /* Provide a tooltip */
633             return "<div rel='tooltip' title='" + code + "'>" + buffer.toString() + "</div>";
634         } else {
635             /* No tooltip in the javahelp browser ...
636              * too limited html capabilities */
637             return buffer.toString();
638         }
639     }
640
641     @Override
642     public String generateImageCode(Image img, String fileName, Map<String, String> attrs) {
643         String style = attrs.get("style");
644         String top = "";
645         boolean display = style != null && style.equals("display");
646
647         if (!display) {
648             top = "top:" + img.descent + "px;";
649         }
650
651         String alignAttr = attrs.get("align");
652         String align = "";
653         String div = "div";
654         if (alignAttr != null) {
655             align = " style=\'text-align:" + alignAttr + "\'";
656         } else if (display) {
657             align = " style=\'text-align:center\'";
658         } else {
659             div = "span";
660         }
661
662         if (getGenerationType() == Backend.JAVAHELP && isLinkedImage()) {
663             // Java HTML renderer is not good... so when  the image is linked, we remove the div
664             return "<img src=\'" + fileName + "\' style=\'position:relative;" + top  + "width:" + img.width + "px;height:" + img.height + "px\'/>>";
665         } else {
666             return "<" + div + align + "><img src=\'" + fileName + "\' style=\'position:relative;" + top  + "width:" + img.width + "px;height:" + img.height + "px\'/></" + div + ">";
667         }
668     }
669
670     @Override
671     public String generateImageCode(String fileName, Map<String, String> attrs) {
672         String idAttr    = attrs.get("id");
673         String alignAttr = attrs.get("align");   // mixes align and valign imagedata attributes
674         String widthAttr = attrs.get("width");
675         String heightAttr= attrs.get("height"); // officially named "depth" as imagedata attribute
676         String styleAttr = attrs.get("style");
677         boolean addDiv = getGenerationType() != Backend.JAVAHELP || !isLinkedImage();
678         final StringBuilder buffer = new StringBuilder(128);
679         if (addDiv && alignAttr != null) {
680             buffer.append("<div style=\'text-align:").append(alignAttr).append("\'>\n");
681         }
682         buffer.append("<img src=\'").append(fileName).append("\' ");
683         if (!addDiv && alignAttr != null) {
684             buffer.append("align=\'").append(alignAttr).append("\' ");
685         }
686         if (idAttr != null){
687             buffer.append("id=\'").append(idAttr).append("\' ");
688         }
689         if (widthAttr != null){   // To avoid misshaping: setting width priority > setting height
690             buffer.append("width=\'").append(widthAttr).append("\' ");
691         }
692         else {
693             if (heightAttr != null) {
694                 buffer.append("height=\'").append(heightAttr).append("\' ");
695             }
696         }
697         if (styleAttr != null) {
698             buffer.append("style=\'").append(styleAttr).append("\'");
699         }
700         buffer.append("/>\n");
701         if (addDiv && alignAttr != null) {
702             buffer.append("</div>\n");
703         }
704
705         return buffer.toString();
706     }
707
708     public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
709         latexCompt = 1;
710         return super.resolveEntity(publicId, systemId);
711     }
712
713     /**
714      * Handle a refentry
715      * @param attributes the tag attributes
716      * @param contents the tag contents
717      * @return the HTML code
718      * @throws SAXEception if an error is encountered
719      */
720     public String handleRefentry(final Map<String, String> attributes, final String contents) throws SAXException {
721         String id = attributes.get("id");
722         if (id != null) {
723             currentId = id;
724         }
725         String fileName = mapId.get(currentId);
726         String needsExampleAttr = attributes.get("needs-examples");
727         createHTMLFile(currentId, fileName, refpurpose, contents);
728         if (!hasExamples && (needsExampleAttr == null || !needsExampleAttr.equals("no"))) {
729             warnings++;
730             //System.err.println("Warning (should be fixed): no example in " + currentFileName);
731         } else {
732             hasExamples = false;
733         }
734         String rp = encloseContents("span", "refentry-description", refpurpose);
735         String str = encloseContents("li", encloseContents("a", new String[] {"href", fileName, "class", "refentry"}, refname) + " &#8212; " + rp);
736         refpurpose = "";
737         refname = "";
738         currentId = null;
739
740         return str;
741     }
742
743     /**
744      * Handle a section
745      * @param attributes the tag attributes
746      * @param contents the tag contents
747      * @return the HTML code
748      * @throws SAXEception if an error is encountered
749      */
750     public String handleSection(final Map<String, String> attributes, final String contents) throws SAXException {
751         String fileName = attributes.get("id") + ".html";
752         String str = encloseContents("ul", "list-refentry", contents);
753         String title = encloseContents("h3", "title-section", sectionTitle);
754         createHTMLFile(attributes.get("id"), fileName, sectionTitle, title + "\n" + str);
755
756         str = encloseContents("li", encloseContents("a", new String[] {"href", fileName, "class", "section"}, sectionTitle) + "\n" + str);
757         sectionTitle = "";
758
759         return str;
760     }
761
762     /**
763      * Handle a book
764      * @param attributes the tag attributes
765      * @param contents the tag contents
766      * @return the HTML code
767      * @throws SAXEception if an error is encountered
768      */
769     public String handleBook(final Map<String, String> attributes, final String contents) throws SAXException {
770         String str = encloseContents("ul", "list-part", contents);
771         String btitle;
772         if (bookTitle.trim().equalsIgnoreCase("Scilab")) {
773             btitle = version;
774         } else {
775             btitle = bookTitle;
776         }
777         String title = encloseContents("h3", "book-title", btitle);
778         createHTMLFile("index", indexFilename, btitle, title + "\n" + str);
779
780         if (warnings != 0) {
781             System.err.println("Total files without example: " + warnings);
782             System.err.println("Total generated html files: " + nbFiles);
783         }
784
785         return encloseContents("li", encloseContents("a", new String[] {"href", indexFilename, "class", "part"}, bookTitle) + "\n" + str);
786     }
787
788     /**
789      * Handle a part
790      * @param attributes the tag attributes
791      * @param contents the tag contents
792      * @return the HTML code
793      * @throws SAXEception if an error is encountered
794      */
795     public String handlePart(final Map<String, String> attributes, final String contents) throws SAXException {
796         String fileName = attributes.get("id") + ".html";
797         String str = encloseContents("ul", "list-chapter", contents);
798         String title = encloseContents("h3", "title-part", partTitle);
799         createHTMLFile(attributes.get("id"), fileName, partTitle, title + "\n" + str);
800         str = encloseContents("li", encloseContents("a", new String[] {"href", fileName, "class", "part"}, partTitle) + "\n" + str);
801         partTitle = "";
802
803         return str;
804     }
805
806     /**
807      * Handle a chapter
808      * @param attributes the tag attributes
809      * @param contents the tag contents
810      * @return the HTML code
811      * @throws SAXEception if an error is encountered
812      */
813     public String handleChapter(final Map<String, String> attributes, final String contents) throws SAXException {
814         String fileName = attributes.get("id") + ".html";
815         String str = encloseContents("ul", "list-refentry", contents);
816         String title = encloseContents("h3", "title-chapter", chapterTitle);
817         createHTMLFile(attributes.get("id"), fileName, chapterTitle, title + "\n" + str);
818
819         str = encloseContents("li", encloseContents("a", new String[] {"href", fileName, "class", "chapter"}, chapterTitle) + "\n" + str);
820         chapterTitle = "";
821
822         return str;
823     }
824
825     // partiellement merdique car le style de title depend du noeud pere.
826     /**
827      * Handle a title
828      * @param attributes the tag attributes
829      * @param contents the tag contents
830      * @return the HTML code
831      * @throws SAXEception if an error is encountered
832      */
833     public String handleTitle(final Map<String, String> attributes, final String contents) throws SAXException {
834         String clazz = "title";
835         String parent = getParentTagName();
836         if (parent.equals("chapter")) {
837             chapterTitle = contents;
838         } else if (parent.equals("part")) {
839             partTitle = contents;
840         } else if (parent.equals("info")) {
841             bookTitle = contents;
842         } else if (parent.equals("section")) {
843             sectionTitle = contents;
844         } else if (parent.equals("refsection") && Pattern.matches("^[ \\t]*ex[ea]mpl[eo].*", contents.toLowerCase())) {
845             hasExamples = true;
846             return encloseContents("h3", clazz, contents);
847         } else if (parent.equals("refsect1")) {
848             return encloseContents("h3", clazz, contents);
849         } else if (parent.equals("refsect2")) {
850             return encloseContents("h4", clazz, contents);
851         } else if (parent.equals("refsect3")) {
852             return encloseContents("h5", clazz, contents);
853         } else {
854             return encloseContents("h3", clazz, contents);
855         }
856
857         return null;
858     }
859
860     /**
861      * Handle a para
862      * @param attributes the tag attributes
863      * @param contents the tag contents
864      * @return the HTML code
865      * @throws SAXEception if an error is encountered
866      */
867     public String handlePara(final Map<String, String> attributes, final String contents) throws SAXException {
868         return encloseContents("p", "para", contents);
869     }
870
871     /**
872      * Handle a literal
873      * @param attributes the tag attributes
874      * @param contents the tag contents
875      * @return the HTML code
876      * @throws SAXEception if an error is encountered
877      */
878     public String handleLiteral(final Map<String, String> attributes, final String contents) throws SAXException {
879       return encloseContents("code", new String[] {"class", "literal", "dir", "ltr"}, contents);
880     }
881
882     /**
883      * Handle a literallayout
884      * @param attributes the tag attributes
885      * @param contents the tag contents
886      * @return the HTML code
887      * @throws SAXEception if an error is encountered
888      */
889     public String handleLiterallayout(final Map<String, String> attributes, final String contents) throws SAXException {
890
891         //replace \n by <br>
892         String s = contents.replace("\n", "<BR>");
893         //replace spaces by &nbsp;
894         s = s.replace(" ", "&nbsp;");
895
896         return encloseContents("code", new String[] {"class", "literallayout", "dir", "ltr"}, s);
897     }
898
899     /**
900      * Handle a varname
901      * @param attributes the tag attributes
902      * @param contents the tag contents
903      * @return the HTML code
904      * @throws SAXEception if an error is encountered
905      */
906     public String handleVarname(final Map<String, String> attributes, final String contents) throws SAXException {
907         return encloseContents("code", "varname", contents);
908     }
909
910     /**
911      * Handle a command
912      * @param attributes the tag attributes
913      * @param contents the tag contents
914      * @return the HTML code
915      * @throws SAXEception if an error is encountered
916      */
917     public String handleCommand(final Map<String, String> attributes, final String contents) throws SAXException {
918         return encloseContents("code", "command", contents);
919     }
920
921     /**
922      * Handle a code
923      * @param attributes the tag attributes
924      * @param contents the tag contents
925      * @return the HTML code
926      * @throws SAXEception if an error is encountered
927      */
928     public String handleCode(final Map<String, String> attributes, final String contents) throws SAXException {
929         return encloseContents("code", "scilabcode", scilabLexer.convert(HTMLScilabCodeHandler.getInstance(refname, currentFileName), contents));//encloseContents("code", "code", contents);
930     }
931
932     /**
933      * Handle a function
934      * @param attributes the tag attributes
935      * @param contents the tag contents
936      * @return the HTML code
937      * @throws SAXEception if an error is encountered
938      */
939     public String handleFunction(final Map<String, String> attributes, final String contents) throws SAXException {
940         return encloseContents("code", "function", contents);
941     }
942
943     /**
944      * Handle a constant
945      * @param attributes the tag attributes
946      * @param contents the tag contents
947      * @return the HTML code
948      * @throws SAXEception if an error is encountered
949      */
950     public String handleConstant(final Map<String, String> attributes, final String contents) throws SAXException {
951         return encloseContents("code", "constant", contents);
952     }
953
954     /**
955      * Handle an option
956      * @param attributes the tag attributes
957      * @param contents the tag contents
958      * @return the HTML code
959      * @throws SAXEception if an error is encountered
960      */
961     public String handleOption(final Map<String, String> attributes, final String contents) throws SAXException {
962         return encloseContents("code", "option", contents);
963     }
964
965     /**
966      * Handle a refnamediv
967      * @param attributes the tag attributes
968      * @param contents the tag contents
969      * @return the HTML code
970      * @throws SAXEception if an error is encountered
971      */
972     public String handleRefnamediv(final Map<String, String> attributes, final String contents) throws SAXException {
973         String id = attributes.get("id");
974         if (id != null) {
975             currentId = id;
976         }
977
978         return encloseContents("div", "refnamediv", contents);
979     }
980
981     /**
982      * Handle a refname
983      * @param attributes the tag attributes
984      * @param contents the tag contents
985      * @return the HTML code
986      * @throws SAXEception if an error is encountered
987      */
988     public String handleRefname(final Map<String, String> attributes, final String contents) throws SAXException {
989         refname = contents;
990         return encloseContents("h1", "refname", contents);
991     }
992
993     /**
994      * Handle a refpurpose
995      * @param attributes the tag attributes
996      * @param contents the tag contents
997      * @return the HTML code
998      * @throws SAXEception if an error is encountered
999      */
1000     public String handleRefpurpose(final Map<String, String> attributes, final String contents) throws SAXException {
1001         refpurpose = contents;
1002         return encloseContents("p", "refpurpose", contents);
1003     }
1004
1005     /**
1006      * Handle a refsynopsisdiv
1007      * @param attributes the tag attributes
1008      * @param contents the tag contents
1009      * @return the HTML code
1010      * @throws SAXEception if an error is encountered
1011      */
1012     public String handleRefsynopsisdiv(final Map<String, String> attributes, final String contents) throws SAXException {
1013         String id = attributes.get("id");
1014         if (id != null) {
1015             return "<a name=\"" + id + "\"></a>" + encloseContents("div", "refsynopsisdiv", contents);
1016         } else {
1017             return encloseContents("div", "refsynopsisdiv", contents);
1018         }
1019     }
1020
1021     /**
1022      * Handle a synopsis
1023      * @param attributes the tag attributes
1024      * @param contents the tag contents
1025      * @return the HTML code
1026      * @throws SAXEception if an error is encountered
1027      */
1028     public String handleSynopsis(final Map<String, String> attributes, final String contents) throws SAXException {
1029         String id = attributes.get("id");
1030         String str = encloseContents("div", "synopsis", encloseContents("pre", SynopsisLexer.convert(refname, contents)));
1031         if (id != null) {
1032             return "<a name=\"" + id + "\"></a>" + str;
1033         } else {
1034             return str;
1035         }
1036     }
1037
1038     /**
1039      * Handle a info
1040      * @param attributes the tag attributes
1041      * @param contents the tag contents
1042      * @return the HTML code
1043      * @throws SAXEception if an error is encountered
1044      */
1045     public String handleInfo(final Map<String, String> attributes, final String contents) throws SAXException {
1046         String id = attributes.get("id");
1047         if (id != null) {
1048             return "<a name=\"" + id + "\"></a>" + encloseContents("div", "info", contents);
1049         } else {
1050             return encloseContents("div", "info", contents);
1051         }
1052     }
1053
1054     /**
1055      * Handle a refsection
1056      * @param attributes the tag attributes
1057      * @param contents the tag contents
1058      * @return the HTML code
1059      * @throws SAXEception if an error is encountered
1060      */
1061     public String handleRefsection(final Map<String, String> attributes, final String contents) throws SAXException {
1062         String id = attributes.get("id");
1063         if (id != null) {
1064             return "<a name=\"" + id + "\"></a>" + encloseContents("div", "refsection", contents);
1065         } else {
1066             return encloseContents("div", "refsection", contents);
1067         }
1068     }
1069
1070     /**
1071      * Handle a refsect1
1072      * @param attributes the tag attributes
1073      * @param contents the tag contents
1074      * @return the HTML code
1075      * @throws SAXEception if an error is encountered
1076      */
1077     public String handleRefsect1(final Map<String, String> attributes, final String contents) throws SAXException {
1078         String id = attributes.get("id");
1079         if (id != null) {
1080             return "<a name=\"" + id + "\"></a>" + encloseContents("div", "refsect1", contents);
1081         } else {
1082             return encloseContents("div", "refsect1", contents);
1083         }
1084     }
1085
1086     /**
1087      * Handle a refsect2
1088      * @param attributes the tag attributes
1089      * @param contents the tag contents
1090      * @return the HTML code
1091      * @throws SAXEception if an error is encountered
1092      */
1093     public String handleRefsect2(final Map<String, String> attributes, final String contents) throws SAXException {
1094         String id = attributes.get("id");
1095         if (id != null) {
1096             return "<a name=\"" + id + "\"></a>" + encloseContents("div", "refsect2", contents);
1097         } else {
1098             return encloseContents("div", "refsect2", contents);
1099         }
1100     }
1101
1102     /**
1103      * Handle a refsect3
1104      * @param attributes the tag attributes
1105      * @param contents the tag contents
1106      * @return the HTML code
1107      * @throws SAXEception if an error is encountered
1108      */
1109     public String handleRefsect3(final Map<String, String> attributes, final String contents) throws SAXException {
1110         String id = attributes.get("id");
1111         if (id != null) {
1112             return "<a name=\"" + id + "\"></a>" + encloseContents("div", "refsect3", contents);
1113         } else {
1114             return encloseContents("div", "refsect3", contents);
1115         }
1116     }
1117
1118     /**
1119      * Handle an anchor
1120      * @param attributes the tag attributes
1121      * @param contents the tag contents
1122      * @return the HTML code
1123      * @throws SAXEception if an error is encountered
1124      */
1125     public String handleAnchor(final Map<String, String> attributes, final String contents) throws SAXException {
1126         String id = attributes.get("id");
1127         if (id != null) {
1128             return "<a name=\"" + id + "\">" + contents + "</a>";
1129         } else {
1130             return contents;
1131         }
1132     }
1133
1134     /**
1135      * Handle a progamlisting
1136      * @param attributes the tag attributes
1137      * @param contents the tag contents
1138      * @return the HTML code
1139      * @throws SAXEception if an error is encountered
1140      */
1141     public String handleProgramlisting(final Map<String, String> attributes, final String contents) throws SAXException {
1142         String id = attributes.get("id");
1143         String role = attributes.get("role");
1144         String str;
1145         if (role == null) {
1146             String code = encloseContents("pre", "scilabcode", scilabLexer.convert(HTMLScilabCodeHandler.getInstance(refname, currentFileName), contents));
1147             if (prependToProgramListing != null) {
1148                 code = prependToProgramListing + code;
1149             }
1150             if (appendToProgramListing != null) {
1151                 code += appendToProgramListing;
1152             }
1153             str = encloseContents("div", "programlisting", code);
1154         } else {
1155             if (role.equals("xml")) {
1156                 str = encloseContents("div", "programlisting", encloseContents("pre", "xmlcode", xmlLexer.convert(HTMLXMLCodeHandler.getInstance(), contents)));
1157             } else if (role.equals("c") || role.equals("cpp") || role.equals("code_gateway")) {
1158                 hasExamples = true;
1159                 str = encloseContents("div", "programlisting", encloseContents("pre", "ccode", cLexer.convert(HTMLCCodeHandler.getInstance(), contents)));
1160             } else if (role.equals("java")) {
1161                 hasExamples = true;
1162                 str = encloseContents("div", "programlisting", encloseContents("pre", "ccode", javaLexer.convert(HTMLCCodeHandler.getInstance(), contents)));
1163             } else if (role.equals("exec")) {
1164                 String code = encloseContents("pre", "scilabcode", scilabLexer.convert(HTMLScilabCodeHandler.getInstance(refname, currentFileName), contents));
1165                 if (prependToProgramListing != null) {
1166                     code = prependToProgramListing + code;
1167                 }
1168                 if (appendForExecToProgramListing != null) {
1169                     code += appendForExecToProgramListing;
1170                 }
1171                 str = encloseContents("div", "programlisting", code);
1172             } else if (role.equals("no-scilab-exec")) {
1173                 hasExamples = true;
1174                 String code = encloseContents("pre", "scilabcode", scilabLexer.convert(HTMLScilabCodeHandler.getInstance(refname, currentFileName), contents));
1175                 str = encloseContents("div", "programlisting", code);
1176             } else {
1177                 String code = encloseContents("pre", "scilabcode", scilabLexer.convert(HTMLScilabCodeHandler.getInstance(refname, currentFileName), contents));
1178                 if (prependToProgramListing != null) {
1179                     code = prependToProgramListing + code;
1180                 }
1181                 if (appendToProgramListing != null) {
1182                     code += appendToProgramListing;
1183                 }
1184                 str = encloseContents("div", "programlisting", code);
1185             }
1186         }
1187         if (id != null) {
1188             return "<a name=\"" + id + "\"></a>" + str;
1189         } else {
1190             return str;
1191         }
1192     }
1193
1194     /**
1195      * Handle a screen
1196      * @param attributes the tag attributes
1197      * @param contents the tag contents
1198      * @return the HTML code
1199      * @throws SAXEception if an error is encountered
1200      */
1201     public String handleScreen(final Map<String, String> attributes, final String contents) throws SAXException {
1202         String id = attributes.get("id");
1203         String str = encloseContents("div", "screen", encloseContents("pre", contents.replace("<", "&lt;")));
1204         if (id != null) {
1205             return "<a name=\"" + id + "\"></a>" + str;
1206         } else {
1207             return str;
1208         }
1209     }
1210
1211     /**
1212      * Handle a pubdate
1213      * @param attributes the tag attributes
1214      * @param contents the tag contents
1215      * @return the HTML code
1216      * @throws SAXEception if an error is encountered
1217      */
1218     public String handlePubdate(final Map<String, String> attributes, final String contents) throws SAXException {
1219         return null;
1220     }
1221
1222     /**
1223      * Handle a simplelist
1224      * @param attributes the tag attributes
1225      * @param contents the tag contents
1226      * @return the HTML code
1227      * @throws SAXEception if an error is encountered
1228      */
1229     public String handleSimplelist(final Map<String, String> attributes, final String contents) throws SAXException {
1230         String style = "itemizedlist";
1231
1232         return encloseContents("ul", style, contents);
1233     }
1234
1235     /**
1236      * Handle a member
1237      * @param attributes the tag attributes
1238      * @param contents the tag contents
1239      * @return the HTML code
1240      * @throws SAXEception if an error is encountered
1241      */
1242     public String handleMember(final Map<String, String> attributes, final String contents) throws SAXException {
1243         return encloseContents("li", "member", contents);
1244     }
1245
1246     /**
1247      * Handle a link
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 handleLink(final Map<String, String> attributes, final String contents) throws SAXException {
1254         String link = attributes.get("linkend");
1255         if (link == null) {
1256             throw new SAXException("No linkend attribute in tag link");
1257         }
1258
1259         String type = attributes.get("type");
1260         String id;
1261         if (type != null && type.equals("scilab")) {
1262             if (this.type == Backend.JAVAHELP || this.type == Backend.HTML) {
1263                 id = resolvScilabLink(link);
1264             } else {
1265                 return contents;
1266             }
1267         } else if (type != null && type.equals("remote")) {
1268             id = makeRemoteLink(link);
1269         } else {
1270             id = mapId.get(link);
1271         }
1272
1273         if (id == null) {
1274             if (isToolbox) {
1275                 if (this.type == Backend.HTML) {
1276                     id = urlBase + link;
1277                     if (linkToTheWeb) {
1278                         id += ".html";
1279                     }
1280                 }
1281                 if (this.type == Backend.JAVAHELP) {
1282                     id = urlBase + link;
1283                 }
1284             } else {
1285                 warnings++;
1286                 System.err.println("Warning (should be fixed): invalid internal link to " + link + " in " + currentFileName + "\nat line " + locator.getLineNumber());
1287                 return null;
1288             }
1289         }
1290
1291         Stack<DocbookElement> stack = getStack();
1292         String refnameTarget = mapIdRefname.get(link);
1293         String str;
1294         if (contents != null && !contents.isEmpty()) {
1295             str = contents;
1296         } else {
1297             str = refnameTarget;
1298         }
1299
1300         if (str == null) {
1301             warnings++;
1302             System.err.println("Warning (should be fixed): empty link (no text will be printed) to " + link + " in " + currentFileName + "\nat line " + locator.getLineNumber());
1303         }
1304
1305         String href = encloseContents("a", new String[] {"href", id, "class", "link"}, str);
1306
1307         int s = stack.size();
1308         if (s >= 3) {
1309             DocbookElement elem = stack.get(s - 3);
1310             if (elem.getName().equals("refsection")) {
1311                 String role = elem.getAttributes().get("role");
1312                 if (role != null && role.equals("see also")) {
1313                     String purpose = mapIdPurpose.get(link);
1314                     if (purpose != null) {
1315                         return href + " &#8212; " + purpose;
1316                     } else {
1317                         return href;
1318                     }
1319                 }
1320             }
1321         }
1322
1323         return href;
1324     }
1325
1326     /**
1327      * Rewrite a link when its type is "scilab"
1328      * @param link the link
1329      * @return the modified link with protocol scilab:// for example
1330      */
1331     protected String resolvScilabLink(String link) {
1332         int pos = link.indexOf("/");
1333         if (pos == -1) {
1334             return null;
1335         }
1336
1337         String first = link.substring(0, pos);
1338         String second = link.substring(pos + 1);
1339         String[] toks = first.split("\\.");
1340         if (toks == null || toks.length != 2) {
1341             return null;
1342         }
1343
1344         if (!linkToTheWeb) {
1345             return urlBase + link;
1346         } else {
1347             if (toks[0].equals("scilab") && toks[1].equals("help")) {
1348                 return urlBase + second + ".html";
1349             } else {
1350                 return "#";
1351             }
1352         }
1353     }
1354
1355     /**
1356      * Make a remote link
1357      * @param link the link
1358      * @return the good link
1359      */
1360     protected String makeRemoteLink(String link) {
1361         return link;
1362     }
1363
1364     /**
1365      * Handle an ulink
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 handleUlink(final Map<String, String> attributes, final String contents) throws SAXException {
1372         String link = attributes.get("url");
1373         if (link == null) {
1374             throw new SAXException("No url attribute in tag ulink");
1375         }
1376
1377         return encloseContents("a", new String[] {"href", link, "class", "ulink"}, contents);
1378     }
1379
1380     /**
1381      * Handle a xref
1382      * @param attributes the tag attributes
1383      * @param contents the tag contents
1384      * @return the HTML code
1385      * @throws SAXEception if an error is encountered
1386      */
1387     public String handleXref(final Map<String, String> attributes, final String contents) throws SAXException {
1388         String link = attributes.get("linkend");
1389         if (link == null) {
1390             throw new SAXException("No linkend attribute in tag link");
1391         }
1392
1393         String id = mapId.get(link);
1394         if (id == null) {
1395             warnings++;
1396             System.err.println("Warning (should be fixed): invalid internal link to " + link + " in " + currentFileName + "\nat line " + locator.getLineNumber());
1397             return null;
1398         }
1399
1400         return encloseContents("a", new String[] {"href", id, "class", "xref"}, contents);
1401     }
1402
1403     /**
1404      * Handle a latex (not really a docbook tag...)
1405      * @param attributes the tag attributes
1406      * @param contents the tag contents
1407      * @return the HTML code
1408      * @throws SAXEception if an error is encountered
1409      */
1410     public String handleLatex(final Map<String, String> attributes, final String contents) throws SAXException {
1411         boolean isLocalized = "true".equals(attributes.get("localized"));
1412         File f;
1413         if (isLocalized) {
1414             f = new File(outImages + "/" + imageDir, LATEXBASENAME + currentBaseName + "_" + language + "_" + (latexCompt++) + ".png");
1415         } else {
1416             if ("ru_RU".equals(language) && HTMLDocbookTagConverter.containsCyrillic(contents)) {
1417                 System.err.println("Warning: LaTeX code in " + getCurrentFileName() + " contains cyrillic character. The tag <latex> should contain the attribute scilab:localized=\"true\"");
1418             } else if ("ja_JP".equals(language) && HTMLDocbookTagConverter.containsCJK(contents)) {
1419                 System.err.println("Warning: LaTeX code in " + getCurrentFileName() + " contains CJK character. The tag <latex> should contain the attribute scilab:localized=\"true\"");
1420             }
1421             f = new File(outImages + "/" + imageDir, LATEXBASENAME + currentBaseName + "_" + (latexCompt++) + ".png");
1422         }
1423
1424         String parent = getParentTagName();
1425         if (parent.equals("para") && !attributes.containsKey("style")) {
1426             attributes.put("style", "text");
1427         }
1428         String fs = attributes.get("fontsize");
1429         if (fs == null) {
1430             attributes.put("fontsize", "16");
1431         }
1432
1433         return getImageConverter().getImageByCode(currentFileName, contents, attributes, "image/latex", f, imageDir + "/" + f.getName(), getBaseImagePath(), locator.getLineNumber(), language, isLocalized);
1434     }
1435
1436     /**
1437      * Handle a term
1438      * @param attributes the tag attributes
1439      * @param contents the tag contents
1440      * @return the HTML code
1441      * @throws SAXEception if an error is encountered
1442      */
1443     public String handleTerm(final Map<String, String> attributes, final String contents) throws SAXException {
1444         String id = attributes.get("id");
1445         if (id != null) {
1446             return "<a name=\"" + id + "\"></a>" + encloseContents("span", "term", contents);
1447         } else {
1448             return encloseContents("span", "term", contents);
1449         }
1450     }
1451
1452     /**
1453      * Handle a listitem
1454      * @param attributes the tag attributes
1455      * @param contents the tag contents
1456      * @return the HTML code
1457      * @throws SAXEception if an error is encountered
1458      */
1459     public String handleListitem(final Map<String, String> attributes, final String contents) throws SAXException {
1460         String parent = getParentTagName();
1461         if (parent.equals("varlistentry")) {
1462             return encloseContents("dd", contents);
1463         }
1464         return encloseContents("li", contents);
1465     }
1466
1467     /**
1468      * Handle a varlistentry
1469      * @param attributes the tag attributes
1470      * @param contents the tag contents
1471      * @return the HTML code
1472      * @throws SAXEception if an error is encountered
1473      */
1474     public String handleVarlistentry(final Map<String, String> attributes, final String contents) throws SAXException {
1475         return encloseContents("dt", contents);
1476     }
1477
1478     /**
1479      * Handle a variablelist
1480      * @param attributes the tag attributes
1481      * @param contents the tag contents
1482      * @return the HTML code
1483      * @throws SAXEception if an error is encountered
1484      */
1485     public String handleVariablelist(final Map<String, String> attributes, final String contents) throws SAXException {
1486         return encloseContents("dl", contents);
1487     }
1488
1489     /**
1490      * Handle an itemizedlist
1491      * @param attributes the tag attributes
1492      * @param contents the tag contents
1493      * @return the HTML code
1494      * @throws SAXEception if an error is encountered
1495      */
1496     public String handleItemizedlist(final Map<String, String> attributes, final String contents) throws SAXException {
1497         String id = attributes.get("id");
1498         if (id != null) {
1499             return "<a name=\"" + id + "\"></a>" + encloseContents("ul", "itemizedlist", contents);
1500         } else {
1501             return encloseContents("ul", "itemizedlist", contents);
1502         }
1503     }
1504
1505     /**
1506      * Handle an emphasis
1507      * @param attributes the tag attributes
1508      * @param contents the tag contents
1509      * @return the HTML code
1510      * @throws SAXEception if an error is encountered
1511      */
1512     public String handleEmphasis(final Map<String, String> attributes, final String contents) throws SAXException {
1513         String role = attributes.get("role");
1514         if (role != null) {
1515             if (role.equals("bold")) {
1516                 return encloseContents("b", contents);
1517             }
1518             if (role.equals("italic")) {
1519                 return encloseContents("i", contents);
1520             }
1521         }
1522
1523         return encloseContents("em", contents);
1524     }
1525
1526     /**
1527      * Handle a tr
1528      * @param attributes the tag attributes
1529      * @param contents the tag contents
1530      * @return the HTML code
1531      * @throws SAXEception if an error is encountered
1532      */
1533     public String handleTr(final Map<String, String> attributes, final String contents) throws SAXException {
1534         String bgcolor = attributes.get("bgcolor");
1535         String valign = attributes.get("valign");
1536         String id = attributes.get("id");
1537
1538         return encloseContents("tr", new String[] {"id", id, "bgcolor", bgcolor, "valign", valign}, contents);
1539     }
1540
1541     /**
1542      * Handle a td
1543      * @param attributes the tag attributes
1544      * @param contents the tag contents
1545      * @return the HTML code
1546      * @throws SAXEception if an error is encountered
1547      */
1548     public String handleTd(final Map<String, String> attributes, final String contents) throws SAXException {
1549         String align   = attributes.get("align");
1550         String valign  = attributes.get("valign");
1551         String bgcolor = attributes.get("bgcolor");
1552         String colspan = attributes.get("colspan");
1553         String rowspan = attributes.get("rowspan");
1554         String style   = attributes.get("style");   /*  for style="white-space:nowrap" */
1555
1556         return encloseContents("td", new String[] {"align", align, "valign", valign, "bgcolor", bgcolor, "colspan", colspan, "rowspan", rowspan, "style", style}, contents);
1557     }
1558
1559     /**
1560      * Handle an informaltable
1561      * @param attributes the tag attributes
1562      * @param contents the tag contents
1563      * @return the HTML code
1564      * @throws SAXEception if an error is encountered
1565      */
1566     public String handleInformaltable(final Map<String, String> attributes, final String contents) throws SAXException {
1567         String id = attributes.get("id");
1568         String border = attributes.get("border");
1569         String cellpadding = attributes.get("cellpadding");
1570         String width = attributes.get("width");
1571         if (id != null) {
1572             return "<a name=\"" + id + "\"></a>" + encloseContents("table", new String[] {"class", "informaltable", "border", border, "cellpadding", cellpadding, "width", width}, contents);
1573         } else {
1574             return encloseContents("table", new String[] {"class", "informaltable", "border", border, "cellpadding", cellpadding, "width", width}, contents);
1575         }
1576     }
1577
1578     /**
1579      * Handle an imagedata
1580      * @param attributes the tag attributes
1581      * @param contents the tag contents
1582      * @return the HTML code
1583      * @throws SAXEception if an error is encountered
1584      */
1585     public String handleImagedata(final Map<String, String> attributes, final String contents) throws SAXException {
1586         String fileref = attributes.get("fileref");
1587         if (fileref == null) {
1588             if (contents == null || contents.length() == 0) {
1589                 throw new SAXException("No fileref attribute or no data in tag imagedata");
1590             }
1591
1592             return contents;
1593         }
1594
1595         try {
1596             String path = new File(new URI(currentFileName)).getParent();
1597             File file = ImageConverter.imageExists(path, fileref);
1598             if (file != null) {
1599                 throw new SAXException("The given fileref is not on an existing image file:\n" + fileref + " [" + file + "]");
1600             }
1601
1602             return getImageConverter().getImageByFile(attributes, path, fileref, outImages, imageDir, getBaseImagePath());
1603         }  catch (URISyntaxException e) {
1604             System.err.println(e);
1605         }
1606
1607         return null;
1608     }
1609
1610     /**
1611      * Handle an imageobject
1612      * @param attributes the tag attributes
1613      * @param contents the tag contents
1614      * @return the HTML code
1615      * @throws SAXEception if an error is encountered
1616      */
1617     public String handleImageobject(final Map<String, String> attributes, final String contents) throws SAXException {
1618         return contents;
1619     }
1620
1621     /**
1622      * Handle an textobject (as an alternative to imageobject)
1623      * @param attributes the tag attributes
1624      * @param contents the tag contents
1625      * @return the HTML code
1626      * @throws SAXEception if an error is encountered
1627      */
1628     public String handleTextobject(final Map<String, String> attributes, final String contents) throws SAXException {
1629         return "<!-- " + contents + " -->";
1630     }
1631
1632     /**
1633      * Handle an inlinemediaobject
1634      * @param attributes the tag attributes
1635      * @param contents the tag contents
1636      * @return the HTML code
1637      * @throws SAXEception if an error is encountered
1638      */
1639     public String handleInlinemediaobject(final Map<String, String> attributes, final String contents) throws SAXException {
1640         return encloseContents("span", contents);
1641     }
1642
1643     /**
1644      * Handle a screenshot
1645      * @param attributes the tag attributes
1646      * @param contents the tag contents
1647      * @return the HTML code
1648      * @throws SAXEception if an error is encountered
1649      */
1650     public String handleScreenshot(final Map<String, String> attributes, final String contents) throws SAXException {
1651         String id = attributes.get("id");
1652         if (id != null) {
1653             return "<a name=\"" + id + "\"></a>" + encloseContents("div", "screenshot", contents);
1654         } else {
1655             return encloseContents("div", "screenshot", contents);
1656         }
1657     }
1658
1659     /**
1660      * Handle a mediaobject
1661      * @param attributes the tag attributes
1662      * @param contents the tag contents
1663      * @return the HTML code
1664      * @throws SAXEception if an error is encountered
1665      */
1666     public String handleMediaobject(final Map<String, String> attributes, final String contents) throws SAXException {
1667         String id = attributes.get("id");
1668         String c = contents.replaceFirst("top:([0-9]+)px;", "");
1669         if (id != null) {
1670             return "<a name=\"" + id + "\"></a>" + encloseContents("div", "mediaobject", c);
1671         } else {
1672             return encloseContents("div", "mediaobject", c);
1673         }
1674     }
1675
1676     /**
1677      * Handle an informalequation
1678      * @param attributes the tag attributes
1679      * @param contents the tag contents
1680      * @return the HTML code
1681      * @throws SAXEception if an error is encountered
1682      */
1683     public String handleInformalequation(final Map<String, String> attributes, final String contents) throws SAXException {
1684         String id = attributes.get("id");
1685         if (id != null) {
1686             return "<a name=\"" + id + "\"></a>" + encloseContents("div", "informalequation", contents);
1687         } else {
1688             return encloseContents("div", "informalequation", contents);
1689         }
1690     }
1691
1692     /**
1693      * Handle an orderedlist
1694      * @param attributes the tag attributes
1695      * @param contents the tag contents
1696      * @return the HTML code
1697      * @throws SAXEception if an error is encountered
1698      */
1699     public String handleOrderedlist(final Map<String, String> attributes, final String contents) throws SAXException {
1700         String numeration = "1";
1701         String numAttr = attributes.get("numeration");
1702         if (numAttr != null) {
1703             if (numAttr.equals("loweralpha")) {
1704                 numeration = "a";
1705             } else if (numAttr.equals("upperalpha")) {
1706                 numeration = "A";
1707             } else if (numAttr.equals("lowerroman")) {
1708                 numeration = "i";
1709             } else if (numAttr.equals("upperroman")) {
1710                 numeration = "I";
1711             }
1712         }
1713
1714         String id = attributes.get("id");
1715         if (id != null) {
1716             return "<a name=\"" + id + "\"></a>" + encloseContents("ol", new String[] {"type", numeration}, contents);
1717         } else {
1718             return encloseContents("ol", new String[] {"type", numeration}, contents);
1719         }
1720     }
1721
1722     /**
1723      * Handle a subscript
1724      * @param attributes the tag attributes
1725      * @param contents the tag contents
1726      * @return the HTML code
1727      * @throws SAXEception if an error is encountered
1728      */
1729     public String handleSubscript(final Map<String, String> attributes, final String contents) throws SAXException {
1730         return encloseContents("sub", contents);
1731     }
1732
1733     /**
1734      * Handle a superscript
1735      * @param attributes the tag attributes
1736      * @param contents the tag contents
1737      * @return the HTML code
1738      * @throws SAXEception if an error is encountered
1739      */
1740     public String handleSuperscript(final Map<String, String> attributes, final String contents) throws SAXException {
1741         return encloseContents("sup", contents);
1742     }
1743
1744     /**
1745      * Handle a replaceable
1746      * @param attributes the tag attributes
1747      * @param contents the tag contents
1748      * @return the HTML code
1749      * @throws SAXEception if an error is encountered
1750      */
1751     public String handleReplaceable(final Map<String, String> attributes, final String contents) throws SAXException {
1752         return encloseContents("span", "replaceable", contents);
1753     }
1754
1755     /**
1756      * Handle a question
1757      * @param attributes the tag attributes
1758      * @param contents the tag contents
1759      * @return the HTML code
1760      * @throws SAXEception if an error is encountered
1761      */
1762     public String handleQuestion(final Map<String, String> attributes, final String contents) throws SAXException {
1763         return encloseContents("dt", encloseContents("strong", contents));
1764     }
1765
1766     /**
1767      * Handle an answer
1768      * @param attributes the tag attributes
1769      * @param contents the tag contents
1770      * @return the HTML code
1771      * @throws SAXEception if an error is encountered
1772      */
1773     public String handleAnswer(final Map<String, String> attributes, final String contents) throws SAXException {
1774         return encloseContents("dd", contents);
1775     }
1776
1777     /**
1778      * Handle a qandaentry
1779      * @param attributes the tag attributes
1780      * @param contents the tag contents
1781      * @return the HTML code
1782      * @throws SAXEception if an error is encountered
1783      */
1784     public String handleQandaentry(final Map<String, String> attributes, final String contents) throws SAXException {
1785         return encloseContents("dl", contents);
1786     }
1787
1788     /**
1789      * Handle a qandaset
1790      * @param attributes the tag attributes
1791      * @param contents the tag contents
1792      * @return the HTML code
1793      * @throws SAXEception if an error is encountered
1794      */
1795     public String handleQandaset(final Map<String, String> attributes, final String contents) throws SAXException {
1796         return encloseContents("div", "qandaset", contents);
1797     }
1798
1799     /**
1800      * Handle a caption
1801      * @param attributes the tag attributes
1802      * @param contents the tag contents
1803      * @return the HTML code
1804      * @throws SAXEception if an error is encountered
1805      */
1806     public String handleCaption(final Map<String, String> attributes, final String contents) throws SAXException {
1807         return encloseContents("caption", encloseContents("b", contents));
1808     }
1809
1810     /**
1811      * Handle a tbody
1812      * @param attributes the tag attributes
1813      * @param contents the tag contents
1814      * @return the HTML code
1815      * @throws SAXEception if an error is encountered
1816      */
1817     public String handleTbody(final Map<String, String> attributes, final String contents) throws SAXException {
1818         return encloseContents("tbody", "tbody", contents);
1819     }
1820
1821     /**
1822      * Handle a table
1823      * @param attributes the tag attributes
1824      * @param contents the tag contents
1825      * @return the HTML code
1826      * @throws SAXEception if an error is encountered
1827      */
1828     public String handleTable(final Map<String, String> attributes, final String contents) throws SAXException {
1829         String id = attributes.get("id");
1830         String bgcolor = attributes.get("bgcolor");
1831         String border = attributes.get("border");
1832         String cellpadding = attributes.get("cellpadding");
1833
1834         if (id != null) {
1835             return "<a name=\"" + id + "\"></a>" + encloseContents("table", new String[] {"class", "doctable", "bgcolor", bgcolor, "border", border, "cellpadding", cellpadding}, contents);
1836         } else {
1837             return encloseContents("table", new String[] {"class", "doctable", "bgcolor", bgcolor, "border", border, "cellpadding", cellpadding}, contents);
1838         }
1839     }
1840
1841     /**
1842      * Handle a surname
1843      * @param attributes the tag attributes
1844      * @param contents the tag contents
1845      * @return the HTML code
1846      * @throws SAXEception if an error is encountered
1847      */
1848     public String handleSurname(final Map<String, String> attributes, final String contents) throws SAXException {
1849         return encloseContents("span", "surname", contents);
1850     }
1851
1852     /**
1853      * Handle a firstname
1854      * @param attributes the tag attributes
1855      * @param contents the tag contents
1856      * @return the HTML code
1857      * @throws SAXEception if an error is encountered
1858      */
1859     public String handleFirstname(final Map<String, String> attributes, final String contents) throws SAXException {
1860         return encloseContents("span", "firstname", contents);
1861     }
1862
1863     /**
1864      * Handle a bibliomset
1865      * @param attributes the tag attributes
1866      * @param contents the tag contents
1867      * @return the HTML code
1868      * @throws SAXEception if an error is encountered
1869      */
1870     public String handleBibliomset(final Map<String, String> attributes, final String contents) throws SAXException {
1871         String id = attributes.get("id");
1872         if (id != null) {
1873             return "<a name=\"" + id + "\"></a>" + encloseContents("div", "bibliomset", contents);
1874         } else {
1875             return encloseContents("div", "bibliomset", contents);
1876         }
1877     }
1878
1879     /**
1880      * Handle a bibliomixed
1881      * @param attributes the tag attributes
1882      * @param contents the tag contents
1883      * @return the HTML code
1884      * @throws SAXEception if an error is encountered
1885      */
1886     public String handleBibliomixed(final Map<String, String> attributes, final String contents) throws SAXException {
1887         String id = attributes.get("id");
1888         if (id != null) {
1889             return "<a name=\"" + id + "\"></a>" + encloseContents("div", "bibliomixed", contents);
1890         } else {
1891             return encloseContents("div", "bibliomixed", contents);
1892         }
1893     }
1894
1895     /**
1896      * Handle a th
1897      * @param attributes the tag attributes
1898      * @param contents the tag contents
1899      * @return the HTML code
1900      * @throws SAXEception if an error is encountered
1901      */
1902     public String handleTh(final Map<String, String> attributes, final String contents) throws SAXException {
1903         String align = attributes.get("align");
1904         String valign = attributes.get("valign");
1905         String style   = attributes.get("style");   /*  for style="white-space:nowrap" */
1906
1907         return encloseContents("th", new String[] {"align", align, "valign", valign, "style", style}, contents);
1908     }
1909
1910     /**
1911      * Handle a revhistory
1912      * @param attributes the tag attributes
1913      * @param contents the tag contents
1914      * @return the HTML code
1915      * @throws SAXEception if an error is encountered
1916      */
1917     public String handleRevhistory(final Map<String, String> attributes, final String contents) throws SAXException {
1918         String id = attributes.get("id");
1919         String str = "<table class=\"revhistory\"><tr class=\"title\"><td>" + VERSION + "</td><td>" + DESCRIPTION + "</td></tr>" + contents + "</table>";
1920         if (id != null) {
1921             return "<a name=\"" + id + "\"></a>" + str;
1922         } else {
1923             return str;
1924         }
1925     }
1926
1927     /**
1928      * Handle a revision
1929      * @param attributes the tag attributes
1930      * @param contents the tag contents
1931      * @return the HTML code
1932      * @throws SAXEception if an error is encountered
1933      */
1934     public String handleRevision(final Map<String, String> attributes, final String contents) throws SAXException {
1935         return encloseContents("tr", new String[] {"valign", "top"}, contents);
1936     }
1937
1938     /**
1939      * Handle a revnumber
1940      * @param attributes the tag attributes
1941      * @param contents the tag contents
1942      * @return the HTML code
1943      * @throws SAXEception if an error is encountered
1944      */
1945     public String handleRevnumber(final Map<String, String> attributes, final String contents) throws SAXException {
1946         return encloseContents("td", "revnumber", contents);
1947     }
1948
1949     /**
1950      * Handle a revremark
1951      * @param attributes the tag attributes
1952      * @param contents the tag contents
1953      * @return the HTML code
1954      * @throws SAXEception if an error is encountered
1955      */
1956     public String handleRevremark(final Map<String, String> attributes, final String contents) throws SAXException {
1957         return encloseContents("td", "revremark", contents);
1958     }
1959
1960     /**
1961      * Handle a revdescription
1962      * @param attributes the tag attributes
1963      * @param contents the tag contents
1964      * @return the HTML code
1965      * @throws SAXEception if an error is encountered
1966      */
1967     public String handleRevdescription(final Map<String, String> attributes, final String contents) throws SAXException {
1968         return encloseContents("td", "revdescription", contents);
1969     }
1970
1971     /**
1972      * Handle a note
1973      * @param attributes the tag attributes
1974      * @param contents the tag contents
1975      * @return the HTML code
1976      * @throws SAXEception if an error is encountered
1977      */
1978     public String handleNote(final Map<String, String> attributes, final String contents) throws SAXException {
1979         String id = attributes.get("id");
1980         String code = "<table><tr><td valign=\"top\"><img src=\"" + getBaseImagePath() + "ScilabNote.png\"/></td><td valign=\"top\">" + encloseContents("div", "note", contents) + "</td></tr></table>";
1981         if (id != null) {
1982             return "<a name=\"" + id + "\"></a>" + code;
1983         } else {
1984             return code;
1985         }
1986     }
1987
1988     /**
1989      * Handle a warning
1990      * @param attributes the tag attributes
1991      * @param contents the tag contents
1992      * @return the HTML code
1993      * @throws SAXEception if an error is encountered
1994      */
1995     public String handleWarning(final Map<String, String> attributes, final String contents) throws SAXException {
1996         String id = attributes.get("id");
1997         String code = "<table><tr><td valign=\"top\"><img src=\"" + getBaseImagePath() + "ScilabWarning.png\"/></td><td valign=\"top\">" + encloseContents("div", "warning", contents) + "</td></tr></table>";
1998         if (id != null) {
1999             return "<a name=\"" + id + "\"></a>" + code;
2000         } else {
2001             return code;
2002         }
2003     }
2004
2005     /**
2006      * Handle a caution
2007      * @param attributes the tag attributes
2008      * @param contents the tag contents
2009      * @return the HTML code
2010      * @throws SAXEception if an error is encountered
2011      */
2012     public String handleCaution(final Map<String, String> attributes, final String contents) throws SAXException {
2013         String id = attributes.get("id");
2014         String code = "<table><tr><td valign=\"top\"><img src=\"" + getBaseImagePath() + "ScilabCaution.png\"/></td><td valign=\"top\">" + encloseContents("div", "caution", contents) + "</td></tr></table>";
2015         if (id != null) {
2016             return "<a name=\"" + id + "\"></a>" + code;
2017         } else {
2018             return code;
2019         }
2020     }
2021
2022     /**
2023      * Handle a tip
2024      * @param attributes the tag attributes
2025      * @param contents the tag contents
2026      * @return the HTML code
2027      * @throws SAXEception if an error is encountered
2028      */
2029     public String handleTip(final Map<String, String> attributes, final String contents) throws SAXException {
2030         String id = attributes.get("id");
2031         String code = "<table><tr><td valign=\"top\"><img src=\"" + getBaseImagePath() + "ScilabTip.png\"/></td><td valign=\"top\">" + encloseContents("div", "tip", contents) + "</td></tr></table>";
2032         if (id != null) {
2033             return "<a name=\"" + id + "\"></a>" + code;
2034         } else {
2035             return code;
2036         }
2037     }
2038
2039     /**
2040      * Handle a important
2041      * @param attributes the tag attributes
2042      * @param contents the tag contents
2043      * @return the HTML code
2044      * @throws SAXEception if an error is encountered
2045      */
2046     public String handleImportant(final Map<String, String> attributes, final String contents) throws SAXException {
2047         String id = attributes.get("id");
2048         String code = "<table><tr><td valign=\"top\"><img src=\"" + getBaseImagePath() + "ScilabImportant.png\"/></td><td valign=\"top\">" + encloseContents("div", "important", contents) + "</td></tr></table>";
2049         if (id != null) {
2050             return "<a name=\"" + id + "\"></a>" + code;
2051         } else {
2052             return code;
2053         }
2054     }
2055
2056     private static final String convertCode(String code) {
2057         if (code == null || code.length() == 0) {
2058             return "";
2059         }
2060
2061         StringBuffer buffer = new StringBuffer(2 * code.length());
2062         int start = 0;
2063         int end = code.length() - 1;
2064         char c = code.charAt(0);
2065
2066         // first we trim
2067         while (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
2068             if (start < end) {
2069                 c = code.charAt(++start);
2070             } else {
2071                 break;
2072             }
2073         }
2074         c = code.charAt(end);
2075         while (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
2076             if (end > 0) {
2077                 c = code.charAt(--end);
2078             } else {
2079                 break;
2080             }
2081         }
2082
2083         // replace chars by their html entities equivalent
2084         for (int j = start; j <= end; j++) {
2085             c = code.charAt(j);
2086             switch (c) {
2087                 case '&':
2088                     buffer.append("&amp;");
2089                     break;
2090                 case '<':
2091                     buffer.append("&lt;");
2092                     break;
2093                 case '>':
2094                     buffer.append("&gt;");
2095                     break;
2096                 case '\n':
2097                     buffer.append("<br />");
2098                     break;
2099                 case '\'':
2100                     buffer.append("&#039;");
2101                     break;
2102                 case '\"':
2103                     buffer.append("&quot;");
2104                     break;
2105                 default:
2106                     buffer.append(c);
2107             }
2108         }
2109
2110         return buffer.toString();
2111     }
2112 }