Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKai Maetzel2002-12-03 13:53:47 +0000
committerKai Maetzel2002-12-03 13:53:47 +0000
commit12a19d1dcedb0e74ec7448608e801550e9ddf756 (patch)
tree666fd0e3d69aeaa61cae9fc0a44a95a6eb6614c1 /org.eclipse.text
parentcca5d0bee1158d234c5366d10b4dcb9126932563 (diff)
downloadeclipse.platform.text-12a19d1dcedb0e74ec7448608e801550e9ddf756.tar.gz
eclipse.platform.text-12a19d1dcedb0e74ec7448608e801550e9ddf756.tar.xz
eclipse.platform.text-12a19d1dcedb0e74ec7448608e801550e9ddf756.zip
projection
Diffstat (limited to 'org.eclipse.text')
-rw-r--r--org.eclipse.text/.classpath2
-rw-r--r--org.eclipse.text/.project1
-rw-r--r--org.eclipse.text/build.properties3
-rw-r--r--org.eclipse.text/projection/org/eclipse/jface/text/CoordinatesTranslator.java288
-rw-r--r--org.eclipse.text/projection/org/eclipse/jface/text/Fragment.java43
-rw-r--r--org.eclipse.text/projection/org/eclipse/jface/text/FragmentUpdater.java104
-rw-r--r--org.eclipse.text/projection/org/eclipse/jface/text/ProjectionDocument.java745
-rw-r--r--org.eclipse.text/projection/org/eclipse/jface/text/ProjectionDocumentManager.java287
-rw-r--r--org.eclipse.text/projection/org/eclipse/jface/text/ProjectionPosition.java42
-rw-r--r--org.eclipse.text/projection/org/eclipse/jface/text/ProjectionPositionUpdater.java51
-rw-r--r--org.eclipse.text/projection/org/eclipse/jface/text/ProjectionTextStore.java132
-rw-r--r--org.eclipse.text/scripts/exportplugin.xml1
-rw-r--r--org.eclipse.text/src/org/eclipse/jface/text/ChildDocument.java2
-rw-r--r--org.eclipse.text/src/org/eclipse/jface/text/ChildDocumentEvent.java39
-rw-r--r--org.eclipse.text/src/org/eclipse/jface/text/ChildDocumentManager.java92
-rw-r--r--org.eclipse.text/src/org/eclipse/jface/text/IDocumentInformationMapping.java27
-rw-r--r--org.eclipse.text/src/org/eclipse/jface/text/ISlaveDocumentManager.java57
-rw-r--r--org.eclipse.text/src/org/eclipse/jface/text/ParentChildMapping.java139
-rw-r--r--org.eclipse.text/src/org/eclipse/jface/text/SlaveDocumentEvent.java45
19 files changed, 2027 insertions, 73 deletions
diff --git a/org.eclipse.text/.classpath b/org.eclipse.text/.classpath
index d8b3fa0d8f2..16fb22f551c 100644
--- a/org.eclipse.text/.classpath
+++ b/org.eclipse.text/.classpath
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="projection"/>
<classpathentry kind="var" path="JRE_LIB" rootpath="JRE_SRCROOT" sourcepath="JRE_SRC"/>
+ <classpathentry kind="src" path="/org.junit"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/org.eclipse.text/.project b/org.eclipse.text/.project
index 9e0b25af586..e6a88f34e13 100644
--- a/org.eclipse.text/.project
+++ b/org.eclipse.text/.project
@@ -3,6 +3,7 @@
<name>org.eclipse.text</name>
<comment></comment>
<projects>
+ <project>org.junit</project>
</projects>
<buildSpec>
<buildCommand>
diff --git a/org.eclipse.text/build.properties b/org.eclipse.text/build.properties
index 04e9be9a51b..03e53ece0c8 100644
--- a/org.eclipse.text/build.properties
+++ b/org.eclipse.text/build.properties
@@ -1,4 +1,5 @@
bin.includes = plugin.properties,\
plugin.xml,\
*.jar
-source.text.jar = src/
+source.text.jar = src/,\
+ projection/
diff --git a/org.eclipse.text/projection/org/eclipse/jface/text/CoordinatesTranslator.java b/org.eclipse.text/projection/org/eclipse/jface/text/CoordinatesTranslator.java
new file mode 100644
index 00000000000..f4c7c3017f8
--- /dev/null
+++ b/org.eclipse.text/projection/org/eclipse/jface/text/CoordinatesTranslator.java
@@ -0,0 +1,288 @@
+/**********************************************************************
+Copyright (c) 2000, 2002 IBM Corp. and others.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Common Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/cpl-v10.html
+
+Contributors:
+ IBM Corporation - Initial implementation
+**********************************************************************/
+
+package org.eclipse.jface.text;
+
+import java.util.Arrays;
+import java.util.Comparator;
+
+/**
+ *
+ */
+public class CoordinatesTranslator implements IDocumentInformationMapping {
+
+ private IDocument fParentDocument;
+ private String fParentCategory;
+ private ProjectionDocument fProjectionDocument;
+ private String fProjectionCategory;
+
+ public CoordinatesTranslator(IDocument parent, String parentCategory, ProjectionDocument projection, String projectionCategory) {
+ fParentDocument= parent;
+ fParentCategory= parentCategory;
+ fProjectionDocument= projection;
+ fProjectionCategory= projectionCategory;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.IDocumentInformationMapping#toOriginOffset(int)
+ */
+ public int toOriginOffset(int imageOffset) throws BadLocationException {
+ Fragment fragment= (Fragment) getPositionOfOffset(fProjectionDocument, ProjectionDocument.FRAGMENT_CATEGORY, imageOffset);
+ if (fragment == null) {
+ if (imageOffset == 0)
+ return 0;
+ throw new BadLocationException();
+ }
+
+ int relative= imageOffset - fragment.offset;
+ return fragment.getOrigin().offset + relative;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.IDocumentInformationMapping#toOriginRegion(org.eclipse.jface.text.IRegion)
+ */
+ public IRegion toOriginRegion(IRegion imageRegion) throws BadLocationException {
+
+ int projectionOffset= imageRegion.getOffset();
+ int projectionLength= imageRegion.getLength();
+
+ if (projectionLength == 0) {
+ if (projectionOffset == 0 && projectionLength == fProjectionDocument.getLength())
+ return new Region(0, fParentDocument.getLength());
+ return new Region(toOriginOffset(projectionOffset), 0);
+ }
+
+ int o1= toOriginOffset(projectionOffset);
+ int o2= toOriginOffset(projectionOffset + projectionLength -1);
+ return new Region(o1, o2 - o1 + 1);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.IDocumentInformationMapping#toOriginLines(int)
+ */
+ public IRegion toOriginLines(int imageLine) throws BadLocationException {
+
+ IRegion projectionDocumentRegion= fProjectionDocument.getLineInformation(imageLine);
+ IRegion parentDocumentRegion= toOriginRegion(projectionDocumentRegion);
+
+ int startLine= fParentDocument.getLineOfOffset(parentDocumentRegion.getOffset());
+ if (parentDocumentRegion.getLength() == 0)
+ return new Region(startLine, 0);
+
+ int endLine= fParentDocument.getLineOfOffset(parentDocumentRegion.getOffset() + parentDocumentRegion.getLength() -1);
+ return new Region(startLine, endLine - startLine);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.IDocumentInformationMapping#toOriginLine(int)
+ */
+ public int toOriginLine(int imageLine) throws BadLocationException {
+ IRegion lines= toOriginLines(imageLine);
+ if (lines.getLength() > 0)
+ throw new IllegalStateException();
+ return lines.getOffset();
+ }
+
+ public int toImageOffset(int originOffset) throws BadLocationException {
+ ProjectionPosition projection= (ProjectionPosition) getPositionOfOffset(fParentDocument, ProjectionDocumentManager.PROJECTION_DOCUMENTS, originOffset);
+ if (projection != null)
+ return translateOffset(projection, originOffset, projection.getFragment());
+ // not included
+ return -1;
+ }
+
+ public IRegion toImageRegion(IRegion originRegion) throws BadLocationException {
+
+ if (originRegion.getLength() == 0) {
+ int projectionOffset= toImageOffset(originRegion.getOffset());
+ return projectionOffset == -1 ? null : new Region(projectionOffset, 0);
+ }
+
+ Position[] positions= getPositionsOfRange(fParentDocument, ProjectionDocumentManager.PROJECTION_DOCUMENTS, originRegion, null);
+ if (positions != null && positions.length > 0) {
+ ProjectionPosition projection= (ProjectionPosition) positions[0];
+
+ int offset= originRegion.getOffset();
+ int length= originRegion.getLength();
+
+ int delta= projection.getOffset() - offset;
+ if (delta > 0) {
+ offset += delta;
+ length -= delta;
+ }
+ int start= translateOffset(projection, offset, projection.getFragment());
+
+ projection= (ProjectionPosition) positions[positions.length -1];
+ int decrease= 0;
+ int endOffset= offset + length;
+ if (length > 0)
+ decrease= 1;
+ endOffset -= decrease;
+
+ delta= endOffset - (projection.getOffset() + Math.max(projection.getLength() -1, 0));
+ if (delta > 0)
+ endOffset -= delta;
+
+ int end= translateOffset(projection, endOffset, projection.getFragment());
+ return new Region(start, end - start + decrease);
+ }
+
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.IDocumentInformationMapping#toImageLine(int)
+ */
+ public int toImageLine(int originLine) throws BadLocationException {
+
+ IRegion parentDocumentRegion= fParentDocument.getLineInformation(originLine);
+ IRegion projectionDocumentRegion= toImageRegion(parentDocumentRegion);
+ if (projectionDocumentRegion == null)
+ return -1;
+
+ int startLine= fProjectionDocument.getLineOfOffset(projectionDocumentRegion.getOffset());
+ if (projectionDocumentRegion.getLength() == 0)
+ return startLine;
+
+ int endLine= fProjectionDocument.getLineOfOffset(projectionDocumentRegion.getOffset() + projectionDocumentRegion.getLength() -1);
+ if (endLine != startLine)
+ throw new IllegalStateException();
+
+ return startLine;
+ }
+
+
+ //-----------------------------------------------------------------------------------------------------------------------------------
+
+
+ private int translateOffset(Position origin, int originOffset, Position target) {
+ int relative= originOffset - origin.offset;
+ return target.offset + relative;
+ }
+
+ private Position getPositionOfOffset(IDocument document, String category, int offset) throws BadLocationException {
+ try {
+ int index= getPositionIndexOfOffset(document, category, offset, 0);
+ if (index > -1) {
+ Position[] positions= document.getPositions(category);
+ return positions[index];
+ }
+ } catch (BadPositionCategoryException x) {
+ }
+ return null;
+ }
+
+ private Position[] getPositionsOfRange(IDocument document, String category, IRegion range, Comparator comparator) {
+
+ int offset= range.getOffset();
+ int length= range.getLength();
+
+ try {
+
+ int start= getPositionIndexOfOffset(document, category, offset, length);
+ int end= getPositionIndexOfOffset(document, category, offset + length -1, 1 - length);
+
+ if (start > -1 && end > -1) {
+
+ Position[] positions= document.getPositions(category);
+
+ if (start == end)
+ return new Position[] { positions[start] };
+
+ Position[] result= new Position[end - start + 1];
+ for (int i= start; i <= end; i++)
+ result[i - start]= positions[i];
+
+ if (comparator != null)
+ Arrays.sort(result, comparator);
+
+ return result;
+ }
+
+ } catch (BadPositionCategoryException e) {
+ } catch (BadLocationException e) {
+ }
+
+ return new Position[0];
+ }
+
+ private int getPositionIndexOfOffset(IDocument document, String category, int offset, int direction ) throws BadPositionCategoryException, BadLocationException{
+
+ Position[] positions= document.getPositions(category);
+ if (positions != null && positions.length > 0) {
+
+ // test for inclusion
+ int index= document.computeIndexInCategory(category, offset);
+ if (index < positions.length && positions[index].includes(offset))
+ return index;
+ if (index > 0 && positions[index -1].includes(offset))
+ return index -1;
+
+ // find next accorrding to direction
+ if (direction != 0) {
+ if (direction > 0) {
+ if (index < positions.length && positions[index].overlapsWith(offset, direction))
+ return index;
+ } else {
+ if (index > 0 && positions[index -1].overlapsWith(offset + direction, -direction))
+ return index -1;
+ }
+ }
+ }
+
+ return -1;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.IDocumentInformationMapping#getCoverage()
+ */
+ public IRegion getCoverage() {
+ Position coverage= fProjectionDocument.getParentDocumentCoverage();
+ return new Region(coverage.getOffset(), coverage.getLength());
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.IDocumentInformationMapping#toClosestImageLine(int)
+ */
+ public int toClosestImageLine(int originLine) throws BadLocationException {
+ try {
+
+ int modelLineOffset= fParentDocument.getLineOffset(originLine);
+ int index= fParentDocument.computeIndexInCategory(ProjectionDocumentManager.PROJECTION_DOCUMENTS, modelLineOffset);
+ Position[] projections= fParentDocument.getPositions(ProjectionDocumentManager.PROJECTION_DOCUMENTS);
+
+ if (index < projections.length) {
+ Position p= projections[index -1];
+ int delta1= modelLineOffset - (p.getOffset() + p.getLength());
+ p= projections[index];
+ int delta2= modelLineOffset - (p.getOffset() + p.getLength());
+ if (delta1 < delta2) {
+ p= projections[index -1];
+ originLine= fParentDocument.getLineOfOffset(p.getOffset() + Math.max(p.getLength() -1, 0));
+ } else {
+ originLine= fParentDocument.getLineOfOffset(p.getOffset());
+ }
+ } else if (projections.length > 0) {
+ Position p= projections[index -1];
+ originLine= fParentDocument.getLineOfOffset(p.getOffset() + Math.max(p.getLength() -1, 0));
+ } else {
+ return 0;
+ }
+
+ return toImageLine(originLine);
+
+ } catch (BadLocationException x) {
+ } catch (BadPositionCategoryException x) {
+ }
+
+ return 0;
+ }
+}
diff --git a/org.eclipse.text/projection/org/eclipse/jface/text/Fragment.java b/org.eclipse.text/projection/org/eclipse/jface/text/Fragment.java
new file mode 100644
index 00000000000..22ee665eee6
--- /dev/null
+++ b/org.eclipse.text/projection/org/eclipse/jface/text/Fragment.java
@@ -0,0 +1,43 @@
+/**********************************************************************
+Copyright (c) 2000, 2002 IBM Corp. and others.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Common Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/cpl-v10.html
+
+Contributors:
+ IBM Corporation - Initial implementation
+**********************************************************************/
+
+package org.eclipse.jface.text;
+
+import org.eclipse.jface.text.Position;
+
+/**
+ * Fragment.java
+ */
+public class Fragment extends Position {
+
+ private Position fOrigin;
+
+ public Fragment(int offset, int length, Position origin) {
+ super(offset, length);
+ fOrigin= origin;
+ }
+
+// public Fragment(int offset, int length) {
+// super(offset, length);
+// }
+
+ /**
+ * Returns the fOrigin.
+ * @return Position
+ */
+ public Position getOrigin() {
+ return fOrigin;
+ }
+
+ public void setOrigin(Position origin) {
+ fOrigin= origin;
+ }
+}
diff --git a/org.eclipse.text/projection/org/eclipse/jface/text/FragmentUpdater.java b/org.eclipse.text/projection/org/eclipse/jface/text/FragmentUpdater.java
new file mode 100644
index 00000000000..7233a2ce57d
--- /dev/null
+++ b/org.eclipse.text/projection/org/eclipse/jface/text/FragmentUpdater.java
@@ -0,0 +1,104 @@
+/**********************************************************************
+Copyright (c) 2000, 2002 IBM Corp. and others.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Common Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/cpl-v10.html
+
+Contributors:
+ IBM Corporation - Initial implementation
+**********************************************************************/
+
+package org.eclipse.jface.text;
+
+
+/**
+ * The position updater used to adapt the fragments of a projection document to
+ * changes of the master document.
+ */
+public class FragmentUpdater extends DefaultPositionUpdater {
+
+ private boolean fShiftMode= false;
+ private boolean fIsLast= false;
+
+ /**
+ * Creates the fragment updater.
+ */
+ protected FragmentUpdater(String fragmentCategory) {
+ super(fragmentCategory);
+ }
+
+ public void enableShiftMode(boolean enable) {
+ fShiftMode= enable;
+ }
+
+ /**
+ * If an insertion happens at a fragment's offset, the fragment is extended
+ * rather than shifted. Also, the last fragment is extended if an inserted
+ * happends at the end of the fragment.
+ */
+ protected void adaptToInsert() {
+
+ if (fShiftMode) {
+ super.adaptToInsert();
+ return;
+ }
+
+ int myStart= fPosition.offset;
+ int myEnd= fPosition.offset + fPosition.length - (fIsLast ? 0 : 1);
+ myEnd= Math.max(myStart, myEnd);
+
+ int yoursStart= fOffset;
+ int yoursEnd= fOffset + fReplaceLength -1;
+ yoursEnd= Math.max(yoursStart, yoursEnd);
+
+ if (myEnd < yoursStart)
+ return;
+
+ if (fLength <= 0) {
+
+ if (myStart <= yoursStart)
+ fPosition.length += fReplaceLength;
+ else
+ fPosition.offset += fReplaceLength;
+
+ } else {
+
+ if (myStart <= yoursStart && fOriginalPosition.offset <= yoursStart)
+ fPosition.length += fReplaceLength;
+ else
+ fPosition.offset += fReplaceLength;
+ }
+ }
+
+ /*
+ * @see IPositionUpdater#update(DocumentEvent event)
+ */
+ public void update(DocumentEvent event) {
+
+ try {
+
+ Position[] category= event.getDocument().getPositions(getCategory());
+
+ fOffset= event.getOffset();
+ fLength= event.getLength();
+ fReplaceLength= (event.getText() == null ? 0 : event.getText().length());
+ fDocument= event.getDocument();
+
+ for (int i= 0; i < category.length; i++) {
+
+ fPosition= category[i];
+ fIsLast= (i == category.length -1);
+
+ fOriginalPosition.offset= fPosition.offset;
+ fOriginalPosition.length= fPosition.length;
+
+ if (notDeleted())
+ adaptToReplace();
+ }
+
+ } catch (BadPositionCategoryException x) {
+ // do nothing
+ }
+ }
+}; \ No newline at end of file
diff --git a/org.eclipse.text/projection/org/eclipse/jface/text/ProjectionDocument.java b/org.eclipse.text/projection/org/eclipse/jface/text/ProjectionDocument.java
new file mode 100644
index 00000000000..9191c9186d4
--- /dev/null
+++ b/org.eclipse.text/projection/org/eclipse/jface/text/ProjectionDocument.java
@@ -0,0 +1,745 @@
+/**********************************************************************
+Copyright (c) 2000, 2002 IBM Corp. and others.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Common Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/cpl-v10.html
+
+Contributors:
+ IBM Corporation - Initial implementation
+**********************************************************************/
+
+package org.eclipse.jface.text;
+
+import java.util.Arrays;
+import java.util.Comparator;
+
+
+
+/**
+ * A patch document represent a projection of its parent document.
+ * The patch document is always in sync with its parent document
+ * by utilizing the parent document as its <code>ITextStore</code>.
+ * This class is for internal use only.
+ *
+ * TODO: sorting Fragments on creation/joining
+ *
+ * @see ITextStore
+ */
+public final class ProjectionDocument extends AbstractDocument {
+
+ final public static String FRAGMENT_CATEGORY= "__fragment_category";
+
+ /** The parent document */
+ private IDocument fParentDocument;
+ /** The parent document as document extension */
+ private IDocumentExtension fExtension;
+ /** The position category defining the projection */
+ private String fProjectionCategory;
+ /** The document event issued by the parent document */
+ private DocumentEvent fParentEvent;
+ /** The document event issued and to be issued by the patch document */
+ private SlaveDocumentEvent fEvent;
+ /** Indicates whether the patch document initiated a parent document update or not */
+ private boolean fIsUpdating= false;
+ /** The fragment updater */
+ private FragmentUpdater fFragmentUpdater= new FragmentUpdater(FRAGMENT_CATEGORY);
+
+ /**
+ * Creates a projection document of the given parent document.
+ *
+ * @param parentDocument the parent Document
+ * @param projectionCategory the document position category whose positions define the projection of the parent document
+ */
+ public ProjectionDocument(IDocument parentDocument, String projectionCategory) {
+ super();
+
+ fParentDocument= parentDocument;
+ if (fParentDocument instanceof IDocumentExtension)
+ fExtension= (IDocumentExtension) fParentDocument;
+
+ ITextStore s= new ProjectionTextStore(this);
+ ILineTracker tracker= new DefaultLineTracker();
+
+ setTextStore(s);
+ setLineTracker(tracker);
+
+ completeInitialization();
+
+ initializeProjection(projectionCategory);
+ tracker.set(s.get(0, s.getLength()));
+ }
+
+ /**
+ * Initializes the projection document from the parent document based on the given
+ * projection category.
+ * @param projectionCategory the document position category whose positions define the projection of the parent document
+ */
+ private void initializeProjection(String projectionCategory) {
+
+ fProjectionCategory= projectionCategory;
+
+ try {
+
+ addPositionCategory(FRAGMENT_CATEGORY);
+ addPositionUpdater(fFragmentUpdater);
+
+ int offset= 0;
+ Position[] patch= fParentDocument.getPositions(fProjectionCategory);
+ for (int i= 0; i < patch.length; i++) {
+ Position p= patch[i];
+ addPosition(FRAGMENT_CATEGORY, new Fragment(offset, p.length, p));
+ offset += p.length;
+ }
+
+ } catch (BadPositionCategoryException x) {
+ } catch (BadLocationException x) {
+ }
+ }
+
+ /**
+ * Creates a fragment from a postion of the parent document.
+ * @param parentPosition a position of the parent document
+ * @return the fragment representing the range given by the parent position
+ */
+ public Fragment createFragment(Position parentPosition) {
+ try {
+
+ int index= fParentDocument.computeIndexInCategory(fProjectionCategory, parentPosition.offset);
+ if (index <= 0)
+ return new Fragment(0, parentPosition.length, parentPosition);
+
+ Position[] fragments= getPositions(FRAGMENT_CATEGORY);
+ Position p= fragments[index -1];
+ return new Fragment(p.offset + p.length, parentPosition.length, parentPosition);
+
+ } catch (BadPositionCategoryException e) {
+ } catch (BadLocationException e) {
+ }
+
+ return null;
+ }
+
+ private int getPositionOfOffset(IDocument document, String category, int offset, int direction ) throws BadPositionCategoryException, BadLocationException{
+
+ Position[] positions= document.getPositions(category);
+ if (positions != null && positions.length > 0) {
+
+ // test for inclusion
+ int index= document.computeIndexInCategory(category, offset);
+ if (index < positions.length && positions[index].includes(offset))
+ return index;
+ if (index > 0 && positions[index -1].includes(offset))
+ return index -1;
+
+ // find next accorrding to direction
+ if (direction != 0) {
+ if (direction > 0) {
+ if (index < positions.length && positions[index].overlapsWith(offset, direction))
+ return index;
+ } else {
+ if (index > 0 && positions[index -1].overlapsWith(offset + direction, -direction))
+ return index -1;
+ }
+ }
+ }
+
+ return -1;
+ }
+
+ /**
+ * Returns the position which is used to manage a parent
+ * document range represented in this projection document and that
+ * includes or is close to the given parent document offset. The distance
+ * is computed based on the given direction hint.
+ *
+ * @param offsetInParent the parent document offset
+ * @param direction the direction hint used for computing the distance
+ * @return position the parent document position including or near to the parent document offset
+ */
+ private Position getParentDocumentPositionOfOffset(int offsetInParent, int direction ) {
+ try {
+
+ int index= getPositionOfOffset(fParentDocument, fProjectionCategory, offsetInParent, direction);
+ if (index > -1) {
+ Position[] positions= fParentDocument.getPositions(fProjectionCategory);
+ return positions[index];
+ }
+
+ } catch (BadPositionCategoryException x) {
+ } catch (BadLocationException x) {
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the offset in the projection document corresponding to the
+ * given parent document offset.
+ *
+ * @param offsetInParent the parent document offset
+ * @return the projection document offset corresponding to the given parent document offset
+ */
+ private int toProjectionDocumentOffset(int offsetInParent, int direction) {
+
+ Position p= getParentDocumentPositionOfOffset(offsetInParent, direction);
+ if (p == null)
+ return -1;
+
+ int relative= offsetInParent - p.offset;
+
+ if (direction > 0) {
+ if (relative < 0)
+ relative= 0;
+ } else if (direction < 0) {
+ if (relative >= p.length)
+ relative= p.length -1;
+ }
+
+ Fragment f= findCorrespondingFragment(p);
+ return f.offset + relative;
+ }
+
+ /**
+ * Creates a position describing the projection document range corresponding to
+ * the given parent document range.
+ *
+ * @param offsetInParent the parent document offset
+ * @param lengthInParent the parent document lengh
+ * @return position describing the projection document range corresponding to the given parent document range
+ */
+ public Position computeProjectionDocumentPosition(int offsetInParent, int lengthInParent) {
+
+ Position p= getParentDocumentCoverage();
+ if (p != null) {
+
+ if (p.overlapsWith(offsetInParent, lengthInParent)) {
+
+ int o1= toProjectionDocumentOffset(offsetInParent, lengthInParent);
+ if (o1 == -1)
+ return null;
+
+ if (lengthInParent == 0)
+ return new Position(o1, 0);
+
+ int o2= toProjectionDocumentOffset(offsetInParent + lengthInParent -1, 1 - lengthInParent);
+ if (o2 == -1)
+ return null;
+
+ return new Position(o1, o2 - o1 + 1);
+
+ } else if (p.getOffset() + p.getLength() == offsetInParent + lengthInParent) {
+
+ Position[] fragments= getFragmentation();
+ if (fragments != null && fragments.length > 0) {
+ Position last= fragments[fragments.length -1];
+ return new Position(last.getOffset() + last.getLength());
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public int toParentDocumentOffset(int offset) throws BadLocationException {
+ Fragment fragment= getFragmentOfOffset(offset);
+
+ if (fragment == null) {
+
+// if (offset == 0)
+// return 0;
+// throw new BadLocationException();
+
+ Position[] fragmentation= getFragmentation();
+ if (fragmentation != null && fragmentation.length > 0) {
+ Fragment last= (Fragment) fragmentation[fragmentation.length -1];
+ if (last.offset + last.length == offset) {
+ Position origin= last.getOrigin();
+ return origin.offset + origin.length;
+ }
+ }
+
+ throw new BadLocationException();
+ }
+
+ int relative= offset - fragment.offset;
+ return fragment.getOrigin().offset + relative;
+ }
+
+ public IRegion computeParentDocumentRegion(int offset, int length) throws BadLocationException {
+
+ if (length == 0) {
+ if (offset == 0 && length == getLength())
+ return new Region(0, fParentDocument.getLength());
+ return new Region(toParentDocumentOffset(offset), 0);
+ }
+
+ int o1= toParentDocumentOffset(offset);
+ int o2= toParentDocumentOffset(offset + length -1);
+ return new Region(o1, o2 - o1 + 1);
+ }
+
+ /**
+ * Removes all fragments and thus empties this projection document.
+ */
+ public void removeAllFragments() {
+ Position[] projection= getProjection();
+ if (projection == null)
+ return;
+
+ for (int i= 0; i < projection.length; i++) {
+ try {
+ removeFragment(projection[i]);
+ } catch (BadLocationException e) {
+ }
+ }
+ }
+
+ /**
+ * Add a new fragment of the parent document to this projection document.
+ *
+ * @param offsetInParent offset of the parent document range
+ * @param lengthInParent length of the parent document range
+ * @return returns the position representing the parent document range in this projection document
+ * @throws BadLocationException
+ */
+ public void addFragment(int offsetInParent, int lengthInParent) throws BadLocationException {
+
+ if (lengthInParent == 0)
+ return;
+
+ try {
+
+ ProjectionPosition p= new ProjectionPosition(this, offsetInParent, lengthInParent);
+ fParentDocument.addPosition(fProjectionCategory, p);
+
+ Fragment fragment= createFragment(p);
+ p.setFragment(fragment);
+ fireDocumentProjectionChanged(new DocumentEvent(this, fragment.offset, 0, fParentDocument.get(offsetInParent, lengthInParent)));
+ addPosition(FRAGMENT_CATEGORY, fragment);
+
+
+ getTracker().set(getStore().get(0, getStore().getLength()));
+
+ } catch (BadPositionCategoryException x) {
+ }
+
+ }
+
+ public void joinFragments() {
+ try {
+ while (joinTwoFragments()) {}
+ } catch (BadPositionCategoryException x) {
+ }
+ }
+
+ private boolean joinTwoFragments() throws BadPositionCategoryException {
+ Position[] projection= getProjection();
+ if (projection != null && projection.length > 0) {
+ Position previous= projection[0];
+ for (int i= 1; i < projection.length; i++) {
+ Position current= projection[i];
+ if (previous.offset + previous.length == current.offset) {
+ join(previous, current);
+ return true;
+ }
+ previous= current;
+ }
+ }
+ return false;
+ }
+
+ private void join(Position p1, Position p2) throws BadPositionCategoryException {
+ // remove p2
+ Fragment fragment= findCorrespondingFragment(p2);
+ removePosition(FRAGMENT_CATEGORY, fragment);
+ fParentDocument.removePosition(fProjectionCategory, p2);
+ // extend p1 by length of p2
+ fragment= findCorrespondingFragment(p1);
+ fragment.length += p2.length;
+ p1.length += p2.length;
+ }
+
+ /**
+ * Removes the given parent document range from this projection document.
+ *
+ * @param parentPosition the position representing the parent document range
+ * @throws BadLocationException
+ */
+ public void removeFragment(Position parentPosition) throws BadLocationException {
+ try {
+
+ Fragment fragment= findCorrespondingFragment(parentPosition);
+ if (fragment != null) {
+ removePosition(FRAGMENT_CATEGORY, fragment);
+ fParentDocument.removePosition(fProjectionCategory, parentPosition);
+ fireDocumentProjectionChanged(new DocumentEvent(this, fragment.offset, fragment.length, null));
+ getTracker().set(getStore().get(0, getStore().getLength()));
+ }
+
+ } catch (BadPositionCategoryException x) {
+ }
+ }
+
+ public Position[] getAffectedFragments(int offsetInParent, int lengthInParent) {
+
+ Position p= computeProjectionDocumentPosition(offsetInParent, lengthInParent);
+ if (p == null)
+ return null;
+
+ Fragment[] f= getFragmentsOfRange(p.offset, p.length);
+ if (f == null)
+ return null;
+
+ Position[] result= new Position[f.length];
+ for (int i= 0; i < f.length; i++)
+ result[i]= f[i].getOrigin();
+ return result;
+ }
+
+ /**
+ * Finds the fragment that represents the given parent document range in this projection document.
+ *
+ * @param parentPosition the parent document range
+ * @return the fragment representing the given parent document range
+ */
+ private Fragment findCorrespondingFragment(Position parentPosition) {
+ try {
+ Position[] fragments= getPositions(FRAGMENT_CATEGORY);
+ for (int i= 0; i < fragments.length; i++) {
+ Fragment f= (Fragment) fragments[i];
+ if (parentPosition.equals(f.getOrigin()))
+ return f;
+ }
+ } catch (BadPositionCategoryException x) {
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the fragment that contains the given offset.
+ *
+ * @param offset the offset
+ * @return the fragment that contains the given offset
+ */
+ protected Fragment getFragmentOfOffset(int offset) throws BadLocationException {
+ try {
+ int index= getPositionOfOffset(this, FRAGMENT_CATEGORY, offset, 0);
+ if (index > -1) {
+ Position[] fragments= getPositions(FRAGMENT_CATEGORY);
+ return (Fragment) fragments[index];
+ }
+ } catch (BadPositionCategoryException x) {
+ }
+ return null;
+ }
+
+ /**
+ * Returns the minimal consecutive list of fragments that completely covers the given range.
+ *
+ * @param offset the offset of the range
+ * @param length the length of the range
+ * @return the minimal consecutive list of fragments convering the given range
+ */
+ protected Fragment[] getFragmentsOfRange(int offset, int length) {
+
+ try {
+
+ int start= getPositionOfOffset(this, FRAGMENT_CATEGORY, offset, length);
+ int end= getPositionOfOffset(this, FRAGMENT_CATEGORY, offset + length -1, 1 - length);
+
+ if (start > -1 && end > -1) {
+
+ Position[] positions= getPositions(FRAGMENT_CATEGORY);
+
+ if (start == end)
+ return new Fragment[] { (Fragment) positions[start] };
+
+ Fragment[] result= new Fragment[end - start + 1];
+ for (int i= start; i <= end; i++)
+ result[i - start]= (Fragment) positions[i];
+ sortFragments(result);
+ return result;
+ }
+
+ } catch (BadPositionCategoryException e) {
+ } catch (BadLocationException e) {
+ }
+
+ return new Fragment[0];
+ }
+
+ /**
+ * Sorts a list of fragments based on the sequence of their origins in the parent document.
+ * @param result
+ */
+ private void sortFragments(Object[] result) {
+
+ Comparator comparator= new Comparator() {
+
+ public int compare(Object o1, Object o2) {
+ Fragment f1= (Fragment) o1;
+ Fragment f2= (Fragment) o2;
+ return f1.getOrigin().getOffset() - f2.getOrigin().getOffset();
+ }
+
+ public boolean equals(Object obj) {
+ return false;
+ }
+ };
+
+ Arrays.sort(result, comparator);
+ }
+
+ /**
+ * Returns the minimal range of the parent document that covers all fragments.
+ *
+ * @return a position describing the minimal parent document range covering all fragments
+ */
+ public Position getParentDocumentCoverage() {
+ Position[] projection= getProjection();
+ if (projection != null && projection.length > 0) {
+ Position first=projection[0];
+ Position last= projection[projection.length -1];
+ return new Position(first.offset, last.offset - first.offset + last.length);
+ }
+ return new Position(0, 0);
+ }
+
+ private void fireDocumentProjectionChanged(DocumentEvent event) {
+ fFragmentUpdater.enableShiftMode(true);
+ try {
+ updatePositions(event);
+ } finally {
+ fFragmentUpdater.enableShiftMode(false);
+ }
+ }
+
+ /**
+ * Returns parent document
+ *
+ * @return the parent document
+ */
+ public IDocument getParentDocument() {
+ return fParentDocument;
+ }
+
+ /**
+ * Returns the ranges of the parent document covered by this patch document.
+ *
+ * @return the child document's parent document range
+ */
+ public Position[] getProjection() {
+ try {
+ return fParentDocument.getPositions(fProjectionCategory);
+ } catch (BadPositionCategoryException x) {
+ }
+ return null;
+ }
+
+ public Position[] getFragmentation() {
+ try {
+
+ Position[] fragmentation= getPositions(FRAGMENT_CATEGORY);
+ sortFragments(fragmentation);
+ return fragmentation;
+
+ } catch (BadPositionCategoryException x) {
+ }
+ return null;
+ }
+
+ /**
+ * Transforms a document event of the parent document into a patch document
+ * based document event.
+ *
+ * @param e the parent document event
+ * @return the child document event
+ */
+ private SlaveDocumentEvent normalize(DocumentEvent e) {
+
+ Position c= computeProjectionDocumentPosition(e.getOffset(), e.getLength());
+
+ if (c != null) {
+ if (c.length == 0) {
+ int insertLength= e.getText() == null ? 0 : e.getText().length();
+ if (insertLength == 0)
+ return null;
+ }
+ return new SlaveDocumentEvent(this, c.offset, c.length, e.getText(), e);
+ }
+
+ return null;
+ }
+
+ /**
+ * When called this patch document is informed about a forthcoming change
+ * of its parent document. This child document checks whether the parent
+ * document change affects it and if so informs all document listeners.
+ *
+ * @param event the parent document event
+ */
+ public void parentDocumentAboutToBeChanged(DocumentEvent event) {
+ fParentEvent= event;
+ fEvent= normalize(event);
+ if (fEvent != null)
+ delayedFireDocumentAboutToBeChanged();
+ }
+
+ /**
+ * When called this child document is informed about a change of its parent document.
+ * If this child document is affected it informs all of its document listeners.
+ *
+ * @param event the parent document event
+ */
+ public void parentDocumentChanged(DocumentEvent event) {
+ if ( !fIsUpdating && event == fParentEvent && fEvent != null) {
+ try {
+ getTracker().replace(fEvent.getOffset(), fEvent.getLength(), fEvent.getText());
+ fireDocumentChanged(fEvent);
+ } catch (BadLocationException x) {
+ Assert.isLegal(false);
+ }
+ }
+ }
+
+ /*
+ * @see AbstractDocument#fireDocumentAboutToBeChanged
+ */
+ protected void fireDocumentAboutToBeChanged(DocumentEvent event) {
+ // delay it until there is a notification from the parent document
+ // otherwise there it is expensive to construct the parent document information
+ }
+
+ /**
+ * Fires the child document event as about-to-be-changed event to all registed listeners.
+ */
+ private void delayedFireDocumentAboutToBeChanged() {
+ super.fireDocumentAboutToBeChanged(fEvent);
+ }
+
+ /**
+ * Ignores the given event and sends the similar child document event instead.
+ *
+ * @param event the event to be ignored
+ */
+ protected void fireDocumentChanged(DocumentEvent event) {
+ super.fireDocumentChanged(fEvent);
+ }
+
+ /*
+ * @see IDocument#replace(int, int, String)
+ * @since 2.0
+ */
+ public void replace(int offset, int length, String text) throws BadLocationException {
+ try {
+ fIsUpdating= true;
+ if (fExtension != null)
+ fExtension.stopPostNotificationProcessing();
+
+ super.replace(offset, length, text);
+
+ } finally {
+ fIsUpdating= false;
+ if (fExtension != null)
+ fExtension.resumePostNotificationProcessing();
+ }
+ }
+
+ /*
+ * @see IDocument#set(String)
+ * @since 2.0
+ */
+ public void set(String text) {
+ try {
+ fIsUpdating= true;
+ if (fExtension != null)
+ fExtension.stopPostNotificationProcessing();
+
+ super.set(text);
+
+ } finally {
+ fIsUpdating= false;
+ if (fExtension != null)
+ fExtension.resumePostNotificationProcessing();
+ }
+ }
+
+ /*
+ * @see IDocumentExtension#registerPostNotificationReplace(IDocumentListener, IDocumentExtension.IReplace)
+ * @since 2.0
+ */
+ public void registerPostNotificationReplace(IDocumentListener owner, IDocumentExtension.IReplace replace) {
+ if (!fIsUpdating)
+ throw new UnsupportedOperationException();
+ super.registerPostNotificationReplace(owner, replace);
+ }
+
+
+ /**
+ * Convenience method for hiding the specified region of the document.
+ * * @param document * @param offsetInParent * @param lengthInParent */
+ public void hide(int offsetInParent, int lengthInParent) {
+
+ IDocument parent= getParentDocument();
+ Position[] effected= getAffectedFragments(offsetInParent, lengthInParent);
+
+ try {
+
+ if (effected == null) {
+ // populate new document with two new fragments, the left and the right of the hidden region
+ int end= offsetInParent + lengthInParent;
+ addFragment(0, offsetInParent);
+ addFragment(end, parent.getLength() - end);
+ } else if (effected.length == 1) {
+ // the only affected fragment must be splitted into two
+ Position fragment= effected[0];
+ removeFragment(fragment);
+ addFragment(fragment.offset, offsetInParent - fragment.offset);
+ int secondOffset= offsetInParent + lengthInParent;
+ addFragment(secondOffset, fragment.offset + fragment.length - secondOffset);
+ } else {
+ // first expand and than collapse
+ internalShow(offsetInParent, lengthInParent, effected);
+ hide(offsetInParent, lengthInParent);
+ }
+
+ joinFragments();
+
+ } catch (BadLocationException x) {
+ }
+ }
+
+ public void show(int offsetInParent, int lengthInParent) {
+
+ Position[] effected= getAffectedFragments(offsetInParent, lengthInParent);
+ if (effected == null || effected.length == 0) {
+ try {
+ addFragment(offsetInParent, lengthInParent);
+ joinFragments();
+ } catch (BadLocationException x) {
+ }
+ return;
+ }
+
+ internalShow(offsetInParent, lengthInParent, effected);
+ joinFragments();
+
+ }
+
+ private void internalShow(int offsetInParent, int lengthInParent, Position[] effected) {
+ try {
+
+ int size= effected.length;
+ for (int i= 0; i < size; i++)
+ removeFragment(effected[i]);
+
+ int offset= Math.min(offsetInParent, effected[0].offset);
+ int end= Math.max(offsetInParent + lengthInParent, effected[size -1].offset + effected[size -1].length);
+ addFragment(offset, end - offset);
+
+ } catch (BadLocationException x) {
+ }
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.text/projection/org/eclipse/jface/text/ProjectionDocumentManager.java b/org.eclipse.text/projection/org/eclipse/jface/text/ProjectionDocumentManager.java
new file mode 100644
index 00000000000..a039af8c598
--- /dev/null
+++ b/org.eclipse.text/projection/org/eclipse/jface/text/ProjectionDocumentManager.java
@@ -0,0 +1,287 @@
+/**********************************************************************
+Copyright (c) 2000, 2002 IBM Corp. and others.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Common Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/cpl-v10.html
+
+Contributors:
+ IBM Corporation - Initial implementation
+**********************************************************************/
+
+package org.eclipse.jface.text;
+
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+
+
+/**
+ * Manages a set of child documents for given parent documents.
+ * A child document represents a particular range of the parent
+ * document and is accordingly adapted to changes of the parent document.
+ * Vice versa, the parent document is accordingly adapted to changes of
+ * its child documents. The manager does not maintain any particular management
+ * structure but utilizes mechanisms given by <code>IDocument</code> such
+ * as position categories and position updaters. <p>
+ *
+ * For internal use only.
+ */
+public final class ProjectionDocumentManager implements IDocumentListener, ISlaveDocumentManager {
+
+
+ /**
+ * Name of the position categories used to keep track of the child
+ * documents offset ranges into the parent document.
+ */
+ public final static String PROJECTION_DOCUMENTS= "__projectiondocuments"; //$NON-NLS-1$
+
+
+// /**
+// * The child document partitioner uses the parent document to answer all questions.
+// */
+// static class ChildPartitioner implements IDocumentPartitioner {
+//
+// protected ProjectionDocument fChildDocument;
+// protected IDocument fParentDocument;
+//
+// protected ChildPartitioner() {
+// }
+//
+// /*
+// * @see IDocumentPartitioner#getPartition(int)
+// */
+// public ITypedRegion getPartition(int offset) {
+// try {
+// offset += fChildDocument.getParentDocumentRange().getOffset();
+// return fParentDocument.getPartition(offset);
+// } catch (BadLocationException x) {
+// }
+//
+// return null;
+// }
+//
+// /*
+// * @see IDocumentPartitioner#computePartitioning(int, int)
+// */
+// public ITypedRegion[] computePartitioning(int offset, int length) {
+// try {
+// offset += fChildDocument.getParentDocumentRange().getOffset();
+// return fParentDocument.computePartitioning(offset, length);
+// } catch (BadLocationException x) {
+// }
+//
+// return null;
+// }
+//
+// /*
+// * @see IDocumentPartitioner#getContentType(int)
+// */
+// public String getContentType(int offset) {
+// try {
+// offset += fChildDocument.getParentDocumentRange().getOffset();
+// return fParentDocument.getContentType(offset);
+// } catch (BadLocationException x) {
+// }
+//
+// return null;
+// }
+//
+// /*
+// * @see IDocumentPartitioner#getLegalContentTypes()
+// */
+// public String[] getLegalContentTypes() {
+// return fParentDocument.getLegalContentTypes();
+// }
+//
+// /*
+// * @see IDocumentPartitioner#documentChanged(DocumentEvent)
+// */
+// public boolean documentChanged(DocumentEvent event) {
+// // ignore as the parent does this for us
+// return false;
+// }
+//
+// /*
+// * @see IDocumentPartitioner#documentAboutToBeChanged(DocumentEvent)
+// */
+// public void documentAboutToBeChanged(DocumentEvent event) {
+// // ignore as the parent does this for us
+// }
+//
+// /*
+// * @see IDocumentPartitioner#disconnect()
+// */
+// public void disconnect() {
+// fChildDocument= null;
+// fParentDocument= null;
+// }
+//
+// /*
+// * @see IDocumentPartitioner#connect(IDocument)
+// */
+// public void connect(IDocument childDocument) {
+// Assert.isTrue(childDocument instanceof ProjectionDocument);
+// fChildDocument= (ProjectionDocument) childDocument;
+// fParentDocument= fChildDocument.getParentDocument();
+// }
+// };
+
+
+
+ /** The position updater shared by all documents which have projection documents */
+ private IPositionUpdater fProjectionPositionUpdater;
+
+ private Map fRegistar= new HashMap();
+
+
+ /**
+ * Returns the projection position updater. If necessary, it is dynamically created.
+ *
+ * @return the child position updater
+ */
+ protected IPositionUpdater getProjectionPositionUpdater() {
+ if (fProjectionPositionUpdater == null)
+ fProjectionPositionUpdater= new FragmentUpdater(PROJECTION_DOCUMENTS);
+ return fProjectionPositionUpdater;
+ }
+
+ private void add(IDocument parent, ProjectionDocument projection) {
+ List list= (List) fRegistar.get(parent);
+ if (list == null) {
+ list= new ArrayList(1);
+ fRegistar.put(parent, list);
+ }
+ list.add(projection);
+ }
+
+ private void remove(IDocument parent, ProjectionDocument projection) {
+ List list= (List) fRegistar.get(parent);
+ if (list != null) {
+ list.remove(projection);
+ if (list.size() == 0)
+ fRegistar.remove(parent);
+ }
+ }
+
+ private boolean hasProjection(IDocument parent) {
+ return (fRegistar.get(parent) instanceof List);
+ }
+
+ private Iterator getProjectionsIterator(IDocument parent) {
+ List list= (List) fRegistar.get(parent);
+ if (list != null)
+ return list.iterator();
+ return null;
+ }
+
+ /**
+ * Informs all child documents of the document which issued this document event.
+ *
+ * @param about indicates whether the change is about to happen or alread happend
+ * @param event the document event which will be processed to inform child documents
+ */
+ protected void fireDocumentEvent(boolean about, DocumentEvent event) {
+ IDocument parent= event.getDocument();
+ Iterator e= getProjectionsIterator(parent);
+ if (e == null)
+ return;
+
+ while (e.hasNext()) {
+ ProjectionDocument document= (ProjectionDocument) e.next();
+ if (about)
+ document.parentDocumentAboutToBeChanged(event);
+ else
+ document.parentDocumentChanged(event);
+ }
+ }
+
+ /*
+ * @see IDocumentListener#documentChanged(DocumentEvent)
+ */
+ public void documentChanged(DocumentEvent event) {
+ fireDocumentEvent(false, event);
+ }
+
+ /*
+ * @see IDocumentListener#documentAboutToBeChanged(DocumentEvent)
+ */
+ public void documentAboutToBeChanged(DocumentEvent event) {
+ fireDocumentEvent(true, event);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.ISlaveDocumentManager#createMasterSlaveMapping(org.eclipse.jface.text.IDocument)
+ */
+ public IDocumentInformationMapping createMasterSlaveMapping(IDocument slave) {
+ if (slave instanceof ProjectionDocument) {
+ ProjectionDocument projectionDocument= (ProjectionDocument) slave;
+ return new CoordinatesTranslator(projectionDocument.getParentDocument(), PROJECTION_DOCUMENTS, projectionDocument, ProjectionDocument.FRAGMENT_CATEGORY);
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.ISlaveDocumentManager#createSlaveDocument(org.eclipse.jface.text.IDocument)
+ */
+ public IDocument createSlaveDocument(IDocument master) {
+ if (!master.containsPositionCategory(PROJECTION_DOCUMENTS)) {
+ master.addPositionCategory(PROJECTION_DOCUMENTS);
+ master.addPositionUpdater(getProjectionPositionUpdater());
+ master.addDocumentListener(this);
+ }
+
+ ProjectionDocument slave= new ProjectionDocument(master, PROJECTION_DOCUMENTS);
+// IDocumentPartitioner partitioner= new ChildPartitioner();
+// child.setDocumentPartitioner(partitioner);
+// partitioner.connect(child);
+
+ add(master, slave);
+ return slave;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.ISlaveDocumentManager#freeSlaveDocument(org.eclipse.jface.text.IDocument)
+ */
+ public void freeSlaveDocument(IDocument slave) {
+
+ if ( !(slave instanceof ProjectionDocument))
+ return;
+
+ ProjectionDocument projectionDocument= (ProjectionDocument) slave;
+
+// childDocument.getDocumentPartitioner().disconnect();
+
+ IDocument parent= projectionDocument.getParentDocument();
+ remove(parent, projectionDocument);
+
+ try {
+ if (!hasProjection(parent)) {
+ parent.removeDocumentListener(this);
+ parent.removePositionUpdater(getProjectionPositionUpdater());
+ parent.removePositionCategory(PROJECTION_DOCUMENTS);
+ }
+ } catch (BadPositionCategoryException x) {
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.ISlaveDocumentManager#getMasterDocument(org.eclipse.jface.text.IDocument)
+ */
+ public IDocument getMasterDocument(IDocument slave) {
+ if (slave instanceof ProjectionDocument)
+ return ((ProjectionDocument) slave).getParentDocument();
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.ISlaveDocumentManager#isSlaveDocument(org.eclipse.jface.text.IDocument)
+ */
+ public boolean isSlaveDocument(IDocument document) {
+ return (document instanceof ProjectionDocument);
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.text/projection/org/eclipse/jface/text/ProjectionPosition.java b/org.eclipse.text/projection/org/eclipse/jface/text/ProjectionPosition.java
new file mode 100644
index 00000000000..14b0eacdcf1
--- /dev/null
+++ b/org.eclipse.text/projection/org/eclipse/jface/text/ProjectionPosition.java
@@ -0,0 +1,42 @@
+/**********************************************************************
+Copyright (c) 2000, 2002 IBM Corp. and others.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Common Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/cpl-v10.html
+
+Contributors:
+ IBM Corporation - Initial implementation
+**********************************************************************/
+package org.eclipse.jface.text;
+
+/**
+ * ProjectionPosition.java
+ */
+public class ProjectionPosition extends Position {
+
+ private IDocument fProjectionDocument;
+ private Fragment fFragment;
+
+ public ProjectionPosition(IDocument projectionDocument, int offset, int length) {
+ super(offset, length);
+ fProjectionDocument= projectionDocument;
+ }
+
+ public void setFragment(Fragment fragment) {
+ fFragment= fragment;
+ }
+
+ public Fragment getFragment() {
+ return fFragment;
+ }
+
+// /**
+// * Changed to be compatible to the position updater behavior
+// * @see Position#overlapsWith(int, int)
+// */
+// public boolean overlapsWith(int offset, int length) {
+// boolean append= (offset == this.offset + this.length) && length == 0;
+// return append || super.overlapsWith(offset, length);
+// }
+}
diff --git a/org.eclipse.text/projection/org/eclipse/jface/text/ProjectionPositionUpdater.java b/org.eclipse.text/projection/org/eclipse/jface/text/ProjectionPositionUpdater.java
new file mode 100644
index 00000000000..a82cf4ce5d3
--- /dev/null
+++ b/org.eclipse.text/projection/org/eclipse/jface/text/ProjectionPositionUpdater.java
@@ -0,0 +1,51 @@
+package org.eclipse.jface.text;
+
+import org.eclipse.jface.text.DefaultPositionUpdater;
+
+/**
+ * The position updater used to adapt the positions representing
+ * the child document ranges to changes of the parent document.
+ */
+
+public class ProjectionPositionUpdater extends DefaultPositionUpdater {
+
+ /**
+ * Creates the position updated.
+ */
+ protected ProjectionPositionUpdater(String category) {
+ super(category);
+ }
+
+ /**
+ * Child document ranges cannot be deleted other then by calling
+ * freeChildDocument.
+ */
+ protected boolean notDeleted() {
+ return true;
+ }
+
+ /**
+ * If an insertion happens at a child document's start offset, the
+ * position is extended rather than shifted. Also, if something is added
+ * right behind the end of the position, the position is extended rather
+ * than kept stable.
+ */
+ protected void adaptToInsert() {
+
+ int myStart= fPosition.offset;
+ int myEnd= fPosition.offset + fPosition.length;
+ myEnd= Math.max(myStart, myEnd);
+
+ int yoursStart= fOffset;
+ int yoursEnd= fOffset + fReplaceLength -1;
+ yoursEnd= Math.max(yoursStart, yoursEnd);
+
+ if (myEnd < yoursStart)
+ return;
+
+ if (myStart <= yoursStart)
+ fPosition.length += fReplaceLength;
+ else
+ fPosition.offset += fReplaceLength;
+ }
+}
diff --git a/org.eclipse.text/projection/org/eclipse/jface/text/ProjectionTextStore.java b/org.eclipse.text/projection/org/eclipse/jface/text/ProjectionTextStore.java
new file mode 100644
index 00000000000..467578330fc
--- /dev/null
+++ b/org.eclipse.text/projection/org/eclipse/jface/text/ProjectionTextStore.java
@@ -0,0 +1,132 @@
+/**********************************************************************
+Copyright (c) 2000, 2002 IBM Corp. and others.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Common Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/cpl-v10.html
+
+Contributors:
+ IBM Corporation - Initial implementation
+**********************************************************************/
+
+package org.eclipse.jface.text;
+
+
+/**
+ * ProjectionTextStore.java
+ */
+public class ProjectionTextStore implements ITextStore {
+
+ private ProjectionDocument fProjectionDocument;
+
+ public ProjectionTextStore(ProjectionDocument projectionDocument) {
+ fProjectionDocument= projectionDocument;
+ }
+
+ private int computeParentDocumentOffset(int offset) {
+ try {
+ return fProjectionDocument.toParentDocumentOffset(offset);
+ } catch (BadLocationException x) {
+ throw new RuntimeException();
+ }
+ }
+
+ /*
+ * @see ITextStore#set
+ */
+ public void set(String contents) {
+
+ try {
+
+ Position[] projection= fProjectionDocument.getProjection();
+ if (projection != null && projection.length > 0) {
+ Position first=projection[0];
+ Position last= projection[projection.length -1];
+ int length= last.offset - first.offset + last.length;
+ getParentDocument().replace(first.getOffset(), length, contents);
+ } else {
+ getParentDocument().set(contents);
+ }
+
+ } catch (BadLocationException x) {
+ }
+ }
+
+ /*
+ * @see ITextStore#replace
+ */
+ public void replace(int offset, int length, String text) {
+
+ try {
+
+ int endoffset= length > 0 ? offset + length -1 : offset;
+ int o2= computeParentDocumentOffset(endoffset);
+ if (length > 0)
+ ++ o2;
+
+ offset= computeParentDocumentOffset(offset);
+ length= o2 - offset;
+
+ getParentDocument().replace(offset, length, text);
+
+ } catch (BadLocationException x) {
+ // ignored as surrounding document should have handled this
+ }
+ }
+
+ /*
+ * @see ITextStore#getLength
+ */
+ public int getLength() {
+ Position[] projection= fProjectionDocument.getProjection();
+ if (projection == null || projection.length == 0)
+ return 0;
+
+ int length= 0;
+ for (int i= 0; i < projection.length; i++)
+ length += projection[i].length;
+ return length;
+ }
+
+ /*
+ * @see ITextStore#get
+ */
+ public String get(int offset, int length) {
+ try {
+
+ Fragment[] fragments= fProjectionDocument.getFragmentsOfRange(offset, length);
+ if (fragments == null || fragments.length == 0)
+ return "";
+
+ StringBuffer buffer= new StringBuffer();
+ for (int i= 0; i < fragments.length; i++) {
+ Position p= fragments[i].getOrigin();
+ buffer.append(getParentDocument().get(p.offset, p.length));
+ }
+
+ offset -= fragments[0].offset;
+ return buffer.substring(offset, offset + length);
+
+ } catch (BadLocationException x) {
+ }
+
+ return null;
+ }
+
+ private IDocument getParentDocument() {
+ return fProjectionDocument.getParentDocument();
+ }
+
+ /*
+ * @see ITextStore#get
+ */
+ public char get(int offset) {
+ try {
+ int o= computeParentDocumentOffset(offset);
+ return getParentDocument().getChar(o);
+ } catch (BadLocationException x) {
+ }
+
+ return (char) 0;
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.text/scripts/exportplugin.xml b/org.eclipse.text/scripts/exportplugin.xml
index 870cc45dc6b..ba29a6de216 100644
--- a/org.eclipse.text/scripts/exportplugin.xml
+++ b/org.eclipse.text/scripts/exportplugin.xml
@@ -23,6 +23,7 @@
<copy file="plugin.properties" todir="${dest}"/>
<zip zipfile="${dest}/textsrc.zip">
<fileset dir="src" />
+ <fileset dir="projection"/>
</zip>
</target>
</project>
diff --git a/org.eclipse.text/src/org/eclipse/jface/text/ChildDocument.java b/org.eclipse.text/src/org/eclipse/jface/text/ChildDocument.java
index 7d2185c3302..c534dd30d96 100644
--- a/org.eclipse.text/src/org/eclipse/jface/text/ChildDocument.java
+++ b/org.eclipse.text/src/org/eclipse/jface/text/ChildDocument.java
@@ -177,7 +177,7 @@ public final class ChildDocument extends AbstractDocument {
if (offset + length > fRange.getLength())
length= fRange.getLength() - offset;
- return new ChildDocumentEvent(this, offset, length, e.fText, e);
+ return new SlaveDocumentEvent(this, offset, length, e.fText, e);
}
/**
diff --git a/org.eclipse.text/src/org/eclipse/jface/text/ChildDocumentEvent.java b/org.eclipse.text/src/org/eclipse/jface/text/ChildDocumentEvent.java
deleted file mode 100644
index cc5e52976b5..00000000000
--- a/org.eclipse.text/src/org/eclipse/jface/text/ChildDocumentEvent.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.eclipse.jface.text;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-
-/**
- * A child document event represents a parent document event as a
- * child-relative document event. It also carries the original event.
- */
-public class ChildDocumentEvent extends DocumentEvent {
-
- /** The parent document event */
- private DocumentEvent fParentEvent;
-
- /**
- * Creates a new child document event.
- *
- * @param doc the child document
- * @param offset the offset in the child document
- * @param length the length in the child document
- * @param text the substitution text
- * @param parentEvent the parent Event
- */
- public ChildDocumentEvent(IDocument doc, int offset, int length, String text, DocumentEvent parentEvent) {
- super(doc, offset, length, text);
- fParentEvent= parentEvent;
- }
-
- /**
- * Returns this event's parent event.
- *
- * @return this event's parent event
- */
- public DocumentEvent getParentEvent() {
- return fParentEvent;
- }
-} \ No newline at end of file
diff --git a/org.eclipse.text/src/org/eclipse/jface/text/ChildDocumentManager.java b/org.eclipse.text/src/org/eclipse/jface/text/ChildDocumentManager.java
index 2b9ed9a4b19..ecf02967892 100644
--- a/org.eclipse.text/src/org/eclipse/jface/text/ChildDocumentManager.java
+++ b/org.eclipse.text/src/org/eclipse/jface/text/ChildDocumentManager.java
@@ -1,10 +1,15 @@
-package org.eclipse.jface.text;
+/**********************************************************************
+Copyright (c) 2000, 2002 IBM Corp. and others.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Common Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/cpl-v10.html
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
+Contributors:
+ IBM Corporation - Initial implementation
+**********************************************************************/
+package org.eclipse.jface.text;
@@ -19,7 +24,7 @@ package org.eclipse.jface.text;
*
* For internal use only.
*/
-public final class ChildDocumentManager implements IDocumentListener {
+public final class ChildDocumentManager implements IDocumentListener, ISlaveDocumentManager {
/**
@@ -210,47 +215,45 @@ public final class ChildDocumentManager implements IDocumentListener {
return fChildPositionUpdater;
}
- /**
- * Creates and returns a new child document for the specified range of the given parent document.
- * The created child document is initialized with a child document partitioner.
- *
- * @param parent the parent document
- * @param offset the offset of the parent document range
- * @param length the length of the parent document range
- * @exception BadLocationException if the specified range is invalid in the parent document
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.ISlaveDocumentManager#createSlaveDocument(org.eclipse.jface.text.IDocument)
*/
- public ChildDocument createChildDocument(IDocument parent, int offset, int length) throws BadLocationException {
-
- if (!parent.containsPositionCategory(CHILDDOCUMENTS)) {
- parent.addPositionCategory(CHILDDOCUMENTS);
- parent.addPositionUpdater(getChildPositionUpdater());
- parent.addDocumentListener(this);
+ public IDocument createSlaveDocument(IDocument master) {
+
+ if (!master.containsPositionCategory(CHILDDOCUMENTS)) {
+ master.addPositionCategory(CHILDDOCUMENTS);
+ master.addPositionUpdater(getChildPositionUpdater());
+ master.addDocumentListener(this);
}
-
- ChildPosition pos= new ChildPosition(parent, offset, length);
+
+ ChildPosition pos= new ChildPosition(master, 0, 0);
try {
- parent.addPosition(CHILDDOCUMENTS, pos);
+ master.addPosition(CHILDDOCUMENTS, pos);
} catch (BadPositionCategoryException x) {
// cannot happen
+ } catch (BadLocationException x) {
+ // (0, 0) is OK
}
-
- ChildDocument child= new ChildDocument(parent, pos);
+
+ ChildDocument child= new ChildDocument(master, pos);
IDocumentPartitioner partitioner= new ChildPartitioner();
child.setDocumentPartitioner(partitioner);
partitioner.connect(child);
-
+
pos.fChildDocument= child;
return child;
}
- /**
- * Disconnects the given child document from it's parent document and frees
- * all resources which are no longer needed.
- *
- * @param childDocument the child document to be freed
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.ISlaveDocumentManager#freeSlaveDocument(org.eclipse.jface.text.IDocument)
*/
- public void freeChildDocument(ChildDocument childDocument) {
+ public void freeSlaveDocument(IDocument slave) {
+
+ if (! (slave instanceof ChildDocument))
+ return;
+
+ ChildDocument childDocument= (ChildDocument) slave;
childDocument.getDocumentPartitioner().disconnect();
@@ -270,6 +273,31 @@ public final class ChildDocumentManager implements IDocumentListener {
}
}
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.ISlaveDocumentManager#createMasterSlaveMapping(org.eclipse.jface.text.IDocument)
+ */
+ public IDocumentInformationMapping createMasterSlaveMapping(IDocument slave) {
+ if (slave instanceof ChildDocument)
+ return new ParentChildMapping((ChildDocument) slave);
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.ISlaveDocumentManager#getMasterDocument(org.eclipse.jface.text.IDocument)
+ */
+ public IDocument getMasterDocument(IDocument slave) {
+ if (slave instanceof ChildDocument)
+ return ((ChildDocument) slave).getParentDocument();
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.ISlaveDocumentManager#isSlaveDocument(org.eclipse.jface.text.IDocument)
+ */
+ public boolean isSlaveDocument(IDocument document) {
+ return (document instanceof ChildDocument);
+ }
+
/**
* Informs all child documents of the document which issued this document event.
*
diff --git a/org.eclipse.text/src/org/eclipse/jface/text/IDocumentInformationMapping.java b/org.eclipse.text/src/org/eclipse/jface/text/IDocumentInformationMapping.java
new file mode 100644
index 00000000000..6fead880e86
--- /dev/null
+++ b/org.eclipse.text/src/org/eclipse/jface/text/IDocumentInformationMapping.java
@@ -0,0 +1,27 @@
+package org.eclipse.jface.text;
+
+
+
+public interface IDocumentInformationMapping {
+
+ IRegion getCoverage();
+
+
+ int toOriginOffset(int imageOffset) throws BadLocationException;
+
+ IRegion toOriginRegion(IRegion imageRegion) throws BadLocationException;
+
+ IRegion toOriginLines(int imageLine) throws BadLocationException;
+
+ int toOriginLine(int imageLine) throws BadLocationException;
+
+
+
+ int toImageOffset(int originOffset) throws BadLocationException;
+
+ IRegion toImageRegion(IRegion originRegion) throws BadLocationException;
+
+ int toImageLine(int originLine) throws BadLocationException;
+
+ int toClosestImageLine(int originLine) throws BadLocationException;
+} \ No newline at end of file
diff --git a/org.eclipse.text/src/org/eclipse/jface/text/ISlaveDocumentManager.java b/org.eclipse.text/src/org/eclipse/jface/text/ISlaveDocumentManager.java
new file mode 100644
index 00000000000..d74731d20af
--- /dev/null
+++ b/org.eclipse.text/src/org/eclipse/jface/text/ISlaveDocumentManager.java
@@ -0,0 +1,57 @@
+/**********************************************************************
+Copyright (c) 2000, 2002 IBM Corp. and others.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Common Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/cpl-v10.html
+
+Contributors:
+ IBM Corporation - Initial implementation
+**********************************************************************/
+
+package org.eclipse.jface.text;
+
+/**
+ * Slave documents are documents that use a text store which is based on a
+ * master document.
+ */
+public interface ISlaveDocumentManager {
+
+ /**
+ * Creates a new slave document for the given master document.
+ *
+ * @param master
+ * @return IDocument
+ */
+ IDocument createSlaveDocument(IDocument master);
+
+ /**
+ * Frees the given slave document.
+ *
+ * @param slave
+ */
+ void freeSlaveDocument(IDocument slave);
+
+ /**
+ * Creates a new mapping between the given slave document and its master.
+ *
+ * @param slaveDocument
+ * @return IDocumentInformationMapping
+ */
+ IDocumentInformationMapping createMasterSlaveMapping(IDocument slave);
+
+ /**
+ * Returns the master of the given slave document.
+ *
+ * @param slave
+ * @return IDocument
+ */
+ IDocument getMasterDocument(IDocument slave);
+
+ /**
+ * Method isSlaveDocument.
+ * @param document
+ * @return boolean
+ */
+ boolean isSlaveDocument(IDocument document);
+} \ No newline at end of file
diff --git a/org.eclipse.text/src/org/eclipse/jface/text/ParentChildMapping.java b/org.eclipse.text/src/org/eclipse/jface/text/ParentChildMapping.java
new file mode 100644
index 00000000000..d47e2c9c796
--- /dev/null
+++ b/org.eclipse.text/src/org/eclipse/jface/text/ParentChildMapping.java
@@ -0,0 +1,139 @@
+package org.eclipse.jface.text;
+
+/**
+ * ParentChildMapping.java
+ */
+public class ParentChildMapping implements IDocumentInformationMapping {
+
+ private IDocument fParentDocument;
+ private ChildDocument fChildDocument;
+
+
+ public ParentChildMapping(ChildDocument childDocument) {
+ fParentDocument= childDocument.getParentDocument();
+ fChildDocument= childDocument;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.IDocumentInformationMapping#getCoverage()
+ */
+ public IRegion getCoverage() {
+ Position p= fChildDocument.getParentDocumentRange();
+ return new Region(p.getOffset(), p.getLength());
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.IDocumentInformationMapping#toOriginOffset(int)
+ */
+ public int toOriginOffset(int imageOffset) throws BadLocationException {
+ int anchorOffset= fChildDocument.getParentDocumentRange().getOffset();
+ return anchorOffset + imageOffset;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.IDocumentInformationMapping#toOriginRegion(org.eclipse.jface.text.IRegion)
+ */
+ public IRegion toOriginRegion(IRegion imageRegion) throws BadLocationException {
+ int anchorOffset= fChildDocument.getParentDocumentRange().getOffset();
+ return new Region(anchorOffset + imageRegion.getOffset(), imageRegion.getLength());
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.IDocumentInformationMapping#toOriginLines(int)
+ */
+ public IRegion toOriginLines(int imageLine) throws BadLocationException {
+ IRegion imageDocumentRegion= fChildDocument.getLineInformation(imageLine);
+ IRegion originDocumentRegion= toOriginRegion(imageDocumentRegion);
+
+ int startLine= fParentDocument.getLineOfOffset(originDocumentRegion.getOffset());
+ if (originDocumentRegion.getLength() == 0)
+ return new Region(startLine, 0);
+
+ int endLine= fParentDocument.getLineOfOffset(originDocumentRegion.getOffset() + originDocumentRegion.getLength() -1);
+ return new Region(startLine, endLine - startLine);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.IDocumentInformationMapping#toOriginLine(int)
+ */
+ public int toOriginLine(int imageLine) throws BadLocationException {
+ int anchorOffset= fChildDocument.getParentDocumentRange().getOffset();
+ return fParentDocument.getLineOfOffset(anchorOffset) + imageLine;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.IDocumentInformationMapping#toImageOffset(int)
+ */
+ public int toImageOffset(int originOffset) throws BadLocationException {
+ Position p= fChildDocument.getParentDocumentRange();
+ if (p.includes(originOffset))
+ return originOffset - p.getOffset();
+ return -1;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.IDocumentInformationMapping#toImageRegion(org.eclipse.jface.text.IRegion)
+ */
+ public IRegion toImageRegion(IRegion originRegion) throws BadLocationException {
+
+ int offset= originRegion.getOffset();
+ int length= originRegion.getLength();
+
+ if (length < 0) {
+ length= -length;
+ offset -= length;
+ }
+
+ Position p= fChildDocument.getParentDocumentRange();
+ if (p.overlapsWith(offset, length)) {
+
+ if (offset < p.getOffset())
+ offset= p.getOffset();
+
+ int end= offset + length;
+ int e= p.getOffset() + p.getLength();
+ if (end > e)
+ end= e;
+
+ offset -= p.getOffset();
+ end -= p.getOffset();
+
+ if (originRegion.getLength() < 0)
+ return new Region(end, offset - end);
+ return new Region(offset, end - offset);
+ }
+
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.IDocumentInformationMapping#toImageLine(int)
+ */
+ public int toImageLine(int originLine) throws BadLocationException {
+ int anchorOffset= fChildDocument.getParentDocumentRange().getOffset();
+ int startLine= fParentDocument.getLineOfOffset(anchorOffset);
+
+ int imageLine= originLine - startLine;
+ if (imageLine < 0 || imageLine > fChildDocument.getNumberOfLines())
+ return -1;
+ return imageLine;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.IDocumentInformationMapping#toClosestImageLine(int)
+ */
+ public int toClosestImageLine(int originLine) throws BadLocationException {
+ int anchorOffset= fChildDocument.getParentDocumentRange().getOffset();
+ int startLine= fParentDocument.getLineOfOffset(anchorOffset);
+
+ int imageLine= originLine - startLine;
+ if (imageLine < 0)
+ return 0;
+
+ int maxLine= fChildDocument.getNumberOfLines();
+ if (imageLine > maxLine)
+ return maxLine;
+
+ return imageLine;
+ }
+}
diff --git a/org.eclipse.text/src/org/eclipse/jface/text/SlaveDocumentEvent.java b/org.eclipse.text/src/org/eclipse/jface/text/SlaveDocumentEvent.java
new file mode 100644
index 00000000000..6563524707f
--- /dev/null
+++ b/org.eclipse.text/src/org/eclipse/jface/text/SlaveDocumentEvent.java
@@ -0,0 +1,45 @@
+/**********************************************************************
+Copyright (c) 2000, 2002 IBM Corp. and others.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Common Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/cpl-v10.html
+
+Contributors:
+ IBM Corporation - Initial implementation
+**********************************************************************/
+
+package org.eclipse.jface.text;
+
+/**
+ * A slave document event represents a master document event as a slave-relative
+ * document event. It also carries the master document event.
+ */
+public class SlaveDocumentEvent extends DocumentEvent {
+
+ /** The master document event */
+ private DocumentEvent fMasterEvent;
+
+ /**
+ * Creates a new slave document event.
+ *
+ * @param doc the slave document
+ * @param offset the offset in the slave document
+ * @param length the length in the slave document
+ * @param text the substitution text
+ * @param masterEvent the master document event
+ */
+ public SlaveDocumentEvent(IDocument doc, int offset, int length, String text, DocumentEvent masterEvent) {
+ super(doc, offset, length, text);
+ fMasterEvent= masterEvent;
+ }
+
+ /**
+ * Returns this event's master event.
+ *
+ * @return this event's master event
+ */
+ public DocumentEvent getMasterEvent() {
+ return fMasterEvent;
+ }
+} \ No newline at end of file

Back to the top