Fix GetBoundedRanges
[platform/core/uifw/at-spi2-atk.git] / atk-adaptor / adaptors / text-adaptor.c
index 7a810b2..80bb921 100644 (file)
@@ -27,7 +27,7 @@
 #include <atk/atk.h>
 #include <droute/droute.h>
 
-#include "common/spi-dbus.h"
+#include "spi-dbus.h"
 #include "object.h"
 #include "introspection.h"
 
@@ -67,14 +67,12 @@ impl_GetText (DBusConnection * bus, DBusMessage * message, void *user_data)
   AtkText *text = (AtkText *) user_data;
   dbus_int32_t startOffset, endOffset;
   gchar *txt;
-  DBusError error;
   DBusMessage *reply;
 
   g_return_val_if_fail (ATK_IS_TEXT (user_data),
                         droute_not_yet_handled_error (message));
-  dbus_error_init (&error);
   if (!dbus_message_get_args
-      (message, &error, DBUS_TYPE_INT32, &startOffset, DBUS_TYPE_INT32,
+      (message, NULL, DBUS_TYPE_INT32, &startOffset, DBUS_TYPE_INT32,
        &endOffset, DBUS_TYPE_INVALID))
     {
       return droute_invalid_arguments_error (message);
@@ -98,14 +96,12 @@ impl_SetCaretOffset (DBusConnection * bus, DBusMessage * message,
   AtkText *text = (AtkText *) user_data;
   dbus_int32_t offset;
   dbus_bool_t rv;
-  DBusError error;
   DBusMessage *reply;
 
   g_return_val_if_fail (ATK_IS_TEXT (user_data),
                         droute_not_yet_handled_error (message));
-  dbus_error_init (&error);
   if (!dbus_message_get_args
-      (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_INVALID))
+      (message, NULL, DBUS_TYPE_INT32, &offset, DBUS_TYPE_INVALID))
     {
       return droute_invalid_arguments_error (message);
     }
@@ -129,14 +125,12 @@ impl_GetTextBeforeOffset (DBusConnection * bus, DBusMessage * message,
   gchar *txt;
   dbus_int32_t startOffset, endOffset;
   gint intstart_offset = 0, intend_offset = 0;
-  DBusError error;
   DBusMessage *reply;
 
   g_return_val_if_fail (ATK_IS_TEXT (user_data),
                         droute_not_yet_handled_error (message));
-  dbus_error_init (&error);
   if (!dbus_message_get_args
-      (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_UINT32, &type,
+      (message, NULL, DBUS_TYPE_INT32, &offset, DBUS_TYPE_UINT32, &type,
        DBUS_TYPE_INVALID))
     {
       return droute_invalid_arguments_error (message);
@@ -168,14 +162,12 @@ impl_GetTextAtOffset (DBusConnection * bus, DBusMessage * message,
   gchar *txt;
   dbus_int32_t startOffset, endOffset;
   gint intstart_offset = 0, intend_offset = 0;
-  DBusError error;
   DBusMessage *reply;
 
   g_return_val_if_fail (ATK_IS_TEXT (user_data),
                         droute_not_yet_handled_error (message));
-  dbus_error_init (&error);
   if (!dbus_message_get_args
-      (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_UINT32, &type,
+      (message, NULL, DBUS_TYPE_INT32, &offset, DBUS_TYPE_UINT32, &type,
        DBUS_TYPE_INVALID))
     {
       return droute_invalid_arguments_error (message);
@@ -208,14 +200,12 @@ impl_GetTextAfterOffset (DBusConnection * bus, DBusMessage * message,
   gchar *txt;
   dbus_int32_t startOffset, endOffset;
   gint intstart_offset = 0, intend_offset = 0;
-  DBusError error;
   DBusMessage *reply;
 
   g_return_val_if_fail (ATK_IS_TEXT (user_data),
                         droute_not_yet_handled_error (message));
-  dbus_error_init (&error);
   if (!dbus_message_get_args
-      (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_UINT32, &type,
+      (message, NULL, DBUS_TYPE_INT32, &offset, DBUS_TYPE_UINT32, &type,
        DBUS_TYPE_INVALID))
     {
       return droute_invalid_arguments_error (message);
@@ -245,14 +235,12 @@ impl_GetCharacterAtOffset (DBusConnection * bus, DBusMessage * message,
   AtkText *text = (AtkText *) user_data;
   dbus_int32_t offset;
   dbus_int32_t ch;
-  DBusError error;
   DBusMessage *reply;
 
   g_return_val_if_fail (ATK_IS_TEXT (user_data),
                         droute_not_yet_handled_error (message));
-  dbus_error_init (&error);
   if (!dbus_message_get_args
-      (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_INVALID))
+      (message, NULL, DBUS_TYPE_INT32, &offset, DBUS_TYPE_INVALID))
     {
       return droute_invalid_arguments_error (message);
     }
@@ -266,6 +254,100 @@ impl_GetCharacterAtOffset (DBusConnection * bus, DBusMessage * message,
   return reply;
 }
 
+static gchar *
+get_text_for_legacy_implementations(AtkText *text,
+                                    gint offset,
+                                    AtkTextGranularity granularity,
+                                    gint *start_offset,
+                                    gint *end_offset)
+{
+  gchar *txt = 0;
+  AtkTextBoundary boundary = 0;
+  switch (granularity) {
+  case ATK_TEXT_GRANULARITY_CHAR:
+    boundary = ATK_TEXT_BOUNDARY_CHAR;
+    break;
+
+  case ATK_TEXT_GRANULARITY_WORD:
+    boundary = ATK_TEXT_BOUNDARY_WORD_START;
+    break;
+
+  case ATK_TEXT_GRANULARITY_SENTENCE:
+    boundary = ATK_TEXT_BOUNDARY_SENTENCE_START;
+    break;
+
+  case ATK_TEXT_GRANULARITY_LINE:
+    boundary = ATK_TEXT_BOUNDARY_LINE_START;
+    break;
+
+  case ATK_TEXT_GRANULARITY_PARAGRAPH:
+    /* This is not implemented in previous versions of ATK */
+    txt = g_strdup("");
+    break;
+
+  default:
+    g_assert_not_reached();
+  }
+
+  if (!txt)
+    {
+      txt =
+        atk_text_get_text_at_offset (text, offset, boundary,
+                                     start_offset, end_offset);
+    }
+
+  return txt;
+}
+
+static DBusMessage *
+impl_GetStringAtOffset (DBusConnection * bus, DBusMessage * message,
+                        void *user_data)
+{
+  AtkText *text = (AtkText *) user_data;
+  dbus_int32_t offset;
+  dbus_uint32_t granularity;
+  gchar *txt = 0;
+  dbus_int32_t startOffset, endOffset;
+  gint intstart_offset = 0, intend_offset = 0;
+  DBusMessage *reply;
+
+  g_return_val_if_fail (ATK_IS_TEXT (user_data),
+                        droute_not_yet_handled_error (message));
+  if (!dbus_message_get_args
+      (message, NULL, DBUS_TYPE_INT32, &offset, DBUS_TYPE_UINT32, &granularity,
+       DBUS_TYPE_INVALID))
+    {
+      return droute_invalid_arguments_error (message);
+    }
+
+  txt =
+    atk_text_get_string_at_offset (text, offset, (AtkTextGranularity) granularity,
+                                   &intstart_offset, &intend_offset);
+
+  /* Accessibility layers implementing an older version of ATK (even if
+   * a new enough version of libatk is installed) might return NULL due
+   * not to provide an implementation for get_string_at_offset(), so we
+   * try with the legacy implementation if that's the case. */
+  if (!txt)
+    txt = get_text_for_legacy_implementations(text, offset,
+                                              (AtkTextGranularity) granularity,
+                                              &intstart_offset, &intend_offset);
+
+  startOffset = intstart_offset;
+  endOffset = intend_offset;
+  txt = validate_allocated_string (txt);
+  reply = dbus_message_new_method_return (message);
+  if (reply)
+    {
+      dbus_message_append_args (reply, DBUS_TYPE_STRING, &txt,
+                                DBUS_TYPE_INT32, &startOffset,
+                                DBUS_TYPE_INT32, &endOffset,
+                                DBUS_TYPE_INVALID);
+    }
+  g_free (txt);
+  return reply;
+}
+
 static DBusMessage *
 impl_GetAttributeValue (DBusConnection * bus, DBusMessage * message,
                         void *user_data)
@@ -277,7 +359,6 @@ impl_GetAttributeValue (DBusConnection * bus, DBusMessage * message,
   dbus_bool_t defined;
   gint intstart_offset = 0, intend_offset = 0;
   char *rv = NULL;
-  DBusError error;
   DBusMessage *reply;
   AtkAttributeSet *set;
   GSList *cur_attr;
@@ -285,9 +366,8 @@ impl_GetAttributeValue (DBusConnection * bus, DBusMessage * message,
 
   g_return_val_if_fail (ATK_IS_TEXT (user_data),
                         droute_not_yet_handled_error (message));
-  dbus_error_init (&error);
   if (!dbus_message_get_args
-      (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_STRING,
+      (message, NULL, DBUS_TYPE_INT32, &offset, DBUS_TYPE_STRING,
        &attributeName, DBUS_TYPE_INVALID))
     {
       return droute_invalid_arguments_error (message);
@@ -324,31 +404,6 @@ impl_GetAttributeValue (DBusConnection * bus, DBusMessage * message,
   return reply;
 }
 
-static char *
-_string_from_attribute_set (AtkAttributeSet * set)
-{
-  gchar *attributes, *tmp, *tmp2;
-  GSList *cur_attr;
-  AtkAttribute *at;
-
-  attributes = g_strdup ("");
-  cur_attr = (GSList *) set;
-  while (cur_attr)
-    {
-      at = (AtkAttribute *) cur_attr->data;
-      tmp = g_strdup_printf ("%s%s:%s%s",
-                             ((GSList *) (set) == cur_attr) ? "" : " ",
-                             at->name, at->value,
-                             (cur_attr->next) ? ";" : "");
-      tmp2 = g_strconcat (attributes, tmp, NULL);
-      g_free (tmp);
-      g_free (attributes);
-      attributes = tmp2;
-      cur_attr = cur_attr->next;
-    }
-  return attributes;
-}
-
 static DBusMessage *
 impl_GetAttributes (DBusConnection * bus, DBusMessage * message,
                     void *user_data)
@@ -357,16 +412,14 @@ impl_GetAttributes (DBusConnection * bus, DBusMessage * message,
   dbus_int32_t offset;
   dbus_int32_t startOffset, endOffset;
   gint intstart_offset, intend_offset;
-  DBusError error;
   DBusMessage *reply;
   AtkAttributeSet *set;
   DBusMessageIter iter;
 
   g_return_val_if_fail (ATK_IS_TEXT (user_data),
                         droute_not_yet_handled_error (message));
-  dbus_error_init (&error);
   if (!dbus_message_get_args
-      (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_INVALID))
+      (message, NULL, DBUS_TYPE_INT32, &offset, DBUS_TYPE_INVALID))
     {
       return droute_invalid_arguments_error (message);
     }
@@ -394,14 +447,12 @@ impl_GetDefaultAttributes (DBusConnection * bus, DBusMessage * message,
                            void *user_data)
 {
   AtkText *text = (AtkText *) user_data;
-  DBusError error;
   DBusMessage *reply;
   AtkAttributeSet *set;
   DBusMessageIter iter;
 
   g_return_val_if_fail (ATK_IS_TEXT (user_data),
                         droute_not_yet_handled_error (message));
-  dbus_error_init (&error);
 
   set = atk_text_get_default_attributes (text);
   reply = dbus_message_new_method_return (message);
@@ -423,14 +474,12 @@ impl_GetCharacterExtents (DBusConnection * bus, DBusMessage * message,
   dbus_uint32_t coordType;
   dbus_int32_t x, y, width, height;
   gint ix = 0, iy = 0, iw = 0, ih = 0;
-  DBusError error;
   DBusMessage *reply;
 
   g_return_val_if_fail (ATK_IS_TEXT (user_data),
                         droute_not_yet_handled_error (message));
-  dbus_error_init (&error);
   if (!dbus_message_get_args
-      (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_UINT32,
+      (message, NULL, DBUS_TYPE_INT32, &offset, DBUS_TYPE_UINT32,
        &coordType, DBUS_TYPE_INVALID))
     {
       return droute_invalid_arguments_error (message);
@@ -459,14 +508,12 @@ impl_GetOffsetAtPoint (DBusConnection * bus, DBusMessage * message,
   dbus_int32_t x, y;
   dbus_uint32_t coordType;
   dbus_int32_t rv;
-  DBusError error;
   DBusMessage *reply;
 
   g_return_val_if_fail (ATK_IS_TEXT (user_data),
                         droute_not_yet_handled_error (message));
-  dbus_error_init (&error);
   if (!dbus_message_get_args
-      (message, &error, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y,
+      (message, NULL, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y,
        DBUS_TYPE_UINT32, &coordType, DBUS_TYPE_INVALID))
     {
       return droute_invalid_arguments_error (message);
@@ -509,14 +556,12 @@ impl_GetSelection (DBusConnection * bus, DBusMessage * message,
   dbus_int32_t selectionNum;
   dbus_int32_t startOffset, endOffset;
   gint intstart_offset = 0, intend_offset = 0;
-  DBusError error;
   DBusMessage *reply;
 
   g_return_val_if_fail (ATK_IS_TEXT (user_data),
                         droute_not_yet_handled_error (message));
-  dbus_error_init (&error);
   if (!dbus_message_get_args
-      (message, &error, DBUS_TYPE_INT32, &selectionNum, DBUS_TYPE_INVALID))
+      (message, NULL, DBUS_TYPE_INT32, &selectionNum, DBUS_TYPE_INVALID))
     {
       return droute_invalid_arguments_error (message);
     }
@@ -542,14 +587,12 @@ impl_AddSelection (DBusConnection * bus, DBusMessage * message,
   AtkText *text = (AtkText *) user_data;
   dbus_int32_t startOffset, endOffset;
   dbus_bool_t rv;
-  DBusError error;
   DBusMessage *reply;
 
   g_return_val_if_fail (ATK_IS_TEXT (user_data),
                         droute_not_yet_handled_error (message));
-  dbus_error_init (&error);
   if (!dbus_message_get_args
-      (message, &error, DBUS_TYPE_INT32, &startOffset, DBUS_TYPE_INT32,
+      (message, NULL, DBUS_TYPE_INT32, &startOffset, DBUS_TYPE_INT32,
        &endOffset, DBUS_TYPE_INVALID))
     {
       return droute_invalid_arguments_error (message);
@@ -571,14 +614,12 @@ impl_RemoveSelection (DBusConnection * bus, DBusMessage * message,
   AtkText *text = (AtkText *) user_data;
   dbus_int32_t selectionNum;
   dbus_bool_t rv;
-  DBusError error;
   DBusMessage *reply;
 
   g_return_val_if_fail (ATK_IS_TEXT (user_data),
                         droute_not_yet_handled_error (message));
-  dbus_error_init (&error);
   if (!dbus_message_get_args
-      (message, &error, DBUS_TYPE_INT32, &selectionNum, DBUS_TYPE_INVALID))
+      (message, NULL, DBUS_TYPE_INT32, &selectionNum, DBUS_TYPE_INVALID))
     {
       return droute_invalid_arguments_error (message);
     }
@@ -599,14 +640,12 @@ impl_SetSelection (DBusConnection * bus, DBusMessage * message,
   AtkText *text = (AtkText *) user_data;
   dbus_int32_t selectionNum, startOffset, endOffset;
   dbus_bool_t rv;
-  DBusError error;
   DBusMessage *reply;
 
   g_return_val_if_fail (ATK_IS_TEXT (user_data),
                         droute_not_yet_handled_error (message));
-  dbus_error_init (&error);
   if (!dbus_message_get_args
-      (message, &error, DBUS_TYPE_INT32, &selectionNum, DBUS_TYPE_INT32,
+      (message, NULL, DBUS_TYPE_INT32, &selectionNum, DBUS_TYPE_INT32,
        &startOffset, DBUS_TYPE_INT32, &endOffset, DBUS_TYPE_INVALID))
     {
       return droute_invalid_arguments_error (message);
@@ -630,14 +669,12 @@ impl_GetRangeExtents (DBusConnection * bus, DBusMessage * message,
   dbus_uint32_t coordType;
   AtkTextRectangle rect;
   dbus_int32_t x, y, width, height;
-  DBusError error;
   DBusMessage *reply;
 
   g_return_val_if_fail (ATK_IS_TEXT (user_data),
                         droute_not_yet_handled_error (message));
-  dbus_error_init (&error);
   if (!dbus_message_get_args
-      (message, &error, DBUS_TYPE_INT32, &startOffset, DBUS_TYPE_INT32,
+      (message, NULL, DBUS_TYPE_INT32, &startOffset, DBUS_TYPE_INT32,
        &endOffset, DBUS_TYPE_UINT32, &coordType, DBUS_TYPE_INVALID))
     {
       return droute_invalid_arguments_error (message);
@@ -668,7 +705,6 @@ impl_GetBoundedRanges (DBusConnection * bus, DBusMessage * message,
   AtkText *text = (AtkText *) user_data;
   dbus_int32_t x, y, width, height;
   dbus_uint32_t coordType, xClipType, yClipType;
-  DBusError error;
   AtkTextRange **range_list = NULL;
   AtkTextRectangle rect;
   DBusMessage *reply;
@@ -676,9 +712,8 @@ impl_GetBoundedRanges (DBusConnection * bus, DBusMessage * message,
 
   g_return_val_if_fail (ATK_IS_TEXT (user_data),
                         droute_not_yet_handled_error (message));
-  dbus_error_init (&error);
   if (!dbus_message_get_args
-      (message, &error, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y,
+      (message, NULL, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y,
        DBUS_TYPE_INT32, &height, DBUS_TYPE_INT32, &width, DBUS_TYPE_UINT32,
        &coordType, DBUS_TYPE_UINT32, &xClipType, DBUS_TYPE_UINT32, &yClipType,
        DBUS_TYPE_INVALID))
@@ -703,7 +738,8 @@ impl_GetBoundedRanges (DBusConnection * bus, DBusMessage * message,
       (&iter, DBUS_TYPE_ARRAY, "(iisv)", &array))
     {
       int len;
-      for (len = 0; len < MAXRANGELEN && range_list[len]; ++len)
+      int count = (range_list ? MAXRANGELEN : 0);
+      for (len = 0; len < count && range_list[len]; ++len)
         {
           if (dbus_message_iter_open_container
               (&array, DBUS_TYPE_STRUCT, NULL, &struc))
@@ -727,10 +763,16 @@ impl_GetBoundedRanges (DBusConnection * bus, DBusMessage * message,
                   dbus_message_iter_close_container (&struc, &variant);
                 }
               dbus_message_iter_close_container (&array, &struc);
+              g_free (range_list[len]->content);
+              g_free (range_list[len]);
             }
         }
       dbus_message_iter_close_container (&iter, &array);
     }
+
+  if (range_list)
+    g_free (range_list);
+
   return reply;
 }
 
@@ -738,7 +780,6 @@ static DBusMessage *
 impl_GetAttributeRun (DBusConnection * bus, DBusMessage * message,
                       void *user_data)
 {
-  DBusError error;
   AtkText *text = (AtkText *) user_data;
   dbus_int32_t offset;
   dbus_bool_t includeDefaults;
@@ -746,14 +787,12 @@ impl_GetAttributeRun (DBusConnection * bus, DBusMessage * message,
   gint intstart_offset = 0, intend_offset = 0;
   DBusMessage *reply;
   AtkAttributeSet *attributes = NULL;
-  AtkAttribute *attr = NULL;
-  DBusMessageIter iter, iterArray;
+  DBusMessageIter iter;
 
   g_return_val_if_fail (ATK_IS_TEXT (user_data),
                         droute_not_yet_handled_error (message));
-  dbus_error_init (&error);
   if (!dbus_message_get_args
-      (message, &error, DBUS_TYPE_INT32, &offset, DBUS_TYPE_BOOLEAN,
+      (message, NULL, DBUS_TYPE_INT32, &offset, DBUS_TYPE_BOOLEAN,
        &includeDefaults, DBUS_TYPE_INVALID))
     {
       return droute_invalid_arguments_error (message);
@@ -819,6 +858,7 @@ static DRouteMethod methods[] = {
   {impl_GetTextBeforeOffset, "GetTextBeforeOffset"},
   {impl_GetTextAtOffset, "GetTextAtOffset"},
   {impl_GetTextAfterOffset, "GetTextAfterOffset"},
+  {impl_GetStringAtOffset, "GetStringAtOffset"},
   {impl_GetCharacterAtOffset, "GetCharacterAtOffset"},
   {impl_GetAttributeValue, "GetAttributeValue"},
   {impl_GetAttributes, "GetAttributes"},
@@ -847,5 +887,5 @@ void
 spi_initialize_text (DRoutePath * path)
 {
   droute_path_add_interface (path,
-                             SPI_DBUS_INTERFACE_TEXT, spi_org_a11y_atspi_Text, methods, properties);
+                             ATSPI_DBUS_INTERFACE_TEXT, spi_org_a11y_atspi_Text, methods, properties);
 };