1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is Mozilla Communicator client code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either of the GNU General Public License Version 2 or later (the "GPL"),
26 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
39 * Base class for DOM Core's nsIDOMComment, nsIDOMDocumentType, nsIDOMText,
40 * nsIDOMCDATASection, and nsIDOMProcessingInstruction nodes.
43 #include "nsGenericDOMDataNode.h"
44 #include "nsGenericElement.h"
45 #include "nsIDocument.h"
46 #include "nsIEventListenerManager.h"
47 #include "nsIDOMDocument.h"
48 #include "nsReadableUtils.h"
49 #include "nsMutationEvent.h"
50 #include "nsINameSpaceManager.h"
51 #include "nsIDOM3Node.h"
53 #include "nsIPrivateDOMEvent.h"
54 #include "nsIDOMEvent.h"
55 #include "nsIDOMText.h"
57 #include "nsDOMString.h"
58 #include "nsIDOMUserDataHandler.h"
59 #include "nsChangeHint.h"
60 #include "nsEventDispatcher.h"
61 #include "nsCOMArray.h"
62 #include "nsNodeUtils.h"
63 #include "nsBindingManager.h"
64 #include "nsCCUncollectableMarker.h"
65 #include "mozAutoDocUpdate.h"
70 nsGenericDOMDataNode::nsGenericDOMDataNode(nsINodeInfo
*aNodeInfo
)
71 : nsIContent(aNodeInfo
)
75 nsGenericDOMDataNode::~nsGenericDOMDataNode()
77 NS_PRECONDITION(!IsInDoc(),
78 "Please remove this from the document properly");
81 NS_IMPL_CYCLE_COLLECTION_CLASS(nsGenericDOMDataNode
)
83 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsGenericDOMDataNode
)
84 nsIDocument
* currentDoc
= tmp
->GetCurrentDoc();
85 if (currentDoc
&& nsCCUncollectableMarker::InGeneration(
86 currentDoc
->GetMarkedCCGeneration())) {
90 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mNodeInfo
)
92 nsIDocument
* ownerDoc
= tmp
->GetOwnerDoc();
94 ownerDoc
->BindingManager()->Traverse(tmp
, cb
);
97 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_LISTENERMANAGER
98 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_USERDATA
99 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_PRESERVED_WRAPPER
100 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
102 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGenericDOMDataNode
)
103 NS_IMPL_CYCLE_COLLECTION_UNLINK_LISTENERMANAGER
104 NS_IMPL_CYCLE_COLLECTION_UNLINK_USERDATA
105 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
106 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
108 NS_INTERFACE_MAP_BEGIN(nsGenericDOMDataNode
)
109 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
110 NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsGenericDOMDataNode
)
111 NS_INTERFACE_MAP_ENTRY(nsIContent
)
112 NS_INTERFACE_MAP_ENTRY(nsINode
)
113 NS_INTERFACE_MAP_ENTRY(nsPIDOMEventTarget
)
114 NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMEventTarget
,
115 nsDOMEventRTTearoff::Create(this))
116 NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOM3EventTarget
,
117 nsDOMEventRTTearoff::Create(this))
118 NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMNSEventTarget
,
119 nsDOMEventRTTearoff::Create(this))
120 NS_INTERFACE_MAP_ENTRY_TEAROFF(nsISupportsWeakReference
,
121 new nsNodeSupportsWeakRefTearoff(this))
122 NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOM3Node
, new nsNode3Tearoff(this))
123 // nsNodeSH::PreCreate() depends on the identity pointer being the
124 // same as nsINode (which nsIContent inherits), so if you change the
125 // below line, make sure nsNodeSH::PreCreate() still does the right
127 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIContent
)
130 NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsGenericDOMDataNode
, nsIContent
)
131 NS_IMPL_CYCLE_COLLECTING_RELEASE_FULL(nsGenericDOMDataNode
, nsIContent
,
132 nsNodeUtils::LastRelease(this))
136 nsGenericDOMDataNode::GetNodeValue(nsAString
& aNodeValue
)
138 return GetData(aNodeValue
);
142 nsGenericDOMDataNode::SetNodeValue(const nsAString
& aNodeValue
)
144 return SetTextInternal(0, mText
.GetLength(), aNodeValue
.BeginReading(),
145 aNodeValue
.Length(), PR_TRUE
);
149 nsGenericDOMDataNode::GetParentNode(nsIDOMNode
** aParentNode
)
151 *aParentNode
= nsnull
;
152 nsINode
*parent
= GetNodeParent();
154 return parent
? CallQueryInterface(parent
, aParentNode
) : NS_OK
;
158 nsGenericDOMDataNode::GetPreviousSibling(nsIDOMNode
** aPrevSibling
)
160 *aPrevSibling
= nsnull
;
162 nsINode
*parent
= GetNodeParent();
167 PRInt32 pos
= parent
->IndexOf(this);
168 nsIContent
*sibling
= parent
->GetChildAt(pos
- 1);
170 return sibling
? CallQueryInterface(sibling
, aPrevSibling
) : NS_OK
;
174 nsGenericDOMDataNode::GetNextSibling(nsIDOMNode
** aNextSibling
)
176 *aNextSibling
= nsnull
;
178 nsINode
*parent
= GetNodeParent();
183 PRInt32 pos
= parent
->IndexOf(this);
184 nsIContent
*sibling
= parent
->GetChildAt(pos
+ 1);
186 return sibling
? CallQueryInterface(sibling
, aNextSibling
) : NS_OK
;
190 nsGenericDOMDataNode::GetChildNodes(nsIDOMNodeList
** aChildNodes
)
192 *aChildNodes
= nsnull
;
193 nsDataSlots
*slots
= GetDataSlots();
194 NS_ENSURE_TRUE(slots
, NS_ERROR_OUT_OF_MEMORY
);
196 if (!slots
->mChildNodes
) {
197 slots
->mChildNodes
= new nsChildContentList(this);
198 NS_ENSURE_TRUE(slots
->mChildNodes
, NS_ERROR_OUT_OF_MEMORY
);
199 NS_ADDREF(slots
->mChildNodes
);
202 NS_ADDREF(*aChildNodes
= slots
->mChildNodes
);
207 nsGenericDOMDataNode::GetOwnerDocument(nsIDOMDocument
** aOwnerDocument
)
209 nsIDocument
*document
= GetOwnerDoc();
211 return CallQueryInterface(document
, aOwnerDocument
);
214 *aOwnerDocument
= nsnull
;
220 nsGenericDOMDataNode::GetNamespaceURI(nsAString
& aNamespaceURI
)
222 SetDOMStringToNull(aNamespaceURI
);
228 nsGenericDOMDataNode::GetPrefix(nsAString
& aPrefix
)
230 SetDOMStringToNull(aPrefix
);
236 nsGenericDOMDataNode::SetPrefix(const nsAString
& aPrefix
)
238 return NS_ERROR_DOM_NAMESPACE_ERR
;
242 nsGenericDOMDataNode::GetLocalName(nsAString
& aLocalName
)
244 SetDOMStringToNull(aLocalName
);
250 nsGenericDOMDataNode::Normalize()
256 nsGenericDOMDataNode::IsSupported(const nsAString
& aFeature
,
257 const nsAString
& aVersion
,
260 return nsGenericElement::InternalIsSupported(static_cast<nsIContent
*>(this),
261 aFeature
, aVersion
, aReturn
);
265 nsGenericDOMDataNode::GetBaseURI(nsAString
& aURI
)
267 nsCOMPtr
<nsIURI
> baseURI
= GetBaseURI();
271 baseURI
->GetSpec(spec
);
274 CopyUTF8toUTF16(spec
, aURI
);
280 nsGenericDOMDataNode::LookupPrefix(const nsAString
& aNamespaceURI
,
285 nsIContent
*parent_weak
= GetParent();
287 // DOM Data Node passes the query on to its parent
288 nsCOMPtr
<nsIDOM3Node
> node(do_QueryInterface(parent_weak
));
290 return node
->LookupPrefix(aNamespaceURI
, aPrefix
);
297 nsGenericDOMDataNode::LookupNamespaceURI(const nsAString
& aNamespacePrefix
,
298 nsAString
& aNamespaceURI
)
300 aNamespaceURI
.Truncate();
302 nsIContent
*parent_weak
= GetParent();
304 // DOM Data Node passes the query on to its parent
305 nsCOMPtr
<nsIDOM3Node
> node(do_QueryInterface(parent_weak
));
308 return node
->LookupNamespaceURI(aNamespacePrefix
, aNamespaceURI
);
314 //----------------------------------------------------------------------
316 // Implementation of nsIDOMCharacterData
319 nsGenericDOMDataNode::GetData(nsAString
& aData
) const
322 aData
.Assign(mText
.Get2b(), mText
.GetLength());
324 // Must use Substring() since nsDependentCString() requires null
325 // terminated strings.
327 const char *data
= mText
.Get1b();
330 CopyASCIItoUTF16(Substring(data
, data
+ mText
.GetLength()), aData
);
340 nsGenericDOMDataNode::SetData(const nsAString
& aData
)
342 return SetTextInternal(0, mText
.GetLength(), aData
.BeginReading(),
343 aData
.Length(), PR_TRUE
);
347 nsGenericDOMDataNode::GetLength(PRUint32
* aLength
)
349 *aLength
= mText
.GetLength();
354 nsGenericDOMDataNode::SubstringData(PRUint32 aStart
, PRUint32 aCount
,
359 // XXX add <0 checks if types change
360 PRUint32 textLength
= PRUint32( mText
.GetLength() );
361 if (aStart
> textLength
) {
362 return NS_ERROR_DOM_INDEX_SIZE_ERR
;
365 PRUint32 amount
= aCount
;
366 if (amount
> textLength
- aStart
) {
367 amount
= textLength
- aStart
;
371 aReturn
.Assign(mText
.Get2b() + aStart
, amount
);
373 // Must use Substring() since nsDependentCString() requires null
374 // terminated strings.
376 const char *data
= mText
.Get1b() + aStart
;
377 CopyASCIItoUTF16(Substring(data
, data
+ amount
), aReturn
);
383 //----------------------------------------------------------------------
386 nsGenericDOMDataNode::AppendData(const nsAString
& aData
)
388 return SetTextInternal(mText
.GetLength(), 0, aData
.BeginReading(),
389 aData
.Length(), PR_TRUE
);
393 nsGenericDOMDataNode::InsertData(PRUint32 aOffset
,
394 const nsAString
& aData
)
396 return SetTextInternal(aOffset
, 0, aData
.BeginReading(),
397 aData
.Length(), PR_TRUE
);
401 nsGenericDOMDataNode::DeleteData(PRUint32 aOffset
, PRUint32 aCount
)
403 return SetTextInternal(aOffset
, aCount
, nsnull
, 0, PR_TRUE
);
407 nsGenericDOMDataNode::ReplaceData(PRUint32 aOffset
, PRUint32 aCount
,
408 const nsAString
& aData
)
410 return SetTextInternal(aOffset
, aCount
, aData
.BeginReading(),
411 aData
.Length(), PR_TRUE
);
415 nsGenericDOMDataNode::SetTextInternal(PRUint32 aOffset
, PRUint32 aCount
,
416 const PRUnichar
* aBuffer
,
417 PRUint32 aLength
, PRBool aNotify
)
419 NS_PRECONDITION(aBuffer
|| !aLength
,
420 "Null buffer passed to SetTextInternal!");
422 // sanitize arguments
423 PRUint32 textLength
= mText
.GetLength();
424 if (aOffset
> textLength
) {
425 return NS_ERROR_DOM_INDEX_SIZE_ERR
;
428 nsIDocument
*document
= GetCurrentDoc();
429 mozAutoDocUpdate
updateBatch(document
, UPDATE_CONTENT_MODEL
, aNotify
);
431 PRBool haveMutationListeners
= aNotify
&&
432 nsContentUtils::HasMutationListeners(this,
433 NS_EVENT_BITS_MUTATION_CHARACTERDATAMODIFIED
,
436 nsCOMPtr
<nsIAtom
> oldValue
;
437 if (haveMutationListeners
) {
438 oldValue
= GetCurrentValueAtom();
441 PRUint32 endOffset
= aOffset
+ aCount
;
442 if (endOffset
> textLength
) {
443 aCount
= textLength
- aOffset
;
444 endOffset
= textLength
;
448 CharacterDataChangeInfo info
= {
449 aOffset
== textLength
,
454 nsNodeUtils::CharacterDataWillChange(this, &info
);
457 if (aOffset
== 0 && endOffset
== textLength
) {
458 // Replacing whole text or old text was empty
459 mText
.SetTo(aBuffer
, aLength
);
461 else if (aOffset
== textLength
) {
462 // Appending to existing
463 mText
.Append(aBuffer
, aLength
);
466 // Merging old and new
468 // Allocate new buffer
469 PRInt32 newLength
= textLength
- aCount
+ aLength
;
470 PRUnichar
* to
= new PRUnichar
[newLength
];
471 NS_ENSURE_TRUE(to
, NS_ERROR_OUT_OF_MEMORY
);
473 // Copy over appropriate data
475 mText
.CopyTo(to
, 0, aOffset
);
478 memcpy(to
+ aOffset
, aBuffer
, aLength
* sizeof(PRUnichar
));
480 if (endOffset
!= textLength
) {
481 mText
.CopyTo(to
+ aOffset
+ aLength
, endOffset
, textLength
- endOffset
);
484 // XXX Add OOM checking to this
485 mText
.SetTo(to
, newLength
);
494 CharacterDataChangeInfo info
= {
495 aOffset
== textLength
,
500 nsNodeUtils::CharacterDataChanged(this, &info
);
502 if (haveMutationListeners
) {
503 mozAutoRemovableBlockerRemover blockerRemover
;
505 nsMutationEvent
mutation(PR_TRUE
, NS_MUTATION_CHARACTERDATAMODIFIED
);
507 mutation
.mPrevAttrValue
= oldValue
;
511 mutation
.mNewAttrValue
= do_GetAtom(val
);
514 mozAutoSubtreeModified
subtree(GetOwnerDoc(), this);
515 nsEventDispatcher::Dispatch(this, nsnull
, &mutation
);
522 //----------------------------------------------------------------------
524 // Implementation of nsIContent
528 nsGenericDOMDataNode::ToCString(nsAString
& aBuf
, PRInt32 aOffset
,
532 const PRUnichar
* cp
= mText
.Get2b() + aOffset
;
533 const PRUnichar
* end
= cp
+ aLen
;
536 PRUnichar ch
= *cp
++;
538 aBuf
.AppendLiteral("&");
539 } else if (ch
== '<') {
540 aBuf
.AppendLiteral("<");
541 } else if (ch
== '>') {
542 aBuf
.AppendLiteral(">");
543 } else if ((ch
< ' ') || (ch
>= 127)) {
545 PR_snprintf(buf
, sizeof(buf
), "\\u%04x", ch
);
546 AppendASCIItoUTF16(buf
, aBuf
);
552 unsigned char* cp
= (unsigned char*)mText
.Get1b() + aOffset
;
553 const unsigned char* end
= cp
+ aLen
;
556 PRUnichar ch
= *cp
++;
558 aBuf
.AppendLiteral("&");
559 } else if (ch
== '<') {
560 aBuf
.AppendLiteral("<");
561 } else if (ch
== '>') {
562 aBuf
.AppendLiteral(">");
563 } else if ((ch
< ' ') || (ch
>= 127)) {
565 PR_snprintf(buf
, sizeof(buf
), "\\u%04x", ch
);
566 AppendASCIItoUTF16(buf
, aBuf
);
577 nsGenericDOMDataNode::BindToTree(nsIDocument
* aDocument
, nsIContent
* aParent
,
578 nsIContent
* aBindingParent
,
579 PRBool aCompileEventHandlers
)
581 NS_PRECONDITION(aParent
|| aDocument
, "Must have document if no parent!");
582 NS_PRECONDITION(HasSameOwnerDoc(NODE_FROM(aParent
, aDocument
)),
583 "Must have the same owner document");
584 NS_PRECONDITION(!aParent
|| aDocument
== aParent
->GetCurrentDoc(),
585 "aDocument must be current doc of aParent");
586 NS_PRECONDITION(!GetCurrentDoc() && !IsInDoc(),
587 "Already have a document. Unbind first!");
588 // Note that as we recurse into the kids, they'll have a non-null parent. So
589 // only assert if our parent is _changing_ while we have a parent.
590 NS_PRECONDITION(!GetParent() || aParent
== GetParent(),
591 "Already have a parent. Unbind first!");
592 NS_PRECONDITION(!GetBindingParent() ||
593 aBindingParent
== GetBindingParent() ||
594 (!aBindingParent
&& aParent
&&
595 aParent
->GetBindingParent() == GetBindingParent()),
596 "Already have a binding parent. Unbind first!");
597 NS_PRECONDITION(aBindingParent
!= this,
598 "Content must not be its own binding parent");
599 NS_PRECONDITION(!IsRootOfNativeAnonymousSubtree() ||
600 aBindingParent
== aParent
,
601 "Native anonymous content must have its parent as its "
602 "own binding parent");
604 if (!aBindingParent
&& aParent
) {
605 aBindingParent
= aParent
->GetBindingParent();
608 // First set the binding parent
609 if (aBindingParent
) {
610 nsDataSlots
*slots
= GetDataSlots();
611 NS_ENSURE_TRUE(slots
, NS_ERROR_OUT_OF_MEMORY
);
613 NS_ASSERTION(IsRootOfNativeAnonymousSubtree() ||
614 !HasFlag(NODE_IS_IN_ANONYMOUS_SUBTREE
) ||
615 (aParent
&& aParent
->IsInNativeAnonymousSubtree()),
616 "Trying to re-bind content from native anonymous subtree to "
617 "non-native anonymous parent!");
618 slots
->mBindingParent
= aBindingParent
; // Weak, so no addref happens.
619 if (IsRootOfNativeAnonymousSubtree() ||
620 aParent
->IsInNativeAnonymousSubtree()) {
621 SetFlags(NODE_IS_IN_ANONYMOUS_SUBTREE
);
628 reinterpret_cast<PtrBits
>(aParent
) | PARENT_BIT_PARENT_IS_CONTENT
;
631 mParentPtrBits
= reinterpret_cast<PtrBits
>(aDocument
);
634 // XXXbz sXBL/XBL2 issue!
638 // XXX See the comment in nsGenericElement::BindToTree
639 mParentPtrBits
|= PARENT_BIT_INDOCUMENT
;
640 if (mText
.IsBidi()) {
641 aDocument
->SetBidiEnabled();
645 nsNodeUtils::ParentChainChanged(this);
647 UpdateEditableState();
649 NS_POSTCONDITION(aDocument
== GetCurrentDoc(), "Bound to wrong document");
650 NS_POSTCONDITION(aParent
== GetParent(), "Bound to wrong parent");
651 NS_POSTCONDITION(aBindingParent
== GetBindingParent(),
652 "Bound to wrong binding parent");
658 nsGenericDOMDataNode::UnbindFromTree(PRBool aDeep
, PRBool aNullParent
)
660 nsIDocument
*document
= GetCurrentDoc();
662 // Notify XBL- & nsIAnonymousContentCreator-generated
663 // anonymous content that the document is changing.
664 // This is needed to update the insertion point.
665 document
->BindingManager()->ChangeDocumentFor(this, document
, nsnull
);
668 mParentPtrBits
= aNullParent
? 0 : mParentPtrBits
& ~PARENT_BIT_INDOCUMENT
;
670 nsDataSlots
*slots
= GetExistingDataSlots();
672 slots
->mBindingParent
= nsnull
;
675 nsNodeUtils::ParentChainChanged(this);
679 nsGenericDOMDataNode::GetIDAttributeName() const
684 already_AddRefed
<nsINodeInfo
>
685 nsGenericDOMDataNode::GetExistingAttrNameFromQName(const nsAString
& aStr
) const
691 nsGenericDOMDataNode::SetAttr(PRInt32 aNameSpaceID
, nsIAtom
* aAttr
,
692 nsIAtom
* aPrefix
, const nsAString
& aValue
,
699 nsGenericDOMDataNode::UnsetAttr(PRInt32 aNameSpaceID
, nsIAtom
* aAttr
,
706 nsGenericDOMDataNode::GetAttr(PRInt32 aNameSpaceID
, nsIAtom
*aAttr
,
707 nsAString
& aResult
) const
715 nsGenericDOMDataNode::HasAttr(PRInt32 aNameSpaceID
, nsIAtom
*aAttribute
) const
721 nsGenericDOMDataNode::GetAttrNameAt(PRUint32 aIndex
) const
727 nsGenericDOMDataNode::GetAttrCount() const
733 nsGenericDOMDataNode::PreHandleEvent(nsEventChainPreVisitor
& aVisitor
)
735 return nsGenericElement::doPreHandleEvent(this, aVisitor
);
739 nsGenericDOMDataNode::PostHandleEvent(nsEventChainPostVisitor
& /*aVisitor*/)
745 nsGenericDOMDataNode::DispatchDOMEvent(nsEvent
* aEvent
,
746 nsIDOMEvent
* aDOMEvent
,
747 nsPresContext
* aPresContext
,
748 nsEventStatus
* aEventStatus
)
750 return nsEventDispatcher::DispatchDOMEvent(static_cast<nsINode
*>(this),
752 aPresContext
, aEventStatus
);
756 nsGenericDOMDataNode::GetListenerManager(PRBool aCreateIfNotFound
,
757 nsIEventListenerManager
** aResult
)
759 return nsContentUtils::GetListenerManager(this, aCreateIfNotFound
, aResult
);
763 nsGenericDOMDataNode::AddEventListenerByIID(nsIDOMEventListener
*aListener
,
766 nsCOMPtr
<nsIEventListenerManager
> elm
;
767 nsresult rv
= GetListenerManager(PR_TRUE
, getter_AddRefs(elm
));
769 return elm
->AddEventListenerByIID(aListener
, aIID
, NS_EVENT_FLAG_BUBBLE
);
775 nsGenericDOMDataNode::RemoveEventListenerByIID(nsIDOMEventListener
*aListener
,
778 nsCOMPtr
<nsIEventListenerManager
> elm
;
779 GetListenerManager(PR_FALSE
, getter_AddRefs(elm
));
781 return elm
->RemoveEventListenerByIID(aListener
, aIID
, NS_EVENT_FLAG_BUBBLE
);
787 nsGenericDOMDataNode::GetSystemEventGroup(nsIDOMEventGroup
** aGroup
)
789 nsCOMPtr
<nsIEventListenerManager
> elm
;
790 nsresult rv
= GetListenerManager(PR_TRUE
, getter_AddRefs(elm
));
792 return elm
->GetSystemEventGroupLM(aGroup
);
798 nsGenericDOMDataNode::GetChildCount() const
804 nsGenericDOMDataNode::GetChildAt(PRUint32 aIndex
) const
810 nsGenericDOMDataNode::GetChildArray(PRUint32
* aChildCount
) const
817 nsGenericDOMDataNode::IndexOf(nsINode
* aPossibleChild
) const
823 nsGenericDOMDataNode::InsertChildAt(nsIContent
* aKid
, PRUint32 aIndex
,
830 nsGenericDOMDataNode::RemoveChildAt(PRUint32 aIndex
, PRBool aNotify
)
837 nsGenericDOMDataNode::MayHaveFrame() const
839 nsIContent
* parent
= GetParent();
840 return parent
&& parent
->MayHaveFrame();
844 nsGenericDOMDataNode::GetBindingParent() const
846 nsDataSlots
*slots
= GetExistingDataSlots();
847 return slots
? slots
->mBindingParent
: nsnull
;
851 nsGenericDOMDataNode::IsNodeOfType(PRUint32 aFlags
) const
853 return !(aFlags
& ~(eCONTENT
| eDATA_NODE
));
857 nsGenericDOMDataNode::SaveSubtreeState()
862 nsGenericDOMDataNode::DestroyContent()
864 // XXX We really should let cycle collection do this, but that currently still
865 // leaks (see https://bugzilla.mozilla.org/show_bug.cgi?id=406684).
871 nsGenericDOMDataNode::List(FILE* out
, PRInt32 aIndent
) const
876 nsGenericDOMDataNode::DumpContent(FILE* out
, PRInt32 aIndent
,
877 PRBool aDumpAll
) const
882 already_AddRefed
<nsIURI
>
883 nsGenericDOMDataNode::GetBaseURI() const
885 // DOM Data Node inherits the base from its parent element/document
886 nsIContent
*parent
= GetParent();
888 return parent
->GetBaseURI();
892 nsIDocument
*doc
= GetOwnerDoc();
894 NS_IF_ADDREF(uri
= doc
->GetBaseURI());
904 nsGenericDOMDataNode::IsLink(nsIURI
** aURI
) const
911 nsGenericDOMDataNode::CreateSlots()
913 return new nsDataSlots(mFlagsOrSlots
);
916 //----------------------------------------------------------------------
918 // Implementation of the nsIDOMText interface
921 nsGenericDOMDataNode::SplitData(PRUint32 aOffset
, nsIContent
** aReturn
,
922 PRBool aCloneAfterOriginal
)
926 nsAutoString cutText
;
927 PRUint32 length
= TextLength();
929 if (aOffset
> length
) {
930 return NS_ERROR_DOM_INDEX_SIZE_ERR
;
933 PRUint32 cutStartOffset
= aCloneAfterOriginal
? aOffset
: 0;
934 PRUint32 cutLength
= aCloneAfterOriginal
? length
- aOffset
: aOffset
;
935 rv
= SubstringData(cutStartOffset
, cutLength
, cutText
);
940 rv
= DeleteData(cutStartOffset
, cutLength
);
946 * Use Clone for creating the new node so that the new node is of same class
950 nsCOMPtr
<nsIContent
> newContent
= CloneDataNode(mNodeInfo
, PR_FALSE
);
952 return NS_ERROR_OUT_OF_MEMORY
;
955 newContent
->SetText(cutText
, PR_TRUE
);
957 nsCOMPtr
<nsINode
> parent
= GetNodeParent();
960 PRInt32 insertionIndex
= parent
->IndexOf(this);
961 if (aCloneAfterOriginal
) {
964 parent
->InsertChildAt(newContent
, insertionIndex
, PR_TRUE
);
967 newContent
.swap(*aReturn
);
972 nsGenericDOMDataNode::SplitText(PRUint32 aOffset
, nsIDOMText
** aReturn
)
974 nsCOMPtr
<nsIContent
> newChild
;
975 nsresult rv
= SplitData(aOffset
, getter_AddRefs(newChild
));
976 if (NS_SUCCEEDED(rv
)) {
977 rv
= CallQueryInterface(newChild
, aReturn
);
982 //----------------------------------------------------------------------
984 // Implementation of the nsGenericDOMDataNode nsIDOM3Text tearoff
986 NS_IMPL_CYCLE_COLLECTION_CLASS(nsText3Tearoff
)
988 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsText3Tearoff
)
989 NS_INTERFACE_MAP_ENTRY(nsIDOM3Text
)
990 NS_INTERFACE_MAP_END_AGGREGATED(mNode
)
992 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsText3Tearoff
)
993 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mNode
)
994 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
996 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsText3Tearoff
)
997 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mNode
, nsIContent
)
998 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
1000 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsText3Tearoff
)
1001 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsText3Tearoff
)
1004 nsText3Tearoff::GetIsElementContentWhitespace(PRBool
*aReturn
)
1006 *aReturn
= mNode
->TextIsOnlyWhitespace();
1011 nsText3Tearoff::GetWholeText(nsAString
& aWholeText
)
1013 return mNode
->GetWholeText(aWholeText
);
1017 nsText3Tearoff::ReplaceWholeText(const nsAString
& aContent
,
1018 nsIDOMText
**aReturn
)
1020 return mNode
->ReplaceWholeText(PromiseFlatString(aContent
), aReturn
);
1023 // Implementation of the nsIDOM3Text interface
1025 /* static */ PRInt32
1026 nsGenericDOMDataNode::FirstLogicallyAdjacentTextNode(nsIContent
* aParent
,
1029 while (aIndex
-- > 0) {
1030 nsIContent
* sibling
= aParent
->GetChildAt(aIndex
);
1031 if (!sibling
->IsNodeOfType(nsINode::eTEXT
))
1037 /* static */ PRInt32
1038 nsGenericDOMDataNode::LastLogicallyAdjacentTextNode(nsIContent
* aParent
,
1042 while (++aIndex
< PRInt32(aCount
)) {
1043 nsIContent
* sibling
= aParent
->GetChildAt(aIndex
);
1044 if (!sibling
->IsNodeOfType(nsINode::eTEXT
))
1051 nsGenericDOMDataNode::GetWholeText(nsAString
& aWholeText
)
1053 nsIContent
* parent
= GetParent();
1055 // Handle parent-less nodes
1057 return GetData(aWholeText
);
1059 PRInt32 index
= parent
->IndexOf(this);
1060 NS_WARN_IF_FALSE(index
>= 0,
1061 "Trying to use .wholeText with an anonymous"
1062 "text node child of a binding parent?");
1063 NS_ENSURE_TRUE(index
>= 0, NS_ERROR_DOM_NOT_SUPPORTED_ERR
);
1065 FirstLogicallyAdjacentTextNode(parent
, index
);
1067 LastLogicallyAdjacentTextNode(parent
, index
, parent
->GetChildCount());
1069 aWholeText
.Truncate();
1071 nsCOMPtr
<nsIDOMText
> node
;
1074 node
= do_QueryInterface(parent
->GetChildAt(first
));
1076 aWholeText
.Append(tmp
);
1077 } while (first
++ < last
);
1083 nsGenericDOMDataNode::ReplaceWholeText(const nsAFlatString
& aContent
,
1084 nsIDOMText
**aReturn
)
1086 // Batch possible DOMSubtreeModified events.
1087 mozAutoSubtreeModified
subtree(GetOwnerDoc(), nsnull
);
1088 mozAutoDocUpdate
updateBatch(GetCurrentDoc(), UPDATE_CONTENT_MODEL
, PR_TRUE
);
1090 nsCOMPtr
<nsIContent
> parent
= GetParent();
1092 // Handle parent-less nodes
1094 if (aContent
.IsEmpty()) {
1099 SetText(aContent
.get(), aContent
.Length(), PR_TRUE
);
1100 return CallQueryInterface(this, aReturn
);
1103 PRInt32 index
= parent
->IndexOf(this);
1104 NS_WARN_IF_FALSE(index
>= 0,
1105 "Trying to use .replaceWholeText with an anonymous"
1106 "text node child of a binding parent?");
1107 NS_ENSURE_TRUE(index
>= 0, NS_ERROR_DOM_NOT_SUPPORTED_ERR
);
1109 // We don't support entity references or read-only nodes, so remove the
1110 // logically adjacent text nodes (which therefore must all be siblings of
1111 // this) and set this one to the provided text, if that text isn't empty.
1113 FirstLogicallyAdjacentTextNode(parent
, index
);
1115 LastLogicallyAdjacentTextNode(parent
, index
, parent
->GetChildCount());
1118 if (last
== index
&& !aContent
.IsEmpty())
1121 parent
->RemoveChildAt(last
, PR_TRUE
);
1122 } while (last
-- > first
);
1124 // Empty string means we removed this node too.
1125 if (aContent
.IsEmpty()) {
1130 SetText(aContent
.get(), aContent
.Length(), PR_TRUE
);
1131 return CallQueryInterface(this, aReturn
);
1134 //----------------------------------------------------------------------
1136 // Implementation of the nsIContent interface text functions
1138 const nsTextFragment
*
1139 nsGenericDOMDataNode::GetText()
1145 nsGenericDOMDataNode::TextLength()
1147 return mText
.GetLength();
1151 nsGenericDOMDataNode::SetText(const PRUnichar
* aBuffer
,
1155 return SetTextInternal(0, mText
.GetLength(), aBuffer
, aLength
, aNotify
);
1159 nsGenericDOMDataNode::AppendText(const PRUnichar
* aBuffer
,
1163 return SetTextInternal(mText
.GetLength(), 0, aBuffer
, aLength
, aNotify
);
1167 nsGenericDOMDataNode::TextIsOnlyWhitespace()
1170 // The fragment contains non-8bit characters and such characters
1171 // are never considered whitespace.
1175 const char* cp
= mText
.Get1b();
1176 const char* end
= cp
+ mText
.GetLength();
1181 if (!XP_IS_SPACE(ch
)) {
1192 nsGenericDOMDataNode::AppendTextTo(nsAString
& aResult
)
1194 mText
.AppendTo(aResult
);
1197 void nsGenericDOMDataNode::SetBidiStatus()
1199 nsIDocument
*document
= GetCurrentDoc();
1200 if (document
&& document
->GetBidiEnabled()) {
1201 // OK, we already know it's Bidi, so we won't test again
1205 mText
.SetBidiFlag();
1207 if (document
&& mText
.IsBidi()) {
1208 document
->SetBidiEnabled();
1212 already_AddRefed
<nsIAtom
>
1213 nsGenericDOMDataNode::GetCurrentValueAtom()
1217 return NS_NewAtom(val
);
1221 nsGenericDOMDataNode::GetID() const
1227 nsGenericDOMDataNode::DoGetClasses() const
1229 NS_NOTREACHED("Shouldn't ever be called");
1234 nsGenericDOMDataNode::WalkContentStyleRules(nsRuleWalker
* aRuleWalker
)
1240 nsGenericDOMDataNode::GetInlineStyleRule()
1246 nsGenericDOMDataNode::SetInlineStyleRule(nsICSSStyleRule
* aStyleRule
,
1249 NS_NOTREACHED("How come we're setting inline style on a non-element?");
1250 return NS_ERROR_UNEXPECTED
;
1253 NS_IMETHODIMP_(PRBool
)
1254 nsGenericDOMDataNode::IsAttributeMapped(const nsIAtom
* aAttribute
) const
1260 nsGenericDOMDataNode::GetAttributeChangeHint(const nsIAtom
* aAttribute
,
1261 PRInt32 aModType
) const
1263 NS_NOTREACHED("Shouldn't be calling this!");
1264 return nsChangeHint(0);
1268 nsGenericDOMDataNode::GetClassAttributeName() const