[Date Prev][Date Next][Thread Prev][Thread Next][Thread Index]

[XaraXtreme-commits] Commit Complete



Commit by  : phil
Repository : xara
Revision   : 992
Date       : Wed May 10 11:36:34 BST 2006

Changed paths:
   M /Trunk/XaraLX/wxOil/Makefile.am
   M /Trunk/XaraLX/wxOil/camelot.cpp
   M /Trunk/XaraLX/wxOil/compatdef.h
   A /Trunk/XaraLX/wxOil/xmlutils.cpp
   A /Trunk/XaraLX/wxOil/xmlutils.h
   M /Trunk/XaraLX/wxOil/xpoilflt.cpp
   M /Trunk/XaraLX/wxOil/xpoilflt.h

First version of XPFilter Capability tree built using libxml2. Not guaranteed working yet.


Diff:
Index: Trunk/XaraLX/wxOil/xpoilflt.cpp
===================================================================
--- Trunk/XaraLX/wxOil/xpoilflt.cpp	(revision 991)
+++ Trunk/XaraLX/wxOil/xpoilflt.cpp	(revision 992)
@@ -113,6 +113,7 @@
 
 #include "ncntrcnt.h"
 //#include "nev.h"		// For _R(IDN_USER_CANCELLED)
+#include "xmlutils.h"
 
 #include "camprocess.h"
 
