зеркало из https://github.com/mozilla/pjs.git
More range gravity work
This commit is contained in:
Родитель
fef94f10f9
Коммит
642ddb05ae
|
@ -584,7 +584,6 @@ nsGenericElement::nsGenericElement()
|
|||
mContent = nsnull;
|
||||
mDOMSlots = nsnull;
|
||||
mListenerManager = nsnull;
|
||||
mRangeList = nsnull;
|
||||
}
|
||||
|
||||
nsGenericElement::~nsGenericElement()
|
||||
|
@ -595,6 +594,7 @@ nsGenericElement::~nsGenericElement()
|
|||
if (nsnull != mDOMSlots->mChildNodes) {
|
||||
mDOMSlots->mChildNodes->DropReference();
|
||||
NS_RELEASE(mDOMSlots->mChildNodes);
|
||||
delete mDOMSlots->mRangeList;
|
||||
}
|
||||
if (nsnull != mDOMSlots->mStyle) {
|
||||
mDOMSlots->mStyle->DropReference();
|
||||
|
@ -603,7 +603,6 @@ nsGenericElement::~nsGenericElement()
|
|||
// XXX Should really be arena managed
|
||||
PR_DELETE(mDOMSlots);
|
||||
}
|
||||
delete mRangeList;
|
||||
}
|
||||
|
||||
nsDOMSlots *
|
||||
|
@ -614,6 +613,7 @@ nsGenericElement::GetDOMSlots()
|
|||
mDOMSlots->mScriptObject = nsnull;
|
||||
mDOMSlots->mChildNodes = nsnull;
|
||||
mDOMSlots->mStyle = nsnull;
|
||||
mDOMSlots->mRangeList = nsnull;
|
||||
}
|
||||
|
||||
return mDOMSlots;
|
||||
|
@ -1008,15 +1008,16 @@ nsGenericElement::HandleDOMEvent(nsIPresContext& aPresContext,
|
|||
nsresult
|
||||
nsGenericElement::RangeAdd(nsIDOMRange& aRange)
|
||||
{
|
||||
if (nsnull == mDOMSlots) GetDOMSlots();
|
||||
// lazy allocation of range list
|
||||
if (nsnull == mRangeList) {
|
||||
mRangeList = new nsVoidArray();
|
||||
if (nsnull == mDOMSlots->mRangeList) {
|
||||
mDOMSlots->mRangeList = new nsVoidArray();
|
||||
}
|
||||
if (nsnull == mRangeList) {
|
||||
if (nsnull == mDOMSlots->mRangeList) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
// dont need to addref - this call is made by the range object itself
|
||||
PRBool rv = mRangeList->AppendElement(&aRange);
|
||||
PRBool rv = mDOMSlots->mRangeList->AppendElement(&aRange);
|
||||
if (rv) return NS_OK;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -1025,14 +1026,37 @@ nsGenericElement::RangeAdd(nsIDOMRange& aRange)
|
|||
nsresult
|
||||
nsGenericElement::RangeRemove(nsIDOMRange& aRange)
|
||||
{
|
||||
if (mRangeList) {
|
||||
if (mDOMSlots && mDOMSlots->mRangeList) {
|
||||
// dont need to release - this call is made by the range object itself
|
||||
PRBool rv = mRangeList->RemoveElement(&aRange);
|
||||
if (rv) return NS_OK;
|
||||
PRBool rv = mDOMSlots->mRangeList->RemoveElement(&aRange);
|
||||
if (rv) {
|
||||
if (mDOMSlots->mRangeList->Count() == 0) {
|
||||
delete mDOMSlots->mRangeList;
|
||||
if ( (mDOMSlots->mScriptObject == nsnull) &&
|
||||
(mDOMSlots->mChildNodes == nsnull) &&
|
||||
(mDOMSlots->mStyle == nsnull) ) {
|
||||
PR_DELETE(mDOMSlots);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsGenericElement::GetRangeList(nsVoidArray*& aResult) const
|
||||
{
|
||||
if (mDOMSlots && mDOMSlots->mRangeList) {
|
||||
aResult = mDOMSlots->mRangeList;
|
||||
}
|
||||
else {
|
||||
aResult = nsnull;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -154,6 +154,7 @@ typedef struct {
|
|||
void *mScriptObject;
|
||||
nsChildContentList *mChildNodes;
|
||||
nsDOMCSSDeclaration *mStyle;
|
||||
nsVoidArray *mRangeList;
|
||||
PRBool mIsContainer;
|
||||
} nsDOMSlots;
|
||||
|
||||
|
@ -217,7 +218,8 @@ public:
|
|||
nsEventStatus& aEventStatus);
|
||||
nsresult RangeAdd(nsIDOMRange& aRange);
|
||||
nsresult RangeRemove(nsIDOMRange& aRange);
|
||||
|
||||
nsresult GetRangeList(nsVoidArray*& aResult) const;
|
||||
|
||||
// Implementation for nsIJSScriptObject
|
||||
PRBool AddProperty(JSContext *aContext, jsval aID, jsval *aVp);
|
||||
PRBool DeleteProperty(JSContext *aContext, jsval aID, jsval *aVp);
|
||||
|
@ -269,7 +271,6 @@ public:
|
|||
nsIAtom* mTag;
|
||||
nsIEventListenerManager* mListenerManager;
|
||||
nsDOMSlots *mDOMSlots;
|
||||
nsVoidArray *mRangeList;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -532,12 +533,16 @@ public:
|
|||
nsIDOMEvent** aDOMEvent, \
|
||||
PRUint32 aFlags, \
|
||||
nsEventStatus& aEventStatus); \
|
||||
NS_IMETHOD RangeAdd(nsIDOMRange& aRange){ \
|
||||
NS_IMETHOD RangeAdd(nsIDOMRange& aRange) { \
|
||||
return _g.RangeAdd(aRange); \
|
||||
} \
|
||||
NS_IMETHOD RangeRemove(nsIDOMRange& aRange){ \
|
||||
NS_IMETHOD RangeRemove(nsIDOMRange& aRange) { \
|
||||
return _g.RangeRemove(aRange); \
|
||||
} \
|
||||
NS_IMETHOD GetRangeList(nsVoidArray*& aResult) const { \
|
||||
return _g.GetRangeList(aResult); \
|
||||
}
|
||||
|
||||
|
||||
#define NS_IMPL_CONTENT_QUERY_INTERFACE(_id, _iptr, _this, _base) \
|
||||
if (_id.Equals(kISupportsIID)) { \
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
* nsRange.cpp: Implementation of the nsIDOMRange object.
|
||||
*/
|
||||
|
||||
#include "nsRange.h"
|
||||
|
||||
#include "nsIDOMRange.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
|
@ -28,107 +30,17 @@
|
|||
#include "nsVoidArray.h"
|
||||
#include "nsIDOMText.h"
|
||||
#include "nsContentIterator.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
static NS_DEFINE_IID(kIRangeIID, NS_IDOMRANGE_IID);
|
||||
static NS_DEFINE_IID(kIContentIID, NS_ICONTENT_IID);
|
||||
static NS_DEFINE_IID(kIDOMTextIID, NS_IDOMTEXT_IID);
|
||||
|
||||
class nsRange : public nsIDOMRange
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsRange();
|
||||
virtual ~nsRange();
|
||||
|
||||
// IsPositioned attribute disappeared from the dom spec
|
||||
NS_IMETHOD GetIsPositioned(PRBool* aIsPositioned);
|
||||
|
||||
NS_IMETHOD GetStartParent(nsIDOMNode** aStartParent);
|
||||
NS_IMETHOD GetStartOffset(PRInt32* aStartOffset);
|
||||
|
||||
NS_IMETHOD GetEndParent(nsIDOMNode** aEndParent);
|
||||
NS_IMETHOD GetEndOffset(PRInt32* aEndOffset);
|
||||
|
||||
NS_IMETHOD GetIsCollapsed(PRBool* aIsCollapsed);
|
||||
|
||||
NS_IMETHOD GetCommonParent(nsIDOMNode** aCommonParent);
|
||||
|
||||
NS_IMETHOD SetStart(nsIDOMNode* aParent, PRInt32 aOffset);
|
||||
NS_IMETHOD SetStartBefore(nsIDOMNode* aSibling);
|
||||
NS_IMETHOD SetStartAfter(nsIDOMNode* aSibling);
|
||||
|
||||
NS_IMETHOD SetEnd(nsIDOMNode* aParent, PRInt32 aOffset);
|
||||
NS_IMETHOD SetEndBefore(nsIDOMNode* aSibling);
|
||||
NS_IMETHOD SetEndAfter(nsIDOMNode* aSibling);
|
||||
|
||||
NS_IMETHOD Collapse(PRBool aToStart);
|
||||
|
||||
NS_IMETHOD Unposition();
|
||||
|
||||
NS_IMETHOD SelectNode(nsIDOMNode* aN);
|
||||
NS_IMETHOD SelectNodeContents(nsIDOMNode* aN);
|
||||
|
||||
NS_IMETHOD CompareEndPoints(PRUint16 how, nsIDOMRange* srcRange, PRInt32* ret);
|
||||
|
||||
NS_IMETHOD DeleteContents();
|
||||
|
||||
NS_IMETHOD ExtractContents(nsIDOMDocumentFragment** aReturn);
|
||||
NS_IMETHOD CloneContents(nsIDOMDocumentFragment** aReturn);
|
||||
|
||||
NS_IMETHOD InsertNode(nsIDOMNode* aN);
|
||||
NS_IMETHOD SurroundContents(nsIDOMNode* aN);
|
||||
|
||||
NS_IMETHOD Clone(nsIDOMRange** aReturn);
|
||||
|
||||
NS_IMETHOD ToString(nsString& aReturn);
|
||||
|
||||
private:
|
||||
PRBool mIsPositioned;
|
||||
nsIDOMNode *mStartParent;
|
||||
nsIDOMNode *mEndParent;
|
||||
PRInt32 mStartOffset;
|
||||
PRInt32 mEndOffset;
|
||||
nsVoidArray *mStartAncestors; // just keeping these around to avoid reallocing the arrays.
|
||||
nsVoidArray *mEndAncestors; // the contents of these arrays are discarded across calls.
|
||||
nsVoidArray *mStartAncestorOffsets; //
|
||||
nsVoidArray *mEndAncestorOffsets; //
|
||||
|
||||
// no copy's or assigns
|
||||
nsRange(const nsRange&);
|
||||
nsRange& operator=(const nsRange&);
|
||||
|
||||
// helper routines
|
||||
|
||||
static PRBool InSameDoc(nsIDOMNode* aNode1, nsIDOMNode* aNode2);
|
||||
static PRInt32 IndexOf(nsIDOMNode* aNode);
|
||||
static PRInt32 FillArrayWithAncestors(nsVoidArray* aArray,nsIDOMNode* aNode);
|
||||
static nsIDOMNode* CommonParent(nsIDOMNode* aNode1, nsIDOMNode* aNode2);
|
||||
|
||||
static nsresult CloneSibsAndParents(nsIDOMNode* parentNode,
|
||||
PRInt32 nodeOffset,
|
||||
nsIDOMNode* clonedNode,
|
||||
nsIDOMNode* commonParent,
|
||||
nsIDOMDocumentFragment* docfrag,
|
||||
PRBool leftP);
|
||||
|
||||
nsresult DoSetRange(nsIDOMNode* aStartN, PRInt32 aStartOffset,
|
||||
nsIDOMNode* aEndN, PRInt32 aEndOffset);
|
||||
|
||||
PRBool IsIncreasing(nsIDOMNode* aStartN, PRInt32 aStartOff,
|
||||
nsIDOMNode* aEndN, PRInt32 aEndOff);
|
||||
|
||||
nsresult IsPointInRange(nsIDOMNode* aParent, PRInt32 aOffset, PRBool* aResult);
|
||||
|
||||
nsresult ComparePointToRange(nsIDOMNode* aParent, PRInt32 aOffset, PRInt32* aResult);
|
||||
|
||||
|
||||
PRInt32 GetAncestorsAndOffsets(nsIDOMNode* aNode, PRInt32 aOffset,
|
||||
nsVoidArray* aAncestorNodes, nsVoidArray* aAncestorOffsets);
|
||||
|
||||
|
||||
};
|
||||
/******************************************************
|
||||
* non members
|
||||
******************************************************/
|
||||
|
||||
nsresult
|
||||
NS_NewRange(nsIDOMRange** aInstancePtrResult)
|
||||
|
@ -137,6 +49,27 @@ NS_NewRange(nsIDOMRange** aInstancePtrResult)
|
|||
return range->QueryInterface(kIRangeIID, (void**) aInstancePtrResult);
|
||||
}
|
||||
|
||||
|
||||
// Returns -1 if point1 < point2, 1, if point1 > point2,
|
||||
// 0 if error or if point1 == point2.
|
||||
PRInt32 ComparePoints(nsIDOMNode* aParent1, PRInt32 aOffset1,
|
||||
nsIDOMNode* aParent2, PRInt32 aOffset2)
|
||||
{
|
||||
if (aParent1 == aParent2 && aOffset1 == aOffset2)
|
||||
return 0;
|
||||
nsRange* range = new nsRange;
|
||||
nsresult res = range->SetStart(aParent1, aOffset1);
|
||||
if (!NS_SUCCEEDED(res))
|
||||
return 0;
|
||||
res = range->SetEnd(aParent2, aOffset2);
|
||||
delete range;
|
||||
if (NS_SUCCEEDED(res))
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************
|
||||
* constructor/destructor
|
||||
******************************************************/
|
||||
|
@ -158,6 +91,7 @@ nsRange::nsRange()
|
|||
|
||||
nsRange::~nsRange()
|
||||
{
|
||||
DoSetRange(nsnull,0,nsnull,0); // we want the side effects (releases and list removals)
|
||||
delete mStartAncestors;
|
||||
delete mEndAncestors;
|
||||
delete mStartAncestorOffsets;
|
||||
|
@ -192,31 +126,6 @@ nsresult nsRange::QueryInterface(const nsIID& aIID,
|
|||
}
|
||||
|
||||
|
||||
/******************************************************
|
||||
* Public helper routines
|
||||
******************************************************/
|
||||
|
||||
//
|
||||
// Returns -1 if point1 < point2, 1, if point1 > point2,
|
||||
// 0 if error or if point1 == point2.
|
||||
//
|
||||
PRInt32 ComparePoints(nsIDOMNode* aParent1, PRInt32 aOffset1,
|
||||
nsIDOMNode* aParent2, PRInt32 aOffset2)
|
||||
{
|
||||
if (aParent1 == aParent2 && aOffset1 == aOffset2)
|
||||
return 0;
|
||||
nsRange* range = new nsRange;
|
||||
nsresult res = range->SetStart(aParent1, aOffset1);
|
||||
if (!NS_SUCCEEDED(res))
|
||||
return 0;
|
||||
res = range->SetEnd(aParent2, aOffset2);
|
||||
delete range;
|
||||
if (NS_SUCCEEDED(res))
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
/******************************************************
|
||||
* Private helper routines
|
||||
******************************************************/
|
||||
|
@ -248,25 +157,94 @@ PRBool nsRange::InSameDoc(nsIDOMNode* aNode1, nsIDOMNode* aNode2)
|
|||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
nsresult nsRange::AddToListOf(nsIDOMNode* aNode)
|
||||
{
|
||||
if (!aNode)
|
||||
{
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
nsIContent *cN;
|
||||
|
||||
nsresult res = aNode->QueryInterface(kIContentIID, (void**)&cN);
|
||||
if (!NS_SUCCEEDED(res))
|
||||
{
|
||||
NS_NOTREACHED("nsRange::AddToListOf");
|
||||
NS_IF_RELEASE(cN);
|
||||
return res;
|
||||
}
|
||||
|
||||
res = cN->RangeAdd(NS_STATIC_CAST(nsIDOMRange,*this));
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
nsresult nsRange::RemoveFromListOf(nsIDOMNode* aNode)
|
||||
{
|
||||
if (!aNode)
|
||||
{
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
nsIContent *cN;
|
||||
|
||||
nsresult res = aNode->QueryInterface(kIContentIID, (void**)&cN);
|
||||
if (!NS_SUCCEEDED(res))
|
||||
{
|
||||
NS_NOTREACHED("nsRange::RemoveFromListOf");
|
||||
NS_IF_RELEASE(cN);
|
||||
return res;
|
||||
}
|
||||
|
||||
res = cN->RangeRemove(NS_STATIC_CAST(nsIDOMRange,*this));
|
||||
return res;
|
||||
}
|
||||
|
||||
// It's important that all setting of the range start/end pionts
|
||||
// go through this function, which will do all the right voodoo
|
||||
// for both refcounting and content notification of range ownership
|
||||
nsresult nsRange::DoSetRange(nsIDOMNode* aStartN, PRInt32 aStartOffset,
|
||||
nsIDOMNode* aEndN, PRInt32 aEndOffset)
|
||||
{
|
||||
if (mStartParent != aStartN)
|
||||
{
|
||||
NS_IF_RELEASE(mStartParent);
|
||||
if (mStartParent) // if it had a former start node, take it off it's list
|
||||
{
|
||||
RemoveFromListOf(mStartParent);
|
||||
NS_RELEASE(mStartParent);
|
||||
}
|
||||
mStartParent = aStartN;
|
||||
NS_ADDREF(mStartParent);
|
||||
if (mStartParent) // if it has a new start node, put it on it's list
|
||||
{
|
||||
AddToListOf(mStartParent);
|
||||
NS_ADDREF(mStartParent);
|
||||
}
|
||||
}
|
||||
mStartOffset = aStartOffset;
|
||||
|
||||
if (mEndParent != aEndN)
|
||||
{
|
||||
NS_IF_RELEASE(mEndParent);
|
||||
if (mEndParent) // if it had a former end node, take it off it's list
|
||||
{
|
||||
RemoveFromListOf(mEndParent);
|
||||
NS_RELEASE(mEndParent);
|
||||
}
|
||||
mEndParent = aEndN;
|
||||
NS_ADDREF(mEndParent);
|
||||
if (mEndParent) // if it has a new end node, put it on it's list
|
||||
{
|
||||
AddToListOf(mEndParent);
|
||||
NS_ADDREF(mEndParent);
|
||||
}
|
||||
}
|
||||
mEndOffset = aEndOffset;
|
||||
|
||||
if (mStartParent) mIsPositioned = PR_TRUE;
|
||||
else mIsPositioned = PR_FALSE;
|
||||
|
||||
// FIX ME need to handle error cases
|
||||
// (range lists return error, or setting only one endpoint to null)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -717,31 +695,17 @@ nsresult nsRange::Collapse(PRBool aToStart)
|
|||
|
||||
if (aToStart)
|
||||
{
|
||||
NS_IF_RELEASE(mEndParent);
|
||||
NS_IF_ADDREF(mStartParent);
|
||||
mEndParent = mStartParent;
|
||||
mEndOffset = mStartOffset;
|
||||
return NS_OK;
|
||||
return DoSetRange(mStartParent,mStartOffset,mStartParent,mStartOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_IF_RELEASE(mStartParent);
|
||||
NS_IF_ADDREF(mEndParent);
|
||||
mStartParent = mEndParent;
|
||||
mStartOffset = mEndOffset;
|
||||
return NS_OK;
|
||||
return DoSetRange(mEndParent,mEndOffset,mEndParent,mEndOffset);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult nsRange::Unposition()
|
||||
{
|
||||
NS_IF_RELEASE(mStartParent);
|
||||
mStartParent = nsnull;
|
||||
mStartOffset = 0;
|
||||
NS_IF_RELEASE(mEndParent);
|
||||
mEndParent = nsnull;
|
||||
mEndOffset = 0;
|
||||
mIsPositioned = PR_FALSE;
|
||||
return DoSetRange(nsnull,0,nsnull,0);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -752,29 +716,24 @@ nsresult nsRange::SelectNode(nsIDOMNode* aN)
|
|||
if (!NS_SUCCEEDED(res))
|
||||
return res;
|
||||
|
||||
if (mIsPositioned)
|
||||
Unposition();
|
||||
NS_IF_ADDREF(parent);
|
||||
mStartParent = parent;
|
||||
mStartOffset = 0; // XXX NO DIRECT WAY TO GET CHILD # OF THIS NODE!
|
||||
NS_IF_ADDREF(parent);
|
||||
mEndParent = parent;
|
||||
mEndOffset = mStartOffset;
|
||||
return NS_OK;
|
||||
PRInt32 indx = IndexOf(aN);
|
||||
return DoSetRange(parent,indx,parent,indx+1);
|
||||
}
|
||||
|
||||
nsresult nsRange::SelectNodeContents(nsIDOMNode* aN)
|
||||
{
|
||||
if (mIsPositioned)
|
||||
Unposition();
|
||||
|
||||
NS_IF_ADDREF(aN);
|
||||
mStartParent = aN;
|
||||
mStartOffset = 0;
|
||||
NS_IF_ADDREF(aN);
|
||||
mEndParent = aN;
|
||||
mEndOffset = 0; // WRONG! SHOULD BE # OF LAST CHILD!
|
||||
return NS_OK;
|
||||
nsIDOMNodeList *aChildNodes;
|
||||
nsresult res = aN->GetChildNodes(&aChildNodes);
|
||||
if (!NS_SUCCEEDED(res))
|
||||
return res;
|
||||
if (aChildNodes==nsnull)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
PRUint32 indx;
|
||||
res = aChildNodes->GetLength(&indx);
|
||||
NS_RELEASE(aChildNodes);
|
||||
if (!NS_SUCCEEDED(res))
|
||||
return res;
|
||||
return DoSetRange(aN,0,aN,indx);
|
||||
}
|
||||
|
||||
nsresult nsRange::DeleteContents()
|
||||
|
@ -1077,6 +1036,8 @@ nsRange::CloneSibsAndParents(nsIDOMNode* parentNode, PRInt32 nodeOffset,
|
|||
// XXX This is fine for left children but it will include too much
|
||||
// XXX instead of stopping at the left children of the end node.
|
||||
//
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
nsresult nsRange::CloneContents(nsIDOMDocumentFragment** aReturn)
|
||||
|
|
|
@ -17,10 +17,118 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* nsRange.h : Useful routines for users of nsRange objects.
|
||||
* This doesn't include the definition of the nsRange class itself,
|
||||
* since range users should always get their ranges via nsIDOMRange.
|
||||
* nsRange.h: interface of the nsRange object.
|
||||
*/
|
||||
|
||||
#include "nsIDOMRange.h"
|
||||
|
||||
class nsIDOMNode;
|
||||
class nsIDOMDocumentFragment;
|
||||
class nsVoidArray;
|
||||
|
||||
class nsRange : public nsIDOMRange
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsRange();
|
||||
virtual ~nsRange();
|
||||
|
||||
// IsPositioned attribute disappeared from the dom spec
|
||||
NS_IMETHOD GetIsPositioned(PRBool* aIsPositioned);
|
||||
|
||||
NS_IMETHOD GetStartParent(nsIDOMNode** aStartParent);
|
||||
NS_IMETHOD GetStartOffset(PRInt32* aStartOffset);
|
||||
|
||||
NS_IMETHOD GetEndParent(nsIDOMNode** aEndParent);
|
||||
NS_IMETHOD GetEndOffset(PRInt32* aEndOffset);
|
||||
|
||||
NS_IMETHOD GetIsCollapsed(PRBool* aIsCollapsed);
|
||||
|
||||
NS_IMETHOD GetCommonParent(nsIDOMNode** aCommonParent);
|
||||
|
||||
NS_IMETHOD SetStart(nsIDOMNode* aParent, PRInt32 aOffset);
|
||||
NS_IMETHOD SetStartBefore(nsIDOMNode* aSibling);
|
||||
NS_IMETHOD SetStartAfter(nsIDOMNode* aSibling);
|
||||
|
||||
NS_IMETHOD SetEnd(nsIDOMNode* aParent, PRInt32 aOffset);
|
||||
NS_IMETHOD SetEndBefore(nsIDOMNode* aSibling);
|
||||
NS_IMETHOD SetEndAfter(nsIDOMNode* aSibling);
|
||||
|
||||
NS_IMETHOD Collapse(PRBool aToStart);
|
||||
|
||||
NS_IMETHOD Unposition();
|
||||
|
||||
NS_IMETHOD SelectNode(nsIDOMNode* aN);
|
||||
NS_IMETHOD SelectNodeContents(nsIDOMNode* aN);
|
||||
|
||||
NS_IMETHOD CompareEndPoints(PRUint16 how, nsIDOMRange* srcRange, PRInt32* ret);
|
||||
|
||||
NS_IMETHOD DeleteContents();
|
||||
|
||||
NS_IMETHOD ExtractContents(nsIDOMDocumentFragment** aReturn);
|
||||
NS_IMETHOD CloneContents(nsIDOMDocumentFragment** aReturn);
|
||||
|
||||
NS_IMETHOD InsertNode(nsIDOMNode* aN);
|
||||
NS_IMETHOD SurroundContents(nsIDOMNode* aN);
|
||||
|
||||
NS_IMETHOD Clone(nsIDOMRange** aReturn);
|
||||
|
||||
NS_IMETHOD ToString(nsString& aReturn);
|
||||
|
||||
|
||||
private:
|
||||
PRBool mIsPositioned;
|
||||
nsIDOMNode *mStartParent;
|
||||
nsIDOMNode *mEndParent;
|
||||
PRInt32 mStartOffset;
|
||||
PRInt32 mEndOffset;
|
||||
nsVoidArray *mStartAncestors; // just keeping these around to avoid reallocing the arrays.
|
||||
nsVoidArray *mEndAncestors; // the contents of these arrays are discarded across calls.
|
||||
nsVoidArray *mStartAncestorOffsets; //
|
||||
nsVoidArray *mEndAncestorOffsets; //
|
||||
|
||||
// no copy's or assigns
|
||||
nsRange(const nsRange&);
|
||||
nsRange& operator=(const nsRange&);
|
||||
|
||||
// helper routines
|
||||
|
||||
static PRBool InSameDoc(nsIDOMNode* aNode1, nsIDOMNode* aNode2);
|
||||
static PRInt32 IndexOf(nsIDOMNode* aNode);
|
||||
static PRInt32 FillArrayWithAncestors(nsVoidArray* aArray,nsIDOMNode* aNode);
|
||||
static nsIDOMNode* CommonParent(nsIDOMNode* aNode1, nsIDOMNode* aNode2);
|
||||
|
||||
static nsresult CloneSibsAndParents(nsIDOMNode* parentNode,
|
||||
PRInt32 nodeOffset,
|
||||
nsIDOMNode* clonedNode,
|
||||
nsIDOMNode* commonParent,
|
||||
nsIDOMDocumentFragment* docfrag,
|
||||
PRBool leftP);
|
||||
|
||||
nsresult DoSetRange(nsIDOMNode* aStartN, PRInt32 aStartOffset,
|
||||
nsIDOMNode* aEndN, PRInt32 aEndOffset);
|
||||
|
||||
PRBool IsIncreasing(nsIDOMNode* aStartN, PRInt32 aStartOff,
|
||||
nsIDOMNode* aEndN, PRInt32 aEndOff);
|
||||
|
||||
nsresult IsPointInRange(nsIDOMNode* aParent, PRInt32 aOffset, PRBool* aResult);
|
||||
|
||||
nsresult ComparePointToRange(nsIDOMNode* aParent, PRInt32 aOffset, PRInt32* aResult);
|
||||
|
||||
|
||||
PRInt32 GetAncestorsAndOffsets(nsIDOMNode* aNode, PRInt32 aOffset,
|
||||
nsVoidArray* aAncestorNodes, nsVoidArray* aAncestorOffsets);
|
||||
|
||||
nsresult AddToListOf(nsIDOMNode* aNode);
|
||||
|
||||
nsresult RemoveFromListOf(nsIDOMNode* aNode);
|
||||
|
||||
};
|
||||
|
||||
// Make a new nsIDOMRange object
|
||||
nsresult NS_NewRange(nsIDOMRange** aInstancePtrResult);
|
||||
|
||||
// Utility routine to compare two "points", were a point is a node/offset pair
|
||||
PRInt32 ComparePoints(nsIDOMNode* aParent1, PRInt32 aOffset1,
|
||||
nsIDOMNode* aParent2, PRInt32 aOffset2);
|
||||
|
|
|
@ -584,7 +584,6 @@ nsGenericElement::nsGenericElement()
|
|||
mContent = nsnull;
|
||||
mDOMSlots = nsnull;
|
||||
mListenerManager = nsnull;
|
||||
mRangeList = nsnull;
|
||||
}
|
||||
|
||||
nsGenericElement::~nsGenericElement()
|
||||
|
@ -595,6 +594,7 @@ nsGenericElement::~nsGenericElement()
|
|||
if (nsnull != mDOMSlots->mChildNodes) {
|
||||
mDOMSlots->mChildNodes->DropReference();
|
||||
NS_RELEASE(mDOMSlots->mChildNodes);
|
||||
delete mDOMSlots->mRangeList;
|
||||
}
|
||||
if (nsnull != mDOMSlots->mStyle) {
|
||||
mDOMSlots->mStyle->DropReference();
|
||||
|
@ -603,7 +603,6 @@ nsGenericElement::~nsGenericElement()
|
|||
// XXX Should really be arena managed
|
||||
PR_DELETE(mDOMSlots);
|
||||
}
|
||||
delete mRangeList;
|
||||
}
|
||||
|
||||
nsDOMSlots *
|
||||
|
@ -614,6 +613,7 @@ nsGenericElement::GetDOMSlots()
|
|||
mDOMSlots->mScriptObject = nsnull;
|
||||
mDOMSlots->mChildNodes = nsnull;
|
||||
mDOMSlots->mStyle = nsnull;
|
||||
mDOMSlots->mRangeList = nsnull;
|
||||
}
|
||||
|
||||
return mDOMSlots;
|
||||
|
@ -1008,15 +1008,16 @@ nsGenericElement::HandleDOMEvent(nsIPresContext& aPresContext,
|
|||
nsresult
|
||||
nsGenericElement::RangeAdd(nsIDOMRange& aRange)
|
||||
{
|
||||
if (nsnull == mDOMSlots) GetDOMSlots();
|
||||
// lazy allocation of range list
|
||||
if (nsnull == mRangeList) {
|
||||
mRangeList = new nsVoidArray();
|
||||
if (nsnull == mDOMSlots->mRangeList) {
|
||||
mDOMSlots->mRangeList = new nsVoidArray();
|
||||
}
|
||||
if (nsnull == mRangeList) {
|
||||
if (nsnull == mDOMSlots->mRangeList) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
// dont need to addref - this call is made by the range object itself
|
||||
PRBool rv = mRangeList->AppendElement(&aRange);
|
||||
PRBool rv = mDOMSlots->mRangeList->AppendElement(&aRange);
|
||||
if (rv) return NS_OK;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -1025,14 +1026,37 @@ nsGenericElement::RangeAdd(nsIDOMRange& aRange)
|
|||
nsresult
|
||||
nsGenericElement::RangeRemove(nsIDOMRange& aRange)
|
||||
{
|
||||
if (mRangeList) {
|
||||
if (mDOMSlots && mDOMSlots->mRangeList) {
|
||||
// dont need to release - this call is made by the range object itself
|
||||
PRBool rv = mRangeList->RemoveElement(&aRange);
|
||||
if (rv) return NS_OK;
|
||||
PRBool rv = mDOMSlots->mRangeList->RemoveElement(&aRange);
|
||||
if (rv) {
|
||||
if (mDOMSlots->mRangeList->Count() == 0) {
|
||||
delete mDOMSlots->mRangeList;
|
||||
if ( (mDOMSlots->mScriptObject == nsnull) &&
|
||||
(mDOMSlots->mChildNodes == nsnull) &&
|
||||
(mDOMSlots->mStyle == nsnull) ) {
|
||||
PR_DELETE(mDOMSlots);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsGenericElement::GetRangeList(nsVoidArray*& aResult) const
|
||||
{
|
||||
if (mDOMSlots && mDOMSlots->mRangeList) {
|
||||
aResult = mDOMSlots->mRangeList;
|
||||
}
|
||||
else {
|
||||
aResult = nsnull;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -154,6 +154,7 @@ typedef struct {
|
|||
void *mScriptObject;
|
||||
nsChildContentList *mChildNodes;
|
||||
nsDOMCSSDeclaration *mStyle;
|
||||
nsVoidArray *mRangeList;
|
||||
PRBool mIsContainer;
|
||||
} nsDOMSlots;
|
||||
|
||||
|
@ -217,7 +218,8 @@ public:
|
|||
nsEventStatus& aEventStatus);
|
||||
nsresult RangeAdd(nsIDOMRange& aRange);
|
||||
nsresult RangeRemove(nsIDOMRange& aRange);
|
||||
|
||||
nsresult GetRangeList(nsVoidArray*& aResult) const;
|
||||
|
||||
// Implementation for nsIJSScriptObject
|
||||
PRBool AddProperty(JSContext *aContext, jsval aID, jsval *aVp);
|
||||
PRBool DeleteProperty(JSContext *aContext, jsval aID, jsval *aVp);
|
||||
|
@ -269,7 +271,6 @@ public:
|
|||
nsIAtom* mTag;
|
||||
nsIEventListenerManager* mListenerManager;
|
||||
nsDOMSlots *mDOMSlots;
|
||||
nsVoidArray *mRangeList;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -532,12 +533,16 @@ public:
|
|||
nsIDOMEvent** aDOMEvent, \
|
||||
PRUint32 aFlags, \
|
||||
nsEventStatus& aEventStatus); \
|
||||
NS_IMETHOD RangeAdd(nsIDOMRange& aRange){ \
|
||||
NS_IMETHOD RangeAdd(nsIDOMRange& aRange) { \
|
||||
return _g.RangeAdd(aRange); \
|
||||
} \
|
||||
NS_IMETHOD RangeRemove(nsIDOMRange& aRange){ \
|
||||
NS_IMETHOD RangeRemove(nsIDOMRange& aRange) { \
|
||||
return _g.RangeRemove(aRange); \
|
||||
} \
|
||||
NS_IMETHOD GetRangeList(nsVoidArray*& aResult) const { \
|
||||
return _g.GetRangeList(aResult); \
|
||||
}
|
||||
|
||||
|
||||
#define NS_IMPL_CONTENT_QUERY_INTERFACE(_id, _iptr, _this, _base) \
|
||||
if (_id.Equals(kISupportsIID)) { \
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
* nsRange.cpp: Implementation of the nsIDOMRange object.
|
||||
*/
|
||||
|
||||
#include "nsRange.h"
|
||||
|
||||
#include "nsIDOMRange.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
|
@ -28,107 +30,17 @@
|
|||
#include "nsVoidArray.h"
|
||||
#include "nsIDOMText.h"
|
||||
#include "nsContentIterator.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
static NS_DEFINE_IID(kIRangeIID, NS_IDOMRANGE_IID);
|
||||
static NS_DEFINE_IID(kIContentIID, NS_ICONTENT_IID);
|
||||
static NS_DEFINE_IID(kIDOMTextIID, NS_IDOMTEXT_IID);
|
||||
|
||||
class nsRange : public nsIDOMRange
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsRange();
|
||||
virtual ~nsRange();
|
||||
|
||||
// IsPositioned attribute disappeared from the dom spec
|
||||
NS_IMETHOD GetIsPositioned(PRBool* aIsPositioned);
|
||||
|
||||
NS_IMETHOD GetStartParent(nsIDOMNode** aStartParent);
|
||||
NS_IMETHOD GetStartOffset(PRInt32* aStartOffset);
|
||||
|
||||
NS_IMETHOD GetEndParent(nsIDOMNode** aEndParent);
|
||||
NS_IMETHOD GetEndOffset(PRInt32* aEndOffset);
|
||||
|
||||
NS_IMETHOD GetIsCollapsed(PRBool* aIsCollapsed);
|
||||
|
||||
NS_IMETHOD GetCommonParent(nsIDOMNode** aCommonParent);
|
||||
|
||||
NS_IMETHOD SetStart(nsIDOMNode* aParent, PRInt32 aOffset);
|
||||
NS_IMETHOD SetStartBefore(nsIDOMNode* aSibling);
|
||||
NS_IMETHOD SetStartAfter(nsIDOMNode* aSibling);
|
||||
|
||||
NS_IMETHOD SetEnd(nsIDOMNode* aParent, PRInt32 aOffset);
|
||||
NS_IMETHOD SetEndBefore(nsIDOMNode* aSibling);
|
||||
NS_IMETHOD SetEndAfter(nsIDOMNode* aSibling);
|
||||
|
||||
NS_IMETHOD Collapse(PRBool aToStart);
|
||||
|
||||
NS_IMETHOD Unposition();
|
||||
|
||||
NS_IMETHOD SelectNode(nsIDOMNode* aN);
|
||||
NS_IMETHOD SelectNodeContents(nsIDOMNode* aN);
|
||||
|
||||
NS_IMETHOD CompareEndPoints(PRUint16 how, nsIDOMRange* srcRange, PRInt32* ret);
|
||||
|
||||
NS_IMETHOD DeleteContents();
|
||||
|
||||
NS_IMETHOD ExtractContents(nsIDOMDocumentFragment** aReturn);
|
||||
NS_IMETHOD CloneContents(nsIDOMDocumentFragment** aReturn);
|
||||
|
||||
NS_IMETHOD InsertNode(nsIDOMNode* aN);
|
||||
NS_IMETHOD SurroundContents(nsIDOMNode* aN);
|
||||
|
||||
NS_IMETHOD Clone(nsIDOMRange** aReturn);
|
||||
|
||||
NS_IMETHOD ToString(nsString& aReturn);
|
||||
|
||||
private:
|
||||
PRBool mIsPositioned;
|
||||
nsIDOMNode *mStartParent;
|
||||
nsIDOMNode *mEndParent;
|
||||
PRInt32 mStartOffset;
|
||||
PRInt32 mEndOffset;
|
||||
nsVoidArray *mStartAncestors; // just keeping these around to avoid reallocing the arrays.
|
||||
nsVoidArray *mEndAncestors; // the contents of these arrays are discarded across calls.
|
||||
nsVoidArray *mStartAncestorOffsets; //
|
||||
nsVoidArray *mEndAncestorOffsets; //
|
||||
|
||||
// no copy's or assigns
|
||||
nsRange(const nsRange&);
|
||||
nsRange& operator=(const nsRange&);
|
||||
|
||||
// helper routines
|
||||
|
||||
static PRBool InSameDoc(nsIDOMNode* aNode1, nsIDOMNode* aNode2);
|
||||
static PRInt32 IndexOf(nsIDOMNode* aNode);
|
||||
static PRInt32 FillArrayWithAncestors(nsVoidArray* aArray,nsIDOMNode* aNode);
|
||||
static nsIDOMNode* CommonParent(nsIDOMNode* aNode1, nsIDOMNode* aNode2);
|
||||
|
||||
static nsresult CloneSibsAndParents(nsIDOMNode* parentNode,
|
||||
PRInt32 nodeOffset,
|
||||
nsIDOMNode* clonedNode,
|
||||
nsIDOMNode* commonParent,
|
||||
nsIDOMDocumentFragment* docfrag,
|
||||
PRBool leftP);
|
||||
|
||||
nsresult DoSetRange(nsIDOMNode* aStartN, PRInt32 aStartOffset,
|
||||
nsIDOMNode* aEndN, PRInt32 aEndOffset);
|
||||
|
||||
PRBool IsIncreasing(nsIDOMNode* aStartN, PRInt32 aStartOff,
|
||||
nsIDOMNode* aEndN, PRInt32 aEndOff);
|
||||
|
||||
nsresult IsPointInRange(nsIDOMNode* aParent, PRInt32 aOffset, PRBool* aResult);
|
||||
|
||||
nsresult ComparePointToRange(nsIDOMNode* aParent, PRInt32 aOffset, PRInt32* aResult);
|
||||
|
||||
|
||||
PRInt32 GetAncestorsAndOffsets(nsIDOMNode* aNode, PRInt32 aOffset,
|
||||
nsVoidArray* aAncestorNodes, nsVoidArray* aAncestorOffsets);
|
||||
|
||||
|
||||
};
|
||||
/******************************************************
|
||||
* non members
|
||||
******************************************************/
|
||||
|
||||
nsresult
|
||||
NS_NewRange(nsIDOMRange** aInstancePtrResult)
|
||||
|
@ -137,6 +49,27 @@ NS_NewRange(nsIDOMRange** aInstancePtrResult)
|
|||
return range->QueryInterface(kIRangeIID, (void**) aInstancePtrResult);
|
||||
}
|
||||
|
||||
|
||||
// Returns -1 if point1 < point2, 1, if point1 > point2,
|
||||
// 0 if error or if point1 == point2.
|
||||
PRInt32 ComparePoints(nsIDOMNode* aParent1, PRInt32 aOffset1,
|
||||
nsIDOMNode* aParent2, PRInt32 aOffset2)
|
||||
{
|
||||
if (aParent1 == aParent2 && aOffset1 == aOffset2)
|
||||
return 0;
|
||||
nsRange* range = new nsRange;
|
||||
nsresult res = range->SetStart(aParent1, aOffset1);
|
||||
if (!NS_SUCCEEDED(res))
|
||||
return 0;
|
||||
res = range->SetEnd(aParent2, aOffset2);
|
||||
delete range;
|
||||
if (NS_SUCCEEDED(res))
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************
|
||||
* constructor/destructor
|
||||
******************************************************/
|
||||
|
@ -158,6 +91,7 @@ nsRange::nsRange()
|
|||
|
||||
nsRange::~nsRange()
|
||||
{
|
||||
DoSetRange(nsnull,0,nsnull,0); // we want the side effects (releases and list removals)
|
||||
delete mStartAncestors;
|
||||
delete mEndAncestors;
|
||||
delete mStartAncestorOffsets;
|
||||
|
@ -192,31 +126,6 @@ nsresult nsRange::QueryInterface(const nsIID& aIID,
|
|||
}
|
||||
|
||||
|
||||
/******************************************************
|
||||
* Public helper routines
|
||||
******************************************************/
|
||||
|
||||
//
|
||||
// Returns -1 if point1 < point2, 1, if point1 > point2,
|
||||
// 0 if error or if point1 == point2.
|
||||
//
|
||||
PRInt32 ComparePoints(nsIDOMNode* aParent1, PRInt32 aOffset1,
|
||||
nsIDOMNode* aParent2, PRInt32 aOffset2)
|
||||
{
|
||||
if (aParent1 == aParent2 && aOffset1 == aOffset2)
|
||||
return 0;
|
||||
nsRange* range = new nsRange;
|
||||
nsresult res = range->SetStart(aParent1, aOffset1);
|
||||
if (!NS_SUCCEEDED(res))
|
||||
return 0;
|
||||
res = range->SetEnd(aParent2, aOffset2);
|
||||
delete range;
|
||||
if (NS_SUCCEEDED(res))
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
/******************************************************
|
||||
* Private helper routines
|
||||
******************************************************/
|
||||
|
@ -248,25 +157,94 @@ PRBool nsRange::InSameDoc(nsIDOMNode* aNode1, nsIDOMNode* aNode2)
|
|||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
nsresult nsRange::AddToListOf(nsIDOMNode* aNode)
|
||||
{
|
||||
if (!aNode)
|
||||
{
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
nsIContent *cN;
|
||||
|
||||
nsresult res = aNode->QueryInterface(kIContentIID, (void**)&cN);
|
||||
if (!NS_SUCCEEDED(res))
|
||||
{
|
||||
NS_NOTREACHED("nsRange::AddToListOf");
|
||||
NS_IF_RELEASE(cN);
|
||||
return res;
|
||||
}
|
||||
|
||||
res = cN->RangeAdd(NS_STATIC_CAST(nsIDOMRange,*this));
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
nsresult nsRange::RemoveFromListOf(nsIDOMNode* aNode)
|
||||
{
|
||||
if (!aNode)
|
||||
{
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
nsIContent *cN;
|
||||
|
||||
nsresult res = aNode->QueryInterface(kIContentIID, (void**)&cN);
|
||||
if (!NS_SUCCEEDED(res))
|
||||
{
|
||||
NS_NOTREACHED("nsRange::RemoveFromListOf");
|
||||
NS_IF_RELEASE(cN);
|
||||
return res;
|
||||
}
|
||||
|
||||
res = cN->RangeRemove(NS_STATIC_CAST(nsIDOMRange,*this));
|
||||
return res;
|
||||
}
|
||||
|
||||
// It's important that all setting of the range start/end pionts
|
||||
// go through this function, which will do all the right voodoo
|
||||
// for both refcounting and content notification of range ownership
|
||||
nsresult nsRange::DoSetRange(nsIDOMNode* aStartN, PRInt32 aStartOffset,
|
||||
nsIDOMNode* aEndN, PRInt32 aEndOffset)
|
||||
{
|
||||
if (mStartParent != aStartN)
|
||||
{
|
||||
NS_IF_RELEASE(mStartParent);
|
||||
if (mStartParent) // if it had a former start node, take it off it's list
|
||||
{
|
||||
RemoveFromListOf(mStartParent);
|
||||
NS_RELEASE(mStartParent);
|
||||
}
|
||||
mStartParent = aStartN;
|
||||
NS_ADDREF(mStartParent);
|
||||
if (mStartParent) // if it has a new start node, put it on it's list
|
||||
{
|
||||
AddToListOf(mStartParent);
|
||||
NS_ADDREF(mStartParent);
|
||||
}
|
||||
}
|
||||
mStartOffset = aStartOffset;
|
||||
|
||||
if (mEndParent != aEndN)
|
||||
{
|
||||
NS_IF_RELEASE(mEndParent);
|
||||
if (mEndParent) // if it had a former end node, take it off it's list
|
||||
{
|
||||
RemoveFromListOf(mEndParent);
|
||||
NS_RELEASE(mEndParent);
|
||||
}
|
||||
mEndParent = aEndN;
|
||||
NS_ADDREF(mEndParent);
|
||||
if (mEndParent) // if it has a new end node, put it on it's list
|
||||
{
|
||||
AddToListOf(mEndParent);
|
||||
NS_ADDREF(mEndParent);
|
||||
}
|
||||
}
|
||||
mEndOffset = aEndOffset;
|
||||
|
||||
if (mStartParent) mIsPositioned = PR_TRUE;
|
||||
else mIsPositioned = PR_FALSE;
|
||||
|
||||
// FIX ME need to handle error cases
|
||||
// (range lists return error, or setting only one endpoint to null)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -717,31 +695,17 @@ nsresult nsRange::Collapse(PRBool aToStart)
|
|||
|
||||
if (aToStart)
|
||||
{
|
||||
NS_IF_RELEASE(mEndParent);
|
||||
NS_IF_ADDREF(mStartParent);
|
||||
mEndParent = mStartParent;
|
||||
mEndOffset = mStartOffset;
|
||||
return NS_OK;
|
||||
return DoSetRange(mStartParent,mStartOffset,mStartParent,mStartOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_IF_RELEASE(mStartParent);
|
||||
NS_IF_ADDREF(mEndParent);
|
||||
mStartParent = mEndParent;
|
||||
mStartOffset = mEndOffset;
|
||||
return NS_OK;
|
||||
return DoSetRange(mEndParent,mEndOffset,mEndParent,mEndOffset);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult nsRange::Unposition()
|
||||
{
|
||||
NS_IF_RELEASE(mStartParent);
|
||||
mStartParent = nsnull;
|
||||
mStartOffset = 0;
|
||||
NS_IF_RELEASE(mEndParent);
|
||||
mEndParent = nsnull;
|
||||
mEndOffset = 0;
|
||||
mIsPositioned = PR_FALSE;
|
||||
return DoSetRange(nsnull,0,nsnull,0);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -752,29 +716,24 @@ nsresult nsRange::SelectNode(nsIDOMNode* aN)
|
|||
if (!NS_SUCCEEDED(res))
|
||||
return res;
|
||||
|
||||
if (mIsPositioned)
|
||||
Unposition();
|
||||
NS_IF_ADDREF(parent);
|
||||
mStartParent = parent;
|
||||
mStartOffset = 0; // XXX NO DIRECT WAY TO GET CHILD # OF THIS NODE!
|
||||
NS_IF_ADDREF(parent);
|
||||
mEndParent = parent;
|
||||
mEndOffset = mStartOffset;
|
||||
return NS_OK;
|
||||
PRInt32 indx = IndexOf(aN);
|
||||
return DoSetRange(parent,indx,parent,indx+1);
|
||||
}
|
||||
|
||||
nsresult nsRange::SelectNodeContents(nsIDOMNode* aN)
|
||||
{
|
||||
if (mIsPositioned)
|
||||
Unposition();
|
||||
|
||||
NS_IF_ADDREF(aN);
|
||||
mStartParent = aN;
|
||||
mStartOffset = 0;
|
||||
NS_IF_ADDREF(aN);
|
||||
mEndParent = aN;
|
||||
mEndOffset = 0; // WRONG! SHOULD BE # OF LAST CHILD!
|
||||
return NS_OK;
|
||||
nsIDOMNodeList *aChildNodes;
|
||||
nsresult res = aN->GetChildNodes(&aChildNodes);
|
||||
if (!NS_SUCCEEDED(res))
|
||||
return res;
|
||||
if (aChildNodes==nsnull)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
PRUint32 indx;
|
||||
res = aChildNodes->GetLength(&indx);
|
||||
NS_RELEASE(aChildNodes);
|
||||
if (!NS_SUCCEEDED(res))
|
||||
return res;
|
||||
return DoSetRange(aN,0,aN,indx);
|
||||
}
|
||||
|
||||
nsresult nsRange::DeleteContents()
|
||||
|
@ -1077,6 +1036,8 @@ nsRange::CloneSibsAndParents(nsIDOMNode* parentNode, PRInt32 nodeOffset,
|
|||
// XXX This is fine for left children but it will include too much
|
||||
// XXX instead of stopping at the left children of the end node.
|
||||
//
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
nsresult nsRange::CloneContents(nsIDOMDocumentFragment** aReturn)
|
||||
|
|
|
@ -17,10 +17,118 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* nsRange.h : Useful routines for users of nsRange objects.
|
||||
* This doesn't include the definition of the nsRange class itself,
|
||||
* since range users should always get their ranges via nsIDOMRange.
|
||||
* nsRange.h: interface of the nsRange object.
|
||||
*/
|
||||
|
||||
#include "nsIDOMRange.h"
|
||||
|
||||
class nsIDOMNode;
|
||||
class nsIDOMDocumentFragment;
|
||||
class nsVoidArray;
|
||||
|
||||
class nsRange : public nsIDOMRange
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsRange();
|
||||
virtual ~nsRange();
|
||||
|
||||
// IsPositioned attribute disappeared from the dom spec
|
||||
NS_IMETHOD GetIsPositioned(PRBool* aIsPositioned);
|
||||
|
||||
NS_IMETHOD GetStartParent(nsIDOMNode** aStartParent);
|
||||
NS_IMETHOD GetStartOffset(PRInt32* aStartOffset);
|
||||
|
||||
NS_IMETHOD GetEndParent(nsIDOMNode** aEndParent);
|
||||
NS_IMETHOD GetEndOffset(PRInt32* aEndOffset);
|
||||
|
||||
NS_IMETHOD GetIsCollapsed(PRBool* aIsCollapsed);
|
||||
|
||||
NS_IMETHOD GetCommonParent(nsIDOMNode** aCommonParent);
|
||||
|
||||
NS_IMETHOD SetStart(nsIDOMNode* aParent, PRInt32 aOffset);
|
||||
NS_IMETHOD SetStartBefore(nsIDOMNode* aSibling);
|
||||
NS_IMETHOD SetStartAfter(nsIDOMNode* aSibling);
|
||||
|
||||
NS_IMETHOD SetEnd(nsIDOMNode* aParent, PRInt32 aOffset);
|
||||
NS_IMETHOD SetEndBefore(nsIDOMNode* aSibling);
|
||||
NS_IMETHOD SetEndAfter(nsIDOMNode* aSibling);
|
||||
|
||||
NS_IMETHOD Collapse(PRBool aToStart);
|
||||
|
||||
NS_IMETHOD Unposition();
|
||||
|
||||
NS_IMETHOD SelectNode(nsIDOMNode* aN);
|
||||
NS_IMETHOD SelectNodeContents(nsIDOMNode* aN);
|
||||
|
||||
NS_IMETHOD CompareEndPoints(PRUint16 how, nsIDOMRange* srcRange, PRInt32* ret);
|
||||
|
||||
NS_IMETHOD DeleteContents();
|
||||
|
||||
NS_IMETHOD ExtractContents(nsIDOMDocumentFragment** aReturn);
|
||||
NS_IMETHOD CloneContents(nsIDOMDocumentFragment** aReturn);
|
||||
|
||||
NS_IMETHOD InsertNode(nsIDOMNode* aN);
|
||||
NS_IMETHOD SurroundContents(nsIDOMNode* aN);
|
||||
|
||||
NS_IMETHOD Clone(nsIDOMRange** aReturn);
|
||||
|
||||
NS_IMETHOD ToString(nsString& aReturn);
|
||||
|
||||
|
||||
private:
|
||||
PRBool mIsPositioned;
|
||||
nsIDOMNode *mStartParent;
|
||||
nsIDOMNode *mEndParent;
|
||||
PRInt32 mStartOffset;
|
||||
PRInt32 mEndOffset;
|
||||
nsVoidArray *mStartAncestors; // just keeping these around to avoid reallocing the arrays.
|
||||
nsVoidArray *mEndAncestors; // the contents of these arrays are discarded across calls.
|
||||
nsVoidArray *mStartAncestorOffsets; //
|
||||
nsVoidArray *mEndAncestorOffsets; //
|
||||
|
||||
// no copy's or assigns
|
||||
nsRange(const nsRange&);
|
||||
nsRange& operator=(const nsRange&);
|
||||
|
||||
// helper routines
|
||||
|
||||
static PRBool InSameDoc(nsIDOMNode* aNode1, nsIDOMNode* aNode2);
|
||||
static PRInt32 IndexOf(nsIDOMNode* aNode);
|
||||
static PRInt32 FillArrayWithAncestors(nsVoidArray* aArray,nsIDOMNode* aNode);
|
||||
static nsIDOMNode* CommonParent(nsIDOMNode* aNode1, nsIDOMNode* aNode2);
|
||||
|
||||
static nsresult CloneSibsAndParents(nsIDOMNode* parentNode,
|
||||
PRInt32 nodeOffset,
|
||||
nsIDOMNode* clonedNode,
|
||||
nsIDOMNode* commonParent,
|
||||
nsIDOMDocumentFragment* docfrag,
|
||||
PRBool leftP);
|
||||
|
||||
nsresult DoSetRange(nsIDOMNode* aStartN, PRInt32 aStartOffset,
|
||||
nsIDOMNode* aEndN, PRInt32 aEndOffset);
|
||||
|
||||
PRBool IsIncreasing(nsIDOMNode* aStartN, PRInt32 aStartOff,
|
||||
nsIDOMNode* aEndN, PRInt32 aEndOff);
|
||||
|
||||
nsresult IsPointInRange(nsIDOMNode* aParent, PRInt32 aOffset, PRBool* aResult);
|
||||
|
||||
nsresult ComparePointToRange(nsIDOMNode* aParent, PRInt32 aOffset, PRInt32* aResult);
|
||||
|
||||
|
||||
PRInt32 GetAncestorsAndOffsets(nsIDOMNode* aNode, PRInt32 aOffset,
|
||||
nsVoidArray* aAncestorNodes, nsVoidArray* aAncestorOffsets);
|
||||
|
||||
nsresult AddToListOf(nsIDOMNode* aNode);
|
||||
|
||||
nsresult RemoveFromListOf(nsIDOMNode* aNode);
|
||||
|
||||
};
|
||||
|
||||
// Make a new nsIDOMRange object
|
||||
nsresult NS_NewRange(nsIDOMRange** aInstancePtrResult);
|
||||
|
||||
// Utility routine to compare two "points", were a point is a node/offset pair
|
||||
PRInt32 ComparePoints(nsIDOMNode* aParent1, PRInt32 aOffset1,
|
||||
nsIDOMNode* aParent2, PRInt32 aOffset2);
|
||||
|
|
|
@ -656,11 +656,25 @@ nsGenericDOMDataNode::RangeRemove(nsIDOMRange& aRange)
|
|||
if (mRangeList) {
|
||||
// dont need to release - this call is made by the range object itself
|
||||
PRBool rv = mRangeList->RemoveElement(&aRange);
|
||||
if (rv) return NS_OK;
|
||||
if (rv) {
|
||||
if (mRangeList->Count() == 0) {
|
||||
delete mRangeList;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsGenericDOMDataNode::GetRangeList(nsVoidArray*& aResult) const
|
||||
{
|
||||
aResult = mRangeList;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Implementation of nsIHTMLContent
|
||||
|
|
|
@ -152,6 +152,7 @@ struct nsGenericDOMDataNode {
|
|||
nsEventStatus& aEventStatus);
|
||||
nsresult RangeAdd(nsIDOMRange& aRange);
|
||||
nsresult RangeRemove(nsIDOMRange& aRange);
|
||||
nsresult GetRangeList(nsVoidArray*& aResult) const;
|
||||
|
||||
// Implementation for nsIHTMLContent
|
||||
nsresult Compact();
|
||||
|
@ -470,6 +471,9 @@ struct nsGenericDOMDataNode {
|
|||
} \
|
||||
NS_IMETHOD RangeRemove(nsIDOMRange& aRange){ \
|
||||
return _g.RangeRemove(aRange); \
|
||||
} \
|
||||
NS_IMETHOD GetRangeList(nsVoidArray*& aResult) const { \
|
||||
return _g.GetRangeList(aResult); \
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1184,8 +1184,8 @@ nsRDFElement::HandleDOMEvent(nsIPresContext& aPresContext,
|
|||
NS_IMETHODIMP
|
||||
nsRDFElement::RangeAdd(nsIDOMRange& aRange)
|
||||
{
|
||||
// rdf content does not yet support DOM ranges
|
||||
return NS_OK;
|
||||
// rdf content does not yet support DOM ranges
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1193,10 +1193,19 @@ nsRDFElement::RangeAdd(nsIDOMRange& aRange)
|
|||
NS_IMETHODIMP
|
||||
nsRDFElement::RangeRemove(nsIDOMRange& aRange)
|
||||
{
|
||||
// rdf content does not yet support DOM ranges
|
||||
return NS_OK;
|
||||
// rdf content does not yet support DOM ranges
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsRDFElement::GetRangeList(nsVoidArray*& aResult) const
|
||||
{
|
||||
// rdf content does not yet support DOM ranges
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// nsIXMLContent
|
||||
|
||||
|
|
|
@ -98,6 +98,7 @@ public:
|
|||
nsEventStatus& aEventStatus);
|
||||
NS_IMETHOD RangeAdd(nsIDOMRange& aRange);
|
||||
NS_IMETHOD RangeRemove(nsIDOMRange& aRange);
|
||||
NS_IMETHOD GetRangeList(nsVoidArray*& aResult) const;
|
||||
|
||||
// nsIXMLContent (from nsIRDFContent)
|
||||
NS_IMETHOD SetNameSpacePrefix(nsIAtom* aNameSpace);
|
||||
|
|
Загрузка…
Ссылка в новой задаче