12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127 |
- /* -*- 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_EditorBase_h
- #define mozilla_EditorBase_h
- #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc.
- #include "mozFlushType.h" // for mozFlushType enum
- #include "mozilla/OwningNonNull.h" // for OwningNonNull
- #include "mozilla/SelectionState.h" // for RangeUpdater, etc.
- #include "mozilla/StyleSheet.h" // for StyleSheet
- #include "mozilla/UniquePtr.h"
- #include "mozilla/WeakPtr.h" // for WeakPtr
- #include "mozilla/dom/Text.h"
- #include "nsCOMPtr.h" // for already_AddRefed, nsCOMPtr
- #include "nsCycleCollectionParticipant.h"
- #include "nsGkAtoms.h"
- #include "nsIDocument.h" // for nsIDocument
- #include "nsIEditor.h" // for nsIEditor::EDirection, etc.
- #include "nsIEditorIMESupport.h" // for NS_DECL_NSIEDITORIMESUPPORT, etc.
- #include "nsIObserver.h" // for NS_DECL_NSIOBSERVER, etc.
- #include "nsIPhonetic.h" // for NS_DECL_NSIPHONETIC, etc.
- #include "nsIPlaintextEditor.h" // for nsIPlaintextEditor, etc.
- #include "nsISelectionController.h" // for nsISelectionController constants
- #include "nsISupportsImpl.h" // for EditorBase::Release, etc.
- #include "nsIWeakReferenceUtils.h" // for nsWeakPtr
- #include "nsLiteralString.h" // for NS_LITERAL_STRING
- #include "nsString.h" // for nsCString
- #include "nsWeakReference.h" // for nsSupportsWeakReference
- #include "nscore.h" // for nsresult, nsAString, etc.
- class nsIAtom;
- class nsIContent;
- class nsIDOMEvent;
- class nsIDOMEventListener;
- class nsIDOMEventTarget;
- class nsIDOMKeyEvent;
- class nsIDOMNode;
- class nsIDocument;
- class nsIDocumentStateListener;
- class nsIEditActionListener;
- class nsIEditorObserver;
- class nsIInlineSpellChecker;
- class nsINode;
- class nsIPresShell;
- class nsISupports;
- class nsITransaction;
- class nsIWidget;
- class nsRange;
- class nsString;
- class nsTransactionManager;
- // This is int32_t instead of int16_t because nsIInlineSpellChecker.idl's
- // spellCheckAfterEditorChange is defined to take it as a long.
- // XXX EditAction causes unnecessary include of EditorBase from some places.
- // Why don't you move this to nsIEditor.idl?
- enum class EditAction : int32_t
- {
- ignore = -1,
- none = 0,
- undo,
- redo,
- insertNode,
- createNode,
- deleteNode,
- splitNode,
- joinNode,
- deleteText = 1003,
- // text commands
- insertText = 2000,
- insertIMEText = 2001,
- deleteSelection = 2002,
- setTextProperty = 2003,
- removeTextProperty = 2004,
- outputText = 2005,
- // html only action
- insertBreak = 3000,
- makeList = 3001,
- indent = 3002,
- outdent = 3003,
- align = 3004,
- makeBasicBlock = 3005,
- removeList = 3006,
- makeDefListItem = 3007,
- insertElement = 3008,
- insertQuotation = 3009,
- htmlPaste = 3012,
- loadHTML = 3013,
- resetTextProperties = 3014,
- setAbsolutePosition = 3015,
- removeAbsolutePosition = 3016,
- decreaseZIndex = 3017,
- increaseZIndex = 3018
- };
- inline bool operator!(const EditAction& aOp)
- {
- return aOp == EditAction::none;
- }
- namespace mozilla {
- class AddStyleSheetTransaction;
- class AutoRules;
- class AutoSelectionRestorer;
- class AutoTransactionsConserveSelection;
- class ChangeAttributeTransaction;
- class CompositionTransaction;
- class CreateElementTransaction;
- class DeleteNodeTransaction;
- class DeleteTextTransaction;
- class EditAggregateTransaction;
- class ErrorResult;
- class InsertNodeTransaction;
- class InsertTextTransaction;
- class JoinNodeTransaction;
- class PlaceholderTransaction;
- class RemoveStyleSheetTransaction;
- class SplitNodeTransaction;
- class TextComposition;
- struct EditorDOMPoint;
- namespace dom {
- class DataTransfer;
- class Element;
- class EventTarget;
- class Selection;
- class Text;
- } // namespace dom
- namespace widget {
- struct IMEState;
- } // namespace widget
- /**
- * CachedWeakPtr stores a pointer to a class which inherits nsIWeakReference.
- * If the instance of the class has already been destroyed, this returns
- * nullptr. Otherwise, returns cached pointer.
- */
- template<class T>
- class CachedWeakPtr final
- {
- public:
- CachedWeakPtr<T>()
- : mCache(nullptr)
- {
- }
- CachedWeakPtr<T>& operator=(T* aObject)
- {
- mWeakPtr = do_GetWeakReference(aObject);
- mCache = aObject;
- return *this;
- }
- CachedWeakPtr<T>& operator=(const nsCOMPtr<T>& aOther)
- {
- mWeakPtr = do_GetWeakReference(aOther);
- mCache = aOther;
- return *this;
- }
- CachedWeakPtr<T>& operator=(already_AddRefed<T>& aOther)
- {
- nsCOMPtr<T> other = aOther;
- mWeakPtr = do_GetWeakReference(other);
- mCache = other;
- return *this;
- }
- bool IsAlive() const { return mWeakPtr && mWeakPtr->IsAlive(); }
- explicit operator bool() const { return mWeakPtr; }
- operator T*() const { return get(); }
- T* get() const
- {
- if (mCache && !mWeakPtr->IsAlive()) {
- const_cast<CachedWeakPtr<T>*>(this)->mCache = nullptr;
- }
- return mCache;
- }
- private:
- nsWeakPtr mWeakPtr;
- T* MOZ_NON_OWNING_REF mCache;
- };
- #define kMOZEditorBogusNodeAttrAtom nsGkAtoms::mozeditorbogusnode
- #define kMOZEditorBogusNodeValue NS_LITERAL_STRING("TRUE")
- /**
- * Implementation of an editor object. it will be the controller/focal point
- * for the main editor services. i.e. the GUIManager, publishing, transaction
- * manager, event interfaces. the idea for the event interfaces is to have them
- * delegate the actual commands to the editor independent of the XPFE
- * implementation.
- */
- class EditorBase : public nsIEditor
- , public nsIEditorIMESupport
- , public nsSupportsWeakReference
- , public nsIPhonetic
- {
- public:
- typedef dom::Element Element;
- typedef dom::Selection Selection;
- typedef dom::Text Text;
- enum IterDirection
- {
- kIterForward,
- kIterBackward
- };
- /**
- * The default constructor. This should suffice. the setting of the
- * interfaces is done after the construction of the editor class.
- */
- EditorBase();
- protected:
- /**
- * The default destructor. This should suffice. Should this be pure virtual
- * for someone to derive from the EditorBase later? I don't believe so.
- */
- virtual ~EditorBase();
- public:
- NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(EditorBase, nsIEditor)
- bool IsInitialized() const { return !!mDocumentWeak; }
- already_AddRefed<nsIDOMDocument> GetDOMDocument();
- already_AddRefed<nsIDocument> GetDocument();
- already_AddRefed<nsIPresShell> GetPresShell();
- already_AddRefed<nsIWidget> GetWidget();
- enum NotificationForEditorObservers
- {
- eNotifyEditorObserversOfEnd,
- eNotifyEditorObserversOfBefore,
- eNotifyEditorObserversOfCancel
- };
- void NotifyEditorObservers(NotificationForEditorObservers aNotification);
- // nsIEditor methods
- NS_DECL_NSIEDITOR
- // nsIEditorIMESupport methods
- NS_DECL_NSIEDITORIMESUPPORT
- // nsIPhonetic
- NS_DECL_NSIPHONETIC
- public:
- virtual bool IsModifiableNode(nsINode* aNode);
- virtual nsresult InsertTextImpl(const nsAString& aStringToInsert,
- nsCOMPtr<nsINode>* aInOutNode,
- int32_t* aInOutOffset,
- nsIDocument* aDoc);
- nsresult InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
- Text& aTextNode, int32_t aOffset,
- bool aSuppressIME = false);
- NS_IMETHOD DeleteSelectionImpl(EDirection aAction,
- EStripWrappers aStripWrappers);
- already_AddRefed<Element> DeleteSelectionAndCreateElement(nsIAtom& aTag);
- /**
- * Helper routines for node/parent manipulations.
- */
- nsresult DeleteNode(nsINode* aNode);
- nsresult InsertNode(nsIContent& aNode, nsINode& aParent, int32_t aPosition);
- enum ECloneAttributes { eDontCloneAttributes, eCloneAttributes };
- already_AddRefed<Element> ReplaceContainer(Element* aOldContainer,
- nsIAtom* aNodeType,
- nsIAtom* aAttribute = nullptr,
- const nsAString* aValue = nullptr,
- ECloneAttributes aCloneAttributes
- = eDontCloneAttributes);
- void CloneAttributes(Element* aDest, Element* aSource);
- nsresult RemoveContainer(nsIContent* aNode);
- already_AddRefed<Element> InsertContainerAbove(nsIContent* aNode,
- nsIAtom* aNodeType,
- nsIAtom* aAttribute = nullptr,
- const nsAString* aValue =
- nullptr);
- nsIContent* SplitNode(nsIContent& aNode, int32_t aOffset,
- ErrorResult& aResult);
- nsresult JoinNodes(nsINode& aLeftNode, nsINode& aRightNode);
- nsresult MoveNode(nsIContent* aNode, nsINode* aParent, int32_t aOffset);
- nsresult CloneAttribute(nsIAtom* aAttribute, Element* aDestElement,
- Element* aSourceElement);
- nsresult RemoveAttribute(Element* aElement, nsIAtom* aAttribute);
- virtual nsresult RemoveAttributeOrEquivalent(Element* aElement,
- nsIAtom* aAttribute,
- bool aSuppressTransaction) = 0;
- nsresult SetAttribute(Element* aElement, nsIAtom* aAttribute,
- const nsAString& aValue);
- virtual nsresult SetAttributeOrEquivalent(Element* aElement,
- nsIAtom* aAttribute,
- const nsAString& aValue,
- bool aSuppressTransaction) = 0;
- /**
- * Method to replace certain CreateElementNS() calls.
- *
- * @param aTag Tag you want.
- */
- already_AddRefed<Element> CreateHTMLContent(nsIAtom* aTag);
- /**
- * IME event handlers.
- */
- virtual nsresult BeginIMEComposition(WidgetCompositionEvent* aEvent);
- virtual nsresult UpdateIMEComposition(
- WidgetCompositionEvent* aCompositionChangeEvent) = 0;
- void EndIMEComposition();
- void SwitchTextDirectionTo(uint32_t aDirection);
- protected:
- nsresult DetermineCurrentDirection();
- void FireInputEvent();
- /**
- * Create a transaction for setting aAttribute to aValue on aElement. Never
- * returns null.
- */
- already_AddRefed<ChangeAttributeTransaction>
- CreateTxnForSetAttribute(Element& aElement, nsIAtom& aAttribute,
- const nsAString& aValue);
- /**
- * Create a transaction for removing aAttribute on aElement. Never returns
- * null.
- */
- already_AddRefed<ChangeAttributeTransaction>
- CreateTxnForRemoveAttribute(Element& aElement, nsIAtom& aAttribute);
- /**
- * Create a transaction for creating a new child node of aParent of type aTag.
- */
- already_AddRefed<CreateElementTransaction>
- CreateTxnForCreateElement(nsIAtom& aTag,
- nsINode& aParent,
- int32_t aPosition);
- already_AddRefed<Element> CreateNode(nsIAtom* aTag, nsINode* aParent,
- int32_t aPosition);
- /**
- * Create a transaction for inserting aNode as a child of aParent.
- */
- already_AddRefed<InsertNodeTransaction>
- CreateTxnForInsertNode(nsIContent& aNode, nsINode& aParent,
- int32_t aOffset);
- /**
- * Create a transaction for removing aNode from its parent.
- */
- nsresult CreateTxnForDeleteNode(nsINode* aNode,
- DeleteNodeTransaction** aTransaction);
- nsresult CreateTxnForDeleteSelection(
- EDirection aAction,
- EditAggregateTransaction** aTransaction,
- nsINode** aNode,
- int32_t* aOffset,
- int32_t* aLength);
- nsresult CreateTxnForDeleteInsertionPoint(
- nsRange* aRange,
- EDirection aAction,
- EditAggregateTransaction* aTransaction,
- nsINode** aNode,
- int32_t* aOffset,
- int32_t* aLength);
- /**
- * Create a transaction for inserting aStringToInsert into aTextNode. Never
- * returns null.
- */
- already_AddRefed<mozilla::InsertTextTransaction>
- CreateTxnForInsertText(const nsAString& aStringToInsert, Text& aTextNode,
- int32_t aOffset);
- /**
- * Never returns null.
- */
- already_AddRefed<mozilla::CompositionTransaction>
- CreateTxnForComposition(const nsAString& aStringToInsert);
- /**
- * Create a transaction for adding a style sheet.
- */
- NS_IMETHOD CreateTxnForAddStyleSheet(
- StyleSheet* aSheet,
- AddStyleSheetTransaction** aTransaction);
- /**
- * Create a transaction for removing a style sheet.
- */
- NS_IMETHOD CreateTxnForRemoveStyleSheet(
- StyleSheet* aSheet,
- RemoveStyleSheetTransaction** aTransaction);
- nsresult DeleteText(nsGenericDOMDataNode& aElement,
- uint32_t aOffset, uint32_t aLength);
- already_AddRefed<DeleteTextTransaction>
- CreateTxnForDeleteText(nsGenericDOMDataNode& aElement,
- uint32_t aOffset, uint32_t aLength);
- already_AddRefed<DeleteTextTransaction>
- CreateTxnForDeleteCharacter(nsGenericDOMDataNode& aData, uint32_t aOffset,
- EDirection aDirection);
- already_AddRefed<SplitNodeTransaction>
- CreateTxnForSplitNode(nsIContent& aNode, uint32_t aOffset);
- already_AddRefed<JoinNodeTransaction>
- CreateTxnForJoinNode(nsINode& aLeftNode, nsINode& aRightNode);
- /**
- * This method first deletes the selection, if it's not collapsed. Then if
- * the selection lies in a CharacterData node, it splits it. If the
- * selection is at this point collapsed in a CharacterData node, it's
- * adjusted to be collapsed right before or after the node instead (which is
- * always possible, since the node was split).
- */
- nsresult DeleteSelectionAndPrepareToCreateNode();
- /**
- * Called after a transaction is done successfully.
- */
- void DoAfterDoTransaction(nsITransaction *aTxn);
- /**
- * Called after a transaction is undone successfully.
- */
- void DoAfterUndoTransaction();
- /**
- * Called after a transaction is redone successfully.
- */
- void DoAfterRedoTransaction();
- enum TDocumentListenerNotification
- {
- eDocumentCreated,
- eDocumentToBeDestroyed,
- eDocumentStateChanged
- };
- /**
- * Tell the doc state listeners that the doc state has changed.
- */
- NS_IMETHOD NotifyDocumentListeners(
- TDocumentListenerNotification aNotificationType);
- /**
- * Make the given selection span the entire document.
- */
- virtual nsresult SelectEntireDocument(Selection* aSelection);
- /**
- * Helper method for scrolling the selection into view after
- * an edit operation. aScrollToAnchor should be true if you
- * want to scroll to the point where the selection was started.
- * If false, it attempts to scroll the end of the selection into view.
- *
- * Editor methods *should* call this method instead of the versions
- * in the various selection interfaces, since this version makes sure
- * that the editor's sync/async settings for reflowing, painting, and
- * scrolling match.
- */
- NS_IMETHOD ScrollSelectionIntoView(bool aScrollToAnchor);
- virtual bool IsBlockNode(nsINode* aNode);
- /**
- * Helper for GetPriorNode() and GetNextNode().
- */
- nsIContent* FindNextLeafNode(nsINode* aCurrentNode,
- bool aGoForward,
- bool bNoBlockCrossing);
- virtual nsresult InstallEventListeners();
- virtual void CreateEventListeners();
- virtual void RemoveEventListeners();
- /**
- * Return true if spellchecking should be enabled for this editor.
- */
- bool GetDesiredSpellCheckState();
- bool CanEnableSpellCheck()
- {
- // Check for password/readonly/disabled, which are not spellchecked
- // regardless of DOM. Also, check to see if spell check should be skipped
- // or not.
- return !IsPasswordEditor() && !IsReadonly() && !IsDisabled() &&
- !ShouldSkipSpellCheck();
- }
- /**
- * EnsureComposition() should be called by composition event handlers. This
- * tries to get the composition for the event and set it to mComposition.
- * However, this may fail because the composition may be committed before
- * the event comes to the editor.
- *
- * @return true if there is a composition. Otherwise, for example,
- * a composition event handler in web contents moved focus
- * for committing the composition, returns false.
- */
- bool EnsureComposition(WidgetCompositionEvent* aCompositionEvent);
- already_AddRefed<nsISelectionController> GetSelectionController();
- nsresult GetSelection(SelectionType aSelectionType,
- nsISelection** aSelection);
- public:
- /**
- * All editor operations which alter the doc should be prefaced
- * with a call to StartOperation, naming the action and direction.
- */
- NS_IMETHOD StartOperation(EditAction opID,
- nsIEditor::EDirection aDirection);
- /**
- * All editor operations which alter the doc should be followed
- * with a call to EndOperation.
- */
- NS_IMETHOD EndOperation();
- /**
- * Routines for managing the preservation of selection across
- * various editor actions.
- */
- bool ArePreservingSelection();
- void PreserveSelectionAcrossActions(Selection* aSel);
- nsresult RestorePreservedSelection(Selection* aSel);
- void StopPreservingSelection();
- /**
- * SplitNode() creates a new node identical to an existing node, and split
- * the contents between the two nodes
- * @param aExistingRightNode The node to split. It will become the new
- * node's next sibling.
- * @param aOffset The offset of aExistingRightNode's
- * content|children to do the split at
- * @param aNewLeftNode The new node resulting from the split, becomes
- * aExistingRightNode's previous sibling.
- */
- nsresult SplitNodeImpl(nsIContent& aExistingRightNode,
- int32_t aOffset,
- nsIContent& aNewLeftNode);
- /**
- * JoinNodes() takes 2 nodes and merge their content|children.
- * @param aNodeToKeep The node that will remain after the join.
- * @param aNodeToJoin The node that will be joined with aNodeToKeep.
- * There is no requirement that the two nodes be of the
- * same type.
- * @param aParent The parent of aNodeToKeep
- */
- nsresult JoinNodesImpl(nsINode* aNodeToKeep,
- nsINode* aNodeToJoin,
- nsINode* aParent);
- /**
- * Return the offset of aChild in aParent. Asserts fatally if parent or
- * child is null, or parent is not child's parent.
- */
- static int32_t GetChildOffset(nsIDOMNode* aChild,
- nsIDOMNode* aParent);
- /**
- * Set outOffset to the offset of aChild in the parent.
- * Returns the parent of aChild.
- */
- static already_AddRefed<nsIDOMNode> GetNodeLocation(nsIDOMNode* aChild,
- int32_t* outOffset);
- static nsINode* GetNodeLocation(nsINode* aChild, int32_t* aOffset);
- /**
- * Returns the number of things inside aNode in the out-param aCount.
- * @param aNode is the node to get the length of.
- * If aNode is text, returns number of characters.
- * If not, returns number of children nodes.
- * @param aCount [OUT] the result of the above calculation.
- */
- static nsresult GetLengthOfDOMNode(nsIDOMNode *aNode, uint32_t &aCount);
- /**
- * Get the node immediately prior to aCurrentNode.
- * @param aCurrentNode the node from which we start the search
- * @param aEditableNode if true, only return an editable node
- * @param aResultNode [OUT] the node that occurs before aCurrentNode in
- * the tree, skipping non-editable nodes if
- * aEditableNode is true. If there is no prior
- * node, aResultNode will be nullptr.
- * @param bNoBlockCrossing If true, don't move across "block" nodes,
- * whatever that means.
- */
- nsIContent* GetPriorNode(nsINode* aCurrentNode, bool aEditableNode,
- bool aNoBlockCrossing = false);
- /**
- * And another version that takes a {parent,offset} pair rather than a node.
- */
- nsIContent* GetPriorNode(nsINode* aParentNode,
- int32_t aOffset,
- bool aEditableNode,
- bool aNoBlockCrossing = false);
- /**
- * Get the node immediately after to aCurrentNode.
- * @param aCurrentNode the node from which we start the search
- * @param aEditableNode if true, only return an editable node
- * @param aResultNode [OUT] the node that occurs after aCurrentNode in the
- * tree, skipping non-editable nodes if
- * aEditableNode is true. If there is no prior
- * node, aResultNode will be nullptr.
- */
- nsIContent* GetNextNode(nsINode* aCurrentNode,
- bool aEditableNode,
- bool bNoBlockCrossing = false);
- /**
- * And another version that takes a {parent,offset} pair rather than a node.
- */
- nsIContent* GetNextNode(nsINode* aParentNode,
- int32_t aOffset,
- bool aEditableNode,
- bool aNoBlockCrossing = false);
- /**
- * Helper for GetNextNode() and GetPriorNode().
- */
- nsIContent* FindNode(nsINode* aCurrentNode,
- bool aGoForward,
- bool aEditableNode,
- bool bNoBlockCrossing);
- /**
- * Get the rightmost child of aCurrentNode;
- * return nullptr if aCurrentNode has no children.
- */
- nsIContent* GetRightmostChild(nsINode* aCurrentNode,
- bool bNoBlockCrossing = false);
- /**
- * Get the leftmost child of aCurrentNode;
- * return nullptr if aCurrentNode has no children.
- */
- nsIContent* GetLeftmostChild(nsINode *aCurrentNode,
- bool bNoBlockCrossing = false);
- /**
- * Returns true if aNode is of the type implied by aTag.
- */
- static inline bool NodeIsType(nsIDOMNode* aNode, nsIAtom* aTag)
- {
- return GetTag(aNode) == aTag;
- }
- /**
- * Returns true if aParent can contain a child of type aTag.
- */
- bool CanContain(nsINode& aParent, nsIContent& aChild);
- bool CanContainTag(nsINode& aParent, nsIAtom& aTag);
- bool TagCanContain(nsIAtom& aParentTag, nsIContent& aChild);
- virtual bool TagCanContainTag(nsIAtom& aParentTag, nsIAtom& aChildTag);
- /**
- * Returns true if aNode is our root node.
- */
- bool IsRoot(nsIDOMNode* inNode);
- bool IsRoot(nsINode* inNode);
- bool IsEditorRoot(nsINode* aNode);
- /**
- * Returns true if aNode is a descendant of our root node.
- */
- bool IsDescendantOfRoot(nsIDOMNode* inNode);
- bool IsDescendantOfRoot(nsINode* inNode);
- bool IsDescendantOfEditorRoot(nsINode* aNode);
- /**
- * Returns true if aNode is a container.
- */
- virtual bool IsContainer(nsINode* aNode);
- virtual bool IsContainer(nsIDOMNode* aNode);
- /**
- * returns true if aNode is an editable node.
- */
- bool IsEditable(nsIDOMNode* aNode);
- virtual bool IsEditable(nsINode* aNode);
- /**
- * Returns true if aNode is a MozEditorBogus node.
- */
- bool IsMozEditorBogusNode(nsINode* aNode);
- /**
- * Counts number of editable child nodes.
- */
- uint32_t CountEditableChildren(nsINode* aNode);
- /**
- * Find the deep first and last children.
- */
- nsINode* GetFirstEditableNode(nsINode* aRoot);
- /**
- * Returns current composition.
- */
- TextComposition* GetComposition() const;
- /**
- * Returns true if there is composition string and not fixed.
- */
- bool IsIMEComposing() const;
- /**
- * Returns true when inserting text should be a part of current composition.
- */
- bool ShouldHandleIMEComposition() const;
- /**
- * From html rules code - migration in progress.
- */
- static nsresult GetTagString(nsIDOMNode* aNode, nsAString& outString);
- static nsIAtom* GetTag(nsIDOMNode* aNode);
- bool NodesSameType(nsIDOMNode* aNode1, nsIDOMNode* aNode2);
- virtual bool AreNodesSameType(nsIContent* aNode1, nsIContent* aNode2);
- static bool IsTextNode(nsIDOMNode* aNode);
- static bool IsTextNode(nsINode* aNode);
- static nsCOMPtr<nsIDOMNode> GetChildAt(nsIDOMNode* aParent, int32_t aOffset);
- static nsIContent* GetNodeAtRangeOffsetPoint(nsIDOMNode* aParentOrNode,
- int32_t aOffset);
- static nsresult GetStartNodeAndOffset(Selection* aSelection,
- nsIDOMNode** outStartNode,
- int32_t* outStartOffset);
- static nsresult GetStartNodeAndOffset(Selection* aSelection,
- nsINode** aStartNode,
- int32_t* aStartOffset);
- static nsresult GetEndNodeAndOffset(Selection* aSelection,
- nsIDOMNode** outEndNode,
- int32_t* outEndOffset);
- static nsresult GetEndNodeAndOffset(Selection* aSelection,
- nsINode** aEndNode,
- int32_t* aEndOffset);
- #if DEBUG_JOE
- static void DumpNode(nsIDOMNode* aNode, int32_t indent = 0);
- #endif
- Selection* GetSelection(SelectionType aSelectionType =
- SelectionType::eNormal);
- /**
- * Helpers to add a node to the selection.
- * Used by table cell selection methods.
- */
- nsresult CreateRange(nsIDOMNode* aStartParent, int32_t aStartOffset,
- nsIDOMNode* aEndParent, int32_t aEndOffset,
- nsRange** aRange);
- /**
- * Creates a range with just the supplied node and appends that to the
- * selection.
- */
- nsresult AppendNodeToSelectionAsRange(nsIDOMNode *aNode);
- /**
- * When you are using AppendNodeToSelectionAsRange(), call this first to
- * start a new selection.
- */
- nsresult ClearSelection();
- nsresult IsPreformatted(nsIDOMNode* aNode, bool* aResult);
- enum class EmptyContainers { no, yes };
- int32_t SplitNodeDeep(nsIContent& aNode, nsIContent& aSplitPointParent,
- int32_t aSplitPointOffset,
- EmptyContainers aEmptyContainers =
- EmptyContainers::yes,
- nsIContent** outLeftNode = nullptr,
- nsIContent** outRightNode = nullptr);
- EditorDOMPoint JoinNodeDeep(nsIContent& aLeftNode,
- nsIContent& aRightNode);
- nsresult GetString(const nsAString& name, nsAString& value);
- void BeginUpdateViewBatch();
- virtual nsresult EndUpdateViewBatch();
- bool GetShouldTxnSetSelection();
- virtual nsresult HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent);
- nsresult HandleInlineSpellCheck(EditAction action,
- Selection* aSelection,
- nsIDOMNode* previousSelectedNode,
- int32_t previousSelectedOffset,
- nsIDOMNode* aStartNode,
- int32_t aStartOffset,
- nsIDOMNode* aEndNode,
- int32_t aEndOffset);
- virtual already_AddRefed<dom::EventTarget> GetDOMEventTarget() = 0;
- /**
- * Fast non-refcounting editor root element accessor
- */
- Element* GetRoot();
- /**
- * Likewise, but gets the editor's root instead, which is different for HTML
- * editors.
- */
- virtual Element* GetEditorRoot();
- /**
- * Likewise, but gets the text control element instead of the root for
- * plaintext editors.
- */
- Element* GetExposedRoot();
- /**
- * Accessor methods to flags.
- */
- bool IsPlaintextEditor() const
- {
- return (mFlags & nsIPlaintextEditor::eEditorPlaintextMask) != 0;
- }
- bool IsSingleLineEditor() const
- {
- return (mFlags & nsIPlaintextEditor::eEditorSingleLineMask) != 0;
- }
- bool IsPasswordEditor() const
- {
- return (mFlags & nsIPlaintextEditor::eEditorPasswordMask) != 0;
- }
- bool IsReadonly() const
- {
- return (mFlags & nsIPlaintextEditor::eEditorReadonlyMask) != 0;
- }
- bool IsDisabled() const
- {
- return (mFlags & nsIPlaintextEditor::eEditorDisabledMask) != 0;
- }
- bool IsInputFiltered() const
- {
- return (mFlags & nsIPlaintextEditor::eEditorFilterInputMask) != 0;
- }
- bool IsMailEditor() const
- {
- return (mFlags & nsIPlaintextEditor::eEditorMailMask) != 0;
- }
- bool IsWrapHackEnabled() const
- {
- return (mFlags & nsIPlaintextEditor::eEditorEnableWrapHackMask) != 0;
- }
- bool IsFormWidget() const
- {
- return (mFlags & nsIPlaintextEditor::eEditorWidgetMask) != 0;
- }
- bool NoCSS() const
- {
- return (mFlags & nsIPlaintextEditor::eEditorNoCSSMask) != 0;
- }
- bool IsInteractionAllowed() const
- {
- return (mFlags & nsIPlaintextEditor::eEditorAllowInteraction) != 0;
- }
- bool DontEchoPassword() const
- {
- return (mFlags & nsIPlaintextEditor::eEditorDontEchoPassword) != 0;
- }
- bool ShouldSkipSpellCheck() const
- {
- return (mFlags & nsIPlaintextEditor::eEditorSkipSpellCheck) != 0;
- }
- bool IsTabbable() const
- {
- return IsSingleLineEditor() || IsPasswordEditor() || IsFormWidget() ||
- IsInteractionAllowed();
- }
- bool HasIndependentSelection() const
- {
- return !!mSelectionControllerWeak;
- }
- /**
- * Get the input event target. This might return null.
- */
- virtual already_AddRefed<nsIContent> GetInputEventTargetContent() = 0;
- /**
- * Get the focused content, if we're focused. Returns null otherwise.
- */
- virtual already_AddRefed<nsIContent> GetFocusedContent();
- /**
- * Get the focused content for the argument of some IMEStateManager's
- * methods.
- */
- virtual already_AddRefed<nsIContent> GetFocusedContentForIME();
- /**
- * Whether the editor is active on the DOM window. Note that when this
- * returns true but GetFocusedContent() returns null, it means that this editor was
- * focused when the DOM window was active.
- */
- virtual bool IsActiveInDOMWindow();
- /**
- * Whether the aGUIEvent should be handled by this editor or not. When this
- * returns false, The aGUIEvent shouldn't be handled on this editor,
- * i.e., The aGUIEvent should be handled by another inner editor or ancestor
- * elements.
- */
- virtual bool IsAcceptableInputEvent(WidgetGUIEvent* aGUIEvent);
- /**
- * FindSelectionRoot() returns a selection root of this editor when aNode
- * gets focus. aNode must be a content node or a document node. When the
- * target isn't a part of this editor, returns nullptr. If this is for
- * designMode, you should set the document node to aNode except that an
- * element in the document has focus.
- */
- virtual already_AddRefed<nsIContent> FindSelectionRoot(nsINode* aNode);
- /**
- * Initializes selection and caret for the editor. If aEventTarget isn't
- * a host of the editor, i.e., the editor doesn't get focus, this does
- * nothing.
- */
- nsresult InitializeSelection(nsIDOMEventTarget* aFocusEventTarget);
- /**
- * This method has to be called by EditorEventListener::Focus.
- * All actions that have to be done when the editor is focused needs to be
- * added here.
- */
- void OnFocus(nsIDOMEventTarget* aFocusEventTarget);
- /**
- * Used to insert content from a data transfer into the editable area.
- * This is called for each item in the data transfer, with the index of
- * each item passed as aIndex.
- */
- virtual nsresult InsertFromDataTransfer(dom::DataTransfer* aDataTransfer,
- int32_t aIndex,
- nsIDOMDocument* aSourceDoc,
- nsIDOMNode* aDestinationNode,
- int32_t aDestOffset,
- bool aDoDeleteSelection) = 0;
- virtual nsresult InsertFromDrop(nsIDOMEvent* aDropEvent) = 0;
- virtual already_AddRefed<nsIDOMNode> FindUserSelectAllNode(nsIDOMNode* aNode)
- {
- return nullptr;
- }
- /**
- * GetIMESelectionStartOffsetIn() returns the start offset of IME selection in
- * the aTextNode. If there is no IME selection, returns -1.
- */
- int32_t GetIMESelectionStartOffsetIn(nsINode* aTextNode);
- /**
- * FindBetterInsertionPoint() tries to look for better insertion point which
- * is typically the nearest text node and offset in it.
- */
- void FindBetterInsertionPoint(nsCOMPtr<nsIDOMNode>& aNode,
- int32_t& aOffset);
- void FindBetterInsertionPoint(nsCOMPtr<nsINode>& aNode,
- int32_t& aOffset);
- /**
- * HideCaret() hides caret with nsCaret::AddForceHide() or may show carent
- * with nsCaret::RemoveForceHide(). This does NOT set visibility of
- * nsCaret. Therefore, this is stateless.
- */
- void HideCaret(bool aHide);
- void FlushFrames()
- {
- nsCOMPtr<nsIDocument> doc = GetDocument();
- if (doc) {
- doc->FlushPendingNotifications(Flush_Frames);
- }
- }
- private:
- // Weak reference to the nsISelectionController.
- // Use GetSelectionController() to retrieve actual pointer.
- CachedWeakPtr<nsISelectionController> mSelectionControllerWeak;
- // Weak reference to the nsIDocument.
- // Use GetDocument() to retrieve actual pointer.
- CachedWeakPtr<nsIDocument> mDocumentWeak;
- protected:
- enum Tristate
- {
- eTriUnset,
- eTriFalse,
- eTriTrue
- };
- // MIME type of the doc we are editing.
- nsCString mContentMIMEType;
- nsCOMPtr<nsIInlineSpellChecker> mInlineSpellChecker;
- RefPtr<nsTransactionManager> mTxnMgr;
- // Cached root node.
- nsCOMPtr<Element> mRootElement;
- // Current IME text node.
- RefPtr<Text> mIMETextNode;
- // The form field as an event receiver.
- nsCOMPtr<dom::EventTarget> mEventTarget;
- nsCOMPtr<nsIDOMEventListener> mEventListener;
- // Weak reference to placeholder for begin/end batch purposes.
- WeakPtr<PlaceholderTransaction> mPlaceholderTransactionWeak;
- // Name of placeholder transaction.
- nsIAtom* mPlaceholderName;
- // Saved selection state for placeholder transaction batching.
- mozilla::UniquePtr<SelectionState> mSelState;
- nsString* mPhonetic;
- // IME composition this is not null between compositionstart and
- // compositionend.
- RefPtr<TextComposition> mComposition;
- // Listens to all low level actions on the doc.
- typedef AutoTArray<OwningNonNull<nsIEditActionListener>, 5>
- AutoActionListenerArray;
- AutoActionListenerArray mActionListeners;
- // Just notify once per high level change.
- typedef AutoTArray<OwningNonNull<nsIEditorObserver>, 3>
- AutoEditorObserverArray;
- AutoEditorObserverArray mEditorObservers;
- // Listen to overall doc state (dirty or not, just created, etc.).
- typedef AutoTArray<OwningNonNull<nsIDocumentStateListener>, 1>
- AutoDocumentStateListenerArray;
- AutoDocumentStateListenerArray mDocStateListeners;
- // Cached selection for AutoSelectionRestorer.
- SelectionState mSavedSel;
- // Utility class object for maintaining preserved ranges.
- RangeUpdater mRangeUpdater;
- // Number of modifications (for undo/redo stack).
- uint32_t mModCount;
- // Behavior flags. See nsIPlaintextEditor.idl for the flags we use.
- uint32_t mFlags;
- int32_t mUpdateCount;
- // Nesting count for batching.
- int32_t mPlaceholderBatch;
- // The current editor action.
- EditAction mAction;
- // Offset in text node where IME comp string begins.
- uint32_t mIMETextOffset;
- // The Length of the composition string or commit string. If this is length
- // of commit string, the length is truncated by maxlength attribute.
- uint32_t mIMETextLength;
- // The current direction of editor action.
- EDirection mDirection;
- // -1 = not initialized
- int8_t mDocDirtyState;
- // A Tristate value.
- uint8_t mSpellcheckCheckboxState;
- // Turn off for conservative selection adjustment by transactions.
- bool mShouldTxnSetSelection;
- // Whether PreDestroy has been called.
- bool mDidPreDestroy;
- // Whether PostCreate has been called.
- bool mDidPostCreate;
- bool mDispatchInputEvent;
- // True while the instance is handling an edit action.
- bool mIsInEditAction;
- // Whether caret is hidden forcibly.
- bool mHidingCaret;
- friend bool NSCanUnload(nsISupports* serviceMgr);
- friend class AutoRules;
- friend class AutoSelectionRestorer;
- friend class AutoTransactionsConserveSelection;
- friend class RangeUpdater;
- };
- } // namespace mozilla
- #endif // #ifndef mozilla_EditorBase_h
|