package org.h3270.render;
/*
* Copyright (C) 2003-2008 akquinet tech@spree
*
* This file is part of h3270.
*
* h3270 is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* h3270 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with h3270; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
import java.util.*;
import org.h3270.host.*;
import org.h3270.web.*;
/**
* @author Andre Spiegel spiegel@gnu.org
* @version $Id: HtmlRenderer.java,v 1.25 2008/11/21 14:48:32 spiegel Exp $
*/
public class HtmlRenderer implements Renderer {
/**
* Maps the integer values of extended color attributes to the
* corresponding CSS classes.
*/
private IntMap extendedColorMap = null;
/**
* Maps the integer values of extended highlight attributes to the
* corresponding CSS classes.
*/
private IntMap extendedHighlightMap = null;
public boolean canRender (Screen s) {
return true;
}
public boolean canRender (String screenText) {
return true;
}
public static String escapeHTMLAttribute (String value) {
return value.replaceAll("\\&","&").
replaceAll("\"",""").
replaceAll("\'","'");
}
public static String escapeHTMLText (String value) {
return value.replaceAll("\\&","&").
replaceAll("\\<","<").
replaceAll("\\>",">");
}
public String render (Screen screen, String actionURL, String id) {
StringBuffer result = new StringBuffer();
result.append ("<form id=\"" + getFormName(id) + "\" "
+ "action=\"" + actionURL + "\" "
+ "onClick=\"installKeyHandler('" + getFormName(id) + "')\" "
+ "onMouseOver=\"installKeyHandler('" + getFormName(id) + "')\" "
+ "method=\"post\" class=\"h3270-form\">\n");
if (screen.isFormatted())
renderFormatted (screen, id, result);
else
renderUnformatted (screen, id, result);
result.append ("<div><input type=\"hidden\" name=\"key\" /></div>\n");
if (id != null && id.length() > 0) {
result.append ("<div><input type=\"hidden\" name=\""
+ SessionState.TERMINAL + "\" value=\""
+ id + "\"></div>\n");
}
result.append ("</form>\n");
appendFocus (screen, id, result);
return result.toString();
}
public String render (Screen screen) {
return this.render (screen, "", null);
}
public String render (Screen screen, String actionURL) {
return this.render (screen, actionURL, null);
}
/**
* If screen has a focused field, append Javascript code to buffer
* so that this field gets the focus in the client browser.
*/
protected void appendFocus (Screen screen, String id, StringBuffer buffer) {
buffer.append ("<script type=\"text/javascript\">\n");
buffer.append (" installKeyHandler('" + getFormName(id) + "');\n");
Field f = screen.getFocusedField();
if (f != null) {
buffer.append (" document.forms[\"" + getFormName(id) + "\"]." +
"field_" + f.getStartX() + "_" + f.getStartY() +
(f.isMultiline() ? "_0" : "") + ".focus()\n");
}
buffer.append ("</script>\n");
}
private void renderFormatted (Screen screen, String id, StringBuffer result) {
result.append ("<pre>");
for (Iterator i = screen.getFields().iterator(); i.hasNext();) {
Field f = (Field)i.next();
if (f instanceof InputField) {
if (f.getStartX() == 0) {
if (f.getStartY() > 0) {
result.append (" \n");
}
} else
result.append (" ");
renderInputField (result, (InputField)f, id);
if (f.getEndX() == screen.getWidth()-1 && f.getEndY() >= f.getStartY())
result.append ("\n");
} else {
String text = f.getText();
// First append the control character that started the field,
// without any formatting applied to it.
if (text.length() > 0) {
result.append(text.charAt(0));
}
if (needSpan (f)) {
result.append ("<span class=\"" + protectedFieldClass(f) + "\">");
}
// Now the rest of the field.
if (text.length() > 1) {
String newText = text.substring(1).replaceAll ("\u0000", " ");
result.append (escapeHTMLText (newText));
}
if (needSpan(f)) result.append ("</span>");
}
}
result.append ("</pre>");
}
private boolean needSpan (Field f) {
return f.isIntensified() || f.isHidden() ||
f.hasExtendedColor() || f.hasExtendedHighlight();
}
private String protectedFieldClass (Field f) {
StringBuffer result = new StringBuffer();
boolean isIntensified = f.isIntensified();
boolean isHidden = f.isHidden();
boolean hasExtendedColor = f.hasExtendedColor();
boolean hasExtendedHighlight = f.hasExtendedHighlight();
if (isIntensified) result.append ("h3270-intensified");
else if (isHidden) result.append ("h3270-hidden");
if (hasExtendedColor) {
if (isIntensified || isHidden) result.append (" ");
result.append (getExtendedColorMap().get (f.getExtendedColor()));
}
if (hasExtendedHighlight) {
if (isIntensified || isHidden || hasExtendedColor) result.append (" ");
result.append (getExtendedHighlightMap().get (f.getExtendedHighlight()));
}
return result.toString();
}
private IntMap getExtendedColorMap() {
if (extendedColorMap == null) {
extendedColorMap = new IntMap();
extendedColorMap.put (Field.ATTR_COL_BLUE, "h3270-color-blue");
extendedColorMap.put (Field.ATTR_COL_RED, "h3270-color-red");
extendedColorMap.put (Field.ATTR_COL_PINK, "h3270-color-pink");
extendedColorMap.put (Field.ATTR_COL_GREEN, "h3270-color-green");
extendedColorMap.put (Field.ATTR_COL_TURQUOISE, "h3270-color-turquoise");
extendedColorMap.put (Field.ATTR_COL_YELLOW, "h3270-color-yellow");
extendedColorMap.put (Field.ATTR_COL_WHITE, "h3270-color-white");
}
return extendedColorMap;
}
private IntMap getExtendedHighlightMap() {
if (extendedHighlightMap == null) {
extendedHighlightMap = new IntMap();
extendedHighlightMap.put (Field.ATTR_EH_BLINK, "h3270-highlight-blink");
extendedHighlightMap.put (Field.ATTR_EH_REV_VIDEO, "h3270-highlight-rev-video");
extendedHighlightMap.put (Field.ATTR_EH_UNDERSCORE,"h3270-highlight-underscore");
}
return extendedHighlightMap;
}
private void renderUnformatted (Screen screen, String id, StringBuffer result) {
result.append ("<textarea name=\"field\" class=\"h3270-input\" "
+ "cursor=\"lime\" "
+ "rows=" + screen.getHeight()
+ " cols=" + screen.getWidth() + ">\n");
for (int y = 0; y < screen.getHeight(); y++) {
for (int x = 0; x < screen.getWidth(); x++) {
char ch = screen.charAt (x, y);
if (ch == '\u0000')
result.append (' ');
else
result.append (ch);
}
result.append ("\n");
}
result.append ("</textarea>\n");
result.append ("<script type=\"text/javascript\">\n");
result.append (" installKeyHandler(' " + getFormName(id) + "');\n");
result.append (" document.forms[\"" + getFormName(id) + "\"].field.focus();\n");
result.append ("</script>\n");
}
protected void renderInputField (StringBuffer result, InputField f, String id) {
if (!f.isMultiline()) {
createHtmlInput (result, f, id, f.getValue(),
-1, f.getEndX() - f.getStartX() + 1);
} else {
createHtmlInput (result, f, id, f.getValue(0), 0,
f.getScreen().getWidth() - f.getStartX());
result.append ("\n");
for (int i=1; i < f.getHeight() - 1; i++) {
createHtmlInput (result, f, id, f.getValue(i), i, f.getScreen().getWidth());
result.append ("\n");
}
int lastLine = f.getHeight() - 1;
createHtmlInput (result, f, id, f.getValue(lastLine), lastLine,
f.getEndX()+1);
}
}
protected void createHtmlInput (StringBuffer result, InputField f, String id,
String value, int lineNumber, int width) {
result.append ("<input ");
result.append ("type=" + (f.isHidden() ? "\"password\" " : "\"text\" "));
result.append ("name=\"field_" + f.getStartX() + "_" + f.getStartY());
if (lineNumber != -1)
result.append ("_" + lineNumber);
result.append ("\" ");
if (f.isIntensified())
result.append ("class=\"h3270-input-intensified\" ");
else if (f.isHidden())
result.append ("class=\"h3270-input-hidden\" ");
else
result.append ("class=\"h3270-input\" ");
result.append ("value=\"" + escapeHTMLAttribute(InputField.trim(value)) + "\" ");
result.append ("maxlength=\"" + width + "\" ");
result.append ("size=\"" + width + "\" ");
result.append ("/>");
}
protected String getFormName (String id) {
if (id == null)
return "screen";
else
return "screen-" + id;
}
}