mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 1156062 part 8 - Clean up nsHTMLEditRules::JoinBlocks; r=ehsan
--HG-- extra : rebase_source : 6b76252e1e569fd792829a0dbe31e8412cd2fa9d
This commit is contained in:
parent
79ea112b87
commit
2dc492c957
@ -2196,7 +2196,9 @@ nsHTMLEditRules::WillDeleteSelection(Selection* aSelection,
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
nsAutoTrackDOMPoint tracker(mHTMLEditor->mRangeUpdater,
|
||||
address_of(selPointNode), &selPointOffset);
|
||||
res = JoinBlocks(GetAsDOMNode(leftNode), GetAsDOMNode(rightNode),
|
||||
NS_ENSURE_STATE(leftNode && leftNode->IsContent() &&
|
||||
rightNode && rightNode->IsContent());
|
||||
res = JoinBlocks(*leftNode->AsContent(), *rightNode->AsContent(),
|
||||
aCancel);
|
||||
*aHandled = true;
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
@ -2246,7 +2248,8 @@ nsHTMLEditRules::WillDeleteSelection(Selection* aSelection,
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
nsAutoTrackDOMPoint tracker(mHTMLEditor->mRangeUpdater,
|
||||
address_of(selPointNode), &selPointOffset);
|
||||
res = JoinBlocks(GetAsDOMNode(leftNode), GetAsDOMNode(rightNode),
|
||||
NS_ENSURE_STATE(leftNode->IsContent() && rightNode->IsContent());
|
||||
res = JoinBlocks(*leftNode->AsContent(), *rightNode->AsContent(),
|
||||
aCancel);
|
||||
*aHandled = true;
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
@ -2432,8 +2435,7 @@ nsHTMLEditRules::WillDeleteSelection(Selection* aSelection,
|
||||
}
|
||||
|
||||
if (join) {
|
||||
res = JoinBlocks(GetAsDOMNode(leftParent), GetAsDOMNode(rightParent),
|
||||
aCancel);
|
||||
res = JoinBlocks(*leftParent, *rightParent, aCancel);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
}
|
||||
}
|
||||
@ -2562,209 +2564,186 @@ nsHTMLEditRules::GetGoodSelPointForNode(nsINode& aNode,
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************************************
|
||||
* JoinBlocks: this method is used to join two block elements. The right element is always joined
|
||||
* to the left element. If the elements are the same type and not nested within each other,
|
||||
* JoinNodesSmart is called (example, joining two list items together into one). If the elements
|
||||
* are not the same type, or one is a descendant of the other, we instead destroy the right block
|
||||
* placing its children into leftblock. DTD containment rules are followed throughout.
|
||||
* nsCOMPtr<nsIDOMNode> *aLeftBlock pointer to the left block
|
||||
* nsCOMPtr<nsIDOMNode> *aRightBlock pointer to the right block; will have contents moved to left block
|
||||
* bool *aCanceled return TRUE if we had to cancel operation
|
||||
*/
|
||||
/**
|
||||
* This method is used to join two block elements. The right element is always
|
||||
* joined to the left element. If the elements are the same type and not
|
||||
* nested within each other, JoinNodesSmart is called (example, joining two
|
||||
* list items together into one). If the elements are not the same type, or
|
||||
* one is a descendant of the other, we instead destroy the right block placing
|
||||
* its children into leftblock. DTD containment rules are followed throughout.
|
||||
*/
|
||||
nsresult
|
||||
nsHTMLEditRules::JoinBlocks(nsIDOMNode *aLeftNode,
|
||||
nsIDOMNode *aRightNode,
|
||||
bool *aCanceled)
|
||||
nsHTMLEditRules::JoinBlocks(nsIContent& aLeftNode, nsIContent& aRightNode,
|
||||
bool* aCanceled)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aLeftNode && aRightNode);
|
||||
MOZ_ASSERT(aCanceled);
|
||||
|
||||
nsCOMPtr<nsIDOMNode> aLeftBlock, aRightBlock;
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
nsCOMPtr<nsIEditor> kungFuDeathGrip(mHTMLEditor);
|
||||
|
||||
if (IsBlockNode(aLeftNode)) {
|
||||
aLeftBlock = aLeftNode;
|
||||
} else if (aLeftNode) {
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
aLeftBlock = mHTMLEditor->GetBlockNodeParent(aLeftNode);
|
||||
}
|
||||
nsCOMPtr<Element> leftBlock = mHTMLEditor->GetBlock(aLeftNode);
|
||||
nsCOMPtr<Element> rightBlock = mHTMLEditor->GetBlock(aRightNode);
|
||||
|
||||
if (IsBlockNode(aRightNode)) {
|
||||
aRightBlock = aRightNode;
|
||||
} else if (aRightNode) {
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
aRightBlock = mHTMLEditor->GetBlockNodeParent(aRightNode);
|
||||
}
|
||||
// Sanity checks
|
||||
NS_ENSURE_TRUE(leftBlock && rightBlock, NS_ERROR_NULL_POINTER);
|
||||
NS_ENSURE_STATE(leftBlock != rightBlock);
|
||||
|
||||
// sanity checks
|
||||
NS_ENSURE_TRUE(aLeftBlock && aRightBlock, NS_ERROR_NULL_POINTER);
|
||||
NS_ENSURE_STATE(aLeftBlock != aRightBlock);
|
||||
|
||||
if (nsHTMLEditUtils::IsTableElement(aLeftBlock) ||
|
||||
nsHTMLEditUtils::IsTableElement(aRightBlock)) {
|
||||
// do not try to merge table elements
|
||||
if (nsHTMLEditUtils::IsTableElement(leftBlock) ||
|
||||
nsHTMLEditUtils::IsTableElement(rightBlock)) {
|
||||
// Do not try to merge table elements
|
||||
*aCanceled = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// make sure we don't try to move thing's into HR's, which look like blocks but aren't containers
|
||||
if (nsHTMLEditUtils::IsHR(aLeftBlock)) {
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
nsCOMPtr<nsIDOMNode> realLeft = mHTMLEditor->GetBlockNodeParent(aLeftBlock);
|
||||
aLeftBlock = realLeft;
|
||||
// Make sure we don't try to move things into HR's, which look like blocks
|
||||
// but aren't containers
|
||||
if (leftBlock->IsHTMLElement(nsGkAtoms::hr)) {
|
||||
leftBlock = mHTMLEditor->GetBlockNodeParent(leftBlock);
|
||||
}
|
||||
if (nsHTMLEditUtils::IsHR(aRightBlock)) {
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
nsCOMPtr<nsIDOMNode> realRight = mHTMLEditor->GetBlockNodeParent(aRightBlock);
|
||||
aRightBlock = realRight;
|
||||
if (rightBlock->IsHTMLElement(nsGkAtoms::hr)) {
|
||||
rightBlock = mHTMLEditor->GetBlockNodeParent(rightBlock);
|
||||
}
|
||||
NS_ENSURE_STATE(aLeftBlock && aRightBlock);
|
||||
NS_ENSURE_STATE(leftBlock && rightBlock);
|
||||
|
||||
// bail if both blocks the same
|
||||
if (aLeftBlock == aRightBlock) {
|
||||
// Bail if both blocks the same
|
||||
if (leftBlock == rightBlock) {
|
||||
*aCanceled = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Joining a list item to its parent is a NOP.
|
||||
if (nsHTMLEditUtils::IsList(aLeftBlock) &&
|
||||
nsHTMLEditUtils::IsListItem(aRightBlock)) {
|
||||
nsCOMPtr<nsIDOMNode> rightParent;
|
||||
aRightBlock->GetParentNode(getter_AddRefs(rightParent));
|
||||
if (rightParent == aLeftBlock) {
|
||||
return NS_OK;
|
||||
}
|
||||
if (nsHTMLEditUtils::IsList(leftBlock) &&
|
||||
nsHTMLEditUtils::IsListItem(rightBlock) &&
|
||||
rightBlock->GetParentNode() == leftBlock) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// special rule here: if we are trying to join list items, and they are in different lists,
|
||||
// join the lists instead.
|
||||
bool bMergeLists = false;
|
||||
// Special rule here: if we are trying to join list items, and they are in
|
||||
// different lists, join the lists instead.
|
||||
bool mergeLists = false;
|
||||
nsIAtom* existingList = nsGkAtoms::_empty;
|
||||
int32_t theOffset;
|
||||
nsCOMPtr<nsIDOMNode> leftList, rightList;
|
||||
if (nsHTMLEditUtils::IsListItem(aLeftBlock) &&
|
||||
nsHTMLEditUtils::IsListItem(aRightBlock)) {
|
||||
aLeftBlock->GetParentNode(getter_AddRefs(leftList));
|
||||
aRightBlock->GetParentNode(getter_AddRefs(rightList));
|
||||
if (leftList && rightList && (leftList!=rightList))
|
||||
{
|
||||
// there are some special complications if the lists are descendants of
|
||||
// the other lists' items. Note that it is ok for them to be descendants
|
||||
// of the other lists themselves, which is the usual case for sublists
|
||||
// in our impllementation.
|
||||
if (!nsEditorUtils::IsDescendantOf(leftList, aRightBlock, &theOffset) &&
|
||||
!nsEditorUtils::IsDescendantOf(rightList, aLeftBlock, &theOffset))
|
||||
{
|
||||
aLeftBlock = leftList;
|
||||
aRightBlock = rightList;
|
||||
bMergeLists = true;
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
existingList = mHTMLEditor->GetTag(leftList);
|
||||
}
|
||||
int32_t offset;
|
||||
nsCOMPtr<Element> leftList, rightList;
|
||||
if (nsHTMLEditUtils::IsListItem(leftBlock) &&
|
||||
nsHTMLEditUtils::IsListItem(rightBlock)) {
|
||||
leftList = leftBlock->GetParentElement();
|
||||
rightList = rightBlock->GetParentElement();
|
||||
if (leftList && rightList && leftList != rightList &&
|
||||
!nsEditorUtils::IsDescendantOf(leftList, rightBlock, &offset) &&
|
||||
!nsEditorUtils::IsDescendantOf(rightList, leftBlock, &offset)) {
|
||||
// There are some special complications if the lists are descendants of
|
||||
// the other lists' items. Note that it is okay for them to be
|
||||
// descendants of the other lists themselves, which is the usual case for
|
||||
// sublists in our implementation.
|
||||
leftBlock = leftList;
|
||||
rightBlock = rightList;
|
||||
mergeLists = true;
|
||||
existingList = leftList->NodeInfo()->NameAtom();
|
||||
}
|
||||
}
|
||||
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
nsAutoTxnsConserveSelection dontSpazMySelection(mHTMLEditor);
|
||||
|
||||
nsresult res = NS_OK;
|
||||
int32_t rightOffset = 0;
|
||||
int32_t leftOffset = -1;
|
||||
int32_t rightOffset = 0;
|
||||
int32_t leftOffset = -1;
|
||||
|
||||
// theOffset below is where you find yourself in aRightBlock when you traverse upwards
|
||||
// from aLeftBlock
|
||||
if (nsEditorUtils::IsDescendantOf(aLeftBlock, aRightBlock, &rightOffset)) {
|
||||
// tricky case. left block is inside right block.
|
||||
// Do ws adjustment. This just destroys non-visible ws at boundaries we will be joining.
|
||||
// offset below is where you find yourself in rightBlock when you traverse
|
||||
// upwards from leftBlock
|
||||
if (nsEditorUtils::IsDescendantOf(leftBlock, rightBlock, &rightOffset)) {
|
||||
// Tricky case. Left block is inside right block. Do ws adjustment. This
|
||||
// just destroys non-visible ws at boundaries we will be joining.
|
||||
rightOffset++;
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
nsCOMPtr<nsINode> leftBlock(do_QueryInterface(aLeftBlock));
|
||||
res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor,
|
||||
nsWSRunObject::kBlockEnd,
|
||||
leftBlock);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
{
|
||||
// We can't just track rightBlock because it's an Element.
|
||||
nsCOMPtr<nsINode> trackingRightBlock(rightBlock);
|
||||
nsAutoTrackDOMPoint tracker(mHTMLEditor->mRangeUpdater,
|
||||
address_of(aRightBlock), &rightOffset);
|
||||
nsCOMPtr<nsINode> rightBlock(do_QueryInterface(aRightBlock));
|
||||
address_of(trackingRightBlock),
|
||||
&rightOffset);
|
||||
res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor,
|
||||
nsWSRunObject::kAfterBlock,
|
||||
rightBlock, rightOffset);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
if (trackingRightBlock->IsElement()) {
|
||||
rightBlock = trackingRightBlock->AsElement();
|
||||
} else {
|
||||
NS_ENSURE_STATE(trackingRightBlock->GetParentElement());
|
||||
rightBlock = trackingRightBlock->GetParentElement();
|
||||
}
|
||||
}
|
||||
// Do br adjustment.
|
||||
nsCOMPtr<nsIDOMNode> brNode;
|
||||
res = CheckForInvisibleBR(aLeftBlock, kBlockEnd, address_of(brNode));
|
||||
res = CheckForInvisibleBR(GetAsDOMNode(leftBlock), kBlockEnd,
|
||||
address_of(brNode));
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
if (bMergeLists)
|
||||
{
|
||||
// idea here is to take all children in rightList that are past
|
||||
// theOffset, and pull them into leftlist.
|
||||
nsCOMPtr<nsIContent> parent(do_QueryInterface(rightList));
|
||||
NS_ENSURE_TRUE(parent, NS_ERROR_NULL_POINTER);
|
||||
|
||||
nsIContent *child = parent->GetChildAt(theOffset);
|
||||
nsCOMPtr<nsINode> leftList_ = do_QueryInterface(leftList);
|
||||
NS_ENSURE_STATE(leftList_);
|
||||
while (child)
|
||||
{
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
res = mHTMLEditor->MoveNode(child, leftList_, -1);
|
||||
if (mergeLists) {
|
||||
// The idea here is to take all children in rightList that are past
|
||||
// offset, and pull them into leftlist.
|
||||
for (nsCOMPtr<nsIContent> child = rightList->GetChildAt(offset);
|
||||
child; child = rightList->GetChildAt(rightOffset)) {
|
||||
res = mHTMLEditor->MoveNode(child, leftList, -1);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
child = parent->GetChildAt(rightOffset);
|
||||
}
|
||||
} else {
|
||||
res = MoveBlock(GetAsDOMNode(leftBlock), GetAsDOMNode(rightBlock),
|
||||
leftOffset, rightOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = MoveBlock(aLeftBlock, aRightBlock, leftOffset, rightOffset);
|
||||
if (brNode) {
|
||||
mHTMLEditor->DeleteNode(brNode);
|
||||
}
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
if (brNode) mHTMLEditor->DeleteNode(brNode);
|
||||
// theOffset below is where you find yourself in aLeftBlock when you traverse upwards
|
||||
// from aRightBlock
|
||||
} else if (nsEditorUtils::IsDescendantOf(aRightBlock, aLeftBlock, &leftOffset)) {
|
||||
// tricky case. right block is inside left block.
|
||||
// Do ws adjustment. This just destroys non-visible ws at boundaries we will be joining.
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
nsCOMPtr<nsINode> rightBlock(do_QueryInterface(aRightBlock));
|
||||
// Offset below is where you find yourself in leftBlock when you traverse
|
||||
// upwards from rightBlock
|
||||
} else if (nsEditorUtils::IsDescendantOf(rightBlock, leftBlock,
|
||||
&leftOffset)) {
|
||||
// Tricky case. Right block is inside left block. Do ws adjustment. This
|
||||
// just destroys non-visible ws at boundaries we will be joining.
|
||||
res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor,
|
||||
nsWSRunObject::kBlockStart,
|
||||
rightBlock);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
{
|
||||
// We can't just track leftBlock because it's an Element, so track
|
||||
// something else.
|
||||
nsCOMPtr<nsINode> trackingLeftBlock(leftBlock);
|
||||
nsAutoTrackDOMPoint tracker(mHTMLEditor->mRangeUpdater,
|
||||
address_of(aLeftBlock), &leftOffset);
|
||||
nsCOMPtr<nsINode> leftBlock(do_QueryInterface(aLeftBlock));
|
||||
address_of(trackingLeftBlock), &leftOffset);
|
||||
res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor,
|
||||
nsWSRunObject::kBeforeBlock,
|
||||
leftBlock, leftOffset);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
if (trackingLeftBlock->IsElement()) {
|
||||
leftBlock = trackingLeftBlock->AsElement();
|
||||
} else {
|
||||
NS_ENSURE_STATE(trackingLeftBlock->GetParentElement());
|
||||
leftBlock = trackingLeftBlock->GetParentElement();
|
||||
}
|
||||
}
|
||||
// Do br adjustment.
|
||||
nsCOMPtr<nsIDOMNode> brNode;
|
||||
res = CheckForInvisibleBR(aLeftBlock, kBeforeBlock, address_of(brNode),
|
||||
leftOffset);
|
||||
res = CheckForInvisibleBR(GetAsDOMNode(leftBlock), kBeforeBlock,
|
||||
address_of(brNode), leftOffset);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
if (bMergeLists)
|
||||
{
|
||||
res = MoveContents(rightList, leftList, &leftOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mergeLists) {
|
||||
res = MoveContents(GetAsDOMNode(rightList), GetAsDOMNode(leftList),
|
||||
&leftOffset);
|
||||
} else {
|
||||
// Left block is a parent of right block, and the parent of the previous
|
||||
// visible content. Right block is a child and contains the contents we
|
||||
// want to move.
|
||||
|
||||
int32_t previousContentOffset;
|
||||
nsCOMPtr<nsIDOMNode> previousContentParent;
|
||||
nsCOMPtr<nsINode> previousContentParent;
|
||||
|
||||
if (aLeftNode == aLeftBlock) {
|
||||
if (&aLeftNode == leftBlock) {
|
||||
// We are working with valid HTML, aLeftNode is a block node, and is
|
||||
// therefore allowed to contain aRightBlock. This is the simple case,
|
||||
// we will simply move the content in aRightBlock out of its block.
|
||||
previousContentParent = aLeftBlock;
|
||||
// therefore allowed to contain rightBlock. This is the simple case,
|
||||
// we will simply move the content in rightBlock out of its block.
|
||||
previousContentParent = leftBlock;
|
||||
previousContentOffset = leftOffset;
|
||||
} else {
|
||||
// We try to work as well as possible with HTML that's already invalid.
|
||||
@ -2777,8 +2756,9 @@ nsHTMLEditRules::JoinBlocks(nsIDOMNode *aLeftNode,
|
||||
// unexpected position. (see bug 200416) The new idea is to make the
|
||||
// moving content a sibling, next to the previous visible content.
|
||||
|
||||
previousContentParent =
|
||||
nsEditor::GetNodeLocation(aLeftNode, &previousContentOffset);
|
||||
previousContentParent = aLeftNode.GetParentNode();
|
||||
previousContentOffset = previousContentParent ?
|
||||
previousContentParent->IndexOf(&aLeftNode) : -1;
|
||||
|
||||
// We want to move our content just after the previous visible node.
|
||||
previousContentOffset++;
|
||||
@ -2787,69 +2767,73 @@ nsHTMLEditRules::JoinBlocks(nsIDOMNode *aLeftNode,
|
||||
// Because we don't want the moving content to receive the style of the
|
||||
// previous content, we split the previous content's style.
|
||||
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
nsCOMPtr<nsINode> editorRoot = mHTMLEditor->GetEditorRoot();
|
||||
if (!editorRoot || aLeftNode != editorRoot->AsDOMNode()) {
|
||||
nsCOMPtr<nsIDOMNode> splittedPreviousContent;
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
res = mHTMLEditor->SplitStyleAbovePoint(address_of(previousContentParent),
|
||||
nsCOMPtr<Element> editorRoot = mHTMLEditor->GetEditorRoot();
|
||||
if (!editorRoot || &aLeftNode != editorRoot) {
|
||||
nsCOMPtr<nsIDOMNode> previousContentParentDOM =
|
||||
GetAsDOMNode(previousContentParent);
|
||||
nsCOMPtr<nsIDOMNode> splittedPreviousContentDOM;
|
||||
res = mHTMLEditor->SplitStyleAbovePoint(address_of(previousContentParentDOM),
|
||||
&previousContentOffset,
|
||||
nullptr, nullptr, nullptr,
|
||||
address_of(splittedPreviousContent));
|
||||
address_of(splittedPreviousContentDOM));
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
previousContentParent = do_QueryInterface(previousContentParentDOM);
|
||||
NS_ENSURE_STATE(previousContentParent || !previousContentParentDOM);
|
||||
|
||||
if (splittedPreviousContent) {
|
||||
previousContentParent =
|
||||
nsEditor::GetNodeLocation(splittedPreviousContent,
|
||||
&previousContentOffset);
|
||||
if (splittedPreviousContentDOM) {
|
||||
nsCOMPtr<nsINode> splittedPreviousContent =
|
||||
do_QueryInterface(splittedPreviousContentDOM);
|
||||
NS_ENSURE_STATE(splittedPreviousContent ||
|
||||
!splittedPreviousContentDOM);
|
||||
previousContentParent = splittedPreviousContent->GetParentNode();
|
||||
previousContentOffset = previousContentParent ?
|
||||
previousContentParent->IndexOf(splittedPreviousContent) : -1;
|
||||
}
|
||||
}
|
||||
|
||||
res = MoveBlock(previousContentParent, aRightBlock,
|
||||
res = MoveBlock(GetAsDOMNode(previousContentParent),
|
||||
GetAsDOMNode(rightBlock),
|
||||
previousContentOffset, rightOffset);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
}
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
if (brNode) mHTMLEditor->DeleteNode(brNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
// normal case. blocks are siblings, or at least close enough to siblings. An example
|
||||
// of the latter is a <p>paragraph</p><ul><li>one<li>two<li>three</ul>. The first
|
||||
// li and the p are not true siblings, but we still want to join them if you backspace
|
||||
// from li into p.
|
||||
if (brNode) {
|
||||
mHTMLEditor->DeleteNode(brNode);
|
||||
}
|
||||
} else {
|
||||
// Normal case. Blocks are siblings, or at least close enough. An example
|
||||
// of the latter is <p>paragraph</p><ul><li>one<li>two<li>three</ul>. The
|
||||
// first li and the p are not true siblings, but we still want to join them
|
||||
// if you backspace from li into p.
|
||||
|
||||
// adjust whitespace at block boundaries
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
nsCOMPtr<Element> leftBlock(do_QueryInterface(aLeftBlock));
|
||||
nsCOMPtr<Element> rightBlock(do_QueryInterface(aRightBlock));
|
||||
// Adjust whitespace at block boundaries
|
||||
res = nsWSRunObject::PrepareToJoinBlocks(mHTMLEditor, leftBlock, rightBlock);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
// Do br adjustment.
|
||||
nsCOMPtr<nsIDOMNode> brNode;
|
||||
res = CheckForInvisibleBR(aLeftBlock, kBlockEnd, address_of(brNode));
|
||||
res = CheckForInvisibleBR(GetAsDOMNode(leftBlock), kBlockEnd,
|
||||
address_of(brNode));
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
if (bMergeLists || mHTMLEditor->NodesSameType(aLeftBlock, aRightBlock)) {
|
||||
// nodes are same type. merge them.
|
||||
if (mergeLists || leftBlock->NodeInfo()->NameAtom() ==
|
||||
rightBlock->NodeInfo()->NameAtom()) {
|
||||
// Nodes are same type. Merge them.
|
||||
::DOMPoint pt = JoinNodesSmart(*leftBlock, *rightBlock);
|
||||
if (pt.node && bMergeLists) {
|
||||
nsCOMPtr<nsIDOMNode> newBlock;
|
||||
res = ConvertListType(aRightBlock, address_of(newBlock),
|
||||
if (pt.node && mergeLists) {
|
||||
nsCOMPtr<Element> newBlock;
|
||||
res = ConvertListType(rightBlock, getter_AddRefs(newBlock),
|
||||
existingList, nsGkAtoms::li);
|
||||
}
|
||||
} else {
|
||||
// Nodes are dissimilar types.
|
||||
res = MoveBlock(GetAsDOMNode(leftBlock), GetAsDOMNode(rightBlock),
|
||||
leftOffset, rightOffset);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
}
|
||||
else
|
||||
{
|
||||
// nodes are disimilar types.
|
||||
res = MoveBlock(aLeftBlock, aRightBlock, leftOffset, rightOffset);
|
||||
}
|
||||
if (NS_SUCCEEDED(res) && brNode)
|
||||
{
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
if (brNode) {
|
||||
res = mHTMLEditor->DeleteNode(brNode);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
@ -152,7 +152,8 @@ protected:
|
||||
nsresult InsertBRIfNeeded(mozilla::dom::Selection* aSelection);
|
||||
::DOMPoint GetGoodSelPointForNode(nsINode& aNode,
|
||||
nsIEditor::EDirection aAction);
|
||||
nsresult JoinBlocks(nsIDOMNode *aLeftNode, nsIDOMNode *aRightNode, bool *aCanceled);
|
||||
nsresult JoinBlocks(nsIContent& aLeftNode, nsIContent& aRightNode,
|
||||
bool* aCanceled);
|
||||
nsresult MoveBlock(nsIDOMNode *aLeft, nsIDOMNode *aRight, int32_t aLeftOffset, int32_t aRightOffset);
|
||||
nsresult MoveNodeSmart(nsIDOMNode *aSource, nsIDOMNode *aDest, int32_t *aOffset);
|
||||
nsresult MoveContents(nsIDOMNode *aSource, nsIDOMNode *aDest, int32_t *aOffset);
|
||||
|
Loading…
Reference in New Issue
Block a user