[227018] Further optimize text region implementations
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/BasicStructuredDocumentRegion.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/BasicStructuredDocumentRegion.java
index e93af09..624956f 100644
--- a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/BasicStructuredDocumentRegion.java
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/BasicStructuredDocumentRegion.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2001, 2005 IBM Corporation and others.
+ * Copyright (c) 2001, 2008 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -32,17 +32,22 @@
 	private static final String UNDEFINED = "org.eclipse.wst.sse.core.structuredDocument.UNDEFINED"; //$NON-NLS-1$
 
 	private ITextRegionList _regions;
-	private boolean fIsDeleted = false;
-	// private String fType;
+	/**
+	 * has this region been removed from its document
+	 */
+	private static final byte MASK_IS_DELETED = 1;
+	/**
+	 * was this region terminated normally
+	 */
+	private static final byte MASK_IS_ENDED = 1 << 1;
+
+	private byte fIsDeletedOrEnded = 0;
+
 	/**
 	 * allow a pointer back to this nodes model
 	 */
 	private IStructuredDocument fParentDocument;
-	/**
-	 * was this node terminated normally
-	 */
-	// 0 == false, 1 == true
-	private byte hasEnd = 0;
+	
 	protected int fLength;
 	private IStructuredDocumentRegion next = null;
 	private IStructuredDocumentRegion previous = null;
