editor/libeditor/base/nsEditor.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial