/* Generated by GOB (v2.0.15)   (do not edit directly) */

/* End world hunger, donate to the World Food Programme, http://www.wfp.org */

#define GOB_VERSION_MAJOR 2
#define GOB_VERSION_MINOR 0
#define GOB_VERSION_PATCHLEVEL 15

#define selfp (self->_priv)

#include <string.h> /* memset() */

#include "mn-popups.h"

#include "mn-popups-private.h"

#ifdef G_LIKELY
#define ___GOB_LIKELY(expr) G_LIKELY(expr)
#define ___GOB_UNLIKELY(expr) G_UNLIKELY(expr)
#else /* ! G_LIKELY */
#define ___GOB_LIKELY(expr) (expr)
#define ___GOB_UNLIKELY(expr) (expr)
#endif /* G_LIKELY */

#line 20 "src/mn-popups.gob"

#include <libnotify/notify.h>
#include "mn-message.h"
#include "mn-shell.h"
#include "mn-util.h"
#include "mn-conf.h"
#include "mn-locked-callback.h"
#include "mn-popup.h"
#include "mn-properties-dialog.h"

#line 37 "mn-popups.c"
/* self casting macros */
#define SELF(x) MN_POPUPS(x)
#define SELF_CONST(x) MN_POPUPS_CONST(x)
#define IS_SELF(x) MN_IS_POPUPS(x)
#define TYPE_SELF MN_TYPE_POPUPS
#define SELF_CLASS(x) MN_POPUPS_CLASS(x)

#define SELF_GET_CLASS(x) MN_POPUPS_GET_CLASS(x)

/* self typedefs */
typedef MNPopups Self;
typedef MNPopupsClass SelfClass;

/* here are local prototypes */
#line 0 "src/mn-popups.gob"
static void mn_popups_class_init (MNPopupsClass * c);
#line 54 "mn-popups.c"
#line 40 "src/mn-popups.gob"
static void mn_popups_init (MNPopups * self);
#line 57 "mn-popups.c"
#line 52 "src/mn-popups.gob"
static void mn_popups_close_cb (const char * id, MNPopup * popup, gpointer user_data);
#line 60 "mn-popups.c"
#line 59 "src/mn-popups.gob"
static void mn_popups_close_popups (MNPopups * self);
#line 63 "mn-popups.c"
#line 65 "src/mn-popups.gob"
static void mn_popups_finalize (MNPopups * self);
#line 66 "mn-popups.c"
#line 71 "src/mn-popups.gob"
static void mn_popups_messages_changed_h (MNMailboxes * mailboxes, gboolean has_new, gpointer user_data);
#line 69 "mn-popups.c"
#line 81 "src/mn-popups.gob"
static void mn_popups_notify_cb (GConfClient * client, unsigned int cnxn_id, GConfEntry * entry, gpointer user_data);
#line 72 "mn-popups.c"
#line 92 "src/mn-popups.gob"
static int mn_popups_popups_show_timestamp_compare_cb (MNPopup * a, MNPopup * b);
#line 75 "mn-popups.c"
#line 104 "src/mn-popups.gob"
static void mn_popups_get_visible_popups_cb (const char * id, MNPopup * popup, GSList ** list);
#line 78 "mn-popups.c"
#line 112 "src/mn-popups.gob"
static GSList * mn_popups_get_visible_popups (MNPopups * self);
#line 81 "mn-popups.c"
#line 122 "src/mn-popups.gob"
static gboolean mn_popups_close_and_remove_stale_cb (const char * id, MNPopup * popup, GHashTable * messages);
#line 84 "mn-popups.c"
#line 136 "src/mn-popups.gob"
static gboolean mn_popups_close_and_remove_visible_cb (const char * id, MNPopup * popup, gpointer user_data);
#line 87 "mn-popups.c"
#line 149 "src/mn-popups.gob"
static void mn_popups_update (MNPopups * self, gboolean reshow_current_popups);
#line 90 "mn-popups.c"

/* pointer to the class of our parent */
static GObjectClass *parent_class = NULL;

/* Short form macros */
#define self_close_cb mn_popups_close_cb
#define self_close_popups mn_popups_close_popups
#define self_messages_changed_h mn_popups_messages_changed_h
#define self_notify_cb mn_popups_notify_cb
#define self_popups_show_timestamp_compare_cb mn_popups_popups_show_timestamp_compare_cb
#define self_get_visible_popups_cb mn_popups_get_visible_popups_cb
#define self_get_visible_popups mn_popups_get_visible_popups
#define self_close_and_remove_stale_cb mn_popups_close_and_remove_stale_cb
#define self_close_and_remove_visible_cb mn_popups_close_and_remove_visible_cb
#define self_update mn_popups_update
#define self_new mn_popups_new
GType
mn_popups_get_type (void)
{
	static GType type = 0;

	if ___GOB_UNLIKELY(type == 0) {
		static const GTypeInfo info = {
			sizeof (MNPopupsClass),
			(GBaseInitFunc) NULL,
			(GBaseFinalizeFunc) NULL,
			(GClassInitFunc) mn_popups_class_init,
			(GClassFinalizeFunc) NULL,
			NULL /* class_data */,
			sizeof (MNPopups),
			0 /* n_preallocs */,
			(GInstanceInitFunc) mn_popups_init,
			NULL
		};

		type = g_type_register_static (G_TYPE_OBJECT, "MNPopups", &info, (GTypeFlags)0);
	}

	return type;
}

/* a macro for creating a new object of our type */
#define GET_NEW ((MNPopups *)g_object_new(mn_popups_get_type(), NULL))

/* a function for creating a new object of our type */
#include <stdarg.h>
static MNPopups * GET_NEW_VARG (const char *first, ...) G_GNUC_UNUSED;
static MNPopups *
GET_NEW_VARG (const char *first, ...)
{
	MNPopups *ret;
	va_list ap;
	va_start (ap, first);
	ret = (MNPopups *)g_object_new_valist (mn_popups_get_type (), first, ap);
	va_end (ap);
	return ret;
}


static void
___finalize(GObject *obj_self)
{
#define __GOB_FUNCTION__ "MN:Popups::finalize"
	MNPopups *self G_GNUC_UNUSED = MN_POPUPS (obj_self);
	gpointer priv G_GNUC_UNUSED = self->_priv;
#line 65 "src/mn-popups.gob"
	mn_popups_finalize (self);
#line 158 "mn-popups.c"
	if(G_OBJECT_CLASS(parent_class)->finalize) \
		(* G_OBJECT_CLASS(parent_class)->finalize)(obj_self);
#line 38 "src/mn-popups.gob"
	if(self->_priv->popups) { g_hash_table_destroy ((gpointer) self->_priv->popups); self->_priv->popups = NULL; }
#line 163 "mn-popups.c"
}
#undef __GOB_FUNCTION__

static void 
mn_popups_class_init (MNPopupsClass * c G_GNUC_UNUSED)
{
#define __GOB_FUNCTION__ "MN:Popups::class_init"
	GObjectClass *g_object_class G_GNUC_UNUSED = (GObjectClass*) c;

	g_type_class_add_private(c,sizeof(MNPopupsPrivate));

	parent_class = g_type_class_ref (G_TYPE_OBJECT);

	g_object_class->finalize = ___finalize;
}
#undef __GOB_FUNCTION__
#line 40 "src/mn-popups.gob"
static void 
mn_popups_init (MNPopups * self G_GNUC_UNUSED)
{
#line 184 "mn-popups.c"
#define __GOB_FUNCTION__ "MN:Popups::init"
	self->_priv = G_TYPE_INSTANCE_GET_PRIVATE(self,MN_TYPE_POPUPS,MNPopupsPrivate);
#line 38 "src/mn-popups.gob"
	self->_priv->popups = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify) mn_g_object_null_unref);
#line 189 "mn-popups.c"
 {
#line 41 "src/mn-popups.gob"

    if (! notify_is_initted())
      return;			/* libnotify init failed */

    mn_g_object_gconf_notifications_add_gdk_locked(self,
						   MN_CONF_POPUPS_NAMESPACE, self_notify_cb, self,
						   NULL);

    g_signal_connect(mn_shell->mailboxes, "messages-changed", G_CALLBACK(self_messages_changed_h), self);
  
#line 202 "mn-popups.c"
 }
}
#undef __GOB_FUNCTION__



#line 52 "src/mn-popups.gob"
static void 
mn_popups_close_cb (const char * id, MNPopup * popup, gpointer user_data)
{
#line 213 "mn-popups.c"
#define __GOB_FUNCTION__ "MN:Popups::close_cb"
{
#line 54 "src/mn-popups.gob"
	
    if (popup)
      mn_popup_close(popup);
  }}
#line 221 "mn-popups.c"
#undef __GOB_FUNCTION__

#line 59 "src/mn-popups.gob"
static void 
mn_popups_close_popups (MNPopups * self)
{
#line 228 "mn-popups.c"
#define __GOB_FUNCTION__ "MN:Popups::close_popups"
#line 59 "src/mn-popups.gob"
	g_return_if_fail (self != NULL);
#line 59 "src/mn-popups.gob"
	g_return_if_fail (MN_IS_POPUPS (self));
#line 234 "mn-popups.c"
{
#line 61 "src/mn-popups.gob"
	
    g_hash_table_foreach(selfp->popups, (GHFunc) self_close_cb, NULL);
  }}
#line 240 "mn-popups.c"
#undef __GOB_FUNCTION__

#line 65 "src/mn-popups.gob"
static void 
mn_popups_finalize (MNPopups * self)
{
#line 247 "mn-popups.c"
#define __GOB_FUNCTION__ "MN:Popups::finalize"
{
#line 66 "src/mn-popups.gob"
	
    /* close popups on exit */
    self_close_popups(self);
  }}
#line 255 "mn-popups.c"
#undef __GOB_FUNCTION__

#line 71 "src/mn-popups.gob"
static void 
mn_popups_messages_changed_h (MNMailboxes * mailboxes, gboolean has_new, gpointer user_data)
{
#line 262 "mn-popups.c"
#define __GOB_FUNCTION__ "MN:Popups::messages_changed_h"
{
#line 75 "src/mn-popups.gob"
	
    Self *self = user_data;

    self_update(self, FALSE);
  }}
#line 271 "mn-popups.c"
#undef __GOB_FUNCTION__

#line 81 "src/mn-popups.gob"
static void 
mn_popups_notify_cb (GConfClient * client, unsigned int cnxn_id, GConfEntry * entry, gpointer user_data)
{
#line 278 "mn-popups.c"
#define __GOB_FUNCTION__ "MN:Popups::notify_cb"
{
#line 86 "src/mn-popups.gob"
	
    Self *self = user_data;

    self_update(self, TRUE);
  }}
#line 287 "mn-popups.c"
#undef __GOB_FUNCTION__

#line 92 "src/mn-popups.gob"
static int 
mn_popups_popups_show_timestamp_compare_cb (MNPopup * a, MNPopup * b)
{
#line 294 "mn-popups.c"
#define __GOB_FUNCTION__ "MN:Popups::popups_show_timestamp_compare_cb"
{
#line 94 "src/mn-popups.gob"
	
    int cmp;

    cmp = a->show_timestamp.tv_sec - b->show_timestamp.tv_sec;
    if (cmp != 0)
      return cmp;

    return a->show_timestamp.tv_usec - b->show_timestamp.tv_usec;
  }}
#line 307 "mn-popups.c"
#undef __GOB_FUNCTION__

#line 104 "src/mn-popups.gob"
static void 
mn_popups_get_visible_popups_cb (const char * id, MNPopup * popup, GSList ** list)
{
#line 314 "mn-popups.c"
#define __GOB_FUNCTION__ "MN:Popups::get_visible_popups_cb"
{
#line 106 "src/mn-popups.gob"
	
    if (popup && popup->visible)
      *list = g_slist_insert_sorted(*list, popup, (GCompareFunc) self_popups_show_timestamp_compare_cb);
  }}
#line 322 "mn-popups.c"
#undef __GOB_FUNCTION__

#line 112 "src/mn-popups.gob"
static GSList * 
mn_popups_get_visible_popups (MNPopups * self)
{
#line 329 "mn-popups.c"
#define __GOB_FUNCTION__ "MN:Popups::get_visible_popups"
#line 112 "src/mn-popups.gob"
	g_return_val_if_fail (self != NULL, (GSList * )0);
#line 112 "src/mn-popups.gob"
	g_return_val_if_fail (MN_IS_POPUPS (self), (GSList * )0);
#line 335 "mn-popups.c"
{
#line 114 "src/mn-popups.gob"
	
    GSList *popups = NULL;

    g_hash_table_foreach(selfp->popups, (GHFunc) self_get_visible_popups_cb, &popups);

    return popups;
  }}
#line 345 "mn-popups.c"
#undef __GOB_FUNCTION__

#line 122 "src/mn-popups.gob"
static gboolean 
mn_popups_close_and_remove_stale_cb (const char * id, MNPopup * popup, GHashTable * messages)
{
#line 352 "mn-popups.c"
#define __GOB_FUNCTION__ "MN:Popups::close_and_remove_stale_cb"
{
#line 124 "src/mn-popups.gob"
	
    if (! g_hash_table_lookup(mn_shell->mailboxes->messages_hash_table, id))
      {
	if (popup)
	  mn_popup_close(popup);

	return TRUE;		/* remove */
      }
    else
      return FALSE;		/* keep */
  }}
#line 367 "mn-popups.c"
#undef __GOB_FUNCTION__

#line 136 "src/mn-popups.gob"
static gboolean 
mn_popups_close_and_remove_visible_cb (const char * id, MNPopup * popup, gpointer user_data)
{
#line 374 "mn-popups.c"
#define __GOB_FUNCTION__ "MN:Popups::close_and_remove_visible_cb"
{
#line 138 "src/mn-popups.gob"
	
    if (popup && popup->visible)
      {
	mn_popup_close(popup);

	return TRUE;		/* remove */
      }
    else
      return FALSE;		/* keep */
  }}
