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 Lesser General Public
11
 * License as published by the Free Software Foundation; either
12
 * version 2.1 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
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public
20
 * License along with this library; if not, write to the
21
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22
 * Boston, MA 02110-1301, USA.
23
 */
24

            
25
#include "atspi-private.h"
26

            
27
/**
28
 * AtspiStateSet:
29
 *
30
 * The atspi-stateset objects implement wrappers around a
31
 * bitmap of accessible states.
32
 */
33

            
34
static void atspi_state_set_class_init (AtspiStateSetClass *klass);
35

            
36
1
G_DEFINE_TYPE (AtspiStateSet, atspi_state_set, G_TYPE_OBJECT)
37

            
38
static void
39
1423
atspi_state_set_init (AtspiStateSet *set)
40
{
41
1423
  set->states = 0;
42
1423
}
43

            
44
static void
45
1
atspi_state_set_class_init (AtspiStateSetClass *klass)
46
{
47
1
}
48

            
49
/**
50
 * atspi_state_set_new:
51
 * @states: (element-type AtspiStateType): An array of states with which the
52
 *          method initializes the state set.
53
 *
54
 * Generates an #AtspiStateSet with the given @states.
55
 *
56
 * Returns: A new #AtspiStateSet with the given states.
57
 **/
58
AtspiStateSet *
59
3
atspi_state_set_new (GArray *states)
60
{
61
3
  AtspiStateSet *set = g_object_new (ATSPI_TYPE_STATE_SET, NULL);
62
  gint i;
63

            
64
3
  if (!set || !states)
65
    return set;
66

            
67
9
  for (i = 0; i < states->len; i++)
68
6
    atspi_state_set_add (set, g_array_index (states, AtspiStateType, i));
69
3
  return set;
70
}
71

            
72
AtspiStateSet *
73
1420
_atspi_state_set_new_internal (AtspiAccessible *accessible, gint64 states)
74
{
75
  AtspiStateSet *set;
76

            
77
1420
  set = g_object_new (ATSPI_TYPE_STATE_SET, NULL);
78
1420
  g_return_val_if_fail (set != NULL, NULL);
79

            
80
1420
  set->accessible = accessible;
81
1420
  set->states = states;
82
1420
  return set;
83
}
84

            
85
/**
86
 * atspi_state_set_set_by_name:
87
 * @set: a pointer to the #AtspiStateSet object on which to operate.
88
 * @name: a string corresponding to a state name.
89
 * @enabled: if #TRUE, @name should be enabled in the @set in question;
90
 *          otherwise, it should be disabled.
91
 *
92
 * Enables/disables a state in an #AtspiStateSet according to its @name.
93
 **/
94
void
95
2
atspi_state_set_set_by_name (AtspiStateSet *set, const gchar *name, gboolean enabled)
96
{
97
  GTypeClass *type_class;
98
  GEnumValue *value;
99

            
100
2
  if (set->accessible &&
101
2
      !(set->accessible->cached_properties & ATSPI_CACHE_STATES))
102
    return;
103

            
104
2
  type_class = g_type_class_ref (ATSPI_TYPE_STATE_TYPE);
105

            
106
2
  value = g_enum_get_value_by_nick (G_ENUM_CLASS (type_class), name);
107

            
108
2
  if (!value)
109
    {
110
      g_warning ("AT-SPI: Attempt to set unknown state '%s'", name);
111
    }
112
2
  else if (enabled)
113
1
    set->states |= ((gint64) 1 << value->value);
114
  else
115
1
    set->states &= ~((gint64) 1 << value->value);
116

            
117
2
  g_type_class_unref (type_class);
118
}
119

            
120
static void
121
1500
refresh_states (AtspiStateSet *set)
122
{
123
  GArray *state_array;
124
  dbus_uint32_t *states;
125

            
126
1500
  if (!set->accessible ||
127
1494
      (set->accessible->cached_properties & ATSPI_CACHE_STATES))
128
1499
    return;
129

            
130
1
  if (!_atspi_dbus_call (set->accessible, atspi_interface_accessible, "GetState", NULL, "=>au", &state_array))
131
    return;
132

            
133
1
  states = (dbus_uint32_t *) state_array->data;
134

            
135
1
  set->states = ((gint64) states[1]) << 32;
136
1
  set->states |= (gint64) states[0];
137
1
  g_array_free (state_array, TRUE);
138
}
139

            
140
/**
141
 * atspi_state_set_add:
142
 * @set: a pointer to the #AtspiStateSet object on which to operate.
143
 * @state: an #AtspiStateType to be added to the specified #AtspiStateSet.
144
 *
145
 * Adds a particular #AtspiState to an #AtspiStateSet (i.e. sets the
146
 *       given state to #TRUE in the stateset).
147
 *
148
 **/
149
void
150
7
atspi_state_set_add (AtspiStateSet *set, AtspiStateType state)
151
{
152
7
  g_return_if_fail (set != NULL);
153
7
  set->states |= (((gint64) 1) << state);
154
}
155

            
156
/**
157
 * atspi_state_set_compare:
158
 * @set: a pointer to the first #AtspiStateSet object on which to operate.
159
 * @set2: a pointer to the second #AtspiStateSet object on which to operate.
160
 *
161
 * Determines the differences between two instances of #AtspiStateSet.
162
 *
163
 * @see #atspi_state_set_equals.
164
 *
165
 * Returns: (transfer full): an #AtspiStateSet object containing all states
166
 * contained on one of the two sets but not the other.
167
 *
168
 **/
169
AtspiStateSet *
170
1
atspi_state_set_compare (AtspiStateSet *set,
171
                         AtspiStateSet *set2)
172
{
173
1
  g_return_val_if_fail (set != NULL, NULL);
174
1
  g_return_val_if_fail (set2 != NULL, NULL);
175

            
176
1
  return _atspi_state_set_new_internal (NULL, set->states ^ set2->states);
177
}
178

            
179
/**
180
 * atspi_state_set_contains:
181
 * @set: a pointer to the #AtspiStateSet object on which to operate.
182
 * @state: an #AtspiStateType for which the specified #AtspiStateSet
183
 *          will be queried.
184
 *
185
 * Determines whether a given #AtspiStateSet includes a given state; that is,
186
 *          whether @state is true for the @set in question.
187
 *
188
 * Returns: #TRUE if @state is true/included in the given #AtspiStateSet,
189
 *          otherwise #FALSE.
190
 *
191
 **/
192
gboolean
193
1492
atspi_state_set_contains (AtspiStateSet *set,
194
                          AtspiStateType state)
195
{
196
1492
  if (!set)
197
    return FALSE;
198
1492
  refresh_states (set);
199
1492
  return (set->states & ((gint64) 1 << state)) ? TRUE : FALSE;
200
}
201

            
202
/**
203
 * atspi_state_set_equals:
204
 * @set: a pointer to the first #AtspiStateSet object on which to operate.
205
 * @set2: a pointer to the second #AtspiStateSet object on which to operate.
206
 *
207
 * Determines whether two instances of #AtspiStateSet are equivalent (i.e.
208
 *          consist of the same #AtspiStates).  Useful for checking multiple
209
 *          state variables at once.
210
 *
211
 * @see #atspi_state_set_compare.
212
 *
213
 * Returns: #TRUE if the two #AtspiStateSets are equivalent,
214
 * otherwise #FALSE.
215
 *
216
 **/
217
gboolean
218
1
atspi_state_set_equals (AtspiStateSet *set,
219
                        AtspiStateSet *set2)
220
{
221
1
  if (set == set2)
222
    return TRUE;
223
1
  if (set == NULL || set2 == NULL)
224
    return FALSE;
225
1
  return (set->states == set2->states);
226
}
227

            
228
/**
229
 * atspi_state_set_get_states:
230
 * @set: The #AtspiStateSet to be queried.
231
 *
232
 * Returns the states in an #AtspiStateSet as an array.
233
 *
234
 * Returns: (element-type AtspiStateType) (transfer full): A #GArray of state
235
 *          types representing the current state.
236
 **/
237
GArray *
238
8
atspi_state_set_get_states (AtspiStateSet *set)
239
{
240
8
  gint i = 0;
241
8
  guint64 val = 1;
242
  GArray *ret;
243

            
244
8
  g_return_val_if_fail (set != NULL, NULL);
245
8
  refresh_states (set);
246
8
  ret = g_array_new (TRUE, TRUE, sizeof (AtspiStateType));
247
8
  if (!ret)
248
    return NULL;
249
520
  for (i = 0; i < 64; i++)
250
    {
251
512
      if (set->states & val)
252
13
        ret = g_array_append_val (ret, i);
253
512
      val <<= 1;
254
    }
255
8
  return ret;
256
}
257

            
258
/**
259
 * atspi_state_set_is_empty:
260
 * @set: The #AtspiStateSet to query.
261
 *
262
 * Returns: #TRUE if the state set contains no states; #FALSE otherwise.
263
 **/
264
gboolean
265
2
atspi_state_set_is_empty (AtspiStateSet *set)
266
{
267
2
  return (set->states == 0);
268
}
269

            
270
/**
271
 * atspi_state_set_remove:
272
 * @set: a pointer to the #AtspiStateSet object on which to operate.
273
 * @state: an #AtspiStateType to remove from the specified @set.
274
 *
275
 * Removes a particular #AtspiState to an #AtspiStateSet (i.e. sets the
276
 *       given state to #FALSE in the stateset.)
277
 *
278
 **/
279
void
280
1
atspi_state_set_remove (AtspiStateSet *set, AtspiStateType state)
281
{
282
1
  g_return_if_fail (set != NULL);
283
1
  set->states &= ~((gint64) 1 << state);
284
}