summaryrefslogtreecommitdiff
path: root/javax/swing/text/GapContent.java
diff options
context:
space:
mode:
Diffstat (limited to 'javax/swing/text/GapContent.java')
-rw-r--r--javax/swing/text/GapContent.java155
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;
+ }
}