<commit_before>/*
 * AT-SPI - Assistive Technology Service Provider Interface
 * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
 *
 * Copyright 2008 Novell, Inc.
 * Copyright 2001, 2002 Sun Microsystems Inc.,
 * Copyright 2001, 2002 Ximian, Inc.
 * Copyright 2008, 2009 Codethink Ltd.
 *
 * 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 <atk/atk.h>
#include <droute/droute.h>

#include "spi-dbus.h"
#include "accessible-stateset.h"
#include "accessible-cache.h"
#include "bridge.h"
#include "object.h"
#include "introspection.h"

/* TODO - This should possibly be a common define */
#define SPI_OBJECT_PREFIX "/org/a11y/atspi"
#define SPI_CACHE_OBJECT_SUFFIX "/cache"
#define SPI_CACHE_OBJECT_PATH SPI_OBJECT_PREFIX SPI_CACHE_OBJECT_SUFFIX

#define SPI_OBJECT_REFERENCE_SIGNATURE "(" \
                                          DBUS_TYPE_STRING_AS_STRING \
                                          DBUS_TYPE_OBJECT_PATH_AS_STRING \
                                       ")"
                                          
#define SPI_CACHE_ITEM_SIGNATURE "(" \
                                   SPI_OBJECT_REFERENCE_SIGNATURE \
                                   SPI_OBJECT_REFERENCE_SIGNATURE \
                                   SPI_OBJECT_REFERENCE_SIGNATURE \
                                   DBUS_TYPE_INT32_AS_STRING \
                                   DBUS_TYPE_INT32_AS_STRING \
                                   DBUS_TYPE_ARRAY_AS_STRING \
                                     DBUS_TYPE_STRING_AS_STRING \
                                   DBUS_TYPE_STRING_AS_STRING \
                                   DBUS_TYPE_UINT32_AS_STRING \
                                   DBUS_TYPE_STRING_AS_STRING \
                                   DBUS_TYPE_ARRAY_AS_STRING \
                                     DBUS_TYPE_UINT32_AS_STRING \
                                 ")"

/*---------------------------------------------------------------------------*/

/*
 * Marshals the given AtkObject into the provided D-Bus iterator.
 *
 * The object is marshalled including all its client side cache data.
 * The format of the structure is (o(so)iiassusau).
 */
static void
append_cache_item (AtkObject * obj, gpointer data)
{
  DBusMessageIter iter_struct, iter_sub_array;
  dbus_uint32_t states[2];
  dbus_int32_t count, index;
  AtkStateSet *set;
  DBusMessageIter *iter_array = (DBusMessageIter *) data;
  const char *name, *desc;
  dbus_uint32_t role;

  set = atk_object_ref_state_set (obj);
    AtkObject *application, *parent;

  dbus_message_iter_open_container (iter_array, DBUS_TYPE_STRUCT, NULL,
                                    &iter_struct);

  /* Marshal object path */
  spi_object_append_reference (&iter_struct, obj);

  role = spi_accessible_role_from_atk_role (atk_object_get_role (obj));

  /* Marshal application */
  application = spi_global_app_data->root;
  spi_object_append_reference (&iter_struct, application);

  /* Marshal parent */
  parent = atk_object_get_parent (obj);
  if (parent == NULL)
    {
      /* TODO, move in to a 'Plug' wrapper. */
      if (ATK_IS_PLUG (obj))
        {
          char *id = g_object_get_data (G_OBJECT (obj), "dbus-plug-parent");
          char *bus_parent;
          char *path_parent;

          if (id)
            {
              bus_parent = g_strdup (id);
              if (bus_parent && (path_parent = g_utf8_strchr (bus_parent + 1, -1, ':')))
                {
                  DBusMessageIter iter_parent;
                  *(path_parent++) = '\0';
                  dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_STRUCT, NULL,
                                                    &iter_parent);
                  dbus_message_iter_append_basic (&iter_parent, DBUS_TYPE_STRING, &bus_parent);
                  dbus_message_iter_append_basic (&iter_parent, DBUS_TYPE_OBJECT_PATH, &path_parent);
                  dbus_message_iter_close_container (&iter_struct, &iter_parent);
                }
              else
                {
                  spi_object_append_null_reference (&iter_struct);
                }
            }
          else
            {
              spi_object_append_null_reference (&iter_struct);
            }
        }
      else if (role != ATSPI_ROLE_APPLICATION)
        spi_object_append_null_reference (&iter_struct);
      else
        spi_object_append_desktop_reference (&iter_struct);
    }
  else
    {
      spi_object_append_reference (&iter_struct, parent);
    }

  /* Marshal index in parent */
  index = (atk_state_set_contains_state (set, ATK_STATE_TRANSIENT)
           ? -1 : atk_object_get_index_in_parent (obj));
  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &index);

  /* marshal child count */
  count = (atk_state_set_contains_state (set, ATK_STATE_MANAGES_DESCENDANTS) ||
           atk_state_set_contains_state (set, ATK_STATE_DEFUNCT))
           ? -1 : atk_object_get_n_accessible_children (obj);
  if (ATK_IS_SOCKET (obj) && atk_socket_is_occupied (ATK_SOCKET (obj)))
    count = 1;
  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &count);

  /* Marshal interfaces */
  dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "s",
                                    &iter_sub_array);
  spi_object_append_interfaces (&iter_sub_array, obj);
  dbus_message_iter_close_container (&iter_struct, &iter_sub_array);

  /* Marshal name */
  name = atk_object_get_name (obj);
  if (!name)
    name = "";
  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name);

  /* Marshal role */
  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &role);
<commit_msg>Don't send children of gtk menus to be cached<commit_after>/*
 * AT-SPI - Assistive Technology Service Provider Interface
 * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
 *
 * Copyright 2008 Novell, Inc.
 * Copyright 2001, 2002 Sun Microsystems Inc.,
 * Copyright 2001, 2002 Ximian, Inc.
 * Copyright 2008, 2009 Codethink Ltd.
 *
 * 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 <atk/atk.h>
#include <droute/droute.h>

#include "spi-dbus.h"
#include "accessible-stateset.h"
#include "accessible-cache.h"
#include "bridge.h"
#include "object.h"
#include "introspection.h"

/* TODO - This should possibly be a common define */
#define SPI_OBJECT_PREFIX "/org/a11y/atspi"
#define SPI_CACHE_OBJECT_SUFFIX "/cache"
#define SPI_CACHE_OBJECT_PATH SPI_OBJECT_PREFIX SPI_CACHE_OBJECT_SUFFIX

#define SPI_OBJECT_REFERENCE_SIGNATURE "(" \
                                          DBUS_TYPE_STRING_AS_STRING \
                                          DBUS_TYPE_OBJECT_PATH_AS_STRING \
                                       ")"
                                          
#define SPI_CACHE_ITEM_SIGNATURE "(" \
                                   SPI_OBJECT_REFERENCE_SIGNATURE \
                                   SPI_OBJECT_REFERENCE_SIGNATURE \
                                   SPI_OBJECT_REFERENCE_SIGNATURE \
                                   DBUS_TYPE_INT32_AS_STRING \
                                   DBUS_TYPE_INT32_AS_STRING \
                                   DBUS_TYPE_ARRAY_AS_STRING \
                                     DBUS_TYPE_STRING_AS_STRING \
                                   DBUS_TYPE_STRING_AS_STRING \
                                   DBUS_TYPE_UINT32_AS_STRING \
                                   DBUS_TYPE_STRING_AS_STRING \
                                   DBUS_TYPE_ARRAY_AS_STRING \
                                     DBUS_TYPE_UINT32_AS_STRING \
                                 ")"

/*---------------------------------------------------------------------------*/

static const char *
get_toolkit_name (AtkObject *obj)
{
  static const char *toolkit_name = NULL;

  if (!toolkit_name)
    toolkit_name = atk_get_toolkit_name ();

  /* TODO: query object attributes */
  return toolkit_name;
}

static gboolean
should_call_index_in_parent (AtkObject *obj, AtkStateSet *set)
{
  if (atk_state_set_contains_state (set, ATK_STATE_TRANSIENT))
    return FALSE;

  if (!strcmp (get_toolkit_name (obj), "gtk") &&
      atk_object_get_role (obj) == ATK_ROLE_MENU_ITEM)
    return FALSE;

  return TRUE;
}

static gboolean
should_cache_children (AtkObject *obj, AtkStateSet *set)
{
  if (atk_state_set_contains_state (set, ATK_STATE_MANAGES_DESCENDANTS) ||
      atk_state_set_contains_state (set, ATK_STATE_DEFUNCT))
    return FALSE;

  if (!strcmp (get_toolkit_name (obj), "gtk") &&
      atk_object_get_role (obj) == ATK_ROLE_MENU)
    return FALSE;

  return TRUE;
}

/*
 * Marshals the given AtkObject into the provided D-Bus iterator.
 *
 * The object is marshalled including all its client side cache data.
 * The format of the structure is (o(so)iiassusau).
 */
static void
append_cache_item (AtkObject * obj, gpointer data)
{
  DBusMessageIter iter_struct, iter_sub_array;
  dbus_uint32_t states[2];
  dbus_int32_t count, index;
  AtkStateSet *set;
  DBusMessageIter *iter_array = (DBusMessageIter *) data;
  const char *name, *desc;
  dbus_uint32_t role;

  set = atk_object_ref_state_set (obj);
    AtkObject *application, *parent;

  dbus_message_iter_open_container (iter_array, DBUS_TYPE_STRUCT, NULL,
                                    &iter_struct);

  /* Marshal object path */
  spi_object_append_reference (&iter_struct, obj);

  role = spi_accessible_role_from_atk_role (atk_object_get_role (obj));

  /* Marshal application */
  application = spi_global_app_data->root;
  spi_object_append_reference (&iter_struct, application);

  /* Marshal parent */
  parent = atk_object_get_parent (obj);
  if (parent == NULL)
    {
      /* TODO, move in to a 'Plug' wrapper. */
      if (ATK_IS_PLUG (obj))
        {
          char *id = g_object_get_data (G_OBJECT (obj), "dbus-plug-parent");
          char *bus_parent;
          char *path_parent;

          if (id)
            {
              bus_parent = g_strdup (id);
              if (bus_parent && (path_parent = g_utf8_strchr (bus_parent + 1, -1, ':')))
                {
                  DBusMessageIter iter_parent;
                  *(path_parent++) = '\0';
                  dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_STRUCT, NULL,
                                                    &iter_parent);
                  dbus_message_iter_append_basic (&iter_parent, DBUS_TYPE_STRING, &bus_parent);
                  dbus_message_iter_append_basic (&iter_parent, DBUS_TYPE_OBJECT_PATH, &path_parent);
                  dbus_message_iter_close_container (&iter_struct, &iter_parent);
                }
              else
                {
                  spi_object_append_null_reference (&iter_struct);
                }
            }
          else
            {
              spi_object_append_null_reference (&iter_struct);
            }
        }
      else if (role != ATSPI_ROLE_APPLICATION)
        spi_object_append_null_reference (&iter_struct);
      else
        spi_object_append_desktop_reference (&iter_struct);
    }
  else
    {
      spi_object_append_reference (&iter_struct, parent);
    }

  /* Marshal index in parent */
  index = (should_call_index_in_parent (obj, set)
           ? atk_object_get_index_in_parent (obj) : -1);
  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &index);

  /* marshal child count */
  count = (should_cache_children (obj, set)
           ? atk_object_get_n_accessible_children (obj) : -1);

  if (ATK_IS_SOCKET (obj) && atk_socket_is_occupied (ATK_SOCKET (obj)))
    count = 1;
  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &count);

  /* Marshal interfaces */
  dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "s",
                                    &iter_sub_array);
  spi_object_append_interfaces (&iter_sub_array, obj);
  dbus_message_iter_close_container (&iter_struct, &iter_sub_array);

  /* Marshal name */
  name = atk_object_get_name (obj);
  if (!name)
    name = "";
  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name);

  /* Marshal role */
  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &role);

{'fraction_non_alphanumeric': 0.09188911704312115, 'fraction_numerical': 0.01070695218539161, 'mean_word_length': 2.2034296452901105, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 46, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5269036', 'n_tokens_mistral': 4250, 'n_tokens_neox': 4014, 'n_words': 945}