/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include"mozilla/EditorBase.h"// for EditorBase #include"mozilla/EditorDOMPoint.h"// for EditorDOMPoint, EditorDOMRange, etc #include"mozilla/EditorForwards.h" #include"mozilla/IntegerRange.h"// for IntegerRange #include"mozilla/Maybe.h"// for Maybe #include"mozilla/Result.h"// for Result<> #include"mozilla/dom/DataTransfer.h"// for dom::DataTransfer #include"mozilla/dom/Element.h"// for dom::Element #include"mozilla/dom/HTMLBRElement.h"// for dom::HTMLBRElement #include"mozilla/dom/Selection.h"// for dom::Selection #include"mozilla/dom/Text.h"// for dom::Text
#include"nsAtom.h"// for nsStaticAtom #include"nsCOMPtr.h"// for nsCOMPtr #include"nsContentUtils.h"// for nsContentUtils #include"nsDebug.h"// for NS_WARNING, etc #include"nsError.h"// for NS_SUCCESS_* and NS_ERROR_* #include"nsRange.h"// for nsRange #include"nsString.h"// for nsAString, nsString, etc
class nsITransferable;
namespace mozilla {
enumclass StyleWhiteSpace : uint8_t;
enumclass SuggestCaret { // If specified, the method returns NS_OK when there is no recommended caret // position.
OnlyIfHasSuggestion, // If specified and if EditorBase::AllowsTransactionsToChangeSelection // returns false, the method does nothing and returns NS_OK.
OnlyIfTransactionsAllowedToDoIt, // If specified, the method returns // NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR even if // EditorBase::CollapseSelectionTo returns an error except when // NS_ERROR_EDITOR_DESTROYED.
AndIgnoreTrivialError,
};
/****************************************************************************** * CaretPoint is a wrapper of EditorDOMPoint and provides a helper method to * collapse Selection there, or move it to a local variable. This is typically * used as the ok type of Result or a base class of DoSomethingResult classes.
******************************************************************************/ class MOZ_STACK_CLASS CaretPoint { public: explicit CaretPoint(const EditorDOMPoint& aPointToPutCaret)
: mCaretPoint(aPointToPutCaret) {} explicit CaretPoint(EditorDOMPoint&& aPointToPutCaret)
: mCaretPoint(std::move(aPointToPutCaret)) {}
/** * Suggest caret position to aEditorBase.
*/
[[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult SuggestCaretPointTo(
EditorBase& aEditorBase, const SuggestCaretOptions& aOptions) const;
/** * IgnoreCaretPointSuggestion() should be called if the method does not want * to use caret position recommended by this instance.
*/ void IgnoreCaretPointSuggestion() const { mHandledCaretPoint = true; }
/** * When propagating the result, it may not want to the caller modify * selection. In such case, this can clear the caret point. Use * IgnoreCaretPointSuggestion() in the caller side instead.
*/ void ForgetCaretPointSuggestion() { mCaretPoint.Clear(); }
/*************************************************************************** * CreateNodeResultBase is a simple class for CreateSomething() methods * which want to return new node.
*/ template <typename NodeType> class MOZ_STACK_CLASS CreateNodeResultBase final : public CaretPoint { using SelfType = CreateNodeResultBase<NodeType>;
/** * This is a result of inserting text. If the text inserted as a part of * composition, this does not return CaretPoint. Otherwise, must return * CaretPoint which is typically same as end of inserted text.
*/ class MOZ_STACK_CLASS InsertTextResult final : public CaretPoint { public:
InsertTextResult() : CaretPoint(EditorDOMPoint()) {} template <typename EditorDOMPointType> explicit InsertTextResult(const EditorDOMPointType& aEndOfInsertedText)
: CaretPoint(EditorDOMPoint()),
mEndOfInsertedText(aEndOfInsertedText.template To<EditorDOMPoint>()) {} explicit InsertTextResult(EditorDOMPoint&& aEndOfInsertedText)
: CaretPoint(EditorDOMPoint()),
mEndOfInsertedText(std::move(aEndOfInsertedText)) {} template <typename PT, typename CT>
InsertTextResult(EditorDOMPoint&& aEndOfInsertedText, const EditorDOMPointBase<PT, CT>& aCaretPoint)
: CaretPoint(aCaretPoint.template To<EditorDOMPoint>()),
mEndOfInsertedText(std::move(aEndOfInsertedText)) {}
InsertTextResult(EditorDOMPoint&& aEndOfInsertedText,
CaretPoint&& aCaretPoint)
: CaretPoint(std::move(aCaretPoint)),
mEndOfInsertedText(std::move(aEndOfInsertedText)) {
UnmarkAsHandledCaretPoint();
}
InsertTextResult(InsertTextResult&& aOther, EditorDOMPoint&& aCaretPoint)
: CaretPoint(std::move(aCaretPoint)),
mEndOfInsertedText(std::move(aOther.mEndOfInsertedText)) {}
/*************************************************************************** * stack based helper class for calling EditorBase::EndTransaction() after * EditorBase::BeginTransaction(). This shouldn't be used in editor classes * or helper classes while an edit action is being handled. Use * AutoTransactionBatch in such cases since it uses non-virtual internal * methods.
***************************************************************************/ class MOZ_RAII AutoTransactionBatchExternal final { public:
MOZ_CAN_RUN_SCRIPT explicit AutoTransactionBatchExternal(
EditorBase& aEditorBase)
: mEditorBase(aEditorBase) {
MOZ_KnownLive(mEditorBase).BeginTransaction();
}
/****************************************************************************** * AutoSelectionRangeArray stores all ranges in `aSelection`. * Note that modifying the ranges means modifing the selection ranges.
*****************************************************************************/ class MOZ_STACK_CLASS AutoSelectionRangeArray final { public: explicit AutoSelectionRangeArray(dom::Selection& aSelection) { for (const uint32_t i : IntegerRange(aSelection.RangeCount())) {
MOZ_ASSERT(aSelection.GetRangeAt(i));
mRanges.AppendElement(*aSelection.GetRangeAt(i));
}
}
private: void FlushAndStopTracking() { if (!mDataTransferForPaste ||
!mEditorBase.GetDocument()->IsClipboardCopyTriggered()) { return;
} // The paste event copied new data to the clipboard, so we need to use // that data to paste into the DOM element below. if (*mDataTransferForPaste) {
(*mDataTransferForPaste)->ClearForPaste();
} // Just null this out so this data won't be used and we will get it directly // from the clipboard in the future.
*mDataTransferForPaste = nullptr;
mDataTransferForPaste = nullptr;
}
class EditorUtils final { public: using EditorType = EditorBase::EditorType; using Selection = dom::Selection;
/** * IsDescendantOf() checks if aNode is a child or a descendant of aParent. * aOutPoint is set to the child of aParent. * * @return true if aNode is a child or a descendant of aParent.
*/ staticbool IsDescendantOf(const nsINode& aNode, const nsINode& aParent,
EditorRawDOMPoint* aOutPoint = nullptr); staticbool IsDescendantOf(const nsINode& aNode, const nsINode& aParent,
EditorDOMPoint* aOutPoint);
/** * Returns true if aContent is a <br> element and it's marked as padding for * empty editor.
*/ staticbool IsPaddingBRElementForEmptyEditor(const nsIContent& aContent) { const dom::HTMLBRElement* brElement =
dom::HTMLBRElement::FromNode(&aContent); return brElement && brElement->IsPaddingForEmptyEditor();
}
/** * Returns true if aContent is a <br> element and it's marked as padding for * empty last line.
*/ staticbool IsPaddingBRElementForEmptyLastLine(const nsIContent& aContent) { const dom::HTMLBRElement* brElement =
dom::HTMLBRElement::FromNode(&aContent); return brElement && brElement->IsPaddingForEmptyLastLine();
}
/** * IsEditableContent() returns true if aContent's data or children is ediable * for the given editor type. Be aware, returning true does NOT mean the * node can be removed from its parent node, and returning false does NOT * mean the node cannot be removed from the parent node. * XXX May be the anonymous nodes in TextEditor not editable? If it's not * so, we can get rid of aEditorType.
*/ staticbool IsEditableContent(const nsIContent& aContent,
EditorType aEditorType) { if (aEditorType == EditorType::HTML &&
(!aContent.IsEditable() || !aContent.IsInComposedDoc())) { // FIXME(emilio): Why only for HTML editors? All content from the root // content in text editors is also editable, so afaict we can remove the // special-case. returnfalse;
} return IsElementOrText(aContent);
}
/** * Returns true if aContent is a usual element node (not padding <br> element * for empty editor) or a text node. In other words, returns true if * aContent is a usual element node or visible data node.
*/ staticbool IsElementOrText(const nsIContent& aContent) { if (aContent.IsText()) { returntrue;
} return aContent.IsElement() && !IsPaddingBRElementForEmptyEditor(aContent);
}
/** * Get the two longhands that make up computed white-space style of aContent.
*/ static Maybe<std::pair<StyleWhiteSpaceCollapse, StyleTextWrapMode>>
GetComputedWhiteSpaceStyles(const nsIContent& aContent);
/** * IsWhiteSpacePreformatted() checks the style info for the node for the * preformatted text style. This does NOT flush layout.
*/ staticbool IsWhiteSpacePreformatted(const nsIContent& aContent);
/** * IsNewLinePreformatted() checks whether the linefeed characters are * preformatted or collapsible white-spaces. This does NOT flush layout.
*/ staticbool IsNewLinePreformatted(const nsIContent& aContent);
/** * IsOnlyNewLinePreformatted() checks whether the linefeed characters are * preformated but white-spaces are collapsed, or otherwise. I.e., this * returns true only when `white-space-collapse:pre-line`.
*/ staticbool IsOnlyNewLinePreformatted(const nsIContent& aContent);
static nsStaticAtom* GetAttributeAtom(const nsAString& aAttribute) { if (aAttribute.IsEmpty()) { return nullptr; // Don't use nsGkAtoms::_empty for attribute.
} return NS_GetStaticAtom(aAttribute);
}
/** * Helper method for deletion. When this returns true, Selection will be * computed with nsFrameSelection that also requires flushed layout * information.
*/ template <typename SelectionOrAutoClonedRangeArray> staticbool IsFrameSelectionRequiredToExtendSelection(
nsIEditor::EDirection aDirectionAndAmount,
SelectionOrAutoClonedRangeArray& aSelectionOrAutoClonedRangeArray) { switch (aDirectionAndAmount) { case nsIEditor::eNextWord: case nsIEditor::ePreviousWord: case nsIEditor::eToBeginningOfLine: case nsIEditor::eToEndOfLine: returntrue; case nsIEditor::ePrevious: case nsIEditor::eNext: return aSelectionOrAutoClonedRangeArray.IsCollapsed(); default: returnfalse;
}
}
/** * Create an nsITransferable instance which has kTextMime and * kMozTextInternal flavors.
*/ static Result<nsCOMPtr<nsITransferable>, nsresult>
CreateTransferableForPlainText(const dom::Document& aDocument);
};
} // namespace mozilla
#endif// #ifndef mozilla_EditorUtils_h
¤ Dauer der Verarbeitung: 0.34 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.