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 / MultiViewPartitioner.java
index c5aa8ec..c51a4aa 100644 (file)
@@ -8,7 +8,7 @@
  * Contributors:
  *     Igor Malinin - initial contribution
  * 
- * $Id: MultiViewPartitioner.java,v 1.1 2004-09-02 18:26:29 jsurfer Exp $
+ * $Id: MultiViewPartitioner.java,v 1.10 2006-10-21 23:13:53 pombredanne Exp $
  */
 
 package net.sourceforge.phpeclipse.ui.text.rules;
@@ -29,628 +29,778 @@ import org.eclipse.jface.text.TypedRegion;
 import org.eclipse.jface.text.rules.IPartitionTokenScanner;
 
 /**
- * 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 MultiViewPartitioner extends AbstractPartitioner {
 
-  class ViewListener implements IDocumentPartitioningListener, IDocumentPartitioningListenerExtension {
-
-    /*
-     * @see org.eclipse.jface.text.IDocumentPartitioningListener#documentPartitioningChanged(IDocument)
-     */
-    public void documentPartitioningChanged(IDocument document) {
-      IDocumentView view = (IDocumentView) document;
-
-      int start = view.getParentOffset(0);
-      int end = view.getParentOffset(view.getLength());
-
-      rememberRegion(start, end - start);
-    }
-
-    /*
-     * @see org.eclipse.jface.text.IDocumentPartitioningListenerExtension#documentPartitioningChanged(IDocument, IRegion)
-     */
-    public void documentPartitioningChanged(IDocument document, IRegion region) {
-      IDocumentView view = (IDocumentView) document;
-
-      int offset = region.getOffset();
-
-      int start = view.getParentOffset(offset);
-      int end = view.getParentOffset(offset + region.getLength());
-
-      rememberRegion(start, end - start);
-    }
-  }
-
-  private ViewListener viewListener = new ViewListener();
-
-  private OuterDocumentView outerDocument;
-
-  private DocumentEvent outerDocumentEvent;
-
-  public MultiViewPartitioner(IPartitionTokenScanner scanner) {
-    super(scanner);
-  }
-
-  public void setOuterPartitioner(IDocumentPartitioner partitioner) {
-    if (outerDocument == null) {
-      if (partitioner == null) {
-        return;
-      }
-
-      outerDocument = new OuterDocumentView(document, nodes);
-      outerDocument.addDocumentPartitioningListener(viewListener);
-    }
-
-    IDocumentPartitioner old = outerDocument.getDocumentPartitioner();
-    if (old != null) {
-      outerDocument.setDocumentPartitioner(null);
-      old.disconnect();
-    }
-
-    if (partitioner != null) {
-      partitioner.connect(outerDocument);
-    }
-
-    outerDocument.setDocumentPartitioner(partitioner);
-
-    if (partitioner == null) {
-      outerDocument.removeDocumentPartitioningListener(viewListener);
-      outerDocument = null;
-    }
-  }
-
-  /**
-   * Create subpartitioner.
-   * 
-   * @param contentType
-   *          name of inner partition or <code>null</code> for outer partition
-   */
-  protected abstract IDocumentPartitioner createPartitioner(String contentType);
-
-  protected void addInnerRegion(FlatNode position) {
-    if (outerDocument != null) {
-      if (DEBUG) {
-        Assert.isTrue(position.offset >= 0, Integer.toString(position.offset));
-      }
-      DocumentEvent event = new DocumentEvent(outerDocument, outerDocument.getLocalOffset(position.offset), position.length, null);
-
-      outerDocument.fireDocumentAboutToBeChanged(event);
-      super.addInnerRegion(position);
-      outerDocument.fireDocumentChanged(event);
-    } else {
-      super.addInnerRegion(position);
-    }
-
-    if (position instanceof ViewNode) {
-      // TODO: revisit condition
-      IDocumentPartitioner partitioner = createPartitioner(position.type);
-      if (partitioner != null) {
-        InnerDocumentView innerDocument = new InnerDocumentView(document, (ViewNode) position);
-
-        ((ViewNode) position).view = innerDocument;
-
-        partitioner.connect(innerDocument);
-        innerDocument.setDocumentPartitioner(partitioner);
-        innerDocument.addDocumentPartitioningListener(viewListener);
-      }
-    }
-  }
-
-  protected void removeInnerRegion(FlatNode position) {
-    try {
-      if (outerDocument != null) {
-        DocumentEvent event = null;
-        if (position.offset >= 0) {
-          event = new DocumentEvent(outerDocument, outerDocument.getLocalOffset(position.offset), 0, document.get(position.offset,
-              position.length));
-
-          outerDocument.fireDocumentAboutToBeChanged(event);
-        }
-        super.removeInnerRegion(position);
-        if (position.offset >= 0) {
-          outerDocument.fireDocumentChanged(event);
-        }
-      } else {
-        super.removeInnerRegion(position);
-      }
-
-      if (position instanceof ViewNode) {
-        // TODO: revisit condition
-        InnerDocumentView innerDocument = ((ViewNode) position).view;
-        if (innerDocument != null) {
-          IDocumentPartitioner partitioner = innerDocument.getDocumentPartitioner();
-
-          innerDocument.removeDocumentPartitioningListener(viewListener);
-          innerDocument.setDocumentPartitioner(null);
-          partitioner.disconnect();
-        }
-      }
-    } catch (BadLocationException e) {
-    }
-  }
-
-  protected void deleteInnerRegion(FlatNode position) {
-    super.deleteInnerRegion(position);
-
-    if (position instanceof ViewNode) {
-      // TODO: revisit condition
-      InnerDocumentView innerDocument = ((ViewNode) position).view;
-      if (innerDocument != null) {
-        IDocumentPartitioner partitioner = innerDocument.getDocumentPartitioner();
-
-        innerDocument.removeDocumentPartitioningListener(viewListener);
-        innerDocument.setDocumentPartitioner(null);
-        partitioner.disconnect();
-      }
-    }
-  }
-
-  public void connect(IDocument document) {
-    //         outerDocument = new OuterDocumentView(document, innerPositions);
-
-    super.connect(document);
-
-    setOuterPartitioner(createPartitioner(null));
-    //         IDocumentPartitioner partitioner =
-    //                 partitioner.connect(outerDocument);
-    //         outerDocument.setDocumentPartitioner(partitioner);
-    //         outerDocument.addDocumentPartitioningListener(viewListener);
-  }
-
-  public void disconnect() {
-    try {
-      if (outerDocument != null) {
-        outerDocument.removeDocumentPartitioningListener(viewListener);
-
-        IDocumentPartitioner partitioner = outerDocument.getDocumentPartitioner();
-
-        outerDocument.setDocumentPartitioner(null);
-        partitioner.disconnect();
-      }
-    } finally {
-      // TODO: cleanup listeners
-      outerDocument = null;
-    }
-  }
-
-  /*
-   * @see org.eclipse.jface.text.IDocumentPartitioner#documentAboutToBeChanged(DocumentEvent)
-   */
-  public void documentAboutToBeChanged(DocumentEvent event) {
-    super.documentAboutToBeChanged(event);
-
-    outerDocumentEvent = null;
-
-    int offset = event.getOffset();
-    int length = event.getLength();
-    int end = offset + length;
-
-    // find left partition
-    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
-        InnerDocumentView innerDocument = null;
-        if (p instanceof ViewNode) {
-          // TODO: revisit condition
-          innerDocument = ((ViewNode) p).view;
-        }
-
-        if (end < right) {
-          if (innerDocument != null) {
-            // cahnge completely inside partition
-            int start = innerDocument.getLocalOffset(offset);
-            innerDocument.fireDocumentAboutToBeChanged(new DocumentEvent(innerDocument, start, length, event.getText()));
-          }
-
-          return;
-        }
-
-        if (innerDocument != null) {
-          // cut partition at right
-          int start = innerDocument.getLocalOffset(offset);
-          innerDocument.fireDocumentAboutToBeChanged(new DocumentEvent(innerDocument, start, innerDocument.getLength() - start,
-              null));
-        }
-      }
-    }
-
-    // find right partition
-    int last = computeFlatNodeIndex(end);
-    if (last > 0) {
-      FlatNode p = (FlatNode) nodes.get(last - 1);
-
-      if (p instanceof ViewNode) {
-        // TODO: revisit condition
-        InnerDocumentView innerDocument = ((ViewNode) p).view;
-        if (innerDocument != null) {
-          int right = p.offset + p.length;
-          if (end < right) {
-            // cut partition at left
-            int cut = innerDocument.getLocalOffset(end);
-            innerDocument.fireDocumentAboutToBeChanged(new DocumentEvent(innerDocument, 0, cut, null));
-          }
-        }
-      }
-    }
-
-    if (outerDocument != null) {
-      int left = outerDocument.getLocalOffset(offset);
-      int right = outerDocument.getLocalOffset(end);
-
-      String text = event.getText();
-
-      if (left != right || text != null && text.length() > 0) {
-        outerDocumentEvent = new DocumentEvent(outerDocument, left, right - left, text);
-
-        outerDocument.fireDocumentAboutToBeChanged(outerDocumentEvent);
-      }
-    }
-  }
-
-  protected int fixupPartitions(DocumentEvent event) {
-    int offset = event.getOffset();
-    int length = event.getLength();
-    int end = offset + length;
-
-    // fixup/notify inner views 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();
-          }
-
-          if (p instanceof ViewNode) {
-            // TODO: revisit condition
-            InnerDocumentView innerDocument = ((ViewNode) p).view;
-            if (innerDocument != null) {
-              int start = innerDocument.getLocalOffset(offset);
-              innerDocument.fireDocumentChanged(new DocumentEvent(innerDocument, start, length, text));
-            }
-          }
-        } else {
-          // cut partition at right
-          int cut = p.offset + p.length - offset;
-          p.length -= cut;
-
-          if (p instanceof ViewNode) {
-            // TODO: revisit condition
-            InnerDocumentView innerDocument = ((ViewNode) p).view;
-            if (innerDocument != null) {
-              int start = innerDocument.getLocalOffset(offset);
-              // TODO: ???fireDocumentAboutToBeChanged???
-              innerDocument.fireDocumentChanged(new DocumentEvent(innerDocument, start, cut, null));
-            }
-          }
-        }
-      }
-    }
-
-    int last = computeFlatNodeIndex(end);
-    if (last > 0 && 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();
-        }
-
-        if (p instanceof ViewNode) {
-          // TODO: revisit condition
-          InnerDocumentView innerDocument = ((ViewNode) p).view;
-          if (innerDocument != null) {
-            // TODO: ???fireDocumentAboutToBeChanged???
-            innerDocument.fireDocumentChanged(new DocumentEvent(innerDocument, 0, cut, null));
-          }
-        }
-
-        --last;
-      }
-    }
-
-    // fixup inner views 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 inner views laying completely inside change boundaries
-
-    if (first < last) {
-      do {
-        deleteInnerRegion((FlatNode) nodes.get(--last));
-      } while (first < last);
-
-      rememberRegion(offset, 0);
-    }
-
-    // notify outer view
-
-    if (outerDocumentEvent != null) {
-      outerDocument.fireDocumentChanged(outerDocumentEvent);
-    }
-
-    return first;
-  }
-
-  /*
-   * @see org.eclipse.jface.text.IDocumentPartitioner#computePartitioning(int, int)
-   */
-  protected String getContentType(String parent, String view) {
-    if (view != null) {
-      return view;
-    }
-
-    if (parent != null) {
-      return parent;
-    }
-
-    return 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)) {
-          addInnerPartitions(list, offset, length, prev);
-        }
-
-        if (end <= prev.offset + prev.length) {
-          break;
-        }
-      }
-
-      FlatNode next = (index < nodes.size()) ? (FlatNode) nodes.get(index) : null;
-
-      if (next == null || offset < next.offset) {
-        addOuterPartitions(list, offset, length, prev, next);
-      }
-
-      if (next == null) {
-        break;
-      }
-
-      ++index;
-    }
-
-    return (TypedRegion[]) list.toArray(new TypedRegion[list.size()]);
-  }
-
-  private void addOuterPartitions(List list, int offset, int length, FlatNode prev, FlatNode next) {
-    // limit region
-    int start = offset;
-    int end = offset + length;
-
-    if (prev != null && start < prev.offset + prev.length) {
-      start = prev.offset + prev.length;
-    }
-
-    if (next != null && next.offset < end) {
-      end = next.offset;
-    }
-
-    if (start == end) {
-      return;
-    }
-
-    if (outerDocument == null) {
-      list.add(new TypedRegion(start, end - start, getContentType(null, IDocument.DEFAULT_CONTENT_TYPE)));
-      return;
-    }
-
-    try {
-      // convert to outer offsets
-      start = outerDocument.getLocalOffset(start);
-      end = outerDocument.getLocalOffset(end);
-      if (end - start >= 0) {//jsurfer insert line
-        ITypedRegion[] regions = outerDocument.computePartitioning(start, end - start);
-
-        for (int i = 0; i < regions.length; i++) {
-          ITypedRegion region = regions[i];
-
-          // convert back to parent offsets
-          start = outerDocument.getParentOffset(region.getOffset());
-          end = start + region.getLength();
-
-          if (prev != null) {
-            offset = prev.offset + prev.length;
-            if (start < offset) {
-              start = offset;
-            }
-          }
-
-          if (next != null) {
-            offset = next.offset;
-            if (offset < end) {
-              end = offset;
-            }
-          }
-
-          list.add(new TypedRegion(start, end - start, getContentType(null, region.getType())));
-        }
-      }
-    } catch (BadLocationException x) {
-    }
-  }
-
-  private void addInnerPartitions(List list, int offset, int length, FlatNode position) {
-    InnerDocumentView innerDocument = null;
-    if (position instanceof ViewNode) {
-      // TODO: revisit condition
-      innerDocument = ((ViewNode) position).view;
-    }
-
-    if (innerDocument == null) {
-      // simple partition
-      list.add(new TypedRegion(position.offset, position.length, getContentType(position.type, null)));
-      return;
-    }
-
-    // multiplexing to inner view
-    try {
-      // limit region
-      int start = Math.max(offset, position.offset);
-      int end = Math.min(offset + length, position.offset + position.length);
-
-      // convert to document offsets
-      length = end - start;
-      offset = innerDocument.getLocalOffset(start);
-
-      ITypedRegion[] regions = innerDocument.computePartitioning(offset, length);
-
-      for (int i = 0; i < regions.length; i++) {
-        ITypedRegion region = regions[i];
-
-        // convert back to parent offsets
-        offset = innerDocument.getParentOffset(region.getOffset());
-        length = region.getLength();
-
-        list.add(new TypedRegion(offset, length, getContentType(position.type, region.getType())));
-      }
-    } catch (BadLocationException x) {
-    }
-  }
-
-  /*
-   * @see org.eclipse.jface.text.IDocumentPartitioner#getPartition(int)
-   */
-  public ITypedRegion getPartition(int offset) {
-    if (nodes.size() == 0) {
-      return getOuterPartition(offset, null, null);
-    }
-
-    int index = computeFlatNodeIndex(offset);
-    if (index < nodes.size()) {
-      FlatNode next = (FlatNode) nodes.get(index);
-
-      if (offset == next.offset) {
-        return getInnerPartition(offset, next);
-      }
-
-      if (index == 0) {
-        return getOuterPartition(offset, null, next);
-      }
-
-      FlatNode prev = (FlatNode) nodes.get(index - 1);
-
-      if (prev.includes(offset)) {
-        return getInnerPartition(offset, prev);
-      }
-
-      return getOuterPartition(offset, prev, next);
-    }
-
-    FlatNode prev = (FlatNode) nodes.get(nodes.size() - 1);
-
-    if (prev.includes(offset)) {
-      return getInnerPartition(offset, prev);
-    }
-
-    return getOuterPartition(offset, prev, null);
-  }
-
-  protected ITypedRegion getOuterPartition(int offset, FlatNode prev, FlatNode next) {
-    try {
-      int start, end;
-      String type;
-
-      if (outerDocument == null) {
-        start = 0;
-        end = document.getLength();
-        type = getContentType(null, IDocument.DEFAULT_CONTENT_TYPE);
-      } else {
-        ITypedRegion region = outerDocument.getPartition(outerDocument.getLocalOffset(offset));
-
-        start = region.getOffset();
-        end = start + region.getLength();
-
-        // convert to parent offset
-        start = outerDocument.getParentOffset(start);
-        end = outerDocument.getParentOffset(end);
-
-        type = getContentType(null, region.getType());
-      }
-
-      if (prev != null) {
-        offset = prev.offset + prev.length;
-        if (start < offset) {
-          start = offset;
-        }
-      }
-
-      if (next != null) {
-        offset = next.offset;
-        if (offset < end) {
-          end = offset;
-        }
-      }
-
-      return new TypedRegion(start, end - start, type);
-    } catch (BadLocationException x) {
-      throw new IllegalArgumentException();
-    }
-  }
-
-  protected ITypedRegion getInnerPartition(int offset, FlatNode position) {
-    if (position instanceof ViewNode) {
-      // TODO: revisit condition
-      InnerDocumentView innerDocument = ((ViewNode) position).view;
-
-      if (innerDocument != null) {
-        // multiplexing to inner view
-        try {
-          // convert to inner offset
-          ITypedRegion region = innerDocument.getPartition(innerDocument.getLocalOffset(offset));
-
-          // convert to parent offset
-          offset = innerDocument.getParentOffset(region.getOffset());
-
-          return new TypedRegion(offset, region.getLength(), getContentType(position.type, region.getType()));
-        } catch (BadLocationException x) {
-        }
-      }
-    }
-
-    // simple partition
-    return new TypedRegion(position.offset, position.length, position.type);
-  }
+       class ViewListener implements IDocumentPartitioningListener,
+                       IDocumentPartitioningListenerExtension {
+
+               /*
+                * @see org.eclipse.jface.text.IDocumentPartitioningListener#documentPartitioningChanged(IDocument)
+                */
+               public void documentPartitioningChanged(IDocument document) {
+                       IDocumentView view = (IDocumentView) document;
+
+                       int start = view.getParentOffset(0);
+                       int end = view.getParentOffset(view.getLength());
+
+                       rememberRegion(start, end - start);
+               }
+
+               /*
+                * @see org.eclipse.jface.text.IDocumentPartitioningListenerExtension#documentPartitioningChanged(IDocument,
+                *      IRegion)
+                */
+               public void documentPartitioningChanged(IDocument document,
+                               IRegion region) {
+                       IDocumentView view = (IDocumentView) document;
+
+                       int offset = region.getOffset();
+
+                       int start = view.getParentOffset(offset);
+                       int end = view.getParentOffset(offset + region.getLength());
+
+                       rememberRegion(start, end - start);
+               }
+       }
+
+       private ViewListener viewListener = new ViewListener();
+
+       private OuterDocumentView outerDocument;
+
+       private DocumentEvent outerDocumentEvent;
+
+       public MultiViewPartitioner(IPartitionTokenScanner scanner) {
+               super(scanner);
+       }
+
+       public void setOuterPartitioner(IDocumentPartitioner partitioner) {
+               if (outerDocument == null) {
+                       if (partitioner == null) {
+                               return;
+                       }
+
+                       outerDocument = new OuterDocumentView(document, nodes);
+                       outerDocument.addDocumentPartitioningListener(viewListener);
+               }
+
+               IDocumentPartitioner old = outerDocument.getDocumentPartitioner();
+               if (old != null) {
+                       outerDocument.setDocumentPartitioner(null);
+                       old.disconnect();
+               }
+
+               if (partitioner != null) {
+                       partitioner.connect(outerDocument);
+               }
+
+               outerDocument.setDocumentPartitioner(partitioner);
+
+               if (partitioner == null) {
+                       outerDocument.removeDocumentPartitioningListener(viewListener);
+                       outerDocument = null;
+               }
+       }
+
+       /**
+        * Create subpartitioner.
+        * 
+        * @param contentType
+        *            name of inner partition or <code>null</code> for outer
+        *            partition
+        */
+       protected abstract IDocumentPartitioner createPartitioner(String contentType);
+
+       protected void addInnerRegion(FlatNode position) {
+               if (outerDocument != null) {
+                       if (DEBUG) {
+                               Assert.isTrue(position.offset >= 0, Integer
+                                               .toString(position.offset));
+                       }
+                       int outerOffset = outerDocument.getLocalOffset(position.offset);
+                       // axelcl start
+                       DocumentEvent event = null;
+                       if (outerOffset >= 0) {
+                               // axelcl end
+                               event = new DocumentEvent(outerDocument, outerOffset,
+                                               position.length, null);
+
+                               outerDocument.fireDocumentAboutToBeChanged(event);
+                       }
+                       super.addInnerRegion(position);
+                       // axelcl start
+                       if (event != null) {
+                               // axelcl end
+                               outerDocument.fireDocumentChanged(event);
+                       }
+               } else {
+                       super.addInnerRegion(position);
+               }
+
+               if (position instanceof ViewNode) {
+                       // TODO: revisit condition
+                       IDocumentPartitioner partitioner = createPartitioner(position.type);
+                       if (partitioner != null) {
+                               InnerDocumentView innerDocument = new InnerDocumentView(
+                                               document, (ViewNode) position);
+
+                               ((ViewNode) position).view = innerDocument;
+
+                               partitioner.connect(innerDocument);
+                               innerDocument.setDocumentPartitioner(partitioner);
+                               innerDocument.addDocumentPartitioningListener(viewListener);
+                       }
+               }
+       }
+
+       protected void removeInnerRegion(FlatNode position) {
+               try {
+                       if (outerDocument != null) {
+                               DocumentEvent event = null;
+                               if (position.offset >= 0 && position.length >= 0) {
+                                       int outerOffset = outerDocument
+                                                       .getLocalOffset(position.offset);
+                                       if (outerOffset > 0) {
+                                               event = new DocumentEvent(outerDocument, outerOffset,
+                                                               0, document.get(position.offset,
+                                                                               position.length));
+
+                                               outerDocument.fireDocumentAboutToBeChanged(event);
+                                       }
+                               }
+                               super.removeInnerRegion(position);
+                               if (position.offset >= 0) {
+                                       if (event != null) {
+                                               outerDocument.fireDocumentChanged(event);
+                                       }
+                               }
+                       } else {
+                               super.removeInnerRegion(position);
+                       }
+
+                       if (position instanceof ViewNode) {
+                               // TODO: revisit condition
+                               InnerDocumentView innerDocument = ((ViewNode) position).view;
+                               if (innerDocument != null) {
+                                       IDocumentPartitioner partitioner = innerDocument
+                                                       .getDocumentPartitioner();
+
+                                       innerDocument
+                                                       .removeDocumentPartitioningListener(viewListener);
+                                       innerDocument.setDocumentPartitioner(null);
+                                       partitioner.disconnect();
+                               }
+                       }
+               } catch (BadLocationException e) {
+               }
+       }
+
+       protected void deleteInnerRegion(FlatNode position) {
+               super.deleteInnerRegion(position);
+
+               if (position instanceof ViewNode) {
+                       // TODO: revisit condition
+                       InnerDocumentView innerDocument = ((ViewNode) position).view;
+                       if (innerDocument != null) {
+                               IDocumentPartitioner partitioner = innerDocument
+                                               .getDocumentPartitioner();
+
+                               innerDocument.removeDocumentPartitioningListener(viewListener);
+                               innerDocument.setDocumentPartitioner(null);
+                               partitioner.disconnect();
+                       }
+               }
+       }
+
+       public void connect(IDocument document) {
+               // outerDocument = new OuterDocumentView(document, innerPositions);
+
+               super.connect(document);
+
+               setOuterPartitioner(createPartitioner(null));
+               // IDocumentPartitioner partitioner =
+               // partitioner.connect(outerDocument);
+               // outerDocument.setDocumentPartitioner(partitioner);
+               // outerDocument.addDocumentPartitioningListener(viewListener);
+       }
+
+       public void disconnect() {
+               try {
+                       if (outerDocument != null) {
+                               outerDocument.removeDocumentPartitioningListener(viewListener);
+
+                               IDocumentPartitioner partitioner = outerDocument
+                                               .getDocumentPartitioner();
+
+                               outerDocument.setDocumentPartitioner(null);
+                               partitioner.disconnect();
+                       }
+               } finally {
+                       // TODO: cleanup listeners
+                       outerDocument = null;
+               }
+       }
+
+       /*
+        * @see org.eclipse.jface.text.IDocumentPartitioner#documentAboutToBeChanged(DocumentEvent)
+        */
+       public void documentAboutToBeChanged(DocumentEvent event) {
+               super.documentAboutToBeChanged(event);
+
+               outerDocumentEvent = null;
+
+               int offset = event.getOffset();
+               int length = event.getLength();
+               int end = offset + length;
+
+               // find left partition
+               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
+                               InnerDocumentView innerDocument = null;
+                               if (p instanceof ViewNode) {
+                                       // TODO: revisit condition
+                                       innerDocument = ((ViewNode) p).view;
+                               }
+
+                               if (end < right) {
+                                       if (innerDocument != null) {
+                                               // cahnge completely inside partition
+                                               int start = innerDocument.getLocalOffset(offset);
+                                               innerDocument
+                                                               .fireDocumentAboutToBeChanged(new DocumentEvent(
+                                                                               innerDocument, start, length, event
+                                                                                               .getText()));
+                                       }
+
+                                       return;
+                               }
+
+                               if (innerDocument != null) {
+                                       // cut partition at right
+                                       int start = innerDocument.getLocalOffset(offset);
+                                       innerDocument
+                                                       .fireDocumentAboutToBeChanged(new DocumentEvent(
+                                                                       innerDocument, start, innerDocument
+                                                                                       .getLength()
+                                                                                       - start, null));
+                               }
+                       }
+               }
+
+               // find right partition
+               int last = computeFlatNodeIndex(end);
+               if (last > 0) {
+                       FlatNode p = (FlatNode) nodes.get(last - 1);
+
+                       if (p instanceof ViewNode) {
+                               // TODO: revisit condition
+                               InnerDocumentView innerDocument = ((ViewNode) p).view;
+                               if (innerDocument != null) {
+                                       int right = p.offset + p.length;
+                                       if (end < right) {
+                                               // cut partition at left
+                                               int cut = innerDocument.getLocalOffset(end);
+                                               innerDocument
+                                                               .fireDocumentAboutToBeChanged(new DocumentEvent(
+                                                                               innerDocument, 0, cut, null));
+                                       }
+                               }
+                       }
+               }
+
+               if (outerDocument != null) {
+                       int left = outerDocument.getLocalOffset(offset);
+                       int right = outerDocument.getLocalOffset(end);
+
+                       String text = event.getText();
+
+                       if (left >= 0 && (right - left >= 0)) {
+                               if (left != right || text != null && text.length() > 0) {
+                                       outerDocumentEvent = new DocumentEvent(outerDocument, left,
+                                                       right - left, text);
+
+                                       outerDocument
+                                                       .fireDocumentAboutToBeChanged(outerDocumentEvent);
+                               }
+                       }
+               }
+       }
+
+       protected int fixupPartitions(DocumentEvent event) {
+               int offset = event.getOffset();
+               int length = event.getLength();
+               int end = offset + length;
+
+               // fixup/notify inner views 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();
+                                       }
+
+                                       if (p instanceof ViewNode) {
+                                               // TODO: revisit condition
+                                               InnerDocumentView innerDocument = ((ViewNode) p).view;
+                                               if (innerDocument != null) {
+                                                       int start = innerDocument.getLocalOffset(offset);
+                                                       innerDocument
+                                                                       .fireDocumentChanged(new DocumentEvent(
+                                                                                       innerDocument, start, length, text));
+                                               }
+                                       }
+                               } else {
+                                       // cut partition at right
+                                       int cut = p.offset + p.length - offset;
+                                       p.length -= cut;
+
+                                       if (p instanceof ViewNode) {
+                                               // TODO: revisit condition
+                                               InnerDocumentView innerDocument = ((ViewNode) p).view;
+                                               if (innerDocument != null) {
+                                                       int start = innerDocument.getLocalOffset(offset);
+                                                       // TODO: ???fireDocumentAboutToBeChanged???
+                                                       innerDocument
+                                                                       .fireDocumentChanged(new DocumentEvent(
+                                                                                       innerDocument, start, cut, null));
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               int last = computeFlatNodeIndex(end);
+               if (last > 0 && 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();
+                               }
+
+                               if (p instanceof ViewNode) {
+                                       // TODO: revisit condition
+                                       InnerDocumentView innerDocument = ((ViewNode) p).view;
+                                       if (innerDocument != null) {
+                                               // TODO: ???fireDocumentAboutToBeChanged???
+                                               innerDocument.fireDocumentChanged(new DocumentEvent(
+                                                               innerDocument, 0, cut, null));
+                                       }
+                               }
+
+                               --last;
+                       }
+               }
+
+               // fixup inner views 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 inner views laying completely inside change boundaries
+
+               if (first < last) {
+                       do {
+                               deleteInnerRegion((FlatNode) nodes.get(--last));
+                       } while (first < last);
+
+                       rememberRegion(offset, 0);
+               }
+
+               // notify outer view
+
+               if (outerDocumentEvent != null) {
+                       outerDocument.fireDocumentChanged(outerDocumentEvent);
+               }
+
+               return first;
+       }
+
+       /*
+        * @see org.eclipse.jface.text.IDocumentPartitioner#computePartitioning(int,
+        *      int)
+        */
+       protected String getContentType(String parent, String view) {
+               if (view != null) {
+                       return view;
+               }
+
+               if (parent != null) {
+                       return parent;
+               }
+
+               return IDocument.DEFAULT_CONTENT_TYPE;
+       }
+
+       /*
+        * @see org.eclipse.jface.text.IDocumentPartitioner#computePartitioning(int,
+        *      int)
+        */
+       public ITypedRegion[] computePartitioning(int offset, int length) {
+               List list = new ArrayList();
+               // if (DEBUG) {
+               // if (length>=9400) {
+               // length--;
+               // }
+               // System.out.print("MultiViewPartitioner::computePartitioning - Offset:
+               // ");
+               // System.out.print(offset);
+               // System.out.print(", Length: ");
+               // System.out.print(length);
+               // System.out.println("");
+               // }
+               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)) {
+                                       addInnerPartitions(list, offset, length, prev);
+                               }
+
+                               if (end <= prev.offset + prev.length) {
+                                       break;
+                               }
+                       }
+
+                       FlatNode next = (index < nodes.size()) ? (FlatNode) nodes
+                                       .get(index) : null;
+
+                       if (next == null || offset < next.offset) {
+                               addOuterPartitions(list, offset, length, prev, next);
+                       }
+
+                       if (next == null) {
+                               break;
+                       }
+
+                       ++index;
+               }
+               // if (DEBUG) {
+               // showList(list);
+               // }
+
+               return (TypedRegion[]) list.toArray(new TypedRegion[list.size()]);
+       }
+
+       private void showList(List list) {
+               try {
+                       throw new NullPointerException();
+               } catch (Exception e) {
+                       e.printStackTrace();
+               }
+               System.out.println(">>>>>List start");
+               TypedRegion temp;
+               for (int i = 0; i < list.size(); i++) {
+                       temp = (TypedRegion) list.get(i);
+                       System.out.print("Offset: ");
+                       System.out.print(temp.getOffset());
+                       System.out.print(", Length: ");
+                       System.out.print(temp.getLength());
+                       System.out.print(", Type: ");
+                       System.out.print(temp.getType());
+                       System.out.println("");
+               }
+               System.out.println("<<<<<List end");
+       }
+
+       private void addOuterPartitions(List list, int offset, int length,
+                       FlatNode prev, FlatNode next) {
+               // limit region
+               int start = offset;
+               int end = offset + length;
+
+               if (prev != null && start < prev.offset + prev.length) {
+                       start = prev.offset + prev.length;
+               }
+
+               if (next != null && next.offset < end) {
+                       end = next.offset;
+               }
+
+               if (start == end) {
+                       return;
+               }
+
+               if (outerDocument == null) {
+                       // if (DEBUG) {
+                       // if (end - start<0) {
+                       // throw new IndexOutOfBoundsException();
+                       // }
+                       // }
+                       list.add(new TypedRegion(start, end - start, getContentType(null,
+                                       IDocument.DEFAULT_CONTENT_TYPE)));
+                       return;
+               }
+
+               try {
+                       // convert to outer offsets
+                       start = outerDocument.getLocalOffset(start);
+                       end = outerDocument.getLocalOffset(end);
+                       int len = end - start;
+                       if (len >= 0) {
+                               ITypedRegion[] regions = null;
+                               try {
+                                       regions = outerDocument.computePartitioning(start, len);
+                               } catch (Exception e) {
+                                       // nasty workaround, which prevents cursor from moveing
+                                       // backwards in the editor
+                                       // but doesn't solve the partitioning problem
+                                       regions = new ITypedRegion[0];
+                                       System.out
+                                                       .println("MultiViewerPartitioner#addOuterPartitions failure\n"
+                                                                       + "start:"
+                                                                       + start
+                                                                       + " length:"
+                                                                       + len
+                                                                       + "\n" + outerDocument.get(start, len));
+                               }
+                               for (int i = 0; i < regions.length; i++) {
+                                       ITypedRegion region = regions[i];
+
+                                       // convert back to parent offsets
+                                       start = outerDocument.getParentOffset(region.getOffset());
+                                       end = start + region.getLength();
+
+                                       if (prev != null) {
+                                               offset = prev.offset + prev.length;
+                                               if (start < offset) {
+                                                       start = offset;
+                                               }
+                                       }
+
+                                       if (next != null) {
+                                               offset = next.offset;
+                                               if (offset < end) {
+                                                       end = offset;
+                                               }
+                                       }
+                                       // if (DEBUG) {
+                                       // if (end - start<0) {
+                                       // showList(list);
+                                       // System.out.print("MultiViewPartitioner::addOuterPartitions
+                                       // - Offset: ");
+                                       // System.out.print(offset);
+                                       // System.out.print(", Start: ");
+                                       // System.out.print(start);
+                                       // System.out.print(", End: ");
+                                       // System.out.print(end);
+                                       // System.out.print(", Type: ");
+                                       // System.out.print(region.getType());
+                                       // System.out.println("");
+                                       // throw new IndexOutOfBoundsException();
+                                       // }
+                                       // }
+                                       list.add(new TypedRegion(start, end - start,
+                                                       getContentType(null, region.getType())));
+                               }
+                       }
+               } catch (BadLocationException x) {
+               }
+       }
+
+       private void addInnerPartitions(List list, int offset, int length,
+                       FlatNode position) {
+               InnerDocumentView innerDocument = null;
+               if (position instanceof ViewNode) {
+                       // TODO: revisit condition
+                       innerDocument = ((ViewNode) position).view;
+               }
+
+               if (innerDocument == null) {
+                       // simple partition
+                       // if (DEBUG) {
+                       // if (position.length<0) {
+                       // throw new IndexOutOfBoundsException();
+                       // }
+                       // }
+                       list.add(new TypedRegion(position.offset, position.length,
+                                       getContentType(position.type, null)));
+                       return;
+               }
+
+               // multiplexing to inner view
+               try {
+                       // limit region
+                       int start = Math.max(offset, position.offset);
+                       int end = Math.min(offset + length, position.offset
+                                       + position.length);
+
+                       // convert to document offsets
+                       length = end - start;
+                       offset = innerDocument.getLocalOffset(start);
+
+                       ITypedRegion[] regions = innerDocument.computePartitioning(offset,
+                                       length);
+
+                       for (int i = 0; i < regions.length; i++) {
+                               ITypedRegion region = regions[i];
+
+                               // convert back to parent offsets
+                               offset = innerDocument.getParentOffset(region.getOffset());
+                               length = region.getLength();
+                               // if (DEBUG) {
+                               // if (length<0) {
+                               // throw new IndexOutOfBoundsException();
+                               // }
+                               // }
+                               list.add(new TypedRegion(offset, length, getContentType(
+                                               position.type, region.getType())));
+                       }
+               } catch (BadLocationException x) {
+               }
+       }
+
+       /*
+        * @see org.eclipse.jface.text.IDocumentPartitioner#getPartition(int)
+        */
+       public ITypedRegion getPartition(int offset) {
+               if (nodes.size() == 0) {
+                       return getOuterPartition(offset, null, null);
+               }
+
+               int index = computeFlatNodeIndex(offset);
+               if (index < nodes.size()) {
+                       FlatNode next = (FlatNode) nodes.get(index);
+
+                       if (offset == next.offset) {
+                               return getInnerPartition(offset, next);
+                       }
+
+                       if (index == 0) {
+                               return getOuterPartition(offset, null, next);
+                       }
+
+                       FlatNode prev = (FlatNode) nodes.get(index - 1);
+
+                       if (prev.includes(offset)) {
+                               return getInnerPartition(offset, prev);
+                       }
+
+                       return getOuterPartition(offset, prev, next);
+               }
+
+               FlatNode prev = (FlatNode) nodes.get(nodes.size() - 1);
+
+               if (prev.includes(offset)) {
+                       return getInnerPartition(offset, prev);
+               }
+
+               return getOuterPartition(offset, prev, null);
+       }
+
+       protected ITypedRegion getOuterPartition(int offset, FlatNode prev,
+                       FlatNode next) {
+               try {
+                       int start, end;
+                       String type;
+
+                       if (outerDocument == null) {
+                               start = 0;
+                               end = document.getLength();
+                               type = getContentType(null, IDocument.DEFAULT_CONTENT_TYPE);
+                       } else {
+                               int outerOffset = outerDocument.getLocalOffset(offset);
+                               // axelcl start
+                               if (outerOffset < 0) {
+                                       start = 0;
+                                       end = document.getLength();
+                                       type = getContentType(null, IDocument.DEFAULT_CONTENT_TYPE);
+                               } else {
+                                       // axelcl end
+                                       ITypedRegion region = outerDocument
+                                                       .getPartition(outerOffset);
+
+                                       start = region.getOffset();
+                                       end = start + region.getLength();
+
+                                       // convert to parent offset
+                                       start = outerDocument.getParentOffset(start);
+                                       end = outerDocument.getParentOffset(end);
+
+                                       type = getContentType(null, region.getType());
+                               }
+                       }
+
+                       if (prev != null) {
+                               offset = prev.offset + prev.length;
+                               if (start < offset) {
+                                       start = offset;
+                               }
+                       }
+
+                       if (next != null) {
+                               offset = next.offset;
+                               if (offset < end) {
+                                       end = offset;
+                               }
+                       }
+
+                       return new TypedRegion(start, end - start, type);
+               } catch (BadLocationException x) {
+                       x.printStackTrace();
+                       throw new IllegalArgumentException();
+               }
+       }
+
+       protected ITypedRegion getInnerPartition(int offset, FlatNode position) {
+               if (position instanceof ViewNode) {
+                       // TODO: revisit condition
+                       InnerDocumentView innerDocument = ((ViewNode) position).view;
+
+                       if (innerDocument != null) {
+                               // multiplexing to inner view
+                               try {
+                                       // convert to inner offset
+                                       ITypedRegion region = innerDocument
+                                                       .getPartition(innerDocument.getLocalOffset(offset));
+
+                                       // convert to parent offset
+                                       offset = innerDocument.getParentOffset(region.getOffset());
+
+                                       return new TypedRegion(offset, region.getLength(),
+                                                       getContentType(position.type, region.getType()));
+                               } catch (BadLocationException x) {
+                               }
+                       }
+               }
+
+               // simple partition
+               return new TypedRegion(position.offset, position.length, position.type);
+       }
 }
\ No newline at end of file