This commit is contained in:
jfrancis%netscape.com 1998-12-18 02:51:34 +00:00
Родитель fef94f10f9
Коммит 642ddb05ae
12 изменённых файлов: 579 добавлений и 355 удалений

Просмотреть файл

@ -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);