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 "InsertNodeTransaction.h"
7 
8 #include "mozilla/EditorBase.h"         // for EditorBase
9 
10 #include "mozilla/dom/Selection.h"      // for Selection
11 
12 #include "nsAString.h"
13 #include "nsDebug.h"                    // for NS_ENSURE_TRUE, etc.
14 #include "nsError.h"                    // for NS_ERROR_NULL_POINTER, etc.
15 #include "nsIContent.h"                 // for nsIContent
16 #include "nsMemory.h"                   // for nsMemory
17 #include "nsReadableUtils.h"            // for ToNewCString
18 #include "nsString.h"                   // for nsString
19 
20 namespace mozilla {
21 
22 using namespace dom;
23 
InsertNodeTransaction(nsIContent & aNode,nsINode & aParent,int32_t aOffset,EditorBase & aEditorBase)24 InsertNodeTransaction::InsertNodeTransaction(nsIContent& aNode,
25                                              nsINode& aParent,
26                                              int32_t aOffset,
27                                              EditorBase& aEditorBase)
28   : mNode(&aNode)
29   , mParent(&aParent)
30   , mOffset(aOffset)
31   , mEditorBase(aEditorBase)
32 {
33 }
34 
~InsertNodeTransaction()35 InsertNodeTransaction::~InsertNodeTransaction()
36 {
37 }
38 
NS_IMPL_CYCLE_COLLECTION_INHERITED(InsertNodeTransaction,EditTransactionBase,mNode,mParent)39 NS_IMPL_CYCLE_COLLECTION_INHERITED(InsertNodeTransaction, EditTransactionBase,
40                                    mNode,
41                                    mParent)
42 
43 NS_IMPL_ADDREF_INHERITED(InsertNodeTransaction, EditTransactionBase)
44 NS_IMPL_RELEASE_INHERITED(InsertNodeTransaction, EditTransactionBase)
45 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(InsertNodeTransaction)
46 NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
47 
48 NS_IMETHODIMP
49 InsertNodeTransaction::DoTransaction()
50 {
51   MOZ_ASSERT(mNode && mParent);
52 
53   uint32_t count = mParent->GetChildCount();
54   if (mOffset > static_cast<int32_t>(count) || mOffset == -1) {
55     // -1 is sentinel value meaning "append at end"
56     mOffset = count;
57   }
58 
59   // Note, it's ok for ref to be null. That means append.
60   nsCOMPtr<nsIContent> ref = mParent->GetChildAt(mOffset);
61 
62   mEditorBase.MarkNodeDirty(GetAsDOMNode(mNode));
63 
64   ErrorResult rv;
65   mParent->InsertBefore(*mNode, ref, rv);
66   NS_ENSURE_TRUE(!rv.Failed(), rv.StealNSResult());
67 
68   // Only set selection to insertion point if editor gives permission
69   if (mEditorBase.GetShouldTxnSetSelection()) {
70     RefPtr<Selection> selection = mEditorBase.GetSelection();
71     NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
72     // Place the selection just after the inserted element
73     selection->Collapse(mParent, mOffset + 1);
74   } else {
75     // Do nothing - DOM Range gravity will adjust selection
76   }
77   return NS_OK;
78 }
79 
80 NS_IMETHODIMP
UndoTransaction()81 InsertNodeTransaction::UndoTransaction()
82 {
83   MOZ_ASSERT(mNode && mParent);
84 
85   ErrorResult rv;
86   mParent->RemoveChild(*mNode, rv);
87   return rv.StealNSResult();
88 }
89 
90 NS_IMETHODIMP
GetTxnDescription(nsAString & aString)91 InsertNodeTransaction::GetTxnDescription(nsAString& aString)
92 {
93   aString.AssignLiteral("InsertNodeTransaction");
94   return NS_OK;
95 }
96 
97 } // namespace mozilla
98