New IDL API, extensions to basic at-spi interfaces.
[platform/core/uifw/at-spi2-atk.git] / libspi / accessible.c
1 /*
2  * AT-SPI - Assistive Technology Service Provider Interface
3  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4  *
5  * Copyright 2001, 2002 Sun Microsystems Inc.,
6  * Copyright 2001, 2002 Ximian, Inc.
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
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 /* accessible.c: the core of the accessibility implementation */
25
26 #include <config.h>
27 #include <stdio.h>
28 #include <bonobo/bonobo-exception.h>
29 #include <atk/atk.h>
30 #include <libspi/libspi.h>
31 #include "spi-private.h"
32
33 /* Our parent Gtk object type  */
34 #define PARENT_TYPE SPI_TYPE_BASE
35
36 static gboolean spi_init_role_lookup_table (Accessibility_Role *role_table);
37 Accessibility_Role spi_accessible_role_from_atk_role (AtkRole role);
38
39 static gboolean
40 spi_init_role_lookup_table (Accessibility_Role *role_table)
41 {
42   int i;
43   /* if it's not in the list below, dunno what it is */
44   for (i = 0; i < ATK_ROLE_LAST_DEFINED; ++i)
45     {
46       role_table [i] = Accessibility_ROLE_UNKNOWN;
47     }
48   
49   role_table [ATK_ROLE_INVALID] =             Accessibility_ROLE_INVALID;
50   role_table [ATK_ROLE_ACCEL_LABEL] =         Accessibility_ROLE_ACCELERATOR_LABEL;
51   role_table [ATK_ROLE_ALERT] =               Accessibility_ROLE_ALERT;
52   role_table [ATK_ROLE_ANIMATION] =           Accessibility_ROLE_ANIMATION; 
53   role_table [ATK_ROLE_ARROW] =               Accessibility_ROLE_ARROW; 
54   role_table [ATK_ROLE_CALENDAR] =            Accessibility_ROLE_CALENDAR; 
55   role_table [ATK_ROLE_CANVAS] =              Accessibility_ROLE_CANVAS;
56   role_table [ATK_ROLE_CHECK_BOX] =           Accessibility_ROLE_CHECK_BOX;
57   role_table [ATK_ROLE_CHECK_MENU_ITEM] =     Accessibility_ROLE_CHECK_MENU_ITEM;
58   role_table [ATK_ROLE_COLOR_CHOOSER] =       Accessibility_ROLE_COLOR_CHOOSER;
59   role_table [ATK_ROLE_COLUMN_HEADER] =       Accessibility_ROLE_COLUMN_HEADER;
60   role_table [ATK_ROLE_COMBO_BOX] =           Accessibility_ROLE_COMBO_BOX;
61   role_table [ATK_ROLE_DATE_EDITOR] =         Accessibility_ROLE_DATE_EDITOR;
62   role_table [ATK_ROLE_DESKTOP_ICON] =        Accessibility_ROLE_DESKTOP_ICON;
63   role_table [ATK_ROLE_DESKTOP_FRAME] =       Accessibility_ROLE_DESKTOP_FRAME;
64   role_table [ATK_ROLE_DIAL] =                Accessibility_ROLE_DIAL;
65   role_table [ATK_ROLE_DIALOG] =              Accessibility_ROLE_DIALOG;
66   role_table [ATK_ROLE_DIRECTORY_PANE] =      Accessibility_ROLE_DIRECTORY_PANE;
67   role_table [ATK_ROLE_DRAWING_AREA] =        Accessibility_ROLE_DRAWING_AREA;
68   role_table [ATK_ROLE_FILE_CHOOSER] =        Accessibility_ROLE_FILE_CHOOSER;
69   role_table [ATK_ROLE_FILLER] =              Accessibility_ROLE_FILLER;
70   role_table [ATK_ROLE_FONT_CHOOSER] =        Accessibility_ROLE_FONT_CHOOSER;
71   role_table [ATK_ROLE_FRAME] =               Accessibility_ROLE_FRAME;
72   role_table [ATK_ROLE_GLASS_PANE] =          Accessibility_ROLE_GLASS_PANE;
73   role_table [ATK_ROLE_HTML_CONTAINER] =      Accessibility_ROLE_HTML_CONTAINER;
74   role_table [ATK_ROLE_ICON] =                Accessibility_ROLE_ICON;
75   role_table [ATK_ROLE_IMAGE] =               Accessibility_ROLE_IMAGE; 
76   role_table [ATK_ROLE_INTERNAL_FRAME] =      Accessibility_ROLE_INTERNAL_FRAME; 
77   role_table [ATK_ROLE_LABEL] =               Accessibility_ROLE_LABEL;
78   role_table [ATK_ROLE_LAYERED_PANE] =        Accessibility_ROLE_LAYERED_PANE;
79   role_table [ATK_ROLE_LIST] =                Accessibility_ROLE_LIST;
80   role_table [ATK_ROLE_LIST_ITEM] =           Accessibility_ROLE_LIST_ITEM;
81   role_table [ATK_ROLE_MENU] =                Accessibility_ROLE_MENU;
82   role_table [ATK_ROLE_MENU_BAR] =            Accessibility_ROLE_MENU_BAR;
83   role_table [ATK_ROLE_MENU_ITEM] =           Accessibility_ROLE_MENU_ITEM;
84   role_table [ATK_ROLE_OPTION_PANE] =         Accessibility_ROLE_OPTION_PANE;
85   role_table [ATK_ROLE_PAGE_TAB] =            Accessibility_ROLE_PAGE_TAB;
86   role_table [ATK_ROLE_PAGE_TAB_LIST] =       Accessibility_ROLE_PAGE_TAB_LIST; 
87   role_table [ATK_ROLE_PANEL] =               Accessibility_ROLE_PANEL;
88   role_table [ATK_ROLE_PASSWORD_TEXT] =       Accessibility_ROLE_PASSWORD_TEXT;
89   role_table [ATK_ROLE_POPUP_MENU] =          Accessibility_ROLE_POPUP_MENU;
90   role_table [ATK_ROLE_PROGRESS_BAR] =        Accessibility_ROLE_PROGRESS_BAR;
91   role_table [ATK_ROLE_PUSH_BUTTON] =         Accessibility_ROLE_PUSH_BUTTON;
92   role_table [ATK_ROLE_RADIO_BUTTON] =        Accessibility_ROLE_RADIO_BUTTON;
93   role_table [ATK_ROLE_RADIO_MENU_ITEM] =     Accessibility_ROLE_RADIO_MENU_ITEM;
94   role_table [ATK_ROLE_ROOT_PANE] =           Accessibility_ROLE_ROOT_PANE;
95   role_table [ATK_ROLE_ROW_HEADER] =          Accessibility_ROLE_ROW_HEADER;
96   role_table [ATK_ROLE_SCROLL_BAR] =          Accessibility_ROLE_SCROLL_BAR;
97   role_table [ATK_ROLE_SCROLL_PANE] =         Accessibility_ROLE_SCROLL_PANE;
98   role_table [ATK_ROLE_SEPARATOR] =           Accessibility_ROLE_SEPARATOR;
99   role_table [ATK_ROLE_SLIDER] =              Accessibility_ROLE_SLIDER;
100   role_table [ATK_ROLE_SPIN_BUTTON] =         Accessibility_ROLE_SPIN_BUTTON;
101   role_table [ATK_ROLE_SPLIT_PANE] =          Accessibility_ROLE_SPLIT_PANE;
102   role_table [ATK_ROLE_STATUSBAR] =           Accessibility_ROLE_STATUS_BAR;
103   role_table [ATK_ROLE_TABLE] =               Accessibility_ROLE_TABLE;
104   role_table [ATK_ROLE_TABLE_CELL] =          Accessibility_ROLE_TABLE_CELL;
105   role_table [ATK_ROLE_TABLE_COLUMN_HEADER] = Accessibility_ROLE_TABLE_COLUMN_HEADER;
106   role_table [ATK_ROLE_TABLE_ROW_HEADER] =    Accessibility_ROLE_TABLE_ROW_HEADER;
107   role_table [ATK_ROLE_TEAR_OFF_MENU_ITEM] =  Accessibility_ROLE_TEAROFF_MENU_ITEM;
108   role_table [ATK_ROLE_TERMINAL] =            Accessibility_ROLE_TERMINAL;
109   role_table [ATK_ROLE_TEXT] =                Accessibility_ROLE_TEXT;
110   role_table [ATK_ROLE_TOGGLE_BUTTON] =       Accessibility_ROLE_TOGGLE_BUTTON;
111   role_table [ATK_ROLE_TOOL_BAR] =            Accessibility_ROLE_TOOL_BAR;
112   role_table [ATK_ROLE_TOOL_TIP] =            Accessibility_ROLE_TOOL_TIP;
113   role_table [ATK_ROLE_TREE] =                Accessibility_ROLE_TREE;
114   role_table [ATK_ROLE_TREE_TABLE] =          Accessibility_ROLE_TREE_TABLE;
115   role_table [ATK_ROLE_UNKNOWN] =             Accessibility_ROLE_UNKNOWN;
116   role_table [ATK_ROLE_VIEWPORT] =            Accessibility_ROLE_VIEWPORT;
117   role_table [ATK_ROLE_WINDOW] =              Accessibility_ROLE_WINDOW;
118   role_table [ATK_ROLE_HEADER] =              Accessibility_ROLE_HEADER;
119   role_table [ATK_ROLE_FOOTER] =              Accessibility_ROLE_FOOTER;
120   role_table [ATK_ROLE_PARAGRAPH] =           Accessibility_ROLE_PARAGRAPH;
121   role_table [ATK_ROLE_RULER] =               Accessibility_ROLE_RULER;
122   role_table [ATK_ROLE_APPLICATION] =         Accessibility_ROLE_APPLICATION;
123   role_table [ATK_ROLE_AUTOCOMPLETE] =        Accessibility_ROLE_AUTOCOMPLETE;
124   role_table [ATK_ROLE_EDITBAR] =             Accessibility_ROLE_EDITBAR;
125   role_table [ATK_ROLE_EMBEDDED] =            Accessibility_ROLE_EMBEDDED;
126   role_table [ATK_ROLE_ENTRY] =               Accessibility_ROLE_ENTRY;
127   role_table [ATK_ROLE_CHART] =               Accessibility_ROLE_CHART;
128   role_table [ATK_ROLE_CAPTION] =             Accessibility_ROLE_CAPTION;
129   role_table [ATK_ROLE_DOCUMENT_FRAME] =      Accessibility_ROLE_DOCUMENT_FRAME;
130   role_table [ATK_ROLE_HEADING] =             Accessibility_ROLE_HEADING;
131   role_table [ATK_ROLE_PAGE] =                Accessibility_ROLE_PAGE;
132   role_table [ATK_ROLE_SECTION] =             Accessibility_ROLE_SECTION;
133   return TRUE;
134 }
135
136 Accessibility_Role
137 spi_accessible_role_from_atk_role (AtkRole role)
138 {
139   static gboolean is_initialized = FALSE;
140   static Accessibility_Role spi_role_table [ATK_ROLE_LAST_DEFINED];
141   Accessibility_Role spi_role;
142
143   if (!is_initialized)
144    {
145      is_initialized = spi_init_role_lookup_table (spi_role_table);         
146    }
147
148   if (role >= 0 && role < ATK_ROLE_LAST_DEFINED)
149     {
150       spi_role = spi_role_table [role];
151     }
152   else
153     {
154       spi_role = Accessibility_ROLE_EXTENDED;       
155     }
156   return spi_role;
157 }
158
159 static AtkObject *
160 get_atkobject_from_servant (PortableServer_Servant servant)
161 {
162   SpiBase *object = SPI_BASE (bonobo_object_from_servant (servant));
163
164   g_return_val_if_fail (object, NULL);
165   g_return_val_if_fail (ATK_IS_OBJECT(object->gobj), NULL);
166   return ATK_OBJECT(object->gobj);
167 }
168
169 /*
170  * CORBA Accessibility::Accessible::get_name method implementation
171  */
172 static CORBA_char *
173 impl_accessibility_accessible_get_name (PortableServer_Servant servant,
174                                         CORBA_Environment     *ev)
175 {
176   const gchar *name;
177   CORBA_char  *retval;
178   AtkObject   *object = get_atkobject_from_servant (servant);
179
180   g_return_val_if_fail (object != NULL, CORBA_string_dup (""));
181
182   name = atk_object_get_name (object);
183
184   if (name)
185     {
186       retval = CORBA_string_dup (name);
187     }
188   else
189     {
190       retval = CORBA_string_dup ("");
191     }
192
193   return retval;
194 }
195
196 /*
197  * CORBA Accessibility::Accessible::set_name method implementation
198  */
199 static void
200 impl_accessibility_accessible_set_name (PortableServer_Servant servant,
201                                         const CORBA_char      *name,
202                                         CORBA_Environment     *ev)
203 {
204   AtkObject *object = get_atkobject_from_servant (servant);
205
206   g_return_if_fail (object != NULL);
207
208   atk_object_set_name (object, name);
209 }
210
211 /*
212  * CORBA Accessibility::Accessible::get_description method implementation
213  */
214 static CORBA_char *
215 impl_accessibility_accessible_get_description (PortableServer_Servant servant,
216                                                CORBA_Environment     *ev)
217 {
218   const gchar *descr;
219   CORBA_char  *retval;
220   AtkObject   *object = get_atkobject_from_servant (servant);
221
222   g_return_val_if_fail (object != NULL, CORBA_string_dup (""));
223
224   descr = atk_object_get_description (object);
225
226   if (descr)
227     {
228       retval = CORBA_string_dup (descr);
229     }
230   else
231     {
232       retval = CORBA_string_dup ("");
233     }
234
235   return retval;
236 }
237
238 /*
239  * CORBA Accessibility::Accessible::set_description method implementation
240  */
241 static void
242 impl_accessibility_accessible_set_description (PortableServer_Servant servant,
243                                                const CORBA_char      *descr,
244                                                CORBA_Environment     *ev)
245 {
246   AtkObject *object = get_atkobject_from_servant (servant);
247
248   g_return_if_fail (object != NULL);
249
250   atk_object_set_description (object, descr);
251 }
252
253 /*
254  * CORBA Accessibility::Accessible::get_parent method implementation
255  */
256 static Accessibility_Accessible
257 impl_accessibility_accessible_get_parent (PortableServer_Servant servant,
258                                           CORBA_Environment     *ev)
259 {
260   AtkObject *parent;
261   AtkObject *object = get_atkobject_from_servant (servant);
262
263   g_return_val_if_fail (object != NULL, CORBA_OBJECT_NIL);
264
265   parent = atk_object_get_parent (object);
266
267   return spi_accessible_new_return (parent, FALSE, ev);
268 }
269
270 /*
271  * CORBA Accessibility::Accessible::get_IndexInParent method implementation
272  */
273 static CORBA_long
274 impl_accessibility_accessible_get_index_in_parent (PortableServer_Servant servant,
275                                                    CORBA_Environment     *ev)
276 {
277   AtkObject *object = get_atkobject_from_servant (servant);
278
279   g_return_val_if_fail (object != NULL, -1);
280
281   return atk_object_get_index_in_parent (object);
282 }
283
284 /*
285  * CORBA Accessibility::Accessible::get_childCount method implementation
286  */
287 static CORBA_long
288 impl_accessibility_accessible_get_child_count (PortableServer_Servant servant,
289                                                CORBA_Environment     *ev)
290 {
291   AtkObject *object = get_atkobject_from_servant (servant);
292
293   g_return_val_if_fail (object != NULL, 0);
294
295   return atk_object_get_n_accessible_children (object);
296 }
297
298 /*
299  * CORBA Accessibility::Accessible::getChildAtIndex method implementation
300  */
301 static Accessibility_Accessible
302 impl_accessibility_accessible_get_child_at_index (PortableServer_Servant servant,
303                                                   const CORBA_long      index,
304                                                   CORBA_Environment     *ev)
305 {
306   AtkObject *child;
307   AtkObject *object = get_atkobject_from_servant (servant);
308
309   g_return_val_if_fail (object != NULL, CORBA_OBJECT_NIL);
310
311   child = atk_object_ref_accessible_child (object, index);
312
313   return spi_accessible_new_return (child, TRUE, ev);
314 }
315
316 /*
317  * CORBA Accessibility::Accessible::getState method implementation
318  */
319 static Accessibility_StateSet
320 impl_accessibility_accessible_get_state (PortableServer_Servant servant,
321                                          CORBA_Environment     *ev)
322 {
323   AtkObject *object = get_atkobject_from_servant (servant);
324   AtkStateSet *atk_set;
325   SpiStateSet *set;
326   Accessibility_StateSet retval;
327
328   bonobo_return_val_if_fail (object != NULL, NULL, ev);
329
330   atk_set = atk_object_ref_state_set (object);
331   
332   set = spi_state_set_new (atk_set);
333   retval = bonobo_object_dup_ref (
334                                   BONOBO_OBJREF(set),
335                                   ev);
336
337   return retval;
338 }
339
340 /*
341  * CORBA Accessibility::Accessible::getRelationSet method implementation
342  */
343 static Accessibility_RelationSet *
344 impl_accessibility_accessible_get_relation_set (PortableServer_Servant servant,
345                                                 CORBA_Environment     *ev)
346 {
347   Accessibility_RelationSet *retval;
348   gint n_relations;
349   gint i;
350   AtkRelationSet *relation_set;
351   AtkObject      *object = get_atkobject_from_servant (servant);
352
353   bonobo_return_val_if_fail (object != NULL, NULL, ev);
354
355   relation_set = atk_object_ref_relation_set (object);
356
357   n_relations = atk_relation_set_get_n_relations (relation_set);
358
359   retval = CORBA_sequence_Accessibility_Relation__alloc ();
360   retval->_length = retval->_maximum = n_relations;
361   retval->_buffer = CORBA_sequence_Accessibility_Relation_allocbuf (n_relations);
362   CORBA_sequence_set_release (retval, CORBA_TRUE);
363           
364   for (i = 0; i < n_relations; ++i)
365     {
366       retval->_buffer[i] =
367         bonobo_object_dup_ref (
368           BONOBO_OBJREF (
369             spi_relation_new (atk_relation_set_get_relation (relation_set, i))),
370           ev);
371     }
372   
373   return retval;
374 }
375
376 /*
377  * CORBA Accessibility::Accessible::getRole method implementation
378  */
379 static Accessibility_Role
380 impl_accessibility_accessible_get_role (PortableServer_Servant servant,
381                                         CORBA_Environment     *ev)
382 {
383   AtkRole            role;
384   Accessibility_Role retval;
385   AtkObject         *object = get_atkobject_from_servant (servant);
386
387   g_return_val_if_fail (object != NULL, 0);
388
389   role = atk_object_get_role (object);
390   retval = spi_role_from_atk_role (role);
391
392   return retval;
393 }
394
395 /*
396  * CORBA Accessibility::Accessible::getRole method implementation
397  */
398 static CORBA_char *
399 impl_accessibility_accessible_get_role_name (PortableServer_Servant servant,
400                                              CORBA_Environment     *ev)
401 {
402   const gchar     *role_name;
403   AtkRole    role;
404   AtkObject *object = get_atkobject_from_servant (servant);
405
406   g_return_val_if_fail (object != NULL, NULL);
407
408   role = atk_object_get_role (object);
409
410   role_name = atk_role_get_name (role);
411   if (role_name)
412     return CORBA_string_dup (role_name);
413   else
414     return CORBA_string_dup ("");
415 }
416
417 /*
418  * CORBA Accessibility::Accessible::getLocalizedRole method implementation
419  */
420 static CORBA_char *
421 impl_accessibility_accessible_get_local_role_name (PortableServer_Servant servant,
422                                                    CORBA_Environment     *ev)
423 {
424   const gchar     *role_name;
425   AtkRole    role;
426   AtkObject *object = get_atkobject_from_servant (servant);
427
428   g_return_val_if_fail (object != NULL, NULL);
429
430   role = atk_object_get_role (object);
431
432   role_name = atk_role_get_localized_name (role);
433   if (role_name)
434     return CORBA_string_dup (role_name);
435   else
436     return CORBA_string_dup ("");
437 }
438
439 static Accessibility_Accessible 
440 impl_accessibility_accessible_get_application (PortableServer_Servant servant,
441                                                CORBA_Environment     *ev)
442 {
443     return spi_accessible_new_return (atk_get_root (), FALSE, ev);
444 }
445
446 static Accessibility_AttributeSet* 
447 impl_accessibility_accessible_get_attributes (PortableServer_Servant servant,
448                                                CORBA_Environment     *ev)
449 {
450     Accessibility_AttributeSet *retval;
451     GSList *attributes;
452     gint n_attributes = 0;
453     gint i;
454     
455     AtkObject *object = get_atkobject_from_servant (servant);
456     
457     g_return_val_if_fail (object != NULL, NULL);
458     attributes = atk_object_get_attributes (object);
459     
460     bonobo_return_val_if_fail (attributes != NULL, NULL, ev);
461     n_attributes = g_slist_length (attributes);
462     
463     retval = CORBA_sequence_CORBA_string__alloc ();
464     retval->_length = retval->_maximum = n_attributes;
465     retval->_buffer = CORBA_sequence_CORBA_string_allocbuf (n_attributes);
466     CORBA_sequence_set_release (retval, CORBA_TRUE);
467     
468     for (i = 0; i < n_attributes; ++i)
469     {
470         retval->_buffer[i] = CORBA_string_dup (g_slist_nth_data (attributes, i));
471     }
472     
473   return retval;
474 }
475
476 static void
477 spi_accessible_class_init (SpiAccessibleClass *klass)
478 {
479         POA_Accessibility_Accessible__epv *epv = &klass->epv;
480
481         epv->_get_name = impl_accessibility_accessible_get_name;
482         epv->_set_name = impl_accessibility_accessible_set_name;
483         epv->_get_description = impl_accessibility_accessible_get_description;
484         epv->_set_description = impl_accessibility_accessible_set_description;
485
486         epv->_get_parent = impl_accessibility_accessible_get_parent;
487         epv->_get_childCount = impl_accessibility_accessible_get_child_count;
488         epv->getChildAtIndex = impl_accessibility_accessible_get_child_at_index;
489         epv->getIndexInParent = impl_accessibility_accessible_get_index_in_parent;
490
491         epv->getRelationSet = impl_accessibility_accessible_get_relation_set;
492         epv->getState = impl_accessibility_accessible_get_state;
493         epv->getRole = impl_accessibility_accessible_get_role;
494         epv->getRoleName = impl_accessibility_accessible_get_role_name;
495         epv->getLocalizedRoleName = impl_accessibility_accessible_get_local_role_name;
496         epv->getApplication = impl_accessibility_accessible_get_application;
497         epv->getAttributes = impl_accessibility_accessible_get_attributes;
498 }
499
500 static void
501 spi_accessible_init (SpiAccessible *accessible)
502 {
503 }
504
505 BONOBO_TYPE_FUNC_FULL (SpiAccessible,
506                        Accessibility_Accessible,
507                        PARENT_TYPE,
508                        spi_accessible)
509
510 static GHashTable *public_corba_refs = NULL;
511
512 static GHashTable *
513 get_public_refs (void)
514 {
515   if (!public_corba_refs)
516     {
517       public_corba_refs = g_hash_table_new (NULL, NULL);
518     }
519   return public_corba_refs;
520 }
521
522 static void
523 de_register_public_ref (SpiBase *object)
524 {
525   g_hash_table_remove (get_public_refs (), object->gobj);
526 }
527
528 SpiAccessible *
529 spi_accessible_new (AtkObject *o)
530 {
531   return spi_accessible_construct (SPI_ACCESSIBLE_TYPE, o);       
532 }
533
534 SpiAccessible *
535 spi_accessible_construct (GType type, AtkObject *o)
536 {
537     SpiAccessible *retval;
538     CORBA_Environment ev;
539
540     CORBA_exception_init (&ev);
541
542     g_assert (o);
543     g_assert (g_type_is_a (type, SPI_ACCESSIBLE_TYPE));
544
545     if ((retval = g_hash_table_lookup (get_public_refs (), o)))
546       {
547         bonobo_object_ref (BONOBO_OBJECT (retval));
548         return retval;
549       }
550     else
551       {
552         retval = g_object_new (type, NULL);
553         spi_base_construct (SPI_BASE (retval), G_OBJECT(o));
554       }
555     
556     g_hash_table_insert (get_public_refs (), o, retval);
557     g_signal_connect (G_OBJECT (retval), "destroy",
558                       G_CALLBACK (de_register_public_ref),
559                       NULL);
560
561     /* aggregate appropriate SPI interfaces based on ATK interfaces */
562  
563     if (ATK_IS_ACTION (o))
564       {
565         bonobo_object_add_interface (bonobo_object (retval),
566                 BONOBO_OBJECT (spi_action_interface_new (o)));
567       }
568
569     if (ATK_IS_COMPONENT (o))
570       {
571         bonobo_object_add_interface (bonobo_object (retval),
572                                      BONOBO_OBJECT (spi_component_interface_new (o)));
573       }
574
575     if (ATK_IS_EDITABLE_TEXT (o))
576       {
577          bonobo_object_add_interface (bonobo_object (retval),
578                                       BONOBO_OBJECT(spi_editable_text_interface_new (o)));
579       }
580
581     else if (ATK_IS_TEXT (o))
582        {
583          bonobo_object_add_interface (bonobo_object (retval),
584                                       BONOBO_OBJECT (spi_text_interface_new (o)));
585        }
586
587     if (ATK_IS_HYPERTEXT (o))
588       {
589         bonobo_object_add_interface (bonobo_object (retval),
590                                      BONOBO_OBJECT (spi_hypertext_interface_new (o)));
591       }
592
593     if (ATK_IS_IMAGE (o))
594       {
595         bonobo_object_add_interface (bonobo_object (retval),
596                                      BONOBO_OBJECT (spi_image_interface_new (o)));
597       }
598
599     if (ATK_IS_SELECTION (o))
600       {
601         bonobo_object_add_interface (bonobo_object (retval),
602                                      BONOBO_OBJECT (spi_selection_interface_new (o)));
603       }
604
605     if (ATK_IS_TABLE (o))
606       {
607         bonobo_object_add_interface (bonobo_object (retval),
608                                      BONOBO_OBJECT (spi_table_interface_new (o)));
609       }
610
611     if (ATK_IS_VALUE (o))
612       {
613         bonobo_object_add_interface (bonobo_object (retval),
614                                      BONOBO_OBJECT (spi_value_interface_new (o)));
615       }
616
617     return retval;
618 }
619
620 /**
621  * spi_accessible_new_return:
622  * @o: an AtkObject or NULL
623  * @release_ref: whether to unref this AtkObject before return
624  * @ev: a CORBA environment
625  * 
626  * A helper function to instantiate a CORBA accessiblility
627  * proxy from an AtkObject.
628  * 
629  * Return value: the proxy or CORBA_OBJECT_NIL
630  **/
631 Accessibility_Accessible
632 spi_accessible_new_return (AtkObject         *o,
633                            gboolean           release_ref,
634                            CORBA_Environment *ev)
635 {
636   SpiAccessible *accessible;
637   Accessibility_Accessible retval;
638
639   if (!o)
640     {
641       return CORBA_OBJECT_NIL;
642     }
643   else if (SPI_IS_REMOTE_OBJECT (o))
644     {
645       retval = spi_remote_object_get_accessible (SPI_REMOTE_OBJECT (o));
646     }
647   else
648     {
649       accessible = spi_accessible_construct (SPI_ACCESSIBLE_TYPE, o);
650       retval = CORBA_Object_duplicate (BONOBO_OBJREF (accessible), ev); 
651     }
652
653   if (release_ref)
654     {
655       g_object_unref (G_OBJECT (o));
656     }
657   
658   return retval;
659 }