Bug 1015433: Backout bug 828169 for regressing text editing

This commit is contained in:
David Zbarsky 2014-06-04 23:51:34 -04:00
parent d39f623cc6
commit dce20d18a7
12 changed files with 192 additions and 203 deletions

View File

@ -7,11 +7,9 @@
#include "nsAString.h"
#include "nsDebug.h" // for NS_ASSERTION
#include "nsError.h" // for NS_ERROR_NOT_INITIALIZED, etc
#include "nsEditor.h" // for nsEditor
#include "nsIDOMElement.h" // for nsIDOMElement
#include "nsIEditor.h" // for nsIEditor
#include "nsString.h" // for nsString
#include "mozilla/dom/Element.h"
using namespace mozilla;
ChangeAttributeTxn::ChangeAttributeTxn()
: EditTxn()
@ -26,8 +24,8 @@ NS_IMPL_RELEASE_INHERITED(ChangeAttributeTxn, EditTxn)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ChangeAttributeTxn)
NS_INTERFACE_MAP_END_INHERITING(EditTxn)
NS_IMETHODIMP ChangeAttributeTxn::Init(nsEditor *aEditor,
dom::Element *aElement,
NS_IMETHODIMP ChangeAttributeTxn::Init(nsIEditor *aEditor,
nsIDOMElement *aElement,
const nsAString& aAttribute,
const nsAString& aValue,
bool aRemoveAttribute)
@ -36,7 +34,7 @@ NS_IMETHODIMP ChangeAttributeTxn::Init(nsEditor *aEditor,
if (!aEditor || !aElement) { return NS_ERROR_NULL_POINTER; }
mEditor = aEditor;
mElement = aElement;
mElement = do_QueryInterface(aElement);
mAttribute = aAttribute;
mValue = aValue;
mRemoveAttribute = aRemoveAttribute;
@ -50,24 +48,20 @@ NS_IMETHODIMP ChangeAttributeTxn::DoTransaction(void)
NS_ASSERTION(mEditor && mElement, "bad state");
if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; }
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(mElement);
// need to get the current value of the attribute and save it, and set mAttributeWasSet
nsresult result = mEditor->GetAttributeValue(element, mAttribute, mUndoValue, &mAttributeWasSet);
NS_ENSURE_SUCCESS(result, result);
nsresult result = mEditor->GetAttributeValue(mElement, mAttribute, mUndoValue, &mAttributeWasSet);
// XXX: hack until attribute-was-set code is implemented
if (!mUndoValue.IsEmpty())
mAttributeWasSet = true;
// XXX: end hack
ErrorResult rv;
// now set the attribute to the new value
if (!mRemoveAttribute)
mElement->SetAttribute(mAttribute, mValue, rv);
result = mElement->SetAttribute(mAttribute, mValue);
else
mElement->RemoveAttribute(mAttribute, rv);
result = mElement->RemoveAttribute(mAttribute);
return rv.ErrorCode();
return result;
}
NS_IMETHODIMP ChangeAttributeTxn::UndoTransaction(void)
@ -75,13 +69,13 @@ NS_IMETHODIMP ChangeAttributeTxn::UndoTransaction(void)
NS_ASSERTION(mEditor && mElement, "bad state");
if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; }
ErrorResult rv;
nsresult result;
if (mAttributeWasSet)
mElement->SetAttribute(mAttribute, mUndoValue, rv);
result = mElement->SetAttribute(mAttribute, mUndoValue);
else
mElement->RemoveAttribute(mAttribute, rv);
result = mElement->RemoveAttribute(mAttribute);
return rv.ErrorCode();
return result;
}
NS_IMETHODIMP ChangeAttributeTxn::RedoTransaction(void)
@ -89,13 +83,13 @@ NS_IMETHODIMP ChangeAttributeTxn::RedoTransaction(void)
NS_ASSERTION(mEditor && mElement, "bad state");
if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; }
ErrorResult rv;
nsresult result;
if (!mRemoveAttribute)
mElement->SetAttribute(mAttribute, mValue, rv);
result = mElement->SetAttribute(mAttribute, mValue);
else
mElement->RemoveAttribute(mAttribute, rv);
result = mElement->RemoveAttribute(mAttribute);
return rv.ErrorCode();
return result;
}
NS_IMETHODIMP ChangeAttributeTxn::GetTxnDescription(nsAString& aString)

View File

