1 /* This file is part of the GtkHTML library.
2 *
3 * Copyright 2002 Ximian, Inc.
4 *
5 * Author: Radek Doulik
6 *
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 */
23
24 #include <config.h>
25 #include <atk/atkhyperlink.h>
26
27 #include "htmltext.h"
28
29 #include "object.h"
30 #include "html.h"
31 #include "hyperlink.h"
32
33 static void html_a11y_hyper_link_class_init (HTMLA11YHyperLinkClass *klass);
34 static void html_a11y_hyper_link_init (HTMLA11YHyperLink *a11y_hyper_link);
35
36 static void atk_action_interface_init (AtkActionIface *iface);
37
38 static gboolean html_a11y_hyper_link_do_action (AtkAction *action, gint i);
39 static gint html_a11y_hyper_link_get_n_actions (AtkAction *action);
40 static const gchar * html_a11y_hyper_link_get_description (AtkAction *action, gint i);
41 static const gchar * html_a11y_hyper_link_get_name (AtkAction *action, gint i);
42 static gboolean html_a11y_hyper_link_set_description (AtkAction *action, gint i, const gchar *description);
43
44 static AtkObjectClass *parent_class = NULL;
45
46 GType
html_a11y_hyper_link_get_type(void)47 html_a11y_hyper_link_get_type (void)
48 {
49 static GType type = 0;
50
51 if (!type) {
52 static const GTypeInfo tinfo = {
53 sizeof (HTMLA11YHyperLinkClass),
54 NULL, /* base init */
55 NULL, /* base finalize */
56 (GClassInitFunc) html_a11y_hyper_link_class_init, /* class init */
57 NULL, /* class finalize */
58 NULL, /* class data */
59 sizeof (HTMLA11YHyperLink), /* instance size */
60 0, /* nb preallocs */
61 (GInstanceInitFunc) html_a11y_hyper_link_init, /* instance init */
62 NULL /* value table */
63 };
64
65 static const GInterfaceInfo atk_action_info = {
66 (GInterfaceInitFunc) atk_action_interface_init,
67 (GInterfaceFinalizeFunc) NULL,
68 NULL
69 };
70
71 type = g_type_register_static (ATK_TYPE_HYPERLINK, "HTMLA11YHyperLink", &tinfo, 0);
72 g_type_add_interface_static (type, ATK_TYPE_ACTION, &atk_action_info);
73 }
74
75 return type;
76 }
77
78 static void
atk_action_interface_init(AtkActionIface * iface)79 atk_action_interface_init (AtkActionIface *iface)
80 {
81 g_return_if_fail (iface != NULL);
82
83 iface->do_action = html_a11y_hyper_link_do_action;
84 iface->get_n_actions = html_a11y_hyper_link_get_n_actions;
85 iface->get_description = html_a11y_hyper_link_get_description;
86 iface->get_name = html_a11y_hyper_link_get_name;
87 iface->set_description = html_a11y_hyper_link_set_description;
88 }
89
90 static void
html_a11y_hyper_link_finalize(GObject * obj)91 html_a11y_hyper_link_finalize (GObject *obj)
92 {
93 HTMLA11YHyperLink *hl = HTML_A11Y_HYPER_LINK (obj);
94
95 if (hl->a11y.object)
96 g_object_remove_weak_pointer (G_OBJECT (hl->a11y.object),
97 &hl->a11y.weakref);
98
99 G_OBJECT_CLASS (parent_class)->finalize (obj);
100 }
101
102 static gint
html_a11y_hyper_link_get_start_index(AtkHyperlink * link)103 html_a11y_hyper_link_get_start_index (AtkHyperlink *link)
104 {
105 HTMLA11YHyperLink *hl = HTML_A11Y_HYPER_LINK (link);
106 HTMLText *text = HTML_TEXT (HTML_A11Y_HTML (hl->a11y.object));
107 Link *a = (Link *) g_slist_nth_data (text->links, hl->num);
108 return a ? a->start_offset : -1;
109 }
110
111 static gint
html_a11y_hyper_link_get_end_index(AtkHyperlink * link)112 html_a11y_hyper_link_get_end_index (AtkHyperlink *link)
113 {
114 HTMLA11YHyperLink *hl = HTML_A11Y_HYPER_LINK (link);
115 Link *a = (Link *) g_slist_nth_data (HTML_TEXT (HTML_A11Y_HTML (hl->a11y.object))->links, hl->num);
116 return a ? a->end_offset : -1;
117 }
118
119 static void
html_a11y_hyper_link_class_init(HTMLA11YHyperLinkClass * klass)120 html_a11y_hyper_link_class_init (HTMLA11YHyperLinkClass *klass)
121 {
122 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
123 AtkHyperlinkClass *atk_hyperlink_class = ATK_HYPERLINK_CLASS (klass);
124 parent_class = g_type_class_peek_parent (klass);
125
126 atk_hyperlink_class->get_start_index = html_a11y_hyper_link_get_start_index;
127 atk_hyperlink_class->get_end_index = html_a11y_hyper_link_get_end_index;
128 gobject_class->finalize = html_a11y_hyper_link_finalize;
129 }
130
131 static void
html_a11y_hyper_link_init(HTMLA11YHyperLink * a11y_hyper_link)132 html_a11y_hyper_link_init (HTMLA11YHyperLink *a11y_hyper_link)
133 {
134 a11y_hyper_link->description = NULL;
135 }
136
137 AtkHyperlink *
html_a11y_hyper_link_new(HTMLA11Y * a11y,gint link_index)138 html_a11y_hyper_link_new (HTMLA11Y *a11y,
139 gint link_index)
140 {
141 HTMLA11YHyperLink *hl;
142
143 g_return_val_if_fail (G_IS_HTML_A11Y (a11y), NULL);
144
145 hl = HTML_A11Y_HYPER_LINK (g_object_new (G_TYPE_HTML_A11Y_HYPER_LINK, NULL));
146
147 hl->a11y.object = a11y;
148 hl->num = link_index;
149 hl->offset = ((Link *) g_slist_nth_data (HTML_TEXT (HTML_A11Y_HTML (a11y))->links, link_index))->start_offset;
150 g_object_add_weak_pointer (G_OBJECT (hl->a11y.object), &hl->a11y.weakref);
151
152 return ATK_HYPERLINK (hl);
153 }
154
155 /*
156 * Action interface
157 */
158
159 static gboolean
html_a11y_hyper_link_do_action(AtkAction * action,gint i)160 html_a11y_hyper_link_do_action (AtkAction *action,
161 gint i)
162 {
163 HTMLA11YHyperLink *hl;
164 gboolean result = FALSE;
165
166 hl = HTML_A11Y_HYPER_LINK (action);
167
168 if (i == 0 && hl->a11y.object) {
169 HTMLText *text = HTML_TEXT (HTML_A11Y_HTML (hl->a11y.object));
170 gchar *url = html_object_get_complete_url (HTML_OBJECT (text), hl->offset);
171
172 if (url && *url) {
173 GObject *gtkhtml = GTK_HTML_A11Y_GTKHTML_POINTER
174 (html_a11y_get_gtkhtml_parent (HTML_A11Y (hl->a11y.object)));
175
176 g_signal_emit_by_name (gtkhtml, "link_clicked", url);
177 result = TRUE;
178 }
179
180 g_free (url);
181 }
182
183 return result;
184 }
185
186 static gint
html_a11y_hyper_link_get_n_actions(AtkAction * action)187 html_a11y_hyper_link_get_n_actions (AtkAction *action)
188 {
189 return 1;
190 }
191
192 static const gchar *
html_a11y_hyper_link_get_description(AtkAction * action,gint i)193 html_a11y_hyper_link_get_description (AtkAction *action,
194 gint i)
195 {
196 if (i == 0) {
197 HTMLA11YHyperLink *hl;
198
199 hl = HTML_A11Y_HYPER_LINK (action);
200
201 return hl->description;
202 }
203
204 return NULL;
205 }
206
207 static const gchar *
html_a11y_hyper_link_get_name(AtkAction * action,gint i)208 html_a11y_hyper_link_get_name (AtkAction *action,
209 gint i)
210 {
211 return i == 0 ? "link click" : NULL;
212 }
213
214 static gboolean
html_a11y_hyper_link_set_description(AtkAction * action,gint i,const gchar * description)215 html_a11y_hyper_link_set_description (AtkAction *action,
216 gint i,
217 const gchar *description)
218 {
219 if (i == 0) {
220 HTMLA11YHyperLink *hl;
221
222 hl = HTML_A11Y_HYPER_LINK (action);
223
224 g_free (hl->description);
225 hl->description = g_strdup (description);
226
227 return TRUE;
228 }
229
230 return FALSE;
231 }
232