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/. */
9 #include "Accessible-inl.h"
10 #include "HyperTextAccessible.h"
11 #include "nsAccUtils.h"
16 ////////////////////////////////////////////////////////////////////////////////
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
;
30 parents1
.AppendElement(p1
);
34 parents2
.AppendElement(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
);
44 return child1
->IndexInParent() < child2
->IndexInParent();
47 NS_ERROR("Broken tree?!");
51 ////////////////////////////////////////////////////////////////////////////////
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
)
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
;
73 parents1
.AppendElement(p1
);
77 parents2
.AppendElement(p2
);
81 // Find where the parent chain differs
82 uint32_t pos1
= parents1
.Length();
83 uint32_t pos2
= parents2
.Length();
84 Accessible
* parent
= nullptr;
86 for (len
= std::min(pos1
, pos2
); len
> 0; --len
) {
87 Accessible
* child1
= parents1
.ElementAt(--pos1
);
88 Accessible
* child2
= parents2
.ElementAt(--pos2
);
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
);
112 Accessible
* p1
= mStartContainer
->GetChildAtOffset(mStartOffset
);
113 Accessible
* p2
= mEndContainer
->GetChildAtOffset(mEndOffset
);
114 nsAutoTArray
<Accessible
*, 30> parents1
, parents2
;
116 parents1
.AppendElement(p1
);
120 parents2
.AppendElement(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
)
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
);
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();
183 current
= current
->NextSibling();
188 TextRange::Bounds(nsTArray
<nsIntRect
> aRects
) const
194 TextRange::Normalize(ETextUnit aUnit
)
200 TextRange::FindText(const nsAString
& aText
, EDirection aDirection
,
201 nsCaseTreatment aCaseSensitive
, TextRange
* aFoundRange
) const
207 TextRange::FindAttr(EAttr aAttr
, nsIVariant
* aValue
, EDirection aDirection
,
208 TextRange
* aFoundRange
) const
214 TextRange::AddToSelection() const
220 TextRange::RemoveFromSelection() const
226 TextRange::Select() const
231 TextRange::ScrollIntoView(EHowToAlign aHow
) const
236 ////////////////////////////////////////////////////////////////////////////////
240 TextRange::Set(HyperTextAccessible
* aRoot
,
241 HyperTextAccessible
* aStartContainer
, int32_t aStartOffset
,
242 HyperTextAccessible
* aEndContainer
, int32_t aEndOffset
)
245 mStartContainer
= aStartContainer
;
246 mEndContainer
= aEndContainer
;
247 mStartOffset
= aStartOffset
;
248 mEndOffset
= aEndOffset
;
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)
268 if (aCurrent
->IsTextLeaf()) {
269 aCurrent
->AppendTextTo(aText
, aStartIntlOffset
,
270 endIntlOffset
- aStartIntlOffset
);
275 Accessible
* next
= aCurrent
->FirstChild();
277 if (!TextInternal(aText
, next
, 0))
281 next
= aCurrent
->NextSibling();
283 if (!TextInternal(aText
, next
, 0))
292 TextRange::MoveInternal(ETextUnit aUnit
, int32_t aCount
,
293 HyperTextAccessible
& aContainer
, int32_t aOffset
,
294 HyperTextAccessible
* aStopContainer
, int32_t aStopOffset
)
300 } // namespace mozilla