nsresult TextEditRules::WillDeleteSelection(Selection* aSelection, nsIEditor::EDirection aCollapsedAction, bool* aCancel, bool* aHandled) { if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; } CANCEL_OPERATION_IF_READONLY_OR_DISABLED // initialize out param *aCancel = false; *aHandled = false; // if there is only bogus content, cancel the operation if (mBogusNode) { *aCancel = true; return NS_OK; } // If the current selection is empty (e.g the user presses backspace with // a collapsed selection), then we want to avoid sending the selectstart // event to the user, so we hide selection changes. However, we still // want to send a single selectionchange event to the document, so we // batch the selectionchange events, such that a single event fires after // the AutoHideSelectionChanges destructor has been run. SelectionBatcher selectionBatcher(aSelection); AutoHideSelectionChanges hideSelection(aSelection); nsAutoScriptBlocker scriptBlocker; if (IsPasswordEditor()) { NS_ENSURE_STATE(mTextEditor); nsresult rv = mTextEditor->ExtendSelectionForDelete(aSelection, &aCollapsedAction); NS_ENSURE_SUCCESS(rv, rv); // manage the password buffer uint32_t start, end; nsContentUtils::GetSelectionInTextControl(aSelection, mTextEditor->GetRoot(), start, end); if (LookAndFeel::GetEchoPassword()) { HideLastPWInput(); mLastStart = start; mLastLength = 0; if (mTimer) { mTimer->Cancel(); } } // Collapsed selection. if (end == start) { // Deleting back. if (nsIEditor::ePrevious == aCollapsedAction && start > 0) { mPasswordText.Cut(start-1, 1); } // Deleting forward. else if (nsIEditor::eNext == aCollapsedAction) { mPasswordText.Cut(start, 1); } // Otherwise nothing to do for this collapsed selection. } // Extended selection. else { mPasswordText.Cut(start, end-start); } } else { nsCOMPtr<nsIDOMNode> startNode; int32_t startOffset; nsresult rv = EditorBase::GetStartNodeAndOffset(aSelection, getter_AddRefs(startNode), &startOffset); NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE); bool bCollapsed; rv = aSelection->GetIsCollapsed(&bCollapsed); NS_ENSURE_SUCCESS(rv, rv); if (!bCollapsed) { return NS_OK; } // Test for distance between caret and text that will be deleted rv = CheckBidiLevelForDeletion(aSelection, startNode, startOffset, aCollapsedAction, aCancel); NS_ENSURE_SUCCESS(rv, rv); if (*aCancel) { return NS_OK; } NS_ENSURE_STATE(mTextEditor); rv = mTextEditor->ExtendSelectionForDelete(aSelection, &aCollapsedAction); NS_ENSURE_SUCCESS(rv, rv); } NS_ENSURE_STATE(mTextEditor); nsresult rv = mTextEditor->DeleteSelectionImpl(aCollapsedAction, nsIEditor::eStrip); NS_ENSURE_SUCCESS(rv, rv); *aHandled = true; ASSERT_PASSWORD_LENGTHS_EQUAL() return NS_OK; }
nsresult nsTextEditRules::WillDeleteSelection(nsISelection *aSelection, nsIEditor::EDirection aCollapsedAction, PRBool *aCancel, PRBool *aHandled) { if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; } CANCEL_OPERATION_IF_READONLY_OR_DISABLED // initialize out param *aCancel = PR_FALSE; *aHandled = PR_FALSE; // if there is only bogus content, cancel the operation if (mBogusNode) { *aCancel = PR_TRUE; return NS_OK; } nsresult res = NS_OK; if (IsPasswordEditor()) { res = mEditor->ExtendSelectionForDelete(aSelection, &aCollapsedAction); NS_ENSURE_SUCCESS(res, res); // manage the password buffer PRUint32 start, end; mEditor->GetTextSelectionOffsets(aSelection, start, end); NS_ENSURE_SUCCESS(res, res); nsCOMPtr<nsILookAndFeel> lookAndFeel = do_GetService(kLookAndFeelCID); if (lookAndFeel->GetEchoPassword()) { HideLastPWInput(); mLastStart = start; mLastLength = 0; if (mTimer) { mTimer->Cancel(); } } if (end == start) { // collapsed selection if (nsIEditor::ePrevious==aCollapsedAction && 0<start) { // del back mPasswordText.Cut(start-1, 1); } else if (nsIEditor::eNext==aCollapsedAction) { // del forward mPasswordText.Cut(start, 1); } // otherwise nothing to do for this collapsed selection } else { // extended selection mPasswordText.Cut(start, end-start); } } else { nsCOMPtr<nsIDOMNode> startNode; PRInt32 startOffset; res = mEditor->GetStartNodeAndOffset(aSelection, getter_AddRefs(startNode), &startOffset); NS_ENSURE_SUCCESS(res, res); NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE); PRBool bCollapsed; res = aSelection->GetIsCollapsed(&bCollapsed); NS_ENSURE_SUCCESS(res, res); if (!bCollapsed) return NS_OK; // Test for distance between caret and text that will be deleted res = CheckBidiLevelForDeletion(aSelection, startNode, startOffset, aCollapsedAction, aCancel); NS_ENSURE_SUCCESS(res, res); if (*aCancel) return NS_OK; res = mEditor->ExtendSelectionForDelete(aSelection, &aCollapsedAction); NS_ENSURE_SUCCESS(res, res); } res = mEditor->DeleteSelectionImpl(aCollapsedAction); NS_ENSURE_SUCCESS(res, res); *aHandled = PR_TRUE; ASSERT_PASSWORD_LENGTHS_EQUAL() return NS_OK; }