зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1574852 - part 105: Get rid of `TextEditRules::WillSetProperty()` and `TextEditRules::WillRemoveProperty()` r=m_kato
Oddly, they are used only by `HTMLEditor`, but implemented by `TextEditRules`. They cancels when the editor is in plaintext mode. So, actual things are implemented by each caller. This patch cleans them up too. Differential Revision: https://phabricator.services.mozilla.com/D45299 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
f521a40385
Коммит
72fa9d1512
|
@ -809,9 +809,11 @@ nsresult HTMLEditRules::WillDoAction(EditSubActionInfo& aInfo, bool* aCancel,
|
|||
case EditSubAction::eUndo:
|
||||
case EditSubAction::eRedo:
|
||||
case EditSubAction::eRemoveList:
|
||||
case EditSubAction::eRemoveTextProperty:
|
||||
case EditSubAction::eSetOrClearAlignment:
|
||||
case EditSubAction::eSetPositionToAbsolute:
|
||||
case EditSubAction::eSetPositionToStatic:
|
||||
case EditSubAction::eSetTextProperty:
|
||||
MOZ_ASSERT_UNREACHABLE("This path should've been dead code");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
default:
|
||||
|
@ -847,9 +849,11 @@ nsresult HTMLEditRules::DidDoAction(EditSubActionInfo& aInfo,
|
|||
case EditSubAction::eUndo:
|
||||
case EditSubAction::eRedo:
|
||||
case EditSubAction::eRemoveList:
|
||||
case EditSubAction::eRemoveTextProperty:
|
||||
case EditSubAction::eSetOrClearAlignment:
|
||||
case EditSubAction::eSetPositionToAbsolute:
|
||||
case EditSubAction::eSetPositionToStatic:
|
||||
case EditSubAction::eSetTextProperty:
|
||||
MOZ_ASSERT_UNREACHABLE("This path should've been dead code");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
default:
|
||||
|
|
|
@ -4150,142 +4150,161 @@ nsresult HTMLEditor::SetCSSBackgroundColorWithTransaction(
|
|||
|
||||
CommitComposition();
|
||||
|
||||
// Protect the edit rules object from dying
|
||||
RefPtr<TextEditRules> rules(mRules);
|
||||
// XXX Shouldn't we do this before calling `CommitComposition()`?
|
||||
if (IsPlaintextEditor()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool isCollapsed = SelectionRefPtr()->IsCollapsed();
|
||||
EditActionResult result = CanHandleHTMLEditSubAction();
|
||||
if (NS_WARN_IF(result.Failed()) || result.Canceled()) {
|
||||
return result.Rv();
|
||||
}
|
||||
|
||||
bool selectionIsCollapsed = SelectionRefPtr()->IsCollapsed();
|
||||
|
||||
AutoPlaceholderBatch treatAsOneTransaction(*this);
|
||||
AutoEditSubActionNotifier startToHandleEditSubAction(
|
||||
*this, EditSubAction::eInsertElement, nsIEditor::eNext);
|
||||
AutoSelectionRestorer restoreSelectionLater(*this);
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(*this);
|
||||
|
||||
// XXX Although, this method may set background color of ancestor block
|
||||
// element, using EditSubAction::eSetTextProperty.
|
||||
bool cancel, handled;
|
||||
EditSubActionInfo subActionInfo(EditSubAction::eSetTextProperty);
|
||||
nsresult rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
if (!cancel && !handled) {
|
||||
{
|
||||
AutoSelectionRestorer restoreSelectionLater(*this);
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(*this);
|
||||
|
||||
// Loop through the ranges in the selection
|
||||
// XXX This is different from `SetInlinePropertyInternal()`. It uses
|
||||
// AutoRangeArray to store all ranges first. The result may be
|
||||
// different if mutation event listener changes the `Selection`.
|
||||
for (uint32_t i = 0; i < SelectionRefPtr()->RangeCount(); i++) {
|
||||
RefPtr<nsRange> range = SelectionRefPtr()->GetRangeAt(i);
|
||||
if (NS_WARN_IF(!range)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<Element> cachedBlockParent;
|
||||
EditorDOMPoint startOfRange(range->StartRef());
|
||||
EditorDOMPoint endOfRange(range->EndRef());
|
||||
if (NS_WARN_IF(!startOfRange.IsSet()) ||
|
||||
NS_WARN_IF(!endOfRange.IsSet())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for easy case: both range endpoints in same text node
|
||||
nsCOMPtr<nsINode> startNode = range->GetStartContainer();
|
||||
int32_t startOffset = range->StartOffset();
|
||||
nsCOMPtr<nsINode> endNode = range->GetEndContainer();
|
||||
int32_t endOffset = range->EndOffset();
|
||||
if (startNode == endNode && IsTextNode(startNode)) {
|
||||
// Let's find the block container of the text node
|
||||
nsCOMPtr<Element> blockParent = GetBlockNodeParent(startNode);
|
||||
// And apply the background color to that block container
|
||||
if (blockParent && cachedBlockParent != blockParent) {
|
||||
cachedBlockParent = blockParent;
|
||||
mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
|
||||
blockParent, nullptr, nsGkAtoms::bgcolor, &aColor, false);
|
||||
}
|
||||
} else if (startNode == endNode &&
|
||||
startNode->IsHTMLElement(nsGkAtoms::body) && isCollapsed) {
|
||||
// No block in the document, let's apply the background to the body
|
||||
mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
|
||||
MOZ_KnownLive(startNode->AsElement()), nullptr, nsGkAtoms::bgcolor,
|
||||
&aColor, false);
|
||||
} else if (startNode == endNode && (endOffset - startOffset == 1 ||
|
||||
(!startOffset && !endOffset))) {
|
||||
// A unique node is selected, let's also apply the background color to
|
||||
// the containing block, possibly the node itself
|
||||
nsCOMPtr<nsIContent> selectedNode = range->GetChildAtStartOffset();
|
||||
nsCOMPtr<Element> blockParent = GetBlock(*selectedNode);
|
||||
if (blockParent && cachedBlockParent != blockParent) {
|
||||
cachedBlockParent = blockParent;
|
||||
mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
|
||||
blockParent, nullptr, nsGkAtoms::bgcolor, &aColor, false);
|
||||
}
|
||||
} else {
|
||||
// Not the easy case. Range not contained in single text node. There
|
||||
// are up to three phases here. There are all the nodes reported by
|
||||
// the subtree iterator to be processed. And there are potentially a
|
||||
// starting textnode and an ending textnode which are only partially
|
||||
// contained by the range.
|
||||
|
||||
// Let's handle the nodes reported by the iterator. These nodes are
|
||||
// entirely contained in the selection range. We build up a list of
|
||||
// them (since doing operations on the document during iteration would
|
||||
// perturb the iterator).
|
||||
|
||||
nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
|
||||
nsCOMPtr<nsINode> node;
|
||||
|
||||
// Iterate range and build up array
|
||||
ContentSubtreeIterator subtreeIter;
|
||||
rv = subtreeIter.Init(range);
|
||||
// Init returns an error if no nodes in range. This can easily happen
|
||||
// with the subtree iterator if the selection doesn't contain any
|
||||
// *whole* nodes.
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
for (; !subtreeIter.IsDone(); subtreeIter.Next()) {
|
||||
node = subtreeIter.GetCurrentNode();
|
||||
NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
|
||||
|
||||
if (IsEditable(node)) {
|
||||
arrayOfNodes.AppendElement(*node);
|
||||
if (startOfRange.GetContainer() == endOfRange.GetContainer()) {
|
||||
// If the range is in a text node, set background color of its parent
|
||||
// block.
|
||||
if (startOfRange.IsInTextNode()) {
|
||||
if (RefPtr<Element> blockParent =
|
||||
GetBlockNodeParent(startOfRange.GetContainer())) {
|
||||
mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
|
||||
blockParent, nullptr, nsGkAtoms::bgcolor, &aColor, false);
|
||||
if (NS_WARN_IF(Destroyed())) {
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
}
|
||||
}
|
||||
}
|
||||
// First check the start parent of the range to see if it needs to be
|
||||
// separately handled (it does if it's a text node, due to how the
|
||||
// subtree iterator works - it will not have reported it).
|
||||
if (IsTextNode(startNode) && IsEditable(startNode)) {
|
||||
nsCOMPtr<Element> blockParent = GetBlockNodeParent(startNode);
|
||||
if (blockParent && cachedBlockParent != blockParent) {
|
||||
cachedBlockParent = blockParent;
|
||||
mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
|
||||
blockParent, nullptr, nsGkAtoms::bgcolor, &aColor, false);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Then loop through the list, set the property on each node
|
||||
for (auto& node : arrayOfNodes) {
|
||||
nsCOMPtr<Element> blockParent = GetBlock(node);
|
||||
if (blockParent && cachedBlockParent != blockParent) {
|
||||
cachedBlockParent = blockParent;
|
||||
// If `Selection` is collapsed in a `<body>` element, set background
|
||||
// color of the `<body>` element.
|
||||
// XXX Why do we refer whether the `Selection` is collapsed rather
|
||||
// than the `nsRange` is collapsed?
|
||||
if (startOfRange.GetContainer()->IsHTMLElement(nsGkAtoms::body) &&
|
||||
selectionIsCollapsed) {
|
||||
mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
|
||||
MOZ_KnownLive(startOfRange.GetContainerAsElement()), nullptr,
|
||||
nsGkAtoms::bgcolor, &aColor, false);
|
||||
if (NS_WARN_IF(Destroyed())) {
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// If one node is selected, set background color of it if it's a
|
||||
// block, or of its parent block otherwise.
|
||||
if ((startOfRange.IsStartOfContainer() &&
|
||||
endOfRange.IsStartOfContainer()) ||
|
||||
startOfRange.Offset() + 1 == endOfRange.Offset()) {
|
||||
if (NS_WARN_IF(startOfRange.IsInDataNode())) {
|
||||
continue;
|
||||
}
|
||||
if (RefPtr<Element> blockParent =
|
||||
GetBlock(*startOfRange.GetChild())) {
|
||||
mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
|
||||
blockParent, nullptr, nsGkAtoms::bgcolor, &aColor, false);
|
||||
if (NS_WARN_IF(Destroyed())) {
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Collect editable nodes which are entirely contained in the range.
|
||||
AutoTArray<OwningNonNull<nsIContent>, 64> arrayOfContents;
|
||||
ContentSubtreeIterator subtreeIter;
|
||||
// If there is no node which is entirely in the range,
|
||||
// `ContentSubtreeIterator::Init()` fails, but this is possible case,
|
||||
// don't warn it.
|
||||
if (NS_SUCCEEDED(subtreeIter.Init(range))) {
|
||||
for (; !subtreeIter.IsDone(); subtreeIter.Next()) {
|
||||
nsINode* node = subtreeIter.GetCurrentNode();
|
||||
if (NS_WARN_IF(!node)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (node->IsContent() && IsEditable(node)) {
|
||||
arrayOfContents.AppendElement(*node->AsContent());
|
||||
}
|
||||
}
|
||||
arrayOfNodes.Clear();
|
||||
}
|
||||
|
||||
// Last, check the end parent of the range to see if it needs to be
|
||||
// separately handled (it does if it's a text node, due to how the
|
||||
// subtree iterator works - it will not have reported it).
|
||||
if (IsTextNode(endNode) && IsEditable(endNode)) {
|
||||
nsCOMPtr<Element> blockParent = GetBlockNodeParent(endNode);
|
||||
if (blockParent && cachedBlockParent != blockParent) {
|
||||
cachedBlockParent = blockParent;
|
||||
mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
|
||||
blockParent, nullptr, nsGkAtoms::bgcolor, &aColor, false);
|
||||
// This caches block parent if we set its background color.
|
||||
RefPtr<Element> handledBlockParent;
|
||||
|
||||
// If start node is a text node, set background color of its parent
|
||||
// block.
|
||||
if (startOfRange.IsInTextNode() &&
|
||||
IsEditable(startOfRange.GetContainer())) {
|
||||
RefPtr<Element> blockParent =
|
||||
GetBlockNodeParent(startOfRange.GetContainer());
|
||||
if (blockParent && handledBlockParent != blockParent) {
|
||||
handledBlockParent = blockParent;
|
||||
mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
|
||||
blockParent, nullptr, nsGkAtoms::bgcolor, &aColor, false);
|
||||
if (NS_WARN_IF(Destroyed())) {
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Then, set background color of each block or block parent of all nodes
|
||||
// in the range entirely.
|
||||
for (auto& content : arrayOfContents) {
|
||||
RefPtr<Element> blockParent = GetBlock(content);
|
||||
if (blockParent && handledBlockParent != blockParent) {
|
||||
handledBlockParent = blockParent;
|
||||
mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
|
||||
blockParent, nullptr, nsGkAtoms::bgcolor, &aColor, false);
|
||||
if (NS_WARN_IF(Destroyed())) {
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, if end node is a text node, set background color of its
|
||||
// parent block.
|
||||
if (endOfRange.IsInTextNode() && IsEditable(endOfRange.GetContainer())) {
|
||||
RefPtr<Element> blockParent =
|
||||
GetBlockNodeParent(endOfRange.GetContainer());
|
||||
if (blockParent && handledBlockParent != blockParent) {
|
||||
mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
|
||||
blockParent, nullptr, nsGkAtoms::bgcolor, &aColor, false);
|
||||
if (NS_WARN_IF(Destroyed())) {
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!cancel) {
|
||||
// Post-process
|
||||
rv = rules->DidDoAction(subActionInfo, rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
|
||||
// Restoring `Selection` may cause destroying us.
|
||||
return NS_WARN_IF(Destroyed()) ? NS_ERROR_EDITOR_DESTROYED : NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -4307,8 +4326,10 @@ nsresult HTMLEditor::SetBackgroundColorAsAction(const nsAString& aColor,
|
|||
// if we are in CSS mode, we have to apply the background color to the
|
||||
// containing block (or the body if we have no block-level element in
|
||||
// the document)
|
||||
return EditorBase::ToGenericNSResult(
|
||||
SetCSSBackgroundColorWithTransaction(aColor));
|
||||
nsresult rv = SetCSSBackgroundColorWithTransaction(aColor);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"SetCSSBackgroundColorWithTransaction() failed");
|
||||
return EditorBase::ToGenericNSResult(rv);
|
||||
}
|
||||
|
||||
// but in HTML mode, we can only set the document's background color
|
||||
|
|
|
@ -3243,11 +3243,33 @@ class HTMLEditor final : public TextEditor,
|
|||
MOZ_CAN_RUN_SCRIPT
|
||||
nsresult LoadHTML(const nsAString& aInputString);
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
nsresult SetInlinePropertyInternal(nsAtom& aProperty, nsAtom* aAttribute,
|
||||
const nsAString& aValue);
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
nsresult RemoveInlinePropertyInternal(nsAtom* aProperty, nsAtom* aAttribute);
|
||||
/**
|
||||
* SetInlinePropertyInternal() stores new style with `mTypeInState` if
|
||||
* `Selection` is collapsed. Otherwise, applying the style at all selection
|
||||
* ranges.
|
||||
*
|
||||
* @param aProperty One of the presentation tag names which we
|
||||
* support in style editor.
|
||||
* @param aAttribute For some aProperty values, needs to be set to
|
||||
* its attribute name. Otherwise, nullptr.
|
||||
* @param aAttributeValue The value of aAttribute.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE nsresult SetInlinePropertyInternal(
|
||||
nsAtom& aProperty, nsAtom* aAttribute, const nsAString& aValue);
|
||||
|
||||
/**
|
||||
* RemoveInlinePropertyInternal() removes specified style from `mTypeInState`
|
||||
* if `Selection` is collapsed. Otherwise, removing the style.
|
||||
* XXX Looks like that this has a lot of bugs in HTML mode.
|
||||
*
|
||||
* @param aProperty nullptr if you want to remove all inline styles.
|
||||
* Otherwise, one of the presentation tag names
|
||||
* which we support in style editor.
|
||||
* @param aAttribute For some aProperty values, need to be set to
|
||||
* its attribute name. Otherwise, nullptr.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE nsresult
|
||||
RemoveInlinePropertyInternal(nsAtom* aProperty, nsAtom* aAttribute);
|
||||
|
||||
/**
|
||||
* ReplaceHeadContentsWithSourceWithTransaction() replaces all children of
|
||||
|
@ -3272,10 +3294,10 @@ class HTMLEditor final : public TextEditor,
|
|||
* This sets background on the appropriate container element (table, cell,)
|
||||
* or calls into nsTextEditor to set the page background.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
nsresult SetCSSBackgroundColorWithTransaction(const nsAString& aColor);
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
nsresult SetHTMLBackgroundColorWithTransaction(const nsAString& aColor);
|
||||
MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE nsresult
|
||||
SetCSSBackgroundColorWithTransaction(const nsAString& aColor);
|
||||
MOZ_CAN_RUN_SCRIPT nsresult
|
||||
SetHTMLBackgroundColorWithTransaction(const nsAString& aColor);
|
||||
|
||||
virtual void InitializeSelectionAncestorLimit(
|
||||
nsIContent& aAncestorLimit) override;
|
||||
|
|
|
@ -100,10 +100,8 @@ nsresult HTMLEditor::SetInlinePropertyAsAction(nsAtom& aProperty,
|
|||
}
|
||||
}
|
||||
nsresult rv = SetInlinePropertyInternal(aProperty, aAttribute, aValue);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return EditorBase::ToGenericNSResult(rv);
|
||||
}
|
||||
return NS_OK;
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "SetInlinePropertyInternal() failed");
|
||||
return EditorBase::ToGenericNSResult(rv);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -135,138 +133,145 @@ HTMLEditor::SetInlineProperty(const nsAString& aProperty,
|
|||
break;
|
||||
}
|
||||
nsresult rv = SetInlinePropertyInternal(*property, attribute, aValue);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return EditorBase::ToGenericNSResult(rv);
|
||||
}
|
||||
return NS_OK;
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "SetInlinePropertyInternal() failed");
|
||||
return EditorBase::ToGenericNSResult(rv);
|
||||
}
|
||||
|
||||
nsresult HTMLEditor::SetInlinePropertyInternal(nsAtom& aProperty,
|
||||
nsAtom* aAttribute,
|
||||
const nsAString& aValue) {
|
||||
nsresult HTMLEditor::SetInlinePropertyInternal(
|
||||
nsAtom& aProperty, nsAtom* aAttribute, const nsAString& aAttributeValue) {
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
if (NS_WARN_IF(!mRules)) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
RefPtr<TextEditRules> rules(mRules);
|
||||
CommitComposition();
|
||||
|
||||
if (SelectionRefPtr()->IsCollapsed()) {
|
||||
// Manipulating text attributes on a collapsed selection only sets state
|
||||
// for the next text insertion
|
||||
mTypeInState->SetProp(&aProperty, aAttribute, aValue);
|
||||
mTypeInState->SetProp(&aProperty, aAttribute, aAttributeValue);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// XXX Shouldn't we return before calling `CommitComposition()`?
|
||||
if (IsPlaintextEditor()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
EditActionResult result = CanHandleHTMLEditSubAction();
|
||||
if (NS_WARN_IF(result.Failed()) || result.Canceled()) {
|
||||
return result.Rv();
|
||||
}
|
||||
|
||||
AutoPlaceholderBatch treatAsOneTransaction(*this);
|
||||
AutoEditSubActionNotifier startToHandleEditSubAction(
|
||||
*this, EditSubAction::eInsertElement, nsIEditor::eNext);
|
||||
AutoSelectionRestorer restoreSelectionLater(*this);
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(*this);
|
||||
|
||||
bool cancel, handled;
|
||||
EditSubActionInfo subActionInfo(EditSubAction::eSetTextProperty);
|
||||
// Protect the edit rules object from dying
|
||||
nsresult rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
if (!cancel && !handled) {
|
||||
{
|
||||
AutoSelectionRestorer restoreSelectionLater(*this);
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(*this);
|
||||
|
||||
// Loop through the ranges in the selection
|
||||
// XXX This is different from `SetCSSBackgroundColorWithTransaction()`.
|
||||
// It refers `Selection::GetRangeAt()` in each time. The result may
|
||||
// be different if mutation event listener changes the `Selection`.
|
||||
AutoRangeArray arrayOfRanges(SelectionRefPtr());
|
||||
for (auto& range : arrayOfRanges.mRanges) {
|
||||
// Adjust range to include any ancestors whose children are entirely
|
||||
// selected
|
||||
rv = PromoteInlineRange(*range);
|
||||
nsresult rv = PromoteInlineRange(*range);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Check for easy case: both range endpoints in same text node
|
||||
nsCOMPtr<nsINode> startNode = range->GetStartContainer();
|
||||
nsCOMPtr<nsINode> endNode = range->GetEndContainer();
|
||||
if (startNode && startNode == endNode && startNode->GetAsText()) {
|
||||
rv = SetInlinePropertyOnTextNode(
|
||||
MOZ_KnownLive(*startNode->GetAsText()), range->StartOffset(),
|
||||
range->EndOffset(), aProperty, aAttribute, aValue);
|
||||
// XXX Shouldn't we skip the range if it's been collapsed by mutation
|
||||
// event listener?
|
||||
|
||||
EditorDOMPoint startOfRange(range->StartRef());
|
||||
EditorDOMPoint endOfRange(range->EndRef());
|
||||
if (NS_WARN_IF(!startOfRange.IsSet()) ||
|
||||
NS_WARN_IF(!endOfRange.IsSet())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If range is in a text node, apply new style simply.
|
||||
if (startOfRange.GetContainer() == endOfRange.GetContainer() &&
|
||||
startOfRange.IsInTextNode()) {
|
||||
nsresult rv = SetInlinePropertyOnTextNode(
|
||||
MOZ_KnownLive(*startOfRange.GetContainerAsText()),
|
||||
startOfRange.Offset(), endOfRange.Offset(), aProperty, aAttribute,
|
||||
aAttributeValue);
|
||||
if (NS_WARN_IF(Destroyed())) {
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Not the easy case. Range not contained in single text node. There
|
||||
// are up to three phases here. There are all the nodes reported by the
|
||||
// subtree iterator to be processed. And there are potentially a
|
||||
// starting textnode and an ending textnode which are only partially
|
||||
// contained by the range.
|
||||
|
||||
// Let's handle the nodes reported by the iterator. These nodes are
|
||||
// entirely contained in the selection range. We build up a list of them
|
||||
// (since doing operations on the document during iteration would perturb
|
||||
// the iterator).
|
||||
|
||||
nsTArray<OwningNonNull<nsIContent>> arrayOfNodes;
|
||||
|
||||
// Iterate range and build up array
|
||||
// Collect editable nodes which are entirely contained in the range.
|
||||
AutoTArray<OwningNonNull<nsIContent>, 64> arrayOfContents;
|
||||
ContentSubtreeIterator subtreeIter;
|
||||
rv = subtreeIter.Init(range);
|
||||
// Init returns an error if there are no nodes in range. This can easily
|
||||
// happen with the subtree iterator if the selection doesn't contain any
|
||||
// *whole* nodes.
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// If there is no node which is entirely in the range,
|
||||
// `ContentSubtreeIterator::Init()` fails, but this is possible case,
|
||||
// don't warn it.
|
||||
if (NS_SUCCEEDED(subtreeIter.Init(range))) {
|
||||
for (; !subtreeIter.IsDone(); subtreeIter.Next()) {
|
||||
OwningNonNull<nsINode> node = *subtreeIter.GetCurrentNode();
|
||||
|
||||
nsINode* node = subtreeIter.GetCurrentNode();
|
||||
if (NS_WARN_IF(!node)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (node->IsContent() && IsEditable(node)) {
|
||||
arrayOfNodes.AppendElement(*node->AsContent());
|
||||
arrayOfContents.AppendElement(*node->AsContent());
|
||||
}
|
||||
}
|
||||
}
|
||||
// First check the start parent of the range to see if it needs to be
|
||||
// separately handled (it does if it's a text node, due to how the
|
||||
// subtree iterator works - it will not have reported it).
|
||||
if (startNode && startNode->GetAsText() && IsEditable(startNode)) {
|
||||
rv = SetInlinePropertyOnTextNode(
|
||||
MOZ_KnownLive(*startNode->GetAsText()), range->StartOffset(),
|
||||
startNode->Length(), aProperty, aAttribute, aValue);
|
||||
|
||||
// If start node is a text node, apply new style to a part of it.
|
||||
if (startOfRange.IsInTextNode() &&
|
||||
IsEditable(startOfRange.GetContainer())) {
|
||||
nsresult rv = SetInlinePropertyOnTextNode(
|
||||
MOZ_KnownLive(*startOfRange.GetContainerAsText()),
|
||||
startOfRange.Offset(), startOfRange.GetContainer()->Length(),
|
||||
aProperty, aAttribute, aAttributeValue);
|
||||
if (NS_WARN_IF(Destroyed())) {
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
// Then loop through the list, set the property on each node
|
||||
for (auto& node : arrayOfNodes) {
|
||||
rv = SetInlinePropertyOnNode(*node, aProperty, aAttribute, aValue);
|
||||
// Then, apply new style to all nodes in the range entirely.
|
||||
for (auto& content : arrayOfContents) {
|
||||
nsresult rv = SetInlinePropertyOnNode(*content, aProperty, aAttribute,
|
||||
aAttributeValue);
|
||||
if (NS_WARN_IF(Destroyed())) {
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
// Last check the end parent of the range to see if it needs to be
|
||||
// separately handled (it does if it's a text node, due to how the
|
||||
// subtree iterator works - it will not have reported it).
|
||||
if (endNode && endNode->GetAsText() && IsEditable(endNode)) {
|
||||
rv = SetInlinePropertyOnTextNode(MOZ_KnownLive(*endNode->GetAsText()),
|
||||
0, range->EndOffset(), aProperty,
|
||||
aAttribute, aValue);
|
||||
// Finally, if end node is a text node, apply new style to a part ot it.
|
||||
if (endOfRange.IsInTextNode() && IsEditable(endOfRange.GetContainer())) {
|
||||
nsresult rv = SetInlinePropertyOnTextNode(
|
||||
MOZ_KnownLive(*endOfRange.GetContainerAsText()), 0,
|
||||
endOfRange.Offset(), aProperty, aAttribute, aAttributeValue);
|
||||
if (NS_WARN_IF(Destroyed())) {
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cancel) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
rv = rules->DidDoAction(subActionInfo, rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
return NS_OK;
|
||||
// Restoring `Selection` may have destroyed us.
|
||||
return NS_WARN_IF(Destroyed()) ? NS_ERROR_EDITOR_DESTROYED : NS_OK;
|
||||
}
|
||||
|
||||
// Helper function for SetInlinePropertyOn*: is aNode a simple old <b>, <font>,
|
||||
|
@ -1259,10 +1264,9 @@ nsresult HTMLEditor::RemoveAllInlinePropertiesAsAction(
|
|||
*this, EditSubAction::eRemoveAllTextProperties, nsIEditor::eNext);
|
||||
|
||||
nsresult rv = RemoveInlinePropertyInternal(nullptr, nullptr);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return EditorBase::ToGenericNSResult(rv);
|
||||
}
|
||||
return NS_OK;
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"RemoveInlinePropertyInternal() failed");
|
||||
return EditorBase::ToGenericNSResult(rv);
|
||||
}
|
||||
|
||||
nsresult HTMLEditor::RemoveInlinePropertyAsAction(nsAtom& aProperty,
|
||||
|
@ -1288,10 +1292,9 @@ nsresult HTMLEditor::RemoveInlinePropertyAsAction(nsAtom& aProperty,
|
|||
break;
|
||||
}
|
||||
nsresult rv = RemoveInlinePropertyInternal(&aProperty, aAttribute);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return EditorBase::ToGenericNSResult(rv);
|
||||
}
|
||||
return NS_OK;
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"RemoveInlinePropertyInternal() failed");
|
||||
return EditorBase::ToGenericNSResult(rv);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -1319,10 +1322,9 @@ HTMLEditor::RemoveInlineProperty(const nsAString& aProperty,
|
|||
break;
|
||||
}
|
||||
nsresult rv = RemoveInlinePropertyInternal(property, attribute);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return EditorBase::ToGenericNSResult(rv);
|
||||
}
|
||||
return NS_OK;
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"RemoveInlinePropertyInternal() failed");
|
||||
return EditorBase::ToGenericNSResult(rv);
|
||||
}
|
||||
|
||||
nsresult HTMLEditor::RemoveInlinePropertyInternal(nsAtom* aProperty,
|
||||
|
@ -1353,21 +1355,24 @@ nsresult HTMLEditor::RemoveInlinePropertyInternal(nsAtom* aProperty,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// XXX Shouldn't we quit before calling `CommitComposition()`?
|
||||
if (IsPlaintextEditor()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
EditActionResult result = CanHandleHTMLEditSubAction();
|
||||
if (NS_WARN_IF(result.Failed()) || result.Canceled()) {
|
||||
return result.Rv();
|
||||
}
|
||||
|
||||
AutoPlaceholderBatch treatAsOneTransaction(*this);
|
||||
AutoEditSubActionNotifier startToHandleEditSubAction(
|
||||
*this, EditSubAction::eRemoveTextProperty, nsIEditor::eNext);
|
||||
AutoSelectionRestorer restoreSelectionLater(*this);
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(*this);
|
||||
|
||||
bool cancel, handled;
|
||||
EditSubActionInfo subActionInfo(EditSubAction::eRemoveTextProperty);
|
||||
// Protect the edit rules object from dying
|
||||
RefPtr<TextEditRules> rules(mRules);
|
||||
nsresult rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
if (!cancel && !handled) {
|
||||
{
|
||||
AutoSelectionRestorer restoreSelectionLater(*this);
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(*this);
|
||||
|
||||
// Loop through the ranges in the selection
|
||||
// Since ranges might be modified by SplitStyleAboveRange, we need hold
|
||||
// current ranges
|
||||
|
@ -1376,14 +1381,14 @@ nsresult HTMLEditor::RemoveInlinePropertyInternal(nsAtom* aProperty,
|
|||
if (aProperty == nsGkAtoms::name) {
|
||||
// Promote range if it starts or end in a named anchor and we want to
|
||||
// remove named anchors
|
||||
rv = PromoteRangeIfStartsOrEndsInNamedAnchor(*range);
|
||||
nsresult rv = PromoteRangeIfStartsOrEndsInNamedAnchor(*range);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
} else {
|
||||
// Adjust range to include any ancestors whose children are entirely
|
||||
// selected
|
||||
rv = PromoteInlineRange(*range);
|
||||
nsresult rv = PromoteInlineRange(*range);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -1391,90 +1396,109 @@ nsresult HTMLEditor::RemoveInlinePropertyInternal(nsAtom* aProperty,
|
|||
|
||||
// Remove this style from ancestors of our range endpoints, splitting
|
||||
// them as appropriate
|
||||
rv = SplitStyleAboveRange(range, aProperty, aAttribute);
|
||||
// FYI: `range` may be modified to a range starting from first right
|
||||
// node child at splitting at range start to first right node
|
||||
// child at splitting at range end.
|
||||
nsresult rv = SplitStyleAboveRange(range, aProperty, aAttribute);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Check for easy case: both range endpoints in same text node
|
||||
nsCOMPtr<nsINode> startNode = range->GetStartContainer();
|
||||
nsCOMPtr<nsINode> endNode = range->GetEndContainer();
|
||||
if (startNode && startNode == endNode && startNode->GetAsText()) {
|
||||
// We're done with this range!
|
||||
if (IsCSSEnabled() && CSSEditUtils::IsCSSEditableProperty(
|
||||
startNode, aProperty, aAttribute)) {
|
||||
// The HTML style defined by aProperty/aAttribute has a CSS
|
||||
// equivalence in this implementation for startNode
|
||||
if (CSSEditUtils::IsCSSEquivalentToHTMLInlineStyleSet(
|
||||
startNode, aProperty, aAttribute, EmptyString(),
|
||||
CSSEditUtils::eComputed)) {
|
||||
// startNode's computed style indicates the CSS equivalence to the
|
||||
// HTML style to remove is applied; but we found no element in the
|
||||
// ancestors of startNode carrying specified styles; assume it
|
||||
// comes from a rule and try to insert a span "inverting" the style
|
||||
if (CSSEditUtils::IsCSSInvertible(*aProperty, aAttribute)) {
|
||||
NS_NAMED_LITERAL_STRING(value, "-moz-editor-invert-value");
|
||||
SetInlinePropertyOnTextNode(
|
||||
MOZ_KnownLive(*startNode->GetAsText()), range->StartOffset(),
|
||||
range->EndOffset(), *aProperty, aAttribute, value);
|
||||
}
|
||||
}
|
||||
EditorDOMPoint startOfRange(range->StartRef());
|
||||
EditorDOMPoint endOfRange(range->EndRef());
|
||||
if (NS_WARN_IF(!startOfRange.IsSet()) ||
|
||||
NS_WARN_IF(!endOfRange.IsSet())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (startOfRange.GetContainer() == endOfRange.GetContainer() &&
|
||||
startOfRange.IsInTextNode()) {
|
||||
// TODO: If parent block has the removing style, we should create
|
||||
// `<span>` element to remove the style even in HTML mode
|
||||
// since Chrome does it. See bug 1566795.
|
||||
if (!IsCSSEnabled()) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// Not the easy case. Range not contained in single text node.
|
||||
if (!CSSEditUtils::IsCSSEditableProperty(startOfRange.GetContainer(),
|
||||
aProperty, aAttribute)) {
|
||||
continue;
|
||||
}
|
||||
// The HTML style defined by aProperty/aAttribute has a CSS
|
||||
// equivalence in this implementation for startOfRange.
|
||||
if (!CSSEditUtils::IsCSSEquivalentToHTMLInlineStyleSet(
|
||||
startOfRange.GetContainer(), aProperty, aAttribute,
|
||||
EmptyString(), CSSEditUtils::eComputed)) {
|
||||
continue;
|
||||
}
|
||||
// startOfRange's computed style indicates the CSS equivalence to the
|
||||
// HTML style to remove is applied; but we found no element in the
|
||||
// ancestors of startOfRange carrying specified styles; assume it
|
||||
// comes from a rule and try to insert a span "inverting" the style
|
||||
if (!CSSEditUtils::IsCSSInvertible(*aProperty, aAttribute)) {
|
||||
continue;
|
||||
}
|
||||
NS_NAMED_LITERAL_STRING(value, "-moz-editor-invert-value");
|
||||
SetInlinePropertyOnTextNode(
|
||||
MOZ_KnownLive(*startOfRange.GetContainerAsText()),
|
||||
startOfRange.Offset(), endOfRange.Offset(), *aProperty, aAttribute,
|
||||
value);
|
||||
if (NS_WARN_IF(Destroyed())) {
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
nsTArray<OwningNonNull<nsIContent>> arrayOfNodes;
|
||||
|
||||
// Iterate range and build up array
|
||||
ContentSubtreeIterator subtreeIter;
|
||||
DebugOnly<nsresult> rvIgnored = subtreeIter.Init(range);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
|
||||
"Failed to initialize subtree iterator");
|
||||
// Collect editable nodes which are entirely contained in the range.
|
||||
AutoTArray<OwningNonNull<nsIContent>, 64> arrayOfContents;
|
||||
ContentSubtreeIterator subtreeIter;
|
||||
if (NS_SUCCEEDED(subtreeIter.Init(range))) {
|
||||
for (; !subtreeIter.IsDone(); subtreeIter.Next()) {
|
||||
nsCOMPtr<nsINode> node = subtreeIter.GetCurrentNode();
|
||||
if (NS_WARN_IF(!node)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (IsEditable(node) && node->IsContent()) {
|
||||
arrayOfNodes.AppendElement(*node->AsContent());
|
||||
if (node->IsContent() && IsEditable(node)) {
|
||||
arrayOfContents.AppendElement(*node->AsContent());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Loop through the list, remove the property on each node
|
||||
for (auto& node : arrayOfNodes) {
|
||||
rv = RemoveStyleInside(node, aProperty, aAttribute);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
if (IsCSSEnabled() &&
|
||||
CSSEditUtils::IsCSSEditableProperty(node, aProperty,
|
||||
aAttribute) &&
|
||||
CSSEditUtils::IsCSSEquivalentToHTMLInlineStyleSet(
|
||||
node, aProperty, aAttribute, EmptyString(),
|
||||
CSSEditUtils::eComputed) &&
|
||||
// startNode's computed style indicates the CSS equivalence to
|
||||
// the HTML style to remove is applied; but we found no element
|
||||
// in the ancestors of startNode carrying specified styles;
|
||||
// assume it comes from a rule and let's try to insert a span
|
||||
// "inverting" the style
|
||||
CSSEditUtils::IsCSSInvertible(*aProperty, aAttribute)) {
|
||||
NS_NAMED_LITERAL_STRING(value, "-moz-editor-invert-value");
|
||||
SetInlinePropertyOnNode(node, *aProperty, aAttribute, value);
|
||||
}
|
||||
for (auto& content : arrayOfContents) {
|
||||
nsresult rv = RemoveStyleInside(content, aProperty, aAttribute);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
// TODO: If parent block has the removing style, we should create
|
||||
// `<span>` element to remove the style even in HTML mode
|
||||
// since Chrome does it. See bug 1566795.
|
||||
if (!IsCSSEnabled()) {
|
||||
continue;
|
||||
}
|
||||
if (!CSSEditUtils::IsCSSEditableProperty(content, aProperty,
|
||||
aAttribute)) {
|
||||
continue;
|
||||
}
|
||||
if (!CSSEditUtils::IsCSSEquivalentToHTMLInlineStyleSet(
|
||||
content, aProperty, aAttribute, EmptyString(),
|
||||
CSSEditUtils::eComputed)) {
|
||||
continue;
|
||||
}
|
||||
// startOfRange's computed style indicates the CSS equivalence to
|
||||
// the HTML style to remove is applied; but we found no element
|
||||
// in the ancestors of startOfRange carrying specified styles;
|
||||
// assume it comes from a rule and let's try to insert a span
|
||||
// "inverting" the style
|
||||
if (!CSSEditUtils::IsCSSInvertible(*aProperty, aAttribute)) {
|
||||
continue;
|
||||
}
|
||||
NS_NAMED_LITERAL_STRING(value, "-moz-editor-invert-value");
|
||||
SetInlinePropertyOnNode(content, *aProperty, aAttribute, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cancel) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
rv = rules->DidDoAction(subActionInfo, rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
return NS_OK;
|
||||
// Restoring `Selection` may cause destroying us.
|
||||
return NS_WARN_IF(Destroyed()) ? NS_ERROR_EDITOR_DESTROYED : NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -207,10 +207,6 @@ nsresult TextEditRules::WillDoAction(EditSubActionInfo& aInfo, bool* aCancel,
|
|||
return WillSetText(aCancel, aHandled, aInfo.inString, aInfo.maxLength);
|
||||
case EditSubAction::eDeleteSelectedContent:
|
||||
return WillDeleteSelection(aInfo.collapsedAction, aCancel, aHandled);
|
||||
case EditSubAction::eSetTextProperty:
|
||||
return WillSetTextProperty(aCancel, aHandled);
|
||||
case EditSubAction::eRemoveTextProperty:
|
||||
return WillRemoveTextProperty(aCancel, aHandled);
|
||||
case EditSubAction::eComputeTextToOutput:
|
||||
return WillOutputText(aInfo.outputFormat, aInfo.outString, aInfo.flags,
|
||||
aCancel, aHandled);
|
||||
|
@ -858,32 +854,6 @@ nsresult TextEditRules::WillSetText(bool* aCancel, bool* aHandled,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult TextEditRules::WillSetTextProperty(bool* aCancel, bool* aHandled) {
|
||||
if (NS_WARN_IF(!aCancel) || NS_WARN_IF(!aHandled)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
// XXX: should probably return a success value other than NS_OK that means
|
||||
// "not allowed"
|
||||
if (IsPlaintextEditor()) {
|
||||
*aCancel = true;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult TextEditRules::WillRemoveTextProperty(bool* aCancel, bool* aHandled) {
|
||||
if (NS_WARN_IF(!aCancel) || NS_WARN_IF(!aHandled)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
// XXX: should probably return a success value other than NS_OK that means
|
||||
// "not allowed"
|
||||
if (IsPlaintextEditor()) {
|
||||
*aCancel = true;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult TextEditRules::WillDeleteSelection(
|
||||
nsIEditor::EDirection aCollapsedAction, bool* aCancel, bool* aHandled) {
|
||||
MOZ_ASSERT(IsEditorDataAvailable());
|
||||
|
|
|
@ -151,10 +151,6 @@ class TextEditRules {
|
|||
MOZ_MUST_USE nsresult DeleteSelectionWithTransaction(
|
||||
nsIEditor::EDirection aCollapsedAction, bool* aCancel, bool* aHandled);
|
||||
|
||||
nsresult WillSetTextProperty(bool* aCancel, bool* aHandled);
|
||||
|
||||
nsresult WillRemoveTextProperty(bool* aCancel, bool* aHandled);
|
||||
|
||||
/**
|
||||
* Called prior to nsIEditor::OutputToString.
|
||||
*
|
||||
|
|
Загрузка…
Ссылка в новой задаче