Protect against NULL pointer dereference
[platform/upstream/atk.git] / atk / atkstateset.c
1 /* ATK -  Accessibility Toolkit
2  * Copyright 2001 Sun Microsystems Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include "config.h"
21
22 #include <glib-object.h>
23
24 #include "atkobject.h"
25 #include "atkstateset.h"
26
27 /**
28  * SECTION:atkstateset
29  * @Short_description: An AtkStateSet contains the states of an object.
30  * @Title:AtkStateSet
31  *
32  * An AtkStateSet is a read-only representation of the full set of #AtkStates
33  * that apply to an object at a given time. This set is not meant to be
34  * modified, but rather created when #atk_object_ref_state_set() is called.
35  */
36
37 #define ATK_STATE(state_enum)             ((AtkState)((guint64)1 << ((state_enum)%64)))
38
39 struct _AtkRealStateSet
40 {
41   GObject parent;
42
43   AtkState state;
44 };
45
46 typedef struct _AtkRealStateSet      AtkRealStateSet;
47
48 static void            atk_state_set_class_init       (AtkStateSetClass  *klass);
49
50 GType
51 atk_state_set_get_type (void)
52 {
53   static GType type = 0;
54
55   if (!type)
56     {
57       static const GTypeInfo typeInfo =
58       {
59         sizeof (AtkStateSetClass),
60         (GBaseInitFunc) NULL,
61         (GBaseFinalizeFunc) NULL,
62         (GClassInitFunc) atk_state_set_class_init,
63         (GClassFinalizeFunc) NULL,
64         NULL,
65         sizeof (AtkRealStateSet),
66         0,
67         (GInstanceInitFunc) NULL,
68       } ;
69       type = g_type_register_static (G_TYPE_OBJECT, "AtkStateSet", &typeInfo, 0) ;
70     }
71   return type;
72 }
73
74 static void
75 atk_state_set_class_init (AtkStateSetClass *klass)
76 {
77 }
78
79 /**
80  * atk_state_set_new:
81  * 
82  * Creates a new empty state set.
83  * 
84  * Returns: a new #AtkStateSet 
85  **/
86 AtkStateSet*
87 atk_state_set_new (void)
88 {
89   return (AtkStateSet*) g_object_new (ATK_TYPE_STATE_SET, NULL);
90 }
91
92 /**
93  * atk_state_set_is_empty:
94  * @set: an #AtkStateType
95  *
96  * Checks whether the state set is empty, i.e. has no states set.
97  *
98  * Returns: %TRUE if @set has no states set, otherwise %FALSE
99  **/
100 gboolean
101 atk_state_set_is_empty (AtkStateSet   *set)
102 {
103   AtkRealStateSet *real_set;
104   g_return_val_if_fail (ATK_IS_STATE_SET (set), FALSE);
105
106   real_set = (AtkRealStateSet *)set;
107
108   if (real_set->state)
109     return FALSE;
110   else
111     return TRUE;
112 }
113
114 /**
115  * atk_state_set_add_state:
116  * @set: an #AtkStateSet
117  * @type: an #AtkStateType
118  *
119  * Adds the state of the specified type to the state set if it is not already
120  * present.
121  *
122  * Note that because an #AtkStateSet is a read-only object, this method should
123  * be used to add a state to a newly-created set which will then be returned by
124  * #atk_object_ref_state_set. It should not be used to modify the existing state
125  * of an object. See also #atk_object_notify_state_change.
126  *
127  * Returns: %TRUE if  the state for @type is not already in @set.
128  **/
129 gboolean
130 atk_state_set_add_state (AtkStateSet   *set,
131                          AtkStateType  type)
132 {
133   AtkRealStateSet *real_set;
134   g_return_val_if_fail (ATK_IS_STATE_SET (set), FALSE);
135
136   real_set = (AtkRealStateSet *)set;
137
138   if (real_set->state & ATK_STATE (type))
139     return FALSE;
140   else
141   {
142     real_set->state |= ATK_STATE (type);
143     return TRUE;
144   }
145 }
146 /**
147  * atk_state_set_add_states:
148  * @set: an #AtkStateSet
149  * @types: (array length=n_types): an array of #AtkStateType
150  * @n_types: The number of elements in the array
151  *
152  * Adds the states of the specified types to the state set.
153  *
154  * Note that because an #AtkStateSet is a read-only object, this method should
155  * be used to add states to a newly-created set which will then be returned by
156  * #atk_object_ref_state_set. It should not be used to modify the existing state
157  * of an object. See also #atk_object_notify_state_change.
158  **/
159 void
160 atk_state_set_add_states (AtkStateSet   *set,
161                           AtkStateType  *types,
162                           gint          n_types)
163 {
164   AtkRealStateSet *real_set;
165   gint     i;
166   g_return_if_fail (ATK_IS_STATE_SET (set));
167
168   real_set = (AtkRealStateSet *)set;
169
170   for (i = 0; i < n_types; i++)
171   {
172     real_set->state |= ATK_STATE (types[i]);
173   }
174 }
175
176 /**
177  * atk_state_set_clear_states:
178  * @set: an #AtkStateSet
179  *
180  * Removes all states from the state set.
181  **/
182 void
183 atk_state_set_clear_states (AtkStateSet   *set)
184 {
185   AtkRealStateSet *real_set;
186   g_return_if_fail (ATK_IS_STATE_SET (set));
187
188   real_set = (AtkRealStateSet *)set;
189
190   real_set->state = 0;
191 }
192
193 /**
194  * atk_state_set_contains_state:
195  * @set: an #AtkStateSet
196  * @type: an #AtkStateType
197  *
198  * Checks whether the state for the specified type is in the specified set.
199  *
200  * Returns: %TRUE if @type is the state type is in @set.
201  **/
202 gboolean
203 atk_state_set_contains_state (AtkStateSet   *set,
204                               AtkStateType  type)
205 {
206   AtkRealStateSet *real_set;
207   g_return_val_if_fail (ATK_IS_STATE_SET (set), FALSE);
208
209   real_set = (AtkRealStateSet *)set;
210
211   if (real_set->state & ATK_STATE (type))
212     return TRUE;
213   else
214     return FALSE;
215 }
216
217 /**
218  * atk_state_set_contains_states:
219  * @set: an #AtkStateSet
220  * @types: (array length=n_types): an array of #AtkStateType
221  * @n_types: The number of elements in the array
222  *
223  * Checks whether the states for all the specified types are in the 
224  * specified set.
225  *
226  * Returns: %TRUE if all the states for @type are in @set.
227  **/
228 gboolean
229 atk_state_set_contains_states (AtkStateSet   *set,
230                                AtkStateType  *types,
231                                gint          n_types)
232 {
233   AtkRealStateSet *real_set;
234   gint i;
235   g_return_val_if_fail (ATK_IS_STATE_SET (set), FALSE);
236
237   real_set = (AtkRealStateSet *)set;
238
239   for (i = 0; i < n_types; i++)
240   {
241     if (!(real_set->state & ATK_STATE (types[i])))
242       return FALSE;
243   }
244   return TRUE;
245 }
246
247 /**
248  * atk_state_set_remove_state:
249  * @set: an #AtkStateSet
250  * @type: an #AtkType
251  *
252  * Removes the state for the specified type from the state set.
253  *
254  * Note that because an #AtkStateSet is a read-only object, this method should
255  * be used to remove a state to a newly-created set which will then be returned
256  * by #atk_object_ref_state_set. It should not be used to modify the existing
257  * state of an object. See also #atk_object_notify_state_change.
258  *
259  * Returns: %TRUE if @type was the state type is in @set.
260  **/
261 gboolean
262 atk_state_set_remove_state (AtkStateSet  *set,
263                             AtkStateType type)
264 {
265   AtkRealStateSet *real_set;
266   g_return_val_if_fail (ATK_IS_STATE_SET (set), FALSE);
267
268   real_set = (AtkRealStateSet *)set;
269
270   if (real_set->state & ATK_STATE (type))
271   {
272     real_set->state ^= ATK_STATE (type);
273     return TRUE;
274   }
275   else
276     return FALSE;
277 }
278
279 /**
280  * atk_state_set_and_sets:
281  * @set: an #AtkStateSet
282  * @compare_set: another #AtkStateSet
283  *
284  * Constructs the intersection of the two sets, returning %NULL if the
285  * intersection is empty.
286  *
287  * Returns: (transfer full): a new #AtkStateSet which is the intersection of
288  * the two sets.
289  **/
290 AtkStateSet*
291 atk_state_set_and_sets (AtkStateSet  *set,
292                         AtkStateSet  *compare_set)
293 {
294   AtkRealStateSet *real_set, *real_compare_set;
295   AtkStateSet *return_set = NULL;
296   AtkState state;
297
298   g_return_val_if_fail (ATK_IS_STATE_SET (set), NULL);
299   g_return_val_if_fail (ATK_IS_STATE_SET (compare_set), NULL);
300
301   real_set = (AtkRealStateSet *)set;
302   real_compare_set = (AtkRealStateSet *)compare_set;
303
304   state = real_set->state & real_compare_set->state;
305   if (state)
306   {
307     return_set = atk_state_set_new();
308     ((AtkRealStateSet *) return_set)->state = state;
309   }
310   return return_set;
311 }
312
313 /**
314  * atk_state_set_or_sets:
315  * @set: an #AtkStateSet
316  * @compare_set: another #AtkStateSet
317  *
318  * Constructs the union of the two sets.
319  *
320  * Returns: (nullable) (transfer full): a new #AtkStateSet which is
321  * the union of the two sets, returning %NULL is empty.
322  **/
323 AtkStateSet*
324 atk_state_set_or_sets (AtkStateSet  *set,
325                        AtkStateSet  *compare_set)
326 {
327   AtkRealStateSet *real_set, *real_compare_set;
328   AtkStateSet *return_set = NULL;
329   AtkState state;
330
331   g_return_val_if_fail (ATK_IS_STATE_SET (set), NULL);
332   g_return_val_if_fail (ATK_IS_STATE_SET (compare_set), NULL);
333
334   real_set = (AtkRealStateSet *)set;
335   real_compare_set = (AtkRealStateSet *)compare_set;
336
337   state = real_set->state | real_compare_set->state;
338
339   if (state)
340   {
341     return_set = atk_state_set_new();
342     ((AtkRealStateSet *) return_set)->state = state;
343   }
344
345   return return_set;
346 }
347
348 /**
349  * atk_state_set_xor_sets:
350  * @set: an #AtkStateSet
351  * @compare_set: another #AtkStateSet
352  *
353  * Constructs the exclusive-or of the two sets, returning %NULL is empty.
354  * The set returned by this operation contains the states in exactly
355  * one of the two sets.
356  *
357  * Returns: (transfer full): a new #AtkStateSet which contains the states
358  * which are in exactly one of the two sets.
359  **/
360 AtkStateSet*
361 atk_state_set_xor_sets (AtkStateSet  *set,
362                         AtkStateSet  *compare_set)
363 {
364   AtkRealStateSet *real_set, *real_compare_set;
365   AtkStateSet *return_set = NULL;
366   AtkState state, state1, state2;
367
368   g_return_val_if_fail (ATK_IS_STATE_SET (set), NULL);
369   g_return_val_if_fail (ATK_IS_STATE_SET (compare_set), NULL);
370
371   real_set = (AtkRealStateSet *)set;
372   real_compare_set = (AtkRealStateSet *)compare_set;
373
374   state1 = real_set->state & (~real_compare_set->state);
375   state2 = (~real_set->state) & real_compare_set->state;
376   state = state1 | state2;
377
378   if (state)
379   {
380     return_set = atk_state_set_new();
381     ((AtkRealStateSet *) return_set)->state = state;
382   }
383   return return_set;
384 }