@ -9,20 +9,15 @@
#include "EditTxn.h"
#include "nsCOMPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIDOMElement.h"
#include "nsISupportsImpl.h"
#include "nsString.h"
#include "nscore.h"
class nsEditor;
namespace mozilla {
namespace dom {
class Element;
}
}
class nsIEditor;
/**
* 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.
*/
class ChangeAttributeTxn : public EditTxn
@ -35,8 +30,8 @@ public:
* @param aValue the new value for aAttribute, if aRemoveAttribute is false
* @param aRemoveAttribute if true, remove aAttribute from aNode
*/
NS_IMETHOD Init(nsEditor *aEditor,
mozilla::dom::Element *aNode,
NS_IMETHOD Init(nsIEditor *aEditor,
nsIDOMElement *aNode,
const nsAString& aAttribute,
const nsAString& aValue,
bool aRemoveAttribute);
@ -53,11 +48,11 @@ public:
protected:
/** the editor that created this transaction */
nsEditor* mEditor;
nsIEditor* mEditor;
/** the element to operate upon */
nsCOMPtr<mozilla::dom::Element> mElement;
nsCOMPtr<nsIDOMElement> mElement;
/** the attribute to change */
nsString mAttribute;

View File

@ -13,6 +13,7 @@
#include "nsError.h"
#include "nsIContent.h"
#include "nsIDOMCharacterData.h"
#include "nsIEditor.h"
#include "nsINode.h"
#include "nsISelection.h"
#include "nsISupportsUtils.h"
@ -42,7 +43,7 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CreateElementTxn)
NS_INTERFACE_MAP_END_INHERITING(EditTxn)
NS_IMETHODIMP CreateElementTxn::Init(nsEditor *aEditor,
const nsAString &aTag,
nsINode *aParent,
nsIDOMNode *aParent,
uint32_t aOffsetInParent)
{
NS_ASSERTION(aEditor&&aParent, "null args");
@ -66,24 +67,28 @@ NS_IMETHODIMP CreateElementTxn::DoTransaction(void)
NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode());
NS_ENSURE_STATE(newContent);
mNewNode = newContent;
mNewNode = newContent->AsDOMNode();
// Try to insert formatting whitespace for the new node:
mEditor->MarkNodeDirty(mNewNode);
// insert the new node
if (CreateElementTxn::eAppend == int32_t(mOffsetInParent)) {
mParent->AppendChild(*mNewNode, rv);
return rv.ErrorCode();
nsCOMPtr<nsIDOMNode> resultNode;
return mParent->AppendChild(mNewNode, getter_AddRefs(resultNode));
}
nsCOMPtr<nsINode> parent = do_QueryInterface(mParent);
NS_ENSURE_STATE(parent);
mOffsetInParent = std::min(mOffsetInParent, mParent->GetChildCount());
mOffsetInParent = std::min(mOffsetInParent, parent->GetChildCount());
// note, it's ok for mRefNode to be null. that means append
mRefNode = mParent->GetChildAt(mOffsetInParent);
nsIContent* refNode = parent->GetChildAt(mOffsetInParent);
mRefNode = refNode ? refNode->AsDOMNode() : nullptr;
mParent->InsertBefore(*mNewNode, mRefNode, rv);
NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode());
nsCOMPtr<nsIDOMNode> resultNode;
nsresult result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode));
NS_ENSURE_SUCCESS(result, result);
// only set selection to insertion point if editor gives permission
bool bAdjustSelection;
@ -94,7 +99,7 @@ NS_IMETHODIMP CreateElementTxn::DoTransaction(void)
}
nsCOMPtr<nsISelection> selection;
nsresult result = mEditor->GetSelection(getter_AddRefs(selection));
result = mEditor->GetSelection(getter_AddRefs(selection));
NS_ENSURE_SUCCESS(result, result);
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
@ -112,9 +117,8 @@ NS_IMETHODIMP CreateElementTxn::UndoTransaction(void)
NS_ASSERTION(mEditor && mParent, "bad state");
NS_ENSURE_TRUE(mEditor && mParent, NS_ERROR_NOT_INITIALIZED);
ErrorResult rv;
mParent->RemoveChild(*mNewNode, rv);
return rv.ErrorCode();
nsCOMPtr<nsIDOMNode> resultNode;
return mParent->RemoveChild(mNewNode, getter_AddRefs(resultNode));
}
NS_IMETHODIMP CreateElementTxn::RedoTransaction(void)
@ -128,11 +132,10 @@ NS_IMETHODIMP CreateElementTxn::RedoTransaction(void)
{
nodeAsText->SetData(EmptyString());
}
// now, reinsert mNewNode
ErrorResult rv;
mParent->InsertBefore(*mNewNode, mRefNode, rv);
return rv.ErrorCode();
nsCOMPtr<nsIDOMNode> resultNode;
return mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode));
}
NS_IMETHODIMP CreateElementTxn::GetTxnDescription(nsAString& aString)
@ -142,7 +145,7 @@ NS_IMETHODIMP CreateElementTxn::GetTxnDescription(nsAString& aString)
return NS_OK;
}
NS_IMETHODIMP CreateElementTxn::GetNewNode(nsINode **aNewNode)
NS_IMETHODIMP CreateElementTxn::GetNewNode(nsIDOMNode **aNewNode)
{
NS_ENSURE_TRUE(aNewNode, NS_ERROR_NULL_POINTER);
NS_ENSURE_TRUE(mNewNode, NS_ERROR_NOT_INITIALIZED);

View File

@ -9,12 +9,12 @@
#include "EditTxn.h"
#include "nsCOMPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIDOMNode.h"
#include "nsISupportsImpl.h"
#include "nsString.h"
#include "nscore.h"
class nsEditor;
class nsINode;
/**
* A transaction that creates a new node in the content tree.
@ -33,7 +33,7 @@ public:
*/
NS_IMETHOD Init(nsEditor *aEditor,
const nsAString& aTag,
nsINode *aParent,
nsIDOMNode *aParent,
uint32_t aOffsetInParent);
CreateElementTxn();
@ -45,27 +45,27 @@ public:
NS_IMETHOD RedoTransaction();
NS_IMETHOD GetNewNode(nsINode **aNewNode);
NS_IMETHOD GetNewNode(nsIDOMNode **aNewNode);
protected:
/** the document into which the new node will be inserted */
nsEditor* mEditor;
/** the tag (mapping to object type) for the new element */
nsString mTag;
/** the node into which the new node will be inserted */
nsCOMPtr<nsINode> mParent;
nsCOMPtr<nsIDOMNode> mParent;
/** the index in mParent for the new node */
uint32_t mOffsetInParent;
/** the new node to insert */
nsCOMPtr<nsINode> mNewNode;
nsCOMPtr<nsIDOMNode> mNewNode;
/** the node we will insert mNewNode before. We compute this ourselves. */
nsCOMPtr<nsINode> mRefNode;
nsCOMPtr<nsIDOMNode> mRefNode;
};
#endif

View File

@ -33,10 +33,10 @@ NS_IMPL_RELEASE_INHERITED(InsertElementTxn, EditTxn)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(InsertElementTxn)
NS_INTERFACE_MAP_END_INHERITING(EditTxn)
NS_IMETHODIMP InsertElementTxn::Init(nsINode *aNode,
nsINode *aParent,
NS_IMETHODIMP InsertElementTxn::Init(nsIDOMNode *aNode,
nsIDOMNode *aParent,
int32_t aOffset,
nsEditor *aEditor)
nsIEditor *aEditor)
{
NS_ASSERTION(aNode && aParent && aEditor, "bad arg");
NS_ENSURE_TRUE(aNode && aParent && aEditor, NS_ERROR_NULL_POINTER);
@ -65,12 +65,14 @@ NS_IMETHODIMP InsertElementTxn::DoTransaction(void)
// note, it's ok for refContent to be null. that means append
nsCOMPtr<nsIContent> refContent = parent->GetChildAt(mOffset);
nsCOMPtr<nsIDOMNode> refNode = refContent ? refContent->AsDOMNode() : nullptr;
mEditor->MarkNodeDirty(mNode);
ErrorResult rv;
mParent->InsertBefore(*mNode, refContent, rv);
NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode());
nsCOMPtr<nsIDOMNode> resultNode;
nsresult result = mParent->InsertBefore(mNode, refNode, getter_AddRefs(resultNode));
NS_ENSURE_SUCCESS(result, result);
NS_ENSURE_TRUE(resultNode, NS_ERROR_NULL_POINTER);
// only set selection to insertion point if editor gives permission
bool bAdjustSelection;
@ -78,26 +80,25 @@ NS_IMETHODIMP InsertElementTxn::DoTransaction(void)
if (bAdjustSelection)
{
nsCOMPtr<nsISelection> selection;
rv = mEditor->GetSelection(getter_AddRefs(selection));
NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode());
result = mEditor->GetSelection(getter_AddRefs(selection));
NS_ENSURE_SUCCESS(result, result);
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
// place the selection just after the inserted element
selection->Collapse(mParent->AsDOMNode(), mOffset+1);
selection->Collapse(mParent, mOffset+1);
}
else
{
// do nothing - dom range gravity will adjust selection
}
return NS_OK;
return result;
}
NS_IMETHODIMP InsertElementTxn::UndoTransaction(void)
{
NS_ENSURE_TRUE(mNode && mParent, NS_ERROR_NOT_INITIALIZED);
ErrorResult rv;
mParent->RemoveChild(*mNode, rv);
return rv.ErrorCode();
nsCOMPtr<nsIDOMNode> resultNode;
return mParent->RemoveChild(mNode, getter_AddRefs(resultNode));
}
NS_IMETHODIMP InsertElementTxn::GetTxnDescription(nsAString& aString)

View File

@ -9,11 +9,11 @@
#include "EditTxn.h" // for EditTxn, NS_DECL_EDITTXN
#include "nsCOMPtr.h" // for nsCOMPtr
#include "nsCycleCollectionParticipant.h"
#include "nsIDOMNode.h" // for nsIDOMNode
#include "nsISupportsImpl.h" // for NS_DECL_ISUPPORTS_INHERITED
#include "nscore.h" // for NS_IMETHOD
class nsEditor;
class nsINode;
class nsIEditor;
/**
* A transaction that inserts a single element
@ -26,10 +26,10 @@ public:
* @param aParent the node to insert into
* @param aOffset the offset in aParent to insert aNode
*/
NS_IMETHOD Init(nsINode *aNode,
nsINode *aParent,
NS_IMETHOD Init(nsIDOMNode *aNode,
nsIDOMNode *aParent,
int32_t aOffset,
nsEditor *aEditor);
nsIEditor *aEditor);
InsertElementTxn();
@ -39,15 +39,15 @@ public:
NS_DECL_EDITTXN
protected:
/** the element to insert */
nsCOMPtr<nsINode> mNode;
nsCOMPtr<nsIDOMNode> mNode;
/** the node into which the new node will be inserted */
nsCOMPtr<nsINode> mParent;
nsCOMPtr<nsIDOMNode> mParent;
/** the editor for this transaction */
nsEditor* mEditor;
nsIEditor* mEditor;
/** the index in mParent for the new node */
int32_t mOffset;

