glib2 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. data/ChangeLog +3023 -0
  2. data/README +28 -0
  3. data/Rakefile +87 -0
  4. data/extconf.rb +61 -0
  5. data/sample/bookmarkfile.rb +66 -0
  6. data/sample/completion.rb +45 -0
  7. data/sample/idle.rb +41 -0
  8. data/sample/iochannel.rb +44 -0
  9. data/sample/keyfile.rb +62 -0
  10. data/sample/shell.rb +36 -0
  11. data/sample/spawn.rb +25 -0
  12. data/sample/timeout.rb +28 -0
  13. data/sample/timeout2.rb +35 -0
  14. data/sample/timer.rb +40 -0
  15. data/sample/type-register.rb +103 -0
  16. data/sample/type-register2.rb +104 -0
  17. data/sample/utils.rb +54 -0
  18. data/src/glib-enum-types.c +1032 -0
  19. data/src/glib-enum-types.h +140 -0
  20. data/src/lib/glib-mkenums.rb +199 -0
  21. data/src/lib/glib2.rb +220 -0
  22. data/src/lib/mkmf-gnome2.rb +390 -0
  23. data/src/lib/pkg-config.rb +137 -0
  24. data/src/rbgcompat.h +30 -0
  25. data/src/rbglib.c +320 -0
  26. data/src/rbglib.h +96 -0
  27. data/src/rbglib_bookmarkfile.c +595 -0
  28. data/src/rbglib_completion.c +192 -0
  29. data/src/rbglib_convert.c +195 -0
  30. data/src/rbglib_error.c +95 -0
  31. data/src/rbglib_fileutils.c +83 -0
  32. data/src/rbglib_i18n.c +44 -0
  33. data/src/rbglib_int64.c +157 -0
  34. data/src/rbglib_iochannel.c +883 -0
  35. data/src/rbglib_keyfile.c +846 -0
  36. data/src/rbglib_maincontext.c +917 -0
  37. data/src/rbglib_mainloop.c +87 -0
  38. data/src/rbglib_messages.c +150 -0
  39. data/src/rbglib_pollfd.c +111 -0
  40. data/src/rbglib_shell.c +68 -0
  41. data/src/rbglib_source.c +190 -0
  42. data/src/rbglib_spawn.c +345 -0
  43. data/src/rbglib_threads.c +51 -0
  44. data/src/rbglib_timer.c +127 -0
  45. data/src/rbglib_unicode.c +611 -0
  46. data/src/rbglib_utils.c +386 -0
  47. data/src/rbglib_win32.c +136 -0
  48. data/src/rbgobj_boxed.c +251 -0
  49. data/src/rbgobj_closure.c +337 -0
  50. data/src/rbgobj_convert.c +167 -0
  51. data/src/rbgobj_enums.c +961 -0
  52. data/src/rbgobj_fundamental.c +30 -0
  53. data/src/rbgobj_object.c +892 -0
  54. data/src/rbgobj_param.c +390 -0
  55. data/src/rbgobj_paramspecs.c +305 -0
  56. data/src/rbgobj_signal.c +963 -0
  57. data/src/rbgobj_strv.c +61 -0
  58. data/src/rbgobj_type.c +851 -0
  59. data/src/rbgobj_typeinstance.c +121 -0
  60. data/src/rbgobj_typeinterface.c +148 -0
  61. data/src/rbgobj_typemodule.c +66 -0
  62. data/src/rbgobj_typeplugin.c +49 -0
  63. data/src/rbgobj_value.c +313 -0
  64. data/src/rbgobj_valuearray.c +59 -0
  65. data/src/rbgobj_valuetypes.c +298 -0
  66. data/src/rbgobject.c +406 -0
  67. data/src/rbgobject.h +265 -0
  68. data/src/rbgprivate.h +88 -0
  69. data/src/rbgutil.c +222 -0
  70. data/src/rbgutil.h +82 -0
  71. data/src/rbgutil_callback.c +231 -0
  72. data/test/glib-test-init.rb +6 -0
  73. data/test/glib-test-utils.rb +12 -0
  74. data/test/run-test.rb +25 -0
  75. data/test/test_enum.rb +99 -0
  76. data/test/test_file_utils.rb +15 -0
  77. data/test/test_glib2.rb +120 -0
  78. data/test/test_iochannel.rb +275 -0
  79. data/test/test_key_file.rb +38 -0
  80. data/test/test_mkenums.rb +25 -0
  81. data/test/test_signal.rb +20 -0
  82. data/test/test_timeout.rb +28 -0
  83. data/test/test_unicode.rb +369 -0
  84. data/test/test_utils.rb +37 -0
  85. data/test/test_win32.rb +13 -0
  86. metadata +165 -0
