started cut at VEXMultiPage Editor
diff --git a/sourceediting/plugins/org.eclipse.wst.xml.vex.core/src/org/eclipse/wst/xml/vex/core/internal/dom/DOMDocumentReader.java b/sourceediting/plugins/org.eclipse.wst.xml.vex.core/src/org/eclipse/wst/xml/vex/core/internal/dom/DOMDocumentReader.java
new file mode 100644
index 0000000..2942e8a
--- /dev/null
+++ b/sourceediting/plugins/org.eclipse.wst.xml.vex.core/src/org/eclipse/wst/xml/vex/core/internal/dom/DOMDocumentReader.java
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 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
+ *******************************************************************************/
+package org.eclipse.wst.xml.vex.core.internal.dom;
+
+import java.io.CharArrayReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.net.URL;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.apache.xerces.util.DOMInputSource;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.Parser;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.ext.LexicalHandler;
+
+/**
+ * Class for creating documents given a URL.
+ */
+public class DOMDocumentReader {
+
+	/**
+	 * Returns the debugging flag.
+	 */
+	public boolean isDebugging() {
+		return debugging;
+	}
+
+	/**
+	 * Returns the entity resolver for this reader.
+	 */
+	public EntityResolver getEntityResolver() {
+		return entityResolver;
+	}
+
+	/**
+	 * Returns the whitespace policy factory for this reader.
+	 */
+	public IWhitespacePolicyFactory getWhitespacePolicyFactory() {
+		return whitespacePolicyFactory;
+	}
+
+	/**
+	 * Reads a document given a URL.
+	 * 
+	 * @param url
+	 *            URL from which to load the document.
+	 */
+	public Document read(org.w3c.dom.Document domDocument) throws IOException,
+			ParserConfigurationException, SAXException {
+		DOMInputSource domIS = new DOMInputSource((org.w3c.dom.Node)domDocument.getDocumentElement());
+		Reader reader = domIS.getCharacterStream();
+		return read(new InputSource(reader));
+	}
+
+	/**
+	 * 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.
+	 */
+	public Document read(String s) throws IOException,
+			ParserConfigurationException, SAXException {
+
+		Reader reader = new CharArrayReader(s.toCharArray());
+		return this.read(new InputSource(reader));
+	}
+
+	/**
+	 * Reads a document given a SAX InputSource.
+	 * 
+	 * @param is
+	 *            SAX InputSource from which to load the document.
+	 */
+	public Document read(InputSource is) throws IOException,
+			ParserConfigurationException, SAXException {
+
+		SAXParserFactory factory = SAXParserFactory.newInstance();
+		factory.setValidating(false); // TODO: experimental--SWT implementation
+		XMLReader xmlReader = factory.newSAXParser().getXMLReader();
+		// xmlReader.setFeature("http://xml.org/sax/features/validation",
+		// false);
+		final org.eclipse.wst.xml.vex.core.internal.dom.DocumentBuilder builder = new org.eclipse.wst.xml.vex.core.internal.dom.DocumentBuilder(
+				this.getWhitespacePolicyFactory());
+
+		ContentHandler contentHandler = builder;
+		LexicalHandler lexicalHandler = builder;
+
+		if (this.isDebugging()) {
+			Object proxy = Proxy.newProxyInstance(this.getClass()
+					.getClassLoader(), new Class[] { ContentHandler.class,
+					LexicalHandler.class }, new InvocationHandler() {
+				public Object invoke(Object proxy, Method method, Object[] args)
+						throws Throwable {
+					try {
+						return method.invoke(builder, args);
+					} catch (InvocationTargetException ex) {
+						ex.getCause().printStackTrace();
+						throw ex.getCause();
+					}
+				}
+			});
+
+			contentHandler = (ContentHandler) proxy;
+			lexicalHandler = (LexicalHandler) proxy;
+		}
+
+		xmlReader.setContentHandler(contentHandler);
+		xmlReader.setProperty("http://xml.org/sax/properties/lexical-handler",
+				lexicalHandler);
+		if (this.getEntityResolver() != null) {
+			xmlReader.setEntityResolver(this.getEntityResolver());
+		}
+		xmlReader.parse(is);
+		return builder.getDocument();
+	}
+	
+	
+
+	/**
+	 * Sets the debugging flag.
+	 * 
+	 * @param debugging
+	 *            true if the component should log debugging info to stdout.
+	 */
+	public void setDebugging(boolean debugging) {
+		this.debugging = debugging;
+	}
+
+	/**
+	 * Sets the entity resolver for this reader.
+	 * 
+	 * @param entityResolver
+	 *            The entityResolver to set.
+	 */
+	public void setEntityResolver(EntityResolver entityResolver) {
+		this.entityResolver = entityResolver;
+	}
+
+	/**
+	 * Sets the whitespace policy factory for this reader. This factory is used
+	 * to obtain a whitespace policy once the public ID of the document is
+	 * known.
+	 * 
+	 * @param whitespacePolicyFactory
+	 *            The whitespacePolicyFactory to set.
+	 */
+	public void setWhitespacePolicyFactory(
+			IWhitespacePolicyFactory whitespacePolicyFactory) {
+		this.whitespacePolicyFactory = whitespacePolicyFactory;
+	}
+
+	// ======================================================= PRIVATE
+
+	private boolean debugging;
+	private EntityResolver entityResolver;
+	private IWhitespacePolicyFactory whitespacePolicyFactory;
+
+}
diff --git a/sourceediting/plugins/org.eclipse.wst.xml.vex.ui/plugin.xml b/sourceediting/plugins/org.eclipse.wst.xml.vex.ui/plugin.xml
index 3404431..9d16685 100644
--- a/sourceediting/plugins/org.eclipse.wst.xml.vex.ui/plugin.xml
+++ b/sourceediting/plugins/org.eclipse.wst.xml.vex.ui/plugin.xml
@@ -122,7 +122,7 @@
 
       </actionSet>
    </extension>
-  <!--
+ 
    <extension
          point="org.eclipse.ui.editors">
       <editor
@@ -134,13 +134,12 @@
             id="org.eclipse.wst.xml.vex.ui.VexEditor">
       </editor>
    </extension>
