From 554fd8c5195424bdbcabf5de30fdc183aba391bd Mon Sep 17 00:00:00 2001 From: upstream source tree Date: Sun, 15 Mar 2015 20:14:05 -0400 Subject: obtained gcc-4.6.4.tar.bz2 from upstream website; verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository. --- .../javax/swing/text/html/HTMLEditorKit.java | 1520 ++++++++++++++++++++ 1 file changed, 1520 insertions(+) create mode 100644 libjava/classpath/javax/swing/text/html/HTMLEditorKit.java (limited to 'libjava/classpath/javax/swing/text/html/HTMLEditorKit.java') diff --git a/libjava/classpath/javax/swing/text/html/HTMLEditorKit.java b/libjava/classpath/javax/swing/text/html/HTMLEditorKit.java new file mode 100644 index 000000000..e3505d3c2 --- /dev/null +++ b/libjava/classpath/javax/swing/text/html/HTMLEditorKit.java @@ -0,0 +1,1520 @@ +/* HTMLEditorKit.java -- + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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 2, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.text.html; + + +import java.awt.event.ActionEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionListener; +import java.awt.Cursor; +import java.awt.Point; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.Serializable; +import java.io.StringReader; +import java.io.Writer; +import java.net.MalformedURLException; +import java.net.URL; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; + +import javax.swing.Action; +import javax.swing.JEditorPane; +import javax.swing.SwingUtilities; +import javax.swing.event.HyperlinkEvent; +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.text.EditorKit; +import javax.swing.text.Element; +import javax.swing.text.MutableAttributeSet; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyledDocument; +import javax.swing.text.StyledEditorKit; +import javax.swing.text.TextAction; +import javax.swing.text.View; +import javax.swing.text.ViewFactory; +import javax.swing.text.html.parser.ParserDelegator; + +/* Move these imports here after javax.swing.text.html to make it compile + with jikes. */ +import gnu.javax.swing.text.html.parser.GnuParserDelegator; +import gnu.javax.swing.text.html.parser.HTML_401F; + +/** + * @author Lillian Angel (langel at redhat dot com) + */ +public class HTMLEditorKit + extends StyledEditorKit + implements Serializable, Cloneable, Accessible +{ + + /** + * Fires the hyperlink events on the associated component + * when needed. + */ + public static class LinkController + extends MouseAdapter + implements MouseMotionListener, Serializable + { + + /** + * The element of the last anchor tag. + */ + private Element lastAnchorElement; + + /** + * Constructor + */ + public LinkController() + { + super(); + } + + /** + * Dispatched when the mouse is clicked. If the component + * is read-only, then the clicked event is used to drive an + * attempt to follow the reference specified by a link + * + * @param e - the mouse event + */ + public void mouseClicked(MouseEvent e) + { + JEditorPane editor = (JEditorPane) e.getSource(); + if (! editor.isEditable() && SwingUtilities.isLeftMouseButton(e)) + { + Point loc = e.getPoint(); + int pos = editor.viewToModel(loc); + if (pos >= 0) + activateLink(pos, editor, e.getX(), e.getY()); + } + } + + /** + * Dispatched when the mouse is dragged on a component. + * + * @param e - the mouse event. + */ + public void mouseDragged(MouseEvent e) + { + // Nothing to do here. + } + + /** + * Dispatched when the mouse cursor has moved into the component. + * + * @param e - the mouse event. + */ + public void mouseMoved(MouseEvent e) + { + JEditorPane editor = (JEditorPane) e.getSource(); + HTMLEditorKit kit = (HTMLEditorKit) editor.getEditorKit(); + if (! editor.isEditable()) + { + Document doc = editor.getDocument(); + if (doc instanceof HTMLDocument) + { + Cursor newCursor = kit.getDefaultCursor(); + HTMLDocument htmlDoc = (HTMLDocument) doc; + Point loc = e.getPoint(); + int pos = editor.viewToModel(loc); + Element el = htmlDoc.getCharacterElement(pos); + if (pos < el.getStartOffset() || pos >= el.getEndOffset()) + el = null; + if (el != null) + { + AttributeSet aAtts = (AttributeSet) + el.getAttributes().getAttribute(HTML.Tag.A); + if (aAtts != null) + { + if (el != lastAnchorElement) + { + if (lastAnchorElement != null) + htmlDoc.updateSpecialClass(lastAnchorElement, + HTML.Attribute.DYNAMIC_CLASS, + null); + lastAnchorElement = el; + htmlDoc.updateSpecialClass(el, + HTML.Attribute.DYNAMIC_CLASS, + "hover"); + } + newCursor = kit.getLinkCursor(); + } + else + { + if (lastAnchorElement != null) + htmlDoc.updateSpecialClass(lastAnchorElement, + HTML.Attribute.DYNAMIC_CLASS, + null); + lastAnchorElement = null; + } + } + else + { + if (lastAnchorElement != null) + htmlDoc.updateSpecialClass(lastAnchorElement, + HTML.Attribute.DYNAMIC_CLASS, + null); + lastAnchorElement = null; + } + if (editor.getCursor() != newCursor) + { + editor.setCursor(newCursor); + } + } + } + } + + /** + * If the given position represents a link, then linkActivated is called + * on the JEditorPane. + * + * @param pos the position + * @param editor the editor pane + */ + protected void activateLink(int pos, JEditorPane editor) + { + activateLink(pos, editor); + } + + private void activateLink(int pos, JEditorPane editor, int x, int y) + { + // TODO: This is here for future extension for mapped links support. + // For the time beeing we implement simple hyperlinks. + Document doc = editor.getDocument(); + if (doc instanceof HTMLDocument) + { + HTMLDocument htmlDoc = (HTMLDocument) doc; + Element el = htmlDoc.getCharacterElement(pos); + AttributeSet atts = el.getAttributes(); + AttributeSet anchorAtts = + (AttributeSet) atts.getAttribute(HTML.Tag.A); + String href = null; + if (anchorAtts != null) + { + href = (String) anchorAtts.getAttribute(HTML.Attribute.HREF); + htmlDoc.updateSpecialClass(el, HTML.Attribute.PSEUDO_CLASS, + "visited"); + } + else + { + // TODO: Implement link maps here. + } + HyperlinkEvent event = null; + if (href != null) + event = createHyperlinkEvent(editor, htmlDoc, href, + anchorAtts, el); + if (event != null) + editor.fireHyperlinkUpdate(event); + } + + } + + /** + * Creates a HyperlinkEvent for the specified href and anchor if + * possible. If for some reason this won't work, return null. + * + * @param editor the editor + * @param doc the document + * @param href the href link + * @param anchor the anchor + * @param el the element + * + * @return the hyperlink event, or null if we couldn't + * create one + */ + private HyperlinkEvent createHyperlinkEvent(JEditorPane editor, + HTMLDocument doc, + String href, + AttributeSet anchor, + Element el) + { + URL url; + try + { + URL base = doc.getBase(); + url = new URL(base, href); + + } + catch (MalformedURLException ex) + { + url = null; + } + HyperlinkEvent ev; + if (doc.isFrameDocument()) + { + String target = null; + if (anchor != null) + target = (String) anchor.getAttribute(HTML.Attribute.TARGET); + if (target == null || target.equals("")) + target = doc.getBaseTarget(); + if (target == null || target.equals("")) + target = "_self"; + ev = new HTMLFrameHyperlinkEvent(editor, + HyperlinkEvent.EventType.ACTIVATED, + url, href, el, target); + } + else + { + ev = new HyperlinkEvent(editor, HyperlinkEvent.EventType.ACTIVATED, + url, href, el); + } + return ev; + } + } + + /** + * This class is used to insert a string of HTML into an existing + * document. At least 2 HTML.Tags need to be supplied. The first Tag (parentTag) + * identifies the parent in the document to add the elements to. The second, (addTag), + * identifies that the first tag should be added to the document as seen in the string. + * The parser will generate all appropriate (opening/closing tags_ even if they are not + * in the HTML string passed in. + */ + public static class InsertHTMLTextAction + extends HTMLTextAction + { + + /** + * Tag in HTML to start adding tags from. + */ + protected HTML.Tag addTag; + + /** + * Alternate tag in HTML to start adding tags from if parentTag is + * not found and alternateParentTag is not found. + */ + protected HTML.Tag alternateAddTag; + + /** + * Alternate tag to check if parentTag is not found. + */ + protected HTML.Tag alternateParentTag; + + /** + * HTML to insert. + */ + protected String html; + + /** + * Tag to check for in the document. + */ + protected HTML.Tag parentTag; + + /** + * Initializes all fields. + * + * @param name - the name of the document. + * @param html - the html to insert + * @param parentTag - the parent tag to check for + * @param addTag - the tag to start adding from + */ + public InsertHTMLTextAction(String name, String html, + HTML.Tag parentTag, HTML.Tag addTag) + { + this(name, html, parentTag, addTag, null, null); + } + + /** + * Initializes all fields and calls super + * + * @param name - the name of the document. + * @param html - the html to insert + * @param parentTag - the parent tag to check for + * @param addTag - the tag to start adding from + * @param alternateParentTag - the alternate parent tag + * @param alternateAddTag - the alternate add tag + */ + public InsertHTMLTextAction(String name, String html, HTML.Tag parentTag, + HTML.Tag addTag, HTML.Tag alternateParentTag, + HTML.Tag alternateAddTag) + { + super(name); + // Fields are for easy access when the action is applied to an actual + // document. + this.html = html; + this.parentTag = parentTag; + this.addTag = addTag; + this.alternateParentTag = alternateParentTag; + this.alternateAddTag = alternateAddTag; + } + + /** + * HTMLEditorKit.insertHTML is called. If an exception is + * thrown, it is wrapped in a RuntimeException and thrown. + * + * @param editor - the editor to use to get the editorkit + * @param doc - + * the Document to insert the HTML into. + * @param offset - + * where to begin inserting the HTML. + * @param html - + * the String to insert + * @param popDepth - + * the number of ElementSpec.EndTagTypes to generate before + * inserting + * @param pushDepth - + * the number of ElementSpec.StartTagTypes with a direction of + * ElementSpec.JoinNextDirection that should be generated before + * @param addTag - + * the first tag to start inserting into document + */ + protected void insertHTML(JEditorPane editor, HTMLDocument doc, int offset, + String html, int popDepth, int pushDepth, + HTML.Tag addTag) + { + try + { + super.getHTMLEditorKit(editor).insertHTML(doc, offset, html, + popDepth, pushDepth, addTag); + } + catch (IOException e) + { + throw (RuntimeException) new RuntimeException("Parser is null.").initCause(e); + } + catch (BadLocationException ex) + { + throw (RuntimeException) new RuntimeException("BadLocationException: " + + offset).initCause(ex); + } + } + + /** + * Invoked when inserting at a boundary. Determines the number of pops, + * and then the number of pushes that need to be performed. The it calls + * insertHTML. + * + * @param editor - + * the editor to use to get the editorkit + * @param doc - + * the Document to insert the HTML into. + * @param offset - + * where to begin inserting the HTML. + * @param insertElement - + * the element to insert + * @param html - + * the html to insert + * @param parentTag - + * the parent tag + * @param addTag - + * the first tag + */ + protected void insertAtBoundary(JEditorPane editor, + HTMLDocument doc, int offset, + Element insertElement, + String html, HTML.Tag parentTag, + HTML.Tag addTag) + { + insertAtBoundry(editor, doc, offset, insertElement, + html, parentTag, addTag); + } + + /** + * Invoked when inserting at a boundary. Determines the number of pops, + * and then the number of pushes that need to be performed. The it calls + * insertHTML. + * + * @param editor - the editor to use to get the editorkit + * @param doc - + * the Document to insert the HTML into. + * @param offset - + * where to begin inserting the HTML. + * @param insertElement - the element to insert + * @param html - the html to insert + * @param parentTag - the parent tag + * @param addTag - the first tag + * + * @deprecated as of v1.3, use insertAtBoundary + */ + protected void insertAtBoundry(JEditorPane editor, + HTMLDocument doc, + int offset, Element insertElement, + String html, HTML.Tag parentTag, + HTML.Tag addTag) + { + Element parent = insertElement; + Element el; + // Find common parent element. + if (offset > 0 || insertElement == null) + { + el = doc.getDefaultRootElement(); + while (el != null && el.getStartOffset() != offset + && ! el.isLeaf()) + el = el.getElement(el.getElementIndex(offset)); + parent = el != null ? el.getParentElement() : null; + } + if (parent != null) + { + int pops = 0; + int pushes = 0; + if (offset == 0 && insertElement != null) + { + el = parent; + while (el != null && ! el.isLeaf()) + { + el = el.getElement(el.getElementIndex(offset)); + pops++; + } + } + else + { + el = parent; + offset--; + while (el != null && ! el.isLeaf()) + { + el = el.getElement(el.getElementIndex(offset)); + pops++; + } + el = parent; + offset++; + while (el != null && el != insertElement) + { + el = el.getElement(el.getElementIndex(offset)); + pushes++; + } + } + pops = Math.max(0, pops - 1); + insertHTML(editor, doc, offset, html, pops, pushes, addTag); + } + } + + /** + * Inserts the HTML. + * + * @param ae - the action performed + */ + public void actionPerformed(ActionEvent ae) + { + JEditorPane source = getEditor(ae); + if (source != null) + { + HTMLDocument d = getHTMLDocument(source); + int offset = source.getSelectionStart(); + int length = d.getLength(); + boolean inserted = true; + if (! tryInsert(source, d, offset, parentTag, addTag)) + { + inserted = tryInsert(source, d, offset, alternateParentTag, + alternateAddTag); + } + if (inserted) + adjustSelection(source, d, offset, length); + } + } + + /** + * Tries to insert the html chunk to the specified addTag. + * + * @param pane the editor + * @param doc the document + * @param offset the offset at which to insert + * @param tag the tag at which to insert + * @param addTag the add tag + * + * @return true when the html has been inserted successfully, + * false otherwise + */ + private boolean tryInsert(JEditorPane pane, HTMLDocument doc, int offset, + HTML.Tag tag, HTML.Tag addTag) + { + boolean inserted = false; + Element el = findElementMatchingTag(doc, offset, tag); + if (el != null && el.getStartOffset() == offset) + { + insertAtBoundary(pane, doc, offset, el, html, tag, addTag); + inserted = true; + } + else if (offset > 0) + { + int depth = elementCountToTag(doc, offset - 1, tag); + if (depth != -1) + { + insertHTML(pane, doc, offset, html, depth, 0, addTag); + inserted = true; + } + } + return inserted; + } + + /** + * Adjusts the selection after an insertion has been performed. + * + * @param pane the editor pane + * @param doc the document + * @param offset the insert offset + * @param oldLen the old document length + */ + private void adjustSelection(JEditorPane pane, HTMLDocument doc, + int offset, int oldLen) + { + int newLen = doc.getLength(); + if (newLen != oldLen && offset < newLen) + { + if (offset > 0) + { + String text; + try + { + text = doc.getText(offset - 1, 1); + } + catch (BadLocationException ex) + { + text = null; + } + if (text != null && text.length() > 0 + && text.charAt(0) == '\n') + { + pane.select(offset, offset); + } + else + { + pane.select(offset + 1, offset + 1); + } + } + else + { + pane.select(1, 1); + } + } + } + } + + /** + * Abstract Action class that helps inserting HTML into an existing document. + */ + public abstract static class HTMLTextAction + extends StyledEditorKit.StyledTextAction + { + + /** + * Constructor + */ + public HTMLTextAction(String name) + { + super(name); + } + + /** + * Gets the HTMLDocument from the JEditorPane. + * + * @param e - the editor pane + * @return the html document. + */ + protected HTMLDocument getHTMLDocument(JEditorPane e) + { + Document d = e.getDocument(); + if (d instanceof HTMLDocument) + return (HTMLDocument) d; + throw new IllegalArgumentException("Document is not a HTMLDocument."); + } + + /** + * Gets the HTMLEditorKit + * + * @param e - the JEditorPane to get the HTMLEditorKit from. + * @return the HTMLEditorKit + */ + protected HTMLEditorKit getHTMLEditorKit(JEditorPane e) + { + EditorKit d = e.getEditorKit(); + if (d instanceof HTMLEditorKit) + return (HTMLEditorKit) d; + throw new IllegalArgumentException("EditorKit is not a HTMLEditorKit."); + } + + /** + * Returns an array of Elements that contain the offset. + * The first elements corresponds to the roots of the doc. + * + * @param doc - the document to get the Elements from. + * @param offset - the offset the Elements must contain + * @return an array of all the elements containing the offset. + */ + protected Element[] getElementsAt(HTMLDocument doc, + int offset) + { + return getElementsAt(doc.getDefaultRootElement(), offset, 0); + } + + /** + * Helper function to get all elements using recursion. + */ + private Element[] getElementsAt(Element root, int offset, int depth) + { + Element[] elements = null; + if (root != null) + { + if (root.isLeaf()) + { + elements = new Element[depth + 1]; + elements[depth] = root; + return elements; + } + elements = getElementsAt(root.getElement(root.getElementIndex(offset)), + offset, depth + 1); + elements[depth] = root; + } + return elements; + } + + /** + * Returns the number of elements, starting at the deepest point, needed + * to get an element representing tag. -1 if no elements are found, 0 if + * the parent of the leaf at offset represents the tag. + * + * @param doc - + * the document to search + * @param offset - + * the offset to check + * @param tag - + * the tag to look for + * @return - the number of elements needed to get an element representing + * tag. + */ + protected int elementCountToTag(HTMLDocument doc, + int offset, HTML.Tag tag) + { + Element root = doc.getDefaultRootElement(); + int num = -1; + Element next = root.getElement(root.getElementIndex(offset)); + + while (!next.isLeaf()) + { + num++; + if (next.getAttributes(). + getAttribute(StyleConstants.NameAttribute).equals(tag)) + return num; + next = next.getElement(next.getElementIndex(offset)); + } + return num; + } + + /** + * Gets the deepest element at offset with the + * matching tag. + * + * @param doc - the document to search + * @param offset - the offset to check for + * @param tag - the tag to match + * @return - the element that is found, null if not found. + */ + protected Element findElementMatchingTag(HTMLDocument doc, + int offset, HTML.Tag tag) + { + Element element = doc.getDefaultRootElement(); + Element tagElement = null; + + while (element != null) + { + Object otag = element.getAttributes().getAttribute( + StyleConstants.NameAttribute); + if (otag instanceof HTML.Tag && otag.equals(tag)) + tagElement = element; + element = element.getElement(element.getElementIndex(offset)); + } + + return tagElement; + } + } + + /** + * A {@link ViewFactory} that is able to create {@link View}s for + * the Elements that are supported. + */ + public static class HTMLFactory + implements ViewFactory + { + + /** + * Constructor + */ + public HTMLFactory() + { + // Do Nothing here. + } + + /** + * Creates a {@link View} for the specified Element. + * + * @param element the Element to create a View + * for + * @return the View for the specified Element + * or null if the type of element is + * not supported + */ + public View create(Element element) + { + View view = null; + Object attr = + element.getAttributes().getAttribute(StyleConstants.NameAttribute); + if (attr instanceof HTML.Tag) + { + HTML.Tag tag = (HTML.Tag) attr; + + if (tag == HTML.Tag.IMPLIED || tag == HTML.Tag.P + || tag == HTML.Tag.H1 || tag == HTML.Tag.H2 + || tag == HTML.Tag.H3 || tag == HTML.Tag.H4 + || tag == HTML.Tag.H5 || tag == HTML.Tag.H6 + || tag == HTML.Tag.DT) + view = new ParagraphView(element); + else if (tag == HTML.Tag.LI || tag == HTML.Tag.DL + || tag == HTML.Tag.DD || tag == HTML.Tag.BODY + || tag == HTML.Tag.HTML || tag == HTML.Tag.CENTER + || tag == HTML.Tag.DIV + || tag == HTML.Tag.BLOCKQUOTE + || tag == HTML.Tag.PRE + || tag == HTML.Tag.FORM + // Misplaced TD and TH tags get mapped as vertical block. + // Note that correctly placed tags get mapped in TableView. + || tag == HTML.Tag.TD || tag == HTML.Tag.TH) + view = new BlockView(element, View.Y_AXIS); + else if (tag == HTML.Tag.TR) + // Misplaced TR tags get mapped as horizontal blocks. + // Note that correctly placed tags get mapped in TableView. + view = new BlockView(element, View.X_AXIS); + else if (tag == HTML.Tag.IMG) + view = new ImageView(element); + + else if (tag == HTML.Tag.CONTENT) + view = new InlineView(element); + else if (tag == HTML.Tag.HEAD) + view = new NullView(element); + else if (tag == HTML.Tag.TABLE) + view = new javax.swing.text.html.TableView(element); + else if (tag == HTML.Tag.HR) + view = new HRuleView(element); + else if (tag == HTML.Tag.BR) + view = new BRView(element); + else if (tag == HTML.Tag.INPUT || tag == HTML.Tag.SELECT + || tag == HTML.Tag.TEXTAREA) + view = new FormView(element); + + else if (tag == HTML.Tag.MENU || tag == HTML.Tag.DIR + || tag == HTML.Tag.UL || tag == HTML.Tag.OL) + view = new ListView(element); + else if (tag == HTML.Tag.FRAMESET) + view = new FrameSetView(element); + else if (tag == HTML.Tag.FRAME) + view = new FrameView(element); + else if (tag == HTML.Tag.OBJECT) + view = new ObjectView(element); + } + if (view == null) + { + view = new NullView(element); + } + return view; + } + } + + /** + * The abstract HTML parser declaration. + */ + public abstract static class Parser + { + /** + * Parse the HTML text, calling various methods of the provided callback + * in response to the occurence of the corresponding HTML constructions. + * @param reader The reader to read the source HTML from. + * @param callback The callback to receive information about the parsed + * HTML structures + * @param ignoreCharSet If true, the parser ignores all charset information + * that may be present in HTML documents. + * @throws IOException, normally if the reader throws one. + */ + public abstract void parse(Reader reader, ParserCallback callback, + boolean ignoreCharSet) throws IOException; + } + + /** + * The "hook" that receives all information about the HTML document + * structure while parsing it. The methods are invoked by parser + * and should be normally overridden. + */ + public static class ParserCallback + { + /** + * If the tag does not occurs in the html stream directly, but + * is supposed by parser, the tag attribute set contains this additional + * attribute, having value Boolean.True. + */ + public static final Object IMPLIED = "_implied_"; + + /** + * Constructor + */ + public ParserCallback() + { + // Nothing to do here. + } + + /** + * The parser calls this method after it finishes parsing the document. + */ + public void flush() throws BadLocationException + { + // Nothing to do here. + } + + /** + * Handle HTML comment, present in the given position. + * @param comment the comment + * @position the position of the comment in the text being parsed. + */ + public void handleComment(char[] comment, int position) + { + // Nothing to do here. + } + + /** + * Notifies about the character sequences, used to separate lines in + * this document. The parser calls this method after it finishes + * parsing the document, but before flush(). + * @param end_of_line The "end of line sequence", one of: \r or \n or \r\n. + */ + public void handleEndOfLineString(String end_of_line) + { + // Nothing to do here. + } + + /** + * The method is called when the HTML closing tag ((like </table>) + * is found or if the parser concludes that the one should be present + * in the current position. + * @param tag The tag being handled + * @param position the tag position in the text being parsed. + */ + public void handleEndTag(HTML.Tag tag, int position) + { + // Nothing to do here. + } + + /** + * Handle the error. + * @param message The message, explaining the error. + * @param position The starting position of the fragment that has caused + * the error in the html document being parsed. + */ + public void handleError(String message, int position) + { + // Nothing to do here. + } + + /** + * Handle the tag with no content, like <br>. The method is + * called for the elements that, in accordance with the current DTD, + * has an empty content. + * @param tag The tag being handled. + * @param position The tag position in the text being parsed. + */ + public void handleSimpleTag(HTML.Tag tag, MutableAttributeSet attributes, + int position) + { + // Nothing to do here. + } + + /** + * The method is called when the HTML opening tag ((like <table>) + * is found or if the parser concludes that the one should be present + * in the current position. + * @param tag The tag being handled + * @param position The tag position in the text being parsed + */ + public void handleStartTag(HTML.Tag tag, MutableAttributeSet attributes, + int position) + { + // Nothing to do here. + } + + /** + * Handle the text section. + * @param text A section text. + * @param position The text position in the HTML document text being parsed. + */ + public void handleText(char[] text, int position) + { + // Nothing to do here. + } + } + + /** + * Use serialVersionUID (v1.4) for interoperability. + */ + private static final long serialVersionUID = 8751997116710384592L; + + /** + * Default cascading stylesheed file ("default.css"). + */ + public static final String DEFAULT_CSS = "default.css"; + + /** + * The bold action identifier. + */ + public static final String BOLD_ACTION = "html-bold-action"; + + /** + * The italic action identifier. + */ + public static final String ITALIC_ACTION = "html-italic-action"; + + /** + * The color action indentifier + * (passing the color as an argument). + */ + public static final String COLOR_ACTION = "html-color-action"; + + /** + * The increase font action identifier. + */ + public static final String FONT_CHANGE_BIGGER = "html-font-bigger"; + + /** + * The decrease font action identifier. + */ + public static final String FONT_CHANGE_SMALLER = "html-font-smaller"; + + /** + * Align images at the bottom. + */ + public static final String IMG_ALIGN_BOTTOM = "html-image-align-bottom"; + + /** + * Align images at the middle. + */ + public static final String IMG_ALIGN_MIDDLE = "html-image-align-middle"; + + /** + * Align images at the top. + */ + public static final String IMG_ALIGN_TOP = "html-image-align-top"; + + /** + * Align images at the border. + */ + public static final String IMG_BORDER = "html-image-border"; + + /** + * The "logical style" action identifier, passing that style as parameter. + */ + public static final String LOGICAL_STYLE_ACTION = "html-logical-style-action"; + + /** + * The "ident paragraph left" action. + */ + public static final String PARA_INDENT_LEFT = "html-para-indent-left"; + + /** + * The "ident paragraph right" action. + */ + public static final String PARA_INDENT_RIGHT = "html-para-indent-right"; + + /** + * Actions for HTML + */ + private static final Action[] defaultActions = + { + new InsertHTMLTextAction("InsertTable", + "
", + HTML.Tag.BODY, HTML.Tag.TABLE), + new InsertHTMLTextAction("InsertTableRow", + "
", + HTML.Tag.TABLE, HTML.Tag.TR, + HTML.Tag.BODY, HTML.Tag.TABLE), + new InsertHTMLTextAction("InsertTableCell", + "
", + HTML.Tag.TR, HTML.Tag.TD, + HTML.Tag.BODY, HTML.Tag.TABLE), + new InsertHTMLTextAction("InsertUnorderedList", + "", + HTML.Tag.BODY, HTML.Tag.UL), + new InsertHTMLTextAction("InsertUnorderedListItem", + "", + HTML.Tag.UL, HTML.Tag.LI, + HTML.Tag.BODY, HTML.Tag.UL), + new InsertHTMLTextAction("InsertOrderedList", + "
", + HTML.Tag.BODY, HTML.Tag.OL), + new InsertHTMLTextAction("InsertOrderedListItem", + "
", + HTML.Tag.OL, HTML.Tag.LI, + HTML.Tag.BODY, HTML.Tag.OL), + new InsertHTMLTextAction("InsertPre", + "
", HTML.Tag.BODY, HTML.Tag.PRE)
+    // TODO: The reference impl has an InsertHRAction too.
+  };
+
+  /**
+   * The current style sheet.
+   */
+  private StyleSheet styleSheet;
+
+  /**
+   * The ViewFactory for HTMLFactory.
+   */
+  HTMLFactory viewFactory;
+
+  /**
+   * The Cursor for links.
+   */
+  Cursor linkCursor;
+
+  /**
+   * The default cursor.
+   */
+  Cursor defaultCursor;
+
+  /**
+   * The parser.
+   */
+  Parser parser;
+
+  /**
+   * The mouse listener used for links.
+   */
+  private LinkController linkController;
+
+  /** The content type */
+  String contentType = "text/html";
+
+  /** The input attributes defined by default.css */
+  MutableAttributeSet inputAttributes;
+
+  /** The editor pane used. */
+  JEditorPane editorPane;
+
+  /**
+   * Whether or not the editor kit handles form submissions.
+   *
+   * @see #isAutoFormSubmission()
+   * @see #setAutoFormSubmission(boolean)
+   */
+  private boolean autoFormSubmission;
+
+  /**
+   * Constructs an HTMLEditorKit, creates a StyleContext, and loads the style sheet.
+   */
+  public HTMLEditorKit()
+  {
+    linkController = new LinkController();
+    autoFormSubmission = true;
+  }
+
+  /**
+   * Gets a factory suitable for producing views of any
+   * models that are produced by this kit.
+   *
+   * @return the view factory suitable for producing views.
+   */
+  public ViewFactory getViewFactory()
+  {
+    if (viewFactory == null)
+      viewFactory = new HTMLFactory();
+    return viewFactory;
+  }
+
+  /**
+   * Create a text storage model for this type of editor.
+   *
+   * @return the model
+   */
+  public Document createDefaultDocument()
+  {
+    // Protect the shared stylesheet.
+    StyleSheet styleSheet = getStyleSheet();
+    StyleSheet ss = new StyleSheet();
+    ss.addStyleSheet(styleSheet);
+
+    HTMLDocument document = new HTMLDocument(ss);
+    document.setParser(getParser());
+    document.setAsynchronousLoadPriority(4);
+    document.setTokenThreshold(100);
+    return document;
+  }
+
+  /**
+   * Get the parser that this editor kit uses for reading HTML streams. This
+   * method can be overridden to use the alternative parser.
+   *
+   * @return the HTML parser (by default, {@link ParserDelegator}).
+   */
+  protected Parser getParser()
+  {
+    if (parser == null)
+      {
+        parser = new GnuParserDelegator(HTML_401F.getInstance());
+      }
+    return parser;
+  }
+
+  /**
+   * Inserts HTML into an existing document.
+   *
+   * @param doc - the Document to insert the HTML into.
+   * @param offset - where to begin inserting the HTML.
+   * @param html - the String to insert
+   * @param popDepth - the number of ElementSpec.EndTagTypes
+   * to generate before inserting
+   * @param pushDepth - the number of ElementSpec.StartTagTypes
+   * with a direction of ElementSpec.JoinNextDirection that
+   * should be generated before
+   * @param insertTag - the first tag to start inserting into document
+   * @throws IOException - on any I/O error
+   * @throws BadLocationException - if pos represents an invalid location
+   * within the document
+   */
+  public void insertHTML(HTMLDocument doc, int offset, String html,
+                         int popDepth, int pushDepth, HTML.Tag insertTag)
+      throws BadLocationException, IOException
+  {
+    Parser parser = getParser();
+    if (offset < 0 || offset > doc.getLength())
+      throw new BadLocationException("Bad location", offset);
+    if (parser == null)
+      throw new IOException("Parser is null.");
+
+    ParserCallback pc = doc.getReader(offset, popDepth, pushDepth, insertTag);
+
+    // FIXME: What should ignoreCharSet be set to?
+
+    // parser.parse inserts html into the buffer
+    parser.parse(new StringReader(html), pc, false);
+    pc.flush();
+  }
+
+  /**
+   * Inserts content from the given stream. Inserting HTML into a non-empty
+   * document must be inside the body Element, if you do not insert into
+   * the body an exception will be thrown. When inserting into a non-empty
+   * document all tags outside of the body (head, title) will be dropped.
+   *
+   * @param in - the stream to read from
+   * @param doc - the destination for the insertion
+   * @param pos - the location in the document to place the content
+   * @throws IOException - on any I/O error
+   * @throws BadLocationException - if pos represents an invalid location
+   * within the document
+   */
+  public void read(Reader in, Document doc, int pos) throws IOException,
+      BadLocationException
+  {
+    if (doc instanceof HTMLDocument)
+      {
+        Parser parser = getParser();
+        if (pos < 0 || pos > doc.getLength())
+          throw new BadLocationException("Bad location", pos);
+        if (parser == null)
+          throw new IOException("Parser is null.");
+
+        HTMLDocument hd = ((HTMLDocument) doc);
+        if (editorPane != null)
+          hd.setBase(editorPane.getPage());
+        ParserCallback pc = hd.getReader(pos);
+
+        // FIXME: What should ignoreCharSet be set to?
+
+        // parser.parse inserts html into the buffer
+        parser.parse(in, pc, false);
+        pc.flush();
+      }
+    else
+      // read in DefaultEditorKit is called.
+      // the string is inserted in the document as usual.
+      super.read(in, doc, pos);
+  }
+
+  /**
+   * Writes content from a document to the given stream in
+   * an appropriate format.
+   *
+   * @param out - the stream to write to
+   * @param doc - the source for the write
+   * @param pos - the location in the document to get the content.
+   * @param len - the amount to write out
+   * @throws IOException - on any I/O error
+   * @throws BadLocationException - if pos represents an invalid location
+   * within the document
+   */
+  public void write(Writer out, Document doc, int pos, int len)
+      throws IOException, BadLocationException
+  {
+    if (doc instanceof HTMLDocument)
+      {
+        HTMLWriter writer = new HTMLWriter(out, (HTMLDocument) doc, pos, len);
+        writer.write();
+      }
+    else if (doc instanceof StyledDocument)
+      {
+        MinimalHTMLWriter writer = new MinimalHTMLWriter(out,
+                                                         (StyledDocument) doc,
+                                                         pos, len);
+        writer.write();
+      }
+    else
+      super.write(out, doc, pos, len);
+  }
+
+  /**
+   * Gets the content type that the kit supports.
+   * This kit supports the type text/html.
+   *
+   * @returns the content type supported.
+   */
+  public String getContentType()
+  {
+    return contentType;
+  }
+
+  /**
+   * Creates a copy of the editor kit.
+   *
+   * @return a copy of this.
+   */
+  public Object clone()
+  {
+    // FIXME: Need to clone all fields
+    HTMLEditorKit copy = (HTMLEditorKit) super.clone();
+    copy.linkController = new LinkController();
+    return copy;
+  }
+
+  /**
+   * Copies the key/values in elements AttributeSet into set.
+   * This does not copy component, icon, or element names attributes.
+   * This is called anytime the caret moves over a different location.
+   *
+   * @param element - the element to create the input attributes for.
+   * @param set - the set to copy the values into.
+   */
+  protected void createInputAttributes(Element element,
+                                       MutableAttributeSet set)
+  {
+    set.removeAttributes(set);
+    set.addAttributes(element.getAttributes());
+    // FIXME: Not fully implemented.
+  }
+
+  /**
+   * Called when this is installed into the JEditorPane.
+   *
+   * @param c - the JEditorPane installed into.
+   */
+  public void install(JEditorPane c)
+  {
+    super.install(c);
+    c.addMouseListener(linkController);
+    c.addMouseMotionListener(linkController);
+    editorPane = c;
+  }
+
+  /**
+   * Called when the this is removed from the JEditorPane.
+   * It unregisters any listeners.
+   *
+   * @param c - the JEditorPane being removed from.
+   */
+  public void deinstall(JEditorPane c)
+  {
+    super.deinstall(c);
+    c.removeMouseListener(linkController);
+    c.removeMouseMotionListener(linkController);
+    editorPane = null;
+  }
+
+  /**
+   * Gets the AccessibleContext associated with this.
+   *
+   * @return the AccessibleContext for this.
+   */
+  public AccessibleContext getAccessibleContext()
+  {
+    // FIXME: Should return an instance of
+    // javax.swing.text.html.AccessibleHTML$RootHTMLAccessibleContext
+    // Not implemented yet.
+    return null;
+  }
+
+  /**
+   * Gets the action list. This list is supported by the superclass
+   * augmented by the collection of actions defined locally for style
+   * operations.
+   *
+   * @return an array of all the actions
+   */
+  public Action[] getActions()
+  {
+    return TextAction.augmentList(super.getActions(), defaultActions);
+  }
+
+  /**
+   * Returns the default cursor.
+   *
+   * @return the default cursor
+   */
+  public Cursor getDefaultCursor()
+  {
+    if (defaultCursor == null)
+      defaultCursor = Cursor.getDefaultCursor();
+    return defaultCursor;
+  }
+
+  /**
+   * Returns the cursor for links.
+   *
+   * @return the cursor for links.
+   */
+  public Cursor getLinkCursor()
+  {
+    if (linkCursor == null)
+      linkCursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
+    return linkCursor;
+  }
+
+  /**
+   * Sets the Cursor for links.
+   *
+   * @param cursor - the new cursor for links.
+   */
+  public void setLinkCursor(Cursor cursor)
+  {
+    linkCursor = cursor;
+  }
+
+  /**
+   * Sets the default cursor.
+   *
+   * @param cursor - the new default cursor.
+   */
+  public void setDefaultCursor(Cursor cursor)
+  {
+    defaultCursor = cursor;
+  }
+
+  /**
+   * Gets the input attributes used for the styled editing actions.
+   *
+   * @return the attribute set
+   */
+  public MutableAttributeSet getInputAttributes()
+  {
+    return inputAttributes;
+  }
+
+  /**
+   * Get the set of styles currently being used to render the HTML elements.
+   * By default the resource specified by DEFAULT_CSS gets loaded, and is
+   * shared by all HTMLEditorKit instances.
+   *
+   * @return the style sheet.
+   */
+  public StyleSheet getStyleSheet()
+  {
+    if (styleSheet == null)
+      {
+        try
+          {
+            styleSheet = new StyleSheet();
+            Class c = HTMLEditorKit.class;
+            InputStream in = c.getResourceAsStream(DEFAULT_CSS);
+            InputStreamReader r = new InputStreamReader(in);
+            styleSheet.loadRules(r,  null);
+            r.close();
+          }
+        catch (IOException ex)
+          {
+            throw new RuntimeException("No style available.", ex);
+          }
+      }
+    return styleSheet;
+  }
+
+  /**
+   * Set the set of styles to be used to render the various HTML elements.
+   * These styles are specified in terms of CSS specifications. Each document
+   * produced by the kit will have a copy of the sheet which it can add the
+   * document specific styles to. By default, the StyleSheet specified is shared
+   * by all HTMLEditorKit instances.
+   *
+   * @param s - the new style sheet
+   */
+  public void setStyleSheet(StyleSheet s)
+  {
+    styleSheet = s;
+  }
+
+  /**
+   * Returns true when forms should be automatically submitted
+   * by the editor kit. Set this to false when you want to
+   * intercept form submission. In this case you'd want to listen for
+   * hyperlink events on the document and handle FormSubmitEvents specially.
+   *
+   * The default is true.
+   *
+   * @return true when forms should be automatically submitted
+   *         by the editor kit, false otherwise
+   *
+   * @since 1.5
+   *
+   * @see #setAutoFormSubmission(boolean)
+   * @see FormSubmitEvent
+   */
+  public boolean isAutoFormSubmission()
+  {
+    return autoFormSubmission;
+  }
+
+  /**
+   * Sets whether or not the editor kit should automatically submit forms.
+   *
+   * @param auto true when the editor kit should handle form
+   *        submission, false otherwise
+   *
+   * @since 1.5
+   *
+   * @see #isAutoFormSubmission()
+   */
+  public void setAutoFormSubmission(boolean auto)
+  {
+    autoFormSubmission = auto;
+  }
+}
-- 
cgit v1.2.3