Update jflex to 1.8.2
[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         String alt = attrs.get("alt");
662         if (alt == null) {
663             alt = "";
664         }
665         else {
666             alt = " alt=\'" + alt + "\'";
667         }
668
669         if (getGenerationType() == Backend.JAVAHELP && isLinkedImage()) {
670             // Java HTML renderer is not good... so when  the image is linked, we remove the div
671             return "<img src=\'" + fileName + "\' style=\'position:relative;" + top  + "width:" + img.width + "px;height:" + img.height + "px\'" + alt + "/>>";
672         } else {
673             return "<" + div + align + "><img src=\'" + fileName + "\' style=\'position:relative;" + top  + "width:" + img.width + "px;height:" + img.height + "px\'" + alt + "/></" + div + ">";
674         }
675     }
676
677     @Override
678     public String generateImageCode(String fileName, Map<String, String> attrs) {
679         String idAttr    = attrs.get("id");
680         String alignAttr = attrs.get("align");   // mixes align and valign imagedata attributes
681         String widthAttr = attrs.get("width");
682         String heightAttr= attrs.get("height");  // officially named "depth" as imagedata attribute
683         String styleAttr = attrs.get("style");
684         String altAttr = attrs.get("alt");       // for example: LaTeX content as text
685         boolean addDiv = getGenerationType() != Backend.JAVAHELP || !isLinkedImage();
686         final StringBuilder buffer = new StringBuilder(128);
687         if (addDiv && alignAttr != null) {
688             buffer.append("<div style=\'text-align:").append(alignAttr).append("\'>\n");
689         }
690         buffer.append("<img src=\'").append(fileName).append("\' ");
691         if (!addDiv && alignAttr != null) {
692             buffer.append("align=\'").append(alignAttr).append("\' ");
693         }
694         if (idAttr != null){
695             buffer.append("id=\'").append(idAttr).append("\' ");
696         }
697         if (widthAttr != null){   // To avoid misshaping: setting width priority > setting height
698             buffer.append("width=\'").append(widthAttr).append("\' ");
699         }
700         else {
701             if (heightAttr != null) {
702                 buffer.append("height=\'").append(heightAttr).append("\' ");
703             }
704         }
705         if (styleAttr != null) {
706             buffer.append("style=\'").append(styleAttr).append("\' ");
707         }
708         if (altAttr != null) {
709             altAttr = altAttr.replaceAll("\'", "&apos;").replaceAll("\"", "&quot;");
710             buffer.append("alt=\'").append(altAttr).append("\'");
711         }
712         buffer.append("/>\n");
713         if (addDiv && alignAttr != null) {
714             buffer.append("</div>\n");
715         }
716
717         return buffer.toString();
718     }
719
720     public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
721         latexCompt = 1;
722         return super.resolveEntity(publicId, systemId);
723     }
724
725     /**
726      * Handle a refentry
727      * @param attributes the tag attributes
728      * @param contents the tag contents
729      * @return the HTML code
730      * @throws SAXEception if an error is encountered
731      */
732     public String handleRefentry(final Map<String, String> attributes, final String contents) throws SAXException {
733         String id = attributes.get("id");
734         if (id != null) {
735             currentId = id;
736         }
737         String fileName = mapId.get(currentId);
738         String needsExampleAttr = attributes.get("needs-examples");
739         createHTMLFile(currentId, fileName, refpurpose, contents);
740         if (!hasExamples && (needsExampleAttr == null || !needsExampleAttr.equals("no"))) {
741             warnings++;
742             //System.err.println("Warning (should be fixed): no example in " + currentFileName);
743         } else {
744             hasExamples = false;
745         }
746         String rp = encloseContents("span", "refentry-description", refpurpose);
747         String str = encloseContents("li", encloseContents("a", new String[] {"href", fileName, "class", "refentry"}, refname) + " &#8212; " + rp);
748         refpurpose = "";
749         refname = "";
750         currentId = null;
751
752         return str;
753     }
754
755     /**
756      * Handle a section
757      * @param attributes the tag attributes
758      * @param contents the tag contents
759      * @return the HTML code
760      * @throws SAXEception if an error is encountered
761      */
762     public String handleSection(final Map<String, String> attributes, final String contents) throws SAXException {
763         String fileName = attributes.get("id") + ".html";
764         String str = encloseContents("ul", "list-refentry", contents);
765         String title = encloseContents("h3", "title-section", sectionTitle);
766         createHTMLFile(attributes.get("id"), fileName, sectionTitle, title + "\n" + str);
767
768         str = encloseContents("li", encloseContents("a", new String[] {"href", fileName, "class", "section"}, sectionTitle) + "\n" + str);
769         sectionTitle = "";
770
771         return str;
772     }
773
774     /**
775      * Handle a book
776      * @param attributes the tag attributes
777      * @param contents the tag contents
778      * @return the HTML code
779      * @throws SAXEception if an error is encountered
780      */
781     public String handleBook(final Map<String, String> attributes, final String contents) throws SAXException {
782         String str = encloseContents("ul", "list-part", contents);
783         String btitle;
784         if (bookTitle.trim().equalsIgnoreCase("Scilab")) {
785             btitle = version;
786         } else {
787             btitle = bookTitle;
788         }
789         String title = encloseContents("h3", "book-title", btitle);
790         createHTMLFile("index", indexFilename, btitle, title + "\n" + str);
791
792         if (warnings != 0) {
793             System.err.println("Total files without example: " + warnings);
794             System.err.println("Total generated html files: " + nbFiles);
795         }
796
797         return encloseContents("li", encloseContents("a", new String[] {"href", indexFilename, "class", "part"}, bookTitle) + "\n" + str);
798     }
799
800     /**
801      * Handle a part
802      * @param attributes the tag attributes
803      * @param contents the tag contents
804      * @return the HTML code
805      * @throws SAXEception if an error is encountered
806      */
807     public String handlePart(final Map<String, String> attributes, final String contents) throws SAXException {
808         String fileName = attributes.get("id") + ".html";
809         String str = encloseContents("ul", "list-chapter", contents);
810         String title = encloseContents("h3", "title-part", partTitle);
811         createHTMLFile(attributes.get("id"), fileName, partTitle, title + "\n" + str);
812         str = encloseContents("li", encloseContents("a", new String[] {"href", fileName, "class", "part"}, partTitle) + "\n" + str);
813         partTitle = "";
814
815         return str;
816     }
817
818     /**
819      * Handle a chapter
820      * @param attributes the tag attributes
821      * @param contents the tag contents
822      * @return the HTML code
823      * @throws SAXEception if an error is encountered
824      */
825     public String handleChapter(final Map<String, String> attributes, final String contents) throws SAXException {
826         String fileName = attributes.get("id") + ".html";
827         String str = encloseContents("ul", "list-refentry", contents);
828         String title = encloseContents("h3", "title-chapter", chapterTitle);
829         createHTMLFile(attributes.get("id"), fileName, chapterTitle, title + "\n" + str);
830
831         str = encloseContents("li", encloseContents("a", new String[] {"href", fileName, "class", "chapter"}, chapterTitle) + "\n" + str);
832         chapterTitle = "";
833
834         return str;
835     }
836
837     // partiellement merdique car le style de title depend du noeud pere.
838     /**
839      * Handle a title
840      * @param attributes the tag attributes
841      * @param contents the tag contents
842      * @return the HTML code
843      * @throws SAXEception if an error is encountered
844      */
845     public String handleTitle(final Map<String, String> attributes, final String contents) throws SAXException {
846         String clazz = "title";
847         String parent = getParentTagName();
848         if (parent.equals("chapter")) {
849             chapterTitle = contents;
850         } else if (parent.equals("part")) {
851             partTitle = contents;
852         } else if (parent.equals("info")) {
853             bookTitle = contents;
854         } else if (parent.equals("section")) {
855             sectionTitle = contents;
856         } else if (parent.equals("refsection") && Pattern.matches("^[ \\t]*ex[ea]mpl[eo].*", contents.toLowerCase())) {
857             hasExamples = true;
858             return encloseContents("h3", clazz, contents);
859         } else if (parent.equals("refsect1")) {
860             return encloseContents("h3", clazz, contents);
861         } else if (parent.equals("refsect2")) {
862             return encloseContents("h4", clazz, contents);
863         } else if (parent.equals("refsect3")) {
864             return encloseContents("h5", clazz, contents);
865         } else {
866             return encloseContents("h3", clazz, contents);
867         }
868
869         return null;
870     }
871
872     /**
873      * Handle a para
874      * @param attributes the tag attributes
875      * @param contents the tag contents
876      * @return the HTML code
877      * @throws SAXEception if an error is encountered
878      */
879     public String handlePara(final Map<String, String> attributes, final String contents) throws SAXException {
880         return encloseContents("p", "para", contents);
881     }
882
883     /**
884      * Handle a literal
885      * @param attributes the tag attributes
886      * @param contents the tag contents
887      * @return the HTML code
888      * @throws SAXEception if an error is encountered
889      */
890     public String handleLiteral(final Map<String, String> attributes, final String contents) throws SAXException {
891       return encloseContents("code", new String[] {"class", "literal", "dir", "ltr"}, contents);
892     }
893
894     /**
895      * Handle a literallayout
896      * @param attributes the tag attributes
897      * @param contents the tag contents
898      * @return the HTML code
899      * @throws SAXEception if an error is encountered
900      */
901     public String handleLiterallayout(final Map<String, String> attributes, final String contents) throws SAXException {
902
903         //replace \n by <br>
904         String s = contents.replace("\n", "<BR>");
905         //replace spaces by &nbsp;
906         s = s.replace(" ", "&nbsp;");
907
908         return encloseContents("code", new String[] {"class", "literallayout", "dir", "ltr"}, s);
909     }
910
911     /**
912      * Handle a varname
913      * @param attributes the tag attributes
914      * @param contents the tag contents
915      * @return the HTML code
916      * @throws SAXEception if an error is encountered
917      */
918     public String handleVarname(final Map<String, String> attributes, final String contents) throws SAXException {
919         return encloseContents("code", "varname", contents);
920     }
921
922     /**
923      * Handle a command
924      * @param attributes the tag attributes
925      * @param contents the tag contents
926      * @return the HTML code
927      * @throws SAXEception if an error is encountered
928      */
929     public String handleCommand(final Map<String, String> attributes, final String contents) throws SAXException {
930         return encloseContents("code", "command", contents);
931     }
932
933     /**
934      * Handle a code
935      * @param attributes the tag attributes
936      * @param contents the tag contents
937      * @return the HTML code
938      * @throws SAXEception if an error is encountered
939      */
940     public String handleCode(final Map<String, String> attributes, final String contents) throws SAXException {
941         return encloseContents("code", "scilabcode", scilabLexer.convert(HTMLScilabCodeHandler.getInstance(refname, currentFileName), contents));//encloseContents("code", "code", contents);
942     }
943
944     /**
945      * Handle a function
946      * @param attributes the tag attributes
947      * @param contents the tag contents
948      * @return the HTML code
949      * @throws SAXEception if an error is encountered
950      */
951     public String handleFunction(final Map<String, String> attributes, final String contents) throws SAXException {
952         return encloseContents("code", "function", contents);
953     }
954
955     /**
956      * Handle a constant
957      * @param attributes the tag attributes
958      * @param contents the tag contents
959      * @return the HTML code
960      * @throws SAXEception if an error is encountered
961      */
962     public String handleConstant(final Map<String, String> attributes, final String contents) throws SAXException {
963         return encloseContents("code", "constant", contents);
964     }
965
966     /**
967      * Handle an option
968      * @param attributes the tag attributes
969      * @param contents the tag contents
970      * @return the HTML code
971      * @throws SAXEception if an error is encountered
972      */
973     public String handleOption(final Map<String, String> attributes, final String contents) throws SAXException {
974         return encloseContents("code", "option", contents);
975     }
976
977     /**
978      * Handle a refnamediv
979      * @param attributes the tag attributes
980      * @param contents the tag contents
981      * @return the HTML code
982      * @throws SAXEception if an error is encountered
983      */
984     public String handleRefnamediv(final Map<String, String> attributes, final String contents) throws SAXException {
985         String id = attributes.get("id");
986         if (id != null) {
987             currentId = id;
988         }
989
990         return encloseContents("div", "refnamediv", contents);
991     }
992
993     /**
994      * Handle a refname
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 handleRefname(final Map<String, String> attributes, final String contents) throws SAXException {
1001         refname = contents;
1002         return encloseContents("h1", "refname", contents);
1003     }
1004
1005     /**
1006      * Handle a refpurpose
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 handleRefpurpose(final Map<String, String> attributes, final String contents) throws SAXException {
1013         refpurpose = contents;
1014         return encloseContents("p", "refpurpose", contents);
1015     }
1016
1017     /**
1018      * Handle a refsynopsisdiv
1019      * @param attributes the tag attributes
1020      * @param contents the tag contents
1021      * @return the HTML code
1022      * @throws SAXEception if an error is encountered
1023      */
1024     public String handleRefsynopsisdiv(final Map<String, String> attributes, final String contents) throws SAXException {
1025         String id = attributes.get("id");
1026         if (id != null) {
1027             return "<a name=\"" + id + "\"></a>" + encloseContents("div", "refsynopsisdiv", contents);
1028         } else {
1029             return encloseContents("div", "refsynopsisdiv", contents);
1030         }
1031     }
1032
1033     /**
1034      * Handle a synopsis
1035      * @param attributes the tag attributes
1036      * @param contents the tag contents
1037      * @return the HTML code
1038      * @throws SAXEception if an error is encountered
1039      */
1040     public String handleSynopsis(final Map<String, String> attributes, final String contents) throws SAXException {
1041         String id = attributes.get("id");
1042         String str = encloseContents("div", "synopsis", encloseContents("pre", SynopsisLexer.convert(refname, contents)));
1043         if (id != null) {
1044             return "<a name=\"" + id + "\"></a>" + str;
1045         } else {
1046             return str;
1047         }
1048     }
1049
1050     /**
1051      * Handle a info
1052      * @param attributes the tag attributes
1053      * @param contents the tag contents
1054      * @return the HTML code
1055      * @throws SAXEception if an error is encountered
1056      */
1057     public String handleInfo(final Map<String, String> attributes, final String contents) throws SAXException {
1058         String id = attributes.get("id");
1059         if (id != null) {
1060             return "<a name=\"" + id + "\"></a>" + encloseContents("div", "info", contents);
1061         } else {
1062             return encloseContents("div", "info", contents);
1063         }
1064     }
1065
1066     /**
1067      * Handle a refsection
1068      * @param attributes the tag attributes
1069      * @param contents the tag contents
1070      * @return the HTML code
1071      * @throws SAXEception if an error is encountered
1072      */
1073     public String handleRefsection(final Map<String, String> attributes, final String contents) throws SAXException {
1074         String id = attributes.get("id");
1075         if (id != null) {
1076             return "<a name=\"" + id + "\"></a>" + encloseContents("div", "refsection", contents);
1077         } else {
1078             return encloseContents("div", "refsection", contents);
1079         }
1080     }
1081
1082     /**
1083      * Handle a refsect1
1084      * @param attributes the tag attributes
1085      * @param contents the tag contents
1086      * @return the HTML code
1087      * @throws SAXEception if an error is encountered
1088      */
1089     public String handleRefsect1(final Map<String, String> attributes, final String contents) throws SAXException {
1090         String id = attributes.get("id");
1091         if (id != null) {
1092             return "<a name=\"" + id + "\"></a>" + encloseContents("div", "refsect1", contents);
1093         } else {
1094             return encloseContents("div", "refsect1", contents);
1095         }
1096     }
1097
1098     /**
1099      * Handle a refsect2
1100      * @param attributes the tag attributes
1101      * @param contents the tag contents
1102      * @return the HTML code
1103      * @throws SAXEception if an error is encountered
1104      */
1105     public String handleRefsect2(final Map<String, String> attributes, final String contents) throws SAXException {
1106         String id = attributes.get("id");
1107         if (id != null) {
1108             return "<a name=\"" + id + "\"></a>" + encloseContents("div", "refsect2", contents);
1109         } else {
1110             return encloseContents("div", "refsect2", contents);
1111         }
1112     }
1113
1114     /**
1115      * Handle a refsect3
1116      * @param attributes the tag attributes
1117      * @param contents the tag contents
1118      * @return the HTML code
1119      * @throws SAXEception if an error is encountered
1120      */
1121     public String handleRefsect3(final Map<String, String> attributes, final String contents) throws SAXException {
1122         String id = attributes.get("id");
1123         if (id != null) {
1124             return "<a name=\"" + id + "\"></a>" + encloseContents("div", "refsect3", contents);
1125         } else {
1126             return encloseContents("div", "refsect3", contents);
1127         }
1128     }
1129
1130     /**
1131      * Handle an anchor
1132      * @param attributes the tag attributes
1133      * @param contents the tag contents
1134      * @return the HTML code
1135      * @throws SAXEception if an error is encountered
1136      */
1137     public String handleAnchor(final Map<String, String> attributes, final String contents) throws SAXException {
1138         String id = attributes.get("id");
1139         if (id != null) {
1140             return "<a name=\"" + id + "\">" + contents + "</a>";
1141         } else {
1142             return contents;
1143         }
1144     }
1145
1146     /**
1147      * Handle a progamlisting
1148      * @param attributes the tag attributes
1149      * @param contents the tag contents
1150      * @return the HTML code
1151      * @throws SAXEception if an error is encountered
1152      */
1153     public String handleProgramlisting(final Map<String, String> attributes, final String contents) throws SAXException {
1154         String id = attributes.get("id");
1155         String role = attributes.get("role");
1156         String str;
1157         if (role == null) {
1158             String code = encloseContents("pre", "scilabcode", scilabLexer.convert(HTMLScilabCodeHandler.getInstance(refname, currentFileName), contents));
1159             if (prependToProgramListing != null) {
1160                 code = prependToProgramListing + code;
1161             }
1162             if (appendToProgramListing != null) {
1163                 code += appendToProgramListing;
1164             }
1165             str = encloseContents("div", "programlisting", code);
1166         } else {
1167             if (role.equals("xml")) {
1168                 str = encloseContents("div", "programlisting", encloseContents("pre", "xmlcode", xmlLexer.convert(HTMLXMLCodeHandler.getInstance(), contents)));
1169             } else if (role.equals("c") || role.equals("cpp") || role.equals("code_gateway")) {
1170                 hasExamples = true;
1171                 str = encloseContents("div", "programlisting", encloseContents("pre", "ccode", cLexer.convert(HTMLCCodeHandler.getInstance(), contents)));
1172             } else if (role.equals("java")) {
1173                 hasExamples = true;
1174                 str = encloseContents("div", "programlisting", encloseContents("pre", "ccode", javaLexer.convert(HTMLCCodeHandler.getInstance(), contents)));
1175             } else if (role.equals("exec")) {
1176                 String code = encloseContents("pre", "scilabcode", scilabLexer.convert(HTMLScilabCodeHandler.getInstance(refname, currentFileName), contents));
1177                 if (prependToProgramListing != null) {
1178                     code = prependToProgramListing + code;
1179                 }
1180                 if (appendForExecToProgramListing != null) {
1181                     code += appendForExecToProgramListing;
1182                 }
1183                 str = encloseContents("div", "programlisting", code);
1184             } else if (role.equals("no-scilab-exec")) {
1185                 hasExamples = true;
1186                 String code = encloseContents("pre", "scilabcode", scilabLexer.convert(HTMLScilabCodeHandler.getInstance(refname, currentFileName), contents));
1187                 str = encloseContents("div", "programlisting", code);
1188             } else {
1189                 String code = encloseContents("pre", "scilabcode", scilabLexer.convert(HTMLScilabCodeHandler.getInstance(refname, currentFileName), contents));
1190                 if (prependToProgramListing != null) {
1191                     code = prependToProgramListing + code;
1192                 }
1193                 if (appendToProgramListing != null) {
1194                     code += appendToProgramListing;
1195                 }
1196                 str = encloseContents("div", "programlisting", code);
1197             }
1198         }
1199         if (id != null) {
1200             return "<a name=\"" + id + "\"></a>" + str;
1201         } else {
1202             return str;
1203         }
1204     }
1205
1206     /**
1207      * Handle a screen
1208      * @param attributes the tag attributes
1209      * @param contents the tag contents
1210      * @return the HTML code
1211      * @throws SAXEception if an error is encountered
1212      */
1213     public String handleScreen(final Map<String, String> attributes, final String contents) throws SAXException {
1214         String id = attributes.get("id");
1215         String str = encloseContents("div", "screen", encloseContents("pre", contents.replace("<", "&lt;")));
1216         if (id != null) {
1217             return "<a name=\"" + id + "\"></a>" + str;
1218         } else {
1219             return str;
1220         }
1221     }
1222
1223     /**
1224      * Handle a pubdate
1225      * @param attributes the tag attributes
1226      * @param contents the tag contents
1227      * @return the HTML code
1228      * @throws SAXEception if an error is encountered
1229      */
1230     public String handlePubdate(final Map<String, String> attributes, final String contents) throws SAXException {
1231         return null;
1232     }
1233
1234     /**
1235      * Handle a simplelist
1236      * @param attributes the tag attributes
1237      * @param contents the tag contents
1238      * @return the HTML code
1239      * @throws SAXEception if an error is encountered
1240      */
1241     public String handleSimplelist(final Map<String, String> attributes, final String contents) throws SAXException {
1242         String style = "itemizedlist";
1243
1244         return encloseContents("ul", style, contents);
1245     }
1246
1247     /**
1248      * Handle a member
1249      * @param attributes the tag attributes
1250      * @param contents the tag contents
1251      * @return the HTML code
1252      * @throws SAXEception if an error is encountered
1253      */
1254     public String handleMember(final Map<String, String> attributes, final String contents) throws SAXException {
1255         return encloseContents("li", "member", contents);
1256     }
1257
1258     /**
1259      * Handle a link
1260      * @param attributes the tag attributes
1261      * @param contents the tag contents
1262      * @return the HTML code
1263      * @throws SAXEception if an error is encountered
1264      */
1265     public String handleLink(final Map<String, String> attributes, final String contents) throws SAXException {
1266         String link = attributes.get("linkend");
1267         if (link == null) {
1268             throw new SAXException("No linkend attribute in tag link");
1269         }
1270
1271         String type = attributes.get("type");
1272         String id;
1273         if (type != null && type.equals("scilab")) {
1274             if (this.type == Backend.JAVAHELP || this.type == Backend.HTML) {
1275                 id = resolvScilabLink(link);
1276             } else {
1277                 return contents;
1278             }
1279         } else if (type != null && type.equals("remote")) {
1280             id = makeRemoteLink(link);
1281         } else {
1282             id = mapId.get(link);
1283         }
1284
1285         if (id == null) {
1286             if (isToolbox) {
1287                 if (this.type == Backend.HTML) {
1288                     id = urlBase + link;
1289                     if (linkToTheWeb) {
1290                         id += ".html";
1291                     }
1292                 }
1293                 if (this.type == Backend.JAVAHELP) {
1294                     id = urlBase + link;
1295                 }
1296             } else {
1297                 warnings++;
1298                 System.err.println("Warning (should be fixed): invalid internal link to " + link + " in " + currentFileName + "\nat line " + locator.getLineNumber());
1299                 return null;
1300             }
1301         }
1302
1303         Stack<DocbookElement> stack = getStack();
1304         String refnameTarget = mapIdRefname.get(link);
1305         String str;
1306         if (contents != null && !contents.isEmpty()) {
1307             str = contents;
1308         } else {
1309             str = refnameTarget;
1310         }
1311
1312         if (str == null) {
1313             warnings++;
1314             System.err.println("Warning (should be fixed): empty link (no text will be printed) to " + link + " in " + currentFileName + "\nat line " + locator.getLineNumber());
1315         }
1316
1317         String href = encloseContents("a", new String[] {"href", id, "class", "link"}, str);
1318
1319         int s = stack.size();
1320         if (s >= 3) {
1321             DocbookElement elem = stack.get(s - 3);
1322             if (elem.getName().equals("refsection")) {
1323                 String role = elem.getAttributes().get("role");
1324                 if (role != null && role.equals("see also")) {
1325                     String purpose = mapIdPurpose.get(link);
1326                     if (purpose != null) {
1327                         return href + " &#8212; " + purpose;
1328                     } else {
1329                         return href;
1330                     }
1331                 }
1332             }
1333         }
1334
1335         return href;
1336     }
1337
1338     /**
1339      * Rewrite a link when its type is "scilab"
1340      * @param link the link
1341      * @return the modified link with protocol scilab:// for example
1342      */
1343     protected String resolvScilabLink(String link) {
1344         int pos = link.indexOf("/");
1345         if (pos == -1) {
1346             return null;
1347         }
1348
1349         String first = link.substring(0, pos);
1350         String second = link.substring(pos + 1);
1351         String[] toks = first.split("\\.");
1352         if (toks == null || toks.length != 2) {
1353             return null;
1354         }
1355
1356         if (!linkToTheWeb) {
1357             return urlBase + link;
1358         } else {
1359             if (toks[0].equals("scilab") && toks[1].equals("help")) {
1360                 return urlBase + second + ".html";
1361             } else {
1362                 return "#";
1363             }
1364         }
1365     }
1366
1367     /**
1368      * Make a remote link
1369      * @param link the link
1370      * @return the good link
1371      */
1372     protected String makeRemoteLink(String link) {
1373         return link;
1374     }
1375
1376     /**
1377      * Handle an ulink
1378      * @param attributes the tag attributes
1379      * @param contents the tag contents
1380      * @return the HTML code
1381      * @throws SAXEception if an error is encountered
1382      */
1383     public String handleUlink(final Map<String, String> attributes, final String contents) throws SAXException {
1384         String link = attributes.get("url");
1385         if (link == null) {
1386             throw new SAXException("No url attribute in tag ulink");
1387         }
1388
1389         return encloseContents("a", new String[] {"href", link, "class", "ulink"}, contents);
1390     }
1391
1392     /**
1393      * Handle a xref
1394      * @param attributes the tag attributes
1395      * @param contents the tag contents
1396      * @return the HTML code
1397      * @throws SAXEception if an error is encountered
1398      */
1399     public String handleXref(final Map<String, String> attributes, final String contents) throws SAXException {
1400         String link = attributes.get("linkend");
1401         if (link == null) {
1402             throw new SAXException("No linkend attribute in tag link");
1403         }
1404
1405         String id = mapId.get(link);
1406         if (id == null) {
1407             warnings++;
1408             System.err.println("Warning (should be fixed): invalid internal link to " + link + " in " + currentFileName + "\nat line " + locator.getLineNumber());
1409             return null;
1410         }
1411
1412         return encloseContents("a", new String[] {"href", id, "class", "xref"}, contents);
1413     }
1414
1415     /**
1416      * Handle a latex (not really a docbook tag...)
1417      * @param attributes the tag attributes
1418      * @param contents the tag contents
1419      * @return the HTML code
1420      * @throws SAXEception if an error is encountered
1421      */
1422     public String handleLatex(final Map<String, String> attributes, final String contents) throws SAXException {
1423         boolean isLocalized = "true".equals(attributes.get("localized"));
1424         File f;
1425         if (isLocalized) {
1426             f = new File(outImages + "/" + imageDir, LATEXBASENAME + currentBaseName + "_" + language + "_" + (latexCompt++) + ".png");
1427         } else {
1428             if ("ru_RU".equals(language) && HTMLDocbookTagConverter.containsCyrillic(contents)) {
1429                 System.err.println("Warning: LaTeX code in " + getCurrentFileName() + " contains cyrillic character. The tag <latex> should contain the attribute scilab:localized=\"true\"");
1430             } else if ("ja_JP".equals(language) && HTMLDocbookTagConverter.containsCJK(contents)) {
1431                 System.err.println("Warning: LaTeX code in " + getCurrentFileName() + " contains CJK character. The tag <latex> should contain the attribute scilab:localized=\"true\"");
1432             }
1433             f = new File(outImages + "/" + imageDir, LATEXBASENAME + currentBaseName + "_" + (latexCompt++) + ".png");
1434         }
1435
1436         String parent = getParentTagName();
1437         if (parent.equals("para") && !attributes.containsKey("style")) {
1438             attributes.put("style", "text");
1439         }
1440         String fs = attributes.get("fontsize");
1441         if (fs == null) {
1442             attributes.put("fontsize", "16");
1443         }
1444
1445         return getImageConverter().getImageByCode(currentFileName, contents, attributes, "image/latex", f, imageDir + "/" + f.getName(), getBaseImagePath(), locator.getLineNumber(), language, isLocalized);
1446     }
1447
1448     /**
1449      * Handle a term
1450      * @param attributes the tag attributes
1451      * @param contents the tag contents
1452      * @return the HTML code
1453      * @throws SAXEception if an error is encountered
1454      */
1455     public String handleTerm(final Map<String, String> attributes, final String contents) throws SAXException {
1456         String id = attributes.get("id");
1457         if (id != null) {
1458             return "<a name=\"" + id + "\"></a>" + encloseContents("span", "term", contents);
1459         } else {
1460             return encloseContents("span", "term", contents);
1461         }
1462     }
1463
1464     /**
1465      * Handle a listitem
1466      * @param attributes the tag attributes
1467      * @param contents the tag contents
1468      * @return the HTML code
1469      * @throws SAXEception if an error is encountered
1470      */
1471     public String handleListitem(final Map<String, String> attributes, final String contents) throws SAXException {
1472         String parent = getParentTagName();
1473         if (parent.equals("varlistentry")) {
1474             return encloseContents("dd", contents);
1475         }
1476         return encloseContents("li", contents);
1477     }
1478
1479     /**
1480      * Handle a varlistentry
1481      * @param attributes the tag attributes
1482      * @param contents the tag contents
1483      * @return the HTML code
1484      * @throws SAXEception if an error is encountered
1485      */
1486     public String handleVarlistentry(final Map<String, String> attributes, final String contents) throws SAXException {
1487         return encloseContents("dt", contents);
1488     }
1489
1490     /**
1491      * Handle a variablelist
1492      * @param attributes the tag attributes
1493      * @param contents the tag contents
1494      * @return the HTML code
1495      * @throws SAXEception if an error is encountered
1496      */
1497     public String handleVariablelist(final Map<String, String> attributes, final String contents) throws SAXException {
1498         return encloseContents("dl", contents);
1499     }
1500
1501     /**
1502      * Handle an itemizedlist
1503      * @param attributes the tag attributes
1504      * @param contents the tag contents
1505      * @return the HTML code
1506      * @throws SAXEception if an error is encountered
1507      */
1508     public String handleItemizedlist(final Map<String, String> attributes, final String contents) throws SAXException {
1509         String id = attributes.get("id");
1510         if (id != null) {
1511             return "<a name=\"" + id + "\"></a>" + encloseContents("ul", "itemizedlist", contents);
1512         } else {
1513             return encloseContents("ul", "itemizedlist", contents);
1514         }
1515     }
1516
1517     /**
1518      * Handle an emphasis
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 handleEmphasis(final Map<String, String> attributes, final String contents) throws SAXException {
1525         String role = attributes.get("role");
1526         if (role != null) {
1527             if (role.equals("bold")) {
1528                 return encloseContents("b", contents);
1529             }
1530             if (role.equals("italic")) {
1531                 return encloseContents("i", contents);
1532             }
1533         }
1534
1535         return encloseContents("em", contents);
1536     }
1537
1538     /**
1539      * Handle a tr
1540      * @param attributes the tag attributes
1541      * @param contents the tag contents
1542      * @return the HTML code
1543      * @throws SAXEception if an error is encountered
1544      */
1545     public String handleTr(final Map<String, String> attributes, final String contents) throws SAXException {
1546         String bgcolor = attributes.get("bgcolor");
1547         String valign = attributes.get("valign");
1548         String id = attributes.get("id");
1549
1550         return encloseContents("tr", new String[] {"id", id, "bgcolor", bgcolor, "valign", valign}, contents);
1551     }
1552
1553     /**
1554      * Handle a td
1555      * @param attributes the tag attributes
1556      * @param contents the tag contents
1557      * @return the HTML code
1558      * @throws SAXEception if an error is encountered
1559      */
1560     public String handleTd(final Map<String, String> attributes, final String contents) throws SAXException {
1561         String align   = attributes.get("align");
1562         String valign  = attributes.get("valign");
1563         String bgcolor = attributes.get("bgcolor");
1564         String colspan = attributes.get("colspan");
1565         String rowspan = attributes.get("rowspan");
1566         String style   = attributes.get("style");   /*  for style="white-space:nowrap" */
1567
1568         return encloseContents("td", new String[] {"align", align, "valign", valign, "bgcolor", bgcolor, "colspan", colspan, "rowspan", rowspan, "style", style}, contents);
1569     }
1570
1571     /**
1572      * Handle an informaltable
1573      * @param attributes the tag attributes
1574      * @param contents the tag contents
1575      * @return the HTML code
1576      * @throws SAXEception if an error is encountered
1577      */
1578     public String handleInformaltable(final Map<String, String> attributes, final String contents) throws SAXException {
1579         String id = attributes.get("id");
1580         String border = attributes.get("border");
1581         String cellpadding = attributes.get("cellpadding");
1582         String width = attributes.get("width");
1583         if (id != null) {
1584             return "<a name=\"" + id + "\"></a>" + encloseContents("table", new String[] {"class", "informaltable", "border", border, "cellpadding", cellpadding, "width", width}, contents);
1585         } else {
1586             return encloseContents("table", new String[] {"class", "informaltable", "border", border, "cellpadding", cellpadding, "width", width}, contents);
1587         }
1588     }
1589
1590     /**
1591      * Handle an imagedata
1592      * @param attributes the tag attributes
1593      * @param contents the tag contents
1594      * @return the HTML code
1595      * @throws SAXEception if an error is encountered
1596      */
1597     public String handleImagedata(final Map<String, String> attributes, final String contents) throws SAXException {
1598         String fileref = attributes.get("fileref");
1599         if (fileref == null) {
1600             if (contents == null || contents.length() == 0) {
1601                 throw new SAXException("No fileref attribute or no data in tag imagedata");
1602             }
1603
1604             return contents;
1605         }
1606
1607         try {
1608             String path = new File(new URI(currentFileName)).getParent();
1609             File file = ImageConverter.imageExists(path, fileref);
1610             if (file != null) {
1611                 throw new SAXException("The given fileref is not on an existing image file:\n" + fileref + " [" + file + "]");
1612             }
1613
1614             return getImageConverter().getImageByFile(attributes, path, fileref, outImages, imageDir, getBaseImagePath());
1615         }  catch (URISyntaxException e) {
1616             System.err.println(e);
1617         }
1618
1619         return null;
1620     }
1621
1622     /**
1623      * Handle an imageobject
1624      * @param attributes the tag attributes
1625      * @param contents the tag contents
1626      * @return the HTML code
1627      * @throws SAXEception if an error is encountered
1628      */
1629     public String handleImageobject(final Map<String, String> attributes, final String contents) throws SAXException {
1630         return contents;
1631     }
1632
1633     /**
1634      * Handle an textobject (as an alternative to imageobject)
1635      * @param attributes the tag attributes
1636      * @param contents the tag contents
1637      * @return the HTML code
1638      * @throws SAXEception if an error is encountered
1639      */
1640     public String handleTextobject(final Map<String, String> attributes, final String contents) throws SAXException {
1641         return "<!-- " + contents + " -->";
1642     }
1643
1644     /**
1645      * Handle an inlinemediaobject
1646      * @param attributes the tag attributes
1647      * @param contents the tag contents
1648      * @return the HTML code
1649      * @throws SAXEception if an error is encountered
1650      */
1651     public String handleInlinemediaobject(final Map<String, String> attributes, final String contents) throws SAXException {
1652         return encloseContents("span", contents);
1653     }
1654
1655     /**
1656      * Handle a screenshot
1657      * @param attributes the tag attributes
1658      * @param contents the tag contents
1659      * @return the HTML code
1660      * @throws SAXEception if an error is encountered
1661      */
1662     public String handleScreenshot(final Map<String, String> attributes, final String contents) throws SAXException {
1663         String id = attributes.get("id");
1664         if (id != null) {
1665             return "<a name=\"" + id + "\"></a>" + encloseContents("div", "screenshot", contents);
1666         } else {
1667             return encloseContents("div", "screenshot", contents);
1668         }
1669     }
1670
1671     /**
1672      * Handle a mediaobject
1673      * @param attributes the tag attributes
1674      * @param contents the tag contents
1675      * @return the HTML code
1676      * @throws SAXEception if an error is encountered
1677      */
1678     public String handleMediaobject(final Map<String, String> attributes, final String contents) throws SAXException {
1679         String id = attributes.get("id");
1680         String c = contents.replaceFirst("top:([0-9]+)px;", "");
1681         if (id != null) {
1682             return "<a name=\"" + id + "\"></a>" + encloseContents("div", "mediaobject", c);
1683         } else {
1684             return encloseContents("div", "mediaobject", c);
1685         }
1686     }
1687
1688     /**
1689      * Handle an informalequation
1690      * @param attributes the tag attributes
1691      * @param contents the tag contents
1692      * @return the HTML code
1693      * @throws SAXEception if an error is encountered
1694      */
1695     public String handleInformalequation(final Map<String, String> attributes, final String contents) throws SAXException {
1696         String id = attributes.get("id");
1697         if (id != null) {
1698             return "<a name=\"" + id + "\"></a>" + encloseContents("div", "informalequation", contents);
1699         } else {
1700             return encloseContents("div", "informalequation", contents);
1701         }
1702     }
1703
1704     /**
1705      * Handle an orderedlist
1706      * @param attributes the tag attributes
1707      * @param contents the tag contents
1708      * @return the HTML code
1709      * @throws SAXEception if an error is encountered
1710      */
1711     public String handleOrderedlist(final Map<String, String> attributes, final String contents) throws SAXException {
1712         String numeration = "1";
1713         String numAttr = attributes.get("numeration");
1714         if (numAttr != null) {
1715             if (numAttr.equals("loweralpha")) {
1716                 numeration = "a";
1717             } else if (numAttr.equals("upperalpha")) {
1718                 numeration = "A";
1719             } else if (numAttr.equals("lowerroman")) {
1720                 numeration = "i";
1721             } else if (numAttr.equals("upperroman")) {
1722                 numeration = "I";
1723             }
1724         }
1725
1726         String id = attributes.get("id");
1727         if (id != null) {
1728             return "<a name=\"" + id + "\"></a>" + encloseContents("ol", new String[] {"type", numeration}, contents);
1729         } else {
1730             return encloseContents("ol", new String[] {"type", numeration}, contents);
1731         }
1732     }
1733
1734     /**
1735      * Handle a subscript
1736      * @param attributes the tag attributes
1737      * @param contents the tag contents
1738      * @return the HTML code
1739      * @throws SAXEception if an error is encountered
1740      */
1741     public String handleSubscript(final Map<String, String> attributes, final String contents) throws SAXException {
1742         return encloseContents("sub", contents);
1743     }
1744
1745     /**
1746      * Handle a superscript
1747      * @param attributes the tag attributes
1748      * @param contents the tag contents
1749      * @return the HTML code
1750      * @throws SAXEception if an error is encountered
1751      */
1752     public String handleSuperscript(final Map<String, String> attributes, final String contents) throws SAXException {
1753         return encloseContents("sup", contents);
1754     }
1755
1756     /**
1757      * Handle a replaceable
1758      * @param attributes the tag attributes
1759      * @param contents the tag contents
1760      * @return the HTML code
1761      * @throws SAXEception if an error is encountered
1762      */
1763     public String handleReplaceable(final Map<String, String> attributes, final String contents) throws SAXException {
1764         return encloseContents("span", "replaceable", contents);
1765     }
1766
1767     /**
1768      * Handle a question
1769      * @param attributes the tag attributes
1770      * @param contents the tag contents
1771      * @return the HTML code
1772      * @throws SAXEception if an error is encountered
1773      */
1774     public String handleQuestion(final Map<String, String> attributes, final String contents) throws SAXException {
1775         return encloseContents("dt", encloseContents("strong", contents));
1776     }
1777
1778     /**
1779      * Handle an answer
1780      * @param attributes the tag attributes
1781      * @param contents the tag contents
1782      * @return the HTML code
1783      * @throws SAXEception if an error is encountered
1784      */
1785     public String handleAnswer(final Map<String, String> attributes, final String contents) throws SAXException {
1786         return encloseContents("dd", contents);
1787     }
1788
1789     /**
1790      * Handle a qandaentry
1791      * @param attributes the tag attributes
1792      * @param contents the tag contents
1793      * @return the HTML code
1794      * @throws SAXEception if an error is encountered
1795      */
1796     public String handleQandaentry(final Map<String, String> attributes, final String contents) throws SAXException {
1797         return encloseContents("dl", contents);
1798     }
1799
1800     /**
1801      * Handle a qandaset
1802      * @param attributes the tag attributes
1803      * @param contents the tag contents
1804      * @return the HTML code
1805      * @throws SAXEception if an error is encountered
1806      */
1807     public String handleQandaset(final Map<String, String> attributes, final String contents) throws SAXException {
1808         return encloseContents("div", "qandaset", contents);
1809     }
1810
1811     /**
1812      * Handle a caption
1813      * @param attributes the tag attributes
1814      * @param contents the tag contents
1815      * @return the HTML code
1816      * @throws SAXEception if an error is encountered
1817      */
1818     public String handleCaption(final Map<String, String> attributes, final String contents) throws SAXException {
1819         return encloseContents("caption", encloseContents("b", contents));
1820     }
1821
1822     /**
1823      * Handle a tbody
1824      * @param attributes the tag attributes
1825      * @param contents the tag contents
1826      * @return the HTML code
1827      * @throws SAXEception if an error is encountered
1828      */
1829     public String handleTbody(final Map<String, String> attributes, final String contents) throws SAXException {
1830         return encloseContents("tbody", "tbody", contents);
1831     }
1832
1833     /**
1834      * Handle a table
1835      * @param attributes the tag attributes
1836      * @param contents the tag contents
1837      * @return the HTML code
1838      * @throws SAXEception if an error is encountered
1839      */
1840     public String handleTable(final Map<String, String> attributes, final String contents) throws SAXException {
1841         String id = attributes.get("id");
1842         String bgcolor = attributes.get("bgcolor");
1843         String border = attributes.get("border");
1844         String cellpadding = attributes.get("cellpadding");
1845
1846         if (id != null) {
1847             return "<a name=\"" + id + "\"></a>" + encloseContents("table", new String[] {"class", "doctable", "bgcolor", bgcolor, "border", border, "cellpadding", cellpadding}, contents);
1848         } else {
1849             return encloseContents("table", new String[] {"class", "doctable", "bgcolor", bgcolor, "border", border, "cellpadding", cellpadding}, contents);
1850         }
1851     }
1852
1853     /**
1854      * Handle a surname
1855      * @param attributes the tag attributes
1856      * @param contents the tag contents
1857      * @return the HTML code
1858      * @throws SAXEception if an error is encountered
1859      */
1860     public String handleSurname(final Map<String, String> attributes, final String contents) throws SAXException {
1861         return encloseContents("span", "surname", contents);
1862     }
1863
1864     /**
1865      * Handle a firstname
1866      * @param attributes the tag attributes
1867      * @param contents the tag contents
1868      * @return the HTML code
1869      * @throws SAXEception if an error is encountered
1870      */
1871     public String handleFirstname(final Map<String, String> attributes, final String contents) throws SAXException {
1872         return encloseContents("span", "firstname", contents);
1873     }
1874
1875     /**
1876      * Handle a bibliomset
1877      * @param attributes the tag attributes
1878      * @param contents the tag contents
1879      * @return the HTML code
1880      * @throws SAXEception if an error is encountered
1881      */
1882     public String handleBibliomset(final Map<String, String> attributes, final String contents) throws SAXException {
1883         String id = attributes.get("id");
1884         if (id != null) {
1885             return "<a name=\"" + id + "\"></a>" + encloseContents("div", "bibliomset", contents);
1886         } else {
1887             return encloseContents("div", "bibliomset", contents);
1888         }
1889     }
1890
1891     /**
1892      * Handle a bibliomixed
1893      * @param attributes the tag attributes
1894      * @param contents the tag contents
1895      * @return the HTML code
1896      * @throws SAXEception if an error is encountered
1897      */
1898     public String handleBibliomixed(final Map<String, String> attributes, final String contents) throws SAXException {
1899         String id = attributes.get("id");
1900         if (id != null) {
1901             return "<a name=\"" + id + "\"></a>" + encloseContents("div", "bibliomixed", contents);
1902         } else {
1903             return encloseContents("div", "bibliomixed", contents);
1904         }
1905     }
1906
1907     /**
1908      * Handle a th
1909      * @param attributes the tag attributes
1910      * @param contents the tag contents
1911      * @return the HTML code
1912      * @throws SAXEception if an error is encountered
1913      */
1914     public String handleTh(final Map<String, String> attributes, final String contents) throws SAXException {
1915         String align = attributes.get("align");
1916         String valign = attributes.get("valign");
1917         String style   = attributes.get("style");   /*  for style="white-space:nowrap" */
1918
1919         return encloseContents("th", new String[] {"align", align, "valign", valign, "style", style}, contents);
1920     }
1921
1922     /**
1923      * Handle a revhistory
1924      * @param attributes the tag attributes
1925      * @param contents the tag contents
1926      * @return the HTML code
1927      * @throws SAXEception if an error is encountered
1928      */
1929     public String handleRevhistory(final Map<String, String> attributes, final String contents) throws SAXException {
1930         String id = attributes.get("id");
1931         String str = "<table class=\"revhistory\"><tr class=\"title\"><td>" + VERSION + "</td><td>" + DESCRIPTION + "</td></tr>" + contents + "</table>";
1932         if (id != null) {
1933             return "<a name=\"" + id + "\"></a>" + str;
1934         } else {
1935             return str;
1936         }
1937     }
1938
1939     /**
1940      * Handle a revision
1941      * @param attributes the tag attributes
1942      * @param contents the tag contents
1943      * @return the HTML code
1944      * @throws SAXEception if an error is encountered
1945      */
1946     public String handleRevision(final Map<String, String> attributes, final String contents) throws SAXException {
1947         return encloseContents("tr", new String[] {"valign", "top"}, contents);
1948     }
1949
1950     /**
1951      * Handle a revnumber
1952      * @param attributes the tag attributes
1953      * @param contents the tag contents
1954      * @return the HTML code
1955      * @throws SAXEception if an error is encountered
1956      */
1957     public String handleRevnumber(final Map<String, String> attributes, final String contents) throws SAXException {
1958         return encloseContents("td", "revnumber", contents);
1959     }
1960
1961     /**
1962      * Handle a revremark
1963      * @param attributes the tag attributes
1964      * @param contents the tag contents
1965      * @return the HTML code
1966      * @throws SAXEception if an error is encountered
1967      */
1968     public String handleRevremark(final Map<String, String> attributes, final String contents) throws SAXException {
1969         return encloseContents("td", "revremark", contents);
1970     }
1971
1972     /**
1973      * Handle a revdescription
1974      * @param attributes the tag attributes
1975      * @param contents the tag contents
1976      * @return the HTML code
1977      * @throws SAXEception if an error is encountered
1978      */
1979     public String handleRevdescription(final Map<String, String> attributes, final String contents) throws SAXException {
1980         return encloseContents("td", "revdescription", contents);
1981     }
1982
1983     /**
1984      * Handle a note
1985      * @param attributes the tag attributes
1986      * @param contents the tag contents
1987      * @return the HTML code
1988      * @throws SAXEception if an error is encountered
1989      */
1990     public String handleNote(final Map<String, String> attributes, final String contents) throws SAXException {
1991         String id = attributes.get("id");
1992         String code = "<table><tr><td valign=\"top\"><img src=\"" + getBaseImagePath() + "ScilabNote.png\"/></td><td valign=\"top\">" + encloseContents("div", "note", contents) + "</td></tr></table>";
1993         if (id != null) {
1994             return "<a name=\"" + id + "\"></a>" + code;
1995         } else {
1996             return code;
1997         }
1998     }
1999
2000     /**
2001      * Handle a warning
2002      * @param attributes the tag attributes
2003      * @param contents the tag contents
2004      * @return the HTML code
2005      * @throws SAXEception if an error is encountered
2006      */
2007     public String handleWarning(final Map<String, String> attributes, final String contents) throws SAXException {
2008         String id = attributes.get("id");
2009         String code = "<table><tr><td valign=\"top\"><img src=\"" + getBaseImagePath() + "ScilabWarning.png\"/></td><td valign=\"top\">" + encloseContents("div", "warning", contents) + "</td></tr></table>";
2010         if (id != null) {
2011             return "<a name=\"" + id + "\"></a>" + code;
2012         } else {
2013             return code;
2014         }
2015     }
2016
2017     /**
2018      * Handle a caution
2019      * @param attributes the tag attributes
2020      * @param contents the tag contents
2021      * @return the HTML code
2022      * @throws SAXEception if an error is encountered
2023      */
2024     public String handleCaution(final Map<String, String> attributes, final String contents) throws SAXException {
2025         String id = attributes.get("id");
2026         String code = "<table><tr><td valign=\"top\"><img src=\"" + getBaseImagePath() + "ScilabCaution.png\"/></td><td valign=\"top\">" + encloseContents("div", "caution", contents) + "</td></tr></table>";
2027         if (id != null) {
2028             return "<a name=\"" + id + "\"></a>" + code;
2029         } else {
2030             return code;
2031         }
2032     }
2033
2034     /**
2035      * Handle a tip
2036      * @param attributes the tag attributes
2037      * @param contents the tag contents
2038      * @return the HTML code
2039      * @throws SAXEception if an error is encountered
2040      */
2041     public String handleTip(final Map<String, String> attributes, final String contents) throws SAXException {
2042         String id = attributes.get("id");
2043         String code = "<table><tr><td valign=\"top\"><img src=\"" + getBaseImagePath() + "ScilabTip.png\"/></td><td valign=\"top\">" + encloseContents("div", "tip", contents) + "</td></tr></table>";
2044         if (id != null) {
2045             return "<a name=\"" + id + "\"></a>" + code;
2046         } else {
2047             return code;
2048         }
2049     }
2050
2051     /**
2052      * Handle a important
2053      * @param attributes the tag attributes
2054      * @param contents the tag contents
2055      * @return the HTML code
2056      * @throws SAXEception if an error is encountered
2057      */
2058     public String handleImportant(final Map<String, String> attributes, final String contents) throws SAXException {
2059         String id = attributes.get("id");
2060         String code = "<table><tr><td valign=\"top\"><img src=\"" + getBaseImagePath() + "ScilabImportant.png\"/></td><td valign=\"top\">" + encloseContents("div", "important", contents) + "</td></tr></table>";
2061         if (id != null) {
2062             return "<a name=\"" + id + "\"></a>" + code;
2063         } else {
2064             return code;
2065         }
2066     }
2067
2068     private static final String convertCode(String code) {
2069         if (code == null || code.length() == 0) {
2070             return "";
2071         }
2072
2073         StringBuffer buffer = new StringBuffer(2 * code.length());
2074         int start = 0;
2075         int end = code.length() - 1;
2076         char c = code.charAt(0);
2077
2078         // first we trim
2079         while (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
2080             if (start < end) {
2081                 c = code.charAt(++start);
2082             } else {
2083                 break;
2084             }
2085         }
2086         c = code.charAt(end);
2087         while (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
2088             if (end > 0) {
2089                 c = code.charAt(--end);
2090             } else {
2091                 break;
2092             }
2093         }
2094
2095         // replace chars by their html entities equivalent
2096         for (int j = start; j <= end; j++) {
2097             c = code.charAt(j);
2098             switch (c) {
2099                 case '&':
2100                     buffer.append("&amp;");
2101                     break;
2102                 case '<':
2103                     buffer.append("&lt;");
2104                     break;
2105                 case '>':
2106                     buffer.append("&gt;");
2107                     break;
2108                 case '\n':
2109                     buffer.append("<br />");
2110                     break;
2111                 case '\'':
2112                     buffer.append("&#039;");
2113                     break;
2114                 case '\"':
2115                     buffer.append("&quot;");
2116                     break;
2117                 default:
2118                     buffer.append(c);
2119             }
2120         }
2121
2122         return buffer.toString();
2123     }
2124 }