Reviewed by Kevin.
[WebKit-https.git] / WebCore / khtml / dom / dom_node.cpp
1 /**
2  * This file is part of the DOM implementation for KDE.
3  *
4  * (C) 1999 Lars Knoll (knoll@kde.org)
5  * Copyright (C) 2004 Apple Computer, Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public License
18  * along with this library; see the file COPYING.LIB.  If not, write to
19  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  *
22  */
23
24 #include "dom/dom_doc.h"
25 #include "dom/dom_exception.h"
26 #include "dom/dom2_events.h"
27 #include "xml/dom_docimpl.h"
28 #include "xml/dom_elementimpl.h"
29 #include "xml/dom2_eventsimpl.h"
30
31 #include <qrect.h>
32
33 using namespace DOM;
34
35 NamedNodeMap::NamedNodeMap()
36 {
37     impl = 0;
38 }
39
40 NamedNodeMap::NamedNodeMap(const NamedNodeMap &other)
41 {
42     impl = other.impl;
43     if (impl) impl->ref();
44 }
45
46 NamedNodeMap::NamedNodeMap(NamedNodeMapImpl *i)
47 {
48     impl = i;
49     if (impl) impl->ref();
50 }
51
52 NamedNodeMap &NamedNodeMap::operator = (const NamedNodeMap &other)
53 {
54     if ( impl != other.impl ) {
55     if(impl) impl->deref();
56     impl = other.impl;
57     if(impl) impl->ref();
58     }
59     return *this;
60 }
61
62 NamedNodeMap::~NamedNodeMap()
63 {
64     if(impl) impl->deref();
65 }
66
67 Node NamedNodeMap::getNamedItem( const DOMString &name ) const
68 {
69     return getNamedItemNS(DOMString(), name);
70 }
71
72 Node NamedNodeMap::setNamedItem( const Node &arg )
73 {
74     return setNamedItemNS(arg);
75 }
76
77 Node NamedNodeMap::removeNamedItem( const DOMString &name )
78 {
79     return removeNamedItemNS(DOMString(), name);
80 }
81
82 Node NamedNodeMap::item( unsigned long index ) const
83 {
84     if (!impl) return 0;
85     return impl->item(index);
86 }
87
88 Node NamedNodeMap::getNamedItemNS( const DOMString &namespaceURI, const DOMString &localName ) const
89 {
90     if (!impl) return 0;
91     return impl->getNamedItem(impl->mapId(namespaceURI, localName, true));
92 }
93
94 Node NamedNodeMap::setNamedItemNS( const Node &arg )
95 {
96     if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
97     int exceptioncode = 0;
98     Node r = impl->setNamedItem(arg.impl, exceptioncode);
99     if (exceptioncode)
100         throw DOMException(exceptioncode);
101     return r;
102 }
103
104 Node NamedNodeMap::removeNamedItemNS( const DOMString &namespaceURI, const DOMString &localName )
105 {
106     if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
107     int exceptioncode = 0;
108     Node r = impl->removeNamedItem(impl->mapId(namespaceURI, localName, true), exceptioncode);
109     if (exceptioncode)
110         throw DOMException(exceptioncode);
111     return r;
112 }
113
114 unsigned long NamedNodeMap::length() const
115 {
116     if (!impl) return 0;
117     return impl->length();
118 }
119
120 NamedNodeMapImpl *NamedNodeMap::handle() const throw()
121 {
122     return impl;
123 }
124
125 bool NamedNodeMap::isNull() const throw()
126 {
127     return (impl == 0);
128 }
129
130 // ---------------------------------------------------------------------------
131
132 Node::Node()
133 {
134     impl = 0;
135 }
136
137 Node::Node(const Node &other)
138 {
139     impl = other.impl;
140     if(impl) impl->ref();
141 }
142
143 Node::Node( NodeImpl *i )
144 {
145     impl = i;
146     if(impl) impl->ref();
147 }
148
149 Node &Node::operator = (const Node &other)
150 {
151     if(impl != other.impl) {
152     if(impl) impl->deref();
153     impl = other.impl;
154     if(impl) impl->ref();
155     }
156     return *this;
157 }
158
159 bool Node::operator == (const Node &other)
160 {
161     return (impl == other.impl);
162 }
163
164 bool Node::operator != (const Node &other)
165 {
166     return !(impl == other.impl);
167 }
168
169 Node::~Node()
170 {
171     if(impl) impl->deref();
172 }
173
174 DOMString Node::nodeName() const
175 {
176     if(impl) return impl->nodeName();
177     return DOMString();
178 }
179
180 DOMString Node::nodeValue() const
181 {
182     // ### should throw exception on plain node ?
183     if(impl) return impl->nodeValue();
184     return DOMString();
185 }
186
187 void Node::setNodeValue( const DOMString &_str )
188 {
189     if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
190
191     int exceptioncode = 0;
192     if(impl) impl->setNodeValue( _str,exceptioncode );
193     if (exceptioncode)
194         throw DOMException(exceptioncode);
195 }
196
197 unsigned short Node::nodeType() const
198 {
199     if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
200     return impl->nodeType();
201 }
202
203 Node Node::parentNode() const
204 {
205     if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
206     return impl->parentNode();
207 }
208
209 NodeList Node::childNodes() const
210 {
211     if (!impl) return 0;
212     return impl->childNodes();
213 }
214
215 Node Node::firstChild() const
216 {
217     if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
218     return impl->firstChild();
219 }
220
221 Node Node::lastChild() const
222 {
223     if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
224     return impl->lastChild();
225 }
226
227 Node Node::previousSibling() const
228 {
229     if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
230     return impl->previousSibling();
231 }
232
233 Node Node::nextSibling() const
234 {
235     if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
236     return impl->nextSibling();
237 }
238
239 NamedNodeMap Node::attributes() const
240 {
241     if (!impl || !impl->isElementNode()) return 0;
242     return static_cast<ElementImpl*>(impl)->attributes();
243 }
244
245 Document Node::ownerDocument() const
246 {
247     // braindead DOM spec says that ownerDocument
248     // should return null if called on the document node
249     // we don't do that in the *impl tree to avoid excessive if()'s
250     // so we simply hack it here in one central place.
251     if (!impl || impl->getDocument() == impl) return Document(false);
252
253     return impl->getDocument();
254 }
255
256 Node Node::insertBefore( const Node &newChild, const Node &refChild )
257 {
258     if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
259     int exceptioncode = 0;
260     NodeImpl *r = impl->insertBefore( newChild.impl, refChild.impl, exceptioncode );
261     if (exceptioncode)
262         throw DOMException(exceptioncode);
263     return r;
264 }
265
266 Node Node::replaceChild( const Node &newChild, const Node &oldChild )
267 {
268     if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
269     int exceptioncode = 0;
270     NodeImpl *r = impl->replaceChild( newChild.impl, oldChild.impl, exceptioncode );
271     if (exceptioncode)
272         throw DOMException(exceptioncode);
273     return r;
274 }
275
276 Node Node::removeChild( const Node &oldChild )
277 {
278     if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
279     int exceptioncode = 0;
280     NodeImpl *r = impl->removeChild( oldChild.impl, exceptioncode );
281     if (exceptioncode)
282         throw DOMException(exceptioncode);
283     return r;
284 }
285
286 Node Node::appendChild( const Node &newChild )
287 {
288     if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
289     int exceptioncode = 0;
290     NodeImpl *r = impl->appendChild( newChild.impl, exceptioncode );
291     if (exceptioncode)
292         throw DOMException(exceptioncode);
293     return r;
294 }
295
296 bool Node::hasAttributes()
297 {
298     if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
299     if (!impl->isElementNode()) return false;
300     ElementImpl* e = static_cast<ElementImpl*>(impl);
301     return e->attributes(true) && e->attributes(true)->length();
302 }
303
304 bool Node::hasChildNodes(  )
305 {
306     if (!impl) return false;
307     return impl->hasChildNodes();
308 }
309
310 Node Node::cloneNode( bool deep )
311 {
312     if (!impl) return 0;
313     return impl->cloneNode( deep  );
314 }
315
316 void Node::normalize (  )
317 {
318     if (!impl) return;
319     impl->normalize();
320 }
321
322 bool Node::isSupported( const DOMString &feature, const DOMString &version ) const
323 {
324     return DOMImplementationImpl::instance()->hasFeature(feature, version);
325 }
326
327 DOMString Node::namespaceURI(  ) const
328 {
329     if (!impl) return DOMString();
330     return impl->getDocument()->namespaceURI(impl->id());
331 }
332
333 DOMString Node::prefix(  ) const
334 {
335     if (!impl) return DOMString();
336     return impl->prefix();
337 }
338
339 void Node::setPrefix(const DOMString &prefix )
340 {
341     if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
342     int exceptioncode = 0;
343     impl->setPrefix(prefix,exceptioncode);
344     if (exceptioncode)
345         throw DOMException(exceptioncode);
346 }
347
348 DOMString Node::localName(  ) const
349 {
350     if (!impl) return DOMString();
351     return impl->localName();
352 }
353
354 void Node::addEventListener(const DOMString &type,
355                           EventListener *listener,
356                           const bool useCapture)
357 {
358     if (!impl) return;
359     impl->addEventListener(EventImpl::typeToId(type),listener,useCapture);
360 }
361
362 void Node::removeEventListener(const DOMString &type,
363                              EventListener *listener,
364                              bool useCapture)
365 {
366     if (!impl) return;
367     impl->removeEventListener(EventImpl::typeToId(type),listener,useCapture);
368 }
369
370 bool Node::dispatchEvent(const Event &evt)
371 {
372     if (!impl)
373         throw DOMException(DOMException::INVALID_STATE_ERR);
374
375     int exceptioncode = 0;
376     bool r = impl->dispatchEvent(evt.handle(),exceptioncode);
377     if (exceptioncode)
378         throw DOMException(exceptioncode);
379     return r;
380 }
381
382
383 unsigned int Node::elementId() const
384 {
385     if (!impl) return 0;
386     return impl->id();
387 }
388
389 unsigned long Node::index() const
390 {
391     if (!impl) return 0;
392     return impl->nodeIndex();
393 }
394
395 QString Node::toHTML()
396 {
397     if (!impl) return QString::null;
398     return impl->toHTML();
399 }
400
401 void Node::applyChanges()
402 {
403     if (!impl) return;
404     impl->recalcStyle( NodeImpl::Inherit );
405 }
406
407 QRect Node::getRect()
408 {
409     if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
410     return impl->getRect();
411 }
412
413 bool Node::isNull() const
414 {
415     return (impl == 0);
416 }
417
418 NodeImpl *Node::handle() const
419 {
420     return impl;
421 }
422
423 bool Node::isContentEditable() const
424 {
425     if (!impl) return false;
426     return impl->isContentEditable();
427 }
428
429 //-----------------------------------------------------------------------------
430
431 NodeList::NodeList()
432 {
433     impl = 0;
434 }
435
436 NodeList::NodeList(const NodeList &other)
437 {
438     impl = other.impl;
439     if(impl) impl->ref();
440 }
441
442 NodeList::NodeList(const NodeListImpl *i)
443 {
444     impl = const_cast<NodeListImpl *>(i);
445     if(impl) impl->ref();
446 }
447
448 NodeList &NodeList::operator = (const NodeList &other)
449 {
450     if ( impl != other.impl ) {
451     if(impl) impl->deref();
452     impl = other.impl;
453     if(impl) impl->ref();
454     }
455     return *this;
456 }
457
458 NodeList::~NodeList()
459 {
460     if(impl) impl->deref();
461 }
462
463 Node NodeList::item( unsigned long index ) const
464 {
465     if (!impl) return 0;
466     return impl->item(index);
467 }
468
469 unsigned long NodeList::length() const
470 {
471     if (!impl) return 0;
472     return impl->length();
473 }
474
475 Node NodeList::itemById (const DOMString& elementId) const
476 {
477     if (!impl) return 0;
478     return impl->itemById(elementId);
479 }
480
481
482 NodeListImpl *NodeList::handle() const
483 {
484     return impl;
485 }
486
487 bool NodeList::isNull() const
488 {
489     return (impl == 0);
490 }
491