Bumping gaia.json for 1 gaia revision(s) a=gaia-bump
[gecko.git] / editor / libeditor / nsEditor.h
blobe3b0549f93bd244735cdd8f11c2a0a0f5ab2a3bd
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/TypedEnum.h" // for MOZ_BEGIN_ENUM_CLASS, etc.
11 #include "mozilla/dom/Text.h"
12 #include "nsAutoPtr.h" // for nsRefPtr
13 #include "nsCOMArray.h" // for nsCOMArray
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 "nsISupportsImpl.h" // for nsEditor::Release, etc
23 #include "nsIWeakReferenceUtils.h" // for nsWeakPtr
24 #include "nsLiteralString.h" // for NS_LITERAL_STRING
25 #include "nsSelectionState.h" // for nsRangeUpdater, etc
26 #include "nsString.h" // for nsCString
27 #include "nsWeakReference.h" // for nsSupportsWeakReference
28 #include "nscore.h" // for nsresult, nsAString, etc
30 class AddStyleSheetTxn;
31 class DeleteNodeTxn;
32 class EditAggregateTxn;
33 class JoinElementTxn;
34 class RemoveStyleSheetTxn;
35 class SplitElementTxn;
36 class nsIAtom;
37 class nsIContent;
38 class nsIDOMCharacterData;
39 class nsIDOMDataTransfer;
40 class nsIDOMDocument;
41 class nsIDOMElement;
42 class nsIDOMEvent;
43 class nsIDOMEventListener;
44 class nsIDOMEventTarget;
45 class nsIDOMKeyEvent;
46 class nsIDOMNode;
47 class nsIDOMRange;
48 class nsIDocument;
49 class nsIDocumentStateListener;
50 class nsIEditActionListener;
51 class nsIEditorObserver;
52 class nsIInlineSpellChecker;
53 class nsINode;
54 class nsIPresShell;
55 class nsISelection;
56 class nsISupports;
57 class nsITransaction;
58 class nsIWidget;
59 class nsRange;
60 class nsString;
61 class nsTransactionManager;
63 namespace mozilla {
64 class CSSStyleSheet;
65 class ErrorResult;
66 class TextComposition;
68 namespace dom {
69 class ChangeAttributeTxn;
70 class CreateElementTxn;
71 class DataTransfer;
72 class DeleteTextTxn;
73 class Element;
74 class EventTarget;
75 class IMETextTxn;
76 class InsertTextTxn;
77 class InsertNodeTxn;
78 class Selection;
79 class Text;
80 } // namespace dom
81 } // namespace mozilla
83 namespace mozilla {
84 namespace widget {
85 struct IMEState;
86 } // namespace widget
87 } // namespace mozilla
89 #define kMOZEditorBogusNodeAttrAtom nsGkAtoms::mozeditorbogusnode
90 #define kMOZEditorBogusNodeValue NS_LITERAL_STRING("TRUE")
92 // This is int32_t instead of int16_t because nsIInlineSpellChecker.idl's
93 // spellCheckAfterEditorChange is defined to take it as a long.
94 MOZ_BEGIN_ENUM_CLASS(EditAction, int32_t)
95 ignore = -1,
96 none = 0,
97 undo,
98 redo,
99 insertNode,
100 createNode,
101 deleteNode,
102 splitNode,
103 joinNode,
104 deleteText = 1003,
106 // text commands
107 insertText = 2000,
108 insertIMEText = 2001,
109 deleteSelection = 2002,
110 setTextProperty = 2003,
111 removeTextProperty = 2004,
112 outputText = 2005,
114 // html only action
115 insertBreak = 3000,
116 makeList = 3001,
117 indent = 3002,
118 outdent = 3003,
119 align = 3004,
120 makeBasicBlock = 3005,
121 removeList = 3006,
122 makeDefListItem = 3007,
123 insertElement = 3008,
124 insertQuotation = 3009,
125 htmlPaste = 3012,
126 loadHTML = 3013,
127 resetTextProperties = 3014,
128 setAbsolutePosition = 3015,
129 removeAbsolutePosition = 3016,
130 decreaseZIndex = 3017,
131 increaseZIndex = 3018
132 MOZ_END_ENUM_CLASS(EditAction)
134 inline bool operator!(const EditAction& aOp)
136 return aOp == EditAction::none;
139 /** implementation of an editor object. it will be the controller/focal point
140 * for the main editor services. i.e. the GUIManager, publishing, transaction
141 * manager, event interfaces. the idea for the event interfaces is to have them
142 * delegate the actual commands to the editor independent of the XPFE implementation.
144 class nsEditor : public nsIEditor,
145 public nsIEditorIMESupport,
146 public nsSupportsWeakReference,
147 public nsIObserver,
148 public nsIPhonetic
150 public:
152 enum IterDirection
154 kIterForward,
155 kIterBackward
158 /** The default constructor. This should suffice. the setting of the interfaces is done
159 * after the construction of the editor class.
161 nsEditor();
163 protected:
164 /** The default destructor. This should suffice. Should this be pure virtual
165 * for someone to derive from the nsEditor later? I don't believe so.
167 virtual ~nsEditor();
169 public:
170 //Interfaces for addref and release and queryinterface
171 //NOTE: Use NS_DECL_ISUPPORTS_INHERITED in any class inherited from nsEditor
172 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
173 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsEditor,
174 nsIEditor)
176 /* ------------ utility methods -------------- */
177 already_AddRefed<nsIDOMDocument> GetDOMDocument();
178 already_AddRefed<nsIDocument> GetDocument();
179 already_AddRefed<nsIPresShell> GetPresShell();
180 already_AddRefed<nsIWidget> GetWidget();
181 enum NotificationForEditorObservers
183 eNotifyEditorObserversOfEnd,
184 eNotifyEditorObserversOfBefore,
185 eNotifyEditorObserversOfCancel
187 void NotifyEditorObservers(NotificationForEditorObservers aNotification);
189 /* ------------ nsIEditor methods -------------- */
190 NS_DECL_NSIEDITOR
192 /* ------------ nsIEditorIMESupport methods -------------- */
193 NS_DECL_NSIEDITORIMESUPPORT
195 /* ------------ nsIObserver methods -------------- */
196 NS_DECL_NSIOBSERVER
198 // nsIPhonetic
199 NS_DECL_NSIPHONETIC
201 public:
203 virtual bool IsModifiableNode(nsINode *aNode);
205 NS_IMETHOD InsertTextImpl(const nsAString& aStringToInsert,
206 nsCOMPtr<nsIDOMNode> *aInOutNode,
207 int32_t *aInOutOffset,
208 nsIDOMDocument *aDoc);
209 nsresult InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
210 mozilla::dom::Text& aTextNode,
211 int32_t aOffset,
212 bool aSuppressIME = false);
213 NS_IMETHOD DeleteSelectionImpl(EDirection aAction,
214 EStripWrappers aStripWrappers);
215 NS_IMETHOD DeleteSelectionAndCreateNode(const nsAString& aTag,
216 nsIDOMNode ** aNewNode);
218 /* helper routines for node/parent manipulations */
219 nsresult DeleteNode(nsINode* aNode);
220 nsresult InsertNode(nsIContent& aNode, nsINode& aParent, int32_t aPosition);
221 enum ECloneAttributes { eDontCloneAttributes, eCloneAttributes };
222 already_AddRefed<mozilla::dom::Element> ReplaceContainer(
223 mozilla::dom::Element* aOldContainer,
224 nsIAtom* aNodeType,
225 nsIAtom* aAttribute = nullptr,
226 const nsAString* aValue = nullptr,
227 ECloneAttributes aCloneAttributes = eDontCloneAttributes);
228 void CloneAttributes(mozilla::dom::Element* aDest,
229 mozilla::dom::Element* aSource);
231 nsresult RemoveContainer(nsIContent* aNode);
232 already_AddRefed<mozilla::dom::Element> InsertContainerAbove(
233 nsIContent* aNode,
234 nsIAtom* aNodeType,
235 nsIAtom* aAttribute = nullptr,
236 const nsAString* aValue = nullptr);
237 nsresult JoinNodes(nsINode* aNodeToKeep, nsIContent* aNodeToMove);
238 nsresult MoveNode(nsIContent* aNode, nsINode* aParent, int32_t aOffset);
240 /* Method to replace certain CreateElementNS() calls.
241 Arguments:
242 nsIAtom* aTag - tag you want
244 already_AddRefed<mozilla::dom::Element> CreateHTMLContent(nsIAtom* aTag);
246 // IME event handlers
247 virtual nsresult BeginIMEComposition(mozilla::WidgetCompositionEvent* aEvent);
248 virtual nsresult UpdateIMEComposition(nsIDOMEvent* aDOMTextEvent) = 0;
249 void EndIMEComposition();
251 void SwitchTextDirectionTo(uint32_t aDirection);
253 protected:
254 nsresult DetermineCurrentDirection();
255 void FireInputEvent();
257 /** Create a transaction for setting aAttribute to aValue on aElement. Never
258 * returns null.
260 already_AddRefed<mozilla::dom::ChangeAttributeTxn>
261 CreateTxnForSetAttribute(mozilla::dom::Element& aElement,
262 nsIAtom& aAttribute, const nsAString& aValue);
264 /** Create a transaction for removing aAttribute on aElement. Never returns
265 * null.
267 already_AddRefed<mozilla::dom::ChangeAttributeTxn>
268 CreateTxnForRemoveAttribute(mozilla::dom::Element& aElement,
269 nsIAtom& aAttribute);
271 /** create a transaction for creating a new child node of aParent of type aTag.
273 already_AddRefed<mozilla::dom::CreateElementTxn>
274 CreateTxnForCreateElement(nsIAtom& aTag,
275 nsINode& aParent,
276 int32_t aPosition);
278 already_AddRefed<mozilla::dom::Element> CreateNode(nsIAtom* aTag,
279 nsINode* aParent,
280 int32_t aPosition);
282 /** create a transaction for inserting aNode as a child of aParent.
284 already_AddRefed<mozilla::dom::InsertNodeTxn>
285 CreateTxnForInsertNode(nsIContent& aNode, nsINode& aParent, int32_t aOffset);
287 /** create a transaction for removing aNode from its parent.
289 nsresult CreateTxnForDeleteNode(nsINode* aNode, DeleteNodeTxn** aTxn);
292 nsresult CreateTxnForDeleteSelection(EDirection aAction,
293 EditAggregateTxn** aTxn,
294 nsINode** aNode,
295 int32_t* aOffset,
296 int32_t* aLength);
298 nsresult CreateTxnForDeleteInsertionPoint(nsRange* aRange,
299 EDirection aAction,
300 EditAggregateTxn* aTxn,
301 nsINode** aNode,
302 int32_t* aOffset,
303 int32_t* aLength);
306 /** Create a transaction for inserting aStringToInsert into aTextNode. Never
307 * returns null.
309 already_AddRefed<mozilla::dom::InsertTextTxn>
310 CreateTxnForInsertText(const nsAString& aStringToInsert,
311 mozilla::dom::Text& aTextNode, int32_t aOffset);
313 // Never returns null.
314 already_AddRefed<mozilla::dom::IMETextTxn>
315 CreateTxnForIMEText(const nsAString & aStringToInsert);
317 /** create a transaction for adding a style sheet
319 NS_IMETHOD CreateTxnForAddStyleSheet(mozilla::CSSStyleSheet* aSheet,
320 AddStyleSheetTxn* *aTxn);
322 /** create a transaction for removing a style sheet
324 NS_IMETHOD CreateTxnForRemoveStyleSheet(mozilla::CSSStyleSheet* aSheet,
325 RemoveStyleSheetTxn* *aTxn);
327 nsresult DeleteText(nsGenericDOMDataNode& aElement,
328 uint32_t aOffset, uint32_t aLength);
330 // NS_IMETHOD DeleteRange(nsIDOMRange *aRange);
332 already_AddRefed<mozilla::dom::DeleteTextTxn>
333 CreateTxnForDeleteText(nsGenericDOMDataNode& aElement,
334 uint32_t aOffset, uint32_t aLength);
336 already_AddRefed<mozilla::dom::DeleteTextTxn>
337 CreateTxnForDeleteCharacter(nsGenericDOMDataNode& aData, uint32_t aOffset,
338 EDirection aDirection);
340 NS_IMETHOD CreateTxnForSplitNode(nsIDOMNode *aNode,
341 uint32_t aOffset,
342 SplitElementTxn **aTxn);
344 NS_IMETHOD CreateTxnForJoinNode(nsIDOMNode *aLeftNode,
345 nsIDOMNode *aRightNode,
346 JoinElementTxn **aTxn);
349 * This method first deletes the selection, if it's not collapsed. Then if
350 * the selection lies in a CharacterData node, it splits it. If the
351 * selection is at this point collapsed in a CharacterData node, it's
352 * adjusted to be collapsed right before or after the node instead (which is
353 * always possible, since the node was split).
355 nsresult DeleteSelectionAndPrepareToCreateNode();
358 // called after a transaction is done successfully
359 void DoAfterDoTransaction(nsITransaction *aTxn);
360 // called after a transaction is undone successfully
361 void DoAfterUndoTransaction();
362 // called after a transaction is redone successfully
363 void DoAfterRedoTransaction();
365 typedef enum {
366 eDocumentCreated,
367 eDocumentToBeDestroyed,
368 eDocumentStateChanged
369 } TDocumentListenerNotification;
371 // tell the doc state listeners that the doc state has changed
372 NS_IMETHOD NotifyDocumentListeners(TDocumentListenerNotification aNotificationType);
374 /** make the given selection span the entire document */
375 NS_IMETHOD SelectEntireDocument(nsISelection *aSelection);
377 /** helper method for scrolling the selection into view after
378 * an edit operation. aScrollToAnchor should be true if you
379 * want to scroll to the point where the selection was started.
380 * If false, it attempts to scroll the end of the selection into view.
382 * Editor methods *should* call this method instead of the versions
383 * in the various selection interfaces, since this version makes sure
384 * that the editor's sync/async settings for reflowing, painting, and
385 * scrolling match.
387 NS_IMETHOD ScrollSelectionIntoView(bool aScrollToAnchor);
389 // Convenience method; forwards to IsBlockNode(nsINode*).
390 bool IsBlockNode(nsIDOMNode* aNode);
391 // stub. see comment in source.
392 virtual bool IsBlockNode(nsINode* aNode);
394 // helper for GetPriorNode and GetNextNode
395 nsIContent* FindNextLeafNode(nsINode *aCurrentNode,
396 bool aGoForward,
397 bool bNoBlockCrossing);
399 // install the event listeners for the editor
400 virtual nsresult InstallEventListeners();
402 virtual void CreateEventListeners();
404 // unregister and release our event listeners
405 virtual void RemoveEventListeners();
408 * Return true if spellchecking should be enabled for this editor.
410 bool GetDesiredSpellCheckState();
412 bool CanEnableSpellCheck()
414 // Check for password/readonly/disabled, which are not spellchecked
415 // regardless of DOM. Also, check to see if spell check should be skipped or not.
416 return !IsPasswordEditor() && !IsReadonly() && !IsDisabled() && !ShouldSkipSpellCheck();
420 * EnsureComposition() should be composition event handlers or text event
421 * handler. This tries to get the composition for the event and set it to
422 * mComposition.
424 void EnsureComposition(mozilla::WidgetGUIEvent* aEvent);
426 public:
428 /** All editor operations which alter the doc should be prefaced
429 * with a call to StartOperation, naming the action and direction */
430 NS_IMETHOD StartOperation(EditAction opID,
431 nsIEditor::EDirection aDirection);
433 /** All editor operations which alter the doc should be followed
434 * with a call to EndOperation */
435 NS_IMETHOD EndOperation();
437 /** routines for managing the preservation of selection across
438 * various editor actions */
439 bool ArePreservingSelection();
440 void PreserveSelectionAcrossActions(mozilla::dom::Selection* aSel);
441 nsresult RestorePreservedSelection(nsISelection *aSel);
442 void StopPreservingSelection();
444 /**
445 * SplitNode() creates a new node identical to an existing node, and split the contents between the two nodes
446 * @param aExistingRightNode the node to split. It will become the new node's next sibling.
447 * @param aOffset the offset of aExistingRightNode's content|children to do the split at
448 * @param aNewLeftNode [OUT] the new node resulting from the split, becomes aExistingRightNode's previous sibling.
449 * @param aParent the parent of aExistingRightNode
451 nsresult SplitNodeImpl(nsIDOMNode *aExistingRightNode,
452 int32_t aOffset,
453 nsIDOMNode *aNewLeftNode,
454 nsIDOMNode *aParent);
456 /**
457 * JoinNodes() takes 2 nodes and merge their content|children.
458 * @param aNodeToKeep The node that will remain after the join.
459 * @param aNodeToJoin The node that will be joined with aNodeToKeep.
460 * There is no requirement that the two nodes be of the same type.
461 * @param aParent The parent of aNodeToKeep
463 nsresult JoinNodesImpl(nsINode* aNodeToKeep,
464 nsINode* aNodeToJoin,
465 nsINode* aParent);
468 * Return the offset of aChild in aParent. Asserts fatally if parent or
469 * child is null, or parent is not child's parent.
471 static int32_t GetChildOffset(nsIDOMNode *aChild,
472 nsIDOMNode *aParent);
475 * Set outOffset to the offset of aChild in the parent.
476 * Returns the parent of aChild.
478 static already_AddRefed<nsIDOMNode> GetNodeLocation(nsIDOMNode* aChild,
479 int32_t* outOffset);
480 static nsINode* GetNodeLocation(nsINode* aChild, int32_t* aOffset);
482 /** returns the number of things inside aNode in the out-param aCount.
483 * @param aNode is the node to get the length of.
484 * If aNode is text, returns number of characters.
485 * If not, returns number of children nodes.
486 * @param aCount [OUT] the result of the above calculation.
488 static nsresult GetLengthOfDOMNode(nsIDOMNode *aNode, uint32_t &aCount);
490 /** get the node immediately prior to aCurrentNode
491 * @param aCurrentNode the node from which we start the search
492 * @param aEditableNode if true, only return an editable node
493 * @param aResultNode [OUT] the node that occurs before aCurrentNode in the tree,
494 * skipping non-editable nodes if aEditableNode is true.
495 * If there is no prior node, aResultNode will be nullptr.
496 * @param bNoBlockCrossing If true, don't move across "block" nodes, whatever that means.
498 nsresult GetPriorNode(nsIDOMNode *aCurrentNode,
499 bool aEditableNode,
500 nsCOMPtr<nsIDOMNode> *aResultNode,
501 bool bNoBlockCrossing = false);
502 nsIContent* GetPriorNode(nsINode* aCurrentNode, bool aEditableNode,
503 bool aNoBlockCrossing = false);
505 // and another version that takes a {parent,offset} pair rather than a node
506 nsresult GetPriorNode(nsIDOMNode *aParentNode,
507 int32_t aOffset,
508 bool aEditableNode,
509 nsCOMPtr<nsIDOMNode> *aResultNode,
510 bool bNoBlockCrossing = false);
511 nsIContent* GetPriorNode(nsINode* aParentNode,
512 int32_t aOffset,
513 bool aEditableNode,
514 bool aNoBlockCrossing = false);
517 /** get the node immediately after to aCurrentNode
518 * @param aCurrentNode the node from which we start the search
519 * @param aEditableNode if true, only return an editable node
520 * @param aResultNode [OUT] the node that occurs after aCurrentNode in the tree,
521 * skipping non-editable nodes if aEditableNode is true.
522 * If there is no prior node, aResultNode will be nullptr.
524 nsresult GetNextNode(nsIDOMNode *aCurrentNode,
525 bool aEditableNode,
526 nsCOMPtr<nsIDOMNode> *aResultNode,
527 bool bNoBlockCrossing = false);
528 nsIContent* GetNextNode(nsINode* aCurrentNode,
529 bool aEditableNode,
530 bool bNoBlockCrossing = false);
532 // and another version that takes a {parent,offset} pair rather than a node
533 nsresult GetNextNode(nsIDOMNode *aParentNode,
534 int32_t aOffset,
535 bool aEditableNode,
536 nsCOMPtr<nsIDOMNode> *aResultNode,
537 bool bNoBlockCrossing = false);
538 nsIContent* GetNextNode(nsINode* aParentNode,
539 int32_t aOffset,
540 bool aEditableNode,
541 bool aNoBlockCrossing = false);
543 // Helper for GetNextNode and GetPriorNode
544 nsIContent* FindNode(nsINode *aCurrentNode,
545 bool aGoForward,
546 bool aEditableNode,
547 bool bNoBlockCrossing);
549 * Get the rightmost child of aCurrentNode;
550 * return nullptr if aCurrentNode has no children.
552 nsIDOMNode* GetRightmostChild(nsIDOMNode* aCurrentNode,
553 bool bNoBlockCrossing = false);
554 nsIContent* GetRightmostChild(nsINode *aCurrentNode,
555 bool bNoBlockCrossing = false);
558 * Get the leftmost child of aCurrentNode;
559 * return nullptr if aCurrentNode has no children.
561 nsIDOMNode* GetLeftmostChild(nsIDOMNode* aCurrentNode,
562 bool bNoBlockCrossing = false);
563 nsIContent* GetLeftmostChild(nsINode *aCurrentNode,
564 bool bNoBlockCrossing = false);
566 /** returns true if aNode is of the type implied by aTag */
567 static inline bool NodeIsType(nsIDOMNode *aNode, nsIAtom *aTag)
569 return GetTag(aNode) == aTag;
572 /** returns true if aParent can contain a child of type aTag */
573 bool CanContain(nsIDOMNode* aParent, nsIDOMNode* aChild);
574 bool CanContainTag(nsIDOMNode* aParent, nsIAtom* aTag);
575 bool TagCanContain(nsIAtom* aParentTag, nsIDOMNode* aChild);
576 virtual bool TagCanContainTag(nsIAtom* aParentTag, nsIAtom* aChildTag);
578 /** returns true if aNode is our root node */
579 bool IsRoot(nsIDOMNode* inNode);
580 bool IsRoot(nsINode* inNode);
581 bool IsEditorRoot(nsINode* aNode);
583 /** returns true if aNode is a descendant of our root node */
584 bool IsDescendantOfRoot(nsIDOMNode* inNode);
585 bool IsDescendantOfRoot(nsINode* inNode);
586 bool IsDescendantOfEditorRoot(nsIDOMNode* aNode);
587 bool IsDescendantOfEditorRoot(nsINode* aNode);
589 /** returns true if aNode is a container */
590 virtual bool IsContainer(nsINode* aNode);
591 virtual bool IsContainer(nsIDOMNode* aNode);
593 /** returns true if aNode is an editable node */
594 bool IsEditable(nsIDOMNode *aNode);
595 virtual bool IsEditable(nsINode* aNode);
597 /** returns true if aNode is a MozEditorBogus node */
598 bool IsMozEditorBogusNode(nsINode* aNode);
600 /** counts number of editable child nodes */
601 uint32_t CountEditableChildren(nsINode* aNode);
603 /** Find the deep first and last children. */
604 nsINode* GetFirstEditableNode(nsINode* aRoot);
607 * Returns current composition.
609 mozilla::TextComposition* GetComposition() const;
611 * Returns true if there is composition string and not fixed.
613 bool IsIMEComposing() const;
615 /** from html rules code - migration in progress */
616 static nsresult GetTagString(nsIDOMNode *aNode, nsAString& outString);
617 static nsIAtom *GetTag(nsIDOMNode *aNode);
619 bool NodesSameType(nsIDOMNode *aNode1, nsIDOMNode *aNode2);
620 virtual bool AreNodesSameType(nsIContent* aNode1, nsIContent* aNode2);
622 static bool IsTextNode(nsIDOMNode *aNode);
623 static bool IsTextNode(nsINode *aNode);
625 static nsCOMPtr<nsIDOMNode> GetChildAt(nsIDOMNode *aParent, int32_t aOffset);
626 static nsCOMPtr<nsIDOMNode> GetNodeAtRangeOffsetPoint(nsIDOMNode* aParentOrNode, int32_t aOffset);
628 static nsresult GetStartNodeAndOffset(nsISelection *aSelection, nsIDOMNode **outStartNode, int32_t *outStartOffset);
629 static nsresult GetStartNodeAndOffset(mozilla::dom::Selection* aSelection,
630 nsINode** aStartNode,
631 int32_t* aStartOffset);
632 static nsresult GetEndNodeAndOffset(nsISelection *aSelection, nsIDOMNode **outEndNode, int32_t *outEndOffset);
633 static nsresult GetEndNodeAndOffset(mozilla::dom::Selection* aSelection,
634 nsINode** aEndNode,
635 int32_t* aEndOffset);
636 #if DEBUG_JOE
637 static void DumpNode(nsIDOMNode *aNode, int32_t indent=0);
638 #endif
639 mozilla::dom::Selection* GetSelection();
641 // Helpers to add a node to the selection.
642 // Used by table cell selection methods
643 nsresult CreateRange(nsIDOMNode *aStartParent, int32_t aStartOffset,
644 nsIDOMNode *aEndParent, int32_t aEndOffset,
645 nsIDOMRange **aRange);
647 // Creates a range with just the supplied node and appends that to the selection
648 nsresult AppendNodeToSelectionAsRange(nsIDOMNode *aNode);
649 // When you are using AppendNodeToSelectionAsRange, call this first to start a new selection
650 nsresult ClearSelection();
652 nsresult IsPreformatted(nsIDOMNode *aNode, bool *aResult);
654 nsresult SplitNodeDeep(nsIDOMNode *aNode,
655 nsIDOMNode *aSplitPointParent,
656 int32_t aSplitPointOffset,
657 int32_t *outOffset,
658 bool aNoEmptyContainers = false,
659 nsCOMPtr<nsIDOMNode> *outLeftNode = 0,
660 nsCOMPtr<nsIDOMNode> *outRightNode = 0);
661 nsresult JoinNodeDeep(nsIDOMNode *aLeftNode, nsIDOMNode *aRightNode, nsCOMPtr<nsIDOMNode> *aOutJoinNode, int32_t *outOffset);
663 nsresult GetString(const nsAString& name, nsAString& value);
665 void BeginUpdateViewBatch(void);
666 virtual nsresult EndUpdateViewBatch(void);
668 bool GetShouldTxnSetSelection();
670 virtual nsresult HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent);
672 nsresult HandleInlineSpellCheck(EditAction action,
673 nsISelection *aSelection,
674 nsIDOMNode *previousSelectedNode,
675 int32_t previousSelectedOffset,
676 nsIDOMNode *aStartNode,
677 int32_t aStartOffset,
678 nsIDOMNode *aEndNode,
679 int32_t aEndOffset);
681 virtual already_AddRefed<mozilla::dom::EventTarget> GetDOMEventTarget() = 0;
683 // Fast non-refcounting editor root element accessor
684 mozilla::dom::Element *GetRoot();
686 // Likewise, but gets the editor's root instead, which is different for HTML
687 // editors
688 virtual mozilla::dom::Element* GetEditorRoot();
690 // Likewise, but gets the text control element instead of the root for
691 // plaintext editors
692 mozilla::dom::Element* GetExposedRoot();
694 // Accessor methods to flags
695 bool IsPlaintextEditor() const
697 return (mFlags & nsIPlaintextEditor::eEditorPlaintextMask) != 0;
700 bool IsSingleLineEditor() const
702 return (mFlags & nsIPlaintextEditor::eEditorSingleLineMask) != 0;
705 bool IsPasswordEditor() const
707 return (mFlags & nsIPlaintextEditor::eEditorPasswordMask) != 0;
710 bool IsReadonly() const
712 return (mFlags & nsIPlaintextEditor::eEditorReadonlyMask) != 0;
715 bool IsDisabled() const
717 return (mFlags & nsIPlaintextEditor::eEditorDisabledMask) != 0;
720 bool IsInputFiltered() const
722 return (mFlags & nsIPlaintextEditor::eEditorFilterInputMask) != 0;
725 bool IsMailEditor() const
727 return (mFlags & nsIPlaintextEditor::eEditorMailMask) != 0;
730 bool IsWrapHackEnabled() const
732 return (mFlags & nsIPlaintextEditor::eEditorEnableWrapHackMask) != 0;
735 bool IsFormWidget() const
737 return (mFlags & nsIPlaintextEditor::eEditorWidgetMask) != 0;
740 bool NoCSS() const
742 return (mFlags & nsIPlaintextEditor::eEditorNoCSSMask) != 0;
745 bool IsInteractionAllowed() const
747 return (mFlags & nsIPlaintextEditor::eEditorAllowInteraction) != 0;
750 bool DontEchoPassword() const
752 return (mFlags & nsIPlaintextEditor::eEditorDontEchoPassword) != 0;
755 bool ShouldSkipSpellCheck() const
757 return (mFlags & nsIPlaintextEditor::eEditorSkipSpellCheck) != 0;
760 bool IsTabbable() const
762 return IsSingleLineEditor() || IsPasswordEditor() || IsFormWidget() ||
763 IsInteractionAllowed();
766 bool HasIndependentSelection() const
768 return !!mSelConWeak;
771 // Get the input event target. This might return null.
772 virtual already_AddRefed<nsIContent> GetInputEventTargetContent() = 0;
774 // Get the focused content, if we're focused. Returns null otherwise.
775 virtual already_AddRefed<nsIContent> GetFocusedContent();
777 // Get the focused content for the argument of some IMEStateManager's
778 // methods.
779 virtual already_AddRefed<nsIContent> GetFocusedContentForIME();
781 // Whether the editor is active on the DOM window. Note that when this
782 // returns true but GetFocusedContent() returns null, it means that this editor was
783 // focused when the DOM window was active.
784 virtual bool IsActiveInDOMWindow();
786 // Whether the aEvent should be handled by this editor or not. When this
787 // returns FALSE, The aEvent shouldn't be handled on this editor,
788 // i.e., The aEvent should be handled by another inner editor or ancestor
789 // elements.
790 virtual bool IsAcceptableInputEvent(nsIDOMEvent* aEvent);
792 // FindSelectionRoot() returns a selection root of this editor when aNode
793 // gets focus. aNode must be a content node or a document node. When the
794 // target isn't a part of this editor, returns nullptr. If this is for
795 // designMode, you should set the document node to aNode except that an
796 // element in the document has focus.
797 virtual already_AddRefed<nsIContent> FindSelectionRoot(nsINode* aNode);
799 // Initializes selection and caret for the editor. If aEventTarget isn't
800 // a host of the editor, i.e., the editor doesn't get focus, this does
801 // nothing.
802 nsresult InitializeSelection(nsIDOMEventTarget* aFocusEventTarget);
804 // Finalizes selection and caret for the editor.
805 void FinalizeSelection();
807 // This method has to be called by nsEditorEventListener::Focus.
808 // All actions that have to be done when the editor is focused needs to be
809 // added here.
810 void OnFocus(nsIDOMEventTarget* aFocusEventTarget);
812 // Used to insert content from a data transfer into the editable area.
813 // This is called for each item in the data transfer, with the index of
814 // each item passed as aIndex.
815 virtual nsresult InsertFromDataTransfer(mozilla::dom::DataTransfer *aDataTransfer,
816 int32_t aIndex,
817 nsIDOMDocument *aSourceDoc,
818 nsIDOMNode *aDestinationNode,
819 int32_t aDestOffset,
820 bool aDoDeleteSelection) = 0;
822 virtual nsresult InsertFromDrop(nsIDOMEvent* aDropEvent) = 0;
824 virtual already_AddRefed<nsIDOMNode> FindUserSelectAllNode(nsIDOMNode* aNode) { return nullptr; }
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 nsRefPtr<nsTransactionManager> mTxnMgr;
838 nsCOMPtr<mozilla::dom::Element> mRootElement; // cached root node
839 nsRefPtr<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 nsRefPtr<mozilla::TextComposition> mComposition;
852 // various listeners
853 nsCOMArray<nsIEditActionListener> mActionListeners; // listens to all low level actions on the doc
854 nsCOMArray<nsIEditorObserver> mEditorObservers; // just notify once per high level change
855 nsCOMArray<nsIDocumentStateListener> mDocStateListeners;// listen to overall doc state (dirty or not, just created, etc)
857 nsSelectionState mSavedSel; // cached selection for nsAutoSelectionReset
858 nsRangeUpdater mRangeUpdater; // utility class object for maintaining preserved ranges
860 uint32_t mModCount; // number of modifications (for undo/redo stack)
861 uint32_t mFlags; // behavior flags. See nsIPlaintextEditor.idl for the flags we use.
863 int32_t mUpdateCount;
865 int32_t mPlaceHolderBatch; // nesting count for batching
866 EditAction mAction; // the current editor action
868 uint32_t mIMETextOffset; // offset in text node where IME comp string begins
870 EDirection mDirection; // the current direction of editor action
871 int8_t mDocDirtyState; // -1 = not initialized
872 uint8_t mSpellcheckCheckboxState; // a Tristate value
874 bool mShouldTxnSetSelection; // turn off for conservative selection adjustment by txns
875 bool mDidPreDestroy; // whether PreDestroy has been called
876 bool mDidPostCreate; // whether PostCreate has been called
877 bool mDispatchInputEvent;
878 bool mIsInEditAction; // true while the instance is handling an edit action
880 friend bool NSCanUnload(nsISupports* serviceMgr);
881 friend class nsAutoTxnsConserveSelection;
882 friend class nsAutoSelectionReset;
883 friend class nsAutoRules;
884 friend class nsRangeUpdater;
888 #endif