/* * AT-SPI - Assistive Technology Service Provider Interface * (Gnome Accessibility Project; https://wiki.gnome.org/Accessibility) * * Copyright (c) 2014 Samsung Electronics Co., Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include "my-atk.h" #define ACCESSIBLE_NODE ((const xmlChar *) "accessible") #define ACC_ACTION_NODE ((const xmlChar *) "accessible_action") #define ACC_COMPONENT_NODE ((const xmlChar *) "accessible_component") #define ACC_DOCUMENT_NODE ((const xmlChar *) "accessible_document") #define ACC_HYPERLINK_NODE ((const xmlChar *) "accessible_hyperlink") #define ACC_HYPERTEXT_NODE ((const xmlChar *) "accessible_hypertext") #define ACC_IMAGE_NODE ((const xmlChar *) "accessible_image") #define ACC_TABLE_NODE ((const xmlChar *) "accessible_table") #define ACC_TABLE_CELL_NODE ((const xmlChar *) "accessible_table_cell") #define ACC_EDIT_TEXT_NODE ((const xmlChar *) "accessible_editable_text") #define ACC_TEXT_NODE ((const xmlChar *) "accessible_text") #define ACC_SELECTION_NODE ((const xmlChar *) "accessible_selection") #define ACC_VALUE_NODE ((const xmlChar *) "accessible_value") #define ACTION_NODE ((const xmlChar *) "action") #define DOCUMENT_NODE ((const xmlChar *) "document") #define INTERFACE_NODE ((const xmlChar *) "interface") #define RELATION_NODE ((const xmlChar *) "relation") #define STATE_NODE ((const xmlChar *) "state") #define COMPONENT_NODE ((const xmlChar *) "component") #define HYPERLINK_NODE ((const xmlChar *) "hyperlink") #define HYPERTEXT_NODE ((const xmlChar *) "hypertext") #define IMAGE_NODE ((const xmlChar *) "image") #define TABLE_NODE ((const xmlChar *) "table") #define TABLE_CELL_NODE ((const xmlChar *) "table_cell") #define TEXT_NODE ((const xmlChar *) "text_node") #define VALUE_NODE ((const xmlChar *) "value_node") #define SELECT_NODE ((const xmlChar *) "select_node") #define NAME_ATTR ((const xmlChar *) "name") #define DESC_ATTR ((const xmlChar *) "description") #define ROLE_ATTR ((const xmlChar *) "role") #define MIN_ATTR ((const xmlChar *) "min") #define MAX_ATTR ((const xmlChar *) "max") #define CURRENT_ATTR ((const xmlChar *) "current") #define STEP_ATTR ((const xmlChar *) "step") #define COL_HEADER_ATTR ((const xmlChar *) "col_header") #define ROW_HEADER_ATTR ((const xmlChar *) "row_header") #define COL_DESC_ATTR ((const xmlChar *) "col_desc") #define ROW_DESC_ATTR ((const xmlChar *) "row_desc") #define SELECTED_ATTR ((const xmlChar *) "selected") #define SELECTED_COL_ATTR ((const xmlChar *) "selected_col") #define RELATION_TYPE_ATTR ((const xmlChar *) "relation_type") #define RELATION_TARGET_NAME_ATTR ((const xmlChar *) "target_name") #define STATE_TYPE_ATTR ((const xmlChar *) "state_enum") #define ACTION_NAME_ATTR ((const xmlChar *) "action_name") #define ACTION_DES_ATTR ((const xmlChar *) "action_description") #define ACTION_KEY_BIND_ATTR ((const xmlChar *) "key_binding") #define COMP_X_ATTR ((const xmlChar *) "x") #define COMP_Y_ATTR ((const xmlChar *) "y") #define COMP_WIDTH_ATTR ((const xmlChar *) "width") #define COMP_HEIGHT_ATTR ((const xmlChar *) "height") #define COMP_LAYER_ATTR ((const xmlChar *) "layer") #define COMP_ZORDER_ATTR ((const xmlChar *) "zorder") #define COMP_ALPHA_ATTR ((const xmlChar *) "alpha") #define IMAGE_DES_ATTR ((const xmlChar *) "image_description") #define IMAGE_LOCALE_ATTR ((const xmlChar *) "image_locale") #define TEXT_TEXT_ATTR ((const xmlChar *) "text") #define TEXT_BOLD_ATTR ((const xmlChar *) "bold_text") #define TEXT_UNDERLINE_ATTR ((const xmlChar *) "underline_text") #define TEXT_DUMMY_ATTR ((const xmlChar *) "dummy_text") #define START_ATTR ((const xmlChar *) "start") #define END_ATTR ((const xmlChar *) "end") #define LINK_ATTR ((const xmlChar *) "link") #define CELL_X_ATTR ((const xmlChar *) "cell_x") #define CELL_Y_ATTR ((const xmlChar *) "cell_y") #define ROW_SPAN_ATTR ((const xmlChar *) "row_span") #define COLUMN_SPAN_ATTR ((const xmlChar *) "column_span") #define SELECT_ATTR ((const xmlChar *) "selected") #define PAGE_ATTR ((const xmlChar *) "page_no") #define PAGE_NUM_ATTR ((const xmlChar *) "page_number") MyAtkObject *relation_target = NULL; static double atof_get_prop (xmlNode *node, const xmlChar *attr) { double ret; xmlChar *str = xmlGetProp (node, attr); if (!str) return 0; ret = atof ((const char *)str); xmlFree(str); return ret; } static int atoi_get_prop (xmlNode *node, const xmlChar *attr) { int ret; xmlChar *str = xmlGetProp (node, attr); if (!str) return 0; ret = atoi ((const char *)str); xmlFree(str); return ret; } static AtkAttribute * get_atk_attribute (xmlNode *node, const xmlChar *attr) { xmlChar *str; AtkAttribute *tmp = g_malloc (sizeof (AtkAttribute)); if (!tmp) return NULL; str = xmlGetProp (node, attr); tmp->name = g_strdup ((const char *)attr); tmp->value = g_strdup ((const char *)str); free (str); return tmp; } static gpointer create_atk_object_from_element (xmlNode *element) { xmlNode *child_node; xmlNode *child_node2; gpointer obj; gpointer child_obj = NULL; AtkRelationSet *relation_set = NULL; AtkObject *array[1]; AtkRelation *relation; AtkStateSet *state_set = NULL; AtkStateType state_type; xmlChar *name; xmlChar *description; xmlChar *state_enum; xmlChar *role; gint relation_type; xmlChar *relation_target_name; xmlChar *action_name; xmlChar *action_des; xmlChar *action_key_bind; xmlChar *image_des; xmlChar *image_locale; xmlChar *text; gint x_size, y_size; gint width, height; gint x_extent, y_extent, w_extent, h_extent; name = xmlGetProp (element, NAME_ATTR); description = xmlGetProp (element, DESC_ATTR); role = xmlGetProp (element, ROLE_ATTR); GType type = MY_TYPE_ATK_OBJECT; gint layer; gint zorder; gdouble alpha; if (!xmlStrcmp (element->name, ACCESSIBLE_NODE)) type = MY_TYPE_ATK_OBJECT; if (!xmlStrcmp (element->name, ACC_ACTION_NODE)) type = MY_TYPE_ATK_ACTION; if (!xmlStrcmp (element->name, ACC_COMPONENT_NODE)) type = MY_TYPE_ATK_COMPONENT; if (!xmlStrcmp (element->name, ACC_DOCUMENT_NODE)) type = MY_TYPE_ATK_DOCUMENT; if (!xmlStrcmp (element->name, ACC_EDIT_TEXT_NODE)) type = MY_TYPE_ATK_EDITABLE_TEXT; if (!xmlStrcmp (element->name, ACC_HYPERLINK_NODE)) type = MY_TYPE_ATK_HYPERTEXT; if (!xmlStrcmp (element->name, ACC_HYPERTEXT_NODE)) type = MY_TYPE_ATK_HYPERTEXT; if (!xmlStrcmp (element->name, ACC_IMAGE_NODE)) type = MY_TYPE_ATK_IMAGE; if (!xmlStrcmp (element->name, ACC_SELECTION_NODE)) type = MY_TYPE_ATK_SELECTION; if (!xmlStrcmp (element->name, ACC_TEXT_NODE)) type = MY_TYPE_ATK_TEXT; if (!xmlStrcmp (element->name, ACC_TABLE_NODE)) type = MY_TYPE_ATK_TABLE; if (!xmlStrcmp (element->name, ACC_TABLE_CELL_NODE)) type = MY_TYPE_ATK_TABLE_CELL; if (!xmlStrcmp (element->name, ACC_VALUE_NODE)) type = MY_TYPE_ATK_VALUE; obj = g_object_new (type, "accessible-name", name, "accessible-description", description, "accessible-role", atk_role_for_name ((const gchar *)role), NULL); child_node = element->xmlChildrenNode; while (child_node != NULL) { if (!xmlStrcmp (child_node->name, ACCESSIBLE_NODE) || !xmlStrcmp (child_node->name, ACC_ACTION_NODE) || !xmlStrcmp (child_node->name, ACC_COMPONENT_NODE) || !xmlStrcmp (child_node->name, ACC_DOCUMENT_NODE) || !xmlStrcmp (child_node->name, ACC_EDIT_TEXT_NODE) || !xmlStrcmp (child_node->name, ACC_HYPERLINK_NODE) || !xmlStrcmp (child_node->name, ACC_HYPERTEXT_NODE) || !xmlStrcmp (child_node->name, ACC_IMAGE_NODE) || !xmlStrcmp (child_node->name, ACC_SELECTION_NODE) || !xmlStrcmp (child_node->name, ACC_TABLE_NODE) || !xmlStrcmp (child_node->name, ACC_TABLE_CELL_NODE) || !xmlStrcmp (child_node->name, ACC_TEXT_NODE) || !xmlStrcmp (child_node->name, ACC_VALUE_NODE)) { child_obj = create_atk_object_from_element (child_node); my_atk_object_add_child (obj, child_obj); } child_node2 = child_node->xmlChildrenNode; while (child_node2 != NULL) { if (!xmlStrcmp (child_node2->name, RELATION_NODE)) { relation_type = atoi_get_prop (child_node2, RELATION_TYPE_ATTR); relation_target_name = xmlGetProp (child_node2, RELATION_TARGET_NAME_ATTR); relation_set = atk_object_ref_relation_set (ATK_OBJECT (child_obj)); array[0] = ATK_OBJECT (obj); relation = atk_relation_new (array, 1, relation_type); atk_relation_new (array, 1, relation_type); atk_relation_set_add (relation_set, relation); g_object_unref (relation); g_object_unref (relation_set); xmlFree (relation_target_name); } if (!xmlStrcmp (child_node2->name, STATE_NODE)) { state_set = atk_object_ref_state_set (ATK_OBJECT (child_obj)); state_enum = xmlGetProp (child_node2, STATE_TYPE_ATTR); state_type = atk_state_type_for_name ((const gchar *)state_enum); atk_state_set_add_state (state_set, state_type); g_object_unref (state_set); xmlFree (state_enum); } if (!xmlStrcmp (child_node2->name, ACTION_NODE)) { action_name = xmlGetProp (child_node2, ACTION_NAME_ATTR); action_des = xmlGetProp (child_node2, ACTION_DES_ATTR); action_key_bind = xmlGetProp (child_node2, ACTION_KEY_BIND_ATTR); my_atk_action_add_action (child_obj, (const gchar *)action_name, (const gchar *)action_des, (const gchar *)action_key_bind); } if (!xmlStrcmp (child_node2->name, COMPONENT_NODE)) { x_extent = atoi_get_prop (child_node2, COMP_X_ATTR); y_extent = atoi_get_prop (child_node2, COMP_Y_ATTR); w_extent = atoi_get_prop (child_node2, COMP_WIDTH_ATTR); h_extent = atoi_get_prop (child_node2, COMP_HEIGHT_ATTR); layer = atoi_get_prop (child_node2, COMP_LAYER_ATTR); zorder = atoi_get_prop (child_node2, COMP_ZORDER_ATTR); alpha = atof_get_prop (child_node2, COMP_ALPHA_ATTR); atk_component_set_extents (ATK_COMPONENT (child_obj), x_extent, y_extent, w_extent, h_extent, ATK_XY_SCREEN); my_atk_component_set_layer (ATK_COMPONENT (child_obj), layer); my_atk_component_set_mdi_zorder (ATK_COMPONENT (child_obj), zorder); my_atk_component_set_alpha (ATK_COMPONENT (child_obj), alpha); } if (!xmlStrcmp (child_node2->name, DOCUMENT_NODE)) { my_atk_set_document (ATK_DOCUMENT(child_obj), atoi_get_prop (child_node2, PAGE_ATTR), atoi_get_prop (child_node2, PAGE_NUM_ATTR)); } if (!xmlStrcmp (child_node2->name, HYPERLINK_NODE)) { xmlChar *text = xmlGetProp (child_node2, TEXT_TEXT_ATTR); my_atk_set_hypertext (ATK_HYPERTEXT (child_obj), (const gchar *)text); xmlFree (text); } if (!xmlStrcmp (child_node2->name, HYPERTEXT_NODE)) { xmlChar *text = xmlGetProp (child_node2, TEXT_TEXT_ATTR); my_atk_set_hypertext (ATK_HYPERTEXT (child_obj), (const gchar *)text); xmlFree (text); } if (!xmlStrcmp (child_node2->name, IMAGE_NODE)) { image_des = xmlGetProp (child_node2, IMAGE_DES_ATTR); x_size = atoi_get_prop (child_node2, COMP_X_ATTR); y_size = atoi_get_prop (child_node2, COMP_Y_ATTR); width = atoi_get_prop (child_node2, COMP_WIDTH_ATTR); height = atoi_get_prop (child_node2, COMP_HEIGHT_ATTR); image_locale = xmlGetProp (child_node2, IMAGE_LOCALE_ATTR); my_atk_set_image (ATK_IMAGE (child_obj), (const gchar *)image_des, x_size, y_size, width, height, (const gchar *)image_locale); } if (!xmlStrcmp (child_node2->name, TEXT_NODE)) { text = xmlGetProp (child_node2, TEXT_TEXT_ATTR); AtkAttributeSet *attrSet = NULL; AtkAttribute *a1 = get_atk_attribute (child_node2, TEXT_BOLD_ATTR); AtkAttribute *a2 = get_atk_attribute (child_node2, TEXT_UNDERLINE_ATTR); AtkAttribute *a3 = get_atk_attribute (child_node2, TEXT_DUMMY_ATTR); attrSet = g_slist_append(NULL, a1); attrSet = g_slist_append(attrSet, a2); attrSet = g_slist_append(attrSet, a3); my_atk_set_text (ATK_TEXT (child_obj), (const gchar *)text, atoi_get_prop (child_node2, COMP_X_ATTR), atoi_get_prop (child_node2, COMP_Y_ATTR), atoi_get_prop (child_node2, COMP_WIDTH_ATTR), atoi_get_prop (child_node2, COMP_HEIGHT_ATTR), attrSet); } if (!xmlStrcmp (child_node2->name, TABLE_CELL_NODE)) { my_atk_set_table_cell (ATK_TABLE_CELL (child_obj), atoi_get_prop (child_node2, CELL_X_ATTR), atoi_get_prop (child_node2, CELL_Y_ATTR), atoi_get_prop (child_node2, ROW_SPAN_ATTR), atoi_get_prop (child_node2, COLUMN_SPAN_ATTR)); } if (!xmlStrcmp (child_node2->name, VALUE_NODE)) { my_atk_set_value (ATK_VALUE(child_obj), atof_get_prop (child_node2, MIN_ATTR), atof_get_prop (child_node2, CURRENT_ATTR), atof_get_prop (child_node2, MAX_ATTR), atof_get_prop (child_node2, STEP_ATTR)); } child_node2 = child_node2->next; } child_node = child_node->next; } return obj; } /* * Reads the XML from filename and uses it * to create a tree of MyAtkObjects. * * returns: The root object of the tree. */ MyAtkObject * atk_object_xml_parse (gchar *filename) { xmlDoc *doc; xmlNode *root_element; MyAtkObject *new_atk_object = NULL; doc = xmlReadFile (filename, NULL, 0); g_assert (doc != NULL); root_element = xmlDocGetRootElement (doc); if (!root_element) return NULL; new_atk_object = create_atk_object_from_element (root_element); xmlFreeDoc (doc); return new_atk_object; }