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