001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Vadim L. Bogdanov
019: * @version $Revision$
020: */package javax.swing.text;
021:
022: import java.io.IOException;
023: import java.io.Writer;
024: import java.security.AccessController;
025: import java.security.PrivilegedAction;
026: import java.util.Arrays;
027: import java.util.Enumeration;
028:
029: public abstract class AbstractWriter {
030: protected static final char NEWLINE = 10;
031: private static final char[] SPACES = createArrayOfSpaces(64);
032:
033: private Document doc;
034: private Writer out;
035: private ElementIterator iterator;
036: private int startOffset;
037: private int endOffset;
038: private int indentSpace = 2;
039: private int lineLength = 100;
040: private boolean canWrapLines = true;
041: private int indentLevel;
042: private int currentLineLength;
043: private String lineSeparator;
044: private boolean isLineStillEmpty;
045:
046: protected AbstractWriter(final Writer w, final Document doc) {
047: this (w, doc.getDefaultRootElement(), 0, doc.getLength());
048: }
049:
050: protected AbstractWriter(final Writer w, final Document doc,
051: final int pos, final int len) {
052: this (w, doc.getDefaultRootElement(), pos, len);
053: }
054:
055: protected AbstractWriter(final Writer w, final Element root) {
056: this (w, root, 0, root.getEndOffset());
057: }
058:
059: protected AbstractWriter(final Writer w, final Element root,
060: final int pos, final int len) {
061: doc = root.getDocument();
062: out = w;
063: iterator = new ElementIterator(root);
064: startOffset = pos;
065: endOffset = pos + len;
066: initLineSeparator();
067: }
068:
069: public int getStartOffset() {
070: return startOffset;
071: }
072:
073: public int getEndOffset() {
074: return endOffset;
075: }
076:
077: public void setLineSeparator(final String value) {
078: lineSeparator = value;
079: }
080:
081: public String getLineSeparator() {
082: return lineSeparator;
083: }
084:
085: protected Writer getWriter() {
086: return out;
087: }
088:
089: protected Document getDocument() {
090: return doc;
091: }
092:
093: protected ElementIterator getElementIterator() {
094: return iterator;
095: }
096:
097: protected String getText(final Element elem)
098: throws BadLocationException {
099: return getDocument().getText(elem.getStartOffset(),
100: elem.getEndOffset() - elem.getStartOffset());
101: }
102:
103: protected boolean inRange(final Element next) {
104: int start = next.getStartOffset();
105: int end = next.getEndOffset();
106: return getStartOffset() <= start && start < getEndOffset()
107: || getStartOffset() < end && end <= getEndOffset()
108: || start <= getStartOffset() && getEndOffset() <= end;
109: }
110:
111: protected void setLineLength(final int l) {
112: lineLength = l;
113: }
114:
115: protected int getLineLength() {
116: return lineLength;
117: }
118:
119: protected boolean isLineEmpty() {
120: return getCurrentLineLength() == 0 || isLineStillEmpty;
121: }
122:
123: protected void setCurrentLineLength(final int length) {
124: currentLineLength = length;
125: }
126:
127: protected int getCurrentLineLength() {
128: return currentLineLength;
129: }
130:
131: protected void setCanWrapLines(final boolean newValue) {
132: canWrapLines = newValue;
133: }
134:
135: protected boolean getCanWrapLines() {
136: return canWrapLines;
137: }
138:
139: protected void incrIndent() {
140: if ((getIndentLevel() + 1) * getIndentSpace() <= getLineLength()) {
141: indentLevel++;
142: }
143: }
144:
145: protected void decrIndent() {
146: indentLevel--;
147: }
148:
149: protected int getIndentLevel() {
150: return indentLevel;
151: }
152:
153: protected void indent() throws IOException {
154: boolean wasLineEmpty = isLineEmpty();
155:
156: int indentLineLength = getIndentLevel() * getIndentSpace();
157: char indentLine[];
158: if (indentLineLength <= SPACES.length) {
159: indentLine = SPACES;
160: } else {
161: indentLine = createArrayOfSpaces(indentLineLength);
162: }
163: output(indentLine, 0, indentLineLength);
164:
165: isLineStillEmpty = wasLineEmpty;
166: }
167:
168: protected void setIndentSpace(final int space) {
169: indentSpace = space;
170: }
171:
172: protected int getIndentSpace() {
173: return indentSpace;
174: }
175:
176: protected void output(final char[] content, final int start,
177: final int length) throws IOException {
178:
179: out.write(content, start, length);
180: setCurrentLineLength(getCurrentLineLength() + length);
181: isLineStillEmpty = false;
182: }
183:
184: protected void text(final Element elem)
185: throws BadLocationException, IOException {
186: String content = getText(elem);
187: int textStart = Math.max(getStartOffset(), elem
188: .getStartOffset())
189: - elem.getStartOffset();
190: int textEnd = Math.min(getEndOffset(), elem.getEndOffset())
191: - elem.getStartOffset();
192:
193: if (textEnd > textStart) {
194: write(content.toCharArray(), textStart, textEnd - textStart);
195: }
196: }
197:
198: protected void write(final char ch) throws IOException {
199: char chars[] = { ch };
200: write(chars, 0, 1);
201: }
202:
203: protected void write(final char[] chars, final int start,
204: final int length) throws IOException {
205: boolean canWrapLines = getCanWrapLines();
206:
207: int writtenLength = 0;
208: boolean firstLine = true;
209: while (writtenLength < length) {
210: if (!firstLine && canWrapLines) {
211: indent();
212: }
213: firstLine = false;
214: int lineLength = findNewline(chars, start + writtenLength,
215: length - writtenLength);
216: if (!canWrapLines) {
217: output(chars, start + writtenLength, lineLength);
218: } else {
219: writeWrappedLine(chars, start + writtenLength,
220: lineLength);
221: }
222: writtenLength += lineLength + 1;
223: if (writtenLength <= length) {
224: writeLineSeparator();
225: }
226: }
227: }
228:
229: protected void write(final String content) throws IOException {
230: char chars[] = content.toCharArray();
231: write(chars, 0, chars.length);
232: }
233:
234: protected void writeAttributes(final AttributeSet attrs)
235: throws IOException {
236:
237: StringBuffer content = new StringBuffer();
238: for (Enumeration keys = attrs.getAttributeNames(); keys
239: .hasMoreElements();) {
240: Object key = keys.nextElement();
241: content.append(" ");
242: content.append(key);
243: content.append("=");
244: content.append(attrs.getAttribute(key));
245: }
246:
247: write(content.toString());
248: }
249:
250: protected void writeLineSeparator() throws IOException {
251: char chars[] = getLineSeparator().toCharArray();
252: output(chars, 0, chars.length);
253: setCurrentLineLength(0);
254: }
255:
256: protected abstract void write() throws IOException,
257: BadLocationException;
258:
259: private void initLineSeparator() {
260: Object separator = (String) getDocument().getProperty(
261: DefaultEditorKit.EndOfLineStringProperty);
262: if (!(separator instanceof String)) {
263: PrivilegedAction action = new PrivilegedAction() {
264: public Object run() {
265: return System.getProperty("line.separator");
266: }
267: };
268:
269: separator = AccessController.doPrivileged(action);
270: }
271: lineSeparator = (String) separator;
272: }
273:
274: private int findNewline(final char[] chars, final int start,
275: final int length) {
276: for (int i = 0; i < length; i++) {
277: if (chars[start + i] == NEWLINE) {
278: return i;
279: }
280: }
281: return length;
282: }
283:
284: private int findWrappedLineBreak(final char[] chars,
285: final int start, final int length) {
286: for (int i = 0; i < length; i++) {
287: if (Character.isWhitespace(chars[start + i])) {
288: return i + 1;
289: }
290: }
291: return length;
292: }
293:
294: private void writeWrappedLine(final char[] chars, final int start,
295: final int length) throws IOException {
296: int writtenLength = 0;
297: boolean firstLine = true;
298: while (writtenLength < length) {
299: int lineLength = findWrappedLineBreak(chars, start
300: + writtenLength, length - writtenLength);
301: if (!firstLine
302: && getCurrentLineLength() + lineLength >= getLineLength()) {
303: writeLineSeparator();
304: indent();
305: }
306: output(chars, start + writtenLength, lineLength);
307: writtenLength += lineLength;
308: firstLine = false;
309: }
310: }
311:
312: private static char[] createArrayOfSpaces(final int length) {
313: char[] spaces = new char[length];
314: Arrays.fill(spaces, ' ');
315: return spaces;
316: }
317: }
|