From 554fd8c5195424bdbcabf5de30fdc183aba391bd Mon Sep 17 00:00:00 2001 From: upstream source tree Date: Sun, 15 Mar 2015 20:14:05 -0400 Subject: obtained gcc-4.6.4.tar.bz2 from upstream website; verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository. --- .../classpath/javax/swing/text/StringContent.java | 569 +++++++++++++++++++++ 1 file changed, 569 insertions(+) create mode 100644 libjava/classpath/javax/swing/text/StringContent.java (limited to 'libjava/classpath/javax/swing/text/StringContent.java') diff --git a/libjava/classpath/javax/swing/text/StringContent.java b/libjava/classpath/javax/swing/text/StringContent.java new file mode 100644 index 000000000..a017de1c9 --- /dev/null +++ b/libjava/classpath/javax/swing/text/StringContent.java @@ -0,0 +1,569 @@ +/* StringContent.java -- + Copyright (C) 2005, 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 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., 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 +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.text; + +import java.io.Serializable; +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; +import java.util.Iterator; +import java.util.Vector; + +import javax.swing.undo.AbstractUndoableEdit; +import javax.swing.undo.CannotRedoException; +import javax.swing.undo.CannotUndoException; +import javax.swing.undo.UndoableEdit; + +/** + * An implementation of the AbstractDocument.Content + * interface useful for small documents or debugging. The character + * content is a simple character array. It's not really efficient. + * + *

Do not use this class for large size.

+ */ +public final class StringContent + implements AbstractDocument.Content, Serializable +{ + /** + * Stores a reference to a mark that can be resetted to the original value + * after a mark has been moved. This is used for undoing actions. + */ + private class UndoPosRef + { + /** + * The mark that might need to be reset. + */ + private Mark mark; + + /** + * The original offset to reset the mark to. + */ + private int undoOffset; + + /** + * Creates a new UndoPosRef. + * + * @param m the mark + */ + UndoPosRef(Mark m) + { + mark = m; + undoOffset = mark.mark; + } + + /** + * Resets the position of the mark to the value that it had when + * creating this UndoPosRef. + */ + void reset() + { + mark.mark = undoOffset; + } + } + + /** + * Holds a mark into the buffer that is used by StickyPosition to find + * the actual offset of the position. This is pulled out of the + * GapContentPosition object so that the mark and position can be handled + * independently, and most important, so that the StickyPosition can + * be garbage collected while we still hold a reference to the Mark object. + */ + private class Mark + { + /** + * The actual mark into the buffer. + */ + int mark; + + + /** + * The number of GapContentPosition object that reference this mark. If + * it reaches zero, it get's deleted by + * {@link StringContent#garbageCollect()}. + */ + int refCount; + + /** + * Creates a new Mark object for the specified offset. + * + * @param offset the offset + */ + Mark(int offset) + { + mark = offset; + } + } + + /** The serialization UID (compatible with JDK1.5). */ + private static final long serialVersionUID = 4755994433709540381L; + + // This is package-private to avoid an accessor method. + char[] content; + + private int count; + + /** + * Holds the marks for the positions. + * + * This is package private to avoid accessor methods. + */ + Vector marks; + + private class InsertUndo extends AbstractUndoableEdit + { + private int start; + + private int length; + + private String redoContent; + + private Vector positions; + + public InsertUndo(int start, int length) + { + super(); + this.start = start; + this.length = length; + } + + public void undo() + { + super.undo(); + try + { + if (marks != null) + positions = getPositionsInRange(null, start, length); + redoContent = getString(start, length); + remove(start, length); + } + catch (BadLocationException b) + { + throw new CannotUndoException(); + } + } + + public void redo() + { + super.redo(); + try + { + insertString(start, redoContent); + redoContent = null; + if (positions != null) + { + updateUndoPositions(positions); + positions = null; + } + } + catch (BadLocationException b) + { + throw new CannotRedoException(); + } + } + } + + private class RemoveUndo extends AbstractUndoableEdit + { + private int start; + private int len; + private String undoString; + + Vector positions; + + public RemoveUndo(int start, String str) + { + super(); + this.start = start; + len = str.length(); + this.undoString = str; + if (marks != null) + positions = getPositionsInRange(null, start, str.length()); + } + + public void undo() + { + super.undo(); + try + { + StringContent.this.insertString(this.start, this.undoString); + if (positions != null) + { + updateUndoPositions(positions); + positions = null; + } + undoString = null; + } + catch (BadLocationException bad) + { + throw new CannotUndoException(); + } + } + + public void redo() + { + super.redo(); + try + { + undoString = getString(start, len); + if (marks != null) + positions = getPositionsInRange(null, start, len); + remove(this.start, len); + } + catch (BadLocationException bad) + { + throw new CannotRedoException(); + } + } + } + + private class StickyPosition implements Position + { + Mark mark; + + public StickyPosition(int offset) + { + // Try to make space. + garbageCollect(); + + mark = new Mark(offset); + mark.refCount++; + marks.add(mark); + + new WeakReference(this, queueOfDeath); + } + + /** + * Should be >=0. + */ + public int getOffset() + { + return mark.mark; + } + } + + /** + * Used in {@link #remove(int,int)}. + */ + private static final char[] EMPTY = new char[0]; + + /** + * Queues all references to GapContentPositions that are about to be + * GC'ed. This is used to remove the corresponding marks from the + * positionMarks array if the number of references to that mark reaches zero. + * + * This is package private to avoid accessor synthetic methods. + */ + ReferenceQueue queueOfDeath; + + /** + * Creates a new instance containing the string "\n". This is equivalent + * to calling {@link #StringContent(int)} with an initialLength + * of 10. + */ + public StringContent() + { + this(10); + } + + /** + * Creates a new instance containing the string "\n". + * + * @param initialLength the initial length of the underlying character + * array used to store the content. + */ + public StringContent(int initialLength) + { + super(); + queueOfDeath = new ReferenceQueue(); + if (initialLength < 1) + initialLength = 1; + this.content = new char[initialLength]; + this.content[0] = '\n'; + this.count = 1; + } + + protected Vector getPositionsInRange(Vector v, + int offset, + int length) + { + Vector refPos = v == null ? new Vector() : v; + Iterator iter = marks.iterator(); + while(iter.hasNext()) + { + Mark m = (Mark) iter.next(); + if (offset <= m.mark && m.mark <= offset + length) + refPos.add(new UndoPosRef(m)); + } + return refPos; + } + + /** + * Creates a position reference for the character at the given offset. The + * position offset will be automatically updated when new characters are + * inserted into or removed from the content. + * + * @param offset the character offset. + * + * @throws BadLocationException if offset is outside the bounds of the + * content. + */ + public Position createPosition(int offset) throws BadLocationException + { + // Lazily create marks vector. + if (marks == null) + marks = new Vector(); + StickyPosition sp = new StickyPosition(offset); + return sp; + } + + /** + * Returns the length of the string content, including the '\n' character at + * the end. + * + * @return The length of the string content. + */ + public int length() + { + return count; + } + + /** + * Inserts str at the given position and returns an + * {@link UndoableEdit} that enables undo/redo support. + * + * @param where the insertion point (must be less than + * length()). + * @param str the string to insert (null not permitted). + * + * @return An object that can undo the insertion. + */ + public UndoableEdit insertString(int where, String str) + throws BadLocationException + { + checkLocation(where, 0); + if (where == this.count) + throw new BadLocationException("Invalid location", 1); + if (str == null) + throw new NullPointerException(); + char[] insert = str.toCharArray(); + replace(where, 0, insert); + + // Move all the positions. + if (marks != null) + { + Iterator iter = marks.iterator(); + int start = where; + if (start == 0) + start = 1; + while (iter.hasNext()) + { + Mark m = (Mark) iter.next(); + if (m.mark >= start) + m.mark += str.length(); + } + } + + InsertUndo iundo = new InsertUndo(where, insert.length); + return iundo; + } + + /** + * Removes the specified range of characters and returns an + * {@link UndoableEdit} that enables undo/redo support. + * + * @param where the starting index. + * @param nitems the number of characters. + * + * @return An object that can undo the removal. + * + * @throws BadLocationException if the character range extends outside the + * bounds of the content OR includes the last character. + */ + public UndoableEdit remove(int where, int nitems) throws BadLocationException + { + checkLocation(where, nitems + 1); + RemoveUndo rundo = new RemoveUndo(where, new String(this.content, where, + nitems)); + + replace(where, nitems, EMPTY); + // Move all the positions. + if (marks != null) + { + Iterator iter = marks.iterator(); + while (iter.hasNext()) + { + Mark m = (Mark) iter.next(); + if (m.mark >= where + nitems) + m.mark -= nitems; + else if (m.mark >= where) + m.mark = where; + } + } + return rundo; + } + + private void replace(int offs, int numRemove, char[] insert) + { + int insertLength = insert.length; + int delta = insertLength - numRemove; + int src = offs + numRemove; + int numMove = count - src; + int dest = src + delta; + if (count + delta >= content.length) + { + // Grow data array. + int newLength = Math.max(2 * content.length, count + delta); + char[] newContent = new char[newLength]; + System.arraycopy(content, 0, newContent, 0, offs); + System.arraycopy(insert, 0, newContent, offs, insertLength); + System.arraycopy(content, src, newContent, dest, numMove); + content = newContent; + } + else + { + System.arraycopy(content, src, content, dest, numMove); + System.arraycopy(insert, 0, content, offs, insertLength); + } + count += delta; + } + + /** + * Returns a new String containing the characters in the + * specified range. + * + * @param where the start index. + * @param len the number of characters. + * + * @return A string. + * + * @throws BadLocationException if the requested range of characters extends + * outside the bounds of the content. + */ + public String getString(int where, int len) throws BadLocationException + { + // The RI throws a StringIndexOutOfBoundsException here, which + // smells like a bug. We throw a BadLocationException instead. + checkLocation(where, len); + return new String(this.content, where, len); + } + + /** + * Updates txt to contain a direct reference to the underlying + * character array. + * + * @param where the index of the first character. + * @param len the number of characters. + * @param txt a carrier for the return result (null not + * permitted). + * + * @throws BadLocationException if the requested character range is not + * within the bounds of the content. + * @throws NullPointerException if txt is null. + */ + public void getChars(int where, int len, Segment txt) + throws BadLocationException + { + if (where + len > count) + throw new BadLocationException("Invalid location", where + len); + txt.array = content; + txt.offset = where; + txt.count = len; + } + + + /** + * Resets the positions in the specified vector to their original offset + * after a undo operation is performed. For example, after removing some + * content, the positions in the removed range will all be set to one + * offset. This method restores the positions to their original offsets + * after an undo. + */ + protected void updateUndoPositions(Vector positions) + { + for (Iterator i = positions.iterator(); i.hasNext();) + { + UndoPosRef pos = (UndoPosRef) i.next(); + pos.reset(); + } + } + + /** + * A utility method that checks the validity of the specified character + * range. + * + * @param where the first character in the range. + * @param len the number of characters in the range. + * + * @throws BadLocationException if the specified range is not within the + * bounds of the content. + */ + void checkLocation(int where, int len) throws BadLocationException + { + if (where < 0) + throw new BadLocationException("Invalid location", 1); + else if (where > this.count) + throw new BadLocationException("Invalid location", this.count); + else if ((where + len) > this.count) + throw new BadLocationException("Invalid range", this.count); + } + + /** + * Polls the queue of death for GapContentPositions, updates the + * corresponding reference count and removes the corresponding mark + * if the refcount reaches zero. + * + * This is package private to avoid accessor synthetic methods. + */ + void garbageCollect() + { + Reference ref = queueOfDeath.poll(); + while (ref != null) + { + if (ref != null) + { + StickyPosition pos = (StickyPosition) ref.get(); + Mark m = pos.mark; + m.refCount--; + if (m.refCount == 0) + marks.remove(m); + } + ref = queueOfDeath.poll(); + } + } +} -- cgit v1.2.3