1
0
mirror of https://github.com/irssi/irssi.git synced 2024-11-03 04:27:19 -05:00

Exported expando interface to perl. Fix for statusbar deinit.

git-svn-id: http://svn.irssi.org/repos/irssi/trunk@2975 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
Timo Sirainen 2002-10-27 22:30:41 +00:00 committed by cras
parent d3f4f13f94
commit d58e119a98
8 changed files with 192 additions and 3 deletions

View File

@ -46,6 +46,8 @@ typedef struct {
int signal_args[MAX_EXPANDO_SIGNALS];
} EXPANDO_REC;
const char *current_expando = NULL;
static int timer_tag;
static EXPANDO_REC *char_expandos[255];

View File

@ -16,6 +16,8 @@ typedef enum {
typedef char* (*EXPANDO_FUNC)
(SERVER_REC *server, void *item, int *free_ret);
extern const char *current_expando;
/* Create expando - overrides any existing ones.
... = signal, type, ..., NULL - list of signals that might change the
value of this expando */

View File

@ -113,8 +113,10 @@ static char *get_long_variable_value(const char *key, SERVER_REC *server,
/* expando? */
func = expando_find_long(key);
if (func != NULL)
if (func != NULL) {
current_expando = key;
return func(server, item, free_ret);
}
/* internal setting? */
type = settings_get_type(key);
@ -176,7 +178,15 @@ static char *get_variable(char **cmd, SERVER_REC *server, void *item,
}
*free_ret = FALSE;
func = expando_find_char(**cmd);
return func == NULL ? NULL : func(server, item, free_ret);
if (func == NULL)
return NULL;
else {
char str[2];
str[0] = **cmd; str[1] = '\0';
current_expando = str;
return func(server, item, free_ret);
}
}
static char *get_history(char **cmd, void *item, int *free_ret)

View File

@ -78,6 +78,7 @@ common_sources = \
common/Irssi.pm \
common/Channel.xs \
common/Core.xs \
common/Expandos.xs \
common/Ignore.xs \
common/Log.xs \
common/Masks.xs \

170
src/perl/common/Expando.xs Normal file
View File

@ -0,0 +1,170 @@
#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;
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));
ret = NULL;
} 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);

View File

@ -14,16 +14,19 @@ CODE:
initialized = TRUE;
perl_settings_init();
perl_expando_init();
void
deinit()
CODE:
if (!initialized) return;
perl_expando_deinit();
perl_settings_deinit();
BOOT:
irssi_boot(Channel);
irssi_boot(Core);
irssi_boot(Expando);
irssi_boot(Ignore);
irssi_boot(Log);
irssi_boot(Masks);

View File

@ -31,7 +31,7 @@ PPCODE:
}
Irssi::Connect
server_create_conn(chat_type, dest, port=6667, chatnet=NULL, password=NULL, nick=NULL)
server_create_conn(chat_type, dest, port, chatnet=NULL, password=NULL, nick=NULL)
int chat_type
char *dest
int port

View File

@ -31,6 +31,7 @@ void perl_statusbar_init(void)
static void statusbar_item_def_destroy(void *key, void *value)
{
statusbar_item_unregister(key);
g_free(key);
g_free(value);
}