Merge tag '1_1_0_RC1' into master_juno

Conflicts:
	org.eclipse.vex.releng/Build All Vex.launch
	org.eclipse.vex.releng/vex.target

Change-Id: I36f363a6ce9e7b5e79e5df1fe71f83507b632c27
diff --git a/CONTRIBUTING b/CONTRIBUTING
new file mode 100644
index 0000000..3dae278
--- /dev/null
+++ b/CONTRIBUTING
@@ -0,0 +1,48 @@
+Contributing to Vex
+===================
+
+Thanks for your interest in this project.
+
+Project description:
+--------------------
+
+The Visual Editor for XML (Vex) is a set of plug-ins that provide WYSIWYM editing ability for XML files, regardless of the XML involved. Vex uses CSS stylesheets to provide the formatting for the presentation layer. All that is needed is a stylesheet and an appropriate XML file to edit. It hides the XML tags from the users, allows them to have a word processor like experience but store the information in the native XML format.
+
+Vex is based off of a contribution from the original Vex project  created by John Krasnay and hosted at sourceforge.net. In the year 2008 this code was donated to Eclipse and has been an Eclipse Web Tools Incubator component. In 2011, the project moved under the hoods of the Mylyn Docs project.
+
+- https://projects.eclipse.org/projects/mylyn.docs.vex
+
+Developer resources:
+--------------------
+
+Information regarding source code management, builds, coding standards, and more.
+
+- https://projects.eclipse.org/projects/mylyn.docs.vex/developer
+
+Contributor License Agreement:
+------------------------------
+
+Before your contribution can be accepted by the project, you need to create and electronically sign the Eclipse Foundation Contributor License Agreement (CLA).
+
+- http://www.eclipse.org/legal/CLA.php
+
+Contact:
+--------
+
+Contact the project developers via the project's "dev" list.
+
+- https://dev.eclipse.org/mailman/listinfo/mylyn-vex-dev
+
+Search for bugs:
+----------------
+
+This project uses Bugzilla to track ongoing development and issues.
+
+- https://bugs.eclipse.org/bugs/buglist.cgi?product=Mylyn%20Docs%20Vex
+
+Create a new bug:
+-----------------
+
+Be sure to search for existing bugs before you create another one. Remember that contributions are always welcome!
+
+- https://bugs.eclipse.org/bugs/enter_bug.cgi?product=Mylyn%20Docs%20Vex
diff --git a/org.eclipse.vex.core.tests/.classpath b/org.eclipse.vex.core.tests/.classpath
index c72d35a..9ce3b1f 100644
--- a/org.eclipse.vex.core.tests/.classpath
+++ b/org.eclipse.vex.core.tests/.classpath
@@ -1,7 +1,11 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
-	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins">
+		<accessrules>
+			<accessrule kind="accessible" pattern="**/wst/**/internal/**"/>
+		</accessrules>
+	</classpathentry>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="output" path="target/classes"/>
 </classpath>
diff --git a/org.eclipse.vex.core.tests/META-INF/MANIFEST.MF b/org.eclipse.vex.core.tests/META-INF/MANIFEST.MF
index 6af706d..c052132 100644
--- a/org.eclipse.vex.core.tests/META-INF/MANIFEST.MF
+++ b/org.eclipse.vex.core.tests/META-INF/MANIFEST.MF
@@ -20,11 +20,14 @@
  com.ibm.icu;bundle-version="[1.0.0,100.0.0)"
 Bundle-RequiredExecutionEnvironment: JavaSE-1.6
 Bundle-ActivationPolicy: lazy
-Export-Package: org.eclipse.vex.core.internal.css;x-internal:=true,
- org.eclipse.vex.core.internal.dom;x-internal:=true,
- org.eclipse.vex.core.internal.io,
- org.eclipse.vex.core.internal.layout;x-internal:=true,
- org.eclipse.vex.core.internal.widget;x-internal:=true,
+Export-Package: org.eclipse.vex.core.internal.core;x-friends:="org.eclipse.vex.ui.tests",
+ org.eclipse.vex.core.internal.css;x-friends:="org.eclipse.vex.ui.tests",
+ org.eclipse.vex.core.internal.dom;x-friends:="org.eclipse.vex.ui.tests",
+ org.eclipse.vex.core.internal.io;x-friends:="org.eclipse.vex.ui.tests",
+ org.eclipse.vex.core.internal.layout;x-friends:="org.eclipse.vex.ui.tests",
+ org.eclipse.vex.core.internal.validator;x-friends:="org.eclipse.vex.ui.tests",
+ org.eclipse.vex.core.internal.widget;x-friends:="org.eclipse.vex.ui.tests",
+ org.eclipse.vex.core.internal.widget.swt;x-friends:="org.eclipse.vex.ui.tests",
  org.eclipse.vex.core.tests
 Bundle-Localization: plugin
 Bundle-ClassPath: .
diff --git a/org.eclipse.vex.core.tests/about.html b/org.eclipse.vex.core.tests/about.html
new file mode 100644
index 0000000..c258ef5
--- /dev/null
+++ b/org.eclipse.vex.core.tests/about.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+ 
+<p>June 5, 2006</p>	
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).  Unless otherwise 
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;).  A copy of the EPL is available 
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content.  Check the Redistributor's license that was 
+provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/org.eclipse.vex.core.tests/build.properties b/org.eclipse.vex.core.tests/build.properties
index edcefb7..6066c71 100644
--- a/org.eclipse.vex.core.tests/build.properties
+++ b/org.eclipse.vex.core.tests/build.properties
@@ -1,7 +1,9 @@
 source.. = src/
-output.. = bin/
+output.. = target/classes
 bin.includes = META-INF/,\
                .,\
                testResources/,\
                plugin.properties,\
-               plugin.xml
+               plugin.xml,\
+               about.html
+src.includes = about.html
diff --git a/org.eclipse.vex.core.tests/pom.xml b/org.eclipse.vex.core.tests/pom.xml
index 6ddf768..3a8dbce 100644
--- a/org.eclipse.vex.core.tests/pom.xml
+++ b/org.eclipse.vex.core.tests/pom.xml
@@ -7,10 +7,10 @@
 	<name>Vex Core Tests</name>
 
 	<parent>
-		<artifactId>org.eclipse.vex-releng</artifactId>
+		<artifactId>bundles</artifactId>
 		<groupId>org.eclipse.vex</groupId>
 		<version>1.1.0-SNAPSHOT</version>
-		<relativePath>../org.eclipse.vex.releng/pom.xml</relativePath>
+		<relativePath>../org.eclipse.vex.releng/bundles-pom.xml</relativePath>
 	</parent>
 
 	<build>
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/core/AfterNIteratorTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/core/AfterNIteratorTest.java
index 886d092..786a35d 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/core/AfterNIteratorTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/core/AfterNIteratorTest.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/core/FilterIteratorTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/core/FilterIteratorTest.java
index 892211c..e71ec8b 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/core/FilterIteratorTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/core/FilterIteratorTest.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

@@ -48,6 +48,7 @@
 

 	private static <T> IFilter<T> all() {

 		return new IFilter<T>() {

+			@Override

 			public boolean matches(final T t) {

 				return true;

 			}

@@ -56,6 +57,7 @@
 

 	private static IFilter<String> noEmptyStrings() {

 		return new IFilter<String>() {

+			@Override

 			public boolean matches(final String string) {

 				return string.length() > 0;

 			}

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/core/FirstNIteratorTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/core/FirstNIteratorTest.java
index 3a33dcb..e016c15 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/core/FirstNIteratorTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/core/FirstNIteratorTest.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/BatikBehaviorTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/BatikBehaviorTest.java
index 7405245..e3542da 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/BatikBehaviorTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/BatikBehaviorTest.java
@@ -4,7 +4,7 @@
  * 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:
  * 		Florian Thienel - initial API and implementation
  * 		Carsten Hiesserich - additional tests
@@ -30,14 +30,14 @@
 	@Test
 	public void pseudoElements() throws Exception {
 		final StyleSheetReader reader = new StyleSheetReader();
-		final StyleSheet styleSheet = reader.read("plan:before { display: block; font-size: 123px; }");
+		final StyleSheet styleSheet = reader.read("plan:before { display: block; font-size: 123px; content: 'test' }");
 		final List<Rule> rules = styleSheet.getRules();
 		assertEquals(1, rules.size());
 		final Rule rule = rules.get(0);
 		final Element element = new Element("plan");
 		// The rule should match the parent of the pseudo element. See StyleSheet#getApplicableDeclarations
 		assertTrue(rule.matches(element));
-		final IElement before = styleSheet.getPseudoElement(element, "before", false);
+		final IElement before = styleSheet.getPseudoElementBefore(element);
 		final Styles beforeStyles = styleSheet.getStyles(before);
 		assertEquals("block", beforeStyles.get("display"));
 		assertEquals(123.0f, beforeStyles.getFontSize(), 0.0f);
@@ -48,7 +48,7 @@
 		final StyleSheetReader reader = new StyleSheetReader();
 		final StyleSheet styleSheet = reader.read("plan {font-size: 123px;} plan:before { content: 'test' }");
 		final Element element = new Element("plan");
-		final IElement before = styleSheet.getPseudoElement(element, "before", false);
+		final IElement before = styleSheet.getPseudoElementBefore(element);
 		final Styles beforeStyles = styleSheet.getStyles(before);
 		assertEquals("test", beforeStyles.getContent(element).get(0));
 		assertEquals(123.0f, beforeStyles.getFontSize(), 0.0f);
@@ -61,7 +61,7 @@
 		final Element element = new Element(new QualifiedName(Namespace.VEX_NAMESPACE_URI, "plan"));
 		final Styles styles = styleSheet.getStyles(element);
 		assertEquals(123.0f, styles.getFontSize(), 0.0f);
-		final IElement before = styleSheet.getPseudoElement(element, "before", false);
+		final IElement before = styleSheet.getPseudoElementBefore(element);
 		final Styles beforeStyles = styleSheet.getStyles(before);
 		assertEquals("test", beforeStyles.getContent(element).get(0));
 		assertEquals(123.0f, beforeStyles.getFontSize(), 0.0f);
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/MockDisplayDevice.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/MockDisplayDevice.java
index 75afe0d..307a0b5 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/MockDisplayDevice.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/MockDisplayDevice.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -28,8 +28,8 @@
 	}
 
 	/**
-     *
-     */
+	 *
+	 */
 
 	@Override
 	public int getVerticalPPI() {
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/MockLU.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/MockLU.java
index 04b9cb7..3fe3306 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/MockLU.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/MockLU.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -47,42 +47,52 @@
 		return result;
 	}
 
+	@Override
 	public String getDimensionUnitText() {
 		return dimensionUnitText;
 	}
 
+	@Override
 	public float getFloatValue() {
 		return floatValue;
 	}
 
+	@Override
 	public String getFunctionName() {
 		return functionName;
 	}
 
+	@Override
 	public int getIntegerValue() {
 		return integerValue;
 	}
 
+	@Override
 	public short getLexicalUnitType() {
 		return lexicalUnitType;
 	}
 
+	@Override
 	public LexicalUnit getNextLexicalUnit() {
 		return nextLexicalUnit;
 	}
 
+	@Override
 	public LexicalUnit getParameters() {
 		return parameters;
 	}
 
+	@Override
 	public LexicalUnit getPreviousLexicalUnit() {
 		return previousLexicalUnit;
 	}
 
+	@Override
 	public String getStringValue() {
 		return stringValue;
 	}
 
+	@Override
 	public LexicalUnit getSubValues() {
 		return subValues;
 	}
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/PropertyTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/PropertyTest.java
index 66970b1..a959da0 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/PropertyTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/PropertyTest.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *     Carsten Hieserich - added test for OutlineContentProperty
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/RuleTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/RuleTest.java
index 9d64343..02088b6 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/RuleTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/RuleTest.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/AxisTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/AxisTest.java
index 94c8c1e..625acf1 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/AxisTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/AxisTest.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

@@ -113,6 +113,7 @@
 	public void givenAxisWithElements_whenFilterIsGiven_shouldProvideOnlyMatchingNodes() throws Exception {

 		int actualNodeCount = 0;

 		for (final INode actualNode : axis(source, nodes("matching", "matching", "not", "not", "matching")).matching(new IFilter<INode>() {

+			@Override

 			public boolean matches(final INode node) {

 				return "matching".equals(((TestNode) node).getName());

 			}

@@ -202,10 +203,12 @@
 			return name;

 		}

 

+		@Override

 		public boolean isKindOf(final INode node) {

 			return false;

 		}

 

+		@Override

 		public void accept(final INodeVisitor visitor) {

 			if (visits == null) {

 				throw new IllegalStateException();

@@ -213,6 +216,7 @@
 			visits[0]++;

 		}

 

+		@Override

 		public <T> T accept(final INodeVisitorWithResult<T> visitor) {

 			throw new UnsupportedOperationException();

 		}

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/BasicNodeTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/BasicNodeTest.java
index 2f21b66..a753b7d 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/BasicNodeTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/BasicNodeTest.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

@@ -22,14 +22,17 @@
 	@Override

 	protected Node createNode() {

 		return new Node() {

+			@Override

 			public void accept(final INodeVisitor visitor) {

 				throw new UnsupportedOperationException();

 			}

 

+			@Override

 			public <T> T accept(final INodeVisitorWithResult<T> visitor) {

 				throw new UnsupportedOperationException();

 			}

 

+			@Override

 			public boolean isKindOf(final INode node) {

 				return false;

 			}

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/ContentRangeTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/ContentRangeTest.java
index 044eeaa..9a7316d 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/ContentRangeTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/ContentRangeTest.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/CopyVisitorTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/CopyVisitorTest.java
index 0780759..00bcd0c 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/CopyVisitorTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/CopyVisitorTest.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DeepCopyTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DeepCopyTest.java
index 2def0cb..cc35256 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DeepCopyTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DeepCopyTest.java
@@ -1,10 +1,10 @@
 /*******************************************************************************

- * Copyright (c) 2012, 2013 Florian Thienel and others.

+ * Copyright (c) 2012, 2014 Florian Thienel 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:

  * 		Florian Thienel - initial API and implementation

  *		Carsten Hiesserich - additional test for namespace inheritance

@@ -21,6 +21,7 @@
 import java.util.Iterator;

 import java.util.List;

 

+import org.eclipse.core.runtime.QualifiedName;

 import org.eclipse.vex.core.provisional.dom.ContentRange;

 import org.eclipse.vex.core.provisional.dom.IContent;

 import org.eclipse.vex.core.provisional.dom.IElement;

@@ -278,6 +279,85 @@
 		assertEquals("Target should be copied", pi.getTarget(), ((ProcessingInstruction) copiedChildren.get(0)).getTarget());

 	}

 

+	@Test

+	public void givenOneParentWithXInclude_shouldCopyParentAndXInclude() throws Exception {

+		final GapContent content = new GapContent(10);

+		content.insertTagMarker(0);

+		content.insertTagMarker(0);

+		content.insertTagMarker(0);

+		content.insertTagMarker(0);

+		final Element parent = new Element("parent");

+		parent.associate(content, content.getRange());

+

+		final QualifiedName includeName = new QualifiedName("http://www.w3.org/2001/XInclude", "include");

+		final Element reference = new Element(includeName);

+		reference.setAttribute("href", "testHRef");

+		reference.setAttribute("parse", "xml");

+		reference.setParent(parent);

+		reference.associate(content, new ContentRange(1, 2));

+		final IncludeNode include = new IncludeNode(reference);

+

+		parent.addChild(include);

+

+		final DeepCopy deepCopy = new DeepCopy(parent);

+		final Element copiedParent = (Element) deepCopy.getNodes().get(0);

+		final List<? extends INode> copiedChildren = copiedParent.children().asList();

+

+		assertEquals(1, copiedChildren.size());

+		assertTrue("Expecting the copied IncludeNode", copiedChildren.get(0) instanceof IncludeNode);

+		final IncludeNode copiedInclude = (IncludeNode) copiedChildren.get(0);

+		assertEquals("Parent of IncludeNode should be set", copiedParent, copiedInclude.getParent());

+		assertEquals("Parent of reference should be set", copiedParent, copiedInclude.getReference().getParent());

+		assertEquals(includeName, copiedInclude.getReference().getQualifiedName());

+

+		assertEquals("Attribute 'href' should be copied", "testHRef", copiedInclude.getReference().getAttribute("href").getValue());

+		assertEquals("Attribute 'parse' should be copied", "xml", copiedInclude.getReference().getAttribute("parse").getValue());

+	}

+

+	@Test

+	public void givenXIncludeWithContent_shouldCopyContent() throws Exception {

+		final GapContent content = new GapContent(10);

+		content.insertTagMarker(0);

+		content.insertTagMarker(0);

+		content.insertTagMarker(0);

+		content.insertTagMarker(0);

+		content.insertTagMarker(0);

+		content.insertTagMarker(0);

+		final Element parent = new Element("parent");

+		parent.associate(content, content.getRange());

+

+		final QualifiedName includeName = new QualifiedName("http://www.w3.org/2001/XInclude", "include");

+		final QualifiedName fallbackName = new QualifiedName("http://www.w3.org/2001/XInclude", "fallback");

+

+		final Element reference = new Element(includeName);

+		reference.setAttribute("href", "testHRef");

+		reference.setAttribute("parse", "xml");

+		reference.setParent(parent);

+		reference.associate(content, new ContentRange(1, 4));

+		final IncludeNode include = new IncludeNode(reference);

+

+		final Element fallback = new Element(fallbackName);

+		fallback.associate(content, new ContentRange(2, 3));

+		reference.addChild(fallback);

+

+		content.insertText(3, "fallbackText");

+

+		parent.addChild(include);

+

+		final DeepCopy deepCopy = new DeepCopy(parent);

+		final Element copiedParent = (Element) deepCopy.getNodes().get(0);

+		final List<? extends INode> copiedChildren = copiedParent.children().asList();

+

+		assertEquals(1, copiedChildren.size());

+		assertTrue("Expecting the copied IncludeNode", copiedChildren.get(0) instanceof IncludeNode);

+		final IncludeNode copiedInclude = (IncludeNode) copiedChildren.get(0);

+

+		final Element copiedFallback = (Element) copiedInclude.getReference().children().get(0);

+		assertEquals("Expecting the copied fallback element", fallbackName, copiedFallback.getQualifiedName());

+		assertEquals("Parent of fallback should be set", copiedInclude.getReference(), copiedFallback.getParent());

+		assertEquals("Copied text content", "fallbackText", copiedFallback.getText());

+	}

+

 	private static void assertNodeIsAssociatedElementWithText(final String expectedText, final INode actualNode) {

 		assertTrue(actualNode.isAssociated());

 		assertTrue(actualNode instanceof Element);

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentEventTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentEventTest.java
index 4e936b6..088b4fc 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentEventTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentEventTest.java
@@ -4,7 +4,7 @@
  * 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:
  * 		Carsten Hiesserich  - initial API and implementation
  *******************************************************************************/
@@ -41,26 +41,32 @@
 		childNode = document.insertElement(2, new QualifiedName(null, "child"));
 		document.addDocumentListener(new IDocumentListener() {
 
+			@Override
 			public void attributeChanged(final AttributeChangeEvent event) {
 
 			}
 
+			@Override
 			public void namespaceChanged(final NamespaceDeclarationChangeEvent event) {
 
 			}
 
+			@Override
 			public void beforeContentDeleted(final ContentChangeEvent event) {
 
 			}
 
+			@Override
 			public void beforeContentInserted(final ContentChangeEvent event) {
 
 			}
 
+			@Override
 			public void contentDeleted(final ContentChangeEvent event) {
 				contentChangeEvent = event;
 			}
 
+			@Override
 			public void contentInserted(final ContentChangeEvent event) {
 				contentChangeEvent = event;
 			}
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentFragmentTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentFragmentTest.java
index ed63fec..13978ca 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentFragmentTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentFragmentTest.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentTest.java
index 1b85387..3744268 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentTest.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  * 		Carsten Hiesserich - automatically declare undeclared namespaces when copiing (bug 409647)

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DummyValidator.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DummyValidator.java
index e33020f..573bfb9 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DummyValidator.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DummyValidator.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

@@ -36,34 +36,47 @@
 		this.documentContentModel = documentContentModel;

 	}

 

+	@Override

 	public DocumentContentModel getDocumentContentModel() {

 		return documentContentModel;

 	}

 

+	@Override

 	public AttributeDefinition getAttributeDefinition(final IAttribute attribute) {

 		return null;

 	}

 

+	@Override

 	public List<AttributeDefinition> getAttributeDefinitions(final IElement element) {

 		return Collections.emptyList();

 	}

 

+	@Override

 	public Set<QualifiedName> getValidRootElements() {

 		return Collections.emptySet();

 	}

 

+	@Override

 	public Set<QualifiedName> getValidItems(final IElement element) {

 		return Collections.emptySet();

 	}

 

+	@Override

 	public boolean isValidSequence(final QualifiedName element, final List<QualifiedName> nodes, final boolean partial) {

 		return false;

 	}

 

+	@Override

 	public boolean isValidSequence(final QualifiedName element, final List<QualifiedName> sequence1, final List<QualifiedName> sequence2, final List<QualifiedName> sequence3, final boolean partial) {

 		return false;

 	}

 

+	@Override

+	public boolean isValidSequenceXInclude(final List<QualifiedName> nodes, final boolean partial) {

+		return false;

+	}

+

+	@Override

 	public Set<String> getRequiredNamespaces() {

 		return Collections.emptySet();

 	}

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1CommentHandlingTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1CommentHandlingTest.java
index 4194c26..dff3823 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1CommentHandlingTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1CommentHandlingTest.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *      Carsten Hiesserich - handling of elements within comments (bug 407801)

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1DeletionTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1DeletionTest.java
index c2d0282..25ab356 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1DeletionTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1DeletionTest.java
@@ -4,7 +4,7 @@
  * 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:
  * 		Carsten Hiesserich - initial API and implementation
  *******************************************************************************/
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1ElementHandlingTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1ElementHandlingTest.java
index 6449281..89dfceb 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1ElementHandlingTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1ElementHandlingTest.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1FragmentHandlingTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1FragmentHandlingTest.java
index decc184..5c02f7e 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1FragmentHandlingTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1FragmentHandlingTest.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1ProcessingInstructionHandlingTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1ProcessingInstructionHandlingTest.java
index 4fee0c6..bf4e0e5 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1ProcessingInstructionHandlingTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1ProcessingInstructionHandlingTest.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Carsten Hiesserich - initial API and implementation

  *******************************************************************************/

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1TextHandlingTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1TextHandlingTest.java
index 5bb45d1..5a458b8 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1TextHandlingTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1TextHandlingTest.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/NamespaceTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/NamespaceTest.java
index e88bff0..57967a8 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/NamespaceTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/NamespaceTest.java
@@ -8,7 +8,7 @@
  * Contributors:

  * 		Florian Thienel - initial API and implementation

  * 		Carsten Hiesserich - test for handling of attribute namespaces in FindUndeclaredNamespacesVisitor

- * 

+ *

  *******************************************************************************/

 package org.eclipse.vex.core.internal.dom;

 

@@ -298,8 +298,8 @@
 	@Test

 	public void readWriteCycle() throws Exception {

 		// Caution: Vex sorts attributes on writing, so the order of attributes may change

-		final String inputContent = "<?xml version='1.0' encoding='UTF-8'?> <ns1:a xmlns=\"http://namespace/default\" xmlns:ns1=\"http://namespace/uri/1\" attr1=\"value1\"> "

-				+ "<ns2:b xmlns:ns2=\"http://namespace/uri/2\" ns1:attr2=\"value2\" ns2:attr3=\"value3\"/> " + "<c attr4=\"value4\" ns1:attr5=\"value5\"/>" + "</ns1:a> ";

+		final String inputContent = "<?xml version='1.0' encoding='UTF-8'?> <ns1:a xmlns=\"http://namespace/default\" xmlns:ns1=\"http://namespace/uri/1\" attr1=\"value1\">"

+				+ "<ns2:b xmlns:ns2=\"http://namespace/uri/2\" ns1:attr2=\"value2\" ns2:attr3=\"value3\"/>" + "<c attr4=\"value4\" ns1:attr5=\"value5\"/>" + "</ns1:a> ";

 		final IDocument document = readDocumentFromString(inputContent);

 

 		final DocumentWriter documentWriter = new DocumentWriter();

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/NodeTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/NodeTest.java
index 44f95c0..115e806 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/NodeTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/NodeTest.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/ParentTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/ParentTest.java
index c894112..f6890eb 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/ParentTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/ParentTest.java
@@ -735,28 +735,34 @@
 	}

 

 	private static class TestParent extends Parent {

+		@Override

 		public void accept(final INodeVisitor visitor) {

 			throw new UnsupportedOperationException();

 		}

 

+		@Override

 		public <T> T accept(final INodeVisitorWithResult<T> visitor) {

 			throw new UnsupportedOperationException();

 		}

 

+		@Override

 		public boolean isKindOf(final INode node) {

 			return false;

 		}

 	}

 

 	private static class TestChild extends Node {

+		@Override

 		public void accept(final INodeVisitor visitor) {

 			throw new UnsupportedOperationException();

 		}

 

+		@Override

 		public <T> T accept(final INodeVisitorWithResult<T> visitor) {

 			throw new UnsupportedOperationException();

 		}

 

+		@Override

 		public boolean isKindOf(final INode node) {

 			return false;

 		}

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentContentModelTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentContentModelTest.java
index 52e3aa7..74c3458 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentContentModelTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentContentModelTest.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentReaderTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentReaderTest.java
index ca6aa00..1660814 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentReaderTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentReaderTest.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *      Carsten Hiesserich - do not add text nodes containing only whitespace when reading the document (bug 407803)

@@ -25,6 +25,7 @@
 

 import org.eclipse.core.runtime.QualifiedName;

 import org.eclipse.vex.core.IFilter;

+import org.eclipse.vex.core.internal.css.CssWhitespacePolicy;

 import org.eclipse.vex.core.internal.dom.DummyValidator;

 import org.eclipse.vex.core.provisional.dom.BaseNodeVisitorWithResult;

 import org.eclipse.vex.core.provisional.dom.DocumentContentModel;

@@ -33,6 +34,7 @@
 import org.eclipse.vex.core.provisional.dom.IComment;

 import org.eclipse.vex.core.provisional.dom.IDocument;

 import org.eclipse.vex.core.provisional.dom.IElement;

+import org.eclipse.vex.core.provisional.dom.IIncludeNode;

 import org.eclipse.vex.core.provisional.dom.INode;

 import org.eclipse.vex.core.provisional.dom.IProcessingInstruction;

 import org.eclipse.vex.core.provisional.dom.IText;

@@ -104,6 +106,7 @@
 			}

 		}));

 		reader.setEntityResolver(new EntityResolver() {

+			@Override

 			public InputSource resolveEntity(final String publicId, final String systemId) throws SAXException, IOException {

 				if (TestResources.TEST_DTD.equals(publicId)) {

 					entityResolverCalled[0] = true;

@@ -132,6 +135,7 @@
 			}

 		}));

 		reader.setEntityResolver(new EntityResolver() {

+			@Override

 			public InputSource resolveEntity(final String publicId, final String systemId) throws SAXException, IOException {

 				if (TestResources.TEST_DTD.equals(publicId)) {

 					entityResolverPosition[0] = ++callPosition[0];

@@ -214,6 +218,7 @@
 		final IElement rootElement = document.getRootElement();

 

 		final IFilter<INode> recursiveWhitespaceTextNodeFilter = new IFilter<INode>() {

+			@Override

 			public boolean matches(final INode node) {

 				return node.accept(new BaseNodeVisitorWithResult<Boolean>(false) {

 					@Override

@@ -253,4 +258,35 @@
 		assertNotNull("Attribute with namespace not found", attr2);

 		assertEquals("Value of attribute without namespace", "ns-content", attr2.getValue());

 	}

+

+	@Test

+	public void readDocumentWithInclude() throws Exception {

+

+		final DocumentReader reader = new DocumentReader();

+		reader.setWhitespacePolicyFactory(CssWhitespacePolicy.FACTORY);

+		final IDocument document = reader.read(TestResources.get("documentWithInclude.xml"));

+

+		final List<? extends INode> nodes = document.getRootElement().children().asList();

+		assertEquals(3, nodes.size());

+

+		assertEquals("title", ((IElement) nodes.get(0)).getLocalName());

+		assertTrue("Expecting an include node", nodes.get(1) instanceof IIncludeNode);

+

+		final IIncludeNode includeNode = (IIncludeNode) nodes.get(1);

+		final IElement includeElement = includeNode.getReference();

+		assertEquals("include", includeElement.getLocalName());

+		assertEquals("http://www.w3.org/2001/XInclude", includeElement.getNamespaceURI("xi"));

+		assertEquals("document.xml", includeElement.getAttribute("href").getValue());

+		assertEquals(2, includeElement.children().count());

+

+		final IElement para = (IElement) nodes.get(2);

+		assertTrue("Expecting an include node", para.children().withoutText().get(0) instanceof IIncludeNode);

+		final IIncludeNode inlineIncludeNode = (IIncludeNode) para.children().withoutText().get(0);

+		final IElement inlineIncludeElement = inlineIncludeNode.getReference();

+		assertEquals("include", inlineIncludeElement.getLocalName());

+		assertEquals("http://www.w3.org/2001/XInclude", inlineIncludeElement.getNamespaceURI("xi"));

+		assertEquals("document.xml", inlineIncludeElement.getAttribute("href").getValue());

+		assertEquals("text", inlineIncludeElement.getAttribute("parse").getValue());

+	}

+

 }

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentWriterTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentWriterTest.java
index f83a0f8..8db51fb 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentWriterTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentWriterTest.java
@@ -1,13 +1,13 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2013 John Krasnay and others.
+ * Copyright (c) 2004, 2014 John Krasnay 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:
  *     John Krasnay - initial API and implementation
- *     Carsten Hiesserich - writeNoWrap(DocumentFragment)
+ *     Carsten Hiesserich - writeNoWrap(DocumentFragment), DocumentWithInclude
  *******************************************************************************/
 package org.eclipse.vex.core.internal.io;
 
@@ -69,6 +69,11 @@
 	}
 
 	@Test
+	public void testDocumentWithInclude() throws Exception {
+		assertWriteReadCycleWorks(TestResources.get("documentWithInclude.xml"));
+	}
+
+	@Test
 	public void writeDocumentFragmentNoWrap() throws Exception {
 		final Document doc = new Document(new QualifiedName(null, "root"));
 		final IElement child1 = doc.insertElement(doc.getRootElement().getEndOffset(), new QualifiedName(null, "child"));
@@ -98,6 +103,7 @@
 		documentWriter.setWhitespacePolicy(new CssWhitespacePolicy(styleSheet));
 		final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
 		documentWriter.write(expectedDocument, buffer);
+		System.out.println(buffer.toString());
 
 		final InputStream inputStream = new ByteArrayInputStream(buffer.toByteArray());
 		final InputSource inputSource = new InputSource(inputStream);
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/NamespaceStackTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/NamespaceStackTest.java
index 45c574d..bf7fe28 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/NamespaceStackTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/NamespaceStackTest.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

@@ -14,7 +14,6 @@
 import static org.junit.Assert.assertNull;

 import static org.junit.Assert.assertTrue;

 

-import org.eclipse.vex.core.internal.io.NamespaceStack;

 import org.junit.Test;

 

 /**

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/RoundTrip.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/RoundTrip.java
index 9207309..443eadd 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/RoundTrip.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/RoundTrip.java
@@ -1,12 +1,13 @@
 /*******************************************************************************

- * Copyright (c) 2013 Florian Thienel and others.

+ * Copyright (c) 2013, 2014 Florian Thienel 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:

  * 		Florian Thienel - initial API and implementation

+ * 		Carsten Hiesserich - added support for include nodes

  *******************************************************************************/

 package org.eclipse.vex.core.internal.io;

 

@@ -22,13 +23,14 @@
 import org.eclipse.vex.core.provisional.dom.IComment;

 import org.eclipse.vex.core.provisional.dom.IDocument;

 import org.eclipse.vex.core.provisional.dom.IElement;

+import org.eclipse.vex.core.provisional.dom.IIncludeNode;

 import org.eclipse.vex.core.provisional.dom.INode;

 import org.eclipse.vex.core.provisional.dom.IParent;

 import org.eclipse.vex.core.provisional.dom.IText;

 

 /**

  * This class provides some special assertions for round trip tests.

- * 

+ *

  * @author Florian Thienel

  */

 public class RoundTrip {

@@ -63,6 +65,11 @@
 				public void visit(final IText text) {

 					assertEquals(expectedNode.getText(), actualNode.getText());

 				}

+

+				@Override

+				public void visit(final IIncludeNode include) {

+					assertElementsEqual(((IIncludeNode) expectedNode).getReference(), ((IIncludeNode) actualNode).getReference());

+				}

 			});

 		}

 		assertFalse("more children expected", expectedChildren.hasNext());

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/SpaceNormalizerTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/SpaceNormalizerTest.java
index 93cbdb9..0d4966c 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/SpaceNormalizerTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/SpaceNormalizerTest.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *     Igor Jacy Lino Campista - Java 5 warnings fixed (bug 311325)
@@ -164,7 +164,7 @@
 
 	/**
 	 * Test the normalize method. Test cases are as follows.
-	 * 
+	 *
 	 * <ul>
 	 * <li>leading w/s trimmed</li>
 	 * <li>trailing w/s trimmed</li>
@@ -300,6 +300,7 @@
 		final SAXParserFactory factory = SAXParserFactory.newInstance();
 		final XMLReader xmlReader = factory.newSAXParser().getXMLReader();
 		final DocumentBuilder builder = new DocumentBuilder(null, new DummyValidator(), new IStyleSheetProvider() {
+			@Override
 			public StyleSheet getStyleSheet(final DocumentContentModel documentContentModel) {
 				return styleSheet;
 			}
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/TextWrapperTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/TextWrapperTest.java
index 1f5e29f..57f499d 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/TextWrapperTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/TextWrapperTest.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *     Igor Jacy Lino Campista - Java 5 warnings fixed (bug 311325)
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/XMLFragmentTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/XMLFragmentTest.java
index b921419..86f3b57 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/XMLFragmentTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/XMLFragmentTest.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/BlockElementBoxTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/BlockElementBoxTest.java
similarity index 87%
rename from org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/BlockElementBoxTest.java
rename to org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/BlockElementBoxTest.java
index 26a09ff..946ec36 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/BlockElementBoxTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/BlockElementBoxTest.java
@@ -8,7 +8,7 @@
  * Contributors:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
-package org.eclipse.vex.core.internal.dom;
+package org.eclipse.vex.core.internal.layout;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
@@ -22,12 +22,6 @@
 import org.eclipse.vex.core.internal.css.StyleSheet;
 import org.eclipse.vex.core.internal.css.StyleSheetReader;
 import org.eclipse.vex.core.internal.io.DocumentReader;
-import org.eclipse.vex.core.internal.layout.BlockElementBox;
-import org.eclipse.vex.core.internal.layout.Box;
-import org.eclipse.vex.core.internal.layout.CssBoxFactory;
-import org.eclipse.vex.core.internal.layout.FakeGraphics;
-import org.eclipse.vex.core.internal.layout.LayoutContext;
-import org.eclipse.vex.core.internal.layout.RootBox;
 import org.eclipse.vex.core.provisional.dom.IDocument;
 import org.eclipse.vex.core.tests.TestResources;
 import org.junit.Test;
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/ContentPositionTableTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/ContentPositionTableTest.java
new file mode 100644
index 0000000..210b375
--- /dev/null
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/ContentPositionTableTest.java
@@ -0,0 +1,188 @@
+package org.eclipse.vex.core.internal.layout;
+
+import static org.junit.Assert.assertEquals;
+
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.vex.core.internal.css.CssWhitespacePolicy;
+import org.eclipse.vex.core.internal.css.StyleSheet;
+import org.eclipse.vex.core.internal.css.StyleSheetReader;
+import org.eclipse.vex.core.internal.dom.Document;
+import org.eclipse.vex.core.provisional.dom.ContentPosition;
+import org.eclipse.vex.core.provisional.dom.IElement;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ContentPositionTableTest {
+
+	FakeGraphics g;
+	LayoutContext context;
+
+	@Before
+	public void setUp() throws Exception {
+
+		// set CSS
+		final String css = "root   {display:block}" + "inline {display:inline}" + "table  {display:table}" + "tcap   {display:table-caption}" + "td     {display:table-cell}"
+				+ "tc     {display:table-column}" + "tcg    {display:table-column-group}" + "tfg    {display:table-footer-group}" + "thg    {display:table-header-group}"
+				+ "tr     {display:table-row}" + "trg    {display:table-row-group}";
+		final StyleSheet styleSheet = new StyleSheetReader().read(css);
+
+		// FakeGraphics uses a fixed char width of 6
+		g = new FakeGraphics();
+
+		context = new LayoutContext();
+		context.setBoxFactory(new CssBoxFactory());
+		context.setGraphics(g);
+		context.setStyleSheet(styleSheet);
+		context.setWhitespacePolicy(new CssWhitespacePolicy(styleSheet));
+	}
+
+	@Test
+	public void testViewToModel() throws Exception {
+		final Document doc = new Document(new QualifiedName(null, "root"));
+		final IElement root = doc.getRootElement();
+
+		final IElement table = doc.insertElement(root.getEndOffset(), new QualifiedName(null, "table"));
+		final IElement row1 = doc.insertElement(table.getEndOffset(), new QualifiedName(null, "tr"));
+		final IElement col11 = doc.insertElement(row1.getEndOffset(), new QualifiedName(null, "td"));
+		final IElement row2 = doc.insertElement(table.getEndOffset(), new QualifiedName(null, "tr"));
+		final IElement col21 = doc.insertElement(row2.getEndOffset(), new QualifiedName(null, "td"));
+		doc.insertText(col11.getEndOffset(), "line1 line2 line3");
+		doc.insertText(col21.getEndOffset(), "line1 line2 line3");
+
+		context.setDocument(doc);
+
+		final RootBox rootBox = new RootBox(context, doc, 36);
+		rootBox.layout(context, 0, Integer.MAX_VALUE);
+
+		assertEquals(col11.getStartPosition().moveBy(1), rootBox.viewToModel(context, 0, 0));
+		assertEquals(row1.getEndPosition(), rootBox.viewToModel(context, 100, 0));
+		assertEquals(col21.getStartPosition().moveBy(1), rootBox.viewToModel(context, 0, 45));
+		assertEquals(row2.getEndPosition(), rootBox.viewToModel(context, 100, 45));
+	}
+
+	@Test
+	public void testGetNextLinePositionXLeft() throws Exception {
+
+		final Document doc = new Document(new QualifiedName(null, "root"));
+		final IElement root = doc.getRootElement();
+
+		final IElement table = doc.insertElement(root.getEndOffset(), new QualifiedName(null, "table"));
+		final IElement row1 = doc.insertElement(table.getEndOffset(), new QualifiedName(null, "tr"));
+		final IElement col11 = doc.insertElement(row1.getEndOffset(), new QualifiedName(null, "td"));
+		final IElement row2 = doc.insertElement(table.getEndOffset(), new QualifiedName(null, "tr"));
+		final IElement col21 = doc.insertElement(row2.getEndOffset(), new QualifiedName(null, "td"));
+		doc.insertText(col11.getEndOffset(), "line1 line2 line3");
+		doc.insertText(col21.getEndOffset(), "line1 line2 line3");
+
+		context.setDocument(doc);
+
+		final RootBox rootBox = new RootBox(context, doc, 36);
+		rootBox.layout(context, 0, Integer.MAX_VALUE);
+
+		final ContentPosition linePosition = col11.getStartPosition().moveBy(1);
+		ContentPosition nextLinePos = rootBox.getNextLinePosition(context, linePosition, 0);
+		assertEquals(col11.getStartPosition().moveBy(7), nextLinePos); // line2
+		nextLinePos = rootBox.getNextLinePosition(context, nextLinePos, 0);
+		assertEquals(col11.getStartPosition().moveBy(13), nextLinePos); // line3
+		nextLinePos = rootBox.getNextLinePosition(context, nextLinePos, 0);
+		assertEquals(table.getStartPosition().moveBy(22), nextLinePos); // Between row1 and row2
+		nextLinePos = rootBox.getNextLinePosition(context, nextLinePos, 0);
+		assertEquals(col21.getStartPosition().moveBy(1), nextLinePos); // row2 - line1
+	}
+
+	@Test
+	public void testGetNextLinePositionXRight() throws Exception {
+		// This is the same test as before, but with a x position at the rigth of the table cells
+
+		final Document doc = new Document(new QualifiedName(null, "root"));
+		final IElement root = doc.getRootElement();
+
+		final IElement table = doc.insertElement(root.getEndOffset(), new QualifiedName(null, "table"));
+		final IElement row1 = doc.insertElement(table.getEndOffset(), new QualifiedName(null, "tr"));
+		final IElement col11 = doc.insertElement(row1.getEndOffset(), new QualifiedName(null, "td"));
+		final IElement row2 = doc.insertElement(table.getEndOffset(), new QualifiedName(null, "tr"));
+		final IElement col21 = doc.insertElement(row2.getEndOffset(), new QualifiedName(null, "td"));
+		doc.insertText(col11.getEndOffset(), "line1 line2 line3");
+		doc.insertText(col21.getEndOffset(), "line1 line2 line3");
+
+		context.setDocument(doc);
+
+		final RootBox rootBox = new RootBox(context, doc, 36);
+		rootBox.layout(context, 0, Integer.MAX_VALUE);
+
+		final ContentPosition linePosition = col11.getStartPosition().moveBy(6); // end of line 1
+		ContentPosition nextLinePos = rootBox.getNextLinePosition(context, linePosition, 35); // X=35 is inside the space
+		assertEquals(col11.getStartOffset() + 12, nextLinePos.getOffset()); // end of line2 (after the space)
+		nextLinePos = rootBox.getNextLinePosition(context, nextLinePos, 35);
+		assertEquals(col11.getStartOffset() + 18, nextLinePos.getOffset()); // placeholder at end of line3
+		nextLinePos = rootBox.getNextLinePosition(context, nextLinePos, 35);
+		assertEquals(row1.getEndOffset() + 1, nextLinePos.getOffset()); // Between row1 and row2
+		nextLinePos = rootBox.getNextLinePosition(context, nextLinePos, 28); // This time before the space
+		assertEquals(col21.getStartOffset() + 6, nextLinePos.getOffset()); // row2 - end of line1 (after the '1`', before the space)
+	}
+
+	@Test
+	public void testGetPreviousLinePosition() throws Exception {
+
+		final Document doc = new Document(new QualifiedName(null, "root"));
+		final IElement root = doc.getRootElement();
+
+		final IElement table = doc.insertElement(root.getEndOffset(), new QualifiedName(null, "table"));
+		final IElement row1 = doc.insertElement(table.getEndOffset(), new QualifiedName(null, "tr"));
+		final IElement col11 = doc.insertElement(row1.getEndOffset(), new QualifiedName(null, "td"));
+		final IElement row2 = doc.insertElement(table.getEndOffset(), new QualifiedName(null, "tr"));
+		final IElement col21 = doc.insertElement(row2.getEndOffset(), new QualifiedName(null, "td"));
+		doc.insertText(col11.getEndOffset(), "line1 line2 line3");
+		doc.insertText(col21.getEndOffset(), "line1 line2 line3");
+
+		context.setDocument(doc);
+
+		final RootBox rootBox = new RootBox(context, doc, 36);
+		rootBox.layout(context, 0, Integer.MAX_VALUE);
+
+		// We test here with a x position inside the table cell.
+		final ContentPosition linePosition = col21.getEndPosition().moveBy(-1);
+		ContentPosition prevLinePos = rootBox.getPreviousLinePosition(context, linePosition, 2);
+		assertEquals(col21.getEndPosition().moveBy(-11), prevLinePos); // start of line2
+		prevLinePos = rootBox.getPreviousLinePosition(context, prevLinePos, 2);
+		assertEquals(col21.getStartPosition().moveBy(1), prevLinePos); // start of line 1
+		prevLinePos = rootBox.getPreviousLinePosition(context, prevLinePos, 2);
+		assertEquals(row1.getEndPosition().moveBy(1), prevLinePos); // Between row1 and row2
+		prevLinePos = rootBox.getPreviousLinePosition(context, prevLinePos, 2);
+		assertEquals(col11.getEndPosition().moveBy(-5), prevLinePos);
+	}
+
+	@Test
+	public void testGetPreviousLinePositionNoSpace() throws Exception {
+		// Same test as before, but this time there is no space to split at
+
+		final Document doc = new Document(new QualifiedName(null, "root"));
+		final IElement root = doc.getRootElement();
+
+		final IElement table = doc.insertElement(root.getEndOffset(), new QualifiedName(null, "table"));
+		final IElement row1 = doc.insertElement(table.getEndOffset(), new QualifiedName(null, "tr"));
+		final IElement col11 = doc.insertElement(row1.getEndOffset(), new QualifiedName(null, "td"));
+		final IElement row2 = doc.insertElement(table.getEndOffset(), new QualifiedName(null, "tr"));
+		final IElement col21 = doc.insertElement(row2.getEndOffset(), new QualifiedName(null, "td"));
+		doc.insertText(col11.getEndOffset(), "line11line22line33");
+		doc.insertText(col21.getEndOffset(), "line11line22line33");
+
+		context.setDocument(doc);
+
+		final RootBox rootBox = new RootBox(context, doc, 36);
+		rootBox.layout(context, 0, Integer.MAX_VALUE);
+
+		// We test here with a x position inside the table cell. A position more to the right would
+		// move between the rows
+		final ContentPosition linePosition = col21.getEndPosition().moveBy(-1);
+		ContentPosition prevLinePos = rootBox.getPreviousLinePosition(context, linePosition, 35);
+		assertEquals(col21.getEndOffset() - 7, prevLinePos.getOffset()); // end of line2
+		prevLinePos = rootBox.getPreviousLinePosition(context, prevLinePos, 35);
+		assertEquals(col21.getEndOffset() - 13, prevLinePos.getOffset()); // end of line 1
+		prevLinePos = rootBox.getPreviousLinePosition(context, prevLinePos, 35);
+		assertEquals(row1.getEndOffset() + 1, prevLinePos.getOffset()); // Between row1 and row2
+		prevLinePos = rootBox.getPreviousLinePosition(context, prevLinePos, 35);
+		assertEquals(col11.getEndOffset() - 1, prevLinePos.getOffset()); // row1 - placeholder at end of line3
+	}
+
+}
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/ContentPositionTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/ContentPositionTest.java
new file mode 100644
index 0000000..b139a46
--- /dev/null
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/ContentPositionTest.java
@@ -0,0 +1,209 @@
+package org.eclipse.vex.core.internal.layout;
+
+import static org.junit.Assert.assertEquals;
+
+import java.net.URL;
+
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.vex.core.internal.core.Caret;
+import org.eclipse.vex.core.internal.css.CssWhitespacePolicy;
+import org.eclipse.vex.core.internal.css.StyleSheet;
+import org.eclipse.vex.core.internal.css.StyleSheetReader;
+import org.eclipse.vex.core.internal.dom.Document;
+import org.eclipse.vex.core.provisional.dom.ContentPosition;
+import org.eclipse.vex.core.provisional.dom.IElement;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ContentPositionTest {
+
+	FakeGraphics g;
+	LayoutContext context;
+
+	@Before
+	public void setUp() throws Exception {
+		final URL url = this.getClass().getResource("test.css");
+		final StyleSheetReader reader = new StyleSheetReader();
+		final StyleSheet styleSheet = reader.read(url);
+
+		g = new FakeGraphics();
+
+		context = new LayoutContext();
+		context.setBoxFactory(new CssBoxFactory());
+		context.setGraphics(g);
+		context.setStyleSheet(styleSheet);
+		context.setWhitespacePolicy(new CssWhitespacePolicy(styleSheet));
+	}
+
+	@Test
+	public void testPositionAtLineStart() throws Exception {
+
+		final Document doc = new Document(new QualifiedName(null, "root"));
+		final IElement root = doc.getRootElement();
+
+		final IElement block1 = doc.insertElement(root.getEndOffset(), new QualifiedName(null, "block"));
+		final IElement block2 = doc.insertElement(root.getEndOffset(), new QualifiedName(null, "block"));
+		doc.insertText(block1.getEndOffset(), "line1 line2 line3");
+		doc.insertText(block2.getEndOffset(), "line1 line2 line3");
+
+		context.setDocument(doc);
+
+		final RootBox rootBox = new RootBox(context, doc, 36);
+		rootBox.layout(context, 0, Integer.MAX_VALUE);
+
+		ContentPosition caretPosition = rootBox.viewToModel(context, 0, 6); // begin of line 1
+		assertEquals(block1.getStartPosition().moveBy(1), caretPosition);
+
+		caretPosition = rootBox.viewToModel(context, 0, 18); // begin of line 2
+		assertEquals(block1.getStartPosition().moveBy(7), caretPosition);
+	}
+
+	@Test
+	public void testPositionAtLineEnd() throws Exception {
+
+		final Document doc = new Document(new QualifiedName(null, "root"));
+		final IElement root = doc.getRootElement();
+
+		final IElement block1 = doc.insertElement(root.getEndOffset(), new QualifiedName(null, "block"));
+		final IElement block2 = doc.insertElement(root.getEndOffset(), new QualifiedName(null, "block"));
+		doc.insertText(block1.getEndOffset(), "line1 line2 line3");
+		doc.insertText(block2.getEndOffset(), "line1 line2 line3");
+
+		context.setDocument(doc);
+
+		final RootBox rootBox = new RootBox(context, doc, 36);
+		rootBox.layout(context, 0, Integer.MAX_VALUE);
+
+		ContentPosition caretPosition = rootBox.viewToModel(context, 100, 6); // end of line 1
+
+		assertEquals(block1.getStartPosition().moveBy(6), caretPosition);
+		Caret caret = rootBox.getCaret(context, caretPosition);
+		assertEquals(0, caret.getY());
+
+		caretPosition = rootBox.viewToModel(context, 100, 18); // end of line 2
+		assertEquals(block1.getStartPosition().moveBy(12), caretPosition);
+		caret = rootBox.getCaret(context, caretPosition);
+		assertEquals(12, caret.getY());
+
+		caretPosition = rootBox.viewToModel(context, 100, 30); // end of line 3
+		assertEquals(block1.getEndPosition(), caretPosition);
+		caret = rootBox.getCaret(context, caretPosition);
+		assertEquals(24, caret.getY());
+	}
+
+	@Test
+	public void testMoveForward() throws Exception {
+
+		final Document doc = new Document(new QualifiedName(null, "root"));
+		final IElement root = doc.getRootElement();
+
+		final IElement block1 = doc.insertElement(root.getEndOffset(), new QualifiedName(null, "block"));
+		doc.insertText(block1.getEndOffset(), "line1 line22 line3");
+
+		context.setDocument(doc);
+		final RootBox rootBox = new RootBox(context, doc, 36);
+		rootBox.layout(context, 0, Integer.MAX_VALUE);
+
+		ContentPosition caretPosition = block1.getStartPosition().moveBy(6); // At the end of line1 before the space
+		Caret caret = rootBox.getCaret(context, caretPosition);
+		assertEquals("Expceting caret in line 1", 0, caret.getY());
+
+		caretPosition = caretPosition.moveBy(1); // Moving by 1 should place the caret at the start of the next line
+		caret = rootBox.getCaret(context, caretPosition);
+		assertEquals("Expceting caret in line 2", 12, caret.getY());
+	}
+
+	@Test
+	public void testGetNextLinePosition() throws Exception {
+
+		final Document doc = new Document(new QualifiedName(null, "root"));
+		final IElement root = doc.getRootElement();
+
+		final IElement block1 = doc.insertElement(root.getEndOffset(), new QualifiedName(null, "block"));
+		final IElement block2 = doc.insertElement(root.getEndOffset(), new QualifiedName(null, "block"));
+		doc.insertText(block1.getEndOffset(), "line1 line22 line3");
+		doc.insertText(block2.getEndOffset(), "line1 line2 line3");
+
+		context.setDocument(doc);
+		final RootBox rootBox = new RootBox(context, doc, 36);
+		rootBox.layout(context, 0, Integer.MAX_VALUE);
+
+		final ContentPosition linePosition = block1.getStartPosition().moveBy(1);
+		ContentPosition nextLinePos = rootBox.getNextLinePosition(context, linePosition, 0);
+		assertEquals(block1.getStartPosition().moveBy(7), nextLinePos); // line2
+		nextLinePos = rootBox.getNextLinePosition(context, nextLinePos, 0);
+		assertEquals(block1.getStartPosition().moveBy(14), nextLinePos); // line3
+		nextLinePos = rootBox.getNextLinePosition(context, nextLinePos, 0);
+		assertEquals(block2.getStartPosition(), nextLinePos); // Between block1 and block2
+		nextLinePos = rootBox.getNextLinePosition(context, nextLinePos, 0);
+		assertEquals(block2.getStartPosition().moveBy(1), nextLinePos); // block2 - line1
+	}
+
+	@Test
+	public void testGetNextLinePosition_CaretAtLineEnd() throws Exception {
+		/*
+		 * The same test as before, but this time there is no space character to split the first block a second time. In
+		 * this case, the last caret position in the second line will be before the last character of the second line.
+		 * The position after that character is not reachable on the second line. It is actually at the beginning of the
+		 * third line.
+		 * 
+		 * In fact there is no common behaviour among other editors (like Word, Open Office or Notepad++), so we stick
+		 * with this solution as it works fine for the moment and the case (no spaces in one line of text) is really
+		 * rare.
+		 */
+
+		final Document doc = new Document(new QualifiedName(null, "root"));
+		final IElement root = doc.getRootElement();
+
+		final IElement block1 = doc.insertElement(root.getEndOffset(), new QualifiedName(null, "block"));
+		final IElement block2 = doc.insertElement(root.getEndOffset(), new QualifiedName(null, "block"));
+		doc.insertText(block1.getEndOffset(), "line1 line22line3");
+		doc.insertText(block2.getEndOffset(), "line1 line2 line3");
+
+		context.setDocument(doc);
+
+		final RootBox rootBox = new RootBox(context, doc, 36);
+		rootBox.layout(context, 0, Integer.MAX_VALUE);
+
+		final ContentPosition linePosition = rootBox.viewToModel(context, 100, 6); // x=100 -> after end of line 1
+		assertEquals(block1.getStartOffset() + 6, linePosition.getOffset()); // line2
+		ContentPosition nextLinePos = rootBox.getNextLinePosition(context, linePosition, 100);
+		assertEquals(block1.getStartOffset() + 12, nextLinePos.getOffset()); // actually before the last character of the second line
+		final Caret caret = rootBox.getCaret(context, nextLinePos);
+		assertEquals(12, caret.getY()); // line height is 12, so this is line 2
+		nextLinePos = rootBox.getNextLinePosition(context, nextLinePos, 100);
+		assertEquals(block1.getEndPosition(), nextLinePos); // line3
+		nextLinePos = rootBox.getNextLinePosition(context, nextLinePos, 100);
+		assertEquals(block2.getStartPosition(), nextLinePos); // Between block1 and block2
+		nextLinePos = rootBox.getNextLinePosition(context, nextLinePos, 100);
+		assertEquals(block2.getStartOffset() + 6, nextLinePos.getOffset()); // block2 - end of line1
+	}
+
+	@Test
+	public void testGetPreviousLinePosition() throws Exception {
+
+		final Document doc = new Document(new QualifiedName(null, "root"));
+		final IElement root = doc.getRootElement();
+
+		final IElement block1 = doc.insertElement(root.getEndOffset(), new QualifiedName(null, "block"));
+		final IElement block2 = doc.insertElement(root.getEndOffset(), new QualifiedName(null, "block"));
+		doc.insertText(block1.getEndOffset(), "line1 line2 line3");
+		doc.insertText(block2.getEndOffset(), "line1 line2 line3");
+
+		context.setDocument(doc);
+
+		final RootBox rootBox = new RootBox(context, doc, 36);
+		rootBox.layout(context, 0, Integer.MAX_VALUE);
+
+		final ContentPosition linePosition = block2.getEndPosition().moveBy(-1);
+		ContentPosition prevLinePos = rootBox.getPreviousLinePosition(context, linePosition, 0);
+		assertEquals(block2.getEndPosition().moveBy(-11), prevLinePos); // start of line2
+		prevLinePos = rootBox.getPreviousLinePosition(context, prevLinePos, 0);
+		assertEquals(block2.getStartPosition().moveBy(1), prevLinePos); // start of line 1
+		prevLinePos = rootBox.getPreviousLinePosition(context, prevLinePos, 0);
+		assertEquals(block2.getStartPosition(), prevLinePos); // Between block1 and block2
+		prevLinePos = rootBox.getPreviousLinePosition(context, prevLinePos, 0);
+		assertEquals(block1.getEndPosition().moveBy(-5), prevLinePos); // block1 - start of line3
+	}
+
+}
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/FakeGraphics.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/FakeGraphics.java
index d790c2e..856af9e 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/FakeGraphics.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/FakeGraphics.java
@@ -48,59 +48,75 @@
 	}
 
 	private final FontMetrics fontMetrics = new FontMetrics() {
+		@Override
 		public int getAscent() {
 			return 10;
 		}
 
+		@Override
 		public int getDescent() {
 			return 3;
 		}
 
+		@Override
 		public int getHeight() {
 			return 13;
 		}
 
+		@Override
 		public int getLeading() {
 			return 2;
 		}
 	};
 
+	@Override
 	public int charsWidth(final char[] data, final int offset, final int length) {
 		return length * charWidth;
 	}
 
+	@Override
 	public ColorResource createColor(final Color rgb) {
 		return new ColorResource() {
+			@Override
 			public void dispose() {
 			}
 		};
 	}
 
+	@Override
 	public FontResource createFont(final FontSpec fontSpec) {
 		return new FontResource() {
+			@Override
 			public void dispose() {
 			}
 		};
 	}
 
+	@Override
 	public void dispose() {
 	}
 
+	@Override
 	public void drawChars(final char[] chars, final int offset, final int length, final int x, final int y) {
 	}
 
+	@Override
 	public void drawLine(final int x1, final int y1, final int x2, final int y2) {
 	}
 
+	@Override
 	public void drawString(final String s, final int x, final int y) {
 	}
 
+	@Override
 	public void drawOval(final int x, final int y, final int width, final int height) {
 	}
 
+	@Override
 	public void drawRect(final int x, final int y, final int width, final int height) {
 	}
 
+	@Override
 	public void drawImage(final Image image, final int x, final int y, final int width, final int height) {
 		Assert.isTrue(image instanceof FakeImage);
 		lastDrawnImageUrl = ((FakeImage) image).url;
@@ -110,12 +126,15 @@
 		return lastDrawnImageUrl;
 	}
 
+	@Override
 	public void fillOval(final int x, final int y, final int width, final int height) {
 	}
 
+	@Override
 	public void fillRect(final int x, final int y, final int width, final int height) {
 	}
 
+	@Override
 	public Rectangle getClipBounds() {
 		return new Rectangle(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE);
 	}
@@ -124,38 +143,47 @@
 		return null;
 	}
 
+	@Override
 	public ColorResource getColor() {
 		return null;
 	}
 
+	@Override
 	public FontResource getFont() {
 		return null;
 	}
 
+	@Override
 	public int getLineStyle() {
 		return 0;
 	}
 
+	@Override
 	public int getLineWidth() {
 		return 0;
 	}
 
+	@Override
 	public ColorResource getSystemColor(final int id) {
 		return null;
 	}
 
+	@Override
 	public FontMetrics getFontMetrics() {
 		return fontMetrics;
 	}
 
+	@Override
 	public Image getImage(final URL url) {
 		return new FakeImage(url);
 	}
 
+	@Override
 	public boolean isAntiAliased() {
 		return false;
 	}
 
+	@Override
 	public void setAntiAliased(final boolean antiAliased) {
 	}
 
@@ -163,20 +191,25 @@
 		return null;
 	}
 
+	@Override
 	public ColorResource setColor(final ColorResource color) {
 		return null;
 	}
 
+	@Override
 	public FontResource setFont(final FontResource font) {
 		return null;
 	}
 
+	@Override
 	public void setLineStyle(final int style) {
 	}
 
+	@Override
 	public void setLineWidth(final int width) {
 	}
 
+	@Override
 	public int stringWidth(final String s) {
 		return charWidth * s.length();
 	}
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/FakeImage.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/FakeImage.java
index b04c86e..c7e5082 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/FakeImage.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/FakeImage.java
@@ -19,11 +19,19 @@
 		this.width = width;

 	}

 

+	@Override

 	public int getHeight() {

 		return height;

 	}

 

+	@Override

 	public int getWidth() {

 		return width;

 	}

+

+	@Override

+	public String toString() {

+		return "FakeImage [url=" + url + ", height=" + height + ", width=" + width + "]";

+	}

+

 }

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/LayoutTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/LayoutTest.java
index 25ea549..853ae61 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/LayoutTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/LayoutTest.java
@@ -36,6 +36,7 @@
 import org.eclipse.vex.core.provisional.dom.DocumentContentModel;
 import org.eclipse.vex.core.provisional.dom.IDocument;
 import org.eclipse.vex.core.provisional.dom.IElement;
+import org.eclipse.vex.core.provisional.dom.IIncludeNode;
 import org.eclipse.vex.core.provisional.dom.INode;
 import org.junit.runner.RunWith;
 import org.junit.runners.AllTests;
@@ -60,7 +61,7 @@
  * The expected layout state of an box may be checked with the attribute <code>layoutState="LAYOUT_XXX"</code> (
  * {@link AbstractBlockBox#LAYOUT_OK}, {@link AbstractBlockBox#LAYOUT_REDO}, {@link AbstractBlockBox#LAYOUT_PROPAGATE}).<br />
  * The expected text after actions are performed is defined with the attribute <code>textAfter</code>.
- * 
+ *
  */
 @RunWith(AllTests.class)
 public class LayoutTest extends TestCase {
@@ -79,8 +80,10 @@
 		suite.addTest(loadSuite("before-after.xml"));
 		suite.addTest(loadSuite("linebreaks.xml"));
 		suite.addTest(loadSuite("tables.xml"));
+		suite.addTest(loadSuite("lists.xml"));
 		suite.addTest(loadSuite("simple-edit.xml"));
 		suite.addTest(loadSuite("comment-processing-instr.xml"));
+		suite.addTest(loadSuite("include.xml"));
 		return suite;
 	}
 
@@ -123,6 +126,7 @@
 		final DocumentReader reader = new DocumentReader();
 		reader.setValidator(new LayoutTestValidator());
 		reader.setStyleSheetProvider(new IStyleSheetProvider() {
+			@Override
 			public StyleSheet getStyleSheet(final DocumentContentModel documentContentModel) {
 				return styleSheet;
 			}
@@ -189,7 +193,7 @@
 
 		boxSpec.children.removeAll(toRemove);
 
-		if (invalidateParentBlock && box instanceof BlockBox && box.getNode() != null) {
+		if (invalidateParentBlock && box instanceof BlockBox && !box.isAnonymous()) {
 			((BlockBox) box).invalidate(true);
 			invalidateParentBlock = false;
 		}
@@ -271,6 +275,11 @@
 			public String visit(final IElement element) {
 				return element.getPrefixedName();
 			}
+
+			@Override
+			public String visit(final IIncludeNode include) {
+				return include.getReference().getPrefixedName();
+			}
 		});
 	}
 
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/MockBoxFactory.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/MockBoxFactory.java
index 5bd3aa1..5358dcc 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/MockBoxFactory.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/MockBoxFactory.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/TableLayoutTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/TableLayoutTest.java
index d857960..2a5cede 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/TableLayoutTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/TableLayoutTest.java
@@ -238,6 +238,7 @@
 		mutableInteger[0] = 0;
 		travelLayoutStack(new StackVisitor() {
 
+			@Override
 			public void visit(final StackElement element) {
 				if (element.box.getClass().equals(blockClass)) {
 					mutableInteger[0]++;
@@ -252,6 +253,7 @@
 		final StringBuilder result = new StringBuilder();
 		travelLayoutStack(new StackVisitor() {
 
+			@Override
 			public void visit(final StackElement element) {
 				if (element.indent > 0) {
 					final char[] indentChars = new char[element.indent * 2];
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/TestDocumentTextBox.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/TestDocumentTextBox.java
index 9efbe3d..1cf55ad 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/TestDocumentTextBox.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/TestDocumentTextBox.java
@@ -109,6 +109,19 @@
 		assertEquals("Last right box should have a width", 36, pair2.getRight().getWidth());
 	}
 
+	@Test
+	public void testPositionUpdate() throws Exception {
+		final IDocument doc = new Document(new QualifiedName(null, "root"));
+		doc.insertText(2, "before 12345 67890 ");
+		final IElement root = doc.getRootElement();
+		final DocumentTextBox box = new DocumentTextBox(context, root, root.getStartOffset() + 8, root.getEndOffset() - 1);
+		final InlineBox.Pair pair = box.split(context, 150, false);
+		doc.insertText(2, "before");
+		assertEquals(root.getStartOffset() + 8 + 6, pair.getLeft().getStartOffset());
+		assertEquals("12345 ", ((DocumentTextBox) pair.getLeft()).getText());
+		assertEquals("67890 ", ((DocumentTextBox) pair.getRight()).getText());
+	}
+
 	private void assertSplit(final INode node, final int splitPos, final boolean force, final String left, final String right) {
 
 		final DocumentTextBox box = new DocumentTextBox(context, node, node.getStartOffset() + 1, node.getEndOffset() - 1);
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/endtoend/EndToEndTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/endtoend/EndToEndTest.java
new file mode 100644
index 0000000..b9dcc03
--- /dev/null
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/endtoend/EndToEndTest.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Florian Thienel 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:
+ * 		Florian Thienel - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.vex.core.internal.layout.endtoend;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.eclipse.vex.core.internal.core.DisplayDevice;
+import org.eclipse.vex.core.internal.css.CssWhitespacePolicy;
+import org.eclipse.vex.core.internal.css.IStyleSheetProvider;
+import org.eclipse.vex.core.internal.css.StyleSheet;
+import org.eclipse.vex.core.internal.css.StyleSheetReader;
+import org.eclipse.vex.core.internal.io.DocumentReader;
+import org.eclipse.vex.core.internal.widget.BaseVexWidget;
+import org.eclipse.vex.core.provisional.dom.DocumentContentModel;
+import org.eclipse.vex.core.provisional.dom.IDocument;
+import org.eclipse.vex.core.provisional.dom.IValidator;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+import org.xml.sax.SAXException;
+
+/**
+ * @author Florian Thienel
+ */
+public class EndToEndTest {
+
+	private static final String UNIX_SEPARATOR = "\n";
+	private static final String LINE_SEPARATOR = "line.separator";
+	private static final DisplayDevice DD_72DPI = new DisplayDevice() {
+		@Override
+		public int getHorizontalPPI() {
+			return 72;
+		}
+
+		@Override
+		public int getVerticalPPI() {
+			return 72;
+		}
+	};
+
+	@Rule
+	public TestName name = new TestName();
+
+	@Test
+	public void simpleParagraph() throws Exception {
+		assertRenderingWorks();
+	}
+
+	private void assertRenderingWorks() throws IOException, ParserConfigurationException, SAXException {
+		final StyleSheet styleSheet = readStyleSheet();
+		final IDocument document = readInputDocument(styleSheet);
+
+		final String expectedTrace = readExpectedTrace();
+		final String actualTrace = traceRendering(document, styleSheet);
+
+		assertEquals(expectedTrace, actualTrace);
+	}
+
+	private static String traceRendering(final IDocument document, final StyleSheet styleSheet) throws IOException, ParserConfigurationException, SAXException {
+		final ByteArrayOutputStream traceBuffer = new ByteArrayOutputStream();
+		final PrintStream printStream = createUnixPrintStream(traceBuffer);
+
+		DisplayDevice.setCurrent(DD_72DPI);
+		final TracingHostComponent hostComponent = new TracingHostComponent(printStream);
+		final BaseVexWidget widget = new BaseVexWidget(hostComponent);
+		widget.setDocument(document, styleSheet);
+		widget.paint(hostComponent.createDefaultGraphics(), 0, 0);
+		return new String(traceBuffer.toByteArray());
+	}
+
+	private static PrintStream createUnixPrintStream(final OutputStream target) {
+		final String originalSeparator = System.getProperty(LINE_SEPARATOR);
+		System.setProperty(LINE_SEPARATOR, UNIX_SEPARATOR);
+		final PrintStream printStream = new PrintStream(target, true);
+		System.setProperty(LINE_SEPARATOR, originalSeparator);
+		return printStream;
+	}
+
+	private StyleSheet readStyleSheet() throws IOException {
+		return new StyleSheetReader().read(getClass().getResource(styleSheetName()));
+	}
+
+	private IDocument readInputDocument(final StyleSheet styleSheet) throws IOException, ParserConfigurationException, SAXException {
+		final DocumentReader reader = new DocumentReader();
+		reader.setValidator(IValidator.NULL);
+		reader.setStyleSheetProvider(new IStyleSheetProvider() {
+			@Override
+			public StyleSheet getStyleSheet(final DocumentContentModel documentContentModel) {
+				return styleSheet;
+			}
+		});
+		reader.setWhitespacePolicyFactory(CssWhitespacePolicy.FACTORY);
+		return reader.read(getClass().getResource(inputName()));
+	}
+
+	private String readExpectedTrace() throws IOException {
+		return readAndCloseStream(getClass().getResourceAsStream(outputName()));
+	}
+
+	private static String readAndCloseStream(final InputStream in) throws IOException {
+		try {
+			final ByteArrayOutputStream content = new ByteArrayOutputStream();
+			final byte[] readBuffer = new byte[1024];
+			int readCount;
+			while ((readCount = in.read(readBuffer)) > 0) {
+				content.write(readBuffer, 0, readCount);
+			}
+			return new String(content.toByteArray());
+		} finally {
+			in.close();
+		}
+	}
+
+	private String inputName() {
+		return name.getMethodName() + "-input.xml";
+	}
+
+	private String outputName() {
+		return name.getMethodName() + "-output.txt";
+	}
+
+	private String styleSheetName() {
+		return name.getMethodName() + ".css";
+	}
+}
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/endtoend/Tracer.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/endtoend/Tracer.java
new file mode 100644
index 0000000..54afaec
--- /dev/null
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/endtoend/Tracer.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Florian Thienel 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:
+ * 		Florian Thienel - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.vex.core.internal.layout.endtoend;
+
+import java.io.PrintStream;
+import java.text.MessageFormat;
+
+/**
+ * @author Florian Thienel
+ */
+public class Tracer {
+
+	private final PrintStream out;
+
+	public Tracer(final PrintStream out) {
+		this.out = out;
+	}
+
+	public void trace(final String message, final Object... arguments) {
+		out.println(MessageFormat.format(message, arguments));
+	}
+}
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/endtoend/TracingColorResource.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/endtoend/TracingColorResource.java
new file mode 100644
index 0000000..af63db6
--- /dev/null
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/endtoend/TracingColorResource.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Florian Thienel 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:
+ * 		Florian Thienel - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.vex.core.internal.layout.endtoend;
+
+import org.eclipse.vex.core.internal.core.Color;
+import org.eclipse.vex.core.internal.core.ColorResource;
+
+/**
+ * @author Florian Thienel
+ */
+public class TracingColorResource implements ColorResource {
+
+	private final Tracer tracer;
+	private final Color color;
+	private final int id;
+
+	public TracingColorResource(final Tracer tracer, final Color color) {
+		this.tracer = tracer;
+		this.color = color;
+		id = -1;
+	}
+
+	public TracingColorResource(final Tracer tracer, final int id) {
+		this.tracer = tracer;
+		color = null;
+		this.id = id;
+	}
+
+	@Override
+	public void dispose() {
+		tracer.trace("ColorResource[{0}, {1}].dispose()", color, id);
+	}
+
+	@Override
+	public String toString() {
+		return "TracingColorResource [color=" + color + ", id=" + id + "]";
+	}
+
+}
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/endtoend/TracingFontResource.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/endtoend/TracingFontResource.java
new file mode 100644
index 0000000..e8a7481
--- /dev/null
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/endtoend/TracingFontResource.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Florian Thienel 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:
+ * 		Florian Thienel - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.vex.core.internal.layout.endtoend;
+
+import org.eclipse.vex.core.internal.core.FontResource;
+import org.eclipse.vex.core.internal.core.FontSpec;
+
+/**
+ * @author Florian Thienel
+ */
+public class TracingFontResource implements FontResource {
+
+	private final Tracer tracer;
+	private final FontSpec fontSpec;
+
+	public TracingFontResource(final Tracer tracer, final FontSpec fontSpec) {
+		this.tracer = tracer;
+		this.fontSpec = fontSpec;
+	}
+
+	@Override
+	public void dispose() {
+		tracer.trace("FontResource[{0}].dispose()", fontSpec);
+	}
+
+	@Override
+	public String toString() {
+		return "TracingFontResource [fontSpec=" + fontSpec + "]";
+	}
+
+}
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/endtoend/TracingGraphics.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/endtoend/TracingGraphics.java
new file mode 100644
index 0000000..6a16725
--- /dev/null
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/endtoend/TracingGraphics.java
@@ -0,0 +1,214 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Florian Thienel 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:
+ * 		Florian Thienel - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.vex.core.internal.layout.endtoend;
+
+import java.net.URL;
+
+import org.eclipse.vex.core.internal.core.Color;
+import org.eclipse.vex.core.internal.core.ColorResource;
+import org.eclipse.vex.core.internal.core.FontMetrics;
+import org.eclipse.vex.core.internal.core.FontResource;
+import org.eclipse.vex.core.internal.core.FontSpec;
+import org.eclipse.vex.core.internal.core.Graphics;
+import org.eclipse.vex.core.internal.core.Image;
+import org.eclipse.vex.core.internal.core.Rectangle;
+import org.eclipse.vex.core.internal.layout.FakeImage;
+
+/**
+ * @author Florian Thienel
+ */
+public class TracingGraphics implements Graphics {
+
+	public static final int CHAR_WIDTH = 6;
+
+	public static final FontMetrics FONT_METRICS = new FontMetrics() {
+		@Override
+		public int getAscent() {
+			return 8;
+		}
+
+		@Override
+		public int getDescent() {
+			return 4;
+		}
+
+		@Override
+		public int getHeight() {
+			return getDescent() + getAscent() + getLeading();
+		}
+
+		@Override
+		public int getLeading() {
+			return 3;
+		}
+	};
+
+	private final Tracer tracer;
+
+	private boolean antiAliased;
+	private int lineWidth;
+	private int lineStyle;
+	private FontResource font;
+	private ColorResource color;
+
+	public TracingGraphics(final Tracer tracer) {
+		this.tracer = tracer;
+	}
+
+	@Override
+	public int charsWidth(final char[] data, final int offset, final int length) {
+		return CHAR_WIDTH * length;
+	}
+
+	@Override
+	public ColorResource createColor(final Color color) {
+		tracer.trace("Graphics.createColor({0})", color);
+		return new TracingColorResource(tracer, color);
+	}
+
+	@Override
+	public FontResource createFont(final FontSpec fontSpec) {
+		tracer.trace("Graphics.createFont({0})", fontSpec);
+		return new TracingFontResource(tracer, fontSpec);
+	}
+
+	@Override
+	public void dispose() {
+		tracer.trace("Graphics.dispose()");
+	}
+
+	@Override
+	public void drawChars(final char[] chars, final int offset, final int length, final int x, final int y) {
+		tracer.trace("Graphics.drawChars({0}, {1,number,#}, {2,number,#}, {3,number,#}, {4,number,#})", new String(chars), offset, length, x, y);
+	}
+
+	@Override
+	public void drawLine(final int x1, final int y1, final int x2, final int y2) {
+		tracer.trace("Graphics.drawLine({0,number,#}, {1,number,#}, {2,number,#}, {3,number,#})", x1, y1, x2, y2);
+	}
+
+	@Override
+	public void drawString(final String s, final int x, final int y) {
+		tracer.trace("Graphics.drawString({0}, {1,number,#}, {2,number,#})", s, x, y);
+	}
+
+	@Override
+	public void drawOval(final int x, final int y, final int width, final int height) {
+		tracer.trace("Graphics.drawOval({0,number,#}, {1,number,#}, {2,number,#}, {3,number,#})", x, y, width, height);
+	}
+
+	@Override
+	public void drawRect(final int x, final int y, final int width, final int height) {
+		tracer.trace("Graphics.drawRect({0,number,#}, {1,number,#}, {2,number,#}, {3,number,#})", x, y, width, height);
+	}
+
+	@Override
+	public void drawImage(final Image image, final int x, final int y, final int width, final int height) {
+		tracer.trace("Graphics.drawImage({0}, {1,number,#}, {2,number,#}, {3,number,#}, {4,number,#})", image, x, y, width, height);
+	}
+
+	@Override
+	public void fillOval(final int x, final int y, final int width, final int height) {
+		tracer.trace("Graphics.fillOval({0,number,#}, {1,number,#}, {2,number,#}, {3,number,#})", x, y, width, height);
+	}
+
+	@Override
+	public void fillRect(final int x, final int y, final int width, final int height) {
+		tracer.trace("Graphics.fillRect({0,number,#}, {1,number,#}, {2,number,#}, {3,number,#})", x, y, width, height);
+	}
+
+	@Override
+	public Rectangle getClipBounds() {
+		return new Rectangle(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE);
+	}
+
+	@Override
+	public ColorResource getColor() {
+		return color;
+	}
+
+	@Override
+	public FontResource getFont() {
+		return font;
+	}
+
+	@Override
+	public int getLineStyle() {
+		return lineStyle;
+	}
+
+	@Override
+	public int getLineWidth() {
+		return lineWidth;
+	}
+
+	@Override
+	public ColorResource getSystemColor(final int id) {
+		tracer.trace("Graphics.getSystemColor({0})", id);
+		return new TracingColorResource(tracer, id);
+	}
+
+	@Override
+	public FontMetrics getFontMetrics() {
+		return FONT_METRICS;
+	}
+
+	@Override
+	public Image getImage(final URL url) {
+		tracer.trace("Graphics.getImage({0})", url);
+		return new FakeImage(url);
+	}
+
+	@Override
+	public boolean isAntiAliased() {
+		return antiAliased;
+	}
+
+	@Override
+	public void setAntiAliased(final boolean antiAliased) {
+		tracer.trace("Graphics.setAntialiased({0})", antiAliased);
+		this.antiAliased = antiAliased;
+	}
+
+	@Override
+	public ColorResource setColor(final ColorResource color) {
+		tracer.trace("Graphics.setColor({0})", color);
+		final ColorResource oldColor = getColor();
+		this.color = color;
+		return oldColor;
+	}
+
+	@Override
+	public FontResource setFont(final FontResource font) {
+		tracer.trace("Graphics.setFont({0})", font);
+		final FontResource oldFont = getFont();
+		this.font = font;
+		return oldFont;
+	}
+
+	@Override
+	public void setLineStyle(final int style) {
+		tracer.trace("Graphics.setLineStyle({0})", style);
+		lineStyle = style;
+	}
+
+	@Override
+	public void setLineWidth(final int width) {
+		tracer.trace("Graphics.setLineWidth({0,number,#})", width);
+		lineWidth = width;
+	}
+
+	@Override
+	public int stringWidth(final String s) {
+		return CHAR_WIDTH * s.length();
+	}
+
+}
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/endtoend/TracingHostComponent.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/endtoend/TracingHostComponent.java
new file mode 100644
index 0000000..72b40cd
--- /dev/null
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/endtoend/TracingHostComponent.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Florian Thienel 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:
+ * 		Florian Thienel - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.vex.core.internal.layout.endtoend;
+
+import java.io.PrintStream;
+
+import org.eclipse.vex.core.internal.core.Graphics;
+import org.eclipse.vex.core.internal.core.Rectangle;
+import org.eclipse.vex.core.internal.widget.IHostComponent;
+
+/**
+ * @author Florian Thienel
+ */
+public class TracingHostComponent implements IHostComponent {
+
+	private final Tracer tracer;
+	private Rectangle viewPort = new Rectangle(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE);
+
+	public TracingHostComponent(final PrintStream out) {
+		tracer = new Tracer(out);
+	}
+
+	@Override
+	public Graphics createDefaultGraphics() {
+		tracer.trace("HostComponent.createDefaultGraphics()");
+		return new TracingGraphics(tracer);
+	}
+
+	@Override
+	public Rectangle getViewport() {
+		tracer.trace("HostComponent.getViewport()");
+		return viewPort;
+	}
+
+	public void setViewport(final Rectangle viewPort) {
+		tracer.trace("HostComponent.setViewport({0})", viewPort);
+		this.viewPort = viewPort;
+	}
+
+	@Override
+	public void fireSelectionChanged() {
+		tracer.trace("HostComponent.fireSelectionChanged()");
+	}
+
+	@Override
+	public void invokeLater(final Runnable runnable) {
+		tracer.trace("HostComponent.invokeLater({0})", runnable.getClass().getName());
+	}
+
+	@Override
+	public void repaint() {
+		tracer.trace("HostComponent.repaint()");
+	}
+
+	@Override
+	public void repaint(final int x, final int y, final int width, final int height) {
+		tracer.trace("HostComponent.repaint({0,number,#}, {1,number,#}, {2,number,#}, {3,number,#})", x, y, width, height);
+	}
+
+	@Override
+	public void scrollTo(final int left, final int top) {
+		tracer.trace("HostComponent.scrollTo({0,number,#}, {1,number,#})", left, top);
+	}
+
+	@Override
+	public void setPreferredSize(final int width, final int height) {
+		tracer.trace("HostComponent.setPreferredSize({0,number,#}. {1,number,#})", width, height);
+	}
+
+}
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/endtoend/simpleParagraph-input.xml b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/endtoend/simpleParagraph-input.xml
new file mode 100644
index 0000000..277f7f8
--- /dev/null
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/endtoend/simpleParagraph-input.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<root>
+	<p>The quick brown fox <b>jumps</b> over the lazy dog's tail.</p>
+</root>
\ No newline at end of file
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/endtoend/simpleParagraph-output.txt b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/endtoend/simpleParagraph-output.txt
new file mode 100644
index 0000000..95daf08
--- /dev/null
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/endtoend/simpleParagraph-output.txt
@@ -0,0 +1,122 @@
+HostComponent.createDefaultGraphics()
+Graphics.dispose()
+HostComponent.createDefaultGraphics()
+HostComponent.repaint(0, 0, 500, 2)
+Graphics.dispose()
+HostComponent.createDefaultGraphics()
+Graphics.createFont(FontSpec [names=[monospaced], size=10.0, style=PLAIN])
+Graphics.setFont(TracingFontResource [fontSpec=FontSpec [names=[monospaced], size=10.0, style=PLAIN]])
+Graphics.setFont(null)
+FontResource[FontSpec [names=[monospaced], size=10.0, style=PLAIN]].dispose()
+Graphics.createFont(FontSpec [names=[monospaced], size=10.0, style=PLAIN])
+Graphics.setFont(TracingFontResource [fontSpec=FontSpec [names=[monospaced], size=10.0, style=PLAIN]])
+Graphics.setFont(null)
+FontResource[FontSpec [names=[monospaced], size=10.0, style=PLAIN]].dispose()
+Graphics.createFont(FontSpec [names=[monospaced], size=10.0, style=PLAIN])
+Graphics.setFont(TracingFontResource [fontSpec=FontSpec [names=[monospaced], size=10.0, style=PLAIN]])
+Graphics.setFont(null)
+FontResource[FontSpec [names=[monospaced], size=10.0, style=PLAIN]].dispose()
+Graphics.createFont(FontSpec [names=[monospaced], size=10.0, style=PLAIN])
+Graphics.setFont(TracingFontResource [fontSpec=FontSpec [names=[monospaced], size=10.0, style=PLAIN]])
+Graphics.setFont(null)
+FontResource[FontSpec [names=[monospaced], size=10.0, style=PLAIN]].dispose()
+Graphics.createFont(FontSpec [names=[monospaced], size=10.0, style=PLAIN])
+Graphics.setFont(TracingFontResource [fontSpec=FontSpec [names=[monospaced], size=10.0, style=PLAIN]])
+Graphics.setFont(null)
+FontResource[FontSpec [names=[monospaced], size=10.0, style=PLAIN]].dispose()
+Graphics.createFont(FontSpec [names=[monospaced], size=10.0, style=PLAIN])
+Graphics.setFont(TracingFontResource [fontSpec=FontSpec [names=[monospaced], size=10.0, style=PLAIN]])
+Graphics.setFont(null)
+FontResource[FontSpec [names=[monospaced], size=10.0, style=PLAIN]].dispose()
+Graphics.createFont(FontSpec [names=[monospaced], size=10.0, style=PLAIN])
+Graphics.setFont(TracingFontResource [fontSpec=FontSpec [names=[monospaced], size=10.0, style=PLAIN]])
+Graphics.setFont(null)
+FontResource[FontSpec [names=[monospaced], size=10.0, style=PLAIN]].dispose()
+Graphics.createFont(FontSpec [names=[monospaced], size=10.0, style=PLAIN])
+Graphics.setFont(TracingFontResource [fontSpec=FontSpec [names=[monospaced], size=10.0, style=PLAIN]])
+Graphics.setFont(null)
+FontResource[FontSpec [names=[monospaced], size=10.0, style=PLAIN]].dispose()
+Graphics.createFont(FontSpec [names=[monospaced], size=10.0, style=PLAIN])
+Graphics.setFont(TracingFontResource [fontSpec=FontSpec [names=[monospaced], size=10.0, style=PLAIN]])
+Graphics.setFont(null)
+FontResource[FontSpec [names=[monospaced], size=10.0, style=PLAIN]].dispose()
+Graphics.createFont(FontSpec [names=[monospaced], size=10.0, style=PLAIN])
+Graphics.setFont(TracingFontResource [fontSpec=FontSpec [names=[monospaced], size=10.0, style=PLAIN]])
+Graphics.setFont(null)
+FontResource[FontSpec [names=[monospaced], size=10.0, style=PLAIN]].dispose()
+Graphics.createFont(FontSpec [names=[monospaced], size=10.0, style=PLAIN])
+Graphics.setFont(TracingFontResource [fontSpec=FontSpec [names=[monospaced], size=10.0, style=PLAIN]])
+Graphics.setFont(null)
+FontResource[FontSpec [names=[monospaced], size=10.0, style=PLAIN]].dispose()
+Graphics.dispose()
+HostComponent.getViewport()
+HostComponent.repaint(0, 0, 2147483647, 36)
+HostComponent.setPreferredSize(500. 36)
+HostComponent.createDefaultGraphics()
+Graphics.dispose()
+HostComponent.createDefaultGraphics()
+Graphics.dispose()
+HostComponent.getViewport()
+HostComponent.fireSelectionChanged()
+HostComponent.createDefaultGraphics()
+HostComponent.repaint(0, 0, 500, 2)
+Graphics.dispose()
+HostComponent.createDefaultGraphics()
+Graphics.setAntialiased(false)
+Graphics.setAntialiased(false)
+Graphics.setAntialiased(false)
+Graphics.setAntialiased(false)
+Graphics.setAntialiased(false)
+Graphics.setAntialiased(false)
+Graphics.createFont(FontSpec [names=[monospaced], size=10.0, style=PLAIN])
+Graphics.setFont(TracingFontResource [fontSpec=FontSpec [names=[monospaced], size=10.0, style=PLAIN]])
+Graphics.createColor(Color[r=0,g=0,b=0])
+Graphics.setColor(TracingColorResource [color=Color[r=0,g=0,b=0], id=-1])
+Graphics.drawChars(The quick brown , 0, 16, 0, 0)
+Graphics.setFont(null)
+Graphics.setColor(null)
+FontResource[FontSpec [names=[monospaced], size=10.0, style=PLAIN]].dispose()
+ColorResource[Color[r=0,g=0,b=0], -1].dispose()
+Graphics.createFont(FontSpec [names=[monospaced], size=10.0, style=PLAIN])
+Graphics.setFont(TracingFontResource [fontSpec=FontSpec [names=[monospaced], size=10.0, style=PLAIN]])
+Graphics.createColor(Color[r=0,g=0,b=0])
+Graphics.setColor(TracingColorResource [color=Color[r=0,g=0,b=0], id=-1])
+Graphics.drawChars(fox , 0, 4, 96, 0)
+Graphics.setFont(null)
+Graphics.setColor(null)
+FontResource[FontSpec [names=[monospaced], size=10.0, style=PLAIN]].dispose()
+ColorResource[Color[r=0,g=0,b=0], -1].dispose()
+Graphics.setAntialiased(false)
+Graphics.setAntialiased(false)
+Graphics.createFont(FontSpec [names=[monospaced], size=10.0, style=PLAIN])
+Graphics.setFont(TracingFontResource [fontSpec=FontSpec [names=[monospaced], size=10.0, style=PLAIN]])
+Graphics.createColor(Color[r=0,g=0,b=0])
+Graphics.setColor(TracingColorResource [color=Color[r=0,g=0,b=0], id=-1])
+Graphics.drawChars(jumps, 0, 5, 0, 12)
+Graphics.setFont(null)
+Graphics.setColor(null)
+FontResource[FontSpec [names=[monospaced], size=10.0, style=PLAIN]].dispose()
+ColorResource[Color[r=0,g=0,b=0], -1].dispose()
+Graphics.createFont(FontSpec [names=[monospaced], size=10.0, style=PLAIN])
+Graphics.setFont(TracingFontResource [fontSpec=FontSpec [names=[monospaced], size=10.0, style=PLAIN]])
+Graphics.createColor(Color[r=0,g=0,b=0])
+Graphics.setColor(TracingColorResource [color=Color[r=0,g=0,b=0], id=-1])
+Graphics.drawChars( over the lazy dog's , 0, 21, 0, 24)
+Graphics.setFont(null)
+Graphics.setColor(null)
+FontResource[FontSpec [names=[monospaced], size=10.0, style=PLAIN]].dispose()
+ColorResource[Color[r=0,g=0,b=0], -1].dispose()
+Graphics.createFont(FontSpec [names=[monospaced], size=10.0, style=PLAIN])
+Graphics.setFont(TracingFontResource [fontSpec=FontSpec [names=[monospaced], size=10.0, style=PLAIN]])
+Graphics.createColor(Color[r=0,g=0,b=0])
+Graphics.setColor(TracingColorResource [color=Color[r=0,g=0,b=0], id=-1])
+Graphics.drawChars(tail., 0, 5, 126, 24)
+Graphics.setFont(null)
+Graphics.setColor(null)
+FontResource[FontSpec [names=[monospaced], size=10.0, style=PLAIN]].dispose()
+ColorResource[Color[r=0,g=0,b=0], -1].dispose()
+Graphics.createColor(Color[r=0,g=0,b=0])
+Graphics.setColor(TracingColorResource [color=Color[r=0,g=0,b=0], id=-1])
+Graphics.fillRect(0, 0, 20, 2)
+Graphics.setColor(null)
+ColorResource[Color[r=0,g=0,b=0], -1].dispose()
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/endtoend/simpleParagraph.css b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/endtoend/simpleParagraph.css
new file mode 100644
index 0000000..7f1f91a
--- /dev/null
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/endtoend/simpleParagraph.css
@@ -0,0 +1,12 @@
+root {
+  display: block;
+  font: 10pt monospaced;
+}
+
+b {
+  display: inline;
+}
+
+p {
+  display: block;
+}
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/include.xml b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/include.xml
new file mode 100644
index 0000000..475c44e
--- /dev/null
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/include.xml
@@ -0,0 +1,102 @@
+<?xml version='1.0'?>

+<testcases css="test.css">

+

+	<test id="Include BlockBox" layoutWidth="500">

+		<doc><![CDATA[ <root><p><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="test" /></p></root> ]]></doc>

+		<result>

+			<box class="RootBox">

+				<box class="BlockElementBox">

+					<box class="BlockElementBox" element="root">

+						<box class="BlockElementBox" element="p">

+							<box class="IncludeBlockBox" element="xi:include">

+								<box class="ParagraphBox">

+									<box class="LineBox">

+										<!-- This is defined in vex-core-styles.css -->

+										<box class="StaticTextBox" text="&lt;XInclude href: " />

+										<box class="StaticTextBox" text="test"/>

+										<box class="StaticTextBox" text="&gt;"/>

+									</box>

+								</box>

+							</box>

+						</box>

+					</box>

+				</box>

+			</box>

+		</result>

+	</test>

+	

+	<test id="Include InlineBox" layoutWidth="500">

+		<!-- parse="text" causes the creation of an inline box (if possible)  -->

+		<doc><![CDATA[ <root><p><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="test" parse="text"/></p></root> ]]></doc>

+		<result>

+			<box class="RootBox">

+				<box class="BlockElementBox">

+					<box class="BlockElementBox" element="root">

+						<box class="BlockElementBox" element="p">

+							<box class="ParagraphBox">

+								<box class="LineBox">

+									<box class="PlaceholderBox" />

+									<box class="IncludeInlineBox" element="xi:include">

+										<!-- This is defined in vex-core-styles.css -->

+										<box class="StaticTextBox" text="&lt;XInclude href: " />

+										<box class="StaticTextBox" text="test"/>

+										<box class="StaticTextBox" text="&gt;"/>

+									</box>

+									<box class="PlaceholderBox" />

+								</box>

+							</box>

+						</box>

+					</box>

+				</box>

+			</box>

+		</result>

+	</test>

+	

+	<test id="Include in root" layoutWidth="500">

+		<doc><![CDATA[ <root><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="test" /></root> ]]></doc>

+		<result>

+			<box class="RootBox">

+				<box class="BlockElementBox">

+					<box class="BlockElementBox" element="root">

+						<box class="IncludeBlockBox" element="xi:include">

+							<box class="ParagraphBox">

+								<box class="LineBox">

+									<!-- This is defined in vex-core-styles.css -->

+									<box class="StaticTextBox" text="&lt;XInclude href: " />

+									<box class="StaticTextBox" text="test"/>

+									<box class="StaticTextBox" text="&gt;"/>

+								</box>

+							</box>

+						</box>

+					</box>

+				</box>

+			</box>

+		</result>

+	</test>

+	

+	<test id="Remove IncludeInlineBox with content" layoutWidth="500" performActions="true">

+		<doc><![CDATA[ <root><p>ab<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="test" parse="text"><xi:fallback>12345</xi:fallback></xi:include></p></root> ]]></doc>

+		<result>

+			<box class="RootBox">

+				<box class="BlockElementBox">

+					<box class="BlockElementBox" element="root">

+						<box class="BlockElementBox" element="p">

+							<box class="ParagraphBox">

+								<box class="LineBox">

+									<box class="DocumentTextBox" text="ab" />

+									<box class="PlaceholderBox" shouldBeRemoved="1"/>

+									<box class="IncludeInlineBox" element="xi:include" removeElementAction="1">

+										<box class="StaticTextBox" text="&lt;XInclude href: " />

+										<box class="StaticTextBox" text="test"/>

+										<box class="StaticTextBox" text="&gt;"/>

+									</box>

+									<box class="PlaceholderBox" />

+								</box>

+							</box>

+						</box>

+					</box>

+				</box>

+			</box>

+		</result>

+	</test>

+</testcases>

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/lists.css b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/lists.css
new file mode 100644
index 0000000..d8cb7ba
--- /dev/null
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/lists.css
@@ -0,0 +1,33 @@
+root {
+	display: block;
+}
+
+ul {
+	display: block;
+	list-style-type: disc;
+}
+
+ul ul {
+	list-style-type: square;
+}
+
+ul ul ul {
+	list-style-type: circle;
+}
+
+ol {
+	display: block;
+	list-item-style: decimal;
+}
+
+ol ol {
+  list-style-type: lower-alpha;
+}
+
+ol ol ol {
+  list-style-type: lower-roman;
+}
+
+li {
+  display: list-item;
+}
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/lists.xml b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/lists.xml
new file mode 100644
index 0000000..6db2071
--- /dev/null
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/lists.xml
@@ -0,0 +1,142 @@
+<?xml version='1.0'?>
+<testcases css="lists.css">
+
+	<test id="UL one level (empty)" layoutWidth="100">
+		<doc><![CDATA[ <root><ul><li></li></ul></root> ]]></doc>
+		<result>
+			<box class="RootBox">
+				<box class="BlockElementBox">
+					<box class="BlockElementBox" element="root">
+						<box class="BlockElementBox" element="ul">
+							<box class="ListItemBox" element="li">
+								<box class="ParagraphBox">
+									<box class="LineBox">
+										<box class="PlaceholderBox" />
+									</box>
+								</box>
+							</box>
+						</box>
+					</box>
+				</box>
+			</box>
+		</result>
+	</test>
+
+	<test id="UL two levels (empty)" layoutWidth="100">
+		<doc><![CDATA[ <root><ul><ul><li></li></ul></ul></root> ]]></doc>
+		<result>
+			<box class="RootBox">
+				<box class="BlockElementBox">
+					<box class="BlockElementBox" element="root">
+						<box class="BlockElementBox" element="ul">
+							<box class="BlockElementBox" element="ul">
+								<box class="ListItemBox" element="li">
+									<box class="ParagraphBox">
+										<box class="LineBox">
+											<box class="PlaceholderBox" />
+										</box>
+									</box>
+								</box>
+							</box>
+						</box>
+					</box>
+				</box>
+			</box>
+		</result>
+	</test>
+
+	<test id="UL three levels (empty)" layoutWidth="100">
+		<doc><![CDATA[ <root><ul><ul><ul><li></li></ul></ul></ul></root> ]]></doc>
+		<result>
+			<box class="RootBox">
+				<box class="BlockElementBox">
+					<box class="BlockElementBox" element="root">
+						<box class="BlockElementBox" element="ul">
+							<box class="BlockElementBox" element="ul">
+								<box class="BlockElementBox" element="ul">
+									<box class="ListItemBox" element="li">
+										<box class="ParagraphBox">
+											<box class="LineBox">
+												<box class="PlaceholderBox" />
+											</box>
+										</box>
+									</box>
+								</box>
+							</box>
+						</box>
+					</box>
+				</box>
+			</box>
+		</result>
+	</test>
+
+	<test id="OL one level (empty)" layoutWidth="100">
+		<doc><![CDATA[ <root><ol><li></li></ol></root> ]]></doc>
+		<result>
+			<box class="RootBox">
+				<box class="BlockElementBox">
+					<box class="BlockElementBox" element="root">
+						<box class="BlockElementBox" element="ol">
+							<box class="ListItemBox" element="li">
+								<box class="ParagraphBox">
+									<box class="LineBox">
+										<box class="PlaceholderBox" />
+									</box>
+								</box>
+							</box>
+						</box>
+					</box>
+				</box>
+			</box>
+		</result>
+	</test>
+
+	<test id="OL two levels (empty)" layoutWidth="100">
+		<doc><![CDATA[ <root><ol><ol><li></li></ol></ol></root> ]]></doc>
+		<result>
+			<box class="RootBox">
+				<box class="BlockElementBox">
+					<box class="BlockElementBox" element="root">
+						<box class="BlockElementBox" element="ol">
+							<box class="BlockElementBox" element="ol">
+								<box class="ListItemBox" element="li">
+									<box class="ParagraphBox">
+										<box class="LineBox">
+											<box class="PlaceholderBox" />
+										</box>
+									</box>
+								</box>
+							</box>
+						</box>
+					</box>
+				</box>
+			</box>
+		</result>
+	</test>
+
+	<test id="OL three levels (empty)" layoutWidth="100">
+		<doc><![CDATA[ <root><ol><ol><ol><li></li></ol></ol></ol></root> ]]></doc>
+		<result>
+			<box class="RootBox">
+				<box class="BlockElementBox">
+					<box class="BlockElementBox" element="root">
+						<box class="BlockElementBox" element="ol">
+							<box class="BlockElementBox" element="ol">
+								<box class="BlockElementBox" element="ol">
+									<box class="ListItemBox" element="li">
+										<box class="ParagraphBox">
+											<box class="LineBox">
+												<box class="PlaceholderBox" />
+											</box>
+										</box>
+									</box>
+								</box>
+							</box>
+						</box>
+					</box>
+				</box>
+			</box>
+		</result>
+	</test>
+
+</testcases>
\ No newline at end of file
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/simple-edit.xml b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/simple-edit.xml
index dc05bf2..536b9c1 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/simple-edit.xml
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/simple-edit.xml
@@ -7,7 +7,7 @@
 			<box class="RootBox">

 				<box class="BlockElementBox">

 					<box class="BlockElementBox" element="root" layoutState="LAYOUT_PROPAGATE">

-						<box class="BlockElementBox" element="p" layoutState="LAYOUT_REDO">

+						<box class="BlockElementBox" element="p" layoutState="LAYOUT_PROPAGATE">

 							<box class="ParagraphBox">

 								<box class="LineBox">

 									<box class="DocumentTextBox" text="before" />

@@ -71,7 +71,7 @@
 				<box class="BlockElementBox">

 					<box class="BlockElementBox" element="root">

 					

-						<box class="BlockElementBox" element="p" layoutState="LAYOUT_REDO">

+						<box class="BlockElementBox" element="p">

 							<box class="ParagraphBox">

 								<box class="LineBox">

 									<box class="DocumentTextBox" text="before" />

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/tables.xml b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/tables.xml
index e9a25b9..ab4a3dc 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/tables.xml
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/tables.xml
@@ -305,7 +305,7 @@
 	</test>
 
 
-<!-- 
+<!--
 	<test id="Anonymous Table and Row - Empty" layoutWidth="100">
 		<doc><![CDATA[ <root><td></td></root> ]]></doc>
 		<result>
@@ -588,7 +588,7 @@
 														</box>
 														<box class="TableRowGroupBox" element="tbody">
 															<box class="TableRowBox">
-						
+
 															</box>
 														</box>
 													</box>
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/validator/DTDValidatorTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/validator/DTDValidatorTest.java
index df646ed..b19138d 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/validator/DTDValidatorTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/validator/DTDValidatorTest.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *     Igor Jacy Lino Campista - Java 5 warnings fixed (bug 311325)
@@ -28,6 +28,7 @@
 
 import org.eclipse.core.runtime.QualifiedName;
 import org.eclipse.vex.core.internal.dom.Document;
+import org.eclipse.vex.core.internal.dom.Namespace;
 import org.eclipse.vex.core.provisional.dom.AttributeDefinition;
 import org.eclipse.vex.core.provisional.dom.IDocument;
 import org.eclipse.vex.core.provisional.dom.IElement;
@@ -39,6 +40,7 @@
 public class DTDValidatorTest {
 
 	private IValidator validator = null;
+	private static final QualifiedName XI = new QualifiedName(Namespace.XINCLUDE_NAMESPACE_URI, "include");
 
 	@Before
 	public void setUp() {
@@ -85,7 +87,7 @@
 	// anySet.add("para");
 	// anySet.add("emphasis");
 	// assertEquals(anySet, getValidItemsAt(doc, 1));
-	//		
+	//
 	// }
 
 	@Test
@@ -200,6 +202,16 @@
 		}
 	}
 
+	private void assertIsValidSequence(final QualifiedName parentElement, final QualifiedName... sequence) {
+		for (int i = 0; i < sequence.length; i++) {
+			final List<QualifiedName> prefix = createPrefix(i, sequence);
+			final List<QualifiedName> toInsert = Collections.singletonList(sequence[i]);
+			final List<QualifiedName> suffix = createSuffix(i, sequence);
+
+			assertTrue(validator.isValidSequence(parentElement, prefix, toInsert, suffix, false));
+		}
+	}
+
 	private static List<QualifiedName> createPrefix(final int index, final String... sequence) {
 		final List<QualifiedName> prefix = new ArrayList<QualifiedName>();
 		for (int i = 0; i < index; i++) {
@@ -216,6 +228,22 @@
 		return suffix;
 	}
 
+	private static List<QualifiedName> createPrefix(final int index, final QualifiedName... sequence) {
+		final List<QualifiedName> prefix = new ArrayList<QualifiedName>();
+		for (int i = 0; i < index; i++) {
+			prefix.add(sequence[i]);
+		}
+		return prefix;
+	}
+
+	private static List<QualifiedName> createSuffix(final int index, final QualifiedName... sequence) {
+		final List<QualifiedName> suffix = new ArrayList<QualifiedName>();
+		for (int i = index + 1; i < sequence.length; i++) {
+			suffix.add(sequence[i]);
+		}
+		return suffix;
+	}
+
 	@Test
 	public void testGetAttributes_shouldReturnAllAttributesButNamespaceDefs() throws Exception {
 		// xmlns:xxx attributes should not be returned
@@ -273,4 +301,14 @@
 		}
 		return adMap;
 	}
+
+	@Test
+	public void testValidationShouldIgnoreXInclude() throws Exception {
+		final QualifiedName section = new QualifiedName(null, "section");
+		final QualifiedName title = new QualifiedName(null, "title");
+		final QualifiedName para = new QualifiedName(null, "para");
+
+		assertIsValidSequence(section, XI, title, para);
+		assertIsValidSequence(section, para, XI, para);
+	}
 }
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/validator/SchemaValidatorTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/validator/SchemaValidatorTest.java
index 6b18519..7f4ce23 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/validator/SchemaValidatorTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/validator/SchemaValidatorTest.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  * 		Carsten Hiesserich - tests for attribute namespaces

@@ -32,6 +32,7 @@
 import org.eclipse.core.runtime.QualifiedName;

 import org.eclipse.vex.core.internal.dom.Document;

 import org.eclipse.vex.core.internal.dom.Element;

+import org.eclipse.vex.core.internal.dom.Namespace;

 import org.eclipse.vex.core.internal.io.DocumentReader;

 import org.eclipse.vex.core.provisional.dom.AttributeDefinition;

 import org.eclipse.vex.core.provisional.dom.DocumentContentModel;

@@ -57,6 +58,7 @@
 	private static final QualifiedName P = new QualifiedName(CONTENT_NS, "p");

 	private static final QualifiedName B = new QualifiedName(CONTENT_NS, "b");

 	private static final QualifiedName I = new QualifiedName(CONTENT_NS, "i");

+	private static final QualifiedName XI = new QualifiedName(Namespace.XINCLUDE_NAMESPACE_URI, "include");

 

 	@Test

 	public void readDocumentWithTwoSchemas() throws Exception {

@@ -282,6 +284,13 @@
 		assertTrue("isRequired should be true", ad.isRequired());

 	}

 

+	@Test

+	public void testValidationShouldIgnoreXInclude() throws Exception {

+		final IValidator validator = new WTPVEXValidator(CONTENT_NS);

+		assertIsValidSequence(validator, P, XI);

+		assertIsValidSequence(validator, P, XI, B, I);

+	}

+

 	private Map<QualifiedName, AttributeDefinition> getAttributeMap() {

 		final IDocument doc = new Document(new QualifiedName(null, "chapter"));

 		final IValidator validator = new WTPVEXValidator(STRUCTURE_NS);

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2CommentEditingTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2CommentEditingTest.java
index 73590f6..5e9339d 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2CommentEditingTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2CommentEditingTest.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

@@ -50,7 +50,7 @@
 		final IComment comment = widget.insertComment();

 		assertTrue(rootElement.getRange().contains(comment.getRange()));

 		assertSame(rootElement, comment.getParent());

-		assertEquals(comment.getEndOffset(), widget.getCaretOffset());

+		assertEquals(comment.getEndPosition(), widget.getCaretPosition());

 	}

 

 	@Test

@@ -91,7 +91,7 @@
 		widget.insertElement(TITLE);

 		widget.insertText("1text before comment1");

 		widget.insertComment();

-		final INode comment = widget.getDocument().getChildAt(widget.getCaretOffset());

+		final INode comment = widget.getDocument().getChildAt(widget.getCaretPosition());

 		widget.insertText("2comment text2");

 		widget.moveBy(1);

 		widget.insertText("3text after comment3");

@@ -99,9 +99,10 @@
 		final String expectedContentStructure = getContentStructure(widget.getDocument().getRootElement());

 

 		widget.doWork(new Runnable() {

+			@Override

 			public void run() {

-				widget.moveTo(comment.getStartOffset() + 1, false);

-				widget.moveTo(comment.getEndOffset() - 1, true);

+				widget.moveTo(comment.getStartPosition().moveBy(1), false);

+				widget.moveTo(comment.getEndPosition().moveBy(-1), true);

 				final IDocumentFragment fragment = widget.getSelectedFragment();

 				widget.deleteSelection();

 

@@ -124,8 +125,8 @@
 		final String expectedXml = getCurrentXML(widget);

 

 		final IComment comment = widget.insertComment();

-		widget.moveTo(comment.getStartOffset());

-		widget.moveTo(comment.getEndOffset(), true);

+		widget.moveTo(comment.getStartPosition());

+		widget.moveTo(comment.getEndPosition(), true);

 		widget.deleteSelection();

 

 		widget.undo(); // delete

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2ProcessingInstructionEditingTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2ProcessingInstructionEditingTest.java
index 5219523..c5ab526 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2ProcessingInstructionEditingTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2ProcessingInstructionEditingTest.java
@@ -4,7 +4,7 @@
  * 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:
  * 		Carsten Hiesserich - initial API and implementation
  *******************************************************************************/
@@ -64,8 +64,8 @@
 
 		final IProcessingInstruction pi = widget.insertProcessingInstruction("target");
 
-		widget.moveTo(pi.getStartOffset());
-		widget.moveTo(pi.getEndOffset(), true);
+		widget.moveTo(pi.getStartPosition());
+		widget.moveTo(pi.getEndPosition(), true);
 		widget.deleteSelection();
 
 		widget.undo(); // delete
@@ -88,8 +88,8 @@
 		widget.doWork(new Runnable() {
 			@Override
 			public void run() {
-				widget.moveTo(pi.getStartOffset() + 1, false);
-				widget.moveTo(pi.getEndOffset() - 1, true);
+				widget.moveTo(pi.getStartPosition().moveBy(1), false);
+				widget.moveTo(pi.getEndPosition().moveBy(-1), true);
 				final IDocumentFragment fragment = widget.getSelectedFragment();
 				widget.deleteSelection();
 
@@ -133,7 +133,7 @@
 
 		final String expectedContentStructure = getContentStructure(widget.getDocument().getRootElement());
 
-		widget.moveTo(pi.getStartOffset() + 1);
+		widget.moveTo(pi.getStartPosition().moveBy(1));
 		widget.editProcessingInstruction("new", "data");
 		widget.undo();
 
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2SelectionTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2SelectionTest.java
index 5fea581..2433996 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2SelectionTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2SelectionTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************

- * Copyright (c) 2012 Florian Thienel and others.

+ * Copyright (c) 2012, 2014 Florian Thienel 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

@@ -7,10 +7,12 @@
  *

  * Contributors:

  * 		Florian Thienel - initial API and implementation

+ *      Carsten Hiesserich - additional tests

  *******************************************************************************/

 package org.eclipse.vex.core.internal.widget;

 

 import static org.eclipse.vex.core.internal.widget.VexWidgetTest.PARA;

+import static org.eclipse.vex.core.internal.widget.VexWidgetTest.PRE;

 import static org.eclipse.vex.core.internal.widget.VexWidgetTest.TITLE;

 import static org.eclipse.vex.core.internal.widget.VexWidgetTest.createDocumentWithDTD;

 import static org.eclipse.vex.core.tests.TestResources.TEST_DTD;

@@ -45,7 +47,7 @@
 		widget.moveBy(-1, true);

 		assertTrue(widget.hasSelection());

 		assertEquals(titleElement.getRange(), widget.getSelectedRange());

-		assertEquals(titleElement.getStartOffset(), widget.getCaretOffset());

+		assertEquals(titleElement.getStartPosition(), widget.getCaretPosition());

 	}

 

 	@Test

@@ -53,10 +55,43 @@
 		final IElement titleElement = widget.insertElement(TITLE);

 		widget.insertText("Hello World");

 		widget.moveBy(-5, false);

-		widget.moveTo(titleElement.getStartOffset(), true);

+		widget.moveTo(titleElement.getStartPosition(), true);

 		assertTrue(widget.hasSelection());

 		assertEquals(titleElement.getRange(), widget.getSelectedRange());

-		assertEquals(titleElement.getStartOffset(), widget.getCaretOffset());

+		assertEquals(titleElement.getStartPosition(), widget.getCaretPosition());

+	}

+

+	@Test

+	public void givenCaretInElementWith_whenSelectionForwardIncludesStartOffset_shouldExpandSelectionToEndOffset() throws Exception {

+		widget.insertElement(PARA);

+		widget.insertText("before");

+		final IElement innerElement = widget.insertElement(PRE);

+		widget.insertText("Selection");

+		widget.moveTo(innerElement.getEndPosition().moveBy(1));

+		widget.insertText("after");

+

+		widget.moveTo(innerElement.getStartPosition().moveBy(-1));

+		widget.moveTo(innerElement.getStartPosition().moveBy(1), true);

+

+		assertTrue(widget.hasSelection());

+		assertEquals(innerElement.getStartPosition().moveBy(-1), widget.getSelectedPositionRange().getStartPosition());

+		assertEquals(innerElement.getEndPosition().moveBy(1), widget.getSelectedPositionRange().getEndPosition());

+		assertEquals(innerElement.getEndPosition().moveBy(1), widget.getCaretPosition());

+	}

+

+	@Test

+	public void givenCaretInElementWith_whenSelectionBackwardIncludesStartOffset_shouldExpandSelectionToEndOffset() throws Exception {

+		widget.insertElement(PARA);

+		final IElement innerElement = widget.insertElement(PRE);

+		widget.insertText("Selection");

+		widget.moveTo(innerElement.getEndPosition().moveBy(1));

+		widget.insertText("after");

+		widget.moveTo(innerElement.getEndPosition().moveBy(-1));

+		widget.moveTo(innerElement.getStartPosition(), true);

+

+		assertTrue(widget.hasSelection());

+		assertEquals(innerElement.getRange(), widget.getSelectedRange());

+		assertEquals(innerElement.getStartPosition(), widget.getCaretPosition());

 	}

 

 	@Test

@@ -66,36 +101,36 @@
 		widget.moveBy(1, true);

 		assertTrue(widget.hasSelection());

 		assertEquals(titleElement.getRange(), widget.getSelectedRange());

-		assertEquals(titleElement.getEndOffset() + 1, widget.getCaretOffset());

+		assertEquals(titleElement.getEndPosition().moveBy(1), widget.getCaretPosition());

 	}

 

 	@Test

 	public void givenCaretInElementAtEndOffset_whenMovedOneBehindStartOffset_shouldNotIncludeEndOffsetInSelectedRange() throws Exception {

 		final IElement titleElement = widget.insertElement(TITLE);

 		widget.insertText("Hello World");

-		widget.moveTo(titleElement.getStartOffset() + 1, true);

+		widget.moveTo(titleElement.getStartPosition().moveBy(1), true);

 		assertEquals(titleElement.getRange().resizeBy(1, -1), widget.getSelectedRange());

-		assertEquals(titleElement.getStartOffset() + 1, widget.getCaretOffset());

+		assertEquals(titleElement.getStartPosition().moveBy(1), widget.getCaretPosition());

 	}

 

 	@Test

 	public void givenCaretAtStartOffsetOfElementWithText_whenMovedByOneForward_shouldExpandSelectionBehindEndOffset() throws Exception {

 		final IElement titleElement = widget.insertElement(TITLE);

 		widget.insertText("Hello World");

-		widget.moveTo(titleElement.getStartOffset(), false);

+		widget.moveTo(titleElement.getStartPosition(), false);

 		widget.moveBy(1, true);

 		assertEquals(titleElement.getRange(), widget.getSelectedRange());

-		assertEquals(titleElement.getEndOffset() + 1, widget.getCaretOffset());

+		assertEquals(titleElement.getEndPosition().moveBy(1), widget.getCaretPosition());

 	}

 

 	@Test

 	public void givenCaretAtStartOffsetOfElementWithText_whenMovedOneForwardAndOneBackward_shouldSelectNothing() throws Exception {

 		final IElement titleElement = widget.insertElement(TITLE);

 		widget.insertText("Hello World");

-		widget.moveTo(titleElement.getStartOffset(), false);

+		widget.moveTo(titleElement.getStartPosition(), false);

 		widget.moveBy(1, true);

 		widget.moveBy(-1, true);

-		assertEquals(titleElement.getStartOffset(), widget.getCaretOffset());

+		assertEquals(titleElement.getStartPosition(), widget.getCaretPosition());

 	}

 

 	@Test

@@ -105,11 +140,11 @@
 		widget.moveBy(1);

 		final IElement paraElement = widget.insertElement(PARA);

 		widget.insertText("Hello Again");

-		widget.moveTo(titleElement.getStartOffset() + 3);

-		widget.moveTo(paraElement.getEndOffset() + 1, true);

+		widget.moveTo(titleElement.getStartPosition().moveBy(3));

+		widget.moveTo(paraElement.getEndPosition().moveBy(1), true);

 		widget.moveBy(-1, true);

 		assertEquals(titleElement.getRange(), widget.getSelectedRange());

-		assertEquals(titleElement.getEndOffset() + 1, widget.getCaretOffset());

+		assertEquals(titleElement.getEndPosition().moveBy(1), widget.getCaretPosition());

 	}

 

 	@Test

@@ -119,12 +154,12 @@
 		widget.moveBy(1);

 		final IElement paraElement = widget.insertElement(PARA);

 		widget.insertText("Hello Again");

-		widget.moveTo(titleElement.getStartOffset() + 3);

-		widget.moveTo(paraElement.getEndOffset() + 1, true);

+		widget.moveTo(titleElement.getStartPosition().moveBy(3));

+		widget.moveTo(paraElement.getEndPosition().moveBy(1), true);

 		widget.moveBy(-1, true);

 		widget.moveBy(-1, true);

 		assertEquals(titleElement.getRange().resizeBy(3, -1), widget.getSelectedRange());

-		assertEquals(titleElement.getEndOffset(), widget.getCaretOffset());

+		assertEquals(titleElement.getEndPosition(), widget.getCaretPosition());

 	}

 

 	@Test

@@ -134,11 +169,11 @@
 		widget.moveBy(1);

 		final IElement paraElement = widget.insertElement(PARA);

 		widget.insertText("Hello Again");

-		widget.moveTo(paraElement.getEndOffset() - 3);

-		widget.moveTo(titleElement.getStartOffset(), true);

+		widget.moveTo(paraElement.getEndPosition().moveBy(-3));

+		widget.moveTo(titleElement.getStartPosition(), true);

 		widget.moveBy(1, true);

 		assertEquals(paraElement.getRange(), widget.getSelectedRange());

-		assertEquals(paraElement.getStartOffset(), widget.getCaretOffset());

+		assertEquals(paraElement.getStartPosition(), widget.getCaretPosition());

 	}

 

 	@Test

@@ -148,12 +183,12 @@
 		widget.moveBy(1);

 		final IElement paraElement = widget.insertElement(PARA);

 		widget.insertText("Hello Again");

-		widget.moveTo(paraElement.getEndOffset() - 3);

-		widget.moveTo(titleElement.getStartOffset(), true);

+		widget.moveTo(paraElement.getEndPosition().moveBy(-3));

+		widget.moveTo(titleElement.getStartPosition(), true);

 		widget.moveBy(1, true);

 		widget.moveBy(1, true);

 		assertEquals(paraElement.getRange().resizeBy(1, -4), widget.getSelectedRange());

-		assertEquals(paraElement.getStartOffset() + 1, widget.getCaretOffset());

+		assertEquals(paraElement.getStartPosition().moveBy(+1), widget.getCaretPosition());

 	}

 

 	@Test

@@ -162,7 +197,7 @@
 		widget.moveBy(-1, true);

 		assertTrue(widget.hasSelection());

 		assertEquals(comment.getRange(), widget.getSelectedRange());

-		assertEquals(comment.getStartOffset(), widget.getCaretOffset());

+		assertEquals(comment.getStartPosition(), widget.getCaretPosition());

 	}

 

 	@Test

@@ -182,7 +217,7 @@
 

 		widget.selectContentOf(title);

 

-		assertEquals(title.getEndOffset(), widget.getCaretOffset());

+		assertEquals(title.getEndPosition(), widget.getCaretPosition());

 		assertFalse(widget.hasSelection());

 	}

 

@@ -202,8 +237,8 @@
 		hostComponent.selectionChanged = false;

 		widget.beginWork();

 		final IElement title = widget.insertElement(TITLE);

-		widget.moveTo(title.getStartOffset());

-		widget.moveTo(title.getEndOffset(), true);

+		widget.moveTo(title.getStartPosition());

+		widget.moveTo(title.getEndPosition(), true);

 		final boolean selectionChangedWhileWorking = hostComponent.selectionChanged;

 		widget.endWork(true);

 

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2SimpleEditingTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2SimpleEditingTest.java
index 7c314f2..2badabf 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2SimpleEditingTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2SimpleEditingTest.java
@@ -63,20 +63,20 @@
 	@Test

 	public void shouldStartInRootElement() throws Exception {

 		assertSame(rootElement, widget.getCurrentElement());

-		assertEquals(rootElement.getEndOffset(), widget.getCaretOffset());

+		assertEquals(rootElement.getEndPosition(), widget.getCaretPosition());

 	}

 

 	@Test

 	public void shouldMoveCaretIntoInsertedElement() throws Exception {

 		final IElement titleElement = widget.insertElement(TITLE);

-		assertEquals(titleElement.getEndOffset(), widget.getCaretOffset());

+		assertEquals(titleElement.getEndPosition(), widget.getCaretPosition());

 	}

 

 	@Test

 	public void shouldProvideInsertionElementAsCurrentElement() throws Exception {

 		final IElement titleElement = widget.insertElement(TITLE);

 		widget.moveBy(-1);

-		assertEquals(titleElement.getStartOffset(), widget.getCaretOffset());

+		assertEquals(titleElement.getStartPosition(), widget.getCaretPosition());

 		assertSame(rootElement, widget.getCurrentElement());

 	}

 

@@ -86,7 +86,7 @@
 		widget.insertText("Hello");

 		widget.deletePreviousChar();

 		assertEquals("Hell", titleElement.getText());

-		assertEquals(titleElement.getEndOffset(), widget.getCaretOffset());

+		assertEquals(titleElement.getEndPosition(), widget.getCaretPosition());

 	}

 

 	@Test

@@ -96,7 +96,7 @@
 		widget.moveBy(-5);

 		widget.deleteNextChar();

 		assertEquals("ello", titleElement.getText());

-		assertEquals(titleElement.getStartOffset() + 1, widget.getCaretOffset());

+		assertEquals(titleElement.getStartPosition().moveBy(1), widget.getCaretPosition());

 	}

 

 	@Test

@@ -155,7 +155,7 @@
 		final IElement para2 = widget.insertElement(PARA);

 		widget.insertText("World");

 

-		widget.moveTo(para2.getStartOffset());

+		widget.moveTo(para2.getStartPosition());

 		widget.deletePreviousChar();

 

 		assertEquals(2, rootElement.children().count());

@@ -176,7 +176,7 @@
 		final IElement para2 = widget.insertElement(PARA);

 		widget.insertText("World");

 

-		widget.moveTo(para2.getStartOffset());

+		widget.moveTo(para2.getStartPosition());

 		widget.deleteNextChar();

 

 		assertEquals(2, rootElement.children().count());

@@ -197,7 +197,7 @@
 		final IElement para2 = widget.insertElement(PARA);

 		widget.insertText("World");

 

-		widget.moveTo(para2.getStartOffset() + 1);

+		widget.moveTo(para2.getStartPosition().moveBy(1));

 		widget.deletePreviousChar();

 

 		assertEquals(2, rootElement.children().count());

@@ -218,7 +218,7 @@
 		final IElement para2 = widget.insertElement(PARA);

 		widget.insertText("World");

 

-		widget.moveTo(para1.getEndOffset());

+		widget.moveTo(para1.getEndPosition());

 		widget.deleteNextChar();

 

 		assertEquals(2, rootElement.children().count());

@@ -276,7 +276,7 @@
 		widget.moveBy(1);

 		final IElement para = widget.insertElement(PARA);

 		final IDocumentFragment fragment = widget.getDocument().getFragment(para.getRange());

-		widget.moveTo(rootElement.getEndOffset());

+		widget.moveTo(rootElement.getEndPosition());

 

 		widget.setReadOnly(true);

 		assertFalse(widget.canInsertFragment(fragment));

@@ -289,7 +289,7 @@
 		widget.moveBy(1);

 		final IElement para1 = widget.insertElement(PARA);

 		widget.insertText("Hello");

-		widget.moveTo(para1.getEndOffset());

+		widget.moveTo(para1.getEndPosition());

 		widget.insertText("\n");

 		assertEquals("Hello", para1.getText());

 		assertEquals(3, rootElement.children().count());

@@ -299,7 +299,7 @@
 	public void givenPreElement_whenInsertingNewline_shouldInsertNewline() throws Exception {

 		final IElement para = widget.insertElement(PARA);

 		final IElement preElement = widget.insertElement(PRE);

-		assertEquals(preElement.getEndOffset(), widget.getCaretOffset());

+		assertEquals(preElement.getEndPosition(), widget.getCaretPosition());

 		widget.insertText("line1");

 		widget.insertText("\n");

 		assertEquals(1, para.children().count());

@@ -311,13 +311,13 @@
 		final IElement para1 = widget.insertElement(PARA);

 		widget.moveBy(1);

 		final IElement para2 = widget.insertElement(PARA);

-		widget.moveTo(para1.getEndOffset());

+		widget.moveTo(para1.getEndPosition());

 		widget.insertText("Para1");

-		widget.moveTo(para2.getEndOffset());

+		widget.moveTo(para2.getEndPosition());

 		widget.insertText("Para2");

 

 		// Insert position is invalid

-		widget.moveTo(para1.getEndOffset() + 1);

+		widget.moveTo(para1.getEndPosition().moveBy(1));

 		try {

 			widget.insertText("Test");

 		} catch (final Exception ex) {

@@ -332,13 +332,13 @@
 		final IElement para1 = widget.insertElement(PARA);

 		widget.moveBy(1);

 		final IElement para2 = widget.insertElement(PARA);

-		widget.moveTo(para1.getEndOffset());

+		widget.moveTo(para1.getEndPosition());

 		widget.insertText("Para1");

-		widget.moveTo(para2.getEndOffset());

+		widget.moveTo(para2.getEndPosition());

 		widget.insertText("Para2");

 

 		// Insert position is invalid

-		widget.moveTo(para1.getEndOffset());

+		widget.moveTo(para1.getEndPosition());

 		try {

 			widget.insertElement(PARA);

 		} catch (final Exception ex) {

@@ -352,7 +352,7 @@
 	public void givenPreElement_whenInsertingTextWithNewline_shouldInsertNewline() throws Exception {

 		widget.insertElement(PARA);

 		final IElement preElement = widget.insertElement(PRE);

-		assertEquals(preElement.getEndOffset(), widget.getCaretOffset());

+		assertEquals(preElement.getEndPosition(), widget.getCaretPosition());

 		widget.insertText("line1\nline2");

 		assertEquals("line1\nline2", preElement.getText());

 	}

@@ -362,7 +362,7 @@
 		widget.insertElement(PARA);

 		final IElement preElement = widget.insertElement(PRE);

 

-		widget.moveTo(preElement.getEndOffset());

+		widget.moveTo(preElement.getEndPosition());

 		widget.insertText("line1\nline2   end");

 

 		final List<? extends INode> children = preElement.children().asList();

@@ -373,10 +373,10 @@
 	@Test

 	public void givenNonPreElement_whenInsertingText_shouldCompressWhitespace() throws Exception {

 		final IElement para = widget.insertElement(PARA);

-		widget.moveTo(para.getEndOffset());

+		widget.moveTo(para.getEndPosition());

 		widget.insertText("line1\nline2   \t end");

 

-		final List<? extends INode> children = rootElement.children().after(para.getStartOffset()).asList();

+		final List<? extends INode> children = rootElement.children().after(para.getStartPosition().getOffset()).asList();

 		assertEquals("two para elements", 2, children.size());

 		assertTrue("original para element", children.get(0) instanceof IParent);

 		assertTrue("splitted para element", children.get(1) instanceof IParent);

@@ -387,10 +387,10 @@
 	@Test

 	public void givenNonPreElement_whenInsertingText_shouldCompressNewlines() throws Exception {

 		final IElement para = widget.insertElement(PARA);

-		widget.moveTo(para.getEndOffset());

+		widget.moveTo(para.getEndPosition());

 		widget.insertText("line1\n\nline2");

 

-		final List<? extends INode> children = rootElement.children().after(para.getStartOffset()).asList();

+		final List<? extends INode> children = rootElement.children().after(para.getStartPosition().getOffset()).asList();

 		assertEquals("two para elements", 2, children.size());

 		assertTrue("original para element", children.get(0) instanceof IParent);

 		assertTrue("splitted para element", children.get(1) instanceof IParent);

@@ -401,13 +401,13 @@
 	@Test

 	public void givenNonPreElement_whenSplitting_shouldSplitIntoTwoElements() throws Exception {

 		final IElement para = widget.insertElement(PARA);

-		widget.moveTo(para.getEndOffset());

+		widget.moveTo(para.getEndPosition());

 		widget.insertText("line1line2");

 		widget.moveBy(-5);

 

 		widget.split();

 

-		final List<? extends INode> children = rootElement.children().after(para.getStartOffset()).asList();

+		final List<? extends INode> children = rootElement.children().after(para.getStartPosition().getOffset()).asList();

 		assertEquals("two para elements", 2, children.size());

 		assertTrue("original para element", children.get(0) instanceof IParent);

 		assertTrue("splitted para element", children.get(1) instanceof IParent);

@@ -421,13 +421,13 @@
 	public void givenPreElement_whenSplitting_shouldSplitIntoTwoElements() throws Exception {

 		final IElement para = widget.insertElement(PARA);

 		final IElement preElement = widget.insertElement(PRE);

-		widget.moveTo(preElement.getEndOffset());

+		widget.moveTo(preElement.getEndPosition());

 		widget.insertText("line1line2");

 		widget.moveBy(-5);

 

 		widget.split();

 

-		final List<? extends INode> children = para.children().after(preElement.getStartOffset()).asList();

+		final List<? extends INode> children = para.children().after(preElement.getStartPosition().getOffset()).asList();

 		assertEquals("two para elements", 2, children.size());

 		assertTrue("original pre element", children.get(0) instanceof IParent);

 		assertTrue("splitted pre element", children.get(1) instanceof IParent);

@@ -472,7 +472,7 @@
 	public void givenElementWithMultipleOccurrence_whenCaretRightAfterStartIndex_shouldSplit() throws Exception {

 		final IElement para = widget.insertElement(PARA);

 		widget.insertText("12345");

-		widget.moveTo(para.getStartOffset() + 1);

+		widget.moveTo(para.getStartPosition().moveBy(1));

 		widget.split();

 

 		final List<? extends INode> children = rootElement.children().asList();

@@ -555,13 +555,13 @@
 

 	@Test

 	public void givenBeforeRootElement_cannotSplitElement() throws Exception {

-		widget.moveTo(rootElement.getStartOffset());

+		widget.moveTo(rootElement.getStartPosition());

 		assertFalse(widget.canSplit());

 	}

 

 	@Test(expected = DocumentValidationException.class)

 	public void givenBeforeRootElement_whenSplitting_shouldThrowDocumentValidationException() throws Exception {

-		widget.moveTo(rootElement.getStartOffset());

+		widget.moveTo(rootElement.getStartPosition());

 		widget.split();

 	}

 

@@ -802,8 +802,8 @@
 		widget.insertText("3");

 		widget.moveBy(1);

 

-		widget.moveTo(firstPara.getStartOffset());

-		widget.moveTo(lastPara.getEndOffset(), true);

+		widget.moveTo(firstPara.getStartPosition());

+		widget.moveTo(lastPara.getEndPosition(), true);

 

 		assertTrue(widget.canJoin());

 	}

@@ -820,8 +820,8 @@
 		widget.insertText("3");

 		widget.moveBy(1);

 

-		widget.moveTo(firstPara.getStartOffset());

-		widget.moveTo(lastPara.getEndOffset(), true);

+		widget.moveTo(firstPara.getStartPosition());

+		widget.moveTo(lastPara.getEndPosition(), true);

 

 		widget.join();

 

@@ -841,8 +841,8 @@
 		firstPara.setAttribute("id", "para1");

 		lastPara.setAttribute("id", "para3");

 

-		widget.moveTo(firstPara.getStartOffset());

-		widget.moveTo(lastPara.getEndOffset(), true);

+		widget.moveTo(firstPara.getStartPosition());

+		widget.moveTo(lastPara.getEndPosition(), true);

 

 		widget.join();

 

@@ -862,8 +862,8 @@
 		firstPara.setAttribute("id", "para1");

 		lastPara.setAttribute("id", "para3");

 

-		widget.moveTo(firstPara.getStartOffset());

-		widget.moveTo(lastPara.getEndOffset(), true);

+		widget.moveTo(firstPara.getStartPosition());

+		widget.moveTo(lastPara.getEndPosition(), true);

 

 		widget.join();

 		widget.undo();

@@ -885,8 +885,8 @@
 		final IElement lastSection = widget.insertElement(SECTION);

 		widget.insertElement(TITLE);

 

-		widget.moveTo(firstSection.getStartOffset());

-		widget.moveTo(lastSection.getEndOffset(), true);

+		widget.moveTo(firstSection.getStartPosition());

+		widget.moveTo(lastSection.getEndPosition(), true);

 

 		assertFalse(widget.canJoin());

 	}

@@ -905,8 +905,8 @@
 		final IElement lastSection = widget.insertElement(SECTION);

 		widget.insertElement(TITLE);

 

-		widget.moveTo(firstSection.getStartOffset());

-		widget.moveTo(lastSection.getEndOffset(), true);

+		widget.moveTo(firstSection.getStartPosition());

+		widget.moveTo(lastSection.getEndPosition(), true);

 

 		widget.join();

 	}

@@ -923,8 +923,8 @@
 		widget.insertText("3");

 		widget.moveBy(1);

 

-		widget.moveTo(title.getStartOffset());

-		widget.moveTo(lastPara.getEndOffset(), true);

+		widget.moveTo(title.getStartPosition());

+		widget.moveTo(lastPara.getEndPosition(), true);

 

 		assertFalse(widget.canJoin());

 	}

@@ -941,8 +941,8 @@
 		widget.insertText("3");

 		widget.moveBy(1);

 

-		widget.moveTo(title.getStartOffset());

-		widget.moveTo(lastPara.getEndOffset(), true);

+		widget.moveTo(title.getStartPosition());

+		widget.moveTo(lastPara.getEndPosition(), true);

 

 		widget.join();

 	}

@@ -965,7 +965,7 @@
 	public void givenOnlyTextSelected_cannotJoin() throws Exception {

 		final IElement title = widget.insertElement(TITLE);

 		widget.insertText("title text");

-		widget.moveTo(title.getStartOffset() + 1, true);

+		widget.moveTo(title.getStartPosition().moveBy(1), true);

 

 		assertFalse(widget.canJoin());

 	}

@@ -985,7 +985,7 @@
 	@Test

 	public void givenOnlySingleElementSelected_cannotJoin() throws Exception {

 		final IElement title = widget.insertElement(TITLE);

-		widget.moveTo(title.getStartOffset(), true);

+		widget.moveTo(title.getStartPosition(), true);

 

 		assertFalse(widget.canJoin());

 	}

@@ -993,7 +993,7 @@
 	@Test

 	public void givenOnlySingleElementSelected_whenRequestedToJoin_shouldIgnoreGracefully() throws Exception {

 		final IElement title = widget.insertElement(TITLE);

-		widget.moveTo(title.getStartOffset(), true);

+		widget.moveTo(title.getStartPosition(), true);

 		final String expectedXml = getCurrentXML(widget);

 

 		widget.join();

@@ -1012,8 +1012,8 @@
 		final IComment lastComment = widget.insertComment();

 		widget.insertText("comment3");

 

-		widget.moveTo(firstComment.getStartOffset());

-		widget.moveTo(lastComment.getEndOffset(), true);

+		widget.moveTo(firstComment.getStartPosition());

+		widget.moveTo(lastComment.getEndPosition(), true);

 

 		assertTrue(widget.canJoin());

 	}

@@ -1029,8 +1029,8 @@
 		final IComment lastComment = widget.insertComment();

 		widget.insertText("comment3");

 

-		widget.moveTo(firstComment.getStartOffset());

-		widget.moveTo(lastComment.getEndOffset(), true);

+		widget.moveTo(firstComment.getStartPosition());

+		widget.moveTo(lastComment.getEndPosition(), true);

 

 		widget.join();

 

@@ -1046,8 +1046,8 @@
 		final IElement lastElement = widget.insertElement(PRE);

 		widget.insertText("2 ");

 

-		widget.moveTo(firstElement.getStartOffset());

-		widget.moveTo(lastElement.getEndOffset(), true);

+		widget.moveTo(firstElement.getStartPosition());

+		widget.moveTo(lastElement.getEndPosition(), true);

 

 		widget.join();

 

@@ -1064,8 +1064,8 @@
 		final IElement lastElement = widget.insertElement(PRE);

 		widget.insertText("2 ");

 

-		widget.moveTo(firstElement.getStartOffset());

-		widget.moveTo(lastElement.getEndOffset(), true);

+		widget.moveTo(firstElement.getStartPosition());

+		widget.moveTo(lastElement.getEndPosition(), true);

 

 		assertFalse(widget.canJoin());

 	}

@@ -1080,8 +1080,8 @@
 		final IElement lastElement = widget.insertElement(PRE);

 		widget.insertText("2 ");

 

-		widget.moveTo(firstElement.getStartOffset());

-		widget.moveTo(lastElement.getEndOffset(), true);

+		widget.moveTo(firstElement.getStartPosition());

+		widget.moveTo(lastElement.getEndPosition(), true);

 

 		widget.join();

 	}

@@ -1090,14 +1090,27 @@
 	public void givenDeletedText_whenDeleteUndone_shouldSetCaretToEndOfRecoveredText() throws Exception {

 		final IElement title = widget.insertElement(TITLE);

 		widget.insertText("Hello World");

-		widget.moveTo(title.getStartOffset() + 1);

+		widget.moveTo(title.getStartPosition().moveBy(1));

 		widget.moveBy(5, true);

-		final int expectedCaretOffset = widget.getSelectedRange().getEndOffset() + 1;

+		final int expectedCaretPosition = widget.getSelectedRange().getEndOffset() + 1;

 

 		widget.deleteSelection();

 		widget.undo();

 

-		assertEquals(expectedCaretOffset, widget.getCaretOffset());

+		assertEquals(expectedCaretPosition, widget.getCaretPosition().getOffset());

+	}

+

+	@Test

+	public void afterDeletingSelection_CaretPositionShouldBeValid() throws Exception {

+		final IElement para = widget.insertElement(PARA);

+		widget.moveTo(para.getEndPosition());

+		final IElement pre = widget.insertElement(PRE);

+		widget.insertText("Hello World");

+		widget.moveTo(pre.getStartPosition());

+		widget.moveTo(pre.getEndPosition().moveBy(-1), true);

+

+		widget.deleteSelection();

+		assertEquals(para.getEndPosition(), widget.getCaretPosition());

 	}

 

 	private static StyleSheet readTestStyleSheet() throws IOException {

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2StyleSheetTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2StyleSheetTest.java
index da9a355..32ebaa0 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2StyleSheetTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2StyleSheetTest.java
@@ -4,7 +4,7 @@
  * 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:
  *     Carsten Hiesserich - initial API and implementation
  *******************************************************************************/
@@ -54,8 +54,8 @@
 
 		assertNotNull("Styles for inserted element", styles);
 
-		widget.moveTo(element.getStartOffset());
-		widget.moveTo(element.getEndOffset(), true);
+		widget.moveTo(element.getStartPosition());
+		widget.moveTo(element.getEndPosition(), true);
 		widget.deleteSelection();
 
 		assertFalse("Styles for deleted element should be removed from cache.", widget.getStyleSheet().testGetStylesCache().containsKey(element));
@@ -71,7 +71,7 @@
 		assertEquals("Background color from <para> style", new Color(255, 255, 255), styles.getBackgroundColor());
 
 		// Insert a new PARA before the existing one
-		widget.moveTo(element.getStartOffset());
+		widget.moveTo(element.getStartPosition());
 		final IElement newElement = widget.insertElement(PARA);
 		final Styles newStyles = widget.getStyleSheet().getStyles(element);
 		assertNotNull("New styles for element", styles);
@@ -93,8 +93,8 @@
 		assertEquals("Background color from <para + para> style", new Color(255, 0, 0), styles.getBackgroundColor());
 
 		// Delete the first PARA
-		widget.moveTo(element1.getStartOffset());
-		widget.moveTo(element1.getEndOffset(), true);
+		widget.moveTo(element1.getStartPosition());
+		widget.moveTo(element1.getEndPosition(), true);
 		widget.deleteSelection();
 
 		final Styles newStyles = widget.getStyleSheet().getStyles(element2);
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2XIncludeEditingTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2XIncludeEditingTest.java
new file mode 100644
index 0000000..5a1f156
--- /dev/null
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2XIncludeEditingTest.java
@@ -0,0 +1,132 @@
+/*******************************************************************************

+ * Copyright (c) 2014 Carsten Hiesserich 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:

+ * 		Carsten Hiesserich - initial API and implementation

+ *******************************************************************************/

+package org.eclipse.vex.core.internal.widget;

+

+import static org.eclipse.vex.core.internal.widget.VexWidgetTest.createDocumentWithDTD;

+import static org.eclipse.vex.core.internal.widget.VexWidgetTest.getCurrentXML;

+import static org.eclipse.vex.core.tests.TestResources.TEST_DTD;

+import static org.junit.Assert.assertEquals;

+import static org.junit.Assert.assertFalse;

+import static org.junit.Assert.assertNull;

+import static org.junit.Assert.assertTrue;

+

+import org.eclipse.vex.core.internal.css.CssWhitespacePolicy;

+import org.eclipse.vex.core.internal.css.StyleSheet;

+import org.eclipse.vex.core.internal.io.XMLFragment;

+import org.eclipse.vex.core.provisional.dom.IElement;

+import org.eclipse.vex.core.provisional.dom.IIncludeNode;

+import org.junit.Before;

+import org.junit.Test;

+

+/**

+ * @author Florian Thienel

+ */

+public class L2XIncludeEditingTest {

+

+	private final String includeXml = "<para>12<xi:include xmlns:xi=\"http://www.w3.org/2001/XInclude\" href=\"test\" />34</para>";

+	private final String includeInlineXml = "<para>12<xi:include xmlns:xi=\"http://www.w3.org/2001/XInclude\" href=\"test\" parse=\"text\" />34</para>";

+

+	private IVexWidget widget;

+	private IElement rootElement;

+	private IElement para;

+	private IIncludeNode includeNode;

+

+	@Before

+	public void setUp() throws Exception {

+		widget = new BaseVexWidget(new MockHostComponent());

+		widget.setDocument(createDocumentWithDTD(TEST_DTD, "section"), StyleSheet.NULL);

+		widget.setWhitespacePolicy(new CssWhitespacePolicy(widget.getStyleSheet()));

+	}

+

+	@Test

+	public void whenCaretAfterEmptyInclude_BackspaceShouldDeleteInclude() throws Exception {

+		createIncludeElement(includeXml);

+		widget.moveTo(includeNode.getEndPosition().moveBy(1));

+		widget.deletePreviousChar();

+

+		assertTrue(para.children().withoutText().isEmpty());

+		assertFalse(includeNode.isAssociated());

+		assertNull(includeNode.getReference().getParent());

+	}

+

+	@Test

+	public void whenIncludeSelected_ShouldDeleteInclude() throws Exception {

+		createIncludeElement(includeXml);

+		widget.moveTo(includeNode.getStartPosition());

+		widget.moveTo(includeNode.getEndPosition(), true);

+		widget.deleteSelection();

+

+		final String currentXml = getCurrentXML(widget);

+		assertEquals("<section><para>1234</para></section>", currentXml);

+

+		assertTrue(para.children().withoutText().isEmpty());

+		assertFalse(includeNode.isAssociated());

+		assertNull(includeNode.getReference().getParent());

+	}

+

+	@Test

+	public void deleteInlineIncludeWithSurroundingContent() throws Exception {

+		createIncludeElement(includeInlineXml);

+

+		widget.moveTo(includeNode.getStartPosition());

+		widget.moveTo(para.getEndPosition().moveBy(-1), true);

+		widget.deleteSelection();

+

+		final String currentXml = getCurrentXML(widget);

+		assertEquals("<section><para>124</para></section>", currentXml);

+

+		assertTrue(para.children().withoutText().isEmpty());

+		assertFalse(includeNode.isAssociated());

+		assertNull(includeNode.getReference().getParent());

+	}

+

+	@Test

+	public void deleteInlineIncludeWithSurroundingContent_selectingBackwards() throws Exception {

+		createIncludeElement(includeInlineXml);

+

+		// Yes, the direction of the selection makes a difference

+		widget.moveTo(para.getEndPosition().moveBy(-1));

+		widget.moveTo(includeNode.getStartPosition(), true);

+

+		widget.deleteSelection();

+

+		final String currentXml = getCurrentXML(widget);

+		assertEquals("<section><para>124</para></section>", currentXml);

+

+		assertTrue(para.children().withoutText().isEmpty());

+		assertFalse(includeNode.isAssociated());

+		assertNull(includeNode.getReference().getParent());

+	}

+

+	@Test

+	public void undoDeleteInclude() throws Exception {

+		createIncludeElement(includeXml);

+		widget.moveTo(includeNode.getStartPosition());

+		widget.moveTo(includeNode.getEndPosition(), true);

+		final String exepctedXml = getCurrentXML(widget);

+		widget.deleteSelection();

+		widget.undo();

+		assertEquals(exepctedXml, getCurrentXML(widget));

+

+		para = (IElement) rootElement.children().get(0);

+		includeNode = (IIncludeNode) para.children().withoutText().get(0);

+		assertTrue(includeNode.isAssociated());

+		assertEquals(para, includeNode.getReference().getParent());

+	}

+

+	private void createIncludeElement(final String xml) {

+		widget.insertFragment(new XMLFragment(xml).getDocumentFragment());

+		rootElement = widget.getDocument().getRootElement();

+		para = (IElement) rootElement.children().get(0);

+		includeNode = (IIncludeNode) para.children().withoutText().get(0);

+	}

+

+}

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2XmlInsertionTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2XmlInsertionTest.java
index a342528..cde5166 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2XmlInsertionTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2XmlInsertionTest.java
@@ -4,8 +4,8 @@
  * 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: 
+ *
+ * Contributors:
  * 		Carsten Hiesserich - initial API and implementation
  *******************************************************************************/
 package org.eclipse.vex.core.internal.widget;
@@ -59,13 +59,13 @@
 		para1 = widget.insertElement(PARA);
 		widget.moveBy(1);
 		widget.insertElement(PARA);
-		widget.moveTo(para1.getEndOffset());
+		widget.moveTo(para1.getEndPosition());
 		pre = widget.insertElement(PRE);
 	}
 
 	@Test
 	public void givenNonPreElement_whenInsertingNotAllowedXML_shouldInsertTextOnly() throws Exception {
-		widget.moveTo(para1.getStartOffset() + 1);
+		widget.moveTo(para1.getStartPosition().moveBy(1));
 		widget.insertXML(createParaXML());
 
 		assertEquals("beforeinnerafter", para1.getText());
@@ -73,14 +73,14 @@
 
 	@Test(expected = DocumentValidationException.class)
 	public void givenNonPreElement_whenInsertingInvalidXML_shouldThrowDocumentValidationExeption() throws Exception {
-		widget.moveTo(para1.getStartOffset() + 1);
+		widget.moveTo(para1.getStartPosition().moveBy(1));
 
 		widget.insertXML("<emphasis>someText</para>");
 	}
 
 	@Test
 	public void givenNonPreElement_whenInsertingValidXML_shouldInsertXml() throws Exception {
-		widget.moveTo(para1.getEndOffset());
+		widget.moveTo(para1.getEndPosition());
 		widget.insertXML(createInlineXML("before", "inner", "after"));
 
 		final List<? extends INode> children = para1.children().asList();
@@ -95,7 +95,7 @@
 
 	@Test
 	public void givenPreElement_whenInsertingInvalidXML_shouldInsertTextWithWhitespace() throws Exception {
-		widget.moveTo(pre.getStartOffset() + 1);
+		widget.moveTo(pre.getStartPosition().moveBy(1));
 		widget.insertXML(createParaXML());
 
 		assertEquals("beforeinnerafter", pre.getText());
@@ -103,7 +103,7 @@
 
 	@Test
 	public void givenPreElement_whenInsertingValidXML_shouldInsertXML() throws Exception {
-		widget.moveTo(pre.getEndOffset());
+		widget.moveTo(pre.getEndPosition());
 		widget.insertXML(createInlineXML("before", "inner", "after"));
 
 		final List<? extends INode> children = pre.children().asList();
@@ -117,7 +117,7 @@
 
 	@Test
 	public void givenPreElement_whenInsertingValidXMLWithWhitespace_shouldKeepWhitespace() throws Exception {
-		widget.moveTo(pre.getEndOffset());
+		widget.moveTo(pre.getEndPosition());
 		widget.insertXML(createInlineXML("line1\nline2   end", "inner", "after"));
 
 		final List<? extends INode> children = pre.children().asList();
@@ -131,10 +131,10 @@
 
 	@Test
 	public void whenInsertingMixedXMLWithWhitespace_shouldKeepWhitecpaceInPre() throws Exception {
-		widget.moveTo(para1.getEndOffset());
+		widget.moveTo(para1.getEndPosition());
 		widget.insertXML("before<pre>pre1\npre2  end</pre>after   \nend");
 
-		final List<? extends INode> children = para1.children().after(pre.getEndOffset()).asList();
+		final List<? extends INode> children = para1.children().after(pre.getEndPosition().getOffset()).asList();
 		assertEquals("New children count", 3, children.size());
 		assertTrue("Expecting IText", children.get(0) instanceof IText);
 		assertEquals("before", children.get(0).getText());
@@ -146,13 +146,13 @@
 
 	@Test(expected = CannotRedoException.class)
 	public void givenNonPreElement_whenInsertingNotAllowedFragment_shouldThrowCannotRedoException() throws Exception {
-		widget.moveTo(para1.getStartOffset() + 1);
+		widget.moveTo(para1.getStartPosition().moveBy(1));
 		widget.insertFragment(createParaFragment());
 	}
 
 	@Test
 	public void givenNonPreElement_whenInsertingValidFragment_shouldInsertXml() throws Exception {
-		widget.moveTo(para1.getEndOffset());
+		widget.moveTo(para1.getEndPosition());
 		widget.insertFragment(createInlineFragment("before", "inner", "after"));
 
 		final List<? extends INode> children = para1.children().asList();
@@ -167,13 +167,13 @@
 
 	@Test(expected = CannotRedoException.class)
 	public void givenPreElement_whenInsertingInvalidFragment_shouldThrowCannotRedoException() throws Exception {
-		widget.moveTo(pre.getStartOffset() + 1);
+		widget.moveTo(pre.getStartPosition().moveBy(1));
 		widget.insertFragment(createParaFragment());
 	}
 
 	@Test
 	public void givenPreElement_whenInsertingValidFragment_shouldInsertXML() throws Exception {
-		widget.moveTo(pre.getEndOffset());
+		widget.moveTo(pre.getEndPosition());
 		widget.insertFragment(createInlineFragment("before", "inner", "after"));
 
 		final List<? extends INode> children = pre.children().asList();
@@ -187,7 +187,7 @@
 
 	@Test
 	public void givenPreElement_whenInsertingValidFragmentWithWhitespace_shouldKeepWhitespace() throws Exception {
-		widget.moveTo(pre.getEndOffset());
+		widget.moveTo(pre.getEndPosition());
 		widget.insertFragment(createInlineFragment("line1\nline2   end", "inner", "after"));
 
 		final List<? extends INode> children = pre.children().asList();
@@ -201,10 +201,10 @@
 
 	@Test
 	public void whenInsertingMixedFragmentWithWhitespace_shouldKeepWhitecpaceInPre() throws Exception {
-		widget.moveTo(para1.getEndOffset());
+		widget.moveTo(para1.getEndPosition());
 		widget.insertFragment(new XMLFragment("before<pre>pre1\npre2  end</pre>after   \nend").getDocumentFragment());
 
-		final List<? extends INode> children = para1.children().after(pre.getEndOffset()).asList();
+		final List<? extends INode> children = para1.children().after(pre.getEndPosition().getOffset()).asList();
 		assertEquals("New children count", 3, children.size());
 		assertTrue("Expecting IText", children.get(0) instanceof IText);
 		assertEquals("before", children.get(0).getText());
@@ -230,7 +230,7 @@
 		emp.associate(content, new ContentRange(offset, offset + 1));
 		nodes.add(emp);
 
-		content.insertText(emp.getEndOffset(), inner);
+		content.insertText(emp.getEndPosition().getOffset(), inner);
 
 		content.insertText(content.length(), after);
 
@@ -253,7 +253,7 @@
 		para.associate(content, new ContentRange(offset, offset + 1));
 		nodes.add(para);
 
-		content.insertText(para.getEndOffset(), "inner");
+		content.insertText(para.getEndPosition().getOffset(), "inner");
 
 		content.insertText(content.length(), "after");
 
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/MockHostComponent.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/MockHostComponent.java
index 695504d..9e7990b 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/MockHostComponent.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/MockHostComponent.java
@@ -18,30 +18,38 @@
 
 	public boolean selectionChanged;
 
+	@Override
 	public Graphics createDefaultGraphics() {
 		return new FakeGraphics();
 	}
 
+	@Override
 	public void fireSelectionChanged() {
 		selectionChanged = true;
 	}
 
+	@Override
 	public Rectangle getViewport() {
 		return new Rectangle(0, 0, 0, 0);
 	}
 
+	@Override
 	public void invokeLater(final Runnable runnable) {
 	}
 
+	@Override
 	public void repaint() {
 	}
 
+	@Override
 	public void repaint(final int x, final int y, final int width, final int height) {
 	}
 
+	@Override
 	public void scrollTo(final int left, final int top) {
 	}
 
+	@Override
 	public void setPreferredSize(final int width, final int height) {
 	}
 
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/VexWidgetTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/VexWidgetTest.java
index 9ed6173..8159954 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/VexWidgetTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/VexWidgetTest.java
@@ -22,6 +22,7 @@
 import org.eclipse.vex.core.internal.dom.Document;
 import org.eclipse.vex.core.internal.io.XMLFragment;
 import org.eclipse.vex.core.internal.validator.WTPVEXValidator;
+import org.eclipse.vex.core.provisional.dom.ContentPosition;
 import org.eclipse.vex.core.provisional.dom.IDocument;
 import org.eclipse.vex.core.provisional.dom.IDocumentFragment;
 import org.eclipse.vex.core.provisional.dom.IElement;
@@ -110,6 +111,7 @@
 		final String expectedContentStructure = getContentStructure(widget.getDocument().getRootElement());
 
 		widget.doWork(new Runnable() {
+			@Override
 			public void run() {
 				widget.selectContentOf(comment);
 				final IDocumentFragment fragment = widget.getSelectedFragment();
@@ -127,6 +129,34 @@
 		assertEquals(expectedContentStructure, getContentStructure(widget.getDocument().getRootElement()));
 	}
 
+	/* bug 421401 */
+	@Test
+	public void whenClickedRightToLineEnd_shouldSetCursorToLineEnd() throws Exception {
+		final IDocument document = createDocument(STRUCTURE_NS, "chapter");
+		widget.setDocument(document, StyleSheet.NULL);
+		widget.insertElement(new QualifiedName(CONTENT_NS, "p"));
+		widget.insertText("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris.");
+		widget.setLayoutWidth(200); // breaks after "amet, "
+
+		final ContentPosition lastPositionInFirstLine = widget.viewToModel(210, 5);
+		assertEquals("last position", 30, lastPositionInFirstLine.getOffset());
+
+		final ContentPosition firstPositionInSecondLine = widget.viewToModel(0, 15);
+		assertEquals("first position", 31, firstPositionInSecondLine.getOffset());
+	}
+
+	@Test
+	public void whenMovingCursorUp_shouldNotGetStuckInHigherLevelElement() throws Exception {
+		final IDocument document = createDocument(STRUCTURE_NS, "chapter");
+		widget.setDocument(document, StyleSheet.NULL);
+		widget.insertElement(new QualifiedName(CONTENT_NS, "p"));
+		widget.insertText("para 1");
+		widget.moveTo(new ContentPosition(document, 1));
+
+		widget.moveToNextLine(false);
+		assertEquals(2, widget.getCaretPosition().getOffset());
+	}
+
 	public static IDocument createDocumentWithDTD(final String dtdIdentifier, final String rootElementName) {
 		final IValidator validator = new WTPVEXValidator(dtdIdentifier);
 		final Document document = new Document(new QualifiedName(null, rootElementName));
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/swt/DocumentFragmentTransferTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/swt/DocumentFragmentTransferTest.java
index 834cd6e..a25e3c8 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/swt/DocumentFragmentTransferTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/swt/DocumentFragmentTransferTest.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/tests/TestResources.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/tests/TestResources.java
index 85de261..f43c3a5 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/tests/TestResources.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/tests/TestResources.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

@@ -16,7 +16,7 @@
 

 /**

  * Provides access to the resources under /testResources.

- * 

+ *

  * @author Florian Thienel

  */

 public class TestResources {

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/tests/VEXCoreTestPlugin.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/tests/VEXCoreTestPlugin.java
index d61de3e..0f7b9ea 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/tests/VEXCoreTestPlugin.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/tests/VEXCoreTestPlugin.java
@@ -22,7 +22,7 @@
 
 	/*
 	 * (non-Javadoc)
-	 * 
+	 *
 	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext )
 	 */
 	@Override
@@ -33,7 +33,7 @@
 
 	/*
 	 * (non-Javadoc)
-	 * 
+	 *
 	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext )
 	 */
 	@Override
@@ -44,7 +44,7 @@
 
 	/**
 	 * Returns the shared instance
-	 * 
+	 *
 	 * @return the shared instance
 	 */
 	public static VEXCoreTestPlugin getDefault() {
diff --git a/org.eclipse.vex.core.tests/testResources/DocumentWriterTest1.xml b/org.eclipse.vex.core.tests/testResources/DocumentWriterTest1.xml
index 4b1428b..4517567 100644
--- a/org.eclipse.vex.core.tests/testResources/DocumentWriterTest1.xml
+++ b/org.eclipse.vex.core.tests/testResources/DocumentWriterTest1.xml
@@ -4,6 +4,7 @@
     <p>This should be a complex document with some <a href="here is a
     URL">elements with attributes</a>. The more complex, the more
     thorough the check will be.</p>
+    <p>Here we test in<b>line</b> elements.</p>
     
     <img src="http://myhost.com/really/long/path/to/a/jpeg.jpg" alt="&lt;pickin &amp; grinnin&gt;"/>
     
diff --git a/org.eclipse.vex.core.tests/testResources/documentWithDtdPublic.xml b/org.eclipse.vex.core.tests/testResources/documentWithDtdPublic.xml
index 70c9dd4..08fa9f4 100644
--- a/org.eclipse.vex.core.tests/testResources/documentWithDtdPublic.xml
+++ b/org.eclipse.vex.core.tests/testResources/documentWithDtdPublic.xml
@@ -2,5 +2,5 @@
 <!DOCTYPE section PUBLIC "-//Eclipse Foundation//DTD Vex Test//EN" "test1.dtd">

 <section>

 	<title>Testdocument with DTD (Public Identifier)</title>

-	<para>This is a Testdocument using a DTD which is referenced by a public identifier.</para>

+	<para>This is a Test<emphasis>document</emphasis> using a DTD which is referenced by a public identifier.</para>

 </section>
\ No newline at end of file
diff --git a/org.eclipse.vex.core.tests/testResources/documentWithInclude.xml b/org.eclipse.vex.core.tests/testResources/documentWithInclude.xml
new file mode 100644
index 0000000..ca170a8
--- /dev/null
+++ b/org.eclipse.vex.core.tests/testResources/documentWithInclude.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<chapter xmlns="http://www.eclipse.org/vex/test/structure">
+	<title>Title</title>
+	<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="document.xml">
+		<!-- Test comment -->
+		<xi:fallback>
+			<chapter><title>Title2</title></chapter>
+		</xi:fallback>
+	</xi:include>
+	<para>12<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="document.xml" parse="text"/>34</para>
+</chapter>
\ No newline at end of file
diff --git a/org.eclipse.vex.core.tests/testResources/test.css b/org.eclipse.vex.core.tests/testResources/test.css
index 7885d56..3a414d9 100644
--- a/org.eclipse.vex.core.tests/testResources/test.css
+++ b/org.eclipse.vex.core.tests/testResources/test.css
@@ -32,6 +32,10 @@
   background-color: red;
 }
 
+emphasis {
+	display: inline;
+}
+
 pre {
   display: block;
   white-space: pre;
diff --git a/org.eclipse.vex.core/.classpath b/org.eclipse.vex.core/.classpath
index c72d35a..9ce3b1f 100644
--- a/org.eclipse.vex.core/.classpath
+++ b/org.eclipse.vex.core/.classpath
@@ -1,7 +1,11 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
-	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins">
+		<accessrules>
+			<accessrule kind="accessible" pattern="**/wst/**/internal/**"/>
+		</accessrules>
+	</classpathentry>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="output" path="target/classes"/>
 </classpath>
diff --git a/org.eclipse.vex.core/META-INF/MANIFEST.MF b/org.eclipse.vex.core/META-INF/MANIFEST.MF
index 06d0fc4..f74f6a5 100644
--- a/org.eclipse.vex.core/META-INF/MANIFEST.MF
+++ b/org.eclipse.vex.core/META-INF/MANIFEST.MF
@@ -16,16 +16,16 @@
  org.eclipse.xsd;bundle-version="[2.8.0,3.0.0)",
  org.eclipse.jface.text;bundle-version="[3.8.0,4.0.0)"
 Export-Package: org.eclipse.vex.core,
- org.eclipse.vex.core.internal;x-friends:="org.eclipse.vex.ui,org.eclipse.vex.core.tests",
- org.eclipse.vex.core.internal.core;x-friends:="org.eclipse.vex.ui,org.eclipse.vex.core.tests",
- org.eclipse.vex.core.internal.css;x-friends:="org.eclipse.vex.ui,org.eclipse.vex.core.tests",
- org.eclipse.vex.core.internal.dom;x-friends:="org.eclipse.vex.ui,org.eclipse.vex.core.tests",
- org.eclipse.vex.core.internal.io;x-friends:="org.eclipse.vex.core.tests,org.eclipse.vex.ui",
- org.eclipse.vex.core.internal.layout;x-friends:="org.eclipse.vex.ui,org.eclipse.vex.core.tests",
- org.eclipse.vex.core.internal.undo;x-friends:="org.eclipse.vex.core.tests,org.eclipse.vex.ui",
- org.eclipse.vex.core.internal.validator;x-friends:="org.eclipse.vex.ui,org.eclipse.vex.core.tests",
- org.eclipse.vex.core.internal.widget;x-friends:="org.eclipse.vex.ui,org.eclipse.vex.core.tests",
- org.eclipse.vex.core.internal.widget.swt;x-friends:="org.eclipse.vex.ui,org.eclipse.vex.core.tests",
+ org.eclipse.vex.core.internal;x-friends:="org.eclipse.vex.ui,org.eclipse.vex.core.tests,org.eclipse.vex.ui.tests",
+ org.eclipse.vex.core.internal.core;x-friends:="org.eclipse.vex.ui,org.eclipse.vex.core.tests,org.eclipse.vex.ui.tests",
+ org.eclipse.vex.core.internal.css;x-friends:="org.eclipse.vex.ui,org.eclipse.vex.core.tests,org.eclipse.vex.ui.tests",
+ org.eclipse.vex.core.internal.dom;x-friends:="org.eclipse.vex.ui,org.eclipse.vex.core.tests,org.eclipse.vex.ui.tests",
+ org.eclipse.vex.core.internal.io;x-friends:="org.eclipse.vex.core.tests,org.eclipse.vex.ui,org.eclipse.vex.ui.tests",
+ org.eclipse.vex.core.internal.layout;x-friends:="org.eclipse.vex.ui,org.eclipse.vex.core.tests,org.eclipse.vex.ui.tests",
+ org.eclipse.vex.core.internal.undo;x-friends:="org.eclipse.vex.core.tests,org.eclipse.vex.ui,org.eclipse.vex.ui.tests",
+ org.eclipse.vex.core.internal.validator;x-friends:="org.eclipse.vex.ui,org.eclipse.vex.core.tests,org.eclipse.vex.ui.tests",
+ org.eclipse.vex.core.internal.widget;x-friends:="org.eclipse.vex.ui,org.eclipse.vex.core.tests,org.eclipse.vex.ui.tests",
+ org.eclipse.vex.core.internal.widget.swt;x-friends:="org.eclipse.vex.ui,org.eclipse.vex.core.tests,org.eclipse.vex.ui.tests",
  org.eclipse.vex.core.provisional.dom;uses:="org.eclipse.vex.core.internal.dom"
 Bundle-Activator: org.eclipse.vex.core.internal.VEXCorePlugin
 Bundle-Localization: plugin
diff --git a/org.eclipse.vex.core/about.html b/org.eclipse.vex.core/about.html
new file mode 100644
index 0000000..c258ef5
--- /dev/null
+++ b/org.eclipse.vex.core/about.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+ 
+<p>June 5, 2006</p>	
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).  Unless otherwise 
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;).  A copy of the EPL is available 
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content.  Check the Redistributor's license that was 
+provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/org.eclipse.vex.core/build.properties b/org.eclipse.vex.core/build.properties
index c9b94a1..1532a5d 100644
--- a/org.eclipse.vex.core/build.properties
+++ b/org.eclipse.vex.core/build.properties
@@ -1,5 +1,8 @@
 source.. = src/
-output.. = bin/
+output.. = target/classes
 bin.includes = plugin.properties,\
                META-INF/,\
-               .
+               .,\
+               plugin.xml,\
+               about.html
+src.includes = about.html
diff --git a/org.eclipse.vex.core/plugin.xml b/org.eclipse.vex.core/plugin.xml
new file mode 100644
index 0000000..4611f5e
--- /dev/null
+++ b/org.eclipse.vex.core/plugin.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+   <extension
+         point="org.eclipse.wst.xml.core.catalogContributions">
+      <catalogContribution
+            id="XInclude">
+         <uri
+               name="http://www.w3.org/2001/XInclude"
+               uri="xsd/XInclude.xsd">
+         </uri>
+         <system
+               systemId="http://www.w3.org/2001/XInclude.xsd"
+               uri="xsd/XInclude.xsd">
+         </system>
+      </catalogContribution>
+   </extension>
+
+</plugin>
diff --git a/org.eclipse.vex.core/pom.xml b/org.eclipse.vex.core/pom.xml
index 95b671c..c0cde84 100644
--- a/org.eclipse.vex.core/pom.xml
+++ b/org.eclipse.vex.core/pom.xml
@@ -7,10 +7,10 @@
 	<name>Vex Core</name>
 
 	<parent>
-		<artifactId>org.eclipse.vex-releng</artifactId>
+		<artifactId>bundles</artifactId>
 		<groupId>org.eclipse.vex</groupId>
 		<version>1.1.0-SNAPSHOT</version>
-		<relativePath>../org.eclipse.vex.releng/pom.xml</relativePath>
+		<relativePath>../org.eclipse.vex.releng/bundles-pom.xml</relativePath>
 	</parent>
 
 </project>
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/IFilter.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/IFilter.java
index dc0f246..a3d13fd 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/IFilter.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/IFilter.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

@@ -12,7 +12,7 @@
 

 /**

  * A simple filtering facility.

- * 

+ *

  * @author Florian Thienel

  */

 public interface IFilter<T> {

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/IValidationResult.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/IValidationResult.java
index 9d604b5..1509e94 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/IValidationResult.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/IValidationResult.java
@@ -14,7 +14,7 @@
 
 /**
  * A VEX specific implementation of the IStatus interface.
- * 
+ *
  * @author chi
  */
 public interface IValidationResult extends IStatus {
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/ValidationResult.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/ValidationResult.java
index 9845bea..42c34e0 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/ValidationResult.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/ValidationResult.java
@@ -24,7 +24,7 @@
 
 	/**
 	 * Create a new error result.
-	 * 
+	 *
 	 * @param message
 	 *            The validation message.
 	 * @return A new ValidationResult with the given message and severity set to {@link IStatus#ERROR}.
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/XML.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/XML.java
index fa815dd..25967a9 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/XML.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/XML.java
@@ -17,7 +17,7 @@
 

 /**

  * Common processing methods according to http://www.w3.org/TR/REC-xml/

- * 

+ *

  * @see http://www.w3.org/TR/REC-xml/#sec-white-space

  * @see http://www.w3.org/TR/REC-xml/#sec-line-ends

  * @see http://www.w3.org/TR/REC-xml/#NT-S

@@ -30,7 +30,7 @@
 	/**

 	 * The xml:base attribute re-defines the base URI for a part of an XML document, according to the XML Base

 	 * Recommendation.

-	 * 

+	 *

 	 * @see http://www.w3.org/TR/xmlbase/

 	 */

 	public static final QualifiedName BASE_ATTRIBUTE = new QualifiedName(Namespace.XML_NAMESPACE_URI, "base");

@@ -49,7 +49,7 @@
 	/**

 	 * Replace runs of XML whitespace (see {@link #isWhitespace}) with a single space. Newlines in the input should be

 	 * normalized before calling this method.

-	 * 

+	 *

 	 * @param input

 	 *            String to compress.

 	 * @param trimLeading

@@ -68,7 +68,7 @@
 	/**

 	 * Replace runs of XML whitespace (see {@link #isWhitespace}) with a single space. Newlines in the input should be

 	 * normalized before calling this method.

-	 * 

+	 *

 	 * @param sb

 	 *            StringBuilder to compress.

 	 * @param trimLeading

@@ -118,7 +118,7 @@
 

 	/**

 	 * Convert lines that end in CR and CRLFs to plain newlines.

-	 * 

+	 *

 	 * @param input

 	 *            String to be normalized.

 	 */

@@ -130,7 +130,7 @@
 

 	/**

 	 * Convert lines that end in CR and CRLFs to plain newlines.

-	 * 

+	 *

 	 * @param sb

 	 *            StringBuilder to be normalized.

 	 */

@@ -183,7 +183,7 @@
 

 	/**

 	 * Validate the target of an processing instruction.

-	 * 

+	 *

 	 * @param target

 	 *            The target String to validate.

 	 * @return The IValidationResult. Use {@link IValidationResult#isOK()} to check if there is an error.

@@ -211,7 +211,7 @@
 

 	/**

 	 * Validate the data of an processing instruction.

-	 * 

+	 *

 	 * @param data

 	 *            The data String to validate.

 	 * @return The IValidationResult. Use {@link IValidationResult#isOK()} to check if there is an error.

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/VEXCorePlugin.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/VEXCorePlugin.java
index 59a036c..f7f197a 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/VEXCorePlugin.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/VEXCorePlugin.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *     David Carver (STAR) - initial renaming
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/AfterNIterator.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/AfterNIterator.java
index 82ae090..e80b385 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/AfterNIterator.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/AfterNIterator.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

@@ -14,7 +14,7 @@
 

 /**

  * This iterator provides a subsequence of a given source iterator which start at the nth element.

- * 

+ *

  * @author Florian Thienel

  */

 public class AfterNIterator<T> implements Iterator<T> {

@@ -39,14 +39,17 @@
 		}

 	}

 

+	@Override

 	public boolean hasNext() {

 		return source.hasNext();

 	}

 

+	@Override

 	public T next() {

 		return source.next();

 	}

 

+	@Override

 	public void remove() {

 		source.remove();

 	}

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/Caret.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/Caret.java
index 6855ee5..7c1961e 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/Caret.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/Caret.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -20,7 +20,7 @@
 
 	/**
 	 * Class constructor
-	 * 
+	 *
 	 * @param x
 	 *            x-coordinate of the top left corner of the caret
 	 * @param y
@@ -33,7 +33,7 @@
 
 	/**
 	 * Draws the caret in the given Graphics context.
-	 * 
+	 *
 	 * @param g
 	 *            Graphics within which the caret should be drawn.
 	 * @param color
@@ -62,7 +62,7 @@
 
 	/**
 	 * Moves the caret by the given x and y distance.
-	 * 
+	 *
 	 * @param x
 	 *            amount by which to move the caret to the right
 	 * @param y
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/Color.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/Color.java
index 33e10d5..6208b58 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/Color.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/Color.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -24,7 +24,7 @@
 
 	/**
 	 * Class constructor.
-	 * 
+	 *
 	 * @param red
 	 *            red value, 0..255
 	 * @param green
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/ColorResource.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/ColorResource.java
index eef4b68..e82b65c 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/ColorResource.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/ColorResource.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -16,9 +16,15 @@
  */
 public interface ColorResource {
 
-	public static final int SELECTION_BACKGROUND = 0;
-	public static final int SELECTION_FOREGROUND = 1;
+	ColorResource NULL = new ColorResource() {
+		@Override
+		public void dispose() {
+		}
+	};
 
-	public void dispose();
+	int SELECTION_BACKGROUND = 0;
+	int SELECTION_FOREGROUND = 1;
+
+	void dispose();
 
 }
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/DisplayDevice.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/DisplayDevice.java
index d82af09..4406f49 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/DisplayDevice.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/DisplayDevice.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -52,7 +52,7 @@
 
 	/**
 	 * Sets the current display device. This is typically called by the platform-specific widget;
-	 * 
+	 *
 	 * @param current
 	 *            The device to use as the current device.
 	 */
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/Drawable.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/Drawable.java
index af13444..f4fa898 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/Drawable.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/Drawable.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -17,7 +17,7 @@
 
 	/**
 	 * Draw the object.
-	 * 
+	 *
 	 * @param g
 	 *            Graphics into which to draw the object.
 	 * @param x
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/ElementName.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/ElementName.java
index e294aca..ee7a056 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/ElementName.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/ElementName.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/FilterIterator.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/FilterIterator.java
index 909a9a1..78b36b6 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/FilterIterator.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/FilterIterator.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

@@ -18,7 +18,7 @@
 /**

  * This iterator fiters the sequence of a given source iterator. It provides only the elements which match a given

  * filter.

- * 

+ *

  * @author Florian Thienel

  * @see IFilter

  */

@@ -52,10 +52,12 @@
 		current = null;

 	}

 

+	@Override

 	public boolean hasNext() {

 		return current != null;

 	}

 

+	@Override

 	public T next() {

 		if (!hasNext()) {

 			throw new NoSuchElementException();

@@ -66,6 +68,7 @@
 		return result;

 	}

 

+	@Override

 	public void remove() {

 		throw new UnsupportedOperationException();

 	}

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/FirstNIterator.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/FirstNIterator.java
index a8af25c..fbf54e7 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/FirstNIterator.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/FirstNIterator.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

@@ -15,7 +15,7 @@
 

 /**

  * This iterator provides the first n elements of the sequence of a given source iterator.

- * 

+ *

  * @author Florian Thienel

  */

 public class FirstNIterator<T> implements Iterator<T> {

@@ -36,10 +36,12 @@
 		cursor = 0;

 	}

 

+	@Override

 	public boolean hasNext() {

 		return cursor < n && source.hasNext();

 	}

 

+	@Override

 	public T next() {

 		if (!hasNext()) {

 			throw new NoSuchElementException();

@@ -48,6 +50,7 @@
 		return source.next();

 	}

 

+	@Override

 	public void remove() {

 		source.remove();

 	}

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/FontMetrics.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/FontMetrics.java
index 9d198d2..8ac74dd 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/FontMetrics.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/FontMetrics.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/FontResource.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/FontResource.java
index 328e409..c1ec168 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/FontResource.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/FontResource.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -16,5 +16,11 @@
  */
 public interface FontResource {
 
-	public void dispose();
+	FontResource NULL = new FontResource() {
+		@Override
+		public void dispose() {
+		}
+	};
+
+	void dispose();
 }
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/FontSpec.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/FontSpec.java
index 04bebd2..62badec 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/FontSpec.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/FontSpec.java
@@ -4,17 +4,19 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *     Dave Holroyd - Implement text decoration
  *******************************************************************************/
 package org.eclipse.vex.core.internal.core;
 
+import java.util.Arrays;
+
 /**
  * Toolkit-independent specifier of a font. This class does not encapsulate an actual font, but simply the information
  * needed for the toolkit to find an actual font.
- * 
+ *
  * <p>
  * An array of font family names may be specified. If more than one name is specified, the toolkit should select the
  * first name that matches an actual font on the platform.
@@ -35,7 +37,7 @@
 
 	/**
 	 * Class constructor.
-	 * 
+	 *
 	 * @param names
 	 *            Array of names of the font family.
 	 * @param style
@@ -65,7 +67,7 @@
 
 	/**
 	 * Returns a bitwise-OR of the style flags. The following sample checks if the font is bold.
-	 * 
+	 *
 	 * <pre>
 	 * if (font.getStyle | VexFont.BOLD) {
 	 * 	// do something bold...
@@ -76,4 +78,30 @@
 		return style;
 	}
 
+	@Override
+	public String toString() {
+		return "FontSpec [names=" + Arrays.toString(names) + ", size=" + size + ", style=" + styleToString(style) + "]";
+	}
+
+	public static String styleToString(final int style) {
+		if (style == PLAIN) {
+			return "PLAIN";
+		}
+		final StringBuilder builder = new StringBuilder();
+		appendIfIncluded(builder, style, BOLD, "BOLD");
+		appendIfIncluded(builder, style, ITALIC, "ITALIC");
+		appendIfIncluded(builder, style, UNDERLINE, "UNDERLINE");
+		appendIfIncluded(builder, style, OVERLINE, "OVERLINE");
+		appendIfIncluded(builder, style, LINE_THROUGH, "LINE_THROUGH");
+		return builder.toString();
+	}
+
+	private static void appendIfIncluded(final StringBuilder builder, final int mask, final int flag, final String representation) {
+		if ((mask & flag) == flag) {
+			if (builder.length() > 0) {
+				builder.append("|");
+			}
+			builder.append(representation);
+		}
+	}
 }
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/Graphics.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/Graphics.java
index 9a52a14..4b2f819 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/Graphics.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/Graphics.java
@@ -4,10 +4,10 @@
  * 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:
  *     John Krasnay - initial API and implementation
- *     Mohamadou Nassourou - Bug 298912 - rudimentary support for images 
+ *     Mohamadou Nassourou - Bug 298912 - rudimentary support for images
  *******************************************************************************/
 package org.eclipse.vex.core.internal.core;
 
@@ -37,7 +37,7 @@
 
 	/**
 	 * Draw the given string at the given point using the current font.
-	 * 
+	 *
 	 * @param s
 	 *            string to draw
 	 * @param x
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/Insets.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/Insets.java
index 7443900..7a755ba 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/Insets.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/Insets.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -25,7 +25,7 @@
 
 	/**
 	 * Class constructor.
-	 * 
+	 *
 	 * @param top
 	 *            Top inset.
 	 * @param left
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/ListenerList.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/ListenerList.java
index 637e560..898c131 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/ListenerList.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/ListenerList.java
@@ -23,7 +23,7 @@
 /**
  * A collection of listener objects. The main point of this class is the fireEvent method, which takes care of the
  * tedium of iterating over the collection and catching exceptions generated by listeners.
- * 
+ *
  * @param <L>
  *            the type of listeners maintained by this list
  * @param <E>
@@ -39,7 +39,7 @@
 
 	/**
 	 * Class constructor.
-	 * 
+	 *
 	 * @param listenerClass
 	 *            Class of the listener interface.
 	 */
@@ -50,7 +50,7 @@
 	/**
 	 * Adds a listener to the list. Rejects listeners that are not subclasses of the listener class passed to the
 	 * constructor.
-	 * 
+	 *
 	 * @param listener
 	 *            Listener to be added.
 	 */
@@ -60,7 +60,7 @@
 
 	/**
 	 * Removes a listener from the list.
-	 * 
+	 *
 	 * @param listener
 	 *            Listener to remove.
 	 */
@@ -72,7 +72,7 @@
 	 * Called from fireEvent whenever a called listener method throws an exception, or if there is a problem looking up
 	 * the listener method by reflection. By default, simply prints the stack trace to stdout. Clients may override this
 	 * method to provide a more suitable implementation.
-	 * 
+	 *
 	 * @param e
 	 *            Exception thrown by the listener method.
 	 */
@@ -83,7 +83,7 @@
 	/**
 	 * Calls the given method on each registered listener. Any exception thrown from one of the called methods is passed
 	 * to handleException, as is any introspection error, e.g. if the given method doesn't exist.
-	 * 
+	 *
 	 * @param methodName
 	 *            Listener method to call.
 	 * @param event
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/Point.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/Point.java
index 37387fd..20f906d 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/Point.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/Point.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -20,7 +20,7 @@
 
 	/**
 	 * Class constructor.
-	 * 
+	 *
 	 * @param x
 	 *            X-coordinate.
 	 * @param y
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/QualifiedNameComparator.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/QualifiedNameComparator.java
index b79c764..8970c17 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/QualifiedNameComparator.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/QualifiedNameComparator.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

@@ -19,6 +19,7 @@
  */

 public class QualifiedNameComparator implements Comparator<QualifiedName> {

 

+	@Override

 	public int compare(final QualifiedName name1, final QualifiedName name2) {

 		return name1.toString().compareTo(name2.toString());

 	}

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/Rectangle.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/Rectangle.java
index 5f6e0e6..9096e98 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/Rectangle.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/Rectangle.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -77,7 +77,7 @@
 
 	/**
 	 * Returns a Rectangle that is the union of this rectangle with another.
-	 * 
+	 *
 	 * @param rect
 	 *            Rectangle with which to union this one.
 	 */
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/AbstractProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/AbstractProperty.java
index 28e4d5d..9d56036 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/AbstractProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/AbstractProperty.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -20,7 +20,7 @@
 
 	/**
 	 * Class constructor.
-	 * 
+	 *
 	 * @param name
 	 *            Name of the property.
 	 */
@@ -35,6 +35,7 @@
 		return lu != null && lu.getLexicalUnitType() == LexicalUnit.SAC_INHERIT;
 	}
 
+	@Override
 	public String getName() {
 		return name;
 	}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BackgroundImageProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BackgroundImageProperty.java
index 2744f46..8a08540 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BackgroundImageProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BackgroundImageProperty.java
@@ -4,7 +4,7 @@
  * 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:

  * 		 Mohamadou Nassourou - initial API and implementation

  *******************************************************************************/

@@ -31,6 +31,7 @@
 		super(CSS.BACKGROUND_IMAGE);

 	}

 

+	@Override

 	public Object calculate(final LexicalUnit lexicalUnit, final Styles parentStyles, final Styles styles, final INode node) {

 		if (lexicalUnit == null) {

 			return DEFAULT;

@@ -51,10 +52,10 @@
 			});

 		default:

 			VEXCorePlugin

-					.getInstance()

-					.getLog()

-					.log(new Status(IStatus.WARNING, VEXCorePlugin.ID, MessageFormat.format("Unsupported lexical unit type in ''background-image: {0}'' (type: {1})", lexicalUnit.toString(),

-							lexicalUnit.getLexicalUnitType())));

+			.getInstance()

+			.getLog()

+			.log(new Status(IStatus.WARNING, VEXCorePlugin.ID, MessageFormat.format("Unsupported lexical unit type in ''background-image: {0}'' (type: {1})", lexicalUnit.toString(),

+					lexicalUnit.getLexicalUnitType())));

 			return DEFAULT;

 		}

 	}

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BorderSpacingProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BorderSpacingProperty.java
index 2ef206c..de7f058 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BorderSpacingProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BorderSpacingProperty.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -57,6 +57,7 @@
 		super(CSS.BORDER_SPACING);
 	}
 
+	@Override
 	public Object calculate(LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 
 		int horizontal = 0;
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BorderStyleProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BorderStyleProperty.java
index 8a28a88..460d924 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BorderStyleProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BorderStyleProperty.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -20,7 +20,7 @@
 
 	/**
 	 * Class constructor.
-	 * 
+	 *
 	 * @param name
 	 *            Name of the property.
 	 */
@@ -30,7 +30,7 @@
 
 	/**
 	 * Returns true if the given lexical unit represents a border style.
-	 * 
+	 *
 	 * @param lu
 	 *            LexicalUnit to check.
 	 */
@@ -46,6 +46,7 @@
 		return false;
 	}
 
+	@Override
 	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 		if (isBorderStyle(lu)) {
 			return lu.getStringValue();
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BorderWidthProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BorderWidthProperty.java
index 0266d69..33db581 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BorderWidthProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BorderWidthProperty.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -53,7 +53,7 @@
 
 	/**
 	 * Class constructor.
-	 * 
+	 *
 	 * @param name
 	 *            Name of the property.
 	 * @param borderStyleName
@@ -70,7 +70,7 @@
 
 	/**
 	 * Returns true if the given lexical unit represents a border width.
-	 * 
+	 *
 	 * @param lu
 	 *            LexicalUnit to check.
 	 */
@@ -87,6 +87,7 @@
 		}
 	}
 
+	@Override
 	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 		return Integer.valueOf(calculateInternal(lu, parentStyles, styles));
 	}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/CSS.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/CSS.java
index 83f064c..a146a86 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/CSS.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/CSS.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *     Dave Holroyd - Implement text decoration
@@ -191,6 +191,7 @@
 	public static final String DOTTED = "dotted";
 	public static final String DOUBLE = "double";
 	public static final String GROOVE = "groove";
+	public static final String INCLUDE = "include";
 	public static final String INLINE = "inline";
 	public static final String INLINE_BLOCK = "inline-block";
 	public static final String INLINE_TABLE = "inline-table";
@@ -238,6 +239,7 @@
 	// Common element names
 	public static final String XML_PROCESSING_INSTRUCTION = "processing-instruction";
 	public static final String XML_COMMENT = "comment";
+	public static final String XINCLUDE_NAMESPACE_PREFIX = "xi";
 	public static final String VEX_NAMESPACE_PREFIX = "vex";
 
 	// Pseudo elements
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/ColorProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/ColorProperty.java
index edf0257..952890f 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/ColorProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/ColorProperty.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -46,17 +46,17 @@
 
 	/**
 	 * Class constructor. The names CSS.COLOR and CSS.BACKGROUND_COLOR are treated specially, as follows.
-	 * 
+	 *
 	 * <ul>
 	 * <li>If name is CSS.COLOR, it is inherited and defaults to black.</li>
 	 * <li>If name is CSS.BACKGROUND_COLOR, it is not inherited and defaults to transparent (null).</li>
 	 * <li>Otherwise, it is not inherited and defaults to the current color.</li>
 	 * </ul>
-	 * 
+	 *
 	 * <p>
 	 * Because of the default in the third case, the ColorProperty for CSS.COLOR must be processed before any others.
 	 * </p>
-	 * 
+	 *
 	 * @param name
 	 *            Name of the element.
 	 */
@@ -64,6 +64,7 @@
 		super(name);
 	}
 
+	@Override
 	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 
 		final boolean inherit = isInherit(lu) || getName().equals(CSS.COLOR);
@@ -85,7 +86,7 @@
 
 	/**
 	 * Returns true if the given lexical unit represents a color.
-	 * 
+	 *
 	 * @param lu
 	 *            LexicalUnit to check.
 	 */
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/CssScanner.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/CssScanner.java
index b1d412c..dc441c4 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/CssScanner.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/CssScanner.java
@@ -26,7 +26,7 @@
 
 	/**
 	 * Creates a new Scanner object.
-	 * 
+	 *
 	 * @param r
 	 *            The reader to scan.
 	 */
@@ -36,7 +36,7 @@
 
 	/**
 	 * Creates a new Scanner object.
-	 * 
+	 *
 	 * @param is
 	 *            The input stream to scan.
 	 * @param enc
@@ -48,7 +48,7 @@
 
 	/**
 	 * Creates a new Scanner object.
-	 * 
+	 *
 	 * @param s
 	 *            The string to scan.
 	 */
@@ -58,7 +58,7 @@
 
 	/**
 	 * Returns the last scanned character.
-	 * 
+	 *
 	 * @return
 	 */
 	public int getCurrent() {
@@ -67,7 +67,7 @@
 
 	/**
 	 * Joins two subsequent identifiers which are seperated by single char.
-	 * 
+	 *
 	 * @throws ParseException
 	 */
 	public void joinIdentifier() throws ParseException {
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/CssWhitespacePolicy.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/CssWhitespacePolicy.java
index 8ae7730..c92d260 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/CssWhitespacePolicy.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/CssWhitespacePolicy.java
@@ -14,6 +14,7 @@
 import org.eclipse.vex.core.provisional.dom.DocumentContentModel;
 import org.eclipse.vex.core.provisional.dom.IComment;
 import org.eclipse.vex.core.provisional.dom.IElement;
+import org.eclipse.vex.core.provisional.dom.IIncludeNode;
 import org.eclipse.vex.core.provisional.dom.INode;
 import org.eclipse.vex.core.provisional.dom.IProcessingInstruction;
 import org.eclipse.vex.core.provisional.dom.IText;
@@ -21,12 +22,13 @@
 
 /**
  * Implementation of IWhitespacePolicy using a CSS stylesheet.
- * 
+ *
  * @see IWhitespacePolicy
  */
 public class CssWhitespacePolicy implements IWhitespacePolicy {
 
 	public static final IWhitespacePolicyFactory FACTORY = new IWhitespacePolicyFactory() {
+		@Override
 		public IWhitespacePolicy createPolicy(final IValidator validator, final DocumentContentModel documentContentModel, final StyleSheet styleSheet) {
 			return new CssWhitespacePolicy(styleSheet);
 		}
@@ -36,7 +38,7 @@
 
 	/**
 	 * Create a whitespace policy based on the given stylesheet.
-	 * 
+	 *
 	 * @param styleSheet
 	 *            the stylesheet used for the policy
 	 */
@@ -44,51 +46,65 @@
 		this.styleSheet = styleSheet;
 	}
 
+	@Override
 	public boolean isBlock(final INode node) {
 		return node.accept(new BaseNodeVisitorWithResult<Boolean>(true) {
 			@Override
 			public Boolean visit(final IElement element) {
-				if (isDisplay(node, CSS.BLOCK)) {
+				if (isDisplay(element, CSS.BLOCK)) {
 					return true;
 				}
 
-				if (isDisplay(node, CSS.LIST_ITEM)) {
+				if (isDisplay(element, CSS.LIST_ITEM)) {
 					return true;
 				}
 
-				if (isDisplay(node, CSS.TABLE)) {
+				if (isDisplay(element, CSS.INCLUDE)) {
+					// When this method is called by the DocumentBuilder, the note is not yet associated
+					if (!element.isAssociated() || element.getDocument() == null) {
+						return false;
+					}
+
+					if (element.getDocument().canInsertText(element.getStartOffset())) {
+						return false;
+					}
+
+					return isBlock(element.getParent());
+				}
+
+				if (isDisplay(element, CSS.TABLE)) {
 					return true;
 				}
 
-				if (isDisplay(node, CSS.TABLE_CAPTION, CSS.TABLE)) {
+				if (isDisplay(element, CSS.TABLE_CAPTION, CSS.TABLE)) {
 					return true;
 				}
 
-				if (isDisplay(node, CSS.TABLE_CELL, CSS.TABLE_ROW)) {
+				if (isDisplay(element, CSS.TABLE_CELL, CSS.TABLE_ROW)) {
 					return true;
 				}
 
-				if (isDisplay(node, CSS.TABLE_COLUMN, CSS.TABLE_COLUMN_GROUP)) {
+				if (isDisplay(element, CSS.TABLE_COLUMN, CSS.TABLE_COLUMN_GROUP)) {
 					return true;
 				}
 
-				if (isDisplay(node, CSS.TABLE_COLUMN_GROUP, CSS.TABLE)) {
+				if (isDisplay(element, CSS.TABLE_COLUMN_GROUP, CSS.TABLE)) {
 					return true;
 				}
 
-				if (isDisplay(node, CSS.TABLE_FOOTER_GROUP, CSS.TABLE, CSS.TABLE_ROW_GROUP)) {
+				if (isDisplay(element, CSS.TABLE_FOOTER_GROUP, CSS.TABLE, CSS.TABLE_ROW_GROUP)) {
 					return true;
 				}
 
-				if (isDisplay(node, CSS.TABLE_HEADER_GROUP, CSS.TABLE, CSS.TABLE_ROW_GROUP)) {
+				if (isDisplay(element, CSS.TABLE_HEADER_GROUP, CSS.TABLE, CSS.TABLE_ROW_GROUP)) {
 					return true;
 				}
 
-				if (isDisplay(node, CSS.TABLE_ROW_GROUP, CSS.TABLE, CSS.TABLE_ROW_GROUP)) {
+				if (isDisplay(element, CSS.TABLE_ROW_GROUP, CSS.TABLE, CSS.TABLE_ROW_GROUP)) {
 					return true;
 				}
 
-				if (isDisplay(node, CSS.TABLE_ROW, CSS.TABLE, CSS.TABLE_ROW_GROUP, CSS.TABLE_HEADER_GROUP, CSS.TABLE_FOOTER_GROUP)) {
+				if (isDisplay(element, CSS.TABLE_ROW, CSS.TABLE, CSS.TABLE_ROW_GROUP, CSS.TABLE_HEADER_GROUP, CSS.TABLE_FOOTER_GROUP)) {
 					return true;
 				}
 
@@ -110,6 +126,12 @@
 			}
 
 			@Override
+			public Boolean visit(final IIncludeNode include) {
+				// TODO Evaluate the included content instead of the element
+				return visit(include.getReference());
+			}
+
+			@Override
 			public Boolean visit(final IText text) {
 				return false;
 			}
@@ -149,6 +171,7 @@
 		return styles.getDisplay();
 	}
 
+	@Override
 	public boolean isPre(final INode node) {
 		return CSS.PRE.equals(styleSheet.getStyles(node).getWhiteSpace());
 	}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/DisplayProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/DisplayProperty.java
index 1cacb75..a5eb10a 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/DisplayProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/DisplayProperty.java
@@ -25,6 +25,7 @@
 		super(CSS.DISPLAY);
 	}
 
+	@Override
 	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 
 		if (isDisplay(lu)) {
@@ -41,7 +42,7 @@
 
 	/**
 	 * Returns true if the value of the given LexicalUnit represents a valid value for this property.
-	 * 
+	 *
 	 * @param lu
 	 *            LexicalUnit to inspect.
 	 */
@@ -52,7 +53,7 @@
 			final String s = lu.getStringValue();
 			return s.equals(CSS.BLOCK) || s.equals(CSS.INLINE) || s.equals(CSS.INLINE_BLOCK) || s.equals(CSS.INLINE_TABLE) || s.equals(CSS.LIST_ITEM) || s.equals(CSS.RUN_IN) || s.equals(CSS.TABLE)
 					|| s.equals(CSS.TABLE_CAPTION) || s.equals(CSS.TABLE_CELL) || s.equals(CSS.TABLE_COLUMN) || s.equals(CSS.TABLE_COLUMN_GROUP) || s.equals(CSS.TABLE_FOOTER_GROUP)
-					|| s.equals(CSS.TABLE_HEADER_GROUP) || s.equals(CSS.TABLE_ROW) || s.equals(CSS.TABLE_ROW_GROUP);
+					|| s.equals(CSS.TABLE_HEADER_GROUP) || s.equals(CSS.TABLE_ROW) || s.equals(CSS.TABLE_ROW_GROUP) || s.equals(CSS.INCLUDE);
 		} else {
 			return false;
 		}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontFamilyProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontFamilyProperty.java
index 2f08875..d9beb25 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontFamilyProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontFamilyProperty.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *     Florian Thienel - bug 304413 - fix immutable array issue.
@@ -30,6 +30,7 @@
 		super(CSS.FONT_FAMILY);
 	}
 
+	@Override
 	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 		if (isFontFamily(lu)) {
 			return getFontFamilies(lu);
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontSizeProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontSizeProperty.java
index 5139667..f4d5b86 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontSizeProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontSizeProperty.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -27,13 +27,14 @@
 		super(CSS.FONT_SIZE);
 	}
 
+	@Override
 	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 		return new Float(calculateInternal(lu, parentStyles, styles));
 	}
 
 	/**
 	 * Returns true if the given lexical unit represents a font size.
-	 * 
+	 *
 	 * @param lu
 	 *            LexicalUnit to check.
 	 */
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontStyleProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontStyleProperty.java
index ef8a4ea..19e53c3 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontStyleProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontStyleProperty.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -25,6 +25,7 @@
 		super(CSS.FONT_STYLE);
 	}
 
+	@Override
 	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 		if (isFontStyle(lu)) {
 			return lu.getStringValue();
@@ -41,7 +42,7 @@
 
 	/**
 	 * Returns true if the given lexical unit represents a font style.
-	 * 
+	 *
 	 * @param lu
 	 *            LexicalUnit to check.
 	 */
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontVariantProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontVariantProperty.java
index be5b5af..878feb7 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontVariantProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontVariantProperty.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -25,6 +25,7 @@
 		super(CSS.FONT_VARIANT);
 	}
 
+	@Override
 	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 		if (isFontVariant(lu)) {
 			return lu.getStringValue();
@@ -41,7 +42,7 @@
 
 	/**
 	 * Returns true if the given lexical unit represents a font variant.
-	 * 
+	 *
 	 * @param lu
 	 *            LexicalUnit to check.
 	 */
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontWeightProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontWeightProperty.java
index 7a0e0dd..5fd04ad 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontWeightProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontWeightProperty.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -28,6 +28,7 @@
 		super(CSS.FONT_WEIGHT);
 	}
 
+	@Override
 	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 		return Integer.valueOf(calculateInternal(lu, parentStyles, styles));
 	}
@@ -48,7 +49,7 @@
 
 	/**
 	 * Returns true if the given lexical unit represents a font weight.
-	 * 
+	 *
 	 * @param lu
 	 *            LexicalUnit to check.
 	 */
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/IProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/IProperty.java
index 0879e7d..a893e68 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/IProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/IProperty.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -29,7 +29,7 @@
 
 	/**
 	 * Calculates the value of a property given a LexicalUnit.
-	 * 
+	 *
 	 * @param lu
 	 *            LexicalUnit to interpret.
 	 * @param parentStyles
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/IStyleSheetProvider.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/IStyleSheetProvider.java
index af76327..7c33713 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/IStyleSheetProvider.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/IStyleSheetProvider.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

@@ -18,6 +18,7 @@
 public interface IStyleSheetProvider {

 

 	static final IStyleSheetProvider NULL = new IStyleSheetProvider() {

+		@Override

 		public StyleSheet getStyleSheet(final DocumentContentModel documentContentModel) {

 			return StyleSheet.NULL;

 		}

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/IWhitespacePolicy.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/IWhitespacePolicy.java
index b6c63d7..dd4a16c 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/IWhitespacePolicy.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/IWhitespacePolicy.java
@@ -23,10 +23,12 @@
 	 * A NULL object of this type. No blocks and no pre elements.
 	 */
 	IWhitespacePolicy NULL = new IWhitespacePolicy() {
+		@Override
 		public boolean isBlock(final INode node) {
 			return false;
 		}
 
+		@Override
 		public boolean isPre(final INode node) {
 			return false;
 		}
@@ -36,10 +38,12 @@
 	 * This policy preserves whitespace but knows no blocks.
 	 */
 	IWhitespacePolicy PRESERVE_WHITESPACE = new IWhitespacePolicy() {
+		@Override
 		public boolean isBlock(final INode node) {
 			return false;
 		}
 
+		@Override
 		public boolean isPre(final INode node) {
 			return true;
 		}
@@ -49,10 +53,12 @@
 	 * This policy treats every node as a block.
 	 */
 	IWhitespacePolicy ALL_BLOCKS = new IWhitespacePolicy() {
+		@Override
 		public boolean isBlock(final INode node) {
 			return true;
 		}
 
+		@Override
 		public boolean isPre(final INode node) {
 			return false;
 		}
@@ -60,7 +66,7 @@
 
 	/**
 	 * Returns true if the given element is normally block-formatted.
-	 * 
+	 *
 	 * @param element
 	 *            Element to test.
 	 */
@@ -68,7 +74,7 @@
 
 	/**
 	 * Returns true if the given element is pre-formatted, that is, all of its contained whitespace should be preserved.
-	 * 
+	 *
 	 * @param element
 	 *            Element to test.
 	 */
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/IWhitespacePolicyFactory.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/IWhitespacePolicyFactory.java
index b359080..60c51e2 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/IWhitespacePolicyFactory.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/IWhitespacePolicyFactory.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *     Florian Thienel - a NULL object
@@ -24,6 +24,7 @@
 	 * A factory that always returns the NULL whitespace policy.
 	 */
 	IWhitespacePolicyFactory NULL = new IWhitespacePolicyFactory() {
+		@Override
 		public IWhitespacePolicy createPolicy(final IValidator validator, final DocumentContentModel documentContentModel, final StyleSheet style) {
 			return IWhitespacePolicy.NULL;
 		}
@@ -31,7 +32,7 @@
 
 	/**
 	 * Return a WhitespacePolicy for documents with the given public ID.
-	 * 
+	 *
 	 * @param publicId
 	 *            Public ID of the document type associated with the document.
 	 */
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/InlineMarkerProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/InlineMarkerProperty.java
index 29275e7..3cbb679 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/InlineMarkerProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/InlineMarkerProperty.java
@@ -4,7 +4,7 @@
  * 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:
  *     Carsten Hiesserich - initial API and implementation
  *******************************************************************************/
@@ -27,6 +27,7 @@
 		super(CSS.INLINE_MARKER);
 	}
 
+	@Override
 	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 		if (isInlineMarker(lu)) {
 			return lu.getStringValue();
@@ -37,7 +38,7 @@
 
 	/**
 	 * Returns true if the given lexical unit represents a valid _vex-inline-marker.
-	 * 
+	 *
 	 * @param lu
 	 *            LexicalUnit to check.
 	 */
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/LengthProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/LengthProperty.java
index 6cef7a8..52f6874 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/LengthProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/LengthProperty.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -37,6 +37,7 @@
 		this.axis = axis;
 	}
 
+	@Override
 	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 		final int ppi = getPpi();
 		if (isAttr(lu)) {
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/LineHeightProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/LineHeightProperty.java
index 0e20549..7041482 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/LineHeightProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/LineHeightProperty.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -32,6 +32,7 @@
 	 * Calculates the value of the property given a LexicalUnit. Returns a RelativeLength that is relative to the
 	 * current font size.
 	 */
+	@Override
 	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 
 		final int ppi = DisplayDevice.getCurrent().getVerticalPPI();
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/ListStyleTypeProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/ListStyleTypeProperty.java
index 1072c68..3ff6c9b 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/ListStyleTypeProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/ListStyleTypeProperty.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -22,6 +22,7 @@
 		super(CSS.LIST_STYLE_TYPE);
 	}
 
+	@Override
 	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 		if (isListStyleType(lu)) {
 			return lu.getStringValue();
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/OutlineContentProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/OutlineContentProperty.java
index 00fe86e..31604b6 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/OutlineContentProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/OutlineContentProperty.java
@@ -4,7 +4,7 @@
  * 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:
  *     Carsten Hiesserich - initial API and implementation
  *******************************************************************************/
@@ -27,13 +27,13 @@
  * of the element's text content.<br />
  * <br />
  * Example:
- * 
+ *
  * <pre>
  * chapter {
  *   -vex-outline-content: titleabbrev, title;
  * }
  * </pre>
- * 
+ *
  */
 public class OutlineContentProperty extends AbstractProperty {
 
@@ -49,6 +49,7 @@
 	 * display as content for the given node. We don't return the actual text here, because then we had to recalculate
 	 * the styles every time the text changes.
 	 */
+	@Override
 	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 
 		if (node == null || !node.isAssociated()) {
@@ -87,9 +88,9 @@
 				// Return element text content as default
 				return element;
 			}
-			
+
 			@Override
-			public Object visit(IProcessingInstruction pi) {
+			public Object visit(final IProcessingInstruction pi) {
 				return pi;
 			}
 		});
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/PropertyDecl.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/PropertyDecl.java
index d1374b5..fe78f80 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/PropertyDecl.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/PropertyDecl.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *     Florian Thienel - bug 306639 - remove serializability from StyleSheet
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/PseudoElement.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/PseudoElement.java
index fc5cea3..ecc69b4 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/PseudoElement.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/PseudoElement.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2013 Carsten Hiesserich and others.
+ * Copyright (c) 2013, 2014 Carsten Hiesserich 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
@@ -17,8 +17,9 @@
 
 /**
  * The PseudoElement is used to pass CSS pseudo elements to layout functions.<br />
- * To get an instance of this class use {@link StyleSheet#getPseudoElement(INode, String, boolean)}.
- * 
+ * To get an instance of this class use {@link StyleSheet#getPseudoElementBefore(INode)} or
+ * {@link StyleSheet#getPseudoElementAfter(INode)}.
+ *
  * @author Carsten Hiesserich
  */
 public class PseudoElement extends Element {
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/RelativeLength.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/RelativeLength.java
index 93b14a9..64d16ca 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/RelativeLength.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/RelativeLength.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -23,7 +23,7 @@
 
 	/**
 	 * Create a relative length representing an absolute value.
-	 * 
+	 *
 	 * @return the new RelativeLength value.
 	 */
 	public static RelativeLength createAbsolute(final int value) {
@@ -36,7 +36,7 @@
 
 	/**
 	 * Create a relative length representing a relative value.
-	 * 
+	 *
 	 * @return the new RelativeLength value.
 	 */
 	public static RelativeLength createRelative(final float percentage) {
@@ -47,7 +47,7 @@
 	 * Return the value of the length given a reference value. If this object represents an absolute value, that value
 	 * is simply returned. Otherwise, returns the given reference length multiplied by the given percentage and rounded
 	 * to the nearest integer.
-	 * 
+	 *
 	 * @param referenceLength
 	 *            reference length by which percentage lengths will by multiplied.
 	 * @return the actual value
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/Rule.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/Rule.java
index fdaaa9a..8f4a7f8 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/Rule.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/Rule.java
@@ -42,7 +42,7 @@
  * Represents a pairing of a selector with a list of styles. This does not exactly correspond to a rule in a style
  * sheet; there is only one selector associated with an instance of this class, whereas multiple selectors may be
  * associated with a style sheet rule.
- * 
+ *
  * Note: <code>Rule</code> implements the <code>Comparable</code> interface in order to be sorted by "specificity" as
  * defined by the CSS spec. However, this ordering is <em>not</em> consistent with <code>equals</code> (rules with the
  * same specificity may not be equal). Therefore, <code>Rule</code> objects should not be used with sorted collections
@@ -57,7 +57,7 @@
 
 	/**
 	 * Class constructor.
-	 * 
+	 *
 	 * @param selector
 	 *            Selector for the rule.
 	 */
@@ -67,7 +67,7 @@
 
 	/**
 	 * Adds a property declaration to the rule.
-	 * 
+	 *
 	 * @param decl
 	 *            new property declaration to add
 	 */
@@ -100,7 +100,7 @@
 
 	/**
 	 * Returns true if the given element matches this rule's selector.
-	 * 
+	 *
 	 * @param node
 	 *            Node to check.
 	 */
@@ -186,7 +186,7 @@
 			return false; // not yet supported
 
 		case Selector.SAC_COMMENT_NODE_SELECTOR:
-			return false; // not yet supported 
+			return false; // not yet supported
 
 		case Selector.SAC_PSEUDO_ELEMENT_SELECTOR:
 			// Always return true here. The Selector is evaluated with SAC_CHILD_SELECTOR.
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/StyleSheet.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/StyleSheet.java
index 9aa8714..9c823c5 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/StyleSheet.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/StyleSheet.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *     Dave Holroyd - Implement font-weight:bolder
@@ -13,7 +13,7 @@
  *     Travis Haagen - bug 260806 - enhanced support for 'content' CSS property
  *     Florian Thienel - bug 306639 - remove serializability from StyleSheet
  *                       and dependend classes
- *     Mohamadou Nassourou - Bug 298912 - rudimentary support for images 
+ *     Mohamadou Nassourou - Bug 298912 - rudimentary support for images
  *     Carsten Hiesserich - Styles cache now uses hard references instead of
  *                          WeekReference. PseudoElements are cached.
  *     Carsten Hiesserich - Added OutlineContent property
@@ -34,6 +34,7 @@
 import java.util.Map.Entry;
 import java.util.WeakHashMap;
 
+import org.eclipse.core.runtime.Assert;
 import org.eclipse.vex.core.internal.core.FontSpec;
 import org.eclipse.vex.core.provisional.dom.IDocument;
 import org.eclipse.vex.core.provisional.dom.IElement;
@@ -51,6 +52,7 @@
 	public static final StyleSheet NULL = new StyleSheet(Collections.<Rule> emptyList());
 
 	private static final Comparator<PropertyDecl> PROPERTY_CASCADE_ORDERING = new Comparator<PropertyDecl>() {
+		@Override
 		public int compare(final PropertyDecl propertyDecl1, final PropertyDecl propertyDecl2) {
 			if (propertyDecl1.isImportant() != propertyDecl2.isImportant()) {
 				return (propertyDecl1.isImportant() ? 1 : 0) - (propertyDecl2.isImportant() ? 1 : 0);
@@ -64,25 +66,25 @@
 	 * Standard CSS properties.
 	 */
 	private static final IProperty[] CSS_PROPERTIES = new IProperty[] { new DisplayProperty(), new LineHeightProperty(), new ListStyleTypeProperty(), new TextAlignProperty(),
-			new WhiteSpaceProperty(),
+		new WhiteSpaceProperty(),
 
-			new FontFamilyProperty(), new FontSizeProperty(), new FontStyleProperty(), new FontWeightProperty(), new TextDecorationProperty(),
+		new FontFamilyProperty(), new FontSizeProperty(), new FontStyleProperty(), new FontWeightProperty(), new TextDecorationProperty(),
 
-			new ColorProperty(CSS.COLOR), new ColorProperty(CSS.BACKGROUND_COLOR),
+		new ColorProperty(CSS.COLOR), new ColorProperty(CSS.BACKGROUND_COLOR),
 
-			new LengthProperty(CSS.MARGIN_BOTTOM, IProperty.Axis.VERTICAL), new LengthProperty(CSS.MARGIN_LEFT, IProperty.Axis.HORIZONTAL),
-			new LengthProperty(CSS.MARGIN_RIGHT, IProperty.Axis.HORIZONTAL), new LengthProperty(CSS.MARGIN_TOP, IProperty.Axis.VERTICAL),
+		new LengthProperty(CSS.MARGIN_BOTTOM, IProperty.Axis.VERTICAL), new LengthProperty(CSS.MARGIN_LEFT, IProperty.Axis.HORIZONTAL),
+		new LengthProperty(CSS.MARGIN_RIGHT, IProperty.Axis.HORIZONTAL), new LengthProperty(CSS.MARGIN_TOP, IProperty.Axis.VERTICAL),
 
-			new LengthProperty(CSS.PADDING_BOTTOM, IProperty.Axis.VERTICAL), new LengthProperty(CSS.PADDING_LEFT, IProperty.Axis.HORIZONTAL),
-			new LengthProperty(CSS.PADDING_RIGHT, IProperty.Axis.HORIZONTAL), new LengthProperty(CSS.PADDING_TOP, IProperty.Axis.VERTICAL),
+		new LengthProperty(CSS.PADDING_BOTTOM, IProperty.Axis.VERTICAL), new LengthProperty(CSS.PADDING_LEFT, IProperty.Axis.HORIZONTAL),
+		new LengthProperty(CSS.PADDING_RIGHT, IProperty.Axis.HORIZONTAL), new LengthProperty(CSS.PADDING_TOP, IProperty.Axis.VERTICAL),
 
-			new ColorProperty(CSS.BORDER_BOTTOM_COLOR), new ColorProperty(CSS.BORDER_LEFT_COLOR), new ColorProperty(CSS.BORDER_RIGHT_COLOR), new ColorProperty(CSS.BORDER_TOP_COLOR),
-			new BorderStyleProperty(CSS.BORDER_BOTTOM_STYLE), new BorderStyleProperty(CSS.BORDER_LEFT_STYLE), new BorderStyleProperty(CSS.BORDER_RIGHT_STYLE),
-			new BorderStyleProperty(CSS.BORDER_TOP_STYLE), new BorderWidthProperty(CSS.BORDER_BOTTOM_WIDTH, CSS.BORDER_BOTTOM_STYLE, IProperty.Axis.VERTICAL),
-			new BorderWidthProperty(CSS.BORDER_LEFT_WIDTH, CSS.BORDER_LEFT_STYLE, IProperty.Axis.HORIZONTAL),
-			new BorderWidthProperty(CSS.BORDER_RIGHT_WIDTH, CSS.BORDER_RIGHT_STYLE, IProperty.Axis.HORIZONTAL),
-			new BorderWidthProperty(CSS.BORDER_TOP_WIDTH, CSS.BORDER_TOP_STYLE, IProperty.Axis.VERTICAL), new BorderSpacingProperty(), new LengthProperty(CSS.HEIGHT, IProperty.Axis.VERTICAL),
-			new LengthProperty(CSS.WIDTH, IProperty.Axis.HORIZONTAL), new BackgroundImageProperty(), new OutlineContentProperty(), new InlineMarkerProperty() };
+		new ColorProperty(CSS.BORDER_BOTTOM_COLOR), new ColorProperty(CSS.BORDER_LEFT_COLOR), new ColorProperty(CSS.BORDER_RIGHT_COLOR), new ColorProperty(CSS.BORDER_TOP_COLOR),
+		new BorderStyleProperty(CSS.BORDER_BOTTOM_STYLE), new BorderStyleProperty(CSS.BORDER_LEFT_STYLE), new BorderStyleProperty(CSS.BORDER_RIGHT_STYLE),
+		new BorderStyleProperty(CSS.BORDER_TOP_STYLE), new BorderWidthProperty(CSS.BORDER_BOTTOM_WIDTH, CSS.BORDER_BOTTOM_STYLE, IProperty.Axis.VERTICAL),
+		new BorderWidthProperty(CSS.BORDER_LEFT_WIDTH, CSS.BORDER_LEFT_STYLE, IProperty.Axis.HORIZONTAL),
+		new BorderWidthProperty(CSS.BORDER_RIGHT_WIDTH, CSS.BORDER_RIGHT_STYLE, IProperty.Axis.HORIZONTAL),
+		new BorderWidthProperty(CSS.BORDER_TOP_WIDTH, CSS.BORDER_TOP_STYLE, IProperty.Axis.VERTICAL), new BorderSpacingProperty(), new LengthProperty(CSS.HEIGHT, IProperty.Axis.VERTICAL),
+		new LengthProperty(CSS.WIDTH, IProperty.Axis.HORIZONTAL), new BackgroundImageProperty(), new OutlineContentProperty(), new InlineMarkerProperty() };
 
 	/**
 	 * The rules that comprise the stylesheet.
@@ -115,7 +117,7 @@
 
 	/**
 	 * Class constructor.
-	 * 
+	 *
 	 * @param rules
 	 *            Rules that constitute the style sheet.
 	 */
@@ -125,7 +127,7 @@
 
 	/**
 	 * Flush any cached styles for the given element.
-	 * 
+	 *
 	 * @param element
 	 *            INode for which styles are to be flushed.
 	 */
@@ -136,7 +138,7 @@
 	/**
 	 * Flush all styles used by the given document. A StyleSheet may be shared by multiple documents, so we only remove
 	 * elements for the specific document.
-	 * 
+	 *
 	 * @param document
 	 *            The document for which to flush cached styles.
 	 */
@@ -155,39 +157,45 @@
 	}
 
 	/**
-	 * Returns a pseudo-element for the given parent element, or null if there is no such element defined in the
-	 * stylesheet.
-	 * 
 	 * @param parent
-	 *            Parent element of the pseudo-element.
-	 * @param pseudoElementName
-	 *            The name of the PseudoElement to return (case insensitive).
-	 * @param hasContent
-	 *            <code>true</code> will only return a PseudoElement with defined content.
-	 * @return
+	 *            parent element of the pseudo-element
+	 * @return the 'before' pseudo-element for the given parent element, or null if there is no such element defined in
+	 *         the stylesheet
 	 */
-	public IElement getPseudoElement(final INode parent, final String pseudoElementName, final boolean hasContent) {
-		if (parent == null) {
-			System.out.println("Warning! StyleSheet#getPseudoElement Parent is null");
-			return null;
-		}
+	public IElement getPseudoElementBefore(final INode parent) {
+		return getPseudoElement(parent, CSS.PSEUDO_BEFORE);
+	}
+
+	/**
+	 * @param parent
+	 *            parent element of the pseudo-element
+	 * @return the 'after' pseudo-element for the given parent element, or null if there is no such element defined in
+	 *         the stylesheet
+	 */
+	public IElement getPseudoElementAfter(final INode parent) {
+		return getPseudoElement(parent, CSS.PSEUDO_AFTER);
+	}
+
+	private IElement getPseudoElement(final INode parent, final String pseudoElementName) {
+		Assert.isNotNull(parent, "The parent node must not be null!");
 
 		final String name = pseudoElementName.toLowerCase();
-		Styles styles = getStyles(parent);
-		if (!styles.hasPseudoElement(name)) {
+		final Styles parentStyles = getStyles(parent);
+		if (parentStyles == null || !parentStyles.hasPseudoElement(name)) {
 			return null;
 		}
 
-		styles = styles.getPseudoElementStyles(name);
-		if (hasContent && (styles == null || !styles.isContentDefined())) {
+		final Styles pseudoElementStyles = parentStyles.getPseudoElementStyles(name);
+		if (pseudoElementStyles == null || !pseudoElementStyles.isContentDefined()) {
 			return null;
 		}
+
 		return new PseudoElement(parent, name);
 	}
 
 	/**
 	 * Returns the styles for the given element. The styles are cached to ensure reasonable performance.
-	 * 
+	 *
 	 * @param node
 	 *            Node for which to calculate the styles.
 	 */
@@ -210,7 +218,7 @@
 
 	private Styles calculateStyles(final INode node) {
 
-		// getApplicableDeclarations returns the elements styles and also pseudo element styles 
+		// getApplicableDeclarations returns the elements styles and also pseudo element styles
 		final Map<String, Map<String, LexicalUnit>> decls = getApplicableDeclarations(node);
 
 		// The null key contains the element's direct styles
@@ -298,7 +306,7 @@
 
 	/**
 	 * Returns all the declarations that apply to the given element and defined pseudo elements.
-	 * 
+	 *
 	 * @return The key 'null' in the returned Map contains the node's declarations. Names keys contain the declarations
 	 *         for pseudo elements.
 	 */
@@ -379,7 +387,7 @@
 
 	/**
 	 * This method is only public to be available for unit testing. It is not meant to be used in an implementation.
-	 * 
+	 *
 	 * @param node
 	 * @return
 	 */
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/StyleSheetReader.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/StyleSheetReader.java
index dce4b62..49d1eb9 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/StyleSheetReader.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/StyleSheetReader.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *     Florian Thienel - bug 306639 - remove serializability from StyleSheet
@@ -113,7 +113,7 @@
 
 	/**
 	 * Creates a new StyleSheet object from a URL.
-	 * 
+	 *
 	 * @param url
 	 *            URL from which to read the style sheet.
 	 */
@@ -123,7 +123,7 @@
 
 	/**
 	 * Creates a style sheet from a string. This is mainly used for small style sheets within unit tests.
-	 * 
+	 *
 	 * @param s
 	 *            String containing the style sheet.
 	 */
@@ -134,7 +134,7 @@
 
 	/**
 	 * Creates a new Stylesheet from an input source.
-	 * 
+	 *
 	 * @param inputSource
 	 *            InputSource from which to read the stylesheet.
 	 * @param url
@@ -148,7 +148,7 @@
 
 	/**
 	 * Parse a stylesheet file from a URL and return the list of rules.
-	 * 
+	 *
 	 * @param url
 	 *            URL from which to read the style sheet.
 	 * @return The List of rules.
@@ -159,7 +159,7 @@
 
 	/**
 	 * Parse a stylesheet file from an input source and return the list of rules.
-	 * 
+	 *
 	 * @param inputSource
 	 *            InputSource from which to read the stylesheet.
 	 * @param url
@@ -197,29 +197,37 @@
 
 		// -------------------------------------------- DocumentHandler methods
 
+		@Override
 		public void comment(final java.lang.String text) {
 		}
 
+		@Override
 		public void endDocument(final InputSource source) {
 		}
 
+		@Override
 		public void endFontFace() {
 		}
 
+		@Override
 		public void endMedia(final SACMediaList media) {
 		}
 
+		@Override
 		public void endPage(final String name, final String pseudo_page) {
 		}
 
+		@Override
 		public void endSelector(final SelectorList selectors) {
 			rules.addAll(currentRules);
 			currentRules = null;
 		}
 
+		@Override
 		public void ignorableAtRule(final String atRule) {
 		}
 
+		@Override
 		public void importStyle(final String uri, final SACMediaList media, final String defaultNamespaceURI) {
 			if (url == null) {
 				return;
@@ -239,9 +247,11 @@
 
 		}
 
+		@Override
 		public void namespaceDeclaration(final String prefix, final String uri) {
 		}
 
+		@Override
 		public void property(final String name, final LexicalUnit value, final boolean important) {
 			if (name.equals(CSS.BORDER)) {
 				this.expandBorder(value, important);
@@ -270,18 +280,23 @@
 			}
 		}
 
+		@Override
 		public void startDocument(final InputSource source) {
 		}
 
+		@Override
 		public void startFontFace() {
 		}
 
+		@Override
 		public void startMedia(final SACMediaList media) {
 		}
 
+		@Override
 		public void startPage(final String name, final String pseudo_page) {
 		}
 
+		@Override
 		public void startSelector(final SelectorList selectors) {
 			currentRules = new ArrayList<Rule>();
 			for (int i = 0; i < selectors.getLength(); i++) {
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/Styles.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/Styles.java
index 5f8e14d..f6a6582 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/Styles.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/Styles.java
@@ -45,7 +45,7 @@
 
 	/**
 	 * Returns the value of the given property, or null if the property does not have a value.
-	 * 
+	 *
 	 * @param propertyName
 	 * @return
 	 */
@@ -141,7 +141,7 @@
 	 * Returns a <code>List</code> of <code>ContentPart</code> objects representing the <code>content</code> property.<br />
 	 * The content is parsed on every access to get the actual values for attributes. Do not try to get the content via
 	 * the {@link #get(String)} method!
-	 * 
+	 *
 	 * @param node
 	 *            The INode to get attr(...) values from
 	 */
@@ -272,7 +272,7 @@
 
 	/**
 	 * Sets the value of a property in this stylesheet.
-	 * 
+	 *
 	 * @param propertyName
 	 *            Name of the property being set.
 	 * @param value
@@ -297,7 +297,7 @@
 
 	/**
 	 * Check if the given pseudo element is defined for this node.
-	 * 
+	 *
 	 * @param pseudoElementName
 	 * @return <code>true</code> when the given pseudo element is defined.
 	 */
@@ -307,7 +307,7 @@
 
 	/**
 	 * Sets the LexicalUnits of the <code>content</code> property.
-	 * 
+	 *
 	 * @param content
 	 *            <code>List</code> of <code>LexicalUnits</code> objects defining the content.
 	 */
@@ -317,7 +317,7 @@
 
 	/**
 	 * Sets the value of the <code>font</code> property.
-	 * 
+	 *
 	 * @param font
 	 *            new value for the <code>font</code> property.
 	 */
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/TextAlignProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/TextAlignProperty.java
index 132c4d3..c8cd073 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/TextAlignProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/TextAlignProperty.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -25,6 +25,7 @@
 		super(CSS.TEXT_ALIGN);
 	}
 
+	@Override
 	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 		if (TextAlignProperty.isTextAlign(lu)) {
 			return lu.getStringValue();
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/TextDecorationProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/TextDecorationProperty.java
index 0c70310..0ecd9b5 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/TextDecorationProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/TextDecorationProperty.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -25,6 +25,7 @@
 		super(CSS.TEXT_DECORATION);
 	}
 
+	@Override
 	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 		if (isTextDecoration(lu)) {
 			return lu.getStringValue();
@@ -42,7 +43,7 @@
 
 	/**
 	 * Returns true if the given lexical unit represents a text decoration.
-	 * 
+	 *
 	 * @param lu
 	 *            LexicalUnit to check.
 	 */
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/VexSelectorFactory.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/VexSelectorFactory.java
index e092e7e..d19fe82 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/VexSelectorFactory.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/VexSelectorFactory.java
@@ -30,7 +30,10 @@
 		final int seperatorIndex = tagName != null ? tagName.indexOf("|") : -1;
 		if (seperatorIndex > -1) {
 			final String namespacePrefix = tagName.substring(0, seperatorIndex);
-			if (namespacePrefix.equals(CSS.VEX_NAMESPACE_PREFIX)) {
+			if (namespacePrefix.equals(CSS.XINCLUDE_NAMESPACE_PREFIX)) {
+				namespaceURI = Namespace.XINCLUDE_NAMESPACE_URI;
+				tagName = tagName.substring(seperatorIndex + 1);
+			} else if (namespacePrefix.equals(CSS.VEX_NAMESPACE_PREFIX)) {
 				namespaceURI = Namespace.VEX_NAMESPACE_URI;
 				tagName = tagName.substring(seperatorIndex + 1);
 			}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/WhiteSpaceProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/WhiteSpaceProperty.java
index d84dcce..d895d96 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/WhiteSpaceProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/WhiteSpaceProperty.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -26,9 +26,10 @@
 	}
 
 	/**
-     *
-     */
+	 *
+	 */
 
+	@Override
 	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 		if (isWhiteSpace(lu)) {
 			return lu.getStringValue();
@@ -45,7 +46,7 @@
 
 	/**
 	 * Returns true if the given lexical unit represents a white space value.
-	 * 
+	 *
 	 * @param lu
 	 *            LexicalUnit to check.
 	 */
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/vex-core-styles.css b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/vex-core-styles.css
index f3c7ca2..861b237 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/vex-core-styles.css
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/vex-core-styles.css
@@ -45,4 +45,28 @@
 vex|comment:after {
 	display: inline;
 	content: '-->';
-}
\ No newline at end of file
+}
+
+xi|include {
+	background-color: #cccccc;
+	margin-top: 5px;
+	mrgin-bottom: 5px;
+	display: block;
+	_vex-outline-content: attr(href);
+}
+
+xi|include[parse="text"] {
+	display: inline;
+}
+
+xi|include:before {
+	display: inline;
+	color: blue;
+	content: '<XInclude href: ',attr(href);
+}
+
+xi|include:after {
+	display: inline;
+	color: blue;
+	content: '>';
+}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/AncestorsIterator.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/AncestorsIterator.java
index 8ce627b..e57cada 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/AncestorsIterator.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/AncestorsIterator.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

@@ -27,10 +27,12 @@
 		current = startNode;

 	}

 

+	@Override

 	public boolean hasNext() {

 		return current.getParent() != null;

 	}

 

+	@Override

 	public IParent next() {

 		if (!hasNext()) {

 			throw new NoSuchElementException();

@@ -39,6 +41,7 @@
 		return (IParent) current;

 	}

 

+	@Override

 	public void remove() {

 		throw new UnsupportedOperationException();

 	}

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Attribute.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Attribute.java
index 508c81a..2b2a670 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Attribute.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Attribute.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

@@ -17,7 +17,7 @@
 /**

  * An immutable representation of an attribute within the start tag of an element. An attribute consists of a qualified

  * name and a value. It is Comparable by its qualified name, which is the natural order of attributes.

- * 

+ *

  * @author Florian Thienel

  */

 public class Attribute implements IAttribute {

@@ -38,22 +38,27 @@
 		this.value = value;

 	}

 

+	@Override

 	public IElement getParent() {

 		return parent;

 	}

 

+	@Override

 	public String getLocalName() {

 		return name.getLocalName();

 	}

 

+	@Override

 	public String getValue() {

 		return value;

 	}

 

+	@Override

 	public QualifiedName getQualifiedName() {

 		return name;

 	}

 

+	@Override

 	public String getPrefixedName() {

 		final String attributeQualifier = name.getQualifier();

 		if (parent == null || attributeQualifier == null) {

@@ -63,6 +68,7 @@
 		return (prefix == null ? "" : prefix + ":") + getLocalName();

 	}

 

+	@Override

 	public int compareTo(final IAttribute otherAttribute) {

 		return name.toString().compareTo(otherAttribute.getQualifiedName().toString());

 	}

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Axis.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Axis.java
index 303b54c..f9abe24 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Axis.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Axis.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

@@ -44,10 +44,12 @@
 		this.sourceNode = sourceNode;

 	}

 

+	@Override

 	public INode getSourceNode() {

 		return sourceNode;

 	}

 

+	@Override

 	@SuppressWarnings("unchecked")

 	public Iterator<T> iterator() {

 		Iterator<? extends T> result = rootIterator();

@@ -74,31 +76,37 @@
 

 	protected abstract Iterator<? extends T> createRootIterator(final ContentRange contentRange, final boolean includeText);

 

+	@Override

 	public Axis<? extends T> in(final ContentRange range) {

 		Assert.isTrue(ContentRange.ALL.equals(contentRange), "Can only use one of 'before', 'after' or 'in' in the same expression.");

 		contentRange = range;

 		return this;

 	}

 

+	@Override

 	public Axis<? extends T> before(final int beforeOffset) {

 		Assert.isTrue(ContentRange.ALL.equals(contentRange), "Can only use one of 'before', 'after' or 'in' in the same expression.");

 		contentRange = new ContentRange(contentRange.getStartOffset(), beforeOffset);

 		return this;

 	}

 

+	@Override

 	public Axis<? extends T> after(final int afterOffset) {

 		Assert.isTrue(ContentRange.ALL.equals(contentRange), "Can only use one of 'before', 'after' or 'in' in the same expression.");

 		contentRange = new ContentRange(afterOffset, contentRange.getEndOffset());

 		return this;

 	}

 

+	@Override

 	public Axis<? extends T> withoutText() {

 		includeText = false;

 		return this;

 	}

 

+	@Override

 	public Axis<? extends T> matching(final IFilter<INode> filter) {

 		chain.add(new IteratorFactory() {

+			@Override

 			public Iterator<? extends INode> iterator(final Iterator<? extends INode> source) {

 				return new FilterIterator<INode>(source, filter);

 			}

@@ -106,22 +114,26 @@
 		return this;

 	}

 

+	@Override

 	public Axis<? extends T> from(final int startIndex) {

 		Assert.isTrue(this.startIndex == UNDEFINED, "Can set start index only once.");

 		this.startIndex = startIndex;

 		return this;

 	}

 

+	@Override

 	public Axis<? extends T> to(final int endIndex) {

 		Assert.isTrue(this.endIndex == UNDEFINED, "Can set end index only once.");

 		this.endIndex = endIndex;

 		return this;

 	}

 

+	@Override

 	public boolean isEmpty() {

 		return !iterator().hasNext();

 	}

 

+	@Override

 	public List<T> asList() {

 		final ArrayList<T> result = new ArrayList<T>();

 		for (final T node : this) {

@@ -130,10 +142,12 @@
 		return result;

 	}

 

+	@Override

 	public T first() {

 		return iterator().next();

 	}

 

+	@Override

 	public T last() {

 		T result = null;

 		final Iterator<T> iterator = iterator();

@@ -146,6 +160,7 @@
 		return result;

 	}

 

+	@Override

 	public T get(final int index) {

 		final Iterator<T> iterator = iterator();

 		int i = 0;

@@ -155,12 +170,14 @@
 		return iterator.next();

 	}

 

+	@Override

 	public void accept(final INodeVisitor visitor) {

 		for (final INode node : this) {

 			node.accept(visitor);

 		}

 	}

 

+	@Override

 	public int count() {

 		int result = 0;

 		final Iterator<T> iterator = iterator();

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Comment.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Comment.java
index 3a2de95..861f28a 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Comment.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Comment.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

@@ -17,19 +17,22 @@
 

 /**

  * A representation of an XML comment in the DOM. Comments have textual content, a start and an end tag.

- * 

+ *

  * @author Florian Thienel

  */

 public class Comment extends Node implements IComment {

 

+	@Override

 	public void accept(final INodeVisitor visitor) {

 		visitor.visit(this);

 	}

 

+	@Override

 	public <T> T accept(final INodeVisitorWithResult<T> visitor) {

 		return visitor.visit(this);

 	}

 

+	@Override

 	public boolean isKindOf(final INode node) {

 		if (!(node instanceof IComment)) {

 			return false;

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/CopyOfElement.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/CopyOfElement.java
index d3a47fd..0d13e54 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/CopyOfElement.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/CopyOfElement.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

@@ -20,7 +20,7 @@
  * <li>attributes</li>

  * <li>namespace declarations</li>

  * </ul>

- * 

+ *

  * @author Florian Thienel

  */

 public class CopyOfElement extends BaseNodeVisitor {

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/CopyVisitor.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/CopyVisitor.java
index 17ce850..10a61d6 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/CopyVisitor.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/CopyVisitor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************

- * Copyright (c) 2012, 2013 Florian Thienel and others.

+ * Copyright (c) 2012, 2014 Florian Thienel 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

@@ -7,7 +7,7 @@
  *

  * Contributors:

  * 		Florian Thienel - initial API and implementation

- * 		Carsten Hiesserich - added processing instructions

+ * 		Carsten Hiesserich - added processing instructions and include

  *******************************************************************************/

 package org.eclipse.vex.core.internal.dom;

 

@@ -15,6 +15,7 @@
 import org.eclipse.vex.core.provisional.dom.IDocument;

 import org.eclipse.vex.core.provisional.dom.IDocumentFragment;

 import org.eclipse.vex.core.provisional.dom.IElement;

+import org.eclipse.vex.core.provisional.dom.IIncludeNode;

 import org.eclipse.vex.core.provisional.dom.INodeVisitorWithResult;

 import org.eclipse.vex.core.provisional.dom.IProcessingInstruction;

 import org.eclipse.vex.core.provisional.dom.IText;

@@ -22,36 +23,51 @@
 /**

  * This visitor creates a simple copy of the visited node. I.e. only the node itself, not its content neither its

  * children are copied. The copy is provided through the getCopy() method.

- * 

+ *

  * @author Florian Thienel

  */

 public class CopyVisitor implements INodeVisitorWithResult<Node> {

 

+	@Override

 	public Document visit(final IDocument document) {

 		throw new UnsupportedOperationException("Document cannot be copied");

 	}

 

+	@Override

 	public DocumentFragment visit(final IDocumentFragment fragment) {

 		throw new UnsupportedOperationException("DocumentFragment cannot be copied");

 	}

 

+	@Override

 	public Element visit(final IElement element) {

 		final Element copyElement = new Element(element.getQualifiedName());

 		copyElement.accept(new CopyOfElement(element));

 		return copyElement;

 	}

 

+	@Override

 	public Text visit(final IText text) {

 		// ignore Text nodes because they are created dynamically in Element.getChildNodes()

 		return null;

 	}

 

+	@Override

 	public Comment visit(final IComment comment) {

 		return new Comment();

 	}

 

+	@Override

 	public ProcessingInstruction visit(final IProcessingInstruction pi) {

 		return new ProcessingInstruction(pi.getTarget());

 	}

 

+	@Override

+	public Node visit(final IIncludeNode include) {

+		// Copy the reference element

+		final Element copyElement = new Element(include.getReference().getQualifiedName());

+		copyElement.accept(new CopyOfElement(include.getReference()));

+

+		return new IncludeNode(copyElement);

+	}

+

 }

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DeepCopy.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DeepCopy.java
index 743a806..5d38e04 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DeepCopy.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DeepCopy.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

@@ -24,7 +24,7 @@
  * instantly when the constructor of DeepCopy is called.

  * <p>

  * DeepCopy means a full copy of all nodes, their children down to the leaf level and the associated content.

- * 

+ *

  * @author Florian Thienel

  */

 public class DeepCopy {

@@ -34,7 +34,7 @@
 

 	/**

 	 * Creates a deep copy of the given node.

-	 * 

+	 *

 	 * @param node

 	 *            the node to copy

 	 */

@@ -55,7 +55,7 @@
 

 	/**

 	 * Creates a deep copy of the child nodes of the given parent within the given range.

-	 * 

+	 *

 	 * @param parent

 	 *            the parent

 	 * @param range

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DeepCopyVisitor.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DeepCopyVisitor.java
index 9ad15f5..45c846e 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DeepCopyVisitor.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DeepCopyVisitor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************

- * Copyright (c) 2012, 2013 Florian Thienel and others.

+ * Copyright (c) 2012, 2014 Florian Thienel 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

@@ -7,7 +7,7 @@
  *

  * Contributors:

  * 		Florian Thienel - initial API and implementation

- * 		Carsten Hiesserich - added processing instructions

+ * 		Carsten Hiesserich - added processing instructions and include

  *******************************************************************************/

 package org.eclipse.vex.core.internal.dom;

 

@@ -19,6 +19,7 @@
 import org.eclipse.vex.core.provisional.dom.IDocument;

 import org.eclipse.vex.core.provisional.dom.IDocumentFragment;

 import org.eclipse.vex.core.provisional.dom.IElement;

+import org.eclipse.vex.core.provisional.dom.IIncludeNode;

 import org.eclipse.vex.core.provisional.dom.INode;

 import org.eclipse.vex.core.provisional.dom.INodeVisitor;

 import org.eclipse.vex.core.provisional.dom.IParent;

@@ -29,7 +30,7 @@
  * This visitor creates a deep copy of the visited nodes. Deep copy means a full copy of each visited node and its

  * children down to the leaf level. All copied nodes are associated with a given content. The copied nodes on the root

  * level are collected in a given List.

- * 

+ *

  * @author Florian Thienel

  */

 public class DeepCopyVisitor implements INodeVisitor {

@@ -57,14 +58,17 @@
 		this.delta = delta;

 	}

 

+	@Override

 	public void visit(final IDocument document) {

 		throw new UnsupportedOperationException("Document cannot be deep copied");

 	}

 

+	@Override

 	public void visit(final IDocumentFragment fragment) {

 		copyChildren(fragment, null);

 	}

 

+	@Override

 	public void visit(final IElement element) {

 		final Element copy = (Element) copy(element);

 		addToParent(copy);

@@ -73,22 +77,34 @@
 		copyChildren(element, copy);

 	}

 

+	@Override

 	public void visit(final IText text) {

 		// ignore Text nodes because they are created dynamically in Element.getChildNodes()

 	}

 

+	@Override

 	public void visit(final IComment comment) {

 		final Comment copy = (Comment) copy(comment);

 		addToParent(copy);

 		associate(comment, copy);

 	}

 

+	@Override

 	public void visit(final IProcessingInstruction pi) {

 		final ProcessingInstruction copy = (ProcessingInstruction) copy(pi);

 		addToParent(copy);

 		associate(pi, copy);

 	}

 

+	@Override

+	public void visit(final IIncludeNode include) {

+		final IncludeNode copy = (IncludeNode) copy(include);

+		addToParent(copy);

+		associate(include, copy);

+

+		copyChildren(include.getReference(), copy.getReference());

+	}

+

 	@SuppressWarnings("unchecked")

 	private <T extends INode> T copy(final T node) {

 		return (T) node.accept(copyVisitor);

@@ -117,5 +133,4 @@
 		}

 		currentParent = lastParent;

 	}

-

 }

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Document.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Document.java
index 2e4ff89..04bd115 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Document.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Document.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *     Igor Jacy Lino Campista - Java 5 warnings fixed (bug 311325)
@@ -30,6 +30,7 @@
 import org.eclipse.vex.core.internal.core.ListenerList;
 import org.eclipse.vex.core.provisional.dom.BaseNodeVisitorWithResult;
 import org.eclipse.vex.core.provisional.dom.ContentChangeEvent;
+import org.eclipse.vex.core.provisional.dom.ContentPosition;
 import org.eclipse.vex.core.provisional.dom.ContentRange;
 import org.eclipse.vex.core.provisional.dom.DocumentEvent;
 import org.eclipse.vex.core.provisional.dom.DocumentValidationException;
@@ -39,6 +40,7 @@
 import org.eclipse.vex.core.provisional.dom.IDocumentFragment;
 import org.eclipse.vex.core.provisional.dom.IDocumentListener;
 import org.eclipse.vex.core.provisional.dom.IElement;
+import org.eclipse.vex.core.provisional.dom.IIncludeNode;
 import org.eclipse.vex.core.provisional.dom.INode;
 import org.eclipse.vex.core.provisional.dom.INodeVisitor;
 import org.eclipse.vex.core.provisional.dom.INodeVisitorWithResult;
@@ -68,7 +70,7 @@
 	/**
 	 * Create a new document with the given root element. This constructor creates a Content object and associates both
 	 * the root element and the document with it.
-	 * 
+	 *
 	 * @param rootElementName
 	 *            the name of the root element of the document
 	 */
@@ -88,12 +90,12 @@
 	/**
 	 * Create a new document with the given content and root element. This constructor assumes that the content and root
 	 * element have bee properly set up and are already associated. It associates the document with the given content.
-	 * 
+	 *
 	 * @param content
 	 *            Content object used to store the document's content
 	 * @param rootElement
 	 *            root element of the document
-	 * 
+	 *
 	 */
 	public Document(final IContent content, final Element rootElement) {
 		Assert.isTrue(content == rootElement.getContent(), "The given root element must already be associated with the given content.");
@@ -119,10 +121,12 @@
 		return getContent().length() - 1;
 	}
 
+	@Override
 	public void accept(final INodeVisitor visitor) {
 		visitor.visit(this);
 	}
 
+	@Override
 	public <T> T accept(final INodeVisitorWithResult<T> visitor) {
 		return visitor.visit(this);
 	}
@@ -132,6 +136,7 @@
 		return getDocumentURI();
 	}
 
+	@Override
 	public boolean isKindOf(final INode node) {
 		return false;
 	}
@@ -140,58 +145,72 @@
 	 * Document
 	 */
 
+	@Override
 	public void setDocumentURI(final String documentURI) {
 		this.documentURI = documentURI;
 	}
 
+	@Override
 	public String getDocumentURI() {
 		return documentURI;
 	}
 
+	@Override
 	public String getEncoding() {
 		return encoding;
 	}
 
+	@Override
 	public void setEncoding(final String encoding) {
 		this.encoding = encoding;
 	}
 
+	@Override
 	public String getPublicID() {
 		return publicID;
 	}
 
+	@Override
 	public void setPublicID(final String publicID) {
 		this.publicID = publicID;
 	}
 
+	@Override
 	public String getSystemID() {
 		return systemID;
 	}
 
+	@Override
 	public void setSystemID(final String systemID) {
 		this.systemID = systemID;
 	}
 
+	@Override
 	public IValidator getValidator() {
 		return validator;
 	}
 
+	@Override
 	public void setValidator(final IValidator validator) {
 		this.validator = validator;
 	}
 
+	@Override
 	public Element getRootElement() {
 		return rootElement;
 	}
 
+	@Override
 	public int getLength() {
 		return getContent().length();
 	}
 
+	@Override
 	public IPosition createPosition(final int offset) {
 		return getContent().createPosition(offset);
 	}
 
+	@Override
 	public void removePosition(final IPosition position) {
 		getContent().removePosition(position);
 	}
@@ -249,24 +268,29 @@
 		});
 	}
 
+	@Override
 	public boolean canInsertText(final int offset) {
 		return canInsertAt(getNodeForInsertionAt(offset), offset, IValidator.PCDATA);
 	}
 
+	@Override
 	public void insertText(final int offset, final String text) throws DocumentValidationException {
 		Assert.isTrue(offset > getStartOffset() && offset <= getEndOffset(), MessageFormat.format("Offset must be in [{0}, {1}]", getStartOffset() + 1, getEndOffset()));
 
 		final String adjustedText = convertControlCharactersToSpaces(text);
 		final INode insertionNode = getNodeForInsertionAt(offset);
 		insertionNode.accept(new INodeVisitor() {
+			@Override
 			public void visit(final IDocument document) {
 				Assert.isTrue(false, "Cannot insert text directly into Document.");
 			}
 
+			@Override
 			public void visit(final IDocumentFragment fragment) {
 				Assert.isTrue(false, "DocumentFragment is never a child of Document.");
 			}
 
+			@Override
 			public void visit(final IElement element) {
 				if (!canInsertAt(element, offset, IValidator.PCDATA)) {
 					throw new DocumentValidationException(MessageFormat.format("Cannot insert text ''{0}'' at offset {1}.", text, offset));
@@ -277,18 +301,21 @@
 				fireContentInserted(new ContentChangeEvent(Document.this, element, new ContentRange(offset, offset + adjustedText.length() - 1), false));
 			}
 
+			@Override
 			public void visit(final IText text) {
 				fireBeforeContentInserted(new ContentChangeEvent(Document.this, text.getParent(), new ContentRange(offset, offset + adjustedText.length() - 1), false));
 				getContent().insertText(offset, adjustedText);
 				fireContentInserted(new ContentChangeEvent(Document.this, text.getParent(), new ContentRange(offset, offset + adjustedText.length() - 1), false));
 			}
 
+			@Override
 			public void visit(final IComment comment) {
 				fireBeforeContentInserted(new ContentChangeEvent(Document.this, comment.getParent(), new ContentRange(offset, offset + adjustedText.length() - 1), false));
 				getContent().insertText(offset, adjustedText);
 				fireContentInserted(new ContentChangeEvent(Document.this, comment.getParent(), new ContentRange(offset, offset + adjustedText.length() - 1), false));
 			}
 
+			@Override
 			public void visit(final IProcessingInstruction pi) {
 				// The target is validated to ensure the instruction is valid after the insertion
 				final String charBefore = pi.getText(new ContentRange(offset - 1, offset - 1));
@@ -304,6 +331,10 @@
 				getContent().insertText(offset, adjustedText);
 				fireContentInserted(new ContentChangeEvent(Document.this, pi.getParent(), new ContentRange(offset, offset + adjustedText.length() - 1), false));
 			}
+
+			public void visit(final IIncludeNode document) {
+				Assert.isTrue(false, "Cannot insert text into an Include.");
+			}
 		});
 	}
 
@@ -319,7 +350,7 @@
 
 	/**
 	 * Inserts a node at the given offset. There is no check that the insertion is valid.
-	 * 
+	 *
 	 * @param node
 	 *            The node to insert
 	 * @param offset
@@ -351,6 +382,7 @@
 		return false;
 	}
 
+	@Override
 	public IComment insertComment(final int offset) throws DocumentValidationException {
 		if (!canInsertComment(offset)) {
 			throw new DocumentValidationException(MessageFormat.format("Cannot insert a comment at offset {0}.", offset));
@@ -418,10 +450,12 @@
 		fireContentInserted(new ContentChangeEvent(this, node.getParent(), new ContentRange(node.getStartOffset(), node.getEndOffset()), false));
 	}
 
+	@Override
 	public boolean canInsertElement(final int offset, final QualifiedName elementName) {
 		return canInsertAt(getNodeForInsertionAt(offset), offset, elementName);
 	}
 
+	@Override
 	public Element insertElement(final int offset, final QualifiedName elementName) throws DocumentValidationException {
 		Assert.isTrue(offset > rootElement.getStartOffset() && offset <= rootElement.getEndOffset(),
 				MessageFormat.format("Offset must be in [{0}, {1}]", rootElement.getStartOffset() + 1, rootElement.getEndOffset()));
@@ -437,10 +471,12 @@
 		return element;
 	}
 
+	@Override
 	public boolean canInsertFragment(final int offset, final IDocumentFragment fragment) {
 		return canInsertAt(getNodeForInsertionAt(offset), offset, fragment.getNodeNames());
 	}
 
+	@Override
 	public void insertFragment(final int offset, final IDocumentFragment fragment) throws DocumentValidationException {
 		Assert.isTrue(isInsertionPointIn(this, offset), "Cannot insert fragment outside of the document range.");
 
@@ -491,6 +527,7 @@
 		}
 	}
 
+	@Override
 	public boolean canDelete(final ContentRange range) {
 		final IParent surroundingParent = getParentAt(range.getStartOffset());
 		final IParent parentAtEndOffset = getParentAt(range.getEndOffset());
@@ -529,6 +566,7 @@
 		return deletionIsValid;
 	}
 
+	@Override
 	public void delete(final ContentRange range) throws DocumentValidationException {
 		IParent surroundingParent = getParentAt(range.getStartOffset());
 		if (range.getStartOffset() == surroundingParent.getStartOffset()) {
@@ -586,6 +624,7 @@
 	 * Miscellaneous
 	 */
 
+	@Override
 	public char getCharacterAt(final int offset) {
 		final String text = getContent().getText(new ContentRange(offset, offset));
 		if (text.length() == 0) {
@@ -599,6 +638,7 @@
 		return text.charAt(0);
 	}
 
+	@Override
 	public INode findCommonNode(final int offset1, final int offset2) {
 		Assert.isTrue(containsOffset(offset1) && containsOffset(offset2));
 		return findCommonNodeIn(this, offset1, offset2);
@@ -624,6 +664,7 @@
 		return node.getRange().resizeBy(1, 0).contains(offset);
 	}
 
+	@Override
 	public INode getNodeForInsertionAt(final int offset) {
 		final INode node = getChildAt(offset);
 		if (node instanceof IText) {
@@ -635,6 +676,11 @@
 		return node;
 	}
 
+	@Override
+	public INode getNodeForInsertionAt(final ContentPosition position) {
+		return position.getNodeForInsertion();
+	}
+
 	private Parent getParentForInsertionAt(final int offset) {
 		final INode node = getChildAt(offset);
 		if (!(node instanceof Parent)) {
@@ -647,6 +693,7 @@
 		return (Parent) node;
 	}
 
+	@Override
 	public Element getElementForInsertionAt(final int offset) {
 		final Element parent = getParentElement(getChildAt(offset));
 		if (parent == null) {
@@ -676,10 +723,12 @@
 		return child.getParent();
 	}
 
+	@Override
 	public boolean isTagAt(final int offset) {
 		return getContent().isTagMarker(offset);
 	}
 
+	@Override
 	public DocumentFragment getFragment(final ContentRange range) {
 		final IParent parent = getParentOfRange(range);
 		final DeepCopy deepCopy = new DeepCopy(parent, range);
@@ -698,6 +747,7 @@
 		return parent;
 	}
 
+	@Override
 	public List<? extends INode> getNodes(final ContentRange range) {
 		return getParentOfRange(range).children().in(range).asList();
 	}
@@ -706,10 +756,12 @@
 	 * Events
 	 */
 
+	@Override
 	public void addDocumentListener(final IDocumentListener listener) {
 		listeners.add(listener);
 	}
 
+	@Override
 	public void removeDocumentListener(final IDocumentListener listener) {
 		listeners.remove(listener);
 	}
@@ -752,10 +804,12 @@
 			this.prefix = prefix;
 		}
 
+		@Override
 		public boolean hasNext() {
 			return true;
 		}
 
+		@Override
 		public String next() {
 			final String result = prefix + namespaceIndex++;
 			if (!element.getNamespacePrefixes().contains(result)) {
@@ -764,6 +818,7 @@
 			return next();
 		}
 
+		@Override
 		public void remove() {
 			throw new UnsupportedOperationException("remove not supported");
 		}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentFragment.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentFragment.java
index 77f210a..126fcdd 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentFragment.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentFragment.java
@@ -4,11 +4,11 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *     Igor Jacy Lino Campista - Java 5 warnings fixed (bug 311325)
- *     Florian Thienel - extracted responsibility for serialization, refactoring to full fledged DOM  
+ *     Florian Thienel - extracted responsibility for serialization, refactoring to full fledged DOM
  *******************************************************************************/
 package org.eclipse.vex.core.internal.dom;
 
@@ -32,14 +32,17 @@
 		}
 	}
 
+	@Override
 	public int getLength() {
 		return getContent().length();
 	}
 
+	@Override
 	public List<QualifiedName> getNodeNames() {
 		return Node.getNodeNames(children());
 	}
 
+	@Override
 	public List<? extends INode> getNodes() {
 		return children().asList();
 	}
@@ -49,14 +52,17 @@
 		return null;
 	}
 
+	@Override
 	public void accept(final INodeVisitor visitor) {
 		visitor.visit(this);
 	}
 
+	@Override
 	public <T> T accept(final INodeVisitorWithResult<T> visitor) {
 		return visitor.visit(this);
 	}
 
+	@Override
 	public boolean isKindOf(final INode node) {
 		return false;
 	}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentTextPosition.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentTextPosition.java
index b729199..99e9dbc 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentTextPosition.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentTextPosition.java
@@ -24,7 +24,7 @@
 
 	/**
 	 * Creates a new position with the given offset and length 0.
-	 * 
+	 *
 	 * @param offset
 	 *            the position offset, must be >= 0
 	 */
@@ -34,7 +34,7 @@
 
 	/**
 	 * Creates a new position with the given offset and length.
-	 * 
+	 *
 	 * @param offset
 	 *            the position offset, must be >= 0
 	 * @param length
@@ -76,7 +76,7 @@
 
 	/**
 	 * Return the previously stored offset.
-	 * 
+	 *
 	 * @return The stored offset
 	 */
 	public int getOffsetInNode() {
@@ -85,7 +85,7 @@
 
 	/**
 	 * Stores an additional offset in this position
-	 * 
+	 *
 	 * @param offsetInNode
 	 *            The offset to store.
 	 */
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Element.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Element.java
index 1ddbc69..1457c36 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Element.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Element.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *     Igor Jacy Lino Campista - Java 5 warnings fixed (bug 311325)
@@ -62,10 +62,12 @@
 		return super.getBaseURI();
 	}
 
+	@Override
 	public void setBaseURI(final String baseURI) {
 		setAttribute(XML.BASE_ATTRIBUTE, baseURI);
 	}
 
+	@Override
 	public boolean isKindOf(final INode other) {
 		if (!(other instanceof IElement)) {
 			return false;
@@ -73,10 +75,12 @@
 		return getQualifiedName().equals(((IElement) other).getQualifiedName());
 	}
 
+	@Override
 	public void accept(final INodeVisitor visitor) {
 		visitor.visit(this);
 	}
 
+	@Override
 	public <T> T accept(final INodeVisitorWithResult<T> visitor) {
 		return visitor.visit(this);
 	}
@@ -85,18 +89,22 @@
 	 * Element Name
 	 */
 
+	@Override
 	public QualifiedName getQualifiedName() {
 		return name;
 	}
 
+	@Override
 	public String getLocalName() {
 		return name.getLocalName();
 	}
 
+	@Override
 	public String getPrefix() {
 		return getNamespacePrefix(name.getQualifier());
 	}
 
+	@Override
 	public String getPrefixedName() {
 		final String prefix = getPrefix();
 		if (prefix == null) {
@@ -105,6 +113,7 @@
 		return prefix + ":" + getLocalName();
 	}
 
+	@Override
 	public QualifiedName qualify(final String localName) {
 		return new QualifiedName(name.getQualifier(), localName);
 	}
@@ -113,18 +122,22 @@
 	 * Attributes
 	 */
 
+	@Override
 	public IAttribute getAttribute(final String localName) {
 		return getAttribute(new QualifiedName(null, localName));
 	}
 
+	@Override
 	public IAttribute getAttribute(final QualifiedName name) {
 		return attributes.get(name);
 	}
 
+	@Override
 	public String getAttributeValue(final String localName) {
 		return getAttributeValue(new QualifiedName(null, localName));
 	}
 
+	@Override
 	public String getAttributeValue(final QualifiedName name) {
 		final IAttribute attribute = getAttribute(name);
 		if (attribute == null || "".equals(attribute.getValue().trim())) {
@@ -133,18 +146,22 @@
 		return attribute.getValue();
 	}
 
+	@Override
 	public boolean canRemoveAttribute(final String localName) {
 		return canRemoveAttribute(qualify(localName));
 	}
 
+	@Override
 	public boolean canRemoveAttribute(final QualifiedName name) {
 		return true; // TODO implement validation for attribute values
 	}
 
+	@Override
 	public void removeAttribute(final String localName) throws DocumentValidationException {
 		removeAttribute(new QualifiedName(null, localName));
 	}
 
+	@Override
 	public void removeAttribute(final QualifiedName name) throws DocumentValidationException {
 		final IAttribute attribute = this.getAttribute(name);
 		if (attribute == null) {
@@ -164,18 +181,22 @@
 		document.fireAttributeChanged(new AttributeChangeEvent(document, this, name, oldValue, newValue));
 	}
 
+	@Override
 	public boolean canSetAttribute(final String localName, final String value) {
 		return canSetAttribute(qualify(localName), value);
 	}
 
+	@Override
 	public boolean canSetAttribute(final QualifiedName name, final String value) {
 		return true; // TODO implement validation for attribute values
 	}
 
+	@Override
 	public void setAttribute(final String localName, final String value) throws DocumentValidationException {
 		setAttribute(new QualifiedName(null, localName), value);
 	}
 
+	@Override
 	public void setAttribute(final QualifiedName name, final String value) throws DocumentValidationException {
 		final IAttribute oldAttribute = attributes.get(name);
 		final String oldValue = oldAttribute != null ? oldAttribute.getValue() : null;
@@ -203,12 +224,14 @@
 		}
 	}
 
+	@Override
 	public Collection<IAttribute> getAttributes() {
 		final ArrayList<IAttribute> result = new ArrayList<IAttribute>(attributes.values());
 		Collections.sort(result);
 		return Collections.unmodifiableCollection(result);
 	}
 
+	@Override
 	public Collection<QualifiedName> getAttributeNames() {
 		final ArrayList<QualifiedName> result = new ArrayList<QualifiedName>();
 		for (final IAttribute attribute : attributes.values()) {
@@ -222,6 +245,7 @@
 	 * Element Structure
 	 */
 
+	@Override
 	public Element getParentElement() {
 		for (final INode ancestor : ancestors()) {
 			if (ancestor instanceof Element) {
@@ -231,6 +255,7 @@
 		return null;
 	}
 
+	@Override
 	@SuppressWarnings("unchecked")
 	public IAxis<Element> childElements() {
 		return (IAxis<Element>) children().withoutText().matching(Filters.elements());
@@ -240,6 +265,7 @@
 	 * Namespaces
 	 */
 
+	@Override
 	public String getNamespaceURI(final String namespacePrefix) {
 		if (namespaceDeclarations.containsKey(namespacePrefix)) {
 			return namespaceDeclarations.get(namespacePrefix);
@@ -251,14 +277,17 @@
 		return null;
 	}
 
+	@Override
 	public String getDefaultNamespaceURI() {
 		return getNamespaceURI(null);
 	}
 
+	@Override
 	public String getDeclaredDefaultNamespaceURI() {
 		return namespaceDeclarations.get(null);
 	}
 
+	@Override
 	public String getNamespacePrefix(final String namespaceURI) {
 		if (namespaceURI == null) {
 			return null;
@@ -284,6 +313,7 @@
 		return null;
 	}
 
+	@Override
 	public Collection<String> getDeclaredNamespacePrefixes() {
 		final ArrayList<String> result = new ArrayList<String>();
 		for (final String prefix : namespaceDeclarations.keySet()) {
@@ -295,6 +325,7 @@
 		return result;
 	}
 
+	@Override
 	public Collection<String> getNamespacePrefixes() {
 		final HashSet<String> result = new HashSet<String>();
 		result.addAll(getDeclaredNamespacePrefixes());
@@ -305,6 +336,7 @@
 		return result;
 	}
 
+	@Override
 	public void declareNamespace(final String namespacePrefix, final String namespaceURI) {
 		if (namespaceURI == null || "".equals(namespaceURI.trim())) {
 			return;
@@ -322,6 +354,7 @@
 		document.fireNamespaceChanged(new NamespaceDeclarationChangeEvent(document, this));
 	}
 
+	@Override
 	public void removeNamespace(final String namespacePrefix) {
 		final String oldNamespaceURI = namespaceDeclarations.remove(namespacePrefix);
 		final Document document = getDocument();
@@ -336,10 +369,12 @@
 		document.fireNamespaceChanged(new NamespaceDeclarationChangeEvent(document, this));
 	}
 
+	@Override
 	public void declareDefaultNamespace(final String namespaceURI) {
 		declareNamespace(null, namespaceURI);
 	}
 
+	@Override
 	public void removeDefaultNamespace() {
 		removeNamespace(null);
 	}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/FindUndeclaredNamespacesVisitor.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/FindUndeclaredNamespacesVisitor.java
index 2062e18..0b08748 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/FindUndeclaredNamespacesVisitor.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/FindUndeclaredNamespacesVisitor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************

- * Copyright (c) 2013 Florian Thienel and others.

+ * Copyright (c) 2014 Florian Thienel 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

@@ -7,7 +7,7 @@
  *

  * Contributors:

  * 		Florian Thienel - initial API and implementation

- * 		Carsten Hiesserich - added processing instruction

+ * 		Carsten Hiesserich - added processing instruction and include

  *******************************************************************************/

 package org.eclipse.vex.core.internal.dom;

 

@@ -20,6 +20,7 @@
 import org.eclipse.vex.core.provisional.dom.IDocument;

 import org.eclipse.vex.core.provisional.dom.IDocumentFragment;

 import org.eclipse.vex.core.provisional.dom.IElement;

+import org.eclipse.vex.core.provisional.dom.IIncludeNode;

 import org.eclipse.vex.core.provisional.dom.INode;

 import org.eclipse.vex.core.provisional.dom.INodeVisitorWithResult;

 import org.eclipse.vex.core.provisional.dom.IProcessingInstruction;

@@ -28,19 +29,22 @@
 /**

  * This visitor implements a deep search for undeclared namespace URIs. The result is returned as a set of strings

  * containing the undeclared URIs.

- * 

+ *

  * @author Florian Thienel

  */

 public class FindUndeclaredNamespacesVisitor implements INodeVisitorWithResult<Set<String>> {

 

+	@Override

 	public Set<String> visit(final IDocument document) {

 		return visitAll(document.children());

 	}

 

+	@Override

 	public Set<String> visit(final IDocumentFragment fragment) {

 		return visitAll(fragment.children());

 	}

 

+	@Override

 	public Set<String> visit(final IElement element) {

 		final Set<String> result = new HashSet<String>();

 

@@ -61,18 +65,26 @@
 		return result;

 	}

 

+	@Override

 	public Set<String> visit(final IText text) {

 		return Collections.emptySet();

 	}

 

+	@Override

 	public Set<String> visit(final IComment comment) {

 		return Collections.emptySet();

 	}

 

+	@Override

 	public Set<String> visit(final IProcessingInstruction pi) {

 		return Collections.emptySet();

 	}

 

+	public Set<String> visit(final IIncludeNode include) {

+		// TODO implement this

+		return Collections.emptySet();

+	}

+

 	private Set<String> visitAll(final Iterable<INode> iterable) {

 		final Set<String> result = new HashSet<String>();

 		for (final INode node : iterable) {

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/GapContent.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/GapContent.java
index fd1d179..30ccb50 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/GapContent.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/GapContent.java
@@ -43,7 +43,7 @@
 
 	/**
 	 * Create a GapContent with the given initial capacity.
-	 * 
+	 *
 	 * @param initialCapacity
 	 *            initial capacity of the content.
 	 */
@@ -55,6 +55,7 @@
 		gapEnd = initialCapacity;
 	}
 
+	@Override
 	public IPosition createPosition(final int offset) {
 
 		assertOffset(offset, 0, length());
@@ -70,6 +71,7 @@
 		return newPosition;
 	}
 
+	@Override
 	public void removePosition(final IPosition position) {
 		if (positions.contains(position)) {
 			/*
@@ -89,6 +91,7 @@
 		return positions.size();
 	}
 
+	@Override
 	public void insertText(final int offset, final String text) {
 		assertOffset(offset, 0, length());
 
@@ -120,12 +123,14 @@
 		}
 	}
 
+	@Override
 	public void insertTagMarker(final int offset) {
 		assertOffset(offset, 0, length());
 
 		insertText(offset, Character.toString(TAG_MARKER));
 	}
 
+	@Override
 	public boolean isTagMarker(final int offset) {
 		if (offset < 0 || offset >= length()) {
 			return false;
@@ -145,6 +150,7 @@
 		return c == TAG_MARKER;
 	}
 
+	@Override
 	public void remove(final ContentRange range) {
 		assertOffset(range.getStartOffset(), 0, length() - range.length());
 		assertPositive(range.length());
@@ -165,10 +171,12 @@
 		}
 	}
 
+	@Override
 	public String getText() {
 		return getText(getRange());
 	}
 
+	@Override
 	public String getText(final ContentRange range) {
 		Assert.isTrue(getRange().contains(range));
 
@@ -196,10 +204,12 @@
 		}
 	}
 
+	@Override
 	public String getRawText() {
 		return getRawText(getRange());
 	}
 
+	@Override
 	public String getRawText(final ContentRange range) {
 		Assert.isTrue(getRange().contains(range));
 
@@ -220,16 +230,19 @@
 		stringBuilder.append(content, range.getStartOffset(), range.length());
 	}
 
+	@Override
 	public void insertContent(final int offset, final IContent content) {
 		assertOffset(offset, 0, length());
 
 		copyContent(content, this, content.getRange(), offset);
 	}
 
+	@Override
 	public IContent getContent() {
 		return getContent(getRange());
 	}
 
+	@Override
 	public IContent getContent(final ContentRange range) {
 		Assert.isTrue(getRange().contains(range));
 
@@ -254,10 +267,12 @@
 	 * @see CharSequence#length()
 	 * @return the length of the raw textual content, including tag markers.
 	 */
+	@Override
 	public int length() {
 		return content.length - (gapEnd - gapStart);
 	}
 
+	@Override
 	public ContentRange getRange() {
 		return new ContentRange(0, length() - 1);
 	}
@@ -268,6 +283,7 @@
 	 *            the offset of the character within the raw textual content
 	 * @return the character at the given offset (tag markers included)
 	 */
+	@Override
 	public char charAt(final int offset) {
 		if (offset < gapStart) {
 			return content[offset];
@@ -278,7 +294,7 @@
 
 	/**
 	 * Get the raw text of a region of this content. The plain text does also contain the tag markers in this content.
-	 * 
+	 *
 	 * @see CharSequence#subSequence(int, int)
 	 * @param startOffset
 	 *            Offset at which the substring begins.
@@ -286,6 +302,7 @@
 	 *            Offset at which the substring ends.
 	 * @return the text of the given region including tag markers
 	 */
+	@Override
 	public CharSequence subSequence(final int startOffset, final int endOffset) {
 		return getRawText(new ContentRange(startOffset, endOffset));
 	}
@@ -303,6 +320,7 @@
 			this.offset = offset;
 		}
 
+		@Override
 		public int getOffset() {
 			return offset;
 		}
@@ -319,6 +337,7 @@
 			useCount--;
 		}
 
+		@Override
 		public boolean isValid() {
 			return useCount > 0;
 		};
@@ -358,6 +377,7 @@
 			return Integer.toString(offset);
 		}
 
+		@Override
 		public int compareTo(final IPosition other) {
 			return offset - other.getOffset();
 		}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/IncludeNode.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/IncludeNode.java
new file mode 100644
index 0000000..0a139d2
--- /dev/null
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/IncludeNode.java
@@ -0,0 +1,153 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Carsten Hiesserich 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:
+ *     Carsten Hiesserich - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.vex.core.internal.dom;
+
+import org.eclipse.core.runtime.AssertionFailedException;
+import org.eclipse.vex.core.provisional.dom.ContentPosition;
+import org.eclipse.vex.core.provisional.dom.ContentRange;
+import org.eclipse.vex.core.provisional.dom.IContent;
+import org.eclipse.vex.core.provisional.dom.IIncludeNode;
+import org.eclipse.vex.core.provisional.dom.INode;
+import org.eclipse.vex.core.provisional.dom.INodeVisitor;
+import org.eclipse.vex.core.provisional.dom.INodeVisitorWithResult;
+
+/**
+ * The IncludeNode wraps an XML include element.
+ */
+public class IncludeNode extends Node implements IIncludeNode {
+
+	private Element reference;
+
+	/**
+	 * Create a new include node that wraps the given Element. The Include node bypasses the element hierarchy, so the
+	 * parent of the given Element has to be set when calling this constructor.
+	 *
+	 * @param element
+	 */
+	public IncludeNode(final Element element) {
+		setReference(element);
+	}
+
+	@Override
+	public boolean isKindOf(final INode node) {
+		return false;
+	}
+
+	@Override
+	public void accept(final INodeVisitor visitor) {
+		visitor.visit(this);
+	}
+
+	@Override
+	public <T> T accept(final INodeVisitorWithResult<T> visitor) {
+		return visitor.visit(this);
+	}
+
+	@Override
+	public boolean isAssociated() {
+		return reference != null && reference.isAssociated();
+	}
+
+	@Override
+	public void associate(final IContent content, final ContentRange range) {
+		reference.associate(content, range);
+	}
+
+	@Override
+	public void dissociate() {
+		if (isAssociated()) {
+			reference.dissociate();
+		}
+	}
+
+	@Override
+	public void setParent(final Parent parent) {
+		super.setParent(parent);
+		reference.setParent(parent);
+	}
+
+	@Override
+	public IContent getContent() {
+		return reference.getContent();
+	}
+
+	@Override
+	public ContentPosition getStartPosition() {
+		if (!isAssociated()) {
+			throw new AssertionFailedException("Node must be associated to a ContentRange to have a start position.");
+		}
+		return new ContentPosition(this, getStartOffset());
+		//return reference.getStartPosition();
+	}
+
+	@Override
+	public int getStartOffset() {
+		if (!isAssociated()) {
+			throw new AssertionFailedException("Node must be associated to a ContentRange to have a start offset.");
+		}
+		return reference.getStartOffset();
+	}
+
+	@Override
+	public ContentPosition getEndPosition() {
+		if (!isAssociated()) {
+			throw new AssertionFailedException("Node must be associated to a ContentRange to have a end position.");
+		}
+		return new ContentPosition(this, getEndOffset());
+		//return reference.getEndPosition();
+	}
+
+	@Override
+	public int getEndOffset() {
+		if (!isAssociated()) {
+			throw new AssertionFailedException("Node must be associated to a ContentRange to have an end offset.");
+		}
+		return reference.getEndOffset();
+	}
+
+	public void setReference(final Element element) {
+		reference = element;
+	}
+
+	@Override
+	public Element getReference() {
+		return reference;
+	}
+
+	@Override
+	public INode getResolved() {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public INode getFallback() {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public String toString() {
+
+		final StringBuffer sb = new StringBuffer();
+
+		sb.append("IncludeNode (");
+		if (reference == null) {
+			sb.append("<Reference element not set>");
+		} else {
+			sb.append("<Reference:");
+			sb.append(reference.toString());
+		}
+
+		return sb.toString();
+	}
+
+}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/MergeNodesWithTextIterator.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/MergeNodesWithTextIterator.java
index 8dca9bb..644c89e 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/MergeNodesWithTextIterator.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/MergeNodesWithTextIterator.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

@@ -91,6 +91,7 @@
 		return currentOffset;

 	}

 

+	@Override

 	public boolean hasNext() {

 		return hasMoreChildrenInRange() || hasMoreText();

 	}

@@ -103,6 +104,7 @@
 		return textCursor < nextTextGap.getStartOffset();

 	}

 

+	@Override

 	public INode next() {

 		if (!hasNext()) {

 			throw new NoSuchElementException();

@@ -138,6 +140,7 @@
 		return new Text(parent, content, new ContentRange(textStart, textEnd));

 	}

 

+	@Override

 	public void remove() {

 		throw new UnsupportedOperationException("Cannot remove node.");

 	}

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Namespace.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Namespace.java
index 7b56681..58c0274 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Namespace.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Namespace.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  * 		Carsten Hiesserich - Vex namespace URI

@@ -26,4 +26,6 @@
 

 	public static final String VEX_NAMESPACE_URI = "http://www.eclipse.org/vex";

 

+	public static final String XINCLUDE_NAMESPACE_URI = "http://www.w3.org/2001/XInclude";

+

 }

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Node.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Node.java
index 66a3355..84d26bc 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Node.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Node.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *     Florian Thienel - refactoring to full fledged DOM
@@ -19,6 +19,8 @@
 import org.eclipse.core.runtime.AssertionFailedException;
 import org.eclipse.core.runtime.QualifiedName;
 import org.eclipse.vex.core.provisional.dom.BaseNodeVisitor;
+import org.eclipse.vex.core.provisional.dom.ContentPosition;
+import org.eclipse.vex.core.provisional.dom.ContentPositionRange;
 import org.eclipse.vex.core.provisional.dom.ContentRange;
 import org.eclipse.vex.core.provisional.dom.IAxis;
 import org.eclipse.vex.core.provisional.dom.IContent;
@@ -41,6 +43,7 @@
 	private IPosition startPosition = IPosition.NULL;
 	private IPosition endPosition = IPosition.NULL;
 
+	@Override
 	public Parent getParent() {
 		return parent;
 	}
@@ -49,11 +52,13 @@
 		this.parent = parent;
 	}
 
+	@Override
 	public IAxis<IParent> ancestors() {
 		return new Axis<IParent>(this) {
 			@Override
 			protected Iterator<IParent> createRootIterator(final ContentRange contentRange, final boolean includeText) {
 				return NodesInContentRangeIterator.iterator(new Iterable<IParent>() {
+					@Override
 					public Iterator<IParent> iterator() {
 						return new AncestorsIterator(Node.this);
 					}
@@ -82,14 +87,17 @@
 		content = null;
 	}
 
+	@Override
 	public boolean isAssociated() {
 		return content != null;
 	}
 
+	@Override
 	public IContent getContent() {
 		return content;
 	}
 
+	@Override
 	public int getStartOffset() {
 		if (!isAssociated()) {
 			throw new AssertionFailedException("Node must be associated to a ContentRange to have a start offset.");
@@ -97,13 +105,31 @@
 		return startPosition.getOffset();
 	}
 
+	@Override
+	public ContentPosition getStartPosition() {
+		if (!isAssociated()) {
+			throw new AssertionFailedException("Node must be associated to a ContentRange to have a start position.");
+		}
+		return new ContentPosition(this, startPosition.getOffset());
+	}
+
+	@Override
 	public int getEndOffset() {
 		if (!isAssociated()) {
-			throw new AssertionFailedException("Node must be associated to a ContentRange to have a start offset.");
+			throw new AssertionFailedException("Node must be associated to a ContentRange to have a end offset.");
 		}
 		return endPosition.getOffset();
 	}
 
+	@Override
+	public ContentPosition getEndPosition() {
+		if (!isAssociated()) {
+			throw new AssertionFailedException("Node must be associated to a ContentRange to have a end position.");
+		}
+		return new ContentPosition(this, endPosition.getOffset());
+	}
+
+	@Override
 	public ContentRange getRange() {
 		if (!isAssociated()) {
 			return ContentRange.NULL;
@@ -111,6 +137,15 @@
 		return new ContentRange(getStartOffset(), getEndOffset());
 	}
 
+	@Override
+	public ContentPositionRange getPositionRange() {
+		if (!isAssociated()) {
+			throw new AssertionFailedException("Node must be associated to a ContentRange to have a ContentPositionRange.");
+		}
+		return new ContentPositionRange(getStartPosition(), getEndPosition());
+	}
+
+	@Override
 	public boolean isEmpty() {
 		if (!isAssociated()) {
 			return false;
@@ -118,6 +153,7 @@
 		return getEndOffset() - getStartOffset() == 1;
 	}
 
+	@Override
 	public boolean containsOffset(final int offset) {
 		if (!isAssociated()) {
 			return false;
@@ -125,6 +161,15 @@
 		return getRange().contains(offset);
 	}
 
+	@Override
+	public boolean containsPosition(final ContentPosition position) {
+		if (!isAssociated()) {
+			return false;
+		}
+		return getPositionRange().contains(position);
+	}
+
+	@Override
 	public boolean isInRange(final ContentRange range) {
 		if (!isAssociated()) {
 			return false;
@@ -132,10 +177,12 @@
 		return range.contains(getRange());
 	}
 
+	@Override
 	public String getText() {
 		return getText(getRange());
 	}
 
+	@Override
 	public String getText(final ContentRange range) {
 		if (!isAssociated()) {
 			throw new AssertionFailedException("Node must be associated to a Content region to have textual content.");
@@ -143,6 +190,7 @@
 		return content.getText(range.intersection(getRange()));
 	}
 
+	@Override
 	public Document getDocument() {
 		if (this instanceof Document) {
 			return (Document) this;
@@ -155,6 +203,7 @@
 		return null;
 	}
 
+	@Override
 	public String getBaseURI() {
 		if (getParent() != null) {
 			return getParent().getBaseURI();
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/NodesInContentRangeIterator.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/NodesInContentRangeIterator.java
index dc4d316..11f4487 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/NodesInContentRangeIterator.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/NodesInContentRangeIterator.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

@@ -29,6 +29,7 @@
 

 	private NodesInContentRangeIterator(final Iterable<? extends INode> nodes, final ContentRange contentRange) {

 		super(nodes.iterator(), new IFilter<INode>() {

+			@Override

 			public boolean matches(final INode node) {

 				return !node.isAssociated() || contentRange.contains(node.getRange());

 			}

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Parent.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Parent.java
index bb19d77..3c5918b 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Parent.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Parent.java
@@ -18,6 +18,7 @@
 

 import org.eclipse.core.runtime.Assert;

 import org.eclipse.core.runtime.AssertionFailedException;

+import org.eclipse.vex.core.provisional.dom.ContentPosition;

 import org.eclipse.vex.core.provisional.dom.ContentRange;

 import org.eclipse.vex.core.provisional.dom.IAxis;

 import org.eclipse.vex.core.provisional.dom.INode;

@@ -27,7 +28,7 @@
  * A Parent node is a Node which can contain other nodes as children. This class defines the tree-like structure of the

  * DOM. It handles the merging of the child nodes and the textual content of one node within the structure of the

  * document.

- * 

+ *

  * @author Florian Thienel

  */

 public abstract class Parent extends Node implements IParent {

@@ -37,7 +38,7 @@
 	/**

 	 * Append the given child node to the end of the list of children. The parent attribute of the child is set to this

 	 * node.

-	 * 

+	 *

 	 * @param child

 	 *            the new child node

 	 */

@@ -49,7 +50,7 @@
 	/**

 	 * Insert the given child node into the list of children at the given offset. The parent attribute of the child is

 	 * set to this node.

-	 * 

+	 *

 	 * @param offset

 	 *            the offset within the associated content at which the new child should be inserted

 	 * @param child

@@ -96,13 +97,19 @@
 		child.setParent(this);

 	}

 

+	@Override

+	public INode getChildAt(final ContentPosition position) {

+		return getChildAt(position.getOffset());

+	}

+

 	/**

 	 * Returns the child node which contains the given offset, or this node, if no child contains the offset.

-	 * 

+	 *

 	 * @param offset

 	 *            the offset

 	 * @return the node at the given offset

 	 */

+	@Override

 	public INode getChildAt(final int offset) {

 		if (!containsOffset(offset)) {

 			throw new AssertionFailedException(MessageFormat.format("Offset must be within {0}.", getRange()));

@@ -169,7 +176,7 @@
 	/**

 	 * Insert the given child into the list of children before the given node. The parent attribute of the child is set

 	 * to this node.

-	 * 

+	 *

 	 * @param beforeNode

 	 *            the node before which the new child should be inserted

 	 * @param child

@@ -183,7 +190,7 @@
 

 	/**

 	 * Remove the given child node from the list of children. The parent attribute of the child will be set to null.

-	 * 

+	 *

 	 * @param child

 	 *            the child node to remove

 	 */

@@ -196,6 +203,7 @@
 	 * @return the children axis of this parent.

 	 * @see IAxis

 	 */

+	@Override

 	public IAxis<INode> children() {

 		return new Axis<INode>(this) {

 			@Override

@@ -210,9 +218,10 @@
 

 	/**

 	 * Indicates whether this parent node has child nodes, including text nodes.

-	 * 

+	 *

 	 * @return true if this parent node has any child nodes

 	 */

+	@Override

 	public boolean hasChildren() {

 		return !children().isEmpty();

 	}

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/ProcessingInstruction.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/ProcessingInstruction.java
index 336cd2e..b4ebaf2 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/ProcessingInstruction.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/ProcessingInstruction.java
@@ -20,7 +20,7 @@
 
 /**
  * A representation of an XML processing insctruction in the DOM. PI's have textual content, a start and an end tag.
- * 
+ *
  * @author Carsten Hiesserich
  */
 public class ProcessingInstruction extends Node implements IProcessingInstruction {
@@ -29,7 +29,7 @@
 
 	/**
 	 * Create a new processing instruction.
-	 * 
+	 *
 	 * @param target
 	 *            The target for this processing instruction.
 	 * @throws DocumentValidationException
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Text.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Text.java
index 032e488..017f83e 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Text.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Text.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *     Florian Thienel - refactoring to full fledged DOM
@@ -23,7 +23,7 @@
 	/**
 	 * Create a new Text node for the given range in the given content. This constructor automatically associates the
 	 * Text node with the given content and sets its parent.
-	 * 
+	 *
 	 * @param parent
 	 *            The parent node containing the text
 	 * @param content
@@ -38,14 +38,17 @@
 		associate(content, range);
 	}
 
+	@Override
 	public void accept(final INodeVisitor visitor) {
 		visitor.visit(this);
 	}
 
+	@Override
 	public <T> T accept(final INodeVisitorWithResult<T> visitor) {
 		return visitor.visit(this);
 	}
 
+	@Override
 	public boolean isKindOf(final INode node) {
 		return false;
 	}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentBuilder.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentBuilder.java
index 5cb845f..4c10019 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentBuilder.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentBuilder.java
@@ -30,6 +30,8 @@
 import org.eclipse.vex.core.internal.dom.DocumentTextPosition;
 import org.eclipse.vex.core.internal.dom.Element;
 import org.eclipse.vex.core.internal.dom.GapContent;
+import org.eclipse.vex.core.internal.dom.IncludeNode;
+import org.eclipse.vex.core.internal.dom.Namespace;
 import org.eclipse.vex.core.internal.dom.Node;
 import org.eclipse.vex.core.internal.dom.ProcessingInstruction;
 import org.eclipse.vex.core.provisional.dom.BaseNodeVisitorWithResult;
@@ -53,7 +55,7 @@
 /**
  * A SAX handler that builds a Vex document. This builder collapses whitespace as it goes, according to the following
  * rules.
- * 
+ *
  * <ul>
  * <li>Elements with style white-space: pre are left alone.</li>
  * <li>Runs of whitespace are replaced with a single space.</li>
@@ -123,6 +125,7 @@
 
 	// ============================================= ContentHandler methods
 
+	@Override
 	public void characters(final char[] ch, final int start, final int length) throws SAXException {
 		appendPendingCharsFiltered(ch, start, length);
 	}
@@ -142,6 +145,7 @@
 		return Character.isISOControl(ch) && ch != '\n' && ch != '\r' && ch != '\t';
 	}
 
+	@Override
 	public void endDocument() {
 		if (rootElement == null) {
 			return;
@@ -160,6 +164,7 @@
 		}
 	}
 
+	@Override
 	public void endElement(final String namespaceURI, final String localName, final String qName) {
 		appendChars(true);
 
@@ -175,12 +180,15 @@
 		}
 	}
 
+	@Override
 	public void endPrefixMapping(final String prefix) {
 	}
 
+	@Override
 	public void ignorableWhitespace(final char[] ch, final int start, final int length) {
 	}
 
+	@Override
 	public void processingInstruction(final String target, final String data) {
 
 		final ProcessingInstruction pi = new ProcessingInstruction(target);
@@ -204,16 +212,20 @@
 		trimLeading = false; // Keep a leading whitespace after a processing instruction
 	}
 
+	@Override
 	public void setDocumentLocator(final Locator locator) {
 		this.locator = locator;
 	}
 
+	@Override
 	public void skippedEntity(final java.lang.String name) {
 	}
 
+	@Override
 	public void startDocument() {
 	}
 
+	@Override
 	public void startElement(final String namespaceURI, final String localName, final String qName, final Attributes attrs) throws SAXException {
 
 		final QualifiedName elementName;
@@ -230,7 +242,16 @@
 			element = new Element(elementName);
 
 			final Element parent = stack.getLast().element;
-			parent.addChild(element);
+
+			// We have to set the parent before accessing the CSS the first time to enable cascading.
+			element.setParent(parent);
+			if (isInclude(element)) {
+				// Wrap the xml element in an include node
+				final Node include = new IncludeNode(element);
+				parent.addChild(include);
+			} else {
+				parent.addChild(element);
+			}
 		}
 
 		if (nodeAtCaret == null && caretPosition != null) {
@@ -290,6 +311,7 @@
 		namespaceStack.clear();
 	}
 
+	@Override
 	public void startPrefixMapping(final String prefix, final String uri) {
 		checkPrefix(prefix);
 		if (isDefaultPrefix(prefix)) {
@@ -309,6 +331,7 @@
 
 	// ============================================== LexicalHandler methods
 
+	@Override
 	public void comment(final char[] ch, final int start, final int length) {
 		if (inDTD) {
 			return;
@@ -375,25 +398,31 @@
 		return stack.isEmpty() && rootElement != null;
 	}
 
+	@Override
 	public void endCDATA() {
 	}
 
+	@Override
 	public void endDTD() {
 		inDTD = false;
 	}
 
+	@Override
 	public void endEntity(final String name) {
 	}
 
+	@Override
 	public void startCDATA() {
 	}
 
+	@Override
 	public void startDTD(final String name, final String publicId, final String systemId) {
 		dtdPublicID = publicId;
 		dtdSystemID = systemId;
 		inDTD = true;
 	}
 
+	@Override
 	public void startEntity(final String name) {
 	}
 
@@ -454,6 +483,10 @@
 		return whitespacePolicy != null && whitespacePolicy.isPre(node);
 	}
 
+	private boolean isInclude(final Element element) {
+		return element.getQualifiedName().equals(new QualifiedName(Namespace.XINCLUDE_NAMESPACE_URI, "include"));
+	}
+
 	private boolean canInsertText(final INode insertionNode, final int offset) {
 
 		final List<QualifiedName> textNode = Arrays.asList(IValidator.PCDATA);
@@ -494,7 +527,7 @@
 	/**
 	 * Set the stored caret position. While parsing the document, the node at this position will be stored and returned
 	 * with {@link #getNodeAtCaret}.
-	 * 
+	 *
 	 * @param position
 	 */
 	public void setCaretPosition(final DocumentTextPosition position) {
@@ -502,9 +535,9 @@
 	}
 
 	/**
-	 * 
+	 *
 	 * @return The node at the given caret position.
-	 * 
+	 *
 	 * @see #setCaretPosition(DocumentTextPosition)
 	 */
 	public INode getNodeAtCaret() {
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentReader.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentReader.java
index 63240f1..6ad6246 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentReader.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentReader.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *     Carsten Hiesserich - added caret position tracking
@@ -58,6 +58,7 @@
 	private INode nodeAtCaret;
 
 	private final EntityResolver combinedEntityResolver = new EntityResolver() {
+		@Override
 		public InputSource resolveEntity(final String publicId, final String systemId) throws SAXException, IOException {
 			final InputSource result;
 			if (entityResolver != null) {
@@ -81,7 +82,7 @@
 
 	/**
 	 * Reads a document given a URL.
-	 * 
+	 *
 	 * @param url
 	 *            URL from which to load the document.
 	 */
@@ -91,7 +92,7 @@
 
 	/**
 	 * Reads a document from a string. This is mainly used for short documents in unit tests.
-	 * 
+	 *
 	 * @param s
 	 *            String containing the document to be read.
 	 */
@@ -102,7 +103,7 @@
 
 	/**
 	 * Reads a document given a SAX InputSource.
-	 * 
+	 *
 	 * @param is
 	 *            SAX InputSource from which to load the document.
 	 */
@@ -120,6 +121,7 @@
 
 		if (isDebugging()) {
 			final Object proxy = Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[] { ContentHandler.class, LexicalHandler.class }, new InvocationHandler() {
+				@Override
 				public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
 					try {
 						return method.invoke(builder, args);
@@ -151,7 +153,7 @@
 
 	/**
 	 * Sets the debugging flag.
-	 * 
+	 *
 	 * @param debugging
 	 *            true if the component should log debugging info to stdout.
 	 */
@@ -161,7 +163,7 @@
 
 	/**
 	 * Sets the entity resolver for this reader.
-	 * 
+	 *
 	 * @param entityResolver
 	 *            The entityResolver to set.
 	 */
@@ -199,7 +201,7 @@
 	/**
 	 * Set the stored caret position. While parsing the document, the node at this position will be stored and returned
 	 * with {@link #getNodeAtCaret}.
-	 * 
+	 *
 	 * @param position
 	 */
 	public void setCaretPosition(final DocumentTextPosition position) {
@@ -207,9 +209,9 @@
 	}
 
 	/**
-	 * 
+	 *
 	 * @return The node at the given caret position.
-	 * 
+	 *
 	 * @see #setCaretPosition(DocumentTextPosition)
 	 */
 	public INode getNodeAtCaret() {
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentWriter.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentWriter.java
index c5214e0..0c1a3f6 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentWriter.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentWriter.java
@@ -30,6 +30,7 @@
 import org.eclipse.vex.core.provisional.dom.IDocument;
 import org.eclipse.vex.core.provisional.dom.IDocumentFragment;
 import org.eclipse.vex.core.provisional.dom.IElement;
+import org.eclipse.vex.core.provisional.dom.IIncludeNode;
 import org.eclipse.vex.core.provisional.dom.INode;
 import org.eclipse.vex.core.provisional.dom.IProcessingInstruction;
 import org.eclipse.vex.core.provisional.dom.IText;
@@ -37,13 +38,13 @@
 
 /**
  * Writes a document to an output stream, using a stylesheet to provide formatting hints.
- * 
+ *
  * <ul>
  * <li>Children of an element are indented by a configurable amount.</li>
  * <li>Text is wrapped to fit within a configurable width.
  * <li>
  * </ul>
- * 
+ *
  * <p>
  * Documents are currently saved UTF-8 encoding, with no encoding specified in the XML declaration.
  * </p>
@@ -67,13 +68,13 @@
 		whitespacePolicy = IWhitespacePolicy.NULL;
 	}
 
-/**
-     * Escapes special XML characters. Changes '<', '>', and '&' to
-     * '&lt;', '&gt;' and '&amp;', respectively.
-     *
-     * @param s the string to be escaped.
-     * @return the escaped string
-     */
+	/**
+	 * Escapes special XML characters. Changes '<', '>', and '&' to
+	 * '&lt;', '&gt;' and '&amp;', respectively.
+	 *
+	 * @param s the string to be escaped.
+	 * @return the escaped string
+	 */
 	public static String escape(final String s) {
 		final StringBuilder result = new StringBuilder(s.length());
 
@@ -105,7 +106,7 @@
 
 	/**
 	 * Sets the value of the indent string.
-	 * 
+	 *
 	 * @param indent
 	 *            new value for the indent string.
 	 */
@@ -123,7 +124,7 @@
 	/**
 	 * Sets the whitespace policy for this writer. The whitespace policy tells the writer which elements are
 	 * block-formatted and which are pre-formatted.
-	 * 
+	 *
 	 * @param whitespacePolicy
 	 *            The whitespacePolicy to set.
 	 */
@@ -144,7 +145,7 @@
 
 	/**
 	 * Sets the value of the wrap column.
-	 * 
+	 *
 	 * @param wrapColumn
 	 *            new value for the wrap column.
 	 */
@@ -182,7 +183,7 @@
 	 * Write the document to the given {@link org.eclipse.jface.text.IDocument}. The document is cleaed before the
 	 * content written.<br />
 	 * While writing the document a Position is created to track the caret when external changes occur.
-	 * 
+	 *
 	 * @param document
 	 * @param doc
 	 * @param nodeAtCaret
@@ -331,6 +332,12 @@
 			}
 
 			@Override
+			public void visit(final IIncludeNode include) {
+				// Write the element that defines this include
+				visit(include.getReference());
+			}
+
+			@Override
 			public void visit(final IText text) {
 				final TextWrapper wrapper = new TextWrapper();
 				wrapper.add(escape(node.getText()));
@@ -382,6 +389,12 @@
 			}
 
 			@Override
+			public void visit(final IIncludeNode include) {
+				// Write the element that defines this include
+				visit(include.getReference());
+			}
+
+			@Override
 			public void visit(final IText text) {
 				docPrint(doc, escape(node.getText()));
 			}
@@ -444,6 +457,12 @@
 			}
 
 			@Override
+			public void visit(final IIncludeNode include) {
+				// Write the element that defines this include
+				visit(include.getReference());
+			}
+
+			@Override
 			public void visit(final IText text) {
 				wrapper.add(escape(node.getText()));
 			}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/NamespaceStack.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/NamespaceStack.java
index e448cbe..da68230 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/NamespaceStack.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/NamespaceStack.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/TextWrapper.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/TextWrapper.java
index d1b1c5a..fbbff22 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/TextWrapper.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/TextWrapper.java
@@ -1,14 +1,15 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2008 John Krasnay and others.
+ * Copyright (c) 2004, 2014 John Krasnay 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:
  *     John Krasnay - initial API and implementation
  *     David Carver unit tests fixes
  *     Igor Jacy Lino Campista - Java 5 warnings fixed (bug 311325)
+ *     Carsten Hiesserich - fix wrapping in addNoSplit
  *******************************************************************************/
 package org.eclipse.vex.core.internal.io;
 
@@ -32,7 +33,7 @@
 
 	/**
 	 * Adds text to the list of things to be wrapped.
-	 * 
+	 *
 	 * @param s
 	 *            Text to be added.
 	 */
@@ -68,12 +69,24 @@
 	/**
 	 * Adds text to the list of things to be wrapped. The given text will be treated as a single unit and will not be
 	 * split across lines.
-	 * 
+	 *
 	 * @param s
 	 *            Text to be added.
 	 */
 	public void addNoSplit(final String s) {
-		parts.add(s);
+
+		if (s.length() == 0) {
+			return;
+		}
+
+		if (lastIsWhite || parts.isEmpty()) {
+			parts.add(s);
+		} else {
+			// Last char is not a whitespace - we must not split here
+			parts.add(parts.remove(parts.size() - 1) + s);
+		}
+
+		lastIsWhite = Character.isWhitespace(s.charAt(s.length() - 1));
 	}
 
 	/**
@@ -86,7 +99,7 @@
 	/**
 	 * Wraps the text into the given width. The text is only broken at spaces, meaning the returned lines will not
 	 * necessarily fit within width.
-	 * 
+	 *
 	 * @param width
 	 */
 	public String[] wrap(final int width) {
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/XMLFragment.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/XMLFragment.java
index 79b77b9..9dc201b 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/XMLFragment.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/XMLFragment.java
@@ -4,7 +4,7 @@
  * 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:
  *     Carsten Hiesserich - initial API and implementation
  *******************************************************************************/
@@ -114,6 +114,7 @@
 			final DocumentReader reader = new DocumentReader();
 
 			reader.setWhitespacePolicyFactory(new IWhitespacePolicyFactory() {
+				@Override
 				public IWhitespacePolicy createPolicy(final IValidator validator, final DocumentContentModel documentContentModel, final StyleSheet styleSheet) {
 					return whitespacePolicy;
 				}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/AbstractBlockBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/AbstractBlockBox.java
index b896ddb..4615fca 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/AbstractBlockBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/AbstractBlockBox.java
@@ -24,8 +24,8 @@
 import org.eclipse.vex.core.internal.core.Insets;
 import org.eclipse.vex.core.internal.css.StyleSheet;
 import org.eclipse.vex.core.internal.css.Styles;
-import org.eclipse.vex.core.internal.widget.IBoxFilter;
 import org.eclipse.vex.core.provisional.dom.BaseNodeVisitorWithResult;
+import org.eclipse.vex.core.provisional.dom.ContentPosition;
 import org.eclipse.vex.core.provisional.dom.ContentRange;
 import org.eclipse.vex.core.provisional.dom.IComment;
 import org.eclipse.vex.core.provisional.dom.IDocument;
@@ -38,10 +38,10 @@
 /**
  * Base class of block boxes that can contain other block boxes. This class implements the layout method and various
  * navigation methods. Subclasses must implement the createChildren method.
- * 
+ *
  * Subclasses can be anonymous or non-anonymous (i.e. generated by an element). Since the vast majority of instances
  * will be non-anonymous, this class can manage the element and top and bottom margins without too much inefficiency.
- * 
+ *
  * <p>
  * Subclasses that can be anonymous must override the getStartPosition and getEndPosition classes to return the range
  * covered by the box.
@@ -75,7 +75,7 @@
 
 	/**
 	 * Class constructor for non-anonymous boxes.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext being used.
 	 * @param parent
@@ -96,7 +96,7 @@
 
 	/**
 	 * Class constructor for anonymous boxes.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext to use.
 	 * @param parent
@@ -121,11 +121,9 @@
 	 * Walks the box tree and returns the nearest enclosing element.
 	 */
 	protected IParent findContainingParent() {
-		BlockBox box = this;
-		INode node = box.getNode();
+		INode node = getNode();
 		while (!(node instanceof IParent)) {
-			box = box.getParent();
-			node = box.getNode();
+			node = node.getParent();
 		}
 		return (IParent) node;
 	}
@@ -138,48 +136,73 @@
 	}
 
 	@Override
-	public Caret getCaret(final LayoutContext context, final int offset) {
-
-		// If we haven't yet laid out this block, estimate the caret.
+	public Caret getCaret(final LayoutContext context, final ContentPosition position) {
 		if (getLayoutState() != LAYOUT_OK) {
-			final int relative = offset - getStartOffset();
-			final int size = getEndOffset() - getStartOffset();
-			int y = 0;
-			if (size > 0) {
-				y = getHeight() * relative / size;
-			}
-			return new HCaret(0, y, getHCaretWidth());
+			return newHCaret(estimateCaretPosition(position));
 		}
 
-		int y;
-
-		final Box[] children = getContentChildren();
-		for (int i = 0; i < children.length; i++) {
-
-			if (offset < children[i].getStartOffset()) {
-				if (i > 0) {
-					y = (children[i - 1].getY() + children[i - 1].getHeight() + children[i].getY()) / 2;
-				} else {
-					y = 0;
-				}
-				return new HCaret(0, y, getHCaretWidth());
+		Box lastBox = null;
+		for (final Box box : getChildrenWithContent()) {
+			if (isPositionBefore(position, box)) {
+				return newHCaret(caretPositionBetween(lastBox, box));
 			}
 
-			if (offset >= children[i].getStartOffset() && offset <= children[i].getEndOffset()) {
-
-				final Caret caret = children[i].getCaret(context, offset);
-				caret.translate(children[i].getX(), children[i].getY());
-				return caret;
+			if (isPositionWithin(position, box)) {
+				return getChildCaret(context, position, box);
 			}
+
+			lastBox = box;
 		}
 
+		return newHCaret(caretPositionAtEnd());
+	}
+
+	private HCaret newHCaret(final int y) {
+		return new HCaret(0, y, getHCaretWidth());
+	}
+
+	private int estimateCaretPosition(final ContentPosition position) {
+		final int relativeOffset = position.getOffset() - getStartOffset();
+		final int charCount = getCharCount();
+		if (charCount > 0) {
+			return getHeight() * relativeOffset / charCount;
+		}
+		return 0;
+	}
+
+	private static int caretPositionBetween(final Box box1, final Box box2) {
+		if (box1 == null || box2 == null) {
+			return 0;
+		}
+		return (box1.getY() + box1.getHeight() + box2.getY()) / 2;
+	}
+
+	private static Caret getChildCaret(final LayoutContext context, final ContentPosition position, final Box box) {
+		final Caret caret = box.getCaret(context, position);
+		caret.translate(box.getX(), box.getY());
+		return caret;
+	}
+
+	private int caretPositionAtEnd() {
+		final int y;
 		if (hasChildren()) {
 			y = getHeight();
 		} else {
 			y = getHeight() / 2;
 		}
+		return y;
+	}
 
-		return new HCaret(0, y, getHCaretWidth());
+	private static boolean isPositionBefore(final ContentPosition position, final Box box) {
+		return position.getOffset() < box.getStartOffset();
+	}
+
+	private static boolean isPositionWithin(final ContentPosition position, final Box box) {
+		return position.getOffset() >= box.getStartOffset() && position.getOffset() <= box.getEndOffset();
+	}
+
+	private int getCharCount() {
+		return getEndOffset() - getStartOffset();
 	}
 
 	@Override
@@ -187,10 +210,7 @@
 		return children;
 	}
 
-	/**
-	 * Return an array of children that contain content.
-	 */
-	protected BlockBox[] getContentChildren() {
+	protected BlockBox[] getChildrenWithContent() {
 		final Box[] children = getChildren();
 		final List<BlockBox> result = new ArrayList<BlockBox>(children.length);
 		for (final Box child : children) {
@@ -203,14 +223,17 @@
 
 	@Override
 	public INode getNode() {
+		if (isAnonymous()) {
+			return parent.getNode();
+		}
+
 		return node;
 	}
 
 	@Override
 	public int getEndOffset() {
-		final INode element = getNode();
-		if (element != null) {
-			return element.getEndOffset();
+		if (!isAnonymous()) {
+			return getNode().getEndOffset();
 		} else if (getEndPosition() != null) {
 			return getEndPosition().getOffset();
 		} else {
@@ -222,7 +245,7 @@
 	 * Returns the estimated size of the box, based on the the current font size and the number of characters covered by
 	 * the box. This is a utility method that can be used in implementation of setInitialSize. It assumes the width of
 	 * the box has already been correctly set.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext to use.
 	 */
@@ -230,7 +253,7 @@
 
 		final INode node = findContainingParent();
 		final Styles styles = context.getStyleSheet().getStyles(node);
-		final int charCount = getEndOffset() - getStartOffset();
+		final int charCount = getCharCount();
 
 		final float fontSize = styles.getFontSize();
 		final float lineHeight = styles.getLineHeight();
@@ -239,6 +262,7 @@
 		return Math.round(Math.max(estHeight, lineHeight));
 	}
 
+	@Override
 	public LineBox getFirstLine() {
 		if (hasChildren()) {
 			final BlockBox firstChild = (BlockBox) getChildren()[0];
@@ -276,6 +300,7 @@
 		}
 	}
 
+	@Override
 	public LineBox getLastLine() {
 		if (hasChildren()) {
 			final BlockBox lastChild = (BlockBox) getChildren()[getChildren().length - 1];
@@ -292,107 +317,117 @@
 		return layoutState;
 	}
 
-	public int getLineEndOffset(final int offset) {
-		final BlockBox[] children = getContentChildren();
+	@Override
+	public ContentPosition getLineEndPosition(final ContentPosition linePosition) {
+		final BlockBox[] children = getChildrenWithContent();
 		for (final BlockBox element2 : children) {
-			if (element2.containsOffset(offset)) {
-				return element2.getLineEndOffset(offset);
+			if (element2.containsPosition(linePosition)) {
+				return element2.getLineEndPosition(linePosition);
 			}
 		}
-		return offset;
+		return linePosition;
 	}
 
-	public int getLineStartOffset(final int offset) {
-		final BlockBox[] children = getContentChildren();
+	@Override
+	public ContentPosition getLineStartPosition(final ContentPosition linePosition) {
+		final BlockBox[] children = getChildrenWithContent();
 		for (final BlockBox element2 : children) {
-			if (element2.containsOffset(offset)) {
-				return element2.getLineStartOffset(offset);
+			if (element2.containsPosition(linePosition)) {
+				return element2.getLineStartPosition(linePosition);
 			}
 		}
-		return offset;
+		return linePosition;
 	}
 
+	@Override
 	public int getMarginBottom() {
 		return marginBottom;
 	}
 
+	@Override
 	public int getMarginTop() {
 		return marginTop;
 	}
 
-	public int getNextLineOffset(final LayoutContext context, final int offset, final int x) {
+	@Override
+	public ContentPosition getNextLinePosition(final LayoutContext context, final ContentPosition linePosition, final int x) {
 
 		//
 		// This algorithm works when this block owns the offsets between
 		// its children.
 		//
 
-		if (offset == getEndOffset()) {
-			return -1;
+		if (linePosition.getOffset() == getEndOffset()) {
+			// We are at the end of this box - no line here
+			return null;
 		}
 
-		final BlockBox[] children = getContentChildren();
+		final BlockBox[] children = getChildrenWithContent();
 
-		if (offset < getStartOffset() && children.length > 0 && children[0].getStartOffset() > getStartOffset()) {
-			//
+		if (linePosition.getOffset() < getStartOffset() && children.length > 0 && children[0].getStartOffset() > getStartOffset()) {
 			// If there's an offset before the first child, put the caret there.
-			//
-			return getStartOffset();
+			return getNode().getStartPosition().moveBy(1);
 		}
 
 		for (final BlockBox child : children) {
-			if (offset <= child.getEndOffset()) {
-				final int newOffset = child.getNextLineOffset(context, offset, x - child.getX());
-				if (newOffset < 0 /* && i < children.length-1 */) {
-					return child.getEndOffset() + 1;
+			if (linePosition.getOffset() <= child.getEndOffset()) {
+				final ContentPosition newPosition = child.getNextLinePosition(context, linePosition, x - child.getX());
+				if (newPosition == null) {
+					// No next line in child box
+					// Return the start position of the next node
+					return child.getNode().getEndPosition().moveBy(1);
 				} else {
-					return newOffset;
+					return newPosition;
 				}
 			}
 		}
 
-		return getEndOffset();
+		return new ContentPosition(getNode(), getEndOffset());
 	}
 
+	@Override
 	public BlockBox getParent() {
 		return parent;
 	}
 
-	public int getPreviousLineOffset(final LayoutContext context, final int offset, final int x) {
+	@Override
+	public ContentPosition getPreviousLinePosition(final LayoutContext context, final ContentPosition linePosition, final int x) {
 
-		if (offset == getStartOffset()) {
-			return -1;
+		if (linePosition.getOffset() == getStartOffset()) {
+			// We are at the start of this box - no previous line here
+			return null;
 		}
 
-		final BlockBox[] children = getContentChildren();
+		final BlockBox[] children = getChildrenWithContent();
 
-		if (offset > getEndOffset() && children.length > 0 && children[children.length - 1].getEndOffset() < getEndOffset()) {
-			//
+		if (linePosition.getOffset() > getEndOffset() && children.length > 0 && children[children.length - 1].getEndOffset() < getEndOffset()) {
 			// If there's an offset after the last child, put the caret there.
-			//
-			return getEndOffset();
+			// This may be an anonymous box without an associated node - Find a parent with an associated node
+			return getNode().getEndPosition();
 		}
 
 		for (int i = children.length; i > 0; i--) {
 			final BlockBox child = children[i - 1];
-			if (offset >= child.getStartOffset()) {
-				final int newOffset = child.getPreviousLineOffset(context, offset, x - child.getX());
-				if (newOffset < 0 && i > 0) {
-					return child.getStartOffset() - 1;
+			if (linePosition.getOffset() >= child.getStartOffset()) {
+				final ContentPosition newPosition = child.getPreviousLinePosition(context, linePosition, x - child.getX());
+				if (newPosition == null && i > 0) {
+					// No previous line in child box
+					// Return the child's start position. Insertions at this position will insert before the node.
+					return child.getNode().getStartPosition();
 				} else {
-					return newOffset;
+					return newPosition;
 				}
 			}
 		}
 
-		return getStartOffset();
+		// No child returned a position, so place the caret before any child
+		return new ContentPosition(getNode(), getStartOffset());
 	}
 
 	@Override
 	public int getStartOffset() {
-		final INode node = getNode();
-		if (node != null) {
-			return node.getStartOffset() + 1;
+		if (!isAnonymous()) {
+			return getNode().getStartOffset() + 1;
 		} else if (getStartPosition() != null) {
 			return getStartPosition().getOffset();
 		} else {
@@ -408,15 +443,12 @@
 		return getNode().isAssociated();
 	}
 
+	@Override
 	public void invalidate(final boolean direct) {
 
 		if (direct) {
 			layoutState = LAYOUT_REDO;
-			if (getParent() instanceof AbstractBlockBox) {
-				// The parent box may contain text elements after the edited offset, that has to be updated
-				((AbstractBlockBox) getParent()).invalidateChildrenAfterOffset(getStartOffset());
-			}
-		} else if (layoutState != LAYOUT_REDO) {
+		} else {
 			layoutState = LAYOUT_PROPAGATE;
 		}
 
@@ -425,38 +457,16 @@
 		}
 	}
 
-	/**
-	 * Checks if there are any children with content after an invalidated element. If so, the box has to update those
-	 * children.
-	 * 
-	 * @param offset
-	 *            The offset of the edited element
-	 */
-	protected void invalidateChildrenAfterOffset(final int offset) {
-		final IBoxFilter filter = new IBoxFilter() {
-			public boolean matches(final Box box) {
-				return box.hasContent() && box.getStartOffset() > offset;
-			}
-		};
-
-		for (final Box child : getChildren()) {
-			if (filter.matches(child)) {
-				layoutState = LAYOUT_REDO;
-				break;
-			}
-		}
-	}
-
 	@Override
 	public boolean isAnonymous() {
-		return getNode() == null;
+		return node == null;
 	}
 
 	/**
 	 * Call the given callback for each child matching one of the given display styles. Any nodes that do not match one
 	 * of the given display types cause the onRange callback to be called, with a range covering all such contiguous
 	 * nodes.
-	 * 
+	 *
 	 * @param styleSheet
 	 *            StyleSheet from which to determine display styles.
 	 * @param displayStyles
@@ -489,6 +499,7 @@
 	 * Default implementation. Width is calculated as the parent's width minus this box's insets. Height is calculated
 	 * by getEstimatedHeight.
 	 */
+	@Override
 	public void setInitialSize(final LayoutContext context) {
 		final int parentWidth = getParent().getWidth();
 		final Insets insets = this.getInsets(context, parentWidth);
@@ -497,16 +508,16 @@
 	}
 
 	@Override
-	public int viewToModel(final LayoutContext context, final int x, final int y) {
+	public ContentPosition viewToModel(final LayoutContext context, final int x, final int y) {
 		final Box[] children = getChildren();
 
 		if (children == null) {
-			final int charCount = getEndOffset() - getStartOffset() - 1;
+			final int charCount = getCharCount() - 1;
 			if (charCount == 0 || getHeight() == 0) {
-				return getEndOffset();
+				return getNode().getEndPosition();
 			}
 
-			return getStartOffset() + charCount * y / getHeight();
+			return new ContentPosition(getNode(), getStartOffset() + charCount * y / getHeight());
 		}
 
 		for (final Box child : children) {
@@ -515,7 +526,7 @@
 			}
 
 			if (y < child.getY()) {
-				return child.getStartOffset() - 1;
+				return child.getNode().getStartPosition().moveBy(-1);
 			}
 
 			if (y < child.getY() + child.getHeight()) {
@@ -524,7 +535,7 @@
 
 		}
 
-		return getEndOffset();
+		return getNode().getEndPosition().copy();
 	}
 
 	// ===================================================== PRIVATE
@@ -534,7 +545,7 @@
 
 	/**
 	 * Paint a frame that indicates a block element box has been selected.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext to use.
 	 * @param x
@@ -617,6 +628,7 @@
 
 	private byte layoutState = LAYOUT_REDO;
 
+	@Override
 	public VerticalRange layout(final LayoutContext context, final int top, final int bottom) {
 
 		VerticalRange repaintRange = null;
@@ -625,9 +637,6 @@
 
 		if (layoutState == LAYOUT_REDO) {
 
-			// System.out.println("Redo layout of " +
-			// this.getElement().getName());
-
 			final List<Box> childList = createChildren(context);
 			children = childList.toArray(new BlockBox[childList.size()]);
 
@@ -829,7 +838,7 @@
 
 	/**
 	 * Sets the layout state of the box.
-	 * 
+	 *
 	 * @param layoutState
 	 *            One of the LAYOUT_* constants
 	 */
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/AbstractBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/AbstractBox.java
index f854bcd..9b3833a 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/AbstractBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/AbstractBox.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -19,6 +19,7 @@
 import org.eclipse.vex.core.internal.core.Rectangle;
 import org.eclipse.vex.core.internal.css.CSS;
 import org.eclipse.vex.core.internal.css.Styles;
+import org.eclipse.vex.core.provisional.dom.ContentPosition;
 import org.eclipse.vex.core.provisional.dom.INode;
 
 /**
@@ -41,63 +42,75 @@
 
 	/**
 	 * Returns true if the given offset is between startOffset and endOffset, inclusive.
-	 * 
+	 *
 	 * @see org.eclipse.vex.core.internal.layout.Box#containsOffset(int)
 	 */
+	@Override
 	public boolean containsOffset(final int offset) {
 		return offset >= getStartOffset() && offset <= getEndOffset();
 	}
 
+	@Override
+	public boolean containsPosition(final ContentPosition position) {
+		return containsOffset(position.getOffset());
+	}
+
 	/**
 	 * Throws <code>IllegalStateException</code>. Boxes with content must provide an implementation of this method.
-	 * 
+	 *
 	 * @see org.eclipse.vex.core.internal.layout.Box#getCaret(org.eclipse.vex.core.internal.layout.LayoutContext, int)
 	 */
-	public Caret getCaret(final LayoutContext context, final int offset) {
+	@Override
+	public Caret getCaret(final LayoutContext context, final ContentPosition position) {
 		throw new IllegalStateException();
 	}
 
 	/**
 	 * Returns an empty array of children.
-	 * 
+	 *
 	 * @see org.eclipse.vex.core.internal.layout.Box#getChildren()
 	 */
+	@Override
 	public Box[] getChildren() {
 		return EMPTY_BOX_ARRAY;
 	}
 
 	/**
 	 * Returns null. Boxes associated with elements must provide an implementation of this method.
-	 * 
+	 *
 	 * @see org.eclipse.vex.core.internal.layout.Box#getNode()
 	 */
+	@Override
 	public INode getNode() {
 		return null;
 	}
 
 	/**
 	 * Throws <code>IllegalStateException</code>. Boxes with content must provide an implementation of this method.
-	 * 
+	 *
 	 * @see org.eclipse.vex.core.internal.layout.Box#getEndOffset()
 	 */
+	@Override
 	public int getEndOffset() {
 		throw new IllegalStateException();
 	}
 
 	/**
 	 * Returns the height set with <code>setHeight</code>.
-	 * 
+	 *
 	 * @see org.eclipse.vex.core.internal.layout.Box#getHeight()
 	 */
+	@Override
 	public int getHeight() {
 		return height;
 	}
 
 	/**
 	 * Throws <code>IllegalStateException</code>. Boxes with content must provide an implementation of this method.
-	 * 
+	 *
 	 * @see org.eclipse.vex.core.internal.layout.Box#getStartOffset()
 	 */
+	@Override
 	public int getStartOffset() {
 		throw new IllegalStateException();
 	}
@@ -106,41 +119,45 @@
 	 * Returns the insets of this box, which is the sum of the margin, border, and padding on each side. If no element
 	 * is associated with this box returns all zeros.
 	 */
+	@Override
 	public Insets getInsets(final LayoutContext context, final int containerWidth) {
-		final INode node = getNode();
-		if (node == null) {
+		if (isAnonymous()) {
 			return Insets.ZERO_INSETS;
 		} else {
-			return getInsets(context.getStyleSheet().getStyles(node), containerWidth);
+
+			return getInsets(context.getStyleSheet().getStyles(getNode()), containerWidth);
 		}
 	}
 
 	/**
 	 * Returns false. Boxes with content must override this method and return true, and must provide implementations for
 	 * the following methods.
-	 * 
+	 *
 	 * <ul>
 	 * <li>{@link Box#getCaretShapes}</li>
 	 * <li>{@link Box#getStartOffset}</li>
 	 * <li>{@link Box#getEndOffset}</li>
 	 * <li>{@link Box#viewToModel}</li>
 	 * </ul>
-	 * 
+	 *
 	 * @see org.eclipse.vex.core.internal.layout.Box#hasContent()
 	 */
+	@Override
 	public boolean hasContent() {
 		return false;
 	}
 
+	@Override
 	public boolean isAnonymous() {
 		return true;
 	}
 
 	/**
 	 * Returns the width set with <code>setWidth</code>.
-	 * 
+	 *
 	 * @see org.eclipse.vex.core.internal.layout.Box#getWidth()
 	 */
+	@Override
 	public int getWidth() {
 		Assert.isTrue(width > -1); // Make sure width has been calculated
 		return width;
@@ -148,27 +165,30 @@
 
 	/**
 	 * Returns the value set with <code>setX</code>.
-	 * 
+	 *
 	 * @see org.eclipse.vex.core.internal.layout.Box#getX()
 	 */
+	@Override
 	public int getX() {
 		return x;
 	}
 
 	/**
 	 * Returns the value set with <code>setY</code>.
-	 * 
+	 *
 	 * @see org.eclipse.vex.core.internal.layout.Box#getY()
 	 */
+	@Override
 	public int getY() {
 		return y;
 	}
 
 	/**
 	 * Paint all children of this box.
-	 * 
+	 *
 	 * @see org.eclipse.vex.core.internal.layout.Box#paint(org.eclipse.vex.core.internal.layout.LayoutContext, int, int)
 	 */
+	@Override
 	public void paint(final LayoutContext context, final int x, final int y) {
 		if (skipPaint(context, x, y)) {
 			return;
@@ -179,7 +199,7 @@
 
 	/**
 	 * Paint the children of this box.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext to use.
 	 * @param x
@@ -195,18 +215,22 @@
 		}
 	}
 
+	@Override
 	public void setHeight(final int height) {
 		this.height = height;
 	}
 
+	@Override
 	public void setWidth(final int width) {
 		this.width = width;
 	}
 
+	@Override
 	public void setX(final int x) {
 		this.x = x;
 	}
 
+	@Override
 	public void setY(final int y) {
 		this.y = y;
 	}
@@ -214,7 +238,7 @@
 	/**
 	 * Returns true if this box is outside the clip region. Implementations of <code>paint</code> should use this to
 	 * avoid unnecessary painting.
-	 * 
+	 *
 	 * @param context
 	 *            <code>LayoutContext</code> in effect.
 	 * @param x
@@ -231,17 +255,18 @@
 
 	/**
 	 * Throws <code>IllegalStateException</code>. Boxes with content must provide an implementation of this method.
-	 * 
+	 *
 	 * @see org.eclipse.vex.core.internal.layout.Box#viewToModel(org.eclipse.vex.core.internal.layout.LayoutContext,
 	 *      int, int)
 	 */
-	public int viewToModel(final LayoutContext context, final int x, final int y) {
+	@Override
+	public ContentPosition viewToModel(final LayoutContext context, final int x, final int y) {
 		throw new IllegalStateException();
 	}
 
 	/**
 	 * Draws the background and borders of a CSS-styled box.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext used for drawing.
 	 * @param x
@@ -260,7 +285,7 @@
 
 	/**
 	 * Draws the background and borders of a CSS-styled box.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext used for drawing.
 	 * @param node
@@ -278,7 +303,7 @@
 	 */
 	protected void drawBox(final LayoutContext context, final INode node, final int x, final int y, final int containerWidth, final boolean drawBorders) {
 
-		if (node == null) {
+		if (isAnonymous()) {
 			return;
 		}
 
@@ -400,7 +425,7 @@
 
 	/**
 	 * Returns the insets for a CSS box with the given styles.
-	 * 
+	 *
 	 * @param styles
 	 *            Styles for the box.
 	 * @param containerWidth
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/AbstractInlineBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/AbstractInlineBox.java
index 0265f9d..67698ea 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/AbstractInlineBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/AbstractInlineBox.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  * 		Carsten Hiesserich - added isSplitable() method

@@ -16,14 +16,17 @@
  */

 public abstract class AbstractInlineBox extends AbstractBox implements InlineBox {

 

+	@Override

 	public void alignOnBaseline(final int baseline) {

 		setY(baseline - getBaseline());

 	}

 

+	@Override

 	public boolean isSplitable() {

 		return false;

 	}

 

+	@Override

 	public Pair split(final LayoutContext context, final int maxWidth, final boolean force) {

 		throw new UnsupportedOperationException("split method not supported");

 	}

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/AnonymousBlockBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/AnonymousBlockBox.java
index 6ce13f2..ddb310c 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/AnonymousBlockBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/AnonymousBlockBox.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *     Igor Jacy Lino Campista - Java 5 warnings fixed (bug 311325)
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/BlockBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/BlockBox.java
index bd085d9..8e87f5d 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/BlockBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/BlockBox.java
@@ -4,12 +4,13 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
 package org.eclipse.vex.core.internal.layout;
 
+import org.eclipse.vex.core.provisional.dom.ContentPosition;
 
 /**
  * Represents a block box. Block boxes are stacked one on top of another.
@@ -28,19 +29,19 @@
 
 	/**
 	 * Returns the offset of the end of the line containing the given offset.
-	 * 
+	 *
 	 * @param offset
 	 *            offset identifying the current line.
 	 */
-	public int getLineEndOffset(int offset);
+	public ContentPosition getLineEndPosition(ContentPosition linePosition);
 
 	/**
 	 * Returns the offset of the start of the line containing the given offset.
-	 * 
+	 *
 	 * @param offset
 	 *            offset identifying the current line.
 	 */
-	public int getLineStartOffset(int offset);
+	public ContentPosition getLineStartPosition(ContentPosition linePosition);
 
 	/**
 	 * Returns the bottom margin of this box.
@@ -55,7 +56,7 @@
 	/**
 	 * Returns the offset on the next line that is closest to the given x coordinate. The given offset may be before the
 	 * start of this box in which case this method should return the offset of the first line in this box.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext used for the layout
 	 * @param offset
@@ -63,12 +64,12 @@
 	 * @param x
 	 *            the x coordinate
 	 */
-	public int getNextLineOffset(LayoutContext context, int offset, int x);
+	public ContentPosition getNextLinePosition(LayoutContext context, ContentPosition linePosition, int x);
 
 	/**
 	 * Returns the offset on the previous line that is closest to the given x coordinate. The given offset may be after
 	 * the end of this box in which case this method should return the offset of the last line in this box.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext used for the layout
 	 * @param offset
@@ -76,7 +77,7 @@
 	 * @param x
 	 *            the x coordinate
 	 */
-	public int getPreviousLineOffset(LayoutContext context, int offset, int x);
+	public ContentPosition getPreviousLinePosition(LayoutContext context, ContentPosition linePosition, int x);
 
 	/**
 	 * Returns the parent box of this box.
@@ -85,7 +86,7 @@
 
 	/**
 	 * Informs this box that its layout has become invalid, and that it should re-do it the next time layout is called.
-	 * 
+	 *
 	 * @param direct
 	 *            If true, the box's content has changed and it must re-create it's children on the next call to layout.
 	 *            Otherwise, it should just propagate the next layout call to its children.
@@ -94,28 +95,28 @@
 
 	/**
 	 * Layout this box. This method is responsible for the following.
-	 * 
+	 *
 	 * <ul>
 	 * <li>Creating any child boxes.</li>
 	 * <li>Calling layout on the child boxes.</li>
 	 * <li>Positioning the child boxes (i.e. calling child.setX() and child.setY())</li>
 	 * <li>Determining this box's height and width.</li>
 	 * </ul>
-	 * 
+	 *
 	 * <p>
 	 * Boxes with no children should simply calculate their width and height here
 	 * </p>
-	 * 
+	 *
 	 * <p>
 	 * This method is passed a vertical range to be layed out. Children falling outside this range need not be layed
 	 * out.
 	 * </p>
-	 * 
+	 *
 	 * <p>
 	 * This method returns an IntRange object representing the vertical range to re-draw due to layout change. Null may
 	 * be returned if there were no changes that need to be re-drawn.
 	 * </p>
-	 * 
+	 *
 	 * @param context
 	 *            The layout context to be used.
 	 * @param top
@@ -127,7 +128,7 @@
 
 	/**
 	 * Sets the initial size of the box.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext to use.
 	 */
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/BlockElementBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/BlockElementBox.java
index fb48dce..13a1c96 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/BlockElementBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/BlockElementBox.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *     Igor Jacy Lino Campista - Java 5 warnings fixed (bug 311325)
@@ -16,16 +16,11 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.eclipse.vex.core.internal.VEXCorePlugin;
-import org.eclipse.vex.core.internal.core.Drawable;
-import org.eclipse.vex.core.internal.core.Graphics;
-import org.eclipse.vex.core.internal.core.Rectangle;
 import org.eclipse.vex.core.internal.css.CSS;
 import org.eclipse.vex.core.internal.css.StyleSheet;
 import org.eclipse.vex.core.internal.css.Styles;
 import org.eclipse.vex.core.provisional.dom.IElement;
 import org.eclipse.vex.core.provisional.dom.INode;
-import org.eclipse.vex.core.provisional.dom.IParent;
 
 /**
  * A block box corresponding to a DOM Element. Block boxes lay their children out stacked top to bottom. Block boxes
@@ -33,20 +28,13 @@
  */
 public class BlockElementBox extends AbstractBlockBox {
 
-	/** hspace btn. list-item bullet and block, as fraction of font-size */
-	static final float BULLET_SPACE = 0.5f;
-
-	/** vspace btn. list-item bullet and baseine, as fraction of font-size */
-	// private static final float BULLET_LIFT = 0.1f;
 	/** number of boxes created since VM startup, for profiling */
 	private static int boxCount;
 
-	BlockBox beforeMarker;
-
 	/**
 	 * Class constructor. This box's children are not created here but in the first call to layout. Instead, we estimate
 	 * the box's height here based on the given width.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext used for this layout.
 	 * @param parent
@@ -59,7 +47,7 @@
 	}
 
 	/**
-	 * Returns the number of boxes created since VM startup. Used for profiling.
+	 * @return the number of boxes created since VM startup. Used for profiling.
 	 */
 	public static int getBoxCount() {
 		return boxCount;
@@ -76,64 +64,23 @@
 	}
 
 	@Override
-	public void paint(final LayoutContext context, final int x, final int y) {
-
-		super.paint(context, x, y);
-
-		if (beforeMarker != null) {
-			beforeMarker.paint(context, x + beforeMarker.getX(), y + beforeMarker.getY());
-		}
-	}
-
-	@Override
-	protected int positionChildren(final LayoutContext context) {
-
-		final int repaintStart = super.positionChildren(context);
-
-		final Styles styles = context.getStyleSheet().getStyles(getNode());
-		if (beforeMarker != null) {
-			final int x = -beforeMarker.getWidth() - Math.round(BULLET_SPACE * styles.getFontSize());
-			int y = getFirstLineTop(context);
-			final LineBox firstLine = getFirstLine();
-			if (firstLine != null) {
-				y += firstLine.getBaseline() - beforeMarker.getFirstLine().getBaseline();
-			}
-
-			beforeMarker.setX(x);
-			beforeMarker.setY(y);
-		}
-
-		return repaintStart;
-	}
-
-	@Override
 	public String toString() {
 		return "BlockElementBox: <" + getNode() + ">" + "[x=" + getX() + ",y=" + getY() + ",width=" + getWidth() + ",height=" + getHeight() + "]";
 	}
 
-	// ===================================================== PRIVATE
-
-	/**
-	 * Lays out the children as vertically stacked blocks. Runs of text and inline elements are wrapped in
-	 * DummyBlockBox's.
-	 */
 	@Override
 	public List<Box> createChildren(final LayoutContext context) {
-		long start = 0;
-		if (VEXCorePlugin.getInstance().isDebugging()) {
-			start = System.currentTimeMillis();
-		}
-
 		final INode node = getNode();
 		final int width = getWidth();
 
 		final List<Box> childList = new ArrayList<Box>();
 
 		final StyleSheet styleSheet = context.getStyleSheet();
+		final Styles styles = styleSheet.getStyles(node);
 
 		// :before content
 		List<InlineBox> beforeInlines = null;
-		final IElement before = styleSheet.getPseudoElement(node, CSS.PSEUDO_BEFORE, true);
+		final IElement before = styleSheet.getPseudoElementBefore(node);
 		if (before != null) {
 			final Styles beforeStyles = styleSheet.getStyles(before);
 			if (beforeStyles.getDisplay().equals(CSS.INLINE)) {
@@ -145,7 +92,6 @@
 		}
 
 		// background image
-		final Styles styles = context.getStyleSheet().getStyles(node);
 		if (styles.hasBackgroundImage() && !styles.getDisplay().equalsIgnoreCase(CSS.NONE)) {
 			final InlineBox imageBox = ImageBox.create(node, context, getWidth());
 			if (imageBox != null) {
@@ -160,7 +106,7 @@
 		Box afterBlock = null;
 		List<InlineBox> afterInlines = null;
 
-		final IElement after = styleSheet.getPseudoElement(node, CSS.PSEUDO_AFTER, true);
+		final IElement after = styleSheet.getPseudoElementAfter(node);
 		if (after != null) {
 			final Styles afterStyles = styleSheet.getStyles(after);
 			if (afterStyles.getDisplay().equals(CSS.INLINE)) {
@@ -180,108 +126,10 @@
 			childList.add(afterBlock);
 		}
 
-		if (styles.getDisplay().equals(CSS.LIST_ITEM) && !styles.getListStyleType().equals(CSS.NONE)) {
-			createListMarker(context);
-		}
-
-		if (VEXCorePlugin.getInstance().isDebugging()) {
-			final long end = System.currentTimeMillis();
-			if (end - start > 10) {
-				System.out.println("BEB.layout for " + getNode() + " took " + (end - start) + "ms");
-			}
-		}
-
 		return childList;
 	}
 
-	/**
-	 * Creates a marker box for this primary box and puts it in the beforeMarker field.
-	 */
-	private void createListMarker(final LayoutContext context) {
-
-		final Styles styles = context.getStyleSheet().getStyles(getNode());
-
-		InlineBox markerInline;
-		final String type = styles.getListStyleType();
-		if (type.equals(CSS.NONE)) {
-			return;
-		} else if (type.equals(CSS.CIRCLE)) {
-			markerInline = createCircleBullet(getNode(), styles);
-		} else if (type.equals(CSS.SQUARE)) {
-			markerInline = createSquareBullet(getNode(), styles);
-		} else if (isEnumeratedListStyleType(type)) {
-			final String item = getItemNumberString(type);
-			markerInline = new StaticTextBox(context, getNode(), item + ".");
-		} else {
-			markerInline = createDiscBullet(getNode(), styles);
-		}
-
-		beforeMarker = ParagraphBox.create(context, getNode(), new InlineBox[] { markerInline }, Integer.MAX_VALUE);
-
-	}
-
-	/**
-	 * Returns a Drawable that draws a circle-style list item bullet.
-	 */
-	private static InlineBox createCircleBullet(final INode node, final Styles styles) {
-		final int size = Math.round(0.5f * styles.getFontSize());
-		final int lift = Math.round(0.1f * styles.getFontSize());
-		final Drawable drawable = new Drawable() {
-			public void draw(final Graphics g, final int x, final int y) {
-				g.setLineStyle(Graphics.LINE_SOLID);
-				g.setLineWidth(1);
-				g.drawOval(x, y - size - lift, size, size);
-			}
-
-			public Rectangle getBounds() {
-				return new Rectangle(0, -size - lift, size, size);
-			}
-		};
-		return new DrawableBox(drawable, node);
-	}
-
-	/**
-	 * Returns a Drawable that draws a disc-style list item bullet.
-	 */
-	private static InlineBox createDiscBullet(final INode node, final Styles styles) {
-		final int size = Math.round(0.5f * styles.getFontSize());
-		final int lift = Math.round(0.1f * styles.getFontSize());
-		final Drawable drawable = new Drawable() {
-			public void draw(final Graphics g, final int x, final int y) {
-				g.fillOval(x, y - size - lift, size, size);
-			}
-
-			public Rectangle getBounds() {
-				return new Rectangle(0, -size - lift, size, size);
-			}
-		};
-		return new DrawableBox(drawable, node);
-	}
-
-	/**
-	 * Returns a Drawable that draws a square-style list item bullet.
-	 */
-	private static InlineBox createSquareBullet(final INode node, final Styles styles) {
-		final int size = Math.round(0.5f * styles.getFontSize());
-		final int lift = Math.round(0.1f * styles.getFontSize());
-		final Drawable drawable = new Drawable() {
-			public void draw(final Graphics g, final int x, final int y) {
-				g.setLineStyle(Graphics.LINE_SOLID);
-				g.setLineWidth(1);
-				g.drawRect(x, y - size - lift, size, size);
-			}
-
-			public Rectangle getBounds() {
-				return new Rectangle(0, -size - lift, size, size);
-			}
-		};
-		return new DrawableBox(drawable, node);
-	}
-
-	/**
-	 * Returns the vertical distance from the top of this box to the top of its first line.
-	 */
-	int getFirstLineTop(final LayoutContext context) {
+	protected int getFirstLineTop(final LayoutContext context) {
 		final Styles styles = context.getStyleSheet().getStyles(getNode());
 		final int top = styles.getBorderTopWidth() + styles.getPaddingTop().get(0);
 		final Box[] children = getChildren();
@@ -292,75 +140,4 @@
 		}
 	}
 
-	/**
-	 * Returns the item number of this box. The item number indicates the ordinal number of the corresponding element
-	 * amongst its siblings starting with 1.
-	 */
-	private int getItemNumber() {
-		final INode node = getNode();
-		final IParent parent = node.getParent();
-
-		if (parent == null) {
-			return 1;
-		}
-
-		int item = 1;
-		for (final INode child : parent.children()) {
-			if (child == node) {
-				return item;
-			}
-			if (child.isKindOf(node)) {
-				item++;
-			}
-		}
-
-		throw new IllegalStateException();
-	}
-
-	private String getItemNumberString(final String style) {
-		final int item = getItemNumber();
-		if (style.equals(CSS.DECIMAL_LEADING_ZERO)) {
-			if (item < 10) {
-				return "0" + Integer.toString(item);
-			} else {
-				return Integer.toString(item);
-			}
-		} else if (style.equals(CSS.LOWER_ALPHA) || style.equals(CSS.LOWER_LATIN)) {
-			return getAlpha(item);
-		} else if (style.equals(CSS.LOWER_ROMAN)) {
-			return getRoman(item);
-		} else if (style.equals(CSS.UPPER_ALPHA) || style.equals(CSS.UPPER_LATIN)) {
-			return getAlpha(item).toUpperCase();
-		} else if (style.equals(CSS.UPPER_ROMAN)) {
-			return getRoman(item).toUpperCase();
-		} else {
-			return Integer.toString(item);
-		}
-	}
-
-	private String getAlpha(final int n) {
-		final String alpha = "abcdefghijklmnopqrstuvwxyz";
-		return String.valueOf(alpha.charAt((n - 1) % 26));
-	}
-
-	private String getRoman(final int n) {
-		final String[] ones = { "", "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix" };
-		final String[] tens = { "", "x", "xx", "xxx", "xl", "l", "lx", "lxx", "lxxx", "xc" };
-		final String[] hundreds = { "", "c", "cc", "ccc", "cd", "d", "dc", "dcc", "dccc", "cm" };
-		final StringBuffer sb = new StringBuffer();
-		for (int i = 0; i < n / 1000; i++) {
-			sb.append("m");
-		}
-		sb.append(hundreds[n / 100 % 10]);
-		sb.append(tens[n / 10 % 10]);
-		sb.append(ones[n % 10]);
-		return sb.toString();
-	}
-
-	private static boolean isEnumeratedListStyleType(final String s) {
-		return s.equals(CSS.ARMENIAN) || s.equals(CSS.CJK_IDEOGRAPHIC) || s.equals(CSS.DECIMAL) || s.equals(CSS.DECIMAL_LEADING_ZERO) || s.equals(CSS.GEORGIAN) || s.equals(CSS.HEBREW)
-				|| s.equals(CSS.HIRAGANA) || s.equals(CSS.HIRAGANA_IROHA) || s.equals(CSS.KATAKANA) || s.equals(CSS.KATAKANA_IROHA) || s.equals(CSS.LOWER_ALPHA) || s.equals(CSS.LOWER_GREEK)
-				|| s.equals(CSS.LOWER_LATIN) || s.equals(CSS.LOWER_ROMAN) || s.equals(CSS.UPPER_ALPHA) || s.equals(CSS.UPPER_LATIN) || s.equals(CSS.UPPER_ROMAN);
-	}
-
 }
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/BlockPseudoElementBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/BlockPseudoElementBox.java
index 7c5a0fa..ff836fe 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/BlockPseudoElementBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/BlockPseudoElementBox.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *     Igor Jacy Lino Campista - Java 5 warnings fixed (bug 311325)
@@ -14,12 +14,13 @@
 import java.util.List;
 
 import org.eclipse.vex.core.internal.css.Styles;
+import org.eclipse.vex.core.provisional.dom.ContentPosition;
 import org.eclipse.vex.core.provisional.dom.IElement;
 import org.eclipse.vex.core.provisional.dom.INode;
 
 /**
  * Implements a Block
- * 
+ *
  * XXX REMOVE THIS HACK!!!
  */
 public class BlockPseudoElementBox extends AbstractBox implements BlockBox {
@@ -56,7 +57,7 @@
 
 	/**
 	 * Provide children for {@link AbstractBox#paint}.
-	 * 
+	 *
 	 * @see org.eclipse.vex.core.internal.layout.Box#getChildren()
 	 */
 	@Override
@@ -75,6 +76,7 @@
 	/**
 	 * @see org.eclipse.vex.core.internal.layout.BlockBox#getFirstLine()
 	 */
+	@Override
 	public LineBox getFirstLine() {
 		throw new IllegalStateException();
 	}
@@ -82,6 +84,7 @@
 	/**
 	 * @see org.eclipse.vex.core.internal.layout.BlockBox#getLastLine()
 	 */
+	@Override
 	public LineBox getLastLine() {
 		throw new IllegalStateException();
 	}
@@ -89,21 +92,25 @@
 	/**
 	 * @see org.eclipse.vex.core.internal.layout.BlockBox#getLineEndOffset(int)
 	 */
-	public int getLineEndOffset(final int offset) {
+	@Override
+	public ContentPosition getLineEndPosition(final ContentPosition position) {
 		throw new IllegalStateException();
 	}
 
 	/**
 	 * @see org.eclipse.vex.core.internal.layout.BlockBox#getLineStartOffset(int)
 	 */
-	public int getLineStartOffset(final int offset) {
+	@Override
+	public ContentPosition getLineStartPosition(final ContentPosition position) {
 		throw new IllegalStateException();
 	}
 
+	@Override
 	public int getMarginBottom() {
 		return marginBottom;
 	}
 
+	@Override
 	public int getMarginTop() {
 		return marginTop;
 	}
@@ -112,13 +119,15 @@
 	 * @see org.eclipse.vex.core.internal.layout.BlockBox#getNextLineOffset(org.eclipse.vex.core.internal.layout.LayoutContext,
 	 *      int, int)
 	 */
-	public int getNextLineOffset(final LayoutContext context, final int offset, final int x) {
+	@Override
+	public ContentPosition getNextLinePosition(final LayoutContext context, final ContentPosition position, final int x) {
 		throw new IllegalStateException();
 	}
 
 	/**
 	 * Returns this box's parent.
 	 */
+	@Override
 	public BlockBox getParent() {
 		return parent;
 	}
@@ -127,21 +136,24 @@
 	 * @see org.eclipse.vex.core.internal.layout.BlockBox#getPreviousLineOffset(org.eclipse.vex.core.internal.layout.LayoutContext,
 	 *      int, int)
 	 */
-	public int getPreviousLineOffset(final LayoutContext context, final int offset, final int x) {
+	@Override
+	public ContentPosition getPreviousLinePosition(final LayoutContext context, final ContentPosition position, final int x) {
 		throw new IllegalStateException();
 	}
 
+	@Override
 	public VerticalRange layout(final LayoutContext context, final int top, final int bottom) {
 		return null;
 	}
 
+	@Override
 	public void invalidate(final boolean direct) {
 		throw new IllegalStateException("invalidate called on a non-element BlockBox");
 	}
 
 	/**
 	 * Draw boxes before painting our child.
-	 * 
+	 *
 	 * @see org.eclipse.vex.core.internal.layout.Box#paint(org.eclipse.vex.core.internal.layout.LayoutContext, int, int)
 	 */
 	@Override
@@ -150,6 +162,7 @@
 		super.paint(context, x, y);
 	}
 
+	@Override
 	public void setInitialSize(final LayoutContext context) {
 		// NOP - size calculated in the ctor
 	}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/Box.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/Box.java
index f2ae0ff..55684d8 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/Box.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/Box.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -12,6 +12,7 @@
 
 import org.eclipse.vex.core.internal.core.Caret;
 import org.eclipse.vex.core.internal.core.Insets;
+import org.eclipse.vex.core.provisional.dom.ContentPosition;
 import org.eclipse.vex.core.provisional.dom.INode;
 
 /**
@@ -23,21 +24,29 @@
 
 	/**
 	 * Returns true if this box contains the given offset.
-	 * 
+	 *
 	 * @param offset
 	 *            the offset to test
 	 */
 	public boolean containsOffset(int offset);
 
 	/**
+	 * Returns true if this box contains the given position.
+	 *
+	 * @param position
+	 *            the ContentPosition to test
+	 */
+	public boolean containsPosition(ContentPosition position);
+
+	/**
 	 * Returns a Caret object representing the given offset.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext to be used
-	 * @param offset
-	 *            offset for which to retrieve the caret
+	 * @param position
+	 *            position for which to retrieve the caret
 	 */
-	public Caret getCaret(LayoutContext context, int offset);
+	public Caret getCaret(LayoutContext context, ContentPosition position);
 
 	/**
 	 * Returns an array of this box's children.
@@ -45,8 +54,9 @@
 	public Box[] getChildren();
 
 	/**
-	 * Returns the Element with which this box is associated, or null if there is no such box. The box may directly
-	 * represent the Element, or simply use it for formatting information.
+	 * Returns the Element with which this box is associated, or the surrounding element if this is an anonymous box.
+	 * The box may directly represent the Element, or simply use it for formatting information.<br>
+	 * To check if this box is directly associated to an Element, use {@link #isAnonymous()}
 	 */
 	public INode getNode();
 
@@ -63,7 +73,7 @@
 
 	/**
 	 * Return an Insets object representing the total width of margins, borders, and padding for this box.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext being used for this layout.
 	 * @param containerWidth
@@ -97,7 +107,7 @@
 	/**
 	 * Returns true if this box represents a portion of the XML document's content. If false is returned, the following
 	 * methods are not supported by this box.
-	 * 
+	 *
 	 * <ul>
 	 * <li>getCaretShapes()</li>
 	 * <li>getEndOffset()</li>
@@ -114,7 +124,7 @@
 
 	/**
 	 * Draws the box's content in the given Graphics context.
-	 * 
+	 *
 	 * @param context
 	 *            <code>LayoutContext</code> containing the <code>Graphics</code> object into which the box should be
 	 *            painted
@@ -127,7 +137,7 @@
 
 	/**
 	 * Sets the height of this box.
-	 * 
+	 *
 	 * @param height
 	 *            new height of the box
 	 */
@@ -135,7 +145,7 @@
 
 	/**
 	 * Sets the width of this box.
-	 * 
+	 *
 	 * @param width
 	 *            new width of the box
 	 */
@@ -143,7 +153,7 @@
 
 	/**
 	 * Sets the x-coordinate of the top-left corner of the box.
-	 * 
+	 *
 	 * @param x
 	 *            the new x-coordinate
 	 */
@@ -151,15 +161,15 @@
 
 	/**
 	 * Sets the y-coordinate of the top-left corner of the box.
-	 * 
+	 *
 	 * @param y
 	 *            the new y-coordinate
 	 */
 	public void setY(int y);
 
 	/**
-	 * Returns the offset in the content closest to the given view position.
-	 * 
+	 * Returns the position in the content closest to the given view position.
+	 *
 	 * @param context
 	 *            <code>LayoutContext</code> for this box tree
 	 * @param x
@@ -167,6 +177,6 @@
 	 * @param y
 	 *            y offset of the view position for which the model offset is to be determined.
 	 */
-	public int viewToModel(LayoutContext context, int x, int y);
+	public ContentPosition viewToModel(LayoutContext context, int x, int y);
 
 }
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/BoxFactory.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/BoxFactory.java
index 9e13685..73cef10 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/BoxFactory.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/BoxFactory.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -21,7 +21,7 @@
 
 	/**
 	 * Creates a box given an element.
-	 * 
+	 *
 	 * @param context
 	 *            CSS styles for the new element
 	 * @param node
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/Bullet.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/Bullet.java
new file mode 100644
index 0000000..0736755
--- /dev/null
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/Bullet.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Florian Thienel 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:
+ * 		Florian Thienel - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.vex.core.internal.layout;
+
+import org.eclipse.vex.core.internal.core.Drawable;
+
+/**
+ * @author Florian Thienel
+ */
+public abstract class Bullet implements Drawable {
+
+	// size of the bullet as fraction of font-size
+	private static final float BULLET_SIZE = 0.5f;
+	// vspace between list-item bullet and baseine, as fraction of font-size
+	private static final float BULLET_LIFT = 0.1f;
+
+	final int size;
+	final int lift;
+
+	public Bullet(final float fontSize) {
+		size = Math.round(BULLET_SIZE * fontSize);
+		lift = Math.round(BULLET_LIFT * fontSize);
+	}
+
+	public int getSize() {
+		return size;
+	}
+
+	public int getLift() {
+		return lift;
+	}
+
+}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/CircleBullet.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/CircleBullet.java
new file mode 100644
index 0000000..99b3779
--- /dev/null
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/CircleBullet.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Florian Thienel 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:
+ * 		Florian Thienel - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.vex.core.internal.layout;
+
+import org.eclipse.vex.core.internal.core.Graphics;
+import org.eclipse.vex.core.internal.core.Rectangle;
+
+/**
+ * @author Florian Thienel
+ */
+public class CircleBullet extends Bullet {
+
+	public CircleBullet(final float fontSize) {
+		super(fontSize);
+	}
+
+	@Override
+	public void draw(final Graphics g, final int x, final int y) {
+		g.setLineStyle(Graphics.LINE_SOLID);
+		g.setLineWidth(1);
+		g.drawOval(x, y - size - lift, size, size);
+	}
+
+	@Override
+	public Rectangle getBounds() {
+		return new Rectangle(0, -size - lift, size, size);
+	}
+
+}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/CompositeInlineBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/CompositeInlineBox.java
index c0334a0..8a19272 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/CompositeInlineBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/CompositeInlineBox.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *     Igor Jacy Lino Campista - Java 5 warnings fixed (bug 311325)
@@ -21,6 +21,7 @@
 import org.eclipse.vex.core.internal.core.FontResource;
 import org.eclipse.vex.core.internal.core.Graphics;
 import org.eclipse.vex.core.internal.css.Styles;
+import org.eclipse.vex.core.provisional.dom.ContentPosition;
 
 /**
  * InlineBox consisting of several children. This is the parent class of InlineElementBox and LineBox, and implements
@@ -46,6 +47,7 @@
 		return false;
 	}
 
+	@Override
 	public boolean isEOL() {
 		final Box[] children = getChildren();
 		return children.length > 0 && ((InlineBox) children[children.length - 1]).isEOL();
@@ -55,7 +57,7 @@
 	 * @see org.eclipse.vex.core.internal.layout.Box#getCaret(org.eclipse.vex.core.internal.layout.LayoutContext, int)
 	 */
 	@Override
-	public Caret getCaret(final LayoutContext context, final int offset) {
+	public Caret getCaret(final LayoutContext context, final ContentPosition position) {
 
 		int x = 0;
 		final Box[] children = getChildren();
@@ -76,10 +78,10 @@
 		for (int i = start; i < end; i++) {
 			final Box child = children[i];
 			if (child.hasContent()) {
-				if (offset < child.getStartOffset()) {
+				if (position.getOffset() < child.getStartOffset()) {
 					break;
-				} else if (offset <= child.getEndOffset()) {
-					final Caret caret = child.getCaret(context, offset);
+				} else if (position.getOffset() <= child.getEndOffset()) {
+					final Caret caret = child.getCaret(context, position);
 					caret.translate(child.getX(), child.getY());
 					return caret;
 				}
@@ -185,7 +187,7 @@
 
 	/**
 	 * Creates a Pair of InlineBoxes, each with its own set of children.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext used for this layout.
 	 * @param lefts
@@ -203,7 +205,7 @@
 	 *      int, int)
 	 */
 	@Override
-	public int viewToModel(final LayoutContext context, final int x, final int y) {
+	public ContentPosition viewToModel(final LayoutContext context, final int x, final int y) {
 
 		if (!hasContent()) {
 			throw new RuntimeException("Oops. Calling viewToModel on a line with no content");
@@ -220,7 +222,7 @@
 				} else if (x > child.getX() + child.getWidth()) {
 					newDelta = x - (child.getX() + child.getWidth());
 				}
-				if (newDelta < delta) {
+				if (newDelta <= delta) {
 					delta = newDelta;
 					closestContentChild = child;
 				}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/CssBoxFactory.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/CssBoxFactory.java
index 44de5e3..02d8dfc 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/CssBoxFactory.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/CssBoxFactory.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2008 John Krasnay and others.
+ * Copyright (c) 2004, 2014 John Krasnay 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
@@ -17,6 +17,7 @@
 import org.eclipse.vex.core.provisional.dom.IDocument;
 import org.eclipse.vex.core.provisional.dom.IDocumentFragment;
 import org.eclipse.vex.core.provisional.dom.IElement;
+import org.eclipse.vex.core.provisional.dom.IIncludeNode;
 import org.eclipse.vex.core.provisional.dom.INode;
 import org.eclipse.vex.core.provisional.dom.IProcessingInstruction;
 import org.eclipse.vex.core.provisional.dom.IText;
@@ -28,6 +29,7 @@
 
 	private static final long serialVersionUID = -6882526795866485074L;
 
+	@Override
 	public Box createBox(final LayoutContext context, final INode node, final BlockBox parentBox, final int containerWidth) {
 		final Styles styles = context.getStyleSheet().getStyles(node);
 		return node.accept(new BaseNodeVisitorWithResult<Box>() {
@@ -43,8 +45,11 @@
 
 			@Override
 			public Box visit(final IElement element) {
-				if (styles.getDisplay().equals(CSS.TABLE)) {
+				final String displayStyle = styles.getDisplay();
+				if (displayStyle.equals(CSS.TABLE)) {
 					return new TableBox(context, parentBox, element);
+				} else if (displayStyle.equals(CSS.LIST_ITEM)) {
+					return new ListItemBox(context, parentBox, node);
 				} else if (context.getWhitespacePolicy().isBlock(element)) {
 					return new BlockElementBox(context, parentBox, node);
 				} else {
@@ -63,6 +68,11 @@
 			}
 
 			@Override
+			public Box visit(final IIncludeNode include) {
+				return new IncludeBlockBox(context, parentBox, include);
+			}
+
+			@Override
 			public Box visit(final IText text) {
 				throw new IllegalStateException("The box factory must not be called for Text nodes.");
 			}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/DiscBullet.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/DiscBullet.java
new file mode 100644
index 0000000..2545856
--- /dev/null
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/DiscBullet.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Florian Thienel 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:
+ * 		Florian Thienel - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.vex.core.internal.layout;
+
+import org.eclipse.vex.core.internal.core.Graphics;
+import org.eclipse.vex.core.internal.core.Rectangle;
+
+/**
+ * @author Florian Thienel
+ */
+public class DiscBullet extends Bullet {
+
+	public DiscBullet(final float fontSize) {
+		super(fontSize);
+	}
+
+	@Override
+	public void draw(final Graphics g, final int x, final int y) {
+		g.fillOval(x, y - size - lift, size, size);
+	}
+
+	@Override
+	public Rectangle getBounds() {
+		return new Rectangle(0, -size - lift, size, size);
+	}
+
+}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/DocumentTextBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/DocumentTextBox.java
index 93890ca..3e3cb2f 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/DocumentTextBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/DocumentTextBox.java
@@ -18,8 +18,10 @@
 import org.eclipse.vex.core.internal.core.FontResource;
 import org.eclipse.vex.core.internal.core.Graphics;
 import org.eclipse.vex.core.internal.css.Styles;
+import org.eclipse.vex.core.provisional.dom.ContentPosition;
 import org.eclipse.vex.core.provisional.dom.ContentRange;
 import org.eclipse.vex.core.provisional.dom.INode;
+import org.eclipse.vex.core.provisional.dom.IPosition;
 
 /**
  * A TextBox that gets its text from the document. Represents text which is editable within the VexWidget.
@@ -27,11 +29,12 @@
 public class DocumentTextBox extends TextBox {
 
 	private int startRelative;
+	private final IPosition startPosition;
 	private final int endRelative;
 
 	/**
 	 * Class constructor.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext used to calculate the box's size.
 	 * @param node
@@ -48,15 +51,15 @@
 			throw new AssertionFailedException(MessageFormat.format("assertion failed: DocumentTextBox for {2}: startOffset {0} > endOffset {1}", startOffset, endOffset, node)); //$NON-NLS-1$
 		}
 
-		final int nodeStart = node.getStartOffset();
-		startRelative = startOffset - nodeStart;
-		endRelative = endOffset - nodeStart;
+		startRelative = 0;
+		startPosition = node.getContent().createPosition(startOffset);
+		endRelative = endOffset - startOffset;
 
 		// The box constructed here will be splitted, so there's no need to calculate the width here.
 		calculateHeight(context);
 		setWidth(-1);
 
-		if (startOffset <= nodeStart || endOffset >= node.getEndOffset()) {
+		if (startOffset <= node.getStartOffset() || endOffset >= node.getEndOffset()) {
 			// Do not use Assert.isTrue. This Contructor is called very often and the use of Assert.isTrue would evaluate the Message.format every time.
 			throw new AssertionFailedException(MessageFormat.format("assertion failed: Range of DocumentTextBox for {0} exceeds content of parent node", node)); //$NON-NLS-1$
 		}
@@ -64,7 +67,7 @@
 
 	/**
 	 * Class constructor used by the splitAt method.
-	 * 
+	 *
 	 * @param other
 	 *            Instance of DocumentTextBox that should be splitted.
 	 * @param endOffset
@@ -74,8 +77,9 @@
 	 */
 	private DocumentTextBox(final DocumentTextBox other, final int endOffset, final int width) {
 		super(other.getNode());
+		startPosition = other.startPosition;
 		startRelative = other.startRelative;
-		endRelative = endOffset - getNode().getStartOffset();
+		endRelative = endOffset - startPosition.getOffset();
 		setWidth(width);
 		setHeight(other.getHeight());
 		setBaseline(other.getBaseline());
@@ -89,7 +93,7 @@
 		if (endRelative == -1) {
 			return -1;
 		} else {
-			return getNode().getStartOffset() + endRelative;
+			return startPosition.getOffset() + endRelative;
 		}
 	}
 
@@ -101,7 +105,7 @@
 		if (startRelative == -1) {
 			return -1;
 		} else {
-			return getNode().getStartOffset() + startRelative;
+			return startPosition.getOffset() + startRelative;
 		}
 	}
 
@@ -222,7 +226,7 @@
 			right = null;
 		} else {
 			// Instead of creating a new box, we reuse this one
-			startRelative = split - getNode().getStartOffset();
+			startRelative = split - startPosition.getOffset();
 			if (left == null) {
 				calculateSize(context);
 				remaining -= getWidth();
@@ -237,7 +241,7 @@
 	 *      int, int)
 	 */
 	@Override
-	public int viewToModel(final LayoutContext context, final int x, final int y) {
+	public ContentPosition viewToModel(final LayoutContext context, final int x, final int y) {
 
 		final Graphics g = context.getGraphics();
 		final Styles styles = context.getStyleSheet().getStyles(getNode());
@@ -246,13 +250,13 @@
 		final char[] chars = getText().toCharArray();
 
 		if (getWidth() <= 0) {
-			return getStartOffset();
+			return getNode().getStartPosition().copy();
 		}
 
 		// first, get an estimate based on x / width
 		int offset = x / getWidth() * chars.length;
 		offset = Math.max(0, offset);
-		offset = Math.min(chars.length, offset);
+		offset = Math.min(chars.length - 1, offset);
 
 		int delta = Math.abs(x - g.charsWidth(chars, 0, offset));
 
@@ -278,7 +282,7 @@
 
 		g.setFont(oldFont);
 		font.dispose();
-		return getStartOffset() + offset;
+		return new ContentPosition(getNode(), getStartOffset() + offset);
 	}
 
 }
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/DrawableBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/DrawableBox.java
index 5ec9ae6..1c1490d 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/DrawableBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/DrawableBox.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -35,7 +35,7 @@
 
 	/**
 	 * Class constructor.
-	 * 
+	 *
 	 * @param drawable
 	 *            Drawable to draw.
 	 * @param node
@@ -48,7 +48,7 @@
 	/**
 	 * Class constructor. This constructor is called when creating a DrawableBox that represents the start or end marker
 	 * of an inline element.
-	 * 
+	 *
 	 * @param drawable
 	 *            Drawable to draw.
 	 * @param node
@@ -68,6 +68,7 @@
 	/**
 	 * @see org.eclipse.vex.core.internal.layout.InlineBox#getBaseline()
 	 */
+	@Override
 	public int getBaseline() {
 		return 0;
 	}
@@ -80,6 +81,7 @@
 		return node;
 	}
 
+	@Override
 	public boolean isEOL() {
 		return false;
 	}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/ElementOrPositionRangeCallback.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/ElementOrPositionRangeCallback.java
new file mode 100644
index 0000000..d34a13d
--- /dev/null
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/ElementOrPositionRangeCallback.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Carsten Hiesserich 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:
+ *     Carsten Hiesserich - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.vex.core.internal.layout;
+
+import org.eclipse.vex.core.provisional.dom.ContentPosition;
+import org.eclipse.vex.core.provisional.dom.IElement;
+import org.eclipse.vex.core.provisional.dom.IParent;
+
+public interface ElementOrPositionRangeCallback {
+	public void onElement(IElement child, String displayStyle);
+
+	public void onRange(IParent parent, ContentPosition startPosition, ContentPosition endPosition);
+}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/ElementOrRangeCallback.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/ElementOrRangeCallback.java
index a193edb..1f04a2e 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/ElementOrRangeCallback.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/ElementOrRangeCallback.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/FormattingPortionIterator.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/FormattingPortionIterator.java
index d2a228b..2c10b20 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/FormattingPortionIterator.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/FormattingPortionIterator.java
@@ -18,6 +18,7 @@
 import org.eclipse.vex.core.provisional.dom.ContentRange;
 import org.eclipse.vex.core.provisional.dom.IComment;
 import org.eclipse.vex.core.provisional.dom.IElement;
+import org.eclipse.vex.core.provisional.dom.IIncludeNode;
 import org.eclipse.vex.core.provisional.dom.INode;
 import org.eclipse.vex.core.provisional.dom.IParent;
 import org.eclipse.vex.core.provisional.dom.IProcessingInstruction;
@@ -131,6 +132,16 @@
 					}
 					return null;
 				}
+
+				@Override
+				public INode visit(final IIncludeNode include) {
+					// For exact WYSIWYG, we would have to check included content to determine how to display it.
+					// Currently, the CSS for xi|include decides if we display inline or block.
+					if (policy.isBlock(include)) {
+						return include;
+					}
+					return null;
+				}
 			});
 			if (nextBlockNode != null) {
 				return nextBlockNode;
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/HCaret.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/HCaret.java
index 78c09c9..e6f06ff 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/HCaret.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/HCaret.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -25,7 +25,7 @@
 
 	/**
 	 * Class constructor.
-	 * 
+	 *
 	 * @param x
 	 *            x-coordinate of the top left corner of the caret
 	 * @param y
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/ImageBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/ImageBox.java
index 7c9dcfd..ab317ed 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/ImageBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/ImageBox.java
@@ -85,6 +85,7 @@
 		super.paint(context, x, y);

 	}

 

+	@Override

 	public int getBaseline() {

 		return 0;

 	}

@@ -94,6 +95,7 @@
 		setY(0);

 	}

 

+	@Override

 	public boolean isEOL() {

 		return false;

 	}

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/IncludeBlockBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/IncludeBlockBox.java
new file mode 100644
index 0000000..6e07357
--- /dev/null
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/IncludeBlockBox.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Carsten Hiesserich 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:
+ * 		Carsten Hiesserich - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.vex.core.internal.layout;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.vex.core.internal.core.Caret;
+import org.eclipse.vex.core.internal.css.CSS;
+import org.eclipse.vex.core.internal.css.StyleSheet;
+import org.eclipse.vex.core.provisional.dom.ContentPosition;
+import org.eclipse.vex.core.provisional.dom.IElement;
+import org.eclipse.vex.core.provisional.dom.IIncludeNode;
+
+/**
+ * This class displays include elements like XInclude.
+ */
+public class IncludeBlockBox extends BlockElementBox {
+	private static final int H_CARET_LENGTH = 20;
+
+	public IncludeBlockBox(final LayoutContext context, final BlockBox parent, final IIncludeNode node) {
+		super(context, parent, node);
+	}
+
+	@Override
+	public Caret getCaret(final LayoutContext context, final ContentPosition position) {
+		return new HCaret(0, getHeight() - 2, H_CARET_LENGTH);
+	}
+
+	@Override
+	public List<Box> createChildren(final LayoutContext context) {
+		final IIncludeNode node = (IIncludeNode) getNode();
+		final int width = getWidth();
+
+		final StyleSheet styleSheet = context.getStyleSheet();
+		final List<Box> result = new ArrayList<Box>();
+		final List<InlineBox> pendingInlines = new ArrayList<InlineBox>();
+
+		// :before content - includes the target
+		final IElement before = styleSheet.getPseudoElementBefore(node.getReference());
+		if (before != null) {
+			pendingInlines.addAll(LayoutUtils.createGeneratedInlines(context, before, StaticTextBox.START_MARKER));
+		}
+
+		// content
+		final String text = LayoutUtils.getGeneratedContent(context, styleSheet.getStyles(node.getReference()), node.getReference());
+		if (text.length() > 0) {
+			pendingInlines.add(new StaticTextBox(context, node.getReference(), text));
+		}
+
+		// :after content
+		final IElement after = styleSheet.getPseudoElementAfter(node.getReference());
+		if (after != null) {
+			pendingInlines.addAll(LayoutUtils.createGeneratedInlines(context, after, StaticTextBox.END_MARKER));
+		}
+
+		if (pendingInlines.isEmpty()) {
+			// No pseudo element and no content - return something
+			pendingInlines.add(new StaticTextBox(context, node.getReference(), CSS.INCLUDE, StaticTextBox.START_MARKER));
+		}
+		result.add(ParagraphBox.create(context, node.getReference(), pendingInlines, width));
+
+		return result;
+	}
+
+	@Override
+	public ContentPosition getNextLinePosition(final LayoutContext context, final ContentPosition linePosition, final int x) {
+		// TODO Auto-generated method stub
+		return super.getNextLinePosition(context, linePosition, x);
+	}
+
+	@Override
+	public ContentPosition viewToModel(final LayoutContext context, final int x, final int y) {
+		return getNode().getStartPosition().moveBy(1);
+	}
+
+	@Override
+	public String toString() {
+		return "IncludeBlockBox: <" + getNode() + ">" + "[x=" + getX() + ",y=" + getY() + ",width=" + getWidth() + ",height=" + getHeight() + "]";
+	}
+}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/IncludeInlineBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/IncludeInlineBox.java
new file mode 100644
index 0000000..7501599
--- /dev/null
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/IncludeInlineBox.java
@@ -0,0 +1,238 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Carsten Hiesserich 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:
+ *     Carsten Hiesserich - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.vex.core.internal.layout;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.vex.core.internal.core.Caret;
+import org.eclipse.vex.core.internal.core.FontMetrics;
+import org.eclipse.vex.core.internal.core.FontResource;
+import org.eclipse.vex.core.internal.core.Graphics;
+import org.eclipse.vex.core.internal.css.CSS;
+import org.eclipse.vex.core.internal.css.Styles;
+import org.eclipse.vex.core.provisional.dom.ContentPosition;
+import org.eclipse.vex.core.provisional.dom.IElement;
+import org.eclipse.vex.core.provisional.dom.IIncludeNode;
+import org.eclipse.vex.core.provisional.dom.INode;
+
+public class IncludeInlineBox extends CompositeInlineBox {
+	private static final int H_CARET_LENGTH = 20;
+
+	private final INode node;
+	private InlineBox[] children;
+	private InlineBox firstContentChild = null;
+	private int baseline;
+
+	/**
+	 * Class constructor, called by the {@link InlineElementBox#createInlineBoxes} static factory method. The Box
+	 * created here is only temporary, it will be replaced by the split method.
+	 *
+	 * @param context
+	 *            LayoutContext to use.
+	 * @param node
+	 *            Element that generated this box
+	 * @param startOffset
+	 *            Start offset of the range being rendered, which may be arbitrarily before or inside the element.
+	 * @param endOffset
+	 *            End offset of the range being rendered, which may be arbitrarily after or inside the element.
+	 */
+	public IncludeInlineBox(final LayoutContext context, final IIncludeNode node, final int startOffset, final int endOffset) {
+		this.node = node;
+		final Styles styles = context.getStyleSheet().getStyles(node.getReference());
+		final List<InlineBox> childList = new ArrayList<InlineBox>();
+
+		if (startOffset <= node.getStartOffset()) {
+			// space for the left margin/border/padding
+			final int space = styles.getMarginLeft().get(0) + styles.getBorderLeftWidth() + styles.getPaddingLeft().get(0);
+
+			if (space > 0) {
+				childList.add(new SpaceBox(space, 1));
+			}
+
+			// :before content
+			final IElement beforeElement = context.getStyleSheet().getPseudoElementBefore(node.getReference());
+			if (beforeElement != null) {
+				childList.addAll(LayoutUtils.createGeneratedInlines(context, beforeElement, StaticTextBox.START_MARKER));
+			}
+
+		}
+
+		if (endOffset > node.getEndOffset()) {
+			// :after content
+			final IElement afterElement = context.getStyleSheet().getPseudoElementAfter(node.getReference());
+			if (afterElement != null) {
+				childList.addAll(LayoutUtils.createGeneratedInlines(context, afterElement, StaticTextBox.END_MARKER));
+			}
+
+			// space for the right margin/border/padding
+			final int space = styles.getMarginRight().get(0) + styles.getBorderRightWidth() + styles.getPaddingRight().get(0);
+
+			if (space > 0) {
+				childList.add(new SpaceBox(space, 1));
+			}
+		}
+
+		if (childList.isEmpty()) {
+			// No pseudo element and no content - return something
+			childList.add(new StaticTextBox(context, node, CSS.INCLUDE, StaticTextBox.START_MARKER));
+		}
+
+		children = childList.toArray(new InlineBox[childList.size()]);
+	}
+
+	/**
+	 * Class constructor. This constructor is called by the split method.
+	 *
+	 * @param context
+	 *            LayoutContext used for the layout.
+	 * @param node
+	 *            Node to which this box applies.
+	 * @param children
+	 *            Child boxes.
+	 */
+	private IncludeInlineBox(final LayoutContext context, final IIncludeNode node, final InlineBox[] children) {
+		this.node = node;
+		this.children = children;
+		layout(context);
+		for (final InlineBox child : children) {
+			if (child.hasContent() && firstContentChild == null) {
+				firstContentChild = child;
+			}
+		}
+	}
+
+	private void layout(final LayoutContext context) {
+		final Graphics g = context.getGraphics();
+		final Styles styles = context.getStyleSheet().getStyles(node);
+		final FontResource font = g.createFont(styles.getFont());
+		final FontResource oldFont = g.setFont(font);
+		final FontMetrics fm = g.getFontMetrics();
+		setHeight(styles.getLineHeight());
+		final int halfLeading = (styles.getLineHeight() - fm.getAscent() - fm.getDescent()) / 2;
+		baseline = halfLeading + fm.getAscent();
+		g.setFont(oldFont);
+		font.dispose();
+
+		int x = 0;
+		for (final InlineBox child : children) {
+			// TODO: honour the child's vertical-align property
+			child.setX(x);
+			child.alignOnBaseline(baseline);
+			x += child.getWidth();
+		}
+
+		setWidth(x);
+	}
+
+	/**
+	 * Override to paint background and borders.
+	 *
+	 * @see org.eclipse.vex.core.internal.layout.AbstractBox#paint(org.eclipse.vex.core.internal.layout.LayoutContext,
+	 *      int, int)
+	 */
+	@Override
+	public void paint(final LayoutContext context, final int x, final int y) {
+		this.drawBox(context, x, y, 0, true);
+		super.paint(context, x, y);
+	}
+
+	/**
+	 * @see org.eclipse.vex.core.internal.layout.Box#getChildren()
+	 */
+	@Override
+	public Box[] getChildren() {
+		return children;
+	}
+
+	/**
+	 * Returns the element associated with this box.
+	 */
+	@Override
+	public INode getNode() {
+		return node;
+	}
+
+	/**
+	 * @see org.eclipse.vex.core.internal.layout.Box#getStartOffset()
+	 */
+	@Override
+	public int getStartOffset() {
+		return getNode().getStartOffset();
+	}
+
+	/**
+	 * @see org.eclipse.vex.core.internal.layout.Box#getEndOffset()
+	 */
+	@Override
+	public int getEndOffset() {
+		return getNode().getEndOffset();
+	}
+
+	@Override
+	public boolean hasContent() {
+		return node.isAssociated();
+	}
+
+	@Override
+	public boolean isAnonymous() {
+		return false;
+	}
+
+	@Override
+	public Caret getCaret(final LayoutContext context, final ContentPosition position) {
+		return new HCaret(0, getBaseline() + 1, H_CARET_LENGTH);
+	}
+
+	@Override
+	public int getBaseline() {
+		return baseline;
+	}
+
+	/**
+	 * @see org.eclipse.vex.core.internal.layout.Box#viewToModel(org.eclipse.vex.core.internal.layout.LayoutContext,
+	 *      int, int)
+	 */
+	@Override
+	public ContentPosition viewToModel(final LayoutContext context, final int x, final int y) {
+		return getNode().getStartPosition().moveBy(1);
+	}
+
+	@Override
+	public Pair split(final LayoutContext context, final InlineBox[] lefts, final InlineBox[] rights, final int remaining) {
+
+		IncludeInlineBox left = null;
+		IncludeInlineBox right = null;
+
+		if (lefts.length > 0 || rights.length == 0) {
+			left = new IncludeInlineBox(context, (IIncludeNode) getNode(), lefts);
+		}
+
+		if (rights.length > 0) {
+			// We reuse this element instead of creating a new one
+			children = rights;
+			for (final InlineBox child : children) {
+				if (child.hasContent()) {
+					// The lastContentChild is already set in this instance an did not change
+					firstContentChild = child;
+					break;
+				}
+			}
+			if (left == null && remaining >= 0) {
+				// There is no left box, and the right box fits without further splitting, so we have to calculate the size here
+				layout(context);
+			}
+			right = this;
+		}
+
+		return new Pair(left, right, remaining);
+	}
+}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/InlineBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/InlineBox.java
index 4531578..73ac0d0 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/InlineBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/InlineBox.java
@@ -26,7 +26,7 @@
 
 		/**
 		 * Class constructor.
-		 * 
+		 *
 		 * @param left
 		 *            box to the left of the split
 		 * @param right
@@ -87,19 +87,19 @@
 	 * (e.g. after a space) and return two boxes representing a split at that point. The width of the last box must not
 	 * exceed <code>maxWidth</code>. If no such natural split exists, null should be returned as the left box and
 	 * <code>this</code> returned as the right box.
-	 * 
+	 *
 	 * <p>
 	 * If <code>force</code> is true, it means we are adding the first inline box to a line, therefore we must return
 	 * something as the left box. In some cases, we may find a suboptimal split (e.g. between characters) that satisfies
 	 * this. In other cases, <code>this</code> should be returned as the left box even though it exceeds maxWidth.
 	 * </p>
-	 * 
+	 *
 	 * <p>
 	 * If the entire box fits within <code>maxWidth</code>, it should only be returned as the left box if it can end a
 	 * line; otherwise, it should be returned as the right box. Most implementations <i>cannot</i> end a line (one
 	 * notable exception being a text box ending in whitespace) and should therefore return themselves as the right box.
 	 * </p>
-	 * 
+	 *
 	 * @param context
 	 *            the layout context to be used.
 	 * @param maxWidth
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/InlineElementBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/InlineElementBox.java
index 61e1211..985fb99 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/InlineElementBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/InlineElementBox.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2013 John Krasnay and others.
+ * Copyright (c) 2004, 2014 John Krasnay 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
@@ -8,7 +8,7 @@
  * Contributors:
  *     John Krasnay - initial API and implementation
  *     Igor Jacy Lino Campista - Java 5 warnings fixed (bug 311325)
- *     Carsten Hiesserich - added support for processing instructions
+ *     Carsten Hiesserich - added support for processing instructions / includes
  *******************************************************************************/
 package org.eclipse.vex.core.internal.layout;
 
@@ -26,6 +26,7 @@
 import org.eclipse.vex.core.provisional.dom.ContentRange;
 import org.eclipse.vex.core.provisional.dom.IComment;
 import org.eclipse.vex.core.provisional.dom.IElement;
+import org.eclipse.vex.core.provisional.dom.IIncludeNode;
 import org.eclipse.vex.core.provisional.dom.INode;
 import org.eclipse.vex.core.provisional.dom.IProcessingInstruction;
 import org.eclipse.vex.core.provisional.dom.IText;
@@ -45,7 +46,7 @@
 	/**
 	 * Class constructor, called by the createInlineBoxes static factory method. The Box created here is only temporary,
 	 * it will be replaced by the split method.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext to use.
 	 * @param node
@@ -74,7 +75,7 @@
 			final boolean showLeftMarker = styles.getInlineMarker().equals(CSS.NORMAL);
 
 			// :before content
-			final IElement beforeElement = context.getStyleSheet().getPseudoElement(node, CSS.PSEUDO_BEFORE, true);
+			final IElement beforeElement = context.getStyleSheet().getPseudoElementBefore(node);
 			if (beforeElement != null) {
 				childList.addAll(LayoutUtils.createGeneratedInlines(context, beforeElement, showLeftMarker ? StaticTextBox.NO_MARKER : StaticTextBox.START_MARKER));
 			}
@@ -94,7 +95,6 @@
 
 		if (styles.isContentDefined()) {
 			// A CSS 'content' definition overrides the actual content
-			System.out.println(styles.getContent(node));
 			final String content = LayoutUtils.getGeneratedContent(context, styles, node);
 			final InlineBox child = new StaticTextBox(context, node, content);
 			childList.add(child);
@@ -117,7 +117,7 @@
 			}
 
 			// :after content
-			final IElement afterElement = context.getStyleSheet().getPseudoElement(node, CSS.PSEUDO_AFTER, true);
+			final IElement afterElement = context.getStyleSheet().getPseudoElementAfter(node);
 			if (afterElement != null) {
 				childList.addAll(LayoutUtils.createGeneratedInlines(context, afterElement, showRightMarker ? StaticTextBox.NO_MARKER : StaticTextBox.END_MARKER));
 			}
@@ -135,7 +135,7 @@
 
 	/**
 	 * Class constructor. This constructor is called by the split method.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext used for the layout.
 	 * @param node
@@ -160,6 +160,7 @@
 	/**
 	 * @see org.eclipse.vex.core.internal.layout.InlineBox#getBaseline()
 	 */
+	@Override
 	public int getBaseline() {
 		return baseline;
 	}
@@ -206,7 +207,7 @@
 
 	/**
 	 * Override to paint background and borders.
-	 * 
+	 *
 	 * @see org.eclipse.vex.core.internal.layout.AbstractBox#paint(org.eclipse.vex.core.internal.layout.LayoutContext,
 	 *      int, int)
 	 */
@@ -284,7 +285,7 @@
 	/**
 	 * Creates a list of inline boxes given a range of offsets. This method is used when creating both ParagraphBoxes
 	 * and InlineElementBoxes.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext to be used.
 	 * @param node
@@ -318,6 +319,13 @@
 						};
 
 						@Override
+						public void visit(final IIncludeNode include) {
+							addPlaceholderBox(result, new PlaceholderBox(context, node, include.getStartOffset() - node.getStartOffset()));
+							final InlineBox child = new IncludeInlineBox(context, include, range.getStartOffset(), range.getEndOffset());
+							addChildInlineBox(result, child);
+						}
+
+						@Override
 						public void visit(final IProcessingInstruction pi) {
 							addPlaceholderBox(result, new PlaceholderBox(context, node, pi.getStartOffset() - node.getStartOffset()));
 							final InlineBox child = new InlineElementBox(context, pi, range.getStartOffset(), range.getEndOffset());
@@ -376,6 +384,7 @@
 		final int size = Math.round(0.5f * styles.getFontSize());
 		final int lift = Math.round(0.1f * styles.getFontSize());
 		final Drawable drawable = new Drawable() {
+			@Override
 			public void draw(final Graphics g, final int x, int y) {
 				g.setLineStyle(Graphics.LINE_SOLID);
 				g.setLineWidth(1);
@@ -385,6 +394,7 @@
 				g.drawLine(x + size - 1, y - size / 2, x, y - size);
 			}
 
+			@Override
 			public Rectangle getBounds() {
 				return new Rectangle(0, -size, size, size);
 			}
@@ -396,6 +406,7 @@
 		final int size = Math.round(0.5f * styles.getFontSize());
 		final int lift = Math.round(0.1f * styles.getFontSize());
 		final Drawable drawable = new Drawable() {
+			@Override
 			public void draw(final Graphics g, final int x, int y) {
 				g.setLineStyle(Graphics.LINE_SOLID);
 				g.setLineWidth(1);
@@ -405,6 +416,7 @@
 				g.drawLine(x, y - size / 2, x + size - 1, y - size);
 			}
 
+			@Override
 			public Rectangle getBounds() {
 				return new Rectangle(0, -size, size, size);
 			}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/LayoutContext.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/LayoutContext.java
index ab8daf4..b04326f 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/LayoutContext.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/LayoutContext.java
@@ -82,7 +82,7 @@
 
 	/**
 	 * Helper method that returns true if the given node is in the selected range.
-	 * 
+	 *
 	 * @param node
 	 *            Node to test. May be null, in which case this method returns false.
 	 */
@@ -141,7 +141,7 @@
 
 	/**
 	 * Sets the offset where the current selection ends.
-	 * 
+	 *
 	 * @param i
 	 *            the new value for selectionEnd
 	 */
@@ -151,7 +151,7 @@
 
 	/**
 	 * Sets the offset where the current selection starts.
-	 * 
+	 *
 	 * @param i
 	 *            the new value for selectionStart
 	 */
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/LayoutUtils.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/LayoutUtils.java
index 1df48ae..e411d88 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/LayoutUtils.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/LayoutUtils.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2013 John Krasnay and others.
+ * Copyright (c) 2004, 2014 John Krasnay 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
@@ -21,7 +21,8 @@
 import org.eclipse.vex.core.internal.css.PseudoElement;
 import org.eclipse.vex.core.internal.css.StyleSheet;
 import org.eclipse.vex.core.internal.css.Styles;
-import org.eclipse.vex.core.provisional.dom.ContentRange;
+import org.eclipse.vex.core.provisional.dom.ContentPosition;
+import org.eclipse.vex.core.provisional.dom.ContentPositionRange;
 import org.eclipse.vex.core.provisional.dom.IElement;
 import org.eclipse.vex.core.provisional.dom.INode;
 import org.eclipse.vex.core.provisional.dom.IParent;
@@ -66,22 +67,6 @@
 	}
 
 	/**
-	 * Returns <code>true</code> if the given offset falls within the given element or range.
-	 *
-	 * @param elementOrRange
-	 *            Element or IntRange object representing a range of offsets.
-	 * @param offset
-	 *            Offset to test.
-	 */
-	public static boolean elementOrRangeContains(final Object elementOrRange, final int offset) {
-		if (elementOrRange instanceof IElement) {
-			return ((IElement) elementOrRange).containsOffset(offset);
-		} else {
-			return ((ContentRange) elementOrRange).contains(offset);
-		}
-	}
-
-	/**
 	 * Creates a string representing the generated content for the given node.
 	 *
 	 * @param context
@@ -118,7 +103,9 @@
 	 * @param callback
 	 *            DisplayStyleCallback through which the caller is notified of matching elements and non-matching
 	 *            ranges.
+	 * @deprecated Use the overload using ContentPosition instead
 	 */
+	@Deprecated
 	public static void iterateChildrenByDisplayStyle(final StyleSheet styleSheet, final Set<String> displayStyles, final IParent parent, final int startOffset, final int endOffset,
 			final ElementOrRangeCallback callback) {
 
@@ -174,6 +161,71 @@
 	 *            LayoutContext to use.
 	 * @param displayStyles
 	 *            Display types to be explicitly recognized.
+	 * @param parent
+	 *            Parent containing the children over which to iterate.
+	 * @param startPosition
+	 *            Starting position of the range containing nodes in which we're interested.
+	 * @param endPosition
+	 *            Ending position of the range containing nodes in which we're interested.
+	 * @param callback
+	 *            DisplayStyleCallback through which the caller is notified of matching elements and non-matching
+	 *            ranges.
+	 */
+	public static void iterateChildrenByDisplayStyle(final StyleSheet styleSheet, final Set<String> displayStyles, final IParent parent, final ContentPosition startPosition,
+			final ContentPosition endPosition, final ElementOrPositionRangeCallback callback) {
+
+		final List<INode> nonMatching = new ArrayList<INode>();
+
+		for (final INode node : parent.children()) {
+			if (node.getEndPosition().isBeforeOrEquals(startPosition)) {
+				continue;
+			} else if (node.getStartPosition().isAfterOrEquals(endPosition)) {
+				break;
+			} else {
+				if (node instanceof IElement) {
+					final IElement childElement = (IElement) node;
+					final String display = styleSheet.getStyles(childElement).getDisplay();
+					if (displayStyles.contains(display)) {
+						if (!nonMatching.isEmpty()) {
+							final INode firstNode = nonMatching.get(0);
+							final INode lastNode = nonMatching.get(nonMatching.size() - 1);
+							if (lastNode instanceof IElement) {
+								callback.onRange(parent, firstNode.getStartPosition(), lastNode.getStartPosition().moveBy(1));
+							} else {
+								callback.onRange(parent, firstNode.getStartPosition(), lastNode.getEndPosition());
+							}
+							nonMatching.clear();
+						}
+						callback.onElement(childElement, display);
+					} else {
+						nonMatching.add(node);
+					}
+				} else {
+					nonMatching.add(node);
+				}
+			}
+		}
+
+		if (!nonMatching.isEmpty()) {
+			final INode firstNode = nonMatching.get(0);
+			final INode lastNode = nonMatching.get(nonMatching.size() - 1);
+			if (lastNode instanceof IElement) {
+				callback.onRange(parent, firstNode.getStartPosition(), lastNode.getStartPosition().moveBy(1));
+			} else {
+				callback.onRange(parent, firstNode.getStartPosition(), lastNode.getStartPosition());
+			}
+		}
+	}
+
+	/**
+	 * Call the given callback for each child matching one of the given display styles. Any nodes that do not match one
+	 * of the given display types cause the onRange callback to be called, with a range covering all such contiguous
+	 * nodes.
+	 *
+	 * @param context
+	 *            LayoutContext to use.
+	 * @param displayStyles
+	 *            Display types to be explicitly recognized.
 	 * @param table
 	 *            Element containing the children over which to iterate.
 	 * @param callback
@@ -200,6 +252,7 @@
 	public static void iterateTableRows(final StyleSheet styleSheet, final IParent element, final int startOffset, final int endOffset, final ElementOrRangeCallback callback) {
 
 		iterateChildrenByDisplayStyle(styleSheet, NON_ROW_STYLES, element, startOffset, endOffset, new ElementOrRangeCallback() {
+			@Override
 			public void onElement(final IElement child, final String displayStyle) {
 				if (displayStyle.equals(CSS.TABLE_ROW_GROUP) || displayStyle.equals(CSS.TABLE_HEADER_GROUP) || displayStyle.equals(CSS.TABLE_FOOTER_GROUP)) {
 
@@ -210,6 +263,7 @@
 				}
 			}
 
+			@Override
 			public void onRange(final IParent parent, final int startOffset, final int endOffset) {
 				// iterate over rows in range
 				iterateChildrenByDisplayStyle(styleSheet, ROW_STYLES, element, startOffset, endOffset, callback);
@@ -218,14 +272,84 @@
 
 	}
 
+	public static void iterateTableRows(final StyleSheet styleSheet, final IParent element, final ContentPosition startPosition, final ContentPosition endPosition,
+			final ElementOrPositionRangeCallback callback) {
+
+		iterateChildrenByDisplayStyle(styleSheet, NON_ROW_STYLES, element, startPosition, endPosition, new ElementOrPositionRangeCallback() {
+			@Override
+			public void onElement(final IElement child, final String displayStyle) {
+				if (displayStyle.equals(CSS.TABLE_ROW_GROUP) || displayStyle.equals(CSS.TABLE_HEADER_GROUP) || displayStyle.equals(CSS.TABLE_FOOTER_GROUP)) {
+
+					// iterate rows in group
+					iterateChildrenByDisplayStyle(styleSheet, ROW_STYLES, child, child.getStartPosition().moveBy(1), child.getEndPosition(), callback);
+				} else {
+					// other element's can't contain rows
+				}
+			}
+
+			@Override
+			public void onRange(final IParent parent, final ContentPosition startPosition, final ContentPosition endPosition) {
+				// iterate over rows in range
+				iterateChildrenByDisplayStyle(styleSheet, ROW_STYLES, element, startPosition, startPosition, callback);
+			}
+		});
+
+	}
+
+	public static void iterateTableCells(final StyleSheet styleSheet, final IParent element, final ContentPosition startPosition, final ContentPosition endPosition,
+			final ElementOrPositionRangeCallback callback) {
+		iterateChildrenByDisplayStyle(styleSheet, CELL_STYLES, element, startPosition, endPosition, callback);
+	}
+
 	public static void iterateTableCells(final StyleSheet styleSheet, final IParent element, final int startOffset, final int endOffset, final ElementOrRangeCallback callback) {
 		iterateChildrenByDisplayStyle(styleSheet, CELL_STYLES, element, startOffset, endOffset, callback);
 	}
 
+	public static void iterateTableCells(final StyleSheet styleSheet, final IParent row, final ElementOrPositionRangeCallback callback) {
+		iterateChildrenByDisplayStyle(styleSheet, CELL_STYLES, row, row.getStartPosition(), row.getEndPosition(), callback);
+	}
+
 	public static void iterateTableCells(final StyleSheet styleSheet, final IParent row, final ElementOrRangeCallback callback) {
 		iterateChildrenByDisplayStyle(styleSheet, CELL_STYLES, row, row.getStartOffset(), row.getEndOffset(), callback);
 	}
 
+	public static class ElementOrRange {
+		private final IElement element;
+		private final ContentPositionRange range;
+
+		public ElementOrRange(final IElement element) {
+			this.element = element;
+			range = null;
+		}
+
+		public ElementOrRange(final ContentPositionRange range) {
+			this.range = range;
+			element = null;
+		}
+
+		public IElement getElement() {
+			return element;
+		}
+
+		public ContentPositionRange getRange() {
+			return range;
+		}
+
+		/**
+		 * Returns <code>true</code> if the given position falls within this element or range.
+		 *
+		 * @param position
+		 *            ContentPosition to test.
+		 */
+		public boolean contains(final ContentPosition position) {
+			if (element != null) {
+				return element.containsPosition(position);
+			} else {
+				return range.contains(position);
+			}
+		}
+	}
+
 	/**
 	 * Set of CSS display values that represent elements that can be children of table elements.
 	 */
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/LineBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/LineBox.java
index 8b90944..cfc0f11 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/LineBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/LineBox.java
@@ -4,12 +4,13 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
 package org.eclipse.vex.core.internal.layout;
 
+import org.eclipse.vex.core.provisional.dom.ContentPosition;
 import org.eclipse.vex.core.provisional.dom.INode;
 
 /**
@@ -25,7 +26,7 @@
 
 	/**
 	 * Class constructor.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext for this layout.
 	 * @param children
@@ -38,7 +39,7 @@
 
 	/**
 	 * Class constructor used by the split method.
-	 * 
+	 *
 	 * @param other
 	 *            Instance of LineBox that should be splitted.
 	 * @param context
@@ -51,12 +52,18 @@
 	private LineBox(final LineBox other, final LayoutContext context, final InlineBox[] children) {
 		node = other.node;
 		this.children = children;
+		//		final Box lastLeft = children[children.length - 1];
+		//		if (lastLeft instanceof DocumentTextBox) {
+		//			this.children = Arrays.copyOf(children, children.length + 1);
+		//			this.children[this.children.length - 1] = new PlaceholderBox(context, lastLeft.getNode(), lastLeft.getEndOffset() - lastLeft.getNode().getStartOffset() + 1);
+		//		}
 		layout(context);
 	}
 
 	/**
 	 * @see org.eclipse.vex.core.internal.layout.InlineBox#getBaseline()
 	 */
+	@Override
 	public int getBaseline() {
 		return baseline;
 	}
@@ -82,6 +89,10 @@
 		return lastContentChild.getEndOffset();
 	}
 
+	public ContentPosition getEndPosition() {
+		return new ContentPosition(lastContentChild.getNode(), lastContentChild.getEndOffset());
+	}
+
 	/**
 	 * @see org.eclipse.vex.core.internal.layout.Box#getStartOffset()
 	 */
@@ -90,6 +101,10 @@
 		return firstContentChild.getStartOffset();
 	}
 
+	public ContentPosition getStartPosition() {
+		return new ContentPosition(firstContentChild.getNode(), firstContentChild.getStartOffset());
+	}
+
 	/**
 	 * @see org.eclipse.vex.core.internal.layout.Box#hasContent()
 	 */
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/ListItemBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/ListItemBox.java
new file mode 100644
index 0000000..0698fae
--- /dev/null
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/ListItemBox.java
@@ -0,0 +1,176 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Florian Thienel 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:
+ * 		Florian Thienel - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.vex.core.internal.layout;
+
+import java.util.List;
+
+import org.eclipse.vex.core.internal.css.CSS;
+import org.eclipse.vex.core.internal.css.Styles;
+import org.eclipse.vex.core.provisional.dom.INode;
+import org.eclipse.vex.core.provisional.dom.IParent;
+
+/**
+ * @author Florian Thienel
+ */
+public class ListItemBox extends BlockElementBox {
+
+	// hspace between list-item bullet and block as fraction of font-size
+	private static final float BULLET_SPACE = 0.5f;
+
+	private BlockBox itemMarker;
+
+	public ListItemBox(final LayoutContext context, final BlockBox parent, final INode node) {
+		super(context, parent, node);
+	}
+
+	@Override
+	public void paint(final LayoutContext context, final int x, final int y) {
+		super.paint(context, x, y);
+
+		if (itemMarker != null) {
+			itemMarker.paint(context, x + itemMarker.getX(), y + itemMarker.getY());
+		}
+	}
+
+	@Override
+	protected int positionChildren(final LayoutContext context) {
+		final int repaintStart = super.positionChildren(context);
+
+		final Styles styles = context.getStyleSheet().getStyles(getNode());
+		if (itemMarker != null) {
+			final int x = -itemMarker.getWidth() - Math.round(BULLET_SPACE * styles.getFontSize());
+			int y = getFirstLineTop(context);
+			final LineBox firstLine = getFirstLine();
+			if (firstLine != null) {
+				y += firstLine.getBaseline() - itemMarker.getFirstLine().getBaseline();
+			}
+
+			itemMarker.setX(x);
+			itemMarker.setY(y);
+		}
+
+		return repaintStart;
+	}
+
+	@Override
+	public List<Box> createChildren(final LayoutContext context) {
+		final Styles styles = context.getStyleSheet().getStyles(getNode());
+		if (!styles.getListStyleType().equals(CSS.NONE)) {
+			itemMarker = createItemMarker(context, getNode());
+		}
+		return super.createChildren(context);
+	}
+
+	private static BlockBox createItemMarker(final LayoutContext context, final INode item) {
+		final Styles styles = context.getStyleSheet().getStyles(item);
+		final String listStyleType = styles.getListStyleType();
+		final float fontSize = styles.getFontSize();
+		if (listStyleType.equals(CSS.NONE)) {
+			return null;
+		}
+
+		final InlineBox markerInline;
+		if (isEnumeratedListStyleType(listStyleType)) {
+			markerInline = createEnumeratedMarker(context, item, listStyleType);
+		} else if (listStyleType.equals(CSS.CIRCLE)) {
+			markerInline = createCircleBullet(item, fontSize);
+		} else if (listStyleType.equals(CSS.SQUARE)) {
+			markerInline = createSquareBullet(item, fontSize);
+		} else {
+			markerInline = createDiscBullet(item, fontSize);
+		}
+
+		return ParagraphBox.create(context, item, new InlineBox[] { markerInline }, Integer.MAX_VALUE);
+	}
+
+	private static InlineBox createEnumeratedMarker(final LayoutContext context, final INode item, final String listStyleType) {
+		final String numberString = numberToString(getItemNumber(item), listStyleType);
+		return new StaticTextBox(context, item, numberString + ".");
+	}
+
+	private static InlineBox createCircleBullet(final INode node, final float fontSize) {
+		return new DrawableBox(new CircleBullet(fontSize), node);
+	}
+
+	private static InlineBox createDiscBullet(final INode node, final float fontSize) {
+		return new DrawableBox(new DiscBullet(fontSize), node);
+	}
+
+	private static InlineBox createSquareBullet(final INode node, final float fontSize) {
+		return new DrawableBox(new SquareBullet(fontSize), node);
+	}
+
+	private static int getItemNumber(final INode item) {
+		final IParent parent = item.getParent();
+
+		if (parent == null) {
+			return 1;
+		}
+
+		int number = 1;
+		for (final INode child : parent.children()) {
+			if (child == item) {
+				return number;
+			}
+			if (child.isKindOf(item)) {
+				number++;
+			}
+		}
+
+		throw new IllegalStateException();
+	}
+
+	private static String numberToString(final int number, final String listStyleType) {
+		if (listStyleType.equals(CSS.DECIMAL_LEADING_ZERO)) {
+			if (number < 10) {
+				return "0" + Integer.toString(number);
+			} else {
+				return Integer.toString(number);
+			}
+		} else if (listStyleType.equals(CSS.LOWER_ALPHA) || listStyleType.equals(CSS.LOWER_LATIN)) {
+			return numberAsAlpha(number);
+		} else if (listStyleType.equals(CSS.LOWER_ROMAN)) {
+			return numberAsRoman(number);
+		} else if (listStyleType.equals(CSS.UPPER_ALPHA) || listStyleType.equals(CSS.UPPER_LATIN)) {
+			return numberAsAlpha(number).toUpperCase();
+		} else if (listStyleType.equals(CSS.UPPER_ROMAN)) {
+			return numberAsRoman(number).toUpperCase();
+		} else {
+			return Integer.toString(number);
+		}
+	}
+
+	private static String numberAsAlpha(final int number) {
+		final String alphabet = "abcdefghijklmnopqrstuvwxyz";
+		return String.valueOf(alphabet.charAt((number - 1) % 26));
+	}
+
+	private static String numberAsRoman(final int number) {
+		final String[] ones = { "", "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix" };
+		final String[] tens = { "", "x", "xx", "xxx", "xl", "l", "lx", "lxx", "lxxx", "xc" };
+		final String[] hundreds = { "", "c", "cc", "ccc", "cd", "d", "dc", "dcc", "dccc", "cm" };
+		final StringBuilder romanNumber = new StringBuilder();
+		for (int i = 0; i < number / 1000; i++) {
+			romanNumber.append("m");
+		}
+		romanNumber.append(hundreds[number / 100 % 10]);
+		romanNumber.append(tens[number / 10 % 10]);
+		romanNumber.append(ones[number % 10]);
+		return romanNumber.toString();
+	}
+
+	private static boolean isEnumeratedListStyleType(final String s) {
+		return s.equals(CSS.ARMENIAN) || s.equals(CSS.CJK_IDEOGRAPHIC) || s.equals(CSS.DECIMAL) || s.equals(CSS.DECIMAL_LEADING_ZERO) || s.equals(CSS.GEORGIAN) || s.equals(CSS.HEBREW)
+				|| s.equals(CSS.HIRAGANA) || s.equals(CSS.HIRAGANA_IROHA) || s.equals(CSS.KATAKANA) || s.equals(CSS.KATAKANA_IROHA) || s.equals(CSS.LOWER_ALPHA) || s.equals(CSS.LOWER_GREEK)
+				|| s.equals(CSS.LOWER_LATIN) || s.equals(CSS.LOWER_ROMAN) || s.equals(CSS.UPPER_ALPHA) || s.equals(CSS.UPPER_LATIN) || s.equals(CSS.UPPER_ROMAN);
+	}
+
+}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/NodeBlockBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/NodeBlockBox.java
index 7b24e53..1217b00 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/NodeBlockBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/NodeBlockBox.java
@@ -4,7 +4,7 @@
  * 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:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

@@ -14,7 +14,6 @@
 import java.util.List;

 

 import org.eclipse.vex.core.internal.VEXCorePlugin;

-import org.eclipse.vex.core.internal.css.CSS;

 import org.eclipse.vex.core.internal.css.StyleSheet;

 import org.eclipse.vex.core.provisional.dom.IElement;

 import org.eclipse.vex.core.provisional.dom.INode;

@@ -48,7 +47,7 @@
 		final List<InlineBox> pendingInlines = new ArrayList<InlineBox>();

 

 		// :before content - includes the target

-		final IElement before = styleSheet.getPseudoElement(node, CSS.PSEUDO_BEFORE, true);

+		final IElement before = styleSheet.getPseudoElementBefore(node);

 		if (before != null) {

 			pendingInlines.addAll(LayoutUtils.createGeneratedInlines(context, before, StaticTextBox.START_MARKER));

 		}

@@ -62,7 +61,7 @@
 		pendingInlines.add(new PlaceholderBox(context, node, node.getEndOffset() - node.getStartOffset()));

 

 		// :after content

-		final IElement after = styleSheet.getPseudoElement(node, CSS.PSEUDO_AFTER, true);

+		final IElement after = styleSheet.getPseudoElementAfter(node);

 		if (after != null) {

 			pendingInlines.addAll(LayoutUtils.createGeneratedInlines(context, after, StaticTextBox.END_MARKER));

 		}

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/ParagraphBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/ParagraphBox.java
index eecb0d0..86145f4 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/ParagraphBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/ParagraphBox.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *     Igor Jacy Lino Campista - Java 5 warnings fixed (bug 311325)
@@ -17,6 +17,7 @@
 import org.eclipse.vex.core.internal.core.Caret;
 import org.eclipse.vex.core.internal.css.CSS;
 import org.eclipse.vex.core.internal.css.Styles;
+import org.eclipse.vex.core.provisional.dom.ContentPosition;
 import org.eclipse.vex.core.provisional.dom.INode;
 
 /**
@@ -24,17 +25,21 @@
  */
 public class ParagraphBox extends AbstractBox implements BlockBox {
 
+	private final INode node;
 	private final LineBox[] children;
 	private LineBox firstContentLine;
 	private LineBox lastContentLine;
 
 	/**
 	 * Class constructor.
-	 * 
+	 *
 	 * @param children
 	 *            Line boxes that comprise the paragraph.
+	 * @param node
+	 *            The node that this paragraph is associated to
 	 */
-	private ParagraphBox(final LineBox[] children) {
+	private ParagraphBox(final LineBox[] children, final INode node) {
+		this.node = node;
 		this.children = children;
 		for (final LineBox element : children) {
 			if (element.hasContent()) {
@@ -48,7 +53,7 @@
 
 	/**
 	 * Create a paragraph by word-wrapping a list of inline boxes.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext used for this layout.
 	 * @param node
@@ -65,7 +70,7 @@
 
 	/**
 	 * Create a paragraph by word-wrapping a list of inline boxes.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext used for this layout
 	 * @param node
@@ -115,7 +120,7 @@
 			actualWidth = Math.max(actualWidth, lineBox.getWidth());
 		}
 
-		final ParagraphBox para = new ParagraphBox(lines.toArray(new LineBox[lines.size()]));
+		final ParagraphBox para = new ParagraphBox(lines.toArray(new LineBox[lines.size()]), node);
 		para.setWidth(actualWidth);
 		para.setHeight(y);
 
@@ -126,10 +131,10 @@
 	 * @see org.eclipse.vex.core.internal.layout.Box#getCaret(org.eclipse.vex.core.internal.layout.LayoutContext, int)
 	 */
 	@Override
-	public Caret getCaret(final LayoutContext context, final int offset) {
+	public Caret getCaret(final LayoutContext context, final ContentPosition position) {
 
-		final LineBox line = getLineAt(offset);
-		final Caret caret = line.getCaret(context, offset);
+		final LineBox line = getLineAt(position);
+		final Caret caret = line.getCaret(context, position);
 		caret.translate(line.getX(), line.getY());
 		return caret;
 
@@ -141,6 +146,11 @@
 	}
 
 	@Override
+	public INode getNode() {
+		return node;
+	}
+
+	@Override
 	public int getEndOffset() {
 		return lastContentLine.getEndOffset();
 	}
@@ -148,6 +158,7 @@
 	/**
 	 * @see org.eclipse.vex.core.internal.layout.BlockBox#getFirstLine()
 	 */
+	@Override
 	public LineBox getFirstLine() {
 		if (children.length == 0) {
 			return null;
@@ -159,6 +170,7 @@
 	/**
 	 * @see org.eclipse.vex.core.internal.layout.BlockBox#getLastLine()
 	 */
+	@Override
 	public LineBox getLastLine() {
 		if (children.length == 0) {
 			return null;
@@ -169,72 +181,83 @@
 
 	/**
 	 * Returns the LineBox at the given offset.
-	 * 
+	 *
 	 * @param offset
 	 *            the offset to check.
 	 */
-	public LineBox getLineAt(final int offset) {
+	public LineBox getLineAt(final ContentPosition linePosition) {
 		final LineBox[] children = this.children;
 		for (final LineBox element : children) {
-			if (element.hasContent() && offset <= element.getEndOffset()) {
+			// When the position is at the end of a line (isLineEnd() == true), we return the line that ends BEFORE the given position
+			final int endOffset = element.getEndOffset();
+			if (element.hasContent() && linePosition.getOffset() <= endOffset) {
 				return element;
 			}
 		}
 		return lastContentLine;
 	}
 
-	public int getLineEndOffset(final int offset) {
-		return getLineAt(offset).getEndOffset();
+	@Override
+	public ContentPosition getLineEndPosition(final ContentPosition linePosition) {
+		return getLineAt(linePosition).getEndPosition();
 	}
 
-	public int getLineStartOffset(final int offset) {
-		return getLineAt(offset).getStartOffset();
+	@Override
+	public ContentPosition getLineStartPosition(final ContentPosition linePosition) {
+		return getLineAt(linePosition).getStartPosition();
 	}
 
+	@Override
 	public int getMarginBottom() {
 		return 0;
 	}
 
+	@Override
 	public int getMarginTop() {
 		return 0;
 	}
 
-	public int getNextLineOffset(final LayoutContext context, final int offset, final int x) {
+	@Override
+	public ContentPosition getNextLinePosition(final LayoutContext context, final ContentPosition linePosition, final int x) {
 		LineBox nextLine = null;
 		final LineBox[] children = this.children;
 		for (final LineBox element : children) {
-			if (element.hasContent() && element.getStartOffset() > offset) {
+			if (element.hasContent() && element.getStartOffset() > linePosition.getOffset()) {
 				nextLine = element;
 				break;
 			}
 		}
-		if (nextLine == null) {
-			// return this.getEndOffset() + 1;
-			return -1;
-		} else {
+
+		if (nextLine != null) {
 			return nextLine.viewToModel(context, x - nextLine.getX(), 0);
 		}
+
+		// No next line - let the parent handle this
+		return null;
 	}
 
+	@Override
 	public BlockBox getParent() {
 		throw new IllegalStateException("ParagraphBox does not currently track parent");
 	}
 
-	public int getPreviousLineOffset(final LayoutContext context, final int offset, final int x) {
+	@Override
+	public ContentPosition getPreviousLinePosition(final LayoutContext context, final ContentPosition linePosition, final int x) {
 		LineBox prevLine = null;
 		final LineBox[] children = this.children;
 		for (int i = children.length - 1; i >= 0; i--) {
-			if (children[i].hasContent() && children[i].getEndOffset() < offset) {
+			if (children[i].hasContent() && children[i].getEndOffset() < linePosition.getOffset()) {
 				prevLine = children[i];
 				break;
 			}
 		}
-		if (prevLine == null) {
-			// return this.getStartOffset() - 1;
-			return -1;
-		} else {
+
+		if (prevLine != null) {
 			return prevLine.viewToModel(context, x - prevLine.getX(), 0);
 		}
+
+		// No next line - let the parent handle this
+		return null;
 	}
 
 	@Override
@@ -247,14 +270,23 @@
 		return firstContentLine != null && firstContentLine.hasContent();
 	}
 
+	@Override
 	public VerticalRange layout(final LayoutContext context, final int top, final int bottom) {
 		return null;
 	}
 
+	@Override
 	public void invalidate(final boolean direct) {
 		throw new IllegalStateException("invalidate called on a non-element BlockBox");
 	}
 
+	@Override
+	public boolean isAnonymous() {
+		// This box stores the node only to return it in an ContentPosition
+		return true;
+	}
+
+	@Override
 	public void setInitialSize(final LayoutContext context) {
 		// NOP - size calculated in factory method
 	}
@@ -265,7 +297,7 @@
 	}
 
 	@Override
-	public int viewToModel(final LayoutContext context, final int x, final int y) {
+	public ContentPosition viewToModel(final LayoutContext context, final int x, final int y) {
 
 		final LineBox[] children = this.children;
 		for (final LineBox child : children) {
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/PlaceholderBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/PlaceholderBox.java
index 0e7f54c..8581c82 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/PlaceholderBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/PlaceholderBox.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -15,6 +15,7 @@
 import org.eclipse.vex.core.internal.core.FontResource;
 import org.eclipse.vex.core.internal.core.Graphics;
 import org.eclipse.vex.core.internal.css.Styles;
+import org.eclipse.vex.core.provisional.dom.ContentPosition;
 import org.eclipse.vex.core.provisional.dom.INode;
 
 /**
@@ -29,7 +30,7 @@
 
 	/**
 	 * Class constructor.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext in effect.
 	 * @param node
@@ -64,6 +65,7 @@
 	/**
 	 * @see org.eclipse.vex.core.internal.layout.InlineBox#getBaseline()
 	 */
+	@Override
 	public int getBaseline() {
 		return baseline;
 	}
@@ -72,7 +74,7 @@
 	 * @see org.eclipse.vex.core.internal.layout.Box#getCaret(org.eclipse.vex.core.internal.layout.LayoutContext, int)
 	 */
 	@Override
-	public Caret getCaret(final LayoutContext context, final int offset) {
+	public Caret getCaret(final LayoutContext context, final ContentPosition position) {
 		return new TextCaret(0, 0, getHeight());
 	}
 
@@ -108,6 +110,7 @@
 		return true;
 	}
 
+	@Override
 	public boolean isEOL() {
 		return false;
 	}
@@ -125,8 +128,8 @@
 	 *      int, int)
 	 */
 	@Override
-	public int viewToModel(final LayoutContext context, final int x, final int y) {
-		return getStartOffset();
+	public ContentPosition viewToModel(final LayoutContext context, final int x, final int y) {
+		return new ContentPosition(getNode(), getStartOffset());
 	}
 
 }
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/RootBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/RootBox.java
index bd82e25..d8766cc 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/RootBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/RootBox.java
@@ -4,16 +4,16 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
 package org.eclipse.vex.core.internal.layout;
 
-import org.eclipse.vex.core.internal.VEXCorePlugin;
 import org.eclipse.vex.core.internal.core.Caret;
 import org.eclipse.vex.core.internal.core.Insets;
 import org.eclipse.vex.core.internal.core.Rectangle;
+import org.eclipse.vex.core.provisional.dom.ContentPosition;
 import org.eclipse.vex.core.provisional.dom.IDocument;
 import org.eclipse.vex.core.provisional.dom.INode;
 
@@ -28,7 +28,7 @@
 
 	/**
 	 * Class constructor.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext used to create children.
 	 * @param document
@@ -53,8 +53,8 @@
 	 * @see org.eclipse.vex.core.internal.layout.Box#getCaret(org.eclipse.vex.core.internal.layout.LayoutContext, int)
 	 */
 	@Override
-	public Caret getCaret(final LayoutContext context, final int offset) {
-		final Caret caret = childBox.getCaret(context, offset);
+	public Caret getCaret(final LayoutContext context, final ContentPosition position) {
+		final Caret caret = childBox.getCaret(context, position);
 		caret.translate(childBox.getX(), childBox.getY());
 		return caret;
 	}
@@ -83,6 +83,7 @@
 	/**
 	 * @see org.eclipse.vex.core.internal.layout.BlockBox#getFirstLine()
 	 */
+	@Override
 	public LineBox getFirstLine() {
 		return childBox.getFirstLine();
 	}
@@ -90,36 +91,46 @@
 	/**
 	 * @see org.eclipse.vex.core.internal.layout.BlockBox#getLastLine()
 	 */
+	@Override
 	public LineBox getLastLine() {
 		return childBox.getLastLine();
 	}
 
-	public int getLineEndOffset(final int offset) {
-		return childBox.getLineEndOffset(offset);
+	@Override
+	public ContentPosition getLineEndPosition(final ContentPosition linePosition) {
+		return childBox.getLineEndPosition(linePosition);
 	}
 
-	public int getLineStartOffset(final int offset) {
-		return childBox.getLineStartOffset(offset);
+	@Override
+	public ContentPosition getLineStartPosition(final ContentPosition linePosition) {
+		return childBox.getLineStartPosition(linePosition);
 	}
 
+	@Override
 	public int getMarginBottom() {
 		return 0;
 	}
 
+	@Override
 	public int getMarginTop() {
 		return 0;
 	}
 
-	public int getNextLineOffset(final LayoutContext context, final int offset, final int x) {
-		return childBox.getNextLineOffset(context, offset, x - childBox.getX());
+	@Override
+	public ContentPosition getNextLinePosition(final LayoutContext context, final ContentPosition linePosition, final int x) {
+		final ContentPosition position = childBox.getNextLinePosition(context, linePosition, x - childBox.getX());
+		return position != null ? position : new ContentPosition(getNode(), getEndOffset());
 	}
 
+	@Override
 	public BlockBox getParent() {
 		throw new IllegalStateException("RootBox does not have a parent");
 	}
 
-	public int getPreviousLineOffset(final LayoutContext context, final int offset, final int x) {
-		return childBox.getPreviousLineOffset(context, offset, x - childBox.getX());
+	@Override
+	public ContentPosition getPreviousLinePosition(final LayoutContext context, final ContentPosition linePosition, final int x) {
+		final ContentPosition position = childBox.getPreviousLinePosition(context, linePosition, x - childBox.getX());
+		return position != null ? position : new ContentPosition(getNode(), getStartOffset() + 1);
 	}
 
 	/**
@@ -130,28 +141,18 @@
 		return childBox.getStartOffset();
 	}
 
+	@Override
 	public void invalidate(final boolean direct) {
 		// do nothing. layout is always propagated to our child box.
 	}
 
+	@Override
 	public VerticalRange layout(final LayoutContext context, final int top, final int bottom) {
 
 		final Insets insets = this.getInsets(context, getWidth());
 
-		long start = 0;
-		if (VEXCorePlugin.getInstance().isDebugging()) {
-			start = System.currentTimeMillis();
-		}
-
 		final VerticalRange repaintRange = childBox.layout(context, top - insets.getTop(), bottom - insets.getBottom());
 
-		if (VEXCorePlugin.getInstance().isDebugging()) {
-			final long end = System.currentTimeMillis();
-			if (end - start > 50) {
-				System.out.println("RootBox.layout took " + (end - start) + "ms");
-			}
-		}
-
 		setHeight(childBox.getHeight() + insets.getTop() + insets.getBottom());
 
 		if (repaintRange != null) {
@@ -163,12 +164,12 @@
 
 	/*
 	 * (non-Javadoc)
-	 * 
+	 *
 	 * @see org.eclipse.vex.core.internal.layout.AbstractBox#viewToModel(
 	 * org.eclipse.vex.core.internal.layout.LayoutContext, int, int)
 	 */
 	@Override
-	public int viewToModel(final LayoutContext context, final int x, final int y) {
+	public ContentPosition viewToModel(final LayoutContext context, final int x, final int y) {
 		return childBox.viewToModel(context, x - childBox.getX(), y - childBox.getY());
 	}
 
@@ -183,6 +184,7 @@
 		}
 	}
 
+	@Override
 	public void setInitialSize(final LayoutContext context) {
 		throw new IllegalStateException();
 	}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/SpaceBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/SpaceBox.java
index 3ded483..e78228d 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/SpaceBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/SpaceBox.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -17,7 +17,7 @@
 
 	/**
 	 * Class constructor.
-	 * 
+	 *
 	 * @param width
 	 *            width of the box
 	 * @param height
@@ -31,10 +31,12 @@
 	/**
 	 * @see org.eclipse.vex.core.internal.layout.InlineBox#getBaseline()
 	 */
+	@Override
 	public int getBaseline() {
 		return getHeight();
 	}
 
+	@Override
 	public boolean isEOL() {
 		return false;
 	}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/SquareBullet.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/SquareBullet.java
new file mode 100644
index 0000000..ff83e22
--- /dev/null
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/SquareBullet.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Florian Thienel 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:
+ * 		Florian Thienel - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.vex.core.internal.layout;
+
+import org.eclipse.vex.core.internal.core.Graphics;
+import org.eclipse.vex.core.internal.core.Rectangle;
+
+/**
+ * @author Florian Thienel
+ */
+public class SquareBullet extends Bullet {
+
+	public SquareBullet(final float fontSize) {
+		super(fontSize);
+	}
+
+	@Override
+	public void draw(final Graphics g, final int x, final int y) {
+		g.setLineStyle(Graphics.LINE_SOLID);
+		g.setLineWidth(1);
+		g.drawRect(x, y - size - lift, size, size);
+	}
+
+	@Override
+	public Rectangle getBounds() {
+		return new Rectangle(0, -size - lift, size, size);
+	}
+
+}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/StaticTextBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/StaticTextBox.java
index 8654b51..2f62f83 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/StaticTextBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/StaticTextBox.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -34,7 +34,7 @@
 
 	/**
 	 * Class constructor.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext used to calculate the box's size.
 	 * @param node
@@ -53,7 +53,7 @@
 	 * Class constructor. This constructor is used when generating a static text box representing a marker for the start
 	 * or end of an inline element. If the selection spans the related marker, the text is drawn in the platform's text
 	 * selection colours.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext used to calculate the box's size
 	 * @param node
@@ -76,7 +76,7 @@
 
 	/**
 	 * Class constructor used by the splitAt method.
-	 * 
+	 *
 	 * @param other
 	 *            Instance of DocumentTextBox that should be splitted.
 	 * @param endOffset
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableBodyBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableBodyBox.java
index ec3b99c..5a59791 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableBodyBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableBodyBox.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *     Igor Jacy Lino Campista - Java 5 warnings fixed (bug 311325)
@@ -43,10 +43,12 @@
 		final List<Box> children = new ArrayList<Box>();
 
 		iterateChildrenByDisplayStyle(context.getStyleSheet(), childDisplayStyles, new ElementOrRangeCallback() {
+			@Override
 			public void onElement(final IElement child, final String displayStyle) {
 				children.add(new TableRowGroupBox(context, TableBodyBox.this, child));
 			}
 
+			@Override
 			public void onRange(final IParent parent, final int startOffset, final int endOffset) {
 				children.add(new TableRowGroupBox(context, TableBodyBox.this, startOffset, endOffset));
 			}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableBox.java
index e0933d1..65e94bc 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableBox.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *     Igor Jacy Lino Campista - Java 5 warnings fixed (bug 311325)
@@ -32,7 +32,7 @@
 
 	/**
 	 * Class constructor.
-	 * 
+	 *
 	 * @param node
 	 *            Element represented by this box.
 	 */
@@ -61,7 +61,7 @@
 		// :before content
 		if (!isAnonymous()) {
 			// This might be an anonymous box if we have nested TABLE-ROW-GROUP's
-			final IElement before = styleSheet.getPseudoElement(node, CSS.PSEUDO_BEFORE, true);
+			final IElement before = styleSheet.getPseudoElementBefore(node);
 			if (before != null) {
 				// before element of tables is always displayed as block
 				children.add(new BlockPseudoElementBox(context, before, this, width));
@@ -69,10 +69,12 @@
 		}
 
 		iterateChildrenByDisplayStyle(context.getStyleSheet(), captionOrColumnStyles, new ElementOrRangeCallback() {
+			@Override
 			public void onElement(final IElement child, final String displayStyle) {
 				children.add(new BlockElementBox(context, TableBox.this, child));
 			}
 
+			@Override
 			public void onRange(final IParent parent, final int startOffset, final int endOffset) {
 				children.add(new TableBodyBox(context, TableBox.this, startOffset, endOffset));
 			}
@@ -80,7 +82,7 @@
 
 		// :after content
 		if (!isAnonymous()) {
-			final IElement after = styleSheet.getPseudoElement(node, CSS.PSEUDO_AFTER, true);
+			final IElement after = styleSheet.getPseudoElementAfter(node);
 			if (after != null) {
 				children.add(new BlockPseudoElementBox(context, after, this, width));
 			}
@@ -167,10 +169,12 @@
 			count = 0;
 		}
 
+		@Override
 		public void onElement(final IElement child, final String displayStyle) {
 			count++;
 		}
 
+		@Override
 		public void onRange(final IParent parent, final int startOffset, final int endOffset) {
 			count++;
 		}
@@ -185,17 +189,19 @@
 
 		final IParent tableElement = findContainingParent();
 		final int[] columnCounts = new int[1]; // work around Java's insistence
-												// on final
+		// on final
 		columnCounts[0] = 0;
 		final StyleSheet styleSheet = context.getStyleSheet();
 		final CountingCallback callback = new CountingCallback();
 		LayoutUtils.iterateTableRows(styleSheet, tableElement, getStartOffset(), getEndOffset(), new ElementOrRangeCallback() {
+			@Override
 			public void onElement(final IElement child, final String displayStyle) {
 				LayoutUtils.iterateTableCells(styleSheet, child, callback);
 				columnCounts[0] = Math.max(columnCounts[0], callback.getCount());
 				callback.reset();
 			}
 
+			@Override
 			public void onRange(final IParent parent, final int startOffset, final int endOffset) {
 				LayoutUtils.iterateTableCells(styleSheet, parent, startOffset, endOffset, callback);
 				columnCounts[0] = Math.max(columnCounts[0], callback.getCount());
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableCellBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableCellBox.java
index 91002ec..4ae5577 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableCellBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableCellBox.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *     Igor Jacy Lino Campista - Java 5 warnings fixed (bug 311325)
@@ -23,7 +23,7 @@
 
 	/**
 	 * Class constructor for non-anonymous table cells.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext to use.
 	 * @param parent
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableRowBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableRowBox.java
index dffdcc0..2a2b68a 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableRowBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableRowBox.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *     Igor Jacy Lino Campista - Java 5 warnings fixed (bug 311325)
@@ -16,6 +16,7 @@
 
 import org.eclipse.vex.core.internal.core.Caret;
 import org.eclipse.vex.core.internal.core.Insets;
+import org.eclipse.vex.core.provisional.dom.ContentPosition;
 import org.eclipse.vex.core.provisional.dom.IElement;
 import org.eclipse.vex.core.provisional.dom.IParent;
 
@@ -43,10 +44,12 @@
 		LayoutUtils.iterateTableCells(context.getStyleSheet(), parent, getStartOffset(), getEndOffset(), new ElementOrRangeCallback() {
 			private int column = 0;
 
+			@Override
 			public void onElement(final IElement child, final String displayStyle) {
 				children.add(new TableCellBox(context, TableRowBox.this, child, widths[column++]));
 			}
 
+			@Override
 			public void onRange(final IParent parent, final int startOffset, final int endOffset) {
 				children.add(new TableCellBox(context, TableRowBox.this, startOffset, endOffset, widths[column++]));
 			}
@@ -69,7 +72,7 @@
 	}
 
 	@Override
-	public Caret getCaret(final LayoutContext context, final int offset) {
+	public Caret getCaret(final LayoutContext context, final ContentPosition position) {
 
 		final int hSpacing = getTableBox().getHorizonalSpacing();
 
@@ -77,7 +80,7 @@
 
 		// If we haven't yet laid out this block, estimate the caret.
 		if (children == null) {
-			final int relative = offset - getStartOffset();
+			final int relative = position.getOffset() - getStartOffset();
 			final int size = getEndOffset() - getStartOffset();
 			int y = 0;
 			if (size > 0) {
@@ -100,13 +103,13 @@
 				continue;
 			}
 
-			if (offset < child.getStartOffset()) {
+			if (position.getOffset() < child.getStartOffset()) {
 				return new TextCaret(x, 0, getHeight());
 			}
 
-			if (offset >= child.getStartOffset() && offset <= child.getEndOffset()) {
+			if (position.getOffset() >= child.getStartOffset() && position.getOffset() <= child.getEndOffset()) {
 
-				final Caret caret = child.getCaret(context, offset);
+				final Caret caret = child.getCaret(context, position);
 				caret.translate(child.getX(), child.getY());
 				return caret;
 			}
@@ -136,47 +139,50 @@
 	}
 
 	@Override
-	public int getNextLineOffset(final LayoutContext context, final int offset, final int x) {
+	public ContentPosition getNextLinePosition(final LayoutContext context, final ContentPosition linePosition, final int x) {
 
-		final BlockBox[] children = getContentChildren();
+		final BlockBox[] children = getChildrenWithContent();
 		final int[] widths = getTableBox().getColumnWidths();
 		int leftEdge = 0;
 
 		for (int i = 0; i < children.length; i++) {
 			if (leftEdge + widths[i] > x) {
-				final int newOffset = children[i].getNextLineOffset(context, offset, x - leftEdge);
-				if (newOffset == children[i].getEndOffset() + 1) {
-					return -1;
+				final ContentPosition newPosition = children[i].getNextLinePosition(context, linePosition, x - leftEdge);
+				if (newPosition != null && newPosition.getOffset() == children[i].getEndOffset() + 1) {
+					// No next line in cell - let the parent find the next row
+					return null;
 				} else {
-					return newOffset;
+					return newPosition;
 				}
 			}
 			leftEdge += widths[i];
 		}
 
-		return -1;
+		return null;
 	}
 
 	@Override
-	public int getPreviousLineOffset(final LayoutContext context, final int offset, final int x) {
+	public ContentPosition getPreviousLinePosition(final LayoutContext context, final ContentPosition linePosition, final int x) {
 
-		final BlockBox[] children = getContentChildren();
+		final BlockBox[] children = getChildrenWithContent();
 		final int[] widths = getTableBox().getColumnWidths();
 		int leftEdge = 0;
 
 		for (int i = 0; i < children.length; i++) {
+			// find the cell at the given x position
 			if (leftEdge + widths[i] > x) {
-				final int newOffset = children[i].getPreviousLineOffset(context, offset, x - leftEdge);
-				if (newOffset == children[i].getStartOffset() - 1) {
-					return -1;
-				} else {
-					return newOffset;
+				// This may return null if the cell has no previous line
+				final ContentPosition newPosition = children[i].getPreviousLinePosition(context, linePosition, x - leftEdge);
+				if (newPosition != null && newPosition.getOffset() == children[i].getStartOffset() - 1) {
+					// No previous line in cell - let the parent find the previous row
+					return null;
 				}
+				return newPosition;
 			}
 			leftEdge += widths[i];
 		}
 
-		return -1;
+		return null;
 	}
 
 	/**
@@ -222,7 +228,7 @@
 	}
 
 	@Override
-	public int viewToModel(final LayoutContext context, final int x, final int y) {
+	public ContentPosition viewToModel(final LayoutContext context, final int x, final int y) {
 
 		final Box[] children = getChildren();
 		if (children == null) {
@@ -235,7 +241,7 @@
 			}
 
 			if (x < child.getX()) {
-				return child.getStartOffset() - 1;
+				return child.getNode().getStartPosition().moveBy(-1);
 			}
 
 			if (x < child.getX() + child.getWidth()) {
@@ -243,7 +249,7 @@
 			}
 		}
 
-		return getEndOffset();
+		return getNode().getEndPosition().copy();
 	}
 
 }
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableRowGroupBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableRowGroupBox.java
index 53643aa..2ef7e6a 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableRowGroupBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableRowGroupBox.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *     Igor Jacy Lino Campista - Java 5 warnings fixed (bug 311325)
@@ -31,7 +31,7 @@
 
 	/**
 	 * Class constructor for non-anonymous table row groups.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext to use.
 	 * @param parent
@@ -45,7 +45,7 @@
 
 	/**
 	 * Class constructor for anonymous table row groups.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext to use.
 	 * @param parent
@@ -71,10 +71,12 @@
 		final List<Box> children = new ArrayList<Box>();
 
 		iterateChildrenByDisplayStyle(context.getStyleSheet(), childDisplayStyles, new ElementOrRangeCallback() {
+			@Override
 			public void onElement(final IElement child, final String displayStyle) {
 				children.add(new TableRowBox(context, TableRowGroupBox.this, child));
 			}
 
+			@Override
 			public void onRange(final IParent parent, final int startOffset, final int endOffset) {
 				children.add(new TableRowBox(context, TableRowGroupBox.this, startOffset, endOffset));
 			}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TextBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TextBox.java
index f975164..35566ae 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TextBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TextBox.java
@@ -18,6 +18,7 @@
 import org.eclipse.vex.core.internal.core.FontSpec;
 import org.eclipse.vex.core.internal.core.Graphics;
 import org.eclipse.vex.core.internal.css.Styles;
+import org.eclipse.vex.core.provisional.dom.ContentPosition;
 import org.eclipse.vex.core.provisional.dom.INode;
 
 /**
@@ -34,7 +35,7 @@
 
 	/**
 	 * Class constructor.
-	 * 
+	 *
 	 * @param node
 	 *            Node containing the text. This is used for styling information.
 	 */
@@ -45,7 +46,7 @@
 	/**
 	 * Causes the box to recalculate it size. Subclasses should call this from their constructors after they are
 	 * initialized.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext used to calculate size. The correct font has to be set in the context's graphics before
 	 *            calling this method.
@@ -75,7 +76,7 @@
 	/**
 	 * Causes the box to recalculate its height and baseline. Subclasses should call this from their constructors after
 	 * they are initialized.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext used to calculate size.
 	 */
@@ -100,6 +101,7 @@
 	/**
 	 * @see org.eclipse.vex.core.internal.layout.InlineBox#getBaseline()
 	 */
+	@Override
 	public int getBaseline() {
 		return baseline;
 	}
@@ -115,14 +117,14 @@
 	 * @see org.eclipse.vex.core.internal.layout.Box#getCaret(org.eclipse.vex.core.internal.layout.LayoutContext, int)
 	 */
 	@Override
-	public Caret getCaret(final LayoutContext context, final int offset) {
+	public Caret getCaret(final LayoutContext context, final ContentPosition position) {
 		final Graphics g = context.getGraphics();
 		final Styles styles = context.getStyleSheet().getStyles(node);
 		final FontResource oldFont = g.getFont();
 		final FontResource font = g.createFont(styles.getFont());
 		g.setFont(font);
 		final char[] chars = getText().toCharArray();
-		final int x = g.charsWidth(chars, 0, offset - getStartOffset());
+		final int x = g.charsWidth(chars, 0, position.getOffset() - getStartOffset());
 		g.setFont(oldFont);
 		font.dispose();
 		return new TextCaret(x, 0, getHeight());
@@ -144,7 +146,7 @@
 
 	/**
 	 * Returns true if the given character is one where a linebreak should occur, e.g. a space.
-	 * 
+	 *
 	 * @param c
 	 *            the character to test
 	 */
@@ -154,7 +156,7 @@
 
 	/**
 	 * Paints a string as selected text.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext to be used. It is assumed that the contained Graphics object is set up with the proper
 	 *            font.
@@ -215,7 +217,7 @@
 
 	/**
 	 * Paint a line along the baseline of the text, for showing underline, overline and strike-through formatting.
-	 * 
+	 *
 	 * @param context
 	 *            LayoutContext to be used. It is assumed that the contained Graphics object is set up with the proper
 	 *            font.
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TextCaret.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TextCaret.java
index 8a90e8d..fc5d6c2 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TextCaret.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TextCaret.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
@@ -27,7 +27,7 @@
 
 	/**
 	 * Class constructor
-	 * 
+	 *
 	 * @param x
 	 *            x-coordinate of the caret
 	 * @param y
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/VerticalRange.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/VerticalRange.java
index c4f8cc1..3bac365 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/VerticalRange.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/VerticalRange.java
@@ -4,7 +4,7 @@
  * 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:
  *     John Krasnay - initial API and implementation
  *     Florian Thienel - inroduce specific implementations for layout and content to separate both domains
@@ -26,7 +26,7 @@
 
 	/**
 	 * Create a new VerticalRange from top to bottom.
-	 * 
+	 *
 	 * @param top
 	 *            top of the range
 	 * @param bottom
@@ -61,7 +61,7 @@
 
 	/**
 	 * Indicates if this range fully contains the given range.
-	 * 
+	 *
 	 * @param other
 	 *            the other range
 	 * @return true if this range fully contains the other range
@@ -72,7 +72,7 @@
 
 	/**
 	 * Indicates if this range contains the given y coordinate.
-	 * 
+	 *
 	 * @param y
 	 *            the coordinate
 	 * @return true if this range contains the y coordinate
@@ -83,7 +83,7 @@
 
 	/**
 	 * Indicates if this range intersects with the given range, even if the given range is only adjacent.
-	 * 
+	 *
 	 * @param other
 	 *            the other range
 	 * @return true if this range intersects with the other range
@@ -95,7 +95,7 @@
 	/**
 	 * Create a range that represents the intersection of this range and the given range. If the ranges do not
 	 * intersect, returns null. May return an empty range if this and the other range are only adjacent.
-	 * 
+	 *
 	 * @param other
 	 *            the other range
 	 * @return the intersection of this range and the other range
@@ -112,7 +112,7 @@