Importing the XDebugProxy code in the HEAD. The repo was tagged with T_BEFORE_XDEBUGP...
[phpeclipse.git] / net.sourceforge.phpeclipse.ui / src / net / sourceforge / phpeclipse / ui / text / rules / AbstractPartitioner.java
index d104237..04819c8 100644 (file)
@@ -8,7 +8,7 @@
  * Contributors:
  *     Igor Malinin - initial contribution
  * 
- * $Id: AbstractPartitioner.java,v 1.2 2004-11-13 12:36:32 axelcl Exp $
+ * $Id: AbstractPartitioner.java,v 1.4 2006-10-21 23:13:53 pombredanne Exp $
  */
 
 package net.sourceforge.phpeclipse.ui.text.rules;
@@ -29,546 +29,568 @@ import org.eclipse.jface.text.rules.IPartitionTokenScanner;
 import org.eclipse.jface.text.rules.IToken;
 
 /**
- * Advanced partitioner which maintains partitions as views to connected document. Views have own partitioners themselves. This
- * class is designed as a base for complex partitioners such as for JSP, PHP, ASP, etc. languages.
+ * Advanced partitioner which maintains partitions as views to connected
+ * document. Views have own partitioners themselves. This class is designed as a
+ * base for complex partitioners such as for JSP, PHP, ASP, etc. languages.
  * 
  * @author Igor Malinin
  */
