pidgin/pidgin
Clone
Summary
Browse
Changes
Graph
stream_management.c was missing from jabber/Makefile.mingw
release-2.x.y
2019-11-11, Gary Kramlich
0857d099906e
stream_management.c was missing from jabber/Makefile.mingw
#include
"perl-common.h"
#include
"perl-handlers.h"
#include
"debug.h"
#include
"signals.h"
extern
PerlInterpreter
*
my_perl
;
static
GSList
*
cmd_handlers
=
NULL
;
static
GSList
*
signal_handlers
=
NULL
;
static
GSList
*
timeout_handlers
=
NULL
;
static
GSList
*
pref_handlers
=
NULL
;
/* perl < 5.8.0 doesn't define PERL_MAGIC_ext */
#ifndef PERL_MAGIC_ext
#define PERL_MAGIC_ext '~'
#endif
void
purple_perl_plugin_action_cb
(
PurplePluginAction
*
action
)
{
SV
**
callback
;
HV
*
hv
=
NULL
;
gchar
*
hvname
;
PurplePlugin
*
plugin
;
PurplePerlScript
*
gps
;
dSP
;
plugin
=
action
->
plugin
;
gps
=
(
PurplePerlScript
*
)
plugin
->
info
->
extra_info
;
hvname
=
g_strdup_printf
(
"%s::plugin_actions"
,
gps
->
package
);
hv
=
get_hv
(
hvname
,
FALSE
);
g_free
(
hvname
);
if
(
hv
==
NULL
)
croak
(
"No plugin_actions hash found in
\"
%s
\"
plugin."
,
purple_plugin_get_name
(
plugin
));
ENTER
;
SAVETMPS
;
callback
=
hv_fetch
(
hv
,
action
->
label
,
strlen
(
action
->
label
),
0
);
if
(
callback
==
NULL
||
*
callback
==
NULL
)
croak
(
"No plugin_action function named
\"
%s
\"
in
\"
%s
\"
plugin."
,
action
->
label
,
purple_plugin_get_name
(
plugin
));
PUSHMARK
(
sp
);
XPUSHs
(
purple_perl_bless_object
(
gps
->
plugin
,
"Purple::Plugin"
));
PUTBACK
;
call_sv
(
*
callback
,
G_EVAL
|
G_VOID
|
G_DISCARD
);
SPAGAIN
;
if
(
SvTRUE
(
ERRSV
))
{
purple_debug_error
(
"perl"
,
"Perl plugin action function exited abnormally: %s
\n
"
,
SvPVutf8_nolen
(
ERRSV
));
}
PUTBACK
;
FREETMPS
;
LEAVE
;
}
GList
*
purple_perl_plugin_actions
(
PurplePlugin
*
plugin
,
gpointer
context
)
{
GList
*
l
=
NULL
;
PurplePerlScript
*
gps
;
int
i
=
0
,
count
=
0
;
dSP
;
gps
=
plugin
->
info
->
extra_info
;
ENTER
;
SAVETMPS
;
PUSHMARK
(
SP
);
XPUSHs
(
sv_2mortal
(
purple_perl_bless_object
(
plugin
,
"Purple::Plugin"
)));
/* XXX This *will* cease working correctly if context gets changed to
* ever be able to hold anything other than a PurpleConnection */
if
(
context
!=
NULL
)
XPUSHs
(
sv_2mortal
(
purple_perl_bless_object
(
context
,
"Purple::Connection"
)));
else
XPUSHs
(
&
PL_sv_undef
);
PUTBACK
;
count
=
call_pv
(
gps
->
plugin_action_sub
,
G_EVAL
|
G_ARRAY
);
SPAGAIN
;
if
(
SvTRUE
(
ERRSV
))
{
purple_debug_error
(
"perl"
,
"Perl plugin actions lookup exited abnormally: %s
\n
"
,
SvPVutf8_nolen
(
ERRSV
));
}
if
(
count
==
0
)
croak
(
"The plugin_actions sub didn't return anything.
\n
"
);
for
(
i
=
0
;
i
<
count
;
i
++
)
{
SV
*
sv
;
PurplePluginAction
*
act
;
sv
=
POPs
;
act
=
purple_plugin_action_new
(
SvPVutf8_nolen
(
sv
),
purple_perl_plugin_action_cb
);
l
=
g_list_prepend
(
l
,
act
);
}
PUTBACK
;
FREETMPS
;
LEAVE
;
return
l
;
}
#ifdef PURPLE_GTKPERL
GtkWidget
*
purple_perl_gtk_get_plugin_frame
(
PurplePlugin
*
plugin
)
{
SV
*
sv
;
int
count
;
MAGIC
*
mg
;
GtkWidget
*
ret
;
PurplePerlScript
*
gps
;
dSP
;
gps
=
plugin
->
info
->
extra_info
;
ENTER
;
SAVETMPS
;
count
=
call_pv
(
gps
->
gtk_prefs_sub
,
G_EVAL
|
G_SCALAR
|
G_NOARGS
);
if
(
count
!=
1
)
croak
(
"call_pv: Did not return the correct number of values.
\n
"
);
/* the frame was created in a perl sub and is returned */
SPAGAIN
;
if
(
SvTRUE
(
ERRSV
))
{
purple_debug_error
(
"perl"
,
"Perl gtk plugin frame init exited abnormally: %s
\n
"
,
SvPVutf8_nolen
(
ERRSV
));
}
/* We have a Gtk2::Frame on top of the stack */
sv
=
POPs
;
/* The magic field hides the pointer to the actual GtkWidget */
mg
=
mg_find
(
SvRV
(
sv
),
PERL_MAGIC_ext
);
ret
=
(
GtkWidget
*
)
mg
->
mg_ptr
;
PUTBACK
;
FREETMPS
;
LEAVE
;
return
ret
;
}
#endif
PurplePluginPrefFrame
*
purple_perl_get_plugin_frame
(
PurplePlugin
*
plugin
)
{
/* Sets up the Perl Stack for our call back into the script to run the
* plugin_pref... sub */
int
count
;
PurplePerlScript
*
gps
;
PurplePluginPrefFrame
*
ret_frame
;
dSP
;
gps
=
(
PurplePerlScript
*
)
plugin
->
info
->
extra_info
;
ENTER
;
SAVETMPS
;
/* Some perl magic to run perl_plugin_pref_frame_SV perl sub and
* return the frame */
PUSHMARK
(
SP
);
PUTBACK
;
count
=
call_pv
(
gps
->
prefs_sub
,
G_EVAL
|
G_SCALAR
|
G_NOARGS
);
SPAGAIN
;
if
(
SvTRUE
(
ERRSV
))
{
purple_debug_error
(
"perl"
,
"Perl plugin prefs frame init exited abnormally: %s
\n
"
,
SvPVutf8_nolen
(
ERRSV
));
}
if
(
count
!=
1
)
croak
(
"call_pv: Did not return the correct number of values.
\n
"
);
/* the frame was created in a perl sub and is returned */
ret_frame
=
(
PurplePluginPrefFrame
*
)
purple_perl_ref_object
(
POPs
);
/* Tidy up the Perl stack */
PUTBACK
;
FREETMPS
;
LEAVE
;
return
ret_frame
;
}
static
gboolean
destroy_timeout_handler
(
PurplePerlTimeoutHandler
*
handler
)
{
gboolean
ret
=
FALSE
;
timeout_handlers
=
g_slist_remove
(
timeout_handlers
,
handler
);
if
(
handler
->
iotag
>
0
)
ret
=
purple_timeout_remove
(
handler
->
iotag
);
if
(
handler
->
callback
!=
NULL
)
SvREFCNT_dec
(
handler
->
callback
);
if
(
handler
->
data
!=
NULL
)
SvREFCNT_dec
(
handler
->
data
);
g_free
(
handler
);
return
ret
;
}
static
void
destroy_signal_handler
(
PurplePerlSignalHandler
*
handler
)
{
signal_handlers
=
g_slist_remove
(
signal_handlers
,
handler
);
if
(
handler
->
callback
!=
NULL
)
SvREFCNT_dec
(
handler
->
callback
);
if
(
handler
->
data
!=
NULL
)
SvREFCNT_dec
(
handler
->
data
);
g_free
(
handler
->
signal
);
g_free
(
handler
);
}
static
gboolean
perl_timeout_cb
(
gpointer
data
)
{
PurplePerlTimeoutHandler
*
handler
=
data
;
gboolean
ret
=
FALSE
;
dSP
;
ENTER
;
SAVETMPS
;
PUSHMARK
(
sp
);
XPUSHs
((
SV
*
)
handler
->
data
);
PUTBACK
;
call_sv
(
handler
->
callback
,
G_EVAL
|
G_SCALAR
);
SPAGAIN
;
if
(
SvTRUE
(
ERRSV
))
{
purple_debug_error
(
"perl"
,
"Perl timeout function exited abnormally: %s
\n
"
,
SvPVutf8_nolen
(
ERRSV
));
}
ret
=
POPi
;
PUTBACK
;
FREETMPS
;
LEAVE
;
if
(
ret
==
FALSE
)
destroy_timeout_handler
(
handler
);
return
ret
;
}
typedef
void
*
DATATYPE
;
static
void
*
perl_signal_cb
(
va_list
args
,
void
*
data
)
{
PurplePerlSignalHandler
*
handler
=
data
;
void
*
ret_val
=
NULL
;
int
i
;
int
count
;
int
value_count
;
PurpleValue
*
ret_value
,
**
values
;
SV
**
sv_args
;
DATATYPE
**
copy_args
;
dSP
;
PERL_SET_CONTEXT
(
my_perl
);
SPAGAIN
;
ENTER
;
SAVETMPS
;
PUSHMARK
(
sp
);
purple_signal_get_values
(
handler
->
instance
,
handler
->
signal
,
&
ret_value
,
&
value_count
,
&
values
);
sv_args
=
g_new
(
SV
*
,
value_count
);
copy_args
=
g_new
(
void
**
,
value_count
);
for
(
i
=
0
;
i
<
value_count
;
i
++
)
{
sv_args
[
i
]
=
purple_perl_sv_from_vargs
(
values
[
i
],
#ifdef VA_COPY_AS_ARRAY
(
va_list
*
)
args
,
#else
(
va_list
*
)
&
args
,
#endif
&
copy_args
[
i
]);
XPUSHs
(
sv_args
[
i
]);
}
XPUSHs
((
SV
*
)
handler
->
data
);
PUTBACK
;
if
(
ret_value
!=
NULL
)
{
count
=
call_sv
(
handler
->
callback
,
G_EVAL
|
G_SCALAR
);
SPAGAIN
;
if
(
count
!=
1
)
croak
(
"Uh oh! call_sv returned %i != 1"
,
i
);
else
ret_val
=
purple_perl_data_from_sv
(
ret_value
,
POPs
);
}
else
{
call_sv
(
handler
->
callback
,
G_EVAL
|
G_SCALAR
);
SPAGAIN
;
}
if
(
SvTRUE
(
ERRSV
))
{
purple_debug_error
(
"perl"
,
"Perl function exited abnormally: %s
\n
"
,
SvPVutf8_nolen
(
ERRSV
));
}
/* See if any parameters changed. */
for
(
i
=
0
;
i
<
value_count
;
i
++
)
{
if
(
purple_value_is_outgoing
(
values
[
i
]))
{
switch
(
purple_value_get_type
(
values
[
i
]))
{
case
PURPLE_TYPE_BOOLEAN
:
*
((
gboolean
*
)
copy_args
[
i
])
=
SvIV
(
sv_args
[
i
]);
break
;
case
PURPLE_TYPE_INT
:
*
((
int
*
)
copy_args
[
i
])
=
SvIV
(
sv_args
[
i
]);
break
;
case
PURPLE_TYPE_UINT
:
*
((
unsigned
int
*
)
copy_args
[
i
])
=
SvUV
(
sv_args
[
i
]);
break
;
case
PURPLE_TYPE_LONG
:
*
((
long
*
)
copy_args
[
i
])
=
SvIV
(
sv_args
[
i
]);
break
;
case
PURPLE_TYPE_ULONG
:
*
((
unsigned
long
*
)
copy_args
[
i
])
=
SvUV
(
sv_args
[
i
]);
break
;
case
PURPLE_TYPE_INT64
:
*
((
gint64
*
)
copy_args
[
i
])
=
SvIV
(
sv_args
[
i
]);
break
;
case
PURPLE_TYPE_UINT64
:
*
((
guint64
*
)
copy_args
[
i
])
=
SvUV
(
sv_args
[
i
]);
break
;
case
PURPLE_TYPE_STRING
:
if
(
!*
((
char
**
)
copy_args
[
i
])
||
!
SvPVX
(
sv_args
[
i
])
||
!
purple_strequal
(
*
((
char
**
)
copy_args
[
i
]),
SvPVX
(
sv_args
[
i
])))
{
g_free
(
*
((
char
**
)
copy_args
[
i
]));
*
((
char
**
)
copy_args
[
i
])
=
g_strdup
(
SvPVutf8_nolen
(
sv_args
[
i
]));
}
/* Clean up sv_args[i] - we're done with it */
sv_2mortal
(
sv_args
[
i
]);
break
;
case
PURPLE_TYPE_POINTER
:
case
PURPLE_TYPE_BOXED
:
*
((
void
**
)
copy_args
[
i
])
=
(
void
*
)
SvIV
(
sv_args
[
i
]);
break
;
case
PURPLE_TYPE_SUBTYPE
:
*
((
void
**
)
copy_args
[
i
])
=
purple_perl_ref_object
(
sv_args
[
i
]);
break
;
default
:
break
;
}
#if 0
*((void **)copy_args[i]) = purple_perl_data_from_sv(values[i],
sv_args[i]);
#endif
}
}
PUTBACK
;
FREETMPS
;
LEAVE
;
g_free
(
sv_args
);
g_free
(
copy_args
);
purple_debug_misc
(
"perl"
,
"ret_val = %p
\n
"
,
ret_val
);
return
ret_val
;
}
static
PurplePerlSignalHandler
*
find_signal_handler
(
PurplePlugin
*
plugin
,
void
*
instance
,
const
char
*
signal
)
{
PurplePerlSignalHandler
*
handler
;
GSList
*
l
;
for
(
l
=
signal_handlers
;
l
!=
NULL
;
l
=
l
->
next
)
{
handler
=
l
->
data
;
if
(
handler
->
plugin
==
plugin
&&
handler
->
instance
==
instance
&&
purple_strequal
(
handler
->
signal
,
signal
))
{
return
handler
;
}
}
return
NULL
;
}
guint
purple_perl_timeout_add
(
PurplePlugin
*
plugin
,
int
seconds
,
SV
*
callback
,
SV
*
data
)
{
PurplePerlTimeoutHandler
*
handler
;
if
(
plugin
==
NULL
)
{
croak
(
"Invalid handle in adding perl timeout handler.
\n
"
);
return
0
;
}
handler
=
g_new0
(
PurplePerlTimeoutHandler
,
1
);
handler
->
plugin
=
plugin
;
handler
->
callback
=
(
callback
!=
NULL
&&
callback
!=
&
PL_sv_undef
?
newSVsv
(
callback
)
:
NULL
);
handler
->
data
=
(
data
!=
NULL
&&
data
!=
&
PL_sv_undef
?
newSVsv
(
data
)
:
NULL
);
timeout_handlers
=
g_slist_append
(
timeout_handlers
,
handler
);
handler
->
iotag
=
purple_timeout_add_seconds
(
seconds
,
perl_timeout_cb
,
handler
);
return
handler
->
iotag
;
}
gboolean
purple_perl_timeout_remove
(
guint
handle
)
{
PurplePerlTimeoutHandler
*
handler
;
GSList
*
l
,
*
l_next
;
for
(
l
=
timeout_handlers
;
l
!=
NULL
;
l
=
l_next
)
{
handler
=
l
->
data
;
l_next
=
l
->
next
;
if
(
handler
->
iotag
==
handle
)
return
destroy_timeout_handler
(
handler
);
}
purple_debug_info
(
"perl"
,
"No timeout handler found with handle %u.
\n
"
,
handle
);
return
FALSE
;
}
void
purple_perl_timeout_clear_for_plugin
(
PurplePlugin
*
plugin
)
{
PurplePerlTimeoutHandler
*
handler
;
GSList
*
l
,
*
l_next
;
for
(
l
=
timeout_handlers
;
l
!=
NULL
;
l
=
l_next
)
{
handler
=
l
->
data
;
l_next
=
l
->
next
;
if
(
handler
->
plugin
==
plugin
)
destroy_timeout_handler
(
handler
);
}
}
void
purple_perl_timeout_clear
(
void
)
{
while
(
timeout_handlers
!=
NULL
)
destroy_timeout_handler
(
timeout_handlers
->
data
);
}
void
purple_perl_signal_connect
(
PurplePlugin
*
plugin
,
void
*
instance
,
const
char
*
signal
,
SV
*
callback
,
SV
*
data
,
int
priority
)
{
PurplePerlSignalHandler
*
handler
;
handler
=
g_new0
(
PurplePerlSignalHandler
,
1
);
handler
->
plugin
=
plugin
;
handler
->
instance
=
instance
;
handler
->
signal
=
g_strdup
(
signal
);
handler
->
callback
=
(
callback
!=
NULL
&&
callback
!=
&
PL_sv_undef
?
newSVsv
(
callback
)
:
NULL
);
handler
->
data
=
(
data
!=
NULL
&&
data
!=
&
PL_sv_undef
?
newSVsv
(
data
)
:
NULL
);
signal_handlers
=
g_slist_append
(
signal_handlers
,
handler
);
purple_signal_connect_priority_vargs
(
instance
,
signal
,
plugin
,
PURPLE_CALLBACK
(
perl_signal_cb
),
handler
,
priority
);
}
void
purple_perl_signal_disconnect
(
PurplePlugin
*
plugin
,
void
*
instance
,
const
char
*
signal
)
{
PurplePerlSignalHandler
*
handler
;
handler
=
find_signal_handler
(
plugin
,
instance
,
signal
);
if
(
handler
==
NULL
)
{
croak
(
"Invalid signal handler information in "
"disconnecting a perl signal handler.
\n
"
);
return
;
}
destroy_signal_handler
(
handler
);
}
void
purple_perl_signal_clear_for_plugin
(
PurplePlugin
*
plugin
)
{
PurplePerlSignalHandler
*
handler
;
GSList
*
l
,
*
l_next
;
for
(
l
=
signal_handlers
;
l
!=
NULL
;
l
=
l_next
)
{
l_next
=
l
->
next
;
handler
=
l
->
data
;
if
(
handler
->
plugin
==
plugin
)
destroy_signal_handler
(
handler
);
}
}
void
purple_perl_signal_clear
(
void
)
{
while
(
signal_handlers
!=
NULL
)
destroy_signal_handler
(
signal_handlers
->
data
);
}
static
PurpleCmdRet
perl_cmd_cb
(
PurpleConversation
*
conv
,
const
gchar
*
command
,
gchar
**
args
,
gchar
**
error
,
void
*
data
)
{
int
i
=
0
,
count
,
ret_value
=
PURPLE_CMD_RET_OK
;
SV
*
cmdSV
,
*
tmpSV
,
*
convSV
;
PurplePerlCmdHandler
*
handler
=
data
;
dSP
;
ENTER
;
SAVETMPS
;
PUSHMARK
(
SP
);
/* Push the conversation onto the perl stack */
convSV
=
sv_2mortal
(
purple_perl_bless_object
(
conv
,
"Purple::Conversation"
));
XPUSHs
(
convSV
);
/* Push the command string onto the perl stack */
cmdSV
=
newSVpv
(
command
,
0
);
cmdSV
=
sv_2mortal
(
cmdSV
);
XPUSHs
(
cmdSV
);
/* Push the data onto the perl stack */
XPUSHs
((
SV
*
)
handler
->
data
);
/* Push any arguments we may have */
for
(
i
=
0
;
args
[
i
]
!=
NULL
;
i
++
)
{
/* XXX The mortality of these created SV's should prevent
* memory issues, if I read/understood everything correctly...
*/
tmpSV
=
newSVpv
(
args
[
i
],
0
);
tmpSV
=
sv_2mortal
(
tmpSV
);
XPUSHs
(
tmpSV
);
}
PUTBACK
;
count
=
call_sv
(
handler
->
callback
,
G_EVAL
|
G_SCALAR
);
if
(
count
!=
1
)
croak
(
"call_sv: Did not return the correct number of values.
\n
"
);
if
(
SvTRUE
(
ERRSV
))
{
purple_debug_error
(
"perl"
,
"Perl plugin command function exited abnormally: %s
\n
"
,
SvPVutf8_nolen
(
ERRSV
));
}
SPAGAIN
;
ret_value
=
POPi
;
PUTBACK
;
FREETMPS
;
LEAVE
;
return
ret_value
;
}
PurpleCmdId
purple_perl_cmd_register
(
PurplePlugin
*
plugin
,
const
gchar
*
command
,
const
gchar
*
args
,
PurpleCmdPriority
priority
,
PurpleCmdFlag
flag
,
const
gchar
*
prpl_id
,
SV
*
callback
,
const
gchar
*
helpstr
,
SV
*
data
)
{
PurplePerlCmdHandler
*
handler
;
handler
=
g_new0
(
PurplePerlCmdHandler
,
1
);
handler
->
plugin
=
plugin
;
handler
->
cmd
=
g_strdup
(
command
);
handler
->
prpl_id
=
g_strdup
(
prpl_id
);
if
(
callback
!=
NULL
&&
callback
!=
&
PL_sv_undef
)
handler
->
callback
=
newSVsv
(
callback
);
else
handler
->
callback
=
NULL
;
if
(
data
!=
NULL
&&
data
!=
&
PL_sv_undef
)
handler
->
data
=
newSVsv
(
data
);
else
handler
->
data
=
NULL
;
cmd_handlers
=
g_slist_append
(
cmd_handlers
,
handler
);
handler
->
id
=
purple_cmd_register
(
command
,
args
,
priority
,
flag
,
prpl_id
,
PURPLE_CMD_FUNC
(
perl_cmd_cb
),
helpstr
,
handler
);
return
handler
->
id
;
}
static
void
destroy_cmd_handler
(
PurplePerlCmdHandler
*
handler
)
{
purple_cmd_unregister
(
handler
->
id
);
cmd_handlers
=
g_slist_remove
(
cmd_handlers
,
handler
);
if
(
handler
->
callback
!=
NULL
)
SvREFCNT_dec
(
handler
->
callback
);
if
(
handler
->
data
!=
NULL
)
SvREFCNT_dec
(
handler
->
data
);
g_free
(
handler
->
cmd
);
g_free
(
handler
->
prpl_id
);
g_free
(
handler
);
}
void
purple_perl_cmd_clear_for_plugin
(
PurplePlugin
*
plugin
)
{
PurplePerlCmdHandler
*
handler
;
GSList
*
l
,
*
l_next
;
for
(
l
=
cmd_handlers
;
l
!=
NULL
;
l
=
l_next
)
{
handler
=
l
->
data
;
l_next
=
l
->
next
;
if
(
handler
->
plugin
==
plugin
)
destroy_cmd_handler
(
handler
);
}
}
static
PurplePerlCmdHandler
*
find_cmd_handler
(
PurpleCmdId
id
)
{
PurplePerlCmdHandler
*
handler
;
GSList
*
l
;
for
(
l
=
cmd_handlers
;
l
!=
NULL
;
l
=
l
->
next
)
{
handler
=
(
PurplePerlCmdHandler
*
)
l
->
data
;
if
(
handler
->
id
==
id
)
return
handler
;
}
return
NULL
;
}
void
purple_perl_cmd_unregister
(
PurpleCmdId
id
)
{
PurplePerlCmdHandler
*
handler
;
handler
=
find_cmd_handler
(
id
);
if
(
handler
==
NULL
)
{
croak
(
"Invalid command id in removing a perl command handler.
\n
"
);
return
;
}
destroy_cmd_handler
(
handler
);
}
static
void
perl_pref_cb
(
const
char
*
name
,
PurplePrefType
type
,
gconstpointer
value
,
gpointer
data
)
{
PurplePerlPrefsHandler
*
handler
=
data
;
dSP
;
ENTER
;
SAVETMPS
;
PUSHMARK
(
sp
);
XPUSHs
(
sv_2mortal
(
newSVpv
(
name
,
0
)));
XPUSHs
(
sv_2mortal
(
newSViv
(
type
)));
switch
(
type
)
{
case
PURPLE_PREF_INT
:
XPUSHs
(
sv_2mortal
(
newSViv
(
GPOINTER_TO_INT
(
value
))));
break
;
case
PURPLE_PREF_BOOLEAN
:
XPUSHs
((
GPOINTER_TO_INT
(
value
)
==
FALSE
)
?
&
PL_sv_no
:
&
PL_sv_yes
);
break
;
case
PURPLE_PREF_STRING
:
case
PURPLE_PREF_PATH
:
XPUSHs
(
sv_2mortal
(
newSVGChar
(
value
)));
break
;
case
PURPLE_PREF_STRING_LIST
:
case
PURPLE_PREF_PATH_LIST
:
{
AV
*
av
=
newAV
();
const
GList
*
l
=
value
;
/* Append stuff backward to preserve order */
while
(
l
&&
l
->
next
)
l
=
l
->
next
;
while
(
l
)
{
av_push
(
av
,
sv_2mortal
(
newSVGChar
(
l
->
data
)));
l
=
l
->
prev
;
}
XPUSHs
(
sv_2mortal
(
newRV_noinc
((
SV
*
)
av
)));
}
break
;
default
:
case
PURPLE_PREF_NONE
:
XPUSHs
(
&
PL_sv_undef
);
break
;
}
XPUSHs
((
SV
*
)
handler
->
data
);
PUTBACK
;
call_sv
(
handler
->
callback
,
G_EVAL
|
G_VOID
|
G_DISCARD
);
SPAGAIN
;
if
(
SvTRUE
(
ERRSV
))
{
purple_debug_error
(
"perl"
,
"Perl prefs callback function exited abnormally: %s
\n
"
,
SvPVutf8_nolen
(
ERRSV
));
}
PUTBACK
;
FREETMPS
;
LEAVE
;
}
guint
purple_perl_prefs_connect_callback
(
PurplePlugin
*
plugin
,
const
char
*
name
,
SV
*
callback
,
SV
*
data
)
{
PurplePerlPrefsHandler
*
handler
;
if
(
plugin
==
NULL
)
{
croak
(
"Invalid handle in adding perl prefs handler.
\n
"
);
return
0
;
}
handler
=
g_new0
(
PurplePerlPrefsHandler
,
1
);
handler
->
plugin
=
plugin
;
handler
->
callback
=
(
callback
!=
NULL
&&
callback
!=
&
PL_sv_undef
?
newSVsv
(
callback
)
:
NULL
);
handler
->
data
=
(
data
!=
NULL
&&
data
!=
&
PL_sv_undef
?
newSVsv
(
data
)
:
NULL
);
pref_handlers
=
g_slist_prepend
(
pref_handlers
,
handler
);
handler
->
iotag
=
purple_prefs_connect_callback
(
plugin
,
name
,
perl_pref_cb
,
handler
);
return
handler
->
iotag
;
}
static
void
destroy_prefs_handler
(
PurplePerlPrefsHandler
*
handler
)
{
pref_handlers
=
g_slist_remove
(
pref_handlers
,
handler
);
if
(
handler
->
iotag
>
0
)
purple_prefs_disconnect_callback
(
handler
->
iotag
);
if
(
handler
->
callback
!=
NULL
)
SvREFCNT_dec
(
handler
->
callback
);
if
(
handler
->
data
!=
NULL
)
SvREFCNT_dec
(
handler
->
data
);
g_free
(
handler
);
}
void
purple_perl_prefs_disconnect_callback
(
guint
callback_id
)
{
GSList
*
l
,
*
l_next
;
PurplePerlPrefsHandler
*
handler
;
for
(
l
=
pref_handlers
;
l
!=
NULL
;
l
=
l_next
)
{
l_next
=
l
->
next
;
handler
=
l
->
data
;
if
(
handler
->
iotag
==
callback_id
)
{
destroy_prefs_handler
(
handler
);
return
;
}
}
purple_debug_info
(
"perl"
,
"No prefs handler found with handle %u.
\n
"
,
callback_id
);
}
void
purple_perl_pref_cb_clear_for_plugin
(
PurplePlugin
*
plugin
)
{
GSList
*
l
,
*
l_next
;
PurplePerlPrefsHandler
*
handler
;
for
(
l
=
pref_handlers
;
l
!=
NULL
;
l
=
l_next
)
{
l_next
=
l
->
next
;
handler
=
l
->
data
;
if
(
handler
->
plugin
==
plugin
)
destroy_prefs_handler
(
handler
);
}
}