@@ -1192,8 +1193,7 @@
 
 	if (code == 0)
 	{
-		// Change this once XML stuff is working
-//		BuildCapabilityTree(bsXML, pCapTree);
+		BuildCapabilityTree(m_XMLFile.GetPath(), pCapTree);
 	}
 	else
 	{
@@ -1340,12 +1340,9 @@
 #endif
 
 
-PORTNOTE("other","PluginFilter COM bits removed")
-#if !defined(EXCLUDE_FROM_XARALX)
-
 /****************************************************************************
 
->	HRESULT PluginOILFilter::BuildCapabilityTree(BSTR bsXML, CapabilityTree* pCapTree)
+>	BOOL PluginOILFilter::BuildCapabilityTree(wxString strXmlFilename, CapabilityTree* pCapTree)
 
 	Author:		Gerry_Iles (Xara Group Ltd) <camelotdev@xxxxxxxx>
 	Created:	17/03/2005
@@ -1357,13 +1354,15 @@
 
 ****************************************************************************/
 
-HRESULT PluginOILFilter::BuildCapabilityTree(BSTR bsXML, CapabilityTree* pCapTree)
+/*HRESULT PluginOILFilter::BuildCapabilityTree(BSTR bsXML, CapabilityTree* pCapTree)
 {
 	// First we need to load the XML into an XML DOM object
 	CComPtr<MSXML2::IXMLDOMDocument2> pDoc;
+	
 	HRESULT hRes = S_OK;
 	hRes = pDoc.CoCreateInstance(__uuidof(MSXML2::DOMDocument40));
 
+	doc = xmlNewDocument();
 	hRes = pDoc->setProperty(CComBSTR(_T("SelectionLanguage")), CComVariant(_T("XPath")));
 	hRes = pDoc->put_async(VARIANT_FALSE);
 	hRes = pDoc->put_preserveWhiteSpace(VARIANT_TRUE);
@@ -1389,8 +1388,6 @@
 		ERROR1(E_FAIL, _R(IDE_XPF_BADXML));
 	}
 
-	// The name should be XPFilterConfig
-
 	// There are 5 phases to the parsing
 	// We will loop round until we run out of child elements
 	// After parsing a node the phase counter will be set to the phase just parsed
@@ -1474,12 +1471,125 @@
 		hRes = pChild->get_nextSibling(&pNextChild);
 		pChild = pNextChild;
 	}
+	return S_OK;
+}*/
 
-	return(S_OK);
+
+BOOL PluginOILFilter::BuildCapabilityTree(wxString strFilename, CapabilityTree* pCapTree)
+{
+
+	// First we need to load the XML into an XML DOM object
+
+	// Set flags in Parser context here?
+
+	BOOL bOK = TRUE;
+    xmlDocPtr doc;
+
+	// If string param contains xml (like original Windows version)
+//	wxCharBuffer buf = strXML.mb_str(wxConvUTF8);
+//	doc = xmlParseDoc((const xmlChar*)buf.data());	// buf will be deallocated when it goes out of scope
+
+	// If string param gives xml filename (like new LX version)
+	wxCharBuffer buf = strFilename.ToAscii();
+	doc = xmlParseFile(buf.data());					// buf will be deallocated when it goes out of scope
+#if _DEBUG
+	if (doc==NULL)
+		doc = xmlParseFile("/tmp/XaraLX/capstest.xml");
+#endif
+	ERROR1IF(doc==NULL, FALSE, _R(IDE_XPF_BADXML));
+
+	// The name of the root element should be XPFilterConfig
+
+	xmlNodePtr node = xmlDocGetRootElement(doc);
+	wxString strName = CXMLUtils::ConvertToWXString(node->name);
+	if (strName!=_T("XPFilterConfig"))
+		ERROR1(FALSE, _R(IDE_XPF_BADXML));
+
+	xmlNodePtr pChild = node->children;
+	INT32 Phase =0;
+
+	// There are 5 phases to the parsing
+	// We will loop round until we run out of child elements
+	// After parsing a node the phase counter will be set to the phase just parsed
+	// If an element should have already been parsed (using the phase counter)
+	// then an error will be indicated
+
+	while (pChild && bOK)
+	{
+		wxString strChildName = CXMLUtils::ConvertToWXString(pChild->name);
+		
+		if (strChildName == _T("#text") || xmlNodeIsText(pChild))
+		{
+			// ignore it
+		}
+		else if (strChildName == _T("Options"))
+		{
+			if (Phase > 0)
+			{
+				ERROR1(FALSE, _R(IDE_XPF_BADXML));
+			}
+			bOK = ReadOptions(pChild, pCapTree);		// Read the options attributes
+			Phase = 1;
+		}
+		else if (strChildName == _T("Rasterise"))
+		{
+			if (Phase > 1)
+			{
+				ERROR1(FALSE, _R(IDE_XPF_BADXML));
+			}
+			bOK = ReadRasterise(pChild, pCapTree);		// Read the dpi and alpha attributes
+			Phase = 2;
+		}
+		else if (strChildName == _T("Spread"))
+		{
+			if (Phase > 2)
+			{
+				ERROR1(FALSE, _R(IDE_XPF_BADXML));
+			}
+			bOK = ReadSpread(pChild, pCapTree);		// Read the as attribute
+			Phase = 3;
+		}
+		else if (strChildName == _T("Objects"))
+		{
+			if (Phase > 3)
+			{
+				ERROR1(FALSE, _R(IDE_XPF_BADXML));
+			}
+			bOK = ReadObjects(pChild, pCapTree);		// Build the tree of XPFCapability derived objects
+			Phase = 4;
+		}
+		else if (strChildName == _T("Attributes"))
+		{
+			if (Phase > 4)
+			{
+				ERROR1(FALSE, _R(IDE_XPF_BADXML));
+			}
+			bOK = ReadAttributes(pChild, pCapTree);	// Build the tree of XPFCapability derived objects
+			Phase = 5;
+		}
+		else if (strChildName == _T("Colour"))
+		{
+			if (Phase > 5)
+			{
+				ERROR1(FALSE, _R(IDE_XPF_BADXML));
+			}
+			bOK = ReadColour(pChild, pCapTree);		// Build the tree of XPFColour objects
+			Phase = 6;
+		}
+		else
+		{
+			ERROR1(FALSE, _R(IDE_XPF_BADXML));
+		}
+
+		pChild = pChild->next;
+	}
+
+
+	return bOK;
 }
 
 
-HRESULT PluginOILFilter::ReadOptions(IXMLDOMNode* pNode, CapabilityTree* pCapTree)
+/*HRESULT PluginOILFilter::ReadOptions(IXMLDOMNode* pNode, CapabilityTree* pCapTree)
 {
 	CComQIPtr<IXMLDOMElement> pElem;
 	pElem = pNode;
@@ -1525,10 +1635,44 @@
 	pCapTree->SetSelection(bSelection);
 
 	return(S_OK);
+}*/
+
+
+BOOL PluginOILFilter::ReadOptions(xmlNodePtr pNode, CapabilityTree* pCapTree)
+{
+	BoundsWriteLevel Level = BWL_NONE;
+
+	wxString strLevel = CXMLUtils::ConvertToWXString(xmlGetProp(pNode, (xmlChar*)"boundslevel"));
+	if (strLevel == _T("none"))
+	{
+		Level = BWL_NONE;
+	}
+	else if (strLevel == _T("compound"))
+	{
+		Level = BWL_COMPOUND;
+	}
+	else if (strLevel == _T("all"))
+	{
+		Level = BWL_ALL;
+	}
+	else
+	{
+		ERROR1(FALSE, _R(IDE_XPF_BADXML));
+	}
+
+	pCapTree->SetBoundsLevel(Level);
+
+	BOOL bSelection = FALSE;
+	wxString strSelection = CXMLUtils::ConvertToWXString(xmlGetProp(pNode, (xmlChar*)"selection"));
+	bSelection = (strSelection == _T("true"));
+
+	pCapTree->SetSelection(bSelection);
+
+	return TRUE;
 }
 
 
-HRESULT PluginOILFilter::ReadRasterise(IXMLDOMNode* pNode, CapabilityTree* pCapTree)
+/*HRESULT PluginOILFilter::ReadRasterise(IXMLDOMNode* pNode, CapabilityTree* pCapTree)
 {
 	CComQIPtr<IXMLDOMElement> pElem;
 	pElem = pNode;
@@ -1561,10 +1705,35 @@
 
 	return(S_OK);
 }
+*/
 
 
-HRESULT PluginOILFilter::ReadSpread(IXMLDOMNode* pNode, CapabilityTree* pCapTree)
+BOOL PluginOILFilter::ReadRasterise(xmlNodePtr pNode, CapabilityTree* pCapTree)
 {
+	double DPI = 96.0;
+	BOOL bAlpha = TRUE;
+	wxString str;
+
+	str = CXMLUtils::ConvertToWXString(xmlGetProp(pNode, (xmlChar*)"dpi"));
+	if (!str.IsEmpty())
+	{
+		str.ToDouble(&DPI);
+	}
+
+	str = CXMLUtils::ConvertToWXString(xmlGetProp(pNode, (xmlChar*)"alpha"));
+	if (!str.IsEmpty())
+	{
+		bAlpha = (str == _T("true"));
+	}
+
+	pCapTree->SetRasterise(DPI, bAlpha);
+
+	return TRUE;
+}
+
+
+/*HRESULT PluginOILFilter::ReadSpread(IXMLDOMNode* pNode, CapabilityTree* pCapTree)
+{
 	CComQIPtr<IXMLDOMElement> pElem(pNode);
 	if (!pElem)
 	{
@@ -1597,10 +1766,34 @@
 		pCapTree->SetSpreadType(Type);
 
 	return(S_OK);
+}*/
+
+
+BOOL PluginOILFilter::ReadSpread(xmlNodePtr pNode, CapabilityTree* pCapTree)
+{
+	XPFConvertType Type = XPFCONVTYPE_UNKNOWN;
+	wxString str = CXMLUtils::ConvertToWXString(xmlGetProp(pNode, (xmlChar*)"as"));
+	if (str.IsEmpty())
+	{
+		Type = XPFCONVTYPE_NATIVE;
+	}
+	else if (str == _T("bitmap"))
+	{
+		Type = XPFCONVTYPE_BITMAP;
+	}
+	else
+	{
+		ERROR1(FALSE, _R(IDE_XPF_BADXML));
+	}
+
+	if (Type != XPFCONVTYPE_UNKNOWN)
+		pCapTree->SetSpreadType(Type);
+
+	return TRUE;
 }
 
 
-HRESULT PluginOILFilter::ReadObjects(IXMLDOMNode* pNode, CapabilityTree* pCapTree)
+/*HRESULT PluginOILFilter::ReadObjects(IXMLDOMNode* pNode, CapabilityTree* pCapTree)
 {
 	// We must loop through the tree of elements
 
@@ -1648,10 +1841,57 @@
 	pCapTree->SetObjectsTree(pObjects, ObjectsType);
 
 	return(S_OK);
+}*/
+
+
+BOOL PluginOILFilter::ReadObjects(xmlNodePtr pNode, CapabilityTree* pCapTree)
+{
+	// We must loop through the tree of elements
+
+	// pNode is the Objects element so read the default as attribute
+
+	XPFCapability* pObjects = NULL;
+	XPFConvertType ObjectsType = XPFCONVTYPE_UNKNOWN;
+
+	HRESULT hRes;
+	hRes = GetConvertAsType(pNode, &ObjectsType);
+
+	// Loop through each child calling the CreateObjectNode recursive function
+	// for each one
+
+	xmlNodePtr pChild;
+	pChild = pNode->children;
+	XPFCapability* pLast = NULL;
+
+	while (pChild)
+	{
+		XPFCapability* pCap = CreateObjectNode(pChild);
+
+		if (pCap)
+		{
+			// If we have a capability node then add it to the list
+			// If we do not have a node already then set pObjects
+			if (pLast)
+			{
+				pLast->SetNext(pCap);
+			}
+			else
+			{
+				pObjects = pCap;
+			}
+			pLast = pCap;
+		}
+
+		pChild = pChild->next;
+	}
+
+	pCapTree->SetObjectsTree(pObjects, ObjectsType);
+
+	return TRUE;
 }
 
 
-HRESULT PluginOILFilter::ReadAttributes(IXMLDOMNode* pNode, CapabilityTree* pCapTree)
+/*HRESULT PluginOILFilter::ReadAttributes(IXMLDOMNode* pNode, CapabilityTree* pCapTree)
 {
 	// We must loop through the tree of elements
 
@@ -1698,10 +1938,58 @@
 	pCapTree->SetAttributesTree(pAttrs, AttrType);
 
 	return(S_OK);
+}*/
+
+
+BOOL PluginOILFilter::ReadAttributes(xmlNodePtr pNode, CapabilityTree* pCapTree)
+{
+	// We must loop through the tree of elements
+
+	// pNode is the Attributes element so read the default as attribute
+
+	XPFCapability* pAttrs = NULL;
+	XPFConvertType AttrType = XPFCONVTYPE_UNKNOWN;
+
+	BOOL bOK = GetConvertAsType(pNode, &AttrType);
+	if (!bOK)
+		return FALSE;
+
+	// Loop through each child calling the CreateAttributeNode recursive function
+	// for each one
+
+	xmlNodePtr pChild;
+	pChild = pNode->children;
+	XPFCapability* pLast = NULL;
+
+	while (pChild)
+	{
+		XPFCapability* pCap = CreateAttributeNode(pChild);
+
+		if (pCap)
+		{
+			// If we have a node then add it to the list
+			// If we do not have a node already then set m_pObjects
+			if (pLast)
+			{
+				pLast->SetNext(pCap);
+			}
+			else
+			{
+				pAttrs = pCap;
+			}
+			pLast = pCap;
+		}
+
+		pChild = pChild->next;
+	}
+
+	pCapTree->SetAttributesTree(pAttrs, AttrType);
+
+	return TRUE;
 }
 
 
-HRESULT PluginOILFilter::ReadColour(IXMLDOMNode* pNode, CapabilityTree* pCapTree)
+/*HRESULT PluginOILFilter::ReadColour(IXMLDOMNode* pNode, CapabilityTree* pCapTree)
 {
 	// We must loop through the tree of elements
 
@@ -1748,10 +2036,58 @@
 	pCapTree->SetColoursTree(pCols, ColType);
 
 	return(S_OK);
+}*/
+
+
+BOOL PluginOILFilter::ReadColour(xmlNodePtr pNode, CapabilityTree* pCapTree)
+{
+	// We must loop through the tree of elements
+
+	// pNode is the Attributes element so read the default as attribute
+
+	XPFCapability* pCols = NULL;
+	XPFConvertType ColType = XPFCONVTYPE_UNKNOWN;
+
+	BOOL bOK = GetConvertAsType(pNode, &ColType);
+	if (!bOK)
+		return FALSE;
+
+	// Loop through each child calling the CreateColourNode recursive function
+	// for each one
+
+	xmlNodePtr pChild;
+	pChild = pNode->children;
+	XPFCapability* pLast = NULL;
+
+	while (pChild)
+	{
+		XPFCapability* pCap = CreateColourNode(pChild);
+
+		if (pCap)
+		{
+			// If we have a node then add it to the list
+			// If we do not have a node already then set m_pObjects
+			if (pLast)
+			{
+				pLast->SetNext(pCap);
+			}
+			else
+			{
+				pCols = pCap;
+			}
+			pLast = pCap;
+		}
+
+		pChild = pChild->next;
+	}
+
+	pCapTree->SetColoursTree(pCols, ColType);
+
+	return TRUE;
 }
 
 
-HRESULT PluginOILFilter::GetConvertAsType(IXMLDOMNode* pNode, XPFConvertType* pValue)
+/*HRESULT PluginOILFilter::GetConvertAsType(IXMLDOMNode* pNode, XPFConvertType* pValue)
 {
 	XPFConvertType AsType = XPFCONVTYPE_UNKNOWN;
 
@@ -1833,10 +2169,88 @@
 
 	*pValue = AsType;
 	return(S_OK);
+}*/
+
+
+BOOL PluginOILFilter::GetConvertAsType(xmlNodePtr pNode, XPFConvertType* pValue)
+{
+	XPFConvertType AsType = XPFCONVTYPE_UNKNOWN;
+
+	if (pNode)
+	{
+		wxString str = CXMLUtils::ConvertToWXString(xmlGetProp(pNode, (xmlChar*)"as"));
+		if (!str.IsEmpty())
+		{
+			if (str == _T("native"))
+			{
+				AsType = XPFCONVTYPE_NATIVE;
+			}
+			else if (str == _T("simple"))
+			{
+				AsType = XPFCONVTYPE_SIMPLE;
+			}
+			else if (str == _T("stroked"))
+			{
+				AsType = XPFCONVTYPE_STROKED;
+			}
+			else if (str == _T("bitmap"))
+			{
+				AsType = XPFCONVTYPE_BITMAP;
+			}
+			else if (str == _T("bitmapfill"))
+			{
+				AsType = XPFCONVTYPE_BITMAPFILL;
+			}
+			else if (str == _T("bitmaptrans"))
+			{
+				AsType = XPFCONVTYPE_BITMAPTRANS;
+			}
+			else if (str == _T("bitmapfilltrans"))
+			{
+				AsType = XPFCONVTYPE_BITMAPFILLTRANS;
+			}
+			else if (str == _T("bitmapspan"))
+			{
+				AsType = XPFCONVTYPE_BITMAPSPAN;
+			}
+			else if (str == _T("reformat"))
+			{
+				AsType = XPFCONVTYPE_REFORMAT;
+			}
+			else if (str == _T("remove"))
+			{
+				AsType = XPFCONVTYPE_REMOVE;
+			}
+			else if (str == _T("simplergb"))
+			{
+				AsType = XPFCONVTYPE_SIMPLERGB;
+			}
+			else if (str == _T("rgb"))
+			{
+				AsType = XPFCONVTYPE_RGB;
+			}
+			else if (str == _T("cmyk"))
+			{
+				AsType = XPFCONVTYPE_CMYK;
+			}
+			else
+			{
+				ERROR1(FALSE, _R(IDE_XPF_BADXML));
+			}
+		}
+	}
+	else
+	{
+		ERROR1(FALSE, _R(IDE_XPF_BADXML));
+	}
+
+	*pValue = AsType;
+
+	return TRUE;
 }
 
 
-HRESULT PluginOILFilter::GetXPFBOOL(IXMLDOMNode* pNode, LPTSTR pAttrName, XPFBOOL* pbValue)
+/*HRESULT PluginOILFilter::GetXPFBOOL(IXMLDOMNode* pNode, LPTSTR pAttrName, XPFBOOL* pbValue)
 {
 	XPFBOOL bValue = XPFB_UNKNOWN;
 
@@ -1874,9 +2288,46 @@
 
 	*pbValue = bValue;
 	return(S_OK);
+}*/
+
+
+BOOL PluginOILFilter::GetXPFBOOL(xmlNodePtr pNode, LPTSTR pAttrName, XPFBOOL* pbValue)
+{
+	XPFBOOL bValue = XPFB_UNKNOWN;
+
+	if (pNode)
+	{
+		wxString strAttrName(pAttrName);
+		wxCharBuffer buf = strAttrName.mb_str(wxConvUTF8);			// buf will remain allocated in this scope
+		wxString str = CXMLUtils::ConvertToWXString(xmlGetProp(pNode, (xmlChar*)buf.data()));
+		if (!str.IsEmpty())
+		{
+			if (str == _T("true"))
+			{
+				bValue = XPFB_TRUE;
+			}
+			else if (str == _T("false"))
+			{
+				bValue = XPFB_FALSE;
+			}
+			else
+			{
+				ERROR1(FALSE, _R(IDE_XPF_BADXML));
+			}
+		}
+	}
+	else
+	{
+		ERROR1(FALSE, _R(IDE_XPF_BADXML));
+	}
+
+	*pbValue = bValue;
+
+	return TRUE;
 }
 
-HRESULT PluginOILFilter::GetXPFProp(IXMLDOMNode* pNode, LPTSTR pAttrName, PropMapEntry aMap[], XPFProp* pValue)
+
+/*HRESULT PluginOILFilter::GetXPFProp(IXMLDOMNode* pNode, LPTSTR pAttrName, PropMapEntry aMap[], XPFProp* pValue)
 {
 	XPFProp Value = XPFP_UNKNOWN;
 
@@ -1919,11 +2370,50 @@
 
 	*pValue = Value;
 	return(S_OK);
+}*/
+
+
+BOOL PluginOILFilter::GetXPFProp(xmlNodePtr pNode, LPTSTR pAttrName, PropMapEntry aMap[], XPFProp* pValue)
+{
+	XPFProp Value = XPFP_UNKNOWN;
+
+	if (pNode)
+	{
+		wxString strAttrName(pAttrName);
+		wxCharBuffer buf = strAttrName.mb_str(wxConvUTF8);			// buf will remain allocated in this scope
+		wxString str = CXMLUtils::ConvertToWXString(xmlGetProp(pNode, (xmlChar*)buf.data()));
+		if (!str.IsEmpty())
+		{
+			// Loop through the map until we find it or the NULL indicating the end
+			INT32 Index = 0;
+			while (aMap[Index].pName)
+			{
+				if (str == aMap[Index].pName)
+				{
+					Value = aMap[Index].Value;
+					break;
+				}
+				Index++;
+			}
+
+			if (Value == XPFP_UNKNOWN)
+			{
+				ERROR1(FALSE, _R(IDE_XPF_BADXML));
+			}
+		}
+	}
+	else
+	{
+		ERROR1(FALSE, _R(IDE_XPF_BADXML));
+	}
+
+	*pValue = Value;
+
+	return TRUE;
 }
 
 
-
-XPFCapability* PluginOILFilter::CreateObjectNode(IXMLDOMNode* pNode)
+/*XPFCapability* PluginOILFilter::CreateObjectNode(IXMLDOMNode* pNode)
 {
 	XPFCapability* pCap = NULL;
 
@@ -2099,11 +2589,184 @@
 	}
 
 	return(pCap);
+}*/
+
+
+XPFCapability* PluginOILFilter::CreateObjectNode(xmlNodePtr pNode)
+{
+	XPFCapability* pCap = NULL;
+
+	wxString strName = CXMLUtils::ConvertToWXString(pNode->name);
+	
+	if (strName == _T("#text") || xmlNodeIsText(pNode))
+	{
+		return(NULL);
+	}
+
+	XPFConvertType AsType = XPFCONVTYPE_UNKNOWN;
+	HRESULT hRes = GetConvertAsType(pNode, &AsType);
+	if (strName == _T("Layer"))
+	{
+		// Read the visible and locked attributes
+		XPFBOOL bVisible = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("visible"), &bVisible);
+		XPFBOOL bLocked = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("locked"), &bLocked);
+		XPFBOOL bPrintable = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("printable"), &bPrintable);
+		XPFBOOL bActive = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("active"), &bActive);
+		XPFBOOL bBackground = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("background"), &bBackground);
+		XPFBOOL bGuide = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("guide"), &bGuide);
+		pCap = new XPFCLayer(AsType, bVisible, bLocked, bPrintable, bActive, bBackground, bGuide);
+	}
+	else if (strName == _T("Contour"))
+	{
+		pCap = new XPFCContour(AsType);
+	}
+	else if (strName == _T("Shadow"))
+	{
+		// Read the type attribute
+		XPFProp Type = XPFP_UNKNOWN;
+		hRes = GetXPFProp(pNode, _T("type"), aShadowTypes, &Type);
+		pCap = new XPFCShadow(AsType, Type);
+	}
+	else if (strName == _T("Bevel"))
+	{
+		// Read the type and side attributes
+		XPFProp Type = XPFP_UNKNOWN;
+		hRes = GetXPFProp(pNode, _T("type"), aBevelTypes, &Type);
+		XPFProp Side = XPFP_UNKNOWN;
+		hRes = GetXPFProp(pNode, _T("side"), aBevelSides, &Side);
+		pCap = new XPFCBevel(AsType, Type, Side);
+	}
+	else if (strName == _T("Blend"))
+	{
+		// Read the effect, oncurve, posprofile and attrprofile attributes
+		XPFProp Effect = XPFP_UNKNOWN;
+		hRes = GetXPFProp(pNode, _T("effect"), aColourEffects, &Effect);
+		XPFBOOL bOnCurve = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("oncurve"), &bOnCurve);
+		XPFBOOL bObjProfile = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("posprofile"), &bObjProfile);
+		XPFBOOL bAttrProfile = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("attrprofile"), &bAttrProfile);
+		pCap = new XPFCBlend(AsType, Effect, bOnCurve, bObjProfile, bAttrProfile);
+	}
+	else if (strName == _T("Mould"))
+	{
+		// Read the as and type attributes
+		XPFProp Type = XPFP_UNKNOWN;
+		hRes = GetXPFProp(pNode, _T("type"), aMouldTypes, &Type);
+		XPFBOOL bGradFill = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("gradfill"), &bGradFill);
+		pCap = new XPFCMould(AsType, Type, bGradFill);
+	}
+	else if (strName == _T("Rectangle"))
+	{
+		// Read the as, rounded and complex attributes
+		XPFBOOL bComplex = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("complex"), &bComplex);
+		XPFBOOL bRounded = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("rounded"), &bRounded);
+		XPFBOOL bStellated = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("stellated"), &bStellated);
+		XPFBOOL bReformed = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("reformed"), &bReformed);
+		pCap = new XPFCRectangle(AsType, bComplex, bRounded, bStellated, bReformed);
+	}
+	else if (strName == _T("Ellipse"))
+	{
+		// Read the as and complex attributes
+		XPFBOOL bComplex = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("complex"), &bComplex);
+		pCap = new XPFCEllipse(AsType, bComplex);
+	}
+	else if (strName == _T("Polygon"))
+	{
+		// Read the as, rounded, stellated and reformed attributes
+		XPFBOOL bRounded = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("rounded"), &bRounded);
+		XPFBOOL bStellated = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("stellated"), &bStellated);
+		XPFBOOL bReformed = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("reformed"), &bReformed);
+		pCap = new XPFCPolygon(AsType, bRounded, bStellated, bReformed);
+	}
+	else if (strName == _T("Bitmap"))
+	{
+		// Read the complex and contone attributes
+		XPFBOOL bComplex = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("complex"), &bComplex);
+		XPFBOOL bContone = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("contone"), &bContone);
+		pCap = new XPFCBitmap(AsType, bComplex, bContone);
+	}
+	else if (strName == _T("Text"))
+	{
+		// Read the onpath, complex and plain attributes
+		XPFBOOL bOnPath = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("onpath"), &bOnPath);
+		XPFBOOL bComplex = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("complex"), &bComplex);
+		XPFBOOL bPlain = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("plain"), &bPlain);
+		XPFBOOL bAutoKern = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("autokern"), &bAutoKern);
+		XPFBOOL bJustified = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("justified"), &bJustified);
+		pCap = new XPFCText(AsType, bOnPath, bComplex, bPlain, bAutoKern, bJustified);
+	}
+	else if (strName == _T("ClipView"))
+	{
+		pCap = new XPFCClipView(AsType);
+	}
+	else if (strName == _T("BitmapEffect"))
+	{
+		pCap = new XPFCBitmapEffect(AsType);
+	}
+	else if (strName == _T("Feather"))
+	{
+		pCap = new XPFCFeather(AsType);
+	}
+	else
+	{
+		ERROR1(NULL, _R(IDE_XPF_BADXML));
+	}
+
+	xmlNodePtr pChild;
+	pChild = pNode->children;
+	XPFCapability* pLast = NULL;
+
+	while (pChild)
+	{
+		XPFCapability* pCapNode = CreateObjectNode(pChild);
+
+		if (pCapNode)
+		{
+			// If we have a node then add it to the list
+			// If we do not have a node already then set m_pObjects
+			if (pLast)
+			{
+				pLast->SetNext(pCapNode);
+			}
+			else
+			{
+				pCap->SetChild(pCapNode);
+			}
+			pLast = pCapNode;
+		}
+
+		pChild = pChild->next;
+	}
+
+	return(pCap);
 }
 
 
-
-XPFCapability* PluginOILFilter::CreateAttributeNode(IXMLDOMNode* pNode)
+/*XPFCapability* PluginOILFilter::CreateAttributeNode(IXMLDOMNode* pNode)
 {
 	XPFCapability* pCap = NULL;
 
@@ -2207,10 +2870,112 @@
 	}
 
 	return(pCap);
+}*/
+
+
+XPFCapability* PluginOILFilter::CreateAttributeNode(xmlNodePtr pNode)
+{
+	XPFCapability* pCap = NULL;
+
+	wxString strName = CXMLUtils::ConvertToWXString(pNode->name);
+	
+	if (strName == _T("#text") || xmlNodeIsText(pNode))
+	{
+		return(NULL);
+	}
+
+	XPFConvertType AsType = XPFCONVTYPE_UNKNOWN;
+	HRESULT hRes = GetConvertAsType(pNode, &AsType);
+	if (strName == _T("Fill"))
+	{
+		XPFProp Shape = XPFP_UNKNOWN;
+		hRes = GetXPFProp(pNode, _T("shape"), aFillShapes, &Shape);
+		XPFProp Repeat = XPFP_UNKNOWN;
+		hRes = GetXPFProp(pNode, _T("repeat"), aFillRepeats, &Repeat);
+		XPFBOOL bMultistage = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("multistage"), &bMultistage);
+		XPFProp Effect = XPFP_UNKNOWN;
+		hRes = GetXPFProp(pNode, _T("effect"), aColourEffects, &Effect);
+		XPFBOOL bProfile = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("profile"), &bProfile);
+		XPFBOOL bContone = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("contone"), &bContone);
+		pCap = new XPFCFill(AsType, Shape, Repeat, bMultistage, Effect, bProfile, bContone);
+	}
+	else if (strName == _T("FillTrans"))
+	{
+		XPFProp Shape = XPFP_UNKNOWN;
+		hRes = GetXPFProp(pNode, _T("shape"), aFillShapes, &Shape);
+		XPFProp Type = XPFP_UNKNOWN;
+		hRes = GetXPFProp(pNode, _T("type"), aTransTypes, &Type);
+		XPFProp Repeat = XPFP_UNKNOWN;
+		hRes = GetXPFProp(pNode, _T("repeat"), aFillRepeats, &Repeat);
+		XPFBOOL bProfile = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("profile"), &bProfile);
+		pCap = new XPFCFillTrans(AsType, Shape, Type, Repeat, bProfile);
+	}
+	else if (strName == _T("Line"))
+	{
+		XPFBOOL bDash = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("dash"), &bDash);
+		XPFBOOL bArrowhead = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("arrowhead"), &bArrowhead);
+		XPFProp Cap = XPFP_UNKNOWN;
+		hRes = GetXPFProp(pNode, _T("cap"), aLineCaps, &Cap);
+		XPFProp Join = XPFP_UNKNOWN;
+		hRes = GetXPFProp(pNode, _T("join"), aLineJoins, &Join);
+		XPFBOOL bStroke = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("stroke"), &bStroke);
+		XPFBOOL bBrush = XPFB_UNKNOWN;
+		hRes = GetXPFBOOL(pNode, _T("brush"), &bBrush);
+		pCap = new XPFCLine(AsType, bDash, bArrowhead, Cap, Join, bStroke, bBrush);
+	}
+	else if (strName == _T("LineTrans"))
+	{
+		XPFProp Type = XPFP_UNKNOWN;
+		hRes = GetXPFProp(pNode, _T("type"), aTransTypes, &Type);
+		pCap = new XPFCLineTrans(AsType, Type);
+	}
+	else if (strName == _T("Feather"))
+	{
+		pCap = new XPFCFeather(AsType);
+	}
+	else
+	{
+		ERROR1(NULL, _R(IDE_XPF_BADXML));
+	}
+
+	xmlNodePtr pChild;
+	pChild = pNode->children;
+	XPFCapability* pLast = NULL;
+
+	while (pChild)
+	{
+		XPFCapability* pCapNode = CreateAttributeNode(pChild);
+
+		if (pCapNode)
+		{
+			// If we have a node then add it to the list
+			// If we do not have a node already then set m_pObjects
+			if (pLast)
+			{
+				pLast->SetNext(pCapNode);
+			}
+			else
+			{
+				pCap->SetChild(pCapNode);
+			}
+			pLast = pCapNode;
+		}
+
+		pChild = pChild->next;
+	}
+
+	return(pCap);
 }
 
 
