713 lines · 22.8 KB · Java
RawDownload
/* * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javax.swing.text; import java.io.Writer;import java.io.IOException;import java.util.Enumeration; /** * AbstractWriter is an abstract class that actually * does the work of writing out the element tree * including the attributes.  In terms of how much is * written out per line, the writer defaults to 100. * But this value can be set by subclasses. * * @author Sunita Mani */ public abstract class AbstractWriter {     private ElementIterator it;    private Writer out;    private int indentLevel = 0;    private int indentSpace = 2;    private Document doc = null;    private int maxLineLength = 100;    private int currLength = 0;    private int startOffset = 0;    private int endOffset = 0;    // If (indentLevel * indentSpace) becomes >= maxLineLength, this will    // get incremened instead of indentLevel to avoid indenting going greater    // than line length.    private int offsetIndent = 0;     /**     * String used for end of line. If the Document has the property     * EndOfLineStringProperty, it will be used for newlines. Otherwise     * the System property line.separator will be used. The line separator     * can also be set.     */    private String lineSeparator;     /**     * True indicates that when writing, the line can be split, false     * indicates that even if the line is > than max line length it should     * not be split.     */    private boolean canWrapLines;     /**     * True while the current line is empty. This will remain true after     * indenting.     */    private boolean isLineEmpty;     /**     * Used when indenting. Will contain the spaces.     */    private char[] indentChars;     /**     * Used when writing out a string.     */    private char[] tempChars;     /**     * This is used in <code>writeLineSeparator</code> instead of     * tempChars. If tempChars were used it would mean write couldn't invoke     * <code>writeLineSeparator</code> as it might have been passed     * tempChars.     */    private char[] newlineChars;     /**     * Used for writing text.     */    private Segment segment;     /**     * How the text packages models newlines.     * @see #getLineSeparator     */    protected static final char NEWLINE = '\n';      /**     * Creates a new AbstractWriter.     * Initializes the ElementIterator with the default     * root of the document.     *     * @param w a Writer.     * @param doc a Document     */    protected AbstractWriter(Writer w, Document doc) {        this(w, doc, 0, doc.getLength());    }     /**     * Creates a new AbstractWriter.     * Initializes the ElementIterator with the     * element passed in.     *     * @param w a Writer     * @param doc an Element     * @param pos The location in the document to fetch the     *   content.     * @param len The amount to write out.     */    protected AbstractWriter(Writer w, Document doc, int pos, int len) {        this.doc = doc;        it = new ElementIterator(doc.getDefaultRootElement());        out = w;        startOffset = pos;        endOffset = pos + len;        Object docNewline = doc.getProperty(DefaultEditorKit.                                       EndOfLineStringProperty);        if (docNewline instanceof String) {            setLineSeparator((String)docNewline);        }        else {            String newline = null;            try {                newline = System.getProperty("line.separator");            } catch (SecurityException se) {}            if (newline == null) {                // Should not get here, but if we do it means we could not                // find a newline string, use \n in this case.                newline = "\n";            }            setLineSeparator(newline);        }        canWrapLines = true;    }     /**     * Creates a new AbstractWriter.     * Initializes the ElementIterator with the     * element passed in.     *     * @param w a Writer     * @param root an Element     */    protected AbstractWriter(Writer w, Element root) {        this(w, root, 0, root.getEndOffset());    }     /**     * Creates a new AbstractWriter.     * Initializes the ElementIterator with the     * element passed in.     *     * @param w a Writer     * @param root an Element     * @param pos The location in the document to fetch the     *   content.     * @param len The amount to write out.     */    protected AbstractWriter(Writer w, Element root, int pos, int len) {        this.doc = root.getDocument();        it = new ElementIterator(root);        out = w;        startOffset = pos;        endOffset = pos + len;        canWrapLines = true;    }     /**     * Returns the first offset to be output.     *     * @since 1.3     */    public int getStartOffset() {        return startOffset;    }     /**     * Returns the last offset to be output.     *     * @since 1.3     */    public int getEndOffset() {        return endOffset;    }     /**     * Fetches the ElementIterator.     *     * @return the ElementIterator.     */    protected ElementIterator getElementIterator() {        return it;    }     /**     * Returns the Writer that is used to output the content.     *     * @since 1.3     */    protected Writer getWriter() {        return out;    }     /**     * Fetches the document.     *     * @return the Document.     */    protected Document getDocument() {        return doc;    }     /**     * This method determines whether the current element     * is in the range specified.  When no range is specified,     * the range is initialized to be the entire document.     * inRange() returns true if the range specified intersects     * with the element's range.     *     * @param  next an Element.     * @return boolean that indicates whether the element     *         is in the range.     */    protected boolean inRange(Element next) {        int startOffset = getStartOffset();        int endOffset = getEndOffset();        if ((next.getStartOffset() >= startOffset &&             next.getStartOffset()  < endOffset) ||            (startOffset >= next.getStartOffset() &&             startOffset < next.getEndOffset())) {            return true;        }        return false;    }     /**     * This abstract method needs to be implemented     * by subclasses.  Its responsibility is to     * iterate over the elements and use the write()     * methods to generate output in the desired format.     */    abstract protected void write() throws IOException, BadLocationException;     /**     * Returns the text associated with the element.     * The assumption here is that the element is a     * leaf element.  Throws a BadLocationException     * when encountered.     *     * @param     elem an <code>Element</code>     * @exception BadLocationException if pos represents an invalid     *            location within the document     * @return    the text as a <code>String</code>     */    protected String getText(Element elem) throws BadLocationException {        return doc.getText(elem.getStartOffset(),                           elem.getEndOffset() - elem.getStartOffset());    }      /**     * Writes out text.  If a range is specified when the constructor     * is invoked, then only the appropriate range of text is written     * out.     *     * @param     elem an Element.     * @exception IOException on any I/O error     * @exception BadLocationException if pos represents an invalid     *            location within the document.     */    protected void text(Element elem) throws BadLocationException,                                             IOException {        int start = Math.max(getStartOffset(), elem.getStartOffset());        int end = Math.min(getEndOffset(), elem.getEndOffset());        if (start < end) {            if (segment == null) {                segment = new Segment();            }            getDocument().getText(start, end - start, segment);            if (segment.count > 0) {                write(segment.array, segment.offset, segment.count);            }        }    }     /**     * Enables subclasses to set the number of characters they     * want written per line.   The default is 100.     *     * @param l the maximum line length.     */    protected void setLineLength(int l) {        maxLineLength = l;    }     /**     * Returns the maximum line length.     *     * @since 1.3     */    protected int getLineLength() {        return maxLineLength;    }     /**     * Sets the current line length.     *     * @since 1.3     */    protected void setCurrentLineLength(int length) {        currLength = length;        isLineEmpty = (currLength == 0);    }     /**     * Returns the current line length.     *     * @since 1.3     */    protected int getCurrentLineLength() {        return currLength;    }     /**     * Returns true if the current line should be considered empty. This     * is true when <code>getCurrentLineLength</code> == 0 ||     * <code>indent</code> has been invoked on an empty line.     *     * @since 1.3     */    protected boolean isLineEmpty() {        return isLineEmpty;    }     /**     * Sets whether or not lines can be wrapped. This can be toggled     * during the writing of lines. For example, outputting HTML might     * set this to false when outputting a quoted string.     *     * @since 1.3     */    protected void setCanWrapLines(boolean newValue) {        canWrapLines = newValue;    }     /**     * Returns whether or not the lines can be wrapped. If this is false     * no lineSeparator's will be output.     *     * @since 1.3     */    protected boolean getCanWrapLines() {        return canWrapLines;    }     /**     * Enables subclasses to specify how many spaces an indent     * maps to. When indentation takes place, the indent level     * is multiplied by this mapping.  The default is 2.     *     * @param space an int representing the space to indent mapping.     */    protected void setIndentSpace(int space) {        indentSpace = space;    }     /**     * Returns the amount of space to indent.     *     * @since 1.3     */    protected int getIndentSpace() {        return indentSpace;    }     /**     * Sets the String used to reprsent newlines. This is initialized     * in the constructor from either the Document, or the System property     * line.separator.     *     * @since 1.3     */    public void setLineSeparator(String value) {        lineSeparator = value;    }     /**     * Returns the string used to represent newlines.     *     * @since 1.3     */    public String getLineSeparator() {        return lineSeparator;    }     /**     * Increments the indent level. If indenting would cause     * <code>getIndentSpace()</code> *<code>getIndentLevel()</code> to be >     * than <code>getLineLength()</code> this will not cause an indent.     */    protected void incrIndent() {        // Only increment to a certain point.        if (offsetIndent > 0) {            offsetIndent++;        }        else {            if (++indentLevel * getIndentSpace() >= getLineLength()) {                offsetIndent++;                --indentLevel;            }        }    }     /**     * Decrements the indent level.     */    protected void decrIndent() {        if (offsetIndent > 0) {            --offsetIndent;        }        else {            indentLevel--;        }    }     /**     * Returns the current indentation level. That is, the number of times     * <code>incrIndent</code> has been invoked minus the number of times     * <code>decrIndent</code> has been invoked.     *     * @since 1.3     */    protected int getIndentLevel() {        return indentLevel;    }     /**     * Does indentation. The number of spaces written     * out is indent level times the space to map mapping. If the current     * line is empty, this will not make it so that the current line is     * still considered empty.     *     * @exception IOException on any I/O error     */    protected void indent() throws IOException {        int max = getIndentLevel() * getIndentSpace();        if (indentChars == null || max > indentChars.length) {            indentChars = new char[max];            for (int counter = 0; counter < max; counter++) {                indentChars[counter] = ' ';            }        }        int length = getCurrentLineLength();        boolean wasEmpty = isLineEmpty();        output(indentChars, 0, max);        if (wasEmpty && length == 0) {            isLineEmpty = true;        }    }     /**     * Writes out a character. This is implemented to invoke     * the <code>write</code> method that takes a char[].     *     * @param     ch a char.     * @exception IOException on any I/O error     */    protected void write(char ch) throws IOException {        if (tempChars == null) {            tempChars = new char[128];        }        tempChars[0] = ch;        write(tempChars, 0, 1);    }     /**     * Writes out a string. This is implemented to invoke the     * <code>write</code> method that takes a char[].

Lines 1–500 of 713.