1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_a11y_TextRange_h__
8 #define mozilla_a11y_TextRange_h__
12 #include "nsCaseTreatment.h"
25 class LocalAccessible
;
26 class HyperTextAccessible
;
29 * A text point (hyper text + offset), represents a boundary of text range.
31 struct TextPoint final
{
32 TextPoint(HyperTextAccessible
* aContainer
, int32_t aOffset
)
33 : mContainer(aContainer
), mOffset(aOffset
) {}
34 TextPoint(const TextPoint
& aPoint
)
35 : mContainer(aPoint
.mContainer
), mOffset(aPoint
.mOffset
) {}
37 HyperTextAccessible
* mContainer
;
40 bool operator==(const TextPoint
& aPoint
) const {
41 return mContainer
== aPoint
.mContainer
&& mOffset
== aPoint
.mOffset
;
43 bool operator<(const TextPoint
& aPoint
) const;
47 * Represents a text range within the text control or document.
49 class TextRange final
{
51 TextRange(HyperTextAccessible
* aRoot
, HyperTextAccessible
* aStartContainer
,
52 int32_t aStartOffset
, HyperTextAccessible
* aEndContainer
,
54 TextRange() : mStartOffset
{0}, mEndOffset
{0} {}
55 TextRange(TextRange
&& aRange
)
56 : mRoot(std::move(aRange
.mRoot
)),
57 mStartContainer(std::move(aRange
.mStartContainer
)),
58 mEndContainer(std::move(aRange
.mEndContainer
)),
59 mStartOffset(aRange
.mStartOffset
),
60 mEndOffset(aRange
.mEndOffset
) {}
62 TextRange
& operator=(TextRange
&& aRange
) {
63 mRoot
= std::move(aRange
.mRoot
);
64 mStartContainer
= std::move(aRange
.mStartContainer
);
65 mEndContainer
= std::move(aRange
.mEndContainer
);
66 mStartOffset
= aRange
.mStartOffset
;
67 mEndOffset
= aRange
.mEndOffset
;
71 HyperTextAccessible
* StartContainer() const { return mStartContainer
; }
72 int32_t StartOffset() const { return mStartOffset
; }
73 HyperTextAccessible
* EndContainer() const { return mEndContainer
; }
74 int32_t EndOffset() const { return mEndOffset
; }
76 bool operator==(const TextRange
& aRange
) const {
77 return mStartContainer
== aRange
.mStartContainer
&&
78 mStartOffset
== aRange
.mStartOffset
&&
79 mEndContainer
== aRange
.mEndContainer
&&
80 mEndOffset
== aRange
.mEndOffset
;
83 TextPoint
StartPoint() const {
84 return TextPoint(mStartContainer
, mStartOffset
);
86 TextPoint
EndPoint() const { return TextPoint(mEndContainer
, mEndOffset
); }
89 * Return a container containing both start and end points.
91 LocalAccessible
* Container() const;
94 * Return a list of embedded objects enclosed by the text range (includes
95 * partially overlapped objects).
97 void EmbeddedChildren(nsTArray
<LocalAccessible
*>* aChildren
) const;
100 * Return text enclosed by the range.
102 void Text(nsAString
& aText
) const;
105 * Return list of bounding rects of the text range by lines.
107 void Bounds(nsTArray
<nsIntRect
> aRects
) const;
109 enum ETextUnit
{ eFormat
, eWord
, eLine
, eParagraph
, ePage
, eDocument
};
112 * Move the range or its points on specified amount of given units.
114 void Move(ETextUnit aUnit
, int32_t aCount
) {
115 MoveEnd(aUnit
, aCount
);
116 MoveStart(aUnit
, aCount
);
118 void MoveStart(ETextUnit aUnit
, int32_t aCount
) {
119 MoveInternal(aUnit
, aCount
, *mStartContainer
, mStartOffset
, mEndContainer
,
122 void MoveEnd(ETextUnit aUnit
, int32_t aCount
) {
123 MoveInternal(aUnit
, aCount
, *mEndContainer
, mEndOffset
);
127 * Move the range points to the closest unit boundaries.
129 void Normalize(ETextUnit aUnit
);
132 * Crops the range if it overlaps the given accessible element boundaries,
133 * returns true if the range was cropped successfully.
135 bool Crop(LocalAccessible
* aContainer
);
137 enum EDirection
{ eBackward
, eForward
};
140 * Return range enclosing the found text.
142 void FindText(const nsAString
& aText
, EDirection aDirection
,
143 nsCaseTreatment aCaseSensitive
, TextRange
* aFoundRange
) const;
147 eAnnotationObjectsAttr
,
148 eAnnotationTypesAttr
,
149 eBackgroundColorAttr
,
158 eForegroundColorAttr
,
159 eHorizontalTextAlignmentAttr
,
160 eIndentationFirstLineAttr
,
161 eIndentationLeadingAttr
,
162 eIndentationTrailingAttr
,
177 eSelectionActiveEndAttr
,
178 eStrikethroughColorAttr
,
179 eStrikethroughStyleAttr
,
183 eTextFlowDirectionsAttr
,
189 * Return range enclosing text having requested attribute.
191 void FindAttr(EAttr aAttr
, nsIVariant
* aValue
, EDirection aDirection
,
192 TextRange
* aFoundRange
) const;
195 * Add/remove the text range from selection.
197 void AddToSelection() const;
198 void RemoveFromSelection() const;
199 MOZ_CAN_RUN_SCRIPT
bool SetSelectionAt(int32_t aSelectionNum
) const;
202 * Scroll the text range into view.
204 void ScrollIntoView(uint32_t aScrollType
) const;
207 * Convert stored hypertext offsets into DOM offsets and assign it to DOM
210 * Note that if start and/or end accessible offsets are in generated content
211 * such as ::before or
212 * ::after, the result range excludes the generated content. See also
213 * ClosestNotGeneratedDOMPoint() for more information.
215 * @param aRange [in, out] the range whose bounds to set
216 * @param aReversed [out] whether the start/end offsets were reversed.
217 * @return true if conversion was successful
219 bool AssignDOMRange(nsRange
* aRange
, bool* aReversed
= nullptr) const;
222 * Return true if this TextRange object represents an actual range of text.
224 bool IsValid() const { return mRoot
; }
226 void SetStartPoint(HyperTextAccessible
* aContainer
, int32_t aOffset
) {
227 mStartContainer
= aContainer
;
228 mStartOffset
= aOffset
;
230 void SetEndPoint(HyperTextAccessible
* aContainer
, int32_t aOffset
) {
231 mStartContainer
= aContainer
;
232 mStartOffset
= aOffset
;
235 static void TextRangesFromSelection(dom::Selection
* aSelection
,
236 nsTArray
<TextRange
>* aRanges
);
239 TextRange(const TextRange
& aRange
) = delete;
240 TextRange
& operator=(const TextRange
& aRange
) = delete;
242 friend class HyperTextAccessible
;
243 friend class xpcAccessibleTextRange
;
245 void Set(HyperTextAccessible
* aRoot
, HyperTextAccessible
* aStartContainer
,
246 int32_t aStartOffset
, HyperTextAccessible
* aEndContainer
,
250 * Text() method helper.
251 * @param aText [in,out] calculated text
252 * @param aCurrent [in] currently traversed node
253 * @param aStartIntlOffset [in] start offset if current node is a text node
254 * @return true if calculation is not finished yet
256 bool TextInternal(nsAString
& aText
, LocalAccessible
* aCurrent
,
257 uint32_t aStartIntlOffset
) const;
259 void MoveInternal(ETextUnit aUnit
, int32_t aCount
,
260 HyperTextAccessible
& aContainer
, int32_t aOffset
,
261 HyperTextAccessible
* aStopContainer
= nullptr,
262 int32_t aStopOffset
= 0);
265 * A helper method returning a common parent for two given accessible
268 LocalAccessible
* CommonParent(LocalAccessible
* aAcc1
, LocalAccessible
* aAcc2
,
269 nsTArray
<LocalAccessible
*>* aParents1
,
271 nsTArray
<LocalAccessible
*>* aParents2
,
272 uint32_t* aPos2
) const;
274 RefPtr
<HyperTextAccessible
> mRoot
;
275 RefPtr
<HyperTextAccessible
> mStartContainer
;
276 RefPtr
<HyperTextAccessible
> mEndContainer
;
277 int32_t mStartOffset
;
282 } // namespace mozilla