/* * Linux Desktop Testing Project http://www.gnomebangalore.org/ldtp * * Author: * Nagappan A * Premkumar J * * Copyright 2004 - 2005 Novell, 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 "appmap-gen.h" #include "utils.h" typedef GHashTable Appmap; int table = 0, canvas = 0, column_header = 0, combo_box = 0, page_tab_list = 0, page_tab = 0, spin_button = 0, button = 0, tbutton = 0, radio_button = 0, check_box = 0, tree_table = 0, layered_pane = 0, text = 0, cal_view = 0, panel = 0, filler = 0, menubar = 0, menu = 0, separator = 0, scroll_bar = 0, scroll_pane = 0, split_pane = 0, slider = 0, html_container = 0, password_text = 0, progress_bar = 0, status_bar = 0, tool_bar = 0, label = 0, unknown = 0; void reset_count() { table = 0; canvas = 0; column_header = 0; combo_box = 0; page_tab_list = 0; page_tab = 0; spin_button = 0; button = 0; tbutton = 0; radio_button = 0; tree_table = 0; layered_pane = 0; text = 0; cal_view = 0; panel = 0; filler = 0; menubar = 0; menu = 0; separator = 0; scroll_bar = 0; scroll_pane = 0; split_pane = 0; slider = 0; html_container = 0; password_text = 0; progress_bar = 0; status_bar = 0; tool_bar = 0; label = 0; check_box = 0; unknown = 0; } /* *GDestroyNotify function for the hashtable used */ void free_element (gpointer data) { char *val; val = (char *) data; g_free (val); } /* Get accessible handle of the given application */ Accessible *accessible_app_handle (char *app_name) { int i, num_apps; Accessible *desktop; /* Get SPI handle of desktop 0 FIXME: Need to change the hardcoded value of desktop */ desktop = SPI_getDesktop (0); /* Get the total count of childs in the desktop */ num_apps = Accessible_getChildCount (desktop); /* Traverse the list of application handle and if application name matches, then return the handle */ for (i = 0; i < num_apps; i++) { char *name; Accessible *child; child = Accessible_getChildAtIndex (desktop, i); if (!child) continue; /* Application name of child handle */ name = Accessible_getName (child); g_print ("Application name: %s\n", name); /* Incase of OO.o due to spaces, string compare gives different result. Found because of extra spaces. Now stripped it ;) */ if (g_utf8_strchr (name, strlen (name), ' ')) g_strstrip (name); if (g_ascii_strcasecmp (name, app_name) == 0) { /* Application name matched */ SPI_freeString (name); Accessible_unref (desktop); return child; } else Accessible_unref (child); SPI_freeString (name); } Accessible_unref (desktop); return NULL; } FILE *open_appmap (char *app_name) { FILE *fp = NULL; char *appmap_file = NULL; appmap_file = g_strdup_printf ("%s.map", app_name); fp = fopen (appmap_file, "w"); if (fp == NULL) return NULL; g_free (appmap_file); return fp; } int close_appmap (FILE *fp) { if (fp) fclose (fp); return 0; } /* * This function filters the appmap entries */ int filter_appmap_data (Accessible *accessible, OBJECT_INFO *obj_info, char *label) { if (g_ascii_strcasecmp (obj_info->object_type, "separator" ) == 0 || g_ascii_strcasecmp (obj_info->object_type, "table_cell" ) == 0) return 0; if (g_ascii_strcasecmp (label, "ukngrip" ) == 0) return 0; if (g_ascii_strcasecmp (obj_info->object_type, "menu_item" ) == 0) { int parent_type; Accessible *parent; Accessible *grand_parent; parent = Accessible_getParent (accessible); grand_parent = Accessible_getParent (parent); parent_type = Accessible_getRole (grand_parent); Accessible_unref (grand_parent); Accessible_unref (parent); if (parent_type == SPI_ROLE_COMBO_BOX) return 0; else return 1; } if (g_ascii_strcasecmp (obj_info->object_type, "list_item") == 0) return 0; if (g_ascii_strcasecmp (obj_info->object_type, "unknown" ) == 0) { Accessible *parent; int parent_type; parent = Accessible_getParent (accessible); parent_type = Accessible_getRole (parent); Accessible_unref (parent); if (parent_type == SPI_ROLE_TABLE || parent_type == SPI_ROLE_TREE_TABLE ) return 0; else return 1; } return 1; } static char *get_keybinding (Accessible *object) { if (Accessible_isAction (object)) { AccessibleAction *action = NULL; action = Accessible_getAction (object); if (action) { char *binding = NULL; binding = AccessibleAction_getKeyBinding (action, 0l); Accessible_unref (action); if (g_utf8_collate (binding, "") == 0) return NULL; if (binding) { gchar *key_binding = NULL; key_binding = search_forward (binding, ';'); SPI_freeString (binding); binding = NULL; if (key_binding && g_utf8_collate (key_binding, "") == 0) return binding; else if (!key_binding) return key_binding; binding = key_binding; if (g_utf8_strchr (binding, strlen (binding), '>') == NULL) return binding; key_binding = search_reverse (binding, '>'); if (key_binding && g_utf8_collate (key_binding, "") == 0) { g_free (binding); return NULL; } else if (!key_binding) return binding; g_free (binding); return key_binding; } } } return NULL; } char *insert_underscore (gchar *text, gchar *binding) { GString *str; GString *tmp; gint length; const gchar *p; const gchar *end; gboolean flag = FALSE; g_return_val_if_fail (text != NULL, NULL); length = strlen (text); str = g_string_sized_new (length); tmp = g_string_sized_new (length); p = text; end = text + length; while (p != end) { const gchar *next; next = g_utf8_next_char (p); if (*p == g_unichar_toupper (*binding)) { g_string_append (tmp, "_"); flag = TRUE; } else if (flag != TRUE && g_unichar_tolower (*p) == g_unichar_tolower (*binding)) { g_string_append (str, "_"); flag = TRUE; } g_string_append_len (str, p, next - p); g_string_append_len (tmp, p, next - p); p = next; } if (g_utf8_collate (str->str, tmp->str) == 0) g_free (tmp->str); else if (g_utf8_strchr (tmp->str, tmp->len, '_')) { g_free (str->str); str = tmp; } else g_free (tmp->str); return g_string_free (str, FALSE); } char *get_relation_name (Accessible *object, long *len) { int i = 0, j = 0; int max_accessible = 0; char *label_by = NULL; AccessibleRelation **relation = NULL; relation = Accessible_getRelationSet (object); if (relation) { max_accessible = AccessibleRelation_getNTargets (*relation); if (max_accessible > 0) { for (i = 0; relation[i] != NULL; i++) { for (j = 0; j < AccessibleRelation_getNTargets (relation[i]); j++) { AccessibleRelationType relation_type; relation_type = AccessibleRelation_getRelationType (relation[i]); if (relation_type == SPI_RELATION_LABELED_BY || relation_type == SPI_RELATION_CONTROLLED_BY || relation_type == SPI_RELATION_LABEL_FOR) { int k = 0; char *name = NULL; Accessible *tmp_obj; tmp_obj = AccessibleRelation_getTarget (relation[i], i); name = Accessible_getName (tmp_obj); if (name == NULL) { Accessible_unref (tmp_obj); for (k = j; relation[k] != NULL; k++) Accessible_unref (relation[k]); Accessible_unref (*relation); return NULL; } if (g_utf8_collate (name, "") == 0) { SPI_freeString (name); Accessible_unref (tmp_obj); for (k = j; relation[k] != NULL; k++) Accessible_unref (relation[k]); Accessible_unref (*relation); return NULL; } g_print ("Relation name: %s\n", name); label_by = g_strdup (name); SPI_freeString (name); if (label_by) { gchar *key_binding = NULL; key_binding = get_keybinding (tmp_obj); if (key_binding) { gchar *tmp = NULL; tmp = insert_underscore (label_by, key_binding); g_free (key_binding); if (tmp) { g_free (label_by); label_by = tmp; } } } if (Accessible_isText (tmp_obj)) { AccessibleText *text = NULL; text = Accessible_getText (tmp_obj); *len = AccessibleText_getCharacterCount (text); Accessible_unref (text); } Accessible_unref (tmp_obj); for (k = j; relation[k] != NULL; k++) Accessible_unref (relation[k]); Accessible_unref (*relation); return label_by; } } } } } Accessible_unref (*relation); return NULL; } /* * This function creates entry in the Appmap file corresponding to the object passed to it */ char *add_appmap_data (FILE *fp, Accessible *accessible, char *parent_name, int child_index, GHashTable *current_context) { int size; long length = -1; long text_len = -1; char *name = NULL; char *key = NULL; char *value = NULL; char *label = NULL; char *label_by = NULL; char *object_record; char *accessible_name; OBJECT_INFO *cur_obj_info = NULL; cur_obj_info = get_object_info (accessible); accessible_name = Accessible_getName (accessible); label_by = get_relation_name (accessible, &length); if (label_by) { if (g_utf8_collate (label_by, "") == 0) label = g_strdup (accessible_name); else { label = g_strdup (label_by); text_len = length; } } else label = g_strdup (accessible_name); if (g_utf8_collate (label, "") != 0) { long label_index = 1; char *value = NULL; char *stripped_data = NULL; if (g_utf8_strchr (label, text_len, ' ')) stripped_data = strip_white_space (label); else stripped_data = g_strdup (label); if (g_utf8_strchr (stripped_data, text_len, '.')) { value = strip_delim (stripped_data, '.'); g_free (stripped_data); stripped_data = g_strdup (value); g_free (value); value = NULL; } if (g_utf8_strchr (stripped_data, text_len, ':')) { value = strip_delim (stripped_data, ':'); g_free (stripped_data); stripped_data = g_strdup (value); g_free (value); value = NULL; } if (g_utf8_strchr (stripped_data, text_len, '\n')) { value = strip_delim (stripped_data, '\n'); g_free (stripped_data); stripped_data = g_strdup (value); g_free (value); value = NULL; } if (g_utf8_strchr (stripped_data, text_len, '_')) { value = remove_char (stripped_data, '_'); g_free (stripped_data); stripped_data = g_strdup (value); g_free (value); value = NULL; } name = g_strdup_printf ("%s%s", cur_obj_info->prefix, stripped_data); value = g_hash_table_lookup (current_context, name); while (value) { if (name) g_free (name); name = g_strdup_printf ("%s%s%ld", cur_obj_info->prefix, stripped_data, label_index); label_index++; value = g_hash_table_lookup (current_context, name); } g_free (stripped_data); } else name = g_strdup_printf ("%s%d", cur_obj_info->prefix, cur_obj_info->instance_index); g_free (label); label = g_strdup (accessible_name); if (label) { gchar *key_binding = NULL; key_binding = get_keybinding (accessible); if (key_binding) { gchar *tmp = NULL; tmp = insert_underscore (label, key_binding); g_free (key_binding); if (tmp) { g_free (label); label = tmp; } } } SPI_freeString (accessible_name); /* * Following code is for limiting appmap from generating * label with value as string made of only space character */ if (g_utf8_strchr (label, strlen (label), ' ')) { char *stripped_data = NULL; stripped_data = strip_white_space (label); if (g_utf8_collate (stripped_data, "") == 0) { g_free (label); label = g_strdup (stripped_data); } g_free (stripped_data); } if (filter_appmap_data (accessible, cur_obj_info, name)) { if (g_utf8_collate (label, "") == 0) { if (!label_by) object_record = g_strdup_printf ("%s={class=%s,parent=%s,child_index=%d}\n", name, cur_obj_info->object_type, parent_name, child_index); else { object_record = g_strdup_printf ("%s={class=%s,parent=%s,child_index=%d,label_by=%s}\n", name, cur_obj_info->object_type, parent_name, child_index, label_by); g_free (label_by); label_by = NULL; } } else { if (g_ascii_strcasecmp (cur_obj_info->object_type, "combo_box") != 0) object_record = g_strdup_printf ("%s={class=%s,parent=%s,child_index=%d,label=%s}\n", name, cur_obj_info->object_type, parent_name, child_index, label); else object_record = g_strdup_printf ("%s={class=%s,parent=%s,child_index=%d}\n", name, cur_obj_info->object_type, parent_name, child_index); } size = strlen (object_record); fwrite (object_record, sizeof (char), size, fp); key = g_strdup (name); value = g_strdup ("ADDED"); if (current_context) g_hash_table_insert (current_context, key, value); else g_print ("Hashtable is NULL\n"); g_free (label); g_free (label_by); g_free (object_record); g_free (cur_obj_info->object_type); g_free (cur_obj_info->prefix); g_free (cur_obj_info); return name; } else { g_free (name); g_free (label); g_free (label_by); g_free (cur_obj_info->object_type); g_free (cur_obj_info->prefix); g_free (cur_obj_info); return NULL; } } /* * This function returns the information about the accessible object passed */ OBJECT_INFO *get_object_info (Accessible *accessible) { OBJECT_INFO *obj_info; int role; obj_info = (OBJECT_INFO *) malloc (sizeof (OBJECT_INFO)); role = Accessible_getRole (accessible); if (role == SPI_ROLE_PAGE_TAB) { obj_info->prefix = g_strdup ("ptab"); obj_info->instance_index = page_tab; page_tab++; obj_info->object_type = g_strdup ("page_tab"); } else if (role == SPI_ROLE_PAGE_TAB_LIST) { obj_info->prefix = g_strdup ("ptl"); obj_info->instance_index = page_tab_list; page_tab_list++; obj_info->object_type = g_strdup ("page_tab_list"); } else if (role == SPI_ROLE_TABLE) { obj_info->prefix = g_strdup ("tbl"); obj_info->instance_index = table; table++; obj_info->object_type = g_strdup ("table"); } else if (role == SPI_ROLE_COMBO_BOX) { obj_info->prefix = g_strdup ("cbo"); obj_info->instance_index = combo_box; combo_box++; obj_info->object_type = g_strdup ("combo_box"); } else if (role == SPI_ROLE_SPIN_BUTTON) { obj_info->prefix = g_strdup ("sbtn"); obj_info->instance_index = spin_button; spin_button++; obj_info->object_type = g_strdup ("spin_button"); } else if (role == SPI_ROLE_FONT_CHOOSER) { obj_info->prefix = g_strdup ("dlg"); obj_info->instance_index = -1; /* Value -1 signifies not applicable */ obj_info->object_type = g_strdup ("font_chooser"); } else if (role == SPI_ROLE_RADIO_BUTTON) { obj_info->prefix = g_strdup ("rbtn"); obj_info->instance_index = radio_button; radio_button++; obj_info->object_type = g_strdup ("radio_button"); } else if (role == SPI_ROLE_TREE_TABLE) { obj_info->prefix = g_strdup ("ttbl"); obj_info->instance_index = tree_table; tree_table++; obj_info->object_type = g_strdup ("tree_table"); } else if (role == SPI_ROLE_LAYERED_PANE) { obj_info->prefix = g_strdup ("pane"); obj_info->instance_index = layered_pane; layered_pane++; obj_info->object_type = g_strdup ("layered_pane"); } else if (role == SPI_ROLE_FRAME) { obj_info->prefix = g_strdup ("frm"); obj_info->instance_index = -1; obj_info->object_type = g_strdup ("frame"); } else if (role == SPI_ROLE_DIALOG) { obj_info->prefix = g_strdup ("dlg"); obj_info->instance_index = -1; obj_info->object_type = g_strdup ("dialog"); } else if (role == SPI_ROLE_ALERT) { obj_info->prefix = g_strdup ("dlg"); obj_info->instance_index = -1; obj_info->object_type = g_strdup ("alert"); } else if (role == SPI_ROLE_CALENDAR) { obj_info->prefix = g_strdup ("calview"); obj_info->instance_index = cal_view; cal_view++; obj_info->object_type = g_strdup ("calendar_view"); } else if (role == SPI_ROLE_PANEL) { obj_info->prefix = g_strdup ("pnl"); obj_info->instance_index = panel; panel++; obj_info->object_type = g_strdup ("panel"); } else if (role == SPI_ROLE_LABEL) { obj_info->prefix = g_strdup ("lbl"); obj_info->instance_index = label; label++; obj_info->object_type = g_strdup ("label"); } else if (role == SPI_ROLE_MENU_BAR) { obj_info->prefix = g_strdup ("mbr"); obj_info->instance_index = menubar; menubar++; obj_info->object_type = g_strdup ("menu_bar"); } else if (role == SPI_ROLE_MENU) { obj_info->prefix = g_strdup ("mnu"); obj_info->instance_index = menu; menu++; obj_info->object_type = g_strdup ("menu"); } else if (role == SPI_ROLE_MENU_ITEM) { obj_info->prefix = g_strdup ("mnu"); obj_info->instance_index = menu; menu++; obj_info->object_type = g_strdup ("menu_item"); } else if (role == SPI_ROLE_LIST_ITEM) { obj_info->prefix = g_strdup ("lst"); obj_info->instance_index = -1; obj_info->object_type = g_strdup ("list_item"); } else if (role == SPI_ROLE_CHECK_MENU_ITEM) { obj_info->prefix = g_strdup ("mnu"); obj_info->instance_index = menu; menu++; obj_info->object_type = g_strdup ("check_menu_item"); } else if (role == SPI_ROLE_RADIO_MENU_ITEM) { obj_info->prefix = g_strdup ("mnu"); obj_info->instance_index = menu; menu++; obj_info->object_type = g_strdup ("radio_menu_item"); } else if (role == SPI_ROLE_PUSH_BUTTON) { obj_info->prefix = g_strdup ("btn"); obj_info->instance_index = button; button++; obj_info->object_type = g_strdup ("push_button"); } else if (role == SPI_ROLE_TOGGLE_BUTTON) { obj_info->prefix = g_strdup ("tbtn"); obj_info->instance_index = tbutton; tbutton++; obj_info->object_type = g_strdup ("toggle_button"); } else if (role == SPI_ROLE_SCROLL_BAR) { obj_info->prefix = g_strdup ("scbr"); obj_info->instance_index = scroll_bar; scroll_bar++; obj_info->object_type = g_strdup ("scroll_bar"); } else if (role == SPI_ROLE_SCROLL_PANE) { obj_info->prefix = g_strdup ("scpn"); obj_info->instance_index = scroll_pane; scroll_pane++; obj_info->object_type = g_strdup ("scroll_pane"); } else if (role == SPI_ROLE_TEXT) { obj_info->prefix = g_strdup ("txt"); obj_info->instance_index = text; text++; obj_info->object_type = g_strdup ("text"); } else if (role == SPI_ROLE_PASSWORD_TEXT) { obj_info->prefix = g_strdup ("txt"); obj_info->instance_index = text; text++; obj_info->object_type = g_strdup ("password_text"); } else if (role == SPI_ROLE_STATUS_BAR) { obj_info->prefix = g_strdup ("stat"); obj_info->instance_index = status_bar; status_bar++; obj_info->object_type = g_strdup ("statusbar"); } else if (role == SPI_ROLE_TABLE_COLUMN_HEADER) { obj_info->prefix = g_strdup ("tch"); obj_info->instance_index = status_bar; column_header++; obj_info->object_type = g_strdup ("table_column_header"); } else if (role == SPI_ROLE_SEPARATOR) { obj_info->prefix = g_strdup ("spr"); obj_info->instance_index = separator; separator++; obj_info->object_type = g_strdup ("separator"); } else if (role == SPI_ROLE_FILLER) { obj_info->prefix = g_strdup ("flr"); obj_info->instance_index = filler; filler++; obj_info->object_type = g_strdup ("filler"); } else if (role == SPI_ROLE_CANVAS) { obj_info->prefix = g_strdup ("cnvs"); obj_info->instance_index = canvas; canvas++; obj_info->object_type = g_strdup ("canvas"); } else if (role == SPI_ROLE_SPLIT_PANE) { obj_info->prefix = g_strdup ("splt"); obj_info->instance_index = split_pane; split_pane++; obj_info->object_type = g_strdup ("split_pane"); } else if (role == SPI_ROLE_SLIDER) { obj_info->prefix = g_strdup ("sldr"); obj_info->instance_index = slider; slider++; obj_info->object_type = g_strdup ("slider"); } else if (role == SPI_ROLE_HTML_CONTAINER) { obj_info->prefix = g_strdup ("html"); obj_info->instance_index = html_container; html_container++; obj_info->object_type = g_strdup ("html_container"); } else if (role == SPI_ROLE_PROGRESS_BAR) { obj_info->prefix = g_strdup ("pbar"); obj_info->instance_index = progress_bar; progress_bar++; obj_info->object_type = g_strdup ("progree_bar"); } else if (role == SPI_ROLE_TOOL_BAR) { obj_info->prefix = g_strdup ("tbar"); obj_info->instance_index = tool_bar; tool_bar++; obj_info->object_type = g_strdup ("tool_bar"); } else if (role == SPI_ROLE_CHECK_BOX) { obj_info->prefix = g_strdup ("chk"); obj_info->instance_index = check_box; check_box++; obj_info->object_type = g_strdup ("check_box"); } else if (role == SPI_ROLE_TABLE_CELL) { obj_info->prefix = g_strdup ("tblc"); obj_info->instance_index = -1; obj_info->object_type = g_strdup ("table_cell"); } else { obj_info->prefix = g_strdup ("ukn"); obj_info->instance_index = unknown; unknown++; obj_info->object_type = g_strdup ("unknown"); } return obj_info; } void insert_context_header (FILE *fp, Accessible *accessible) { char *name; char *label; char *object_record; int size; char *accessible_name; OBJECT_INFO *cur_obj_info = NULL; cur_obj_info = get_object_info (accessible); accessible_name = Accessible_getName (accessible); label = g_strdup (accessible_name); SPI_freeString (accessible_name); if (g_utf8_collate (label, "") != 0) { char *stripped_data = NULL; char *tmp_data = NULL; if (g_utf8_strchr (label, strlen (label), ' ')) stripped_data = strip_white_space (label); else stripped_data = g_strdup (label); if (g_utf8_strchr (stripped_data, strlen (stripped_data), '.')) tmp_data = strip_delim (stripped_data, '.'); else tmp_data = g_strdup (stripped_data); name = g_strdup_printf ("%s%s", cur_obj_info->prefix, tmp_data); g_free (tmp_data); g_free (stripped_data); g_free (label); g_free (cur_obj_info->object_type); g_free (cur_obj_info->prefix); g_free (cur_obj_info); } else { /* * TODO: Handle the case of window label being NULL */ g_print ("Found window with label value as NULL"); g_free (label); g_free (object_record); g_free (cur_obj_info->object_type); g_free (cur_obj_info->prefix); g_free (cur_obj_info); } object_record = g_strdup_printf ("[%s]\n", name); size = strlen (object_record); fwrite (object_record, sizeof (char), size, fp); g_free (name); g_free (object_record); } void create_appmap (FILE *fp, Accessible *accessible, char *application_name) { int i, num_child; char *name; char *label; Accessible *child; GHashTable *current_context = NULL; label = Accessible_getName (accessible); if (g_utf8_strchr (label, strlen (label), ' ')) name = g_strdup_printf ("[%s]\n", strip_white_space (label)); else name = g_strdup_printf ("[%s]\n", label); num_child = Accessible_getChildCount (accessible); for (i = 0; i < num_child; i++) { reset_count (); current_context = g_hash_table_new_full (&g_str_hash, &g_str_equal, &free_element, &free_element); child = Accessible_getChildAtIndex (accessible, i); insert_context_header (fp, child); if (!child) continue; accessible_object_handle (fp, child, application_name, i, current_context); fwrite ("\n", sizeof (char), 1, fp); g_hash_table_destroy (current_context); current_context = NULL; } g_free (name); SPI_freeString (label); Accessible_unref (accessible); } /* Get accessible handle of the given object */ void accessible_object_handle (FILE *fp, Accessible *accessible, char* parent_name, int child_index, GHashTable *current_context) { int i, num_child; Accessible *child; char *current_parent = NULL; char *temp_parent = NULL; num_child = Accessible_getChildCount (accessible); temp_parent = add_appmap_data (fp, accessible, parent_name, child_index, current_context); if (temp_parent) { current_parent = g_strdup_printf ("%s", temp_parent); g_free (temp_parent); for (i = 0; i < num_child; i++) { child = Accessible_getChildAtIndex (accessible, i); if (!child) continue; /* * To eliminate unnecessary processing of table cells */ if (Accessible_getRole (child) == SPI_ROLE_TABLE_CELL) { Accessible_unref (child); break; } /* Call this function recursively, until we reach the end of depth first search in all the given object handle */ accessible_object_handle (fp, child, current_parent, i, current_context); } g_free (current_parent); } Accessible_unref (accessible); } void ldtp_print (const char *string) { if (getenv ("LDTP_DEBUG") != NULL) printf ("%s", string); } int appmap_main (char *app_name) { FILE *fp = NULL; Accessible *parent; parent = accessible_app_handle (app_name); if (!parent) { printf ("Application %s seems to be not running\n", app_name); return -1; } fp = open_appmap (app_name); if (fp) { create_appmap (fp, parent, app_name); close_appmap (fp); } else g_print ("Unable to open file for writing application map\n"); return 0; } int main (int argc, char *argv[]) { int leaked; int init_error; char *application_name; char *map_filename; if (argc < 2) { g_print ("Syntax: appmap \n"); exit(0); } application_name = strdup (argv[1]); map_filename = g_strdup_printf ("%s.map", argv[1]); init_error = SPI_init (); if (init_error) { g_print ("Error: SPI Init\n"); return init_error; } putenv ("GTK_MODULES=gail:atk-bridge"); putenv ("GNOME_ACCESSIBILITY=1"); // Register local print function g_set_print_handler (ldtp_print); appmap_main (application_name); g_free (application_name); g_free (map_filename); leaked = SPI_exit (); if (leaked) g_print ("Leaked %d SPI handles\n", leaked); putenv ("AT_BRIDGE_SHUTDOWN=1"); return 0; }