1
0
mirror of https://github.com/irssi/irssi.git synced 2024-06-30 06:45:25 +00:00

added signal_continue() for continuing signal emission with new parameters.

git-svn-id: http://svn.irssi.org/repos/irssi/trunk@2730 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
Timo Sirainen 2002-04-27 21:53:25 +00:00 committed by cras
parent 4b45f190a2
commit da867d4d68
3 changed files with 67 additions and 13 deletions

View File

@ -39,6 +39,7 @@ typedef struct {
int emitting; /* signal is being emitted */
int stop_emit; /* this signal was stopped */
int continue_emit; /* this signal emit was continued elsewhere */
int remove_count; /* hooks were removed from signal */
SignalHook *hooks;
@ -51,6 +52,7 @@ void *signal_user_data;
static GHashTable *signals;
static Signal *current_emitted_signal;
static SignalHook *current_emitted_hook;
#define signal_ref(signal) ++(signal)->refcount
#define signal_unref(signal) (signal_unref_full(signal, TRUE))
@ -208,12 +210,13 @@ static void signal_hooks_clean(Signal *rec)
}
}
static int signal_emit_real(Signal *rec, int params, va_list va)
static int signal_emit_real(Signal *rec, int params, va_list va,
SignalHook *first_hook)
{
const void *arglist[SIGNAL_MAX_ARGUMENTS];
Signal *prev_emitted_signal;
SignalHook *hook;
int i, stopped, stop_emit_count;
SignalHook *hook, *prev_emitted_hook;
int i, stopped, stop_emit_count, continue_emit_count;
for (i = 0; i < SIGNAL_MAX_ARGUMENTS; i++)
arglist[i] = i >= params ? NULL : va_arg(va, const void *);
@ -221,18 +224,22 @@ static int signal_emit_real(Signal *rec, int params, va_list va)
/* signal_stop_by_name("signal"); signal_emit("signal", ...);
fails if we compare rec->stop_emit against 0. */
stop_emit_count = rec->stop_emit;
continue_emit_count = rec->continue_emit;
signal_ref(rec);
stopped = FALSE;
rec->emitting++;
for (hook = rec->hooks; hook != NULL; hook = hook->next) {
prev_emitted_signal = current_emitted_signal;
prev_emitted_hook = current_emitted_hook;
current_emitted_signal = rec;
for (hook = first_hook; hook != NULL; hook = hook->next) {
if (hook->func == NULL)
continue; /* removed */
prev_emitted_signal = current_emitted_signal;
current_emitted_signal = rec;
current_emitted_hook = hook;
#if SIGNAL_MAX_ARGUMENTS != 6
# error SIGNAL_MAX_ARGUMENTS changed - update code
#endif
@ -240,7 +247,8 @@ static int signal_emit_real(Signal *rec, int params, va_list va)
hook->func(arglist[0], arglist[1], arglist[2], arglist[3],
arglist[4], arglist[5]);
current_emitted_signal = prev_emitted_signal;
if (rec->continue_emit != continue_emit_count)
rec->continue_emit--;
if (rec->stop_emit != stop_emit_count) {
stopped = TRUE;
@ -248,14 +256,16 @@ static int signal_emit_real(Signal *rec, int params, va_list va)
break;
}
}
current_emitted_signal = prev_emitted_signal;
current_emitted_hook = prev_emitted_hook;
rec->emitting--;
signal_user_data = NULL;
if (!rec->emitting) {
if (rec->stop_emit != 0) {
/* signal_stop() used too many times */
rec->stop_emit = 0;
}
g_assert(rec->stop_emit == 0);
g_assert(rec->continue_emit == 0);
if (rec->remove_count > 0)
signal_hooks_clean(rec);
@ -278,7 +288,7 @@ int signal_emit(const char *signal, int params, ...)
rec = g_hash_table_lookup(signals, GINT_TO_POINTER(signal_id));
if (rec != NULL) {
va_start(va, params);
signal_emit_real(rec, params, va);
signal_emit_real(rec, params, va, rec->hooks);
va_end(va);
}
@ -296,13 +306,35 @@ int signal_emit_id(int signal_id, int params, ...)
rec = g_hash_table_lookup(signals, GINT_TO_POINTER(signal_id));
if (rec != NULL) {
va_start(va, params);
signal_emit_real(rec, params, va);
signal_emit_real(rec, params, va, rec->hooks);
va_end(va);
}
return rec != NULL;
}
void signal_continue(int params, ...)
{
Signal *rec;
va_list va;
rec = current_emitted_signal;
if (rec == NULL || rec->emitting <= rec->continue_emit)
g_warning("signal_continue() : no signals are being emitted currently");
else {
va_start(va, params);
/* stop the signal */
if (rec->emitting > rec->stop_emit)
rec->stop_emit++;
/* re-emit */
rec->continue_emit++;
signal_emit_real(rec, params, va, current_emitted_hook->next);
va_end(va);
}
}
/* stop the current ongoing signal emission */
void signal_stop(void)
{

View File

@ -43,6 +43,9 @@ void signal_remove_id(int signal_id, SIGNAL_FUNC func, void *user_data);
int signal_emit(const char *signal, int params, ...);
int signal_emit_id(int signal_id, int params, ...);
/* continue currently emitted signal with different parameters */
void signal_continue(int params, ...);
/* stop the current ongoing signal emission */
void signal_stop(void);
/* stop ongoing signal emission by signal name */

View File

@ -76,6 +76,25 @@ CODE:
}
signal_emit(signal, items-1, p[0], p[1], p[2], p[3], p[4], p[5]);
void
signal_continue(...)
CODE:
void *p[SIGNAL_MAX_ARGUMENTS];
int n;
memset(p, 0, sizeof(p));
for (n = 0; n < items && n < SIGNAL_MAX_ARGUMENTS; n++) {
if (SvPOKp(ST(n)))
p[n] = SvPV(ST(n), PL_na);
else if (irssi_is_ref_object(ST(n)))
p[n] = irssi_ref_object(ST(n));
else if (SvROK(ST(n)))
p[n] = (void *) SvIV((SV*)SvRV(ST(n)));
else
p[n] = NULL;
}
signal_continue(items, p[0], p[1], p[2], p[3], p[4], p[5]);
void
signal_add(...)
CODE: