diff --git a/editor/base/nsHTMLEditRules.cpp b/editor/base/nsHTMLEditRules.cpp
index eaf8492e7ff8..40062de34705 100644
--- a/editor/base/nsHTMLEditRules.cpp
+++ b/editor/base/nsHTMLEditRules.cpp
@@ -1320,8 +1320,6 @@ nsHTMLEditRules::WillDeleteSelection(nsISelection *aSelection,
// initialize out param
*aCancel = PR_FALSE;
*aHandled = PR_FALSE;
- nsCOMPtr selection(aSelection);
- nsCOMPtr selPriv(do_QueryInterface(selection));
// if there is only bogus content, cancel the operation
if (mBogusNode)
@@ -1342,13 +1340,15 @@ nsHTMLEditRules::WillDeleteSelection(nsISelection *aSelection,
// first check for table selection mode. If so,
// hand off to table editor.
- nsCOMPtr cell;
- res = mHTMLEditor->GetFirstSelectedCell(getter_AddRefs(cell), nsnull);
- if (NS_SUCCEEDED(res) && cell)
{
- res = mHTMLEditor->DeleteTableCellContents();
- *aHandled = PR_TRUE;
- return res;
+ nsCOMPtr cell;
+ res = mHTMLEditor->GetFirstSelectedCell(getter_AddRefs(cell), nsnull);
+ if (NS_SUCCEEDED(res) && cell)
+ {
+ res = mHTMLEditor->DeleteTableCellContents();
+ *aHandled = PR_TRUE;
+ return res;
+ }
}
res = mHTMLEditor->GetStartNodeAndOffset(aSelection, address_of(startNode), &startOffset);
@@ -1356,43 +1356,22 @@ nsHTMLEditRules::WillDeleteSelection(nsISelection *aSelection,
if (!startNode) return NS_ERROR_FAILURE;
// get the root element
- nsCOMPtr bodyElement;
nsCOMPtr bodyNode;
- res = mHTMLEditor->GetRootElement(getter_AddRefs(bodyElement));
- if (NS_FAILED(res)) return res;
- if (!bodyElement) return NS_ERROR_UNEXPECTED;
- bodyNode = do_QueryInterface(bodyElement);
+ {
+ nsCOMPtr bodyElement;
+ res = mHTMLEditor->GetRootElement(getter_AddRefs(bodyElement));
+ if (NS_FAILED(res)) return res;
+ if (!bodyElement) return NS_ERROR_UNEXPECTED;
+ bodyNode = do_QueryInterface(bodyElement);
+ }
if (bCollapsed)
{
// if we are inside an empty block, delete it.
- // Note: do NOT delete table elements this way.
- nsCOMPtr block;
- if (IsBlockNode(startNode))
- block = startNode;
- else
- block = mHTMLEditor->GetBlockNodeParent(startNode);
- PRBool bIsEmptyNode;
- if (block != bodyNode)
- {
- res = mHTMLEditor->IsEmptyNode(block, &bIsEmptyNode, PR_TRUE, PR_FALSE);
- if (NS_FAILED(res)) return res;
- if (bIsEmptyNode && !nsHTMLEditUtils::IsTableElement(startNode))
- {
- // adjust selection to be right after it
- nsCOMPtr blockParent;
- PRInt32 offset;
- res = nsEditor::GetNodeLocation(block, address_of(blockParent), &offset);
- if (NS_FAILED(res)) return res;
- if (!blockParent || offset < 0) return NS_ERROR_FAILURE;
- res = aSelection->Collapse(blockParent, offset+1);
- if (NS_FAILED(res)) return res;
- res = mHTMLEditor->DeleteNode(block);
- *aHandled = PR_TRUE;
- return res;
- }
- }
-
+ res = CheckForEmptyBlock(startNode, bodyNode, aSelection, aHandled);
+ if (NS_FAILED(res)) return res;
+ if (*aHandled) return NS_OK;
+
#ifdef IBMBIDI
// Test for distance between caret and text that will be deleted
res = CheckBidiLevelForDeletion(startNode, startOffset, aAction, aCancel);
@@ -1402,40 +1381,12 @@ nsHTMLEditRules::WillDeleteSelection(nsISelection *aSelection,
if (!bPlaintext)
{
- // gather up ws data here. We may be next to non-significant ws.
- nsWSRunObject wsObj(mHTMLEditor, startNode, startOffset);
- nsCOMPtr visNode;
- PRInt32 visOffset;
- PRInt16 wsType;
- if (aAction == nsIEditor::ePrevious)
- {
- res = wsObj.PriorVisibleNode(startNode, startOffset, address_of(visNode), &visOffset, &wsType);
- // note that visOffset is _after_ what we are about to delete.
- }
- else if (aAction == nsIEditor::eNext)
- {
- res = wsObj.NextVisibleNode(startNode, startOffset, address_of(visNode), &visOffset, &wsType);
- // note that visOffset is _before_ what we are about to delete.
- }
- if (NS_SUCCEEDED(res))
- {
- if (wsType==nsWSRunObject::eNormalWS)
- {
- // we found some visible ws to delete. Let ws code handle it.
- if (aAction == nsIEditor::ePrevious)
- res = wsObj.DeleteWSBackward();
- else if (aAction == nsIEditor::eNext)
- res = wsObj.DeleteWSForward();
- *aHandled = PR_TRUE;
- return res;
- }
- else if (visNode)
- {
- // reposition startNode and startOffset so that we skip over any non-significant ws
- startNode = visNode;
- startOffset = visOffset;
- }
- }
+ // Check for needed whitespace adjustments. If we need to delete
+ // just whitespace, that is handled here.
+ res = CheckForWhitespaceDeletion(address_of(startNode), &startOffset,
+ aAction, aHandled);
+ if (NS_FAILED(res)) return res;
+ if (*aHandled) return NS_OK;
}
// in a text node:
if (mHTMLEditor->IsTextNode(startNode))
@@ -1949,6 +1900,7 @@ nsHTMLEditRules::WillDeleteSelection(nsISelection *aSelection,
// table elements.
*aHandled = PR_TRUE;
nsCOMPtr enumerator;
+ nsCOMPtr selPriv(do_QueryInterface(aSelection));
res = selPriv->GetEnumerator(getter_AddRefs(enumerator));
if (NS_FAILED(res)) return res;
if (!enumerator) return NS_ERROR_UNEXPECTED;
@@ -3289,7 +3241,95 @@ nsHTMLEditRules::AlignBlockContents(nsIDOMNode *aNode, const nsAReadableString *
return res;
}
+///////////////////////////////////////////////////////////////////////////
+// CheckForEmptyBlock: Called by WillDeleteSelection to detect and handle
+// case of deleting from inside an empty block.
+//
+nsresult
+nsHTMLEditRules::CheckForEmptyBlock(nsIDOMNode *aStartNode,
+ nsIDOMNode *aBodyNode,
+ nsISelection *aSelection,
+ PRBool *aHandled)
+{
+ // if we are inside an empty block, delete it.
+ // Note: do NOT delete table elements this way.
+ nsresult res = NS_OK;
+ nsCOMPtr block;
+ if (IsBlockNode(aStartNode))
+ block = aStartNode;
+ else
+ block = mHTMLEditor->GetBlockNodeParent(aStartNode);
+ PRBool bIsEmptyNode;
+ if (block != aBodyNode)
+ {
+ res = mHTMLEditor->IsEmptyNode(block, &bIsEmptyNode, PR_TRUE, PR_FALSE);
+ if (NS_FAILED(res)) return res;
+ if (bIsEmptyNode && !nsHTMLEditUtils::IsTableElement(aStartNode))
+ {
+ // adjust selection to be right after it
+ nsCOMPtr blockParent;
+ PRInt32 offset;
+ res = nsEditor::GetNodeLocation(block, address_of(blockParent), &offset);
+ if (NS_FAILED(res)) return res;
+ if (!blockParent || offset < 0) return NS_ERROR_FAILURE;
+ res = aSelection->Collapse(blockParent, offset+1);
+ if (NS_FAILED(res)) return res;
+ res = mHTMLEditor->DeleteNode(block);
+ *aHandled = PR_TRUE;
+ }
+ }
+ return res;
+}
+///////////////////////////////////////////////////////////////////////////
+// CheckForWhitespaceDeletion: Called by WillDeleteSelection to detect and handle
+// case of deleting whitespace. If we need to skip over
+// whitespace, visNode and visOffset are updated to new
+// location to handle deletion.
+//
+nsresult
+nsHTMLEditRules::CheckForWhitespaceDeletion(nsCOMPtr *ioStartNode,
+ PRInt32 *ioStartOffset,
+ PRInt32 aAction,
+ PRBool *aHandled)
+{
+ nsresult res = NS_OK;
+ // gather up ws data here. We may be next to non-significant ws.
+ nsWSRunObject wsObj(mHTMLEditor, *ioStartNode, *ioStartOffset);
+ nsCOMPtr visNode;
+ PRInt32 visOffset;
+ PRInt16 wsType;
+ if (aAction == nsIEditor::ePrevious)
+ {
+ res = wsObj.PriorVisibleNode(*ioStartNode, *ioStartOffset, address_of(visNode), &visOffset, &wsType);
+ // note that visOffset is _after_ what we are about to delete.
+ }
+ else if (aAction == nsIEditor::eNext)
+ {
+ res = wsObj.NextVisibleNode(*ioStartNode, *ioStartOffset, address_of(visNode), &visOffset, &wsType);
+ // note that visOffset is _before_ what we are about to delete.
+ }
+ if (NS_SUCCEEDED(res))
+ {
+ if (wsType==nsWSRunObject::eNormalWS)
+ {
+ // we found some visible ws to delete. Let ws code handle it.
+ if (aAction == nsIEditor::ePrevious)
+ res = wsObj.DeleteWSBackward();
+ else if (aAction == nsIEditor::eNext)
+ res = wsObj.DeleteWSForward();
+ *aHandled = PR_TRUE;
+ return res;
+ }
+ else if (visNode)
+ {
+ // reposition startNode and startOffset so that we skip over any non-significant ws
+ *ioStartNode = visNode;
+ *ioStartOffset = visOffset;
+ }
+ }
+ return res;
+}
///////////////////////////////////////////////////////////////////////////
// GetInnerContent: aList and aTbl allow the caller to specify what kind
diff --git a/editor/base/nsHTMLEditRules.h b/editor/base/nsHTMLEditRules.h
index a4237c4456c2..1af843c82dd3 100644
--- a/editor/base/nsHTMLEditRules.h
+++ b/editor/base/nsHTMLEditRules.h
@@ -128,6 +128,14 @@ protected:
PRBool *outIsEmptyBlock,
PRBool aMozBRDoesntCount = PR_FALSE,
PRBool aListItemsNotEmpty = PR_FALSE);
+ nsresult CheckForEmptyBlock(nsIDOMNode *aStartNode,
+ nsIDOMNode *aBodyNode,
+ nsISelection *aSelection,
+ PRBool *aHandled);
+ nsresult CheckForWhitespaceDeletion(nsCOMPtr *ioStartNode,
+ PRInt32 *ioStartOffset,
+ PRInt32 aAction,
+ PRBool *aHandled);
PRBool IsFirstNode(nsIDOMNode *aNode);
PRBool IsLastNode(nsIDOMNode *aNode);
PRBool AtStartOfBlock(nsIDOMNode *aNode, PRInt32 aOffset, nsIDOMNode *aBlock);
diff --git a/editor/libeditor/html/nsHTMLEditRules.cpp b/editor/libeditor/html/nsHTMLEditRules.cpp
index eaf8492e7ff8..40062de34705 100644
--- a/editor/libeditor/html/nsHTMLEditRules.cpp
+++ b/editor/libeditor/html/nsHTMLEditRules.cpp
@@ -1320,8 +1320,6 @@ nsHTMLEditRules::WillDeleteSelection(nsISelection *aSelection,
// initialize out param
*aCancel = PR_FALSE;
*aHandled = PR_FALSE;
- nsCOMPtr selection(aSelection);
- nsCOMPtr selPriv(do_QueryInterface(selection));
// if there is only bogus content, cancel the operation
if (mBogusNode)
@@ -1342,13 +1340,15 @@ nsHTMLEditRules::WillDeleteSelection(nsISelection *aSelection,
// first check for table selection mode. If so,
// hand off to table editor.
- nsCOMPtr cell;
- res = mHTMLEditor->GetFirstSelectedCell(getter_AddRefs(cell), nsnull);
- if (NS_SUCCEEDED(res) && cell)
{
- res = mHTMLEditor->DeleteTableCellContents();
- *aHandled = PR_TRUE;
- return res;
+ nsCOMPtr cell;
+ res = mHTMLEditor->GetFirstSelectedCell(getter_AddRefs(cell), nsnull);
+ if (NS_SUCCEEDED(res) && cell)
+ {
+ res = mHTMLEditor->DeleteTableCellContents();
+ *aHandled = PR_TRUE;
+ return res;
+ }
}
res = mHTMLEditor->GetStartNodeAndOffset(aSelection, address_of(startNode), &startOffset);
@@ -1356,43 +1356,22 @@ nsHTMLEditRules::WillDeleteSelection(nsISelection *aSelection,
if (!startNode) return NS_ERROR_FAILURE;
// get the root element
- nsCOMPtr bodyElement;
nsCOMPtr bodyNode;
- res = mHTMLEditor->GetRootElement(getter_AddRefs(bodyElement));
- if (NS_FAILED(res)) return res;
- if (!bodyElement) return NS_ERROR_UNEXPECTED;
- bodyNode = do_QueryInterface(bodyElement);
+ {
+ nsCOMPtr bodyElement;
+ res = mHTMLEditor->GetRootElement(getter_AddRefs(bodyElement));
+ if (NS_FAILED(res)) return res;
+ if (!bodyElement) return NS_ERROR_UNEXPECTED;
+ bodyNode = do_QueryInterface(bodyElement);
+ }
if (bCollapsed)
{
// if we are inside an empty block, delete it.
- // Note: do NOT delete table elements this way.
- nsCOMPtr block;
- if (IsBlockNode(startNode))
- block = startNode;
- else
- block = mHTMLEditor->GetBlockNodeParent(startNode);
- PRBool bIsEmptyNode;
- if (block != bodyNode)
- {
- res = mHTMLEditor->IsEmptyNode(block, &bIsEmptyNode, PR_TRUE, PR_FALSE);
- if (NS_FAILED(res)) return res;
- if (bIsEmptyNode && !nsHTMLEditUtils::IsTableElement(startNode))
- {
- // adjust selection to be right after it
- nsCOMPtr blockParent;
- PRInt32 offset;
- res = nsEditor::GetNodeLocation(block, address_of(blockParent), &offset);
- if (NS_FAILED(res)) return res;
- if (!blockParent || offset < 0) return NS_ERROR_FAILURE;
- res = aSelection->Collapse(blockParent, offset+1);
- if (NS_FAILED(res)) return res;
- res = mHTMLEditor->DeleteNode(block);
- *aHandled = PR_TRUE;
- return res;
- }
- }
-
+ res = CheckForEmptyBlock(startNode, bodyNode, aSelection, aHandled);
+ if (NS_FAILED(res)) return res;
+ if (*aHandled) return NS_OK;
+
#ifdef IBMBIDI
// Test for distance between caret and text that will be deleted
res = CheckBidiLevelForDeletion(startNode, startOffset, aAction, aCancel);
@@ -1402,40 +1381,12 @@ nsHTMLEditRules::WillDeleteSelection(nsISelection *aSelection,
if (!bPlaintext)
{
- // gather up ws data here. We may be next to non-significant ws.
- nsWSRunObject wsObj(mHTMLEditor, startNode, startOffset);
- nsCOMPtr visNode;
- PRInt32 visOffset;
- PRInt16 wsType;
- if (aAction == nsIEditor::ePrevious)
- {
- res = wsObj.PriorVisibleNode(startNode, startOffset, address_of(visNode), &visOffset, &wsType);
- // note that visOffset is _after_ what we are about to delete.
- }
- else if (aAction == nsIEditor::eNext)
- {
- res = wsObj.NextVisibleNode(startNode, startOffset, address_of(visNode), &visOffset, &wsType);
- // note that visOffset is _before_ what we are about to delete.
- }
- if (NS_SUCCEEDED(res))
- {
- if (wsType==nsWSRunObject::eNormalWS)
- {
- // we found some visible ws to delete. Let ws code handle it.
- if (aAction == nsIEditor::ePrevious)
- res = wsObj.DeleteWSBackward();
- else if (aAction == nsIEditor::eNext)
- res = wsObj.DeleteWSForward();
- *aHandled = PR_TRUE;
- return res;
- }
- else if (visNode)
- {
- // reposition startNode and startOffset so that we skip over any non-significant ws
- startNode = visNode;
- startOffset = visOffset;
- }
- }
+ // Check for needed whitespace adjustments. If we need to delete
+ // just whitespace, that is handled here.
+ res = CheckForWhitespaceDeletion(address_of(startNode), &startOffset,
+ aAction, aHandled);
+ if (NS_FAILED(res)) return res;
+ if (*aHandled) return NS_OK;
}
// in a text node:
if (mHTMLEditor->IsTextNode(startNode))
@@ -1949,6 +1900,7 @@ nsHTMLEditRules::WillDeleteSelection(nsISelection *aSelection,
// table elements.
*aHandled = PR_TRUE;
nsCOMPtr enumerator;
+ nsCOMPtr selPriv(do_QueryInterface(aSelection));
res = selPriv->GetEnumerator(getter_AddRefs(enumerator));
if (NS_FAILED(res)) return res;
if (!enumerator) return NS_ERROR_UNEXPECTED;
@@ -3289,7 +3241,95 @@ nsHTMLEditRules::AlignBlockContents(nsIDOMNode *aNode, const nsAReadableString *
return res;
}
+///////////////////////////////////////////////////////////////////////////
+// CheckForEmptyBlock: Called by WillDeleteSelection to detect and handle
+// case of deleting from inside an empty block.
+//
+nsresult
+nsHTMLEditRules::CheckForEmptyBlock(nsIDOMNode *aStartNode,
+ nsIDOMNode *aBodyNode,
+ nsISelection *aSelection,
+ PRBool *aHandled)
+{
+ // if we are inside an empty block, delete it.
+ // Note: do NOT delete table elements this way.
+ nsresult res = NS_OK;
+ nsCOMPtr block;
+ if (IsBlockNode(aStartNode))
+ block = aStartNode;
+ else
+ block = mHTMLEditor->GetBlockNodeParent(aStartNode);
+ PRBool bIsEmptyNode;
+ if (block != aBodyNode)
+ {
+ res = mHTMLEditor->IsEmptyNode(block, &bIsEmptyNode, PR_TRUE, PR_FALSE);
+ if (NS_FAILED(res)) return res;
+ if (bIsEmptyNode && !nsHTMLEditUtils::IsTableElement(aStartNode))
+ {
+ // adjust selection to be right after it
+ nsCOMPtr blockParent;
+ PRInt32 offset;
+ res = nsEditor::GetNodeLocation(block, address_of(blockParent), &offset);
+ if (NS_FAILED(res)) return res;
+ if (!blockParent || offset < 0) return NS_ERROR_FAILURE;
+ res = aSelection->Collapse(blockParent, offset+1);
+ if (NS_FAILED(res)) return res;
+ res = mHTMLEditor->DeleteNode(block);
+ *aHandled = PR_TRUE;
+ }
+ }
+ return res;
+}
+///////////////////////////////////////////////////////////////////////////
+// CheckForWhitespaceDeletion: Called by WillDeleteSelection to detect and handle
+// case of deleting whitespace. If we need to skip over
+// whitespace, visNode and visOffset are updated to new
+// location to handle deletion.
+//
+nsresult
+nsHTMLEditRules::CheckForWhitespaceDeletion(nsCOMPtr *ioStartNode,
+ PRInt32 *ioStartOffset,
+ PRInt32 aAction,
+ PRBool *aHandled)
+{
+ nsresult res = NS_OK;
+ // gather up ws data here. We may be next to non-significant ws.
+ nsWSRunObject wsObj(mHTMLEditor, *ioStartNode, *ioStartOffset);
+ nsCOMPtr visNode;
+ PRInt32 visOffset;
+ PRInt16 wsType;
+ if (aAction == nsIEditor::ePrevious)
+ {
+ res = wsObj.PriorVisibleNode(*ioStartNode, *ioStartOffset, address_of(visNode), &visOffset, &wsType);
+ // note that visOffset is _after_ what we are about to delete.
+ }
+ else if (aAction == nsIEditor::eNext)
+ {
+ res = wsObj.NextVisibleNode(*ioStartNode, *ioStartOffset, address_of(visNode), &visOffset, &wsType);
+ // note that visOffset is _before_ what we are about to delete.
+ }
+ if (NS_SUCCEEDED(res))
+ {
+ if (wsType==nsWSRunObject::eNormalWS)
+ {
+ // we found some visible ws to delete. Let ws code handle it.
+ if (aAction == nsIEditor::ePrevious)
+ res = wsObj.DeleteWSBackward();
+ else if (aAction == nsIEditor::eNext)
+ res = wsObj.DeleteWSForward();
+ *aHandled = PR_TRUE;
+ return res;
+ }
+ else if (visNode)
+ {
+ // reposition startNode and startOffset so that we skip over any non-significant ws
+ *ioStartNode = visNode;
+ *ioStartOffset = visOffset;
+ }
+ }
+ return res;
+}
///////////////////////////////////////////////////////////////////////////
// GetInnerContent: aList and aTbl allow the caller to specify what kind
diff --git a/editor/libeditor/html/nsHTMLEditRules.h b/editor/libeditor/html/nsHTMLEditRules.h
index a4237c4456c2..1af843c82dd3 100644
--- a/editor/libeditor/html/nsHTMLEditRules.h
+++ b/editor/libeditor/html/nsHTMLEditRules.h
@@ -128,6 +128,14 @@ protected:
PRBool *outIsEmptyBlock,
PRBool aMozBRDoesntCount = PR_FALSE,
PRBool aListItemsNotEmpty = PR_FALSE);
+ nsresult CheckForEmptyBlock(nsIDOMNode *aStartNode,
+ nsIDOMNode *aBodyNode,
+ nsISelection *aSelection,
+ PRBool *aHandled);
+ nsresult CheckForWhitespaceDeletion(nsCOMPtr *ioStartNode,
+ PRInt32 *ioStartOffset,
+ PRInt32 aAction,
+ PRBool *aHandled);
PRBool IsFirstNode(nsIDOMNode *aNode);
PRBool IsLastNode(nsIDOMNode *aNode);
PRBool AtStartOfBlock(nsIDOMNode *aNode, PRInt32 aOffset, nsIDOMNode *aBlock);