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 "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 : #define MAI_ATK_HYPERLINK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),\
17 : 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 : #define MAI_IS_ATK_HYPERLINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\
21 : 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 0 : GetMaiHyperlink(AtkHyperlink *aHyperlink)
68 : {
69 0 : NS_ENSURE_TRUE(MAI_IS_ATK_HYPERLINK(aHyperlink), nullptr);
70 : 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 : }
76 :
77 : GType
78 0 : mai_atk_hyperlink_get_type(void)
79 : {
80 : static GType type = 0;
81 :
82 0 : if (!type) {
83 : static const GTypeInfo tinfo = {
84 : sizeof(MaiAtkHyperlinkClass),
85 : (GBaseInitFunc)nullptr,
86 : (GBaseFinalizeFunc)nullptr,
87 : (GClassInitFunc)classInitCB,
88 : (GClassFinalizeFunc)nullptr,
89 : nullptr, /* class data */
90 : sizeof(MaiAtkHyperlink), /* instance size */
91 : 0, /* nb preallocs */
92 : (GInstanceInitFunc)nullptr,
93 : nullptr /* value table */
94 : };
95 :
96 0 : type = g_type_register_static(ATK_TYPE_HYPERLINK,
97 : "MaiAtkHyperlink",
98 : &tinfo, GTypeFlags(0));
99 : }
100 0 : return type;
101 : }
102 :
103 0 : MaiHyperlink::MaiHyperlink(AccessibleOrProxy aHyperLink) :
104 : mHyperlink(aHyperLink),
105 0 : mMaiAtkHyperlink(nullptr)
106 : {
107 0 : mMaiAtkHyperlink =
108 : 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 :
114 0 : MAI_ATK_HYPERLINK(mMaiAtkHyperlink)->maiHyperlink = this;
115 : }
116 :
117 0 : MaiHyperlink::~MaiHyperlink()
118 : {
119 0 : if (mMaiAtkHyperlink) {
120 0 : MAI_ATK_HYPERLINK(mMaiAtkHyperlink)->maiHyperlink = nullptr;
121 0 : g_object_unref(mMaiAtkHyperlink);
122 : }
123 0 : }
124 :
125 :
126 : /* static functions for ATK callbacks */
127 :
128 : void
129 0 : classInitCB(AtkHyperlinkClass *aClass)
130 : {
131 0 : GObjectClass *gobject_class = G_OBJECT_CLASS(aClass);
132 :
133 0 : parent_class = g_type_class_peek_parent(aClass);
134 :
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 :
142 0 : gobject_class->finalize = finalizeCB;
143 0 : }
144 :
145 : void
146 0 : finalizeCB(GObject *aObj)
147 : {
148 0 : NS_ASSERTION(MAI_IS_ATK_HYPERLINK(aObj), "Invalid MaiAtkHyperlink");
149 0 : if (!MAI_IS_ATK_HYPERLINK(aObj))
150 0 : return;
151 :
152 0 : MaiAtkHyperlink *maiAtkHyperlink = MAI_ATK_HYPERLINK(aObj);
153 0 : maiAtkHyperlink->maiHyperlink = nullptr;
154 :
155 : /* call parent finalize function */
156 0 : if (G_OBJECT_CLASS (parent_class)->finalize)
157 0 : G_OBJECT_CLASS (parent_class)->finalize(aObj);
158 : }
159 :
160 : gchar *
161 0 : getUriCB(AtkHyperlink *aLink, gint aLinkIndex)
162 : {
163 0 : MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
164 0 : if (!maiLink)
165 0 : return nullptr;
166 :
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 :
173 0 : nsresult rv = uri->GetSpec(cautoStr);
174 0 : NS_ENSURE_SUCCESS(rv, nullptr);
175 :
176 0 : return g_strdup(cautoStr.get());
177 : }
178 :
179 : bool valid;
180 0 : maiLink->Proxy()->AnchorURIAt(aLinkIndex, cautoStr, &valid);
181 0 : if (!valid)
182 0 : return nullptr;
183 :
184 0 : return g_strdup(cautoStr.get());
185 : }
186 :
187 : AtkObject *
188 0 : getObjectCB(AtkHyperlink *aLink, gint aLinkIndex)
189 : {
190 0 : MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
191 0 : if (!maiLink) {
192 0 : return nullptr;
193 : }
194 :
195 0 : if (Accessible* hyperlink = maiLink->GetAccHyperlink()) {
196 0 : Accessible* anchor = hyperlink->AnchorAt(aLinkIndex);
197 0 : NS_ENSURE_TRUE(anchor, nullptr);
198 :
199 0 : return AccessibleWrap::GetAtkObject(anchor);
200 : }
201 :
202 0 : ProxyAccessible* anchor = maiLink->Proxy()->AnchorAt(aLinkIndex);
203 0 : return anchor ? GetWrapperFor(anchor) : nullptr;
204 : }
205 :
206 : gint
207 0 : getEndIndexCB(AtkHyperlink *aLink)
208 : {
209 0 : MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
210 0 : if (!maiLink)
211 0 : return false;
212 :
213 0 : if (Accessible* hyperlink = maiLink->GetAccHyperlink())
214 0 : return static_cast<gint>(hyperlink->EndOffset());
215 :
216 0 : bool valid = false;
217 0 : uint32_t endIdx = maiLink->Proxy()->EndOffset(&valid);
218 0 : return valid ? static_cast<gint>(endIdx) : -1;
219 : }
220 :
221 : gint
222 0 : getStartIndexCB(AtkHyperlink *aLink)
223 : {
224 0 : MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
225 0 : if (!maiLink)
226 0 : return -1;
227 :
228 0 : if (Accessible* hyperlink = maiLink->GetAccHyperlink())
229 0 : return static_cast<gint>(hyperlink->StartOffset());
230 :
231 0 : bool valid = false;
232 0 : uint32_t startIdx = maiLink->Proxy()->StartOffset(&valid);
233 0 : return valid ? static_cast<gint>(startIdx) : -1;
234 : }
235 :
236 : gboolean
237 0 : isValidCB(AtkHyperlink *aLink)
238 : {
239 0 : MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
240 0 : if (!maiLink)
241 0 : return false;
242 :
243 0 : if (Accessible* hyperlink = maiLink->GetAccHyperlink())
244 0 : return static_cast<gboolean>(hyperlink->IsLinkValid());
245 :
246 0 : return static_cast<gboolean>(maiLink->Proxy()->IsLinkValid());
247 : }
248 :
249 : gint
250 0 : getAnchorCountCB(AtkHyperlink *aLink)
251 : {
252 0 : MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
253 0 : if (!maiLink)
254 0 : return -1;
255 :
256 0 : if (Accessible* hyperlink = maiLink->GetAccHyperlink())
257 0 : return static_cast<gint>(hyperlink->AnchorCount());
258 :
259 0 : bool valid = false;
260 0 : uint32_t anchorCount = maiLink->Proxy()->AnchorCount(&valid);
261 0 : return valid ? static_cast<gint>(anchorCount) : -1;
262 : }
|