1
0
mirror of https://github.com/irssi/irssi.git synced 2024-11-03 04:27:19 -05:00
irssi/src/perl/textui/Statusbar.xs
LemonBoy 21539019dd Make sure to make a copy of ERRSV content.
Otherwise we might end up showing an empty message.
Fixes #522.
2016-09-13 17:11:05 +02:00

168 lines
4.1 KiB
Plaintext

#define PERL_NO_GET_CONTEXT
#include "module.h"
static GHashTable *perl_sbar_defs;
static int check_sbar_destroy(char *key, char *value, char *script)
{
if (strncmp(value, script, strlen(script)) == 0 &&
value[strlen(script)] == ':') {
statusbar_item_unregister(key);
g_free(key);
g_free(value);
return TRUE;
}
return FALSE;
}
static void script_unregister_statusbars(PERL_SCRIPT_REC *script)
{
g_hash_table_foreach_remove(perl_sbar_defs,
(GHRFunc) check_sbar_destroy,
script->package);
}
void perl_statusbar_init(void)
{
perl_sbar_defs = g_hash_table_new((GHashFunc) g_str_hash,
(GCompareFunc) g_str_equal);
signal_add("script destroyed", (SIGNAL_FUNC) script_unregister_statusbars);
}
static void statusbar_item_def_destroy(void *key, void *value)
{
statusbar_item_unregister(key);
g_free(key);
g_free(value);
}
void perl_statusbar_deinit(void)
{
signal_remove("script destroyed", (SIGNAL_FUNC) script_unregister_statusbars);
g_hash_table_foreach(perl_sbar_defs,
(GHFunc) statusbar_item_def_destroy, NULL);
g_hash_table_destroy(perl_sbar_defs);
}
static void perl_statusbar_event(char *function, SBAR_ITEM_REC *item,
int get_size_only)
{
dSP;
SV *item_sv, **sv;
HV *hv;
ENTER;
SAVETMPS;
PUSHMARK(SP);
item_sv = plain_bless(item, "Irssi::TextUI::StatusbarItem");
XPUSHs(sv_2mortal(item_sv));
XPUSHs(sv_2mortal(newSViv(get_size_only)));
PUTBACK;
perl_call_pv(function, G_EVAL|G_DISCARD);
SPAGAIN;
if (SvTRUE(ERRSV)) {
PERL_SCRIPT_REC *script;
char *package;
package = perl_function_get_package(function);
script = perl_script_find_package(package);
g_free(package);
if (script != NULL) {
/* make sure we don't get back here */
script_unregister_statusbars(script);
}
char *error = g_strdup(SvPV_nolen(ERRSV));
signal_emit("script error", 2, script, error);
g_free(error);
} else {
/* min_size and max_size can be changed, move them to SBAR_ITEM_REC */
hv = hvref(item_sv);
if (hv != NULL) {
sv = hv_fetch(hv, "min_size", 8, 0);
if (sv != NULL) item->min_size = SvIV(*sv);
sv = hv_fetch(hv, "max_size", 8, 0);
if (sv != NULL) item->max_size = SvIV(*sv);
}
}
FREETMPS;
LEAVE;
}
static void sig_perl_statusbar(SBAR_ITEM_REC *item, int get_size_only)
{
char *function;
function = g_hash_table_lookup(perl_sbar_defs, item->config->name);
if (function != NULL)
perl_statusbar_event(function, item, get_size_only);
else {
/* use default function - this shouldn't actually happen.. */
statusbar_item_default_handler(item, get_size_only, NULL, "", TRUE);
}
}
MODULE = Irssi::TextUI::Statusbar PACKAGE = Irssi
PROTOTYPES: ENABLE
void
statusbar_item_register(name, value, func = NULL)
char *name
char *value
char *func
CODE:
statusbar_item_register(name, value, func == NULL || *func == '\0' ? NULL : sig_perl_statusbar);
if (func != NULL) {
g_hash_table_insert(perl_sbar_defs, g_strdup(name),
g_strdup_printf("%s::%s", perl_get_package(), func));
}
void
statusbar_item_unregister(name)
char *name
PREINIT:
gpointer key, value;
CODE:
if (g_hash_table_lookup_extended(perl_sbar_defs, name, &key, &value)) {
g_hash_table_remove(perl_sbar_defs, name);
g_free(key);
g_free(value);
}
statusbar_item_unregister(name);
void
statusbar_items_redraw(name)
char *name
void
statusbars_recreate_items()
#*******************************
MODULE = Irssi::TextUI::Statusbar PACKAGE = Irssi::TextUI::StatusbarItem PREFIX = statusbar_item_
#*******************************
void
statusbar_item_default_handler(item, get_size_only, str, data, escape_vars = TRUE)
Irssi::TextUI::StatusbarItem item
int get_size_only
char *str
char *data
int escape_vars
PREINIT:
HV *hv;
CODE:
statusbar_item_default_handler(item, get_size_only,
*str == '\0' ? NULL : str,
data, escape_vars);
hv = hvref(ST(0));
(void) hv_store(hv, "min_size", 8, newSViv(item->min_size), 0);
(void) hv_store(hv, "max_size", 8, newSViv(item->max_size), 0);