зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1574852 - part 20: Move `HTMLEditRules::GetPromotedPoint()` to `HTMLEditor` r=m_kato
`HTMLEditRules::GetPromotedPoint()` does too many things. Therefore, this patch splits it to 3 methods. One is for specific `EditSubAction` values, that's the first block in `GetPromotedPoint()`. It's named as `GetWhiteSpaceEndPoint()`. Next one is for expanding start of the range to start of its line. It's named as `GetCurrentHardLineStartPoint()`. The last one is for expanding end of the range to end of its line. It's named as `GetCurrentHardLineEndPoint()`. Differential Revision: https://phabricator.services.mozilla.com/D42791 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
9efbc2ee5b
Коммит
39bbc90bb9
|
@ -6862,118 +6862,123 @@ nsresult HTMLEditRules::NormalizeSelection() {
|
|||
return error.StealNSResult();
|
||||
}
|
||||
|
||||
EditorDOMPoint HTMLEditRules::GetPromotedPoint(
|
||||
RulesEndpoint aWhere, nsINode& aNode, int32_t aOffset,
|
||||
EditSubAction aEditSubAction) const {
|
||||
MOZ_ASSERT(IsEditorDataAvailable());
|
||||
|
||||
// we do one thing for text actions, something else entirely for other
|
||||
// actions
|
||||
if (aEditSubAction == EditSubAction::eInsertText ||
|
||||
aEditSubAction == EditSubAction::eInsertTextComingFromIME ||
|
||||
aEditSubAction == EditSubAction::eInsertLineBreak ||
|
||||
aEditSubAction == EditSubAction::eInsertParagraphSeparator ||
|
||||
aEditSubAction == EditSubAction::eDeleteText) {
|
||||
bool isSpace, isNBSP;
|
||||
nsCOMPtr<nsIContent> content =
|
||||
aNode.IsContent() ? aNode.AsContent() : nullptr;
|
||||
nsCOMPtr<nsIContent> temp;
|
||||
int32_t newOffset = aOffset;
|
||||
// for text actions, we want to look backwards (or forwards, as
|
||||
// appropriate) for additional whitespace or nbsp's. We may have to act on
|
||||
// these later even though they are outside of the initial selection. Even
|
||||
// if they are in another node!
|
||||
while (content) {
|
||||
int32_t offset;
|
||||
if (aWhere == kStart) {
|
||||
HTMLEditorRef().IsPrevCharInNodeWhitespace(
|
||||
content, newOffset, &isSpace, &isNBSP, getter_AddRefs(temp),
|
||||
&offset);
|
||||
} else {
|
||||
HTMLEditorRef().IsNextCharInNodeWhitespace(
|
||||
content, newOffset, &isSpace, &isNBSP, getter_AddRefs(temp),
|
||||
&offset);
|
||||
}
|
||||
if (isSpace || isNBSP) {
|
||||
content = temp;
|
||||
newOffset = offset;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return EditorDOMPoint(content, newOffset);
|
||||
// static
|
||||
EditorDOMPoint HTMLEditor::GetWhiteSpaceEndPoint(const RangeBoundary& aPoint,
|
||||
ScanDirection aScanDirection) {
|
||||
if (NS_WARN_IF(!aPoint.IsSet()) ||
|
||||
NS_WARN_IF(!aPoint.Container()->IsContent())) {
|
||||
return EditorDOMPoint();
|
||||
}
|
||||
|
||||
EditorDOMPoint point(&aNode, aOffset);
|
||||
|
||||
// else not a text section. In this case we want to see if we should grab
|
||||
// any adjacent inline nodes and/or parents and other ancestors
|
||||
if (aWhere == kStart) {
|
||||
// some special casing for text nodes
|
||||
if (point.IsInTextNode()) {
|
||||
if (!point.GetContainer()->GetParentNode()) {
|
||||
// Okay, can't promote any further
|
||||
return point;
|
||||
}
|
||||
point.Set(point.GetContainer());
|
||||
bool isSpace = false, isNBSP = false;
|
||||
nsIContent* newContent = aPoint.Container()->AsContent();
|
||||
int32_t newOffset = aPoint.Offset();
|
||||
while (newContent) {
|
||||
int32_t offset = -1;
|
||||
nsCOMPtr<nsIContent> content;
|
||||
if (aScanDirection == ScanDirection::Backward) {
|
||||
HTMLEditor::IsPrevCharInNodeWhitespace(newContent, newOffset, &isSpace,
|
||||
&isNBSP, getter_AddRefs(content),
|
||||
&offset);
|
||||
} else {
|
||||
HTMLEditor::IsNextCharInNodeWhitespace(newContent, newOffset, &isSpace,
|
||||
&isNBSP, getter_AddRefs(content),
|
||||
&offset);
|
||||
}
|
||||
|
||||
// look back through any further inline nodes that aren't across a <br>
|
||||
// from us, and that are enclosed in the same block.
|
||||
nsCOMPtr<nsINode> priorNode =
|
||||
HTMLEditorRef().GetPreviousEditableHTMLNodeInBlock(point);
|
||||
|
||||
while (priorNode && priorNode->GetParentNode() &&
|
||||
!HTMLEditorRef().IsVisibleBRElement(priorNode) &&
|
||||
!HTMLEditor::NodeIsBlockStatic(*priorNode)) {
|
||||
point.Set(priorNode);
|
||||
priorNode = HTMLEditorRef().GetPreviousEditableHTMLNodeInBlock(point);
|
||||
if (!isSpace && !isNBSP) {
|
||||
break;
|
||||
}
|
||||
newContent = content;
|
||||
newOffset = offset;
|
||||
}
|
||||
return EditorDOMPoint(newContent, newOffset);
|
||||
}
|
||||
|
||||
// finding the real start for this point. look up the tree for as long as
|
||||
// we are the first node in the container, and as long as we haven't hit
|
||||
// the body node.
|
||||
nsCOMPtr<nsIContent> nearNode =
|
||||
HTMLEditorRef().GetPreviousEditableHTMLNodeInBlock(point);
|
||||
while (!nearNode && !point.IsContainerHTMLElement(nsGkAtoms::body) &&
|
||||
point.GetContainer()->GetParentNode()) {
|
||||
// some cutoffs are here: we don't need to also include them in the
|
||||
// aWhere == kEnd case. as long as they are in one or the other it will
|
||||
// work. special case for outdent: don't keep looking up if we have
|
||||
// found a blockquote element to act on
|
||||
if (aEditSubAction == EditSubAction::eOutdent &&
|
||||
point.IsContainerHTMLElement(nsGkAtoms::blockquote)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Don't walk past the editable section. Note that we need to check
|
||||
// before walking up to a parent because we need to return the parent
|
||||
// object, so the parent itself might not be in the editable area, but
|
||||
// it's OK if we're not performing a block-level action.
|
||||
bool blockLevelAction =
|
||||
aEditSubAction == EditSubAction::eIndent ||
|
||||
aEditSubAction == EditSubAction::eOutdent ||
|
||||
aEditSubAction == EditSubAction::eSetOrClearAlignment ||
|
||||
aEditSubAction == EditSubAction::eCreateOrRemoveBlock;
|
||||
if (!HTMLEditorRef().IsDescendantOfEditorRoot(
|
||||
point.GetContainer()->GetParentNode()) &&
|
||||
(blockLevelAction ||
|
||||
!HTMLEditorRef().IsDescendantOfEditorRoot(point.GetContainer()))) {
|
||||
break;
|
||||
}
|
||||
|
||||
point.Set(point.GetContainer());
|
||||
nearNode = HTMLEditorRef().GetPreviousEditableHTMLNodeInBlock(point);
|
||||
}
|
||||
return point;
|
||||
EditorDOMPoint HTMLEditor::GetCurrentHardLineStartPoint(
|
||||
const RangeBoundary& aPoint, EditSubAction aEditSubAction) {
|
||||
if (NS_WARN_IF(!aPoint.IsSet())) {
|
||||
return EditorDOMPoint();
|
||||
}
|
||||
|
||||
// aWhere == kEnd
|
||||
// some special casing for text nodes
|
||||
EditorDOMPoint point(aPoint);
|
||||
// Start scanning from the container node if aPoint is in a text node.
|
||||
// XXX Perhaps, IsInDataNode() must be expected.
|
||||
if (point.IsInTextNode()) {
|
||||
if (!point.GetContainer()->GetParentNode()) {
|
||||
// Okay, can't promote any further
|
||||
// XXX Why don't we return start of the text node?
|
||||
return point;
|
||||
}
|
||||
point.Set(point.GetContainer());
|
||||
}
|
||||
|
||||
// Look back through any further inline nodes that aren't across a <br>
|
||||
// from us, and that are enclosed in the same block.
|
||||
// I.e., looking for start of current hard line.
|
||||
for (nsIContent* previousEditableContent =
|
||||
GetPreviousEditableHTMLNodeInBlock(point);
|
||||
previousEditableContent && previousEditableContent->GetParentNode() &&
|
||||
!IsVisibleBRElement(previousEditableContent) &&
|
||||
!HTMLEditor::NodeIsBlockStatic(*previousEditableContent);
|
||||
previousEditableContent = GetPreviousEditableHTMLNodeInBlock(point)) {
|
||||
point.Set(previousEditableContent);
|
||||
// XXX Why don't we check \n in pre-formated text node here?
|
||||
}
|
||||
|
||||
// Finding the real start for this point unless current line starts after
|
||||
// <br> element. Look up the tree for as long as we are the first node in
|
||||
// the container (typically, start of nearest block ancestor), and as long
|
||||
// as we haven't hit the body node.
|
||||
for (nsIContent* nearContent = GetPreviousEditableHTMLNodeInBlock(point);
|
||||
!nearContent && !point.IsContainerHTMLElement(nsGkAtoms::body) &&
|
||||
point.GetContainer()->GetParentNode();
|
||||
nearContent = GetPreviousEditableHTMLNodeInBlock(point)) {
|
||||
// Don't keep looking up if we have found a blockquote element to act on
|
||||
// when we handle outdent.
|
||||
// XXX Sounds like this is hacky. If possible, it should be check in
|
||||
// outdent handler for consistency between edit sub-actions.
|
||||
// We should check Chromium's behavior of outdent when Selection
|
||||
// starts from `<blockquote>` and starts from first child of
|
||||
// `<blockquote>`.
|
||||
if (aEditSubAction == EditSubAction::eOutdent &&
|
||||
point.IsContainerHTMLElement(nsGkAtoms::blockquote)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Don't walk past the editable section. Note that we need to check
|
||||
// before walking up to a parent because we need to return the parent
|
||||
// object, so the parent itself might not be in the editable area, but
|
||||
// it's OK if we're not performing a block-level action.
|
||||
// XXX Here is too slow. Let's cache active editing host first, then,
|
||||
// compair with container of the point when we climb up the tree.
|
||||
bool blockLevelAction =
|
||||
aEditSubAction == EditSubAction::eIndent ||
|
||||
aEditSubAction == EditSubAction::eOutdent ||
|
||||
aEditSubAction == EditSubAction::eSetOrClearAlignment ||
|
||||
aEditSubAction == EditSubAction::eCreateOrRemoveBlock;
|
||||
if (!IsDescendantOfEditorRoot(point.GetContainer()->GetParentNode()) &&
|
||||
(blockLevelAction || !IsDescendantOfEditorRoot(point.GetContainer()))) {
|
||||
break;
|
||||
}
|
||||
|
||||
point.Set(point.GetContainer());
|
||||
}
|
||||
return point;
|
||||
}
|
||||
|
||||
EditorDOMPoint HTMLEditor::GetCurrentHardLineEndPoint(
|
||||
const RangeBoundary& aPoint) {
|
||||
if (NS_WARN_IF(!aPoint.IsSet())) {
|
||||
return EditorDOMPoint();
|
||||
}
|
||||
|
||||
EditorDOMPoint point(aPoint);
|
||||
// Start scanning from the container node if aPoint is in a text node.
|
||||
// XXX Perhaps, IsInDataNode() must be expected.
|
||||
if (point.IsInTextNode()) {
|
||||
if (!point.GetContainer()->GetParentNode()) {
|
||||
// Okay, can't promote any further
|
||||
// XXX Why don't we return end of the text node?
|
||||
return point;
|
||||
}
|
||||
// want to be after the text node
|
||||
|
@ -6983,7 +6988,7 @@ EditorDOMPoint HTMLEditRules::GetPromotedPoint(
|
|||
"Failed to advance offset to after the text node");
|
||||
}
|
||||
|
||||
// look ahead through any further inline nodes that aren't across a <br> from
|
||||
// Look ahead through any further inline nodes that aren't across a <br> from
|
||||
// us, and that are enclosed in the same block.
|
||||
// XXX Currently, we stop block-extending when finding visible <br> element.
|
||||
// This might be different from "block-extend" of execCommand spec.
|
||||
|
@ -6997,49 +7002,53 @@ EditorDOMPoint HTMLEditRules::GetPromotedPoint(
|
|||
// * <div contenteditable>foo[]<b contenteditable="false">bar</b>baz</div>
|
||||
// Only in the first case, after the caret position isn't wrapped with
|
||||
// new <div> element.
|
||||
nsCOMPtr<nsIContent> nextNode =
|
||||
HTMLEditorRef().GetNextEditableHTMLNodeInBlock(point);
|
||||
|
||||
while (nextNode && !HTMLEditor::NodeIsBlockStatic(*nextNode) &&
|
||||
nextNode->GetParentNode()) {
|
||||
point.Set(nextNode);
|
||||
for (nsIContent* nextEditableContent = GetNextEditableHTMLNodeInBlock(point);
|
||||
nextEditableContent &&
|
||||
!HTMLEditor::NodeIsBlockStatic(*nextEditableContent) &&
|
||||
nextEditableContent->GetParent();
|
||||
nextEditableContent = GetNextEditableHTMLNodeInBlock(point)) {
|
||||
point.Set(nextEditableContent);
|
||||
if (NS_WARN_IF(!point.AdvanceOffset())) {
|
||||
break;
|
||||
}
|
||||
if (HTMLEditorRef().IsVisibleBRElement(nextNode)) {
|
||||
if (IsVisibleBRElement(nextEditableContent)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Check for newlines in pre-formatted text nodes.
|
||||
if (EditorBase::IsPreformatted(nextNode) &&
|
||||
EditorBase::IsTextNode(nextNode)) {
|
||||
nsAutoString tempString;
|
||||
nextNode->GetAsText()->GetData(tempString);
|
||||
int32_t newlinePos = tempString.FindChar(nsCRT::LF);
|
||||
if (EditorBase::IsPreformatted(nextEditableContent) &&
|
||||
EditorBase::IsTextNode(nextEditableContent)) {
|
||||
nsAutoString textContent;
|
||||
nextEditableContent->GetAsText()->GetData(textContent);
|
||||
int32_t newlinePos = textContent.FindChar(nsCRT::LF);
|
||||
if (newlinePos >= 0) {
|
||||
if (static_cast<uint32_t>(newlinePos) + 1 == tempString.Length()) {
|
||||
if (static_cast<uint32_t>(newlinePos) + 1 == textContent.Length()) {
|
||||
// No need for special processing if the newline is at the end.
|
||||
break;
|
||||
}
|
||||
return EditorDOMPoint(nextNode, newlinePos + 1);
|
||||
return EditorDOMPoint(nextEditableContent, newlinePos + 1);
|
||||
}
|
||||
}
|
||||
nextNode = HTMLEditorRef().GetNextEditableHTMLNodeInBlock(point);
|
||||
}
|
||||
|
||||
// finding the real end for this point. look up the tree for as long as we
|
||||
// are the last node in the container, and as long as we haven't hit the body
|
||||
// Finding the real end for this point unless current line ends with a <br>
|
||||
// element. Look up the tree for as long as we are the last node in the
|
||||
// container (typically, block node), and as long as we haven't hit the body
|
||||
// node.
|
||||
nsCOMPtr<nsIContent> nearNode =
|
||||
HTMLEditorRef().GetNextEditableHTMLNodeInBlock(point);
|
||||
while (!nearNode && !point.IsContainerHTMLElement(nsGkAtoms::body) &&
|
||||
point.GetContainer()->GetParentNode()) {
|
||||
for (nsIContent* nearContent = GetNextEditableHTMLNodeInBlock(point);
|
||||
!nearContent && !point.IsContainerHTMLElement(nsGkAtoms::body) &&
|
||||
point.GetContainer()->GetParentNode();
|
||||
nearContent = GetNextEditableHTMLNodeInBlock(point)) {
|
||||
// Don't walk past the editable section. Note that we need to check before
|
||||
// walking up to a parent because we need to return the parent object, so
|
||||
// the parent itself might not be in the editable area, but it's OK.
|
||||
if (!HTMLEditorRef().IsDescendantOfEditorRoot(point.GetContainer()) &&
|
||||
!HTMLEditorRef().IsDescendantOfEditorRoot(
|
||||
point.GetContainer()->GetParentNode())) {
|
||||
// XXX Maybe returning parent of editing host is really error prone since
|
||||
// everybody need to check whether the end point is in editing host
|
||||
// when they touch there.
|
||||
// XXX Here is too slow. Let's cache active editing host first, then,
|
||||
// compair with container of the point when we climb up the tree.
|
||||
if (!IsDescendantOfEditorRoot(point.GetContainer()) &&
|
||||
!IsDescendantOfEditorRoot(point.GetContainer()->GetParentNode())) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -7047,7 +7056,6 @@ EditorDOMPoint HTMLEditRules::GetPromotedPoint(
|
|||
if (NS_WARN_IF(!point.AdvanceOffset())) {
|
||||
break;
|
||||
}
|
||||
nearNode = HTMLEditorRef().GetNextEditableHTMLNodeInBlock(point);
|
||||
}
|
||||
return point;
|
||||
}
|
||||
|
@ -7090,9 +7098,11 @@ void HTMLEditRules::PromoteRange(nsRange& aRange,
|
|||
int32_t endOffset = aRange.EndOffset();
|
||||
|
||||
// MOOSE major hack:
|
||||
// GetPromotedPoint doesn't really do the right thing for collapsed ranges
|
||||
// The following methods don't really do the right thing for collapsed ranges
|
||||
// inside block elements that contain nothing but a solo <br>. It's easier
|
||||
// to put a workaround here than to revamp GetPromotedPoint. :-(
|
||||
// to put a workaround here than to revamp them. :-(
|
||||
// XXX This sounds odd in the cases using `GetWhiteSpaceEndPoint()`. Don't
|
||||
// we hack something in the edit sub-action handlers?
|
||||
if (startNode == endNode && startOffset == endOffset) {
|
||||
RefPtr<Element> block = HTMLEditorRef().GetBlock(*startNode);
|
||||
if (block) {
|
||||
|
@ -7114,44 +7124,81 @@ void HTMLEditRules::PromoteRange(nsRange& aRange,
|
|||
}
|
||||
}
|
||||
|
||||
if (aEditSubAction == EditSubAction::eInsertText ||
|
||||
aEditSubAction == EditSubAction::eInsertTextComingFromIME ||
|
||||
aEditSubAction == EditSubAction::eInsertLineBreak ||
|
||||
aEditSubAction == EditSubAction::eInsertParagraphSeparator ||
|
||||
aEditSubAction == EditSubAction::eDeleteText) {
|
||||
if (!startNode->IsContent() || !endNode->IsContent()) {
|
||||
// GetPromotedPoint cannot promote node when action type is text
|
||||
// operation and selected node isn't content node.
|
||||
return;
|
||||
switch (aEditSubAction) {
|
||||
case EditSubAction::eInsertText:
|
||||
case EditSubAction::eInsertTextComingFromIME:
|
||||
case EditSubAction::eInsertLineBreak:
|
||||
case EditSubAction::eInsertParagraphSeparator:
|
||||
case EditSubAction::eDeleteText: {
|
||||
if (!startNode->IsContent() || !endNode->IsContent()) {
|
||||
return;
|
||||
}
|
||||
// For text actions, we want to look backwards (or forwards, as
|
||||
// appropriate) for additional whitespace or nbsp's. We may have to act
|
||||
// on these later even though they are outside of the initial selection.
|
||||
// Even if they are in another node!
|
||||
// XXX Although the comment mentioned that this may scan other text nodes,
|
||||
// GetWhiteSpaceEndPoint() scans only in given container node.
|
||||
// XXX Looks like that we should make GetWhiteSpaceEndPoint() be a
|
||||
// instance method and stop scanning whitespaces when it reaches
|
||||
// active editing host.
|
||||
EditorDOMPoint startPoint = HTMLEditor::GetWhiteSpaceEndPoint(
|
||||
RangeBoundary(startNode, startOffset),
|
||||
HTMLEditor::ScanDirection::Backward);
|
||||
if (!HTMLEditorRef().IsDescendantOfEditorRoot(
|
||||
EditorBase::GetNodeAtRangeOffsetPoint(startPoint))) {
|
||||
return;
|
||||
}
|
||||
EditorDOMPoint endPoint =
|
||||
HTMLEditor::GetWhiteSpaceEndPoint(RangeBoundary(endNode, endOffset),
|
||||
HTMLEditor::ScanDirection::Forward);
|
||||
EditorRawDOMPoint lastRawPoint(endPoint);
|
||||
lastRawPoint.RewindOffset();
|
||||
if (!HTMLEditorRef().IsDescendantOfEditorRoot(
|
||||
EditorBase::GetNodeAtRangeOffsetPoint(lastRawPoint))) {
|
||||
return;
|
||||
}
|
||||
DebugOnly<nsresult> rvIgnored = aRange.SetStartAndEnd(
|
||||
startPoint.ToRawRangeBoundary(), endPoint.ToRawRangeBoundary());
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rvIgnored));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// Make a new adjusted range to represent the appropriate block content.
|
||||
// This is tricky. The basic idea is to push out the range endpoints to
|
||||
// truly enclose the blocks that we will affect.
|
||||
|
||||
// Make sure that the new range ends up to be in the editable section.
|
||||
// XXX Looks like that this check wastes the time. Perhaps, we should
|
||||
// implement a method which checks both two DOM points in the editor
|
||||
// root.
|
||||
|
||||
EditorDOMPoint startPoint = HTMLEditorRef().GetCurrentHardLineStartPoint(
|
||||
RangeBoundary(startNode, startOffset), aEditSubAction);
|
||||
// XXX GetCurrentHardLineStartPoint() may return point of editing host.
|
||||
// Perhaps, we should change it and stop checking it here since
|
||||
// this check may be expensive.
|
||||
if (!HTMLEditorRef().IsDescendantOfEditorRoot(
|
||||
EditorBase::GetNodeAtRangeOffsetPoint(startPoint))) {
|
||||
return;
|
||||
}
|
||||
EditorDOMPoint endPoint = HTMLEditorRef().GetCurrentHardLineEndPoint(
|
||||
RangeBoundary(endNode, endOffset));
|
||||
EditorRawDOMPoint lastRawPoint(endPoint);
|
||||
lastRawPoint.RewindOffset();
|
||||
// XXX GetCurrentHardLineEndPoint() may return point of editing host.
|
||||
// Perhaps, we should change it and stop checking it here since this
|
||||
// check may be expensive.
|
||||
if (!HTMLEditorRef().IsDescendantOfEditorRoot(
|
||||
EditorBase::GetNodeAtRangeOffsetPoint(lastRawPoint))) {
|
||||
return;
|
||||
}
|
||||
DebugOnly<nsresult> rvIgnored = aRange.SetStartAndEnd(
|
||||
startPoint.ToRawRangeBoundary(), endPoint.ToRawRangeBoundary());
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rvIgnored));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Make a new adjusted range to represent the appropriate block content.
|
||||
// This is tricky. The basic idea is to push out the range endpoints to
|
||||
// truly enclose the blocks that we will affect.
|
||||
|
||||
// Make sure that the new range ends up to be in the editable section.
|
||||
// XXX Looks like that this check wastes the time. Perhaps, we should
|
||||
// implement a method which checks both two DOM points in the editor
|
||||
// root.
|
||||
EditorDOMPoint startPoint =
|
||||
GetPromotedPoint(kStart, *startNode, startOffset, aEditSubAction);
|
||||
if (!HTMLEditorRef().IsDescendantOfEditorRoot(
|
||||
EditorBase::GetNodeAtRangeOffsetPoint(startPoint))) {
|
||||
return;
|
||||
}
|
||||
EditorDOMPoint endPoint =
|
||||
GetPromotedPoint(kEnd, *endNode, endOffset, aEditSubAction);
|
||||
EditorRawDOMPoint lastRawPoint(endPoint);
|
||||
lastRawPoint.RewindOffset();
|
||||
if (!HTMLEditorRef().IsDescendantOfEditorRoot(
|
||||
EditorBase::GetNodeAtRangeOffsetPoint(lastRawPoint))) {
|
||||
return;
|
||||
}
|
||||
|
||||
DebugOnly<nsresult> rv = aRange.SetStartAndEnd(
|
||||
startPoint.ToRawRangeBoundary(), endPoint.ToRawRangeBoundary());
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
}
|
||||
|
||||
class UniqueFunctor final : public BoolDomIterFunctor {
|
||||
|
@ -7196,9 +7243,8 @@ nsresult HTMLEditor::SplitInlinesAndCollectEditTargetNodes(
|
|||
|
||||
nsresult HTMLEditor::SplitTextNodesAtRangeEnd(
|
||||
nsTArray<RefPtr<nsRange>>& aArrayOfRanges) {
|
||||
// Split text nodes. This is necessary, since GetPromotedPoint() may return
|
||||
// a range ending in a text node in case where part of a pre-formatted
|
||||
// elements needs to be moved.
|
||||
// Split text nodes. This is necessary, since given ranges may end in text
|
||||
// nodes in case where part of a pre-formatted elements needs to be moved.
|
||||
for (RefPtr<nsRange>& range : aArrayOfRanges) {
|
||||
EditorDOMPoint atEnd(range->EndRef());
|
||||
if (NS_WARN_IF(!atEnd.IsSet()) || !atEnd.IsInTextNode()) {
|
||||
|
|
|
@ -118,8 +118,6 @@ class HTMLEditRules : public TextEditRules {
|
|||
return mData->HTMLEditorRef();
|
||||
}
|
||||
|
||||
enum RulesEndpoint { kStart, kEnd };
|
||||
|
||||
/**
|
||||
* WillInsertParagraphSeparator() is called when insertParagraph command is
|
||||
* executed or something equivalent. This method actually tries to insert
|
||||
|
@ -788,14 +786,6 @@ class HTMLEditRules : public TextEditRules {
|
|||
MOZ_CAN_RUN_SCRIPT
|
||||
MOZ_MUST_USE nsresult NormalizeSelection();
|
||||
|
||||
/**
|
||||
* GetPromotedPoint() figures out where a start or end point for a block
|
||||
* operation really is.
|
||||
*/
|
||||
EditorDOMPoint GetPromotedPoint(RulesEndpoint aWhere, nsINode& aNode,
|
||||
int32_t aOffset,
|
||||
EditSubAction aEditSubAction) const;
|
||||
|
||||
/**
|
||||
* GetPromotedRanges() runs all the selection range endpoint through
|
||||
* GetPromotedPoint().
|
||||
|
|
|
@ -1320,6 +1320,39 @@ class HTMLEditor final : public TextEditor,
|
|||
nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes,
|
||||
EditSubAction aEditSubAction) const;
|
||||
|
||||
/**
|
||||
* GetWhiteSpaceEndPoint() returns point at first or last ASCII whitespace
|
||||
* or non-breakable space starting from aPoint. I.e., this returns next or
|
||||
* previous point whether the character is neither ASCII whitespace nor
|
||||
* non-brekable space.
|
||||
*/
|
||||
enum class ScanDirection { Backward, Forward };
|
||||
static EditorDOMPoint GetWhiteSpaceEndPoint(const RangeBoundary& aPoint,
|
||||
ScanDirection aScanDirection);
|
||||
|
||||
/**
|
||||
* GetCurrentHardLineStartPoint() returns start point of hard line
|
||||
* including aPoint. If the line starts after a `<br>` element, returns
|
||||
* next sibling of the `<br>` element. If the line is first line of a block,
|
||||
* returns point of the block.
|
||||
* NOTE: The result may be point of editing host. I.e., the container may
|
||||
* be outside of editing host.
|
||||
*/
|
||||
EditorDOMPoint GetCurrentHardLineStartPoint(const RangeBoundary& aPoint,
|
||||
EditSubAction aEditSubAction);
|
||||
|
||||
/**
|
||||
* GetCurrentHardLineEndPoint() returns end point of hard line including
|
||||
* aPoint. If the line ends with a `<br>` element, returns the `<br>`
|
||||
* element unless it's the last node of a block. If the line is last line
|
||||
* of a block, returns next sibling of the block. Additionally, if the
|
||||
* line ends with a linefeed in pre-formated text node, returns point of
|
||||
* the linefeed.
|
||||
* NOTE: This result may be point of editing host. I.e., the container
|
||||
* may be outside of editing host.
|
||||
*/
|
||||
EditorDOMPoint GetCurrentHardLineEndPoint(const RangeBoundary& aPoint);
|
||||
|
||||
protected: // Called by helper classes.
|
||||
virtual void OnStartToHandleTopLevelEditSubAction(
|
||||
EditSubAction aEditSubAction, nsIEditor::EDirection aDirection) override;
|
||||
|
|
Загрузка…
Ссылка в новой задаче