if(doc == null) return;
// slurp everything up into local variables in case another
// thread changes them during coloring process
AttributeSet globalStyle = doc.getGlobalStyle();
Lexer syntaxLexer = doc.getSyntaxLexer();
DocumentReader documentReader = doc.getDocumentReader();
Object docLock = doc.getDocumentLock();
if(globalStyle != null) {
int start = Math.min(position, position + adjustment);
int stop = Math.max(position, position + adjustment);
synchronized(docLock) {
doc.setCharacterAttributes(start, stop - start,
globalStyle, true);
}
return;
}
SortedSet workingSet;
Iterator workingIt;
DocPosition startRequest = new DocPosition(position);
DocPosition endRequest = new DocPosition(position + Math.abs(adjustment));
DocPosition dp;
DocPosition dpStart = null;
DocPosition dpEnd = null;
// find the starting position. We must start at least one
// token before the current position
try {
// all the good positions before
workingSet = iniPositions.headSet(startRequest);
// the last of the stuff before
dpStart = (DocPosition) workingSet.last();
} catch (NoSuchElementException x) {
// if there were no good positions before the requested
// start,
// we can always start at the very beginning.
dpStart = new DocPosition(0);
}
// if stuff was removed, take any removed positions off the
// list.
if (adjustment < 0) {
workingSet = iniPositions.subSet(startRequest,
endRequest);
workingIt = workingSet.iterator();
while (workingIt.hasNext()) {
workingIt.next();
workingIt.remove();
}
}
// adjust the positions of everything after the
// insertion/removal.
workingSet = iniPositions.tailSet(startRequest);
workingIt = workingSet.iterator();
while (workingIt.hasNext()) {
((DocPosition) workingIt.next()).adjustPosition(adjustment);
}
// now go through and highlight as much as needed
workingSet = iniPositions.tailSet(dpStart);
workingIt = workingSet.iterator();
dp = null;
if (workingIt.hasNext()) {
dp = (DocPosition) workingIt.next();
}
try {
Token t;
boolean done = false;
dpEnd = dpStart;
synchronized (docLock) {
// we are playing some games with the lexer for
// efficiency.
// we could just create a new lexer each time here,
// but instead,
// we will just reset it so that it thinks it is
// starting at the
// beginning of the document but reporting a funny
// start position.
// Reseting the lexer causes the close() method on
// the reader
// to be called but because the close() method has
// no effect on the
// DocumentReader, we can do this.
syntaxLexer.reset(documentReader, 0, dpStart
.getPosition(), 0);
// After the lexer has been set up, scroll the
// reader so that it
// is in the correct spot as well.
documentReader.seek(dpStart.getPosition());
// we will highlight tokens until we reach a good
// stopping place.
// the first obvious stopping place is the end of
// the document.
// the lexer will return null at the end of the
// document and wee
// need to stop there.
t = syntaxLexer.getNextToken();
}
newPositions.add(dpStart);
while (!done && t != null) {
// this is the actual command that colors the stuff.
// Color stuff with the description of the styles
// stored in tokenStyles.
if (t.getCharEnd() <= doc.getLength()) {
doc.setCharacterAttributes(t.getCharBegin() + change,
t.getCharEnd() - t.getCharBegin(),
TokenStyles.getStyle(t.getDescription()),
true);
// record the position of the last bit of
// text that we colored
dpEnd = new DocPosition(t.getCharEnd());
}
lastPosition = (t.getCharEnd() + change);
// The other more complicated reason for doing no
// more highlighting
// is that all the colors are the same from here on
// out anyway.
// We can detect this by seeing if the place that
// the lexer returned
// to the initial state last time we highlighted is
// the same as the
// place that returned to the initial state this
// time.
// As long as that place is after the last changed
// text, everything
// from there on is fine already.
if (t.getState() == Token.INITIAL_STATE) {
// look at all the positions from last time that
// are less than or
// equal to the current position
while (dp != null
&& dp.getPosition() <= t.getCharEnd()) {
if (dp.getPosition() == t.getCharEnd()
&& dp.getPosition() >= endRequest
.getPosition()) {
// we have found a state that is the
// same
done = true;
dp = null;
} else if (workingIt.hasNext()) {
// didn't find it, try again.
dp = (DocPosition) workingIt.next();
} else {
// didn't find it, and there is no more
// info from last
// time. This means that we will just
// continue
// until the end of the document.
dp = null;
}
}
// so that we can do this check next time,
// record all the
// initial states from this time.
newPositions.add(dpEnd);
}
synchronized (docLock) {
t = syntaxLexer.getNextToken();
}
}
// remove all the old initial positions from the place
// where