-   -->
-   
+<!--
    	<extension point="org.eclipse.ui.editors">
 		<editor
 			name="%VexEditor.name"
 			icon="$nl$/vex16.gif"
-			contributorClass="org.eclipse.wst.xml.vex.ui.internal.action.VexActionBarContributor"
+			contributorClass="org.eclipse.wst.xml.vex.ui.internal.editor.VexActionBarContributor"
 			class="org.eclipse.wst.xml.vex.ui.internal.editor.VEXMultiPageEditorPart"
 			symbolicFontName="org.eclipse.wst.sse.ui.textfont"
 			id="org.eclipse.wst.xml.vex.ui.VexEditor">
@@ -151,7 +150,7 @@
 
 		</editor>
 	</extension>
-   
+ -->  
    
    <extension
          point="org.eclipse.ui.newWizards">
diff --git a/sourceediting/plugins/org.eclipse.wst.xml.vex.ui/src/org/eclipse/wst/xml/vex/ui/internal/editor/VEXMultiPageEditorPart.java b/sourceediting/plugins/org.eclipse.wst.xml.vex.ui/src/org/eclipse/wst/xml/vex/ui/internal/editor/VEXMultiPageEditorPart.java
index 2a08c03..3c39868 100644
--- a/sourceediting/plugins/org.eclipse.wst.xml.vex.ui/src/org/eclipse/wst/xml/vex/ui/internal/editor/VEXMultiPageEditorPart.java
+++ b/sourceediting/plugins/org.eclipse.wst.xml.vex.ui/src/org/eclipse/wst/xml/vex/ui/internal/editor/VEXMultiPageEditorPart.java
@@ -4,26 +4,31 @@
 import org.eclipse.jface.text.IDocument;
 import org.eclipse.ui.PartInitException;
 import org.eclipse.ui.part.MultiPageEditorPart;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
 import org.eclipse.wst.sse.ui.StructuredTextEditor;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
 import org.eclipse.wst.xml.ui.internal.Logger;
 import org.eclipse.wst.xml.ui.internal.tabletree.XMLEditorMessages;
+import org.eclipse.wst.xml.ui.internal.tabletree.XMLTableTreeViewer;
 
 public class VEXMultiPageEditorPart extends MultiPageEditorPart {
 
 	private StructuredTextEditor textEditor = null;
-	private VexEditor vexEditor = null;
+	private VexEditorMultiPage vexEditor = null;
 	private int sourcePageIndex;
 	private int visualPageIndex;
+	private IDOMDocument modelDocument;
 	
 	protected void createPages() {
 		try {
-			createVisualEditorPage();
 			createSourcePage();
-
-			addVisualEditorPage();
+			createVisualEditorPage();
 			addSourcePage();
-			vexEditor.setDocument(getDocument());
-			setActivePage(visualPageIndex);
+			addVisualEditorPage();
+			setActivePage(sourcePageIndex);
+
 		} catch (PartInitException e) {
 			Logger.logException(e);
 			throw new RuntimeException(e);
@@ -37,7 +42,7 @@
 	}
 	
 	private void createVisualEditorPage() {
-		vexEditor = new VexEditor();
+		vexEditor = new VexEditorMultiPage();
 	}
 	
 	/**
@@ -46,7 +51,7 @@
 	private void addSourcePage() throws PartInitException {
 		sourcePageIndex = addPage(textEditor, getEditorInput());
 		setPageText(sourcePageIndex, XMLEditorMessages.XMLMultiPageEditorPart_0);
-
+		vexEditor.setDomDoc(modelDocument);
 		firePropertyChange(PROP_TITLE);
 
 		// Changes to the Text Viewer's document instance should also
@@ -78,5 +83,18 @@
 			document = textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput());
 		}
 		return document;
-	}	
+	}
+	
+	private void setDOMDocument(IDocument document) {
+	    IStructuredModel model = StructuredModelManager.getModelManager().getExistingModelForRead(getDocument());
+	    IDOMDocument modelDocument = null;
+	    try {
+	      if (model instanceof IDOMModel) {
+	        modelDocument = ((IDOMModel)model).getDocument();
+	      }
+	    } finally {
+	      if (model != null)
+	        model.releaseFromRead();
+	    }
+	}
 }
diff --git a/sourceediting/plugins/org.eclipse.wst.xml.vex.ui/src/org/eclipse/wst/xml/vex/ui/internal/action/VexActionBarContributor.java b/sourceediting/plugins/org.eclipse.wst.xml.vex.ui/src/org/eclipse/wst/xml/vex/ui/internal/editor/VexActionBarContributor.java
similarity index 90%
rename from sourceediting/plugins/org.eclipse.wst.xml.vex.ui/src/org/eclipse/wst/xml/vex/ui/internal/action/VexActionBarContributor.java
rename to sourceediting/plugins/org.eclipse.wst.xml.vex.ui/src/org/eclipse/wst/xml/vex/ui/internal/editor/VexActionBarContributor.java
index c4372a6..233c186 100644
--- a/sourceediting/plugins/org.eclipse.wst.xml.vex.ui/src/org/eclipse/wst/xml/vex/ui/internal/action/VexActionBarContributor.java
+++ b/sourceediting/plugins/org.eclipse.wst.xml.vex.ui/src/org/eclipse/wst/xml/vex/ui/internal/editor/VexActionBarContributor.java
@@ -8,7 +8,7 @@
  * Contributors:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
-package org.eclipse.wst.xml.vex.ui.internal.action;
+package org.eclipse.wst.xml.vex.ui.internal.editor;
 
 import org.eclipse.jface.action.Action;
 import org.eclipse.jface.action.GroupMarker;
@@ -29,9 +29,20 @@
 import org.eclipse.wst.xml.ui.internal.tabletree.XMLMultiPageEditorActionBarContributor;
 import org.eclipse.wst.xml.vex.core.internal.dom.DocumentValidationException;
 import org.eclipse.wst.xml.vex.core.internal.widget.IVexWidget;
+import org.eclipse.wst.xml.vex.ui.internal.action.ActionUtils;
+import org.eclipse.wst.xml.vex.ui.internal.action.DeleteColumnAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.DeleteRowAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.InsertColumnAfterAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.InsertColumnBeforeAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.InsertElementAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.InsertRowAboveAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.InsertRowBelowAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.MoveColumnLeftAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.MoveColumnRightAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.MoveRowDownAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.MoveRowUpAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.VexActionAdapter;
 import org.eclipse.wst.xml.vex.ui.internal.config.Style;
-import org.eclipse.wst.xml.vex.ui.internal.editor.Messages;
-import org.eclipse.wst.xml.vex.ui.internal.editor.VexEditor;
 import org.eclipse.wst.xml.vex.ui.internal.swt.VexWidget;
 
 /**
diff --git a/sourceediting/plugins/org.eclipse.wst.xml.vex.ui/src/org/eclipse/wst/xml/vex/ui/internal/editor/VexEditor.java b/sourceediting/plugins/org.eclipse.wst.xml.vex.ui/src/org/eclipse/wst/xml/vex/ui/internal/editor/VexEditor.java
index 92a13f3..cf43448 100644
--- a/sourceediting/plugins/org.eclipse.wst.xml.vex.ui/src/org/eclipse/wst/xml/vex/ui/internal/editor/VexEditor.java
+++ b/sourceediting/plugins/org.eclipse.wst.xml.vex.ui/src/org/eclipse/wst/xml/vex/ui/internal/editor/VexEditor.java
@@ -37,7 +37,6 @@
 import org.eclipse.jface.action.MenuManager;
 import org.eclipse.jface.commands.ActionHandler;
 import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.jface.text.IDocument;
 import org.eclipse.jface.viewers.ISelectionChangedListener;
 import org.eclipse.jface.viewers.IStructuredSelection;
 import org.eclipse.jface.viewers.SelectionChangedEvent;
@@ -63,9 +62,6 @@
 import org.eclipse.ui.views.properties.IPropertySource;
 import org.eclipse.ui.views.properties.IPropertySourceProvider;
 import org.eclipse.ui.views.properties.PropertySheetPage;
-import org.eclipse.wst.sse.core.StructuredModelManager;
-import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
-import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
 import org.eclipse.wst.xml.vex.core.internal.core.ListenerList;
 import org.eclipse.wst.xml.vex.core.internal.dom.Document;
 import org.eclipse.wst.xml.vex.core.internal.dom.DocumentReader;
@@ -324,7 +320,7 @@
 		}
 	}
 
-	private void loadInput() {
+	protected void loadInput() {
 
 		if (this.vexWidget != null) {
 			this.vexEditorListeners.fireEvent(
@@ -638,12 +634,12 @@
 		gd.verticalAlignment = GridData.FILL;
 		this.vexWidget.setLayoutData(gd);
 
-//		VexActionBarContributor contributor = (VexActionBarContributor) this
-//				.getEditorSite().getActionBarContributor();
-//
-//		MenuManager menuMgr = contributor.getContextMenuManager();
-//		this.getSite().registerContextMenu(menuMgr, this.vexWidget);
-//		this.vexWidget.setMenu(menuMgr.createContextMenu(this.vexWidget));
+		VexActionBarContributor contributor = (VexActionBarContributor) this
+				.getEditorSite().getActionBarContributor();
+
+		MenuManager menuMgr = contributor.getContextMenuManager();
+		this.getSite().registerContextMenu(menuMgr, this.vexWidget);
+		this.vexWidget.setMenu(menuMgr.createContextMenu(this.vexWidget));
 
 		this.savedUndoDepth = this.vexWidget.getUndoDepth();
 
@@ -1060,26 +1056,4 @@
 		}
 	}
 
-	public void setDocument(IDocument document) {
-		/*
-		 * let the text editor to be the one that manages the model's lifetime
-		 */
-		IStructuredModel model = null;
-		try {
-			model = StructuredModelManager.getModelManager().getExistingModelForRead(document);
-
-			if ((model != null) && (model instanceof IDOMModel)) {
-				org.w3c.dom.Document domDoc = null;
-				domDoc = ((IDOMModel) model).getDocument();
-			}
-			else {
-			}
-		}
-		finally {
-			if (model != null) {
-				model.releaseFromRead();
-			}
-		}
-	}
-	
 }