View File

@ -31,18 +31,20 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(JoinElementTxn)
NS_INTERFACE_MAP_END_INHERITING(EditTxn)
NS_IMETHODIMP JoinElementTxn::Init(nsEditor *aEditor,
nsINode *aLeftNode,
nsINode *aRightNode)
nsIDOMNode *aLeftNode,
nsIDOMNode *aRightNode)
{
NS_PRECONDITION((aEditor && aLeftNode && aRightNode), "null arg");
if (!aEditor || !aLeftNode || !aRightNode) { return NS_ERROR_NULL_POINTER; }
mEditor = aEditor;
mLeftNode = aLeftNode;
nsCOMPtr<nsINode> leftParent = mLeftNode->GetParentNode();
mLeftNode = do_QueryInterface(aLeftNode);
nsCOMPtr<nsIDOMNode>leftParent;
nsresult result = mLeftNode->GetParentNode(getter_AddRefs(leftParent));
NS_ENSURE_SUCCESS(result, result);
if (!mEditor->IsModifiableNode(leftParent)) {
return NS_ERROR_FAILURE;
}
mRightNode = aRightNode;
mRightNode = do_QueryInterface(aRightNode);
mOffset = 0;
return NS_OK;
}
@ -54,11 +56,13 @@ NS_IMETHODIMP JoinElementTxn::DoTransaction(void)
if (!mEditor || !mLeftNode || !mRightNode) { return NS_ERROR_NOT_INITIALIZED; }
// get the parent node
nsCOMPtr<nsINode> leftParent = mLeftNode->GetParentNode();
nsCOMPtr<nsINode> leftNode = do_QueryInterface(mLeftNode);
nsCOMPtr<nsINode> leftParent = leftNode->GetParentNode();
NS_ENSURE_TRUE(leftParent, NS_ERROR_NULL_POINTER);
// verify that mLeftNode and mRightNode have the same parent
nsCOMPtr<nsINode> rightParent = mRightNode->GetParentNode();
nsCOMPtr<nsINode> rightNode = do_QueryInterface(mRightNode);
nsCOMPtr<nsINode> rightParent = rightNode->GetParentNode();
NS_ENSURE_TRUE(rightParent, NS_ERROR_NULL_POINTER);
if (leftParent != rightParent) {
@ -68,10 +72,11 @@ NS_IMETHODIMP JoinElementTxn::DoTransaction(void)
// set this instance mParent.
// Other methods will see a non-null mParent and know all is well
mParent = leftParent;
mOffset = mLeftNode->Length();
mParent = leftParent->AsDOMNode();
mOffset = leftNode->Length();
return mEditor->JoinNodesImpl(mRightNode, mLeftNode, mParent);
nsCOMPtr<nsINode> parent = do_QueryInterface(mParent);
return mEditor->JoinNodesImpl(rightNode, leftNode, parent);
}
//XXX: what if instead of split, we just deleted the unneeded children of mRight
@ -81,26 +86,31 @@ NS_IMETHODIMP JoinElementTxn::UndoTransaction(void)
NS_ASSERTION(mRightNode && mLeftNode && mParent, "bad state");
if (!mRightNode || !mLeftNode || !mParent) { return NS_ERROR_NOT_INITIALIZED; }
// first, massage the existing node so it is in its post-split state
nsresult result;
nsCOMPtr<nsIDOMNode>resultNode;
nsCOMPtr<nsIDOMCharacterData>rightNodeAsText = do_QueryInterface(mRightNode);
ErrorResult rv;
if (rightNodeAsText)
{
rv = rightNodeAsText->DeleteData(0, mOffset);
NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode());
result = rightNodeAsText->DeleteData(0, mOffset);
}
else
{
for (nsCOMPtr<nsINode> child = mRightNode->GetFirstChild();
child;
child = child->GetNextSibling())
nsCOMPtr<nsIDOMNode>child;
result = mRightNode->GetFirstChild(getter_AddRefs(child));
nsCOMPtr<nsIDOMNode>nextSibling;
uint32_t i;
for (i=0; i<mOffset; i++)
{
mLeftNode->AppendChild(*child, rv);
NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode());
if (NS_FAILED(result)) {return result;}
if (!child) {return NS_ERROR_NULL_POINTER;}
child->GetNextSibling(getter_AddRefs(nextSibling));
result = mLeftNode->AppendChild(child, getter_AddRefs(resultNode));
child = do_QueryInterface(nextSibling);
}
}
// second, re-insert the left node into the tree
mParent->InsertBefore(*mLeftNode, mRightNode, rv);
return rv.ErrorCode();
result = mParent->InsertBefore(mLeftNode, mRightNode, getter_AddRefs(resultNode));
return result;
}
NS_IMETHODIMP JoinElementTxn::GetTxnDescription(nsAString& aString)

View File

@ -10,14 +10,14 @@
#include "nsCOMPtr.h" // for nsCOMPtr
#include "nsCycleCollectionParticipant.h"
#include "nsID.h" // for REFNSIID
#include "nsIDOMNode.h" // for nsIDOMNode
#include "nscore.h" // for NS_IMETHOD
class nsEditor;
class nsINode;
/**
* A transaction that joins two elements E1 (left node) and E2 (right node)
* into a single node E.
* into a single node E.
* The children of E are the children of E1 followed by the children of E2.
* After DoTransaction() and RedoTransaction(), E1 is removed from the content
* tree and E2 remains.
@ -31,8 +31,8 @@ public:
* @param aRightNode the second of two nodes to join
*/
NS_IMETHOD Init(nsEditor *aEditor,
nsINode *aLeftNode,
nsINode *aRightNode);
nsIDOMNode *aLeftNode,
nsIDOMNode *aRightNode);
JoinElementTxn();
@ -42,21 +42,21 @@ public:
NS_DECL_EDITTXN
protected:
/** the elements to operate upon.
/** the elements to operate upon.
* After the merge, mRightNode remains and mLeftNode is removed from the content tree.
*/
nsCOMPtr<nsINode> mLeftNode;
nsCOMPtr<nsINode> mRightNode;
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 first child in the right node.
* mOffset is the index of the first child in the right node.
* -1 means the left node had no children.
*/
uint32_t mOffset;
/** the parent node containing mLeftNode and mRightNode */
nsCOMPtr<nsINode> mParent;
nsCOMPtr<nsIDOMNode> mParent;
nsEditor* mEditor;
};

View File

