/*
* 02/24/2004
*
* DocumentReader.java - A reader for javax.swing.text.Document
* objects.
* Copyright (C) 2004 Robert Futrell
* robert_futrell at users.sourceforge.net
* http://fifesoft.com/rsyntaxtextarea
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
package org.fife.io;
import java.io.Reader;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.Segment;
/**
* A <code>Reader</code> for <code>javax.swing.text.Document</code> objects.
*
* @author Robert Futrell
* @version 1.0
*/
public class DocumentReader extends Reader {
/**
* The stream's position in the document.
*/
private long position;
/**
* A remembered position in the document.
*/
private long mark;
/**
* The document we're working on.
*/
private Document document;
/**
* Used for fast character access.
*/
private Segment segment;
/**
* Constructor.
*
* @param document
* The document we're 'reading'.
*/
public DocumentReader(Document document) {
position = 0;
mark = -1;
this.document = document;
this.segment = new Segment();
}
/**
* This currently does nothing...
*/
public void close() {
}
/**
* Marks the present position in the stream. Subsequent calls to <code>reset()</code> will reposition the stream to
* this point.
*
* @param readAheadLimit
* Ignored.
*/
public void mark(int readAheadLimit) {
mark = position;
}
/**
* Tells whether this reader supports the <code>mark</code> operation. This always returns <code>true</code> for
* <code>DocumentReader</code>.
*/
public boolean markSupported() {
return true;
}
/**
* Reads the single character at the current position in the document.
*/
public int read() {
if (position >= document.getLength()) {
return -1; // Read past end of document.
}
try {
document.getText((int) position, 1, segment);
position++;
return segment.array[segment.offset];
} catch (BadLocationException ble) {
/* Should never happen?? */
ble.printStackTrace();
return -1;
}
}
/**
* Read <code>array.length</code> characters from the beginning of the document into <code>array</code>.
*
* @param array
* The array to read characters into.
* @return The number of characters read.
*/
public int read(char array[]) {
return read(array, 0, array.length);
}
/**
* Reads characters into a portion of an array.
*
* @param cbuf
* The destination buffer.
* @param off
* Offset at which to start storing characters.
* @param len
* Maximum number of characters to read.
* @return The number of characters read, or <code>-1</code> if the end of the stream (document) has been reached.
*/
public int read(char cbuf[], int off, int len) {
int k;
if (position >= document.getLength()) {
return -1; // Read past end of document.
}
k = len;
if ((position + k) >= document.getLength())
k = document.getLength() - (int) position;
if (off + k >= cbuf.length)
k = cbuf.length - off;
try {
document.getText((int) position, k, segment);
position += k;
System.arraycopy(segment.array, segment.offset,
cbuf, off,
k);
return k;
} catch (BadLocationException ble) {
/* Should never happen ? */
return -1;
}
}
/**
* Tells whether this reader is ready to be read without blocking for input. <code>DocumentReader</code> will always
* return true.
*
* @return <code>true</code> if the next read operation will return without blocking.
*/
public boolean ready() {
return true;
}
/**
* Resets the stream. If the stream has been marked, then attempt to reposition it at the mark. If the stream has
* not been marked, then move it to the beginning of the document.
*/
public void reset() {
if (mark == -1) {
position = 0;
}
else {
position = mark;
mark = -1;
}
}
/**
* Skips characters. This will not 'skip' past the end of the document.
*
* @param n
* The number of characters to skip.
* @return The number of characters actually skipped.
*/
public long skip(long n) {
if (position + n <= document.getLength()) {
position += n;
return n;
}
long temp = position;
position = document.getLength();
return document.getLength() - temp;
}
/**
* Move to the specified position in the document. If <code>pos</code> is greater than the document's length, the
* stream's position is moved to the end of the document.
*
* @param pos
* The position in the document to move to.
*/
public void seek(long pos) {
position = Math.min(pos, document.getLength());
}
}