summaryrefslogtreecommitdiffstats
path: root/editor/libeditor/TextEditRules.h
diff options
context:
space:
mode:
Diffstat (limited to 'editor/libeditor/TextEditRules.h')
-rw-r--r--editor/libeditor/TextEditRules.h357
1 files changed, 357 insertions, 0 deletions
diff --git a/editor/libeditor/TextEditRules.h b/editor/libeditor/TextEditRules.h
new file mode 100644
index 000000000..6d4915f15
--- /dev/null
+++ b/editor/libeditor/TextEditRules.h
@@ -0,0 +1,357 @@
+/* -*- 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/. */
+
+#ifndef mozilla_TextEditRules_h
+#define mozilla_TextEditRules_h
+
+#include "mozilla/EditorBase.h"
+#include "nsCOMPtr.h"
+#include "nsCycleCollectionParticipant.h"
+#include "nsIEditRules.h"
+#include "nsIEditor.h"
+#include "nsISupportsImpl.h"
+#include "nsITimer.h"
+#include "nsString.h"
+#include "nscore.h"
+
+class nsIDOMElement;
+class nsIDOMNode;
+
+namespace mozilla {
+
+class AutoLockRulesSniffing;
+class TextEditor;
+namespace dom {
+class Selection;
+} // namespace dom
+
+/**
+ * Object that encapsulates HTML text-specific editing rules.
+ *
+ * To be a good citizen, edit rules must live by these restrictions:
+ * 1. All data manipulation is through the editor.
+ * Content nodes in the document tree must <B>not</B> be manipulated
+ * directly. Content nodes in document fragments that are not part of the
+ * document itself may be manipulated at will. Operations on document
+ * fragments must <B>not</B> go through the editor.
+ * 2. Selection must not be explicitly set by the rule method.
+ * Any manipulation of Selection must be done by the editor.
+ */
+class TextEditRules : public nsIEditRules
+ , public nsITimerCallback
+{
+public:
+ typedef dom::Element Element;
+ typedef dom::Selection Selection;
+ typedef dom::Text Text;
+ template<typename T> using OwningNonNull = OwningNonNull<T>;
+
+ NS_DECL_NSITIMERCALLBACK
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(TextEditRules, nsIEditRules)
+
+ TextEditRules();
+
+ // nsIEditRules methods
+ NS_IMETHOD Init(TextEditor* aTextEditor) override;
+ NS_IMETHOD SetInitialValue(const nsAString& aValue) override;
+ NS_IMETHOD DetachEditor() override;
+ NS_IMETHOD BeforeEdit(EditAction action,
+ nsIEditor::EDirection aDirection) override;
+ NS_IMETHOD AfterEdit(EditAction action,
+ nsIEditor::EDirection aDirection) override;
+ NS_IMETHOD WillDoAction(Selection* aSelection, RulesInfo* aInfo,
+ bool* aCancel, bool* aHandled) override;
+ NS_IMETHOD DidDoAction(Selection* aSelection, RulesInfo* aInfo,
+ nsresult aResult) override;
+ NS_IMETHOD DocumentIsEmpty(bool* aDocumentIsEmpty) override;
+ NS_IMETHOD DocumentModified() override;
+
+protected:
+ virtual ~TextEditRules();
+
+public:
+ void ResetIMETextPWBuf();
+
+ /**
+ * Handles the newline characters either according to aNewLineHandling
+ * or to the default system prefs if aNewLineHandling is negative.
+ *
+ * @param aString the string to be modified in place.
+ * @param aNewLineHandling determine the desired type of newline handling:
+ * * negative values:
+ * handle newlines according to platform defaults.
+ * * nsIPlaintextEditor::eNewlinesReplaceWithSpaces:
+ * replace newlines with spaces.
+ * * nsIPlaintextEditor::eNewlinesStrip:
+ * remove newlines from the string.
+ * * nsIPlaintextEditor::eNewlinesReplaceWithCommas:
+ * replace newlines with commas.
+ * * nsIPlaintextEditor::eNewlinesStripSurroundingWhitespace:
+ * collapse newlines and surrounding whitespace characters and
+ * remove them from the string.
+ * * nsIPlaintextEditor::eNewlinesPasteIntact:
+ * only remove the leading and trailing newlines.
+ * * nsIPlaintextEditor::eNewlinesPasteToFirst or any other value:
+ * remove the first newline and all characters following it.
+ */
+ static void HandleNewLines(nsString& aString, int32_t aNewLineHandling);
+
+ /**
+ * Prepare a string buffer for being displayed as the contents of a password
+ * field. This function uses the platform-specific character for representing
+ * characters entered into password fields.
+ *
+ * @param aOutString the output string. When this function returns,
+ * aOutString will contain aLength password characters.
+ * @param aLength the number of password characters that aOutString should
+ * contain.
+ */
+ static void FillBufWithPWChars(nsAString* aOutString, int32_t aLength);
+
+protected:
+
+ void InitFields();
+
+ // TextEditRules implementation methods
+ nsresult WillInsertText(EditAction aAction,
+ Selection* aSelection,
+ bool* aCancel,
+ bool* aHandled,
+ const nsAString* inString,
+ nsAString* outString,
+ int32_t aMaxLength);
+ nsresult DidInsertText(Selection* aSelection, nsresult aResult);
+ nsresult GetTopEnclosingPre(nsIDOMNode* aNode, nsIDOMNode** aOutPreNode);
+
+ nsresult WillInsertBreak(Selection* aSelection, bool* aCancel,
+ bool* aHandled, int32_t aMaxLength);
+ nsresult DidInsertBreak(Selection* aSelection, nsresult aResult);
+
+ void WillInsert(Selection& aSelection, bool* aCancel);
+ nsresult DidInsert(Selection* aSelection, nsresult aResult);
+
+ nsresult WillDeleteSelection(Selection* aSelection,
+ nsIEditor::EDirection aCollapsedAction,
+ bool* aCancel,
+ bool* aHandled);
+ nsresult DidDeleteSelection(Selection* aSelection,
+ nsIEditor::EDirection aCollapsedAction,
+ nsresult aResult);
+
+ nsresult WillSetTextProperty(Selection* aSelection, bool* aCancel,
+ bool* aHandled);
+ nsresult DidSetTextProperty(Selection* aSelection, nsresult aResult);
+
+ nsresult WillRemoveTextProperty(Selection* aSelection, bool* aCancel,
+ bool* aHandled);
+ nsresult DidRemoveTextProperty(Selection* aSelection, nsresult aResult);
+
+ nsresult WillUndo(Selection* aSelection, bool* aCancel, bool* aHandled);
+ nsresult DidUndo(Selection* aSelection, nsresult aResult);
+
+ nsresult WillRedo(Selection* aSelection, bool* aCancel, bool* aHandled);
+ nsresult DidRedo(Selection* aSelection, nsresult aResult);
+
+ /**
+ * Called prior to nsIEditor::OutputToString.
+ * @param aSelection
+ * @param aInFormat The format requested for the output, a MIME type.
+ * @param aOutText The string to use for output, if aCancel is set to true.
+ * @param aOutCancel If set to true, the caller should cancel the operation
+ * and use aOutText as the result.
+ */
+ nsresult WillOutputText(Selection* aSelection,
+ const nsAString* aInFormat,
+ nsAString* aOutText,
+ bool* aOutCancel,
+ bool* aHandled);
+
+ nsresult DidOutputText(Selection* aSelection, nsresult aResult);
+
+ /**
+ * Check for and replace a redundant trailing break.
+ */
+ nsresult RemoveRedundantTrailingBR();
+
+ /**
+ * Creates a trailing break in the text doc if there is not one already.
+ */
+ nsresult CreateTrailingBRIfNeeded();
+
+ /**
+ * Creates a bogus text node if the document has no editable content.
+ */
+ nsresult CreateBogusNodeIfNeeded(Selection* aSelection);
+
+ /**
+ * Returns a truncated insertion string if insertion would place us over
+ * aMaxLength
+ */
+ nsresult TruncateInsertionIfNeeded(Selection* aSelection,
+ const nsAString* aInString,
+ nsAString* aOutString,
+ int32_t aMaxLength,
+ bool* aTruncated);
+
+ /**
+ * Remove IME composition text from password buffer.
+ */
+ void RemoveIMETextFromPWBuf(int32_t& aStart, nsAString* aIMEString);
+
+ nsresult CreateMozBR(nsIDOMNode* inParent, int32_t inOffset,
+ nsIDOMNode** outBRNode = nullptr);
+
+ void UndefineCaretBidiLevel(Selection* aSelection);
+
+ nsresult CheckBidiLevelForDeletion(Selection* aSelection,
+ nsIDOMNode* aSelNode,
+ int32_t aSelOffset,
+ nsIEditor::EDirection aAction,
+ bool* aCancel);
+
+ nsresult HideLastPWInput();
+
+ nsresult CollapseSelectionToTrailingBRIfNeeded(Selection* aSelection);
+
+ bool IsPasswordEditor() const;
+ bool IsSingleLineEditor() const;
+ bool IsPlaintextEditor() const;
+ bool IsReadonly() const;
+ bool IsDisabled() const;
+ bool IsMailEditor() const;
+ bool DontEchoPassword() const;
+
+ // Note that we do not refcount the editor.
+ TextEditor* mTextEditor;
+ // A buffer we use to store the real value of password editors.
+ nsString mPasswordText;
+ // A buffer we use to track the IME composition string.
+ nsString mPasswordIMEText;
+ uint32_t mPasswordIMEIndex;
+ // Magic node acts as placeholder in empty doc.
+ nsCOMPtr<nsIDOMNode> mBogusNode;
+ // Cached selected node.
+ nsCOMPtr<nsIDOMNode> mCachedSelectionNode;
+ // Cached selected offset.
+ int32_t mCachedSelectionOffset;
+ uint32_t mActionNesting;
+ bool mLockRulesSniffing;
+ bool mDidExplicitlySetInterline;
+ // In bidirectional text, delete characters not visually adjacent to the
+ // caret without moving the caret first.
+ bool mDeleteBidiImmediately;
+ // The top level editor action.
+ EditAction mTheAction;
+ nsCOMPtr<nsITimer> mTimer;
+ uint32_t mLastStart;
+ uint32_t mLastLength;
+
+ // friends
+ friend class AutoLockRulesSniffing;
+};
+
+class TextRulesInfo final : public RulesInfo
+{
+public:
+ explicit TextRulesInfo(EditAction aAction)
+ : RulesInfo(aAction)
+ , inString(nullptr)
+ , outString(nullptr)
+ , outputFormat(nullptr)
+ , maxLength(-1)
+ , collapsedAction(nsIEditor::eNext)
+ , stripWrappers(nsIEditor::eStrip)
+ , bOrdered(false)
+ , entireList(false)
+ , bulletType(nullptr)
+ , alignType(nullptr)
+ , blockType(nullptr)
+ , insertElement(nullptr)
+ {}
+
+ // kInsertText
+ const nsAString* inString;
+ nsAString* outString;
+ const nsAString* outputFormat;
+ int32_t maxLength;
+
+ // kDeleteSelection
+ nsIEditor::EDirection collapsedAction;
+ nsIEditor::EStripWrappers stripWrappers;
+
+ // kMakeList
+ bool bOrdered;
+ bool entireList;
+ const nsAString* bulletType;
+
+ // kAlign
+ const nsAString* alignType;
+
+ // kMakeBasicBlock
+ const nsAString* blockType;
+
+ // kInsertElement
+ const nsIDOMElement* insertElement;
+};
+
+/**
+ * Stack based helper class for StartOperation()/EndOperation() sandwich.
+ * This class sets a bool letting us know to ignore any rules sniffing
+ * that tries to occur reentrantly.
+ */
+class MOZ_STACK_CLASS AutoLockRulesSniffing final
+{
+public:
+ explicit AutoLockRulesSniffing(TextEditRules* aRules)
+ : mRules(aRules)
+ {
+ if (mRules) {
+ mRules->mLockRulesSniffing = true;
+ }
+ }
+
+ ~AutoLockRulesSniffing()
+ {
+ if (mRules) {
+ mRules->mLockRulesSniffing = false;
+ }
+ }
+
+protected:
+ TextEditRules* mRules;
+};
+
+/**
+ * Stack based helper class for turning on/off the edit listener.
+ */
+class MOZ_STACK_CLASS AutoLockListener final
+{
+public:
+ explicit AutoLockListener(bool* aEnabled)
+ : mEnabled(aEnabled)
+ , mOldState(false)
+ {
+ if (mEnabled) {
+ mOldState = *mEnabled;
+ *mEnabled = false;
+ }
+ }
+
+ ~AutoLockListener()
+ {
+ if (mEnabled) {
+ *mEnabled = mOldState;
+ }
+ }
+
+protected:
+ bool* mEnabled;
+ bool mOldState;
+};
+
+} // namespace mozilla
+
+#endif // #ifndef mozilla_TextEditRules_h