mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-19 08:15:31 +00:00
365f79c262
EditorUtils::IsDescendantOf() current takes a pointer to offset or a pointer to child content if the caller needs to know the child of the most ancestor node. However, some callers should get a child as EditorDOMPoint or EditorRawDOMPoint. Then, they can be used for some editor methods which need to take child node for performance optimization. This patch makes EditorUtils::IsDescendantOf() as only two overloads. One takes pointer to EditorRawDOMPoint as optional out argument. The other takes pointer to EditorDOMPoint as an out param. Additionally, this creates new constructor of AutoTrackDOMPoint for making it can treat EditorDOMPoint directly. MozReview-Commit-ID: IsAGTUvKI19 --HG-- extra : rebase_source : 97469a21b974c6a1dd515ab472bbc4a88c1899c8
674 lines
17 KiB
C++
674 lines
17 KiB
C++
/* -*- 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/. */
|
|
|
|
#include "mozilla/SelectionState.h"
|
|
|
|
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc.
|
|
#include "mozilla/EditorUtils.h" // for EditorUtils
|
|
#include "mozilla/dom/Selection.h" // for Selection
|
|
#include "nsAString.h" // for nsAString::Length
|
|
#include "nsCycleCollectionParticipant.h"
|
|
#include "nsDebug.h" // for NS_ENSURE_TRUE, etc.
|
|
#include "nsError.h" // for NS_OK, etc.
|
|
#include "nsIContent.h" // for nsIContent
|
|
#include "nsIDOMCharacterData.h" // for nsIDOMCharacterData
|
|
#include "nsIDOMNode.h" // for nsIDOMNode
|
|
#include "nsISupportsImpl.h" // for nsRange::Release
|
|
#include "nsRange.h" // for nsRange
|
|
|
|
namespace mozilla {
|
|
|
|
using namespace dom;
|
|
|
|
/******************************************************************************
|
|
* mozilla::SelectionState
|
|
*
|
|
* Class for recording selection info. Stores selection as collection of
|
|
* { {startnode, startoffset} , {endnode, endoffset} } tuples. Can't store
|
|
* ranges since dom gravity will possibly change the ranges.
|
|
******************************************************************************/
|
|
SelectionState::SelectionState()
|
|
{
|
|
}
|
|
|
|
SelectionState::~SelectionState()
|
|
{
|
|
MakeEmpty();
|
|
}
|
|
|
|
void
|
|
SelectionState::SaveSelection(Selection* aSel)
|
|
{
|
|
MOZ_ASSERT(aSel);
|
|
int32_t arrayCount = mArray.Length();
|
|
int32_t rangeCount = aSel->RangeCount();
|
|
|
|
// if we need more items in the array, new them
|
|
if (arrayCount < rangeCount) {
|
|
for (int32_t i = arrayCount; i < rangeCount; i++) {
|
|
mArray.AppendElement();
|
|
mArray[i] = new RangeItem();
|
|
}
|
|
} else if (arrayCount > rangeCount) {
|
|
// else if we have too many, delete them
|
|
for (int32_t i = arrayCount - 1; i >= rangeCount; i--) {
|
|
mArray.RemoveElementAt(i);
|
|
}
|
|
}
|
|
|
|
// now store the selection ranges
|
|
for (int32_t i = 0; i < rangeCount; i++) {
|
|
mArray[i]->StoreRange(aSel->GetRangeAt(i));
|
|
}
|
|
}
|
|
|
|
nsresult
|
|
SelectionState::RestoreSelection(Selection* aSel)
|
|
{
|
|
NS_ENSURE_TRUE(aSel, NS_ERROR_NULL_POINTER);
|
|
|
|
// clear out selection
|
|
aSel->RemoveAllRanges();
|
|
|
|
// set the selection ranges anew
|
|
size_t arrayCount = mArray.Length();
|
|
for (size_t i = 0; i < arrayCount; i++) {
|
|
RefPtr<nsRange> range = mArray[i]->GetRange();
|
|
NS_ENSURE_TRUE(range, NS_ERROR_UNEXPECTED);
|
|
|
|
nsresult rv = aSel->AddRange(range);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
bool
|
|
SelectionState::IsCollapsed()
|
|
{
|
|
if (mArray.Length() != 1) {
|
|
return false;
|
|
}
|
|
RefPtr<nsRange> range = mArray[0]->GetRange();
|
|
NS_ENSURE_TRUE(range, false);
|
|
return range->Collapsed();
|
|
}
|
|
|
|
bool
|
|
SelectionState::IsEqual(SelectionState* aSelState)
|
|
{
|
|
NS_ENSURE_TRUE(aSelState, false);
|
|
size_t myCount = mArray.Length(), itsCount = aSelState->mArray.Length();
|
|
if (myCount != itsCount) {
|
|
return false;
|
|
}
|
|
if (!myCount) {
|
|
return false;
|
|
}
|
|
|
|
for (size_t i = 0; i < myCount; i++) {
|
|
RefPtr<nsRange> myRange = mArray[i]->GetRange();
|
|
RefPtr<nsRange> itsRange = aSelState->mArray[i]->GetRange();
|
|
NS_ENSURE_TRUE(myRange && itsRange, false);
|
|
|
|
int16_t compResult;
|
|
nsresult rv;
|
|
rv = myRange->CompareBoundaryPoints(nsIDOMRange::START_TO_START, itsRange, &compResult);
|
|
if (NS_FAILED(rv) || compResult) {
|
|
return false;
|
|
}
|
|
rv = myRange->CompareBoundaryPoints(nsIDOMRange::END_TO_END, itsRange, &compResult);
|
|
if (NS_FAILED(rv) || compResult) {
|
|
return false;
|
|
}
|
|
}
|
|
// if we got here, they are equal
|
|
return true;
|
|
}
|
|
|
|
void
|
|
SelectionState::MakeEmpty()
|
|
{
|
|
// free any items in the array
|
|
mArray.Clear();
|
|
}
|
|
|
|
bool
|
|
SelectionState::IsEmpty()
|
|
{
|
|
return mArray.IsEmpty();
|
|
}
|
|
|
|
/******************************************************************************
|
|
* mozilla::RangeUpdater
|
|
*
|
|
* Class for updating nsRanges in response to editor actions.
|
|
******************************************************************************/
|
|
|
|
RangeUpdater::RangeUpdater()
|
|
: mLock(false)
|
|
{
|
|
}
|
|
|
|
RangeUpdater::~RangeUpdater()
|
|
{
|
|
// nothing to do, we don't own the items in our array.
|
|
}
|
|
|
|
void
|
|
RangeUpdater::RegisterRangeItem(RangeItem* aRangeItem)
|
|
{
|
|
if (!aRangeItem) {
|
|
return;
|
|
}
|
|
if (mArray.Contains(aRangeItem)) {
|
|
NS_ERROR("tried to register an already registered range");
|
|
return; // don't register it again. It would get doubly adjusted.
|
|
}
|
|
mArray.AppendElement(aRangeItem);
|
|
}
|
|
|
|
void
|
|
RangeUpdater::DropRangeItem(RangeItem* aRangeItem)
|
|
{
|
|
if (!aRangeItem) {
|
|
return;
|
|
}
|
|
mArray.RemoveElement(aRangeItem);
|
|
}
|
|
|
|
nsresult
|
|
RangeUpdater::RegisterSelectionState(SelectionState& aSelState)
|
|
{
|
|
size_t theCount = aSelState.mArray.Length();
|
|
if (theCount < 1) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
for (size_t i = 0; i < theCount; i++) {
|
|
RegisterRangeItem(aSelState.mArray[i]);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
RangeUpdater::DropSelectionState(SelectionState& aSelState)
|
|
{
|
|
size_t theCount = aSelState.mArray.Length();
|
|
if (theCount < 1) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
for (size_t i = 0; i < theCount; i++) {
|
|
DropRangeItem(aSelState.mArray[i]);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
// gravity methods:
|
|
|
|
nsresult
|
|
RangeUpdater::SelAdjCreateNode(nsINode* aParent,
|
|
int32_t aPosition)
|
|
{
|
|
if (mLock) {
|
|
// lock set by Will/DidReplaceParent, etc...
|
|
return NS_OK;
|
|
}
|
|
NS_ENSURE_TRUE(aParent, NS_ERROR_NULL_POINTER);
|
|
size_t count = mArray.Length();
|
|
if (!count) {
|
|
return NS_OK;
|
|
}
|
|
|
|
for (size_t i = 0; i < count; i++) {
|
|
RangeItem* item = mArray[i];
|
|
NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER);
|
|
|
|
if (item->mStartContainer == aParent && item->mStartOffset > aPosition) {
|
|
item->mStartOffset++;
|
|
}
|
|
if (item->mEndContainer == aParent && item->mEndOffset > aPosition) {
|
|
item->mEndOffset++;
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
RangeUpdater::SelAdjInsertNode(nsINode* aParent,
|
|
int32_t aPosition)
|
|
{
|
|
return SelAdjCreateNode(aParent, aPosition);
|
|
}
|
|
|
|
void
|
|
RangeUpdater::SelAdjDeleteNode(nsINode* aNode)
|
|
{
|
|
if (mLock) {
|
|
// lock set by Will/DidReplaceParent, etc...
|
|
return;
|
|
}
|
|
MOZ_ASSERT(aNode);
|
|
size_t count = mArray.Length();
|
|
if (!count) {
|
|
return;
|
|
}
|
|
|
|
nsCOMPtr<nsINode> parent = aNode->GetParentNode();
|
|
int32_t offset = parent ? parent->IndexOf(aNode) : -1;
|
|
|
|
// check for range endpoints that are after aNode and in the same parent
|
|
for (size_t i = 0; i < count; i++) {
|
|
RangeItem* item = mArray[i];
|
|
MOZ_ASSERT(item);
|
|
|
|
if (item->mStartContainer == parent && item->mStartOffset > offset) {
|
|
item->mStartOffset--;
|
|
}
|
|
if (item->mEndContainer == parent && item->mEndOffset > offset) {
|
|
item->mEndOffset--;
|
|
}
|
|
|
|
// check for range endpoints that are in aNode
|
|
if (item->mStartContainer == aNode) {
|
|
item->mStartContainer = parent;
|
|
item->mStartOffset = offset;
|
|
}
|
|
if (item->mEndContainer == aNode) {
|
|
item->mEndContainer = parent;
|
|
item->mEndOffset = offset;
|
|
}
|
|
|
|
// check for range endpoints that are in descendants of aNode
|
|
nsCOMPtr<nsINode> oldStart;
|
|
if (EditorUtils::IsDescendantOf(*item->mStartContainer, *aNode)) {
|
|
oldStart = item->mStartContainer; // save for efficiency hack below.
|
|
item->mStartContainer = parent;
|
|
item->mStartOffset = offset;
|
|
}
|
|
|
|
// avoid having to call IsDescendantOf() for common case of range startnode == range endnode.
|
|
if (item->mEndContainer == oldStart ||
|
|
EditorUtils::IsDescendantOf(*item->mEndContainer, *aNode)) {
|
|
item->mEndContainer = parent;
|
|
item->mEndOffset = offset;
|
|
}
|
|
}
|
|
}
|
|
|
|
nsresult
|
|
RangeUpdater::SelAdjSplitNode(nsIContent& aOldRightNode,
|
|
int32_t aOffset,
|
|
nsIContent* aNewLeftNode)
|
|
{
|
|
if (mLock) {
|
|
// lock set by Will/DidReplaceParent, etc...
|
|
return NS_OK;
|
|
}
|
|
NS_ENSURE_TRUE(aNewLeftNode, NS_ERROR_NULL_POINTER);
|
|
size_t count = mArray.Length();
|
|
if (!count) {
|
|
return NS_OK;
|
|
}
|
|
|
|
nsCOMPtr<nsINode> parent = aOldRightNode.GetParentNode();
|
|
int32_t offset = parent ? parent->IndexOf(&aOldRightNode) : -1;
|
|
|
|
// first part is same as inserting aNewLeftnode
|
|
nsresult rv = SelAdjInsertNode(parent, offset - 1);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// next step is to check for range enpoints inside aOldRightNode
|
|
for (size_t i = 0; i < count; i++) {
|
|
RangeItem* item = mArray[i];
|
|
NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER);
|
|
|
|
if (item->mStartContainer == &aOldRightNode) {
|
|
if (item->mStartOffset > aOffset) {
|
|
item->mStartOffset -= aOffset;
|
|
} else {
|
|
item->mStartContainer = aNewLeftNode;
|
|
}
|
|
}
|
|
if (item->mEndContainer == &aOldRightNode) {
|
|
if (item->mEndOffset > aOffset) {
|
|
item->mEndOffset -= aOffset;
|
|
} else {
|
|
item->mEndContainer = aNewLeftNode;
|
|
}
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
RangeUpdater::SelAdjJoinNodes(nsINode& aLeftNode,
|
|
nsINode& aRightNode,
|
|
nsINode& aParent,
|
|
int32_t aOffset,
|
|
int32_t aOldLeftNodeLength)
|
|
{
|
|
if (mLock) {
|
|
// lock set by Will/DidReplaceParent, etc...
|
|
return NS_OK;
|
|
}
|
|
size_t count = mArray.Length();
|
|
if (!count) {
|
|
return NS_OK;
|
|
}
|
|
|
|
for (size_t i = 0; i < count; i++) {
|
|
RangeItem* item = mArray[i];
|
|
NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER);
|
|
|
|
if (item->mStartContainer == &aParent) {
|
|
// adjust start point in aParent
|
|
if (item->mStartOffset > aOffset) {
|
|
item->mStartOffset--;
|
|
} else if (item->mStartOffset == aOffset) {
|
|
// join keeps right hand node
|
|
item->mStartContainer = &aRightNode;
|
|
item->mStartOffset = aOldLeftNodeLength;
|
|
}
|
|
} else if (item->mStartContainer == &aRightNode) {
|
|
// adjust start point in aRightNode
|
|
item->mStartOffset += aOldLeftNodeLength;
|
|
} else if (item->mStartContainer == &aLeftNode) {
|
|
// adjust start point in aLeftNode
|
|
item->mStartContainer = &aRightNode;
|
|
}
|
|
|
|
if (item->mEndContainer == &aParent) {
|
|
// adjust end point in aParent
|
|
if (item->mEndOffset > aOffset) {
|
|
item->mEndOffset--;
|
|
} else if (item->mEndOffset == aOffset) {
|
|
// join keeps right hand node
|
|
item->mEndContainer = &aRightNode;
|
|
item->mEndOffset = aOldLeftNodeLength;
|
|
}
|
|
} else if (item->mEndContainer == &aRightNode) {
|
|
// adjust end point in aRightNode
|
|
item->mEndOffset += aOldLeftNodeLength;
|
|
} else if (item->mEndContainer == &aLeftNode) {
|
|
// adjust end point in aLeftNode
|
|
item->mEndContainer = &aRightNode;
|
|
}
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
void
|
|
RangeUpdater::SelAdjInsertText(Text& aTextNode,
|
|
int32_t aOffset,
|
|
const nsAString& aString)
|
|
{
|
|
if (mLock) {
|
|
// lock set by Will/DidReplaceParent, etc...
|
|
return;
|
|
}
|
|
|
|
size_t count = mArray.Length();
|
|
if (!count) {
|
|
return;
|
|
}
|
|
|
|
size_t len = aString.Length();
|
|
for (size_t i = 0; i < count; i++) {
|
|
RangeItem* item = mArray[i];
|
|
MOZ_ASSERT(item);
|
|
|
|
if (item->mStartContainer == &aTextNode && item->mStartOffset > aOffset) {
|
|
item->mStartOffset += len;
|
|
}
|
|
if (item->mEndContainer == &aTextNode && item->mEndOffset > aOffset) {
|
|
item->mEndOffset += len;
|
|
}
|
|
}
|
|
}
|
|
|
|
nsresult
|
|
RangeUpdater::SelAdjDeleteText(nsIContent* aTextNode,
|
|
int32_t aOffset,
|
|
int32_t aLength)
|
|
{
|
|
if (mLock) {
|
|
// lock set by Will/DidReplaceParent, etc...
|
|
return NS_OK;
|
|
}
|
|
|
|
size_t count = mArray.Length();
|
|
if (!count) {
|
|
return NS_OK;
|
|
}
|
|
NS_ENSURE_TRUE(aTextNode, NS_ERROR_NULL_POINTER);
|
|
|
|
for (size_t i = 0; i < count; i++) {
|
|
RangeItem* item = mArray[i];
|
|
NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER);
|
|
|
|
if (item->mStartContainer == aTextNode && item->mStartOffset > aOffset) {
|
|
item->mStartOffset -= aLength;
|
|
if (item->mStartOffset < 0) {
|
|
item->mStartOffset = 0;
|
|
}
|
|
}
|
|
if (item->mEndContainer == aTextNode && item->mEndOffset > aOffset) {
|
|
item->mEndOffset -= aLength;
|
|
if (item->mEndOffset < 0) {
|
|
item->mEndOffset = 0;
|
|
}
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
RangeUpdater::SelAdjDeleteText(nsIDOMCharacterData* aTextNode,
|
|
int32_t aOffset,
|
|
int32_t aLength)
|
|
{
|
|
nsCOMPtr<nsIContent> textNode = do_QueryInterface(aTextNode);
|
|
return SelAdjDeleteText(textNode, aOffset, aLength);
|
|
}
|
|
|
|
nsresult
|
|
RangeUpdater::WillReplaceContainer()
|
|
{
|
|
if (mLock) {
|
|
return NS_ERROR_UNEXPECTED;
|
|
}
|
|
mLock = true;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
RangeUpdater::DidReplaceContainer(Element* aOriginalNode,
|
|
Element* aNewNode)
|
|
{
|
|
NS_ENSURE_TRUE(mLock, NS_ERROR_UNEXPECTED);
|
|
mLock = false;
|
|
|
|
NS_ENSURE_TRUE(aOriginalNode && aNewNode, NS_ERROR_NULL_POINTER);
|
|
size_t count = mArray.Length();
|
|
if (!count) {
|
|
return NS_OK;
|
|
}
|
|
|
|
for (size_t i = 0; i < count; i++) {
|
|
RangeItem* item = mArray[i];
|
|
NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER);
|
|
|
|
if (item->mStartContainer == aOriginalNode) {
|
|
item->mStartContainer = aNewNode;
|
|
}
|
|
if (item->mEndContainer == aOriginalNode) {
|
|
item->mEndContainer = aNewNode;
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
RangeUpdater::WillRemoveContainer()
|
|
{
|
|
if (mLock) {
|
|
return NS_ERROR_UNEXPECTED;
|
|
}
|
|
mLock = true;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
RangeUpdater::DidRemoveContainer(nsINode* aNode,
|
|
nsINode* aParent,
|
|
int32_t aOffset,
|
|
uint32_t aNodeOrigLen)
|
|
{
|
|
NS_ENSURE_TRUE(mLock, NS_ERROR_UNEXPECTED);
|
|
mLock = false;
|
|
|
|
NS_ENSURE_TRUE(aNode && aParent, NS_ERROR_NULL_POINTER);
|
|
size_t count = mArray.Length();
|
|
if (!count) {
|
|
return NS_OK;
|
|
}
|
|
|
|
for (size_t i = 0; i < count; i++) {
|
|
RangeItem* item = mArray[i];
|
|
NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER);
|
|
|
|
if (item->mStartContainer == aNode) {
|
|
item->mStartContainer = aParent;
|
|
item->mStartOffset += aOffset;
|
|
} else if (item->mStartContainer == aParent &&
|
|
item->mStartOffset > aOffset) {
|
|
item->mStartOffset += (int32_t)aNodeOrigLen - 1;
|
|
}
|
|
|
|
if (item->mEndContainer == aNode) {
|
|
item->mEndContainer = aParent;
|
|
item->mEndOffset += aOffset;
|
|
} else if (item->mEndContainer == aParent && item->mEndOffset > aOffset) {
|
|
item->mEndOffset += (int32_t)aNodeOrigLen - 1;
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
RangeUpdater::DidRemoveContainer(nsIDOMNode* aNode,
|
|
nsIDOMNode* aParent,
|
|
int32_t aOffset,
|
|
uint32_t aNodeOrigLen)
|
|
{
|
|
nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
|
|
nsCOMPtr<nsINode> parent = do_QueryInterface(aParent);
|
|
return DidRemoveContainer(node, parent, aOffset, aNodeOrigLen);
|
|
}
|
|
|
|
nsresult
|
|
RangeUpdater::WillInsertContainer()
|
|
{
|
|
if (mLock) {
|
|
return NS_ERROR_UNEXPECTED;
|
|
}
|
|
mLock = true;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
RangeUpdater::DidInsertContainer()
|
|
{
|
|
NS_ENSURE_TRUE(mLock, NS_ERROR_UNEXPECTED);
|
|
mLock = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
void
|
|
RangeUpdater::WillMoveNode()
|
|
{
|
|
mLock = true;
|
|
}
|
|
|
|
void
|
|
RangeUpdater::DidMoveNode(nsINode* aOldParent, int32_t aOldOffset,
|
|
nsINode* aNewParent, int32_t aNewOffset)
|
|
{
|
|
MOZ_ASSERT(aOldParent);
|
|
MOZ_ASSERT(aNewParent);
|
|
NS_ENSURE_TRUE_VOID(mLock);
|
|
mLock = false;
|
|
|
|
for (size_t i = 0, count = mArray.Length(); i < count; ++i) {
|
|
RangeItem* item = mArray[i];
|
|
NS_ENSURE_TRUE_VOID(item);
|
|
|
|
// like a delete in aOldParent
|
|
if (item->mStartContainer == aOldParent &&
|
|
item->mStartOffset > aOldOffset) {
|
|
item->mStartOffset--;
|
|
}
|
|
if (item->mEndContainer == aOldParent && item->mEndOffset > aOldOffset) {
|
|
item->mEndOffset--;
|
|
}
|
|
|
|
// and like an insert in aNewParent
|
|
if (item->mStartContainer == aNewParent &&
|
|
item->mStartOffset > aNewOffset) {
|
|
item->mStartOffset++;
|
|
}
|
|
if (item->mEndContainer == aNewParent && item->mEndOffset > aNewOffset) {
|
|
item->mEndOffset++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************************************************************
|
|
* mozilla::RangeItem
|
|
*
|
|
* Helper struct for SelectionState. This stores range endpoints.
|
|
******************************************************************************/
|
|
|
|
RangeItem::RangeItem()
|
|
{
|
|
}
|
|
|
|
RangeItem::~RangeItem()
|
|
{
|
|
}
|
|
|
|
NS_IMPL_CYCLE_COLLECTION(RangeItem, mStartContainer, mEndContainer)
|
|
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(RangeItem, AddRef)
|
|
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(RangeItem, Release)
|
|
|
|
void
|
|
RangeItem::StoreRange(nsRange* aRange)
|
|
{
|
|
MOZ_ASSERT(aRange);
|
|
mStartContainer = aRange->GetStartContainer();
|
|
mStartOffset = aRange->StartOffset();
|
|
mEndContainer = aRange->GetEndContainer();
|
|
mEndOffset = aRange->EndOffset();
|
|
}
|
|
|
|
already_AddRefed<nsRange>
|
|
RangeItem::GetRange()
|
|
{
|
|
RefPtr<nsRange> range = new nsRange(mStartContainer);
|
|
if (NS_FAILED(range->SetStartAndEnd(mStartContainer, mStartOffset,
|
|
mEndContainer, mEndOffset))) {
|
|
return nullptr;
|
|
}
|
|
return range.forget();
|
|
}
|
|
|
|
} // namespace mozilla
|