EditorBase.h 37 KB

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