1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #include "JoinNodeTransaction.h"
7 
8 #include "mozilla/EditorBase.h"         // for EditorBase
9 #include "nsAString.h"
10 #include "nsDebug.h"                    // for NS_ASSERTION, etc.
11 #include "nsError.h"                    // for NS_ERROR_NULL_POINTER, etc.
12 #include "nsIContent.h"                 // for nsIContent
13 #include "nsIDOMCharacterData.h"        // for nsIDOMCharacterData
14 #include "nsIEditor.h"                  // for EditorBase::IsModifiableNode
15 #include "nsISupportsImpl.h"            // for QueryInterface, etc.
16 
17 namespace mozilla {
18 
19 using namespace dom;
20 
JoinNodeTransaction(EditorBase & aEditorBase,nsINode & aLeftNode,nsINode & aRightNode)21 JoinNodeTransaction::JoinNodeTransaction(EditorBase& aEditorBase,
22                                          nsINode& aLeftNode,
23                                          nsINode& aRightNode)
24   : mEditorBase(aEditorBase)
25   , mLeftNode(&aLeftNode)
26   , mRightNode(&aRightNode)
27   , mOffset(0)
28 {
29 }
30 
NS_IMPL_CYCLE_COLLECTION_INHERITED(JoinNodeTransaction,EditTransactionBase,mLeftNode,mRightNode,mParent)31 NS_IMPL_CYCLE_COLLECTION_INHERITED(JoinNodeTransaction, EditTransactionBase,
32                                    mLeftNode,
33                                    mRightNode,
34                                    mParent)
35 
36 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(JoinNodeTransaction)
37 NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
38 
39 nsresult
40 JoinNodeTransaction::CheckValidity()
41 {
42   if (!mEditorBase.IsModifiableNode(mLeftNode->GetParentNode())) {
43     return NS_ERROR_FAILURE;
44   }
45   return NS_OK;
46 }
47 
48 // After DoTransaction() and RedoTransaction(), the left node is removed from
49 // the content tree and right node remains.
50 NS_IMETHODIMP
DoTransaction()51 JoinNodeTransaction::DoTransaction()
52 {
53   // Get the parent node
54   nsCOMPtr<nsINode> leftParent = mLeftNode->GetParentNode();
55   NS_ENSURE_TRUE(leftParent, NS_ERROR_NULL_POINTER);
56 
57   // Verify that mLeftNode and mRightNode have the same parent
58   if (leftParent != mRightNode->GetParentNode()) {
59     NS_ASSERTION(false, "Nodes do not have same parent");
60     return NS_ERROR_INVALID_ARG;
61   }
62 
63   // Set this instance's mParent.  Other methods will see a non-null mParent
64   // and know all is well
65   mParent = leftParent;
66   mOffset = mLeftNode->Length();
67 
68   return mEditorBase.JoinNodesImpl(mRightNode, mLeftNode, mParent);
69 }
70 
71 //XXX: What if instead of split, we just deleted the unneeded children of
72 //     mRight and re-inserted mLeft?
73 NS_IMETHODIMP
UndoTransaction()74 JoinNodeTransaction::UndoTransaction()
75 {
76   MOZ_ASSERT(mParent);
77 
78   // First, massage the existing node so it is in its post-split state
79   ErrorResult rv;
80   if (mRightNode->GetAsText()) {
81     rv = mRightNode->GetAsText()->DeleteData(0, mOffset);
82   } else {
83     nsCOMPtr<nsIContent> child = mRightNode->GetFirstChild();
84     for (uint32_t i = 0; i < mOffset; i++) {
85       if (rv.Failed()) {
86         return rv.StealNSResult();
87       }
88       if (!child) {
89         return NS_ERROR_NULL_POINTER;
90       }
91       nsCOMPtr<nsIContent> nextSibling = child->GetNextSibling();
92       mLeftNode->AppendChild(*child, rv);
93       child = nextSibling;
94     }
95   }
96   // Second, re-insert the left node into the tree
97   nsCOMPtr<nsINode> refNode = mRightNode;
98   mParent->InsertBefore(*mLeftNode, refNode, rv);
99   return rv.StealNSResult();
100 }
101 
102 NS_IMETHODIMP
GetTxnDescription(nsAString & aString)103 JoinNodeTransaction::GetTxnDescription(nsAString& aString)
104 {
105   aString.AssignLiteral("JoinNodeTransaction");
106   return NS_OK;
107 }
108 
109 } // namespace mozilla
110