@@ -0,0 +1,167 @@
1
+ /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
2
+ /************************************************
3
+
4
+ rbgobj_convert.c -
5
+
6
+ $Author: mutoh $
7
+ $Date: 2006/05/22 17:13:05 $
8
+
9
+ Copyright (C) 2006 Sjoerd Simons, Masao Mutoh
10
+ ************************************************/
11
+
12
+ #include "rbgobject.h"
13
+ #include "rbgprivate.h"
14
+
15
+ static GHashTable *tables, *class_to_g_type_map;
16
+
17
+ void
18
+ Init_gobject_convert(void)
19
+ {
20
+ tables = g_hash_table_new(g_int_hash, g_int_equal);
21
+ class_to_g_type_map = g_hash_table_new(g_int_hash, g_int_equal);
22
+ }
23
+
24
+ void
25
+ rbgobj_convert_define(RGConvertTable *table)
26
+ {
27
+ g_hash_table_insert(tables, &(table->type), table);
28
+ if (table->klass && !NIL_P(table->klass)) {
29
+ g_hash_table_insert(class_to_g_type_map,
30
+ &(table->klass), &(table->type));
31
+ }
32
+ }
33
+
34
+ RGConvertTable *
35
+ rbgobj_convert_lookup(GType type)
36
+ {
37
+ return g_hash_table_lookup(tables, &type);
38
+ }
39
+
40
+ gboolean
41
+ rbgobj_convert_has_type(GType type)
42
+ {
43
+ return rbgobj_convert_lookup(type) != NULL;
44
+ }
45
+
46
+ gboolean
47
+ rbgobj_convert_get_superclass(GType type, VALUE *result)
48
+ {
49
+ RGConvertTable *table;
50
+
51
+ table = rbgobj_convert_lookup(type);
52
+ if (table && table->get_superclass) {
53
+ *result = table->get_superclass();
54
+ return TRUE;
55
+ }
56
+
57
+ return FALSE;
58
+ }
59
+
60
+ gboolean
61
+ rbgobj_convert_type_init_hook(GType type, VALUE klass)
62
+ {
63
+ RGConvertTable *table;
64
+
65
+ table = rbgobj_convert_lookup(type);
66
+ if (table && table->type_init_hook) {
67
+ table->type_init_hook(klass);
68
+ return TRUE;
69
+ }
70
+
71
+ return FALSE;
72
+ }
73
+
74
+ gboolean
75
+ rbgobj_convert_rvalue2gvalue(GType type, VALUE value, GValue *result)
76
+ {
77
+ RGConvertTable *table;
78
+
79
+ table = rbgobj_convert_lookup(type);
80
+ if (table && table->rvalue2gvalue) {
81
+ table->rvalue2gvalue(value, result);
82
+ return TRUE;
83
+ }
84
+
85
+ return FALSE;
86
+ }
87
+
88
+ gboolean
89
+ rbgobj_convert_gvalue2rvalue(GType type, const GValue *value, VALUE *result)
90
+ {
91
+ RGConvertTable *table;
92
+
93
+ table = rbgobj_convert_lookup(type);
94
+ if (table && table->gvalue2rvalue) {
95
+ *result = table->gvalue2rvalue(value);
96
+ return TRUE;
97
+ }
98
+
99
+ return FALSE;
100
+ }
101
+
102
+ GType
103
+ rbgobj_convert_rvalue2gtype(VALUE value)
104
+ {
105
+ VALUE klass;
106
+ GType *result;
107
+
108
+ klass = rb_class_of(value);
109
+ result = g_hash_table_lookup(class_to_g_type_map, &klass);
110
+ return result ? *result : 0;
111
+ }
112
+
113
+ gboolean
114
+ rbgobj_convert_initialize(GType type, VALUE obj, gpointer cobj)
115
+ {
116
+ RGConvertTable *table;
117
+
118
+ table = rbgobj_convert_lookup(type);
119
+ if (table && table->initialize) {
120
+ table->initialize(obj, cobj);
121
+ return TRUE;
122
+ }
123
+
124
+ return FALSE;
125
+ }
126
+
127
+ gboolean
128
+ rbgobj_convert_robj2instance(GType type, VALUE obj, gpointer *result)
129
+ {
130
+ RGConvertTable *table;
131
+
132
+ table = rbgobj_convert_lookup(type);
133
+ if (table && table->robj2instance) {
134
+ *result = table->robj2instance(obj);
135
+ return TRUE;
136
+ }
137
+
138
+ return FALSE;
139
+ }
140
+
141
+ gboolean
142
+ rbgobj_convert_instance2robj(GType type, gpointer instance, VALUE *result)
143
+ {
144
+ RGConvertTable *table;
145
+
146
+ table = rbgobj_convert_lookup(type);
147
+ if (table && table->instance2robj) {
148
+ *result = table->instance2robj(instance);
149
+ return TRUE;
150
+ }
151
+
152
+ return FALSE;
153
+ }
154
+
155
+ gboolean
156
+ rbgobj_convert_unref(GType type, gpointer instance)
157
+ {
158
+ RGConvertTable *table;
159
+
160
+ table = rbgobj_convert_lookup(type);
161
+ if (table && table->unref) {
162
+ table->unref(instance);
163
+ return TRUE;
164
+ }
165
+
166
+ return FALSE;
167
+ }
@@ -0,0 +1,961 @@
1
+ /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
2
+ /**********************************************************************
3
+
4
+ rbgobj_enums.c -
5
+
6
+ $Author: ktou $
7
+ $Date: 2007/08/08 11:53:09 $
8
+ created at: Sat Jul 27 16:56:01 JST 2002
9
+
10
+ Copyright (C) 2004-2006 Ruby-GNOME2 Project Team
11
+ Copyright (C) 2002,2003 Masahiro Sakai
12
+ **********************************************************************/
13
+
14
+ #include "rbgprivate.h"
15
+ #include <ctype.h>
16
+
17
+ VALUE rbgobj_cEnum, rbgobj_cFlags;
18
+
19
+ static ID id_new;
20
+ static ID id_module_eval;
21
+ static ID id_to_s;
22
+ static ID id_or;
23
+
24
+ /**********************************************************************/
25
+
26
+ typedef struct {
27
+ char *original;
28
+ char *replacement;
29
+ } constant_map;
30
+
31
+ static GSList *rbgobj_cmap = NULL;
32
+
33
+ static gchar *
34
+ nick_to_const_name(const gchar *nick)
35
+ {
36
+ gchar *const_name;
37
+ gchar *p;
38
+
39
+ if (!nick)
40
+ return NULL;
41
+
42
+ const_name = g_strdup(nick);
43
+ for (p = const_name; *p; p++) {
44
+ if (*p == '-' || *p == ' ')
45
+ *p = '_';
46
+ else
47
+ *p = g_ascii_toupper(*p);
48
+ }
49
+ return const_name;
50
+ }
51
+
52
+ static VALUE
53
+ resolve_enum_value(VALUE klass, VALUE nick)
54
+ {
55
+ VALUE value = Qnil;
56
+ gchar *const_nick;
57
+ ID const_nick_id;
58
+
59
+ if (RVAL2CBOOL(rb_obj_is_kind_of(nick, klass)))
60
+ return nick;
61
+
62
+ nick = rb_funcall(nick, id_to_s, 0);
63
+ const_nick = nick_to_const_name(RVAL2CSTR(nick));
64
+ const_nick_id = rb_intern(const_nick);
65
+ if (rb_const_defined(klass, const_nick_id)) {
66
+ value = rb_const_get(klass, const_nick_id);
67
+ }
68
+ g_free(const_nick);
69
+
70
+ return value;
71
+ }
72
+
73
+ static VALUE
74
+ resolve_flags_value(VALUE klass, VALUE nick_or_nicks)
75
+ {
76
+ int i, len;
77
+ VALUE flags_value;
78
+
79
+ if (!RVAL2CBOOL(rb_obj_is_kind_of(nick_or_nicks, rb_cArray)))
80
+ return resolve_enum_value(klass, nick_or_nicks);
81
+
82
+ len = RARRAY_LEN(nick_or_nicks);
83
+ flags_value = rb_funcall(klass, id_new, 0);
84
+ for (i = 0; i < len; i++) {
85
+ VALUE value;
86
+
87
+ value = resolve_enum_value(klass, RARRAY_PTR(nick_or_nicks)[i]);
88
+ if (NIL_P(value))
89
+ return Qnil;
90
+
91
+ flags_value = rb_funcall(flags_value, id_or, 1, value);
92
+ }
93
+
94
+ return flags_value;
95
+ }
96
+
97
+ static gint
98
+ rbgobj_constant_find(constant_map *a, char *name)
99
+ {
100
+ return strcmp(a->original, name);
101
+ }
102
+
103
+ void
104
+ rbgobj_constant_remap(const char *original, const char *replacement)
105
+ {
106
+ constant_map *map = g_new(constant_map,1);
107
+
108
+ map -> original = g_strdup(original);
109
+ map -> replacement = g_strdup(replacement);
110
+
111
+ rbgobj_cmap = g_slist_append(rbgobj_cmap, map);
112
+ }
113
+
114
+ static char *
115
+ rbgobj_constant_lookup(const char *name)
116
+ {
117
+ GSList *p = rbgobj_cmap;
118
+
119
+ p = g_slist_find_custom(rbgobj_cmap, name,
120
+ (GCompareFunc)rbgobj_constant_find);
121
+ if (p)
122
+ {
123
+ char *replacement;
124
+ constant_map *map;
125
+
126
+ map = (constant_map*) p -> data;
127
+ rbgobj_cmap = g_slist_delete_link(rbgobj_cmap, p);
128
+ replacement = map -> replacement;
129
+
130
+ g_free(map -> original);
131
+ g_free(map);
132
+
133
+ return replacement;
134
+ }
135
+ return NULL;
136
+ }
137
+
138
+ void
139
+ rbgobj_define_const(VALUE mod, const char *name,
140
+ VALUE value)
141
+ {
142
+ if (name[0] >= 'A' && name[0] <= 'Z')
143
+ {
144
+ rb_define_const(mod, name, value);
145
+ }
146
+ else
147
+ {
148
+ char *new_name = rbgobj_constant_lookup(name);
149
+
150
+ if (new_name)
151
+ {
152
+ rb_define_const(mod, new_name, value);
153
+ g_free(new_name);
154
+ }
155
+ else
156
+ {
157
+ rb_warn("Invalid constant name '%s' - skipped", name);
158
+ }
159
+ }
160
+ }
161
+
162
+ static void
163
+ rbgobj_enum_add_constants(VALUE mod, GType enum_type,
164
+ const gchar *strip_prefix)
165
+ {
166
+ GEnumClass *gclass;
167
+ int i;
168
+ int prefix_len = strlen(strip_prefix);
169
+
170
+ gclass = G_ENUM_CLASS(g_type_class_ref(enum_type));
171
+
172
+ for (i = 0; i < gclass->n_values; i++) {
173
+ const GEnumValue* value = &gclass->values[i];
174
+
175
+ if (strncmp(value->value_name, strip_prefix, prefix_len)) {
176
+ g_warning("\"%s\" doesn't have prefix \"%s\"",
177
+ value->value_name, strip_prefix);
178
+ } else {
179
+ const char* name = value->value_name + prefix_len;
180
+ rbgobj_define_const(mod, name,
181
+ rbgobj_make_enum(value->value, enum_type));
182
+ }
183
+ }
184
+
185
+ g_type_class_unref(gclass);
186
+ }
187
+
188
+ static void
189
+ rbgobj_flags_add_constants(VALUE mod, GType flags_type,
190
+ const gchar *strip_prefix)
191
+ {
192
+ GFlagsClass *gclass;
193
+ int i;
194
+ int prefix_len = strlen(strip_prefix);
195
+
196
+ gclass = G_FLAGS_CLASS(g_type_class_ref(flags_type));
197
+
198
+ for (i = 0; i < gclass->n_values; i++) {
199
+ const GFlagsValue* value = &gclass->values[i];
200
+
201
+ if (strncmp(value->value_name, strip_prefix, prefix_len)) {
202
+ g_warning("\"%s\" doesn't have prefix \"%s\"",
203
+ value->value_name, strip_prefix);
204
+ } else {
205
+ const char* name = value->value_name + prefix_len;
206
+ rbgobj_define_const(mod, name,
207
+ rbgobj_make_flags(value->value, flags_type));
208
+
209
+ }
210
+ }
211
+
212
+ g_type_class_unref(gclass);
213
+ }
214
+
215
+ void
216
+ rbgobj_add_constants(VALUE mod, GType type, const gchar *strip_prefix)
217
+ {
218
+ if (G_TYPE_IS_ENUM(type)) {
219
+ rbgobj_enum_add_constants(mod, type, strip_prefix);
220
+ } else if (G_TYPE_IS_FLAGS(type)) {
221
+ rbgobj_flags_add_constants(mod, type, strip_prefix);
222
+ } else {
223
+ g_warning("`%s' is not an enum/flags type", g_type_name(type));
224
+ }
225
+ }
226
+
227
+ /**********************************************************************/
228
+
229
+ typedef struct {
230
+ GEnumClass* gclass;
231
+ gint value;
232
+ GEnumValue* info;
233
+ } enum_holder;
234
+
235
+ static void
236
+ enum_free(enum_holder* p)
237
+ {
238
+ g_type_class_unref(p->gclass);
239
+ free(p);
240
+ }
241
+
242
+ static enum_holder*
243
+ enum_get_holder(VALUE obj)
244
+ {
245
+ enum_holder* p;
246
+ Data_Get_Struct(obj, enum_holder, p);
247
+ return p;
248
+ }
249
+
250
+ static VALUE
251
+ make_enum(gint n, VALUE klass)
252
+ {
253
+ return rb_funcall(klass, id_new, 1, INT2NUM(n));
254
+ }
255
+
256
+ VALUE
257
+ rbgobj_make_enum(gint n, GType gtype)
258
+ {
259
+ return make_enum(n, GTYPE2CLASS(gtype));
260
+ }
261
+
262
+ gint
263
+ rbgobj_get_enum(VALUE obj, GType gtype)
264
+ {
265
+ VALUE klass;
266
+
267
+ if (!g_type_is_a(gtype, G_TYPE_ENUM))
268
+ rb_raise(rb_eTypeError, "%s is not a %s: %s",
269
+ g_type_name(gtype), g_type_name(G_TYPE_ENUM),
270
+ RBG_INSPECT(obj));
271
+
272
+ /* for compatibility */
273
+ if (rb_obj_is_kind_of(obj, rb_cInteger))
274
+ obj = rbgobj_make_enum(NUM2INT(obj), gtype);
275
+
276
+ klass = GTYPE2CLASS(gtype);
277
+
278
+ if (!rb_obj_is_kind_of(obj, klass)) {
279
+ VALUE enum_value;
280
+
281
+ enum_value = resolve_enum_value(klass, obj);
282
+ if (!NIL_P(enum_value))
283
+ obj = enum_value;
284
+ }
285
+
286
+ if (rb_obj_is_kind_of(obj, klass))
287
+ return enum_get_holder(obj)->value;
288
+ else
289
+ rb_raise(rb_eTypeError, "not a %s: %s",
290
+ rb_class2name(klass), RBG_INSPECT(obj));
291
+ }
292
+
293
+ /**********************************************************************/
294
+
295
+ void
296
+ rbgobj_init_enum_class(VALUE klass)
297
+ {
298
+ GEnumClass* gclass = g_type_class_ref(CLASS2GTYPE(klass));
299
+ int i;
300
+
301
+ for (i = 0; i < gclass->n_values; i++) {
302
+ GEnumValue* entry = &(gclass->values[i]);
303
+ gchar *const_nick_name;
304
+
305
+ const_nick_name = nick_to_const_name(entry->value_nick);
306
+
307
+ #if 0
308
+ {
309
+ ID id = rb_intern(const_nick_name);
310
+ if (rb_is_const_id(id)) {
311
+ VALUE value;
312
+
313
+ value = make_enum(entry->value, klass);
314
+ rb_define_const(klass, const_nick_name, value);
315
+ }
316
+ }
317
+ #else
318
+ {
319
+ if (const_nick_name) {
320
+ VALUE value;
321
+
322
+ value = make_enum(entry->value, klass);
323
+ rbgobj_define_const(klass, const_nick_name, value);
324
+ }
325
+ }
326
+ #endif
327
+
328
+ g_free(const_nick_name);
329
+ }
330
+
331
+ g_type_class_unref(gclass);
332
+ }
333
+
334
+ static VALUE
335
+ enum_s_range(self)
336
+ VALUE self;
337
+ {
338
+ GEnumClass* gclass = g_type_class_ref(CLASS2GTYPE(self));
339
+ VALUE result = rb_range_new(INT2NUM(gclass->minimum),
340
+ INT2NUM(gclass->maximum),
341
+ FALSE);
342
+ g_type_class_unref(gclass);
343
+ return result;
344
+ }
345
+
346
+ static VALUE
347
+ enum_s_values(VALUE self)
348
+ {
349
+ GEnumClass *gclass;
350
+ VALUE result;
351
+ int i;
352
+
353
+ gclass = g_type_class_ref(CLASS2GTYPE(self));;
354
+ result = rb_ary_new();
355
+ for (i = 0; i < gclass->n_values; i++) {
356
+ GEnumValue *p = &(gclass->values[i]);
357
+ rb_ary_push(result, make_enum(p->value, self));
358
+ }
359
+
360
+ g_type_class_unref(gclass);
361
+ return result;
362
+ }
363
+
364
+ static VALUE
365
+ enum_s_allocate(VALUE self)
366
+ {
367
+ GType gtype = CLASS2GTYPE(self);
368
+
369
+ if (G_TYPE_IS_ABSTRACT(gtype)) {
370
+ rb_raise(rb_eTypeError, "abstract class");
371
+ } else {
372
+ enum_holder* p;
373
+ VALUE result = Data_Make_Struct(self, enum_holder, NULL, enum_free, p);
374
+ p->gclass = g_type_class_ref(gtype);
375
+ p->info = NULL;
376
+ return result;
377
+ }
378
+ }
379
+
380
+ static VALUE
381
+ enum_initialize(VALUE self, VALUE arg)
382
+ {
383
+ enum_holder* p = enum_get_holder(self);
384
+
385
+ if (rb_respond_to(arg, rb_intern("to_str"))) {
386
+ const char* str = StringValuePtr(arg);
387
+ p->info = g_enum_get_value_by_name(p->gclass, str);
388
+ if (! p->info)
389
+ p->info = g_enum_get_value_by_nick(p->gclass, str);
390
+ if (! p->info)
391
+ rb_raise(rb_eArgError, "invalid argument");
392
+ } else {
393
+ p->value = NUM2INT(arg);
394
+ p->info = g_enum_get_value(p->gclass, p->value);
395
+ }
396
+
397
+ return Qnil;
398
+ }
399
+
400
+ static VALUE
401
+ enum_to_i(VALUE self)
402
+ {
403
+ enum_holder* p = enum_get_holder(self);
404
+ return INT2NUM(p->value);
405
+ }
406
+
407
+ static VALUE
408
+ enum_name(VALUE self)
409
+ {
410
+ enum_holder* p = enum_get_holder(self);
411
+ return p->info ? rb_str_new2(p->info->value_name) : Qnil;
412
+ }
413
+
414
+ static VALUE
415
+ enum_nick(VALUE self)
416
+ {
417
+ enum_holder* p = enum_get_holder(self);
418
+ return p->info ? rb_str_new2(p->info->value_nick) : Qnil;
419
+ }
420
+
421
+ static VALUE
422
+ enum_inspect(VALUE self)
423
+ {
424
+ const char* cname = rb_class2name(CLASS_OF(self));
425
+ enum_holder* p = enum_get_holder(self);
426
+ gchar* str;
427
+ VALUE result;
428
+
429
+ if (p->info)
430
+ str = g_strdup_printf("#<%s %s>",
431
+ cname, p->info->value_nick);
432
+ else
433
+ str = g_strdup_printf("#<%s %d>",
434
+ cname, p->value);
435
+ result = rb_str_new2(str);
436
+ g_free(str);
437
+
438
+ return result;
439
+ }
440
+
441
+ static VALUE
442
+ enum_eqv(VALUE self, VALUE rhs)
443
+ {
444
+ enum_holder* p = enum_get_holder(self);
445
+ GType gtype = G_TYPE_FROM_CLASS(p->gclass);
446
+ if (CLASS_OF(rhs) != CLASS_OF(self) &&
447
+ !rb_obj_is_kind_of(rhs, rb_cInteger))
448
+ return Qnil;
449
+ return CBOOL2RVAL(rbgobj_get_enum(self, gtype) == rbgobj_get_enum(rhs, gtype));
450
+ }
451
+
452
+ static VALUE
453
+ enum_hash(VALUE self)
454
+ {
455
+ enum_holder* p = enum_get_holder(self);
456
+ return UINT2NUM(p->value ^ G_TYPE_FROM_CLASS(p->gclass));
457
+ }
458
+
459
+ static VALUE
460
+ enum_coerce(VALUE self, VALUE other)
461
+ {
462
+ enum_holder *holder;
463
+ GType gtype;
464
+
465
+ if (!rb_obj_is_kind_of(other, rb_cInteger))
466
+ rb_raise(rb_eTypeError, "can't coerce");
467
+
468
+ holder = enum_get_holder(self);
469
+ gtype = G_TYPE_FROM_CLASS(holder->gclass);
470
+ other = rbgobj_make_enum(NUM2INT(other), gtype);
471
+ return rb_ary_new3(2, other, self);
472
+ }
473
+
474
+ static void
475
+ Init_enum()
476
+ {
477
+ VALUE cEnum;
478
+
479
+ rbgobj_cEnum = G_DEF_CLASS(G_TYPE_ENUM, "Enum", mGLib);
480
+ cEnum = rbgobj_cEnum;
481
+
482
+ rb_define_singleton_method(cEnum, "gtype", generic_s_gtype, 0);
483
+ rb_define_method(cEnum, "gtype", generic_gtype, 0);
484
+
485
+ rb_define_singleton_method(cEnum, "range", enum_s_range, 0);
486
+ rb_define_singleton_method(cEnum, "values", enum_s_values, 0);
487
+
488
+ rb_define_alloc_func(cEnum, enum_s_allocate);
489
+
490
+ rb_define_method(cEnum, "initialize", enum_initialize, 1);
491
+ rb_define_method(cEnum, "to_i", enum_to_i, 0);
492
+ rb_define_method(cEnum, "name", enum_name, 0);
493
+ rb_define_method(cEnum, "nick", enum_nick, 0);
494
+
495
+ rb_define_method(cEnum, "inspect", enum_inspect, 0);
496
+ rb_define_method(cEnum, "==", enum_eqv, 1);
497
+ rb_define_method(cEnum, "hash", enum_hash, 0);
498
+ rb_define_method(cEnum, "eql?", enum_eqv, 1);
499
+
500
+ /* for compatibility */
501
+ rb_define_method(cEnum, "coerce", enum_coerce, 1);
502
+ rb_define_alias(cEnum, "to_int", "to_i");
503
+ }
504
+
505
+ /**********************************************************************/
506
+
507
+ typedef struct {
508
+ GFlagsClass* gclass;
509
+ guint value;
510
+ GFlagsValue* info;
511
+ } flags_holder;
512
+
513
+ static void
514
+ flags_free(enum_holder* p)
515
+ {
516
+ g_type_class_unref(p->gclass);
517
+ free(p);
518
+ }
519
+
520
+ static flags_holder*
521
+ flags_get_holder(VALUE obj)
522
+ {
523
+ flags_holder* p;
524
+ Data_Get_Struct(obj, flags_holder, p);
525
+ return p;
526
+ }
527
+
528
+ static VALUE
529
+ make_flags(guint n, VALUE klass)
530
+ {
531
+ return rb_funcall(klass, id_new, 1, UINT2NUM(n));
532
+ }
533
+
534
+ VALUE
535
+ rbgobj_make_flags(guint n, GType gtype)
536
+ {
537
+ return make_flags(n, GTYPE2CLASS(gtype));
538
+ }
539
+
540
+ guint
541
+ rbgobj_get_flags(VALUE obj, GType gtype)
542
+ {
543
+ VALUE klass;
544
+
545
+ if (!g_type_is_a(gtype, G_TYPE_FLAGS))
546
+ rb_raise(rb_eTypeError, "%s is not a %s",
547
+ g_type_name(gtype), g_type_name(G_TYPE_FLAGS));
548
+
549
+ /* for compatibility */
550
+ if (rb_obj_is_kind_of(obj, rb_cInteger))
551
+ obj = rbgobj_make_flags(NUM2UINT(obj), gtype);
552
+
553
+ klass = GTYPE2CLASS(gtype);
554
+
555
+ if (!rb_obj_is_kind_of(obj, klass)) {
556
+ VALUE flags_value = Qnil;
557
+
558
+ flags_value = resolve_flags_value(klass, obj);
559
+ if (!NIL_P(flags_value))
560
+ obj = flags_value;
561
+ }
562
+
563
+ if (rb_obj_is_kind_of(obj, klass))
564
+ return flags_get_holder(obj)->value;
565
+ else
566
+ rb_raise(rb_eTypeError, "not a %s: %s",
567
+ rb_class2name(klass), RBG_INSPECT(obj));
568
+ }
569
+
570
+ /**********************************************************************/
571
+
572
+ void
573
+ rbgobj_init_flags_class(VALUE klass)
574
+ {
575
+ GFlagsClass* gclass = g_type_class_ref(CLASS2GTYPE(klass));
576
+ GString* source = g_string_new(NULL);
577
+ int i;
578
+
579
+ for (i = 0; i < gclass->n_values; i++) {
580
+ GFlagsValue* entry = &(gclass->values[i]);
581
+ gchar* nick;
582
+ gchar* p;
583
+ gchar* replace_nick;
584
+
585
+ replace_nick = rbgobj_constant_lookup(entry->value_nick);
586
+ if (replace_nick){
587
+ nick = g_strdup(replace_nick);
588
+ } else {
589
+ nick = g_strdup(entry->value_nick);
590
+ }
591
+
592
+ for (p = nick; *p; p++)
593
+ if (*p == '-' || *p == ' ')
594
+ *p = '_';
595
+ else
596
+ *p = tolower(*p);
597
+
598
+ g_string_append_printf(
599
+ source,
600
+ "def %s%s?; self >= self.class.new(%d); end\n",
601
+ g_ascii_isdigit(nick[0]) ? "_" : "",
602
+ nick, entry->value);
603
+
604
+ for (p = nick; *p; p++)
605
+ *p = g_ascii_toupper(*p);
606
+
607
+ #if 0
608
+ {
609
+ ID id = rb_intern(nick);
610
+ if (rb_is_const_id(id)) {
611
+ rb_define_const(klass, nick, make_flags(entry->value, klass));
612
+ }
613
+ }
614
+ #else
615
+ {
616
+ rbgobj_define_const(klass, nick, make_flags(entry->value, klass));
617
+ }
618
+ #endif
619
+
620
+ g_free(nick);
621
+ }
622
+
623
+ rb_funcall(klass, id_module_eval, 1, rb_str_new2(source->str));
624
+ g_string_free(source, TRUE);
625
+
626
+ g_type_class_unref(gclass);
627
+ }
628
+
629
+ static VALUE
630
+ flags_s_mask(VALUE klass)
631
+ {
632
+ GFlagsClass* gclass = g_type_class_ref(CLASS2GTYPE(klass));
633
+ VALUE result = UINT2NUM(gclass->mask);
634
+ g_type_class_unref(gclass);
635
+ return result;
636
+ }
637
+
638
+ static VALUE
639
+ flags_s_values(VALUE klass)
640
+ {
641
+ GFlagsClass *gclass;
642
+ VALUE result;
643
+ int i;
644
+
645
+ gclass = g_type_class_ref(CLASS2GTYPE(klass));
646
+ result = rb_ary_new();
647
+ for (i = 0; i < gclass->n_values; i++) {
648
+ GFlagsValue *p = &(gclass->values[i]);
649
+ rb_ary_push(result, make_flags(p->value, klass));
650
+ }
651
+ g_type_class_unref(gclass);
652
+
653
+ return result;
654
+ }
655
+
656
+ static VALUE
657
+ flags_s_allocate(VALUE self)
658
+ {
659
+ GType gtype = CLASS2GTYPE(self);
660
+
661
+ if (G_TYPE_IS_ABSTRACT(gtype)) {
662
+ rb_raise(rb_eTypeError, "abstract class");
663
+ } else {
664
+ flags_holder* p;
665
+ VALUE result = Data_Make_Struct(self, flags_holder, NULL, flags_free, p);
666
+ p->gclass = g_type_class_ref(gtype);
667
+ p->value = 0;
668
+ p->info = NULL;
669
+ return result;
670
+ }
671
+ }
672
+
673
+ static VALUE
674
+ flags_initialize(int argc, VALUE* argv, VALUE self)
675
+ {
676
+ flags_holder* p = flags_get_holder(self);
677
+ VALUE arg;
678
+
679
+ rb_scan_args(argc, argv, "01", &arg);
680
+
681
+ if (argc == 0) {
682
+ p->value = 0;
683
+ } else {
684
+ if (rb_respond_to(arg, rb_intern("to_str"))) {
685
+ const char* str = StringValuePtr(arg);
686
+ p->info = g_flags_get_value_by_name(p->gclass, str);
687
+ if (!p->info)
688
+ p->info = g_flags_get_value_by_nick(p->gclass, str);
689
+ if (!p->info)
690
+ rb_raise(rb_eArgError, "invalid argument");
691
+ p->value = p->info->value;
692
+ } else {
693
+ p->value = NUM2UINT(arg);
694
+ }
695
+ }
696
+
697
+ if (!p->info) {
698
+ int i;
699
+ for (i = 0; i < p->gclass->n_values; i++){
700
+ GFlagsValue* val = &(p->gclass->values[i]);
701
+ if (val->value == p->value){
702
+ p->info = val;
703
+ break;
704
+ }
705
+ }
706
+ }
707
+
708
+ return Qnil;
709
+ }
710
+
711
+ static VALUE
712
+ flags_to_i(VALUE self)
713
+ {
714
+ flags_holder* p = flags_get_holder(self);
715
+ return UINT2NUM(p->value);
716
+ }
717
+
718
+ static VALUE
719
+ flags_name(VALUE self)
720
+ {
721
+ flags_holder* p = flags_get_holder(self);
722
+ return p->info ? rb_str_new2(p->info->value_name) : Qnil;
723
+ }
724
+
725
+ static VALUE
726
+ flags_nick(VALUE self)
727
+ {
728
+ flags_holder* p = flags_get_holder(self);
729
+ return p->info ? rb_str_new2(p->info->value_nick) : Qnil;
730
+ }
731
+
732
+ static VALUE
733
+ flags_compare(VALUE self, VALUE rhs)
734
+ {
735
+ flags_holder* p = flags_get_holder(self);
736
+ GType gtype = G_TYPE_FROM_CLASS(p->gclass);
737
+ guint rhs_val;
738
+
739
+ if (CLASS_OF(rhs) != CLASS_OF(self) &&
740
+ !rb_obj_is_kind_of(rhs, rb_cInteger))
741
+ return Qnil;
742
+
743
+ rhs_val = rbgobj_get_flags(rhs, gtype);
744
+
745
+ if (p->value == rhs_val)
746
+ return INT2FIX(0);
747
+ else if ((p->value & rhs_val) == rhs_val)
748
+ return INT2FIX(1);
749
+ else if ((p->value & rhs_val) == p->value)
750
+ return INT2FIX(-1);
751
+ else
752
+ return Qnil;
753
+ }
754
+
755
+ static VALUE
756
+ flags_eqv(VALUE self, VALUE rhs)
757
+ {
758
+ flags_holder* p = flags_get_holder(self);
759
+ GType gtype = G_TYPE_FROM_CLASS(p->gclass);
760
+ guint rhs_val;
761
+
762
+ if (CLASS_OF(rhs) != CLASS_OF(self) &&
763
+ !rb_obj_is_kind_of(rhs, rb_cInteger))
764
+ return Qnil;
765
+
766
+ rhs_val = rbgobj_get_flags(rhs, gtype);
767
+ return CBOOL2RVAL(p->value == rhs_val);
768
+ }
769
+
770
+ static VALUE
771
+ flags_gt_eq(VALUE self, VALUE rhs)
772
+ {
773
+ flags_holder* p = flags_get_holder(self);
774
+ GType gtype = G_TYPE_FROM_CLASS(p->gclass);
775
+ guint rhs_val;
776
+
777
+ if (CLASS_OF(rhs) != CLASS_OF(self) &&
778
+ !rb_obj_is_kind_of(rhs, rb_cInteger))
779
+ return Qnil;
780
+
781
+ rhs_val = rbgobj_get_flags(rhs, gtype);
782
+ return CBOOL2RVAL((p->value & rhs_val) == rhs_val);
783
+ }
784
+
785
+ static VALUE
786
+ flags_lt_eq(VALUE self, VALUE rhs)
787
+ {
788
+ flags_holder* p = flags_get_holder(self);
789
+ GType gtype = G_TYPE_FROM_CLASS(p->gclass);
790
+ guint rhs_val;
791
+
792
+ if (CLASS_OF(rhs) != CLASS_OF(self) &&
793
+ !rb_obj_is_kind_of(rhs, rb_cInteger))
794
+ return Qnil;
795
+
796
+ rhs_val = rbgobj_get_flags(rhs, gtype);
797
+ return CBOOL2RVAL((p->value & rhs_val) == p->value);
798
+ }
799
+
800
+ static VALUE
801
+ flags_gt(VALUE self, VALUE rhs)
802
+ {
803
+ flags_holder* p = flags_get_holder(self);
804
+ GType gtype = G_TYPE_FROM_CLASS(p->gclass);
805
+ guint rhs_val;
806
+
807
+ if (CLASS_OF(rhs) != CLASS_OF(self) &&
808
+ !rb_obj_is_kind_of(rhs, rb_cInteger))
809
+ return Qnil;
810
+
811
+ rhs_val = rbgobj_get_flags(rhs, gtype);
812
+ return CBOOL2RVAL((p->value & rhs_val) == rhs_val &&
813
+ p->value != rhs_val);
814
+ }
815
+
816
+ static VALUE
817
+ flags_lt(VALUE self, VALUE rhs)
818
+ {
819
+ flags_holder* p = flags_get_holder(self);
820
+ GType gtype = G_TYPE_FROM_CLASS(p->gclass);
821
+ guint rhs_val;
822
+
823
+ if (CLASS_OF(rhs) != CLASS_OF(self) &&
824
+ !rb_obj_is_kind_of(rhs, rb_cInteger))
825
+ return Qnil;
826
+
827
+ rhs_val = rbgobj_get_flags(rhs, gtype);
828
+ return CBOOL2RVAL((p->value & rhs_val) == p->value &&
829
+ p->value != rhs_val);
830
+ }
831
+
832
+ static VALUE
833
+ flags_not(VALUE self, VALUE rhs)
834
+ {
835
+ flags_holder* p = flags_get_holder(self);
836
+ return rbgobj_make_flags((~ p->value) & p->gclass->mask,
837
+ G_TYPE_FROM_CLASS(p->gclass));
838
+ }
839
+
840
+ #define LIFT_BINARY_OP(funcname, op) \
841
+ static VALUE \
842
+ funcname(VALUE self, VALUE rhs) \
843
+ { \
844
+ flags_holder* p = flags_get_holder(self); \
845
+ GType gtype = G_TYPE_FROM_CLASS(p->gclass); \
846
+ return rbgobj_make_flags(p->value op rbgobj_get_flags(rhs, gtype), \
847
+ gtype); \
848
+ }
849
+
850
+ LIFT_BINARY_OP(flags_and, &)
851
+ LIFT_BINARY_OP(flags_or, |)
852
+ LIFT_BINARY_OP(flags_xor, ^)
853
+
854
+ static VALUE
855
+ flags_minus(VALUE self, VALUE rhs)
856
+ {
857
+ flags_holder* p = flags_get_holder(self);
858
+ GType gtype = G_TYPE_FROM_CLASS(p->gclass);
859
+ return rbgobj_make_flags(p->value & ~rbgobj_get_flags(rhs, gtype),
860
+ gtype);
861
+ }
862
+
863
+ static VALUE
864
+ flags_empty_p(VALUE self)
865
+ {
866
+ flags_holder* p = flags_get_holder(self);
867
+ return CBOOL2RVAL(p->value == 0);
868
+ }
869
+
870
+ static VALUE
871
+ flags_hash(VALUE self)
872
+ {
873
+ flags_holder* p = flags_get_holder(self);
874
+ return UINT2NUM(p->value ^ G_TYPE_FROM_CLASS(p->gclass));
875
+ }
876
+
877
+ static VALUE
878
+ flags_coerce(VALUE self, VALUE other)
879
+ {
880
+ flags_holder *holder;
881
+ GType gtype;
882
+
883
+ if (rb_obj_is_kind_of(other, rb_cInteger))
884
+ rb_raise(rb_eTypeError, "can't coerce");
885
+
886
+ holder = flags_get_holder(self);
887
+ gtype = G_TYPE_FROM_CLASS(holder->gclass);
888
+ other = rbgobj_make_flags(NUM2UINT(other), gtype);
889
+ return rb_ary_new3(2, other, self);
890
+ }
891
+
892
+ static VALUE
893
+ flags_nonzero_p(VALUE self)
894
+ {
895
+ flags_holder* p = flags_get_holder(self);
896
+ return CBOOL2RVAL(p->value != 0);
897
+ }
898
+
899
+ static void
900
+ Init_flags()
901
+ {
902
+ VALUE cFlags;
903
+
904
+ rbgobj_cFlags = G_DEF_CLASS(G_TYPE_FLAGS, "Flags", mGLib);
905
+ cFlags = rbgobj_cFlags;
906
+
907
+ rb_define_singleton_method(cFlags, "gtype", generic_s_gtype, 0);
908
+ rb_define_method(cFlags, "gtype", generic_gtype, 0);
909
+
910
+ rb_define_singleton_method(cFlags, "mask", flags_s_mask, 0);
911
+ rb_define_singleton_method(cFlags, "values", flags_s_values, 0);
912
+
913
+ rb_define_alloc_func(cFlags, flags_s_allocate);
914
+
915
+ rb_define_method(cFlags, "initialize", flags_initialize, -1);
916
+
917
+ rb_define_method(cFlags, "to_i", flags_to_i, 0);
918
+ rb_define_alias(cFlags, "to_int", "to_i");
919
+ rb_define_method(cFlags, "name", flags_name, 0);
920
+ rb_define_method(cFlags, "nick", flags_nick, 0);
921
+
922
+ /*
923
+ rb_define_method(cFlags, "inspect", flags_inspect, 0);
924
+ */
925
+
926
+ rb_define_method(cFlags, "<=>", flags_compare, 1);
927
+ rb_define_method(cFlags, "==", flags_eqv, 1);
928
+ rb_define_method(cFlags, ">=", flags_gt_eq, 1);
929
+ rb_define_method(cFlags, "<=", flags_lt_eq, 1);
930
+ rb_define_method(cFlags, ">", flags_gt, 1);
931
+ rb_define_method(cFlags, "<", flags_lt, 1);
932
+ rb_define_method(cFlags, "~", flags_not, 0);
933
+ rb_define_method(cFlags, "&", flags_and, 1);
934
+ rb_define_method(cFlags, "|", flags_or, 1);
935
+ rb_define_method(cFlags, "^", flags_xor, 1);
936
+ rb_define_method(cFlags, "-", flags_minus, 1);
937
+
938
+ rb_define_method(cFlags, "empty?", flags_empty_p, 0);
939
+
940
+ rb_define_method(cFlags, "hash", flags_hash, 0);
941
+ rb_define_method(cFlags, "eql?", flags_eqv, 1);
942
+
943
+ /* for compatibility */
944
+ rb_define_method(cFlags, "coerce", flags_coerce, 1);
945
+ rb_define_method(cFlags, "zero?", flags_empty_p, 0);
946
+ rb_define_method(cFlags, "nonzero?", flags_nonzero_p, 0);
947
+ }
948
+
949
+ /**********************************************************************/
950
+
951
+ void
952
+ Init_gobject_genums()
953
+ {
954
+ id_module_eval = rb_intern("module_eval");
955
+ id_new = rb_intern("new");
956
+ id_to_s = rb_intern("to_s");
957
+ id_or = rb_intern("|");
958
+
959
+ Init_enum();
960
+ Init_flags();
961
+ }