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