diff options
Diffstat (limited to 'javax/swing/text/GapContent.java')
-rw-r--r-- | javax/swing/text/GapContent.java | 155 |
1 files changed, 144 insertions, 11 deletions
diff --git a/javax/swing/text/GapContent.java b/javax/swing/text/GapContent.java index 111617e94..94084800c 100644 --- a/javax/swing/text/GapContent.java +++ b/javax/swing/text/GapContent.java @@ -15,8 +15,8 @@ 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., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. +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 @@ -39,6 +39,9 @@ exception statement from your version. */ package javax.swing.text; import java.io.Serializable; +import java.util.Collections; +import java.util.LinkedList; +import java.util.ListIterator; import javax.swing.undo.UndoableEdit; @@ -57,6 +60,67 @@ import javax.swing.undo.UndoableEdit; public class GapContent implements AbstractDocument.Content, Serializable { + + /** + * A {@link Position} implementation for <code>GapContent</code>. + */ + class GapContentPosition implements Position, Comparable + { + + /** The index within the buffer array. */ + int mark; + + /** + * Creates a new GapContentPosition object. + * + * @param mark the mark of this Position + */ + GapContentPosition(int mark) + { + this.mark = mark; + } + + /** + * Comparable interface implementation. This is used to store all + * positions in an ordered fashion. + * + * @param o the object to be compared to this + * + * @return a negative integer if this is less than <code>o</code>, zero + * if both are equal or a positive integer if this is greater + * than <code>o</code> + * + * @throws ClassCastException if <code>o</code> is not a GapContentPosition + * or Integer object + */ + public int compareTo(Object o) + { + if (o instanceof Integer) + { + int otherMark = ((Integer) o).intValue(); + return mark - otherMark; + } + else + { + GapContentPosition other = (GapContentPosition) o; + return mark - other.mark; + } + } + + /** + * Returns the current offset of this Position within the content. + * + * @return the current offset of this Position within the content. + */ + public int getOffset() + { + if (mark <= gapStart) + return mark; + else + return mark - (gapEnd - gapStart); + } + } + private static final long serialVersionUID = 8374645204155842629L; /** @@ -81,6 +145,12 @@ public class GapContent int gapEnd; /** + * The positions generated by this GapContent. They are kept in an + * ordered fashion, so they can be looked up easily. + */ + LinkedList positions; + + /** * Creates a new GapContent object. */ public GapContent() @@ -99,6 +169,7 @@ public class GapContent gapStart = 0; gapEnd = size - 1; buffer[size - 1] = '\n'; + positions = new LinkedList(); } /** @@ -288,15 +359,24 @@ public class GapContent */ public Position createPosition(final int offset) throws BadLocationException { - return new Position() - { - int off = offset; - - public int getOffset() - { - return off; - } - }; + if (offset < 0 || offset > length()) + throw new BadLocationException("The offset was out of the bounds of this" + + " buffer", offset); + + // We store the actual array index in the GapContentPosition. The real + // offset is then calculated in the GapContentPosition. + int mark = offset; + if (offset > gapStart) + mark += gapEnd - gapStart; + GapContentPosition pos = new GapContentPosition(mark); + + // Add this into our list in a sorted fashion. + int index = Collections.binarySearch(positions, pos); + if (index < 0) + index = -(index + 1); + positions.add(index, pos); + + return pos; } /** @@ -309,12 +389,25 @@ public class GapContent */ protected void shiftEnd(int newSize) { + int delta = (gapEnd - gapStart) - newSize; char[] newBuf = (char[]) allocateArray(length() + newSize); System.arraycopy(buffer, 0, newBuf, 0, gapStart); System.arraycopy(buffer, gapEnd, newBuf, gapStart + newSize, buffer.length - gapEnd); gapEnd = gapStart + newSize; buffer = newBuf; + + // Update the marks after the gapEnd. + int index = Collections.binarySearch(positions, new Integer(gapEnd)); + if (index < 0) + { + index = -(index + 1); + } + for (ListIterator i = positions.listIterator(index); i.hasNext();) + { + GapContentPosition p = (GapContentPosition) i.next(); + p.mark += delta; + } } /** @@ -326,6 +419,22 @@ public class GapContent { int newGapEnd = newGapStart + (gapEnd - gapStart); + + // Update the positions between newGapEnd and (old) gapEnd. The marks + // must be shifted by (gapEnd - newGapEnd). + int index1 = Collections.binarySearch(positions, new Integer(gapEnd)); + int index2 = Collections.binarySearch(positions, new Integer(newGapEnd)); + int i1 = Math.min(index1, index2); + int i2 = Math.max(index1, index2); + for (ListIterator i = positions.listIterator(i1); i.hasNext();) + { + if (i.nextIndex() > i2) + break; + + GapContentPosition p = (GapContentPosition) i.next(); + p.mark += gapEnd - newGapEnd; + } + if (newGapStart == gapStart) return; else if (newGapStart < gapStart) @@ -353,4 +462,28 @@ public class GapContent { return buffer; } + + /** + * Replaces a portion of the storage with the specified items. + * + * @param position the position at which to remove items + * @param rmSize the number of items to remove + * @param addItems the items to add at location + * @param addSize the number of items to add + */ + protected void replace(int position, int rmSize, Object addItems, + int addSize) + { + // Remove content + shiftGap(position); + gapEnd += rmSize; + + // If gap is too small, enlarge the gap. + if ((gapEnd - gapStart) < addSize) + shiftEnd(addSize); + + // Add new items to the buffer. + System.arraycopy(addItems, 0, buffer, gapStart, addSize); + gapStart += addSize; + } } |