Index: atk/ext/atk/rbatkeditabletext.c =================================================================== --- atk/ext/atk/rbatkeditabletext.c (revision 4688) +++ atk/ext/atk/rbatkeditabletext.c (working copy) @@ -12,28 +12,100 @@ #define _SELF(s) (ATK_EDITABLE_TEXT(RVAL2GOBJ(s))) +struct rval2atkattributegslist_args { + VALUE ary; + long n; + GSList *result; +}; + static VALUE -rbatk_edit_set_run_attributes(VALUE self, VALUE attributes, VALUE start_offset, VALUE end_offset) +rbatk_rval2atkattributegslist_body(VALUE value) { long i; - gboolean ret; - AtkAttributeSet* list = NULL; - - if (NIL_P(attributes)) return Qfalse; + struct rval2atkattributegslist_args *args = (struct rval2atkattributegslist_args *)value; - Check_Type(attributes, T_ARRAY); - for (i=0; in; i++) { + VALUE ary = rb_ary_to_ary(RARRAY_PTR(args->ary)[i]); + AtkAttribute *attribute; + + if (RARRAY_LEN(ary) != 2) + rb_raise(rb_eArgError, "attribute %ld should be an array of length 2", i); + + attribute = g_new(AtkAttribute, 1); + args->result = g_slist_append(args->result, attribute); + attribute->name = g_strdup(RVAL2CSTR(RARRAY_PTR(ary)[0])); + attribute->value = g_strdup(RVAL2CSTR(RARRAY_PTR(ary)[1])); } - ret = CBOOL2RVAL(atk_editable_text_set_run_attributes( - _SELF(self), list, - NUM2INT(start_offset), NUM2INT(end_offset))); + return Qnil; +} + +static void +rbatk_atkattributegslist_free(GSList *list) +{ + GSList *p; + + for (p = list; p != NULL; p = g_slist_next(p)) { + AtkAttribute *attribute = (AtkAttribute *)p->data; + + g_free(attribute->value); + g_free(attribute->name); + g_free(attribute); + } + g_slist_free(list); - return ret; } static VALUE +rbatk_rval2atkattributegslist_rescue(VALUE value) +{ + rbatk_atkattributegslist_free(((struct rval2atkattributegslist_args *)value)->result); + + rb_exc_raise(rb_errinfo()); +} + +static GSList * +rbatk_rval2atkattributegslist(VALUE value) +{ + struct rval2atkattributegslist_args args; + + args.ary = rb_ary_to_ary(value); + args.n = RARRAY_LEN(args.ary); + args.result = NULL; + + rb_rescue(rbatk_rval2atkattributegslist_body, (VALUE)&args, + rbatk_rval2atkattributegslist_rescue, (VALUE)&args); + + return args.result; +} + +#define RVAL2ATKATTRIBUTEGSLIST(value) rbatk_rval2atkattributegslist(value) + +static VALUE +rbatk_edit_set_run_attributes(VALUE self, + VALUE attributes, + VALUE rbstart_offset, + VALUE rbend_offset) +{ + AtkEditableText *editable; + gint start_offset, end_offset; + AtkAttributeSet *list; + gboolean result; + + if (NIL_P(attributes)) + return Qfalse; + + editable = _SELF(self); + start_offset = NUM2INT(rbstart_offset); + end_offset = NUM2INT(rbend_offset); + list = RVAL2ATKATTRIBUTEGSLIST(attributes); + result = atk_editable_text_set_run_attributes(editable, list, start_offset, end_offset); + rbatk_atkattributegslist_free(list); + + return CBOOL2RVAL(result); +} + +static VALUE rbatk_edit_set_text_contents(VALUE self, VALUE str) { atk_editable_text_set_text_contents(_SELF(self), RVAL2CSTR(str)); Index: atk/ext/atk/rbatkstateset.c =================================================================== --- atk/ext/atk/rbatkstateset.c (revision 4688) +++ atk/ext/atk/rbatkstateset.c (working copy) @@ -33,21 +33,49 @@ RVAL2GENUM(type, ATK_TYPE_STATE_TYPE))); } +struct rval2atkstatetype_args { + VALUE ary; + long n; + AtkStateType *result; +}; + static VALUE +rval2atkstatetype_body(VALUE value) +{ + long i; + struct rval2atkstatetype_args *args = (struct rval2atkstatetype_args *)value; + + for (i = 0; i < args->n; i++) + args->result[i] = RVAL2GENUM(RARRAY_PTR(args->ary)[i], ATK_TYPE_STATE_TYPE); + + return Qnil; +} + +static VALUE +rval2atkstatetype_rescue(VALUE value) +{ + g_free(((struct rval2atkstatetype_args *)value)->result); + + rb_exc_raise(rb_errinfo()); +} + +static VALUE rbatkstateset_add_states(VALUE self, VALUE types) { - gint i; - gint n_types = RARRAY_LEN(types); - AtkStateType* atypes = g_new(AtkStateType, n_types); + AtkStateSet *set = _SELF(self); + struct rval2atkstatetype_args args; - Check_Type(types, T_ARRAY); + args.ary = rb_ary_to_ary(types); + args.n = RARRAY_LEN(args.ary); + args.result = g_new(AtkStateType, args.n + 1); - for (i = 0; i < n_types; i++) { - atypes[i] = RVAL2GENUM(RARRAY_PTR(types)[i], ATK_TYPE_STATE_TYPE); - } + rb_rescue(rval2atkstatetype_body, (VALUE)&args, + rval2atkstatetype_rescue, (VALUE)&args); - atk_state_set_add_states(_SELF(self), atypes, n_types); - g_free(atypes); + atk_state_set_add_states(set, args.result, args.n); + + g_free(args.result); + return self; } @@ -68,21 +96,22 @@ static VALUE rbatkstateset_contains_states(VALUE self, VALUE types) { - gint i; - gboolean ret; - gint n_types = RARRAY_LEN(types); - AtkStateType* atypes = g_new(AtkStateType, n_types); + AtkStateSet *set = _SELF(self); + struct rval2atkstatetype_args args; + gboolean result; - Check_Type(types, T_ARRAY); + args.ary = rb_ary_to_ary(types); + args.n = RARRAY_LEN(args.ary); + args.result = g_new(AtkStateType, args.n + 1); - for (i = 0; i < n_types; i++) { - atypes[i] = RVAL2GENUM(RARRAY_PTR(types)[i], ATK_TYPE_STATE_TYPE); - } + rb_rescue(rval2atkstatetype_body, (VALUE)&args, + rval2atkstatetype_rescue, (VALUE)&args); - ret = CBOOL2RVAL(atk_state_set_contains_states(_SELF(self), atypes, n_types)); + result = atk_state_set_contains_states(set, args.result, args.n); - g_free(atypes); - return ret; + g_free(args.result); + + return CBOOL2RVAL(result); } static VALUE Index: atk/ext/atk/rbatkrelation.c =================================================================== --- atk/ext/atk/rbatkrelation.c (revision 4688) +++ atk/ext/atk/rbatkrelation.c (working copy) @@ -29,24 +29,52 @@ return GENUM2RVAL(atk_relation_type_for_name(RVAL2CSTR(name)), ATK_TYPE_RELATION_TYPE); } +struct rval2atkobjects_args { + VALUE ary; + long n; + AtkObject **result; +}; static VALUE -rbatkrel_initialize(VALUE self, VALUE targets, VALUE relationship) +rval2atkobjects_body(VALUE value) { - VALUE ary = rb_ary_to_ary(targets); long i; - long len = RARRAY_LEN(ary); - AtkObject **objects = g_new(AtkObject *, len); + struct rval2atkobjects_args *args = (struct rval2atkobjects_args *)value; - for (i = 0; i < len; i++) - objects[i] = RVAL2ATKOBJECT(RARRAY_PTR(targets)[i]); + for (i = 0; i < args->n; i++) + args->result[i] = ATK_OBJECT(RVAL2GOBJ(RARRAY_PTR(args->ary)[i])); - G_INITIALIZE(self, atk_relation_new(objects, - len, - RVAL2GENUM(relationship, ATK_TYPE_RELATION_TYPE))); + return Qnil; +} - g_free(objects); +static VALUE +rval2atkobjects_rescue(VALUE value) +{ + g_free(((struct rval2atkobjects_args *)value)->result); + rb_exc_raise(rb_errinfo()); +} + +static VALUE +rbatkrel_initialize(VALUE self, VALUE targets, VALUE rbrelationship) +{ + AtkRelationType relationship = RVAL2GENUM(rbrelationship, ATK_TYPE_RELATION_TYPE); + struct rval2atkobjects_args args; + AtkRelation *relation; + + args.ary = rb_ary_to_ary(targets); + args.n = RARRAY_LEN(args.ary); + args.result = g_new(AtkObject *, args.n + 1); + + rb_rescue(rval2atkobjects_body, (VALUE)&args, + rval2atkobjects_rescue, (VALUE)&args); + + relation = atk_relation_new(args.result, args.n, relationship); + + g_free(args.result); + + G_INITIALIZE(self, relation); + return Qnil; } Index: atk/ChangeLog =================================================================== --- atk/ChangeLog (revision 4688) +++ atk/ChangeLog (working copy) @@ -1,3 +1,7 @@ +2011-09-19 Nikolai Weibull + + * ext/atk/*.c: Ensure that all array conversions are freed. + 2011-09-16 Nikolai Weibull * lib/atk.rb: Remove unused variable. Index: glib2/ext/glib2/rbgobj_valuearray.c =================================================================== --- glib2/ext/glib2/rbgobj_valuearray.c (revision 4688) +++ glib2/ext/glib2/rbgobj_valuearray.c (working copy) @@ -28,11 +28,42 @@ return ary; } +struct value_array_from_ruby_args { + VALUE ary; + long n; + GValueArray *result; +}; + +static VALUE +value_array_from_ruby_body(VALUE value) +{ + long i; + struct value_array_from_ruby_args *args = (struct value_array_from_ruby_args *)value; + + for (i = 0; i < args->n; i++) { + GValue v = { 0 }; + + g_value_init(&v, RVAL2GTYPE(RARRAY_PTR(args->ary)[i])); + rbgobj_rvalue_to_gvalue(RARRAY_PTR(args->ary)[i], &v); + + g_value_array_append(args->result, &v); + } + + return Qnil; +} + +static VALUE +value_array_from_ruby_rescue(VALUE value) +{ + g_value_array_free(((struct value_array_from_ruby_args *)value)->result); + + rb_exc_raise(rb_errinfo()); +} + static void value_array_from_ruby(const VALUE from, GValue *to) { - int i; - GValueArray *array; + struct value_array_from_ruby_args args; if (NIL_P(from)) { g_value_set_boxed(to, NULL); @@ -40,19 +71,14 @@ return; } - Check_Type(from, T_ARRAY); + args.ary = rb_ary_to_ary(from); + args.n = RARRAY_LEN(args.ary); + args.result = g_value_array_new(args.n); - array = g_value_array_new(RARRAY_LEN(from)); + rb_rescue(value_array_from_ruby_body, (VALUE)&args, + value_array_from_ruby_rescue, (VALUE)&args); - for (i = 0; i < RARRAY_LEN(from); i++) { - GValue v = { 0, }; - g_value_init(&v, RVAL2GTYPE(RARRAY_PTR(from)[i])); - rbgobj_rvalue_to_gvalue(RARRAY_PTR(from)[i], &v); - - g_value_array_append(array, &v); - } - - g_value_set_boxed(to, array); + g_value_set_boxed(to, args.result); } void Index: glib2/ext/glib2/rbglib.c =================================================================== --- glib2/ext/glib2/rbglib.c (revision 4688) +++ glib2/ext/glib2/rbglib.c (working copy) @@ -294,7 +294,7 @@ struct rval2strv_args { VALUE ary; long n; - const gchar **strings; + const gchar **result; }; static VALUE @@ -304,8 +304,8 @@ struct rval2strv_args *args = (struct rval2strv_args *)value; for (i = 0; i < args->n; i++) - args->strings[i] = RVAL2CSTR(RARRAY_PTR(args->ary)[i]); - args->strings[args->n] = NULL; + args->result[i] = RVAL2CSTR(RARRAY_PTR(args->ary)[i]); + args->result[args->n] = NULL; return Qnil; } @@ -313,38 +313,45 @@ static VALUE rbg_rval2strv_rescue(VALUE value) { - struct rval2strv_args *args = (struct rval2strv_args *)value; + g_free(((struct rval2strv_args *)value)->result); - g_free(args->strings); - rb_exc_raise(rb_errinfo()); } const gchar ** -rbg_rval2strv(VALUE value) +rbg_rval2strv(VALUE value, long *n) { struct rval2strv_args args; args.ary = rb_ary_to_ary(value); args.n = RARRAY_LEN(args.ary); - args.strings = g_new(const gchar *, args.n + 1); + args.result = g_new(const gchar *, args.n + 1); rb_rescue(rbg_rval2strv_body, (VALUE)&args, rbg_rval2strv_rescue, (VALUE)&args); - return args.strings; + if (n != NULL) + *n = args.n; + + return args.result; } const gchar ** -rbg_rval2strv_accept_nil(VALUE ary) +rbg_rval2strv_accept_nil(VALUE ary, long *n) { - return NIL_P(ary) ? NULL : rbg_rval2strv(ary); + if (!NIL_P(ary)) + rbg_rval2strv(ary, n); + + if (n != NULL) + *n = 0; + + return NULL; } struct rval2strv_dup_args { VALUE ary; long n; - gchar **strings; + gchar **result; }; static VALUE @@ -354,8 +361,8 @@ struct rval2strv_dup_args *args = (struct rval2strv_dup_args *)value; for (i = 0; i < args->n; i++) - args->strings[i] = g_strdup(RVAL2CSTR(RARRAY_PTR(args->ary)[i])); - args->strings[args->n] = NULL; + args->result[i] = g_strdup(RVAL2CSTR(RARRAY_PTR(args->ary)[i])); + args->result[args->n] = NULL; return Qnil; } @@ -363,32 +370,39 @@ static VALUE rbg_rval2strv_dup_rescue(VALUE value) { - struct rval2strv_dup_args *args = (struct rval2strv_dup_args *)value; + g_free(((struct rval2strv_dup_args *)value)->result); - g_free(args->strings); - rb_exc_raise(rb_errinfo()); } gchar ** -rbg_rval2strv_dup(VALUE value) +rbg_rval2strv_dup(VALUE value, long *n) { struct rval2strv_dup_args args; args.ary = rb_ary_to_ary(value); args.n = RARRAY_LEN(args.ary); - args.strings = g_new(gchar *, args.n + 1); + args.result = g_new(gchar *, args.n + 1); rb_rescue(rbg_rval2strv_dup_body, (VALUE)&args, rbg_rval2strv_dup_rescue, (VALUE)&args); - return args.strings; + if (n != NULL) + *n = args.n; + + return args.result; } gchar ** -rbg_rval2strv_dup_accept_nil(VALUE ary) +rbg_rval2strv_dup_accept_nil(VALUE ary, long *n) { - return NIL_P(ary) ? NULL : rbg_rval2strv_dup(ary); + if (!NIL_P(ary)) + rbg_rval2strv_dup(ary, n); + + if (n != NULL) + *n = 0; + + return NULL; } VALUE @@ -428,6 +442,264 @@ rbg_strv2rval_free_ensure, (VALUE)strings); } +struct rbg_rval2gbooleans_args { + VALUE ary; + long n; + gboolean *result; +}; + +static VALUE +rbg_rval2gbooleans_body(VALUE value) +{ + long i; + struct rbg_rval2gbooleans_args *args = (struct rbg_rval2gbooleans_args *)value; + + for (i = 0; i < args->n; i++) + args->result[i] = RVAL2CBOOL(RARRAY_PTR(args->ary)[i]); + + return Qnil; +} + +static VALUE +rbg_rval2gbooleans_rescue(VALUE value) +{ + g_free(((struct rbg_rval2gbooleans_args *)value)->result); + + rb_exc_raise(rb_errinfo()); +} + +gboolean * +rbg_rval2gbooleans(VALUE value, long *n) +{ + struct rbg_rval2gbooleans_args args; + + args.ary = rb_ary_to_ary(value); + args.n = RARRAY_LEN(args.ary); + args.result = g_new(gboolean, args.n + 1); + + rb_rescue(rbg_rval2gbooleans_body, (VALUE)&args, + rbg_rval2gbooleans_rescue, (VALUE)&args); + + *n = args.n; + + return args.result; +} + +struct rbg_rval2gints_args { + VALUE ary; + long n; + gint *result; +}; + +static VALUE +rbg_rval2gints_body(VALUE value) +{ + long i; + struct rbg_rval2gints_args *args = (struct rbg_rval2gints_args *)value; + + for (i = 0; i < args->n; i++) + args->result[i] = NUM2INT(RARRAY_PTR(args->ary)[i]); + + return Qnil; +} + +static VALUE +rbg_rval2gints_rescue(VALUE value) +{ + g_free(((struct rbg_rval2gints_args *)value)->result); + + rb_exc_raise(rb_errinfo()); +} + +gint * +rbg_rval2gints(VALUE value, long *n) +{ + struct rbg_rval2gints_args args; + + args.ary = rb_ary_to_ary(value); + args.n = RARRAY_LEN(args.ary); + args.result = g_new(gint, args.n + 1); + + rb_rescue(rbg_rval2gints_body, (VALUE)&args, + rbg_rval2gints_rescue, (VALUE)&args); + + *n = args.n; + + return args.result; +} + +struct rbg_rval2gint8s_args { + VALUE ary; + long n; + gint8 *result; +}; + +static VALUE +rbg_rval2gint8s_body(VALUE value) +{ + long i; + struct rbg_rval2gint8s_args *args = (struct rbg_rval2gint8s_args *)value; + + for (i = 0; i < args->n; i++) + args->result[i] = NUM2CHR(RARRAY_PTR(args->ary)[i]); + + return Qnil; +} + +static VALUE +rbg_rval2gint8s_rescue(VALUE value) +{ + g_free(((struct rbg_rval2gint8s_args *)value)->result); + + rb_exc_raise(rb_errinfo()); +} + +gint8 * +rbg_rval2gint8s(VALUE value, long *n) +{ + struct rbg_rval2gint8s_args args; + + args.ary = rb_ary_to_ary(value); + args.n = RARRAY_LEN(args.ary); + args.result = g_new(gint8, args.n + 1); + + rb_rescue(rbg_rval2gint8s_body, (VALUE)&args, + rbg_rval2gint8s_rescue, (VALUE)&args); + + *n = args.n; + + return args.result; +} + +struct rbg_rval2guint16s_args { + VALUE ary; + long n; + guint16 *result; +}; + +static VALUE +rbg_rval2guint16s_body(VALUE value) +{ + long i; + struct rbg_rval2guint16s_args *args = (struct rbg_rval2guint16s_args *)value; + + for (i = 0; i < args->n; i++) + args->result[i] = NUM2UINT(RARRAY_PTR(args->ary)[i]); + + return Qnil; +} + +static VALUE +rbg_rval2guint16s_rescue(VALUE value) +{ + g_free(((struct rbg_rval2guint16s_args *)value)->result); + + rb_exc_raise(rb_errinfo()); +} + +guint16 * +rbg_rval2guint16s(VALUE value, long *n) +{ + struct rbg_rval2guint16s_args args; + + args.ary = rb_ary_to_ary(value); + args.n = RARRAY_LEN(args.ary); + args.result = g_new(guint16, args.n + 1); + + rb_rescue(rbg_rval2guint16s_body, (VALUE)&args, + rbg_rval2guint16s_rescue, (VALUE)&args); + + *n = args.n; + + return args.result; +} + +struct rbg_rval2guint32s_args { + VALUE ary; + long n; + guint32 *result; +}; + +static VALUE +rbg_rval2guint32s_body(VALUE value) +{ + long i; + struct rbg_rval2guint32s_args *args = (struct rbg_rval2guint32s_args *)value; + + for (i = 0; i < args->n; i++) + args->result[i] = NUM2UINT(RARRAY_PTR(args->ary)[i]); + + return Qnil; +} + +static VALUE +rbg_rval2guint32s_rescue(VALUE value) +{ + g_free(((struct rbg_rval2guint32s_args *)value)->result); + + rb_exc_raise(rb_errinfo()); +} + +guint32 * +rbg_rval2guint32s(VALUE value, long *n) +{ + struct rbg_rval2guint32s_args args; + + args.ary = rb_ary_to_ary(value); + args.n = RARRAY_LEN(args.ary); + args.result = g_new(guint32, args.n + 1); + + rb_rescue(rbg_rval2guint32s_body, (VALUE)&args, + rbg_rval2guint32s_rescue, (VALUE)&args); + + *n = args.n; + + return args.result; +} + +struct rbg_rval2gdoubles_args { + VALUE ary; + long n; + gdouble *result; +}; + +static VALUE +rbg_rval2gdoubles_body(VALUE value) +{ + long i; + struct rbg_rval2gdoubles_args *args = (struct rbg_rval2gdoubles_args *)value; + + for (i = 0; i < args->n; i++) + args->result[i] = NUM2DBL(RARRAY_PTR(args->ary)[i]); + + return Qnil; +} + +static VALUE +rbg_rval2gdoubles_rescue(VALUE value) +{ + g_free(((struct rbg_rval2gdoubles_args *)value)->result); + + rb_exc_raise(rb_errinfo()); +} + +gdouble * +rbg_rval2gdoubles(VALUE value, long *n) +{ + struct rbg_rval2gdoubles_args args; + + args.ary = rb_ary_to_ary(value); + args.n = RARRAY_LEN(args.ary); + args.result = g_new(gdouble, args.n + 1); + + rb_rescue(rbg_rval2gdoubles_body, (VALUE)&args, + rbg_rval2gdoubles_rescue, (VALUE)&args); + + *n = args.n; + + return args.result; +} + #if 0 /* 2004-04-15 Commented out by Masao. Index: glib2/ext/glib2/rbglib.h =================================================================== --- glib2/ext/glib2/rbglib.h (revision 4688) +++ glib2/ext/glib2/rbglib.h (working copy) @@ -60,14 +60,25 @@ #define CSTRFILENAME2RVAL_FREE(s) (rbg_filename_to_ruby_free(s)) #define CSTRFILENAMEARRAY2RVAL_FREE(s) (rbg_filename_gslist_to_array_free(s)) -#define RVAL2STRV(ary) rbg_rval2strv(ary) -#define RVAL2STRV_ACCEPT_NIL(ary) rbg_rval2strv_accept_nil(ary) -#define RVAL2STRV_DUP(ary) rbg_rval2strv_dup(ary) -#define RVAL2STRV_DUP_ACCEPT_NIL(ary) rbg_rval2strv_dup_accept_nil(ary) +#define RVAL2STRS(ary, n) rbg_rval2strv(ary, n) +#define RVAL2STRS_ACCEPT_NIL(ary, n) rbg_rval2strv_accept_nil(ary, n) +#define RVAL2STRV(ary) rbg_rval2strv(ary, NULL) +#define RVAL2STRV_ACCEPT_NIL(ary) rbg_rval2strv_accept_nil(ary, NULL) +#define RVAL2STRS_DUP(ary, n) rbg_rval2strv_dup(ary, n) +#define RVAL2STRS_DUP_ACCEPT_NIL(ary, n) rbg_rval2strv_dup_accept_nil(ary, n) +#define RVAL2STRV_DUP(ary) rbg_rval2strv_dup(ary, NULL) +#define RVAL2STRV_DUP_ACCEPT_NIL(ary) rbg_rval2strv_dup_accept_nil(ary, NULL) #define STRV2RVAL(strings) rbg_strv2rval(strings) #define STRV2RVAL_FREE(strings) rbg_strv2rval_free(strings) +#define RVAL2GBOOLEANS(ary, n) rbg_rval2gbooleans(ary, n) +#define RVAL2GINTS(ary, n) rbg_rval2gints(ary, n) +#define RVAL2GINT8S(ary, n) rbg_rval2gint8s(ary, n) +#define RVAL2GUINT16S(ary, n) rbg_rval2guint16s(ary, n) +#define RVAL2GUINT32S(ary, n) rbg_rval2guint32s(ary, n) +#define RVAL2GDOUBLES(ary, n) rbg_rval2gdoubles(ary, n) + #define CBOOL2RVAL(b) ((b) ? Qtrue : Qfalse) #define RVAL2CBOOL(b) (RTEST(b)) #define GERROR2RVAL(error) (rbgerr_gerror2exception(error)) @@ -109,14 +120,20 @@ extern gchar *rbg_filename_from_ruby(VALUE filename); extern VALUE rbg_filename_gslist_to_array_free(GSList *list); -const gchar **rbg_rval2strv(VALUE ary); -const gchar **rbg_rval2strv_accept_nil(VALUE ary); -gchar **rbg_rval2strv_dup(VALUE ary); -gchar **rbg_rval2strv_dup_accept_nil(VALUE ary); -const gchar **rbg_rval2argv(VALUE ary); +const gchar **rbg_rval2strv(VALUE ary, long *n); +const gchar **rbg_rval2strv_accept_nil(VALUE ary, long *n); +gchar **rbg_rval2strv_dup(VALUE ary, long *n); +gchar **rbg_rval2strv_dup_accept_nil(VALUE ary, long *n); VALUE rbg_strv2rval(const gchar **strings); VALUE rbg_strv2rval_free(gchar **strings); +gboolean *rbg_rval2gbooleans(VALUE value, long *n); +gint *rbg_rval2gints(VALUE value, long *n); +gint8 *rbg_rval2gint8s(VALUE value, long *n); +guint16 *rbg_rval2guint16s(VALUE value, long *n); +guint32 *rbg_rval2guint32s(VALUE value, long *n); +gdouble *rbg_rval2gdoubles(VALUE value, long *n); + /* rbgerror.h */ extern VALUE rbgerr_gerror2exception(GError *error); extern VALUE rbgerr_define_gerror(GQuark domain, const gchar* name, VALUE module, VALUE parent, VALUE gtype); Index: glib2/ext/glib2/rbglib_keyfile.c =================================================================== --- glib2/ext/glib2/rbglib_keyfile.c (revision 4688) +++ glib2/ext/glib2/rbglib_keyfile.c (working copy) @@ -505,16 +505,15 @@ #endif static VALUE -keyfile_set_string_list(VALUE self, VALUE group_name, VALUE key, VALUE rblist) +keyfile_set_string_list(VALUE self, VALUE rbgroup_name, VALUE rbkey, VALUE rblist) { - VALUE ary = rb_ary_to_ary(rblist); - const gchar **list = RVAL2STRV(ary); + GKeyFile *key_file = _SELF(self); + const gchar *group_name = RVAL2CSTR(rbgroup_name); + const gchar *key = RVAL2CSTR(rbkey); + long n; + const gchar **list = RVAL2STRS(rblist, &n); - g_key_file_set_string_list(_SELF(self), - RVAL2CSTR(group_name), - RVAL2CSTR(key), - list, - RARRAY_LEN(ary)); + g_key_file_set_string_list(key_file, group_name, key, list, n); g_free(list); @@ -522,17 +521,16 @@ } static VALUE -keyfile_set_locale_string_list(VALUE self, VALUE group_name, VALUE key, VALUE locale, VALUE rblist) +keyfile_set_locale_string_list(VALUE self, VALUE rbgroup_name, VALUE rbkey, VALUE rblocale, VALUE rblist) { - VALUE ary = rb_ary_to_ary(rblist); - const gchar **list = RVAL2STRV(ary); + GKeyFile *key_file = _SELF(self); + const gchar *group_name = RVAL2CSTR(rbgroup_name); + const gchar *key = RVAL2CSTR(rbkey); + const gchar *locale = RVAL2CSTR(rblocale); + long n; + const gchar **list = RVAL2STRS(rblist, &n); - g_key_file_set_locale_string_list(_SELF(self), - RVAL2CSTR(group_name), - RVAL2CSTR(key), - RVAL2CSTR(locale), - list, - RARRAY_LEN(ary)); + g_key_file_set_locale_string_list(key_file, group_name, key, locale, list, n); g_free(list); @@ -540,68 +538,48 @@ } static VALUE -keyfile_set_boolean_list(VALUE self, VALUE group_name, VALUE key, VALUE list) +keyfile_set_boolean_list(VALUE self, VALUE rbgroup_name, VALUE rbkey, VALUE rblist) { - VALUE ary; - long i, n; - gboolean *booleans; + GKeyFile *key_file = _SELF(self); + const gchar *group_name = RVAL2CSTR(rbgroup_name); + const gchar *key = RVAL2CSTR(rbkey); + long n; + gboolean *list = RVAL2GBOOLEANS(rblist, &n); - ary = rb_ary_to_ary(list); - n = RARRAY_LEN(ary); - booleans = ALLOCA_N(gboolean, n); - for (i = 0; i < n; i++) - booleans[i] = RVAL2CBOOL(RARRAY_PTR(ary)[i]); + g_key_file_set_boolean_list(key_file, group_name, key, list, n); - g_key_file_set_boolean_list(_SELF(self), - RVAL2CSTR(group_name), - RVAL2CSTR(key), - booleans, - n); + g_free(list); return self; } static VALUE -keyfile_set_integer_list(VALUE self, VALUE group_name, VALUE key, VALUE list) +keyfile_set_integer_list(VALUE self, VALUE rbgroup_name, VALUE rbkey, VALUE rblist) { - VALUE ary; - long i, n; - gint *ints; + GKeyFile *key_file = _SELF(self); + const gchar *group_name = RVAL2CSTR(rbgroup_name); + const gchar *key = RVAL2CSTR(rbkey); + long n; + gint *list = RVAL2GINTS(rblist, &n); - ary = rb_ary_to_ary(list); - n = RARRAY_LEN(ary); - ints = ALLOCA_N(gint, n); - for (i = 0; i < n; i++) - ints[i] = NUM2INT(RARRAY_PTR(ary)[i]); + g_key_file_set_integer_list(key_file, group_name, key, list, n); - g_key_file_set_integer_list(_SELF(self), - RVAL2CSTR(group_name), - RVAL2CSTR(key), - ints, - n); + g_free(list); return self; } #if GLIB_CHECK_VERSION(2,12,0) static VALUE -keyfile_set_double_list(VALUE self, VALUE group_name, VALUE key, VALUE list) +keyfile_set_double_list(VALUE self, VALUE rbgroup_name, VALUE rbkey, VALUE rblist) { - VALUE ary; - long i, n; - gdouble *doubles; - - ary = rb_ary_to_ary(list); - n = RARRAY_LEN(ary); - doubles = ALLOCA_N(gdouble, n); - for (i = 0; i < n; i++) - doubles[i] = NUM2DBL(RARRAY_PTR(ary)[i]); + GKeyFile *key_file = _SELF(self); + const gchar *group_name = RVAL2CSTR(rbgroup_name); + const gchar *key = RVAL2CSTR(rbkey); + long n; + gdouble *list = RVAL2GDOUBLES(rblist, &n); - g_key_file_set_double_list(_SELF(self), - RVAL2CSTR(group_name), - RVAL2CSTR(key), - doubles, - n); + g_key_file_set_double_list(key_file, group_name, key, list, n); return self; } Index: glib2/ext/glib2/glib2.def =================================================================== --- glib2/ext/glib2/glib2.def (revision 4688) +++ glib2/ext/glib2/glib2.def (working copy) @@ -75,6 +75,12 @@ rbg_rval2strv_dup_accept_nil rbg_strv2rval rbg_strv2rval_free + rbg_rval2gbooleans + rbg_rval2gints + rbg_rval2gint8s + rbg_rval2guint16s + rbg_rval2guint32s + rbg_rval2gdoubles rbgutil_id_module_eval DATA rbgutil_def_setters rbgutil_glist2ary Index: glib2/ext/glib2/rbglib_bookmarkfile.c =================================================================== --- glib2/ext/glib2/rbglib_bookmarkfile.c (revision 4688) +++ glib2/ext/glib2/rbglib_bookmarkfile.c (working copy) @@ -370,13 +370,15 @@ } static VALUE -bf_set_groups(VALUE self, VALUE uri, VALUE rbgroups) +bf_set_groups(VALUE self, VALUE rburi, VALUE rbgroups) { - VALUE ary = rb_ary_to_ary(rbgroups); - const gchar **groups = RVAL2STRV(ary); - - g_bookmark_file_set_groups(_SELF(self), RVAL2CSTR(uri), groups, RARRAY_LEN(ary)); + GBookmarkFile *bookmark = _SELF(self); + const gchar *uri = RVAL2CSTR(rburi); + long n; + const gchar **groups = RVAL2STRS(rbgroups, &n); + g_bookmark_file_set_groups(bookmark, uri, groups, n); + g_free(groups); return self; Index: glib2/ext/glib2/rbgobj_signal.c =================================================================== --- glib2/ext/glib2/rbgobj_signal.c (revision 4688) +++ glib2/ext/glib2/rbgobj_signal.c (working copy) @@ -118,7 +118,7 @@ param_types = NULL; } else { n_params = RARRAY_LEN(params); - param_types = ALLOCA_N(GType, n_params); + param_types = g_new(GType, n_params); for (i = 0; i < n_params; i++) param_types[i] = rbgobj_gtype_get(RARRAY_PTR(params)[i]); } @@ -134,6 +134,8 @@ n_params, param_types); + g_free(param_types); + if (!sig) rb_raise(rb_eRuntimeError, "g_signal_newv failed"); Index: glib2/ext/glib2/rbglib_completion.c =================================================================== --- glib2/ext/glib2/rbglib_completion.c (revision 4688) +++ glib2/ext/glib2/rbglib_completion.c (working copy) @@ -84,7 +84,7 @@ static VALUE comp_add_items(VALUE self, VALUE items) { - gint i, len; + long i, len; GList* list = (GList*)NULL; VALUE items_internal = rb_ivar_get(self, id_items_internal); @@ -104,7 +104,7 @@ static VALUE comp_remove_items(VALUE self, VALUE items) { - gint i, len; + long i, len; GList* list = (GList*)NULL; VALUE items_internal = rb_ivar_get(self, id_items_internal); Index: glib2/ChangeLog =================================================================== --- glib2/ChangeLog (revision 4688) +++ glib2/ChangeLog (working copy) @@ -1,3 +1,7 @@ +2011-09-19 Nikolai Weibull + + * ext/glib2/*.c: Ensure that all array conversions are freed. + 2011-09-19 Kouhei Sutou * lib/mkmf-gnome2.rb (check_cairo): really support RubyGems 1.8.6... Index: gio2/ext/gio2/util.c =================================================================== --- gio2/ext/gio2/util.c (revision 4688) +++ gio2/ext/gio2/util.c (working copy) @@ -117,26 +117,48 @@ rbgio_fds_to_ary_free_ensure, (VALUE)fds); } -GList * -rbgio_gfile_ary_to_glist(VALUE ary) +struct rbgio_gfile_ary_to_glist_args { + VALUE ary; + long n; + GList *result; +}; + +static VALUE +rbgio_gfile_ary_to_glist_body(VALUE value) { - int i, n; - volatile GFile *file; - GList *list = NULL; + long i; + struct rbgio_gfile_ary_to_glist_args *args = (struct rbgio_gfile_ary_to_glist_args *)value; - ary = rb_ary_to_ary(ary); - n = RARRAY_LEN(ary); + for (i = 0; i < args->n; i++) + args->result = g_list_append(args->result, RVAL2GFILE(RARRAY_PTR(args->ary)[i])); - for (i = 0; i < n; i++) - file = RVAL2GFILE(RARRAY_PTR(ary)[i]); + return Qnil; +} - for (i = 0; i < n; i++) - list = g_list_append(list, RVAL2GFILE(RARRAY_PTR(ary)[i])); +static G_GNUC_NORETURN VALUE +rbgio_gfile_ary_to_glist_rescue(VALUE value) +{ + g_list_free(((struct rbgio_gfile_ary_to_glist_args *)value)->result); - return list; + rb_exc_raise(rb_errinfo()); } GList * +rbgio_gfile_ary_to_glist(VALUE value) +{ + struct rbgio_gfile_ary_to_glist_args args; + + args.ary = rb_ary_to_ary(value); + args.n = RARRAY_LEN(args.ary); + args.result = NULL; + + rb_rescue(rbgio_gfile_ary_to_glist_body, (VALUE)&args, + rbgio_gfile_ary_to_glist_rescue, (VALUE)&args); + + return args.result; +} + +GList * rbgio_gfile_ary_to_glist_accept_nil(VALUE ary) { if (NIL_P(ary)) @@ -165,39 +187,6 @@ } } -VALUE -rbgio_str_vector_to_ary(const gchar * const *vector) -{ - int i, n; - VALUE ary; - - if (vector == NULL) - return Qnil; - - for (i = n = 0; vector[i] != NULL; i++) - n++; - ary = rb_ary_new2(n); - for (i = 0; i < n; i++) - RARRAY_PTR(ary)[i] = CSTR2RVAL(vector[i]); - - return ary; -} - -static VALUE -rbgio_str_vector_to_ary_free_ensure(gchar **vector) -{ - g_strfreev(vector); - - return Qnil; -} - -VALUE -rbgio_str_vector_to_ary_free(gchar **vector) -{ - return rb_ensure(rbgio_str_vector_to_ary, (VALUE)vector, - rbgio_str_vector_to_ary_free_ensure, (VALUE)vector); -} - struct async_ready_callback_data { GAsyncResult *result; Index: gio2/ext/gio2/gio2.h =================================================================== --- gio2/ext/gio2/gio2.h (revision 4688) +++ gio2/ext/gio2/gio2.h (working copy) @@ -168,6 +168,7 @@ /* Integer Type Conversion Macros */ #define FD2RVAL(value) INT2FIX(value) #define RVAL2FD(value) FIX2INT(value) +#define RVAL2FDS(value, n) RVAL2GINTS(value, n) #define GINT2RVAL(value) INT2NUM(value) #define RVAL2GINT(value) NUM2INT(value) Index: gio2/ext/gio2/gunixfdlist.c =================================================================== --- gio2/ext/gio2/gunixfdlist.c (revision 4688) +++ gio2/ext/gio2/gunixfdlist.c (working copy) @@ -29,22 +29,23 @@ unixfdlist_initialize(int argc, VALUE *argv, VALUE self) { VALUE rbfds; - gint i, n_fds; + long n; gint *fds; + GUnixFDList *list; rb_scan_args(argc, argv, "0*", &rbfds); - n_fds = RARRAY_LEN(rbfds); - if (n_fds == 0) { + fds = RVAL2FDS(rbfds, &n); + if (n == 0) { G_INITIALIZE(self, g_unix_fd_list_new()); return Qnil; } - fds = ALLOCA_N(gint, n_fds); - for (i = 0; i < n_fds; i++) - fds[0] = RVAL2FD(RARRAY_PTR(rbfds)[i]); + list = g_unix_fd_list_new_from_array(fds, n); - G_INITIALIZE(self, g_unix_fd_list_new_from_array(fds, n_fds)); + g_free(fds); + G_INITIALIZE(self, list); + return Qnil; } Index: gio2/ChangeLog =================================================================== --- gio2/ChangeLog (revision 4688) +++ gio2/ChangeLog (working copy) @@ -1,3 +1,7 @@ +2011-09-19 Nikolai Weibull + + * ext/gio2/*.c: Ensure that all array conversions are freed. + 2011-09-16 Nikolai Weibull * lib/gio2.rb: Remove unused variable. Index: pango/ext/pango/rbpangolayoutline.c =================================================================== --- pango/ext/pango/rbpangolayoutline.c (revision 4688) +++ pango/ext/pango/rbpangolayoutline.c (working copy) @@ -158,24 +158,50 @@ } #endif +struct layout_line_set_runs_args { + PangoLayoutLine *line; + VALUE ary; + long n; + GSList *result; +}; + static VALUE -layout_line_set_runs(VALUE self, VALUE ary) +layout_line_set_runs_body(VALUE value) { - int i, len; - GSList* list = NULL; + struct layout_line_set_runs_args *args = (struct layout_line_set_runs_args *)value; + long i; - len = RARRAY_LEN(ary); + for (i = 0; i < args->n; i++) + args->result = g_slist_append(args->result, + RVAL2BOXED(RARRAY_PTR(args->ary)[i], + PANGO_TYPE_GLYPH_ITEM)); - for (i = 0; i < len; i++) { - list = g_slist_append(list, RVAL2BOXED(RARRAY_PTR(ary)[i], - PANGO_TYPE_GLYPH_ITEM)); - } + g_slist_free(args->line->runs); + args->line->runs = args->result; - if (_SELF(self)->runs) { - g_slist_free(_SELF(self)->runs); - } - _SELF(self)->runs = list; + return Qnil; +} +static VALUE +layout_line_set_runs_rescue(VALUE value) +{ + g_slist_free(((struct layout_line_set_runs_args *)value)->result); + + rb_exc_raise(rb_errinfo()); +} + +static VALUE +layout_line_set_runs(VALUE self, VALUE attrs) +{ + struct layout_line_set_runs_args args; + args.line = _SELF(self); + args.ary = rb_ary_to_ary(attrs); + args.n = RARRAY_LEN(args.ary); + args.result = NULL; + + rb_rescue(layout_line_set_runs_body, (VALUE)&args, + layout_line_set_runs_rescue, (VALUE)&args); + return self; } Index: pango/ext/pango/rbpangoanalysis.c =================================================================== --- pango/ext/pango/rbpangoanalysis.c (revision 4688) +++ pango/ext/pango/rbpangoanalysis.c (working copy) @@ -130,18 +130,47 @@ return BOXED2RVAL(_SELF(self)->language, PANGO_TYPE_LANGUAGE); } +struct ana_set_extra_attrs_args { + PangoAnalysis *analysis; + VALUE ary; + long n; + GSList *result; +}; + static VALUE +ana_set_extra_attrs_body(VALUE value) +{ + struct ana_set_extra_attrs_args *args = (struct ana_set_extra_attrs_args *)value; + long i; + + for (i = 0; i < args->n; i++) + args->result = g_slist_append(args->result, RVAL2ATTR(RARRAY_PTR(args->ary)[i])); + + args->analysis->extra_attrs = args->result; + + return Qnil; +} + +static VALUE +ana_set_extra_attrs_rescue(VALUE value) +{ + g_slist_free(((struct ana_set_extra_attrs_args *)value)->result); + + rb_exc_raise(rb_errinfo()); +} + +static VALUE ana_set_extra_attrs(VALUE self, VALUE attrs) { - gint i; - gint len = RARRAY_LEN(attrs); - GSList* gattrs = NULL; + struct ana_set_extra_attrs_args args; + args.analysis = _SELF(self); + args.ary = rb_ary_to_ary(attrs); + args.n = RARRAY_LEN(args.ary); + args.result = NULL; - for (i = 0; i < len; i++){ - gattrs = g_slist_append(gattrs, RVAL2ATTR(RARRAY_PTR(attrs)[i])); - } + rb_rescue(ana_set_extra_attrs_body, (VALUE)&args, + ana_set_extra_attrs_rescue, (VALUE)&args); - _SELF(self)->extra_attrs = gattrs; return self; } Index: pango/ext/pango/rbpangomain.c =================================================================== --- pango/ext/pango/rbpangomain.c (revision 4688) +++ pango/ext/pango/rbpangomain.c (working copy) @@ -15,25 +15,51 @@ * Rendering */ +struct rpango_reorder_items_args { + PangoItem *item; + VALUE ary; + long n; + GList *result; +}; + static VALUE -rpango_reorder_items(VALUE self, VALUE logical_items) +rpango_reorder_items_body(VALUE value) { - int i; - GList *glist = NULL; - GList* ret; + struct rpango_reorder_items_args *args = (struct rpango_reorder_items_args *)value; + long i; + GList *result; - Check_Type(logical_items, T_ARRAY); + for (i = 0; i < args->n; i++) + args->result = g_list_append(args->result, + RVAL2BOXED(RARRAY_PTR(args->ary)[i], + PANGO_TYPE_ITEM)); - for (i = 0; i < RARRAY_LEN(logical_items); i++){ - glist = g_list_append(glist, RVAL2BOXED(RARRAY_PTR(logical_items)[i], PANGO_TYPE_ITEM)); - } + result = pango_reorder_items(args->result); + g_list_free(args->result); - ret = pango_reorder_items(glist); - g_list_free(glist); + return GLIST2ARY2(result, PANGO_TYPE_ITEM); +} - return GLIST2ARY2(ret, PANGO_TYPE_ITEM); +static VALUE +rpango_reorder_items_ensure(VALUE value) +{ + g_list_free(((struct rpango_reorder_items_args *)value)->result); + + return Qnil; } +static VALUE +rpango_reorder_items(VALUE self, VALUE attrs) +{ + struct rpango_reorder_items_args args; + args.ary = rb_ary_to_ary(attrs); + args.n = RARRAY_LEN(args.ary); + args.result = NULL; + + return rb_ensure(rpango_reorder_items_body, (VALUE)&args, + rpango_reorder_items_ensure, (VALUE)&args); +} + #if PANGO_CHECK_VERSION(1,4,0) static VALUE rpango_unichar_direction(VALUE self, VALUE ch) Index: pango/ChangeLog =================================================================== --- pango/ChangeLog (revision 4688) +++ pango/ChangeLog (working copy) @@ -1,3 +1,7 @@ +2011-09-19 Nikolai Weibull + + * ext/pango/*.c: Ensure that all array conversions are freed. + 2011-09-16 Nikolai Weibull * lib/pango.rb: Remove unused variable. Index: gtk2/ext/gtk2/rbgtkwindow.c =================================================================== --- gtk2/ext/gtk2/rbgtkwindow.c (revision 4688) +++ gtk2/ext/gtk2/rbgtkwindow.c (working copy) @@ -463,17 +463,15 @@ } static VALUE -gwin_s_set_default_icon_list(VALUE self, VALUE list) +gwin_s_set_default_icon_list(VALUE self, VALUE rblist) { - int i; - GList *glist = NULL; - Check_Type(list, T_ARRAY); - for (i = 0; i < RARRAY_LEN(list); i++){ - glist = g_list_append(glist, RVAL2GOBJ(RARRAY_PTR(list)[i])); - } - gtk_window_set_default_icon_list(glist); - g_list_free(glist); - return list; + GList *list = RVAL2GDKPIXBUFGLIST(rblist); + + gtk_window_set_default_icon_list(list); + + g_list_free(list); + + return rblist; } #if GTK_CHECK_VERSION(2,2,0) @@ -527,17 +525,17 @@ } static VALUE -gwin_set_icon_list(VALUE self, VALUE list) +gwin_set_icon_list(VALUE self, VALUE rblist) { - int i; - GList *glist = NULL; - Check_Type(list, T_ARRAY); - for (i = 0; i < RARRAY_LEN(list); i++){ - glist = g_list_append(glist, RVAL2GOBJ(RARRAY_PTR(list)[i])); - } - gtk_window_set_icon_list(_SELF(self), glist); - g_list_free(glist); - return list; + GtkWindow *window = _SELF(self); + GList *list = RVAL2GDKPIXBUFGLIST(rblist); + + gtk_window_set_icon_list(window, list); + + g_list_free(list); + + /* TODO: Shouldn’t we return self? */ + return rblist; } #if GTK_CHECK_VERSION(2,2,0) Index: gtk2/ext/gtk2/rbgtktextbuffer.c =================================================================== --- gtk2/ext/gtk2/rbgtktextbuffer.c (revision 4688) +++ gtk2/ext/gtk2/rbgtktextbuffer.c (working copy) @@ -684,6 +684,8 @@ if (RARRAY_LEN(tags) == 0) return self; + /* TODO: Do we really want to do this before we know that everything + * below passed without any errors? */ G_CHILD_ADD(self, tags); gtk_text_buffer_get_iter_at_offset(_SELF(self), &start, start_offset); Index: gtk2/ext/gtk2/rbgtkcolorsel.c =================================================================== --- gtk2/ext/gtk2/rbgtkcolorsel.c (revision 4688) +++ gtk2/ext/gtk2/rbgtkcolorsel.c (working copy) @@ -78,29 +78,72 @@ return ary; } +struct rbgdk_rval2gdkcolors_args { + VALUE ary; + long n; + GdkColor *result; +}; + static VALUE +rbgdk_rval2gdkcolors_body(VALUE value) +{ + long i; + struct rbgdk_rval2gdkcolors_args *args = (struct rbgdk_rval2gdkcolors_args *)value; + + for (i = 0; i < args->n; i++) + args->result[i] = *RVAL2GDKCOLOR(RARRAY_PTR(args->ary)[i]); + + return Qnil; +} + +static VALUE +rbgdk_rval2gdkcolors_rescue(VALUE value) +{ + g_free(((struct rbgdk_rval2gdkcolors_args *)value)->result); + + rb_exc_raise(rb_errinfo()); +} + +static GdkColor * +rbgdk_rval2gdkcolors(VALUE value, long *n) +{ + struct rbgdk_rval2gdkcolors_args args; + + args.ary = rb_ary_to_ary(value); + args.n = RARRAY_LEN(args.ary); + args.result = g_new(GdkColor, args.n + 1); + + rb_rescue(rbgdk_rval2gdkcolors_body, (VALUE)&args, + rbgdk_rval2gdkcolors_rescue, (VALUE)&args); + + if (n != NULL) + *n = args.n; + + return args.result; +} + +#define RVAL2GDKCOLORS(value, n) rbgdk_rval2gdkcolors(value, n) + +static VALUE colorsel_s_palette_to_string(int argc, VALUE *argv, VALUE self) { - GdkColor* gcolors; - GdkColor* gcolor; - VALUE colors; - gint i, len; + VALUE rbcolors; + long n; + GdkColor *colors; + gchar *palette; - if (argc > 1) { - rb_scan_args(argc, argv, "*", &colors); - } else { - rb_scan_args(argc, argv, "10", &colors); - } + if (argc > 1) + rb_scan_args(argc, argv, "*", &rbcolors); + else + rb_scan_args(argc, argv, "10", &rbcolors); - len = RARRAY_LEN(colors); - gcolors = ALLOCA_N(GdkColor, len); + colors = RVAL2GDKCOLORS(rbcolors, &n); - for (i = 0; i < len; i++) { - gcolor = RVAL2GDKCOLOR(RARRAY_PTR(colors)[i]); - gcolors[i] = *gcolor; - } + palette = gtk_color_selection_palette_to_string(colors, n); - return CSTR2RVAL(gtk_color_selection_palette_to_string((const GdkColor*)gcolors, len)); + g_free(colors); + + return CSTR2RVAL_FREE(palette); } #if GTK_CHECK_VERSION(2,2,0) Index: gtk2/ext/gtk2/rbgtkimcontextsimple.c =================================================================== --- gtk2/ext/gtk2/rbgtkimcontextsimple.c (revision 4688) +++ gtk2/ext/gtk2/rbgtkimcontextsimple.c (working copy) @@ -16,21 +16,32 @@ imcsimple_initialize(VALUE self) { G_INITIALIZE(self, gtk_im_context_simple_new()); + return Qnil; } +/* TODO: Why are we taking a third argument? Shouldn’t it be determined by the + * length of rbdata? */ static VALUE -imcsimple_add_table(VALUE self, VALUE data, VALUE max_seq_len, VALUE n_seqs) +imcsimple_add_table(VALUE self, VALUE rbdata, VALUE rbmax_seq_len, VALUE rbn_seqs) { - int i; - guint16* gdata = ALLOCA_N(guint16, RARRAY_LEN(data)); - - for (i = 0; i < RARRAY_LEN(data); i++) { - gdata[i] = NUM2INT(RARRAY_PTR(data)[i]); - } - - gtk_im_context_simple_add_table(_SELF(self), gdata, - NUM2INT(max_seq_len), NUM2INT(n_seqs)); + GtkIMContextSimple *context_simple = _SELF(self); + gint max_seq_len = NUM2INT(rbmax_seq_len); + gint n_seqs = NUM2INT(rbn_seqs); + long n; + guint16 *data; + + if (max_seq_len > GTK_MAX_COMPOSE_LEN) + rb_raise(rb_eArgError, + "max_seq_len cannot be greater than GTK_MAX_COMPOSE_LEN: %d > %d", + max_seq_len, GTK_MAX_COMPOSE_LEN); + + data = RVAL2GUINT16S(rbdata, &n); + + gtk_im_context_simple_add_table(context_simple, data, max_seq_len, n_seqs); + + g_free(data); + return self; } Index: gtk2/ext/gtk2/rbgtkselection.c =================================================================== --- gtk2/ext/gtk2/rbgtkselection.c (revision 4688) +++ gtk2/ext/gtk2/rbgtkselection.c (working copy) @@ -51,11 +51,17 @@ } static VALUE -gtkdrag_selection_add_targets(VALUE self, VALUE widget, VALUE selection, VALUE targets) +gtkdrag_selection_add_targets(VALUE self, VALUE rbwidget, VALUE rbselection, VALUE rbtargets) { - gtk_selection_add_targets(RVAL2WIDGET(widget), - RVAL2ATOM(selection), - rbgtk_get_target_entry(targets), RARRAY_LEN(targets)); + GtkWidget *widget = RVAL2WIDGET(rbwidget); + GdkAtom selection = RVAL2ATOM(rbselection); + long n; + GtkTargetEntry *targets = RVAL2GTKTARGETENTRIES(rbtargets, &n); + + gtk_selection_add_targets(widget, selection, targets, n); + + g_free(targets); + return self; } @@ -84,57 +90,61 @@ #if GTK_CHECK_VERSION(2,10,0) static VALUE -targets_include_image(VALUE self, VALUE targets, VALUE writable) +targets_include_image(VALUE self, VALUE rbtargets, VALUE rbwritable) { - gint i; - gint len = RARRAY_LEN(targets); - GdkAtom* gtargets = ALLOCA_N(GdkAtom, len); + gboolean writable = RVAL2CBOOL(rbwritable); + long n; + GdkAtom *targets = RVAL2GDKATOMS(rbtargets, &n); + gboolean result; - for (i = 0; i < len; i++){ - gtargets[i] = RVAL2ATOM(RARRAY_PTR(targets)[i]); - } + result = gtk_targets_include_image(targets, n, writable); - return CBOOL2RVAL(gtk_targets_include_image(gtargets, len, RVAL2CBOOL(writable))); + g_free(targets); + + return result; } static VALUE -targets_include_text(VALUE self, VALUE targets) +targets_include_text(VALUE self, VALUE rbtargets) { - gint i; - gint len = RARRAY_LEN(targets); - GdkAtom* gtargets = ALLOCA_N(GdkAtom, len); - for (i = 0; i < len; i++){ - gtargets[i] = RVAL2ATOM(RARRAY_PTR(targets)[i]); - } - return CBOOL2RVAL(gtk_targets_include_text(gtargets, len)); + long n; + GdkAtom *targets = RVAL2GDKATOMS(rbtargets, &n); + gboolean result; + + result = gtk_targets_include_text(targets, n); + + g_free(targets); + + return result; } static VALUE -targets_include_uri(VALUE self, VALUE targets) +targets_include_uri(VALUE self, VALUE rbtargets) { - gint i; - gint len = RARRAY_LEN(targets); - GdkAtom* gtargets = ALLOCA_N(GdkAtom, len); + long n; + GdkAtom *targets = RVAL2GDKATOMS(rbtargets, &n); + gboolean result; - for (i = 0; i < len; i++){ - gtargets[i] = RVAL2ATOM(RARRAY_PTR(targets)[i]); - } + result = gtk_targets_include_uri(targets, n); - return CBOOL2RVAL(gtk_targets_include_uri(gtargets, len)); + g_free(targets); + + return result; } static VALUE -targets_include_rich_text(VALUE self, VALUE targets, VALUE buffer) +targets_include_rich_text(VALUE self, VALUE rbtargets, VALUE rbbuffer) { - gint i; - gint len = RARRAY_LEN(targets); - GdkAtom* gtargets = ALLOCA_N(GdkAtom, len); + GtkTextBuffer *buffer = GTK_TEXT_BUFFER(RVAL2GOBJ(rbbuffer)); + long n; + GdkAtom *targets = RVAL2GDKATOMS(rbtargets, &n); + gboolean result; - for (i = 0; i < len; i++){ - gtargets[i] = RVAL2ATOM(RARRAY_PTR(targets)[i]); - } + result = gtk_targets_include_rich_text(targets, n, buffer); - return CBOOL2RVAL(gtk_targets_include_rich_text(gtargets, len, RVAL2GOBJ(buffer))); + g_free(targets); + + return result; } #endif Index: gtk2/ext/gtk2/rbgtkdialog.c =================================================================== --- gtk2/ext/gtk2/rbgtkdialog.c (revision 4688) +++ gtk2/ext/gtk2/rbgtkdialog.c (working copy) @@ -31,21 +31,47 @@ RVAL2GENUM(response_id, GTK_TYPE_RESPONSE_TYPE))); } +struct rbgtk_dialog_add_buttons_internal_args { + VALUE self; + VALUE buttons; +}; + +static VALUE +rbgtk_dialog_add_buttons_internal_body(VALUE value) +{ + struct rbgtk_dialog_add_buttons_internal_args *args = (struct rbgtk_dialog_add_buttons_internal_args *)value; + long i; + long n = RARRAY_LEN(args->buttons); + + for (i = 0; i < n; i++) { + VALUE button = rb_ary_to_ary(RARRAY_PTR(args->buttons)[i]); + + dialog_add_button(args->self, RARRAY_PTR(button)[0], RARRAY_PTR(button)[1]); + } + + return args->self; +} + +static VALUE +rbgtk_dialog_add_buttons_internal_ensure(VALUE value) +{ + g_object_thaw_notify(RVAL2GOBJ(((struct rbgtk_dialog_add_buttons_internal_args *)value)->self)); + + return Qnil; +} + VALUE -rbgtk_dialog_add_buttons_internal(VALUE self, VALUE button_ary) +rbgtk_dialog_add_buttons_internal(VALUE self, VALUE buttons) { - int i; - GObject* obj = RVAL2GOBJ(self); - if (RARRAY_PTR(button_ary)[0] != Qnil){ - g_object_freeze_notify(obj); - for (i = 0; i < RARRAY_LEN(button_ary); i++) { - Check_Type(RARRAY_PTR(button_ary)[i], T_ARRAY); - dialog_add_button(self, RARRAY_PTR(RARRAY_PTR(button_ary)[i])[0], - RARRAY_PTR(RARRAY_PTR(button_ary)[i])[1]); - } - g_object_thaw_notify(obj); - } - return self; + struct rbgtk_dialog_add_buttons_internal_args args = { self, buttons }; + + if (NIL_P(RARRAY_PTR(buttons)[0])) + return self; + + g_object_freeze_notify(RVAL2GOBJ(self)); + + return rb_ensure(rbgtk_dialog_add_buttons_internal_body, (VALUE)&args, + rbgtk_dialog_add_buttons_internal_ensure, (VALUE)&args); } static VALUE @@ -147,18 +173,16 @@ */ static VALUE -dialog_set_alternative_button_order(VALUE self, VALUE new_order) +dialog_set_alternative_button_order(VALUE self, VALUE rbnew_order) { - gint i; - gint len = RARRAY_LEN(new_order); - gint* gnew_order = g_new(gint, len); + GtkDialog *dialog = _SELF(self); + long n; + gint *new_order = RVAL2GINTS(rbnew_order, &n); - for (i = 0; i < len; i++){ - gnew_order[i] = NUM2INT(RARRAY_PTR(new_order)[i]); - } + gtk_dialog_set_alternative_button_order_from_array(dialog, n, new_order); - gtk_dialog_set_alternative_button_order_from_array(_SELF(self), len, gnew_order); - g_free(gnew_order); + g_free(new_order); + return self; } Index: gtk2/ext/gtk2/rbgtktreerowreference.c =================================================================== --- gtk2/ext/gtk2/rbgtktreerowreference.c (revision 4688) +++ gtk2/ext/gtk2/rbgtktreerowreference.c (working copy) @@ -115,22 +115,31 @@ } static VALUE -treerowref_s_reordered(VALUE self, VALUE proxy, VALUE path, VALUE iter, VALUE new_orders) +treerowref_s_reordered(VALUE self, VALUE rbproxy, VALUE rbpath, VALUE rbiter, VALUE rbnew_order) { - gint i, len; - gint* orders; + GObject *proxy = RVAL2GOBJ(rbproxy); + GtkTreePath *path = RVAL2GTKTREEPATH(rbpath); + GtkTreeIter *iter = RVAL2GTKTREEITER(rbiter); + /* TODO: How do we implement this check? + gint columns = gtk_tree_model_get_n_columns(proxy); + */ + long n; + gint *new_order = RVAL2GINTS(rbnew_order, &n); - Check_Type(new_orders, T_ARRAY); + /* + if (n != columns) { + g_free(new_order); - len = RARRAY_LEN(new_orders); - orders = ALLOCA_N(gint, len); - - for (i = 0; i < len; i++) { - orders[i] = RARRAY_PTR(new_orders)[i]; + rb_raise(rb_eArgError, + "new order array must contain same number of elements as the number of columns in the store: %ld != %d", + n, columns); } + */ - gtk_tree_row_reference_reordered(RVAL2GOBJ(proxy), RVAL2GTKTREEPATH(path), - RVAL2GTKTREEITER(iter), orders); + gtk_tree_row_reference_reordered(proxy, path, iter, new_order); + + g_free(new_order); + return self; } Index: gtk2/ext/gtk2/rbgtkdrag.c =================================================================== --- gtk2/ext/gtk2/rbgtkdrag.c (revision 4688) +++ gtk2/ext/gtk2/rbgtkdrag.c (working copy) @@ -15,52 +15,88 @@ #define RVAL2DC(c) (GDK_DRAG_CONTEXT(RVAL2GOBJ(c))) #define RVAL2WIDGET(w) (GTK_WIDGET(RVAL2GOBJ(w))) -GtkTargetEntry* -rbgtk_get_target_entry(VALUE targets) -{ +struct rbgtk_rval2gtktargetentries_args { VALUE ary; - VALUE e_target, e_flags, e_info; - GtkTargetEntry *entries; - int i, n_targets; - - if (NIL_P(targets)) return NULL; - Check_Type(targets, T_ARRAY); - - n_targets = RARRAY_LEN(targets); - entries = ALLOC_N(GtkTargetEntry, n_targets); - - for (i = 0; i < n_targets; i++) { - ary = rb_ary_entry(targets, i); - Check_Type(ary, T_ARRAY); - e_target = rb_ary_entry(ary, 0); - e_flags = rb_ary_entry(ary, 1); - e_info = rb_ary_entry(ary, 2); - - entries[i].target = NIL_P(e_target) ? NULL : (char *)RVAL2CSTR(e_target); - entries[i].flags = NIL_P(e_flags) ? 0 : RVAL2GFLAGS(e_flags, GTK_TYPE_TARGET_FLAGS); - entries[i].info = NIL_P(e_info) ? 0 : NUM2INT(e_info); + long n; + GtkTargetEntry *result; +}; +static VALUE +rbgtk_rval2gtktargetentries_body(VALUE value) +{ + long i; + struct rbgtk_rval2gtktargetentries_args *args = (struct rbgtk_rval2gtktargetentries_args *)value; + + for (i = 0; i < args->n; i++) { + VALUE entry = rb_ary_to_ary(RARRAY_PTR(args->ary)[i]); + VALUE flags = RARRAY_PTR(entry)[1]; + VALUE info = RARRAY_PTR(entry)[2]; + + args->result[i].target = (gchar *)RVAL2CSTR_ACCEPT_NIL(RARRAY_PTR(entry)[0]); + args->result[i].flags = NIL_P(flags) ? 0 : RVAL2GFLAGS(flags, GTK_TYPE_TARGET_FLAGS); + args->result[i].info = NIL_P(info) ? 0 : NUM2INT(info); } - return entries; + + return Qnil; } static VALUE -gtkdrag_dest_set(VALUE self, VALUE widget, VALUE flags, VALUE targets, VALUE actions) +rbgtk_rval2gtktargetentries_rescue(VALUE value) { - int num; - GtkTargetEntry* entries = rbgtk_get_target_entry(targets); - if (entries){ - num = RARRAY_LEN(targets); - - gtk_drag_dest_set(RVAL2WIDGET(widget), RVAL2GFLAGS(flags, GTK_TYPE_DEST_DEFAULTS), - entries, - num, RVAL2GFLAGS(actions, GDK_TYPE_DRAG_ACTION)); - } - else - { - gtk_drag_dest_set(RVAL2WIDGET(widget), RVAL2GFLAGS(flags, GTK_TYPE_DEST_DEFAULTS), - NULL, 0, RVAL2GFLAGS(actions, GDK_TYPE_DRAG_ACTION)); - } + g_free(((struct rbgtk_rval2gtktargetentries_args *)value)->result); + + rb_exc_raise(rb_errinfo()); +} + +GtkTargetEntry * +rbgtk_rval2gtktargetentries(VALUE value, long *n) +{ + struct rbgtk_rval2gtktargetentries_args args; + + args.ary = rb_ary_to_ary(value); + args.n = RARRAY_LEN(args.ary); + args.result = g_new(GtkTargetEntry, args.n + 1); + + rb_rescue(rbgtk_rval2gtktargetentries_body, (VALUE)&args, + rbgtk_rval2gtktargetentries_rescue, (VALUE)&args); + + *n = args.n; + + return args.result; +} + +GtkTargetEntry * +rbgtk_rval2gtktargetentries_accept_nil(VALUE value, long *n) +{ + if (!NIL_P(value)) + return rbgtk_rval2gtktargetentries(value, n); + + *n = 0; + + return NULL; +} + +GtkTargetEntry * +rbgtk_get_target_entry(VALUE targets) +{ + long n; + + return RVAL2GTKTARGETENTRIES(targets, &n); +} + +static VALUE +gtkdrag_dest_set(VALUE self, VALUE rbwidget, VALUE rbflags, VALUE rbtargets, VALUE rbactions) +{ + GtkWidget *widget = RVAL2WIDGET(rbwidget); + GtkDestDefaults flags = RVAL2GFLAGS(rbflags, GTK_TYPE_DEST_DEFAULTS); + GdkDragAction actions = RVAL2GFLAGS(rbactions, GDK_TYPE_DRAG_ACTION); + long n; + GtkTargetEntry *targets = RVAL2GTKTARGETENTRIES_ACCEPT_NIL(rbtargets, &n); + + gtk_drag_dest_set(widget, flags, targets, n, actions); + + g_free(targets); + return self; } @@ -252,12 +288,18 @@ } static VALUE -gtkdrag_source_set(VALUE self, VALUE widget, VALUE flags, VALUE targets, VALUE actions) +gtkdrag_source_set(VALUE self, VALUE rbwidget, VALUE rbstart_button_mask, VALUE rbtargets, VALUE rbactions) { - gtk_drag_source_set(RVAL2WIDGET(widget), RVAL2GFLAGS(flags, GDK_TYPE_MODIFIER_TYPE), - rbgtk_get_target_entry(targets), - RARRAY_LEN(targets), - RVAL2GFLAGS(actions, GDK_TYPE_DRAG_ACTION)); + GtkWidget *widget = RVAL2WIDGET(rbwidget); + GdkModifierType start_button_mask = RVAL2GFLAGS(rbstart_button_mask, GDK_TYPE_MODIFIER_TYPE); + GdkDragAction actions = RVAL2GFLAGS(rbactions, GDK_TYPE_DRAG_ACTION); + long n; + GtkTargetEntry *targets = RVAL2GTKTARGETENTRIES(rbtargets, &n); + + gtk_drag_source_set(widget, start_button_mask, targets, n, actions); + + g_free(targets); + return self; } Index: gtk2/ext/gtk2/rbgdkdraw.c =================================================================== --- gtk2/ext/gtk2/rbgdkdraw.c (revision 4688) +++ gtk2/ext/gtk2/rbgdkdraw.c (working copy) @@ -88,24 +88,17 @@ } static VALUE -gdkdraw_draw_points(VALUE self, VALUE gc, VALUE pnts) +gdkdraw_draw_points(VALUE self, VALUE rbgc, VALUE rbpoints) { - GdkPoint *points; - int i; + GdkDrawable *drawable = _SELF(self); + GdkGC *gc = GDK_GC(RVAL2GOBJ(rbgc)); + long n; + GdkPoint *points = RVAL2GDKPOINTS(rbpoints, &n); - Check_Type(pnts, T_ARRAY); - points = ALLOCA_N(GdkPoint,RARRAY_LEN(pnts)); - for (i = 0; i < RARRAY_LEN(pnts); i++) { - Check_Type(RARRAY_PTR(pnts)[i], T_ARRAY); - if (RARRAY_LEN(RARRAY_PTR(pnts)[i]) < 2) { - rb_raise(rb_eArgError, "point %d should be array of size 2", i); - } - points[i].x = NUM2INT(RARRAY_PTR(RARRAY_PTR(pnts)[i])[0]); - points[i].y = NUM2INT(RARRAY_PTR(RARRAY_PTR(pnts)[i])[1]); - } - gdk_draw_points(_SELF(self), GDK_GC(RVAL2GOBJ(gc)), - points, - RARRAY_LEN(pnts)); + gdk_draw_points(drawable, gc, points, n); + + g_free(points); + return self; } @@ -119,24 +112,17 @@ } static VALUE -gdkdraw_draw_lines(VALUE self, VALUE gc, VALUE pnts) +gdkdraw_draw_lines(VALUE self, VALUE rbgc, VALUE rbpoints) { - GdkPoint *points; - int i; + GdkDrawable *drawable = _SELF(self); + GdkGC *gc = GDK_GC(RVAL2GOBJ(rbgc)); + long n; + GdkPoint *points = RVAL2GDKPOINTS(rbpoints, &n); - Check_Type(pnts, T_ARRAY); - points = ALLOCA_N(GdkPoint,RARRAY_LEN(pnts)); - for (i = 0; i < RARRAY_LEN(pnts); i++) { - Check_Type(RARRAY_PTR(pnts)[i], T_ARRAY); - if (RARRAY_LEN(RARRAY_PTR(pnts)[i]) < 2) { - rb_raise(rb_eArgError, "point %d should be array of size 2", i); - } - points[i].x = NUM2INT(RARRAY_PTR(RARRAY_PTR(pnts)[i])[0]); - points[i].y = NUM2INT(RARRAY_PTR(RARRAY_PTR(pnts)[i])[1]); - } - gdk_draw_lines(_SELF(self), GDK_GC(RVAL2GOBJ(gc)), - points, - RARRAY_LEN(pnts)); + gdk_draw_lines(drawable, gc, points, n); + + g_free(points); + return self; } @@ -156,26 +142,73 @@ } #endif +struct rbgdk_rval2gdksegments_args { + VALUE ary; + long n; + GdkSegment *result; +}; + static VALUE -gdkdraw_draw_segs(VALUE self, VALUE gc, VALUE segs) +rbgdk_rval2gdksegments_body(VALUE value) { - GdkSegment *segments; - int i; + long i; + struct rbgdk_rval2gdksegments_args *args = (struct rbgdk_rval2gdksegments_args *)value; - Check_Type(segs, T_ARRAY); - segments = ALLOCA_N(GdkSegment,RARRAY_LEN(segs)); - for (i = 0; i < RARRAY_LEN(segs); i++) { - Check_Type(RARRAY_PTR(segs)[i], T_ARRAY); - if (RARRAY_LEN(RARRAY_PTR(segs)[i]) < 4) { - rb_raise(rb_eArgError, "segment %d should be array of size 4", i); - } - segments[i].x1 = NUM2INT(RARRAY_PTR(RARRAY_PTR(segs)[i])[0]); - segments[i].y1 = NUM2INT(RARRAY_PTR(RARRAY_PTR(segs)[i])[1]); - segments[i].x2 = NUM2INT(RARRAY_PTR(RARRAY_PTR(segs)[i])[2]); - segments[i].y2 = NUM2INT(RARRAY_PTR(RARRAY_PTR(segs)[i])[3]); + for (i = 0; i < args->n; i++) { + VALUE segments = rb_ary_to_ary(RARRAY_PTR(args->ary)[i]); + + if (RARRAY_LEN(segments) != 2) + rb_raise(rb_eArgError, "segment %ld should be array of size 4", i); + + args->result[i].x1 = NUM2INT(RARRAY_PTR(segments)[0]); + args->result[i].y1 = NUM2INT(RARRAY_PTR(segments)[1]); + args->result[i].x2 = NUM2INT(RARRAY_PTR(segments)[2]); + args->result[i].y2 = NUM2INT(RARRAY_PTR(segments)[3]); } - gdk_draw_segments(_SELF(self), GDK_GC(RVAL2GOBJ(gc)), - segments, RARRAY_LEN(segs)); + + return Qnil; +} + +static VALUE +rbgdk_rval2gdksegments_rescue(VALUE value) +{ + g_free(((struct rbgdk_rval2gdksegments_args *)value)->result); + + rb_exc_raise(rb_errinfo()); +} + +static GdkSegment * +rbgdk_rval2gdksegments(VALUE value, long *n) +{ + struct rbgdk_rval2gdksegments_args args; + + args.ary = rb_ary_to_ary(value); + args.n = RARRAY_LEN(args.ary); + args.result = g_new(GdkSegment, args.n + 1); + + rb_rescue(rbgdk_rval2gdksegments_body, (VALUE)&args, + rbgdk_rval2gdksegments_rescue, (VALUE)&args); + + if (n != NULL) + *n = args.n; + + return args.result; +} + +#define RVAL2GDKSEGMENTS(value, n) rbgdk_rval2gdksegments(value, n) + +static VALUE +gdkdraw_draw_segs(VALUE self, VALUE rbgc, VALUE rbsegments) +{ + GdkDrawable *drawable = _SELF(self); + GdkGC *gc = GDK_GC(RVAL2GOBJ(rbgc)); + long n; + GdkSegment *segments = RVAL2GDKSEGMENTS(rbsegments, &n); + + gdk_draw_segments(drawable, gc, segments, n); + + g_free(segments); + return self; } @@ -201,25 +234,18 @@ } static VALUE -gdkdraw_draw_poly(VALUE self, VALUE gc, VALUE filled, VALUE pnts) +gdkdraw_draw_poly(VALUE self, VALUE rbgc, VALUE rbfilled, VALUE rbpoints) { - GdkPoint *points; - int i; + GdkDrawable *drawable = _SELF(self); + GdkGC *gc = GDK_GC(RVAL2GOBJ(rbgc)); + gboolean filled = RVAL2CBOOL(rbfilled); + long n; + GdkPoint *points = RVAL2GDKPOINTS(rbpoints, &n); - Check_Type(pnts, T_ARRAY); - points = ALLOCA_N(GdkPoint,RARRAY_LEN(pnts)); - for (i = 0; i < RARRAY_LEN(pnts); i++) { - Check_Type(RARRAY_PTR(pnts)[i], T_ARRAY); - if (RARRAY_LEN(RARRAY_PTR(pnts)[i]) < 2) { - rb_raise(rb_eArgError, "point %d should be array of size 2", i); - } - points[i].x = NUM2INT(RARRAY_PTR(RARRAY_PTR(pnts)[i])[0]); - points[i].y = NUM2INT(RARRAY_PTR(RARRAY_PTR(pnts)[i])[1]); - } - gdk_draw_polygon(_SELF(self), GDK_GC(RVAL2GOBJ(gc)), - RVAL2CBOOL(filled), - points, - RARRAY_LEN(pnts)); + gdk_draw_polygon(drawable, gc, filled, points, n); + + g_free(points); + return self; } @@ -227,32 +253,77 @@ /* trapezoids = [[y1, x11, x21, y2, x12, x22], ...] */ +struct rbgdk_rval2gdktrapezoids_args { + VALUE ary; + long n; + GdkTrapezoid *result; +}; + static VALUE -gdkdraw_draw_trapezoids(VALUE self, VALUE gc, VALUE trapezoids) +rbgdk_rval2gdktrapezoids_body(VALUE value) { - GdkTrapezoid *gtrapezoids; - gint i, len; + long i; + struct rbgdk_rval2gdktrapezoids_args *args = (struct rbgdk_rval2gdktrapezoids_args *)value; - Check_Type(trapezoids, T_ARRAY); + for (i = 0; i < args->n; i++) { + VALUE trapezoids = rb_ary_to_ary(RARRAY_PTR(args->ary)[i]); - len = RARRAY_LEN(trapezoids); + if (RARRAY_LEN(trapezoids) != 6) + rb_raise(rb_eArgError, "trapezoid %ld should be array of size 6", i); - gtrapezoids = ALLOCA_N(GdkTrapezoid, len); - for (i = 0; i < len; i++) { - Check_Type(RARRAY_PTR(trapezoids)[i], T_ARRAY); - if (RARRAY_LEN(RARRAY_PTR(trapezoids)[i]) < 6) { - rb_raise(rb_eArgError, "trapezoids %d should be array of size 6", i); - } - gtrapezoids[i].y1 = NUM2DBL(RARRAY_PTR(RARRAY_PTR(trapezoids)[i])[0]); - gtrapezoids[i].x11 = NUM2DBL(RARRAY_PTR(RARRAY_PTR(trapezoids)[i])[1]); - gtrapezoids[i].x21 = NUM2DBL(RARRAY_PTR(RARRAY_PTR(trapezoids)[i])[2]); - gtrapezoids[i].y2 = NUM2DBL(RARRAY_PTR(RARRAY_PTR(trapezoids)[i])[3]); - gtrapezoids[i].x12 = NUM2DBL(RARRAY_PTR(RARRAY_PTR(trapezoids)[i])[4]); - gtrapezoids[i].x22 = NUM2DBL(RARRAY_PTR(RARRAY_PTR(trapezoids)[i])[5]); + args->result[i].y1 = NUM2DBL(RARRAY_PTR(trapezoids)[0]); + args->result[i].x11 = NUM2DBL(RARRAY_PTR(trapezoids)[1]); + args->result[i].x21 = NUM2DBL(RARRAY_PTR(trapezoids)[2]); + args->result[i].y2 = NUM2DBL(RARRAY_PTR(trapezoids)[3]); + args->result[i].x12 = NUM2DBL(RARRAY_PTR(trapezoids)[4]); + args->result[i].x22 = NUM2DBL(RARRAY_PTR(trapezoids)[5]); } - gdk_draw_trapezoids(_SELF(self), GDK_GC(RVAL2GOBJ(gc)), gtrapezoids, len); - return self; + + return Qnil; } + +static VALUE +rbgdk_rval2gdktrapezoids_rescue(VALUE value) +{ + g_free(((struct rbgdk_rval2gdktrapezoids_args *)value)->result); + + rb_exc_raise(rb_errinfo()); +} + +static GdkTrapezoid * +rbgdk_rval2gdktrapezoids(VALUE value, long *n) +{ + struct rbgdk_rval2gdktrapezoids_args args; + + args.ary = rb_ary_to_ary(value); + args.n = RARRAY_LEN(args.ary); + args.result = g_new(GdkTrapezoid, args.n + 1); + + rb_rescue(rbgdk_rval2gdktrapezoids_body, (VALUE)&args, + rbgdk_rval2gdktrapezoids_rescue, (VALUE)&args); + + if (n != NULL) + *n = args.n; + + return args.result; +} + +#define RVAL2GDKTRAPEZOIDS(value, n) rbgdk_rval2gdktrapezoids(value, n) + +static VALUE +gdkdraw_draw_trapezoids(VALUE self, VALUE rbgc, VALUE rbtrapezoids) +{ + GdkDrawable *drawable = _SELF(self); + GdkGC *gc = GDK_GC(RVAL2GOBJ(rbgc)); + long n; + GdkTrapezoid *trapezoids = RVAL2GDKTRAPEZOIDS(rbtrapezoids, &n); + + gdk_draw_trapezoids(drawable, gc, trapezoids, n); + + g_free(trapezoids); + + return self; +} #endif static VALUE Index: gtk2/ext/gtk2/rbgtktargetlist.c =================================================================== --- gtk2/ext/gtk2/rbgtktargetlist.c (revision 4688) +++ gtk2/ext/gtk2/rbgtktargetlist.c (working copy) @@ -40,12 +40,16 @@ /**********************************/ static VALUE -target_list_initialize(VALUE self, VALUE targets) +target_list_initialize(VALUE self, VALUE rbtargets) { - Check_Type(targets, T_ARRAY); - G_INITIALIZE(self, gtk_target_list_new( - rbgtk_get_target_entry(targets), - RARRAY_LEN(targets))); + long n; + GtkTargetEntry *targets = RVAL2GTKTARGETENTRIES(rbtargets, &n); + GtkTargetList *list = gtk_target_list_new(targets, n); + + g_free(targets); + + G_INITIALIZE(self, list); + return Qnil; } @@ -58,11 +62,16 @@ } static VALUE -target_list_add_table(VALUE self, VALUE targets) +target_list_add_table(VALUE self, VALUE rbtargets) { - gtk_target_list_add_table(_SELF(self), - rbgtk_get_target_entry(targets), - RARRAY_LEN(targets)); + GtkTargetList *list = _SELF(self); + long n; + GtkTargetEntry *targets = RVAL2GTKTARGETENTRIES(rbtargets, &n); + + gtk_target_list_add_table(list, targets, n); + + g_free(targets); + return self; } Index: gtk2/ext/gtk2/rbgdkpango.c =================================================================== --- gtk2/ext/gtk2/rbgdkpango.c (revision 4688) +++ gtk2/ext/gtk2/rbgdkpango.c (working copy) @@ -65,36 +65,51 @@ } static VALUE -gdkpango_layout_get_clip_region(VALUE self, VALUE x_origin, VALUE y_origin, VALUE index_ranges) +gdkpango_layout_get_clip_region(VALUE self, VALUE rbx_origin, VALUE rby_origin, VALUE rbindex_ranges) { - int i; - gint len = RARRAY_LEN(index_ranges); - gint* ranges = g_new(gint, len); + PangoLayout *layout = PANGO_LAYOUT(RVAL2GOBJ(self)); + gint x_origin = NUM2INT(rbx_origin); + gint y_origin = NUM2INT(rby_origin); + long n; + gint *index_ranges = RVAL2GINTS(rbindex_ranges, &n); + GdkRegion *result; - for (i = 0; i < len; i++) { - ranges[i] = RARRAY_PTR(index_ranges)[i]; + if (n % 2 != 0) { + g_free(index_ranges); + + rb_raise(rb_eArgError, + "an even number of byte indexes must be given"); } - return BOXED2RVAL(gdk_pango_layout_get_clip_region(PANGO_LAYOUT(RVAL2GOBJ(self)), - NUM2INT(x_origin), - NUM2INT(y_origin), - ranges, len), GDK_TYPE_REGION); + + result = gdk_pango_layout_get_clip_region(layout, x_origin, y_origin, index_ranges, n / 2); + + g_free(index_ranges); + + return BOXED2RVAL(result, GDK_TYPE_REGION); } static VALUE -gdkpango_layout_line_get_clip_region(VALUE self, VALUE x_origin, VALUE y_origin, VALUE index_ranges) +gdkpango_layout_line_get_clip_region(VALUE self, VALUE rbx_origin, VALUE rby_origin, VALUE rbindex_ranges) { - int i; - gint len = RARRAY_LEN(index_ranges); - gint* ranges = g_new(gint, len); + PangoLayoutLine *line = (PangoLayoutLine *)RVAL2BOXED(self, PANGO_TYPE_LAYOUT_LINE); + gint x_origin = NUM2INT(rbx_origin); + gint y_origin = NUM2INT(rby_origin); + long n; + gint *index_ranges = RVAL2GINTS(rbindex_ranges, &n); + GdkRegion *result; - for (i = 0; i < len; i++) { - ranges[i] = RARRAY_PTR(index_ranges)[i]; + if (n % 2 != 0) { + g_free(index_ranges); + + rb_raise(rb_eArgError, + "an even number of byte indexes must be given"); } - return BOXED2RVAL(gdk_pango_layout_line_get_clip_region( - (PangoLayoutLine*)RVAL2BOXED(self, PANGO_TYPE_LAYOUT_LINE), - NUM2INT(x_origin), - NUM2INT(y_origin), - ranges, len), GDK_TYPE_REGION); + + result = gdk_pango_layout_line_get_clip_region(line, x_origin, y_origin, index_ranges, n / 2); + + g_free(index_ranges); + + return BOXED2RVAL(result, GDK_TYPE_REGION); } #if GTK_CHECK_VERSION(2, 12, 0) Index: gtk2/ext/gtk2/rbgtkclipboard.c =================================================================== --- gtk2/ext/gtk2/rbgtkclipboard.c (revision 4688) +++ gtk2/ext/gtk2/rbgtkclipboard.c (working copy) @@ -73,7 +73,7 @@ #if GTK_CHECK_VERSION(2,2,0) return GOBJ2RVAL(gtk_clipboard_get_display(_SELF(self))); #else - return Qnil; + return Qnil; #endif } @@ -84,19 +84,53 @@ BOXED2RVAL(selection_data, GTK_TYPE_SELECTION_DATA)); } +struct clipboard_set_args { + VALUE self; + VALUE targets; + VALUE func; +}; + static VALUE -clipboard_set(VALUE self, VALUE targets) +clipboard_set_body(VALUE value) { - const GtkTargetEntry* gtargets = (const GtkTargetEntry*)rbgtk_get_target_entry(targets); - VALUE func = rb_block_proc(); - G_RELATIVE(self, func); - return CBOOL2RVAL(gtk_clipboard_set_with_data(_SELF(self), - gtargets, - RARRAY_LEN(targets), + struct clipboard_set_args *args = (struct clipboard_set_args *)value; + GtkClipboard *clipboard = _SELF(args->self); + long n; + GtkTargetEntry *targets; + targets = RVAL2GTKTARGETENTRIES(args->targets, &n); + gboolean result = gtk_clipboard_set_with_data(clipboard, + targets, + n, (GtkClipboardGetFunc)clipboard_get_func, (GtkClipboardClearFunc)NULL, - (gpointer)func)); + (gpointer)args->func); + + g_free(targets); + + return CBOOL2RVAL(result); } + +static VALUE +clipboard_set_rescue(VALUE value) +{ + struct clipboard_set_args *args = (struct clipboard_set_args *)value; + + G_CHILD_REMOVE(args->self, args->func); + + rb_exc_raise(rb_errinfo()); +} + +static VALUE +clipboard_set(VALUE self, VALUE targets) +{ + struct clipboard_set_args args = { self, targets, rb_block_proc() }; + + G_CHILD_ADD(self, args.func); + + return rb_rescue(clipboard_set_body, (VALUE)&args, + clipboard_set_rescue, (VALUE)&args); +} + /* Do not implement this. Use Gtk::Clipboard#set_with_data instead. gboolean gtk_clipboard_set_with_owner (GtkClipboard *clipboard, @@ -351,16 +385,16 @@ } static VALUE -clipboard_set_can_store(VALUE self, VALUE targets) +clipboard_set_can_store(VALUE self, VALUE rbtargets) { - gint n_targets = 0; - GtkTargetEntry* entries = (GtkTargetEntry*)NULL; + GtkClipboard *clipboard = _SELF(self); + long n = 0; + GtkTargetEntry *targets = RVAL2GTKTARGETENTRIES_ACCEPT_NIL(rbtargets, &n); - if (!NIL_P(targets)){ - n_targets = RARRAY_LEN(targets); - entries = rbgtk_get_target_entry(targets); - } - gtk_clipboard_set_can_store(_SELF(self), entries, n_targets); + gtk_clipboard_set_can_store(clipboard, targets, n); + + g_free(targets); + return self; } @@ -368,6 +402,7 @@ clipboard_store(VALUE self) { gtk_clipboard_store(_SELF(self)); + return self; } #endif Index: gtk2/ext/gtk2/rbgtkradiomenuitem.c =================================================================== --- gtk2/ext/gtk2/rbgtkradiomenuitem.c (revision 4688) +++ gtk2/ext/gtk2/rbgtkradiomenuitem.c (working copy) @@ -15,22 +15,50 @@ #include "global.h" -static GSList* -ary2gslist(VALUE ary) +struct rbgtk_rval2gtkradiomenuitemgslist_args { + VALUE ary; + long n; + GSList *result; +}; + +static VALUE +rbgtk_rval2gtkradiomenuitemgslist_body(VALUE value) { long i; - GSList *glist = NULL; + struct rbgtk_rval2gtkradiomenuitemgslist_args *args = (struct rbgtk_rval2gtkradiomenuitemgslist_args *)value; - if (NIL_P(ary)) return NULL; - Check_Type(ary, T_ARRAY); - for (i=0; in; i++) + args->result = g_slist_append(args->result, GTK_RADIO_MENU_ITEM(RVAL2GOBJ(RARRAY_PTR(args->ary)[i]))); - return glist; + return Qnil; } static VALUE +rbgtk_rval2gtkradiomenuitemgslist_rescue(VALUE value) +{ + g_slist_free(((struct rbgtk_rval2gtkradiomenuitemgslist_args *)value)->result); + + rb_exc_raise(rb_errinfo()); +} + +static GSList * +rbgtk_rval2gtkradiomenuitemgslist(VALUE value) +{ + struct rbgtk_rval2gtkradiomenuitemgslist_args args; + + args.ary = rb_ary_to_ary(value); + args.n = RARRAY_LEN(args.ary); + args.result = NULL; + + rb_rescue(rbgtk_rval2gtkradiomenuitemgslist_body, (VALUE)&args, + rbgtk_rval2gtkradiomenuitemgslist_rescue, (VALUE)&args); + + return args.result; +} + +#define RVAL2GTKRADIOMENUITEMGSLIST(value) rbgtk_rval2gtkradiomenuitemgslist(value) + +static VALUE rmitem_initialize(int argc, VALUE *argv, VALUE self) { VALUE arg1, arg2, arg3; @@ -41,36 +69,37 @@ if (rb_scan_args(argc, argv, "03", &arg1, &arg2, &arg3) > 0 && TYPE(arg1) == T_STRING) { - if (NIL_P(arg2) || RVAL2CBOOL(arg2)){ + if (NIL_P(arg2) || RVAL2CBOOL(arg2)) mnemonic = RVAL2CSTR(arg1); - } else { + else label = RVAL2CSTR(arg1); - } } else { if (!NIL_P(arg2)) { - if (NIL_P(arg3) || RVAL2CBOOL(arg3)){ + if (NIL_P(arg3) || RVAL2CBOOL(arg3)) mnemonic = RVAL2CSTR(arg2); - } else { + else label = RVAL2CSTR(arg2); - } } - if (rb_obj_is_kind_of(arg1, GTYPE2CLASS(GTK_TYPE_RADIO_MENU_ITEM))){ - list = GTK_RADIO_MENU_ITEM(RVAL2GOBJ(arg1))->group; - } else if (TYPE(arg1) == T_ARRAY){ - list = ary2gslist(arg1); - } else if (! NIL_P(arg1)){ + + if (rb_obj_is_kind_of(arg1, GTYPE2CLASS(GTK_TYPE_RADIO_MENU_ITEM))) + list = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(RVAL2GOBJ(arg1))); + else if (TYPE(arg1) == T_ARRAY) + /* TODO: This might leak. */ + list = RVAL2GTKRADIOMENUITEMGSLIST(arg1); + else if (!NIL_P(arg1)) rb_raise(rb_eArgError, "invalid argument %s (expect Array or Gtk::RadioMenuItem)", - rb_class2name(CLASS_OF(label))); - } + rb_class2name(CLASS_OF(arg1))); } - if (label) { + + if (label != NULL) widget = gtk_radio_menu_item_new_with_label(list, label); - } else if (mnemonic){ + else if (mnemonic != NULL) widget = gtk_radio_menu_item_new_with_mnemonic(list, mnemonic); - } else { + else widget = gtk_radio_menu_item_new(list); - } + RBGTK_INITIALIZE(self, widget); + return Qnil; } Index: gtk2/ext/gtk2/rbgdktimecoord.c =================================================================== --- gtk2/ext/gtk2/rbgdktimecoord.c (revision 4688) +++ gtk2/ext/gtk2/rbgdktimecoord.c (working copy) @@ -37,22 +37,29 @@ /**********************************/ static VALUE -timecoord_initialize(VALUE self, VALUE time, VALUE axes) +timecoord_initialize(VALUE self, VALUE rbtime, VALUE rbaxes) { - GdkTimeCoord coord; - int i; - coord.time = NUM2UINT(time); + guint32 time = NUM2UINT(rbtime); + long n; + gdouble *axes = RVAL2GDOUBLES(rbaxes, &n); + GdkTimeCoord *coord; - if (RARRAY_LEN(axes) > GDK_MAX_TIMECOORD_AXES){ - rb_raise(rb_eArgError, "axes: Out of range: %ld", RARRAY_LEN(axes)); - } + if (n > GDK_MAX_TIMECOORD_AXES) { + g_free(axes); - for (i = 0; i < RARRAY_LEN(axes); i++){ - coord.axes[i] = NUM2DBL(RARRAY_PTR(axes)[i]); + rb_raise(rb_eArgError, + "axes out of range: %ld (0..%d)", + n, GDK_MAX_TIMECOORD_AXES); } - G_INITIALIZE(self, &coord); + coord = g_new(GdkTimeCoord, 1); + coord->time = time; + MEMCPY(coord->axes, axes, gdouble, n); + g_free(axes); + + G_INITIALIZE(self, coord); + return Qnil; } @@ -81,18 +88,21 @@ } static VALUE -timecoord_set_axes(VALUE self, VALUE axes) +timecoord_set_axes(VALUE self, VALUE rbaxes) { - int i; - GdkTimeCoord* coord = _SELF(self); + GdkTimeCoord *coord = _SELF(self); + VALUE axes = rb_ary_to_ary(rbaxes); + long i; + long n = RARRAY_LEN(axes); - if (RARRAY_LEN(axes) > GDK_MAX_TIMECOORD_AXES){ - rb_raise(rb_eArgError, "axes: Out of range: %ld", RARRAY_LEN(axes)); - } + if (n < 0 || n > GDK_MAX_TIMECOORD_AXES) + rb_raise(rb_eArgError, + "axes out of range: %ld (0..%d)", + n, GDK_MAX_TIMECOORD_AXES); - for (i = 0; i < RARRAY_LEN(axes); i++){ + for (i = 0; i < n; i++) coord->axes[i] = NUM2DBL(RARRAY_PTR(axes)[i]); - } + return self; } Index: gtk2/ext/gtk2/rbgdkdisplay.c =================================================================== --- gtk2/ext/gtk2/rbgdkdisplay.c (revision 4688) +++ gtk2/ext/gtk2/rbgdkdisplay.c (working copy) @@ -323,18 +323,18 @@ } static VALUE -gdkdisplay_store_clipboard(VALUE self, VALUE clipboard_window, VALUE time_, VALUE targets) +gdkdisplay_store_clipboard(VALUE self, VALUE rbclipboard_window, VALUE rbtime_, VALUE rbtargets) { - gint i; - gint n_targets = RARRAY_LEN(targets); - GdkAtom* gtargets = g_new(GdkAtom, n_targets); + GdkDisplay *display = _SELF(self); + GdkWindow *clipboard_window = GDK_WINDOW(RVAL2GOBJ(rbclipboard_window)); + guint32 time_ = NUM2UINT(rbtime_); + long n; + GdkAtom *targets = RVAL2GDKATOMS(rbtargets, &n); - for (i = 0; i < n_targets; i++){ - gtargets[i] = RVAL2ATOM(RARRAY_PTR(targets)[i]); - } + gdk_display_store_clipboard(display, clipboard_window, time_, targets, n); - gdk_display_store_clipboard(_SELF(self), GDK_WINDOW(RVAL2GOBJ(clipboard_window)), - NUM2UINT(time_), gtargets, n_targets); + g_free(targets); + return self; } #endif Index: gtk2/ext/gtk2/rbgtkradiotoolbutton.c =================================================================== --- gtk2/ext/gtk2/rbgtkradiotoolbutton.c (revision 4688) +++ gtk2/ext/gtk2/rbgtkradiotoolbutton.c (working copy) @@ -17,39 +17,77 @@ static VALUE gRToolButton; +struct rbgtk_rval2gtkradiotoolbuttongslist_args { + VALUE ary; + long n; + GSList *result; +}; + static VALUE +rbgtk_rval2gtkradiotoolbuttongslist_body(VALUE value) +{ + long i; + struct rbgtk_rval2gtkradiotoolbuttongslist_args *args = (struct rbgtk_rval2gtkradiotoolbuttongslist_args *)value; + + for (i = 0; i < args->n; i++) + args->result = g_slist_append(args->result, GTK_RADIO_MENU_ITEM(RVAL2GOBJ(RARRAY_PTR(args->ary)[i]))); + + return Qnil; +} + +static VALUE +rbgtk_rval2gtkradiotoolbuttongslist_rescue(VALUE value) +{ + g_slist_free(((struct rbgtk_rval2gtkradiotoolbuttongslist_args *)value)->result); + + rb_exc_raise(rb_errinfo()); +} + +static GSList * +rbgtk_rval2gtkradiotoolbuttongslist(VALUE value) +{ + struct rbgtk_rval2gtkradiotoolbuttongslist_args args; + + args.ary = rb_ary_to_ary(value); + args.n = RARRAY_LEN(args.ary); + args.result = NULL; + + rb_rescue(rbgtk_rval2gtkradiotoolbuttongslist_body, (VALUE)&args, + rbgtk_rval2gtkradiotoolbuttongslist_rescue, (VALUE)&args); + + return args.result; +} + +#define RVAL2GTKRADIOTOOLBUTTONGSLIST(value) rbgtk_rval2gtkradiotoolbuttongslist(value) + +static VALUE rbtn_initialize(int argc, VALUE *argv, VALUE self) { - VALUE group_or_stock_id, stock_id; + VALUE group_or_stock_id, rbstock_id; GtkToolItem *widget; - if (rb_scan_args(argc, argv, "02", &group_or_stock_id, &stock_id) > 0) { - GSList* list = NULL; - if (TYPE(group_or_stock_id) == T_ARRAY){ - int i; - Check_Type(group_or_stock_id, T_ARRAY); - for (i = 0; i < RARRAY_LEN(group_or_stock_id); i++) { - list = g_slist_append(list, RVAL2GOBJ(RARRAY_PTR(group_or_stock_id)[i])); - } - } else if (rb_obj_is_kind_of(group_or_stock_id, gRToolButton)){ - list = gtk_radio_tool_button_get_group(_SELF(group_or_stock_id)); - } else { - list = NULL; - } - if (NIL_P(stock_id)){ - widget = gtk_radio_tool_button_new(list); - } else { - if (TYPE(stock_id) == T_SYMBOL){ - widget = gtk_radio_tool_button_new_from_stock(list, rb_id2name(SYM2ID(stock_id))); - } else { - widget = gtk_radio_tool_button_new_from_stock(list, RVAL2CSTR(stock_id)); - } - } + if (rb_scan_args(argc, argv, "02", &group_or_stock_id, &rbstock_id) > 0) { + GSList *group = NULL; + const gchar *stock_id = TYPE(rbstock_id) == T_SYMBOL ? + rb_id2name(SYM2ID(rbstock_id)) : + RVAL2CSTR_ACCEPT_NIL(rbstock_id); + + if (TYPE(group_or_stock_id) == T_ARRAY) + /* TODO: This has a potential for leaking. */ + group = RVAL2GTKRADIOTOOLBUTTONGSLIST(group_or_stock_id); + else if (rb_obj_is_kind_of(group_or_stock_id, gRToolButton)) + group = gtk_radio_tool_button_get_group(_SELF(group_or_stock_id)); + + if (stock_id == NULL) + widget = gtk_radio_tool_button_new(group); + else + widget = gtk_radio_tool_button_new_from_stock(group, stock_id); } else { widget = gtk_radio_tool_button_new(NULL); } - + RBGTK_INITIALIZE(self, widget); + return Qnil; } @@ -61,19 +99,16 @@ } static VALUE -rbtn_set_group(VALUE self, VALUE group) +rbtn_set_group(VALUE self, VALUE rbgroup) { - GSList* list = NULL; - if (TYPE(group) == T_ARRAY){ - int i; - for (i = 0; i < RARRAY_LEN(group); i++){ - list = g_slist_append(list, RVAL2GOBJ(RARRAY_PTR(group)[i])); - } - } else { - list = gtk_radio_tool_button_get_group(_SELF(group)); - } - gtk_radio_tool_button_set_group(_SELF(self), list); - + GtkRadioToolButton *button = _SELF(self); + GSList *group = TYPE(rbgroup) == T_ARRAY ? + /* TODO: This might leak. */ + RVAL2GTKRADIOTOOLBUTTONGSLIST(rbgroup) : + gtk_radio_tool_button_get_group(_SELF(rbgroup)); + + gtk_radio_tool_button_set_group(button, group); + return self; } Index: gtk2/ext/gtk2/rbgtkstyle.c =================================================================== --- gtk2/ext/gtk2/rbgtkstyle.c (revision 4688) +++ gtk2/ext/gtk2/rbgtkstyle.c (working copy) @@ -231,20 +231,25 @@ } static VALUE -style_paint_polygon(VALUE self, VALUE gdkwindow, VALUE state_type, VALUE shadow_type, VALUE area, VALUE widget, VALUE detail, VALUE points, VALUE fill) +style_paint_polygon(VALUE self, VALUE rbwindow, VALUE rbstate_type, + VALUE rbshadow_type, VALUE rbarea, VALUE rbwidget, + VALUE rbdetail, VALUE rbpoints, VALUE rbfill) { - int i; - GdkPoint* gpoints = g_new (GdkPoint, RARRAY_LEN(points)); + GtkStyle *style = _SELF(self); + GdkWindow *window = GDK_WINDOW(RVAL2GOBJ(rbwindow)); + GtkStateType state_type = RVAL2STATE(rbstate_type); + GtkShadowType shadow_type = RVAL2SHADOW(rbshadow_type); + GdkRectangle *area = RVAL2REC(rbarea); + GtkWidget *widget = GTK_WIDGET(RVAL2GOBJ(rbwidget)); + const gchar *detail = RVAL2CSTR_ACCEPT_NIL(rbdetail); + gboolean fill = RVAL2CBOOL(rbfill); + long n; + GdkPoint *points = RVAL2GDKPOINTS(rbpoints, &n); - for (i = 0; i < RARRAY_LEN(points); i++){ - gpoints[i].x = RARRAY_PTR(RARRAY_PTR(points)[i])[0]; - gpoints[i].y = RARRAY_PTR(RARRAY_PTR(points)[i])[1]; - } - gtk_paint_polygon(_SELF(self), GDK_WINDOW(RVAL2GOBJ(gdkwindow)), - RVAL2STATE(state_type), RVAL2SHADOW(shadow_type), RVAL2REC(area), - GTK_WIDGET(RVAL2GOBJ(widget)), - NIL_P(detail) ? NULL : RVAL2CSTR(detail), gpoints, - RARRAY_LEN(points), RVAL2CBOOL(fill)); + gtk_paint_polygon(style, window, state_type, shadow_type, area, widget, detail, points, n, fill); + + g_free(points); + return self; } Index: gtk2/ext/gtk2/rbgdkregion.c =================================================================== --- gtk2/ext/gtk2/rbgdkregion.c (revision 4688) +++ gtk2/ext/gtk2/rbgdkregion.c (working copy) @@ -31,28 +31,21 @@ static VALUE gdkregion_initialize(int argc, VALUE *argv, VALUE self) { - VALUE points_or_rectangle, fill_rule; - GdkRegion* region; - GdkPoint *gpoints; - int i; + VALUE points_or_rectangle, rbfill_rule; + GdkRegion *region; - rb_scan_args(argc, argv, "02", &points_or_rectangle, &fill_rule); - if (NIL_P(points_or_rectangle)){ + rb_scan_args(argc, argv, "02", &points_or_rectangle, &rbfill_rule); + if (NIL_P(points_or_rectangle)) { region = gdk_region_new(); - } else if (TYPE(points_or_rectangle) == T_ARRAY){ - gpoints = ALLOCA_N(GdkPoint, RARRAY_LEN(points_or_rectangle)); + } else if (TYPE(points_or_rectangle) == T_ARRAY) { + GdkFillRule fill_rule = RVAL2GENUM(rbfill_rule, GDK_TYPE_FILL_RULE); + long n; + GdkPoint *points = RVAL2GDKPOINTS(points_or_rectangle, &n); - for (i = 0; i < RARRAY_LEN(points_or_rectangle); i++) { - Check_Type(RARRAY_PTR(points_or_rectangle)[i], T_ARRAY); - if (RARRAY_LEN(RARRAY_PTR(points_or_rectangle)[i]) < 2) { - rb_raise(rb_eArgError, "point %d should be array of size 2", i); - } - gpoints[i].x = NUM2INT(RARRAY_PTR(RARRAY_PTR(points_or_rectangle)[i])[0]); - gpoints[i].y = NUM2INT(RARRAY_PTR(RARRAY_PTR(points_or_rectangle)[i])[1]); - } - region = gdk_region_polygon(gpoints, RARRAY_LEN(points_or_rectangle), - RVAL2GENUM(fill_rule, GDK_TYPE_FILL_RULE)); - } else if (RVAL2GTYPE(points_or_rectangle) == GDK_TYPE_RECTANGLE){ + region = gdk_region_polygon(points, n, fill_rule); + + g_free(points); + } else if (RVAL2GTYPE(points_or_rectangle) == GDK_TYPE_RECTANGLE) { region = gdk_region_rectangle((GdkRectangle*)RVAL2BOXED(points_or_rectangle, GDK_TYPE_RECTANGLE)); } else { @@ -62,6 +55,7 @@ } G_INITIALIZE(self, region); + return Qnil; } @@ -88,22 +82,82 @@ INT2NUM(span->x), INT2NUM(span->y), INT2NUM(span->width)); } +struct rbgdk_rval2gdkspans_args { + VALUE ary; + long n; + GdkSpan *result; +}; + static VALUE -gdkregion_spans_intersect_foreach(VALUE self, VALUE spans, VALUE sorted) +rbgdk_rval2gdkspans_body(VALUE value) { - int i; - GdkSpan* gspans = ALLOCA_N(GdkSpan, RARRAY_LEN(spans)); - volatile VALUE func = rb_block_proc(); + long i; + struct rbgdk_rval2gdkspans_args *args = (struct rbgdk_rval2gdkspans_args *)value; + for (i = 0; i < args->n; i++) { + VALUE points = rb_ary_to_ary(RARRAY_PTR(args->ary)[i]); + + if (RARRAY_LEN(points) != 2) + rb_raise(rb_eArgError, "point %ld should be array of size 3", i); + + args->result[i].x = NUM2INT(RARRAY_PTR(points)[0]); + args->result[i].y = NUM2INT(RARRAY_PTR(points)[1]); + args->result[i].width = NUM2INT(RARRAY_PTR(points)[1]); + } + + return Qnil; +} + +static VALUE +rbgdk_rval2gdkspans_rescue(VALUE value) +{ + g_free(((struct rbgdk_rval2gdkspans_args *)value)->result); + + rb_exc_raise(rb_errinfo()); +} + +static GdkSpan * +rbgdk_rval2gdkspans(VALUE value, long *n) +{ + struct rbgdk_rval2gdkspans_args args; + + args.ary = rb_ary_to_ary(value); + args.n = RARRAY_LEN(args.ary); + args.result = g_new(GdkSpan, args.n + 1); + + rb_rescue(rbgdk_rval2gdkspans_body, (VALUE)&args, + rbgdk_rval2gdkspans_rescue, (VALUE)&args); + + if (n != NULL) + *n = args.n; + + return args.result; +} + +#define RVAL2GDKSPANS(value, n) rbgdk_rval2gdkspans(value, n) + +static VALUE +gdkregion_spans_intersect_foreach(VALUE self, VALUE rbspans, VALUE rbsorted) +{ + GdkRegion *region = _SELF(self); + gboolean sorted = RVAL2CBOOL(rbsorted); + VALUE func = rb_block_proc(); + long n; + GdkSpan *spans; + G_RELATIVE(self, func); - for (i = 0; i < RARRAY_LEN(spans); i++) { - gspans[i].x = NUM2INT(RARRAY_PTR(RARRAY_PTR(spans)[i])[0]); - gspans[i].y = NUM2INT(RARRAY_PTR(RARRAY_PTR(spans)[i])[1]); - gspans[i].width = NUM2INT(RARRAY_PTR(RARRAY_PTR(spans)[i])[2]); - } - gdk_region_spans_intersect_foreach(_SELF(self), - gspans, RARRAY_LEN(spans), RVAL2CBOOL(sorted), - (GdkSpanFunc)gdkregion_span_func, (gpointer)func); + + spans = RVAL2GDKSPANS(rbspans, &n); + + gdk_region_spans_intersect_foreach(region, + spans, + n, + sorted, + (GdkSpanFunc)gdkregion_span_func, + (gpointer)func); + + g_free(spans); + return self; } Index: gtk2/ext/gtk2/rbgtkicontheme.c =================================================================== --- gtk2/ext/gtk2/rbgtkicontheme.c (revision 4688) +++ gtk2/ext/gtk2/rbgtkicontheme.c (working copy) @@ -44,39 +44,27 @@ } static VALUE -it_set_search_path(VALUE self, VALUE paths) +it_set_search_path(VALUE self, VALUE rbpath) { - gchar** gpaths; - gint size, i; + GtkIconTheme *theme = _SELF(self); + long n; + const gchar **path = RVAL2STRS(rbpath, &n); - Check_Type(paths, T_ARRAY); - - size = RARRAY_LEN(paths); - gpaths = g_new(gchar*, size); + gtk_icon_theme_set_search_path(theme, path, n); - for (i = 0; i < size; i++) { - gpaths[i] = (gchar*)(RARRAY_PTR(paths)[0]); - } - gtk_icon_theme_set_search_path(_SELF(self), (const gchar**)gpaths, size); - g_free(gpaths); + g_free(path); + return self; } static VALUE it_get_search_path(VALUE self) { - gchar** path; - gint size, i; + gchar **path; - - VALUE ret = rb_ary_new(); - gtk_icon_theme_get_search_path(_SELF(self), &path, &size); + gtk_icon_theme_get_search_path(_SELF(self), &path, NULL); - for (i = 0; i < size; i++){ - rb_ary_push(ret, CSTR2RVAL(path[i])); - } - g_strfreev(path); - return ret; + return STRV2RVAL_FREE(path); } static VALUE Index: gtk2/ext/gtk2/rbgdkgc.c =================================================================== --- gtk2/ext/gtk2/rbgdkgc.c (revision 4688) +++ gtk2/ext/gtk2/rbgdkgc.c (working copy) @@ -159,20 +159,16 @@ } static VALUE -gdkgc_set_dashes(VALUE self, VALUE dash_offset, VALUE dash_list) +gdkgc_set_dashes(VALUE self, VALUE rbdash_offset, VALUE rbdash_list) { - gint8 *buf; - int i; + GdkGC *gc = _SELF(self); + gint dash_offset = NUM2INT(rbdash_offset); + long n; + gint8 *dash_list = RVAL2GINT8S(rbdash_list, &n); - Check_Type(dash_list, T_ARRAY); + gdk_gc_set_dashes(gc, dash_offset, dash_list, n); - buf = ALLOCA_N(gint8, RARRAY_LEN(dash_list)); - for (i = 0; i < RARRAY_LEN(dash_list); i++) { - Check_Type(RARRAY_PTR(dash_list)[i], T_FIXNUM); - buf[i] = (gint8)NUM2CHR(RARRAY_PTR(dash_list)[i]); - } - gdk_gc_set_dashes(_SELF(self), NUM2INT(dash_offset), - (gint8*)buf, RARRAY_LEN(dash_list)); + g_free(dash_list); return self; } Index: gtk2/ext/gtk2/rbgtktreemodel.c =================================================================== --- gtk2/ext/gtk2/rbgtktreemodel.c (revision 4688) +++ gtk2/ext/gtk2/rbgtktreemodel.c (working copy) @@ -146,21 +146,27 @@ } static VALUE -treemodel_rows_reordered(VALUE self, VALUE path, VALUE iter, VALUE new_orders) +treemodel_rows_reordered(VALUE self, VALUE rbpath, VALUE rbiter, VALUE rbnew_order) { - gint i, len; - gint* orders; + GtkTreeModel *proxy = _SELF(self); + GtkTreePath *path = RVAL2GTKTREEPATH(rbpath); + GtkTreeIter *iter = RVAL2GTKTREEITER(rbiter); + gint columns = gtk_tree_model_get_n_columns(proxy); + long n; + gint *new_order = RVAL2GINTS(rbnew_order, &n); - Check_Type(new_orders, T_ARRAY); + if (n != columns) { + g_free(new_order); - len = RARRAY_LEN(new_orders); - orders = ALLOCA_N(gint, len); + rb_raise(rb_eArgError, + "new order array must contain same number of elements as the number of columns in the store: %ld != %d", + n, columns); + } - for (i = 0; i < len; i++) { - orders[i] = RARRAY_PTR(new_orders)[i]; - } - - gtk_tree_model_rows_reordered(_SELF(self), RVAL2GTKTREEPATH(path), RVAL2GTKTREEITER(iter), orders); + gtk_tree_model_rows_reordered(proxy, path, iter, new_order); + + g_free(new_order); + return self; } Index: gtk2/ext/gtk2/rbgtkprintsettings.c =================================================================== --- gtk2/ext/gtk2/rbgtkprintsettings.c (revision 4688) +++ gtk2/ext/gtk2/rbgtkprintsettings.c (working copy) @@ -500,21 +500,70 @@ return rb_ranges; } +struct rbgtk_rval2gtkpageranges_args { + VALUE ary; + long n; + GtkPageRange *result; +}; + static VALUE -ps_set_page_ranges(VALUE self, VALUE rb_page_ranges) +rbgtk_rval2gtkpageranges_body(VALUE value) { - GtkPageRange *page_ranges; - gint i, num_ranges; + long i; + struct rbgtk_rval2gtkpageranges_args *args = (struct rbgtk_rval2gtkpageranges_args *)value; - num_ranges = RARRAY_LEN(rb_page_ranges); - page_ranges = ALLOCA_N(GtkPageRange, num_ranges); - for (i = 0; i < num_ranges; i++) { - VALUE page_range; - page_range = RARRAY_PTR(rb_page_ranges)[i]; - page_ranges[i].start = NUM2INT(RARRAY_PTR(page_range)[0]); - page_ranges[i].end = NUM2INT(RARRAY_PTR(page_range)[1]); + for (i = 0; i < args->n; i++) { + VALUE ary = rb_ary_to_ary(RARRAY_PTR(args->ary)[i]); + + if (RARRAY_LEN(ary) != 2) + rb_raise(rb_eArgError, "range %ld should be array of size 2", i); + + args->result[i].start = NUM2INT(RARRAY_PTR(ary)[0]); + args->result[i].end = NUM2INT(RARRAY_PTR(ary)[1]); } - gtk_print_settings_set_page_ranges(_SELF(self), page_ranges, num_ranges); + + return Qnil; +} + +static VALUE +rbgtk_rval2gtkpageranges_rescue(VALUE value) +{ + g_free(((struct rbgtk_rval2gtkpageranges_args *)value)->result); + + rb_exc_raise(rb_errinfo()); +} + +static GtkPageRange * +rbgtk_rval2gtkpageranges(VALUE value, long *n) +{ + struct rbgtk_rval2gtkpageranges_args args; + + args.ary = rb_ary_to_ary(value); + args.n = RARRAY_LEN(args.ary); + args.result = g_new(GtkPageRange, args.n + 1); + + rb_rescue(rbgtk_rval2gtkpageranges_body, (VALUE)&args, + rbgtk_rval2gtkpageranges_rescue, (VALUE)&args); + + if (n != NULL) + *n = args.n; + + return args.result; +} + +#define RVAL2GTKPAGERANGES(value, n) rbgtk_rval2gtkpageranges(value, n) + +static VALUE +ps_set_page_ranges(VALUE self, VALUE rbpage_ranges) +{ + GtkPrintSettings *settings = _SELF(self); + long n; + GtkPageRange *page_ranges = RVAL2GTKPAGERANGES(rbpage_ranges, &n); + + gtk_print_settings_set_page_ranges(settings, page_ranges, n); + + g_free(page_ranges); + return self; } Index: gtk2/ext/gtk2/rbgdkdevice.c =================================================================== --- gtk2/ext/gtk2/rbgdkdevice.c (revision 4688) +++ gtk2/ext/gtk2/rbgdkdevice.c (working copy) @@ -99,26 +99,26 @@ } static VALUE -device_get_axis(VALUE self, VALUE axes, VALUE use) +device_get_axis(VALUE self, VALUE rbaxes, VALUE rbuse) { + GdkDevice *device = _SELF(self); + GdkAxisUse use = RVAL2GENUM(rbuse, GDK_TYPE_AXIS_USE); + long n; + gdouble *axes = RVAL2GDOUBLES(rbaxes, &n); + gint device_n_axes = gdk_device_get_n_axes(device); gdouble value; - gboolean ret; - gdouble* gaxes; - gint i; - gint len = RARRAY_LEN(axes); + gboolean found; - gaxes = g_new(gdouble, len); + if (n != device_n_axes) + rb_raise(rb_eArgError, + "unexpected number of axes: %ld != %d", + n, device_n_axes); - for (i = 0; i < len; i++){ - gaxes[i] = RARRAY_PTR(axes)[i]; - } + found = gdk_device_get_axis(device, axes, use, &value); - ret = gdk_device_get_axis(_SELF(self), gaxes, RVAL2GENUM(use, GDK_TYPE_AXIS_USE), - &value); + g_free(axes); - g_free(gaxes); - - return ret ? rb_float_new(value) : Qnil; + return found ? DBL2NUM(value) : Qnil; } /* Accessor */ Index: gtk2/ext/gtk2/gtk2.def =================================================================== --- gtk2/ext/gtk2/gtk2.def (revision 4688) +++ gtk2/ext/gtk2/gtk2.def (working copy) @@ -4,6 +4,9 @@ rb_cGdkColor DATA mGtk DATA exec_callback + rbgdk_rval2gdkpoints + rbgdk_rval2gdkatoms + rbgdk_rval2gdkpixbufglist gdk_atom_copy gdk_atom_get_type gdk_geometry_get_type @@ -20,6 +23,8 @@ notebookpage_copy rbgtk_atom2selectiondata rbgtk_atom2selectiondata_free + rbgtk_rval2gtktargetentries + rbgtk_rval2gtktargetentries_accept_nil rbgtk_get_target_entry rbgtk_initialize_gtkobject rbgtk_register_treeiter_set_value_func Index: gtk2/ext/gtk2/rbgdkdragcontext.c =================================================================== --- gtk2/ext/gtk2/rbgdkdragcontext.c (revision 4688) +++ gtk2/ext/gtk2/rbgdkdragcontext.c (working copy) @@ -163,23 +163,62 @@ GENUM2RVAL(prot, GDK_TYPE_DRAG_PROTOCOL)); } +struct rbgdk_rval2gdkatomglist_args { + VALUE ary; + long n; + GList *result; +}; + static VALUE -gdkdragcontext_s_drag_begin(VALUE self, VALUE window, VALUE targets) +rbgdk_rval2gdkatomglist_body(VALUE value) { - GList* list = NULL; - VALUE ret; - int i; - for (i = 0; i < RARRAY_LEN(targets); i++){ - list = g_list_append(list, GINT_TO_POINTER(RVAL2ATOM(RARRAY_PTR(targets)[0]))); - } + long i; + struct rbgdk_rval2gdkatomglist_args *args = (struct rbgdk_rval2gdkatomglist_args *)value; - ret = GOBJ2RVAL(gdk_drag_begin(GDK_WINDOW(RVAL2GOBJ(window)), list)); - g_list_free(list); + for (i = 0; i < args->n; i++) + args->result = g_list_append(args->result, GINT_TO_POINTER(RVAL2ATOM(RARRAY_PTR(args->ary)[i]))); - return ret; + return Qnil; } static VALUE +rbgdk_rval2gdkatomglist_rescue(VALUE value) +{ + g_free(((struct rbgdk_rval2gdkatomglist_args *)value)->result); + + rb_exc_raise(rb_errinfo()); +} + +static GList * +rbgdk_rval2gdkatomglist(VALUE value) +{ + struct rbgdk_rval2gdkatomglist_args args; + + args.ary = rb_ary_to_ary(value); + args.n = RARRAY_LEN(args.ary); + args.result = NULL; + + rb_rescue(rbgdk_rval2gdkatomglist_body, (VALUE)&args, + rbgdk_rval2gdkatomglist_rescue, (VALUE)&args); + + return args.result; +} + +#define RVAL2GDKATOMGLIST(value) rbgdk_rval2gdkatomglist(value) + +static VALUE +gdkdragcontext_s_drag_begin(VALUE self, VALUE rbwindow, VALUE rbtargets) +{ + GdkWindow *window = GDK_WINDOW(RVAL2GOBJ(rbwindow)); + GList *targets = RVAL2GDKATOMGLIST(rbtargets); + GdkDragContext *result = gdk_drag_begin(window, targets); + + g_list_free(targets); + + return GOBJ2RVAL(result); +} + +static VALUE gdkdragcontext_drag_motion(VALUE self, VALUE dest_window, VALUE protocol, VALUE x_root, VALUE y_root, VALUE suggested_action, VALUE possible_actions, VALUE time) { gboolean ret = gdk_drag_motion(_SELF(self), Index: gtk2/ext/gtk2/rbgtkcontainer.c =================================================================== --- gtk2/ext/gtk2/rbgtkcontainer.c (revision 4688) +++ gtk2/ext/gtk2/rbgtkcontainer.c (working copy) @@ -340,19 +340,59 @@ return GLIST2ARYF(glist); } +struct rval2gtkwidgetglist_args { + VALUE ary; + long n; + GList *result; +}; + static VALUE -cont_set_focus_chain(VALUE self, VALUE focusable_widgets) +rbg_rval2gtkwidgetglist_body(VALUE value) { - int i; - GList *glist = NULL; + long i; + struct rval2gtkwidgetglist_args *args = (struct rval2gtkwidgetglist_args *)value; - Check_Type(focusable_widgets, T_ARRAY); - for (i = 0; i < RARRAY_LEN(focusable_widgets); i++) { - glist = g_list_append(glist, RVAL2GOBJ(RARRAY_PTR(focusable_widgets)[i])); - } - gtk_container_set_focus_chain(_SELF(self), glist); - g_list_free(glist); + for (i = 0; i < args->n; i++) + args->result = g_list_append(args->result, GTK_WIDGET(RVAL2GOBJ(RARRAY_PTR(args->ary)[i]))); + return Qnil; +} + +static VALUE +rbg_rval2gtkwidgetglist_rescue(VALUE value) +{ + g_list_free(((struct rval2gtkwidgetglist_args *)value)->result); + + rb_exc_raise(rb_errinfo()); +} + +static GList * +rbg_rval2gtkwidgetglist(VALUE value) +{ + struct rval2gtkwidgetglist_args args; + + args.ary = rb_ary_to_ary(value); + args.n = RARRAY_LEN(args.ary); + args.result = NULL; + + rb_rescue(rbg_rval2gtkwidgetglist_body, (VALUE)&args, + rbg_rval2gtkwidgetglist_rescue, (VALUE)&args); + + return args.result; +} + +#define RVAL2GTKWIDGETGLIST(value) rbg_rval2gtkwidgetglist(value) + +static VALUE +cont_set_focus_chain(VALUE self, VALUE rbfocusable_widgets) +{ + GtkContainer *container = _SELF(self); + GList *focusable_widgets = RVAL2GTKWIDGETGLIST(rbfocusable_widgets); + + gtk_container_set_focus_chain(container, focusable_widgets); + + g_list_free(focusable_widgets); + return self; } Index: gtk2/ext/gtk2/rbgtktreeview.c =================================================================== --- gtk2/ext/gtk2/rbgtktreeview.c (revision 4688) +++ gtk2/ext/gtk2/rbgtktreeview.c (working copy) @@ -117,6 +117,8 @@ Check_Type(args[3], T_HASH); + /* TODO: Should this really be done before we know that everything + * below worked without error? */ G_CHILD_ADD(self, args[2]); G_CHILD_ADD(self, args[3]); @@ -438,28 +440,36 @@ #endif static VALUE -treeview_enable_model_drag_dest(VALUE self, VALUE targets, VALUE actions) +treeview_enable_model_drag_dest(VALUE self, VALUE rbtargets, VALUE rbactions) { - const GtkTargetEntry* entries = rbgtk_get_target_entry(targets); - int num = RARRAY_LEN(targets); + GtkTreeView *view = _SELF(self); + GdkDragAction actions = RVAL2GFLAGS(rbactions, GDK_TYPE_DRAG_ACTION); + long n; + GtkTargetEntry *targets = RVAL2GTKTARGETENTRIES(rbtargets, &n); - gtk_tree_view_enable_model_drag_dest(_SELF(self), entries, - num, RVAL2GFLAGS(actions, GDK_TYPE_DRAG_ACTION)); + gtk_tree_view_enable_model_drag_dest(view, targets, n, actions); + + g_free(targets); + return self; } static VALUE -treeview_enable_model_drag_source(VALUE self, VALUE start_button_mask, VALUE targets, VALUE actions) +treeview_enable_model_drag_source(VALUE self, VALUE rbstart_button_mask, VALUE rbtargets, VALUE rbactions) { - GtkTargetEntry* entries = rbgtk_get_target_entry(targets); - if (entries){ - gint num = RARRAY_LEN(targets); - - gtk_tree_view_enable_model_drag_source(_SELF(self), - RVAL2GFLAGS(start_button_mask, GDK_TYPE_MODIFIER_TYPE), - entries, num, - RVAL2GFLAGS(actions, GDK_TYPE_DRAG_ACTION)); - } + GtkTreeView *view = _SELF(self); + GdkModifierType start_button_mask = RVAL2GFLAGS(rbstart_button_mask, GDK_TYPE_MODIFIER_TYPE); + GdkDragAction actions = RVAL2GFLAGS(rbactions, GDK_TYPE_DRAG_ACTION); + long n; + GtkTargetEntry *targets = RVAL2GTKTARGETENTRIES_ACCEPT_NIL(rbtargets, &n); + + if (targets == NULL) + return self; + + gtk_tree_view_enable_model_drag_source(view, start_button_mask, targets, n, actions); + + g_free(targets); + return self; } Index: gtk2/ext/gtk2/rbgdk.c =================================================================== --- gtk2/ext/gtk2/rbgdk.c (revision 4688) +++ gtk2/ext/gtk2/rbgdk.c (working copy) @@ -25,6 +25,140 @@ gchar ***argv); */ +struct rbgdk_rval2gdkpoints_args { + VALUE ary; + long n; + GdkPoint *result; +}; + +static VALUE +rbgdk_rval2gdkpoints_body(VALUE value) +{ + long i; + struct rbgdk_rval2gdkpoints_args *args = (struct rbgdk_rval2gdkpoints_args *)value; + + for (i = 0; i < args->n; i++) { + VALUE points = rb_ary_to_ary(RARRAY_PTR(args->ary)[i]); + + if (RARRAY_LEN(points) != 2) + rb_raise(rb_eArgError, "point %ld should be array of size 2", i); + + args->result[i].x = NUM2INT(RARRAY_PTR(points)[0]); + args->result[i].y = NUM2INT(RARRAY_PTR(points)[1]); + } + + return Qnil; +} + +static VALUE +rbgdk_rval2gdkpoints_rescue(VALUE value) +{ + g_free(((struct rbgdk_rval2gdkpoints_args *)value)->result); + + rb_exc_raise(rb_errinfo()); +} + +GdkPoint * +rbgdk_rval2gdkpoints(VALUE value, long *n) +{ + struct rbgdk_rval2gdkpoints_args args; + + args.ary = rb_ary_to_ary(value); + args.n = RARRAY_LEN(args.ary); + args.result = g_new(GdkPoint, args.n + 1); + + rb_rescue(rbgdk_rval2gdkpoints_body, (VALUE)&args, + rbgdk_rval2gdkpoints_rescue, (VALUE)&args); + + *n = args.n; + + return args.result; +} + +struct rbgdk_rval2gdkatoms_args { + VALUE ary; + long n; + GdkAtom *result; +}; + +static VALUE +rbgdk_rval2gdkatoms_body(VALUE value) +{ + long i; + struct rbgdk_rval2gdkatoms_args *args = (struct rbgdk_rval2gdkatoms_args *)value; + + for (i = 0; i < args->n; i++) + args->result[i] = RVAL2ATOM(RARRAY_PTR(args->ary)[i]); + + return Qnil; +} + +static VALUE +rbgdk_rval2gdkatoms_rescue(VALUE value) +{ + g_free(((struct rbgdk_rval2gdkatoms_args *)value)->result); + + rb_exc_raise(rb_errinfo()); +} + +GdkAtom * +rbgdk_rval2gdkatoms(VALUE value, long *n) +{ + struct rbgdk_rval2gdkatoms_args args; + + args.ary = rb_ary_to_ary(value); + args.n = RARRAY_LEN(args.ary); + args.result = g_new(GdkAtom, args.n + 1); + + rb_rescue(rbgdk_rval2gdkatoms_body, (VALUE)&args, + rbgdk_rval2gdkatoms_rescue, (VALUE)&args); + + *n = args.n; + + return args.result; +} + +struct rval2gdkpixbufglist_args { + VALUE ary; + long n; + GList *result; +}; + +static VALUE +rbgdk_rval2gdkpixbufglist_body(VALUE value) +{ + long i; + struct rval2gdkpixbufglist_args *args = (struct rval2gdkpixbufglist_args *)value; + + for (i = 0; i < args->n; i++) + args->result = g_list_append(args->result, GDK_PIXBUF(RVAL2GOBJ(RARRAY_PTR(args->ary)[i]))); + + return Qnil; +} + +static VALUE +rbgdk_rval2gdkpixbufglist_rescue(VALUE value) +{ + g_list_free(((struct rval2gdkpixbufglist_args *)value)->result); + + rb_exc_raise(rb_errinfo()); +} + +GList * +rbgdk_rval2gdkpixbufglist(VALUE value) +{ + struct rval2gdkpixbufglist_args args; + + args.ary = rb_ary_to_ary(value); + args.n = RARRAY_LEN(args.ary); + args.result = NULL; + + rb_rescue(rbgdk_rval2gdkpixbufglist_body, (VALUE)&args, + rbgdk_rval2gdkpixbufglist_rescue, (VALUE)&args); + + return args.result; +} + #if GTK_CHECK_VERSION(2,2,0) static VALUE gdk_s_get_display_arg_name(VALUE self) Index: gtk2/ext/gtk2/rbgdk.h =================================================================== --- gtk2/ext/gtk2/rbgdk.h (revision 4688) +++ gtk2/ext/gtk2/rbgdk.h (working copy) @@ -18,6 +18,11 @@ # include #endif +#define RVAL2GDKPOINTS(value, n) rbgdk_rval2gdkpoints(value, n) +#define RVAL2GDKATOMS(value, n) rbgdk_rval2gdkatoms(value, n) + +#define RVAL2GDKPIXBUFGLIST(value) rbgdk_rval2gdkpixbufglist(value) + #define GDK_BITMAP(b) ((GdkBitmap*)GDK_PIXMAP(b)) #define GEV2RVAL(ev) (make_gdkevent(ev)) @@ -40,6 +45,11 @@ GdkAtom atom; } GdkAtomData; +GdkPoint *rbgdk_rval2gdkpoints(VALUE value, long *n); +GdkAtom *rbgdk_rval2gdkatoms(VALUE value, long *n); + +GList *rbgdk_rval2gdkpixbufglist(VALUE value); + extern GType gdk_windowattr_get_type(void); extern GType gdk_atom_get_type(void); extern GType gdk_geometry_get_type(void); Index: gtk2/ext/gtk2/rbgtktreestore.c =================================================================== --- gtk2/ext/gtk2/rbgtktreestore.c (revision 4688) +++ gtk2/ext/gtk2/rbgtktreestore.c (working copy) @@ -282,6 +282,7 @@ gtk_tree_store_clear(_SELF(self)); return self; } + #if GTK_CHECK_VERSION(2,2,0) static VALUE tstore_iter_is_valid(VALUE self, VALUE iter) @@ -289,27 +290,38 @@ return (NIL_P(iter)) ? Qfalse : CBOOL2RVAL(gtk_tree_store_iter_is_valid(_SELF(self), RVAL2GTKTREEITER(iter))); } + static VALUE -tstore_reorder(VALUE self, VALUE parent, VALUE new_order) +tstore_reorder(VALUE self, VALUE rbparent, VALUE rbnew_order) { - gint i; - gint len = RARRAY_LEN(new_order); - gint* gnew_order = g_new(gint, len); + GtkTreeStore *store = _SELF(self); + GtkTreeIter *parent = RVAL2GTKTREEITER(rbparent); + gint columns = gtk_tree_model_get_n_columns(GTK_TREE_MODEL(store)); + long n; + gint *new_order = RVAL2GINTS(rbnew_order, &n); - for (i = 0; i < len; i++){ - gnew_order[i] = NUM2INT(RARRAY_PTR(new_order)[i]); + if (n != columns) { + g_free(new_order); + + rb_raise(rb_eArgError, + "new order array must contain same number of elements as the number of columns in the store: %ld != %d", + n, columns); } + + gtk_tree_store_reorder(store, parent, new_order); - gtk_tree_store_reorder(_SELF(self), RVAL2GTKTREEITER(parent), gnew_order); - g_free(gnew_order); + g_free(new_order); + return self; } + static VALUE tstore_swap(VALUE self, VALUE iter1, VALUE iter2) { gtk_tree_store_swap(_SELF(self), RVAL2GTKTREEITER(iter1), RVAL2GTKTREEITER(iter2)); return self; } + static VALUE tstore_move_before(VALUE self, VALUE iter, VALUE position) { @@ -317,6 +329,7 @@ NIL_P(position) ? NULL : RVAL2GTKTREEITER(position)); return self; } + static VALUE tstore_move_after(VALUE self, VALUE iter, VALUE position) { Index: gtk2/ext/gtk2/rbgtkiconview.c =================================================================== --- gtk2/ext/gtk2/rbgtkiconview.c (revision 4688) +++ gtk2/ext/gtk2/rbgtkiconview.c (working copy) @@ -159,23 +159,33 @@ } static VALUE -iview_enable_model_drag_dest(VALUE self, VALUE targets, VALUE actions) +iview_enable_model_drag_dest(VALUE self, VALUE rbtargets, VALUE rbactions) { - gtk_icon_view_enable_model_drag_dest(_SELF(self), - rbgtk_get_target_entry(targets), - RARRAY_LEN(targets), - RVAL2GFLAGS(actions, GDK_TYPE_DRAG_ACTION)); + GtkIconView *icon_view = _SELF(self); + GdkDragAction actions = RVAL2GFLAGS(rbactions, GDK_TYPE_DRAG_ACTION); + long n; + GtkTargetEntry *targets = RVAL2GTKTARGETENTRIES(rbtargets, &n); + + gtk_icon_view_enable_model_drag_dest(icon_view, targets, n, actions); + + g_free(targets); + return self; } static VALUE -iview_enable_model_drag_source(VALUE self, VALUE flags, VALUE targets, VALUE actions) +iview_enable_model_drag_source(VALUE self, VALUE rbstart_button_mask, VALUE rbtargets, VALUE rbactions) { - gtk_icon_view_enable_model_drag_source(_SELF(self), - RVAL2GFLAGS(flags, GDK_TYPE_MODIFIER_TYPE), - rbgtk_get_target_entry(targets), - RARRAY_LEN(targets), - RVAL2GFLAGS(actions, GDK_TYPE_DRAG_ACTION)); + GtkIconView *icon_view = _SELF(self); + GdkModifierType start_button_mask = RVAL2GFLAGS(rbstart_button_mask, GDK_TYPE_MODIFIER_TYPE); + GdkDragAction actions = RVAL2GFLAGS(rbactions, GDK_TYPE_DRAG_ACTION); + long n; + GtkTargetEntry *targets = RVAL2GTKTARGETENTRIES(rbtargets, &n); + + gtk_icon_view_enable_model_drag_source(icon_view, start_button_mask, targets, n, actions); + + g_free(targets); + return self; } Index: gtk2/ext/gtk2/rbgtk.h =================================================================== --- gtk2/ext/gtk2/rbgtk.h (revision 4688) +++ gtk2/ext/gtk2/rbgtk.h (working copy) @@ -97,7 +97,12 @@ /* * Gtk::Drag */ -extern GtkTargetEntry* rbgtk_get_target_entry(VALUE targets); +#define RVAL2GTKTARGETENTRIES(value, n) rbgtk_rval2gtktargetentries(value, n) +extern GtkTargetEntry *rbgtk_rval2gtktargetentries(VALUE value, long *n); +#define RVAL2GTKTARGETENTRIES_ACCEPT_NIL(value, n) rbgtk_rval2gtktargetentries_accept_nil(value, n) +GtkTargetEntry *rbgtk_rval2gtktargetentries_accept_nil(VALUE value, long *n); +/* Only for backwards compatibility. */ +GtkTargetEntry *rbgtk_get_target_entry(VALUE targets); /* * Gtk::Container Index: gtk2/ext/gtk2/rbgdkwindow.c =================================================================== --- gtk2/ext/gtk2/rbgdkwindow.c (revision 4688) +++ gtk2/ext/gtk2/rbgdkwindow.c (working copy) @@ -632,17 +632,15 @@ } static VALUE -gdkwin_set_icon_list(VALUE self, VALUE pixbufs) +gdkwin_set_icon_list(VALUE self, VALUE rbpixbufs) { - int i; - GList *glist = NULL; + GdkWindow *window = _SELF(self); + GList *pixbufs = RVAL2GDKPIXBUFGLIST(rbpixbufs); - Check_Type(pixbufs, T_ARRAY); - for (i = 0; i < RARRAY_LEN(pixbufs); i++) { - glist = g_list_append(glist, GDK_PIXBUF(RVAL2GOBJ(RARRAY_PTR(pixbufs)[i]))); - } + gdk_window_set_icon_list(window, pixbufs); - gdk_window_set_icon_list(_SELF(self), glist); + g_list_free(pixbufs); + return self; } Index: gtk2/ext/gtk2/rbgtkliststore.c =================================================================== --- gtk2/ext/gtk2/rbgtkliststore.c (revision 4688) +++ gtk2/ext/gtk2/rbgtkliststore.c (working copy) @@ -192,60 +192,93 @@ #endif } +struct lstore_insert_args { + GtkListStore *store; + GtkTreeIter iter; + gint position; + VALUE ary; + long i; + long n; + gint *columns; + GValue *values; +}; + +static VALUE +lstore_insert_body(VALUE value) +{ + struct lstore_insert_args *args = (struct lstore_insert_args *)value; + GtkTreeModel *model = GTK_TREE_MODEL(args->store); + + for (args->i = 0; args->i < args->n; args->i++) { + VALUE ary = rb_ary_to_ary(RARRAY_PTR(args->ary)[args->i]); + + args->columns[args->i] = NUM2INT(RARRAY_PTR(ary)[1]); + g_value_init(&args->values[args->i], + gtk_tree_model_get_column_type(model, args->columns[args->i])); + rbgobj_rvalue_to_gvalue(RARRAY_PTR(ary)[0], &args->values[args->i]); + } + + gtk_list_store_insert_with_valuesv(args->store, + &args->iter, + args->position, + args->columns, + args->values, + args->n); + + return Qnil; +} + +static VALUE +lstore_insert_ensure(VALUE value) +{ + long i; + struct lstore_insert_args *args = (struct lstore_insert_args *)value; + + for (i = 0; i < args->i; i++) + g_value_unset(&args->values[i]); + + g_free(args->values); + g_free(args->columns); + + return Qnil; +} + /* Gtk::ListStore#insert(pos, val1 => 0, val2 => 2, ... ) */ static VALUE lstore_insert(int argc, VALUE *argv, VALUE self) { - VALUE position, values, ret; - GtkTreeIter iter; - GtkListStore* store = _SELF(self); + VALUE position, values, result; + struct lstore_insert_args args = { _SELF(self) }; rb_scan_args(argc, argv, "11", &position, &values); + args.position = NUM2INT(position); if (NIL_P(values)){ - gtk_list_store_insert(store, &iter, NUM2INT(position)); + gtk_list_store_insert(args.store, &args.iter, args.position); } else { #if GTK_CHECK_VERSION(2,6,0) - gint cnt, n_values; - gint* columns; - GType gtype; - GValue* gvalues; - VALUE ary = rb_funcall(values, id_to_a, 0); + args.ary = rb_funcall(values, id_to_a, 0); + args.n = RARRAY_LEN(args.ary); + args.columns = g_new(gint, args.n); + args.values = g_new0(GValue, args.n); - n_values = RARRAY_LEN(ary); - - gvalues = g_new(GValue, n_values); - columns = g_new(gint, n_values); - - for (cnt = 0; cnt < n_values; cnt++) { - Check_Type(RARRAY_PTR(ary)[cnt], T_ARRAY); - columns[cnt] = NUM2INT(RARRAY_PTR(RARRAY_PTR(ary)[cnt])[1]); - gtype = gtk_tree_model_get_column_type(GTK_TREE_MODEL(store), columns[cnt]); - gvalues[cnt].g_type = 0; - g_value_init(&gvalues[cnt], gtype); - rbgobj_rvalue_to_gvalue(RARRAY_PTR(RARRAY_PTR(ary)[cnt])[0], &gvalues[cnt]); - } - - gtk_list_store_insert_with_valuesv(store, &iter, NUM2INT(position), - columns, gvalues, n_values); - - for (cnt = 0; cnt < n_values; cnt++) { - g_value_unset(&gvalues[cnt]); - } - g_free(gvalues); - g_free(columns); + rb_ensure(lstore_insert_body, (VALUE)&args, + lstore_insert_ensure, (VALUE)&args); #else - gtk_list_store_insert(store, &iter, NUM2INT(position)); - rb_warn("Ignored 2nd argument under this environment. Because it has been supported since GTK+-2.6. "); + gtk_list_store_insert(args.store, &args.iter, args.position); + rb_warn("Ignored 2nd argument under this environment, as it has been supported since GTK+-2.6."); #endif } - iter.user_data3 = store; - ret = GTKTREEITER2RVAL(&iter); - G_CHILD_ADD(self, ret); - return ret; + args.iter.user_data3 = args.store; + + result = GTKTREEITER2RVAL(&args.iter); + + G_CHILD_ADD(self, result); + + return result; } static VALUE @@ -321,18 +354,16 @@ } static VALUE -lstore_reorder(VALUE self, VALUE new_order) +lstore_reorder(VALUE self, VALUE rbnew_order) { - gint i; - gint len = RARRAY_LEN(new_order); - gint* gnew_order = g_new(gint, len); + GtkListStore *store = _SELF(self); + long n; + gint *new_order = RVAL2GINTS(rbnew_order, &n); - for (i = 0; i < len; i++){ - gnew_order[i] = NUM2INT(RARRAY_PTR(new_order)[i]); - } + gtk_list_store_reorder(store, new_order); - gtk_list_store_reorder(_SELF(self), gnew_order); - g_free(gnew_order); + g_free(new_order); + return self; } static VALUE Index: gtk2/ext/gtk2/rbgdkrgb.c =================================================================== --- gtk2/ext/gtk2/rbgdkrgb.c (revision 4688) +++ gtk2/ext/gtk2/rbgdkrgb.c (working copy) @@ -46,31 +46,37 @@ } static VALUE -rgb_draw_indexed_image(VALUE self, VALUE win, VALUE gc, VALUE x, VALUE y, VALUE w, VALUE h, VALUE dither, VALUE buf, VALUE rowstride, VALUE colors) +rgb_draw_indexed_image(VALUE self, VALUE win, VALUE rbgc, VALUE rbx, VALUE rby, + VALUE rbwidth, VALUE rbheight, VALUE rbdither, + VALUE rbbuf, VALUE rbrowstride, VALUE rbcolors) { - GdkRgbCmap* cmap; - guint32* gcolors; - gint i, n_colors; + GdkDrawable *drawable = RVAL2DRAW(win); + GdkGC *gc = GDK_GC(RVAL2GOBJ(rbgc)); + gint x = NUM2INT(rbx); + gint y = NUM2INT(rby); + gint width = NUM2INT(rbwidth); + gint height = NUM2INT(rbheight); + GdkRgbDither dither = RVAL2GENUM(rbdither, GDK_TYPE_RGB_DITHER); + const guchar *buf = (const guchar *)RVAL2CSTR(rbbuf); + gint rowstride = NUM2INT(rbrowstride); + long n; + guint32 *colors = RVAL2GUINT32S(rbcolors, &n); + GdkRgbCmap *cmap; - n_colors = RARRAY_LEN(colors); + if (n < 0 || n > 255) { + g_free(colors); - if (n_colors > 255) rb_raise(rb_eArgError, "colors: out of range (0 - 255)"); - - gcolors = g_new(guint32, n_colors); - for (i = 0; i < n_colors; i++) { - gcolors[i] = NUM2UINT(RARRAY_PTR(colors)[i]); } - cmap = gdk_rgb_cmap_new(gcolors, n_colors); + cmap = gdk_rgb_cmap_new(colors, n); + + g_free(colors); - gdk_draw_indexed_image(RVAL2DRAW(win), GDK_GC(RVAL2GOBJ(gc)), - NUM2INT(x), NUM2INT(y), - NUM2INT(w), NUM2INT(h), - RVAL2GENUM(dither, GDK_TYPE_RGB_DITHER), - (guchar*)RVAL2CSTR(buf), - NUM2INT(rowstride), cmap); + gdk_draw_indexed_image(drawable, gc, x, y, width, height, dither, buf, rowstride, cmap); + gdk_rgb_cmap_free(cmap); + return self; } Index: gtk2/ext/gtk2/rbgtkradioaction.c =================================================================== --- gtk2/ext/gtk2/rbgtkradioaction.c (revision 4688) +++ gtk2/ext/gtk2/rbgtkradioaction.c (working copy) @@ -40,22 +40,63 @@ return GSLIST2ARY(gtk_radio_action_get_group(_SELF(self))); } +struct rbgtk_rval2gtkradioactiongslist_args { + VALUE ary; + long n; + GSList *result; +}; + static VALUE -raction_set_group(VALUE self, VALUE group) +rbgtk_rval2gtkradioactiongslist_body(VALUE value) { long i; - GSList *glist = NULL; + struct rbgtk_rval2gtkradioactiongslist_args *args = (struct rbgtk_rval2gtkradioactiongslist_args *)value; - if (TYPE(group) == T_ARRAY){ - for (i = 0; i < RARRAY_LEN(group); i++) { - glist = g_slist_append(glist, RVAL2GOBJ(RARRAY_PTR(group)[i])); - } - gtk_radio_action_set_group(_SELF(group), glist); - g_slist_free(glist); - } else { - glist = gtk_radio_action_get_group(GTK_RADIO_ACTION(RVAL2GOBJ(group))); - gtk_radio_action_set_group(_SELF(group), glist); - } + for (i = 0; i < args->n; i++) + args->result = g_slist_append(args->result, GTK_RADIO_ACTION(RVAL2GOBJ(RARRAY_PTR(args->ary)[i]))); + + return Qnil; +} + +static VALUE +rbgtk_rval2gtkradioactiongslist_rescue(VALUE value) +{ + g_slist_free(((struct rbgtk_rval2gtkradioactiongslist_args *)value)->result); + + rb_exc_raise(rb_errinfo()); +} + +static GSList * +rbgtk_rval2gtkradioactiongslist(VALUE value) +{ + struct rbgtk_rval2gtkradioactiongslist_args args; + + args.ary = rb_ary_to_ary(value); + args.n = RARRAY_LEN(args.ary); + args.result = NULL; + + rb_rescue(rbgtk_rval2gtkradioactiongslist_body, (VALUE)&args, + rbgtk_rval2gtkradioactiongslist_rescue, (VALUE)&args); + + return args.result; +} + +#define RVAL2GTKRADIOACTIONGSLIST(value) rbgtk_rval2gtkradioactiongslist(value) + +static VALUE +raction_set_group(VALUE self, VALUE rbgroup) +{ + GtkRadioAction *action = _SELF(self); + + /* TODO: This might leak. Use gtk_radio_action_join_group() in 3.0. */ + if (TYPE(rbgroup) == T_ARRAY) + gtk_radio_action_set_group(action, RVAL2GTKRADIOACTIONGSLIST(rbgroup)); + else if (NIL_P(rbgroup)) + gtk_radio_action_set_group(action, NULL); + else + gtk_radio_action_set_group(action, + gtk_radio_action_get_group(GTK_RADIO_ACTION(RVAL2GOBJ(rbgroup)))); + return self; } @@ -87,7 +128,7 @@ rb_define_method(gRadioAction, "current_value", raction_get_current_value, 0); #endif G_REPLACE_GET_PROPERTY(gRadioAction, "group", raction_get_group, 0); - G_REPLACE_SET_PROPERTY(gRadioAction, "group", raction_get_group, 1); + G_REPLACE_SET_PROPERTY(gRadioAction, "group", raction_set_group, 1); #endif } Index: gtk2/ChangeLog =================================================================== --- gtk2/ChangeLog (revision 4688) +++ gtk2/ChangeLog (working copy) @@ -1,7 +1,11 @@ +2011-09-19 Nikolai Weibull + + * ext/gtk2/*.c: Ensure that all array conversions are freed. + 2011-09-16 Nikolai Weibull * lib/gtk2.rb: Remove unused variable. - * gtk2/ext/gtk2/rbgdkscreen.c: Use RVAL2STRV() instead of RVAL2ARGV(). + * ext/gtk2/rbgdkscreen.c: Use RVAL2STRV() instead of RVAL2ARGV(). 2011-09-15 Nikolai Weibull