1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/editor/libeditor/base/InsertTextTxn.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,149 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include <stdio.h> // for printf 1.10 + 1.11 +#include "InsertTextTxn.h" 1.12 +#include "nsAString.h" 1.13 +#include "nsDebug.h" // for NS_ASSERTION, etc 1.14 +#include "nsError.h" // for NS_OK, etc 1.15 +#include "nsIDOMCharacterData.h" // for nsIDOMCharacterData 1.16 +#include "nsIEditor.h" // for nsIEditor 1.17 +#include "nsISelection.h" // for nsISelection 1.18 +#include "nsISupportsUtils.h" // for NS_ADDREF_THIS, NS_RELEASE 1.19 +#include "nsITransaction.h" // for nsITransaction 1.20 + 1.21 +InsertTextTxn::InsertTextTxn() 1.22 + : EditTxn() 1.23 +{ 1.24 +} 1.25 + 1.26 +NS_IMPL_CYCLE_COLLECTION_INHERITED(InsertTextTxn, EditTxn, 1.27 + mElement) 1.28 + 1.29 +NS_IMPL_ADDREF_INHERITED(InsertTextTxn, EditTxn) 1.30 +NS_IMPL_RELEASE_INHERITED(InsertTextTxn, EditTxn) 1.31 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(InsertTextTxn) 1.32 + if (aIID.Equals(InsertTextTxn::GetCID())) { 1.33 + *aInstancePtr = (void*)(InsertTextTxn*)this; 1.34 + NS_ADDREF_THIS(); 1.35 + return NS_OK; 1.36 + } else 1.37 +NS_INTERFACE_MAP_END_INHERITING(EditTxn) 1.38 + 1.39 +NS_IMETHODIMP InsertTextTxn::Init(nsIDOMCharacterData *aElement, 1.40 + uint32_t aOffset, 1.41 + const nsAString &aStringToInsert, 1.42 + nsIEditor *aEditor) 1.43 +{ 1.44 +#if 0 1.45 + nsAutoString text; 1.46 + aElement->GetData(text); 1.47 + printf("InsertTextTxn: Offset to insert at = %d. Text of the node to insert into:\n", aOffset); 1.48 + wprintf(text.get()); 1.49 + printf("\n"); 1.50 +#endif 1.51 + 1.52 + NS_ASSERTION(aElement && aEditor, "bad args"); 1.53 + NS_ENSURE_TRUE(aElement && aEditor, NS_ERROR_NULL_POINTER); 1.54 + 1.55 + mElement = do_QueryInterface(aElement); 1.56 + mOffset = aOffset; 1.57 + mStringToInsert = aStringToInsert; 1.58 + mEditor = aEditor; 1.59 + return NS_OK; 1.60 +} 1.61 + 1.62 +NS_IMETHODIMP InsertTextTxn::DoTransaction(void) 1.63 +{ 1.64 + NS_ASSERTION(mElement && mEditor, "bad state"); 1.65 + if (!mElement || !mEditor) { return NS_ERROR_NOT_INITIALIZED; } 1.66 + 1.67 + nsresult result = mElement->InsertData(mOffset, mStringToInsert); 1.68 + NS_ENSURE_SUCCESS(result, result); 1.69 + 1.70 + // only set selection to insertion point if editor gives permission 1.71 + bool bAdjustSelection; 1.72 + mEditor->ShouldTxnSetSelection(&bAdjustSelection); 1.73 + if (bAdjustSelection) 1.74 + { 1.75 + nsCOMPtr<nsISelection> selection; 1.76 + result = mEditor->GetSelection(getter_AddRefs(selection)); 1.77 + NS_ENSURE_SUCCESS(result, result); 1.78 + NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER); 1.79 + result = selection->Collapse(mElement, mOffset+mStringToInsert.Length()); 1.80 + NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after insert."); 1.81 + } 1.82 + else 1.83 + { 1.84 + // do nothing - dom range gravity will adjust selection 1.85 + } 1.86 + 1.87 + return result; 1.88 +} 1.89 + 1.90 +NS_IMETHODIMP InsertTextTxn::UndoTransaction(void) 1.91 +{ 1.92 + NS_ASSERTION(mElement && mEditor, "bad state"); 1.93 + if (!mElement || !mEditor) { return NS_ERROR_NOT_INITIALIZED; } 1.94 + 1.95 + uint32_t length = mStringToInsert.Length(); 1.96 + return mElement->DeleteData(mOffset, length); 1.97 +} 1.98 + 1.99 +NS_IMETHODIMP InsertTextTxn::Merge(nsITransaction *aTransaction, bool *aDidMerge) 1.100 +{ 1.101 + // set out param default value 1.102 + if (aDidMerge) 1.103 + *aDidMerge = false; 1.104 + nsresult result = NS_OK; 1.105 + if (aDidMerge && aTransaction) 1.106 + { 1.107 + // if aTransaction is a InsertTextTxn, and if the selection hasn't changed, 1.108 + // then absorb it 1.109 + InsertTextTxn *otherInsTxn = nullptr; 1.110 + aTransaction->QueryInterface(InsertTextTxn::GetCID(), (void **)&otherInsTxn); 1.111 + if (otherInsTxn) 1.112 + { 1.113 + if (IsSequentialInsert(otherInsTxn)) 1.114 + { 1.115 + nsAutoString otherData; 1.116 + otherInsTxn->GetData(otherData); 1.117 + mStringToInsert += otherData; 1.118 + *aDidMerge = true; 1.119 + } 1.120 + NS_RELEASE(otherInsTxn); 1.121 + } 1.122 + } 1.123 + return result; 1.124 +} 1.125 + 1.126 +NS_IMETHODIMP InsertTextTxn::GetTxnDescription(nsAString& aString) 1.127 +{ 1.128 + aString.AssignLiteral("InsertTextTxn: "); 1.129 + aString += mStringToInsert; 1.130 + return NS_OK; 1.131 +} 1.132 + 1.133 +/* ============ protected methods ================== */ 1.134 + 1.135 +NS_IMETHODIMP InsertTextTxn::GetData(nsString& aResult) 1.136 +{ 1.137 + aResult = mStringToInsert; 1.138 + return NS_OK; 1.139 +} 1.140 + 1.141 +bool InsertTextTxn::IsSequentialInsert(InsertTextTxn *aOtherTxn) 1.142 +{ 1.143 + NS_ASSERTION(aOtherTxn, "null param"); 1.144 + if (aOtherTxn && aOtherTxn->mElement == mElement) 1.145 + { 1.146 + // here, we need to compare offsets. 1.147 + int32_t length = mStringToInsert.Length(); 1.148 + if (aOtherTxn->mOffset == (mOffset + length)) 1.149 + return true; 1.150 + } 1.151 + return false; 1.152 +}