summaryrefslogtreecommitdiffstats
path: root/editor/libeditor/InsertTextTransaction.cpp
blob: 0434b2dd5b3e83ddf42b58a03261a242617b803c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "InsertTextTransaction.h"

#include "mozilla/EditorBase.h"         // mEditorBase
#include "mozilla/SelectionState.h"     // RangeUpdater
#include "mozilla/dom/Selection.h"      // Selection local var
#include "mozilla/dom/Text.h"           // mTextNode
#include "nsAString.h"                  // nsAString parameter
#include "nsDebug.h"                    // for NS_ASSERTION, etc.
#include "nsError.h"                    // for NS_OK, etc.
#include "nsQueryObject.h"              // for do_QueryObject

namespace mozilla {

using namespace dom;

InsertTextTransaction::InsertTextTransaction(Text& aTextNode,
                                             uint32_t aOffset,
                                             const nsAString& aStringToInsert,
                                             EditorBase& aEditorBase,
                                             RangeUpdater* aRangeUpdater)
  : mTextNode(&aTextNode)
  , mOffset(aOffset)
  , mStringToInsert(aStringToInsert)
  , mEditorBase(&aEditorBase)
  , mRangeUpdater(aRangeUpdater)
{
}

InsertTextTransaction::~InsertTextTransaction()
{
}

NS_IMPL_CYCLE_COLLECTION_INHERITED(InsertTextTransaction, EditTransactionBase,
                                   mEditorBase,
                                   mTextNode)

NS_IMPL_ADDREF_INHERITED(InsertTextTransaction, EditTransactionBase)
NS_IMPL_RELEASE_INHERITED(InsertTextTransaction, EditTransactionBase)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(InsertTextTransaction)
  if (aIID.Equals(NS_GET_IID(InsertTextTransaction))) {
    foundInterface = static_cast<nsITransaction*>(this);
  } else
NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)


NS_IMETHODIMP
InsertTextTransaction::DoTransaction()
{
  if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mTextNode)) {
    return NS_ERROR_NOT_AVAILABLE;
  }

  nsresult rv = mTextNode->InsertData(mOffset, mStringToInsert);
  NS_ENSURE_SUCCESS(rv, rv);

  // Only set selection to insertion point if editor gives permission
  if (mEditorBase->GetShouldTxnSetSelection()) {
    RefPtr<Selection> selection = mEditorBase->GetSelection();
    NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
    DebugOnly<nsresult> rv =
      selection->Collapse(mTextNode, mOffset + mStringToInsert.Length());
    NS_ASSERTION(NS_SUCCEEDED(rv),
                 "Selection could not be collapsed after insert");
  } else {
    // Do nothing - DOM Range gravity will adjust selection
  }
  mRangeUpdater->SelAdjInsertText(*mTextNode, mOffset, mStringToInsert);

  return NS_OK;
}

NS_IMETHODIMP
InsertTextTransaction::UndoTransaction()
{
  return mTextNode->DeleteData(mOffset, mStringToInsert.Length());
}

NS_IMETHODIMP
InsertTextTransaction::Merge(nsITransaction* aTransaction,
                             bool* aDidMerge)
{
  if (!aTransaction || !aDidMerge) {
    return NS_OK;
  }
  // Set out param default value
  *aDidMerge = false;

  // If aTransaction is a InsertTextTransaction, and if the selection hasn't
  // changed, then absorb it.
  RefPtr<InsertTextTransaction> otherTransaction = do_QueryObject(aTransaction);
  if (otherTransaction && IsSequentialInsert(*otherTransaction)) {
    nsAutoString otherData;
    otherTransaction->GetData(otherData);
    mStringToInsert += otherData;
    *aDidMerge = true;
  }

  return NS_OK;
}

NS_IMETHODIMP
InsertTextTransaction::GetTxnDescription(nsAString& aString)
{
  aString.AssignLiteral("InsertTextTransaction: ");
  aString += mStringToInsert;
  return NS_OK;
}

/* ============ private methods ================== */

void
InsertTextTransaction::GetData(nsString& aResult)
{
  aResult = mStringToInsert;
}

bool
InsertTextTransaction::IsSequentialInsert(
                         InsertTextTransaction& aOtherTransaction)
{
  return aOtherTransaction.mTextNode == mTextNode &&
         aOtherTransaction.mOffset == mOffset + mStringToInsert.Length();
}

} // namespace mozilla