]> Pileus Git - ~andy/gtk/blob - gtk/a11y/gtkentryaccessible.c
First cut at GailEntry -> GtkEntryAccessible
[~andy/gtk] / gtk / a11y / gtkentryaccessible.c
1 /* GAIL - The GNOME Accessibility Implementation Library
2  * Copyright 2001, 2002, 2003 Sun Microsystems Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include "config.h"
21
22 #include <string.h>
23 #include <gtk/gtk.h>
24 #include <gdk/gdkkeysyms.h>
25 #include "gtkentryaccessible.h"
26 #include "gailcombobox.h"
27 #include <libgail-util/gailmisc.h>
28
29 static void       gtk_entry_accessible_class_init            (GtkEntryAccessibleClass       *klass);
30 static void       gtk_entry_accessible_init                  (GtkEntryAccessible            *entry);
31 static void       gtk_entry_accessible_real_initialize       (AtkObject            *obj,
32                                                     gpointer             data);
33 static void       text_setup                       (GtkEntryAccessible            *entry,
34                                                     GtkEntry             *gtk_entry);
35 static void       gtk_entry_accessible_real_notify_gtk     (GObject              *obj,
36                                                     GParamSpec           *pspec);
37 static void       gtk_entry_accessible_finalize              (GObject              *object);
38
39 static gint       gtk_entry_accessible_get_index_in_parent   (AtkObject            *accessible);
40
41 /* atkobject.h */
42
43 static AtkStateSet*     gtk_entry_accessible_ref_state_set   (AtkObject            *accessible);
44 static AtkAttributeSet* gtk_entry_accessible_get_attributes  (AtkObject            *accessible);
45
46 /* atktext.h */
47
48 static void       atk_text_interface_init          (AtkTextIface         *iface);
49
50 static gchar*     gtk_entry_accessible_get_text              (AtkText              *text,
51                                                     gint                 start_pos,
52                                                     gint                 end_pos);
53 static gunichar   gtk_entry_accessible_get_character_at_offset
54                                                    (AtkText              *text,
55                                                     gint                 offset);
56 static gchar*     gtk_entry_accessible_get_text_before_offset(AtkText            *text,
57                                                     gint                 offset,
58                                                     AtkTextBoundary      boundary_type,
59                                                     gint                 *start_offset,
60                                                     gint                 *end_offset);
61 static gchar*     gtk_entry_accessible_get_text_at_offset          (AtkText              *text,
62                                                     gint                 offset,
63                                                     AtkTextBoundary      boundary_type,
64                                                     gint                 *start_offset,
65                                                     gint                 *end_offset);
66 static gchar*     gtk_entry_accessible_get_text_after_offset (AtkText            *text,
67                                                     gint                 offset,
68                                                     AtkTextBoundary      boundary_type,
69                                                     gint                 *start_offset,
70                                                     gint                 *end_offset);
71 static gint       gtk_entry_accessible_get_caret_offset      (AtkText              *text);
72 static gboolean   gtk_entry_accessible_set_caret_offset      (AtkText              *text,
73                                                     gint                 offset);
74 static gint       gtk_entry_accessible_get_n_selections    (AtkText              *text);
75 static gchar*     gtk_entry_accessible_get_selection       (AtkText              *text,
76                                                     gint                 selection_num,
77                                                     gint                 *start_offset,
78                                                     gint                 *end_offset);
79 static gboolean   gtk_entry_accessible_add_selection       (AtkText              *text,
80                                                     gint                 start_offset,
81                                                     gint                 end_offset);
82 static gboolean   gtk_entry_accessible_remove_selection    (AtkText              *text,
83                                                     gint                 selection_num);
84 static gboolean   gtk_entry_accessible_set_selection       (AtkText              *text,
85                                                     gint                 selection_num,
86                                                     gint                 start_offset,
87                                                     gint                 end_offset);
88 static gint       gtk_entry_accessible_get_character_count   (AtkText            *text);
89 static AtkAttributeSet *  gtk_entry_accessible_get_run_attributes 
90                                                    (AtkText              *text,
91                                                     gint                 offset,
92                                                     gint                 *start_offset,
93                                                     gint                 *end_offset);
94 static AtkAttributeSet *  gtk_entry_accessible_get_default_attributes 
95                                                    (AtkText              *text);
96 static void gtk_entry_accessible_get_character_extents       (AtkText            *text,
97                                                     gint                 offset,
98                                                     gint                 *x,
99                                                     gint                 *y,
100                                                     gint                 *width,
101                                                     gint                 *height,
102                                                     AtkCoordType         coords);
103 static gint gtk_entry_accessible_get_offset_at_point         (AtkText              *text,
104                                                     gint                 x,
105                                                     gint                 y,
106                                                     AtkCoordType         coords);
107 /* atkeditabletext.h */
108
109 static void       atk_editable_text_interface_init (AtkEditableTextIface *iface);
110 static void       gtk_entry_accessible_set_text_contents     (AtkEditableText      *text,
111                                                     const gchar          *string);
112 static void       gtk_entry_accessible_insert_text           (AtkEditableText      *text,
113                                                     const gchar          *string,
114                                                     gint                 length,
115                                                     gint                 *position);
116 static void       gtk_entry_accessible_copy_text             (AtkEditableText      *text,
117                                                     gint                 start_pos,
118                                                     gint                 end_pos);
119 static void       gtk_entry_accessible_cut_text              (AtkEditableText      *text,
120                                                     gint                 start_pos,
121                                                     gint                 end_pos);
122 static void       gtk_entry_accessible_delete_text           (AtkEditableText      *text,
123                                                     gint                 start_pos,
124                                                     gint                 end_pos);
125 static void       gtk_entry_accessible_paste_text            (AtkEditableText      *text,
126                                                     gint                 position);
127 static void       gtk_entry_accessible_paste_received      (GtkClipboard *clipboard,
128                                                     const gchar  *text,
129                                                     gpointer     data);
130
131
132 /* Callbacks */
133
134 static gboolean   gtk_entry_accessible_idle_notify_insert    (gpointer data);
135 static void       gtk_entry_accessible_notify_insert         (GtkEntryAccessible            *entry);
136 static void       gtk_entry_accessible_notify_delete         (GtkEntryAccessible            *entry);
137 static void       _gtk_entry_accessible_insert_text_cb     (GtkEntry             *entry,
138                                                     gchar                *arg1,
139                                                     gint                 arg2,
140                                                     gpointer             arg3);
141 static void       _gtk_entry_accessible_delete_text_cb     (GtkEntry             *entry,
142                                                     gint                 arg1,
143                                                     gint                 arg2);
144 static void       _gtk_entry_accessible_changed_cb           (GtkEntry           *entry);
145 static gboolean   check_for_selection_change       (GtkEntryAccessible            *entry,
146                                                     GtkEntry             *gtk_entry);
147
148 static void                  atk_action_interface_init          (AtkActionIface  *iface);
149
150 static gboolean              gtk_entry_accessible_do_action               (AtkAction       *action,
151                                                                  gint            i);
152 static gboolean              idle_do_action                     (gpointer        data);
153 static gint                  gtk_entry_accessible_get_n_actions           (AtkAction       *action);
154 static const gchar* gtk_entry_accessible_get_keybinding          (AtkAction       *action,
155                                                                  gint            i);
156 static const gchar* gtk_entry_accessible_action_get_name         (AtkAction       *action,
157                                                                  gint            i);
158
159 typedef struct _GtkEntryAccessiblePaste                 GtkEntryAccessiblePaste;
160
161 struct _GtkEntryAccessiblePaste
162 {
163   GtkEntry* entry;
164   gint position;
165 };
166
167 G_DEFINE_TYPE_WITH_CODE (GtkEntryAccessible, gtk_entry_accessible, GAIL_TYPE_WIDGET,
168                          G_IMPLEMENT_INTERFACE (ATK_TYPE_EDITABLE_TEXT, atk_editable_text_interface_init)
169                          G_IMPLEMENT_INTERFACE (ATK_TYPE_TEXT, atk_text_interface_init)
170                          G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, atk_action_interface_init))
171
172 static void
173 gtk_entry_accessible_class_init (GtkEntryAccessibleClass *klass)
174 {
175   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
176   AtkObjectClass  *class = ATK_OBJECT_CLASS (klass);
177   GailWidgetClass *widget_class;
178
179   widget_class = (GailWidgetClass*)klass;
180
181   gobject_class->finalize = gtk_entry_accessible_finalize;
182
183   class->ref_state_set = gtk_entry_accessible_ref_state_set;
184   class->get_index_in_parent = gtk_entry_accessible_get_index_in_parent;
185   class->initialize = gtk_entry_accessible_real_initialize;
186   class->get_attributes = gtk_entry_accessible_get_attributes;
187
188   widget_class->notify_gtk = gtk_entry_accessible_real_notify_gtk;
189 }
190
191 static void
192 gtk_entry_accessible_init (GtkEntryAccessible *entry)
193 {
194   entry->textutil = NULL;
195   entry->signal_name_insert = NULL;
196   entry->signal_name_delete = NULL;
197   entry->cursor_position = 0;
198   entry->selection_bound = 0;
199   entry->activate_keybinding = NULL;
200 }
201
202 static void
203 gtk_entry_accessible_real_initialize (AtkObject *obj, 
204                             gpointer  data)
205 {
206   GtkEntry *entry;
207   GtkEntryAccessible *gtk_entry_accessible;
208   gint start_pos, end_pos;
209
210   ATK_OBJECT_CLASS (gtk_entry_accessible_parent_class)->initialize (obj, data);
211
212   gtk_entry_accessible = GTK_ENTRY_ACCESSIBLE (obj);
213   gtk_entry_accessible->textutil = gail_text_util_new ();
214   
215   g_assert (GTK_IS_ENTRY (data));
216
217   entry = GTK_ENTRY (data);
218   text_setup (gtk_entry_accessible, entry);
219   gtk_editable_get_selection_bounds (GTK_EDITABLE (entry),
220                                      &start_pos, &end_pos);
221   gtk_entry_accessible->cursor_position = end_pos;
222   gtk_entry_accessible->selection_bound = start_pos;
223
224   /* Set up signal callbacks */
225   g_signal_connect (data, "insert-text",
226         G_CALLBACK (_gtk_entry_accessible_insert_text_cb), NULL);
227   g_signal_connect (data, "delete-text",
228         G_CALLBACK (_gtk_entry_accessible_delete_text_cb), NULL);
229   g_signal_connect (data, "changed",
230         G_CALLBACK (_gtk_entry_accessible_changed_cb), NULL);
231
232   if (gtk_entry_get_visibility (entry))
233     obj->role = ATK_ROLE_TEXT;
234   else
235     obj->role = ATK_ROLE_PASSWORD_TEXT;
236 }
237
238 static void
239 gtk_entry_accessible_real_notify_gtk (GObject           *obj,
240                             GParamSpec          *pspec)
241 {
242   GtkWidget *widget;
243   AtkObject* atk_obj;
244   GtkEntry* gtk_entry;
245   GtkEntryAccessible* entry;
246
247   widget = GTK_WIDGET (obj);
248   atk_obj = gtk_widget_get_accessible (widget);
249   gtk_entry = GTK_ENTRY (widget);
250   entry = GTK_ENTRY_ACCESSIBLE (atk_obj);
251
252   if (strcmp (pspec->name, "cursor-position") == 0)
253     {
254       if (entry->insert_idle_handler == 0)
255         entry->insert_idle_handler = gdk_threads_add_idle (gtk_entry_accessible_idle_notify_insert, entry);
256
257       if (check_for_selection_change (entry, gtk_entry))
258         g_signal_emit_by_name (atk_obj, "text_selection_changed");
259       /*
260        * The entry cursor position has moved so generate the signal.
261        */
262       g_signal_emit_by_name (atk_obj, "text_caret_moved", 
263                              entry->cursor_position);
264     }
265   else if (strcmp (pspec->name, "selection-bound") == 0)
266     {
267       if (entry->insert_idle_handler == 0)
268         entry->insert_idle_handler = gdk_threads_add_idle (gtk_entry_accessible_idle_notify_insert, entry);
269
270       if (check_for_selection_change (entry, gtk_entry))
271         g_signal_emit_by_name (atk_obj, "text_selection_changed");
272     }
273   else if (strcmp (pspec->name, "editable") == 0)
274     {
275       gboolean value;
276
277       g_object_get (obj, "editable", &value, NULL);
278       atk_object_notify_state_change (atk_obj, ATK_STATE_EDITABLE,
279                                                value);
280     }
281   else if (strcmp (pspec->name, "visibility") == 0)
282     {
283       gboolean visibility;
284       AtkRole new_role;
285
286       text_setup (entry, gtk_entry);
287       visibility = gtk_entry_get_visibility (gtk_entry);
288       new_role = visibility ? ATK_ROLE_TEXT : ATK_ROLE_PASSWORD_TEXT;
289       atk_object_set_role (atk_obj, new_role);
290     }
291   else if (strcmp (pspec->name, "invisible-char") == 0)
292     {
293       text_setup (entry, gtk_entry);
294     }
295   else if (strcmp (pspec->name, "editing-canceled") == 0)
296     {
297       if (entry->insert_idle_handler)
298         {
299           g_source_remove (entry->insert_idle_handler);
300           entry->insert_idle_handler = 0;
301         }
302     }
303   else
304     GAIL_WIDGET_CLASS (gtk_entry_accessible_parent_class)->notify_gtk (obj, pspec);
305 }
306
307 static void
308 text_setup (GtkEntryAccessible *entry,
309             GtkEntry  *gtk_entry)
310 {
311   if (gtk_entry_get_visibility (gtk_entry))
312     {
313       gail_text_util_text_setup (entry->textutil, gtk_entry_get_text (gtk_entry));
314     }
315   else
316     {
317       gunichar invisible_char;
318       GString *tmp_string = g_string_new (NULL);
319       gint ch_len; 
320       gchar buf[7];
321       guint length;
322       gint i;
323
324       invisible_char = gtk_entry_get_invisible_char (gtk_entry);
325       if (invisible_char == 0)
326         invisible_char = ' ';
327
328       ch_len = g_unichar_to_utf8 (invisible_char, buf);
329       length = gtk_entry_get_text_length (gtk_entry);
330       for (i = 0; i < length; i++)
331         {
332           g_string_append_len (tmp_string, buf, ch_len);
333         }
334
335       gail_text_util_text_setup (entry->textutil, tmp_string->str);
336       g_string_free (tmp_string, TRUE);
337
338     } 
339 }
340
341 static void
342 gtk_entry_accessible_finalize (GObject            *object)
343 {
344   GtkEntryAccessible *entry = GTK_ENTRY_ACCESSIBLE (object);
345
346   g_object_unref (entry->textutil);
347   g_free (entry->activate_keybinding);
348   if (entry->action_idle_handler)
349     {
350       g_source_remove (entry->action_idle_handler);
351       entry->action_idle_handler = 0;
352     }
353   if (entry->insert_idle_handler)
354     {
355       g_source_remove (entry->insert_idle_handler);
356       entry->insert_idle_handler = 0;
357     }
358   G_OBJECT_CLASS (gtk_entry_accessible_parent_class)->finalize (object);
359 }
360
361 static gint
362 gtk_entry_accessible_get_index_in_parent (AtkObject *accessible)
363 {
364   /*
365    * If the parent widget is a combo box then the index is 1
366    * otherwise do the normal thing.
367    */
368   if (accessible->accessible_parent)
369     if (GAIL_IS_COMBO_BOX (accessible->accessible_parent))
370       return 1;
371
372   return ATK_OBJECT_CLASS (gtk_entry_accessible_parent_class)->get_index_in_parent (accessible);
373 }
374
375 /* atkobject.h */
376
377 static AtkStateSet*
378 gtk_entry_accessible_ref_state_set (AtkObject *accessible)
379 {
380   AtkStateSet *state_set;
381   GtkEntry *entry;
382   gboolean value;
383   GtkWidget *widget;
384
385   state_set = ATK_OBJECT_CLASS (gtk_entry_accessible_parent_class)->ref_state_set (accessible);
386   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
387
388   if (widget == NULL)
389     return state_set;
390
391   entry = GTK_ENTRY (widget);
392
393   g_object_get (G_OBJECT (entry), "editable", &value, NULL);
394   if (value)
395     atk_state_set_add_state (state_set, ATK_STATE_EDITABLE);
396   atk_state_set_add_state (state_set, ATK_STATE_SINGLE_LINE);
397
398   return state_set;
399 }
400
401 static AtkAttributeSet *
402 gtk_entry_accessible_get_attributes (AtkObject *accessible)
403 {
404   GtkWidget *widget;
405   AtkAttributeSet *attributes;
406   AtkAttribute *placeholder_text;
407   const gchar *text;
408
409   attributes = ATK_OBJECT_CLASS (gtk_entry_accessible_parent_class)->get_attributes (accessible);
410
411   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
412   if (widget == NULL)
413     return attributes;
414
415   text = gtk_entry_get_placeholder_text (GTK_ENTRY (widget));
416   if (text == NULL)
417     return attributes;
418
419   placeholder_text = g_malloc (sizeof (AtkAttribute));
420   placeholder_text->name = g_strdup ("placeholder-text");
421   placeholder_text->value = g_strdup (text);
422
423   attributes = g_slist_append (attributes, placeholder_text);
424
425   return attributes;
426 }
427
428 /* atktext.h */
429
430 static void
431 atk_text_interface_init (AtkTextIface *iface)
432 {
433   iface->get_text = gtk_entry_accessible_get_text;
434   iface->get_character_at_offset = gtk_entry_accessible_get_character_at_offset;
435   iface->get_text_before_offset = gtk_entry_accessible_get_text_before_offset;
436   iface->get_text_at_offset = gtk_entry_accessible_get_text_at_offset;
437   iface->get_text_after_offset = gtk_entry_accessible_get_text_after_offset;
438   iface->get_caret_offset = gtk_entry_accessible_get_caret_offset;
439   iface->set_caret_offset = gtk_entry_accessible_set_caret_offset;
440   iface->get_character_count = gtk_entry_accessible_get_character_count;
441   iface->get_n_selections = gtk_entry_accessible_get_n_selections;
442   iface->get_selection = gtk_entry_accessible_get_selection;
443   iface->add_selection = gtk_entry_accessible_add_selection;
444   iface->remove_selection = gtk_entry_accessible_remove_selection;
445   iface->set_selection = gtk_entry_accessible_set_selection;
446   iface->get_run_attributes = gtk_entry_accessible_get_run_attributes;
447   iface->get_default_attributes = gtk_entry_accessible_get_default_attributes;
448   iface->get_character_extents = gtk_entry_accessible_get_character_extents;
449   iface->get_offset_at_point = gtk_entry_accessible_get_offset_at_point;
450 }
451
452 static gchar*
453 gtk_entry_accessible_get_text (AtkText *text,
454                      gint    start_pos,
455                      gint    end_pos)
456 {
457   GtkWidget *widget;
458
459   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
460   if (widget == NULL)
461     /* State is defunct */
462     return NULL;
463
464   return gail_text_util_get_substring (GTK_ENTRY_ACCESSIBLE (text)->textutil, start_pos, end_pos);
465 }
466
467 static gchar*
468 gtk_entry_accessible_get_text_before_offset (AtkText        *text,
469                                    gint             offset,
470                                    AtkTextBoundary  boundary_type,
471                                    gint             *start_offset,
472                                    gint             *end_offset)
473 {
474   GtkWidget *widget;
475   GtkEntry *entry;
476
477   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
478   if (widget == NULL)
479     /* State is defunct */
480     return NULL;
481
482   /* Get Entry */
483   entry = GTK_ENTRY (widget);
484
485   return gail_text_util_get_text (GTK_ENTRY_ACCESSIBLE (text)->textutil,
486                           gtk_entry_get_layout (entry), GAIL_BEFORE_OFFSET, 
487                           boundary_type, offset, start_offset, end_offset);
488 }
489
490 static gchar*
491 gtk_entry_accessible_get_text_at_offset (AtkText          *text,
492                                gint             offset,
493                                AtkTextBoundary  boundary_type,
494                                gint             *start_offset,
495                                gint             *end_offset)
496 {
497   GtkWidget *widget;
498   GtkEntry *entry;
499
500   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
501   if (widget == NULL)
502     /* State is defunct */
503     return NULL;
504
505   /* Get Entry */
506   entry = GTK_ENTRY (widget);
507
508   return gail_text_util_get_text (GTK_ENTRY_ACCESSIBLE (text)->textutil,
509                             gtk_entry_get_layout (entry), GAIL_AT_OFFSET, 
510                             boundary_type, offset, start_offset, end_offset);
511 }
512
513 static gchar*
514 gtk_entry_accessible_get_text_after_offset  (AtkText        *text,
515                                    gint             offset,
516                                    AtkTextBoundary  boundary_type,
517                                    gint             *start_offset,
518                                    gint             *end_offset)
519 {
520   GtkWidget *widget;
521   GtkEntry *entry;
522
523   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
524   if (widget == NULL)
525     /* State is defunct */
526     return NULL;
527
528   /* Get Entry */
529   entry = GTK_ENTRY (widget);
530
531   return gail_text_util_get_text (GTK_ENTRY_ACCESSIBLE (text)->textutil,
532                            gtk_entry_get_layout (entry), GAIL_AFTER_OFFSET, 
533                            boundary_type, offset, start_offset, end_offset);
534 }
535
536 static gint
537 gtk_entry_accessible_get_character_count (AtkText *text)
538 {
539   GtkEntry *entry;
540   GtkWidget *widget;
541
542   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
543   if (widget == NULL)
544     /* State is defunct */
545     return 0;
546
547   entry = GTK_ENTRY (widget);
548   return g_utf8_strlen (gtk_entry_get_text (entry), -1);
549 }
550
551 static gint
552 gtk_entry_accessible_get_caret_offset (AtkText *text)
553 {
554   GtkEntry *entry;
555   GtkWidget *widget;
556
557   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
558   if (widget == NULL)
559     /* State is defunct */
560     return 0;
561
562   entry = GTK_ENTRY (widget);
563
564   return gtk_editable_get_position (GTK_EDITABLE (entry));
565 }
566
567 static gboolean
568 gtk_entry_accessible_set_caret_offset (AtkText *text, gint offset)
569 {
570   GtkEntry *entry;
571   GtkWidget *widget;
572
573   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
574   if (widget == NULL)
575     /* State is defunct */
576     return FALSE;
577
578   entry = GTK_ENTRY (widget);
579
580   gtk_editable_set_position (GTK_EDITABLE (entry), offset);
581   return TRUE;
582 }
583
584 static AtkAttributeSet*
585 gtk_entry_accessible_get_run_attributes (AtkText *text,
586                                gint    offset,
587                                gint    *start_offset,
588                                gint    *end_offset)
589 {
590   GtkWidget *widget;
591   GtkEntry *entry;
592   AtkAttributeSet *at_set = NULL;
593   GtkTextDirection dir;
594
595   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
596   if (widget == NULL)
597     /* State is defunct */
598     return NULL;
599
600   entry = GTK_ENTRY (widget);
601  
602   dir = gtk_widget_get_direction (widget);
603   if (dir == GTK_TEXT_DIR_RTL)
604     {
605       at_set = gail_misc_add_attribute (at_set,
606                                         ATK_TEXT_ATTR_DIRECTION,
607        g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_DIRECTION, dir)));
608     }
609
610   at_set = gail_misc_layout_get_run_attributes (at_set,
611                                                 gtk_entry_get_layout (entry),
612                                                 (gchar*)gtk_entry_get_text (entry),
613                                                 offset,
614                                                 start_offset,
615                                                 end_offset);
616   return at_set;
617 }
618
619 static AtkAttributeSet*
620 gtk_entry_accessible_get_default_attributes (AtkText *text)
621 {
622   GtkWidget *widget;
623   GtkEntry *entry;
624   AtkAttributeSet *at_set = NULL;
625
626   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
627   if (widget == NULL)
628     /* State is defunct */
629     return NULL;
630
631   entry = GTK_ENTRY (widget);
632
633   at_set = gail_misc_get_default_attributes (at_set,
634                                              gtk_entry_get_layout (entry),
635                                              widget);
636   return at_set;
637 }
638   
639 static void
640 gtk_entry_accessible_get_character_extents (AtkText *text,
641                                   gint    offset,
642                                   gint    *x,
643                                   gint    *y,
644                                   gint    *width,
645                                   gint    *height,
646                                   AtkCoordType coords)
647 {
648   GtkWidget *widget;
649   GtkEntry *entry;
650   PangoRectangle char_rect;
651   gint index, x_layout, y_layout;
652   const gchar *entry_text;
653   gint start_pos, end_pos;
654
655   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
656   if (widget == NULL)
657     /* State is defunct */
658     return;
659
660   entry = GTK_ENTRY (widget);
661
662   gtk_editable_get_selection_bounds (GTK_EDITABLE (entry),
663                                      &start_pos, &end_pos);
664   gtk_entry_get_layout_offsets (entry, &x_layout, &y_layout);
665   entry_text = gtk_entry_get_text (entry);
666
667   index = g_utf8_offset_to_pointer (entry_text, offset) - entry_text;
668
669   /* FIXME: entry->preedit cannot be accessed directly
670   cursor_index = g_utf8_offset_to_pointer (entry_text, end_pos) - entry_text;
671   if (index > cursor_index)
672     index += entry->preedit_length;
673   */
674   pango_layout_index_to_pos (gtk_entry_get_layout(entry), index, &char_rect);
675  
676   gail_misc_get_extents_from_pango_rectangle (widget, &char_rect, 
677                         x_layout, y_layout, x, y, width, height, coords);
678
679
680 static gint 
681 gtk_entry_accessible_get_offset_at_point (AtkText *text,
682                                 gint x,
683                                 gint y,
684                                 AtkCoordType coords)
685
686   GtkWidget *widget;
687   GtkEntry *entry;
688   gint index, x_layout, y_layout;
689   const gchar *entry_text;
690
691   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
692   if (widget == NULL)
693     /* State is defunct */
694     return -1;
695
696   entry = GTK_ENTRY (widget);
697   
698   gtk_entry_get_layout_offsets (entry, &x_layout, &y_layout);
699   entry_text = gtk_entry_get_text (entry);
700   
701   index = gail_misc_get_index_at_point_in_layout (widget, 
702                gtk_entry_get_layout(entry), x_layout, y_layout, x, y, coords);
703   if (index == -1)
704     {
705       if (coords == ATK_XY_SCREEN || coords == ATK_XY_WINDOW)
706         return g_utf8_strlen (entry_text, -1);
707
708       return index;  
709     }
710   else
711     {
712       gint start_pos, end_pos;
713
714       gtk_editable_get_selection_bounds (GTK_EDITABLE (entry),
715                                          &start_pos, &end_pos);
716       /* FIXME: entry->preedit_length cannot be accessed directly
717       cursor_index = g_utf8_offset_to_pointer (entry_text, end_pos) - entry_text;
718       if (index >= cursor_index && entry->preedit_length)
719         {
720           if (index >= cursor_index + entry->preedit_length)
721             index -= entry->preedit_length;
722           else
723             index = cursor_index;
724         }
725       */
726       return g_utf8_pointer_to_offset (entry_text, entry_text + index);
727     }
728 }
729
730 static gint
731 gtk_entry_accessible_get_n_selections (AtkText              *text)
732 {
733   GtkEntry *entry;
734   GtkWidget *widget;
735   gint select_start, select_end;
736
737   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
738   if (widget == NULL)
739     /* State is defunct */
740     return -1;
741
742   entry = GTK_ENTRY (widget);
743
744   gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &select_start, 
745                                      &select_end);
746
747   if (select_start != select_end)
748     return 1;
749   else
750     return 0;
751 }
752
753 static gchar*
754 gtk_entry_accessible_get_selection (AtkText *text,
755                           gint    selection_num,
756                           gint    *start_pos,
757                           gint    *end_pos)
758 {
759   GtkEntry *entry;
760   GtkWidget *widget;
761
762   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
763   if (widget == NULL)
764     /* State is defunct */
765     return NULL;
766
767  /* Only let the user get the selection if one is set, and if the
768   * selection_num is 0.
769   */
770   if (selection_num != 0)
771      return NULL;
772
773   entry = GTK_ENTRY (widget);
774   gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), start_pos, end_pos);
775
776   if (*start_pos != *end_pos)
777      return gtk_editable_get_chars (GTK_EDITABLE (entry), *start_pos, *end_pos);
778   else
779      return NULL;
780 }
781
782 static gboolean
783 gtk_entry_accessible_add_selection (AtkText *text,
784                           gint    start_pos,
785                           gint    end_pos)
786 {
787   GtkEntry *entry;
788   GtkWidget *widget;
789   gint select_start, select_end;
790
791   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
792   if (widget == NULL)
793     /* State is defunct */
794     return FALSE;
795
796   entry = GTK_ENTRY (widget);
797
798   gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &select_start, 
799                                      &select_end);
800
801  /* If there is already a selection, then don't allow another to be added,
802   * since GtkEntry only supports one selected region.
803   */
804   if (select_start == select_end)
805     {
806        gtk_editable_select_region (GTK_EDITABLE (entry), start_pos, end_pos);
807        return TRUE;
808     }
809   else
810    return FALSE;
811 }
812
813 static gboolean
814 gtk_entry_accessible_remove_selection (AtkText *text,
815                              gint    selection_num)
816 {
817   GtkEntry *entry;
818   GtkWidget *widget;
819   gint select_start, select_end, caret_pos;
820
821   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
822   if (widget == NULL)
823     /* State is defunct */
824     return FALSE;
825
826   if (selection_num != 0)
827      return FALSE;
828
829   entry = GTK_ENTRY (widget);
830   gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &select_start, 
831                                      &select_end);
832
833   if (select_start != select_end)
834     {
835      /* Setting the start & end of the selected region to the caret position
836       * turns off the selection.
837       */
838       caret_pos = gtk_editable_get_position (GTK_EDITABLE (entry));
839       gtk_editable_select_region (GTK_EDITABLE (entry), caret_pos, caret_pos);
840       return TRUE;
841     }
842   else
843     return FALSE;
844 }
845
846 static gboolean
847 gtk_entry_accessible_set_selection (AtkText *text,
848                           gint    selection_num,
849                           gint    start_pos,
850                           gint    end_pos)
851 {
852   GtkEntry *entry;
853   GtkWidget *widget;
854   gint select_start, select_end;
855
856   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
857   if (widget == NULL)
858     /* State is defunct */
859     return FALSE;
860
861  /* Only let the user move the selection if one is set, and if the
862   * selection_num is 0
863   */
864   if (selection_num != 0)
865      return FALSE;
866
867   entry = GTK_ENTRY (widget);
868
869   gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &select_start, 
870                                      &select_end);
871
872   if (select_start != select_end)
873     {
874       gtk_editable_select_region (GTK_EDITABLE (entry), start_pos, end_pos);
875       return TRUE;
876     }
877   else
878     return FALSE;
879 }
880
881 static void
882 atk_editable_text_interface_init (AtkEditableTextIface *iface)
883 {
884   iface->set_text_contents = gtk_entry_accessible_set_text_contents;
885   iface->insert_text = gtk_entry_accessible_insert_text;
886   iface->copy_text = gtk_entry_accessible_copy_text;
887   iface->cut_text = gtk_entry_accessible_cut_text;
888   iface->delete_text = gtk_entry_accessible_delete_text;
889   iface->paste_text = gtk_entry_accessible_paste_text;
890   iface->set_run_attributes = NULL;
891 }
892
893 static void
894 gtk_entry_accessible_set_text_contents (AtkEditableText *text,
895                               const gchar     *string)
896 {
897   GtkEntry *entry;
898   GtkWidget *widget;
899   GtkEditable *editable;
900
901   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
902   if (widget == NULL)
903     /* State is defunct */
904     return;
905
906   entry = GTK_ENTRY (widget);
907   editable = GTK_EDITABLE (entry);
908   if (!gtk_editable_get_editable (editable))
909     return;
910
911   gtk_entry_set_text (entry, string);
912 }
913
914 static void
915 gtk_entry_accessible_insert_text (AtkEditableText *text,
916                         const gchar     *string,
917                         gint            length,
918                         gint            *position)
919 {
920   GtkEntry *entry;
921   GtkWidget *widget;
922   GtkEditable *editable;
923
924   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
925   if (widget == NULL)
926     /* State is defunct */
927     return;
928
929   entry = GTK_ENTRY (widget);
930   editable = GTK_EDITABLE (entry);
931   if (!gtk_editable_get_editable (editable))
932     return;
933
934   gtk_editable_insert_text (editable, string, length, position);
935   gtk_editable_set_position (editable, *position);
936 }
937
938 static void
939 gtk_entry_accessible_copy_text   (AtkEditableText *text,
940                         gint            start_pos,
941                         gint            end_pos)
942 {
943   GtkEntry *entry;
944   GtkWidget *widget;
945   GtkEditable *editable;
946   gchar *str;
947   GtkClipboard *clipboard;
948
949   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
950   if (widget == NULL)
951     /* State is defunct */
952     return;
953
954   entry = GTK_ENTRY (widget);
955   editable = GTK_EDITABLE (entry);
956   str = gtk_editable_get_chars (editable, start_pos, end_pos);
957   clipboard = gtk_clipboard_get_for_display (gtk_widget_get_display (widget),
958                                              GDK_SELECTION_CLIPBOARD);
959   gtk_clipboard_set_text (clipboard, str, -1);
960 }
961
962 static void
963 gtk_entry_accessible_cut_text (AtkEditableText *text,
964                      gint            start_pos,
965                      gint            end_pos)
966 {
967   GtkEntry *entry;
968   GtkWidget *widget;
969   GtkEditable *editable;
970   gchar *str;
971   GtkClipboard *clipboard;
972
973   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
974   if (widget == NULL)
975     /* State is defunct */
976     return;
977
978   entry = GTK_ENTRY (widget);
979   editable = GTK_EDITABLE (entry);
980   if (!gtk_editable_get_editable (editable))
981     return;
982   str = gtk_editable_get_chars (editable, start_pos, end_pos);
983   clipboard = gtk_clipboard_get_for_display (gtk_widget_get_display (widget),
984                                              GDK_SELECTION_CLIPBOARD);
985   gtk_clipboard_set_text (clipboard, str, -1);
986   gtk_editable_delete_text (editable, start_pos, end_pos);
987 }
988
989 static void
990 gtk_entry_accessible_delete_text (AtkEditableText *text,
991                         gint            start_pos,
992                         gint            end_pos)
993 {
994   GtkEntry *entry;
995   GtkWidget *widget;
996   GtkEditable *editable;
997
998   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
999   if (widget == NULL)
1000     /* State is defunct */
1001     return;
1002
1003   entry = GTK_ENTRY (widget);
1004   editable = GTK_EDITABLE (entry);
1005   if (!gtk_editable_get_editable (editable))
1006     return;
1007
1008   gtk_editable_delete_text (editable, start_pos, end_pos);
1009 }
1010
1011 static void
1012 gtk_entry_accessible_paste_text (AtkEditableText *text,
1013                        gint            position)
1014 {
1015   GtkWidget *widget;
1016   GtkEditable *editable;
1017   GtkEntryAccessiblePaste paste_struct;
1018   GtkClipboard *clipboard;
1019
1020   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
1021   if (widget == NULL)
1022     /* State is defunct */
1023     return;
1024
1025   editable = GTK_EDITABLE (widget);
1026   if (!gtk_editable_get_editable (editable))
1027     return;
1028   paste_struct.entry = GTK_ENTRY (widget);
1029   paste_struct.position = position;
1030
1031   g_object_ref (paste_struct.entry);
1032   clipboard = gtk_clipboard_get_for_display (gtk_widget_get_display (widget),
1033                                              GDK_SELECTION_CLIPBOARD);
1034   gtk_clipboard_request_text (clipboard,
1035     gtk_entry_accessible_paste_received, &paste_struct);
1036 }
1037
1038 static void
1039 gtk_entry_accessible_paste_received (GtkClipboard *clipboard,
1040                 const gchar  *text,
1041                 gpointer     data)
1042 {
1043   GtkEntryAccessiblePaste* paste_struct = (GtkEntryAccessiblePaste *)data;
1044
1045   if (text)
1046     gtk_editable_insert_text (GTK_EDITABLE (paste_struct->entry), text, -1,
1047        &(paste_struct->position));
1048
1049   g_object_unref (paste_struct->entry);
1050 }
1051
1052 /* Callbacks */
1053
1054 static gboolean
1055 gtk_entry_accessible_idle_notify_insert (gpointer data)
1056 {
1057   GtkEntryAccessible *entry;
1058
1059   entry = GTK_ENTRY_ACCESSIBLE (data);
1060   entry->insert_idle_handler = 0;
1061   gtk_entry_accessible_notify_insert (entry);
1062
1063   return FALSE;
1064 }
1065
1066 static void
1067 gtk_entry_accessible_notify_insert (GtkEntryAccessible *entry)
1068 {
1069   GtkWidget *widget;
1070
1071   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (entry));
1072   if (gtk_entry_get_text_length (GTK_ENTRY (widget)) == 0)
1073     return;
1074
1075   if (entry->signal_name_insert)
1076     {
1077       g_signal_emit_by_name (entry, 
1078                              entry->signal_name_insert,
1079                              entry->position_insert,
1080                              entry->length_insert);
1081       entry->signal_name_insert = NULL;
1082     }
1083 }
1084
1085 /* Note arg1 returns the character at the start of the insert.
1086  * arg2 returns the number of characters inserted.
1087  */
1088 static void 
1089 _gtk_entry_accessible_insert_text_cb (GtkEntry *entry, 
1090                             gchar    *arg1, 
1091                             gint     arg2,
1092                             gpointer arg3)
1093 {
1094   AtkObject *accessible;
1095   GtkEntryAccessible *entry_accessible;
1096   gint *position = (gint *) arg3;
1097
1098   if (arg2 == 0)
1099     return;
1100
1101   accessible = gtk_widget_get_accessible (GTK_WIDGET (entry));
1102   entry_accessible = GTK_ENTRY_ACCESSIBLE (accessible);
1103   if (!entry_accessible->signal_name_insert)
1104     {
1105       entry_accessible->signal_name_insert = "text_changed::insert";
1106       entry_accessible->position_insert = *position;
1107       entry_accessible->length_insert = g_utf8_strlen(arg1, arg2);
1108     }
1109   /*
1110    * The signal will be emitted when the cursor position is updated.
1111    * or in an idle handler if it not updated.
1112    */
1113    if (entry_accessible->insert_idle_handler == 0)
1114      entry_accessible->insert_idle_handler = gdk_threads_add_idle (gtk_entry_accessible_idle_notify_insert, entry_accessible);
1115 }
1116
1117 static gunichar 
1118 gtk_entry_accessible_get_character_at_offset (AtkText *text,
1119                                     gint     offset)
1120 {
1121   GtkWidget *widget;
1122   GtkEntryAccessible *entry;
1123   gchar *string;
1124   gchar *index;
1125   gunichar unichar;
1126
1127   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
1128   if (widget == NULL)
1129     /* State is defunct */
1130     return '\0';
1131
1132   entry = GTK_ENTRY_ACCESSIBLE (text);
1133   string = gail_text_util_get_substring (entry->textutil, 0, -1);
1134   if (offset >= g_utf8_strlen (string, -1))
1135     {
1136       unichar = '\0';
1137     }
1138   else
1139     {
1140       index = g_utf8_offset_to_pointer (string, offset);
1141
1142       unichar = g_utf8_get_char(index);
1143     }
1144
1145   g_free(string);
1146   return unichar;
1147 }
1148
1149 static void
1150 gtk_entry_accessible_notify_delete (GtkEntryAccessible *entry)
1151 {
1152   if (entry->signal_name_delete)
1153     {
1154       g_signal_emit_by_name (entry, 
1155                              entry->signal_name_delete,
1156                              entry->position_delete,
1157                              entry->length_delete);
1158       entry->signal_name_delete = NULL;
1159     }
1160 }
1161
1162 /* Note arg1 returns the start of the delete range, arg2 returns the
1163  * end of the delete range if multiple characters are deleted.  
1164  */
1165 static void 
1166 _gtk_entry_accessible_delete_text_cb (GtkEntry *entry, 
1167                             gint      arg1, 
1168                             gint      arg2)
1169 {
1170   AtkObject *accessible;
1171   GtkEntryAccessible *entry_accessible;
1172
1173   /*
1174    * Zero length text deleted so ignore
1175    */
1176   if (arg2 - arg1 == 0)
1177     return;
1178
1179   accessible = gtk_widget_get_accessible (GTK_WIDGET (entry));
1180   entry_accessible = GTK_ENTRY_ACCESSIBLE (accessible);
1181   if (!entry_accessible->signal_name_delete)
1182     {
1183       entry_accessible->signal_name_delete = "text_changed::delete";
1184       entry_accessible->position_delete = arg1;
1185       entry_accessible->length_delete = arg2 - arg1;
1186     }
1187   gtk_entry_accessible_notify_delete (entry_accessible);
1188 }
1189
1190 static void
1191 _gtk_entry_accessible_changed_cb (GtkEntry *entry)
1192 {
1193   AtkObject *accessible;
1194   GtkEntryAccessible *gtk_entry_accessible;
1195
1196   accessible = gtk_widget_get_accessible (GTK_WIDGET (entry));
1197
1198   gtk_entry_accessible = GTK_ENTRY_ACCESSIBLE (accessible);
1199
1200   text_setup (gtk_entry_accessible, entry);
1201 }
1202
1203 static gboolean 
1204 check_for_selection_change (GtkEntryAccessible   *entry,
1205                             GtkEntry    *gtk_entry)
1206 {
1207   gboolean selected, ret_val = FALSE;
1208   gint start_pos, end_pos;
1209
1210   selected = gtk_editable_get_selection_bounds (GTK_EDITABLE (gtk_entry),
1211                                                 &start_pos, &end_pos);
1212   if (selected)
1213     {
1214       if (end_pos != entry->cursor_position ||
1215           start_pos != entry->selection_bound)
1216         /*
1217          * This check is here as this function can be called
1218          * for notification of selection_bound and current_pos.
1219          * The values of current_pos and selection_bound may be the same 
1220          * for both notifications and we only want to generate one
1221          * text_selection_changed signal.
1222          */
1223         ret_val = TRUE;
1224     }
1225   else 
1226     {
1227       /* We had a selection */
1228       ret_val = (entry->cursor_position != entry->selection_bound);
1229     }
1230   entry->cursor_position = end_pos;
1231   entry->selection_bound = start_pos;
1232
1233   return ret_val;
1234 }
1235
1236 static void
1237 atk_action_interface_init (AtkActionIface *iface)
1238 {
1239   iface->do_action = gtk_entry_accessible_do_action;
1240   iface->get_n_actions = gtk_entry_accessible_get_n_actions;
1241   iface->get_keybinding = gtk_entry_accessible_get_keybinding;
1242   iface->get_name = gtk_entry_accessible_action_get_name;
1243 }
1244
1245 static gboolean
1246 gtk_entry_accessible_do_action (AtkAction *action,
1247                       gint      i)
1248 {
1249   GtkEntryAccessible *entry;
1250   GtkWidget *widget;
1251   gboolean return_value = TRUE;
1252
1253   entry = GTK_ENTRY_ACCESSIBLE (action);
1254   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (action));
1255   if (widget == NULL)
1256     /*
1257      * State is defunct
1258      */
1259     return FALSE;
1260
1261   if (!gtk_widget_get_sensitive (widget) || !gtk_widget_get_visible (widget))
1262     return FALSE;
1263
1264   switch (i)
1265     {
1266     case 0:
1267       if (entry->action_idle_handler)
1268         return_value = FALSE;
1269       else
1270         entry->action_idle_handler = gdk_threads_add_idle (idle_do_action, entry);
1271       break;
1272     default:
1273       return_value = FALSE;
1274       break;
1275     }
1276   return return_value; 
1277 }
1278
1279 static gboolean
1280 idle_do_action (gpointer data)
1281 {
1282   GtkEntryAccessible *entry;
1283   GtkWidget *widget;
1284
1285   entry = GTK_ENTRY_ACCESSIBLE (data);
1286   entry->action_idle_handler = 0;
1287   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (entry));
1288   if (widget == NULL /* State is defunct */ ||
1289       !gtk_widget_get_sensitive (widget) || !gtk_widget_get_visible (widget))
1290     return FALSE;
1291
1292   gtk_widget_activate (widget);
1293
1294   return FALSE;
1295 }
1296
1297 static gint
1298 gtk_entry_accessible_get_n_actions (AtkAction *action)
1299 {
1300   return 1;
1301 }
1302
1303 static const gchar*
1304 gtk_entry_accessible_get_keybinding (AtkAction *action,
1305                            gint      i)
1306 {
1307   GtkEntryAccessible *entry;
1308   gchar *return_value = NULL;
1309
1310   entry = GTK_ENTRY_ACCESSIBLE (action);
1311   switch (i)
1312     {
1313     case 0:
1314       {
1315         /*
1316          * We look for a mnemonic on the label
1317          */
1318         GtkWidget *widget;
1319         GtkWidget *label;
1320         AtkRelationSet *set;
1321         AtkRelation *relation;
1322         GPtrArray *target;
1323         gpointer target_object;
1324         guint key_val; 
1325
1326         entry = GTK_ENTRY_ACCESSIBLE (action);
1327         widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (entry));
1328         if (widget == NULL)
1329           /*
1330            * State is defunct
1331            */
1332           return NULL;
1333
1334         /* Find labelled-by relation */
1335
1336         set = atk_object_ref_relation_set (ATK_OBJECT (action));
1337         if (!set)
1338           return NULL;
1339         label = NULL;
1340         relation = atk_relation_set_get_relation_by_type (set, ATK_RELATION_LABELLED_BY);
1341         if (relation)
1342           {              
1343             target = atk_relation_get_target (relation);
1344           
1345             target_object = g_ptr_array_index (target, 0);
1346             label = gtk_accessible_get_widget (GTK_ACCESSIBLE (target_object));
1347           }
1348
1349         g_object_unref (set);
1350
1351         if (GTK_IS_LABEL (label))
1352           {
1353             key_val = gtk_label_get_mnemonic_keyval (GTK_LABEL (label)); 
1354             if (key_val != GDK_KEY_VoidSymbol)
1355               return_value = gtk_accelerator_name (key_val, GDK_MOD1_MASK);
1356           }
1357         g_free (entry->activate_keybinding);
1358         entry->activate_keybinding = return_value;
1359         break;
1360       }
1361     default:
1362       break;
1363     }
1364   return return_value; 
1365 }
1366
1367 static const gchar*
1368 gtk_entry_accessible_action_get_name (AtkAction *action,
1369                             gint      i)
1370 {
1371   const gchar *return_value;
1372
1373   switch (i)
1374     {
1375     case 0:
1376       return_value = "activate";
1377       break;
1378     default:
1379       return_value = NULL;
1380       break;
1381   }
1382   return return_value; 
1383 }