Bug 1528824 - [wpt-sync] Update web-platform-tests to f8a1bfbe5454352d3f5b58845829968...
[gecko.git] / editor / spellchecker / TextServicesDocument.h
blob94f249118e82d9fb6ee79bf549411a9e4b4bb2c6
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/. */
6 #ifndef mozilla_TextServicesDocument_h
7 #define mozilla_TextServicesDocument_h
9 #include "nsCOMPtr.h"
10 #include "nsCycleCollectionParticipant.h"
11 #include "nsIEditActionListener.h"
12 #include "nsISupportsImpl.h"
13 #include "nsStringFwd.h"
14 #include "nsTArray.h"
15 #include "nscore.h"
17 class nsIContent;
18 class nsIEditor;
19 class nsINode;
20 class nsISelectionController;
21 class nsRange;
23 namespace mozilla {
25 class FilteredContentIterator;
26 class OffsetEntry;
27 class TextEditor;
29 namespace dom {
30 class Document;
31 class Element;
32 }; // namespace dom
34 /**
35 * The TextServicesDocument presents the document in as a bunch of flattened
36 * text blocks. Each text block can be retrieved as an nsString.
38 class TextServicesDocument final : public nsIEditActionListener {
39 private:
40 enum class IteratorStatus : uint8_t {
41 // No iterator (I), or iterator doesn't point to anything valid.
42 eDone = 0,
43 // I points to first text node (TN) in current block (CB).
44 eValid,
45 // No TN in CB, I points to first TN in prev block.
46 ePrev,
47 // No TN in CB, I points to first TN in next block.
48 eNext,
51 RefPtr<dom::Document> mDocument;
52 nsCOMPtr<nsISelectionController> mSelCon;
53 RefPtr<TextEditor> mTextEditor;
54 RefPtr<FilteredContentIterator> mFilteredIter;
55 nsCOMPtr<nsIContent> mPrevTextBlock;
56 nsCOMPtr<nsIContent> mNextTextBlock;
57 nsTArray<OffsetEntry*> mOffsetTable;
58 RefPtr<nsRange> mExtent;
59 uint32_t mTxtSvcFilterType;
61 int32_t mSelStartIndex;
62 int32_t mSelStartOffset;
63 int32_t mSelEndIndex;
64 int32_t mSelEndOffset;
66 IteratorStatus mIteratorStatus;
68 protected:
69 virtual ~TextServicesDocument();
71 public:
72 TextServicesDocument();
74 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
75 NS_DECL_CYCLE_COLLECTION_CLASS(TextServicesDocument)
77 /**
78 * Initializes the text services document to use a particular editor. The
79 * text services document will use the DOM document and presentation shell
80 * used by the editor.
82 * @param aEditor The editor to use.
84 nsresult InitWithEditor(nsIEditor* aEditor);
86 /**
87 * Sets the range/extent over which the text services document will iterate.
88 * Note that InitWithEditor() should have been called prior to calling this
89 * method. If this method is never called, the text services defaults to
90 * iterating over the entire document.
92 * @param aDOMRange The range to use. aDOMRange must point to a
93 * valid range object.
95 nsresult SetExtent(nsRange* aRange);
97 /**
98 * Expands the end points of the range so that it spans complete words. This
99 * call does not change any internal state of the text services document.
101 * @param aDOMRange The range to be expanded/adjusted.
103 nsresult ExpandRangeToWordBoundaries(nsRange* aRange);
106 * Sets the filter type to be used while iterating over content.
107 * This will clear the current filter type if it's not either
108 * FILTERTYPE_NORMAL or FILTERTYPE_MAIL.
110 * @param aFilterType The filter type to be used while iterating over
111 * content.
113 nsresult SetFilterType(uint32_t aFilterType);
116 * Returns the text in the current text block.
118 * @param aStr [OUT] This will contain the text.
120 nsresult GetCurrentTextBlock(nsString* aStr);
123 * Tells the document to point to the first text block in the document. This
124 * method does not adjust the current cursor position or selection.
126 nsresult FirstBlock();
128 enum class BlockSelectionStatus {
129 // There is no text block (TB) in or before the selection (S).
130 eBlockNotFound = 0,
131 // No TB in S, but found one before/after S.
132 eBlockOutside,
133 // S extends beyond the start and end of TB.
134 eBlockInside,
135 // TB contains entire S.
136 eBlockContains,
137 // S begins or ends in TB but extends outside of TB.
138 eBlockPartial,
142 * Tells the document to point to the last text block that contains the
143 * current selection or caret.
145 * @param aSelectionStatus [OUT] This will contain the text block
146 * selection status.
147 * @param aSelectionOffset [OUT] This will contain the offset into the
148 * string returned by GetCurrentTextBlock() where
149 * the selection begins.
150 * @param aLength [OUT] This will contain the number of
151 * characters that are selected in the string.
153 nsresult LastSelectedBlock(BlockSelectionStatus* aSelStatus,
154 int32_t* aSelOffset, int32_t* aSelLength);
157 * Tells the document to point to the text block before the current one.
158 * This method will return NS_OK, even if there is no previous block.
159 * Callers should call IsDone() to check if we have gone beyond the first
160 * text block in the document.
162 nsresult PrevBlock();
165 * Tells the document to point to the text block after the current one.
166 * This method will return NS_OK, even if there is no next block. Callers
167 * should call IsDone() to check if we have gone beyond the last text block
168 * in the document.
170 nsresult NextBlock();
173 * IsDone() will always set aIsDone == false unless the document contains
174 * no text, PrevBlock() was called while the document was already pointing
175 * to the first text block in the document, or NextBlock() was called while
176 * the document was already pointing to the last text block in the document.
178 * @param aIsDone [OUT] This will contain the result.
180 nsresult IsDone(bool* aIsDone);
183 * SetSelection() allows the caller to set the selection based on an offset
184 * into the string returned by GetCurrentTextBlock(). A length of zero
185 * places the cursor at that offset. A positive non-zero length "n" selects
186 * n characters in the string.
188 * @param aOffset Offset into string returned by
189 * GetCurrentTextBlock().
190 * @param aLength Number of characters selected.
192 nsresult SetSelection(int32_t aOffset, int32_t aLength);
195 * Scrolls the document so that the current selection is visible.
197 nsresult ScrollSelectionIntoView();
200 * Deletes the text selected by SetSelection(). Calling DeleteSelection()
201 * with nothing selected, or with a collapsed selection (cursor) does
202 * nothing and returns NS_OK.
204 nsresult DeleteSelection();
207 * Inserts the given text at the current cursor position. If there is a
208 * selection, it will be deleted before the text is inserted.
210 nsresult InsertText(const nsString* aText);
213 * nsIEditActionListener method implementations.
215 NS_DECL_NSIEDITACTIONLISTENER
218 * Actual edit action listeners. When you add new method here for listening
219 * to new edit action, you need to make it called by EditorBase.
220 * Additionally, you need to call it from proper method of
221 * nsIEditActionListener too because if this is created not for inline
222 * spell checker of the editor, edit actions will be notified via
223 * nsIEditActionListener (slow path, though).
225 void DidDeleteNode(nsINode* aChild);
226 void DidJoinNodes(nsINode& aLeftNode, nsINode& aRightNode);
228 static nsresult GetRangeEndPoints(nsRange* aRange, nsINode** aStartContainer,
229 int32_t* aStartOffset,
230 nsINode** aEndContainer,
231 int32_t* aEndOffset);
233 private:
234 nsresult CreateFilteredContentIterator(
235 nsRange* aRange, FilteredContentIterator** aFilteredIter);
237 dom::Element* GetDocumentContentRootNode() const;
238 already_AddRefed<nsRange> CreateDocumentContentRange();
239 already_AddRefed<nsRange> CreateDocumentContentRootToNodeOffsetRange(
240 nsINode* aParent, uint32_t aOffset, bool aToStart);
241 nsresult CreateDocumentContentIterator(
242 FilteredContentIterator** aFilteredIter);
244 nsresult AdjustContentIterator();
246 static nsresult FirstTextNode(FilteredContentIterator* aFilteredIter,
247 IteratorStatus* aIteratorStatus);
248 static nsresult LastTextNode(FilteredContentIterator* aFilteredIter,
249 IteratorStatus* aIteratorStatus);
251 static nsresult FirstTextNodeInCurrentBlock(
252 FilteredContentIterator* aFilteredIter);
253 static nsresult FirstTextNodeInPrevBlock(
254 FilteredContentIterator* aFilteredIter);
255 static nsresult FirstTextNodeInNextBlock(
256 FilteredContentIterator* aFilteredIter);
258 nsresult GetFirstTextNodeInPrevBlock(nsIContent** aContent);
259 nsresult GetFirstTextNodeInNextBlock(nsIContent** aContent);
261 static bool IsBlockNode(nsIContent* aContent);
262 static bool IsTextNode(nsIContent* aContent);
264 static bool DidSkip(FilteredContentIterator* aFilteredIter);
265 static void ClearDidSkip(FilteredContentIterator* aFilteredIter);
267 static bool HasSameBlockNodeParent(nsIContent* aContent1,
268 nsIContent* aContent2);
270 nsresult SetSelectionInternal(int32_t aOffset, int32_t aLength,
271 bool aDoUpdate);
272 nsresult GetSelection(BlockSelectionStatus* aSelStatus, int32_t* aSelOffset,
273 int32_t* aSelLength);
274 nsresult GetCollapsedSelection(BlockSelectionStatus* aSelStatus,
275 int32_t* aSelOffset, int32_t* aSelLength);
276 nsresult GetUncollapsedSelection(BlockSelectionStatus* aSelStatus,
277 int32_t* aSelOffset, int32_t* aSelLength);
279 bool SelectionIsCollapsed();
280 bool SelectionIsValid();
282 static nsresult CreateOffsetTable(nsTArray<OffsetEntry*>* aOffsetTable,
283 FilteredContentIterator* aFilteredIter,
284 IteratorStatus* aIteratorStatus,
285 nsRange* aIterRange, nsString* aStr);
286 static nsresult ClearOffsetTable(nsTArray<OffsetEntry*>* aOffsetTable);
288 static nsresult NodeHasOffsetEntry(nsTArray<OffsetEntry*>* aOffsetTable,
289 nsINode* aNode, bool* aHasEntry,
290 int32_t* aEntryIndex);
292 nsresult RemoveInvalidOffsetEntries();
293 nsresult SplitOffsetEntry(int32_t aTableIndex, int32_t aOffsetIntoEntry);
295 static nsresult FindWordBounds(nsTArray<OffsetEntry*>* aOffsetTable,
296 nsString* aBlockStr, nsINode* aNode,
297 int32_t aNodeOffset, nsINode** aWordStartNode,
298 int32_t* aWordStartOffset,
299 nsINode** aWordEndNode,
300 int32_t* aWordEndOffset);
303 } // namespace mozilla
305 #endif // #ifndef mozilla_TextServicesDocument_h