Initial cspi commit
authorMike Gorse <mgorse@boston.site>
Mon, 23 Jun 2008 22:20:04 +0000 (18:20 -0400)
committerMike Gorse <mgorse@boston.site>
Mon, 23 Jun 2008 22:20:04 +0000 (18:20 -0400)
23 files changed:
Makefile.am
configure.ac
cspi/Makefile.am [new file with mode: 0644]
cspi/spi-impl.h [new file with mode: 0644]
cspi/spi-listener.h [new file with mode: 0644]
cspi/spi-private.h [new file with mode: 0644]
cspi/spi.h [new file with mode: 0644]
cspi/spi_accessible.c [new file with mode: 0644]
cspi/spi_action.c [new file with mode: 0644]
cspi/spi_component.c [new file with mode: 0644]
cspi/spi_editabletext.c [new file with mode: 0644]
cspi/spi_event.c [new file with mode: 0644]
cspi/spi_hyperlink.c [new file with mode: 0644]
cspi/spi_hypertext.c [new file with mode: 0644]
cspi/spi_listener.c [new file with mode: 0644]
cspi/spi_main.c [new file with mode: 0644]
cspi/spi_registry.c [new file with mode: 0644]
cspi/spi_selection.c [new file with mode: 0644]
cspi/spi_streamablecontent.c [new file with mode: 0644]
cspi/spi_table.c [new file with mode: 0644]
cspi/spi_text.c [new file with mode: 0644]
cspi/spi_value.c [new file with mode: 0644]
tests/clients/Makefile.am

index d92ac75..0ac4523 100644 (file)
@@ -1 +1 @@
-SUBDIRS=xml idl tests tools droute spi-common atk-adaptor registryd
+SUBDIRS=xml idl tools droute spi-common atk-adaptor registryd dbind cspi tests
index 72f533c..15a9fec 100644 (file)
@@ -1,5 +1,30 @@
 
 AC_INIT([at-spi], [1.9.0], [accessibility-atspi@lists.linux-foundation.org])
+
+AT_SPI_MAJOR_VERSION=1
+AT_SPI_MINOR_VERSION=23
+AT_SPI_MICRO_VERSION=3
+AT_SPI_INTERFACE_AGE=0
+AT_SPI_BINARY_AGE=0
+AT_SPI_VERSION="$AT_SPI_MAJOR_VERSION.$AT_SPI_MINOR_VERSION.$AT_SPI_MICRO_VERSION"
+AC_SUBST(AT_SPI_MAJOR_VERSION)
+AC_SUBST(AT_SPI_MINOR_VERSION)
+AC_SUBST(AT_SPI_MICRO_VERSION)
+AC_SUBST(AT_SPI_INTERFACE_AGE)
+AC_SUBST(AT_SPI_BINARY_AGE)
+
+# libtool versioning
+LT_RELEASE=$AT_SPI_MAJOR_VERSION.$AT_SPI_MINOR_VERSION
+LT_CURRENT=10
+LT_REVISION=11
+LT_AGE=10
+LT_VERSION_INFO='-version-info ${LT_CURRENT}:${LT_REVISION}:${LT_AGE}'
+AC_SUBST(LT_VERSION_INFO)
+AC_SUBST(LT_RELEASE)
+AC_SUBST(LT_CURRENT)
+AC_SUBST(LT_REVISION)
+AC_SUBST(LT_AGE)
+
 AM_INIT_AUTOMAKE([-Wall foreign])
 
 AC_PROG_CC
@@ -10,6 +35,14 @@ PKG_PROG_PKG_CONFIG
 
 AC_CONFIG_HEADERS([config.h])
 
+PKG_CHECK_MODULES(DBUS, [dbus-1 >= 1.0])
+AC_SUBST(DBUS_LIBS)
+AC_SUBST(DBUS_CFLAGS)
+
+PKG_CHECK_MODULES(GLIB, [glib-2.0])
+AC_SUBST(GLIB_LIBS)
+AC_SUBST(GLIB_CFLAGS)
+
 PKG_CHECK_MODULES(DBUS_GLIB, [dbus-glib-1 >= 0.7.0])
 AC_SUBST(DBUS_GLIB_LIBS)
 AC_SUBST(DBUS_GLIB_CFLAGS)
@@ -110,9 +143,26 @@ if test -z "$GTK_MODULE_DIR"; then
          GTK_MODULE_DIR=gtk-2.0/modules
 fi
 
+dnl find sizes & alignments
+orig_CPPFLAGS=$CPPFLAGS
+CPPFLAGS="$CPPFLAGS $DBUS_CFLAGS"
+DBIND_CHECK_ALIGNOF(char)
+DBIND_CHECK_ALIGNOF(dbus_bool_t)
+DBIND_CHECK_ALIGNOF(dbus_int16_t)
+DBIND_CHECK_ALIGNOF(dbus_int32_t)
+DBIND_CHECK_ALIGNOF(dbus_int64_t)
+DBIND_CHECK_ALIGNOF(double)
+DBIND_CHECK_ALIGNOF(dbind_pointer)
+DBIND_CHECK_ALIGNOF(dbind_struct)
+CPPFLAGS=$orig_CPPFLAGS 
+
+#libtool option to strip symbols starting with cspi
+#
+LIBTOOL_EXPORT_OPTIONS='-export-symbols-regex "^[[^cspi]].*"'
+AC_SUBST(LIBTOOL_EXPORT_OPTIONS)
+
 AC_CONFIG_FILES([Makefile
                 xml/Makefile
-                idl/Makefile
                 tests/Makefile
                 tools/Makefile
                 droute/Makefile
@@ -121,6 +171,9 @@ AC_CONFIG_FILES([Makefile
                 atk-adaptor/Makefile
                 tests/dummyatk/Makefile
                 tests/clients/Makefile
-                tests/apps/Makefile])
+                tests/apps/Makefile
+                dbind/Makefile
+                cspi/Makefile
+                dbind-config.h])
 
 AC_OUTPUT
diff --git a/cspi/Makefile.am b/cspi/Makefile.am
new file mode 100644 (file)
index 0000000..c251fc0
--- /dev/null
@@ -0,0 +1,43 @@
+NULL=
+
+lib_LTLIBRARIES = libcspi.la
+
+libcspi_la_LDFLAGS = @LDFLAGS@ @LT_VERSION_INFO@ @LIBTOOL_EXPORT_OPTIONS@ -no-undefined
+
+libcspi_la_CFLAGS = $(DBUS_GLIB_CFLAGS) $(ATK_CFLAGS) -I$(top_srcdir)
+
+LDADD = $(DBUS_GLIB_LIBS)                      \
+                     $(top_builddir)/spi-common/libspicommon.la
+
+libcspidir = $(includedir)/at-spi-1.0/cspi
+libcspi_HEADERS =              \
+       spi.h                   \
+       spi-impl.h              \
+       spi-listener.h          \
+       spi-roletypes.h         \
+       spi-statetypes.h
+
+libcspi_la_SOURCES =           \
+       cspi-lowlevel.h         \
+       spi_accessible.c \
+       spi_action.c \
+       spi_component.c \
+       spi_editabletext.c \
+       spi_event.c \
+       spi_hyperlink.c \
+       spi_hypertext.c \
+       spi_listener.c \
+       spi_main.c              \
+       spi_registry.c \
+       spi_selection.c \
+       spi_stateset.c \
+       spi_streamablecontent.c \
+       spi_table.c \
+       spi_text.c \
+       spi_value.c \
+       spi-private.h
+
+libcspi_la_LIBADD =            \
+       $(top_builddir)/spi-common/libspicommon.la \
+                     $(top_builddir)/dbind/libdbind.la\
+       $(LIBCSPI_LIBS) $(X_LIBS)
diff --git a/cspi/spi-impl.h b/cspi/spi-impl.h
new file mode 100644 (file)
index 0000000..60049b3
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * A load of opaque handles that people can't poke at.
+ */
+#ifndef _SPI_IMPL_H_
+#define _SPI_IMPL_H_
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+typedef struct _Accessible AccessibleUnknown;
+typedef AccessibleUnknown  Accessible;
+
+typedef Accessible AccessibleAction;
+typedef Accessible AccessibleApplication;
+typedef Accessible AccessibleCollection;
+typedef Accessible AccessibleComponent;
+typedef Accessible AccessibleDocument;
+typedef Accessible AccessibleEditableText;
+typedef Accessible AccessibleHyperlink;
+typedef Accessible AccessibleHypertext;
+typedef Accessible AccessibleImage;
+typedef Accessible AccessibleMatchRule;
+
+typedef struct _AccessibleRelation AccessibleRelation;
+struct _AccessibleRelation
+{
+  gint ref_count;
+  Accessibility_RelationType type;
+  GArray *targets;
+};
+
+typedef Accessible AccessibleSelection;
+typedef Accessible AccessibleStreamableContent;
+typedef Accessible AccessibleTable;
+typedef Accessible AccessibleText;
+typedef Accessible AccessibleValue;
+typedef Accessible AccessibilityRegistry;
+
+/** 
+ * AccessibleStateSet:
+ * @ref_count: private
+ * @states: private
+ *
+ * An opaque structure representing an accessible object's state,
+ * which can then be queried via AccessibleStateSet APIs.
+ **/
+typedef void AccessibleStateSet;
+typedef void AccessibleEventListener;
+typedef void AccessibleKeystrokeListener;
+typedef void AccessibleDeviceListener;
+
+typedef unsigned int SPIBoolean;
+#define SPI_FALSE (0)
+#define SPI_TRUE (!SPI_FALSE)
+
+/**
+ * SPIRect:
+ * @x: The position of the minimum x value of the rectangle (i.e. left hand corner)
+ * @y: The position of the minimum y value of the rectangle's bounds.
+ * @width: Width of the rectangle in pixels.
+ * @height: Height of the rectangle in pixels.
+ *
+ * A structure encapsulating a rectangle. 
+ **/
+typedef struct {
+       long x;
+       long y;
+       long width;
+       long height;
+} SPIRect;
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff --git a/cspi/spi-listener.h b/cspi/spi-listener.h
new file mode 100644 (file)
index 0000000..862a646
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _SPI_LISTENER_H_
+#define _SPI_LISTENER_H_
+
+#include <cspi/spi-impl.h>
+#include <glib-object.h>
+#include "spi-common/spi-types.h"
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+typedef enum
+{
+  EVENT_DATA_STRING,
+  EVENT_DATA_OBJECT,
+  EVENT_DATA_RECT
+} EVENT_DATA_TYPE;
+
+/**
+ * AccessibleEvent:
+ * @type: a string representing the type of the event, with increasing specificity
+ * from left to right, delimited by colons.  Leftmost token represents event source type,
+ * next token represents event category, and next token represents the subcategory
+ * of the event, for instance the specific property, state, or attribute being notified.
+ * @source: The #Accessible from which the event originated.
+ * @detail1: an event-type-specific integer value.
+ * @detail2: an event-type-specific integer value.
+ *
+ * A structure used to encapsulate event information.
+ **/
+typedef struct {
+  const char  *type;
+  Accessible  *source;
+  long         detail1;
+  long         detail2;
+  EVENT_DATA_TYPE v_type;
+  union
+  {
+    char *text;
+    Accessible *accessible;
+    SPIRect rect;
+  } v;
+} AccessibleEvent;
+
+/**
+ *AccessibleDeviceEventType:
+ *@SPI_KEY_PRESSED: A device key has been pressed.
+ *@SPI_KEY_RELEASED: A device key has been released.
+ *@SPI_BUTTON_PRESSED: A device button or switch (other than a keyboard key) 
+ * has been pressed.
+ *@SPI_BUTTON_RELEASED: A device button or switch has been released.
+ *
+ *The type of an AccessibleDeviceEvent.
+ **/
+typedef enum {
+  SPI_KEY_PRESSED  = 1<<0,
+  SPI_KEY_RELEASED = 1<<1,
+  SPI_BUTTON_PRESSED = 1<<2,
+  SPI_BUTTON_RELEASED = 1<<3
+} AccessibleDeviceEventType;
+
+/**
+ *AccessibleKeyEventType:
+ *
+ *This is a synonym for AccessibleDeviceEventType
+ **/
+typedef AccessibleDeviceEventType AccessibleKeyEventType;
+
+/**
+ * AccessibleDeviceEvent:
+ * @keyID: Symbolic representation for the key or switch generating the event, e.g. keysym or button number.
+ * @keystring: A symbolic name for the key or switch, or, if is_text is true, a string approximating the
+ * inserted text characters which would result from this event, if a text entry field has keyboard focus.
+ * @timestamp: A time in ms when this event occurred, relative to some unspecified starting point.  
+ * Timestamp values should therefore be used to compare events but should not be tested against a 
+ * fixed time.
+ * @type: The #AccessibleDeviceEventType identifying the specific type of event.
+ * @is_text: A boolean value indicating whether the event represents 'printable' text (i.e. whether it
+ * changes the current insertion buffer of a focussed text entry component or not).  Whitespace
+ * is considered "printable" in this context, since it typically inserts characters into the buffer.
+ *
+ * A structure encapsulating information relevant to a device event notification.
+ **/
+typedef struct {
+  long                   keyID;
+  short                  keycode;
+  char *                 keystring;
+  long                   timestamp;
+  AccessibleDeviceEventType type;
+  unsigned short         modifiers;
+  SPIBoolean             is_text;      
+} AccessibleDeviceEvent;
+
+typedef AccessibleDeviceEvent AccessibleKeystroke;
+
+/*
+ * Function prototype typedefs for Event Listener Callbacks.
+ * (see libspi/accessibleeventlistener.h for definition of SpiVoidEventListenerCB).
+ *
+ * usage: signatures should be
+ * void (*AccessibleEventListenerCB) (AccessibleEvent *event);
+ *
+ * SPIBoolean (*AccessibleKeystrokeListenerCB) (AccessibleKeystrokeEvent *Event);
+ * Note that AccessibleKeystrokeListeners may consume the event received
+ * if one of their callbacks returns TRUE (see SPI_registerAccessibleKeystrokeListener)
+ */
+
+/**
+ * AccessibleEventListenerCB:
+ * @event: The event for which notification is sent.
+ * @user_data: User data which is passed to the callback each time a notification takes place.
+ *
+ * A function prototype for callbacks via which clients are notified of AT-SPI events.
+ * 
+ **/
+typedef void       (*AccessibleEventListenerCB)     (const AccessibleEvent     *event,
+                                                    void                      *user_data);
+/**
+ * AccessibleKeystrokeListenerCB:
+ * @stroke: the #AccessibleKeystroke event for which notification is taking place.
+ * @user_data: data passed to the callback each time it is notified, according to the data
+ * which was passed in when the listener/callback was registered.
+ *
+ * A function prototype for a callback function called when a key event notification takes place.
+ *
+ * Returns: %TRUE if the client wishes to consume the event and prevent its
+ * dispatch to other listeners or the currently focussed application, if
+ * the relevant callback was registered with the #SPI_KEYLISTENER_CANCONSUME flag.
+ **/
+typedef SPIBoolean (*AccessibleKeystrokeListenerCB) (const AccessibleKeystroke *stroke,
+                                                    void                      *user_data);
+/**
+ * AccessibleDeviceListenerCB:
+ * @stroke: The #AccessibleDeviceEvent for which notification is being received.
+ * @user_data: Data which is passed to the client each time this callback is notified.
+ *
+ * A callback function prototype via which clients receive device event notifications.
+ *
+ * Returns: %TRUE if the client wishes to consume/preempt the event, preventing it from being
+ * relayed to the currently focussed application, %FALSE if the event delivery should proceed as normal.
+ **/
+typedef SPIBoolean (*AccessibleDeviceListenerCB)    (const AccessibleDeviceEvent *stroke,
+                                                    void                      *user_data);
+
+#define CSPI_EVENT_LISTENER_TYPE        (cspi_event_listener_get_type ())
+#define CSPI_EVENT_LISTENER(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), CSPI_EVENT_LISTENER_TYPE, CSpiEventListener))
+#define CSPI_EVENT_LISTENER_CLASS(k)    (G_TYPE_CHECK_CLASS_CAST((k), CSPI_EVENT_LISTENER_TYPE, CSpiEventListenerClass))
+#define CSPI_IS_EVENT_LISTENER(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), CSPI_EVENT_LISTENER_TYPE))
+#define CSPI_IS_EVENT_LISTENER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CSPI_EVENT_LISTENER_TYPE))
+#define CSPI_EVENT_LISTENER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CSPI_EVENT_LISTENER_TYPE, CSpiEventListenerClass))
+
+typedef struct {
+       GObject parent;
+       GList           *callbacks;
+} CSpiEventListener;
+
+typedef struct {
+  GObjectClass parent_class;
+
+  /* signals */
+  void (*event) (CSpiEventListener    *listener,
+                AccessibleEvent *e);
+} CSpiEventListenerClass;
+
+GType cspi_event_listener_get_type (void);
+
+#define CSPI_DEVICE_LISTENER_TYPE        (cspi_device_listener_get_type ())
+#define CSPI_DEVICE_LISTENER(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), CSPI_DEVICE_LISTENER_TYPE, CSpiDeviceListener))
+#define CSPI_DEVICE_LISTENER_CLASS(k)    (G_TYPE_CHECK_CLASS_CAST((k), CSPI_DEVICE_LISTENER_TYPE, CSpiDeviceListenerClass))
+#define CSPI_IS_DEVICE_LISTENER(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), CSPI_DEVICE_LISTENER_TYPE))
+#define CSPI_IS_DEVICE_LISTENER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CSPI_DEVICE_LISTENER_TYPE))
+#define CSPI_DEVICE_LISTENER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CSPI_DEVICE_LISTENER_TYPE, CSpiDeviceListenerClass))
+
+typedef struct {
+       GObject parent;
+       guint id;
+       GList            *callbacks;
+} CSpiDeviceListener;
+
+typedef struct {
+       GObjectClass parent_class;
+       gboolean (*device_event) (CSpiDeviceListener *listener, const Accessibility_DeviceEvent *key);
+} CSpiDeviceListenerClass;
+
+GType cspi_device_listener_get_type (void);
+gpointer cspi_device_listener_new (void);
+void cspi_device_listener_add_cb (AccessibleDeviceListener  *al,
+                                  AccessibleDeviceListenerCB callback,
+                                  void                      *user_data);
+void cspi_device_listener_remove_cb (AccessibleDeviceListener  *al,
+                                     AccessibleDeviceListenerCB callback);
+void cspi_device_listener_unref (AccessibleDeviceListener *listener);
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff --git a/cspi/spi-private.h b/cspi/spi-private.h
new file mode 100644 (file)
index 0000000..3e8926c
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2002 Ximian, Inc.
+ *           2002 Sun Microsystems Inc.
+ *           
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _SPI_PRIVATE_H_
+#define _SPI_PRIVATE_H_
+
+/* Private internal implementation details of at-spi. */
+
+#include <spi-common/spi-dbus.h>
+#include <cspi/spi.h>
+#include <string.h>
+#include "cspi/cspi-lowlevel.h"
+#include "cspi/spi-listener.h"
+#include "dbind/dbind.h"
+#include <glib-object.h>
+
+typedef struct _CSpiApplication CSpiApplication;
+struct _CSpiApplication
+{
+  GHashTable *hash;
+  char *bus_name;
+};
+
+struct _Accessible {
+  gint ref_count;
+  Accessible *parent;
+  GList *children;
+       CSpiApplication *app;
+       union
+       {
+         gint id;
+         char *path;
+       } v;
+  gint role : 8;
+  gint interfaces : 24;
+  char *name;
+  char *description;
+};
+
+struct _AccessibleStateSet {
+       guint   ref_count;
+       GArray *states;
+};
+
+#define SPI_INTERNAL_EVENT_MAGIC 0xc3
+/* 
+ * For internal use by CSPI implementation only
+ */
+typedef struct {
+  AccessibleEvent event;
+  guint           id;
+  guchar          magic;
+  guchar          type;
+  guint16         ref_count;
+} InternalEvent;
+
+struct _SPIException {
+  SPIExceptionType type;
+  Accessible *source;
+  DBusError *error;
+  SPIExceptionCode code;
+  char * desc;
+};
+
+DBusConnection *spi_bus (void);
+SPIBoolean             cspi_exception         (void);
+Accessible            *cspi_object_add (Accessible  *accessible);
+void                   cspi_object_ref        (Accessible  *accessible);
+void                   cspi_object_unref      (Accessible  *accessible);
+SPIBoolean             cspi_accessible_is_a   (Accessible  *accessible,
+                                              const char  *interface_name);
+AccessibleRole         cspi_role_from_spi_role (Accessibility_Role role);
+void                   cspi_streams_close_all (void);
+gboolean               cspi_exception_throw (DBusError *error, char *desc_prefix);
+
+AccessibleAttributeSet 
+                     *_cspi_attribute_set_from_sequence (const GArray *seq);
+#define cspi_return_if_fail(val)               \
+       if (!(val))                             \
+               return
+#define cspi_return_val_if_fail(val, ret)      \
+       if (!(val))                             \
+               return (ret)
+
+#define cspi_return_if_ev(err)                 \
+       if (cspi_exception ()) \
+               return;
+#define cspi_return_val_if_ev(err, ret)        \
+       if (cspi_exception ()) \
+               return (ret);
+
+typedef struct _Accessibility_BoundingBox Accessibility_BoundingBox;
+struct _Accessibility_BoundingBox
+{
+  dbus_uint32_t x;
+  dbus_uint32_t y;
+  dbus_uint32_t width;
+  dbus_uint32_t height;
+};
+
+#endif /* _SPI_PRIVATE_H_ */
diff --git a/cspi/spi.h b/cspi/spi.h
new file mode 100644 (file)
index 0000000..619b59b
--- /dev/null
@@ -0,0 +1,1230 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _SPI_H
+#define _SPI_H
+
+#include <cspi/spi-impl.h>
+/*
+ * Definitions for AccessibleRole, AccessibleState,
+ * and event listeners.
+ */
+#include <cspi/spi-roletypes.h>
+#include <cspi/spi-statetypes.h>
+#include <cspi/spi-listener.h>
+
+
+/*
+ * Auxiliary typedefs and mask definitions
+ */
+#include <spi-common/keymasks.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/**
+ *AccessibleCollectionMatchType:
+ *
+ *@SPI_COLLECTION_MATCH_INVALID        
+ *@SPI_COLLECTION_MATCH_ALL    TRUE if all of the criteria are met
+ *@SPI_COLLECTION_MATCH_ANY    TRUE if any of the criteria are met
+ *@SPI_COLLECTION_MATCH_NONE   TRUE if none of the criteria are met
+ *@SPI_COLLECTION_MATCH_EMPTY  Same as MATCH_ALL if the criteria is non-empty; 
+ * for empty criteria this rule requires returned value to also have empty set.
+ *@SPI_COLLECTION_MATCH_LAST_DEFINED   
+ *
+ **/
+typedef enum
+{
+     SPI_COLLECTION_MATCH_INVALID,
+     SPI_COLLECTION_MATCH_ALL,
+     SPI_COLLECTION_MATCH_ANY,
+     SPI_COLLECTION_MATCH_NONE,
+     SPI_COLLECTION_MATCH_EMPTY,
+     SPI_COLLECTION_MATCH_LAST_DEFINED
+}AccessibleCollectionMatchType;
+
+
+/**
+ *AccessibleTextBoundaryType:
+ *@SPI_TEXT_BOUNDARY_CHAR: Delimiter is the current character's bounds.
+ *@SPI_TEXT_BOUNDARY_CURSOR_POS: Delimiter is the current text caret position.
+ *@SPI_TEXT_BOUNDARY_WORD_START: Bounds run from the first character of a word to the first 
+ * character of the following word (i.e. including trailing whitespace, if any) within the text object.
+ *@SPI_TEXT_BOUNDARY_WORD_END: Bounds run from the last character of a word to the last 
+ * character of the following word (i.e. including leading whitespace) within the text object.
+ *@SPI_TEXT_BOUNDARY_SENTENCE_START: Bounds run from the first character of a sentence to the first 
+ * character of the next sentence in the text object.
+ *@SPI_TEXT_BOUNDARY_SENTENCE_END: Bounds run from the last character of a sentence to the last 
+ * character of the next sentence in the text object.
+ *@SPI_TEXT_BOUNDARY_LINE_START: Bounds span one line of text, with the line delimiter at the end of the
+ * bounds, if present, within the current text object.
+ *@SPI_TEXT_BOUNDARY_LINE_END: Bounds span one line of text, including a preceding line delimiter
+ * if present within the current text object.
+ *@SPI_TEXT_BOUNDARY_ATTRIBUTE_RANGE: Bounds span the run, relative to the specified offset and
+ * text accessor API rules, over which the attributes of the text object are invariant.  
+ *
+ *Text boundary types used for specifying boundaries for regions of text.
+ **/
+typedef enum
+{
+  SPI_TEXT_BOUNDARY_CHAR,
+  SPI_TEXT_BOUNDARY_CURSOR_POS,
+  SPI_TEXT_BOUNDARY_WORD_START,
+  SPI_TEXT_BOUNDARY_WORD_END,
+  SPI_TEXT_BOUNDARY_SENTENCE_START,
+  SPI_TEXT_BOUNDARY_SENTENCE_END,
+  SPI_TEXT_BOUNDARY_LINE_START,
+  SPI_TEXT_BOUNDARY_LINE_END,
+  SPI_TEXT_BOUNDARY_ATTRIBUTE_RANGE
+} AccessibleTextBoundaryType;
+
+/**
+ *AccessibleTextClipType
+ *@SPI_TEXT_CLIP_NONE: No clipping to be done
+ *@SPI_TEXT_CLIP_MIN: Text clipped by min coordinate is omitted
+ *@SPI_TEXT_CLIP_MAX: Text clipped by max coordinate is omitted
+ *@SPI_TEXT_CLIP_BOTH: Only text fully within mix/max bound is retained
+ *
+ *Describes the type of clipping required.
+ **/
+typedef enum
+{
+  SPI_TEXT_CLIP_NONE,
+  SPI_TEXT_CLIP_MIN,
+  SPI_TEXT_CLIP_MAX,
+  SPI_TEXT_CLIP_BOTH
+} AccessibleTextClipType;
+
+/**
+ *AccessibleRelationType:
+ *@SPI_RELATION_NULL: Not used, this is an invalid value for this enumeration.
+ *@SPI_RELATION_LABEL_FOR: Indicates an object is a label for one or more target objects.
+ *@SPI_RELATION_LABELED_BY: Indicates an object is labelled by one or more target objects.
+ *@SPI_RELATION_CONTROLLED_BY: Indicates an object controlled by one or more target objects.
+ *@SPI_RELATION_CONTROLLER_FOR: Indicates an object is an controller for one or more target objects.
+ *@SPI_RELATION_MEMBER_OF: Indicates an object is a member of a group of one or
+more target objects.
+ *@SPI_RELATION_NODE_CHILD_OF: Indicates an object is a cell in a treetable which is displayed because a cell in the same column is expanded and identifies that cell.
+ *@SPI_RELATION_EXTENDED: This value indicates that a relation other than those pre-specified by this version of AT-SPI
+ * is present.
+ *@SPI_RELATION_FLOWS_TO: Indicates that the object has content that flows logically to another
+ *  AtkObject in a sequential way, (for instance text-flow).
+ *@SPI_RELATION_FLOWS_FROM: Indicates that the object has content that flows logically from
+ *  another AtkObject in a sequential way, (for instance text-flow).
+ *@SPI_RELATION_SUBWINDOW_OF: Indicates a subwindow attached to a component but otherwise has no connection in the UI heirarchy to that component.
+ *@SPI_RELATION_EMBEDS: Indicates that the object visually embeds
+ *  another object's content, i.e. this object's content flows around
+ *  another's content.
+ *@SPI_RELATION_EMBEDDED_BY: Inverse of %SPI_RELATION_EMBEDS, indicates that
+ *  this object's content is visualy embedded in another object.
+ *@SPI_RELATION_POPUP_FOR: Indicates that an object is a popup for another object.
+ *@SPI_RELATION_PARENT_WINDOW_OF: Indicates that an object is a parent window of another object.
+ *@SPI_RELATION_DESCRIBED_BY: Indicates that another object provides descriptive information about this object; more verbose than %SPI_RELATION_LABELLED_BY.
+ *@SPI_RELATION_DESCRIPTION_FOR: Indicates that an object provides descriptive information about another object; more verbose than %SPI_RELATION_LABEL_FOR.
+ *@SPI_RELATION_LAST_DEFINED: Do not use, this is an implementation detail used
+ *  to identify the size of this enumeration.
+ *
+ *Describes the type of the relation
+ **/
+typedef enum
+{
+  SPI_RELATION_NULL,
+  SPI_RELATION_LABEL_FOR,
+  SPI_RELATION_LABELED_BY,
+  SPI_RELATION_CONTROLLER_FOR,
+  SPI_RELATION_CONTROLLED_BY,
+  SPI_RELATION_MEMBER_OF,
+  SPI_RELATION_NODE_CHILD_OF,
+  SPI_RELATION_EXTENDED,
+  SPI_RELATION_FLOWS_TO,
+  SPI_RELATION_FLOWS_FROM,
+  SPI_RELATION_SUBWINDOW_OF,
+  SPI_RELATION_EMBEDS,
+  SPI_RELATION_EMBEDDED_BY,
+  SPI_RELATION_POPUP_FOR,
+  SPI_RELATION_PARENT_WINDOW_OF,
+  SPI_RELATION_DESCRIPTION_FOR,
+  SPI_RELATION_DESCRIBED_BY,
+  SPI_RELATION_LAST_DEFINED
+} AccessibleRelationType;
+
+
+/* don't change the order of these ! */
+/**
+ *AccessibleCoordType:
+ *@SPI_COORD_TYPE_SCREEN: specifies xy coordinates relative to the screen
+ *@SPI_COORD_TYPE_WINDOW: specifies xy coordinates relative to an object's
+ * top-level window
+ *
+ *Specifies how xy coordinates are to be interpreted. Used by functions such
+ *as AccessibleComponent_getPosition() and AccessibleText_getCharacterExtents()
+ **/
+typedef enum {
+  SPI_COORD_TYPE_SCREEN,
+  SPI_COORD_TYPE_WINDOW
+} AccessibleCoordType;
+
+/**
+ *AccessibleKeySynthType:
+ *@SPI_KEY_PRESS: Generates a keypress event (requires a subsequent #SPI_KEY_RELEASE event)
+ *@SPI_KEY_RELEASE: Generates a key-release event
+ *@SPI_KEY_PRESSRELEASE: Generates a key press/release event pair.
+ *@SPI_KEY_SYM: Injects a "keysym" event into the stream, as if a press/release pair occurred; allows 
+ * the user to specify the key via its symbolic name, as opposed to simulating a hardware press of a 
+ * specific key.
+ *@SPI_KEY_STRING: Injects one or more keysym events into the keyboard buffer, or directly inserts 
+ * a string value into the currently focussed text widget, if the widgets supports this.
+ * #SPI_KEY_STRING synthesis provides a shortcut for text substring insertion, and also allows the
+ * insertion of text which is not currently available via the current keyboard's keymap.
+ *
+ * Specifies the type of a generated event.
+ **/
+typedef enum {
+  SPI_KEY_PRESS,
+  SPI_KEY_RELEASE, 
+  SPI_KEY_PRESSRELEASE,
+  SPI_KEY_SYM,
+  SPI_KEY_STRING
+} AccessibleKeySynthType;
+
+/**
+ *AccessibleKeyListenerSyncType:
+ *@SPI_KEYLISTENER_NOSYNC: Events may be delivered asynchronously, 
+ * which means in some cases they may already have been delivered to the 
+ * application before the AT client receives the notification.  
+ *@SPI_KEYLISTENER_SYNCHRONOUS: Events are delivered synchronously, before the 
+ * currently focussed application sees them.  
+ *@SPI_KEYLISTENER_CANCONSUME: Events may be consumed by the AT client.  Presumes and
+ * requires #SPI_KEYLISTENER_SYNCHRONOUS, incompatible with #SPI_KEYLISTENER_NOSYNC.
+ *@SPI_KEYLISTENER_ALL_WINDOWS: Events are received not from the application toolkit layer, but
+ * from the device driver or windowing system subsystem; such notifications are 'global' in the 
+ * sense that they are not broken or defeated by applications that participate poorly
+ * in the accessibility APIs, or not at all; however because of the intrusive nature of
+ * such snooping, it can have side-effects on certain older platforms.  If unconditional
+ * event notifications, even when inaccessible or "broken" applications have focus, are not
+ * required, it may be best to avoid this enum value/flag.
+ *
+ *Specified the tyupe of a key listener event.
+ * Certain of the values above can and should be bitwise-'OR'ed
+ * together, observing the compatibility limitations specified in the description of
+ * each value.  For instance, #SPI_KEYLISTENER_ALL_WINDOWS | #SPI_KEYLISTENER_CANCONSUME is
+ * a commonly used combination which gives the AT complete control over the delivery of matching
+ * events.  However, such filters should be used sparingly as they may have a negative impact on 
+ * system performance.
+ **/
+typedef enum {
+  SPI_KEYLISTENER_NOSYNC = 0,
+  SPI_KEYLISTENER_SYNCHRONOUS = 1,
+  SPI_KEYLISTENER_CANCONSUME = 2,
+  SPI_KEYLISTENER_ALL_WINDOWS = 4
+} AccessibleKeyListenerSyncType;
+
+
+/**
+ *AccessibleStreamableContentSeekType
+ *@SPI_STREAM_SEEK_SET: seek from the 'top' of the streamable
+ *@SPI_STREAM_SEEK_CUR: seek from the current position in the stream
+ *@SPI_STREAM_SEEK_END: seek from the end of the stream (if known)
+ *
+ *The seek type for a specified offset in AccessibleStreamableContent_seek.
+ **/
+typedef enum
+{
+  SPI_STREAM_SEEK_SET,
+  SPI_STREAM_SEEK_CUR,
+  SPI_STREAM_SEEK_END
+} AccessibleStreamableContentSeekType;
+
+/**
+ * SPIException:
+ * @type: private
+ * @source: private
+ * @ev: private
+ * @code: private
+ * @desc: private
+ *
+ * An opaque object encapsulating information about thrown exceptions.
+ **/
+typedef struct _SPIException SPIException;
+
+/**
+ * SPIExceptionHandler:
+ * @err: points to the SPIException opaque object.
+ * @is_fatal: indicates whether the exception is a fatal error or not.
+ *
+ * A function type for functions to be called when exceptions occur.
+ *
+ * Returns 
+ **/
+typedef SPIBoolean (*SPIExceptionHandler) (SPIException *err, SPIBoolean is_fatal);
+
+/**
+ * SPIExceptionCode:
+ * @SPI_EXCEPTION_UNSPECIFIED: An exception of unknown type, or which doesn't fit the other types.
+ * @SPI_EXCEPTION_DISCONNECT: Communication with the object or service has been disconnected;
+ * this usually means that the object or service has died or exited.
+ * @SPI_EXCEPTION_NO_IMPL: The object or service is missing the implementation for a request.
+ * @SPI_EXCEPTION_IO: The communications channel has become corrupted, blocked, or is otherwise in a bad state.
+ * @SPI_EXCEPTION_BAD_DATA: The data received or sent over the interface has been identified as 
+ * improperly formatted or otherwise fails to match the expectations.
+ *
+ * Exception codes indicating what's gone wrong in an AT-SPI call.
+ **/
+typedef enum {
+       SPI_EXCEPTION_UNSPECIFIED,
+       SPI_EXCEPTION_DISCONNECT,
+       SPI_EXCEPTION_NO_IMPL,
+       SPI_EXCEPTION_IO,
+       SPI_EXCEPTION_BAD_DATA
+} SPIExceptionCode;
+
+/**
+ * SPIExceptionType:
+ * @SPI_EXCEPTION_SOURCE_UNSPECIFIED: Don't know or can't tell where the problem is
+ * @SPI_EXCEPTION_SOURCE_ACCESSIBLE: The source of an event or query (i.e. an app) has thrown the exception.
+ * @SPI_EXCEPTION_SOURCE_REGISTRY: The AT-SPI registry has thrown the exception or cannot be reached.
+ * @SPI_EXCEPTION_SOURCE_DEVICE: The device event subsystem has encountered an error condition.
+ *
+ * The general source of the failure, i.e. whether the app, registry, or device system has encountered trouble.
+ **/
+typedef enum {
+       SPI_EXCEPTION_SOURCE_UNSPECIFIED,
+       SPI_EXCEPTION_SOURCE_ACCESSIBLE,
+       SPI_EXCEPTION_SOURCE_REGISTRY,
+       SPI_EXCEPTION_SOURCE_DEVICE
+} SPIExceptionType;
+
+typedef unsigned long AccessibleKeyEventMask;
+typedef unsigned long AccessibleDeviceEventMask;
+
+/**
+ *AccessibleComponentLayer:
+ *@SPI_LAYER_INVALID: The layer cannot be determined or is somehow undefined.
+ *@SPI_LAYER_BACKGROUND: Component belongs to the destop background.
+ *@SPI_LAYER_CANVAS: Component is a canvas backdrop or drawing area.
+ *@SPI_LAYER_WIDGET: Component is a 'normal' widget.
+ *@SPI_LAYER_MDI: Component is drawn in the MDI layer and may have valid
+ *                         Z-information relative to other MDI-layer components.
+ *@SPI_LAYER_POPUP: Component is in the popup layer, above other widgets and
+ *                         MDI components.
+ *@SPI_LAYER_OVERLAY: Component is in the overlay plane - this value is reserved
+ *                         for future use.
+ *@SPI_LAYER_WINDOW: Component is in the window layer and have valid Z-information
+ *                   relative to other window-layer components.
+ *@SPI_LAYER_LAST_DEFINED: Used to determine the last valid value in the enum,
+ *                         should not be encountered.  
+ *
+ * Describes the layer of a component.
+ *
+ * These enumerated "layer values" are used when determining which UI
+ * rendering layer a component is drawn into, which can help in making
+ * determinations of when components occlude one another.
+ **/
+typedef enum {
+    SPI_LAYER_INVALID,
+    SPI_LAYER_BACKGROUND,
+    SPI_LAYER_CANVAS,
+    SPI_LAYER_WIDGET,
+    SPI_LAYER_MDI,
+    SPI_LAYER_POPUP,
+    SPI_LAYER_OVERLAY,
+    SPI_LAYER_WINDOW,
+    SPI_LAYER_LAST_DEFINED     
+} AccessibleComponentLayer;
+
+
+/**
+ * AccessibleTextRange:
+ * @start: the first nominal character position within the range.
+ * @end: the first nominal character position following the range.
+ * @content: The actual text content between @start and @end, as a UTF-8 string.
+ *
+ * Structure which encapsulates a text range - must be associated with an
+ *          AccessibleText-implementing object.
+ **/
+typedef struct _AccessibleTextRange
+{
+  long int        start;
+  long int        end;
+  char           *contents;
+} AccessibleTextRange;
+
+/**
+ * AccessibleKeySet:
+ * @keysyms:
+ * @keycodes:
+ * @len:
+ *
+ * Structure containing identifying information about a set of keycode or
+ *        keysyms.
+ **/
+typedef struct _AccessibleKeySet
+{
+  unsigned long  *keysyms;
+  unsigned short *keycodes;
+  char          **keystrings;
+  short           len;
+} AccessibleKeySet;
+
+/*
+ * A special value for an AccessibleKeySet type, which tacitly
+ * includes all keycodes and keyvals for the specified modifier set.
+ */
+#define SPI_KEYSET_ALL_KEYS NULL
+
+typedef unsigned long AccessibleModifierMaskType;
+/**
+ *AccessibleKeyMaskType:
+ *
+ *AccessibleKeyMaskType is a mask which is a set of key event modifiers
+ *which is specified in SPI_registerAccessibleKeystrokeListener.
+ **/
+
+typedef AccessibleModifierMaskType AccessibleKeyMaskType;
+
+typedef struct _AccessibleAttributeSet
+{
+    int len;
+    char **attributes;
+} AccessibleAttributeSet;
+
+typedef struct _AccessibleRoleSet
+{
+     int len;
+     AccessibleRole *roles;
+} AccessibleRoleSet;
+
+
+
+/* Basic SPI initialization and event loop function prototypes */
+
+int              SPI_init         (void);
+void             SPI_event_main   (void);
+void             SPI_event_quit   (void);
+SPIBoolean       SPI_eventIsReady (void);
+AccessibleEvent *SPI_nextEvent    (SPIBoolean waitForEvent);
+int              SPI_exit         (void);
+
+/* Event Listener creation and support.  */
+
+void                      SPI_freeAccessibleKeySet (
+                                                  AccessibleKeySet         *keyset);
+AccessibleKeySet        * SPI_createAccessibleKeySet (
+                                                  int                       len,
+                                                  const char               *keysyms,
+                                                  short                    *keycodes,
+                                                  const char              **keystrings);
+AccessibleEventListener * SPI_createAccessibleEventListener (
+                                                  AccessibleEventListenerCB callback,
+                                                  void                     *user_data);
+SPIBoolean                AccessibleEventListener_addCallback (
+                                                  AccessibleEventListener  *listener,
+                                                  AccessibleEventListenerCB callback,
+                                                  void                     *user_data);
+SPIBoolean                AccessibleEventListener_removeCallback (
+                                                  AccessibleEventListener  *listener,
+                                                  AccessibleEventListenerCB callback);
+void                      AccessibleEventListener_unref (
+                                                  AccessibleEventListener  *listener);
+
+/* Device Event Listener creation and support.  */
+
+/* First four are deprecated in favor of the last four; really just a re-name */
+
+AccessibleKeystrokeListener * SPI_createAccessibleKeystrokeListener (
+                                       AccessibleKeystrokeListenerCB callback,
+                                       void                         *user_data);
+SPIBoolean                    AccessibleKeystrokeListener_addCallback (
+                                       AccessibleKeystrokeListener  *listener,
+                                       AccessibleKeystrokeListenerCB callback,
+                                       void                         *user_data);
+SPIBoolean                    AccessibleKeystrokeListener_removeCallback (
+                                       AccessibleKeystrokeListener *listener,
+                                       AccessibleKeystrokeListenerCB callback);
+void                          AccessibleKeystrokeListener_unref (
+                                       AccessibleKeystrokeListener *listener);
+
+AccessibleDeviceListener   * SPI_createAccessibleDeviceListener (
+                                       AccessibleDeviceListenerCB callback,
+                                       void                      *user_data);
+SPIBoolean                    AccessibleDeviceListener_addCallback (
+                                       AccessibleDeviceListener  *listener,
+                                       AccessibleDeviceListenerCB callback,
+                                       void                      *user_data);
+SPIBoolean                    AccessibleDeviceListener_removeCallback (
+                                       AccessibleDeviceListener  *listener,
+                                       AccessibleDeviceListenerCB callback);
+void                          AccessibleDeviceListener_unref (
+                                       AccessibleDeviceListener *listener);
+
+/* Global functions serviced by the registry */
+
+SPIBoolean SPI_registerGlobalEventListener           (
+                                      AccessibleEventListener *listener,
+                                      const char              *eventType);
+SPIBoolean SPI_deregisterGlobalEventListener         (
+                                      AccessibleEventListener *listener,
+                                      const char              *eventType);
+SPIBoolean SPI_deregisterGlobalEventListenerAll      (
+                                      AccessibleEventListener *listener);
+SPIBoolean SPI_registerAccessibleKeystrokeListener   (
+                                       AccessibleKeystrokeListener *listener,
+                                      AccessibleKeySet             *keys,
+                                      AccessibleKeyMaskType         modmask,
+                                      AccessibleKeyEventMask        eventmask,
+                                      AccessibleKeyListenerSyncType sync_type);
+SPIBoolean SPI_deregisterAccessibleKeystrokeListener (
+                                      AccessibleKeystrokeListener *listener,
+                                      AccessibleKeyMaskType        modmask);
+
+SPIBoolean SPI_registerDeviceEventListener   (
+                                       AccessibleDeviceListener   *listener,
+                                      AccessibleDeviceEventMask   eventmask,
+                                      void                       *filter);
+SPIBoolean SPI_deregisterDeviceEventListener (
+                                      AccessibleDeviceListener   *listener,
+                                      void                       *filter);
+
+int         SPI_getDesktopCount                  (void);
+Accessible *SPI_getDesktop                       (int i);
+int         SPI_getDesktopList                   (Accessible ***desktop_list);
+void        SPI_freeDesktopList                  (Accessible  **desktop_list);
+
+SPIBoolean  SPI_generateKeyboardEvent            (long int                    keyval,
+                                                 char                       *keystring,
+                                                 AccessibleKeySynthType      synth_type);
+
+SPIBoolean  SPI_generateMouseEvent               (long int x, long int y, char *name);
+
+/* Accessible function prototypes  */
+
+void                 Accessible_ref              (Accessible *obj);
+void                 Accessible_unref            (Accessible *obj);
+char *               Accessible_getName          (Accessible *obj);
+char *               Accessible_getDescription   (Accessible *obj);
+Accessible *         Accessible_getParent        (Accessible *obj);
+long                 Accessible_getChildCount    (Accessible *obj);
+Accessible *         Accessible_getChildAtIndex  (Accessible *obj,
+                                                 long int    childIndex);
+long                 Accessible_getIndexInParent (Accessible *obj);
+AccessibleRelation **Accessible_getRelationSet   (Accessible *obj);
+AccessibleRole       Accessible_getRole          (Accessible *obj);
+char *               Accessible_getRoleName      (Accessible *obj);
+char *               Accessible_getLocalizedRoleName (Accessible *obj);
+AccessibleStateSet * Accessible_getStateSet      (Accessible *obj);
+AccessibleAttributeSet *Accessible_getAttributes (Accessible *obj);
+AccessibleApplication *Accessible_getHostApplication (Accessible *obj);
+
+/* Interface query methods */
+
+SPIBoolean Accessible_isAction            (Accessible *obj);
+SPIBoolean Accessible_isApplication       (Accessible *obj);
+SPIBoolean Accessible_isCollection        (Accessible *obj);
+SPIBoolean Accessible_isComponent         (Accessible *obj);
+SPIBoolean Accessible_isDocument          (Accessible *obj);
+SPIBoolean Accessible_isEditableText      (Accessible *obj);
+SPIBoolean Accessible_isHypertext         (Accessible *obj);
+SPIBoolean Accessible_isImage             (Accessible *obj);
+SPIBoolean Accessible_isMatchRule         (Accessible *obj);
+SPIBoolean Accessible_isSelection         (Accessible *obj);
+SPIBoolean Accessible_isStreamableContent (Accessible *obj);
+SPIBoolean Accessible_isTable             (Accessible *obj);
+SPIBoolean Accessible_isText              (Accessible *obj);
+SPIBoolean Accessible_isValue             (Accessible *obj);
+
+AccessibleAction *            Accessible_getAction            (Accessible *obj);
+AccessibleApplication *       Accessible_getApplication       (Accessible *obj);
+AccessibleCollection *        Accessible_getCollection        (Accessible *obj);
+AccessibleComponent *         Accessible_getComponent         (Accessible *obj);
+AccessibleDocument *          Accessible_getDocument          (Accessible *obj);
+AccessibleEditableText *      Accessible_getEditableText      (Accessible *obj);
+AccessibleHypertext *         Accessible_getHypertext         (Accessible *obj);
+AccessibleImage *             Accessible_getImage             (Accessible *obj);
+AccessibleMatchRule *         Accessible_getMatchRule         (Accessible *obj);
+AccessibleSelection *         Accessible_getSelection         (Accessible *obj);
+AccessibleStreamableContent * Accessible_getStreamableContent (Accessible *obj);
+AccessibleTable *             Accessible_getTable             (Accessible *obj);
+AccessibleText *              Accessible_getText              (Accessible *obj);
+AccessibleValue *             Accessible_getValue             (Accessible *obj);
+AccessibleUnknown *           Accessible_queryInterface       (Accessible *obj,
+                                                  const char *interface_name);
+
+/* AccessibleAction function prototypes  */
+
+void       AccessibleAction_ref            (AccessibleAction *obj);
+void       AccessibleAction_unref          (AccessibleAction *obj);
+long       AccessibleAction_getNActions    (AccessibleAction *obj);
+char      *AccessibleAction_getName        (AccessibleAction *obj,
+                                           long int          i);
+char      *AccessibleAction_getDescription (AccessibleAction *obj,
+                                           long int          i);
+SPIBoolean AccessibleAction_doAction       (AccessibleAction *obj,
+                                           long int          i);
+char      *AccessibleAction_getKeyBinding  (AccessibleAction *obj,
+                                           long int          i);
+
+/* AccessibleApplication function prototypes  */
+
+void       AccessibleApplication_ref            (AccessibleApplication *obj);
+void       AccessibleApplication_unref          (AccessibleApplication *obj);
+char      *AccessibleApplication_getToolkitName (AccessibleApplication *obj);
+char      *AccessibleApplication_getVersion     (AccessibleApplication *obj);
+long       AccessibleApplication_getID          (AccessibleApplication *obj);
+char      *AccessibleApplication_getLocale      (AccessibleApplication *obj, int lc_category);
+SPIBoolean AccessibleApplication_pause          (AccessibleApplication *obj);
+SPIBoolean AccessibleApplication_resume         (AccessibleApplication *obj);
+
+/* AccessibleCollection function prototypes */
+void       AccessibleCollection_ref (AccessibleCollection *obj);
+void       AccessibleCollection_unref (AccessibleCollection *obj);
+AccessibleMatchRule *
+AccessibleCollection_createMatchRule (AccessibleCollection *obj,
+                                     AccessibleStateSet *states,
+                                     AccessibleCollectionMatchType statematchtype,
+                                     AccessibleAttributeSet *attributes,
+                                     AccessibleCollectionMatchType attributematchtype,
+                                     AccessibleRoleSet *roles,
+                                     AccessibleCollectionMatchType rolematchtype,
+                                     char *interfaces,
+                                     AccessibleCollectionMatchType interfacematchtype,
+                                     long int invert);
+void
+AccessibleCollection_freeMatchRule (AccessibleCollection *obj,
+                                   AccessibleMatchRule  *matchrule);
+/* AccessibleComponent function prototypes */
+
+void        AccessibleComponent_ref         (AccessibleComponent *obj);
+void        AccessibleComponent_unref       (AccessibleComponent *obj);
+SPIBoolean  AccessibleComponent_contains    (AccessibleComponent *obj,
+                                            long int             x,
+                                            long int             y,
+                                            AccessibleCoordType  ctype);
+Accessible *AccessibleComponent_getAccessibleAtPoint (
+                                             AccessibleComponent *obj,
+                                            long int             x,
+                                            long int             y,
+                                            AccessibleCoordType  ctype);
+void        AccessibleComponent_getExtents  (AccessibleComponent *obj,
+                                            long int            *x,
+                                            long int            *y,
+                                            long int            *width,
+                                            long int            *height,
+                                            AccessibleCoordType  ctype);
+void        AccessibleComponent_getPosition (AccessibleComponent *obj,
+                                            long int            *x,
+                                            long int            *y,
+                                            AccessibleCoordType  ctype);
+void        AccessibleComponent_getSize     (AccessibleComponent *obj,
+                                            long int            *width,
+                                            long int            *height);
+AccessibleComponentLayer
+            AccessibleComponent_getLayer    (AccessibleComponent *obj);
+SPIBoolean  AccessibleComponent_grabFocus   (AccessibleComponent *obj);
+short       AccessibleComponent_getMDIZOrder(AccessibleComponent *obj);
+double      AccessibleComponent_getAlpha    (AccessibleComponent *obj);
+
+/* AccessibleDocument function prototypes  */
+
+void        AccessibleDocument_ref               (AccessibleDocument *obj);
+void        AccessibleDocument_unref             (AccessibleDocument *obj);
+char       *AccessibleDocument_getLocale         (AccessibleDocument *obj);
+char       *AccessibleDocument_getAttributeValue (AccessibleDocument *obj,
+                                                 char *attribute);
+AccessibleAttributeSet *AccessibleDocument_getAttributes     (AccessibleDocument *obj);
+
+/* AccessibleEditableText function prototypes  */
+
+void
+AccessibleEditableText_ref (AccessibleEditableText *obj);
+
+void
+AccessibleEditableText_unref (AccessibleEditableText *obj);
+
+SPIBoolean
+AccessibleEditableText_setAttributes (AccessibleEditableText *obj,
+                                     const char *attributes,
+                                     long int startOffset,
+                                     long int endOffset);
+
+SPIBoolean
+AccessibleEditableText_setTextContents (AccessibleEditableText *obj,
+                                        const char *newContents);
+
+SPIBoolean
+AccessibleEditableText_insertText (AccessibleEditableText *obj,
+                                   long int position,
+                                   const char *text,
+                                   long int length);
+
+SPIBoolean
+AccessibleEditableText_copyText (AccessibleText *obj,
+                                 long int startPos,
+                                 long int endPos);
+
+SPIBoolean
+AccessibleEditableText_cutText (AccessibleEditableText *obj,
+                                long int startPos,
+                                long int endPos);
+
+SPIBoolean
+AccessibleEditableText_deleteText (AccessibleEditableText *obj,
+                                   long int startPos,
+                                   long int endPos);
+
+SPIBoolean
+AccessibleEditableText_pasteText (AccessibleEditableText *obj,
+                                  long int position);
+
+/*
+ *
+ * AccessibleHyperlink function prototypes
+ *
+ */
+void
+AccessibleHyperlink_ref (AccessibleHyperlink *obj);
+void
+AccessibleHyperlink_unref (AccessibleHyperlink *obj);
+
+long
+AccessibleHyperlink_getNAnchors (AccessibleHyperlink *obj);
+
+char *
+AccessibleHyperlink_getURI (AccessibleHyperlink *obj,
+                            long int i);
+
+Accessible *
+AccessibleHyperlink_getObject (AccessibleHyperlink *obj,
+                               long int i);
+
+void
+AccessibleHyperlink_getIndexRange (AccessibleHyperlink *obj,
+                                   long int *startIndex,
+                                   long int *endIndex);
+
+SPIBoolean
+AccessibleHyperlink_isValid (AccessibleHyperlink *obj);
+
+/*
+ *
+ * AccessibleHypertext function prototypes
+ *
+ */
+
+void
+AccessibleHypertext_ref (AccessibleHypertext *obj);
+
+void
+AccessibleHypertext_unref (AccessibleHypertext *obj);
+
+long
+AccessibleHypertext_getNLinks (AccessibleHypertext *obj);
+
+AccessibleHyperlink *
+AccessibleHypertext_getLink (AccessibleHypertext *obj,
+                             long int linkIndex);
+
+long
+AccessibleHypertext_getLinkIndex (AccessibleHypertext *obj,
+                                  long int characterOffset);
+
+/*
+ *
+ * AccessibleImage function prototypes
+ *
+ */
+
+void
+AccessibleImage_ref (AccessibleImage *obj);
+
+void
+AccessibleImage_unref (AccessibleImage *obj);
+
+char *
+AccessibleImage_getImageDescription (AccessibleImage *obj);
+
+void
+AccessibleImage_getImageSize (AccessibleImage *obj,
+                              long int *width,
+                              long int *height);
+
+void
+AccessibleImage_getImagePosition (AccessibleImage *obj,
+                                  long int *x,
+                                  long int *y,
+                                  AccessibleCoordType ctype);
+
+void
+AccessibleImage_getImageExtents (AccessibleImage *obj,
+                                long int *x,
+                                long int *y,
+                                long int *width,
+                                long int *height,
+                                AccessibleCoordType ctype);
+char *
+AccessibleImage_getImageLocale  (AccessibleImage *obj);
+
+/*
+ *
+ * AccessibleMatchRule function prototypes
+ *
+ */
+void       AccessibleMatchRule_ref (AccessibleMatchRule *obj);
+void       AccessibleMatchRule_unref (AccessibleMatchRule *obj);
+
+/*
+ *
+ * AccessibleRelation function prototypes
+ *
+ */
+
+void AccessibleRelation_ref   (AccessibleRelation *obj);
+void AccessibleRelation_unref (AccessibleRelation *obj);
+
+AccessibleRelationType
+AccessibleRelation_getRelationType (AccessibleRelation *obj);
+
+int
+AccessibleRelation_getNTargets (AccessibleRelation *obj);
+
+Accessible *
+AccessibleRelation_getTarget (AccessibleRelation *obj, int i);
+
+
+/*
+ *
+ * AccessibleSelection function prototypes
+ *
+ */
+
+void AccessibleSelection_ref   (AccessibleSelection *obj);
+void AccessibleSelection_unref (AccessibleSelection *obj);
+
+long
+AccessibleSelection_getNSelectedChildren (AccessibleSelection *obj);
+
+Accessible *
+AccessibleSelection_getSelectedChild (AccessibleSelection *obj,
+                                      long int selectedChildIndex);
+
+SPIBoolean
+AccessibleSelection_selectChild (AccessibleSelection *obj,
+                                 long int childIndex);
+
+SPIBoolean
+AccessibleSelection_deselectSelectedChild (AccessibleSelection *obj,
+                                           long int selectedChildIndex);
+
+SPIBoolean
+AccessibleSelection_deselectChild (AccessibleSelection *obj,
+                                  long int childIndex);
+
+SPIBoolean
+AccessibleSelection_isChildSelected (AccessibleSelection *obj,
+                                     long int childIndex);
+
+SPIBoolean
+AccessibleSelection_selectAll (AccessibleSelection *obj);
+
+SPIBoolean
+AccessibleSelection_clearSelection (AccessibleSelection *obj);
+
+
+/*
+ *
+ * AccessibleStateSet function prototypes
+ *
+ */
+
+void AccessibleStateSet_ref   (AccessibleStateSet *obj);
+void AccessibleStateSet_unref (AccessibleStateSet *obj);
+
+SPIBoolean
+AccessibleStateSet_contains (AccessibleStateSet *obj,
+                             AccessibleState state);
+
+void
+AccessibleStateSet_add (AccessibleStateSet *obj,
+                        AccessibleState state);
+
+void
+AccessibleStateSet_remove (AccessibleStateSet *obj,
+                           AccessibleState state);
+
+SPIBoolean
+AccessibleStateSet_equals (AccessibleStateSet *obj,
+                           AccessibleStateSet *obj2);
+
+AccessibleStateSet *
+AccessibleStateSet_compare (AccessibleStateSet *obj,
+                            AccessibleStateSet *obj2);
+
+SPIBoolean
+AccessibleStateSet_isEmpty (AccessibleStateSet *obj);
+
+void
+AccessibleStreamableContent_ref (AccessibleStreamableContent *obj);
+void
+AccessibleStreamableContent_unref (AccessibleStreamableContent *obj);
+char **
+AccessibleStreamableContent_getContentTypes (AccessibleStreamableContent *obj);
+
+void
+AccessibleStreamableContent_freeContentTypesList (AccessibleStreamableContent *obj,
+                                                char **content_types);
+#define AccessibleStreamableContent_freeContentTypeList(a, b) AccessibleStreamableContent_freeContentTypesList(a,b)
+
+SPIBoolean
+AccessibleStreamableContent_open (AccessibleStreamableContent *obj,
+                                 const char *content_type);
+SPIBoolean
+AccessibleStreamableContent_close (AccessibleStreamableContent *obj);
+
+long
+AccessibleStreamableContent_seek (AccessibleStreamableContent *obj,
+                                 long int offset,
+                                 AccessibleStreamableContentSeekType seek_type);
+SPIBoolean
+AccessibleStreamableContent_read (AccessibleStreamableContent *obj,
+                                 void *buff,
+                                 long int nbytes,
+                                 unsigned int read_type);
+/*
+ *
+ * AccessibleTable function prototypes
+ *
+ */
+
+void AccessibleTable_ref   (AccessibleTable *obj);
+void AccessibleTable_unref (AccessibleTable *obj);
+
+Accessible *
+AccessibleTable_getCaption (AccessibleTable *obj);
+
+Accessible *
+AccessibleTable_getSummary (AccessibleTable *obj);
+
+long
+AccessibleTable_getNRows (AccessibleTable *obj);
+
+long
+AccessibleTable_getNColumns (AccessibleTable *obj);
+
+Accessible *
+AccessibleTable_getAccessibleAt (AccessibleTable *obj,
+                                 long int row,
+                                 long int column);
+
+long
+AccessibleTable_getIndexAt (AccessibleTable *obj,
+                            long int row,
+                            long int column);
+
+long
+AccessibleTable_getRowAtIndex (AccessibleTable *obj,
+                               long int index);
+
+long
+AccessibleTable_getColumnAtIndex (AccessibleTable *obj,
+                                  long int index);
+
+char *
+AccessibleTable_getRowDescription (AccessibleTable *obj,
+                                  long int row);
+
+char *
+AccessibleTable_getColumnDescription (AccessibleTable *obj,
+                                     long int column);
+
+long
+AccessibleTable_getRowExtentAt (AccessibleTable *obj,
+                                long int row,
+                                long int column);
+
+long
+AccessibleTable_getColumnExtentAt (AccessibleTable *obj,
+                                   long int row,
+                                   long int column);
+
+SPIBoolean
+AccessibleTable_getRowColumnExtentsAtIndex (AccessibleTable *obj,
+                                           long int index, long int *row, long int *col, 
+                                           long int *row_extents, long int *col_extents, 
+                                           long int *is_selected);
+
+Accessible *
+AccessibleTable_getRowHeader (AccessibleTable *obj,
+                             long int row);
+
+Accessible *
+AccessibleTable_getColumnHeader (AccessibleTable *obj,
+                                long int column);
+
+long
+AccessibleTable_getNSelectedRows (AccessibleTable *obj);
+
+long
+AccessibleTable_getSelectedRows (AccessibleTable *obj,
+                                 long int **selectedRows);
+
+long
+AccessibleTable_getNSelectedColumns (AccessibleTable *obj);
+
+long
+AccessibleTable_getSelectedColumns (AccessibleTable *obj,
+                                    long int **selectedColumns);
+
+SPIBoolean
+AccessibleTable_isRowSelected (AccessibleTable *obj,
+                               long int row);
+
+SPIBoolean
+AccessibleTable_isColumnSelected (AccessibleTable *obj,
+                                  long int column);
+
+SPIBoolean
+AccessibleTable_isSelected (AccessibleTable *obj,
+                            long int row,
+                            long int column);
+
+SPIBoolean
+AccessibleTable_addRowSelection (AccessibleTable *obj,
+                                long int row);
+SPIBoolean
+AccessibleTable_addColumnSelection (AccessibleTable *obj,
+                                   long int column);
+
+SPIBoolean
+AccessibleTable_removeRowSelection (AccessibleTable *obj,
+                                   long int row);
+SPIBoolean
+AccessibleTable_removeColumnSelection (AccessibleTable *obj,
+                                      long int column);
+
+/*
+ *
+ * AccessibleText function prototypes
+ *
+ */
+
+void AccessibleText_ref   (AccessibleText *obj);
+void AccessibleText_unref (AccessibleText *obj);
+
+long
+AccessibleText_getCharacterCount (AccessibleText *obj);
+
+char *
+AccessibleText_getText (AccessibleText *obj,
+                        long int startOffset,
+                        long int endOffset);
+
+long
+AccessibleText_getCaretOffset (AccessibleText *obj);
+
+char *
+AccessibleText_getAttributes (AccessibleText *obj,
+                                long int offset,
+                                long int *startOffset,
+                                long int *endOffset);
+
+char *
+AccessibleText_getDefaultAttributes (AccessibleText *obj);
+
+SPIBoolean
+AccessibleText_setCaretOffset (AccessibleText *obj,
+                               long int newOffset);
+
+char *
+AccessibleText_getTextBeforeOffset (AccessibleText *obj,
+                                    long int offset,
+                                    AccessibleTextBoundaryType type,
+                                   long int *startOffset,
+                                   long int *endOffset);
+
+char *
+AccessibleText_getTextAtOffset (AccessibleText *obj,
+                               long int offset,
+                               AccessibleTextBoundaryType type,
+                               long int *startOffset,
+                               long int *endOffset);
+
+char *
+AccessibleText_getTextAfterOffset (AccessibleText *obj,
+                                  long int offset,
+                                  AccessibleTextBoundaryType type,
+                                  long int *startOffset,
+                                  long int *endOffset);
+
+unsigned long
+AccessibleText_getCharacterAtOffset (AccessibleText *obj,
+                                     long int offset);
+
+void
+AccessibleText_getCharacterExtents (AccessibleText *obj,
+                                    long int offset,
+                                    long int *x,
+                                    long int *y,
+                                    long int *width,
+                                    long int *height,
+                                   AccessibleCoordType type);
+
+void
+AccessibleText_getRangeExtents (AccessibleText *obj,
+                               long int startOffset,
+                               long int endOffset,
+                               long int *x,
+                               long int *y,
+                               long int *width,
+                               long int *height,
+                               AccessibleCoordType type);
+
+AccessibleTextRange **
+AccessibleText_getBoundedRanges (AccessibleText *obj,
+                                long int x,
+                                long int y,
+                                long int width,
+                                long int height,
+                                AccessibleCoordType type,
+                                AccessibleTextClipType clipTypeX,
+                                AccessibleTextClipType clipTypeY);
+
+void
+AccessibleTextRange_freeRanges (AccessibleTextRange **ranges);
+
+long
+AccessibleText_getOffsetAtPoint (AccessibleText *obj,
+                                 long int x,
+                                 long int y,
+                                AccessibleCoordType type);
+
+long
+AccessibleText_getNSelections (AccessibleText *obj);
+
+void
+AccessibleText_getSelection (AccessibleText *obj,
+                            long int selectionNum,
+                            long int *startOffset,
+                            long int *endOffset);
+
+
+SPIBoolean
+AccessibleText_addSelection (AccessibleText *obj,
+                            long int startOffset,
+                            long int endOffset);
+
+SPIBoolean
+AccessibleText_removeSelection (AccessibleText *obj,
+                               long int selectionNum);
+
+SPIBoolean
+AccessibleText_setSelection (AccessibleText *obj,
+                            long int selectionNum,
+                            long int startOffset,
+                            long int endOffset);
+AccessibleAttributeSet *
+AccessibleText_getAttributeRun  (AccessibleText *obj,
+                                long int offset,
+                                long int *startOffset,
+                                long int *endOffset,
+                                long int includeDefaults);
+AccessibleAttributeSet *
+AccessibleText_getDefaultAttributeSet (AccessibleText *obj);
+
+/* AccessibleValue Function Prototypes:  */
+
+void       AccessibleValue_ref             (AccessibleValue *obj);
+void       AccessibleValue_unref           (AccessibleValue *obj);
+double     AccessibleValue_getMinimumValue (AccessibleValue *obj);
+double     AccessibleValue_getCurrentValue (AccessibleValue *obj);
+double     AccessibleValue_getMaximumValue (AccessibleValue *obj);
+SPIBoolean AccessibleValue_setCurrentValue (AccessibleValue *obj,
+                                           double           newValue);
+double     AccessibleValue_getMinimumIncrement (AccessibleValue *obj);
+
+/* Persistance and lifecycle control for AccessibleEvents. */
+SPIBoolean AccessibleEvent_ref (const AccessibleEvent *e);
+void AccessibleEvent_unref (const AccessibleEvent *e);
+
+/*
+ * Prototypes for accessor functions, to obtain context
+ * information for accessible events.
+ */
+
+char*                  AccessibleEvent_getSourceName (const AccessibleEvent *e);
+AccessibleRole         AccessibleEvent_getSourceRole (const AccessibleEvent *e);
+AccessibleApplication* AccessibleEvent_getSourceApplication (const AccessibleEvent *e);
+SPIBoolean             AccessibleEvent_getSourceDetails (const AccessibleEvent *e, char **name, 
+                                                        AccessibleRole *role, 
+                                                        AccessibleApplication **app);
+
+char*        AccessibleTextChangedEvent_getChangeString (const AccessibleEvent *e);
+Accessible * AccessibleChildChangedEvent_getChildAccessible (const AccessibleEvent *e);
+
+Accessible * AccessibleParentChangedEvent_getParentAccessible (const AccessibleEvent *e);
+
+char*        AccessibleTextSelectionChangedEvent_getSelectionString (const AccessibleEvent *e);
+
+char*        AccessibleWindowEvent_getTitleString (const AccessibleEvent *e);
+
+Accessible * AccessibleActiveDescendantChangedEvent_getActiveDescendant (const AccessibleEvent *e);
+
+Accessible * AccessibleTableSummaryChangedEvent_getSummaryAccessible (const AccessibleEvent *e); 
+
+Accessible * AccessibleTableHeaderChangedEvent_getHeaderAccessible (const AccessibleEvent *e);
+
+char *       AccessibleTableCaptionChangedEvent_getCaptionString (const AccessibleEvent *e);
+
+char *       AccessibleTableRowDescriptionChangedEvent_getDescriptionString (const AccessibleEvent *e);
+
+char *       AccessibleTableColumnDescriptionChangedEvent_getDescriptionString (const AccessibleEvent *e);
+
+char *       AccessibleDescriptionChangedEvent_getDescriptionString (const AccessibleEvent *e);
+
+char *       AccessibleNameChangedEvent_getNameString (const AccessibleEvent *e);
+SPIRect *    AccessibleBoundsChangedEvent_getNewBounds (const AccessibleEvent *e);
+
+/* Misc methods and error handling */
+void SPI_freeString (char *s);
+
+char* SPI_dupString (char *s);
+
+void SPI_freeRect (SPIRect *r);
+
+SPIBoolean SPI_exceptionHandlerPush (SPIExceptionHandler *handler);
+
+SPIExceptionHandler* SPI_exceptionHandlerPop (void);
+
+SPIExceptionType SPIException_getSourceType (SPIException *err);
+
+SPIExceptionCode SPIException_getExceptionCode (SPIException *err);
+
+Accessible* SPIAccessibleException_getSource (SPIException *err);
+
+char* SPIException_getDescription (SPIException *err);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff --git a/cspi/spi_accessible.c b/cspi/spi_accessible.c
new file mode 100644 (file)
index 0000000..958c20c
--- /dev/null
@@ -0,0 +1,1471 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <stdlib.h> /* for malloc */
+#include "spi-stateset.h"
+#include <cspi/spi-private.h>
+
+static const char *role_names [] =
+{
+  "invalid",
+  "accel-label",
+  "alert",
+  "animation",
+  "arrow",
+  "calendar",
+  "canvas",
+  "check-box",
+  "check-menu-item",
+  "color-chooser",
+  "column-header",
+  "combo-box",
+  "date-editor",
+  "desktop-icon",
+  "desktop-frame",
+  "dial",
+  "dialog",
+  "directory-pane",
+  "drawing-area",
+  "file-chooser",
+  "filler",
+  "font-chooser",
+  "frame",
+  "glass-pane",
+  "html-container",
+  "icon",
+  "image",
+  "internalframe",
+  "label",
+  "layered-pane",
+  "list",
+  "list-item",
+  "menu",
+  "menu-bar",
+  "menu-item",
+  "option-pane",
+  "page-tab",
+  "page-tab-list",
+  "panel",
+  "password-text",
+  "popup-menu",
+  "progress-bar",
+  "push-button",
+  "radio-button",
+  "radio-menu-item",
+  "root-pane",
+  "row-header",
+  "scroll-bar",
+  "scroll-pane",
+  "separator",
+  "slider",
+  "spin-button",
+  "split-pane",
+  "statusbar",
+  "table",
+  "table-cell",
+  "table-column-header",
+  "table-row-header",
+  "tear-off-menu-item",
+  "terminal",
+  "text",
+  "toggle-button",
+  "tool-bar",
+  "tool-tip",
+  "tree",
+  "tree-table",
+  "unknown",
+  "viewport",
+  "window",
+  NULL,
+  "header",
+  "fooler",
+  "paragraph",
+  "ruler",
+  "application",
+  "autocomplete",
+  "editbar",
+  "embedded",
+  "entry",
+  "chart",
+  "caption",
+  "document_frame",
+  "heading",
+  "page",
+  "section",
+  "form",
+  "redundant object",
+  "link",
+  "input method window"
+};
+
+#define MAX_ROLES (sizeof (role_names) / sizeof (char *))
+
+static SPIBoolean
+cspi_init_role_table (AccessibleRole *role_table)
+{
+  int i;
+  for (i = 0; i < Accessibility_ROLE_LAST_DEFINED; ++i)
+    {
+      role_table [i] = SPI_ROLE_UNKNOWN;
+    }
+  role_table [Accessibility_ROLE_INVALID] = SPI_ROLE_INVALID;
+  role_table [Accessibility_ROLE_ACCELERATOR_LABEL] = SPI_ROLE_ACCEL_LABEL;
+  role_table [Accessibility_ROLE_ALERT] = SPI_ROLE_ALERT;
+  role_table [Accessibility_ROLE_ANIMATION] = SPI_ROLE_ANIMATION;
+  role_table [Accessibility_ROLE_ARROW] = SPI_ROLE_ARROW;
+  role_table [Accessibility_ROLE_CALENDAR] = SPI_ROLE_CALENDAR;
+  role_table [Accessibility_ROLE_CANVAS] = SPI_ROLE_CANVAS;
+  role_table [Accessibility_ROLE_CHECK_BOX] = SPI_ROLE_CHECK_BOX;
+  role_table [Accessibility_ROLE_CHECK_MENU_ITEM] = SPI_ROLE_CHECK_MENU_ITEM;
+  role_table [Accessibility_ROLE_COLOR_CHOOSER] = SPI_ROLE_COLOR_CHOOSER;
+  role_table [Accessibility_ROLE_COLUMN_HEADER] = SPI_ROLE_COLUMN_HEADER;
+  role_table [Accessibility_ROLE_COMBO_BOX] = SPI_ROLE_COMBO_BOX;
+  role_table [Accessibility_ROLE_DATE_EDITOR] = SPI_ROLE_DATE_EDITOR;
+  role_table [Accessibility_ROLE_DESKTOP_ICON] = SPI_ROLE_DESKTOP_ICON;
+  role_table [Accessibility_ROLE_DESKTOP_FRAME] = SPI_ROLE_DESKTOP_FRAME;
+  role_table [Accessibility_ROLE_DIAL] = SPI_ROLE_DIAL;
+  role_table [Accessibility_ROLE_DIALOG] = SPI_ROLE_DIALOG;
+  role_table [Accessibility_ROLE_DIRECTORY_PANE] = SPI_ROLE_DIRECTORY_PANE;
+  role_table [Accessibility_ROLE_DRAWING_AREA] = SPI_ROLE_DRAWING_AREA;
+  role_table [Accessibility_ROLE_FILE_CHOOSER] = SPI_ROLE_FILE_CHOOSER;
+  role_table [Accessibility_ROLE_FILLER] = SPI_ROLE_FILLER;
+  role_table [Accessibility_ROLE_FONT_CHOOSER] = SPI_ROLE_FONT_CHOOSER;
+  role_table [Accessibility_ROLE_FRAME] = SPI_ROLE_FRAME;
+  role_table [Accessibility_ROLE_GLASS_PANE] = SPI_ROLE_GLASS_PANE;
+  role_table [Accessibility_ROLE_HTML_CONTAINER] = SPI_ROLE_HTML_CONTAINER;
+  role_table [Accessibility_ROLE_ICON] = SPI_ROLE_ICON;
+  role_table [Accessibility_ROLE_IMAGE] = SPI_ROLE_IMAGE;
+  role_table [Accessibility_ROLE_INTERNAL_FRAME] = SPI_ROLE_INTERNAL_FRAME;
+  role_table [Accessibility_ROLE_LABEL] = SPI_ROLE_LABEL;
+  role_table [Accessibility_ROLE_LAYERED_PANE] = SPI_ROLE_LAYERED_PANE;
+  role_table [Accessibility_ROLE_LIST] = SPI_ROLE_LIST;
+  role_table [Accessibility_ROLE_LIST_ITEM] = SPI_ROLE_LIST_ITEM;
+  role_table [Accessibility_ROLE_MENU] = SPI_ROLE_MENU;
+  role_table [Accessibility_ROLE_MENU_BAR] = SPI_ROLE_MENU_BAR;
+  role_table [Accessibility_ROLE_MENU_ITEM] = SPI_ROLE_MENU_ITEM;
+  role_table [Accessibility_ROLE_OPTION_PANE] = SPI_ROLE_OPTION_PANE;
+  role_table [Accessibility_ROLE_PAGE_TAB] = SPI_ROLE_PAGE_TAB;
+  role_table [Accessibility_ROLE_PAGE_TAB_LIST] = SPI_ROLE_PAGE_TAB_LIST;
+  role_table [Accessibility_ROLE_PANEL] = SPI_ROLE_PANEL;
+  role_table [Accessibility_ROLE_PASSWORD_TEXT] = SPI_ROLE_PASSWORD_TEXT;
+  role_table [Accessibility_ROLE_POPUP_MENU] = SPI_ROLE_POPUP_MENU;
+  role_table [Accessibility_ROLE_PROGRESS_BAR] = SPI_ROLE_PROGRESS_BAR;
+  role_table [Accessibility_ROLE_PUSH_BUTTON] = SPI_ROLE_PUSH_BUTTON;
+  role_table [Accessibility_ROLE_RADIO_BUTTON] = SPI_ROLE_RADIO_BUTTON;
+  role_table [Accessibility_ROLE_RADIO_MENU_ITEM] = SPI_ROLE_RADIO_MENU_ITEM;
+  role_table [Accessibility_ROLE_ROOT_PANE] = SPI_ROLE_ROOT_PANE;
+  role_table [Accessibility_ROLE_ROW_HEADER] = SPI_ROLE_ROW_HEADER;
+  role_table [Accessibility_ROLE_SCROLL_BAR] = SPI_ROLE_SCROLL_BAR;
+  role_table [Accessibility_ROLE_SCROLL_PANE] = SPI_ROLE_SCROLL_PANE;
+  role_table [Accessibility_ROLE_SEPARATOR] = SPI_ROLE_SEPARATOR;
+  role_table [Accessibility_ROLE_SLIDER] = SPI_ROLE_SLIDER;
+  role_table [Accessibility_ROLE_SPIN_BUTTON] = SPI_ROLE_SPIN_BUTTON;
+  role_table [Accessibility_ROLE_SPLIT_PANE] = SPI_ROLE_SPLIT_PANE;
+  role_table [Accessibility_ROLE_STATUS_BAR] = SPI_ROLE_STATUS_BAR;
+  role_table [Accessibility_ROLE_TABLE] = SPI_ROLE_TABLE;
+  role_table [Accessibility_ROLE_TABLE_CELL] = SPI_ROLE_TABLE_CELL;
+  role_table[Accessibility_ROLE_TABLE_COLUMN_HEADER] = SPI_ROLE_TABLE_COLUMN_HEADER;
+  role_table[Accessibility_ROLE_TABLE_ROW_HEADER] = SPI_ROLE_TABLE_ROW_HEADER;
+  role_table [Accessibility_ROLE_TEAROFF_MENU_ITEM] = SPI_ROLE_TEAROFF_MENU_ITEM;
+  role_table[Accessibility_ROLE_TERMINAL] = SPI_ROLE_TERMINAL;
+  role_table [Accessibility_ROLE_TEXT] = SPI_ROLE_TEXT;
+  role_table [Accessibility_ROLE_TOGGLE_BUTTON] = SPI_ROLE_TOGGLE_BUTTON;
+  role_table [Accessibility_ROLE_TOOL_BAR] = SPI_ROLE_TOOL_BAR;
+  role_table [Accessibility_ROLE_TOOL_TIP] = SPI_ROLE_TOOL_TIP;
+  role_table [Accessibility_ROLE_TREE] = SPI_ROLE_TREE;
+  role_table [Accessibility_ROLE_TREE_TABLE] = SPI_ROLE_TREE_TABLE;
+  role_table [Accessibility_ROLE_VIEWPORT] = SPI_ROLE_VIEWPORT;
+  role_table [Accessibility_ROLE_WINDOW] = SPI_ROLE_WINDOW;
+  role_table [Accessibility_ROLE_EXTENDED] = SPI_ROLE_EXTENDED;
+  role_table [Accessibility_ROLE_HEADER] = SPI_ROLE_HEADER;
+  role_table [Accessibility_ROLE_FOOTER] = SPI_ROLE_FOOTER;
+  role_table [Accessibility_ROLE_PARAGRAPH] = SPI_ROLE_PARAGRAPH;
+  role_table [Accessibility_ROLE_RULER] = SPI_ROLE_RULER;
+  role_table [Accessibility_ROLE_APPLICATION] = SPI_ROLE_APPLICATION;
+  role_table [Accessibility_ROLE_AUTOCOMPLETE] = SPI_ROLE_AUTOCOMPLETE;
+  role_table [Accessibility_ROLE_EDITBAR] = SPI_ROLE_EDITBAR;
+  role_table [Accessibility_ROLE_EMBEDDED] = SPI_ROLE_EMBEDDED;
+  role_table [Accessibility_ROLE_ENTRY] = SPI_ROLE_ENTRY;
+  role_table [Accessibility_ROLE_CHART] = SPI_ROLE_CHART;
+  role_table [Accessibility_ROLE_CAPTION] = SPI_ROLE_CAPTION;
+  role_table [Accessibility_ROLE_DOCUMENT_FRAME] = SPI_ROLE_DOCUMENT_FRAME;
+  role_table [Accessibility_ROLE_HEADING] = SPI_ROLE_HEADING;
+  role_table [Accessibility_ROLE_PAGE] = SPI_ROLE_PAGE;
+  role_table [Accessibility_ROLE_SECTION] = SPI_ROLE_SECTION;
+  role_table [Accessibility_ROLE_FORM] = SPI_ROLE_FORM;
+  role_table [Accessibility_ROLE_REDUNDANT_OBJECT] = SPI_ROLE_REDUNDANT_OBJECT;
+  role_table [Accessibility_ROLE_LINK] = SPI_ROLE_LINK;
+  role_table [Accessibility_ROLE_INPUT_METHOD_WINDOW] = SPI_ROLE_INPUT_METHOD_WINDOW;
+
+  return TRUE;
+}
+
+AccessibleRole
+cspi_role_from_spi_role (Accessibility_Role role)
+{
+  /* array is sized according to IDL roles because IDL roles are the index */  
+  static AccessibleRole cspi_role_table [Accessibility_ROLE_LAST_DEFINED];
+  static SPIBoolean is_initialized = FALSE;
+  AccessibleRole cspi_role;
+  if (!is_initialized)
+    {
+      is_initialized = cspi_init_role_table (cspi_role_table);     
+    }
+  if (role >= 0 && role < Accessibility_ROLE_LAST_DEFINED)
+    {
+      cspi_role = cspi_role_table [role];          
+    }
+  else
+    {
+      cspi_role = SPI_ROLE_EXTENDED;
+    }
+  return cspi_role; 
+}
+
+AccessibleAttributeSet *
+_cspi_attribute_set_from_sequence (const GArray *seq)
+{
+    AccessibleAttributeSet *set = g_new0 (AccessibleAttributeSet, 1);
+    int i;
+
+    set->len = seq->len;
+    set->attributes = g_new0 (char *, set->len);
+    for (i = 0; i < set->len; ++i)
+    {
+       set->attributes[i] = g_array_index (seq, char *, i);
+    }
+
+  g_array_free (seq, TRUE);
+    return set;
+}
+
+/**
+ * AccessibleRole_getName:
+ * @role: an #AccessibleRole object to query.
+ *
+ * Get a localizeable string that indicates the name of an #AccessibleRole.
+ * <em>DEPRECATED.</em>
+ *
+ * Returns: a localizable string name for an #AccessibleRole enumerated type.
+ **/
+char *
+AccessibleRole_getName (AccessibleRole role)
+{
+  if (role < MAX_ROLES && role_names [(int) role])
+    {
+      return g_strdup (role_names [(int) role]);
+    }
+  else
+    {
+      return g_strdup ("");
+    }
+}
+
+/**
+ * Accessible_ref:
+ * @obj: a pointer to the #Accessible object on which to operate.
+ *
+ * Increment the reference count for an #Accessible object.
+ **/
+void
+Accessible_ref (Accessible *obj)
+{
+  cspi_object_ref (obj);
+}
+
+/**
+ * Accessible_unref:
+ * @obj: a pointer to the #Accessible object on which to operate.
+ *
+ * Decrement the reference count for an #Accessible object.
+ **/
+void
+Accessible_unref (Accessible *obj)
+{
+  cspi_object_unref (obj);
+}
+
+/**
+ * Accessible_getName:
+ * @obj: a pointer to the #Accessible object on which to operate.
+ *
+ * Get the name of an #Accessible object.
+ *
+ * Returns: a UTF-8 string indicating the name of the #Accessible object.
+ * or NULL on exception
+ **/
+char *
+Accessible_getName (Accessible *obj)
+{
+  cspi_return_val_if_fail (obj != NULL, NULL);
+  return g_strdup (obj->name);
+}
+
+/**
+ * Accessible_getDescription:
+ * @obj: a pointer to the #Accessible object on which to operate.
+ *
+ * Get the description of an #Accessible object.
+ *
+ * Returns: a UTF-8 string describing the #Accessible object.
+ * or NULL on exception
+ **/
+char *
+Accessible_getDescription (Accessible *obj)
+{
+  cspi_return_val_if_fail (obj != NULL, NULL);
+
+  return g_strdup (obj->description);
+}
+
+/**
+ * Accessible_getParent:
+ * @obj: a pointer to the #Accessible object to query.
+ *
+ * Get an #Accessible object's parent container.
+ *
+ * Returns: a pointer tothe #Accessible object which contains the given
+ *          #Accessible instance, or NULL if the @obj has no parent container.
+ *
+ **/
+Accessible *
+Accessible_getParent (Accessible *obj)
+{
+  cspi_return_val_if_fail (obj != NULL, NULL);
+
+  return cspi_object_add (obj->parent);
+}
+
+/**
+ * Accessible_getChildCount:
+ * @obj: a pointer to the #Accessible object on which to operate.
+ *
+ * Get the number of children contained by an #Accessible object.
+ *
+ * Returns: a #long indicating the number of #Accessible children
+ *          contained by an #Accessible object. or -1 on exception
+ *
+ **/
+long
+Accessible_getChildCount (Accessible *obj)
+{
+  cspi_return_val_if_fail (obj != NULL, -1);
+
+  return g_list_length (obj->children);
+}
+
+/**
+ * Accessible_getChildAtIndex:
+ * @obj: a pointer to the #Accessible object on which to operate.
+ * @childIndex: a #long indicating which child is specified.
+ *
+ * Get the #Accessible child of an #Accessible object at a given index.
+ *
+ * Returns: a pointer to the #Accessible child object at index
+ *          @childIndex. or NULL on exception
+ **/
+Accessible *
+Accessible_getChildAtIndex (Accessible *obj,
+                            long int    childIndex)
+{
+  Accessible *child;
+
+  cspi_return_val_if_fail (obj != NULL, NULL);
+
+  child = g_list_nth_data (obj->children, childIndex);
+  return cspi_object_add(child);
+}
+
+/**
+ * Accessible_getIndexInParent:
+ * @obj: a pointer to the #Accessible object on which to operate.
+ *
+ * Get the index of an #Accessible object in its containing #Accessible.
+ *
+ * Returns: a #long indicating the index of the #Accessible object
+ *          in its parent (i.e. containing) #Accessible instance,
+ *          or -1 if @obj has no containing parent or on exception.
+ **/
+long
+Accessible_getIndexInParent (Accessible *obj)
+{
+  GList *l;
+  gint i;
+
+  cspi_return_val_if_fail (obj != NULL, -1);
+  if (!obj->parent) return -1;
+  l = obj->parent->children;
+  while (l)
+  {
+    if (l->data == obj) return i;
+    l = g_list_next (l);
+    i++;
+  }
+  return -1;
+}
+
+typedef struct
+{
+  dbus_uint32_t type;
+  GArray *targets;
+} Accessibility_Relation;
+
+/**
+ * Accessible_getRelationSet:
+ * @obj: a pointer to the #Accessible object on which to operate.
+ *
+ * Get the set of #AccessibleRelation objects which describe this #Accessible object's
+ *       relationships with other #Accessible objects.
+ *
+ * Returns: an array of #AccessibleRelation pointers. or NULL on exception
+ **/
+AccessibleRelation **
+Accessible_getRelationSet (Accessible *obj)
+{
+  int i;
+  int n_relations;
+  AccessibleRelation **relations;
+  GArray *relation_set;
+  DBusError error;
+
+  cspi_return_val_if_fail (obj != NULL, NULL);
+
+  g_assert (!cspi_exception ());
+
+  dbus_error_init (&error);
+  cspi_dbus_call (obj, spi_interface_accessible, "getAttributes", &error, "=>a(uao)", &relation_set);
+
+  cspi_return_val_if_ev ("getRelationSet", NULL); 
+  
+  n_relations = relation_set->len;
+  relations = malloc (sizeof (AccessibleRelation *) * (n_relations + 1));
+  
+  for (i = 0; i < n_relations; ++i)
+    {
+      Accessibility_Relation *r = g_array_index (relation_set, Accessibility_Relation *, i);
+      relations[i] = g_new (AccessibleRelation, 1);
+      if (!relations[i]) continue;
+      relations[i]->ref_count = 1;
+      relations[i]->type = r->type;
+      relations[i]->targets = r->targets;
+    }
+  relations[i] = NULL;
+
+  g_array_free (relation_set, TRUE);
+
+  return relations;
+}
+
+/**
+ * Accessible_getRole:
+ * @obj: a pointer to the #Accessible object on which to operate.
+ *
+ * Get the UI role of an #Accessible object.
+ * A UTF-8 string describing this role can be obtained via Accessible_getRoleName ().
+ *
+ * Returns: the #AccessibleRole of the object.
+ *
+ **/
+AccessibleRole
+Accessible_getRole (Accessible *obj)
+{
+  cspi_return_val_if_fail (obj != NULL, SPI_ROLE_INVALID);
+
+  return obj->role;
+}
+
+/**
+ * Accessible_getRoleName:
+ * @obj: a pointer to the #Accessible object on which to operate.
+ *
+ * Get a UTF-8 string describing the role this object plays in the UI.
+ * This method will return useful values for roles that fall outside the
+ * enumeration used in Accessible_getRole ().
+ *
+ * Returns: a UTF-8 string specifying the role of this #Accessible object.
+ *
+ **/
+char *
+Accessible_getRoleName (Accessible *obj)
+{
+  char *retval;
+
+  cspi_return_val_if_fail (obj != NULL, g_strdup ("invalid"));
+
+  cspi_dbus_call (obj, spi_interface_accessible, "getRoleName", NULL, "=>s", &retval);
+
+  cspi_return_val_if_ev ("getRoleName", g_strdup ("invalid")); 
+
+  return retval;
+}
+
+/**
+ * Accessible_getLocalizedRoleName:
+ * @obj: a pointer to the #Accessible object on which to operate.
+ *
+ * Get a UTF-8 string describing the (localized) role this object plays in the UI.
+ * This method will return useful values for roles that fall outside the
+ * enumeration used in Accessible_getRole ().
+ *
+ * @Since: AT-SPI 1.4
+ *
+ * Returns: a UTF-8 string specifying the role of this #Accessible object.
+ *
+ **/
+char *
+Accessible_getLocalizedRoleName (Accessible *obj)
+{
+  char *retval;
+
+  cspi_return_val_if_fail (obj != NULL, g_strdup ("invalid"));
+
+  cspi_dbus_call (obj, spi_interface_accessible, "getLocalizedRoleName", NULL, "=>s", &retval);
+
+  cspi_return_val_if_ev ("getLocalizedRoleName", g_strdup ("invalid")); 
+
+  return retval;
+}
+
+/**
+ * Accessible_getStateSet:
+ * @obj: a pointer to the #Accessible object on which to operate.
+ *
+ * Gets the current state of an object.
+ *
+ * Returns: a pointer to an #AccessibleStateSet representing the object's current state.
+ **/
+AccessibleStateSet *
+Accessible_getStateSet (Accessible *obj)
+{
+  GArray *state_bitflags;
+  AccessibleStateSet *retval;
+
+  cspi_return_val_if_fail (obj != NULL, NULL);
+
+  cspi_dbus_call (obj, spi_interface_accessible, "getStateSet", NULL, "=>au", &state_bitflags);
+  cspi_return_val_if_ev ("getState", NULL);
+
+  retval = spi_state_set_cache_new (state_bitflags);
+
+  g_array_free (state_bitflags, TRUE);
+
+  return retval;
+}
+
+/**
+ * Accessible_getAttributes:
+ * @obj: The #Accessible being queried.
+ *
+ * Get the #AttributeSet representing any assigned 
+ * name-value pair attributes or annotations for this object.
+ * For typographic, textual, or textually-semantic attributes, see
+ * AccessibleText_getAttributes instead.
+ *
+ * Returns: The name-value-pair attributes assigned to this object.
+ */
+AccessibleAttributeSet *
+Accessible_getAttributes (Accessible *obj)
+{
+    AccessibleAttributeSet *retval;
+  GArray *dbus_seq;
+
+    cspi_return_val_if_fail (obj != NULL, NULL);
+
+  cspi_dbus_call (obj, spi_interface_accessible, "getAttributes", NULL, "=>as", &dbus_seq);
+
+    cspi_return_val_if_ev ("getAttributes", NULL);
+    
+    retval = _cspi_attribute_set_from_sequence (dbus_seq);
+
+    return retval;
+}
+
+/**
+ * Accessible_getHostApplication:
+ * @obj: The #Accessible being queried.
+ *
+ * Get the containing #AccessibleApplication for an object.
+ *
+ * Returns: the containing AccessibleApplication instance for this object.
+ */
+AccessibleApplication *
+Accessible_getHostApplication (Accessible *obj)
+{
+  while (obj->parent) obj = obj->parent;
+  return obj;
+}
+
+/* Interface query methods */
+
+/**
+ * Accessible_isAction:
+ * @obj: a pointer to the #Accessible instance to query.
+ *
+ * Query whether the specified #Accessible implements #AccessibleAction.
+ *
+ * Returns: #TRUE if @obj implements the #AccessibleAction interface,
+ *          #FALSE otherwise.
+ **/
+SPIBoolean
+Accessible_isAction (Accessible *obj)
+{
+  return cspi_accessible_is_a (obj,
+                             spi_interface_action);
+}
+
+/**
+ * Accessible_isApplication:
+ * @obj: a pointer to the #Accessible instance to query.
+ *
+ * Query whether the specified #Accessible implements #AccessibleApplication.
+ *
+ * Returns: #TRUE if @obj implements the #AccessibleApplication interface,
+ *          #FALSE otherwise.
+ **/
+SPIBoolean
+Accessible_isApplication (Accessible *obj)
+{
+  return cspi_accessible_is_a (obj,
+                             spi_interface_application);
+}
+
+/**                      
+ * Accessible_isCollection:                                                                                                                                                                          * @obj: a pointer to the #Accessible instance to query.                                                                                                                                          
+ *                          
+ * Query whether the specified #Accessible implements #AccessibleCollection.    
+ * Returns: #TRUE if @obj implements the #AccessibleCollection interface,                                                                                                               
+ *          #FALSE otherwise.
+ **/
+
+SPIBoolean
+Accessible_isCollection (Accessible *obj)
+{
+#if 0
+     g_warning ("Collections not implemented");
+     return cspi_accessible_is_a (obj,
+                             spi_interface_collection);
+#else
+     return FALSE;
+#endif
+}
+
+/**
+ * Accessible_isComponent:
+ * @obj: a pointer to the #Accessible instance to query.
+ *
+ * Query whether the specified #Accessible implements #AccessibleComponent.
+ *
+ * Returns: #TRUE if @obj implements the #AccessibleComponent interface,
+ *          #FALSE otherwise.
+ **/
+SPIBoolean
+Accessible_isComponent (Accessible *obj)
+{
+  return cspi_accessible_is_a (obj,
+                             spi_interface_component);
+}
+
+/**
+ * Accessible_isDocument:
+ * @obj: a pointer to the #Accessible instance to query.
+ *
+ * Query whether the specified #Accessible implements #AccessibleDocument.
+ *
+ * Returns: #TRUE if @obj implements the #AccessibleDocument interface,
+ *          #FALSE otherwise.
+ **/
+SPIBoolean
+Accessible_isDocument (Accessible *obj)
+{
+  return cspi_accessible_is_a (obj,
+                             spi_interface_document);
+}
+
+/**
+ * Accessible_isEditableText:
+ * @obj: a pointer to the #Accessible instance to query.
+ *
+ * Query whether the specified #Accessible implements #AccessibleEditableText.
+ *
+ * Returns: #TRUE if @obj implements the #AccessibleEditableText interface,
+ *          #FALSE otherwise.
+ **/
+SPIBoolean
+Accessible_isEditableText (Accessible *obj)
+{
+  return cspi_accessible_is_a (obj,
+                             spi_interface_editable_text);
+}
+                                                                                                                                                                        
+/**
+ * Accessible_isMatchRule:
+ * @obj: a pointer to the #Accessible instance to query.
+ *
+ * Query whether the specified #Accessible implements #AccessibleMatchRule.
+ *
+ * Returns: #TRUE if @obj implements the #AccessibleMatchRule interface,
+ *          #FALSE otherwise.
+ **/
+SPIBoolean
+Accessible_isMatchRule (Accessible *obj)
+{
+#if 0
+     return cspi_accessible_is_a (obj, 
+                                 spi_interface_match_rule);
+#else
+     g_warning ("Match rules not implemented");
+     return FALSE;
+#endif
+}
+
+/**
+ * Accessible_isHypertext:
+ * @obj: a pointer to the #Accessible instance to query.
+ *
+ * Query whether the specified #Accessible implements #AccessibleHypertext.
+ *
+ * Returns: #TRUE if @obj implements the #AccessibleHypertext interface,
+ *          #FALSE otherwise.
+ **/
+SPIBoolean
+Accessible_isHypertext (Accessible *obj)
+{
+  return cspi_accessible_is_a (obj,
+                             spi_interface_hypertext);
+}
+
+/**
+ * Accessible_isImage:
+ * @obj: a pointer to the #Accessible instance to query.
+ *
+ * Query whether the specified #Accessible implements #AccessibleImage.
+ *
+ * Returns: #TRUE if @obj implements the #AccessibleImage interface,
+ *          #FALSE otherwise.
+**/
+SPIBoolean
+Accessible_isImage (Accessible *obj)
+{
+  return cspi_accessible_is_a (obj,
+                             spi_interface_image);
+}
+
+/**
+ * Accessible_isSelection:
+ * @obj: a pointer to the #Accessible instance to query.
+ *
+ * Query whether the specified #Accessible implements #AccessibleSelection.
+ *
+ * Returns: #TRUE if @obj implements the #AccessibleSelection interface,
+ *          #FALSE otherwise.
+**/
+SPIBoolean
+Accessible_isSelection (Accessible *obj)
+{
+  return cspi_accessible_is_a (obj,
+                             spi_interface_selection);
+}
+
+/**
+ * Accessible_isTable:
+ * @obj: a pointer to the #Accessible instance to query.
+ *
+ * Query whether the specified #Accessible implements #AccessibleTable.
+ *
+ * Returns: #TRUE if @obj implements the #AccessibleTable interface,
+ *          #FALSE otherwise.
+**/
+SPIBoolean
+Accessible_isTable (Accessible *obj)
+{
+  return cspi_accessible_is_a (obj,
+                             spi_interface_table);
+}
+
+/**
+ * Accessible_isStreamableContent:
+ * @obj: a pointer to the #Accessible instance to query.
+ *
+ * Query whether the specified #Accessible implements
+ *          #AccessibleStreamableContent.
+ *
+ * Returns: #TRUE if @obj implements the #AccessibleStreamableContent interface,
+ *          #FALSE otherwise.
+**/
+SPIBoolean
+Accessible_isStreamableContent (Accessible *obj)
+{
+#if 0
+  return cspi_accessible_is_a (obj,
+                             spi_interface_streamable_content);
+#else
+  g_warning ("Streamable content not implemented");
+  return FALSE;
+#endif
+}
+
+/**
+ * Accessible_isText:
+ * @obj: a pointer to the #Accessible instance to query.
+ *
+ * Query whether the specified #Accessible implements #AccessibleText.
+ *
+ * Returns: #TRUE if @obj implements the #AccessibleText interface,
+ *          #FALSE otherwise.
+**/
+SPIBoolean
+Accessible_isText (Accessible *obj)
+{
+  return cspi_accessible_is_a (obj,
+                             spi_interface_text);
+}
+
+/**
+ * Accessible_isValue:
+ * @obj: a pointer to the #Accessible instance to query.
+ *
+ * Query whether the specified #Accessible implements #AccessibleValue.
+ *
+ * Returns: #TRUE if @obj implements the #AccessibleValue interface,
+ *          #FALSE otherwise.
+**/
+SPIBoolean
+Accessible_isValue (Accessible *obj)
+{
+  return cspi_accessible_is_a (obj,
+                             spi_interface_value);
+}
+
+/**
+ * Accessible_getApplication:
+ * @obj: a pointer to the #Accessible instance to query.
+ *
+ * Get the #AccessibleApplication interface for an #Accessible.
+ *
+ * Returns: a pointer to an #AccessibleApplication interface instance, or
+ *          NULL if @obj does not implement #AccessibleApplication.
+ **/
+AccessibleApplication *
+Accessible_getApplication (Accessible *obj)
+{
+  return (AccessibleApplication *) Accessible_queryInterface (
+         obj, spi_interface_application);
+}
+
+/**
+ * Accessible_getAction:
+ * @obj: a pointer to the #Accessible instance to query.
+ *
+ * Get the #AccessibleAction interface for an #Accessible.
+ *
+ * Returns: a pointer to an #AccessibleAction interface instance, or
+ *          NULL if @obj does not implement #AccessibleAction.
+ **/
+AccessibleAction *
+Accessible_getAction (Accessible *obj)
+{
+  return (AccessibleAction *) Accessible_queryInterface (
+         obj, spi_interface_action);
+}
+
+
+/**
+ * Accessible_getCollection:
+ * @obj: a pointer to the #Accessible instance to query.
+ *
+ * Get the #AccessibleCollection interface for an #Accessible.
+ *
+ * Returns: a pointer to an #AccessibleCollection interface instance, or
+ *          NULL if @obj does not implement #AccessibleCollection.
+ **/
+AccessibleCollection *
+Accessible_getCollection (Accessible *obj)
+{
+#if 0
+  return (AccessibleCollection *) Accessible_queryInterface (
+         obj, spi_interface_collection);
+#else
+  g_warning ("Collections not implemented");
+#endif
+}
+
+/**
+ * Accessible_getComponent:
+ * @obj: a pointer to the #Accessible instance to query.
+ *
+ * Get the #AccessibleComponent interface for an #Accessible.
+ *
+ * Returns: a pointer to an #AccessibleComponent interface instance, or
+ *          NULL if @obj does not implement #AccessibleComponent.
+ **/
+AccessibleComponent *
+Accessible_getComponent (Accessible *obj)
+{
+  return (AccessibleComponent *) Accessible_queryInterface (
+         obj, spi_interface_component);
+}
+
+/**
+ * Accessible_getDocument:
+ * @obj: a pointer to the #Accessible instance to query.
+ *
+ * Get the #AccessibleDocument interface for an #Accessible.
+ *
+ * Returns: a pointer to an #AccessibleDocument interface instance, or
+ *          NULL if @obj does not implement #AccessibleDocument.
+ **/
+AccessibleDocument *
+Accessible_getDocument (Accessible *obj)
+{
+  return (AccessibleDocument *) Accessible_queryInterface (
+         obj, spi_interface_document);
+}
+
+/**
+ * Accessible_getEditableText:
+ * @obj: a pointer to the #Accessible instance to query.
+ *
+ * Get the #AccessibleEditableText interface for an #Accessible.
+ *
+ * Returns: a pointer to an #AccessibleEditableText interface instance, or
+ *          NULL if @obj does not implement #AccessibleEditableText.
+ **/
+AccessibleEditableText *
+Accessible_getEditableText (Accessible *obj)
+{
+  return (AccessibleEditableText *) Accessible_queryInterface (
+         obj, spi_interface_editable_text);
+}
+
+
+/**
+ * Accessible_getHypertext:
+ * @obj: a pointer to the #Accessible instance to query.
+ *
+ * Get the #AccessibleHypertext interface for an #Accessible.
+ *
+ * Returns: a pointer to an #AccessibleHypertext interface instance, or
+ *          NULL if @obj does not implement #AccessibleHypertext.
+ **/
+AccessibleHypertext *
+Accessible_getHypertext (Accessible *obj)
+{
+  return (AccessibleHypertext *) Accessible_queryInterface (
+         obj, spi_interface_hypertext);
+}
+
+
+
+/**
+ * Accessible_getImage:
+ * @obj: a pointer to the #Accessible instance to query.
+ *
+ * Get the #AccessibleImage interface for an #Accessible.
+ *
+ * Returns: a pointer to an #AccessibleImage interface instance, or
+ *          NULL if @obj does not implement #AccessibleImage.
+ **/
+AccessibleImage *
+Accessible_getImage (Accessible *obj)
+{
+  return (AccessibleImage *) Accessible_queryInterface (
+         obj, spi_interface_image);
+}
+
+/**
+ * Accessible_getMatchRule:
+ * @obj: a pointer to the #Accessible instance to query.
+ *
+ * Get the #AccessibleMatchRule interface for an #Accessible.
+ *
+ * Returns: a pointer to an #AccessibleMatchRule interface instance, or
+ *          NULL if @obj does not implement #AccessibleMatchRule.
+ **/
+AccessibleMatchRule *
+Accessible_getMatchRule (Accessible *obj)
+{
+#if 0
+  return (AccessibleMatchRule *) Accessible_queryInterface (
+         obj, spi_interface_match_rule);
+#else
+  g_warning ("Match rules not supported");
+#endif
+}
+
+/**
+ * Accessible_getSelection:
+ * @obj: a pointer to the #Accessible instance to query.
+ *
+ * Get the #AccessibleSelection interface for an #Accessible.
+ *
+ * Returns: a pointer to an #AccessibleSelection interface instance, or
+ *          NULL if @obj does not implement #AccessibleSelection.
+ **/
+AccessibleSelection *
+Accessible_getSelection (Accessible *obj)
+{
+  return (AccessibleSelection *) Accessible_queryInterface (
+         obj, spi_interface_selection);
+}
+
+
+
+/**
+ * Accessible_getStreamableContent:
+ * @obj: a pointer to the #Accessible instance to query.
+ *
+ * Get the #AccessibleStreamableContent interface for an #Accessible.
+ *
+ * Returns: a pointer to an #AccessibleStreamableContent interface instance, or
+ *          NULL if @obj does not implement #AccessibleStreamableContent.
+ **/
+AccessibleStreamableContent *
+Accessible_getStreamableContent (Accessible *obj)
+{
+#if 0
+  return (AccessibleStreamableContent *) Accessible_queryInterface (
+         obj, spi_interface_streamable_content);
+#else
+  g_warning ("Streamable content not supported");
+#endif
+}
+
+/**
+ * Accessible_getTable:
+ * @obj: a pointer to the #Accessible instance to query.
+ *
+ * Get the #AccessibleTable interface for an #Accessible.
+ *
+ * Returns: a pointer to an #AccessibleTable interface instance, or
+ *          NULL if @obj does not implement #AccessibleTable.
+ **/
+AccessibleTable *
+Accessible_getTable (Accessible *obj)
+{
+  return (AccessibleTable *) Accessible_queryInterface (
+         obj, spi_interface_table);
+}
+
+/**
+ * Accessible_getText:
+ * @obj: a pointer to the #Accessible instance to query.
+ *
+ * Get the #AccessibleText interface for an #Accessible.
+ *
+ * Returns: a pointer to an #AccessibleText interface instance, or
+ *          NULL if @obj does not implement #AccessibleText.
+ **/
+AccessibleText *
+Accessible_getText (Accessible *obj)
+{
+  return (AccessibleText *) Accessible_queryInterface (
+         obj, spi_interface_text);
+}
+
+
+
+/**
+ * Accessible_getValue:
+ * @obj: a pointer to the #Accessible instance to query.
+ *
+ * Get the #AccessibleValue interface for an #Accessible.
+ *
+ * Returns: a pointer to an #AccessibleValue interface instance, or
+ *          NULL if @obj does not implement #AccessibleValue.
+ **/
+AccessibleValue *
+Accessible_getValue (Accessible *obj)
+{
+  return (AccessibleValue *) Accessible_queryInterface (
+         obj, spi_interface_value);
+}
+
+
+
+/**
+ * Accessible_queryInterface:
+ * @obj: a pointer to the #Accessible instance to query.
+ * @interface_name: a UTF-8 character string specifiying the requested interface.
+ *
+ * Query an #Accessible object to for a named interface.
+ *
+ * Returns: an instance of the named interface object, if it is implemented
+ *          by @obj, or NULL otherwise.
+ *
+ **/
+AccessibleUnknown *
+Accessible_queryInterface (Accessible *obj,
+                          const char *interface_name)
+{
+  if (cspi_accessible_is_a (obj, interface_name))
+  {
+    /* The original code called cspi_object_add(obj) instead, but gok and
+     * simple-at don't treat interfaces as references, so I'm confused
+     * and not going to replicate this bit of code */
+    return obj;
+  }
+  return NULL;
+}
+
+
+/**
+ * AccessibleRelation_ref:
+ * @obj: a pointer to the #AccessibleRelation object on which to operate.
+ *
+ * Increment the reference count for an #AccessibleRelation object.
+ *
+ **/
+void
+AccessibleRelation_ref (AccessibleRelation *obj)
+{
+  obj->ref_count++;
+}
+
+/**
+ * AccessibleRelation_unref:
+ * @obj: a pointer to the #AccessibleRelation object on which to operate.
+ *
+ * Decrement the reference count for an #AccessibleRelation object.
+ *
+ **/
+void
+AccessibleRelation_unref (AccessibleRelation *obj)
+{
+  obj->ref_count--;
+  if (obj->ref_count <= 0)
+  {
+    g_array_free (obj->targets, TRUE);
+    g_free (obj);
+  }
+}
+
+static SPIBoolean
+cspi_init_relation_type_table (AccessibleRelationType *relation_type_table)
+{
+  int i;
+  for (i = 0; i < Accessibility_RELATION_LAST_DEFINED; ++i)
+    {
+      relation_type_table [i] = SPI_RELATION_NULL;
+    }
+  relation_type_table [Accessibility_RELATION_NULL] = SPI_RELATION_NULL;
+  relation_type_table [Accessibility_RELATION_LABEL_FOR] = SPI_RELATION_LABEL_FOR;
+  relation_type_table [Accessibility_RELATION_LABELLED_BY] = SPI_RELATION_LABELED_BY;
+  relation_type_table [Accessibility_RELATION_CONTROLLER_FOR] = SPI_RELATION_CONTROLLER_FOR;
+  relation_type_table [Accessibility_RELATION_CONTROLLED_BY] = SPI_RELATION_CONTROLLED_BY;
+  relation_type_table [Accessibility_RELATION_MEMBER_OF] = SPI_RELATION_MEMBER_OF;
+  relation_type_table [Accessibility_RELATION_TOOLTIP_FOR] = SPI_RELATION_NULL;
+  relation_type_table [Accessibility_RELATION_NODE_CHILD_OF] = SPI_RELATION_NODE_CHILD_OF;
+  relation_type_table [Accessibility_RELATION_EXTENDED] = SPI_RELATION_EXTENDED;
+  relation_type_table [Accessibility_RELATION_FLOWS_TO] = SPI_RELATION_FLOWS_TO;
+  relation_type_table [Accessibility_RELATION_FLOWS_FROM] = SPI_RELATION_FLOWS_FROM;
+  relation_type_table [Accessibility_RELATION_SUBWINDOW_OF] = SPI_RELATION_SUBWINDOW_OF;
+  relation_type_table [Accessibility_RELATION_EMBEDS] = SPI_RELATION_EMBEDS;
+  relation_type_table [Accessibility_RELATION_EMBEDDED_BY] = SPI_RELATION_EMBEDDED_BY;
+  relation_type_table [Accessibility_RELATION_POPUP_FOR] = SPI_RELATION_POPUP_FOR;
+  relation_type_table [Accessibility_RELATION_PARENT_WINDOW_OF] = SPI_RELATION_PARENT_WINDOW_OF;
+  relation_type_table [Accessibility_RELATION_DESCRIBED_BY] = SPI_RELATION_DESCRIBED_BY;
+  relation_type_table [Accessibility_RELATION_DESCRIPTION_FOR] = SPI_RELATION_DESCRIPTION_FOR;
+  return TRUE;
+}
+
+static AccessibleRelationType
+cspi_relation_type_from_spi_relation_type (Accessibility_RelationType type)
+{
+  /* array is sized according to IDL RelationType because IDL RelationTypes are the index */   
+  static AccessibleRelationType cspi_relation_type_table [Accessibility_RELATION_LAST_DEFINED];
+  static SPIBoolean is_initialized = FALSE;
+  AccessibleRelationType cspi_type;
+  if (!is_initialized)
+    {
+      is_initialized = cspi_init_relation_type_table (cspi_relation_type_table);           
+    }
+  if (type >= 0 && type < Accessibility_RELATION_LAST_DEFINED)
+    {
+      cspi_type = cspi_relation_type_table [type];         
+    }
+  else
+    {
+      cspi_type = SPI_RELATION_NULL;
+    }
+  return cspi_type; 
+}
+/**
+ * AccessibleRelation_getRelationType:
+ * @obj: a pointer to the #AccessibleRelation object to query.
+ *
+ * Get the type of relationship represented by an #AccessibleRelation.
+ *
+ * Returns: an #AccessibleRelationType indicating the type of relation
+ *         encapsulated in this #AccessibleRelation object.
+ *
+ **/
+AccessibleRelationType
+AccessibleRelation_getRelationType (AccessibleRelation *obj)
+{
+  cspi_return_val_if_fail (obj, SPI_RELATION_NULL);
+  return cspi_relation_type_from_spi_relation_type (obj->type);
+}
+
+/**
+ * AccessibleRelation_getNTargets:
+ * @obj: a pointer to the #AccessibleRelation object to query.
+ *
+ * Get the number of objects which this relationship has as its
+ *       target objects (the subject is the #Accessible from which this
+ *       #AccessibleRelation originated).
+ *
+ * Returns: a short integer indicating how many target objects which the
+ *       originating #Accessible object has the #AccessibleRelation
+ *       relationship with.
+ **/
+int
+AccessibleRelation_getNTargets (AccessibleRelation *obj)
+{
+  cspi_return_val_if_fail (obj, -1);
+  return obj->targets->len;
+}
+
+/**
+ * AccessibleRelation_getTarget:
+ * @obj: a pointer to the #AccessibleRelation object to query.
+ * @i: a (zero-index) integer indicating which (of possibly several) target is requested.
+ *
+ * Get the @i-th target of a specified #AccessibleRelation relationship.
+ *
+ * Returns: an #Accessible which is the @i-th object with which the
+ *      originating #Accessible has relationship specified in the
+ *      #AccessibleRelation object.
+ *
+ **/
+Accessible *
+AccessibleRelation_getTarget (AccessibleRelation *obj, int i)
+{
+  cspi_return_val_if_fail (obj, NULL);
+
+  if (i < 0 || i >= obj->targets->len) return NULL;
+  return cspi_object_add (
+                        g_array_index (obj->targets, Accessible *, i));
+}
+
+/**
+ * AccessibleStateSet_ref:
+ * @obj: a pointer to the #AccessibleStateSet object on which to operate.
+ *
+ * Increment the reference count for an #AccessibleStateSet object.
+ *
+ **/
+void
+AccessibleStateSet_ref (AccessibleStateSet *obj)
+{
+  spi_state_set_cache_ref (obj);
+}
+
+/**
+ * AccessibleStateSet_unref:
+ * @obj: a pointer to the #AccessibleStateSet object on which to operate.
+ *
+ * Decrement the reference count for an #AccessibleStateSet object.
+ *
+ **/
+void
+AccessibleStateSet_unref (AccessibleStateSet *obj)
+{
+  spi_state_set_cache_unref (obj);
+}
+
+static Accessibility_StateType
+spi_state_to_dbus (AccessibleState state)
+{
+#define MAP_STATE(a) \
+  case SPI_STATE_##a: \
+    return Accessibility_STATE_##a
+
+  switch (state)
+    {
+      MAP_STATE (INVALID);
+      MAP_STATE (ACTIVE);
+      MAP_STATE (ARMED);
+      MAP_STATE (BUSY);
+      MAP_STATE (CHECKED);
+      MAP_STATE (DEFUNCT);
+      MAP_STATE (EDITABLE);
+      MAP_STATE (ENABLED);
+      MAP_STATE (EXPANDABLE);
+      MAP_STATE (EXPANDED);
+      MAP_STATE (FOCUSABLE);
+      MAP_STATE (FOCUSED);
+      MAP_STATE (HORIZONTAL);
+      MAP_STATE (ICONIFIED);
+      MAP_STATE (MODAL);
+      MAP_STATE (MULTI_LINE);
+      MAP_STATE (MULTISELECTABLE);
+      MAP_STATE (OPAQUE);
+      MAP_STATE (PRESSED);
+      MAP_STATE (RESIZABLE);
+      MAP_STATE (SELECTABLE);
+      MAP_STATE (SELECTED);
+      MAP_STATE (SENSITIVE);
+      MAP_STATE (SHOWING);
+      MAP_STATE (SINGLE_LINE);
+      MAP_STATE (STALE);
+      MAP_STATE (TRANSIENT);
+      MAP_STATE (VERTICAL);
+      MAP_STATE (VISIBLE);
+      MAP_STATE (MANAGES_DESCENDANTS);
+      MAP_STATE (INDETERMINATE);
+      MAP_STATE (TRUNCATED);
+      MAP_STATE (REQUIRED);
+      MAP_STATE (INVALID_ENTRY);
+      MAP_STATE (SUPPORTS_AUTOCOMPLETION);
+      MAP_STATE (SELECTABLE_TEXT);
+      MAP_STATE (IS_DEFAULT);
+      MAP_STATE (VISITED);
+    default:
+      return Accessibility_STATE_INVALID;
+  }
+#undef MAP_STATE
+}            
+
+/**
+ * AccessibleStateSet_contains:
+ * @obj: a pointer to the #AccessibleStateSet object on which to operate.
+ * @state: an #AccessibleState for which the specified #AccessibleStateSet
+ *       will be queried.
+ *
+ * Determine whether a given #AccessibleStateSet includes a given state; that is,
+ *       whether @state is true for the stateset in question.
+ *
+ * Returns: #TRUE if @state is true/included in the given #AccessibleStateSet,
+ *          otherwise #FALSE.
+ *
+ **/
+SPIBoolean
+AccessibleStateSet_contains (AccessibleStateSet *obj,
+                            AccessibleState state)
+{
+  return spi_state_set_cache_contains (obj, spi_state_to_dbus (state));
+}
+
+/**
+ * AccessibleStateSet_add:
+ * @obj: a pointer to the #AccessibleStateSet object on which to operate.
+ * @state: an #AccessibleState to be added to the specified #AccessibleStateSet
+ *
+ * Add a particular #AccessibleState to an #AccessibleStateSet (i.e. set the
+ *       given state to #TRUE in the stateset.
+ *
+ **/
+void
+AccessibleStateSet_add (AccessibleStateSet *obj,
+                       AccessibleState state)
+{
+  spi_state_set_cache_add (obj, spi_state_to_dbus (state));
+}
+
+/**
+ * AccessibleStateSet_remove:
+ * @obj: a pointer to the #AccessibleStateSet object on which to operate.
+ * @state: an #AccessibleState to be removed from the specified #AccessibleStateSet
+ *
+ * Remove a particular #AccessibleState to an #AccessibleStateSet (i.e. set the
+ *       given state to #FALSE in the stateset.)
+ *
+ **/
+void
+AccessibleStateSet_remove (AccessibleStateSet *obj,
+                          AccessibleState state)
+{
+  spi_state_set_cache_remove (obj, spi_state_to_dbus (state));
+}
+
+/**
+ * AccessibleStateSet_equals:
+ * @obj: a pointer to the first #AccessibleStateSet object on which to operate.
+ * @obj2: a pointer to the second #AccessibleStateSet object on which to operate.
+ *
+ * Determine whether two instances of #AccessibleStateSet are equivalent (i.e.
+ *         consist of the same #AccessibleStates).  Useful for checking multiple
+ *         state variables at once; construct the target state then compare against it.
+ *
+ * @see AccessibleStateSet_compare().
+ *
+ * Returns: #TRUE if the two #AccessibleStateSets are equivalent,
+ *          otherwise #FALSE.
+ *
+ **/
+SPIBoolean
+AccessibleStateSet_equals (AccessibleStateSet *obj,
+                           AccessibleStateSet *obj2)
+{
+  SPIBoolean   eq;
+  AtkStateSet *cmp;
+
+  if (obj == obj2)
+    {
+      return TRUE;
+    }
+
+  cmp = spi_state_set_cache_xor (obj, obj2);
+  eq = spi_state_set_cache_is_empty (cmp);
+  spi_state_set_cache_unref (cmp);
+
+  return eq;
+}
+
+/**
+ * AccessibleStateSet_compare:
+ * @obj: a pointer to the first #AccessibleStateSet object on which to operate.
+ * @obj2: a pointer to the second #AccessibleStateSet object on which to operate.
+ *
+ * Determine the differences between two instances of #AccessibleStateSet.
+ * Not Yet Implemented.
+ *.
+ * @see AccessibleStateSet_equals().
+ *
+ * Returns: an #AccessibleStateSet object containing all states contained on one of
+ *          the two sets but not the other.
+ *
+ **/
+AccessibleStateSet *
+AccessibleStateSet_compare (AccessibleStateSet *obj,
+                            AccessibleStateSet *obj2)
+{
+  return spi_state_set_cache_xor (obj, obj2);
+}
+
+/**
+ * AccessibleStateSet_isEmpty:
+ * @obj: a pointer to the #AccessibleStateSet object on which to operate.
+ *
+ * Determine whether a given #AccessibleStateSet is the empty set.
+ *
+ * Returns: #TRUE if the given #AccessibleStateSet contains no (true) states,
+ *          otherwise #FALSE.
+ *
+ **/
+SPIBoolean
+AccessibleStateSet_isEmpty (AccessibleStateSet *obj)
+{
+  return spi_state_set_cache_is_empty (obj);
+}
+
diff --git a/cspi/spi_action.c b/cspi/spi_action.c
new file mode 100644 (file)
index 0000000..7136b45
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <cspi/spi-private.h>
+
+/**
+ * AccessibleAction_ref:
+ * @obj: a pointer to the #AccessibleAction on which to operate.
+ *
+ * Increment the reference count for an #AccessibleAction.
+ **/
+void
+AccessibleAction_ref (AccessibleAction *obj)
+{
+  cspi_object_ref (obj);
+}
+
+/**
+ * AccessibleAction_unref:
+ * @obj: a pointer to the #AccessibleAction on which to operate.
+ *
+ * Decrement the reference count for an #AccessibleAction.
+ **/
+void
+AccessibleAction_unref (AccessibleAction *obj)
+{
+  cspi_object_unref (obj);
+}
+
+/**
+ * AccessibleAction_getNActions:
+ * @obj: a pointer to the #AccessibleAction to query.
+ *
+ * Get the number of actions invokable on an #AccessibleAction implementor.
+ *
+ * Returns: a #long integer indicatin the number of invokable actions.
+ **/
+long
+AccessibleAction_getNActions (AccessibleAction *obj)
+{
+  dbus_int32_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, -1);
+
+  cspi_dbus_get_property (obj, spi_interface_action, "nActions", NULL, "i", &retval);
+
+  cspi_return_val_if_ev ("getNActions", -1);
+
+  return retval;
+}
+
+/**
+ * AccessibleAction_getDescription:
+ * @obj: a pointer to the #AccessibleAction implementor to query.
+ * @i: a long integer indicating which action to query.
+ *
+ * Get the description of '@i-th' action invokable on an
+ *      object implementing #AccessibleAction.
+ *
+ * Returns: a UTF-8 string describing the '@i-th' invokable action.
+ **/
+char *
+AccessibleAction_getDescription (AccessibleAction *obj,
+                                 long int          i)
+{
+  dbus_int32_t d_i = i;
+  char *retval;
+  cspi_return_val_if_fail (obj != NULL, NULL);
+
+  cspi_dbus_call (obj, spi_interface_action, "getDescription", NULL, "i=>s", d_i, &retval);
+
+  cspi_return_val_if_ev ("getDescription", NULL);
+
+  return retval;
+}
+
+/**
+ * AccessibleAction_getKeyBinding:
+ * @obj: a pointer to the #AccessibleAction implementor to query.
+ * @i: a long integer indicating which action to query.
+ *
+ * Get the keybindings for the @i-th action invokable on an
+ *      object implementing #AccessibleAction, if any are defined.
+ *      The keybindings string format is as follows:
+ *        there are multiple parts to a keybinding string (typically 3).
+ *        They are delimited with ";".  The first is the action's
+ *        keybinding which is usable if the object implementing the action
+ *        is currently posted to the screen, e.g. if a menu is posted 
+ *        then these keybindings for the corresponding menu-items are
+ *        available.  The second keybinding substring is the full key sequence
+ *        necessary to post the action's widget and activate it, e.g. for
+ *        a menu item such as "File->Open" it would both post the menu and
+ *        activate the item.  Thus the second keybinding string is available
+ *        during the lifetime of the containing toplevel window as a whole,
+ *        whereas the first keybinding string only works while the object
+ *        implementing AtkAction is posted.  The third (and optional)
+ *        keybinding string is the "keyboard shortcut" which invokes the 
+ *        action without posting any menus. 
+ *        Meta-keys are indicated by the conventional strings
+ *        "<Control>", "<Alt>", "<Shift>", "<Mod2>",
+ *        etc. (we use the same string as gtk_accelerator_name() in 
+ *        gtk+-2.X.
+ *
+ * Returns: a UTF-8 string which can be parsed to determine the @i-th
+ *       invokable action's keybindings.
+ **/
+char *
+AccessibleAction_getKeyBinding (AccessibleAction *obj,
+                               long int          i)
+{
+  dbus_int32_t d_i = i;
+  char *retval;
+  cspi_return_val_if_fail (obj != NULL, NULL);
+
+  cspi_dbus_call (obj, spi_interface_action, "getKeyBinding", NULL, "i=>s", d_i, &retval);
+
+  cspi_return_val_if_ev ("getKeyBinding", NULL);
+
+  return retval;
+}
+
+/**
+ * AccessibleAction_getName:
+ * @obj: a pointer to the #AccessibleAction implementor to query.
+ * @i: a long integer indicating which action to query.
+ *
+ * Get the name of the '@i-th' action invokable on an
+ *      object implementing #AccessibleAction.
+ *
+ * Returns: the 'event type' name of the action, as a UTF-8 string.
+ **/
+char *
+AccessibleAction_getName (AccessibleAction *obj,
+                         long int          i)
+{
+  dbus_int32_t d_i = i;
+  char *retval;
+  cspi_return_val_if_fail (obj != NULL, NULL);
+
+  cspi_dbus_call (obj, spi_interface_action, "getName", NULL, "i=>s", d_i, &retval);
+
+  cspi_return_val_if_ev ("getName", NULL);
+
+  return retval;
+}
+
+/**
+ * AccessibleAction_doAction:
+ * @obj: a pointer to the #AccessibleAction to query.
+ * @i: an integer specifying which action to invoke.
+ *
+ * Invoke the action indicated by #index.
+ *
+ * Returns: #TRUE if the action is successfully invoked, otherwise #FALSE.
+ **/
+SPIBoolean
+AccessibleAction_doAction (AccessibleAction *obj,
+                           long int i)
+{
+  dbus_int32_t d_i = i;
+  dbus_bool_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_action, "doAction", NULL, "i=>b", d_i, &retval);
+
+  cspi_return_val_if_ev ("doAction", FALSE);
+
+  return retval;
+}
diff --git a/cspi/spi_component.c b/cspi/spi_component.c
new file mode 100644 (file)
index 0000000..93a30c5
--- /dev/null
@@ -0,0 +1,346 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ *
+ * AccessibleComponent function implementations
+ *
+ */
+
+#include <cspi/spi-private.h>
+
+/**
+ * AccessibleComponent_ref:
+ * @obj: a pointer to an object implementing #AccessibleComponent on which to operate.
+ *
+ * Increment the reference count for an #AccessibleComponent.
+ **/
+void
+AccessibleComponent_ref (AccessibleComponent *obj)
+{
+  cspi_object_ref (obj);
+}
+
+/**
+ * AccessibleComponent_unref:
+ * @obj: a pointer to the object implementing #AccessibleComponent on which to operate.
+ *
+ * Decrement the reference count for an #AccessibleComponent.
+ **/
+void
+AccessibleComponent_unref (AccessibleComponent *obj)
+{
+  cspi_object_unref (obj);
+}
+
+/**
+ * AccessibleComponent_contains:
+ * @obj: a pointer to the #AccessibleComponent to query.
+ * @x: a #long specifying the x coordinate in question.
+ * @y: a #long specifying the y coordinate in question.
+ * @ctype: the desired coordinate system of the point (@x, @y)
+ *         (e.g. CSPI_COORD_TYPE_WINDOW, CSPI_COORD_TYPE_SCREEN).
+ *
+ * Query whether a given #AccessibleComponent contains a particular point.
+ *
+ * Returns: a #TRUE if the specified component contains the point (@x, @y),
+ *          otherwise #FALSE.
+ **/
+SPIBoolean
+AccessibleComponent_contains (AccessibleComponent *obj,
+                              long int x,
+                              long int y,
+                              AccessibleCoordType ctype)
+{
+  dbus_bool_t retval;
+  dbus_int32_t d_x = x, d_y = y;
+  dbus_uint16_t d_ctype = ctype;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_component, "contains", NULL, "iin=>b", d_x, d_y, d_ctype, &retval);
+
+  cspi_return_val_if_ev ("contains", FALSE);
+
+  return retval;
+}
+
+/**
+ * AccessibleComponent_getAccessibleAtPoint:
+ * @obj: a pointer to the #AccessibleComponent to query.
+ * @x: a #long specifying the x coordinate of the point in question.
+ * @y: a #long specifying the y coordinate of the point in question.
+ * @ctype: the coordinate system of the point (@x, @y)
+ *         (e.g. CSPI_COORD_TYPE_WINDOW, CSPI_COORD_TYPE_SCREEN).
+ *
+ * Get the accessible child at a given coordinate within an #AccessibleComponent.
+ *
+ * Returns: a pointer to an #Accessible child of the specified component which
+ *          contains the point (@x, @y), or NULL of no child contains the point.
+ **/
+Accessible *
+AccessibleComponent_getAccessibleAtPoint (AccessibleComponent *obj,
+                                          long int x,
+                                          long int y,
+                                          AccessibleCoordType ctype)
+{
+  dbus_int32_t d_x = x, d_y = y;
+  dbus_uint16_t d_ctype = ctype;
+  char *path = NULL;
+  Accessible *retval;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_component, "getAccessibleAtPoint", NULL, "iin=>o", d_x, d_y, d_ctype, &path);
+
+  retval = cspi_ref_related_accessible (obj, path);
+  g_free (path);
+  return retval;
+}
+
+/**
+ * AccessibleComponent_getExtents:
+ * @obj: a pointer to the #AccessibleComponent to query.
+ * @x: a pointer to a #long into which the minimum x coordinate will be returned.
+ * @y: a pointer to a #long into which the minimum y coordinate will be returned.
+ * @width: a pointer to a #long into which the x extents (width) will be returned.
+ * @height: a pointer to a #long into which the y extents (height) will be returned.
+ * @ctype: the desired coordinate system into which to return the results,
+ *         (e.g. CSPI_COORD_TYPE_WINDOW, CSPI_COORD_TYPE_SCREEN).
+ *
+ * Get the bounding box of the specified #AccessibleComponent.
+ *
+ **/
+void
+AccessibleComponent_getExtents (AccessibleComponent *obj,
+                                long int *x,
+                                long int *y,
+                                long int *width,
+                                long int *height,
+                                AccessibleCoordType ctype)
+{
+  dbus_int16_t d_ctype = ctype;
+  Accessibility_BoundingBox bbox;
+
+  cspi_return_if_fail (obj != NULL);
+
+  cspi_dbus_call (obj, spi_interface_component, "getExtents", NULL, "n=>(iiii)", d_ctype, &bbox);
+  if (!cspi_check_ev ("getExtents"))
+    {
+      *x = *y = *width = *height = 0;    
+    }
+  else
+    {
+      *x = bbox.x;
+      *y = bbox.y;
+      *width = bbox.width;
+      *height = bbox.height;
+    }
+}
+
+/**
+ * AccessibleComponent_getPosition:
+ * @obj: a pointer to the #AccessibleComponent to query.
+ * @x: a pointer to a #long into which the minimum x coordinate will be returned.
+ * @y: a pointer to a #long into which the minimum y coordinate will be returned.
+ * @ctype: the desired coordinate system into which to return the results,
+ *         (e.g. CSPI_COORD_TYPE_WINDOW, CSPI_COORD_TYPE_SCREEN).
+ *
+ * Get the minimum x and y coordinates of the specified #AccessibleComponent.
+ *
+ **/
+void
+AccessibleComponent_getPosition (AccessibleComponent *obj,
+                                 long int *x,
+                                 long int *y,
+                                 AccessibleCoordType ctype)
+{
+  dbus_int32_t d_x, d_y;
+  dbus_uint16_t d_ctype = ctype;
+
+  cspi_return_if_fail (obj != NULL);
+
+  cspi_dbus_call (obj, spi_interface_component, "getPosition", NULL, "n=>ii", d_ctype, &d_x, &d_y);
+
+  if (!cspi_check_ev ("getPosition"))
+    {
+      *x = *y = 0;
+    }
+  else
+    {
+      *x = d_x;
+      *y = d_y;
+    }
+}
+
+/**
+ * AccessibleComponent_getSize:
+ * @obj: a pointer to the #AccessibleComponent to query.
+ * @width: a pointer to a #long into which the x extents (width) will be returned.
+ * @height: a pointer to a #long into which the y extents (height) will be returned.
+ *
+ * Get the size of the specified #AccessibleComponent.
+ *
+ **/
+void
+AccessibleComponent_getSize (AccessibleComponent *obj,
+                             long int *width,
+                             long int *height)
+{
+  dbus_int32_t d_w, d_h;
+
+  cspi_return_if_fail (obj != NULL);
+
+  cspi_dbus_call (obj, spi_interface_component, "getSize", NULL, "=>ii", &d_w, &d_h);
+  if (cspi_check_ev ("getSize"))
+  {
+    *width = *height = 0;
+  }
+  else
+  {
+    *width = d_w;
+    *height = d_h;
+  }
+}
+
+/**
+ * AccessibleComponent_getLayer:
+ * @obj: a pointer to the #AccessibleComponent to query.
+ *
+ * Query which layer the component is painted into, to help determine its 
+ *      visibility in terms of stacking order.
+ *
+ * Returns: the #AccessibleComponentLayer into which this component is painted.
+ **/
+AccessibleComponentLayer
+AccessibleComponent_getLayer (AccessibleComponent *obj)
+{
+  AccessibleComponentLayer     retval;
+  dbus_uint32_t zlayer;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_component, "getLayer", NULL, "=>u", &zlayer);
+
+  cspi_return_val_if_ev ("getLayer", SPI_LAYER_INVALID);
+
+  switch (zlayer)
+    {
+    case Accessibility_LAYER_BACKGROUND:
+      retval = SPI_LAYER_BACKGROUND;
+      break;
+    case Accessibility_LAYER_CANVAS:     
+      retval = SPI_LAYER_CANVAS;
+      break;
+    case Accessibility_LAYER_WIDGET:     
+      retval = SPI_LAYER_WIDGET;
+      break;
+    case Accessibility_LAYER_MDI:        
+      retval = SPI_LAYER_MDI;
+      break;
+    case Accessibility_LAYER_POPUP:      
+      retval = SPI_LAYER_POPUP;
+      break;
+    case Accessibility_LAYER_OVERLAY:    
+      retval = SPI_LAYER_OVERLAY;
+      break;
+    case Accessibility_LAYER_WINDOW:     
+      retval = SPI_LAYER_WINDOW;
+      break;
+    default:
+      retval = SPI_LAYER_INVALID;
+      break;
+    }
+
+  return retval;
+}
+
+/**
+ * AccessibleComponent_getMDIZOrder:
+ * @obj: a pointer to the #AccessibleComponent to query.
+ *
+ * Query the z stacking order of a component which is in the MDI or window
+ *       layer. (Bigger z-order numbers mean nearer the top)
+ *
+ * Returns: a short integer indicating the stacking order of the component 
+ *       in the MDI layer, or -1 if the component is not in the MDI layer.
+ **/
+short
+AccessibleComponent_getMDIZOrder (AccessibleComponent *obj)
+{
+  dbus_uint16_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_component, "getMDIZOrder", NULL, "=>n", &retval);
+
+  cspi_return_val_if_ev ("getMDIZOrder", FALSE);
+
+  return retval;
+}
+
+/**
+ * AccessibleComponent_grabFocus:
+ * @obj: a pointer to the #AccessibleComponent on which to operate.
+ *
+ * Attempt to set the keyboard input focus to the specified
+ *         #AccessibleComponent.
+ *
+ * Returns: #TRUE if successful, #FALSE otherwise.
+ *
+ **/
+SPIBoolean
+AccessibleComponent_grabFocus (AccessibleComponent *obj)
+{
+  dbus_bool_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_component, "grabFocus", NULL, "=>b", &retval);
+
+  cspi_return_val_if_ev ("grabFocus", FALSE);
+
+  return retval;
+}
+
+/**
+ * AccessibleComponent_getAlpha:
+ * @obj: The #AccessibleComponent to be queried.
+ *
+ * Get the opacity/alpha value of a component, if alpha blending is in use.
+ *
+ * Returns: the opacity value of a component, as a double between 0.0 and 1.0. 
+ **/
+double      
+AccessibleComponent_getAlpha    (AccessibleComponent *obj)
+{
+  double retval;
+
+  cspi_return_val_if_fail (obj != NULL, 1.0);
+
+  cspi_dbus_call (obj, spi_interface_component, "getAlpha", NULL, "=>d", &retval);
+
+  cspi_return_val_if_ev ("getAlpha", 1.0);
+
+  return retval;
+}
diff --git a/cspi/spi_editabletext.c b/cspi/spi_editabletext.c
new file mode 100644 (file)
index 0000000..31ae429
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <cspi/spi-private.h>
+
+/**
+ * AccessibleEditableText_ref:
+ * @obj: a pointer to the #AccessibleEditableText object on which to operate.
+ *
+ * Increment the reference count for an #AccessibleEditableText object.
+ *       Since AccessibleEditableText is derived from AccessibleText,
+ *       this is the same as AccessibleText_ref().
+ **/
+void
+AccessibleEditableText_ref (AccessibleEditableText *obj)
+{
+  cspi_object_ref (obj);
+}
+
+/**
+ * AccessibleEditableText_unref:
+ * @obj: a pointer to the #AccessibleEditableText object on which to operate.
+ *
+ * Decrement the reference count for an #AccessibleEdiitableText object.
+ *       Since AccessibleEditableText is derived from AccessibleText,
+ *       this is the same as AccessibleText_unref().
+ **/
+void
+AccessibleEditableText_unref (AccessibleEditableText *obj)
+{
+  cspi_object_unref (obj);
+}
+
+/**
+ * AccessibleEditableText_setAttributes:
+ * @obj: a pointer to the #AccessibleEditableText object to modify.
+ * @attributes: a character string indicating the attributes to apply to the range,
+ *        delimited by ':'.
+ * @startOffset: a #long indicating the start of the desired text range.
+ * @endOffset: a #long indicating the first character past the desired range.
+ *
+ * Set the attributes applied to a range of text from an #AccessibleEditableText
+ *          object, and the bounds of the range.
+ *
+ * Returns: #TRUE if the operation was successful, otherwise #FALSE.
+ **/
+SPIBoolean
+AccessibleEditableText_setAttributes (AccessibleEditableText *obj,
+                                     const char *attributes,
+                                     long int startPos,
+                                     long int endPos)
+{
+  dbus_int32_t d_startPos = startPos, d_endPos = endPos;
+  dbus_bool_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_editable_text, "setAttributes", NULL, "sii=>b", attributes, d_startPos, d_endPos, &retval);
+
+  cspi_return_val_if_ev ("setAttributes", FALSE);
+
+  return retval;
+}
+
+/**
+ * AccessibleEditableText_setTextContents:
+ * @obj: a pointer to the #AccessibleEditableText object to modify.
+ * @newContents: a character string, encoded in UTF-8, which is to
+ *      become the new text contents of the #AccessibleEditableText object.
+ *
+ * Replace the entire text contents of an #AccessibleEditableText object.
+ *
+ * Returns: #TRUE if the operation was successful, otherwise #FALSE.
+ **/
+SPIBoolean
+AccessibleEditableText_setTextContents (AccessibleEditableText *obj,
+                                        const char *newContents)
+{
+  dbus_bool_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_editable_text, "setTextContents", NULL, "s=>b", newContents, &retval);
+
+  cspi_return_val_if_ev ("setTextContents", FALSE);
+
+  return retval;
+}
+
+/**
+ * AccessibleEditableText_insertText:
+ * @obj: a pointer to the #AccessibleEditableText object to modify.
+ * @position: an integer indicating the character offset at which to insert
+ *       the new text.  
+ * @text: a char* pointer to the text to insert, in UTF-8 encoding.
+ * @length: (frankly I'm not sure this parameter should be here)
+ *
+ * Insert text into an #AccessibleEditableText object.
+ * As with all character offsets, the specified @position may not be the
+ *       same as the resulting byte offset, since the text is in a
+ *       variable-width encoding.
+ *
+ * Returns: #TRUE if the operation was successful, otherwise #FALSE.
+ **/
+SPIBoolean
+AccessibleEditableText_insertText (AccessibleEditableText *obj,
+                                   long int position,
+                                   const char *text,
+                                   long int length)
+{
+  dbus_int32_t d_position = position, d_length = length;
+  dbus_bool_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_editable_text, "insertText", NULL, "isi=>b", d_position, text, d_length, &retval);
+
+  cspi_return_val_if_ev ("insertText", FALSE);
+
+  return retval;
+}
+
+/**
+ * AccessibleEditableText_copyText:
+ * @obj: a pointer to the #AccessibleEditableText object to modify.
+ * @startPos: an integer indicating the starting character offset
+ *       of the text to copy.
+ * @endPos: an integer indicating the offset of the first character
+ *       past the end of the text section to be copied.
+ *
+ * Copy text from an #AccessibleEditableText object into the clipboard.
+ *
+ * @see: AccessibleEditableText_pasteText 
+ *
+ * Returns: #TRUE if the operation was successful, otherwise #FALSE.
+ **/
+SPIBoolean
+AccessibleEditableText_copyText (AccessibleText *obj,
+                                 long int startPos,
+                                 long int endPos)
+{
+  dbus_int32_t d_startPos = startPos, d_endPos = endPos;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_editable_text, "copyText", NULL, "ii", startPos, endPos);
+
+  cspi_return_val_if_ev ("copyText", FALSE);
+
+  return TRUE;
+}
+
+/**
+ * AccessibleEditableText_cutText:
+ * @obj: a pointer to the #AccessibleEditableText object to modify.
+ * @startPos: an integer indicating the starting character offset
+ *       of the text to cut.
+ * @endPos: an integer indicating the offset of the first character
+ *       past the end of the text section to be cut.
+ *
+ * Delete text from an #AccessibleEditableText object, copying the
+ *       excised portion into the clipboard.
+ *
+ * @see: AccessibleEditableText_pasteText
+ *
+ * Returns: #TRUE if operation was successful, #FALSE otherwise.
+ **/
+SPIBoolean
+AccessibleEditableText_cutText (AccessibleEditableText *obj,
+                                long int startPos,
+                                long int endPos)
+{
+  dbus_int32_t d_startPos = startPos, d_endPos = endPos;
+  dbus_bool_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_editable_text, "cutText", NULL, "ii=>b", d_startPos, d_endPos, &retval);
+
+  cspi_return_val_if_ev ("cutText", FALSE);
+
+  return retval;
+}
+
+/**
+ * AccessibleEditableText_deleteText:
+ * @obj: a pointer to the #AccessibleEditableText object to modify.
+ * @startPos: an integer indicating the starting character offset
+ *       of the text to delete.
+ * @endPos: an integer indicating the offset of the first character
+ *       past the end of the text section to be deleted.
+ *
+ * Delete text from an #AccessibleEditableText object, without copying the
+ *       excised portion into the clipboard.
+ *
+ * @see: AccessibleEditableText_cutText
+ *
+ * Returns: #TRUE if the operation was successful, otherwise #FALSE.
+ **/
+SPIBoolean
+AccessibleEditableText_deleteText (AccessibleEditableText *obj,
+                                   long startPos,
+                                   long endPos)
+{
+  dbus_int32_t d_startPos = startPos, d_endPos = endPos;
+  dbus_bool_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_editable_text, "deleteText", NULL, "ii=>b", d_startPos, d_endPos, &retval);
+
+  cspi_return_val_if_ev ("deleteText", FALSE);
+
+  return retval;
+}
+
+/**
+ * AccessibleEditableText_pasteText:
+ * @obj: a pointer to the #AccessibleEditableText object to modify.
+ * @position: an integer indicating the character offset at which to insert
+ *       the new text.  
+ *
+ * Insert text from the clipboard into an #AccessibleEditableText object.
+ * As with all character offsets, the specified @position may not be the
+ *       same as the resulting byte offset, since the text is in a
+ *       variable-width encoding.
+ *
+ * Returns: #TRUE if the operation was successful, otherwise #FALSE.
+ **/
+SPIBoolean
+AccessibleEditableText_pasteText (AccessibleEditableText *obj,
+                                  long int position)
+{
+  dbus_int32_t d_position = position;
+  dbus_bool_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_editable_text, "pasteText", NULL, "i=>b", d_position, &retval);
+
+  cspi_return_val_if_ev ("pasteText", FALSE);
+
+  return retval;
+}
diff --git a/cspi/spi_event.c b/cspi/spi_event.c
new file mode 100644 (file)
index 0000000..32719b7
--- /dev/null
@@ -0,0 +1,1230 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002, 2003 Sun Microsystems Inc.,
+ * Copyright 2001, 2002, 2003 Ximian, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <cspi/spi-private.h>
+
+static GSList *_cspi_event_queue = NULL;
+
+/**
+ * SPI_freeAccessibleKeySet:
+ * @keyset: An AccessibleKeyset to free.
+ *
+ * Release the memory used by an AccessibleKeySet.
+ *
+ **/
+void
+SPI_freeAccessibleKeySet (AccessibleKeySet *keyset)
+{
+  int i = 0;   
+  g_free (keyset->keysyms);
+  g_free (keyset->keycodes);
+  while (keyset->keystrings [i])
+    {
+      g_free (keyset->keystrings [i++]);
+    }
+  g_free (keyset->keystrings);
+  g_free (keyset);
+}
+
+/**
+ * SPI_createAccessibleKeySet:
+ * @len: the number of key values in the key set.
+ * @keysyms: a UTF-8 string containing symbolic key values to be matched, or NULL if
+ *           matching is performed against other key values instead.
+ * @keycodes: an array of unsigned short values which are the hardware keycodes
+ *           to be matched, or NULL if the keyset is specified solely by keysyms
+ *           and/or keystrings.
+ * @keystrings: an array of null-terminated character strings which specify key
+ *             name values to match, or NULL if the keyset is specified solely by
+ *             keycodes and/or keysyms.
+ *
+ * Create a new #AccessibleKeySet of a specified length.
+ * A KeySet is used typically to match key event values, and a matches are made
+ * using the following criteria: a match exists with a key event if all non-null
+ * i-th members of the keyset match the key event.
+ * If both keystring and keysym values are NULL, a keycode value match is
+ * forced, thus the match for keysym=0, keycode=0, keystring=NULL is
+ * keycode 0.
+ *
+ * Returns: a pointer to a newly-created #AccessibleKeySet.
+ *
+ **/
+AccessibleKeySet *
+SPI_createAccessibleKeySet (int len, const char *keysyms, short *keycodes,
+                           const char **keystrings)
+{
+  AccessibleKeySet *keyset = g_new0 (AccessibleKeySet, 1);
+  int i, keysym_len = 0;
+  const char *keysym_ptr = keysyms;
+  keyset->len = len;
+  keyset->keysyms = g_new0 (unsigned long, len);
+  keyset->keycodes = g_new0 (unsigned short, len);
+  keyset->keystrings = g_new0 (char *, len);
+  if (keysyms)
+    {
+      keysym_len = g_utf8_strlen (keysyms, -1);
+    }
+  for (i = 0; i < len; ++i)
+    {
+      if (i < keysym_len)
+        {
+         keyset->keysyms [i] = (unsigned long) g_utf8_get_char (keysym_ptr);
+         keysym_ptr = g_utf8_find_next_char (keysym_ptr, NULL);
+        }
+      else
+        {
+          keyset->keysyms [i] = 0;
+        }
+      if (keycodes)
+        {
+         keyset->keycodes [i] = keycodes [i];
+       }
+      if (keystrings)
+        {
+         keyset->keystrings [i] = g_strdup (keystrings [i]);
+       }
+    }
+  return keyset;       
+}
+
+/**
+ * SPI_createAccessibleEventListener:
+ * @callback : an #AccessibleEventListenerCB callback function, or NULL.
+ * @user_data: a pointer to data which will be passed to the callback when invoked.
+ *
+ * Create a new #AccessibleEventListener with a specified (in-process) callback function.
+ *
+ * Returns: a pointer to a newly-created #AccessibleEventListener.
+ *
+ **/
+AccessibleEventListener *
+SPI_createAccessibleEventListener (AccessibleEventListenerCB callback,
+                                  void                     *user_data)
+{
+  AccessibleEventListener *listener = cspi_event_listener_new ();
+  if (callback)
+    {
+      AccessibleEventListener_addCallback (listener, callback, user_data);
+    }
+  return listener;
+}
+
+/**
+ * AccessibleEventListener_addCallback:
+ * @listener: the #AccessibleEventListener instance to modify.
+ * @callback: an #AccessibleEventListenerCB function pointer.
+ * @user_data: a pointer to data which will be passed to the callback when invoked.
+ *
+ * Add an in-process callback function to an existing AccessibleEventListener.
+ * Note that the callback function must live in the same address
+ * space as the AccessibleEventListener implementation code, thus one should not
+ * use this function to attach callbacks to a 'remote' event listener
+ * (that is, one that was not created by a client call to
+ * createAccessibleEventListener ();
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ *
+ **/
+SPIBoolean
+AccessibleEventListener_addCallback (AccessibleEventListener *listener,
+                                    AccessibleEventListenerCB callback,
+                                    void                     *user_data)
+{
+  cspi_event_listener_add_cb (listener, callback, user_data);
+  return TRUE;
+}
+
+/**
+ * AccessibleEventListener_unref:
+ * @listener: a pointer to the #AccessibleEventListener being operated on.
+ *
+ * Decrements an #AccessibleEventListener's reference count.
+ **/
+void
+AccessibleEventListener_unref (AccessibleEventListener *listener)
+{
+  cspi_event_listener_unref (listener);
+}
+
+/**
+ * AccessibleEventListener_removeCallback:
+ * @listener: the #AccessibleEventListener instance to modify.
+ * @callback: an #AccessibleEventListenerCB function pointer.
+ *
+ * Remove an in-process callback function from an existing AccessibleEventListener.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ *
+ **/
+SPIBoolean
+AccessibleEventListener_removeCallback (AccessibleEventListener  *listener,
+                                       AccessibleEventListenerCB callback)
+{
+  cspi_event_listener_remove_cb (listener, callback);
+  return TRUE;
+}
+
+/**
+ * SPI_createAccessibleKeystrokeListener:
+ * @callback : an #AccessibleKeystrokeListenerCB callback function, or NULL.
+ * @user_data: a pointer to data which will be passed to the callback when invoked.
+ *
+ * Create a new #AccessibleKeystrokeListener with a specified callback function.
+ *
+ * Returns: a pointer to a newly-created #AccessibleKeystrokeListener.
+ *
+ **/
+AccessibleKeystrokeListener *
+SPI_createAccessibleKeystrokeListener (AccessibleKeystrokeListenerCB callback,
+                                      void                         *user_data)
+{
+  AccessibleDeviceListener *listener = cspi_device_listener_new ();
+  if (callback)
+    {
+      AccessibleDeviceListener_addCallback (listener, callback, user_data);
+    }
+  return listener;
+}
+
+/**
+ * AccessibleKeystrokeListener_addCallback:
+ * @listener: the #AccessibleKeystrokeListener instance to modify.
+ * @callback: an #AccessibleKeystrokeListenerCB function pointer.
+ * @user_data: a pointer to data which will be passed to the callback when invoked.
+ *
+ * Add an in-process callback function to an existing #AccessibleKeystrokeListener.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ *
+ **/
+SPIBoolean
+AccessibleKeystrokeListener_addCallback (AccessibleKeystrokeListener *listener,
+                                        AccessibleKeystrokeListenerCB callback,
+                                        void                         *user_data)
+{
+  cspi_device_listener_add_cb (listener, callback, user_data);
+  return TRUE;
+}
+
+/**
+ * AccessibleKeystrokeListener_removeCallback:
+ * @listener: the #AccessibleKeystrokeListener instance to modify.
+ * @callback: an #AccessibleKeystrokeListenerCB function pointer.
+ *
+ * Remove an in-process callback function from an existing #AccessibleKeystrokeListener.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ *
+ **/
+SPIBoolean
+AccessibleKeystrokeListener_removeCallback (AccessibleKeystrokeListener *listener,
+                                           AccessibleKeystrokeListenerCB callback)
+{
+  cspi_device_listener_remove_cb (listener, callback);
+  return TRUE;
+}
+
+/**
+ * AccessibleKeystrokeListener_unref:
+ * @listener: a pointer to the #AccessibleKeystrokeListener being operated on.
+ *
+ * Decrements an #AccessibleKeystrokeListener's reference count.
+ **/
+void
+AccessibleKeystrokeListener_unref (AccessibleKeystrokeListener *listener)
+{
+  cspi_device_listener_unref (listener);
+}
+
+/**
+ * SPI_createAccessibleDeviceListener:
+ * @callback : an #AccessibleDeviceListenerCB callback function, or NULL.
+ * @user_data: a pointer to data which will be passed to the callback when invoked.
+ *
+ * Create a new #AccessibleDeviceListener with a specified callback function.
+ *
+ * Returns: a pointer to a newly-created #AccessibleDeviceListener.
+ *
+ **/
+AccessibleDeviceListener *
+SPI_createAccessibleDeviceListener (AccessibleDeviceListenerCB callback,
+                                      void                         *user_data)
+{
+  AccessibleDeviceListener *listener = cspi_device_listener_new ();
+  if (callback)
+    {
+      AccessibleDeviceListener_addCallback (listener, callback, user_data);
+    }
+  return listener;
+}
+
+/**
+ * AccessibleDeviceListener_addCallback:
+ * @listener: the #AccessibleDeviceListener instance to modify.
+ * @callback: an #AccessibleDeviceListenerCB function pointer.
+ * @user_data: a pointer to data which will be passed to the callback when invoked.
+ *
+ * Add an in-process callback function to an existing #AccessibleDeviceListener.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ *
+ **/
+SPIBoolean
+AccessibleDeviceListener_addCallback (AccessibleDeviceListener *listener,
+                                        AccessibleDeviceListenerCB callback,
+                                        void                         *user_data)
+{
+  cspi_device_listener_add_cb (listener, callback, user_data);
+  return TRUE;
+}
+
+/**
+ * AccessibleDeviceListener_removeCallback:
+ * @listener: the #AccessibleDeviceListener instance to modify.
+ * @callback: an #AccessibleDeviceListenerCB function pointer.
+ *
+ * Remove an in-process callback function from an existing #AccessibleDeviceListener.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ *
+ **/
+SPIBoolean
+AccessibleDeviceListener_removeCallback (AccessibleDeviceListener *listener,
+                                           AccessibleDeviceListenerCB callback)
+{
+  cspi_device_listener_remove_cb (listener, callback);
+  return TRUE;
+}
+
+/**
+ * AccessibleDeviceListener_unref:
+ * @listener: a pointer to the #AccessibleDeviceListener being operated on.
+ *
+ * Decrements an #AccessibleDeviceListener's reference count.
+ **/
+void
+AccessibleDeviceListener_unref (AccessibleDeviceListener *listener)
+{
+  cspi_device_listener_unref (listener);
+}
+
+static char *
+cspi_internal_event_get_text (const InternalEvent *e)
+{
+  g_return_val_if_fail (e, NULL);
+  if (e->event.v_type == EVENT_DATA_STRING)
+    {
+      return g_strdup (e->event.v.text? e->event.v.text: "");
+    }
+  return NULL;
+}
+
+static Accessible *
+cspi_internal_event_get_object (const InternalEvent *e)
+{
+  g_return_val_if_fail (e, NULL);
+  if (e->event.v_type == EVENT_DATA_OBJECT)
+    {
+      cspi_object_ref (e->event.v.accessible);
+      return e->event.v.accessible;
+    }
+  return NULL;
+}
+
+static SPIRect *
+cspi_internal_event_get_rect (const InternalEvent *e)
+{
+  g_return_val_if_fail (e, NULL);
+  if (e->event.v_type == EVENT_DATA_RECT)
+  {
+      SPIRect *rect = g_new (SPIRect, 1);
+      if (rect) memcpy (rect, &e->event.v.rect, sizeof(*rect));
+      return rect;
+    }
+  return NULL;
+}
+
+/**
+ * AccessibleEvent_getSourceName:
+ * @e: an #AccessibleEvent to be queried. 
+ *
+ * Get the 'accessible-name' of the object emitting the event.
+ *
+ * Returns: The name of the event source, or NULL if the event source cannot be identified
+ *          or does not report a name.
+ */
+char*        AccessibleEvent_getSourceName (const AccessibleEvent *e)
+{
+  if (e && e->source)
+    {
+      return Accessible_getName (e->source);
+    }
+  return NULL;
+}
+
+/**
+ * AccessibleEvent_getSourceRole:
+ * @e: an #AccessibleEvent to be queried. 
+ *
+ * Get the #AccessibleRole of the object emitting the event.
+ *
+ * Returns: #AccessibleRole of the event source, or SPI_ROLE_UNKNOWN
+ *          if the event source's role is unknown or unspecified.
+ *          (Some kinds of events, such as 'mouse:' events or
+ *          toolkit events, don't have associated object roles.)
+ */
+AccessibleRole AccessibleEvent_getSourceRole (const AccessibleEvent *e)
+{
+  if (e && e->source)
+    {
+      return Accessible_getRole (e->source);
+    }
+       return SPI_ROLE_UNKNOWN;
+}
+
+/**
+ * AccessibleEvent_getSourceApplication:
+ * @e: an #AccessibleEvent to be queried. 
+ *
+ * Get the #Application hosting the object which emitted the event.
+ *
+ * Returns: A pointer to the host #Application contining the event source
+ *          component.
+ */
+#if 0
+AccessibleApplication* AccessibleEvent_getSourceApplication (const AccessibleEvent *e)
+{
+xyzzy
+    InternalEvent *ie = (InternalEvent *)e;
+    CORBA_any *any = ((ie && ie->data) ? (CORBA_any *)ie->data : NULL);
+    if (any &&
+       CORBA_TypeCode_equivalent (any->_type, 
+                                  TC_Accessibility_EventDetails, NULL))
+      {
+         Accessibility_EventDetails *details = (Accessibility_EventDetails *) any->_value;
+         return  cspi_object_take (details->host_application);
+      }
+    else
+       return NULL;
+}
+#endif
+
+/**
+ * AccessibleEvent_getSourceDetails:
+ * @e: an #AccessibleEvent to be queried. 
+ * @name: a pointer to a character string which will point to the name of the event source 
+ * on successful completion of the call.
+ * @role: a pointer to an #AccessibleRole which will point to the role of the event source
+ * on successful completion of the call.
+ * @app: A pointer to an #AccessibleApplication which points to the host application for this event
+ * on successful completion of the call.
+ *
+ * Get the host #Application, "accessible name", and #AccessibleRole 
+ * of the object which emitted the event.
+ *
+ * Returns: TRUE if the source details were successfully retrieved, 
+ *          FALSE if they were not, either due to error, incomplete data,
+ *          or the fact that the event did not encapsulate the required data.
+ */
+#if 0
+SPIBoolean   AccessibleEvent_getSourceDetails (const AccessibleEvent *e, 
+                                              char **name, AccessibleRole *role, 
+                                              AccessibleApplication **app)
+{
+    InternalEvent *ie = (InternalEvent *)e;
+    CORBA_any *any = ((ie && ie->data) ? (CORBA_any *)ie->data : NULL);
+    if (any &&
+       CORBA_TypeCode_equivalent (any->_type, 
+                                  TC_Accessibility_EventDetails, NULL))
+      {
+         Accessibility_EventDetails *details = (Accessibility_EventDetails *) any->_value;
+         *name = CORBA_string_dup (details->source_name);
+         *role = cspi_role_from_spi_role (details->source_role);
+         *app = cspi_object_take (details->host_application);
+         return TRUE;
+      }
+    else
+      {
+        *name = NULL;
+       *role = SPI_ROLE_UNKNOWN;
+       *app = NULL;
+       return FALSE;
+      }
+}
+#endif
+
+/**
+ * AccessibleTextChangedEvent_getChangeString:
+ * @e: a pointer to the #AccessibleEvent being queried.
+ *
+ * Queries an #AccessibleEvent of type "object:text-changed", 
+ *         returning the text inserted or deleted.
+ *
+ * Returns: a UTF-8 text string indicating the text inserted,
+ *          deleted, or substituted by this event.
+ **/
+char *
+AccessibleTextChangedEvent_getChangeString (const AccessibleEvent *e)
+{
+  const InternalEvent *foo = (InternalEvent *) e;
+  /* TODO: check the event type. */
+  return cspi_internal_event_get_text (foo);
+}
+
+/**
+ * AccessibleTextSelectionChangedEvent_getSelectionString:
+ * @e: a pointer to the #AccessibleEvent being queried.
+ *
+ * Queries an #AccessibleEvent of type "object:text-selection-changed", 
+ *         returning the newly added, removed, or modified selection string.
+ *
+ * Returns: a UTF-8 text string indicating the recently changed selection.
+ **/
+char *
+AccessibleTextSelectionChangedEvent_getSelectionString (const AccessibleEvent *e)
+{
+  const InternalEvent *foo = (InternalEvent *) e;
+  /* TODO: check the event type. */
+  return cspi_internal_event_get_text (foo);
+}
+
+/**
+ * AccessibleWindowEvent_getTitleString:
+ * @e: a pointer to the #AccessibleEvent being queried.
+ *
+ * Queries an #AccessibleEvent of type "window:", 
+ *         returning the window title.
+ *
+ * Returns: a UTF-8 text string representing the title of the 
+ *         recently changed window.
+ **/
+char *
+AccessibleWindowEvent_getTitleString (const AccessibleEvent *e)
+{
+  const InternalEvent *foo = (InternalEvent *) e;
+  /* TODO: check the event type. */
+  return cspi_internal_event_get_text (foo);
+}
+
+/**
+ * AccessibleChildChangedEvent_getChildAccessible:
+ * @e: a pointer to the #AccessibleEvent being queried.
+ *
+ * Queries an #AccessibleEvent of type "object:children_changed"
+ *         to get a reference to the changed #Accessible.
+ *         Note that context #Accessibles are not guaranteed to outlive
+ *         event delivery, in which case this call may return %NULL
+ *         even if the object existed at the time of dispatch.
+ *
+ * Returns: the context #Accessible for the event, or %NULL if
+ *          there is no longer a valid context #Accessible 
+ *          object for the event.
+ **/
+Accessible *
+AccessibleChildChangedEvent_getChildAccessible (const AccessibleEvent *e)
+{
+  const InternalEvent *foo = (InternalEvent *) e;
+  return (Accessible *) cspi_internal_event_get_object (foo);
+}
+
+/**
+ * AccessibleParentChangedEvent_getParentAccessible:
+ * @e: a pointer to the #AccessibleEvent being queried.
+ *
+ * Queries an #AccessibleEvent of type "object:property-change:accessible-parent"
+ *         to get a reference to the changed #Accessible.
+ *         Note that context #Accessibles are not guaranteed to outlive
+ *         event delivery, in which case this call may return %NULL
+ *         even if the object existed at the time of dispatch.
+ *
+ * Returns: an #Accessible pointer representing the new parent object.
+ **/
+Accessible *
+AccessibleParentChangedEvent_getParentAccessible (const AccessibleEvent *e)
+{
+  const InternalEvent *foo = (InternalEvent *) e;
+  return (Accessible *) cspi_internal_event_get_object (foo);
+}
+
+/**
+ * AccessibleActiveDescendantChangedEvent_getActiveDescendant:
+ * @e: a pointer to the #AccessibleEvent being queried.
+ *
+ * Queries an #AccessibleEvent of type "object:active-descendant-changed"
+ *         to get a reference to the changed #Accessible.
+ *         Note that context #Accessibles are not guaranteed to outlive
+ *         event delivery, in which case this call may return %NULL
+ *         even if the object existed at the time of dispatch.
+ *
+ * Returns: an #Accessible pointer representing the new active descendant.
+ **/
+Accessible *
+AccessibleActiveDescendantChangedEvent_getActiveDescendant (const AccessibleEvent *e) 
+{
+  const InternalEvent *foo = (InternalEvent *) e;
+  return (Accessible *) cspi_internal_event_get_object (foo);
+}
+
+/**
+ * AccessibleTableSummaryChangedEvent_getSummaryAccessible:
+ * @e: a pointer to the #AccessibleEvent being queried.
+ *
+ * Queries an #AccessibleEvent of type "object:property-changed:accessible-table-summary"
+ *         to get a reference to the changed #Accessible.
+ *         Note that context #Accessibles are not guaranteed to outlive
+ *         event delivery, in which case this call may return %NULL
+ *         even if the object existed at the time of dispatch.
+ *
+ * Returns: an #Accessible pointer representing the new table summary.
+ **/
+Accessible *
+AccessibleTableSummaryChangedEvent_getSummaryAccessible (const AccessibleEvent *e) 
+{
+  const InternalEvent *foo = (InternalEvent *) e;
+  return (Accessible *) cspi_internal_event_get_object (foo);
+}
+
+/**
+ * AccessibleTableHeaderChangedEvent_getHeaderAccessible:
+ * @e: a pointer to the #AccessibleEvent being queried.
+ *
+ * Queries an #AccessibleEvent of type 
+ *         "object:property-changed:accessible-table-row-header" or
+ *         "object:property-changed:accessible-table-column-header"
+ *         to get a reference to the changed #Accessible.
+ *         Note that context #Accessibles are not guaranteed to outlive
+ *         event delivery, in which case this call may return %NULL
+ *         even if the object existed at the time of dispatch.
+ *
+ * Returns: an #Accessible pointer representing the new table header.
+ **/
+Accessible *
+AccessibleTableHeaderChangedEvent_getHeaderAccessible (const AccessibleEvent *e)
+{
+  const InternalEvent *foo = (InternalEvent *) e;
+  return (Accessible *) cspi_internal_event_get_object (foo);
+}
+
+
+/**
+ * AccessibleTableCaptionChangedEvent_getCaptionString:
+ * @e: a pointer to the #AccessibleEvent being queried.
+ *
+ * Queries an #AccessibleEvent of type 
+ *         "object:property-changed:accessible-table-caption-object" 
+ *         returning the text in the caption, if present.
+ *
+ * Returns: a UTF-8 text string indicating the text in the caption.
+ **/
+char *
+AccessibleTableCaptionChangedEvent_getCaptionString (const AccessibleEvent *e)
+{
+  const InternalEvent *foo = (InternalEvent *) e;
+  /* TODO: check the event type. */
+  return cspi_internal_event_get_text (foo);
+}
+
+/**
+ * AccessibleTableRowDescriptionChangedEvent_getDescriptionString:
+ * @e: a pointer to the #AccessibleEvent being queried.
+ *
+ * Queries an #AccessibleEvent of type 
+ *         "object:property-changed:accessible-table-row-description" 
+ *         returning the new table row description.
+ *
+ * Returns: a UTF-8 text string representing the recently changed
+ *         table row description 
+ **/
+char *
+AccessibleTableRowDescriptionChangedEvent_getDescriptionString (const AccessibleEvent *e)
+{
+  const InternalEvent *foo = (InternalEvent *) e;
+  /* TODO: check the event type. */
+  return cspi_internal_event_get_text (foo);
+}
+
+/**
+ * AccessibleTableColumnDescriptionChangedEvent_getDescriptionString:
+ * @e: a pointer to the #AccessibleEvent being queried.
+ *
+ * Queries an #AccessibleEvent of type 
+ *         "object:property-changed:accessible-table-column-description" 
+ *         returning the new table column description.
+ *
+ * Returns: a UTF-8 text string representing the recently changed
+ *         table column description 
+ **/
+char *
+AccessibleTableColumnDescriptionChangedEvent_getDescriptionString (const AccessibleEvent *e)
+{
+  const InternalEvent *foo = (InternalEvent *) e;
+  /* TODO: check the event type. */
+  return cspi_internal_event_get_text (foo);
+}
+
+/**
+ * AccessibleDescriptionChangedEvent_getDescriptionString:
+ * @e: a pointer to the #AccessibleEvent being queried.
+ *
+ * Queries an #AccessibleEvent of type 
+ *         "object:property-changed:accessible-description" 
+ *         returning the new description.
+ *
+ * Returns: a UTF-8 text string representing the recently changed
+ *         description 
+ **/
+char *
+AccessibleDescriptionChangedEvent_getDescriptionString (const AccessibleEvent *e)
+{
+  const InternalEvent *foo = (InternalEvent *) e;
+  /* TODO: check the event type. */
+  return cspi_internal_event_get_text (foo);
+}
+
+/**
+ * AccessibleBoundsChangedEvent_getNewBounds:
+ * @e: a pointer to the #AccessibleEvent being queried.
+ *
+ * Queries an #AccessibleEvent of type "object:bounds-changed", 
+ *         returning a pointer to an SPIRect structure containing the
+ *         new bounds, or NULL on error.
+ *         The returned structure should be freed with SPI_freeRect when 
+ *         the caller has finished referencing it.
+ *
+ * @Since: AT-SPI 1.6
+ *
+ * Returns: a pointer to an SPIRect defining the new object bounds.
+ **/
+SPIRect *
+AccessibleBoundsChangedEvent_getNewBounds (const AccessibleEvent *e)
+{
+  const InternalEvent *foo = (InternalEvent *) e;
+  /* TODO: check the event type. */
+  return cspi_internal_event_get_rect (foo);
+}
+
+static gint
+cspi_event_compare (gconstpointer p1, gconstpointer p2)
+{
+  const InternalEvent *e1 = p1, *e2 = p2;
+  return (gint) ((long) e2->id  - (long) e1->id);
+}
+
+static InternalEvent *
+cspi_internal_event_lookup (const InternalEvent *e)
+{
+  InternalEvent *internal = NULL;
+  GSList *p =
+    g_slist_find_custom (_cspi_event_queue, e, cspi_event_compare);
+  if (p)
+    internal = p->data;
+  return internal;
+}
+
+static const InternalEvent *
+cspi_internal_event_check (const AccessibleEvent *e)
+{
+  InternalEvent *internal = (InternalEvent *) e;
+  if (internal->magic == SPI_INTERNAL_EVENT_MAGIC) 
+    return internal;
+  else
+    return NULL;
+}
+
+static InternalEvent *
+cspi_internal_event_add (const InternalEvent *e)
+{
+  _cspi_event_queue = g_slist_prepend (_cspi_event_queue, (gpointer) e);
+  return (InternalEvent *) e;
+}
+
+static void
+cspi_internal_event_remove (const InternalEvent *e)
+{
+  GSList *link = g_slist_find_custom (_cspi_event_queue, e, cspi_event_compare);
+  if (link)
+    _cspi_event_queue = g_slist_remove_link (_cspi_event_queue, link);
+}
+
+/**
+ * AccessibleNameChangedEvent_getNameString:
+ * @e: a pointer to the #AccessibleEvent being queried.
+ *
+ * Queries an #AccessibleEvent of type "object:property-change:accessible_name:", 
+ *         returning the name.
+ *
+ * Returns: a UTF-8 text string representing the name of the 
+ *         object which recently changed.
+ **/
+char *
+AccessibleNameChangedEvent_getNameString (const AccessibleEvent *e)
+{
+  const InternalEvent *foo = (InternalEvent *) e;
+  return cspi_internal_event_get_text (foo);
+}
+
+/**
+ * AccessibleEvent_ref:
+ * @e: a pointer to the #AccessibleEvent being referenced.
+ *
+ * Increments by 1 the reference count of the event
+ *
+ * Returns: TRUE if the function succeeded; FALSE if the pointer is not a
+ *         valid event.
+ **/
+SPIBoolean
+AccessibleEvent_ref (const AccessibleEvent *e)
+{
+  const InternalEvent *private = cspi_internal_event_check (e);
+  if (private)
+    {
+      InternalEvent *event = cspi_internal_event_lookup (private);
+      /* 
+       * put event in the cache if it's not there already, 
+       * and increment refcount 
+       */
+      if (!event)
+       {
+         event = cspi_internal_event_add (private);
+       }
+      event->ref_count++;
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+/**
+ * AccessibleEvent_unref:
+ * @e: a pointer to the #AccessibleEvent being referenced.
+ *
+ * Decrements by 1 the reference count of the event. The event is destroyed
+ * when the reference count recahes zero.
+ *
+ **/
+void
+AccessibleEvent_unref (const AccessibleEvent *e)
+{
+  const InternalEvent *private = cspi_internal_event_check (e);
+  /* decrement refcount and remove if appropriate */
+  if (private)
+    {
+      InternalEvent *event = cspi_internal_event_lookup (private);
+      if (event) 
+       {
+         event->ref_count--;
+         if (event->ref_count < 1)
+            {
+             cspi_internal_event_remove (event);
+              g_free ((gpointer)e->type);
+              Accessible_unref (e->source);
+             if (event->event.v_type == EVENT_DATA_OBJECT)
+               {
+                 Accessible_unref (event->event.v.accessible);
+               }
+              g_free ((gpointer)e);
+            }
+       }
+    }
+}
+
+typedef struct
+{
+  CSpiEventListener *listener;
+  char *event;
+  char *detail;
+} CSpiEventListenerEntry;
+
+static GList *event_listeners = NULL;
+
+static dbus_bool_t
+demarshal_rect (DBusMessageIter *iter, SPIRect *rect)
+{
+  dbus_int32_t x, y, width, height;
+  DBusMessageIter iter_struct;
+
+  dbus_message_iter_recurse (iter, &iter_struct);
+  if (dbus_message_iter_get_arg_type (&iter_struct) != DBUS_TYPE_INT32) return FALSE;
+  dbus_message_iter_get_basic (&iter_struct, &x);
+  dbus_message_iter_next (&iter_struct);
+  if (dbus_message_iter_get_arg_type (&iter_struct) != DBUS_TYPE_INT32) return FALSE;
+  dbus_message_iter_get_basic (&iter_struct, &y);
+  dbus_message_iter_next (&iter_struct);
+  if (dbus_message_iter_get_arg_type (&iter_struct) != DBUS_TYPE_INT32) return FALSE;
+  dbus_message_iter_get_basic (&iter_struct, &width);
+  dbus_message_iter_next (&iter_struct);
+  if (dbus_message_iter_get_arg_type (&iter_struct) != DBUS_TYPE_INT32) return FALSE;
+  dbus_message_iter_get_basic (&iter_struct, &height);
+  rect->x = x;
+  rect->y = y;
+  rect->width = width;
+  rect->height = height;
+  return TRUE;
+}
+
+static gboolean
+parse_eventType (const char *eventType, char **type, char **detail, char **matchrule)
+{
+  char *p, *q;
+  char *t, *d;
+
+  p = strchr (eventType, ':');
+  if (!p) return FALSE;
+  p = strchr (p + 1, ':');
+  if (!p) p = eventType + strlen (eventType);
+  t = g_malloc (p - eventType + 1);
+  if (t)
+  {
+    memcpy (t, eventType, p - eventType);
+    t[p - eventType] = '\0';
+  }
+  else return FALSE;
+  if (*p == ':')
+  {
+    d = g_strdup (p + 1);
+    if (!d)
+    {
+      g_free (t);
+      return FALSE;
+    }
+  }
+  else d = NULL;
+  if ((p = strchr (t, ':')))
+  {
+    *p = (p[1] == '\0'? '\0': '_');
+  }
+  while ((p = strchr (t, '-'))) *p = '_';
+  if (matchrule)
+  {
+    *matchrule = g_strdup_printf ("type='signal',interface='%s',member='%s'", spi_interface_accessible, t);
+    if (!*matchrule)
+    {
+      g_free (t);
+      if (d) g_free (d);
+      return FALSE;
+    }
+  }
+  if (type) *type = t;
+  if (detail) *detail = d;
+  return TRUE;
+}
+
+static void listener_data_free (CSpiEventListenerEntry *e)
+{
+  g_free (e->event);
+  if (e->detail) g_free (e->detail);
+  g_free (e);
+}
+
+/**
+ * SPI_registerGlobalEventListener:
+ * @listener: the #AccessibleEventListener to be registered against an
+ *            event type.
+ * @eventType: a character string indicating the type of events for which
+ *            notification is requested.  Format is
+ *            EventClass:major_type:minor_type:detail
+ *            where all subfields other than EventClass are optional.
+ *            EventClasses include "object", "window", "mouse",
+ *            and toolkit events (e.g. "Gtk", "AWT").
+ *            Examples: "focus:", "Gtk:GtkWidget:button_press_event".
+ *
+ * Legal object event types:
+ *
+ *    (property change events)
+ *
+ *            object:property-change
+ *            object:property-change:accessible-name
+ *            object:property-change:accessible-description
+ *            object:property-change:accessible-parent
+ *            object:property-change:accessible-value
+ *            object:property-change:accessible-role
+ *            object:property-change:accessible-table-caption
+ *            object:property-change:accessible-table-column-description
+ *            object:property-change:accessible-table-column-header
+ *            object:property-change:accessible-table-row-description
+ *            object:property-change:accessible-table-row-header
+ *            object:property-change:accessible-table-summary
+ *
+ *    (other object events)
+ *
+ *            object:state-changed 
+ *            object:children-changed
+ *            object:visible-data-changed
+ *            object:selection-changed
+ *            object:text-selection-changed
+ *            object:text-changed
+ *            object:text-caret-moved
+ *            object:row-inserted
+ *            object:row-reordered
+ *            object:row-deleted
+ *            object:column-inserted
+ *            object:column-reordered
+ *            object:column-deleted
+ *            object:model-changed
+ *            object:active-descendant-changed
+ *
+ *  (window events)
+ *
+ *            window:minimize
+ *            window:maximize
+ *            window:restore
+ *            window:close
+ *            window:create
+ *            window:reparent
+ *            window:desktop-create
+ *            window:desktop-destroy
+ *            window:activate
+ *            window:deactivate
+ *            window:raise
+ *            window:lower
+ *            window:move
+ *            window:resize
+ *            window:shade
+ *            window:unshade
+ *            window:restyle
+ *
+ *  (other events)
+ *
+ *            focus:
+ *            mouse:abs
+ *            mouse:rel
+ *            mouse:b1p
+ *            mouse:b1r
+ *            mouse:b2p
+ *            mouse:b2r
+ *            mouse:b3p
+ *            mouse:b3r
+ *
+ * NOTE: this string may be UTF-8, but should not contain byte value 56
+ *            (ascii ':'), except as a delimiter, since non-UTF-8 string
+ *            delimiting functions are used internally.
+ *            In general, listening to
+ *            toolkit-specific events is not recommended.
+ *
+ * Add an in-process callback function to an existing AccessibleEventListener.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ **/
+SPIBoolean
+SPI_registerGlobalEventListener (AccessibleEventListener *listener,
+                                const char              *eventType)
+{
+  CSpiEventListenerEntry *e;
+  char *matchrule;
+  DBusError error;
+  GList *new_list;
+
+  if (!listener)
+    {
+      return FALSE;
+    }
+
+  e = g_new (CSpiEventListenerEntry, 1);
+  if (!e) return FALSE;
+  e->listener = listener;
+  parse_eventType (eventType, &e->event, &e->detail, &matchrule);
+  new_list = g_list_prepend (event_listeners, e);
+  if (!new_list)
+  {
+    listener_data_free (e);
+    return FALSE;
+  }
+  event_listeners = new_list;
+  dbus_error_init (&error);
+  dbus_bus_add_match (cspi_bus(), matchrule, &error);
+  if (error.message)
+  {
+    g_warning ("Adding match: %s", error.message);
+  }
+  return TRUE;
+}
+
+/**
+ * SPI_deregisterGlobalEventListenerAll:
+ * @listener: the #AccessibleEventListener to be registered against
+ *            an event type.
+ *
+ * deregisters an AccessibleEventListener from the registry, for all
+ *            event types it may be listening to. Use
+ *            AccessibleEventListener_unref to release the
+ *            listener reference.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ **/
+SPIBoolean
+SPI_deregisterGlobalEventListenerAll (AccessibleEventListener *listener)
+{
+  GList *l;
+
+  if (!listener)
+    {
+      return FALSE;
+    }
+
+  for (l = event_listeners; l;)
+  {
+    CSpiEventListenerEntry *e = l->data;
+    if (e->listener == listener)
+    {
+      listener_data_free (e);
+      l = g_list_remove (l, e);
+    }
+    else l = g_list_next (l);
+  }
+  return TRUE;
+}
+
+/**
+ * SPI_deregisterGlobalEventListener:
+ * @listener: the #AccessibleEventListener registered against an event type.
+ * @eventType: a string specifying the event type for which this
+ *             listener is to be deregistered.
+ *
+ * deregisters an AccessibleEventListener from the registry, for a specific
+ *             event type.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ **/
+SPIBoolean
+SPI_deregisterGlobalEventListener (AccessibleEventListener *listener,
+                                  const char              *eventType)
+{
+  char *type, *detail, *matchrule;
+  GList *l;
+
+  if (!parse_eventType (eventType, &type, &detail, &matchrule))
+  {
+    return FALSE;
+  }
+  if (!listener)
+    {
+      return FALSE;
+    }
+
+  for (l = event_listeners; l;)
+  {
+    CSpiEventListenerEntry *e = l->data;
+    if (e->listener == listener && !strcmp (e->event, type) && (e->detail == detail || !strcmp (e->detail, detail)))
+    {
+      DBusError error;
+      listener_data_free (e);
+      l = g_list_remove (l, e);
+      dbus_error_init (&error);
+      dbus_bus_remove_match (cspi_bus(), matchrule, &error);
+    }
+    else l = g_list_next (l);
+  }
+  g_free (type);
+  if (detail) g_free (detail);
+  g_free (matchrule);
+  return TRUE;
+}
+
+void
+cspi_dispatch_event (AccessibleEvent *e)
+{
+  char *event, *detail;
+  GList *l;
+
+  parse_eventType (e->type, &event, &detail, NULL);
+  for (l = event_listeners; l; l = g_list_next (l))
+  {
+    CSpiEventListenerEntry *entry = l->data;
+    if (!strcmp (event, entry->event) &&
+        (entry->detail == NULL || !strcmp (detail, entry->detail)))
+    {
+      CSpiEventListenerClass *klass = CSPI_EVENT_LISTENER_GET_CLASS (entry->listener);
+      if (klass->event) (*klass->event)(entry->listener, e);
+    }
+  }
+  if (detail) g_free (detail);
+  g_free (event);
+}
+
+DBusHandlerResult
+cspi_dbus_handle_event (DBusConnection *bus, DBusMessage *message, void *data)
+{
+  char *detail = NULL;
+  const char *event = dbus_message_get_member (message);
+  DBusMessageIter iter, iter_variant;
+  dbus_message_iter_init (message, &iter);
+  AccessibleEvent e;
+  dbus_int32_t detail1, detail2;
+  char *p;
+
+  g_return_if_fail (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_STRING);
+  dbus_message_iter_get_basic (&iter, &detail);
+  dbus_message_iter_next (&iter);
+  g_return_if_fail (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_INT32);
+  dbus_message_iter_get_basic (&iter, &detail1);
+  e.detail1 = detail1;
+  dbus_message_iter_next (&iter);
+  g_return_if_fail (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_INT32);
+  dbus_message_iter_get_basic (&iter, &detail2);
+  e.detail2 = detail2;
+  dbus_message_iter_next (&iter);
+printf("event: %s %s\n", event, detail);
+  e.type = g_strdup (event);
+  p = strchr (e.type, '_');
+  if (p) *p = ':';
+  p = g_strconcat (e.type, ":", detail, NULL);
+  if (p)
+  {
+    g_free (e.type);
+    e.type = p;
+  }
+    while ((p = strchr (p, '_'))) *p = '-';
+  e.source = cspi_ref_accessible (dbus_message_get_sender(message), dbus_message_get_path(message));
+  dbus_message_iter_recurse (&iter, &iter_variant);
+  switch (dbus_message_iter_get_arg_type (&iter_variant))
+  {
+    case DBUS_TYPE_OBJECT_PATH:
+    {
+      char *p;
+      dbus_message_iter_get_basic (&iter_variant, &p);
+      e.v_type = EVENT_DATA_OBJECT;
+      e.v.accessible = cspi_ref_accessible (dbus_message_get_sender(message), p);
+      break;
+    }
+    case DBUS_TYPE_STRING:
+    {
+      char *p;
+      dbus_message_iter_get_basic (&iter_variant, &p);
+      e.v_type = EVENT_DATA_STRING;
+      e.v.text = g_strdup (p);
+      break;
+    }
+    case DBUS_TYPE_STRUCT:
+    {
+      if (demarshal_rect (&iter_variant, &e.v.rect))
+      {
+       e.v_type = EVENT_DATA_RECT;
+      }
+      break;
+    }
+  default:
+    break;
+  }
+  cspi_dispatch_event (&e);
+  return DBUS_HANDLER_RESULT_HANDLED;
+}
diff --git a/cspi/spi_hyperlink.c b/cspi/spi_hyperlink.c
new file mode 100644 (file)
index 0000000..45f7256
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <cspi/spi-private.h>
+
+/**
+ * AccessibleHyperlink_ref:
+ * @obj: a pointer to the #AccessibleHyperlink object on which to operate.
+ *
+ * Increment the reference count for an #AccessibleHyperlink object.
+ **/
+void
+AccessibleHyperlink_ref (AccessibleHyperlink *obj)
+{
+  cspi_object_ref (obj);
+}
+
+/**
+ * AccessibleHyperlink_unref:
+ * @obj: a pointer to the #AccessibleHyperlink object on which to operate.
+ *
+ * Decrement the reference count for an #AccessibleHyperlink object.
+ **/
+void
+AccessibleHyperlink_unref (AccessibleHyperlink *obj)
+{
+  cspi_object_unref (obj);
+}
+
+/**
+ * AccessibleHyperlink_getNAnchors:
+ * @obj: a pointer to the #AccessibleHyperlink object on which to operate.
+ *
+ * Get the total number of anchors which an #AccessibleHyperlink implementor has.
+ *       Though typical hyperlinks have only one anchor, client-side image maps and
+ *       other hypertext objects may potentially activate or refer to multiple
+ *       URIs.  For each anchor there is a corresponding URI and object.
+ * @see AccessibleHyperlink_getURI() and AccessibleHyperlink_getObject().
+ *
+ * Returns: a #long indicating the number of anchors in this hyperlink.
+ **/
+long
+AccessibleHyperlink_getNAnchors (AccessibleHyperlink *obj)
+{
+  dbus_int16_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, -1);
+
+  cspi_dbus_get_property (obj, spi_interface_hyperlink, "nAnchors", NULL, "n", &retval);
+
+  cspi_return_val_if_ev ("getNAnchors", -1);
+
+  return retval;
+}
+
+/**
+ * AccessibleHyperlink_getURI:
+ * @obj: a pointer to the #AccessibleHyperlink implementor on which to operate.
+ * @i: a (zero-index) long integer indicating which hyperlink anchor to query.
+ *
+ * Get the URI associated with a particular hyperlink anchor.  
+ *
+ * Returns: a UTF-8 string giving the URI of the @ith hyperlink anchor.
+ **/
+char *
+AccessibleHyperlink_getURI (AccessibleHyperlink *obj,
+                            long int             i)
+{
+  dbus_int32_t d_i = i;
+  char *retval;
+
+  cspi_return_val_if_fail (obj != NULL, NULL);
+
+  cspi_dbus_call (obj, spi_interface_hyperlink, "getURI", NULL, "i=>s", d_i, &retval);
+
+  cspi_return_val_if_ev ("getURI", NULL);
+
+  return retval;
+}
+
+/**
+ * AccessibleHyperlink_getObject:
+ * @obj: a pointer to the #AccessibleHyperlink implementor on which to operate.
+ * @i: a (zero-index) long integer indicating which hyperlink anchor to query.
+ *
+ * Get the object associated with a particular hyperlink anchor, as an #Accessible. 
+ *
+ * Returns: an #Accessible that represents the object associated with the @ith anchor
+ *        of the specified #AccessibleHyperlink.
+ **/
+Accessible*
+AccessibleHyperlink_getObject (AccessibleHyperlink *obj,
+                               long int             i)
+{
+  dbus_int32_t d_i = i;
+  char *path;
+  Accessible *retval;
+
+  cspi_return_val_if_fail (obj != NULL, NULL);
+
+  cspi_dbus_call (obj, spi_interface_hyperlink, "getObject", NULL, "i=>o", d_i, &path);
+  retval = cspi_ref_related_accessible (obj, path);
+  g_free (path);
+}
+
+/**
+ * AccessibleHyperlink_getIndexRange:
+ * @obj: a pointer to the #AccessibleHyperlink implementor on which to operate.
+ * @startIndex: a pointer to a long integer into which the starting
+ *       offset of the text associated with this #AccessibleHyperlink is returned.
+ * @endIndex: a pointer to a long integer into which the offset of the first character
+ *       after the text associated with this #AccessibleHyperlink is returned.
+ *
+ *
+ * Get the starting and ending character offsets of the text range associated with
+ *       a #AccessibleHyperlink, in its originating #AccessibleHypertext.
+ **/
+void
+AccessibleHyperlink_getIndexRange (AccessibleHyperlink *obj,
+                                   long int *startIndex,
+                                   long int *endIndex)
+{
+  dbus_int32_t si, ei;
+
+  cspi_return_if_fail (obj != NULL);
+
+  cspi_dbus_get_property (obj, spi_interface_hyperlink, "startIndex", NULL, "i", &si);
+ cspi_return_if_ev ("startIndex");
+  cspi_dbus_get_property (obj, spi_interface_hyperlink, "endIndex", NULL, "i", &ei);
+ cspi_return_if_ev ("endIndex");
+ *startIndex = si;
+ *endIndex = ei; 
+}
+
+/**
+ * AccessibleHyperlink_isValid:
+ * @obj: a pointer to the #AccessibleHyperlink on which to operate.
+ *
+ * Tell whether an #AccessibleHyperlink object is still valid with respect to its
+ *          originating hypertext object.
+ *
+ * Returns: #TRUE of the specified #AccessibleHyperlink is still valid with respect
+ *          to its originating #AccessibleHypertext object, #FALSE otherwise.
+ **/
+SPIBoolean
+AccessibleHyperlink_isValid (AccessibleHyperlink *obj)
+{
+  dbus_bool_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_hyperlink, "isValid", NULL, "=>b", &retval);
+
+  cspi_return_val_if_ev ("isValid", FALSE);
+
+  return retval;
+}
+
+
diff --git a/cspi/spi_hypertext.c b/cspi/spi_hypertext.c
new file mode 100644 (file)
index 0000000..e6f7a7b
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <cspi/spi-private.h>
+
+/**
+ * AccessibleHypertext_ref:
+ * @obj: a pointer to the #AccessibleHypertext object on which to operate.
+ *
+ * Increment the reference count for an #AccessibleHypertext object.
+ *       Since AccessibleHypertext is derived from AccessibleText,
+ *       this is the same as AccessibleText_unref().
+ **/
+void
+AccessibleHypertext_ref (AccessibleHypertext *obj)
+{
+  cspi_object_ref (obj);
+}
+
+/**
+ * AccessibleHypertext_unref:
+ * @obj: a pointer to the #AccessibleHypertext object on which to operate.
+ *
+ * Decrement the reference count for an #AccessibleHypertext object.
+ *       Since AccessibleHypertext is derived from AccessibleText,
+ *       this is the same as AccessibleText_unref().
+ **/
+void
+AccessibleHypertext_unref (AccessibleHypertext *obj)
+{
+  cspi_object_unref (obj);
+}
+
+/**
+ * AccessibleHypertext_getNLinks:
+ * @obj: a pointer to the #AccessibleHypertext implementor on which to operate.
+ *
+ * Get the total number of #AccessibleHyperlinks which an
+ *        #AccessibleHypertext implementor has.
+ *
+ * Returns: a #long indicating the number of #AccessibleHyperlinks
+ *        of the #AccessibleHypertext implementor, or -1 if
+ *        the number cannot be determined (for example, if the
+ *        #AccessibleHypertext object is so large that it is not
+ *        all currently in the memory cache).
+ **/
+long
+AccessibleHypertext_getNLinks (AccessibleHypertext *obj)
+{
+  dbus_int32_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_hypertext, "getNLinks", NULL, "=>i", &retval);
+
+  cspi_return_val_if_ev ("getNLinks", -1);
+
+  return retval;
+}
+
+/**
+ * AccessibleHypertext_getLink:
+ * @obj: a pointer to the #AccessibleHypertext implementor on which to operate.
+ * @linkIndex: a (zero-index) long integer indicating which hyperlink to query.
+ *
+ * Get the #AccessibleHyperlink object at a specified index.
+ *
+ * Returns: the #AccessibleHyperlink object specified by #linkIndex.
+ **/
+AccessibleHyperlink *
+AccessibleHypertext_getLink (AccessibleHypertext *obj,
+                             long int             linkIndex)
+{
+  dbus_int32_t d_linkIndex = linkIndex;
+  char *path;
+  AccessibleHyperlink *retval;
+       
+  cspi_return_val_if_fail (obj != NULL, NULL);
+
+  cspi_dbus_call (obj, spi_interface_hypertext, "getLink", NULL, "i=>o", d_linkIndex, &path);
+
+  cspi_return_val_if_ev ("getLink", NULL); 
+
+  retval = cspi_ref_related_accessible (obj, path);
+  g_free (path);
+  
+  return retval;
+}
+
+/**
+ * AccessibleHypertext_getLinkIndex:
+ * @obj: a pointer to the #AccessibleHypertext implementor on which to operate.
+ * @characterOffset: an integer specifying the character offset to query.
+ *
+ * Get the index of the #AccessibleHyperlink object at a specified
+ *        character offset.
+ *
+ * Returns: the linkIndex of the #AccessibleHyperlink active at
+ *        character offset @characterOffset, or -1 if there is
+ *        no hyperlink at the specified character offset.
+ **/
+long
+AccessibleHypertext_getLinkIndex (AccessibleHypertext *obj,
+                                  long int             characterOffset)
+{
+  dbus_int32_t d_characterOffset = characterOffset;
+  dbus_int32_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, -1);
+
+  cspi_dbus_call (obj, spi_interface_hypertext, "getLinkIndex", NULL, "i=>i", d_characterOffset, &retval);
+
+  cspi_return_val_if_ev ("getLinkIndex", -1);
+
+  return retval;
+}
+
+
diff --git a/cspi/spi_listener.c b/cspi/spi_listener.c
new file mode 100644 (file)
index 0000000..3429386
--- /dev/null
@@ -0,0 +1,406 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2002 Ximian Inc.
+ * Copyright 2002 Sun Microsystems, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "spi-private.h"
+#include <stdio.h>
+
+typedef struct
+{
+  union
+    {
+      AccessibleEventListenerCB     event;
+      AccessibleDeviceListenerCB    device_event;
+      gpointer                      method;
+    } cb;
+  gpointer user_data;
+} EventHandler;
+
+GObjectClass *event_parent_class;
+GObjectClass *device_parent_class;
+
+static guint32 _e_id = 0;
+
+/*
+ * Misc. helpers.
+ */
+
+static EventHandler *
+cspi_event_handler_new (gpointer method, gpointer user_data)
+{
+  EventHandler *eh = g_new0 (EventHandler, 1);
+
+  eh->cb.method = method;
+  eh->user_data = user_data;
+
+  return eh;
+}
+
+static void
+cspi_event_handler_free (EventHandler *handler)
+{
+  g_free (handler);
+}
+
+static GList *
+cspi_event_list_remove_by_cb (GList *list, gpointer callback)
+{
+  GList *l, *next;
+       
+  for (l = list; l; l = next)
+    {
+      EventHandler *eh = l->data;
+      next = l->next;
+
+      if (eh->cb.method == callback)
+      {
+        list = g_list_delete_link (list, l);
+       cspi_event_handler_free (eh);
+      }
+    }
+
+  return list;
+}
+
+/*
+ * Standard event dispatcher
+ */
+
+G_DEFINE_TYPE (CSpiEventListener, cspi_event_listener,
+                         G_TYPE_OBJECT)
+
+static void
+cspi_event (CSpiEventListener    *listener,
+           AccessibleEvent *event)
+{
+  GList *l;
+  CSpiEventListener *clistener = (CSpiEventListener *) listener;
+  InternalEvent     *ievent;
+  AccessibleEvent   *aevent;
+  
+  ievent = g_new0(InternalEvent, 1);
+  ievent->event.type    = g_strdup (event->type);
+  ievent->event.source  = event->source;
+  ievent->event.detail1 = event->detail1;
+  ievent->event.detail2 = event->detail2;
+  ievent->event.v_type = event->v_type;
+  if (event->v_type == EVENT_DATA_STRING)
+  {
+    ievent->event.v.text = g_strdup (event->v.text);
+  }
+  else memcpy (&ievent->event.v, &event->v, sizeof(event->v));
+  ievent->id            = _e_id++;
+  ievent->magic         = SPI_INTERNAL_EVENT_MAGIC;
+  ievent->ref_count     = 0;
+  aevent = (AccessibleEvent *)ievent;
+  Accessible_ref (aevent->source);
+  AccessibleEvent_ref (aevent);
+
+  /* FIXME: re-enterancy hazard on this list */
+  for (l = clistener->callbacks; l; l = l->next)
+    {
+      EventHandler *eh = l->data;
+      /* cast hides our private stuff from client handlers */
+      eh->cb.event (aevent, eh->user_data);
+    }
+
+  AccessibleEvent_unref (aevent);
+}
+
+static guint listener_id = 0;
+static GList *device_listeners = NULL;
+
+static gboolean
+id_is_free (guint id)
+{
+  GList *l;
+
+  for (l = device_listeners; l; l = g_list_next (l))
+  {
+    CSpiDeviceListener *listener = l->data;
+    if (listener->id == id) return FALSE;
+  }
+  return TRUE;
+}
+
+static void remove_listener (GObject *obj, gpointer data)
+{
+  device_listeners = g_list_remove (device_listeners, obj);
+}
+
+static void
+cspi_event_listener_instance_init (CSpiEventListener *listener)
+{
+}
+
+static void
+cspi_event_listener_finalize (GObject *object)
+{
+  CSpiEventListener *listener = (CSpiEventListener *) object;
+  GList *l;
+  
+  for (l = listener->callbacks; l; l = l->next)
+    {
+      cspi_event_handler_free (l->data);
+    }
+  
+  g_list_free (listener->callbacks);
+
+  event_parent_class->finalize (object);
+}
+
+static void
+cspi_event_listener_class_init (CSpiEventListenerClass *klass)
+{
+  GObjectClass *object_class = (GObjectClass *) klass;
+
+  event_parent_class = g_type_class_peek_parent (klass);
+  object_class->finalize = cspi_event_listener_finalize;
+
+  klass->event = cspi_event;
+}
+
+gpointer
+cspi_event_listener_new (void)
+{
+  CSpiEventListener *listener;
+
+  listener = g_object_new (cspi_event_listener_get_type (), NULL);
+
+  return listener;
+}
+
+static void
+cspi_event_listener_init (CSpiEventListener *listener)
+{
+}
+
+void
+cspi_event_listener_add_cb (AccessibleEventListener  *al,
+                           AccessibleEventListenerCB callback,
+                           void                     *user_data)
+{
+  CSpiEventListener *listener = al;
+
+  g_return_if_fail (CSPI_IS_EVENT_LISTENER (listener));
+
+  listener->callbacks = g_list_prepend (listener->callbacks,
+                                       cspi_event_handler_new ((void *) callback, user_data));
+}
+
+void
+cspi_event_listener_remove_cb (AccessibleEventListener  *al,
+                              AccessibleEventListenerCB callback)
+{
+  CSpiEventListener *listener = al;
+
+  g_return_if_fail (CSPI_IS_EVENT_LISTENER (listener));
+
+  listener->callbacks = cspi_event_list_remove_by_cb (listener->callbacks, (void *) callback);
+}
+
+/* 
+ * Device event handler
+ */
+static gboolean
+cspi_device_event (CSpiDeviceListener               *listener,
+                  const Accessibility_DeviceEvent *event)
+{
+  GList *l;
+  CSpiDeviceListener *clistener = (CSpiDeviceListener *) listener;
+  AccessibleDeviceEvent anevent;
+  gboolean handled = FALSE;
+
+  switch (event->type)
+    {
+      case Accessibility_KEY_PRESSED_EVENT:
+       anevent.type = SPI_KEY_PRESSED;
+       break;
+      case Accessibility_KEY_RELEASED_EVENT:
+       anevent.type = SPI_KEY_RELEASED;
+       break;
+      case Accessibility_BUTTON_PRESSED_EVENT:
+       anevent.type = SPI_BUTTON_PRESSED;
+       break;
+      case Accessibility_BUTTON_RELEASED_EVENT:
+       anevent.type = SPI_BUTTON_RELEASED;
+       break;
+      default:
+       anevent.type = 0;
+       break;
+    }
+  anevent.keyID     = event->id;
+  anevent.keycode   = event->hw_code;
+  anevent.timestamp = event->timestamp;
+  anevent.keystring = g_strdup (event->event_string);
+  anevent.modifiers = event->modifiers;
+  anevent.is_text = event->is_text;
+
+  /* FIXME: re-enterancy hazard on this list */
+  for (l = clistener->callbacks; l; l = l->next)
+    {
+      EventHandler *eh = l->data;
+
+      if ((handled = eh->cb.device_event (&anevent, eh->user_data)))
+        {
+         break;
+       }
+    }
+  g_free (anevent.keystring);
+
+  return handled;
+}
+
+static void
+cspi_device_listener_init (CSpiDeviceListener *listener)
+{
+  GList *new_list;
+
+  do
+  {
+    listener->id = listener_id++;
+  } while (!id_is_free (listener->id));
+  new_list = g_list_append (device_listeners, listener);
+  if (new_list) device_listeners = new_list;
+}
+
+static void
+cspi_device_listener_finalize (GObject *object)
+{
+  CSpiDeviceListener *listener = (CSpiDeviceListener *) object;
+  GList *l;
+  
+  for (l = listener->callbacks; l; l = l->next)
+    {
+      cspi_event_handler_free (l->data);
+    }
+  
+  g_list_free (listener->callbacks);
+
+  device_parent_class->finalize (object);
+}
+
+static void
+cspi_device_listener_class_init (CSpiDeviceListenerClass *klass)
+{
+  GObjectClass *object_class = (GObjectClass *) klass;
+
+  device_parent_class = g_type_class_peek_parent (klass);
+  object_class->finalize = cspi_device_listener_finalize;
+
+  klass->device_event = cspi_device_event;
+}
+
+G_DEFINE_TYPE (CSpiDeviceListener, cspi_device_listener,
+                         G_TYPE_OBJECT)
+
+gpointer
+cspi_device_listener_new (void)
+{
+  CSpiEventListener *listener = g_object_new (cspi_device_listener_get_type (), NULL);
+
+  return listener;
+}
+
+void
+cspi_device_listener_add_cb (AccessibleDeviceListener  *al,
+                            AccessibleDeviceListenerCB callback,
+                            void                      *user_data)
+{
+  CSpiDeviceListener *listener = al;
+
+  g_return_if_fail (CSPI_IS_DEVICE_LISTENER (listener));
+
+  listener->callbacks = g_list_prepend (listener->callbacks,
+                                       cspi_event_handler_new ((void *)callback, user_data));
+}
+
+void
+cspi_device_listener_remove_cb (AccessibleDeviceListener  *al,
+                               AccessibleDeviceListenerCB callback)
+{
+  CSpiDeviceListener *listener = al;
+
+  g_return_if_fail (CSPI_IS_DEVICE_LISTENER (listener));
+
+  listener->callbacks = cspi_event_list_remove_by_cb (listener->callbacks, (void *) callback);
+}
+
+void
+cspi_event_listener_unref (AccessibleEventListener *listener)
+{
+  g_object_unref (G_OBJECT (listener));
+}
+
+void
+cspi_device_listener_unref (AccessibleDeviceListener *listener)
+{
+  g_object_unref (G_OBJECT (listener));
+}
+
+static const char *deviceEvent_type = "(uinnisb)";
+
+DBusHandlerResult
+cspi_dbus_handle_deviceEvent (DBusConnection *bus, DBusMessage *message, void *data)
+{
+  const char *path = dbus_message_get_path (message);
+  int id;
+  Accessibility_DeviceEvent event;
+    CSpiDeviceListener *listener;
+  DBusMessageIter iter;
+  CSpiDeviceListenerClass *klass;
+  dbus_bool_t retval = FALSE;
+  GList *l;
+  DBusMessage *reply;
+  void *p = &event;
+
+  if (sscanf (path, "/org/freedesktop/atspi/listeners/%d", &id) != 1)
+  {
+    g_warning ("Bad listener path: %s\n", path);
+    goto done;
+  }
+  for (l = device_listeners; l; l = g_list_next (l))
+  {
+    listener = l->data;
+    if (listener->id == id) break;
+  }
+  if (!l)
+  {
+    goto done;
+  }
+  dbus_message_iter_init (message, &iter);
+  dbind_any_demarshal (iter, &deviceEvent_type, &p);
+  klass = CSPI_DEVICE_LISTENER_GET_CLASS (listener);
+  if (klass->device_event)
+  {
+    retval = (*klass->device_event) (listener, &event);
+  }
+done:
+  reply = dbus_message_new_method_return (message);
+  if (reply)
+  {
+    dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &retval, DBUS_TYPE_INVALID);
+    dbus_connection_send (cspi_bus(), reply, NULL);
+    dbus_message_unref (reply);
+  }
+  return DBUS_HANDLER_RESULT_HANDLED;
+}
diff --git a/cspi/spi_main.c b/cspi/spi_main.c
new file mode 100644 (file)
index 0000000..17c394e
--- /dev/null
@@ -0,0 +1,1085 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ *
+ * Basic SPI initialization and event loop function prototypes
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <cspi/spi-private.h>
+#include "spi.h"
+
+#undef DEBUG_OBJECTS
+
+static DBusConnection *bus = NULL;
+static GHashTable *apps = NULL;
+static GHashTable *live_refs = NULL;
+static GQueue *exception_handlers = NULL;
+static DBusError exception;
+
+static void
+cspi_object_release (gpointer value)
+{
+}
+
+gboolean
+cspi_exception_throw (DBusError *error, char *desc_prefix)
+{
+  SPIExceptionHandler *handler = NULL;
+  SPIException ex;
+  if (exception_handlers) handler = g_queue_peek_head (exception_handlers);
+
+  ex.type = SPI_EXCEPTION_SOURCE_UNSPECIFIED;
+  ex.source = NULL;
+  ex.code = SPI_EXCEPTION_UNSPECIFIED;
+  ex.error = error;
+  // TODO: Fill in description
+  
+  if (handler)
+    return (*handler) (&ex, FALSE);
+  else
+    return FALSE; /* means exception was not handled */
+}
+
+const char *spi_path_dec = SPI_DBUS_PATH_DEC;
+const char *spi_path_registry = SPI_DBUS_PATH_REGISTRY;
+const char *spi_bus_registry = SPI_DBUS_NAME_REGISTRY;
+const char *spi_path_desktop = SPI_DBUS_PATH_DESKTOP;
+const char *spi_interface_accessible = SPI_DBUS_INTERFACE_ACCESSIBLE;
+const char *spi_interface_action = SPI_DBUS_INTERFACE_ACTION;
+const char *spi_interface_application = SPI_DBUS_INTERFACE_APPLICATION;
+const char *spi_interface_component = SPI_DBUS_INTERFACE_COMPONENT;
+const char *spi_interface_dec = SPI_DBUS_INTERFACE_DEC;
+const char *spi_interface_desktop = SPI_DBUS_INTERFACE_DESKTOP;
+const char *spi_interface_device_event_listener = SPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER;
+const char *spi_interface_document = SPI_DBUS_INTERFACE_DOCUMENT;
+const char *spi_interface_editable_text = SPI_DBUS_INTERFACE_EDITABLE_TEXT;
+const char *spi_interface_hyperlink = SPI_DBUS_INTERFACE_HYPERLINK;
+const char *spi_interface_hypertext = SPI_DBUS_INTERFACE_HYPERTEXT;
+const char *spi_interface_image = SPI_DBUS_INTERFACE_IMAGE;
+const char *spi_interface_registry = SPI_DBUS_INTERFACE_REGISTRY;
+const char *spi_interface_selection = SPI_DBUS_INTERFACE_SELECTION;
+const char *spi_interface_table = SPI_DBUS_INTERFACE_TABLE;
+const char *spi_interface_text = SPI_DBUS_INTERFACE_TEXT;
+const char *spi_interface_tree = SPI_DBUS_INTERFACE_TREE;
+const char *spi_interface_value = SPI_DBUS_INTERFACE_VALUE;
+
+static const char *interfaces[] =
+{
+  SPI_DBUS_INTERFACE_ACCESSIBLE,
+  SPI_DBUS_INTERFACE_ACTION,
+  SPI_DBUS_INTERFACE_APPLICATION,
+  SPI_DBUS_INTERFACE_COMPONENT,
+  SPI_DBUS_INTERFACE_DOCUMENT,
+  SPI_DBUS_INTERFACE_EDITABLE_TEXT,
+  SPI_DBUS_INTERFACE_HYPERLINK,
+  SPI_DBUS_INTERFACE_HYPERTEXT,
+  SPI_DBUS_INTERFACE_IMAGE,
+  "org.freedesktop.atspi.LoginHelper",
+  SPI_DBUS_INTERFACE_SELECTION,
+  "org.freedesktop.atspi.Selector",
+  SPI_DBUS_INTERFACE_TABLE,
+  SPI_DBUS_INTERFACE_TEXT,
+  SPI_DBUS_INTERFACE_VALUE,
+  NULL
+};
+
+static gint get_iface_num (const char *iface)
+{
+  // TODO: Use a binary search or hash to improve performance
+  int i;
+
+  for (i = 0; interfaces[i]; i++)
+  {
+    if (!strcmp(iface, interfaces[i])) return i;
+  }
+  return -1;
+}
+
+SPIBoolean
+cspi_accessible_is_a (Accessible *accessible,
+                     const char *interface_name)
+{
+  int n;
+
+  if (accessible == NULL)
+    {
+      return FALSE;
+    }
+
+  n = get_iface_num (interface_name);
+  if (n == -1) return FALSE;
+  return (SPIBoolean)((accessible->interfaces & (1 << n))? TRUE: FALSE);
+}
+
+static GHashTable *
+cspi_get_live_refs (void)
+{
+  if (!live_refs) 
+    {
+      live_refs = g_hash_table_new (g_direct_hash, g_direct_equal);
+    }
+  return live_refs;
+}
+
+DBusConnection *
+cspi_bus (void)
+{
+  return bus;
+}
+
+SPIBoolean
+cspi_exception (void)
+{
+  if (dbus_error_is_set (&exception))
+  {
+    dbus_error_free (&exception);
+    return TRUE;
+  }
+  return FALSE;
+}
+
+SPIBoolean cspi_check_ev (const char *error_string)
+{
+  // TODO: Store exception
+  return FALSE;
+}
+
+Accessible *
+cspi_object_add (Accessible *accessible)
+{
+  if (accessible) cspi_object_ref (accessible);
+  return accessible;
+}
+
+void
+cspi_object_ref (Accessible *accessible)
+{
+  g_return_if_fail (accessible != NULL);
+
+printf("ref: %p (%d)\n", accessible, accessible->ref_count);fflush(stdout);
+  accessible->ref_count++;
+  g_hash_table_insert (live_refs, accessible, accessible);
+}
+
+#define APP_IS_REGISTRY(app) (!strcmp (app->bus_name, "org.freedesktop.atspi.registry"))
+
+static void
+cspi_object_unref_internal (Accessible *accessible, gboolean defunct)
+{
+  gboolean cached;
+
+  if (accessible == NULL)
+    {
+      return;
+    }
+
+printf("unref: %p (%d)\n", accessible, accessible->ref_count - 1);fflush(stdout);
+  if (--accessible->ref_count == 0 || (accessible->ref_count == 1 && !defunct) && g_hash_table_lookup (live_refs, accessible))
+  {
+    AccessibleEvent e;
+    memset (&e, 0, sizeof(e));
+    e.type = "object:state-change:defunct";
+    e.source = accessible;
+    e.detail1 = 1;
+    cspi_dispatch_event (&e);
+    g_hash_table_remove (live_refs, accessible);
+  }
+  if (accessible->ref_count == 0)
+  {
+    if (APP_IS_REGISTRY (accessible->app))
+    {
+      g_free (accessible->v.path);
+    }
+    g_free(accessible);
+  }
+}
+
+void
+cspi_object_unref (Accessible *accessible)
+{
+  cspi_object_unref_internal (accessible, FALSE);
+}
+
+static void
+cspi_cleanup (void)
+{
+  GHashTable *refs;
+
+  cspi_streams_close_all ();
+
+  refs = live_refs;
+  live_refs = NULL;
+  if (refs)
+    {
+      g_hash_table_destroy (refs);
+    }
+}
+
+static gboolean SPI_inited = FALSE;
+
+static GHashTable *app_hash = NULL;
+
+static Accessible *
+ref_accessible (CSpiApplication *app, const char *path)
+{
+  int id;
+  guint *id_val;
+
+  if (sscanf (path, "/org/freedesktop/atspi/accessible/%d", &id) != 1)
+  {
+    return NULL;
+  }
+  Accessible *a = g_hash_table_lookup (app->hash, &id);
+  if (a)
+  {
+    cspi_object_ref (a);
+printf("Got %p from %p for %d\n", a, app->hash, id);fflush(stdout);
+    return a;
+  }
+  id_val = g_new (guint, 1);
+  if (!id_val) return NULL;
+  *id_val = id;
+  a = g_new0 (Accessible, 1);
+  if (!a)
+  {
+    g_free (id_val);
+    return NULL;
+  }
+printf("Inserting %p into %p for %d\n", a, app->hash, *id_val);
+  g_hash_table_insert (app->hash, id_val, a);
+  a->app = app;
+  a->v.id = id;
+  a->ref_count = 2;    /* one for the caller, one for the hash */
+  return a;
+}
+
+static CSpiApplication *
+cspi_get_application (const char *bus_name)
+{
+  CSpiApplication *app = NULL;
+  char *bus_name_dup;
+
+  if (!app_hash)
+  {
+    app_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_hash_table_unref);
+    if (!app_hash) return;
+  }
+  app = g_hash_table_lookup (app_hash, bus_name);
+  if (app) return app;
+  bus_name_dup = g_strdup (bus_name);
+  if (!bus_name_dup) return NULL;
+  // TODO: change below to something that will send state-change:defunct notification if necessary */
+  app = g_new (CSpiApplication, 1);
+  if (!app) return NULL;
+  app->bus_name = bus_name_dup;
+  if (APP_IS_REGISTRY (app))
+  {
+    app->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, cspi_object_unref);
+  }
+  else
+  {
+    app->hash = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, cspi_object_unref);
+  }
+  g_hash_table_insert (app_hash, bus_name_dup, app);
+  return app;
+}
+
+typedef struct
+{
+  char *path;
+  char *parent;
+  GArray *children;
+  GArray *interfaces;
+  char *name;
+  dbus_uint32_t role;
+  char *description;
+} CACHE_ADDITION;
+
+/* Update the cache with added/modified objects and free the array */
+static void
+handle_additions (CSpiApplication*app, GArray *additions)
+{
+  gint i, j;
+  GList *l, *new_list;
+
+  if (!additions)
+  {
+    return;
+  }
+  for (i = 0; i < additions->len; i++)
+  {
+    CACHE_ADDITION *ca = &g_array_index (additions, CACHE_ADDITION, i);
+    Accessible *a = ref_accessible (app, ca->path);
+      /* Note: children don't hold refs for their parents or vice versa */
+    a->parent = ref_accessible (app, ca->parent);
+    if (a->parent) cspi_object_unref (a->parent);
+    if (a->children)
+    {
+      g_list_free (a->children);
+      a->children = NULL;
+    }
+    for (j = 0; j < ca->children->len; j++)
+    {
+      const char *child_path = g_array_index (ca->children, const char *, j);
+      Accessible *child = ref_accessible (app, child_path);
+      new_list = g_list_append (a->children, child);
+      if (new_list) a->children = new_list;
+      cspi_object_unref (child);
+    }
+    a->interfaces = 0;
+    for (j = 0; j < ca->interfaces->len; j++)
+    {
+      const char *iface = g_array_index (ca->interfaces, const char *, j);
+      if (!strcmp (iface, "org.freedesktop.DBus.Introspectable")) continue;
+      gint n = get_iface_num (iface);
+      if (n == -1)
+      {
+       g_warning ("Unknown interface %s", iface);
+      }
+      else a->interfaces |= (1 << n);
+      g_free (iface);
+    }
+    if (a->name) g_free (a->name);
+    a->name = ca->name;
+    a->role = ca->role;
+    if (a->description) g_free (a->description);
+    a->description = ca->description;
+    g_array_free (ca->interfaces, TRUE);
+    g_array_free (ca->children, TRUE);
+    /* This is a bit of a hack since ref_accessible sets ref_count to 2
+     * for a new object, one of the refs being for the cache */
+    cspi_object_unref (a);
+  }
+  g_array_free (additions, TRUE);
+}
+
+static void
+handle_removals (CSpiApplication *app, GArray *removals)
+{
+  gint j;
+
+  if (!removals) return;
+  for (j = 0; j < removals->len; j++)
+  {
+    const char *path = g_array_index (removals, const char *, j);
+    Accessible *a = ref_accessible (app, path);
+    if (a->parent && g_list_find (a->parent->children, a))
+    {
+      a->parent->children = g_list_remove (a->parent->children, a);
+      /* Note: children don't hold refs for their parents or vice versa */
+    }
+    g_hash_table_remove (app->hash, &a->v.id);
+    cspi_object_unref_internal (a, TRUE);      /* unref our own ref */
+  }
+  g_array_free (removals, TRUE);
+}
+
+static gboolean
+add_app_to_desktop (Accessible *a, const char *bus_name)
+{
+  DBusError error;
+  char *root_path;
+
+  dbus_error_init (&error);
+  if (dbind_connection_method_call (bus, bus_name, "/org/freedesktop/atspi/tree", spi_interface_tree, "getRoot", &error, "=>o", &root_path))
+  {
+    Accessible *obj = cspi_ref_accessible (bus_name, root_path);
+    if (obj)
+    {
+      GList *new_list = g_list_append (a->children, obj);
+      if (new_list)
+      {
+       a->children = new_list;
+       return TRUE;
+      }
+    }
+    g_free (root_path);
+  }
+  else
+  {
+    g_warning ("Error calling getRoot for %s: %s", bus_name, error.message);
+  }
+  return FALSE;
+}
+
+static void
+send_children_change (Accessible *parent, Accessible *child, gboolean add)
+{
+  AccessibleEvent e;
+
+  memset (&e, 0, sizeof(e));
+  e.type = (add? "object:children-change:add": "object:children-change:remove");
+  e.source = parent;
+  e.detail1 = g_list_index (parent->children, child);
+  cspi_dispatch_event (&e);
+}
+
+static void
+unref_object_and_children (Accessible *obj)
+{
+  GList *l;
+
+  for (l = obj->children; l; l = l->next)
+  {
+    unref_object_and_children (l->data);
+  }
+  cspi_object_unref_internal (obj, TRUE);
+}
+
+static gboolean
+remove_app_from_desktop (Accessible *a, const char *bus_name)
+{
+  GList *l;
+  Accessible *child;
+
+  for (l = a->children; l; l = l->next)
+  {
+    child = l->data;
+    if (!strcmp (bus_name, child->app->bus_name)) break;
+  }
+  if (!l)
+  {
+    g_warning ("Removing unregistered app %s; doing nothing\n", bus_name);
+    return FALSE;
+  }
+  send_children_change (a, child, FALSE);
+  a->children = g_list_remove (a->children, child);
+  unref_object_and_children (child);
+  return TRUE;
+}
+
+static Accessible *
+ref_accessible_desktop (CSpiApplication *app, const char *path)
+{
+  char *path_dup;
+  DBusError error;
+  GArray *apps = NULL;
+  GArray *additions;
+  gint i;
+
+  Accessible *a = g_hash_table_lookup (app->hash, path);
+printf("got %p from %p for %s\n", a, app_hash, path);
+  if (a)
+  {
+    cspi_object_ref (a);
+    return a;
+  }
+  path_dup = g_strdup (path);
+  if (!path_dup) return NULL;
+  a = g_new0 (Accessible, 1);
+  if (!a)
+  {
+    g_free (path_dup);
+    return NULL;
+  }
+printf("Inserting %p into %p for %s\n", a, app->hash, path_dup);
+  g_hash_table_insert (app->hash, path_dup, a);
+  a->app = app;
+  a->v.path = path_dup;
+  a->ref_count = 2;    /* one for the caller, one for the hash */
+  cspi_dbus_get_property (a, SPI_DBUS_INTERFACE_ACCESSIBLE, "name", NULL, "s", &a->name);
+  dbus_error_init (&error);
+  if (!dbind_connection_method_call (bus, spi_bus_registry, a->v.path, spi_interface_desktop, "getChildren", &error, "=>as", &apps))
+  {
+    g_error ("Couldn't get desktop children: %s", error.message);
+  }
+  for (i = 0; i < apps->len; i++)
+  {
+    const char *app_name = g_array_index (apps, char *, i);
+    if (app_name[0] == '\0')
+    {
+      g_warning ("Got empty app name");
+      continue;
+    }
+    CSpiApplication *app = cspi_get_application (app_name);
+    additions = NULL;
+    dbus_error_init (&error);
+    dbind_connection_method_call (bus, app_name, "/org/freedesktop/atspi/tree", spi_interface_tree, "getTree", &error, "=>a(ooaoassus)", &additions);
+    if (error.message)
+    {
+      g_warning ("getTree (%s): %s", app_name, error.message);
+    }
+    handle_additions (app, additions);
+    add_app_to_desktop (a, app_name);
+  }
+  g_array_free (apps, TRUE);
+  return a;
+}
+
+Accessible *
+cspi_ref_accessible (const char *app, const char *path)
+{
+  CSpiApplication *a = cspi_get_application (app);
+  if (!a) return NULL;
+  if ( APP_IS_REGISTRY(a))
+  {
+    return ref_accessible_desktop (a, path);
+  }
+  return ref_accessible (a, path);
+}
+
+Accessible *
+cspi_ref_related_accessible (Accessible *obj, const char *path)
+{
+  return ref_accessible (obj->app, path);
+}
+
+typedef struct
+{
+  GArray *additions;
+  GArray *removals;
+} CacheSignalData;
+
+static const char *cacheSignalType = "a(ooaoassus)ao";
+
+static DBusHandlerResult
+cspi_dbus_handle_update_tree (DBusConnection *bus, DBusMessage *message, void *user_data)
+{
+  DBusMessageIter iter;
+  CacheSignalData cd;
+  void *p = &cd;
+  const char *sender = dbus_message_get_sender (message);
+  CSpiApplication *app = cspi_get_application (sender);
+  const char *type = cacheSignalType;
+
+printf("update tree: %p\n", app);
+  if (!app)
+  {
+    g_warning ("UpdateTree from unknown app.  Should we add it?", sender);
+    return;
+  }
+  dbus_message_iter_init (message, &iter);
+  // TODO: Check signature
+  dbind_any_demarshal (&iter, &type, &p);      /* additions */
+  dbind_any_demarshal (&iter, &type, &p);      /* removals */
+  handle_additions (app, cd.additions);
+  handle_removals (app, cd.removals);
+}
+
+static DBusHandlerResult
+cspi_dbus_handle_add_application (DBusConnection *bus, DBusMessage *message, void *user_data)
+{
+  DBusError error;
+  dbus_uint32_t v;
+  Accessible *a;
+  char *bus_name;
+
+  dbus_error_init (&error);
+  if (!dbus_message_get_args (message, NULL, DBUS_TYPE_UINT32, &v, DBUS_TYPE_STRING, &bus_name, DBUS_TYPE_INVALID))
+  {
+    g_warning ("Error processing %s: %s\n", dbus_message_get_member(message), error.message);
+    dbus_error_free (&error);
+    return DBUS_HANDLER_RESULT_HANDLED;
+  }
+  a = cspi_ref_accessible ("org.freedesktop.atspi.registry", dbus_message_get_path(message));
+printf("Adding %s to %p\n", bus_name, a);
+  if (add_app_to_desktop (a, bus_name))
+  {
+    send_children_change (a, g_list_last (a->children)->data, TRUE);
+  }
+  cspi_object_unref (a);
+  return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+cspi_dbus_handle_remove_application (DBusConnection *bus, DBusMessage *message, void *user_data)
+{
+  DBusError error;
+  dbus_uint32_t v;
+  Accessible *a;
+  char *bus_name;
+
+  dbus_error_init (&error);
+  if (!dbus_message_get_args (message, NULL, DBUS_TYPE_UINT32, &v, DBUS_TYPE_STRING, &bus_name, DBUS_TYPE_INVALID))
+  {
+    g_warning ("Error processing %s: %s\n", dbus_message_get_member(message), error.message);
+    dbus_error_free (&error);
+    return DBUS_HANDLER_RESULT_HANDLED;
+  }
+  a = cspi_ref_accessible ("org.freedesktop.atspi.registry", dbus_message_get_path(message));
+printf("Removing %s from %p\n", bus_name, a);
+  remove_app_from_desktop (a, bus_name);
+  cspi_object_unref (a);
+  return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+
+static DBusHandlerResult
+cspi_dbus_filter (DBusConnection *bus, DBusMessage *message, void *data)
+{
+  int type = dbus_message_get_type (message);
+  const char *interface = dbus_message_get_interface (message);
+  const char *member = dbus_message_get_member (message); 
+  dbus_uint32_t v;
+  char *bus_name;
+
+  if (type == DBUS_MESSAGE_TYPE_SIGNAL &&
+      !strcmp (interface, SPI_DBUS_INTERFACE_ACCESSIBLE))
+  {
+    return cspi_dbus_handle_event (bus, message, data);
+  }
+  if (dbus_message_is_method_call (message, spi_interface_device_event_listener, "notifyEvent"))
+  {
+    return cspi_dbus_handle_deviceEvent (bus, message, data);
+  }
+  if (dbus_message_is_signal (message, spi_interface_tree, "updateTree"))
+  {
+    return cspi_dbus_handle_update_tree (bus, message, data);
+  }
+  if (dbus_message_is_signal (message, spi_interface_registry, "applicationAdd"))
+  {
+    return cspi_dbus_handle_add_application (bus, message, data);
+  }
+  if (dbus_message_is_signal (message, spi_interface_registry, "applicationRemove"))
+  {
+    return cspi_dbus_handle_remove_application (bus, message, data);
+  }
+if (type == DBUS_MESSAGE_TYPE_SIGNAL) printf("got %s of %s from %s\n", dbus_message_get_member (message), dbus_message_get_interface(message), dbus_message_get_sender(message));
+  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+/**
+ * SPI_init:
+ *
+ * Connects to the accessibility registry and initializes the SPI.
+ *
+ * Returns: 0 on success, otherwise an integer error code.  
+ **/
+int
+SPI_init (void)
+{
+  DBusError error;
+  char *match;
+
+  if (SPI_inited)
+    {
+      return 1;
+    }
+
+  SPI_inited = TRUE;
+
+  g_type_init ();
+
+  cspi_get_live_refs();
+  g_atexit (cspi_cleanup);
+
+  dbus_error_init (&error);
+  bus = dbus_bus_get (DBUS_BUS_SESSION, &error);
+  if (!bus)
+  {
+    g_error ("Couldn't get session bus");
+    return 2;
+  }
+  dbus_bus_register (bus, &error);
+  dbus_connection_setup_with_g_main(bus, g_main_context_default());
+  dbus_connection_add_filter (bus, cspi_dbus_filter, NULL, NULL);
+  match = g_strdup_printf ("type='signal',interface='%s',member='updateTree'", spi_interface_tree);
+  dbus_error_init (&error);
+  dbus_bus_add_match (bus, match, &error);
+  g_free (match);
+  match = g_strdup_printf ("type='signal',sender='%s'", SPI_DBUS_NAME_REGISTRY);
+  dbus_bus_add_match (bus, match, &error);
+  g_free (match);
+  return 0;
+}
+
+  static GMainLoop *mainloop;
+
+/**
+ * SPI_event_main:
+ *
+ * Starts/enters the main event loop for the SPI services.
+ *
+ * (NOTE: This method does not return control, it is exited via a call to
+ *  SPI_event_quit () from within an event handler).
+ *
+ **/
+void
+SPI_event_main (void)
+{
+
+  mainloop = g_main_loop_new (NULL, FALSE);
+  g_main_loop_run (mainloop);
+}
+
+/**
+ * SPI_event_quit:
+ *
+ * Quits the last main event loop for the SPI services,
+ * see SPI_event_main
+ **/
+void
+SPI_event_quit (void)
+{
+  g_main_loop_quit (mainloop);
+}
+
+/**
+ * SPI_eventIsReady:
+ *
+ * Checks to see if an SPI event is waiting in the event queue.
+ * Used by clients that don't wish to use SPI_event_main().
+ *
+ * Not Yet Implemented.
+ *
+ * Returns: #TRUE if an event is waiting, otherwise #FALSE.
+ *
+ **/
+SPIBoolean
+SPI_eventIsReady (void)
+{
+  return FALSE;
+}
+
+/**
+ * SPI_nextEvent:
+ * @waitForEvent: a #SPIBoolean indicating whether to block or not.
+ *
+ * Gets the next event in the SPI event queue; blocks if no event
+ * is pending and @waitForEvent is #TRUE.
+ * Used by clients that don't wish to use SPI_event_main().
+ *
+ * Not Yet Implemented.
+ *
+ * Returns: the next #AccessibleEvent in the SPI event queue.
+ **/
+AccessibleEvent *
+SPI_nextEvent (SPIBoolean waitForEvent)
+{
+  return NULL;
+}
+
+#ifdef PRINT_LEAKS
+static void
+report_leaked_ref (gpointer key, gpointer val, gpointer user_data)
+{
+  char *name, *role;
+  Accessible *a = (Accessible *) val;
+  
+  name = Accessible_getName (a);
+  if (cspi_exception ())
+    {
+      name = NULL;
+    }
+
+  role = Accessible_getRoleName (a);
+  if (cspi_exception ())
+    {
+      role = NULL;
+    }
+
+  fprintf (stderr, "leaked %d references to object %s, role %s %p\n",
+          a->ref_count, name ? name : "<?>", role ? role : "<?>", a);
+
+  SPI_freeString (name);
+}
+#endif
+
+/**
+ * SPI_exit:
+ *
+ * Disconnects from the Accessibility Registry and releases 
+ * any floating resources. Call only once at exit.
+ *
+ * Returns: 0 if there were no leaks, otherwise non zero.
+ **/
+int
+SPI_exit (void)
+{
+  int leaked;
+
+  if (!SPI_inited)
+    {
+      return 0;
+    }
+
+  SPI_inited = FALSE;
+
+  if (live_refs)
+    {
+      leaked = g_hash_table_size (live_refs);
+#ifdef DEBUG_OBJECTS
+      fprintf (stderr, "Leaked %d SPI handles\n", leaked);
+
+#define PRINT_LEAKS
+#ifdef PRINT_LEAKS
+      g_hash_table_foreach (live_refs, report_leaked_ref, NULL);
+#endif
+
+#endif
+    }
+  else
+    {
+      leaked = 0;
+    }
+
+  cspi_cleanup ();
+
+  return leaked;
+}
+
+/**
+ * SPI_freeString:
+ * @s: a character string returned from another at-spi call.
+ *
+ * Free a character string returned from an at-spi call.  Clients of
+ * at-spi should use this function instead of free () or g_free().
+ * A NULL string @s will be silently ignored.
+ * This API should not be used to free strings
+ * from other libraries or allocated by the client.
+ **/
+void
+SPI_freeString (char *s)
+{
+  if (s)
+    {
+      g_free (s);
+    }
+}
+
+/**
+ * SPI_freeRect:
+ * @r: a pointer to an SPIRect returned from another at-spi call.
+ *
+ * Free a SPIRect structure returned from an at-spi call.  Clients of
+ * at-spi should use this function instead of free () or g_free().
+ * A NULL rect @r will be silently ignored.
+ * This API should not be used to free data
+ * from other libraries or allocated by the client.
+ *
+ * @Since: AT-SPI 1.6
+ **/
+void
+SPI_freeRect (SPIRect *r)
+{
+  if (r)
+    {
+      /* err, okay, in this case the client _could_ 
+        have called g_free, but we don't want to guarantee it */
+      g_free (r);
+    }
+}
+
+/**
+ * SPI_dupString:
+ * @s: a UTF-8 string to be duplicated
+ * 
+ * @Since: AT-SPI 1.4
+ *
+ * Returns: a duplicate of the string passed as a parameter, which should
+ * be freed via SPI_freeString after use.
+ **/
+char *
+SPI_dupString (char *s)
+{
+  if (s)
+    {
+      return g_strdup (s);
+    }
+  else 
+    return NULL;
+}
+
+/**
+ * SPI_exceptionHandlerPush:
+ * @handler: an #SPIExceptionHandler to install as the first code to deal with exceptions.
+ *
+ * Install a client-side handler for #SPIException instances, which can see and handle any
+ * exceptions before chaining them to the next exception handler in the stack.
+ *
+ * @Since: AT-SPI 1.4
+ *
+ * Returns %TRUE if the result succeeded, %FALSE if @hander could not be registered.
+ **/
+SPIBoolean SPI_exceptionHandlerPush (SPIExceptionHandler *handler)
+{
+  if (!exception_handlers)
+    exception_handlers = g_queue_new ();
+  g_queue_push_head (exception_handlers, handler);
+  return TRUE;
+}
+
+/**
+ * SPI_exceptionHandlerPop:
+ * 
+ * Remove/pop an #SPIExceptionHandler off the error handler stack and return the new handler.
+ *
+ * @Since: AT-SPI 1.4
+ *
+ * Returns the #SPIExceptionHandler which is now at the top of the error handler stack after the call.
+ **/
+SPIExceptionHandler* SPI_exceptionHandlerPop (void)
+{
+  return (SPIExceptionHandler *) g_queue_pop_head (exception_handlers);
+}
+
+/**
+ * SPIException_getSourceType:
+ * @err: the exception being queried
+ *
+ * Get the #SPIExceptionType of an exception which has been thrown.
+ *
+ * @Since: AT-SPI 1.4
+ *
+ * Returns: the #SPIExceptionType corresponding to exception @err.
+ **/
+SPIExceptionType SPIException_getSourceType (SPIException *err)
+{
+  if (err)
+    return err->type;
+  else
+    return SPI_EXCEPTION_SOURCE_UNSPECIFIED;
+}
+
+/**
+ * SPIException_getExceptionCode:
+ * @err: the #SPIException being queried.
+ *
+ * Get the #SPIExceptionCode telling what type of exception condition has occurred.
+ *
+ * @Since: AT-SPI 1.4
+ *
+ * Returns: the #SPIExceptionCode corresponding to exception @err.
+ **/
+SPIExceptionCode SPIException_getExceptionCode (SPIException *err)
+{  
+  return err->code;
+}
+
+/**
+ * SPIAccessibleException_getSource:
+ * @err: the #SPIException being queried.
+ *
+ * Get the identity of the object which threw an exception.
+ *
+ * @Since: AT-SPI 1.4
+ *
+ * Returns: a pointer to the #Accessible object which threw the exception.
+ **/
+Accessible* SPIAccessibleException_getSource (SPIException *err)
+{
+  if (err->type == SPI_EXCEPTION_SOURCE_ACCESSIBLE)
+    cspi_object_ref (err->source);
+    return err->source;
+  return NULL;
+}
+
+/**
+ * SPIException_getDescription:
+ * @err: the #SPIException being queried.
+ *
+ * Get a text description of the exception that has been thrown.
+ * Unfortunately these descriptions tend to be terse and limited in
+ * the detail which they can provide.
+ *
+ * Returns: a brief character string describing the exception.
+ **/
+char* SPIException_getDescription (SPIException *err)
+{
+  /* TODO: friendlier error messages? */
+  if (err->error)
+    return err->error->message;
+  return NULL;
+}
+
+static char *
+get_path (Accessible *obj)
+{
+  if (APP_IS_REGISTRY (obj->app))
+  {
+    return g_strdup_printf (SPI_DBUS_PATH_DESKTOP);
+  }
+  return g_strdup_printf ("/org/freedesktop/atspi/accessible/%d", obj->v.id);
+}
+
+dbus_bool_t
+cspi_dbus_call (Accessible *obj, const char *interface, const char *method, DBusError *error, const char *type, ...)
+{
+  va_list args;
+  char *path = get_path (obj);
+  dbus_bool_t retval;
+  DBusError err;
+
+  if (!error) error = &err;
+  dbus_error_init (error);
+  va_start (args, type);
+  retval = dbind_connection_method_call_va (cspi_bus(), obj->app->bus_name, path, interface, method, error, type, args);
+  va_end (args);
+  g_free (path);
+  if (dbus_error_is_set (error))
+  {
+    if (!dbus_error_is_set (&exception))
+    {
+      // TODO: Should we call cspi_exception_throw?
+      dbus_move_error (error, &exception);
+    }
+    else if (error == &err) dbus_error_free (error);
+  }
+  return retval;
+}
+
+dbus_bool_t
+cspi_dbus_get_property (Accessible *obj, const char *interface, const char *name, DBusError *error, const char *type, void *data)
+{
+  DBusMessage *message, *reply;
+  char *path = get_path (obj);
+  DBusMessageIter iter, iter_variant;
+  DBusError err;
+  dbus_bool_t retval = FALSE;
+
+  message = dbus_message_new_method_call (obj->app->bus_name, path, "org.freedesktop.DBus.Properties", "Get");
+  if (!message)
+  {
+    // TODO: throw exception
+    goto done;
+  }
+  dbus_message_append_args (message, DBUS_TYPE_STRING, &interface, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID);
+  if (!error) error = &err;
+  dbus_error_init (error);
+  reply = dbus_connection_send_with_reply_and_block (cspi_bus(), message, 1000, error);
+  dbus_message_unref (message);
+  if (!reply)
+  {
+    // TODO: throw exception
+    goto done;
+  }
+  dbus_message_iter_init (reply, &iter);
+  dbus_message_iter_recurse (&iter, &iter_variant);
+  if (dbus_message_iter_get_arg_type (&iter_variant) != type[0])
+  {
+    g_warning ("cspi_dbus_get_property: Wrong type: expected %s, got %c\n", type, dbus_message_iter_get_arg_type (&iter_variant));
+    goto done;
+  }
+  dbus_message_iter_get_basic (&iter_variant, data);
+  dbus_message_unref (reply);
+  if (type[0] == 's') *(char **)data = g_strdup (*(char **)data);
+  retval = TRUE;
+done:
+  g_free (path);
+  return retval;
+}
diff --git a/cspi/spi_registry.c b/cspi/spi_registry.c
new file mode 100644 (file)
index 0000000..98f3779
--- /dev/null
@@ -0,0 +1,438 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* spi_registry.c: Global functions wrapping the registry */
+
+#include <cspi/spi-private.h>
+
+static GArray *desktops;
+
+/**
+ * SPI_getDesktopCount:
+ *
+ * Get the number of virtual desktops.
+ * NOTE: currently multiple virtual desktops are not implemented, this
+ *       function always returns '1'.
+ *
+ * Returns: an integer indicating the number of active virtual desktops.
+ **/
+int
+SPI_getDesktopCount ()
+{
+  if (!desktops) SPI_getDesktopList (NULL);
+  if (!desktops) return -1;
+  return desktops->len;
+}
+
+/**
+ * SPI_getDesktop:
+ * @i: an integer indicating which of the accessible desktops is to be returned.
+ *
+ * Get the virtual desktop indicated by index @i.
+ * NOTE: currently multiple virtual desktops are not implemented, this
+ *       function always returns '1'.
+ *
+ * Returns: a pointer to the 'i-th' virtual desktop's #Accessible representation.
+ **/
+Accessible*
+SPI_getDesktop (int i)
+{
+  if (!desktops) SPI_getDesktopList (NULL);
+  if (!desktops) return NULL;
+  return cspi_ref_accessible (spi_bus_registry, g_array_index (desktops, char *, i));
+}
+
+/**
+ * SPI_getDesktopList:
+ * @desktop_list: a pointer to an array of #Accessible references.
+ *
+ * Get the list of virtual desktops.  On return, @list will point
+ *     to a newly-created, NULL terminated array of virtual desktop
+ *     pointers.
+ *     It is the responsibility of the caller to free this array when
+ *     it is no longer needed.
+ *
+ * Not Yet Implemented : this implementation always returns a single
+ * #Accessible desktop.
+ *
+ * Returns: an integer indicating how many virtual desktops have been
+ *          placed in the list pointed to by parameter @list.
+ **/
+int
+SPI_getDesktopList (Accessible ***desktop_list)
+{
+  int i;
+  Accessible **list;
+
+  if (desktop_list) *desktop_list = NULL;
+
+  if (!desktops)
+  {
+    dbind_connection_method_call (cspi_bus(), spi_bus_registry, spi_path_registry, spi_interface_registry, "getDesktopList", NULL, "=>ao", &desktops);
+    if (!desktops) return 0;
+  }
+
+  list = g_new0 (Accessible *, desktops->len + 1);
+
+  if (!desktop_list) return desktops->len;
+  for (i = 0; i < desktops->len; i++)
+    {
+      list [i] = cspi_ref_accessible (spi_bus_registry, g_array_index (desktops, char *, i));
+    }
+  list [i] = NULL;
+
+  *desktop_list = list;
+
+  return i;
+}
+
+/**
+ * SPI_freeDesktopList:
+ * @desktop_list: a pointer to an array of #Accessible objects
+ * as returned from @SPI_getDesktopList
+ * 
+ * This routine frees the memory associated with the list.
+ **/
+void
+SPI_freeDesktopList (Accessible **desktop_list)
+{
+  Accessible **p;
+  
+  for (p = desktop_list; p && *p; p++)
+    {
+      cspi_object_unref (*p);
+    }
+  g_free (desktop_list);
+}
+
+/**
+ * SPI_KEYSET_ALL_KEYS:
+ * @SPI_KEYSET_ALL_KEYS: A special value for an AccessibleKeySet type, which tacitly
+ *                       includes all keycodes and keyvals for the specified modifier set.
+ **/
+
+/**
+ * SPI_registerAccessibleKeystrokeListener:
+ * @listener:  a pointer to the #AccessibleKeystrokeListener for which
+ *             keystroke events are requested.
+ * @keys:      a pointer to the #AccessibleKeySet indicating which
+ *             keystroke events are requested, or #SPI_KEYSET_ALL_KEYS
+ *             to indicate that all keycodes and keyvals for the specified
+ *             modifier set are to be included.
+ * @modmask:   an #AccessibleKeyMaskType mask indicating which
+ *             key event modifiers must be set in combination with @keys,
+ *             events will only be reported for key events for which all
+ *             modifiers in @modmask are set.  If you wish to listen for
+ *             events with multiple modifier combinations you must call
+ *             registerAccessibleKeystrokeListener() once for each combination.
+ * @eventmask: an #AccessibleKeyMaskType mask indicating which
+ *             types of key events are requested (#SPI_KEY_PRESSED, etc.).
+ * @sync_type: a #AccessibleKeyListenerSyncType parameter indicating
+ *             the behavior of the notification/listener transaction.
+ *             
+ * Register a listener for keystroke events, either pre-emptively for
+ *             all windows (SPI_KEYLISTENER_ALL_WINDOWS),
+ *             non-preemptively (SPI_KEYLISTENER_NOSYNC), or
+ *             pre-emptively at the toolkit level (SPI_KEYLISTENER_CANCONSUME).
+ *             If ALL_WINDOWS or CANCONSUME are used, the event is consumed
+ *             upon receipt if one of @listener's callbacks returns #TRUE.
+ *             ( Other sync_type values may be available in the future )
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ **/
+SPIBoolean
+SPI_registerAccessibleKeystrokeListener (AccessibleKeystrokeListener  *listener,
+                                        AccessibleKeySet             *keys,
+                                        AccessibleKeyMaskType         modmask,
+                                        AccessibleKeyEventMask        eventmask,
+                                        AccessibleKeyListenerSyncType sync_type)
+{
+  gchar *path = cspi_device_listener_get_path (listener);
+  gint                                i;
+  GArray *key_set;
+  dbus_uint32_t key_events = 0;
+  Accessibility_ControllerEventMask   controller_event_mask;
+  Accessibility_EventListenerMode     listener_mode;
+  DBusError error;
+  SPIBoolean                          retval = FALSE;
+
+  if (!listener)
+    {
+      return retval;
+    }
+
+  /* copy the keyval filter values from the C api into the DBind KeySet */
+  if (keys)
+    {
+      key_set = g_array_sized_new (FALSE, TRUE, sizeof (Accessibility_KeyDefinition), keys->len);
+      key_set->len = keys->len;
+      for (i = 0; i < keys->len; ++i)
+        {
+         Accessibility_KeyDefinition *kd =  ((Accessibility_KeyDefinition *) key_set->data) + i;
+          kd->keycode = keys->keycodes[i];
+         kd->keysym = keys->keysyms[i];
+         if (keys->keystrings && keys->keystrings[i])
+           {
+             kd->keystring = keys->keystrings[i];
+           } 
+          else 
+            {
+             kd->keystring = "";
+           }
+        }
+    }
+  else
+    {
+      key_set = g_array_sized_new (FALSE, TRUE, sizeof (Accessibility_KeyDefinition), 0);
+    }
+       
+  /* copy the event filter values from the C api into the DBus key_events */
+  if (eventmask & SPI_KEY_PRESSED)
+    {
+      key_events |= (1 << Accessibility_KEY_PRESSED_EVENT);
+    }
+  if (eventmask & SPI_KEY_RELEASED)
+    {
+      key_events |= (1 << Accessibility_KEY_RELEASED_EVENT);
+    }
+  
+  controller_event_mask = (dbus_uint32_t) modmask;
+
+  listener_mode.synchronous =
+         (dbus_bool_t) ((sync_type & SPI_KEYLISTENER_SYNCHRONOUS)!=0);
+  listener_mode.preemptive =
+         (dbus_bool_t) ((sync_type & SPI_KEYLISTENER_CANCONSUME)!=0);
+  listener_mode.global =
+         (dbus_bool_t) ((sync_type & SPI_KEYLISTENER_ALL_WINDOWS)!=0);
+
+    dbus_error_init (&error);
+    dbind_connection_method_call (cspi_bus(), spi_bus_registry, spi_path_dec, spi_interface_dec, "registerKeystrokeListener", &error, "oa(iisi)uu(bbb)=>b", path, key_set, key_events, controller_event_mask, &listener_mode, &retval);
+
+  g_array_free (key_set, TRUE);
+  g_free (path);
+
+  return retval;
+}
+
+/**
+ * SPI_deregisterAccessibleKeystrokeListener:
+ * @listener: a pointer to the #AccessibleKeystrokeListener for which
+ *            keystroke events are requested.
+ * @modmask:  the key modifier mask for which this listener is to be
+ *            'deregistered' (of type #AccessibleeyMaskType).
+ *
+ * Removes a keystroke event listener from the registry's listener queue,
+ *            ceasing notification of events with modifiers matching @modmask.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ **/
+SPIBoolean
+SPI_deregisterAccessibleKeystrokeListener (AccessibleKeystrokeListener *listener,
+                                          AccessibleKeyMaskType        modmask)
+{
+  gchar *path = cspi_device_listener_get_path (listener);
+  Accessibility_ControllerEventMask   controller_event_mask;
+  GArray *key_set;
+  dbus_uint32_t key_events = 0;
+  DBusError error;
+
+  if (!listener)
+    {
+      return FALSE;
+    }
+
+
+  controller_event_mask = (dbus_uint32_t) modmask;
+
+      key_set = g_array_sized_new (FALSE, TRUE, sizeof (Accessibility_KeyDefinition), 0);
+    dbind_connection_method_call (cspi_bus(), spi_bus_registry, spi_path_dec, spi_interface_dec, "deregisterKeystrokeListener", &error, "oa(iisi)uu", path, &key_set, key_events, controller_event_mask);
+  g_free (path);
+  return TRUE;
+}
+
+/**
+ * SPI_registerDeviceEventListener:
+ * @listener:  a pointer to the #AccessibleDeviceListener which requests
+ *             the events.
+ * @eventmask: an #AccessibleDeviceEventMask mask indicating which
+ *             types of key events are requested (#SPI_KEY_PRESSED, etc.).
+ * @filter: Unused parameter.
+ *             
+ * Register a listener for device events, for instance button events.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ **/
+SPIBoolean
+SPI_registerDeviceEventListener (AccessibleDeviceListener  *listener,
+                                AccessibleDeviceEventMask  eventmask,
+                                void                      *filter)
+{
+  SPIBoolean                          retval = FALSE;
+  dbus_uint32_t event_types = 0;
+  gint                                i;
+  gchar *path = cspi_device_listener_get_path (listener);
+  DBusError error;
+
+  if (!listener)
+    {
+      return retval;
+    }
+
+  /* copy the event filter values from the C api into the CORBA KeyEventTypeSeq */
+  
+  if (eventmask & SPI_BUTTON_PRESSED)
+    {
+      event_types |= (1 << Accessibility_BUTTON_PRESSED_EVENT);
+    }
+  if (eventmask & SPI_BUTTON_RELEASED)
+    {
+      event_types |= (1 << Accessibility_BUTTON_RELEASED_EVENT);
+    }
+
+  dbus_error_init (&error);
+    dbind_connection_method_call (cspi_bus(), spi_bus_registry, spi_path_dec, spi_interface_dec, "registerDeviceEventListener", &error, "ou=>b", path, &event_types, &retval);
+  g_free (path);
+  return retval;
+}
+
+/**
+ * SPI_deregisterDeviceEventListener:
+ * @listener: a pointer to the #AccessibleDeviceListener for which
+ *            device events are requested.
+ * @filter: Unused parameter.
+ *
+ * Removes a device event listener from the registry's listener queue,
+ *            ceasing notification of events of the specified type.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ **/
+SPIBoolean
+SPI_deregisterDeviceEventListener (AccessibleDeviceListener *listener,
+                                  void                     *filter)
+{
+  dbus_uint32_t event_types = 0;
+  gchar *path = cspi_device_listener_get_path (listener);
+  DBusError error;
+
+  if (!listener)
+    {
+      return FALSE;
+    }
+
+  event_types |= (1 << Accessibility_BUTTON_PRESSED_EVENT);
+  event_types |= (1 << Accessibility_BUTTON_RELEASED_EVENT);
+
+  dbus_error_init (&error);
+    dbind_connection_method_call (cspi_bus(), spi_bus_registry, spi_path_dec, spi_interface_dec, "deregisterDeviceEventListener", &error, "ou", path, &event_types);
+  g_free (path);
+  return TRUE;
+}
+
+/**
+ * SPI_generateKeyboardEvent:
+ * @keyval: a long integer indicating the keycode or keysym of the key event
+ *           being synthesized.
+ * @keystring: an (optional) UTF-8 string which, if @keyval is NULL,
+ *           indicates a 'composed' keyboard input string which is 
+ *           being synthesized; this type of keyboard event synthesis does
+ *           not emulate hardware keypresses but injects the string 
+ *           as though a composing input method (such as XIM) were used.
+ * @synth_type: a #AccessibleKeySynthType flag indicating whether @keyval
+ *           is to be interpreted as a keysym rather than a keycode
+ *           (CSPI_KEYSYM), or whether to synthesize
+ *           SPI_KEY_PRESS, SPI_KEY_RELEASE, or both (SPI_KEY_PRESSRELEASE).
+ *
+ * Synthesize a keyboard event (as if a hardware keyboard event occurred in the
+ * current UI context).
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ **/
+SPIBoolean
+SPI_generateKeyboardEvent (long int keyval,
+                          char *keystring,
+                          AccessibleKeySynthType synth_type)
+{
+  dbus_uint32_t keysynth_type;
+  dbus_int16_t keycode = keyval;
+  DBusError error;
+
+  switch (synth_type)
+    {
+      case SPI_KEY_PRESS:
+         keysynth_type = Accessibility_KEY_PRESS;
+         break;
+      case SPI_KEY_RELEASE:
+         keysynth_type = Accessibility_KEY_RELEASE;
+         break;
+      case SPI_KEY_PRESSRELEASE:
+         keysynth_type = Accessibility_KEY_PRESSRELEASE;
+         break;
+      case SPI_KEY_SYM:
+         keysynth_type = Accessibility_KEY_SYM;
+         break;
+      case SPI_KEY_STRING:
+         keysynth_type = Accessibility_KEY_STRING;
+         break;
+      default:
+          return FALSE;
+    }
+
+  if (!keystring) keystring = "";
+  dbus_error_init (&error);
+    dbind_connection_method_call (cspi_bus(), spi_bus_registry, spi_path_dec, spi_interface_dec, "generateKeyboardEvent", &error, "isu", &keycode, &keystring, &keysynth_type);
+
+  return TRUE;
+}
+
+/**
+ * SPI_generateMouseEvent:
+ * @x: a #long indicating the screen x coordinate of the mouse event.
+ * @y: a #long indicating the screen y coordinate of the mouse event.
+ * @name: a string indicating which mouse event to be synthesized
+ *        (e.g. "b1p", "b1c", "b2r", "rel", "abs").
+ *
+ * Synthesize a mouse event at a specific screen coordinate.
+ * Most AT clients should use the #AccessibleAction interface when
+ * tempted to generate mouse events, rather than this method.
+ * Event names: b1p = button 1 press; b2r = button 2 release;
+ *              b3c = button 3 click; b2d = button 2 double-click;
+ *              abs = absolute motion; rel = relative motion.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ **/
+SPIBoolean
+SPI_generateMouseEvent (long x, long y, char *name)
+{
+  dbus_int32_t dbus_x = x, dbus__y = y;
+  DBusError error;
+
+  dbus_error_init (&error);
+    dbind_connection_method_call (cspi_bus(), spi_bus_registry, spi_path_dec, spi_interface_dec, "generateMouseEvent", &error, "iis", &x, &y, &name);
+  return TRUE;
+}
+
+char *
+cspi_device_listener_get_path (CSpiDeviceListener *listener)
+{
+  return g_strdup_printf ("/org/freedesktop/atspi/listeners/%d", listener->id);
+}
diff --git a/cspi/spi_selection.c b/cspi/spi_selection.c
new file mode 100644 (file)
index 0000000..d369070
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <cspi/spi-private.h>
+
+/**
+ * AccessibleSelection_ref:
+ * @obj: a pointer to the #AccessibleSelection implementor on which to operate.
+ *
+ * Increment the reference count for an #AccessibleSelection object.
+ *
+ **/
+void
+AccessibleSelection_ref (AccessibleSelection *obj)
+{
+  cspi_object_ref (obj);
+}
+
+/**
+ * AccessibleSelection_unref:
+ * @obj: a pointer to the #AccessibleSelection implementor on which to operate. 
+ *
+ * Decrement the reference count for an #Accessible object.
+ *
+ **/
+void
+AccessibleSelection_unref (AccessibleSelection *obj)
+{
+  cspi_object_unref (obj);
+}
+
+/**
+ * AccessibleSelection_getNSelectedChildren:
+ * @obj: a pointer to the #AccessibleSelection implementor on which to operate.
+ *
+ * Get the number of children of an #AccessibleSelection implementor which are
+ *        currently selected.
+ *
+ * Returns: a #long indicating the number of #Accessible children
+ *        of the #AccessibleSelection implementor which are currently selected.
+ *
+ **/
+long
+AccessibleSelection_getNSelectedChildren (AccessibleSelection *obj)
+{
+  dbus_int32_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, -1);
+
+  cspi_dbus_get_property (obj, spi_interface_selection, "nSelectedChildren", NULL, "i", &retval);
+
+  cspi_return_val_if_ev ("getNSelectedChildren", -1);
+
+  return retval;
+}
+
+/**
+ * AccessibleSelection_getSelectedChild:
+ * @obj: a pointer to the #AccessibleSelection on which to operate.
+ * @selectedChildIndex: a #long indicating which of the selected
+ *      children is specified.
+ *
+ * Get the i-th selected #Accessible child of an #AccessibleSelection.
+ *      Note that @childIndex refers to the index in the list of 'selected'
+ *      children and generally differs from that used in
+ *      #Accessible_getChildAtIndex() or returned by
+ *      #Accessible_getIndexInParent(). @selectedChildIndex must lie between 0
+ *      and #AccessibleSelection_getNSelectedChildren()-1, inclusive.
+ *
+ * Returns: a pointer to a selected #Accessible child object,
+ *          specified by @childIndex.
+ *
+ **/
+Accessible *
+AccessibleSelection_getSelectedChild (AccessibleSelection *obj,
+                                      long int selectedChildIndex)
+{
+  dbus_int32_t d_selectedChildIndex = selectedChildIndex;
+  char *path;
+  Accessible *child;
+
+  cspi_return_val_if_fail (obj != NULL, NULL);
+  
+  cspi_dbus_call (obj, spi_interface_selection, "getSelectedChild", NULL, "i=>o", &d_selectedChildIndex, &path);
+  child = cspi_ref_related_accessible (obj, path);
+  g_free (path);
+  return child;
+}
+
+/**
+ * AccessibleSelection_selectChild:
+ * @obj: a pointer to the #AccessibleSelection on which to operate.
+ * @childIndex: a #long indicating which child of the #Accessible
+ *              is to be selected.
+ *
+ * Add a child to the selected children list of an #AccessibleSelection.
+ *         For #AccessibleSelection implementors that only allow
+ *         single selections, this may replace the (single) current
+ *         selection.
+ *
+ * Returns: #TRUE if the child was successfully selected, #FALSE otherwise.
+ **/
+SPIBoolean
+AccessibleSelection_selectChild (AccessibleSelection *obj,
+                                 long int childIndex)
+{
+  dbus_int32_t d_childIndex = childIndex;
+  dbus_bool_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_selection, "selectChild", NULL, "i=>b", &d_childIndex, &retval);
+
+  cspi_return_val_if_ev ("selectChild", FALSE);
+
+  return retval;
+}
+
+/**
+ * AccessibleSelection_deselectSelectedChild:
+ * @obj: a pointer to the #AccessibleSelection on which to operate.
+ * @selectedChildIndex: a #long indicating which of the selected children
+ *              of the #Accessible is to be selected.
+ *
+ * Remove a child to the selected children list of an #AccessibleSelection.
+ *          Note that @childIndex is the index in the selected-children list,
+ *          not the index in the parent container.  @selectedChildIndex in this
+ *          method, and @childIndex in #AccessibleSelection_selectChild
+ *          are asymmettric.
+ *
+ * Returns: #TRUE if the child was successfully deselected, #FALSE otherwise.
+ **/
+SPIBoolean
+AccessibleSelection_deselectSelectedChild (AccessibleSelection *obj,
+                                           long int selectedChildIndex)
+{
+  dbus_int32_t d_selectedChildIndex = selectedChildIndex;
+  dbus_bool_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_selection, "deselectSelectedChild", NULL, "i=>b", &d_selectedChildIndex, &retval);
+
+  cspi_return_val_if_ev ("deselectSelectedChild", FALSE);
+
+  return retval;
+}
+
+/**
+ * AccessibleSelection_deselectChild:
+ * @obj: a pointer to the #AccessibleSelection on which to operate.
+ * @childIndex: a #long indicating which of the children
+ *              of the #Accessible is to be de-selected.
+ *
+ * Deselect a specific child of an #AccessibleSelection.
+ *          Note that @childIndex is the index of the child
+ *          in the parent container.
+ * 
+ * See #AccessibleSelection_deselectSelectedChild
+ *
+ * Since AT-SPI 1.8.0
+ * 
+ * Returns: #TRUE if the child was successfully deselected, #FALSE otherwise.
+ **/
+SPIBoolean
+AccessibleSelection_deselectChild (AccessibleSelection *obj,
+                                  long int childIndex)
+{
+  dbus_int32_t d_childIndex = childIndex;
+  dbus_bool_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_selection, "deselectChild", NULL, "i=>b", &d_childIndex, &retval);
+
+  cspi_return_val_if_ev ("deselectChild", FALSE);
+
+  return retval;
+}
+
+/**
+ * AccessibleSelection_isChildSelected:
+ * @obj: a pointer to the #AccessibleSelection implementor on which to operate.
+ * @childIndex: an index into the #AccessibleSelection's list of children.
+ *
+ * Determine whether a particular child of an #AccessibleSelection implementor
+ *        is currently selected.  Note that @childIndex is the index into the
+ *        standard #Accessible container's list of children.
+ *
+ * Returns: #TRUE if the specified child is currently selected,
+ *          #FALSE otherwise.
+ **/
+SPIBoolean
+AccessibleSelection_isChildSelected (AccessibleSelection *obj,
+                                     long int childIndex)
+{
+  dbus_int32_t d_childIndex = childIndex;
+  dbus_bool_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_selection, "isChildSelected", NULL, "i=>b", &d_childIndex, &retval);
+
+  cspi_return_val_if_ev ("isChildSelected", FALSE);
+
+  return retval;
+}
+
+/**
+ * AccessibleSelection_selectAll:
+ * @obj: a pointer to the #AccessibleSelection implementor on which to operate.
+ *
+ * Attempt to select all of the children of an #AccessibleSelection implementor.
+ * Not all #AccessibleSelection implementors support this operation.
+ *
+ * Returns: #TRUE if successful, #FALSE otherwise.
+ *
+ **/
+SPIBoolean
+AccessibleSelection_selectAll (AccessibleSelection *obj)
+{
+  dbus_bool_t retval;
+  
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_selection, "selectAll", NULL, "=>b", &retval);
+
+  cspi_return_val_if_ev ("selectAll", FALSE);
+
+  return retval;
+}
+
+/**
+ * AccessibleSelection_clearSelection:
+ * @obj: a pointer to the #AccessibleSelection implementor on which to operate.
+ *
+ * Clear the current selection, removing all selected children from the
+ *       specified #AccessibleSelection implementor's selection list.
+ *
+ * Returns: #TRUE if successful, #FALSE otherwise.
+ *
+ **/
+SPIBoolean
+AccessibleSelection_clearSelection (AccessibleSelection *obj)
+{
+  dbus_bool_t retval;
+  
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_selection, "clearSelection", NULL, "=>b", &retval);
+
+  return retval;
+}
+
diff --git a/cspi/spi_streamablecontent.c b/cspi/spi_streamablecontent.c
new file mode 100644 (file)
index 0000000..2bb1632
--- /dev/null
@@ -0,0 +1,429 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include <cspi/spi-private.h>
+
+#define CORBA_BLOCK_SIZE 65536 /* see libbonobo, dunno where this is officially dictated */
+
+#if 0  // TODO
+struct StreamCacheItem {
+  Accessibility_ContentStream stream;
+  gchar *mimetype;
+};
+
+static gboolean
+streams_equal_func (gconstpointer a, gconstpointer b)
+{
+  const struct StreamCacheItem *c1 = a, *c2 = b;
+  return CORBA_Object_is_equivalent (c1->stream, c2->stream, cspi_ev ());
+}
+
+static void
+stream_cache_item_free (gpointer a)
+{
+  struct StreamCacheItem *cache_item = a;
+
+  cspi_release_unref (cache_item->stream);
+  SPI_freeString (cache_item->mimetype);
+  g_free (cache_item);
+}
+
+static GHashTable *streams = NULL;
+
+static GHashTable *
+get_streams (void) 
+{
+  if (streams == NULL)
+      streams = g_hash_table_new_full (g_direct_hash, streams_equal_func, 
+                                      NULL, stream_cache_item_free);
+  return streams;
+}
+
+static CORBA_long
+accessible_content_stream_client_seek (const Accessibility_ContentStream stream,
+                                     CORBA_long offset,
+                                     Accessibility_ContentStream_SeekType seek_type,
+                                     CORBA_Environment  *opt_ev)
+{
+       CORBA_Environment  *ev, temp_ev;
+       CORBA_long ret_offset;
+       
+       if (!opt_ev) {
+               CORBA_exception_init (&temp_ev);
+               ev = &temp_ev;
+       } else
+               ev = opt_ev;
+
+       ret_offset = Accessibility_ContentStream_seek (stream, offset, seek_type, ev);
+       if (BONOBO_EX (ev))
+               ret_offset = -1;
+
+       if (!opt_ev)
+               CORBA_exception_free (&temp_ev);
+       
+       return ret_offset;
+}
+
+static guint8*
+accessible_content_stream_client_read (const Accessibility_ContentStream stream,
+                                      const size_t size,
+                                      CORBA_long *length_read,
+                                      CORBA_Environment  *ev)
+{
+       size_t  pos;
+       guint8 *mem;
+       size_t  length;
+
+       g_return_val_if_fail (ev != NULL, NULL);
+
+       if (length_read)
+               *length_read = size;
+
+       length = size;
+
+       if (length == 0)
+               return NULL;
+
+       mem = g_try_malloc (length);
+       if (!mem) {
+               CORBA_exception_set_system (ev, ex_CORBA_NO_MEMORY,
+                                           CORBA_COMPLETED_NO);
+               return NULL;
+       }
+
+       *length_read = 0;
+
+       for (pos = 0; pos < length;) {
+               Accessibility_ContentStream_iobuf *buf;
+               CORBA_long           len;
+
+               len = (pos + CORBA_BLOCK_SIZE < length) ?
+                       CORBA_BLOCK_SIZE : length - pos;
+
+               Accessibility_ContentStream_read (stream, len, &buf, ev);
+
+               if (BONOBO_EX (ev) || !buf)
+                       goto io_error;
+
+               if (buf->_length > 0) {
+                       memcpy (mem + pos, buf->_buffer, buf->_length);
+                       pos += buf->_length;
+                       *length_read += buf->_length;
+                       /* we assume a short read equals EOF ... is that right? */
+                       if (buf->_length < len || *length_read == size)
+                           return mem;
+               } else {
+                       g_warning ("Buffer length %d", buf->_length);
+                       goto io_error;
+               }
+               *length_read += buf->_length;
+
+               CORBA_free (buf);
+       }
+
+       return mem;
+
+ io_error:
+       return NULL;
+}
+#endif         // TODO
+
+/* internal use only, declared in cspi-private.h */
+void
+cspi_streams_close_all (void)
+{
+#if 0  // TODO
+  if (streams)
+    {
+      g_hash_table_destroy (streams);
+      streams = NULL;
+    }
+#else
+  g_warning ("Streams not implemented yet");
+#endif // TODO
+}
+
+#if 0  // TODO
+/**
+ * AccessibleStreamableContent_ref:
+ * @obj: a pointer to the #AccessibleStreamableContent implementor on which to
+ *       operate.
+ *
+ * Increment the reference count for an #AccessibleStreamableContent object.
+ *
+ * @Since: AT-SPI 1.4
+ **/
+void
+AccessibleStreamableContent_ref (AccessibleStreamableContent *obj)
+{
+  cspi_object_ref (obj);
+}
+
+/**
+ * AccessibleStreamableContent_unref:
+ * @obj: a pointer to the #AccessibleStreamableContent implementor
+ *       on which to operate. 
+ *
+ * Decrement the reference count for an #AccessibleStreamableContent object.
+ *
+ * @Since: AT-SPI 1.4
+ **/
+void
+AccessibleStreamableContent_unref (AccessibleStreamableContent *obj)
+{
+  cspi_object_unref (obj);
+}
+
+/**
+ * AccessibleStreamableContent_getContentTypes:
+ * @obj: a pointer to the #AccessibleStreamableContent implementor on which to operate.
+ *
+ * Get a list of strings containing the content mimetypes available from an
+ *       #AccessibleStreamableContent implementor.
+ *
+ * @Since: AT-SPI 1.4
+ *
+ * Returns: an array of strings, terminated by a NULL string, specifying the
+ *       mimetypes for which the streamed content is available.
+ *
+ **/
+
+char **
+AccessibleStreamableContent_getContentTypes (AccessibleStreamableContent *obj)
+{
+  Accessibility_StringSeq *mimeseq;
+  char **content_types;
+  int i;
+
+  g_return_val_if_fail (obj != NULL, NULL);
+
+  mimeseq = Accessibility_StreamableContent_getContentTypes (CSPI_OBJREF (obj),
+                                                            cspi_ev ());
+  cspi_return_val_if_ev ("getContentTypes", NULL); 
+  content_types = g_new0 (char *, mimeseq->_length + 1);
+  for (i = 0; i < mimeseq->_length; ++i)
+    content_types[i] = g_strdup (mimeseq->_buffer[i]);
+  content_types [mimeseq->_length] = NULL;
+  CORBA_free (mimeseq);
+  
+  return content_types;
+}
+/**
+* AccessibleStreamableContent_freeContentTypesList:
+* @obj: the AccessibleStreamableContent implementor on which to operate.
+* @content_types: a list of content types previously returned by 
+*     #AccessibleStreamableContent_getContentTypes.
+*
+* Free the memory associated with a call to #AccessibleStreamableContent_getContentTypes, once 
+* the result has been used.
+*
+* Since: AT-SPI 1.4
+**/
+void
+AccessibleStreamableContent_freeContentTypesList (AccessibleStreamableContent *obj,
+                                                 char **content_types)
+{
+  if (content_types) 
+    {
+      gint i = 0;
+      while (content_types[i])
+       {
+         g_free (content_types[i]);
+         i++;
+       }
+      g_free (content_types);
+    }
+}
+
+/**
+ * AccessibleStreamableContent_open:
+ * @obj: a pointer to the #AccessibleStreamableContent implementor on which to operate.
+ * @content_type: a string specifying the content type to retrieve (should match one
+ * of the return strings from #AccessibleStreamableContent_getContentTypes ()).
+ *
+ * Open a streaming connection to an AccessibleStreamableContent implementor,
+ *       of a particular content type.  Note that a client may only have one
+ *       open stream per streamable interface instance in the current 
+ *       implementation.
+ *
+ * @Since: AT-SPI 1.4
+ *
+ * Returns: #TRUE if successful, #FALSE if unsuccessful.
+ *
+ **/
+SPIBoolean
+AccessibleStreamableContent_open (AccessibleStreamableContent *obj,
+                                 const char *content_type)
+{
+  Accessibility_ContentStream stream;
+  struct StreamCacheItem *cache;
+  stream = Accessibility_StreamableContent_getStream (CSPI_OBJREF (obj),
+                                                     content_type,
+                                                     cspi_ev ());
+  cspi_return_val_if_ev ("getContent", FALSE); 
+
+  if (stream != CORBA_OBJECT_NIL) {
+    cache = g_new0 (struct StreamCacheItem, 1);
+    cache->stream = stream;
+    cache->mimetype = CORBA_string_dup (content_type);
+
+    g_hash_table_replace (get_streams (), CSPI_OBJREF (obj), cache);
+    /* FIXME 
+     * This limits us to one concurrent stream per streamable interface
+     * for a given client.
+     * It might be reasonable for a client to open more than one stream
+     * to content, in different mime-types, at the same time.
+     */
+
+    return TRUE;
+  }
+  return FALSE;
+}
+
+/**
+ * AccessibleStreamableContent_close:
+ * @obj: a pointer to the #AccessibleStreamableContent implementor on which to operate.
+ *
+ * Close the current streaming connection to an AccessibleStreamableContent implementor.
+ * This must be called before any subsequent AccessibleStreamableContent_open
+ * calls on the same object.
+ * 
+ * @Since: AT-SPI 1.4
+ *
+ * Returns: #TRUE if successful, #FALSE if unsuccessful.
+ *
+ **/
+SPIBoolean
+AccessibleStreamableContent_close (AccessibleStreamableContent *obj)
+{
+  if (CSPI_OBJREF (obj) != CORBA_OBJECT_NIL) {
+    if (g_hash_table_remove (get_streams (), CSPI_OBJREF (obj)))
+      return TRUE;
+  }
+  return FALSE;
+}
+
+/**
+ * AccessibleStreamableContent_seek:
+ * @obj: a pointer to the #AccessibleStreamableContent implementor on which to operate.
+ * @offset: a long int specifying the offset into the stream.
+ * @seek_type: an enum indicating the seek offset type, may be SEEK_SET,
+ *            SEEK_CUR, SEEK_END (as in the lseek() libc command).
+ *
+ * Cause the current streamable content connection (obtained via
+ *     #AccessibleStreamableContent_open()) to seek to a particular offset in the
+ *     stream.
+ *
+ * @Since: AT-SPI 1.4
+ *
+ * Returns: #TRUE if successful, #FALSE if unsuccessful.
+ *
+ **/
+long int
+AccessibleStreamableContent_seek (AccessibleStreamableContent *obj,
+                                 long int offset,
+                                 AccessibleStreamableContentSeekType seek_type)
+{
+  Accessibility_ContentStream stream;
+  long int ret_offset = 0;
+  struct StreamCacheItem *cached; 
+  Accessibility_ContentStream_SeekType content_seek_type;
+
+  cached = g_hash_table_lookup (get_streams (), CSPI_OBJREF (obj));
+  if (cached)
+    {
+      stream = cached->stream;
+      if (stream != CORBA_OBJECT_NIL)
+       {
+         switch (seek_type) {
+         case SPI_STREAM_SEEK_SET:
+           content_seek_type = Accessibility_ContentStream_SEEK_SET; 
+           break;
+         case SPI_STREAM_SEEK_END:
+           content_seek_type = Accessibility_ContentStream_SEEK_END; 
+           break;
+         case SPI_STREAM_SEEK_CUR:
+         default:
+           content_seek_type = Accessibility_ContentStream_SEEK_CURRENT; 
+           break;
+         }
+         ret_offset = accessible_content_stream_client_seek (stream, offset, 
+                                                            content_seek_type, cspi_ev ());
+         cspi_return_val_if_ev ("seek", FALSE);
+       }
+    }
+  return ret_offset;
+}
+
+/**
+ * AccessibleStreamableContent_read:
+ * @obj: a pointer to the #AccessibleStreamableContent implementor on which to operate.
+ * @buff: a pointer to a buffer into which the resulting bytes read from the stream
+ *        are to be written.
+ * @nbytes: a long integer indicating the number of bytes to read/write.
+ * @read_type: currently unused, specifies behavior of reads for streamed content
+ *        if blocking is not allowed, etc.
+ *
+ * Copy (read) bytes from the currently open streamable content connection
+ *     to a buffer.  This is a blocking API, in the sense that it does not 
+ *     return until the bytes have been read, or an error condition is 
+ *     detected.
+ *
+ * @Since: AT-SPI 1.4
+ *
+ * Returns: an integer indicating the number of bytes read, or -1 on error.
+ *
+ **/
+SPIBoolean
+AccessibleStreamableContent_read (AccessibleStreamableContent *obj,
+                                 void *buff,
+                                 long int nbytes,
+                                 unsigned int read_type)
+{
+  Accessibility_ContentStream stream;
+  struct StreamCacheItem *cached; 
+  cached = g_hash_table_lookup (get_streams (), CSPI_OBJREF (obj));
+  if (cached)
+    {
+      CORBA_long len_read = 0;
+      stream = cached->stream;
+      if (stream != CORBA_OBJECT_NIL)
+       {
+          guint8 *mem;
+
+         mem = accessible_content_stream_client_read (stream, (size_t) nbytes, &len_read, cspi_ev ());
+         cspi_return_val_if_ev ("read", FALSE);
+         if (mem)
+            {
+              memcpy (buff, mem, len_read);
+             g_free (mem);
+             if ((nbytes == -1) || (len_read == nbytes))
+                return TRUE;
+           }
+       }
+    }
+  else g_message ("no matching stream was opened...");
+  return FALSE;
+}
+#endif // TODO
diff --git a/cspi/spi_table.c b/cspi/spi_table.c
new file mode 100644 (file)
index 0000000..e45408c
--- /dev/null
@@ -0,0 +1,815 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <stdlib.h> /* for malloc */
+#include <cspi/spi-private.h>
+
+/**
+ * AccessibleTable_ref:
+ * @obj: a pointer to the #AccessibleTable implementor on which to operate.
+ *
+ * Increment the reference count for an #AccessibleTable object.
+ **/
+void
+AccessibleTable_ref (AccessibleTable *obj)
+{
+  cspi_object_ref (obj);
+}
+
+/**
+ * AccessibleTable_unref:
+ * @obj: a pointer to the #AccessibleTable implementor on which to operate.
+ *
+ * Decrement the reference count for an #AccessibleTable object.
+ **/
+void
+AccessibleTable_unref (AccessibleTable *obj)
+{
+  cspi_object_unref (obj);
+}
+
+/**
+ * AccessibleTable_getCaption:
+ * @obj: a pointer to the #AccessibleTable implementor on which to operate.
+ *
+ * Get an accessible representation of the caption for an #AccessibleTable.
+ *
+ * Returns: an #Accessible object that serves as the table's caption.
+ **/
+Accessible *
+AccessibleTable_getCaption (AccessibleTable *obj)
+{
+  char *path;
+  Accessible *retval;
+
+  cspi_return_val_if_fail (obj != NULL, NULL);
+
+  cspi_dbus_get_property (obj, spi_interface_table, "caption", NULL, "o", &path);
+  cspi_return_val_if_ev ("getCaption", NULL);
+  retval =  cspi_ref_related_accessible (obj, path);
+  g_free (path);
+  return retval;
+}
+
+/**
+ * AccessibleTable_getSummary:
+ * @obj: a pointer to the #AccessibleTable implementor on which to operate.
+ *
+ * Get an accessible object which summarizes the contents of an #AccessibleTable.
+ *
+ * Returns: an #Accessible object that serves as the table's summary (often a
+ *          reduced #AccessibleTable).
+ **/
+Accessible *
+AccessibleTable_getSummary (AccessibleTable *obj)
+{
+  char *path;
+  Accessible *retval;
+
+  cspi_return_val_if_fail (obj != NULL, NULL);
+
+  cspi_dbus_get_property (obj, spi_interface_table, "summary", NULL, "o", &path);
+  cspi_return_val_if_ev ("getSummary", NULL);
+  retval =  cspi_ref_related_accessible (obj, path);
+  g_free (path);
+ return retval;
+}
+
+/**
+ * AccessibleTable_getNRows:
+ * @obj: a pointer to the #AccessibleTable implementor on which to operate.
+ *
+ * Get the number of rows in an #AccessibleTable,
+ *        exclusive of any rows that are programmatically hidden, but inclusive
+ *        of rows that may be outside of the current scrolling window or viewport.
+ *
+ * Returns: a #long integer indicating the number of rows in the table.
+ **/
+long
+AccessibleTable_getNRows (AccessibleTable *obj)
+{
+  dbus_int32_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, -1);
+
+  cspi_dbus_get_property (obj, spi_interface_table, "nRows", NULL, "i", &retval);
+         
+  cspi_return_val_if_ev ("getNRows", -1);
+
+  return retval;
+         
+}
+
+/**
+ * AccessibleTable_getNColumns:
+ * @obj: a pointer to the #AccessibleTable implementor on which to operate.
+ *
+ * Get the number of columns in an #AccessibleTable,
+ *        exclusive of any columns that are programmatically hidden, but inclusive
+ *        of columns that may be outside of the current scrolling window or viewport.
+ *
+ * Returns: a #long integer indicating the number of columns in the table.
+ **/
+long
+AccessibleTable_getNColumns (AccessibleTable *obj)
+{
+  dbus_int32_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, -1);
+
+  cspi_dbus_get_property (obj, spi_interface_table, "nColumns", NULL, "i", &retval);
+         
+  cspi_return_val_if_ev ("getNColumns", -1);
+
+  return retval;
+}
+
+/**
+ * AccessibleTable_getAccessibleAt:
+ * @obj: a pointer to the #AccessibleTable implementor on which to operate.
+ * @row: the specified table row, zero-indexed.
+ * @column: the specified table column, zero-indexed.
+ *
+ * Get the table cell at the specified row and column indices.
+ *          To get the accessible object at a particular (x, y) screen coordinate,
+ *          use #Accessible_getAccessibleAtPoint ().
+ *
+ * Returns: an #Accessible object representing the specified table cell.
+ **/
+Accessible *
+AccessibleTable_getAccessibleAt (AccessibleTable *obj,
+                                 long int row,
+                                 long int column)
+{
+  dbus_int32_t d_row = row, d_column = column;
+  char *path;
+  Accessible *retval;
+
+  cspi_return_val_if_fail (obj != NULL, NULL);
+
+  cspi_dbus_call (obj, spi_interface_table, "getAccessibleAt", NULL, "ii=>o", &d_row, &d_column, &path);
+  cspi_return_val_if_ev ("getAccessibleAt", NULL);
+  retval = cspi_ref_related_accessible (obj, path);
+  g_free (path);
+ return retval;
+}
+
+/**
+ * AccessibleTable_getIndexAt:
+ * @obj: a pointer to the #AccessibleTable implementor on which to operate.
+ * @row: the specified table row, zero-indexed.
+ * @column: the specified table column, zero-indexed.
+ *
+ * Get the 1-D child index corresponding to the specified 2-D row and column indices.
+ *          To get the accessible object at a particular (x, y) screen coordinate,
+ *          use #Accessible_getAccessibleAtPoint ().
+ * @see #AccessibleTable_getRowAtIndex(), #AccessibleTable_getColumnAtIndex()
+ *
+ * Returns: a long integer which serves as the index of a specified cell in the
+ *          table, in a form usable by #Accessible_getChildAtIndex().
+ **/
+long
+AccessibleTable_getIndexAt (AccessibleTable *obj,
+                            long int row,
+                            long int column)
+{
+  dbus_int32_t d_row = row, d_column = column;
+  dbus_int32_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, -1);
+
+  cspi_dbus_call (obj, spi_interface_table, "getIndexAt", NULL, "ii=>i", d_row, d_column, &retval);
+         
+  cspi_return_val_if_ev ("getIndexAt", -1);
+
+  return retval;
+}
+
+/**
+ * AccessibleTable_getRowAtIndex:
+ * @obj: a pointer to the #AccessibleTable implementor on which to operate.
+ * @index: the specified child index, zero-indexed.
+ *
+ * Get the table row index occupied by the child at a particular 1-D child index.
+ *
+ * @see #AccessibleTable_getIndexAt(), #AccessibleTable_getColumnAtIndex()
+ *
+ * Returns: a long integer indicating the first row spanned by the child of a
+ *          table, at the specified 1-D (zero-offset) @index.
+ **/
+long
+AccessibleTable_getRowAtIndex (AccessibleTable *obj,
+                               long index)
+{
+  dbus_int32_t d_index = index;
+  dbus_int32_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, -1);
+
+  cspi_dbus_call (obj, spi_interface_table, "getRowAtIndex", NULL, "i=>i", d_index, &retval);
+         
+  cspi_return_val_if_ev ("getRowAtIndex", -1);
+
+  return retval;
+}
+
+/**
+ * AccessibleTable_getColumnAtIndex:
+ * @obj: a pointer to the #AccessibleTable implementor on which to operate.
+ * @index: the specified child index, zero-indexed.
+ *
+ * Get the table column index occupied by the child at a particular 1-D child index.
+ *
+ * @see #AccessibleTable_getIndexAt(), #AccessibleTable_getRowAtIndex()
+ *
+ * Returns: a long integer indicating the first column spanned by the child of a
+ *          table, at the specified 1-D (zero-offset) @index.
+ **/
+long
+AccessibleTable_getColumnAtIndex (AccessibleTable *obj,
+                                  long index)
+{
+  dbus_int32_t d_index = index;
+  dbus_int32_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, -1);
+
+  cspi_dbus_call (obj, spi_interface_table, "getColumnAtIndex", NULL, "i=>i", d_index, &retval);
+         
+  cspi_return_val_if_ev ("getColumnAtIndex", -1);
+
+  return retval;
+}
+
+/**
+ * AccessibleTable_getRowDescription:
+ * @obj: a pointer to the #AccessibleTable implementor on which to operate.
+ * @row: the specified table row, zero-indexed.
+ *
+ * Get a text description of a particular table row.  This differs from
+ * AccessibleTable_getRowHeader, which returns an #Accessible.
+ *
+ * Returns: a UTF-8 string describing the specified table row, if available.
+ **/
+char *
+AccessibleTable_getRowDescription (AccessibleTable *obj,
+                                  long int         row)
+{
+  dbus_int32_t d_row = row;
+  char *retval;
+
+  cspi_return_val_if_fail (obj != NULL, NULL);
+
+  cspi_dbus_call (obj, spi_interface_table, "getRowDescription", NULL, "i=>s", d_row, &retval);
+         
+  cspi_return_val_if_ev ("getRowDescription", NULL);
+
+  return retval;
+}
+
+/**
+ * AccessibleTable_getColumnDescription:
+ * @obj: a pointer to the #AccessibleTable implementor on which to operate.
+ * @column: the specified table column, zero-indexed.
+ *
+ * Get a text description of a particular table column.  This differs from
+ * AccessibleTable_getColumnHeader, which returns an #Accessible.
+ *
+ * Returns: a UTF-8 string describing the specified table column, if available.
+ **/
+char *
+AccessibleTable_getColumnDescription (AccessibleTable *obj,
+                                     long int         column)
+{
+  dbus_int32_t d_column = column;
+  char *retval;
+
+  cspi_return_val_if_fail (obj != NULL, NULL);
+
+  cspi_dbus_call (obj, spi_interface_table, "getColumnDescription", NULL, "i=>s", d_column, &retval);
+
+  cspi_return_val_if_ev ("getColumnDescription", NULL);
+
+  return retval;
+}
+
+/**
+ * AccessibleTable_getRowExtentAt:
+ * @obj: a pointer to the #AccessibleTable implementor on which to operate.
+ * @row: the specified table row, zero-indexed.
+ * @column: the specified table column, zero-indexed.
+ *
+ * Get the number of rows spanned by the table cell at the specific row and column.
+ * (some tables can have cells which span multiple rows and/or columns).
+ *
+ * Returns: a long integer indicating the number of rows spanned by the specified cell.
+ **/
+long
+AccessibleTable_getRowExtentAt (AccessibleTable *obj,
+                                long int         row,
+                                long int         column)
+{
+  dbus_int32_t d_row = row, d_column = column;
+  dbus_int32_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, -1);
+
+  cspi_dbus_call (obj, spi_interface_table, "getRowExtentAt", NULL, "ii=>i", d_row, d_column, &retval);
+         
+  cspi_return_val_if_ev ("getRowExtentAt", -1);
+
+  return retval;
+}
+
+/**
+ * AccessibleTable_getColumnExtentAt:
+ * @obj: a pointer to the #AccessibleTable implementor on which to operate.
+ * @row: the specified table row, zero-indexed.
+ * @column: the specified table column, zero-indexed.
+ *
+ * Get the number of columns spanned by the table cell at the specific row and column.
+ * (some tables can have cells which span multiple rows and/or columns).
+ *
+ * Returns: a long integer indicating the number of columns spanned by the specified cell.
+ **/
+long
+AccessibleTable_getColumnExtentAt (AccessibleTable *obj,
+                                   long int         row,
+                                   long int         column)
+{
+  dbus_int32_t d_row = row, d_column = column;
+  dbus_int32_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, -1);
+
+  cspi_dbus_call (obj, spi_interface_table, "getColumnExtentAt", NULL, "ii=>i", d_row, d_column, &retval);
+         
+  cspi_return_val_if_ev ("getColumnExtentAt", -1);
+
+  return retval;
+}
+
+/**
+ * AccessibleTable_getRowHeader:
+ * @obj: a pointer to the #AccessibleTable implementor on which to operate.
+ * @row: the specified table row, zero-indexed.
+ *
+ * Get the header associated with a table row, if available.  This differs from
+ * AccessibleTable_getRowDescription, which returns a string.
+ *
+ * Returns: a #Accessible representatin of the specified table row, if available.
+ **/
+Accessible *
+AccessibleTable_getRowHeader (AccessibleTable *obj,
+                             long int         row)
+{
+  dbus_int32_t d_row = row;
+  char *path;
+  Accessible *retval;
+
+  cspi_return_val_if_fail (obj != NULL, NULL);
+
+  cspi_dbus_call (obj, spi_interface_table, "getRowHeader", NULL, "i=>o", d_row, &path);
+  cspi_return_val_if_ev ("getRowHeader", NULL);
+  retval = cspi_ref_related_accessible (obj, path);
+  g_free (path);
+
+ return retval;
+}
+
+/**
+ * AccessibleTable_getColumnHeader:
+ * @obj: a pointer to the #AccessibleTable implementor on which to operate.
+ * @column: the specified table column, zero-indexed.
+ *
+ * Get the header associated with a table column, if available.  This differs from
+ * AccessibleTable_getColumnDescription, which returns a string.
+ *
+ * Returns: a #Accessible representatin of the specified table column, if available.
+ **/
+Accessible *
+AccessibleTable_getColumnHeader (AccessibleTable *obj,
+                                long int column)
+{
+  dbus_int32_t d_column = column;
+  char *path;
+  Accessible *retval;
+
+  cspi_return_val_if_fail (obj != NULL, NULL);
+
+  cspi_dbus_call (obj, spi_interface_table, "getColumnHeader", NULL, "i=>o", d_column, &path);
+  cspi_return_val_if_ev ("getColumnHeader", NULL);
+  retval = cspi_ref_related_accessible (obj, path);
+  g_free (path);
+
+  return retval;
+}
+
+/**
+ * AccessibleTable_getNSelectedRows:
+ * @obj: a pointer to the #AccessibleTable implementor on which to operate.
+ *
+ * Query a table to find out how many rows are currently selected.  Not all tables
+ *  support row selection.
+ *
+ * Returns: a long integer indicating the number of rows currently selected.
+ **/
+long
+AccessibleTable_getNSelectedRows (AccessibleTable *obj)
+{
+  dbus_int32_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, -1);
+
+  cspi_dbus_get_property (obj, spi_interface_table, "nSelectedRows", NULL, "i", &retval);
+         
+  cspi_return_val_if_ev ("getNSelectedRows", -1);
+
+  return retval;
+}
+
+static long
+cspi_long_seq_to_array (GArray *seq, long int **array)
+{
+  long *j;
+  long length, i;
+
+  if (!cspi_check_ev ("getSelectionItems"))
+    {
+      *array = NULL;
+      return 0;
+    }
+
+  length = seq->len;
+
+  j = *array = malloc (sizeof (long) * length);
+
+  for (i = 0; i < length; i++)
+    {
+      j[i] = g_array_index (seq, long, i);
+    }
+
+  g_array_free (seq, TRUE);
+
+  return length;
+}
+
+/**
+ * AccessibleTable_getSelectedRows:
+ * @obj: a pointer to the #AccessibleTable implementor on which to operate.
+ * @selectedRows: a doubly indirected pointer which will be set to the address
+ *       of an array of long integers, specifying which rows are currently selected.
+ *
+ * Query a table for a list of indices of rows which are currently selected.
+ *
+ * Returns: a long integer indicating the length of the array returned in @selectedRows.
+ **/
+long
+AccessibleTable_getSelectedRows (AccessibleTable *obj,
+                                 long int       **selectedRows)
+{
+  GArray *rows;
+
+  *selectedRows = NULL;
+
+  cspi_return_val_if_fail (obj != NULL, 0);
+
+  cspi_dbus_call (obj, spi_interface_table, "getSelectedRows", NULL, "=>ai", &rows);
+
+  cspi_return_val_if_ev ("getSelectedRows", -1);
+
+  return cspi_long_seq_to_array (rows, selectedRows);
+}
+
+/**
+ * AccessibleTable_getNSelectedColumns:
+ * @obj: a pointer to the #AccessibleTable implementor on which to operate.
+ *
+ * Query a table to find out how many columns are currently selected.  Not all tables
+ *  support column selection.
+ *
+ * Returns: a long integer indicating the number of columns currently selected.
+ **/
+long
+AccessibleTable_getNSelectedColumns (AccessibleTable *obj)
+{
+  dbus_int32_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, -1);
+
+  cspi_dbus_get_property (obj, spi_interface_table, "nSelectedColumns", NULL, "i", &retval);
+         
+  cspi_return_val_if_ev ("getNSelectedColumns", -1);
+
+  return retval;
+}
+
+/**
+ * AccessibleTable_getSelectedColumns:
+ * @obj: a pointer to the #AccessibleTable implementor on which to operate.
+ * @selectedColumns: a doubly indirected pointer which will be set to the address
+ *       of an array of long integers, specifying which columns are currently selected.
+ *
+ * Query a table for a list of indices of columns which are currently selected.
+ *       Not all tables support column selection.
+ *
+ * Returns: a long integer indicating the length of the array returned in @selectedColumns.
+ **/
+long
+AccessibleTable_getSelectedColumns (AccessibleTable *obj,
+                                    long int       **selectedColumns)
+{
+  GArray *columns;
+
+  *selectedColumns = NULL;
+
+  cspi_return_val_if_fail (obj != NULL, 0);
+
+  cspi_dbus_call (obj, spi_interface_table, "getSelectedColumns", NULL, "=>ai", &columns);
+
+  cspi_return_val_if_ev ("getSelectedColumns", -1);
+  return cspi_long_seq_to_array (columns, selectedColumns);
+}
+
+/**
+ * AccessibleTable_isRowSelected:
+ * @obj: a pointer to the #AccessibleTable implementor on which to operate.
+ * @row: the zero-indexed row number of the row being queried.
+ *
+ * Determine whether a table row is selected.  Not all tables support row selection.
+ *
+ * Returns: #TRUE if the specified row is currently selected, #FALSE if not.
+ **/
+SPIBoolean
+AccessibleTable_isRowSelected (AccessibleTable *obj,
+                               long int         row)
+{
+  dbus_int32_t d_row = row;
+  dbus_bool_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_table, "isRowSelected", NULL, "i=>b", d_row, &retval);
+
+  cspi_return_val_if_ev ("isRowSelected", FALSE);
+
+  return retval;
+}
+
+/**
+ * AccessibleTable_isColumnSelected:
+ * @obj: a pointer to the #AccessibleTable implementor on which to operate.
+ * @column: the zero-indexed column number of the column being queried.
+ *
+ * Determine whether specified table column is selected.
+ * Not all tables support column selection.
+ *
+ * Returns: #TRUE if the specified column is currently selected, #FALSE if not.
+ **/
+SPIBoolean
+AccessibleTable_isColumnSelected (AccessibleTable *obj,
+                                  long int         column)
+{
+  dbus_int32_t d_column = column;
+  dbus_bool_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_table, "isColumnSelected", NULL, "i=>b", d_column, &retval);
+         
+  cspi_return_val_if_ev ("isColumnSelected", FALSE);
+
+  return retval;
+}
+
+/**
+ * AccessibleTable_addRowSelection:
+ * @obj: a pointer to the #AccessibleTable implementor on which to operate.
+ * @row: the zero-indexed row number of the row being selected.
+ *
+ * Select the specified row, adding it to the current row selection.
+ * Not all tables support row selection.
+ *
+ * Returns: #TRUE if the specified row was successfully selected, #FALSE if not.
+ **/
+SPIBoolean
+AccessibleTable_addRowSelection (AccessibleTable *obj,
+                                long int         row)
+{
+  dbus_int32_t d_row = row;
+  dbus_bool_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_table, "addRowSelection", NULL, "i=>b", d_row, &retval);
+         
+  cspi_return_val_if_ev ("addRowSelection", FALSE);
+
+  return retval;
+}
+
+/**
+ * AccessibleTable_addColumnSelection:
+ * @obj: a pointer to the #AccessibleTable implementor on which to operate.
+ * @column: the zero-indexed column number of the column being selected.
+ *
+ * Select the specified column, adding it to the current column selection.
+ * Not all tables support column selection.
+ *
+ * Returns: #TRUE if the specified column was successfully selected, #FALSE if not.
+ **/
+SPIBoolean
+AccessibleTable_addColumnSelection (AccessibleTable *obj,
+                                   long int         column)
+{
+  dbus_int32_t d_column = column;
+  dbus_bool_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_table, "addColumnSelection", NULL, "i=>b", d_column, &retval);
+         
+  cspi_return_val_if_ev ("addColumnSelection", FALSE);
+
+  return retval;
+}
+
+/**
+ * AccessibleTable_removeRowSelection:
+ * @obj: a pointer to the #AccessibleTable implementor on which to operate.
+ * @row: the zero-indexed number of the row being deselected.
+ *
+ * De-select the specified row, removing it to the current row selection.
+ * Not all tables support row selection.
+ *
+ * Returns: #TRUE if the specified row was successfully de-selected, #FALSE if not.
+ **/
+SPIBoolean
+AccessibleTable_removeRowSelection (AccessibleTable *obj,
+                                   long int         row)
+{
+  dbus_int32_t d_row = row;
+  dbus_bool_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_table, "removeRowSelection", NULL, "i=>b", d_row, &retval);
+         
+  cspi_return_val_if_ev ("removeRowSelection", FALSE);
+
+  return retval;
+}
+
+/**
+ * AccessibleTable_removeColumnSelection:
+ * @obj: a pointer to the #AccessibleTable implementor on which to operate.
+ * @column: the zero-indexed column number of the column being de-selected.
+ *
+ * De-select the specified column, removing it to the current column selection.
+ * Not all tables support column selection.
+ *
+ * Returns: #TRUE if the specified column was successfully de-selected, #FALSE if not.
+ **/
+SPIBoolean
+AccessibleTable_removeColumnSelection (AccessibleTable *obj,
+                                      long int         column)
+{
+  dbus_int32_t d_column = column;
+  dbus_bool_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_table, "removeColumnSelection", NULL, "i=>b", d_column, &retval);
+         
+  cspi_return_val_if_ev ("removeColumnSelection", FALSE);
+
+  return retval;
+}
+
+/**
+ * AccessibleTable_getRowColumnExtentsAtIndex:
+ * @obj: a pointer to the #AccessibleTable implementor on which to operate.
+ * @index: the index of the Table child whose row/column 
+ * extents are requested.
+ * @row: back-filled with the first table row associated with
+ * the cell with child index \c index.
+ * @col: back-filled with the first table column associated 
+ * with the cell with child index \c index.
+ * @row_extents: back-filled with the number of table rows 
+ * across which child \c i extends.
+ * @col_extents: back-filled with the number of table columns
+ * across which child \c i extends.
+ * @is_selected: a boolean which is back-filled with \c True
+ * if the child at index \c i corresponds to a selected table cell,
+ * \c False otherwise.
+ *
+ * Given a child index, determine the row and column indices and 
+ * extents, and whether the cell is currently selected.  If
+ * the child at \c index is not a cell (for instance, if it is 
+ * a summary, caption, etc.), \c False is returned.
+ *
+ * Example:
+ * If the Table child at index '6' extends across columns 5 and 6 of
+ * row 2 of a Table instance, and is currently selected, then
+ * 
+ * retval = table::getRowColumnExtentsAtIndex (6, row, col, 
+ *                                             row_extents,
+ *                                             col_extents,
+ *                                             is_selected);
+ * 
+ * will return True, and after the call
+ * row, col, row_extents, col_extents,
+ * and \c is_selected will contain 2, 5, 1, 2, and 
+ * True, respectively.
+ *
+ * Returns: \c True if the index is associated with a valid table
+ * cell, \c False if the index does not correspond to a cell.  If 
+ * \c False is returned, the values of the out parameters are 
+ * undefined.
+ * 
+ * Since AT-SPI 1.7.0
+ **/
+SPIBoolean
+AccessibleTable_getRowColumnExtentsAtIndex (AccessibleTable *obj,
+                                           long int index, long int *row, long int *col, 
+                                           long int *row_extents, long int *col_extents, 
+                                           long int *is_selected)
+{
+  dbus_int32_t d_index = index;
+  dbus_bool_t retval;
+  dbus_int32_t d_row,  d_col, d_row_extents, d_col_extents; 
+  dbus_bool_t d_is_selected;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_table, "getRowColumnExtentsAtIndex", NULL, "i=>iiiibb", d_index, &d_row, &d_col, &d_row_extents, &d_col_extents, &d_is_selected, &retval);
+
+  if (!cspi_check_ev ("getRowColumnExtentsAtIndex")){
+    
+    *row = 0;
+    *col = 0;
+    *row_extents = 0;
+    *col_extents = 0;
+    *is_selected = FALSE;
+    retval = FALSE;
+  }
+
+  else {
+    *row = d_row;
+    *col = d_col;
+    *row_extents = d_row_extents;;
+    *col_extents = d_col_extents;
+    *is_selected = d_is_selected;;
+  }
+  
+  return retval;
+}
+
+
+/**
+ * AccessibleTable_isSelected:
+ * @obj: a pointer to the #AccessibleTable implementor on which to operate.
+ * @row: the zero-indexed row of the cell being queried.
+ * @column: the zero-indexed column of the cell being queried.
+ *
+ * Determine whether the cell at a specific row and column is selected.
+ *
+ * Returns: #TRUE if the specified cell is currently selected, #FALSE if not.
+ **/
+SPIBoolean
+AccessibleTable_isSelected (AccessibleTable *obj,
+                            long int row,
+                            long int column)
+{
+  dbus_int32_t d_row = row, d_column = column;
+  dbus_bool_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_table, "isSelected", NULL, "ii=>b", d_row, d_column, &retval);
+         
+  cspi_return_val_if_ev ("isSelected", FALSE);
+
+  return retval;
+}
+
diff --git a/cspi/spi_text.c b/cspi/spi_text.c
new file mode 100644 (file)
index 0000000..5339a39
--- /dev/null
@@ -0,0 +1,967 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <cspi/spi-private.h>
+
+static Accessibility_TEXT_BOUNDARY_TYPE
+get_accessible_text_boundary_type (AccessibleTextBoundaryType type)
+{
+  switch (type)
+    {
+    case SPI_TEXT_BOUNDARY_CHAR:
+      return Accessibility_TEXT_BOUNDARY_CHAR;
+      break;
+    case SPI_TEXT_BOUNDARY_CURSOR_POS:
+      /* FixME */
+      return Accessibility_TEXT_BOUNDARY_CHAR;
+      break;
+    case SPI_TEXT_BOUNDARY_WORD_START:
+      return Accessibility_TEXT_BOUNDARY_WORD_START;
+      break;
+    case SPI_TEXT_BOUNDARY_WORD_END:
+      return Accessibility_TEXT_BOUNDARY_WORD_END;
+      break;
+    case SPI_TEXT_BOUNDARY_SENTENCE_START:
+      return Accessibility_TEXT_BOUNDARY_SENTENCE_START;
+      break;
+    case SPI_TEXT_BOUNDARY_SENTENCE_END:
+      return Accessibility_TEXT_BOUNDARY_SENTENCE_END;
+      break;
+    case SPI_TEXT_BOUNDARY_LINE_START:
+      return Accessibility_TEXT_BOUNDARY_LINE_START;
+      break;
+    case SPI_TEXT_BOUNDARY_LINE_END:
+      return Accessibility_TEXT_BOUNDARY_LINE_END;
+      break;
+    case SPI_TEXT_BOUNDARY_ATTRIBUTE_RANGE:
+      /* Fixme */
+      return Accessibility_TEXT_BOUNDARY_CHAR;
+      break;
+    default:
+      /* FIXME */
+      return Accessibility_TEXT_BOUNDARY_CHAR;
+    }
+}
+
+static Accessibility_TEXT_CLIP_TYPE
+get_accessible_text_clip_type (AccessibleTextClipType type)
+{
+  switch (type)
+    {
+    case SPI_TEXT_CLIP_NONE:
+      return Accessibility_TEXT_CLIP_NONE;
+      break;
+    case SPI_TEXT_CLIP_MIN:
+      return Accessibility_TEXT_CLIP_MIN;
+      break;
+    case SPI_TEXT_CLIP_MAX:      
+      return Accessibility_TEXT_CLIP_MAX;
+      break;
+    default:
+      return Accessibility_TEXT_CLIP_BOTH;
+    }
+}
+
+typedef struct
+{
+  dbus_int32_t startOffset;
+  dbus_int32_t endOffset;
+  char *content;
+} Accessibility_Range;
+
+static AccessibleTextRange **
+get_accessible_text_ranges_from_range_seq (GArray *range_seq)
+{
+  AccessibleTextRange **ranges = NULL;
+  AccessibleTextRange *array = NULL;
+  int i;
+  if (range_seq && range_seq->len > 0) 
+    {
+      ranges = g_new0 (AccessibleTextRange *, range_seq->len + 1);
+    }
+  array = g_new0 (AccessibleTextRange, range_seq->len);
+  for (i = 0; i < range_seq->len; i++) 
+    {
+      Accessibility_Range *r = g_array_index (range_seq, Accessibility_Range *, i);
+      AccessibleTextRange *range;
+      range = &array[i];
+      range->start = r->startOffset;
+      range->end = r->endOffset;
+      range->contents = g_strdup (r->content);
+      ranges[i] = range;
+    }
+  ranges[i] = NULL; /* null-terminated list! */
+  // TODO: Figure out whether we're leaking strings
+  g_array_free (range_seq, TRUE);
+
+  return ranges;
+}
+
+
+/**
+ * AccessibleText_ref:
+ * @obj: a pointer to the #AccessibleText object on which to operate.
+ *
+ * Increment the reference count for an #AccessibleText object.
+ **/
+void
+AccessibleText_ref (AccessibleText *obj)
+{
+  cspi_object_ref (obj);
+}
+
+/**
+ * AccessibleText_unref:
+ * @obj: a pointer to the #Accessible object on which to operate.
+ *
+ * Decrement the reference count for an #AccessibleText object.
+ **/
+void
+AccessibleText_unref (AccessibleText *obj)
+{
+  cspi_object_unref (obj);
+}
+
+/**
+ * AccessibleText_getCharacterCount:
+ * @obj: a pointer to the #AccessibleText object to query.
+ *
+ * Get the character count of an #AccessibleText object.
+ *
+ * Returns: a long integer indicating the total number of
+ *              characters in the #AccessibleText object.
+ **/
+long
+AccessibleText_getCharacterCount (AccessibleText *obj)
+{
+  dbus_int32_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, -1);
+
+  cspi_dbus_get_property (obj, spi_interface_text, "characterCount", NULL, "i", &retval);
+
+  cspi_return_val_if_ev ("getCharacterCount", -1);
+
+  return retval;
+}
+
+/**
+ * AccessibleText_getText:
+ * @obj: a pointer to the #AccessibleText object to query.
+ * @startOffset: a #long indicating the start of the desired text range.
+ * @endOffset: a #long indicating the first character past the desired range.
+ *
+ * Get a range of text from an #AccessibleText object.  The number of bytes
+ *          in the returned string may exceed endOffset-startOffset, since
+ *          UTF-8 is a variable-width encoding.
+ *
+ * Returns: a text string containing characters from @startOffset
+ *          to @endOffset-1, inclusive, encoded as UTF-8.
+ **/
+char *
+AccessibleText_getText (AccessibleText *obj,
+                        long int startOffset,
+                        long int endOffset)
+{
+  char *retval;
+  dbus_int32_t d_startOffset = startOffset, d_endOffset = endOffset;
+
+  cspi_return_val_if_fail (obj != NULL, NULL);
+
+  cspi_dbus_call (obj, spi_interface_text, "getText", NULL, "ii=>s", startOffset, endOffset, &retval);
+
+  cspi_return_val_if_ev ("getText", NULL);
+
+  return retval;
+}
+
+/**
+ * AccessibleText_getCaretOffset:
+ * @obj: a pointer to the #AccessibleText object to query.
+ *
+ * Get the current offset of the text caret in an #AccessibleText object.
+ *
+ * Returns: a long integer indicating the current position of the text caret.
+ **/
+long
+AccessibleText_getCaretOffset (AccessibleText *obj)
+{
+  dbus_int32_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, -1);
+
+  cspi_dbus_get_property (obj, spi_interface_text, "caretOffset", NULL, "i", &retval);
+
+  cspi_return_val_if_ev ("getCaretOffset", -1);
+
+  return retval;
+}
+
+/**
+ * AccessibleText_getAttributes:
+ * @obj: a pointer to the #AccessibleText object to query.
+ * @offset: a long integer indicating the offset from which the attribute
+ *        search is based.
+ * @startOffset: a #long indicating the start of the desired text range.
+ * @endOffset: a #long indicating the first character past the desired range.
+ *
+ * Get the attributes applied to a range of text from an #AccessibleText
+ *          object, and the bounds of the range.
+ *          The text attributes correspond to CSS attributes where possible,
+ *          keys and values are delimited from one another via ":", and
+ *          the delimiter between key/value pairs is ";". Thus 
+ *          "font-size:10;foreground-color:0,0,0" would be a valid
+ *          return string.
+ *
+ * Returns: a text string describing the attributes occurring within the
+ *          attribute run containing @offset, encoded as UTF-8.
+ **/
+char *
+AccessibleText_getAttributes (AccessibleText *obj,
+                             long int offset,
+                             long int *startOffset,
+                             long int *endOffset)
+{
+  dbus_int32_t d_offset = offset;
+  dbus_int32_t retStartOffset, retEndOffset;
+  char *retval;        
+
+  if (obj == NULL)
+    {
+      *startOffset = *endOffset = -1;
+      return NULL;
+    }
+
+  cspi_dbus_call (obj, spi_interface_text, "getAttributes", NULL, "i=>iis", d_offset, &retStartOffset, &retEndOffset, &retval);
+
+  if (!cspi_check_ev ("getAttributes"))
+    {
+      *startOffset = *endOffset = -1;
+      retval = NULL;
+    }
+  else
+    {
+      *startOffset = retStartOffset;
+      *endOffset   = retEndOffset;
+    }
+
+  return retval;
+}
+
+/**
+ * AccessibleText_getDefaultAttributes:
+ * @obj: a pointer to the #AccessibleText object to query.
+ *
+ * Get the default attributes applied to an #AccessibleText
+ *          object.
+ *          The text attributes correspond to CSS attributes where possible,
+ *          keys and values are delimited from one another via ":", and
+ *          the delimiter between key/value pairs is ";". Thus 
+ *          "font-size:10;foreground-color:0,0,0" would be a valid
+ *          return string.  The combination of this attribute set and
+ *          the attributes reported by #AccessibleText_getAttributes
+ *          describes the entire set of text attributes over a range.
+ *
+ * @Since: AT-SPI 1.4
+ *
+ * Returns: a text string describing the default attributes 
+ *          applied to a text object, (exclusive of explicitly-set
+ *          attributes), encoded as UTF-8.
+ **/
+char *
+AccessibleText_getDefaultAttributes (AccessibleText *obj)
+{
+  char *retval;        
+
+  if (obj == NULL)
+    {
+      return NULL;
+    }
+
+  cspi_dbus_call (obj, spi_interface_text, "getAttributes", NULL, "=>s", &retval);
+
+  if (!cspi_check_ev ("getAttributes"))
+    {
+      retval = NULL;
+    }
+
+  return retval;
+}
+
+/**
+ * AccessibleText_setCaretOffset:
+ * @obj: a pointer to the #AccessibleText object on which to operate.
+ * @newOffset: the offset to which the text caret is to be moved.
+ *
+ * Set the text caret position for an #AccessibleText object.
+ *
+ * Returns: #TRUE if successful, #FALSE otherwise.
+ **/
+SPIBoolean
+AccessibleText_setCaretOffset (AccessibleText *obj,
+                               long int newOffset)
+{
+  dbus_int32_t d_newOffset = newOffset;
+  dbus_bool_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_text, "setCaretOffset", NULL, "i=>b", d_newOffset, &retval);
+
+  cspi_return_val_if_ev ("setCaretOffset", FALSE);
+
+  return retval;
+}
+
+/**
+ * AccessibleText_getTextBeforeOffset:
+ * @obj: a pointer to the #AccessibleText object on which to operate.
+ * @offset: a long integer indicating the offset from which the delimiter
+ *        search is based.
+ * @type: an #AccessibleTextBoundaryType indicating whether the desired
+ *       text string is a word, sentence, line, or attribute run.
+ * @startOffset: a pointer to a long integer which is assigned the
+ *       starting offset of the returned string, relative to the
+ *       original #AccessibleText.
+ * @endOffset: a pointer to a long integer which is assigned the
+ *       ending offset of the returned string, relative to the original
+ *       #AccessibleText.
+ *
+ * Get delimited text from an #AccessibleText object which precedes a given
+ *          text offset.
+ *
+ * Returns: a UTF-8 string representing the delimited text, both of whose
+ *          delimiting boundaries are before the current offset, or
+ *          an empty string if no such text exists.
+ **/
+char *
+AccessibleText_getTextBeforeOffset (AccessibleText *obj,
+                                    long int offset,
+                                    AccessibleTextBoundaryType type,
+                                   long int *startOffset,
+                                   long int *endOffset)
+{
+  dbus_int32_t d_offset = offset;
+  dbus_uint32_t d_type = type;
+  dbus_int32_t retStartOffset, retEndOffset;
+  char *retval;
+
+  if (obj == NULL)
+    {
+      *startOffset = *endOffset = -1;
+      return NULL;
+    }
+
+  cspi_dbus_call (obj, spi_interface_text, "getTextBeforeOffset", NULL, "iu=>iis", d_offset, d_type, &retStartOffset, &retEndOffset, &retval);
+  if (!cspi_check_ev ("getTextBeforeOffset"))
+    {
+      *startOffset = *endOffset = -1;
+      retval = NULL;
+    }
+  else
+    {
+      *startOffset = retStartOffset;
+      *endOffset = retEndOffset;
+    }
+  return retval;
+}
+
+/**
+ * AccessibleText_getTextAtOffset:
+ * @obj: a pointer to the #AccessibleText object on which to operate.
+ * @offset: a long integer indicating the offset from which the delimiter
+ *        search is based.
+ * @type: an #AccessibleTextBoundaryType indicating whether the desired
+ *       text string is a word, sentence, line, or attribute run.
+ * @startOffset: a pointer to a long integer which is assigned the
+ *       starting offset of the returned string, relative to the
+ *       original #AccessibleText.
+ * @endOffset: a pointer to a long integer which is assigned the
+ *       ending offset of the returned string, relative to the original
+ *       #AccessibleText.
+ *
+ * Get delimited text from an #AccessibleText object which includes a given
+ *          text offset.
+ *
+ * Returns: a UTF-8 string representing the delimited text, whose
+ *          delimiting boundaries bracket the current offset, or
+ *          an empty string if no such text exists.
+ **/
+char *
+AccessibleText_getTextAtOffset (AccessibleText *obj,
+                               long int offset,
+                               AccessibleTextBoundaryType type,
+                               long int *startOffset, long int *endOffset)
+{
+  dbus_int32_t d_offset = offset;
+  dbus_uint32_t d_type = type;
+  dbus_int32_t retStartOffset, retEndOffset;
+  char *retval;
+
+  if (obj == NULL)
+    {
+      *startOffset = *endOffset = -1;
+      return NULL;
+    }
+
+  cspi_dbus_call (obj, spi_interface_text, "getTextAtOffset", NULL, "iu=>iis", d_offset, d_type, &retStartOffset, &retEndOffset, &retval);
+
+  if (!cspi_check_ev ("getTextAtOffset"))
+    {
+      *startOffset = *endOffset = -1;
+      retval = NULL;
+    }
+  else
+    {
+      *startOffset = retStartOffset;
+      *endOffset   = retEndOffset;
+    }
+  return retval;
+}
+
+/**
+ * AccessibleText_getTextAfterOffset:
+ * @obj: a pointer to the #AccessibleText object on which to operate.
+ * @offset: a long integer indicating the offset from which the delimiter
+ *        search is based.
+ * @type: an #AccessibleTextBoundaryType indicating whether the desired
+ *       text string is a word, sentence, line, or attribute run.
+ * @startOffset: a pointer to a long integer which is assigned the
+ *       starting offset of the returned string, relative to the
+ *       original #AccessibleText.
+ * @endOffset: a pointer to a long integer which is assigned the
+ *       ending offset of the returned string, relative to the original
+ *       #AccessibleText.
+ *
+ * Get delimited text from an #AccessibleText object which follows a given
+ *          text offset.
+ *
+ * Returns: a UTF-8 string representing the delimited text, both of whose
+ *          delimiting boundaries are after or inclusive of the current
+ *          offset, or an empty string if no such text exists.
+ **/
+char *
+AccessibleText_getTextAfterOffset (AccessibleText *obj,
+                                  long int offset,
+                                  AccessibleTextBoundaryType type,
+                                  long int *startOffset, long int *endOffset)
+{
+  dbus_int32_t d_offset = offset;
+  dbus_uint32_t d_type = type;
+  dbus_int32_t retStartOffset, retEndOffset;
+  char *retval;
+
+  if (obj == NULL)
+    {
+      *startOffset = *endOffset = -1;
+      return NULL;
+    }
+
+  cspi_dbus_call (obj, spi_interface_text, "getTextAfterOffset", NULL, "iu=>iis", d_offset, d_type, &retStartOffset, &retEndOffset, &retval);
+
+  if (!cspi_check_ev ("getTextAfterOffset"))
+    {
+      *startOffset = *endOffset = -1;
+      retval = NULL;
+    }
+  else
+    {
+      *startOffset = retStartOffset;
+      *endOffset   = retEndOffset;
+    }
+  return retval;
+}
+
+/**
+ * AccessibleText_getCharacterAtOffset:
+ * @obj: a pointer to the #AccessibleText object on which to operate.
+ * @offset: a long integer indicating the text offset where the desired
+ *          character is located.
+ *
+ * Get the character at a given offset for an #AccessibleText object.
+ *
+ * Returns: an #unsigned long integer which represents the
+ *        UCS-4 unicode code point of the given character, or
+ *        0xFFFFFFFF if the character in question cannot be represented
+ *        in the UCS-4 encoding.
+ **/
+unsigned long
+AccessibleText_getCharacterAtOffset (AccessibleText *obj,
+                                     long int offset)
+{
+  dbus_int32_t d_offset = offset;
+  dbus_int32_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, -1);
+
+  cspi_dbus_call (obj, spi_interface_text, "getCharacterAtOffset", NULL, "i=>i", d_offset, &retval);
+
+  cspi_return_val_if_ev ("getCharacterAtOffset", -1);
+
+  return retval;
+}
+
+/**
+ * AccessibleText_getCharacterExtents:
+ * @obj: a pointer to the #AccessibleText object on which to operate.
+ * @offset: an integer indicating the offset of the text character for
+ *        whom boundary information is requested.
+ * @x: a pointer to a long integer into which the nominal x coordinate
+ *     of the corresponding glyph will be returned.
+ * @y:a pointer to a long integer into which the nominal y coordinate
+ *     of the corresponding glyph will be returned.
+ * @width:a pointer to a long integer into which the width
+ *     of the corresponding glyph will be returned.
+ * @height: a pointer to a long integer into which the height
+ *     of the corresponding glyph will be returned.
+ * @type: an #AccessibleCoordType indicating the coordinate system to use
+ *        for the returned values.
+ *
+ * Get the bounding box containing the glyph representing
+ *        the character at a particular text offset.
+ **/
+void
+AccessibleText_getCharacterExtents (AccessibleText *obj,
+                                    long int offset,
+                                    long int *x,
+                                    long int *y,
+                                    long int *width,
+                                    long int *height,
+                                   AccessibleCoordType type)
+{
+  dbus_int32_t d_offset = offset;
+  dbus_uint16_t d_type = type;
+  dbus_int32_t retX, retY, retWidth, retHeight;
+
+  if (obj == NULL)
+    {
+      *x = *y = -1;
+      *width = *height = -1;
+      return;
+    }
+
+  cspi_dbus_call (obj, spi_interface_text, "getCharacterExtents", NULL, "in=>iiii", d_offset, d_type, &retX, &retY, &retWidth, &retHeight);
+
+  if (!cspi_check_ev ("getCharacterExtents"))
+    {
+      *x = *y = -1;
+      *width = *height = -1;
+    }
+  else
+    {
+      *x = retX;
+      *y = retY;
+      *width = retWidth;
+      *height = retHeight;
+    }
+}
+
+/**
+ * AccessibleText_getOffsetAtPoint:
+ * @obj: a pointer to the #AccessibleText object on which to operate.
+ * @x: the x coordinate of the point to be queried.
+ * @y: the y coordinate of the point to be queried.
+ * @type: an #AccessibleCoordType indicating the coordinate system in which
+ *       the values should be returned.
+ *
+ * Get the bounding box for a glyph at a certain #AccessibleText offset.
+ *
+ * Returns: the offset (as a long integer) at the point (@x, @y)
+ *       in the specified coordinate system.
+ *
+ **/
+long
+AccessibleText_getOffsetAtPoint (AccessibleText *obj,
+                                 long int x,
+                                 long int y,
+                                AccessibleCoordType type)
+{
+  dbus_int32_t d_x = x, d_y = y;
+  dbus_uint16_t d_type = type;
+  dbus_int32_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, -1);
+
+  cspi_dbus_call (obj, spi_interface_text, "getOffsetAtPoint", NULL, "iin=>i", d_x, d_y, d_type, &retval);
+
+  cspi_return_val_if_ev ("getOffsetAtPoint", -1);
+
+  return retval;
+}
+
+/**
+ * AccessibleText_getRangeExtents:
+ * @obj: a pointer to the #AccessibleText object on which to operate.
+ * @startOffset: an integer indicating the offset of the first text character for
+ *        whom boundary information is requested.
+ * @endOffset: an integer indicating the offset of the text character 
+ *        after the last character for whom boundary information is requested.
+ * @x: a pointer to a long integer into which the nominal x coordinate
+ *     of the corresponding bounding box will be returned.
+ * @y:a pointer to a long integer into which the nominal y coordinate
+ *     of the corresponding bounding box will be returned.
+ * @width:a pointer to a long integer into which the width
+ *     of the corresponding bounding box will be returned.
+ * @height: a pointer to a long integer into which the height
+ *     of the corresponding bounding box will be returned.
+ * @type: an #AccessibleCoordType indicating the coordinate system to use
+ *        for the returned values.
+ *
+ * Get the bounding box for text within a range in an  #AccessibleText object.
+ *
+ * @Since: AT-SPI 1.2
+ **/
+void
+AccessibleText_getRangeExtents (AccessibleText *obj,
+                               long int startOffset,
+                               long int endOffset,
+                               long int *x,
+                               long int *y,
+                               long int *width,
+                               long int *height,
+                               AccessibleCoordType type)
+{
+  dbus_int32_t d_startOffset = startOffset, d_endOffset = endOffset;
+  dbus_int16_t d_type = type;
+  dbus_int32_t retX, retY, retWidth, retHeight;
+
+  if (obj == NULL)
+    {
+      *x = *y = -1;
+      *width = *height = -1;
+      return;
+    }
+
+  cspi_dbus_call (obj, spi_interface_text, "getRangeExtents", NULL, "iin=>iiii", d_startOffset, d_endOffset, d_type, &retX, &retY, &retWidth, &retHeight);
+
+  if (!cspi_check_ev ("getRangeExtents"))
+    {
+      *x = *y = -1;
+      *width = *height = -1;
+    }
+  else
+    {
+      *x = retX;
+      *y = retY;
+      *width = retWidth;
+      *height = retHeight;
+    }
+}
+
+/**
+ * AccessibleText_getBoundedRanges:
+ * @obj: a pointer to the #AccessibleText object on which to operate.
+ * @x: the 'starting' x coordinate of the bounding box.
+ * @y: the 'starting' y coordinate of the bounding box.
+ * @width: the x extent of the bounding box.
+ * @height: the y extent of the bounding box.
+ * @type: an #AccessibleCoordType indicating the coordinate system to use
+ *        for the returned values.
+ * @clipTypeX: an #AccessibleTextClipType indicating how to treat characters that
+ *        intersect the bounding box's x extents.
+ * @clipTypeY: an #AccessibleTextClipType indicating how to treat characters that
+ *        intersect the bounding box's y extents.
+ *
+ * Get the ranges of text from an #AccessibleText object which lie within the
+ *          bounds defined by (@x, @y) and (@x+@width, @y+@height).  
+ *
+ * @Since: AT-SPI 1.2
+ *
+ * Returns: a null-terminated list of pointers to AccessibleTextRange structs 
+ *          detailing the bounded text.
+ **/
+AccessibleTextRange **
+AccessibleText_getBoundedRanges (AccessibleText *obj,
+                                long int x,
+                                long int y,
+                                long int width,
+                                long int height,
+                                AccessibleCoordType type,
+                                AccessibleTextClipType clipTypeX,
+                                AccessibleTextClipType clipTypeY)
+{
+  dbus_int32_t d_x = x, d_y = y, d_width = width, d_height = height;
+  dbus_uint16_t d_type = type;
+  dbus_uint32_t d_clipTypeX = clipTypeX, d_clipTypeY = clipTypeY;
+  GArray *range_seq;
+
+  cspi_return_val_if_fail (obj != NULL, NULL);
+
+  cspi_dbus_call (obj, spi_interface_text, "getBoundedRanges", NULL, "iiiinuu=>a(iisv)", d_x, d_y, d_width, d_height, d_type, d_clipTypeX, d_clipTypeY, &range_seq);
+
+  cspi_return_val_if_ev ("getBoundedRanges", NULL); 
+  return get_accessible_text_ranges_from_range_seq (range_seq);
+}
+
+/**
+ * AccessibleTextRange_freeRanges:
+ * @ranges: a pointer to an array of AccessibleTextRange structs.
+ *
+ * Free the memory used by a list of AccessibleTextRange structs.
+ * The argument passed in should be an array of pointers 
+ * AccessibleTextRange structs.  
+ *
+ * @Since: AT-SPI 1.2
+ **/
+void
+AccessibleTextRange_freeRanges (AccessibleTextRange **ranges)
+{
+  /* this was a contiguously allocated block, only free the first element */
+  g_free (ranges[0]); 
+  g_free (ranges);
+}
+
+/**
+ * AccessibleText_getNSelections:
+ * @obj: a pointer to the #AccessibleText object on which to operate.
+ *
+ * Get the number of active non-contiguous selections for an
+ *          #AccessibleText object.
+ *
+ * Returns: a long integer indicating the current
+ *          number of non-contiguous text selections active
+ *          within an #AccessibleText object.
+ **/
+long
+AccessibleText_getNSelections (AccessibleText *obj)
+{
+  dbus_int32_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, -1);
+
+  cspi_dbus_call (obj, spi_interface_text, "getNSelections", NULL, "i", &retval);
+
+  cspi_return_val_if_ev ("getNSelections", -1);
+
+  return retval;
+}
+
+/**
+ * AccessibleText_getSelection:
+ * @obj: a pointer to the #AccessibleText object on which to operate.
+ * @selectionNum: an integer indicating which selection to query.
+ * @startOffset: a pointer to a long integer into which the start offset
+ *           of the selection will be returned.
+ * @endOffset: a pointer to a long integer into which the start offset
+ *           of the selection will be returned.
+ *
+ * Get the bounds of the @selectionNum-th active text selection for an
+ *         #AccessibleText object.
+ **/
+void
+AccessibleText_getSelection (AccessibleText *obj,
+                            long int selectionNum,
+                            long int *startOffset,
+                            long int *endOffset)
+{
+  dbus_int32_t d_selectionNum = selectionNum;
+  dbus_int32_t retStartOffset, retEndOffset;
+
+  if (obj == NULL)
+    {
+      *endOffset = *startOffset = -1;
+      return;
+    }
+
+  cspi_dbus_call (obj, spi_interface_text, "getSelection", NULL, "i=>ii", d_selectionNum, &retStartOffset, &retEndOffset);
+
+  if (!cspi_check_ev ("getSelection"))
+    {
+      *startOffset = *endOffset = -1;
+    }
+  else
+    {
+      *startOffset = retStartOffset;
+      *endOffset   = retEndOffset;
+    }
+}
+
+/**
+ * AccessibleText_addSelection:
+ * @obj: a pointer to the #AccessibleText object on which to operate.
+ * @startOffset: the starting offset of the desired new selection.
+ * @endOffset: the offset of the first character after the new selection.
+ *
+ * Select some text (add a text selection) in an #AccessibleText object.
+ *
+ * Returns: #TRUE if successful, #FALSE otherwise.
+ **/
+SPIBoolean
+AccessibleText_addSelection (AccessibleText *obj,
+                            long int startOffset, long int endOffset)
+{
+  dbus_int32_t d_startOffset = startOffset, d_endOffset = endOffset;
+  dbus_bool_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_text, "addSelection", NULL, "ii=>b", d_startOffset, d_endOffset, &retval);
+
+  cspi_return_val_if_ev ("addSelection", FALSE);
+
+  return retval;
+}
+
+/**
+ * AccessibleText_removeSelection:
+ * @obj: a pointer to the #AccessibleText object on which to operate.
+ * @selectionNum: an integer indicating which (possibly of several)
+ *         text selection to remove.
+ *
+ * De-select a text selection.
+ *
+ * Returns: #TRUE if successful, #FALSE otherwise.
+ **/
+SPIBoolean
+AccessibleText_removeSelection (AccessibleText *obj,
+                               long int selectionNum)
+{
+  dbus_int32_t d_selectionNum = selectionNum;
+  dbus_bool_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_text, "removeSelection", NULL, "i=>b", d_selectionNum, &retval);
+
+  cspi_return_val_if_ev ("removeSelection", FALSE);
+
+  return retval;
+}
+
+/**
+ * AccessibleText_setSelection:
+ * @obj: a pointer to the #AccessibleText object on which to operate.
+ * @selectionNum: a zero-offset index indicating which text selection to modify.
+ * @startOffset: a long int, the new starting offset for the selection.
+ * @endOffset: a long int, the desired new offset of the first character
+ *             after the selection.
+ *
+ * Change the bounds of an existing #AccessibleText text selection.
+ *
+ * Returns: #TRUE if successful, #FALSE otherwise.
+ **/
+SPIBoolean
+AccessibleText_setSelection (AccessibleText *obj,
+                            long int selectionNum,
+                            long int startOffset,
+                            long int endOffset)
+{
+  dbus_int32_t d_selectionNum = selectionNum, d_startOffset = startOffset, d_endOffset = endOffset;
+  dbus_bool_t retval;
+
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_text, "setSelection", NULL, "iii=>b", d_selectionNum, d_startOffset, d_endOffset, &retval);
+
+  cspi_return_val_if_ev ("setSelection", FALSE);
+
+  return retval;
+}
+
+
+/**
+ * AccessibleText_getAttributeRun:
+ * @obj: a pointer to the #AccessibleText object to query.
+ * @offset: a long integer indicating the offset from which the attribute
+ *        search is based.
+ * @startOffset: a #long indicating the start of the desired text range.
+ * @endOffset: a #long indicating the first character past the desired range.
+ * @includeDefaults: a #bool if False, the call should only return those 
+ *                 attributes which are explicitly set on the current attribute 
+ *                 run, omitting any attributes which are inherited from the 
+ *                 default values.
+ *
+ *  @Since: AT-SPI 1.7
+ *
+ * Returns: the AttributeSet defined at offset, optionally including the 'default' attributes.
+ **/
+
+AccessibleAttributeSet *
+AccessibleText_getAttributeRun (AccessibleText *obj,
+                               long int offset,
+                               long int *startOffset,
+                               long int *endOffset,
+                               long int includeDefaults){
+
+  dbus_int32_t d_offset = offset;
+  dbus_bool_t d_includeDefaults = includeDefaults;
+  dbus_int32_t retStartOffset, retEndOffset;
+  AccessibleAttributeSet *retval;
+  GArray *attributes;
+
+  if (obj == NULL)
+  {
+       *startOffset = *endOffset = -1;
+       return NULL;
+  }
+
+  cspi_dbus_call (obj, spi_interface_text, "getAttributeRun", NULL, "ib=>iias", d_offset, d_includeDefaults, &retStartOffset, &retEndOffset, &attributes);
+
+  if (!cspi_check_ev ("getAttributeRun"))
+    {
+      *startOffset = *endOffset = -1;
+      retval = NULL;
+    }
+  else 
+  {
+      *startOffset = retStartOffset;
+      *endOffset   = retEndOffset;
+      retval =  _cspi_attribute_set_from_sequence (attributes);
+  }
+
+  return retval;
+                                    
+}
+
+/**
+ * AccessibleText_getDefaultAttributeSet:
+ * @obj: a pointer to the #AccessibleText object to query.
+ *
+ *
+ *  @Since: AT-SPI 1.7
+ *
+ * Returns: an AttributeSet containing the text attributes 
+ * which apply to all text in the object by virtue of the
+ * default settings of the document, view, or user agent; e.g.
+ * those attributes which are implied rather than explicitly 
+ * applied to the text object. For instance, an object whose 
+ * entire text content has been explicitly marked as 'bold' 
+ * will report the 'bold' attribute via getAttributeRun(), 
+ * whereas an object whose text weight is inspecified may 
+ * report the default or implied text weight in the default AttributeSet.
+ *
+ **/
+
+AccessibleAttributeSet *
+AccessibleText_getDefaultAttributeSet (AccessibleText *obj){
+   AccessibleAttributeSet *retval;
+   GArray *attributes;
+
+   cspi_return_val_if_fail (obj != NULL, NULL);
+
+  cspi_dbus_call (obj, spi_interface_text, "getDefaultAttributes", NULL, "as", &attributes);
+  
+  retval = _cspi_attribute_set_from_sequence (attributes);
+  return retval;
+}
diff --git a/cspi/spi_value.c b/cspi/spi_value.c
new file mode 100644 (file)
index 0000000..576eb06
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <cspi/spi-private.h>
+
+/**
+ * AccessibleValue_ref:
+ * @obj: a pointer to the #AccessibleValue implementor on which to operate.
+ *
+ * Increment the reference count for an #AccessibleValue object.
+ **/
+void
+AccessibleValue_ref (AccessibleValue *obj)
+{
+  cspi_object_ref (obj);
+}
+
+/**
+ * AccessibleValue_unref:
+ * @obj: a pointer to the #AccessibleValue implementor on which to operate. 
+ *
+ * Decrement the reference count for an #AccessibleValue object.
+ **/
+void
+AccessibleValue_unref (AccessibleValue *obj)
+{
+  cspi_object_unref (obj);
+}
+
+/**
+ * AccessibleValue_getMinimumValue:
+ * @obj: a pointer to the #AccessibleValue implementor on which to operate. 
+ *
+ * Get the minimum allowed value for an #AccessibleValue.
+ *
+ * Returns: the minimum allowed value for this object.
+ *
+ **/
+double
+AccessibleValue_getMinimumValue (AccessibleValue *obj)
+{
+  double retval;
+
+  cspi_return_val_if_fail (obj != NULL, 0.0);
+
+  cspi_dbus_get_property (obj, spi_interface_value, "minimumValue", NULL, "d", &retval);
+  
+  cspi_return_val_if_ev ("getMinimumValue", 0.0);
+
+  return retval;
+}
+
+/**
+ * AccessibleValue_getCurrentValue:
+ * @obj: a pointer to the #AccessibleValue implementor on which to operate. 
+ *
+ * Get the current value for an #AccessibleValue.
+ *
+ * Returns: the current value for this object.
+ **/
+double
+AccessibleValue_getCurrentValue (AccessibleValue *obj)
+{
+  double retval;
+
+  cspi_return_val_if_fail (obj != NULL, 0.0);
+
+  cspi_dbus_get_property (obj, spi_interface_value, "currentValue", NULL, "d", &retval);
+
+  cspi_return_val_if_ev ("getCurrentValue", 0.0);
+
+  return retval;
+}
+
+/**
+ * AccessibleValue_getMaximumValue:
+ * @obj: a pointer to the #AccessibleValue implementor on which to operate. 
+ *
+ * Get the maximum allowed value for an #AccessibleValue.
+ *
+ * Returns: the maximum allowed value for this object.
+ **/
+double
+AccessibleValue_getMaximumValue (AccessibleValue *obj)
+{
+  double retval;       
+  cspi_return_val_if_fail (obj != NULL, 0.0);
+
+  cspi_dbus_get_property (obj, spi_interface_value, "maximumValue", NULL, "d", &retval);
+
+  cspi_return_val_if_ev ("getMaximumValue", 0.0);
+
+  return retval;
+}
+
+/**
+ * AccessibleValue_setCurrentValue:
+ * @obj: a pointer to the #AccessibleValue implementor on which to operate.
+ * @newValue: a #float value which is the desired new value of the object.
+ *
+ * Set the current value of an #AccessibleValue.
+ *
+ * Returns: #TRUE if the value could be assigned the specified value,
+ *          #FALSE otherwise.
+ **/
+SPIBoolean
+AccessibleValue_setCurrentValue (AccessibleValue *obj,
+                                 double newValue)
+{
+  cspi_return_val_if_fail (obj != NULL, FALSE);
+
+  cspi_dbus_call (obj, spi_interface_value, "setCurrentValue", NULL, "d", &newValue);
+
+  cspi_return_val_if_ev ("setCurrentValue", FALSE);
+
+  return TRUE;
+}
+
+/**
+ * AccessibleValue_getMinimumIncrement:
+ * @obj: a pointer to the #AccessibleValue implementor on which to operate. 
+ *
+ * Get the minimum increment by which an #AccessibleValue can be adjusted.
+ *
+ * Returns: the minimum increment by which the value may be changed, or
+ * zero if the minimum increment cannot be determined.
+ *
+ **/
+double
+AccessibleValue_getMinimumIncrement (AccessibleValue *obj)
+{
+  double retval;
+
+  cspi_return_val_if_fail (obj != NULL, 0.0);
+
+  cspi_dbus_get_property (obj, spi_interface_value, "minimumIncrement", NULL, "d", &retval);
+  
+  cspi_return_val_if_ev ("getMinimumIncrement", 0.0);
+
+  return retval;
+}
+
index 5c96eae..a9db444 100644 (file)
@@ -5,3 +5,17 @@ EXTRA_DIST = \
        testutil.py
 
 CLEANFILES = *.pyc
+
+noinst_PROGRAMS = simple-at
+
+simple_at_SOURCES = simple-at.c 
+
+INCLUDES = -I$(top_srcdir)           \
+           -I$(top_builddir)         \
+          $(DBUS_CFLAGS)            \
+          $(GLIB_CFLAGS)            \
+          $(ATK_CFLAGS)             \
+          $(DEBUG_CFLAGS)
+
+#LDADD = ../spi-common/libspicommon.la ../cspi/libcspi.la ../login-helper/libloginhelper.la $(TESTS_LIBS) $(X_LIBS) $(XINPUT_LIBS)
+LDADD = ../../spi-common/libspicommon.la ../../cspi/libcspi.la $(TESTS_LIBS) $(X_LIBS) $(XINPUT_LIBS) $(ATK_LIBS)