@@ -351,7 +356,7 @@
 	 * @see org.eclipse.wst.sse.core.text.IStructuredDocumentRegion#isDeleted()
 	 */
 	public boolean isDeleted() {
-		return fIsDeleted || (fParentDocument == null);
+		return (fIsDeletedOrEnded & MASK_IS_DELETED) != 0 || (fParentDocument == null);
 	}
 
 	/**
@@ -359,7 +364,7 @@
 	 * @return boolean
 	 */
 	public boolean isEnded() {
-		return (hasEnd == 1);
+		return (fIsDeletedOrEnded & MASK_IS_ENDED) != 0;
 	}
 
 	public boolean sameAs(IStructuredDocumentRegion region, int shift) {
@@ -464,8 +469,7 @@
 	 * @see org.eclipse.wst.sse.core.text.IStructuredDocumentRegion#setDelete(boolean)
 	 */
 	public void setDeleted(boolean isDeleted) {
-		fIsDeleted = isDeleted;
-
+		fIsDeletedOrEnded = (byte) (isDeleted ? fIsDeletedOrEnded | MASK_IS_DELETED : 0);
 	}
 
 	/**
@@ -474,12 +478,7 @@
 	 *            boolean
 	 */
 	public void setEnded(boolean newHasEnd) {
-		if (newHasEnd) {
-			hasEnd = 1;
-		}
-		else {
-			hasEnd = 0;
-		}
+		fIsDeletedOrEnded = (byte) (newHasEnd ? fIsDeletedOrEnded | MASK_IS_ENDED : 0);
 	}
 
 	public void setLength(int newLength) {
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/EmptyTagCloseRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/EmptyTagCloseRegion.java
new file mode 100644
index 0000000..339d692
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/EmptyTagCloseRegion.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+
+public class EmptyTagCloseRegion implements ITextRegion {
+	private int fLength = 2;
+	static private final byte fTextLength = 2;
+	static private final String fType = DOMRegionContext.XML_EMPTY_TAG_CLOSE;
+	private int fStart;
+
+
+	public EmptyTagCloseRegion() {
+		super();
+	}
+
+	public EmptyTagCloseRegion(int start, int textLength, int length) {
+		super();
+		fStart = start;
+		fLength = length;
+		if (fTextLength != textLength)
+			throw new RuntimeException("invalid for this region type"); //$NON-NLS-1$
+	}
+
+	public void adjustLength(int i) {
+		fLength += i;
+	}
+
+	public void adjustStart(int i) {
+		fStart += i;
+
+	}
+
+	public void adjustTextLength(int i) {
+		throw new RuntimeException("invalid for this region type"); //$NON-NLS-1$
+	}
+
+	public void equatePositions(ITextRegion region) {
+		fStart = region.getStart();
+	}
+
+	public int getEnd() {
+		return fStart + fLength;
+	}
+
+	public int getLength() {
+		return fLength;
+	}
+
+	public int getStart() {
+		return fStart;
+	}
+
+	public int getTextEnd() {
+		return fStart + fTextLength;
+	}
+
+	public int getTextLength() {
+		return fTextLength;
+	}
+
+	public String getType() {
+		return fType;
+	}
+
+	public String toString() {
+		return RegionToStringUtil.toString(this);
+	}
+
+	public StructuredDocumentEvent updateRegion(Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+		// can never be updated
+		return null;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/EndTagOpenRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/EndTagOpenRegion.java
new file mode 100644
index 0000000..1ad5549
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/EndTagOpenRegion.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+
+public class EndTagOpenRegion implements ITextRegion {
+	static private final String fType = DOMRegionContext.XML_END_TAG_OPEN;
+	private int fLength;
+	private int fStart;
+	static private final byte fTextLength = 2;
+
+
+	public EndTagOpenRegion() {
+		super();
+	}
+
+	public EndTagOpenRegion(int start, int textLength, int length) {
+		this();
+		fStart = start;
+		if (fTextLength != textLength)
+			throw new RuntimeException("invalid for this region type"); //$NON-NLS-1$
+		fLength = length;
+	}
+
+	public EndTagOpenRegion(int start, int length) {
+		this();
+		fStart = start;
+		fLength = length;
+	}
+
+	public void adjustLength(int i) {
+		fLength += i;
+
+	}
+
+	public void adjustStart(int i) {
+		fStart += i;
+
+	}
+
+
+	public void adjustTextLength(int i) {
+//		fTextLength += 1;
+		throw new RuntimeException("invalid for this region type"); //$NON-NLS-1$
+	}
+
+	public void equatePositions(ITextRegion region) {
+		fStart = region.getStart();
+		fLength = region.getLength();
+//		fTextLength = region.getTextLength();
+	}
+
+	public int getEnd() {
+		return fStart + fLength;
+	}
+
+	public int getLength() {
+		return fLength;
+	}
+
+	public int getStart() {
+		return fStart;
+	}
+
+	public int getTextEnd() {
+		return fStart + fTextLength;
+	}
+
+	public int getTextLength() {
+		return fTextLength;
+	}
+
+	public String getType() {
+		return fType;
+	}
+
+	public String toString() {
+		return RegionToStringUtil.toString(this);
+	}
+
+	public StructuredDocumentEvent updateRegion(Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+		// can never be updated
+		return null;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/TagOpenRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/TagOpenRegion.java
index 27ad9ae..e8cb85e 100644
--- a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/TagOpenRegion.java
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/TagOpenRegion.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2001, 2005 IBM Corporation and others.
+ * Copyright (c) 2001, 2008 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -22,7 +22,7 @@
 	static private final String fType = DOMRegionContext.XML_TAG_OPEN;
 	private int fLength;
 	private int fStart;
-	private int fTextLength;
+	static private final byte fTextLength = 1;
 
 
 	public TagOpenRegion() {
@@ -30,9 +30,14 @@
 	}
 
 	public TagOpenRegion(int start, int textLength, int length) {
+		this(start, length);
+		if (fTextLength != textLength)
+			throw new RuntimeException("invalid for this region type"); //$NON-NLS-1$
+	}
+
+	public TagOpenRegion(int start, int length) {
 		this();
 		fStart = start;
-		fTextLength = textLength;
 		fLength = length;
 	}
 
@@ -48,14 +53,13 @@
 
 
 	public void adjustTextLength(int i) {
-		fTextLength += 1;
-
+//		fTextLength += 1;
+		throw new RuntimeException("invalid for this region type"); //$NON-NLS-1$
 	}
 
 	public void equatePositions(ITextRegion region) {
 		fStart = region.getStart();
 		fLength = region.getLength();
-		fTextLength = region.getTextLength();
 	}
 
 	public int getEnd() {
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLParserRegionFactory.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLParserRegionFactory.java
index b967526..581f447 100644
--- a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLParserRegionFactory.java
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLParserRegionFactory.java
@@ -71,9 +71,15 @@
 		else if (context == DOMRegionContext.XML_TAG_OPEN) {
 			newRegion = new TagOpenRegion(start, textLength, length);
 		}
+		else if (context == DOMRegionContext.XML_END_TAG_OPEN) {
+			newRegion = new EndTagOpenRegion(start, textLength, length);
+		}
 		else if (context == DOMRegionContext.XML_TAG_CLOSE) {
 			newRegion = new TagCloseRegion(start);
 		}
+		else if (context == DOMRegionContext.XML_EMPTY_TAG_CLOSE) {
+			newRegion = new EmptyTagCloseRegion(start, textLength, length);
+		}
 		else if (context == DOMRegionContext.WHITE_SPACE) {
 			newRegion = new WhiteSpaceOnlyRegion(start, length);
 		}