In Perl-Gtk, eveny signals are captured by a generic signal handler and map to a perl function. The arguments of signals are translated into corresponding perl object according to the prototype registered in Gtk signal system. For example, a typical Gtk signal is registered in the following way,
widget_signals[DEBUG_MSG] =
gtk_signal_new ("debug_msg",
GTK_RUN_LAST | GTK_RUN_ACTION,
object_class->type,
GTK_SIGNAL_OFFSET (GtkWidgetClass, debug_msg),
gtk_marshal_NONE__STRING,
GTK_TYPE_NONE, 1,
GTK_TYPE_STRING);
The signal "debug_msg" returns nothing and has one argument whose type is
string. For this case, you need to do nothing because the generic signal
handler can translate the argument to perl string since it has been resgitered
in Gtk signal system with known type. However, the following signal can not be translated automatically since it register an argument of type GTK_POINTER which can not be translated into perl object directly.
extext_signals[PROPERTY_TEXT_INSERT]=gtk_signal_new ("property_text_insert",
GTK_RUN_LAST,
object_class->type,
GTK_SIGNAL_OFFSET (GtkExTextClass, property_text_insert),
gtk_marshal_BOOL__POINTER_INT_INT,
GTK_TYPE_BOOL, 3,GTK_TYPE_POINTER,GTK_TYPE_INT,GTK_TYPE_INT);This example defines the "property_text_insert" signal for 'Gtk::ExText'. The 'Gtk::ExText::Property' object is treated as type GTK_POINTER because gtkextext module doesn't define GtkExTextProperty as Gtk type. You must provide the routine used to translate gpointer into 'GtkExText::Property' object of perl.
You need two code blocks to define the translation machenism. Firstly, you need bind the new signal with translation routine. The following codes can be used to do that.
void
init(Class)
SV * Class
CODE:
{
static char *names[] = {"property_text_insert",
"property_text_remove",
"property_destroy",
"undo_changed",
"property_mark",
"line_insert",
"line_remove",
NULL};
static int did_it = 0;
if (did_it)
return;
did_it = 1;
GtkExText_InstallTypedefs();
GtkExText_InstallObjects();
AddSignalHelperParts(gtk_extext_get_type(), names, fixup_extext_u, 0);
}
And then you should define the translation routine 'fixup_extext_u'. This function takes arguments of the signal as an array, translate them into corresponding perl forms and push all of them into perl stack.
#define sp (*_sp)
static int fixup_extext_u(SV ** * _sp, int match, GtkObject * object, char * signame, int nparams, GtkArg * args, GtkType return_type)
{
dTHR;
if (match == 0) {
XPUSHs(sv_2mortal(newSVGtkExTextProperty((GtkExTextProperty*)GTK_VALUE_POINTER(args[0]))));
XPUSHs(sv_2mortal(newSViv(GTK_VALUE_INT(args[1]))));
XPUSHs(sv_2mortal(newSViv(GTK_VALUE_INT(args[2]))));
} else if (match == 1) {
XPUSHs(sv_2mortal(newSVGtkExTextProperty((GtkExTextProperty*)GTK_VALUE_POINTER(args[0]))));
XPUSHs(sv_2mortal(newSViv(GTK_VALUE_INT(args[1]))));
XPUSHs(sv_2mortal(newSViv(GTK_VALUE_INT(args[2]))));
} else if (match == 2) {
XPUSHs(sv_2mortal(newSVGtkExTextProperty((GtkExTextProperty*)GTK_VALUE_POINTER(args[0]))));
} else if (match == 3) {
XPUSHs(sv_2mortal(newSVGtkExTextProperty((GtkExTextProperty*)GTK_VALUE_POINTER(args[0]))));
} else if (match == 4) {
XPUSHs(sv_2mortal(newSViv(GTK_VALUE_INT(args[0]))));
XPUSHs(sv_2mortal(newSViv(GTK_VALUE_INT(args[1]))));
} else if (match == 5) {
XPUSHs(sv_2mortal(newSViv(GTK_VALUE_INT(args[0]))));
} else if (match == 6) {
XPUSHs(sv_2mortal(newSViv(GTK_VALUE_INT(args[0]))));
}
return 1;
}
#undef sp
The only special thing we do in the above example is to create an perl object of type 'Gtk::ExText::Property' for the first argument of signal 'property_text_insert' and 'property_text_remove'.