LCOV - code coverage report
Current view: top level - editor/libeditor - EditorBase.h (source / functions) Hit Total Coverage
Test: output.info Lines: 39 145 26.9 %
Date: 2018-08-07 16:35:00 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       5             : 
       6             : #ifndef mozilla_EditorBase_h
       7             : #define mozilla_EditorBase_h
       8             : 
       9             : #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc.
      10             : #include "mozilla/EditorDOMPoint.h"     // for EditorDOMPoint
      11             : #include "mozilla/Maybe.h"              // for Maybe
      12             : #include "mozilla/OwningNonNull.h"      // for OwningNonNull
      13             : #include "mozilla/PresShell.h"          // for PresShell
      14             : #include "mozilla/RangeBoundary.h"      // for RawRangeBoundary, RangeBoundary
      15             : #include "mozilla/SelectionState.h"     // for RangeUpdater, etc.
      16             : #include "mozilla/StyleSheet.h"         // for StyleSheet
      17             : #include "mozilla/TransactionManager.h" // for TransactionManager
      18             : #include "mozilla/WeakPtr.h"            // for WeakPtr
      19             : #include "mozilla/dom/Selection.h"
      20             : #include "mozilla/dom/Text.h"
      21             : #include "nsCOMPtr.h"                   // for already_AddRefed, nsCOMPtr
      22             : #include "nsCycleCollectionParticipant.h"
      23             : #include "nsGkAtoms.h"
      24             : #include "nsIDocument.h"                // for nsIDocument
      25             : #include "nsIContentInlines.h"          // for nsINode::IsEditable()
      26             : #include "nsIEditor.h"                  // for nsIEditor, etc.
      27             : #include "nsIObserver.h"                // for NS_DECL_NSIOBSERVER, etc.
      28             : #include "nsIPlaintextEditor.h"         // for nsIPlaintextEditor, etc.
      29             : #include "nsISelectionController.h"     // for nsISelectionController constants
      30             : #include "nsISelectionListener.h"       // for nsISelectionListener
      31             : #include "nsISupportsImpl.h"            // for EditorBase::Release, etc.
      32             : #include "nsIWeakReferenceUtils.h"      // for nsWeakPtr
      33             : #include "nsLiteralString.h"            // for NS_LITERAL_STRING
      34             : #include "nsString.h"                   // for nsCString
      35             : #include "nsTArray.h"                   // for nsTArray and nsAutoTArray
      36             : #include "nsWeakReference.h"            // for nsSupportsWeakReference
      37             : #include "nscore.h"                     // for nsresult, nsAString, etc.
      38             : 
      39             : class mozInlineSpellChecker;
      40             : class nsAtom;
      41             : class nsIContent;
      42             : class nsIDocumentStateListener;
      43             : class nsIEditActionListener;
      44             : class nsIEditorObserver;
      45             : class nsINode;
      46             : class nsIPresShell;
      47             : class nsISupports;
      48             : class nsITransaction;
      49             : class nsITransactionListener;
      50             : class nsIWidget;
      51             : class nsRange;
      52             : 
      53             : namespace mozilla {
      54             : class AddStyleSheetTransaction;
      55             : class AutoSelectionRestorer;
      56             : class AutoTopLevelEditSubActionNotifier;
      57             : class AutoTransactionsConserveSelection;
      58             : class AutoUpdateViewBatch;
      59             : class ChangeAttributeTransaction;
      60             : class CompositionTransaction;
      61             : class CreateElementTransaction;
      62             : class CSSEditUtils;
      63             : class DeleteNodeTransaction;
      64             : class DeleteTextTransaction;
      65             : class EditAggregateTransaction;
      66             : class EditorEventListener;
      67             : class EditTransactionBase;
      68             : class ErrorResult;
      69             : class HTMLEditor;
      70             : class HTMLEditUtils;
      71             : class IMEContentObserver;
      72             : class InsertNodeTransaction;
      73             : class InsertTextTransaction;
      74             : class JoinNodeTransaction;
      75             : class PlaceholderTransaction;
      76             : class RemoveStyleSheetTransaction;
      77             : class SplitNodeResult;
      78             : class SplitNodeTransaction;
      79             : class TextComposition;
      80             : class TextEditor;
      81             : class TextEditRules;
      82             : class TextInputListener;
      83             : class TextServicesDocument;
      84             : class TypeInState;
      85             : class WSRunObject;
      86             : enum class EditSubAction : int32_t;
      87             : 
      88             : namespace dom {
      89             : class DataTransfer;
      90             : class DragEvent;
      91             : class Element;
      92             : class EventTarget;
      93             : class Text;
      94             : } // namespace dom
      95             : 
      96             : namespace widget {
      97             : struct IMEState;
      98             : } // namespace widget
      99             : 
     100             : /**
     101             :  * CachedWeakPtr stores a pointer to a class which inherits nsIWeakReference.
     102             :  * If the instance of the class has already been destroyed, this returns
     103             :  * nullptr.  Otherwise, returns cached pointer.
     104             :  * If class T inherits nsISupports a lot, specify Base explicitly for avoiding
     105             :  * ambiguous conversion to nsISupports.
     106             :  */
     107             : template<class T, class Base = nsISupports>
     108           0 : class CachedWeakPtr final
     109             : {
     110             : public:
     111             :   CachedWeakPtr<T, Base>()
     112             :     : mCache(nullptr)
     113             :   {
     114             :   }
     115           0 :   explicit CachedWeakPtr<T, Base>(T* aObject)
     116           0 :   {
     117           0 :     mWeakPtr = do_GetWeakReference(static_cast<Base*>(aObject));
     118           0 :     mCache = aObject;
     119           0 :   }
     120             :   explicit CachedWeakPtr<T, Base>(const nsCOMPtr<T>& aOther)
     121             :   {
     122             :     mWeakPtr = do_GetWeakReference(static_cast<Base*>(aOther.get()));
     123             :     mCache = aOther;
     124             :   }
     125             :   explicit CachedWeakPtr<T, Base>(already_AddRefed<T>& aOther)
     126             :   {
     127             :     RefPtr<T> other = aOther;
     128             :     mWeakPtr = do_GetWeakReference(static_cast<Base*>(other.get()));
     129             :     mCache = other;
     130             :   }
     131             : 
     132             :   CachedWeakPtr<T, Base>& operator=(T* aObject)
     133             :   {
     134             :     mWeakPtr = do_GetWeakReference(static_cast<Base*>(aObject));
     135             :     mCache = aObject;
     136             :     return *this;
     137             :   }
     138             :   CachedWeakPtr<T, Base>& operator=(const nsCOMPtr<T>& aOther)
     139             :   {
     140             :     mWeakPtr = do_GetWeakReference(static_cast<Base*>(aOther.get()));
     141             :     mCache = aOther;
     142             :     return *this;
     143             :   }
     144             :   CachedWeakPtr<T, Base>& operator=(already_AddRefed<T>& aOther)
     145             :   {
     146             :     RefPtr<T> other = aOther;
     147             :     mWeakPtr = do_GetWeakReference(static_cast<Base*>(other.get()));
     148             :     mCache = other;
     149             :     return *this;
     150             :   }
     151             : 
     152             :   bool IsAlive() const { return mWeakPtr && mWeakPtr->IsAlive(); }
     153             : 
     154             :   explicit operator bool() const { return mWeakPtr; }
     155             :   operator T*() const { return get(); }
     156           0 :   T* get() const
     157             :   {
     158           0 :     if (mCache && !mWeakPtr->IsAlive()) {
     159           0 :       const_cast<CachedWeakPtr<T, Base>*>(this)->mCache = nullptr;
     160             :     }
     161           0 :     return mCache;
     162             :   }
     163             : 
     164             : private:
     165             :   nsWeakPtr mWeakPtr;
     166             :   T* MOZ_NON_OWNING_REF mCache;
     167             : };
     168             : 
     169             : #define kMOZEditorBogusNodeAttrAtom nsGkAtoms::mozeditorbogusnode
     170             : #define kMOZEditorBogusNodeValue NS_LITERAL_STRING("TRUE")
     171             : 
     172             : /**
     173             :  * SplitAtEdges is for EditorBase::SplitNodeDeepWithTransaction(),
     174             :  * HTMLEditor::InsertNodeAtPoint()
     175             :  */
     176             : enum class SplitAtEdges
     177             : {
     178             :   // EditorBase::SplitNodeDeepWithTransaction() won't split container element
     179             :   // nodes at their edges.  I.e., when split point is start or end of
     180             :   // container, it won't be split.
     181             :   eDoNotCreateEmptyContainer,
     182             :   // EditorBase::SplitNodeDeepWithTransaction() always splits containers even
     183             :   // if the split point is at edge of a container.  E.g., if split point is
     184             :   // start of an inline element, empty inline element is created as a new left
     185             :   // node.
     186             :   eAllowToCreateEmptyContainer,
     187             : };
     188             : 
     189             : /**
     190             :  * Implementation of an editor object.  it will be the controller/focal point
     191             :  * for the main editor services. i.e. the GUIManager, publishing, transaction
     192             :  * manager, event interfaces. the idea for the event interfaces is to have them
     193             :  * delegate the actual commands to the editor independent of the XPFE
     194             :  * implementation.
     195             :  */
     196             : class EditorBase : public nsIEditor
     197             :                  , public nsISelectionListener
     198             :                  , public nsSupportsWeakReference
     199             : {
     200             : public:
     201             :   /****************************************************************************
     202             :    * NOTE: DO NOT MAKE YOUR NEW METHODS PUBLIC IF they are called by other
     203             :    *       classes under libeditor except EditorEventListener and
     204             :    *       HTMLEditorEventListener because each public method which may fire
     205             :    *       eEditorInput event will need to instantiate new stack class for
     206             :    *       managing input type value of eEditorInput and cache some objects
     207             :    *       for smarter handling.  In other words, when you add new root
     208             :    *       method to edit the DOM tree, you can make your new method public.
     209             :    ****************************************************************************/
     210             : 
     211             :   typedef dom::Element Element;
     212             :   typedef dom::Selection Selection;
     213             :   typedef dom::Text Text;
     214             : 
     215             :   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     216           0 :   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(EditorBase, nsIEditor)
     217             : 
     218             :   // nsIEditor methods
     219             :   NS_DECL_NSIEDITOR
     220             : 
     221             :   // nsISelectionListener method
     222             :   NS_DECL_NSISELECTIONLISTENER
     223             : 
     224             :   /**
     225             :    * The default constructor. This should suffice. the setting of the
     226             :    * interfaces is done after the construction of the editor class.
     227             :    */
     228             :   EditorBase();
     229             : 
     230             :   /**
     231             :    * Init is to tell the implementation of nsIEditor to begin its services
     232             :    * @param aDoc          The dom document interface being observed
     233             :    * @param aRoot         This is the root of the editable section of this
     234             :    *                      document. If it is null then we get root
     235             :    *                      from document body.
     236             :    * @param aSelCon       this should be used to get the selection location
     237             :    *                      (will be null for HTML editors)
     238             :    * @param aFlags        A bitmask of flags for specifying the behavior
     239             :    *                      of the editor.
     240             :    */
     241             :   virtual nsresult Init(nsIDocument& doc,
     242             :                         Element* aRoot,
     243             :                         nsISelectionController* aSelCon,
     244             :                         uint32_t aFlags,
     245             :                         const nsAString& aInitialValue);
     246             : 
     247             :   /**
     248             :    * PostCreate should be called after Init, and is the time that the editor
     249             :    * tells its documentStateObservers that the document has been created.
     250             :    */
     251             :   nsresult PostCreate();
     252             : 
     253             :   /**
     254             :    * PreDestroy is called before the editor goes away, and gives the editor a
     255             :    * chance to tell its documentStateObservers that the document is going away.
     256             :    * @param aDestroyingFrames set to true when the frames being edited
     257             :    * are being destroyed (so there is no need to modify any nsISelections,
     258             :    * nor is it safe to do so)
     259             :    */
     260             :   virtual void PreDestroy(bool aDestroyingFrames);
     261             : 
     262          22 :   bool IsInitialized() const { return !!mDocument; }
     263             :   bool Destroyed() const { return mDidPreDestroy; }
     264             : 
     265           4 :   nsIDocument* GetDocument() const { return mDocument; }
     266             : 
     267           4 :   nsIPresShell* GetPresShell() const
     268             :   {
     269          12 :     return mDocument ? mDocument->GetShell() : nullptr;
     270             :   }
     271           0 :   nsPresContext* GetPresContext() const
     272             :   {
     273           0 :     nsIPresShell* presShell = GetPresShell();
     274           0 :     return presShell ? presShell->GetPresContext() : nullptr;
     275             :   }
     276             : 
     277             :   already_AddRefed<nsIWidget> GetWidget();
     278             : 
     279          16 :   nsISelectionController* GetSelectionController() const
     280             :   {
     281          32 :     if (mSelectionController) {
     282             :       return mSelectionController;
     283             :     }
     284           0 :     if (!mDocument) {
     285             :       return nullptr;
     286             :     }
     287           0 :     nsIPresShell* presShell = mDocument->GetShell();
     288           0 :     if (!presShell) {
     289             :       return nullptr;
     290             :     }
     291           0 :     nsISelectionController* sc = static_cast<PresShell*>(presShell);
     292           0 :     return sc;
     293             :   }
     294             : 
     295             :   nsresult GetSelection(SelectionType aSelectionType,
     296             :                         Selection** aSelection);
     297             : 
     298          14 :   Selection* GetSelection(SelectionType aSelectionType =
     299             :                                           SelectionType::eNormal)
     300             :   {
     301           0 :     nsISelectionController* sc = GetSelectionController();
     302          14 :     if (!sc) {
     303             :       return nullptr;
     304             :     }
     305           0 :     Selection* selection = sc->GetSelection(ToRawSelectionType(aSelectionType));
     306          14 :     return selection;
     307             :   }
     308             : 
     309             :   /**
     310             :    * Fast non-refcounting editor root element accessor
     311             :    */
     312          20 :   Element* GetRoot() const { return mRootElement; }
     313             : 
     314           0 :   RangeUpdater& RangeUpdaterRef() { return mRangeUpdater; }
     315             : 
     316             :   /**
     317             :    * Set or unset TextInputListener.  If setting non-nullptr when the editor
     318             :    * already has a TextInputListener, this will crash in debug build.
     319             :    */
     320             :   void SetTextInputListener(TextInputListener* aTextInputListener);
     321             : 
     322             :   /**
     323             :    * Set or unset IMEContentObserver.  If setting non-nullptr when the editor
     324             :    * already has an IMEContentObserver, this will crash in debug build.
     325             :    */
     326             :   void SetIMEContentObserver(IMEContentObserver* aIMEContentObserver);
     327             : 
     328             :   /**
     329             :    * Returns current composition.
     330             :    */
     331             :   TextComposition* GetComposition() const;
     332             : 
     333             :   /**
     334             :    * Get preferred IME status of current widget.
     335             :    */
     336             :   virtual nsresult GetPreferredIMEState(widget::IMEState* aState);
     337             : 
     338             :   /**
     339             :    * Returns true if there is composition string and not fixed.
     340             :    */
     341             :   bool IsIMEComposing() const;
     342             : 
     343             :   /**
     344             :    * Commit composition if there is.
     345             :    * Note that when there is a composition, this requests to commit composition
     346             :    * to native IME.  Therefore, when there is composition, this can do anything.
     347             :    * For example, the editor instance, the widget or the process itself may
     348             :    * be destroyed.
     349             :    */
     350             :   nsresult CommitComposition();
     351             : 
     352             :   /**
     353             :    * ToggleTextDirection() toggles text-direction of the root element.
     354             :    */
     355             :   nsresult ToggleTextDirection();
     356             : 
     357             :   /**
     358             :    * SwitchTextDirectionTo() sets the text-direction of the root element to
     359             :    * LTR or RTL.
     360             :    */
     361             :   enum class TextDirection
     362             :   {
     363             :     eLTR,
     364             :     eRTL,
     365             :   };
     366             :   void SwitchTextDirectionTo(TextDirection aTextDirection);
     367             : 
     368             :   /**
     369             :    * Finalizes selection and caret for the editor.
     370             :    */
     371             :   nsresult FinalizeSelection();
     372             : 
     373             :   /**
     374             :    * Returns true if selection is in an editable element and both the range
     375             :    * start and the range end are editable.  E.g., even if the selection range
     376             :    * includes non-editable elements, returns true when one of common ancestors
     377             :    * of the range start and the range end is editable.  Otherwise, false.
     378             :    */
     379             :   bool IsSelectionEditable();
     380             : 
     381             :   /**
     382             :    * Returns number of undo or redo items.
     383             :    */
     384           1 :   size_t NumberOfUndoItems() const
     385             :   {
     386           3 :     return mTransactionManager ? mTransactionManager->NumberOfUndoItems() : 0;
     387             :   }
     388           1 :   size_t NumberOfRedoItems() const
     389             :   {
     390           3 :     return mTransactionManager ? mTransactionManager->NumberOfRedoItems() : 0;
     391             :   }
     392             : 
     393             :   /**
     394             :    * Returns true if this editor can store transactions for undo/redo.
     395             :    */
     396             :   bool IsUndoRedoEnabled() const
     397             :   {
     398           4 :     return !!mTransactionManager;
     399             :   }
     400             : 
     401             :   /**
     402             :    * Return true if it's possible to undo/redo right now.
     403             :    */
     404           1 :   bool CanUndo() const
     405             :   {
     406           1 :     return IsUndoRedoEnabled() && NumberOfUndoItems() > 0;
     407             :   }
     408           1 :   bool CanRedo() const
     409             :   {
     410           1 :     return IsUndoRedoEnabled() && NumberOfRedoItems() > 0;
     411             :   }
     412             : 
     413             :   /**
     414             :    * Enables or disables undo/redo feature.  Returns true if it succeeded,
     415             :    * otherwise, e.g., we're undoing or redoing, returns false.
     416             :    */
     417           0 :   bool EnableUndoRedo(int32_t aMaxTransactionCount = -1)
     418             :   {
     419           0 :     if (!mTransactionManager) {
     420           1 :       mTransactionManager = new TransactionManager();
     421             :     }
     422           2 :     return mTransactionManager->EnableUndoRedo(aMaxTransactionCount);
     423             :   }
     424           0 :   bool DisableUndoRedo()
     425             :   {
     426           0 :     if (!mTransactionManager) {
     427             :       return true;
     428             :     }
     429             :     // XXX Even we clear the transaction manager, IsUndoRedoEnabled() keep
     430             :     //     returning true...
     431           0 :     return mTransactionManager->DisableUndoRedo();
     432             :   }
     433           1 :   bool ClearUndoRedo()
     434             :   {
     435           2 :     if (!mTransactionManager) {
     436             :       return true;
     437             :     }
     438           0 :     return mTransactionManager->ClearUndoRedo();
     439             :   }
     440             : 
     441             :   /**
     442             :    * Adds or removes transaction listener to or from the transaction manager.
     443             :    * Note that TransactionManager does not check if the listener is in the
     444             :    * array.  So, caller of AddTransactionListener() needs to manage if it's
     445             :    * already been registered to the transaction manager.
     446             :    */
     447           0 :   bool AddTransactionListener(nsITransactionListener& aListener)
     448             :   {
     449           0 :     if (!mTransactionManager) {
     450             :       return false;
     451             :     }
     452           0 :     return mTransactionManager->AddTransactionListener(aListener);
     453             :   }
     454           0 :   bool RemoveTransactionListener(nsITransactionListener& aListener)
     455             :   {
     456           0 :     if (!mTransactionManager) {
     457             :       return false;
     458             :     }
     459           0 :     return mTransactionManager->RemoveTransactionListener(aListener);
     460             :   }
     461             : 
     462             :   virtual nsresult HandleKeyPressEvent(WidgetKeyboardEvent* aKeyboardEvent);
     463             : 
     464             :   virtual dom::EventTarget* GetDOMEventTarget() = 0;
     465             : 
     466             :   /**
     467             :    * Accessor methods to flags.
     468             :    */
     469             :   uint32_t Flags() const { return mFlags; }
     470             : 
     471           0 :   nsresult AddFlags(uint32_t aFlags)
     472             :   {
     473           0 :     const uint32_t kOldFlags = Flags();
     474           0 :     const uint32_t kNewFlags = (kOldFlags | aFlags);
     475           0 :     if (kNewFlags == kOldFlags) {
     476             :       return NS_OK;
     477             :     }
     478           0 :     return SetFlags(kNewFlags); // virtual call and may be expensive.
     479             :   }
     480           1 :   nsresult RemoveFlags(uint32_t aFlags)
     481             :   {
     482           0 :     const uint32_t kOldFlags = Flags();
     483           1 :     const uint32_t kNewFlags = (kOldFlags & ~aFlags);
     484           1 :     if (kNewFlags == kOldFlags) {
     485             :       return NS_OK;
     486             :     }
     487           1 :     return SetFlags(kNewFlags); // virtual call and may be expensive.
     488             :   }
     489             :   nsresult AddAndRemoveFlags(uint32_t aAddingFlags, uint32_t aRemovingFlags)
     490             :   {
     491             :     MOZ_ASSERT(!(aAddingFlags & aRemovingFlags),
     492             :                "Same flags are specified both adding and removing");
     493             :     const uint32_t kOldFlags = Flags();
     494             :     const uint32_t kNewFlags = ((kOldFlags | aAddingFlags) & ~aRemovingFlags);
     495             :     if (kNewFlags == kOldFlags) {
     496             :       return NS_OK;
     497             :     }
     498             :     return SetFlags(kNewFlags); // virtual call and may be expensive.
     499             :   }
     500             : 
     501             :   bool IsPlaintextEditor() const
     502             :   {
     503           0 :     return (mFlags & nsIPlaintextEditor::eEditorPlaintextMask) != 0;
     504             :   }
     505             : 
     506             :   bool IsSingleLineEditor() const
     507             :   {
     508           0 :     return (mFlags & nsIPlaintextEditor::eEditorSingleLineMask) != 0;
     509             :   }
     510             : 
     511             :   bool IsPasswordEditor() const
     512             :   {
     513          10 :     return (mFlags & nsIPlaintextEditor::eEditorPasswordMask) != 0;
     514             :   }
     515             : 
     516             :   // FYI: Both IsRightToLeft() and IsLeftToRight() may return false if
     517             :   //      the editor inherits the content node's direction.
     518             :   bool IsRightToLeft() const
     519             :   {
     520           0 :     return (mFlags & nsIPlaintextEditor::eEditorRightToLeft) != 0;
     521             :   }
     522             :   bool IsLeftToRight() const
     523             :   {
     524           0 :     return (mFlags & nsIPlaintextEditor::eEditorLeftToRight) != 0;
     525             :   }
     526             : 
     527             :   bool IsReadonly() const
     528             :   {
     529           0 :     return (mFlags & nsIPlaintextEditor::eEditorReadonlyMask) != 0;
     530             :   }
     531             : 
     532             :   bool IsDisabled() const
     533             :   {
     534           1 :     return (mFlags & nsIPlaintextEditor::eEditorDisabledMask) != 0;
     535             :   }
     536             : 
     537             :   bool IsInputFiltered() const
     538             :   {
     539           0 :     return (mFlags & nsIPlaintextEditor::eEditorFilterInputMask) != 0;
     540             :   }
     541             : 
     542             :   bool IsMailEditor() const
     543             :   {
     544           0 :     return (mFlags & nsIPlaintextEditor::eEditorMailMask) != 0;
     545             :   }
     546             : 
     547             :   bool IsWrapHackEnabled() const
     548             :   {
     549           0 :     return (mFlags & nsIPlaintextEditor::eEditorEnableWrapHackMask) != 0;
     550             :   }
     551             : 
     552             :   bool IsFormWidget() const
     553             :   {
     554           0 :     return (mFlags & nsIPlaintextEditor::eEditorWidgetMask) != 0;
     555             :   }
     556             : 
     557             :   bool NoCSS() const
     558             :   {
     559           0 :     return (mFlags & nsIPlaintextEditor::eEditorNoCSSMask) != 0;
     560             :   }
     561             : 
     562             :   bool IsInteractionAllowed() const
     563             :   {
     564           1 :     return (mFlags & nsIPlaintextEditor::eEditorAllowInteraction) != 0;
     565             :   }
     566             : 
     567             :   bool DontEchoPassword() const
     568             :   {
     569           0 :     return (mFlags & nsIPlaintextEditor::eEditorDontEchoPassword) != 0;
     570             :   }
     571             : 
     572             :   bool ShouldSkipSpellCheck() const
     573             :   {
     574           0 :     return (mFlags & nsIPlaintextEditor::eEditorSkipSpellCheck) != 0;
     575             :   }
     576             : 
     577           0 :   bool IsTabbable() const
     578             :   {
     579           0 :     return IsSingleLineEditor() || IsPasswordEditor() || IsFormWidget() ||
     580           0 :            IsInteractionAllowed();
     581             :   }
     582             : 
     583             :   bool HasIndependentSelection() const
     584             :   {
     585           0 :     return !!mSelectionController;
     586             :   }
     587             : 
     588             :   bool IsModifiable() const
     589             :   {
     590           2 :     return !IsReadonly();
     591             :   }
     592             : 
     593             :   /**
     594             :    * IsInEditSubAction() return true while the instance is handling an edit
     595             :    * sub-action.  Otherwise, false.
     596             :    */
     597             :   bool IsInEditSubAction() const { return mIsInEditSubAction; }
     598             : 
     599             :   /**
     600             :    * SuppressDispatchingInputEvent() suppresses or unsuppresses dispatching
     601             :    * "input" event.
     602             :    */
     603             :   void SuppressDispatchingInputEvent(bool aSuppress)
     604             :   {
     605           0 :     mDispatchInputEvent = !aSuppress;
     606             :   }
     607             : 
     608             :   /**
     609             :    * IsSuppressingDispatchingInputEvent() returns true if the editor stops
     610             :    * dispatching input event.  Otherwise, false.
     611             :    */
     612             :   bool IsSuppressingDispatchingInputEvent() const
     613             :   {
     614           0 :     return !mDispatchInputEvent;
     615             :   }
     616             : 
     617             :   /**
     618             :    * Returns true if markNodeDirty() has any effect.  Returns false if
     619             :    * markNodeDirty() is a no-op.
     620             :    */
     621           1 :   bool OutputsMozDirty() const
     622             :   {
     623             :     // Return true for Composer (!IsInteractionAllowed()) or mail
     624             :     // (IsMailEditor()), but false for webpages.
     625           2 :     return !IsInteractionAllowed() || IsMailEditor();
     626             :   }
     627             : 
     628             :   /**
     629             :    * Get the focused content, if we're focused.  Returns null otherwise.
     630             :    */
     631             :   virtual nsIContent* GetFocusedContent();
     632             : 
     633             :   /**
     634             :    * Get the focused content for the argument of some IMEStateManager's
     635             :    * methods.
     636             :    */
     637             :   virtual already_AddRefed<nsIContent> GetFocusedContentForIME();
     638             : 
     639             :   /**
     640             :    * Whether the aGUIEvent should be handled by this editor or not.  When this
     641             :    * returns false, The aGUIEvent shouldn't be handled on this editor,
     642             :    * i.e., The aGUIEvent should be handled by another inner editor or ancestor
     643             :    * elements.
     644             :    */
     645             :   virtual bool IsAcceptableInputEvent(WidgetGUIEvent* aGUIEvent);
     646             : 
     647             :   /**
     648             :    * FindSelectionRoot() returns a selection root of this editor when aNode
     649             :    * gets focus.  aNode must be a content node or a document node.  When the
     650             :    * target isn't a part of this editor, returns nullptr.  If this is for
     651             :    * designMode, you should set the document node to aNode except that an
     652             :    * element in the document has focus.
     653             :    */
     654             :   virtual already_AddRefed<nsIContent> FindSelectionRoot(nsINode* aNode);
     655             : 
     656             :   /**
     657             :    * This method has to be called by EditorEventListener::Focus.
     658             :    * All actions that have to be done when the editor is focused needs to be
     659             :    * added here.
     660             :    */
     661             :   void OnFocus(dom::EventTarget* aFocusEventTarget);
     662             : 
     663             :   /** Resyncs spellchecking state (enabled/disabled).  This should be called
     664             :     * when anything that affects spellchecking state changes, such as the
     665             :     * spellcheck attribute value.
     666             :     */
     667             :   void SyncRealTimeSpell();
     668             : 
     669             : protected: // May be called by friends.
     670             :   /****************************************************************************
     671             :    * Some classes like TextEditRules, HTMLEditRules, WSRunObject which are
     672             :    * part of handling edit actions are allowed to call the following protected
     673             :    * methods.  However, those methods won't prepare caches of some objects
     674             :    * which are necessary for them.  So, if you want some following methods
     675             :    * to do that for you, you need to create a wrapper method in public scope
     676             :    * and call it.
     677             :    ****************************************************************************/
     678             : 
     679             :   /**
     680             :    * InsertTextWithTransaction() inserts aStringToInsert to aPointToInsert or
     681             :    * better insertion point around it.  If aPointToInsert isn't in a text node,
     682             :    * this method looks for the nearest point in a text node with
     683             :    * FindBetterInsertionPoint().  If there is no text node, this creates
     684             :    * new text node and put aStringToInsert to it.
     685             :    *
     686             :    * @param aDocument       The document of this editor.
     687             :    * @param aStringToInsert The string to insert.
     688             :    * @param aPointToInser   The point to insert aStringToInsert.
     689             :    *                        Must be valid DOM point.
     690             :    * @param aPointAfterInsertedString
     691             :    *                        The point after inserted aStringToInsert.
     692             :    *                        So, when this method actually inserts string,
     693             :    *                        this is set to a point in the text node.
     694             :    *                        Otherwise, this may be set to aPointToInsert.
     695             :    * @return                When this succeeds to insert the string or
     696             :    *                        does nothing during composition, returns NS_OK.
     697             :    *                        Otherwise, an error code.
     698             :    */
     699             :   virtual nsresult
     700             :   InsertTextWithTransaction(nsIDocument& aDocument,
     701             :                             const nsAString& aStringToInsert,
     702             :                             const EditorRawDOMPoint& aPointToInsert,
     703             :                             EditorRawDOMPoint* aPointAfterInsertedString =
     704             :                               nullptr);
     705             : 
     706             :   /**
     707             :    * InsertTextIntoTextNodeWithTransaction() inserts aStringToInsert into
     708             :    * aOffset of aTextNode with transaction.
     709             :    *
     710             :    * @param aStringToInsert     String to be inserted.
     711             :    * @param aTextNode           Text node to contain aStringToInsert.
     712             :    * @param aOffset             Offset at insertion point in aTextNode.
     713             :    * @param aSuppressIME        true if it's not a part of IME composition.
     714             :    *                            E.g., adjusting whitespaces during composition.
     715             :    *                            false, otherwise.
     716             :    */
     717             :   nsresult
     718             :   InsertTextIntoTextNodeWithTransaction(const nsAString& aStringToInsert,
     719             :                                         Text& aTextNode, int32_t aOffset,
     720             :                                         bool aSuppressIME = false);
     721             : 
     722             :   nsresult SetTextImpl(Selection& aSelection,
     723             :                        const nsAString& aString,
     724             :                        Text& aTextNode);
     725             : 
     726             :   /**
     727             :    * DeleteNodeWithTransaction() removes aNode from the DOM tree.
     728             :    *
     729             :    * @param aNode       The node which will be removed form the DOM tree.
     730             :    */
     731             :   nsresult DeleteNodeWithTransaction(nsINode& aNode);
     732             : 
     733             :   /**
     734             :    * InsertNodeWithTransaction() inserts aContentToInsert before the child
     735             :    * specified by aPointToInsert.
     736             :    *
     737             :    * @param aContentToInsert    The node to be inserted.
     738             :    * @param aPointToInsert      The insertion point of aContentToInsert.
     739             :    *                            If this refers end of the container, the
     740             :    *                            transaction will append the node to the
     741             :    *                            container.  Otherwise, will insert the node
     742             :    *                            before child node referred by this.
     743             :    */
     744             :   template<typename PT, typename CT>
     745             :   nsresult
     746             :   InsertNodeWithTransaction(nsIContent& aContentToInsert,
     747             :                             const EditorDOMPointBase<PT, CT>& aPointToInsert);
     748             : 
     749             :   /**
     750             :    * ReplaceContainerWithTransaction() creates new element whose name is
     751             :    * aTagName, moves all children in aOldContainer to the new element, then,
     752             :    * removes aOldContainer from the DOM tree.
     753             :    *
     754             :    * @param aOldContainer       The element node which should be replaced
     755             :    *                            with new element.
     756             :    * @param aTagName            The name of new element node.
     757             :    */
     758             :   already_AddRefed<Element>
     759           0 :   ReplaceContainerWithTransaction(Element& aOldContainer,
     760             :                                   nsAtom& aTagName)
     761             :   {
     762             :     return ReplaceContainerWithTransactionInternal(aOldContainer, aTagName,
     763             :                                                    *nsGkAtoms::_empty,
     764           0 :                                                    EmptyString(), false);
     765             :   }
     766             : 
     767             :   /**
     768             :    * ReplaceContainerAndCloneAttributesWithTransaction() creates new element
     769             :    * whose name is aTagName, copies all attributes from aOldContainer to the
     770             :    * new element, moves all children in aOldContainer to the new element, then,
     771             :    * removes aOldContainer from the DOM tree.
     772             :    *
     773             :    * @param aOldContainer       The element node which should be replaced
     774             :    *                            with new element.
     775             :    * @param aTagName            The name of new element node.
     776             :    */
     777             :   already_AddRefed<Element>
     778           0 :   ReplaceContainerAndCloneAttributesWithTransaction(Element& aOldContainer,
     779             :                                                     nsAtom& aTagName)
     780             :   {
     781             :     return ReplaceContainerWithTransactionInternal(aOldContainer, aTagName,
     782             :                                                    *nsGkAtoms::_empty,
     783           0 :                                                    EmptyString(), true);
     784             :   }
     785             : 
     786             :   /**
     787             :    * ReplaceContainerWithTransaction() creates new element whose name is
     788             :    * aTagName, sets aAttributes of the new element to aAttributeValue, moves
     789             :    * all children in aOldContainer to the new element, then, removes
     790             :    * aOldContainer from the DOM tree.
     791             :    *
     792             :    * @param aOldContainer       The element node which should be replaced
     793             :    *                            with new element.
     794             :    * @param aTagName            The name of new element node.
     795             :    * @param aAttribute          Attribute name to be set to the new element.
     796             :    * @param aAttributeValue     Attribute value to be set to aAttribute.
     797             :    */
     798             :   already_AddRefed<Element>
     799             :   ReplaceContainerWithTransaction(Element& aOldContainer,
     800             :                                   nsAtom& aTagName,
     801             :                                   nsAtom& aAttribute,
     802             :                                   const nsAString& aAttributeValue)
     803             :   {
     804             :     return ReplaceContainerWithTransactionInternal(aOldContainer, aTagName,
     805             :                                                    aAttribute,
     806             :                                                    aAttributeValue, false);
     807             :   }
     808             : 
     809             :   /**
     810             :    * CloneAttributesWithTransaction() clones all attributes from
     811             :    * aSourceElement to aDestElement after removing all attributes in
     812             :    * aDestElement.
     813             :    */
     814             :   void CloneAttributesWithTransaction(Element& aDestElement,
     815             :                                       Element& aSourceElement);
     816             : 
     817             :   /**
     818             :    * RemoveContainerWithTransaction() removes aElement from the DOM tree and
     819             :    * moves all its children to the parent of aElement.
     820             :    *
     821             :    * @param aElement            The element to be removed.
     822             :    */
     823             :   nsresult RemoveContainerWithTransaction(Element& aElement);
     824             : 
     825             :   /**
     826             :    * InsertContainerWithTransaction() creates new element whose name is
     827             :    * aTagName, moves aContent into the new element, then, inserts the new
     828             :    * element into where aContent was.
     829             :    * Note that this method does not check if aContent is valid child of
     830             :    * the new element.  So, callers need to guarantee it.
     831             :    *
     832             :    * @param aContent            The content which will be wrapped with new
     833             :    *                            element.
     834             :    * @param aTagName            Element name of new element which will wrap
     835             :    *                            aContent and be inserted into where aContent
     836             :    *                            was.
     837             :    * @return                    The new element.
     838             :    */
     839             :   already_AddRefed<Element>
     840           0 :   InsertContainerWithTransaction(nsIContent& aContent, nsAtom& aTagName)
     841             :   {
     842             :     return InsertContainerWithTransactionInternal(aContent, aTagName,
     843             :                                                   *nsGkAtoms::_empty,
     844           0 :                                                   EmptyString());
     845             :   }
     846             : 
     847             :   /**
     848             :    * InsertContainerWithTransaction() creates new element whose name is
     849             :    * aTagName, sets its aAttribute to aAttributeValue, moves aContent into the
     850             :    * new element, then, inserts the new element into where aContent was.
     851             :    * Note that this method does not check if aContent is valid child of
     852             :    * the new element.  So, callers need to guarantee it.
     853             :    *
     854             :    * @param aContent            The content which will be wrapped with new
     855             :    *                            element.
     856             :    * @param aTagName            Element name of new element which will wrap
     857             :    *                            aContent and be inserted into where aContent
     858             :    *                            was.
     859             :    * @param aAttribute          Attribute which should be set to the new
     860             :    *                            element.
     861             :    * @param aAttributeValue     Value to be set to aAttribute.
     862             :    * @return                    The new element.
     863             :    */
     864             :   already_AddRefed<Element>
     865             :   InsertContainerWithTransaction(nsIContent& aContent, nsAtom& aTagName,
     866             :                                  nsAtom& aAttribute,
     867             :                                  const nsAString& aAttributeValue)
     868             :   {
     869             :     return InsertContainerWithTransactionInternal(aContent, aTagName,
     870           0 :                                                   aAttribute, aAttributeValue);
     871             :   }
     872             : 
     873             :   /**
     874             :    * SplitNodeWithTransaction() creates a transaction to create a new node
     875             :    * (left node) identical to an existing node (right node), and split the
     876             :    * contents between the same point in both nodes, then, execute the
     877             :    * transaction.
     878             :    *
     879             :    * @param aStartOfRightNode   The point to split.  Its container will be
     880             :    *                            the right node, i.e., become the new node's
     881             :    *                            next sibling.  And the point will be start
     882             :    *                            of the right node.
     883             :    * @param aError              If succeed, returns no error.  Otherwise, an
     884             :    *                            error.
     885             :    */
     886             :   template<typename PT, typename CT>
     887             :   already_AddRefed<nsIContent>
     888             :   SplitNodeWithTransaction(const EditorDOMPointBase<PT, CT>& aStartOfRightNode,
     889             :                            ErrorResult& aResult);
     890             : 
     891             :   /**
     892             :    * JoinNodesWithTransaction() joins aLeftNode and aRightNode.  Content of
     893             :    * aLeftNode will be merged into aRightNode.  Actual implemenation of this
     894             :    * method is JoinNodesImpl().  So, see its explanation for the detail.
     895             :    *
     896             :    * @param aLeftNode   Will be removed from the DOM tree.
     897             :    * @param aRightNode  The node which will be new container of the content of
     898             :    *                    aLeftNode.
     899             :    */
     900             :   nsresult JoinNodesWithTransaction(nsINode& aLeftNode, nsINode& aRightNode);
     901             : 
     902             :   /**
     903             :    * MoveNodeWithTransaction() moves aContent to aPointToInsert.
     904             :    *
     905             :    * @param aContent        The node to be moved.
     906             :    */
     907             :   template<typename PT, typename CT>
     908             :   nsresult
     909             :   MoveNodeWithTransaction(nsIContent& aContent,
     910             :                           const EditorDOMPointBase<PT, CT>& aPointToInsert);
     911             : 
     912             :   /**
     913             :    * MoveNodeToEndWithTransaction() moves aContent to end of aNewContainer.
     914             :    *
     915             :    * @param aContent        The node to be moved.
     916             :    * @param aNewContainer   The new container which will contain aContent as
     917             :    *                        its last child.
     918             :    */
     919             :   nsresult
     920           0 :   MoveNodeToEndWithTransaction(nsIContent& aContent,
     921             :                                nsINode& aNewContainer)
     922             :   {
     923           0 :     EditorRawDOMPoint pointToInsert;
     924           0 :     pointToInsert.SetToEndOf(&aNewContainer);
     925           0 :     return MoveNodeWithTransaction(aContent, pointToInsert);
     926             :   }
     927             : 
     928             :   /**
     929             :    * MoveAllChildren() moves all children of aContainer to before
     930             :    * aPointToInsert.GetChild().
     931             :    * See explanation of MoveChildren() for the detail of the behavior.
     932             :    *
     933             :    * @param aContainer          The container node whose all children should
     934             :    *                            be moved.
     935             :    * @param aPointToInsert      The insertion point.  The container must not
     936             :    *                            be a data node like a text node.
     937             :    * @param aError              The result.  If this succeeds to move children,
     938             :    *                            returns NS_OK.  Otherwise, an error.
     939             :    */
     940             :   void MoveAllChildren(nsINode& aContainer,
     941             :                        const EditorRawDOMPoint& aPointToInsert,
     942             :                        ErrorResult& aError);
     943             : 
     944             :   /**
     945             :    * MovePreviousSiblings() moves all siblings before aChild (i.e., aChild
     946             :    * won't be moved) to before aPointToInsert.GetChild().
     947             :    * See explanation of MoveChildren() for the detail of the behavior.
     948             :    *
     949             :    * @param aChild              The node which is next sibling of the last
     950             :    *                            node to be moved.
     951             :    * @param aPointToInsert      The insertion point.  The container must not
     952             :    *                            be a data node like a text node.
     953             :    * @param aError              The result.  If this succeeds to move children,
     954             :    *                            returns NS_OK.  Otherwise, an error.
     955             :    */
     956             :   void MovePreviousSiblings(nsIContent& aChild,
     957             :                             const EditorRawDOMPoint& aPointToInsert,
     958             :                             ErrorResult& aError);
     959             : 
     960             :   /**
     961             :    * MoveChildren() moves all children between aFirstChild and aLastChild to
     962             :    * before aPointToInsert.GetChild().
     963             :    * If some children are moved to different container while this method
     964             :    * moves other children, they are just ignored.
     965             :    * If the child node referred by aPointToInsert is moved to different
     966             :    * container while this method moves children, returns error.
     967             :    *
     968             :    * @param aFirstChild         The first child which should be moved to
     969             :    *                            aPointToInsert.
     970             :    * @param aLastChild          The last child which should be moved.  This
     971             :    *                            must be a sibling of aFirstChild and it should
     972             :    *                            be positioned after aFirstChild in the DOM tree
     973             :    *                            order.
     974             :    * @param aPointToInsert      The insertion point.  The container must not
     975             :    *                            be a data node like a text node.
     976             :    * @param aError              The result.  If this succeeds to move children,
     977             :    *                            returns NS_OK.  Otherwise, an error.
     978             :    */
     979             :   void MoveChildren(nsIContent& aFirstChild,
     980             :                     nsIContent& aLastChild,
     981             :                     const EditorRawDOMPoint& aPointToInsert,
     982             :                     ErrorResult& aError);
     983             : 
     984             :   /**
     985             :    * CloneAttributeWithTransaction() copies aAttribute of aSourceElement to
     986             :    * aDestElement.  If aSourceElement doesn't have aAttribute, this removes
     987             :    * aAttribute from aDestElement.
     988             :    *
     989             :    * @param aAttribute          Attribute name to be cloned.
     990             :    * @param aDestElement        Element node which will be set aAttribute or
     991             :    *                            whose aAttribute will be removed.
     992             :    * @param aSourceElement      Element node which provides the value of
     993             :    *                            aAttribute in aDestElement.
     994             :    */
     995             :   nsresult CloneAttributeWithTransaction(nsAtom& aAttribute,
     996             :                                          Element& aDestElement,
     997             :                                          Element& aSourceElement);
     998             : 
     999             :   /**
    1000             :    * RemoveAttributeWithTransaction() removes aAttribute from aElement.
    1001             :    *
    1002             :    * @param aElement        Element node which will lose aAttribute.
    1003             :    * @param aAttribute      Attribute name to be removed from aElement.
    1004             :    */
    1005             :   nsresult RemoveAttributeWithTransaction(Element& aElement,
    1006             :                                           nsAtom& aAttribute);
    1007             : 
    1008             :   virtual nsresult RemoveAttributeOrEquivalent(Element* aElement,
    1009             :                                                nsAtom* aAttribute,
    1010             :                                                bool aSuppressTransaction) = 0;
    1011             : 
    1012             :   /**
    1013             :    * SetAttributeWithTransaction() sets aAttribute of aElement to aValue.
    1014             :    *
    1015             :    * @param aElement        Element node which will have aAttribute.
    1016             :    * @param aAttribute      Attribute name to be set.
    1017             :    * @param aValue          Attribute value be set to aAttribute.
    1018             :    */
    1019             :   nsresult SetAttributeWithTransaction(Element& aElement,
    1020             :                                        nsAtom& aAttribute,
    1021             :                                        const nsAString& aValue);
    1022             : 
    1023             :   virtual nsresult SetAttributeOrEquivalent(Element* aElement,
    1024             :                                             nsAtom* aAttribute,
    1025             :                                             const nsAString& aValue,
    1026             :                                             bool aSuppressTransaction) = 0;
    1027             : 
    1028             :   /**
    1029             :    * Method to replace certain CreateElementNS() calls.
    1030             :    *
    1031             :    * @param aTag        Tag you want.
    1032             :    */
    1033             :   already_AddRefed<Element> CreateHTMLContent(nsAtom* aTag);
    1034             : 
    1035             :   /**
    1036             :    * Creates text node which is marked as "maybe modified frequently".
    1037             :    */
    1038             :   static already_AddRefed<nsTextNode> CreateTextNode(nsIDocument& aDocument,
    1039             :                                                      const nsAString& aData);
    1040             : 
    1041             :   /**
    1042             :    * Create an element node whose name is aTag at before aPointToInsert.  When
    1043             :    * this succeed to create an element node, this sets aPointToInsert to the
    1044             :    * new element because the relation of child and offset may be broken.
    1045             :    * If the caller needs to collapse the selection to next to the new element
    1046             :    * node, it should call |aPointToInsert.AdvanceOffset()| after calling this.
    1047             :    *
    1048             :    * @param aTag            The element name to create.
    1049             :    * @param aPointToInsert  The insertion point of new element.  If this refers
    1050             :    *                        end of the container or after, the transaction
    1051             :    *                        will append the element to the container.
    1052             :    *                        Otherwise, will insert the element before the
    1053             :    *                        child node referred by this.
    1054             :    * @return                The created new element node.
    1055             :    */
    1056             :   template<typename PT, typename CT>
    1057             :   already_AddRefed<Element>
    1058             :   CreateNodeWithTransaction(nsAtom& aTag,
    1059             :                             const EditorDOMPointBase<PT, CT>& aPointToInsert);
    1060             : 
    1061             :   /**
    1062             :    * Create an aggregate transaction for delete selection.  The result may
    1063             :    * include DeleteNodeTransactions and/or DeleteTextTransactions as its
    1064             :    * children.
    1065             :    *
    1066             :    * @param aAction             The action caused removing the selection.
    1067             :    * @param aRemovingNode       The node to be removed.
    1068             :    * @param aOffset             The start offset of the range in aRemovingNode.
    1069             :    * @param aLength             The length of the range in aRemovingNode.
    1070             :    * @return                    If it can remove the selection, returns an
    1071             :    *                            aggregate transaction which has some
    1072             :    *                            DeleteNodeTransactions and/or
    1073             :    *                            DeleteTextTransactions as its children.
    1074             :    */
    1075             :   already_AddRefed<EditAggregateTransaction>
    1076             :     CreateTxnForDeleteSelection(EDirection aAction,
    1077             :                                 nsINode** aNode,
    1078             :                                 int32_t* aOffset,
    1079             :                                 int32_t* aLength);
    1080             : 
    1081             :   /**
    1082             :    * Create a transaction for removing the nodes and/or text in aRange.
    1083             :    *
    1084             :    * @param aRangeToDelete      The range to be removed.
    1085             :    * @param aAction             The action caused removing the range.
    1086             :    * @param aRemovingNode       The node to be removed.
    1087             :    * @param aOffset             The start offset of the range in aRemovingNode.
    1088             :    * @param aLength             The length of the range in aRemovingNode.
    1089             :    * @return                    The transaction to remove the range.  Its type
    1090             :    *                            is DeleteNodeTransaction or
    1091             :    *                            DeleteTextTransaction.
    1092             :    */
    1093             :   already_AddRefed<EditTransactionBase>
    1094             :     CreateTxnForDeleteRange(nsRange* aRangeToDelete,
    1095             :                             EDirection aAction,
    1096             :                             nsINode** aRemovingNode,
    1097             :                             int32_t* aOffset,
    1098             :                             int32_t* aLength);
    1099             : 
    1100             :   /**
    1101             :    * DeleteTextWithTransaction() removes text in the range from aCharData.
    1102             :    *
    1103             :    * @param aCharData           The data node which should be modified.
    1104             :    * @param aOffset             Start offset of removing text in aCharData.
    1105             :    * @param aLength             Length of removing text.
    1106             :    */
    1107             :   nsresult DeleteTextWithTransaction(dom::CharacterData& aCharacterData,
    1108             :                                      uint32_t aOffset, uint32_t aLength);
    1109             : 
    1110             :   /**
    1111             :    * ReplaceContainerWithTransactionInternal() is implementation of
    1112             :    * ReplaceContainerWithTransaction() and
    1113             :    * ReplaceContainerAndCloneAttributesWithTransaction().
    1114             :    *
    1115             :    * @param aOldContainer       The element which will be replaced with new
    1116             :    *                            element.
    1117             :    * @param aTagName            The name of new element node.
    1118             :    * @param aAttribute          Attribute name which will be set to the new
    1119             :    *                            element.  This will be ignored if
    1120             :    *                            aCloneAllAttributes is set to true.
    1121             :    * @param aAttributeValue     Attribute value which will be set to
    1122             :    *                            aAttribute.
    1123             :    * @param aCloneAllAttributes If true, all attributes of aOldContainer will
    1124             :    *                            be copied to the new element.
    1125             :    */
    1126             :   already_AddRefed<Element>
    1127             :   ReplaceContainerWithTransactionInternal(Element& aElement,
    1128             :                                           nsAtom& aTagName,
    1129             :                                           nsAtom& aAttribute,
    1130             :                                           const nsAString& aAttributeValue,
    1131             :                                           bool aCloneAllAttributes);
    1132             : 
    1133             :   /**
    1134             :    * InsertContainerWithTransactionInternal() creates new element whose name is
    1135             :    * aTagName, moves aContent into the new element, then, inserts the new
    1136             :    * element into where aContent was.  If aAttribute is not nsGkAtoms::_empty,
    1137             :    * aAttribute of the new element will be set to aAttributeValue.
    1138             :    *
    1139             :    * @param aContent            The content which will be wrapped with new
    1140             :    *                            element.
    1141             :    * @param aTagName            Element name of new element which will wrap
    1142             :    *                            aContent and be inserted into where aContent
    1143             :    *                            was.
    1144             :    * @param aAttribute          Attribute which should be set to the new
    1145             :    *                            element.  If this is nsGkAtoms::_empty,
    1146             :    *                            this does not set any attributes to the new
    1147             :    *                            element.
    1148             :    * @param aAttributeValue     Value to be set to aAttribute.
    1149             :    * @return                    The new element.
    1150             :    */
    1151             :   already_AddRefed<Element>
    1152             :   InsertContainerWithTransactionInternal(nsIContent& aContent,
    1153             :                                          nsAtom& aTagName,
    1154             :                                          nsAtom& aAttribute,
    1155             :                                          const nsAString& aAttributeValue);
    1156             : 
    1157             :   /**
    1158             :    * DoSplitNode() creates a new node (left node) identical to an existing
    1159             :    * node (right node), and split the contents between the same point in both
    1160             :    * nodes.
    1161             :    *
    1162             :    * @param aStartOfRightNode   The point to split.  Its container will be
    1163             :    *                            the right node, i.e., become the new node's
    1164             :    *                            next sibling.  And the point will be start
    1165             :    *                            of the right node.
    1166             :    * @param aNewLeftNode        The new node called as left node, so, this
    1167             :    *                            becomes the container of aPointToSplit's
    1168             :    *                            previous sibling.
    1169             :    * @param aError              Must have not already failed.
    1170             :    *                            If succeed to insert aLeftNode before the
    1171             :    *                            right node and remove unnecessary contents
    1172             :    *                            (and collapse selection at end of the left
    1173             :    *                            node if necessary), returns no error.
    1174             :    *                            Otherwise, an error.
    1175             :    */
    1176             :   void DoSplitNode(const EditorDOMPoint& aStartOfRightNode,
    1177             :                    nsIContent& aNewLeftNode,
    1178             :                    ErrorResult& aError);
    1179             : 
    1180             :   /**
    1181             :    * DoJoinNodes() merges contents in aNodeToJoin to aNodeToKeep and remove
    1182             :    * aNodeToJoin from the DOM tree.  aNodeToJoin and aNodeToKeep must have
    1183             :    * same parent, aParent.  Additionally, if one of aNodeToJoin or aNodeToKeep
    1184             :    * is a text node, the other must be a text node.
    1185             :    *
    1186             :    * @param aNodeToKeep   The node that will remain after the join.
    1187             :    * @param aNodeToJoin   The node that will be joined with aNodeToKeep.
    1188             :    *                      There is no requirement that the two nodes be of the
    1189             :    *                      same type.
    1190             :    * @param aParent       The parent of aNodeToKeep
    1191             :    */
    1192             :   nsresult DoJoinNodes(nsINode* aNodeToKeep,
    1193             :                        nsINode* aNodeToJoin,
    1194             :                        nsINode* aParent);
    1195             : 
    1196             :   /**
    1197             :    * SplitNodeDeepWithTransaction() splits aMostAncestorToSplit deeply.
    1198             :    *
    1199             :    * @param aMostAncestorToSplit        The most ancestor node which should be
    1200             :    *                                    split.
    1201             :    * @param aStartOfDeepestRightNode    The start point of deepest right node.
    1202             :    *                                    This point must be descendant of
    1203             :    *                                    aMostAncestorToSplit.
    1204             :    * @param aSplitAtEdges               Whether the caller allows this to
    1205             :    *                                    create empty container element when
    1206             :    *                                    split point is start or end of an
    1207             :    *                                    element.
    1208             :    * @return                            SplitPoint() returns split point in
    1209             :    *                                    aMostAncestorToSplit.  The point must
    1210             :    *                                    be good to insert something if the
    1211             :    *                                    caller want to do it.
    1212             :    */
    1213             :   template<typename PT, typename CT>
    1214             :   SplitNodeResult
    1215             :   SplitNodeDeepWithTransaction(
    1216             :     nsIContent& aMostAncestorToSplit,
    1217             :     const EditorDOMPointBase<PT, CT>& aDeepestStartOfRightNode,
    1218             :     SplitAtEdges aSplitAtEdges);
    1219             : 
    1220             :   /**
    1221             :    * JoinNodesDeepWithTransaction() joins aLeftNode and aRightNode "deeply".
    1222             :    * First, they are joined simply, then, new right node is assumed as the
    1223             :    * child at length of the left node before joined and new left node is
    1224             :    * assumed as its previous sibling.  Then, they will be joined again.
    1225             :    * And then, these steps are repeated.
    1226             :    *
    1227             :    * @param aLeftNode   The node which will be removed form the tree.
    1228             :    * @param aRightNode  The node which will be inserted the contents of
    1229             :    *                    aLeftNode.
    1230             :    * @return            The point of the first child of the last right node.
    1231             :    */
    1232             :   EditorDOMPoint JoinNodesDeepWithTransaction(nsIContent& aLeftNode,
    1233             :                                               nsIContent& aRightNode);
    1234             : 
    1235             :   /**
    1236             :    * Note that aSelection is optional and can be nullptr.
    1237             :    */
    1238             :   nsresult DoTransaction(Selection* aSelection,
    1239             :                          nsITransaction* aTxn);
    1240             : 
    1241             :   virtual bool IsBlockNode(nsINode* aNode);
    1242             : 
    1243             :   /**
    1244             :    * Set outOffset to the offset of aChild in the parent.
    1245             :    * Returns the parent of aChild.
    1246             :    */
    1247             :   static nsINode* GetNodeLocation(nsINode* aChild, int32_t* aOffset);
    1248             : 
    1249             :   /**
    1250             :    * Get the previous node.
    1251             :    */
    1252             :   nsIContent* GetPreviousNode(const EditorRawDOMPoint& aPoint)
    1253             :   {
    1254             :     return GetPreviousNodeInternal(aPoint, false, true, false);
    1255             :   }
    1256             :   nsIContent* GetPreviousElementOrText(const EditorRawDOMPoint& aPoint)
    1257             :   {
    1258             :     return GetPreviousNodeInternal(aPoint, false, false, false);
    1259             :   }
    1260           0 :   nsIContent* GetPreviousEditableNode(const EditorRawDOMPoint& aPoint)
    1261             :   {
    1262           0 :     return GetPreviousNodeInternal(aPoint, true, true, false);
    1263             :   }
    1264             :   nsIContent* GetPreviousNodeInBlock(const EditorRawDOMPoint& aPoint)
    1265             :   {
    1266             :     return GetPreviousNodeInternal(aPoint, false, true, true);
    1267             :   }
    1268             :   nsIContent* GetPreviousElementOrTextInBlock(const EditorRawDOMPoint& aPoint)
    1269             :   {
    1270             :     return GetPreviousNodeInternal(aPoint, false, false, true);
    1271             :   }
    1272           0 :   nsIContent* GetPreviousEditableNodeInBlock(
    1273             :                 const EditorRawDOMPoint& aPoint)
    1274             :   {
    1275           0 :     return GetPreviousNodeInternal(aPoint, true, true, true);
    1276             :   }
    1277             :   nsIContent* GetPreviousNode(nsINode& aNode)
    1278             :   {
    1279             :     return GetPreviousNodeInternal(aNode, false, true, false);
    1280             :   }
    1281           0 :   nsIContent* GetPreviousElementOrText(nsINode& aNode)
    1282             :   {
    1283           0 :     return GetPreviousNodeInternal(aNode, false, false, false);
    1284             :   }
    1285           0 :   nsIContent* GetPreviousEditableNode(nsINode& aNode)
    1286             :   {
    1287           0 :     return GetPreviousNodeInternal(aNode, true, true, false);
    1288             :   }
    1289             :   nsIContent* GetPreviousNodeInBlock(nsINode& aNode)
    1290             :   {
    1291             :     return GetPreviousNodeInternal(aNode, false, true, true);
    1292             :   }
    1293           0 :   nsIContent* GetPreviousElementOrTextInBlock(nsINode& aNode)
    1294             :   {
    1295           0 :     return GetPreviousNodeInternal(aNode, false, false, true);
    1296             :   }
    1297           0 :   nsIContent* GetPreviousEditableNodeInBlock(nsINode& aNode)
    1298             :   {
    1299           0 :     return GetPreviousNodeInternal(aNode, true, true, true);
    1300             :   }
    1301             : 
    1302             :   /**
    1303             :    * Get the next node.
    1304             :    *
    1305             :    * Note that methods taking EditorRawDOMPoint behavior includes the
    1306             :    * child at offset as search target.  E.g., following code causes infinite
    1307             :    * loop.
    1308             :    *
    1309             :    * EditorRawDOMPoint point(aEditableNode);
    1310             :    * while (nsIContent* content = GetNextEditableNode(point)) {
    1311             :    *   // Do something...
    1312             :    *   point.Set(content);
    1313             :    * }
    1314             :    *
    1315             :    * Following code must be you expected:
    1316             :    *
    1317             :    * while (nsIContent* content = GetNextEditableNode(point)) {
    1318             :    *   // Do something...
    1319             :    *   DebugOnly<bool> advanced = point.Advanced();
    1320             :    *   MOZ_ASSERT(advanced);
    1321             :    *   point.Set(point.GetChild());
    1322             :    * }
    1323             :    *
    1324             :    * On the other hand, the methods taking nsINode behavior must be what
    1325             :    * you want.  They start to search the result from next node of the given
    1326             :    * node.
    1327             :    */
    1328             :   template<typename PT, typename CT>
    1329           0 :   nsIContent* GetNextNode(const EditorDOMPointBase<PT, CT>& aPoint)
    1330             :   {
    1331           0 :     return GetNextNodeInternal(aPoint, false, true, false);
    1332             :   }
    1333             :   template<typename PT, typename CT>
    1334             :   nsIContent* GetNextElementOrText(const EditorDOMPointBase<PT, CT>& aPoint)
    1335             :   {
    1336             :     return GetNextNodeInternal(aPoint, false, false, false);
    1337             :   }
    1338             :   template<typename PT, typename CT>
    1339           0 :   nsIContent* GetNextEditableNode(const EditorDOMPointBase<PT, CT>& aPoint)
    1340             :   {
    1341           0 :     return GetNextNodeInternal(aPoint, true, true, false);
    1342             :   }
    1343             :   template<typename PT, typename CT>
    1344             :   nsIContent* GetNextNodeInBlock(const EditorDOMPointBase<PT, CT>& aPoint)
    1345             :   {
    1346             :     return GetNextNodeInternal(aPoint, false, true, true);
    1347             :   }
    1348             :   template<typename PT, typename CT>
    1349             :   nsIContent* GetNextElementOrTextInBlock(
    1350             :                 const EditorDOMPointBase<PT, CT>& aPoint)
    1351             :   {
    1352             :     return GetNextNodeInternal(aPoint, false, false, true);
    1353             :   }
    1354             :   template<typename PT, typename CT>
    1355           0 :   nsIContent* GetNextEditableNodeInBlock(
    1356             :                 const EditorDOMPointBase<PT, CT>& aPoint)
    1357             :   {
    1358           0 :     return GetNextNodeInternal(aPoint, true, true, true);
    1359             :   }
    1360             :   nsIContent* GetNextNode(nsINode& aNode)
    1361             :   {
    1362             :     return GetNextNodeInternal(aNode, false, true, false);
    1363             :   }
    1364           0 :   nsIContent* GetNextElementOrText(nsINode& aNode)
    1365             :   {
    1366           0 :     return GetNextNodeInternal(aNode, false, false, false);
    1367             :   }
    1368           0 :   nsIContent* GetNextEditableNode(nsINode& aNode)
    1369             :   {
    1370           0 :     return GetNextNodeInternal(aNode, true, true, false);
    1371             :   }
    1372             :   nsIContent* GetNextNodeInBlock(nsINode& aNode)
    1373             :   {
    1374             :     return GetNextNodeInternal(aNode, false, true, true);
    1375             :   }
    1376           0 :   nsIContent* GetNextElementOrTextInBlock(nsINode& aNode)
    1377             :   {
    1378           0 :     return GetNextNodeInternal(aNode, false, false, true);
    1379             :   }
    1380           0 :   nsIContent* GetNextEditableNodeInBlock(nsINode& aNode)
    1381             :   {
    1382           0 :     return GetNextNodeInternal(aNode, true, true, true);
    1383             :   }
    1384             : 
    1385             :   /**
    1386             :    * Get the rightmost child of aCurrentNode;
    1387             :    * return nullptr if aCurrentNode has no children.
    1388             :    */
    1389             :   nsIContent* GetRightmostChild(nsINode* aCurrentNode,
    1390             :                                 bool bNoBlockCrossing = false);
    1391             : 
    1392             :   /**
    1393             :    * Get the leftmost child of aCurrentNode;
    1394             :    * return nullptr if aCurrentNode has no children.
    1395             :    */
    1396             :   nsIContent* GetLeftmostChild(nsINode *aCurrentNode,
    1397             :                                bool bNoBlockCrossing = false);
    1398             : 
    1399             :   /**
    1400             :    * Returns true if aParent can contain a child of type aTag.
    1401             :    */
    1402             :   bool CanContain(nsINode& aParent, nsIContent& aChild) const;
    1403             :   bool CanContainTag(nsINode& aParent, nsAtom& aTag) const;
    1404             :   bool TagCanContain(nsAtom& aParentTag, nsIContent& aChild) const;
    1405             :   virtual bool TagCanContainTag(nsAtom& aParentTag, nsAtom& aChildTag) const;
    1406             : 
    1407             :   /**
    1408             :    * Returns true if aNode is our root node.
    1409             :    */
    1410             :   bool IsRoot(nsINode* inNode);
    1411             :   bool IsEditorRoot(nsINode* aNode);
    1412             : 
    1413             :   /**
    1414             :    * Returns true if aNode is a descendant of our root node.
    1415             :    */
    1416             :   bool IsDescendantOfRoot(nsINode* inNode);
    1417             :   bool IsDescendantOfEditorRoot(nsINode* aNode);
    1418             : 
    1419             :   /**
    1420             :    * Returns true if aNode is a container.
    1421             :    */
    1422             :   virtual bool IsContainer(nsINode* aNode);
    1423             : 
    1424             :   /**
    1425             :    * returns true if aNode is an editable node.
    1426             :    */
    1427           6 :   bool IsEditable(nsINode* aNode)
    1428             :   {
    1429           0 :     NS_ENSURE_TRUE(aNode, false);
    1430             : 
    1431           0 :     if (!aNode->IsContent() || IsMozEditorBogusNode(aNode) ||
    1432           6 :         !IsModifiableNode(aNode)) {
    1433             :       return false;
    1434             :     }
    1435             : 
    1436           6 :     switch (aNode->NodeType()) {
    1437             :       case nsINode::ELEMENT_NODE:
    1438             :         // In HTML editors, if we're dealing with an element, then ask it
    1439             :         // whether it's editable.
    1440           6 :         return mIsHTMLEditorClass ? aNode->IsEditable() : true;
    1441             :       case nsINode::TEXT_NODE:
    1442             :         // Text nodes are considered to be editable by both typed of editors.
    1443             :         return true;
    1444             :       default:
    1445           0 :         return false;
    1446             :     }
    1447             :   }
    1448             : 
    1449             :   /**
    1450             :    * Returns true if aNode is a usual element node (not bogus node) or
    1451             :    * a text node.  In other words, returns true if aNode is a usual element
    1452             :    * node or visible data node.
    1453             :    */
    1454           0 :   bool IsElementOrText(const nsINode& aNode) const
    1455             :   {
    1456           0 :     if (!aNode.IsContent() || IsMozEditorBogusNode(&aNode)) {
    1457             :       return false;
    1458             :     }
    1459           0 :     return aNode.NodeType() == nsINode::ELEMENT_NODE ||
    1460           0 :            aNode.NodeType() == nsINode::TEXT_NODE;
    1461             :   }
    1462             : 
    1463             :   /**
    1464             :    * Returns true if aNode is a MozEditorBogus node.
    1465             :    */
    1466           6 :   bool IsMozEditorBogusNode(const nsINode* aNode) const
    1467             :   {
    1468           0 :     return aNode && aNode->IsElement() &&
    1469           6 :            aNode->AsElement()->AttrValueIs(kNameSpaceID_None,
    1470             :                kMOZEditorBogusNodeAttrAtom, kMOZEditorBogusNodeValue,
    1471           0 :                eCaseMatters);
    1472             :   }
    1473             : 
    1474             :   /**
    1475             :    * Counts number of editable child nodes.
    1476             :    */
    1477             :   uint32_t CountEditableChildren(nsINode* aNode);
    1478             : 
    1479             :   /**
    1480             :    * Find the deep first and last children.
    1481             :    */
    1482             :   nsINode* GetFirstEditableNode(nsINode* aRoot);
    1483             : 
    1484             :   /**
    1485             :    * Returns true when inserting text should be a part of current composition.
    1486             :    */
    1487             :   bool ShouldHandleIMEComposition() const;
    1488             : 
    1489             :   /**
    1490             :    * From html rules code - migration in progress.
    1491             :    */
    1492             :   virtual bool AreNodesSameType(nsIContent* aNode1, nsIContent* aNode2);
    1493             : 
    1494           0 :   static bool IsTextNode(nsINode* aNode)
    1495             :   {
    1496           0 :     return aNode->NodeType() == nsINode::TEXT_NODE;
    1497             :   }
    1498             : 
    1499             :   virtual bool IsModifiableNode(nsINode* aNode);
    1500             : 
    1501             :   /**
    1502             :    * GetNodeAtRangeOffsetPoint() returns the node at this position in a range,
    1503             :    * assuming that the container is the node itself if it's a text node, or
    1504             :    * the node's parent otherwise.
    1505             :    */
    1506             :   static nsIContent* GetNodeAtRangeOffsetPoint(nsINode* aContainer,
    1507             :                                                int32_t aOffset)
    1508             :   {
    1509             :     return GetNodeAtRangeOffsetPoint(RawRangeBoundary(aContainer, aOffset));
    1510             :   }
    1511             :   static nsIContent* GetNodeAtRangeOffsetPoint(const RawRangeBoundary& aPoint);
    1512             : 
    1513             :   static EditorRawDOMPoint GetStartPoint(Selection* aSelection);
    1514             :   static EditorRawDOMPoint GetEndPoint(Selection* aSelection);
    1515             : 
    1516             :   static nsresult GetEndChildNode(Selection* aSelection,
    1517             :                                   nsIContent** aEndNode);
    1518             : 
    1519             :   /**
    1520             :    * CollapseSelectionToEnd() collapses the selection to the end of the editor.
    1521             :    */
    1522             :   nsresult CollapseSelectionToEnd(Selection* aSelection);
    1523             : 
    1524             :   /**
    1525             :    * Helpers to add a node to the selection.
    1526             :    * Used by table cell selection methods.
    1527             :    */
    1528             :   nsresult CreateRange(nsINode* aStartContainer, int32_t aStartOffset,
    1529             :                        nsINode* aEndContainer, int32_t aEndOffset,
    1530             :                        nsRange** aRange);
    1531             : 
    1532             :   static bool IsPreformatted(nsINode* aNode);
    1533             : 
    1534             :   bool GetShouldTxnSetSelection();
    1535             : 
    1536             :   nsresult HandleInlineSpellCheck(EditSubAction aEditSubAction,
    1537             :                                   Selection& aSelection,
    1538             :                                   nsINode* previousSelectedNode,
    1539             :                                   uint32_t previousSelectedOffset,
    1540             :                                   nsINode* aStartContainer,
    1541             :                                   uint32_t aStartOffset,
    1542             :                                   nsINode* aEndContainer,
    1543             :                                   uint32_t aEndOffset);
    1544             : 
    1545             :   /**
    1546             :    * Likewise, but gets the editor's root instead, which is different for HTML
    1547             :    * editors.
    1548             :    */
    1549             :   virtual Element* GetEditorRoot();
    1550             : 
    1551             :   /**
    1552             :    * Likewise, but gets the text control element instead of the root for
    1553             :    * plaintext editors.
    1554             :    */
    1555             :   Element* GetExposedRoot();
    1556             : 
    1557             :   /**
    1558             :    * Whether the editor is active on the DOM window.  Note that when this
    1559             :    * returns true but GetFocusedContent() returns null, it means that this editor was
    1560             :    * focused when the DOM window was active.
    1561             :    */
    1562             :   virtual bool IsActiveInDOMWindow();
    1563             : 
    1564             :   /**
    1565             :    * GetIMESelectionStartOffsetIn() returns the start offset of IME selection in
    1566             :    * the aTextNode.  If there is no IME selection, returns -1.
    1567             :    */
    1568             :   int32_t GetIMESelectionStartOffsetIn(nsINode* aTextNode);
    1569             : 
    1570             :   /**
    1571             :    * FindBetterInsertionPoint() tries to look for better insertion point which
    1572             :    * is typically the nearest text node and offset in it.
    1573             :    *
    1574             :    * @param aPoint      Insertion point which the callers found.
    1575             :    * @return            Better insertion point if there is.  If not returns
    1576             :    *                    same point as aPoint.
    1577             :    */
    1578             :   EditorRawDOMPoint FindBetterInsertionPoint(const EditorRawDOMPoint& aPoint);
    1579             : 
    1580             :   /**
    1581             :    * HideCaret() hides caret with nsCaret::AddForceHide() or may show carent
    1582             :    * with nsCaret::RemoveForceHide().  This does NOT set visibility of
    1583             :    * nsCaret.  Therefore, this is stateless.
    1584             :    */
    1585             :   void HideCaret(bool aHide);
    1586             : 
    1587             : protected: // Called by helper classes.
    1588             : 
    1589             :   /**
    1590             :    * OnStartToHandleTopLevelEditSubAction() is called when
    1591             :    * mTopLevelEditSubAction is EditSubAction::eNone and somebody starts to
    1592             :    * handle aEditSubAction.
    1593             :    *
    1594             :    * @param aEditSubAction      Top level edit sub action which will be
    1595             :    *                            handled soon.
    1596             :    * @param aDirection          Direction of aEditSubAction.
    1597             :    */
    1598             :   virtual void
    1599             :   OnStartToHandleTopLevelEditSubAction(EditSubAction aEditSubAction,
    1600             :                                        nsIEditor::EDirection aDirection);
    1601             : 
    1602             :   /**
    1603             :    * OnEndHandlingTopLevelEditSubAction() is called after
    1604             :    * mTopLevelEditSubAction is handled.
    1605             :    */
    1606             :   virtual void OnEndHandlingTopLevelEditSubAction();
    1607             : 
    1608             :   /**
    1609             :    * Routines for managing the preservation of selection across
    1610             :    * various editor actions.
    1611             :    */
    1612             :   bool ArePreservingSelection();
    1613             :   void PreserveSelectionAcrossActions(Selection* aSel);
    1614             :   nsresult RestorePreservedSelection(Selection* aSel);
    1615             :   void StopPreservingSelection();
    1616             : 
    1617             :   /**
    1618             :    * (Begin|End)PlaceholderTransaction() are called by AutoPlaceholderBatch.
    1619             :    * This set of methods are similar to the (Begin|End)Transaction(), but do
    1620             :    * not use the transaction managers batching feature.  Instead we use a
    1621             :    * placeholder transaction to wrap up any further transaction while the
    1622             :    * batch is open.  The advantage of this is that placeholder transactions
    1623             :    * can later merge, if needed.  Merging is unavailable between transaction
    1624             :    * manager batches.
    1625             :    */
    1626             :   void BeginPlaceholderTransaction(nsAtom* aTransactionName);
    1627             :   void EndPlaceholderTransaction();
    1628             : 
    1629             :   void BeginUpdateViewBatch();
    1630             :   virtual nsresult EndUpdateViewBatch();
    1631             : 
    1632             : protected: // Shouldn't be used by friend classes
    1633             :   /**
    1634             :    * The default destructor. This should suffice. Should this be pure virtual
    1635             :    * for someone to derive from the EditorBase later? I don't believe so.
    1636             :    */
    1637             :   virtual ~EditorBase();
    1638             : 
    1639             :   /**
    1640             :    * SelectAllInternal() should be used instead of SelectAll() in editor
    1641             :    * because SelectAll() creates AutoEditActionSetter but we should avoid
    1642             :    * to create it as far as possible.
    1643             :    */
    1644             :   virtual nsresult SelectAllInternal();
    1645             : 
    1646             :   nsresult DetermineCurrentDirection();
    1647             :   void FireInputEvent();
    1648             : 
    1649             :   /**
    1650             :    * Called after a transaction is done successfully.
    1651             :    */
    1652             :   void DoAfterDoTransaction(nsITransaction *aTxn);
    1653             : 
    1654             :   /**
    1655             :    * Called after a transaction is undone successfully.
    1656             :    */
    1657             : 
    1658             :   void DoAfterUndoTransaction();
    1659             : 
    1660             :   /**
    1661             :    * Called after a transaction is redone successfully.
    1662             :    */
    1663             :   void DoAfterRedoTransaction();
    1664             : 
    1665             :   /**
    1666             :    * Tell the doc state listeners that the doc state has changed.
    1667             :    */
    1668             :   enum TDocumentListenerNotification
    1669             :   {
    1670             :     eDocumentCreated,
    1671             :     eDocumentToBeDestroyed,
    1672             :     eDocumentStateChanged
    1673             :   };
    1674             :   nsresult NotifyDocumentListeners(
    1675             :              TDocumentListenerNotification aNotificationType);
    1676             : 
    1677             :   /**
    1678             :    * Make the given selection span the entire document.
    1679             :    */
    1680             :   virtual nsresult SelectEntireDocument(Selection* aSelection);
    1681             : 
    1682             :   /**
    1683             :    * Helper method for scrolling the selection into view after
    1684             :    * an edit operation. aScrollToAnchor should be true if you
    1685             :    * want to scroll to the point where the selection was started.
    1686             :    * If false, it attempts to scroll the end of the selection into view.
    1687             :    *
    1688             :    * Editor methods *should* call this method instead of the versions
    1689             :    * in the various selection interfaces, since this version makes sure
    1690             :    * that the editor's sync/async settings for reflowing, painting, and
    1691             :    * scrolling match.
    1692             :    */
    1693             :   nsresult ScrollSelectionIntoView(bool aScrollToAnchor);
    1694             : 
    1695             :   /**
    1696             :    * Helper for GetPreviousNodeInternal() and GetNextNodeInternal().
    1697             :    */
    1698             :   nsIContent* FindNextLeafNode(nsINode* aCurrentNode,
    1699             :                                bool aGoForward,
    1700             :                                bool bNoBlockCrossing);
    1701             :   nsIContent* FindNode(nsINode* aCurrentNode,
    1702             :                        bool aGoForward,
    1703             :                        bool aEditableNode,
    1704             :                        bool aFindAnyDataNode,
    1705             :                        bool bNoBlockCrossing);
    1706             : 
    1707             :   /**
    1708             :    * Get the node immediately previous node of aNode.
    1709             :    * @param atNode               The node from which we start the search.
    1710             :    * @param aFindEditableNode    If true, only return an editable node.
    1711             :    * @param aFindAnyDataNode     If true, may return invisible data node
    1712             :    *                             like Comment.
    1713             :    * @param aNoBlockCrossing     If true, don't move across "block" nodes,
    1714             :    *                             whatever that means.
    1715             :    * @return                     The node that occurs before aNode in
    1716             :    *                             the tree, skipping non-editable nodes if
    1717             :    *                             aFindEditableNode is true.  If there is no
    1718             :    *                             previous node, returns nullptr.
    1719             :    */
    1720             :   nsIContent* GetPreviousNodeInternal(nsINode& aNode,
    1721             :                                       bool aFindEditableNode,
    1722             :                                       bool aFindAnyDataNode,
    1723             :                                       bool aNoBlockCrossing);
    1724             : 
    1725             :   /**
    1726             :    * And another version that takes a point in DOM tree rather than a node.
    1727             :    */
    1728             :   nsIContent* GetPreviousNodeInternal(const EditorRawDOMPoint& aPoint,
    1729             :                                       bool aFindEditableNode,
    1730             :                                       bool aFindAnyDataNode,
    1731             :                                       bool aNoBlockCrossing);
    1732             : 
    1733             :   /**
    1734             :    * Get the node immediately next node of aNode.
    1735             :    * @param aNode                The node from which we start the search.
    1736             :    * @param aFindEditableNode    If true, only return an editable node.
    1737             :    * @param aFindAnyDataNode     If true, may return invisible data node
    1738             :    *                             like Comment.
    1739             :    * @param aNoBlockCrossing     If true, don't move across "block" nodes,
    1740             :    *                             whatever that means.
    1741             :    * @return                     The node that occurs after aNode in the
    1742             :    *                             tree, skipping non-editable nodes if
    1743             :    *                             aFindEditableNode is true.  If there is no
    1744             :    *                             next node, returns nullptr.
    1745             :    */
    1746             :   nsIContent* GetNextNodeInternal(nsINode& aNode,
    1747             :                                   bool aFindEditableNode,
    1748             :                                   bool aFindAnyDataNode,
    1749             :                                   bool bNoBlockCrossing);
    1750             : 
    1751             :   /**
    1752             :    * And another version that takes a point in DOM tree rather than a node.
    1753             :    */
    1754             :   nsIContent* GetNextNodeInternal(const EditorRawDOMPoint& aPoint,
    1755             :                                   bool aFindEditableNode,
    1756             :                                   bool aFindAnyDataNode,
    1757             :                                   bool aNoBlockCrossing);
    1758             : 
    1759             : 
    1760             :   virtual nsresult InstallEventListeners();
    1761             :   virtual void CreateEventListeners();
    1762             :   virtual void RemoveEventListeners();
    1763             : 
    1764             :   /**
    1765             :    * Get the input event target. This might return null.
    1766             :    */
    1767             :   virtual already_AddRefed<nsIContent> GetInputEventTargetContent() = 0;
    1768             : 
    1769             :   /**
    1770             :    * Return true if spellchecking should be enabled for this editor.
    1771             :    */
    1772             :   bool GetDesiredSpellCheckState();
    1773             : 
    1774             :   bool CanEnableSpellCheck()
    1775             :   {
    1776             :     // Check for password/readonly/disabled, which are not spellchecked
    1777             :     // regardless of DOM. Also, check to see if spell check should be skipped
    1778             :     // or not.
    1779             :     return !IsPasswordEditor() && !IsReadonly() && !IsDisabled() &&
    1780             :            !ShouldSkipSpellCheck();
    1781             :   }
    1782             : 
    1783             :   /**
    1784             :    * InitializeSelectionAncestorLimit() is called by InitializeSelection().
    1785             :    * When this is called, each implementation has to call
    1786             :    * aSelection.SetAncestorLimiter() with aAnotherLimit.
    1787             :    *
    1788             :    * @param aSelection          The selection.
    1789             :    * @param aAncestorLimit      New ancestor limit of aSelection.  This always
    1790             :    *                            has parent node.  So, it's always safe to
    1791             :    *                            call SetAncestorLimit() with this node.
    1792             :    */
    1793             :   virtual void InitializeSelectionAncestorLimit(Selection& aSelection,
    1794             :                                                 nsIContent& aAncestorLimit);
    1795             : 
    1796             :   /**
    1797             :    * Return the offset of aChild in aParent.  Asserts fatally if parent or
    1798             :    * child is null, or parent is not child's parent.
    1799             :    * FYI: aChild must not be being removed from aParent.  In such case, these
    1800             :    *      methods may return wrong index if aChild doesn't have previous
    1801             :    *      sibling or next sibling.
    1802             :    */
    1803             :   static int32_t GetChildOffset(nsINode* aChild,
    1804             :                                 nsINode* aParent);
    1805             : 
    1806             :   /**
    1807             :    * Creates a range with just the supplied node and appends that to the
    1808             :    * selection.
    1809             :    */
    1810             :   nsresult AppendNodeToSelectionAsRange(nsINode* aNode);
    1811             : 
    1812             :   /**
    1813             :    * When you are using AppendNodeToSelectionAsRange(), call this first to
    1814             :    * start a new selection.
    1815             :    */
    1816             :   nsresult ClearSelection();
    1817             : 
    1818             :   /**
    1819             :    * Initializes selection and caret for the editor.  If aEventTarget isn't
    1820             :    * a host of the editor, i.e., the editor doesn't get focus, this does
    1821             :    * nothing.
    1822             :    */
    1823             :   nsresult InitializeSelection(dom::EventTarget* aFocusEventTarget);
    1824             : 
    1825             :   /**
    1826             :    * Used to insert content from a data transfer into the editable area.
    1827             :    * This is called for each item in the data transfer, with the index of
    1828             :    * each item passed as aIndex.
    1829             :    */
    1830             :   virtual nsresult InsertFromDataTransfer(dom::DataTransfer* aDataTransfer,
    1831             :                                           int32_t aIndex,
    1832             :                                           nsIDocument* aSourceDoc,
    1833             :                                           nsINode* aDestinationNode,
    1834             :                                           int32_t aDestOffset,
    1835             :                                           bool aDoDeleteSelection) = 0;
    1836             : 
    1837             :   enum NotificationForEditorObservers
    1838             :   {
    1839             :     eNotifyEditorObserversOfEnd,
    1840             :     eNotifyEditorObserversOfBefore,
    1841             :     eNotifyEditorObserversOfCancel
    1842             :   };
    1843             :   void NotifyEditorObservers(NotificationForEditorObservers aNotification);
    1844             : 
    1845             : private:
    1846             :   nsCOMPtr<nsISelectionController> mSelectionController;
    1847             :   nsCOMPtr<nsIDocument> mDocument;
    1848             : 
    1849             : 
    1850             :   /**
    1851             :    * SetTextDirectionTo() sets text-direction of the root element.
    1852             :    * Should use SwitchTextDirectionTo() or ToggleTextDirection() instead.
    1853             :    * This is a helper class of them.
    1854             :    */
    1855             :   nsresult SetTextDirectionTo(TextDirection aTextDirection);
    1856             : protected:
    1857             :   enum Tristate
    1858             :   {
    1859             :     eTriUnset,
    1860             :     eTriFalse,
    1861             :     eTriTrue
    1862             :   };
    1863             : 
    1864             :   // MIME type of the doc we are editing.
    1865             :   nsCString mContentMIMEType;
    1866             : 
    1867             :   RefPtr<mozInlineSpellChecker> mInlineSpellChecker;
    1868             :   // Reference to text services document for mInlineSpellChecker.
    1869             :   RefPtr<TextServicesDocument> mTextServicesDocument;
    1870             : 
    1871             :   RefPtr<TransactionManager> mTransactionManager;
    1872             :   // Cached root node.
    1873             :   RefPtr<Element> mRootElement;
    1874             :   // The form field as an event receiver.
    1875             :   nsCOMPtr<dom::EventTarget> mEventTarget;
    1876             :   RefPtr<EditorEventListener> mEventListener;
    1877             :   // Strong reference to placeholder for begin/end batch purposes.
    1878             :   RefPtr<PlaceholderTransaction> mPlaceholderTransaction;
    1879             :   // Name of placeholder transaction.
    1880             :   nsAtom* mPlaceholderName;
    1881             :   // Saved selection state for placeholder transaction batching.
    1882             :   mozilla::Maybe<SelectionState> mSelState;
    1883             :   // IME composition this is not null between compositionstart and
    1884             :   // compositionend.
    1885             :   RefPtr<TextComposition> mComposition;
    1886             : 
    1887             :   RefPtr<TextEditRules> mRules;
    1888             : 
    1889             :   RefPtr<TextInputListener> mTextInputListener;
    1890             : 
    1891             :   RefPtr<IMEContentObserver> mIMEContentObserver;
    1892             : 
    1893             :   // Listens to all low level actions on the doc.
    1894             :   typedef AutoTArray<OwningNonNull<nsIEditActionListener>, 5>
    1895             :             AutoActionListenerArray;
    1896             :   AutoActionListenerArray mActionListeners;
    1897             :   // Just notify once per high level change.
    1898             :   typedef AutoTArray<OwningNonNull<nsIEditorObserver>, 3>
    1899             :             AutoEditorObserverArray;
    1900             :   AutoEditorObserverArray mEditorObservers;
    1901             :   // Listen to overall doc state (dirty or not, just created, etc.).
    1902             :   typedef AutoTArray<OwningNonNull<nsIDocumentStateListener>, 1>
    1903             :             AutoDocumentStateListenerArray;
    1904             :   AutoDocumentStateListenerArray mDocStateListeners;
    1905             : 
    1906             :   // Cached selection for AutoSelectionRestorer.
    1907             :   SelectionState mSavedSel;
    1908             :   // Utility class object for maintaining preserved ranges.
    1909             :   RangeUpdater mRangeUpdater;
    1910             : 
    1911             :   // Number of modifications (for undo/redo stack).
    1912             :   uint32_t mModCount;
    1913             :   // Behavior flags. See nsIPlaintextEditor.idl for the flags we use.
    1914             :   uint32_t mFlags;
    1915             : 
    1916             :   int32_t mUpdateCount;
    1917             : 
    1918             :   // Nesting count for batching.
    1919             :   int32_t mPlaceholderBatch;
    1920             :   // The top level edit sub-action.
    1921             :   EditSubAction mTopLevelEditSubAction;
    1922             : 
    1923             :   // The top level edit sub-action's direction.
    1924             :   EDirection mDirection;
    1925             :   // -1 = not initialized
    1926             :   int8_t mDocDirtyState;
    1927             :   // A Tristate value.
    1928             :   uint8_t mSpellcheckCheckboxState;
    1929             : 
    1930             :   // Turn off for conservative selection adjustment by transactions.
    1931             :   bool mShouldTxnSetSelection;
    1932             :   // Whether PreDestroy has been called.
    1933             :   bool mDidPreDestroy;
    1934             :   // Whether PostCreate has been called.
    1935             :   bool mDidPostCreate;
    1936             :   bool mDispatchInputEvent;
    1937             :   // True while the instance is handling an edit sub-action.
    1938             :   bool mIsInEditSubAction;
    1939             :   // Whether caret is hidden forcibly.
    1940             :   bool mHidingCaret;
    1941             :   // Whether spellchecker dictionary is initialized after focused.
    1942             :   bool mSpellCheckerDictionaryUpdated;
    1943             :   // Whether we are an HTML editor class.
    1944             :   bool mIsHTMLEditorClass;
    1945             : 
    1946             :   friend class AutoPlaceholderBatch;
    1947             :   friend class AutoSelectionRestorer;
    1948             :   friend class AutoTopLevelEditSubActionNotifier;
    1949             :   friend class AutoTransactionsConserveSelection;
    1950             :   friend class AutoUpdateViewBatch;
    1951             :   friend class CompositionTransaction;
    1952             :   friend class CreateElementTransaction;
    1953             :   friend class CSSEditUtils;
    1954             :   friend class DeleteNodeTransaction;
    1955             :   friend class DeleteTextTransaction;
    1956             :   friend class HTMLEditRules;
    1957             :   friend class HTMLEditUtils;
    1958             :   friend class InsertNodeTransaction;
    1959             :   friend class InsertTextTransaction;
    1960             :   friend class JoinNodeTransaction;
    1961             :   friend class SplitNodeTransaction;
    1962             :   friend class TextEditRules;
    1963             :   friend class TypeInState;
    1964             :   friend class WSRunObject;
    1965             :   friend class nsIEditor;
    1966             : };
    1967             : 
    1968             : } // namespace mozilla
    1969             : 
    1970             : mozilla::EditorBase*
    1971             : nsIEditor::AsEditorBase()
    1972             : {
    1973             :   return static_cast<mozilla::EditorBase*>(this);
    1974             : }
    1975             : 
    1976             : const mozilla::EditorBase*
    1977             : nsIEditor::AsEditorBase() const
    1978             : {
    1979             :   return static_cast<const mozilla::EditorBase*>(this);
    1980             : }
    1981             : 
    1982             : #endif // #ifndef mozilla_EditorBase_h

Generated by: LCOV version 1.13-14-ga5dd952