diff -r 000000000000 -r 6474c204b198 editor/libeditor/text/nsTextEditRules.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/editor/libeditor/text/nsTextEditRules.h Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,336 @@ +/* -*- 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 nsTextEditRules_h__ +#define nsTextEditRules_h__ + +#include "nsCOMPtr.h" +#include "nsCycleCollectionParticipant.h" +#include "nsEditRules.h" +#include "nsEditor.h" +#include "nsIEditor.h" +#include "nsISupportsImpl.h" +#include "nsITimer.h" +#include "nsPlaintextEditor.h" +#include "nsString.h" +#include "nscore.h" + +class nsIDOMElement; +class nsIDOMNode; +class nsISelection; +namespace mozilla { +namespace dom { +class Selection; +} // namespace dom +} // namespace mozilla + +/** 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 not 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 not + * 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 nsTextEditRules : public nsIEditRules, public nsITimerCallback +{ +public: + NS_DECL_NSITIMERCALLBACK + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsTextEditRules, nsIEditRules) + + nsTextEditRules(); + virtual ~nsTextEditRules(); + + // nsIEditRules methods + NS_IMETHOD Init(nsPlaintextEditor *aEditor); + NS_IMETHOD SetInitialValue(const nsAString& aValue); + NS_IMETHOD DetachEditor(); + NS_IMETHOD BeforeEdit(EditAction action, + nsIEditor::EDirection aDirection); + NS_IMETHOD AfterEdit(EditAction action, + nsIEditor::EDirection aDirection); + NS_IMETHOD WillDoAction(mozilla::dom::Selection* aSelection, + nsRulesInfo* aInfo, bool* aCancel, bool* aHandled); + NS_IMETHOD DidDoAction(nsISelection *aSelection, nsRulesInfo *aInfo, nsresult aResult); + NS_IMETHOD DocumentIsEmpty(bool *aDocumentIsEmpty); + NS_IMETHOD DocumentModified(); + +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(); + + // nsTextEditRules implementation methods + nsresult WillInsertText( EditAction aAction, + mozilla::dom::Selection* aSelection, + bool *aCancel, + bool *aHandled, + const nsAString *inString, + nsAString *outString, + int32_t aMaxLength); + nsresult DidInsertText(nsISelection *aSelection, nsresult aResult); + nsresult GetTopEnclosingPre(nsIDOMNode *aNode, nsIDOMNode** aOutPreNode); + + nsresult WillInsertBreak(mozilla::dom::Selection* aSelection, bool* aCancel, + bool *aHandled, int32_t aMaxLength); + nsresult DidInsertBreak(nsISelection *aSelection, nsresult aResult); + + nsresult WillInsert(nsISelection *aSelection, bool *aCancel); + nsresult DidInsert(nsISelection *aSelection, nsresult aResult); + + nsresult WillDeleteSelection(mozilla::dom::Selection* aSelection, + nsIEditor::EDirection aCollapsedAction, + bool *aCancel, + bool *aHandled); + nsresult DidDeleteSelection(nsISelection *aSelection, + nsIEditor::EDirection aCollapsedAction, + nsresult aResult); + + nsresult WillSetTextProperty(nsISelection *aSelection, bool *aCancel, bool *aHandled); + nsresult DidSetTextProperty(nsISelection *aSelection, nsresult aResult); + + nsresult WillRemoveTextProperty(nsISelection *aSelection, bool *aCancel, bool *aHandled); + nsresult DidRemoveTextProperty(nsISelection *aSelection, nsresult aResult); + + nsresult WillUndo(nsISelection *aSelection, bool *aCancel, bool *aHandled); + nsresult DidUndo(nsISelection *aSelection, nsresult aResult); + + nsresult WillRedo(nsISelection *aSelection, bool *aCancel, bool *aHandled); + nsresult DidRedo(nsISelection *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(nsISelection *aSelection, + const nsAString *aInFormat, + nsAString *aOutText, + bool *aOutCancel, + bool *aHandled); + + nsresult DidOutputText(nsISelection *aSelection, nsresult aResult); + + + // helper functions + + /** 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(nsISelection *aSelection); + + /** returns a truncated insertion string if insertion would place us + over aMaxLength */ + nsresult TruncateInsertionIfNeeded(mozilla::dom::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); + + nsresult CheckBidiLevelForDeletion(nsISelection *aSelection, + nsIDOMNode *aSelNode, + int32_t aSelOffset, + nsIEditor::EDirection aAction, + bool *aCancel); + + nsresult HideLastPWInput(); + + nsresult CollapseSelectionToTrailingBRIfNeeded(nsISelection *aSelection); + + bool IsPasswordEditor() const + { + return mEditor ? mEditor->IsPasswordEditor() : false; + } + bool IsSingleLineEditor() const + { + return mEditor ? mEditor->IsSingleLineEditor() : false; + } + bool IsPlaintextEditor() const + { + return mEditor ? mEditor->IsPlaintextEditor() : false; + } + bool IsReadonly() const + { + return mEditor ? mEditor->IsReadonly() : false; + } + bool IsDisabled() const + { + return mEditor ? mEditor->IsDisabled() : false; + } + bool IsMailEditor() const + { + return mEditor ? mEditor->IsMailEditor() : false; + } + bool DontEchoPassword() const + { + return mEditor ? mEditor->DontEchoPassword() : false; + } + + // data members + nsPlaintextEditor *mEditor; // note that we do not refcount the editor + nsString mPasswordText; // a buffer we use to store the real value of password editors + nsString mPasswordIMEText; // a buffer we use to track the IME composition string + uint32_t mPasswordIMEIndex; + nsCOMPtr mBogusNode; // magic node acts as placeholder in empty doc + nsCOMPtr mCachedSelectionNode; // cached selected node + int32_t mCachedSelectionOffset; // cached selected offset + uint32_t mActionNesting; + bool mLockRulesSniffing; + bool mDidExplicitlySetInterline; + bool mDeleteBidiImmediately; // in bidirectional text, delete + // characters not visually + // adjacent to the caret without + // moving the caret first. + EditAction mTheAction; // the top level editor action + nsCOMPtr mTimer; + uint32_t mLastStart, mLastLength; + + // friends + friend class nsAutoLockRulesSniffing; + +}; + + + +class nsTextRulesInfo : public nsRulesInfo +{ + public: + + nsTextRulesInfo(EditAction aAction) : + nsRulesInfo(aAction), + inString(0), + outString(0), + outputFormat(0), + maxLength(-1), + collapsedAction(nsIEditor::eNext), + stripWrappers(nsIEditor::eStrip), + bOrdered(false), + entireList(false), + bulletType(0), + alignType(0), + blockType(0), + insertElement(0) + {} + + virtual ~nsTextRulesInfo() {} + + // 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 nsAutoLockRulesSniffing +{ + public: + + nsAutoLockRulesSniffing(nsTextEditRules *rules) : mRules(rules) + {if (mRules) mRules->mLockRulesSniffing = true;} + ~nsAutoLockRulesSniffing() + {if (mRules) mRules->mLockRulesSniffing = false;} + + protected: + nsTextEditRules *mRules; +}; + + + +/*************************************************************************** + * stack based helper class for turning on/off the edit listener. + */ +class nsAutoLockListener +{ + public: + + nsAutoLockListener(bool *enabled) : mEnabled(enabled) + {if (mEnabled) { mOldState=*mEnabled; *mEnabled = false;}} + ~nsAutoLockListener() + {if (mEnabled) *mEnabled = mOldState;} + + protected: + bool *mEnabled; + bool mOldState; +}; + +#endif //nsTextEditRules_h__