зеркало из https://github.com/mozilla/pjs.git
* added TransactionFactory. Editor no longer allocates its own transactions. This gives us an oppurtunity for a recycler.
* added DeleteSelection to editor. Doesn't work very well yet because selection is giving me random offsets into text content. * lots of work in the various transactions.
This commit is contained in:
Родитель
5d9c7b3a64
Коммит
83a4e325ce
|
@ -17,23 +17,33 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ChangeAttributeTxn.h"
|
#include "ChangeAttributeTxn.h"
|
||||||
#include "editor.h"
|
|
||||||
#include "nsIDOMElement.h"
|
#include "nsIDOMElement.h"
|
||||||
|
#include "editor.h"
|
||||||
|
|
||||||
// note that aEditor is not refcounted
|
ChangeAttributeTxn::ChangeAttributeTxn()
|
||||||
ChangeAttributeTxn::ChangeAttributeTxn(nsEditor *aEditor,
|
: EditTxn()
|
||||||
nsIDOMElement *aElement,
|
|
||||||
const nsString& aAttribute,
|
|
||||||
const nsString& aValue,
|
|
||||||
PRBool aRemoveAttribute)
|
|
||||||
: EditTxn(aEditor)
|
|
||||||
{
|
{
|
||||||
mElement = aElement;
|
}
|
||||||
mAttribute = aAttribute;
|
|
||||||
mValue = aValue;
|
nsresult ChangeAttributeTxn::Init(nsIEditor *aEditor,
|
||||||
mRemoveAttribute = aRemoveAttribute;
|
nsIDOMElement *aElement,
|
||||||
mAttributeWasSet=PR_FALSE;
|
const nsString& aAttribute,
|
||||||
mUndoValue="";
|
const nsString& aValue,
|
||||||
|
PRBool aRemoveAttribute)
|
||||||
|
{
|
||||||
|
if (nsnull!=aEditor && nsnull!=aElement)
|
||||||
|
{
|
||||||
|
mEditor = aEditor;
|
||||||
|
mElement = aElement;
|
||||||
|
mAttribute = aAttribute;
|
||||||
|
mValue = aValue;
|
||||||
|
mRemoveAttribute = aRemoveAttribute;
|
||||||
|
mAttributeWasSet=PR_FALSE;
|
||||||
|
mUndoValue="";
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult ChangeAttributeTxn::Do(void)
|
nsresult ChangeAttributeTxn::Do(void)
|
||||||
|
|
|
@ -20,8 +20,14 @@
|
||||||
#define ChangeAttributeTxn_h__
|
#define ChangeAttributeTxn_h__
|
||||||
|
|
||||||
#include "EditTxn.h"
|
#include "EditTxn.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsIDOMElement.h"
|
||||||
|
#include "nsIEditor.h"
|
||||||
|
|
||||||
class nsIDOMElement;
|
#define CHANGE_ATTRIBUTE_TXN_IID \
|
||||||
|
{/* 97818860-ac48-11d2-86d8-000064657374 */ \
|
||||||
|
0x97818860, 0xac48, 0x11d2, \
|
||||||
|
{0x86, 0xd8, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A transaction that changes an attribute of a content node.
|
* A transaction that changes an attribute of a content node.
|
||||||
|
@ -31,11 +37,16 @@ class ChangeAttributeTxn : public EditTxn
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ChangeAttributeTxn(nsEditor *aEditor,
|
virtual nsresult Init(nsIEditor *aEditor,
|
||||||
nsIDOMElement *aElement,
|
nsIDOMElement *aElement,
|
||||||
const nsString& aAttribute,
|
const nsString& aAttribute,
|
||||||
const nsString& aValue,
|
const nsString& aValue,
|
||||||
PRBool aRemoveAttribute);
|
PRBool aRemoveAttribute);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ChangeAttributeTxn();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
virtual nsresult Do(void);
|
virtual nsresult Do(void);
|
||||||
|
|
||||||
|
@ -55,8 +66,11 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
/** the editor that created this transaction */
|
||||||
|
nsCOMPtr<nsIEditor> mEditor;
|
||||||
|
|
||||||
/** the element to operate upon */
|
/** the element to operate upon */
|
||||||
nsIDOMElement *mElement;
|
nsCOMPtr<nsIDOMElement> mElement;
|
||||||
|
|
||||||
/** the attribute to change */
|
/** the attribute to change */
|
||||||
nsString mAttribute;
|
nsString mAttribute;
|
||||||
|
@ -72,6 +86,8 @@ protected:
|
||||||
|
|
||||||
/** PR_TRUE if the operation is to remove mAttribute from mElement */
|
/** PR_TRUE if the operation is to remove mAttribute from mElement */
|
||||||
PRBool mRemoveAttribute;
|
PRBool mRemoveAttribute;
|
||||||
|
|
||||||
|
friend class TransactionFactory;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,52 +17,50 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "CreateElementTxn.h"
|
#include "CreateElementTxn.h"
|
||||||
#include "editor.h"
|
|
||||||
#include "nsIDOMNode.h"
|
|
||||||
#include "nsIDOMNodeList.h"
|
#include "nsIDOMNodeList.h"
|
||||||
#include "nsIDOMDocument.h"
|
|
||||||
#include "nsIDOMElement.h"
|
|
||||||
|
|
||||||
// note that aEditor is not refcounted
|
CreateElementTxn::CreateElementTxn()
|
||||||
CreateElementTxn::CreateElementTxn(nsEditor *aEditor,
|
: EditTxn()
|
||||||
nsIDOMDocument *aDoc,
|
|
||||||
const nsString& aTag,
|
|
||||||
nsIDOMNode *aParent,
|
|
||||||
PRUint32 aOffsetInParent)
|
|
||||||
: EditTxn(aEditor)
|
|
||||||
{
|
{
|
||||||
mDoc = aDoc;
|
|
||||||
NS_ADDREF(mDoc);
|
|
||||||
mTag = aTag;
|
|
||||||
mParent = aParent;
|
|
||||||
NS_ADDREF(mParent);
|
|
||||||
mOffsetInParent = aOffsetInParent;
|
|
||||||
mNewNode = nsnull;
|
|
||||||
mRefNode = nsnull;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult CreateElementTxn::Init(nsIDOMDocument *aDoc,
|
||||||
|
const nsString& aTag,
|
||||||
|
nsIDOMNode *aParent,
|
||||||
|
PRUint32 aOffsetInParent)
|
||||||
|
{
|
||||||
|
if ((nsnull!=aDoc) && (nsnull!=aParent))
|
||||||
|
{
|
||||||
|
mDoc = aDoc;
|
||||||
|
mTag = aTag;
|
||||||
|
mParent = aParent;
|
||||||
|
mOffsetInParent = aOffsetInParent;
|
||||||
|
mNewNode = nsnull;
|
||||||
|
mRefNode = nsnull;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CreateElementTxn::~CreateElementTxn()
|
CreateElementTxn::~CreateElementTxn()
|
||||||
{
|
{
|
||||||
NS_IF_RELEASE(mDoc);
|
|
||||||
NS_IF_RELEASE(mParent);
|
|
||||||
NS_IF_RELEASE(mNewNode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult CreateElementTxn::Do(void)
|
nsresult CreateElementTxn::Do(void)
|
||||||
{
|
{
|
||||||
// create a new node
|
// create a new node
|
||||||
nsresult result = mDoc->CreateElement(mTag, &mNewNode);
|
nsresult result = mDoc->CreateElement(mTag, getter_AddRefs(mNewNode));
|
||||||
NS_ASSERTION(((NS_SUCCEEDED(result)) && (nsnull!=mNewNode)), "could not create element.");
|
NS_ASSERTION(((NS_SUCCEEDED(result)) && (mNewNode)), "could not create element.");
|
||||||
|
|
||||||
if ((NS_SUCCEEDED(result)) && (nsnull!=mNewNode))
|
if ((NS_SUCCEEDED(result)) && (mNewNode))
|
||||||
{
|
{
|
||||||
// insert the new node
|
// insert the new node
|
||||||
nsIDOMNode *resultNode=nsnull;
|
nsCOMPtr<nsIDOMNode> resultNode;
|
||||||
if (CreateElementTxn::eAppend==mOffsetInParent)
|
if (CreateElementTxn::eAppend==mOffsetInParent)
|
||||||
{
|
{
|
||||||
result = mParent->AppendChild(mNewNode, &resultNode);
|
result = mParent->AppendChild(mNewNode, getter_AddRefs(resultNode));
|
||||||
if ((NS_SUCCEEDED(result)) && (nsnull!=resultNode))
|
|
||||||
NS_RELEASE(resultNode); // this object already holds a ref from CreateElement
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -70,12 +68,10 @@ nsresult CreateElementTxn::Do(void)
|
||||||
result = mParent->GetChildNodes(getter_AddRefs(childNodes));
|
result = mParent->GetChildNodes(getter_AddRefs(childNodes));
|
||||||
if ((NS_SUCCEEDED(result)) && (childNodes))
|
if ((NS_SUCCEEDED(result)) && (childNodes))
|
||||||
{
|
{
|
||||||
result = childNodes->Item(mOffsetInParent, &mRefNode);
|
result = childNodes->Item(mOffsetInParent, getter_AddRefs(mRefNode));
|
||||||
if ((NS_SUCCEEDED(result)) && (nsnull!=mRefNode))
|
if ((NS_SUCCEEDED(result)) && (mRefNode))
|
||||||
{
|
{
|
||||||
result = mParent->InsertBefore(mNewNode, mRefNode, &resultNode);
|
result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode));
|
||||||
if ((NS_SUCCEEDED(result)) && (nsnull!=resultNode))
|
|
||||||
NS_RELEASE(resultNode); // this object already holds a ref from CreateElement
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,20 +81,16 @@ nsresult CreateElementTxn::Do(void)
|
||||||
|
|
||||||
nsresult CreateElementTxn::Undo(void)
|
nsresult CreateElementTxn::Undo(void)
|
||||||
{
|
{
|
||||||
nsIDOMNode *resultNode=nsnull;
|
nsCOMPtr<nsIDOMNode> resultNode;
|
||||||
nsresult result = mParent->RemoveChild(mNewNode, &resultNode);
|
nsresult result = mParent->RemoveChild(mNewNode, getter_AddRefs(resultNode));
|
||||||
if ((NS_SUCCEEDED(result)) && (nsnull!=resultNode))
|
|
||||||
NS_RELEASE(resultNode);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult CreateElementTxn::Redo(void)
|
nsresult CreateElementTxn::Redo(void)
|
||||||
{
|
{
|
||||||
nsIDOMNode *resultNode=nsnull;
|
nsCOMPtr<nsIDOMNode> resultNode;
|
||||||
nsresult result = mParent->InsertBefore(mNewNode, mRefNode, &resultNode);
|
nsresult result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode));
|
||||||
if ((NS_SUCCEEDED(result)) && (nsnull!=resultNode))
|
return result;
|
||||||
NS_RELEASE(resultNode);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult CreateElementTxn::GetIsTransient(PRBool *aIsTransient)
|
nsresult CreateElementTxn::GetIsTransient(PRBool *aIsTransient)
|
||||||
|
|
|
@ -20,10 +20,15 @@
|
||||||
#define CreateElementTxn_h__
|
#define CreateElementTxn_h__
|
||||||
|
|
||||||
#include "EditTxn.h"
|
#include "EditTxn.h"
|
||||||
|
#include "nsIDOMDocument.h"
|
||||||
|
#include "nsIDOMNode.h"
|
||||||
|
#include "nsIDOMElement.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
|
||||||
class nsIDOMDocument;
|
#define CREATE_ELEMENT_TXN_IID \
|
||||||
class nsIDOMNode;
|
{/* 7a6393c0-ac48-11d2-86d8-000064657374 */ \
|
||||||
class nsIDOMElement;
|
0x7a6393c0, 0xac48, 0x11d2, \
|
||||||
|
{0x86, 0xd8, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A transaction that creates a new node in the content tree.
|
* A transaction that creates a new node in the content tree.
|
||||||
|
@ -34,11 +39,15 @@ public:
|
||||||
|
|
||||||
enum { eAppend=-1 };
|
enum { eAppend=-1 };
|
||||||
|
|
||||||
CreateElementTxn(nsEditor *aEditor,
|
virtual nsresult Init(nsIDOMDocument *aDoc,
|
||||||
nsIDOMDocument *aDoc,
|
const nsString& aTag,
|
||||||
const nsString& aTag,
|
nsIDOMNode *aParent,
|
||||||
nsIDOMNode *aParent,
|
PRUint32 aOffsetInParent);
|
||||||
PRUint32 aOffsetInParent);
|
|
||||||
|
private:
|
||||||
|
CreateElementTxn();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
virtual ~CreateElementTxn();
|
virtual ~CreateElementTxn();
|
||||||
|
|
||||||
|
@ -61,22 +70,24 @@ public:
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/** the document into which the new node will be inserted */
|
/** the document into which the new node will be inserted */
|
||||||
nsIDOMDocument *mDoc;
|
nsCOMPtr<nsIDOMDocument> mDoc;
|
||||||
|
|
||||||
/** the tag (mapping to object type) for the new element */
|
/** the tag (mapping to object type) for the new element */
|
||||||
nsString mTag;
|
nsString mTag;
|
||||||
|
|
||||||
/** the node into which the new node will be inserted */
|
/** the node into which the new node will be inserted */
|
||||||
nsIDOMNode *mParent;
|
nsCOMPtr<nsIDOMNode> mParent;
|
||||||
|
|
||||||
/** the index in mParent for the new node */
|
/** the index in mParent for the new node */
|
||||||
PRUint32 mOffsetInParent;
|
PRUint32 mOffsetInParent;
|
||||||
|
|
||||||
/** the new node to insert */
|
/** the new node to insert */
|
||||||
nsIDOMElement *mNewNode;
|
nsCOMPtr<nsIDOMElement> mNewNode;
|
||||||
|
|
||||||
/** the node we will insert mNewNode before. We compute this ourselves. */
|
/** the node we will insert mNewNode before. We compute this ourselves. */
|
||||||
nsIDOMNode *mRefNode;
|
nsCOMPtr<nsIDOMNode> mRefNode;
|
||||||
|
|
||||||
|
friend class TransactionFactory;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -17,30 +17,32 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "DeleteElementTxn.h"
|
#include "DeleteElementTxn.h"
|
||||||
#include "editor.h"
|
#ifdef NS_DEBUG
|
||||||
#include "nsIDOMDocument.h"
|
|
||||||
#include "nsIDOMElement.h"
|
#include "nsIDOMElement.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// note that aEditor is not refcounted
|
|
||||||
DeleteElementTxn::DeleteElementTxn(nsEditor * aEditor,
|
DeleteElementTxn::DeleteElementTxn()
|
||||||
nsIDOMDocument *aDoc,
|
: EditTxn()
|
||||||
nsIDOMNode * aElement,
|
|
||||||
nsIDOMNode * aParent)
|
|
||||||
: EditTxn(aEditor)
|
|
||||||
{
|
{
|
||||||
mDoc = aDoc;
|
|
||||||
NS_ADDREF(mDoc);
|
|
||||||
mElement = aElement;
|
|
||||||
NS_ADDREF(mElement);
|
|
||||||
mParent = aParent;
|
|
||||||
NS_ADDREF(mParent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult DeleteElementTxn::Init(nsIDOMNode *aElement,
|
||||||
|
nsIDOMNode *aParent)
|
||||||
|
{
|
||||||
|
if ((nsnull!=aElement) && (nsnull!=aParent))
|
||||||
|
{
|
||||||
|
mElement = aElement;
|
||||||
|
mParent = aParent;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DeleteElementTxn::~DeleteElementTxn()
|
DeleteElementTxn::~DeleteElementTxn()
|
||||||
{
|
{
|
||||||
NS_IF_RELEASE(mDoc);
|
|
||||||
NS_IF_RELEASE(mParent);
|
|
||||||
NS_IF_RELEASE(mElement);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult DeleteElementTxn::Do(void)
|
nsresult DeleteElementTxn::Do(void)
|
||||||
|
@ -48,11 +50,32 @@ nsresult DeleteElementTxn::Do(void)
|
||||||
if (!mParent || !mElement)
|
if (!mParent || !mElement)
|
||||||
return NS_ERROR_NULL_POINTER;
|
return NS_ERROR_NULL_POINTER;
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
|
// begin debug output
|
||||||
|
nsCOMPtr<nsIDOMElement> element=mElement;
|
||||||
|
nsAutoString elementTag="text node";
|
||||||
|
if (element)
|
||||||
|
element->GetTagName(elementTag);
|
||||||
|
nsCOMPtr<nsIDOMElement> parentElement=mParent;
|
||||||
|
nsAutoString parentElementTag="text node";
|
||||||
|
if (parentElement)
|
||||||
|
parentElement->GetTagName(parentElementTag);
|
||||||
|
char *c, *p;
|
||||||
|
c = elementTag.ToNewCString();
|
||||||
|
p = parentElementTag.ToNewCString();
|
||||||
|
if (c&&p)
|
||||||
|
{
|
||||||
|
printf("DeleteElementTxn: deleting child %s from parent %s\n", c, p);
|
||||||
|
delete [] c;
|
||||||
|
delete [] p;
|
||||||
|
}
|
||||||
|
// end debug output
|
||||||
|
// begin sanity check 1: parent-child relationship
|
||||||
nsresult testResult;
|
nsresult testResult;
|
||||||
nsCOMPtr<nsIDOMNode> parentNode;
|
nsCOMPtr<nsIDOMNode> parentNode;
|
||||||
testResult = mElement->GetParentNode(getter_AddRefs(parentNode));
|
testResult = mElement->GetParentNode(getter_AddRefs(parentNode));
|
||||||
NS_ASSERTION((NS_SUCCEEDED(testResult)), "bad mElement, couldn't get parent");
|
NS_ASSERTION((NS_SUCCEEDED(testResult)), "bad mElement, couldn't get parent");
|
||||||
NS_ASSERTION((parentNode==mParent), "bad mParent, mParent!=mElement->GetParent() ");
|
NS_ASSERTION((parentNode==mParent), "bad mParent, mParent!=mElement->GetParent() ");
|
||||||
|
// end sanity check 1.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// remember which child mElement was (by remembering which child was next)
|
// remember which child mElement was (by remembering which child was next)
|
||||||
|
|
|
@ -23,8 +23,10 @@
|
||||||
#include "nsIDOMNode.h"
|
#include "nsIDOMNode.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
|
|
||||||
class nsIDOMDocument;
|
#define DELETE_ELEMENT_TXN_IID \
|
||||||
class nsIDOMElement;
|
{/* 6fd77770-ac49-11d2-86d8-000064657374 */ \
|
||||||
|
0x6fd77770, 0xac49, 0x11d2, \
|
||||||
|
{0x86, 0xd8, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A transaction that deletes a single element
|
* A transaction that deletes a single element
|
||||||
|
@ -33,10 +35,13 @@ class DeleteElementTxn : public EditTxn
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DeleteElementTxn(nsEditor *aEditor,
|
virtual nsresult Init(nsIDOMNode *aElement,
|
||||||
nsIDOMDocument *aDoc,
|
nsIDOMNode *aParent);
|
||||||
nsIDOMNode *aElement,
|
|
||||||
nsIDOMNode *aParent);
|
private:
|
||||||
|
DeleteElementTxn();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
virtual ~DeleteElementTxn();
|
virtual ~DeleteElementTxn();
|
||||||
|
|
||||||
|
@ -58,14 +63,11 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/** the document into which the new node will be inserted */
|
|
||||||
nsIDOMDocument *mDoc;
|
|
||||||
|
|
||||||
/** the element to delete */
|
/** the element to delete */
|
||||||
nsIDOMNode *mElement;
|
nsCOMPtr<nsIDOMNode> mElement;
|
||||||
|
|
||||||
/** the node into which the new node will be inserted */
|
/** the node into which the new node will be inserted */
|
||||||
nsIDOMNode *mParent;
|
nsCOMPtr<nsIDOMNode> mParent;
|
||||||
|
|
||||||
/** the index in mParent for the new node */
|
/** the index in mParent for the new node */
|
||||||
PRUint32 mOffsetInParent;
|
PRUint32 mOffsetInParent;
|
||||||
|
@ -73,6 +75,8 @@ protected:
|
||||||
/** the node we will insert mNewNode before. We compute this ourselves. */
|
/** the node we will insert mNewNode before. We compute this ourselves. */
|
||||||
nsCOMPtr<nsIDOMNode> mRefNode;
|
nsCOMPtr<nsIDOMNode> mRefNode;
|
||||||
|
|
||||||
|
friend class TransactionFactory;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,18 +17,73 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "DeleteRangeTxn.h"
|
#include "DeleteRangeTxn.h"
|
||||||
#include "editor.h"
|
|
||||||
#include "nsIDOMRange.h"
|
#include "nsIDOMRange.h"
|
||||||
|
#include "nsIDOMCharacterData.h"
|
||||||
|
#include "nsIDOMNodeList.h"
|
||||||
|
#include "DeleteTextTxn.h"
|
||||||
|
#include "DeleteElementTxn.h"
|
||||||
|
#include "TransactionFactory.h"
|
||||||
|
#include "nsISupportsArray.h"
|
||||||
|
|
||||||
|
static NS_DEFINE_IID(kDeleteTextTxnIID, DELETE_TEXT_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kDeleteElementTxnIID, DELETE_ELEMENT_TXN_IID);
|
||||||
|
|
||||||
|
|
||||||
// note that aEditor is not refcounted
|
// note that aEditor is not refcounted
|
||||||
DeleteRangeTxn::DeleteRangeTxn(nsEditor *aEditor,
|
DeleteRangeTxn::DeleteRangeTxn()
|
||||||
nsIDOMRange *aRange)
|
: EditAggregateTxn()
|
||||||
: EditTxn(aEditor)
|
|
||||||
{
|
{
|
||||||
aRange->GetStartParent(getter_AddRefs(mStartParent));
|
}
|
||||||
aRange->GetEndParent(getter_AddRefs(mEndParent));
|
|
||||||
aRange->GetStartOffset(&mStartOffset);
|
nsresult DeleteRangeTxn::Init(nsIDOMRange *aRange)
|
||||||
aRange->GetEndOffset(&mEndOffset);
|
{
|
||||||
|
if (nsnull!=aRange)
|
||||||
|
{
|
||||||
|
nsresult result = aRange->GetStartParent(getter_AddRefs(mStartParent));
|
||||||
|
NS_ASSERTION((NS_SUCCEEDED(result)), "GetStartParent failed.");
|
||||||
|
result = aRange->GetEndParent(getter_AddRefs(mEndParent));
|
||||||
|
NS_ASSERTION((NS_SUCCEEDED(result)), "GetEndParent failed.");
|
||||||
|
result = aRange->GetStartOffset(&mStartOffset);
|
||||||
|
NS_ASSERTION((NS_SUCCEEDED(result)), "GetStartOffset failed.");
|
||||||
|
result = aRange->GetEndOffset(&mEndOffset);
|
||||||
|
NS_ASSERTION((NS_SUCCEEDED(result)), "GetEndOffset failed.");
|
||||||
|
result = aRange->GetCommonParent(getter_AddRefs(mCommonParent));
|
||||||
|
NS_ASSERTION((NS_SUCCEEDED(result)), "GetCommonParent failed.");
|
||||||
|
|
||||||
|
#ifdef NS_DEBUG
|
||||||
|
PRUint32 count;
|
||||||
|
nsCOMPtr<nsIDOMCharacterData> textNode;
|
||||||
|
textNode = mStartParent;
|
||||||
|
if (textNode)
|
||||||
|
textNode->GetLength(&count);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMNodeList> children;
|
||||||
|
result = mStartParent->GetChildNodes(getter_AddRefs(children));
|
||||||
|
NS_ASSERTION(((NS_SUCCEEDED(result)) && children), "bad start child list");
|
||||||
|
children->GetLength(&count);
|
||||||
|
}
|
||||||
|
NS_ASSERTION(mStartOffset<count, "bad start offset");
|
||||||
|
|
||||||
|
textNode = mEndParent;
|
||||||
|
if (textNode)
|
||||||
|
textNode->GetLength(&count);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMNodeList> children;
|
||||||
|
result = mEndParent->GetChildNodes(getter_AddRefs(children));
|
||||||
|
NS_ASSERTION(((NS_SUCCEEDED(result)) && children), "bad end child list");
|
||||||
|
children->GetLength(&count);
|
||||||
|
}
|
||||||
|
NS_ASSERTION(mEndOffset<count, "bad end offset");
|
||||||
|
|
||||||
|
printf ("DeleteRange: %d of %p to %d of %p\n",
|
||||||
|
mStartOffset, (void *)mStartParent, mEndOffset, (void *)mEndParent);
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
DeleteRangeTxn::~DeleteRangeTxn()
|
DeleteRangeTxn::~DeleteRangeTxn()
|
||||||
|
@ -37,28 +92,59 @@ DeleteRangeTxn::~DeleteRangeTxn()
|
||||||
|
|
||||||
nsresult DeleteRangeTxn::Do(void)
|
nsresult DeleteRangeTxn::Do(void)
|
||||||
{
|
{
|
||||||
if (!mStartParent || !mEndParent)
|
if (!mStartParent || !mEndParent || !mCommonParent)
|
||||||
return NS_ERROR_NULL_POINTER;
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
|
||||||
nsresult result;
|
nsresult result;
|
||||||
|
|
||||||
|
// build the child transactions
|
||||||
|
|
||||||
|
if (mStartParent==mEndParent)
|
||||||
|
{ // the selection begins and ends in the same node
|
||||||
|
result = CreateTxnsToDeleteBetween(mStartParent, mStartOffset, mEndOffset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // the selection ends in a different node from where it started
|
||||||
|
// delete the relevant content in the start node
|
||||||
|
result = CreateTxnsToDeleteContent(mStartParent, mStartOffset, nsIEditor::eLTR);
|
||||||
|
if (NS_SUCCEEDED(result))
|
||||||
|
{
|
||||||
|
// delete the intervening nodes
|
||||||
|
result = CreateTxnsToDeleteNodesBetween(mCommonParent, mStartParent, mEndParent);
|
||||||
|
if (NS_SUCCEEDED(result))
|
||||||
|
{
|
||||||
|
// delete the relevant content in the end node
|
||||||
|
result = CreateTxnsToDeleteContent(mEndParent, mEndOffset, nsIEditor::eRTL);
|
||||||
|
if (NS_SUCCEEDED(result))
|
||||||
|
{ // now we have all our child transactions, do them
|
||||||
|
result = EditAggregateTxn::Do();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we've successfully built this aggregate transaction, then do it.
|
||||||
|
if (NS_SUCCEEDED(result))
|
||||||
|
result = EditAggregateTxn::Do();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult DeleteRangeTxn::Undo(void)
|
nsresult DeleteRangeTxn::Undo(void)
|
||||||
{
|
{
|
||||||
if (!mStartParent || !mEndParent)
|
if (!mStartParent || !mEndParent || !mCommonParent)
|
||||||
return NS_ERROR_NULL_POINTER;
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
|
||||||
nsresult result;
|
nsresult result = EditAggregateTxn::Undo();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult DeleteRangeTxn::Redo(void)
|
nsresult DeleteRangeTxn::Redo(void)
|
||||||
{
|
{
|
||||||
if (!mStartParent || !mEndParent)
|
if (!mStartParent || !mEndParent || !mCommonParent)
|
||||||
return NS_ERROR_NULL_POINTER;
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
|
||||||
nsresult result;
|
nsresult result = EditAggregateTxn::Redo();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,3 +184,265 @@ nsresult DeleteRangeTxn::GetRedoString(nsString **aString)
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult DeleteRangeTxn::CreateTxnsToDeleteBetween(nsIDOMNode *aStartParent,
|
||||||
|
PRUint32 aStartOffset,
|
||||||
|
PRUint32 aEndOffset)
|
||||||
|
{
|
||||||
|
nsresult result;
|
||||||
|
// see what kind of node we have
|
||||||
|
nsCOMPtr<nsIDOMCharacterData> textNode;
|
||||||
|
textNode = aStartParent; // this uses implicit nsCOMPtr QI
|
||||||
|
if (textNode)
|
||||||
|
{ // if the node is a text node, then delete text content
|
||||||
|
DeleteTextTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kDeleteTextTxnIID, (EditTxn **)&txn);
|
||||||
|
if (nsnull!=txn)
|
||||||
|
{
|
||||||
|
txn->Init(textNode, aStartOffset, (aEndOffset-aStartOffset)+1);
|
||||||
|
AppendChild(txn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PRUint32 childCount;
|
||||||
|
nsCOMPtr<nsIDOMNodeList> children;
|
||||||
|
result = aStartParent->GetChildNodes(getter_AddRefs(children));
|
||||||
|
if ((NS_SUCCEEDED(result)) && children)
|
||||||
|
{
|
||||||
|
children->GetLength(&childCount);
|
||||||
|
NS_ASSERTION(aEndOffset<childCount, "bad aEndOffset");
|
||||||
|
PRUint32 i;
|
||||||
|
for (i=aStartOffset; i<=aEndOffset; i++)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMNode> child;
|
||||||
|
result = children->Item(i, getter_AddRefs(child));
|
||||||
|
if ((NS_SUCCEEDED(result)) && child)
|
||||||
|
{
|
||||||
|
DeleteElementTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kDeleteElementTxnIID, (EditTxn **)&txn);
|
||||||
|
if (nsnull!=txn)
|
||||||
|
{
|
||||||
|
txn->Init(child, aStartParent);
|
||||||
|
AppendChild(txn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult DeleteRangeTxn::CreateTxnsToDeleteContent(nsIDOMNode *aParent,
|
||||||
|
PRUint32 aOffset,
|
||||||
|
nsIEditor::Direction aDir)
|
||||||
|
{
|
||||||
|
nsresult result;
|
||||||
|
// see what kind of node we have
|
||||||
|
nsCOMPtr<nsIDOMCharacterData> textNode;
|
||||||
|
textNode = aParent; // this uses implicit nsCOMPtr QI
|
||||||
|
if (textNode)
|
||||||
|
{ // if the node is a text node, then delete text content
|
||||||
|
PRUint32 start, numToDelete;
|
||||||
|
if (nsIEditor::eLTR==aDir)
|
||||||
|
{
|
||||||
|
start=aOffset;
|
||||||
|
textNode->GetLength(&numToDelete);
|
||||||
|
numToDelete -= (aOffset+1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
start=0;
|
||||||
|
numToDelete=aOffset;
|
||||||
|
}
|
||||||
|
DeleteTextTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kDeleteTextTxnIID, (EditTxn **)&txn);
|
||||||
|
if (nsnull!=txn)
|
||||||
|
{
|
||||||
|
txn->Init(textNode, start, numToDelete);
|
||||||
|
AppendChild(txn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // we have an interior node, so delete some of its children
|
||||||
|
if (nsIEditor::eLTR==aDir)
|
||||||
|
{ // delete from aOffset to end
|
||||||
|
PRUint32 childCount;
|
||||||
|
nsCOMPtr<nsIDOMNodeList> children;
|
||||||
|
result = aParent->GetChildNodes(getter_AddRefs(children));
|
||||||
|
if ((NS_SUCCEEDED(result)) && children)
|
||||||
|
{
|
||||||
|
children->GetLength(&childCount);
|
||||||
|
PRUint32 i;
|
||||||
|
for (i=aOffset; i<childCount; i++)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMNode> child;
|
||||||
|
result = children->Item(i, getter_AddRefs(child));
|
||||||
|
if ((NS_SUCCEEDED(result)) && child)
|
||||||
|
{
|
||||||
|
DeleteElementTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kDeleteElementTxnIID, (EditTxn **)&txn);
|
||||||
|
if (nsnull!=txn)
|
||||||
|
{
|
||||||
|
txn->Init(child, aParent);
|
||||||
|
AppendChild(txn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // delete from 0 to aOffset
|
||||||
|
nsCOMPtr<nsIDOMNode> child;
|
||||||
|
result = aParent->GetFirstChild(getter_AddRefs(child));
|
||||||
|
for (PRUint32 i=0; i<aOffset; i++)
|
||||||
|
{
|
||||||
|
if ((NS_SUCCEEDED(result)) && child)
|
||||||
|
{
|
||||||
|
DeleteElementTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kDeleteElementTxnIID, (EditTxn **)&txn);
|
||||||
|
if (nsnull!=txn)
|
||||||
|
{
|
||||||
|
txn->Init(child, aParent);
|
||||||
|
AppendChild(txn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
nsCOMPtr<nsIDOMNode> temp = child;
|
||||||
|
result = temp->GetNextSibling(getter_AddRefs(child));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult DeleteRangeTxn::CreateTxnsToDeleteNodesBetween(nsIDOMNode *aCommonParent,
|
||||||
|
nsIDOMNode *aFirstChild,
|
||||||
|
nsIDOMNode *aLastChild)
|
||||||
|
{
|
||||||
|
nsresult result;
|
||||||
|
PRBool needToProcessLastChild=PR_TRUE; // set to false if we discover we can delete all required nodes by just walking up aFirstChild's parent list
|
||||||
|
nsCOMPtr<nsIDOMNode> parent; // the current parent in the iteration up the ancestors
|
||||||
|
nsCOMPtr<nsIDOMNode> child; // the current child of parent
|
||||||
|
nsISupportsArray *ancestorList; // the ancestorList of the other endpoint, used to gate deletion
|
||||||
|
NS_NewISupportsArray(&ancestorList);
|
||||||
|
if (nsnull==ancestorList)
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
|
||||||
|
// Walk up the parent list of aFirstChild to aCommonParent,
|
||||||
|
// deleting all siblings to the right of the ancestors of aFirstChild.
|
||||||
|
BuildAncestorList(aLastChild, ancestorList);
|
||||||
|
child = aFirstChild;
|
||||||
|
result = child->GetParentNode(getter_AddRefs(parent));
|
||||||
|
while ((NS_SUCCEEDED(result)) && parent)
|
||||||
|
{
|
||||||
|
while ((NS_SUCCEEDED(result)) && child)
|
||||||
|
{ // this loop starts with the first sibling of an ancestor of aFirstChild
|
||||||
|
nsCOMPtr<nsIDOMNode> temp = child;
|
||||||
|
result = temp->GetNextSibling(getter_AddRefs(child));
|
||||||
|
if ((NS_SUCCEEDED(result)) && child)
|
||||||
|
{
|
||||||
|
if (child==aLastChild)
|
||||||
|
{ // aFirstChild and aLastChild have the same parent, and we've reached aLastChild
|
||||||
|
needToProcessLastChild = PR_FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// test if child is an ancestor of the other node. If it is, don't process this parent anymore
|
||||||
|
PRInt32 index;
|
||||||
|
index = ancestorList->IndexOf((nsISupports*)child);
|
||||||
|
if (-1!=index)
|
||||||
|
break;
|
||||||
|
DeleteElementTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kDeleteElementTxnIID, (EditTxn **)&txn);
|
||||||
|
if (nsnull!=txn)
|
||||||
|
{
|
||||||
|
txn->Init(child, parent);
|
||||||
|
AppendChild(txn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (parent==aCommonParent)
|
||||||
|
break;
|
||||||
|
child = parent;
|
||||||
|
nsCOMPtr<nsIDOMNode> temp=parent;
|
||||||
|
result = temp->GetParentNode(getter_AddRefs(parent));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk up the parent list of aLastChild to aCommonParent,
|
||||||
|
// deleting all siblings to the left of the ancestors of aLastChild.
|
||||||
|
BuildAncestorList(aFirstChild, ancestorList);
|
||||||
|
if (PR_TRUE==needToProcessLastChild)
|
||||||
|
{
|
||||||
|
child = aLastChild;
|
||||||
|
result = child->GetParentNode(getter_AddRefs(parent));
|
||||||
|
while ((NS_SUCCEEDED(result)) && parent)
|
||||||
|
{
|
||||||
|
while ((NS_SUCCEEDED(result)) && child)
|
||||||
|
{ // this loop starts with the first sibling of an ancestor of aFirstChild
|
||||||
|
nsCOMPtr<nsIDOMNode> temp = child;
|
||||||
|
result = temp->GetPreviousSibling(getter_AddRefs(child));
|
||||||
|
if ((NS_SUCCEEDED(result)) && child)
|
||||||
|
{
|
||||||
|
// test if child is an ancestor of the other node. If it is, don't process this parent anymore
|
||||||
|
PRInt32 index;
|
||||||
|
index = ancestorList->IndexOf((nsISupports*)child);
|
||||||
|
if (-1!=index)
|
||||||
|
break;
|
||||||
|
DeleteElementTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kDeleteElementTxnIID, (EditTxn **)&txn);
|
||||||
|
if (nsnull!=txn)
|
||||||
|
{
|
||||||
|
txn->Init(child, parent);
|
||||||
|
AppendChild(txn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (parent==aCommonParent)
|
||||||
|
break;
|
||||||
|
child = parent;
|
||||||
|
nsCOMPtr<nsIDOMNode> temp=parent;
|
||||||
|
result = temp->GetParentNode(getter_AddRefs(parent));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NS_RELEASE(ancestorList);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult DeleteRangeTxn::BuildAncestorList(nsIDOMNode *aNode, nsISupportsArray *aList)
|
||||||
|
{
|
||||||
|
nsresult result=NS_OK;
|
||||||
|
if (nsnull!=aNode && nsnull!=aList)
|
||||||
|
{
|
||||||
|
aList->Clear();
|
||||||
|
nsCOMPtr<nsIDOMNode> parent;
|
||||||
|
nsCOMPtr<nsIDOMNode> child = aNode;
|
||||||
|
result = child->GetParentNode(getter_AddRefs(parent));
|
||||||
|
while ((NS_SUCCEEDED(result)) && child && parent)
|
||||||
|
{
|
||||||
|
nsISupports * parentAsISupports;
|
||||||
|
parent->QueryInterface(nsISupports::IID(), (void **)&parentAsISupports);
|
||||||
|
aList->AppendElement(parentAsISupports);
|
||||||
|
child = parent;
|
||||||
|
nsCOMPtr<nsIDOMNode> temp=parent;
|
||||||
|
result = temp->GetParentNode(getter_AddRefs(parent));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = NS_ERROR_NULL_POINTER;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -19,22 +19,33 @@
|
||||||
#ifndef DeleteRangeTxn_h__
|
#ifndef DeleteRangeTxn_h__
|
||||||
#define DeleteRangeTxn_h__
|
#define DeleteRangeTxn_h__
|
||||||
|
|
||||||
#include "EditTxn.h"
|
#include "EditAggregateTxn.h"
|
||||||
#include "nsIDOMNode.h"
|
#include "nsIDOMNode.h"
|
||||||
|
#include "nsIEditor.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
|
|
||||||
class nsIDOMDocument;
|
class nsIDOMDocument;
|
||||||
class nsIDOMRange;
|
class nsIDOMRange;
|
||||||
|
class nsISupportsArray;
|
||||||
|
|
||||||
|
#define DELETE_RANGE_TXN_IID \
|
||||||
|
{/* 5ec6b260-ac49-11d2-86d8-000064657374 */ \
|
||||||
|
0x5ec6b260, 0xac49, 0x11d2, \
|
||||||
|
{0x86, 0xd8, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A transaction that deletes an entire range in the content tree
|
* A transaction that deletes an entire range in the content tree
|
||||||
*/
|
*/
|
||||||
class DeleteRangeTxn : public EditTxn
|
class DeleteRangeTxn : public EditAggregateTxn
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DeleteRangeTxn(nsEditor *aEditor,
|
virtual nsresult Init(nsIDOMRange *aRange);
|
||||||
nsIDOMRange *aRange);
|
|
||||||
|
private:
|
||||||
|
DeleteRangeTxn();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
virtual ~DeleteRangeTxn();
|
virtual ~DeleteRangeTxn();
|
||||||
|
|
||||||
|
@ -54,6 +65,23 @@ public:
|
||||||
|
|
||||||
virtual nsresult GetRedoString(nsString **aString);
|
virtual nsresult GetRedoString(nsString **aString);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual nsresult CreateTxnsToDeleteBetween(nsIDOMNode *aStartParent,
|
||||||
|
PRUint32 aStartOffset,
|
||||||
|
PRUint32 aEndOffset);
|
||||||
|
|
||||||
|
virtual nsresult CreateTxnsToDeleteNodesBetween(nsIDOMNode *aParent,
|
||||||
|
nsIDOMNode *aFirstChild,
|
||||||
|
nsIDOMNode *aLastChild);
|
||||||
|
|
||||||
|
virtual nsresult CreateTxnsToDeleteContent(nsIDOMNode *aParent,
|
||||||
|
PRUint32 aOffset,
|
||||||
|
nsIEditor::Direction aDir);
|
||||||
|
|
||||||
|
virtual nsresult BuildAncestorList(nsIDOMNode *aNode,
|
||||||
|
nsISupportsArray *aList);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/** p1 in the range */
|
/** p1 in the range */
|
||||||
|
@ -65,9 +93,14 @@ protected:
|
||||||
/** p2 in the range */
|
/** p2 in the range */
|
||||||
nsCOMPtr<nsIDOMNode> mEndParent;
|
nsCOMPtr<nsIDOMNode> mEndParent;
|
||||||
|
|
||||||
|
/** the closest common parent of p1 and p2 */
|
||||||
|
nsCOMPtr<nsIDOMNode> mCommonParent;
|
||||||
|
|
||||||
/** p2 offset */
|
/** p2 offset */
|
||||||
PRInt32 mEndOffset;
|
PRInt32 mEndOffset;
|
||||||
|
|
||||||
|
friend class TransactionFactory;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,20 +17,23 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "DeleteTextTxn.h"
|
#include "DeleteTextTxn.h"
|
||||||
#include "editor.h"
|
|
||||||
#include "nsIDOMCharacterData.h"
|
#include "nsIDOMCharacterData.h"
|
||||||
|
|
||||||
// note that aEditor is not refcounted
|
|
||||||
DeleteTextTxn::DeleteTextTxn(nsEditor *aEditor,
|
DeleteTextTxn::DeleteTextTxn()
|
||||||
nsIDOMCharacterData *aElement,
|
: EditTxn()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult DeleteTextTxn::Init(nsIDOMCharacterData *aElement,
|
||||||
PRUint32 aOffset,
|
PRUint32 aOffset,
|
||||||
PRUint32 aNumCharsToDelete)
|
PRUint32 aNumCharsToDelete)
|
||||||
: EditTxn(aEditor)
|
|
||||||
{
|
{
|
||||||
mElement = aElement;
|
mElement = aElement;
|
||||||
mOffset = aOffset;
|
mOffset = aOffset;
|
||||||
mNumCharsToDelete = aNumCharsToDelete;
|
mNumCharsToDelete = aNumCharsToDelete;
|
||||||
mDeletedText = "";
|
mDeletedText = "";
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult DeleteTextTxn::Do(void)
|
nsresult DeleteTextTxn::Do(void)
|
||||||
|
|
|
@ -20,8 +20,13 @@
|
||||||
#define DeleteTextTxn_h__
|
#define DeleteTextTxn_h__
|
||||||
|
|
||||||
#include "EditTxn.h"
|
#include "EditTxn.h"
|
||||||
|
#include "nsIDOMCharacterData.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
|
||||||
class nsIDOMCharacterData;
|
#define DELETE_TEXT_TXN_IID \
|
||||||
|
{/* 4d3a2720-ac49-11d2-86d8-000064657374 */ \
|
||||||
|
0x4d3a2720, 0xac49, 0x11d2, \
|
||||||
|
{0x86, 0xd8, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A transaction that changes an attribute of a content node.
|
* A transaction that changes an attribute of a content node.
|
||||||
|
@ -31,10 +36,14 @@ class DeleteTextTxn : public EditTxn
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DeleteTextTxn(nsEditor *aEditor,
|
virtual nsresult Init(nsIDOMCharacterData *aElement,
|
||||||
nsIDOMCharacterData *aElement,
|
PRUint32 aOffset,
|
||||||
PRUint32 aOffset,
|
PRUint32 aNumCharsToDelete);
|
||||||
PRUint32 aNumCharsToDelete);
|
|
||||||
|
private:
|
||||||
|
DeleteTextTxn();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
virtual nsresult Do(void);
|
virtual nsresult Do(void);
|
||||||
|
|
||||||
|
@ -53,7 +62,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/** the text element to operate upon */
|
/** the text element to operate upon */
|
||||||
nsIDOMCharacterData *mElement;
|
nsCOMPtr<nsIDOMCharacterData> mElement;
|
||||||
|
|
||||||
/** the offset into mElement where the deletion is to take place */
|
/** the offset into mElement where the deletion is to take place */
|
||||||
PRUint32 mOffset;
|
PRUint32 mOffset;
|
||||||
|
@ -64,6 +73,8 @@ protected:
|
||||||
/** the text that was deleted */
|
/** the text that was deleted */
|
||||||
nsString mDeletedText;
|
nsString mDeletedText;
|
||||||
|
|
||||||
|
friend class TransactionFactory;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,145 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public License
|
||||||
|
* Version 1.0 (the "NPL") you may not use this file except in
|
||||||
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||||
|
* http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* NPL.
|
||||||
|
*
|
||||||
|
* The Initial Developer of this code under the NPL is Netscape
|
||||||
|
* Communications Corporation. Portions created by Netscape are
|
||||||
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||||
|
* Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "EditAggregateTxn.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsIDOMNode.h"
|
||||||
|
#include "nsVoidArray.h"
|
||||||
|
|
||||||
|
EditAggregateTxn::EditAggregateTxn()
|
||||||
|
: EditTxn()
|
||||||
|
{
|
||||||
|
mChildren = new nsVoidArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
EditAggregateTxn::~EditAggregateTxn()
|
||||||
|
{
|
||||||
|
if (nsnull!=mChildren)
|
||||||
|
{
|
||||||
|
PRInt32 i;
|
||||||
|
PRInt32 count = mChildren->Count();
|
||||||
|
for (i=0; i<count; i++)
|
||||||
|
{
|
||||||
|
EditTxn *txn = (EditTxn*)(mChildren->ElementAt(i));
|
||||||
|
NS_IF_RELEASE(txn);
|
||||||
|
}
|
||||||
|
delete mChildren;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult EditAggregateTxn::Do(void)
|
||||||
|
{
|
||||||
|
nsresult result=NS_OK; // it's legal (but not very useful) to have an empty child list
|
||||||
|
if (nsnull!=mChildren)
|
||||||
|
{
|
||||||
|
PRInt32 i;
|
||||||
|
PRInt32 count = mChildren->Count();
|
||||||
|
for (i=0; i<count; i++)
|
||||||
|
{
|
||||||
|
EditTxn *txn = (EditTxn*)(mChildren->ElementAt(i));
|
||||||
|
result = txn->Do();
|
||||||
|
if (NS_FAILED(result))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult EditAggregateTxn::Undo(void)
|
||||||
|
{
|
||||||
|
nsresult result=NS_OK; // it's legal (but not very useful) to have an empty child list
|
||||||
|
if (nsnull!=mChildren)
|
||||||
|
{
|
||||||
|
PRInt32 i;
|
||||||
|
PRInt32 count = mChildren->Count();
|
||||||
|
// undo goes through children backwards
|
||||||
|
for (i=count-1; i>=0; i--)
|
||||||
|
{
|
||||||
|
EditTxn *txn = (EditTxn*)(mChildren->ElementAt(i));
|
||||||
|
result = txn->Undo();
|
||||||
|
if (NS_FAILED(result))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult EditAggregateTxn::Redo(void)
|
||||||
|
{
|
||||||
|
nsresult result=NS_OK; // it's legal (but not very useful) to have an empty child list
|
||||||
|
if (nsnull!=mChildren)
|
||||||
|
{
|
||||||
|
PRInt32 i;
|
||||||
|
PRInt32 count = mChildren->Count();
|
||||||
|
for (i=0; i<count; i++)
|
||||||
|
{
|
||||||
|
EditTxn *txn = (EditTxn*)(mChildren->ElementAt(i));
|
||||||
|
result = txn->Redo();
|
||||||
|
if (NS_FAILED(result))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult EditAggregateTxn::GetIsTransient(PRBool *aIsTransient)
|
||||||
|
{
|
||||||
|
if (nsnull!=aIsTransient)
|
||||||
|
*aIsTransient = PR_TRUE;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult EditAggregateTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
|
||||||
|
{
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult EditAggregateTxn::Write(nsIOutputStream *aOutputStream)
|
||||||
|
{
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult EditAggregateTxn::GetUndoString(nsString **aString)
|
||||||
|
{
|
||||||
|
if (nsnull!=aString)
|
||||||
|
*aString=nsnull;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult EditAggregateTxn::GetRedoString(nsString **aString)
|
||||||
|
{
|
||||||
|
if (nsnull!=aString)
|
||||||
|
*aString=nsnull;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult EditAggregateTxn::AppendChild(EditTxn *aTxn)
|
||||||
|
{
|
||||||
|
if ((nsnull!=mChildren) && (nsnull!=aTxn))
|
||||||
|
{
|
||||||
|
mChildren->AppendElement(aTxn);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public License
|
||||||
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||||
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||||
|
* http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* NPL.
|
||||||
|
*
|
||||||
|
* The Initial Developer of this code under the NPL is Netscape
|
||||||
|
* Communications Corporation. Portions created by Netscape are
|
||||||
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||||
|
* Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EditAggregateTxn_h__
|
||||||
|
#define EditAggregateTxn_h__
|
||||||
|
|
||||||
|
#include "EditTxn.h"
|
||||||
|
|
||||||
|
#define EDIT_AGGREGATE_TXN_IID \
|
||||||
|
{/* 345921a0-ac49-11d2-86d8-000064657374 */ \
|
||||||
|
0x345921a0, 0xac49, 0x11d2, \
|
||||||
|
{0x86, 0xd8, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
|
||||||
|
|
||||||
|
class nsVoidArray;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* base class for all document editing transactions that require aggregation.
|
||||||
|
* provides a list of child transactions.
|
||||||
|
*/
|
||||||
|
class EditAggregateTxn : public EditTxn
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
EditAggregateTxn();
|
||||||
|
|
||||||
|
virtual ~EditAggregateTxn();
|
||||||
|
|
||||||
|
virtual nsresult Do(void);
|
||||||
|
|
||||||
|
virtual nsresult Undo(void);
|
||||||
|
|
||||||
|
virtual nsresult Redo(void);
|
||||||
|
|
||||||
|
virtual nsresult GetIsTransient(PRBool *aIsTransient);
|
||||||
|
|
||||||
|
virtual nsresult Merge(PRBool *aDidMerge, nsITransaction *aTransaction);
|
||||||
|
|
||||||
|
virtual nsresult Write(nsIOutputStream *aOutputStream);
|
||||||
|
|
||||||
|
virtual nsresult GetUndoString(nsString **aString);
|
||||||
|
|
||||||
|
virtual nsresult GetRedoString(nsString **aString);
|
||||||
|
|
||||||
|
virtual nsresult AppendChild(EditTxn *aTxn);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
nsVoidArray *mChildren;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -28,10 +28,8 @@ NS_IMPL_ADDREF(EditTxn)
|
||||||
NS_IMPL_RELEASE(EditTxn)
|
NS_IMPL_RELEASE(EditTxn)
|
||||||
|
|
||||||
// note that aEditor is not refcounted
|
// note that aEditor is not refcounted
|
||||||
EditTxn::EditTxn(nsEditor *aEditor)
|
EditTxn::EditTxn()
|
||||||
{
|
{
|
||||||
NS_ASSERTION(nsnull!=aEditor, "null aEditor arg to EditTxn constructor");
|
|
||||||
mEditor = aEditor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult EditTxn::Do(void)
|
nsresult EditTxn::Do(void)
|
||||||
|
|
|
@ -20,13 +20,17 @@
|
||||||
#define EditTxn_h__
|
#define EditTxn_h__
|
||||||
|
|
||||||
#include "nsITransaction.h"
|
#include "nsITransaction.h"
|
||||||
class nsEditor;
|
|
||||||
|
|
||||||
class nsIDOMNode;
|
class nsIDOMNode;
|
||||||
|
|
||||||
|
#define EDIT_TXN_IID \
|
||||||
|
{/* c5ea31b0-ac48-11d2-86d8-000064657374 */ \
|
||||||
|
0xc5ea31b0, 0xac48, 0x11d2, \
|
||||||
|
{0x86, 0xd8, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* base class for all document editing transactions.
|
* base class for all document editing transactions.
|
||||||
* provides access to the nsEditor that created this transaction.
|
* provides default concrete behavior for all nsITransaction methods.
|
||||||
*/
|
*/
|
||||||
class EditTxn : public nsITransaction
|
class EditTxn : public nsITransaction
|
||||||
{
|
{
|
||||||
|
@ -34,7 +38,7 @@ public:
|
||||||
|
|
||||||
NS_DECL_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
|
|
||||||
EditTxn(nsEditor *aEditor);
|
EditTxn();
|
||||||
|
|
||||||
virtual nsresult Do(void);
|
virtual nsresult Do(void);
|
||||||
|
|
||||||
|
@ -52,10 +56,6 @@ public:
|
||||||
|
|
||||||
virtual nsresult GetRedoString(nsString **aString);
|
virtual nsresult GetRedoString(nsString **aString);
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
nsEditor *mEditor;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -20,18 +20,22 @@
|
||||||
#include "editor.h"
|
#include "editor.h"
|
||||||
#include "nsIDOMCharacterData.h"
|
#include "nsIDOMCharacterData.h"
|
||||||
|
|
||||||
static NS_DEFINE_IID(kInsertTextTxnIID, INSERTTEXTTXN_IID);
|
static NS_DEFINE_IID(kInsertTextTxnIID, INSERT_TEXT_TXN_IID);
|
||||||
|
|
||||||
// note that aEditor is not refcounted
|
|
||||||
InsertTextTxn::InsertTextTxn(nsEditor *aEditor,
|
InsertTextTxn::InsertTextTxn()
|
||||||
nsIDOMCharacterData *aElement,
|
: EditTxn()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult InsertTextTxn::Init(nsIDOMCharacterData *aElement,
|
||||||
PRUint32 aOffset,
|
PRUint32 aOffset,
|
||||||
const nsString& aStringToInsert)
|
const nsString& aStringToInsert)
|
||||||
: EditTxn(aEditor)
|
|
||||||
{
|
{
|
||||||
mElement = aElement;
|
mElement = aElement;
|
||||||
mOffset = aOffset;
|
mOffset = aOffset;
|
||||||
mStringToInsert = aStringToInsert;
|
mStringToInsert = aStringToInsert;
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult InsertTextTxn::Do(void)
|
nsresult InsertTextTxn::Do(void)
|
||||||
|
@ -60,11 +64,11 @@ nsresult InsertTextTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
|
||||||
if ((nsnull!=aDidMerge) && (nsnull!=aTransaction))
|
if ((nsnull!=aDidMerge) && (nsnull!=aTransaction))
|
||||||
{
|
{
|
||||||
// if aTransaction isa InsertTextTxn, absorb it
|
// if aTransaction isa InsertTextTxn, absorb it
|
||||||
nsCOMPtr<InsertTextTxn> otherTxn;
|
nsCOMPtr<InsertTextTxn> otherTxn = aTransaction;
|
||||||
nsresult result = aTransaction->QueryInterface(kInsertTextTxnIID, getter_AddRefs(otherTxn));
|
nsresult result=NS_OK;// = aTransaction->QueryInterface(kInsertTextTxnIID, getter_AddRefs(otherTxn));
|
||||||
if (NS_SUCCEEDED(result) && (otherTxn))
|
if (NS_SUCCEEDED(result) && (otherTxn))
|
||||||
{
|
{
|
||||||
nsString otherData;
|
nsAutoString otherData;
|
||||||
otherTxn->GetData(otherData);
|
otherTxn->GetData(otherData);
|
||||||
mStringToInsert += otherData;
|
mStringToInsert += otherData;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,14 +20,14 @@
|
||||||
#define InsertTextTxn_h__
|
#define InsertTextTxn_h__
|
||||||
|
|
||||||
#include "EditTxn.h"
|
#include "EditTxn.h"
|
||||||
|
#include "nsIDOMCharacterData.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
|
||||||
#define INSERTTEXTTXN_IID \
|
#define INSERT_TEXT_TXN_IID \
|
||||||
{/* 93276f00-ab2c-11d2-8f4b-006008159b0c*/ \
|
{/* 93276f00-ab2c-11d2-8f4b-006008159b0c*/ \
|
||||||
0x93276f00, 0xab2c, 0x11d2, \
|
0x93276f00, 0xab2c, 0x11d2, \
|
||||||
{0x8f, 0xb4, 0x0, 0x60, 0x8, 0x15, 0x9b, 0xc} }
|
{0x8f, 0xb4, 0x0, 0x60, 0x8, 0x15, 0x9b, 0xc} }
|
||||||
|
|
||||||
class nsIDOMCharacterData;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A transaction that changes an attribute of a content node.
|
* A transaction that changes an attribute of a content node.
|
||||||
* This transaction covers add, remove, and change attribute.
|
* This transaction covers add, remove, and change attribute.
|
||||||
|
@ -36,15 +36,13 @@ class InsertTextTxn : public EditTxn
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
InsertTextTxn(nsEditor *aEditor,
|
virtual nsresult Init(nsIDOMCharacterData *aElement,
|
||||||
nsIDOMCharacterData *aElement,
|
PRUint32 aOffset,
|
||||||
PRUint32 aOffset,
|
const nsString& aStringToInsert);
|
||||||
const nsString& aStringToInsert);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// default ctor so that nsCOMPtr is happy
|
InsertTextTxn();
|
||||||
InsertTextTxn() : EditTxn(nsnull) {}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -67,7 +65,7 @@ public:
|
||||||
// override QueryInterface to handle InsertTextTxn request
|
// override QueryInterface to handle InsertTextTxn request
|
||||||
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
|
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
|
||||||
|
|
||||||
static const nsIID& IID() { static nsIID iid = INSERTTEXTTXN_IID; return iid; }
|
static const nsIID& IID() { static nsIID iid = INSERT_TEXT_TXN_IID; return iid; }
|
||||||
|
|
||||||
|
|
||||||
virtual nsresult GetData(nsString& aResult);
|
virtual nsresult GetData(nsString& aResult);
|
||||||
|
@ -75,7 +73,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/** the text element to operate upon */
|
/** the text element to operate upon */
|
||||||
nsIDOMCharacterData *mElement;
|
nsCOMPtr<nsIDOMCharacterData> mElement;
|
||||||
|
|
||||||
/** the offset into mElement where the insertion is to take place */
|
/** the offset into mElement where the insertion is to take place */
|
||||||
PRUint32 mOffset;
|
PRUint32 mOffset;
|
||||||
|
@ -86,6 +84,8 @@ protected:
|
||||||
/** the text to insert into mElement at mOffset */
|
/** the text to insert into mElement at mOffset */
|
||||||
nsString mStringToInsert;
|
nsString mStringToInsert;
|
||||||
|
|
||||||
|
friend class TransactionFactory;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public License
|
||||||
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||||
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||||
|
* http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* NPL.
|
||||||
|
*
|
||||||
|
* The Initial Developer of this code under the NPL is Netscape
|
||||||
|
* Communications Corporation. Portions created by Netscape are
|
||||||
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||||
|
* Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "JoinElementTxn.h"
|
||||||
|
#include "nsIDOMNodeList.h"
|
||||||
|
#include "editor.h"
|
||||||
|
|
||||||
|
|
||||||
|
JoinElementTxn::JoinElementTxn()
|
||||||
|
: EditTxn()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult JoinElementTxn::Init(nsIDOMNode *aLeftNode,
|
||||||
|
nsIDOMNode *aRightNode)
|
||||||
|
{
|
||||||
|
mLeftNode = aLeftNode;
|
||||||
|
mRightNode = aRightNode;
|
||||||
|
mOffset=0;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
JoinElementTxn::~JoinElementTxn()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult JoinElementTxn::Do(void)
|
||||||
|
{
|
||||||
|
nsresult result;
|
||||||
|
|
||||||
|
if ((mLeftNode) && (mRightNode))
|
||||||
|
{ // get the parent node
|
||||||
|
nsCOMPtr<nsIDOMNode>leftParent;
|
||||||
|
result = mLeftNode->GetParentNode(getter_AddRefs(leftParent));
|
||||||
|
if ((NS_SUCCEEDED(result)) && (leftParent))
|
||||||
|
{ // verify that mLeftNode and mRightNode have the same parent
|
||||||
|
nsCOMPtr<nsIDOMNode>rightParent;
|
||||||
|
result = mRightNode->GetParentNode(getter_AddRefs(rightParent));
|
||||||
|
if ((NS_SUCCEEDED(result)) && (rightParent))
|
||||||
|
{
|
||||||
|
if (leftParent==rightParent)
|
||||||
|
{
|
||||||
|
mParent=leftParent; // set this instance mParent.
|
||||||
|
// Other methods see a non-null mParent and know all is well
|
||||||
|
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||||
|
result = mLeftNode->GetChildNodes(getter_AddRefs(childNodes));
|
||||||
|
if ((NS_SUCCEEDED(result)) && (childNodes))
|
||||||
|
{
|
||||||
|
childNodes->GetLength(&mOffset);
|
||||||
|
}
|
||||||
|
result = nsEditor::JoinNodes(mLeftNode, mRightNode, mParent, PR_FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
nsresult JoinElementTxn::Undo(void)
|
||||||
|
{
|
||||||
|
nsresult result = nsEditor::SplitNode(mRightNode, mOffset, mLeftNode, mParent);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult JoinElementTxn::Redo(void)
|
||||||
|
{
|
||||||
|
nsresult result = nsEditor::JoinNodes(mLeftNode, mRightNode, mParent, PR_FALSE);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult JoinElementTxn::GetIsTransient(PRBool *aIsTransient)
|
||||||
|
{
|
||||||
|
if (nsnull!=aIsTransient)
|
||||||
|
*aIsTransient = PR_FALSE;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult JoinElementTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
|
||||||
|
{
|
||||||
|
if (nsnull!=aDidMerge)
|
||||||
|
*aDidMerge=PR_FALSE;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult JoinElementTxn::Write(nsIOutputStream *aOutputStream)
|
||||||
|
{
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult JoinElementTxn::GetUndoString(nsString **aString)
|
||||||
|
{
|
||||||
|
if (nsnull!=aString)
|
||||||
|
{
|
||||||
|
**aString="Join Element";
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult JoinElementTxn::GetRedoString(nsString **aString)
|
||||||
|
{
|
||||||
|
if (nsnull!=aString)
|
||||||
|
{
|
||||||
|
**aString="Split Element";
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public License
|
||||||
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||||
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||||
|
* http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* NPL.
|
||||||
|
*
|
||||||
|
* The Initial Developer of this code under the NPL is Netscape
|
||||||
|
* Communications Corporation. Portions created by Netscape are
|
||||||
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||||
|
* Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef JoinElementTxn_h__
|
||||||
|
#define JoinElementTxn_h__
|
||||||
|
|
||||||
|
#include "EditTxn.h"
|
||||||
|
#include "nsIDOMNode.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
|
||||||
|
#define JOIN_ELEMENT_TXN_IID \
|
||||||
|
{/* 9bc5f9f0-ac48-11d2-86d8-000064657374 */ \
|
||||||
|
0x9bc5f9f0, 0xac48, 0x11d2, \
|
||||||
|
{0x86, 0xd8, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A transaction that joins two elements E1 and E2 into a single node E.
|
||||||
|
* The children of E are the children of E1 followed by the children of E2.
|
||||||
|
*/
|
||||||
|
class JoinElementTxn : public EditTxn
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual nsresult Init(nsIDOMNode *aLeftNode,
|
||||||
|
nsIDOMNode *aRightNode);
|
||||||
|
protected:
|
||||||
|
JoinElementTxn();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual ~JoinElementTxn();
|
||||||
|
|
||||||
|
virtual nsresult Do(void);
|
||||||
|
|
||||||
|
virtual nsresult Undo(void);
|
||||||
|
|
||||||
|
virtual nsresult Redo(void);
|
||||||
|
|
||||||
|
virtual nsresult GetIsTransient(PRBool *aIsTransient);
|
||||||
|
|
||||||
|
virtual nsresult Merge(PRBool *aDidMerge, nsITransaction *aTransaction);
|
||||||
|
|
||||||
|
virtual nsresult Write(nsIOutputStream *aOutputStream);
|
||||||
|
|
||||||
|
virtual nsresult GetUndoString(nsString **aString);
|
||||||
|
|
||||||
|
virtual nsresult GetRedoString(nsString **aString);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/** the elements to operate upon.
|
||||||
|
* After the merge, mRightNode remains and mLeftNode is removed from the content tree.
|
||||||
|
*/
|
||||||
|
nsCOMPtr<nsIDOMNode> mLeftNode;
|
||||||
|
nsCOMPtr<nsIDOMNode> mRightNode;
|
||||||
|
|
||||||
|
/** the offset into mNode where the children of mElement are split (for undo).<BR>
|
||||||
|
* mOffset is the index of the last child in the left node.
|
||||||
|
* -1 means the left node gets no children.
|
||||||
|
*/
|
||||||
|
PRUint32 mOffset;
|
||||||
|
|
||||||
|
/** the parent node containing mLeftNode and mRightNode */
|
||||||
|
nsCOMPtr<nsIDOMNode> mParent;
|
||||||
|
|
||||||
|
friend class TransactionFactory;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -30,12 +30,15 @@ CPPSRCS = \
|
||||||
nsEditFactory.cpp \
|
nsEditFactory.cpp \
|
||||||
ChangeAttributeTxn.cpp \
|
ChangeAttributeTxn.cpp \
|
||||||
EditTxn.cpp \
|
EditTxn.cpp \
|
||||||
|
EditAggregateTxn.cpp \
|
||||||
InsertTextTxn.cpp \
|
InsertTextTxn.cpp \
|
||||||
DeleteTextTxn.cpp \
|
DeleteTextTxn.cpp \
|
||||||
CreateElementTxn.cpp \
|
CreateElementTxn.cpp \
|
||||||
DeleteElementTxn.cpp \
|
DeleteElementTxn.cpp \
|
||||||
DeleteRangeTxn.cpp \
|
DeleteRangeTxn.cpp \
|
||||||
SplitElementTxn.cpp \
|
SplitElementTxn.cpp \
|
||||||
|
JoinElementTxn.cpp \
|
||||||
|
TransactionFactory.cpp \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
MODULE = editor
|
MODULE = editor
|
||||||
|
|
|
@ -17,44 +17,42 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "SplitElementTxn.h"
|
#include "SplitElementTxn.h"
|
||||||
#include "editor.h"
|
|
||||||
#include "nsIDOMNode.h"
|
#include "nsIDOMNode.h"
|
||||||
#include "nsIDOMElement.h"
|
#include "nsIDOMElement.h"
|
||||||
|
#include "editor.h"
|
||||||
|
|
||||||
// note that aEditor is not refcounted
|
// note that aEditor is not refcounted
|
||||||
SplitElementTxn::SplitElementTxn(nsEditor *aEditor,
|
SplitElementTxn::SplitElementTxn()
|
||||||
nsIDOMNode *aNode,
|
: EditTxn()
|
||||||
PRInt32 aOffset)
|
|
||||||
: EditTxn(aEditor)
|
|
||||||
{
|
{
|
||||||
mNode = aNode;
|
}
|
||||||
NS_ADDREF(mNode);
|
|
||||||
|
nsresult SplitElementTxn::Init(nsIDOMNode *aNode,
|
||||||
|
PRInt32 aOffset)
|
||||||
|
{
|
||||||
|
mExistingRightNode = aNode;
|
||||||
mOffset = aOffset;
|
mOffset = aOffset;
|
||||||
mNewNode = nsnull;
|
return NS_OK;
|
||||||
mParent = nsnull;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SplitElementTxn::~SplitElementTxn()
|
SplitElementTxn::~SplitElementTxn()
|
||||||
{
|
{
|
||||||
NS_IF_RELEASE(mNode);
|
|
||||||
NS_IF_RELEASE(mNewNode);
|
|
||||||
NS_IF_RELEASE(mParent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult SplitElementTxn::Do(void)
|
nsresult SplitElementTxn::Do(void)
|
||||||
{
|
{
|
||||||
// create a new node
|
// create a new node
|
||||||
nsresult result = mNode->CloneNode(PR_FALSE, &mNewNode);
|
nsresult result = mExistingRightNode->CloneNode(PR_FALSE, getter_AddRefs(mNewLeftNode));
|
||||||
NS_ASSERTION(((NS_SUCCEEDED(result)) && (nsnull!=mNewNode)), "could not create element.");
|
NS_ASSERTION(((NS_SUCCEEDED(result)) && (mNewLeftNode)), "could not create element.");
|
||||||
|
|
||||||
if ((NS_SUCCEEDED(result)) && (nsnull!=mNewNode))
|
if ((NS_SUCCEEDED(result)) && (mNewLeftNode))
|
||||||
{
|
{
|
||||||
// get the parent node
|
// get the parent node
|
||||||
result = mNode->GetParentNode(&mParent);
|
result = mExistingRightNode->GetParentNode(getter_AddRefs(mParent));
|
||||||
// insert the new node
|
// insert the new node
|
||||||
if ((NS_SUCCEEDED(result)) && (nsnull!=mParent))
|
if ((NS_SUCCEEDED(result)) && (mParent))
|
||||||
{
|
{
|
||||||
result = mEditor->SplitNode(mNode, mOffset, mNewNode, mParent);
|
result = nsEditor::SplitNode(mExistingRightNode, mOffset, mNewLeftNode, mParent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -63,13 +61,13 @@ nsresult SplitElementTxn::Do(void)
|
||||||
nsresult SplitElementTxn::Undo(void)
|
nsresult SplitElementTxn::Undo(void)
|
||||||
{
|
{
|
||||||
// this assumes Do inserted the new node in front of the prior existing node
|
// this assumes Do inserted the new node in front of the prior existing node
|
||||||
nsresult result = mEditor->JoinNodes(mNode, mNewNode, mParent, PR_FALSE);
|
nsresult result = nsEditor::JoinNodes(mExistingRightNode, mNewLeftNode, mParent, PR_FALSE);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult SplitElementTxn::Redo(void)
|
nsresult SplitElementTxn::Redo(void)
|
||||||
{
|
{
|
||||||
nsresult result = mEditor->SplitNode(mNode, mOffset, mNewNode, mParent);
|
nsresult result = nsEditor::SplitNode(mExistingRightNode, mOffset, mNewLeftNode, mParent);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,10 +20,13 @@
|
||||||
#define SplitElementTxn_h__
|
#define SplitElementTxn_h__
|
||||||
|
|
||||||
#include "EditTxn.h"
|
#include "EditTxn.h"
|
||||||
|
#include "nsIDOMNode.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
|
||||||
class nsIDOMNode;
|
#define SPLIT_ELEMENT_TXN_IID \
|
||||||
class nsIDOMElement;
|
{/* 690c6290-ac48-11d2-86d8-000064657374 */ \
|
||||||
class nsIDOMDocument;
|
0x690c6290, 0xac48, 0x11d2, \
|
||||||
|
{0x86, 0xd8, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A transaction that splits an element E into two identical nodes, E1 and E2
|
* A transaction that splits an element E into two identical nodes, E1 and E2
|
||||||
|
@ -33,10 +36,12 @@ class SplitElementTxn : public EditTxn
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
SplitElementTxn(nsEditor *aEditor,
|
virtual nsresult Init (nsIDOMNode *aNode,
|
||||||
nsIDOMNode *aNode,
|
PRInt32 aOffset);
|
||||||
PRInt32 aOffset);
|
protected:
|
||||||
|
SplitElementTxn();
|
||||||
|
|
||||||
|
public:
|
||||||
virtual ~SplitElementTxn();
|
virtual ~SplitElementTxn();
|
||||||
|
|
||||||
virtual nsresult Do(void);
|
virtual nsresult Do(void);
|
||||||
|
@ -58,7 +63,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/** the element to operate upon */
|
/** the element to operate upon */
|
||||||
nsIDOMNode *mNode;
|
nsCOMPtr<nsIDOMNode> mExistingRightNode;
|
||||||
|
|
||||||
/** the offset into mElement where the children of mElement are split.<BR>
|
/** the offset into mElement where the children of mElement are split.<BR>
|
||||||
* mOffset is the index of the last child in the left node.
|
* mOffset is the index of the last child in the left node.
|
||||||
|
@ -67,8 +72,12 @@ protected:
|
||||||
PRInt32 mOffset;
|
PRInt32 mOffset;
|
||||||
|
|
||||||
/** the element we create when splitting mElement */
|
/** the element we create when splitting mElement */
|
||||||
nsIDOMNode *mNewNode;
|
nsCOMPtr<nsIDOMNode> mNewLeftNode;
|
||||||
nsIDOMNode *mParent;
|
|
||||||
|
/** the parent shared by mExistingRightNode and mNewLeftNode */
|
||||||
|
nsCOMPtr<nsIDOMNode> mParent;
|
||||||
|
|
||||||
|
friend class TransactionFactory;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public License
|
||||||
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||||
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||||
|
* http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* NPL.
|
||||||
|
*
|
||||||
|
* The Initial Developer of this code under the NPL is Netscape
|
||||||
|
* Communications Corporation. Portions created by Netscape are
|
||||||
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||||
|
* Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "TransactionFactory.h"
|
||||||
|
// transactions this factory knows how to build
|
||||||
|
#include "InsertTextTxn.h"
|
||||||
|
#include "DeleteTextTxn.h"
|
||||||
|
#include "CreateElementTxn.h"
|
||||||
|
#include "DeleteElementTxn.h"
|
||||||
|
#include "DeleteRangeTxn.h"
|
||||||
|
#include "ChangeAttributeTxn.h"
|
||||||
|
#include "SplitElementTxn.h"
|
||||||
|
#include "JoinElementTxn.h"
|
||||||
|
|
||||||
|
static NS_DEFINE_IID(kInsertTextTxnIID, INSERT_TEXT_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kDeleteTextTxnIID, DELETE_TEXT_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kCreateElementTxnIID, CREATE_ELEMENT_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kDeleteElementTxnIID, DELETE_ELEMENT_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kDeleteRangeTxnIID, DELETE_RANGE_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kChangeAttributeTxnIID,CHANGE_ATTRIBUTE_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kSplitElementTxnIID, SPLIT_ELEMENT_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kJoinElementTxnIID, JOIN_ELEMENT_TXN_IID);
|
||||||
|
|
||||||
|
TransactionFactory::TransactionFactory()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
TransactionFactory::~TransactionFactory()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
TransactionFactory::GetNewTransaction(REFNSIID aTxnType, EditTxn **aResult)
|
||||||
|
{
|
||||||
|
nsresult result = NS_OK;
|
||||||
|
*aResult = nsnull;
|
||||||
|
if (aTxnType.Equals(kInsertTextTxnIID))
|
||||||
|
*aResult = new InsertTextTxn();
|
||||||
|
else if (aTxnType.Equals(kDeleteTextTxnIID))
|
||||||
|
*aResult = new DeleteTextTxn();
|
||||||
|
else if (aTxnType.Equals(kCreateElementTxnIID))
|
||||||
|
*aResult = new CreateElementTxn();
|
||||||
|
else if (aTxnType.Equals(kDeleteElementTxnIID))
|
||||||
|
*aResult = new DeleteElementTxn();
|
||||||
|
else if (aTxnType.Equals(kDeleteRangeTxnIID))
|
||||||
|
*aResult = new DeleteRangeTxn();
|
||||||
|
else if (aTxnType.Equals(kChangeAttributeTxnIID))
|
||||||
|
*aResult = new ChangeAttributeTxn();
|
||||||
|
else if (aTxnType.Equals(kSplitElementTxnIID))
|
||||||
|
*aResult = new SplitElementTxn();
|
||||||
|
else if (aTxnType.Equals(kJoinElementTxnIID))
|
||||||
|
*aResult = new JoinElementTxn();
|
||||||
|
|
||||||
|
if (nsnull==*aResult)
|
||||||
|
result = NS_ERROR_INVALID_ARG;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public License
|
||||||
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||||
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||||
|
* http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* NPL.
|
||||||
|
*
|
||||||
|
* The Initial Developer of this code under the NPL is Netscape
|
||||||
|
* Communications Corporation. Portions created by Netscape are
|
||||||
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||||
|
* Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TransactionFactory_h__
|
||||||
|
#define TransactionFactory_h__
|
||||||
|
|
||||||
|
#include "nsISupports.h"
|
||||||
|
|
||||||
|
class EditTxn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class instantiates and optionally recycles edit transactions
|
||||||
|
* A recycler would be a separate static object, since this class does not get instantiated
|
||||||
|
*/
|
||||||
|
class TransactionFactory
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
TransactionFactory();
|
||||||
|
virtual ~TransactionFactory();
|
||||||
|
|
||||||
|
public:
|
||||||
|
static nsresult GetNewTransaction(REFNSIID aTxnType, EditTxn **aResult);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -33,16 +33,22 @@
|
||||||
#include "nsTransactionManagerCID.h"
|
#include "nsTransactionManagerCID.h"
|
||||||
#include "nsITransactionManager.h"
|
#include "nsITransactionManager.h"
|
||||||
#include "nsIPresShell.h"
|
#include "nsIPresShell.h"
|
||||||
|
#include "nsIViewManager.h"
|
||||||
#include "nsISelection.h"
|
#include "nsISelection.h"
|
||||||
|
#include "nsICollection.h"
|
||||||
|
#include "nsIEnumerator.h"
|
||||||
#include "nsIAtom.h"
|
#include "nsIAtom.h"
|
||||||
|
|
||||||
// transactions the editor knows how to build
|
// transactions the editor knows how to build
|
||||||
|
#include "TransactionFactory.h"
|
||||||
#include "ChangeAttributeTxn.h"
|
#include "ChangeAttributeTxn.h"
|
||||||
#include "CreateElementTxn.h"
|
#include "CreateElementTxn.h"
|
||||||
#include "DeleteElementTxn.h"
|
#include "DeleteElementTxn.h"
|
||||||
#include "InsertTextTxn.h"
|
#include "InsertTextTxn.h"
|
||||||
#include "DeleteTextTxn.h"
|
#include "DeleteTextTxn.h"
|
||||||
#include "DeleteRangeTxn.h"
|
#include "DeleteRangeTxn.h"
|
||||||
|
#include "SplitElementTxn.h"
|
||||||
|
#include "JoinElementTxn.h"
|
||||||
|
|
||||||
|
|
||||||
static NS_DEFINE_IID(kIDOMEventReceiverIID, NS_IDOMEVENTRECEIVER_IID);
|
static NS_DEFINE_IID(kIDOMEventReceiverIID, NS_IDOMEVENTRECEIVER_IID);
|
||||||
|
@ -58,8 +64,18 @@ static NS_DEFINE_IID(kIEditFactoryIID, NS_IEDITORFACTORY_IID);
|
||||||
static NS_DEFINE_IID(kIEditorIID, NS_IEDITOR_IID);
|
static NS_DEFINE_IID(kIEditorIID, NS_IEDITOR_IID);
|
||||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||||
static NS_DEFINE_IID(kEditorCID, NS_EDITOR_CID);
|
static NS_DEFINE_IID(kEditorCID, NS_EDITOR_CID);
|
||||||
|
// transaction manager
|
||||||
static NS_DEFINE_IID(kITransactionManagerIID, NS_ITRANSACTIONMANAGER_IID);
|
static NS_DEFINE_IID(kITransactionManagerIID, NS_ITRANSACTIONMANAGER_IID);
|
||||||
static NS_DEFINE_CID(kCTransactionManagerFactoryCID, NS_TRANSACTION_MANAGER_FACTORY_CID);
|
static NS_DEFINE_CID(kCTransactionManagerFactoryCID, NS_TRANSACTION_MANAGER_FACTORY_CID);
|
||||||
|
// transactions
|
||||||
|
static NS_DEFINE_IID(kInsertTextTxnIID, INSERT_TEXT_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kDeleteTextTxnIID, DELETE_TEXT_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kCreateElementTxnIID, CREATE_ELEMENT_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kDeleteElementTxnIID, DELETE_ELEMENT_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kDeleteRangeTxnIID, DELETE_RANGE_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kChangeAttributeTxnIID,CHANGE_ATTRIBUTE_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kSplitElementTxnIID, SPLIT_ELEMENT_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kJoinElementTxnIID, JOIN_ELEMENT_TXN_IID);
|
||||||
|
|
||||||
|
|
||||||
#ifdef XP_PC
|
#ifdef XP_PC
|
||||||
|
@ -165,6 +181,7 @@ nsEditor::nsEditor()
|
||||||
nsEditor::~nsEditor()
|
nsEditor::~nsEditor()
|
||||||
{
|
{
|
||||||
NS_IF_RELEASE(mPresShell);
|
NS_IF_RELEASE(mPresShell);
|
||||||
|
NS_IF_RELEASE(mViewManager);
|
||||||
NS_IF_RELEASE(mTxnMgr);
|
NS_IF_RELEASE(mTxnMgr);
|
||||||
|
|
||||||
//the autopointers will clear themselves up.
|
//the autopointers will clear themselves up.
|
||||||
|
@ -229,6 +246,8 @@ nsEditor::Init(nsIDOMDocument *aDomInterface, nsIPresShell* aPresShell)
|
||||||
mDomInterfaceP = aDomInterface;
|
mDomInterfaceP = aDomInterface;
|
||||||
mPresShell = aPresShell;
|
mPresShell = aPresShell;
|
||||||
NS_ADDREF(mPresShell);
|
NS_ADDREF(mPresShell);
|
||||||
|
mViewManager = mPresShell->GetViewManager();
|
||||||
|
mUpdateCount=0;
|
||||||
|
|
||||||
nsresult t_result = NS_NewEditorKeyListener(getter_AddRefs(mKeyListenerP), this);
|
nsresult t_result = NS_NewEditorKeyListener(getter_AddRefs(mKeyListenerP), this);
|
||||||
if (NS_OK != t_result)
|
if (NS_OK != t_result)
|
||||||
|
@ -308,13 +327,13 @@ nsEditor::Init(nsIDOMDocument *aDomInterface, nsIPresShell* aPresShell)
|
||||||
nsresult
|
nsresult
|
||||||
nsEditor::InsertString(nsString *aString)
|
nsEditor::InsertString(nsString *aString)
|
||||||
{
|
{
|
||||||
return AppendText(aString);
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsEditor::SetProperties(PROPERTIES aProperty)
|
nsEditor::SetProperties(Properties aProperties)
|
||||||
{
|
{
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -322,7 +341,7 @@ nsEditor::SetProperties(PROPERTIES aProperty)
|
||||||
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsEditor::GetProperties(PROPERTIES **)
|
nsEditor::GetProperties(Properties **aProperties)
|
||||||
{
|
{
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -334,9 +353,13 @@ nsEditor::SetAttribute(nsIDOMElement *aElement, const nsString& aAttribute, cons
|
||||||
nsresult result;
|
nsresult result;
|
||||||
if (nsnull != aElement)
|
if (nsnull != aElement)
|
||||||
{
|
{
|
||||||
ChangeAttributeTxn *txn = new ChangeAttributeTxn(this, aElement, aAttribute, aValue, PR_FALSE);
|
ChangeAttributeTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kChangeAttributeTxnIID, (EditTxn **)&txn);
|
||||||
if (nsnull!=txn)
|
if (nsnull!=txn)
|
||||||
result = ExecuteTransaction(txn);
|
{
|
||||||
|
txn->Init(this, aElement, aAttribute, aValue, PR_FALSE);
|
||||||
|
result = Do(txn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -369,10 +392,14 @@ nsEditor::RemoveAttribute(nsIDOMElement *aElement, const nsString& aAttribute)
|
||||||
nsresult result;
|
nsresult result;
|
||||||
if (nsnull != aElement)
|
if (nsnull != aElement)
|
||||||
{
|
{
|
||||||
nsString value;
|
ChangeAttributeTxn *txn;
|
||||||
ChangeAttributeTxn *txn = new ChangeAttributeTxn(this, aElement, aAttribute, value, PR_TRUE);
|
result = TransactionFactory::GetNewTransaction(kChangeAttributeTxnIID, (EditTxn **)&txn);
|
||||||
if (nsnull!=txn)
|
if (nsnull!=txn)
|
||||||
result = ExecuteTransaction(txn);
|
{
|
||||||
|
nsAutoString value;
|
||||||
|
txn->Init(this, aElement, aAttribute, value, PR_TRUE);
|
||||||
|
result = Do(txn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -420,26 +447,6 @@ nsEditor::MouseClick(int aX,int aY)
|
||||||
//BEGIN nsEditor Private methods
|
//BEGIN nsEditor Private methods
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
nsEditor::AppendText(nsString *aStr)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIDOMNode> currentNode;
|
|
||||||
nsCOMPtr<nsIDOMNode> textNode;
|
|
||||||
nsCOMPtr<nsIDOMText> text;
|
|
||||||
if (!aStr)
|
|
||||||
return NS_ERROR_NULL_POINTER;
|
|
||||||
if (NS_SUCCEEDED(GetCurrentNode(getter_AddRefs(currentNode))) &&
|
|
||||||
NS_SUCCEEDED(GetFirstTextNode(currentNode,getter_AddRefs(textNode))) &&
|
|
||||||
NS_SUCCEEDED(textNode->QueryInterface(kIDOMTextIID, getter_AddRefs(text)))) {
|
|
||||||
text->AppendData(*aStr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsEditor::GetCurrentNode(nsIDOMNode ** aNode)
|
nsEditor::GetCurrentNode(nsIDOMNode ** aNode)
|
||||||
{
|
{
|
||||||
|
@ -485,7 +492,7 @@ nsEditor::GetFirstNodeOfType(nsIDOMNode *aStartNode, const nsString &aTag, nsIDO
|
||||||
while (childNode)
|
while (childNode)
|
||||||
{
|
{
|
||||||
result = childNode->QueryInterface(kIDOMNodeIID,getter_AddRefs(element));
|
result = childNode->QueryInterface(kIDOMNodeIID,getter_AddRefs(element));
|
||||||
nsString tag;
|
nsAutoString tag;
|
||||||
if (NS_SUCCEEDED(result) && (element))
|
if (NS_SUCCEEDED(result) && (element))
|
||||||
{
|
{
|
||||||
element->GetTagName(tag);
|
element->GetTagName(tag);
|
||||||
|
@ -500,9 +507,8 @@ nsEditor::GetFirstNodeOfType(nsIDOMNode *aStartNode, const nsString &aTag, nsIDO
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nsCOMPtr<nsIDOMNode> xNode;
|
nsCOMPtr<nsIDOMNode> temp = childNode;
|
||||||
childNode->GetNextSibling(getter_AddRefs(xNode));
|
temp->GetNextSibling(getter_AddRefs(childNode));
|
||||||
childNode=xNode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
@ -559,7 +565,7 @@ nsEditor::GetFirstTextNode(nsIDOMNode *aNode, nsIDOMNode **aRetNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsEditor::ExecuteTransaction(nsITransaction *aTxn)
|
nsEditor::Do(nsITransaction *aTxn)
|
||||||
{
|
{
|
||||||
nsresult result = NS_OK;
|
nsresult result = NS_OK;
|
||||||
if (nsnull!=aTxn)
|
if (nsnull!=aTxn)
|
||||||
|
@ -577,27 +583,65 @@ nsEditor::ExecuteTransaction(nsITransaction *aTxn)
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsEditor::Undo()
|
nsEditor::Undo(PRUint32 aCount)
|
||||||
{
|
{
|
||||||
nsresult result = NS_OK;
|
nsresult result = NS_OK;
|
||||||
if (nsnull!=mTxnMgr)
|
if (nsnull!=mTxnMgr)
|
||||||
{
|
{
|
||||||
result = mTxnMgr->Undo();
|
PRUint32 i=0;
|
||||||
|
for ( ; i<aCount; i++)
|
||||||
|
{
|
||||||
|
result = mTxnMgr->Undo();
|
||||||
|
if (NS_FAILED(result))
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsEditor::Redo()
|
nsEditor::Redo(PRUint32 aCount)
|
||||||
{
|
{
|
||||||
nsresult result = NS_OK;
|
nsresult result = NS_OK;
|
||||||
if (nsnull!=mTxnMgr)
|
if (nsnull!=mTxnMgr)
|
||||||
{
|
{
|
||||||
result = mTxnMgr->Redo();
|
PRUint32 i=0;
|
||||||
|
for ( ; i<aCount; i++)
|
||||||
|
{
|
||||||
|
result = mTxnMgr->Redo();
|
||||||
|
if (NS_FAILED(result))
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsEditor::BeginUpdate()
|
||||||
|
{
|
||||||
|
NS_PRECONDITION(mUpdateCount>=0, "bad state");
|
||||||
|
if (nsnull!=mViewManager)
|
||||||
|
{
|
||||||
|
if (0==mUpdateCount)
|
||||||
|
mViewManager->DisableRefresh();
|
||||||
|
mUpdateCount++;
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsEditor::EndUpdate()
|
||||||
|
{
|
||||||
|
NS_PRECONDITION(mUpdateCount>0, "bad state");
|
||||||
|
if (nsnull!=mViewManager)
|
||||||
|
{
|
||||||
|
mUpdateCount--;
|
||||||
|
if (0==mUpdateCount)
|
||||||
|
mViewManager->EnableRefresh();
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult nsEditor::Delete(PRBool aForward, PRUint32 aCount)
|
nsresult nsEditor::Delete(PRBool aForward, PRUint32 aCount)
|
||||||
{
|
{
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
@ -610,9 +654,13 @@ nsresult nsEditor::CreateElement(const nsString& aTag,
|
||||||
nsresult result;
|
nsresult result;
|
||||||
if (nsnull != aParent)
|
if (nsnull != aParent)
|
||||||
{
|
{
|
||||||
CreateElementTxn *txn = new CreateElementTxn(this, mDomInterfaceP, aTag, aParent, aPosition);
|
CreateElementTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kCreateElementTxnIID, (EditTxn **)&txn);
|
||||||
if (nsnull!=txn)
|
if (nsnull!=txn)
|
||||||
result = ExecuteTransaction(txn);
|
{
|
||||||
|
txn->Init(mDomInterfaceP, aTag, aParent, aPosition);
|
||||||
|
result = Do(txn);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
result = NS_ERROR_OUT_OF_MEMORY;
|
result = NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
@ -628,9 +676,13 @@ nsresult nsEditor::DeleteElement(nsIDOMNode * aParent,
|
||||||
nsresult result;
|
nsresult result;
|
||||||
if ((nsnull != aParent) && (nsnull != aElement))
|
if ((nsnull != aParent) && (nsnull != aElement))
|
||||||
{
|
{
|
||||||
DeleteElementTxn *txn = new DeleteElementTxn(this, mDomInterfaceP, aElement, aParent);
|
DeleteElementTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kDeleteElementTxnIID, (EditTxn **)&txn);
|
||||||
if (nsnull!=txn)
|
if (nsnull!=txn)
|
||||||
result = ExecuteTransaction(txn);
|
{
|
||||||
|
txn->Init(aElement, aParent);
|
||||||
|
result = Do(txn);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
result = NS_ERROR_OUT_OF_MEMORY;
|
result = NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
@ -640,18 +692,51 @@ nsresult nsEditor::DeleteElement(nsIDOMNode * aParent,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult nsEditor::InsertText(nsIDOMCharacterData *aElement,
|
// XXX; factor -- should call BuildInsertTextTransaction to do most of the work
|
||||||
PRUint32 aOffset,
|
nsresult nsEditor::InsertText(const nsString& aStringToInsert)
|
||||||
const nsString& aStringToInsert)
|
|
||||||
{
|
{
|
||||||
nsresult result;
|
nsresult result;
|
||||||
if (nsnull != aElement)
|
nsISelection* selection;
|
||||||
|
result = mPresShell->GetSelection(&selection);
|
||||||
|
if ((NS_SUCCEEDED(result)) && (nsnull!=selection))
|
||||||
{
|
{
|
||||||
InsertTextTxn *txn = new InsertTextTxn(this, aElement, aOffset, aStringToInsert);
|
nsCOMPtr<nsIEnumerator> enumerator;
|
||||||
if (nsnull!=txn)
|
enumerator = selection;
|
||||||
result = ExecuteTransaction(txn);
|
if (enumerator)
|
||||||
else
|
{
|
||||||
result = NS_ERROR_OUT_OF_MEMORY;
|
enumerator->First();
|
||||||
|
nsISupports *currentItem;
|
||||||
|
result = enumerator->CurrentItem(¤tItem);
|
||||||
|
if ((NS_SUCCEEDED(result)) && (nsnull!=currentItem))
|
||||||
|
{
|
||||||
|
// XXX: we'll want to deleteRange if the selection isn't just an insertion point
|
||||||
|
// for now, just insert text after the start of the first node
|
||||||
|
nsCOMPtr<nsIDOMRange> range = currentItem;
|
||||||
|
if (range)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMNode> node;
|
||||||
|
result = range->GetStartParent(getter_AddRefs(node));
|
||||||
|
if ((NS_SUCCEEDED(result)) && (node))
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMCharacterData> nodeAsText = node;
|
||||||
|
if (nodeAsText)
|
||||||
|
{
|
||||||
|
PRInt32 offset;
|
||||||
|
range->GetStartOffset(&offset);
|
||||||
|
InsertTextTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kInsertTextTxnIID, (EditTxn **)&txn);
|
||||||
|
if (nsnull!=txn)
|
||||||
|
{
|
||||||
|
txn->Init(nodeAsText, offset, aStringToInsert);
|
||||||
|
result = Do(txn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
result = NS_ERROR_INVALID_ARG;
|
result = NS_ERROR_INVALID_ARG;
|
||||||
|
@ -659,6 +744,7 @@ nsresult nsEditor::InsertText(nsIDOMCharacterData *aElement,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX; factor -- should call BuildDeleteTextTransaction to do most of the work
|
||||||
nsresult nsEditor::DeleteText(nsIDOMCharacterData *aElement,
|
nsresult nsEditor::DeleteText(nsIDOMCharacterData *aElement,
|
||||||
PRUint32 aOffset,
|
PRUint32 aOffset,
|
||||||
PRUint32 aLength)
|
PRUint32 aLength)
|
||||||
|
@ -666,9 +752,13 @@ nsresult nsEditor::DeleteText(nsIDOMCharacterData *aElement,
|
||||||
nsresult result=NS_OK;
|
nsresult result=NS_OK;
|
||||||
if (nsnull != aElement)
|
if (nsnull != aElement)
|
||||||
{
|
{
|
||||||
DeleteTextTxn *txn = new DeleteTextTxn(this, aElement, aOffset, aLength);
|
DeleteTextTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kDeleteTextTxnIID, (EditTxn **)&txn);
|
||||||
if (nsnull!=txn)
|
if (nsnull!=txn)
|
||||||
result = ExecuteTransaction(txn);
|
{
|
||||||
|
txn->Init(aElement, aOffset, aLength);
|
||||||
|
result = Do(txn);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
result = NS_ERROR_OUT_OF_MEMORY;
|
result = NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
@ -678,6 +768,10 @@ nsresult nsEditor::DeleteText(nsIDOMCharacterData *aElement,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX; factor -- should call DeleteSelectionTransaction to do most of the work
|
||||||
|
// XXX: these should get wrapped up in a single composite transaction
|
||||||
|
// rather than executing each individually, maybe I should alloc a generic aggregate
|
||||||
|
// and stick each in there, then execute the aggregate
|
||||||
nsresult nsEditor::DeleteSelection()
|
nsresult nsEditor::DeleteSelection()
|
||||||
{
|
{
|
||||||
nsresult result;
|
nsresult result;
|
||||||
|
@ -685,15 +779,34 @@ nsresult nsEditor::DeleteSelection()
|
||||||
result = mPresShell->GetSelection(&selection);
|
result = mPresShell->GetSelection(&selection);
|
||||||
if ((NS_SUCCEEDED(result)) && (nsnull!=selection))
|
if ((NS_SUCCEEDED(result)) && (nsnull!=selection))
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIDOMRange> range;
|
nsCOMPtr<nsIEnumerator> enumerator;
|
||||||
result = selection->QueryInterface(kIDOMRangeIID, getter_AddRefs(range));
|
enumerator = selection;
|
||||||
if ((NS_SUCCEEDED(result)) && (range))
|
if (enumerator)
|
||||||
{
|
{
|
||||||
DeleteRangeTxn *txn = new DeleteRangeTxn(this, range);
|
enumerator->First();
|
||||||
if (nsnull!=txn)
|
nsISupports *currentItem;
|
||||||
result = ExecuteTransaction(txn);
|
result = enumerator->CurrentItem(¤tItem);
|
||||||
else
|
if ((NS_SUCCEEDED(result)) && (nsnull!=currentItem))
|
||||||
result = NS_ERROR_OUT_OF_MEMORY;
|
{
|
||||||
|
nsCOMPtr<nsIDOMRange> range = currentItem;
|
||||||
|
DeleteRangeTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kDeleteRangeTxnIID, (EditTxn **)&txn);
|
||||||
|
if (nsnull!=txn)
|
||||||
|
{
|
||||||
|
txn->Init(range);
|
||||||
|
result = Do(txn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
if (NS_SUCCEEDED(result))
|
||||||
|
{
|
||||||
|
nsresult nextResult = enumerator->Next();
|
||||||
|
if (NS_SUCCEEDED(nextResult))
|
||||||
|
{
|
||||||
|
result = enumerator->CurrentItem(¤tItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -703,30 +816,31 @@ nsresult nsEditor::DeleteSelection()
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsEditor::SplitNode(nsIDOMNode * aNode,
|
nsEditor::SplitNode(nsIDOMNode * aExistingRightNode,
|
||||||
PRInt32 aOffset,
|
PRInt32 aOffset,
|
||||||
nsIDOMNode* aNewNode,
|
nsIDOMNode* aNewLeftNode,
|
||||||
nsIDOMNode* aParent)
|
nsIDOMNode* aParent)
|
||||||
{
|
{
|
||||||
nsresult result;
|
nsresult result;
|
||||||
NS_ASSERTION(((nsnull!=aNode) &&
|
NS_ASSERTION(((nsnull!=aExistingRightNode) &&
|
||||||
(nsnull!=aNewNode) &&
|
(nsnull!=aNewLeftNode) &&
|
||||||
(nsnull!=aParent)),
|
(nsnull!=aParent)),
|
||||||
"null arg");
|
"null arg");
|
||||||
if ((nsnull!=aNode) &&
|
if ((nsnull!=aExistingRightNode) &&
|
||||||
(nsnull!=aNewNode) &&
|
(nsnull!=aNewLeftNode) &&
|
||||||
(nsnull!=aParent))
|
(nsnull!=aParent))
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIDOMNode> resultNode;
|
nsCOMPtr<nsIDOMNode> resultNode;
|
||||||
result = aParent->InsertBefore(aNewNode, aNode, getter_AddRefs(resultNode));
|
result = aParent->InsertBefore(aNewLeftNode, aExistingRightNode, getter_AddRefs(resultNode));
|
||||||
if (NS_SUCCEEDED(result))
|
if (NS_SUCCEEDED(result))
|
||||||
{
|
{
|
||||||
// split the children between the 2 nodes
|
// split the children between the 2 nodes
|
||||||
// at this point, nNode has all the children
|
// at this point, aExistingRightNode has all the children
|
||||||
|
// move all the children whose index is < aOffset to aNewLeftNode
|
||||||
if (0<=aOffset) // don't bother unless we're going to move at least one child
|
if (0<=aOffset) // don't bother unless we're going to move at least one child
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||||
result = aParent->GetChildNodes(getter_AddRefs(childNodes));
|
result = aExistingRightNode->GetChildNodes(getter_AddRefs(childNodes));
|
||||||
if ((NS_SUCCEEDED(result)) && (childNodes))
|
if ((NS_SUCCEEDED(result)) && (childNodes))
|
||||||
{
|
{
|
||||||
PRInt32 i=0;
|
PRInt32 i=0;
|
||||||
|
@ -736,10 +850,10 @@ nsEditor::SplitNode(nsIDOMNode * aNode,
|
||||||
result = childNodes->Item(i, getter_AddRefs(childNode));
|
result = childNodes->Item(i, getter_AddRefs(childNode));
|
||||||
if ((NS_SUCCEEDED(result)) && (childNode))
|
if ((NS_SUCCEEDED(result)) && (childNode))
|
||||||
{
|
{
|
||||||
result = aNode->RemoveChild(childNode, getter_AddRefs(resultNode));
|
result = aExistingRightNode->RemoveChild(childNode, getter_AddRefs(resultNode));
|
||||||
if (NS_SUCCEEDED(result))
|
if (NS_SUCCEEDED(result))
|
||||||
{
|
{
|
||||||
result = aNewNode->AppendChild(childNode, getter_AddRefs(resultNode));
|
result = aNewLeftNode->AppendChild(childNode, getter_AddRefs(resultNode));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,9 @@
|
||||||
* Reserved.
|
* Reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef __editor_h__
|
||||||
|
#define __editor_h__
|
||||||
|
|
||||||
#include "prmon.h"
|
#include "prmon.h"
|
||||||
#include "nsIEditor.h"
|
#include "nsIEditor.h"
|
||||||
#include "nsIContextLoader.h"
|
#include "nsIContextLoader.h"
|
||||||
|
@ -24,11 +27,13 @@
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "editorInterfaces.h"
|
#include "editorInterfaces.h"
|
||||||
#include "nsITransactionManager.h"
|
#include "nsITransactionManager.h"
|
||||||
|
#include "TransactionFactory.h"
|
||||||
#include "nsRepository.h"
|
#include "nsRepository.h"
|
||||||
//#include "nsISelection.h"
|
//#include "nsISelection.h"
|
||||||
|
|
||||||
class nsIDOMCharacterData;
|
class nsIDOMCharacterData;
|
||||||
class nsIPresShell;
|
class nsIPresShell;
|
||||||
|
class nsIViewManager;
|
||||||
|
|
||||||
//This is the monitor for the editor.
|
//This is the monitor for the editor.
|
||||||
PRMonitor *getEditorMonitor();
|
PRMonitor *getEditorMonitor();
|
||||||
|
@ -42,15 +47,19 @@ PRMonitor *getEditorMonitor();
|
||||||
class nsEditor : public nsIEditor
|
class nsEditor : public nsIEditor
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
nsIPresShell *mPresShell;
|
nsIPresShell *mPresShell;
|
||||||
|
nsIViewManager *mViewManager;
|
||||||
|
PRUint32 mUpdateCount;
|
||||||
nsCOMPtr<nsIDOMDocument> mDomInterfaceP;
|
nsCOMPtr<nsIDOMDocument> mDomInterfaceP;
|
||||||
nsCOMPtr<nsIDOMEventListener> mKeyListenerP;
|
nsCOMPtr<nsIDOMEventListener> mKeyListenerP;
|
||||||
nsCOMPtr<nsIDOMEventListener> mMouseListenerP;
|
nsCOMPtr<nsIDOMEventListener> mMouseListenerP;
|
||||||
// nsCOMPtr<nsISelection> mSelectionP;
|
// nsCOMPtr<nsISelection> mSelectionP;
|
||||||
//nsCOMPtr<nsITransactionManager> mTxnMgrP;
|
//nsCOMPtr<nsITransactionManager> mTxnMgrP;
|
||||||
|
|
||||||
nsITransactionManager * mTxnMgr;
|
nsITransactionManager * mTxnMgr;
|
||||||
friend PRBool NSCanUnload(void);
|
friend PRBool NSCanUnload(void);
|
||||||
static PRInt32 gInstanceCount;
|
static PRInt32 gInstanceCount;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** The default constructor. This should suffice. the setting of the interfaces is done
|
/** The default constructor. This should suffice. the setting of the interfaces is done
|
||||||
* after the construction of the editor class.
|
* after the construction of the editor class.
|
||||||
|
@ -70,9 +79,9 @@ public:
|
||||||
|
|
||||||
virtual nsresult GetDomInterface(nsIDOMDocument **aDomInterface);
|
virtual nsresult GetDomInterface(nsIDOMDocument **aDomInterface);
|
||||||
|
|
||||||
virtual nsresult SetProperties(PROPERTIES aProperty);
|
virtual nsresult SetProperties(Properties aProperties);
|
||||||
|
|
||||||
virtual nsresult GetProperties(PROPERTIES **);
|
virtual nsresult GetProperties(Properties **aProperties);
|
||||||
|
|
||||||
virtual nsresult SetAttribute(nsIDOMElement * aElement,
|
virtual nsresult SetAttribute(nsIDOMElement * aElement,
|
||||||
const nsString& aAttribute,
|
const nsString& aAttribute,
|
||||||
|
@ -85,11 +94,15 @@ public:
|
||||||
|
|
||||||
virtual nsresult RemoveAttribute(nsIDOMElement *aElement, const nsString& aAttribute);
|
virtual nsresult RemoveAttribute(nsIDOMElement *aElement, const nsString& aAttribute);
|
||||||
|
|
||||||
virtual nsresult InsertString(nsString *aString);
|
virtual nsresult Do(nsITransaction *aTxn);
|
||||||
|
|
||||||
virtual nsresult Commit(PRBool aCtrlKey);
|
virtual nsresult Undo(PRUint32 aCount);
|
||||||
|
|
||||||
|
virtual nsresult Redo(PRUint32 aCount);
|
||||||
|
|
||||||
|
virtual nsresult BeginUpdate();
|
||||||
|
|
||||||
|
virtual nsresult EndUpdate();
|
||||||
|
|
||||||
/*END nsIEditor interfaces*/
|
/*END nsIEditor interfaces*/
|
||||||
|
|
||||||
|
@ -113,12 +126,6 @@ public:
|
||||||
|
|
||||||
/*BEGIN private methods used by the implementations of the above functions*/
|
/*BEGIN private methods used by the implementations of the above functions*/
|
||||||
|
|
||||||
/** AppendText is a private method that accepts a pointer to a string
|
|
||||||
* and will append it to the current node. this will be depricated
|
|
||||||
* @param nsString *aStr is the pointer to the valid string
|
|
||||||
*/
|
|
||||||
nsresult AppendText(nsString *aStr);
|
|
||||||
|
|
||||||
/** GetCurrentNode ADDREFFS and will get the current node from selection.
|
/** GetCurrentNode ADDREFFS and will get the current node from selection.
|
||||||
* now it simply returns the first node in the dom
|
* now it simply returns the first node in the dom
|
||||||
* @param nsIDOMNode **aNode is the return location of the dom node
|
* @param nsIDOMNode **aNode is the return location of the dom node
|
||||||
|
@ -142,33 +149,6 @@ public:
|
||||||
*/
|
*/
|
||||||
nsresult GetFirstNodeOfType(nsIDOMNode *aStartNode, const nsString &aTag, nsIDOMNode **aResult);
|
nsresult GetFirstNodeOfType(nsIDOMNode *aStartNode, const nsString &aTag, nsIDOMNode **aResult);
|
||||||
|
|
||||||
/** ExecuteTransaction fires a transaction. It is provided here so
|
|
||||||
* clients need no knowledge of whether the editor has a transaction manager or not.
|
|
||||||
* If a transaction manager is present, it is used.
|
|
||||||
* Otherwise, the transaction is just executed directly.
|
|
||||||
*
|
|
||||||
* @param aTxn the transaction to execute
|
|
||||||
*/
|
|
||||||
nsresult ExecuteTransaction(nsITransaction *aTxn);
|
|
||||||
|
|
||||||
/** Undo reverses the effects of the last ExecuteTransaction operation
|
|
||||||
* It is provided here so clients need no knowledge of whether the editor has a transaction manager or not.
|
|
||||||
* If a transaction manager is present, it is told to undo and the result of
|
|
||||||
* that undo is returned.
|
|
||||||
* Otherwise, the Undo request is ignored.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
nsresult Undo();
|
|
||||||
|
|
||||||
/** Redo reverses the effects of the last Undo operation
|
|
||||||
* It is provided here so clients need no knowledge of whether the editor has a transaction manager or not.
|
|
||||||
* If a transaction manager is present, it is told to redo and the result of
|
|
||||||
* that redo is returned.
|
|
||||||
* Otherwise, the Redo request is ignored.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
nsresult Redo();
|
|
||||||
|
|
||||||
nsresult CreateElement(const nsString& aTag,
|
nsresult CreateElement(const nsString& aTag,
|
||||||
nsIDOMNode * aParent,
|
nsIDOMNode * aParent,
|
||||||
PRInt32 aPosition);
|
PRInt32 aPosition);
|
||||||
|
@ -178,17 +158,15 @@ public:
|
||||||
|
|
||||||
nsresult DeleteSelection();
|
nsresult DeleteSelection();
|
||||||
|
|
||||||
nsresult InsertText(nsIDOMCharacterData *aElement,
|
nsresult InsertText(const nsString& aStringToInsert);
|
||||||
PRUint32 aOffset,
|
|
||||||
const nsString& aStringToInsert);
|
|
||||||
|
|
||||||
nsresult DeleteText(nsIDOMCharacterData *aElement,
|
nsresult DeleteText(nsIDOMCharacterData *aElement,
|
||||||
PRUint32 aOffset,
|
PRUint32 aOffset,
|
||||||
PRUint32 aLength);
|
PRUint32 aLength);
|
||||||
|
|
||||||
static nsresult SplitNode(nsIDOMNode * aNode,
|
static nsresult SplitNode(nsIDOMNode * aExistingRightNode,
|
||||||
PRInt32 aOffset,
|
PRInt32 aOffset,
|
||||||
nsIDOMNode * aNewNode,
|
nsIDOMNode * aNewLeftNode,
|
||||||
nsIDOMNode * aParent);
|
nsIDOMNode * aParent);
|
||||||
|
|
||||||
static nsresult JoinNodes(nsIDOMNode * aNodeToKeep,
|
static nsresult JoinNodes(nsIDOMNode * aNodeToKeep,
|
||||||
|
@ -198,6 +176,10 @@ public:
|
||||||
|
|
||||||
nsresult Delete(PRBool aForward, PRUint32 aCount);
|
nsresult Delete(PRBool aForward, PRUint32 aCount);
|
||||||
|
|
||||||
|
virtual nsresult InsertString(nsString *aString);
|
||||||
|
|
||||||
|
virtual nsresult Commit(PRBool aCtrlKey);
|
||||||
|
|
||||||
/*END private methods of nsEditor*/
|
/*END private methods of nsEditor*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -207,3 +189,6 @@ factory method(s)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
nsresult NS_MakeEditorLoader(nsIContextLoader **aResult);
|
nsresult NS_MakeEditorLoader(nsIContextLoader **aResult);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -19,7 +19,6 @@
|
||||||
#include "editor.h"
|
#include "editor.h"
|
||||||
|
|
||||||
#include "CreateElementTxn.h"
|
#include "CreateElementTxn.h"
|
||||||
#include "SplitElementTxn.h"
|
|
||||||
|
|
||||||
#include "nsIDOMDocument.h"
|
#include "nsIDOMDocument.h"
|
||||||
#include "nsIDOMElement.h"
|
#include "nsIDOMElement.h"
|
||||||
|
@ -178,7 +177,7 @@ nsEditorKeyListener::KeyDown(nsIDOMEvent* aKeyEvent)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // XXX: delete the first P we find
|
{ // XXX: delete the first P we find
|
||||||
nsString pTag("P");
|
nsAutoString pTag("P");
|
||||||
nsCOMPtr<nsIDOMNode> currentNode;
|
nsCOMPtr<nsIDOMNode> currentNode;
|
||||||
nsCOMPtr<nsIDOMNode> parentNode;
|
nsCOMPtr<nsIDOMNode> parentNode;
|
||||||
nsCOMPtr<nsIDOMElement> element;
|
nsCOMPtr<nsIDOMElement> element;
|
||||||
|
@ -199,25 +198,12 @@ nsEditorKeyListener::KeyDown(nsIDOMEvent* aKeyEvent)
|
||||||
{
|
{
|
||||||
// XXX Replace with x-platform NS-virtkeycode transform.
|
// XXX Replace with x-platform NS-virtkeycode transform.
|
||||||
if (NS_OK == GetCharFromKeyCode(keyCode, isShift, & character)) {
|
if (NS_OK == GetCharFromKeyCode(keyCode, isShift, & character)) {
|
||||||
nsString key;
|
nsAutoString key;
|
||||||
key += character;
|
key += character;
|
||||||
if (!isShift) {
|
if (!isShift) {
|
||||||
key.ToLowerCase();
|
key.ToLowerCase();
|
||||||
}
|
}
|
||||||
|
mEditor->InsertText(key);
|
||||||
// XXX: for now, just grab the first text node
|
|
||||||
nsCOMPtr<nsIDOMNode> currentNode;
|
|
||||||
nsCOMPtr<nsIDOMNode> textNode;
|
|
||||||
nsCOMPtr<nsIDOMCharacterData> text;
|
|
||||||
if (NS_SUCCEEDED(mEditor->GetCurrentNode(getter_AddRefs(currentNode))) &&
|
|
||||||
NS_SUCCEEDED(mEditor->GetFirstTextNode(currentNode,getter_AddRefs(textNode))) &&
|
|
||||||
NS_SUCCEEDED(textNode->QueryInterface(kIDOMCharacterDataIID, getter_AddRefs(text))))
|
|
||||||
{
|
|
||||||
// XXX: for now, just append the text
|
|
||||||
PRUint32 offset;
|
|
||||||
text->GetLength(&offset);
|
|
||||||
mEditor->InsertText(text, offset, key);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -244,6 +230,10 @@ nsEditorKeyListener::KeyPress(nsIDOMEvent* aKeyEvent)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* these includes are for debug only. this module should never instantiate it's own transactions */
|
||||||
|
#include "SplitElementTxn.h"
|
||||||
|
#include "TransactionFactory.h"
|
||||||
|
static NS_DEFINE_IID(kSplitElementTxnIID, SPLIT_ELEMENT_TXN_IID);
|
||||||
nsresult
|
nsresult
|
||||||
nsEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aProcessed)
|
nsEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aProcessed)
|
||||||
{
|
{
|
||||||
|
@ -265,7 +255,7 @@ nsEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aProces
|
||||||
if (PR_TRUE==ctrlKey)
|
if (PR_TRUE==ctrlKey)
|
||||||
{
|
{
|
||||||
if (nsnull!=mEditor)
|
if (nsnull!=mEditor)
|
||||||
mEditor->Undo();
|
mEditor->Undo(1);
|
||||||
}
|
}
|
||||||
aProcessed=PR_TRUE;
|
aProcessed=PR_TRUE;
|
||||||
break;
|
break;
|
||||||
|
@ -275,7 +265,7 @@ nsEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aProces
|
||||||
if (PR_TRUE==ctrlKey)
|
if (PR_TRUE==ctrlKey)
|
||||||
{
|
{
|
||||||
if (nsnull!=mEditor)
|
if (nsnull!=mEditor)
|
||||||
mEditor->Redo();
|
mEditor->Redo(1);
|
||||||
}
|
}
|
||||||
aProcessed=PR_TRUE;
|
aProcessed=PR_TRUE;
|
||||||
break;
|
break;
|
||||||
|
@ -283,17 +273,27 @@ nsEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aProces
|
||||||
// hard-coded split node test: works on first <P> in the document
|
// hard-coded split node test: works on first <P> in the document
|
||||||
case nsIDOMEvent::VK_S:
|
case nsIDOMEvent::VK_S:
|
||||||
{
|
{
|
||||||
nsString pTag("P");
|
nsAutoString pTag("P");
|
||||||
nsCOMPtr<nsIDOMNode> currentNode;
|
nsCOMPtr<nsIDOMNode> currentNode;
|
||||||
nsCOMPtr<nsIDOMElement> element;
|
nsCOMPtr<nsIDOMElement> element;
|
||||||
if (NS_SUCCEEDED(mEditor->GetFirstNodeOfType(nsnull, pTag, getter_AddRefs(currentNode))))
|
if (NS_SUCCEEDED(mEditor->GetFirstNodeOfType(nsnull, pTag, getter_AddRefs(currentNode))))
|
||||||
{
|
{
|
||||||
|
nsresult result;
|
||||||
SplitElementTxn *txn;
|
SplitElementTxn *txn;
|
||||||
if (PR_FALSE==isShift) // split the element so there are 0 children in the first half
|
if (PR_FALSE==isShift) // split the element so there are 0 children in the first half
|
||||||
txn = new SplitElementTxn(mEditor, currentNode, -1);
|
{
|
||||||
|
result = TransactionFactory::GetNewTransaction(kSplitElementTxnIID, (EditTxn **)&txn);
|
||||||
|
if (txn)
|
||||||
|
txn->Init(currentNode, -1);
|
||||||
|
}
|
||||||
else // split the element so there are 2 children in the first half
|
else // split the element so there are 2 children in the first half
|
||||||
txn = new SplitElementTxn(mEditor, currentNode, 1);
|
{
|
||||||
mEditor->ExecuteTransaction(txn);
|
result = TransactionFactory::GetNewTransaction(kSplitElementTxnIID, (EditTxn **)&txn);
|
||||||
|
if (txn)
|
||||||
|
txn->Init(currentNode, 1);
|
||||||
|
}
|
||||||
|
if (txn)
|
||||||
|
mEditor->Do(txn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
aProcessed=PR_TRUE;
|
aProcessed=PR_TRUE;
|
||||||
|
@ -305,10 +305,10 @@ nsEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aProces
|
||||||
{
|
{
|
||||||
//XXX: should be from a factory
|
//XXX: should be from a factory
|
||||||
//XXX: should manage the refcount of txn
|
//XXX: should manage the refcount of txn
|
||||||
nsString attribute("width");
|
nsAutoString attribute("width");
|
||||||
nsString value("400");
|
nsAutoString value("400");
|
||||||
|
|
||||||
nsString tableTag("TABLE");
|
nsAutoString tableTag("TABLE");
|
||||||
nsCOMPtr<nsIDOMNode> currentNode;
|
nsCOMPtr<nsIDOMNode> currentNode;
|
||||||
nsCOMPtr<nsIDOMElement> element;
|
nsCOMPtr<nsIDOMElement> element;
|
||||||
if (NS_SUCCEEDED(mEditor->GetFirstNodeOfType(nsnull, tableTag, getter_AddRefs(currentNode))))
|
if (NS_SUCCEEDED(mEditor->GetFirstNodeOfType(nsnull, tableTag, getter_AddRefs(currentNode))))
|
||||||
|
@ -331,11 +331,11 @@ nsEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aProces
|
||||||
nsresult result;
|
nsresult result;
|
||||||
//XXX: should be from a factory
|
//XXX: should be from a factory
|
||||||
//XXX: should manage the refcount of txn
|
//XXX: should manage the refcount of txn
|
||||||
nsString attribute("src");
|
nsAutoString attribute("src");
|
||||||
nsString value("resource:/res/samples/raptor.jpg");
|
nsAutoString value("resource:/res/samples/raptor.jpg");
|
||||||
|
|
||||||
nsString imgTag("HR");
|
nsAutoString imgTag("HR");
|
||||||
nsString bodyTag("BODY");
|
nsAutoString bodyTag("BODY");
|
||||||
nsCOMPtr<nsIDOMNode> currentNode;
|
nsCOMPtr<nsIDOMNode> currentNode;
|
||||||
result = mEditor->GetFirstNodeOfType(nsnull, bodyTag, getter_AddRefs(currentNode));
|
result = mEditor->GetFirstNodeOfType(nsnull, bodyTag, getter_AddRefs(currentNode));
|
||||||
if (NS_SUCCEEDED(result))
|
if (NS_SUCCEEDED(result))
|
||||||
|
@ -356,7 +356,7 @@ nsEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aProces
|
||||||
{
|
{
|
||||||
ChangeAttributeTxn *txn;
|
ChangeAttributeTxn *txn;
|
||||||
txn = new ChangeAttributeTxn(mEditor, element, attribute, value, PR_FALSE);
|
txn = new ChangeAttributeTxn(mEditor, element, attribute, value, PR_FALSE);
|
||||||
mEditor->ExecuteTransaction(txn);
|
mEditor->Do(txn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
@ -523,3 +523,4 @@ NS_NewEditorMouseListener(nsIDOMEventListener ** aInstancePtrResult, nsEditor *a
|
||||||
return it->QueryInterface(kIDOMEventListenerIID, (void **) aInstancePtrResult);
|
return it->QueryInterface(kIDOMEventListenerIID, (void **) aInstancePtrResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ CPPSRCS = \
|
||||||
editorInterfaces.cpp \
|
editorInterfaces.cpp \
|
||||||
nsEditFactory.cpp \
|
nsEditFactory.cpp \
|
||||||
EditTxn.cpp \
|
EditTxn.cpp \
|
||||||
|
EditAggregateTxn.cpp \
|
||||||
ChangeAttributeTxn.cpp \
|
ChangeAttributeTxn.cpp \
|
||||||
InsertTextTxn.cpp \
|
InsertTextTxn.cpp \
|
||||||
DeleteTextTxn.cpp \
|
DeleteTextTxn.cpp \
|
||||||
|
@ -32,6 +33,8 @@ CPPSRCS = \
|
||||||
DeleteElementTxn.cpp \
|
DeleteElementTxn.cpp \
|
||||||
DeleteRangeTxn.cpp \
|
DeleteRangeTxn.cpp \
|
||||||
SplitElementTxn.cpp \
|
SplitElementTxn.cpp \
|
||||||
|
JoinElementTxn.cpp \
|
||||||
|
TransactionFactory.cpp \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
CPP_OBJS = \
|
CPP_OBJS = \
|
||||||
|
@ -39,6 +42,7 @@ CPP_OBJS = \
|
||||||
.\$(OBJDIR)\nsEditFactory.obj \
|
.\$(OBJDIR)\nsEditFactory.obj \
|
||||||
.\$(OBJDIR)\editorInterfaces.obj \
|
.\$(OBJDIR)\editorInterfaces.obj \
|
||||||
.\$(OBJDIR)\EditTxn.obj \
|
.\$(OBJDIR)\EditTxn.obj \
|
||||||
|
.\$(OBJDIR)\EditAggregateTxn.obj \
|
||||||
.\$(OBJDIR)\ChangeAttributeTxn.obj \
|
.\$(OBJDIR)\ChangeAttributeTxn.obj \
|
||||||
.\$(OBJDIR)\InsertTextTxn.obj \
|
.\$(OBJDIR)\InsertTextTxn.obj \
|
||||||
.\$(OBJDIR)\DeleteTextTxn.obj \
|
.\$(OBJDIR)\DeleteTextTxn.obj \
|
||||||
|
@ -46,6 +50,8 @@ CPP_OBJS = \
|
||||||
.\$(OBJDIR)\DeleteElementTxn.obj \
|
.\$(OBJDIR)\DeleteElementTxn.obj \
|
||||||
.\$(OBJDIR)\DeleteRangeTxn.obj \
|
.\$(OBJDIR)\DeleteRangeTxn.obj \
|
||||||
.\$(OBJDIR)\SplitElementTxn.obj \
|
.\$(OBJDIR)\SplitElementTxn.obj \
|
||||||
|
.\$(OBJDIR)\JoinElementTxn.obj \
|
||||||
|
.\$(OBJDIR)\TransactionFactory.obj \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
MODULE=editor
|
MODULE=editor
|
||||||
|
|
|
@ -17,23 +17,33 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ChangeAttributeTxn.h"
|
#include "ChangeAttributeTxn.h"
|
||||||
#include "editor.h"
|
|
||||||
#include "nsIDOMElement.h"
|
#include "nsIDOMElement.h"
|
||||||
|
#include "editor.h"
|
||||||
|
|
||||||
// note that aEditor is not refcounted
|
ChangeAttributeTxn::ChangeAttributeTxn()
|
||||||
ChangeAttributeTxn::ChangeAttributeTxn(nsEditor *aEditor,
|
: EditTxn()
|
||||||
nsIDOMElement *aElement,
|
|
||||||
const nsString& aAttribute,
|
|
||||||
const nsString& aValue,
|
|
||||||
PRBool aRemoveAttribute)
|
|
||||||
: EditTxn(aEditor)
|
|
||||||
{
|
{
|
||||||
mElement = aElement;
|
}
|
||||||
mAttribute = aAttribute;
|
|
||||||
mValue = aValue;
|
nsresult ChangeAttributeTxn::Init(nsIEditor *aEditor,
|
||||||
mRemoveAttribute = aRemoveAttribute;
|
nsIDOMElement *aElement,
|
||||||
mAttributeWasSet=PR_FALSE;
|
const nsString& aAttribute,
|
||||||
mUndoValue="";
|
const nsString& aValue,
|
||||||
|
PRBool aRemoveAttribute)
|
||||||
|
{
|
||||||
|
if (nsnull!=aEditor && nsnull!=aElement)
|
||||||
|
{
|
||||||
|
mEditor = aEditor;
|
||||||
|
mElement = aElement;
|
||||||
|
mAttribute = aAttribute;
|
||||||
|
mValue = aValue;
|
||||||
|
mRemoveAttribute = aRemoveAttribute;
|
||||||
|
mAttributeWasSet=PR_FALSE;
|
||||||
|
mUndoValue="";
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult ChangeAttributeTxn::Do(void)
|
nsresult ChangeAttributeTxn::Do(void)
|
||||||
|
|
|
@ -20,8 +20,14 @@
|
||||||
#define ChangeAttributeTxn_h__
|
#define ChangeAttributeTxn_h__
|
||||||
|
|
||||||
#include "EditTxn.h"
|
#include "EditTxn.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsIDOMElement.h"
|
||||||
|
#include "nsIEditor.h"
|
||||||
|
|
||||||
class nsIDOMElement;
|
#define CHANGE_ATTRIBUTE_TXN_IID \
|
||||||
|
{/* 97818860-ac48-11d2-86d8-000064657374 */ \
|
||||||
|
0x97818860, 0xac48, 0x11d2, \
|
||||||
|
{0x86, 0xd8, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A transaction that changes an attribute of a content node.
|
* A transaction that changes an attribute of a content node.
|
||||||
|
@ -31,11 +37,16 @@ class ChangeAttributeTxn : public EditTxn
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ChangeAttributeTxn(nsEditor *aEditor,
|
virtual nsresult Init(nsIEditor *aEditor,
|
||||||
nsIDOMElement *aElement,
|
nsIDOMElement *aElement,
|
||||||
const nsString& aAttribute,
|
const nsString& aAttribute,
|
||||||
const nsString& aValue,
|
const nsString& aValue,
|
||||||
PRBool aRemoveAttribute);
|
PRBool aRemoveAttribute);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ChangeAttributeTxn();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
virtual nsresult Do(void);
|
virtual nsresult Do(void);
|
||||||
|
|
||||||
|
@ -55,8 +66,11 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
/** the editor that created this transaction */
|
||||||
|
nsCOMPtr<nsIEditor> mEditor;
|
||||||
|
|
||||||
/** the element to operate upon */
|
/** the element to operate upon */
|
||||||
nsIDOMElement *mElement;
|
nsCOMPtr<nsIDOMElement> mElement;
|
||||||
|
|
||||||
/** the attribute to change */
|
/** the attribute to change */
|
||||||
nsString mAttribute;
|
nsString mAttribute;
|
||||||
|
@ -72,6 +86,8 @@ protected:
|
||||||
|
|
||||||
/** PR_TRUE if the operation is to remove mAttribute from mElement */
|
/** PR_TRUE if the operation is to remove mAttribute from mElement */
|
||||||
PRBool mRemoveAttribute;
|
PRBool mRemoveAttribute;
|
||||||
|
|
||||||
|
friend class TransactionFactory;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,52 +17,50 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "CreateElementTxn.h"
|
#include "CreateElementTxn.h"
|
||||||
#include "editor.h"
|
|
||||||
#include "nsIDOMNode.h"
|
|
||||||
#include "nsIDOMNodeList.h"
|
#include "nsIDOMNodeList.h"
|
||||||
#include "nsIDOMDocument.h"
|
|
||||||
#include "nsIDOMElement.h"
|
|
||||||
|
|
||||||
// note that aEditor is not refcounted
|
CreateElementTxn::CreateElementTxn()
|
||||||
CreateElementTxn::CreateElementTxn(nsEditor *aEditor,
|
: EditTxn()
|
||||||
nsIDOMDocument *aDoc,
|
|
||||||
const nsString& aTag,
|
|
||||||
nsIDOMNode *aParent,
|
|
||||||
PRUint32 aOffsetInParent)
|
|
||||||
: EditTxn(aEditor)
|
|
||||||
{
|
{
|
||||||
mDoc = aDoc;
|
|
||||||
NS_ADDREF(mDoc);
|
|
||||||
mTag = aTag;
|
|
||||||
mParent = aParent;
|
|
||||||
NS_ADDREF(mParent);
|
|
||||||
mOffsetInParent = aOffsetInParent;
|
|
||||||
mNewNode = nsnull;
|
|
||||||
mRefNode = nsnull;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult CreateElementTxn::Init(nsIDOMDocument *aDoc,
|
||||||
|
const nsString& aTag,
|
||||||
|
nsIDOMNode *aParent,
|
||||||
|
PRUint32 aOffsetInParent)
|
||||||
|
{
|
||||||
|
if ((nsnull!=aDoc) && (nsnull!=aParent))
|
||||||
|
{
|
||||||
|
mDoc = aDoc;
|
||||||
|
mTag = aTag;
|
||||||
|
mParent = aParent;
|
||||||
|
mOffsetInParent = aOffsetInParent;
|
||||||
|
mNewNode = nsnull;
|
||||||
|
mRefNode = nsnull;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CreateElementTxn::~CreateElementTxn()
|
CreateElementTxn::~CreateElementTxn()
|
||||||
{
|
{
|
||||||
NS_IF_RELEASE(mDoc);
|
|
||||||
NS_IF_RELEASE(mParent);
|
|
||||||
NS_IF_RELEASE(mNewNode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult CreateElementTxn::Do(void)
|
nsresult CreateElementTxn::Do(void)
|
||||||
{
|
{
|
||||||
// create a new node
|
// create a new node
|
||||||
nsresult result = mDoc->CreateElement(mTag, &mNewNode);
|
nsresult result = mDoc->CreateElement(mTag, getter_AddRefs(mNewNode));
|
||||||
NS_ASSERTION(((NS_SUCCEEDED(result)) && (nsnull!=mNewNode)), "could not create element.");
|
NS_ASSERTION(((NS_SUCCEEDED(result)) && (mNewNode)), "could not create element.");
|
||||||
|
|
||||||
if ((NS_SUCCEEDED(result)) && (nsnull!=mNewNode))
|
if ((NS_SUCCEEDED(result)) && (mNewNode))
|
||||||
{
|
{
|
||||||
// insert the new node
|
// insert the new node
|
||||||
nsIDOMNode *resultNode=nsnull;
|
nsCOMPtr<nsIDOMNode> resultNode;
|
||||||
if (CreateElementTxn::eAppend==mOffsetInParent)
|
if (CreateElementTxn::eAppend==mOffsetInParent)
|
||||||
{
|
{
|
||||||
result = mParent->AppendChild(mNewNode, &resultNode);
|
result = mParent->AppendChild(mNewNode, getter_AddRefs(resultNode));
|
||||||
if ((NS_SUCCEEDED(result)) && (nsnull!=resultNode))
|
|
||||||
NS_RELEASE(resultNode); // this object already holds a ref from CreateElement
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -70,12 +68,10 @@ nsresult CreateElementTxn::Do(void)
|
||||||
result = mParent->GetChildNodes(getter_AddRefs(childNodes));
|
result = mParent->GetChildNodes(getter_AddRefs(childNodes));
|
||||||
if ((NS_SUCCEEDED(result)) && (childNodes))
|
if ((NS_SUCCEEDED(result)) && (childNodes))
|
||||||
{
|
{
|
||||||
result = childNodes->Item(mOffsetInParent, &mRefNode);
|
result = childNodes->Item(mOffsetInParent, getter_AddRefs(mRefNode));
|
||||||
if ((NS_SUCCEEDED(result)) && (nsnull!=mRefNode))
|
if ((NS_SUCCEEDED(result)) && (mRefNode))
|
||||||
{
|
{
|
||||||
result = mParent->InsertBefore(mNewNode, mRefNode, &resultNode);
|
result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode));
|
||||||
if ((NS_SUCCEEDED(result)) && (nsnull!=resultNode))
|
|
||||||
NS_RELEASE(resultNode); // this object already holds a ref from CreateElement
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,20 +81,16 @@ nsresult CreateElementTxn::Do(void)
|
||||||
|
|
||||||
nsresult CreateElementTxn::Undo(void)
|
nsresult CreateElementTxn::Undo(void)
|
||||||
{
|
{
|
||||||
nsIDOMNode *resultNode=nsnull;
|
nsCOMPtr<nsIDOMNode> resultNode;
|
||||||
nsresult result = mParent->RemoveChild(mNewNode, &resultNode);
|
nsresult result = mParent->RemoveChild(mNewNode, getter_AddRefs(resultNode));
|
||||||
if ((NS_SUCCEEDED(result)) && (nsnull!=resultNode))
|
|
||||||
NS_RELEASE(resultNode);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult CreateElementTxn::Redo(void)
|
nsresult CreateElementTxn::Redo(void)
|
||||||
{
|
{
|
||||||
nsIDOMNode *resultNode=nsnull;
|
nsCOMPtr<nsIDOMNode> resultNode;
|
||||||
nsresult result = mParent->InsertBefore(mNewNode, mRefNode, &resultNode);
|
nsresult result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode));
|
||||||
if ((NS_SUCCEEDED(result)) && (nsnull!=resultNode))
|
return result;
|
||||||
NS_RELEASE(resultNode);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult CreateElementTxn::GetIsTransient(PRBool *aIsTransient)
|
nsresult CreateElementTxn::GetIsTransient(PRBool *aIsTransient)
|
||||||
|
|
|
@ -20,10 +20,15 @@
|
||||||
#define CreateElementTxn_h__
|
#define CreateElementTxn_h__
|
||||||
|
|
||||||
#include "EditTxn.h"
|
#include "EditTxn.h"
|
||||||
|
#include "nsIDOMDocument.h"
|
||||||
|
#include "nsIDOMNode.h"
|
||||||
|
#include "nsIDOMElement.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
|
||||||
class nsIDOMDocument;
|
#define CREATE_ELEMENT_TXN_IID \
|
||||||
class nsIDOMNode;
|
{/* 7a6393c0-ac48-11d2-86d8-000064657374 */ \
|
||||||
class nsIDOMElement;
|
0x7a6393c0, 0xac48, 0x11d2, \
|
||||||
|
{0x86, 0xd8, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A transaction that creates a new node in the content tree.
|
* A transaction that creates a new node in the content tree.
|
||||||
|
@ -34,11 +39,15 @@ public:
|
||||||
|
|
||||||
enum { eAppend=-1 };
|
enum { eAppend=-1 };
|
||||||
|
|
||||||
CreateElementTxn(nsEditor *aEditor,
|
virtual nsresult Init(nsIDOMDocument *aDoc,
|
||||||
nsIDOMDocument *aDoc,
|
const nsString& aTag,
|
||||||
const nsString& aTag,
|
nsIDOMNode *aParent,
|
||||||
nsIDOMNode *aParent,
|
PRUint32 aOffsetInParent);
|
||||||
PRUint32 aOffsetInParent);
|
|
||||||
|
private:
|
||||||
|
CreateElementTxn();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
virtual ~CreateElementTxn();
|
virtual ~CreateElementTxn();
|
||||||
|
|
||||||
|
@ -61,22 +70,24 @@ public:
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/** the document into which the new node will be inserted */
|
/** the document into which the new node will be inserted */
|
||||||
nsIDOMDocument *mDoc;
|
nsCOMPtr<nsIDOMDocument> mDoc;
|
||||||
|
|
||||||
/** the tag (mapping to object type) for the new element */
|
/** the tag (mapping to object type) for the new element */
|
||||||
nsString mTag;
|
nsString mTag;
|
||||||
|
|
||||||
/** the node into which the new node will be inserted */
|
/** the node into which the new node will be inserted */
|
||||||
nsIDOMNode *mParent;
|
nsCOMPtr<nsIDOMNode> mParent;
|
||||||
|
|
||||||
/** the index in mParent for the new node */
|
/** the index in mParent for the new node */
|
||||||
PRUint32 mOffsetInParent;
|
PRUint32 mOffsetInParent;
|
||||||
|
|
||||||
/** the new node to insert */
|
/** the new node to insert */
|
||||||
nsIDOMElement *mNewNode;
|
nsCOMPtr<nsIDOMElement> mNewNode;
|
||||||
|
|
||||||
/** the node we will insert mNewNode before. We compute this ourselves. */
|
/** the node we will insert mNewNode before. We compute this ourselves. */
|
||||||
nsIDOMNode *mRefNode;
|
nsCOMPtr<nsIDOMNode> mRefNode;
|
||||||
|
|
||||||
|
friend class TransactionFactory;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -17,30 +17,32 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "DeleteElementTxn.h"
|
#include "DeleteElementTxn.h"
|
||||||
#include "editor.h"
|
#ifdef NS_DEBUG
|
||||||
#include "nsIDOMDocument.h"
|
|
||||||
#include "nsIDOMElement.h"
|
#include "nsIDOMElement.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// note that aEditor is not refcounted
|
|
||||||
DeleteElementTxn::DeleteElementTxn(nsEditor * aEditor,
|
DeleteElementTxn::DeleteElementTxn()
|
||||||
nsIDOMDocument *aDoc,
|
: EditTxn()
|
||||||
nsIDOMNode * aElement,
|
|
||||||
nsIDOMNode * aParent)
|
|
||||||
: EditTxn(aEditor)
|
|
||||||
{
|
{
|
||||||
mDoc = aDoc;
|
|
||||||
NS_ADDREF(mDoc);
|
|
||||||
mElement = aElement;
|
|
||||||
NS_ADDREF(mElement);
|
|
||||||
mParent = aParent;
|
|
||||||
NS_ADDREF(mParent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult DeleteElementTxn::Init(nsIDOMNode *aElement,
|
||||||
|
nsIDOMNode *aParent)
|
||||||
|
{
|
||||||
|
if ((nsnull!=aElement) && (nsnull!=aParent))
|
||||||
|
{
|
||||||
|
mElement = aElement;
|
||||||
|
mParent = aParent;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DeleteElementTxn::~DeleteElementTxn()
|
DeleteElementTxn::~DeleteElementTxn()
|
||||||
{
|
{
|
||||||
NS_IF_RELEASE(mDoc);
|
|
||||||
NS_IF_RELEASE(mParent);
|
|
||||||
NS_IF_RELEASE(mElement);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult DeleteElementTxn::Do(void)
|
nsresult DeleteElementTxn::Do(void)
|
||||||
|
@ -48,11 +50,32 @@ nsresult DeleteElementTxn::Do(void)
|
||||||
if (!mParent || !mElement)
|
if (!mParent || !mElement)
|
||||||
return NS_ERROR_NULL_POINTER;
|
return NS_ERROR_NULL_POINTER;
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
|
// begin debug output
|
||||||
|
nsCOMPtr<nsIDOMElement> element=mElement;
|
||||||
|
nsAutoString elementTag="text node";
|
||||||
|
if (element)
|
||||||
|
element->GetTagName(elementTag);
|
||||||
|
nsCOMPtr<nsIDOMElement> parentElement=mParent;
|
||||||
|
nsAutoString parentElementTag="text node";
|
||||||
|
if (parentElement)
|
||||||
|
parentElement->GetTagName(parentElementTag);
|
||||||
|
char *c, *p;
|
||||||
|
c = elementTag.ToNewCString();
|
||||||
|
p = parentElementTag.ToNewCString();
|
||||||
|
if (c&&p)
|
||||||
|
{
|
||||||
|
printf("DeleteElementTxn: deleting child %s from parent %s\n", c, p);
|
||||||
|
delete [] c;
|
||||||
|
delete [] p;
|
||||||
|
}
|
||||||
|
// end debug output
|
||||||
|
// begin sanity check 1: parent-child relationship
|
||||||
nsresult testResult;
|
nsresult testResult;
|
||||||
nsCOMPtr<nsIDOMNode> parentNode;
|
nsCOMPtr<nsIDOMNode> parentNode;
|
||||||
testResult = mElement->GetParentNode(getter_AddRefs(parentNode));
|
testResult = mElement->GetParentNode(getter_AddRefs(parentNode));
|
||||||
NS_ASSERTION((NS_SUCCEEDED(testResult)), "bad mElement, couldn't get parent");
|
NS_ASSERTION((NS_SUCCEEDED(testResult)), "bad mElement, couldn't get parent");
|
||||||
NS_ASSERTION((parentNode==mParent), "bad mParent, mParent!=mElement->GetParent() ");
|
NS_ASSERTION((parentNode==mParent), "bad mParent, mParent!=mElement->GetParent() ");
|
||||||
|
// end sanity check 1.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// remember which child mElement was (by remembering which child was next)
|
// remember which child mElement was (by remembering which child was next)
|
||||||
|
|
|
@ -23,8 +23,10 @@
|
||||||
#include "nsIDOMNode.h"
|
#include "nsIDOMNode.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
|
|
||||||
class nsIDOMDocument;
|
#define DELETE_ELEMENT_TXN_IID \
|
||||||
class nsIDOMElement;
|
{/* 6fd77770-ac49-11d2-86d8-000064657374 */ \
|
||||||
|
0x6fd77770, 0xac49, 0x11d2, \
|
||||||
|
{0x86, 0xd8, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A transaction that deletes a single element
|
* A transaction that deletes a single element
|
||||||
|
@ -33,10 +35,13 @@ class DeleteElementTxn : public EditTxn
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DeleteElementTxn(nsEditor *aEditor,
|
virtual nsresult Init(nsIDOMNode *aElement,
|
||||||
nsIDOMDocument *aDoc,
|
nsIDOMNode *aParent);
|
||||||
nsIDOMNode *aElement,
|
|
||||||
nsIDOMNode *aParent);
|
private:
|
||||||
|
DeleteElementTxn();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
virtual ~DeleteElementTxn();
|
virtual ~DeleteElementTxn();
|
||||||
|
|
||||||
|
@ -58,14 +63,11 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/** the document into which the new node will be inserted */
|
|
||||||
nsIDOMDocument *mDoc;
|
|
||||||
|
|
||||||
/** the element to delete */
|
/** the element to delete */
|
||||||
nsIDOMNode *mElement;
|
nsCOMPtr<nsIDOMNode> mElement;
|
||||||
|
|
||||||
/** the node into which the new node will be inserted */
|
/** the node into which the new node will be inserted */
|
||||||
nsIDOMNode *mParent;
|
nsCOMPtr<nsIDOMNode> mParent;
|
||||||
|
|
||||||
/** the index in mParent for the new node */
|
/** the index in mParent for the new node */
|
||||||
PRUint32 mOffsetInParent;
|
PRUint32 mOffsetInParent;
|
||||||
|
@ -73,6 +75,8 @@ protected:
|
||||||
/** the node we will insert mNewNode before. We compute this ourselves. */
|
/** the node we will insert mNewNode before. We compute this ourselves. */
|
||||||
nsCOMPtr<nsIDOMNode> mRefNode;
|
nsCOMPtr<nsIDOMNode> mRefNode;
|
||||||
|
|
||||||
|
friend class TransactionFactory;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,18 +17,73 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "DeleteRangeTxn.h"
|
#include "DeleteRangeTxn.h"
|
||||||
#include "editor.h"
|
|
||||||
#include "nsIDOMRange.h"
|
#include "nsIDOMRange.h"
|
||||||
|
#include "nsIDOMCharacterData.h"
|
||||||
|
#include "nsIDOMNodeList.h"
|
||||||
|
#include "DeleteTextTxn.h"
|
||||||
|
#include "DeleteElementTxn.h"
|
||||||
|
#include "TransactionFactory.h"
|
||||||
|
#include "nsISupportsArray.h"
|
||||||
|
|
||||||
|
static NS_DEFINE_IID(kDeleteTextTxnIID, DELETE_TEXT_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kDeleteElementTxnIID, DELETE_ELEMENT_TXN_IID);
|
||||||
|
|
||||||
|
|
||||||
// note that aEditor is not refcounted
|
// note that aEditor is not refcounted
|
||||||
DeleteRangeTxn::DeleteRangeTxn(nsEditor *aEditor,
|
DeleteRangeTxn::DeleteRangeTxn()
|
||||||
nsIDOMRange *aRange)
|
: EditAggregateTxn()
|
||||||
: EditTxn(aEditor)
|
|
||||||
{
|
{
|
||||||
aRange->GetStartParent(getter_AddRefs(mStartParent));
|
}
|
||||||
aRange->GetEndParent(getter_AddRefs(mEndParent));
|
|
||||||
aRange->GetStartOffset(&mStartOffset);
|
nsresult DeleteRangeTxn::Init(nsIDOMRange *aRange)
|
||||||
aRange->GetEndOffset(&mEndOffset);
|
{
|
||||||
|
if (nsnull!=aRange)
|
||||||
|
{
|
||||||
|
nsresult result = aRange->GetStartParent(getter_AddRefs(mStartParent));
|
||||||
|
NS_ASSERTION((NS_SUCCEEDED(result)), "GetStartParent failed.");
|
||||||
|
result = aRange->GetEndParent(getter_AddRefs(mEndParent));
|
||||||
|
NS_ASSERTION((NS_SUCCEEDED(result)), "GetEndParent failed.");
|
||||||
|
result = aRange->GetStartOffset(&mStartOffset);
|
||||||
|
NS_ASSERTION((NS_SUCCEEDED(result)), "GetStartOffset failed.");
|
||||||
|
result = aRange->GetEndOffset(&mEndOffset);
|
||||||
|
NS_ASSERTION((NS_SUCCEEDED(result)), "GetEndOffset failed.");
|
||||||
|
result = aRange->GetCommonParent(getter_AddRefs(mCommonParent));
|
||||||
|
NS_ASSERTION((NS_SUCCEEDED(result)), "GetCommonParent failed.");
|
||||||
|
|
||||||
|
#ifdef NS_DEBUG
|
||||||
|
PRUint32 count;
|
||||||
|
nsCOMPtr<nsIDOMCharacterData> textNode;
|
||||||
|
textNode = mStartParent;
|
||||||
|
if (textNode)
|
||||||
|
textNode->GetLength(&count);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMNodeList> children;
|
||||||
|
result = mStartParent->GetChildNodes(getter_AddRefs(children));
|
||||||
|
NS_ASSERTION(((NS_SUCCEEDED(result)) && children), "bad start child list");
|
||||||
|
children->GetLength(&count);
|
||||||
|
}
|
||||||
|
NS_ASSERTION(mStartOffset<count, "bad start offset");
|
||||||
|
|
||||||
|
textNode = mEndParent;
|
||||||
|
if (textNode)
|
||||||
|
textNode->GetLength(&count);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMNodeList> children;
|
||||||
|
result = mEndParent->GetChildNodes(getter_AddRefs(children));
|
||||||
|
NS_ASSERTION(((NS_SUCCEEDED(result)) && children), "bad end child list");
|
||||||
|
children->GetLength(&count);
|
||||||
|
}
|
||||||
|
NS_ASSERTION(mEndOffset<count, "bad end offset");
|
||||||
|
|
||||||
|
printf ("DeleteRange: %d of %p to %d of %p\n",
|
||||||
|
mStartOffset, (void *)mStartParent, mEndOffset, (void *)mEndParent);
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
DeleteRangeTxn::~DeleteRangeTxn()
|
DeleteRangeTxn::~DeleteRangeTxn()
|
||||||
|
@ -37,28 +92,59 @@ DeleteRangeTxn::~DeleteRangeTxn()
|
||||||
|
|
||||||
nsresult DeleteRangeTxn::Do(void)
|
nsresult DeleteRangeTxn::Do(void)
|
||||||
{
|
{
|
||||||
if (!mStartParent || !mEndParent)
|
if (!mStartParent || !mEndParent || !mCommonParent)
|
||||||
return NS_ERROR_NULL_POINTER;
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
|
||||||
nsresult result;
|
nsresult result;
|
||||||
|
|
||||||
|
// build the child transactions
|
||||||
|
|
||||||
|
if (mStartParent==mEndParent)
|
||||||
|
{ // the selection begins and ends in the same node
|
||||||
|
result = CreateTxnsToDeleteBetween(mStartParent, mStartOffset, mEndOffset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // the selection ends in a different node from where it started
|
||||||
|
// delete the relevant content in the start node
|
||||||
|
result = CreateTxnsToDeleteContent(mStartParent, mStartOffset, nsIEditor::eLTR);
|
||||||
|
if (NS_SUCCEEDED(result))
|
||||||
|
{
|
||||||
|
// delete the intervening nodes
|
||||||
|
result = CreateTxnsToDeleteNodesBetween(mCommonParent, mStartParent, mEndParent);
|
||||||
|
if (NS_SUCCEEDED(result))
|
||||||
|
{
|
||||||
|
// delete the relevant content in the end node
|
||||||
|
result = CreateTxnsToDeleteContent(mEndParent, mEndOffset, nsIEditor::eRTL);
|
||||||
|
if (NS_SUCCEEDED(result))
|
||||||
|
{ // now we have all our child transactions, do them
|
||||||
|
result = EditAggregateTxn::Do();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we've successfully built this aggregate transaction, then do it.
|
||||||
|
if (NS_SUCCEEDED(result))
|
||||||
|
result = EditAggregateTxn::Do();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult DeleteRangeTxn::Undo(void)
|
nsresult DeleteRangeTxn::Undo(void)
|
||||||
{
|
{
|
||||||
if (!mStartParent || !mEndParent)
|
if (!mStartParent || !mEndParent || !mCommonParent)
|
||||||
return NS_ERROR_NULL_POINTER;
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
|
||||||
nsresult result;
|
nsresult result = EditAggregateTxn::Undo();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult DeleteRangeTxn::Redo(void)
|
nsresult DeleteRangeTxn::Redo(void)
|
||||||
{
|
{
|
||||||
if (!mStartParent || !mEndParent)
|
if (!mStartParent || !mEndParent || !mCommonParent)
|
||||||
return NS_ERROR_NULL_POINTER;
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
|
||||||
nsresult result;
|
nsresult result = EditAggregateTxn::Redo();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,3 +184,265 @@ nsresult DeleteRangeTxn::GetRedoString(nsString **aString)
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult DeleteRangeTxn::CreateTxnsToDeleteBetween(nsIDOMNode *aStartParent,
|
||||||
|
PRUint32 aStartOffset,
|
||||||
|
PRUint32 aEndOffset)
|
||||||
|
{
|
||||||
|
nsresult result;
|
||||||
|
// see what kind of node we have
|
||||||
|
nsCOMPtr<nsIDOMCharacterData> textNode;
|
||||||
|
textNode = aStartParent; // this uses implicit nsCOMPtr QI
|
||||||
|
if (textNode)
|
||||||
|
{ // if the node is a text node, then delete text content
|
||||||
|
DeleteTextTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kDeleteTextTxnIID, (EditTxn **)&txn);
|
||||||
|
if (nsnull!=txn)
|
||||||
|
{
|
||||||
|
txn->Init(textNode, aStartOffset, (aEndOffset-aStartOffset)+1);
|
||||||
|
AppendChild(txn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PRUint32 childCount;
|
||||||
|
nsCOMPtr<nsIDOMNodeList> children;
|
||||||
|
result = aStartParent->GetChildNodes(getter_AddRefs(children));
|
||||||
|
if ((NS_SUCCEEDED(result)) && children)
|
||||||
|
{
|
||||||
|
children->GetLength(&childCount);
|
||||||
|
NS_ASSERTION(aEndOffset<childCount, "bad aEndOffset");
|
||||||
|
PRUint32 i;
|
||||||
|
for (i=aStartOffset; i<=aEndOffset; i++)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMNode> child;
|
||||||
|
result = children->Item(i, getter_AddRefs(child));
|
||||||
|
if ((NS_SUCCEEDED(result)) && child)
|
||||||
|
{
|
||||||
|
DeleteElementTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kDeleteElementTxnIID, (EditTxn **)&txn);
|
||||||
|
if (nsnull!=txn)
|
||||||
|
{
|
||||||
|
txn->Init(child, aStartParent);
|
||||||
|
AppendChild(txn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult DeleteRangeTxn::CreateTxnsToDeleteContent(nsIDOMNode *aParent,
|
||||||
|
PRUint32 aOffset,
|
||||||
|
nsIEditor::Direction aDir)
|
||||||
|
{
|
||||||
|
nsresult result;
|
||||||
|
// see what kind of node we have
|
||||||
|
nsCOMPtr<nsIDOMCharacterData> textNode;
|
||||||
|
textNode = aParent; // this uses implicit nsCOMPtr QI
|
||||||
|
if (textNode)
|
||||||
|
{ // if the node is a text node, then delete text content
|
||||||
|
PRUint32 start, numToDelete;
|
||||||
|
if (nsIEditor::eLTR==aDir)
|
||||||
|
{
|
||||||
|
start=aOffset;
|
||||||
|
textNode->GetLength(&numToDelete);
|
||||||
|
numToDelete -= (aOffset+1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
start=0;
|
||||||
|
numToDelete=aOffset;
|
||||||
|
}
|
||||||
|
DeleteTextTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kDeleteTextTxnIID, (EditTxn **)&txn);
|
||||||
|
if (nsnull!=txn)
|
||||||
|
{
|
||||||
|
txn->Init(textNode, start, numToDelete);
|
||||||
|
AppendChild(txn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // we have an interior node, so delete some of its children
|
||||||
|
if (nsIEditor::eLTR==aDir)
|
||||||
|
{ // delete from aOffset to end
|
||||||
|
PRUint32 childCount;
|
||||||
|
nsCOMPtr<nsIDOMNodeList> children;
|
||||||
|
result = aParent->GetChildNodes(getter_AddRefs(children));
|
||||||
|
if ((NS_SUCCEEDED(result)) && children)
|
||||||
|
{
|
||||||
|
children->GetLength(&childCount);
|
||||||
|
PRUint32 i;
|
||||||
|
for (i=aOffset; i<childCount; i++)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMNode> child;
|
||||||
|
result = children->Item(i, getter_AddRefs(child));
|
||||||
|
if ((NS_SUCCEEDED(result)) && child)
|
||||||
|
{
|
||||||
|
DeleteElementTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kDeleteElementTxnIID, (EditTxn **)&txn);
|
||||||
|
if (nsnull!=txn)
|
||||||
|
{
|
||||||
|
txn->Init(child, aParent);
|
||||||
|
AppendChild(txn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // delete from 0 to aOffset
|
||||||
|
nsCOMPtr<nsIDOMNode> child;
|
||||||
|
result = aParent->GetFirstChild(getter_AddRefs(child));
|
||||||
|
for (PRUint32 i=0; i<aOffset; i++)
|
||||||
|
{
|
||||||
|
if ((NS_SUCCEEDED(result)) && child)
|
||||||
|
{
|
||||||
|
DeleteElementTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kDeleteElementTxnIID, (EditTxn **)&txn);
|
||||||
|
if (nsnull!=txn)
|
||||||
|
{
|
||||||
|
txn->Init(child, aParent);
|
||||||
|
AppendChild(txn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
nsCOMPtr<nsIDOMNode> temp = child;
|
||||||
|
result = temp->GetNextSibling(getter_AddRefs(child));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult DeleteRangeTxn::CreateTxnsToDeleteNodesBetween(nsIDOMNode *aCommonParent,
|
||||||
|
nsIDOMNode *aFirstChild,
|
||||||
|
nsIDOMNode *aLastChild)
|
||||||
|
{
|
||||||
|
nsresult result;
|
||||||
|
PRBool needToProcessLastChild=PR_TRUE; // set to false if we discover we can delete all required nodes by just walking up aFirstChild's parent list
|
||||||
|
nsCOMPtr<nsIDOMNode> parent; // the current parent in the iteration up the ancestors
|
||||||
|
nsCOMPtr<nsIDOMNode> child; // the current child of parent
|
||||||
|
nsISupportsArray *ancestorList; // the ancestorList of the other endpoint, used to gate deletion
|
||||||
|
NS_NewISupportsArray(&ancestorList);
|
||||||
|
if (nsnull==ancestorList)
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
|
||||||
|
// Walk up the parent list of aFirstChild to aCommonParent,
|
||||||
|
// deleting all siblings to the right of the ancestors of aFirstChild.
|
||||||
|
BuildAncestorList(aLastChild, ancestorList);
|
||||||
|
child = aFirstChild;
|
||||||
|
result = child->GetParentNode(getter_AddRefs(parent));
|
||||||
|
while ((NS_SUCCEEDED(result)) && parent)
|
||||||
|
{
|
||||||
|
while ((NS_SUCCEEDED(result)) && child)
|
||||||
|
{ // this loop starts with the first sibling of an ancestor of aFirstChild
|
||||||
|
nsCOMPtr<nsIDOMNode> temp = child;
|
||||||
|
result = temp->GetNextSibling(getter_AddRefs(child));
|
||||||
|
if ((NS_SUCCEEDED(result)) && child)
|
||||||
|
{
|
||||||
|
if (child==aLastChild)
|
||||||
|
{ // aFirstChild and aLastChild have the same parent, and we've reached aLastChild
|
||||||
|
needToProcessLastChild = PR_FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// test if child is an ancestor of the other node. If it is, don't process this parent anymore
|
||||||
|
PRInt32 index;
|
||||||
|
index = ancestorList->IndexOf((nsISupports*)child);
|
||||||
|
if (-1!=index)
|
||||||
|
break;
|
||||||
|
DeleteElementTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kDeleteElementTxnIID, (EditTxn **)&txn);
|
||||||
|
if (nsnull!=txn)
|
||||||
|
{
|
||||||
|
txn->Init(child, parent);
|
||||||
|
AppendChild(txn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (parent==aCommonParent)
|
||||||
|
break;
|
||||||
|
child = parent;
|
||||||
|
nsCOMPtr<nsIDOMNode> temp=parent;
|
||||||
|
result = temp->GetParentNode(getter_AddRefs(parent));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk up the parent list of aLastChild to aCommonParent,
|
||||||
|
// deleting all siblings to the left of the ancestors of aLastChild.
|
||||||
|
BuildAncestorList(aFirstChild, ancestorList);
|
||||||
|
if (PR_TRUE==needToProcessLastChild)
|
||||||
|
{
|
||||||
|
child = aLastChild;
|
||||||
|
result = child->GetParentNode(getter_AddRefs(parent));
|
||||||
|
while ((NS_SUCCEEDED(result)) && parent)
|
||||||
|
{
|
||||||
|
while ((NS_SUCCEEDED(result)) && child)
|
||||||
|
{ // this loop starts with the first sibling of an ancestor of aFirstChild
|
||||||
|
nsCOMPtr<nsIDOMNode> temp = child;
|
||||||
|
result = temp->GetPreviousSibling(getter_AddRefs(child));
|
||||||
|
if ((NS_SUCCEEDED(result)) && child)
|
||||||
|
{
|
||||||
|
// test if child is an ancestor of the other node. If it is, don't process this parent anymore
|
||||||
|
PRInt32 index;
|
||||||
|
index = ancestorList->IndexOf((nsISupports*)child);
|
||||||
|
if (-1!=index)
|
||||||
|
break;
|
||||||
|
DeleteElementTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kDeleteElementTxnIID, (EditTxn **)&txn);
|
||||||
|
if (nsnull!=txn)
|
||||||
|
{
|
||||||
|
txn->Init(child, parent);
|
||||||
|
AppendChild(txn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (parent==aCommonParent)
|
||||||
|
break;
|
||||||
|
child = parent;
|
||||||
|
nsCOMPtr<nsIDOMNode> temp=parent;
|
||||||
|
result = temp->GetParentNode(getter_AddRefs(parent));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NS_RELEASE(ancestorList);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult DeleteRangeTxn::BuildAncestorList(nsIDOMNode *aNode, nsISupportsArray *aList)
|
||||||
|
{
|
||||||
|
nsresult result=NS_OK;
|
||||||
|
if (nsnull!=aNode && nsnull!=aList)
|
||||||
|
{
|
||||||
|
aList->Clear();
|
||||||
|
nsCOMPtr<nsIDOMNode> parent;
|
||||||
|
nsCOMPtr<nsIDOMNode> child = aNode;
|
||||||
|
result = child->GetParentNode(getter_AddRefs(parent));
|
||||||
|
while ((NS_SUCCEEDED(result)) && child && parent)
|
||||||
|
{
|
||||||
|
nsISupports * parentAsISupports;
|
||||||
|
parent->QueryInterface(nsISupports::IID(), (void **)&parentAsISupports);
|
||||||
|
aList->AppendElement(parentAsISupports);
|
||||||
|
child = parent;
|
||||||
|
nsCOMPtr<nsIDOMNode> temp=parent;
|
||||||
|
result = temp->GetParentNode(getter_AddRefs(parent));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = NS_ERROR_NULL_POINTER;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -19,22 +19,33 @@
|
||||||
#ifndef DeleteRangeTxn_h__
|
#ifndef DeleteRangeTxn_h__
|
||||||
#define DeleteRangeTxn_h__
|
#define DeleteRangeTxn_h__
|
||||||
|
|
||||||
#include "EditTxn.h"
|
#include "EditAggregateTxn.h"
|
||||||
#include "nsIDOMNode.h"
|
#include "nsIDOMNode.h"
|
||||||
|
#include "nsIEditor.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
|
|
||||||
class nsIDOMDocument;
|
class nsIDOMDocument;
|
||||||
class nsIDOMRange;
|
class nsIDOMRange;
|
||||||
|
class nsISupportsArray;
|
||||||
|
|
||||||
|
#define DELETE_RANGE_TXN_IID \
|
||||||
|
{/* 5ec6b260-ac49-11d2-86d8-000064657374 */ \
|
||||||
|
0x5ec6b260, 0xac49, 0x11d2, \
|
||||||
|
{0x86, 0xd8, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A transaction that deletes an entire range in the content tree
|
* A transaction that deletes an entire range in the content tree
|
||||||
*/
|
*/
|
||||||
class DeleteRangeTxn : public EditTxn
|
class DeleteRangeTxn : public EditAggregateTxn
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DeleteRangeTxn(nsEditor *aEditor,
|
virtual nsresult Init(nsIDOMRange *aRange);
|
||||||
nsIDOMRange *aRange);
|
|
||||||
|
private:
|
||||||
|
DeleteRangeTxn();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
virtual ~DeleteRangeTxn();
|
virtual ~DeleteRangeTxn();
|
||||||
|
|
||||||
|
@ -54,6 +65,23 @@ public:
|
||||||
|
|
||||||
virtual nsresult GetRedoString(nsString **aString);
|
virtual nsresult GetRedoString(nsString **aString);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual nsresult CreateTxnsToDeleteBetween(nsIDOMNode *aStartParent,
|
||||||
|
PRUint32 aStartOffset,
|
||||||
|
PRUint32 aEndOffset);
|
||||||
|
|
||||||
|
virtual nsresult CreateTxnsToDeleteNodesBetween(nsIDOMNode *aParent,
|
||||||
|
nsIDOMNode *aFirstChild,
|
||||||
|
nsIDOMNode *aLastChild);
|
||||||
|
|
||||||
|
virtual nsresult CreateTxnsToDeleteContent(nsIDOMNode *aParent,
|
||||||
|
PRUint32 aOffset,
|
||||||
|
nsIEditor::Direction aDir);
|
||||||
|
|
||||||
|
virtual nsresult BuildAncestorList(nsIDOMNode *aNode,
|
||||||
|
nsISupportsArray *aList);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/** p1 in the range */
|
/** p1 in the range */
|
||||||
|
@ -65,9 +93,14 @@ protected:
|
||||||
/** p2 in the range */
|
/** p2 in the range */
|
||||||
nsCOMPtr<nsIDOMNode> mEndParent;
|
nsCOMPtr<nsIDOMNode> mEndParent;
|
||||||
|
|
||||||
|
/** the closest common parent of p1 and p2 */
|
||||||
|
nsCOMPtr<nsIDOMNode> mCommonParent;
|
||||||
|
|
||||||
/** p2 offset */
|
/** p2 offset */
|
||||||
PRInt32 mEndOffset;
|
PRInt32 mEndOffset;
|
||||||
|
|
||||||
|
friend class TransactionFactory;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,20 +17,23 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "DeleteTextTxn.h"
|
#include "DeleteTextTxn.h"
|
||||||
#include "editor.h"
|
|
||||||
#include "nsIDOMCharacterData.h"
|
#include "nsIDOMCharacterData.h"
|
||||||
|
|
||||||
// note that aEditor is not refcounted
|
|
||||||
DeleteTextTxn::DeleteTextTxn(nsEditor *aEditor,
|
DeleteTextTxn::DeleteTextTxn()
|
||||||
nsIDOMCharacterData *aElement,
|
: EditTxn()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult DeleteTextTxn::Init(nsIDOMCharacterData *aElement,
|
||||||
PRUint32 aOffset,
|
PRUint32 aOffset,
|
||||||
PRUint32 aNumCharsToDelete)
|
PRUint32 aNumCharsToDelete)
|
||||||
: EditTxn(aEditor)
|
|
||||||
{
|
{
|
||||||
mElement = aElement;
|
mElement = aElement;
|
||||||
mOffset = aOffset;
|
mOffset = aOffset;
|
||||||
mNumCharsToDelete = aNumCharsToDelete;
|
mNumCharsToDelete = aNumCharsToDelete;
|
||||||
mDeletedText = "";
|
mDeletedText = "";
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult DeleteTextTxn::Do(void)
|
nsresult DeleteTextTxn::Do(void)
|
||||||
|
|
|
@ -20,8 +20,13 @@
|
||||||
#define DeleteTextTxn_h__
|
#define DeleteTextTxn_h__
|
||||||
|
|
||||||
#include "EditTxn.h"
|
#include "EditTxn.h"
|
||||||
|
#include "nsIDOMCharacterData.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
|
||||||
class nsIDOMCharacterData;
|
#define DELETE_TEXT_TXN_IID \
|
||||||
|
{/* 4d3a2720-ac49-11d2-86d8-000064657374 */ \
|
||||||
|
0x4d3a2720, 0xac49, 0x11d2, \
|
||||||
|
{0x86, 0xd8, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A transaction that changes an attribute of a content node.
|
* A transaction that changes an attribute of a content node.
|
||||||
|
@ -31,10 +36,14 @@ class DeleteTextTxn : public EditTxn
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DeleteTextTxn(nsEditor *aEditor,
|
virtual nsresult Init(nsIDOMCharacterData *aElement,
|
||||||
nsIDOMCharacterData *aElement,
|
PRUint32 aOffset,
|
||||||
PRUint32 aOffset,
|
PRUint32 aNumCharsToDelete);
|
||||||
PRUint32 aNumCharsToDelete);
|
|
||||||
|
private:
|
||||||
|
DeleteTextTxn();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
virtual nsresult Do(void);
|
virtual nsresult Do(void);
|
||||||
|
|
||||||
|
@ -53,7 +62,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/** the text element to operate upon */
|
/** the text element to operate upon */
|
||||||
nsIDOMCharacterData *mElement;
|
nsCOMPtr<nsIDOMCharacterData> mElement;
|
||||||
|
|
||||||
/** the offset into mElement where the deletion is to take place */
|
/** the offset into mElement where the deletion is to take place */
|
||||||
PRUint32 mOffset;
|
PRUint32 mOffset;
|
||||||
|
@ -64,6 +73,8 @@ protected:
|
||||||
/** the text that was deleted */
|
/** the text that was deleted */
|
||||||
nsString mDeletedText;
|
nsString mDeletedText;
|
||||||
|
|
||||||
|
friend class TransactionFactory;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,145 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public License
|
||||||
|
* Version 1.0 (the "NPL") you may not use this file except in
|
||||||
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||||
|
* http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* NPL.
|
||||||
|
*
|
||||||
|
* The Initial Developer of this code under the NPL is Netscape
|
||||||
|
* Communications Corporation. Portions created by Netscape are
|
||||||
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||||
|
* Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "EditAggregateTxn.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsIDOMNode.h"
|
||||||
|
#include "nsVoidArray.h"
|
||||||
|
|
||||||
|
EditAggregateTxn::EditAggregateTxn()
|
||||||
|
: EditTxn()
|
||||||
|
{
|
||||||
|
mChildren = new nsVoidArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
EditAggregateTxn::~EditAggregateTxn()
|
||||||
|
{
|
||||||
|
if (nsnull!=mChildren)
|
||||||
|
{
|
||||||
|
PRInt32 i;
|
||||||
|
PRInt32 count = mChildren->Count();
|
||||||
|
for (i=0; i<count; i++)
|
||||||
|
{
|
||||||
|
EditTxn *txn = (EditTxn*)(mChildren->ElementAt(i));
|
||||||
|
NS_IF_RELEASE(txn);
|
||||||
|
}
|
||||||
|
delete mChildren;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult EditAggregateTxn::Do(void)
|
||||||
|
{
|
||||||
|
nsresult result=NS_OK; // it's legal (but not very useful) to have an empty child list
|
||||||
|
if (nsnull!=mChildren)
|
||||||
|
{
|
||||||
|
PRInt32 i;
|
||||||
|
PRInt32 count = mChildren->Count();
|
||||||
|
for (i=0; i<count; i++)
|
||||||
|
{
|
||||||
|
EditTxn *txn = (EditTxn*)(mChildren->ElementAt(i));
|
||||||
|
result = txn->Do();
|
||||||
|
if (NS_FAILED(result))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult EditAggregateTxn::Undo(void)
|
||||||
|
{
|
||||||
|
nsresult result=NS_OK; // it's legal (but not very useful) to have an empty child list
|
||||||
|
if (nsnull!=mChildren)
|
||||||
|
{
|
||||||
|
PRInt32 i;
|
||||||
|
PRInt32 count = mChildren->Count();
|
||||||
|
// undo goes through children backwards
|
||||||
|
for (i=count-1; i>=0; i--)
|
||||||
|
{
|
||||||
|
EditTxn *txn = (EditTxn*)(mChildren->ElementAt(i));
|
||||||
|
result = txn->Undo();
|
||||||
|
if (NS_FAILED(result))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult EditAggregateTxn::Redo(void)
|
||||||
|
{
|
||||||
|
nsresult result=NS_OK; // it's legal (but not very useful) to have an empty child list
|
||||||
|
if (nsnull!=mChildren)
|
||||||
|
{
|
||||||
|
PRInt32 i;
|
||||||
|
PRInt32 count = mChildren->Count();
|
||||||
|
for (i=0; i<count; i++)
|
||||||
|
{
|
||||||
|
EditTxn *txn = (EditTxn*)(mChildren->ElementAt(i));
|
||||||
|
result = txn->Redo();
|
||||||
|
if (NS_FAILED(result))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult EditAggregateTxn::GetIsTransient(PRBool *aIsTransient)
|
||||||
|
{
|
||||||
|
if (nsnull!=aIsTransient)
|
||||||
|
*aIsTransient = PR_TRUE;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult EditAggregateTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
|
||||||
|
{
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult EditAggregateTxn::Write(nsIOutputStream *aOutputStream)
|
||||||
|
{
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult EditAggregateTxn::GetUndoString(nsString **aString)
|
||||||
|
{
|
||||||
|
if (nsnull!=aString)
|
||||||
|
*aString=nsnull;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult EditAggregateTxn::GetRedoString(nsString **aString)
|
||||||
|
{
|
||||||
|
if (nsnull!=aString)
|
||||||
|
*aString=nsnull;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult EditAggregateTxn::AppendChild(EditTxn *aTxn)
|
||||||
|
{
|
||||||
|
if ((nsnull!=mChildren) && (nsnull!=aTxn))
|
||||||
|
{
|
||||||
|
mChildren->AppendElement(aTxn);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public License
|
||||||
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||||
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||||
|
* http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* NPL.
|
||||||
|
*
|
||||||
|
* The Initial Developer of this code under the NPL is Netscape
|
||||||
|
* Communications Corporation. Portions created by Netscape are
|
||||||
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||||
|
* Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EditAggregateTxn_h__
|
||||||
|
#define EditAggregateTxn_h__
|
||||||
|
|
||||||
|
#include "EditTxn.h"
|
||||||
|
|
||||||
|
#define EDIT_AGGREGATE_TXN_IID \
|
||||||
|
{/* 345921a0-ac49-11d2-86d8-000064657374 */ \
|
||||||
|
0x345921a0, 0xac49, 0x11d2, \
|
||||||
|
{0x86, 0xd8, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
|
||||||
|
|
||||||
|
class nsVoidArray;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* base class for all document editing transactions that require aggregation.
|
||||||
|
* provides a list of child transactions.
|
||||||
|
*/
|
||||||
|
class EditAggregateTxn : public EditTxn
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
EditAggregateTxn();
|
||||||
|
|
||||||
|
virtual ~EditAggregateTxn();
|
||||||
|
|
||||||
|
virtual nsresult Do(void);
|
||||||
|
|
||||||
|
virtual nsresult Undo(void);
|
||||||
|
|
||||||
|
virtual nsresult Redo(void);
|
||||||
|
|
||||||
|
virtual nsresult GetIsTransient(PRBool *aIsTransient);
|
||||||
|
|
||||||
|
virtual nsresult Merge(PRBool *aDidMerge, nsITransaction *aTransaction);
|
||||||
|
|
||||||
|
virtual nsresult Write(nsIOutputStream *aOutputStream);
|
||||||
|
|
||||||
|
virtual nsresult GetUndoString(nsString **aString);
|
||||||
|
|
||||||
|
virtual nsresult GetRedoString(nsString **aString);
|
||||||
|
|
||||||
|
virtual nsresult AppendChild(EditTxn *aTxn);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
nsVoidArray *mChildren;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -28,10 +28,8 @@ NS_IMPL_ADDREF(EditTxn)
|
||||||
NS_IMPL_RELEASE(EditTxn)
|
NS_IMPL_RELEASE(EditTxn)
|
||||||
|
|
||||||
// note that aEditor is not refcounted
|
// note that aEditor is not refcounted
|
||||||
EditTxn::EditTxn(nsEditor *aEditor)
|
EditTxn::EditTxn()
|
||||||
{
|
{
|
||||||
NS_ASSERTION(nsnull!=aEditor, "null aEditor arg to EditTxn constructor");
|
|
||||||
mEditor = aEditor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult EditTxn::Do(void)
|
nsresult EditTxn::Do(void)
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the Netscape Public License
|
|
||||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
||||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
||||||
* http://www.mozilla.org/NPL/
|
|
||||||
*
|
|
||||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
||||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
||||||
* for the specific language governing rights and limitations under the
|
|
||||||
* NPL.
|
|
||||||
*
|
|
||||||
* The Initial Developer of this code under the NPL is Netscape
|
|
||||||
* Communications Corporation. Portions created by Netscape are
|
|
||||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
||||||
* Reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EditTxn_h__
|
|
||||||
#define EditTxn_h__
|
|
||||||
|
|
||||||
#include "nsITransaction.h"
|
|
||||||
class nsEditor;
|
|
||||||
|
|
||||||
class nsIDOMNode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* base class for all document editing transactions.
|
|
||||||
* provides access to the nsEditor that created this transaction.
|
|
||||||
*/
|
|
||||||
class EditTxn : public nsITransaction
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
NS_DECL_ISUPPORTS
|
|
||||||
|
|
||||||
EditTxn(nsEditor *aEditor);
|
|
||||||
|
|
||||||
virtual nsresult Do(void);
|
|
||||||
|
|
||||||
virtual nsresult Undo(void);
|
|
||||||
|
|
||||||
virtual nsresult Redo(void);
|
|
||||||
|
|
||||||
virtual nsresult GetIsTransient(PRBool *aIsTransient);
|
|
||||||
|
|
||||||
virtual nsresult Merge(PRBool *aDidMerge, nsITransaction *aTransaction);
|
|
||||||
|
|
||||||
virtual nsresult Write(nsIOutputStream *aOutputStream);
|
|
||||||
|
|
||||||
virtual nsresult GetUndoString(nsString **aString);
|
|
||||||
|
|
||||||
virtual nsresult GetRedoString(nsString **aString);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
nsEditor *mEditor;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -20,18 +20,22 @@
|
||||||
#include "editor.h"
|
#include "editor.h"
|
||||||
#include "nsIDOMCharacterData.h"
|
#include "nsIDOMCharacterData.h"
|
||||||
|
|
||||||
static NS_DEFINE_IID(kInsertTextTxnIID, INSERTTEXTTXN_IID);
|
static NS_DEFINE_IID(kInsertTextTxnIID, INSERT_TEXT_TXN_IID);
|
||||||
|
|
||||||
// note that aEditor is not refcounted
|
|
||||||
InsertTextTxn::InsertTextTxn(nsEditor *aEditor,
|
InsertTextTxn::InsertTextTxn()
|
||||||
nsIDOMCharacterData *aElement,
|
: EditTxn()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult InsertTextTxn::Init(nsIDOMCharacterData *aElement,
|
||||||
PRUint32 aOffset,
|
PRUint32 aOffset,
|
||||||
const nsString& aStringToInsert)
|
const nsString& aStringToInsert)
|
||||||
: EditTxn(aEditor)
|
|
||||||
{
|
{
|
||||||
mElement = aElement;
|
mElement = aElement;
|
||||||
mOffset = aOffset;
|
mOffset = aOffset;
|
||||||
mStringToInsert = aStringToInsert;
|
mStringToInsert = aStringToInsert;
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult InsertTextTxn::Do(void)
|
nsresult InsertTextTxn::Do(void)
|
||||||
|
@ -60,11 +64,11 @@ nsresult InsertTextTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
|
||||||
if ((nsnull!=aDidMerge) && (nsnull!=aTransaction))
|
if ((nsnull!=aDidMerge) && (nsnull!=aTransaction))
|
||||||
{
|
{
|
||||||
// if aTransaction isa InsertTextTxn, absorb it
|
// if aTransaction isa InsertTextTxn, absorb it
|
||||||
nsCOMPtr<InsertTextTxn> otherTxn;
|
nsCOMPtr<InsertTextTxn> otherTxn = aTransaction;
|
||||||
nsresult result = aTransaction->QueryInterface(kInsertTextTxnIID, getter_AddRefs(otherTxn));
|
nsresult result=NS_OK;// = aTransaction->QueryInterface(kInsertTextTxnIID, getter_AddRefs(otherTxn));
|
||||||
if (NS_SUCCEEDED(result) && (otherTxn))
|
if (NS_SUCCEEDED(result) && (otherTxn))
|
||||||
{
|
{
|
||||||
nsString otherData;
|
nsAutoString otherData;
|
||||||
otherTxn->GetData(otherData);
|
otherTxn->GetData(otherData);
|
||||||
mStringToInsert += otherData;
|
mStringToInsert += otherData;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,14 +20,14 @@
|
||||||
#define InsertTextTxn_h__
|
#define InsertTextTxn_h__
|
||||||
|
|
||||||
#include "EditTxn.h"
|
#include "EditTxn.h"
|
||||||
|
#include "nsIDOMCharacterData.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
|
||||||
#define INSERTTEXTTXN_IID \
|
#define INSERT_TEXT_TXN_IID \
|
||||||
{/* 93276f00-ab2c-11d2-8f4b-006008159b0c*/ \
|
{/* 93276f00-ab2c-11d2-8f4b-006008159b0c*/ \
|
||||||
0x93276f00, 0xab2c, 0x11d2, \
|
0x93276f00, 0xab2c, 0x11d2, \
|
||||||
{0x8f, 0xb4, 0x0, 0x60, 0x8, 0x15, 0x9b, 0xc} }
|
{0x8f, 0xb4, 0x0, 0x60, 0x8, 0x15, 0x9b, 0xc} }
|
||||||
|
|
||||||
class nsIDOMCharacterData;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A transaction that changes an attribute of a content node.
|
* A transaction that changes an attribute of a content node.
|
||||||
* This transaction covers add, remove, and change attribute.
|
* This transaction covers add, remove, and change attribute.
|
||||||
|
@ -36,15 +36,13 @@ class InsertTextTxn : public EditTxn
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
InsertTextTxn(nsEditor *aEditor,
|
virtual nsresult Init(nsIDOMCharacterData *aElement,
|
||||||
nsIDOMCharacterData *aElement,
|
PRUint32 aOffset,
|
||||||
PRUint32 aOffset,
|
const nsString& aStringToInsert);
|
||||||
const nsString& aStringToInsert);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// default ctor so that nsCOMPtr is happy
|
InsertTextTxn();
|
||||||
InsertTextTxn() : EditTxn(nsnull) {}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -67,7 +65,7 @@ public:
|
||||||
// override QueryInterface to handle InsertTextTxn request
|
// override QueryInterface to handle InsertTextTxn request
|
||||||
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
|
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
|
||||||
|
|
||||||
static const nsIID& IID() { static nsIID iid = INSERTTEXTTXN_IID; return iid; }
|
static const nsIID& IID() { static nsIID iid = INSERT_TEXT_TXN_IID; return iid; }
|
||||||
|
|
||||||
|
|
||||||
virtual nsresult GetData(nsString& aResult);
|
virtual nsresult GetData(nsString& aResult);
|
||||||
|
@ -75,7 +73,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/** the text element to operate upon */
|
/** the text element to operate upon */
|
||||||
nsIDOMCharacterData *mElement;
|
nsCOMPtr<nsIDOMCharacterData> mElement;
|
||||||
|
|
||||||
/** the offset into mElement where the insertion is to take place */
|
/** the offset into mElement where the insertion is to take place */
|
||||||
PRUint32 mOffset;
|
PRUint32 mOffset;
|
||||||
|
@ -86,6 +84,8 @@ protected:
|
||||||
/** the text to insert into mElement at mOffset */
|
/** the text to insert into mElement at mOffset */
|
||||||
nsString mStringToInsert;
|
nsString mStringToInsert;
|
||||||
|
|
||||||
|
friend class TransactionFactory;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
#!gmake
|
|
||||||
#
|
|
||||||
# The contents of this file are subject to the Netscape Public License
|
|
||||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
|
||||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
|
||||||
# http://www.mozilla.org/NPL/
|
|
||||||
#
|
|
||||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
||||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
||||||
# for the specific language governing rights and limitations under the
|
|
||||||
# NPL.
|
|
||||||
#
|
|
||||||
# The Initial Developer of this code under the NPL is Netscape
|
|
||||||
# Communications Corporation. Portions created by Netscape are
|
|
||||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
||||||
# Reserved.
|
|
||||||
|
|
||||||
DEPTH=../..
|
|
||||||
topsrcdir = @top_srcdir@
|
|
||||||
srcdir = @srcdir@
|
|
||||||
VPATH = @srcdir@
|
|
||||||
|
|
||||||
include $(DEPTH)/config/autoconf.mk
|
|
||||||
|
|
||||||
LIBRARY_NAME = ender
|
|
||||||
|
|
||||||
CPPSRCS = \
|
|
||||||
editor.cpp \
|
|
||||||
editorInterfaces.cpp \
|
|
||||||
nsEditFactory.cpp \
|
|
||||||
ChangeAttributeTxn.cpp \
|
|
||||||
EditTxn.cpp \
|
|
||||||
InsertTextTxn.cpp \
|
|
||||||
DeleteTextTxn.cpp \
|
|
||||||
CreateElementTxn.cpp \
|
|
||||||
DeleteElementTxn.cpp \
|
|
||||||
DeleteRangeTxn.cpp \
|
|
||||||
SplitElementTxn.cpp \
|
|
||||||
$(NULL)
|
|
||||||
|
|
||||||
MODULE = editor
|
|
||||||
|
|
||||||
REQUIRES = xpcom raptor dom base
|
|
||||||
|
|
||||||
include $(topsrcdir)/config/config.mk
|
|
||||||
|
|
||||||
include $(topsrcdir)/config/rules.mk
|
|
||||||
|
|
|
@ -17,44 +17,42 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "SplitElementTxn.h"
|
#include "SplitElementTxn.h"
|
||||||
#include "editor.h"
|
|
||||||
#include "nsIDOMNode.h"
|
#include "nsIDOMNode.h"
|
||||||
#include "nsIDOMElement.h"
|
#include "nsIDOMElement.h"
|
||||||
|
#include "editor.h"
|
||||||
|
|
||||||
// note that aEditor is not refcounted
|
// note that aEditor is not refcounted
|
||||||
SplitElementTxn::SplitElementTxn(nsEditor *aEditor,
|
SplitElementTxn::SplitElementTxn()
|
||||||
nsIDOMNode *aNode,
|
: EditTxn()
|
||||||
PRInt32 aOffset)
|
|
||||||
: EditTxn(aEditor)
|
|
||||||
{
|
{
|
||||||
mNode = aNode;
|
}
|
||||||
NS_ADDREF(mNode);
|
|
||||||
|
nsresult SplitElementTxn::Init(nsIDOMNode *aNode,
|
||||||
|
PRInt32 aOffset)
|
||||||
|
{
|
||||||
|
mExistingRightNode = aNode;
|
||||||
mOffset = aOffset;
|
mOffset = aOffset;
|
||||||
mNewNode = nsnull;
|
return NS_OK;
|
||||||
mParent = nsnull;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SplitElementTxn::~SplitElementTxn()
|
SplitElementTxn::~SplitElementTxn()
|
||||||
{
|
{
|
||||||
NS_IF_RELEASE(mNode);
|
|
||||||
NS_IF_RELEASE(mNewNode);
|
|
||||||
NS_IF_RELEASE(mParent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult SplitElementTxn::Do(void)
|
nsresult SplitElementTxn::Do(void)
|
||||||
{
|
{
|
||||||
// create a new node
|
// create a new node
|
||||||
nsresult result = mNode->CloneNode(PR_FALSE, &mNewNode);
|
nsresult result = mExistingRightNode->CloneNode(PR_FALSE, getter_AddRefs(mNewLeftNode));
|
||||||
NS_ASSERTION(((NS_SUCCEEDED(result)) && (nsnull!=mNewNode)), "could not create element.");
|
NS_ASSERTION(((NS_SUCCEEDED(result)) && (mNewLeftNode)), "could not create element.");
|
||||||
|
|
||||||
if ((NS_SUCCEEDED(result)) && (nsnull!=mNewNode))
|
if ((NS_SUCCEEDED(result)) && (mNewLeftNode))
|
||||||
{
|
{
|
||||||
// get the parent node
|
// get the parent node
|
||||||
result = mNode->GetParentNode(&mParent);
|
result = mExistingRightNode->GetParentNode(getter_AddRefs(mParent));
|
||||||
// insert the new node
|
// insert the new node
|
||||||
if ((NS_SUCCEEDED(result)) && (nsnull!=mParent))
|
if ((NS_SUCCEEDED(result)) && (mParent))
|
||||||
{
|
{
|
||||||
result = mEditor->SplitNode(mNode, mOffset, mNewNode, mParent);
|
result = nsEditor::SplitNode(mExistingRightNode, mOffset, mNewLeftNode, mParent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -63,13 +61,13 @@ nsresult SplitElementTxn::Do(void)
|
||||||
nsresult SplitElementTxn::Undo(void)
|
nsresult SplitElementTxn::Undo(void)
|
||||||
{
|
{
|
||||||
// this assumes Do inserted the new node in front of the prior existing node
|
// this assumes Do inserted the new node in front of the prior existing node
|
||||||
nsresult result = mEditor->JoinNodes(mNode, mNewNode, mParent, PR_FALSE);
|
nsresult result = nsEditor::JoinNodes(mExistingRightNode, mNewLeftNode, mParent, PR_FALSE);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult SplitElementTxn::Redo(void)
|
nsresult SplitElementTxn::Redo(void)
|
||||||
{
|
{
|
||||||
nsresult result = mEditor->SplitNode(mNode, mOffset, mNewNode, mParent);
|
nsresult result = nsEditor::SplitNode(mExistingRightNode, mOffset, mNewLeftNode, mParent);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,10 +20,13 @@
|
||||||
#define SplitElementTxn_h__
|
#define SplitElementTxn_h__
|
||||||
|
|
||||||
#include "EditTxn.h"
|
#include "EditTxn.h"
|
||||||
|
#include "nsIDOMNode.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
|
||||||
class nsIDOMNode;
|
#define SPLIT_ELEMENT_TXN_IID \
|
||||||
class nsIDOMElement;
|
{/* 690c6290-ac48-11d2-86d8-000064657374 */ \
|
||||||
class nsIDOMDocument;
|
0x690c6290, 0xac48, 0x11d2, \
|
||||||
|
{0x86, 0xd8, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A transaction that splits an element E into two identical nodes, E1 and E2
|
* A transaction that splits an element E into two identical nodes, E1 and E2
|
||||||
|
@ -33,10 +36,12 @@ class SplitElementTxn : public EditTxn
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
SplitElementTxn(nsEditor *aEditor,
|
virtual nsresult Init (nsIDOMNode *aNode,
|
||||||
nsIDOMNode *aNode,
|
PRInt32 aOffset);
|
||||||
PRInt32 aOffset);
|
protected:
|
||||||
|
SplitElementTxn();
|
||||||
|
|
||||||
|
public:
|
||||||
virtual ~SplitElementTxn();
|
virtual ~SplitElementTxn();
|
||||||
|
|
||||||
virtual nsresult Do(void);
|
virtual nsresult Do(void);
|
||||||
|
@ -58,7 +63,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/** the element to operate upon */
|
/** the element to operate upon */
|
||||||
nsIDOMNode *mNode;
|
nsCOMPtr<nsIDOMNode> mExistingRightNode;
|
||||||
|
|
||||||
/** the offset into mElement where the children of mElement are split.<BR>
|
/** the offset into mElement where the children of mElement are split.<BR>
|
||||||
* mOffset is the index of the last child in the left node.
|
* mOffset is the index of the last child in the left node.
|
||||||
|
@ -67,8 +72,12 @@ protected:
|
||||||
PRInt32 mOffset;
|
PRInt32 mOffset;
|
||||||
|
|
||||||
/** the element we create when splitting mElement */
|
/** the element we create when splitting mElement */
|
||||||
nsIDOMNode *mNewNode;
|
nsCOMPtr<nsIDOMNode> mNewLeftNode;
|
||||||
nsIDOMNode *mParent;
|
|
||||||
|
/** the parent shared by mExistingRightNode and mNewLeftNode */
|
||||||
|
nsCOMPtr<nsIDOMNode> mParent;
|
||||||
|
|
||||||
|
friend class TransactionFactory;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public License
|
||||||
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||||
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||||
|
* http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* NPL.
|
||||||
|
*
|
||||||
|
* The Initial Developer of this code under the NPL is Netscape
|
||||||
|
* Communications Corporation. Portions created by Netscape are
|
||||||
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||||
|
* Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "TransactionFactory.h"
|
||||||
|
// transactions this factory knows how to build
|
||||||
|
#include "InsertTextTxn.h"
|
||||||
|
#include "DeleteTextTxn.h"
|
||||||
|
#include "CreateElementTxn.h"
|
||||||
|
#include "DeleteElementTxn.h"
|
||||||
|
#include "DeleteRangeTxn.h"
|
||||||
|
#include "ChangeAttributeTxn.h"
|
||||||
|
#include "SplitElementTxn.h"
|
||||||
|
#include "JoinElementTxn.h"
|
||||||
|
|
||||||
|
static NS_DEFINE_IID(kInsertTextTxnIID, INSERT_TEXT_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kDeleteTextTxnIID, DELETE_TEXT_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kCreateElementTxnIID, CREATE_ELEMENT_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kDeleteElementTxnIID, DELETE_ELEMENT_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kDeleteRangeTxnIID, DELETE_RANGE_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kChangeAttributeTxnIID,CHANGE_ATTRIBUTE_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kSplitElementTxnIID, SPLIT_ELEMENT_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kJoinElementTxnIID, JOIN_ELEMENT_TXN_IID);
|
||||||
|
|
||||||
|
TransactionFactory::TransactionFactory()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
TransactionFactory::~TransactionFactory()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
TransactionFactory::GetNewTransaction(REFNSIID aTxnType, EditTxn **aResult)
|
||||||
|
{
|
||||||
|
nsresult result = NS_OK;
|
||||||
|
*aResult = nsnull;
|
||||||
|
if (aTxnType.Equals(kInsertTextTxnIID))
|
||||||
|
*aResult = new InsertTextTxn();
|
||||||
|
else if (aTxnType.Equals(kDeleteTextTxnIID))
|
||||||
|
*aResult = new DeleteTextTxn();
|
||||||
|
else if (aTxnType.Equals(kCreateElementTxnIID))
|
||||||
|
*aResult = new CreateElementTxn();
|
||||||
|
else if (aTxnType.Equals(kDeleteElementTxnIID))
|
||||||
|
*aResult = new DeleteElementTxn();
|
||||||
|
else if (aTxnType.Equals(kDeleteRangeTxnIID))
|
||||||
|
*aResult = new DeleteRangeTxn();
|
||||||
|
else if (aTxnType.Equals(kChangeAttributeTxnIID))
|
||||||
|
*aResult = new ChangeAttributeTxn();
|
||||||
|
else if (aTxnType.Equals(kSplitElementTxnIID))
|
||||||
|
*aResult = new SplitElementTxn();
|
||||||
|
else if (aTxnType.Equals(kJoinElementTxnIID))
|
||||||
|
*aResult = new JoinElementTxn();
|
||||||
|
|
||||||
|
if (nsnull==*aResult)
|
||||||
|
result = NS_ERROR_INVALID_ARG;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,16 +33,22 @@
|
||||||
#include "nsTransactionManagerCID.h"
|
#include "nsTransactionManagerCID.h"
|
||||||
#include "nsITransactionManager.h"
|
#include "nsITransactionManager.h"
|
||||||
#include "nsIPresShell.h"
|
#include "nsIPresShell.h"
|
||||||
|
#include "nsIViewManager.h"
|
||||||
#include "nsISelection.h"
|
#include "nsISelection.h"
|
||||||
|
#include "nsICollection.h"
|
||||||
|
#include "nsIEnumerator.h"
|
||||||
#include "nsIAtom.h"
|
#include "nsIAtom.h"
|
||||||
|
|
||||||
// transactions the editor knows how to build
|
// transactions the editor knows how to build
|
||||||
|
#include "TransactionFactory.h"
|
||||||
#include "ChangeAttributeTxn.h"
|
#include "ChangeAttributeTxn.h"
|
||||||
#include "CreateElementTxn.h"
|
#include "CreateElementTxn.h"
|
||||||
#include "DeleteElementTxn.h"
|
#include "DeleteElementTxn.h"
|
||||||
#include "InsertTextTxn.h"
|
#include "InsertTextTxn.h"
|
||||||
#include "DeleteTextTxn.h"
|
#include "DeleteTextTxn.h"
|
||||||
#include "DeleteRangeTxn.h"
|
#include "DeleteRangeTxn.h"
|
||||||
|
#include "SplitElementTxn.h"
|
||||||
|
#include "JoinElementTxn.h"
|
||||||
|
|
||||||
|
|
||||||
static NS_DEFINE_IID(kIDOMEventReceiverIID, NS_IDOMEVENTRECEIVER_IID);
|
static NS_DEFINE_IID(kIDOMEventReceiverIID, NS_IDOMEVENTRECEIVER_IID);
|
||||||
|
@ -58,8 +64,18 @@ static NS_DEFINE_IID(kIEditFactoryIID, NS_IEDITORFACTORY_IID);
|
||||||
static NS_DEFINE_IID(kIEditorIID, NS_IEDITOR_IID);
|
static NS_DEFINE_IID(kIEditorIID, NS_IEDITOR_IID);
|
||||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||||
static NS_DEFINE_IID(kEditorCID, NS_EDITOR_CID);
|
static NS_DEFINE_IID(kEditorCID, NS_EDITOR_CID);
|
||||||
|
// transaction manager
|
||||||
static NS_DEFINE_IID(kITransactionManagerIID, NS_ITRANSACTIONMANAGER_IID);
|
static NS_DEFINE_IID(kITransactionManagerIID, NS_ITRANSACTIONMANAGER_IID);
|
||||||
static NS_DEFINE_CID(kCTransactionManagerFactoryCID, NS_TRANSACTION_MANAGER_FACTORY_CID);
|
static NS_DEFINE_CID(kCTransactionManagerFactoryCID, NS_TRANSACTION_MANAGER_FACTORY_CID);
|
||||||
|
// transactions
|
||||||
|
static NS_DEFINE_IID(kInsertTextTxnIID, INSERT_TEXT_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kDeleteTextTxnIID, DELETE_TEXT_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kCreateElementTxnIID, CREATE_ELEMENT_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kDeleteElementTxnIID, DELETE_ELEMENT_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kDeleteRangeTxnIID, DELETE_RANGE_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kChangeAttributeTxnIID,CHANGE_ATTRIBUTE_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kSplitElementTxnIID, SPLIT_ELEMENT_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kJoinElementTxnIID, JOIN_ELEMENT_TXN_IID);
|
||||||
|
|
||||||
|
|
||||||
#ifdef XP_PC
|
#ifdef XP_PC
|
||||||
|
@ -165,6 +181,7 @@ nsEditor::nsEditor()
|
||||||
nsEditor::~nsEditor()
|
nsEditor::~nsEditor()
|
||||||
{
|
{
|
||||||
NS_IF_RELEASE(mPresShell);
|
NS_IF_RELEASE(mPresShell);
|
||||||
|
NS_IF_RELEASE(mViewManager);
|
||||||
NS_IF_RELEASE(mTxnMgr);
|
NS_IF_RELEASE(mTxnMgr);
|
||||||
|
|
||||||
//the autopointers will clear themselves up.
|
//the autopointers will clear themselves up.
|
||||||
|
@ -229,6 +246,8 @@ nsEditor::Init(nsIDOMDocument *aDomInterface, nsIPresShell* aPresShell)
|
||||||
mDomInterfaceP = aDomInterface;
|
mDomInterfaceP = aDomInterface;
|
||||||
mPresShell = aPresShell;
|
mPresShell = aPresShell;
|
||||||
NS_ADDREF(mPresShell);
|
NS_ADDREF(mPresShell);
|
||||||
|
mViewManager = mPresShell->GetViewManager();
|
||||||
|
mUpdateCount=0;
|
||||||
|
|
||||||
nsresult t_result = NS_NewEditorKeyListener(getter_AddRefs(mKeyListenerP), this);
|
nsresult t_result = NS_NewEditorKeyListener(getter_AddRefs(mKeyListenerP), this);
|
||||||
if (NS_OK != t_result)
|
if (NS_OK != t_result)
|
||||||
|
@ -308,13 +327,13 @@ nsEditor::Init(nsIDOMDocument *aDomInterface, nsIPresShell* aPresShell)
|
||||||
nsresult
|
nsresult
|
||||||
nsEditor::InsertString(nsString *aString)
|
nsEditor::InsertString(nsString *aString)
|
||||||
{
|
{
|
||||||
return AppendText(aString);
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsEditor::SetProperties(PROPERTIES aProperty)
|
nsEditor::SetProperties(Properties aProperties)
|
||||||
{
|
{
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -322,7 +341,7 @@ nsEditor::SetProperties(PROPERTIES aProperty)
|
||||||
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsEditor::GetProperties(PROPERTIES **)
|
nsEditor::GetProperties(Properties **aProperties)
|
||||||
{
|
{
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -334,9 +353,13 @@ nsEditor::SetAttribute(nsIDOMElement *aElement, const nsString& aAttribute, cons
|
||||||
nsresult result;
|
nsresult result;
|
||||||
if (nsnull != aElement)
|
if (nsnull != aElement)
|
||||||
{
|
{
|
||||||
ChangeAttributeTxn *txn = new ChangeAttributeTxn(this, aElement, aAttribute, aValue, PR_FALSE);
|
ChangeAttributeTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kChangeAttributeTxnIID, (EditTxn **)&txn);
|
||||||
if (nsnull!=txn)
|
if (nsnull!=txn)
|
||||||
result = ExecuteTransaction(txn);
|
{
|
||||||
|
txn->Init(this, aElement, aAttribute, aValue, PR_FALSE);
|
||||||
|
result = Do(txn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -369,10 +392,14 @@ nsEditor::RemoveAttribute(nsIDOMElement *aElement, const nsString& aAttribute)
|
||||||
nsresult result;
|
nsresult result;
|
||||||
if (nsnull != aElement)
|
if (nsnull != aElement)
|
||||||
{
|
{
|
||||||
nsString value;
|
ChangeAttributeTxn *txn;
|
||||||
ChangeAttributeTxn *txn = new ChangeAttributeTxn(this, aElement, aAttribute, value, PR_TRUE);
|
result = TransactionFactory::GetNewTransaction(kChangeAttributeTxnIID, (EditTxn **)&txn);
|
||||||
if (nsnull!=txn)
|
if (nsnull!=txn)
|
||||||
result = ExecuteTransaction(txn);
|
{
|
||||||
|
nsAutoString value;
|
||||||
|
txn->Init(this, aElement, aAttribute, value, PR_TRUE);
|
||||||
|
result = Do(txn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -420,26 +447,6 @@ nsEditor::MouseClick(int aX,int aY)
|
||||||
//BEGIN nsEditor Private methods
|
//BEGIN nsEditor Private methods
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
nsEditor::AppendText(nsString *aStr)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIDOMNode> currentNode;
|
|
||||||
nsCOMPtr<nsIDOMNode> textNode;
|
|
||||||
nsCOMPtr<nsIDOMText> text;
|
|
||||||
if (!aStr)
|
|
||||||
return NS_ERROR_NULL_POINTER;
|
|
||||||
if (NS_SUCCEEDED(GetCurrentNode(getter_AddRefs(currentNode))) &&
|
|
||||||
NS_SUCCEEDED(GetFirstTextNode(currentNode,getter_AddRefs(textNode))) &&
|
|
||||||
NS_SUCCEEDED(textNode->QueryInterface(kIDOMTextIID, getter_AddRefs(text)))) {
|
|
||||||
text->AppendData(*aStr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsEditor::GetCurrentNode(nsIDOMNode ** aNode)
|
nsEditor::GetCurrentNode(nsIDOMNode ** aNode)
|
||||||
{
|
{
|
||||||
|
@ -485,7 +492,7 @@ nsEditor::GetFirstNodeOfType(nsIDOMNode *aStartNode, const nsString &aTag, nsIDO
|
||||||
while (childNode)
|
while (childNode)
|
||||||
{
|
{
|
||||||
result = childNode->QueryInterface(kIDOMNodeIID,getter_AddRefs(element));
|
result = childNode->QueryInterface(kIDOMNodeIID,getter_AddRefs(element));
|
||||||
nsString tag;
|
nsAutoString tag;
|
||||||
if (NS_SUCCEEDED(result) && (element))
|
if (NS_SUCCEEDED(result) && (element))
|
||||||
{
|
{
|
||||||
element->GetTagName(tag);
|
element->GetTagName(tag);
|
||||||
|
@ -500,9 +507,8 @@ nsEditor::GetFirstNodeOfType(nsIDOMNode *aStartNode, const nsString &aTag, nsIDO
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nsCOMPtr<nsIDOMNode> xNode;
|
nsCOMPtr<nsIDOMNode> temp = childNode;
|
||||||
childNode->GetNextSibling(getter_AddRefs(xNode));
|
temp->GetNextSibling(getter_AddRefs(childNode));
|
||||||
childNode=xNode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
@ -559,7 +565,7 @@ nsEditor::GetFirstTextNode(nsIDOMNode *aNode, nsIDOMNode **aRetNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsEditor::ExecuteTransaction(nsITransaction *aTxn)
|
nsEditor::Do(nsITransaction *aTxn)
|
||||||
{
|
{
|
||||||
nsresult result = NS_OK;
|
nsresult result = NS_OK;
|
||||||
if (nsnull!=aTxn)
|
if (nsnull!=aTxn)
|
||||||
|
@ -577,27 +583,65 @@ nsEditor::ExecuteTransaction(nsITransaction *aTxn)
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsEditor::Undo()
|
nsEditor::Undo(PRUint32 aCount)
|
||||||
{
|
{
|
||||||
nsresult result = NS_OK;
|
nsresult result = NS_OK;
|
||||||
if (nsnull!=mTxnMgr)
|
if (nsnull!=mTxnMgr)
|
||||||
{
|
{
|
||||||
result = mTxnMgr->Undo();
|
PRUint32 i=0;
|
||||||
|
for ( ; i<aCount; i++)
|
||||||
|
{
|
||||||
|
result = mTxnMgr->Undo();
|
||||||
|
if (NS_FAILED(result))
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsEditor::Redo()
|
nsEditor::Redo(PRUint32 aCount)
|
||||||
{
|
{
|
||||||
nsresult result = NS_OK;
|
nsresult result = NS_OK;
|
||||||
if (nsnull!=mTxnMgr)
|
if (nsnull!=mTxnMgr)
|
||||||
{
|
{
|
||||||
result = mTxnMgr->Redo();
|
PRUint32 i=0;
|
||||||
|
for ( ; i<aCount; i++)
|
||||||
|
{
|
||||||
|
result = mTxnMgr->Redo();
|
||||||
|
if (NS_FAILED(result))
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsEditor::BeginUpdate()
|
||||||
|
{
|
||||||
|
NS_PRECONDITION(mUpdateCount>=0, "bad state");
|
||||||
|
if (nsnull!=mViewManager)
|
||||||
|
{
|
||||||
|
if (0==mUpdateCount)
|
||||||
|
mViewManager->DisableRefresh();
|
||||||
|
mUpdateCount++;
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsEditor::EndUpdate()
|
||||||
|
{
|
||||||
|
NS_PRECONDITION(mUpdateCount>0, "bad state");
|
||||||
|
if (nsnull!=mViewManager)
|
||||||
|
{
|
||||||
|
mUpdateCount--;
|
||||||
|
if (0==mUpdateCount)
|
||||||
|
mViewManager->EnableRefresh();
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult nsEditor::Delete(PRBool aForward, PRUint32 aCount)
|
nsresult nsEditor::Delete(PRBool aForward, PRUint32 aCount)
|
||||||
{
|
{
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
@ -610,9 +654,13 @@ nsresult nsEditor::CreateElement(const nsString& aTag,
|
||||||
nsresult result;
|
nsresult result;
|
||||||
if (nsnull != aParent)
|
if (nsnull != aParent)
|
||||||
{
|
{
|
||||||
CreateElementTxn *txn = new CreateElementTxn(this, mDomInterfaceP, aTag, aParent, aPosition);
|
CreateElementTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kCreateElementTxnIID, (EditTxn **)&txn);
|
||||||
if (nsnull!=txn)
|
if (nsnull!=txn)
|
||||||
result = ExecuteTransaction(txn);
|
{
|
||||||
|
txn->Init(mDomInterfaceP, aTag, aParent, aPosition);
|
||||||
|
result = Do(txn);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
result = NS_ERROR_OUT_OF_MEMORY;
|
result = NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
@ -628,9 +676,13 @@ nsresult nsEditor::DeleteElement(nsIDOMNode * aParent,
|
||||||
nsresult result;
|
nsresult result;
|
||||||
if ((nsnull != aParent) && (nsnull != aElement))
|
if ((nsnull != aParent) && (nsnull != aElement))
|
||||||
{
|
{
|
||||||
DeleteElementTxn *txn = new DeleteElementTxn(this, mDomInterfaceP, aElement, aParent);
|
DeleteElementTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kDeleteElementTxnIID, (EditTxn **)&txn);
|
||||||
if (nsnull!=txn)
|
if (nsnull!=txn)
|
||||||
result = ExecuteTransaction(txn);
|
{
|
||||||
|
txn->Init(aElement, aParent);
|
||||||
|
result = Do(txn);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
result = NS_ERROR_OUT_OF_MEMORY;
|
result = NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
@ -640,18 +692,51 @@ nsresult nsEditor::DeleteElement(nsIDOMNode * aParent,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult nsEditor::InsertText(nsIDOMCharacterData *aElement,
|
// XXX; factor -- should call BuildInsertTextTransaction to do most of the work
|
||||||
PRUint32 aOffset,
|
nsresult nsEditor::InsertText(const nsString& aStringToInsert)
|
||||||
const nsString& aStringToInsert)
|
|
||||||
{
|
{
|
||||||
nsresult result;
|
nsresult result;
|
||||||
if (nsnull != aElement)
|
nsISelection* selection;
|
||||||
|
result = mPresShell->GetSelection(&selection);
|
||||||
|
if ((NS_SUCCEEDED(result)) && (nsnull!=selection))
|
||||||
{
|
{
|
||||||
InsertTextTxn *txn = new InsertTextTxn(this, aElement, aOffset, aStringToInsert);
|
nsCOMPtr<nsIEnumerator> enumerator;
|
||||||
if (nsnull!=txn)
|
enumerator = selection;
|
||||||
result = ExecuteTransaction(txn);
|
if (enumerator)
|
||||||
else
|
{
|
||||||
result = NS_ERROR_OUT_OF_MEMORY;
|
enumerator->First();
|
||||||
|
nsISupports *currentItem;
|
||||||
|
result = enumerator->CurrentItem(¤tItem);
|
||||||
|
if ((NS_SUCCEEDED(result)) && (nsnull!=currentItem))
|
||||||
|
{
|
||||||
|
// XXX: we'll want to deleteRange if the selection isn't just an insertion point
|
||||||
|
// for now, just insert text after the start of the first node
|
||||||
|
nsCOMPtr<nsIDOMRange> range = currentItem;
|
||||||
|
if (range)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMNode> node;
|
||||||
|
result = range->GetStartParent(getter_AddRefs(node));
|
||||||
|
if ((NS_SUCCEEDED(result)) && (node))
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMCharacterData> nodeAsText = node;
|
||||||
|
if (nodeAsText)
|
||||||
|
{
|
||||||
|
PRInt32 offset;
|
||||||
|
range->GetStartOffset(&offset);
|
||||||
|
InsertTextTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kInsertTextTxnIID, (EditTxn **)&txn);
|
||||||
|
if (nsnull!=txn)
|
||||||
|
{
|
||||||
|
txn->Init(nodeAsText, offset, aStringToInsert);
|
||||||
|
result = Do(txn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
result = NS_ERROR_INVALID_ARG;
|
result = NS_ERROR_INVALID_ARG;
|
||||||
|
@ -659,6 +744,7 @@ nsresult nsEditor::InsertText(nsIDOMCharacterData *aElement,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX; factor -- should call BuildDeleteTextTransaction to do most of the work
|
||||||
nsresult nsEditor::DeleteText(nsIDOMCharacterData *aElement,
|
nsresult nsEditor::DeleteText(nsIDOMCharacterData *aElement,
|
||||||
PRUint32 aOffset,
|
PRUint32 aOffset,
|
||||||
PRUint32 aLength)
|
PRUint32 aLength)
|
||||||
|
@ -666,9 +752,13 @@ nsresult nsEditor::DeleteText(nsIDOMCharacterData *aElement,
|
||||||
nsresult result=NS_OK;
|
nsresult result=NS_OK;
|
||||||
if (nsnull != aElement)
|
if (nsnull != aElement)
|
||||||
{
|
{
|
||||||
DeleteTextTxn *txn = new DeleteTextTxn(this, aElement, aOffset, aLength);
|
DeleteTextTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kDeleteTextTxnIID, (EditTxn **)&txn);
|
||||||
if (nsnull!=txn)
|
if (nsnull!=txn)
|
||||||
result = ExecuteTransaction(txn);
|
{
|
||||||
|
txn->Init(aElement, aOffset, aLength);
|
||||||
|
result = Do(txn);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
result = NS_ERROR_OUT_OF_MEMORY;
|
result = NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
@ -678,6 +768,10 @@ nsresult nsEditor::DeleteText(nsIDOMCharacterData *aElement,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX; factor -- should call DeleteSelectionTransaction to do most of the work
|
||||||
|
// XXX: these should get wrapped up in a single composite transaction
|
||||||
|
// rather than executing each individually, maybe I should alloc a generic aggregate
|
||||||
|
// and stick each in there, then execute the aggregate
|
||||||
nsresult nsEditor::DeleteSelection()
|
nsresult nsEditor::DeleteSelection()
|
||||||
{
|
{
|
||||||
nsresult result;
|
nsresult result;
|
||||||
|
@ -685,15 +779,34 @@ nsresult nsEditor::DeleteSelection()
|
||||||
result = mPresShell->GetSelection(&selection);
|
result = mPresShell->GetSelection(&selection);
|
||||||
if ((NS_SUCCEEDED(result)) && (nsnull!=selection))
|
if ((NS_SUCCEEDED(result)) && (nsnull!=selection))
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIDOMRange> range;
|
nsCOMPtr<nsIEnumerator> enumerator;
|
||||||
result = selection->QueryInterface(kIDOMRangeIID, getter_AddRefs(range));
|
enumerator = selection;
|
||||||
if ((NS_SUCCEEDED(result)) && (range))
|
if (enumerator)
|
||||||
{
|
{
|
||||||
DeleteRangeTxn *txn = new DeleteRangeTxn(this, range);
|
enumerator->First();
|
||||||
if (nsnull!=txn)
|
nsISupports *currentItem;
|
||||||
result = ExecuteTransaction(txn);
|
result = enumerator->CurrentItem(¤tItem);
|
||||||
else
|
if ((NS_SUCCEEDED(result)) && (nsnull!=currentItem))
|
||||||
result = NS_ERROR_OUT_OF_MEMORY;
|
{
|
||||||
|
nsCOMPtr<nsIDOMRange> range = currentItem;
|
||||||
|
DeleteRangeTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kDeleteRangeTxnIID, (EditTxn **)&txn);
|
||||||
|
if (nsnull!=txn)
|
||||||
|
{
|
||||||
|
txn->Init(range);
|
||||||
|
result = Do(txn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
if (NS_SUCCEEDED(result))
|
||||||
|
{
|
||||||
|
nsresult nextResult = enumerator->Next();
|
||||||
|
if (NS_SUCCEEDED(nextResult))
|
||||||
|
{
|
||||||
|
result = enumerator->CurrentItem(¤tItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -703,30 +816,31 @@ nsresult nsEditor::DeleteSelection()
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsEditor::SplitNode(nsIDOMNode * aNode,
|
nsEditor::SplitNode(nsIDOMNode * aExistingRightNode,
|
||||||
PRInt32 aOffset,
|
PRInt32 aOffset,
|
||||||
nsIDOMNode* aNewNode,
|
nsIDOMNode* aNewLeftNode,
|
||||||
nsIDOMNode* aParent)
|
nsIDOMNode* aParent)
|
||||||
{
|
{
|
||||||
nsresult result;
|
nsresult result;
|
||||||
NS_ASSERTION(((nsnull!=aNode) &&
|
NS_ASSERTION(((nsnull!=aExistingRightNode) &&
|
||||||
(nsnull!=aNewNode) &&
|
(nsnull!=aNewLeftNode) &&
|
||||||
(nsnull!=aParent)),
|
(nsnull!=aParent)),
|
||||||
"null arg");
|
"null arg");
|
||||||
if ((nsnull!=aNode) &&
|
if ((nsnull!=aExistingRightNode) &&
|
||||||
(nsnull!=aNewNode) &&
|
(nsnull!=aNewLeftNode) &&
|
||||||
(nsnull!=aParent))
|
(nsnull!=aParent))
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIDOMNode> resultNode;
|
nsCOMPtr<nsIDOMNode> resultNode;
|
||||||
result = aParent->InsertBefore(aNewNode, aNode, getter_AddRefs(resultNode));
|
result = aParent->InsertBefore(aNewLeftNode, aExistingRightNode, getter_AddRefs(resultNode));
|
||||||
if (NS_SUCCEEDED(result))
|
if (NS_SUCCEEDED(result))
|
||||||
{
|
{
|
||||||
// split the children between the 2 nodes
|
// split the children between the 2 nodes
|
||||||
// at this point, nNode has all the children
|
// at this point, aExistingRightNode has all the children
|
||||||
|
// move all the children whose index is < aOffset to aNewLeftNode
|
||||||
if (0<=aOffset) // don't bother unless we're going to move at least one child
|
if (0<=aOffset) // don't bother unless we're going to move at least one child
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||||
result = aParent->GetChildNodes(getter_AddRefs(childNodes));
|
result = aExistingRightNode->GetChildNodes(getter_AddRefs(childNodes));
|
||||||
if ((NS_SUCCEEDED(result)) && (childNodes))
|
if ((NS_SUCCEEDED(result)) && (childNodes))
|
||||||
{
|
{
|
||||||
PRInt32 i=0;
|
PRInt32 i=0;
|
||||||
|
@ -736,10 +850,10 @@ nsEditor::SplitNode(nsIDOMNode * aNode,
|
||||||
result = childNodes->Item(i, getter_AddRefs(childNode));
|
result = childNodes->Item(i, getter_AddRefs(childNode));
|
||||||
if ((NS_SUCCEEDED(result)) && (childNode))
|
if ((NS_SUCCEEDED(result)) && (childNode))
|
||||||
{
|
{
|
||||||
result = aNode->RemoveChild(childNode, getter_AddRefs(resultNode));
|
result = aExistingRightNode->RemoveChild(childNode, getter_AddRefs(resultNode));
|
||||||
if (NS_SUCCEEDED(result))
|
if (NS_SUCCEEDED(result))
|
||||||
{
|
{
|
||||||
result = aNewNode->AppendChild(childNode, getter_AddRefs(resultNode));
|
result = aNewLeftNode->AppendChild(childNode, getter_AddRefs(resultNode));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,9 @@
|
||||||
* Reserved.
|
* Reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef __editor_h__
|
||||||
|
#define __editor_h__
|
||||||
|
|
||||||
#include "prmon.h"
|
#include "prmon.h"
|
||||||
#include "nsIEditor.h"
|
#include "nsIEditor.h"
|
||||||
#include "nsIContextLoader.h"
|
#include "nsIContextLoader.h"
|
||||||
|
@ -24,11 +27,13 @@
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "editorInterfaces.h"
|
#include "editorInterfaces.h"
|
||||||
#include "nsITransactionManager.h"
|
#include "nsITransactionManager.h"
|
||||||
|
#include "TransactionFactory.h"
|
||||||
#include "nsRepository.h"
|
#include "nsRepository.h"
|
||||||
//#include "nsISelection.h"
|
//#include "nsISelection.h"
|
||||||
|
|
||||||
class nsIDOMCharacterData;
|
class nsIDOMCharacterData;
|
||||||
class nsIPresShell;
|
class nsIPresShell;
|
||||||
|
class nsIViewManager;
|
||||||
|
|
||||||
//This is the monitor for the editor.
|
//This is the monitor for the editor.
|
||||||
PRMonitor *getEditorMonitor();
|
PRMonitor *getEditorMonitor();
|
||||||
|
@ -42,15 +47,19 @@ PRMonitor *getEditorMonitor();
|
||||||
class nsEditor : public nsIEditor
|
class nsEditor : public nsIEditor
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
nsIPresShell *mPresShell;
|
nsIPresShell *mPresShell;
|
||||||
|
nsIViewManager *mViewManager;
|
||||||
|
PRUint32 mUpdateCount;
|
||||||
nsCOMPtr<nsIDOMDocument> mDomInterfaceP;
|
nsCOMPtr<nsIDOMDocument> mDomInterfaceP;
|
||||||
nsCOMPtr<nsIDOMEventListener> mKeyListenerP;
|
nsCOMPtr<nsIDOMEventListener> mKeyListenerP;
|
||||||
nsCOMPtr<nsIDOMEventListener> mMouseListenerP;
|
nsCOMPtr<nsIDOMEventListener> mMouseListenerP;
|
||||||
// nsCOMPtr<nsISelection> mSelectionP;
|
// nsCOMPtr<nsISelection> mSelectionP;
|
||||||
//nsCOMPtr<nsITransactionManager> mTxnMgrP;
|
//nsCOMPtr<nsITransactionManager> mTxnMgrP;
|
||||||
|
|
||||||
nsITransactionManager * mTxnMgr;
|
nsITransactionManager * mTxnMgr;
|
||||||
friend PRBool NSCanUnload(void);
|
friend PRBool NSCanUnload(void);
|
||||||
static PRInt32 gInstanceCount;
|
static PRInt32 gInstanceCount;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** The default constructor. This should suffice. the setting of the interfaces is done
|
/** The default constructor. This should suffice. the setting of the interfaces is done
|
||||||
* after the construction of the editor class.
|
* after the construction of the editor class.
|
||||||
|
@ -70,9 +79,9 @@ public:
|
||||||
|
|
||||||
virtual nsresult GetDomInterface(nsIDOMDocument **aDomInterface);
|
virtual nsresult GetDomInterface(nsIDOMDocument **aDomInterface);
|
||||||
|
|
||||||
virtual nsresult SetProperties(PROPERTIES aProperty);
|
virtual nsresult SetProperties(Properties aProperties);
|
||||||
|
|
||||||
virtual nsresult GetProperties(PROPERTIES **);
|
virtual nsresult GetProperties(Properties **aProperties);
|
||||||
|
|
||||||
virtual nsresult SetAttribute(nsIDOMElement * aElement,
|
virtual nsresult SetAttribute(nsIDOMElement * aElement,
|
||||||
const nsString& aAttribute,
|
const nsString& aAttribute,
|
||||||
|
@ -85,11 +94,15 @@ public:
|
||||||
|
|
||||||
virtual nsresult RemoveAttribute(nsIDOMElement *aElement, const nsString& aAttribute);
|
virtual nsresult RemoveAttribute(nsIDOMElement *aElement, const nsString& aAttribute);
|
||||||
|
|
||||||
virtual nsresult InsertString(nsString *aString);
|
virtual nsresult Do(nsITransaction *aTxn);
|
||||||
|
|
||||||
virtual nsresult Commit(PRBool aCtrlKey);
|
virtual nsresult Undo(PRUint32 aCount);
|
||||||
|
|
||||||
|
virtual nsresult Redo(PRUint32 aCount);
|
||||||
|
|
||||||
|
virtual nsresult BeginUpdate();
|
||||||
|
|
||||||
|
virtual nsresult EndUpdate();
|
||||||
|
|
||||||
/*END nsIEditor interfaces*/
|
/*END nsIEditor interfaces*/
|
||||||
|
|
||||||
|
@ -113,12 +126,6 @@ public:
|
||||||
|
|
||||||
/*BEGIN private methods used by the implementations of the above functions*/
|
/*BEGIN private methods used by the implementations of the above functions*/
|
||||||
|
|
||||||
/** AppendText is a private method that accepts a pointer to a string
|
|
||||||
* and will append it to the current node. this will be depricated
|
|
||||||
* @param nsString *aStr is the pointer to the valid string
|
|
||||||
*/
|
|
||||||
nsresult AppendText(nsString *aStr);
|
|
||||||
|
|
||||||
/** GetCurrentNode ADDREFFS and will get the current node from selection.
|
/** GetCurrentNode ADDREFFS and will get the current node from selection.
|
||||||
* now it simply returns the first node in the dom
|
* now it simply returns the first node in the dom
|
||||||
* @param nsIDOMNode **aNode is the return location of the dom node
|
* @param nsIDOMNode **aNode is the return location of the dom node
|
||||||
|
@ -142,33 +149,6 @@ public:
|
||||||
*/
|
*/
|
||||||
nsresult GetFirstNodeOfType(nsIDOMNode *aStartNode, const nsString &aTag, nsIDOMNode **aResult);
|
nsresult GetFirstNodeOfType(nsIDOMNode *aStartNode, const nsString &aTag, nsIDOMNode **aResult);
|
||||||
|
|
||||||
/** ExecuteTransaction fires a transaction. It is provided here so
|
|
||||||
* clients need no knowledge of whether the editor has a transaction manager or not.
|
|
||||||
* If a transaction manager is present, it is used.
|
|
||||||
* Otherwise, the transaction is just executed directly.
|
|
||||||
*
|
|
||||||
* @param aTxn the transaction to execute
|
|
||||||
*/
|
|
||||||
nsresult ExecuteTransaction(nsITransaction *aTxn);
|
|
||||||
|
|
||||||
/** Undo reverses the effects of the last ExecuteTransaction operation
|
|
||||||
* It is provided here so clients need no knowledge of whether the editor has a transaction manager or not.
|
|
||||||
* If a transaction manager is present, it is told to undo and the result of
|
|
||||||
* that undo is returned.
|
|
||||||
* Otherwise, the Undo request is ignored.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
nsresult Undo();
|
|
||||||
|
|
||||||
/** Redo reverses the effects of the last Undo operation
|
|
||||||
* It is provided here so clients need no knowledge of whether the editor has a transaction manager or not.
|
|
||||||
* If a transaction manager is present, it is told to redo and the result of
|
|
||||||
* that redo is returned.
|
|
||||||
* Otherwise, the Redo request is ignored.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
nsresult Redo();
|
|
||||||
|
|
||||||
nsresult CreateElement(const nsString& aTag,
|
nsresult CreateElement(const nsString& aTag,
|
||||||
nsIDOMNode * aParent,
|
nsIDOMNode * aParent,
|
||||||
PRInt32 aPosition);
|
PRInt32 aPosition);
|
||||||
|
@ -178,17 +158,15 @@ public:
|
||||||
|
|
||||||
nsresult DeleteSelection();
|
nsresult DeleteSelection();
|
||||||
|
|
||||||
nsresult InsertText(nsIDOMCharacterData *aElement,
|
nsresult InsertText(const nsString& aStringToInsert);
|
||||||
PRUint32 aOffset,
|
|
||||||
const nsString& aStringToInsert);
|
|
||||||
|
|
||||||
nsresult DeleteText(nsIDOMCharacterData *aElement,
|
nsresult DeleteText(nsIDOMCharacterData *aElement,
|
||||||
PRUint32 aOffset,
|
PRUint32 aOffset,
|
||||||
PRUint32 aLength);
|
PRUint32 aLength);
|
||||||
|
|
||||||
static nsresult SplitNode(nsIDOMNode * aNode,
|
static nsresult SplitNode(nsIDOMNode * aExistingRightNode,
|
||||||
PRInt32 aOffset,
|
PRInt32 aOffset,
|
||||||
nsIDOMNode * aNewNode,
|
nsIDOMNode * aNewLeftNode,
|
||||||
nsIDOMNode * aParent);
|
nsIDOMNode * aParent);
|
||||||
|
|
||||||
static nsresult JoinNodes(nsIDOMNode * aNodeToKeep,
|
static nsresult JoinNodes(nsIDOMNode * aNodeToKeep,
|
||||||
|
@ -198,6 +176,10 @@ public:
|
||||||
|
|
||||||
nsresult Delete(PRBool aForward, PRUint32 aCount);
|
nsresult Delete(PRBool aForward, PRUint32 aCount);
|
||||||
|
|
||||||
|
virtual nsresult InsertString(nsString *aString);
|
||||||
|
|
||||||
|
virtual nsresult Commit(PRBool aCtrlKey);
|
||||||
|
|
||||||
/*END private methods of nsEditor*/
|
/*END private methods of nsEditor*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -207,3 +189,6 @@ factory method(s)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
nsresult NS_MakeEditorLoader(nsIContextLoader **aResult);
|
nsresult NS_MakeEditorLoader(nsIContextLoader **aResult);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -19,7 +19,6 @@
|
||||||
#include "editor.h"
|
#include "editor.h"
|
||||||
|
|
||||||
#include "CreateElementTxn.h"
|
#include "CreateElementTxn.h"
|
||||||
#include "SplitElementTxn.h"
|
|
||||||
|
|
||||||
#include "nsIDOMDocument.h"
|
#include "nsIDOMDocument.h"
|
||||||
#include "nsIDOMElement.h"
|
#include "nsIDOMElement.h"
|
||||||
|
@ -178,7 +177,7 @@ nsEditorKeyListener::KeyDown(nsIDOMEvent* aKeyEvent)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // XXX: delete the first P we find
|
{ // XXX: delete the first P we find
|
||||||
nsString pTag("P");
|
nsAutoString pTag("P");
|
||||||
nsCOMPtr<nsIDOMNode> currentNode;
|
nsCOMPtr<nsIDOMNode> currentNode;
|
||||||
nsCOMPtr<nsIDOMNode> parentNode;
|
nsCOMPtr<nsIDOMNode> parentNode;
|
||||||
nsCOMPtr<nsIDOMElement> element;
|
nsCOMPtr<nsIDOMElement> element;
|
||||||
|
@ -199,25 +198,12 @@ nsEditorKeyListener::KeyDown(nsIDOMEvent* aKeyEvent)
|
||||||
{
|
{
|
||||||
// XXX Replace with x-platform NS-virtkeycode transform.
|
// XXX Replace with x-platform NS-virtkeycode transform.
|
||||||
if (NS_OK == GetCharFromKeyCode(keyCode, isShift, & character)) {
|
if (NS_OK == GetCharFromKeyCode(keyCode, isShift, & character)) {
|
||||||
nsString key;
|
nsAutoString key;
|
||||||
key += character;
|
key += character;
|
||||||
if (!isShift) {
|
if (!isShift) {
|
||||||
key.ToLowerCase();
|
key.ToLowerCase();
|
||||||
}
|
}
|
||||||
|
mEditor->InsertText(key);
|
||||||
// XXX: for now, just grab the first text node
|
|
||||||
nsCOMPtr<nsIDOMNode> currentNode;
|
|
||||||
nsCOMPtr<nsIDOMNode> textNode;
|
|
||||||
nsCOMPtr<nsIDOMCharacterData> text;
|
|
||||||
if (NS_SUCCEEDED(mEditor->GetCurrentNode(getter_AddRefs(currentNode))) &&
|
|
||||||
NS_SUCCEEDED(mEditor->GetFirstTextNode(currentNode,getter_AddRefs(textNode))) &&
|
|
||||||
NS_SUCCEEDED(textNode->QueryInterface(kIDOMCharacterDataIID, getter_AddRefs(text))))
|
|
||||||
{
|
|
||||||
// XXX: for now, just append the text
|
|
||||||
PRUint32 offset;
|
|
||||||
text->GetLength(&offset);
|
|
||||||
mEditor->InsertText(text, offset, key);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -244,6 +230,10 @@ nsEditorKeyListener::KeyPress(nsIDOMEvent* aKeyEvent)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* these includes are for debug only. this module should never instantiate it's own transactions */
|
||||||
|
#include "SplitElementTxn.h"
|
||||||
|
#include "TransactionFactory.h"
|
||||||
|
static NS_DEFINE_IID(kSplitElementTxnIID, SPLIT_ELEMENT_TXN_IID);
|
||||||
nsresult
|
nsresult
|
||||||
nsEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aProcessed)
|
nsEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aProcessed)
|
||||||
{
|
{
|
||||||
|
@ -265,7 +255,7 @@ nsEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aProces
|
||||||
if (PR_TRUE==ctrlKey)
|
if (PR_TRUE==ctrlKey)
|
||||||
{
|
{
|
||||||
if (nsnull!=mEditor)
|
if (nsnull!=mEditor)
|
||||||
mEditor->Undo();
|
mEditor->Undo(1);
|
||||||
}
|
}
|
||||||
aProcessed=PR_TRUE;
|
aProcessed=PR_TRUE;
|
||||||
break;
|
break;
|
||||||
|
@ -275,7 +265,7 @@ nsEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aProces
|
||||||
if (PR_TRUE==ctrlKey)
|
if (PR_TRUE==ctrlKey)
|
||||||
{
|
{
|
||||||
if (nsnull!=mEditor)
|
if (nsnull!=mEditor)
|
||||||
mEditor->Redo();
|
mEditor->Redo(1);
|
||||||
}
|
}
|
||||||
aProcessed=PR_TRUE;
|
aProcessed=PR_TRUE;
|
||||||
break;
|
break;
|
||||||
|
@ -283,17 +273,27 @@ nsEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aProces
|
||||||
// hard-coded split node test: works on first <P> in the document
|
// hard-coded split node test: works on first <P> in the document
|
||||||
case nsIDOMEvent::VK_S:
|
case nsIDOMEvent::VK_S:
|
||||||
{
|
{
|
||||||
nsString pTag("P");
|
nsAutoString pTag("P");
|
||||||
nsCOMPtr<nsIDOMNode> currentNode;
|
nsCOMPtr<nsIDOMNode> currentNode;
|
||||||
nsCOMPtr<nsIDOMElement> element;
|
nsCOMPtr<nsIDOMElement> element;
|
||||||
if (NS_SUCCEEDED(mEditor->GetFirstNodeOfType(nsnull, pTag, getter_AddRefs(currentNode))))
|
if (NS_SUCCEEDED(mEditor->GetFirstNodeOfType(nsnull, pTag, getter_AddRefs(currentNode))))
|
||||||
{
|
{
|
||||||
|
nsresult result;
|
||||||
SplitElementTxn *txn;
|
SplitElementTxn *txn;
|
||||||
if (PR_FALSE==isShift) // split the element so there are 0 children in the first half
|
if (PR_FALSE==isShift) // split the element so there are 0 children in the first half
|
||||||
txn = new SplitElementTxn(mEditor, currentNode, -1);
|
{
|
||||||
|
result = TransactionFactory::GetNewTransaction(kSplitElementTxnIID, (EditTxn **)&txn);
|
||||||
|
if (txn)
|
||||||
|
txn->Init(currentNode, -1);
|
||||||
|
}
|
||||||
else // split the element so there are 2 children in the first half
|
else // split the element so there are 2 children in the first half
|
||||||
txn = new SplitElementTxn(mEditor, currentNode, 1);
|
{
|
||||||
mEditor->ExecuteTransaction(txn);
|
result = TransactionFactory::GetNewTransaction(kSplitElementTxnIID, (EditTxn **)&txn);
|
||||||
|
if (txn)
|
||||||
|
txn->Init(currentNode, 1);
|
||||||
|
}
|
||||||
|
if (txn)
|
||||||
|
mEditor->Do(txn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
aProcessed=PR_TRUE;
|
aProcessed=PR_TRUE;
|
||||||
|
@ -305,10 +305,10 @@ nsEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aProces
|
||||||
{
|
{
|
||||||
//XXX: should be from a factory
|
//XXX: should be from a factory
|
||||||
//XXX: should manage the refcount of txn
|
//XXX: should manage the refcount of txn
|
||||||
nsString attribute("width");
|
nsAutoString attribute("width");
|
||||||
nsString value("400");
|
nsAutoString value("400");
|
||||||
|
|
||||||
nsString tableTag("TABLE");
|
nsAutoString tableTag("TABLE");
|
||||||
nsCOMPtr<nsIDOMNode> currentNode;
|
nsCOMPtr<nsIDOMNode> currentNode;
|
||||||
nsCOMPtr<nsIDOMElement> element;
|
nsCOMPtr<nsIDOMElement> element;
|
||||||
if (NS_SUCCEEDED(mEditor->GetFirstNodeOfType(nsnull, tableTag, getter_AddRefs(currentNode))))
|
if (NS_SUCCEEDED(mEditor->GetFirstNodeOfType(nsnull, tableTag, getter_AddRefs(currentNode))))
|
||||||
|
@ -331,11 +331,11 @@ nsEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aProces
|
||||||
nsresult result;
|
nsresult result;
|
||||||
//XXX: should be from a factory
|
//XXX: should be from a factory
|
||||||
//XXX: should manage the refcount of txn
|
//XXX: should manage the refcount of txn
|
||||||
nsString attribute("src");
|
nsAutoString attribute("src");
|
||||||
nsString value("resource:/res/samples/raptor.jpg");
|
nsAutoString value("resource:/res/samples/raptor.jpg");
|
||||||
|
|
||||||
nsString imgTag("HR");
|
nsAutoString imgTag("HR");
|
||||||
nsString bodyTag("BODY");
|
nsAutoString bodyTag("BODY");
|
||||||
nsCOMPtr<nsIDOMNode> currentNode;
|
nsCOMPtr<nsIDOMNode> currentNode;
|
||||||
result = mEditor->GetFirstNodeOfType(nsnull, bodyTag, getter_AddRefs(currentNode));
|
result = mEditor->GetFirstNodeOfType(nsnull, bodyTag, getter_AddRefs(currentNode));
|
||||||
if (NS_SUCCEEDED(result))
|
if (NS_SUCCEEDED(result))
|
||||||
|
@ -356,7 +356,7 @@ nsEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aProces
|
||||||
{
|
{
|
||||||
ChangeAttributeTxn *txn;
|
ChangeAttributeTxn *txn;
|
||||||
txn = new ChangeAttributeTxn(mEditor, element, attribute, value, PR_FALSE);
|
txn = new ChangeAttributeTxn(mEditor, element, attribute, value, PR_FALSE);
|
||||||
mEditor->ExecuteTransaction(txn);
|
mEditor->Do(txn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
@ -523,3 +523,4 @@ NS_NewEditorMouseListener(nsIDOMEventListener ** aInstancePtrResult, nsEditor *a
|
||||||
return it->QueryInterface(kIDOMEventListenerIID, (void **) aInstancePtrResult);
|
return it->QueryInterface(kIDOMEventListenerIID, (void **) aInstancePtrResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,90 +0,0 @@
|
||||||
#!nmake
|
|
||||||
#
|
|
||||||
# The contents of this file are subject to the Netscape Public License
|
|
||||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
|
||||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
|
||||||
# http://www.mozilla.org/NPL/
|
|
||||||
#
|
|
||||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
||||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
||||||
# for the specific language governing rights and limitations under the
|
|
||||||
# NPL.
|
|
||||||
#
|
|
||||||
# The Initial Developer of this code under the NPL is Netscape
|
|
||||||
# Communications Corporation. Portions created by Netscape are
|
|
||||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
||||||
# Reserved.
|
|
||||||
|
|
||||||
DEPTH=..\..
|
|
||||||
IGNORE_MANIFEST=1
|
|
||||||
|
|
||||||
LIBRARY_NAME=ender
|
|
||||||
|
|
||||||
CPPSRCS = \
|
|
||||||
editor.cpp \
|
|
||||||
editorInterfaces.cpp \
|
|
||||||
nsEditFactory.cpp \
|
|
||||||
EditTxn.cpp \
|
|
||||||
ChangeAttributeTxn.cpp \
|
|
||||||
InsertTextTxn.cpp \
|
|
||||||
DeleteTextTxn.cpp \
|
|
||||||
CreateElementTxn.cpp \
|
|
||||||
DeleteElementTxn.cpp \
|
|
||||||
DeleteRangeTxn.cpp \
|
|
||||||
SplitElementTxn.cpp \
|
|
||||||
$(NULL)
|
|
||||||
|
|
||||||
CPP_OBJS = \
|
|
||||||
.\$(OBJDIR)\editor.obj \
|
|
||||||
.\$(OBJDIR)\nsEditFactory.obj \
|
|
||||||
.\$(OBJDIR)\editorInterfaces.obj \
|
|
||||||
.\$(OBJDIR)\EditTxn.obj \
|
|
||||||
.\$(OBJDIR)\ChangeAttributeTxn.obj \
|
|
||||||
.\$(OBJDIR)\InsertTextTxn.obj \
|
|
||||||
.\$(OBJDIR)\DeleteTextTxn.obj \
|
|
||||||
.\$(OBJDIR)\CreateElementTxn.obj \
|
|
||||||
.\$(OBJDIR)\DeleteElementTxn.obj \
|
|
||||||
.\$(OBJDIR)\DeleteRangeTxn.obj \
|
|
||||||
.\$(OBJDIR)\SplitElementTxn.obj \
|
|
||||||
$(NULL)
|
|
||||||
|
|
||||||
MODULE=editor
|
|
||||||
|
|
||||||
REQUIRES=xpcom raptor dom base
|
|
||||||
|
|
||||||
LINCS=-I$(PUBLIC)\editor \
|
|
||||||
-I$(PUBLIC)\xpcom \
|
|
||||||
-I$(PUBLIC)\raptor \
|
|
||||||
-I$(PUBLIC)\js \
|
|
||||||
-I$(PUBLIC)\txmgr \
|
|
||||||
-I$(PUBLIC)\dom
|
|
||||||
|
|
||||||
MAKE_OBJ_TYPE = DLL
|
|
||||||
DLLNAME = ender
|
|
||||||
DLL=.\$(OBJDIR)\$(DLLNAME).dll
|
|
||||||
|
|
||||||
LCFLAGS = \
|
|
||||||
$(LCFLAGS) \
|
|
||||||
$(DEFINES) \
|
|
||||||
$(NULL)
|
|
||||||
|
|
||||||
# These are the libraries we need to link with to create the dll
|
|
||||||
LLIBS= \
|
|
||||||
$(DIST)\lib\xpcom32.lib \
|
|
||||||
$(DIST)\lib\libplc21.lib \
|
|
||||||
$(DIST)\lib\raptorbase.lib \
|
|
||||||
$(LIBNSPR)
|
|
||||||
!if "$(MOZ_BITS)"=="32" && defined(MOZ_DEBUG) && defined(GLOWCODE)
|
|
||||||
LLIBS=$(LLIBS) $(GLOWDIR)\glowcode.lib
|
|
||||||
!endif
|
|
||||||
|
|
||||||
|
|
||||||
include <$(DEPTH)\config\rules.mak>
|
|
||||||
|
|
||||||
libs:: $(DLL)
|
|
||||||
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).dll $(DIST)\bin
|
|
||||||
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).lib $(DIST)\lib
|
|
||||||
|
|
||||||
clobber::
|
|
||||||
rm -f $(DIST)\bin\$(DLLNAME).dll
|
|
||||||
rm -f $(DIST)\lib\$(DLLNAME).lib
|
|
|
@ -17,23 +17,33 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ChangeAttributeTxn.h"
|
#include "ChangeAttributeTxn.h"
|
||||||
#include "editor.h"
|
|
||||||
#include "nsIDOMElement.h"
|
#include "nsIDOMElement.h"
|
||||||
|
#include "editor.h"
|
||||||
|
|
||||||
// note that aEditor is not refcounted
|
ChangeAttributeTxn::ChangeAttributeTxn()
|
||||||
ChangeAttributeTxn::ChangeAttributeTxn(nsEditor *aEditor,
|
: EditTxn()
|
||||||
nsIDOMElement *aElement,
|
|
||||||
const nsString& aAttribute,
|
|
||||||
const nsString& aValue,
|
|
||||||
PRBool aRemoveAttribute)
|
|
||||||
: EditTxn(aEditor)
|
|
||||||
{
|
{
|
||||||
mElement = aElement;
|
}
|
||||||
mAttribute = aAttribute;
|
|
||||||
mValue = aValue;
|
nsresult ChangeAttributeTxn::Init(nsIEditor *aEditor,
|
||||||
mRemoveAttribute = aRemoveAttribute;
|
nsIDOMElement *aElement,
|
||||||
mAttributeWasSet=PR_FALSE;
|
const nsString& aAttribute,
|
||||||
mUndoValue="";
|
const nsString& aValue,
|
||||||
|
PRBool aRemoveAttribute)
|
||||||
|
{
|
||||||
|
if (nsnull!=aEditor && nsnull!=aElement)
|
||||||
|
{
|
||||||
|
mEditor = aEditor;
|
||||||
|
mElement = aElement;
|
||||||
|
mAttribute = aAttribute;
|
||||||
|
mValue = aValue;
|
||||||
|
mRemoveAttribute = aRemoveAttribute;
|
||||||
|
mAttributeWasSet=PR_FALSE;
|
||||||
|
mUndoValue="";
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult ChangeAttributeTxn::Do(void)
|
nsresult ChangeAttributeTxn::Do(void)
|
||||||
|
|
|
@ -20,8 +20,14 @@
|
||||||
#define ChangeAttributeTxn_h__
|
#define ChangeAttributeTxn_h__
|
||||||
|
|
||||||
#include "EditTxn.h"
|
#include "EditTxn.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsIDOMElement.h"
|
||||||
|
#include "nsIEditor.h"
|
||||||
|
|
||||||
class nsIDOMElement;
|
#define CHANGE_ATTRIBUTE_TXN_IID \
|
||||||
|
{/* 97818860-ac48-11d2-86d8-000064657374 */ \
|
||||||
|
0x97818860, 0xac48, 0x11d2, \
|
||||||
|
{0x86, 0xd8, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A transaction that changes an attribute of a content node.
|
* A transaction that changes an attribute of a content node.
|
||||||
|
@ -31,11 +37,16 @@ class ChangeAttributeTxn : public EditTxn
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ChangeAttributeTxn(nsEditor *aEditor,
|
virtual nsresult Init(nsIEditor *aEditor,
|
||||||
nsIDOMElement *aElement,
|
nsIDOMElement *aElement,
|
||||||
const nsString& aAttribute,
|
const nsString& aAttribute,
|
||||||
const nsString& aValue,
|
const nsString& aValue,
|
||||||
PRBool aRemoveAttribute);
|
PRBool aRemoveAttribute);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ChangeAttributeTxn();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
virtual nsresult Do(void);
|
virtual nsresult Do(void);
|
||||||
|
|
||||||
|
@ -55,8 +66,11 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
/** the editor that created this transaction */
|
||||||
|
nsCOMPtr<nsIEditor> mEditor;
|
||||||
|
|
||||||
/** the element to operate upon */
|
/** the element to operate upon */
|
||||||
nsIDOMElement *mElement;
|
nsCOMPtr<nsIDOMElement> mElement;
|
||||||
|
|
||||||
/** the attribute to change */
|
/** the attribute to change */
|
||||||
nsString mAttribute;
|
nsString mAttribute;
|
||||||
|
@ -72,6 +86,8 @@ protected:
|
||||||
|
|
||||||
/** PR_TRUE if the operation is to remove mAttribute from mElement */
|
/** PR_TRUE if the operation is to remove mAttribute from mElement */
|
||||||
PRBool mRemoveAttribute;
|
PRBool mRemoveAttribute;
|
||||||
|
|
||||||
|
friend class TransactionFactory;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,52 +17,50 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "CreateElementTxn.h"
|
#include "CreateElementTxn.h"
|
||||||
#include "editor.h"
|
|
||||||
#include "nsIDOMNode.h"
|
|
||||||
#include "nsIDOMNodeList.h"
|
#include "nsIDOMNodeList.h"
|
||||||
#include "nsIDOMDocument.h"
|
|
||||||
#include "nsIDOMElement.h"
|
|
||||||
|
|
||||||
// note that aEditor is not refcounted
|
CreateElementTxn::CreateElementTxn()
|
||||||
CreateElementTxn::CreateElementTxn(nsEditor *aEditor,
|
: EditTxn()
|
||||||
nsIDOMDocument *aDoc,
|
|
||||||
const nsString& aTag,
|
|
||||||
nsIDOMNode *aParent,
|
|
||||||
PRUint32 aOffsetInParent)
|
|
||||||
: EditTxn(aEditor)
|
|
||||||
{
|
{
|
||||||
mDoc = aDoc;
|
|
||||||
NS_ADDREF(mDoc);
|
|
||||||
mTag = aTag;
|
|
||||||
mParent = aParent;
|
|
||||||
NS_ADDREF(mParent);
|
|
||||||
mOffsetInParent = aOffsetInParent;
|
|
||||||
mNewNode = nsnull;
|
|
||||||
mRefNode = nsnull;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult CreateElementTxn::Init(nsIDOMDocument *aDoc,
|
||||||
|
const nsString& aTag,
|
||||||
|
nsIDOMNode *aParent,
|
||||||
|
PRUint32 aOffsetInParent)
|
||||||
|
{
|
||||||
|
if ((nsnull!=aDoc) && (nsnull!=aParent))
|
||||||
|
{
|
||||||
|
mDoc = aDoc;
|
||||||
|
mTag = aTag;
|
||||||
|
mParent = aParent;
|
||||||
|
mOffsetInParent = aOffsetInParent;
|
||||||
|
mNewNode = nsnull;
|
||||||
|
mRefNode = nsnull;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CreateElementTxn::~CreateElementTxn()
|
CreateElementTxn::~CreateElementTxn()
|
||||||
{
|
{
|
||||||
NS_IF_RELEASE(mDoc);
|
|
||||||
NS_IF_RELEASE(mParent);
|
|
||||||
NS_IF_RELEASE(mNewNode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult CreateElementTxn::Do(void)
|
nsresult CreateElementTxn::Do(void)
|
||||||
{
|
{
|
||||||
// create a new node
|
// create a new node
|
||||||
nsresult result = mDoc->CreateElement(mTag, &mNewNode);
|
nsresult result = mDoc->CreateElement(mTag, getter_AddRefs(mNewNode));
|
||||||
NS_ASSERTION(((NS_SUCCEEDED(result)) && (nsnull!=mNewNode)), "could not create element.");
|
NS_ASSERTION(((NS_SUCCEEDED(result)) && (mNewNode)), "could not create element.");
|
||||||
|
|
||||||
if ((NS_SUCCEEDED(result)) && (nsnull!=mNewNode))
|
if ((NS_SUCCEEDED(result)) && (mNewNode))
|
||||||
{
|
{
|
||||||
// insert the new node
|
// insert the new node
|
||||||
nsIDOMNode *resultNode=nsnull;
|
nsCOMPtr<nsIDOMNode> resultNode;
|
||||||
if (CreateElementTxn::eAppend==mOffsetInParent)
|
if (CreateElementTxn::eAppend==mOffsetInParent)
|
||||||
{
|
{
|
||||||
result = mParent->AppendChild(mNewNode, &resultNode);
|
result = mParent->AppendChild(mNewNode, getter_AddRefs(resultNode));
|
||||||
if ((NS_SUCCEEDED(result)) && (nsnull!=resultNode))
|
|
||||||
NS_RELEASE(resultNode); // this object already holds a ref from CreateElement
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -70,12 +68,10 @@ nsresult CreateElementTxn::Do(void)
|
||||||
result = mParent->GetChildNodes(getter_AddRefs(childNodes));
|
result = mParent->GetChildNodes(getter_AddRefs(childNodes));
|
||||||
if ((NS_SUCCEEDED(result)) && (childNodes))
|
if ((NS_SUCCEEDED(result)) && (childNodes))
|
||||||
{
|
{
|
||||||
result = childNodes->Item(mOffsetInParent, &mRefNode);
|
result = childNodes->Item(mOffsetInParent, getter_AddRefs(mRefNode));
|
||||||
if ((NS_SUCCEEDED(result)) && (nsnull!=mRefNode))
|
if ((NS_SUCCEEDED(result)) && (mRefNode))
|
||||||
{
|
{
|
||||||
result = mParent->InsertBefore(mNewNode, mRefNode, &resultNode);
|
result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode));
|
||||||
if ((NS_SUCCEEDED(result)) && (nsnull!=resultNode))
|
|
||||||
NS_RELEASE(resultNode); // this object already holds a ref from CreateElement
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,20 +81,16 @@ nsresult CreateElementTxn::Do(void)
|
||||||
|
|
||||||
nsresult CreateElementTxn::Undo(void)
|
nsresult CreateElementTxn::Undo(void)
|
||||||
{
|
{
|
||||||
nsIDOMNode *resultNode=nsnull;
|
nsCOMPtr<nsIDOMNode> resultNode;
|
||||||
nsresult result = mParent->RemoveChild(mNewNode, &resultNode);
|
nsresult result = mParent->RemoveChild(mNewNode, getter_AddRefs(resultNode));
|
||||||
if ((NS_SUCCEEDED(result)) && (nsnull!=resultNode))
|
|
||||||
NS_RELEASE(resultNode);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult CreateElementTxn::Redo(void)
|
nsresult CreateElementTxn::Redo(void)
|
||||||
{
|
{
|
||||||
nsIDOMNode *resultNode=nsnull;
|
nsCOMPtr<nsIDOMNode> resultNode;
|
||||||
nsresult result = mParent->InsertBefore(mNewNode, mRefNode, &resultNode);
|
nsresult result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode));
|
||||||
if ((NS_SUCCEEDED(result)) && (nsnull!=resultNode))
|
return result;
|
||||||
NS_RELEASE(resultNode);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult CreateElementTxn::GetIsTransient(PRBool *aIsTransient)
|
nsresult CreateElementTxn::GetIsTransient(PRBool *aIsTransient)
|
||||||
|
|
|
@ -20,10 +20,15 @@
|
||||||
#define CreateElementTxn_h__
|
#define CreateElementTxn_h__
|
||||||
|
|
||||||
#include "EditTxn.h"
|
#include "EditTxn.h"
|
||||||
|
#include "nsIDOMDocument.h"
|
||||||
|
#include "nsIDOMNode.h"
|
||||||
|
#include "nsIDOMElement.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
|
||||||
class nsIDOMDocument;
|
#define CREATE_ELEMENT_TXN_IID \
|
||||||
class nsIDOMNode;
|
{/* 7a6393c0-ac48-11d2-86d8-000064657374 */ \
|
||||||
class nsIDOMElement;
|
0x7a6393c0, 0xac48, 0x11d2, \
|
||||||
|
{0x86, 0xd8, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A transaction that creates a new node in the content tree.
|
* A transaction that creates a new node in the content tree.
|
||||||
|
@ -34,11 +39,15 @@ public:
|
||||||
|
|
||||||
enum { eAppend=-1 };
|
enum { eAppend=-1 };
|
||||||
|
|
||||||
CreateElementTxn(nsEditor *aEditor,
|
virtual nsresult Init(nsIDOMDocument *aDoc,
|
||||||
nsIDOMDocument *aDoc,
|
const nsString& aTag,
|
||||||
const nsString& aTag,
|
nsIDOMNode *aParent,
|
||||||
nsIDOMNode *aParent,
|
PRUint32 aOffsetInParent);
|
||||||
PRUint32 aOffsetInParent);
|
|
||||||
|
private:
|
||||||
|
CreateElementTxn();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
virtual ~CreateElementTxn();
|
virtual ~CreateElementTxn();
|
||||||
|
|
||||||
|
@ -61,22 +70,24 @@ public:
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/** the document into which the new node will be inserted */
|
/** the document into which the new node will be inserted */
|
||||||
nsIDOMDocument *mDoc;
|
nsCOMPtr<nsIDOMDocument> mDoc;
|
||||||
|
|
||||||
/** the tag (mapping to object type) for the new element */
|
/** the tag (mapping to object type) for the new element */
|
||||||
nsString mTag;
|
nsString mTag;
|
||||||
|
|
||||||
/** the node into which the new node will be inserted */
|
/** the node into which the new node will be inserted */
|
||||||
nsIDOMNode *mParent;
|
nsCOMPtr<nsIDOMNode> mParent;
|
||||||
|
|
||||||
/** the index in mParent for the new node */
|
/** the index in mParent for the new node */
|
||||||
PRUint32 mOffsetInParent;
|
PRUint32 mOffsetInParent;
|
||||||
|
|
||||||
/** the new node to insert */
|
/** the new node to insert */
|
||||||
nsIDOMElement *mNewNode;
|
nsCOMPtr<nsIDOMElement> mNewNode;
|
||||||
|
|
||||||
/** the node we will insert mNewNode before. We compute this ourselves. */
|
/** the node we will insert mNewNode before. We compute this ourselves. */
|
||||||
nsIDOMNode *mRefNode;
|
nsCOMPtr<nsIDOMNode> mRefNode;
|
||||||
|
|
||||||
|
friend class TransactionFactory;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -17,30 +17,32 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "DeleteElementTxn.h"
|
#include "DeleteElementTxn.h"
|
||||||
#include "editor.h"
|
#ifdef NS_DEBUG
|
||||||
#include "nsIDOMDocument.h"
|
|
||||||
#include "nsIDOMElement.h"
|
#include "nsIDOMElement.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// note that aEditor is not refcounted
|
|
||||||
DeleteElementTxn::DeleteElementTxn(nsEditor * aEditor,
|
DeleteElementTxn::DeleteElementTxn()
|
||||||
nsIDOMDocument *aDoc,
|
: EditTxn()
|
||||||
nsIDOMNode * aElement,
|
|
||||||
nsIDOMNode * aParent)
|
|
||||||
: EditTxn(aEditor)
|
|
||||||
{
|
{
|
||||||
mDoc = aDoc;
|
|
||||||
NS_ADDREF(mDoc);
|
|
||||||
mElement = aElement;
|
|
||||||
NS_ADDREF(mElement);
|
|
||||||
mParent = aParent;
|
|
||||||
NS_ADDREF(mParent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult DeleteElementTxn::Init(nsIDOMNode *aElement,
|
||||||
|
nsIDOMNode *aParent)
|
||||||
|
{
|
||||||
|
if ((nsnull!=aElement) && (nsnull!=aParent))
|
||||||
|
{
|
||||||
|
mElement = aElement;
|
||||||
|
mParent = aParent;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DeleteElementTxn::~DeleteElementTxn()
|
DeleteElementTxn::~DeleteElementTxn()
|
||||||
{
|
{
|
||||||
NS_IF_RELEASE(mDoc);
|
|
||||||
NS_IF_RELEASE(mParent);
|
|
||||||
NS_IF_RELEASE(mElement);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult DeleteElementTxn::Do(void)
|
nsresult DeleteElementTxn::Do(void)
|
||||||
|
@ -48,11 +50,32 @@ nsresult DeleteElementTxn::Do(void)
|
||||||
if (!mParent || !mElement)
|
if (!mParent || !mElement)
|
||||||
return NS_ERROR_NULL_POINTER;
|
return NS_ERROR_NULL_POINTER;
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
|
// begin debug output
|
||||||
|
nsCOMPtr<nsIDOMElement> element=mElement;
|
||||||
|
nsAutoString elementTag="text node";
|
||||||
|
if (element)
|
||||||
|
element->GetTagName(elementTag);
|
||||||
|
nsCOMPtr<nsIDOMElement> parentElement=mParent;
|
||||||
|
nsAutoString parentElementTag="text node";
|
||||||
|
if (parentElement)
|
||||||
|
parentElement->GetTagName(parentElementTag);
|
||||||
|
char *c, *p;
|
||||||
|
c = elementTag.ToNewCString();
|
||||||
|
p = parentElementTag.ToNewCString();
|
||||||
|
if (c&&p)
|
||||||
|
{
|
||||||
|
printf("DeleteElementTxn: deleting child %s from parent %s\n", c, p);
|
||||||
|
delete [] c;
|
||||||
|
delete [] p;
|
||||||
|
}
|
||||||
|
// end debug output
|
||||||
|
// begin sanity check 1: parent-child relationship
|
||||||
nsresult testResult;
|
nsresult testResult;
|
||||||
nsCOMPtr<nsIDOMNode> parentNode;
|
nsCOMPtr<nsIDOMNode> parentNode;
|
||||||
testResult = mElement->GetParentNode(getter_AddRefs(parentNode));
|
testResult = mElement->GetParentNode(getter_AddRefs(parentNode));
|
||||||
NS_ASSERTION((NS_SUCCEEDED(testResult)), "bad mElement, couldn't get parent");
|
NS_ASSERTION((NS_SUCCEEDED(testResult)), "bad mElement, couldn't get parent");
|
||||||
NS_ASSERTION((parentNode==mParent), "bad mParent, mParent!=mElement->GetParent() ");
|
NS_ASSERTION((parentNode==mParent), "bad mParent, mParent!=mElement->GetParent() ");
|
||||||
|
// end sanity check 1.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// remember which child mElement was (by remembering which child was next)
|
// remember which child mElement was (by remembering which child was next)
|
||||||
|
|
|
@ -23,8 +23,10 @@
|
||||||
#include "nsIDOMNode.h"
|
#include "nsIDOMNode.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
|
|
||||||
class nsIDOMDocument;
|
#define DELETE_ELEMENT_TXN_IID \
|
||||||
class nsIDOMElement;
|
{/* 6fd77770-ac49-11d2-86d8-000064657374 */ \
|
||||||
|
0x6fd77770, 0xac49, 0x11d2, \
|
||||||
|
{0x86, 0xd8, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A transaction that deletes a single element
|
* A transaction that deletes a single element
|
||||||
|
@ -33,10 +35,13 @@ class DeleteElementTxn : public EditTxn
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DeleteElementTxn(nsEditor *aEditor,
|
virtual nsresult Init(nsIDOMNode *aElement,
|
||||||
nsIDOMDocument *aDoc,
|
nsIDOMNode *aParent);
|
||||||
nsIDOMNode *aElement,
|
|
||||||
nsIDOMNode *aParent);
|
private:
|
||||||
|
DeleteElementTxn();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
virtual ~DeleteElementTxn();
|
virtual ~DeleteElementTxn();
|
||||||
|
|
||||||
|
@ -58,14 +63,11 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/** the document into which the new node will be inserted */
|
|
||||||
nsIDOMDocument *mDoc;
|
|
||||||
|
|
||||||
/** the element to delete */
|
/** the element to delete */
|
||||||
nsIDOMNode *mElement;
|
nsCOMPtr<nsIDOMNode> mElement;
|
||||||
|
|
||||||
/** the node into which the new node will be inserted */
|
/** the node into which the new node will be inserted */
|
||||||
nsIDOMNode *mParent;
|
nsCOMPtr<nsIDOMNode> mParent;
|
||||||
|
|
||||||
/** the index in mParent for the new node */
|
/** the index in mParent for the new node */
|
||||||
PRUint32 mOffsetInParent;
|
PRUint32 mOffsetInParent;
|
||||||
|
@ -73,6 +75,8 @@ protected:
|
||||||
/** the node we will insert mNewNode before. We compute this ourselves. */
|
/** the node we will insert mNewNode before. We compute this ourselves. */
|
||||||
nsCOMPtr<nsIDOMNode> mRefNode;
|
nsCOMPtr<nsIDOMNode> mRefNode;
|
||||||
|
|
||||||
|
friend class TransactionFactory;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,18 +17,73 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "DeleteRangeTxn.h"
|
#include "DeleteRangeTxn.h"
|
||||||
#include "editor.h"
|
|
||||||
#include "nsIDOMRange.h"
|
#include "nsIDOMRange.h"
|
||||||
|
#include "nsIDOMCharacterData.h"
|
||||||
|
#include "nsIDOMNodeList.h"
|
||||||
|
#include "DeleteTextTxn.h"
|
||||||
|
#include "DeleteElementTxn.h"
|
||||||
|
#include "TransactionFactory.h"
|
||||||
|
#include "nsISupportsArray.h"
|
||||||
|
|
||||||
|
static NS_DEFINE_IID(kDeleteTextTxnIID, DELETE_TEXT_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kDeleteElementTxnIID, DELETE_ELEMENT_TXN_IID);
|
||||||
|
|
||||||
|
|
||||||
// note that aEditor is not refcounted
|
// note that aEditor is not refcounted
|
||||||
DeleteRangeTxn::DeleteRangeTxn(nsEditor *aEditor,
|
DeleteRangeTxn::DeleteRangeTxn()
|
||||||
nsIDOMRange *aRange)
|
: EditAggregateTxn()
|
||||||
: EditTxn(aEditor)
|
|
||||||
{
|
{
|
||||||
aRange->GetStartParent(getter_AddRefs(mStartParent));
|
}
|
||||||
aRange->GetEndParent(getter_AddRefs(mEndParent));
|
|
||||||
aRange->GetStartOffset(&mStartOffset);
|
nsresult DeleteRangeTxn::Init(nsIDOMRange *aRange)
|
||||||
aRange->GetEndOffset(&mEndOffset);
|
{
|
||||||
|
if (nsnull!=aRange)
|
||||||
|
{
|
||||||
|
nsresult result = aRange->GetStartParent(getter_AddRefs(mStartParent));
|
||||||
|
NS_ASSERTION((NS_SUCCEEDED(result)), "GetStartParent failed.");
|
||||||
|
result = aRange->GetEndParent(getter_AddRefs(mEndParent));
|
||||||
|
NS_ASSERTION((NS_SUCCEEDED(result)), "GetEndParent failed.");
|
||||||
|
result = aRange->GetStartOffset(&mStartOffset);
|
||||||
|
NS_ASSERTION((NS_SUCCEEDED(result)), "GetStartOffset failed.");
|
||||||
|
result = aRange->GetEndOffset(&mEndOffset);
|
||||||
|
NS_ASSERTION((NS_SUCCEEDED(result)), "GetEndOffset failed.");
|
||||||
|
result = aRange->GetCommonParent(getter_AddRefs(mCommonParent));
|
||||||
|
NS_ASSERTION((NS_SUCCEEDED(result)), "GetCommonParent failed.");
|
||||||
|
|
||||||
|
#ifdef NS_DEBUG
|
||||||
|
PRUint32 count;
|
||||||
|
nsCOMPtr<nsIDOMCharacterData> textNode;
|
||||||
|
textNode = mStartParent;
|
||||||
|
if (textNode)
|
||||||
|
textNode->GetLength(&count);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMNodeList> children;
|
||||||
|
result = mStartParent->GetChildNodes(getter_AddRefs(children));
|
||||||
|
NS_ASSERTION(((NS_SUCCEEDED(result)) && children), "bad start child list");
|
||||||
|
children->GetLength(&count);
|
||||||
|
}
|
||||||
|
NS_ASSERTION(mStartOffset<count, "bad start offset");
|
||||||
|
|
||||||
|
textNode = mEndParent;
|
||||||
|
if (textNode)
|
||||||
|
textNode->GetLength(&count);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMNodeList> children;
|
||||||
|
result = mEndParent->GetChildNodes(getter_AddRefs(children));
|
||||||
|
NS_ASSERTION(((NS_SUCCEEDED(result)) && children), "bad end child list");
|
||||||
|
children->GetLength(&count);
|
||||||
|
}
|
||||||
|
NS_ASSERTION(mEndOffset<count, "bad end offset");
|
||||||
|
|
||||||
|
printf ("DeleteRange: %d of %p to %d of %p\n",
|
||||||
|
mStartOffset, (void *)mStartParent, mEndOffset, (void *)mEndParent);
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
DeleteRangeTxn::~DeleteRangeTxn()
|
DeleteRangeTxn::~DeleteRangeTxn()
|
||||||
|
@ -37,28 +92,59 @@ DeleteRangeTxn::~DeleteRangeTxn()
|
||||||
|
|
||||||
nsresult DeleteRangeTxn::Do(void)
|
nsresult DeleteRangeTxn::Do(void)
|
||||||
{
|
{
|
||||||
if (!mStartParent || !mEndParent)
|
if (!mStartParent || !mEndParent || !mCommonParent)
|
||||||
return NS_ERROR_NULL_POINTER;
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
|
||||||
nsresult result;
|
nsresult result;
|
||||||
|
|
||||||
|
// build the child transactions
|
||||||
|
|
||||||
|
if (mStartParent==mEndParent)
|
||||||
|
{ // the selection begins and ends in the same node
|
||||||
|
result = CreateTxnsToDeleteBetween(mStartParent, mStartOffset, mEndOffset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // the selection ends in a different node from where it started
|
||||||
|
// delete the relevant content in the start node
|
||||||
|
result = CreateTxnsToDeleteContent(mStartParent, mStartOffset, nsIEditor::eLTR);
|
||||||
|
if (NS_SUCCEEDED(result))
|
||||||
|
{
|
||||||
|
// delete the intervening nodes
|
||||||
|
result = CreateTxnsToDeleteNodesBetween(mCommonParent, mStartParent, mEndParent);
|
||||||
|
if (NS_SUCCEEDED(result))
|
||||||
|
{
|
||||||
|
// delete the relevant content in the end node
|
||||||
|
result = CreateTxnsToDeleteContent(mEndParent, mEndOffset, nsIEditor::eRTL);
|
||||||
|
if (NS_SUCCEEDED(result))
|
||||||
|
{ // now we have all our child transactions, do them
|
||||||
|
result = EditAggregateTxn::Do();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we've successfully built this aggregate transaction, then do it.
|
||||||
|
if (NS_SUCCEEDED(result))
|
||||||
|
result = EditAggregateTxn::Do();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult DeleteRangeTxn::Undo(void)
|
nsresult DeleteRangeTxn::Undo(void)
|
||||||
{
|
{
|
||||||
if (!mStartParent || !mEndParent)
|
if (!mStartParent || !mEndParent || !mCommonParent)
|
||||||
return NS_ERROR_NULL_POINTER;
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
|
||||||
nsresult result;
|
nsresult result = EditAggregateTxn::Undo();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult DeleteRangeTxn::Redo(void)
|
nsresult DeleteRangeTxn::Redo(void)
|
||||||
{
|
{
|
||||||
if (!mStartParent || !mEndParent)
|
if (!mStartParent || !mEndParent || !mCommonParent)
|
||||||
return NS_ERROR_NULL_POINTER;
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
|
||||||
nsresult result;
|
nsresult result = EditAggregateTxn::Redo();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,3 +184,265 @@ nsresult DeleteRangeTxn::GetRedoString(nsString **aString)
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult DeleteRangeTxn::CreateTxnsToDeleteBetween(nsIDOMNode *aStartParent,
|
||||||
|
PRUint32 aStartOffset,
|
||||||
|
PRUint32 aEndOffset)
|
||||||
|
{
|
||||||
|
nsresult result;
|
||||||
|
// see what kind of node we have
|
||||||
|
nsCOMPtr<nsIDOMCharacterData> textNode;
|
||||||
|
textNode = aStartParent; // this uses implicit nsCOMPtr QI
|
||||||
|
if (textNode)
|
||||||
|
{ // if the node is a text node, then delete text content
|
||||||
|
DeleteTextTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kDeleteTextTxnIID, (EditTxn **)&txn);
|
||||||
|
if (nsnull!=txn)
|
||||||
|
{
|
||||||
|
txn->Init(textNode, aStartOffset, (aEndOffset-aStartOffset)+1);
|
||||||
|
AppendChild(txn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PRUint32 childCount;
|
||||||
|
nsCOMPtr<nsIDOMNodeList> children;
|
||||||
|
result = aStartParent->GetChildNodes(getter_AddRefs(children));
|
||||||
|
if ((NS_SUCCEEDED(result)) && children)
|
||||||
|
{
|
||||||
|
children->GetLength(&childCount);
|
||||||
|
NS_ASSERTION(aEndOffset<childCount, "bad aEndOffset");
|
||||||
|
PRUint32 i;
|
||||||
|
for (i=aStartOffset; i<=aEndOffset; i++)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMNode> child;
|
||||||
|
result = children->Item(i, getter_AddRefs(child));
|
||||||
|
if ((NS_SUCCEEDED(result)) && child)
|
||||||
|
{
|
||||||
|
DeleteElementTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kDeleteElementTxnIID, (EditTxn **)&txn);
|
||||||
|
if (nsnull!=txn)
|
||||||
|
{
|
||||||
|
txn->Init(child, aStartParent);
|
||||||
|
AppendChild(txn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult DeleteRangeTxn::CreateTxnsToDeleteContent(nsIDOMNode *aParent,
|
||||||
|
PRUint32 aOffset,
|
||||||
|
nsIEditor::Direction aDir)
|
||||||
|
{
|
||||||
|
nsresult result;
|
||||||
|
// see what kind of node we have
|
||||||
|
nsCOMPtr<nsIDOMCharacterData> textNode;
|
||||||
|
textNode = aParent; // this uses implicit nsCOMPtr QI
|
||||||
|
if (textNode)
|
||||||
|
{ // if the node is a text node, then delete text content
|
||||||
|
PRUint32 start, numToDelete;
|
||||||
|
if (nsIEditor::eLTR==aDir)
|
||||||
|
{
|
||||||
|
start=aOffset;
|
||||||
|
textNode->GetLength(&numToDelete);
|
||||||
|
numToDelete -= (aOffset+1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
start=0;
|
||||||
|
numToDelete=aOffset;
|
||||||
|
}
|
||||||
|
DeleteTextTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kDeleteTextTxnIID, (EditTxn **)&txn);
|
||||||
|
if (nsnull!=txn)
|
||||||
|
{
|
||||||
|
txn->Init(textNode, start, numToDelete);
|
||||||
|
AppendChild(txn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // we have an interior node, so delete some of its children
|
||||||
|
if (nsIEditor::eLTR==aDir)
|
||||||
|
{ // delete from aOffset to end
|
||||||
|
PRUint32 childCount;
|
||||||
|
nsCOMPtr<nsIDOMNodeList> children;
|
||||||
|
result = aParent->GetChildNodes(getter_AddRefs(children));
|
||||||
|
if ((NS_SUCCEEDED(result)) && children)
|
||||||
|
{
|
||||||
|
children->GetLength(&childCount);
|
||||||
|
PRUint32 i;
|
||||||
|
for (i=aOffset; i<childCount; i++)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMNode> child;
|
||||||
|
result = children->Item(i, getter_AddRefs(child));
|
||||||
|
if ((NS_SUCCEEDED(result)) && child)
|
||||||
|
{
|
||||||
|
DeleteElementTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kDeleteElementTxnIID, (EditTxn **)&txn);
|
||||||
|
if (nsnull!=txn)
|
||||||
|
{
|
||||||
|
txn->Init(child, aParent);
|
||||||
|
AppendChild(txn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // delete from 0 to aOffset
|
||||||
|
nsCOMPtr<nsIDOMNode> child;
|
||||||
|
result = aParent->GetFirstChild(getter_AddRefs(child));
|
||||||
|
for (PRUint32 i=0; i<aOffset; i++)
|
||||||
|
{
|
||||||
|
if ((NS_SUCCEEDED(result)) && child)
|
||||||
|
{
|
||||||
|
DeleteElementTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kDeleteElementTxnIID, (EditTxn **)&txn);
|
||||||
|
if (nsnull!=txn)
|
||||||
|
{
|
||||||
|
txn->Init(child, aParent);
|
||||||
|
AppendChild(txn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
nsCOMPtr<nsIDOMNode> temp = child;
|
||||||
|
result = temp->GetNextSibling(getter_AddRefs(child));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult DeleteRangeTxn::CreateTxnsToDeleteNodesBetween(nsIDOMNode *aCommonParent,
|
||||||
|
nsIDOMNode *aFirstChild,
|
||||||
|
nsIDOMNode *aLastChild)
|
||||||
|
{
|
||||||
|
nsresult result;
|
||||||
|
PRBool needToProcessLastChild=PR_TRUE; // set to false if we discover we can delete all required nodes by just walking up aFirstChild's parent list
|
||||||
|
nsCOMPtr<nsIDOMNode> parent; // the current parent in the iteration up the ancestors
|
||||||
|
nsCOMPtr<nsIDOMNode> child; // the current child of parent
|
||||||
|
nsISupportsArray *ancestorList; // the ancestorList of the other endpoint, used to gate deletion
|
||||||
|
NS_NewISupportsArray(&ancestorList);
|
||||||
|
if (nsnull==ancestorList)
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
|
||||||
|
// Walk up the parent list of aFirstChild to aCommonParent,
|
||||||
|
// deleting all siblings to the right of the ancestors of aFirstChild.
|
||||||
|
BuildAncestorList(aLastChild, ancestorList);
|
||||||
|
child = aFirstChild;
|
||||||
|
result = child->GetParentNode(getter_AddRefs(parent));
|
||||||
|
while ((NS_SUCCEEDED(result)) && parent)
|
||||||
|
{
|
||||||
|
while ((NS_SUCCEEDED(result)) && child)
|
||||||
|
{ // this loop starts with the first sibling of an ancestor of aFirstChild
|
||||||
|
nsCOMPtr<nsIDOMNode> temp = child;
|
||||||
|
result = temp->GetNextSibling(getter_AddRefs(child));
|
||||||
|
if ((NS_SUCCEEDED(result)) && child)
|
||||||
|
{
|
||||||
|
if (child==aLastChild)
|
||||||
|
{ // aFirstChild and aLastChild have the same parent, and we've reached aLastChild
|
||||||
|
needToProcessLastChild = PR_FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// test if child is an ancestor of the other node. If it is, don't process this parent anymore
|
||||||
|
PRInt32 index;
|
||||||
|
index = ancestorList->IndexOf((nsISupports*)child);
|
||||||
|
if (-1!=index)
|
||||||
|
break;
|
||||||
|
DeleteElementTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kDeleteElementTxnIID, (EditTxn **)&txn);
|
||||||
|
if (nsnull!=txn)
|
||||||
|
{
|
||||||
|
txn->Init(child, parent);
|
||||||
|
AppendChild(txn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (parent==aCommonParent)
|
||||||
|
break;
|
||||||
|
child = parent;
|
||||||
|
nsCOMPtr<nsIDOMNode> temp=parent;
|
||||||
|
result = temp->GetParentNode(getter_AddRefs(parent));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk up the parent list of aLastChild to aCommonParent,
|
||||||
|
// deleting all siblings to the left of the ancestors of aLastChild.
|
||||||
|
BuildAncestorList(aFirstChild, ancestorList);
|
||||||
|
if (PR_TRUE==needToProcessLastChild)
|
||||||
|
{
|
||||||
|
child = aLastChild;
|
||||||
|
result = child->GetParentNode(getter_AddRefs(parent));
|
||||||
|
while ((NS_SUCCEEDED(result)) && parent)
|
||||||
|
{
|
||||||
|
while ((NS_SUCCEEDED(result)) && child)
|
||||||
|
{ // this loop starts with the first sibling of an ancestor of aFirstChild
|
||||||
|
nsCOMPtr<nsIDOMNode> temp = child;
|
||||||
|
result = temp->GetPreviousSibling(getter_AddRefs(child));
|
||||||
|
if ((NS_SUCCEEDED(result)) && child)
|
||||||
|
{
|
||||||
|
// test if child is an ancestor of the other node. If it is, don't process this parent anymore
|
||||||
|
PRInt32 index;
|
||||||
|
index = ancestorList->IndexOf((nsISupports*)child);
|
||||||
|
if (-1!=index)
|
||||||
|
break;
|
||||||
|
DeleteElementTxn *txn;
|
||||||
|
result = TransactionFactory::GetNewTransaction(kDeleteElementTxnIID, (EditTxn **)&txn);
|
||||||
|
if (nsnull!=txn)
|
||||||
|
{
|
||||||
|
txn->Init(child, parent);
|
||||||
|
AppendChild(txn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (parent==aCommonParent)
|
||||||
|
break;
|
||||||
|
child = parent;
|
||||||
|
nsCOMPtr<nsIDOMNode> temp=parent;
|
||||||
|
result = temp->GetParentNode(getter_AddRefs(parent));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NS_RELEASE(ancestorList);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult DeleteRangeTxn::BuildAncestorList(nsIDOMNode *aNode, nsISupportsArray *aList)
|
||||||
|
{
|
||||||
|
nsresult result=NS_OK;
|
||||||
|
if (nsnull!=aNode && nsnull!=aList)
|
||||||
|
{
|
||||||
|
aList->Clear();
|
||||||
|
nsCOMPtr<nsIDOMNode> parent;
|
||||||
|
nsCOMPtr<nsIDOMNode> child = aNode;
|
||||||
|
result = child->GetParentNode(getter_AddRefs(parent));
|
||||||
|
while ((NS_SUCCEEDED(result)) && child && parent)
|
||||||
|
{
|
||||||
|
nsISupports * parentAsISupports;
|
||||||
|
parent->QueryInterface(nsISupports::IID(), (void **)&parentAsISupports);
|
||||||
|
aList->AppendElement(parentAsISupports);
|
||||||
|
child = parent;
|
||||||
|
nsCOMPtr<nsIDOMNode> temp=parent;
|
||||||
|
result = temp->GetParentNode(getter_AddRefs(parent));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = NS_ERROR_NULL_POINTER;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -19,22 +19,33 @@
|
||||||
#ifndef DeleteRangeTxn_h__
|
#ifndef DeleteRangeTxn_h__
|
||||||
#define DeleteRangeTxn_h__
|
#define DeleteRangeTxn_h__
|
||||||
|
|
||||||
#include "EditTxn.h"
|
#include "EditAggregateTxn.h"
|
||||||
#include "nsIDOMNode.h"
|
#include "nsIDOMNode.h"
|
||||||
|
#include "nsIEditor.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
|
|
||||||
class nsIDOMDocument;
|
class nsIDOMDocument;
|
||||||
class nsIDOMRange;
|
class nsIDOMRange;
|
||||||
|
class nsISupportsArray;
|
||||||
|
|
||||||
|
#define DELETE_RANGE_TXN_IID \
|
||||||
|
{/* 5ec6b260-ac49-11d2-86d8-000064657374 */ \
|
||||||
|
0x5ec6b260, 0xac49, 0x11d2, \
|
||||||
|
{0x86, 0xd8, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A transaction that deletes an entire range in the content tree
|
* A transaction that deletes an entire range in the content tree
|
||||||
*/
|
*/
|
||||||
class DeleteRangeTxn : public EditTxn
|
class DeleteRangeTxn : public EditAggregateTxn
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DeleteRangeTxn(nsEditor *aEditor,
|
virtual nsresult Init(nsIDOMRange *aRange);
|
||||||
nsIDOMRange *aRange);
|
|
||||||
|
private:
|
||||||
|
DeleteRangeTxn();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
virtual ~DeleteRangeTxn();
|
virtual ~DeleteRangeTxn();
|
||||||
|
|
||||||
|
@ -54,6 +65,23 @@ public:
|
||||||
|
|
||||||
virtual nsresult GetRedoString(nsString **aString);
|
virtual nsresult GetRedoString(nsString **aString);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual nsresult CreateTxnsToDeleteBetween(nsIDOMNode *aStartParent,
|
||||||
|
PRUint32 aStartOffset,
|
||||||
|
PRUint32 aEndOffset);
|
||||||
|
|
||||||
|
virtual nsresult CreateTxnsToDeleteNodesBetween(nsIDOMNode *aParent,
|
||||||
|
nsIDOMNode *aFirstChild,
|
||||||
|
nsIDOMNode *aLastChild);
|
||||||
|
|
||||||
|
virtual nsresult CreateTxnsToDeleteContent(nsIDOMNode *aParent,
|
||||||
|
PRUint32 aOffset,
|
||||||
|
nsIEditor::Direction aDir);
|
||||||
|
|
||||||
|
virtual nsresult BuildAncestorList(nsIDOMNode *aNode,
|
||||||
|
nsISupportsArray *aList);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/** p1 in the range */
|
/** p1 in the range */
|
||||||
|
@ -65,9 +93,14 @@ protected:
|
||||||
/** p2 in the range */
|
/** p2 in the range */
|
||||||
nsCOMPtr<nsIDOMNode> mEndParent;
|
nsCOMPtr<nsIDOMNode> mEndParent;
|
||||||
|
|
||||||
|
/** the closest common parent of p1 and p2 */
|
||||||
|
nsCOMPtr<nsIDOMNode> mCommonParent;
|
||||||
|
|
||||||
/** p2 offset */
|
/** p2 offset */
|
||||||
PRInt32 mEndOffset;
|
PRInt32 mEndOffset;
|
||||||
|
|
||||||
|
friend class TransactionFactory;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,20 +17,23 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "DeleteTextTxn.h"
|
#include "DeleteTextTxn.h"
|
||||||
#include "editor.h"
|
|
||||||
#include "nsIDOMCharacterData.h"
|
#include "nsIDOMCharacterData.h"
|
||||||
|
|
||||||
// note that aEditor is not refcounted
|
|
||||||
DeleteTextTxn::DeleteTextTxn(nsEditor *aEditor,
|
DeleteTextTxn::DeleteTextTxn()
|
||||||
nsIDOMCharacterData *aElement,
|
: EditTxn()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult DeleteTextTxn::Init(nsIDOMCharacterData *aElement,
|
||||||
PRUint32 aOffset,
|
PRUint32 aOffset,
|
||||||
PRUint32 aNumCharsToDelete)
|
PRUint32 aNumCharsToDelete)
|
||||||
: EditTxn(aEditor)
|
|
||||||
{
|
{
|
||||||
mElement = aElement;
|
mElement = aElement;
|
||||||
mOffset = aOffset;
|
mOffset = aOffset;
|
||||||
mNumCharsToDelete = aNumCharsToDelete;
|
mNumCharsToDelete = aNumCharsToDelete;
|
||||||
mDeletedText = "";
|
mDeletedText = "";
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult DeleteTextTxn::Do(void)
|
nsresult DeleteTextTxn::Do(void)
|
||||||
|
|
|
@ -20,8 +20,13 @@
|
||||||
#define DeleteTextTxn_h__
|
#define DeleteTextTxn_h__
|
||||||
|
|
||||||
#include "EditTxn.h"
|
#include "EditTxn.h"
|
||||||
|
#include "nsIDOMCharacterData.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
|
||||||
class nsIDOMCharacterData;
|
#define DELETE_TEXT_TXN_IID \
|
||||||
|
{/* 4d3a2720-ac49-11d2-86d8-000064657374 */ \
|
||||||
|
0x4d3a2720, 0xac49, 0x11d2, \
|
||||||
|
{0x86, 0xd8, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A transaction that changes an attribute of a content node.
|
* A transaction that changes an attribute of a content node.
|
||||||
|
@ -31,10 +36,14 @@ class DeleteTextTxn : public EditTxn
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DeleteTextTxn(nsEditor *aEditor,
|
virtual nsresult Init(nsIDOMCharacterData *aElement,
|
||||||
nsIDOMCharacterData *aElement,
|
PRUint32 aOffset,
|
||||||
PRUint32 aOffset,
|
PRUint32 aNumCharsToDelete);
|
||||||
PRUint32 aNumCharsToDelete);
|
|
||||||
|
private:
|
||||||
|
DeleteTextTxn();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
virtual nsresult Do(void);
|
virtual nsresult Do(void);
|
||||||
|
|
||||||
|
@ -53,7 +62,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/** the text element to operate upon */
|
/** the text element to operate upon */
|
||||||
nsIDOMCharacterData *mElement;
|
nsCOMPtr<nsIDOMCharacterData> mElement;
|
||||||
|
|
||||||
/** the offset into mElement where the deletion is to take place */
|
/** the offset into mElement where the deletion is to take place */
|
||||||
PRUint32 mOffset;
|
PRUint32 mOffset;
|
||||||
|
@ -64,6 +73,8 @@ protected:
|
||||||
/** the text that was deleted */
|
/** the text that was deleted */
|
||||||
nsString mDeletedText;
|
nsString mDeletedText;
|
||||||
|
|
||||||
|
friend class TransactionFactory;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,145 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public License
|
||||||
|
* Version 1.0 (the "NPL") you may not use this file except in
|
||||||
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||||
|
* http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* NPL.
|
||||||
|
*
|
||||||
|
* The Initial Developer of this code under the NPL is Netscape
|
||||||
|
* Communications Corporation. Portions created by Netscape are
|
||||||
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||||
|
* Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "EditAggregateTxn.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsIDOMNode.h"
|
||||||
|
#include "nsVoidArray.h"
|
||||||
|
|
||||||
|
EditAggregateTxn::EditAggregateTxn()
|
||||||
|
: EditTxn()
|
||||||
|
{
|
||||||
|
mChildren = new nsVoidArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
EditAggregateTxn::~EditAggregateTxn()
|
||||||
|
{
|
||||||
|
if (nsnull!=mChildren)
|
||||||
|
{
|
||||||
|
PRInt32 i;
|
||||||
|
PRInt32 count = mChildren->Count();
|
||||||
|
for (i=0; i<count; i++)
|
||||||
|
{
|
||||||
|
EditTxn *txn = (EditTxn*)(mChildren->ElementAt(i));
|
||||||
|
NS_IF_RELEASE(txn);
|
||||||
|
}
|
||||||
|
delete mChildren;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult EditAggregateTxn::Do(void)
|
||||||
|
{
|
||||||
|
nsresult result=NS_OK; // it's legal (but not very useful) to have an empty child list
|
||||||
|
if (nsnull!=mChildren)
|
||||||
|
{
|
||||||
|
PRInt32 i;
|
||||||
|
PRInt32 count = mChildren->Count();
|
||||||
|
for (i=0; i<count; i++)
|
||||||
|
{
|
||||||
|
EditTxn *txn = (EditTxn*)(mChildren->ElementAt(i));
|
||||||
|
result = txn->Do();
|
||||||
|
if (NS_FAILED(result))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult EditAggregateTxn::Undo(void)
|
||||||
|
{
|
||||||
|
nsresult result=NS_OK; // it's legal (but not very useful) to have an empty child list
|
||||||
|
if (nsnull!=mChildren)
|
||||||
|
{
|
||||||
|
PRInt32 i;
|
||||||
|
PRInt32 count = mChildren->Count();
|
||||||
|
// undo goes through children backwards
|
||||||
|
for (i=count-1; i>=0; i--)
|
||||||
|
{
|
||||||
|
EditTxn *txn = (EditTxn*)(mChildren->ElementAt(i));
|
||||||
|
result = txn->Undo();
|
||||||
|
if (NS_FAILED(result))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult EditAggregateTxn::Redo(void)
|
||||||
|
{
|
||||||
|
nsresult result=NS_OK; // it's legal (but not very useful) to have an empty child list
|
||||||
|
if (nsnull!=mChildren)
|
||||||
|
{
|
||||||
|
PRInt32 i;
|
||||||
|
PRInt32 count = mChildren->Count();
|
||||||
|
for (i=0; i<count; i++)
|
||||||
|
{
|
||||||
|
EditTxn *txn = (EditTxn*)(mChildren->ElementAt(i));
|
||||||
|
result = txn->Redo();
|
||||||
|
if (NS_FAILED(result))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult EditAggregateTxn::GetIsTransient(PRBool *aIsTransient)
|
||||||
|
{
|
||||||
|
if (nsnull!=aIsTransient)
|
||||||
|
*aIsTransient = PR_TRUE;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult EditAggregateTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
|
||||||
|
{
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult EditAggregateTxn::Write(nsIOutputStream *aOutputStream)
|
||||||
|
{
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult EditAggregateTxn::GetUndoString(nsString **aString)
|
||||||
|
{
|
||||||
|
if (nsnull!=aString)
|
||||||
|
*aString=nsnull;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult EditAggregateTxn::GetRedoString(nsString **aString)
|
||||||
|
{
|
||||||
|
if (nsnull!=aString)
|
||||||
|
*aString=nsnull;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult EditAggregateTxn::AppendChild(EditTxn *aTxn)
|
||||||
|
{
|
||||||
|
if ((nsnull!=mChildren) && (nsnull!=aTxn))
|
||||||
|
{
|
||||||
|
mChildren->AppendElement(aTxn);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public License
|
||||||
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||||
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||||
|
* http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* NPL.
|
||||||
|
*
|
||||||
|
* The Initial Developer of this code under the NPL is Netscape
|
||||||
|
* Communications Corporation. Portions created by Netscape are
|
||||||
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||||
|
* Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EditAggregateTxn_h__
|
||||||
|
#define EditAggregateTxn_h__
|
||||||
|
|
||||||
|
#include "EditTxn.h"
|
||||||
|
|
||||||
|
#define EDIT_AGGREGATE_TXN_IID \
|
||||||
|
{/* 345921a0-ac49-11d2-86d8-000064657374 */ \
|
||||||
|
0x345921a0, 0xac49, 0x11d2, \
|
||||||
|
{0x86, 0xd8, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
|
||||||
|
|
||||||
|
class nsVoidArray;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* base class for all document editing transactions that require aggregation.
|
||||||
|
* provides a list of child transactions.
|
||||||
|
*/
|
||||||
|
class EditAggregateTxn : public EditTxn
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
EditAggregateTxn();
|
||||||
|
|
||||||
|
virtual ~EditAggregateTxn();
|
||||||
|
|
||||||
|
virtual nsresult Do(void);
|
||||||
|
|
||||||
|
virtual nsresult Undo(void);
|
||||||
|
|
||||||
|
virtual nsresult Redo(void);
|
||||||
|
|
||||||
|
virtual nsresult GetIsTransient(PRBool *aIsTransient);
|
||||||
|
|
||||||
|
virtual nsresult Merge(PRBool *aDidMerge, nsITransaction *aTransaction);
|
||||||
|
|
||||||
|
virtual nsresult Write(nsIOutputStream *aOutputStream);
|
||||||
|
|
||||||
|
virtual nsresult GetUndoString(nsString **aString);
|
||||||
|
|
||||||
|
virtual nsresult GetRedoString(nsString **aString);
|
||||||
|
|
||||||
|
virtual nsresult AppendChild(EditTxn *aTxn);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
nsVoidArray *mChildren;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -28,10 +28,8 @@ NS_IMPL_ADDREF(EditTxn)
|
||||||
NS_IMPL_RELEASE(EditTxn)
|
NS_IMPL_RELEASE(EditTxn)
|
||||||
|
|
||||||
// note that aEditor is not refcounted
|
// note that aEditor is not refcounted
|
||||||
EditTxn::EditTxn(nsEditor *aEditor)
|
EditTxn::EditTxn()
|
||||||
{
|
{
|
||||||
NS_ASSERTION(nsnull!=aEditor, "null aEditor arg to EditTxn constructor");
|
|
||||||
mEditor = aEditor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult EditTxn::Do(void)
|
nsresult EditTxn::Do(void)
|
||||||
|
|
|
@ -20,13 +20,17 @@
|
||||||
#define EditTxn_h__
|
#define EditTxn_h__
|
||||||
|
|
||||||
#include "nsITransaction.h"
|
#include "nsITransaction.h"
|
||||||
class nsEditor;
|
|
||||||
|
|
||||||
class nsIDOMNode;
|
class nsIDOMNode;
|
||||||
|
|
||||||
|
#define EDIT_TXN_IID \
|
||||||
|
{/* c5ea31b0-ac48-11d2-86d8-000064657374 */ \
|
||||||
|
0xc5ea31b0, 0xac48, 0x11d2, \
|
||||||
|
{0x86, 0xd8, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* base class for all document editing transactions.
|
* base class for all document editing transactions.
|
||||||
* provides access to the nsEditor that created this transaction.
|
* provides default concrete behavior for all nsITransaction methods.
|
||||||
*/
|
*/
|
||||||
class EditTxn : public nsITransaction
|
class EditTxn : public nsITransaction
|
||||||
{
|
{
|
||||||
|
@ -34,7 +38,7 @@ public:
|
||||||
|
|
||||||
NS_DECL_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
|
|
||||||
EditTxn(nsEditor *aEditor);
|
EditTxn();
|
||||||
|
|
||||||
virtual nsresult Do(void);
|
virtual nsresult Do(void);
|
||||||
|
|
||||||
|
@ -52,10 +56,6 @@ public:
|
||||||
|
|
||||||
virtual nsresult GetRedoString(nsString **aString);
|
virtual nsresult GetRedoString(nsString **aString);
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
nsEditor *mEditor;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -20,18 +20,22 @@
|
||||||
#include "editor.h"
|
#include "editor.h"
|
||||||
#include "nsIDOMCharacterData.h"
|
#include "nsIDOMCharacterData.h"
|
||||||
|
|
||||||
static NS_DEFINE_IID(kInsertTextTxnIID, INSERTTEXTTXN_IID);
|
static NS_DEFINE_IID(kInsertTextTxnIID, INSERT_TEXT_TXN_IID);
|
||||||
|
|
||||||
// note that aEditor is not refcounted
|
|
||||||
InsertTextTxn::InsertTextTxn(nsEditor *aEditor,
|
InsertTextTxn::InsertTextTxn()
|
||||||
nsIDOMCharacterData *aElement,
|
: EditTxn()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult InsertTextTxn::Init(nsIDOMCharacterData *aElement,
|
||||||
PRUint32 aOffset,
|
PRUint32 aOffset,
|
||||||
const nsString& aStringToInsert)
|
const nsString& aStringToInsert)
|
||||||
: EditTxn(aEditor)
|
|
||||||
{
|
{
|
||||||
mElement = aElement;
|
mElement = aElement;
|
||||||
mOffset = aOffset;
|
mOffset = aOffset;
|
||||||
mStringToInsert = aStringToInsert;
|
mStringToInsert = aStringToInsert;
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult InsertTextTxn::Do(void)
|
nsresult InsertTextTxn::Do(void)
|
||||||
|
@ -60,11 +64,11 @@ nsresult InsertTextTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
|
||||||
if ((nsnull!=aDidMerge) && (nsnull!=aTransaction))
|
if ((nsnull!=aDidMerge) && (nsnull!=aTransaction))
|
||||||
{
|
{
|
||||||
// if aTransaction isa InsertTextTxn, absorb it
|
// if aTransaction isa InsertTextTxn, absorb it
|
||||||
nsCOMPtr<InsertTextTxn> otherTxn;
|
nsCOMPtr<InsertTextTxn> otherTxn = aTransaction;
|
||||||
nsresult result = aTransaction->QueryInterface(kInsertTextTxnIID, getter_AddRefs(otherTxn));
|
nsresult result=NS_OK;// = aTransaction->QueryInterface(kInsertTextTxnIID, getter_AddRefs(otherTxn));
|
||||||
if (NS_SUCCEEDED(result) && (otherTxn))
|
if (NS_SUCCEEDED(result) && (otherTxn))
|
||||||
{
|
{
|
||||||
nsString otherData;
|
nsAutoString otherData;
|
||||||
otherTxn->GetData(otherData);
|
otherTxn->GetData(otherData);
|
||||||
mStringToInsert += otherData;
|
mStringToInsert += otherData;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,14 +20,14 @@
|
||||||
#define InsertTextTxn_h__
|
#define InsertTextTxn_h__
|
||||||
|
|
||||||
#include "EditTxn.h"
|
#include "EditTxn.h"
|
||||||
|
#include "nsIDOMCharacterData.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
|
||||||
#define INSERTTEXTTXN_IID \
|
#define INSERT_TEXT_TXN_IID \
|
||||||
{/* 93276f00-ab2c-11d2-8f4b-006008159b0c*/ \
|
{/* 93276f00-ab2c-11d2-8f4b-006008159b0c*/ \
|
||||||
0x93276f00, 0xab2c, 0x11d2, \
|
0x93276f00, 0xab2c, 0x11d2, \
|
||||||
{0x8f, 0xb4, 0x0, 0x60, 0x8, 0x15, 0x9b, 0xc} }
|
{0x8f, 0xb4, 0x0, 0x60, 0x8, 0x15, 0x9b, 0xc} }
|
||||||
|
|
||||||
class nsIDOMCharacterData;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A transaction that changes an attribute of a content node.
|
* A transaction that changes an attribute of a content node.
|
||||||
* This transaction covers add, remove, and change attribute.
|
* This transaction covers add, remove, and change attribute.
|
||||||
|
@ -36,15 +36,13 @@ class InsertTextTxn : public EditTxn
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
InsertTextTxn(nsEditor *aEditor,
|
virtual nsresult Init(nsIDOMCharacterData *aElement,
|
||||||
nsIDOMCharacterData *aElement,
|
PRUint32 aOffset,
|
||||||
PRUint32 aOffset,
|
const nsString& aStringToInsert);
|
||||||
const nsString& aStringToInsert);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// default ctor so that nsCOMPtr is happy
|
InsertTextTxn();
|
||||||
InsertTextTxn() : EditTxn(nsnull) {}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -67,7 +65,7 @@ public:
|
||||||
// override QueryInterface to handle InsertTextTxn request
|
// override QueryInterface to handle InsertTextTxn request
|
||||||
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
|
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
|
||||||
|
|
||||||
static const nsIID& IID() { static nsIID iid = INSERTTEXTTXN_IID; return iid; }
|
static const nsIID& IID() { static nsIID iid = INSERT_TEXT_TXN_IID; return iid; }
|
||||||
|
|
||||||
|
|
||||||
virtual nsresult GetData(nsString& aResult);
|
virtual nsresult GetData(nsString& aResult);
|
||||||
|
@ -75,7 +73,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/** the text element to operate upon */
|
/** the text element to operate upon */
|
||||||
nsIDOMCharacterData *mElement;
|
nsCOMPtr<nsIDOMCharacterData> mElement;
|
||||||
|
|
||||||
/** the offset into mElement where the insertion is to take place */
|
/** the offset into mElement where the insertion is to take place */
|
||||||
PRUint32 mOffset;
|
PRUint32 mOffset;
|
||||||
|
@ -86,6 +84,8 @@ protected:
|
||||||
/** the text to insert into mElement at mOffset */
|
/** the text to insert into mElement at mOffset */
|
||||||
nsString mStringToInsert;
|
nsString mStringToInsert;
|
||||||
|
|
||||||
|
friend class TransactionFactory;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public License
|
||||||
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||||
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||||
|
* http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* NPL.
|
||||||
|
*
|
||||||
|
* The Initial Developer of this code under the NPL is Netscape
|
||||||
|
* Communications Corporation. Portions created by Netscape are
|
||||||
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||||
|
* Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "JoinElementTxn.h"
|
||||||
|
#include "nsIDOMNodeList.h"
|
||||||
|
#include "editor.h"
|
||||||
|
|
||||||
|
|
||||||
|
JoinElementTxn::JoinElementTxn()
|
||||||
|
: EditTxn()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult JoinElementTxn::Init(nsIDOMNode *aLeftNode,
|
||||||
|
nsIDOMNode *aRightNode)
|
||||||
|
{
|
||||||
|
mLeftNode = aLeftNode;
|
||||||
|
mRightNode = aRightNode;
|
||||||
|
mOffset=0;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
JoinElementTxn::~JoinElementTxn()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult JoinElementTxn::Do(void)
|
||||||
|
{
|
||||||
|
nsresult result;
|
||||||
|
|
||||||
|
if ((mLeftNode) && (mRightNode))
|
||||||
|
{ // get the parent node
|
||||||
|
nsCOMPtr<nsIDOMNode>leftParent;
|
||||||
|
result = mLeftNode->GetParentNode(getter_AddRefs(leftParent));
|
||||||
|
if ((NS_SUCCEEDED(result)) && (leftParent))
|
||||||
|
{ // verify that mLeftNode and mRightNode have the same parent
|
||||||
|
nsCOMPtr<nsIDOMNode>rightParent;
|
||||||
|
result = mRightNode->GetParentNode(getter_AddRefs(rightParent));
|
||||||
|
if ((NS_SUCCEEDED(result)) && (rightParent))
|
||||||
|
{
|
||||||
|
if (leftParent==rightParent)
|
||||||
|
{
|
||||||
|
mParent=leftParent; // set this instance mParent.
|
||||||
|
// Other methods see a non-null mParent and know all is well
|
||||||
|
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||||
|
result = mLeftNode->GetChildNodes(getter_AddRefs(childNodes));
|
||||||
|
if ((NS_SUCCEEDED(result)) && (childNodes))
|
||||||
|
{
|
||||||
|
childNodes->GetLength(&mOffset);
|
||||||
|
}
|
||||||
|
result = nsEditor::JoinNodes(mLeftNode, mRightNode, mParent, PR_FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
nsresult JoinElementTxn::Undo(void)
|
||||||
|
{
|
||||||
|
nsresult result = nsEditor::SplitNode(mRightNode, mOffset, mLeftNode, mParent);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult JoinElementTxn::Redo(void)
|
||||||
|
{
|
||||||
|
nsresult result = nsEditor::JoinNodes(mLeftNode, mRightNode, mParent, PR_FALSE);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult JoinElementTxn::GetIsTransient(PRBool *aIsTransient)
|
||||||
|
{
|
||||||
|
if (nsnull!=aIsTransient)
|
||||||
|
*aIsTransient = PR_FALSE;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult JoinElementTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
|
||||||
|
{
|
||||||
|
if (nsnull!=aDidMerge)
|
||||||
|
*aDidMerge=PR_FALSE;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult JoinElementTxn::Write(nsIOutputStream *aOutputStream)
|
||||||
|
{
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult JoinElementTxn::GetUndoString(nsString **aString)
|
||||||
|
{
|
||||||
|
if (nsnull!=aString)
|
||||||
|
{
|
||||||
|
**aString="Join Element";
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult JoinElementTxn::GetRedoString(nsString **aString)
|
||||||
|
{
|
||||||
|
if (nsnull!=aString)
|
||||||
|
{
|
||||||
|
**aString="Split Element";
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public License
|
||||||
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||||
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||||
|
* http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* NPL.
|
||||||
|
*
|
||||||
|
* The Initial Developer of this code under the NPL is Netscape
|
||||||
|
* Communications Corporation. Portions created by Netscape are
|
||||||
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||||
|
* Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef JoinElementTxn_h__
|
||||||
|
#define JoinElementTxn_h__
|
||||||
|
|
||||||
|
#include "EditTxn.h"
|
||||||
|
#include "nsIDOMNode.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
|
||||||
|
#define JOIN_ELEMENT_TXN_IID \
|
||||||
|
{/* 9bc5f9f0-ac48-11d2-86d8-000064657374 */ \
|
||||||
|
0x9bc5f9f0, 0xac48, 0x11d2, \
|
||||||
|
{0x86, 0xd8, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A transaction that joins two elements E1 and E2 into a single node E.
|
||||||
|
* The children of E are the children of E1 followed by the children of E2.
|
||||||
|
*/
|
||||||
|
class JoinElementTxn : public EditTxn
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual nsresult Init(nsIDOMNode *aLeftNode,
|
||||||
|
nsIDOMNode *aRightNode);
|
||||||
|
protected:
|
||||||
|
JoinElementTxn();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual ~JoinElementTxn();
|
||||||
|
|
||||||
|
virtual nsresult Do(void);
|
||||||
|
|
||||||
|
virtual nsresult Undo(void);
|
||||||
|
|
||||||
|
virtual nsresult Redo(void);
|
||||||
|
|
||||||
|
virtual nsresult GetIsTransient(PRBool *aIsTransient);
|
||||||
|
|
||||||
|
virtual nsresult Merge(PRBool *aDidMerge, nsITransaction *aTransaction);
|
||||||
|
|
||||||
|
virtual nsresult Write(nsIOutputStream *aOutputStream);
|
||||||
|
|
||||||
|
virtual nsresult GetUndoString(nsString **aString);
|
||||||
|
|
||||||
|
virtual nsresult GetRedoString(nsString **aString);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/** the elements to operate upon.
|
||||||
|
* After the merge, mRightNode remains and mLeftNode is removed from the content tree.
|
||||||
|
*/
|
||||||
|
nsCOMPtr<nsIDOMNode> mLeftNode;
|
||||||
|
nsCOMPtr<nsIDOMNode> mRightNode;
|
||||||
|
|
||||||
|
/** the offset into mNode where the children of mElement are split (for undo).<BR>
|
||||||
|
* mOffset is the index of the last child in the left node.
|
||||||
|
* -1 means the left node gets no children.
|
||||||
|
*/
|
||||||
|
PRUint32 mOffset;
|
||||||
|
|
||||||
|
/** the parent node containing mLeftNode and mRightNode */
|
||||||
|
nsCOMPtr<nsIDOMNode> mParent;
|
||||||
|
|
||||||
|
friend class TransactionFactory;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -17,44 +17,42 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "SplitElementTxn.h"
|
#include "SplitElementTxn.h"
|
||||||
#include "editor.h"
|
|
||||||
#include "nsIDOMNode.h"
|
#include "nsIDOMNode.h"
|
||||||
#include "nsIDOMElement.h"
|
#include "nsIDOMElement.h"
|
||||||
|
#include "editor.h"
|
||||||
|
|
||||||
// note that aEditor is not refcounted
|
// note that aEditor is not refcounted
|
||||||
SplitElementTxn::SplitElementTxn(nsEditor *aEditor,
|
SplitElementTxn::SplitElementTxn()
|
||||||
nsIDOMNode *aNode,
|
: EditTxn()
|
||||||
PRInt32 aOffset)
|
|
||||||
: EditTxn(aEditor)
|
|
||||||
{
|
{
|
||||||
mNode = aNode;
|
}
|
||||||
NS_ADDREF(mNode);
|
|
||||||
|
nsresult SplitElementTxn::Init(nsIDOMNode *aNode,
|
||||||
|
PRInt32 aOffset)
|
||||||
|
{
|
||||||
|
mExistingRightNode = aNode;
|
||||||
mOffset = aOffset;
|
mOffset = aOffset;
|
||||||
mNewNode = nsnull;
|
return NS_OK;
|
||||||
mParent = nsnull;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SplitElementTxn::~SplitElementTxn()
|
SplitElementTxn::~SplitElementTxn()
|
||||||
{
|
{
|
||||||
NS_IF_RELEASE(mNode);
|
|
||||||
NS_IF_RELEASE(mNewNode);
|
|
||||||
NS_IF_RELEASE(mParent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult SplitElementTxn::Do(void)
|
nsresult SplitElementTxn::Do(void)
|
||||||
{
|
{
|
||||||
// create a new node
|
// create a new node
|
||||||
nsresult result = mNode->CloneNode(PR_FALSE, &mNewNode);
|
nsresult result = mExistingRightNode->CloneNode(PR_FALSE, getter_AddRefs(mNewLeftNode));
|
||||||
NS_ASSERTION(((NS_SUCCEEDED(result)) && (nsnull!=mNewNode)), "could not create element.");
|
NS_ASSERTION(((NS_SUCCEEDED(result)) && (mNewLeftNode)), "could not create element.");
|
||||||
|
|
||||||
if ((NS_SUCCEEDED(result)) && (nsnull!=mNewNode))
|
if ((NS_SUCCEEDED(result)) && (mNewLeftNode))
|
||||||
{
|
{
|
||||||
// get the parent node
|
// get the parent node
|
||||||
result = mNode->GetParentNode(&mParent);
|
result = mExistingRightNode->GetParentNode(getter_AddRefs(mParent));
|
||||||
// insert the new node
|
// insert the new node
|
||||||
if ((NS_SUCCEEDED(result)) && (nsnull!=mParent))
|
if ((NS_SUCCEEDED(result)) && (mParent))
|
||||||
{
|
{
|
||||||
result = mEditor->SplitNode(mNode, mOffset, mNewNode, mParent);
|
result = nsEditor::SplitNode(mExistingRightNode, mOffset, mNewLeftNode, mParent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -63,13 +61,13 @@ nsresult SplitElementTxn::Do(void)
|
||||||
nsresult SplitElementTxn::Undo(void)
|
nsresult SplitElementTxn::Undo(void)
|
||||||
{
|
{
|
||||||
// this assumes Do inserted the new node in front of the prior existing node
|
// this assumes Do inserted the new node in front of the prior existing node
|
||||||
nsresult result = mEditor->JoinNodes(mNode, mNewNode, mParent, PR_FALSE);
|
nsresult result = nsEditor::JoinNodes(mExistingRightNode, mNewLeftNode, mParent, PR_FALSE);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult SplitElementTxn::Redo(void)
|
nsresult SplitElementTxn::Redo(void)
|
||||||
{
|
{
|
||||||
nsresult result = mEditor->SplitNode(mNode, mOffset, mNewNode, mParent);
|
nsresult result = nsEditor::SplitNode(mExistingRightNode, mOffset, mNewLeftNode, mParent);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,10 +20,13 @@
|
||||||
#define SplitElementTxn_h__
|
#define SplitElementTxn_h__
|
||||||
|
|
||||||
#include "EditTxn.h"
|
#include "EditTxn.h"
|
||||||
|
#include "nsIDOMNode.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
|
||||||
class nsIDOMNode;
|
#define SPLIT_ELEMENT_TXN_IID \
|
||||||
class nsIDOMElement;
|
{/* 690c6290-ac48-11d2-86d8-000064657374 */ \
|
||||||
class nsIDOMDocument;
|
0x690c6290, 0xac48, 0x11d2, \
|
||||||
|
{0x86, 0xd8, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A transaction that splits an element E into two identical nodes, E1 and E2
|
* A transaction that splits an element E into two identical nodes, E1 and E2
|
||||||
|
@ -33,10 +36,12 @@ class SplitElementTxn : public EditTxn
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
SplitElementTxn(nsEditor *aEditor,
|
virtual nsresult Init (nsIDOMNode *aNode,
|
||||||
nsIDOMNode *aNode,
|
PRInt32 aOffset);
|
||||||
PRInt32 aOffset);
|
protected:
|
||||||
|
SplitElementTxn();
|
||||||
|
|
||||||
|
public:
|
||||||
virtual ~SplitElementTxn();
|
virtual ~SplitElementTxn();
|
||||||
|
|
||||||
virtual nsresult Do(void);
|
virtual nsresult Do(void);
|
||||||
|
@ -58,7 +63,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/** the element to operate upon */
|
/** the element to operate upon */
|
||||||
nsIDOMNode *mNode;
|
nsCOMPtr<nsIDOMNode> mExistingRightNode;
|
||||||
|
|
||||||
/** the offset into mElement where the children of mElement are split.<BR>
|
/** the offset into mElement where the children of mElement are split.<BR>
|
||||||
* mOffset is the index of the last child in the left node.
|
* mOffset is the index of the last child in the left node.
|
||||||
|
@ -67,8 +72,12 @@ protected:
|
||||||
PRInt32 mOffset;
|
PRInt32 mOffset;
|
||||||
|
|
||||||
/** the element we create when splitting mElement */
|
/** the element we create when splitting mElement */
|
||||||
nsIDOMNode *mNewNode;
|
nsCOMPtr<nsIDOMNode> mNewLeftNode;
|
||||||
nsIDOMNode *mParent;
|
|
||||||
|
/** the parent shared by mExistingRightNode and mNewLeftNode */
|
||||||
|
nsCOMPtr<nsIDOMNode> mParent;
|
||||||
|
|
||||||
|
friend class TransactionFactory;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public License
|
||||||
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||||
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||||
|
* http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* NPL.
|
||||||
|
*
|
||||||
|
* The Initial Developer of this code under the NPL is Netscape
|
||||||
|
* Communications Corporation. Portions created by Netscape are
|
||||||
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||||
|
* Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "TransactionFactory.h"
|
||||||
|
// transactions this factory knows how to build
|
||||||
|
#include "InsertTextTxn.h"
|
||||||
|
#include "DeleteTextTxn.h"
|
||||||
|
#include "CreateElementTxn.h"
|
||||||
|
#include "DeleteElementTxn.h"
|
||||||
|
#include "DeleteRangeTxn.h"
|
||||||
|
#include "ChangeAttributeTxn.h"
|
||||||
|
#include "SplitElementTxn.h"
|
||||||
|
#include "JoinElementTxn.h"
|
||||||
|
|
||||||
|
static NS_DEFINE_IID(kInsertTextTxnIID, INSERT_TEXT_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kDeleteTextTxnIID, DELETE_TEXT_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kCreateElementTxnIID, CREATE_ELEMENT_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kDeleteElementTxnIID, DELETE_ELEMENT_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kDeleteRangeTxnIID, DELETE_RANGE_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kChangeAttributeTxnIID,CHANGE_ATTRIBUTE_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kSplitElementTxnIID, SPLIT_ELEMENT_TXN_IID);
|
||||||
|
static NS_DEFINE_IID(kJoinElementTxnIID, JOIN_ELEMENT_TXN_IID);
|
||||||
|
|
||||||
|
TransactionFactory::TransactionFactory()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
TransactionFactory::~TransactionFactory()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
TransactionFactory::GetNewTransaction(REFNSIID aTxnType, EditTxn **aResult)
|
||||||
|
{
|
||||||
|
nsresult result = NS_OK;
|
||||||
|
*aResult = nsnull;
|
||||||
|
if (aTxnType.Equals(kInsertTextTxnIID))
|
||||||
|
*aResult = new InsertTextTxn();
|
||||||
|
else if (aTxnType.Equals(kDeleteTextTxnIID))
|
||||||
|
*aResult = new DeleteTextTxn();
|
||||||
|
else if (aTxnType.Equals(kCreateElementTxnIID))
|
||||||
|
*aResult = new CreateElementTxn();
|
||||||
|
else if (aTxnType.Equals(kDeleteElementTxnIID))
|
||||||
|
*aResult = new DeleteElementTxn();
|
||||||
|
else if (aTxnType.Equals(kDeleteRangeTxnIID))
|
||||||
|
*aResult = new DeleteRangeTxn();
|
||||||
|
else if (aTxnType.Equals(kChangeAttributeTxnIID))
|
||||||
|
*aResult = new ChangeAttributeTxn();
|
||||||
|
else if (aTxnType.Equals(kSplitElementTxnIID))
|
||||||
|
*aResult = new SplitElementTxn();
|
||||||
|
else if (aTxnType.Equals(kJoinElementTxnIID))
|
||||||
|
*aResult = new JoinElementTxn();
|
||||||
|
|
||||||
|
if (nsnull==*aResult)
|
||||||
|
result = NS_ERROR_INVALID_ARG;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public License
|
||||||
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||||
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||||
|
* http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* NPL.
|
||||||
|
*
|
||||||
|
* The Initial Developer of this code under the NPL is Netscape
|
||||||
|
* Communications Corporation. Portions created by Netscape are
|
||||||
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||||
|
* Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TransactionFactory_h__
|
||||||
|
#define TransactionFactory_h__
|
||||||
|
|
||||||
|
#include "nsISupports.h"
|
||||||
|
|
||||||
|
class EditTxn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class instantiates and optionally recycles edit transactions
|
||||||
|
* A recycler would be a separate static object, since this class does not get instantiated
|
||||||
|
*/
|
||||||
|
class TransactionFactory
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
TransactionFactory();
|
||||||
|
virtual ~TransactionFactory();
|
||||||
|
|
||||||
|
public:
|
||||||
|
static nsresult GetNewTransaction(REFNSIID aTxnType, EditTxn **aResult);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
Загрузка…
Ссылка в новой задаче