#line 388 "mn-popups.c"
#undef __GOB_FUNCTION__

#line 149 "src/mn-popups.gob"
static void 
mn_popups_update (MNPopups * self, gboolean reshow_current_popups)
{
#line 395 "mn-popups.c"
#define __GOB_FUNCTION__ "MN:Popups::update"
#line 149 "src/mn-popups.gob"
	g_return_if_fail (self != NULL);
#line 149 "src/mn-popups.gob"
	g_return_if_fail (MN_IS_POPUPS (self));
#line 401 "mn-popups.c"
{
#line 151 "src/mn-popups.gob"
	
    int i;

    /* close and remove stale popups */
    g_hash_table_foreach_remove(selfp->popups, (GHRFunc) self_close_and_remove_stale_cb, NULL);

    if (reshow_current_popups)
      /*
       * We have to reshow the currently visible popups, so close and
       * remove them.
       */
      g_hash_table_foreach_remove(selfp->popups, (GHRFunc) self_close_and_remove_visible_cb, NULL);

    if (mn_conf_get_bool(MN_CONF_POPUPS_ENABLED))
      {
	GPtrArray *messages;	/* for O(1) length retrieval and indexing */
	GSList *visible_popups;
	int num_visible_popups;
	int popup_limit;
	int new_popup_count;
	int messages_to_popup;	/* the number of messages to popup */

	if (mn_conf_get_enum_value(MN_TYPE_POPUP_POSITION, MN_CONF_POPUPS_POSITION) == MN_POPUP_POSITION_ATTACHED)
	  /* the popup is attached to the icon: allow at most one popup */
	  popup_limit = 1;
	else
	  popup_limit = mn_conf_get_int(MN_CONF_POPUPS_LIMIT);

	/* build a list of messages which are not already known */

	messages = g_ptr_array_new();

	MN_ARRAY_FOREACH(i, mn_shell->mailboxes->messages)
	  {
	    MNMessage *message = g_ptr_array_index(mn_shell->mailboxes->messages, i);
	    gpointer ptr;

	    if (! g_hash_table_lookup_extended(selfp->popups, message->id, NULL, &ptr))
	      g_ptr_array_add(messages, message);
	  }

	visible_popups = self_get_visible_popups(self);
	num_visible_popups = g_slist_length(visible_popups);

	new_popup_count = num_visible_popups + messages->len;
	if (new_popup_count > popup_limit)
	  {
	    int to_remove;

	    /* make room for n new popups by closing the n oldest popups */

	    to_remove = new_popup_count - popup_limit;
	    to_remove = MIN(num_visible_popups, to_remove);

	    while (to_remove > 0)
	      {
		MNPopup *oldest;

		g_assert(visible_popups != NULL);

		oldest = visible_popups->data;
		mn_popup_close(oldest);

		visible_popups = g_slist_delete_link(visible_popups, visible_popups);
		to_remove--;
	      }
	  }

	g_slist_free(visible_popups);

	messages_to_popup = MIN(messages->len, popup_limit);

	/*
	 * Below we iterate over the messages array backwards because
	 * it is sorted by sent time most recent first, while we want
	 * to popup the oldest messages first.
	 */

	/* register the messages which we will not popup */

	for (i = messages->len - 1; i >= messages_to_popup; i--)
	  {
	    MNMessage *message = g_ptr_array_index(messages, i);

	    g_hash_table_replace(selfp->popups, g_strdup(message->id), NULL);
	  }

	/* popup the first messages_to_popup messages */

	for (i = messages_to_popup - 1; i >= 0; i--)
	  {
	    MNMessage *message = g_ptr_array_index(messages, i);
	    MNPopup *popup;

	    popup = mn_popup_new(message);
	    mn_popup_show(popup);

	    g_hash_table_replace(selfp->popups, g_strdup(message->id), popup);
	  }

	g_ptr_array_free(messages, TRUE);
      }
    else
      {
	/* register the new messages */

	MN_ARRAY_FOREACH(i, mn_shell->mailboxes->messages)
	  {
	    MNMessage *message = g_ptr_array_index(mn_shell->mailboxes->messages, i);
	    g_hash_table_replace(selfp->popups, g_strdup(message->id), NULL);
	  }
      }
  }}
#line 517 "mn-popups.c"
#undef __GOB_FUNCTION__

#line 265 "src/mn-popups.gob"
MNPopups * 
mn_popups_new (void)
{
#line 524 "mn-popups.c"
#define __GOB_FUNCTION__ "MN:Popups::new"
{
#line 267 "src/mn-popups.gob"
	
    return GET_NEW;
  }}
#line 531 "mn-popups.c"
#undef __GOB_FUNCTION__
