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