glib2 0.20.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ }