xref: /aoo4110/main/unoxml/source/dom/node.cxx (revision b1cdbd2c)
1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski #include <node.hxx>
25*b1cdbd2cSJim Jagielski 
26*b1cdbd2cSJim Jagielski #include <stdio.h>
27*b1cdbd2cSJim Jagielski #include <string.h>
28*b1cdbd2cSJim Jagielski 
29*b1cdbd2cSJim Jagielski #include <libxml/xmlstring.h>
30*b1cdbd2cSJim Jagielski 
31*b1cdbd2cSJim Jagielski #include <algorithm>
32*b1cdbd2cSJim Jagielski 
33*b1cdbd2cSJim Jagielski #include <boost/bind.hpp>
34*b1cdbd2cSJim Jagielski 
35*b1cdbd2cSJim Jagielski #include <rtl/uuid.h>
36*b1cdbd2cSJim Jagielski #include <rtl/instance.hxx>
37*b1cdbd2cSJim Jagielski #include <osl/mutex.hxx>
38*b1cdbd2cSJim Jagielski 
39*b1cdbd2cSJim Jagielski #include <com/sun/star/xml/sax/FastToken.hpp>
40*b1cdbd2cSJim Jagielski 
41*b1cdbd2cSJim Jagielski #include <document.hxx>
42*b1cdbd2cSJim Jagielski #include <attr.hxx>
43*b1cdbd2cSJim Jagielski #include <childlist.hxx>
44*b1cdbd2cSJim Jagielski 
45*b1cdbd2cSJim Jagielski #include "../events/eventdispatcher.hxx"
46*b1cdbd2cSJim Jagielski #include "../events/mutationevent.hxx"
47*b1cdbd2cSJim Jagielski 
48*b1cdbd2cSJim Jagielski 
49*b1cdbd2cSJim Jagielski 
50*b1cdbd2cSJim Jagielski using namespace ::com::sun::star;
51*b1cdbd2cSJim Jagielski 
52*b1cdbd2cSJim Jagielski 
53*b1cdbd2cSJim Jagielski namespace {
54*b1cdbd2cSJim Jagielski     struct UnoTunnelId
55*b1cdbd2cSJim Jagielski         : public ::rtl::StaticWithInit< Sequence<sal_Int8>, UnoTunnelId >
56*b1cdbd2cSJim Jagielski     {
operator ()__anonbe23c9670111::UnoTunnelId57*b1cdbd2cSJim Jagielski         Sequence<sal_Int8> operator() ()
58*b1cdbd2cSJim Jagielski         {
59*b1cdbd2cSJim Jagielski             Sequence<sal_Int8> ret(16);
60*b1cdbd2cSJim Jagielski             rtl_createUuid(
61*b1cdbd2cSJim Jagielski                 reinterpret_cast<sal_uInt8*>(ret.getArray()), 0, sal_True);
62*b1cdbd2cSJim Jagielski             return ret;
63*b1cdbd2cSJim Jagielski         }
64*b1cdbd2cSJim Jagielski     };
65*b1cdbd2cSJim Jagielski }
66*b1cdbd2cSJim Jagielski 
67*b1cdbd2cSJim Jagielski namespace DOM
68*b1cdbd2cSJim Jagielski {
pushContext(Context & io_rContext)69*b1cdbd2cSJim Jagielski     void pushContext(Context& io_rContext)
70*b1cdbd2cSJim Jagielski     {
71*b1cdbd2cSJim Jagielski         io_rContext.maNamespaces.push_back(
72*b1cdbd2cSJim Jagielski             io_rContext.maNamespaces.back());
73*b1cdbd2cSJim Jagielski     }
74*b1cdbd2cSJim Jagielski 
popContext(Context & io_rContext)75*b1cdbd2cSJim Jagielski     void popContext(Context& io_rContext)
76*b1cdbd2cSJim Jagielski     {
77*b1cdbd2cSJim Jagielski         io_rContext.maNamespaces.pop_back();
78*b1cdbd2cSJim Jagielski     }
79*b1cdbd2cSJim Jagielski 
addNamespaces(Context & io_rContext,xmlNodePtr pNode)80*b1cdbd2cSJim Jagielski     void addNamespaces(Context& io_rContext, xmlNodePtr pNode)
81*b1cdbd2cSJim Jagielski     {
82*b1cdbd2cSJim Jagielski         // add node's namespaces to current context
83*b1cdbd2cSJim Jagielski         for (xmlNsPtr pNs = pNode->nsDef; pNs != 0; pNs = pNs->next) {
84*b1cdbd2cSJim Jagielski             const xmlChar *pPrefix = pNs->prefix;
85*b1cdbd2cSJim Jagielski             OString prefix(reinterpret_cast<const sal_Char*>(pPrefix),
86*b1cdbd2cSJim Jagielski                            strlen(reinterpret_cast<const char*>(pPrefix)));
87*b1cdbd2cSJim Jagielski             const xmlChar *pHref = pNs->href;
88*b1cdbd2cSJim Jagielski             OUString val(reinterpret_cast<const sal_Char*>(pHref),
89*b1cdbd2cSJim Jagielski                 strlen(reinterpret_cast<const char*>(pHref)),
90*b1cdbd2cSJim Jagielski                 RTL_TEXTENCODING_UTF8);
91*b1cdbd2cSJim Jagielski 
92*b1cdbd2cSJim Jagielski             OSL_TRACE("Trying to add namespace %s (prefix %s)",
93*b1cdbd2cSJim Jagielski                       (const char*)pHref, (const char*)pPrefix);
94*b1cdbd2cSJim Jagielski 
95*b1cdbd2cSJim Jagielski             Context::NamespaceMapType::iterator aIter=
96*b1cdbd2cSJim Jagielski                 io_rContext.maNamespaceMap.find(val);
97*b1cdbd2cSJim Jagielski             if( aIter != io_rContext.maNamespaceMap.end() )
98*b1cdbd2cSJim Jagielski             {
99*b1cdbd2cSJim Jagielski                 Context::Namespace aNS;
100*b1cdbd2cSJim Jagielski                 aNS.maPrefix = prefix;
101*b1cdbd2cSJim Jagielski                 aNS.mnToken = aIter->second;
102*b1cdbd2cSJim Jagielski                 aNS.maNamespaceURL = val;
103*b1cdbd2cSJim Jagielski 
104*b1cdbd2cSJim Jagielski                 io_rContext.maNamespaces.back().push_back(aNS);
105*b1cdbd2cSJim Jagielski 
106*b1cdbd2cSJim Jagielski                 OSL_TRACE("Added with token 0x%x", aIter->second);
107*b1cdbd2cSJim Jagielski             }
108*b1cdbd2cSJim Jagielski         }
109*b1cdbd2cSJim Jagielski     }
110*b1cdbd2cSJim Jagielski 
getToken(const Context & rContext,const sal_Char * pToken)111*b1cdbd2cSJim Jagielski     sal_Int32 getToken( const Context& rContext, const sal_Char* pToken )
112*b1cdbd2cSJim Jagielski     {
113*b1cdbd2cSJim Jagielski         const Sequence<sal_Int8> aSeq( (sal_Int8*)pToken, strlen( pToken ) );
114*b1cdbd2cSJim Jagielski         return rContext.mxTokenHandler->getTokenFromUTF8( aSeq );
115*b1cdbd2cSJim Jagielski     }
116*b1cdbd2cSJim Jagielski 
getTokenWithPrefix(const Context & rContext,const sal_Char * pPrefix,const sal_Char * pName)117*b1cdbd2cSJim Jagielski     sal_Int32 getTokenWithPrefix( const Context& rContext, const sal_Char* pPrefix, const sal_Char* pName )
118*b1cdbd2cSJim Jagielski     {
119*b1cdbd2cSJim Jagielski         sal_Int32 nNamespaceToken = FastToken::DONTKNOW;
120*b1cdbd2cSJim Jagielski         OString prefix(pPrefix,
121*b1cdbd2cSJim Jagielski                        strlen(reinterpret_cast<const char*>(pPrefix)));
122*b1cdbd2cSJim Jagielski 
123*b1cdbd2cSJim Jagielski         OSL_TRACE("getTokenWithPrefix(): prefix %s, name %s",
124*b1cdbd2cSJim Jagielski                   (const char*)pPrefix, (const char*)pName);
125*b1cdbd2cSJim Jagielski 
126*b1cdbd2cSJim Jagielski         Context::NamespaceVectorType::value_type::const_iterator aIter;
127*b1cdbd2cSJim Jagielski         if( (aIter=std::find_if(rContext.maNamespaces.back().begin(),
128*b1cdbd2cSJim Jagielski                                 rContext.maNamespaces.back().end(),
129*b1cdbd2cSJim Jagielski                                 boost::bind(std::equal_to<OString>(),
130*b1cdbd2cSJim Jagielski                                             boost::bind(&Context::Namespace::getPrefix,
131*b1cdbd2cSJim Jagielski                                                         _1),
132*b1cdbd2cSJim Jagielski                                             boost::cref(prefix)))) != rContext.maNamespaces.back().end() )
133*b1cdbd2cSJim Jagielski         {
134*b1cdbd2cSJim Jagielski             nNamespaceToken = aIter->mnToken;
135*b1cdbd2cSJim Jagielski             sal_Int32 nNameToken = getToken( rContext, pName );
136*b1cdbd2cSJim Jagielski             if( nNameToken != FastToken::DONTKNOW )
137*b1cdbd2cSJim Jagielski                 nNamespaceToken |= nNameToken;
138*b1cdbd2cSJim Jagielski         }
139*b1cdbd2cSJim Jagielski 
140*b1cdbd2cSJim Jagielski         return nNamespaceToken;
141*b1cdbd2cSJim Jagielski     }
142*b1cdbd2cSJim Jagielski 
143*b1cdbd2cSJim Jagielski 
CNode(CDocument const & rDocument,::osl::Mutex const & rMutex,NodeType const & reNodeType,xmlNodePtr const & rpNode)144*b1cdbd2cSJim Jagielski     CNode::CNode(CDocument const& rDocument, ::osl::Mutex const& rMutex,
145*b1cdbd2cSJim Jagielski                 NodeType const& reNodeType, xmlNodePtr const& rpNode)
146*b1cdbd2cSJim Jagielski         :   m_bUnlinked(false)
147*b1cdbd2cSJim Jagielski         ,   m_aNodeType(reNodeType)
148*b1cdbd2cSJim Jagielski         ,   m_aNodePtr(rpNode)
149*b1cdbd2cSJim Jagielski         // keep containing document alive
150*b1cdbd2cSJim Jagielski         // (but not if this is a document; that would create a leak!)
151*b1cdbd2cSJim Jagielski         ,   m_xDocument( (m_aNodePtr->type != XML_DOCUMENT_NODE)
152*b1cdbd2cSJim Jagielski                 ? &const_cast<CDocument&>(rDocument) : 0 )
153*b1cdbd2cSJim Jagielski         ,   m_rMutex(const_cast< ::osl::Mutex & >(rMutex))
154*b1cdbd2cSJim Jagielski     {
155*b1cdbd2cSJim Jagielski         OSL_ASSERT(m_aNodePtr);
156*b1cdbd2cSJim Jagielski     }
157*b1cdbd2cSJim Jagielski 
invalidate()158*b1cdbd2cSJim Jagielski     void CNode::invalidate()
159*b1cdbd2cSJim Jagielski     {
160*b1cdbd2cSJim Jagielski         //remove from list if this wrapper goes away
161*b1cdbd2cSJim Jagielski         if (m_aNodePtr != 0 && m_xDocument.is()) {
162*b1cdbd2cSJim Jagielski             m_xDocument->RemoveCNode(m_aNodePtr, this);
163*b1cdbd2cSJim Jagielski         }
164*b1cdbd2cSJim Jagielski         // #i113663#: unlinked nodes will not be freed by xmlFreeDoc
165*b1cdbd2cSJim Jagielski         if (m_bUnlinked) {
166*b1cdbd2cSJim Jagielski             xmlFreeNode(m_aNodePtr);
167*b1cdbd2cSJim Jagielski         }
168*b1cdbd2cSJim Jagielski         m_aNodePtr = 0;
169*b1cdbd2cSJim Jagielski     }
170*b1cdbd2cSJim Jagielski 
~CNode()171*b1cdbd2cSJim Jagielski     CNode::~CNode()
172*b1cdbd2cSJim Jagielski     {
173*b1cdbd2cSJim Jagielski         // if this is the document itself, the mutex is already freed!
174*b1cdbd2cSJim Jagielski         if (NodeType_DOCUMENT_NODE == m_aNodeType) {
175*b1cdbd2cSJim Jagielski             invalidate();
176*b1cdbd2cSJim Jagielski         } else {
177*b1cdbd2cSJim Jagielski             ::osl::MutexGuard const g(m_rMutex);
178*b1cdbd2cSJim Jagielski             invalidate(); // other nodes are still alive so must lock mutex
179*b1cdbd2cSJim Jagielski         }
180*b1cdbd2cSJim Jagielski     }
181*b1cdbd2cSJim Jagielski 
182*b1cdbd2cSJim Jagielski     CNode *
GetImplementation(uno::Reference<uno::XInterface> const & xNode)183*b1cdbd2cSJim Jagielski     CNode::GetImplementation(uno::Reference<uno::XInterface> const& xNode)
184*b1cdbd2cSJim Jagielski     {
185*b1cdbd2cSJim Jagielski         uno::Reference<lang::XUnoTunnel> const xUnoTunnel(xNode, UNO_QUERY);
186*b1cdbd2cSJim Jagielski         if (!xUnoTunnel.is()) { return 0; }
187*b1cdbd2cSJim Jagielski         CNode *const pCNode( reinterpret_cast< CNode* >(
188*b1cdbd2cSJim Jagielski                         ::sal::static_int_cast< sal_IntPtr >(
189*b1cdbd2cSJim Jagielski                             xUnoTunnel->getSomething(UnoTunnelId::get()))));
190*b1cdbd2cSJim Jagielski         return pCNode;
191*b1cdbd2cSJim Jagielski     }
192*b1cdbd2cSJim Jagielski 
GetOwnerDocument()193*b1cdbd2cSJim Jagielski     CDocument & CNode::GetOwnerDocument()
194*b1cdbd2cSJim Jagielski     {
195*b1cdbd2cSJim Jagielski         OSL_ASSERT(m_xDocument.is());
196*b1cdbd2cSJim Jagielski         return *m_xDocument; // needs overriding in CDocument!
197*b1cdbd2cSJim Jagielski     }
198*b1cdbd2cSJim Jagielski 
199*b1cdbd2cSJim Jagielski 
lcl_nsexchange(xmlNodePtr const aNode,xmlNsPtr const oldNs,xmlNsPtr const newNs)200*b1cdbd2cSJim Jagielski     static void lcl_nsexchange(
201*b1cdbd2cSJim Jagielski             xmlNodePtr const aNode, xmlNsPtr const oldNs, xmlNsPtr const newNs)
202*b1cdbd2cSJim Jagielski     {
203*b1cdbd2cSJim Jagielski         // recursively exchange any references to oldNs with references to newNs
204*b1cdbd2cSJim Jagielski         xmlNodePtr cur = aNode;
205*b1cdbd2cSJim Jagielski         while (cur != 0)
206*b1cdbd2cSJim Jagielski         {
207*b1cdbd2cSJim Jagielski             if (cur->ns == oldNs)
208*b1cdbd2cSJim Jagielski                 cur->ns = newNs;
209*b1cdbd2cSJim Jagielski             if (cur->type == XML_ELEMENT_NODE)
210*b1cdbd2cSJim Jagielski             {
211*b1cdbd2cSJim Jagielski                 xmlAttrPtr curAttr = cur->properties;
212*b1cdbd2cSJim Jagielski                 while(curAttr != 0)
213*b1cdbd2cSJim Jagielski                 {
214*b1cdbd2cSJim Jagielski                     if (curAttr->ns == oldNs)
215*b1cdbd2cSJim Jagielski                         curAttr->ns = newNs;
216*b1cdbd2cSJim Jagielski                     curAttr = curAttr->next;
217*b1cdbd2cSJim Jagielski                 }
218*b1cdbd2cSJim Jagielski                 lcl_nsexchange(cur->children, oldNs, newNs);
219*b1cdbd2cSJim Jagielski             }
220*b1cdbd2cSJim Jagielski             cur = cur->next;
221*b1cdbd2cSJim Jagielski         }
222*b1cdbd2cSJim Jagielski     }
223*b1cdbd2cSJim Jagielski 
nscleanup(const xmlNodePtr aNode,const xmlNodePtr aParent)224*b1cdbd2cSJim Jagielski     /*static*/ void nscleanup(const xmlNodePtr aNode, const xmlNodePtr aParent)
225*b1cdbd2cSJim Jagielski     {
226*b1cdbd2cSJim Jagielski         xmlNodePtr cur = aNode;
227*b1cdbd2cSJim Jagielski 
228*b1cdbd2cSJim Jagielski         //handle attributes
229*b1cdbd2cSJim Jagielski         if (cur != NULL && cur->type == XML_ELEMENT_NODE)
230*b1cdbd2cSJim Jagielski         {
231*b1cdbd2cSJim Jagielski             xmlAttrPtr curAttr = cur->properties;
232*b1cdbd2cSJim Jagielski             while(curAttr != 0)
233*b1cdbd2cSJim Jagielski             {
234*b1cdbd2cSJim Jagielski                 if (curAttr->ns != NULL)
235*b1cdbd2cSJim Jagielski                 {
236*b1cdbd2cSJim Jagielski                     xmlNsPtr ns = xmlSearchNs(cur->doc, aParent, curAttr->ns->prefix);
237*b1cdbd2cSJim Jagielski                     if (ns != NULL)
238*b1cdbd2cSJim Jagielski                         curAttr->ns = ns;
239*b1cdbd2cSJim Jagielski                 }
240*b1cdbd2cSJim Jagielski                 curAttr = curAttr->next;
241*b1cdbd2cSJim Jagielski             }
242*b1cdbd2cSJim Jagielski         }
243*b1cdbd2cSJim Jagielski 
244*b1cdbd2cSJim Jagielski         while (cur != NULL)
245*b1cdbd2cSJim Jagielski         {
246*b1cdbd2cSJim Jagielski             nscleanup(cur->children, cur);
247*b1cdbd2cSJim Jagielski             if (cur->ns != NULL)
248*b1cdbd2cSJim Jagielski             {
249*b1cdbd2cSJim Jagielski                 xmlNsPtr ns = xmlSearchNs(cur->doc, aParent, cur->ns->prefix);
250*b1cdbd2cSJim Jagielski                 if (ns != NULL && ns != cur->ns && strcmp((char*)ns->href, (char*)cur->ns->href)==0)
251*b1cdbd2cSJim Jagielski                 {
252*b1cdbd2cSJim Jagielski                     xmlNsPtr curDef = cur->nsDef;
253*b1cdbd2cSJim Jagielski                     xmlNsPtr *refp = &(cur->nsDef); // insert point
254*b1cdbd2cSJim Jagielski                     while (curDef != NULL)
255*b1cdbd2cSJim Jagielski                     {
256*b1cdbd2cSJim Jagielski                         ns = xmlSearchNs(cur->doc, aParent, curDef->prefix);
257*b1cdbd2cSJim Jagielski                         if (ns != NULL && ns != curDef && strcmp((char*)ns->href, (char*)curDef->href)==0)
258*b1cdbd2cSJim Jagielski                         {
259*b1cdbd2cSJim Jagielski                             // reconnect ns pointers in sub-tree to newly found ns before
260*b1cdbd2cSJim Jagielski                             // removing redundant nsdecl to prevent dangling pointers.
261*b1cdbd2cSJim Jagielski                             lcl_nsexchange(cur, curDef, ns);
262*b1cdbd2cSJim Jagielski                             *refp = curDef->next;
263*b1cdbd2cSJim Jagielski                             xmlFreeNs(curDef);
264*b1cdbd2cSJim Jagielski                             curDef = *refp;
265*b1cdbd2cSJim Jagielski                         } else {
266*b1cdbd2cSJim Jagielski                             refp = &(curDef->next);
267*b1cdbd2cSJim Jagielski                             curDef = curDef->next;
268*b1cdbd2cSJim Jagielski                         }
269*b1cdbd2cSJim Jagielski                     }
270*b1cdbd2cSJim Jagielski                 }
271*b1cdbd2cSJim Jagielski             }
272*b1cdbd2cSJim Jagielski             cur = cur->next;
273*b1cdbd2cSJim Jagielski         }
274*b1cdbd2cSJim Jagielski     }
275*b1cdbd2cSJim Jagielski 
saxify(const Reference<XDocumentHandler> & i_xHandler)276*b1cdbd2cSJim Jagielski     void CNode::saxify(const Reference< XDocumentHandler >& i_xHandler)
277*b1cdbd2cSJim Jagielski     {
278*b1cdbd2cSJim Jagielski         if (!i_xHandler.is()) throw RuntimeException();
279*b1cdbd2cSJim Jagielski         // default: do nothing
280*b1cdbd2cSJim Jagielski     }
281*b1cdbd2cSJim Jagielski 
fastSaxify(Context & io_rContext)282*b1cdbd2cSJim Jagielski     void CNode::fastSaxify(Context& io_rContext)
283*b1cdbd2cSJim Jagielski     {
284*b1cdbd2cSJim Jagielski         if (!io_rContext.mxDocHandler.is()) throw RuntimeException();
285*b1cdbd2cSJim Jagielski         // default: do nothing
286*b1cdbd2cSJim Jagielski     }
287*b1cdbd2cSJim Jagielski 
IsChildTypeAllowed(NodeType const)288*b1cdbd2cSJim Jagielski     bool CNode::IsChildTypeAllowed(NodeType const /*nodeType*/)
289*b1cdbd2cSJim Jagielski     {
290*b1cdbd2cSJim Jagielski         // default: no children allowed
291*b1cdbd2cSJim Jagielski         return false;
292*b1cdbd2cSJim Jagielski     }
293*b1cdbd2cSJim Jagielski 
294*b1cdbd2cSJim Jagielski     /**
295*b1cdbd2cSJim Jagielski     Adds the node newChild to the end of the list of children of this node.
296*b1cdbd2cSJim Jagielski     */
appendChild(Reference<XNode> const & xNewChild)297*b1cdbd2cSJim Jagielski     Reference< XNode > SAL_CALL CNode::appendChild(
298*b1cdbd2cSJim Jagielski             Reference< XNode > const& xNewChild)
299*b1cdbd2cSJim Jagielski         throw (RuntimeException, DOMException)
300*b1cdbd2cSJim Jagielski     {
301*b1cdbd2cSJim Jagielski         ::osl::ClearableMutexGuard guard(m_rMutex);
302*b1cdbd2cSJim Jagielski 
303*b1cdbd2cSJim Jagielski         if (0 == m_aNodePtr) { return 0; }
304*b1cdbd2cSJim Jagielski 
305*b1cdbd2cSJim Jagielski         CNode *const pNewChild(CNode::GetImplementation(xNewChild));
306*b1cdbd2cSJim Jagielski         if (!pNewChild) { throw RuntimeException(); }
307*b1cdbd2cSJim Jagielski         xmlNodePtr const cur = pNewChild->GetNodePtr();
308*b1cdbd2cSJim Jagielski         if (!cur) { throw RuntimeException(); }
309*b1cdbd2cSJim Jagielski 
310*b1cdbd2cSJim Jagielski         // error checks:
311*b1cdbd2cSJim Jagielski         // from other document
312*b1cdbd2cSJim Jagielski         if (cur->doc != m_aNodePtr->doc) {
313*b1cdbd2cSJim Jagielski             DOMException e;
314*b1cdbd2cSJim Jagielski             e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
315*b1cdbd2cSJim Jagielski             throw e;
316*b1cdbd2cSJim Jagielski         }
317*b1cdbd2cSJim Jagielski         // same node
318*b1cdbd2cSJim Jagielski         if (cur == m_aNodePtr) {
319*b1cdbd2cSJim Jagielski             DOMException e;
320*b1cdbd2cSJim Jagielski             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
321*b1cdbd2cSJim Jagielski             throw e;
322*b1cdbd2cSJim Jagielski         }
323*b1cdbd2cSJim Jagielski         if (cur->parent != NULL) {
324*b1cdbd2cSJim Jagielski             DOMException e;
325*b1cdbd2cSJim Jagielski             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
326*b1cdbd2cSJim Jagielski             throw e;
327*b1cdbd2cSJim Jagielski         }
328*b1cdbd2cSJim Jagielski         if (!IsChildTypeAllowed(pNewChild->m_aNodeType)) {
329*b1cdbd2cSJim Jagielski             DOMException e;
330*b1cdbd2cSJim Jagielski             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
331*b1cdbd2cSJim Jagielski             throw e;
332*b1cdbd2cSJim Jagielski         }
333*b1cdbd2cSJim Jagielski 
334*b1cdbd2cSJim Jagielski         // check whether this is an attribute node; it needs special handling
335*b1cdbd2cSJim Jagielski         xmlNodePtr res = NULL;
336*b1cdbd2cSJim Jagielski         if (cur->type == XML_ATTRIBUTE_NODE)
337*b1cdbd2cSJim Jagielski         {
338*b1cdbd2cSJim Jagielski             xmlChar const*const pChildren((cur->children)
339*b1cdbd2cSJim Jagielski                     ? cur->children->content
340*b1cdbd2cSJim Jagielski                     : reinterpret_cast<xmlChar const*>(""));
341*b1cdbd2cSJim Jagielski             CAttr *const pCAttr(dynamic_cast<CAttr *>(pNewChild));
342*b1cdbd2cSJim Jagielski             if (!pCAttr) { throw RuntimeException(); }
343*b1cdbd2cSJim Jagielski             xmlNsPtr const pNs( pCAttr->GetNamespace(m_aNodePtr) );
344*b1cdbd2cSJim Jagielski             if (pNs) {
345*b1cdbd2cSJim Jagielski                 res = reinterpret_cast<xmlNodePtr>(
346*b1cdbd2cSJim Jagielski                         xmlNewNsProp(m_aNodePtr, pNs, cur->name, pChildren));
347*b1cdbd2cSJim Jagielski             } else {
348*b1cdbd2cSJim Jagielski                 res = reinterpret_cast<xmlNodePtr>(
349*b1cdbd2cSJim Jagielski                         xmlNewProp(m_aNodePtr, cur->name, pChildren));
350*b1cdbd2cSJim Jagielski             }
351*b1cdbd2cSJim Jagielski         }
352*b1cdbd2cSJim Jagielski         else
353*b1cdbd2cSJim Jagielski         {
354*b1cdbd2cSJim Jagielski             res = xmlAddChild(m_aNodePtr, cur);
355*b1cdbd2cSJim Jagielski 
356*b1cdbd2cSJim Jagielski             // libxml can do optimization when appending nodes.
357*b1cdbd2cSJim Jagielski             // if res != cur, something was optimized and the newchild-wrapper
358*b1cdbd2cSJim Jagielski             // should be updated
359*b1cdbd2cSJim Jagielski             if (res && (cur != res)) {
360*b1cdbd2cSJim Jagielski                 pNewChild->invalidate(); // cur has been freed
361*b1cdbd2cSJim Jagielski             }
362*b1cdbd2cSJim Jagielski         }
363*b1cdbd2cSJim Jagielski 
364*b1cdbd2cSJim Jagielski         if (!res) { return 0; }
365*b1cdbd2cSJim Jagielski 
366*b1cdbd2cSJim Jagielski         // use custom ns cleanup instead of
367*b1cdbd2cSJim Jagielski         // xmlReconciliateNs(m_aNodePtr->doc, m_aNodePtr);
368*b1cdbd2cSJim Jagielski         // because that will not remove unneeded ns decls
369*b1cdbd2cSJim Jagielski         nscleanup(res, m_aNodePtr);
370*b1cdbd2cSJim Jagielski 
371*b1cdbd2cSJim Jagielski         ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode(res);
372*b1cdbd2cSJim Jagielski 
373*b1cdbd2cSJim Jagielski         if (!pNode.is()) { return 0; }
374*b1cdbd2cSJim Jagielski 
375*b1cdbd2cSJim Jagielski         // dispatch DOMNodeInserted event, target is the new node
376*b1cdbd2cSJim Jagielski         // this node is the related node
377*b1cdbd2cSJim Jagielski         // does bubble
378*b1cdbd2cSJim Jagielski         pNode->m_bUnlinked = false; // will be deleted by xmlFreeDoc
379*b1cdbd2cSJim Jagielski         Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
380*b1cdbd2cSJim Jagielski         Reference< XMutationEvent > event(docevent->createEvent(
381*b1cdbd2cSJim Jagielski             OUString::createFromAscii("DOMNodeInserted")), UNO_QUERY);
382*b1cdbd2cSJim Jagielski         event->initMutationEvent(OUString::createFromAscii("DOMNodeInserted")
383*b1cdbd2cSJim Jagielski             , sal_True, sal_False,
384*b1cdbd2cSJim Jagielski             this,
385*b1cdbd2cSJim Jagielski             OUString(), OUString(), OUString(), (AttrChangeType)0 );
386*b1cdbd2cSJim Jagielski 
387*b1cdbd2cSJim Jagielski         // the following dispatch functions use only UNO interfaces
388*b1cdbd2cSJim Jagielski         // and call event listeners, so release mutex to prevent deadlocks.
389*b1cdbd2cSJim Jagielski         guard.clear();
390*b1cdbd2cSJim Jagielski 
391*b1cdbd2cSJim Jagielski         dispatchEvent(Reference< XEvent >(event, UNO_QUERY));
392*b1cdbd2cSJim Jagielski         // dispatch subtree modified for this node
393*b1cdbd2cSJim Jagielski         dispatchSubtreeModified();
394*b1cdbd2cSJim Jagielski 
395*b1cdbd2cSJim Jagielski         return pNode.get();
396*b1cdbd2cSJim Jagielski     }
397*b1cdbd2cSJim Jagielski 
398*b1cdbd2cSJim Jagielski     /**
399*b1cdbd2cSJim Jagielski     Returns a duplicate of this node, i.e., serves as a generic copy
400*b1cdbd2cSJim Jagielski     constructor for nodes.
401*b1cdbd2cSJim Jagielski     */
cloneNode(sal_Bool bDeep)402*b1cdbd2cSJim Jagielski     Reference< XNode > SAL_CALL CNode::cloneNode(sal_Bool bDeep)
403*b1cdbd2cSJim Jagielski         throw (RuntimeException)
404*b1cdbd2cSJim Jagielski     {
405*b1cdbd2cSJim Jagielski         ::osl::MutexGuard const g(m_rMutex);
406*b1cdbd2cSJim Jagielski 
407*b1cdbd2cSJim Jagielski         if (0 == m_aNodePtr) {
408*b1cdbd2cSJim Jagielski             return 0;
409*b1cdbd2cSJim Jagielski         }
410*b1cdbd2cSJim Jagielski         ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode(
411*b1cdbd2cSJim Jagielski             xmlCopyNode(m_aNodePtr, (bDeep) ? 1 : 0));
412*b1cdbd2cSJim Jagielski         if (!pNode.is()) { return 0; }
413*b1cdbd2cSJim Jagielski         pNode->m_bUnlinked = true; // not linked yet
414*b1cdbd2cSJim Jagielski         return pNode.get();
415*b1cdbd2cSJim Jagielski     }
416*b1cdbd2cSJim Jagielski 
417*b1cdbd2cSJim Jagielski     /**
418*b1cdbd2cSJim Jagielski     A NamedNodeMap containing the attributes of this node (if it is an Element)
419*b1cdbd2cSJim Jagielski     or null otherwise.
420*b1cdbd2cSJim Jagielski     */
getAttributes()421*b1cdbd2cSJim Jagielski     Reference< XNamedNodeMap > SAL_CALL CNode::getAttributes()
422*b1cdbd2cSJim Jagielski         throw (RuntimeException)
423*b1cdbd2cSJim Jagielski     {
424*b1cdbd2cSJim Jagielski         // return empty reference; only element node may override this impl
425*b1cdbd2cSJim Jagielski         return Reference< XNamedNodeMap>();
426*b1cdbd2cSJim Jagielski     }
427*b1cdbd2cSJim Jagielski 
428*b1cdbd2cSJim Jagielski     /**
429*b1cdbd2cSJim Jagielski     A NodeList that contains all children of this node.
430*b1cdbd2cSJim Jagielski     */
getChildNodes()431*b1cdbd2cSJim Jagielski     Reference< XNodeList > SAL_CALL CNode::getChildNodes()
432*b1cdbd2cSJim Jagielski         throw (RuntimeException)
433*b1cdbd2cSJim Jagielski     {
434*b1cdbd2cSJim Jagielski         ::osl::MutexGuard const g(m_rMutex);
435*b1cdbd2cSJim Jagielski 
436*b1cdbd2cSJim Jagielski         if (0 == m_aNodePtr) {
437*b1cdbd2cSJim Jagielski             return 0;
438*b1cdbd2cSJim Jagielski         }
439*b1cdbd2cSJim Jagielski         Reference< XNodeList > const xNodeList(new CChildList(this, m_rMutex));
440*b1cdbd2cSJim Jagielski         return xNodeList;
441*b1cdbd2cSJim Jagielski     }
442*b1cdbd2cSJim Jagielski 
443*b1cdbd2cSJim Jagielski     /**
444*b1cdbd2cSJim Jagielski     The first child of this node.
445*b1cdbd2cSJim Jagielski     */
getFirstChild()446*b1cdbd2cSJim Jagielski     Reference< XNode > SAL_CALL CNode::getFirstChild()
447*b1cdbd2cSJim Jagielski         throw (RuntimeException)
448*b1cdbd2cSJim Jagielski     {
449*b1cdbd2cSJim Jagielski         ::osl::MutexGuard const g(m_rMutex);
450*b1cdbd2cSJim Jagielski 
451*b1cdbd2cSJim Jagielski         if (0 == m_aNodePtr) {
452*b1cdbd2cSJim Jagielski             return 0;
453*b1cdbd2cSJim Jagielski         }
454*b1cdbd2cSJim Jagielski         Reference< XNode > const xNode(
455*b1cdbd2cSJim Jagielski                 GetOwnerDocument().GetCNode(m_aNodePtr->children).get());
456*b1cdbd2cSJim Jagielski         return xNode;
457*b1cdbd2cSJim Jagielski     }
458*b1cdbd2cSJim Jagielski 
459*b1cdbd2cSJim Jagielski     /**
460*b1cdbd2cSJim Jagielski     The last child of this node.
461*b1cdbd2cSJim Jagielski     */
getLastChild()462*b1cdbd2cSJim Jagielski     Reference< XNode > SAL_CALL CNode::getLastChild()
463*b1cdbd2cSJim Jagielski         throw (RuntimeException)
464*b1cdbd2cSJim Jagielski     {
465*b1cdbd2cSJim Jagielski         ::osl::MutexGuard const g(m_rMutex);
466*b1cdbd2cSJim Jagielski 
467*b1cdbd2cSJim Jagielski         if (0 == m_aNodePtr) {
468*b1cdbd2cSJim Jagielski             return 0;
469*b1cdbd2cSJim Jagielski         }
470*b1cdbd2cSJim Jagielski         Reference< XNode > const xNode(
471*b1cdbd2cSJim Jagielski             GetOwnerDocument().GetCNode(xmlGetLastChild(m_aNodePtr)).get());
472*b1cdbd2cSJim Jagielski         return xNode;
473*b1cdbd2cSJim Jagielski     }
474*b1cdbd2cSJim Jagielski 
475*b1cdbd2cSJim Jagielski     /**
476*b1cdbd2cSJim Jagielski     Returns the local part of the qualified name of this node.
477*b1cdbd2cSJim Jagielski     */
getLocalName()478*b1cdbd2cSJim Jagielski     OUString SAL_CALL CNode::getLocalName()
479*b1cdbd2cSJim Jagielski         throw (RuntimeException)
480*b1cdbd2cSJim Jagielski     {
481*b1cdbd2cSJim Jagielski         // see CElement/CAttr
482*b1cdbd2cSJim Jagielski         return ::rtl::OUString();
483*b1cdbd2cSJim Jagielski     }
484*b1cdbd2cSJim Jagielski 
485*b1cdbd2cSJim Jagielski 
486*b1cdbd2cSJim Jagielski     /**
487*b1cdbd2cSJim Jagielski     The namespace URI of this node, or null if it is unspecified.
488*b1cdbd2cSJim Jagielski     */
getNamespaceURI()489*b1cdbd2cSJim Jagielski     OUString SAL_CALL CNode::getNamespaceURI()
490*b1cdbd2cSJim Jagielski         throw (RuntimeException)
491*b1cdbd2cSJim Jagielski     {
492*b1cdbd2cSJim Jagielski         ::osl::MutexGuard const g(m_rMutex);
493*b1cdbd2cSJim Jagielski 
494*b1cdbd2cSJim Jagielski         OUString aURI;
495*b1cdbd2cSJim Jagielski         if (m_aNodePtr != NULL &&
496*b1cdbd2cSJim Jagielski             (m_aNodePtr->type == XML_ELEMENT_NODE || m_aNodePtr->type == XML_ATTRIBUTE_NODE) &&
497*b1cdbd2cSJim Jagielski             m_aNodePtr->ns != NULL)
498*b1cdbd2cSJim Jagielski         {
499*b1cdbd2cSJim Jagielski             const xmlChar* xHref = m_aNodePtr->ns->href;
500*b1cdbd2cSJim Jagielski             aURI = OUString((sal_Char*)xHref, strlen((char*)xHref), RTL_TEXTENCODING_UTF8);
501*b1cdbd2cSJim Jagielski         }
502*b1cdbd2cSJim Jagielski         return aURI;
503*b1cdbd2cSJim Jagielski     }
504*b1cdbd2cSJim Jagielski 
505*b1cdbd2cSJim Jagielski     /**
506*b1cdbd2cSJim Jagielski     The node immediately following this node.
507*b1cdbd2cSJim Jagielski     */
getNextSibling()508*b1cdbd2cSJim Jagielski     Reference< XNode > SAL_CALL CNode::getNextSibling()
509*b1cdbd2cSJim Jagielski         throw (RuntimeException)
510*b1cdbd2cSJim Jagielski     {
511*b1cdbd2cSJim Jagielski         ::osl::MutexGuard const g(m_rMutex);
512*b1cdbd2cSJim Jagielski 
513*b1cdbd2cSJim Jagielski         if (0 == m_aNodePtr) {
514*b1cdbd2cSJim Jagielski             return 0;
515*b1cdbd2cSJim Jagielski         }
516*b1cdbd2cSJim Jagielski         Reference< XNode > const xNode(
517*b1cdbd2cSJim Jagielski                 GetOwnerDocument().GetCNode(m_aNodePtr->next).get());
518*b1cdbd2cSJim Jagielski         return xNode;
519*b1cdbd2cSJim Jagielski     }
520*b1cdbd2cSJim Jagielski 
521*b1cdbd2cSJim Jagielski     /**
522*b1cdbd2cSJim Jagielski     The name of this node, depending on its type; see the table above.
523*b1cdbd2cSJim Jagielski     */
getNodeName()524*b1cdbd2cSJim Jagielski     OUString SAL_CALL CNode::getNodeName()
525*b1cdbd2cSJim Jagielski         throw (RuntimeException)
526*b1cdbd2cSJim Jagielski     {
527*b1cdbd2cSJim Jagielski         /*
528*b1cdbd2cSJim Jagielski         Interface  	     nodeName  	            nodeValue  	                    attributes
529*b1cdbd2cSJim Jagielski         --------------------------------------------------------------------------------------
530*b1cdbd2cSJim Jagielski         Attr 	         name of attribute 	    value of attribute 	            null
531*b1cdbd2cSJim Jagielski         CDATASection 	 "#cdata-section" 	    content of the CDATA Section 	null
532*b1cdbd2cSJim Jagielski         Comment 	     "#comment" 	        content of the comment 	        null
533*b1cdbd2cSJim Jagielski         Document 	     "#document" 	        null 	                        null
534*b1cdbd2cSJim Jagielski         DocumentFragment "#document-fragment" 	null 	                        null
535*b1cdbd2cSJim Jagielski         DocumentType 	 document type name 	null 	                        null
536*b1cdbd2cSJim Jagielski         Element 	     tag name 	            null 	                        NamedNodeMap
537*b1cdbd2cSJim Jagielski         Entity 	         entity name 	        null 	                        null
538*b1cdbd2cSJim Jagielski         EntityReference  name of entity         null 	                        null
539*b1cdbd2cSJim Jagielski                          referenced
540*b1cdbd2cSJim Jagielski         Notation 	     notation name 	        null 	                        null
541*b1cdbd2cSJim Jagielski         Processing\   	 target                 entire content excluding        null
542*b1cdbd2cSJim Jagielski         Instruction 	                        the target
543*b1cdbd2cSJim Jagielski         Text 	         "#text" 	            content of the text node     	null
544*b1cdbd2cSJim Jagielski         */
545*b1cdbd2cSJim Jagielski         OUString aName;
546*b1cdbd2cSJim Jagielski         return aName;
547*b1cdbd2cSJim Jagielski     }
548*b1cdbd2cSJim Jagielski 
549*b1cdbd2cSJim Jagielski     /**
550*b1cdbd2cSJim Jagielski     A code representing the type of the underlying object, as defined above.
551*b1cdbd2cSJim Jagielski     */
getNodeType()552*b1cdbd2cSJim Jagielski     NodeType SAL_CALL CNode::getNodeType()
553*b1cdbd2cSJim Jagielski         throw (RuntimeException)
554*b1cdbd2cSJim Jagielski     {
555*b1cdbd2cSJim Jagielski         ::osl::MutexGuard const g(m_rMutex);
556*b1cdbd2cSJim Jagielski 
557*b1cdbd2cSJim Jagielski         return m_aNodeType;
558*b1cdbd2cSJim Jagielski     }
559*b1cdbd2cSJim Jagielski 
560*b1cdbd2cSJim Jagielski     /**
561*b1cdbd2cSJim Jagielski     The value of this node, depending on its type; see the table above.
562*b1cdbd2cSJim Jagielski     */
getNodeValue()563*b1cdbd2cSJim Jagielski     OUString SAL_CALL CNode::getNodeValue()
564*b1cdbd2cSJim Jagielski         throw (RuntimeException)
565*b1cdbd2cSJim Jagielski     {
566*b1cdbd2cSJim Jagielski         OUString aValue;
567*b1cdbd2cSJim Jagielski         return aValue;
568*b1cdbd2cSJim Jagielski     }
569*b1cdbd2cSJim Jagielski 
570*b1cdbd2cSJim Jagielski     /**
571*b1cdbd2cSJim Jagielski     The Document object associated with this node.
572*b1cdbd2cSJim Jagielski     */
getOwnerDocument()573*b1cdbd2cSJim Jagielski     Reference< XDocument > SAL_CALL CNode::getOwnerDocument()
574*b1cdbd2cSJim Jagielski         throw (RuntimeException)
575*b1cdbd2cSJim Jagielski     {
576*b1cdbd2cSJim Jagielski         ::osl::MutexGuard const g(m_rMutex);
577*b1cdbd2cSJim Jagielski 
578*b1cdbd2cSJim Jagielski         if (0 == m_aNodePtr) {
579*b1cdbd2cSJim Jagielski             return 0;
580*b1cdbd2cSJim Jagielski         }
581*b1cdbd2cSJim Jagielski         Reference< XDocument > const xDoc(& GetOwnerDocument());
582*b1cdbd2cSJim Jagielski         return xDoc;
583*b1cdbd2cSJim Jagielski     }
584*b1cdbd2cSJim Jagielski 
585*b1cdbd2cSJim Jagielski     /**
586*b1cdbd2cSJim Jagielski     The parent of this node.
587*b1cdbd2cSJim Jagielski     */
getParentNode()588*b1cdbd2cSJim Jagielski     Reference< XNode > SAL_CALL CNode::getParentNode()
589*b1cdbd2cSJim Jagielski         throw (RuntimeException)
590*b1cdbd2cSJim Jagielski     {
591*b1cdbd2cSJim Jagielski         ::osl::MutexGuard const g(m_rMutex);
592*b1cdbd2cSJim Jagielski 
593*b1cdbd2cSJim Jagielski         if (0 == m_aNodePtr) {
594*b1cdbd2cSJim Jagielski             return 0;
595*b1cdbd2cSJim Jagielski         }
596*b1cdbd2cSJim Jagielski         Reference< XNode > const xNode(
597*b1cdbd2cSJim Jagielski                 GetOwnerDocument().GetCNode(m_aNodePtr->parent).get());
598*b1cdbd2cSJim Jagielski         return xNode;
599*b1cdbd2cSJim Jagielski     }
600*b1cdbd2cSJim Jagielski 
601*b1cdbd2cSJim Jagielski     /**
602*b1cdbd2cSJim Jagielski     The namespace prefix of this node, or null if it is unspecified.
603*b1cdbd2cSJim Jagielski     */
getPrefix()604*b1cdbd2cSJim Jagielski     OUString SAL_CALL CNode::getPrefix()
605*b1cdbd2cSJim Jagielski         throw (RuntimeException)
606*b1cdbd2cSJim Jagielski     {
607*b1cdbd2cSJim Jagielski         ::osl::MutexGuard const g(m_rMutex);
608*b1cdbd2cSJim Jagielski 
609*b1cdbd2cSJim Jagielski         OUString aPrefix;
610*b1cdbd2cSJim Jagielski         if (m_aNodePtr != NULL &&
611*b1cdbd2cSJim Jagielski             (m_aNodePtr->type == XML_ELEMENT_NODE || m_aNodePtr->type == XML_ATTRIBUTE_NODE) &&
612*b1cdbd2cSJim Jagielski             m_aNodePtr->ns != NULL)
613*b1cdbd2cSJim Jagielski         {
614*b1cdbd2cSJim Jagielski             const xmlChar* xPrefix = m_aNodePtr->ns->prefix;
615*b1cdbd2cSJim Jagielski             if( xPrefix != NULL )
616*b1cdbd2cSJim Jagielski                 aPrefix = OUString((sal_Char*)xPrefix, strlen((char*)xPrefix), RTL_TEXTENCODING_UTF8);
617*b1cdbd2cSJim Jagielski         }
618*b1cdbd2cSJim Jagielski         return aPrefix;
619*b1cdbd2cSJim Jagielski 
620*b1cdbd2cSJim Jagielski     }
621*b1cdbd2cSJim Jagielski 
622*b1cdbd2cSJim Jagielski     /**
623*b1cdbd2cSJim Jagielski     The node immediately preceding this node.
624*b1cdbd2cSJim Jagielski     */
getPreviousSibling()625*b1cdbd2cSJim Jagielski     Reference< XNode > SAL_CALL CNode::getPreviousSibling()
626*b1cdbd2cSJim Jagielski         throw (RuntimeException)
627*b1cdbd2cSJim Jagielski     {
628*b1cdbd2cSJim Jagielski         ::osl::MutexGuard const g(m_rMutex);
629*b1cdbd2cSJim Jagielski 
630*b1cdbd2cSJim Jagielski         if (0 == m_aNodePtr) {
631*b1cdbd2cSJim Jagielski             return 0;
632*b1cdbd2cSJim Jagielski         }
633*b1cdbd2cSJim Jagielski         Reference< XNode > const xNode(
634*b1cdbd2cSJim Jagielski                 GetOwnerDocument().GetCNode(m_aNodePtr->prev).get());
635*b1cdbd2cSJim Jagielski         return xNode;
636*b1cdbd2cSJim Jagielski     }
637*b1cdbd2cSJim Jagielski 
638*b1cdbd2cSJim Jagielski     /**
639*b1cdbd2cSJim Jagielski     Returns whether this node (if it is an element) has any attributes.
640*b1cdbd2cSJim Jagielski     */
hasAttributes()641*b1cdbd2cSJim Jagielski     sal_Bool SAL_CALL CNode::hasAttributes()
642*b1cdbd2cSJim Jagielski         throw (RuntimeException)
643*b1cdbd2cSJim Jagielski     {
644*b1cdbd2cSJim Jagielski         ::osl::MutexGuard const g(m_rMutex);
645*b1cdbd2cSJim Jagielski 
646*b1cdbd2cSJim Jagielski         return (m_aNodePtr != NULL && m_aNodePtr->properties != NULL);
647*b1cdbd2cSJim Jagielski     }
648*b1cdbd2cSJim Jagielski 
649*b1cdbd2cSJim Jagielski     /**
650*b1cdbd2cSJim Jagielski     Returns whether this node has any children.
651*b1cdbd2cSJim Jagielski     */
hasChildNodes()652*b1cdbd2cSJim Jagielski     sal_Bool SAL_CALL CNode::hasChildNodes()
653*b1cdbd2cSJim Jagielski         throw (RuntimeException)
654*b1cdbd2cSJim Jagielski     {
655*b1cdbd2cSJim Jagielski         ::osl::MutexGuard const g(m_rMutex);
656*b1cdbd2cSJim Jagielski 
657*b1cdbd2cSJim Jagielski         return (m_aNodePtr != NULL && m_aNodePtr->children != NULL);
658*b1cdbd2cSJim Jagielski     }
659*b1cdbd2cSJim Jagielski 
660*b1cdbd2cSJim Jagielski     /**
661*b1cdbd2cSJim Jagielski     Inserts the node newChild before the existing child node refChild.
662*b1cdbd2cSJim Jagielski     */
insertBefore(const Reference<XNode> & newChild,const Reference<XNode> & refChild)663*b1cdbd2cSJim Jagielski     Reference< XNode > SAL_CALL CNode::insertBefore(
664*b1cdbd2cSJim Jagielski             const Reference< XNode >& newChild, const Reference< XNode >& refChild)
665*b1cdbd2cSJim Jagielski         throw (RuntimeException, DOMException)
666*b1cdbd2cSJim Jagielski     {
667*b1cdbd2cSJim Jagielski         if (!newChild.is() || !refChild.is()) { throw RuntimeException(); }
668*b1cdbd2cSJim Jagielski 
669*b1cdbd2cSJim Jagielski         if (newChild->getOwnerDocument() != getOwnerDocument()) {
670*b1cdbd2cSJim Jagielski             DOMException e;
671*b1cdbd2cSJim Jagielski             e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
672*b1cdbd2cSJim Jagielski             throw e;
673*b1cdbd2cSJim Jagielski         }
674*b1cdbd2cSJim Jagielski         if (refChild->getParentNode() != Reference< XNode >(this)) {
675*b1cdbd2cSJim Jagielski             DOMException e;
676*b1cdbd2cSJim Jagielski             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
677*b1cdbd2cSJim Jagielski             throw e;
678*b1cdbd2cSJim Jagielski         }
679*b1cdbd2cSJim Jagielski 
680*b1cdbd2cSJim Jagielski         ::osl::ClearableMutexGuard guard(m_rMutex);
681*b1cdbd2cSJim Jagielski 
682*b1cdbd2cSJim Jagielski         CNode *const pNewNode(CNode::GetImplementation(newChild));
683*b1cdbd2cSJim Jagielski         CNode *const pRefNode(CNode::GetImplementation(refChild));
684*b1cdbd2cSJim Jagielski         if (!pNewNode || !pRefNode) { throw RuntimeException(); }
685*b1cdbd2cSJim Jagielski         xmlNodePtr const pNewChild(pNewNode->GetNodePtr());
686*b1cdbd2cSJim Jagielski         xmlNodePtr const pRefChild(pRefNode->GetNodePtr());
687*b1cdbd2cSJim Jagielski         if (!pNewChild || !pRefChild) { throw RuntimeException(); }
688*b1cdbd2cSJim Jagielski 
689*b1cdbd2cSJim Jagielski         if (pNewChild == m_aNodePtr) {
690*b1cdbd2cSJim Jagielski             DOMException e;
691*b1cdbd2cSJim Jagielski             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
692*b1cdbd2cSJim Jagielski             throw e;
693*b1cdbd2cSJim Jagielski         }
694*b1cdbd2cSJim Jagielski         // already has parent
695*b1cdbd2cSJim Jagielski         if (pNewChild->parent != NULL)
696*b1cdbd2cSJim Jagielski         {
697*b1cdbd2cSJim Jagielski             DOMException e;
698*b1cdbd2cSJim Jagielski             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
699*b1cdbd2cSJim Jagielski             throw e;
700*b1cdbd2cSJim Jagielski         }
701*b1cdbd2cSJim Jagielski         if (!IsChildTypeAllowed(pNewNode->m_aNodeType)) {
702*b1cdbd2cSJim Jagielski             DOMException e;
703*b1cdbd2cSJim Jagielski             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
704*b1cdbd2cSJim Jagielski             throw e;
705*b1cdbd2cSJim Jagielski         }
706*b1cdbd2cSJim Jagielski 
707*b1cdbd2cSJim Jagielski         // attributes are unordered anyway, so just do appendChild
708*b1cdbd2cSJim Jagielski         if (XML_ATTRIBUTE_NODE == pNewChild->type) {
709*b1cdbd2cSJim Jagielski             guard.clear();
710*b1cdbd2cSJim Jagielski             return appendChild(newChild);
711*b1cdbd2cSJim Jagielski         }
712*b1cdbd2cSJim Jagielski 
713*b1cdbd2cSJim Jagielski         xmlNodePtr cur = m_aNodePtr->children;
714*b1cdbd2cSJim Jagielski 
715*b1cdbd2cSJim Jagielski         //search child before which to insert
716*b1cdbd2cSJim Jagielski         while (cur != NULL)
717*b1cdbd2cSJim Jagielski         {
718*b1cdbd2cSJim Jagielski             if (cur == pRefChild) {
719*b1cdbd2cSJim Jagielski                 // insert before
720*b1cdbd2cSJim Jagielski                 pNewChild->next = cur;
721*b1cdbd2cSJim Jagielski                 pNewChild->prev = cur->prev;
722*b1cdbd2cSJim Jagielski                 cur->prev = pNewChild;
723*b1cdbd2cSJim Jagielski                 if (pNewChild->prev != NULL) {
724*b1cdbd2cSJim Jagielski                     pNewChild->prev->next = pNewChild;
725*b1cdbd2cSJim Jagielski                 }
726*b1cdbd2cSJim Jagielski                 pNewChild->parent = cur->parent;
727*b1cdbd2cSJim Jagielski                 if (pNewChild->parent->children == cur) {
728*b1cdbd2cSJim Jagielski                     pNewChild->parent->children = pNewChild;
729*b1cdbd2cSJim Jagielski                 }
730*b1cdbd2cSJim Jagielski                 // do not update parent->last here!
731*b1cdbd2cSJim Jagielski                 pNewNode->m_bUnlinked = false; // will be deleted by xmlFreeDoc
732*b1cdbd2cSJim Jagielski                 break;
733*b1cdbd2cSJim Jagielski             }
734*b1cdbd2cSJim Jagielski             cur = cur->next;
735*b1cdbd2cSJim Jagielski         }
736*b1cdbd2cSJim Jagielski         return refChild;
737*b1cdbd2cSJim Jagielski     }
738*b1cdbd2cSJim Jagielski 
739*b1cdbd2cSJim Jagielski     /**
740*b1cdbd2cSJim Jagielski     Tests whether the DOM implementation implements a specific feature and
741*b1cdbd2cSJim Jagielski     that feature is supported by this node.
742*b1cdbd2cSJim Jagielski     */
isSupported(const OUString &,const OUString &)743*b1cdbd2cSJim Jagielski   sal_Bool SAL_CALL CNode::isSupported(const OUString& /*feature*/, const OUString& /*ver*/)
744*b1cdbd2cSJim Jagielski         throw (RuntimeException)
745*b1cdbd2cSJim Jagielski     {
746*b1cdbd2cSJim Jagielski         OSL_ENSURE(false, "CNode::isSupported: not implemented (#i113683#)");
747*b1cdbd2cSJim Jagielski         return sal_False;
748*b1cdbd2cSJim Jagielski     }
749*b1cdbd2cSJim Jagielski 
750*b1cdbd2cSJim Jagielski     /**
751*b1cdbd2cSJim Jagielski     Puts all Text nodes in the full depth of the sub-tree underneath this
752*b1cdbd2cSJim Jagielski     Node, including attribute nodes, into a "normal" form where only structure
753*b1cdbd2cSJim Jagielski     (e.g., elements, comments, processing instructions, CDATA sections, and
754*b1cdbd2cSJim Jagielski     entity references) separates Text nodes, i.e., there are neither adjacent
755*b1cdbd2cSJim Jagielski     Text nodes nor empty Text nodes.
756*b1cdbd2cSJim Jagielski     */
normalize()757*b1cdbd2cSJim Jagielski     void SAL_CALL CNode::normalize()
758*b1cdbd2cSJim Jagielski         throw (RuntimeException)
759*b1cdbd2cSJim Jagielski     {
760*b1cdbd2cSJim Jagielski         //XXX combine adjacent text nodes and remove empty ones
761*b1cdbd2cSJim Jagielski         OSL_ENSURE(false, "CNode::normalize: not implemented (#i113683#)");
762*b1cdbd2cSJim Jagielski     }
763*b1cdbd2cSJim Jagielski 
764*b1cdbd2cSJim Jagielski     /**
765*b1cdbd2cSJim Jagielski     Removes the child node indicated by oldChild from the list of children,
766*b1cdbd2cSJim Jagielski     and returns it.
767*b1cdbd2cSJim Jagielski     */
768*b1cdbd2cSJim Jagielski     Reference< XNode > SAL_CALL
removeChild(const Reference<XNode> & xOldChild)769*b1cdbd2cSJim Jagielski     CNode::removeChild(const Reference< XNode >& xOldChild)
770*b1cdbd2cSJim Jagielski         throw (RuntimeException, DOMException)
771*b1cdbd2cSJim Jagielski     {
772*b1cdbd2cSJim Jagielski         if (!xOldChild.is()) {
773*b1cdbd2cSJim Jagielski             throw RuntimeException();
774*b1cdbd2cSJim Jagielski         }
775*b1cdbd2cSJim Jagielski 
776*b1cdbd2cSJim Jagielski         if (xOldChild->getOwnerDocument() != getOwnerDocument()) {
777*b1cdbd2cSJim Jagielski             DOMException e;
778*b1cdbd2cSJim Jagielski             e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
779*b1cdbd2cSJim Jagielski             throw e;
780*b1cdbd2cSJim Jagielski         }
781*b1cdbd2cSJim Jagielski         if (xOldChild->getParentNode() != Reference< XNode >(this)) {
782*b1cdbd2cSJim Jagielski             DOMException e;
783*b1cdbd2cSJim Jagielski             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
784*b1cdbd2cSJim Jagielski             throw e;
785*b1cdbd2cSJim Jagielski         }
786*b1cdbd2cSJim Jagielski 
787*b1cdbd2cSJim Jagielski         ::osl::ClearableMutexGuard guard(m_rMutex);
788*b1cdbd2cSJim Jagielski 
789*b1cdbd2cSJim Jagielski         if (!m_aNodePtr) { throw RuntimeException(); }
790*b1cdbd2cSJim Jagielski 
791*b1cdbd2cSJim Jagielski         Reference<XNode> xReturn( xOldChild );
792*b1cdbd2cSJim Jagielski 
793*b1cdbd2cSJim Jagielski         ::rtl::Reference<CNode> const pOld(CNode::GetImplementation(xOldChild));
794*b1cdbd2cSJim Jagielski         if (!pOld.is()) { throw RuntimeException(); }
795*b1cdbd2cSJim Jagielski         xmlNodePtr const old = pOld->GetNodePtr();
796*b1cdbd2cSJim Jagielski         if (!old) { throw RuntimeException(); }
797*b1cdbd2cSJim Jagielski 
798*b1cdbd2cSJim Jagielski         if( old->type == XML_ATTRIBUTE_NODE )
799*b1cdbd2cSJim Jagielski         {
800*b1cdbd2cSJim Jagielski             xmlAttrPtr pAttr = reinterpret_cast<xmlAttrPtr>(old);
801*b1cdbd2cSJim Jagielski             xmlRemoveProp( pAttr );
802*b1cdbd2cSJim Jagielski             pOld->invalidate(); // freed by xmlRemoveProp
803*b1cdbd2cSJim Jagielski             xReturn.clear();
804*b1cdbd2cSJim Jagielski         }
805*b1cdbd2cSJim Jagielski         else
806*b1cdbd2cSJim Jagielski         {
807*b1cdbd2cSJim Jagielski             xmlUnlinkNode(old);
808*b1cdbd2cSJim Jagielski             pOld->m_bUnlinked = true;
809*b1cdbd2cSJim Jagielski         }
810*b1cdbd2cSJim Jagielski 
811*b1cdbd2cSJim Jagielski         /*DOMNodeRemoved
812*b1cdbd2cSJim Jagielski          * Fired when a node is being removed from its parent node.
813*b1cdbd2cSJim Jagielski          * This event is dispatched before the node is removed from the tree.
814*b1cdbd2cSJim Jagielski          * The target of this event is the node being removed.
815*b1cdbd2cSJim Jagielski          *   Bubbles: Yes
816*b1cdbd2cSJim Jagielski          *   Cancelable: No
817*b1cdbd2cSJim Jagielski          *   Context Info: relatedNode holds the parent node
818*b1cdbd2cSJim Jagielski          */
819*b1cdbd2cSJim Jagielski         Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
820*b1cdbd2cSJim Jagielski         Reference< XMutationEvent > event(docevent->createEvent(
821*b1cdbd2cSJim Jagielski             OUString::createFromAscii("DOMNodeRemoved")), UNO_QUERY);
822*b1cdbd2cSJim Jagielski         event->initMutationEvent(OUString::createFromAscii("DOMNodeRemoved"),
823*b1cdbd2cSJim Jagielski             sal_True,
824*b1cdbd2cSJim Jagielski             sal_False,
825*b1cdbd2cSJim Jagielski             this,
826*b1cdbd2cSJim Jagielski             OUString(), OUString(), OUString(), (AttrChangeType)0 );
827*b1cdbd2cSJim Jagielski 
828*b1cdbd2cSJim Jagielski         // the following dispatch functions use only UNO interfaces
829*b1cdbd2cSJim Jagielski         // and call event listeners, so release mutex to prevent deadlocks.
830*b1cdbd2cSJim Jagielski         guard.clear();
831*b1cdbd2cSJim Jagielski 
832*b1cdbd2cSJim Jagielski         dispatchEvent(Reference< XEvent >(event, UNO_QUERY));
833*b1cdbd2cSJim Jagielski         // subtree modified for this node
834*b1cdbd2cSJim Jagielski         dispatchSubtreeModified();
835*b1cdbd2cSJim Jagielski 
836*b1cdbd2cSJim Jagielski         return xReturn;
837*b1cdbd2cSJim Jagielski     }
838*b1cdbd2cSJim Jagielski 
839*b1cdbd2cSJim Jagielski     /**
840*b1cdbd2cSJim Jagielski     Replaces the child node oldChild with newChild in the list of children,
841*b1cdbd2cSJim Jagielski     and returns the oldChild node.
842*b1cdbd2cSJim Jagielski     */
replaceChild(Reference<XNode> const & xNewChild,Reference<XNode> const & xOldChild)843*b1cdbd2cSJim Jagielski     Reference< XNode > SAL_CALL CNode::replaceChild(
844*b1cdbd2cSJim Jagielski             Reference< XNode > const& xNewChild,
845*b1cdbd2cSJim Jagielski             Reference< XNode > const& xOldChild)
846*b1cdbd2cSJim Jagielski         throw (RuntimeException, DOMException)
847*b1cdbd2cSJim Jagielski     {
848*b1cdbd2cSJim Jagielski         if (!xOldChild.is() || !xNewChild.is()) {
849*b1cdbd2cSJim Jagielski             throw RuntimeException();
850*b1cdbd2cSJim Jagielski         }
851*b1cdbd2cSJim Jagielski 
852*b1cdbd2cSJim Jagielski         if (xNewChild->getOwnerDocument() != getOwnerDocument()) {
853*b1cdbd2cSJim Jagielski             DOMException e;
854*b1cdbd2cSJim Jagielski             e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
855*b1cdbd2cSJim Jagielski             throw e;
856*b1cdbd2cSJim Jagielski         }
857*b1cdbd2cSJim Jagielski         if (xOldChild->getParentNode() != Reference< XNode >(this)) {
858*b1cdbd2cSJim Jagielski             DOMException e;
859*b1cdbd2cSJim Jagielski             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
860*b1cdbd2cSJim Jagielski             throw e;
861*b1cdbd2cSJim Jagielski         }
862*b1cdbd2cSJim Jagielski 
863*b1cdbd2cSJim Jagielski         ::osl::ClearableMutexGuard guard(m_rMutex);
864*b1cdbd2cSJim Jagielski 
865*b1cdbd2cSJim Jagielski /*
866*b1cdbd2cSJim Jagielski         Reference< XNode > aNode = removeChild(oldChild);
867*b1cdbd2cSJim Jagielski         appendChild(newChild);
868*b1cdbd2cSJim Jagielski */
869*b1cdbd2cSJim Jagielski         ::rtl::Reference<CNode> const pOldNode(
870*b1cdbd2cSJim Jagielski                 CNode::GetImplementation(xOldChild));
871*b1cdbd2cSJim Jagielski         ::rtl::Reference<CNode> const pNewNode(
872*b1cdbd2cSJim Jagielski                 CNode::GetImplementation(xNewChild));
873*b1cdbd2cSJim Jagielski         if (!pOldNode.is() || !pNewNode.is()) { throw RuntimeException(); }
874*b1cdbd2cSJim Jagielski         xmlNodePtr const pOld = pOldNode->GetNodePtr();
875*b1cdbd2cSJim Jagielski         xmlNodePtr const pNew = pNewNode->GetNodePtr();
876*b1cdbd2cSJim Jagielski         if (!pOld || !pNew) { throw RuntimeException(); }
877*b1cdbd2cSJim Jagielski 
878*b1cdbd2cSJim Jagielski         if (pNew == m_aNodePtr) {
879*b1cdbd2cSJim Jagielski             DOMException e;
880*b1cdbd2cSJim Jagielski             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
881*b1cdbd2cSJim Jagielski             throw e;
882*b1cdbd2cSJim Jagielski         }
883*b1cdbd2cSJim Jagielski         // already has parent
884*b1cdbd2cSJim Jagielski         if (pNew->parent != NULL) {
885*b1cdbd2cSJim Jagielski             DOMException e;
886*b1cdbd2cSJim Jagielski             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
887*b1cdbd2cSJim Jagielski             throw e;
888*b1cdbd2cSJim Jagielski         }
889*b1cdbd2cSJim Jagielski         if (!IsChildTypeAllowed(pNewNode->m_aNodeType)) {
890*b1cdbd2cSJim Jagielski             DOMException e;
891*b1cdbd2cSJim Jagielski             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
892*b1cdbd2cSJim Jagielski             throw e;
893*b1cdbd2cSJim Jagielski         }
894*b1cdbd2cSJim Jagielski 
895*b1cdbd2cSJim Jagielski         if( pOld->type == XML_ATTRIBUTE_NODE )
896*b1cdbd2cSJim Jagielski         {
897*b1cdbd2cSJim Jagielski             // can only replace attribute with attribute
898*b1cdbd2cSJim Jagielski             if ( pOld->type != pNew->type )
899*b1cdbd2cSJim Jagielski             {
900*b1cdbd2cSJim Jagielski                 DOMException e;
901*b1cdbd2cSJim Jagielski                 e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
902*b1cdbd2cSJim Jagielski                 throw e;
903*b1cdbd2cSJim Jagielski             }
904*b1cdbd2cSJim Jagielski 
905*b1cdbd2cSJim Jagielski             xmlAttrPtr pAttr = (xmlAttrPtr)pOld;
906*b1cdbd2cSJim Jagielski             xmlRemoveProp( pAttr );
907*b1cdbd2cSJim Jagielski             pOldNode->invalidate(); // freed by xmlRemoveProp
908*b1cdbd2cSJim Jagielski             appendChild(xNewChild);
909*b1cdbd2cSJim Jagielski         }
910*b1cdbd2cSJim Jagielski         else
911*b1cdbd2cSJim Jagielski         {
912*b1cdbd2cSJim Jagielski 
913*b1cdbd2cSJim Jagielski         xmlNodePtr cur = m_aNodePtr->children;
914*b1cdbd2cSJim Jagielski         //find old node in child list
915*b1cdbd2cSJim Jagielski         while (cur != NULL)
916*b1cdbd2cSJim Jagielski         {
917*b1cdbd2cSJim Jagielski             if(cur == pOld)
918*b1cdbd2cSJim Jagielski             {
919*b1cdbd2cSJim Jagielski                 // exchange nodes
920*b1cdbd2cSJim Jagielski                 pNew->prev = pOld->prev;
921*b1cdbd2cSJim Jagielski                 if (pNew->prev != NULL)
922*b1cdbd2cSJim Jagielski                     pNew->prev->next = pNew;
923*b1cdbd2cSJim Jagielski                 pNew->next = pOld->next;
924*b1cdbd2cSJim Jagielski                 if (pNew->next != NULL)
925*b1cdbd2cSJim Jagielski                     pNew->next->prev = pNew;
926*b1cdbd2cSJim Jagielski                 pNew->parent = pOld->parent;
927*b1cdbd2cSJim Jagielski                 if(pNew->parent->children == pOld)
928*b1cdbd2cSJim Jagielski                     pNew->parent->children = pNew;
929*b1cdbd2cSJim Jagielski                 if(pNew->parent->last == pOld)
930*b1cdbd2cSJim Jagielski                     pNew->parent->last = pNew;
931*b1cdbd2cSJim Jagielski                 pOld->next = NULL;
932*b1cdbd2cSJim Jagielski                 pOld->prev = NULL;
933*b1cdbd2cSJim Jagielski                 pOld->parent = NULL;
934*b1cdbd2cSJim Jagielski                 pOldNode->m_bUnlinked = true;
935*b1cdbd2cSJim Jagielski                 pNewNode->m_bUnlinked = false; // will be deleted by xmlFreeDoc
936*b1cdbd2cSJim Jagielski             }
937*b1cdbd2cSJim Jagielski             cur = cur->next;
938*b1cdbd2cSJim Jagielski         }
939*b1cdbd2cSJim Jagielski         }
940*b1cdbd2cSJim Jagielski 
941*b1cdbd2cSJim Jagielski         guard.clear(); // release for calling event handlers
942*b1cdbd2cSJim Jagielski         dispatchSubtreeModified();
943*b1cdbd2cSJim Jagielski 
944*b1cdbd2cSJim Jagielski         return xOldChild;
945*b1cdbd2cSJim Jagielski     }
946*b1cdbd2cSJim Jagielski 
dispatchSubtreeModified()947*b1cdbd2cSJim Jagielski     void CNode::dispatchSubtreeModified()
948*b1cdbd2cSJim Jagielski     {
949*b1cdbd2cSJim Jagielski         // only uses UNO interfaces => needs no mutex
950*b1cdbd2cSJim Jagielski 
951*b1cdbd2cSJim Jagielski         // dispatch DOMSubtreeModified
952*b1cdbd2cSJim Jagielski         // target is _this_ node
953*b1cdbd2cSJim Jagielski         Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
954*b1cdbd2cSJim Jagielski         Reference< XMutationEvent > event(docevent->createEvent(
955*b1cdbd2cSJim Jagielski             OUString::createFromAscii("DOMSubtreeModified")), UNO_QUERY);
956*b1cdbd2cSJim Jagielski         event->initMutationEvent(
957*b1cdbd2cSJim Jagielski             OUString::createFromAscii("DOMSubtreeModified"), sal_True,
958*b1cdbd2cSJim Jagielski             sal_False, Reference< XNode >(),
959*b1cdbd2cSJim Jagielski             OUString(), OUString(), OUString(), (AttrChangeType)0 );
960*b1cdbd2cSJim Jagielski         dispatchEvent(Reference< XEvent >(event, UNO_QUERY));
961*b1cdbd2cSJim Jagielski     }
962*b1cdbd2cSJim Jagielski 
963*b1cdbd2cSJim Jagielski     /**
964*b1cdbd2cSJim Jagielski     The value of this node, depending on its type; see the table above.
965*b1cdbd2cSJim Jagielski     */
setNodeValue(const OUString &)966*b1cdbd2cSJim Jagielski     void SAL_CALL CNode::setNodeValue(const OUString& /*nodeValue*/)
967*b1cdbd2cSJim Jagielski         throw (RuntimeException, DOMException)
968*b1cdbd2cSJim Jagielski     {
969*b1cdbd2cSJim Jagielski         // use specific node implememntation
970*b1cdbd2cSJim Jagielski         // if we end up down here, something went wrong
971*b1cdbd2cSJim Jagielski         DOMException e;
972*b1cdbd2cSJim Jagielski         e.Code = DOMExceptionType_NO_MODIFICATION_ALLOWED_ERR;
973*b1cdbd2cSJim Jagielski         throw e;
974*b1cdbd2cSJim Jagielski     }
975*b1cdbd2cSJim Jagielski 
976*b1cdbd2cSJim Jagielski     /**
977*b1cdbd2cSJim Jagielski     The namespace prefix of this node, or null if it is unspecified.
978*b1cdbd2cSJim Jagielski     */
setPrefix(const OUString & prefix)979*b1cdbd2cSJim Jagielski     void SAL_CALL CNode::setPrefix(const OUString& prefix)
980*b1cdbd2cSJim Jagielski         throw (RuntimeException, DOMException)
981*b1cdbd2cSJim Jagielski     {
982*b1cdbd2cSJim Jagielski         ::osl::MutexGuard const g(m_rMutex);
983*b1cdbd2cSJim Jagielski 
984*b1cdbd2cSJim Jagielski         if ((0 == m_aNodePtr) ||
985*b1cdbd2cSJim Jagielski             ((m_aNodePtr->type != XML_ELEMENT_NODE) &&
986*b1cdbd2cSJim Jagielski              (m_aNodePtr->type != XML_ATTRIBUTE_NODE)))
987*b1cdbd2cSJim Jagielski         {
988*b1cdbd2cSJim Jagielski             DOMException e;
989*b1cdbd2cSJim Jagielski             e.Code = DOMExceptionType_NO_MODIFICATION_ALLOWED_ERR;
990*b1cdbd2cSJim Jagielski             throw e;
991*b1cdbd2cSJim Jagielski         }
992*b1cdbd2cSJim Jagielski         OString o1 = OUStringToOString(prefix, RTL_TEXTENCODING_UTF8);
993*b1cdbd2cSJim Jagielski         xmlChar *pBuf = (xmlChar*)o1.getStr();
994*b1cdbd2cSJim Jagielski         if (m_aNodePtr != NULL && m_aNodePtr->ns != NULL)
995*b1cdbd2cSJim Jagielski         {
996*b1cdbd2cSJim Jagielski             xmlFree(const_cast<xmlChar *>(m_aNodePtr->ns->prefix));
997*b1cdbd2cSJim Jagielski             m_aNodePtr->ns->prefix = xmlStrdup(pBuf);
998*b1cdbd2cSJim Jagielski         }
999*b1cdbd2cSJim Jagielski 
1000*b1cdbd2cSJim Jagielski     }
1001*b1cdbd2cSJim Jagielski 
1002*b1cdbd2cSJim Jagielski         // --- XEventTarget
addEventListener(const OUString & eventType,const Reference<com::sun::star::xml::dom::events::XEventListener> & listener,sal_Bool useCapture)1003*b1cdbd2cSJim Jagielski     void SAL_CALL CNode::addEventListener(const OUString& eventType,
1004*b1cdbd2cSJim Jagielski         const Reference< com::sun::star::xml::dom::events::XEventListener >& listener,
1005*b1cdbd2cSJim Jagielski         sal_Bool useCapture)
1006*b1cdbd2cSJim Jagielski         throw (RuntimeException)
1007*b1cdbd2cSJim Jagielski     {
1008*b1cdbd2cSJim Jagielski         ::osl::MutexGuard const g(m_rMutex);
1009*b1cdbd2cSJim Jagielski 
1010*b1cdbd2cSJim Jagielski         CDocument & rDocument(GetOwnerDocument());
1011*b1cdbd2cSJim Jagielski         events::CEventDispatcher & rDispatcher(rDocument.GetEventDispatcher());
1012*b1cdbd2cSJim Jagielski         rDispatcher.addListener(m_aNodePtr, eventType, listener, useCapture);
1013*b1cdbd2cSJim Jagielski     }
1014*b1cdbd2cSJim Jagielski 
removeEventListener(const OUString & eventType,const Reference<com::sun::star::xml::dom::events::XEventListener> & listener,sal_Bool useCapture)1015*b1cdbd2cSJim Jagielski     void SAL_CALL CNode::removeEventListener(const OUString& eventType,
1016*b1cdbd2cSJim Jagielski         const Reference< com::sun::star::xml::dom::events::XEventListener >& listener,
1017*b1cdbd2cSJim Jagielski         sal_Bool useCapture)
1018*b1cdbd2cSJim Jagielski         throw (RuntimeException)
1019*b1cdbd2cSJim Jagielski     {
1020*b1cdbd2cSJim Jagielski         ::osl::MutexGuard const g(m_rMutex);
1021*b1cdbd2cSJim Jagielski 
1022*b1cdbd2cSJim Jagielski         CDocument & rDocument(GetOwnerDocument());
1023*b1cdbd2cSJim Jagielski         events::CEventDispatcher & rDispatcher(rDocument.GetEventDispatcher());
1024*b1cdbd2cSJim Jagielski         rDispatcher.removeListener(m_aNodePtr, eventType, listener, useCapture);
1025*b1cdbd2cSJim Jagielski     }
1026*b1cdbd2cSJim Jagielski 
dispatchEvent(const Reference<XEvent> & evt)1027*b1cdbd2cSJim Jagielski     sal_Bool SAL_CALL CNode::dispatchEvent(const Reference< XEvent >& evt)
1028*b1cdbd2cSJim Jagielski         throw(RuntimeException, EventException)
1029*b1cdbd2cSJim Jagielski     {
1030*b1cdbd2cSJim Jagielski         CDocument * pDocument;
1031*b1cdbd2cSJim Jagielski         events::CEventDispatcher * pDispatcher;
1032*b1cdbd2cSJim Jagielski         xmlNodePtr pNode;
1033*b1cdbd2cSJim Jagielski         {
1034*b1cdbd2cSJim Jagielski             ::osl::MutexGuard const g(m_rMutex);
1035*b1cdbd2cSJim Jagielski 
1036*b1cdbd2cSJim Jagielski             pDocument = & GetOwnerDocument();
1037*b1cdbd2cSJim Jagielski             pDispatcher = & pDocument->GetEventDispatcher();
1038*b1cdbd2cSJim Jagielski             pNode = m_aNodePtr;
1039*b1cdbd2cSJim Jagielski         }
1040*b1cdbd2cSJim Jagielski         // this calls event listeners, do not call with locked mutex
1041*b1cdbd2cSJim Jagielski         pDispatcher->dispatchEvent(*pDocument, m_rMutex, pNode, this, evt);
1042*b1cdbd2cSJim Jagielski         return sal_True;
1043*b1cdbd2cSJim Jagielski     }
1044*b1cdbd2cSJim Jagielski 
1045*b1cdbd2cSJim Jagielski     ::sal_Int64 SAL_CALL
getSomething(Sequence<::sal_Int8> const & rId)1046*b1cdbd2cSJim Jagielski     CNode::getSomething(Sequence< ::sal_Int8 > const& rId)
1047*b1cdbd2cSJim Jagielski         throw (RuntimeException)
1048*b1cdbd2cSJim Jagielski     {
1049*b1cdbd2cSJim Jagielski         if ((rId.getLength() == 16) &&
1050*b1cdbd2cSJim Jagielski             (0 == rtl_compareMemory(UnoTunnelId::get().getConstArray(),
1051*b1cdbd2cSJim Jagielski                                     rId.getConstArray(), 16)))
1052*b1cdbd2cSJim Jagielski         {
1053*b1cdbd2cSJim Jagielski             return ::sal::static_int_cast< sal_Int64 >(
1054*b1cdbd2cSJim Jagielski                     reinterpret_cast< sal_IntPtr >(this) );
1055*b1cdbd2cSJim Jagielski         }
1056*b1cdbd2cSJim Jagielski         return 0;
1057*b1cdbd2cSJim Jagielski     }
1058*b1cdbd2cSJim Jagielski }
1059*b1cdbd2cSJim Jagielski 
1060