Initial pass at adding i18n and proper object disposal
[platform/upstream/at-spi2-core.git] / atspi / atspi-matchrule.c
1 /*
2  * AT-SPI - Assistive Technology Service Provider Interface
3  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4  *
5  * Copyright 2001, 2002 Sun Microsystems Inc.,
6  * Copyright 2001, 2002 Ximian, Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 #include "atspi-private.h"
25
26 G_DEFINE_TYPE (AtspiMatchRule, atspi_match_rule, G_TYPE_OBJECT)
27
28 static void
29 atspi_match_rule_init (AtspiMatchRule *match_rule)
30 {
31 }
32
33 static void
34 atspi_match_rule_dispose (GObject *object)
35 {
36   AtspiMatchRule *rule = ATSPI_MATCH_RULE (object);
37
38   if (rule->states)
39   {
40     g_object_unref (rule->states);
41     rule->states = NULL;
42   }
43
44   if (rule->attributes)
45   {
46     g_hash_table_unref (rule->attributes);
47     rule->attributes = NULL;
48   }
49
50   G_OBJECT_CLASS (atspi_match_rule_parent_class)->dispose (object);
51 }
52
53 static void
54 atspi_match_rule_finalize (GObject *object)
55 {
56   AtspiMatchRule *rule = ATSPI_MATCH_RULE (object);
57
58   /* TODO: Check that interfaces don't leak */
59   if (rule->interfaces)
60     g_array_free (rule->interfaces, TRUE);
61
62   G_OBJECT_CLASS (atspi_match_rule_parent_class)->finalize (object);
63 }
64
65 static void
66 atspi_match_rule_class_init (AtspiMatchRuleClass *klass)
67 {
68   GObjectClass *object_class = G_OBJECT_CLASS (klass);
69
70   object_class->dispose = atspi_match_rule_dispose;
71   object_class->finalize = atspi_match_rule_finalize;
72 }
73
74 /**
75  * atspi_match_rule_new:
76  *
77  * @states: An #AtspiStateSet specifying the states to match or NULL if none.
78  * @statematchtype: An #AtspiCollectionMatchType specifying how to interpret
79  *                  @states.
80  * @attributes: (element-type gchar* gchar*): A #GHashTable specifying
81  *              attributes to match.
82  * @attributematchtype: An #AtspiCollectionMatchType specifying how to
83  *                      interpret @attributes.
84  * @interfaces: (element-type gchar*): An array of interfaces to match, or
85  *              NUL if not applicable.  Interface names should be specified
86  *              by their DBus names (org.a11y.Atspi.Accessible,
87  *              org.a11y.Atspi.Component, etc).
88  * @interfacematchtype: An #AtspiCollectionMatchType specifying how to
89  *                      interpret @interfaces.
90  * @roles: (element-type AtspiRole): A #GArray of roles to match, or NULL if
91  *         not applicable.
92  * @rolematchtype: An #AtspiCollectionMatchType specifying how to
93  *                      interpret @roles.
94  * @invert: Specifies whether results should be inverted.
95  * TODO: Document this parameter better.
96  *
97  * Returns: (transfer full): A new #AtspiMatchRule.
98  */
99 AtspiMatchRule *
100 atspi_match_rule_new (AtspiStateSet *states,
101                       AtspiCollectionMatchType statematchtype,
102                       GHashTable *attributes,
103                       AtspiCollectionMatchType attributematchtype,
104                       GArray *roles,
105                       AtspiCollectionMatchType rolematchtype,
106                       GArray *interfaces,
107                       AtspiCollectionMatchType interfacematchtype,
108                       gboolean invert)
109 {
110   AtspiMatchRule *rule = g_object_new (ATSPI_TYPE_MATCH_RULE, NULL);
111   int i;
112
113   if (!rule)
114     return NULL;
115
116   if (states)
117     rule->states = g_object_ref (states);
118   rule->statematchtype = statematchtype;
119
120   if (attributes)
121     rule->attributes = g_hash_table_ref (attributes);
122     rule->attributematchtype = attributematchtype;
123
124   if (interfaces)
125     rule->interfaces = g_array_ref (interfaces);
126   rule->interfacematchtype = interfacematchtype;
127
128   if (roles)
129   {
130     for (i = 0; i < roles->len; i++)
131     {
132       AtspiRole role = g_array_index (roles, AtspiRole, i);
133       if (role < 128)
134         rule->roles [role / 32] |= (1 << (role % 32));
135       else
136         g_warning ("Atspi: unexpected role %d\n", role);
137     }
138   }
139   else
140     rule->roles [0] = rule->roles [1] = 0;
141   rule->rolematchtype = rolematchtype;
142
143   rule->invert = invert;
144
145   return rule;
146 }
147
148 static void
149 append_entry (gpointer *key, gpointer *val, gpointer data)
150 {
151   DBusMessageIter *iter = data;
152   DBusMessageIter iter_entry;
153
154   if (!dbus_message_iter_open_container (iter, DBUS_TYPE_DICT_ENTRY, NULL,
155                                         &iter_entry))
156     return;
157   dbus_message_iter_append_basic (&iter_entry, DBUS_TYPE_STRING, &key);
158   dbus_message_iter_append_basic (&iter_entry, DBUS_TYPE_STRING, &val);
159   dbus_message_iter_close_container (iter, &iter_entry);
160 }
161
162 gboolean
163 _atspi_match_rule_marshal (AtspiMatchRule *rule, DBusMessageIter *iter)
164 {
165   DBusMessageIter iter_struct, iter_array, iter_dict;
166   dbus_int32_t states [2];
167   dbus_int32_t d_statematchtype = rule->statematchtype;
168   dbus_int32_t d_attributematchtype = rule->attributematchtype;
169   dbus_int32_t d_interfacematchtype = rule->interfacematchtype;
170   dbus_uint32_t d_rolematchtype = rule->rolematchtype;
171   dbus_bool_t d_invert = rule->invert;
172   gint i;
173   dbus_int32_t d_role;
174
175   if (!dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL,
176                                          &iter_struct))
177     return FALSE;
178
179   /* states */
180   if (rule->states)
181   {
182     states [0] = rule->states->states & 0xffffffff;
183     states [1] = rule->states->states >> 32;
184   }
185   else
186   {
187     states [0] = states [1] = 0;
188   }
189   dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "i", &iter_array);
190   dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &states [0]);
191   dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &states [1]);
192   dbus_message_iter_close_container (&iter_struct, &iter_array);
193   dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &d_statematchtype);
194
195   /* attributes */
196   if (!dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "{ss}",
197                                          &iter_dict))
198     return FALSE;
199   g_hash_table_foreach (rule->attributes, append_entry, &iter_dict);
200   dbus_message_iter_close_container (&iter_struct, &iter_dict);
201   dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &d_attributematchtype);
202
203   if (!dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "i",
204       &iter_array))
205     return FALSE;
206   d_role = rule->roles [0];
207   dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &d_role);
208   d_role = rule->roles [1];
209   dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &d_role);
210   d_role = rule->roles [2];
211   dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &d_role);
212   d_role = rule->roles [3];
213   dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &d_role);
214   dbus_message_iter_close_container (&iter_struct, &iter_array);
215   dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32,
216                                   &d_rolematchtype);
217
218   /* interfaces */
219   if (!dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "s",
220       &iter_array))
221     return FALSE;
222   if (rule->interfaces)
223   {
224     for (i = 0; i < rule->interfaces->len; i++)
225     {
226       char *val = g_array_index (rule->interfaces, gchar *, i);
227       dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_STRING, &val);
228     }
229   }
230   dbus_message_iter_close_container (&iter_struct, &iter_array);
231   dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &d_interfacematchtype);
232
233   dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_BOOLEAN, &d_invert);
234
235   dbus_message_iter_close_container (iter, &iter_struct);
236   return TRUE;
237 }