Bumping manifests a=b2g-bump
[gecko.git] / accessible / base / TextRange.cpp
blob500fd3bf7fc91e4224f62f479a1f4dd4956a420e
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.h"
9 #include "Accessible-inl.h"
10 #include "HyperTextAccessible.h"
11 #include "nsAccUtils.h"
13 namespace mozilla {
14 namespace a11y {
16 ////////////////////////////////////////////////////////////////////////////////
17 // TextPoint
19 bool
20 TextPoint::operator <(const TextPoint& aPoint) const
22 if (mContainer == aPoint.mContainer)
23 return mOffset < aPoint.mOffset;
25 // Build the chain of parents
26 Accessible* p1 = mContainer;
27 Accessible* p2 = aPoint.mContainer;
28 nsAutoTArray<Accessible*, 30> parents1, parents2;
29 do {
30 parents1.AppendElement(p1);
31 p1 = p1->Parent();
32 } while (p1);
33 do {
34 parents2.AppendElement(p2);
35 p2 = p2->Parent();
36 } while (p2);
38 // Find where the parent chain differs
39 uint32_t pos1 = parents1.Length(), pos2 = parents2.Length();
40 for (uint32_t len = std::min(pos1, pos2); len > 0; --len) {
41 Accessible* child1 = parents1.ElementAt(--pos1);
42 Accessible* child2 = parents2.ElementAt(--pos2);
43 if (child1 != child2)
44 return child1->IndexInParent() < child2->IndexInParent();
47 NS_ERROR("Broken tree?!");
48 return false;
51 ////////////////////////////////////////////////////////////////////////////////
52 // TextRange
54 TextRange::TextRange(HyperTextAccessible* aRoot,
55 HyperTextAccessible* aStartContainer, int32_t aStartOffset,
56 HyperTextAccessible* aEndContainer, int32_t aEndOffset) :
57 mRoot(aRoot), mStartContainer(aStartContainer), mEndContainer(aEndContainer),
58 mStartOffset(aStartOffset), mEndOffset(aEndOffset)
62 Accessible*
63 TextRange::Container() const
65 if (mStartContainer == mEndContainer)
66 return mStartContainer;
68 // Build the chain of parents
69 Accessible* p1 = mStartContainer;
70 Accessible* p2 = mEndContainer;
71 nsAutoTArray<Accessible*, 30> parents1, parents2;
72 do {
73 parents1.AppendElement(p1);
74 p1 = p1->Parent();
75 } while (p1);
76 do {
77 parents2.AppendElement(p2);
78 p2 = p2->Parent();
79 } while (p2);
81 // Find where the parent chain differs
82 uint32_t pos1 = parents1.Length();
83 uint32_t pos2 = parents2.Length();
84 Accessible* parent = nullptr;
85 uint32_t len = 0;
86 for (len = std::min(pos1, pos2); len > 0; --len) {
87 Accessible* child1 = parents1.ElementAt(--pos1);
88 Accessible* child2 = parents2.ElementAt(--pos2);
89 if (child1 != child2)
90 break;
92 parent = child1;
95 return parent;
98 void
99 TextRange::EmbeddedChildren(nsTArray<Accessible*>* aChildren) const
101 if (mStartContainer == mEndContainer) {
102 int32_t startIdx = mStartContainer->GetChildIndexAtOffset(mStartOffset);
103 int32_t endIdx = mStartContainer->GetChildIndexAtOffset(mEndOffset);
104 for (int32_t idx = startIdx; idx <= endIdx; idx++) {
105 Accessible* child = mStartContainer->GetChildAt(idx);
106 if (nsAccUtils::IsEmbeddedObject(child))
107 aChildren->AppendElement(child);
109 return;
112 Accessible* p1 = mStartContainer->GetChildAtOffset(mStartOffset);
113 Accessible* p2 = mEndContainer->GetChildAtOffset(mEndOffset);
114 nsAutoTArray<Accessible*, 30> parents1, parents2;
115 do {
116 parents1.AppendElement(p1);
117 p1 = p1->Parent();
118 } while (p1);
119 do {
120 parents2.AppendElement(p2);
121 p2 = p2->Parent();
122 } while (p2);
124 // Find deepest common container.
125 uint32_t pos1 = parents1.Length();
126 uint32_t pos2 = parents2.Length();
127 Accessible* container = nullptr;
128 for (uint32_t len = std::min(pos1, pos2); len > 0; --len) {
129 Accessible* child1 = parents1.ElementAt(--pos1);
130 Accessible* child2 = parents2.ElementAt(--pos2);
131 if (child1 != child2)
132 break;
134 container = child1;
137 // Traverse the tree up to the container and collect embedded objects.
138 for (uint32_t idx = 0; idx < pos1 - 1; idx++) {
139 Accessible* parent = parents1[idx + 1];
140 Accessible* child = parents1[idx];
141 uint32_t childCount = parent->ChildCount();
142 for (uint32_t childIdx = child->IndexInParent(); childIdx < childCount; childIdx++) {
143 Accessible* next = parent->GetChildAt(childIdx);
144 if (nsAccUtils::IsEmbeddedObject(next))
145 aChildren->AppendElement(next);
149 // Traverse through direct children in the container.
150 int32_t endIdx = parents2[pos2 - 1]->IndexInParent();
151 int32_t childIdx = parents1[pos1 - 1]->IndexInParent() + 1;
152 for (; childIdx < endIdx; childIdx++) {
153 Accessible* next = container->GetChildAt(childIdx);
154 if (nsAccUtils::IsEmbeddedObject(next))
155 aChildren->AppendElement(next);
158 // Traverse down from the container to end point.
159 for (int32_t idx = pos2 - 2; idx > 0; idx--) {
160 Accessible* parent = parents2[idx];
161 Accessible* child = parents2[idx - 1];
162 int32_t endIdx = child->IndexInParent();
163 for (int32_t childIdx = 0; childIdx < endIdx; childIdx++) {
164 Accessible* next = parent->GetChildAt(childIdx);
165 if (nsAccUtils::IsEmbeddedObject(next))
166 aChildren->AppendElement(next);
171 void
172 TextRange::Text(nsAString& aText) const
174 Accessible* current = mStartContainer->GetChildAtOffset(mStartOffset);
175 uint32_t startIntlOffset =
176 mStartOffset - mStartContainer->GetChildOffset(current);
178 while (current && TextInternal(aText, current, startIntlOffset)) {
179 current = current->Parent();
180 if (!current)
181 break;
183 current = current->NextSibling();
187 void
188 TextRange::Bounds(nsTArray<nsIntRect> aRects) const
193 void
194 TextRange::Normalize(ETextUnit aUnit)
199 void
200 TextRange::FindText(const nsAString& aText, EDirection aDirection,
201 nsCaseTreatment aCaseSensitive, TextRange* aFoundRange) const
206 void
207 TextRange::FindAttr(EAttr aAttr, nsIVariant* aValue, EDirection aDirection,
208 TextRange* aFoundRange) const
213 void
214 TextRange::AddToSelection() const
219 void
220 TextRange::RemoveFromSelection() const
225 void
226 TextRange::Select() const
230 void
231 TextRange::ScrollIntoView(EHowToAlign aHow) const
236 ////////////////////////////////////////////////////////////////////////////////
237 // pivate
239 void
240 TextRange::Set(HyperTextAccessible* aRoot,
241 HyperTextAccessible* aStartContainer, int32_t aStartOffset,
242 HyperTextAccessible* aEndContainer, int32_t aEndOffset)
244 mRoot = aRoot;
245 mStartContainer = aStartContainer;
246 mEndContainer = aEndContainer;
247 mStartOffset = aStartOffset;
248 mEndOffset = aEndOffset;
251 bool
252 TextRange::TextInternal(nsAString& aText, Accessible* aCurrent,
253 uint32_t aStartIntlOffset) const
255 bool moveNext = true;
256 int32_t endIntlOffset = -1;
257 if (aCurrent->Parent() == mEndContainer &&
258 mEndContainer->GetChildAtOffset(mEndOffset) == aCurrent) {
260 uint32_t currentStartOffset = mEndContainer->GetChildOffset(aCurrent);
261 endIntlOffset = mEndOffset - currentStartOffset;
262 if (endIntlOffset == 0)
263 return false;
265 moveNext = false;
268 if (aCurrent->IsTextLeaf()) {
269 aCurrent->AppendTextTo(aText, aStartIntlOffset,
270 endIntlOffset - aStartIntlOffset);
271 if (!moveNext)
272 return false;
275 Accessible* next = aCurrent->FirstChild();
276 if (next) {
277 if (!TextInternal(aText, next, 0))
278 return false;
281 next = aCurrent->NextSibling();
282 if (next) {
283 if (!TextInternal(aText, next, 0))
284 return false;
287 return moveNext;
291 void
292 TextRange::MoveInternal(ETextUnit aUnit, int32_t aCount,
293 HyperTextAccessible& aContainer, int32_t aOffset,
294 HyperTextAccessible* aStopContainer, int32_t aStopOffset)
299 } // namespace a11y
300 } // namespace mozilla