editor/libeditor/base/nsEditor.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/editor/libeditor/base/nsEditor.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,883 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#ifndef __editor_h__
    1.10 +#define __editor_h__
    1.11 +
    1.12 +#include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc.
    1.13 +#include "mozilla/TypedEnum.h"          // for MOZ_BEGIN_ENUM_CLASS, etc.
    1.14 +#include "nsAutoPtr.h"                  // for nsRefPtr
    1.15 +#include "nsCOMArray.h"                 // for nsCOMArray
    1.16 +#include "nsCOMPtr.h"                   // for already_AddRefed, nsCOMPtr
    1.17 +#include "nsCycleCollectionParticipant.h"
    1.18 +#include "nsEditProperty.h"             // for nsEditProperty, etc
    1.19 +#include "nsIEditor.h"                  // for nsIEditor::EDirection, etc
    1.20 +#include "nsIEditorIMESupport.h"        // for NS_DECL_NSIEDITORIMESUPPORT, etc
    1.21 +#include "nsIObserver.h"                // for NS_DECL_NSIOBSERVER, etc
    1.22 +#include "nsIPhonetic.h"                // for NS_DECL_NSIPHONETIC, etc
    1.23 +#include "nsIPlaintextEditor.h"         // for nsIPlaintextEditor, etc
    1.24 +#include "nsISupportsImpl.h"            // for nsEditor::Release, etc
    1.25 +#include "nsIWeakReferenceUtils.h"      // for nsWeakPtr
    1.26 +#include "nsLiteralString.h"            // for NS_LITERAL_STRING
    1.27 +#include "nsSelectionState.h"           // for nsRangeUpdater, etc
    1.28 +#include "nsString.h"                   // for nsCString
    1.29 +#include "nsWeakReference.h"            // for nsSupportsWeakReference
    1.30 +#include "nscore.h"                     // for nsresult, nsAString, etc
    1.31 +
    1.32 +class AddStyleSheetTxn;
    1.33 +class ChangeAttributeTxn;
    1.34 +class CreateElementTxn;
    1.35 +class DeleteNodeTxn;
    1.36 +class DeleteTextTxn;
    1.37 +class EditAggregateTxn;
    1.38 +class IMETextTxn;
    1.39 +class InsertElementTxn;
    1.40 +class InsertTextTxn;
    1.41 +class JoinElementTxn;
    1.42 +class RemoveStyleSheetTxn;
    1.43 +class SplitElementTxn;
    1.44 +class nsCSSStyleSheet;
    1.45 +class nsIAtom;
    1.46 +class nsIContent;
    1.47 +class nsIDOMCharacterData;
    1.48 +class nsIDOMDataTransfer;
    1.49 +class nsIDOMDocument;
    1.50 +class nsIDOMElement;
    1.51 +class nsIDOMEvent;
    1.52 +class nsIDOMEventListener;
    1.53 +class nsIDOMEventTarget;
    1.54 +class nsIDOMKeyEvent;
    1.55 +class nsIDOMNode;
    1.56 +class nsIDOMRange;
    1.57 +class nsIDocument;
    1.58 +class nsIDocumentStateListener;
    1.59 +class nsIEditActionListener;
    1.60 +class nsIEditorObserver;
    1.61 +class nsIInlineSpellChecker;
    1.62 +class nsINode;
    1.63 +class nsIPresShell;
    1.64 +class nsISelection;
    1.65 +class nsISupports;
    1.66 +class nsITransaction;
    1.67 +class nsIWidget;
    1.68 +class nsRange;
    1.69 +class nsString;
    1.70 +class nsTransactionManager;
    1.71 +
    1.72 +namespace mozilla {
    1.73 +class TextComposition;
    1.74 +
    1.75 +namespace dom {
    1.76 +class DataTransfer;
    1.77 +class Element;
    1.78 +class EventTarget;
    1.79 +class Selection;
    1.80 +}  // namespace dom
    1.81 +}  // namespace mozilla
    1.82 +
    1.83 +namespace mozilla {
    1.84 +namespace widget {
    1.85 +struct IMEState;
    1.86 +} // namespace widget
    1.87 +} // namespace mozilla
    1.88 +
    1.89 +#define kMOZEditorBogusNodeAttrAtom nsEditProperty::mozEditorBogusNode
    1.90 +#define kMOZEditorBogusNodeValue NS_LITERAL_STRING("TRUE")
    1.91 +
    1.92 +// This is int32_t instead of int16_t because nsIInlineSpellChecker.idl's
    1.93 +// spellCheckAfterEditorChange is defined to take it as a long.
    1.94 +MOZ_BEGIN_ENUM_CLASS(EditAction, int32_t)
    1.95 +  ignore = -1,
    1.96 +  none = 0,
    1.97 +  undo,
    1.98 +  redo,
    1.99 +  insertNode,
   1.100 +  createNode,
   1.101 +  deleteNode,
   1.102 +  splitNode,
   1.103 +  joinNode,
   1.104 +  deleteText = 1003,
   1.105 +
   1.106 +  // text commands
   1.107 +  insertText         = 2000,
   1.108 +  insertIMEText      = 2001,
   1.109 +  deleteSelection    = 2002,
   1.110 +  setTextProperty    = 2003,
   1.111 +  removeTextProperty = 2004,
   1.112 +  outputText         = 2005,
   1.113 +
   1.114 +  // html only action
   1.115 +  insertBreak         = 3000,
   1.116 +  makeList            = 3001,
   1.117 +  indent              = 3002,
   1.118 +  outdent             = 3003,
   1.119 +  align               = 3004,
   1.120 +  makeBasicBlock      = 3005,
   1.121 +  removeList          = 3006,
   1.122 +  makeDefListItem     = 3007,
   1.123 +  insertElement       = 3008,
   1.124 +  insertQuotation     = 3009,
   1.125 +  htmlPaste           = 3012,
   1.126 +  loadHTML            = 3013,
   1.127 +  resetTextProperties = 3014,
   1.128 +  setAbsolutePosition = 3015,
   1.129 +  removeAbsolutePosition = 3016,
   1.130 +  decreaseZIndex      = 3017,
   1.131 +  increaseZIndex      = 3018
   1.132 +MOZ_END_ENUM_CLASS(EditAction)
   1.133 +
   1.134 +inline bool operator!(const EditAction& aOp)
   1.135 +{
   1.136 +  return aOp == EditAction::none;
   1.137 +}
   1.138 +
   1.139 +/** implementation of an editor object.  it will be the controller/focal point 
   1.140 + *  for the main editor services. i.e. the GUIManager, publishing, transaction 
   1.141 + *  manager, event interfaces. the idea for the event interfaces is to have them 
   1.142 + *  delegate the actual commands to the editor independent of the XPFE implementation.
   1.143 + */
   1.144 +class nsEditor : public nsIEditor,
   1.145 +                 public nsIEditorIMESupport,
   1.146 +                 public nsSupportsWeakReference,
   1.147 +                 public nsIObserver,
   1.148 +                 public nsIPhonetic
   1.149 +{
   1.150 +public:
   1.151 +
   1.152 +  enum IterDirection
   1.153 +  {
   1.154 +    kIterForward,
   1.155 +    kIterBackward
   1.156 +  };
   1.157 +
   1.158 +  /** The default constructor. This should suffice. the setting of the interfaces is done
   1.159 +   *  after the construction of the editor class.
   1.160 +   */
   1.161 +  nsEditor();
   1.162 +  /** The default destructor. This should suffice. Should this be pure virtual 
   1.163 +   *  for someone to derive from the nsEditor later? I don't believe so.
   1.164 +   */
   1.165 +  virtual ~nsEditor();
   1.166 +
   1.167 +//Interfaces for addref and release and queryinterface
   1.168 +//NOTE: Use   NS_DECL_ISUPPORTS_INHERITED in any class inherited from nsEditor
   1.169 +  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   1.170 +  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsEditor,
   1.171 +                                           nsIEditor)
   1.172 +
   1.173 +  /* ------------ utility methods   -------------- */
   1.174 +  already_AddRefed<nsIDOMDocument> GetDOMDocument();
   1.175 +  already_AddRefed<nsIDocument> GetDocument();
   1.176 +  already_AddRefed<nsIPresShell> GetPresShell();
   1.177 +  already_AddRefed<nsIWidget> GetWidget();
   1.178 +  void NotifyEditorObservers();
   1.179 +
   1.180 +  /* ------------ nsIEditor methods -------------- */
   1.181 +  NS_DECL_NSIEDITOR
   1.182 +
   1.183 +  /* ------------ nsIEditorIMESupport methods -------------- */
   1.184 +  NS_DECL_NSIEDITORIMESUPPORT
   1.185 +
   1.186 +  /* ------------ nsIObserver methods -------------- */
   1.187 +  NS_DECL_NSIOBSERVER
   1.188 +
   1.189 +  // nsIPhonetic
   1.190 +  NS_DECL_NSIPHONETIC
   1.191 +
   1.192 +public:
   1.193 +
   1.194 +  virtual bool IsModifiableNode(nsINode *aNode);
   1.195 +
   1.196 +  NS_IMETHOD InsertTextImpl(const nsAString& aStringToInsert, 
   1.197 +                               nsCOMPtr<nsIDOMNode> *aInOutNode, 
   1.198 +                               int32_t *aInOutOffset,
   1.199 +                               nsIDOMDocument *aDoc);
   1.200 +  nsresult InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert, 
   1.201 +                                      nsIDOMCharacterData *aTextNode, 
   1.202 +                                      int32_t aOffset,
   1.203 +                                      bool aSuppressIME = false);
   1.204 +  NS_IMETHOD DeleteSelectionImpl(EDirection aAction,
   1.205 +                                 EStripWrappers aStripWrappers);
   1.206 +  NS_IMETHOD DeleteSelectionAndCreateNode(const nsAString& aTag,
   1.207 +                                           nsIDOMNode ** aNewNode);
   1.208 +
   1.209 +  /* helper routines for node/parent manipulations */
   1.210 +  nsresult DeleteNode(nsINode* aNode);
   1.211 +  nsresult ReplaceContainer(nsINode* inNode,
   1.212 +                            mozilla::dom::Element** outNode,
   1.213 +                            const nsAString& aNodeType,
   1.214 +                            const nsAString* aAttribute = nullptr,
   1.215 +                            const nsAString* aValue = nullptr,
   1.216 +                            bool aCloneAttributes = false);
   1.217 +  nsresult ReplaceContainer(nsIDOMNode *inNode, 
   1.218 +                            nsCOMPtr<nsIDOMNode> *outNode, 
   1.219 +                            const nsAString &aNodeType,
   1.220 +                            const nsAString *aAttribute = nullptr,
   1.221 +                            const nsAString *aValue = nullptr,
   1.222 +                            bool aCloneAttributes = false);
   1.223 +
   1.224 +  nsresult RemoveContainer(nsINode* aNode);
   1.225 +  nsresult RemoveContainer(nsIDOMNode *inNode);
   1.226 +  nsresult InsertContainerAbove(nsIContent* aNode,
   1.227 +                                mozilla::dom::Element** aOutNode,
   1.228 +                                const nsAString& aNodeType,
   1.229 +                                const nsAString* aAttribute = nullptr,
   1.230 +                                const nsAString* aValue = nullptr);
   1.231 +  nsresult InsertContainerAbove(nsIDOMNode *inNode, 
   1.232 +                                nsCOMPtr<nsIDOMNode> *outNode, 
   1.233 +                                const nsAString &aNodeType,
   1.234 +                                const nsAString *aAttribute = nullptr,
   1.235 +                                const nsAString *aValue = nullptr);
   1.236 +  nsresult JoinNodes(nsINode* aNodeToKeep, nsIContent* aNodeToMove);
   1.237 +  nsresult MoveNode(nsINode* aNode, nsINode* aParent, int32_t aOffset);
   1.238 +  nsresult MoveNode(nsIDOMNode *aNode, nsIDOMNode *aParent, int32_t aOffset);
   1.239 +
   1.240 +  /* Method to replace certain CreateElementNS() calls. 
   1.241 +     Arguments:
   1.242 +      nsString& aTag          - tag you want
   1.243 +      nsIContent** aContent   - returned Content that was created with above namespace.
   1.244 +  */
   1.245 +  nsresult CreateHTMLContent(const nsAString& aTag,
   1.246 +                             mozilla::dom::Element** aContent);
   1.247 +
   1.248 +  // IME event handlers
   1.249 +  virtual nsresult BeginIMEComposition(mozilla::WidgetCompositionEvent* aEvent);
   1.250 +  virtual nsresult UpdateIMEComposition(nsIDOMEvent* aDOMTextEvent) = 0;
   1.251 +  void EndIMEComposition();
   1.252 +
   1.253 +  void SwitchTextDirectionTo(uint32_t aDirection);
   1.254 +
   1.255 +protected:
   1.256 +  nsresult DetermineCurrentDirection();
   1.257 +  void FireInputEvent();
   1.258 +
   1.259 +  /** create a transaction for setting aAttribute to aValue on aElement
   1.260 +    */
   1.261 +  NS_IMETHOD CreateTxnForSetAttribute(nsIDOMElement *aElement, 
   1.262 +                                      const nsAString &  aAttribute, 
   1.263 +                                      const nsAString &  aValue,
   1.264 +                                      ChangeAttributeTxn ** aTxn);
   1.265 +
   1.266 +  /** create a transaction for removing aAttribute on aElement
   1.267 +    */
   1.268 +  NS_IMETHOD CreateTxnForRemoveAttribute(nsIDOMElement *aElement, 
   1.269 +                                         const nsAString &  aAttribute,
   1.270 +                                         ChangeAttributeTxn ** aTxn);
   1.271 +
   1.272 +  /** create a transaction for creating a new child node of aParent of type aTag.
   1.273 +    */
   1.274 +  NS_IMETHOD CreateTxnForCreateElement(const nsAString & aTag,
   1.275 +                                       nsIDOMNode     *aParent,
   1.276 +                                       int32_t         aPosition,
   1.277 +                                       CreateElementTxn ** aTxn);
   1.278 +
   1.279 +  /** create a transaction for inserting aNode as a child of aParent.
   1.280 +    */
   1.281 +  NS_IMETHOD CreateTxnForInsertElement(nsIDOMNode * aNode,
   1.282 +                                       nsIDOMNode * aParent,
   1.283 +                                       int32_t      aOffset,
   1.284 +                                       InsertElementTxn ** aTxn);
   1.285 +
   1.286 +  /** create a transaction for removing aNode from its parent.
   1.287 +    */
   1.288 +  nsresult CreateTxnForDeleteNode(nsINode* aNode, DeleteNodeTxn** aTxn);
   1.289 +
   1.290 +
   1.291 +  nsresult CreateTxnForDeleteSelection(EDirection aAction,
   1.292 +                                       EditAggregateTxn** aTxn,
   1.293 +                                       nsINode** aNode,
   1.294 +                                       int32_t* aOffset,
   1.295 +                                       int32_t* aLength);
   1.296 +
   1.297 +  nsresult CreateTxnForDeleteInsertionPoint(nsRange* aRange, 
   1.298 +                                            EDirection aAction, 
   1.299 +                                            EditAggregateTxn* aTxn,
   1.300 +                                            nsINode** aNode,
   1.301 +                                            int32_t* aOffset,
   1.302 +                                            int32_t* aLength);
   1.303 +
   1.304 +
   1.305 +  /** create a transaction for inserting aStringToInsert into aTextNode
   1.306 +    * if aTextNode is null, the string is inserted at the current selection.
   1.307 +    */
   1.308 +  NS_IMETHOD CreateTxnForInsertText(const nsAString & aStringToInsert,
   1.309 +                                    nsIDOMCharacterData *aTextNode,
   1.310 +                                    int32_t aOffset,
   1.311 +                                    InsertTextTxn ** aTxn);
   1.312 +
   1.313 +  NS_IMETHOD CreateTxnForIMEText(const nsAString & aStringToInsert,
   1.314 +                                 IMETextTxn ** aTxn);
   1.315 +
   1.316 +  /** create a transaction for adding a style sheet
   1.317 +    */
   1.318 +  NS_IMETHOD CreateTxnForAddStyleSheet(nsCSSStyleSheet* aSheet, AddStyleSheetTxn* *aTxn);
   1.319 +
   1.320 +  /** create a transaction for removing a style sheet
   1.321 +    */
   1.322 +  NS_IMETHOD CreateTxnForRemoveStyleSheet(nsCSSStyleSheet* aSheet, RemoveStyleSheetTxn* *aTxn);
   1.323 +  
   1.324 +  NS_IMETHOD DeleteText(nsIDOMCharacterData *aElement,
   1.325 +                        uint32_t             aOffset,
   1.326 +                        uint32_t             aLength);
   1.327 +
   1.328 +//  NS_IMETHOD DeleteRange(nsIDOMRange *aRange);
   1.329 +
   1.330 +  nsresult CreateTxnForDeleteText(nsIDOMCharacterData* aElement,
   1.331 +                                  uint32_t             aOffset,
   1.332 +                                  uint32_t             aLength,
   1.333 +                                  DeleteTextTxn**      aTxn);
   1.334 +
   1.335 +  nsresult CreateTxnForDeleteCharacter(nsIDOMCharacterData* aData,
   1.336 +                                       uint32_t             aOffset,
   1.337 +                                       EDirection           aDirection,
   1.338 +                                       DeleteTextTxn**      aTxn);
   1.339 +	
   1.340 +  NS_IMETHOD CreateTxnForSplitNode(nsIDOMNode *aNode,
   1.341 +                                   uint32_t    aOffset,
   1.342 +                                   SplitElementTxn **aTxn);
   1.343 +
   1.344 +  NS_IMETHOD CreateTxnForJoinNode(nsIDOMNode  *aLeftNode,
   1.345 +                                  nsIDOMNode  *aRightNode,
   1.346 +                                  JoinElementTxn **aTxn);
   1.347 +
   1.348 +  /**
   1.349 +   * This method first deletes the selection, if it's not collapsed.  Then if
   1.350 +   * the selection lies in a CharacterData node, it splits it.  If the
   1.351 +   * selection is at this point collapsed in a CharacterData node, it's
   1.352 +   * adjusted to be collapsed right before or after the node instead (which is
   1.353 +   * always possible, since the node was split).
   1.354 +   */
   1.355 +  nsresult DeleteSelectionAndPrepareToCreateNode();
   1.356 +
   1.357 +
   1.358 +  // called after a transaction is done successfully
   1.359 +  void DoAfterDoTransaction(nsITransaction *aTxn);
   1.360 +  // called after a transaction is undone successfully
   1.361 +  void DoAfterUndoTransaction();
   1.362 +  // called after a transaction is redone successfully
   1.363 +  void DoAfterRedoTransaction();
   1.364 +
   1.365 +  typedef enum {
   1.366 +    eDocumentCreated,
   1.367 +    eDocumentToBeDestroyed,
   1.368 +    eDocumentStateChanged
   1.369 +  } TDocumentListenerNotification;
   1.370 +  
   1.371 +  // tell the doc state listeners that the doc state has changed
   1.372 +  NS_IMETHOD NotifyDocumentListeners(TDocumentListenerNotification aNotificationType);
   1.373 +  
   1.374 +  /** make the given selection span the entire document */
   1.375 +  NS_IMETHOD SelectEntireDocument(nsISelection *aSelection);
   1.376 +
   1.377 +  /** helper method for scrolling the selection into view after
   1.378 +   *  an edit operation. aScrollToAnchor should be true if you
   1.379 +   *  want to scroll to the point where the selection was started.
   1.380 +   *  If false, it attempts to scroll the end of the selection into view.
   1.381 +   *
   1.382 +   *  Editor methods *should* call this method instead of the versions
   1.383 +   *  in the various selection interfaces, since this version makes sure
   1.384 +   *  that the editor's sync/async settings for reflowing, painting, and
   1.385 +   *  scrolling match.
   1.386 +   */
   1.387 +  NS_IMETHOD ScrollSelectionIntoView(bool aScrollToAnchor);
   1.388 +
   1.389 +  // Convenience method; forwards to IsBlockNode(nsINode*).
   1.390 +  bool IsBlockNode(nsIDOMNode* aNode);
   1.391 +  // stub.  see comment in source.                     
   1.392 +  virtual bool IsBlockNode(nsINode* aNode);
   1.393 +  
   1.394 +  // helper for GetPriorNode and GetNextNode
   1.395 +  nsIContent* FindNextLeafNode(nsINode  *aCurrentNode,
   1.396 +                               bool      aGoForward,
   1.397 +                               bool      bNoBlockCrossing);
   1.398 +
   1.399 +  // install the event listeners for the editor 
   1.400 +  virtual nsresult InstallEventListeners();
   1.401 +
   1.402 +  virtual void CreateEventListeners();
   1.403 +
   1.404 +  // unregister and release our event listeners
   1.405 +  virtual void RemoveEventListeners();
   1.406 +
   1.407 +  /**
   1.408 +   * Return true if spellchecking should be enabled for this editor.
   1.409 +   */
   1.410 +  bool GetDesiredSpellCheckState();
   1.411 +
   1.412 +  bool CanEnableSpellCheck()
   1.413 +  {
   1.414 +    // Check for password/readonly/disabled, which are not spellchecked
   1.415 +    // regardless of DOM. Also, check to see if spell check should be skipped or not.
   1.416 +    return !IsPasswordEditor() && !IsReadonly() && !IsDisabled() && !ShouldSkipSpellCheck();
   1.417 +  }
   1.418 +
   1.419 +  /**
   1.420 +   * EnsureComposition() should be composition event handlers or text event
   1.421 +   * handler.  This tries to get the composition for the event and set it to
   1.422 +   * mComposition.
   1.423 +   */
   1.424 +  void EnsureComposition(mozilla::WidgetGUIEvent* aEvent);
   1.425 +
   1.426 +public:
   1.427 +
   1.428 +  /** All editor operations which alter the doc should be prefaced
   1.429 +   *  with a call to StartOperation, naming the action and direction */
   1.430 +  NS_IMETHOD StartOperation(EditAction opID,
   1.431 +                            nsIEditor::EDirection aDirection);
   1.432 +
   1.433 +  /** All editor operations which alter the doc should be followed
   1.434 +   *  with a call to EndOperation */
   1.435 +  NS_IMETHOD EndOperation();
   1.436 +
   1.437 +  /** routines for managing the preservation of selection across 
   1.438 +   *  various editor actions */
   1.439 +  bool     ArePreservingSelection();
   1.440 +  void     PreserveSelectionAcrossActions(mozilla::dom::Selection* aSel);
   1.441 +  nsresult RestorePreservedSelection(nsISelection *aSel);
   1.442 +  void     StopPreservingSelection();
   1.443 +
   1.444 +  /** 
   1.445 +   * SplitNode() creates a new node identical to an existing node, and split the contents between the two nodes
   1.446 +   * @param aExistingRightNode   the node to split.  It will become the new node's next sibling.
   1.447 +   * @param aOffset              the offset of aExistingRightNode's content|children to do the split at
   1.448 +   * @param aNewLeftNode         [OUT] the new node resulting from the split, becomes aExistingRightNode's previous sibling.
   1.449 +   * @param aParent              the parent of aExistingRightNode
   1.450 +   */
   1.451 +  nsresult SplitNodeImpl(nsIDOMNode *aExistingRightNode,
   1.452 +                         int32_t     aOffset,
   1.453 +                         nsIDOMNode *aNewLeftNode,
   1.454 +                         nsIDOMNode *aParent);
   1.455 +
   1.456 +  /** 
   1.457 +   * JoinNodes() takes 2 nodes and merge their content|children.
   1.458 +   * @param aNodeToKeep   The node that will remain after the join.
   1.459 +   * @param aNodeToJoin   The node that will be joined with aNodeToKeep.
   1.460 +   *                      There is no requirement that the two nodes be of the same type.
   1.461 +   * @param aParent       The parent of aNodeToKeep
   1.462 +   */
   1.463 +  nsresult JoinNodesImpl(nsINode* aNodeToKeep,
   1.464 +                         nsINode* aNodeToJoin,
   1.465 +                         nsINode* aParent);
   1.466 +
   1.467 +  /**
   1.468 +   * Return the offset of aChild in aParent.  Asserts fatally if parent or
   1.469 +   * child is null, or parent is not child's parent.
   1.470 +   */
   1.471 +  static int32_t GetChildOffset(nsIDOMNode *aChild,
   1.472 +                                nsIDOMNode *aParent);
   1.473 +
   1.474 +  /**
   1.475 +   *  Set outOffset to the offset of aChild in the parent.
   1.476 +   *  Returns the parent of aChild.
   1.477 +   */
   1.478 +  static already_AddRefed<nsIDOMNode> GetNodeLocation(nsIDOMNode* aChild,
   1.479 +                                                      int32_t* outOffset);
   1.480 +  static nsINode* GetNodeLocation(nsINode* aChild, int32_t* aOffset);
   1.481 +
   1.482 +  /** returns the number of things inside aNode in the out-param aCount.  
   1.483 +    * @param  aNode is the node to get the length of.  
   1.484 +    *         If aNode is text, returns number of characters. 
   1.485 +    *         If not, returns number of children nodes.
   1.486 +    * @param  aCount [OUT] the result of the above calculation.
   1.487 +    */
   1.488 +  static nsresult GetLengthOfDOMNode(nsIDOMNode *aNode, uint32_t &aCount);
   1.489 +
   1.490 +  /** get the node immediately prior to aCurrentNode
   1.491 +    * @param aCurrentNode   the node from which we start the search
   1.492 +    * @param aEditableNode  if true, only return an editable node
   1.493 +    * @param aResultNode    [OUT] the node that occurs before aCurrentNode in the tree,
   1.494 +    *                       skipping non-editable nodes if aEditableNode is true.
   1.495 +    *                       If there is no prior node, aResultNode will be nullptr.
   1.496 +    * @param bNoBlockCrossing If true, don't move across "block" nodes, whatever that means.
   1.497 +    */
   1.498 +  nsresult GetPriorNode(nsIDOMNode  *aCurrentNode, 
   1.499 +                        bool         aEditableNode,
   1.500 +                        nsCOMPtr<nsIDOMNode> *aResultNode,
   1.501 +                        bool         bNoBlockCrossing = false);
   1.502 +  nsIContent* GetPriorNode(nsINode* aCurrentNode, bool aEditableNode,
   1.503 +                           bool aNoBlockCrossing = false);
   1.504 +
   1.505 +  // and another version that takes a {parent,offset} pair rather than a node
   1.506 +  nsresult GetPriorNode(nsIDOMNode  *aParentNode, 
   1.507 +                        int32_t      aOffset, 
   1.508 +                        bool         aEditableNode, 
   1.509 +                        nsCOMPtr<nsIDOMNode> *aResultNode,
   1.510 +                        bool         bNoBlockCrossing = false);
   1.511 +  nsIContent* GetPriorNode(nsINode* aParentNode,
   1.512 +                           int32_t aOffset,
   1.513 +                           bool aEditableNode,
   1.514 +                           bool aNoBlockCrossing = false);
   1.515 +
   1.516 +
   1.517 +  /** get the node immediately after to aCurrentNode
   1.518 +    * @param aCurrentNode   the node from which we start the search
   1.519 +    * @param aEditableNode  if true, only return an editable node
   1.520 +    * @param aResultNode    [OUT] the node that occurs after aCurrentNode in the tree,
   1.521 +    *                       skipping non-editable nodes if aEditableNode is true.
   1.522 +    *                       If there is no prior node, aResultNode will be nullptr.
   1.523 +    */
   1.524 +  nsresult GetNextNode(nsIDOMNode  *aCurrentNode, 
   1.525 +                       bool         aEditableNode,
   1.526 +                       nsCOMPtr<nsIDOMNode> *aResultNode,
   1.527 +                       bool         bNoBlockCrossing = false);
   1.528 +  nsIContent* GetNextNode(nsINode* aCurrentNode,
   1.529 +                          bool aEditableNode,
   1.530 +                          bool bNoBlockCrossing = false);
   1.531 +
   1.532 +  // and another version that takes a {parent,offset} pair rather than a node
   1.533 +  nsresult GetNextNode(nsIDOMNode  *aParentNode, 
   1.534 +                       int32_t      aOffset, 
   1.535 +                       bool         aEditableNode, 
   1.536 +                       nsCOMPtr<nsIDOMNode> *aResultNode,
   1.537 +                       bool         bNoBlockCrossing = false);
   1.538 +  nsIContent* GetNextNode(nsINode* aParentNode,
   1.539 +                          int32_t aOffset,
   1.540 +                          bool aEditableNode,
   1.541 +                          bool aNoBlockCrossing = false);
   1.542 +
   1.543 +  // Helper for GetNextNode and GetPriorNode
   1.544 +  nsIContent* FindNode(nsINode *aCurrentNode,
   1.545 +                       bool     aGoForward,
   1.546 +                       bool     aEditableNode,
   1.547 +                       bool     bNoBlockCrossing);
   1.548 +  /**
   1.549 +   * Get the rightmost child of aCurrentNode;
   1.550 +   * return nullptr if aCurrentNode has no children.
   1.551 +   */
   1.552 +  nsIDOMNode* GetRightmostChild(nsIDOMNode* aCurrentNode,
   1.553 +                                bool bNoBlockCrossing = false);
   1.554 +  nsIContent* GetRightmostChild(nsINode *aCurrentNode,
   1.555 +                                bool     bNoBlockCrossing = false);
   1.556 +
   1.557 +  /**
   1.558 +   * Get the leftmost child of aCurrentNode;
   1.559 +   * return nullptr if aCurrentNode has no children.
   1.560 +   */
   1.561 +  nsIDOMNode* GetLeftmostChild(nsIDOMNode* aCurrentNode,
   1.562 +                               bool bNoBlockCrossing = false);
   1.563 +  nsIContent* GetLeftmostChild(nsINode *aCurrentNode,
   1.564 +                               bool     bNoBlockCrossing = false);
   1.565 +
   1.566 +  /** returns true if aNode is of the type implied by aTag */
   1.567 +  static inline bool NodeIsType(nsIDOMNode *aNode, nsIAtom *aTag)
   1.568 +  {
   1.569 +    return GetTag(aNode) == aTag;
   1.570 +  }
   1.571 +
   1.572 +  /** returns true if aParent can contain a child of type aTag */
   1.573 +  bool CanContain(nsIDOMNode* aParent, nsIDOMNode* aChild);
   1.574 +  bool CanContainTag(nsIDOMNode* aParent, nsIAtom* aTag);
   1.575 +  bool TagCanContain(nsIAtom* aParentTag, nsIDOMNode* aChild);
   1.576 +  virtual bool TagCanContainTag(nsIAtom* aParentTag, nsIAtom* aChildTag);
   1.577 +
   1.578 +  /** returns true if aNode is our root node */
   1.579 +  bool IsRoot(nsIDOMNode* inNode);
   1.580 +  bool IsRoot(nsINode* inNode);
   1.581 +  bool IsEditorRoot(nsINode* aNode);
   1.582 +
   1.583 +  /** returns true if aNode is a descendant of our root node */
   1.584 +  bool IsDescendantOfRoot(nsIDOMNode* inNode);
   1.585 +  bool IsDescendantOfRoot(nsINode* inNode);
   1.586 +  bool IsDescendantOfEditorRoot(nsIDOMNode* aNode);
   1.587 +  bool IsDescendantOfEditorRoot(nsINode* aNode);
   1.588 +
   1.589 +  /** returns true if aNode is a container */
   1.590 +  virtual bool IsContainer(nsIDOMNode *aNode);
   1.591 +
   1.592 +  /** returns true if aNode is an editable node */
   1.593 +  bool IsEditable(nsIDOMNode *aNode);
   1.594 +  virtual bool IsEditable(nsIContent *aNode);
   1.595 +
   1.596 +  /** returns true if aNode is a MozEditorBogus node */
   1.597 +  bool IsMozEditorBogusNode(nsIContent *aNode);
   1.598 +
   1.599 +  /** counts number of editable child nodes */
   1.600 +  uint32_t CountEditableChildren(nsINode* aNode);
   1.601 +  
   1.602 +  /** Find the deep first and last children. */
   1.603 +  nsINode* GetFirstEditableNode(nsINode* aRoot);
   1.604 +
   1.605 +  /**
   1.606 +   * Returns current composition.
   1.607 +   */
   1.608 +  mozilla::TextComposition* GetComposition() const;
   1.609 +  /**
   1.610 +   * Returns true if there is composition string and not fixed.
   1.611 +   */
   1.612 +  bool IsIMEComposing() const;
   1.613 +
   1.614 +  /** from html rules code - migration in progress */
   1.615 +  static nsresult GetTagString(nsIDOMNode *aNode, nsAString& outString);
   1.616 +  static nsIAtom *GetTag(nsIDOMNode *aNode);
   1.617 +
   1.618 +  bool NodesSameType(nsIDOMNode *aNode1, nsIDOMNode *aNode2);
   1.619 +  virtual bool AreNodesSameType(nsIContent* aNode1, nsIContent* aNode2);
   1.620 +
   1.621 +  static bool IsTextNode(nsIDOMNode *aNode);
   1.622 +  static bool IsTextNode(nsINode *aNode);
   1.623 +  
   1.624 +  static nsCOMPtr<nsIDOMNode> GetChildAt(nsIDOMNode *aParent, int32_t aOffset);
   1.625 +  static nsCOMPtr<nsIDOMNode> GetNodeAtRangeOffsetPoint(nsIDOMNode* aParentOrNode, int32_t aOffset);
   1.626 +
   1.627 +  static nsresult GetStartNodeAndOffset(nsISelection *aSelection, nsIDOMNode **outStartNode, int32_t *outStartOffset);
   1.628 +  static nsresult GetStartNodeAndOffset(mozilla::dom::Selection* aSelection,
   1.629 +                                        nsINode** aStartNode,
   1.630 +                                        int32_t* aStartOffset);
   1.631 +  static nsresult GetEndNodeAndOffset(nsISelection *aSelection, nsIDOMNode **outEndNode, int32_t *outEndOffset);
   1.632 +  static nsresult GetEndNodeAndOffset(mozilla::dom::Selection* aSelection,
   1.633 +                                      nsINode** aEndNode,
   1.634 +                                      int32_t* aEndOffset);
   1.635 +#if DEBUG_JOE
   1.636 +  static void DumpNode(nsIDOMNode *aNode, int32_t indent=0);
   1.637 +#endif
   1.638 +  mozilla::dom::Selection* GetSelection();
   1.639 +
   1.640 +  // Helpers to add a node to the selection. 
   1.641 +  // Used by table cell selection methods
   1.642 +  nsresult CreateRange(nsIDOMNode *aStartParent, int32_t aStartOffset,
   1.643 +                       nsIDOMNode *aEndParent, int32_t aEndOffset,
   1.644 +                       nsIDOMRange **aRange);
   1.645 +
   1.646 +  // Creates a range with just the supplied node and appends that to the selection
   1.647 +  nsresult AppendNodeToSelectionAsRange(nsIDOMNode *aNode);
   1.648 +  // When you are using AppendNodeToSelectionAsRange, call this first to start a new selection
   1.649 +  nsresult ClearSelection();
   1.650 +
   1.651 +  nsresult IsPreformatted(nsIDOMNode *aNode, bool *aResult);
   1.652 +
   1.653 +  nsresult SplitNodeDeep(nsIDOMNode *aNode, 
   1.654 +                         nsIDOMNode *aSplitPointParent, 
   1.655 +                         int32_t aSplitPointOffset,
   1.656 +                         int32_t *outOffset,
   1.657 +                         bool    aNoEmptyContainers = false,
   1.658 +                         nsCOMPtr<nsIDOMNode> *outLeftNode = 0,
   1.659 +                         nsCOMPtr<nsIDOMNode> *outRightNode = 0);
   1.660 +  nsresult JoinNodeDeep(nsIDOMNode *aLeftNode, nsIDOMNode *aRightNode, nsCOMPtr<nsIDOMNode> *aOutJoinNode, int32_t *outOffset); 
   1.661 +
   1.662 +  nsresult GetString(const nsAString& name, nsAString& value);
   1.663 +
   1.664 +  void BeginUpdateViewBatch(void);
   1.665 +  virtual nsresult EndUpdateViewBatch(void);
   1.666 +
   1.667 +  bool GetShouldTxnSetSelection();
   1.668 +
   1.669 +  virtual nsresult HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent);
   1.670 +
   1.671 +  nsresult HandleInlineSpellCheck(EditAction action,
   1.672 +                                    nsISelection *aSelection,
   1.673 +                                    nsIDOMNode *previousSelectedNode,
   1.674 +                                    int32_t previousSelectedOffset,
   1.675 +                                    nsIDOMNode *aStartNode,
   1.676 +                                    int32_t aStartOffset,
   1.677 +                                    nsIDOMNode *aEndNode,
   1.678 +                                    int32_t aEndOffset);
   1.679 +
   1.680 +  virtual already_AddRefed<mozilla::dom::EventTarget> GetDOMEventTarget() = 0;
   1.681 +
   1.682 +  // Fast non-refcounting editor root element accessor
   1.683 +  mozilla::dom::Element *GetRoot();
   1.684 +
   1.685 +  // Likewise, but gets the editor's root instead, which is different for HTML
   1.686 +  // editors
   1.687 +  virtual mozilla::dom::Element* GetEditorRoot();
   1.688 +
   1.689 +  // Likewise, but gets the text control element instead of the root for
   1.690 +  // plaintext editors
   1.691 +  mozilla::dom::Element* GetExposedRoot();
   1.692 +
   1.693 +  // Accessor methods to flags
   1.694 +  bool IsPlaintextEditor() const
   1.695 +  {
   1.696 +    return (mFlags & nsIPlaintextEditor::eEditorPlaintextMask) != 0;
   1.697 +  }
   1.698 +
   1.699 +  bool IsSingleLineEditor() const
   1.700 +  {
   1.701 +    return (mFlags & nsIPlaintextEditor::eEditorSingleLineMask) != 0;
   1.702 +  }
   1.703 +
   1.704 +  bool IsPasswordEditor() const
   1.705 +  {
   1.706 +    return (mFlags & nsIPlaintextEditor::eEditorPasswordMask) != 0;
   1.707 +  }
   1.708 +
   1.709 +  bool IsReadonly() const
   1.710 +  {
   1.711 +    return (mFlags & nsIPlaintextEditor::eEditorReadonlyMask) != 0;
   1.712 +  }
   1.713 +
   1.714 +  bool IsDisabled() const
   1.715 +  {
   1.716 +    return (mFlags & nsIPlaintextEditor::eEditorDisabledMask) != 0;
   1.717 +  }
   1.718 +
   1.719 +  bool IsInputFiltered() const
   1.720 +  {
   1.721 +    return (mFlags & nsIPlaintextEditor::eEditorFilterInputMask) != 0;
   1.722 +  }
   1.723 +
   1.724 +  bool IsMailEditor() const
   1.725 +  {
   1.726 +    return (mFlags & nsIPlaintextEditor::eEditorMailMask) != 0;
   1.727 +  }
   1.728 +
   1.729 +  bool IsWrapHackEnabled() const
   1.730 +  {
   1.731 +    return (mFlags & nsIPlaintextEditor::eEditorEnableWrapHackMask) != 0;
   1.732 +  }
   1.733 +
   1.734 +  bool IsFormWidget() const
   1.735 +  {
   1.736 +    return (mFlags & nsIPlaintextEditor::eEditorWidgetMask) != 0;
   1.737 +  }
   1.738 +
   1.739 +  bool NoCSS() const
   1.740 +  {
   1.741 +    return (mFlags & nsIPlaintextEditor::eEditorNoCSSMask) != 0;
   1.742 +  }
   1.743 +
   1.744 +  bool IsInteractionAllowed() const
   1.745 +  {
   1.746 +    return (mFlags & nsIPlaintextEditor::eEditorAllowInteraction) != 0;
   1.747 +  }
   1.748 +
   1.749 +  bool DontEchoPassword() const
   1.750 +  {
   1.751 +    return (mFlags & nsIPlaintextEditor::eEditorDontEchoPassword) != 0;
   1.752 +  }
   1.753 +  
   1.754 +  bool ShouldSkipSpellCheck() const
   1.755 +  {
   1.756 +    return (mFlags & nsIPlaintextEditor::eEditorSkipSpellCheck) != 0;
   1.757 +  }
   1.758 +
   1.759 +  bool IsTabbable() const
   1.760 +  {
   1.761 +    return IsSingleLineEditor() || IsPasswordEditor() || IsFormWidget() ||
   1.762 +           IsInteractionAllowed();
   1.763 +  }
   1.764 +
   1.765 +  bool HasIndependentSelection() const
   1.766 +  {
   1.767 +    return !!mSelConWeak;
   1.768 +  }
   1.769 +
   1.770 +  // Get the input event target. This might return null.
   1.771 +  virtual already_AddRefed<nsIContent> GetInputEventTargetContent() = 0;
   1.772 +
   1.773 +  // Get the focused content, if we're focused.  Returns null otherwise.
   1.774 +  virtual already_AddRefed<nsIContent> GetFocusedContent();
   1.775 +
   1.776 +  // Get the focused content for the argument of some IMEStateManager's
   1.777 +  // methods.
   1.778 +  virtual already_AddRefed<nsIContent> GetFocusedContentForIME();
   1.779 +
   1.780 +  // Whether the editor is active on the DOM window.  Note that when this
   1.781 +  // returns true but GetFocusedContent() returns null, it means that this editor was
   1.782 +  // focused when the DOM window was active.
   1.783 +  virtual bool IsActiveInDOMWindow();
   1.784 +
   1.785 +  // Whether the aEvent should be handled by this editor or not.  When this
   1.786 +  // returns FALSE, The aEvent shouldn't be handled on this editor,
   1.787 +  // i.e., The aEvent should be handled by another inner editor or ancestor
   1.788 +  // elements.
   1.789 +  virtual bool IsAcceptableInputEvent(nsIDOMEvent* aEvent);
   1.790 +
   1.791 +  // FindSelectionRoot() returns a selection root of this editor when aNode
   1.792 +  // gets focus.  aNode must be a content node or a document node.  When the
   1.793 +  // target isn't a part of this editor, returns nullptr.  If this is for
   1.794 +  // designMode, you should set the document node to aNode except that an
   1.795 +  // element in the document has focus.
   1.796 +  virtual already_AddRefed<nsIContent> FindSelectionRoot(nsINode* aNode);
   1.797 +
   1.798 +  // Initializes selection and caret for the editor.  If aEventTarget isn't
   1.799 +  // a host of the editor, i.e., the editor doesn't get focus, this does
   1.800 +  // nothing.
   1.801 +  nsresult InitializeSelection(nsIDOMEventTarget* aFocusEventTarget);
   1.802 +
   1.803 +  // Finalizes selection and caret for the editor.
   1.804 +  void FinalizeSelection();
   1.805 +
   1.806 +  // This method has to be called by nsEditorEventListener::Focus.
   1.807 +  // All actions that have to be done when the editor is focused needs to be
   1.808 +  // added here.
   1.809 +  void OnFocus(nsIDOMEventTarget* aFocusEventTarget);
   1.810 +
   1.811 +  // Used to insert content from a data transfer into the editable area.
   1.812 +  // This is called for each item in the data transfer, with the index of
   1.813 +  // each item passed as aIndex.
   1.814 +  virtual nsresult InsertFromDataTransfer(mozilla::dom::DataTransfer *aDataTransfer,
   1.815 +                                          int32_t aIndex,
   1.816 +                                          nsIDOMDocument *aSourceDoc,
   1.817 +                                          nsIDOMNode *aDestinationNode,
   1.818 +                                          int32_t aDestOffset,
   1.819 +                                          bool aDoDeleteSelection) = 0;
   1.820 +
   1.821 +  virtual nsresult InsertFromDrop(nsIDOMEvent* aDropEvent) = 0;
   1.822 +
   1.823 +  virtual already_AddRefed<nsIDOMNode> FindUserSelectAllNode(nsIDOMNode* aNode) { return nullptr; }
   1.824 +
   1.825 +protected:
   1.826 +  enum Tristate {
   1.827 +    eTriUnset,
   1.828 +    eTriFalse,
   1.829 +    eTriTrue
   1.830 +  };
   1.831 +  // Spellchecking
   1.832 +  nsCString mContentMIMEType;       // MIME type of the doc we are editing.
   1.833 +
   1.834 +  nsCOMPtr<nsIInlineSpellChecker> mInlineSpellChecker;
   1.835 +
   1.836 +  nsRefPtr<nsTransactionManager> mTxnMgr;
   1.837 +  nsCOMPtr<mozilla::dom::Element> mRootElement; // cached root node
   1.838 +  nsCOMPtr<nsIDOMCharacterData>     mIMETextNode;      // current IME text node
   1.839 +  nsCOMPtr<mozilla::dom::EventTarget> mEventTarget; // The form field as an event receiver
   1.840 +  nsCOMPtr<nsIDOMEventListener> mEventListener;
   1.841 +  nsWeakPtr        mSelConWeak;          // weak reference to the nsISelectionController
   1.842 +  nsWeakPtr        mPlaceHolderTxn;      // weak reference to placeholder for begin/end batch purposes
   1.843 +  nsWeakPtr        mDocWeak;             // weak reference to the nsIDOMDocument
   1.844 +  nsIAtom          *mPlaceHolderName;    // name of placeholder transaction
   1.845 +  nsSelectionState *mSelState;           // saved selection state for placeholder txn batching
   1.846 +  nsString         *mPhonetic;
   1.847 +  // IME composition this is not null between compositionstart and
   1.848 +  // compositionend.
   1.849 +  nsRefPtr<mozilla::TextComposition> mComposition;
   1.850 +
   1.851 +  // various listeners
   1.852 +  nsCOMArray<nsIEditActionListener> mActionListeners;  // listens to all low level actions on the doc
   1.853 +  nsCOMArray<nsIEditorObserver> mEditorObservers;  // just notify once per high level change
   1.854 +  nsCOMArray<nsIDocumentStateListener> mDocStateListeners;// listen to overall doc state (dirty or not, just created, etc)
   1.855 +
   1.856 +  nsSelectionState  mSavedSel;           // cached selection for nsAutoSelectionReset
   1.857 +  nsRangeUpdater    mRangeUpdater;       // utility class object for maintaining preserved ranges
   1.858 +
   1.859 +  uint32_t          mModCount;     // number of modifications (for undo/redo stack)
   1.860 +  uint32_t          mFlags;        // behavior flags. See nsIPlaintextEditor.idl for the flags we use.
   1.861 +
   1.862 +  int32_t           mUpdateCount;
   1.863 +
   1.864 +  int32_t           mPlaceHolderBatch;   // nesting count for batching
   1.865 +  EditAction        mAction;             // the current editor action
   1.866 +
   1.867 +  uint32_t          mIMETextOffset;    // offset in text node where IME comp string begins
   1.868 +
   1.869 +  EDirection        mDirection;          // the current direction of editor action
   1.870 +  int8_t            mDocDirtyState;      // -1 = not initialized
   1.871 +  uint8_t           mSpellcheckCheckboxState; // a Tristate value
   1.872 +
   1.873 +  bool mShouldTxnSetSelection;  // turn off for conservative selection adjustment by txns
   1.874 +  bool mDidPreDestroy;    // whether PreDestroy has been called
   1.875 +  bool mDidPostCreate;    // whether PostCreate has been called
   1.876 +  bool mDispatchInputEvent;
   1.877 +
   1.878 +  friend bool NSCanUnload(nsISupports* serviceMgr);
   1.879 +  friend class nsAutoTxnsConserveSelection;
   1.880 +  friend class nsAutoSelectionReset;
   1.881 +  friend class nsAutoRules;
   1.882 +  friend class nsRangeUpdater;
   1.883 +};
   1.884 +
   1.885 +
   1.886 +#endif

mercurial