author | Aryeh Gregor <ayg@aryeh.name> |
Sat, 23 Apr 2016 19:29:43 +0900 | |
changeset 332531 | 11c00c64207d2fa97d2bcf1401019560200b5ad3 |
parent 332530 | bb29532b1b73e1cd5d904e7b7615c840a82b0a8a |
child 332532 | 645d28b3957926e969c8add1757ed6caebe108d6 |
push id | 6048 |
push user | kmoir@mozilla.com |
push date | Mon, 06 Jun 2016 19:02:08 +0000 |
treeherder | mozilla-beta@46d72a56c57d [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | ehsan |
bugs | 1190172 |
milestone | 48.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
editor/libeditor/nsHTMLEditRules.cpp | file | annotate | diff | comparison | revisions | |
editor/libeditor/nsHTMLEditRules.h | file | annotate | diff | comparison | revisions |
--- a/editor/libeditor/nsHTMLEditRules.cpp +++ b/editor/libeditor/nsHTMLEditRules.cpp @@ -2231,17 +2231,17 @@ nsHTMLEditRules::WillDeleteSelection(Sel } aSelection->Collapse(selPointNode, selPointOffset); return NS_OK; } } // Else we have a non-collapsed selection. First adjust the selection. - res = ExpandSelectionForDeletion(aSelection); + res = ExpandSelectionForDeletion(*aSelection); NS_ENSURE_SUCCESS(res, res); // Remember that we did a ranged delete for the benefit of AfterEditInner(). mDidRangedDelete = true; // Refresh start and end points NS_ENSURE_STATE(aSelection->GetRangeAt(0)); startNode = aSelection->GetRangeAt(0)->GetStartParent(); @@ -5033,190 +5033,148 @@ nsHTMLEditRules::GetInnerContent(nsINode GetInnerContent(*node, aOutArrayOfNodes, aIndex, aLists, aTables); } else { aOutArrayOfNodes.InsertElementAt(*aIndex, *node); (*aIndex)++; } } } -/////////////////////////////////////////////////////////////////////////// -// ExpandSelectionForDeletion: this promotes our selection to include blocks -// that have all their children selected. -// +/** + * Promotes selection to include blocks that have all their children selected. + */ nsresult -nsHTMLEditRules::ExpandSelectionForDeletion(Selection* aSelection) -{ - NS_ENSURE_TRUE(aSelection, NS_ERROR_NULL_POINTER); - - // don't need to touch collapsed selections - if (aSelection->Collapsed()) { +nsHTMLEditRules::ExpandSelectionForDeletion(Selection& aSelection) +{ + // Don't need to touch collapsed selections + if (aSelection.Collapsed()) { + return NS_OK; + } + + // We don't need to mess with cell selections, and we assume multirange + // selections are those. + if (aSelection.RangeCount() != 1) { return NS_OK; } - int32_t rangeCount; - nsresult res = aSelection->GetRangeCount(&rangeCount); - NS_ENSURE_SUCCESS(res, res); - - // we don't need to mess with cell selections, and we assume multirange selections are those. - if (rangeCount != 1) return NS_OK; - - // find current sel start and end - RefPtr<nsRange> range = aSelection->GetRangeAt(0); - NS_ENSURE_TRUE(range, NS_ERROR_NULL_POINTER); - nsCOMPtr<nsIDOMNode> selStartNode, selEndNode, selCommon; - int32_t selStartOffset, selEndOffset; - - res = range->GetStartContainer(getter_AddRefs(selStartNode)); - NS_ENSURE_SUCCESS(res, res); - res = range->GetStartOffset(&selStartOffset); - NS_ENSURE_SUCCESS(res, res); - res = range->GetEndContainer(getter_AddRefs(selEndNode)); - NS_ENSURE_SUCCESS(res, res); - res = range->GetEndOffset(&selEndOffset); - NS_ENSURE_SUCCESS(res, res); - - // find current selection common block parent - res = range->GetCommonAncestorContainer(getter_AddRefs(selCommon)); - NS_ENSURE_SUCCESS(res, res); - if (!IsBlockNode(selCommon)) - selCommon = nsHTMLEditor::GetBlockNodeParent(selCommon); + // Find current sel start and end + NS_ENSURE_TRUE(aSelection.GetRangeAt(0), NS_ERROR_NULL_POINTER); + OwningNonNull<nsRange> range = *aSelection.GetRangeAt(0); + + nsCOMPtr<nsINode> selStartNode = range->GetStartParent(); + int32_t selStartOffset = range->StartOffset(); + nsCOMPtr<nsINode> selEndNode = range->GetEndParent(); + int32_t selEndOffset = range->EndOffset(); + + // Find current selection common block parent + nsCOMPtr<Element> selCommon = + nsHTMLEditor::GetBlock(*range->GetCommonAncestor()); NS_ENSURE_STATE(selCommon); - // set up for loops and cache our root element - bool stillLooking = true; - nsCOMPtr<nsIDOMNode> firstBRParent; + // Set up for loops and cache our root element + nsCOMPtr<nsINode> firstBRParent; nsCOMPtr<nsINode> unused; - int32_t visOffset=0, firstBROffset=0; + int32_t visOffset = 0, firstBROffset = 0; WSType wsType; - nsCOMPtr<nsIContent> rootContent = mHTMLEditor->GetActiveEditingHost(); - nsCOMPtr<nsIDOMNode> rootElement = do_QueryInterface(rootContent); - NS_ENSURE_TRUE(rootElement, NS_ERROR_FAILURE); - - // find previous visible thingy before start of selection - if ((selStartNode!=selCommon) && (selStartNode!=rootElement)) - { - while (stillLooking) - { + nsCOMPtr<Element> root = mHTMLEditor->GetActiveEditingHost(); + NS_ENSURE_TRUE(root, NS_ERROR_FAILURE); + + // Find previous visible thingy before start of selection + if (selStartNode != selCommon && selStartNode != root) { + while (true) { nsWSRunObject wsObj(mHTMLEditor, selStartNode, selStartOffset); - nsCOMPtr<nsINode> selStartNode_(do_QueryInterface(selStartNode)); - wsObj.PriorVisibleNode(selStartNode_, selStartOffset, address_of(unused), + wsObj.PriorVisibleNode(selStartNode, selStartOffset, address_of(unused), &visOffset, &wsType); - if (wsType == WSType::thisBlock) { - // we want to keep looking up. But stop if we are crossing table element - // boundaries, or if we hit the root. - if (nsHTMLEditUtils::IsTableElement(wsObj.mStartReasonNode) || - selCommon == GetAsDOMNode(wsObj.mStartReasonNode) || - rootElement == GetAsDOMNode(wsObj.mStartReasonNode)) { - stillLooking = false; - } - else - { - selStartNode = nsEditor::GetNodeLocation(GetAsDOMNode(wsObj.mStartReasonNode), - &selStartOffset); - } - } - else - { - stillLooking = false; - } - } - } - - stillLooking = true; - // find next visible thingy after end of selection - if ((selEndNode!=selCommon) && (selEndNode!=rootElement)) - { - while (stillLooking) - { + if (wsType != WSType::thisBlock) { + break; + } + // We want to keep looking up. But stop if we are crossing table + // element boundaries, or if we hit the root. + if (nsHTMLEditUtils::IsTableElement(wsObj.mStartReasonNode) || + selCommon == wsObj.mStartReasonNode || + root == wsObj.mStartReasonNode) { + break; + } + selStartNode = wsObj.mStartReasonNode->GetParentNode(); + selStartOffset = selStartNode ? + selStartNode->IndexOf(wsObj.mStartReasonNode) : -1; + } + } + + // Find next visible thingy after end of selection + if (selEndNode != selCommon && selEndNode != root) { + while (true) { nsWSRunObject wsObj(mHTMLEditor, selEndNode, selEndOffset); - nsCOMPtr<nsINode> selEndNode_(do_QueryInterface(selEndNode)); - wsObj.NextVisibleNode(selEndNode_, selEndOffset, address_of(unused), + wsObj.NextVisibleNode(selEndNode, selEndOffset, address_of(unused), &visOffset, &wsType); if (wsType == WSType::br) { - if (mHTMLEditor->IsVisBreak(wsObj.mEndReasonNode)) - { - stillLooking = false; + if (mHTMLEditor->IsVisBreak(wsObj.mEndReasonNode)) { + break; + } + if (!firstBRParent) { + firstBRParent = selEndNode; + firstBROffset = selEndOffset; } - else - { - if (!firstBRParent) - { - firstBRParent = selEndNode; - firstBROffset = selEndOffset; - } - selEndNode = nsEditor::GetNodeLocation(GetAsDOMNode(wsObj.mEndReasonNode), &selEndOffset); - ++selEndOffset; - } + selEndNode = wsObj.mEndReasonNode->GetParentNode(); + selEndOffset = selEndNode + ? selEndNode->IndexOf(wsObj.mEndReasonNode) + 1 : 0; } else if (wsType == WSType::thisBlock) { - // we want to keep looking up. But stop if we are crossing table element - // boundaries, or if we hit the root. + // We want to keep looking up. But stop if we are crossing table + // element boundaries, or if we hit the root. if (nsHTMLEditUtils::IsTableElement(wsObj.mEndReasonNode) || - selCommon == GetAsDOMNode(wsObj.mEndReasonNode) || - rootElement == GetAsDOMNode(wsObj.mEndReasonNode)) { - stillLooking = false; - } - else - { - selEndNode = nsEditor::GetNodeLocation(GetAsDOMNode(wsObj.mEndReasonNode), &selEndOffset); - ++selEndOffset; + selCommon == wsObj.mEndReasonNode || + root == wsObj.mEndReasonNode) { + break; } - } - else - { - stillLooking = false; - } - } - } - // now set the selection to the new range - aSelection->Collapse(selStartNode, selStartOffset); - - // expand selection endpoint only if we didnt pass a br, - // or if we really needed to pass that br (ie, its block is now - // totally selected) + selEndNode = wsObj.mEndReasonNode->GetParentNode(); + selEndOffset = 1 + selEndNode->IndexOf(wsObj.mEndReasonNode); + } else { + break; + } + } + } + // Now set the selection to the new range + aSelection.Collapse(selStartNode, selStartOffset); + + // Expand selection endpoint only if we didn't pass a br, or if we really + // needed to pass that br (i.e., its block is now totally selected) + nsresult res; bool doEndExpansion = true; - if (firstBRParent) - { - // find block node containing br - nsCOMPtr<nsIDOMNode> brBlock = firstBRParent; - if (!IsBlockNode(brBlock)) - brBlock = nsHTMLEditor::GetBlockNodeParent(brBlock); - bool nodeBefore=false, nodeAfter=false; - - // create a range that represents expanded selection - nsCOMPtr<nsINode> node = do_QueryInterface(selStartNode); - NS_ENSURE_STATE(node); - RefPtr<nsRange> range = new nsRange(node); + if (firstBRParent) { + // Find block node containing br + nsCOMPtr<Element> brBlock = nsHTMLEditor::GetBlock(*firstBRParent); + bool nodeBefore = false, nodeAfter = false; + + // Create a range that represents expanded selection + RefPtr<nsRange> range = new nsRange(selStartNode); res = range->SetStart(selStartNode, selStartOffset); NS_ENSURE_SUCCESS(res, res); res = range->SetEnd(selEndNode, selEndOffset); NS_ENSURE_SUCCESS(res, res); - // check if block is entirely inside range - nsCOMPtr<nsIContent> brContentBlock = do_QueryInterface(brBlock); - if (brContentBlock) { - res = nsRange::CompareNodeToRange(brContentBlock, range, &nodeBefore, - &nodeAfter); - } - - // if block isn't contained, forgo grabbing the br in the expanded selection - if (nodeBefore || nodeAfter) + // Check if block is entirely inside range + if (brBlock) { + nsRange::CompareNodeToRange(brBlock, range, &nodeBefore, &nodeAfter); + } + + // If block isn't contained, forgo grabbing the br in expanded selection + if (nodeBefore || nodeAfter) { doEndExpansion = false; - } - if (doEndExpansion) - { - res = aSelection->Extend(selEndNode, selEndOffset); - } - else - { - // only expand to just before br - res = aSelection->Extend(firstBRParent, firstBROffset); - } - - return res; + } + } + if (doEndExpansion) { + res = aSelection.Extend(selEndNode, selEndOffset); + NS_ENSURE_SUCCESS(res, res); + } else { + // Only expand to just before br + res = aSelection.Extend(firstBRParent, firstBROffset); + NS_ENSURE_SUCCESS(res, res); + } + + return NS_OK; } /////////////////////////////////////////////////////////////////////////// // NormalizeSelection: tweak non-collapsed selections to be more "natural". // Idea here is to adjust selection endpoint so that they do not cross // breaks or block boundaries unless something editable beyond that boundary // is also selected. This adjustment makes it much easier for the various
--- a/editor/libeditor/nsHTMLEditRules.h +++ b/editor/libeditor/nsHTMLEditRules.h @@ -255,17 +255,17 @@ protected: MozBRCounts aMozBRCounts = MozBRCounts::yes); nsresult CheckForEmptyBlock(nsINode* aStartNode, mozilla::dom::Element* aBodyNode, mozilla::dom::Selection* aSelection, nsIEditor::EDirection aAction, bool* aHandled); nsresult CheckForInvisibleBR(nsIDOMNode *aBlock, nsHTMLEditRules::BRLocation aWhere, nsCOMPtr<nsIDOMNode> *outBRNode, int32_t aOffset=0); - nsresult ExpandSelectionForDeletion(mozilla::dom::Selection* aSelection); + nsresult ExpandSelectionForDeletion(mozilla::dom::Selection& aSelection); bool IsFirstNode(nsIDOMNode *aNode); bool IsLastNode(nsIDOMNode *aNode); nsresult NormalizeSelection(mozilla::dom::Selection* aSelection); void GetPromotedPoint(RulesEndpoint aWhere, nsIDOMNode* aNode, int32_t aOffset, EditAction actionID, nsCOMPtr<nsIDOMNode>* outNode, int32_t* outOffset); void GetPromotedRanges(mozilla::dom::Selection& aSelection, nsTArray<RefPtr<nsRange>>& outArrayOfRanges,