Bug 1626988 [wpt PR 22658] - wake lock: Remove WakeLockPermissionDescriptor, use...
[gecko.git] / accessible / base / TextRange.cpp
blobd73d8c9803a8577c1dad6162431ea7f9ab28ebfe
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 #include "TextRange-inl.h"
9 #include "Accessible-inl.h"
10 #include "nsAccUtils.h"
12 namespace mozilla {
13 namespace a11y {
15 ////////////////////////////////////////////////////////////////////////////////
16 // TextPoint
18 bool TextPoint::operator<(const TextPoint& aPoint) const {
19 if (mContainer == aPoint.mContainer) return mOffset < aPoint.mOffset;
21 // Build the chain of parents
22 Accessible* p1 = mContainer;
23 Accessible* p2 = aPoint.mContainer;
24 AutoTArray<Accessible*, 30> parents1, parents2;
25 do {
26 parents1.AppendElement(p1);
27 p1 = p1->Parent();
28 } while (p1);
29 do {
30 parents2.AppendElement(p2);
31 p2 = p2->Parent();
32 } while (p2);
34 // Find where the parent chain differs
35 uint32_t pos1 = parents1.Length(), pos2 = parents2.Length();
36 for (uint32_t len = std::min(pos1, pos2); len > 0; --len) {
37 Accessible* child1 = parents1.ElementAt(--pos1);
38 Accessible* child2 = parents2.ElementAt(--pos2);
39 if (child1 != child2)
40 return child1->IndexInParent() < child2->IndexInParent();
43 NS_ERROR("Broken tree?!");
44 return false;
47 ////////////////////////////////////////////////////////////////////////////////
48 // TextRange
50 TextRange::TextRange(HyperTextAccessible* aRoot,
51 HyperTextAccessible* aStartContainer, int32_t aStartOffset,
52 HyperTextAccessible* aEndContainer, int32_t aEndOffset)
53 : mRoot(aRoot),
54 mStartContainer(aStartContainer),
55 mEndContainer(aEndContainer),
56 mStartOffset(aStartOffset),
57 mEndOffset(aEndOffset) {}
59 void TextRange::EmbeddedChildren(nsTArray<Accessible*>* aChildren) const {
60 if (mStartContainer == mEndContainer) {
61 int32_t startIdx = mStartContainer->GetChildIndexAtOffset(mStartOffset);
62 int32_t endIdx = mStartContainer->GetChildIndexAtOffset(mEndOffset);
63 for (int32_t idx = startIdx; idx <= endIdx; idx++) {
64 Accessible* child = mStartContainer->GetChildAt(idx);
65 if (!child->IsText()) {
66 aChildren->AppendElement(child);
69 return;
72 Accessible* p1 = mStartContainer->GetChildAtOffset(mStartOffset);
73 Accessible* p2 = mEndContainer->GetChildAtOffset(mEndOffset);
75 uint32_t pos1 = 0, pos2 = 0;
76 AutoTArray<Accessible*, 30> parents1, parents2;
77 Accessible* container =
78 CommonParent(p1, p2, &parents1, &pos1, &parents2, &pos2);
80 // Traverse the tree up to the container and collect embedded objects.
81 for (uint32_t idx = 0; idx < pos1 - 1; idx++) {
82 Accessible* parent = parents1[idx + 1];
83 Accessible* child = parents1[idx];
84 uint32_t childCount = parent->ChildCount();
85 for (uint32_t childIdx = child->IndexInParent(); childIdx < childCount;
86 childIdx++) {
87 Accessible* next = parent->GetChildAt(childIdx);
88 if (!next->IsText()) {
89 aChildren->AppendElement(next);
94 // Traverse through direct children in the container.
95 int32_t endIdx = parents2[pos2 - 1]->IndexInParent();
96 int32_t childIdx = parents1[pos1 - 1]->IndexInParent() + 1;
97 for (; childIdx < endIdx; childIdx++) {
98 Accessible* next = container->GetChildAt(childIdx);
99 if (!next->IsText()) {
100 aChildren->AppendElement(next);
104 // Traverse down from the container to end point.
105 for (int32_t idx = pos2 - 2; idx > 0; idx--) {
106 Accessible* parent = parents2[idx];
107 Accessible* child = parents2[idx - 1];
108 int32_t endIdx = child->IndexInParent();
109 for (int32_t childIdx = 0; childIdx < endIdx; childIdx++) {
110 Accessible* next = parent->GetChildAt(childIdx);
111 if (!next->IsText()) {
112 aChildren->AppendElement(next);
118 void TextRange::Text(nsAString& aText) const {
119 Accessible* current = mStartContainer->GetChildAtOffset(mStartOffset);
120 uint32_t startIntlOffset =
121 mStartOffset - mStartContainer->GetChildOffset(current);
123 while (current && TextInternal(aText, current, startIntlOffset)) {
124 current = current->Parent();
125 if (!current) break;
127 current = current->NextSibling();
131 void TextRange::Bounds(nsTArray<nsIntRect> aRects) const {}
133 void TextRange::Normalize(ETextUnit aUnit) {}
135 bool TextRange::Crop(Accessible* aContainer) {
136 uint32_t boundaryPos = 0, containerPos = 0;
137 AutoTArray<Accessible*, 30> boundaryParents, containerParents;
139 // Crop the start boundary.
140 Accessible* container = nullptr;
141 Accessible* boundary = mStartContainer->GetChildAtOffset(mStartOffset);
142 if (boundary != aContainer) {
143 CommonParent(boundary, aContainer, &boundaryParents, &boundaryPos,
144 &containerParents, &containerPos);
146 if (boundaryPos == 0) {
147 if (containerPos != 0) {
148 // The container is contained by the start boundary, reduce the range to
149 // the point starting at the container.
150 aContainer->ToTextPoint(mStartContainer.StartAssignment(),
151 &mStartOffset);
152 static_cast<Accessible*>(mStartContainer)->AddRef();
153 } else {
154 // The start boundary and the container are siblings.
155 container = aContainer;
157 } else if (containerPos != 0) {
158 // The container does not contain the start boundary.
159 boundary = boundaryParents[boundaryPos];
160 container = containerParents[containerPos];
163 if (container) {
164 // If the range start is after the container, then make the range invalid.
165 if (boundary->IndexInParent() > container->IndexInParent()) {
166 return !!(mRoot = nullptr);
169 // If the range starts before the container, then reduce the range to
170 // the point starting at the container.
171 if (boundary->IndexInParent() < container->IndexInParent()) {
172 container->ToTextPoint(mStartContainer.StartAssignment(),
173 &mStartOffset);
174 mStartContainer.get()->AddRef();
178 boundaryParents.SetLengthAndRetainStorage(0);
179 containerParents.SetLengthAndRetainStorage(0);
182 boundary = mEndContainer->GetChildAtOffset(mEndOffset);
183 if (boundary == aContainer) {
184 return true;
187 // Crop the end boundary.
188 container = nullptr;
189 CommonParent(boundary, aContainer, &boundaryParents, &boundaryPos,
190 &containerParents, &containerPos);
192 if (boundaryPos == 0) {
193 if (containerPos != 0) {
194 aContainer->ToTextPoint(mEndContainer.StartAssignment(), &mEndOffset,
195 false);
196 static_cast<Accessible*>(mEndContainer)->AddRef();
197 } else {
198 container = aContainer;
200 } else if (containerPos != 0) {
201 boundary = boundaryParents[boundaryPos];
202 container = containerParents[containerPos];
205 if (!container) {
206 return true;
209 if (boundary->IndexInParent() < container->IndexInParent()) {
210 return !!(mRoot = nullptr);
213 if (boundary->IndexInParent() > container->IndexInParent()) {
214 container->ToTextPoint(mEndContainer.StartAssignment(), &mEndOffset, false);
215 static_cast<Accessible*>(mEndContainer)->AddRef();
218 return true;
221 void TextRange::FindText(const nsAString& aText, EDirection aDirection,
222 nsCaseTreatment aCaseSensitive,
223 TextRange* aFoundRange) const {}
225 void TextRange::FindAttr(EAttr aAttr, nsIVariant* aValue, EDirection aDirection,
226 TextRange* aFoundRange) const {}
228 void TextRange::AddToSelection() const {}
230 void TextRange::RemoveFromSelection() const {}
232 void TextRange::Select() const {}
234 void TextRange::ScrollIntoView(EHowToAlign aHow) const {}
236 ////////////////////////////////////////////////////////////////////////////////
237 // pivate
239 void TextRange::Set(HyperTextAccessible* aRoot,
240 HyperTextAccessible* aStartContainer, int32_t aStartOffset,
241 HyperTextAccessible* aEndContainer, int32_t aEndOffset) {
242 mRoot = aRoot;
243 mStartContainer = aStartContainer;
244 mEndContainer = aEndContainer;
245 mStartOffset = aStartOffset;
246 mEndOffset = aEndOffset;
249 bool TextRange::TextInternal(nsAString& aText, Accessible* aCurrent,
250 uint32_t aStartIntlOffset) const {
251 bool moveNext = true;
252 int32_t endIntlOffset = -1;
253 if (aCurrent->Parent() == mEndContainer &&
254 mEndContainer->GetChildAtOffset(mEndOffset) == aCurrent) {
255 uint32_t currentStartOffset = mEndContainer->GetChildOffset(aCurrent);
256 endIntlOffset = mEndOffset - currentStartOffset;
257 if (endIntlOffset == 0) return false;
259 moveNext = false;
262 if (aCurrent->IsTextLeaf()) {
263 aCurrent->AppendTextTo(aText, aStartIntlOffset,
264 endIntlOffset - aStartIntlOffset);
265 if (!moveNext) return false;
268 Accessible* next = aCurrent->FirstChild();
269 if (next) {
270 if (!TextInternal(aText, next, 0)) return false;
273 next = aCurrent->NextSibling();
274 if (next) {
275 if (!TextInternal(aText, next, 0)) return false;
278 return moveNext;
281 void TextRange::MoveInternal(ETextUnit aUnit, int32_t aCount,
282 HyperTextAccessible& aContainer, int32_t aOffset,
283 HyperTextAccessible* aStopContainer,
284 int32_t aStopOffset) {}
286 Accessible* TextRange::CommonParent(Accessible* aAcc1, Accessible* aAcc2,
287 nsTArray<Accessible*>* aParents1,
288 uint32_t* aPos1,
289 nsTArray<Accessible*>* aParents2,
290 uint32_t* aPos2) const {
291 if (aAcc1 == aAcc2) {
292 return aAcc1;
295 MOZ_ASSERT(aParents1->Length() == 0 || aParents2->Length() == 0,
296 "Wrong arguments");
298 // Build the chain of parents.
299 Accessible* p1 = aAcc1;
300 Accessible* p2 = aAcc2;
301 do {
302 aParents1->AppendElement(p1);
303 p1 = p1->Parent();
304 } while (p1);
305 do {
306 aParents2->AppendElement(p2);
307 p2 = p2->Parent();
308 } while (p2);
310 // Find where the parent chain differs
311 *aPos1 = aParents1->Length();
312 *aPos2 = aParents2->Length();
313 Accessible* parent = nullptr;
314 uint32_t len = 0;
315 for (len = std::min(*aPos1, *aPos2); len > 0; --len) {
316 Accessible* child1 = aParents1->ElementAt(--(*aPos1));
317 Accessible* child2 = aParents2->ElementAt(--(*aPos2));
318 if (child1 != child2) break;
320 parent = child1;
323 return parent;
326 } // namespace a11y
327 } // namespace mozilla