1 /*
2  * This file is part of the DOM implementation for KDE.
3  *
4  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
5  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
6  *           (C) 2001 Dirk Mueller (mueller@kde.org)
7  *           (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public License
20  * along with this library; see the file COPYING.LIB.  If not, write to
21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  *
24  */
25 #ifndef _DOM_NodeImpl_h_
26 #define _DOM_NodeImpl_h_
27 
28 #include "dom/dom_misc.h"
29 #include "dom/dom_string.h"
30 #include "dom/dom_node.h"
31 #include "misc/helper.h"
32 #include "misc/shared.h"
33 #include "misc/idstring.h"
34 #include "wtf/PassRefPtr.h"
35 #include "misc/htmlnames.h"
36 #include "dom/QualifiedName.h"
37 #include "xml/dom2_eventsimpl.h"
38 
39 template <class type> class QList;
40 class KHTMLView;
41 class QRect;
42 class QMouseEvent;
43 class QKeyEvent;
44 
45 namespace khtml
46 {
47 class RenderStyle;
48 class RenderObject;
49 class RenderArena;
50 class RenderPosition;
51 }
52 
53 namespace DOM
54 {
55 
56 class NodeListImpl;
57 class NamedNodeMapImpl;
58 class DocumentImpl;
59 class ElementImpl;
60 class RegisteredEventListener;
61 class EventImpl;
62 class Selection;
63 
64 class NodeImpl : public EventTargetImpl
65 {
66     friend class DocumentImpl;
67 public:
68     NodeImpl(DocumentImpl *doc);
69     virtual ~NodeImpl();
70 
71     //stuff for WebCore DOM & SVG
hasTagName(const QualifiedName &)72     virtual bool hasTagName(const QualifiedName & /*name*/) const
73     {
74         return false;
75     }
76 
77     // EventTarget
eventTargetType()78     Type eventTargetType() const override
79     {
80         return DOM_NODE;
81     }
82     // covariant override
parent()83     NodeImpl *parent() const
84     {
85         return parentNode();
86     }
87 
88     // DOM methods & attributes for Node
89     virtual DOMString nodeName() const;
90     virtual DOMString nodeValue() const;
91     virtual void setNodeValue(const DOMString &_nodeValue, int &exceptioncode);
92     virtual unsigned short nodeType() const;
parentNode()93     NodeImpl *parentNode() const
94     {
95         return static_cast<NodeImpl *>(m_parent);
96     }
previousSibling()97     NodeImpl *previousSibling() const
98     {
99         return m_previous;
100     }
nextSibling()101     NodeImpl *nextSibling() const
102     {
103         return m_next;
104     }
105     virtual WTF::PassRefPtr<NodeListImpl> childNodes();
106     virtual NodeImpl *firstChild() const;
107     virtual NodeImpl *lastChild() const;
108 
109     virtual bool hasAttributes() const;
110     //OwnerDocument as specified by the DOM. Do not use for other purposes, it's weird!
111     DocumentImpl *ownerDocument() const;
112     NodeListImpl *getElementsByTagName(const DOMString &tagName);
113     NodeListImpl *getElementsByTagNameNS(const DOMString &namespaceURI, const DOMString &localName);
114 
115     // HTML 5
116     NodeListImpl *getElementsByClassName(const DOMString &name);
117 
118     // DOM3. See the wrapper (DOM::Node for the constants used in the return value
119     unsigned compareDocumentPosition(const DOM::NodeImpl *other);
120 
121     // WA Selector API L1. It's specified only for some types, but we provide it here
122     WTF::PassRefPtr<DOM::ElementImpl>  querySelector(const DOM::DOMString &query, int &ec);
123     WTF::PassRefPtr<DOM::NodeListImpl> querySelectorAll(const DOM::DOMString &query, int &ec);
124 
125     // insertBefore, replaceChild and appendChild also close newChild
126     // unlike the speed optimized addChild (which is used by the parser)
127     virtual NodeImpl *insertBefore(NodeImpl *newChild, NodeImpl *refChild, int &exceptioncode);
128 
129     /* These two methods may delete the old node, so make sure to reference it if you need it */
130     virtual void replaceChild(NodeImpl *newChild, NodeImpl *oldChild, int &exceptioncode);
131     virtual void removeChild(NodeImpl *oldChild, int &exceptioncode);
132     virtual NodeImpl *appendChild(NodeImpl *newChild, int &exceptioncode);
133     virtual void remove(int &exceptioncode);
134     virtual bool hasChildNodes() const;
135     virtual WTF::PassRefPtr<NodeImpl> cloneNode(bool deep) = 0;
136     virtual DOMString localName() const;
137     virtual DOMString prefix() const;
138     virtual DOMString namespaceURI() const;
139     virtual void setPrefix(const DOMString &_prefix, int &exceptioncode);
140     void normalize();
141     static bool isSupported(const DOMString &feature, const DOMString &version);
142 
143     // Other methods (not part of DOM)
isElementNode()144     virtual bool isElementNode() const
145     {
146         return false;
147     }
isHTMLElement()148     virtual bool isHTMLElement() const
149     {
150         return false;
151     }
isAttributeNode()152     virtual bool isAttributeNode() const
153     {
154         return false;
155     }
isTextNode()156     virtual bool isTextNode() const
157     {
158         return false;
159     }
isDocumentNode()160     virtual bool isDocumentNode() const
161     {
162         return false;
163     }
isXMLElementNode()164     virtual bool isXMLElementNode() const
165     {
166         return false;
167     }
isGenericFormElement()168     virtual bool isGenericFormElement() const
169     {
170         return false;
171     }
containsOnlyWhitespace()172     virtual bool containsOnlyWhitespace() const
173     {
174         return false;
175     }
176     bool isBlockFlow() const;
177 
178     // methods for WebCore api compat (SVG)
isSVGElement()179     virtual bool isSVGElement() const
180     {
181         return false;
182     }
isShadowNode()183     virtual bool isShadowNode() const
184     {
185         return false;
186     }
shadowParentNode()187     virtual NodeImpl *shadowParentNode()
188     {
189         return nullptr;
190     }
191 
192     DOMString textContent() const;
193     void setTextContent(const DOMString &text, int &ec);
194 
195     // helper functions not being part of the DOM
196     // Attention: they assume that the caller did the consistency checking!
setPreviousSibling(NodeImpl * previous)197     void setPreviousSibling(NodeImpl *previous)
198     {
199         m_previous = previous;
200     }
setNextSibling(NodeImpl * next)201     void setNextSibling(NodeImpl *next)
202     {
203         m_next = next;
204     }
205 
206     virtual void setFirstChild(NodeImpl *child);
207     virtual void setLastChild(NodeImpl *child);
208 
209     /** (Not part of the official DOM)
210      * Returns the next leaf node.
211      *
212      * Using this function delivers leaf nodes as if the whole DOM tree
213      * were a linear chain of its leaf nodes.
214      * @return next leaf node or 0 if there are no more.
215      */
216     NodeImpl *nextLeafNode() const;
217 
218     /** (Not part of the official DOM)
219      * Returns the previous leaf node.
220      *
221      * Using this function delivers leaf nodes as if the whole DOM tree
222      * were a linear chain of its leaf nodes.
223      * @return previous leaf node or 0 if there are no more.
224      */
225     NodeImpl *previousLeafNode() const;
226 
227     bool isEditableBlock() const;
228     ElementImpl *enclosingBlockFlowElement() const;
229     ElementImpl *rootEditableElement() const;
230 
231     bool inSameRootEditableElement(NodeImpl *);
232     bool inSameContainingBlockFlowElement(NodeImpl *);
233 
234     khtml::RenderPosition positionForCoordinates(int x, int y) const;
235     bool isPointInsideSelection(int x, int y, const Selection &) const;
236 
237     // used by the parser. Doesn't do as many error checkings as
238     // appendChild(), and returns the node into which will be parsed next.
239     virtual NodeImpl *addChild(NodeImpl *newChild);
240 
241     typedef quint32 Id;
242     // id() is used to easily and exactly identify a node. It
243     // is optimized for quick comparison and low memory consumption.
244     // its value depends on the owner document of the node and is
245     // categorized in the following way:
246     // 1..ID_LAST_TAG: the node inherits HTMLElementImpl and is
247     //                 part of the HTML namespace.
248     //                 The HTML namespace is either the global
249     //                 one (no namespace) or the XHTML namespace
250     //                 depending on the owner document's doctype
251     // ID_LAST_TAG+1..0xffff: non-HTML elements in the global namespace
252     // others       non-HTML elements in a namespace.
253     //                 the upper 16 bit identify the namespace
254     //                 the lower 16 bit identify the local part of the
255     //                 qualified element name.
id()256     virtual Id id() const
257     {
258         return 0;
259     }
260 
261     enum MouseEventType {
262         MousePress,
263         MouseRelease,
264         MouseClick,
265         MouseDblClick,
266         MouseMove,
267         MouseWheel
268     };
269 
270     struct MouseEvent {
271         MouseEvent(int _button, MouseEventType _type,
272                    const DOMString &_url = DOMString(), const DOMString &_target = DOMString(),
273                    NodeImpl *_innerNode = nullptr, NodeImpl *_innerNonSharedNode = nullptr)
274         {
275             button = _button; type = _type;
276             url = _url; target = _target;
277             innerNode = _innerNode;
278             innerNonSharedNode = _innerNonSharedNode;
279         }
280 
281         int button;
282         MouseEventType type;
283         DOMString url; // url under mouse or empty
284         DOMString target;
285         Node innerNode;
286         Node innerNonSharedNode;
287     };
288 
289     // for LINK and STYLE
290     // will increase/decrease the document's pending sheet count if appropriate
checkAddPendingSheet()291     virtual bool checkAddPendingSheet()
292     {
293         return true;
294     }
checkRemovePendingSheet()295     virtual bool checkRemovePendingSheet()
296     {
297         return true;
298     }
299 
hasID()300     bool hasID() const
301     {
302         return m_hasId;
303     }
hasClass()304     bool hasClass() const
305     {
306         return m_hasClass;
307     }
hasCombinedStyle()308     bool hasCombinedStyle() const
309     {
310         return m_hasCombinedStyle;
311     }
active()312     bool active() const
313     {
314         return m_active;
315     }
focused()316     bool focused() const
317     {
318         return m_focused;
319     }
hovered()320     bool hovered() const
321     {
322         return m_hovered;
323     }
attached()324     bool attached() const
325     {
326         return m_attached;
327     }
closed()328     bool closed() const
329     {
330         return m_closed;
331     }
changed()332     bool changed() const
333     {
334         return m_changed;
335     }
hasChangedChild()336     bool hasChangedChild() const
337     {
338         return m_hasChangedChild;
339     }
hasAnchor()340     bool hasAnchor() const
341     {
342         return m_hasAnchor;
343     }
inDocument()344     bool inDocument() const
345     {
346         return m_inDocument;
347     }
implicitNode()348     bool implicitNode() const
349     {
350         return m_implicit;
351     }
htmlCompat()352     bool htmlCompat() const
353     {
354         return m_htmlCompat;
355     }
356     void setHasID(bool b = true)
357     {
358         m_hasId = b;
359     }
360     void setHasClass(bool b = true)
361     {
362         m_hasClass = b;
363     }
364     void setHasChangedChild(bool b = true)
365     {
366         m_hasChangedChild = b;
367     }
368     void setInDocument(bool b = true)
369     {
370         m_inDocument = b;
371     }
setHTMLCompat(bool b)372     void setHTMLCompat(bool b)
373     {
374         m_htmlCompat = b;
375     }
hasHoverDependency()376     bool hasHoverDependency()
377     {
378         return m_hasHoverDependency;
379     }
380     void setHasHoverDependency(bool b = true)
381     {
382         m_hasHoverDependency = b;
383     }
384     void setNeedsStyleAttributeUpdate(bool b = true)
385     {
386         m_needsStyleAttributeUpdate = b;
387     }
388     virtual void setFocus(bool b = true)
389     {
390         m_focused = b;
391     }
392     virtual void setActive(bool b = true)
393     {
394         m_active = b;
395     }
396     virtual void setHovered(bool b = true)
397     {
398         m_hovered = b;
399     }
400     virtual void setChanged(bool b = true);
401     // for WebCore API compatibility
402     void setAttached(bool b = true)
403     {
404         m_attached = b;
405     }
406 
407     // for descending restyle when ID or CLASS changes
changedAscendentAttribute()408     bool changedAscendentAttribute() const
409     {
410         return m_changedAscendentAttribute;
411     }
setChangedAscendentAttribute(bool b)412     void setChangedAscendentAttribute(bool b)
413     {
414         m_changedAscendentAttribute = b;
415     }
416 
tabIndex()417     virtual short tabIndex() const
418     {
419         return 0;
420     }
421 
422     enum FocusType {
423         FT_Any,
424         FT_Mouse,
425         FT_Tab
426     };
427 
428     // Elements that are focusable by default should override this.
429     // Warning: if they're in a language that supports tabIndex (e.g. HTML),
430     // they must call back to the base class whenever hasTabIndex() is set.
isFocusableImpl(FocusType)431     virtual bool isFocusableImpl(FocusType) const
432     {
433         return false;
434     }
isFocusable()435     bool isFocusable() const
436     {
437         return isFocusableImpl(FT_Any);
438     }
isMouseFocusable()439     bool isMouseFocusable() const
440     {
441         return isFocusableImpl(FT_Mouse);
442     }
isTabFocusable()443     bool isTabFocusable() const
444     {
445         return isFocusableImpl(FT_Tab);
446     }
447 
448     virtual bool isInline() const;
449 
450     virtual bool isContentEditable() const;
451     virtual void getCaret(int offset, bool override, int &_x, int &_y, int &width, int &height);
452     virtual QRect getRect() const;
453 
454     enum StyleChange { NoChange, NoInherit, Inherit, Detach, Force };
455     virtual void recalcStyle(StyleChange = NoChange) {}
456     static StyleChange diff(khtml::RenderStyle *s1, khtml::RenderStyle *s2);
457     static bool pseudoDiff(khtml::RenderStyle *s1, khtml::RenderStyle *s2, unsigned int pid);
458 
459     virtual bool affectedByNoInherit() const;
460 
461     unsigned long nodeIndex() const;
462     // Returns the document that this node is associated with. This is guaranteed to always be non-null, as opposed to
463     // DOM's ownerDocument() which is null for Document nodes (and sometimes DocumentType nodes).
document()464     DocumentImpl *document() const
465     {
466         return m_document.get();
467     }
468     void setDocument(DocumentImpl *doc);
469 
470     DocumentImpl *eventTargetDocument() override;
471 
472     void dispatchEvent(EventImpl *evt, int &exceptioncode, bool tempEvent = false);
473 
474     // takes care of bubbling and the like. The target is generally 'this',
475     // unless the event specifies something special like Window as the target,
476     // in which case that's used for dispatch.
477     void dispatchGenericEvent(EventImpl *evt, int &exceptioncode);
478 
479     // return true if event not prevented
480     bool dispatchHTMLEvent(int _id, bool canBubbleArg, bool cancelableArg);
481 
482     // Window events are special in that they're only dispatched on Window, and not
483     // the current node.
484     void dispatchWindowEvent(int _id, bool canBubbleArg, bool cancelableArg);
485     void dispatchWindowEvent(EventImpl *evt);
486 
487     void dispatchMouseEvent(QMouseEvent *e, int overrideId = 0, int overrideDetail = 0);
488     void dispatchUIEvent(int _id, int detail = 0);
489     void dispatchSubtreeModifiedEvent();
490     // return true if defaultPrevented (i.e. event should be swallowed)
491     // this matches the logic in KHTMLView.
492     bool dispatchKeyEvent(QKeyEvent *key, bool keypress);
493 
494     virtual bool isReadOnly();
childTypeAllowed(unsigned short)495     virtual bool childTypeAllowed(unsigned short /*type*/)
496     {
497         return false;
498     }
499     virtual unsigned long childNodeCount();
500     virtual NodeImpl *childNode(unsigned long index);
501 
502     /**
503      * Does a pre-order traversal of the tree to find the node next node after this one. This uses the same order that
504      * the tags appear in the source file.
505      *
506      * @param stayWithin If not null, the traversal will stop once the specified node is reached. This can be used to
507      * restrict traversal to a particular sub-tree.
508      *
509      * @return The next node, in document order
510      *
511      * see traversePreviousNode()
512      */
513     NodeImpl *traverseNextNode(NodeImpl *stayWithin = nullptr) const;
514 
515     /**
516      * Does a reverse pre-order traversal to find the node that comes before the current one in document order
517      *
518      * see traverseNextNode()
519      */
520     NodeImpl *traversePreviousNode() const;
521 
docPtr()522     DocumentImpl *docPtr() const
523     {
524         return m_document.get();
525     }
526 
527     NodeImpl *previousEditable() const;
528     NodeImpl *nextEditable() const;
529     //bool isEditable() const;
530 
renderer()531     khtml::RenderObject *renderer() const
532     {
533         return m_render;
534     }
535     khtml::RenderObject *nextRenderer();
536     khtml::RenderObject *previousRenderer();
setRenderer(khtml::RenderObject * renderer)537     void setRenderer(khtml::RenderObject *renderer)
538     {
539         m_render = renderer;
540     }
541 
542     void checkSetPrefix(const DOMString &_prefix, int &exceptioncode);
543     void checkAddChild(NodeImpl *newChild, int &exceptioncode);
544     bool isAncestor(NodeImpl *other) const;
545     virtual bool childAllowed(NodeImpl *newChild);
546 
547     // Used to determine whether range offsets use characters or node indices.
offsetInCharacters()548     virtual bool offsetInCharacters() const
549     {
550         return false;
551     }
552     // Number of DOM 16-bit units contained in node. Note that rendered text length can be different - e.g. because of
553     // css-transform:capitalize breaking up precomposed characters and ligatures.
maxCharacterOffset()554     virtual int maxCharacterOffset() const
555     {
556         return 0;
557     }
558 
559     virtual long maxOffset() const;
560     virtual long caretMinOffset() const;
561     virtual long caretMaxOffset() const;
562     virtual unsigned long caretMaxRenderedOffset() const;
563 
564     // -----------------------------------------------------------------------------
565     // Integration with rendering tree
566 
567     /**
568      * Attaches this node to the rendering tree. This calculates the style to be applied to the node and creates an
569      * appropriate RenderObject which will be inserted into the tree (except when the style has display: none). This
570      * makes the node visible in the KHTMLView.
571      */
572     virtual void attach();
573 
574     /**
575      * Detaches the node from the rendering tree, making it invisible in the rendered view. This method will remove
576      * the node's rendering object from the rendering tree and delete it.
577      */
578     virtual void detach();
579 
580     /**
581      * Notifies the node that no more children will be added during parsing.
582      * After a node has been closed all changes must go through the DOM interface.
583      */
584     virtual void close();
585 
structureChanged()586     virtual void structureChanged() {}
backwardsStructureChanged()587     virtual void backwardsStructureChanged() {}
588 
589     void createRendererIfNeeded();
590     virtual khtml::RenderStyle *styleForRenderer(khtml::RenderObject *parent);
591     virtual bool rendererIsNeeded(khtml::RenderStyle *);
592     virtual khtml::RenderObject *createRenderer(khtml::RenderArena *, khtml::RenderStyle *);
593 
594     virtual khtml::RenderStyle *computedStyle();
595 
596     // -----------------------------------------------------------------------------
597     // Methods for maintaining the state of the element between history navigation
598 
599     /**
600      * Indicates whether or not this type of node maintains its state. If so, the state of the node will be stored when
601      * the user goes to a different page using the state() method, and restored using the restoreState() method if the
602      * user returns (e.g. using the back button). This is used to ensure that user-changeable elements such as form
603      * controls maintain their contents when the user returns to a previous page in the history.
604      */
605     virtual bool maintainsState();
606 
607     /**
608      * Returns the state of this node represented as a string. This string will be passed to restoreState() if the user
609      * returns to the page.
610      *
611      * @return State information about the node represented as a string
612      */
613     virtual QString state();
614 
615     /**
616      * Sets the state of the element based on a string previosuly returned by state(). This is used to initialize form
617      * controls with their old values when the user returns to the page in their history.
618      *
619      * @param state A string representation of the node's previously-stored state
620      */
621     virtual void restoreState(const QString &state);
622 
623     // -----------------------------------------------------------------------------
624     // Notification of document structure changes
625 
626     /**
627      * Notifies the node that it has been inserted into the document. This is called during document parsing, and also
628      * when a node is added through the DOM methods insertBefore(), appendChild() or replaceChild(). Note that this only
629      * happens when the node becomes part of the document tree, i.e. only when the document is actually an ancestor of
630      * the node. The call happens _after_ the node has been added to the tree.
631      *
632      * This is similar to the DOMNodeInsertedIntoDocument DOM event, but does not require the overhead of event
633      * dispatching.
634      */
635     virtual void insertedIntoDocument();
636 
637     /**
638      * Notifies the node that it is no longer part of the document tree, i.e. when the document is no longer an ancestor
639      * node.
640      *
641      * This is similar to the DOMNodeRemovedFromDocument DOM event, but does not require the overhead of event
642      * dispatching, and is called _after_ the node is removed from the tree.
643      */
644     virtual void removedFromDocument();
645 
646     /**
647      * Notifies the node that its list of children have changed (either by adding or removing child nodes), or a child
648      * node that is of the type CDATA_SECTION_NODE, TEXT_NODE or COMMENT_NODE has changed its value.
649      */
650     virtual void childrenChanged();
651 
652     virtual DOMString toString() const = 0;
653     /**
654      * Sometimes we need to get the string between two points on the DOM graph.  Use this function to do this.
655      * For example, when the user copies some selected text to the clipboard as html.
656      * @param selectionStart Where to start the selection.  If selectionStart != this, it is assumed we are after the start point
657      * @param selectionEnd   Where to end the selection.  If selectionEnd != this, it is assumed we are before the end point (unless found is true)
658      * @param startOffset    Number of characters into the text in selectionStart that the start of the selection is.
659      * @param endOffset      Number of characters into the text in selectionEnd that the end of the selection is.
660      * @param found          When this is set to true, don't print anymore but closing tags.
661      * @return An html formatted string for this node and its children between the selectionStart and selectionEnd.
662      */
selectionToString(NodeImpl * selectionStart,NodeImpl * selectionEnd,int startOffset,int endOffset,bool & found)663     virtual DOMString selectionToString(NodeImpl *selectionStart,
664                                         NodeImpl *selectionEnd,
665                                         int startOffset,
666                                         int endOffset,
667                                         bool &found) const
668     {
669         Q_UNUSED(selectionStart);
670         Q_UNUSED(selectionEnd);
671         Q_UNUSED(startOffset);
672         Q_UNUSED(endOffset);
673         Q_UNUSED(found);
674         return toString();
675     }
676 
677     // FOR SVG Events support (WebCore API compatibility)
localEventListeners()678     QList<RegisteredEventListener> *localEventListeners()
679     {
680         return listenerList().listeners;
681     }
682 
683     DOMString lookupNamespaceURI(const DOMString &prefix);
684 
685 private: // members
686     khtml::DocPtr<DocumentImpl> m_document;
687     NodeImpl *m_previous;
688     NodeImpl *m_next;
689 
690     NodeImpl *findNextElementAncestor(NodeImpl *node);
691 protected:
692     khtml::RenderObject *m_render;
693 
694     bool m_hasId : 1;
695     bool m_attached : 1;
696     bool m_closed : 1;
697     bool m_changed : 1;
698     bool m_hasChangedChild : 1;
699     bool m_changedAscendentAttribute : 1;
700     bool m_inDocument : 1;
701     bool m_hasAnchor : 1;
702 
703     bool m_hovered : 1;
704     bool m_focused : 1;
705     bool m_active : 1;
706     bool m_implicit : 1; // implicitely generated by the parser
707     bool m_htmlCompat : 1; // true if element was created in HTML compat mode
708     bool m_hasClass : 1;   // true if element has a class property, as relevant to CSS
709     bool m_hasCombinedStyle : 1; // true if element has inline styles and presentational styles
710     bool m_hasHoverDependency : 1; // true if element has hover dependency on itself
711 
712     bool m_elementHasRareData : 1;
713     mutable bool m_needsStyleAttributeUpdate : 1; // true if |style| attribute is out of sync (i.e. CSSOM modified our inline styles)
714 
715     // 14 bits left
716 };
717 
718 // this is the full Node Implementation with parents and children.
719 class NodeBaseImpl : public NodeImpl
720 {
721 public:
NodeBaseImpl(DocumentImpl * doc)722     NodeBaseImpl(DocumentImpl *doc)
723         : NodeImpl(doc), _first(nullptr), _last(nullptr) {}
724     virtual ~NodeBaseImpl();
725 
726     // DOM methods overridden from  parent classes
727     NodeImpl *firstChild() const override;
728     NodeImpl *lastChild() const override;
729     NodeImpl *insertBefore(NodeImpl *newChild, NodeImpl *refChild, int &exceptioncode) override;
730     void replaceChild(NodeImpl *newChild, NodeImpl *oldChild, int &exceptioncode) override;
731     void removeChild(NodeImpl *oldChild, int &exceptioncode) override;
732     NodeImpl *appendChild(NodeImpl *newChild, int &exceptioncode) override;
733     bool hasChildNodes() const override;
734 
735     // Other methods (not part of DOM)
736     virtual void removeChildren();
737     void cloneChildNodes(NodeImpl *clone);
738 
739     void setFirstChild(NodeImpl *child) override;
740     void setLastChild(NodeImpl *child) override;
741     NodeImpl *addChild(NodeImpl *newChild) override;
742     void attach() override;
743     void detach() override;
744 
745     bool getUpperLeftCorner(int &xPos, int &yPos) const;
746     bool getLowerRightCorner(int &xPos, int &yPos) const;
747 
748     void setFocus(bool = true) override;
749     void setActive(bool = true) override;
750     void setHovered(bool = true) override;
751     unsigned long childNodeCount() override;
752     NodeImpl *childNode(unsigned long index) override;
753 
754 protected:
755     NodeImpl *_first;
756     NodeImpl *_last;
757 
758     // helper functions for inserting children:
759 
760     // ### this should vanish. do it in dom/ !
761     // check for same source document:
762     bool checkSameDocument(NodeImpl *newchild, int &exceptioncode);
763     // check for being child:
764     bool checkIsChild(NodeImpl *oldchild, int &exceptioncode);
765     // ###
766 
767     // find out if a node is allowed to be our child
768     void dispatchChildInsertedEvents(NodeImpl *child, int &exceptioncode);
769     void dispatchChildRemovalEvents(NodeImpl *child, int &exceptioncode);
770 };
771 
772 // Generic NamedNodeMap interface
773 // Other classes implement this for more specific situations e.g. attributes
774 // of an element
775 class NamedNodeMapImpl : public khtml::Shared<NamedNodeMapImpl>
776 {
777 public:
778     NamedNodeMapImpl();
779     virtual ~NamedNodeMapImpl();
780 
781     // DOM methods & attributes for NamedNodeMap
782     virtual NodeImpl *getNamedItem(NodeImpl::Id id, const PrefixName &prefix = emptyPrefixName, bool nsAware = false) = 0;
783     virtual Node removeNamedItem(NodeImpl::Id id, const PrefixName &prefix, bool nsAware, int &exceptioncode) = 0;
784     virtual Node setNamedItem(NodeImpl *arg, const PrefixName &prefix, bool nsAware, int &exceptioncode) = 0;
785 
786     //The DOM-style wrappers
787     NodeImpl *getNamedItem(const DOMString &name);
788     Node setNamedItem(const Node &arg, int &exceptioncode);
789     Node removeNamedItem(const DOMString &name, int &exceptioncode);
790     Node getNamedItemNS(const DOMString &namespaceURI, const DOMString &localName);
791     Node setNamedItemNS(const Node &arg, int &exceptioncode);
792     Node removeNamedItemNS(const DOMString &namespaceURI, const DOMString &localName, int &exceptioncode);
793 
794     virtual NodeImpl *item(unsigned index) = 0;
795     virtual unsigned length() const = 0;
796 
isReadOnly()797     virtual bool isReadOnly()
798     {
799         return false;
800     }
htmlCompat()801     virtual bool htmlCompat()
802     {
803         return false;
804     }
805 };
806 
807 // Generic read-only NamedNodeMap implementation
808 // Used for e.g. entities and notations in DocumentType.
809 // You can add nodes using addNode
810 class GenericRONamedNodeMapImpl : public NamedNodeMapImpl
811 {
812 public:
813     GenericRONamedNodeMapImpl(DocumentImpl *doc);
814     virtual ~GenericRONamedNodeMapImpl();
815 
816     // DOM methods & attributes for NamedNodeMap
817 
818     NodeImpl *getNamedItem(NodeImpl::Id id, const PrefixName &prefix = emptyPrefixName, bool nsAware = false) override;
819     Node removeNamedItem(NodeImpl::Id id, const PrefixName &prefix, bool nsAware, int &exceptioncode) override;
820     Node setNamedItem(NodeImpl *arg, const PrefixName &prefix, bool nsAware, int &exceptioncode) override;
821 
822     NodeImpl *item(unsigned index) override;
823     unsigned length() const override;
824 
isReadOnly()825     bool isReadOnly() override
826     {
827         return true;
828     }
829 
830     void addNode(NodeImpl *n);
831 
832 protected:
833     DocumentImpl *m_doc;
834     QList<NodeImpl *> *m_contents;
835 };
836 
837 } //namespace
838 #endif
839