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/. */
6 #include "PlaceholderTxn.h"
8 #include "IMETextTxn.h"
10 #include "mozilla/dom/Selection.h"
11 #include "nsQueryObject.h"
13 using namespace mozilla
;
14 using namespace mozilla::dom
;
16 PlaceholderTxn::PlaceholderTxn() : EditAggregateTxn(),
27 PlaceholderTxn::~PlaceholderTxn()
31 NS_IMPL_CYCLE_COLLECTION_CLASS(PlaceholderTxn
)
33 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PlaceholderTxn
,
35 tmp
->mStartSel
->DoUnlink();
36 tmp
->mEndSel
.DoUnlink();
37 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
39 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PlaceholderTxn
,
41 tmp
->mStartSel
->DoTraverse(cb
);
42 tmp
->mEndSel
.DoTraverse(cb
);
43 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
45 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PlaceholderTxn
)
46 NS_INTERFACE_MAP_ENTRY(nsIAbsorbingTransaction
)
47 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference
)
48 NS_INTERFACE_MAP_END_INHERITING(EditAggregateTxn
)
50 NS_IMPL_ADDREF_INHERITED(PlaceholderTxn
, EditAggregateTxn
)
51 NS_IMPL_RELEASE_INHERITED(PlaceholderTxn
, EditAggregateTxn
)
54 PlaceholderTxn::Init(nsIAtom
* aName
, nsSelectionState
* aSelState
,
57 NS_ENSURE_TRUE(aEditor
&& aSelState
, NS_ERROR_NULL_POINTER
);
60 mStartSel
= aSelState
;
65 NS_IMETHODIMP
PlaceholderTxn::DoTransaction(void)
70 NS_IMETHODIMP
PlaceholderTxn::UndoTransaction(void)
73 nsresult res
= EditAggregateTxn::UndoTransaction();
74 NS_ENSURE_SUCCESS(res
, res
);
76 NS_ENSURE_TRUE(mStartSel
, NS_ERROR_NULL_POINTER
);
78 // now restore selection
79 RefPtr
<Selection
> selection
= mEditor
->GetSelection();
80 NS_ENSURE_TRUE(selection
, NS_ERROR_NULL_POINTER
);
81 return mStartSel
->RestoreSelection(selection
);
85 NS_IMETHODIMP
PlaceholderTxn::RedoTransaction(void)
88 nsresult res
= EditAggregateTxn::RedoTransaction();
89 NS_ENSURE_SUCCESS(res
, res
);
91 // now restore selection
92 RefPtr
<Selection
> selection
= mEditor
->GetSelection();
93 NS_ENSURE_TRUE(selection
, NS_ERROR_NULL_POINTER
);
94 return mEndSel
.RestoreSelection(selection
);
98 NS_IMETHODIMP
PlaceholderTxn::Merge(nsITransaction
*aTransaction
, bool *aDidMerge
)
100 NS_ENSURE_TRUE(aDidMerge
&& aTransaction
, NS_ERROR_NULL_POINTER
);
102 // set out param default value
107 NS_NOTREACHED("tried to merge into a placeholder that was in forwarding mode!");
108 return NS_ERROR_FAILURE
;
111 // check to see if aTransaction is one of the editor's
112 // private transactions. If not, we want to avoid merging
113 // the foreign transaction into our placeholder since we
114 // don't know what it does.
116 nsCOMPtr
<nsPIEditorTransaction
> pTxn
= do_QueryInterface(aTransaction
);
117 NS_ENSURE_TRUE(pTxn
, NS_OK
); // it's foreign so just bail!
119 EditTxn
*editTxn
= (EditTxn
*)aTransaction
; //XXX: hack, not safe! need nsIEditTransaction!
120 // determine if this incoming txn is a placeholder txn
121 nsCOMPtr
<nsIAbsorbingTransaction
> plcTxn
= do_QueryObject(editTxn
);
123 // we are absorbing all txn's if mAbsorb is lit.
126 RefPtr
<IMETextTxn
> otherTxn
= do_QueryObject(aTransaction
);
128 // special handling for IMETextTxn's: they need to merge with any previous
129 // IMETextTxn in this placeholder, if possible.
132 // this is the first IME txn in the placeholder
133 mIMETextTxn
=otherTxn
;
134 AppendChild(editTxn
);
139 mIMETextTxn
->Merge(otherTxn
, &didMerge
);
142 // it wouldn't merge. Earlier IME txn is already committed and will
143 // not absorb further IME txns. So just stack this one after it
144 // and remember it as a candidate for further merges.
145 mIMETextTxn
=otherTxn
;
146 AppendChild(editTxn
);
150 else if (!plcTxn
) // see bug 171243: just drop incoming placeholders on the floor.
151 { // their children will be swallowed by this preexisting one.
152 AppendChild(editTxn
);
155 // RememberEndingSelection();
156 // efficiency hack: no need to remember selection here, as we haven't yet
157 // finished the initial batch and we know we will be told when the batch ends.
158 // we can remeber the selection then.
161 { // merge typing or IME or deletion transactions if the selection matches
162 if (((mName
.get() == nsGkAtoms::TypingTxnName
) ||
163 (mName
.get() == nsGkAtoms::IMETxnName
) ||
164 (mName
.get() == nsGkAtoms::DeleteTxnName
))
167 nsCOMPtr
<nsIAbsorbingTransaction
> plcTxn
= do_QueryObject(editTxn
);
169 nsCOMPtr
<nsIAtom
> atom
;
170 plcTxn
->GetTxnName(getter_AddRefs(atom
));
171 if (atom
&& (atom
== mName
))
173 // check if start selection of next placeholder matches
174 // end selection of this placeholder
176 plcTxn
->StartSelectionEquals(&mEndSel
, &isSame
);
179 mAbsorb
= true; // we need to start absorbing again
180 plcTxn
->ForwardEndBatchTo(this);
181 // AppendChild(editTxn);
182 // see bug 171243: we don't need to merge placeholders
183 // into placeholders. We just reactivate merging in the pre-existing
184 // placeholder and drop the new one on the floor. The EndPlaceHolderBatch()
185 // call on the new placeholder will be forwarded to this older one.
186 RememberEndingSelection();
196 NS_IMETHODIMP
PlaceholderTxn::GetTxnDescription(nsAString
& aString
)
198 aString
.AssignLiteral("PlaceholderTxn: ");
203 mName
->ToString(name
);
210 NS_IMETHODIMP
PlaceholderTxn::GetTxnName(nsIAtom
**aName
)
212 return GetName(aName
);
215 NS_IMETHODIMP
PlaceholderTxn::StartSelectionEquals(nsSelectionState
*aSelState
, bool *aResult
)
217 // determine if starting selection matches the given selection state.
218 // note that we only care about collapsed selections.
219 NS_ENSURE_TRUE(aResult
&& aSelState
, NS_ERROR_NULL_POINTER
);
220 if (!mStartSel
->IsCollapsed() || !aSelState
->IsCollapsed())
225 *aResult
= mStartSel
->IsEqual(aSelState
);
229 NS_IMETHODIMP
PlaceholderTxn::EndPlaceHolderBatch()
235 nsCOMPtr
<nsIAbsorbingTransaction
> plcTxn
= do_QueryReferent(mForwarding
);
236 if (plcTxn
) plcTxn
->EndPlaceHolderBatch();
239 // remember our selection state.
240 return RememberEndingSelection();
243 NS_IMETHODIMP
PlaceholderTxn::ForwardEndBatchTo(nsIAbsorbingTransaction
*aForwardingAddress
)
245 mForwarding
= do_GetWeakReference(aForwardingAddress
);
249 NS_IMETHODIMP
PlaceholderTxn::Commit()
255 nsresult
PlaceholderTxn::RememberEndingSelection()
257 RefPtr
<Selection
> selection
= mEditor
->GetSelection();
258 NS_ENSURE_TRUE(selection
, NS_ERROR_NULL_POINTER
);
259 mEndSel
.SaveSelection(selection
);