Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/editor/libeditor/InsertTextTransaction.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 "InsertTextTransaction.h"
7
8
#include "mozilla/EditorBase.h"         // mEditorBase
9
#include "mozilla/SelectionState.h"     // RangeUpdater
10
#include "mozilla/dom/Selection.h"      // Selection local var
11
#include "mozilla/dom/Text.h"           // mTextNode
12
#include "nsAString.h"                  // nsAString parameter
13
#include "nsDebug.h"                    // for NS_ASSERTION, etc.
14
#include "nsError.h"                    // for NS_OK, etc.
15
#include "nsQueryObject.h"              // for do_QueryObject
16
17
namespace mozilla {
18
19
using namespace dom;
20
21
// static
22
already_AddRefed<InsertTextTransaction>
23
InsertTextTransaction::Create(EditorBase& aEditorBase,
24
                              const nsAString& aStringToInsert,
25
                              Text& aTextNode,
26
                              uint32_t aOffset)
27
0
{
28
0
  RefPtr<InsertTextTransaction> transaction =
29
0
    new InsertTextTransaction(aEditorBase, aStringToInsert, aTextNode, aOffset);
30
0
  return transaction.forget();
31
0
}
32
33
InsertTextTransaction::InsertTextTransaction(EditorBase& aEditorBase,
34
                                             const nsAString& aStringToInsert,
35
                                             Text& aTextNode,
36
                                             uint32_t aOffset)
37
  : mTextNode(&aTextNode)
38
  , mOffset(aOffset)
39
  , mStringToInsert(aStringToInsert)
40
  , mEditorBase(&aEditorBase)
41
0
{
42
0
}
43
44
InsertTextTransaction::~InsertTextTransaction()
45
0
{
46
0
}
47
48
NS_IMPL_CYCLE_COLLECTION_INHERITED(InsertTextTransaction, EditTransactionBase,
49
                                   mEditorBase,
50
                                   mTextNode)
51
52
NS_IMPL_ADDREF_INHERITED(InsertTextTransaction, EditTransactionBase)
53
NS_IMPL_RELEASE_INHERITED(InsertTextTransaction, EditTransactionBase)
54
0
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(InsertTextTransaction)
55
0
  NS_INTERFACE_MAP_ENTRY_CONCRETE(InsertTextTransaction)
56
0
NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
57
58
59
NS_IMETHODIMP
60
InsertTextTransaction::DoTransaction()
61
0
{
62
0
  if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mTextNode)) {
63
0
    return NS_ERROR_NOT_AVAILABLE;
64
0
  }
65
0
66
0
  ErrorResult rv;
67
0
  mTextNode->InsertData(mOffset, mStringToInsert, rv);
68
0
  if (NS_WARN_IF(rv.Failed())) {
69
0
    return rv.StealNSResult();
70
0
  }
71
0
72
0
  // Only set selection to insertion point if editor gives permission
73
0
  if (mEditorBase->AllowsTransactionsToChangeSelection()) {
74
0
    RefPtr<Selection> selection = mEditorBase->GetSelection();
75
0
    if (NS_WARN_IF(!selection)) {
76
0
      return NS_ERROR_FAILURE;
77
0
    }
78
0
    DebugOnly<nsresult> rv =
79
0
      selection->Collapse(mTextNode, mOffset + mStringToInsert.Length());
80
0
    NS_ASSERTION(NS_SUCCEEDED(rv),
81
0
                 "Selection could not be collapsed after insert");
82
0
  } else {
83
0
    // Do nothing - DOM Range gravity will adjust selection
84
0
  }
85
0
  // XXX Other transactions do not do this but its callers do.
86
0
  //     Why do this transaction do this by itself?
87
0
  mEditorBase->RangeUpdaterRef().
88
0
                 SelAdjInsertText(*mTextNode, mOffset, mStringToInsert);
89
0
90
0
  return NS_OK;
91
0
}
92
93
NS_IMETHODIMP
94
InsertTextTransaction::UndoTransaction()
95
0
{
96
0
  ErrorResult rv;
97
0
  mTextNode->DeleteData(mOffset, mStringToInsert.Length(), rv);
98
0
  return rv.StealNSResult();
99
0
}
100
101
NS_IMETHODIMP
102
InsertTextTransaction::Merge(nsITransaction* aTransaction,
103
                             bool* aDidMerge)
104
0
{
105
0
  if (!aTransaction || !aDidMerge) {
106
0
    return NS_OK;
107
0
  }
108
0
  // Set out param default value
109
0
  *aDidMerge = false;
110
0
111
0
  // If aTransaction is a InsertTextTransaction, and if the selection hasn't
112
0
  // changed, then absorb it.
113
0
  RefPtr<InsertTextTransaction> otherTransaction = do_QueryObject(aTransaction);
114
0
  if (otherTransaction && IsSequentialInsert(*otherTransaction)) {
115
0
    nsAutoString otherData;
116
0
    otherTransaction->GetData(otherData);
117
0
    mStringToInsert += otherData;
118
0
    *aDidMerge = true;
119
0
  }
120
0
121
0
  return NS_OK;
122
0
}
123
124
/* ============ private methods ================== */
125
126
void
127
InsertTextTransaction::GetData(nsString& aResult)
128
0
{
129
0
  aResult = mStringToInsert;
130
0
}
131
132
bool
133
InsertTextTransaction::IsSequentialInsert(
134
                         InsertTextTransaction& aOtherTransaction)
135
0
{
136
0
  return aOtherTransaction.mTextNode == mTextNode &&
137
0
         aOtherTransaction.mOffset == mOffset + mStringToInsert.Length();
138
0
}
139
140
} // namespace mozilla