-XPFCapability* PluginOILFilter::CreateColourNode(IXMLDOMNode* pNode)
+/*XPFCapability* PluginOILFilter::CreateColourNode(IXMLDOMNode* pNode)
 {
 	XPFCapability* pCap = NULL;
 
@@ -2264,8 +3029,58 @@
 	}
 
 	return(pCap);
+}*/
+
+XPFCapability* PluginOILFilter::CreateColourNode(xmlNodePtr pNode)
+{
+	XPFCapability* pCap = NULL;
+
+	wxString strName = CXMLUtils::ConvertToWXString(pNode->name);
+	
+	if (strName == _T("#text") || xmlNodeIsText(pNode))
+	{
+		return(NULL);
+	}
+
+	XPFConvertType AsType = XPFCONVTYPE_UNKNOWN;
+	HRESULT hRes = GetConvertAsType(pNode, &AsType);
+	if (strName == _T("Colour"))
+	{
+		pCap = new XPFCColour(AsType);
+	}
+	else
+	{
+		ERROR1(NULL, _R(IDE_XPF_BADXML));
+	}
+
+	xmlNodePtr pChild;
+	pChild = pNode->children;
+	XPFCapability* pLast = NULL;
+
+	while (pChild)
+	{
+		XPFCapability* pCapNode = CreateColourNode(pChild);
+
+		if (pCapNode)
+		{
+			// If we have a node then add it to the list
+			// If we do not have a node already then set m_pObjects
+			if (pLast)
+			{
+				pLast->SetNext(pCapNode);
+			}
+			else
+			{
+				pCap->SetChild(pCapNode);
+			}
+			pLast = pCapNode;
+		}
+
+		pChild = pChild->next;
+	}
+
+	return(pCap);
 }
