diff --git a/editor/libeditor/EditorDOMPoint.h b/editor/libeditor/EditorDOMPoint.h index 718cda2e8f41..fd384705558f 100644 --- a/editor/libeditor/EditorDOMPoint.h +++ b/editor/libeditor/EditorDOMPoint.h @@ -85,8 +85,8 @@ class EditorDOMPointBase final { : mParent(nullptr), mChild(nullptr), mIsChildInitialized(false) {} template - EditorDOMPointBase(ContainerType* aContainer, int32_t aOffset) - : mParent(aContainer), + EditorDOMPointBase(const ContainerType* aContainer, int32_t aOffset) + : mParent(const_cast(aContainer)), mChild(nullptr), mOffset(mozilla::Some(aOffset)), mIsChildInitialized(false) { diff --git a/editor/libeditor/HTMLEditSubActionHandler.cpp b/editor/libeditor/HTMLEditSubActionHandler.cpp index eb5c7abe3c03..b31f9b42d75e 100644 --- a/editor/libeditor/HTMLEditSubActionHandler.cpp +++ b/editor/libeditor/HTMLEditSubActionHandler.cpp @@ -2527,7 +2527,8 @@ EditActionResult HTMLEditor::ChangeSelectedHardLinesToList( bool bOnlyBreaks = true; for (auto& content : arrayOfContents) { // if content is not a Break or empty inline, we're done - if (!content->IsHTMLElement(nsGkAtoms::br) && !IsEmptyInlineNode(content)) { + if (!content->IsHTMLElement(nsGkAtoms::br) && + !HTMLEditUtils::IsEmptyInlineContent(content)) { bOnlyBreaks = false; break; } @@ -2647,7 +2648,8 @@ EditActionResult HTMLEditor::ChangeSelectedHardLinesToList( // list item element. // If current node is an empty inline node, just delete it. if (EditorUtils::IsEditableContent(content, EditorType::HTML) && - (content->IsHTMLElement(nsGkAtoms::br) || IsEmptyInlineNode(content))) { + (content->IsHTMLElement(nsGkAtoms::br) || + HTMLEditUtils::IsEmptyInlineContent(content))) { nsresult rv = DeleteNodeWithTransaction(*content); if (NS_WARN_IF(Destroyed())) { return EditActionResult(NS_ERROR_EDITOR_DESTROYED); @@ -3097,7 +3099,7 @@ nsresult HTMLEditor::FormatBlockContainerWithTransaction(nsAtom& blockType) { // If there is no visible and editable nodes in the edit targets, make an // empty block. // XXX Isn't this odd if there are only non-editable visible nodes? - if (IsEmptyOneHardLine(arrayOfContents)) { + if (HTMLEditUtils::IsEmptyOneHardLine(arrayOfContents)) { const nsRange* firstRange = SelectionRef().GetRangeAt(0); if (NS_WARN_IF(!firstRange)) { return NS_ERROR_FAILURE; @@ -3555,7 +3557,7 @@ nsresult HTMLEditor::HandleCSSIndentAtSelectionInternal() { // If there is no visible and editable nodes in the edit targets, make an // empty block. // XXX Isn't this odd if there are only non-editable visible nodes? - if (IsEmptyOneHardLine(arrayOfContents)) { + if (HTMLEditUtils::IsEmptyOneHardLine(arrayOfContents)) { // get selection location const nsRange* firstRange = SelectionRef().GetRangeAt(0); if (NS_WARN_IF(!firstRange)) { @@ -3776,7 +3778,7 @@ nsresult HTMLEditor::HandleHTMLIndentAtSelectionInternal() { // If there is no visible and editable nodes in the edit targets, make an // empty block. // XXX Isn't this odd if there are only non-editable visible nodes? - if (IsEmptyOneHardLine(arrayOfContents)) { + if (HTMLEditUtils::IsEmptyOneHardLine(arrayOfContents)) { const nsRange* firstRange = SelectionRef().GetRangeAt(0); if (NS_WARN_IF(!firstRange)) { return NS_ERROR_FAILURE; @@ -9365,7 +9367,7 @@ nsresult HTMLEditor::MoveSelectedContentsToDivElementToMakeItAbsolutePosition( // If there is no visible and editable nodes in the edit targets, make an // empty block. // XXX Isn't this odd if there are only non-editable visible nodes? - if (IsEmptyOneHardLine(arrayOfContents)) { + if (HTMLEditUtils::IsEmptyOneHardLine(arrayOfContents)) { const nsRange* firstRange = SelectionRef().GetRangeAt(0); if (NS_WARN_IF(!firstRange)) { return NS_ERROR_FAILURE; diff --git a/editor/libeditor/HTMLEditUtils.cpp b/editor/libeditor/HTMLEditUtils.cpp index 1b03137c286e..81ff6e8ead18 100644 --- a/editor/libeditor/HTMLEditUtils.cpp +++ b/editor/libeditor/HTMLEditUtils.cpp @@ -204,7 +204,7 @@ bool HTMLEditUtils::IsHeader(nsINode& aNode) { /** * IsListItem() returns true if aNode is an html list item. */ -bool HTMLEditUtils::IsListItem(nsINode* aNode) { +bool HTMLEditUtils::IsListItem(const nsINode* aNode) { MOZ_ASSERT(aNode); return aNode->IsAnyOfHTMLElements(nsGkAtoms::li, nsGkAtoms::dd, nsGkAtoms::dt); @@ -248,7 +248,7 @@ bool HTMLEditUtils::IsTableRow(nsINode* aNode) { /** * IsTableCell() returns true if aNode is an html td or th. */ -bool HTMLEditUtils::IsTableCell(nsINode* aNode) { +bool HTMLEditUtils::IsTableCell(const nsINode* aNode) { MOZ_ASSERT(aNode); return aNode->IsAnyOfHTMLElements(nsGkAtoms::td, nsGkAtoms::th); } @@ -302,7 +302,7 @@ bool HTMLEditUtils::IsLink(nsINode* aNode) { return !tmpText.IsEmpty(); } -bool HTMLEditUtils::IsNamedAnchor(nsINode* aNode) { +bool HTMLEditUtils::IsNamedAnchor(const nsINode* aNode) { MOZ_ASSERT(aNode); if (!aNode->IsHTMLElement(nsGkAtoms::a)) { return false; @@ -350,7 +350,7 @@ bool HTMLEditUtils::IsMailCite(nsINode* aNode) { /** * IsFormWidget() returns true if aNode is a form widget of some kind. */ -bool HTMLEditUtils::IsFormWidget(nsINode* aNode) { +bool HTMLEditUtils::IsFormWidget(const nsINode* aNode) { MOZ_ASSERT(aNode); return aNode->IsAnyOfHTMLElements(nsGkAtoms::textarea, nsGkAtoms::select, nsGkAtoms::button, nsGkAtoms::output, @@ -366,13 +366,13 @@ bool HTMLEditUtils::SupportsAlignAttr(nsINode& aNode) { nsGkAtoms::h4, nsGkAtoms::h5, nsGkAtoms::h6); } -bool HTMLEditUtils::IsVisibleTextNode(Text& aText, - Element* aEditingHost /* = nullptr */) { +bool HTMLEditUtils::IsVisibleTextNode( + const Text& aText, const Element* aEditingHost /* = nullptr */) { if (!aText.TextDataLength()) { return false; } - if (!aText.TextIsOnlyWhitespace()) { + if (!const_cast(aText).TextIsOnlyWhitespace()) { return true; } @@ -388,7 +388,7 @@ bool HTMLEditUtils::IsVisibleTextNode(Text& aText, } bool HTMLEditUtils::IsInVisibleTextFrames(nsPresContext* aPresContext, - Text& aText) { + const Text& aText) { MOZ_ASSERT(aPresContext); nsIFrame* frame = aText.GetPrimaryFrame(); @@ -417,7 +417,7 @@ bool HTMLEditUtils::IsInVisibleTextFrames(nsPresContext* aPresContext, // bug 46209.) bool isVisible = false; rv = selectionController->CheckVisibilityContent( - &aText, 0, aText.TextDataLength(), &isVisible); + const_cast(&aText), 0, aText.TextDataLength(), &isVisible); NS_WARNING_ASSERTION( NS_SUCCEEDED(rv), "nsISelectionController::CheckVisibilityContent() failed"); @@ -489,7 +489,8 @@ bool HTMLEditUtils::IsVisibleBRElement( .ReachedBlockBoundary(); } -bool HTMLEditUtils::IsEmptyNode(nsPresContext* aPresContext, nsINode& aNode, +bool HTMLEditUtils::IsEmptyNode(nsPresContext* aPresContext, + const nsINode& aNode, const EmptyCheckOptions& aOptions /* = {} */, bool* aSeenBR /* = nullptr */) { MOZ_ASSERT_IF(aOptions.contains(EmptyCheckOption::SafeToAskLayout), @@ -506,7 +507,7 @@ bool HTMLEditUtils::IsEmptyNode(nsPresContext* aPresContext, nsINode& aNode, *aNode.AsContent()) : nullptr; - if (Text* text = Text::FromNode(&aNode)) { + if (const Text* text = Text::FromNode(&aNode)) { return aOptions.contains(EmptyCheckOption::SafeToAskLayout) ? !IsInVisibleTextFrames(aPresContext, *text) : !IsVisibleTextNode(*text, maybeParentBlockElement); diff --git a/editor/libeditor/HTMLEditUtils.h b/editor/libeditor/HTMLEditUtils.h index 46e1c1c91bbb..94ec1d6ad443 100644 --- a/editor/libeditor/HTMLEditUtils.h +++ b/editor/libeditor/HTMLEditUtils.h @@ -120,21 +120,21 @@ class HTMLEditUtils final { static bool IsFormatNode(nsINode* aNode); static bool IsNodeThatCanOutdent(nsINode* aNode); static bool IsHeader(nsINode& aNode); - static bool IsListItem(nsINode* aNode); + static bool IsListItem(const nsINode* aNode); static bool IsTable(nsINode* aNode); static bool IsTableRow(nsINode* aNode); static bool IsAnyTableElement(nsINode* aNode); static bool IsAnyTableElementButNotTable(nsINode* aNode); - static bool IsTableCell(nsINode* node); + static bool IsTableCell(const nsINode* aNode); static bool IsTableCellOrCaption(nsINode& aNode); static bool IsAnyListElement(nsINode* aNode); static bool IsPre(nsINode* aNode); static bool IsImage(nsINode* aNode); static bool IsLink(nsINode* aNode); - static bool IsNamedAnchor(nsINode* aNode); + static bool IsNamedAnchor(const nsINode* aNode); static bool IsMozDiv(nsINode* aNode); static bool IsMailCite(nsINode* aNode); - static bool IsFormWidget(nsINode* aNode); + static bool IsFormWidget(const nsINode* aNode); static bool SupportsAlignAttr(nsINode& aNode); static bool CanNodeContain(const nsINode& aParent, const nsIContent& aChild) { @@ -252,15 +252,15 @@ class HTMLEditUtils final { * But if you call this a lot, please specify proper editing host (or parent * block) for the performance. */ - static bool IsVisibleTextNode(dom::Text& aText, - Element* aEditingHost = nullptr); + static bool IsVisibleTextNode(const dom::Text& aText, + const Element* aEditingHost = nullptr); /** * IsInVisibleTextFrames() returns true if all text in aText is in visible * text frames. Callers have to guarantee that there is no pending reflow. */ static bool IsInVisibleTextFrames(nsPresContext* aPresContext, - dom::Text& aText); + const dom::Text& aText); /** * IsVisibleBRElement() and IsInvisibleBRElement() return true if aContent is @@ -298,16 +298,59 @@ class HTMLEditUtils final { SafeToAskLayout, }; using EmptyCheckOptions = EnumSet; - static bool IsEmptyNode(nsPresContext* aPresContext, nsINode& aNode, + static bool IsEmptyNode(nsPresContext* aPresContext, const nsINode& aNode, const EmptyCheckOptions& aOptions = {}, bool* aSeenBR = nullptr); - static bool IsEmptyNode(nsINode& aNode, + static bool IsEmptyNode(const nsINode& aNode, const EmptyCheckOptions& aOptions = {}, bool* aSeenBR = nullptr) { MOZ_ASSERT(!aOptions.contains(EmptyCheckOption::SafeToAskLayout)); return IsEmptyNode(nullptr, aNode, aOptions, aSeenBR); } + /** + * IsEmptyInlineContent() returns true if aContent is an inline node and it + * does not have meaningful content. + */ + static bool IsEmptyInlineContent(const nsIContent& aContent) { + return HTMLEditUtils::IsInlineElement(aContent) && + HTMLEditUtils::IsContainerNode(aContent) && + HTMLEditUtils::IsEmptyNode( + aContent, {EmptyCheckOption::TreatSingleBRElementAsVisible}); + } + + /** + * IsEmptyOneHardLine() returns true if aArrayOfContents does not represent + * 2 or more lines and have meaningful content. + */ + static bool IsEmptyOneHardLine( + nsTArray>& aArrayOfContents) { + if (NS_WARN_IF(aArrayOfContents.IsEmpty())) { + return true; + } + + bool brElementHasFound = false; + for (OwningNonNull& content : aArrayOfContents) { + if (!EditorUtils::IsEditableContent(content, + EditorUtils::EditorType::HTML)) { + continue; + } + if (content->IsHTMLElement(nsGkAtoms::br)) { + // If there are 2 or more `
` elements, it's not empty line since + // there may be only one `
` element in a hard line. + if (brElementHasFound) { + return false; + } + brElementHasFound = true; + continue; + } + if (!HTMLEditUtils::IsEmptyInlineContent(content)) { + return false; + } + } + return true; + } + /** * IsPointAtEdgeOfLink() returns true if aPoint is at start or end of a * link. diff --git a/editor/libeditor/HTMLEditor.cpp b/editor/libeditor/HTMLEditor.cpp index 9245065ab9ff..84f2c352e89b 100644 --- a/editor/libeditor/HTMLEditor.cpp +++ b/editor/libeditor/HTMLEditor.cpp @@ -899,17 +899,6 @@ NS_IMETHODIMP HTMLEditor::NodeIsBlock(nsINode* aNode, bool* aIsBlock) { return NS_OK; } -bool HTMLEditor::IsEmptyInlineNode(nsIContent& aContent) const { - MOZ_ASSERT(IsEditActionDataAvailable()); - - if (!HTMLEditUtils::IsInlineElement(aContent) || - !HTMLEditUtils::IsContainerNode(aContent)) { - return false; - } - return HTMLEditUtils::IsEmptyNode( - aContent, {EmptyCheckOption::TreatSingleBRElementAsVisible}); -} - /** * IsNextCharInNodeWhiteSpace() checks the adjacent content in the same node to * see if following selection is white-space or nbsp. diff --git a/editor/libeditor/HTMLEditor.h b/editor/libeditor/HTMLEditor.h index e383a81cc78f..733dece9a946 100644 --- a/editor/libeditor/HTMLEditor.h +++ b/editor/libeditor/HTMLEditor.h @@ -1442,43 +1442,6 @@ class HTMLEditor final : public TextEditor, [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult MaybeExtendSelectionToHardLineEdgesForBlockEditAction(); - /** - * IsEmptyInlineNode() returns true if aContent is an inline node and it does - * not have meaningful content. - */ - bool IsEmptyInlineNode(nsIContent& aContent) const; - - /** - * IsEmptyOneHardLine() returns true if aArrayOfContents does not represent - * 2 or more lines and have meaningful content. - */ - bool IsEmptyOneHardLine( - nsTArray>& aArrayOfContents) const { - if (NS_WARN_IF(aArrayOfContents.IsEmpty())) { - return true; - } - - bool brElementHasFound = false; - for (OwningNonNull& content : aArrayOfContents) { - if (!EditorUtils::IsEditableContent(content, EditorType::HTML)) { - continue; - } - if (content->IsHTMLElement(nsGkAtoms::br)) { - // If there are 2 or more `
` elements, it's not empty line since - // there may be only one `
` element in a hard line. - if (brElementHasFound) { - return false; - } - brElementHasFound = true; - continue; - } - if (!IsEmptyInlineNode(content)) { - return false; - } - } - return true; - } - /** * MaybeSplitAncestorsForInsertWithTransaction() does nothing if container of * aStartOfDeepestRightNode can have an element whose tag name is aTag. diff --git a/editor/libeditor/WSRunObject.h b/editor/libeditor/WSRunObject.h index b26eff5d41b4..799fe7d9edb2 100644 --- a/editor/libeditor/WSRunObject.h +++ b/editor/libeditor/WSRunObject.h @@ -283,10 +283,10 @@ class MOZ_STACK_CLASS WSRunScanner final { using WSType = WSScanResult::WSType; template - WSRunScanner(dom::Element* aEditingHost, + WSRunScanner(const dom::Element* aEditingHost, const EditorDOMPointType& aScanStartPoint) : mScanStartPoint(aScanStartPoint), - mEditingHost(aEditingHost), + mEditingHost(const_cast(aEditingHost)), mTextFragmentDataAtStart(mScanStartPoint, mEditingHost) {} // ScanNextVisibleNodeOrBlockBoundaryForwardFrom() returns the first visible @@ -298,7 +298,8 @@ class MOZ_STACK_CLASS WSRunScanner final { const EditorDOMPointBase& aPoint) const; template static WSScanResult ScanNextVisibleNodeOrBlockBoundary( - dom::Element* aEditingHost, const EditorDOMPointBase& aPoint) { + const dom::Element* aEditingHost, + const EditorDOMPointBase& aPoint) { return WSRunScanner(aEditingHost, aPoint) .ScanNextVisibleNodeOrBlockBoundaryFrom(aPoint); } @@ -312,7 +313,8 @@ class MOZ_STACK_CLASS WSRunScanner final { const EditorDOMPointBase& aPoint) const; template static WSScanResult ScanPreviousVisibleNodeOrBlockBoundary( - dom::Element* aEditingHost, const EditorDOMPointBase& aPoint) { + const dom::Element* aEditingHost, + const EditorDOMPointBase& aPoint) { return WSRunScanner(aEditingHost, aPoint) .ScanPreviousVisibleNodeOrBlockBoundaryFrom(aPoint); }