Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/editor/libeditor/JoinNodeTransaction.cpp
Line
Count
Source (jump to first uncovered line)
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 "mozilla/dom/Text.h"
10
#include "nsAString.h"
11
#include "nsDebug.h"                    // for NS_ASSERTION, etc.
12
#include "nsError.h"                    // for NS_ERROR_NULL_POINTER, etc.
13
#include "nsIContent.h"                 // for nsIContent
14
#include "nsISupportsImpl.h"            // for QueryInterface, etc.
15
16
namespace mozilla {
17
18
using namespace dom;
19
20
// static
21
already_AddRefed<JoinNodeTransaction>
22
JoinNodeTransaction::MaybeCreate(EditorBase& aEditorBase,
23
                                 nsINode& aLeftNode,
24
                                 nsINode& aRightNode)
25
0
{
26
0
  RefPtr<JoinNodeTransaction> transaction =
27
0
    new JoinNodeTransaction(aEditorBase, aLeftNode, aRightNode);
28
0
  if (NS_WARN_IF(!transaction->CanDoIt())) {
29
0
    return nullptr;
30
0
  }
31
0
  return transaction.forget();
32
0
}
33
34
JoinNodeTransaction::JoinNodeTransaction(EditorBase& aEditorBase,
35
                                         nsINode& aLeftNode,
36
                                         nsINode& aRightNode)
37
  : mEditorBase(&aEditorBase)
38
  , mLeftNode(&aLeftNode)
39
  , mRightNode(&aRightNode)
40
  , mOffset(0)
41
0
{
42
0
}
43
44
NS_IMPL_CYCLE_COLLECTION_INHERITED(JoinNodeTransaction, EditTransactionBase,
45
                                   mEditorBase,
46
                                   mLeftNode,
47
                                   mRightNode,
48
                                   mParent)
49
50
0
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(JoinNodeTransaction)
51
0
NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
52
53
bool
54
JoinNodeTransaction::CanDoIt() const
55
0
{
56
0
  if (NS_WARN_IF(!mLeftNode) ||
57
0
      NS_WARN_IF(!mRightNode) ||
58
0
      NS_WARN_IF(!mEditorBase) ||
59
0
      !mLeftNode->GetParentNode()) {
60
0
    return false;
61
0
  }
62
0
  return mEditorBase->IsModifiableNode(*mLeftNode->GetParentNode());
63
0
}
64
65
// After DoTransaction() and RedoTransaction(), the left node is removed from
66
// the content tree and right node remains.
67
NS_IMETHODIMP
68
JoinNodeTransaction::DoTransaction()
69
0
{
70
0
  if (NS_WARN_IF(!mEditorBase) ||
71
0
      NS_WARN_IF(!mLeftNode) ||
72
0
      NS_WARN_IF(!mRightNode)) {
73
0
    return NS_ERROR_NOT_INITIALIZED;
74
0
  }
75
0
76
0
  // Get the parent node
77
0
  nsCOMPtr<nsINode> leftParent = mLeftNode->GetParentNode();
78
0
  NS_ENSURE_TRUE(leftParent, NS_ERROR_NULL_POINTER);
79
0
80
0
  // Verify that mLeftNode and mRightNode have the same parent
81
0
  if (leftParent != mRightNode->GetParentNode()) {
82
0
    NS_ASSERTION(false, "Nodes do not have same parent");
83
0
    return NS_ERROR_INVALID_ARG;
84
0
  }
85
0
86
0
  // Set this instance's mParent.  Other methods will see a non-null mParent
87
0
  // and know all is well
88
0
  mParent = leftParent;
89
0
  mOffset = mLeftNode->Length();
90
0
91
0
  return mEditorBase->DoJoinNodes(mRightNode, mLeftNode, mParent);
92
0
}
93
94
//XXX: What if instead of split, we just deleted the unneeded children of
95
//     mRight and re-inserted mLeft?
96
NS_IMETHODIMP
97
JoinNodeTransaction::UndoTransaction()
98
0
{
99
0
  if (NS_WARN_IF(!mParent) ||
100
0
      NS_WARN_IF(!mLeftNode) ||
101
0
      NS_WARN_IF(!mRightNode)) {
102
0
    return NS_ERROR_NOT_INITIALIZED;
103
0
  }
104
0
105
0
  // First, massage the existing node so it is in its post-split state
106
0
  ErrorResult rv;
107
0
  if (mRightNode->GetAsText()) {
108
0
    mRightNode->GetAsText()->DeleteData(0, mOffset, rv);
109
0
    if (rv.Failed()) {
110
0
      return rv.StealNSResult();
111
0
    }
112
0
  } else {
113
0
    nsCOMPtr<nsIContent> child = mRightNode->GetFirstChild();
114
0
    for (uint32_t i = 0; i < mOffset; i++) {
115
0
      if (rv.Failed()) {
116
0
        return rv.StealNSResult();
117
0
      }
118
0
      if (!child) {
119
0
        return NS_ERROR_NULL_POINTER;
120
0
      }
121
0
      nsCOMPtr<nsIContent> nextSibling = child->GetNextSibling();
122
0
      mLeftNode->AppendChild(*child, rv);
123
0
      child = nextSibling;
124
0
    }
125
0
  }
126
0
  // Second, re-insert the left node into the tree
127
0
  nsCOMPtr<nsINode> refNode = mRightNode;
128
0
  mParent->InsertBefore(*mLeftNode, refNode, rv);
129
0
  return rv.StealNSResult();
130
0
}
131
132
} // namespace mozilla