+++ /dev/null
-#include "module.h"
-#include "expandos.h"
-
-typedef struct {
- PERL_SCRIPT_REC *script;
- SV *func;
-} PerlExpando;
-
-static GHashTable *perl_expando_defs;
-
-static char *sig_perl_expando(SERVER_REC *server, void *item, int *free_ret);
-
-static int check_expando_destroy(char *key, PerlExpando *rec,
- PERL_SCRIPT_REC *script)
-{
- if (rec->script == script) {
- expando_destroy(key, sig_perl_expando);
- SvREFCNT_dec(rec->func);
- g_free(key);
- g_free(rec);
- return TRUE;
- }
-
- return FALSE;
-}
-
-static void script_unregister_expandos(PERL_SCRIPT_REC *script)
-{
- g_hash_table_foreach_remove(perl_expando_defs,
- (GHRFunc) check_expando_destroy, script);
-}
-
-void perl_expando_init(void)
-{
- perl_expando_defs = g_hash_table_new((GHashFunc) g_str_hash,
- (GCompareFunc) g_str_equal);
- signal_add("script destroyed", (SIGNAL_FUNC) script_unregister_expandos);
-}
-
-static void expando_def_destroy(char *key, PerlExpando *rec)
-{
- SvREFCNT_dec(rec->func);
- g_free(key);
- g_free(rec);
-}
-
-void perl_expando_deinit(void)
-{
- signal_remove("script destroyed", (SIGNAL_FUNC) script_unregister_expandos);
-
- g_hash_table_foreach(perl_expando_defs,
- (GHFunc) expando_def_destroy, NULL);
- g_hash_table_destroy(perl_expando_defs);
-}
-
-static char *perl_expando_event(PerlExpando *rec, SERVER_REC *server,
- WI_ITEM_REC *item, int *free_ret)
-{
- dSP;
- char *ret;
- int retcount;
-
- ENTER;
- SAVETMPS;
-
- PUSHMARK(SP);
- XPUSHs(sv_2mortal(iobject_bless(server)));
- XPUSHs(sv_2mortal(iobject_bless(item)));
- PUTBACK;
-
- retcount = perl_call_sv(rec->func, G_EVAL|G_SCALAR);
- SPAGAIN;
-
- ret = NULL;
- if (SvTRUE(ERRSV)) {
- /* make sure we don't get back here */
- if (rec->script != NULL)
- script_unregister_expandos(rec->script);
-
- signal_emit("script error", 2, rec->script, SvPV(ERRSV, PL_na));
- } else if (retcount > 0) {
- ret = g_strdup(POPp);
- *free_ret = TRUE;
- }
-
- PUTBACK;
- FREETMPS;
- LEAVE;
-
- return ret;
-}
-
-static char *sig_perl_expando(SERVER_REC *server, void *item, int *free_ret)
-{
- PerlExpando *rec;
-
- rec = g_hash_table_lookup(perl_expando_defs, current_expando);
- if (rec != NULL)
- return perl_expando_event(rec, server, item, free_ret);
- return NULL;
-}
-
-void expando_signals_add_hash(const char *key, SV *signals)
-{
- HV *hv;
- HE *he;
- I32 len;
- const char *argstr;
- ExpandoArg arg;
-
- if (!is_hvref(signals)) {
- croak("Usage: Irssi::expando_create(key, func, hash)");
- return;
- }
-
- hv = hvref(signals);
- hv_iterinit(hv);
- while ((he = hv_iternext(hv)) != NULL) {
- SV *argsv = HeVAL(he);
- argstr = SvPV(argsv, PL_na);
-
- if (strcasecmp(argstr, "none") == 0)
- arg = EXPANDO_ARG_NONE;
- else if (strcasecmp(argstr, "server") == 0)
- arg = EXPANDO_ARG_SERVER;
- else if (strcasecmp(argstr, "window") == 0)
- arg = EXPANDO_ARG_WINDOW;
- else if (strcasecmp(argstr, "windowitem") == 0)
- arg = EXPANDO_ARG_WINDOW_ITEM;
- else if (strcasecmp(argstr, "never") == 0)
- arg = EXPANDO_NEVER;
- else {
- croak("Unknown signal type: %s", argstr);
- break;
- }
- expando_add_signal(key, hv_iterkey(he, &len), arg);
- }
-}
-
-MODULE = Irssi::Expando PACKAGE = Irssi
-PROTOTYPES: ENABLE
-
-void
-expando_create(key, func, signals)
- char *key
- SV *func
- SV *signals
-PREINIT:
- PerlExpando *rec;
-CODE:
- rec = g_new0(PerlExpando, 1);
- rec->script = perl_script_find_package(perl_get_package());
- rec->func = perl_func_sv_inc(func, perl_get_package());
-
- expando_create(key, sig_perl_expando, NULL);
- g_hash_table_insert(perl_expando_defs, g_strdup(key), rec);
- expando_signals_add_hash(key, signals);
-
-void
-expando_destroy(name)
- char *name
-PREINIT:
- gpointer key, value;
-CODE:
- if (g_hash_table_lookup_extended(perl_expando_defs, name, &key, &value)) {
- g_hash_table_remove(perl_expando_defs, name);
- g_free(key);
- SvREFCNT_dec((SV *) value);
- }
- expando_destroy(name, sig_perl_expando);