Method from javax.swing.text.GapContent Detail: |
protected Object allocateArray(int len) {
return new char[len];
}
Allocate an array to store items of the type
appropriate (which is determined by the subclass). |
final int compare(MarkData o1,
MarkData o2) {
if (o1.index < o2.index) {
return -1;
} else if (o1.index > o2.index) {
return 1;
} else {
return 0;
}
}
|
public Position createPosition(int offset) throws BadLocationException {
while ( queue.poll() != null ) {
unusedMarks++;
}
if (unusedMarks > Math.max(5, (marks.size() / 10))) {
removeUnusedMarks();
}
int g0 = getGapStart();
int g1 = getGapEnd();
int index = (offset < g0) ? offset : offset + (g1 - g0);
search.index = index;
int sortIndex = findSortIndex(search);
MarkData m;
StickyPosition position;
if (sortIndex < marks.size()
&& (m = marks.elementAt(sortIndex)).index == index
&& (position = m.getPosition()) != null) {
//position references the correct StickyPostition
} else {
position = new StickyPosition();
m = new MarkData(index,position,queue);
position.setMark(m);
marks.insertElementAt(m, sortIndex);
}
return position;
}
Creates a position within the content that will
track change as the content is mutated. |
final int findMarkAdjustIndex(int searchIndex) {
search.index = Math.max(searchIndex, 1);
int index = findSortIndex(search);
// return the first in the series
// (ie. there may be duplicates).
for (int i = index - 1; i >= 0; i--) {
MarkData d = marks.elementAt(i);
if (d.index != search.index) {
break;
}
index -= 1;
}
return index;
}
Finds the index to start mark adjustments given
some search index. |
final int findSortIndex(MarkData o) {
int lower = 0;
int upper = marks.size() - 1;
int mid = 0;
if (upper == -1) {
return 0;
}
int cmp;
MarkData last = marks.elementAt(upper);
cmp = compare(o, last);
if (cmp > 0)
return upper + 1;
while (lower < = upper) {
mid = lower + ((upper - lower) / 2);
MarkData entry = marks.elementAt(mid);
cmp = compare(o, entry);
if (cmp == 0) {
// found a match
return mid;
} else if (cmp < 0) {
upper = mid - 1;
} else {
lower = mid + 1;
}
}
// didn't find it, but we indicate the index of where it would belong.
return (cmp < 0) ? mid : mid + 1;
}
Finds the index of where to insert a new mark. |
protected int getArrayLength() {
char[] carray = (char[]) getArray();
return carray.length;
}
Get the length of the allocated array. |
public void getChars(int where,
int len,
Segment chars) throws BadLocationException {
int end = where + len;
if (where < 0 || end < 0) {
throw new BadLocationException("Invalid location", -1);
}
if (end > length() || where > length()) {
throw new BadLocationException("Invalid location", length() + 1);
}
int g0 = getGapStart();
int g1 = getGapEnd();
char[] array = (char[]) getArray();
if ((where + len) < = g0) {
// below gap
chars.array = array;
chars.offset = where;
} else if (where >= g0) {
// above gap
chars.array = array;
chars.offset = g1 + where - g0;
} else {
// spans the gap
int before = g0 - where;
if (chars.isPartialReturn()) {
// partial return allowed, return amount before the gap
chars.array = array;
chars.offset = where;
chars.count = before;
return;
}
// partial return not allowed, must copy
chars.array = new char[len];
chars.offset = 0;
System.arraycopy(array, where, chars.array, 0, before);
System.arraycopy(array, g1, chars.array, before, len - before);
}
chars.count = len;
}
Retrieves a portion of the content. If the desired content spans
the gap, we copy the content. If the desired content does not
span the gap, the actual store is returned to avoid the copy since
it is contiguous. |
int getNewArraySize(int reqSize) {
if (reqSize < GROWTH_SIZE) {
return super.getNewArraySize(reqSize);
} else {
return reqSize + GROWTH_SIZE;
}
}
Overridden to make growth policy less agressive for large
text amount. |
protected Vector getPositionsInRange(Vector v,
int offset,
int length) {
int endOffset = offset + length;
int startIndex;
int endIndex;
int g0 = getGapStart();
int g1 = getGapEnd();
// Find the index of the marks.
if (offset < g0) {
if (offset == 0) {
// findMarkAdjustIndex start at 1!
startIndex = 0;
}
else {
startIndex = findMarkAdjustIndex(offset);
}
if (endOffset >= g0) {
endIndex = findMarkAdjustIndex(endOffset + (g1 - g0) + 1);
}
else {
endIndex = findMarkAdjustIndex(endOffset + 1);
}
}
else {
startIndex = findMarkAdjustIndex(offset + (g1 - g0));
endIndex = findMarkAdjustIndex(endOffset + (g1 - g0) + 1);
}
Vector placeIn = (v == null) ? new Vector(Math.max(1, endIndex -
startIndex)) : v;
for (int counter = startIndex; counter < endIndex; counter++) {
placeIn.addElement(new UndoPosRef(marks.elementAt(counter)));
}
return placeIn;
}
Returns a Vector containing instances of UndoPosRef for the
Positions in the range
offset to offset + length .
If v is not null the matching Positions are placed in
there. The vector with the resulting Positions are returned. |
public String getString(int where,
int len) throws BadLocationException {
Segment s = new Segment();
getChars(where, len, s);
return new String(s.array, s.offset, s.count);
}
Retrieves a portion of the content. |
public UndoableEdit insertString(int where,
String str) throws BadLocationException {
if (where > length() || where < 0) {
throw new BadLocationException("Invalid insert", length());
}
char[] chars = str.toCharArray();
replace(where, 0, chars, chars.length);
return new InsertUndo(where, str.length());
}
Inserts a string into the content. |
public int length() {
int len = getArrayLength() - (getGapEnd() - getGapStart());
return len;
}
Returns the length of the content. |
public UndoableEdit remove(int where,
int nitems) throws BadLocationException {
if (where + nitems >= length()) {
throw new BadLocationException("Invalid remove", length() + 1);
}
String removedString = getString(where, nitems);
UndoableEdit edit = new RemoveUndo(where, removedString);
replace(where, nitems, empty, 0);
return edit;
}
Removes part of the content. |
final void removeUnusedMarks() {
int n = marks.size();
MarkVector cleaned = new MarkVector(n);
for (int i = 0; i < n; i++) {
MarkData mark = marks.elementAt(i);
if (mark.get() != null) {
cleaned.addElement(mark);
}
}
marks = cleaned;
unusedMarks = 0;
}
Remove all unused marks out of the sorted collection
of marks. |
protected void resetMarksAtZero() {
if (marks != null && getGapStart() == 0) {
int g1 = getGapEnd();
for (int counter = 0, maxCounter = marks.size();
counter < maxCounter; counter++) {
MarkData mark = marks.elementAt(counter);
if (mark.index < = g1) {
mark.index = 0;
}
else {
break;
}
}
}
}
Resets all the marks that have an offset of 0 to have an index of
zero as well. |
protected void shiftEnd(int newSize) {
int oldGapEnd = getGapEnd();
super.shiftEnd(newSize);
// Adjust marks.
int dg = getGapEnd() - oldGapEnd;
int adjustIndex = findMarkAdjustIndex(oldGapEnd);
int n = marks.size();
for (int i = adjustIndex; i < n; i++) {
MarkData mark = marks.elementAt(i);
mark.index += dg;
}
}
Make the gap bigger, moving any necessary data and updating
the appropriate marks |
protected void shiftGap(int newGapStart) {
int oldGapStart = getGapStart();
int dg = newGapStart - oldGapStart;
int oldGapEnd = getGapEnd();
int newGapEnd = oldGapEnd + dg;
int gapSize = oldGapEnd - oldGapStart;
// shift gap in the character array
super.shiftGap(newGapStart);
// update the marks
if (dg > 0) {
// Move gap up, move data and marks down.
int adjustIndex = findMarkAdjustIndex(oldGapStart);
int n = marks.size();
for (int i = adjustIndex; i < n; i++) {
MarkData mark = marks.elementAt(i);
if (mark.index >= newGapEnd) {
break;
}
mark.index -= gapSize;
}
} else if (dg < 0) {
// Move gap down, move data and marks up.
int adjustIndex = findMarkAdjustIndex(newGapStart);
int n = marks.size();
for (int i = adjustIndex; i < n; i++) {
MarkData mark = marks.elementAt(i);
if (mark.index >= oldGapEnd) {
break;
}
mark.index += gapSize;
}
}
resetMarksAtZero();
}
Move the start of the gap to a new location,
without changing the size of the gap. This
moves the data in the array and updates the
marks accordingly. |
protected void shiftGapEndUp(int newGapEnd) {
int adjustIndex = findMarkAdjustIndex(getGapEnd());
int n = marks.size();
for (int i = adjustIndex; i < n; i++) {
MarkData mark = marks.elementAt(i);
if (mark.index >= newGapEnd) {
break;
}
mark.index = newGapEnd;
}
// shift the gap in the character array
super.shiftGapEndUp(newGapEnd);
resetMarksAtZero();
}
Adjust the gap end upward. This doesn't move
any data, but it does update any marks affected
by the boundary change. All marks from the old
gap end up to the new gap end are squeezed
to the end of the gap (their location has been
removed). |
protected void shiftGapStartDown(int newGapStart) {
// Push aside all marks from oldGapStart down to newGapStart.
int adjustIndex = findMarkAdjustIndex(newGapStart);
int n = marks.size();
int g0 = getGapStart();
int g1 = getGapEnd();
for (int i = adjustIndex; i < n; i++) {
MarkData mark = marks.elementAt(i);
if (mark.index > g0) {
// no more marks to adjust
break;
}
mark.index = g1;
}
// shift the gap in the character array
super.shiftGapStartDown(newGapStart);
resetMarksAtZero();
}
Adjust the gap end downward. This doesn't move
any data, but it does update any marks affected
by the boundary change. All marks from the old
gap start down to the new gap start are squeezed
to the end of the gap (their location has been
removed). |
protected void updateUndoPositions(Vector positions,
int offset,
int length) {
// Find the indexs of the end points.
int endOffset = offset + length;
int g1 = getGapEnd();
int startIndex;
int endIndex = findMarkAdjustIndex(g1 + 1);
if (offset != 0) {
startIndex = findMarkAdjustIndex(g1);
}
else {
startIndex = 0;
}
// Reset the location of the refenences.
for(int counter = positions.size() - 1; counter >= 0; counter--) {
UndoPosRef ref = (UndoPosRef)positions.elementAt(counter);
ref.resetLocation(endOffset, g1);
}
// We have to resort the marks in the range startIndex to endIndex.
// We can take advantage of the fact that it will be in
// increasing order, accept there will be a bunch of MarkData's with
// the index g1 (or 0 if offset == 0) interspersed throughout.
if (startIndex < endIndex) {
Object[] sorted = new Object[endIndex - startIndex];
int addIndex = 0;
int counter;
if (offset == 0) {
// If the offset is 0, the positions won't have incremented,
// have to do the reverse thing.
// Find the elements in startIndex whose index is 0
for (counter = startIndex; counter < endIndex; counter++) {
MarkData mark = marks.elementAt(counter);
if (mark.index == 0) {
sorted[addIndex++] = mark;
}
}
for (counter = startIndex; counter < endIndex; counter++) {
MarkData mark = marks.elementAt(counter);
if (mark.index != 0) {
sorted[addIndex++] = mark;
}
}
}
else {
for (counter = startIndex; counter < endIndex; counter++) {
MarkData mark = marks.elementAt(counter);
if (mark.index != g1) {
sorted[addIndex++] = mark;
}
}
for (counter = startIndex; counter < endIndex; counter++) {
MarkData mark = marks.elementAt(counter);
if (mark.index == g1) {
sorted[addIndex++] = mark;
}
}
}
// And replace
marks.replaceRange(startIndex, endIndex, sorted);
}
}
Resets the location for all the UndoPosRef instances
in positions .
This is meant for internal usage, and is generally not of interest
to subclasses. |