home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1998 November
/
Chip_1998-11_cd.bin
/
tema
/
Cafe
/
jfc.bin
/
HTMLDocument.java
< prev
next >
Wrap
Text File
|
1998-02-26
|
38KB
|
1,472 lines
/*
* @(#)HTMLDocument.java 1.53 98/02/02
*
* Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the confidential and proprietary information of Sun
* Microsystems, Inc. ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Sun.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
* SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
* THIS SOFTWARE OR ITS DERIVATIVES.
*
*/
package com.sun.java.swing.text.html;
import java.awt.Color;
import java.awt.Component;
import java.util.Vector;
import java.util.Stack;
import java.util.Enumeration;
import java.net.URL;
import java.net.MalformedURLException;
import java.io.*;
import com.sun.java.swing.*;
import com.sun.java.swing.text.*;
import com.sun.java.swing.Icon;
import com.sun.java.swing.ImageIcon;
/**
* A document that maintains an html element structure.
*
* @author Timothy Prinzing
* @author Sara Swanson
* @author Makarand Gokhale
* @version 1.53 02/02/98
*/
class HTMLDocument extends DefaultStyledDocument implements HTMLDefs {
/**
* The property name for the actual html tag name used
* as an attribute for the writer.
*/
public static final String HTMLTagAttribute = "htmltag";
/**
* The property name for the base href which is used to
* define the absolute URL against relatives URLs in the document.
*/
public static final String BaseHrefProperty = "basehref";
/**
* The property name for the BGCOLOR which is used to
* define the Background Color for a HTML Document
*/
public static final String BGCOLOR = "BGCOLOR";
/**
* The property name for the BACKGROUND (Image) which is used to
* define the Background Image for a HTML Document
*/
public static final String BACKGROUND = "BACKGROUND";
/**
* The property name for the Keywords which is used to
* define the keywords for a HTML Document
*/
public static final String KEYWORDS = "Keywords";
/**
* The property name for the TEXT which is used to
* define the text color for a HTML Document
*/
public static final String TEXT = "TEXT";
/**
* The property name for the LINK which is used to
* define the hyperlink color which is NOT Visited or NOT active
*/
public static final String LINK = "LINK";
/**
* The property name for the VLINK which is used to
* define the visited hyperlink color for a HTML Document
*/
public static final String VLINK = "VLINK";
/**
* The property name for the ALINK which is used to
* define the active hyperlink color for a HTML Document
*/
public static final String ALINK = "ALINK";
/**
* The attribute name used to identify INPUT tag elements.
*/
public static final String HTMLInputComponent = "input-component";
/**
* Constructs an html document.
*/
public HTMLDocument() {
super();
}
/**
* Constructs an html document with the default content
* storage implementation and a shared set of styles.
*
* @param styles the styles
*/
public HTMLDocument(StyleContext styles) {
super(new StringContent(BUFFER_SIZE_DEFAULT), styles);
}
public void setRootElementAttributes(MutableAttributeSet attr) {
Element section = getDefaultRootElement();
try {
writeLock();
MutableAttributeSet mattr = (MutableAttributeSet) section.getAttributes();
mattr.addAttributes(attr);
}
finally {
writeUnlock();
}
}
public void read(Reader in, int pos) throws IOException {
Object desc = getProperty(Document.StreamDescriptionProperty);
if (desc instanceof URL) {
reference = (URL) desc;
}
HTMLReader reader = new HTMLReader();
reader.read(pos, in);
}
/**
* Inserts new elements in bulk.
*
* @param offset the starting offset
* @data the element data
* @exception BadLocationException for an invalid starting offset
* @see StyledDocument#insert
* @exception BadLocationException if the given position does not
* represent a valid location in the associated document.
*/
protected void insert(int offset, ElementSpec[] data) throws BadLocationException {
super.insert(offset, data);
}
StyleContext getStyleContext() {
return (StyleContext) getAttributeContext();
}
/**
* Return a vector containing any components on the page that were
* derived from the contents of a FORM tag.
*/
public void getComponents(Vector compList) {
AbstractElement section = (AbstractElement)getDefaultRootElement();
findComponents(section, compList);
}
/**
* A recursive function that searches the model for components and
* determines if they are FORM components.
*/
private void findComponents(AbstractElement elem, Vector compList) {
if (elem.isLeaf()) {
AttributeSet a = elem.getAttributes();
String str = new String(HTMLInputComponent);
if (a.getAttribute(str) != null) {
compList.addElement((Component)a.getAttribute(
StyleConstants.ComponentAttribute));
}
} else {
int n = elem.getElementCount();
for (int i = 0; i < n; i++) {
AbstractElement e = (AbstractElement) elem.getElement(i);
findComponents(e, compList);
}
}
}
/**
* The location to resolve relative url's against. By
* default this will be the documents url if the document
* was loaded from a url. If a base tag is found and
* can be parsed, it will be used as the reference location.
*/
URL reference;
/**
* An HTML reader to load a styled document with an HTML
* element structure.
*/
class HTMLReader extends HTMLParserCallbackDefault {
/**
* Loads the given input stream (which is expected to
* contain valid html) into the given StyledDocument.
*
* @param doc the document to read into
* @param offset the starting offset in the document
* @param in the input stream
*/
public void read(int offset, Reader in) throws IOException {
parser = new html32(in);
StyleContext context = getStyleContext();
charAttr = context.addStyle(null, null);
attr = context.addStyle(null, null);
resolver = getStyle(StyleReader.DEFAULT_STYLE_HIERARCHY);
String hack = " ";
ElementSpec es = new ElementSpec(
null, ElementSpec.ContentType, hack.toCharArray(), 0, 1);
parseBuffer.addElement(es);
es = new ElementSpec(null, ElementSpec.EndTagType);
parseBuffer.addElement(es);
parser.setCallback(this);
try {
parser.html();
} catch (Exception e) {
e.printStackTrace();
throw new IOException(e.toString());
}
ElementSpec[] spec = new ElementSpec[parseBuffer.size()];
parseBuffer.copyInto(spec);
try {
insert(offset, spec);
} catch (BadLocationException bl) {
throw new IOException("BadLocationException: " + bl.getMessage());
}
}
/**
* Fetches the CHILD_STYLE from a named style previously added.
*
* @param nm the name of the style
* @return the style
*/
public Style getChildStyle(String nm) {
Style shStyle = getStyle("SH" + nm);
return (Style)shStyle.getAttribute(StyleReader.CHILD_STYLE);
}
/**
* Adds an attribute for the current tag being
* scanned.
*
* @param name the attribute name
* @param value the attribute value
*/
public void attributeAction(String name, String value) {
if (value == null) {
value = HTMLDefs.NULL_ATTRIBUTE;
}
attr.addAttribute(name.toLowerCase(), value);
}
private void setAlignment(MutableAttributeSet a) {
String align = (String) a.getAttribute(ALIGN);
if (align != null) {
align = align.toLowerCase();
if (align.equals("left")) {
StyleConstants.setAlignment(a, StyleConstants.ALIGN_LEFT);
} else if (align.equals("center")) {
StyleConstants.setAlignment(a, StyleConstants.ALIGN_CENTER);
} else if (align.equals("right")) {
StyleConstants.setAlignment(a, StyleConstants.ALIGN_RIGHT);
}
}
}
public void blockOpenAction(String tag) {
setAlignment(attr);
blockOpen(tag, false);
}
public void blockCloseAction(String tag) {
blockClose();
}
public void incrementPCData() {
if (!dataCountStack.empty()) {
DataCounter dc = (DataCounter)dataCountStack.pop();
dc.incCounter();
dataCountStack.push(dc);
}
}
/**
* Implements the pcdata action to create an ElementSpec
* record for content with the current character attributes
* defined. This is added to the parse buffer
*/
public void pcdataAction(String data) {
// Keep track of the pcdata's seen in each nested block
incrementPCData();
// Translate special characters like ", <, and &034
String xstr = xlateSpecialChars(data);
if (xstr != null) {
data = xstr;
}
if (inPre) {
preContent(data);
} else if (inTitle) {
titleContent(data);
} else if (inOption) {
data = cleanString(data);
combobox.addItem(data);
} else if (inBlock > 0) {
data = cleanString(data);
if (data.length() >= 1) {
AttributeSet a = charAttr.copyAttributes();
ElementSpec es = new ElementSpec(a, ElementSpec.ContentType,
data.toCharArray(), 0, data.length());
parseBuffer.addElement(es);
}
}
attr.removeAttributes(attr);
}
/**
* cleanEndTag removes any whitespace immediately preceding an
* end tag. It also appends an newline character to the text
* before the end tag so that the insertion caret is positioned
* properly when editing.
*/
protected void cleanEndTag(boolean endParagraphSeen) {
// Fetch the last character data added to the parseBuffer
ElementSpec lastes = (ElementSpec) parseBuffer.lastElement();
if (lastes == null)
return;
char [] lastchars = lastes.getArray();
if (lastchars == null)
return;
String clean = new String (lastchars);
if (clean.length() == 0)
return;
// Eat last whitespace - there's exactly one trailing whitespace
// because the string was trimmed in cleanString & one space was
// appended.
if (isWhiteSpace(clean.charAt(clean.length() - 1))) {
clean = clean.substring(0, clean.length() - 1);
}
// For proper cursor positioning during editing,there must be a
// newline at the end of each paragraph.
if (endParagraphSeen) {
clean = clean + "\n";
}
// Replace the last character data with the modified string
// in the parseBuffer
ElementSpec es = new ElementSpec(lastes.getAttributes(),
ElementSpec.ContentType, clean.toCharArray(),
0, clean.length());
parseBuffer.removeElementAt(parseBuffer.size() - 1);
parseBuffer.addElement(es);
}
/**
* isWhiteSpace returns true if a character is whitespace and
* otherwise returns false.
*/
protected boolean isWhiteSpace(char c) {
if ((c == ' ')
|| (c == 10)
|| (c == 13)
|| (c == '\t')) {
return true;
} else {
return false;
}
}
/**
* cleanString replaces any sequence of blanks, tabs, & newlines
* with a single blank where a newline equals CR LF, CR only,
* or LF only.
* A newline immediately following a start tag is trimmed.
*/
protected String cleanString(String s) {
if (s.length() < 1)
return s;
// Remove all preceding & trailing whitespace & replace with a
// single space. If there is no whitespace to begin with, don't
// add any.
String endSpace = "";
String begSpace = "";
if ((s.length() > 1)
&& isWhiteSpace(s.charAt(s.length()-1)))
endSpace = new String (" ");
if (isWhiteSpace(s.charAt(0)))
begSpace = new String (" ");
String clean = begSpace + s.trim() + endSpace;
// Remove all preceding white space if the pcdata immediately
// follows an open tag.
if (openTagSeen && begSpace.equals(" ")) {
clean = clean.substring(1, clean.length());
}
openTagSeen = false;
// Search the entire string for whitespace & replace any sequence
// of blanks, tabs, & newlines with a single space.
int index = 0;
while (index < clean.length()) {
int endindex = index;
// Eat whitespace
if (isWhiteSpace(clean.charAt(endindex))) {
while ((endindex < clean.length())
&& (isWhiteSpace(clean.charAt(endindex)))) {
endindex++;
}
clean = clean.substring(0, index) + " "
+ clean.substring(endindex, clean.length());
index = endindex;
} else {
index++;
}
}
return clean;
}
public void fontOpenAction() {
openTagSeen = true;
pushCharacterStyle();
Color fg = getColor(attr);
if (fg != null) {
StyleConstants.setForeground(charAttr, fg);
}
String face = (String) attr.getAttribute(FACE);
if (face != null) {
StyleConstants.setFontFamily(charAttr, face);
}
String size = (String) attr.getAttribute(SIZE);
StyleSheet ss = StyleReader.getStyleSheet();
if (size != null) {
StyleConstants.setFontSize(charAttr, ss.getPtSize(size));
}
}
public void fontCloseAction() {
popCharacterStyle();
}
public void htmlOpenAction() {
;
}
public void htmlCloseAction() {
;
}
public void headOpenAction() {
;
}
public void headCloseAction() {
;
}
public void bodyOpenAction() {
setRootElementAttributes(attr);
}
public void bodyCloseAction() {
}
public void whitespaceAction(String data) {
;
addContent(data);
}
public void titleOpenAction() {
;
inTitle = true;
}
public void titleCloseAction() {
;
inTitle = false;
}
public void preOpenAction() {
inPre = true;
blockOpen(PRE, true);
blockOpen(PRELINE, true);
}
public void preCloseAction() {
inPre = false;
blockClose();
blockClose();
}
/**
* Set the title as a property on the doc.
*/
void titleContent(String s) {
putProperty(Document.TitleProperty, s);
}
void preContent(String s) {
int last = 0;
for (int index = s.indexOf('\n'); index >= 0; index = s.indexOf('\n', last)) {
String chunk = s.substring(last, index);
addContent(chunk);
blockClose();
blockOpen(PRELINE, true);
last = index + 1;
}
if (last < s.length()) {
addContent(s.substring(last, s.length()));
}
}
public void ttOpenAction() {
pushCharacterStyle();
attr.addAttribute(TT, "true");
AttributeSet look = getChildStyle(TT);
if (look != null) {
charAttr.addAttributes(look);
charAttr.removeAttribute(StyleConstants.ResolveAttribute);
}
else
StyleConstants.setFontFamily(charAttr, "Monospaced");
charAttr.addAttributes(attr);
}
public void ttCloseAction() {
popCharacterStyle();
}
public void dfnOpenAction() {
pushCharacterStyle();
AttributeSet look = getChildStyle(DFN);
if (look != null) {
charAttr.addAttributes(look);
charAttr.removeAttribute(StyleConstants.ResolveAttribute);
}
else
StyleConstants.setItalic(charAttr, true);
charAttr.addAttributes(attr);
}
public void dfnCloseAction() {
popCharacterStyle();
}
public void citeOpenAction() {
pushCharacterStyle();
AttributeSet look = getChildStyle(CITE);
if (look != null) {
charAttr.addAttributes(look);
charAttr.removeAttribute(StyleConstants.ResolveAttribute);
}
else
StyleConstants.setItalic(charAttr, true);
charAttr.addAttributes(attr);
}
public void citeCloseAction() {
popCharacterStyle();
}
public void bigOpenAction() {
pushCharacterStyle();
AttributeSet look = getChildStyle(BIG);
if (look != null) {
charAttr.addAttributes(look);
charAttr.removeAttribute(StyleConstants.ResolveAttribute);
}
else {
String fontval = StyleXlater.convertFontSizeString("x-large");
StyleSheet ss = StyleReader.getStyleSheet();
int size = ss.getPtSize(fontval);
StyleConstants.setFontSize(charAttr, size);
}
}
public void bigCloseAction() {
popCharacterStyle();
}
public void smallOpenAction() {
pushCharacterStyle();
AttributeSet look = getChildStyle(SMALL);
if (look != null) {
charAttr.addAttributes(look);
charAttr.removeAttribute(StyleConstants.ResolveAttribute);
}
else {
String fontval = StyleXlater.convertFontSizeString("x-small");
StyleSheet ss = StyleReader.getStyleSheet();
int size = ss.getPtSize(fontval);
StyleConstants.setFontSize(charAttr, size);
}
}
public void smallCloseAction() {
popCharacterStyle();
}
public void sampOpenAction() {
pushCharacterStyle();
AttributeSet look = getChildStyle(SAMP);
if (look != null) {
charAttr.addAttributes(look);
charAttr.removeAttribute(StyleConstants.ResolveAttribute);
}
else {
String fontval = StyleXlater.convertFontSizeString("small");
StyleSheet ss = StyleReader.getStyleSheet();
int size = ss.getPtSize(fontval);
StyleConstants.setFontSize(charAttr, size);
StyleConstants.setFontFamily(charAttr, "Monospaced");
}
}
public void sampCloseAction() {
popCharacterStyle();
}
public void codeOpenAction() {
pushCharacterStyle();
AttributeSet look = getChildStyle(CODE);
if (look != null) {
charAttr.addAttributes(look);
charAttr.removeAttribute(StyleConstants.ResolveAttribute);
}
else {
String fontval = StyleXlater.convertFontSizeString("small");
StyleSheet ss = StyleReader.getStyleSheet();
int size = ss.getPtSize(fontval);
StyleConstants.setFontSize(charAttr, size);
StyleConstants.setFontFamily(charAttr, "Monospaced");
}
}
public void codeCloseAction() {
popCharacterStyle();
}
public void strikeOpenAction() {
pushCharacterStyle();
AttributeSet look = getChildStyle(STRIKE);
if (look != null) {
charAttr.addAttributes(look);
charAttr.removeAttribute(StyleConstants.ResolveAttribute);
}
else {
; // Add code here to do strikethrough when implemented in text.
}
}
public void strikeCloseAction() {
popCharacterStyle();
}
public void blockquoteOpenAction() {
blockOpen(BLOCKQUOTE, false);
}
public void blockquoteCloseAction() {
blockClose();
}
public void emOpenAction() {
pushCharacterStyle();
AttributeSet look = getChildStyle(EM);
if (look != null) {
charAttr.addAttributes(look);
charAttr.removeAttribute(StyleConstants.ResolveAttribute);
}
else
StyleConstants.setItalic(charAttr, true);
charAttr.addAttributes(attr);
}
public void emCloseAction() {
popCharacterStyle();
}
public void addressOpenAction() {
pushCharacterStyle();
AttributeSet look = getChildStyle(ADDRESS);
if (look != null) {
charAttr.addAttributes(look);
charAttr.removeAttribute(StyleConstants.ResolveAttribute);
}
else
StyleConstants.setItalic(charAttr, true);
charAttr.addAttributes(attr);
}
public void addressCloseAction() {
popCharacterStyle();
}
public void strongOpenAction() {
pushCharacterStyle();
AttributeSet look = getChildStyle(STRONG);
if (look != null) {
charAttr.addAttributes(look);
charAttr.removeAttribute(StyleConstants.ResolveAttribute);
}
else
StyleConstants.setBold(charAttr, true);
charAttr.addAttributes(attr);
}
public void strongCloseAction() {
popCharacterStyle();
}
public void varOpenAction() {
pushCharacterStyle();
AttributeSet look = getChildStyle(VAR);
if (look != null) {
charAttr.addAttributes(look);
charAttr.removeAttribute(StyleConstants.ResolveAttribute);
}
else {
StyleConstants.setBold(charAttr, true);
StyleConstants.setItalic(charAttr, true);
}
charAttr.addAttributes(attr);
}
public void varCloseAction() {
popCharacterStyle();
}
public void basefontAction() {
/** This is wrong.
It sets all Paragraphs to be that basefont size
even if the basefont tag was in the middle of the doc
If we set the size on the charAttr, then it only
takes effect for those within this character style run.
String size = (String) attr.getAttribute(SIZE);
if (size != null) {
StyleSheet ss = StyleReader.getStyleSheet();
ss.setBaseFontSize(size);
//Style defStyle = getStyle(StyleContext.DEFAULT_STYLE);
Style style = getChildStyle(P);
// This currently only changes text in a P block.
StyleConstants.setFontSize(style, ss.getPtSize(size));
}
*/
//
// Save this attribute on the element for writing.
//
attr.addAttribute(HTMLTagAttribute, BASEFONT);
addSpecialElement(attr);
}
public void brAction() {
/*
blockOpen(BR, false);
AttributeSet a = charAttr.copyAttributes();
ElementSpec es = new ElementSpec(a, ElementSpec.ContentType,
null, 0, 0);
parseBuffer.addElement(es);
blockClose();
*/
;
}
public void aOpenAction() {
pushCharacterStyle();
AttributeSet look = getChildStyle(A);
if (look != null) {
charAttr.addAttributes(look);
charAttr.removeAttribute(StyleConstants.ResolveAttribute);
}
charAttr.addAttributes(attr);
}
private void checkPCData() {
// If no pcdata was found, add an empty content anyway
if (!dataCountStack.empty()) {
DataCounter dc = (DataCounter)dataCountStack.peek();
if (dc.noPCData()) {
AttributeSet a = charAttr.copyAttributes();
String empty = new String("");
ElementSpec es = new ElementSpec(a, ElementSpec.ContentType,
empty.toCharArray(), 0, empty.length());
parseBuffer.addElement(es);
}
}
}
public void aCloseAction() {
checkPCData();
popCharacterStyle();
}
public void hrAction() {
// Get the margins off the body & set them on the hr
/*
Style candidate = (Style)getChildStyle(BODY);
if (candidate != null) {
float margin_left = StyleConstants.getLeftIndent(candidate);
float margin_right = StyleConstants.getRightIndent(candidate);
StyleConstants.setLeftIndent(attr, margin_left);
StyleConstants.setRightIndent(attr, margin_right);
}
*/
setAlignment(attr);
attr.addAttribute(AbstractDocument.ElementNameAttribute, HR);
addSpecialElement(attr);
}
public void imgAction() {
attr.addAttribute(AbstractDocument.ElementNameAttribute, IMG);
attr.addAttributes(charAttr); // so ImageView will know char color
ImageView.addImageDataAttribute(attr); // add side data for ImageView
addSpecialElement(attr);
}
public void iOpenAction() {
pushCharacterStyle();
AttributeSet look = getChildStyle(I);
if (look != null) {
charAttr.addAttributes(look);
charAttr.removeAttribute(StyleConstants.ResolveAttribute);
}
else
StyleConstants.setItalic(charAttr, true);
charAttr.addAttributes(attr);
}
public void iCloseAction() {
popCharacterStyle();
}
public void bOpenAction() {
pushCharacterStyle();
AttributeSet look = getChildStyle(B);
if (look != null) {
charAttr.addAttributes(look);
charAttr.removeAttribute(StyleConstants.ResolveAttribute);
}
else
StyleConstants.setBold(charAttr, true);
charAttr.addAttributes(attr);
}
public void bCloseAction() {
popCharacterStyle();
}
public void uOpenAction() {
pushCharacterStyle();
AttributeSet look = getChildStyle(U);
if (look != null) {
charAttr.addAttributes(look);
charAttr.removeAttribute(StyleConstants.ResolveAttribute);
}
else
StyleConstants.setUnderline(charAttr, true);
}
public void uCloseAction() {
popCharacterStyle();
}
public void kbdOpenAction() {
pushCharacterStyle();
AttributeSet look = getChildStyle(KBD);
if (look != null) {
charAttr.addAttributes(look);
charAttr.removeAttribute(StyleConstants.ResolveAttribute);
}
else {
StyleConstants.setFontFamily(charAttr, "Monospaced");
String fontval = StyleXlater.convertFontSizeString("small");
StyleSheet ss = StyleReader.getStyleSheet();
int size = ss.getPtSize(fontval);
StyleConstants.setFontSize(charAttr, size);
}
charAttr.addAttributes(attr);
}
public void kbdCloseAction() {
popCharacterStyle();
}
public void baseAction() {
String href = (String) attr.getAttribute(HREF);
if (href != null) {
putProperty(BaseHrefProperty, href);
try {
reference = new URL(href);
} catch (MalformedURLException ex) {
}
}
}
public void subOpenAction() {
openTagSeen = true;
pushCharacterStyle();
AttributeSet look = getChildStyle(SUB);
if (look != null) {
charAttr.addAttributes(look);
charAttr.removeAttribute(StyleConstants.ResolveAttribute);
}
//else
// set subscripting
//StyleConstants.set*
charAttr.addAttributes(attr);
}
public void subCloseAction() {
cleanEndTag(false);
popCharacterStyle();
}
public void supOpenAction() {
openTagSeen = true;
attr.addAttribute(SUP, "true");
pushCharacterStyle();
AttributeSet look = getChildStyle(SUP);
if (look != null) {
charAttr.addAttributes(look);
charAttr.removeAttribute(StyleConstants.ResolveAttribute);
}
//else
// set superscripting
//StyleConstants.set*(charAttr, true);
charAttr.addAttributes(attr);
}
public void supCloseAction() {
cleanEndTag(false);
popCharacterStyle();
}
// --- list actions ---------------------------
public void liOpenAction() {
blockOpen(LI, true);
}
public void liCloseAction() {
blockClose();
}
public void ulOpenAction() {
blockOpen(UL, true);
}
public void ulCloseAction() {
blockClose();
}
public void olOpenAction() {
blockOpen(OL, true);
}
public void olCloseAction() {
blockClose();
}
public void dlOpenAction() {
blockOpen(DL, true);
}
public void dlCloseAction() {
blockClose();
}
public void ddOpenAction() {
blockOpen(DD, true);
}
public void ddCloseAction() {
blockClose();
}
public void dtOpenAction() {
blockOpen(DT, true);
}
public void dtCloseAction() {
blockClose();
}
public void dirOpenAction() {
blockOpen(DIR, true);
}
public void dirCloseAction() {
blockClose();
}
public void menuOpenAction() {
blockOpen(MENU, true);
}
public void menuCloseAction() {
blockClose();
}
// --- form actions ---------------------------
public void formOpenAction(){
// blockOpen(FORM, true);
}
public void formCloseAction(){
// blockClose();
}
public void inputAction(){
String type = (String) attr.getAttribute(TYPE);
if (type == null)
type = new String("text");
if (type.equalsIgnoreCase("hidden")) {
addSpecialElement(attr);
return;
}
Component c;
if (type.equalsIgnoreCase("submit")
|| type.equalsIgnoreCase("reset")) {
String value = (String) attr.getAttribute(VALUE);
c = (Component) new JButton(value);
} else if (type.equalsIgnoreCase("image")) {
String src = (String) attr.getAttribute(SRC);
c = (Component) new JButton(src);
} else if (type.equalsIgnoreCase("checkbox")) {
c = (Component) new JCheckBox();
} else if (type.equalsIgnoreCase("radio")) {
String value = (String) attr.getAttribute(VALUE);
c = (Component) new JRadioButton(value);
} else if (type.equalsIgnoreCase("text")
|| type.equalsIgnoreCase("password")) {
int size;
String sizestr = (String) attr.getAttribute(SIZE);
if (sizestr != null) {
try {
size = Integer.valueOf(sizestr).intValue();
} catch (NumberFormatException e) {
size = 40;
}
} else {
size = 40;
}
String value = (String) attr.getAttribute(VALUE);
c = (Component) new JTextField(value, size);
} else {
c = (Component) new JButton();
}
attr.addAttribute(HTMLInputComponent, HTMLInputComponent);
StyleConstants.setComponent(attr, c);
addSpecialElement(attr);
}
public void selectOpenAction(){
Component c;
int rows;
String rowsstr = (String) attr.getAttribute(ROWS);
if (rowsstr != null) {
try {
rows = Integer.valueOf(rowsstr).intValue();
} catch (NumberFormatException e) {
rows = 10;
}
} else {
rows = 10;
}
int cols;
String colsstr = (String) attr.getAttribute(COLS);
if (colsstr != null) {
try {
cols = Integer.valueOf(colsstr).intValue();
} catch (NumberFormatException e) {
cols = 40;
}
} else {
cols = 40;
}
String value = (String) attr.getAttribute(VALUE);
combobox = new JComboBox();
combobox.setEditable(false);
c = (Component) combobox;
attr.addAttribute(HTMLInputComponent, HTMLInputComponent);
StyleConstants.setComponent(attr, c);
addSpecialElement(attr);
}
public void selectCloseAction(){
}
public void optionOpenAction(){
inOption = true;
}
public void optionCloseAction(){
inOption = false;
}
public void textareaOpenAction(){
Component c;
int rows;
String rowsstr = (String) attr.getAttribute(ROWS);
if (rowsstr != null) {
try {
rows = Integer.valueOf(rowsstr).intValue();
} catch (NumberFormatException e) {
rows = 10;
}
} else {
rows = 10;
}
int cols;
String colsstr = (String) attr.getAttribute(COLS);
if (colsstr != null) {
try {
cols = Integer.valueOf(colsstr).intValue();
} catch (NumberFormatException e) {
cols = 40;
}
} else {
cols = 40;
}
String value = (String) attr.getAttribute(VALUE);
JTextArea ta = new JTextArea(value, rows, cols);
ta.setEditable(true);
JScrollPane scroller = new JScrollPane(
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
scroller.getViewport().add(ta);
c = (Component) scroller;
attr.addAttribute(HTMLInputComponent, HTMLInputComponent);
StyleConstants.setComponent(attr, c);
addSpecialElement(attr);
}
public void textareaCloseAction(){
}
// --- table actions -------------------
/*
public void tableOpenAction() {
blockOpen(TABLE, true);
}
public void tableCloseAction() {
blockClose();
}
public void trOpenAction() {
blockOpen(TR, true);
}
public void trCloseAction() {
blockClose();
}
public void thOpenAction() {
blockOpen(TH, true);
}
public void thCloseAction() {
blockClose();
}
public void tdOpenAction() {
blockOpen(TD, true);
}
public void tdCloseAction() {
blockClose();
}
public void captionOpenAction() {
blockOpen(CAPTION, true);
}
public void captionCloseAction() {
blockClose();
}
*/
// --- utility methods used by the reader ------------------
/**
* Try to turn an html color spec into a Color object.
*/
Color getColor(AttributeSet a) {
String name = (String) attr.getAttribute(COLOR);
if (name != null) {
try {
Color c = HTMLUtils.stringToColor(name);
return c;
}
catch (HTMLException e) {
return null;
}
}
return null;
}
/**
* Push the current character style on a stack in preparation
* for forming a new nested character style.
*/
void pushCharacterStyle() {
charAttrStack.push(charAttr.copyAttributes());
}
/**
* Pop a previously pushed character style off the stack
* to return to a previous style.
*/
void popCharacterStyle() {
charAttr = (MutableAttributeSet) charAttrStack.peek();
charAttrStack.pop();
}
/**
* Push the current logical style on the style stack and
* set the current logical style to new named style (as
* it resolves from the old style.
*/
void pushStyle(String name) {
styleStack.push(resolver);
// FIXME - should create a local def if it doesn't
// exist, so that styles can later be dynamically
// updated and the element will be pointing to the
// correct style if one is added!!
String str = "SH" + name;
Style candidate = (Style) resolver.getAttribute(str);
if ((candidate == null) && name.equalsIgnoreCase(HTMLDefs.IMPLIEDP)) {
str = new String("SHp");
candidate = (Style) resolver.getAttribute(str);
}
if (candidate != null) {
resolver = candidate;
}
}
/**
* Restores a previously pushed style back as the current
* style.
*/
void popStyle() {
resolver = (Style) styleStack.peek();
styleStack.pop();
}
/**
* Add a specification to create a new branch element,
* optionally with the given tag name.
*/
void blockOpen(String tag, boolean setName) {
// Increment the parent data count to include this block
incrementPCData();
// Keep track of the pcdata's seen in each nested block
dataCountStack.push(new DataCounter());
openTagSeen = true;
inBlock++;
pushStyle(tag);
//Style s = getStyle(tag);
if (resolver != null) {
// resolve to the tag-named style if it exists
Style tmpResolver
= (Style) resolver.getAttribute(StyleReader.CHILD_STYLE);
if (tmpResolver != null) {
attr.addAttribute(StyleConstants.ResolveAttribute, tmpResolver);
}
}
if (setName) {
attr.addAttribute(AbstractDocument.ElementNameAttribute, tag);
}
if (tag.equalsIgnoreCase(HTMLDefs.IMPLIEDP)) {
attr.addAttribute(HTMLDefs.IMPLIEDP, HTMLDefs.IMPLIEDP);
}
ElementSpec es = new ElementSpec(
attr.copyAttributes(), ElementSpec.StartTagType);
parseBuffer.addElement(es);
attr.removeAttributes(attr);
}
/**
* Close out an element.
*/
void blockClose() {
// Keep track of the pcdata's seen in each nested block
checkPCData();
dataCountStack.pop();
cleanEndTag(true);
inBlock --;
popStyle();
// an open/close with no content will be removed, so we
// add a space of content to keep the element being formed.
ElementSpec prev = (ElementSpec) parseBuffer.lastElement();
if (prev != null && prev.getType() == ElementSpec.StartTagType) {
addContent(" ");
}
ElementSpec es = new ElementSpec(
null, ElementSpec.EndTagType);
parseBuffer.addElement(es);
}
/**
* Add some text with the current character attributes
*/
void addContent(String data) {
AttributeSet a = charAttr.copyAttributes();
ElementSpec es = new ElementSpec(
a, ElementSpec.ContentType, data.toCharArray(), 0, data.length());
parseBuffer.addElement(es);
}
/**
* Add content that is basically specified entirely
* in the attribute set.
*/
void addSpecialElement(AttributeSet a) {
char[] one = new char[1];
one[0] = ' ';
a = a.copyAttributes();
ElementSpec es = new ElementSpec(
a.copyAttributes(), ElementSpec.ContentType, one, 0, 1);
parseBuffer.addElement(es);
attr.removeAttributes(attr);
}
/**
* Replace the substring in str indicated by the start and end
* indices with the character.
*/
private String replaceSpecialChar(String str, int startindex,
int endindex, char ch) {
String newstr = null;
newstr = str.substring(0, startindex) + ch
+ str.substring(endindex+1, str.length());
return(newstr);
}
/**
* Translate embedded character entities into their respective
* characters.
*/
private String xlateSpecialChars(String str) {
String result = null;
int index = 0;
// Look for the '&' character which designates special html chars.
index = str.indexOf('&');
while ((index < str.length()) && (index > 0)) {
// The special character description ends with ';' so find the
// beginning and ending indexes of the special character.
int jindex = 0;
jindex = str.indexOf(';', index);
if (jindex < 0) {
return(null);
}
// If a '#' character follows '&' then the special character is
// being represented by an ascii numeric code. Replace the
// code with the special character itself and return the string.
if (str.charAt(index+1) == '#') {
String sstr = str.substring(index+2, jindex);
int num = Integer.valueOf(sstr).intValue();
result = replaceSpecialChar(str, index, jindex, (char)num);
}
// Otherwise, look up the character name (e.g. ") in the
// SpecialCharTable. Replace the code with the special
// character itself and return the string.
else {
String sstr = str.substring(index+1, jindex);
char lookup = ' ';
boolean found = false;
try {
lookup = specTable.getSymbol(sstr);
found = true;
} catch (HTMLException e) {
;
}
if (found) {
result = replaceSpecialChar(str, index, jindex, lookup);
}
}
index = str.indexOf('&', index + 1);
}
return(result);
}
boolean openTagSeen = false;
boolean inPre = false;
boolean inTitle = false;
boolean inOption = false;
Stack dataCountStack = new Stack();
JComboBox combobox = null;
Vector parseBuffer = new Vector(); // Vector<ElementSpec>
MutableAttributeSet charAttr = new SimpleAttributeSet();
Stack charAttrStack = new Stack();
Style resolver;
Stack styleStack = new Stack();
MutableAttributeSet attr = new SimpleAttributeSet();
int inBlock = 0;
html32 parser;
SpecialCharTable specTable = new SpecialCharTable();
class DataCounter {
int dc = 0;
public DataCounter() {
;
}
public void incCounter() {
dc++;
}
public void decCounter() {
dc--;
}
public boolean noPCData() {
if (dc > 0)
return false;
else
return true;
}
}
}
}