-#endif
 
 /****************************************************************************
 
@@ -2285,3 +3100,6 @@
 	ReleaseFilterObject();
 #endif
 }
+
+
+
Index: Trunk/XaraLX/wxOil/compatdef.h
===================================================================
--- Trunk/XaraLX/wxOil/compatdef.h	(revision 991)
+++ Trunk/XaraLX/wxOil/compatdef.h	(revision 992)
@@ -327,6 +327,7 @@
 
 typedef DWORD				HRESULT;
 const HRESULT				S_OK = 0;
+const HRESULT				E_FAIL = 0x80004005;
 
 typedef char			   *LPSTR;
 typedef const char		   *LPCSTR;
Index: Trunk/XaraLX/wxOil/xmlutils.h
===================================================================
--- Trunk/XaraLX/wxOil/xmlutils.h	(revision 0)
+++ Trunk/XaraLX/wxOil/xmlutils.h	(revision 992)
@@ -0,0 +1,163 @@
+// $Id: xmlutils.h 751 2006-03-31 15:43:49Z alex $
+/* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
+================================XARAHEADERSTART===========================
+ 
+               Xara LX, a vector drawing and manipulation program.
+                    Copyright (C) 1993-2006 Xara Group Ltd.
+       Copyright on certain contributions may be held in joint with their
+              respective authors. See AUTHORS file for details.
+
+LICENSE TO USE AND MODIFY SOFTWARE
+----------------------------------
+
+This file is part of Xara LX.
+
+Xara LX is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 as published
+by the Free Software Foundation.
+
+Xara LX and its component source files are distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with Xara LX (see the file GPL in the root directory of the
+distribution); if not, write to the Free Software Foundation, Inc., 51
+Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+
+
+ADDITIONAL RIGHTS
+-----------------
+
+Conditional upon your continuing compliance with the GNU General Public
+License described above, Xara Group Ltd grants to you certain additional
+rights. 
+
+The additional rights are to use, modify, and distribute the software
+together with the wxWidgets library, the wxXtra library, and the "CDraw"
+library and any other such library that any version of Xara LX relased
+by Xara Group Ltd requires in order to compile and execute, including
+the static linking of that library to XaraLX. In the case of the
+"CDraw" library, you may satisfy obligation under the GNU General Public
+License to provide source code by providing a binary copy of the library
+concerned and a copy of the license accompanying it.
+
+Nothing in this section restricts any of the rights you have under
+the GNU General Public License.
+
+
+SCOPE OF LICENSE
+----------------
+
+This license applies to this program (XaraLX) and its constituent source
+files only, and does not necessarily apply to other Xara products which may
+in part share the same code base, and are subject to their own licensing
+terms.
+
+This license does not apply to files in the wxXtra directory, which
+are built into a separate library, and are subject to the wxWindows
+license contained within that directory in the file "WXXTRA-LICENSE".
+
+This license does not apply to the binary libraries (if any) within
+the "libs" directory, which are subject to a separate license contained
+within that directory in the file "LIBS-LICENSE".
+
+
+ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
+----------------------------------------------
+
+Subject to the terms of the GNU Public License (see above), you are
+free to do whatever you like with your modifications. However, you may
+(at your option) wish contribute them to Xara's source tree. You can
+find details of how to do this at:
+  http://www.xaraxtreme.org/developers/
+
+Prior to contributing your modifications, you will need to complete our
+contributor agreement. This can be found at:
+  http://www.xaraxtreme.org/developers/contribute/
+
+Please note that Xara will not accept modifications which modify any of
+the text between the start and end of this header (marked
+XARAHEADERSTART and XARAHEADEREND).
+
+
+MARKS
+-----
+
+Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
+designs are registered or unregistered trademarks, design-marks, and/or
+service marks of Xara Group Ltd. All rights in these marks are reserved.
+
+
+      Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
+                        http://www.xara.com/
+
+=================================XARAHEADEREND============================
+ */
+
+// The module that controls the OIL side of plugin import/export filters.
+
+#ifndef INC_XMLUTILS
+#define INC_XMLUTILS
+
+#include <libxml/xpathInternals.h>
+
+class CXMLUtils : public CCObject
+{
+public:
+	CXMLUtils() {;}
+	virtual ~CXMLUtils() {;}
+
+	static BOOL			Initialise();
+	static BOOL			DeInitialise();
+
+	// All unicode data is stored as UTF-8 in libxml2 and xmlChar* is a pointer to a UTF-8 byte stream
+	// Remember that unicode data is stored as UTF-16 in XAR files, as UTF-16 in memory on Windows builds
+	// but as UTF-4/UTF-32 in memory on Linuxbuilds. So we need conversion functions!
+	static wxString 	ConvertToWXString(const xmlChar*);
+	static void			ConvertToXMLString(wxString str, xmlChar** pxmlstr);
+
+
+#if _DEBUG
+	static void Test();
+	static int example4(const char *filename, const xmlChar * xpathExpr, const xmlChar * value);
+	static void update_xpath_nodes(xmlNodeSetPtr nodes, const xmlChar * value);
+#endif
+
+
+/*	static IXMLDOMDocument2Ptr NewDocument();
+	static IXMLDOMDocument2Ptr NewDocument(IXMLDOMDocument2Ptr pCopySourceDoc);
+
+	static PrepareDocument(IXMLDOMNodePtr pNode);
+	static PrepareDocument(IXMLDOMDocument2Ptr pDoc2);
+	static AddEncodingInstruction(IXMLDOMDocument2Ptr pDoc2,
+									const CString& strVersion,
+									const CString& strEncoding);
+
+	static IXMLDOMElementPtr AppendElement(IXMLDOMElementPtr pContext, const CString& elname, const CString* value = NULL);
+	static IXMLDOMElementPtr AppendElement(IXMLDOMElementPtr pContext, const CString& elname, const LONG lValue);
+	static IXMLDOMElementPtr AppendElement(IXMLDOMElementPtr pContext, const CString& elname, const BOOL bValue);
+
+	static BOOL		ReplaceElement(IXMLDOMElementPtr pElement, const CString& strElPath, const CString& strText, const BOOL bIgnoreBlank = FALSE);
+	static BOOL		ReplaceElement(IXMLDOMElementPtr pElement, const CString& strElPath, const LONG lValue);
+	static BOOL		ReplaceElement(IXMLDOMElementPtr pElement, const CString& strElPath, const BOOL bValue);
+
+	static CString	GetNodeString(IXMLDOMNodePtr pNode, const CString& strNodePath, const CString& strDefault = _T(""));
+	static LONG		GetNodeLong(IXMLDOMNodePtr pNode, const CString& strNodePath, const LONG lDefault = 0);
+	static BOOL		GetNodeBOOL(IXMLDOMNodePtr pNode, const CString& strNodePath, const BOOL bDefault = FALSE);
+
+	static CString	GetAttributeString(IXMLDOMElementPtr pNode, const CString& strAttrName, const CString& strDefault = _T(""));
+	static LONG		GetAttributeLong(IXMLDOMElementPtr pNode, const CString& strAttrName, const LONG lDefault = 0);
+	static BOOL		GetAttributeBOOL(IXMLDOMElementPtr pNode, const CString& strAttrName, const BOOL bDefault = FALSE);
+
+	static BOOL		SetAttribute(IXMLDOMNodePtr pNode, const CString& strName, const CString& strValue);
+	static BOOL		SetAttribute(IXMLDOMNodePtr pNode, const CString& strName, const LONG lValue);
+	static BOOL		SetAttribute(IXMLDOMNodePtr pNode, const CString& strName, const BOOL bValue);
+
+	static CString	GetNodeName(IXMLDOMNodePtr pNode);
+*/
+};
+
+#endif // INC_XMLUTILS
+
Index: Trunk/XaraLX/wxOil/Makefile.am
===================================================================
--- Trunk/XaraLX/wxOil/Makefile.am	(revision 991)
+++ Trunk/XaraLX/wxOil/Makefile.am	(revision 992)
@@ -42,7 +42,7 @@
 	ctrllist.cpp dlgcol.cpp thumb.cpp dragmgr.cpp ccolbar.cpp dragcol.cpp \
 	drawctl.cpp filedlgs.cpp fileutil.cpp ktimer.cpp camplatform.cpp \
 	outptdib.cpp outptpng.cpp outptgif.cpp gpalopt.cpp bmpfiltr.cpp giffiltr.cpp \
