Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
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 "nsAutoPtr.h" // for nsRefPtr
12 #include "nsCOMArray.h" // for nsCOMArray
13 #include "nsCOMPtr.h" // for already_AddRefed, nsCOMPtr
14 #include "nsCycleCollectionParticipant.h"
15 #include "nsEditProperty.h" // for nsEditProperty, etc
16 #include "nsIEditor.h" // for nsIEditor::EDirection, etc
17 #include "nsIEditorIMESupport.h" // for NS_DECL_NSIEDITORIMESUPPORT, etc
18 #include "nsIObserver.h" // for NS_DECL_NSIOBSERVER, etc
19 #include "nsIPhonetic.h" // for NS_DECL_NSIPHONETIC, etc
20 #include "nsIPlaintextEditor.h" // for nsIPlaintextEditor, etc
21 #include "nsISupportsImpl.h" // for nsEditor::Release, etc
22 #include "nsIWeakReferenceUtils.h" // for nsWeakPtr
23 #include "nsLiteralString.h" // for NS_LITERAL_STRING
24 #include "nsSelectionState.h" // for nsRangeUpdater, etc
25 #include "nsString.h" // for nsCString
26 #include "nsWeakReference.h" // for nsSupportsWeakReference
27 #include "nscore.h" // for nsresult, nsAString, etc
29 class AddStyleSheetTxn;
30 class ChangeAttributeTxn;
31 class CreateElementTxn;
32 class DeleteNodeTxn;
33 class DeleteTextTxn;
34 class EditAggregateTxn;
35 class IMETextTxn;
36 class InsertElementTxn;
37 class InsertTextTxn;
38 class JoinElementTxn;
39 class RemoveStyleSheetTxn;
40 class SplitElementTxn;
41 class nsCSSStyleSheet;
42 class nsIAtom;
43 class nsIContent;
44 class nsIDOMCharacterData;
45 class nsIDOMDataTransfer;
46 class nsIDOMDocument;
47 class nsIDOMElement;
48 class nsIDOMEvent;
49 class nsIDOMEventListener;
50 class nsIDOMEventTarget;
51 class nsIDOMKeyEvent;
52 class nsIDOMNode;
53 class nsIDOMRange;
54 class nsIDocument;
55 class nsIDocumentStateListener;
56 class nsIEditActionListener;
57 class nsIEditorObserver;
58 class nsIInlineSpellChecker;
59 class nsINode;
60 class nsIPresShell;
61 class nsISelection;
62 class nsISupports;
63 class nsITransaction;
64 class nsIWidget;
65 class nsRange;
66 class nsString;
67 class nsTransactionManager;
69 namespace mozilla {
70 class TextComposition;
72 namespace dom {
73 class DataTransfer;
74 class Element;
75 class EventTarget;
76 class Selection;
77 } // namespace dom
78 } // namespace mozilla
80 namespace mozilla {
81 namespace widget {
82 struct IMEState;
83 } // namespace widget
84 } // namespace mozilla
86 #define kMOZEditorBogusNodeAttrAtom nsEditProperty::mozEditorBogusNode
87 #define kMOZEditorBogusNodeValue NS_LITERAL_STRING("TRUE")
89 // This is int32_t instead of int16_t because nsIInlineSpellChecker.idl's
90 // spellCheckAfterEditorChange is defined to take it as a long.
91 MOZ_BEGIN_ENUM_CLASS(EditAction, int32_t)
92 ignore = -1,
93 none = 0,
94 undo,
95 redo,
96 insertNode,
97 createNode,
98 deleteNode,
99 splitNode,
100 joinNode,
101 deleteText = 1003,
103 // text commands
104 insertText = 2000,
105 insertIMEText = 2001,
106 deleteSelection = 2002,
107 setTextProperty = 2003,
108 removeTextProperty = 2004,
109 outputText = 2005,
111 // html only action
112 insertBreak = 3000,
113 makeList = 3001,
114 indent = 3002,
115 outdent = 3003,
116 align = 3004,
117 makeBasicBlock = 3005,
118 removeList = 3006,
119 makeDefListItem = 3007,
120 insertElement = 3008,
121 insertQuotation = 3009,
122 htmlPaste = 3012,
123 loadHTML = 3013,
124 resetTextProperties = 3014,
125 setAbsolutePosition = 3015,
126 removeAbsolutePosition = 3016,
127 decreaseZIndex = 3017,
128 increaseZIndex = 3018
129 MOZ_END_ENUM_CLASS(EditAction)
131 inline bool operator!(const EditAction& aOp)
132 {
133 return aOp == EditAction::none;
134 }
136 /** implementation of an editor object. it will be the controller/focal point
137 * for the main editor services. i.e. the GUIManager, publishing, transaction
138 * manager, event interfaces. the idea for the event interfaces is to have them
139 * delegate the actual commands to the editor independent of the XPFE implementation.
140 */
141 class nsEditor : public nsIEditor,
142 public nsIEditorIMESupport,
143 public nsSupportsWeakReference,
144 public nsIObserver,
145 public nsIPhonetic
146 {
147 public:
149 enum IterDirection
150 {
151 kIterForward,
152 kIterBackward
153 };
155 /** The default constructor. This should suffice. the setting of the interfaces is done
156 * after the construction of the editor class.
157 */
158 nsEditor();
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.
161 */
162 virtual ~nsEditor();
164 //Interfaces for addref and release and queryinterface
165 //NOTE: Use NS_DECL_ISUPPORTS_INHERITED in any class inherited from nsEditor
166 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
167 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsEditor,
168 nsIEditor)
170 /* ------------ utility methods -------------- */
171 already_AddRefed<nsIDOMDocument> GetDOMDocument();
172 already_AddRefed<nsIDocument> GetDocument();
173 already_AddRefed<nsIPresShell> GetPresShell();
174 already_AddRefed<nsIWidget> GetWidget();
175 void NotifyEditorObservers();
177 /* ------------ nsIEditor methods -------------- */
178 NS_DECL_NSIEDITOR
180 /* ------------ nsIEditorIMESupport methods -------------- */
181 NS_DECL_NSIEDITORIMESUPPORT
183 /* ------------ nsIObserver methods -------------- */
184 NS_DECL_NSIOBSERVER
186 // nsIPhonetic
187 NS_DECL_NSIPHONETIC
189 public:
191 virtual bool IsModifiableNode(nsINode *aNode);
193 NS_IMETHOD InsertTextImpl(const nsAString& aStringToInsert,
194 nsCOMPtr<nsIDOMNode> *aInOutNode,
195 int32_t *aInOutOffset,
196 nsIDOMDocument *aDoc);
197 nsresult InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
198 nsIDOMCharacterData *aTextNode,
199 int32_t aOffset,
200 bool aSuppressIME = false);
201 NS_IMETHOD DeleteSelectionImpl(EDirection aAction,
202 EStripWrappers aStripWrappers);
203 NS_IMETHOD DeleteSelectionAndCreateNode(const nsAString& aTag,
204 nsIDOMNode ** aNewNode);
206 /* helper routines for node/parent manipulations */
207 nsresult DeleteNode(nsINode* aNode);
208 nsresult ReplaceContainer(nsINode* inNode,
209 mozilla::dom::Element** outNode,
210 const nsAString& aNodeType,
211 const nsAString* aAttribute = nullptr,
212 const nsAString* aValue = nullptr,
213 bool aCloneAttributes = false);
214 nsresult ReplaceContainer(nsIDOMNode *inNode,
215 nsCOMPtr<nsIDOMNode> *outNode,
216 const nsAString &aNodeType,
217 const nsAString *aAttribute = nullptr,
218 const nsAString *aValue = nullptr,
219 bool aCloneAttributes = false);
221 nsresult RemoveContainer(nsINode* aNode);
222 nsresult RemoveContainer(nsIDOMNode *inNode);
223 nsresult InsertContainerAbove(nsIContent* aNode,
224 mozilla::dom::Element** aOutNode,
225 const nsAString& aNodeType,
226 const nsAString* aAttribute = nullptr,
227 const nsAString* aValue = nullptr);
228 nsresult InsertContainerAbove(nsIDOMNode *inNode,
229 nsCOMPtr<nsIDOMNode> *outNode,
230 const nsAString &aNodeType,
231 const nsAString *aAttribute = nullptr,
232 const nsAString *aValue = nullptr);
233 nsresult JoinNodes(nsINode* aNodeToKeep, nsIContent* aNodeToMove);
234 nsresult MoveNode(nsINode* aNode, nsINode* aParent, int32_t aOffset);
235 nsresult MoveNode(nsIDOMNode *aNode, nsIDOMNode *aParent, int32_t aOffset);
237 /* Method to replace certain CreateElementNS() calls.
238 Arguments:
239 nsString& aTag - tag you want
240 nsIContent** aContent - returned Content that was created with above namespace.
241 */
242 nsresult CreateHTMLContent(const nsAString& aTag,
243 mozilla::dom::Element** aContent);
245 // IME event handlers
246 virtual nsresult BeginIMEComposition(mozilla::WidgetCompositionEvent* aEvent);
247 virtual nsresult UpdateIMEComposition(nsIDOMEvent* aDOMTextEvent) = 0;
248 void EndIMEComposition();
250 void SwitchTextDirectionTo(uint32_t aDirection);
252 protected:
253 nsresult DetermineCurrentDirection();
254 void FireInputEvent();
256 /** create a transaction for setting aAttribute to aValue on aElement
257 */
258 NS_IMETHOD CreateTxnForSetAttribute(nsIDOMElement *aElement,
259 const nsAString & aAttribute,
260 const nsAString & aValue,
261 ChangeAttributeTxn ** aTxn);
263 /** create a transaction for removing aAttribute on aElement
264 */
265 NS_IMETHOD CreateTxnForRemoveAttribute(nsIDOMElement *aElement,
266 const nsAString & aAttribute,
267 ChangeAttributeTxn ** aTxn);
269 /** create a transaction for creating a new child node of aParent of type aTag.
270 */
271 NS_IMETHOD CreateTxnForCreateElement(const nsAString & aTag,
272 nsIDOMNode *aParent,
273 int32_t aPosition,
274 CreateElementTxn ** aTxn);
276 /** create a transaction for inserting aNode as a child of aParent.
277 */
278 NS_IMETHOD CreateTxnForInsertElement(nsIDOMNode * aNode,
279 nsIDOMNode * aParent,
280 int32_t aOffset,
281 InsertElementTxn ** aTxn);
283 /** create a transaction for removing aNode from its parent.
284 */
285 nsresult CreateTxnForDeleteNode(nsINode* aNode, DeleteNodeTxn** aTxn);
288 nsresult CreateTxnForDeleteSelection(EDirection aAction,
289 EditAggregateTxn** aTxn,
290 nsINode** aNode,
291 int32_t* aOffset,
292 int32_t* aLength);
294 nsresult CreateTxnForDeleteInsertionPoint(nsRange* aRange,
295 EDirection aAction,
296 EditAggregateTxn* aTxn,
297 nsINode** aNode,
298 int32_t* aOffset,
299 int32_t* aLength);
302 /** create a transaction for inserting aStringToInsert into aTextNode
303 * if aTextNode is null, the string is inserted at the current selection.
304 */
305 NS_IMETHOD CreateTxnForInsertText(const nsAString & aStringToInsert,
306 nsIDOMCharacterData *aTextNode,
307 int32_t aOffset,
308 InsertTextTxn ** aTxn);
310 NS_IMETHOD CreateTxnForIMEText(const nsAString & aStringToInsert,
311 IMETextTxn ** aTxn);
313 /** create a transaction for adding a style sheet
314 */
315 NS_IMETHOD CreateTxnForAddStyleSheet(nsCSSStyleSheet* aSheet, AddStyleSheetTxn* *aTxn);
317 /** create a transaction for removing a style sheet
318 */
319 NS_IMETHOD CreateTxnForRemoveStyleSheet(nsCSSStyleSheet* aSheet, RemoveStyleSheetTxn* *aTxn);
321 NS_IMETHOD DeleteText(nsIDOMCharacterData *aElement,
322 uint32_t aOffset,
323 uint32_t aLength);
325 // NS_IMETHOD DeleteRange(nsIDOMRange *aRange);
327 nsresult CreateTxnForDeleteText(nsIDOMCharacterData* aElement,
328 uint32_t aOffset,
329 uint32_t aLength,
330 DeleteTextTxn** aTxn);
332 nsresult CreateTxnForDeleteCharacter(nsIDOMCharacterData* aData,
333 uint32_t aOffset,
334 EDirection aDirection,
335 DeleteTextTxn** aTxn);
337 NS_IMETHOD CreateTxnForSplitNode(nsIDOMNode *aNode,
338 uint32_t aOffset,
339 SplitElementTxn **aTxn);
341 NS_IMETHOD CreateTxnForJoinNode(nsIDOMNode *aLeftNode,
342 nsIDOMNode *aRightNode,
343 JoinElementTxn **aTxn);
345 /**
346 * This method first deletes the selection, if it's not collapsed. Then if
347 * the selection lies in a CharacterData node, it splits it. If the
348 * selection is at this point collapsed in a CharacterData node, it's
349 * adjusted to be collapsed right before or after the node instead (which is
350 * always possible, since the node was split).
351 */
352 nsresult DeleteSelectionAndPrepareToCreateNode();
355 // called after a transaction is done successfully
356 void DoAfterDoTransaction(nsITransaction *aTxn);
357 // called after a transaction is undone successfully
358 void DoAfterUndoTransaction();
359 // called after a transaction is redone successfully
360 void DoAfterRedoTransaction();
362 typedef enum {
363 eDocumentCreated,
364 eDocumentToBeDestroyed,
365 eDocumentStateChanged
366 } TDocumentListenerNotification;
368 // tell the doc state listeners that the doc state has changed
369 NS_IMETHOD NotifyDocumentListeners(TDocumentListenerNotification aNotificationType);
371 /** make the given selection span the entire document */
372 NS_IMETHOD SelectEntireDocument(nsISelection *aSelection);
374 /** helper method for scrolling the selection into view after
375 * an edit operation. aScrollToAnchor should be true if you
376 * want to scroll to the point where the selection was started.
377 * If false, it attempts to scroll the end of the selection into view.
378 *
379 * Editor methods *should* call this method instead of the versions
380 * in the various selection interfaces, since this version makes sure
381 * that the editor's sync/async settings for reflowing, painting, and
382 * scrolling match.
383 */
384 NS_IMETHOD ScrollSelectionIntoView(bool aScrollToAnchor);
386 // Convenience method; forwards to IsBlockNode(nsINode*).
387 bool IsBlockNode(nsIDOMNode* aNode);
388 // stub. see comment in source.
389 virtual bool IsBlockNode(nsINode* aNode);
391 // helper for GetPriorNode and GetNextNode
392 nsIContent* FindNextLeafNode(nsINode *aCurrentNode,
393 bool aGoForward,
394 bool bNoBlockCrossing);
396 // install the event listeners for the editor
397 virtual nsresult InstallEventListeners();
399 virtual void CreateEventListeners();
401 // unregister and release our event listeners
402 virtual void RemoveEventListeners();
404 /**
405 * Return true if spellchecking should be enabled for this editor.
406 */
407 bool GetDesiredSpellCheckState();
409 bool CanEnableSpellCheck()
410 {
411 // Check for password/readonly/disabled, which are not spellchecked
412 // regardless of DOM. Also, check to see if spell check should be skipped or not.
413 return !IsPasswordEditor() && !IsReadonly() && !IsDisabled() && !ShouldSkipSpellCheck();
414 }
416 /**
417 * EnsureComposition() should be composition event handlers or text event
418 * handler. This tries to get the composition for the event and set it to
419 * mComposition.
420 */
421 void EnsureComposition(mozilla::WidgetGUIEvent* aEvent);
423 public:
425 /** All editor operations which alter the doc should be prefaced
426 * with a call to StartOperation, naming the action and direction */
427 NS_IMETHOD StartOperation(EditAction opID,
428 nsIEditor::EDirection aDirection);
430 /** All editor operations which alter the doc should be followed
431 * with a call to EndOperation */
432 NS_IMETHOD EndOperation();
434 /** routines for managing the preservation of selection across
435 * various editor actions */
436 bool ArePreservingSelection();
437 void PreserveSelectionAcrossActions(mozilla::dom::Selection* aSel);
438 nsresult RestorePreservedSelection(nsISelection *aSel);
439 void StopPreservingSelection();
441 /**
442 * SplitNode() creates a new node identical to an existing node, and split the contents between the two nodes
443 * @param aExistingRightNode the node to split. It will become the new node's next sibling.
444 * @param aOffset the offset of aExistingRightNode's content|children to do the split at
445 * @param aNewLeftNode [OUT] the new node resulting from the split, becomes aExistingRightNode's previous sibling.
446 * @param aParent the parent of aExistingRightNode
447 */
448 nsresult SplitNodeImpl(nsIDOMNode *aExistingRightNode,
449 int32_t aOffset,
450 nsIDOMNode *aNewLeftNode,
451 nsIDOMNode *aParent);
453 /**
454 * JoinNodes() takes 2 nodes and merge their content|children.
455 * @param aNodeToKeep The node that will remain after the join.
456 * @param aNodeToJoin The node that will be joined with aNodeToKeep.
457 * There is no requirement that the two nodes be of the same type.
458 * @param aParent The parent of aNodeToKeep
459 */
460 nsresult JoinNodesImpl(nsINode* aNodeToKeep,
461 nsINode* aNodeToJoin,
462 nsINode* aParent);
464 /**
465 * Return the offset of aChild in aParent. Asserts fatally if parent or
466 * child is null, or parent is not child's parent.
467 */
468 static int32_t GetChildOffset(nsIDOMNode *aChild,
469 nsIDOMNode *aParent);
471 /**
472 * Set outOffset to the offset of aChild in the parent.
473 * Returns the parent of aChild.
474 */
475 static already_AddRefed<nsIDOMNode> GetNodeLocation(nsIDOMNode* aChild,
476 int32_t* outOffset);
477 static nsINode* GetNodeLocation(nsINode* aChild, int32_t* aOffset);
479 /** returns the number of things inside aNode in the out-param aCount.
480 * @param aNode is the node to get the length of.
481 * If aNode is text, returns number of characters.
482 * If not, returns number of children nodes.
483 * @param aCount [OUT] the result of the above calculation.
484 */
485 static nsresult GetLengthOfDOMNode(nsIDOMNode *aNode, uint32_t &aCount);
487 /** get the node immediately prior to aCurrentNode
488 * @param aCurrentNode the node from which we start the search
489 * @param aEditableNode if true, only return an editable node
490 * @param aResultNode [OUT] the node that occurs before aCurrentNode in the tree,
491 * skipping non-editable nodes if aEditableNode is true.
492 * If there is no prior node, aResultNode will be nullptr.
493 * @param bNoBlockCrossing If true, don't move across "block" nodes, whatever that means.
494 */
495 nsresult GetPriorNode(nsIDOMNode *aCurrentNode,
496 bool aEditableNode,
497 nsCOMPtr<nsIDOMNode> *aResultNode,
498 bool bNoBlockCrossing = false);
499 nsIContent* GetPriorNode(nsINode* aCurrentNode, bool aEditableNode,
500 bool aNoBlockCrossing = false);
502 // and another version that takes a {parent,offset} pair rather than a node
503 nsresult GetPriorNode(nsIDOMNode *aParentNode,
504 int32_t aOffset,
505 bool aEditableNode,
506 nsCOMPtr<nsIDOMNode> *aResultNode,
507 bool bNoBlockCrossing = false);
508 nsIContent* GetPriorNode(nsINode* aParentNode,
509 int32_t aOffset,
510 bool aEditableNode,
511 bool aNoBlockCrossing = false);
514 /** get the node immediately after to aCurrentNode
515 * @param aCurrentNode the node from which we start the search
516 * @param aEditableNode if true, only return an editable node
517 * @param aResultNode [OUT] the node that occurs after aCurrentNode in the tree,
518 * skipping non-editable nodes if aEditableNode is true.
519 * If there is no prior node, aResultNode will be nullptr.
520 */
521 nsresult GetNextNode(nsIDOMNode *aCurrentNode,
522 bool aEditableNode,
523 nsCOMPtr<nsIDOMNode> *aResultNode,
524 bool bNoBlockCrossing = false);
525 nsIContent* GetNextNode(nsINode* aCurrentNode,
526 bool aEditableNode,
527 bool bNoBlockCrossing = false);
529 // and another version that takes a {parent,offset} pair rather than a node
530 nsresult GetNextNode(nsIDOMNode *aParentNode,
531 int32_t aOffset,
532 bool aEditableNode,
533 nsCOMPtr<nsIDOMNode> *aResultNode,
534 bool bNoBlockCrossing = false);
535 nsIContent* GetNextNode(nsINode* aParentNode,
536 int32_t aOffset,
537 bool aEditableNode,
538 bool aNoBlockCrossing = false);
540 // Helper for GetNextNode and GetPriorNode
541 nsIContent* FindNode(nsINode *aCurrentNode,
542 bool aGoForward,
543 bool aEditableNode,
544 bool bNoBlockCrossing);
545 /**
546 * Get the rightmost child of aCurrentNode;
547 * return nullptr if aCurrentNode has no children.
548 */
549 nsIDOMNode* GetRightmostChild(nsIDOMNode* aCurrentNode,
550 bool bNoBlockCrossing = false);
551 nsIContent* GetRightmostChild(nsINode *aCurrentNode,
552 bool bNoBlockCrossing = false);
554 /**
555 * Get the leftmost child of aCurrentNode;
556 * return nullptr if aCurrentNode has no children.
557 */
558 nsIDOMNode* GetLeftmostChild(nsIDOMNode* aCurrentNode,
559 bool bNoBlockCrossing = false);
560 nsIContent* GetLeftmostChild(nsINode *aCurrentNode,
561 bool bNoBlockCrossing = false);
563 /** returns true if aNode is of the type implied by aTag */
564 static inline bool NodeIsType(nsIDOMNode *aNode, nsIAtom *aTag)
565 {
566 return GetTag(aNode) == aTag;
567 }
569 /** returns true if aParent can contain a child of type aTag */
570 bool CanContain(nsIDOMNode* aParent, nsIDOMNode* aChild);
571 bool CanContainTag(nsIDOMNode* aParent, nsIAtom* aTag);
572 bool TagCanContain(nsIAtom* aParentTag, nsIDOMNode* aChild);
573 virtual bool TagCanContainTag(nsIAtom* aParentTag, nsIAtom* aChildTag);
575 /** returns true if aNode is our root node */
576 bool IsRoot(nsIDOMNode* inNode);
577 bool IsRoot(nsINode* inNode);
578 bool IsEditorRoot(nsINode* aNode);
580 /** returns true if aNode is a descendant of our root node */
581 bool IsDescendantOfRoot(nsIDOMNode* inNode);
582 bool IsDescendantOfRoot(nsINode* inNode);
583 bool IsDescendantOfEditorRoot(nsIDOMNode* aNode);
584 bool IsDescendantOfEditorRoot(nsINode* aNode);
586 /** returns true if aNode is a container */
587 virtual bool IsContainer(nsIDOMNode *aNode);
589 /** returns true if aNode is an editable node */
590 bool IsEditable(nsIDOMNode *aNode);
591 virtual bool IsEditable(nsIContent *aNode);
593 /** returns true if aNode is a MozEditorBogus node */
594 bool IsMozEditorBogusNode(nsIContent *aNode);
596 /** counts number of editable child nodes */
597 uint32_t CountEditableChildren(nsINode* aNode);
599 /** Find the deep first and last children. */
600 nsINode* GetFirstEditableNode(nsINode* aRoot);
602 /**
603 * Returns current composition.
604 */
605 mozilla::TextComposition* GetComposition() const;
606 /**
607 * Returns true if there is composition string and not fixed.
608 */
609 bool IsIMEComposing() const;
611 /** from html rules code - migration in progress */
612 static nsresult GetTagString(nsIDOMNode *aNode, nsAString& outString);
613 static nsIAtom *GetTag(nsIDOMNode *aNode);
615 bool NodesSameType(nsIDOMNode *aNode1, nsIDOMNode *aNode2);
616 virtual bool AreNodesSameType(nsIContent* aNode1, nsIContent* aNode2);
618 static bool IsTextNode(nsIDOMNode *aNode);
619 static bool IsTextNode(nsINode *aNode);
621 static nsCOMPtr<nsIDOMNode> GetChildAt(nsIDOMNode *aParent, int32_t aOffset);
622 static nsCOMPtr<nsIDOMNode> GetNodeAtRangeOffsetPoint(nsIDOMNode* aParentOrNode, int32_t aOffset);
624 static nsresult GetStartNodeAndOffset(nsISelection *aSelection, nsIDOMNode **outStartNode, int32_t *outStartOffset);
625 static nsresult GetStartNodeAndOffset(mozilla::dom::Selection* aSelection,
626 nsINode** aStartNode,
627 int32_t* aStartOffset);
628 static nsresult GetEndNodeAndOffset(nsISelection *aSelection, nsIDOMNode **outEndNode, int32_t *outEndOffset);
629 static nsresult GetEndNodeAndOffset(mozilla::dom::Selection* aSelection,
630 nsINode** aEndNode,
631 int32_t* aEndOffset);
632 #if DEBUG_JOE
633 static void DumpNode(nsIDOMNode *aNode, int32_t indent=0);
634 #endif
635 mozilla::dom::Selection* GetSelection();
637 // Helpers to add a node to the selection.
638 // Used by table cell selection methods
639 nsresult CreateRange(nsIDOMNode *aStartParent, int32_t aStartOffset,
640 nsIDOMNode *aEndParent, int32_t aEndOffset,
641 nsIDOMRange **aRange);
643 // Creates a range with just the supplied node and appends that to the selection
644 nsresult AppendNodeToSelectionAsRange(nsIDOMNode *aNode);
645 // When you are using AppendNodeToSelectionAsRange, call this first to start a new selection
646 nsresult ClearSelection();
648 nsresult IsPreformatted(nsIDOMNode *aNode, bool *aResult);
650 nsresult SplitNodeDeep(nsIDOMNode *aNode,
651 nsIDOMNode *aSplitPointParent,
652 int32_t aSplitPointOffset,
653 int32_t *outOffset,
654 bool aNoEmptyContainers = false,
655 nsCOMPtr<nsIDOMNode> *outLeftNode = 0,
656 nsCOMPtr<nsIDOMNode> *outRightNode = 0);
657 nsresult JoinNodeDeep(nsIDOMNode *aLeftNode, nsIDOMNode *aRightNode, nsCOMPtr<nsIDOMNode> *aOutJoinNode, int32_t *outOffset);
659 nsresult GetString(const nsAString& name, nsAString& value);
661 void BeginUpdateViewBatch(void);
662 virtual nsresult EndUpdateViewBatch(void);
664 bool GetShouldTxnSetSelection();
666 virtual nsresult HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent);
668 nsresult HandleInlineSpellCheck(EditAction action,
669 nsISelection *aSelection,
670 nsIDOMNode *previousSelectedNode,
671 int32_t previousSelectedOffset,
672 nsIDOMNode *aStartNode,
673 int32_t aStartOffset,
674 nsIDOMNode *aEndNode,
675 int32_t aEndOffset);
677 virtual already_AddRefed<mozilla::dom::EventTarget> GetDOMEventTarget() = 0;
679 // Fast non-refcounting editor root element accessor
680 mozilla::dom::Element *GetRoot();
682 // Likewise, but gets the editor's root instead, which is different for HTML
683 // editors
684 virtual mozilla::dom::Element* GetEditorRoot();
686 // Likewise, but gets the text control element instead of the root for
687 // plaintext editors
688 mozilla::dom::Element* GetExposedRoot();
690 // Accessor methods to flags
691 bool IsPlaintextEditor() const
692 {
693 return (mFlags & nsIPlaintextEditor::eEditorPlaintextMask) != 0;
694 }
696 bool IsSingleLineEditor() const
697 {
698 return (mFlags & nsIPlaintextEditor::eEditorSingleLineMask) != 0;
699 }
701 bool IsPasswordEditor() const
702 {
703 return (mFlags & nsIPlaintextEditor::eEditorPasswordMask) != 0;
704 }
706 bool IsReadonly() const
707 {
708 return (mFlags & nsIPlaintextEditor::eEditorReadonlyMask) != 0;
709 }
711 bool IsDisabled() const
712 {
713 return (mFlags & nsIPlaintextEditor::eEditorDisabledMask) != 0;
714 }
716 bool IsInputFiltered() const
717 {
718 return (mFlags & nsIPlaintextEditor::eEditorFilterInputMask) != 0;
719 }
721 bool IsMailEditor() const
722 {
723 return (mFlags & nsIPlaintextEditor::eEditorMailMask) != 0;
724 }
726 bool IsWrapHackEnabled() const
727 {
728 return (mFlags & nsIPlaintextEditor::eEditorEnableWrapHackMask) != 0;
729 }
731 bool IsFormWidget() const
732 {
733 return (mFlags & nsIPlaintextEditor::eEditorWidgetMask) != 0;
734 }
736 bool NoCSS() const
737 {
738 return (mFlags & nsIPlaintextEditor::eEditorNoCSSMask) != 0;
739 }
741 bool IsInteractionAllowed() const
742 {
743 return (mFlags & nsIPlaintextEditor::eEditorAllowInteraction) != 0;
744 }
746 bool DontEchoPassword() const
747 {
748 return (mFlags & nsIPlaintextEditor::eEditorDontEchoPassword) != 0;
749 }
751 bool ShouldSkipSpellCheck() const
752 {
753 return (mFlags & nsIPlaintextEditor::eEditorSkipSpellCheck) != 0;
754 }
756 bool IsTabbable() const
757 {
758 return IsSingleLineEditor() || IsPasswordEditor() || IsFormWidget() ||
759 IsInteractionAllowed();
760 }
762 bool HasIndependentSelection() const
763 {
764 return !!mSelConWeak;
765 }
767 // Get the input event target. This might return null.
768 virtual already_AddRefed<nsIContent> GetInputEventTargetContent() = 0;
770 // Get the focused content, if we're focused. Returns null otherwise.
771 virtual already_AddRefed<nsIContent> GetFocusedContent();
773 // Get the focused content for the argument of some IMEStateManager's
774 // methods.
775 virtual already_AddRefed<nsIContent> GetFocusedContentForIME();
777 // Whether the editor is active on the DOM window. Note that when this
778 // returns true but GetFocusedContent() returns null, it means that this editor was
779 // focused when the DOM window was active.
780 virtual bool IsActiveInDOMWindow();
782 // Whether the aEvent should be handled by this editor or not. When this
783 // returns FALSE, The aEvent shouldn't be handled on this editor,
784 // i.e., The aEvent should be handled by another inner editor or ancestor
785 // elements.
786 virtual bool IsAcceptableInputEvent(nsIDOMEvent* aEvent);
788 // FindSelectionRoot() returns a selection root of this editor when aNode
789 // gets focus. aNode must be a content node or a document node. When the
790 // target isn't a part of this editor, returns nullptr. If this is for
791 // designMode, you should set the document node to aNode except that an
792 // element in the document has focus.
793 virtual already_AddRefed<nsIContent> FindSelectionRoot(nsINode* aNode);
795 // Initializes selection and caret for the editor. If aEventTarget isn't
796 // a host of the editor, i.e., the editor doesn't get focus, this does
797 // nothing.
798 nsresult InitializeSelection(nsIDOMEventTarget* aFocusEventTarget);
800 // Finalizes selection and caret for the editor.
801 void FinalizeSelection();
803 // This method has to be called by nsEditorEventListener::Focus.
804 // All actions that have to be done when the editor is focused needs to be
805 // added here.
806 void OnFocus(nsIDOMEventTarget* aFocusEventTarget);
808 // Used to insert content from a data transfer into the editable area.
809 // This is called for each item in the data transfer, with the index of
810 // each item passed as aIndex.
811 virtual nsresult InsertFromDataTransfer(mozilla::dom::DataTransfer *aDataTransfer,
812 int32_t aIndex,
813 nsIDOMDocument *aSourceDoc,
814 nsIDOMNode *aDestinationNode,
815 int32_t aDestOffset,
816 bool aDoDeleteSelection) = 0;
818 virtual nsresult InsertFromDrop(nsIDOMEvent* aDropEvent) = 0;
820 virtual already_AddRefed<nsIDOMNode> FindUserSelectAllNode(nsIDOMNode* aNode) { return nullptr; }
822 protected:
823 enum Tristate {
824 eTriUnset,
825 eTriFalse,
826 eTriTrue
827 };
828 // Spellchecking
829 nsCString mContentMIMEType; // MIME type of the doc we are editing.
831 nsCOMPtr<nsIInlineSpellChecker> mInlineSpellChecker;
833 nsRefPtr<nsTransactionManager> mTxnMgr;
834 nsCOMPtr<mozilla::dom::Element> mRootElement; // cached root node
835 nsCOMPtr<nsIDOMCharacterData> mIMETextNode; // current IME text node
836 nsCOMPtr<mozilla::dom::EventTarget> mEventTarget; // The form field as an event receiver
837 nsCOMPtr<nsIDOMEventListener> mEventListener;
838 nsWeakPtr mSelConWeak; // weak reference to the nsISelectionController
839 nsWeakPtr mPlaceHolderTxn; // weak reference to placeholder for begin/end batch purposes
840 nsWeakPtr mDocWeak; // weak reference to the nsIDOMDocument
841 nsIAtom *mPlaceHolderName; // name of placeholder transaction
842 nsSelectionState *mSelState; // saved selection state for placeholder txn batching
843 nsString *mPhonetic;
844 // IME composition this is not null between compositionstart and
845 // compositionend.
846 nsRefPtr<mozilla::TextComposition> mComposition;
848 // various listeners
849 nsCOMArray<nsIEditActionListener> mActionListeners; // listens to all low level actions on the doc
850 nsCOMArray<nsIEditorObserver> mEditorObservers; // just notify once per high level change
851 nsCOMArray<nsIDocumentStateListener> mDocStateListeners;// listen to overall doc state (dirty or not, just created, etc)
853 nsSelectionState mSavedSel; // cached selection for nsAutoSelectionReset
854 nsRangeUpdater mRangeUpdater; // utility class object for maintaining preserved ranges
856 uint32_t mModCount; // number of modifications (for undo/redo stack)
857 uint32_t mFlags; // behavior flags. See nsIPlaintextEditor.idl for the flags we use.
859 int32_t mUpdateCount;
861 int32_t mPlaceHolderBatch; // nesting count for batching
862 EditAction mAction; // the current editor action
864 uint32_t mIMETextOffset; // offset in text node where IME comp string begins
866 EDirection mDirection; // the current direction of editor action
867 int8_t mDocDirtyState; // -1 = not initialized
868 uint8_t mSpellcheckCheckboxState; // a Tristate value
870 bool mShouldTxnSetSelection; // turn off for conservative selection adjustment by txns
871 bool mDidPreDestroy; // whether PreDestroy has been called
872 bool mDidPostCreate; // whether PostCreate has been called
873 bool mDispatchInputEvent;
875 friend bool NSCanUnload(nsISupports* serviceMgr);
876 friend class nsAutoTxnsConserveSelection;
877 friend class nsAutoSelectionReset;
878 friend class nsAutoRules;
879 friend class nsRangeUpdater;
880 };
883 #endif