-public abstract class AbstractPartitioner implements IDocumentPartitioner, IDocumentPartitionerExtension {
-  public final static boolean DEBUG = false;
-
-  /** Partition scanner */
-  protected IPartitionTokenScanner scanner;
-
-  /** Connected document */
-  protected IDocument document;
-
-  /** Flat structure of the document */
-  protected List nodes = new ArrayList();
-
-  /** The offset at which the first changed partition starts */
-  protected int regionStart;
-
-  /** The offset at which the last changed partition ends */
-  protected int regionEnd;
-
-  public AbstractPartitioner(IPartitionTokenScanner scanner) {
-    this.scanner = scanner;
-  }
-
-  protected FlatNode createNode(String type, int offset, int length) {
-    if (DEBUG) {
-      Assert.isTrue(offset >= 0, Integer.toString(offset));
-    }
-    FlatNode node = new FlatNode(type);
-    node.offset = offset;
-    node.length = length;
-    return node;
-  }
-
-  protected void addInnerRegion(FlatNode position) {
-    nodes.add(computeFlatNodeIndex(position.offset), position);
-  }
-
-  protected void removeInnerRegion(FlatNode position) {
-    nodes.remove(position); // TODO: Indexed remove?
-  }
-
-  protected void deleteInnerRegion(FlatNode position) {
-    nodes.remove(position); // TODO: Indexed remove?
-  }
-
-  protected void resizeInnerRegion(FlatNode position) {
-  }
-
-  /*
-   * @see org.eclipse.jface.text.IDocumentPartitioner#connect(IDocument)
-   */
-  public void connect(IDocument document) {
-    this.document = document;
-
-    initialize();
-  }
-
-  /*
-   * @see org.eclipse.jface.text.IDocumentPartitioner#disconnect()
-   */
-  public void disconnect() {
-    nodes.clear();
-    document = null;
-  }
-
-  /**
-   * Performs the initial partitioning of the partitioner's document.
-   */
-  protected void initialize() {
-    scanner.setRange(document, 0, document.getLength());
-    nodes.clear();
-    IToken token = scanner.nextToken();
-    while (!token.isEOF()) {
-      String contentType = getTokenContentType(token);
-
-      if (isSupportedContentType(contentType)) {
-        addInnerRegion(createNode(contentType, scanner.getTokenOffset(), scanner.getTokenLength()));
-      }
-
-      token = scanner.nextToken();
-    }
-  }
-
-  /*
-   * @see org.eclipse.jface.text.IDocumentPartitioner#documentAboutToBeChanged(DocumentEvent)
-   */
-  public void documentAboutToBeChanged(DocumentEvent event) {
-    regionStart = regionEnd = -1;
-  }
-
-  /*
-   * @see org.eclipse.jface.text.IDocumentPartitioner#documentChanged(DocumentEvent)
-   */
-  public boolean documentChanged(DocumentEvent event) {
-    return (documentChanged2(event) != null);
-  }
-
-  /*
-   * @see org.eclipse.jface.text.IDocumentPartitionerExtension#documentChanged2(DocumentEvent)
-   */
-  public IRegion documentChanged2(DocumentEvent event) {
-    int first = fixupPartitions(event);
-
-    FlatNode[] category = (FlatNode[]) nodes.toArray(new FlatNode[nodes.size()]);
-
-    // repartition changed region
-
-    String contentType = IDocument.DEFAULT_CONTENT_TYPE;
-
-    int offset;
-
-    if (first == 0) {
-      offset = 0; // Bug #697414: first offset
-    } else {
-      offset = event.getOffset();
-
-      FlatNode partition = category[first - 1];
-      if (partition.includes(offset)) {
-        offset = partition.offset;
-        contentType = partition.type;
-        --first;
-      } else if (offset == partition.offset + partition.length) {
-        offset = partition.offset;
-        contentType = partition.type;
-        --first;
-      } else {
-        offset = partition.offset + partition.length;
-      }
-    }
-
-    // should not be changed since last conversion
-    // category = (FlatNode[]) nodes.toArray(new FlatNode[nodes.size()]);
-    if (DEBUG) {
-      Assert.isTrue(offset >= 0, Integer.toString(offset));
-    }
-    scanner.setPartialRange(document, offset, document.getLength(), contentType, offset);
-
-    int lastScannedPosition = offset;
-    IToken token = scanner.nextToken();
-    while (!token.isEOF()) {
-      contentType = getTokenContentType(token);
-
-      if (!isSupportedContentType(contentType)) {
-        token = scanner.nextToken();
-        continue;
-      }
-
-      offset = scanner.getTokenOffset();
-      if (DEBUG) {
-        Assert.isTrue(offset >= 0, scanner.toString());
-      }
-      int length = scanner.getTokenLength();
-
-      lastScannedPosition = offset + length;
-
-      // remove all affected positions
-      while (first < category.length) {
-        FlatNode p = category[first];
-        if (p.offset + p.length < lastScannedPosition
-            || (p.overlapsWith(offset, length) && (!containsPosition(offset, length) || !contentType.equals(p.type)))) {
-          removeInnerRegion(p);
-          rememberRegion(p.offset, p.length);
-          ++first;
-        } else {
-          break;
-        }
-      }
-
-      // if position already exists we are done
-      if (containsPosition(offset, length)) {
-        if (lastScannedPosition > event.getOffset()) {
-          // TODO: optional repartition till end of doc
-          return createRegion();
-        }
-
-        ++first;
-      } else {
-        // insert the new type position
-        addInnerRegion(createNode(contentType, offset, length));
-        rememberRegion(offset, length);
-      }
-      //            try {
-      token = scanner.nextToken();
-      //            } catch (ArrayIndexOutOfBoundsException e) {
-      //              System.out.println(this.getClass().toString());
-      //              throw e;
-      //            }
-    }
-
-    // remove all positions behind lastScannedPosition
-    // since there aren't any further types
-
-    // Do not need to recalculate (lost remove events)!
-    // first = computeIndexInInnerDocuments(lastScannedPosition);
-    while (first < category.length) {
-      FlatNode p = category[first++];
-      removeInnerRegion(p);
-      rememberRegion(p.offset, p.length);
-    }
-
-    return createRegion();
-  }
-
-  protected int fixupPartitions(DocumentEvent event) {
-    int offset = event.getOffset();
-    int length = event.getLength();
-    int end = offset + length;
-
-    // fixup flat nodes laying on change boundaries
-
-    int first = computeFlatNodeIndex(offset);
-    if (first > 0) {
-      FlatNode p = (FlatNode) nodes.get(first - 1);
-
-      int right = p.offset + p.length;
-      if (offset < right) {
-        // change overlaps with partition
-        if (end < right) {
-          // cahnge completely inside partition
-          String text = event.getText();
-          p.length -= length;
-          if (text != null) {
-            p.length += text.length();
-          }
-        } else {
-          // cut partition at right
-          int cut = p.offset + p.length - offset;
-          p.length -= cut;
-        }
-      }
-    }
-
-    int last = computeFlatNodeIndex(end);
-    if (first < last) {
-      FlatNode p = (FlatNode) nodes.get(last - 1);
-
-      int right = p.offset + p.length;
-      if (end < right) {
-        // cut partition at left
-        int cut = end - p.offset;
-        p.length -= cut;
-        p.offset = offset;
-
-        String text = event.getText();
-        if (text != null) {
-          p.offset += text.length();
-        }
-
-        --last;
-      }
-    }
-
-    // fixup flat nodes laying afrer change
-
-    String text = event.getText();
-    if (text != null) {
-      length -= text.length();
-    }
-
-    for (int i = last, size = nodes.size(); i < size; i++) {
-      ((FlatNode) nodes.get(i)).offset -= length;
-    }
-
-    // delete flat nodes laying completely inside change boundaries
-
-    if (first < last) {
-      do {
-        deleteInnerRegion((FlatNode) nodes.get(--last));
-      } while (first < last);
-
-      rememberRegion(offset, 0);
-    }
-
-    return first;
-  }
-
-  /**
-   * Returns whether the given type is one of the legal content types.
-   * 
-   * @param contentType
-   *          the content type to check
-   * @return <code>true</code> if the content type is a legal content type
-   */
-  protected boolean isSupportedContentType(String contentType) {
-    /* TODO: implementation */
-    //         if (contentType != null) {
-    //                 for (int i= 0; i < fLegalContentTypes.length; i++) {
-    //                         if (fLegalContentTypes[i].equals(contentType)) {
-    //                                 return true;
-    //                         }
-    //                 }
-    //         }
-    //         return false;
-    return (contentType != null);
-  }
-
-  /**
-   * Returns a content type encoded in the given token. If the token's data is not <code>null</code> and a string it is assumed
-   * that it is the encoded content type.
-   * 
-   * @param token
-   *          the token whose content type is to be determined
-   * @return the token's content type
-   */
-  protected String getTokenContentType(IToken token) {
-    Object data = token.getData();
-    if (data instanceof String) {
-      return (String) data;
-    }
-
-    return null;
-  }
-
-  /*
-   * @see org.eclipse.jface.text.IDocumentPartitioner#getLegalContentTypes()
-   */
-  public String[] getLegalContentTypes() {
-    // TODO: implementation
-    return null;
-  }
-
-  /*
-   * @see org.eclipse.jface.text.IDocumentPartitioner#getContentType(int)
-   */
-  public String getContentType(int offset) {
-    return getPartition(offset).getType();
-  }
-
-  /*
-   * @see org.eclipse.jface.text.IDocumentPartitioner#getPartition(int)
-   */
-  public ITypedRegion getPartition(int offset) {
-    if (nodes.size() == 0) {
-      return new TypedRegion(0, document.getLength(), IDocument.DEFAULT_CONTENT_TYPE);
-    }
-
-    int index = computeFlatNodeIndex(offset);
-    if (index < nodes.size()) {
-      FlatNode next = (FlatNode) nodes.get(index);
-
-      if (offset == next.offset) {
-        return new TypedRegion(next.offset, next.length, next.type);
-      }
-
-      if (index == 0) {
-        return new TypedRegion(0, next.offset, IDocument.DEFAULT_CONTENT_TYPE);
-      }
-
-      FlatNode prev = (FlatNode) nodes.get(index - 1);
-
-      if (prev.includes(offset)) {
-        return new TypedRegion(prev.offset, prev.length, prev.type);
-      }
-
-      int end = prev.offset + prev.length;
-      return new TypedRegion(end, next.offset - end, IDocument.DEFAULT_CONTENT_TYPE);
-    }
-
-    FlatNode prev = (FlatNode) nodes.get(nodes.size() - 1);
-
-    if (prev.includes(offset)) {
-      return new TypedRegion(prev.offset, prev.length, prev.type);
-    }
-
-    int end = prev.offset + prev.length;
-
-    return new TypedRegion(end, document.getLength() - end, IDocument.DEFAULT_CONTENT_TYPE);
-  }
-
-  /*
-   * @see org.eclipse.jface.text.IDocumentPartitioner#computePartitioning(int, int)
-   */
-  public ITypedRegion[] computePartitioning(int offset, int length) {
-    List list = new ArrayList();
-
-    int end = offset + length;
-
-    int index = computeFlatNodeIndex(offset);
-    while (true) {
-      FlatNode prev = (index > 0) ? (FlatNode) nodes.get(index - 1) : null;
-
-      if (prev != null) {
-        if (prev.overlapsWith(offset, length)) {
-          list.add(new TypedRegion(prev.offset, prev.length, prev.type));
-        }
-
-        if (end <= prev.offset + prev.length) {
-          break;
-        }
-      }
-
-      FlatNode next = (index < nodes.size()) ? (FlatNode) nodes.get(index) : null;
-
-      if (next == null || offset < next.offset) {
-        int off0 = offset;
-        int off1 = offset + length;
-
-        if (prev != null && off0 < prev.offset + prev.length) {
-          off0 = prev.offset + prev.length;
-        }
-
-        if (next != null && next.offset < off1) {
-          off1 = next.offset;
-        }
-
-        if (off0 < off1) {
-          list.add(new TypedRegion(off0, off1 - off0, IDocument.DEFAULT_CONTENT_TYPE));
-        }
-      }
-
-      if (next == null) {
-        break;
-      }
-
-      ++index;
-    }
-
-    return (TypedRegion[]) list.toArray(new TypedRegion[list.size()]);
-  }
-
-  /**
-   * Computes the index in the list of flat nodes at which an flat node with the given offset would be inserted. The flat node is
-   * supposed to become the first in this list of all flat nodes with the same offset.
-   * 
-   * @param offset
-   *          the offset for which the index is computed
-   * @return the computed index
-   */
-  protected int computeFlatNodeIndex(int offset) {
-    if (nodes.size() == 0) {
-      return 0;
-    }
-
-    int left = 0, mid = 0;
-    int right = nodes.size() - 1;
-
-    FlatNode p = null;
-
-    while (left < right) {
-      mid = (left + right) / 2;
-
-      p = (FlatNode) nodes.get(mid);
-
-      if (offset < p.offset) {
-        right = (left == mid) ? left : mid - 1;
-      } else if (offset > p.offset) {
-        left = (right == mid) ? right : mid + 1;
-      } else if (offset == p.offset) {
-        left = right = mid;
-      }
-    }
-
-    int pos = left;
-    p = (FlatNode) nodes.get(pos);
-    if (offset > p.offset) {
-      // append to the end
-      pos++;
-    } else {
-      // entry will became the first of all entries with the same offset
-      do {
-        --pos;
-        if (pos < 0) {
-          break;
-        }
-        p = (FlatNode) nodes.get(pos);
-      } while (offset == p.offset);
-      ++pos;
-    }
-
-    return pos;
-  }
-
-  public boolean containsPosition(int offset, int length) {
-    int size = nodes.size();
-    if (size == 0) {
-      return false;
-    }
-
-    int index = computeFlatNodeIndex(offset);
-    if (index < size) {
-      FlatNode p = (FlatNode) nodes.get(index);
-
-      while (p.offset == offset) {
-        if (p.length == length) {
-          return true;
-        }
-
-        if (++index < size) {
-          p = (FlatNode) nodes.get(index);
-        } else {
-          break;
-        }
-      }
-    }
-
-    return false;
-  }
-
-  /**
-   * Helper method for tracking the minimal region containg all partition changes. If <code>offset</code> is smaller than the
-   * remembered offset, <code>offset</code> will from now on be remembered. If <code>offset + length</code> is greater than the
-   * remembered end offset, it will be remembered from now on.
-   * 
-   * @param offset
-   *          the offset
-   * @param length
-   *          the length
-   */
-  protected final void rememberRegion(int offset, int length) {
-    // remember start offset
-    if (regionStart == -1) {
-      regionStart = offset;
-    } else if (offset < regionStart) {
-      regionStart = offset;
-    }
-
-    // remember end offset
-    int endOffset = offset + length;
-
-    if (regionEnd == -1) {
-      regionEnd = endOffset;
-    } else if (endOffset > regionEnd) {
-      regionEnd = endOffset;
-    }
-  }
-
-  /**
-   * Creates the minimal region containing all partition changes using the remembered offsets.
-   * 
-   * @return the minimal region containing all the partition changes
-   */
-  protected final IRegion createRegion() {
-    if (regionStart == -1 || regionEnd == -1) {
-      return null;
-    }
-
-    return new Region(regionStart, regionEnd - regionStart);
-  }
+public abstract class AbstractPartitioner implements IDocumentPartitioner,
+               IDocumentPartitionerExtension {
+       public final static boolean DEBUG = false;
+
+       /** Partition scanner */
+       protected IPartitionTokenScanner scanner;
+
+       /** Connected document */
+       protected IDocument document;
+
+       /** Flat structure of the document */
+       protected List nodes = new ArrayList();
+
+       /** The offset at which the first changed partition starts */
+       protected int regionStart;
+
+       /** The offset at which the last changed partition ends */
+       protected int regionEnd;
+
+       public AbstractPartitioner(IPartitionTokenScanner scanner) {
+               this.scanner = scanner;
+       }
+
+       protected FlatNode createNode(String type, int offset, int length) {
+               if (DEBUG) {
+                       Assert.isTrue(offset >= 0, Integer.toString(offset));
+               }
+               FlatNode node = new FlatNode(type);
+               node.offset = offset;
+               node.length = length;
+               return node;
+       }
+
+       protected void addInnerRegion(FlatNode position) {
+               nodes.add(computeFlatNodeIndex(position.offset), position);
+       }
+
+       protected void removeInnerRegion(FlatNode position) {
+               nodes.remove(position); // TODO: Indexed remove?
+       }
+
+       protected void deleteInnerRegion(FlatNode position) {
+               nodes.remove(position); // TODO: Indexed remove?
+       }
+
+       protected void resizeInnerRegion(FlatNode position) {
+       }
+
+       /*
+        * @see org.eclipse.jface.text.IDocumentPartitioner#connect(IDocument)
+        */
+       public void connect(IDocument document) {
+               this.document = document;
+
+               initialize();
+       }
+
+       /*
+        * @see org.eclipse.jface.text.IDocumentPartitioner#disconnect()
+        */
+       public void disconnect() {
+               nodes.clear();
+               document = null;
+       }
+
+       /**
+        * Performs the initial partitioning of the partitioner's document.
+        */
+       protected void initialize() {
+               scanner.setRange(document, 0, document.getLength());
+               // axelcl start
+               nodes.clear();
+               // axelcl end
+               IToken token = scanner.nextToken();
+               while (!token.isEOF()) {
+                       String contentType = getTokenContentType(token);
+
+                       if (isSupportedContentType(contentType)) {
+                               addInnerRegion(createNode(contentType,
+                                               scanner.getTokenOffset(), scanner.getTokenLength()));
+                       }
+
+                       token = scanner.nextToken();
+               }
+       }
+
+       /*
+        * @see org.eclipse.jface.text.IDocumentPartitioner#documentAboutToBeChanged(DocumentEvent)
+        */
+       public void documentAboutToBeChanged(DocumentEvent event) {
+               regionStart = regionEnd = -1;
+       }
+
+       /*
+        * @see org.eclipse.jface.text.IDocumentPartitioner#documentChanged(DocumentEvent)
+        */
+       public boolean documentChanged(DocumentEvent event) {
+               return (documentChanged2(event) != null);
+       }
+
+       /*
+        * @see org.eclipse.jface.text.IDocumentPartitionerExtension#documentChanged2(DocumentEvent)
+        */
+       public IRegion documentChanged2(DocumentEvent event) {
+               int first = fixupPartitions(event);
+
+               FlatNode[] category = (FlatNode[]) nodes.toArray(new FlatNode[nodes
+                               .size()]);
+
+               // repartition changed region
+
+               String contentType = IDocument.DEFAULT_CONTENT_TYPE;
+
+               int offset;
+
+               if (first == 0) {
+                       offset = 0; // Bug #697414: first offset
+               } else {
+                       offset = event.getOffset();
+
+                       FlatNode partition = category[first - 1];
+                       if (partition.includes(offset)) {
+                               offset = partition.offset;
+                               contentType = partition.type;
+                               --first;
+                       } else if (offset == partition.offset + partition.length) {
+                               offset = partition.offset;
+                               contentType = partition.type;
+                               --first;
+                       } else {
+                               offset = partition.offset + partition.length;
+                       }
+               }
+
+               // should not be changed since last conversion
+               // category = (FlatNode[]) nodes.toArray(new FlatNode[nodes.size()]);
+               if (DEBUG) {
+                       Assert.isTrue(offset >= 0, Integer.toString(offset));
+               }
+               scanner.setPartialRange(document, offset, document.getLength(),
+                               contentType, offset);
+
+               int lastScannedPosition = offset;
+               IToken token = scanner.nextToken();
+               while (!token.isEOF()) {
+                       contentType = getTokenContentType(token);
+
+                       if (!isSupportedContentType(contentType)) {
+                               token = scanner.nextToken();
+                               continue;
+                       }
+
+                       offset = scanner.getTokenOffset();
+                       if (DEBUG) {
+                               Assert.isTrue(offset >= 0, scanner.toString());
+                       }
+                       int length = scanner.getTokenLength();
+
+                       lastScannedPosition = offset + length;
+
+                       // remove all affected positions
+                       while (first < category.length) {
+                               FlatNode p = category[first];
+                               if (p.offset + p.length < lastScannedPosition
+                                               || (p.overlapsWith(offset, length) && (!containsPosition(
+                                                               offset, length) || !contentType.equals(p.type)))) {
+                                       removeInnerRegion(p);
+                                       rememberRegion(p.offset, p.length);
+                                       ++first;
+                               } else {
+                                       break;
+                               }
+                       }
+
+                       // if position already exists we are done
+                       if (containsPosition(offset, length)) {
+                               if (lastScannedPosition > event.getOffset()) {
+                                       // TODO: optional repartition till end of doc
+                                       return createRegion();
+                               }
+
+                               ++first;
+                       } else {
+                               // insert the new type position
+                               addInnerRegion(createNode(contentType, offset, length));
+                               rememberRegion(offset, length);
+                       }
+                       // try {
+                       token = scanner.nextToken();
+                       // } catch (ArrayIndexOutOfBoundsException e) {
+                       // System.out.println(this.getClass().toString());
+                       // throw e;
+                       // }
+               }
+
+               // remove all positions behind lastScannedPosition
+               // since there aren't any further types
+
+               // Do not need to recalculate (lost remove events)!
+               // first = computeIndexInInnerDocuments(lastScannedPosition);
+               while (first < category.length) {
+                       FlatNode p = category[first++];
+                       removeInnerRegion(p);
+                       rememberRegion(p.offset, p.length);
+               }
+
+               return createRegion();
+       }
+
+       protected int fixupPartitions(DocumentEvent event) {
+               int offset = event.getOffset();
+               int length = event.getLength();
+               int end = offset + length;
+
+               // fixup flat nodes laying on change boundaries
+
+               int first = computeFlatNodeIndex(offset);
+               if (first > 0) {
+                       FlatNode p = (FlatNode) nodes.get(first - 1);
+
+                       int right = p.offset + p.length;
+                       if (offset < right) {
+                               // change overlaps with partition
+                               if (end < right) {
+                                       // cahnge completely inside partition
+                                       String text = event.getText();
+                                       p.length -= length;
+                                       if (text != null) {
+                                               p.length += text.length();
+                                       }
+                               } else {
+                                       // cut partition at right
+                                       int cut = p.offset + p.length - offset;
+                                       p.length -= cut;
+                               }
+                       }
+               }
+
+               int last = computeFlatNodeIndex(end);
+               if (first < last) {
+                       FlatNode p = (FlatNode) nodes.get(last - 1);
+
+                       int right = p.offset + p.length;
+                       if (end < right) {
+                               // cut partition at left
+                               int cut = end - p.offset;
+                               p.length -= cut;
+                               p.offset = offset;
+
+                               String text = event.getText();
+                               if (text != null) {
+                                       p.offset += text.length();
+                               }
+
+                               --last;
+                       }
+               }
+
+               // fixup flat nodes laying afrer change
+
+               String text = event.getText();
+               if (text != null) {
+                       length -= text.length();
+               }
+
+               for (int i = last, size = nodes.size(); i < size; i++) {
+                       ((FlatNode) nodes.get(i)).offset -= length;
+               }
+
+               // delete flat nodes laying completely inside change boundaries
+
+               if (first < last) {
+                       do {
+                               deleteInnerRegion((FlatNode) nodes.get(--last));
+                       } while (first < last);
+
+                       rememberRegion(offset, 0);
+               }
+
+               return first;
+       }
+
+       /**
+        * Returns whether the given type is one of the legal content types.
+        * 
+        * @param contentType
+        *            the content type to check
+        * @return <code>true</code> if the content type is a legal content type
+        */
+       protected boolean isSupportedContentType(String contentType) {
+               /* TODO: implementation */
+               // if (contentType != null) {
+               // for (int i= 0; i < fLegalContentTypes.length; i++) {
+               // if (fLegalContentTypes[i].equals(contentType)) {
+               // return true;
+               // }
+               // }
+               // }
+               // return false;
+               return (contentType != null);
+       }
+
+       /**
+        * Returns a content type encoded in the given token. If the token's data is
+        * not <code>null</code> and a string it is assumed that it is the encoded
+        * content type.
+        * 
+        * @param token
+        *            the token whose content type is to be determined
+        * @return the token's content type
+        */
+       protected String getTokenContentType(IToken token) {
+               Object data = token.getData();
+               if (data instanceof String) {
+                       return (String) data;
+               }
+
+               return null;
+       }
+
+       /*
+        * @see org.eclipse.jface.text.IDocumentPartitioner#getLegalContentTypes()
+        */
+       public String[] getLegalContentTypes() {
+               // TODO: implementation
+               return null;
+       }
+
+       /*
+        * @see org.eclipse.jface.text.IDocumentPartitioner#getContentType(int)
+        */
+       public String getContentType(int offset) {
+               return getPartition(offset).getType();
+       }
+
+       /*
+        * @see org.eclipse.jface.text.IDocumentPartitioner#getPartition(int)
+        */
+       public ITypedRegion getPartition(int offset) {
+               if (nodes.size() == 0) {
+                       return new TypedRegion(0, document.getLength(),
+                                       IDocument.DEFAULT_CONTENT_TYPE);
+               }
+
+               int index = computeFlatNodeIndex(offset);
+               if (index < nodes.size()) {
+                       FlatNode next = (FlatNode) nodes.get(index);
+
+                       if (offset == next.offset) {
+                               return new TypedRegion(next.offset, next.length, next.type);
+                       }
+
+                       if (index == 0) {
+                               return new TypedRegion(0, next.offset,
+                                               IDocument.DEFAULT_CONTENT_TYPE);
+                       }
+
+                       FlatNode prev = (FlatNode) nodes.get(index - 1);
+
+                       if (prev.includes(offset)) {
+                               return new TypedRegion(prev.offset, prev.length, prev.type);
+                       }
+
+                       int end = prev.offset + prev.length;
+                       return new TypedRegion(end, next.offset - end,
+                                       IDocument.DEFAULT_CONTENT_TYPE);
+               }
+
+               FlatNode prev = (FlatNode) nodes.get(nodes.size() - 1);
+
+               if (prev.includes(offset)) {
+                       return new TypedRegion(prev.offset, prev.length, prev.type);
+               }
+
+               int end = prev.offset + prev.length;
+
+               return new TypedRegion(end, document.getLength() - end,
+                               IDocument.DEFAULT_CONTENT_TYPE);
+       }
+
+       /*
+        * @see org.eclipse.jface.text.IDocumentPartitioner#computePartitioning(int,
+        *      int)
+        */
+       public ITypedRegion[] computePartitioning(int offset, int length) {
+               List list = new ArrayList();
+
+               int end = offset + length;
+
+               int index = computeFlatNodeIndex(offset);
+               while (true) {
+                       FlatNode prev = (index > 0) ? (FlatNode) nodes.get(index - 1)
+                                       : null;
+
+                       if (prev != null) {
+                               if (prev.overlapsWith(offset, length)) {
+                                       list.add(new TypedRegion(prev.offset, prev.length,
+                                                       prev.type));
+                               }
+
+                               if (end <= prev.offset + prev.length) {
+                                       break;
+                               }
+                       }
+
+                       FlatNode next = (index < nodes.size()) ? (FlatNode) nodes
+                                       .get(index) : null;
+
+                       if (next == null || offset < next.offset) {
+                               int off0 = offset;
+                               int off1 = offset + length;
+
+                               if (prev != null && off0 < prev.offset + prev.length) {
+                                       off0 = prev.offset + prev.length;
+                               }
+
+                               if (next != null && next.offset < off1) {
+                                       off1 = next.offset;
+                               }
+
+                               if (off0 < off1) {
+                                       list.add(new TypedRegion(off0, off1 - off0,
+                                                       IDocument.DEFAULT_CONTENT_TYPE));
+                               }
+                       }
+
+                       if (next == null) {
+                               break;
+                       }
+
+                       ++index;
+               }
+
+               return (TypedRegion[]) list.toArray(new TypedRegion[list.size()]);
+       }
+
+       /**
+        * Computes the index in the list of flat nodes at which an flat node with
+        * the given offset would be inserted. The flat node is supposed to become
+        * the first in this list of all flat nodes with the same offset.
+        * 
+        * @param offset
+        *            the offset for which the index is computed
+        * @return the computed index
+        */
+       protected int computeFlatNodeIndex(int offset) {
+               if (nodes.size() == 0) {
+                       return 0;
+               }
+
+               int left = 0, mid = 0;
+               int right = nodes.size() - 1;
+
+               FlatNode p = null;
+
+               while (left < right) {
+                       mid = (left + right) / 2;
+
+                       p = (FlatNode) nodes.get(mid);
+
+                       if (offset < p.offset) {
+                               right = (left == mid) ? left : mid - 1;
+                       } else if (offset > p.offset) {
+                               left = (right == mid) ? right : mid + 1;
+                       } else if (offset == p.offset) {
+                               left = right = mid;
+                       }
+               }
+
+               int pos = left;
+               p = (FlatNode) nodes.get(pos);
+               if (offset > p.offset) {
+                       // append to the end
+                       pos++;
+               } else {
+                       // entry will became the first of all entries with the same offset
+                       do {
+                               --pos;
+                               if (pos < 0) {
+                                       break;
+                               }
+                               p = (FlatNode) nodes.get(pos);
+                       } while (offset == p.offset);
+                       ++pos;
+               }
+
+               return pos;
+       }
+
+       public boolean containsPosition(int offset, int length) {
+               int size = nodes.size();
+               if (size == 0) {
+                       return false;
+               }
+
+               int index = computeFlatNodeIndex(offset);
+               if (index < size) {
+                       FlatNode p = (FlatNode) nodes.get(index);
+
+                       while (p.offset == offset) {
+                               if (p.length == length) {
+                                       return true;
+                               }
+
+                               if (++index < size) {
+                                       p = (FlatNode) nodes.get(index);
+                               } else {
+                                       break;
+                               }
+                       }
+               }
+
+               return false;
+       }
+
+       /**
+        * Helper method for tracking the minimal region containg all partition
+        * changes. If <code>offset</code> is smaller than the remembered offset,
+        * <code>offset</code> will from now on be remembered. If
+        * <code>offset + length</code> is greater than the remembered end offset,
+        * it will be remembered from now on.
+        * 
+        * @param offset
+        *            the offset
+        * @param length
+        *            the length
+        */
+       protected final void rememberRegion(int offset, int length) {
+               // remember start offset
+               if (regionStart == -1) {
+                       regionStart = offset;
+               } else if (offset < regionStart) {
+                       regionStart = offset;
+               }
+
+               // remember end offset
+               int endOffset = offset + length;
+
+               if (regionEnd == -1) {
+                       regionEnd = endOffset;
+               } else if (endOffset > regionEnd) {
+                       regionEnd = endOffset;
+               }
+       }
+
+       /**
+        * Creates the minimal region containing all partition changes using the
+        * remembered offsets.
+        * 
+        * @return the minimal region containing all the partition changes
+        */
+       protected final IRegion createRegion() {
+               if (regionStart == -1 || regionEnd == -1) {
+                       return null;
+               }
+
+               return new Region(regionStart, regionEnd - regionStart);
+       }
 }
\ No newline at end of file