-	fontbase.cpp ftfonts.cpp textfuns.cpp dragbmp.cpp xpoilflt.cpp \
+	fontbase.cpp ftfonts.cpp textfuns.cpp dragbmp.cpp xpoilflt.cpp xmlutils.cpp \
 	fltrdisc.cpp camprocess.cpp \
 	resources.cpp
 
Index: Trunk/XaraLX/wxOil/xpoilflt.h
===================================================================
--- Trunk/XaraLX/wxOil/xpoilflt.h	(revision 991)
+++ Trunk/XaraLX/wxOil/xpoilflt.h	(revision 992)
@@ -110,6 +110,7 @@
 #endif
 
 #include "xpfcaps.h"
+#include "xmlutils.h"
 
 class PluginNativeFilter;
 
@@ -198,27 +199,24 @@
 	void ReleaseFilterObject();
 #endif
 
-PORTNOTE("other","PluginFilter XML bits removed")
-#if !defined(EXCLUDE_FROM_XARALX)
 //	This function is called from GetCapabilities to parse the XML
-	HRESULT BuildCapabilityTree(BSTR bsXML, CapabilityTree* pCapTree);
+	BOOL BuildCapabilityTree(wxString strXML, CapabilityTree* pCapTree);
 
-	// The functions from here down to CreateColourNode are all concerned with the 
+	// The functions from here down to CreateColourNode are all concerned with the
 	// parsing of the XML and the creation of the CapabilityTree
