+static void _print_horizontal_line_in_relation_table() {
+ for (int i = 0; i < RELATION_TABLE_COLUMN_COUNT; i++) {
+ for (int j = 0; j < RELATION_COLUMN_WIDTH; j++)
+ printf("-");
+ printf("+");
+ }
+ printf("\n");
+}
+
+static void _print_legend_for_relation_table() {
+ char *table[] = {"OBJECT", "CONTROLLER_FOR", "CONTROLLED_BY", "FLOWS_TO", "FLOWS_FROM", "DESCRIBED_BY", "OTHER RELATION [ID]"};
+ assert(sizeof(table) / sizeof(table[0]) == RELATION_TABLE_COLUMN_COUNT);
+ for(int i = 0; i < RELATION_TABLE_COLUMN_COUNT; i++)
+ printf("%*s|", RELATION_COLUMN_WIDTH , table[i]);
+ printf("\n");
+ _print_horizontal_line_in_relation_table();
+}
+
+static char *_get_path_to_object_in_relation(AtspiRelation *relation) {
+ if (!relation)
+ return NULL;
+ gint last_index = atspi_relation_get_n_targets(relation) - 1;
+ AtspiAccessible *target = atspi_relation_get_target(relation, last_index);
+ return atspi_accessible_get_path(target, NULL);
+}
+
+static void _print_relations_for_object(AtspiAccessible *node) {
+ GArray *relations = atspi_accessible_get_relation_set(node, NULL);
+ if (!relations)
+ return;
+
+ if (relations->len) {
+ int size = RELATION_TABLE_COLUMN_COUNT * sizeof(char *);
+ char **table = malloc(size);
+ memset(table, 0, size);
+ table[0] = atspi_accessible_get_path(node, NULL);
+ char buf[8] = "";
+ for (int i = 0; i < relations->len; i++) {
+ AtspiRelation *relation = g_array_index(relations, AtspiRelation *, i);
+ AtspiRelationType type = atspi_relation_get_relation_type(relation);
+ switch (type) {
+ case ATSPI_RELATION_CONTROLLER_FOR:
+ table[1] = _get_path_to_object_in_relation(relation);
+ break;
+ case ATSPI_RELATION_CONTROLLED_BY:
+ table[2] = _get_path_to_object_in_relation(relation);
+ break;
+ case ATSPI_RELATION_FLOWS_TO:
+ table[3] = _get_path_to_object_in_relation(relation);
+ break;
+ case ATSPI_RELATION_FLOWS_FROM:
+ table[4] = _get_path_to_object_in_relation(relation);
+ break;
+ case ATSPI_RELATION_DESCRIBED_BY:
+ table[5] = _get_path_to_object_in_relation(relation);
+ break;
+ default:
+ snprintf(buf, 8, " [%d]", type);
+ _combine_strings(&table[RELATION_TABLE_COLUMN_COUNT - 1], buf);
+ }
+ }
+
+ for (int i = 0; i < RELATION_TABLE_COLUMN_COUNT; i++) {
+ printf("%*s|", RELATION_COLUMN_WIDTH, table[i] ? table[i] : "");
+ free(table[i]);
+ }
+ free(table);
+
+ printf("\n");
+ _print_horizontal_line_in_relation_table();
+ }
+ g_array_free(relations, TRUE);
+
+ int count = atspi_accessible_get_child_count(node, NULL);
+ for (int i = 0; i < count; i++) {
+ AtspiAccessible *child = atspi_accessible_get_child_at_index(node, i, NULL);
+ if (child)
+ _print_relations_for_object(child);
+ }
+}
+