1
0
mirror of https://github.com/irssi/irssi.git synced 2024-09-29 04:45:57 -04: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 emitting; /* signal is being emitted */
int stop_emit; /* this signal was stopped */ int stop_emit; /* this signal was stopped */
int continue_emit; /* this signal emit was continued elsewhere */
int remove_count; /* hooks were removed from signal */ int remove_count; /* hooks were removed from signal */
SignalHook *hooks; SignalHook *hooks;
@ -51,6 +52,7 @@ void *signal_user_data;
static GHashTable *signals; static GHashTable *signals;
static Signal *current_emitted_signal; static Signal *current_emitted_signal;
static SignalHook *current_emitted_hook;
#define signal_ref(signal) ++(signal)->refcount #define signal_ref(signal) ++(signal)->refcount
#define signal_unref(signal) (signal_unref_full(signal, TRUE)) #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]; const void *arglist[SIGNAL_MAX_ARGUMENTS];
Signal *prev_emitted_signal; Signal *prev_emitted_signal;
SignalHook *hook; SignalHook *hook, *prev_emitted_hook;
int i, stopped, stop_emit_count; int i, stopped, stop_emit_count, continue_emit_count;
for (i = 0; i < SIGNAL_MAX_ARGUMENTS; i++) for (i = 0; i < SIGNAL_MAX_ARGUMENTS; i++)
arglist[i] = i >= params ? NULL : va_arg(va, const void *); 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", ...); /* signal_stop_by_name("signal"); signal_emit("signal", ...);
fails if we compare rec->stop_emit against 0. */ fails if we compare rec->stop_emit against 0. */
stop_emit_count = rec->stop_emit; stop_emit_count = rec->stop_emit;
continue_emit_count = rec->continue_emit;
signal_ref(rec); signal_ref(rec);
stopped = FALSE; stopped = FALSE;
rec->emitting++; 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) if (hook->func == NULL)
continue; /* removed */ continue; /* removed */
prev_emitted_signal = current_emitted_signal; current_emitted_hook = hook;
current_emitted_signal = rec;
#if SIGNAL_MAX_ARGUMENTS != 6 #if SIGNAL_MAX_ARGUMENTS != 6
# error SIGNAL_MAX_ARGUMENTS changed - update code # error SIGNAL_MAX_ARGUMENTS changed - update code
#endif #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], hook->func(arglist[0], arglist[1], arglist[2], arglist[3],
arglist[4], arglist[5]); 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) { if (rec->stop_emit != stop_emit_count) {
stopped = TRUE; stopped = TRUE;
@ -248,14 +256,16 @@ static int signal_emit_real(Signal *rec, int params, va_list va)
break; break;
} }
} }
current_emitted_signal = prev_emitted_signal;
current_emitted_hook = prev_emitted_hook;
rec->emitting--; rec->emitting--;
signal_user_data = NULL; signal_user_data = NULL;
if (!rec->emitting) { if (!rec->emitting) {
if (rec->stop_emit != 0) { g_assert(rec->stop_emit == 0);
/* signal_stop() used too many times */ g_assert(rec->continue_emit == 0);
rec->stop_emit = 0;
}
if (rec->remove_count > 0) if (rec->remove_count > 0)
signal_hooks_clean(rec); 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)); rec = g_hash_table_lookup(signals, GINT_TO_POINTER(signal_id));
if (rec != NULL) { if (rec != NULL) {
va_start(va, params); va_start(va, params);
signal_emit_real(rec, params, va); signal_emit_real(rec, params, va, rec->hooks);
va_end(va); 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)); rec = g_hash_table_lookup(signals, GINT_TO_POINTER(signal_id));
if (rec != NULL) { if (rec != NULL) {
va_start(va, params); va_start(va, params);
signal_emit_real(rec, params, va); signal_emit_real(rec, params, va, rec->hooks);
va_end(va); va_end(va);
} }
return rec != NULL; 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 */ /* stop the current ongoing signal emission */
void signal_stop(void) 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(const char *signal, int params, ...);
int signal_emit_id(int signal_id, 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 */ /* stop the current ongoing signal emission */
void signal_stop(void); void signal_stop(void);
/* stop ongoing signal emission by signal name */ /* 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]); 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 void
signal_add(...) signal_add(...)
CODE: CODE: