diff --git a/mozilla/accessible/src/base/nsDocAccessible.cpp b/mozilla/accessible/src/base/nsDocAccessible.cpp index 9d3743922ac..ec5f473da29 100644 --- a/mozilla/accessible/src/base/nsDocAccessible.cpp +++ b/mozilla/accessible/src/base/nsDocAccessible.cpp @@ -967,7 +967,7 @@ void nsDocAccessible::ContentStatesChanged(nsIDocument* aDocument, void nsDocAccessible::CharacterDataChanged(nsIDocument *aDocument, nsIContent* aContent, - PRBool aAppend) + CharacterDataChangeInfo* aInfo) { InvalidateCacheSubtree(aContent, nsIAccessibleEvent::EVENT_REORDER); } diff --git a/mozilla/content/base/public/nsContentUtils.h b/mozilla/content/base/public/nsContentUtils.h index ddb6f6f5ca1..554cfbc1251 100644 --- a/mozilla/content/base/public/nsContentUtils.h +++ b/mozilla/content/base/public/nsContentUtils.h @@ -88,7 +88,6 @@ class nsIScriptGlobalObject; template class nsCOMArray; class nsIPref; class nsVoidArray; -class nsIRange; struct JSRuntime; #ifdef MOZ_XTF class nsIXTFService; @@ -782,43 +781,6 @@ public: PRBool aCancelable, PRBool *aDefaultAction = nsnull); - /** - * Add aRange to the list of ranges with a start- or endpoint containing - * aNode. aCreated will be set to PR_TRUE if this call created a new list - * (meaning the list was empty before the call to AddToRangeList). - * - * @param aNode The node contained in the start- or endpoint of aRange. - * @param aRange The range containing aNode in its start- or endpoint. - * @param aCreated [out] Set to PR_TRUE if a new list was created. - */ - static nsresult AddToRangeList(nsINode *aNode, nsIRange *aRange, - PRBool *aCreated); - - /** - * Remove aRange from the list of ranges with a start- or endpoint containing - * aNode. This will return PR_TRUE if aRange was the last range in the list. - * - * @param aNode The node for which to remove aRange. - * @param aRange The range to remove. - * @return PR_TRUE if aRange was the last range in the list. - */ - static PRBool RemoveFromRangeList(nsINode *aNode, nsIRange *aRange); - - /** - * Look up the list of ranges containing aNode. - * - * @param aNode The node for which to look up the range list. - * @return The range list if one exists. - */ - static const nsVoidArray* LookupRangeList(const nsINode *aNode); - - /** - * Remove the list of ranges containing aNode as their start- or endpoint. - * - * @param aNode The node for which to remove the range list. - */ - static void RemoveRangeList(nsINode *aNode); - /** * Get the eventlistener manager for aNode. If a new eventlistener manager * was created, aCreated is set to PR_TRUE. diff --git a/mozilla/content/base/public/nsIMutationObserver.h b/mozilla/content/base/public/nsIMutationObserver.h index 10f422a38cb..d5b2d03e46c 100755 --- a/mozilla/content/base/public/nsIMutationObserver.h +++ b/mozilla/content/base/public/nsIMutationObserver.h @@ -48,6 +48,17 @@ class nsINode; { 0x0864a23d, 0x824b, 0x48be, \ { 0x9d, 0x50, 0xff, 0x30, 0x2f, 0xf2, 0x79, 0xfe } } +/** + * Information details about a characterdata change + */ +struct CharacterDataChangeInfo +{ + PRBool mAppend; + PRUint32 mChangeStart; + PRUint32 mChangeEnd; + PRUint32 mReplaceLength; +}; + // Mutation observer interface class nsIMutationObserver : public nsISupports { @@ -68,7 +79,7 @@ public: */ virtual void CharacterDataChanged(nsIDocument *aDocument, nsIContent* aContent, - PRBool aAppend) = 0; + CharacterDataChangeInfo* aInfo) = 0; /** * Notification that an attribute of an element has changed. @@ -159,7 +170,7 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIMutationObserver, NS_IMUTATION_OBSERVER_IID) #define NS_DECL_NSIMUTATIONOBSERVER \ virtual void CharacterDataChanged(nsIDocument* aDocument, \ nsIContent* aContent, \ - PRBool aAppend); \ + CharacterDataChangeInfo* aInfo); \ virtual void AttributeChanged(nsIDocument* aDocument, \ nsIContent* aContent, \ PRInt32 aNameSpaceID, \ @@ -189,7 +200,7 @@ _class::NodeWillBeDestroyed(const nsINode* aNode) void \ _class::CharacterDataChanged(nsIDocument* aDocument, \ nsIContent* aContent, \ - PRBool aAppend) \ + CharacterDataChangeInfo* aInfo) \ { \ } \ void \ diff --git a/mozilla/content/base/public/nsINode.h b/mozilla/content/base/public/nsINode.h index b3193760260..91f3322631b 100644 --- a/mozilla/content/base/public/nsINode.h +++ b/mozilla/content/base/public/nsINode.h @@ -55,38 +55,34 @@ class nsIEventListenerManager; class nsIPrincipal; class nsVoidArray; class nsIMutationObserver; -class nsIRange; // This bit will be set if the node doesn't have nsSlots #define NODE_DOESNT_HAVE_SLOTS 0x00000001U -// This bit will be set if the node has a range list in the range list hash -#define NODE_HAS_RANGELIST 0x00000002U - // This bit will be set if the node has a listener manager in the listener // manager hash -#define NODE_HAS_LISTENERMANAGER 0x00000004U +#define NODE_HAS_LISTENERMANAGER 0x00000002U // Whether this node has had any properties set on it -#define NODE_HAS_PROPERTIES 0x00000008U +#define NODE_HAS_PROPERTIES 0x00000004U // Whether this node is anonymous // NOTE: Should only be used on nsIContent nodes -#define NODE_IS_ANONYMOUS 0x00000010U +#define NODE_IS_ANONYMOUS 0x00000008U // Whether this node is anonymous for events // NOTE: Should only be used on nsIContent nodes -#define NODE_IS_ANONYMOUS_FOR_EVENTS 0x00000020U +#define NODE_IS_ANONYMOUS_FOR_EVENTS 0x00000010U // Whether this node may have a frame // NOTE: Should only be used on nsIContent nodes -#define NODE_MAY_HAVE_FRAME 0x00000040U +#define NODE_MAY_HAVE_FRAME 0x00000020U // Four bits for the script-type ID -#define NODE_SCRIPT_TYPE_OFFSET 7 +#define NODE_SCRIPT_TYPE_OFFSET 6 // Remaining bits are node type specific. -#define NODE_TYPE_SPECIFIC_BITS_OFFSET 0x0b +#define NODE_TYPE_SPECIFIC_BITS_OFFSET 0x0a // Useful macro for getting a node given an nsIContent and an nsIDocument // Returns the first argument cast to nsINode if it is non-null, otherwise @@ -434,35 +430,6 @@ public: return HasFlag(NODE_HAS_PROPERTIES); } - /** - * Inform node of range ownership changes. This allows the node to do the - * right thing to ranges in the face of changes to the content model. - * - * RangeRemove -- informs content that it no longer owns a range endpoint - * GetRangeList -- returns the list of ranges that have one or both endpoints - * within this content item - */ - /** - * Inform node that it owns one or both range endpoints - * @param aRange the range the node owns - */ - virtual nsresult RangeAdd(nsIRange* aRange); - - /** - * Inform node that it no longer owns either range endpoint - * @param aRange the range the node no longer owns - */ - virtual void RangeRemove(nsIRange* aRange); - - /** - * Get the list of ranges that have either endpoint in this node - * item. - * @return the list of ranges owned partially by this node. The - * nsVoidArray is owned by the node object and its lifetime is - * controlled completely by the node object. - */ - virtual const nsVoidArray *GetRangeList() const; - /** * Return the principal of this node. This is guaranteed to never be a null * pointer. diff --git a/mozilla/content/base/src/nsContentUtils.cpp b/mozilla/content/base/src/nsContentUtils.cpp index 337210432cf..d05d5437134 100644 --- a/mozilla/content/base/src/nsContentUtils.cpp +++ b/mozilla/content/base/src/nsContentUtils.cpp @@ -186,33 +186,8 @@ nsIBidiKeyboard *nsContentUtils::sBidiKeyboard = nsnull; PRBool nsContentUtils::sInitialized = PR_FALSE; -static PLDHashTable sRangeListsHash; static PLDHashTable sEventListenerManagersHash; -class RangeListMapEntry : public PLDHashEntryHdr -{ -public: - RangeListMapEntry(const void *aKey) - : mKey(aKey), mRangeList(nsnull) - { - } - - ~RangeListMapEntry() - { - delete mRangeList; - } - -private: - const void *mKey; // must be first to look like PLDHashEntryStub - -public: - // We want mRangeList to be an nsAutoVoidArray but we can't make an - // nsAutoVoidArray a direct member of RangeListMapEntry since it - // will be moved around in memory, and nsAutoVoidArray can't deal - // with that. - nsVoidArray *mRangeList; -}; - class EventListenerManagerMapEntry : public PLDHashEntryHdr { public: @@ -233,24 +208,6 @@ public: nsCOMPtr mListenerManager; }; -PR_STATIC_CALLBACK(PRBool) -RangeListHashInitEntry(PLDHashTable *table, PLDHashEntryHdr *entry, - const void *key) -{ - // Initialize the entry with placement new - new (entry) RangeListMapEntry(key); - return PR_TRUE; -} - -PR_STATIC_CALLBACK(void) -RangeListHashClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry) -{ - RangeListMapEntry *r = NS_STATIC_CAST(RangeListMapEntry *, entry); - - // Let the RangeListMapEntry clean itself up... - r->~RangeListMapEntry(); -} - PR_STATIC_CALLBACK(PRBool) EventListenerManagerHashInitEntry(PLDHashTable *table, PLDHashEntryHdr *entry, const void *key) @@ -330,28 +287,6 @@ nsContentUtils::Init() return NS_ERROR_OUT_OF_MEMORY; } - if (!sRangeListsHash.ops) { - static PLDHashTableOps hash_table_ops = - { - PL_DHashAllocTable, - PL_DHashFreeTable, - PL_DHashGetKeyStub, - PL_DHashVoidPtrKeyStub, - PL_DHashMatchEntryStub, - PL_DHashMoveEntryStub, - RangeListHashClearEntry, - PL_DHashFinalizeStub, - RangeListHashInitEntry - }; - - if (!PL_DHashTableInit(&sRangeListsHash, &hash_table_ops, nsnull, - sizeof(RangeListMapEntry), 16)) { - sRangeListsHash.ops = nsnull; - - return NS_ERROR_OUT_OF_MEMORY; - } - } - if (!sEventListenerManagersHash.ops) { static PLDHashTableOps hash_table_ops = { @@ -370,9 +305,6 @@ nsContentUtils::Init() nsnull, sizeof(EventListenerManagerMapEntry), 16)) { sEventListenerManagersHash.ops = nsnull; - PL_DHashTableFinish(&sRangeListsHash); - sRangeListsHash.ops = nsnull; - return NS_ERROR_OUT_OF_MEMORY; } } @@ -644,33 +576,6 @@ nsContentUtils::Shutdown() sPtrsToPtrsToRelease = nsnull; } - if (sRangeListsHash.ops) { - NS_ASSERTION(sRangeListsHash.entryCount == 0, - "Range list hash not empty at shutdown!"); - - // We're already being shut down and if there are entries left in - // this hash at this point it means we leaked nsGenericElements or - // nsGenericDOMDataNodes. Since we're already partly through the - // shutdown process it's too late to release what's held on to by - // this hash (since the teardown code relies on some things being - // around that aren't around any more) so we rather leak what's - // already leaked in stead of crashing trying to release what - // should've been released much earlier on. - - // Copy the ops out of the hash table - PLDHashTableOps hash_table_ops = *sRangeListsHash.ops; - - // Set the clearEntry hook to be a nop - hash_table_ops.clearEntry = NopClearEntry; - - // Set the ops in the hash table to be the new ops - sRangeListsHash.ops = &hash_table_ops; - - PL_DHashTableFinish(&sRangeListsHash); - - sRangeListsHash.ops = nsnull; - } - if (sEventListenerManagersHash.ops) { NS_ASSERTION(sEventListenerManagersHash.entryCount == 0, "Event listener manager hash not empty at shutdown!"); @@ -3099,127 +3004,6 @@ nsContentUtils::RemoveListenerManager(nsINode *aNode) } } -/* static */ -nsresult -nsContentUtils::AddToRangeList(nsINode *aNode, nsIRange *aRange, - PRBool *aCreated) -{ - *aCreated = PR_FALSE; - - if (!sRangeListsHash.ops) { - // We've already been shut down, don't bother adding a range... - - return NS_OK; - } - - RangeListMapEntry *entry = - NS_STATIC_CAST(RangeListMapEntry *, - PL_DHashTableOperate(&sRangeListsHash, aNode, - PL_DHASH_ADD)); - - if (!entry) { - return NS_ERROR_OUT_OF_MEMORY; - } - - // lazy allocation of range list - if (!entry->mRangeList) { - entry->mRangeList = new nsAutoVoidArray(); - - if (!entry->mRangeList) { - PL_DHashTableRawRemove(&sRangeListsHash, entry); - - return NS_ERROR_OUT_OF_MEMORY; - } - - *aCreated = PR_TRUE; - } - else { - // Make sure we don't add a range that is already in the list! - PRInt32 i = entry->mRangeList->IndexOf(aRange); - - if (i >= 0) { - // Range is already in the list, so there is nothing to do! - - return NS_OK; - } - } - - // dont need to addref - this call is made by the range object - // itself - PRBool rv = entry->mRangeList->AppendElement(aRange); - if (!rv) { - if (entry->mRangeList->Count() == 0) { - // Fresh entry, remove it from the hash... - - PL_DHashTableRawRemove(&sRangeListsHash, entry); - } - - return NS_ERROR_OUT_OF_MEMORY; - } - - return NS_OK; -} - -/* static */ -PRBool -nsContentUtils::RemoveFromRangeList(nsINode *aNode, nsIRange *aRange) -{ - if (!sRangeListsHash.ops) { - // We've already been shut down, don't bother removing a range... - - return PR_FALSE; - } - - RangeListMapEntry *entry = - NS_STATIC_CAST(RangeListMapEntry *, - PL_DHashTableOperate(&sRangeListsHash, aNode, - PL_DHASH_LOOKUP)); - - if (PL_DHASH_ENTRY_IS_FREE(entry)) { - return PR_FALSE; - } - - NS_ASSERTION(entry->mRangeList, "In the hash but without an object?"); - - // dont need to release - this call is made by the range object itself - entry->mRangeList->RemoveElement(aRange); - - if (entry->mRangeList->Count() != 0) { - return PR_FALSE; - } - - PL_DHashTableRawRemove(&sRangeListsHash, entry); - - return PR_TRUE; -} - -/* static */ -const nsVoidArray* -nsContentUtils::LookupRangeList(const nsINode *aNode) -{ - if (!sRangeListsHash.ops) { - // We've already been shut down, don't bother getting a range list... - - return nsnull; - } - - RangeListMapEntry *entry = - NS_STATIC_CAST(RangeListMapEntry *, - PL_DHashTableOperate(&sRangeListsHash, aNode, - PL_DHASH_LOOKUP)); - - return PL_DHASH_ENTRY_IS_BUSY(entry) ? entry->mRangeList : nsnull; -} - -/* static */ -void -nsContentUtils::RemoveRangeList(nsINode *aNode) -{ - if (sRangeListsHash.ops) { - PL_DHashTableOperate(&sRangeListsHash, aNode, PL_DHASH_REMOVE); - } -} - /* static */ PRBool nsContentUtils::IsValidNodeName(nsIAtom *aLocalName, nsIAtom *aPrefix, diff --git a/mozilla/content/base/src/nsGenericDOMDataNode.cpp b/mozilla/content/base/src/nsGenericDOMDataNode.cpp index 76f330df44c..e68279812bd 100644 --- a/mozilla/content/base/src/nsGenericDOMDataNode.cpp +++ b/mozilla/content/base/src/nsGenericDOMDataNode.cpp @@ -460,12 +460,6 @@ nsGenericDOMDataNode::SetTextInternal(PRUint32 aOffset, PRUint32 aCount, SetBidiStatus(); - // inform any enclosed ranges of change - const nsVoidArray *rangeList = GetRangeList(); - if (rangeList) { - nsRange::TextOwnerChanged(this, rangeList, aOffset, endOffset, aLength); - } - // Notify observers if (aNotify) { if (haveMutationListeners) { @@ -481,7 +475,13 @@ nsGenericDOMDataNode::SetTextInternal(PRUint32 aOffset, PRUint32 aCount, nsEventDispatcher::Dispatch(this, nsnull, &mutation); } - nsNodeUtils::CharacterDataChanged(this, aOffset == textLength); + CharacterDataChangeInfo info = { + aOffset == textLength, + aOffset, + endOffset, + aLength + }; + nsNodeUtils::CharacterDataChanged(this, &info); } return NS_OK; diff --git a/mozilla/content/base/src/nsGenericElement.cpp b/mozilla/content/base/src/nsGenericElement.cpp index 0af87ba540d..a9e2f21b23e 100644 --- a/mozilla/content/base/src/nsGenericElement.cpp +++ b/mozilla/content/base/src/nsGenericElement.cpp @@ -50,11 +50,9 @@ #include "nsIDocument.h" #include "nsIDOMNodeList.h" #include "nsIDOMDocument.h" -#include "nsIDOMRange.h" #include "nsIDOMText.h" #include "nsIDOMEventReceiver.h" #include "nsIContentIterator.h" -#include "nsRange.h" #include "nsIEventListenerManager.h" #include "nsILinkHandler.h" #include "nsIScriptGlobalObject.h" @@ -199,48 +197,6 @@ nsINode::UnsetProperty(PRUint16 aCategory, nsIAtom *aPropertyName, aStatus); } -nsresult -nsINode::RangeAdd(nsIRange* aRange) -{ - PRBool created; - nsresult rv = nsContentUtils::AddToRangeList(this, aRange, &created); - if (NS_SUCCEEDED(rv) && created) { - NS_ASSERTION(!HasFlag(NODE_HAS_RANGELIST), - "Huh, nsGenericElement flags don't reflect reality!!!"); - SetFlags(NODE_HAS_RANGELIST); - } - return rv; -} - -void -nsINode::RangeRemove(nsIRange* aRange) -{ - if (!HasFlag(NODE_HAS_RANGELIST)) { - return; - } - - PRBool removed = nsContentUtils::RemoveFromRangeList(this, aRange); - if (removed) { - UnsetFlags(NODE_HAS_RANGELIST); - } -} - -const nsVoidArray * -nsINode::GetRangeList() const -{ - if (!HasFlag(NODE_HAS_RANGELIST)) { - return nsnull; - } - - const nsVoidArray* rangeList = nsContentUtils::LookupRangeList(this); - - NS_ASSERTION(rangeList || !nsContentUtils::IsInitialized(), - "Huh, our bit says we have a range list, but there's nothing " - "in the hash!?!!"); - - return rangeList; -} - NS_IMETHODIMP nsINode::GetListenerManager(PRBool aCreateIfNotFound, nsIEventListenerManager** aResult) @@ -2319,11 +2275,6 @@ nsGenericElement::doInsertChildAt(nsIContent* aKid, PRUint32 aIndex, return rv; } - // Adjust ranges, but only if we're not appending to the end of the list - if (aParent && !isAppend) { - nsRange::OwnerChildInserted(aParent, aIndex); - } - // The kid may have removed its parent from the document, so recheck that // that's still in the document before proceeding. Also, the kid may have // just removed itself, in which case we don't really want to fire @@ -2407,10 +2358,6 @@ nsGenericElement::doRemoveChildAt(PRUint32 aIndex, PRBool aNotify, } } - if (aParent) { - nsRange::OwnerChildRemoved(aParent, aIndex, aKid); - } - aChildArray.RemoveChildAt(aIndex); if (aNotify) { diff --git a/mozilla/content/base/src/nsNodeUtils.cpp b/mozilla/content/base/src/nsNodeUtils.cpp index 0b5ed199ed3..f2fb7d0dda2 100755 --- a/mozilla/content/base/src/nsNodeUtils.cpp +++ b/mozilla/content/base/src/nsNodeUtils.cpp @@ -79,11 +79,12 @@ void -nsNodeUtils::CharacterDataChanged(nsIContent* aContent, PRBool aAppend) +nsNodeUtils::CharacterDataChanged(nsIContent* aContent, + CharacterDataChangeInfo* aInfo) { nsIDocument* doc = aContent->GetOwnerDoc(); IMPL_MUTATION_NOTIFICATION(CharacterDataChanged, aContent, - (doc, aContent, aAppend)); + (doc, aContent, aInfo)); } void @@ -183,19 +184,6 @@ nsNodeUtils::LastRelease(nsINode* aNode, PRBool aDelete) aNode->UnsetFlags(NODE_HAS_PROPERTIES); } - if (aNode->HasFlag(NODE_HAS_RANGELIST)) { -#ifdef DEBUG - if (!nsContentUtils::LookupRangeList(aNode) && - nsContentUtils::IsInitialized()) { - NS_ERROR("Huh, our bit says we have a range list, but there's nothing " - "in the hash!?!!"); - } -#endif - - nsContentUtils::RemoveRangeList(aNode); - aNode->UnsetFlags(NODE_HAS_RANGELIST); - } - if (aNode->HasFlag(NODE_HAS_LISTENERMANAGER)) { #ifdef DEBUG if (nsContentUtils::IsInitialized()) { diff --git a/mozilla/content/base/src/nsNodeUtils.h b/mozilla/content/base/src/nsNodeUtils.h index fa44b5aa3fc..2d53a4301f4 100755 --- a/mozilla/content/base/src/nsNodeUtils.h +++ b/mozilla/content/base/src/nsNodeUtils.h @@ -46,6 +46,7 @@ struct JSObject; class nsINode; class nsNodeInfoManager; template class nsCOMArray; +struct CharacterDataChangeInfo; class nsNodeUtils { @@ -53,10 +54,11 @@ public: /** * Send CharacterDataChanged notifications to nsIMutationObservers. * @param aContent Node whose data changed - * @param aAppend True if data was only appended + * @param aInfo Struct with information details about the change * @see nsIMutationObserver::CharacterDataChanged */ - static void CharacterDataChanged(nsIContent* aContent, PRBool aAppend); + static void CharacterDataChanged(nsIContent* aContent, + CharacterDataChangeInfo* aInfo); /** * Send AttributeChanged notifications to nsIMutationObservers. diff --git a/mozilla/content/base/src/nsRange.cpp b/mozilla/content/base/src/nsRange.cpp index dcf67c13236..30f5b2c3e93 100644 --- a/mozilla/content/base/src/nsRange.cpp +++ b/mozilla/content/base/src/nsRange.cpp @@ -54,7 +54,7 @@ #include "nsDOMError.h" #include "nsIContentIterator.h" #include "nsIDOMNodeList.h" - +#include "nsGkAtoms.h" #include "nsContentUtils.h" nsresult NS_NewContentIterator(nsIContentIterator** aInstancePtrResult); @@ -79,8 +79,6 @@ nsresult NS_NewContentSubtreeIterator(nsIContentIterator** aInstancePtrResult); } \ PR_END_MACRO -static nsresult ContentOwnsRange(nsIRange* aRange, nsINode* aNode); - // Utility routine to detect if a content node is completely contained in a range // If outNodeBefore is returned true, then the node starts before the range does. // If outNodeAfter is returned true, then the node ends after the range does. @@ -212,7 +210,7 @@ NS_NewRange(nsIDOMRange** aResult) nsRange::~nsRange() { - DoSetRange(nsnull, 0, nsnull, 0); + DoSetRange(nsnull, 0, nsnull, 0, nsnull); // we want the side effects (releases and list removals) } @@ -225,6 +223,7 @@ NS_INTERFACE_MAP_BEGIN(nsRange) NS_INTERFACE_MAP_ENTRY(nsIDOMRange) NS_INTERFACE_MAP_ENTRY(nsIRange) NS_INTERFACE_MAP_ENTRY(nsIDOMNSRange) + NS_INTERFACE_MAP_ENTRY(nsIMutationObserver) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRange) NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(Range) NS_INTERFACE_MAP_END @@ -232,7 +231,97 @@ NS_INTERFACE_MAP_END NS_IMPL_ADDREF(nsRange) NS_IMPL_RELEASE(nsRange) -PRBool InSameDoc(nsINode* aNode1, nsINode* aNode2); +/****************************************************** + * nsIMutationObserver implementation + ******************************************************/ + +void +nsRange::CharacterDataChanged(nsIDocument* aDocument, + nsIContent* aContent, + CharacterDataChangeInfo* aInfo) +{ + NS_ASSERTION(mIsPositioned, "shouldn't be notified if not positioned"); + + // If the changed node contains our start boundry and the change starts + // before the boundry we'll need to adjust the offset. + if (aContent == mStartParent && + aInfo->mChangeStart < (PRUint32)mStartOffset) { + // If boundry is inside changed text, position it before change + // else adjust start offset for the change in length + mStartOffset = (PRUint32)mStartOffset < aInfo->mChangeEnd ? + aInfo->mChangeStart : + mStartOffset + aInfo->mChangeStart - aInfo->mChangeEnd + + aInfo->mReplaceLength; + } + + // Do same thing for end boundry. + if (aContent == mEndParent && aInfo->mChangeStart < (PRUint32)mEndOffset) { + mEndOffset = (PRUint32)mEndOffset < aInfo->mChangeEnd ? + aInfo->mChangeStart : + mEndOffset + aInfo->mChangeStart - aInfo->mChangeEnd + + aInfo->mReplaceLength; + } +} + +void +nsRange::ContentInserted(nsIDocument* aDocument, + nsIContent* aContainer, + nsIContent* aChild, + PRInt32 aIndexInContainer) +{ + NS_ASSERTION(mIsPositioned, "shouldn't be notified if not positioned"); + + nsINode* container = NODE_FROM(aContainer, aDocument); + + // Adjust position if a sibling was inserted. + if (container == mStartParent && aIndexInContainer < mStartOffset) { + ++mStartOffset; + } + if (container == mEndParent && aIndexInContainer < mEndOffset) { + ++mEndOffset; + } +} + +void +nsRange::ContentRemoved(nsIDocument* aDocument, + nsIContent* aContainer, + nsIContent* aChild, + PRInt32 aIndexInContainer) +{ + NS_ASSERTION(mIsPositioned, "shouldn't be notified if not positioned"); + + nsINode* container = NODE_FROM(aContainer, aDocument); + + // Adjust position if a sibling was removed... + if (container == mStartParent && aIndexInContainer < mStartOffset) { + --mStartOffset; + } + // ...or gravitate if an ancestor was removed. + else if (nsContentUtils::ContentIsDescendantOf(mStartParent, aChild)) { + mStartParent = container; + mStartOffset = aIndexInContainer; + } + + // Do same thing for end boundry. + if (container == mEndParent && aIndexInContainer < mEndOffset) { + --mEndOffset; + } + else if (nsContentUtils::ContentIsDescendantOf(mEndParent, aChild)) { + mEndParent = container; + mEndOffset = aIndexInContainer; + } +} + +void +nsRange::NodeWillBeDestroyed(const nsINode* aNode) +{ + NS_ASSERTION(mIsPositioned, "shouldn't be notified if not positioned"); + + // No need to detach, but reset positions so that the endpoints don't + // end up disconnected from each other. + // An alternative solution would be to make mRoot a strong pointer. + DoSetRange(nsnull, 0, nsnull, 0, nsnull); +} /******************************************************** * Utilities for comparing points: API from nsIDOMNSRange @@ -262,7 +351,7 @@ nsRange::ComparePoint(nsIDOMNode* aParent, PRInt32 aOffset, PRInt16* aResult) nsCOMPtr parent = do_QueryInterface(aParent); NS_ENSURE_TRUE(parent, NS_ERROR_DOM_HIERARCHY_REQUEST_ERR); - if (!InSameDoc(parent, mStartParent)) { + if (!nsContentUtils::ContentIsDescendantOf(parent, mRoot)) { return NS_ERROR_DOM_WRONG_DOCUMENT_ERR; } @@ -304,46 +393,38 @@ static PRInt32 GetNodeLength(nsINode *aNode) // the range to have both endpoints point to the other node void nsRange::DoSetRange(nsINode* aStartN, PRInt32 aStartOffset, - nsINode* aEndN, PRInt32 aEndOffset) + nsINode* aEndN, PRInt32 aEndOffset, + nsINode* aRoot) { - NS_PRECONDITION((aStartN && aEndN) || (!aStartN && !aEndN), - "Set both or neither"); - if (mIsPositioned) { - if (mStartParent != aStartN && mStartParent != aEndN) { - // if old start parent no longer involved, remove range from that - // node's range list. - mStartParent->RangeRemove(this); - } + NS_PRECONDITION((aStartN && aEndN && aRoot) || + (!aStartN && !aEndN && !aRoot), + "Set all or none"); + NS_PRECONDITION(!aRoot || + (nsContentUtils::ContentIsDescendantOf(aStartN, aRoot) && + nsContentUtils::ContentIsDescendantOf(aEndN, aRoot)), + "Wrong root"); + NS_PRECONDITION(!aRoot || + (!aRoot->GetNodeParent() && + (aRoot->IsNodeOfType(nsINode::eDOCUMENT) || + aRoot->IsNodeOfType(nsINode::eATTRIBUTE) || + aRoot->IsNodeOfType(nsINode::eDOCUMENT_FRAGMENT))), + "Bad root"); - if (mEndParent != aStartN && mEndParent != aEndN) { - // if old end parent no longer involved, remove range from that - // node's range list. - mEndParent->RangeRemove(this); + if (mRoot != aRoot) { + if (mRoot) { + mRoot->RemoveMutationObserver(this); + } + if (aRoot) { + aRoot->AddMutationObserver(this); } } - if (mStartParent != aStartN) { - mStartParent = aStartN; - // if it has a new start node, put it on it's list - if (mStartParent) { - mStartParent->RangeAdd(this); // RangeAdd() detects duplication for us - } - } + mStartParent = aStartN; mStartOffset = aStartOffset; - - if (mEndParent != aEndN) { - mEndParent = aEndN; - // if it has a new end node, put it on it's list - if (mEndParent) { - mEndParent->RangeAdd(this); // RangeAdd() detects duplication for us - } - } + mEndParent = aEndN; mEndOffset = aEndOffset; - - mIsPositioned = mStartParent != nsnull; - - // FIX ME need to handle error cases - // (range lists return error, or setting only one endpoint to null) + mIsPositioned = !!mStartParent; + mRoot = aRoot; } static PRInt32 @@ -362,79 +443,6 @@ IndexOf(nsIDOMNode* aChildNode) return parent ? parent->IndexOf(child) : -1; } -static nsresult -PopRanges(nsIDOMNode* aDestNode, PRInt32 aOffset, nsIContent* aSourceNode) -{ - // utility routine to pop all the range endpoints inside the content subtree defined by - // aSourceNode, into the node/offset represented by aDestNode/aOffset. - - nsCOMPtr iter; - nsresult res = NS_NewContentIterator(getter_AddRefs(iter)); - iter->Init(aSourceNode); - - const nsVoidArray* theRangeList; - - while (!iter->IsDone()) - { - nsIContent *cN = iter->GetCurrentNode(); - - theRangeList = cN->GetRangeList(); - if (theRangeList) - { - nsRange* theRange; - PRInt32 theCount = theRangeList->Count(); - while (theCount) - { - theRange = NS_STATIC_CAST(nsRange*, (theRangeList->ElementAt(0))); - if (theRange) - { - // sanity check - do range and content agree over ownership? - res = ContentOwnsRange(theRange, cN); - NS_POSTCONDITION(NS_SUCCEEDED(res), "range and content disagree over range ownership"); - - if (theRange->GetStartParent() == cN) - { - // promote start point up to replacement point - res = theRange->SetStart(aDestNode, aOffset); - NS_POSTCONDITION(NS_SUCCEEDED(res), "nsRange::PopRanges() got error from SetStart()"); - if (NS_FAILED(res)) return res; - } - if (theRange->GetEndParent() == cN) - { - // promote end point up to replacement point - res = theRange->SetEnd(aDestNode, aOffset); - NS_POSTCONDITION(NS_SUCCEEDED(res), "nsRange::PopRanges() got error from SetEnd()"); - if (NS_FAILED(res)) return res; - } - } - // must refresh theRangeList - it might have gone away! - theRangeList = cN->GetRangeList(); - if (theRangeList) - theCount = theRangeList->Count(); - else - theCount = 0; - } - } - - iter->Next(); - } - - return NS_OK; -} - -// sanity check routine for content helpers. confirms that given -// node owns one or both range endpoints. -static nsresult -ContentOwnsRange(nsIRange* aRange, nsINode* aNode) -{ - NS_PRECONDITION(aNode, "null pointer"); - if (aRange->GetStartParent() != aNode && aRange->GetEndParent() != aNode) { - NS_NOTREACHED("nsRange::ContentOwnsRange"); - return NS_ERROR_UNEXPECTED; - } - return NS_OK; -} - /****************************************************** * nsIRange implementation ******************************************************/ @@ -450,7 +458,7 @@ nsRange::GetCommonAncestor() void nsRange::Reset() { - DoSetRange(nsnull, 0, nsnull, 0); + DoSetRange(nsnull, 0, nsnull, 0, nsnull); } /****************************************************** @@ -521,87 +529,59 @@ nsresult nsRange::GetCommonAncestorContainer(nsIDOMNode** aCommonParent) return NS_ERROR_NOT_INITIALIZED; } -static nsresult -IsValidBoundary(nsIDOMNode* aNode) +static nsINode* +IsValidBoundary(nsINode* aNode) { if (!aNode) { - // DOM 2 Range specification doesn't define the error code for this case, - // but this is the best one we have. - return NS_ERROR_DOM_RANGE_BAD_BOUNDARYPOINTS_ERR; + return nsnull; } - PRUint16 nodeType = 0; - aNode->GetNodeType(&nodeType); - switch (nodeType) { - case nsIDOMNode::DOCUMENT_TYPE_NODE: - case nsIDOMNode::ENTITY_NODE: - case nsIDOMNode::NOTATION_NODE: - return NS_ERROR_DOM_RANGE_INVALID_NODE_TYPE_ERR; - case nsIDOMNode::DOCUMENT_NODE: - case nsIDOMNode::DOCUMENT_FRAGMENT_NODE: - case nsIDOMNode::ATTRIBUTE_NODE: - return NS_OK; - default: - break; - } - - nsCOMPtr content = do_QueryInterface(aNode); - if (!content) { - // DOM 2 Range specification doesn't define the error code for this case, - // but this is the best one we have. - return NS_ERROR_DOM_RANGE_BAD_BOUNDARYPOINTS_ERR; + if (aNode->IsNodeOfType(nsINode::eCONTENT) && + NS_STATIC_CAST(nsIContent*, aNode)->Tag() == + nsGkAtoms::documentTypeNodeName) { + return nsnull; } // Elements etc. must be in document or in document fragment, // text nodes in document, in document fragment or in attribute. - if (content->IsInDoc()) { - return NS_OK; + nsINode* root = aNode->GetCurrentDoc(); + if (root) { + return root; } - nsINode* parent = content->GetNodeParent(); - if (parent) { - if (parent->IsNodeOfType(nsINode::eATTRIBUTE)) { - return NS_OK; - } + root = aNode; + while ((aNode = aNode->GetNodeParent())) { + root = aNode; + } - do { - if (parent->IsNodeOfType(nsINode::eDOCUMENT_FRAGMENT)) { - return NS_OK; - } - parent = parent->GetNodeParent(); - } while(parent); + NS_ASSERTION(!root->IsNodeOfType(nsINode::eDOCUMENT), + "GetCurrentDoc should have returned a doc"); + + if (root->IsNodeOfType(nsINode::eDOCUMENT_FRAGMENT) || + root->IsNodeOfType(nsINode::eATTRIBUTE)) { + return root; } #ifdef DEBUG_smaug - nsAutoString name; - content->Tag()->ToString(name); - printf("nsRange::IsValidBoundary: node is not a valid boundary point [%s]\n", - NS_ConvertUTF16toUTF8(name).get()); + nsCOMPtr cont = do_QueryInterface(root); + if (cont) { + nsAutoString name; + content->Tag()->ToString(name); + printf("nsRange::IsValidBoundary: node is not a valid boundary point [%s]\n", + NS_ConvertUTF16toUTF8(name).get()); + } #endif - // DOM 2 Range specification doesn't define the error code for this case, - // but this is the best one we have. - return NS_ERROR_DOM_RANGE_BAD_BOUNDARYPOINTS_ERR; -} - -/** - * This should really check that the two nodes have a common ancestor - */ -PRBool InSameDoc(nsINode* aNode1, nsINode* aNode2) -{ - // XXX if it's in an attribute node, end must be in or descended from same - // node - return aNode1->GetCurrentDoc() == aNode2->GetCurrentDoc(); + return nsnull; } nsresult nsRange::SetStart(nsIDOMNode* aParent, PRInt32 aOffset) { VALIDATE_ACCESS(aParent); - nsresult rv = IsValidBoundary(aParent); - NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr parent = do_QueryInterface(aParent); - NS_ENSURE_TRUE(parent, NS_ERROR_DOM_RANGE_BAD_BOUNDARYPOINTS_ERR); + nsINode* newRoot = IsValidBoundary(parent); + NS_ENSURE_TRUE(newRoot, NS_ERROR_DOM_RANGE_INVALID_NODE_TYPE_ERR); PRInt32 len = GetNodeLength(parent); if (aOffset < 0 || aOffset > len) @@ -609,15 +589,15 @@ nsresult nsRange::SetStart(nsIDOMNode* aParent, PRInt32 aOffset) // Collapse if not positioned yet, if positioned in another doc or // if the new start is after end. - if (!mIsPositioned || !InSameDoc(parent, mEndParent) || + if (!mIsPositioned || newRoot != mRoot || nsContentUtils::ComparePoints(parent, aOffset, mEndParent, mEndOffset) == 1) { - DoSetRange(parent, aOffset, parent, aOffset); + DoSetRange(parent, aOffset, parent, aOffset, newRoot); return NS_OK; } - DoSetRange(parent, aOffset, mEndParent, mEndOffset); + DoSetRange(parent, aOffset, mEndParent, mEndOffset, mRoot); return NS_OK; } @@ -651,11 +631,10 @@ nsresult nsRange::SetStartAfter(nsIDOMNode* aSibling) nsresult nsRange::SetEnd(nsIDOMNode* aParent, PRInt32 aOffset) { VALIDATE_ACCESS(aParent); - nsresult rv = IsValidBoundary(aParent); - NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr parent = do_QueryInterface(aParent); - NS_ENSURE_TRUE(parent, NS_ERROR_DOM_RANGE_BAD_BOUNDARYPOINTS_ERR); + nsINode* newRoot = IsValidBoundary(parent); + NS_ENSURE_TRUE(newRoot, NS_ERROR_DOM_RANGE_INVALID_NODE_TYPE_ERR); PRInt32 len = GetNodeLength(parent); if (aOffset < 0 || aOffset > len) { @@ -664,15 +643,15 @@ nsresult nsRange::SetEnd(nsIDOMNode* aParent, PRInt32 aOffset) // Collapse if not positioned yet, if positioned in another doc or // if the new end is before start. - if (!mIsPositioned || !InSameDoc(parent, mStartParent) || + if (!mIsPositioned || newRoot != mRoot || nsContentUtils::ComparePoints(mStartParent, mStartOffset, parent, aOffset) == 1) { - DoSetRange(parent, aOffset, parent, aOffset); + DoSetRange(parent, aOffset, parent, aOffset, newRoot); return NS_OK; } - DoSetRange(mStartParent, mStartOffset, parent, aOffset); + DoSetRange(mStartParent, mStartOffset, parent, aOffset, mRoot); return NS_OK; } @@ -711,9 +690,9 @@ nsresult nsRange::Collapse(PRBool aToStart) return NS_ERROR_NOT_INITIALIZED; if (aToStart) - DoSetRange(mStartParent, mStartOffset, mStartParent, mStartOffset); + DoSetRange(mStartParent, mStartOffset, mStartParent, mStartOffset, mRoot); else - DoSetRange(mEndParent, mEndOffset, mEndParent, mEndOffset); + DoSetRange(mEndParent, mEndOffset, mEndParent, mEndOffset, mRoot); return NS_OK; } @@ -722,32 +701,19 @@ nsresult nsRange::SelectNode(nsIDOMNode* aN) { VALIDATE_ACCESS(aN); - PRUint16 type = 0; - aN->GetNodeType(&type); - - switch (type) { - case nsIDOMNode::ATTRIBUTE_NODE : - case nsIDOMNode::ENTITY_NODE : - case nsIDOMNode::DOCUMENT_NODE : - case nsIDOMNode::DOCUMENT_FRAGMENT_NODE : - case nsIDOMNode::NOTATION_NODE : - return NS_ERROR_DOM_RANGE_INVALID_NODE_TYPE_ERR; - } - nsCOMPtr node = do_QueryInterface(aN); NS_ENSURE_TRUE(node, NS_ERROR_DOM_RANGE_INVALID_NODE_TYPE_ERR); nsINode* parent = node->GetNodeParent(); - if(!parent) { - return NS_ERROR_DOM_RANGE_INVALID_NODE_TYPE_ERR; - } + nsINode* newRoot = IsValidBoundary(parent); + NS_ENSURE_TRUE(newRoot, NS_ERROR_DOM_RANGE_INVALID_NODE_TYPE_ERR); PRInt32 index = parent->IndexOf(node); if (index < 0) { return NS_ERROR_DOM_RANGE_INVALID_NODE_TYPE_ERR; } - DoSetRange(parent, index, parent, index + 1); + DoSetRange(parent, index, parent, index + 1, newRoot); return NS_OK; } @@ -755,11 +721,12 @@ nsresult nsRange::SelectNode(nsIDOMNode* aN) nsresult nsRange::SelectNodeContents(nsIDOMNode* aN) { VALIDATE_ACCESS(aN); - + nsCOMPtr node = do_QueryInterface(aN); - NS_ENSURE_TRUE(node, NS_ERROR_DOM_RANGE_INVALID_NODE_TYPE_ERR); + nsINode* newRoot = IsValidBoundary(node); + NS_ENSURE_TRUE(newRoot, NS_ERROR_DOM_RANGE_INVALID_NODE_TYPE_ERR); - DoSetRange(node, 0, node, GetNodeLength(node)); + DoSetRange(node, 0, node, GetNodeLength(node), newRoot); return NS_OK; } @@ -1540,7 +1507,7 @@ nsresult nsRange::CloneRange(nsIDOMRange** aReturn) NS_ADDREF(*aReturn = range); - range->DoSetRange(mStartParent, mStartOffset, mEndParent, mEndOffset); + range->DoSetRange(mStartParent, mStartOffset, mEndParent, mEndOffset, mRoot); return NS_OK; } @@ -1757,169 +1724,11 @@ nsRange::Detach() mIsDetached = PR_TRUE; - DoSetRange(nsnull, 0, nsnull, 0); + DoSetRange(nsnull, 0, nsnull, 0, nsnull); return NS_OK; } - - -nsresult nsRange::OwnerGone(nsIContent* aDyingNode) -{ - // nothing for now - should be impossible to getter here - // No node should be deleted if it holds a range endpoint, - // since the range endpoint addrefs the node. - NS_ASSERTION(PR_FALSE,"Deleted content holds a range endpoint"); - return NS_OK; -} - - -nsresult nsRange::OwnerChildInserted(nsIContent* aParentNode, PRInt32 aOffset) -{ - // sanity check - null nodes shouldn't have enclosed ranges - if (!aParentNode) return NS_ERROR_UNEXPECTED; - - nsCOMPtr parent( do_QueryInterface(aParentNode) ); - // quick return if no range list - const nsVoidArray *theRangeList = parent->GetRangeList(); - if (!theRangeList) return NS_OK; - - nsresult res; - - PRInt32 count = theRangeList->Count(); - for (PRInt32 loop = 0; loop < count; loop++) - { - nsRange* theRange = NS_STATIC_CAST(nsRange*, (theRangeList->ElementAt(loop))); - NS_ASSERTION(theRange, "oops, no range"); - - // sanity check - do range and content agree over ownership? - res = ContentOwnsRange(theRange, parent); - NS_PRECONDITION(NS_SUCCEEDED(res), "range and content disagree over range ownership"); - if (NS_SUCCEEDED(res)) - { - if (theRange->mStartParent == parent) - { - // if child inserted before start, move start offset right one - if (aOffset < theRange->mStartOffset) theRange->mStartOffset++; - } - if (theRange->mEndParent == parent) - { - // if child inserted before end, move end offset right one - if (aOffset < theRange->mEndOffset) theRange->mEndOffset++; - } - NS_PRECONDITION(NS_SUCCEEDED(res), "error updating range list"); - } - } - return NS_OK; -} - - -nsresult nsRange::OwnerChildRemoved(nsIContent* aParentNode, PRInt32 aOffset, nsIContent* aRemovedNode) -{ - // sanity check - null nodes shouldn't have enclosed ranges - if (!aParentNode) return NS_ERROR_UNEXPECTED; - - nsCOMPtr parent( do_QueryInterface(aParentNode) ); - nsCOMPtr removed( do_QueryInterface(aRemovedNode) ); - - // any ranges in the content subtree rooted by aRemovedNode need to - // have the enclosed endpoints promoted up to the parentNode/offset - nsCOMPtr domNode(do_QueryInterface(parent)); - if (!domNode) return NS_ERROR_UNEXPECTED; - nsresult res = PopRanges(domNode, aOffset, removed); - - // quick return if no range list - const nsVoidArray *theRangeList = parent->GetRangeList(); - if (!theRangeList) return NS_OK; - - PRInt32 count = theRangeList->Count(); - for (PRInt32 loop = 0; loop < count; loop++) - { - nsRange* theRange = NS_STATIC_CAST(nsRange*, (theRangeList->ElementAt(loop))); - NS_ASSERTION(theRange, "oops, no range"); - - // sanity check - do range and content agree over ownership? - res = ContentOwnsRange(theRange, parent); - NS_PRECONDITION(NS_SUCCEEDED(res), "range and content disagree over range ownership"); - if (NS_SUCCEEDED(res)) - { - if (theRange->mStartParent == parent) - { - // if child deleted before start, move start offset left one - if (aOffset < theRange->mStartOffset) theRange->mStartOffset--; - } - if (theRange->mEndParent == parent) - { - // if child deleted before end, move end offset left one - if (aOffset < theRange->mEndOffset) - { - if (theRange->mEndOffset>0) theRange->mEndOffset--; - } - } - } - } - - return NS_OK; -} - -nsresult -nsRange::TextOwnerChanged(nsIContent* aTextNode, const nsVoidArray *aRangeList, - PRInt32 aStartChanged, PRInt32 aEndChanged, - PRInt32 aReplaceLength) -{ - NS_ASSERTION(aRangeList, - "Don't call TextOwnerChanged if aTextNode is not in a range!"); - NS_ASSERTION(aTextNode, "Null nodes don't have enclosed ranges!"); - - nsCOMPtr domNode(do_QueryInterface(aTextNode)); - if (!domNode) return NS_ERROR_UNEXPECTED; - - PRInt32 count = aRangeList->Count(); - for (PRInt32 loop = 0; loop < count; loop++) - { - nsRange* theRange = NS_STATIC_CAST(nsRange*, (aRangeList->ElementAt(loop))); - NS_ASSERTION(theRange, "oops, no range"); - - // sanity check - do range and content agree over ownership? - nsresult res = ContentOwnsRange(theRange, aTextNode); - NS_PRECONDITION(NS_SUCCEEDED(res), "range and content disagree over range ownership"); - if (NS_SUCCEEDED(res)) - { - PRBool bStartPointInChangedText = PR_FALSE; - - if (theRange->mStartParent == aTextNode) - { - // if range start is inside changed text, position it after change - if ((aStartChanged <= theRange->mStartOffset) && (aEndChanged >= theRange->mStartOffset)) - { - theRange->mStartOffset = aStartChanged+aReplaceLength; - bStartPointInChangedText = PR_TRUE; - } - // else if text changed before start, adjust start offset - else if (aEndChanged <= theRange->mStartOffset) - theRange->mStartOffset += aStartChanged + aReplaceLength - aEndChanged; - } - if (theRange->mEndParent == aTextNode) - { - // if range end is inside changed text, position it before change - if ((aStartChanged <= theRange->mEndOffset) && (aEndChanged >= theRange->mEndOffset)) - { - theRange->mEndOffset = aStartChanged; - // hack: if BOTH range endpoints were inside the change, then they - // both get collapsed to the beginning of the change. - if (bStartPointInChangedText) theRange->mStartOffset = aStartChanged; - } - // else if text changed before end, adjust end offset - else if (aEndChanged <= theRange->mEndOffset) - theRange->mEndOffset += aStartChanged + aReplaceLength - aEndChanged; - } - } - } - - return NS_OK; -} - - // nsIDOMNSRange interface NS_IMETHODIMP nsRange::CreateContextualFragment(const nsAString& aFragment, diff --git a/mozilla/content/base/src/nsRange.h b/mozilla/content/base/src/nsRange.h index 74a5d248bac..f300d9a1ef7 100644 --- a/mozilla/content/base/src/nsRange.h +++ b/mozilla/content/base/src/nsRange.h @@ -51,6 +51,7 @@ #include "nsIContent.h" #include "nsIDOMNode.h" #include "prmon.h" +#include "nsStubMutationObserver.h" class nsVoidArray; @@ -75,10 +76,12 @@ public: class nsRange : public nsIRange, public nsIDOMRange, - public nsIDOMNSRange + public nsIDOMNSRange, + public nsStubMutationObserver { public: nsRange() + : mRoot(nsnull) { } virtual ~nsRange(); @@ -95,19 +98,19 @@ public: virtual nsINode* GetCommonAncestor(); virtual void Reset(); - // nsRange interface extensions - - static NS_METHOD OwnerGone(nsIContent* aParentNode); - - static NS_METHOD OwnerChildInserted(nsIContent* aParentNode, PRInt32 aOffset); - - static NS_METHOD OwnerChildRemoved(nsIContent* aParentNode, PRInt32 aOffset, nsIContent* aRemovedNode); - - static nsresult TextOwnerChanged(nsIContent *aTextNode, - const nsVoidArray *aRangeList, - PRInt32 aStartOffset, - PRInt32 aEndOffset, - PRInt32 aReplaceLength); + // nsIMutationObserver methods + virtual void CharacterDataChanged(nsIDocument* aDocument, + nsIContent* aContent, + CharacterDataChangeInfo* aChangeInfo); + virtual void ContentInserted(nsIDocument* aDocument, + nsIContent* aContainer, + nsIContent* aChild, + PRInt32 aIndexInContainer); + virtual void ContentRemoved(nsIDocument* aDocument, + nsIContent* aContainer, + nsIContent* aChild, + PRInt32 aIndexInContainer); + virtual void NodeWillBeDestroyed(const nsINode* aNode); private: // no copy's or assigns @@ -127,8 +130,11 @@ public: PRBool *outNodeAfter); protected: + nsINode* mRoot; + void DoSetRange(nsINode* aStartN, PRInt32 aStartOffset, - nsINode* aEndN, PRInt32 aEndOffset); + nsINode* aEndN, PRInt32 aEndOffset, + nsINode* aRoot); }; // Make a new nsIDOMRange object diff --git a/mozilla/content/events/src/nsXMLEventsManager.cpp b/mozilla/content/events/src/nsXMLEventsManager.cpp index 360a9190407..ed3c172679a 100644 --- a/mozilla/content/events/src/nsXMLEventsManager.cpp +++ b/mozilla/content/events/src/nsXMLEventsManager.cpp @@ -351,7 +351,7 @@ NS_IMPL_NSIDOCUMENTOBSERVER_STATE_STUB(nsXMLEventsManager) void nsXMLEventsManager::CharacterDataChanged(nsIDocument* aDocument, nsIContent* aContent, - PRBool aAppend) {} + CharacterDataChangeInfo* aInfo) {} void nsXMLEventsManager::AttributeChanged(nsIDocument* aDocument, nsIContent* aContent, diff --git a/mozilla/content/svg/content/src/nsSVGPatternElement.cpp b/mozilla/content/svg/content/src/nsSVGPatternElement.cpp index 05a7e85da42..b7a423bc1e4 100644 --- a/mozilla/content/svg/content/src/nsSVGPatternElement.cpp +++ b/mozilla/content/svg/content/src/nsSVGPatternElement.cpp @@ -321,7 +321,7 @@ nsSVGPatternElement::PushUpdate() void nsSVGPatternElement::CharacterDataChanged(nsIDocument *aDocument, nsIContent *aContent, - PRBool aAppend) + CharacterDataChangeInfo *aInfo) { PushUpdate(); } diff --git a/mozilla/content/svg/content/src/nsSVGUseElement.cpp b/mozilla/content/svg/content/src/nsSVGUseElement.cpp index d2edfa71589..1918229c3ef 100644 --- a/mozilla/content/svg/content/src/nsSVGUseElement.cpp +++ b/mozilla/content/svg/content/src/nsSVGUseElement.cpp @@ -286,7 +286,7 @@ nsSVGUseElement::DidModifySVGObservable(nsISVGValue* aObservable, void nsSVGUseElement::CharacterDataChanged(nsIDocument *aDocument, nsIContent *aContent, - PRBool aAppend) + CharacterDataChangeInfo* aInfo) { TriggerReclone(); } diff --git a/mozilla/content/xbl/src/nsBindingManager.cpp b/mozilla/content/xbl/src/nsBindingManager.cpp index 26fe7061b79..883cf1a7991 100644 --- a/mozilla/content/xbl/src/nsBindingManager.cpp +++ b/mozilla/content/xbl/src/nsBindingManager.cpp @@ -1157,10 +1157,10 @@ nsBindingManager::RemoveObserver(nsIMutationObserver* aObserver) void nsBindingManager::CharacterDataChanged(nsIDocument* aDocument, nsIContent* aContent, - PRBool aAppend) + CharacterDataChangeInfo* aInfo) { NS_BINDINGMANAGER_NOTIFY_OBSERVERS(CharacterDataChanged, - (aDocument, aContent, aAppend)); + (aDocument, aContent, aInfo)); } void diff --git a/mozilla/content/xslt/src/xpath/nsXPathResult.cpp b/mozilla/content/xslt/src/xpath/nsXPathResult.cpp index fa94b69a119..b70dae3317f 100644 --- a/mozilla/content/xslt/src/xpath/nsXPathResult.cpp +++ b/mozilla/content/xslt/src/xpath/nsXPathResult.cpp @@ -210,7 +210,7 @@ nsXPathResult::NodeWillBeDestroyed(const nsINode* aNode) void nsXPathResult::CharacterDataChanged(nsIDocument* aDocument, nsIContent *aContent, - PRBool aAppend) + CharacterDataChangeInfo* aInfo) { Invalidate(); } diff --git a/mozilla/content/xslt/src/xslt/txMozillaXSLTProcessor.cpp b/mozilla/content/xslt/src/xslt/txMozillaXSLTProcessor.cpp index a4e4c613eb1..a7cbd97f9e3 100644 --- a/mozilla/content/xslt/src/xslt/txMozillaXSLTProcessor.cpp +++ b/mozilla/content/xslt/src/xslt/txMozillaXSLTProcessor.cpp @@ -1199,7 +1199,7 @@ txMozillaXSLTProcessor::NodeWillBeDestroyed(const nsINode* aNode) void txMozillaXSLTProcessor::CharacterDataChanged(nsIDocument* aDocument, nsIContent *aContent, - PRBool aAppend) + CharacterDataChangeInfo* aInfo) { mStylesheet = nsnull; } diff --git a/mozilla/content/xul/content/src/nsXULElement.cpp b/mozilla/content/xul/content/src/nsXULElement.cpp index 1680a8b7a10..a52385df43f 100644 --- a/mozilla/content/xul/content/src/nsXULElement.cpp +++ b/mozilla/content/xul/content/src/nsXULElement.cpp @@ -153,7 +153,6 @@ #include "nsIFrame.h" #include "nsNodeInfoManager.h" #include "nsXBLBinding.h" -#include "nsRange.h" #include "nsEventDispatcher.h" /** @@ -1742,28 +1741,6 @@ nsXULElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor) return nsGenericElement::PreHandleEvent(aVisitor); } -nsresult -nsXULElement::RangeAdd(nsIRange* aRange) -{ - // rdf content does not yet support DOM ranges - return NS_OK; -} - - -void -nsXULElement::RangeRemove(nsIRange* aRange) -{ - // rdf content does not yet support DOM ranges -} - - -const nsVoidArray * -nsXULElement::GetRangeList() const -{ - // XUL content does not yet support DOM ranges - return nsnull; -} - // XXX This _should_ be an implementation method, _not_ publicly exposed :-( NS_IMETHODIMP nsXULElement::GetResource(nsIRDFResource** aResource) diff --git a/mozilla/content/xul/content/src/nsXULElement.h b/mozilla/content/xul/content/src/nsXULElement.h index 6ea1afac003..eb4c6548807 100644 --- a/mozilla/content/xul/content/src/nsXULElement.h +++ b/mozilla/content/xul/content/src/nsXULElement.h @@ -514,9 +514,6 @@ public: } #endif - virtual nsresult RangeAdd(nsIRange* aRange); - virtual void RangeRemove(nsIRange* aRange); - virtual const nsVoidArray *GetRangeList() const; virtual void SetFocus(nsPresContext* aPresContext); virtual void RemoveFocus(nsPresContext* aPresContext); diff --git a/mozilla/docshell/shistory/src/nsSHEntry.cpp b/mozilla/docshell/shistory/src/nsSHEntry.cpp index 926f78047f3..e09c06b962f 100644 --- a/mozilla/docshell/shistory/src/nsSHEntry.cpp +++ b/mozilla/docshell/shistory/src/nsSHEntry.cpp @@ -651,7 +651,7 @@ nsSHEntry::NodeWillBeDestroyed(const nsINode* aNode) void nsSHEntry::CharacterDataChanged(nsIDocument* aDocument, nsIContent* aContent, - PRBool aAppend) + CharacterDataChangeInfo* aInfo) { DocumentMutated(); } diff --git a/mozilla/layout/base/nsPresShell.cpp b/mozilla/layout/base/nsPresShell.cpp index f4b52f6976e..c1bb219e3fb 100644 --- a/mozilla/layout/base/nsPresShell.cpp +++ b/mozilla/layout/base/nsPresShell.cpp @@ -1234,7 +1234,7 @@ public: virtual void EndLoad(nsIDocument* aDocument); virtual void CharacterDataChanged(nsIDocument* aDocument, nsIContent* aContent, - PRBool aAppend); + CharacterDataChangeInfo* aInfo); virtual void ContentStatesChanged(nsIDocument* aDocument, nsIContent* aContent1, nsIContent* aContent2, @@ -5229,7 +5229,7 @@ PresShell::GetReflowBatchingStatus(PRBool* aIsBatching) void PresShell::CharacterDataChanged(nsIDocument *aDocument, nsIContent* aContent, - PRBool aAppend) + CharacterDataChangeInfo* aInfo) { NS_PRECONDITION(!mIsDocumentGone, "Unexpected CharacterDataChanged"); NS_PRECONDITION(aDocument == mDocument, "Unexpected aDocument"); @@ -5244,7 +5244,7 @@ PresShell::CharacterDataChanged(nsIDocument *aDocument, // frame to the caret. mCaret->InvalidateOutsideCaret(); } - mFrameConstructor->CharacterDataChanged(aContent, aAppend); + mFrameConstructor->CharacterDataChanged(aContent, aInfo->mAppend); VERIFY_STYLE_TREE; DidCauseReflow(); } diff --git a/mozilla/layout/inspector/src/inDOMView.cpp b/mozilla/layout/inspector/src/inDOMView.cpp index 89a8363b070..ef965e249b1 100644 --- a/mozilla/layout/inspector/src/inDOMView.cpp +++ b/mozilla/layout/inspector/src/inDOMView.cpp @@ -832,7 +832,7 @@ inDOMView::ContentAppended(nsIDocument *aDocument, void inDOMView::CharacterDataChanged(nsIDocument *aDocument, nsIContent* aContent, - PRBool aAppend) + CharacterDataChangeInfo* aInfo) { } diff --git a/mozilla/widget/src/cocoa/nsMenuBarX.mm b/mozilla/widget/src/cocoa/nsMenuBarX.mm index bfe3170a441..66f1fabf85b 100644 --- a/mozilla/widget/src/cocoa/nsMenuBarX.mm +++ b/mozilla/widget/src/cocoa/nsMenuBarX.mm @@ -831,7 +831,8 @@ NS_IMETHODIMP nsMenuBarX::Paint() void nsMenuBarX::CharacterDataChanged(nsIDocument * aDocument, - nsIContent * aContent, PRBool aAppend) + nsIContent * aContent, + CharacterDataChangeInfo * aInfo) { } diff --git a/mozilla/widget/src/mac/nsMenuBarX.cpp b/mozilla/widget/src/mac/nsMenuBarX.cpp index 43e2174e0b7..65ed3a78749 100644 --- a/mozilla/widget/src/mac/nsMenuBarX.cpp +++ b/mozilla/widget/src/mac/nsMenuBarX.cpp @@ -656,7 +656,8 @@ NS_METHOD nsMenuBarX::Paint() void nsMenuBarX::CharacterDataChanged( nsIDocument * aDocument, - nsIContent * aContent, PRBool aAppend) + nsIContent * aContent, + CharacterDataChangeInfo * aInfo) { }