3 * This program is free software; you can redistribute it and/or modify it
4 * under the terms of the GNU Lesser General Public License as published by
5 * the Free Software Foundation.
7 * This program is distributed in the hope that it will be useful, but
8 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
9 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * You should have received a copy of the GNU Lesser General Public License
13 * along with this program; if not, see <http://www.gnu.org/licenses/>.
17 * Chris Lahey <clahey@ximian.com>
19 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
29 #include "e-bit-array.h"
31 #define ONES ((guint32) 0xffffffff)
33 #define BOX(n) ((n) / 32)
34 #define OFFSET(n) (31 - ((n) % 32))
35 #define BITMASK(n) ((guint32)(((guint32) 0x1) << OFFSET((n))))
36 #define BITMASK_LEFT(n) ((((n) % 32) == 0) ? 0 : (ONES << (32 - ((n) % 32))))
37 #define BITMASK_RIGHT(n) ((guint32)(((guint32) ONES) >> ((n) % 32)))
45 e_bit_array_insert_real (EBitArray
*bit_array
,
50 if (bit_array
->bit_count
>= 0) {
51 /* Add another word if needed. */
52 if ((bit_array
->bit_count
& 0x1f) == 0) {
53 bit_array
->data
= g_renew (
54 guint32
, bit_array
->data
,
55 (bit_array
->bit_count
>> 5) + 1);
56 bit_array
->data
[bit_array
->bit_count
>> 5] = 0;
59 /* The box is the word that our row is in. */
61 /* Shift all words to the right of our box right one bit. */
62 for (i
= bit_array
->bit_count
>> 5; i
> box
; i
--) {
64 (bit_array
->data
[i
] >> 1) |
65 (bit_array
->data
[i
- 1] << 31);
68 /* Shift right half of box one bit to the right. */
69 bit_array
->data
[box
] =
70 (bit_array
->data
[box
] & BITMASK_LEFT (row
)) |
71 ((bit_array
->data
[box
] & BITMASK_RIGHT (row
)) >> 1);
72 bit_array
->bit_count
++;
77 e_bit_array_delete_real (EBitArray
*bit_array
,
79 gboolean move_selection_mode
)
84 gint selected
= FALSE
;
86 if (bit_array
->bit_count
> 0) {
89 last
= (bit_array
->bit_count
- 1) >> 5;
91 /* Build bitmasks for the left and right half of the box */
92 bitmask
= BITMASK_RIGHT (row
) >> 1;
93 if (move_selection_mode
)
94 selected
= e_bit_array_value_at (bit_array
, row
);
95 /* Shift right half of box one bit to the left. */
96 bit_array
->data
[box
] =
97 (bit_array
->data
[box
] & BITMASK_LEFT (row
)) |
98 ((bit_array
->data
[box
] & bitmask
) << 1);
100 /* Shift all words to the right of our box left one bit. */
102 bit_array
->data
[box
] &= bit_array
->data
[box
+ 1] >> 31;
104 for (i
= box
+ 1; i
< last
; i
++) {
106 (bit_array
->data
[i
] << 1) |
107 (bit_array
->data
[i
+ 1] >> 31);
109 /* this over-runs our memory! */
110 /*bit_array->data[i] = bit_array->data[i] << 1; */
112 bit_array
->bit_count
--;
113 /* Remove the last word if not needed. */
114 if ((bit_array
->bit_count
& 0x1f) == 0) {
115 bit_array
->data
= g_renew (guint32
, bit_array
->data
, bit_array
->bit_count
>> 5);
117 if (move_selection_mode
&& selected
&& bit_array
->bit_count
> 0) {
118 e_bit_array_select_single_row (
119 bit_array
, row
== bit_array
->bit_count
? row
- 1 : row
);
124 /* FIXME : Improve efficiency here. */
126 e_bit_array_delete (EBitArray
*bit_array
,
131 for (i
= 0; i
< count
; i
++)
132 e_bit_array_delete_real (bit_array
, row
, FALSE
);
135 /* FIXME : Improve efficiency here. */
137 e_bit_array_delete_single_mode (EBitArray
*bit_array
,
142 for (i
= 0; i
< count
; i
++)
143 e_bit_array_delete_real (bit_array
, row
, TRUE
);
146 /* FIXME : Improve efficiency here. */
148 e_bit_array_insert (EBitArray
*bit_array
,
153 for (i
= 0; i
< count
; i
++)
154 e_bit_array_insert_real (bit_array
, row
);
157 /* FIXME: Implement this more efficiently. */
159 e_bit_array_move_row (EBitArray
*bit_array
,
163 e_bit_array_delete_real (bit_array
, old_row
, FALSE
);
164 e_bit_array_insert_real (bit_array
, new_row
);
168 bit_array_finalize (GObject
*object
)
170 EBitArray
*bit_array
;
172 bit_array
= E_BIT_ARRAY (object
);
174 g_free (bit_array
->data
);
176 /* Chain up to parent's finalize() method. */
177 G_OBJECT_CLASS (e_bit_array_parent_class
)->finalize (object
);
181 * e_bit_array_value_at
182 * @bit_array: #EBitArray to check
183 * @n: The row to check
185 * This routine calculates whether the given row is selected.
187 * Returns: %TRUE if the given row is selected
190 e_bit_array_value_at (EBitArray
*bit_array
,
193 if (bit_array
->bit_count
< n
|| bit_array
->bit_count
== 0)
196 return (bit_array
->data
[BOX (n
)] >> OFFSET (n
)) & 0x1;
200 * e_bit_array_foreach
201 * @bit_array: #EBitArray to traverse
202 * @callback: The callback function to call back.
203 * @closure: The closure
205 * This routine calls the given callback function once for each
206 * selected row, passing closure as the closure.
209 e_bit_array_foreach (EBitArray
*bit_array
,
210 EForeachFunc callback
,
214 gint last
= (bit_array
->bit_count
+ 31) / 32;
215 for (i
= 0; i
< last
; i
++) {
216 if (bit_array
->data
[i
]) {
218 guint32 value
= bit_array
->data
[i
];
219 for (j
= 0; j
< 32; j
++) {
220 if (value
& 0x80000000) {
221 callback (i
* 32 + j
, closure
);
229 #define PART(x,n) (((x) & (0x01010101 << n)) >> n)
230 #define SECTION(x, n) (((x) >> (n * 8)) & 0xff)
233 * e_bit_array_selected_count
234 * @bit_array: #EBitArray to count
236 * This routine calculates the number of rows selected.
238 * Returns: The number of rows selected in the given model.
241 e_bit_array_selected_count (EBitArray
*bit_array
)
247 if (!bit_array
->data
)
252 last
= BOX (bit_array
->bit_count
- 1);
254 for (i
= 0; i
<= last
; i
++) {
256 guint32 thiscount
= 0;
257 for (j
= 0; j
< 8; j
++)
258 thiscount
+= PART (bit_array
->data
[i
], j
);
259 for (j
= 0; j
< 4; j
++)
260 count
+= SECTION (thiscount
, j
);
267 * e_bit_array_select_all
268 * @bit_array: #EBitArray to select all
270 * This routine selects all the rows in the given
274 e_bit_array_select_all (EBitArray
*bit_array
)
278 if (!bit_array
->data
)
279 bit_array
->data
= g_new0 (guint32
, (bit_array
->bit_count
+ 31) / 32);
281 for (i
= 0; i
< (bit_array
->bit_count
+ 31) / 32; i
++) {
282 bit_array
->data
[i
] = ONES
;
285 /* need to zero out the bits corresponding to the rows not
286 * selected in the last full 32 bit mask */
287 if (bit_array
->bit_count
% 32) {
288 gint unselected_mask
= 0;
289 gint num_unselected_in_last_byte
= 32 - bit_array
->bit_count
% 32;
291 for (i
= 0; i
< num_unselected_in_last_byte
; i
++)
292 unselected_mask
|= 1 << i
;
294 bit_array
->data
[(bit_array
->bit_count
+ 31) / 32 - 1] &= ~unselected_mask
;
299 e_bit_array_bit_count (EBitArray
*bit_array
)
301 return bit_array
->bit_count
;
304 #define OPERATE(object, i,mask,grow) \
305 ((grow) ? (((object)->data[(i)]) |= ((guint32) ~(mask))) : \
306 (((object)->data[(i)]) &= (mask)))
309 e_bit_array_change_one_row (EBitArray
*bit_array
,
316 OPERATE (bit_array
, i
, ~BITMASK (row
), grow
);
320 e_bit_array_change_range (EBitArray
*bit_array
,
332 bit_array
, i
, BITMASK_LEFT (start
) |
333 BITMASK_RIGHT (end
), grow
);
335 OPERATE (bit_array
, i
, BITMASK_LEFT (start
), grow
);
337 for (i
++; i
< last
; i
++)
338 bit_array
->data
[i
] = ONES
;
340 for (i
++; i
< last
; i
++)
341 bit_array
->data
[i
] = 0;
342 OPERATE (bit_array
, i
, BITMASK_RIGHT (end
), grow
);
348 e_bit_array_select_single_row (EBitArray
*bit_array
,
352 for (i
= 0; i
< ((bit_array
->bit_count
+ 31) / 32); i
++) {
353 if (!((i
== BOX (row
) && bit_array
->data
[i
] == BITMASK (row
)) ||
354 (i
!= BOX (row
) && bit_array
->data
[i
] == 0))) {
355 g_free (bit_array
->data
);
356 bit_array
->data
= g_new0 (guint32
, (bit_array
->bit_count
+ 31) / 32);
357 bit_array
->data
[BOX (row
)] = BITMASK (row
);
365 e_bit_array_toggle_single_row (EBitArray
*bit_array
,
368 if (bit_array
->data
[BOX (row
)] & BITMASK (row
))
369 bit_array
->data
[BOX (row
)] &= ~BITMASK (row
);
371 bit_array
->data
[BOX (row
)] |= BITMASK (row
);
375 e_bit_array_init (EBitArray
*bit_array
)
377 bit_array
->data
= NULL
;
378 bit_array
->bit_count
= 0;
382 e_bit_array_class_init (EBitArrayClass
*class)
384 GObjectClass
*object_class
;
386 object_class
= G_OBJECT_CLASS (class);
387 object_class
->finalize
= bit_array_finalize
;
391 e_bit_array_new (gint count
)
393 EBitArray
*bit_array
;
395 bit_array
= g_object_new (E_TYPE_BIT_ARRAY
, NULL
);
396 bit_array
->bit_count
= count
;
397 bit_array
->data
= g_new0 (guint32
, (bit_array
->bit_count
+ 31) / 32);