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,963 @@
1
+ /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
2
+ /**********************************************************************
3
+
4
+ rbgobj_signal.c -
5
+
6
+ $Author: ssimons $
7
+ $Date: 2007/07/25 17:04:28 $
8
+ created at: Sat Jul 27 16:56:01 JST 2002
9
+
10
+ Copyright (C) 2002-2004 Ruby-GNOME2 Project Team
11
+ Copyright (C) 2002,2003 Masahiro Sakai
12
+
13
+ **********************************************************************/
14
+
15
+ #include "rbgprivate.h"
16
+
17
+ static VALUE cSignal;
18
+ VALUE rbgobj_signal_wrap(guint sig_id);
19
+
20
+ #define default_handler_method_prefix "signal_do_"
21
+
22
+ /**********************************************************************/
23
+
24
+ static VALUE signal_func_table;
25
+
26
+ void
27
+ rbgobj_set_signal_func(klass, sig_name, func)
28
+ VALUE klass;
29
+ gchar* sig_name;
30
+ GValToRValSignalFunc func;
31
+ {
32
+ VALUE obj = Data_Wrap_Struct(rb_cData, NULL, NULL, func);
33
+ guint signal_id = g_signal_lookup(sig_name, CLASS2GTYPE(klass));
34
+ rb_hash_aset(signal_func_table, UINT2NUM(signal_id), obj);
35
+ }
36
+
37
+ GValToRValSignalFunc
38
+ rbgobj_get_signal_func(guint signal_id)
39
+ {
40
+ GValToRValSignalFunc func = NULL;
41
+ VALUE func_obj = rb_hash_aref(signal_func_table, UINT2NUM(signal_id));
42
+ if (!NIL_P(func_obj))
43
+ Data_Get_Struct(func_obj, void, func);
44
+ return func;
45
+ }
46
+
47
+ /**********************************************************************/
48
+
49
+ static VALUE eNoSignalError;
50
+
51
+ // FIXME: use rb_protect
52
+ static gboolean
53
+ accumulator_func(GSignalInvocationHint* ihint,
54
+ GValue* return_accu,
55
+ const GValue* handler_return,
56
+ gpointer data)
57
+ {
58
+ VALUE proc = (VALUE)data;
59
+ VALUE val = GVAL2RVAL(return_accu);
60
+ VALUE new = GVAL2RVAL(handler_return);
61
+ VALUE hint = Qnil; // FIXME
62
+ VALUE tmp;
63
+ gboolean continue_emission = TRUE;
64
+
65
+ tmp = rb_funcall(proc, rb_intern("call"), 3, hint, val, new);
66
+ /* FIXME */
67
+ if (TYPE(tmp) == T_ARRAY) {
68
+ continue_emission = RVAL2CBOOL(rb_ary_entry(tmp, 0));
69
+ val = rb_ary_entry(tmp, 1);
70
+ } else {
71
+ val = tmp;
72
+ }
73
+ rbgobj_rvalue_to_gvalue(val, return_accu);
74
+
75
+ return continue_emission;
76
+ }
77
+
78
+ static VALUE
79
+ gobj_s_signal_new(int argc, VALUE* argv, VALUE self)
80
+ {
81
+ const RGObjClassInfo* cinfo = rbgobj_lookup_class(self);
82
+ VALUE signal_name, signal_flags, accumulator, return_type, params;
83
+ GClosure* class_closure;
84
+ GType* param_types;
85
+ guint n_params;
86
+ int i;
87
+ guint sig;
88
+
89
+ rb_scan_args(argc, argv, "4*", &signal_name, &signal_flags,
90
+ &accumulator, &return_type, &params);
91
+
92
+ if (cinfo->klass != self)
93
+ rb_raise(rb_eTypeError, "%s isn't registerd class",
94
+ rb_class2name(self));
95
+
96
+ if (SYMBOL_P(signal_name))
97
+ signal_name = rb_str_new2(rb_id2name(SYM2ID(signal_name)));
98
+ else
99
+ StringValue(signal_name);
100
+
101
+ {
102
+ VALUE factory;
103
+ VALUE proc;
104
+ ID method_id;
105
+
106
+ method_id = rb_to_id(rb_str_concat(rb_str_new2(default_handler_method_prefix), signal_name));
107
+
108
+ factory = rb_eval_string(
109
+ "lambda{|klass, id|\n"
110
+ " lambda{|instance,*args|\n"
111
+ " klass.instance_method(id).bind(instance).call(*args)\n"
112
+ " }\n"
113
+ "}\n");
114
+ proc = rb_funcall(factory, rb_intern("call"), 2, self, ID2SYM(method_id));
115
+
116
+ class_closure = g_rclosure_new(proc, Qnil, NULL);
117
+ g_rclosure_attach(class_closure, self);
118
+ }
119
+
120
+ if (NIL_P(params)) {
121
+ n_params = 0;
122
+ param_types = NULL;
123
+ } else {
124
+ n_params = RARRAY_LEN(params);
125
+ param_types = ALLOCA_N(GType, n_params);
126
+ for (i = 0; i < n_params; i++)
127
+ param_types[i] = rbgobj_gtype_get(RARRAY_PTR(params)[i]);
128
+ }
129
+
130
+ sig = g_signal_newv(StringValuePtr(signal_name),
131
+ cinfo->gtype,
132
+ NUM2INT(signal_flags),
133
+ class_closure,
134
+ NIL_P(accumulator) ? NULL : accumulator_func,
135
+ NIL_P(accumulator) ? NULL : (gpointer)accumulator,
136
+ NULL, /* c_marshaller */
137
+ rbgobj_gtype_get(return_type),
138
+ n_params,
139
+ param_types);
140
+
141
+ if (!sig)
142
+ rb_raise(rb_eRuntimeError, "g_signal_newv failed");
143
+
144
+ if (!NIL_P(accumulator))
145
+ G_RELATIVE(self, accumulator); /* FIXME */
146
+
147
+ return rbgobj_signal_wrap(sig);
148
+ }
149
+
150
+ static void
151
+ _signal_list(VALUE result, GType gtype)
152
+ {
153
+ guint n_ids, i;
154
+ guint* ids = g_signal_list_ids(gtype, &n_ids);
155
+ for (i = 0; i < n_ids; i++)
156
+ rb_ary_push(result, rb_str_new2(g_signal_name(ids[i])));
157
+ g_free(ids);
158
+ }
159
+
160
+ static VALUE
161
+ gobj_s_signals(int argc, VALUE* argv, VALUE self)
162
+ {
163
+ GType gtype;
164
+ VALUE inherited_too, result;
165
+
166
+ if (rb_scan_args(argc, argv, "01", &inherited_too) == 0)
167
+ inherited_too = Qtrue;
168
+ gtype = CLASS2GTYPE(self);
169
+ result = rb_ary_new();
170
+
171
+ if (RVAL2CBOOL(inherited_too)){
172
+ guint n_interfaces, i;
173
+ GType* interfaces = g_type_interfaces(gtype, &n_interfaces);
174
+ for (i = 0; i < n_interfaces; i++)
175
+ _signal_list(result, interfaces[i]);
176
+ g_free(interfaces);
177
+
178
+ for (; gtype; gtype = g_type_parent(gtype))
179
+ _signal_list(result, gtype);
180
+ } else if (GTYPE2CLASS(gtype) == self) {
181
+ _signal_list(result, gtype);
182
+ }
183
+
184
+ return result;
185
+ }
186
+
187
+ static VALUE
188
+ gobj_s_signal(VALUE self, VALUE name)
189
+ {
190
+ const char* sig_name;
191
+ guint sig_id;
192
+
193
+ if (SYMBOL_P(name))
194
+ sig_name = rb_id2name(SYM2ID(name));
195
+ else
196
+ sig_name = StringValuePtr(name);
197
+
198
+ sig_id = g_signal_lookup(sig_name, CLASS2GTYPE(self));
199
+ if (!sig_id)
200
+ rb_raise(eNoSignalError, "no such signal: %s", sig_name);
201
+
202
+ return rbgobj_signal_wrap(sig_id);
203
+ }
204
+
205
+ static VALUE
206
+ gobj_sig_has_handler_pending(argc, argv, self)
207
+ int argc;
208
+ VALUE *argv;
209
+ VALUE self;
210
+ {
211
+ VALUE sig, may_be_blocked;
212
+ const char* sig_name;
213
+ guint signal_id;
214
+ GQuark detail;
215
+
216
+ rb_scan_args(argc, argv, "11", &sig, &may_be_blocked);
217
+
218
+ if (SYMBOL_P(sig))
219
+ sig_name = rb_id2name(SYM2ID(sig));
220
+ else
221
+ sig_name = StringValuePtr(sig);
222
+
223
+ if (!g_signal_parse_name(sig_name, CLASS2GTYPE(CLASS_OF(self)), &signal_id, &detail, TRUE))
224
+ rb_raise(eNoSignalError, "no such signal: %s", sig_name);
225
+
226
+ return CBOOL2RVAL(g_signal_has_handler_pending(RVAL2GOBJ(self),
227
+ signal_id, detail,
228
+ RVAL2CBOOL(may_be_blocked)));
229
+ }
230
+
231
+ static VALUE
232
+ gobj_sig_connect_impl(after, argc, argv, self)
233
+ gboolean after;
234
+ int argc;
235
+ VALUE *argv;
236
+ VALUE self;
237
+ {
238
+ VALUE sig, rest;
239
+ int i;
240
+ GClosure* rclosure;
241
+ const char* sig_name;
242
+ guint signal_id;
243
+ GQuark detail;
244
+ VALUE func;
245
+ GObject *g_object;
246
+ gchar *tag;
247
+
248
+ rb_scan_args(argc, argv, "1*", &sig, &rest);
249
+
250
+ if (NIL_P(rest)) rest = rb_ary_new();
251
+
252
+ if (SYMBOL_P(sig))
253
+ sig_name = rb_id2name(SYM2ID(sig));
254
+ else
255
+ sig_name = StringValuePtr(sig);
256
+
257
+ if (!g_signal_parse_name(sig_name, CLASS2GTYPE(CLASS_OF(self)), &signal_id, &detail, TRUE))
258
+ rb_raise(eNoSignalError, "no such signal: %s", sig_name);
259
+
260
+ func = rb_block_proc();
261
+ rclosure = g_rclosure_new(func, rest,
262
+ rbgobj_get_signal_func(signal_id));
263
+ g_rclosure_attach((GClosure *)rclosure, self);
264
+ g_object = RVAL2GOBJ(self);
265
+ tag = g_strdup_printf("%s::%s",
266
+ G_OBJECT_CLASS_NAME(G_OBJECT_GET_CLASS(g_object)),
267
+ sig_name);
268
+ g_rclosure_set_tag((GClosure *)rclosure, tag);
269
+ g_free(tag);
270
+ i = g_signal_connect_closure_by_id(g_object, signal_id, detail, rclosure, after);
271
+
272
+ return INT2FIX(i);
273
+ }
274
+
275
+ static VALUE
276
+ gobj_sig_connect(argc, argv, self)
277
+ int argc;
278
+ VALUE *argv;
279
+ VALUE self;
280
+ {
281
+ return gobj_sig_connect_impl(FALSE, argc, argv, self);
282
+ }
283
+
284
+ static VALUE
285
+ gobj_sig_connect_after(argc, argv, self)
286
+ int argc;
287
+ VALUE *argv;
288
+ VALUE self;
289
+ {
290
+ return gobj_sig_connect_impl(TRUE, argc, argv, self);
291
+ }
292
+
293
+ #if 0
294
+ static VALUE
295
+ gobj_sig_get_invocation_hint(self)
296
+ VALUE self;
297
+ {
298
+ GSignalInvocationHint* hint;
299
+ hint = g_signal_get_invocation_hint(RVAL2GOBJ(self));
300
+ return rb_ary_new3(3,
301
+ rbgobj_signal_wrap(hint->signal_id),
302
+ hint->detail ? rb_str_new2(g_quark_to_string(hint->detail)) : Qnil,
303
+ INT2NUM(hint->run_type));
304
+ }
305
+ #endif
306
+
307
+ struct emit_arg{
308
+ VALUE self;
309
+ VALUE args;
310
+
311
+ GSignalQuery query;
312
+ GQuark detail;
313
+ GValueArray* instance_and_params;
314
+ };
315
+
316
+ static VALUE
317
+ emit_body(struct emit_arg* arg)
318
+ {
319
+ GValue param = { 0, };
320
+
321
+ g_value_init(&param, G_TYPE_FROM_INSTANCE(RVAL2GOBJ(arg->self)));
322
+ rbgobj_rvalue_to_gvalue(arg->self, &param);
323
+ g_value_array_append(arg->instance_and_params, &param);
324
+ g_value_unset(&param);
325
+
326
+ {
327
+ int i;
328
+ for (i = 0; i < arg->query.n_params; i++){
329
+ GType gtype = arg->query.param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE;
330
+
331
+ g_value_init(&param, gtype);
332
+
333
+ rbgobj_rvalue_to_gvalue(rb_ary_entry(arg->args, i), &param);
334
+ g_value_array_append(arg->instance_and_params, &param);
335
+ g_value_unset(&param);
336
+ }
337
+ }
338
+
339
+ {
340
+ gboolean use_ret = (arg->query.return_type != G_TYPE_NONE);
341
+ GValue return_value = {0,};
342
+
343
+ if (use_ret)
344
+ g_value_init(&return_value,
345
+ arg->query.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
346
+
347
+ g_signal_emitv(arg->instance_and_params->values,
348
+ arg->query.signal_id, arg->detail,
349
+ (use_ret) ? &return_value : NULL);
350
+
351
+ if (use_ret) {
352
+ VALUE ret = GVAL2RVAL(&return_value);
353
+ g_value_unset(&return_value);
354
+ return ret;
355
+ } else {
356
+ return Qnil;
357
+ }
358
+ }
359
+ }
360
+
361
+ static VALUE
362
+ emit_ensure(struct emit_arg* arg)
363
+ {
364
+ g_value_array_free(arg->instance_and_params);
365
+ return Qnil;
366
+ }
367
+
368
+ static VALUE
369
+ gobj_sig_emit(argc, argv, self)
370
+ int argc;
371
+ VALUE *argv;
372
+ VALUE self;
373
+ {
374
+ VALUE sig;
375
+ const char* sig_name;
376
+ guint signal_id;
377
+ struct emit_arg arg;
378
+
379
+ rb_scan_args(argc, argv, "1*", &sig, &arg.args);
380
+
381
+ if (SYMBOL_P(sig))
382
+ sig_name = rb_id2name(SYM2ID(sig));
383
+ else
384
+ sig_name = StringValuePtr(sig);
385
+
386
+ if (!g_signal_parse_name(sig_name,
387
+ CLASS2GTYPE(CLASS_OF(self)),
388
+ &signal_id, &arg.detail, FALSE))
389
+ rb_raise(eNoSignalError, "invalid signal \"%s\"", sig_name);
390
+
391
+ g_signal_query(signal_id, &arg.query);
392
+
393
+ if (arg.query.n_params != RARRAY_LEN(arg.args))
394
+ rb_raise(rb_eArgError, "wrong number of arguments(%ld for %d)",
395
+ RARRAY_LEN(arg.args) + 1,
396
+ arg.query.n_params + 1);
397
+
398
+ arg.self = self;
399
+ arg.instance_and_params = g_value_array_new(1 + arg.query.n_params);
400
+
401
+ return rb_ensure(emit_body, (VALUE)&arg, emit_ensure, (VALUE)&arg);
402
+ }
403
+
404
+ static VALUE
405
+ gobj_sig_emit_stop(self, sig)
406
+ VALUE self, sig;
407
+ {
408
+ gpointer instance = RVAL2GOBJ(self);
409
+ const char* sig_name;
410
+ guint signal_id;
411
+ GQuark detail;
412
+
413
+ if (SYMBOL_P(sig))
414
+ sig_name = rb_id2name(SYM2ID(sig));
415
+ else
416
+ sig_name = StringValuePtr(sig);
417
+
418
+ if (!g_signal_parse_name(sig_name,
419
+ CLASS2GTYPE(CLASS_OF(self)),
420
+ &signal_id, &detail, FALSE))
421
+ rb_raise(eNoSignalError, "invalid signal \"%s\"", sig_name);
422
+
423
+ g_signal_stop_emission(instance, signal_id, detail);
424
+ return self;
425
+ }
426
+
427
+ static VALUE gobj_sig_handler_unblock(VALUE self, VALUE id);
428
+
429
+ static VALUE
430
+ _sig_handler_block_ensure(arg)
431
+ VALUE arg;
432
+ {
433
+ VALUE self = RARRAY_PTR(arg)[0];
434
+ VALUE id = RARRAY_PTR(arg)[1];
435
+ gobj_sig_handler_unblock(self, id);
436
+ return Qnil;
437
+ }
438
+
439
+ static VALUE
440
+ gobj_sig_handler_block(self, id)
441
+ VALUE self, id;
442
+ {
443
+ g_signal_handler_block(RVAL2GOBJ(self), NUM2ULONG(id));
444
+ if (rb_block_given_p())
445
+ rb_ensure(rb_yield, self, _sig_handler_block_ensure,
446
+ rb_ary_new3(2, self, id));
447
+ return self;
448
+ }
449
+
450
+ static VALUE
451
+ gobj_sig_handler_unblock(self, id)
452
+ VALUE self, id;
453
+ {
454
+ g_signal_handler_unblock(RVAL2GOBJ(self), NUM2ULONG(id));
455
+ return self;
456
+ }
457
+
458
+ static VALUE
459
+ gobj_sig_handler_disconnect(self, id)
460
+ VALUE self, id;
461
+ {
462
+ g_signal_handler_disconnect(RVAL2GOBJ(self), NUM2ULONG(id));
463
+ return self;
464
+ }
465
+
466
+ static VALUE
467
+ gobj_sig_handler_is_connected(self, id)
468
+ VALUE self, id;
469
+ {
470
+ return CBOOL2RVAL(g_signal_handler_is_connected(RVAL2GOBJ(self), NUM2ULONG(id)));
471
+ }
472
+
473
+ #if 0
474
+ gulong g_signal_handler_find (gpointer instance,
475
+ GSignalMatchType mask,
476
+ guint signal_id,
477
+ GQuark detail,
478
+ GClosure *closure,
479
+ gpointer func,
480
+ gpointer data);
481
+ guint g_signal_handlers_block_matched (gpointer instance,
482
+ GSignalMatchType mask,
483
+ guint signal_id,
484
+ GQuark detail,
485
+ GClosure *closure,
486
+ gpointer func,
487
+ gpointer data);
488
+ guint g_signal_handlers_unblock_matched (gpointer instance,
489
+ GSignalMatchType mask,
490
+ guint signal_id,
491
+ GQuark detail,
492
+ GClosure *closure,
493
+ gpointer func,
494
+ gpointer data);
495
+ guint g_signal_handlers_disconnect_matched (gpointer instance,
496
+ GSignalMatchType mask,
497
+ guint signal_id,
498
+ GQuark detail,
499
+ GClosure *closure,
500
+ gpointer func,
501
+ gpointer data);
502
+ #endif
503
+
504
+ static VALUE
505
+ chain_from_overridden_body(struct emit_arg* arg)
506
+ {
507
+ g_value_init(arg->instance_and_params->values,
508
+ G_TYPE_FROM_INSTANCE(RVAL2GOBJ(arg->self)));
509
+ rbgobj_rvalue_to_gvalue(arg->self, arg->instance_and_params->values);
510
+
511
+ {
512
+ GValue* params = arg->instance_and_params->values + 1;
513
+ int i;
514
+ for (i = 0; i < arg->query.n_params; i++) {
515
+ GType gtype = arg->query.param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE;
516
+ g_value_init(params + i, gtype);
517
+ rbgobj_rvalue_to_gvalue(rb_ary_entry(arg->args, i), params + i);
518
+ }
519
+ }
520
+
521
+ {
522
+ gboolean use_ret = (arg->query.return_type != G_TYPE_NONE);
523
+ GValue return_value = {0,};
524
+
525
+ if (use_ret)
526
+ g_value_init(&return_value,
527
+ arg->query.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
528
+
529
+ g_signal_chain_from_overridden(arg->instance_and_params->values,
530
+ (use_ret) ? &return_value : NULL);
531
+
532
+ if (use_ret) {
533
+ VALUE ret = GVAL2RVAL(&return_value);
534
+ g_value_unset(&return_value);
535
+ return ret;
536
+ } else {
537
+ return Qnil;
538
+ }
539
+ }
540
+ }
541
+
542
+ static VALUE
543
+ gobj_sig_chain_from_overridden(argc, argv, self)
544
+ int argc;
545
+ VALUE* argv;
546
+ VALUE self;
547
+ {
548
+ struct emit_arg arg;
549
+
550
+ {
551
+ GSignalInvocationHint* hint;
552
+ hint = g_signal_get_invocation_hint(RVAL2GOBJ(self));
553
+ if (!hint)
554
+ rb_raise(rb_eRuntimeError, "can't get signal invocation hint");
555
+ g_signal_query(hint->signal_id, &arg.query);
556
+ }
557
+
558
+ if (arg.query.n_params != argc)
559
+ rb_raise(rb_eArgError, "wrong number of arguments(%d for %d)",
560
+ argc, arg.query.n_params);
561
+
562
+ arg.self = self;
563
+ arg.args = rb_ary_new4(argc, argv);
564
+ arg.instance_and_params = g_value_array_new(1 + argc);
565
+
566
+ return rb_ensure(chain_from_overridden_body, (VALUE)&arg,
567
+ emit_ensure, (VALUE)&arg);
568
+ }
569
+
570
+ static VALUE
571
+ gobj_s_method_added(klass, id)
572
+ VALUE klass, id;
573
+ {
574
+ const RGObjClassInfo* cinfo = rbgobj_lookup_class(klass);
575
+ const char* name = rb_id2name(SYM2ID(id));
576
+ const int prefix_len = strlen(default_handler_method_prefix);
577
+ guint signal_id;
578
+
579
+ if (cinfo->klass != klass) return Qnil;
580
+ if (strncmp(default_handler_method_prefix, name, prefix_len)) return Qnil;
581
+
582
+ signal_id = g_signal_lookup(name + prefix_len, cinfo->gtype);
583
+ if (!signal_id) return Qnil;
584
+
585
+ {
586
+ GSignalQuery query;
587
+ g_signal_query(signal_id, &query);
588
+ if (query.itype == cinfo->gtype)
589
+ return Qnil;
590
+ }
591
+
592
+ {
593
+ VALUE f = rb_eval_string(
594
+ "lambda{|klass, id|\n"
595
+ " lambda{|instance,*args|\n"
596
+ " klass.instance_method(id).bind(instance).call(*args)\n"
597
+ " }\n"
598
+ "}\n");
599
+ VALUE proc = rb_funcall(f, rb_intern("call"), 2, klass, id);
600
+ GClosure* rclosure = g_rclosure_new(proc, Qnil,
601
+ rbgobj_get_signal_func(signal_id));
602
+ g_rclosure_attach((GClosure *)rclosure, klass);
603
+ g_signal_override_class_closure(signal_id, cinfo->gtype, rclosure);
604
+ }
605
+
606
+ {
607
+ VALUE mod = rb_define_module_under(klass, RubyGObjectHookModule);
608
+ rb_include_module(klass, mod);
609
+ rb_define_method(mod, name, gobj_sig_chain_from_overridden, -1);
610
+ }
611
+
612
+ return Qnil;
613
+ }
614
+
615
+ static void
616
+ Init_signal_misc()
617
+ {
618
+ signal_func_table = rb_hash_new();
619
+ rb_global_variable(&signal_func_table);
620
+
621
+ rb_define_method(mMetaInterface, "signal_new", gobj_s_signal_new, -1);
622
+ rb_define_method(mMetaInterface, "signals", gobj_s_signals, -1);
623
+ rb_define_method(mMetaInterface, "signal", gobj_s_signal, 1);
624
+
625
+ rb_define_method(cInstantiatable, "signal_has_handler_pending?",
626
+ gobj_sig_has_handler_pending, -1);
627
+ rb_define_method(cInstantiatable, "signal_connect", gobj_sig_connect, -1);
628
+ rb_define_method(cInstantiatable, "signal_connect_after",
629
+ gobj_sig_connect_after, -1);
630
+
631
+ #if 0
632
+ rb_define_method(cInstantiatable, "signal_invocation_hint",
633
+ gobj_sig_get_invocation_hint, 0);
634
+ #endif
635
+
636
+ rb_define_method(cInstantiatable, "signal_emit",
637
+ gobj_sig_emit, -1);
638
+ rb_define_method(cInstantiatable, "signal_emit_stop",
639
+ gobj_sig_emit_stop, 1);
640
+ rb_define_method(cInstantiatable, "signal_handler_block",
641
+ gobj_sig_handler_block, 1);
642
+ rb_define_method(cInstantiatable, "signal_handler_unblock",
643
+ gobj_sig_handler_unblock, 1);
644
+ rb_define_method(cInstantiatable, "signal_handler_disconnect",
645
+ gobj_sig_handler_disconnect, 1);
646
+
647
+ rb_define_method(cInstantiatable, "signal_handler_is_connected?",
648
+ gobj_sig_handler_is_connected, 1);
649
+
650
+ rb_define_singleton_method(cInstantiatable, "method_added",
651
+ gobj_s_method_added, 1);
652
+ }
653
+
654
+ /**********************************************************************/
655
+
656
+ VALUE
657
+ rbgobj_signal_wrap(sig_id)
658
+ guint sig_id;
659
+ {
660
+ VALUE result;
661
+ GSignalQuery* query;
662
+
663
+ result = Data_Make_Struct(cSignal, GSignalQuery, NULL, free, query);
664
+ g_signal_query(sig_id, query);
665
+ return result;
666
+ }
667
+
668
+ static VALUE
669
+ query_signal_id(self)
670
+ VALUE self;
671
+ {
672
+ GSignalQuery* query;
673
+ Data_Get_Struct(self, GSignalQuery, query);
674
+ return UINT2NUM(query->signal_id);
675
+ }
676
+
677
+ static VALUE
678
+ query_signal_name(self)
679
+ VALUE self;
680
+ {
681
+ GSignalQuery* query;
682
+ Data_Get_Struct(self, GSignalQuery, query);
683
+ return rb_str_new2(query->signal_name);
684
+ }
685
+
686
+ static VALUE
687
+ query_itype(self)
688
+ VALUE self;
689
+ {
690
+ GSignalQuery* query;
691
+ Data_Get_Struct(self, GSignalQuery, query);
692
+ return rbgobj_gtype_new(query->itype);
693
+ }
694
+
695
+ static VALUE
696
+ query_owner(self)
697
+ VALUE self;
698
+ {
699
+ GSignalQuery* query;
700
+ Data_Get_Struct(self, GSignalQuery, query);
701
+ return GTYPE2CLASS(query->itype);
702
+ }
703
+
704
+ static VALUE
705
+ query_return_type(self)
706
+ VALUE self;
707
+ {
708
+ GSignalQuery* query;
709
+ Data_Get_Struct(self, GSignalQuery, query);
710
+ return rbgobj_gtype_new(query->return_type);
711
+ }
712
+
713
+ static VALUE
714
+ query_signal_flags(self)
715
+ VALUE self;
716
+ {
717
+ GSignalQuery* query;
718
+ Data_Get_Struct(self, GSignalQuery, query);
719
+ return UINT2NUM(query->signal_flags);
720
+ }
721
+
722
+ static VALUE
723
+ query_param_types(self)
724
+ VALUE self;
725
+ {
726
+ GSignalQuery* query;
727
+ VALUE result;
728
+ int i;
729
+ Data_Get_Struct(self, GSignalQuery, query);
730
+
731
+ result = rb_ary_new2(query->n_params);
732
+ for (i = 0; i < query->n_params; i++)
733
+ rb_ary_store(result, i, rbgobj_gtype_new(query->param_types[i]));
734
+
735
+ return result;
736
+ }
737
+
738
+ static VALUE
739
+ query_inspect(self)
740
+ VALUE self;
741
+ {
742
+ GSignalQuery* query;
743
+ gchar* s;
744
+ VALUE result, v;
745
+
746
+ Data_Get_Struct(self, GSignalQuery, query);
747
+
748
+ v = rb_inspect(GTYPE2CLASS(query->itype));
749
+
750
+ s = g_strdup_printf("#<%s: %s#%s>",
751
+ rb_class2name(CLASS_OF(self)),
752
+ StringValuePtr(v),
753
+ query->signal_name);
754
+ result = rb_str_new2(s);
755
+ g_free(s);
756
+
757
+ return result;
758
+ }
759
+
760
+ #define query_is_flag(flag) \
761
+ static VALUE \
762
+ query_is_##flag(self) \
763
+ VALUE self; \
764
+ { \
765
+ GSignalQuery* query; \
766
+ Data_Get_Struct(self, GSignalQuery, query); \
767
+ return CBOOL2RVAL(query->signal_flags & flag); \
768
+ }
769
+
770
+ query_is_flag(G_SIGNAL_RUN_FIRST)
771
+ query_is_flag(G_SIGNAL_RUN_LAST)
772
+ query_is_flag(G_SIGNAL_RUN_CLEANUP)
773
+ query_is_flag(G_SIGNAL_NO_RECURSE)
774
+ query_is_flag(G_SIGNAL_DETAILED)
775
+ query_is_flag(G_SIGNAL_ACTION)
776
+ query_is_flag(G_SIGNAL_NO_HOOKS)
777
+
778
+
779
+ static gboolean
780
+ hook_func(GSignalInvocationHint* ihint,
781
+ guint n_param_values,
782
+ const GValue* param_values,
783
+ gpointer data)
784
+ {
785
+ GClosure* closure = data;
786
+ GValue ret_val ={0,};
787
+ gboolean ret;
788
+
789
+ g_value_init(&ret_val, G_TYPE_BOOLEAN);
790
+ g_closure_invoke(closure, &ret_val, n_param_values, param_values, ihint);
791
+ ret = g_value_get_boolean(&ret_val);
792
+ g_value_unset(&ret_val);
793
+
794
+ return ret;
795
+ }
796
+
797
+ static gulong
798
+ g_signal_add_emission_hook_closure (guint signal_id,
799
+ GQuark detail,
800
+ GClosure* closure)
801
+ {
802
+ guint hook_id;
803
+ g_closure_ref(closure);
804
+ g_closure_sink(closure);
805
+ hook_id = g_signal_add_emission_hook(signal_id, detail,
806
+ &hook_func, closure,
807
+ (GDestroyNotify)&g_closure_unref);
808
+ return hook_id;
809
+ }
810
+
811
+ static VALUE
812
+ signal_add_emission_hook(int argc, VALUE* argv, VALUE self)
813
+ {
814
+ GSignalQuery* query;
815
+ VALUE proc;
816
+ guint hook_id;
817
+ GQuark detail = 0;
818
+ GClosure* closure;
819
+
820
+ Data_Get_Struct(self, GSignalQuery, query);
821
+
822
+ if (query->signal_flags & G_SIGNAL_DETAILED) {
823
+ VALUE detail_obj;
824
+ if (rb_scan_args(argc, argv, "01&", &detail_obj, &proc) == 1) {
825
+ if (SYMBOL_P(detail_obj))
826
+ detail = g_quark_from_string(rb_id2name(SYM2ID(detail_obj)));
827
+ else
828
+ detail = g_quark_from_string(StringValuePtr(detail_obj));
829
+ }
830
+ } else {
831
+ rb_scan_args(argc, argv, "00&", &proc);
832
+ }
833
+
834
+ closure = g_rclosure_new(proc, Qnil,
835
+ rbgobj_get_signal_func(query->signal_id));
836
+ g_rclosure_attach(closure, self);
837
+ hook_id = g_signal_add_emission_hook_closure(query->signal_id, detail, closure);
838
+ return ULONG2NUM(hook_id);
839
+ }
840
+
841
+ static VALUE
842
+ signal_remove_emission_hook(VALUE self, VALUE hook_id)
843
+ {
844
+ GSignalQuery* query;
845
+ Data_Get_Struct(self, GSignalQuery, query);
846
+ g_signal_remove_emission_hook(query->signal_id, NUM2ULONG(hook_id));
847
+ return Qnil;
848
+ }
849
+
850
+ static void
851
+ Init_signal_class()
852
+ {
853
+ VALUE cSignalFlags, cSignalMatchType;
854
+
855
+ cSignal = rb_define_class_under(mGLib, "Signal", rb_cData);
856
+
857
+ rb_define_method(cSignal, "id", query_signal_id, 0);
858
+ rb_define_method(cSignal, "name", query_signal_name, 0);
859
+ rb_define_method(cSignal, "flags", query_signal_flags, 0);
860
+ rb_define_method(cSignal, "itype", query_itype, 0);
861
+ rb_define_method(cSignal, "owner", query_owner, 0);
862
+ rb_define_method(cSignal, "return_type", query_return_type, 0);
863
+ rb_define_method(cSignal, "param_types", query_param_types, 0);
864
+ rb_define_method(cSignal, "inspect", query_inspect, 0);
865
+
866
+ rb_define_method(cSignal, "add_emission_hook", signal_add_emission_hook, -1);
867
+ rb_define_method(cSignal, "remove_emission_hook", signal_remove_emission_hook, 1);
868
+
869
+ /* GSignalFlags */
870
+ cSignalFlags = G_DEF_CLASS(G_TYPE_SIGNAL_FLAGS, "SignalFlags", mGLib);
871
+ G_DEF_CONSTANTS(cSignal, G_TYPE_SIGNAL_FLAGS, "G_SIGNAL_");
872
+ rb_define_const(cSignalFlags, "MASK", INT2NUM(G_SIGNAL_FLAGS_MASK));
873
+ rb_define_const(cSignal, "FLAGS_MASK", INT2NUM(G_SIGNAL_FLAGS_MASK));
874
+
875
+ rb_define_method(cSignal, "run_first?", query_is_G_SIGNAL_RUN_FIRST, 0);
876
+ rb_define_method(cSignal, "run_last?", query_is_G_SIGNAL_RUN_LAST, 0);
877
+ rb_define_method(cSignal, "run_cleanup?", query_is_G_SIGNAL_RUN_CLEANUP, 0);
878
+ rb_define_method(cSignal, "no_recurse?", query_is_G_SIGNAL_NO_RECURSE, 0);
879
+ rb_define_method(cSignal, "detailed?", query_is_G_SIGNAL_DETAILED, 0);
880
+ rb_define_method(cSignal, "action?", query_is_G_SIGNAL_ACTION, 0);
881
+ rb_define_method(cSignal, "no_hooks?", query_is_G_SIGNAL_NO_HOOKS, 0);
882
+
883
+
884
+ /* GConnectFlags */
885
+ G_DEF_CLASS(G_TYPE_CONNECT_FLAGS, "ConnectFlags", mGLib);
886
+ G_DEF_CONSTANTS(cSignal, G_TYPE_CONNECT_FLAGS, "G_");
887
+
888
+ /* GSignalMatchType */
889
+ cSignalMatchType = G_DEF_CLASS(G_TYPE_SIGNAL_MATCH_TYPE,
890
+ "SignalMatchType", mGLib);
891
+ G_DEF_CONSTANTS(cSignal, G_TYPE_SIGNAL_MATCH_TYPE, "G_SIGNAL_");
892
+ rb_define_const(cSignalMatchType, "MASK", INT2NUM(G_SIGNAL_MATCH_MASK));
893
+ rb_define_const(cSignal, "MATCH_MASK", INT2NUM(G_SIGNAL_MATCH_MASK));
894
+
895
+ rb_define_const(cSignal, "TYPE_STATIC_SCOPE", INT2FIX(G_SIGNAL_TYPE_STATIC_SCOPE));
896
+
897
+ eNoSignalError = rb_define_class_under(mGLib, "NoSignalError", rb_eNameError);
898
+ }
899
+
900
+ /**********************************************************************/
901
+
902
+ void
903
+ rbgobj_define_action_methods(VALUE klass)
904
+ {
905
+ GType gtype = CLASS2GTYPE(klass);
906
+ GString* source;
907
+ guint n_ids;
908
+ guint* ids;
909
+ int i;
910
+
911
+ if (gtype == G_TYPE_INTERFACE)
912
+ return;
913
+
914
+ ids = g_signal_list_ids(gtype, &n_ids);
915
+ if (n_ids == 0)
916
+ return;
917
+
918
+ source = g_string_new(NULL);
919
+ for (i = 0; i < n_ids; i++){
920
+ GSignalQuery query;
921
+ g_signal_query(ids[i], &query);
922
+
923
+ if (query.signal_flags & G_SIGNAL_ACTION) {
924
+ gchar* method_name = g_strdup(query.signal_name);
925
+ gchar* p;
926
+ GString* args;
927
+ int j;
928
+
929
+ for (p = method_name; *p; p++)
930
+ if (*p == '-')
931
+ *p = '_';
932
+
933
+ args = g_string_new(NULL);
934
+ for (j = 0; j < query.n_params; j++)
935
+ g_string_append_printf(args, ",x%d", j);
936
+
937
+ g_string_append_printf(
938
+ source,
939
+ "def %s(%s)\n signal_emit('%s'%s)\nend\n",
940
+ method_name,
941
+ (query.n_params > 0) ? args->str + 1 : "", // hack
942
+ query.signal_name,
943
+ args->str);
944
+
945
+ g_free(method_name);
946
+ g_string_free(args, TRUE);
947
+ }
948
+ }
949
+
950
+ if (source->len > 0)
951
+ rb_funcall(klass, rb_intern("module_eval"), 1, rb_str_new2(source->str));
952
+ g_string_free(source, TRUE);
953
+ }
954
+
955
+ /**********************************************************************/
956
+
957
+ void
958
+ Init_gobject_gsignal()
959
+ {
960
+ Init_signal_class();
961
+ Init_signal_misc();
962
+ }
963
+