Loading editor/libeditor/html/nsHTMLEditRules.cpp +130 −86 Original line number Diff line number Diff line Loading @@ -2072,7 +2072,7 @@ nsHTMLEditRules::WillDeleteSelection(Selection* aSelection, &otherOffset, &otherWSType); // first find the adjacent node in the block nsCOMPtr<nsIDOMNode> leafNode, leftNode, rightNode, leftParent, rightParent; nsCOMPtr<nsIDOMNode> leafNode, leftNode, rightNode; if (aAction == nsIEditor::ePrevious) { res = mHTMLEditor->GetLastEditableLeaf( visNode, address_of(leafNode)); Loading Loading @@ -2114,28 +2114,13 @@ nsHTMLEditRules::WillDeleteSelection(Selection* aSelection, // else we are joining content to block // find the relavent blocks if (IsBlockNode(leftNode)) leftParent = leftNode; else if (leftNode) leftParent = mHTMLEditor->GetBlockNodeParent(leftNode); if (IsBlockNode(rightNode)) rightParent = rightNode; else rightParent = mHTMLEditor->GetBlockNodeParent(rightNode); // sanity checks NS_ENSURE_TRUE(leftParent && rightParent, NS_ERROR_NULL_POINTER); if (leftParent == rightParent) return NS_ERROR_UNEXPECTED; // now join them nsCOMPtr<nsIDOMNode> selPointNode = startNode; int32_t selPointOffset = startOffset; { nsAutoTrackDOMPoint tracker(mHTMLEditor->mRangeUpdater, address_of(selPointNode), &selPointOffset); res = JoinBlocks(address_of(leftParent), address_of(rightParent), aCancel); res = JoinBlocks(leftNode, rightNode, aCancel); *aHandled = true; NS_ENSURE_SUCCESS(res, res); } aSelection->Collapse(selPointNode, selPointOffset); return res; Loading @@ -2151,7 +2136,7 @@ nsHTMLEditRules::WillDeleteSelection(Selection* aSelection, } // first find the relavent nodes nsCOMPtr<nsIDOMNode> leftNode, rightNode, leftParent, rightParent; nsCOMPtr<nsIDOMNode> leftNode, rightNode; if (aAction == nsIEditor::ePrevious) { res = mHTMLEditor->GetPriorHTMLNode(visNode, address_of(leftNode)); Loading @@ -2178,28 +2163,13 @@ nsHTMLEditRules::WillDeleteSelection(Selection* aSelection, return NS_OK; } // find the relavent blocks if (IsBlockNode(leftNode)) leftParent = leftNode; else leftParent = mHTMLEditor->GetBlockNodeParent(leftNode); if (IsBlockNode(rightNode)) rightParent = rightNode; else rightParent = mHTMLEditor->GetBlockNodeParent(rightNode); // sanity checks NS_ENSURE_TRUE(leftParent && rightParent, NS_ERROR_NULL_POINTER); if (leftParent == rightParent) return NS_ERROR_UNEXPECTED; // now join them nsCOMPtr<nsIDOMNode> selPointNode = startNode; int32_t selPointOffset = startOffset; { nsAutoTrackDOMPoint tracker(mHTMLEditor->mRangeUpdater, address_of(selPointNode), &selPointOffset); res = JoinBlocks(address_of(leftParent), address_of(rightParent), aCancel); res = JoinBlocks(leftNode, rightNode, aCancel); *aHandled = true; NS_ENSURE_SUCCESS(res, res); } aSelection->Collapse(selPointNode, selPointOffset); return res; Loading Loading @@ -2414,8 +2384,7 @@ nsHTMLEditRules::WillDeleteSelection(Selection* aSelection, } if (join) { res = JoinBlocks(address_of(leftParent), address_of(rightParent), aCancel); res = JoinBlocks(leftParent, rightParent, aCancel); NS_ENSURE_SUCCESS(res, res); } } Loading Loading @@ -2531,45 +2500,62 @@ nsHTMLEditRules::GetGoodSelPointForNode(nsIDOMNode *aNode, nsIEditor::EDirection * bool *aCanceled return TRUE if we had to cancel operation */ nsresult nsHTMLEditRules::JoinBlocks(nsCOMPtr<nsIDOMNode> *aLeftBlock, nsCOMPtr<nsIDOMNode> *aRightBlock, nsHTMLEditRules::JoinBlocks(nsIDOMNode *aLeftNode, nsIDOMNode *aRightNode, bool *aCanceled) { NS_ENSURE_TRUE(aLeftBlock && aRightBlock && *aLeftBlock && *aRightBlock, NS_ERROR_NULL_POINTER); if (nsHTMLEditUtils::IsTableElement(*aLeftBlock) || nsHTMLEditUtils::IsTableElement(*aRightBlock)) { NS_ENSURE_ARG_POINTER(aLeftNode && aRightNode); nsCOMPtr<nsIDOMNode> aLeftBlock, aRightBlock; if (IsBlockNode(aLeftNode)) { aLeftBlock = aLeftNode; } else if (aLeftNode) { aLeftBlock = mHTMLEditor->GetBlockNodeParent(aLeftNode); } if (IsBlockNode(aRightNode)) { aRightBlock = aRightNode; } else if (aRightNode) { aRightBlock = mHTMLEditor->GetBlockNodeParent(aRightNode); } // 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 *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)) { nsCOMPtr<nsIDOMNode> realLeft = mHTMLEditor->GetBlockNodeParent(*aLeftBlock); *aLeftBlock = realLeft; if (nsHTMLEditUtils::IsHR(aLeftBlock)) { nsCOMPtr<nsIDOMNode> realLeft = mHTMLEditor->GetBlockNodeParent(aLeftBlock); aLeftBlock = realLeft; } if (nsHTMLEditUtils::IsHR(*aRightBlock)) { nsCOMPtr<nsIDOMNode> realRight = mHTMLEditor->GetBlockNodeParent(*aRightBlock); *aRightBlock = realRight; if (nsHTMLEditUtils::IsHR(aRightBlock)) { nsCOMPtr<nsIDOMNode> realRight = mHTMLEditor->GetBlockNodeParent(aRightBlock); aRightBlock = realRight; } // bail if both blocks the same if (*aLeftBlock == *aRightBlock) { if (aLeftBlock == aRightBlock) { *aCanceled = true; return NS_OK; } // Joining a list item to its parent is a NOP. if (nsHTMLEditUtils::IsList(*aLeftBlock) && nsHTMLEditUtils::IsListItem(*aRightBlock)) { if (nsHTMLEditUtils::IsList(aLeftBlock) && nsHTMLEditUtils::IsListItem(aRightBlock)) { nsCOMPtr<nsIDOMNode> rightParent; (*aRightBlock)->GetParentNode(getter_AddRefs(rightParent)); if (rightParent == *aLeftBlock) aRightBlock->GetParentNode(getter_AddRefs(rightParent)); if (rightParent == aLeftBlock) { return NS_OK; } } // special rule here: if we are trying to join list items, and they are in different lists, // join the lists instead. Loading @@ -2577,21 +2563,21 @@ nsHTMLEditRules::JoinBlocks(nsCOMPtr<nsIDOMNode> *aLeftBlock, 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 (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)) if (!nsEditorUtils::IsDescendantOf(leftList, aRightBlock, &theOffset) && !nsEditorUtils::IsDescendantOf(rightList, aLeftBlock, &theOffset)) { *aLeftBlock = leftList; *aRightBlock = rightList; aLeftBlock = leftList; aRightBlock = rightList; bMergeLists = true; existingList = mHTMLEditor->GetTag(leftList); } Loading @@ -2606,18 +2592,22 @@ nsHTMLEditRules::JoinBlocks(nsCOMPtr<nsIDOMNode> *aLeftBlock, // theOffset below is where you find yourself in aRightBlock when you traverse upwards // from aLeftBlock if (nsEditorUtils::IsDescendantOf(*aLeftBlock, *aRightBlock, &rightOffset)) { 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. rightOffset++; res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor, aLeftBlock, nsWSRunObject::kBlockEnd); res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor, address_of(aLeftBlock), nsWSRunObject::kBlockEnd); NS_ENSURE_SUCCESS(res, res); res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor, aRightBlock, nsWSRunObject::kAfterBlock, &rightOffset); res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor, address_of(aRightBlock), nsWSRunObject::kAfterBlock, &rightOffset); NS_ENSURE_SUCCESS(res, res); // Do br adjustment. nsCOMPtr<nsIDOMNode> brNode; res = CheckForInvisibleBR(*aLeftBlock, kBlockEnd, address_of(brNode)); res = CheckForInvisibleBR(aLeftBlock, kBlockEnd, address_of(brNode)); NS_ENSURE_SUCCESS(res, res); if (bMergeLists) { Loading @@ -2639,23 +2629,27 @@ nsHTMLEditRules::JoinBlocks(nsCOMPtr<nsIDOMNode> *aLeftBlock, } else { res = MoveBlock(*aLeftBlock, *aRightBlock, leftOffset, rightOffset); res = MoveBlock(aLeftBlock, aRightBlock, leftOffset, rightOffset); } 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)) { } 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. res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor, aRightBlock, nsWSRunObject::kBlockStart); res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor, address_of(aRightBlock), nsWSRunObject::kBlockStart); NS_ENSURE_SUCCESS(res, res); res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor, aLeftBlock, nsWSRunObject::kBeforeBlock, &leftOffset); res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor, address_of(aLeftBlock), nsWSRunObject::kBeforeBlock, &leftOffset); NS_ENSURE_SUCCESS(res, res); // Do br adjustment. nsCOMPtr<nsIDOMNode> brNode; res = CheckForInvisibleBR(*aLeftBlock, kBeforeBlock, address_of(brNode), leftOffset); res = CheckForInvisibleBR(aLeftBlock, kBeforeBlock, address_of(brNode), leftOffset); NS_ENSURE_SUCCESS(res, res); if (bMergeLists) { Loading @@ -2663,7 +2657,58 @@ nsHTMLEditRules::JoinBlocks(nsCOMPtr<nsIDOMNode> *aLeftBlock, } else { res = MoveBlock(*aLeftBlock, *aRightBlock, leftOffset, rightOffset); // 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; if (aLeftNode == aLeftBlock) { // 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; previousContentOffset = leftOffset; } else { // We try to work as well as possible with HTML that's already invalid. // Although "right block" is a block, and a block must not be contained // in inline elements, reality is that broken documents do exist. The // DIRECT parent of "left NODE" might be an inline element. Previous // versions of this code skipped inline parents until the first block // parent was found (and used "left block" as the destination). // However, in some situations this strategy moves the content to an // 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); // We want to move our content just after the previous visible node. previousContentOffset++; } // Because we don't want the moving content to receive the style of the // previous content, we split the previous content's style. nsCOMPtr<nsINode> editorRoot = mHTMLEditor->GetEditorRoot(); if (!editorRoot || aLeftNode != editorRoot->AsDOMNode()) { nsCOMPtr<nsIDOMNode> splittedPreviousContent; res = mHTMLEditor->SplitStyleAbovePoint(address_of(previousContentParent), &previousContentOffset, nullptr, nullptr, nullptr, address_of(splittedPreviousContent)); NS_ENSURE_SUCCESS(res, res); if (splittedPreviousContent) { previousContentParent = nsEditor::GetNodeLocation(splittedPreviousContent, &previousContentOffset); } } res = MoveBlock(previousContentParent, aRightBlock, previousContentOffset, rightOffset); } if (brNode) mHTMLEditor->DeleteNode(brNode); } Loading @@ -2675,29 +2720,28 @@ nsHTMLEditRules::JoinBlocks(nsCOMPtr<nsIDOMNode> *aLeftBlock, // from li into p. // adjust whitespace at block boundaries res = nsWSRunObject::PrepareToJoinBlocks(mHTMLEditor, *aLeftBlock, *aRightBlock); res = nsWSRunObject::PrepareToJoinBlocks(mHTMLEditor, aLeftBlock, aRightBlock); NS_ENSURE_SUCCESS(res, res); // Do br adjustment. nsCOMPtr<nsIDOMNode> brNode; res = CheckForInvisibleBR(*aLeftBlock, kBlockEnd, address_of(brNode)); res = CheckForInvisibleBR(aLeftBlock, kBlockEnd, address_of(brNode)); NS_ENSURE_SUCCESS(res, res); if (bMergeLists || mHTMLEditor->NodesSameType(*aLeftBlock, *aRightBlock)) { if (bMergeLists || mHTMLEditor->NodesSameType(aLeftBlock, aRightBlock)) { // nodes are same type. merge them. nsCOMPtr<nsIDOMNode> parent; int32_t offset; res = JoinNodesSmart(*aLeftBlock, *aRightBlock, address_of(parent), &offset); res = JoinNodesSmart(aLeftBlock, aRightBlock, address_of(parent), &offset); if (NS_SUCCEEDED(res) && bMergeLists) { nsCOMPtr<nsIDOMNode> newBlock; res = ConvertListType(*aRightBlock, address_of(newBlock), res = ConvertListType(aRightBlock, address_of(newBlock), existingList, nsGkAtoms::li); } } else { // nodes are disimilar types. res = MoveBlock(*aLeftBlock, *aRightBlock, leftOffset, rightOffset); res = MoveBlock(aLeftBlock, aRightBlock, leftOffset, rightOffset); } if (NS_SUCCEEDED(res) && brNode) { Loading editor/libeditor/html/nsHTMLEditRules.h +1 −1 Original line number Diff line number Diff line Loading @@ -150,7 +150,7 @@ protected: nsresult InsertBRIfNeeded(nsISelection *aSelection); nsresult GetGoodSelPointForNode(nsIDOMNode *aNode, nsIEditor::EDirection aAction, nsCOMPtr<nsIDOMNode> *outSelNode, int32_t *outSelOffset); nsresult JoinBlocks(nsCOMPtr<nsIDOMNode> *aLeftBlock, nsCOMPtr<nsIDOMNode> *aRightBlock, bool *aCanceled); nsresult JoinBlocks(nsIDOMNode *aLeftNode, nsIDOMNode *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 Loading
editor/libeditor/html/nsHTMLEditRules.cpp +130 −86 Original line number Diff line number Diff line Loading @@ -2072,7 +2072,7 @@ nsHTMLEditRules::WillDeleteSelection(Selection* aSelection, &otherOffset, &otherWSType); // first find the adjacent node in the block nsCOMPtr<nsIDOMNode> leafNode, leftNode, rightNode, leftParent, rightParent; nsCOMPtr<nsIDOMNode> leafNode, leftNode, rightNode; if (aAction == nsIEditor::ePrevious) { res = mHTMLEditor->GetLastEditableLeaf( visNode, address_of(leafNode)); Loading Loading @@ -2114,28 +2114,13 @@ nsHTMLEditRules::WillDeleteSelection(Selection* aSelection, // else we are joining content to block // find the relavent blocks if (IsBlockNode(leftNode)) leftParent = leftNode; else if (leftNode) leftParent = mHTMLEditor->GetBlockNodeParent(leftNode); if (IsBlockNode(rightNode)) rightParent = rightNode; else rightParent = mHTMLEditor->GetBlockNodeParent(rightNode); // sanity checks NS_ENSURE_TRUE(leftParent && rightParent, NS_ERROR_NULL_POINTER); if (leftParent == rightParent) return NS_ERROR_UNEXPECTED; // now join them nsCOMPtr<nsIDOMNode> selPointNode = startNode; int32_t selPointOffset = startOffset; { nsAutoTrackDOMPoint tracker(mHTMLEditor->mRangeUpdater, address_of(selPointNode), &selPointOffset); res = JoinBlocks(address_of(leftParent), address_of(rightParent), aCancel); res = JoinBlocks(leftNode, rightNode, aCancel); *aHandled = true; NS_ENSURE_SUCCESS(res, res); } aSelection->Collapse(selPointNode, selPointOffset); return res; Loading @@ -2151,7 +2136,7 @@ nsHTMLEditRules::WillDeleteSelection(Selection* aSelection, } // first find the relavent nodes nsCOMPtr<nsIDOMNode> leftNode, rightNode, leftParent, rightParent; nsCOMPtr<nsIDOMNode> leftNode, rightNode; if (aAction == nsIEditor::ePrevious) { res = mHTMLEditor->GetPriorHTMLNode(visNode, address_of(leftNode)); Loading @@ -2178,28 +2163,13 @@ nsHTMLEditRules::WillDeleteSelection(Selection* aSelection, return NS_OK; } // find the relavent blocks if (IsBlockNode(leftNode)) leftParent = leftNode; else leftParent = mHTMLEditor->GetBlockNodeParent(leftNode); if (IsBlockNode(rightNode)) rightParent = rightNode; else rightParent = mHTMLEditor->GetBlockNodeParent(rightNode); // sanity checks NS_ENSURE_TRUE(leftParent && rightParent, NS_ERROR_NULL_POINTER); if (leftParent == rightParent) return NS_ERROR_UNEXPECTED; // now join them nsCOMPtr<nsIDOMNode> selPointNode = startNode; int32_t selPointOffset = startOffset; { nsAutoTrackDOMPoint tracker(mHTMLEditor->mRangeUpdater, address_of(selPointNode), &selPointOffset); res = JoinBlocks(address_of(leftParent), address_of(rightParent), aCancel); res = JoinBlocks(leftNode, rightNode, aCancel); *aHandled = true; NS_ENSURE_SUCCESS(res, res); } aSelection->Collapse(selPointNode, selPointOffset); return res; Loading Loading @@ -2414,8 +2384,7 @@ nsHTMLEditRules::WillDeleteSelection(Selection* aSelection, } if (join) { res = JoinBlocks(address_of(leftParent), address_of(rightParent), aCancel); res = JoinBlocks(leftParent, rightParent, aCancel); NS_ENSURE_SUCCESS(res, res); } } Loading Loading @@ -2531,45 +2500,62 @@ nsHTMLEditRules::GetGoodSelPointForNode(nsIDOMNode *aNode, nsIEditor::EDirection * bool *aCanceled return TRUE if we had to cancel operation */ nsresult nsHTMLEditRules::JoinBlocks(nsCOMPtr<nsIDOMNode> *aLeftBlock, nsCOMPtr<nsIDOMNode> *aRightBlock, nsHTMLEditRules::JoinBlocks(nsIDOMNode *aLeftNode, nsIDOMNode *aRightNode, bool *aCanceled) { NS_ENSURE_TRUE(aLeftBlock && aRightBlock && *aLeftBlock && *aRightBlock, NS_ERROR_NULL_POINTER); if (nsHTMLEditUtils::IsTableElement(*aLeftBlock) || nsHTMLEditUtils::IsTableElement(*aRightBlock)) { NS_ENSURE_ARG_POINTER(aLeftNode && aRightNode); nsCOMPtr<nsIDOMNode> aLeftBlock, aRightBlock; if (IsBlockNode(aLeftNode)) { aLeftBlock = aLeftNode; } else if (aLeftNode) { aLeftBlock = mHTMLEditor->GetBlockNodeParent(aLeftNode); } if (IsBlockNode(aRightNode)) { aRightBlock = aRightNode; } else if (aRightNode) { aRightBlock = mHTMLEditor->GetBlockNodeParent(aRightNode); } // 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 *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)) { nsCOMPtr<nsIDOMNode> realLeft = mHTMLEditor->GetBlockNodeParent(*aLeftBlock); *aLeftBlock = realLeft; if (nsHTMLEditUtils::IsHR(aLeftBlock)) { nsCOMPtr<nsIDOMNode> realLeft = mHTMLEditor->GetBlockNodeParent(aLeftBlock); aLeftBlock = realLeft; } if (nsHTMLEditUtils::IsHR(*aRightBlock)) { nsCOMPtr<nsIDOMNode> realRight = mHTMLEditor->GetBlockNodeParent(*aRightBlock); *aRightBlock = realRight; if (nsHTMLEditUtils::IsHR(aRightBlock)) { nsCOMPtr<nsIDOMNode> realRight = mHTMLEditor->GetBlockNodeParent(aRightBlock); aRightBlock = realRight; } // bail if both blocks the same if (*aLeftBlock == *aRightBlock) { if (aLeftBlock == aRightBlock) { *aCanceled = true; return NS_OK; } // Joining a list item to its parent is a NOP. if (nsHTMLEditUtils::IsList(*aLeftBlock) && nsHTMLEditUtils::IsListItem(*aRightBlock)) { if (nsHTMLEditUtils::IsList(aLeftBlock) && nsHTMLEditUtils::IsListItem(aRightBlock)) { nsCOMPtr<nsIDOMNode> rightParent; (*aRightBlock)->GetParentNode(getter_AddRefs(rightParent)); if (rightParent == *aLeftBlock) aRightBlock->GetParentNode(getter_AddRefs(rightParent)); if (rightParent == aLeftBlock) { return NS_OK; } } // special rule here: if we are trying to join list items, and they are in different lists, // join the lists instead. Loading @@ -2577,21 +2563,21 @@ nsHTMLEditRules::JoinBlocks(nsCOMPtr<nsIDOMNode> *aLeftBlock, 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 (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)) if (!nsEditorUtils::IsDescendantOf(leftList, aRightBlock, &theOffset) && !nsEditorUtils::IsDescendantOf(rightList, aLeftBlock, &theOffset)) { *aLeftBlock = leftList; *aRightBlock = rightList; aLeftBlock = leftList; aRightBlock = rightList; bMergeLists = true; existingList = mHTMLEditor->GetTag(leftList); } Loading @@ -2606,18 +2592,22 @@ nsHTMLEditRules::JoinBlocks(nsCOMPtr<nsIDOMNode> *aLeftBlock, // theOffset below is where you find yourself in aRightBlock when you traverse upwards // from aLeftBlock if (nsEditorUtils::IsDescendantOf(*aLeftBlock, *aRightBlock, &rightOffset)) { 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. rightOffset++; res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor, aLeftBlock, nsWSRunObject::kBlockEnd); res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor, address_of(aLeftBlock), nsWSRunObject::kBlockEnd); NS_ENSURE_SUCCESS(res, res); res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor, aRightBlock, nsWSRunObject::kAfterBlock, &rightOffset); res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor, address_of(aRightBlock), nsWSRunObject::kAfterBlock, &rightOffset); NS_ENSURE_SUCCESS(res, res); // Do br adjustment. nsCOMPtr<nsIDOMNode> brNode; res = CheckForInvisibleBR(*aLeftBlock, kBlockEnd, address_of(brNode)); res = CheckForInvisibleBR(aLeftBlock, kBlockEnd, address_of(brNode)); NS_ENSURE_SUCCESS(res, res); if (bMergeLists) { Loading @@ -2639,23 +2629,27 @@ nsHTMLEditRules::JoinBlocks(nsCOMPtr<nsIDOMNode> *aLeftBlock, } else { res = MoveBlock(*aLeftBlock, *aRightBlock, leftOffset, rightOffset); res = MoveBlock(aLeftBlock, aRightBlock, leftOffset, rightOffset); } 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)) { } 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. res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor, aRightBlock, nsWSRunObject::kBlockStart); res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor, address_of(aRightBlock), nsWSRunObject::kBlockStart); NS_ENSURE_SUCCESS(res, res); res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor, aLeftBlock, nsWSRunObject::kBeforeBlock, &leftOffset); res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor, address_of(aLeftBlock), nsWSRunObject::kBeforeBlock, &leftOffset); NS_ENSURE_SUCCESS(res, res); // Do br adjustment. nsCOMPtr<nsIDOMNode> brNode; res = CheckForInvisibleBR(*aLeftBlock, kBeforeBlock, address_of(brNode), leftOffset); res = CheckForInvisibleBR(aLeftBlock, kBeforeBlock, address_of(brNode), leftOffset); NS_ENSURE_SUCCESS(res, res); if (bMergeLists) { Loading @@ -2663,7 +2657,58 @@ nsHTMLEditRules::JoinBlocks(nsCOMPtr<nsIDOMNode> *aLeftBlock, } else { res = MoveBlock(*aLeftBlock, *aRightBlock, leftOffset, rightOffset); // 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; if (aLeftNode == aLeftBlock) { // 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; previousContentOffset = leftOffset; } else { // We try to work as well as possible with HTML that's already invalid. // Although "right block" is a block, and a block must not be contained // in inline elements, reality is that broken documents do exist. The // DIRECT parent of "left NODE" might be an inline element. Previous // versions of this code skipped inline parents until the first block // parent was found (and used "left block" as the destination). // However, in some situations this strategy moves the content to an // 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); // We want to move our content just after the previous visible node. previousContentOffset++; } // Because we don't want the moving content to receive the style of the // previous content, we split the previous content's style. nsCOMPtr<nsINode> editorRoot = mHTMLEditor->GetEditorRoot(); if (!editorRoot || aLeftNode != editorRoot->AsDOMNode()) { nsCOMPtr<nsIDOMNode> splittedPreviousContent; res = mHTMLEditor->SplitStyleAbovePoint(address_of(previousContentParent), &previousContentOffset, nullptr, nullptr, nullptr, address_of(splittedPreviousContent)); NS_ENSURE_SUCCESS(res, res); if (splittedPreviousContent) { previousContentParent = nsEditor::GetNodeLocation(splittedPreviousContent, &previousContentOffset); } } res = MoveBlock(previousContentParent, aRightBlock, previousContentOffset, rightOffset); } if (brNode) mHTMLEditor->DeleteNode(brNode); } Loading @@ -2675,29 +2720,28 @@ nsHTMLEditRules::JoinBlocks(nsCOMPtr<nsIDOMNode> *aLeftBlock, // from li into p. // adjust whitespace at block boundaries res = nsWSRunObject::PrepareToJoinBlocks(mHTMLEditor, *aLeftBlock, *aRightBlock); res = nsWSRunObject::PrepareToJoinBlocks(mHTMLEditor, aLeftBlock, aRightBlock); NS_ENSURE_SUCCESS(res, res); // Do br adjustment. nsCOMPtr<nsIDOMNode> brNode; res = CheckForInvisibleBR(*aLeftBlock, kBlockEnd, address_of(brNode)); res = CheckForInvisibleBR(aLeftBlock, kBlockEnd, address_of(brNode)); NS_ENSURE_SUCCESS(res, res); if (bMergeLists || mHTMLEditor->NodesSameType(*aLeftBlock, *aRightBlock)) { if (bMergeLists || mHTMLEditor->NodesSameType(aLeftBlock, aRightBlock)) { // nodes are same type. merge them. nsCOMPtr<nsIDOMNode> parent; int32_t offset; res = JoinNodesSmart(*aLeftBlock, *aRightBlock, address_of(parent), &offset); res = JoinNodesSmart(aLeftBlock, aRightBlock, address_of(parent), &offset); if (NS_SUCCEEDED(res) && bMergeLists) { nsCOMPtr<nsIDOMNode> newBlock; res = ConvertListType(*aRightBlock, address_of(newBlock), res = ConvertListType(aRightBlock, address_of(newBlock), existingList, nsGkAtoms::li); } } else { // nodes are disimilar types. res = MoveBlock(*aLeftBlock, *aRightBlock, leftOffset, rightOffset); res = MoveBlock(aLeftBlock, aRightBlock, leftOffset, rightOffset); } if (NS_SUCCEEDED(res) && brNode) { Loading
editor/libeditor/html/nsHTMLEditRules.h +1 −1 Original line number Diff line number Diff line Loading @@ -150,7 +150,7 @@ protected: nsresult InsertBRIfNeeded(nsISelection *aSelection); nsresult GetGoodSelPointForNode(nsIDOMNode *aNode, nsIEditor::EDirection aAction, nsCOMPtr<nsIDOMNode> *outSelNode, int32_t *outSelOffset); nsresult JoinBlocks(nsCOMPtr<nsIDOMNode> *aLeftBlock, nsCOMPtr<nsIDOMNode> *aRightBlock, bool *aCanceled); nsresult JoinBlocks(nsIDOMNode *aLeftNode, nsIDOMNode *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