1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
9 #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc.
10 #include "mozilla/OwningNonNull.h" // for OwningNonNull
11 #include "mozilla/StyleSheetHandle.h" // for StyleSheetHandle
12 #include "mozilla/dom/Text.h"
13 #include "nsAutoPtr.h" // for nsRefPtr
14 #include "nsCOMPtr.h" // for already_AddRefed, nsCOMPtr
15 #include "nsCycleCollectionParticipant.h"
16 #include "nsGkAtoms.h"
17 #include "nsIEditor.h" // for nsIEditor::EDirection, etc
18 #include "nsIEditorIMESupport.h" // for NS_DECL_NSIEDITORIMESUPPORT, etc
19 #include "nsIObserver.h" // for NS_DECL_NSIOBSERVER, etc
20 #include "nsIPhonetic.h" // for NS_DECL_NSIPHONETIC, etc
21 #include "nsIPlaintextEditor.h" // for nsIPlaintextEditor, etc
22 #include "nsISelectionController.h" // for nsISelectionController constants
23 #include "nsISupportsImpl.h" // for nsEditor::Release, etc
24 #include "nsIWeakReferenceUtils.h" // for nsWeakPtr
25 #include "nsLiteralString.h" // for NS_LITERAL_STRING
26 #include "nsSelectionState.h" // for nsRangeUpdater, etc
27 #include "nsString.h" // for nsCString
28 #include "nsWeakReference.h" // for nsSupportsWeakReference
29 #include "nscore.h" // for nsresult, nsAString, etc
31 class AddStyleSheetTxn
;
33 class EditAggregateTxn
;
34 class RemoveStyleSheetTxn
;
39 class nsIDOMEventListener
;
40 class nsIDOMEventTarget
;
44 class nsIDocumentStateListener
;
45 class nsIEditActionListener
;
46 class nsIEditorObserver
;
47 class nsIInlineSpellChecker
;
55 class nsTransactionManager
;
60 class TextComposition
;
63 class ChangeAttributeTxn
;
64 class CreateElementTxn
;
77 } // namespace mozilla
83 } // namespace mozilla
85 #define kMOZEditorBogusNodeAttrAtom nsGkAtoms::mozeditorbogusnode
86 #define kMOZEditorBogusNodeValue NS_LITERAL_STRING("TRUE")
88 // This is int32_t instead of int16_t because nsIInlineSpellChecker.idl's
89 // spellCheckAfterEditorChange is defined to take it as a long.
90 enum class EditAction
: int32_t {
104 insertIMEText
= 2001,
105 deleteSelection
= 2002,
106 setTextProperty
= 2003,
107 removeTextProperty
= 2004,
116 makeBasicBlock
= 3005,
118 makeDefListItem
= 3007,
119 insertElement
= 3008,
120 insertQuotation
= 3009,
123 resetTextProperties
= 3014,
124 setAbsolutePosition
= 3015,
125 removeAbsolutePosition
= 3016,
126 decreaseZIndex
= 3017,
127 increaseZIndex
= 3018
130 inline bool operator!(const EditAction
& aOp
)
132 return aOp
== EditAction::none
;
135 /** implementation of an editor object. it will be the controller/focal point
136 * for the main editor services. i.e. the GUIManager, publishing, transaction
137 * manager, event interfaces. the idea for the event interfaces is to have them
138 * delegate the actual commands to the editor independent of the XPFE implementation.
140 class nsEditor
: public nsIEditor
,
141 public nsIEditorIMESupport
,
142 public nsSupportsWeakReference
,
153 /** The default constructor. This should suffice. the setting of the interfaces is done
154 * after the construction of the editor class.
159 /** The default destructor. This should suffice. Should this be pure virtual
160 * for someone to derive from the nsEditor later? I don't believe so.
165 //Interfaces for addref and release and queryinterface
166 //NOTE: Use NS_DECL_ISUPPORTS_INHERITED in any class inherited from nsEditor
167 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
168 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsEditor
,
171 /* ------------ utility methods -------------- */
172 already_AddRefed
<nsIDOMDocument
> GetDOMDocument();
173 already_AddRefed
<nsIDocument
> GetDocument();
174 already_AddRefed
<nsIPresShell
> GetPresShell();
175 already_AddRefed
<nsIWidget
> GetWidget();
176 enum NotificationForEditorObservers
178 eNotifyEditorObserversOfEnd
,
179 eNotifyEditorObserversOfBefore
,
180 eNotifyEditorObserversOfCancel
182 void NotifyEditorObservers(NotificationForEditorObservers aNotification
);
184 /* ------------ nsIEditor methods -------------- */
187 /* ------------ nsIEditorIMESupport methods -------------- */
188 NS_DECL_NSIEDITORIMESUPPORT
195 virtual bool IsModifiableNode(nsINode
*aNode
);
197 virtual nsresult
InsertTextImpl(const nsAString
& aStringToInsert
,
198 nsCOMPtr
<nsINode
>* aInOutNode
,
199 int32_t* aInOutOffset
,
201 nsresult
InsertTextIntoTextNodeImpl(const nsAString
& aStringToInsert
,
202 mozilla::dom::Text
& aTextNode
,
204 bool aSuppressIME
= false);
205 NS_IMETHOD
DeleteSelectionImpl(EDirection aAction
,
206 EStripWrappers aStripWrappers
);
208 already_AddRefed
<mozilla::dom::Element
>
209 DeleteSelectionAndCreateElement(nsIAtom
& aTag
);
211 /* helper routines for node/parent manipulations */
212 nsresult
DeleteNode(nsINode
* aNode
);
213 nsresult
InsertNode(nsIContent
& aNode
, nsINode
& aParent
, int32_t aPosition
);
214 enum ECloneAttributes
{ eDontCloneAttributes
, eCloneAttributes
};
215 already_AddRefed
<mozilla::dom::Element
> ReplaceContainer(
216 mozilla::dom::Element
* aOldContainer
,
218 nsIAtom
* aAttribute
= nullptr,
219 const nsAString
* aValue
= nullptr,
220 ECloneAttributes aCloneAttributes
= eDontCloneAttributes
);
221 void CloneAttributes(mozilla::dom::Element
* aDest
,
222 mozilla::dom::Element
* aSource
);
224 nsresult
RemoveContainer(nsIContent
* aNode
);
225 already_AddRefed
<mozilla::dom::Element
> InsertContainerAbove(
228 nsIAtom
* aAttribute
= nullptr,
229 const nsAString
* aValue
= nullptr);
230 nsIContent
* SplitNode(nsIContent
& aNode
, int32_t aOffset
,
231 mozilla::ErrorResult
& aResult
);
232 nsresult
JoinNodes(nsINode
& aLeftNode
, nsINode
& aRightNode
);
233 nsresult
MoveNode(nsIContent
* aNode
, nsINode
* aParent
, int32_t aOffset
);
235 /* Method to replace certain CreateElementNS() calls.
237 nsIAtom* aTag - tag you want
239 already_AddRefed
<mozilla::dom::Element
> CreateHTMLContent(nsIAtom
* aTag
);
241 // IME event handlers
242 virtual nsresult
BeginIMEComposition(mozilla::WidgetCompositionEvent
* aEvent
);
243 virtual nsresult
UpdateIMEComposition(nsIDOMEvent
* aDOMTextEvent
) = 0;
244 void EndIMEComposition();
246 void SwitchTextDirectionTo(uint32_t aDirection
);
249 nsresult
DetermineCurrentDirection();
250 void FireInputEvent();
252 /** Create a transaction for setting aAttribute to aValue on aElement. Never
255 already_AddRefed
<mozilla::dom::ChangeAttributeTxn
>
256 CreateTxnForSetAttribute(mozilla::dom::Element
& aElement
,
257 nsIAtom
& aAttribute
, const nsAString
& aValue
);
259 /** Create a transaction for removing aAttribute on aElement. Never returns
262 already_AddRefed
<mozilla::dom::ChangeAttributeTxn
>
263 CreateTxnForRemoveAttribute(mozilla::dom::Element
& aElement
,
264 nsIAtom
& aAttribute
);
266 /** create a transaction for creating a new child node of aParent of type aTag.
268 already_AddRefed
<mozilla::dom::CreateElementTxn
>
269 CreateTxnForCreateElement(nsIAtom
& aTag
,
273 already_AddRefed
<mozilla::dom::Element
> CreateNode(nsIAtom
* aTag
,
277 /** create a transaction for inserting aNode as a child of aParent.
279 already_AddRefed
<mozilla::dom::InsertNodeTxn
>
280 CreateTxnForInsertNode(nsIContent
& aNode
, nsINode
& aParent
, int32_t aOffset
);
282 /** create a transaction for removing aNode from its parent.
284 nsresult
CreateTxnForDeleteNode(nsINode
* aNode
, DeleteNodeTxn
** aTxn
);
287 nsresult
CreateTxnForDeleteSelection(EDirection aAction
,
288 EditAggregateTxn
** aTxn
,
293 nsresult
CreateTxnForDeleteInsertionPoint(nsRange
* aRange
,
295 EditAggregateTxn
* aTxn
,
301 /** Create a transaction for inserting aStringToInsert into aTextNode. Never
304 already_AddRefed
<mozilla::dom::InsertTextTxn
>
305 CreateTxnForInsertText(const nsAString
& aStringToInsert
,
306 mozilla::dom::Text
& aTextNode
, int32_t aOffset
);
308 // Never returns null.
309 already_AddRefed
<mozilla::dom::IMETextTxn
>
310 CreateTxnForIMEText(const nsAString
& aStringToInsert
);
312 /** create a transaction for adding a style sheet
314 NS_IMETHOD
CreateTxnForAddStyleSheet(mozilla::StyleSheetHandle aSheet
,
315 AddStyleSheetTxn
* *aTxn
);
317 /** create a transaction for removing a style sheet
319 NS_IMETHOD
CreateTxnForRemoveStyleSheet(mozilla::StyleSheetHandle aSheet
,
320 RemoveStyleSheetTxn
* *aTxn
);
322 nsresult
DeleteText(nsGenericDOMDataNode
& aElement
,
323 uint32_t aOffset
, uint32_t aLength
);
325 // NS_IMETHOD DeleteRange(nsIDOMRange *aRange);
327 already_AddRefed
<mozilla::dom::DeleteTextTxn
>
328 CreateTxnForDeleteText(nsGenericDOMDataNode
& aElement
,
329 uint32_t aOffset
, uint32_t aLength
);
331 already_AddRefed
<mozilla::dom::DeleteTextTxn
>
332 CreateTxnForDeleteCharacter(nsGenericDOMDataNode
& aData
, uint32_t aOffset
,
333 EDirection aDirection
);
335 already_AddRefed
<mozilla::dom::SplitNodeTxn
>
336 CreateTxnForSplitNode(nsIContent
& aNode
, uint32_t aOffset
);
338 already_AddRefed
<mozilla::dom::JoinNodeTxn
>
339 CreateTxnForJoinNode(nsINode
& aLeftNode
, nsINode
& aRightNode
);
342 * This method first deletes the selection, if it's not collapsed. Then if
343 * the selection lies in a CharacterData node, it splits it. If the
344 * selection is at this point collapsed in a CharacterData node, it's
345 * adjusted to be collapsed right before or after the node instead (which is
346 * always possible, since the node was split).
348 nsresult
DeleteSelectionAndPrepareToCreateNode();
351 // called after a transaction is done successfully
352 void DoAfterDoTransaction(nsITransaction
*aTxn
);
353 // called after a transaction is undone successfully
354 void DoAfterUndoTransaction();
355 // called after a transaction is redone successfully
356 void DoAfterRedoTransaction();
360 eDocumentToBeDestroyed
,
361 eDocumentStateChanged
362 } TDocumentListenerNotification
;
364 // tell the doc state listeners that the doc state has changed
365 NS_IMETHOD
NotifyDocumentListeners(TDocumentListenerNotification aNotificationType
);
367 /** make the given selection span the entire document */
368 virtual nsresult
SelectEntireDocument(mozilla::dom::Selection
* aSelection
);
370 /** helper method for scrolling the selection into view after
371 * an edit operation. aScrollToAnchor should be true if you
372 * want to scroll to the point where the selection was started.
373 * If false, it attempts to scroll the end of the selection into view.
375 * Editor methods *should* call this method instead of the versions
376 * in the various selection interfaces, since this version makes sure
377 * that the editor's sync/async settings for reflowing, painting, and
380 NS_IMETHOD
ScrollSelectionIntoView(bool aScrollToAnchor
);
382 // Convenience method; forwards to IsBlockNode(nsINode*).
383 bool IsBlockNode(nsIDOMNode
* aNode
);
384 // stub. see comment in source.
385 virtual bool IsBlockNode(nsINode
* aNode
);
387 // helper for GetPriorNode and GetNextNode
388 nsIContent
* FindNextLeafNode(nsINode
*aCurrentNode
,
390 bool bNoBlockCrossing
);
392 // install the event listeners for the editor
393 virtual nsresult
InstallEventListeners();
395 virtual void CreateEventListeners();
397 // unregister and release our event listeners
398 virtual void RemoveEventListeners();
401 * Return true if spellchecking should be enabled for this editor.
403 bool GetDesiredSpellCheckState();
405 bool CanEnableSpellCheck()
407 // Check for password/readonly/disabled, which are not spellchecked
408 // regardless of DOM. Also, check to see if spell check should be skipped or not.
409 return !IsPasswordEditor() && !IsReadonly() && !IsDisabled() && !ShouldSkipSpellCheck();
413 * EnsureComposition() should be called by composition event handlers. This
414 * tries to get the composition for the event and set it to mComposition.
416 void EnsureComposition(mozilla::WidgetCompositionEvent
* aCompositionEvent
);
418 nsresult
GetSelection(int16_t aSelectionType
, nsISelection
** aSelection
);
422 /** All editor operations which alter the doc should be prefaced
423 * with a call to StartOperation, naming the action and direction */
424 NS_IMETHOD
StartOperation(EditAction opID
,
425 nsIEditor::EDirection aDirection
);
427 /** All editor operations which alter the doc should be followed
428 * with a call to EndOperation */
429 NS_IMETHOD
EndOperation();
431 /** routines for managing the preservation of selection across
432 * various editor actions */
433 bool ArePreservingSelection();
434 void PreserveSelectionAcrossActions(mozilla::dom::Selection
* aSel
);
435 nsresult
RestorePreservedSelection(mozilla::dom::Selection
* aSel
);
436 void StopPreservingSelection();
439 * SplitNode() creates a new node identical to an existing node, and split
440 * the contents between the two nodes
441 * @param aExistingRightNode The node to split. It will become the new
442 * node's next sibling.
443 * @param aOffset The offset of aExistingRightNode's
444 * content|children to do the split at
445 * @param aNewLeftNode The new node resulting from the split, becomes
446 * aExistingRightNode's previous sibling.
448 nsresult
SplitNodeImpl(nsIContent
& aExistingRightNode
,
450 nsIContent
& aNewLeftNode
);
453 * JoinNodes() takes 2 nodes and merge their content|children.
454 * @param aNodeToKeep The node that will remain after the join.
455 * @param aNodeToJoin The node that will be joined with aNodeToKeep.
456 * There is no requirement that the two nodes be of the same type.
457 * @param aParent The parent of aNodeToKeep
459 nsresult
JoinNodesImpl(nsINode
* aNodeToKeep
,
460 nsINode
* aNodeToJoin
,
464 * Return the offset of aChild in aParent. Asserts fatally if parent or
465 * child is null, or parent is not child's parent.
467 static int32_t GetChildOffset(nsIDOMNode
*aChild
,
468 nsIDOMNode
*aParent
);
471 * Set outOffset to the offset of aChild in the parent.
472 * Returns the parent of aChild.
474 static already_AddRefed
<nsIDOMNode
> GetNodeLocation(nsIDOMNode
* aChild
,
476 static nsINode
* GetNodeLocation(nsINode
* aChild
, int32_t* aOffset
);
478 /** returns the number of things inside aNode in the out-param aCount.
479 * @param aNode is the node to get the length of.
480 * If aNode is text, returns number of characters.
481 * If not, returns number of children nodes.
482 * @param aCount [OUT] the result of the above calculation.
484 static nsresult
GetLengthOfDOMNode(nsIDOMNode
*aNode
, uint32_t &aCount
);
486 /** get the node immediately prior to aCurrentNode
487 * @param aCurrentNode the node from which we start the search
488 * @param aEditableNode if true, only return an editable node
489 * @param aResultNode [OUT] the node that occurs before aCurrentNode in the tree,
490 * skipping non-editable nodes if aEditableNode is true.
491 * If there is no prior node, aResultNode will be nullptr.
492 * @param bNoBlockCrossing If true, don't move across "block" nodes, whatever that means.
494 nsIContent
* GetPriorNode(nsINode
* aCurrentNode
, bool aEditableNode
,
495 bool aNoBlockCrossing
= false);
497 // and another version that takes a {parent,offset} pair rather than a node
498 nsIContent
* GetPriorNode(nsINode
* aParentNode
,
501 bool aNoBlockCrossing
= false);
504 /** get the node immediately after to aCurrentNode
505 * @param aCurrentNode the node from which we start the search
506 * @param aEditableNode if true, only return an editable node
507 * @param aResultNode [OUT] the node that occurs after aCurrentNode in the tree,
508 * skipping non-editable nodes if aEditableNode is true.
509 * If there is no prior node, aResultNode will be nullptr.
511 nsIContent
* GetNextNode(nsINode
* aCurrentNode
,
513 bool bNoBlockCrossing
= false);
515 // and another version that takes a {parent,offset} pair rather than a node
516 nsIContent
* GetNextNode(nsINode
* aParentNode
,
519 bool aNoBlockCrossing
= false);
521 // Helper for GetNextNode and GetPriorNode
522 nsIContent
* FindNode(nsINode
*aCurrentNode
,
525 bool bNoBlockCrossing
);
527 * Get the rightmost child of aCurrentNode;
528 * return nullptr if aCurrentNode has no children.
530 nsIContent
* GetRightmostChild(nsINode
*aCurrentNode
,
531 bool bNoBlockCrossing
= false);
534 * Get the leftmost child of aCurrentNode;
535 * return nullptr if aCurrentNode has no children.
537 nsIContent
* GetLeftmostChild(nsINode
*aCurrentNode
,
538 bool bNoBlockCrossing
= false);
540 /** returns true if aNode is of the type implied by aTag */
541 static inline bool NodeIsType(nsIDOMNode
*aNode
, nsIAtom
*aTag
)
543 return GetTag(aNode
) == aTag
;
546 /** returns true if aParent can contain a child of type aTag */
547 bool CanContain(nsINode
& aParent
, nsIContent
& aChild
);
548 bool CanContainTag(nsINode
& aParent
, nsIAtom
& aTag
);
549 bool TagCanContain(nsIAtom
& aParentTag
, nsIContent
& aChild
);
550 virtual bool TagCanContainTag(nsIAtom
& aParentTag
, nsIAtom
& aChildTag
);
552 /** returns true if aNode is our root node */
553 bool IsRoot(nsIDOMNode
* inNode
);
554 bool IsRoot(nsINode
* inNode
);
555 bool IsEditorRoot(nsINode
* aNode
);
557 /** returns true if aNode is a descendant of our root node */
558 bool IsDescendantOfRoot(nsIDOMNode
* inNode
);
559 bool IsDescendantOfRoot(nsINode
* inNode
);
560 bool IsDescendantOfEditorRoot(nsIDOMNode
* aNode
);
561 bool IsDescendantOfEditorRoot(nsINode
* aNode
);
563 /** returns true if aNode is a container */
564 virtual bool IsContainer(nsINode
* aNode
);
565 virtual bool IsContainer(nsIDOMNode
* aNode
);
567 /** returns true if aNode is an editable node */
568 bool IsEditable(nsIDOMNode
*aNode
);
569 virtual bool IsEditable(nsINode
* aNode
);
571 /** returns true if aNode is a MozEditorBogus node */
572 bool IsMozEditorBogusNode(nsINode
* aNode
);
574 /** counts number of editable child nodes */
575 uint32_t CountEditableChildren(nsINode
* aNode
);
577 /** Find the deep first and last children. */
578 nsINode
* GetFirstEditableNode(nsINode
* aRoot
);
581 * Returns current composition.
583 mozilla::TextComposition
* GetComposition() const;
585 * Returns true if there is composition string and not fixed.
587 bool IsIMEComposing() const;
589 * Returns true when inserting text should be a part of current composition.
591 bool ShouldHandleIMEComposition() const;
593 /** from html rules code - migration in progress */
594 static nsresult
GetTagString(nsIDOMNode
*aNode
, nsAString
& outString
);
595 static nsIAtom
*GetTag(nsIDOMNode
*aNode
);
597 bool NodesSameType(nsIDOMNode
*aNode1
, nsIDOMNode
*aNode2
);
598 virtual bool AreNodesSameType(nsIContent
* aNode1
, nsIContent
* aNode2
);
600 static bool IsTextNode(nsIDOMNode
*aNode
);
601 static bool IsTextNode(nsINode
*aNode
);
603 static nsCOMPtr
<nsIDOMNode
> GetChildAt(nsIDOMNode
*aParent
, int32_t aOffset
);
604 static nsCOMPtr
<nsIDOMNode
> GetNodeAtRangeOffsetPoint(nsIDOMNode
* aParentOrNode
, int32_t aOffset
);
606 static nsresult
GetStartNodeAndOffset(mozilla::dom::Selection
* aSelection
,
607 nsIDOMNode
** outStartNode
,
608 int32_t* outStartOffset
);
609 static nsresult
GetStartNodeAndOffset(mozilla::dom::Selection
* aSelection
,
610 nsINode
** aStartNode
,
611 int32_t* aStartOffset
);
612 static nsresult
GetEndNodeAndOffset(mozilla::dom::Selection
* aSelection
,
613 nsIDOMNode
** outEndNode
,
614 int32_t* outEndOffset
);
615 static nsresult
GetEndNodeAndOffset(mozilla::dom::Selection
* aSelection
,
617 int32_t* aEndOffset
);
619 static void DumpNode(nsIDOMNode
*aNode
, int32_t indent
=0);
621 mozilla::dom::Selection
* GetSelection(int16_t aSelectionType
=
622 nsISelectionController::SELECTION_NORMAL
);
624 // Helpers to add a node to the selection.
625 // Used by table cell selection methods
626 nsresult
CreateRange(nsIDOMNode
*aStartParent
, int32_t aStartOffset
,
627 nsIDOMNode
*aEndParent
, int32_t aEndOffset
,
630 // Creates a range with just the supplied node and appends that to the selection
631 nsresult
AppendNodeToSelectionAsRange(nsIDOMNode
*aNode
);
632 // When you are using AppendNodeToSelectionAsRange, call this first to start a new selection
633 nsresult
ClearSelection();
635 nsresult
IsPreformatted(nsIDOMNode
*aNode
, bool *aResult
);
637 enum class EmptyContainers
{ no
, yes
};
638 int32_t SplitNodeDeep(nsIContent
& aNode
, nsIContent
& aSplitPointParent
,
639 int32_t aSplitPointOffset
,
640 EmptyContainers aEmptyContainers
=
641 EmptyContainers::yes
,
642 nsIContent
** outLeftNode
= nullptr,
643 nsIContent
** outRightNode
= nullptr);
644 ::DOMPoint
JoinNodeDeep(nsIContent
& aLeftNode
, nsIContent
& aRightNode
);
646 nsresult
GetString(const nsAString
& name
, nsAString
& value
);
648 void BeginUpdateViewBatch(void);
649 virtual nsresult
EndUpdateViewBatch(void);
651 bool GetShouldTxnSetSelection();
653 virtual nsresult
HandleKeyPressEvent(nsIDOMKeyEvent
* aKeyEvent
);
655 nsresult
HandleInlineSpellCheck(EditAction action
,
656 mozilla::dom::Selection
* aSelection
,
657 nsIDOMNode
*previousSelectedNode
,
658 int32_t previousSelectedOffset
,
659 nsIDOMNode
*aStartNode
,
660 int32_t aStartOffset
,
661 nsIDOMNode
*aEndNode
,
664 virtual already_AddRefed
<mozilla::dom::EventTarget
> GetDOMEventTarget() = 0;
666 // Fast non-refcounting editor root element accessor
667 mozilla::dom::Element
*GetRoot();
669 // Likewise, but gets the editor's root instead, which is different for HTML
671 virtual mozilla::dom::Element
* GetEditorRoot();
673 // Likewise, but gets the text control element instead of the root for
675 mozilla::dom::Element
* GetExposedRoot();
677 // Accessor methods to flags
678 bool IsPlaintextEditor() const
680 return (mFlags
& nsIPlaintextEditor::eEditorPlaintextMask
) != 0;
683 bool IsSingleLineEditor() const
685 return (mFlags
& nsIPlaintextEditor::eEditorSingleLineMask
) != 0;
688 bool IsPasswordEditor() const
690 return (mFlags
& nsIPlaintextEditor::eEditorPasswordMask
) != 0;
693 bool IsReadonly() const
695 return (mFlags
& nsIPlaintextEditor::eEditorReadonlyMask
) != 0;
698 bool IsDisabled() const
700 return (mFlags
& nsIPlaintextEditor::eEditorDisabledMask
) != 0;
703 bool IsInputFiltered() const
705 return (mFlags
& nsIPlaintextEditor::eEditorFilterInputMask
) != 0;
708 bool IsMailEditor() const
710 return (mFlags
& nsIPlaintextEditor::eEditorMailMask
) != 0;
713 bool IsWrapHackEnabled() const
715 return (mFlags
& nsIPlaintextEditor::eEditorEnableWrapHackMask
) != 0;
718 bool IsFormWidget() const
720 return (mFlags
& nsIPlaintextEditor::eEditorWidgetMask
) != 0;
725 return (mFlags
& nsIPlaintextEditor::eEditorNoCSSMask
) != 0;
728 bool IsInteractionAllowed() const
730 return (mFlags
& nsIPlaintextEditor::eEditorAllowInteraction
) != 0;
733 bool DontEchoPassword() const
735 return (mFlags
& nsIPlaintextEditor::eEditorDontEchoPassword
) != 0;
738 bool ShouldSkipSpellCheck() const
740 return (mFlags
& nsIPlaintextEditor::eEditorSkipSpellCheck
) != 0;
743 bool IsTabbable() const
745 return IsSingleLineEditor() || IsPasswordEditor() || IsFormWidget() ||
746 IsInteractionAllowed();
749 bool HasIndependentSelection() const
751 return !!mSelConWeak
;
754 // Get the input event target. This might return null.
755 virtual already_AddRefed
<nsIContent
> GetInputEventTargetContent() = 0;
757 // Get the focused content, if we're focused. Returns null otherwise.
758 virtual already_AddRefed
<nsIContent
> GetFocusedContent();
760 // Get the focused content for the argument of some IMEStateManager's
762 virtual already_AddRefed
<nsIContent
> GetFocusedContentForIME();
764 // Whether the editor is active on the DOM window. Note that when this
765 // returns true but GetFocusedContent() returns null, it means that this editor was
766 // focused when the DOM window was active.
767 virtual bool IsActiveInDOMWindow();
769 // Whether the aEvent should be handled by this editor or not. When this
770 // returns FALSE, The aEvent shouldn't be handled on this editor,
771 // i.e., The aEvent should be handled by another inner editor or ancestor
773 virtual bool IsAcceptableInputEvent(nsIDOMEvent
* aEvent
);
775 // FindSelectionRoot() returns a selection root of this editor when aNode
776 // gets focus. aNode must be a content node or a document node. When the
777 // target isn't a part of this editor, returns nullptr. If this is for
778 // designMode, you should set the document node to aNode except that an
779 // element in the document has focus.
780 virtual already_AddRefed
<nsIContent
> FindSelectionRoot(nsINode
* aNode
);
782 // Initializes selection and caret for the editor. If aEventTarget isn't
783 // a host of the editor, i.e., the editor doesn't get focus, this does
785 nsresult
InitializeSelection(nsIDOMEventTarget
* aFocusEventTarget
);
787 // This method has to be called by nsEditorEventListener::Focus.
788 // All actions that have to be done when the editor is focused needs to be
790 void OnFocus(nsIDOMEventTarget
* aFocusEventTarget
);
792 // Used to insert content from a data transfer into the editable area.
793 // This is called for each item in the data transfer, with the index of
794 // each item passed as aIndex.
795 virtual nsresult
InsertFromDataTransfer(mozilla::dom::DataTransfer
*aDataTransfer
,
797 nsIDOMDocument
*aSourceDoc
,
798 nsIDOMNode
*aDestinationNode
,
800 bool aDoDeleteSelection
) = 0;
802 virtual nsresult
InsertFromDrop(nsIDOMEvent
* aDropEvent
) = 0;
804 virtual already_AddRefed
<nsIDOMNode
> FindUserSelectAllNode(nsIDOMNode
* aNode
) { return nullptr; }
807 * GetIMESelectionStartOffsetIn() returns the start offset of IME selection in
808 * the aTextNode. If there is no IME selection, returns -1.
810 int32_t GetIMESelectionStartOffsetIn(nsINode
* aTextNode
);
813 * FindBetterInsertionPoint() tries to look for better insertion point which
814 * is typically the nearest text node and offset in it.
816 void FindBetterInsertionPoint(nsCOMPtr
<nsINode
>& aNode
,
820 * HideCaret() hides caret with nsCaret::AddForceHide() or may show carent
821 * with nsCaret::RemoveForceHide(). This does NOT set visibility of
822 * nsCaret. Therefore, this is stateless.
824 void HideCaret(bool aHide
);
833 nsCString mContentMIMEType
; // MIME type of the doc we are editing.
835 nsCOMPtr
<nsIInlineSpellChecker
> mInlineSpellChecker
;
837 RefPtr
<nsTransactionManager
> mTxnMgr
;
838 nsCOMPtr
<mozilla::dom::Element
> mRootElement
; // cached root node
839 RefPtr
<mozilla::dom::Text
> mIMETextNode
; // current IME text node
840 nsCOMPtr
<mozilla::dom::EventTarget
> mEventTarget
; // The form field as an event receiver
841 nsCOMPtr
<nsIDOMEventListener
> mEventListener
;
842 nsWeakPtr mSelConWeak
; // weak reference to the nsISelectionController
843 nsWeakPtr mPlaceHolderTxn
; // weak reference to placeholder for begin/end batch purposes
844 nsWeakPtr mDocWeak
; // weak reference to the nsIDOMDocument
845 nsIAtom
*mPlaceHolderName
; // name of placeholder transaction
846 nsSelectionState
*mSelState
; // saved selection state for placeholder txn batching
848 // IME composition this is not null between compositionstart and
850 RefPtr
<mozilla::TextComposition
> mComposition
;
853 // Listens to all low level actions on the doc
854 nsTArray
<mozilla::OwningNonNull
<nsIEditActionListener
>> mActionListeners
;
855 // Just notify once per high level change
856 nsTArray
<mozilla::OwningNonNull
<nsIEditorObserver
>> mEditorObservers
;
857 // Listen to overall doc state (dirty or not, just created, etc)
858 nsTArray
<mozilla::OwningNonNull
<nsIDocumentStateListener
>> mDocStateListeners
;
860 nsSelectionState mSavedSel
; // cached selection for nsAutoSelectionReset
861 nsRangeUpdater mRangeUpdater
; // utility class object for maintaining preserved ranges
863 uint32_t mModCount
; // number of modifications (for undo/redo stack)
864 uint32_t mFlags
; // behavior flags. See nsIPlaintextEditor.idl for the flags we use.
866 int32_t mUpdateCount
;
868 int32_t mPlaceHolderBatch
; // nesting count for batching
869 EditAction mAction
; // the current editor action
871 uint32_t mIMETextOffset
; // offset in text node where IME comp string begins
872 // The Length of the composition string or commit string. If this is length
873 // of commit string, the length is truncated by maxlength attribute.
874 uint32_t mIMETextLength
;
876 EDirection mDirection
; // the current direction of editor action
877 int8_t mDocDirtyState
; // -1 = not initialized
878 uint8_t mSpellcheckCheckboxState
; // a Tristate value
880 bool mShouldTxnSetSelection
; // turn off for conservative selection adjustment by txns
881 bool mDidPreDestroy
; // whether PreDestroy has been called
882 bool mDidPostCreate
; // whether PostCreate has been called
883 bool mDispatchInputEvent
;
884 bool mIsInEditAction
; // true while the instance is handling an edit action
885 bool mHidingCaret
; // whether caret is hidden forcibly.
887 friend bool NSCanUnload(nsISupports
* serviceMgr
);
888 friend class nsAutoTxnsConserveSelection
;
889 friend class nsAutoSelectionReset
;
890 friend class nsAutoRules
;
891 friend class nsRangeUpdater
;