/work/obj-fuzz/dist/include/mozilla/HTMLEditor.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
3 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
4 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
5 | | |
6 | | #ifndef mozilla_HTMLEditor_h |
7 | | #define mozilla_HTMLEditor_h |
8 | | |
9 | | #include "mozilla/Attributes.h" |
10 | | #include "mozilla/ComposerCommandsUpdater.h" |
11 | | #include "mozilla/CSSEditUtils.h" |
12 | | #include "mozilla/ManualNAC.h" |
13 | | #include "mozilla/StyleSheet.h" |
14 | | #include "mozilla/TextEditor.h" |
15 | | #include "mozilla/UniquePtr.h" |
16 | | #include "mozilla/dom/Element.h" |
17 | | #include "mozilla/dom/File.h" |
18 | | |
19 | | #include "nsAttrName.h" |
20 | | #include "nsCOMPtr.h" |
21 | | #include "nsICSSLoaderObserver.h" |
22 | | #include "nsIDocumentObserver.h" |
23 | | #include "nsIDOMEventListener.h" |
24 | | #include "nsIEditorMailSupport.h" |
25 | | #include "nsIEditorStyleSheets.h" |
26 | | #include "nsIHTMLAbsPosEditor.h" |
27 | | #include "nsIHTMLEditor.h" |
28 | | #include "nsIHTMLInlineTableEditor.h" |
29 | | #include "nsIHTMLObjectResizer.h" |
30 | | #include "nsITableEditor.h" |
31 | | #include "nsPoint.h" |
32 | | #include "nsStubMutationObserver.h" |
33 | | #include "nsTArray.h" |
34 | | |
35 | | class nsDocumentFragment; |
36 | | class nsHTMLDocument; |
37 | | class nsITransferable; |
38 | | class nsIClipboard; |
39 | | class nsILinkHandler; |
40 | | class nsTableWrapperFrame; |
41 | | class nsRange; |
42 | | |
43 | | namespace mozilla { |
44 | | class AutoSelectionSetterAfterTableEdit; |
45 | | class DocumentResizeEventListener; |
46 | | class EmptyEditableFunctor; |
47 | | class ResizerSelectionListener; |
48 | | enum class EditSubAction : int32_t; |
49 | | struct PropItem; |
50 | | template<class T> class OwningNonNull; |
51 | | namespace dom { |
52 | | class Blob; |
53 | | class DocumentFragment; |
54 | | class Event; |
55 | | class MouseEvent; |
56 | | } // namespace dom |
57 | | namespace widget { |
58 | | struct IMEState; |
59 | | } // namespace widget |
60 | | |
61 | | enum class ParagraphSeparator { div, p, br }; |
62 | | |
63 | | /** |
64 | | * The HTML editor implementation.<br> |
65 | | * Use to edit HTML document represented as a DOM tree. |
66 | | */ |
67 | | class HTMLEditor final : public TextEditor |
68 | | , public nsIHTMLEditor |
69 | | , public nsIHTMLObjectResizer |
70 | | , public nsIHTMLAbsPosEditor |
71 | | , public nsITableEditor |
72 | | , public nsIHTMLInlineTableEditor |
73 | | , public nsIEditorStyleSheets |
74 | | , public nsStubMutationObserver |
75 | | , public nsIEditorMailSupport |
76 | | { |
77 | | public: |
78 | | /**************************************************************************** |
79 | | * NOTE: DO NOT MAKE YOUR NEW METHODS PUBLIC IF they are called by other |
80 | | * classes under libeditor except EditorEventListener and |
81 | | * HTMLEditorEventListener because each public method which may fire |
82 | | * eEditorInput event will need to instantiate new stack class for |
83 | | * managing input type value of eEditorInput and cache some objects |
84 | | * for smarter handling. In other words, when you add new root |
85 | | * method to edit the DOM tree, you can make your new method public. |
86 | | ****************************************************************************/ |
87 | | |
88 | | NS_DECL_ISUPPORTS_INHERITED |
89 | | NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLEditor, TextEditor) |
90 | | |
91 | | // nsStubMutationObserver overrides |
92 | | NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED |
93 | | NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED |
94 | | NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED |
95 | | |
96 | | // nsIHTMLEditor methods |
97 | | NS_DECL_NSIHTMLEDITOR |
98 | | |
99 | | // nsIHTMLObjectResizer methods (implemented in HTMLObjectResizer.cpp) |
100 | | NS_DECL_NSIHTMLOBJECTRESIZER |
101 | | |
102 | | // nsIHTMLAbsPosEditor methods (implemented in HTMLAbsPositionEditor.cpp) |
103 | | NS_DECL_NSIHTMLABSPOSEDITOR |
104 | | |
105 | | // nsIHTMLInlineTableEditor methods (implemented in HTMLInlineTableEditor.cpp) |
106 | | NS_DECL_NSIHTMLINLINETABLEEDITOR |
107 | | |
108 | | // nsIEditorStyleSheets methods |
109 | | NS_DECL_NSIEDITORSTYLESHEETS |
110 | | |
111 | | // nsIEditorMailSupport methods |
112 | | NS_DECL_NSIEDITORMAILSUPPORT |
113 | | |
114 | | // nsITableEditor methods |
115 | | NS_DECL_NSITABLEEDITOR |
116 | | |
117 | | // nsISelectionListener overrides |
118 | | NS_DECL_NSISELECTIONLISTENER |
119 | | |
120 | | HTMLEditor(); |
121 | | |
122 | | nsHTMLDocument* GetHTMLDocument() const; |
123 | | |
124 | | virtual void PreDestroy(bool aDestroyingFrames) override; |
125 | | |
126 | | bool GetReturnInParagraphCreatesNewParagraph(); |
127 | | |
128 | | // TextEditor overrides |
129 | | virtual nsresult Init(nsIDocument& aDoc, Element* aRoot, |
130 | | nsISelectionController* aSelCon, uint32_t aFlags, |
131 | | const nsAString& aValue) override; |
132 | | NS_IMETHOD BeginningOfDocument() override; |
133 | | NS_IMETHOD SetFlags(uint32_t aFlags) override; |
134 | | |
135 | | NS_IMETHOD CanPaste(int32_t aSelectionType, bool* aCanPaste) override; |
136 | | |
137 | | NS_IMETHOD PasteTransferable(nsITransferable* aTransferable) override; |
138 | | |
139 | | NS_IMETHOD DeleteNode(nsINode* aNode) override; |
140 | | |
141 | | NS_IMETHOD DebugUnitTests(int32_t* outNumTests, |
142 | | int32_t* outNumTestsFailed) override; |
143 | | |
144 | | virtual nsresult HandleKeyPressEvent( |
145 | | WidgetKeyboardEvent* aKeyboardEvent) override; |
146 | | virtual nsIContent* GetFocusedContent() override; |
147 | | virtual already_AddRefed<nsIContent> GetFocusedContentForIME() override; |
148 | | virtual bool IsActiveInDOMWindow() override; |
149 | | virtual dom::EventTarget* GetDOMEventTarget() override; |
150 | | virtual already_AddRefed<nsIContent> FindSelectionRoot( |
151 | | nsINode *aNode) override; |
152 | | virtual bool IsAcceptableInputEvent(WidgetGUIEvent* aGUIEvent) override; |
153 | | virtual nsresult GetPreferredIMEState(widget::IMEState* aState) override; |
154 | | |
155 | | /** |
156 | | * PasteAsQuotationAsAction() pastes content in clipboard with newly created |
157 | | * blockquote element. If the editor is in plaintext mode, will paste the |
158 | | * content with appending ">" to start of each line. |
159 | | * |
160 | | * @param aClipboardType nsIClipboard::kGlobalClipboard or |
161 | | * nsIClipboard::kSelectionClipboard. |
162 | | */ |
163 | | virtual nsresult PasteAsQuotationAsAction(int32_t aClipboardType) override; |
164 | | |
165 | | /** |
166 | | * Can we paste |aTransferable| or, if |aTransferable| is null, will a call |
167 | | * to pasteTransferable later possibly succeed if given an instance of |
168 | | * nsITransferable then? True if the doc is modifiable, and, if |
169 | | * |aTransfeable| is non-null, we have pasteable data in |aTransfeable|. |
170 | | */ |
171 | | virtual bool CanPasteTransferable(nsITransferable* aTransferable) override; |
172 | | |
173 | | /** |
174 | | * OnInputLineBreak() is called when user inputs a line break with |
175 | | * Shift + Enter or something. |
176 | | */ |
177 | | nsresult OnInputLineBreak(); |
178 | | |
179 | | /** |
180 | | * CreateElementWithDefaults() creates new element whose name is |
181 | | * aTagName with some default attributes are set. Note that this is a |
182 | | * public utility method. I.e., just creates element, not insert it |
183 | | * into the DOM tree. |
184 | | * NOTE: This is available for internal use too since this does not change |
185 | | * the DOM tree nor undo transactions, and does not refer Selection, |
186 | | * HTMLEditRules, etc. |
187 | | * |
188 | | * @param aTagName The new element's tag name. If the name is |
189 | | * one of "href", "anchor" or "namedanchor", |
190 | | * this creates an <a> element. |
191 | | * @return Newly created element. |
192 | | */ |
193 | | already_AddRefed<Element> CreateElementWithDefaults(const nsAtom& aTagName); |
194 | | |
195 | | /** |
196 | | * Indent or outdent content around Selection. |
197 | | */ |
198 | | nsresult IndentAsAction(); |
199 | | nsresult OutdentAsAction(); |
200 | | |
201 | | /** |
202 | | * event callback when a mouse button is pressed |
203 | | * @param aX [IN] horizontal position of the pointer |
204 | | * @param aY [IN] vertical position of the pointer |
205 | | * @param aTarget [IN] the element triggering the event |
206 | | * @param aMouseEvent [IN] the event |
207 | | */ |
208 | | nsresult OnMouseDown(int32_t aX, int32_t aY, Element* aTarget, |
209 | | dom::Event* aMouseEvent); |
210 | | |
211 | | /** |
212 | | * event callback when a mouse button is released |
213 | | * @param aX [IN] horizontal position of the pointer |
214 | | * @param aY [IN] vertical position of the pointer |
215 | | * @param aTarget [IN] the element triggering the event |
216 | | */ |
217 | | nsresult OnMouseUp(int32_t aX, int32_t aY, Element* aTarget); |
218 | | |
219 | | /** |
220 | | * event callback when the mouse pointer is moved |
221 | | * @param aMouseEvent [IN] the event |
222 | | */ |
223 | | nsresult OnMouseMove(dom::MouseEvent* aMouseEvent); |
224 | | |
225 | | /** |
226 | | * IsCSSEnabled() returns true if this editor treats styles with style |
227 | | * attribute of HTML elements. Otherwise, if this editor treats all styles |
228 | | * with "font style elements" like <b>, <i>, etc, and <blockquote> to indent, |
229 | | * align attribute to align contents, returns false. |
230 | | */ |
231 | | bool IsCSSEnabled() const |
232 | 0 | { |
233 | 0 | // TODO: removal of mCSSAware and use only the presence of mCSSEditUtils |
234 | 0 | return mCSSAware && mCSSEditUtils && mCSSEditUtils->IsCSSPrefChecked(); |
235 | 0 | } |
236 | | |
237 | | |
238 | | /** |
239 | | * Enable/disable object resizers for <img> elements, <table> elements, |
240 | | * absolute positioned elements (required absolute position editor enabled). |
241 | | */ |
242 | | void EnableObjectResizer(bool aEnable) |
243 | 0 | { |
244 | 0 | if (mIsObjectResizingEnabled == aEnable) { |
245 | 0 | return; |
246 | 0 | } |
247 | 0 | mIsObjectResizingEnabled = aEnable; |
248 | 0 | RefPtr<Selection> selection = GetSelection(); |
249 | 0 | if (NS_WARN_IF(!selection)) { |
250 | 0 | return; |
251 | 0 | } |
252 | 0 | RefereshEditingUI(*selection); |
253 | 0 | } |
254 | | bool IsObjectResizerEnabled() const |
255 | 0 | { |
256 | 0 | return mIsObjectResizingEnabled; |
257 | 0 | } |
258 | | |
259 | | /** |
260 | | * Enable/disable inline table editor, e.g., adding new row or column, |
261 | | * removing existing row or column. |
262 | | */ |
263 | | void EnableInlineTableEditor(bool aEnable) |
264 | 0 | { |
265 | 0 | if (mIsInlineTableEditingEnabled == aEnable) { |
266 | 0 | return; |
267 | 0 | } |
268 | 0 | mIsInlineTableEditingEnabled = aEnable; |
269 | 0 | RefPtr<Selection> selection = GetSelection(); |
270 | 0 | if (NS_WARN_IF(!selection)) { |
271 | 0 | return; |
272 | 0 | } |
273 | 0 | RefereshEditingUI(*selection); |
274 | 0 | } |
275 | | bool IsInlineTableEditorEnabled() const |
276 | 0 | { |
277 | 0 | return mIsInlineTableEditingEnabled; |
278 | 0 | } |
279 | | |
280 | | /** |
281 | | * Enable/disable absolute position editor, resizing absolute positioned |
282 | | * elements (required object resizers enabled) or positioning them with |
283 | | * dragging grabber. |
284 | | */ |
285 | | void EnableAbsolutePositionEditor(bool aEnable) |
286 | 0 | { |
287 | 0 | if (mIsAbsolutelyPositioningEnabled == aEnable) { |
288 | 0 | return; |
289 | 0 | } |
290 | 0 | mIsAbsolutelyPositioningEnabled = aEnable; |
291 | 0 | RefPtr<Selection> selection = GetSelection(); |
292 | 0 | if (NS_WARN_IF(!selection)) { |
293 | 0 | return; |
294 | 0 | } |
295 | 0 | RefereshEditingUI(*selection); |
296 | 0 | } |
297 | | bool IsAbsolutePositionEditorEnabled() const |
298 | 0 | { |
299 | 0 | return mIsAbsolutelyPositioningEnabled; |
300 | 0 | } |
301 | | |
302 | | // non-virtual methods of interface methods |
303 | | |
304 | | /** |
305 | | * returns the deepest absolutely positioned container of the selection |
306 | | * if it exists or null. |
307 | | */ |
308 | | already_AddRefed<Element> GetAbsolutelyPositionedSelectionContainer(); |
309 | | |
310 | | Element* GetPositionedElement() const |
311 | 0 | { |
312 | 0 | return mAbsolutelyPositionedObject; |
313 | 0 | } |
314 | | |
315 | | /** |
316 | | * extracts the selection from the normal flow of the document and |
317 | | * positions it. |
318 | | * @param aEnabled [IN] true to absolutely position the selection, |
319 | | * false to put it back in the normal flow |
320 | | */ |
321 | | nsresult SetSelectionToAbsoluteOrStatic(bool aEnabled); |
322 | | |
323 | | /** |
324 | | * returns the absolute z-index of a positioned element. Never returns 'auto' |
325 | | * @return the z-index of the element |
326 | | * @param aElement [IN] the element. |
327 | | */ |
328 | | int32_t GetZIndex(Element& aElement); |
329 | | |
330 | | /** |
331 | | * adds aChange to the z-index of the currently positioned element. |
332 | | * @param aChange [IN] relative change to apply to current z-index |
333 | | */ |
334 | | nsresult AddZIndex(int32_t aChange); |
335 | | |
336 | | nsresult SetInlineProperty(nsAtom& aProperty, |
337 | | nsAtom* aAttribute, |
338 | | const nsAString& aValue) |
339 | 0 | { |
340 | 0 | nsresult rv = SetInlinePropertyInternal(aProperty, aAttribute, aValue); |
341 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
342 | 0 | return rv; |
343 | 0 | } |
344 | 0 | return NS_OK; |
345 | 0 | } |
346 | | |
347 | | nsresult GetInlineProperty(nsAtom* aProperty, |
348 | | nsAtom* aAttribute, |
349 | | const nsAString& aValue, |
350 | | bool* aFirst, |
351 | | bool* aAny, |
352 | | bool* aAll); |
353 | | nsresult GetInlinePropertyWithAttrValue(nsAtom* aProperty, |
354 | | nsAtom* aAttr, |
355 | | const nsAString& aValue, |
356 | | bool* aFirst, |
357 | | bool* aAny, |
358 | | bool* aAll, |
359 | | nsAString& outValue); |
360 | | nsresult RemoveInlineProperty(nsAtom* aProperty, |
361 | | nsAtom* aAttribute) |
362 | 0 | { |
363 | 0 | nsresult rv = RemoveInlinePropertyInternal(aProperty, aAttribute); |
364 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
365 | 0 | return rv; |
366 | 0 | } |
367 | 0 | return NS_OK; |
368 | 0 | } |
369 | | |
370 | | /** |
371 | | * GetFontColorState() returns foreground color information in first |
372 | | * range of Selection. |
373 | | * If first range of Selection is collapsed and there is a cache of style for |
374 | | * new text, aIsMixed is set to false and aColor is set to the cached color. |
375 | | * If first range of Selection is collapsed and there is no cached color, |
376 | | * this returns the color of the node, aIsMixed is set to false and aColor is |
377 | | * set to the color. |
378 | | * If first range of Selection is not collapsed, this collects colors of |
379 | | * each node in the range. If there are two or more colors, aIsMixed is set |
380 | | * to true and aColor is truncated. If only one color is set to all of the |
381 | | * range, aIsMixed is set to false and aColor is set to the color. |
382 | | * If there is no Selection ranges, aIsMixed is set to false and aColor is |
383 | | * truncated. |
384 | | * |
385 | | * @param aIsMixed Must not be nullptr. This is set to true |
386 | | * if there is two or more colors in first |
387 | | * range of Selection. |
388 | | * @param aColor Returns the color if only one color is set to |
389 | | * all of first range in Selection. Otherwise, |
390 | | * returns empty string. |
391 | | * @return Returns error only when illegal cases, e.g., |
392 | | * Selection instance has gone, first range |
393 | | * Selection is broken. |
394 | | */ |
395 | | nsresult GetFontColorState(bool* aIsMixed, nsAString& aColor); |
396 | | |
397 | | /** |
398 | | * SetComposerCommandsUpdater() sets or unsets mComposerCommandsUpdater. |
399 | | * This will crash in debug build if the editor already has an instance |
400 | | * but called with another instance. |
401 | | */ |
402 | | void SetComposerCommandsUpdater( |
403 | | ComposerCommandsUpdater* aComposerCommandsUpdater) |
404 | 0 | { |
405 | 0 | MOZ_ASSERT(!aComposerCommandsUpdater || !mComposerCommandsUpdater || |
406 | 0 | aComposerCommandsUpdater == mComposerCommandsUpdater); |
407 | 0 | mComposerCommandsUpdater = aComposerCommandsUpdater; |
408 | 0 | } |
409 | | |
410 | | ParagraphSeparator GetDefaultParagraphSeparator() const |
411 | 0 | { |
412 | 0 | return mDefaultParagraphSeparator; |
413 | 0 | } |
414 | | void SetDefaultParagraphSeparator(ParagraphSeparator aSep) |
415 | 0 | { |
416 | 0 | mDefaultParagraphSeparator = aSep; |
417 | 0 | } |
418 | | |
419 | | /** |
420 | | * Modifies the table containing the selection according to the |
421 | | * activation of an inline table editing UI element |
422 | | * @param aUIAnonymousElement [IN] the inline table editing UI element |
423 | | */ |
424 | | nsresult DoInlineTableEditingAction(const Element& aUIAnonymousElement); |
425 | | |
426 | | /** |
427 | | * GetElementOrParentByTagName() looks for an element node whose name matches |
428 | | * aTagName from aNode or anchor node of Selection to <body> element. |
429 | | * |
430 | | * @param aTagName The tag name which you want to look for. |
431 | | * Must not be nsGkAtoms::_empty. |
432 | | * If nsGkAtoms::list, the result may be <ul>, <ol> or |
433 | | * <dl> element. |
434 | | * If nsGkAtoms::td, the result may be <td> or <th>. |
435 | | * If nsGkAtoms::href, the result may be <a> element |
436 | | * which has "href" attribute with non-empty value. |
437 | | * If nsGkAtoms::anchor, the result may be <a> which |
438 | | * has "name" attribute with non-empty value. |
439 | | * @param aNode If non-nullptr, this starts to look for the result |
440 | | * from it. Otherwise, i.e., nullptr, starts from |
441 | | * anchor node of Selection. |
442 | | * @return If an element which matches aTagName, returns |
443 | | * an Element. Otherwise, nullptr. |
444 | | */ |
445 | | Element* |
446 | | GetElementOrParentByTagName(const nsAtom& aTagName, nsINode* aNode) const; |
447 | | |
448 | | /** |
449 | | * Get an active editor's editing host in DOM window. If this editor isn't |
450 | | * active in the DOM window, this returns NULL. |
451 | | */ |
452 | | Element* GetActiveEditingHost() const; |
453 | | |
454 | | /** Insert a string as quoted text |
455 | | * (whose representation is dependant on the editor type), |
456 | | * replacing the selected text (if any). |
457 | | * |
458 | | * @param aQuotedText The actual text to be quoted |
459 | | * @parem aNodeInserted Return the node which was inserted. |
460 | | */ |
461 | | nsresult InsertAsQuotation(const nsAString& aQuotedText, |
462 | | nsINode** aNodeInserted); |
463 | | |
464 | | /** |
465 | | * Inserts a plaintext string at the current location, |
466 | | * with special processing for lines beginning with ">", |
467 | | * which will be treated as mail quotes and inserted |
468 | | * as plaintext quoted blocks. |
469 | | * If the selection is not collapsed, the selection is deleted |
470 | | * and the insertion takes place at the resulting collapsed selection. |
471 | | * |
472 | | * @param aString the string to be inserted |
473 | | */ |
474 | | nsresult InsertTextWithQuotations(const nsAString& aStringToInsert); |
475 | | |
476 | | protected: // May be called by friends. |
477 | | /**************************************************************************** |
478 | | * Some classes like TextEditRules, HTMLEditRules, WSRunObject which are |
479 | | * part of handling edit actions are allowed to call the following protected |
480 | | * methods. However, those methods won't prepare caches of some objects |
481 | | * which are necessary for them. So, if you want some following methods |
482 | | * to do that for you, you need to create a wrapper method in public scope |
483 | | * and call it. |
484 | | ****************************************************************************/ |
485 | | |
486 | | /** |
487 | | * DeleteSelectionWithTransaction() removes selected content or content |
488 | | * around caret with transactions. |
489 | | * |
490 | | * @param aDirection How much range should be removed. |
491 | | * @param aStripWrappers Whether the parent blocks should be removed |
492 | | * when they become empty. |
493 | | */ |
494 | | virtual nsresult |
495 | | DeleteSelectionWithTransaction(EDirection aAction, |
496 | | EStripWrappers aStripWrappers) override; |
497 | | |
498 | | /** |
499 | | * DeleteNodeWithTransaction() removes aNode from the DOM tree if it's |
500 | | * modifiable. Note that this is not an override of same method of |
501 | | * EditorBase. |
502 | | * |
503 | | * @param aNode The node to be removed from the DOM tree. |
504 | | */ |
505 | | nsresult DeleteNodeWithTransaction(nsINode& aNode); |
506 | | |
507 | | /** |
508 | | * DeleteTextWithTransaction() removes text in the range from aCharData if |
509 | | * it's modifiable. Note that this not an override of same method of |
510 | | * EditorBase. |
511 | | * |
512 | | * @param aCharData The data node which should be modified. |
513 | | * @param aOffset Start offset of removing text in aCharData. |
514 | | * @param aLength Length of removing text. |
515 | | */ |
516 | | nsresult DeleteTextWithTransaction(dom::CharacterData& aTextNode, |
517 | | uint32_t aOffset, uint32_t aLength); |
518 | | |
519 | | /** |
520 | | * InsertTextWithTransaction() inserts aStringToInsert at aPointToInsert. |
521 | | */ |
522 | | virtual nsresult |
523 | | InsertTextWithTransaction(nsIDocument& aDocument, |
524 | | const nsAString& aStringToInsert, |
525 | | const EditorRawDOMPoint& aPointToInsert, |
526 | | EditorRawDOMPoint* aPointAfterInsertedString = |
527 | | nullptr) override; |
528 | | |
529 | | /** |
530 | | * CopyLastEditableChildStyles() clones inline container elements into |
531 | | * aPreviousBlock to aNewBlock to keep using same style in it. |
532 | | * |
533 | | * @param aPreviousBlock The previous block element. All inline |
534 | | * elements which are last sibling of each level |
535 | | * are cloned to aNewBlock. |
536 | | * @param aNewBlock New block container element. |
537 | | * @param aNewBrElement If this method creates a new <br> element for |
538 | | * placeholder, this is set to the new <br> |
539 | | * element. |
540 | | */ |
541 | | nsresult |
542 | | CopyLastEditableChildStylesWithTransaction(Element& aPreviousBlock, |
543 | | Element& aNewBlock, |
544 | | RefPtr<Element>* aNewBrElement); |
545 | | |
546 | | /** |
547 | | * RemoveBlockContainerWithTransaction() removes aElement from the DOM tree |
548 | | * but moves its all children to its parent node and if its parent needs <br> |
549 | | * element to have at least one line-height, this inserts <br> element |
550 | | * automatically. |
551 | | * |
552 | | * @param aElement Block element to be removed. |
553 | | */ |
554 | | nsresult RemoveBlockContainerWithTransaction(Element& aElement); |
555 | | |
556 | | virtual Element* GetEditorRoot() const override; |
557 | | using EditorBase::IsEditable; |
558 | | virtual nsresult RemoveAttributeOrEquivalent( |
559 | | Element* aElement, |
560 | | nsAtom* aAttribute, |
561 | | bool aSuppressTransaction) override; |
562 | | virtual nsresult SetAttributeOrEquivalent(Element* aElement, |
563 | | nsAtom* aAttribute, |
564 | | const nsAString& aValue, |
565 | | bool aSuppressTransaction) override; |
566 | | using EditorBase::RemoveAttributeOrEquivalent; |
567 | | using EditorBase::SetAttributeOrEquivalent; |
568 | | |
569 | | /** |
570 | | * GetBlockNodeParent() returns parent or nearest ancestor of aNode if |
571 | | * there is a block parent. If aAncestorLimiter is not nullptr, |
572 | | * this stops looking for the result. |
573 | | */ |
574 | | static Element* GetBlockNodeParent(nsINode* aNode, |
575 | | nsINode* aAncestorLimiter = nullptr); |
576 | | |
577 | | /** |
578 | | * GetBlock() returns aNode itself, or parent or nearest ancestor of aNode |
579 | | * if there is a block parent. If aAncestorLimiter is not nullptr, |
580 | | * this stops looking for the result. |
581 | | */ |
582 | | static Element* GetBlock(nsINode& aNode, |
583 | | nsINode* aAncestorLimiter = nullptr); |
584 | | |
585 | | /** |
586 | | * Returns container element of ranges in Selection. If Selection is |
587 | | * collapsed, returns focus container node (or its parent element). |
588 | | * If Selection selects only one element node, returns the element node. |
589 | | * If Selection is only one range, returns common ancestor of the range. |
590 | | * XXX If there are two or more Selection ranges, this returns parent node |
591 | | * of start container of a range which starts with different node from |
592 | | * start container of the first range. |
593 | | */ |
594 | | Element* GetSelectionContainerElement(Selection& aSelection) const; |
595 | | |
596 | | /** |
597 | | * GetFirstSelectedTableCellElement() returns a <td> or <th> element if |
598 | | * first range of Selection (i.e., result of Selection::GetRangeAt(0)) |
599 | | * selects a <td> element or <th> element. Even if Selection is in |
600 | | * a cell element, this returns nullptr. And even if 2nd or later |
601 | | * range of Selection selects a cell element, also returns nullptr. |
602 | | * Note that when this looks for a cell element, this resets the internal |
603 | | * index of ranges of Selection. When you call |
604 | | * GetNextSelectedTableCellElement() after a call of this, it'll return 2nd |
605 | | * selected cell if there is. |
606 | | * |
607 | | * @param aSelection Selection for this editor. |
608 | | * @param aRv Returns error if there is no selection or |
609 | | * first range of Selection is unexpected. |
610 | | * @return A <td> or <th> element is selected by first |
611 | | * range of Selection. Note that the range must |
612 | | * be: startContaienr and endContainer are same |
613 | | * <tr> element, startOffset + 1 equals endOffset. |
614 | | */ |
615 | | already_AddRefed<Element> |
616 | | GetFirstSelectedTableCellElement(Selection& aSelection, |
617 | | ErrorResult& aRv) const; |
618 | | |
619 | | /** |
620 | | * GetNextSelectedTableCellElement() is a stateful method to retrieve |
621 | | * selected table cell elements which are selected by 2nd or later ranges |
622 | | * of Selection. When you call GetFirstSelectedTableCellElement(), it |
623 | | * resets internal counter of this method. Then, following calls of |
624 | | * GetNextSelectedTableCellElement() scans the remaining ranges of Selection. |
625 | | * If a range selects a <td> or <th> element, returns the cell element. |
626 | | * If a range selects an element but neither <td> nor <th> element, this |
627 | | * ignores the range. If a range is in a text node, returns null without |
628 | | * throwing exception, but stops scanning the remaining ranges even you |
629 | | * call this again. |
630 | | * Note that this may cross <table> boundaries since this method just |
631 | | * scans all ranges of Selection. Therefore, returning cells which |
632 | | * belong to different <table> elements. |
633 | | * |
634 | | * @param Selection Selection for this editor. |
635 | | * @param aRv Returns error if Selection doesn't have |
636 | | * range properly. |
637 | | * @return A <td> or <th> element if one of remaining |
638 | | * ranges selects a <td> or <th> element unless |
639 | | * this does not meet a range in a text node. |
640 | | */ |
641 | | already_AddRefed<Element> |
642 | | GetNextSelectedTableCellElement(Selection& aSelection, |
643 | | ErrorResult& aRv) const; |
644 | | |
645 | | /** |
646 | | * DeleteTableCellContentsWithTransaction() removes any contents in cell |
647 | | * elements. If two or more cell elements are selected, this removes |
648 | | * all selected cells' contents. Otherwise, this removes contents of |
649 | | * a cell which contains first selection range. This does not return |
650 | | * error even if selection is not in cell element, just does nothing. |
651 | | */ |
652 | | nsresult DeleteTableCellContentsWithTransaction(); |
653 | | |
654 | | void IsNextCharInNodeWhitespace(nsIContent* aContent, |
655 | | int32_t aOffset, |
656 | | bool* outIsSpace, |
657 | | bool* outIsNBSP, |
658 | | nsIContent** outNode = nullptr, |
659 | | int32_t* outOffset = 0); |
660 | | void IsPrevCharInNodeWhitespace(nsIContent* aContent, |
661 | | int32_t aOffset, |
662 | | bool* outIsSpace, |
663 | | bool* outIsNBSP, |
664 | | nsIContent** outNode = nullptr, |
665 | | int32_t* outOffset = 0); |
666 | | |
667 | | /** |
668 | | * @param aElement Must not be null. |
669 | | */ |
670 | | static bool NodeIsBlockStatic(const nsINode* aElement); |
671 | | |
672 | | /** |
673 | | * extracts an element from the normal flow of the document and |
674 | | * positions it, and puts it back in the normal flow. |
675 | | * @param aElement [IN] the element |
676 | | * @param aEnabled [IN] true to absolutely position the element, |
677 | | * false to put it back in the normal flow |
678 | | */ |
679 | | nsresult SetPositionToAbsoluteOrStatic(Element& aElement, |
680 | | bool aEnabled); |
681 | | |
682 | | /** |
683 | | * adds aChange to the z-index of an arbitrary element. |
684 | | * @param aElement [IN] the element |
685 | | * @param aChange [IN] relative change to apply to current z-index of |
686 | | * the element |
687 | | * @param aReturn [OUT] the new z-index of the element |
688 | | */ |
689 | | nsresult RelativeChangeElementZIndex(Element& aElement, int32_t aChange, |
690 | | int32_t* aReturn); |
691 | | |
692 | | virtual bool IsBlockNode(nsINode *aNode) override; |
693 | | using EditorBase::IsBlockNode; |
694 | | |
695 | | /** |
696 | | * returns true if aParentTag can contain a child of type aChildTag. |
697 | | */ |
698 | | virtual bool TagCanContainTag(nsAtom& aParentTag, |
699 | | nsAtom& aChildTag) const override; |
700 | | |
701 | | /** |
702 | | * Returns true if aNode is a container. |
703 | | */ |
704 | | virtual bool IsContainer(nsINode* aNode) override; |
705 | | |
706 | | /** |
707 | | * Join together any adjacent editable text nodes in the range. |
708 | | */ |
709 | | nsresult CollapseAdjacentTextNodes(nsRange* aRange); |
710 | | |
711 | | /** |
712 | | * IsInVisibleTextFrames() returns true if all text in aText is in visible |
713 | | * text frames. Callers have to guarantee that there is no pending reflow. |
714 | | */ |
715 | | bool IsInVisibleTextFrames(dom::Text& aText); |
716 | | |
717 | | /** |
718 | | * IsVisibleTextNode() returns true if aText has visible text. If it has |
719 | | * only whitespaces and they are collapsed, returns false. |
720 | | */ |
721 | | bool IsVisibleTextNode(Text& aText); |
722 | | |
723 | | /** |
724 | | * aNode must be a non-null text node. |
725 | | * outIsEmptyNode must be non-null. |
726 | | */ |
727 | | nsresult IsEmptyNode(nsINode* aNode, bool* outIsEmptyBlock, |
728 | | bool aMozBRDoesntCount = false, |
729 | | bool aListOrCellNotEmpty = false, |
730 | | bool aSafeToAskFrames = false); |
731 | | nsresult IsEmptyNodeImpl(nsINode* aNode, |
732 | | bool* outIsEmptyBlock, |
733 | | bool aMozBRDoesntCount, |
734 | | bool aListOrCellNotEmpty, |
735 | | bool aSafeToAskFrames, |
736 | | bool* aSeenBR); |
737 | | |
738 | | static bool HasAttributes(Element* aElement) |
739 | 0 | { |
740 | 0 | MOZ_ASSERT(aElement); |
741 | 0 | uint32_t attrCount = aElement->GetAttrCount(); |
742 | 0 | return attrCount > 1 || |
743 | 0 | (1 == attrCount && |
744 | 0 | !aElement->GetAttrNameAt(0)->Equals(nsGkAtoms::mozdirty)); |
745 | 0 | } |
746 | | |
747 | | /** |
748 | | * Content-based query returns true if <aProperty aAttribute=aValue> effects |
749 | | * aNode. If <aProperty aAttribute=aValue> contains aNode, but |
750 | | * <aProperty aAttribute=SomeOtherValue> also contains aNode and the second is |
751 | | * more deeply nested than the first, then the first does not effect aNode. |
752 | | * |
753 | | * @param aNode The target of the query |
754 | | * @param aProperty The property that we are querying for |
755 | | * @param aAttribute The attribute of aProperty, example: color in |
756 | | * <FONT color="blue"> May be null. |
757 | | * @param aValue The value of aAttribute, example: blue in |
758 | | * <FONT color="blue"> May be null. Ignored if aAttribute |
759 | | * is null. |
760 | | * @param outValue [OUT] the value of the attribute, if aIsSet is true |
761 | | * @return true if <aProperty aAttribute=aValue> effects |
762 | | * aNode. |
763 | | * |
764 | | * The nsIContent variant returns aIsSet instead of using an out parameter. |
765 | | */ |
766 | | bool IsTextPropertySetByContent(nsINode* aNode, |
767 | | nsAtom* aProperty, |
768 | | nsAtom* aAttribute, |
769 | | const nsAString* aValue, |
770 | | nsAString* outValue = nullptr); |
771 | | |
772 | | static dom::Element* GetLinkElement(nsINode* aNode); |
773 | | |
774 | | /** |
775 | | * Small utility routine to test if a break node is visible to user. |
776 | | */ |
777 | | bool IsVisibleBRElement(nsINode* aNode); |
778 | | |
779 | | /** |
780 | | * Helper routines for font size changing. |
781 | | */ |
782 | | enum class FontSize { incr, decr }; |
783 | | nsresult RelativeFontChangeOnTextNode(FontSize aDir, |
784 | | Text& aTextNode, |
785 | | int32_t aStartOffset, |
786 | | int32_t aEndOffset); |
787 | | |
788 | | nsresult SetInlinePropertyOnNode(nsIContent& aNode, |
789 | | nsAtom& aProperty, |
790 | | nsAtom* aAttribute, |
791 | | const nsAString& aValue); |
792 | | |
793 | | nsresult SplitStyleAbovePoint(nsCOMPtr<nsINode>* aNode, int32_t* aOffset, |
794 | | nsAtom* aProperty, |
795 | | nsAtom* aAttribute, |
796 | | nsIContent** aOutLeftNode = nullptr, |
797 | | nsIContent** aOutRightNode = nullptr); |
798 | | |
799 | | nsIContent* GetPriorHTMLSibling(nsINode* aNode); |
800 | | |
801 | | nsIContent* GetNextHTMLSibling(nsINode* aNode); |
802 | | |
803 | | /** |
804 | | * GetPreviousHTMLElementOrText*() methods are similar to |
805 | | * EditorBase::GetPreviousElementOrText*() but this won't return nodes |
806 | | * outside active editing host. |
807 | | */ |
808 | | nsIContent* GetPreviousHTMLElementOrText(nsINode& aNode) |
809 | 0 | { |
810 | 0 | return GetPreviousHTMLElementOrTextInternal(aNode, false); |
811 | 0 | } |
812 | | nsIContent* GetPreviousHTMLElementOrTextInBlock(nsINode& aNode) |
813 | 0 | { |
814 | 0 | return GetPreviousHTMLElementOrTextInternal(aNode, true); |
815 | 0 | } |
816 | | template<typename PT, typename CT> |
817 | | nsIContent* |
818 | | GetPreviousHTMLElementOrText(const EditorDOMPointBase<PT, CT>& aPoint) |
819 | | { |
820 | | return GetPreviousHTMLElementOrTextInternal(aPoint, false); |
821 | | } |
822 | | template<typename PT, typename CT> |
823 | | nsIContent* |
824 | | GetPreviousHTMLElementOrTextInBlock(const EditorDOMPointBase<PT, CT>& aPoint) |
825 | | { |
826 | | return GetPreviousHTMLElementOrTextInternal(aPoint, true); |
827 | | } |
828 | | |
829 | | /** |
830 | | * GetPreviousHTMLElementOrTextInternal() methods are common implementation |
831 | | * of above methods. Please don't use this method directly. |
832 | | */ |
833 | | nsIContent* GetPreviousHTMLElementOrTextInternal(nsINode& aNode, |
834 | | bool aNoBlockCrossing); |
835 | | template<typename PT, typename CT> |
836 | | nsIContent* |
837 | | GetPreviousHTMLElementOrTextInternal(const EditorDOMPointBase<PT, CT>& aPoint, |
838 | | bool aNoBlockCrossing); |
839 | | |
840 | | /** |
841 | | * GetPreviousEditableHTMLNode*() methods are similar to |
842 | | * EditorBase::GetPreviousEditableNode() but this won't return nodes outside |
843 | | * active editing host. |
844 | | */ |
845 | | nsIContent* GetPreviousEditableHTMLNode(nsINode& aNode) |
846 | 0 | { |
847 | 0 | return GetPreviousEditableHTMLNodeInternal(aNode, false); |
848 | 0 | } |
849 | | nsIContent* GetPreviousEditableHTMLNodeInBlock(nsINode& aNode) |
850 | 0 | { |
851 | 0 | return GetPreviousEditableHTMLNodeInternal(aNode, true); |
852 | 0 | } |
853 | | template<typename PT, typename CT> |
854 | | nsIContent* |
855 | | GetPreviousEditableHTMLNode(const EditorDOMPointBase<PT, CT>& aPoint) |
856 | 0 | { |
857 | 0 | return GetPreviousEditableHTMLNodeInternal(aPoint, false); |
858 | 0 | } Unexecuted instantiation: nsIContent* mozilla::HTMLEditor::GetPreviousEditableHTMLNode<nsINode*, nsIContent*>(mozilla::EditorDOMPointBase<nsINode*, nsIContent*> const&) Unexecuted instantiation: nsIContent* mozilla::HTMLEditor::GetPreviousEditableHTMLNode<nsCOMPtr<nsINode>, nsCOMPtr<nsIContent> >(mozilla::EditorDOMPointBase<nsCOMPtr<nsINode>, nsCOMPtr<nsIContent> > const&) |
859 | | template<typename PT, typename CT> |
860 | | nsIContent* GetPreviousEditableHTMLNodeInBlock( |
861 | | const EditorDOMPointBase<PT, CT>& aPoint) |
862 | 0 | { |
863 | 0 | return GetPreviousEditableHTMLNodeInternal(aPoint, true); |
864 | 0 | } |
865 | | |
866 | | /** |
867 | | * GetPreviousEditableHTMLNodeInternal() methods are common implementation |
868 | | * of above methods. Please don't use this method directly. |
869 | | */ |
870 | | nsIContent* GetPreviousEditableHTMLNodeInternal(nsINode& aNode, |
871 | | bool aNoBlockCrossing); |
872 | | template<typename PT, typename CT> |
873 | | nsIContent* GetPreviousEditableHTMLNodeInternal( |
874 | | const EditorDOMPointBase<PT, CT>& aPoint, |
875 | | bool aNoBlockCrossing); |
876 | | |
877 | | /** |
878 | | * GetNextHTMLElementOrText*() methods are similar to |
879 | | * EditorBase::GetNextElementOrText*() but this won't return nodes outside |
880 | | * active editing host. |
881 | | * |
882 | | * Note that same as EditorBase::GetTextEditableNode(), methods which take |
883 | | * |const EditorRawDOMPoint&| start to search from the node pointed by it. |
884 | | * On the other hand, methods which take |nsINode&| start to search from |
885 | | * next node of aNode. |
886 | | */ |
887 | | nsIContent* GetNextHTMLElementOrText(nsINode& aNode) |
888 | 0 | { |
889 | 0 | return GetNextHTMLElementOrTextInternal(aNode, false); |
890 | 0 | } |
891 | | nsIContent* GetNextHTMLElementOrTextInBlock(nsINode& aNode) |
892 | 0 | { |
893 | 0 | return GetNextHTMLElementOrTextInternal(aNode, true); |
894 | 0 | } |
895 | | template<typename PT, typename CT> |
896 | | nsIContent* |
897 | | GetNextHTMLElementOrText(const EditorDOMPointBase<PT, CT>& aPoint) |
898 | | { |
899 | | return GetNextHTMLElementOrTextInternal(aPoint, false); |
900 | | } |
901 | | template<typename PT, typename CT> |
902 | | nsIContent* |
903 | | GetNextHTMLElementOrTextInBlock(const EditorDOMPointBase<PT, CT>& aPoint) |
904 | | { |
905 | | return GetNextHTMLElementOrTextInternal(aPoint, true); |
906 | | } |
907 | | |
908 | | /** |
909 | | * GetNextHTMLNodeInternal() methods are common implementation |
910 | | * of above methods. Please don't use this method directly. |
911 | | */ |
912 | | nsIContent* GetNextHTMLElementOrTextInternal(nsINode& aNode, |
913 | | bool aNoBlockCrossing); |
914 | | template<typename PT, typename CT> |
915 | | nsIContent* |
916 | | GetNextHTMLElementOrTextInternal(const EditorDOMPointBase<PT, CT>& aPoint, |
917 | | bool aNoBlockCrossing); |
918 | | |
919 | | /** |
920 | | * GetNextEditableHTMLNode*() methods are similar to |
921 | | * EditorBase::GetNextEditableNode() but this won't return nodes outside |
922 | | * active editing host. |
923 | | * |
924 | | * Note that same as EditorBase::GetTextEditableNode(), methods which take |
925 | | * |const EditorRawDOMPoint&| start to search from the node pointed by it. |
926 | | * On the other hand, methods which take |nsINode&| start to search from |
927 | | * next node of aNode. |
928 | | */ |
929 | | nsIContent* GetNextEditableHTMLNode(nsINode& aNode) |
930 | 0 | { |
931 | 0 | return GetNextEditableHTMLNodeInternal(aNode, false); |
932 | 0 | } |
933 | | nsIContent* GetNextEditableHTMLNodeInBlock(nsINode& aNode) |
934 | 0 | { |
935 | 0 | return GetNextEditableHTMLNodeInternal(aNode, true); |
936 | 0 | } |
937 | | template<typename PT, typename CT> |
938 | | nsIContent* GetNextEditableHTMLNode(const EditorDOMPointBase<PT, CT>& aPoint) |
939 | 0 | { |
940 | 0 | return GetNextEditableHTMLNodeInternal(aPoint, false); |
941 | 0 | } Unexecuted instantiation: nsIContent* mozilla::HTMLEditor::GetNextEditableHTMLNode<nsCOMPtr<nsINode>, nsCOMPtr<nsIContent> >(mozilla::EditorDOMPointBase<nsCOMPtr<nsINode>, nsCOMPtr<nsIContent> > const&) Unexecuted instantiation: nsIContent* mozilla::HTMLEditor::GetNextEditableHTMLNode<nsINode*, nsIContent*>(mozilla::EditorDOMPointBase<nsINode*, nsIContent*> const&) |
942 | | template<typename PT, typename CT> |
943 | | nsIContent* GetNextEditableHTMLNodeInBlock( |
944 | | const EditorDOMPointBase<PT, CT>& aPoint) |
945 | 0 | { |
946 | 0 | return GetNextEditableHTMLNodeInternal(aPoint, true); |
947 | 0 | } Unexecuted instantiation: nsIContent* mozilla::HTMLEditor::GetNextEditableHTMLNodeInBlock<nsCOMPtr<nsINode>, nsCOMPtr<nsIContent> >(mozilla::EditorDOMPointBase<nsCOMPtr<nsINode>, nsCOMPtr<nsIContent> > const&) Unexecuted instantiation: nsIContent* mozilla::HTMLEditor::GetNextEditableHTMLNodeInBlock<nsINode*, nsIContent*>(mozilla::EditorDOMPointBase<nsINode*, nsIContent*> const&) |
948 | | |
949 | | /** |
950 | | * GetNextEditableHTMLNodeInternal() methods are common implementation |
951 | | * of above methods. Please don't use this method directly. |
952 | | */ |
953 | | nsIContent* GetNextEditableHTMLNodeInternal(nsINode& aNode, |
954 | | bool aNoBlockCrossing); |
955 | | template<typename PT, typename CT> |
956 | | nsIContent* GetNextEditableHTMLNodeInternal( |
957 | | const EditorDOMPointBase<PT, CT>& aPoint, |
958 | | bool aNoBlockCrossing); |
959 | | |
960 | | bool IsFirstEditableChild(nsINode* aNode); |
961 | | bool IsLastEditableChild(nsINode* aNode); |
962 | | nsIContent* GetFirstEditableChild(nsINode& aNode); |
963 | | nsIContent* GetLastEditableChild(nsINode& aNode); |
964 | | |
965 | | nsIContent* GetFirstEditableLeaf(nsINode& aNode); |
966 | | nsIContent* GetLastEditableLeaf(nsINode& aNode); |
967 | | |
968 | | nsresult GetInlinePropertyBase(nsAtom& aProperty, |
969 | | nsAtom* aAttribute, |
970 | | const nsAString* aValue, |
971 | | bool* aFirst, |
972 | | bool* aAny, |
973 | | bool* aAll, |
974 | | nsAString* outValue); |
975 | | |
976 | | nsresult ClearStyle(nsCOMPtr<nsINode>* aNode, int32_t* aOffset, |
977 | | nsAtom* aProperty, nsAtom* aAttribute); |
978 | | |
979 | | nsresult SetPositionToAbsolute(Element& aElement); |
980 | | nsresult SetPositionToStatic(Element& aElement); |
981 | | |
982 | | protected: // Called by helper classes. |
983 | | virtual void |
984 | | OnStartToHandleTopLevelEditSubAction( |
985 | | EditSubAction aEditSubAction, nsIEditor::EDirection aDirection) override; |
986 | | virtual void OnEndHandlingTopLevelEditSubAction() override; |
987 | | |
988 | | protected: // Shouldn't be used by friend classes |
989 | | virtual ~HTMLEditor(); |
990 | | |
991 | | virtual nsresult SelectAllInternal() override; |
992 | | |
993 | | /** |
994 | | * SelectContentInternal() sets Selection to aContentToSelect to |
995 | | * aContentToSelect + 1 in parent of aContentToSelect. |
996 | | * |
997 | | * @param aSelection The Selection, callers have to guarantee the |
998 | | * lifetime. |
999 | | * @param aContentToSelect The content which should be selected. |
1000 | | */ |
1001 | | nsresult SelectContentInternal(Selection& aSelection, |
1002 | | nsIContent& aContentToSelect); |
1003 | | |
1004 | | /** |
1005 | | * CollapseSelectionAfter() collapses Selection after aElement. |
1006 | | * If aElement is an orphan node or not in editing host, returns error. |
1007 | | */ |
1008 | | nsresult CollapseSelectionAfter(Selection& aSelection, |
1009 | | Element& aElement); |
1010 | | |
1011 | | /** |
1012 | | * GetElementOrParentByTagNameAtSelection() looks for an element node whose |
1013 | | * name matches aTagName from anchor node of Selection to <body> element. |
1014 | | * |
1015 | | * @param aSelection The Selection for this editor. |
1016 | | * @param aTagName The tag name which you want to look for. |
1017 | | * Must not be nsGkAtoms::_empty. |
1018 | | * If nsGkAtoms::list, the result may be <ul>, <ol> or |
1019 | | * <dl> element. |
1020 | | * If nsGkAtoms::td, the result may be <td> or <th>. |
1021 | | * If nsGkAtoms::href, the result may be <a> element |
1022 | | * which has "href" attribute with non-empty value. |
1023 | | * If nsGkAtoms::anchor, the result may be <a> which |
1024 | | * has "name" attribute with non-empty value. |
1025 | | * @return If an element which matches aTagName, returns |
1026 | | * an Element. Otherwise, nullptr. |
1027 | | */ |
1028 | | Element* |
1029 | | GetElementOrParentByTagNameAtSelection(Selection& aSelection, |
1030 | | const nsAtom& aTagName) const; |
1031 | | |
1032 | | /** |
1033 | | * GetElementOrParentByTagNameInternal() looks for an element node whose |
1034 | | * name matches aTagName from aNode to <body> element. |
1035 | | * |
1036 | | * @param aTagName The tag name which you want to look for. |
1037 | | * Must not be nsGkAtoms::_empty. |
1038 | | * If nsGkAtoms::list, the result may be <ul>, <ol> or |
1039 | | * <dl> element. |
1040 | | * If nsGkAtoms::td, the result may be <td> or <th>. |
1041 | | * If nsGkAtoms::href, the result may be <a> element |
1042 | | * which has "href" attribute with non-empty value. |
1043 | | * If nsGkAtoms::anchor, the result may be <a> which |
1044 | | * has "name" attribute with non-empty value. |
1045 | | * @param aNode Start node to look for the element. |
1046 | | * @return If an element which matches aTagName, returns |
1047 | | * an Element. Otherwise, nullptr. |
1048 | | */ |
1049 | | Element* |
1050 | | GetElementOrParentByTagNameInternal(const nsAtom& aTagName, |
1051 | | nsINode& aNode) const; |
1052 | | |
1053 | | /** |
1054 | | * GetSelectedElement() returns an element node which is in first range of |
1055 | | * aSelection. The rule is a little bit complicated and the rules do not |
1056 | | * make sense except in a few cases. If you want to use this newly, |
1057 | | * you should create new method instead. This needs to be here for |
1058 | | * comm-central. |
1059 | | * The rules are: |
1060 | | * 1. If Selection selects an element node, i.e., both containers are |
1061 | | * same node and start offset and end offset is start offset + 1. |
1062 | | * (XXX However, if last child is selected, this path is not used.) |
1063 | | * 2. If the argument is "href", look for anchor elements whose href |
1064 | | * attribute is not empty from container of anchor/focus of Selection |
1065 | | * to <body> element. Then, both result are same one, returns the node. |
1066 | | * (i.e., this allows collapsed selection.) |
1067 | | * 3. If the Selection is collapsed, returns null. |
1068 | | * 4. Otherwise, listing up all nodes with content iterator (post-order). |
1069 | | * 4-1. When first element node does *not* match with the argument, |
1070 | | * *returns* the element. |
1071 | | * 4-2. When first element node matches with the argument, returns |
1072 | | * *next* element node. |
1073 | | * |
1074 | | * @param aSelection The Selection. |
1075 | | * @param aTagName The atom of tag name in lower case. |
1076 | | * If nullptr, look for any element node. |
1077 | | * If nsGkAtoms::href, look for an <a> element |
1078 | | * which has non-empty href attribute. |
1079 | | * If nsGkAtoms::anchor or atomized "namedanchor", |
1080 | | * look for an <a> element which has non-empty |
1081 | | * name attribute. |
1082 | | * @param aRv Returns error code. |
1083 | | * @return An element in first range of aSelection. |
1084 | | */ |
1085 | | already_AddRefed<Element> |
1086 | | GetSelectedElement(Selection& aSelection, |
1087 | | const nsAtom* aTagName, |
1088 | | ErrorResult& aRv); |
1089 | | |
1090 | | /** |
1091 | | * GetFirstTableRowElement() returns the first <tr> element in the most |
1092 | | * nearest ancestor of aTableOrElementInTable or itself. |
1093 | | * |
1094 | | * @param aTableOrElementInTable <table> element or another element. |
1095 | | * If this is a <table> element, returns |
1096 | | * first <tr> element in it. Otherwise, |
1097 | | * returns first <tr> element in nearest |
1098 | | * ancestor <table> element. |
1099 | | * @param aRv Returns an error code. When |
1100 | | * aTableOrElementInTable is neither |
1101 | | * <table> nor in a <table> element, |
1102 | | * returns NS_ERROR_FAILURE. |
1103 | | * However, if <table> does not have |
1104 | | * <tr> element, returns NS_OK. |
1105 | | */ |
1106 | | Element* |
1107 | | GetFirstTableRowElement(Element& aTableOrElementInTable, |
1108 | | ErrorResult& aRv) const; |
1109 | | |
1110 | | /** |
1111 | | * GetNextTableRowElement() returns next <tr> element of aTableRowElement. |
1112 | | * This won't cross <table> element boundary but may cross table section |
1113 | | * elements like <tbody>. |
1114 | | * |
1115 | | * @param aTableRowElement A <tr> element. |
1116 | | * @param aRv Returns error. If given element is <tr> but |
1117 | | * there is no next <tr> element, this returns |
1118 | | * nullptr but does not return error. |
1119 | | */ |
1120 | | Element* |
1121 | | GetNextTableRowElement(Element& aTableRowElement, |
1122 | | ErrorResult& aRv) const; |
1123 | | |
1124 | | struct CellAndIndexes; |
1125 | | |
1126 | | /** |
1127 | | * CellIndexes store both row index and column index of a table cell. |
1128 | | */ |
1129 | | struct MOZ_STACK_CLASS CellIndexes final |
1130 | | { |
1131 | | int32_t mRow; |
1132 | | int32_t mColumn; |
1133 | | |
1134 | | /** |
1135 | | * This constructor initializes mRowIndex and mColumnIndex with indexes of |
1136 | | * aCellElement. |
1137 | | * |
1138 | | * @param aCellElement An <td> or <th> element. |
1139 | | * @param aRv Returns error if layout information is not |
1140 | | * available or given element is not a table cell. |
1141 | | */ |
1142 | | CellIndexes(Element& aCellElement, ErrorResult& aRv) |
1143 | | : mRow(-1) |
1144 | | , mColumn(-1) |
1145 | 0 | { |
1146 | 0 | MOZ_ASSERT(!aRv.Failed()); |
1147 | 0 | Update(aCellElement, aRv); |
1148 | 0 | } |
1149 | | |
1150 | | /** |
1151 | | * Update mRowIndex and mColumnIndex with indexes of aCellElement. |
1152 | | * |
1153 | | * @param See above. |
1154 | | */ |
1155 | | void Update(Element& aCellElement, ErrorResult& aRv); |
1156 | | |
1157 | | /** |
1158 | | * This constructor initializes mRowIndex and mColumnIndex with indexes of |
1159 | | * cell element which contains anchor of Selection. |
1160 | | * |
1161 | | * @param aHTMLEditor The editor which creates the instance. |
1162 | | * @param aSelection The Selection for the editor. |
1163 | | * @param aRv Returns error if there is no cell element |
1164 | | * which contains anchor of Selection, or layout |
1165 | | * information is not available. |
1166 | | */ |
1167 | | CellIndexes(HTMLEditor& aHTMLEditor, Selection& aSelection, |
1168 | | ErrorResult& aRv) |
1169 | | : mRow(-1) |
1170 | | , mColumn(-1) |
1171 | 0 | { |
1172 | 0 | Update(aHTMLEditor, aSelection, aRv); |
1173 | 0 | } |
1174 | | |
1175 | | /** |
1176 | | * Update mRowIndex and mColumnIndex with indexes of cell element which |
1177 | | * contains anchor of Selection. |
1178 | | * |
1179 | | * @param See above. |
1180 | | */ |
1181 | | void Update(HTMLEditor& aHTMLEditor, Selection& aSelection, |
1182 | | ErrorResult& aRv); |
1183 | | |
1184 | | private: |
1185 | | CellIndexes() |
1186 | | : mRow(-1) |
1187 | | , mColumn(-1) |
1188 | 0 | { |
1189 | 0 | } |
1190 | | |
1191 | | friend struct CellAndIndexes; |
1192 | | }; |
1193 | | |
1194 | | struct MOZ_STACK_CLASS CellAndIndexes final |
1195 | | { |
1196 | | RefPtr<Element> mElement; |
1197 | | CellIndexes mIndexes; |
1198 | | |
1199 | | /** |
1200 | | * This constructor initializes the members with cell element which is |
1201 | | * selected by first range of the Selection. Note that even if the |
1202 | | * first range is in the cell element, this does not treat it as the |
1203 | | * cell element is selected. |
1204 | | */ |
1205 | | CellAndIndexes(HTMLEditor& aHTMLEditor, Selection& aSelection, |
1206 | | ErrorResult& aRv) |
1207 | 0 | { |
1208 | 0 | Update(aHTMLEditor, aSelection, aRv); |
1209 | 0 | } |
1210 | | |
1211 | | /** |
1212 | | * Update mElement and mIndexes with cell element which is selected by |
1213 | | * first range of the Selection. Note that even if the first range is |
1214 | | * in the cell element, this does not treat it as the cell element is |
1215 | | * selected. |
1216 | | */ |
1217 | | void Update(HTMLEditor& aHTMLEditor, Selection& aSelection, |
1218 | | ErrorResult& aRv); |
1219 | | }; |
1220 | | |
1221 | | /** |
1222 | | * TableSize stores and computes number of rows and columns of a <table> |
1223 | | * element. |
1224 | | */ |
1225 | | struct MOZ_STACK_CLASS TableSize final |
1226 | | { |
1227 | | int32_t mRowCount; |
1228 | | int32_t mColumnCount; |
1229 | | |
1230 | | /** |
1231 | | * @param aHTMLEditor The editor which creates the instance. |
1232 | | * @param aTableOrElementInTable If a <table> element, computes number |
1233 | | * of rows and columns of it. |
1234 | | * If another element in a <table> element, |
1235 | | * computes number of rows and columns |
1236 | | * of nearest ancestor <table> element. |
1237 | | * Otherwise, i.e., non-<table> element |
1238 | | * not in <table>, returns error. |
1239 | | * @param aRv Returns error if the element is not |
1240 | | * in <table> or layout information is |
1241 | | * not available. |
1242 | | */ |
1243 | | TableSize(HTMLEditor& aHTMLEditor, Element& aTableOrElementInTable, |
1244 | | ErrorResult& aRv) |
1245 | | : mRowCount(-1) |
1246 | | , mColumnCount(-1) |
1247 | 0 | { |
1248 | 0 | MOZ_ASSERT(!aRv.Failed()); |
1249 | 0 | Update(aHTMLEditor, aTableOrElementInTable, aRv); |
1250 | 0 | } |
1251 | | |
1252 | | /** |
1253 | | * Update mRowCount and mColumnCount for aTableOrElementInTable. |
1254 | | * See above for the detail. |
1255 | | */ |
1256 | | void Update(HTMLEditor& aHTMLEditor, Element& aTableOrElementInTable, |
1257 | | ErrorResult& aRv); |
1258 | | |
1259 | | bool IsEmpty() const |
1260 | 0 | { |
1261 | 0 | return !mRowCount || !mColumnCount; |
1262 | 0 | } |
1263 | | }; |
1264 | | |
1265 | | /** |
1266 | | * GetTableCellElementAt() returns a <td> or <th> element of aTableElement |
1267 | | * if there is a cell at the indexes. |
1268 | | * |
1269 | | * @param aTableElement Must be a <table> element. |
1270 | | * @param aCellIndexes Indexes of cell which you want. |
1271 | | * If rowspan and/or colspan is specified 2 or |
1272 | | * larger, any indexes are allowed to retrieve |
1273 | | * the cell in the area. |
1274 | | * @return The cell element if there is in the <table>. |
1275 | | * Returns nullptr without error if the indexes |
1276 | | * are out of bounds. |
1277 | | */ |
1278 | | Element* GetTableCellElementAt(Element& aTableElement, |
1279 | | const CellIndexes& aCellIndexes) const |
1280 | 0 | { |
1281 | 0 | return GetTableCellElementAt(aTableElement, aCellIndexes.mRow, |
1282 | 0 | aCellIndexes.mColumn); |
1283 | 0 | } |
1284 | | Element* GetTableCellElementAt(Element& aTableElement, |
1285 | | int32_t aRowIndex, |
1286 | | int32_t aColumnIndex) const; |
1287 | | |
1288 | | /** |
1289 | | * GetSelectedOrParentTableElement() returns <td>, <th>, <tr> or <table> |
1290 | | * element: |
1291 | | * #1 if the first selection range selects a cell, returns it. |
1292 | | * #2 if the first selection range does not select a cell and |
1293 | | * the selection anchor refers a <table>, returns it. |
1294 | | * #3 if the first selection range does not select a cell and |
1295 | | * the selection anchor refers a <tr>, returns it. |
1296 | | * #4 if the first selection range does not select a cell and |
1297 | | * the selection anchor refers a <td>, returns it. |
1298 | | * #5 otherwise, nearest ancestor <td> or <th> element of the |
1299 | | * selection anchor if there is. |
1300 | | * In #1 and #4, *aIsCellSelected will be set to true (i.e,, when |
1301 | | * a selection range selects a cell element). |
1302 | | */ |
1303 | | already_AddRefed<Element> |
1304 | | GetSelectedOrParentTableElement(Selection& aSelection, |
1305 | | ErrorResult& aRv, |
1306 | | bool* aIsCellSelected = nullptr) const; |
1307 | | |
1308 | | /** |
1309 | | * PasteInternal() pasts text with replacing selected content. |
1310 | | * This tries to dispatch ePaste event first. If its defaultPrevent() is |
1311 | | * called, this does nothing but returns NS_OK. |
1312 | | * |
1313 | | * @param aClipboardType nsIClipboard::kGlobalClipboard or |
1314 | | * nsIClipboard::kSelectionClipboard. |
1315 | | */ |
1316 | | nsresult PasteInternal(int32_t aClipboardType); |
1317 | | |
1318 | | /** |
1319 | | * InsertNodeIntoProperAncestorWithTransaction() attempts to insert aNode |
1320 | | * into the document, at aPointToInsert. Checks with strict dtd to see if |
1321 | | * containment is allowed. If not allowed, will attempt to find a parent |
1322 | | * in the parent hierarchy of aPointToInsert.GetContainer() that will accept |
1323 | | * aNode as a child. If such a parent is found, will split the document |
1324 | | * tree from aPointToInsert up to parent, and then insert aNode. |
1325 | | * aPointToInsert is then adjusted to point to the actual location that |
1326 | | * aNode was inserted at. aSplitAtEdges specifies if the splitting process |
1327 | | * is allowed to result in empty nodes. |
1328 | | * |
1329 | | * @param aNode Node to insert. |
1330 | | * @param aPointToInsert Insertion point. |
1331 | | * @param aSplitAtEdges Splitting can result in empty nodes? |
1332 | | * @return Returns inserted point if succeeded. |
1333 | | * Otherwise, the result is not set. |
1334 | | */ |
1335 | | template<typename PT, typename CT> |
1336 | | EditorDOMPoint |
1337 | | InsertNodeIntoProperAncestorWithTransaction( |
1338 | | nsIContent& aNode, |
1339 | | const EditorDOMPointBase<PT, CT>& aPointToInsert, |
1340 | | SplitAtEdges aSplitAtEdges); |
1341 | | |
1342 | | /** |
1343 | | * InsertBrElementAtSelectionWithTransaction() inserts a new <br> element at |
1344 | | * selection. If there is non-collapsed selection ranges, the selected |
1345 | | * ranges is deleted first. |
1346 | | */ |
1347 | | nsresult InsertBrElementAtSelectionWithTransaction(); |
1348 | | |
1349 | | /** |
1350 | | * InsertTextWithQuotationsInternal() replaces selection with new content. |
1351 | | * First, this method splits aStringToInsert to multiple chunks which start |
1352 | | * with non-linebreaker except first chunk and end with a linebreaker except |
1353 | | * last chunk. Then, each chunk starting with ">" is inserted after wrapping |
1354 | | * with <span _moz_quote="true">, and each chunk not starting with ">" is |
1355 | | * inserted as normal text. |
1356 | | */ |
1357 | | nsresult InsertTextWithQuotationsInternal(const nsAString& aStringToInsert); |
1358 | | |
1359 | | /** |
1360 | | * IndentOrOutdentAsSubAction() indents or outdents the content around |
1361 | | * Selection. Callers have to guarantee that there is a placeholder |
1362 | | * transaction. |
1363 | | * |
1364 | | * @param aEditSubAction Must be EditSubAction::eIndent or |
1365 | | * EditSubAction::eOutdent. |
1366 | | */ |
1367 | | nsresult IndentOrOutdentAsSubAction(EditSubAction aEditSubAction); |
1368 | | |
1369 | | nsresult LoadHTML(const nsAString& aInputString); |
1370 | | |
1371 | | nsresult SetInlinePropertyInternal(nsAtom& aProperty, |
1372 | | nsAtom* aAttribute, |
1373 | | const nsAString& aValue); |
1374 | | nsresult RemoveInlinePropertyInternal(nsAtom* aProperty, |
1375 | | nsAtom* aAttribute); |
1376 | | |
1377 | | /** |
1378 | | * ReplaceHeadContentsWithSourceWithTransaction() replaces all children of |
1379 | | * <head> element with given source code. This is undoable. |
1380 | | * |
1381 | | * @param aSourceToInsert HTML source fragment to replace the children |
1382 | | * of <head> element. |
1383 | | */ |
1384 | | nsresult |
1385 | | ReplaceHeadContentsWithSourceWithTransaction( |
1386 | | const nsAString& aSourceToInsert); |
1387 | | |
1388 | | nsresult GetCSSBackgroundColorState(bool* aMixed, nsAString& aOutColor, |
1389 | | bool aBlockLevel); |
1390 | | nsresult GetHTMLBackgroundColorState(bool* aMixed, nsAString& outColor); |
1391 | | |
1392 | | nsresult GetLastCellInRow(nsINode* aRowNode, |
1393 | | nsINode** aCellNode); |
1394 | | |
1395 | | static nsresult GetCellFromRange(nsRange* aRange, Element** aCell); |
1396 | | |
1397 | | /** |
1398 | | * This sets background on the appropriate container element (table, cell,) |
1399 | | * or calls into nsTextEditor to set the page background. |
1400 | | */ |
1401 | | nsresult SetCSSBackgroundColorWithTransaction(const nsAString& aColor); |
1402 | | nsresult SetHTMLBackgroundColorWithTransaction(const nsAString& aColor); |
1403 | | |
1404 | | virtual void |
1405 | | InitializeSelectionAncestorLimit(Selection& aSelection, |
1406 | | nsIContent& aAncestorLimit) override; |
1407 | | |
1408 | | /** |
1409 | | * Make the given selection span the entire document. |
1410 | | */ |
1411 | | virtual nsresult SelectEntireDocument(Selection* aSelection) override; |
1412 | | |
1413 | | /** |
1414 | | * Use this to assure that selection is set after attribute nodes when |
1415 | | * trying to collapse selection at begining of a block node |
1416 | | * e.g., when setting at beginning of a table cell |
1417 | | * This will stop at a table, however, since we don't want to |
1418 | | * "drill down" into nested tables. |
1419 | | * @param aSelection Optional. If null, we get current selection. |
1420 | | */ |
1421 | | void CollapseSelectionToDeepestNonTableFirstChild(Selection* aSelection, |
1422 | | nsINode* aNode); |
1423 | | |
1424 | | /** |
1425 | | * Returns TRUE if sheet was loaded, false if it wasn't. |
1426 | | */ |
1427 | | bool EnableExistingStyleSheet(const nsAString& aURL); |
1428 | | |
1429 | | /** |
1430 | | * GetStyleSheetForURL() returns a pointer to StyleSheet which was added |
1431 | | * with AddOverrideStyleSheetInternal(). If it's not found, returns nullptr. |
1432 | | * |
1433 | | * @param aURL URL to the style sheet. |
1434 | | */ |
1435 | | StyleSheet* GetStyleSheetForURL(const nsAString& aURL); |
1436 | | |
1437 | | /** |
1438 | | * Add a url + known style sheet to the internal lists. |
1439 | | */ |
1440 | | nsresult AddNewStyleSheetToList(const nsAString &aURL, |
1441 | | StyleSheet* aStyleSheet); |
1442 | | |
1443 | | /** |
1444 | | * Removes style sheet from the internal lists. |
1445 | | * |
1446 | | * @param aURL URL to the style sheet. |
1447 | | * @return If the URL is in the internal list, returns the |
1448 | | * removed style sheet. Otherwise, i.e., not found, |
1449 | | * nullptr. |
1450 | | */ |
1451 | | already_AddRefed<StyleSheet> RemoveStyleSheetFromList(const nsAString& aURL); |
1452 | | |
1453 | | /** |
1454 | | * Add and apply the style sheet synchronously. |
1455 | | * |
1456 | | * @param aURL URL to the style sheet. |
1457 | | */ |
1458 | | nsresult AddOverrideStyleSheetInternal(const nsAString& aURL); |
1459 | | |
1460 | | /** |
1461 | | * Remove the style sheet from this editor synchronously. |
1462 | | * |
1463 | | * @param aURL URL to the style sheet. |
1464 | | * @return Even if there is no specified style sheet in the |
1465 | | * internal lists, this returns NS_OK. |
1466 | | */ |
1467 | | nsresult RemoveOverrideStyleSheetInternal(const nsAString& aURL); |
1468 | | |
1469 | | /** |
1470 | | * Enable or disable the style sheet synchronously. |
1471 | | * aURL is just a key to specify a style sheet in the internal array. |
1472 | | * I.e., the style sheet has already been registered with |
1473 | | * AddOverrideStyleSheetInternal(). |
1474 | | * |
1475 | | * @param aURL URL to the style sheet. |
1476 | | * @param aEnable true if enable the style sheet. false if disable it. |
1477 | | */ |
1478 | | void EnableStyleSheetInternal(const nsAString& aURL, bool aEnable); |
1479 | | |
1480 | | /** |
1481 | | * MaybeCollapseSelectionAtFirstEditableNode() may collapse selection at |
1482 | | * proper position to staring to edit. If there is a non-editable node |
1483 | | * before any editable text nodes or inline elements which can have text |
1484 | | * nodes as their children, collapse selection at start of the editing |
1485 | | * host. If there is an editable text node which is not collapsed, collapses |
1486 | | * selection at the start of the text node. If there is an editable inline |
1487 | | * element which cannot have text nodes as its child, collapses selection at |
1488 | | * before the element node. Otherwise, collapses selection at start of the |
1489 | | * editing host. |
1490 | | * |
1491 | | * @param aIgnoreIfSelectionInEditingHost |
1492 | | * This method does nothing if selection is in the |
1493 | | * editing host except if it's collapsed at start of |
1494 | | * the editing host. |
1495 | | * Note that if selection ranges were outside of |
1496 | | * current selection limiter, selection was collapsed |
1497 | | * at the start of the editing host therefore, if |
1498 | | * you call this with setting this to true, you can |
1499 | | * keep selection ranges if user has already been |
1500 | | * changed. |
1501 | | */ |
1502 | | nsresult |
1503 | | MaybeCollapseSelectionAtFirstEditableNode( |
1504 | | bool aIgnoreIfSelectionInEditingHost); |
1505 | | |
1506 | | class BlobReader final |
1507 | | { |
1508 | | public: |
1509 | | BlobReader(dom::BlobImpl* aBlob, HTMLEditor* aHTMLEditor, |
1510 | | bool aIsSafe, nsIDocument* aSourceDoc, |
1511 | | nsINode* aDestinationNode, int32_t aDestOffset, |
1512 | | bool aDoDeleteSelection); |
1513 | | |
1514 | | NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(BlobReader) |
1515 | | NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(BlobReader) |
1516 | | |
1517 | | nsresult OnResult(const nsACString& aResult); |
1518 | | nsresult OnError(const nsAString& aErrorName); |
1519 | | |
1520 | | private: |
1521 | | ~BlobReader() |
1522 | 0 | { |
1523 | 0 | } |
1524 | | |
1525 | | RefPtr<dom::BlobImpl> mBlob; |
1526 | | RefPtr<HTMLEditor> mHTMLEditor; |
1527 | | bool mIsSafe; |
1528 | | nsCOMPtr<nsIDocument> mSourceDoc; |
1529 | | nsCOMPtr<nsINode> mDestinationNode; |
1530 | | int32_t mDestOffset; |
1531 | | bool mDoDeleteSelection; |
1532 | | }; |
1533 | | |
1534 | | virtual nsresult InitRules() override; |
1535 | | |
1536 | | virtual void CreateEventListeners() override; |
1537 | | virtual nsresult InstallEventListeners() override; |
1538 | | virtual void RemoveEventListeners() override; |
1539 | | |
1540 | | bool ShouldReplaceRootElement(); |
1541 | | void NotifyRootChanged(); |
1542 | | Element* GetBodyElement(); |
1543 | | |
1544 | | /** |
1545 | | * Get the focused node of this editor. |
1546 | | * @return If the editor has focus, this returns the focused node. |
1547 | | * Otherwise, returns null. |
1548 | | */ |
1549 | | already_AddRefed<nsINode> GetFocusedNode(); |
1550 | | |
1551 | | virtual already_AddRefed<nsIContent> GetInputEventTargetContent() override; |
1552 | | |
1553 | | /** |
1554 | | * Return TRUE if aElement is a table-related elemet and caret was set. |
1555 | | */ |
1556 | | bool SetCaretInTableCell(dom::Element* aElement); |
1557 | | |
1558 | | nsresult TabInTable(bool inIsShift, bool* outHandled); |
1559 | | |
1560 | | /** |
1561 | | * InsertPosition is an enum to indicate where the method should insert to. |
1562 | | */ |
1563 | | enum class InsertPosition |
1564 | | { |
1565 | | // Before selected cell or a cell containing first selection range. |
1566 | | eBeforeSelectedCell, |
1567 | | // After selected cell or a cell containing first selection range. |
1568 | | eAfterSelectedCell, |
1569 | | }; |
1570 | | |
1571 | | /** |
1572 | | * InsertTableCellsWithTransaction() inserts <td> elements before or after |
1573 | | * a cell element containing first selection range. I.e., if the cell |
1574 | | * spans columns and aInsertPosition is eAfterSelectedCell, new columns |
1575 | | * will be inserted after the right-most column which contains the cell. |
1576 | | * Note that this simply inserts <td> elements, i.e., colspan and rowspan |
1577 | | * around the cell containing selection are not modified. So, for example, |
1578 | | * adding a cell to rectangular table changes non-rectangular table. |
1579 | | * And if the cell containing selection is at left of row-spanning cell, |
1580 | | * it may be moved to right side of the row-spanning cell after inserting |
1581 | | * some cell elements before it. Similarly, colspan won't be adjusted |
1582 | | * for keeping table rectangle. |
1583 | | * If first selection range is not in table cell element, this does nothing |
1584 | | * but does not return error. |
1585 | | * |
1586 | | * @param aNumberOfCellssToInsert Number of cells to insert. |
1587 | | * @param aInsertPosition Before or after the target cell which |
1588 | | * contains first selection range. |
1589 | | */ |
1590 | | nsresult InsertTableCellsWithTransaction(int32_t aNumberOfCellsToInsert, |
1591 | | InsertPosition aInsertPosition); |
1592 | | |
1593 | | /** |
1594 | | * InsertTableColumnsWithTransaction() inserts columns before or after |
1595 | | * a cell element containing first selection range. I.e., if the cell |
1596 | | * spans columns and aInsertPosition is eAfterSelectedCell, new columns |
1597 | | * will be inserted after the right-most row which contains the cell. |
1598 | | * If first selection range is not in table cell element, this does nothing |
1599 | | * but does not return error. |
1600 | | * |
1601 | | * @param aNumberOfColumnsToInsert Number of columns to insert. |
1602 | | * @param aInsertPosition Before or after the target cell which |
1603 | | * contains first selection range. |
1604 | | */ |
1605 | | nsresult InsertTableColumnsWithTransaction(int32_t aNumberOfColumnsToInsert, |
1606 | | InsertPosition aInsertPosition); |
1607 | | |
1608 | | /** |
1609 | | * InsertTableRowsWithTransaction() inserts <tr> elements before or after |
1610 | | * a cell element containing first selection range. I.e., if the cell |
1611 | | * spans rows and aInsertPosition is eAfterSelectedCell, new rows will be |
1612 | | * inserted after the most-bottom row which contains the cell. If first |
1613 | | * selection range is not in table cell element, this does nothing but |
1614 | | * does not return error. |
1615 | | * |
1616 | | * @param aNumberOfRowsToInsert Number of rows to insert. |
1617 | | * @param aInsertPosition Before or after the target cell which |
1618 | | * contains first selection range. |
1619 | | */ |
1620 | | nsresult InsertTableRowsWithTransaction(int32_t aNumberOfRowsToInsert, |
1621 | | InsertPosition aInsertPosition); |
1622 | | |
1623 | | /** |
1624 | | * Insert a new cell after or before supplied aCell. |
1625 | | * Optional: If aNewCell supplied, returns the newly-created cell (addref'd, |
1626 | | * of course) |
1627 | | * This doesn't change or use the current selection. |
1628 | | */ |
1629 | | nsresult InsertCell(Element* aCell, int32_t aRowSpan, |
1630 | | int32_t aColSpan, bool aAfter, bool aIsHeader, |
1631 | | Element** aNewCell); |
1632 | | |
1633 | | /** |
1634 | | * DeleteSelectedTableColumnsWithTransaction() removes cell elements which |
1635 | | * belong to same columns of selected cell elements. |
1636 | | * If only one cell element is selected or first selection range is |
1637 | | * in a cell, removes cell elements which belong to same column. |
1638 | | * If 2 or more cell elements are selected, removes cell elements which |
1639 | | * belong to any of all selected columns. In this case, |
1640 | | * aNumberOfColumnsToDelete is ignored. |
1641 | | * If there is no selection ranges, returns error. |
1642 | | * If selection is not in a cell element, this does not return error, |
1643 | | * just does nothing. |
1644 | | * WARNING: This does not remove <col> nor <colgroup> elements. |
1645 | | * |
1646 | | * @param aNumberOfColumnsToDelete Number of columns to remove. This is |
1647 | | * ignored if 2 ore more cells are |
1648 | | * selected. |
1649 | | */ |
1650 | | nsresult |
1651 | | DeleteSelectedTableColumnsWithTransaction(int32_t aNumberOfColumnsToDelete); |
1652 | | |
1653 | | /** |
1654 | | * DeleteTableColumnWithTransaction() removes cell elements which belong |
1655 | | * to the specified column. |
1656 | | * This method adjusts colspan attribute value if cells spanning the |
1657 | | * column to delete. |
1658 | | * WARNING: This does not remove <col> nor <colgroup> elements. |
1659 | | * |
1660 | | * @param aTableElement The <table> element which contains the |
1661 | | * column which you want to remove. |
1662 | | * @param aRowIndex Index of the column which you want to remove. |
1663 | | * 0 is the first column. |
1664 | | */ |
1665 | | nsresult |
1666 | | DeleteTableColumnWithTransaction(Element& aTableElement, |
1667 | | int32_t aColumnIndex); |
1668 | | |
1669 | | /** |
1670 | | * DeleteSelectedTableRowsWithTransaction() removes <tr> elements. |
1671 | | * If only one cell element is selected or first selection range is |
1672 | | * in a cell, removes <tr> elements starting from a <tr> element |
1673 | | * containing the selected cell or first selection range. |
1674 | | * If 2 or more cell elements are selected, all <tr> elements |
1675 | | * which contains selected cell(s). In this case, aNumberOfRowsToDelete |
1676 | | * is ignored. |
1677 | | * If there is no selection ranges, returns error. |
1678 | | * If selection is not in a cell element, this does not return error, |
1679 | | * just does nothing. |
1680 | | * |
1681 | | * @param aNumberOfRowsToDelete Number of rows to remove. This is ignored |
1682 | | * if 2 or more cells are selected. |
1683 | | */ |
1684 | | nsresult |
1685 | | DeleteSelectedTableRowsWithTransaction(int32_t aNumberOfRowsToDelete); |
1686 | | |
1687 | | /** |
1688 | | * DeleteTableRowWithTransaction() removes a <tr> element whose index in |
1689 | | * the <table> is aRowIndex. |
1690 | | * This method adjusts rowspan attribute value if the <tr> element contains |
1691 | | * cells which spans rows. |
1692 | | * |
1693 | | * @param aTableElement The <table> element which contains the |
1694 | | * <tr> element which you want to remove. |
1695 | | * @param aRowIndex Index of the <tr> element which you want to |
1696 | | * remove. 0 is the first row. |
1697 | | */ |
1698 | | nsresult |
1699 | | DeleteTableRowWithTransaction(Element& aTableElement, int32_t aRowIndex); |
1700 | | |
1701 | | /** |
1702 | | * DeleteTableCellWithTransaction() removes table cell elements. If two or |
1703 | | * more cell elements are selected, this removes all selected cell elements. |
1704 | | * Otherwise, this removes some cell elements starting from selected cell |
1705 | | * element or a cell containing first selection range. When this removes |
1706 | | * last cell element in <tr> or <table>, this removes the <tr> or the |
1707 | | * <table> too. Note that when removing a cell causes number of its row |
1708 | | * becomes less than the others, this method does NOT fill the place with |
1709 | | * rowspan nor colspan. This does not return error even if selection is not |
1710 | | * in cell element, just does nothing. |
1711 | | * |
1712 | | * @param aNumberOfCellsToDelete Number of cells to remove. This is ignored |
1713 | | * if 2 or more cells are selected. |
1714 | | */ |
1715 | | nsresult DeleteTableCellWithTransaction(int32_t aNumberOfCellsToDelete); |
1716 | | |
1717 | | /** |
1718 | | * DeleteAllChildrenWithTransaction() removes all children of aElement from |
1719 | | * the tree. |
1720 | | * |
1721 | | * @param aElement The element whose children you want to remove. |
1722 | | */ |
1723 | | nsresult DeleteAllChildrenWithTransaction(Element& aElement); |
1724 | | |
1725 | | /** |
1726 | | * Move all contents from aCellToMerge into aTargetCell (append at end). |
1727 | | */ |
1728 | | nsresult MergeCells(RefPtr<Element> aTargetCell, |
1729 | | RefPtr<Element> aCellToMerge, |
1730 | | bool aDeleteCellToMerge); |
1731 | | |
1732 | | /** |
1733 | | * DeleteTableElementAndChildren() removes aTableElement (and its children) |
1734 | | * from the DOM tree with transaction. |
1735 | | * |
1736 | | * @param aSelection The normal Selection for the editor. |
1737 | | * @param aTableElement The <table> element which you want to remove. |
1738 | | */ |
1739 | | nsresult |
1740 | | DeleteTableElementAndChildrenWithTransaction(Selection& aSelection, |
1741 | | Element& aTableElement); |
1742 | | |
1743 | | nsresult SetColSpan(Element* aCell, int32_t aColSpan); |
1744 | | nsresult SetRowSpan(Element* aCell, int32_t aRowSpan); |
1745 | | |
1746 | | /** |
1747 | | * Helper used to get nsTableWrapperFrame for a table. |
1748 | | */ |
1749 | | static nsTableWrapperFrame* GetTableFrame(Element* aTable); |
1750 | | |
1751 | | /** |
1752 | | * GetNumberOfCellsInRow() returns number of actual cell elements in the row. |
1753 | | * If some cells appear by "rowspan" in other rows, they are ignored. |
1754 | | * |
1755 | | * @param aTableElement The <table> element. |
1756 | | * @param aRowIndex Valid row index in aTableElement. This method |
1757 | | * counts cell elements in the row. |
1758 | | * @return -1 if this meets unexpected error. |
1759 | | * Otherwise, number of cells which this method found. |
1760 | | */ |
1761 | | int32_t GetNumberOfCellsInRow(Element& aTableElement, int32_t aRowIndex); |
1762 | | |
1763 | | /** |
1764 | | * Test if all cells in row or column at given index are selected. |
1765 | | */ |
1766 | | bool AllCellsInRowSelected(Element* aTable, int32_t aRowIndex, |
1767 | | int32_t aNumberOfColumns); |
1768 | | bool AllCellsInColumnSelected(Element* aTable, int32_t aColIndex, |
1769 | | int32_t aNumberOfRows); |
1770 | | |
1771 | | bool IsEmptyCell(Element* aCell); |
1772 | | |
1773 | | /** |
1774 | | * Most insert methods need to get the same basic context data. |
1775 | | * Any of the pointers may be null if you don't need that datum (for more |
1776 | | * efficiency). |
1777 | | * Input: *aCell is a known cell, |
1778 | | * if null, cell is obtained from the anchor node of the selection. |
1779 | | * Returns NS_EDITOR_ELEMENT_NOT_FOUND if cell is not found even if aCell is |
1780 | | * null. |
1781 | | */ |
1782 | | nsresult GetCellContext(Selection** aSelection, Element** aTable, |
1783 | | Element** aCell, nsINode** aCellParent, |
1784 | | int32_t* aCellOffset, int32_t* aRowIndex, |
1785 | | int32_t* aColIndex); |
1786 | | |
1787 | | nsresult GetCellSpansAt(Element* aTable, int32_t aRowIndex, |
1788 | | int32_t aColIndex, int32_t& aActualRowSpan, |
1789 | | int32_t& aActualColSpan); |
1790 | | |
1791 | | nsresult SplitCellIntoColumns(Element* aTable, int32_t aRowIndex, |
1792 | | int32_t aColIndex, int32_t aColSpanLeft, |
1793 | | int32_t aColSpanRight, |
1794 | | Element** aNewCell); |
1795 | | |
1796 | | nsresult SplitCellIntoRows(Element* aTable, int32_t aRowIndex, |
1797 | | int32_t aColIndex, int32_t aRowSpanAbove, |
1798 | | int32_t aRowSpanBelow, Element** aNewCell); |
1799 | | |
1800 | | nsresult CopyCellBackgroundColor(Element* aDestCell, |
1801 | | Element* aSourceCell); |
1802 | | |
1803 | | /** |
1804 | | * Reduce rowspan/colspan when cells span into nonexistent rows/columns. |
1805 | | */ |
1806 | | nsresult FixBadRowSpan(Element* aTable, int32_t aRowIndex, |
1807 | | int32_t& aNewRowCount); |
1808 | | nsresult FixBadColSpan(Element* aTable, int32_t aColIndex, |
1809 | | int32_t& aNewColCount); |
1810 | | |
1811 | | /** |
1812 | | * XXX NormalizeTable() is broken. If it meets a cell which has bigger or |
1813 | | * smaller rowspan or colspan than actual number of cells, this always |
1814 | | * failed to scan the table. Therefore, this does nothing when the |
1815 | | * table should be normalized. |
1816 | | * |
1817 | | * @param aSelection The Selection for the editor. |
1818 | | * @param aTableOrElementInTable An element which is in a <table> element |
1819 | | * or <table> element itself. Otherwise, |
1820 | | * this returns NS_OK but does nothing. |
1821 | | */ |
1822 | | nsresult NormalizeTable(Selection& aSelection, |
1823 | | Element& aTableOrElementInTable); |
1824 | | |
1825 | | /** |
1826 | | * Fallback method: Call this after using ClearSelection() and you |
1827 | | * failed to set selection to some other content in the document. |
1828 | | */ |
1829 | | nsresult SetSelectionAtDocumentStart(Selection* aSelection); |
1830 | | |
1831 | | static Element* GetEnclosingTable(nsINode* aNode); |
1832 | | |
1833 | | // Methods for handling plaintext quotations |
1834 | | nsresult PasteAsPlaintextQuotation(int32_t aSelectionType); |
1835 | | |
1836 | | /** |
1837 | | * Insert a string as quoted text, replacing the selected text (if any). |
1838 | | * @param aQuotedText The string to insert. |
1839 | | * @param aAddCites Whether to prepend extra ">" to each line |
1840 | | * (usually true, unless those characters |
1841 | | * have already been added.) |
1842 | | * @return aNodeInserted The node spanning the insertion, if applicable. |
1843 | | * If aAddCites is false, this will be null. |
1844 | | */ |
1845 | | nsresult InsertAsPlaintextQuotation(const nsAString& aQuotedText, |
1846 | | bool aAddCites, |
1847 | | nsINode** aNodeInserted); |
1848 | | |
1849 | | nsresult InsertObject(const nsACString& aType, nsISupports* aObject, |
1850 | | bool aIsSafe, |
1851 | | nsIDocument* aSourceDoc, |
1852 | | nsINode* aDestinationNode, |
1853 | | int32_t aDestOffset, |
1854 | | bool aDoDeleteSelection); |
1855 | | |
1856 | | // factored methods for handling insertion of data from transferables |
1857 | | // (drag&drop or clipboard) |
1858 | | virtual nsresult PrepareTransferable(nsITransferable** transferable) override; |
1859 | | nsresult PrepareHTMLTransferable(nsITransferable** transferable); |
1860 | | nsresult InsertFromTransferable(nsITransferable* transferable, |
1861 | | nsIDocument* aSourceDoc, |
1862 | | const nsAString& aContextStr, |
1863 | | const nsAString& aInfoStr, |
1864 | | bool havePrivateHTMLFlavor, |
1865 | | bool aDoDeleteSelection); |
1866 | | virtual nsresult InsertFromDataTransfer(dom::DataTransfer* aDataTransfer, |
1867 | | int32_t aIndex, |
1868 | | nsIDocument* aSourceDoc, |
1869 | | nsINode* aDestinationNode, |
1870 | | int32_t aDestOffset, |
1871 | | bool aDoDeleteSelection) override; |
1872 | | bool HavePrivateHTMLFlavor(nsIClipboard* clipboard ); |
1873 | | nsresult ParseCFHTML(nsCString& aCfhtml, char16_t** aStuffToPaste, |
1874 | | char16_t** aCfcontext); |
1875 | | |
1876 | | nsresult StripFormattingNodes(nsIContent& aNode, bool aOnlyList = false); |
1877 | | nsresult CreateDOMFragmentFromPaste(const nsAString& aInputString, |
1878 | | const nsAString& aContextStr, |
1879 | | const nsAString& aInfoStr, |
1880 | | nsCOMPtr<nsINode>* outFragNode, |
1881 | | nsCOMPtr<nsINode>* outStartNode, |
1882 | | nsCOMPtr<nsINode>* outEndNode, |
1883 | | int32_t* outStartOffset, |
1884 | | int32_t* outEndOffset, |
1885 | | bool aTrustedInput); |
1886 | | nsresult ParseFragment(const nsAString& aStr, nsAtom* aContextLocalName, |
1887 | | nsIDocument* aTargetDoc, |
1888 | | dom::DocumentFragment** aFragment, bool aTrustedInput); |
1889 | | void CreateListOfNodesToPaste(dom::DocumentFragment& aFragment, |
1890 | | nsTArray<OwningNonNull<nsINode>>& outNodeList, |
1891 | | nsINode* aStartContainer, |
1892 | | int32_t aStartOffset, |
1893 | | nsINode* aEndContainer, |
1894 | | int32_t aEndOffset); |
1895 | | enum class StartOrEnd { start, end }; |
1896 | | void GetListAndTableParents(StartOrEnd aStartOrEnd, |
1897 | | nsTArray<OwningNonNull<nsINode>>& aNodeList, |
1898 | | nsTArray<OwningNonNull<Element>>& outArray); |
1899 | | int32_t DiscoverPartialListsAndTables( |
1900 | | nsTArray<OwningNonNull<nsINode>>& aPasteNodes, |
1901 | | nsTArray<OwningNonNull<Element>>& aListsAndTables); |
1902 | | nsINode* ScanForListAndTableStructure( |
1903 | | StartOrEnd aStartOrEnd, |
1904 | | nsTArray<OwningNonNull<nsINode>>& aNodes, |
1905 | | Element& aListOrTable); |
1906 | | void ReplaceOrphanedStructure( |
1907 | | StartOrEnd aStartOrEnd, |
1908 | | nsTArray<OwningNonNull<nsINode>>& aNodeArray, |
1909 | | nsTArray<OwningNonNull<Element>>& aListAndTableArray, |
1910 | | int32_t aHighWaterMark); |
1911 | | |
1912 | | /** |
1913 | | * GetBetterInsertionPointFor() returns better insertion point to insert |
1914 | | * aNodeToInsert. |
1915 | | * |
1916 | | * @param aNodeToInsert The node to insert. |
1917 | | * @param aPointToInsert A candidate point to insert the node. |
1918 | | * @return Better insertion point if next visible node |
1919 | | * is a <br> element and previous visible node |
1920 | | * is neither none, another <br> element nor |
1921 | | * different block level element. |
1922 | | */ |
1923 | | EditorRawDOMPoint |
1924 | | GetBetterInsertionPointFor(nsINode& aNodeToInsert, |
1925 | | const EditorRawDOMPoint& aPointToInsert); |
1926 | | |
1927 | | /** |
1928 | | * MakeDefinitionListItemWithTransaction() replaces parent list of current |
1929 | | * selection with <dl> or create new <dl> element and creates a definition |
1930 | | * list item whose name is aTagName. |
1931 | | * |
1932 | | * @param aTagName Must be nsGkAtoms::dt or nsGkAtoms::dd. |
1933 | | */ |
1934 | | nsresult MakeDefinitionListItemWithTransaction(nsAtom& aTagName); |
1935 | | |
1936 | | /** |
1937 | | * InsertBasicBlockWithTransaction() inserts a block element whose name |
1938 | | * is aTagName at selection. |
1939 | | * |
1940 | | * @param aTagName A block level element name. Must NOT be |
1941 | | * nsGkAtoms::dt nor nsGkAtoms::dd. |
1942 | | */ |
1943 | | nsresult InsertBasicBlockWithTransaction(nsAtom& aTagName); |
1944 | | |
1945 | | /** |
1946 | | * Increase/decrease the font size of selection. |
1947 | | */ |
1948 | | nsresult RelativeFontChange(FontSize aDir); |
1949 | | |
1950 | | nsresult RelativeFontChangeOnNode(int32_t aSizeChange, nsIContent* aNode); |
1951 | | nsresult RelativeFontChangeHelper(int32_t aSizeChange, nsINode* aNode); |
1952 | | |
1953 | | /** |
1954 | | * Helper routines for inline style. |
1955 | | */ |
1956 | | nsresult SetInlinePropertyOnTextNode(Text& aData, |
1957 | | int32_t aStartOffset, |
1958 | | int32_t aEndOffset, |
1959 | | nsAtom& aProperty, |
1960 | | nsAtom* aAttribute, |
1961 | | const nsAString& aValue); |
1962 | | |
1963 | | nsresult PromoteInlineRange(nsRange& aRange); |
1964 | | nsresult PromoteRangeIfStartsOrEndsInNamedAnchor(nsRange& aRange); |
1965 | | nsresult SplitStyleAboveRange(nsRange* aRange, |
1966 | | nsAtom* aProperty, |
1967 | | nsAtom* aAttribute); |
1968 | | nsresult RemoveStyleInside(nsIContent& aNode, |
1969 | | nsAtom* aProperty, |
1970 | | nsAtom* aAttribute, |
1971 | | const bool aChildrenOnly = false); |
1972 | | |
1973 | | bool NodeIsProperty(nsINode& aNode); |
1974 | | bool IsAtFrontOfNode(nsINode& aNode, int32_t aOffset); |
1975 | | bool IsAtEndOfNode(nsINode& aNode, int32_t aOffset); |
1976 | | bool IsOnlyAttribute(const Element* aElement, nsAtom* aAttribute); |
1977 | | |
1978 | | bool HasStyleOrIdOrClass(Element* aElement); |
1979 | | nsresult RemoveElementIfNoStyleOrIdOrClass(Element& aElement); |
1980 | | |
1981 | | /** |
1982 | | * Whether the outer window of the DOM event target has focus or not. |
1983 | | */ |
1984 | | bool OurWindowHasFocus(); |
1985 | | |
1986 | | /** |
1987 | | * This function is used to insert a string of HTML input optionally with some |
1988 | | * context information into the editable field. The HTML input either comes |
1989 | | * from a transferable object created as part of a drop/paste operation, or |
1990 | | * from the InsertHTML method. We may want the HTML input to be sanitized |
1991 | | * (for example, if it's coming from a transferable object), in which case |
1992 | | * aTrustedInput should be set to false, otherwise, the caller should set it |
1993 | | * to true, which means that the HTML will be inserted in the DOM verbatim. |
1994 | | * |
1995 | | * aClearStyle should be set to false if you want the paste to be affected by |
1996 | | * local style (e.g., for the insertHTML command). |
1997 | | */ |
1998 | | nsresult DoInsertHTMLWithContext(const nsAString& aInputString, |
1999 | | const nsAString& aContextStr, |
2000 | | const nsAString& aInfoStr, |
2001 | | const nsAString& aFlavor, |
2002 | | nsIDocument* aSourceDoc, |
2003 | | nsINode* aDestNode, |
2004 | | int32_t aDestOffset, |
2005 | | bool aDeleteSelection, |
2006 | | bool aTrustedInput, |
2007 | | bool aClearStyle = true); |
2008 | | |
2009 | | /** |
2010 | | * sets the position of an element; warning it does NOT check if the |
2011 | | * element is already positioned or not and that's on purpose. |
2012 | | * @param aElement [IN] the element |
2013 | | * @param aX [IN] the x position in pixels. |
2014 | | * @param aY [IN] the y position in pixels. |
2015 | | */ |
2016 | | void SetTopAndLeft(Element& aElement, int32_t aX, int32_t aY); |
2017 | | |
2018 | | /** |
2019 | | * Reset a selected cell or collapsed selection (the caret) after table |
2020 | | * editing. |
2021 | | * |
2022 | | * @param aTable A table in the document. |
2023 | | * @param aRow The row ... |
2024 | | * @param aCol ... and column defining the cell where we will try to |
2025 | | * place the caret. |
2026 | | * @param aSelected If true, we select the whole cell instead of setting |
2027 | | * caret. |
2028 | | * @param aDirection If cell at (aCol, aRow) is not found, search for |
2029 | | * previous cell in the same column (aPreviousColumn) or |
2030 | | * row (ePreviousRow) or don't search for another cell |
2031 | | * (aNoSearch). If no cell is found, caret is place just |
2032 | | * before table; and if that fails, at beginning of |
2033 | | * document. Thus we generally don't worry about the |
2034 | | * return value and can use the |
2035 | | * AutoSelectionSetterAfterTableEdit stack-based object to |
2036 | | * insure we reset the caret in a table-editing method. |
2037 | | */ |
2038 | | void SetSelectionAfterTableEdit(Element* aTable, |
2039 | | int32_t aRow, int32_t aCol, |
2040 | | int32_t aDirection, bool aSelected); |
2041 | | |
2042 | | void RemoveListenerAndDeleteRef(const nsAString& aEvent, |
2043 | | nsIDOMEventListener* aListener, |
2044 | | bool aUseCapture, |
2045 | | ManualNACPtr aElement, |
2046 | | nsIPresShell* aShell); |
2047 | | void DeleteRefToAnonymousNode(ManualNACPtr aContent, |
2048 | | nsIPresShell* aShell); |
2049 | | |
2050 | | /** |
2051 | | * RefereshEditingUI() may refresh editing UIs for current Selection, focus, |
2052 | | * etc. If this shows or hides some UIs, it causes reflow. So, this is |
2053 | | * not safe method. |
2054 | | */ |
2055 | | nsresult RefereshEditingUI(Selection& aSelection); |
2056 | | |
2057 | | /** |
2058 | | * Returns the offset of an element's frame to its absolute containing block. |
2059 | | */ |
2060 | | nsresult GetElementOrigin(Element& aElement, |
2061 | | int32_t& aX, int32_t& aY); |
2062 | | nsresult GetPositionAndDimensions(Element& aElement, |
2063 | | int32_t& aX, int32_t& aY, |
2064 | | int32_t& aW, int32_t& aH, |
2065 | | int32_t& aBorderLeft, |
2066 | | int32_t& aBorderTop, |
2067 | | int32_t& aMarginLeft, |
2068 | | int32_t& aMarginTop); |
2069 | | |
2070 | | bool IsInObservedSubtree(nsIContent* aChild); |
2071 | | |
2072 | | void UpdateRootElement(); |
2073 | | |
2074 | | /** |
2075 | | * SetAllResizersPosition() moves all resizers to proper position. |
2076 | | * If the resizers are hidden or replaced with another set of resizers |
2077 | | * while this is running, this returns error. So, callers shouldn't |
2078 | | * keep handling the resizers if this returns error. |
2079 | | */ |
2080 | | nsresult SetAllResizersPosition(); |
2081 | | |
2082 | | /** |
2083 | | * Shows active resizers around an element's frame |
2084 | | * @param aResizedElement [IN] a DOM Element |
2085 | | */ |
2086 | | nsresult ShowResizersInternal(Element& aResizedElement); |
2087 | | |
2088 | | /** |
2089 | | * Hide resizers if they are visible. If this is called while there is no |
2090 | | * visible resizers, this does not return error, but does nothing. |
2091 | | */ |
2092 | | nsresult HideResizersInternal(); |
2093 | | |
2094 | | /** |
2095 | | * RefreshResizersInternal() moves resizers to proper position. This does |
2096 | | * nothing if there is no resizing target. |
2097 | | */ |
2098 | | nsresult RefreshResizersInternal(); |
2099 | | |
2100 | | ManualNACPtr CreateResizer(int16_t aLocation, nsIContent& aParentContent); |
2101 | | void SetAnonymousElementPosition(int32_t aX, int32_t aY, |
2102 | | Element* aResizer); |
2103 | | |
2104 | | ManualNACPtr CreateShadow(nsIContent& aParentContent, |
2105 | | Element& aOriginalObject); |
2106 | | |
2107 | | /** |
2108 | | * SetShadowPosition() moves the shadow element to proper position. |
2109 | | * |
2110 | | * @param aShadowElement Must be mResizingShadow or mPositioningShadow. |
2111 | | * @param aElement The element which has the shadow. |
2112 | | * @param aElementX Left of aElement. |
2113 | | * @param aElementY Top of aElement. |
2114 | | */ |
2115 | | nsresult SetShadowPosition(Element& aShadowElement, |
2116 | | Element& aElement, |
2117 | | int32_t aElementLeft, |
2118 | | int32_t aElementTop); |
2119 | | |
2120 | | ManualNACPtr CreateResizingInfo(nsIContent& aParentContent); |
2121 | | nsresult SetResizingInfoPosition(int32_t aX, int32_t aY, |
2122 | | int32_t aW, int32_t aH); |
2123 | | |
2124 | | enum class ResizeAt |
2125 | | { |
2126 | | eX, |
2127 | | eY, |
2128 | | eWidth, |
2129 | | eHeight, |
2130 | | }; |
2131 | | int32_t GetNewResizingIncrement(int32_t aX, int32_t aY, |
2132 | | ResizeAt aResizeAt); |
2133 | | |
2134 | | nsresult StartResizing(Element* aHandle); |
2135 | | int32_t GetNewResizingX(int32_t aX, int32_t aY); |
2136 | | int32_t GetNewResizingY(int32_t aX, int32_t aY); |
2137 | | int32_t GetNewResizingWidth(int32_t aX, int32_t aY); |
2138 | | int32_t GetNewResizingHeight(int32_t aX, int32_t aY); |
2139 | | void HideShadowAndInfo(); |
2140 | | void SetFinalSize(int32_t aX, int32_t aY); |
2141 | | void SetResizeIncrements(int32_t aX, int32_t aY, int32_t aW, int32_t aH, |
2142 | | bool aPreserveRatio); |
2143 | | |
2144 | | /** |
2145 | | * HideAnonymousEditingUIs() forcibly hides all editing UIs (resizers, |
2146 | | * inline-table-editing UI, absolute positioning UI). |
2147 | | */ |
2148 | | void HideAnonymousEditingUIs(); |
2149 | | |
2150 | | /** |
2151 | | * HideAnonymousEditingUIsIfUnnecessary() hides all editing UIs if some of |
2152 | | * visible UIs are now unnecessary. |
2153 | | */ |
2154 | | void HideAnonymousEditingUIsIfUnnecessary(); |
2155 | | |
2156 | | /** |
2157 | | * sets the z-index of an element. |
2158 | | * @param aElement [IN] the element |
2159 | | * @param aZorder [IN] the z-index |
2160 | | */ |
2161 | | void SetZIndex(Element& aElement, int32_t aZorder); |
2162 | | |
2163 | | /** |
2164 | | * shows a grabber attached to an arbitrary element. The grabber is an image |
2165 | | * positioned on the left hand side of the top border of the element. Draggin |
2166 | | * and dropping it allows to change the element's absolute position in the |
2167 | | * document. See chrome://editor/content/images/grabber.gif |
2168 | | * @param aElement [IN] the element |
2169 | | */ |
2170 | | nsresult ShowGrabberInternal(Element& aElement); |
2171 | | |
2172 | | /** |
2173 | | * Setting grabber to proper position for current mAbsolutelyPositionedObject. |
2174 | | * For example, while an element has grabber, the element may be resized |
2175 | | * or repositioned by script or something. Then, you need to reset grabber |
2176 | | * position with this. |
2177 | | */ |
2178 | | nsresult RefreshGrabberInternal(); |
2179 | | |
2180 | | /** |
2181 | | * hide the grabber if it shown. |
2182 | | */ |
2183 | | void HideGrabberInternal(); |
2184 | | |
2185 | | /** |
2186 | | * CreateGrabberInternal() creates a grabber for moving aParentContent. |
2187 | | * This sets mGrabber to the new grabber. If this returns true, it's |
2188 | | * always non-nullptr. Otherwise, i.e., the grabber is hidden during |
2189 | | * creation, this returns false. |
2190 | | */ |
2191 | | bool CreateGrabberInternal(nsIContent& aParentContent); |
2192 | | |
2193 | | nsresult StartMoving(); |
2194 | | nsresult SetFinalPosition(int32_t aX, int32_t aY); |
2195 | | void AddPositioningOffset(int32_t& aX, int32_t& aY); |
2196 | | void SnapToGrid(int32_t& newX, int32_t& newY); |
2197 | | nsresult GrabberClicked(); |
2198 | | nsresult EndMoving(); |
2199 | | nsresult GetTemporaryStyleForFocusedPositionedElement(Element& aElement, |
2200 | | nsAString& aReturn); |
2201 | | |
2202 | | /** |
2203 | | * Shows inline table editing UI around a <table> element which contains |
2204 | | * aCellElement. This returns error if creating UI is hidden during this, |
2205 | | * or detects another set of UI during this. In such case, callers |
2206 | | * shouldn't keep handling anything for the UI. |
2207 | | * |
2208 | | * @param aCellElement Must be an <td> or <th> element. |
2209 | | */ |
2210 | | nsresult ShowInlineTableEditingUIInternal(Element& aCellElement); |
2211 | | |
2212 | | /** |
2213 | | * Hide all inline table editing UI. |
2214 | | */ |
2215 | | void HideInlineTableEditingUIInternal(); |
2216 | | |
2217 | | /** |
2218 | | * RefreshInlineTableEditingUIInternal() moves inline table editing UI to |
2219 | | * proper position. This returns error if the UI is hidden or replaced |
2220 | | * during moving. |
2221 | | */ |
2222 | | nsresult RefreshInlineTableEditingUIInternal(); |
2223 | | |
2224 | | /** |
2225 | | * IsEmptyTextNode() returns true if aNode is a text node and does not have |
2226 | | * any visible characters. |
2227 | | */ |
2228 | | bool IsEmptyTextNode(nsINode& aNode); |
2229 | | |
2230 | | bool IsSimpleModifiableNode(nsIContent* aContent, |
2231 | | nsAtom* aProperty, |
2232 | | nsAtom* aAttribute, |
2233 | | const nsAString* aValue); |
2234 | | nsresult SetInlinePropertyOnNodeImpl(nsIContent& aNode, |
2235 | | nsAtom& aProperty, |
2236 | | nsAtom* aAttribute, |
2237 | | const nsAString& aValue); |
2238 | | typedef enum { eInserted, eAppended } InsertedOrAppended; |
2239 | | void DoContentInserted(nsIContent* aChild, InsertedOrAppended); |
2240 | | |
2241 | | /** |
2242 | | * Returns an anonymous Element of type aTag, |
2243 | | * child of aParentContent. If aIsCreatedHidden is true, the class |
2244 | | * "hidden" is added to the created element. If aAnonClass is not |
2245 | | * the empty string, it becomes the value of the attribute "_moz_anonclass" |
2246 | | * @return a Element |
2247 | | * @param aTag [IN] desired type of the element to create |
2248 | | * @param aParentContent [IN] the parent node of the created anonymous |
2249 | | * element |
2250 | | * @param aAnonClass [IN] contents of the _moz_anonclass attribute |
2251 | | * @param aIsCreatedHidden [IN] a boolean specifying if the class "hidden" |
2252 | | * is to be added to the created anonymous |
2253 | | * element |
2254 | | */ |
2255 | | ManualNACPtr CreateAnonymousElement(nsAtom* aTag, |
2256 | | nsIContent& aParentContent, |
2257 | | const nsAString& aAnonClass, |
2258 | | bool aIsCreatedHidden); |
2259 | | |
2260 | | /** |
2261 | | * Reads a blob into memory and notifies the BlobReader object when the read |
2262 | | * operation is finished. |
2263 | | * |
2264 | | * @param aBlob The input blob |
2265 | | * @param aWindow The global object under which the read should happen. |
2266 | | * @param aBlobReader The blob reader object to be notified when finished. |
2267 | | */ |
2268 | | static nsresult SlurpBlob(dom::Blob* aBlob, |
2269 | | nsPIDOMWindowOuter* aWindow, |
2270 | | BlobReader* aBlobReader); |
2271 | | protected: |
2272 | | RefPtr<TypeInState> mTypeInState; |
2273 | | RefPtr<ComposerCommandsUpdater> mComposerCommandsUpdater; |
2274 | | |
2275 | | bool mCRInParagraphCreatesParagraph; |
2276 | | |
2277 | | bool mCSSAware; |
2278 | | UniquePtr<CSSEditUtils> mCSSEditUtils; |
2279 | | |
2280 | | // mSelectedCellIndex is reset by GetFirstSelectedTableCellElement(), |
2281 | | // then, it'll be referred and incremented by |
2282 | | // GetNextSelectedTableCellElement(). |
2283 | | mutable uint32_t mSelectedCellIndex; |
2284 | | |
2285 | | nsString mLastStyleSheetURL; |
2286 | | nsString mLastOverrideStyleSheetURL; |
2287 | | |
2288 | | // Maintain a list of associated style sheets and their urls. |
2289 | | nsTArray<nsString> mStyleSheetURLs; |
2290 | | nsTArray<RefPtr<StyleSheet>> mStyleSheets; |
2291 | | |
2292 | | // resizing |
2293 | | // If the instance has shown resizers at least once, mHasShownResizers is |
2294 | | // set to true. |
2295 | | bool mHasShownResizers; |
2296 | | bool mIsObjectResizingEnabled; |
2297 | | bool mIsResizing; |
2298 | | bool mPreserveRatio; |
2299 | | bool mResizedObjectIsAnImage; |
2300 | | |
2301 | | // absolute positioning |
2302 | | bool mIsAbsolutelyPositioningEnabled; |
2303 | | bool mResizedObjectIsAbsolutelyPositioned; |
2304 | | // If the instance has shown grabber at least once, mHasShownGrabber is |
2305 | | // set to true. |
2306 | | bool mHasShownGrabber; |
2307 | | bool mGrabberClicked; |
2308 | | bool mIsMoving; |
2309 | | |
2310 | | bool mSnapToGridEnabled; |
2311 | | |
2312 | | // inline table editing |
2313 | | // If the instance has shown inline table editor at least once, |
2314 | | // mHasShownInlineTableEditor is set to true. |
2315 | | bool mHasShownInlineTableEditor; |
2316 | | bool mIsInlineTableEditingEnabled; |
2317 | | |
2318 | | // resizing |
2319 | | ManualNACPtr mTopLeftHandle; |
2320 | | ManualNACPtr mTopHandle; |
2321 | | ManualNACPtr mTopRightHandle; |
2322 | | ManualNACPtr mLeftHandle; |
2323 | | ManualNACPtr mRightHandle; |
2324 | | ManualNACPtr mBottomLeftHandle; |
2325 | | ManualNACPtr mBottomHandle; |
2326 | | ManualNACPtr mBottomRightHandle; |
2327 | | |
2328 | | RefPtr<Element> mActivatedHandle; |
2329 | | |
2330 | | ManualNACPtr mResizingShadow; |
2331 | | ManualNACPtr mResizingInfo; |
2332 | | |
2333 | | RefPtr<Element> mResizedObject; |
2334 | | |
2335 | | nsCOMPtr<nsIDOMEventListener> mMouseMotionListenerP; |
2336 | | nsCOMPtr<nsIDOMEventListener> mResizeEventListenerP; |
2337 | | |
2338 | | int32_t mOriginalX; |
2339 | | int32_t mOriginalY; |
2340 | | |
2341 | | int32_t mResizedObjectX; |
2342 | | int32_t mResizedObjectY; |
2343 | | int32_t mResizedObjectWidth; |
2344 | | int32_t mResizedObjectHeight; |
2345 | | |
2346 | | int32_t mResizedObjectMarginLeft; |
2347 | | int32_t mResizedObjectMarginTop; |
2348 | | int32_t mResizedObjectBorderLeft; |
2349 | | int32_t mResizedObjectBorderTop; |
2350 | | |
2351 | | int32_t mXIncrementFactor; |
2352 | | int32_t mYIncrementFactor; |
2353 | | int32_t mWidthIncrementFactor; |
2354 | | int32_t mHeightIncrementFactor; |
2355 | | |
2356 | | // When resizers, grabber and/or inline table editor are operated by user |
2357 | | // actually, the following counters are increased. |
2358 | | uint32_t mResizerUsedCount; |
2359 | | uint32_t mGrabberUsedCount; |
2360 | | uint32_t mInlineTableEditorUsedCount; |
2361 | | |
2362 | | int8_t mInfoXIncrement; |
2363 | | int8_t mInfoYIncrement; |
2364 | | |
2365 | | // absolute positioning |
2366 | | int32_t mPositionedObjectX; |
2367 | | int32_t mPositionedObjectY; |
2368 | | int32_t mPositionedObjectWidth; |
2369 | | int32_t mPositionedObjectHeight; |
2370 | | |
2371 | | int32_t mPositionedObjectMarginLeft; |
2372 | | int32_t mPositionedObjectMarginTop; |
2373 | | int32_t mPositionedObjectBorderLeft; |
2374 | | int32_t mPositionedObjectBorderTop; |
2375 | | |
2376 | | RefPtr<Element> mAbsolutelyPositionedObject; |
2377 | | ManualNACPtr mGrabber; |
2378 | | ManualNACPtr mPositioningShadow; |
2379 | | |
2380 | | int32_t mGridSize; |
2381 | | |
2382 | | // inline table editing |
2383 | | RefPtr<Element> mInlineEditedCell; |
2384 | | |
2385 | | ManualNACPtr mAddColumnBeforeButton; |
2386 | | ManualNACPtr mRemoveColumnButton; |
2387 | | ManualNACPtr mAddColumnAfterButton; |
2388 | | |
2389 | | ManualNACPtr mAddRowBeforeButton; |
2390 | | ManualNACPtr mRemoveRowButton; |
2391 | | ManualNACPtr mAddRowAfterButton; |
2392 | | |
2393 | | void AddMouseClickListener(Element* aElement); |
2394 | | void RemoveMouseClickListener(Element* aElement); |
2395 | | |
2396 | | nsCOMPtr<nsILinkHandler> mLinkHandler; |
2397 | | |
2398 | | ParagraphSeparator mDefaultParagraphSeparator; |
2399 | | |
2400 | | friend class AutoSelectionSetterAfterTableEdit; |
2401 | | friend class CSSEditUtils; |
2402 | | friend class DocumentResizeEventListener; |
2403 | | friend class EditorBase; |
2404 | | friend class EmptyEditableFunctor; |
2405 | | friend class HTMLEditRules; |
2406 | | friend class SlurpBlobEventListener; |
2407 | | friend class TextEditor; |
2408 | | friend class WSRunObject; |
2409 | | }; |
2410 | | |
2411 | | } // namespace mozilla |
2412 | | |
2413 | | mozilla::HTMLEditor* |
2414 | | nsIEditor::AsHTMLEditor() |
2415 | 0 | { |
2416 | 0 | return static_cast<mozilla::EditorBase*>(this)->mIsHTMLEditorClass ? |
2417 | 0 | static_cast<mozilla::HTMLEditor*>(this) : nullptr; |
2418 | 0 | } |
2419 | | |
2420 | | const mozilla::HTMLEditor* |
2421 | | nsIEditor::AsHTMLEditor() const |
2422 | 0 | { |
2423 | 0 | return static_cast<const mozilla::EditorBase*>(this)->mIsHTMLEditorClass ? |
2424 | 0 | static_cast<const mozilla::HTMLEditor*>(this) : nullptr; |
2425 | 0 | } |
2426 | | |
2427 | | #endif // #ifndef mozilla_HTMLEditor_h |