2003-08-19 Padraig O'Briain <padraig.obriain@sun.com>
[platform/core/uifw/at-spi2-atk.git] / cspi / spi_main.c
index 6d0efd1..f54b60a 100644 (file)
@@ -2,7 +2,8 @@
  * AT-SPI - Assistive Technology Service Provider Interface
  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
  *
- * Copyright 2001 Sun Microsystems Inc.
+ * 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
  * 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 CORBA_Environment ev = { 0 };
 static Accessibility_Registry registry = CORBA_OBJECT_NIL;
 static GHashTable *live_refs = NULL;
+static GQueue *exception_handlers = NULL;
 
 static guint
 cspi_object_hash (gconstpointer key)
@@ -49,7 +54,7 @@ cspi_object_equal (gconstpointer a, gconstpointer b)
   CORBA_Object objecta = (CORBA_Object) a;
   CORBA_Object objectb = (CORBA_Object) b;
 
-  return CORBA_Object_is_equivalent (objecta, objectb, &ev);
+  return CORBA_Object_is_equivalent (objecta, objectb, cspi_ev ());
 }
 
 static void
@@ -74,6 +79,34 @@ cspi_object_release (gpointer value)
 #endif
 }
 
+gboolean
+_cspi_exception_throw (CORBA_Environment *ev, 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 = CORBA_OBJECT_NIL; /* can we get this from here? */
+  ex.ev = CORBA_exception__copy (ev);
+  switch (ev->_major) {
+  case CORBA_SYSTEM_EXCEPTION:
+    ex.code = SPI_EXCEPTION_UNSPECIFIED;
+    break;
+  case CORBA_USER_EXCEPTION: /* help! how to interpret this? */
+    ex.code = SPI_EXCEPTION_UNSPECIFIED;
+    break;
+  default:
+    ex.code = SPI_EXCEPTION_UNSPECIFIED;
+    break;
+  }
+  
+  if (handler)
+    return (*handler) (&ex, FALSE);
+  else
+    return FALSE; /* means exception was not handled */
+}
+
 SPIBoolean
 cspi_accessible_is_a (Accessible *accessible,
                      const char *interface_name)
@@ -91,12 +124,13 @@ cspi_accessible_is_a (Accessible *accessible,
 
   if (ev._major != CORBA_NO_EXCEPTION)
     {
-      g_error ("Exception '%s' checking if is '%s'",
-              cspi_exception_get_text (),
-              interface_name);
+      g_warning ("Exception '%s' checking if is '%s'",
+                cspi_exception_get_text (),
+                interface_name);
+      retval = FALSE;
     }
 
-  if (unknown != CORBA_OBJECT_NIL)
+  else if (unknown != CORBA_OBJECT_NIL)
     {
       retval = TRUE;
       cspi_release_unref (unknown);
@@ -123,8 +157,15 @@ cspi_get_live_refs (void)
 }
 
 CORBA_Environment *
+cspi_peek_ev (void)
+{
+  return &ev;
+}
+
+CORBA_Environment *
 cspi_ev (void)
 {
+  CORBA_exception_init (&ev);
   return &ev;
 }
 
@@ -242,6 +283,27 @@ cspi_object_return (Accessible *accessible)
     }
 }
 
+Accessible *
+cspi_object_take (CORBA_Object corba_object)
+{
+  Accessible *accessible;
+  accessible = cspi_object_borrow (corba_object);
+
+  cspi_object_ref (accessible);
+  /* 
+   * if the remote object is dead, 
+   * cspi_object_return will throw an exception. 
+   * FIXME: what clears that exception context ever ?
+   */
+  cspi_object_return (accessible);
+  if (cspi_exception ()) 
+    {
+      cspi_object_unref (accessible);
+      accessible = NULL;
+    }
+  return accessible;
+}
+
 void
 cspi_object_ref (Accessible *accessible)
 {
@@ -269,6 +331,8 @@ cspi_cleanup (void)
 {
   GHashTable *refs;
 
+  cspi_streams_close_all ();
+
   refs = live_refs;
   live_refs = NULL;
   if (refs)
@@ -391,8 +455,8 @@ report_leaked_ref (gpointer key, gpointer val, gpointer user_data)
       role = NULL;
     }
 
-  fprintf (stderr, "leaked %d references to object %s, role %s\n",
-          a->ref_count, name ? name : "<?>", role ? role : "<?>");
+  fprintf (stderr, "leaked %d references to object %s, role %s %p\n",
+          a->ref_count, name ? name : "<?>", role ? role : "<?>", a);
 
   SPI_freeString (name);
 }
@@ -463,3 +527,76 @@ SPI_freeString (char *s)
       CORBA_free (s);
     }
 }
+
+/**
+ * DOCUMENT_ME!
+ **/
+char *
+SPI_dupString (char *s)
+{
+  if (s)
+    {
+      return CORBA_string_dup (s);
+    }
+  else 
+    return NULL;
+}
+
+/**
+ * DOCUMENT_ME!
+ **/
+SPIBoolean SPI_exceptionHandlerPush (SPIExceptionHandler *handler)
+{
+  if (!exception_handlers)
+    exception_handlers = g_queue_new ();
+  g_queue_push_head (exception_handlers, handler);
+  return TRUE;
+}
+
+/**
+ * DOCUMENT_ME!
+ **/
+SPIExceptionHandler* SPI_exceptionHandlerPop (void)
+{
+  return (SPIExceptionHandler *) g_queue_pop_head (exception_handlers);
+}
+
+/**
+ * DOCUMENT_ME!
+ **/
+SPIExceptionType SPIException_getSourceType (SPIException *err)
+{
+  if (err)
+    return err->type;
+  else
+    return SPI_EXCEPTION_SOURCE_UNSPECIFIED;
+}
+
+/**
+ * DOCUMENT_ME!
+ **/
+SPIExceptionCode SPIException_getExceptionCode (SPIException *err)
+{  
+  return err->code;
+}
+
+/**
+ * DOCUMENT_ME!
+ **/
+Accessible* SPIAccessibleException_getSource (SPIException *err)
+{
+  if (err->type == SPI_EXCEPTION_SOURCE_ACCESSIBLE)
+    return cspi_object_get_ref (err->source, FALSE);
+  return NULL;
+}
+
+/**
+ * DOCUMENT_ME!
+ **/
+char* SPIException_getDescription (SPIException *err)
+{
+  /* TODO: friendlier error messages? */
+  if (err->ev)
+    return CORBA_exception_id (err->ev);
+  return NULL;
+}