/src/mozilla-central/accessible/atk/nsMaiHyperlink.cpp
Line | Count | Source (jump to first uncovered line) |
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 "nsIURI.h" |
8 | | #include "nsMaiHyperlink.h" |
9 | | #include "mozilla/a11y/ProxyAccessible.h" |
10 | | |
11 | | using namespace mozilla::a11y; |
12 | | |
13 | | /* MaiAtkHyperlink */ |
14 | | |
15 | | #define MAI_TYPE_ATK_HYPERLINK (mai_atk_hyperlink_get_type ()) |
16 | 0 | #define MAI_ATK_HYPERLINK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),\ |
17 | 0 | MAI_TYPE_ATK_HYPERLINK, MaiAtkHyperlink)) |
18 | | #define MAI_ATK_HYPERLINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass),\ |
19 | | MAI_TYPE_ATK_HYPERLINK, MaiAtkHyperlinkClass)) |
20 | 0 | #define MAI_IS_ATK_HYPERLINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\ |
21 | 0 | MAI_TYPE_ATK_HYPERLINK)) |
22 | | #define MAI_IS_ATK_HYPERLINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),\ |
23 | | MAI_TYPE_ATK_HYPERLINK)) |
24 | | #define MAI_ATK_HYPERLINK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),\ |
25 | | MAI_TYPE_ATK_HYPERLINK, MaiAtkHyperlinkClass)) |
26 | | |
27 | | /** |
28 | | * This MaiAtkHyperlink is a thin wrapper, in the MAI namespace, |
29 | | * for AtkHyperlink |
30 | | */ |
31 | | |
32 | | struct MaiAtkHyperlink |
33 | | { |
34 | | AtkHyperlink parent; |
35 | | |
36 | | /* |
37 | | * The MaiHyperlink whose properties and features are exported via this |
38 | | * hyperlink instance. |
39 | | */ |
40 | | MaiHyperlink *maiHyperlink; |
41 | | }; |
42 | | |
43 | | struct MaiAtkHyperlinkClass |
44 | | { |
45 | | AtkHyperlinkClass parent_class; |
46 | | }; |
47 | | |
48 | | GType mai_atk_hyperlink_get_type(void); |
49 | | |
50 | | G_BEGIN_DECLS |
51 | | /* callbacks for AtkHyperlink */ |
52 | | static void classInitCB(AtkHyperlinkClass *aClass); |
53 | | static void finalizeCB(GObject *aObj); |
54 | | |
55 | | /* callbacks for AtkHyperlink virtual functions */ |
56 | | static gchar *getUriCB(AtkHyperlink *aLink, gint aLinkIndex); |
57 | | static AtkObject *getObjectCB(AtkHyperlink *aLink, gint aLinkIndex); |
58 | | static gint getEndIndexCB(AtkHyperlink *aLink); |
59 | | static gint getStartIndexCB(AtkHyperlink *aLink); |
60 | | static gboolean isValidCB(AtkHyperlink *aLink); |
61 | | static gint getAnchorCountCB(AtkHyperlink *aLink); |
62 | | G_END_DECLS |
63 | | |
64 | | static gpointer parent_class = nullptr; |
65 | | |
66 | | static MaiHyperlink* |
67 | | GetMaiHyperlink(AtkHyperlink *aHyperlink) |
68 | 0 | { |
69 | 0 | NS_ENSURE_TRUE(MAI_IS_ATK_HYPERLINK(aHyperlink), nullptr); |
70 | 0 | MaiHyperlink * maiHyperlink = |
71 | 0 | MAI_ATK_HYPERLINK(aHyperlink)->maiHyperlink; |
72 | 0 | NS_ENSURE_TRUE(maiHyperlink != nullptr, nullptr); |
73 | 0 | NS_ENSURE_TRUE(maiHyperlink->GetAtkHyperlink() == aHyperlink, nullptr); |
74 | 0 | return maiHyperlink; |
75 | 0 | } |
76 | | |
77 | | GType |
78 | | mai_atk_hyperlink_get_type(void) |
79 | 0 | { |
80 | 0 | static GType type = 0; |
81 | 0 |
|
82 | 0 | if (!type) { |
83 | 0 | static const GTypeInfo tinfo = { |
84 | 0 | sizeof(MaiAtkHyperlinkClass), |
85 | 0 | (GBaseInitFunc)nullptr, |
86 | 0 | (GBaseFinalizeFunc)nullptr, |
87 | 0 | (GClassInitFunc)classInitCB, |
88 | 0 | (GClassFinalizeFunc)nullptr, |
89 | 0 | nullptr, /* class data */ |
90 | 0 | sizeof(MaiAtkHyperlink), /* instance size */ |
91 | 0 | 0, /* nb preallocs */ |
92 | 0 | (GInstanceInitFunc)nullptr, |
93 | 0 | nullptr /* value table */ |
94 | 0 | }; |
95 | 0 |
|
96 | 0 | type = g_type_register_static(ATK_TYPE_HYPERLINK, |
97 | 0 | "MaiAtkHyperlink", |
98 | 0 | &tinfo, GTypeFlags(0)); |
99 | 0 | } |
100 | 0 | return type; |
101 | 0 | } |
102 | | |
103 | | MaiHyperlink::MaiHyperlink(AccessibleOrProxy aHyperLink) : |
104 | | mHyperlink(aHyperLink), |
105 | | mMaiAtkHyperlink(nullptr) |
106 | 0 | { |
107 | 0 | mMaiAtkHyperlink = |
108 | 0 | reinterpret_cast<AtkHyperlink *> |
109 | 0 | (g_object_new(mai_atk_hyperlink_get_type(), nullptr)); |
110 | 0 | NS_ASSERTION(mMaiAtkHyperlink, "OUT OF MEMORY"); |
111 | 0 | if (!mMaiAtkHyperlink) |
112 | 0 | return; |
113 | 0 | |
114 | 0 | MAI_ATK_HYPERLINK(mMaiAtkHyperlink)->maiHyperlink = this; |
115 | 0 | } |
116 | | |
117 | | MaiHyperlink::~MaiHyperlink() |
118 | 0 | { |
119 | 0 | if (mMaiAtkHyperlink) { |
120 | 0 | MAI_ATK_HYPERLINK(mMaiAtkHyperlink)->maiHyperlink = nullptr; |
121 | 0 | g_object_unref(mMaiAtkHyperlink); |
122 | 0 | } |
123 | 0 | } |
124 | | |
125 | | |
126 | | /* static functions for ATK callbacks */ |
127 | | |
128 | | void |
129 | | classInitCB(AtkHyperlinkClass *aClass) |
130 | 0 | { |
131 | 0 | GObjectClass *gobject_class = G_OBJECT_CLASS(aClass); |
132 | 0 |
|
133 | 0 | parent_class = g_type_class_peek_parent(aClass); |
134 | 0 |
|
135 | 0 | aClass->get_uri = getUriCB; |
136 | 0 | aClass->get_object = getObjectCB; |
137 | 0 | aClass->get_end_index = getEndIndexCB; |
138 | 0 | aClass->get_start_index = getStartIndexCB; |
139 | 0 | aClass->is_valid = isValidCB; |
140 | 0 | aClass->get_n_anchors = getAnchorCountCB; |
141 | 0 |
|
142 | 0 | gobject_class->finalize = finalizeCB; |
143 | 0 | } |
144 | | |
145 | | void |
146 | | finalizeCB(GObject *aObj) |
147 | 0 | { |
148 | 0 | NS_ASSERTION(MAI_IS_ATK_HYPERLINK(aObj), "Invalid MaiAtkHyperlink"); |
149 | 0 | if (!MAI_IS_ATK_HYPERLINK(aObj)) |
150 | 0 | return; |
151 | 0 | |
152 | 0 | MaiAtkHyperlink *maiAtkHyperlink = MAI_ATK_HYPERLINK(aObj); |
153 | 0 | maiAtkHyperlink->maiHyperlink = nullptr; |
154 | 0 |
|
155 | 0 | /* call parent finalize function */ |
156 | 0 | if (G_OBJECT_CLASS (parent_class)->finalize) |
157 | 0 | G_OBJECT_CLASS (parent_class)->finalize(aObj); |
158 | 0 | } |
159 | | |
160 | | gchar * |
161 | | getUriCB(AtkHyperlink *aLink, gint aLinkIndex) |
162 | 0 | { |
163 | 0 | MaiHyperlink* maiLink = GetMaiHyperlink(aLink); |
164 | 0 | if (!maiLink) |
165 | 0 | return nullptr; |
166 | 0 | |
167 | 0 | nsAutoCString cautoStr; |
168 | 0 | if (Accessible* hyperlink = maiLink->GetAccHyperlink()) { |
169 | 0 | nsCOMPtr<nsIURI> uri = hyperlink->AnchorURIAt(aLinkIndex); |
170 | 0 | if (!uri) |
171 | 0 | return nullptr; |
172 | 0 | |
173 | 0 | nsresult rv = uri->GetSpec(cautoStr); |
174 | 0 | NS_ENSURE_SUCCESS(rv, nullptr); |
175 | 0 |
|
176 | 0 | return g_strdup(cautoStr.get()); |
177 | 0 | } |
178 | 0 | |
179 | 0 | bool valid; |
180 | 0 | maiLink->Proxy()->AnchorURIAt(aLinkIndex, cautoStr, &valid); |
181 | 0 | if (!valid) |
182 | 0 | return nullptr; |
183 | 0 | |
184 | 0 | return g_strdup(cautoStr.get()); |
185 | 0 | } |
186 | | |
187 | | AtkObject * |
188 | | getObjectCB(AtkHyperlink *aLink, gint aLinkIndex) |
189 | 0 | { |
190 | 0 | MaiHyperlink* maiLink = GetMaiHyperlink(aLink); |
191 | 0 | if (!maiLink) { |
192 | 0 | return nullptr; |
193 | 0 | } |
194 | 0 | |
195 | 0 | if (Accessible* hyperlink = maiLink->GetAccHyperlink()) { |
196 | 0 | Accessible* anchor = hyperlink->AnchorAt(aLinkIndex); |
197 | 0 | NS_ENSURE_TRUE(anchor, nullptr); |
198 | 0 |
|
199 | 0 | return AccessibleWrap::GetAtkObject(anchor); |
200 | 0 | } |
201 | 0 | |
202 | 0 | ProxyAccessible* anchor = maiLink->Proxy()->AnchorAt(aLinkIndex); |
203 | 0 | return anchor ? GetWrapperFor(anchor) : nullptr; |
204 | 0 | } |
205 | | |
206 | | gint |
207 | | getEndIndexCB(AtkHyperlink *aLink) |
208 | 0 | { |
209 | 0 | MaiHyperlink* maiLink = GetMaiHyperlink(aLink); |
210 | 0 | if (!maiLink) |
211 | 0 | return false; |
212 | 0 | |
213 | 0 | if (Accessible* hyperlink = maiLink->GetAccHyperlink()) |
214 | 0 | return static_cast<gint>(hyperlink->EndOffset()); |
215 | 0 | |
216 | 0 | bool valid = false; |
217 | 0 | uint32_t endIdx = maiLink->Proxy()->EndOffset(&valid); |
218 | 0 | return valid ? static_cast<gint>(endIdx) : -1; |
219 | 0 | } |
220 | | |
221 | | gint |
222 | | getStartIndexCB(AtkHyperlink *aLink) |
223 | 0 | { |
224 | 0 | MaiHyperlink* maiLink = GetMaiHyperlink(aLink); |
225 | 0 | if (!maiLink) |
226 | 0 | return -1; |
227 | 0 | |
228 | 0 | if (Accessible* hyperlink = maiLink->GetAccHyperlink()) |
229 | 0 | return static_cast<gint>(hyperlink->StartOffset()); |
230 | 0 | |
231 | 0 | bool valid = false; |
232 | 0 | uint32_t startIdx = maiLink->Proxy()->StartOffset(&valid); |
233 | 0 | return valid ? static_cast<gint>(startIdx) : -1; |
234 | 0 | } |
235 | | |
236 | | gboolean |
237 | | isValidCB(AtkHyperlink *aLink) |
238 | 0 | { |
239 | 0 | MaiHyperlink* maiLink = GetMaiHyperlink(aLink); |
240 | 0 | if (!maiLink) |
241 | 0 | return false; |
242 | 0 | |
243 | 0 | if (Accessible* hyperlink = maiLink->GetAccHyperlink()) |
244 | 0 | return static_cast<gboolean>(hyperlink->IsLinkValid()); |
245 | 0 | |
246 | 0 | return static_cast<gboolean>(maiLink->Proxy()->IsLinkValid()); |
247 | 0 | } |
248 | | |
249 | | gint |
250 | | getAnchorCountCB(AtkHyperlink *aLink) |
251 | 0 | { |
252 | 0 | MaiHyperlink* maiLink = GetMaiHyperlink(aLink); |
253 | 0 | if (!maiLink) |
254 | 0 | return -1; |
255 | 0 | |
256 | 0 | if (Accessible* hyperlink = maiLink->GetAccHyperlink()) |
257 | 0 | return static_cast<gint>(hyperlink->AnchorCount()); |
258 | 0 | |
259 | 0 | bool valid = false; |
260 | 0 | uint32_t anchorCount = maiLink->Proxy()->AnchorCount(&valid); |
261 | 0 | return valid ? static_cast<gint>(anchorCount) : -1; |
262 | 0 | } |