Bug 1247796. Use keyboardFocusIndicatorColor for ActiveBorder system color keyword...
[gecko.git] / editor / libeditor / nsEditor.h
blobad6b2c75d0b9c38b3a5cdd7712880c160174e7bc
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/. */
6 #ifndef __editor_h__
7 #define __editor_h__
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;
32 class DeleteNodeTxn;
33 class EditAggregateTxn;
34 class RemoveStyleSheetTxn;
35 class nsIAtom;
36 class nsIContent;
37 class nsIDOMDocument;
38 class nsIDOMEvent;
39 class nsIDOMEventListener;
40 class nsIDOMEventTarget;
41 class nsIDOMKeyEvent;
42 class nsIDOMNode;
43 class nsIDocument;
44 class nsIDocumentStateListener;
45 class nsIEditActionListener;
46 class nsIEditorObserver;
47 class nsIInlineSpellChecker;
48 class nsINode;
49 class nsIPresShell;
50 class nsISupports;
51 class nsITransaction;
52 class nsIWidget;
53 class nsRange;
54 class nsString;
55 class nsTransactionManager;
56 struct DOMPoint;
58 namespace mozilla {
59 class ErrorResult;
60 class TextComposition;
62 namespace dom {
63 class ChangeAttributeTxn;
64 class CreateElementTxn;
65 class DataTransfer;
66 class DeleteTextTxn;
67 class Element;
68 class EventTarget;
69 class IMETextTxn;
70 class InsertTextTxn;
71 class InsertNodeTxn;
72 class JoinNodeTxn;
73 class Selection;
74 class SplitNodeTxn;
75 class Text;
76 } // namespace dom
77 } // namespace mozilla
79 namespace mozilla {
80 namespace widget {
81 struct IMEState;
82 } // namespace widget
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 {
91 ignore = -1,
92 none = 0,
93 undo,
94 redo,
95 insertNode,
96 createNode,
97 deleteNode,
98 splitNode,
99 joinNode,
100 deleteText = 1003,
102 // text commands
103 insertText = 2000,
104 insertIMEText = 2001,
105 deleteSelection = 2002,
106 setTextProperty = 2003,
107 removeTextProperty = 2004,
108 outputText = 2005,
110 // html only action
111 insertBreak = 3000,
112 makeList = 3001,
113 indent = 3002,
114 outdent = 3003,
115 align = 3004,
116 makeBasicBlock = 3005,
117 removeList = 3006,
118 makeDefListItem = 3007,
119 insertElement = 3008,
120 insertQuotation = 3009,
121 htmlPaste = 3012,
122 loadHTML = 3013,
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,
143 public nsIPhonetic
145 public:
147 enum IterDirection
149 kIterForward,
150 kIterBackward
153 /** The default constructor. This should suffice. the setting of the interfaces is done
154 * after the construction of the editor class.
156 nsEditor();
158 protected:
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.
162 virtual ~nsEditor();
164 public:
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,
169 nsIEditor)
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 -------------- */
185 NS_DECL_NSIEDITOR
187 /* ------------ nsIEditorIMESupport methods -------------- */
188 NS_DECL_NSIEDITORIMESUPPORT
190 // nsIPhonetic
191 NS_DECL_NSIPHONETIC
193 public:
195 virtual bool IsModifiableNode(nsINode *aNode);
197 virtual nsresult InsertTextImpl(const nsAString& aStringToInsert,
198 nsCOMPtr<nsINode>* aInOutNode,
199 int32_t* aInOutOffset,
200 nsIDocument* aDoc);
201 nsresult InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
202 mozilla::dom::Text& aTextNode,
203 int32_t aOffset,
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,
217 nsIAtom* aNodeType,
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(
226 nsIContent* aNode,
227 nsIAtom* aNodeType,
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.
236 Arguments:
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);
248 protected:
249 nsresult DetermineCurrentDirection();
250 void FireInputEvent();
252 /** Create a transaction for setting aAttribute to aValue on aElement. Never
253 * returns null.
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
260 * null.
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,
270 nsINode& aParent,
271 int32_t aPosition);
273 already_AddRefed<mozilla::dom::Element> CreateNode(nsIAtom* aTag,
274 nsINode* aParent,
275 int32_t aPosition);
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,
289 nsINode** aNode,
290 int32_t* aOffset,
291 int32_t* aLength);
293 nsresult CreateTxnForDeleteInsertionPoint(nsRange* aRange,
294 EDirection aAction,
295 EditAggregateTxn* aTxn,
296 nsINode** aNode,
297 int32_t* aOffset,
298 int32_t* aLength);
301 /** Create a transaction for inserting aStringToInsert into aTextNode. Never
302 * returns null.
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();
358 typedef enum {
359 eDocumentCreated,
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
378 * scrolling match.
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,
389 bool aGoForward,
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);
420 public:
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,
449 int32_t aOffset,
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,
461 nsINode* aParent);
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,
475 int32_t* outOffset);
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,
499 int32_t aOffset,
500 bool aEditableNode,
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,
512 bool aEditableNode,
513 bool bNoBlockCrossing = false);
515 // and another version that takes a {parent,offset} pair rather than a node
516 nsIContent* GetNextNode(nsINode* aParentNode,
517 int32_t aOffset,
518 bool aEditableNode,
519 bool aNoBlockCrossing = false);
521 // Helper for GetNextNode and GetPriorNode
522 nsIContent* FindNode(nsINode *aCurrentNode,
523 bool aGoForward,
524 bool aEditableNode,
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,
616 nsINode** aEndNode,
617 int32_t* aEndOffset);
618 #if DEBUG_JOE
619 static void DumpNode(nsIDOMNode *aNode, int32_t indent=0);
620 #endif
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,
628 nsRange** aRange);
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,
662 int32_t aEndOffset);
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
670 // editors
671 virtual mozilla::dom::Element* GetEditorRoot();
673 // Likewise, but gets the text control element instead of the root for
674 // plaintext editors
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;
723 bool NoCSS() const
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
761 // methods.
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
772 // elements.
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
784 // nothing.
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
789 // added here.
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,
796 int32_t aIndex,
797 nsIDOMDocument *aSourceDoc,
798 nsIDOMNode *aDestinationNode,
799 int32_t aDestOffset,
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,
817 int32_t& aOffset);
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);
826 protected:
827 enum Tristate {
828 eTriUnset,
829 eTriFalse,
830 eTriTrue
832 // Spellchecking
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
847 nsString *mPhonetic;
848 // IME composition this is not null between compositionstart and
849 // compositionend.
850 RefPtr<mozilla::TextComposition> mComposition;
852 // various listeners
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;
895 #endif