📄 althtmlwriter.java
字号:
/** * AltHTMLWriter.java * Hacked version of javax.swing.text.html.HTMLWriter * Created on 18.02.2003, 16:27:05 Alex * Package: javax.swing.text.html * * @author Alex V. Alishevskikh, alex@openmechanics.net * Copyright (c) 2003 OpenMechanics.org */package net.sf.memoranda.ui.htmleditor;import java.awt.Polygon;import java.io.IOException;import java.io.Serializable;import java.io.Writer;import java.util.BitSet;import java.util.Enumeration;import java.util.Stack;import java.util.StringTokenizer;import java.util.Vector;import javax.swing.DefaultComboBoxModel;import javax.swing.DefaultListModel;import javax.swing.ListSelectionModel;import javax.swing.event.EventListenerList;import javax.swing.event.ListSelectionEvent;import javax.swing.event.ListSelectionListener;import javax.swing.text.AbstractWriter;import javax.swing.text.AttributeSet;import javax.swing.text.BadLocationException;import javax.swing.text.Document;import javax.swing.text.Element;import javax.swing.text.ElementIterator;import javax.swing.text.MutableAttributeSet;import javax.swing.text.Segment;import javax.swing.text.SimpleAttributeSet;import javax.swing.text.Style;import javax.swing.text.StyleConstants;import javax.swing.text.StyleContext;import javax.swing.text.html.CSS;import javax.swing.text.html.HTML;import javax.swing.text.html.HTMLDocument;import javax.swing.text.html.Option;import javax.swing.text.html.StyleSheet;/** * This is an alternate writer for HTMLDocuments. * * Based on original javax.swing.text.html.HTMLWriter: * * Sun Java(TM) 2 SDK, Standard Edition Version 1.4.1 * HTMLWriter.java 1.30 01/12/03 * author Sunita Mani * version 1.26, 02/02/00 * Copyright 2002 Sun Microsystems, Inc. */public class AltHTMLWriter extends AbstractWriter { /* * Stores all elements for which end tags have to * be emitted. */ private Stack blockElementStack = new Stack(); private boolean inContent = false; private boolean inPre = false; /** When inPre is true, this will indicate the end offset of the pre * element. */ private int preEndOffset; private boolean inTextArea = false; private boolean newlineOutputed = false; private boolean completeDoc; /* * Stores all embedded tags. Embedded tags are tags that are * stored as attributes in other tags. Generally they're * character level attributes. Examples include * <b>, <i>, <font>, and <a>. */ private Vector tags = new Vector(10); /** * Values for the tags. */ private Vector tagValues = new Vector(10); /** * Used when writing out content. */ private Segment segment; /* * This is used in closeOutUnwantedEmbeddedTags. */ private Vector tagsToRemove = new Vector(10); /** * Set to true after the head has been output. */ private boolean wroteHead; /** * Set to true when entities (such as <) should be replaced. */ private boolean replaceEntities; /** * Temporary buffer. */ private char[] tempChars; private String encoding = null; /** * Creates a new HTMLWriter. * * @param w a Writer * @param doc an HTMLDocument * */ public AltHTMLWriter(Writer w, HTMLDocument doc) { this(w, doc, 0, doc.getLength(), null, false); } public AltHTMLWriter(Writer w, HTMLDocument doc, String enc) { this(w, doc, 0, doc.getLength(), enc, false); } public AltHTMLWriter(Writer w, HTMLDocument doc, String enc, boolean nument) { this(w, doc, 0, doc.getLength(), enc, nument); } boolean _nument = false; /** * Creates a new HTMLWriter. * * @param w a Writer * @param doc an HTMLDocument * @param pos the document location from which to fetch the content * @param len the amount to write out */ public AltHTMLWriter(Writer w, HTMLDocument doc, int pos, int len, String enc, boolean nument) { super(w, doc, pos, len); completeDoc = (pos == 0 && len == doc.getLength()); setLineLength(80); this.encoding = enc; this._nument = nument; } /** * Iterates over the * Element tree and controls the writing out of * all the tags and its attributes. * * @exception IOException on any I/O error * @exception BadLocationException if pos represents an invalid * location within the document. * */ public void write() throws IOException, BadLocationException { ElementIterator it = getElementIterator(); Element current = null; Element next = null; wroteHead = false; setCurrentLineLength(0); replaceEntities = false; setCanWrapLines(false); if (segment == null) { segment = new Segment(); } inPre = false; boolean forcedBody = false; while ((next = it.next()) != null) { if (!inRange(next)) { if (completeDoc && next.getAttributes().getAttribute(StyleConstants.NameAttribute) == HTML.Tag.BODY) { forcedBody = true; } else { continue; } } if (current != null) { /* if next is child of current increment indent */ if (indentNeedsIncrementing(current, next)) { incrIndent(); } else if (current.getParentElement() != next.getParentElement()) { /* next and current are not siblings so emit end tags for items on the stack until the item on top of the stack, is the parent of the next. */ Element top = (Element) blockElementStack.peek(); while (top != next.getParentElement()) { /* pop() will return top. */ blockElementStack.pop(); if (!synthesizedElement(top)) { AttributeSet attrs = top.getAttributes(); if (!matchNameAttribute(attrs, HTML.Tag.PRE) && !isFormElementWithContent(attrs)) { decrIndent(); } endTag(top); } top = (Element) blockElementStack.peek(); } } else if (current.getParentElement() == next.getParentElement()) { /* if next and current are siblings the indent level is correct. But, we need to make sure that if current is on the stack, we pop it off, and put out its end tag. */ Element top = (Element) blockElementStack.peek(); if (top == current) { blockElementStack.pop(); endTag(top); } } } if (!next.isLeaf() || isFormElementWithContent(next.getAttributes())) { blockElementStack.push(next); startTag(next); } else { emptyTag(next); } current = next; } /* Emit all remaining end tags */ /* A null parameter ensures that all embedded tags currently in the tags vector have their corresponding end tags written out. */ closeOutUnwantedEmbeddedTags(null); if (forcedBody) { blockElementStack.pop(); endTag(current); } while (!blockElementStack.empty()) { current = (Element) blockElementStack.pop(); if (!synthesizedElement(current)) { AttributeSet attrs = current.getAttributes(); if (!matchNameAttribute(attrs, HTML.Tag.PRE) && !isFormElementWithContent(attrs)) { decrIndent(); } endTag(current); } } /*if (completeDoc) { writeAdditionalComments(); }*/ segment.array = null; } /** * Writes out the attribute set. Ignores all * attributes with a key of type HTML.Tag, * attributes with a key of type StyleConstants, * and attributes with a key of type * HTML.Attribute.ENDTAG. * * @param attr an AttributeSet * @exception IOException on any I/O error * */ protected void writeAttributes(AttributeSet attr) throws IOException { // translate css attributes to html convAttr.removeAttributes(convAttr); convertToHTML32(attr, convAttr); Enumeration names = convAttr.getAttributeNames(); while (names.hasMoreElements()) { Object name = names.nextElement(); if (name instanceof HTML.Tag || name instanceof StyleConstants || name == HTML.Attribute.ENDTAG) { continue; } write(" " + name + "=\"" + convAttr.getAttribute(name) + "\""); } } /** * Writes out all empty elements (all tags that have no * corresponding end tag). * * @param elem an Element * @exception IOException on any I/O error * @exception BadLocationException if pos represents an invalid * location within the document. */ protected void emptyTag(Element elem) throws BadLocationException, IOException { if (!inContent && !inPre) { indent(); } AttributeSet attr = elem.getAttributes(); closeOutUnwantedEmbeddedTags(attr); writeEmbeddedTags(attr); if (matchNameAttribute(attr, HTML.Tag.CONTENT)) { inContent = true; text(elem); } else if (matchNameAttribute(attr, HTML.Tag.COMMENT)) { comment(elem); } else { boolean isBlock = isBlockTag(elem.getAttributes()); if (inContent && isBlock) { writeLineSeparator(); indent(); } Object nameTag = (attr != null) ? attr.getAttribute(StyleConstants.NameAttribute) : null; Object endTag = (attr != null) ? attr.getAttribute(HTML.Attribute.ENDTAG) : null; boolean outputEndTag = false; // If an instance of an UNKNOWN Tag, or an instance of a // tag that is only visible during editing // if (nameTag != null && endTag != null && (endTag instanceof String) && ((String) endTag).equals("true")) { outputEndTag = true; } if (completeDoc && matchNameAttribute(attr, HTML.Tag.HEAD)) { if (outputEndTag) { // Write out any styles. writeStyles(((HTMLDocument) getDocument()).getStyleSheet()); } wroteHead = true; } write('<'); if (outputEndTag) { write('/'); } write(elem.getName()); writeAttributes(attr); write('>'); if (matchNameAttribute(attr, HTML.Tag.TITLE) && !outputEndTag) { Document doc = elem.getDocument(); String title = (String) doc.getProperty(Document.TitleProperty); write(title); } else if (!inContent || isBlock) { writeLineSeparator(); if (isBlock && inContent) { indent(); } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -