Bug 590640 part 5 - Delete empty wrappers when we delete the selection; r=ehsan

This commit is contained in:
Aryeh Gregor 2012-05-10 17:54:33 +03:00
parent 230fe5a06a
commit 1fffe1dc4d
26 changed files with 178 additions and 74 deletions

View File

@ -1498,7 +1498,7 @@ nsHyperTextAccessible::DeleteText(PRInt32 aStartPos, PRInt32 aEndPos)
nsresult rv = SetSelectionRange(aStartPos, aEndPos);
NS_ENSURE_SUCCESS(rv, rv);
return editor->DeleteSelection(nsIEditor::eNone);
return editor->DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip);
}
NS_IMETHODIMP

View File

@ -1863,7 +1863,7 @@ nsTextEditorState::SetValue(const nsAString& aValue, bool aUserInput)
plaintextEditor->SetMaxTextLength(-1);
if (insertValue.IsEmpty()) {
mEditor->DeleteSelection(nsIEditor::eNone);
mEditor->DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip);
} else {
plaintextEditor->InsertText(insertValue);
}

View File

@ -1641,22 +1641,12 @@
"[[\"stylewithcss\",\"false\"],[\"defaultparagraphseparator\",\"p\"],[\"delete\",\"\"]] \"<p style=color:blue>foo<div style=color:brown><p style=color:green>[]bar\" queryCommandIndeterm(\"defaultparagraphseparator\") after":true,
"[[\"stylewithcss\",\"false\"],[\"defaultparagraphseparator\",\"p\"],[\"delete\",\"\"]] \"<p style=color:blue>foo<div style=color:brown><p style=color:green>[]bar\" queryCommandState(\"defaultparagraphseparator\") after":true,
"[[\"stylewithcss\",\"false\"],[\"defaultparagraphseparator\",\"p\"],[\"delete\",\"\"]] \"<p style=color:blue>foo<div style=color:brown><p style=color:green>[]bar\" queryCommandValue(\"defaultparagraphseparator\") after":true,
"[[\"stylewithcss\",\"true\"],[\"delete\",\"\"]] \"<p>foo<span style=color:#aBcDeF>[bar]</span>baz\" compare innerHTML":true,
"[[\"stylewithcss\",\"false\"],[\"delete\",\"\"]] \"<p>foo<span style=color:#aBcDeF>[bar]</span>baz\" compare innerHTML":true,
"[[\"stylewithcss\",\"true\"],[\"delete\",\"\"]] \"<p>foo<span style=color:#aBcDeF>{bar}</span>baz\" compare innerHTML":true,
"[[\"stylewithcss\",\"false\"],[\"delete\",\"\"]] \"<p>foo<span style=color:#aBcDeF>{bar}</span>baz\" compare innerHTML":true,
"[[\"stylewithcss\",\"true\"],[\"delete\",\"\"]] \"<p>[foo<span style=color:#aBcDeF>bar]</span>baz\" compare innerHTML":true,
"[[\"stylewithcss\",\"false\"],[\"delete\",\"\"]] \"<p>[foo<span style=color:#aBcDeF>bar]</span>baz\" compare innerHTML":true,
"[[\"stylewithcss\",\"true\"],[\"delete\",\"\"]] \"<p>{foo<span style=color:#aBcDeF>bar}</span>baz\" compare innerHTML":true,
"[[\"stylewithcss\",\"false\"],[\"delete\",\"\"]] \"<p>{foo<span style=color:#aBcDeF>bar}</span>baz\" compare innerHTML":true,
"[[\"stylewithcss\",\"true\"],[\"delete\",\"\"]] \"<p>foo<span style=color:#aBcDeF>[bar</span>baz]\" compare innerHTML":true,
"[[\"stylewithcss\",\"false\"],[\"delete\",\"\"]] \"<p>foo<span style=color:#aBcDeF>[bar</span>baz]\" compare innerHTML":true,
"[[\"stylewithcss\",\"true\"],[\"delete\",\"\"]] \"<p>foo<span style=color:#aBcDeF>{bar</span>baz}\" compare innerHTML":true,
"[[\"stylewithcss\",\"false\"],[\"delete\",\"\"]] \"<p>foo<span style=color:#aBcDeF>{bar</span>baz}\" compare innerHTML":true,
"[[\"stylewithcss\",\"true\"],[\"delete\",\"\"]] \"<p>foo<span style=color:#aBcDeF>[bar</span><span style=color:#fEdCbA>baz]</span>quz\" compare innerHTML":true,
"[[\"stylewithcss\",\"false\"],[\"delete\",\"\"]] \"<p>foo<span style=color:#aBcDeF>[bar</span><span style=color:#fEdCbA>baz]</span>quz\" compare innerHTML":true,
"[[\"delete\",\"\"]] \"foo<span>[bar]</span>baz\" compare innerHTML":true,
"[[\"delete\",\"\"]] \"foo<span>{bar}</span>baz\" compare innerHTML":true,
"[[\"delete\",\"\"]] \"<p>foo</p><p>{bar</p>}<p>baz</p>\" compare innerHTML":true,
"[[\"defaultparagraphseparator\",\"div\"],[\"delete\",\"\"]] \"<p>foo</p>{<p>bar}</p><p>baz</p>\": execCommand(\"defaultparagraphseparator\", false, \"div\") return value":true,
"[[\"defaultparagraphseparator\",\"div\"],[\"delete\",\"\"]] \"<p>foo</p>{<p>bar}</p><p>baz</p>\" queryCommandIndeterm(\"defaultparagraphseparator\") before":true,
@ -1745,7 +1735,6 @@
"[[\"defaultparagraphseparator\",\"p\"],[\"delete\",\"\"]] \"<p><b>foo[bar</b><p>baz]quz\" queryCommandState(\"defaultparagraphseparator\") after":true,
"[[\"defaultparagraphseparator\",\"p\"],[\"delete\",\"\"]] \"<p><b>foo[bar</b><p>baz]quz\" queryCommandValue(\"defaultparagraphseparator\") after":true,
"[[\"defaultparagraphseparator\",\"div\"],[\"delete\",\"\"]] \"<div><p>foo[bar</div><p>baz]quz\": execCommand(\"defaultparagraphseparator\", false, \"div\") return value":true,
"[[\"defaultparagraphseparator\",\"div\"],[\"delete\",\"\"]] \"<div><p>foo[bar</div><p>baz]quz\" checks for modifications to non-editable content":true,
"[[\"defaultparagraphseparator\",\"div\"],[\"delete\",\"\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandIndeterm(\"defaultparagraphseparator\") before":true,
"[[\"defaultparagraphseparator\",\"div\"],[\"delete\",\"\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandState(\"defaultparagraphseparator\") before":true,
"[[\"defaultparagraphseparator\",\"div\"],[\"delete\",\"\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandValue(\"defaultparagraphseparator\") before":true,
@ -2076,7 +2065,6 @@
"[[\"delete\",\"\"]] \"<ol><li>fo[o</ol><ul><li>b]ar</ul>\" compare innerHTML":true,
"[[\"delete\",\"\"]] \"<b>foo [&nbsp;</b>bar]\" compare innerHTML":true,
"[[\"delete\",\"\"]] \"foo<b> [&nbsp;bar]</b>\" compare innerHTML":true,
"[[\"delete\",\"\"]] \"[foo<b>&nbsp;] bar</b>\" compare innerHTML":true,
"[[\"delete\",\"\"]] \"<p style=display:inline>fo[o<p style=display:inline>b]ar\" compare innerHTML":true,
"[[\"stylewithcss\",\"true\"],[\"delete\",\"\"]] \"<span style=display:block>fo[o</span><span style=display:block>b]ar</span>\" compare innerHTML":true,
"[[\"stylewithcss\",\"false\"],[\"delete\",\"\"]] \"<span style=display:block>fo[o</span><span style=display:block>b]ar</span>\" compare innerHTML":true,
@ -10858,8 +10846,6 @@
"[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p><b>foo[bar</b><p>baz]quz\" queryCommandState(\"defaultparagraphseparator\") after":true,
"[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p><b>foo[bar</b><p>baz]quz\" queryCommandValue(\"defaultparagraphseparator\") after":true,
"[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\": execCommand(\"defaultparagraphseparator\", false, \"div\") return value":true,
"[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\": execCommand(\"insertimage\", false, \"/img/lion.svg\") return value":true,
"[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\" compare innerHTML":true,
"[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandIndeterm(\"defaultparagraphseparator\") before":true,
"[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandState(\"defaultparagraphseparator\") before":true,
"[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandValue(\"defaultparagraphseparator\") before":true,
@ -10867,8 +10853,6 @@
"[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandState(\"defaultparagraphseparator\") after":true,
"[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandValue(\"defaultparagraphseparator\") after":true,
"[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\": execCommand(\"defaultparagraphseparator\", false, \"p\") return value":true,
"[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\": execCommand(\"insertimage\", false, \"/img/lion.svg\") return value":true,
"[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\" compare innerHTML":true,
"[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandIndeterm(\"defaultparagraphseparator\") before":true,
"[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandState(\"defaultparagraphseparator\") before":true,
"[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandValue(\"defaultparagraphseparator\") before":true,
@ -10876,8 +10860,6 @@
"[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandState(\"defaultparagraphseparator\") after":true,
"[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandValue(\"defaultparagraphseparator\") after":true,
"[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\": execCommand(\"defaultparagraphseparator\", false, \"div\") return value":true,
"[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\": execCommand(\"insertimage\", false, \"/img/lion.svg\") return value":true,
"[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\" compare innerHTML":true,
"[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\" queryCommandIndeterm(\"defaultparagraphseparator\") before":true,
"[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\" queryCommandState(\"defaultparagraphseparator\") before":true,
"[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\" queryCommandValue(\"defaultparagraphseparator\") before":true,
@ -10885,8 +10867,6 @@
"[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\" queryCommandState(\"defaultparagraphseparator\") after":true,
"[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\" queryCommandValue(\"defaultparagraphseparator\") after":true,
"[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\": execCommand(\"defaultparagraphseparator\", false, \"p\") return value":true,
"[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\": execCommand(\"insertimage\", false, \"/img/lion.svg\") return value":true,
"[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\" compare innerHTML":true,
"[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\" queryCommandIndeterm(\"defaultparagraphseparator\") before":true,
"[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\" queryCommandState(\"defaultparagraphseparator\") before":true,
"[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\" queryCommandValue(\"defaultparagraphseparator\") before":true,

View File

@ -55,12 +55,13 @@ interface nsIEditActionListener;
interface nsIInlineSpellChecker;
interface nsITransferable;
[scriptable, uuid(7861fe14-9977-413f-a893-3e1000c40817)]
[scriptable, uuid(7ad59e28-f3d5-4e14-8ea3-794ad4a86de3)]
interface nsIEditor : nsISupports
{
%{C++
typedef short EDirection;
typedef short EStripWrappers;
%}
const short eNone = 0;
const short eNext = 1;
@ -70,6 +71,9 @@ interface nsIEditor : nsISupports
const short eToBeginningOfLine = 5;
const short eToEndOfLine = 6;
const short eStrip = 0;
const short eNoStrip = 1;
readonly attribute nsISelection selection;
/**
@ -146,8 +150,12 @@ interface nsIEditor : nsISupports
* DeleteSelection removes all nodes in the current selection.
* @param aDir if eNext, delete to the right (for example, the DEL key)
* if ePrevious, delete to the left (for example, the BACKSPACE key)
* @param stripWrappers If eStrip, strip any empty inline elements left
* behind after the deletion; if eNoStrip, don't. If in
* doubt, pass eStrip -- eNoStrip is only for if you're
* about to insert text or similar right after.
*/
void deleteSelection(in short action);
void deleteSelection(in short action, in short stripWrappers);
/* ------------ Document info and file methods -------------- */

View File

@ -616,9 +616,10 @@ nsEditor::GetSelectionController(nsISelectionController **aSel)
NS_IMETHODIMP
nsEditor::DeleteSelection(EDirection aAction)
nsEditor::DeleteSelection(EDirection aAction, EStripWrappers aStripWrappers)
{
return DeleteSelectionImpl(aAction);
MOZ_ASSERT(aStripWrappers == eStrip || aStripWrappers == eNoStrip);
return DeleteSelectionImpl(aAction, aStripWrappers);
}
@ -634,6 +635,23 @@ nsEditor::GetSelection(nsISelection **aSelection)
return selcon->GetSelection(nsISelectionController::SELECTION_NORMAL, aSelection); // does an addref
}
nsTypedSelection*
nsEditor::GetTypedSelection()
{
nsCOMPtr<nsISelection> sel;
nsresult res = GetSelection(getter_AddRefs(sel));
NS_ENSURE_SUCCESS(res, nsnull);
nsCOMPtr<nsISelectionPrivate> selPrivate = do_QueryInterface(sel);
NS_ENSURE_TRUE(selPrivate, nsnull);
nsRefPtr<nsFrameSelection> frameSel;
res = selPrivate->GetFrameSelection(getter_AddRefs(frameSel));
NS_ENSURE_SUCCESS(res, nsnull);
return frameSel->GetSelection(nsISelectionController::SELECTION_NORMAL);
}
NS_IMETHODIMP
nsEditor::DoTransaction(nsITransaction *aTxn)
{
@ -4301,8 +4319,11 @@ nsEditor::GetShouldTxnSetSelection()
NS_IMETHODIMP
nsEditor::DeleteSelectionImpl(nsIEditor::EDirection aAction)
nsEditor::DeleteSelectionImpl(EDirection aAction,
EStripWrappers aStripWrappers)
{
MOZ_ASSERT(aStripWrappers == eStrip || aStripWrappers == eNoStrip);
nsCOMPtr<nsISelection>selection;
nsresult res = GetSelection(getter_AddRefs(selection));
NS_ENSURE_SUCCESS(res, res);
@ -4431,7 +4452,7 @@ nsEditor::DeleteSelectionAndPrepareToCreateNode(nsCOMPtr<nsIDOMNode> &parentSele
result = selection->GetIsCollapsed(&collapsed);
if (NS_SUCCEEDED(result) && !collapsed)
{
result = DeleteSelection(nsIEditor::eNone);
result = DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip);
if (NS_FAILED(result)) {
return result;
}
@ -5105,7 +5126,7 @@ nsEditor::HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent)
nativeKeyEvent->IsMeta()) {
return NS_OK;
}
DeleteSelection(nsIEditor::ePrevious);
DeleteSelection(nsIEditor::ePrevious, nsIEditor::eStrip);
aKeyEvent->PreventDefault(); // consumed
return NS_OK;
case nsIDOMKeyEvent::DOM_VK_DELETE:
@ -5116,7 +5137,7 @@ nsEditor::HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent)
nativeKeyEvent->IsAlt() || nativeKeyEvent->IsMeta()) {
return NS_OK;
}
DeleteSelection(nsIEditor::eNext);
DeleteSelection(nsIEditor::eNext, nsIEditor::eStrip);
aKeyEvent->PreventDefault(); // consumed
return NS_OK;
}

View File

@ -50,6 +50,8 @@
#include "nsIAtom.h"
#include "nsIDOMDocument.h"
#include "nsISelection.h"
#include "nsRange.h"
#include "nsTypedSelection.h"
#include "nsIDOMCharacterData.h"
#include "nsIPrivateTextRange.h"
#include "nsITransactionManager.h"
@ -203,7 +205,8 @@ public:
nsIDOMCharacterData *aTextNode,
PRInt32 aOffset,
bool aSuppressIME = false);
NS_IMETHOD DeleteSelectionImpl(EDirection aAction);
NS_IMETHOD DeleteSelectionImpl(EDirection aAction,
EStripWrappers aStripWrappers);
NS_IMETHOD DeleteSelectionAndCreateNode(const nsAString& aTag,
nsIDOMNode ** aNewNode);
@ -618,6 +621,7 @@ public:
#if DEBUG_JOE
static void DumpNode(nsIDOMNode *aNode, PRInt32 indent=0);
#endif
nsTypedSelection* GetTypedSelection();
// Helpers to add a node to the selection.
// Used by table cell selection methods

View File

@ -286,7 +286,7 @@ nsCutOrDeleteCommand::DoCommand(const char *aCommandName,
bool isCollapsed;
rv = selection->GetIsCollapsed(&isCollapsed);
if (NS_SUCCEEDED(rv) && isCollapsed)
return editor->DeleteSelection(nsIEditor::eNext);
return editor->DeleteSelection(nsIEditor::eNext, nsIEditor::eStrip);
}
return editor->Cut();
}
@ -384,7 +384,8 @@ nsCopyOrDeleteCommand::DoCommand(const char *aCommandName,
bool isCollapsed;
rv = selection->GetIsCollapsed(&isCollapsed);
if (NS_SUCCEEDED(rv) && isCollapsed)
return editor->DeleteSelection(nsIEditor::eNextWord);
return editor->DeleteSelection(nsIEditor::eNextWord,
nsIEditor::eStrip);
}
return editor->Copy();
}
@ -627,7 +628,7 @@ nsDeleteCommand::DoCommand(const char *aCommandName, nsISupports *aCommandRefCon
else if (!nsCRT::strcmp("cmd_deleteToEndOfLine",aCommandName))
deleteDir = nsIEditor::eToEndOfLine;
return editor->DeleteSelection(deleteDir);
return editor->DeleteSelection(deleteDir, nsIEditor::eStrip);
}
NS_IMETHODIMP

View File

@ -122,7 +122,7 @@ nsresult TextEditorTest::InitDoc()
{
nsresult result = mEditor->SelectAll();
TEST_RESULT(result);
result = mEditor->DeleteSelection(nsIEditor::eNext);
result = mEditor->DeleteSelection(nsIEditor::eNext, nsIEditor::eStrip);
TEST_RESULT(result);
return result;
}

View File

@ -206,7 +206,7 @@ NS_IMETHODIMP nsHTMLEditor::LoadHTML(const nsAString & aInputString)
// Delete Selection, but only if it isn't collapsed, see bug #106269
if (!isCollapsed)
{
rv = DeleteSelection(eNone);
rv = DeleteSelection(eNone, eStrip);
NS_ENSURE_SUCCESS(rv, rv);
}
@ -351,7 +351,7 @@ nsHTMLEditor::DoInsertHTMLWithContext(const nsAString & aInputString,
// Use an auto tracker so that our drop point is correctly
// positioned after the delete.
nsAutoTrackDOMPoint tracker(mRangeUpdater, &targetNode, &targetOffset);
rv = DeleteSelection(eNone);
rv = DeleteSelection(eNone, eStrip);
NS_ENSURE_SUCCESS(rv, rv);
}

View File

@ -616,7 +616,8 @@ nsHTMLEditRules::WillDoAction(nsISelection *aSelection,
case nsEditor::kOpInsertBreak:
return WillInsertBreak(aSelection, aCancel, aHandled);
case nsEditor::kOpDeleteSelection:
return WillDeleteSelection(aSelection, info->collapsedAction, aCancel, aHandled);
return WillDeleteSelection(aSelection, info->collapsedAction,
info->stripWrappers, aCancel, aHandled);
case nsEditor::kOpMakeList:
return WillMakeList(aSelection, info->blockType, info->entireList, info->bulletType, aCancel, aHandled);
case nsEditor::kOpIndent:
@ -1306,7 +1307,7 @@ nsHTMLEditRules::WillInsertText(nsEditor::OperationID aAction,
NS_ENSURE_SUCCESS(res, res);
if (!bCollapsed)
{
res = mHTMLEditor->DeleteSelection(nsIEditor::eNone);
res = mHTMLEditor->DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip);
NS_ENSURE_SUCCESS(res, res);
}
@ -1514,7 +1515,7 @@ nsHTMLEditRules::WillInsertBreak(nsISelection* aSelection,
nsresult res = aSelection->GetIsCollapsed(&bCollapsed);
NS_ENSURE_SUCCESS(res, res);
if (!bCollapsed) {
res = mHTMLEditor->DeleteSelection(nsIEditor::eNone);
res = mHTMLEditor->DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip);
NS_ENSURE_SUCCESS(res, res);
}
@ -1819,11 +1820,14 @@ nsHTMLEditRules::SplitMailCites(nsISelection *aSelection, bool aPlaintext, bool
nsresult
nsHTMLEditRules::WillDeleteSelection(nsISelection *aSelection,
nsIEditor::EDirection aAction,
bool *aCancel,
bool *aHandled)
nsHTMLEditRules::WillDeleteSelection(nsISelection* aSelection,
nsIEditor::EDirection aAction,
nsIEditor::EStripWrappers aStripWrappers,
bool* aCancel,
bool* aHandled)
{
MOZ_ASSERT(aStripWrappers == nsIEditor::eStrip ||
aStripWrappers == nsIEditor::eNoStrip);
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
// initialize out param
@ -1988,7 +1992,8 @@ nsHTMLEditRules::WillDeleteSelection(nsISelection *aSelection,
{
res = mHTMLEditor->DeleteNode(visNode);
NS_ENSURE_SUCCESS(res, res);
return WillDeleteSelection(aSelection, aAction, aCancel, aHandled);
return WillDeleteSelection(aSelection, aAction, aStripWrappers,
aCancel, aHandled);
}
// special handling for backspace when positioned after <hr>
@ -2292,14 +2297,17 @@ nsHTMLEditRules::WillDeleteSelection(nsISelection *aSelection,
}
{
// track end location of where we are deleting
nsAutoTrackDOMPoint tracker(mHTMLEditor->mRangeUpdater, address_of(endNode), &endOffset);
// track location of where we are deleting
nsAutoTrackDOMPoint startTracker(mHTMLEditor->mRangeUpdater,
address_of(startNode), &startOffset);
nsAutoTrackDOMPoint endTracker(mHTMLEditor->mRangeUpdater,
address_of(endNode), &endOffset);
// we are handling all ranged deletions directly now.
*aHandled = true;
if (endNode == startNode)
{
res = mHTMLEditor->DeleteSelectionImpl(aAction);
res = mHTMLEditor->DeleteSelectionImpl(aAction, aStripWrappers);
NS_ENSURE_SUCCESS(res, res);
}
else
@ -2339,7 +2347,7 @@ nsHTMLEditRules::WillDeleteSelection(nsISelection *aSelection,
// are endpoint block parents the same? use default deletion
if (leftParent == rightParent)
{
res = mHTMLEditor->DeleteSelectionImpl(aAction);
res = mHTMLEditor->DeleteSelectionImpl(aAction, aStripWrappers);
}
else
{
@ -2360,7 +2368,7 @@ nsHTMLEditRules::WillDeleteSelection(nsISelection *aSelection,
if (nsHTMLEditUtils::IsParagraph(leftParent))
{
// first delete the selection
res = mHTMLEditor->DeleteSelectionImpl(aAction);
res = mHTMLEditor->DeleteSelectionImpl(aAction, aStripWrappers);
NS_ENSURE_SUCCESS(res, res);
// then join para's, insert break
res = mHTMLEditor->JoinNodeDeep(leftParent,rightParent,address_of(selNode),&selOffset);
@ -2373,7 +2381,7 @@ nsHTMLEditRules::WillDeleteSelection(nsISelection *aSelection,
|| nsHTMLEditUtils::IsHeader(leftParent))
{
// first delete the selection
res = mHTMLEditor->DeleteSelectionImpl(aAction);
res = mHTMLEditor->DeleteSelectionImpl(aAction, aStripWrappers);
NS_ENSURE_SUCCESS(res, res);
// join blocks
res = mHTMLEditor->JoinNodeDeep(leftParent,rightParent,address_of(selNode),&selOffset);

View File

@ -152,8 +152,10 @@ protected:
nsresult StandardBreakImpl(nsIDOMNode *aNode, PRInt32 aOffset, nsISelection *aSelection);
nsresult DidInsertBreak(nsISelection *aSelection, nsresult aResult);
nsresult SplitMailCites(nsISelection *aSelection, bool aPlaintext, bool *aHandled);
nsresult WillDeleteSelection(nsISelection *aSelection, nsIEditor::EDirection aAction,
bool *aCancel, bool *aHandled);
nsresult WillDeleteSelection(nsISelection* aSelection,
nsIEditor::EDirection aAction,
nsIEditor::EStripWrappers aStripWrappers,
bool* aCancel, bool* aHandled);
nsresult DidDeleteSelection(nsISelection *aSelection,
nsIEditor::EDirection aDir,
nsresult aResult);

View File

@ -1757,6 +1757,15 @@ nsHTMLEditor::InsertElementAtSelection(nsIDOMElement* aElement, bool aDeleteSele
{
if (aDeleteSelection)
{
if (!IsBlockNode(aElement)) {
// E.g., inserting an image. In this case we don't need to delete any
// inline wrappers before we do the insertion. Otherwise we let
// DeleteSelectionAndPrepareToCreateNode do the deletion for us, which
// calls DeleteSelection with aStripWrappers = eStrip.
res = DeleteSelection(nsIEditor::eNone, nsIEditor::eNoStrip);
NS_ENSURE_SUCCESS(res, res);
}
nsCOMPtr<nsIDOMNode> tempNode;
PRInt32 tempOffset;
nsresult result = DeleteSelectionAndPrepareToCreateNode(tempNode,tempOffset);
@ -3453,6 +3462,66 @@ nsHTMLEditor::GetEmbeddedObjects(nsISupportsArray** aNodeList)
}
NS_IMETHODIMP
nsHTMLEditor::DeleteSelectionImpl(EDirection aAction,
EStripWrappers aStripWrappers)
{
MOZ_ASSERT(aStripWrappers == eStrip || aStripWrappers == eNoStrip);
nsresult res = nsEditor::DeleteSelectionImpl(aAction, aStripWrappers);
NS_ENSURE_SUCCESS(res, res);
// If we weren't asked to strip any wrappers, we're done.
if (aStripWrappers == eNoStrip) {
return NS_OK;
}
nsRefPtr<nsTypedSelection> typedSel = GetTypedSelection();
// Just checking that the selection itself is collapsed doesn't seem to work
// right in the multi-range case
NS_ENSURE_STATE(typedSel);
NS_ENSURE_STATE(typedSel->GetAnchorFocusRange());
NS_ENSURE_STATE(typedSel->GetAnchorFocusRange()->Collapsed());
nsCOMPtr<nsIContent> content = do_QueryInterface(typedSel->GetAnchorNode());
NS_ENSURE_STATE(content);
// Don't strip wrappers if this is the only wrapper in the block. Then we'll
// add a <br> later, so it won't be an empty wrapper in the end.
nsCOMPtr<nsIContent> blockParent = content;
while (!IsBlockNode(blockParent)) {
blockParent = blockParent->GetParent();
}
bool emptyBlockParent;
res = IsEmptyNode(blockParent, &emptyBlockParent);
NS_ENSURE_SUCCESS(res, res);
if (emptyBlockParent) {
return NS_OK;
}
if (content && !IsBlockNode(content) && !content->Length() &&
content->IsEditable() && content != content->GetEditingHost()) {
while (content->GetParent() && !IsBlockNode(content->GetParent()) &&
content->GetParent()->Length() == 1 &&
content->GetParent()->IsEditable() &&
content->GetParent() != content->GetEditingHost()) {
content = content->GetParent();
}
res = DeleteNode(content);
NS_ENSURE_SUCCESS(res, res);
}
return NS_OK;
}
nsresult
nsHTMLEditor::DeleteNode(nsINode* aNode)
{
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aNode);
return DeleteNode(node);
}
NS_IMETHODIMP
nsHTMLEditor::DeleteNode(nsIDOMNode* aNode)
{

View File

@ -327,6 +327,9 @@ public:
virtual bool NodesSameType(nsIDOMNode *aNode1, nsIDOMNode *aNode2);
NS_IMETHOD DeleteSelectionImpl(EDirection aAction,
EStripWrappers aStripWrappers);
nsresult DeleteNode(nsINode* aNode);
NS_IMETHODIMP DeleteNode(nsIDOMNode * aNode);
NS_IMETHODIMP DeleteText(nsIDOMCharacterData *aTextNode,
PRUint32 aOffset,

View File

@ -145,7 +145,8 @@ nsHTMLEditorLog::RemoveInlineProperty(nsIAtom *aProperty, const nsAString &aAttr
}
NS_IMETHODIMP
nsHTMLEditorLog::DeleteSelection(nsIEditor::EDirection aAction)
nsHTMLEditorLog::DeleteSelection(nsIEditor::EDirection aAction,
nsIEditor::EStripWrappers aStripWrappers)
{
nsAutoHTMLEditorLogLock logLock(this);
@ -159,7 +160,7 @@ nsHTMLEditorLog::DeleteSelection(nsIEditor::EDirection aAction)
Flush();
}
return nsHTMLEditor::DeleteSelection(aAction);
return nsHTMLEditor::DeleteSelection(aAction, aStripWrappers);
}
NS_IMETHODIMP

View File

@ -73,7 +73,8 @@ public:
const nsAString & aValue);
NS_IMETHOD SetParagraphFormat(const nsAString& aParagraphFormat);
NS_IMETHOD RemoveInlineProperty(nsIAtom *aProperty, const nsAString& aAttribute);
NS_IMETHOD DeleteSelection(nsIEditor::EDirection aAction);
NS_IMETHOD DeleteSelection(nsIEditor::EDirection aAction,
nsIEditor::EStripWrappers aStripWrappers);
NS_IMETHOD InsertText(const nsAString& aStringToInsert);
NS_IMETHOD InsertLineBreak();
NS_IMETHOD Undo(PRUint32 aCount);

View File

@ -749,7 +749,7 @@ nsHTMLEditor::DeleteTable2(nsIDOMElement *aTable, nsISelection *aSelection)
res = AppendNodeToSelectionAsRange(aTable);
NS_ENSURE_SUCCESS(res, res);
return DeleteSelection(nsIEditor::eNext);
return DeleteSelection(nsIEditor::eNext, nsIEditor::eStrip);
}
NS_IMETHODIMP

View File

@ -968,8 +968,6 @@ const knownFailures = {
"D-Proposed-CHAR-7_SC-dM": true,
"D-Proposed-CHAR-7_SC-body": true,
"D-Proposed-CHAR-7_SC-div": true,
"D-Proposed-B-1_SW-dM": true,
"D-Proposed-B-1_SW-body": true,
"D-Proposed-B-1_SW-div": true,
"D-Proposed-B-1_SL-dM": true,
"D-Proposed-B-1_SL-body": true,

View File

@ -108,11 +108,11 @@ function runTests() {
for (var i = 0; i < nodes.length; i++) {
var node = nodes[i];
node.focus();
is(checkBR(node), 0, "This node should not have any <br> element yet.");
is(checkBR(node), 0, node.textContent.trim() + ": This node should not have any <br> element yet.");
for (var j = 0; j < 3; j++) { // CARET_BEGIN|MIDDLE|END
split(node, j);
ok(checkBR(node) > 0, "Pressing [Return] should add (at least) one <br> element.");
is(getBlockCount(), count, "Pressing [Return] should not change the number of non-<br> elements.");
ok(checkBR(node) > 0, node.textContent.trim() + " " + j + ": Pressing [Return] should add (at least) one <br> element.");
is(getBlockCount(), count, node.textContent.trim() + " " + j + ": Pressing [Return] should not change the number of non-<br> elements.");
document.execCommand("Undo", false, null);
}
}

View File

@ -60,7 +60,7 @@ function runTests() {
select(document.querySelector("#test2 span"));
document.querySelector("#test2 [contenteditable]").focus();
synthesizeKey("VK_DELETE", {});
todo_is(document.querySelector("#test2 span"), null,
is(document.querySelector("#test2 span"), null,
"The <span> element should have been deleted.");
// done

View File

@ -109,7 +109,7 @@ nsresult nsPlaintextEditor::InsertTextAt(const nsAString &aStringToInsert,
// Use an auto tracker so that our drop point is correctly
// positioned after the delete.
nsAutoTrackDOMPoint tracker(mRangeUpdater, &targetNode, &targetOffset);
res = DeleteSelection(eNone);
res = DeleteSelection(eNone, eStrip);
NS_ENSURE_SUCCESS(res, res);
}

View File

@ -553,7 +553,7 @@ nsPlaintextEditor::InsertBR(nsCOMPtr<nsIDOMNode>* outBRNode)
NS_ENSURE_SUCCESS(res, res);
if (!bCollapsed)
{
res = DeleteSelection(nsIEditor::eNone);
res = DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip);
NS_ENSURE_SUCCESS(res, res);
}
nsCOMPtr<nsIDOMNode> selNode;
@ -739,8 +739,12 @@ nsPlaintextEditor::ExtendSelectionForDelete(nsISelection *aSelection,
return result;
}
NS_IMETHODIMP nsPlaintextEditor::DeleteSelection(nsIEditor::EDirection aAction)
nsresult
nsPlaintextEditor::DeleteSelection(EDirection aAction,
EStripWrappers aStripWrappers)
{
MOZ_ASSERT(aStripWrappers == eStrip || aStripWrappers == eNoStrip);
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
// Protect the edit rules object from dying
@ -785,12 +789,13 @@ NS_IMETHODIMP nsPlaintextEditor::DeleteSelection(nsIEditor::EDirection aAction)
nsTextRulesInfo ruleInfo(kOpDeleteSelection);
ruleInfo.collapsedAction = aAction;
ruleInfo.stripWrappers = aStripWrappers;
bool cancel, handled;
result = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
NS_ENSURE_SUCCESS(result, result);
if (!cancel && !handled)
{
result = DeleteSelectionImpl(aAction);
result = DeleteSelectionImpl(aAction, aStripWrappers);
}
if (!cancel)
{
@ -1291,7 +1296,7 @@ NS_IMETHODIMP nsPlaintextEditor::Cut()
HandlingTrustedAction trusted(this);
if (FireClipboardEvent(NS_CUT))
return DeleteSelection(eNone);
return DeleteSelection(eNone, eStrip);
return NS_OK;
}

View File

@ -102,7 +102,8 @@ public:
NS_IMETHOD GetDocumentIsEmpty(bool *aDocumentIsEmpty);
NS_IMETHOD GetIsDocumentEditable(bool *aIsDocumentEditable);
NS_IMETHOD DeleteSelection(EDirection aAction);
NS_IMETHOD DeleteSelection(EDirection aAction,
EStripWrappers aStripWrappers);
NS_IMETHOD SetDocumentCharacterSet(const nsACString & characterSet);

View File

@ -410,7 +410,7 @@ nsTextEditRules::WillInsertBreak(nsISelection *aSelection,
NS_ENSURE_SUCCESS(res, res);
if (!bCollapsed)
{
res = mEditor->DeleteSelection(nsIEditor::eNone);
res = mEditor->DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip);
NS_ENSURE_SUCCESS(res, res);
}
@ -638,7 +638,7 @@ nsTextEditRules::WillInsertText(nsEditor::OperationID aAction,
NS_ENSURE_SUCCESS(res, res);
if (!bCollapsed)
{
res = mEditor->DeleteSelection(nsIEditor::eNone);
res = mEditor->DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip);
NS_ENSURE_SUCCESS(res, res);
}
@ -878,7 +878,7 @@ nsTextEditRules::WillDeleteSelection(nsISelection *aSelection,
NS_ENSURE_SUCCESS(res, res);
}
res = mEditor->DeleteSelectionImpl(aCollapsedAction);
res = mEditor->DeleteSelectionImpl(aCollapsedAction, nsIEditor::eStrip);
NS_ENSURE_SUCCESS(res, res);
*aHandled = true;

View File

@ -275,6 +275,7 @@ class nsTextRulesInfo : public nsRulesInfo
outputFormat(0),
maxLength(-1),
collapsedAction(nsIEditor::eNext),
stripWrappers(nsIEditor::eStrip),
bOrdered(false),
entireList(false),
bulletType(0),
@ -293,6 +294,7 @@ class nsTextRulesInfo : public nsRulesInfo
// kDeleteSelection
nsIEditor::EDirection collapsedAction;
nsIEditor::EStripWrappers stripWrappers;
// kMakeList
bool bOrdered;

View File

@ -1377,7 +1377,7 @@ nsTextServicesDocument::DeleteSelection()
// Now delete the actual content!
result = editor->DeleteSelection(nsIEditor::ePrevious);
result = editor->DeleteSelection(nsIEditor::ePrevious, nsIEditor::eStrip);
if (NS_FAILED(result))
{

View File

@ -832,7 +832,7 @@ mozInlineSpellChecker::ReplaceWord(nsIDOMNode *aNode, PRInt32 aOffset,
NS_ENSURE_SUCCESS(res, res);
selection->RemoveAllRanges();
selection->AddRange(range);
editor->DeleteSelection(nsIEditor::eNone);
editor->DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip);
nsCOMPtr<nsIPlaintextEditor> textEditor(do_QueryReferent(mEditor));
textEditor->InsertText(newword);