Fix atspi_accessible_get_description
[platform/upstream/at-spi2-core.git] / atspi / atspi-stateset.c
1 #include "atspi-private.h"
2
3 static void atspi_state_set_class_init (AtspiStateSetClass *klass);
4
5 G_DEFINE_TYPE (AtspiStateSet, atspi_state_set, G_TYPE_OBJECT)
6
7 static const char *state_names [] =
8 {
9   "invalid",
10   "active",
11   "armed",
12   "busy",
13   "checked",
14   "collapsed",
15   "defunct",
16   "editable",
17   "enabled",
18   "expandable",
19   "expanded",
20   "focusable",
21   "focused",
22   "has-tool-tip",
23   "horizontal",
24   "iconified",
25   "modal",
26   "multi-line",
27   "multiselectable",
28   "opaque",
29   "pressed",
30   "resizable",
31   "selectable",
32   "selected",
33   "sensitive",
34   "showing",
35   "singleLine",
36   "stale",
37   "transient",
38   "vertical",
39   "visible",
40   "manages-descendants",
41   "indeterminate",
42   "required",
43   "truncated",
44   "animated",
45   "invalid-entry",
46   "supports-autocompletion",
47   "selectable-text",
48   "is-default",
49   "visited",
50   NULL
51 };
52
53 static void
54 atspi_state_set_init (AtspiStateSet *set)
55 {
56   set->states = 0;
57 }
58
59 static void
60 atspi_state_set_class_init (AtspiStateSetClass* klass)
61 {
62 }
63
64 /*
65  * atspi_state_set_new:
66  *
67  * @states: (element-type AtspiStateType): An array of states with which to initialize
68  * the state set.
69  *
70  * Returns: A new #AtspiStateSet with the given states.
71  **/
72 AtspiStateSet *
73 atspi_state_set_new (GArray *states)
74 {
75   AtspiStateSet *set = g_object_new (ATSPI_TYPE_STATE_SET, NULL);
76   gint i;
77
78   if (!set || !states)
79     return set;
80
81   for (i = 0; i < states->len; i++)
82     atspi_state_set_add (set, g_array_index (states, AtspiStateType, i));
83   return set;
84 }
85
86 AtspiStateSet *
87 _atspi_state_set_new_internal (AtspiAccessible *accessible, gint64 states)
88 {
89   AtspiStateSet *set;
90   
91   set = g_object_new (ATSPI_TYPE_STATE_SET, NULL);
92   g_return_val_if_fail (set != NULL, NULL);
93
94   set->accessible = accessible;
95   set->states = states;
96   return set;
97 }
98
99 void
100 atspi_state_set_set_by_name (AtspiStateSet *set, const gchar *name, gboolean enabled)
101 {
102   gint i = 0;
103
104   if (set->accessible &&
105       !(set->accessible->cached_properties & ATSPI_CACHE_STATES))
106     return;
107
108   /* TODO: This could perhaps be optimized */
109   for (i = 0; state_names [i]; i++)
110   {
111     if (!strcmp (state_names [i], name))
112     {
113       if (enabled)
114         set->states |= (1 << i);
115       else
116         set->states &= ~(1 << i);
117       return;
118     }
119   }
120   g_warning ("at-spi: Attempt to set unknown state '%s'", name);
121 }
122
123 static void
124 refresh_states (AtspiStateSet *set)
125 {
126   GArray *state_array;
127   dbus_uint32_t *states;
128
129   if (!set->accessible ||
130       (set->accessible->cached_properties & ATSPI_CACHE_STATES))
131     return;
132
133   if (!_atspi_dbus_call (set->accessible, atspi_interface_accessible, "GetState", NULL, "=>au", &state_array))
134     return;
135
136   states = (dbus_uint32_t *) state_array->data;
137
138   set->states = ((gint64)states [1]) << 32;
139   set->states += states [0];
140   g_array_free (state_array, TRUE);
141 }
142
143 /**
144  * atspi_state_set_add:
145  *
146  * @set: a pointer to the #AtspiStateSet object on which to operate.
147  * @state: an #AtspiStateType to be added to the specified #AtspiStateSet.
148  *
149  * Add a particular #AtspiState to an #AtspiStateSet (i.e. set the
150  *       given state to #TRUE in the stateset.
151  *
152  **/
153 void
154 atspi_state_set_add (AtspiStateSet *set, AtspiStateType state)
155 {
156   g_return_if_fail (set != NULL);
157   set->states |= (((gint64)1) << state);
158 }
159
160 /**
161  * atspi_state_set_compare:
162  * @set: a pointer to the first #AtspiStateSet object on which to operate.
163  * @set: a pointer to the second #AtspiStateSet setect on which to operate.
164  *
165  * Determine the differences between two instances of #AtspiStateSet.
166  *.
167  * @see AtspiStateSet_equals().
168  *
169  * Returns: (transfer full): an #AtspiStateSet object containing all states
170  *          contained on one of the two sets but not the other.
171  *
172  **/
173 AtspiStateSet *
174 atspi_state_set_compare (AtspiStateSet *set,
175                          AtspiStateSet *set2)
176 {
177   g_return_val_if_fail (set != NULL, NULL);
178   g_return_val_if_fail (set2 != NULL, NULL);
179
180   return _atspi_state_set_new_internal (NULL, set->states ^ set2->states);
181 }
182
183 /**
184  * atspi_state_set_contains:
185  * @set: a pointer to the #AtspiStateSet object on which to operate.
186  * @state: an #AtspiStateType for which the specified #AtspiStateSet
187  *       will be queried.
188  *
189  * Determine whether a given #AtspiStateSet includes a given state; that is,
190  *       whether @state is true for the stateset in question.
191  *
192  * Returns: #TRUE if @state is true/included in the given #AtspiStateSet,
193  *          otherwise #FALSE.
194  *
195  **/
196 gboolean
197 atspi_state_set_contains (AtspiStateSet *set,
198                              AtspiStateType state)
199 {
200   refresh_states (set);
201   return (set->states & (1 << state)) ? TRUE : FALSE;
202 }
203
204 /**
205  * atspi_state_set_equals:
206  * @set: a pointer to the first #AtspiStateSet object on which to operate.
207  * @set2: a pointer to the second #AtspiStateSet object on which to operate.
208  *
209  * Determine whether two instances of #AtspiStateSet are equivalent (i.e.
210  *         consist of the same #AtspiStates).  Useful for checking multiple
211  *         state variables at once; construct the target state then compare against it.
212  *
213  * @see AtspiStateSet_compare().
214  *
215  * Returns: #TRUE if the two #AtspiStateSets are equivalent,
216  *          otherwise #FALSE.
217  *
218  **/
219 gboolean
220 atspi_state_set_equals (AtspiStateSet *set,
221                            AtspiStateSet *set2)
222 {
223   if (set == set2)
224     return TRUE;
225   if (set == NULL || set2 == NULL)
226     return FALSE;
227   return (set->states == set2->states);
228 }
229
230 /**
231  * atspi_state_set_get_states:
232  *
233  * @set: The #AtspiStateSet to be queried.
234  *
235  * Return the states in an #AtspiStateSet as an array.
236  *
237  * Returns: (element-type AtspiStateType) (transfer full): A #GArray of state
238  *          types representing the current state.
239  **/
240 GArray *
241 atspi_state_set_get_states (AtspiStateSet *set)
242 {
243   gint i = 0;
244   guint64 val = 1;
245   GArray *ret;
246
247   g_return_val_if_fail (set != NULL, NULL);
248   refresh_states (set);
249   ret = g_array_new (TRUE, TRUE, sizeof (AtspiStateType));
250   if (!ret)
251     return NULL;
252   for (i = 0; i < 64; i++)
253   {
254     if (set->states & val)
255     {
256       GArray *new_array = g_array_append_val (ret, i);
257       if (new_array)
258         ret = new_array;
259     }
260     val <<= 1;
261   }
262   return ret;
263 }
264
265 /**
266  * atspi_state_set_is_empty:
267  *
268  * @set: The #AtspiStateSet to query.
269  *
270  * Returns: #TRUE if the state set contains no states; #FALSE otherwise.
271  **/
272 gboolean
273 atspi_state_set_is_empty (AtspiStateSet *set)
274 {
275   return (set->states == 0);
276 }
277
278 /**
279  * atspi_state_set_remove:
280  *
281  * @set: a pointer to the #AtspiStateSet object on which to operate.
282  * @state: an #AtspiStateType to remove from the specifiedn state set.
283  *
284  * Remove a particular #AtspiState to an #AtspiStateSet (i.e. set the
285  *       given state to #FALSE in the stateset.)
286  *
287  **/
288 void
289 atspi_state_set_remove (AtspiStateSet *set, AtspiStateType state)
290 {
291   g_return_if_fail (set != NULL);
292   set->states &= ~(1 << state);
293 }
294