Line data Source code
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/. */
6 :
7 : #include "InterfaceInitFuncs.h"
8 : #include "mozilla/a11y/PDocAccessible.h"
9 : #include "Accessible-inl.h"
10 : #include "HyperTextAccessible-inl.h"
11 : #include "nsMai.h"
12 : #include "ProxyAccessible.h"
13 :
14 : #include "nsIAccessibleTypes.h"
15 : #include "nsIPersistentProperties2.h"
16 : #include "nsISimpleEnumerator.h"
17 :
18 : #include "mozilla/Likely.h"
19 :
20 : using namespace mozilla;
21 : using namespace mozilla::a11y;
22 :
23 : static const char* sAtkTextAttrNames[ATK_TEXT_ATTR_LAST_DEFINED];
24 :
25 : void
26 0 : ConvertTextAttributeToAtkAttribute(const nsACString& aName,
27 : const nsAString& aValue,
28 : AtkAttributeSet** aAttributeSet)
29 : {
30 : // Handle attributes where atk has its own name.
31 0 : const char* atkName = nullptr;
32 0 : nsAutoString atkValue;
33 0 : if (aName.EqualsLiteral("color")) {
34 : // The format of the atk attribute is r,g,b and the gecko one is
35 : // rgb(r, g, b).
36 0 : atkValue = Substring(aValue, 4, aValue.Length() - 5);
37 0 : atkValue.StripWhitespace();
38 0 : atkName = sAtkTextAttrNames[ATK_TEXT_ATTR_FG_COLOR];
39 0 : } else if (aName.EqualsLiteral("background-color")) {
40 : // The format of the atk attribute is r,g,b and the gecko one is
41 : // rgb(r, g, b).
42 0 : atkValue = Substring(aValue, 4, aValue.Length() - 5);
43 0 : atkValue.StripWhitespace();
44 0 : atkName = sAtkTextAttrNames[ATK_TEXT_ATTR_BG_COLOR];
45 0 : } else if (aName.EqualsLiteral("font-family")) {
46 0 : atkValue = aValue;
47 0 : atkName = sAtkTextAttrNames[ATK_TEXT_ATTR_FAMILY_NAME];
48 0 : } else if (aName.EqualsLiteral("font-size")) {
49 : // ATK wants the number of pixels without px at the end.
50 0 : atkValue = StringHead(aValue, aValue.Length() - 2);
51 0 : atkName = sAtkTextAttrNames[ATK_TEXT_ATTR_SIZE];
52 0 : } else if (aName.EqualsLiteral("font-weight")) {
53 0 : atkValue = aValue;
54 0 : atkName = sAtkTextAttrNames[ATK_TEXT_ATTR_WEIGHT];
55 0 : } else if (aName.EqualsLiteral("invalid")) {
56 0 : atkValue = aValue;
57 0 : atkName = sAtkTextAttrNames[ATK_TEXT_ATTR_INVALID];
58 : }
59 :
60 0 : if (atkName) {
61 : AtkAttribute* objAttr =
62 0 : static_cast<AtkAttribute*>(g_malloc(sizeof(AtkAttribute)));
63 0 : objAttr->name = g_strdup(atkName);
64 0 : objAttr->value = g_strdup(NS_ConvertUTF16toUTF8(atkValue).get());
65 0 : *aAttributeSet = g_slist_prepend(*aAttributeSet, objAttr);
66 : }
67 0 : }
68 :
69 : static AtkAttributeSet*
70 0 : ConvertToAtkTextAttributeSet(nsTArray<Attribute>& aAttributes)
71 : {
72 0 : AtkAttributeSet* objAttributeSet = nullptr;
73 0 : for (size_t i = 0; i < aAttributes.Length(); ++i) {
74 0 : AtkAttribute* objAttr = (AtkAttribute *)g_malloc(sizeof(AtkAttribute));
75 0 : objAttr->name = g_strdup(aAttributes[i].Name().get());
76 0 : objAttr->value =
77 0 : g_strdup(NS_ConvertUTF16toUTF8(aAttributes[i].Value()).get());
78 0 : objAttributeSet = g_slist_prepend(objAttributeSet, objAttr);
79 0 : ConvertTextAttributeToAtkAttribute(aAttributes[i].Name(),
80 0 : aAttributes[i].Value(),
81 0 : &objAttributeSet);
82 : }
83 0 : return objAttributeSet;
84 : }
85 :
86 : static AtkAttributeSet*
87 0 : ConvertToAtkTextAttributeSet(nsIPersistentProperties* aAttributes)
88 : {
89 0 : if (!aAttributes)
90 0 : return nullptr;
91 :
92 0 : AtkAttributeSet* objAttributeSet = nullptr;
93 0 : nsCOMPtr<nsISimpleEnumerator> propEnum;
94 0 : nsresult rv = aAttributes->Enumerate(getter_AddRefs(propEnum));
95 0 : NS_ENSURE_SUCCESS(rv, nullptr);
96 :
97 0 : bool hasMore = false;
98 0 : while (NS_SUCCEEDED(propEnum->HasMoreElements(&hasMore)) && hasMore) {
99 0 : nsCOMPtr<nsISupports> sup;
100 0 : rv = propEnum->GetNext(getter_AddRefs(sup));
101 0 : NS_ENSURE_SUCCESS(rv, objAttributeSet);
102 :
103 0 : nsCOMPtr<nsIPropertyElement> propElem(do_QueryInterface(sup));
104 0 : NS_ENSURE_TRUE(propElem, objAttributeSet);
105 :
106 0 : nsAutoCString name;
107 0 : rv = propElem->GetKey(name);
108 0 : NS_ENSURE_SUCCESS(rv, objAttributeSet);
109 :
110 0 : nsAutoString value;
111 0 : rv = propElem->GetValue(value);
112 0 : NS_ENSURE_SUCCESS(rv, objAttributeSet);
113 :
114 0 : AtkAttribute* objAttr = (AtkAttribute*)g_malloc(sizeof(AtkAttribute));
115 0 : objAttr->name = g_strdup(name.get());
116 0 : objAttr->value = g_strdup(NS_ConvertUTF16toUTF8(value).get());
117 0 : objAttributeSet = g_slist_prepend(objAttributeSet, objAttr);
118 :
119 0 : ConvertTextAttributeToAtkAttribute(name, value, &objAttributeSet);
120 : }
121 :
122 : // libatk-adaptor will free it
123 0 : return objAttributeSet;
124 : }
125 :
126 : static void
127 0 : ConvertTexttoAsterisks(AccessibleWrap* accWrap, nsAString& aString)
128 : {
129 : // convert each char to "*" when it's "password text"
130 0 : if (accWrap->NativeRole() == roles::PASSWORD_TEXT) {
131 0 : for (uint32_t i = 0; i < aString.Length(); i++)
132 0 : aString.Replace(i, 1, NS_LITERAL_STRING("*"));
133 : }
134 0 : }
135 :
136 : extern "C" {
137 :
138 : static gchar*
139 0 : getTextCB(AtkText *aText, gint aStartOffset, gint aEndOffset)
140 : {
141 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
142 0 : nsAutoString autoStr;
143 0 : if (accWrap) {
144 0 : HyperTextAccessible* text = accWrap->AsHyperText();
145 0 : if (!text || !text->IsTextRole())
146 0 : return nullptr;
147 :
148 0 : text->TextSubstring(aStartOffset, aEndOffset, autoStr);
149 :
150 0 : ConvertTexttoAsterisks(accWrap, autoStr);
151 0 : } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
152 0 : proxy->TextSubstring(aStartOffset, aEndOffset, autoStr);
153 : }
154 :
155 0 : NS_ConvertUTF16toUTF8 cautoStr(autoStr);
156 :
157 : //copy and return, libspi will free it.
158 0 : return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr;
159 : }
160 :
161 : static gchar*
162 0 : getTextAfterOffsetCB(AtkText *aText, gint aOffset,
163 : AtkTextBoundary aBoundaryType,
164 : gint *aStartOffset, gint *aEndOffset)
165 : {
166 0 : nsAutoString autoStr;
167 0 : int32_t startOffset = 0, endOffset = 0;
168 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
169 0 : if (accWrap) {
170 0 : HyperTextAccessible* text = accWrap->AsHyperText();
171 0 : if (!text || !text->IsTextRole())
172 0 : return nullptr;
173 :
174 0 : text->TextAfterOffset(aOffset, aBoundaryType, &startOffset, &endOffset, autoStr);
175 0 : ConvertTexttoAsterisks(accWrap, autoStr);
176 0 : } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
177 0 : proxy->GetTextAfterOffset(aOffset, aBoundaryType, autoStr, &startOffset,
178 0 : &endOffset);
179 : }
180 :
181 0 : *aStartOffset = startOffset;
182 0 : *aEndOffset = endOffset;
183 :
184 0 : NS_ConvertUTF16toUTF8 cautoStr(autoStr);
185 0 : return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr;
186 : }
187 :
188 : static gchar*
189 0 : getTextAtOffsetCB(AtkText *aText, gint aOffset,
190 : AtkTextBoundary aBoundaryType,
191 : gint *aStartOffset, gint *aEndOffset)
192 : {
193 0 : nsAutoString autoStr;
194 0 : int32_t startOffset = 0, endOffset = 0;
195 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
196 0 : if (accWrap) {
197 0 : HyperTextAccessible* text = accWrap->AsHyperText();
198 0 : if (!text || !text->IsTextRole())
199 0 : return nullptr;
200 :
201 0 : text->TextAtOffset(aOffset, aBoundaryType, &startOffset, &endOffset, autoStr);
202 0 : ConvertTexttoAsterisks(accWrap, autoStr);
203 0 : } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
204 0 : proxy->GetTextAtOffset(aOffset, aBoundaryType, autoStr, &startOffset,
205 0 : &endOffset);
206 : }
207 :
208 0 : *aStartOffset = startOffset;
209 0 : *aEndOffset = endOffset;
210 :
211 0 : NS_ConvertUTF16toUTF8 cautoStr(autoStr);
212 0 : return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr;
213 : }
214 :
215 : static gunichar
216 0 : getCharacterAtOffsetCB(AtkText* aText, gint aOffset)
217 : {
218 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
219 0 : if (accWrap) {
220 0 : HyperTextAccessible* text = accWrap->AsHyperText();
221 0 : if (!text || !text->IsTextRole()) {
222 0 : return 0;
223 : }
224 :
225 : // char16_t is unsigned short in Mozilla, gnuichar is guint32 in glib.
226 0 : return static_cast<gunichar>(text->CharAt(aOffset));
227 : }
228 :
229 0 : if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
230 0 : return static_cast<gunichar>(proxy->CharAt(aOffset));
231 : }
232 :
233 0 : return 0;
234 : }
235 :
236 : static gchar*
237 0 : getTextBeforeOffsetCB(AtkText *aText, gint aOffset,
238 : AtkTextBoundary aBoundaryType,
239 : gint *aStartOffset, gint *aEndOffset)
240 : {
241 0 : nsAutoString autoStr;
242 0 : int32_t startOffset = 0, endOffset = 0;
243 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
244 0 : if (accWrap) {
245 0 : HyperTextAccessible* text = accWrap->AsHyperText();
246 0 : if (!text || !text->IsTextRole())
247 0 : return nullptr;
248 :
249 0 : text->TextBeforeOffset(aOffset, aBoundaryType,
250 0 : &startOffset, &endOffset, autoStr);
251 0 : ConvertTexttoAsterisks(accWrap, autoStr);
252 0 : } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
253 0 : proxy->GetTextBeforeOffset(aOffset, aBoundaryType, autoStr, &startOffset,
254 0 : &endOffset);
255 : }
256 :
257 0 : *aStartOffset = startOffset;
258 0 : *aEndOffset = endOffset;
259 :
260 0 : NS_ConvertUTF16toUTF8 cautoStr(autoStr);
261 0 : return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr;
262 : }
263 :
264 : static gint
265 0 : getCaretOffsetCB(AtkText *aText)
266 : {
267 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
268 0 : if (accWrap) {
269 0 : HyperTextAccessible* text = accWrap->AsHyperText();
270 0 : if (!text || !text->IsTextRole()) {
271 0 : return 0;
272 : }
273 :
274 0 : return static_cast<gint>(text->CaretOffset());
275 : }
276 :
277 0 : if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
278 0 : return static_cast<gint>(proxy->CaretOffset());
279 : }
280 :
281 0 : return 0;
282 : }
283 :
284 : static AtkAttributeSet*
285 0 : getRunAttributesCB(AtkText *aText, gint aOffset,
286 : gint *aStartOffset,
287 : gint *aEndOffset)
288 : {
289 0 : *aStartOffset = -1;
290 0 : *aEndOffset = -1;
291 0 : int32_t startOffset = 0, endOffset = 0;
292 :
293 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
294 0 : if (accWrap) {
295 0 : HyperTextAccessible* text = accWrap->AsHyperText();
296 0 : if (!text || !text->IsTextRole()) {
297 0 : return nullptr;
298 : }
299 :
300 : nsCOMPtr<nsIPersistentProperties> attributes =
301 0 : text->TextAttributes(false, aOffset, &startOffset, &endOffset);
302 :
303 0 : *aStartOffset = startOffset;
304 0 : *aEndOffset = endOffset;
305 :
306 0 : return ConvertToAtkTextAttributeSet(attributes);
307 : }
308 :
309 0 : ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText));
310 0 : if (!proxy) {
311 0 : return nullptr;
312 : }
313 :
314 0 : AutoTArray<Attribute, 10> attrs;
315 0 : proxy->TextAttributes(false, aOffset, &attrs, &startOffset, &endOffset);
316 0 : *aStartOffset = startOffset;
317 0 : *aEndOffset = endOffset;
318 0 : return ConvertToAtkTextAttributeSet(attrs);
319 : }
320 :
321 : static AtkAttributeSet*
322 0 : getDefaultAttributesCB(AtkText *aText)
323 : {
324 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
325 0 : if (accWrap) {
326 0 : HyperTextAccessible* text = accWrap->AsHyperText();
327 0 : if (!text || !text->IsTextRole()) {
328 0 : return nullptr;
329 : }
330 :
331 0 : nsCOMPtr<nsIPersistentProperties> attributes = text->DefaultTextAttributes();
332 0 : return ConvertToAtkTextAttributeSet(attributes);
333 : }
334 :
335 0 : ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText));
336 0 : if (!proxy) {
337 0 : return nullptr;
338 : }
339 :
340 0 : AutoTArray<Attribute, 10> attrs;
341 0 : proxy->DefaultTextAttributes(&attrs);
342 0 : return ConvertToAtkTextAttributeSet(attrs);
343 : }
344 :
345 : static void
346 0 : getCharacterExtentsCB(AtkText *aText, gint aOffset,
347 : gint *aX, gint *aY,
348 : gint *aWidth, gint *aHeight,
349 : AtkCoordType aCoords)
350 : {
351 0 : if(!aX || !aY || !aWidth || !aHeight) {
352 0 : return;
353 : }
354 :
355 0 : nsIntRect rect;
356 : uint32_t geckoCoordType;
357 0 : if (aCoords == ATK_XY_SCREEN) {
358 0 : geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE;
359 : } else {
360 0 : geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE;
361 : }
362 :
363 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
364 0 : if (accWrap) {
365 0 : HyperTextAccessible* text = accWrap->AsHyperText();
366 0 : if (!text || !text->IsTextRole()) {
367 0 : return;
368 : }
369 :
370 0 : rect = text->CharBounds(aOffset, geckoCoordType);
371 0 : } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
372 0 : rect = proxy->CharBounds(aOffset, geckoCoordType);
373 : } else {
374 0 : return;
375 : }
376 :
377 0 : *aX = rect.x;
378 0 : *aY = rect.y;
379 0 : *aWidth = rect.width;
380 0 : *aHeight = rect.height;
381 : }
382 :
383 : static void
384 0 : getRangeExtentsCB(AtkText *aText, gint aStartOffset, gint aEndOffset,
385 : AtkCoordType aCoords, AtkTextRectangle *aRect)
386 : {
387 0 : if (!aRect) {
388 0 : return;
389 : }
390 :
391 0 : nsIntRect rect;
392 : uint32_t geckoCoordType;
393 0 : if (aCoords == ATK_XY_SCREEN) {
394 0 : geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE;
395 : } else {
396 0 : geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE;
397 : }
398 :
399 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
400 0 : if(accWrap) {
401 0 : HyperTextAccessible* text = accWrap->AsHyperText();
402 0 : if (!text || !text->IsTextRole()) {
403 0 : return;
404 : }
405 :
406 0 : rect = text->TextBounds(aStartOffset, aEndOffset, geckoCoordType);
407 0 : } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
408 0 : rect = proxy->TextBounds(aStartOffset, aEndOffset, geckoCoordType);
409 : } else {
410 0 : return;
411 : }
412 :
413 0 : aRect->x = rect.x;
414 0 : aRect->y = rect.y;
415 0 : aRect->width = rect.width;
416 0 : aRect->height = rect.height;
417 : }
418 :
419 : static gint
420 0 : getCharacterCountCB(AtkText *aText)
421 : {
422 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
423 0 : if (accWrap) {
424 0 : HyperTextAccessible* textAcc = accWrap->AsHyperText();
425 : return
426 0 : textAcc->IsDefunct() ? 0 : static_cast<gint>(textAcc->CharacterCount());
427 : }
428 :
429 0 : if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
430 0 : return proxy->CharacterCount();
431 : }
432 :
433 0 : return 0;
434 : }
435 :
436 : static gint
437 0 : getOffsetAtPointCB(AtkText *aText,
438 : gint aX, gint aY,
439 : AtkCoordType aCoords)
440 : {
441 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
442 0 : if (accWrap) {
443 0 : HyperTextAccessible* text = accWrap->AsHyperText();
444 0 : if (!text || !text->IsTextRole()) {
445 0 : return -1;
446 : }
447 :
448 : return static_cast<gint>(
449 0 : text->OffsetAtPoint(aX, aY,
450 : (aCoords == ATK_XY_SCREEN ?
451 : nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
452 0 : nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE)));
453 : }
454 :
455 0 : if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
456 : return static_cast<gint>(
457 0 : proxy->OffsetAtPoint(aX, aY,
458 : (aCoords == ATK_XY_SCREEN ?
459 : nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
460 0 : nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE)));
461 : }
462 :
463 0 : return -1;
464 : }
465 :
466 : static gint
467 0 : getTextSelectionCountCB(AtkText *aText)
468 : {
469 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
470 0 : if (accWrap) {
471 0 : HyperTextAccessible* text = accWrap->AsHyperText();
472 0 : if (!text || !text->IsTextRole()) {
473 0 : return 0;
474 : }
475 :
476 0 : return text->SelectionCount();
477 : }
478 :
479 0 : if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
480 0 : return proxy->SelectionCount();
481 : }
482 :
483 0 : return 0;
484 : }
485 :
486 : static gchar*
487 0 : getTextSelectionCB(AtkText *aText, gint aSelectionNum,
488 : gint *aStartOffset, gint *aEndOffset)
489 : {
490 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
491 0 : int32_t startOffset = 0, endOffset = 0;
492 0 : if (accWrap) {
493 0 : HyperTextAccessible* text = accWrap->AsHyperText();
494 0 : if (!text || !text->IsTextRole()) {
495 0 : return nullptr;
496 : }
497 :
498 0 : text->SelectionBoundsAt(aSelectionNum, &startOffset, &endOffset);
499 0 : *aStartOffset = startOffset;
500 0 : *aEndOffset = endOffset;
501 :
502 0 : return getTextCB(aText, *aStartOffset, *aEndOffset);
503 : }
504 0 : if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
505 0 : nsString data;
506 0 : proxy->SelectionBoundsAt(aSelectionNum, data, &startOffset, &endOffset);
507 0 : *aStartOffset = startOffset;
508 0 : *aEndOffset = endOffset;
509 :
510 0 : NS_ConvertUTF16toUTF8 dataAsUTF8(data);
511 0 : return (dataAsUTF8.get()) ? g_strdup(dataAsUTF8.get()) : nullptr;
512 : }
513 0 : return nullptr;
514 : }
515 :
516 : // set methods
517 : static gboolean
518 0 : addTextSelectionCB(AtkText *aText,
519 : gint aStartOffset,
520 : gint aEndOffset)
521 : {
522 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
523 0 : if (accWrap) {
524 0 : HyperTextAccessible* text = accWrap->AsHyperText();
525 0 : if (!text || !text->IsTextRole()) {
526 0 : return FALSE;
527 : }
528 :
529 0 : return text->AddToSelection(aStartOffset, aEndOffset);
530 : }
531 0 : if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
532 0 : return proxy->AddToSelection(aStartOffset, aEndOffset);
533 : }
534 :
535 0 : return FALSE;
536 : }
537 :
538 : static gboolean
539 0 : removeTextSelectionCB(AtkText *aText,
540 : gint aSelectionNum)
541 : {
542 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
543 0 : if (accWrap) {
544 0 : HyperTextAccessible* text = accWrap->AsHyperText();
545 0 : if (!text || !text->IsTextRole()) {
546 0 : return FALSE;
547 : }
548 :
549 0 : return text->RemoveFromSelection(aSelectionNum);
550 : }
551 0 : if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
552 0 : return proxy->RemoveFromSelection(aSelectionNum);
553 : }
554 :
555 0 : return FALSE;
556 : }
557 :
558 : static gboolean
559 0 : setTextSelectionCB(AtkText *aText, gint aSelectionNum,
560 : gint aStartOffset, gint aEndOffset)
561 : {
562 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
563 0 : if (accWrap) {
564 0 : HyperTextAccessible* text = accWrap->AsHyperText();
565 0 : if (!text || !text->IsTextRole()) {
566 0 : return FALSE;
567 : }
568 :
569 0 : return text->SetSelectionBoundsAt(aSelectionNum, aStartOffset, aEndOffset);
570 : }
571 0 : if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
572 0 : return proxy->SetSelectionBoundsAt(aSelectionNum, aStartOffset, aEndOffset);
573 : }
574 :
575 0 : return FALSE;
576 : }
577 :
578 : static gboolean
579 0 : setCaretOffsetCB(AtkText *aText, gint aOffset)
580 : {
581 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
582 0 : if (accWrap) {
583 0 : HyperTextAccessible* text = accWrap->AsHyperText();
584 0 : if (!text || !text->IsTextRole() || !text->IsValidOffset(aOffset)) {
585 0 : return FALSE;
586 : }
587 :
588 0 : text->SetCaretOffset(aOffset);
589 0 : return TRUE;
590 : }
591 :
592 0 : if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
593 0 : proxy->SetCaretOffset(aOffset);
594 0 : return TRUE;
595 : }
596 :
597 0 : return FALSE;
598 : }
599 : }
600 :
601 : void
602 0 : textInterfaceInitCB(AtkTextIface* aIface)
603 : {
604 0 : NS_ASSERTION(aIface, "Invalid aIface");
605 0 : if (MOZ_UNLIKELY(!aIface))
606 0 : return;
607 :
608 0 : aIface->get_text = getTextCB;
609 0 : aIface->get_text_after_offset = getTextAfterOffsetCB;
610 0 : aIface->get_text_at_offset = getTextAtOffsetCB;
611 0 : aIface->get_character_at_offset = getCharacterAtOffsetCB;
612 0 : aIface->get_text_before_offset = getTextBeforeOffsetCB;
613 0 : aIface->get_caret_offset = getCaretOffsetCB;
614 0 : aIface->get_run_attributes = getRunAttributesCB;
615 0 : aIface->get_default_attributes = getDefaultAttributesCB;
616 0 : aIface->get_character_extents = getCharacterExtentsCB;
617 0 : aIface->get_range_extents = getRangeExtentsCB;
618 0 : aIface->get_character_count = getCharacterCountCB;
619 0 : aIface->get_offset_at_point = getOffsetAtPointCB;
620 0 : aIface->get_n_selections = getTextSelectionCountCB;
621 0 : aIface->get_selection = getTextSelectionCB;
622 :
623 : // set methods
624 0 : aIface->add_selection = addTextSelectionCB;
625 0 : aIface->remove_selection = removeTextSelectionCB;
626 0 : aIface->set_selection = setTextSelectionCB;
627 0 : aIface->set_caret_offset = setCaretOffsetCB;
628 :
629 : // Cache the string values of the atk text attribute names.
630 0 : for (uint32_t i = 0; i < ArrayLength(sAtkTextAttrNames); i++)
631 0 : sAtkTextAttrNames[i] =
632 0 : atk_text_attribute_get_name(static_cast<AtkTextAttribute>(i));
633 : }
|