|
Server : Apache/2.2.17 (Unix) mod_ssl/2.2.17 OpenSSL/0.9.8e-fips-rhel5 DAV/2 PHP/5.2.17 System : Linux localhost 2.6.18-419.el5 #1 SMP Fri Feb 24 22:47:42 UTC 2017 x86_64 User : nobody ( 99) PHP Version : 5.2.17 Disable Function : NONE Directory : /proc/22697/root/usr/lib64/xulrunner-devel-17.0.10/include/ |
Upload File : |
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* Implementation of the DOM nsIDOMRange object.
*/
#ifndef nsRange_h___
#define nsRange_h___
#include "nsIDOMRange.h"
#include "nsCOMPtr.h"
#include "nsIDOMDocumentFragment.h"
#include "nsINode.h"
#include "nsIDOMNode.h"
#include "prmon.h"
#include "nsStubMutationObserver.h"
class nsRange : public nsIDOMRange,
public nsStubMutationObserver
{
public:
nsRange()
: mRoot(nullptr)
, mStartOffset(0)
, mEndOffset(0)
, mIsPositioned(false)
, mIsDetached(false)
, mMaySpanAnonymousSubtrees(false)
, mInSelection(false)
, mEnableGravitationOnElementRemoval(true)
{}
virtual ~nsRange();
static nsresult CreateRange(nsIDOMNode* aStartParent, int32_t aStartOffset,
nsIDOMNode* aEndParent, int32_t aEndOffset,
nsRange** aRange);
static nsresult CreateRange(nsIDOMNode* aStartParent, int32_t aStartOffset,
nsIDOMNode* aEndParent, int32_t aEndOffset,
nsIDOMRange** aRange);
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsRange, nsIDOMRange)
/**
* The DOM Range spec requires that when a node is removed from its parent,
* and the node's subtree contains the start or end point of a range, that
* start or end point is moved up to where the node was removed from its
* parent.
* For some internal uses of Ranges it's useful to disable that behavior,
* so that a range of children within a single parent is preserved even if
* that parent is removed from the document tree.
*/
void SetEnableGravitationOnElementRemoval(bool aEnable)
{
mEnableGravitationOnElementRemoval = aEnable;
}
// nsIDOMRange interface
NS_DECL_NSIDOMRANGE
nsINode* GetRoot() const
{
return mRoot;
}
nsINode* GetStartParent() const
{
return mStartParent;
}
nsINode* GetEndParent() const
{
return mEndParent;
}
int32_t StartOffset() const
{
return mStartOffset;
}
int32_t EndOffset() const
{
return mEndOffset;
}
bool IsPositioned() const
{
return mIsPositioned;
}
bool Collapsed() const
{
return mIsPositioned && mStartParent == mEndParent &&
mStartOffset == mEndOffset;
}
void SetMaySpanAnonymousSubtrees(bool aMaySpanAnonymousSubtrees)
{
mMaySpanAnonymousSubtrees = aMaySpanAnonymousSubtrees;
}
/**
* Return true iff this range is part of at least one Selection object
* and isn't detached.
*/
bool IsInSelection() const
{
return mInSelection;
}
/**
* Called when the range is added/removed from a Selection.
*/
void SetInSelection(bool aInSelection)
{
if (mInSelection == aInSelection) {
return;
}
mInSelection = aInSelection;
nsINode* commonAncestor = GetCommonAncestor();
NS_ASSERTION(commonAncestor, "unexpected disconnected nodes");
if (mInSelection) {
RegisterCommonAncestor(commonAncestor);
} else {
UnregisterCommonAncestor(commonAncestor);
}
}
nsINode* GetCommonAncestor() const;
void Reset();
nsresult SetStart(nsINode* aParent, int32_t aOffset);
nsresult SetEnd(nsINode* aParent, int32_t aOffset);
already_AddRefed<nsRange> CloneRange() const;
nsresult Set(nsINode* aStartParent, int32_t aStartOffset,
nsINode* aEndParent, int32_t aEndOffset)
{
// If this starts being hot, we may be able to optimize this a bit,
// but for now just set start and end separately.
nsresult rv = SetStart(aStartParent, aStartOffset);
NS_ENSURE_SUCCESS(rv, rv);
return SetEnd(aEndParent, aEndOffset);
}
NS_IMETHOD GetUsedFontFaces(nsIDOMFontFaceList** aResult);
// nsIMutationObserver methods
NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
NS_DECL_NSIMUTATIONOBSERVER_PARENTCHAINCHANGED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
private:
// no copy's or assigns
nsRange(const nsRange&);
nsRange& operator=(const nsRange&);
/**
* Cut or delete the range's contents.
*
* @param aFragment nsIDOMDocumentFragment containing the nodes.
* May be null to indicate the caller doesn't want a fragment.
*/
nsresult CutContents(nsIDOMDocumentFragment** frag);
static nsresult CloneParentsBetween(nsIDOMNode *aAncestor,
nsIDOMNode *aNode,
nsIDOMNode **aClosestAncestor,
nsIDOMNode **aFarthestAncestor);
public:
/******************************************************************************
* Utility routine to detect if a content node starts before a range and/or
* ends after a range. If neither it is contained inside the range.
*
* XXX - callers responsibility to ensure node in same doc as range!
*
*****************************************************************************/
static nsresult CompareNodeToRange(nsINode* aNode, nsRange* aRange,
bool *outNodeBefore,
bool *outNodeAfter);
static bool IsNodeSelected(nsINode* aNode, uint32_t aStartOffset,
uint32_t aEndOffset);
typedef nsTHashtable<nsPtrHashKey<nsRange> > RangeHashTable;
protected:
void RegisterCommonAncestor(nsINode* aNode);
void UnregisterCommonAncestor(nsINode* aNode);
nsINode* IsValidBoundary(nsINode* aNode);
// CharacterDataChanged set aNotInsertedYet to true to disable an assertion
// and suppress re-registering a range common ancestor node since
// the new text node of a splitText hasn't been inserted yet.
// CharacterDataChanged does the re-registering when needed.
void DoSetRange(nsINode* aStartN, int32_t aStartOffset,
nsINode* aEndN, int32_t aEndOffset,
nsINode* aRoot, bool aNotInsertedYet = false);
/**
* For a range for which IsInSelection() is true, return the common
* ancestor for the range. This method uses the selection bits and
* nsGkAtoms::range property on the nodes to quickly find the ancestor.
* That is, it's a faster version of GetCommonAncestor that only works
* for ranges in a Selection. The method will assert and the behavior
* is undefined if called on a range where IsInSelection() is false.
*/
nsINode* GetRegisteredCommonAncestor();
struct NS_STACK_CLASS AutoInvalidateSelection
{
AutoInvalidateSelection(nsRange* aRange) : mRange(aRange)
{
#ifdef DEBUG
mWasInSelection = mRange->IsInSelection();
#endif
if (!mRange->IsInSelection() || mIsNested) {
return;
}
mIsNested = true;
mCommonAncestor = mRange->GetRegisteredCommonAncestor();
}
~AutoInvalidateSelection();
nsRange* mRange;
nsRefPtr<nsINode> mCommonAncestor;
#ifdef DEBUG
bool mWasInSelection;
#endif
static bool mIsNested;
};
nsCOMPtr<nsINode> mRoot;
nsCOMPtr<nsINode> mStartParent;
nsCOMPtr<nsINode> mEndParent;
int32_t mStartOffset;
int32_t mEndOffset;
bool mIsPositioned;
bool mIsDetached;
bool mMaySpanAnonymousSubtrees;
bool mInSelection;
bool mEnableGravitationOnElementRemoval;
};
#endif /* nsRange_h___ */