Personal copy of mcabber
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

222 lines
5.7 KiB

/*
* events.c -- Events fonctions
*
* Copyright (C) 2006-2010 Mikael Berthe <mikael@lilotux.net>
* Copyright (C) 2010 Myhailo Danylenko <isbear@ukrpost.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <glib.h>
#include <string.h>
#include "events.h"
#include "screen.h"
typedef struct {
char *id;
char *description;
time_t timeout;
guint source;
evs_callback_t callback;
gpointer data;
GDestroyNotify notify;
} evs_t;
static GSList *evs_list; // Events list
static evs_t *evs_find(const char *evid);
static gboolean evs_check_timeout (gpointer userdata)
{
evs_t *event = userdata;
if (event->callback &&
!event->callback(EVS_CONTEXT_TIMEOUT, NULL, event->data)) {
evs_del(event->id);
return FALSE;
}
return TRUE; // XXX
}
// evs_new(type, timeout)
// Create new event. If id is omitted, generates unique
// numerical id (recommended). If timeout is specified, sets
// up timeout source, that will call handler in timeout
// context after specified number of seconds. If supplied id
// already exists, returns NULL, calling destroy notifier, if
// one is specified.
const char *evs_new(const char *desc, const char *id, time_t timeout, evs_callback_t callback, gpointer udata, GDestroyNotify notify)
{
static guint evs_idn;
evs_t *event;
char *stridn;
if (!id) {
if (!++evs_idn)
evs_idn = 1;
/* Check for wrapping, we shouldn't reuse ids */
stridn = g_strdup_printf("%d", evs_idn);
if (evs_find(stridn)) {
g_free(stridn);
// We could try another id but for now giving up should be fine...
if (notify)
notify(udata);
return NULL;
}
} else if (!evs_find(id))
stridn = g_strdup(id);
else {
if (notify)
notify(udata);
return NULL;
}
event = g_new(evs_t, 1);
event->id = stridn;
event->description = g_strdup(desc);
event->timeout = timeout;
event->callback = callback;
event->data = udata;
event->notify = notify;
if (timeout)
event->source = g_timeout_add_seconds(timeout, evs_check_timeout, event);
else
event->source = 0;
evs_list = g_slist_append(evs_list, event);
return stridn;
}
static evs_t *evs_find(const char *evid)
{
GSList *p;
if (!evid)
return NULL;
for (p = evs_list; p; p = g_slist_next(p)) {
evs_t *i = p->data;
if (!strcmp(evid, i->id))
return i;
}
return NULL;
}
// evs_del(evid)
// Deletes event.
// This will not call event handler, however this will
// call destroy notify function.
// Returns 0 in case of success, -1 if the evid hasn't been found.
int evs_del(const char *evid)
{
evs_t *event = evs_find(evid);
if (!event)
return -1;
if (event->notify)
event->notify(event->data);
if (event->source)
g_source_remove(event->source);
evs_list = g_slist_remove(evs_list, event);
g_free(event->id);
g_free(event->description);
g_free(event);
return 0; // Ok, deleted
}
// evs_callback(evid, evcontext, argument)
// Callback processing for the specified event.
// If event handler will return FALSE, event will be destroyed.
// Return 0 in case of success, -1 if the evid hasn't been found.
// evcontext and argument are transparently passed to event handler.
int evs_callback(const char *evid, guint context, const char *arg)
{
evs_t *event;
event = evs_find(evid);
if (!event)
return -1;
if (event->callback &&
!event->callback(context, arg, event->data))
evs_del(evid);
return 0;
}
// evs_display_list()
// Prints list of events to mcabber log window.
void evs_display_list(void)
{
guint count = 0;
GSList *p;
scr_LogPrint(LPRINT_NORMAL, "Events list:");
for (p = evs_list; p; p = g_slist_next(p)) {
evs_t *i = p->data;
scr_LogPrint(LPRINT_NORMAL,
"Id: %-3s %s", i->id,
(i->description ? i->description : ""));
count++;
}
scr_LogPrint(LPRINT_NORMAL, "End of events list.");
if (count+2 > scr_getlogwinheight()) {
scr_setmsgflag_if_needed(SPECIAL_BUFFER_STATUS_ID, TRUE);
scr_setattentionflag_if_needed(SPECIAL_BUFFER_STATUS_ID, TRUE,
ROSTER_UI_PRIO_STATUS_WIN_MESSAGE, prio_max);
}
}
// evs_geteventslist()
// Return a singly-linked-list of events ids.
// Data in list should not be modified and can disappear,
// you must strdup them, if you want them to persist.
// Note: the caller should free the list after use.
GSList *evs_geteventslist(void)
{
GSList *evidlist = NULL, *p;
for (p = evs_list; p; p = g_slist_next(p)) {
evs_t *i = p->data;
evidlist = g_slist_append(evidlist, i->id);
}
return evidlist;
}
// evs_deinit()
// Frees all events.
void evs_deinit(void)
{
GSList *eel;
for (eel = evs_list; eel; eel = eel->next) {
evs_t *event = eel->data;
if (event->notify)
event->notify(event->data);
if (event->source)
g_source_remove(event->source);
evs_list = g_slist_remove(evs_list, event);
g_free(event->id);
g_free(event->description);
g_free(event);
}
g_slist_free(evs_list);
evs_list = NULL;
}
/* vim: set expandtab cindent cinoptions=>2\:2(0 sw=2 ts=2: For Vim users... */