-	HRESULT ReadOptions(IXMLDOMNode* pNode, CapabilityTree* pCapTree);
-	HRESULT ReadRasterise(IXMLDOMNode* pNode, CapabilityTree* pCapTree);
-	HRESULT ReadSpread(IXMLDOMNode* pNode, CapabilityTree* pCapTree);
-	HRESULT ReadObjects(IXMLDOMNode* pNode, CapabilityTree* pCapTree);
-	HRESULT ReadAttributes(IXMLDOMNode* pNode, CapabilityTree* pCapTree);
-	HRESULT ReadColour(IXMLDOMNode* pNode, CapabilityTree* pCapTree);
+	BOOL ReadOptions(xmlNodePtr pNode, CapabilityTree* pCapTree);
+	BOOL ReadRasterise(xmlNodePtr pNode, CapabilityTree* pCapTree);
+	BOOL ReadSpread(xmlNodePtr pNode, CapabilityTree* pCapTree);
+	BOOL ReadObjects(xmlNodePtr pNode, CapabilityTree* pCapTree);
+	BOOL ReadAttributes(xmlNodePtr pNode, CapabilityTree* pCapTree);
+	BOOL ReadColour(xmlNodePtr pNode, CapabilityTree* pCapTree);
 
-	HRESULT GetConvertAsType(IXMLDOMNode* pNode, XPFConvertType* pValue);
-	HRESULT GetXPFBOOL(IXMLDOMNode* pNode, LPTSTR pAttrName, XPFBOOL* pbValue);
-	HRESULT GetXPFProp(IXMLDOMNode* pNode, LPTSTR pAttrName, PropMapEntry aMap[], XPFProp* pValue);
-	XPFCapability* CreateObjectNode(IXMLDOMNode* pNode);
-	XPFCapability* CreateAttributeNode(IXMLDOMNode* pNode);
-	XPFCapability* CreateColourNode(IXMLDOMNode* pNode);
-#endif
+	BOOL GetConvertAsType(xmlNodePtr pNode, XPFConvertType* pValue);
+	BOOL GetXPFBOOL(xmlNodePtr pNode, LPTSTR pAttrName, XPFBOOL* pbValue);
+	BOOL GetXPFProp(xmlNodePtr pNode, LPTSTR pAttrName, PropMapEntry aMap[], XPFProp* pValue);
+	XPFCapability* CreateObjectNode(xmlNodePtr pNode);
+	XPFCapability* CreateAttributeNode(xmlNodePtr pNode);
+	XPFCapability* CreateColourNode(xmlNodePtr pNode);
 
 protected:
 	BOOL m_bImport;
Index: Trunk/XaraLX/wxOil/camelot.cpp
===================================================================
--- Trunk/XaraLX/wxOil/camelot.cpp	(revision 991)
+++ Trunk/XaraLX/wxOil/camelot.cpp	(revision 992)
@@ -127,7 +127,9 @@
 #include "cartprov.h"
 #include "ctrllist.h"
 #include "cartctl.h"
+#include "xmlutils.h"
 #include "camplatform.h"
+
 //
 // Define FILELIST for recent file list on file menu.
 // Note that this currently seems to be rather unreliable.