@ -34,7 +34,7 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SplitElementTxn)
NS_INTERFACE_MAP_END_INHERITING(EditTxn)
NS_IMETHODIMP SplitElementTxn::Init(nsEditor *aEditor,
nsINode *aNode,
nsIDOMNode *aNode,
int32_t aOffset)
{
NS_ASSERTION(aEditor && aNode, "bad args");
@ -52,23 +52,18 @@ NS_IMETHODIMP SplitElementTxn::DoTransaction(void)
if (!mExistingRightNode || !mEditor) { return NS_ERROR_NOT_INITIALIZED; }
// create a new node
ErrorResult rv;
mNewLeftNode = mExistingRightNode->CloneNode(false, rv);
NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode());
NS_ASSERTION(mNewLeftNode, "could not create element.");
NS_ENSURE_TRUE(mNewLeftNode, NS_ERROR_NULL_POINTER);
nsresult result = mExistingRightNode->CloneNode(false, 1, getter_AddRefs(mNewLeftNode));
NS_ASSERTION(((NS_SUCCEEDED(result)) && (mNewLeftNode)), "could not create element.");
NS_ENSURE_SUCCESS(result, result);
mEditor->MarkNodeDirty(mExistingRightNode);
// get the parent node
mParent = mExistingRightNode->GetParentNode();
result = mExistingRightNode->GetParentNode(getter_AddRefs(mParent));
NS_ENSURE_SUCCESS(result, result);
NS_ENSURE_TRUE(mParent, NS_ERROR_NULL_POINTER);
// insert the new node
nsresult result = mEditor->SplitNodeImpl(mExistingRightNode->AsDOMNode(),
mOffset,
mNewLeftNode->AsDOMNode(),
mParent->AsDOMNode());
NS_ENSURE_SUCCESS(result, result);
result = mEditor->SplitNodeImpl(mExistingRightNode, mOffset, mNewLeftNode, mParent);
if (mNewLeftNode) {
bool bAdjustSelection;
mEditor->ShouldTxnSetSelection(&bAdjustSelection);
@ -78,7 +73,7 @@ NS_IMETHODIMP SplitElementTxn::DoTransaction(void)
result = mEditor->GetSelection(getter_AddRefs(selection));
NS_ENSURE_SUCCESS(result, result);
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
result = selection->Collapse(mNewLeftNode->AsDOMNode(), mOffset);
result = selection->Collapse(mNewLeftNode, mOffset);
}
else
{
@ -96,7 +91,10 @@ NS_IMETHODIMP SplitElementTxn::UndoTransaction(void)
}
// this assumes Do inserted the new node in front of the prior existing node
return mEditor->JoinNodesImpl(mExistingRightNode, mNewLeftNode, mParent);
nsCOMPtr<nsINode> right = do_QueryInterface(mExistingRightNode);
nsCOMPtr<nsINode> left = do_QueryInterface(mNewLeftNode);
nsCOMPtr<nsINode> parent = do_QueryInterface(mParent);
return mEditor->JoinNodesImpl(right, left, parent);
}
/* redo cannot simply resplit the right node, because subsequent transactions
@ -109,6 +107,8 @@ NS_IMETHODIMP SplitElementTxn::RedoTransaction(void)
return NS_ERROR_NOT_INITIALIZED;
}
nsresult result;
nsCOMPtr<nsIDOMNode>resultNode;
// first, massage the existing node so it is in its post-split state
nsCOMPtr<nsIDOMCharacterData>rightNodeAsText = do_QueryInterface(mExistingRightNode);
if (rightNodeAsText)
@ -118,24 +118,26 @@ NS_IMETHODIMP SplitElementTxn::RedoTransaction(void)
}
else
{
nsCOMPtr<nsINode> child = mExistingRightNode->GetFirstChild();
for (int32_t i=0; i<mOffset; i++)
nsCOMPtr<nsIDOMNode>child;
nsCOMPtr<nsIDOMNode>nextSibling;
result = mExistingRightNode->GetFirstChild(getter_AddRefs(child));
int32_t i;
for (i=0; i<mOffset; i++)
{
if (NS_FAILED(result)) {return result;}
if (!child) {return NS_ERROR_NULL_POINTER;}
ErrorResult rv;
mExistingRightNode->RemoveChild(*child, rv);
if (NS_SUCCEEDED(rv.ErrorCode()))
child->GetNextSibling(getter_AddRefs(nextSibling));
result = mExistingRightNode->RemoveChild(child, getter_AddRefs(resultNode));
if (NS_SUCCEEDED(result))
{
mNewLeftNode->AppendChild(*child, rv);
NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode());
result = mNewLeftNode->AppendChild(child, getter_AddRefs(resultNode));
}
child = child->GetNextSibling();
child = do_QueryInterface(nextSibling);
}
}
// second, re-insert the left node into the tree
ErrorResult rv;
mParent->InsertBefore(*mNewLeftNode, mExistingRightNode, rv);
return rv.ErrorCode();
result = mParent->InsertBefore(mNewLeftNode, mExistingRightNode, getter_AddRefs(resultNode));
return result;
}
@ -145,7 +147,7 @@ NS_IMETHODIMP SplitElementTxn::GetTxnDescription(nsAString& aString)
return NS_OK;
}
NS_IMETHODIMP SplitElementTxn::GetNewNode(nsINode **aNewNode)
NS_IMETHODIMP SplitElementTxn::GetNewNode(nsIDOMNode **aNewNode)
{
NS_ENSURE_TRUE(aNewNode, NS_ERROR_NULL_POINTER);
NS_ENSURE_TRUE(mNewLeftNode, NS_ERROR_NOT_INITIALIZED);

View File

@ -9,11 +9,11 @@
#include "EditTxn.h" // for EditTxn, NS_DECL_EDITTXN
#include "nsCOMPtr.h" // for nsCOMPtr
#include "nsCycleCollectionParticipant.h"
#include "nsIDOMNode.h" // for nsIDOMNode
#include "nsISupportsImpl.h" // for NS_DECL_ISUPPORTS_INHERITED
#include "nscore.h" // for NS_IMETHOD
class nsEditor;
class nsINode;
/**
* A transaction that splits an element E into two identical nodes, E1 and E2
@ -30,7 +30,7 @@ public:
* The left node will have child|content 0..aOffset-1.
*/
NS_IMETHOD Init (nsEditor *aEditor,
nsINode *aNode,
nsIDOMNode *aNode,
int32_t aOffset);
SplitElementTxn();
@ -42,12 +42,12 @@ public:
NS_IMETHOD RedoTransaction(void);
NS_IMETHOD GetNewNode(nsINode **aNewNode);
NS_IMETHOD GetNewNode(nsIDOMNode **aNewNode);
protected:
/** the element to operate upon */
nsCOMPtr<nsINode> mExistingRightNode;
nsCOMPtr<nsIDOMNode> mExistingRightNode;
/** the offset into mElement where the children of mElement are split.<BR>
* mOffset is the index of the first child in the right node.
@ -56,10 +56,10 @@ protected:
int32_t mOffset;
/** the element we create when splitting mElement */
nsCOMPtr<nsINode> mNewLeftNode;
nsCOMPtr<nsIDOMNode> mNewLeftNode;
/** the parent shared by mExistingRightNode and mNewLeftNode */
nsCOMPtr<nsINode> mParent;
nsCOMPtr<nsIDOMNode> mParent;
nsEditor* mEditor;
};

View File

