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.
- data/ChangeLog +3023 -0
- data/README +28 -0
- data/Rakefile +87 -0
- data/extconf.rb +61 -0
- data/sample/bookmarkfile.rb +66 -0
- data/sample/completion.rb +45 -0
- data/sample/idle.rb +41 -0
- data/sample/iochannel.rb +44 -0
- data/sample/keyfile.rb +62 -0
- data/sample/shell.rb +36 -0
- data/sample/spawn.rb +25 -0
- data/sample/timeout.rb +28 -0
- data/sample/timeout2.rb +35 -0
- data/sample/timer.rb +40 -0
- data/sample/type-register.rb +103 -0
- data/sample/type-register2.rb +104 -0
- data/sample/utils.rb +54 -0
- data/src/glib-enum-types.c +1032 -0
- data/src/glib-enum-types.h +140 -0
- data/src/lib/glib-mkenums.rb +199 -0
- data/src/lib/glib2.rb +220 -0
- data/src/lib/mkmf-gnome2.rb +390 -0
- data/src/lib/pkg-config.rb +137 -0
- data/src/rbgcompat.h +30 -0
- data/src/rbglib.c +320 -0
- data/src/rbglib.h +96 -0
- data/src/rbglib_bookmarkfile.c +595 -0
- data/src/rbglib_completion.c +192 -0
- data/src/rbglib_convert.c +195 -0
- data/src/rbglib_error.c +95 -0
- data/src/rbglib_fileutils.c +83 -0
- data/src/rbglib_i18n.c +44 -0
- data/src/rbglib_int64.c +157 -0
- data/src/rbglib_iochannel.c +883 -0
- data/src/rbglib_keyfile.c +846 -0
- data/src/rbglib_maincontext.c +917 -0
- data/src/rbglib_mainloop.c +87 -0
- data/src/rbglib_messages.c +150 -0
- data/src/rbglib_pollfd.c +111 -0
- data/src/rbglib_shell.c +68 -0
- data/src/rbglib_source.c +190 -0
- data/src/rbglib_spawn.c +345 -0
- data/src/rbglib_threads.c +51 -0
- data/src/rbglib_timer.c +127 -0
- data/src/rbglib_unicode.c +611 -0
- data/src/rbglib_utils.c +386 -0
- data/src/rbglib_win32.c +136 -0
- data/src/rbgobj_boxed.c +251 -0
- data/src/rbgobj_closure.c +337 -0
- data/src/rbgobj_convert.c +167 -0
- data/src/rbgobj_enums.c +961 -0
- data/src/rbgobj_fundamental.c +30 -0
- data/src/rbgobj_object.c +892 -0
- data/src/rbgobj_param.c +390 -0
- data/src/rbgobj_paramspecs.c +305 -0
- data/src/rbgobj_signal.c +963 -0
- data/src/rbgobj_strv.c +61 -0
- data/src/rbgobj_type.c +851 -0
- data/src/rbgobj_typeinstance.c +121 -0
- data/src/rbgobj_typeinterface.c +148 -0
- data/src/rbgobj_typemodule.c +66 -0
- data/src/rbgobj_typeplugin.c +49 -0
- data/src/rbgobj_value.c +313 -0
- data/src/rbgobj_valuearray.c +59 -0
- data/src/rbgobj_valuetypes.c +298 -0
- data/src/rbgobject.c +406 -0
- data/src/rbgobject.h +265 -0
- data/src/rbgprivate.h +88 -0
- data/src/rbgutil.c +222 -0
- data/src/rbgutil.h +82 -0
- data/src/rbgutil_callback.c +231 -0
- data/test/glib-test-init.rb +6 -0
- data/test/glib-test-utils.rb +12 -0
- data/test/run-test.rb +25 -0
- data/test/test_enum.rb +99 -0
- data/test/test_file_utils.rb +15 -0
- data/test/test_glib2.rb +120 -0
- data/test/test_iochannel.rb +275 -0
- data/test/test_key_file.rb +38 -0
- data/test/test_mkenums.rb +25 -0
- data/test/test_signal.rb +20 -0
- data/test/test_timeout.rb +28 -0
- data/test/test_unicode.rb +369 -0
- data/test/test_utils.rb +37 -0
- data/test/test_win32.rb +13 -0
- metadata +165 -0
data/src/rbgobj_boxed.c
ADDED
@@ -0,0 +1,251 @@
|
|
1
|
+
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
|
2
|
+
/**********************************************************************
|
3
|
+
|
4
|
+
rbgobj_boxed.c -
|
5
|
+
|
6
|
+
$Author: sakai $
|
7
|
+
$Date: 2007/07/14 13:33:07 $
|
8
|
+
created at: Sat Jul 27 16:56:01 JST 2002
|
9
|
+
|
10
|
+
Copyright (C) 2002,2003 Masahiro Sakai
|
11
|
+
|
12
|
+
**********************************************************************/
|
13
|
+
|
14
|
+
#include "rbgprivate.h"
|
15
|
+
|
16
|
+
VALUE rbgobj_cBoxed;
|
17
|
+
|
18
|
+
static void
|
19
|
+
boxed_mark(boxed_holder *holder)
|
20
|
+
{
|
21
|
+
const RGObjClassInfo *cinfo;
|
22
|
+
|
23
|
+
cinfo = GTYPE2CINFO_NO_CREATE(holder->type);
|
24
|
+
if (cinfo && cinfo->mark)
|
25
|
+
cinfo->mark(holder->boxed);
|
26
|
+
}
|
27
|
+
|
28
|
+
static void
|
29
|
+
boxed_free(boxed_holder *holder)
|
30
|
+
{
|
31
|
+
const RGObjClassInfo *cinfo;
|
32
|
+
|
33
|
+
cinfo = GTYPE2CINFO_NO_CREATE(holder->type);
|
34
|
+
if (cinfo && cinfo->free)
|
35
|
+
cinfo->free(holder->boxed);
|
36
|
+
|
37
|
+
if (holder->own && holder->boxed)
|
38
|
+
g_boxed_free(holder->type, holder->boxed);
|
39
|
+
|
40
|
+
free(holder);
|
41
|
+
}
|
42
|
+
|
43
|
+
/**********************************************************************/
|
44
|
+
|
45
|
+
static VALUE
|
46
|
+
rbgobj_boxed_s_allocate(klass)
|
47
|
+
VALUE klass;
|
48
|
+
{
|
49
|
+
const RGObjClassInfo* cinfo = rbgobj_lookup_class(klass);
|
50
|
+
boxed_holder* holder;
|
51
|
+
VALUE result;
|
52
|
+
|
53
|
+
if (cinfo->gtype == G_TYPE_BOXED)
|
54
|
+
rb_raise(rb_eTypeError, "abstract class");
|
55
|
+
|
56
|
+
result = Data_Make_Struct(klass, boxed_holder,
|
57
|
+
boxed_mark, boxed_free, holder);
|
58
|
+
holder->type = cinfo->gtype;
|
59
|
+
holder->boxed = NULL;
|
60
|
+
holder->own = FALSE;
|
61
|
+
|
62
|
+
return result;
|
63
|
+
}
|
64
|
+
|
65
|
+
static VALUE
|
66
|
+
rbgobj_boxed_init(self)
|
67
|
+
VALUE self;
|
68
|
+
{
|
69
|
+
rb_raise(rb_eTypeError, "can't initialize %s",
|
70
|
+
rb_class2name(CLASS_OF(self)));
|
71
|
+
}
|
72
|
+
|
73
|
+
static VALUE
|
74
|
+
rbgobj_boxed_inspect(self)
|
75
|
+
VALUE self;
|
76
|
+
{
|
77
|
+
boxed_holder* holder;
|
78
|
+
gchar* s;
|
79
|
+
VALUE result;
|
80
|
+
|
81
|
+
Data_Get_Struct(self, boxed_holder, holder);
|
82
|
+
|
83
|
+
s = g_strdup_printf("#<%s:%p ptr=%p own=%s>",
|
84
|
+
rb_class2name(CLASS_OF(self)),
|
85
|
+
(void *)self,
|
86
|
+
holder->boxed,
|
87
|
+
holder->own ? "true" : "false");
|
88
|
+
|
89
|
+
result = rb_str_new2(s);
|
90
|
+
g_free(s);
|
91
|
+
|
92
|
+
return result;
|
93
|
+
}
|
94
|
+
|
95
|
+
static VALUE
|
96
|
+
rbgobj_boxed_init_copy(self, orig)
|
97
|
+
VALUE self, orig;
|
98
|
+
{
|
99
|
+
boxed_holder* holder1;
|
100
|
+
boxed_holder* holder2;
|
101
|
+
|
102
|
+
if (self == orig) return self;
|
103
|
+
|
104
|
+
if (!rb_obj_is_instance_of(orig, rb_obj_class(self))) {
|
105
|
+
rb_raise(rb_eTypeError, "wrong argument class");
|
106
|
+
}
|
107
|
+
|
108
|
+
Data_Get_Struct(self, boxed_holder, holder1);
|
109
|
+
Data_Get_Struct(orig, boxed_holder, holder2);
|
110
|
+
|
111
|
+
holder1->boxed = g_boxed_copy(holder2->type, holder2->boxed);
|
112
|
+
holder1->own = TRUE;
|
113
|
+
|
114
|
+
if (!holder1->boxed)
|
115
|
+
rb_raise(rb_eRuntimeError, "g_boxed_copy() failed");
|
116
|
+
|
117
|
+
return self;
|
118
|
+
}
|
119
|
+
|
120
|
+
/* deprecated */
|
121
|
+
VALUE
|
122
|
+
rbgobj_boxed_create(klass)
|
123
|
+
VALUE klass;
|
124
|
+
{
|
125
|
+
return rbgobj_boxed_s_allocate(klass);
|
126
|
+
}
|
127
|
+
|
128
|
+
/**********************************************************************/
|
129
|
+
|
130
|
+
void
|
131
|
+
rbgobj_boxed_initialize(obj, boxed)
|
132
|
+
VALUE obj;
|
133
|
+
gpointer boxed;
|
134
|
+
{
|
135
|
+
boxed_holder* holder;
|
136
|
+
Data_Get_Struct(obj, boxed_holder, holder);
|
137
|
+
holder->boxed = g_boxed_copy(holder->type, boxed);
|
138
|
+
holder->own = TRUE;
|
139
|
+
}
|
140
|
+
|
141
|
+
gpointer
|
142
|
+
rbgobj_boxed_get(obj, gtype)
|
143
|
+
VALUE obj;
|
144
|
+
GType gtype;
|
145
|
+
{
|
146
|
+
boxed_holder* holder;
|
147
|
+
|
148
|
+
if (NIL_P(obj))
|
149
|
+
return NULL;
|
150
|
+
|
151
|
+
if (!RVAL2CBOOL(rb_obj_is_kind_of(obj, GTYPE2CLASS(gtype))))
|
152
|
+
rb_raise(rb_eArgError, "invalid argument %s (expect %s)",
|
153
|
+
rb_class2name(CLASS_OF(obj)),
|
154
|
+
rb_class2name(GTYPE2CLASS(gtype)));
|
155
|
+
|
156
|
+
Data_Get_Struct(obj, boxed_holder, holder);
|
157
|
+
if (!holder->boxed)
|
158
|
+
rb_raise(rb_eArgError, "uninitialize %s", rb_class2name(CLASS_OF(obj)));
|
159
|
+
|
160
|
+
return holder->boxed;
|
161
|
+
}
|
162
|
+
|
163
|
+
VALUE
|
164
|
+
rbgobj_make_boxed(p, gtype)
|
165
|
+
gpointer p;
|
166
|
+
GType gtype;
|
167
|
+
{
|
168
|
+
const RGObjClassInfo* cinfo;
|
169
|
+
VALUE result;
|
170
|
+
boxed_holder* holder;
|
171
|
+
|
172
|
+
if (!p)
|
173
|
+
return Qnil;
|
174
|
+
|
175
|
+
cinfo = GTYPE2CINFO(gtype);
|
176
|
+
result = rbgobj_boxed_s_allocate(cinfo->klass);
|
177
|
+
|
178
|
+
Data_Get_Struct(result, boxed_holder, holder);
|
179
|
+
|
180
|
+
if (cinfo->flags & RBGOBJ_BOXED_NOT_COPY){
|
181
|
+
holder->boxed = p;
|
182
|
+
holder->own = FALSE;
|
183
|
+
} else {
|
184
|
+
holder->boxed = g_boxed_copy(gtype, p);
|
185
|
+
holder->own = TRUE;
|
186
|
+
}
|
187
|
+
|
188
|
+
return result;
|
189
|
+
}
|
190
|
+
|
191
|
+
void
|
192
|
+
rbgobj_boxed_not_copy_obj(gtype)
|
193
|
+
GType gtype;
|
194
|
+
{
|
195
|
+
RGObjClassInfo* cinfo = (RGObjClassInfo*)GTYPE2CINFO(gtype);
|
196
|
+
cinfo->flags |= RBGOBJ_BOXED_NOT_COPY;
|
197
|
+
}
|
198
|
+
|
199
|
+
/**********************************************************************/
|
200
|
+
|
201
|
+
static VALUE
|
202
|
+
boxed_to_ruby(const GValue* from)
|
203
|
+
{
|
204
|
+
gpointer boxed = g_value_get_boxed(from);
|
205
|
+
if (!boxed)
|
206
|
+
return Qnil;
|
207
|
+
else
|
208
|
+
return rbgobj_make_boxed(boxed, G_VALUE_TYPE(from));
|
209
|
+
}
|
210
|
+
|
211
|
+
static void
|
212
|
+
boxed_from_ruby(VALUE from, GValue* to)
|
213
|
+
{
|
214
|
+
boxed_holder* holder;
|
215
|
+
|
216
|
+
if (NIL_P(from)) {
|
217
|
+
g_value_set_boxed(to, NULL);
|
218
|
+
return;
|
219
|
+
}
|
220
|
+
|
221
|
+
Data_Get_Struct(from, boxed_holder, holder);
|
222
|
+
|
223
|
+
if (g_type_is_a(holder->type, G_VALUE_TYPE(to)))
|
224
|
+
g_value_set_boxed(to, holder->boxed);
|
225
|
+
else
|
226
|
+
rb_raise(rb_eRuntimeError, "%s is not a subtype of %s",
|
227
|
+
g_type_name(holder->type),
|
228
|
+
g_type_name(G_VALUE_TYPE(to)));
|
229
|
+
}
|
230
|
+
|
231
|
+
/**********************************************************************/
|
232
|
+
|
233
|
+
void
|
234
|
+
Init_gobject_gboxed()
|
235
|
+
{
|
236
|
+
VALUE gBoxed;
|
237
|
+
|
238
|
+
rbgobj_cBoxed = G_DEF_CLASS(G_TYPE_BOXED, "Boxed", mGLib);
|
239
|
+
gBoxed = rbgobj_cBoxed;
|
240
|
+
|
241
|
+
rbgobj_register_g2r_func(G_TYPE_BOXED, boxed_to_ruby);
|
242
|
+
rbgobj_register_r2g_func(G_TYPE_BOXED, boxed_from_ruby);
|
243
|
+
|
244
|
+
rb_define_alloc_func(gBoxed, (VALUE(*)_((VALUE)))rbgobj_boxed_s_allocate);
|
245
|
+
rb_define_singleton_method(gBoxed, "gtype", generic_s_gtype, 0);
|
246
|
+
rb_define_method(gBoxed, "gtype", generic_gtype, 0);
|
247
|
+
rb_define_method(gBoxed, "initialize", rbgobj_boxed_init, 0);
|
248
|
+
rb_define_method(gBoxed, "inspect", rbgobj_boxed_inspect, 0);
|
249
|
+
rb_define_method(gBoxed, "initialize_copy", rbgobj_boxed_init_copy, 1);
|
250
|
+
rb_define_alias(gBoxed, "copy", "dup");
|
251
|
+
}
|
@@ -0,0 +1,337 @@
|
|
1
|
+
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
|
2
|
+
/**********************************************************************
|
3
|
+
|
4
|
+
rbgobj_closure.c -
|
5
|
+
|
6
|
+
$Author: ggc $
|
7
|
+
$Date: 2007/07/13 14:27:06 $
|
8
|
+
|
9
|
+
Copyright (C) 2002-2006 Ruby-GNOME2 Project
|
10
|
+
Copyright (C) 2002,2003 Masahiro Sakai
|
11
|
+
|
12
|
+
**********************************************************************/
|
13
|
+
|
14
|
+
#include "rbgprivate.h"
|
15
|
+
|
16
|
+
static ID id_call, id_closures;
|
17
|
+
static gboolean rclosure_initialized = FALSE;
|
18
|
+
|
19
|
+
#define TAG_SIZE 64
|
20
|
+
typedef struct _GRClosure GRClosure;
|
21
|
+
struct _GRClosure
|
22
|
+
{
|
23
|
+
GClosure closure;
|
24
|
+
VALUE callback;
|
25
|
+
VALUE extra_args;
|
26
|
+
VALUE rb_holder;
|
27
|
+
gint count;
|
28
|
+
GList *objects;
|
29
|
+
GValToRValSignalFunc g2r_func;
|
30
|
+
gchar tag[TAG_SIZE];
|
31
|
+
};
|
32
|
+
|
33
|
+
static VALUE
|
34
|
+
rclosure_default_g2r_func(num, values)
|
35
|
+
guint num;
|
36
|
+
const GValue* values;
|
37
|
+
{
|
38
|
+
int i;
|
39
|
+
VALUE args = rb_ary_new2(num);
|
40
|
+
for (i = 0; i < num; i++)
|
41
|
+
rb_ary_store(args, i, GVAL2RVAL(&values[i]));
|
42
|
+
return args;
|
43
|
+
}
|
44
|
+
|
45
|
+
struct marshal_arg
|
46
|
+
{
|
47
|
+
GClosure* closure;
|
48
|
+
GValue* return_value;
|
49
|
+
guint n_param_values;
|
50
|
+
const GValue* param_values;
|
51
|
+
gpointer invocation_hint;
|
52
|
+
gpointer marshal_data;
|
53
|
+
};
|
54
|
+
|
55
|
+
static int
|
56
|
+
rclosure_alive_p(GRClosure *rclosure)
|
57
|
+
{
|
58
|
+
return (rclosure->count > 0 && !NIL_P(rclosure->rb_holder));
|
59
|
+
}
|
60
|
+
|
61
|
+
static VALUE
|
62
|
+
rclosure_marshal_do(VALUE arg_)
|
63
|
+
{
|
64
|
+
struct marshal_arg *arg;
|
65
|
+
GRClosure* rclosure;
|
66
|
+
GValue* return_value;
|
67
|
+
guint n_param_values;
|
68
|
+
const GValue* param_values;
|
69
|
+
/* gpointer invocation_hint;*/
|
70
|
+
/* gpointer marshal_data; */
|
71
|
+
|
72
|
+
VALUE ret = Qnil;
|
73
|
+
VALUE args;
|
74
|
+
GValToRValSignalFunc func;
|
75
|
+
|
76
|
+
arg = (struct marshal_arg*)arg_;
|
77
|
+
rclosure = (GRClosure *)(arg->closure);
|
78
|
+
return_value = arg->return_value;
|
79
|
+
n_param_values = arg->n_param_values;
|
80
|
+
param_values = arg->param_values;
|
81
|
+
/* invocation_hint = arg->invocation_hint; */
|
82
|
+
/* marshal_data = arg->marshal_data; */
|
83
|
+
|
84
|
+
if (rclosure->g2r_func){
|
85
|
+
func = (GValToRValSignalFunc)rclosure->g2r_func;
|
86
|
+
} else {
|
87
|
+
func = (GValToRValSignalFunc)rclosure_default_g2r_func;
|
88
|
+
}
|
89
|
+
args = (*func)(n_param_values, param_values);
|
90
|
+
|
91
|
+
if (rclosure_alive_p(rclosure)) {
|
92
|
+
VALUE callback, extra_args;
|
93
|
+
callback = rclosure->callback;
|
94
|
+
extra_args = rclosure->extra_args;
|
95
|
+
|
96
|
+
if (!NIL_P(extra_args)) {
|
97
|
+
args = rb_ary_concat(args, extra_args);
|
98
|
+
}
|
99
|
+
|
100
|
+
ret = rb_apply(callback, id_call, args);
|
101
|
+
} else {
|
102
|
+
rb_warn("GRClosure invoking callback: already destroyed: %s",
|
103
|
+
rclosure->tag[0] ? rclosure->tag : "(anonymous)");
|
104
|
+
}
|
105
|
+
|
106
|
+
if (return_value && G_VALUE_TYPE(return_value))
|
107
|
+
rbgobj_rvalue_to_gvalue(ret, return_value);
|
108
|
+
|
109
|
+
return Qnil;
|
110
|
+
}
|
111
|
+
|
112
|
+
static void
|
113
|
+
rclosure_marshal(GClosure* closure,
|
114
|
+
GValue* return_value,
|
115
|
+
guint n_param_values,
|
116
|
+
const GValue* param_values,
|
117
|
+
gpointer invocation_hint,
|
118
|
+
gpointer marshal_data)
|
119
|
+
{
|
120
|
+
struct marshal_arg arg;
|
121
|
+
|
122
|
+
if (!rclosure_initialized) {
|
123
|
+
g_closure_invalidate(closure);
|
124
|
+
return;
|
125
|
+
}
|
126
|
+
|
127
|
+
arg.closure = closure;
|
128
|
+
arg.return_value = return_value;
|
129
|
+
arg.n_param_values = n_param_values;
|
130
|
+
arg.param_values = param_values;
|
131
|
+
arg.invocation_hint = invocation_hint;
|
132
|
+
arg.marshal_data = marshal_data;
|
133
|
+
|
134
|
+
G_PROTECT_CALLBACK(rclosure_marshal_do, &arg);
|
135
|
+
}
|
136
|
+
|
137
|
+
static void rclosure_weak_notify(gpointer data, GObject* where_the_object_was);
|
138
|
+
|
139
|
+
static void
|
140
|
+
rclosure_unref(GRClosure *rclosure)
|
141
|
+
{
|
142
|
+
rclosure->count--;
|
143
|
+
|
144
|
+
if (!rclosure_alive_p(rclosure)) {
|
145
|
+
GList *next;
|
146
|
+
for (next = rclosure->objects; next; next = next->next) {
|
147
|
+
GObject *object = G_OBJECT(next->data);
|
148
|
+
g_object_weak_unref(object, rclosure_weak_notify, rclosure);
|
149
|
+
}
|
150
|
+
g_list_free(rclosure->objects);
|
151
|
+
rclosure->objects = NULL;
|
152
|
+
if (!NIL_P(rclosure->rb_holder)) {
|
153
|
+
RDATA(rclosure->rb_holder)->dmark = NULL;
|
154
|
+
RDATA(rclosure->rb_holder)->dfree = NULL;
|
155
|
+
rclosure->rb_holder = Qnil;
|
156
|
+
}
|
157
|
+
}
|
158
|
+
}
|
159
|
+
|
160
|
+
static void
|
161
|
+
rclosure_invalidate(gpointer data, GClosure* closure)
|
162
|
+
{
|
163
|
+
GRClosure *rclosure = (GRClosure*)closure;
|
164
|
+
|
165
|
+
if (rclosure->count > 0) {
|
166
|
+
GList *next;
|
167
|
+
|
168
|
+
rclosure->count = 1;
|
169
|
+
for (next = rclosure->objects; next; next = next->next) {
|
170
|
+
GObject *object = G_OBJECT(next->data);
|
171
|
+
VALUE obj = rbgobj_ruby_object_from_instance2(object, FALSE);
|
172
|
+
if (!NIL_P(rclosure->rb_holder) && !NIL_P(obj))
|
173
|
+
G_REMOVE_RELATIVE(obj, id_closures, rclosure->rb_holder);
|
174
|
+
}
|
175
|
+
|
176
|
+
rclosure_unref(rclosure);
|
177
|
+
}
|
178
|
+
}
|
179
|
+
|
180
|
+
static void
|
181
|
+
gr_closure_holder_mark(GRClosure *rclosure)
|
182
|
+
{
|
183
|
+
rb_gc_mark(rclosure->callback);
|
184
|
+
rb_gc_mark(rclosure->extra_args);
|
185
|
+
}
|
186
|
+
|
187
|
+
static void
|
188
|
+
gr_closure_holder_free(GRClosure *rclosure)
|
189
|
+
{
|
190
|
+
if (rclosure->count > 0) {
|
191
|
+
rclosure->count = 1;
|
192
|
+
|
193
|
+
/* No need to remove us from the relatives hash of our objects, as
|
194
|
+
* those aren't alive anymore anyway */
|
195
|
+
rclosure_unref(rclosure);
|
196
|
+
}
|
197
|
+
}
|
198
|
+
|
199
|
+
GClosure*
|
200
|
+
g_rclosure_new(VALUE callback_proc, VALUE extra_args, GValToRValSignalFunc g2r_func)
|
201
|
+
{
|
202
|
+
GRClosure* closure;
|
203
|
+
|
204
|
+
closure = (GRClosure*)g_closure_new_simple(sizeof(GRClosure), NULL);
|
205
|
+
|
206
|
+
closure->count = 1;
|
207
|
+
closure->g2r_func = g2r_func;
|
208
|
+
closure->objects = NULL;
|
209
|
+
closure->callback = callback_proc;
|
210
|
+
closure->extra_args = extra_args;
|
211
|
+
closure->rb_holder = Data_Wrap_Struct(rb_cData,
|
212
|
+
gr_closure_holder_mark,
|
213
|
+
gr_closure_holder_free,
|
214
|
+
closure);
|
215
|
+
closure->tag[0] = '\0';
|
216
|
+
|
217
|
+
g_closure_set_marshal((GClosure*)closure, &rclosure_marshal);
|
218
|
+
g_closure_add_invalidate_notifier((GClosure*)closure, NULL,
|
219
|
+
&rclosure_invalidate);
|
220
|
+
|
221
|
+
return (GClosure*)closure;
|
222
|
+
}
|
223
|
+
|
224
|
+
static void
|
225
|
+
rclosure_weak_notify(gpointer data, GObject* where_the_object_was)
|
226
|
+
{
|
227
|
+
GRClosure *rclosure = data;
|
228
|
+
if (rclosure_alive_p(rclosure)) {
|
229
|
+
rclosure->objects =
|
230
|
+
g_list_remove(rclosure->objects, where_the_object_was);
|
231
|
+
rclosure_unref(rclosure);
|
232
|
+
}
|
233
|
+
}
|
234
|
+
|
235
|
+
void
|
236
|
+
g_rclosure_attach(GClosure *closure, VALUE object)
|
237
|
+
{
|
238
|
+
static VALUE mGLibObject = (VALUE)NULL;
|
239
|
+
GRClosure *rclosure = (GRClosure *)closure;
|
240
|
+
|
241
|
+
G_RELATIVE2(object, Qnil, id_closures, rclosure->rb_holder);
|
242
|
+
|
243
|
+
if (!mGLibObject) {
|
244
|
+
mGLibObject = rb_const_get(mGLib, rb_intern("Object"));
|
245
|
+
}
|
246
|
+
if (rb_obj_is_kind_of(object, mGLibObject)) {
|
247
|
+
GObject *gobject;
|
248
|
+
gobject = RVAL2GOBJ(object);
|
249
|
+
rclosure->count++;
|
250
|
+
g_object_weak_ref(gobject, rclosure_weak_notify, rclosure);
|
251
|
+
rclosure->objects = g_list_prepend(rclosure->objects, gobject);
|
252
|
+
}
|
253
|
+
}
|
254
|
+
|
255
|
+
void
|
256
|
+
g_rclosure_set_tag(GClosure *closure, const gchar *tag)
|
257
|
+
{
|
258
|
+
GRClosure *rclosure = (GRClosure *)closure;
|
259
|
+
|
260
|
+
if (tag) {
|
261
|
+
strncpy(rclosure->tag, tag, TAG_SIZE);
|
262
|
+
rclosure->tag[TAG_SIZE - 1] = '\0';
|
263
|
+
} else {
|
264
|
+
rclosure->tag[0] = '\0';
|
265
|
+
}
|
266
|
+
}
|
267
|
+
|
268
|
+
static void
|
269
|
+
rclosure_end_proc(VALUE _)
|
270
|
+
{
|
271
|
+
rclosure_initialized = FALSE;
|
272
|
+
}
|
273
|
+
|
274
|
+
static void
|
275
|
+
Init_rclosure()
|
276
|
+
{
|
277
|
+
id_call = rb_intern("call");
|
278
|
+
id_closures = rb_intern("closures");
|
279
|
+
rclosure_initialized = TRUE;
|
280
|
+
rb_set_end_proc(rclosure_end_proc, Qnil);
|
281
|
+
}
|
282
|
+
|
283
|
+
/**********************************************************************/
|
284
|
+
|
285
|
+
static VALUE
|
286
|
+
closure_initialize(self)
|
287
|
+
VALUE self;
|
288
|
+
{
|
289
|
+
GClosure* closure = g_rclosure_new(rb_block_proc(), Qnil, NULL);
|
290
|
+
G_INITIALIZE(self, closure);
|
291
|
+
g_closure_sink(closure);
|
292
|
+
return self;
|
293
|
+
}
|
294
|
+
|
295
|
+
static VALUE
|
296
|
+
closure_in_marshal(self)
|
297
|
+
VALUE self;
|
298
|
+
{
|
299
|
+
GClosure* closure = RVAL2BOXED(self, G_TYPE_CLOSURE);
|
300
|
+
return CBOOL2RVAL(closure->in_marshal);
|
301
|
+
}
|
302
|
+
|
303
|
+
static VALUE
|
304
|
+
closure_is_invalid(self)
|
305
|
+
VALUE self;
|
306
|
+
{
|
307
|
+
GClosure* closure = RVAL2BOXED(self, G_TYPE_CLOSURE);
|
308
|
+
return CBOOL2RVAL(closure->is_invalid);
|
309
|
+
}
|
310
|
+
|
311
|
+
static VALUE
|
312
|
+
closure_invalidate(self)
|
313
|
+
VALUE self;
|
314
|
+
{
|
315
|
+
GClosure* closure = RVAL2BOXED(self, G_TYPE_CLOSURE);
|
316
|
+
g_closure_invalidate(closure);
|
317
|
+
return self;
|
318
|
+
}
|
319
|
+
|
320
|
+
static void
|
321
|
+
Init_closure()
|
322
|
+
{
|
323
|
+
VALUE cClosure = G_DEF_CLASS(G_TYPE_CLOSURE, "Closure", mGLib);
|
324
|
+
rb_define_method(cClosure, "initialize", closure_initialize, 0);
|
325
|
+
rb_define_method(cClosure, "in_marshal?", closure_in_marshal, 0);
|
326
|
+
rb_define_method(cClosure, "invalid?", closure_is_invalid, 0);
|
327
|
+
rb_define_method(cClosure, "invalidate", closure_invalidate, 0);
|
328
|
+
}
|
329
|
+
|
330
|
+
/**********************************************************************/
|
331
|
+
|
332
|
+
void Init_gobject_gclosure()
|
333
|
+
{
|
334
|
+
Init_rclosure();
|
335
|
+
Init_closure();
|
336
|
+
}
|
337
|
+
|