diff --git a/editor/libeditor/text/nsTextEditRules.cpp b/editor/libeditor/text/nsTextEditRules.cpp index d4042e6b5a70..0e1f2a6388dd 100644 --- a/editor/libeditor/text/nsTextEditRules.cpp +++ b/editor/libeditor/text/nsTextEditRules.cpp @@ -520,6 +520,38 @@ nsTextEditRules::DidInsertBreak(nsISelection *aSelection, nsresult aResult) return res; } +static inline already_AddRefed +GetTextNode(nsISelection *selection, nsEditor *editor) { + PRInt32 selOffset; + nsCOMPtr selNode; + nsresult res = editor->GetStartNodeAndOffset(selection, address_of(selNode), &selOffset); + if (NS_FAILED(res)) return nsnull; + if (!editor->IsTextNode(selNode)) { + // Get an nsINode from the nsIDOMNode + nsCOMPtr node = do_QueryInterface(selNode); + // if node is null, return it to indicate there's no text + if (!node) return nsnull; + // This should be the root node, walk the tree looking for text nodes + nsNodeIterator iter(node, nsIDOMNodeFilter::SHOW_TEXT, nsnull, PR_TRUE); + while (!editor->IsTextNode(selNode)) { + if (NS_FAILED(res = iter.NextNode(getter_AddRefs(selNode))) || !selNode) { + return nsnull; + } + } + } + return selNode.forget(); +} +#ifdef DEBUG +#define ASSERT_PASSWORD_LENGTHS_EQUAL() \ + if (mFlags & nsIPlaintextEditor::eEditorPasswordMask) { \ + PRInt32 txtLen; \ + mEditor->GetTextLength(&txtLen); \ + NS_ASSERTION(mPasswordText.Length() == txtLen, \ + "password length not equal to number of asterisks"); \ + } +#else +#define ASSERT_PASSWORD_LENGTHS_EQUAL() +#endif nsresult nsTextEditRules::WillInsertText(PRInt32 aAction, @@ -674,9 +706,7 @@ nsTextEditRules::WillInsertText(PRInt32 aAction, nsCOMPtr lookAndFeel = do_GetService(kLookAndFeelCID); if (lookAndFeel->GetEchoPassword() && !(mFlags & nsIPlaintextEditor::eEditorDontEchoPassword)) { - if (mPasswordText.Length() > outString->Length()) { - HideLastPWInput(); - } + HideLastPWInput(); mLastStart = start; mLastLength = outString->Length(); if (mTimer) @@ -863,6 +893,7 @@ nsTextEditRules::WillInsertText(PRInt32 aAction, selPrivate->SetInterlinePosition(endsWithLF); } } + ASSERT_PASSWORD_LENGTHS_EQUAL() return res; } @@ -943,6 +974,18 @@ nsTextEditRules::WillDeleteSelection(nsISelection *aSelection, PRUint32 start, end; mEditor->GetTextSelectionOffsets(aSelection, start, end); NS_ENSURE_SUCCESS(res, res); + nsCOMPtr 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 selNode; + if (!mLastLength) { + // Special case, we're trying to replace a range that no longer exists + return NS_OK; + } + + nsAutoString hiddenText; + FillBufWithPWChars(&hiddenText, mLastLength); + nsCOMPtr selection; - PRInt32 selOffset; PRUint32 start, end; nsresult res = mEditor->GetSelection(getter_AddRefs(selection)); if (NS_FAILED(res)) return res; res = mEditor->GetTextSelectionOffsets(selection, start, end); if (NS_FAILED(res)) return res; - res = mEditor->GetStartNodeAndOffset(selection, address_of(selNode), &selOffset); - if (NS_FAILED(res)) return res; - if (!mEditor->IsTextNode(selNode)) { - // Get an nsINode from the nsIDOMNode - nsCOMPtr node = do_QueryInterface(selNode); - // if node is null, return NS_OK because there's no text to hide - if (!node) return NS_OK; - // This should be the root node, walk the tree looking for text nodes - nsNodeIterator iter(node, nsIDOMNodeFilter::SHOW_TEXT, nsnull, PR_TRUE); - while (!mEditor->IsTextNode(selNode)) { - if (NS_FAILED(res = iter.NextNode(getter_AddRefs(selNode))) || - selNode == nsnull) { - return NS_SUCCEEDED(res) ? NS_ERROR_NULL_POINTER : res; - } - } - } + + nsCOMPtr selNode = GetTextNode(selection, mEditor); + if (!selNode) + return NS_OK; + nsCOMPtr nodeAsText(do_QueryInterface(selNode)); - if (!nodeAsText) return NS_ERROR_FAILURE; - nsAutoString hiddenText; - FillBufWithPWChars(&hiddenText, mLastLength); + if (!nodeAsText) + return NS_OK; + nodeAsText->ReplaceData(mLastStart, mLastLength, hiddenText); selection->Collapse(selNode, start); if (start != end)