/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun * Microsystems, Inc. All Rights Reserved. */ package org.netbeans.editor; import javax.swing.text.BadLocationException; import javax.swing.text.Segment; import java.lang.ref.WeakReference; import java.util.ArrayList; /** * Encapsulation of a special static segment used * by syntax scanners. Unfortunately document cache cannot * guarantee that its fragment(s) will hold more than one character * at the time so syntax scanning cannot be done by finder. Instead * all the syntax analyzes are done over the syntax segment's data. * Although it's shared across all instances of editors * the loads into it should be fast as they are done from cache fragments * by arraycopy() method. * The syntax segment is separated into the slots because there * can be more scanning necessary at one time. * All the scanning must be done * * @author Miloslav Metelka * @version 1.00 */ class SyntaxSeg extends Segment { private static final char[] EMPTY_CHAR_ARRAY = new char[0]; private static final int MAX_SLOT_COUNT = 100; private static final int REALLOC_INCREMENT = 2048; private static ArrayList slotList = new ArrayList(); static synchronized Slot getFreeSlot() { int cnt = slotList.size(); return (cnt > 0) ? (Slot)slotList.remove(cnt - 1) : new Slot(); } static synchronized void releaseSlot(Slot slot) { slotList.add(slot); } /** From this position on, the data in syntax segment must be marked * invalid. */ static synchronized void invalidate(BaseDocument doc, int pos) { int cnt = slotList.size(); for (int i = 0; i < cnt; i++) { ((Slot)slotList.get(i)).invalidate(doc, pos); } } static class Slot extends Segment { /** Document from which the data in syntax segment come from */ WeakReference segDocRef = new WeakReference(null); /** Begining of valid data in syntax segment */ int segPos; /** Begining of valid data in syntax segment */ int segLen; Slot() { this.array = EMPTY_CHAR_ARRAY; } /** Load the syntax segment if necessary from some location in some * document. For best performance there's no pos or len correctness * checking. Therefore caller must guarantee the correctness. * @return real length that was loaded (syntax segment has limitation * in size) */ int load(BaseDocument doc, int pos, int len) throws BadLocationException { if (len <= 0) { if (len == 0) { count = 0; return 0; } throw new RuntimeException("len=" + len); // Critical error NOI18N } BaseDocument segDoc = (BaseDocument)segDocRef.get(); boolean difDoc = (doc != segDoc); if (difDoc) { segDoc = doc; segDocRef = new WeakReference(segDoc); } if (difDoc // different documents || pos < segPos // position too low || pos > segPos + segLen // position too high || pos - segPos + len > array.length ) { // wouldn't fit // possibly realloc the array if (len > array.length) { char tmp[] = new char[len + REALLOC_INCREMENT]; array = tmp; // original data are not recopied } segPos = pos; segLen = len; doc.getChars(pos, array, 0, len); // read chars into array } else { // inside array and will fit int endSegPos = segPos + segLen; int restLen = pos + len - endSegPos; if (restLen > 0) { // not fully inside doc.getChars(endSegPos, array, segLen, restLen); segLen += restLen; } } offset = pos - segPos; count = len; if (offset < 0 || len < 0) { throw new BadLocationException("pos=" + pos + ", offset=" + offset // NOI18N + "len=" + len, offset); // Critical error NOI18N } return len; } /** Is the area inside the segment? */ boolean isAreaInside(BaseDocument doc, int pos, int len) { return (doc == (BaseDocument)segDocRef.get() && pos >= segPos && pos + len <= segPos + segLen); } /** Invalidate the slot if it contains the data from the given document. * @param doc document in which the change occured * @param pos position in the document where the change occured */ void invalidate(BaseDocument doc, int pos) { if (doc == (BaseDocument)segDocRef.get()) { if (pos < segPos) { segLen = 0; } else if (pos < segPos + segLen) { segLen = pos - segPos; } } } } }