diff --git a/sourceediting/plugins/org.eclipse.wst.xml.vex.ui/src/org/eclipse/wst/xml/vex/ui/internal/editor/VexEditorMultiPage.java b/sourceediting/plugins/org.eclipse.wst.xml.vex.ui/src/org/eclipse/wst/xml/vex/ui/internal/editor/VexEditorMultiPage.java
new file mode 100644
index 0000000..7d495ae
--- /dev/null
+++ b/sourceediting/plugins/org.eclipse.wst.xml.vex.ui/src/org/eclipse/wst/xml/vex/ui/internal/editor/VexEditorMultiPage.java
@@ -0,0 +1,969 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 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
+ *******************************************************************************/
+package org.eclipse.wst.xml.vex.ui.internal.editor;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.URL;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.preferences.IPreferencesService;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.commands.ActionHandler;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.contexts.IContextService;
+import org.eclipse.ui.dialogs.SaveAsDialog;
+import org.eclipse.ui.editors.text.ILocationProvider;
+import org.eclipse.ui.handlers.IHandlerService;
+import org.eclipse.ui.part.EditorPart;
+import org.eclipse.ui.part.FileEditorInput;
+import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
+import org.eclipse.ui.views.properties.IPropertySheetPage;
+import org.eclipse.ui.views.properties.IPropertySource;
+import org.eclipse.ui.views.properties.IPropertySourceProvider;
+import org.eclipse.ui.views.properties.PropertySheetPage;
+import org.eclipse.wst.xml.vex.core.internal.core.ListenerList;
+import org.eclipse.wst.xml.vex.core.internal.dom.DOMDocumentReader;
+import org.eclipse.wst.xml.vex.core.internal.dom.Document;
+import org.eclipse.wst.xml.vex.core.internal.dom.DocumentReader;
+import org.eclipse.wst.xml.vex.core.internal.dom.DocumentWriter;
+import org.eclipse.wst.xml.vex.core.internal.dom.Element;
+import org.eclipse.wst.xml.vex.core.internal.dom.IWhitespacePolicy;
+import org.eclipse.wst.xml.vex.core.internal.dom.IWhitespacePolicyFactory;
+import org.eclipse.wst.xml.vex.core.internal.dom.Validator;
+import org.eclipse.wst.xml.vex.core.internal.widget.CssWhitespacePolicy;
+import org.eclipse.wst.xml.vex.ui.internal.VexPlugin;
+import org.eclipse.wst.xml.vex.ui.internal.action.ChangeElementAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.DeleteColumnAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.DeleteRowAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.DuplicateSelectionAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.InsertColumnAfterAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.InsertColumnBeforeAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.InsertElementAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.InsertRowAboveAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.InsertRowBelowAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.MoveColumnLeftAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.MoveColumnRightAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.MoveRowDownAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.MoveRowUpAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.NextTableCellAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.PasteTextAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.PreviousTableCellAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.RemoveElementAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.RestoreLastSelectionAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.SplitAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.SplitItemAction;
+import org.eclipse.wst.xml.vex.ui.internal.action.VexActionAdapter;
+import org.eclipse.wst.xml.vex.ui.internal.config.ConfigEvent;
+import org.eclipse.wst.xml.vex.ui.internal.config.ConfigRegistry;
+import org.eclipse.wst.xml.vex.ui.internal.config.DocumentType;
+import org.eclipse.wst.xml.vex.ui.internal.config.IConfigListener;
+import org.eclipse.wst.xml.vex.ui.internal.config.Style;
+import org.eclipse.wst.xml.vex.ui.internal.outline.DocumentOutlinePage;
+import org.eclipse.wst.xml.vex.ui.internal.property.ElementPropertySource;
+import org.eclipse.wst.xml.vex.ui.internal.swt.VexWidget;
+import org.osgi.service.prefs.BackingStoreException;
+import org.osgi.service.prefs.Preferences;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+/**
+ * Editor for editing XML file using the VexWidget.
+ */
+public class VexEditorMultiPage extends VexEditor {
+
+	/**
+	 * ID of this editor extension.
+	 */
+	public static final String ID = "org.eclipse.wst.xml.vex.ui.internal.editor.VexEditorMultiPage"; //$NON-NLS-1$
+	private org.w3c.dom.Document domDoc = null;
+
+	/**
+	 * Class constructor.
+	 */
+	public VexEditorMultiPage() {
+		this.debugging = VexPlugin.getInstance().isDebugging()
+				&& "true".equalsIgnoreCase(Platform.getDebugOption(VexPlugin.ID + "/debug/layout")); //$NON-NLS-1$ //$NON-NLS-2$
+	}
+
+	/**
+	 * Add a VexEditorListener to the notification list.
+	 * 
+	 * @param listener
+	 *            VexEditorListener to be added.
+	 */
+	public void addVexEditorListener(IVexEditorListener listener) {
+		this.vexEditorListeners.add(listener);
+	}
+
+	public void dispose() {
+		super.dispose();
+
+		if (this.parentControl != null) {
+			// createPartControl was called, so we must de-register from config
+			// events
+			ConfigRegistry.getInstance().removeConfigListener(
+					this.configListener);
+		}
+
+		if (getEditorInput() instanceof IFileEditorInput) {
+			ResourcesPlugin.getWorkspace().removeResourceChangeListener(
+					this.resourceChangeListener);
+		}
+
+	}
+
+	public void doSave(IProgressMonitor monitor) {
+
+		IEditorInput input = this.getEditorInput();
+		OutputStream os = null;
+		try {
+			this.resourceChangeListener.setSaving(true);
+			DocumentWriter writer = new DocumentWriter();
+			writer.setWhitespacePolicy(new CssWhitespacePolicy(this.style
+					.getStyleSheet()));
+
+			if (input instanceof IFileEditorInput) {
+				ByteArrayOutputStream baos = new ByteArrayOutputStream();
+				writer.write(this.doc, baos);
+				baos.close();
+				ByteArrayInputStream bais = new ByteArrayInputStream(baos
+						.toByteArray());
+				((IFileEditorInput) input).getFile().setContents(bais, false,
+						false, monitor);
+			} else {
+				os = new FileOutputStream(((ILocationProvider) input).getPath(
+						input).toFile());
+				writer.write(this.doc, os);
+			}
+
+			this.savedUndoDepth = this.vexWidget.getUndoDepth();
+			this.firePropertyChange(EditorPart.PROP_DIRTY);
+
+		} catch (Exception ex) {
+			monitor.setCanceled(true);
+			String title = Messages.getString("VexEditor.errorSaving.title"); //$NON-NLS-1$
+			String message = MessageFormat.format(Messages
+					.getString("VexEditor.errorSaving.message"), //$NON-NLS-1$
+					new Object[] { input.getName(), ex.getMessage() });
+			MessageDialog.openError(this.getEditorSite().getShell(), title,
+					message);
+			VexPlugin.getInstance().log(IStatus.ERROR, message, ex);
+		} finally {
+			if (os != null) {
+				try {
+					os.close();
+				} catch (IOException e) {
+				}
+			}
+			this.resourceChangeListener.setSaving(false);
+		}
+	}
+
+	public void doSaveAs() {
+		SaveAsDialog dlg = new SaveAsDialog(this.getSite().getShell());
+		int result = dlg.open();
+		if (result == Window.OK) {
+			IPath path = dlg.getResult();
+			try {
+				this.resourceChangeListener.setSaving(true);
+				ByteArrayOutputStream baos = new ByteArrayOutputStream();
+				DocumentWriter writer = new DocumentWriter();
+				writer.setWhitespacePolicy(new CssWhitespacePolicy(this.style
+						.getStyleSheet()));
+				writer.write(this.doc, baos);
+				baos.close();
+
+				ByteArrayInputStream bais = new ByteArrayInputStream(baos
+						.toByteArray());
+				IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(
+						path);
+				file.create(bais, false, null);
+
+				IFileEditorInput input = new FileEditorInput(file);
+				this.setInput(input);
+				this.savedUndoDepth = this.vexWidget.getUndoDepth();
+
+				this.firePropertyChange(EditorPart.PROP_DIRTY);
+				this.firePropertyChange(EditorPart.PROP_INPUT);
+				this.firePropertyChange(EditorPart.PROP_TITLE);
+
+			} catch (Exception ex) {
+				String title = Messages
+						.getString("VexEditor.errorSaving.title"); //$NON-NLS-1$
+				String message = MessageFormat.format(Messages
+						.getString("VexEditor.errorSaving.message"), //$NON-NLS-1$
+						new Object[] { path, ex.getMessage() });
+				MessageDialog.openError(this.getEditorSite().getShell(), title,
+						message);
+				VexPlugin.getInstance().log(IStatus.ERROR, message, ex);
+			} finally {
+				this.resourceChangeListener.setSaving(false);
+			}
+		}
+
+	}
+
+	/**
+	 * Return a reasonable style for the given doctype.
+	 * 
+	 * @param publicId
+	 *            Public ID for which to return the style.
+	 */
+	public static Style findStyleForDoctype(String publicId) {
+
+		IPreferencesService preferences = Platform.getPreferencesService();
+		String key = getStylePreferenceKey(publicId);
+		String preferredStyleId = preferences.getString(VexPlugin.ID, key,
+				null, null);
+
+		Preferences prefs = new InstanceScope().getNode(VexPlugin.ID);
+		preferredStyleId = prefs.get(key, null);
+
+		Style firstStyle = null;
+		ConfigRegistry registry = ConfigRegistry.getInstance();
+		List styles = registry.getAllConfigItems(Style.EXTENSION_POINT);
+		for (Iterator it = styles.iterator(); it.hasNext();) {
+			Style style = (Style) it.next();
+			if (style.appliesTo(publicId)) {
+				if (firstStyle == null) {
+					firstStyle = style;
+				}
+				if (style.getUniqueId().equals(preferredStyleId)) {
+					return style;
+				}
+			}
+		}
+		return firstStyle;
+	}
+
+	/**
+	 * Returns the DocumentType associated with this editor.
+	 */
+	public DocumentType getDocumentType() {
+		return this.doctype;
+	}
+
+	/**
+	 * Returns the Style currently associated with the editor. May be null.
+	 */
+	public Style getStyle() {
+		return style;
+	}
+
+	/**
+	 * Returns the VexWidget that implements this editor.
+	 */
+	public VexWidget getVexWidget() {
+		return this.vexWidget;
+	}
+
+	public void gotoMarker(IMarker marker) {
+		// TODO Auto-generated method stub
+
+	}
+
+	public void init(IEditorSite site, IEditorInput input)
+			throws PartInitException {
+
+		this.setSite(site);
+		this.setInput(input);
+
+		this.getEditorSite().setSelectionProvider(this.selectionProvider);
+		this.getEditorSite().getSelectionProvider()
+				.addSelectionChangedListener(selectionChangedListener);
+
+		if (input instanceof IFileEditorInput) {
+			ResourcesPlugin.getWorkspace().addResourceChangeListener(
+					this.resourceChangeListener,
+					IResourceChangeEvent.POST_CHANGE);
+		}
+	}
+
+	protected void loadInput() {
+
+		if (this.vexWidget != null) {
+			this.vexEditorListeners.fireEvent(
+					"documentUnloaded", new VexEditorMultiPageEvent(this)); //$NON-NLS-1$
+		}
+
+		this.loaded = false;
+
+		IEditorInput input = this.getEditorInput();
+
+		try {
+			long start = System.currentTimeMillis();
+
+			IPath inputPath = null;
+
+			if (input instanceof IFileEditorInput) {
+				inputPath = ((IFileEditorInput) input).getFile()
+						.getRawLocation();
+			} else if (input instanceof ILocationProvider) {
+				// Yuck, this a crappy way for Eclipse to do this
+				// How about an exposed IJavaFileEditorInput, pleeze?
+				inputPath = ((ILocationProvider) input).getPath(input);
+			} else {
+				String msg = MessageFormat.format(Messages
+						.getString("VexEditor.unknownInputClass"), //$NON-NLS-1$
+						new Object[] { input.getClass() });
+				this.showLabel(msg);
+				return;
+			}
+
+			URL url = inputPath.toFile().toURL();
+
+			DOMDocumentReader reader = new DOMDocumentReader();
+			reader.setDebugging(this.debugging);
+			reader.setEntityResolver(entityResolver);
+			reader.setWhitespacePolicyFactory(wsFactory);
+			doctype = null;
+			doc = reader.read(domDoc);
+
+			if (this.debugging) {
+				long end = System.currentTimeMillis();
+				System.out
+						.println("Parsed document in " + (end - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+
+			// this.doctype is set either by wsPolicyFactory or entityResolver
+			// this.style is set by wsPolicyFactory
+			// Otherwise, a PartInitException would have been thrown by now
+
+			Validator validator = this.doctype.getValidator();
+			if (validator != null) {
+				this.doc.setValidator(validator);
+				if (this.debugging) {
+					long end = System.currentTimeMillis();
+					System.out
+							.println("Got validator in " + (end - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
+				}
+			}
+
+			this.showVexWidget();
+
+			this.vexWidget.setDebugging(debugging);
+			this.vexWidget.setDocument(this.doc, this.style.getStyleSheet());
+
+			if (this.updateDoctypeDecl) {
+				this.doc.setPublicID(this.doctype.getPublicId());
+				this.doc.setSystemID(this.doctype.getSystemId());
+				this.doSave(null);
+			}
+
+			this.loaded = true;
+			this.savedUndoDepth = this.vexWidget.getUndoDepth();
+			firePropertyChange(EditorPart.PROP_DIRTY);
+			this.wasDirty = isDirty();
+
+			this.vexEditorListeners.fireEvent(
+					"documentLoaded", new VexEditorMultiPageEvent(this)); //$NON-NLS-1$
+
+		} catch (SAXParseException ex) {
+
+			if (ex.getException() instanceof NoRegisteredDoctypeException) {
+				// TODO doc did not have document type and the user
+				// declined to select another one. Should fail silently.
+				String msg;
+				NoRegisteredDoctypeException ex2 = (NoRegisteredDoctypeException) ex
+						.getException();
+				if (ex2.getPublicId() == null) {
+					msg = Messages.getString("VexEditor.noDoctype"); //$NON-NLS-1$
+				} else {
+					msg = MessageFormat.format(Messages
+							.getString("VexEditor.unknownDoctype"), //$NON-NLS-1$
+							new Object[] { ex2.getPublicId() });
+				}
+				this.showLabel(msg);
+			} else if (ex.getException() instanceof NoStyleForDoctypeException) {
+				String msg = MessageFormat.format(Messages
+						.getString("VexEditor.noStyles"), //$NON-NLS-1$
+						new Object[] { this.doctype.getPublicId() });
+				this.showLabel(msg);
+			} else {
+				String file = ex.getSystemId();
+				if (file == null) {
+					file = input.getName();
+				}
+
+				String msg = MessageFormat.format(Messages
+						.getString("VexEditor.parseError"), //$NON-NLS-1$
+						new Object[] { new Integer(ex.getLineNumber()), file,
+								ex.getLocalizedMessage() });
+
+				this.showLabel(msg);
+
+				VexPlugin.getInstance().log(IStatus.ERROR, msg, ex);
+			}
+
+		} catch (Exception ex) {
+
+			String msg = MessageFormat.format(Messages
+					.getString("VexEditor.unexpectedError"), //$NON-NLS-1$
+					new Object[] { input.getName() });
+
+			VexPlugin.getInstance().log(IStatus.ERROR, msg, ex);
+
+			this.showLabel(msg);
+		}
+	}
+
+	public boolean isDirty() {
+		if (this.vexWidget != null) {
+			return this.savedUndoDepth != this.vexWidget.getUndoDepth();
+		} else {
+			return false;
+		}
+	}
+
+	/**
+	 * Returns true if this editor has finished loading its document.
+	 */
+	public boolean isLoaded() {
+		return this.loaded;
+	}
+
+	public boolean isSaveAsAllowed() {
+		return true;
+	}
+
+	public void createPartControl(Composite parent) {
+
+		this.parentControl = parent;
+
+		ConfigRegistry registry = ConfigRegistry.getInstance();
+
+		registry.addConfigListener(this.configListener);
+
+		if (registry.isConfigLoaded()) {
+			this.loadInput();
+		} else {
+			this.showLabel(Messages.getString("VexEditor.loading")); //$NON-NLS-1$
+		}
+	}
+
+	/**
+	 * Remove a VexEditorListener from the notification list.
+	 * 
+	 * @param listener
+	 *            VexEditorListener to be removed.
+	 */
+	public void removeVexEditorListener(IVexEditorListener listener) {
+		this.vexEditorListeners.remove(listener);
+	}
+
+	public void setFocus() {
+		if (this.vexWidget != null) {
+			this.vexWidget.setFocus();
+			setStatus(getLocation());
+		}
+	}
+
+	protected void setInput(IEditorInput input) {
+		super.setInput(input);
+		this.setPartName(input.getName());
+		this.setContentDescription(input.getName());
+		//this.setTitleToolTip(input.getToolTipText());
+	}
+
+	public void setStatus(String text) {
+		// this.statusLabel.setText(text);
+		this.getEditorSite().getActionBars().getStatusLineManager().setMessage(
+				text);
+	}
+
+	/**
+	 * Sets the style for this editor.
+	 * 
+	 * @param style
+	 *            Style to use.
+	 */
+	public void setStyle(Style style) {
+		this.style = style;
+		if (this.vexWidget != null) {
+			this.vexWidget.setStyleSheet(style.getStyleSheet());
+			Preferences prefs = new InstanceScope().getNode(VexPlugin.ID);
+			String key = getStylePreferenceKey(this.doc.getPublicID());
+			prefs.put(key, style.getUniqueId());
+			try {
+				prefs.flush();
+			} catch (BackingStoreException e) {
+				VexPlugin
+						.getInstance()
+						.log(
+								IStatus.ERROR,
+								Messages
+										.getString("VexEditor.errorSavingStylePreference"), e); //$NON-NLS-1$
+			}
+		}
+	}
+
+	// ========================================================= PRIVATE
+
+	private boolean debugging;
+
+	private Composite parentControl;
+	private Label loadingLabel;
+
+	private boolean loaded;
+	private DocumentType doctype;
+	private Document doc;
+	private Style style;
+
+	private VexWidget vexWidget;
+
+	private int savedUndoDepth;
+	private boolean wasDirty;
+	// private Label statusLabel;
+
+	// This is true if the document's doctype decl is missing or unrecognized
+	// AND the user selected a new document type
+	// AND the user wants to always use the doctype for this document
+	private boolean updateDoctypeDecl;
+
+	private ListenerList vexEditorListeners = new ListenerList(
+			IVexEditorListener.class, VexEditorEvent.class);
+
+	private SelectionProvider selectionProvider = new SelectionProvider();
+
+	/**
+	 * Returns the preference key used to access the style ID for documents with
+	 * the same public ID as the current document.
+	 */
+	private static String getStylePreferenceKey(String publicId) {
+		return publicId + ".style"; //$NON-NLS-1$
+	}
+
+	private void showLabel(String message) {
+		if (this.loadingLabel == null) {
+			if (this.vexWidget != null) {
+				this.vexWidget.dispose();
+				this.vexWidget = null;
+			}
+			this.loadingLabel = new Label(this.parentControl, SWT.WRAP);
+		}
+		this.loadingLabel.setText(message);
+		this.parentControl.layout(true);
+	}
+
+	private void showVexWidget() {
+
+		if (this.vexWidget != null) {
+			return;
+		}
+
+		if (this.loadingLabel != null) {
+			this.loadingLabel.dispose();
+			this.loadingLabel = null;
+		}
+
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 1;
+		layout.verticalSpacing = 0;
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		this.parentControl.setLayout(layout);
+		GridData gd;
+
+		// StatusPanel statusPanel = new StatusPanel(this.parentControl);
+
+		// Composite statusPanel = new Composite(this.parentControl, SWT.NONE);
+		// statusPanel.setLayout(new GridLayout());
+		// gd = new GridData();
+		// gd.grabExcessHorizontalSpace = true;
+		// gd.horizontalAlignment = GridData.FILL;
+		// statusPanel.setLayoutData(gd);
+
+		// this.statusLabel = new Label(statusPanel, SWT.NONE);
+		// gd = new GridData();
+		// gd.grabExcessHorizontalSpace = true;
+		// gd.horizontalAlignment = GridData.FILL;
+		// this.statusLabel.setLayoutData(gd);
+
+		gd = new GridData();
+		gd.grabExcessHorizontalSpace = true;
+		gd.grabExcessVerticalSpace = true;
+		gd.horizontalAlignment = GridData.FILL;
+		gd.verticalAlignment = GridData.FILL;
+
+		this.vexWidget = new VexWidget(this.parentControl, SWT.V_SCROLL);
+		gd = new GridData();
+		gd.grabExcessHorizontalSpace = true;
+		gd.grabExcessVerticalSpace = true;
+		gd.horizontalAlignment = GridData.FILL;
+		gd.verticalAlignment = GridData.FILL;
+		this.vexWidget.setLayoutData(gd);
+
+//		VexActionBarContributor contributor = (VexActionBarContributor) this
+//				.getEditorSite().getActionBarContributor();
+//
+//		MenuManager menuMgr = contributor.getContextMenuManager();
+//		this.getSite().registerContextMenu(menuMgr, this.vexWidget);
+//		this.vexWidget.setMenu(menuMgr.createContextMenu(this.vexWidget));
+
+		this.savedUndoDepth = this.vexWidget.getUndoDepth();
+
+		// new for scopes
+		IContextService cs = (IContextService) this.getSite().getService(
+				IContextService.class);
+		cs.activateContext("org.eclipse.wst.xml.vex.ui.VexEditorContext");
+
+		this.vexWidget.addSelectionChangedListener(this.selectionProvider);
+
+		this.parentControl.layout(true);
+
+	}
+
+	private void handleResourceChanged(IResourceDelta delta) {
+
+		if (delta.getKind() == IResourceDelta.CHANGED) {
+			if ((delta.getFlags() & IResourceDelta.CONTENT) != 0) {
+				this.handleResourceContentChanged();
+			}
+		} else if (delta.getKind() == IResourceDelta.REMOVED) {
+			if ((delta.getFlags() & IResourceDelta.MOVED_TO) != 0) {
+				IPath toPath = delta.getMovedToPath();
+				IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(
+						toPath);
+				this.setInput(new FileEditorInput(file));
+			} else {
+				if (!this.isDirty()) {
+					this.getEditorSite().getPage().closeEditor(this, false);
+				} else {
+					this.handleResourceDeleted();
+				}
+			}
+		}
+
+	}
+
+	private void handleResourceContentChanged() {
+
+		if (!this.isDirty()) {
+			this.loadInput();
+		} else {
+
+			String message = MessageFormat.format(Messages
+					.getString("VexEditor.docChanged.message"), //$NON-NLS-1$
+					new Object[] { this.getEditorInput().getName() });
+
+			MessageDialog dlg = new MessageDialog(
+					this.getSite().getShell(),
+					Messages.getString("VexEditor.docChanged.title"), //$NON-NLS-1$
+					null,
+					message,
+					MessageDialog.QUESTION,
+					new String[] {
+							Messages.getString("VexEditor.docChanged.discard"), //$NON-NLS-1$
+							Messages
+									.getString("VexEditor.docChanged.overwrite") }, //$NON-NLS-1$
+					1);
+
+			int result = dlg.open();
+
+			if (result == 0) { // Discard my changes
+				this.loadInput();
+			} else { // Overwrite other changes
+				this.doSave(null);
+			}
+		}
+	}
+
+	private void handleResourceDeleted() {
+
+		String message = MessageFormat.format(Messages
+				.getString("VexEditor.docDeleted.message"), //$NON-NLS-1$
+				new Object[] { this.getEditorInput().getName() });
+
+		MessageDialog dlg = new MessageDialog(this.getSite().getShell(),
+				Messages.getString("VexEditor.docDeleted.title"), //$NON-NLS-1$
+				null, message, MessageDialog.QUESTION, new String[] {
+						Messages.getString("VexEditor.docDeleted.discard"), //$NON-NLS-1$ 
+						Messages.getString("VexEditor.docDeleted.save") }, //$NON-NLS-1$
+				1);
+
+		int result = dlg.open();
+
+		if (result == 0) { // Discard
+
+			this.getEditorSite().getPage().closeEditor(this, false);
+
+		} else { // Save
+
+			this.doSaveAs();
+
+			// Check if they saved or not. If not, close the editor
+			if (!this.getEditorInput().exists()) {
+				this.getEditorSite().getPage().closeEditor(this, false);
+			}
+		}
+	}
+
+	// Listen for stylesheet changes and respond appropriately
+	private IConfigListener configListener = new IConfigListener() {
+
+		public void configChanged(ConfigEvent e) {
+			if (style != null) {
+				ConfigRegistry registry = ConfigRegistry.getInstance();
+				String currId = style.getUniqueId();
+				Style newStyle = (Style) registry.getConfigItem(
+						Style.EXTENSION_POINT, currId);
+				if (newStyle == null) {
+					// Oops, style went bye-bye
+					// Let's just hold on to it in case it comes back later
+				} else {
+					vexWidget.setStyleSheet(newStyle.getStyleSheet());
+					style = newStyle;
+				}
+			}
+		}
+
+		public void configLoaded(ConfigEvent e) {
+			loadInput();
+		}
+	};
+
+	private ISelectionChangedListener selectionChangedListener = new ISelectionChangedListener() {
+		public void selectionChanged(SelectionChangedEvent event) {
+			if (isDirty() != wasDirty) {
+				firePropertyChange(EditorPart.PROP_DIRTY);
+				wasDirty = isDirty();
+			}
+			setStatus(getLocation());
+		}
+	};
+
+	private EntityResolver entityResolver = new EntityResolver() {
+		public InputSource resolveEntity(String publicId, String systemId)
+				throws SAXException, IOException {
+
+			// System.out.println("### Resolving publicId " + publicId +
+			// ", systemId " + systemId);
+
+			if (doctype == null) {
+				//
+				// If doctype hasn't already been set, this must be the doctype
+				// decl.
+				//
+				if (publicId != null) {
+					doctype = DocumentType.getDocumentType(publicId);
+				}
+
+				if (doctype == null) {
+					DocumentTypeSelectionDialog dlg = DocumentTypeSelectionDialog
+							.create(getSite().getShell(), publicId);
+					dlg.open();
+					doctype = dlg.getDoctype();
+					updateDoctypeDecl = dlg.alwaysUseThisDoctype();
+
+					if (doctype == null) {
+						throw new NoRegisteredDoctypeException(publicId);
+					}
+				}
+
+				URL url = doctype.getResourceUrl();
+
+				if (url == null) {
+					String message = MessageFormat.format(Messages
+							.getString("VexEditor.noUrlForDoctype"), //$NON-NLS-1$
+							new Object[] { publicId });
+					throw new RuntimeException(message);
+				}
+
+				return new InputSource(url.toString());
+			} else {
+				return null;
+			}
+		}
+	};
+
+	private IWhitespacePolicyFactory wsFactory = new IWhitespacePolicyFactory() {
+		public IWhitespacePolicy getPolicy(String publicId) {
+
+			if (doctype == null) {
+				DocumentTypeSelectionDialog dlg = DocumentTypeSelectionDialog
+						.create(getSite().getShell(), publicId);
+				dlg.open();
+				doctype = dlg.getDoctype();
+				updateDoctypeDecl = dlg.alwaysUseThisDoctype();
+
+				if (doctype == null) {
+					throw new NoRegisteredDoctypeException(null);
+				}
+			}
+
+			style = VexEditorMultiPage.findStyleForDoctype(doctype.getPublicId());
+			if (style == null) {
+				throw new NoStyleForDoctypeException(doctype);
+			}
+
+			return new CssWhitespacePolicy(style.getStyleSheet());
+		}
+
+	};
+
+	private class ResourceChangeListener implements IResourceChangeListener {
+
+		public void resourceChanged(IResourceChangeEvent event) {
+
+			if (this.saving) {
+				return;
+			}
+
+			IPath path = ((IFileEditorInput) getEditorInput()).getFile()
+					.getFullPath();
+			final IResourceDelta delta = event.getDelta().findMember(path);
+			if (delta != null) {
+				Display.getDefault().asyncExec(new Runnable() {
+					public void run() {
+						handleResourceChanged(delta);
+					}
+				});
+			}
+		}
+
+		public void setSaving(boolean saving) {
+			this.saving = saving;
+		}
+
+		// Set to true so we can ignore change events while we're saving.
+		private boolean saving;
+	};
+
+	private ResourceChangeListener resourceChangeListener = new ResourceChangeListener();
+
+	//
+	// wsFactory communicates failures back to init() through the XML parser
+	// by throwing one of these exceptions
+	//
+
+	/**
+	 * Indicates that no document type is registered for the public ID in the
+	 * document, or that the document does not have a PUBLIC DOCTYPE decl, in
+	 * which case publicId is null.
+	 */
+	private class NoRegisteredDoctypeException extends RuntimeException {
+		public NoRegisteredDoctypeException(String publicId) {
+			this.publicId = publicId;
+		}
+
+		public String getPublicId() {
+			return this.publicId;
+		}
+
+		private String publicId;
+	}
+
+	/**
+	 * Indicates that the document was matched to a registered doctype, but that
+	 * the given doctype does not have a matching style.
+	 */
+	private class NoStyleForDoctypeException extends RuntimeException {
+
+		public NoStyleForDoctypeException(DocumentType doctype) {
+			this.doctype = doctype;
+		}
+
+		public DocumentType getDoctype() {
+			return this.doctype;
+		}
+
+		private DocumentType doctype;
+	}
+
+	private String getLocation() {
+		List path = new ArrayList();
+		Element element = this.vexWidget.getCurrentElement();
+		while (element != null) {
+			path.add(element.getName());
+			element = element.getParent();
+		}
+		Collections.reverse(path);
+		StringBuffer sb = new StringBuffer(path.size() * 15);
+		for (int i = 0; i < path.size(); i++) {
+			sb.append("/"); //$NON-NLS-1$
+			sb.append(path.get(i));
+		}
+		return sb.toString();
+	}
+
+	public Object getAdapter(Class adapter) {
+
+		if (adapter == IContentOutlinePage.class) {
+
+			return new DocumentOutlinePage();
+
+		} else if (adapter == IPropertySheetPage.class) {
+			PropertySheetPage page = new PropertySheetPage();
+			page.setPropertySourceProvider(new IPropertySourceProvider() {
+				public IPropertySource getPropertySource(Object object) {
+					if (object instanceof Element) {
+						IStructuredSelection sel = (IStructuredSelection) vexWidget
+								.getSelection();
+						boolean multi = (sel != null && sel.size() > 1);
+						Validator validator = vexWidget.getDocument()
+								.getValidator();
+						return new ElementPropertySource((Element) object,
+								validator, multi);
+					} else {
+						return null;
+					}
+				}
+			});
+			return page;
+		} else {
+			return super.getAdapter(adapter);
+		}
+	}
+
+	public org.w3c.dom.Document getDomDoc() {
+		return domDoc;
+	}
+
+	public void setDomDoc(org.w3c.dom.Document domDoc) {
+		this.domDoc = domDoc;
+	}
+
+}
diff --git a/sourceediting/plugins/org.eclipse.wst.xml.vex.ui/src/org/eclipse/wst/xml/vex/ui/internal/editor/VexEditorMultiPageEvent.java b/sourceediting/plugins/org.eclipse.wst.xml.vex.ui/src/org/eclipse/wst/xml/vex/ui/internal/editor/VexEditorMultiPageEvent.java
new file mode 100644
index 0000000..c9eec3b
--- /dev/null
+++ b/sourceediting/plugins/org.eclipse.wst.xml.vex.ui/src/org/eclipse/wst/xml/vex/ui/internal/editor/VexEditorMultiPageEvent.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 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
+ *******************************************************************************/
+package org.eclipse.wst.xml.vex.ui.internal.editor;
+
+import java.util.EventObject;
+
+/**
+ * Event object published through the IVexEditorListener interface.
+ */
+public class VexEditorMultiPageEvent extends EventObject {
+
+	/**
+	 * Class constructor.
+	 * 
+	 * @param source
+	 *            VexEditor that originated this event.
+	 */
+	public VexEditorMultiPageEvent(VexEditorMultiPage source) {
+		super(source);
+	}
+
+	/**
+	 * Returns the VexEditor that originated this event.
+	 */
+	public VexEditor getVexEditor() {
+		return (VexEditor) this.getSource();
+	}
+}