@ -1174,15 +1174,14 @@ nsEditor::CanPasteTransferable(nsITransferable *aTransferable, bool *aCanPaste)
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
NS_IMETHODIMP
nsEditor::SetAttribute(nsIDOMElement *aElement, const nsAString & aAttribute, const nsAString & aValue)
{
nsRefPtr<ChangeAttributeTxn> txn;
nsCOMPtr<Element> element = do_QueryInterface(aElement);
nsresult result = CreateTxnForSetAttribute(element, aAttribute, aValue,
nsresult result = CreateTxnForSetAttribute(aElement, aAttribute, aValue,
getter_AddRefs(txn));
if (NS_SUCCEEDED(result)) {
result = DoTransaction(txn);
result = DoTransaction(txn);
}
return result;
}
@ -1208,15 +1207,14 @@ nsEditor::GetAttributeValue(nsIDOMElement *aElement,
return rv;
}
NS_IMETHODIMP
NS_IMETHODIMP
nsEditor::RemoveAttribute(nsIDOMElement *aElement, const nsAString& aAttribute)
{
nsRefPtr<ChangeAttributeTxn> txn;
nsCOMPtr<Element> element = do_QueryInterface(aElement);
nsresult result = CreateTxnForRemoveAttribute(element, aAttribute,
nsresult result = CreateTxnForRemoveAttribute(aElement, aAttribute,
getter_AddRefs(txn));
if (NS_SUCCEEDED(result)) {
result = DoTransaction(txn);
result = DoTransaction(txn);
}
return result;
}
@ -1234,21 +1232,15 @@ nsEditor::OutputsMozDirty()
NS_IMETHODIMP
nsEditor::MarkNodeDirty(nsIDOMNode* aNode)
{
nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
return MarkNodeDirty(node);
}
nsresult
nsEditor::MarkNodeDirty(nsINode* aNode)
{
{
// Mark the node dirty, but not for webpages (bug 599983)
if (!OutputsMozDirty()) {
return NS_OK;
}
if (aNode->IsElement()) {
aNode->AsElement()->SetAttr(kNameSpaceID_None, nsEditProperty::mozdirty,
EmptyString(), false);
nsCOMPtr<dom::Element> element = do_QueryInterface(aNode);
if (element) {
element->SetAttr(kNameSpaceID_None, nsEditProperty::mozdirty,
EmptyString(), false);
}
return NS_OK;
}
@ -1356,17 +1348,14 @@ NS_IMETHODIMP nsEditor::CreateNode(const nsAString& aTag,
mActionListeners[i]->WillCreateNode(aTag, aParent, aPosition);
nsRefPtr<CreateElementTxn> txn;
nsCOMPtr<nsINode> parent = do_QueryInterface(aParent);
nsresult result = CreateTxnForCreateElement(aTag, parent, aPosition,
nsresult result = CreateTxnForCreateElement(aTag, aParent, aPosition,
getter_AddRefs(txn));
if (NS_SUCCEEDED(result))
{
result = DoTransaction(txn);
if (NS_SUCCEEDED(result))
{
nsCOMPtr<nsINode> newNode;
result = txn->GetNewNode(getter_AddRefs(newNode));
CallQueryInterface(newNode, aNewNode);
result = txn->GetNewNode(aNewNode);
NS_ASSERTION((NS_SUCCEEDED(result)), "GetNewNode can't fail if txn::DoTransaction succeeded.");
}
}
@ -1400,8 +1389,8 @@ NS_IMETHODIMP nsEditor::InsertNode(nsIDOMNode * aNode,
nsRefPtr<InsertElementTxn> txn;
nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
nsCOMPtr<nsINode> parent = do_QueryInterface(aParent);
nsresult result = CreateTxnForInsertElement(node, parent, aPosition,
getter_AddRefs(txn));
nsresult result = CreateTxnForInsertElement(node->AsDOMNode(), parent->AsDOMNode(),
aPosition, getter_AddRefs(txn));
if (NS_SUCCEEDED(result)) {
result = DoTransaction(txn);
}
@ -1427,16 +1416,13 @@ nsEditor::SplitNode(nsIDOMNode * aNode,
mActionListeners[i]->WillSplitNode(aNode, aOffset);
nsRefPtr<SplitElementTxn> txn;
nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
nsresult result = CreateTxnForSplitNode(node, aOffset, getter_AddRefs(txn));
nsresult result = CreateTxnForSplitNode(aNode, aOffset, getter_AddRefs(txn));
if (NS_SUCCEEDED(result))
{
result = DoTransaction(txn);
if (NS_SUCCEEDED(result))
{
nsCOMPtr<nsINode> leftNode;
result = txn->GetNewNode(getter_AddRefs(leftNode));
CallQueryInterface(leftNode, aNewLeftNode);
result = txn->GetNewNode(aNewLeftNode);
NS_ASSERTION((NS_SUCCEEDED(result)), "result must succeeded for GetNewNode");
}
}
@ -1487,15 +1473,13 @@ nsEditor::JoinNodes(nsIDOMNode * aLeftNode,
mActionListeners[i]->WillJoinNodes(aLeftNode, aRightNode, aParent);
nsRefPtr<JoinElementTxn> txn;
nsCOMPtr<nsINode> leftNode = do_QueryInterface(aLeftNode);
nsCOMPtr<nsINode> rightNode = do_QueryInterface(aRightNode);
result = CreateTxnForJoinNode(leftNode, rightNode, getter_AddRefs(txn));
result = CreateTxnForJoinNode(aLeftNode, aRightNode, getter_AddRefs(txn));
if (NS_SUCCEEDED(result)) {
result = DoTransaction(txn);
result = DoTransaction(txn);
}
mRangeUpdater.SelAdjJoinNodes(aLeftNode, aRightNode, aParent, offset, (int32_t)oldLeftNodeLen);
for (i = 0; i < mActionListeners.Count(); i++)
mActionListeners[i]->DidJoinNodes(aLeftNode, aRightNode, aParent, result);
@ -2688,7 +2672,7 @@ nsEditor::CreateTxnForDeleteText(nsIDOMCharacterData* aElement,
NS_IMETHODIMP nsEditor::CreateTxnForSplitNode(nsINode *aNode,
NS_IMETHODIMP nsEditor::CreateTxnForSplitNode(nsIDOMNode *aNode,
uint32_t aOffset,
SplitElementTxn **aTxn)
{
@ -2705,8 +2689,8 @@ NS_IMETHODIMP nsEditor::CreateTxnForSplitNode(nsINode *aNode,
return rv;
}
NS_IMETHODIMP nsEditor::CreateTxnForJoinNode(nsINode *aLeftNode,
nsINode *aRightNode,
NS_IMETHODIMP nsEditor::CreateTxnForJoinNode(nsIDOMNode *aLeftNode,
nsIDOMNode *aRightNode,
JoinElementTxn **aTxn)
{
NS_ENSURE_TRUE(aLeftNode && aRightNode, NS_ERROR_NULL_POINTER);
@ -4329,9 +4313,9 @@ nsEditor::DoAfterRedoTransaction()
IncrementModificationCount(1)));
}
NS_IMETHODIMP
nsEditor::CreateTxnForSetAttribute(Element *aElement,
const nsAString& aAttribute,
NS_IMETHODIMP
nsEditor::CreateTxnForSetAttribute(nsIDOMElement *aElement,
const nsAString& aAttribute,
const nsAString& aValue,
ChangeAttributeTxn ** aTxn)
{
@ -4349,8 +4333,8 @@ nsEditor::CreateTxnForSetAttribute(Element *aElement,
}
NS_IMETHODIMP
nsEditor::CreateTxnForRemoveAttribute(Element *aElement,
NS_IMETHODIMP
nsEditor::CreateTxnForRemoveAttribute(nsIDOMElement *aElement,
const nsAString& aAttribute,
ChangeAttributeTxn ** aTxn)
{
@ -4369,7 +4353,7 @@ nsEditor::CreateTxnForRemoveAttribute(Element *aElement,
NS_IMETHODIMP nsEditor::CreateTxnForCreateElement(const nsAString& aTag,
nsINode *aParent,
nsIDOMNode *aParent,
int32_t aPosition,
CreateElementTxn ** aTxn)
{
@ -4387,8 +4371,8 @@ NS_IMETHODIMP nsEditor::CreateTxnForCreateElement(const nsAString& aTag,
}
NS_IMETHODIMP nsEditor::CreateTxnForInsertElement(nsINode * aNode,
nsINode * aParent,
NS_IMETHODIMP nsEditor::CreateTxnForInsertElement(nsIDOMNode * aNode,
nsIDOMNode * aParent,
int32_t aPosition,
InsertElementTxn ** aTxn)
{

View File

@ -264,28 +264,28 @@ protected:
/** create a transaction for setting aAttribute to aValue on aElement
*/
NS_IMETHOD CreateTxnForSetAttribute(mozilla::dom::Element *aElement,
NS_IMETHOD CreateTxnForSetAttribute(nsIDOMElement *aElement,
const nsAString & aAttribute,
const nsAString & aValue,
ChangeAttributeTxn ** aTxn);
/** create a transaction for removing aAttribute on aElement
*/
NS_IMETHOD CreateTxnForRemoveAttribute(mozilla::dom::Element *aElement,
NS_IMETHOD CreateTxnForRemoveAttribute(nsIDOMElement *aElement,
const nsAString & aAttribute,
ChangeAttributeTxn ** aTxn);
/** create a transaction for creating a new child node of aParent of type aTag.
*/
NS_IMETHOD CreateTxnForCreateElement(const nsAString & aTag,
nsINode *aParent,
nsIDOMNode *aParent,
int32_t aPosition,
CreateElementTxn ** aTxn);
/** create a transaction for inserting aNode as a child of aParent.
*/
NS_IMETHOD CreateTxnForInsertElement(nsINode * aNode,
nsINode * aParent,
NS_IMETHOD CreateTxnForInsertElement(nsIDOMNode * aNode,
nsIDOMNode * aParent,
int32_t aOffset,
InsertElementTxn ** aTxn);
@ -350,12 +350,12 @@ protected:
EDirection aDirection,
DeleteTextTxn** aTxn);
NS_IMETHOD CreateTxnForSplitNode(nsINode *aNode,
NS_IMETHOD CreateTxnForSplitNode(nsIDOMNode *aNode,
uint32_t aOffset,
SplitElementTxn **aTxn);
NS_IMETHOD CreateTxnForJoinNode(nsINode *aLeftNode,
nsINode *aRightNode,
NS_IMETHOD CreateTxnForJoinNode(nsIDOMNode *aLeftNode,
nsIDOMNode *aRightNode,
JoinElementTxn **aTxn);
/**