@@ -236,8 +238,11 @@
 	if( event.GetEventType() == wxEVT_CHAR )
 	{
 		wxObject* pEventObject = event.GetEventObject();
-		TRACEUSER( "jlh92", _T("KeyEvent 4 %s CH
"), 
-			((wxWindow*)pEventObject)->GetClassInfo()->GetClassName() );
+		if (pEventObject)
+		{
+			TRACEUSER( "jlh92", _T("KeyEvent 4 %s CH
"), 
+				((wxWindow*)pEventObject)->GetClassInfo()->GetClassName() );
+		}
 	}
 
 	if( event.GetEventType() == wxEVT_KEY_DOWN ||
@@ -654,6 +659,8 @@
 	// Remove the splash screen
 	CamResource::DoneInit();
 
+	CXMLUtils::Initialise();
+
 	// Give focus to any child that will take it, parent can't have it since
 	// it's a frame (see gtk_widget_grab_focus)
 	GiveFocusToFocusableOffspring( m_pMainFrame );
@@ -687,6 +694,8 @@
 
 	// Now deinit everything
 
+	CXMLUtils::DeInitialise();
+
 	DeinitKernel();
 
 #if CUSTOM_INONE == 2
Index: Trunk/XaraLX/wxOil/xmlutils.cpp
===================================================================
--- Trunk/XaraLX/wxOil/xmlutils.cpp	(revision 0)
+++ Trunk/XaraLX/wxOil/xmlutils.cpp	(revision 992)
@@ -0,0 +1,359 @@
+// $Id: xmlutils.cpp 836 2006-04-18 16:06:15Z gerry $
+/* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
+================================XARAHEADERSTART===========================
+ 
+               Xara LX, a vector drawing and manipulation program.
+                    Copyright (C) 1993-2006 Xara Group Ltd.
+       Copyright on certain contributions may be held in joint with their
+              respective authors. See AUTHORS file for details.
+
+LICENSE TO USE AND MODIFY SOFTWARE
+----------------------------------
+
+This file is part of Xara LX.
+
+Xara LX is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 as published
+by the Free Software Foundation.
+
+Xara LX and its component source files are distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with Xara LX (see the file GPL in the root directory of the
+distribution); if not, write to the Free Software Foundation, Inc., 51
+Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+
+
+ADDITIONAL RIGHTS
+-----------------
+
+Conditional upon your continuing compliance with the GNU General Public
+License described above, Xara Group Ltd grants to you certain additional
+rights. 
+
+The additional rights are to use, modify, and distribute the software
+together with the wxWidgets library, the wxXtra library, and the "CDraw"
+library and any other such library that any version of Xara LX relased
+by Xara Group Ltd requires in order to compile and execute, including
+the static linking of that library to XaraLX. In the case of the
+"CDraw" library, you may satisfy obligation under the GNU General Public
+License to provide source code by providing a binary copy of the library
+concerned and a copy of the license accompanying it.
+
+Nothing in this section restricts any of the rights you have under
+the GNU General Public License.
+
+
+SCOPE OF LICENSE
+----------------
+
+This license applies to this program (XaraLX) and its constituent source
+files only, and does not necessarily apply to other Xara products which may
+in part share the same code base, and are subject to their own licensing
+terms.
+
+This license does not apply to files in the wxXtra directory, which
+are built into a separate library, and are subject to the wxWindows
+license contained within that directory in the file "WXXTRA-LICENSE".
+
+This license does not apply to the binary libraries (if any) within
+the "libs" directory, which are subject to a separate license contained
+within that directory in the file "LIBS-LICENSE".
+
+
+ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
+----------------------------------------------
+
+Subject to the terms of the GNU Public License (see above), you are
+free to do whatever you like with your modifications. However, you may
+(at your option) wish contribute them to Xara's source tree. You can
+find details of how to do this at:
+  http://www.xaraxtreme.org/developers/
+
+Prior to contributing your modifications, you will need to complete our
+contributor agreement. This can be found at:
+  http://www.xaraxtreme.org/developers/contribute/
+
+Please note that Xara will not accept modifications which modify any of
+the text between the start and end of this header (marked
+XARAHEADERSTART and XARAHEADEREND).
+
+
+MARKS
+-----
+
+Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
+designs are registered or unregistered trademarks, design-marks, and/or
+service marks of Xara Group Ltd. All rights in these marks are reserved.
+
+
+      Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
+                        http://www.xara.com/
+
+=================================XARAHEADEREND============================
+ */
+
+// The module that controls the OIL side of import/export filters.
+
+
+#include "camtypes.h"
+
+#include "xmlutils.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+//#include <libxml/xpath.h>
+
+/************************************************************************************
+> 	BOOL CXMLUtils::Initialise()
+
+    Author: 	Phil_Martin (Xara Group Ltd) <camelotdev@xxxxxxxx>
+    Created:	08/May/2006
+	Inputs:		-
+	Outputs:	-
+	Returns:	TRUE if succeeded
+    Purpose:	Set up application wide XML support
+
+************************************************************************************/
+BOOL CXMLUtils::Initialise()
+{
+	xmlInitParser();
+    LIBXML_TEST_VERSION
+
+	return TRUE;
+}
+
+
+
+
+/************************************************************************************
+> 	BOOL CXMLUtils::DeInitialise()
+
+    Author: 	Phil_Martin (Xara Group Ltd) <camelotdev@xxxxxxxx>
+    Created:	08/May/2006
+	Inputs:		-
+	Outputs:	-
+	Returns:	TRUE if succeeded
+    Purpose:	Set up application wide XML support
+
+************************************************************************************/
+BOOL CXMLUtils::DeInitialise()
+{
+	xmlCleanupParser();
+
+#if _DEBUG
+    /*
+     * this is to debug memory for regression tests
+     */
+    xmlMemoryDump();
+#endif
+
+	return TRUE;
+}
+
+
+
+
+/************************************************************************************
+>	static wxString CXMLUtils::ConvertToWXString(xmlChar* xmlString)
+
+    Author: 	Phil_Martin (Xara Group Ltd) <camelotdev@xxxxxxxx>
+    Created:	08/May/2006
+	Inputs:		-
+	Outputs:	-
+	Returns:	Pointer to newly allocated StringBase object (caller takes ownership)
+    Purpose:	Set up application wide XML support
+
+************************************************************************************/
+wxString CXMLUtils::ConvertToWXString(const xmlChar* xmlString)
+{
+	// Use wx to convert from UTF8 to native
+	wxString strTemp((const char*)xmlString, wxConvUTF8);
+
+	return strTemp;
+}
+
+
+
+
+/************************************************************************************
+>	static void CXMLUtils::ConvertToXMLString(wxString str)
+
+    Author: 	Phil_Martin (Xara Group Ltd) <camelotdev@xxxxxxxx>
+    Created:	09/May/2006
+	Inputs:		str - wxString input
+	Outputs:	pxmlstr - xmlChar* output
+	Returns:	Pointer to newly allocated StringBase object (caller takes ownership)
+    Purpose:	Set up application wide XML support
+
+************************************************************************************/
+void CXMLUtils::ConvertToXMLString(wxString str, xmlChar** pxmlstr)
+{
+//	wxCharBuffer buf = str.mb_str(wxConvUTF8);
+//	wxStrdup from buf to pxmlstr?
+}
+
+
+
+
+#if _DEBUG
+#if defined(LIBXML_XPATH_ENABLED) && \
+	defined(LIBXML_SAX1_ENABLED) && \
+    defined(LIBXML_OUTPUT_ENABLED)
+
+/*
+ * section: 	XPath
+ * synopsis: 	Load a document, locate subelements with XPath, modify
+ *              said elements and save the resulting document.
+ * purpose: 	Shows how to make a full round-trip from a load/edit/save
+ * usage:	xpath2 <xml-file> <xpath-expr> <new-value>
+ * test:	xpath2 test3.xml '//discarded' discarded > xpath2.tmp ; diff xpath2.tmp xpath2.res ; rm xpath2.tmp
+ * author: 	Aleksey Sanin and Daniel Veillard
+ * copy: 	see Copyright for the status of this software.
+ */
+void CXMLUtils::Test()
+{
+    /* Init libxml */
+    xmlInitParser();
+    LIBXML_TEST_VERSION
+
+    /* Do the main job */
+    example4("/tmp/testin.xml", (xmlChar*)"//fred", (xmlChar*)"jim");
+
+    /* Shutdown libxml */
+    xmlCleanupParser();
+    
+    /*
+     * this is to debug memory for regression tests
+     */
+    xmlMemoryDump();
+}
+
+/**
+ * example4:
+ * @filename:		the input XML filename.
+ * @xpathExpr:		the xpath expression for evaluation.
+ * @value:		the new node content.
+ *
+ * Parses input XML file, evaluates XPath expression and update the nodes
+ * then print the result.
+ *
+ * Returns 0 on success and a negative value otherwise.
+ */
+int CXMLUtils::example4(const char* filename, const xmlChar* xpathExpr, const xmlChar* value)
+{
+    xmlDocPtr doc;
+    xmlXPathContextPtr xpathCtx; 
+    xmlXPathObjectPtr xpathObj; 
+    
+    assert(filename);
+    assert(xpathExpr);
+    assert(value);
+
+    /* Load XML document */
+    doc = xmlParseFile(filename);
+    if (doc == NULL) {
+	fprintf(stderr, "Error: unable to parse file \"%s\"
", filename);
+	return(-1);
+    }
+
+    /* Create xpath evaluation context */
+    xpathCtx = xmlXPathNewContext(doc);
+    if(xpathCtx == NULL) {
+        fprintf(stderr,"Error: unable to create new XPath context
");
+        xmlFreeDoc(doc); 
+        return(-1);
+    }
+    
+    /* Evaluate xpath expression */
+    xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx);
+    if(xpathObj == NULL) {
+        fprintf(stderr,"Error: unable to evaluate xpath expression \"%s\"
", xpathExpr);
+        xmlXPathFreeContext(xpathCtx); 
+        xmlFreeDoc(doc); 
+        return(-1);
+    }
+
+    /* update selected nodes */
+    update_xpath_nodes(xpathObj->nodesetval, value);
+
+    
+    /* Cleanup of XPath data */
+    xmlXPathFreeObject(xpathObj);
+    xmlXPathFreeContext(xpathCtx); 
+
+    /* dump the resulting document */
+    xmlDocDump(stdout, doc);
+
+	/* save the doc out to a temp file */
+	xmlSaveFileEnc("/tmp/testout.xml", doc, "UTF-8");
+
+    /* free the document */
+    xmlFreeDoc(doc); 
+    
+    return(0);
+}
+
+/**
+ * update_xpath_nodes:
+ * @nodes:		the nodes set.
+ * @value:		the new value for the node(s)
+ *
+ * Prints the @nodes content to @output.
+ */
+void CXMLUtils::update_xpath_nodes(xmlNodeSetPtr nodes, const xmlChar* value)
+{
+    int size;
+    int i;
+    
+    assert(value);
+    size = (nodes) ? nodes->nodeNr : 0;
+    
+    /*
+     * NOTE: the nodes are processed in reverse order, i.e. reverse document
+     *       order because xmlNodeSetContent can actually free up descendant
+     *       of the node and such nodes may have been selected too ! Handling
+     *       in reverse order ensure that descendant are accessed first, before
+     *       they get removed. Mixing XPath and modifications on a tree must be
+     *       done carefully !
+     */
+    for(i = size - 1; i >= 0; i--) {
+	assert(nodes->nodeTab[i]);
+	
+	xmlNodeSetContent(nodes->nodeTab[i], value);
+	/*
+	 * All the elements returned by an XPath query are pointers to
+	 * elements from the tree *except* namespace nodes where the XPath
+	 * semantic is different from the implementation in libxml2 tree.
+	 * As a result when a returned node set is freed when
+	 * xmlXPathFreeObject() is called, that routine must check the
+	 * element type. But node from the returned set may have been removed
+	 * by xmlNodeSetContent() resulting in access to freed data.
+	 * This can be exercised by running
+	 *       valgrind xpath2 test3.xml '//discarded' discarded
+	 * There is 2 ways around it:
+	 *   - make a copy of the pointers to the nodes from the result set 
+	 *     then call xmlXPathFreeObject() and then modify the nodes
+	 * or
+	 *   - remove the reference to the modified nodes from the node set
+	 *     as they are processed, if they are not namespace nodes.
+	 */
+	if (nodes->nodeTab[i]->type != XML_NAMESPACE_DECL)
+	    nodes->nodeTab[i] = NULL;
+    }
+}
+
+#else
+	#pragma error "XPath support not compiled in"
+#endif
+
+#endif
+


Xara