NS_IMETHODIMP CompositionTransaction::DoTransaction() { if (NS_WARN_IF(!mEditorBase)) { return NS_ERROR_NOT_INITIALIZED; } // Fail before making any changes if there's no selection controller nsCOMPtr<nsISelectionController> selCon; mEditorBase->GetSelectionController(getter_AddRefs(selCon)); NS_ENSURE_TRUE(selCon, NS_ERROR_NOT_INITIALIZED); // Advance caret: This requires the presentation shell to get the selection. if (mReplaceLength == 0) { ErrorResult rv; mTextNode->InsertData(mOffset, mStringToInsert, rv); if (NS_WARN_IF(rv.Failed())) { return rv.StealNSResult(); } mEditorBase->RangeUpdaterRef().SelAdjInsertText(*mTextNode, mOffset, mStringToInsert); } else { uint32_t replaceableLength = mTextNode->TextLength() - mOffset; ErrorResult rv; mTextNode->ReplaceData(mOffset, mReplaceLength, mStringToInsert, rv); if (NS_WARN_IF(rv.Failed())) { return rv.StealNSResult(); } mEditorBase->RangeUpdaterRef().SelAdjDeleteText(mTextNode, mOffset, mReplaceLength); mEditorBase->RangeUpdaterRef().SelAdjInsertText(*mTextNode, mOffset, mStringToInsert); // If IME text node is multiple node, ReplaceData doesn't remove all IME // text. So we need remove remained text into other text node. if (replaceableLength < mReplaceLength) { int32_t remainLength = mReplaceLength - replaceableLength; nsCOMPtr<nsINode> node = mTextNode->GetNextSibling(); while (node && node->IsText() && remainLength > 0) { Text* text = static_cast<Text*>(node.get()); uint32_t textLength = text->TextLength(); text->DeleteData(0, remainLength, IgnoreErrors()); mEditorBase->RangeUpdaterRef().SelAdjDeleteText(text, 0, remainLength); remainLength -= textLength; node = node->GetNextSibling(); } } } nsresult rv = SetSelectionForRanges(); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; }
NS_IMETHODIMP InsertTextTransaction::DoTransaction() { if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mTextNode)) { return NS_ERROR_NOT_AVAILABLE; } ErrorResult rv; mTextNode->InsertData(mOffset, mStringToInsert, rv); if (NS_WARN_IF(rv.Failed())) { return rv.StealNSResult(); } // Only set selection to insertion point if editor gives permission if (mEditorBase->GetShouldTxnSetSelection()) { RefPtr<Selection> selection = mEditorBase->GetSelection(); if (NS_WARN_IF(!selection)) { return NS_ERROR_FAILURE; } 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 } mEditorBase->RangeUpdaterRef(). SelAdjInsertText(*mTextNode, mOffset, mStringToInsert); return NS_OK; }
NS_IMETHODIMP DeleteTextTransaction::DoTransaction() { if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mCharData)) { return NS_ERROR_NOT_AVAILABLE; } // Get the text that we're about to delete ErrorResult err; mCharData->SubstringData(mOffset, mLengthToDelete, mDeletedText, err); if (NS_WARN_IF(err.Failed())) { return err.StealNSResult(); } mCharData->DeleteData(mOffset, mLengthToDelete, err); if (NS_WARN_IF(err.Failed())) { return err.StealNSResult(); } mEditorBase->RangeUpdaterRef(). SelAdjDeleteText(mCharData, mOffset, mLengthToDelete); if (!mEditorBase->AllowsTransactionsToChangeSelection()) { return NS_OK; } RefPtr<Selection> selection = mEditorBase->GetSelection(); if (NS_WARN_IF(!selection)) { return NS_ERROR_FAILURE; } ErrorResult error; selection->Collapse(EditorRawDOMPoint(mCharData, mOffset), error); if (NS_WARN_IF(error.Failed())) { return error.StealNSResult(); } return NS_OK; }