no bug - Import translations from android-l10n r=release a=l10n CLOSED TREE
[gecko.git] / accessible / windows / ia2 / ia2AccessibleTextSelectionContainer.cpp
blob0360cc20286c92148d50f1dd29f90ee59acbfb24
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:expandtab:shiftwidth=2:tabstop=2:
3 */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 #include "ia2AccessibleTextSelectionContainer.h"
10 #include "AccessibleTextSelectionContainer_i.c"
11 #include "ia2AccessibleHypertext.h"
12 #include "mozilla/a11y/HyperTextAccessibleBase.h"
13 #include "TextRange.h"
14 #include "TextLeafRange.h"
16 using namespace mozilla::a11y;
18 // IAccessibleTextSelectionContainer
20 STDMETHODIMP
21 ia2AccessibleTextSelectionContainer::get_selections(
22 IA2TextSelection** selections, long* nSelections) {
23 if (!selections || !nSelections) {
24 return E_INVALIDARG;
26 *nSelections = 0;
27 HyperTextAccessibleBase* text = TextAcc();
28 if (!text) {
29 return CO_E_OBJNOTCONNECTED;
31 AutoTArray<TextRange, 1> ranges;
32 text->CroppedSelectionRanges(ranges);
33 *nSelections = ranges.Length();
34 *selections = static_cast<IA2TextSelection*>(
35 ::CoTaskMemAlloc(sizeof(IA2TextSelection) * *nSelections));
36 if (!*selections) {
37 return E_OUTOFMEMORY;
39 for (uint32_t idx = 0; idx < static_cast<uint32_t>(*nSelections); idx++) {
40 RefPtr<IAccessibleText> startObj =
41 GetIATextFrom(ranges[idx].StartContainer());
42 startObj.forget(&(*selections)[idx].startObj);
43 (*selections)[idx].startOffset = ranges[idx].StartOffset();
44 RefPtr<IAccessibleText> endObj = GetIATextFrom(ranges[idx].EndContainer());
45 endObj.forget(&(*selections)[idx].endObj);
46 (*selections)[idx].endOffset = ranges[idx].EndOffset();
47 // XXX Expose this properly somehow.
48 (*selections)[idx].startIsActive = true;
50 return S_OK;
53 STDMETHODIMP
54 ia2AccessibleTextSelectionContainer::setSelections(
55 long nSelections, IA2TextSelection* selections) {
56 if (nSelections < 0 || (nSelections > 0 && !selections)) {
57 return E_INVALIDARG;
59 HyperTextAccessibleBase* text = TextAcc();
60 if (!text) {
61 return CO_E_OBJNOTCONNECTED;
63 // Build and validate new selection ranges.
64 AutoTArray<TextLeafRange, 1> newRanges;
65 newRanges.SetCapacity(nSelections);
66 for (long r = 0; r < nSelections; ++r) {
67 TextLeafRange range(GetTextLeafPointFrom(selections[r].startObj,
68 selections[r].startOffset, false),
69 GetTextLeafPointFrom(selections[r].endObj,
70 selections[r].endOffset, true));
71 if (!range) {
72 return E_INVALIDARG;
74 newRanges.AppendElement(range);
76 // Get the number of existing selections. We use SelectionRanges rather than
77 // SelectionCount because SelectionCount is restricted to this Accessible,
78 // whereas we want all selections within the control/document.
79 AutoTArray<TextRange, 1> oldRanges;
80 text->SelectionRanges(&oldRanges);
81 // Set the new selections.
82 for (long r = 0; r < nSelections; ++r) {
83 newRanges[r].SetSelection(r);
85 // Remove any remaining old selections if there were more than nSelections.
86 for (long r = nSelections; r < static_cast<long>(oldRanges.Length()); ++r) {
87 text->RemoveFromSelection(r);
89 return S_OK;
92 // ia2AccessibleTextSelectionContainer
94 HyperTextAccessibleBase* ia2AccessibleTextSelectionContainer::TextAcc() {
95 auto hyp = static_cast<ia2AccessibleHypertext*>(this);
96 Accessible* acc = hyp->Acc();
97 return acc ? acc->AsHyperTextBase() : nullptr;
100 /* static */
101 RefPtr<IAccessibleText> ia2AccessibleTextSelectionContainer::GetIATextFrom(
102 Accessible* aAcc) {
103 MsaaAccessible* msaa = MsaaAccessible::GetFrom(aAcc);
104 MOZ_ASSERT(msaa);
105 RefPtr<IAccessibleText> text;
106 msaa->QueryInterface(IID_IAccessibleText, getter_AddRefs(text));
107 MOZ_ASSERT(text);
108 return text;
111 /* static */
112 TextLeafPoint ia2AccessibleTextSelectionContainer::GetTextLeafPointFrom(
113 IAccessibleText* aText, long aOffset, bool aDescendToEnd) {
114 if (!aText) {
115 return TextLeafPoint();
117 Accessible* acc = MsaaAccessible::GetAccessibleFrom(aText);
118 if (!acc) {
119 return TextLeafPoint();
121 HyperTextAccessibleBase* hyp = acc->AsHyperTextBase();
122 if (!hyp) {
123 return TextLeafPoint();
125 return hyp->ToTextLeafPoint(aOffset, aDescendToEnd);