/* mentions.c generated by valac 0.56.19, the Vala compiler
 * generated from mentions.vala, do not modify */

#include <glib-object.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <gobject/gvaluecollector.h>

#define DC_MENTIONS_DEFAULT_ACCENT "#3584e4"
#define DC_MENTIONS_SENTINEL "\xEF\xBF\xBC"
#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif
#if !defined(VALA_EXTERN)
#if defined(_MSC_VER)
#define VALA_EXTERN __declspec(dllexport) extern
#elif __GNUC__ >= 4
#define VALA_EXTERN __attribute__((visibility("default"))) extern
#else
#define VALA_EXTERN extern
#endif
#endif

#define DC_TYPE_MENTION_MEMBER (dc_mention_member_get_type ())
#define DC_MENTION_MEMBER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DC_TYPE_MENTION_MEMBER, DcMentionMember))
#define DC_MENTION_MEMBER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DC_TYPE_MENTION_MEMBER, DcMentionMemberClass))
#define DC_IS_MENTION_MEMBER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DC_TYPE_MENTION_MEMBER))
#define DC_IS_MENTION_MEMBER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DC_TYPE_MENTION_MEMBER))
#define DC_MENTION_MEMBER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DC_TYPE_MENTION_MEMBER, DcMentionMemberClass))

typedef struct _DcMentionMember DcMentionMember;
typedef struct _DcMentionMemberClass DcMentionMemberClass;
typedef struct _DcMentionMemberPrivate DcMentionMemberPrivate;
enum  {
	DC_MENTION_MEMBER_0_PROPERTY,
	DC_MENTION_MEMBER_DISPLAY_NAME_PROPERTY,
	DC_MENTION_MEMBER_ADDRESS_PROPERTY,
	DC_MENTION_MEMBER_CONTACT_ID_PROPERTY,
	DC_MENTION_MEMBER_IS_SELF_PROPERTY,
	DC_MENTION_MEMBER_AVATAR_PATH_PROPERTY,
	DC_MENTION_MEMBER_NUM_PROPERTIES
};
static GParamSpec* dc_mention_member_properties[DC_MENTION_MEMBER_NUM_PROPERTIES];
#define _g_free0(var) (var = (g_free (var), NULL))

#define DC_TYPE_MENTION_SPAN (dc_mention_span_get_type ())
#define DC_MENTION_SPAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DC_TYPE_MENTION_SPAN, DcMentionSpan))
#define DC_MENTION_SPAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DC_TYPE_MENTION_SPAN, DcMentionSpanClass))
#define DC_IS_MENTION_SPAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DC_TYPE_MENTION_SPAN))
#define DC_IS_MENTION_SPAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DC_TYPE_MENTION_SPAN))
#define DC_MENTION_SPAN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DC_TYPE_MENTION_SPAN, DcMentionSpanClass))

typedef struct _DcMentionSpan DcMentionSpan;
typedef struct _DcMentionSpanClass DcMentionSpanClass;
typedef struct _DcMentionSpanPrivate DcMentionSpanPrivate;
enum  {
	DC_MENTION_SPAN_0_PROPERTY,
	DC_MENTION_SPAN_NUM_PROPERTIES
};
static GParamSpec* dc_mention_span_properties[DC_MENTION_SPAN_NUM_PROPERTIES];

#define DC_TYPE_MENTION_ROSTER (dc_mention_roster_get_type ())
#define DC_MENTION_ROSTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DC_TYPE_MENTION_ROSTER, DcMentionRoster))
#define DC_MENTION_ROSTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DC_TYPE_MENTION_ROSTER, DcMentionRosterClass))
#define DC_IS_MENTION_ROSTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DC_TYPE_MENTION_ROSTER))
#define DC_IS_MENTION_ROSTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DC_TYPE_MENTION_ROSTER))
#define DC_MENTION_ROSTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DC_TYPE_MENTION_ROSTER, DcMentionRosterClass))

typedef struct _DcMentionRoster DcMentionRoster;
typedef struct _DcMentionRosterClass DcMentionRosterClass;
typedef struct _DcMentionRosterPrivate DcMentionRosterPrivate;
enum  {
	DC_MENTION_ROSTER_0_PROPERTY,
	DC_MENTION_ROSTER_NUM_PROPERTIES
};
static GParamSpec* dc_mention_roster_properties[DC_MENTION_ROSTER_NUM_PROPERTIES];
#define _g_ptr_array_unref0(var) ((var == NULL) ? NULL : (var = (g_ptr_array_unref (var), NULL)))
#define _g_hash_table_unref0(var) ((var == NULL) ? NULL : (var = (g_hash_table_unref (var), NULL)))
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
typedef struct _Block21Data Block21Data;

#define DC_TYPE_MENTIONS (dc_mentions_get_type ())
#define DC_MENTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DC_TYPE_MENTIONS, DcMentions))
#define DC_MENTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DC_TYPE_MENTIONS, DcMentionsClass))
#define DC_IS_MENTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DC_TYPE_MENTIONS))
#define DC_IS_MENTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DC_TYPE_MENTIONS))
#define DC_MENTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DC_TYPE_MENTIONS, DcMentionsClass))

typedef struct _DcMentions DcMentions;
typedef struct _DcMentionsClass DcMentionsClass;
typedef struct _DcMentionsPrivate DcMentionsPrivate;
#define _g_regex_unref0(var) ((var == NULL) ? NULL : (var = (g_regex_unref (var), NULL)))
#define _g_string_free0(var) ((var == NULL) ? NULL : (var = (g_string_free (var, TRUE), NULL)))
typedef struct _DcParamSpecMentions DcParamSpecMentions;

struct _DcMentionMember {
	GObject parent_instance;
	DcMentionMemberPrivate * priv;
};

struct _DcMentionMemberClass {
	GObjectClass parent_class;
};

struct _DcMentionMemberPrivate {
	gchar* _display_name;
	gchar* _address;
	gint _contact_id;
	gboolean _is_self;
	gchar* _avatar_path;
};

struct _DcMentionSpan {
	GObject parent_instance;
	DcMentionSpanPrivate * priv;
	gint start;
	gint end;
	gchar* href;
	gboolean is_self;
	gchar* display;
};

struct _DcMentionSpanClass {
	GObjectClass parent_class;
};

struct _DcMentionRoster {
	GObject parent_instance;
	DcMentionRosterPrivate * priv;
	GPtrArray* members;
};

struct _DcMentionRosterClass {
	GObjectClass parent_class;
};

struct _DcMentionRosterPrivate {
	GHashTable* by_address;
	GPtrArray* name_sorted;
	GPtrArray* self_keys;
	DcMentionMember* self_member;
};

struct _Block21Data {
	int _ref_count_;
	GPtrArray* self;
	GCompareFunc compare_func;
};

struct _DcMentions {
	GTypeInstance parent_instance;
	volatile int ref_count;
	DcMentionsPrivate * priv;
};

struct _DcMentionsClass {
	GTypeClass parent_class;
	void (*finalize) (DcMentions *self);
};

struct _DcParamSpecMentions {
	GParamSpec parent_instance;
};

static gint DcMentionMember_private_offset;
static gpointer dc_mention_member_parent_class = NULL;
static gpointer dc_mention_span_parent_class = NULL;
static gint DcMentionRoster_private_offset;
static gpointer dc_mention_roster_parent_class = NULL;
static gpointer dc_mentions_parent_class = NULL;
static gchar* dc_mentions_accent_override;
static gchar* dc_mentions_accent_override = NULL;

VALA_EXTERN GType dc_mention_member_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (DcMentionMember, g_object_unref)
VALA_EXTERN DcMentionMember* dc_mention_member_new (gint contact_id,
                                        const gchar* display_name,
                                        const gchar* address,
                                        gboolean is_self,
                                        const gchar* avatar_path);
VALA_EXTERN DcMentionMember* dc_mention_member_construct (GType object_type,
                                              gint contact_id,
                                              const gchar* display_name,
                                              const gchar* address,
                                              gboolean is_self,
                                              const gchar* avatar_path);
VALA_EXTERN void dc_mention_member_set_contact_id (DcMentionMember* self,
                                       gint value);
VALA_EXTERN void dc_mention_member_set_display_name (DcMentionMember* self,
                                         const gchar* value);
VALA_EXTERN void dc_mention_member_set_address (DcMentionMember* self,
                                    const gchar* value);
VALA_EXTERN void dc_mention_member_set_is_self (DcMentionMember* self,
                                    gboolean value);
VALA_EXTERN void dc_mention_member_set_avatar_path (DcMentionMember* self,
                                        const gchar* value);
VALA_EXTERN const gchar* dc_mention_member_get_display_name (DcMentionMember* self);
VALA_EXTERN const gchar* dc_mention_member_get_address (DcMentionMember* self);
VALA_EXTERN gint dc_mention_member_get_contact_id (DcMentionMember* self);
VALA_EXTERN gboolean dc_mention_member_get_is_self (DcMentionMember* self);
VALA_EXTERN const gchar* dc_mention_member_get_avatar_path (DcMentionMember* self);
static void dc_mention_member_finalize (GObject * obj);
static GType dc_mention_member_get_type_once (void);
static void _vala_dc_mention_member_get_property (GObject * object,
                                           guint property_id,
                                           GValue * value,
                                           GParamSpec * pspec);
static void _vala_dc_mention_member_set_property (GObject * object,
                                           guint property_id,
                                           const GValue * value,
                                           GParamSpec * pspec);
VALA_EXTERN GType dc_mention_span_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (DcMentionSpan, g_object_unref)
VALA_EXTERN DcMentionSpan* dc_mention_span_new (void);
VALA_EXTERN DcMentionSpan* dc_mention_span_construct (GType object_type);
static void dc_mention_span_finalize (GObject * obj);
static GType dc_mention_span_get_type_once (void);
VALA_EXTERN GType dc_mention_roster_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (DcMentionRoster, g_object_unref)
static void _g_object_unref0_ (gpointer var);
static void _g_free0_ (gpointer var);
VALA_EXTERN void dc_mention_roster_add_member (DcMentionRoster* self,
                                   DcMentionMember* m);
VALA_EXTERN void dc_mention_roster_register_address (DcMentionRoster* self,
                                         DcMentionMember* m);
VALA_EXTERN void dc_mention_roster_add_self_key (DcMentionRoster* self,
                                     const gchar* key);
VALA_EXTERN gboolean dc_mention_roster_has_members (DcMentionRoster* self);
VALA_EXTERN DcMentionMember* dc_mention_roster_lookup_contact (DcMentionRoster* self,
                                                   gint contact_id);
static gboolean dc_mention_roster_key_is_self (DcMentionRoster* self,
                                        const gchar* down_value);
static GPtrArray* dc_mention_roster_names_longest_first (DcMentionRoster* self);
static Block21Data* block21_data_ref (Block21Data* _data21_);
static void block21_data_unref (void * _userdata_);
static gint ___lambda0__gcompare_data_func (gconstpointer a,
                                     gconstpointer b,
                                     gpointer self);
static gint __lambda7_ (DcMentionMember* a,
                 DcMentionMember* b);
static gint ___lambda7__gcompare_func (gconstpointer a,
                                gconstpointer b);
VALA_EXTERN DcMentionSpan* dc_mention_roster_resolve_at (DcMentionRoster* self,
                                             const gchar* raw,
                                             gint at);
static DcMentionSpan* dc_mention_roster_resolve_address (DcMentionRoster* self,
                                                  const gchar* raw,
                                                  gint at,
                                                  const gchar* rest);
static DcMentionSpan* dc_mention_roster_resolve_name (DcMentionRoster* self,
                                               const gchar* raw,
                                               gint at,
                                               const gchar* rest);
static DcMentionSpan* dc_mention_roster_resolve_self_name (DcMentionRoster* self,
                                                    const gchar* raw,
                                                    gint at,
                                                    const gchar* rest);
static gchar* dc_mention_roster_self_display (DcMentionRoster* self,
                                       const gchar* fallback);
static gchar* dc_mention_roster_trim_trailing_punct (const gchar* s);
VALA_EXTERN gboolean dc_mention_roster_boundary_after (const gchar* s,
                                           gint pos);
static gboolean dc_mention_roster_is_name_joiner (gunichar c);
VALA_EXTERN DcMentionRoster* dc_mention_roster_new (void);
VALA_EXTERN DcMentionRoster* dc_mention_roster_construct (GType object_type);
static void dc_mention_roster_finalize (GObject * obj);
static GType dc_mention_roster_get_type_once (void);
VALA_EXTERN gpointer dc_mentions_ref (gpointer instance);
VALA_EXTERN void dc_mentions_unref (gpointer instance);
VALA_EXTERN GParamSpec* dc_param_spec_mentions (const gchar* name,
                                    const gchar* nick,
                                    const gchar* blurb,
                                    GType object_type,
                                    GParamFlags flags);
VALA_EXTERN void dc_value_set_mentions (GValue* value,
                            gpointer v_object);
VALA_EXTERN void dc_value_take_mentions (GValue* value,
                             gpointer v_object);
VALA_EXTERN gpointer dc_value_get_mentions (const GValue* value);
VALA_EXTERN GType dc_mentions_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (DcMentions, dc_mentions_unref)
VALA_EXTERN void dc_mentions_set_accent (const gchar* hex);
static gchar* dc_mentions_accent (void);
VALA_EXTERN GPtrArray* dc_mentions_find_mentions (const gchar* raw,
                                      DcMentionRoster* roster);
VALA_EXTERN gchar* dc_mentions_render_markup (const gchar* raw,
                                  DcMentionRoster* roster);
VALA_EXTERN gchar* dc_markdown_format (const gchar* input);
static gchar* dc_mentions_anchor_markup (DcMentionSpan* span);
VALA_EXTERN gboolean dc_mentions_has_self_mention (const gchar* raw,
                                       DcMentionRoster* roster);
VALA_EXTERN gboolean dc_mentions_mentions_self (const gchar* text,
                                    gchar** self_keys,
                                    gint self_keys_length1);
static gboolean dc_mentions_matches_self_key_at (const gchar* text,
                                          gint after,
                                          gchar** self_keys,
                                          gint self_keys_length1);
static gboolean dc_mentions_is_addr_terminator (gunichar c);
VALA_EXTERN DcMentions* dc_mentions_new (void);
VALA_EXTERN DcMentions* dc_mentions_construct (GType object_type);
static void dc_mentions_finalize (DcMentions * obj);
static GType dc_mentions_get_type_once (void);
static inline gpointer _vala_memdup2 (gconstpointer mem,
                        gsize byte_size);

static inline gpointer
dc_mention_member_get_instance_private (DcMentionMember* self)
{
	return G_STRUCT_MEMBER_P (self, DcMentionMember_private_offset);
}

DcMentionMember*
dc_mention_member_construct (GType object_type,
                             gint contact_id,
                             const gchar* display_name,
                             const gchar* address,
                             gboolean is_self,
                             const gchar* avatar_path)
{
	DcMentionMember * self = NULL;
	g_return_val_if_fail (display_name != NULL, NULL);
	g_return_val_if_fail (address != NULL, NULL);
	self = (DcMentionMember*) g_object_new (object_type, NULL);
	dc_mention_member_set_contact_id (self, contact_id);
	dc_mention_member_set_display_name (self, display_name);
	dc_mention_member_set_address (self, address);
	dc_mention_member_set_is_self (self, is_self);
	dc_mention_member_set_avatar_path (self, avatar_path);
	return self;
}

DcMentionMember*
dc_mention_member_new (gint contact_id,
                       const gchar* display_name,
                       const gchar* address,
                       gboolean is_self,
                       const gchar* avatar_path)
{
	return dc_mention_member_construct (DC_TYPE_MENTION_MEMBER, contact_id, display_name, address, is_self, avatar_path);
}

const gchar*
dc_mention_member_get_display_name (DcMentionMember* self)
{
	const gchar* result;
	const gchar* _tmp0_;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->_display_name;
	result = _tmp0_;
	return result;
}

void
dc_mention_member_set_display_name (DcMentionMember* self,
                                    const gchar* value)
{
	gchar* old_value;
	g_return_if_fail (self != NULL);
	old_value = dc_mention_member_get_display_name (self);
	if (g_strcmp0 (value, old_value) != 0) {
		gchar* _tmp0_;
		_tmp0_ = g_strdup (value);
		_g_free0 (self->priv->_display_name);
		self->priv->_display_name = _tmp0_;
		g_object_notify_by_pspec ((GObject *) self, dc_mention_member_properties[DC_MENTION_MEMBER_DISPLAY_NAME_PROPERTY]);
	}
}

const gchar*
dc_mention_member_get_address (DcMentionMember* self)
{
	const gchar* result;
	const gchar* _tmp0_;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->_address;
	result = _tmp0_;
	return result;
}

void
dc_mention_member_set_address (DcMentionMember* self,
                               const gchar* value)
{
	gchar* old_value;
	g_return_if_fail (self != NULL);
	old_value = dc_mention_member_get_address (self);
	if (g_strcmp0 (value, old_value) != 0) {
		gchar* _tmp0_;
		_tmp0_ = g_strdup (value);
		_g_free0 (self->priv->_address);
		self->priv->_address = _tmp0_;
		g_object_notify_by_pspec ((GObject *) self, dc_mention_member_properties[DC_MENTION_MEMBER_ADDRESS_PROPERTY]);
	}
}

gint
dc_mention_member_get_contact_id (DcMentionMember* self)
{
	gint result;
	g_return_val_if_fail (self != NULL, -1);
	result = self->priv->_contact_id;
	return result;
}

void
dc_mention_member_set_contact_id (DcMentionMember* self,
                                  gint value)
{
	gint old_value;
	g_return_if_fail (self != NULL);
	old_value = dc_mention_member_get_contact_id (self);
	if (old_value != value) {
		self->priv->_contact_id = value;
		g_object_notify_by_pspec ((GObject *) self, dc_mention_member_properties[DC_MENTION_MEMBER_CONTACT_ID_PROPERTY]);
	}
}

gboolean
dc_mention_member_get_is_self (DcMentionMember* self)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	result = self->priv->_is_self;
	return result;
}

void
dc_mention_member_set_is_self (DcMentionMember* self,
                               gboolean value)
{
	gboolean old_value;
	g_return_if_fail (self != NULL);
	old_value = dc_mention_member_get_is_self (self);
	if (old_value != value) {
		self->priv->_is_self = value;
		g_object_notify_by_pspec ((GObject *) self, dc_mention_member_properties[DC_MENTION_MEMBER_IS_SELF_PROPERTY]);
	}
}

const gchar*
dc_mention_member_get_avatar_path (DcMentionMember* self)
{
	const gchar* result;
	const gchar* _tmp0_;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->_avatar_path;
	result = _tmp0_;
	return result;
}

void
dc_mention_member_set_avatar_path (DcMentionMember* self,
                                   const gchar* value)
{
	gchar* old_value;
	g_return_if_fail (self != NULL);
	old_value = dc_mention_member_get_avatar_path (self);
	if (g_strcmp0 (value, old_value) != 0) {
		gchar* _tmp0_;
		_tmp0_ = g_strdup (value);
		_g_free0 (self->priv->_avatar_path);
		self->priv->_avatar_path = _tmp0_;
		g_object_notify_by_pspec ((GObject *) self, dc_mention_member_properties[DC_MENTION_MEMBER_AVATAR_PATH_PROPERTY]);
	}
}

static void
dc_mention_member_class_init (DcMentionMemberClass * klass,
                              gpointer klass_data)
{
	dc_mention_member_parent_class = g_type_class_peek_parent (klass);
	g_type_class_adjust_private_offset (klass, &DcMentionMember_private_offset);
	G_OBJECT_CLASS (klass)->get_property = _vala_dc_mention_member_get_property;
	G_OBJECT_CLASS (klass)->set_property = _vala_dc_mention_member_set_property;
	G_OBJECT_CLASS (klass)->finalize = dc_mention_member_finalize;
	g_object_class_install_property (G_OBJECT_CLASS (klass), DC_MENTION_MEMBER_DISPLAY_NAME_PROPERTY, dc_mention_member_properties[DC_MENTION_MEMBER_DISPLAY_NAME_PROPERTY] = g_param_spec_string ("display-name", "display-name", "display-name", NULL, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE));
	g_object_class_install_property (G_OBJECT_CLASS (klass), DC_MENTION_MEMBER_ADDRESS_PROPERTY, dc_mention_member_properties[DC_MENTION_MEMBER_ADDRESS_PROPERTY] = g_param_spec_string ("address", "address", "address", NULL, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE));
	g_object_class_install_property (G_OBJECT_CLASS (klass), DC_MENTION_MEMBER_CONTACT_ID_PROPERTY, dc_mention_member_properties[DC_MENTION_MEMBER_CONTACT_ID_PROPERTY] = g_param_spec_int ("contact-id", "contact-id", "contact-id", G_MININT, G_MAXINT, 0, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE));
	g_object_class_install_property (G_OBJECT_CLASS (klass), DC_MENTION_MEMBER_IS_SELF_PROPERTY, dc_mention_member_properties[DC_MENTION_MEMBER_IS_SELF_PROPERTY] = g_param_spec_boolean ("is-self", "is-self", "is-self", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE));
	g_object_class_install_property (G_OBJECT_CLASS (klass), DC_MENTION_MEMBER_AVATAR_PATH_PROPERTY, dc_mention_member_properties[DC_MENTION_MEMBER_AVATAR_PATH_PROPERTY] = g_param_spec_string ("avatar-path", "avatar-path", "avatar-path", NULL, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE));
}

static void
dc_mention_member_instance_init (DcMentionMember * self,
                                 gpointer klass)
{
	gchar* _tmp0_;
	gchar* _tmp1_;
	self->priv = dc_mention_member_get_instance_private (self);
	_tmp0_ = g_strdup ("");
	self->priv->_display_name = _tmp0_;
	_tmp1_ = g_strdup ("");
	self->priv->_address = _tmp1_;
	self->priv->_contact_id = 0;
	self->priv->_is_self = FALSE;
	self->priv->_avatar_path = NULL;
}

static void
dc_mention_member_finalize (GObject * obj)
{
	DcMentionMember * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, DC_TYPE_MENTION_MEMBER, DcMentionMember);
	_g_free0 (self->priv->_display_name);
	_g_free0 (self->priv->_address);
	_g_free0 (self->priv->_avatar_path);
	G_OBJECT_CLASS (dc_mention_member_parent_class)->finalize (obj);
}

/**
     * A person that can be mentioned. Used both for the composer autocomplete
     * (members of the current chat) and for resolving mention tokens found in
     * message text (via the roster's address book).
     */
static GType
dc_mention_member_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (DcMentionMemberClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) dc_mention_member_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (DcMentionMember), 0, (GInstanceInitFunc) dc_mention_member_instance_init, NULL };
	GType dc_mention_member_type_id;
	dc_mention_member_type_id = g_type_register_static (G_TYPE_OBJECT, "DcMentionMember", &g_define_type_info, 0);
	DcMentionMember_private_offset = g_type_add_instance_private (dc_mention_member_type_id, sizeof (DcMentionMemberPrivate));
	return dc_mention_member_type_id;
}

GType
dc_mention_member_get_type (void)
{
	static volatile gsize dc_mention_member_type_id__once = 0;
	if (g_once_init_enter (&dc_mention_member_type_id__once)) {
		GType dc_mention_member_type_id;
		dc_mention_member_type_id = dc_mention_member_get_type_once ();
		g_once_init_leave (&dc_mention_member_type_id__once, dc_mention_member_type_id);
	}
	return dc_mention_member_type_id__once;
}

static void
_vala_dc_mention_member_get_property (GObject * object,
                                      guint property_id,
                                      GValue * value,
                                      GParamSpec * pspec)
{
	DcMentionMember * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, DC_TYPE_MENTION_MEMBER, DcMentionMember);
	switch (property_id) {
		case DC_MENTION_MEMBER_DISPLAY_NAME_PROPERTY:
		g_value_set_string (value, dc_mention_member_get_display_name (self));
		break;
		case DC_MENTION_MEMBER_ADDRESS_PROPERTY:
		g_value_set_string (value, dc_mention_member_get_address (self));
		break;
		case DC_MENTION_MEMBER_CONTACT_ID_PROPERTY:
		g_value_set_int (value, dc_mention_member_get_contact_id (self));
		break;
		case DC_MENTION_MEMBER_IS_SELF_PROPERTY:
		g_value_set_boolean (value, dc_mention_member_get_is_self (self));
		break;
		case DC_MENTION_MEMBER_AVATAR_PATH_PROPERTY:
		g_value_set_string (value, dc_mention_member_get_avatar_path (self));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static void
_vala_dc_mention_member_set_property (GObject * object,
                                      guint property_id,
                                      const GValue * value,
                                      GParamSpec * pspec)
{
	DcMentionMember * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, DC_TYPE_MENTION_MEMBER, DcMentionMember);
	switch (property_id) {
		case DC_MENTION_MEMBER_DISPLAY_NAME_PROPERTY:
		dc_mention_member_set_display_name (self, g_value_get_string (value));
		break;
		case DC_MENTION_MEMBER_ADDRESS_PROPERTY:
		dc_mention_member_set_address (self, g_value_get_string (value));
		break;
		case DC_MENTION_MEMBER_CONTACT_ID_PROPERTY:
		dc_mention_member_set_contact_id (self, g_value_get_int (value));
		break;
		case DC_MENTION_MEMBER_IS_SELF_PROPERTY:
		dc_mention_member_set_is_self (self, g_value_get_boolean (value));
		break;
		case DC_MENTION_MEMBER_AVATAR_PATH_PROPERTY:
		dc_mention_member_set_avatar_path (self, g_value_get_string (value));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

DcMentionSpan*
dc_mention_span_construct (GType object_type)
{
	DcMentionSpan * self = NULL;
	self = (DcMentionSpan*) g_object_new (object_type, NULL);
	return self;
}

DcMentionSpan*
dc_mention_span_new (void)
{
	return dc_mention_span_construct (DC_TYPE_MENTION_SPAN);
}

static void
dc_mention_span_class_init (DcMentionSpanClass * klass,
                            gpointer klass_data)
{
	dc_mention_span_parent_class = g_type_class_peek_parent (klass);
	G_OBJECT_CLASS (klass)->finalize = dc_mention_span_finalize;
}

static void
dc_mention_span_instance_init (DcMentionSpan * self,
                               gpointer klass)
{
}

static void
dc_mention_span_finalize (GObject * obj)
{
	DcMentionSpan * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, DC_TYPE_MENTION_SPAN, DcMentionSpan);
	_g_free0 (self->href);
	_g_free0 (self->display);
	G_OBJECT_CLASS (dc_mention_span_parent_class)->finalize (obj);
}

/**
     * A single resolved mention token located inside message text.
     * Byte offsets index into the raw (unescaped) text.
     */
static GType
dc_mention_span_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (DcMentionSpanClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) dc_mention_span_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (DcMentionSpan), 0, (GInstanceInitFunc) dc_mention_span_instance_init, NULL };
	GType dc_mention_span_type_id;
	dc_mention_span_type_id = g_type_register_static (G_TYPE_OBJECT, "DcMentionSpan", &g_define_type_info, 0);
	return dc_mention_span_type_id;
}

GType
dc_mention_span_get_type (void)
{
	static volatile gsize dc_mention_span_type_id__once = 0;
	if (g_once_init_enter (&dc_mention_span_type_id__once)) {
		GType dc_mention_span_type_id;
		dc_mention_span_type_id = dc_mention_span_get_type_once ();
		g_once_init_leave (&dc_mention_span_type_id__once, dc_mention_span_type_id);
	}
	return dc_mention_span_type_id__once;
}

static inline gpointer
dc_mention_roster_get_instance_private (DcMentionRoster* self)
{
	return G_STRUCT_MEMBER_P (self, DcMentionRoster_private_offset);
}

static void
_g_object_unref0_ (gpointer var)
{
	(var == NULL) ? NULL : (var = (g_object_unref (var), NULL));
}

static void
_g_free0_ (gpointer var)
{
	var = (g_free (var), NULL);
}

static gpointer
_g_object_ref0 (gpointer self)
{
	return self ? g_object_ref (self) : NULL;
}

void
dc_mention_roster_add_member (DcMentionRoster* self,
                              DcMentionMember* m)
{
	GPtrArray* _tmp0_;
	DcMentionMember* _tmp1_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (m != NULL);
	_tmp0_ = self->members;
	_tmp1_ = _g_object_ref0 (m);
	g_ptr_array_add (_tmp0_, _tmp1_);
	dc_mention_roster_register_address (self, m);
	_g_ptr_array_unref0 (self->priv->name_sorted);
	self->priv->name_sorted = NULL;
}

void
dc_mention_roster_register_address (DcMentionRoster* self,
                                    DcMentionMember* m)
{
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_;
	gboolean _tmp2_;
	const gchar* _tmp5_;
	const gchar* _tmp6_;
	gint _tmp7_;
	gint _tmp8_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (m != NULL);
	_tmp1_ = dc_mention_member_get_is_self (m);
	_tmp2_ = _tmp1_;
	if (_tmp2_) {
		DcMentionMember* _tmp3_;
		_tmp3_ = self->priv->self_member;
		_tmp0_ = _tmp3_ == NULL;
	} else {
		_tmp0_ = FALSE;
	}
	if (_tmp0_) {
		DcMentionMember* _tmp4_;
		_tmp4_ = _g_object_ref0 (m);
		_g_object_unref0 (self->priv->self_member);
		self->priv->self_member = _tmp4_;
	}
	_tmp5_ = dc_mention_member_get_address (m);
	_tmp6_ = _tmp5_;
	_tmp7_ = strlen (_tmp6_);
	_tmp8_ = _tmp7_;
	if (_tmp8_ > 0) {
		GHashTable* _tmp9_;
		const gchar* _tmp10_;
		const gchar* _tmp11_;
		gchar* _tmp12_;
		DcMentionMember* _tmp13_;
		_tmp9_ = self->priv->by_address;
		_tmp10_ = dc_mention_member_get_address (m);
		_tmp11_ = _tmp10_;
		_tmp12_ = g_utf8_strdown (_tmp11_, (gssize) -1);
		_tmp13_ = _g_object_ref0 (m);
		g_hash_table_insert (_tmp9_, _tmp12_, _tmp13_);
	}
}

static gchar*
string_strip (const gchar* self)
{
	gchar* _result_ = NULL;
	gchar* _tmp0_;
	gchar* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = g_strdup (self);
	_result_ = _tmp0_;
	g_strstrip (_result_);
	result = _result_;
	return result;
}

static gint
vala_g_ptr_array_get_length (GPtrArray* self)
{
	gint result;
	g_return_val_if_fail (self != NULL, -1);
	result = (gint) self->len;
	return result;
}

void
dc_mention_roster_add_self_key (DcMentionRoster* self,
                                const gchar* key)
{
	gchar* k = NULL;
	gchar* _tmp0_;
	gchar* _tmp1_;
	gchar* _tmp2_;
	gchar* _tmp3_;
	const gchar* _tmp4_;
	gint _tmp5_;
	gint _tmp6_;
	GPtrArray* _tmp15_;
	const gchar* _tmp16_;
	gchar* _tmp17_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (key != NULL);
	_tmp0_ = string_strip (key);
	_tmp1_ = _tmp0_;
	_tmp2_ = g_utf8_strdown (_tmp1_, (gssize) -1);
	_tmp3_ = _tmp2_;
	_g_free0 (_tmp1_);
	k = _tmp3_;
	_tmp4_ = k;
	_tmp5_ = strlen (_tmp4_);
	_tmp6_ = _tmp5_;
	if (_tmp6_ == 0) {
		_g_free0 (k);
		return;
	}
	{
		gint i = 0;
		i = 0;
		{
			gboolean _tmp7_ = FALSE;
			_tmp7_ = TRUE;
			while (TRUE) {
				GPtrArray* _tmp9_;
				gint _tmp10_;
				gint _tmp11_;
				GPtrArray* _tmp12_;
				gconstpointer _tmp13_;
				const gchar* _tmp14_;
				if (!_tmp7_) {
					gint _tmp8_;
					_tmp8_ = i;
					i = _tmp8_ + 1;
				}
				_tmp7_ = FALSE;
				_tmp9_ = self->priv->self_keys;
				_tmp10_ = vala_g_ptr_array_get_length (_tmp9_);
				_tmp11_ = _tmp10_;
				if (!(i < _tmp11_)) {
					break;
				}
				_tmp12_ = self->priv->self_keys;
				_tmp13_ = g_ptr_array_index (_tmp12_, (guint) i);
				_tmp14_ = k;
				if (g_strcmp0 ((const gchar*) _tmp13_, _tmp14_) == 0) {
					_g_free0 (k);
					return;
				}
			}
		}
	}
	_tmp15_ = self->priv->self_keys;
	_tmp16_ = k;
	_tmp17_ = g_strdup (_tmp16_);
	g_ptr_array_add (_tmp15_, _tmp17_);
	_g_free0 (k);
}

gboolean
dc_mention_roster_has_members (DcMentionRoster* self)
{
	GPtrArray* _tmp0_;
	gint _tmp1_;
	gint _tmp2_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = self->members;
	_tmp1_ = vala_g_ptr_array_get_length (_tmp0_);
	_tmp2_ = _tmp1_;
	result = _tmp2_ > 0;
	return result;
}

DcMentionMember*
dc_mention_roster_lookup_contact (DcMentionRoster* self,
                                  gint contact_id)
{
	DcMentionMember* result;
	g_return_val_if_fail (self != NULL, NULL);
	{
		gint i = 0;
		i = 0;
		{
			gboolean _tmp0_ = FALSE;
			_tmp0_ = TRUE;
			while (TRUE) {
				GPtrArray* _tmp2_;
				gint _tmp3_;
				gint _tmp4_;
				GPtrArray* _tmp5_;
				gconstpointer _tmp6_;
				gint _tmp7_;
				gint _tmp8_;
				if (!_tmp0_) {
					gint _tmp1_;
					_tmp1_ = i;
					i = _tmp1_ + 1;
				}
				_tmp0_ = FALSE;
				_tmp2_ = self->members;
				_tmp3_ = vala_g_ptr_array_get_length (_tmp2_);
				_tmp4_ = _tmp3_;
				if (!(i < _tmp4_)) {
					break;
				}
				_tmp5_ = self->members;
				_tmp6_ = g_ptr_array_index (_tmp5_, (guint) i);
				_tmp7_ = dc_mention_member_get_contact_id ((DcMentionMember*) _tmp6_);
				_tmp8_ = _tmp7_;
				if (_tmp8_ == contact_id) {
					GPtrArray* _tmp9_;
					gconstpointer _tmp10_;
					DcMentionMember* _tmp11_;
					_tmp9_ = self->members;
					_tmp10_ = g_ptr_array_index (_tmp9_, (guint) i);
					_tmp11_ = _g_object_ref0 ((DcMentionMember*) _tmp10_);
					result = _tmp11_;
					return result;
				}
			}
		}
	}
	result = NULL;
	return result;
}

static gboolean
dc_mention_roster_key_is_self (DcMentionRoster* self,
                               const gchar* down_value)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (down_value != NULL, FALSE);
	{
		gint i = 0;
		i = 0;
		{
			gboolean _tmp0_ = FALSE;
			_tmp0_ = TRUE;
			while (TRUE) {
				GPtrArray* _tmp2_;
				gint _tmp3_;
				gint _tmp4_;
				GPtrArray* _tmp5_;
				gconstpointer _tmp6_;
				if (!_tmp0_) {
					gint _tmp1_;
					_tmp1_ = i;
					i = _tmp1_ + 1;
				}
				_tmp0_ = FALSE;
				_tmp2_ = self->priv->self_keys;
				_tmp3_ = vala_g_ptr_array_get_length (_tmp2_);
				_tmp4_ = _tmp3_;
				if (!(i < _tmp4_)) {
					break;
				}
				_tmp5_ = self->priv->self_keys;
				_tmp6_ = g_ptr_array_index (_tmp5_, (guint) i);
				if (g_strcmp0 ((const gchar*) _tmp6_, down_value) == 0) {
					result = TRUE;
					return result;
				}
			}
		}
	}
	result = FALSE;
	return result;
}

static gpointer
_g_ptr_array_ref0 (gpointer self)
{
	return self ? g_ptr_array_ref (self) : NULL;
}

static Block21Data*
block21_data_ref (Block21Data* _data21_)
{
	g_atomic_int_inc (&_data21_->_ref_count_);
	return _data21_;
}

static void
block21_data_unref (void * _userdata_)
{
	Block21Data* _data21_;
	_data21_ = (Block21Data*) _userdata_;
	if (g_atomic_int_dec_and_test (&_data21_->_ref_count_)) {
		GPtrArray* self;
		self = _data21_->self;
		_g_ptr_array_unref0 (self);
		g_slice_free (Block21Data, _data21_);
	}
}

static gint
__lambda0_ (Block21Data* _data21_,
            gconstpointer** a,
            gconstpointer** b)
{
	GPtrArray* self;
	gint result;
	self = _data21_->self;
	result = _data21_->compare_func ((gconstpointer**) (*a), (gconstpointer**) (*b));
	return result;
}

static gint
___lambda0__gcompare_data_func (gconstpointer a,
                                gconstpointer b,
                                gpointer self)
{
	gint result;
	result = __lambda0_ (self, a, b);
	return result;
}

static void
vala_g_ptr_array_sort (GPtrArray* self,
                       GCompareFunc compare_func)
{
	Block21Data* _data21_;
	g_return_if_fail (self != NULL);
	_data21_ = g_slice_new0 (Block21Data);
	_data21_->_ref_count_ = 1;
	_data21_->self = g_ptr_array_ref (self);
	_data21_->compare_func = compare_func;
	g_ptr_array_sort_with_data (self, ___lambda0__gcompare_data_func, _data21_);
	block21_data_unref (_data21_);
	_data21_ = NULL;
}

static gint
__lambda7_ (DcMentionMember* a,
            DcMentionMember* b)
{
	const gchar* _tmp0_;
	const gchar* _tmp1_;
	gint _tmp2_;
	gint _tmp3_;
	const gchar* _tmp4_;
	const gchar* _tmp5_;
	gint _tmp6_;
	gint _tmp7_;
	gint result;
	g_return_val_if_fail (a != NULL, -1);
	g_return_val_if_fail (b != NULL, -1);
	_tmp0_ = dc_mention_member_get_display_name (b);
	_tmp1_ = _tmp0_;
	_tmp2_ = strlen (_tmp1_);
	_tmp3_ = _tmp2_;
	_tmp4_ = dc_mention_member_get_display_name (a);
	_tmp5_ = _tmp4_;
	_tmp6_ = strlen (_tmp5_);
	_tmp7_ = _tmp6_;
	result = ((gint) _tmp3_) - ((gint) _tmp7_);
	return result;
}

static gint
___lambda7__gcompare_func (gconstpointer a,
                           gconstpointer b)
{
	gint result;
	result = __lambda7_ ((DcMentionMember*) a, (DcMentionMember*) b);
	return result;
}

static GPtrArray*
dc_mention_roster_names_longest_first (DcMentionRoster* self)
{
	GPtrArray* _tmp0_;
	GPtrArray* _tmp3_;
	GPtrArray* _tmp22_;
	GPtrArray* _tmp23_;
	GPtrArray* _tmp24_;
	GPtrArray* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->name_sorted;
	if (_tmp0_ != NULL) {
		GPtrArray* _tmp1_;
		GPtrArray* _tmp2_;
		_tmp1_ = self->priv->name_sorted;
		_tmp2_ = _g_ptr_array_ref0 (_tmp1_);
		result = _tmp2_;
		return result;
	}
	_tmp3_ = g_ptr_array_new_full ((guint) 0, _g_object_unref0_);
	_g_ptr_array_unref0 (self->priv->name_sorted);
	self->priv->name_sorted = _tmp3_;
	{
		gint i = 0;
		i = 0;
		{
			gboolean _tmp4_ = FALSE;
			_tmp4_ = TRUE;
			while (TRUE) {
				GPtrArray* _tmp6_;
				gint _tmp7_;
				gint _tmp8_;
				GPtrArray* _tmp9_;
				gconstpointer _tmp10_;
				const gchar* _tmp11_;
				const gchar* _tmp12_;
				gchar* _tmp13_;
				gchar* _tmp14_;
				gint _tmp15_;
				gint _tmp16_;
				gboolean _tmp17_;
				if (!_tmp4_) {
					gint _tmp5_;
					_tmp5_ = i;
					i = _tmp5_ + 1;
				}
				_tmp4_ = FALSE;
				_tmp6_ = self->members;
				_tmp7_ = vala_g_ptr_array_get_length (_tmp6_);
				_tmp8_ = _tmp7_;
				if (!(i < _tmp8_)) {
					break;
				}
				_tmp9_ = self->members;
				_tmp10_ = g_ptr_array_index (_tmp9_, (guint) i);
				_tmp11_ = dc_mention_member_get_display_name ((DcMentionMember*) _tmp10_);
				_tmp12_ = _tmp11_;
				_tmp13_ = string_strip (_tmp12_);
				_tmp14_ = _tmp13_;
				_tmp15_ = strlen (_tmp14_);
				_tmp16_ = _tmp15_;
				_tmp17_ = _tmp16_ > 0;
				_g_free0 (_tmp14_);
				if (_tmp17_) {
					GPtrArray* _tmp18_;
					GPtrArray* _tmp19_;
					gconstpointer _tmp20_;
					DcMentionMember* _tmp21_;
					_tmp18_ = self->priv->name_sorted;
					_tmp19_ = self->members;
					_tmp20_ = g_ptr_array_index (_tmp19_, (guint) i);
					_tmp21_ = _g_object_ref0 ((DcMentionMember*) _tmp20_);
					g_ptr_array_add (_tmp18_, _tmp21_);
				}
			}
		}
	}
	_tmp22_ = self->priv->name_sorted;
	vala_g_ptr_array_sort (_tmp22_, ___lambda7__gcompare_func);
	_tmp23_ = self->priv->name_sorted;
	_tmp24_ = _g_ptr_array_ref0 (_tmp23_);
	result = _tmp24_;
	return result;
}

/**
         * Try to resolve a mention starting at the '@' at byte offset `at` in
         * `raw`. Returns the span (with token length) or null if nothing
         * resolves. Assumes the caller already checked the word boundary before
         * the '@'.
         */
static glong
string_strnlen (gchar* str,
                glong maxlen)
{
	gchar* end = NULL;
	gchar* _tmp0_;
	gchar* _tmp1_;
	glong result;
	_tmp0_ = memchr (str, 0, (gsize) maxlen);
	end = _tmp0_;
	_tmp1_ = end;
	if (_tmp1_ == NULL) {
		result = maxlen;
		return result;
	} else {
		gchar* _tmp2_;
		_tmp2_ = end;
		result = (glong) (_tmp2_ - str);
		return result;
	}
}

static gchar*
string_substring (const gchar* self,
                  glong offset,
                  glong len)
{
	glong string_length = 0L;
	gboolean _tmp0_ = FALSE;
	gchar* _tmp3_;
	gchar* result;
	g_return_val_if_fail (self != NULL, NULL);
	if (offset >= ((glong) 0)) {
		_tmp0_ = len >= ((glong) 0);
	} else {
		_tmp0_ = FALSE;
	}
	if (_tmp0_) {
		string_length = string_strnlen ((gchar*) self, offset + len);
	} else {
		gint _tmp1_;
		gint _tmp2_;
		_tmp1_ = strlen (self);
		_tmp2_ = _tmp1_;
		string_length = (glong) _tmp2_;
	}
	if (offset < ((glong) 0)) {
		offset = string_length + offset;
		g_return_val_if_fail (offset >= ((glong) 0), NULL);
	} else {
		g_return_val_if_fail (offset <= string_length, NULL);
	}
	if (len < ((glong) 0)) {
		len = string_length - offset;
	}
	g_return_val_if_fail ((offset + len) <= string_length, NULL);
	_tmp3_ = g_strndup (((gchar*) self) + offset, (gsize) len);
	result = _tmp3_;
	return result;
}

DcMentionSpan*
dc_mention_roster_resolve_at (DcMentionRoster* self,
                              const gchar* raw,
                              gint at)
{
	gint after = 0;
	gint _tmp0_;
	gint _tmp1_;
	gchar* rest = NULL;
	gchar* _tmp2_;
	DcMentionSpan* span = NULL;
	const gchar* _tmp3_;
	DcMentionSpan* _tmp4_;
	DcMentionSpan* _tmp5_;
	const gchar* _tmp6_;
	DcMentionSpan* _tmp7_;
	DcMentionSpan* _tmp8_;
	const gchar* _tmp9_;
	DcMentionSpan* _tmp10_;
	DcMentionSpan* result;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (raw != NULL, NULL);
	after = at + 1;
	_tmp0_ = strlen (raw);
	_tmp1_ = _tmp0_;
	if (after > _tmp1_) {
		result = NULL;
		return result;
	}
	_tmp2_ = string_substring (raw, (glong) after, (glong) -1);
	rest = _tmp2_;
	_tmp3_ = rest;
	_tmp4_ = dc_mention_roster_resolve_address (self, raw, at, _tmp3_);
	span = _tmp4_;
	_tmp5_ = span;
	if (_tmp5_ != NULL) {
		result = span;
		_g_free0 (rest);
		return result;
	}
	_tmp6_ = rest;
	_tmp7_ = dc_mention_roster_resolve_name (self, raw, at, _tmp6_);
	_g_object_unref0 (span);
	span = _tmp7_;
	_tmp8_ = span;
	if (_tmp8_ != NULL) {
		result = span;
		_g_free0 (rest);
		return result;
	}
	_tmp9_ = rest;
	_tmp10_ = dc_mention_roster_resolve_self_name (self, raw, at, _tmp9_);
	result = _tmp10_;
	_g_object_unref0 (span);
	_g_free0 (rest);
	return result;
}

static gchar*
dc_mention_roster_self_display (DcMentionRoster* self,
                                const gchar* fallback)
{
	gboolean _tmp0_ = FALSE;
	DcMentionMember* _tmp1_;
	gchar* _tmp11_;
	gchar* result;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (fallback != NULL, NULL);
	_tmp1_ = self->priv->self_member;
	if (_tmp1_ != NULL) {
		DcMentionMember* _tmp2_;
		const gchar* _tmp3_;
		const gchar* _tmp4_;
		gint _tmp5_;
		gint _tmp6_;
		_tmp2_ = self->priv->self_member;
		_tmp3_ = dc_mention_member_get_display_name (_tmp2_);
		_tmp4_ = _tmp3_;
		_tmp5_ = strlen (_tmp4_);
		_tmp6_ = _tmp5_;
		_tmp0_ = _tmp6_ > 0;
	} else {
		_tmp0_ = FALSE;
	}
	if (_tmp0_) {
		DcMentionMember* _tmp7_;
		const gchar* _tmp8_;
		const gchar* _tmp9_;
		gchar* _tmp10_;
		_tmp7_ = self->priv->self_member;
		_tmp8_ = dc_mention_member_get_display_name (_tmp7_);
		_tmp9_ = _tmp8_;
		_tmp10_ = g_strdup (_tmp9_);
		result = _tmp10_;
		return result;
	}
	_tmp11_ = g_strdup (fallback);
	result = _tmp11_;
	return result;
}

static gboolean
string_get_next_char (const gchar* self,
                      gint* index,
                      gunichar* c)
{
	gunichar _vala_c = 0U;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	_vala_c = g_utf8_get_char (((gchar*) self) + (*index));
	if (_vala_c != ((gunichar) 0)) {
		gchar* _tmp0_;
		_tmp0_ = g_utf8_next_char (((gchar*) self) + (*index));
		*index = (gint) (_tmp0_ - ((gchar*) self));
		result = TRUE;
		if (c) {
			*c = _vala_c;
		}
		return result;
	} else {
		result = FALSE;
		if (c) {
			*c = _vala_c;
		}
		return result;
	}
}

static gboolean
string_contains (const gchar* self,
                 const gchar* needle)
{
	gchar* _tmp0_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (needle != NULL, FALSE);
	_tmp0_ = strstr ((gchar*) self, (gchar*) needle);
	result = _tmp0_ != NULL;
	return result;
}

static DcMentionSpan*
dc_mention_roster_resolve_address (DcMentionRoster* self,
                                   const gchar* raw,
                                   gint at,
                                   const gchar* rest)
{
	gint len = 0;
	gboolean seen_at = FALSE;
	gunichar c = 0U;
	gint idx = 0;
	gboolean _tmp2_ = FALSE;
	gchar* candidate = NULL;
	gchar* _tmp3_;
	const gchar* _tmp4_;
	gchar* _tmp5_;
	gboolean _tmp6_ = FALSE;
	const gchar* _tmp7_;
	gint _tmp8_;
	gint _tmp9_;
	DcMentionMember* member = NULL;
	GHashTable* _tmp11_;
	const gchar* _tmp12_;
	gchar* _tmp13_;
	gchar* _tmp14_;
	gconstpointer _tmp15_;
	DcMentionMember* _tmp16_;
	DcMentionMember* _tmp17_;
	DcMentionMember* _tmp18_;
	DcMentionSpan* span = NULL;
	DcMentionSpan* _tmp19_;
	DcMentionSpan* _tmp20_;
	DcMentionSpan* _tmp21_;
	const gchar* _tmp22_;
	gint _tmp23_;
	gint _tmp24_;
	gboolean _tmp25_ = FALSE;
	DcMentionMember* _tmp26_;
	gboolean _tmp27_;
	gboolean _tmp28_;
	DcMentionSpan* _tmp32_;
	gchar* _tmp33_ = NULL;
	DcMentionSpan* _tmp34_;
	DcMentionSpan* _tmp57_;
	gchar* _tmp58_;
	DcMentionSpan* _tmp59_;
	DcMentionMember* _tmp60_;
	gint _tmp61_;
	gint _tmp62_;
	gchar* _tmp63_;
	DcMentionSpan* result;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (raw != NULL, NULL);
	g_return_val_if_fail (rest != NULL, NULL);
	len = 0;
	seen_at = FALSE;
	idx = 0;
	while (TRUE) {
		gunichar _tmp0_ = 0U;
		gboolean _tmp1_;
		_tmp1_ = string_get_next_char (rest, &idx, &_tmp0_);
		c = _tmp0_;
		if (!_tmp1_) {
			break;
		}
		if (g_unichar_isspace (c)) {
			break;
		}
		if (c == ((gunichar) '@')) {
			seen_at = TRUE;
		}
		len = idx;
	}
	if (!seen_at) {
		_tmp2_ = TRUE;
	} else {
		_tmp2_ = len == 0;
	}
	if (_tmp2_) {
		result = NULL;
		return result;
	}
	_tmp3_ = string_substring (rest, (glong) 0, (glong) len);
	candidate = _tmp3_;
	_tmp4_ = candidate;
	_tmp5_ = dc_mention_roster_trim_trailing_punct (_tmp4_);
	_g_free0 (candidate);
	candidate = _tmp5_;
	_tmp7_ = candidate;
	_tmp8_ = strlen (_tmp7_);
	_tmp9_ = _tmp8_;
	if (_tmp9_ == 0) {
		_tmp6_ = TRUE;
	} else {
		const gchar* _tmp10_;
		_tmp10_ = candidate;
		_tmp6_ = !string_contains (_tmp10_, "@");
	}
	if (_tmp6_) {
		result = NULL;
		_g_free0 (candidate);
		return result;
	}
	_tmp11_ = self->priv->by_address;
	_tmp12_ = candidate;
	_tmp13_ = g_utf8_strdown (_tmp12_, (gssize) -1);
	_tmp14_ = _tmp13_;
	_tmp15_ = g_hash_table_lookup (_tmp11_, _tmp14_);
	_tmp16_ = _g_object_ref0 ((DcMentionMember*) _tmp15_);
	_tmp17_ = _tmp16_;
	_g_free0 (_tmp14_);
	member = _tmp17_;
	_tmp18_ = member;
	if (_tmp18_ == NULL) {
		result = NULL;
		_g_object_unref0 (member);
		_g_free0 (candidate);
		return result;
	}
	_tmp19_ = dc_mention_span_new ();
	span = _tmp19_;
	_tmp20_ = span;
	_tmp20_->start = at;
	_tmp21_ = span;
	_tmp22_ = candidate;
	_tmp23_ = strlen (_tmp22_);
	_tmp24_ = _tmp23_;
	_tmp21_->end = (at + 1) + _tmp24_;
	_tmp26_ = member;
	_tmp27_ = dc_mention_member_get_is_self (_tmp26_);
	_tmp28_ = _tmp27_;
	if (_tmp28_) {
		_tmp25_ = TRUE;
	} else {
		const gchar* _tmp29_;
		gchar* _tmp30_;
		gchar* _tmp31_;
		_tmp29_ = candidate;
		_tmp30_ = g_utf8_strdown (_tmp29_, (gssize) -1);
		_tmp31_ = _tmp30_;
		_tmp25_ = dc_mention_roster_key_is_self (self, _tmp31_);
		_g_free0 (_tmp31_);
	}
	_tmp32_ = span;
	_tmp32_->is_self = _tmp25_;
	_tmp34_ = span;
	if (_tmp34_->is_self) {
		const gchar* _tmp35_ = NULL;
		DcMentionMember* _tmp36_;
		const gchar* _tmp37_;
		const gchar* _tmp38_;
		gint _tmp39_;
		gint _tmp40_;
		gchar* _tmp45_;
		_tmp36_ = member;
		_tmp37_ = dc_mention_member_get_display_name (_tmp36_);
		_tmp38_ = _tmp37_;
		_tmp39_ = strlen (_tmp38_);
		_tmp40_ = _tmp39_;
		if (_tmp40_ > 0) {
			DcMentionMember* _tmp41_;
			const gchar* _tmp42_;
			const gchar* _tmp43_;
			_tmp41_ = member;
			_tmp42_ = dc_mention_member_get_display_name (_tmp41_);
			_tmp43_ = _tmp42_;
			_tmp35_ = _tmp43_;
		} else {
			const gchar* _tmp44_;
			_tmp44_ = candidate;
			_tmp35_ = _tmp44_;
		}
		_tmp45_ = dc_mention_roster_self_display (self, _tmp35_);
		_g_free0 (_tmp33_);
		_tmp33_ = _tmp45_;
	} else {
		const gchar* _tmp46_ = NULL;
		DcMentionMember* _tmp47_;
		const gchar* _tmp48_;
		const gchar* _tmp49_;
		gint _tmp50_;
		gint _tmp51_;
		gchar* _tmp56_;
		_tmp47_ = member;
		_tmp48_ = dc_mention_member_get_display_name (_tmp47_);
		_tmp49_ = _tmp48_;
		_tmp50_ = strlen (_tmp49_);
		_tmp51_ = _tmp50_;
		if (_tmp51_ > 0) {
			DcMentionMember* _tmp52_;
			const gchar* _tmp53_;
			const gchar* _tmp54_;
			_tmp52_ = member;
			_tmp53_ = dc_mention_member_get_display_name (_tmp52_);
			_tmp54_ = _tmp53_;
			_tmp46_ = _tmp54_;
		} else {
			const gchar* _tmp55_;
			_tmp55_ = candidate;
			_tmp46_ = _tmp55_;
		}
		_tmp56_ = g_strdup (_tmp46_);
		_g_free0 (_tmp33_);
		_tmp33_ = _tmp56_;
	}
	_tmp57_ = span;
	_tmp58_ = _tmp33_;
	_tmp33_ = NULL;
	_g_free0 (_tmp57_->display);
	_tmp57_->display = _tmp58_;
	_tmp59_ = span;
	_tmp60_ = member;
	_tmp61_ = dc_mention_member_get_contact_id (_tmp60_);
	_tmp62_ = _tmp61_;
	_tmp63_ = g_strdup_printf ("parla-mention:cid=%d", _tmp62_);
	_g_free0 (_tmp59_->href);
	_tmp59_->href = _tmp63_;
	result = span;
	_g_free0 (_tmp33_);
	_g_object_unref0 (member);
	_g_free0 (candidate);
	return result;
}

static DcMentionSpan*
dc_mention_roster_resolve_name (DcMentionRoster* self,
                                const gchar* raw,
                                gint at,
                                const gchar* rest)
{
	GPtrArray* candidates = NULL;
	GPtrArray* _tmp0_;
	gchar* rest_down = NULL;
	gchar* _tmp1_;
	DcMentionSpan* result;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (raw != NULL, NULL);
	g_return_val_if_fail (rest != NULL, NULL);
	_tmp0_ = dc_mention_roster_names_longest_first (self);
	candidates = _tmp0_;
	_tmp1_ = g_utf8_strdown (rest, (gssize) -1);
	rest_down = _tmp1_;
	{
		gint i = 0;
		i = 0;
		{
			gboolean _tmp2_ = FALSE;
			_tmp2_ = TRUE;
			while (TRUE) {
				GPtrArray* _tmp4_;
				gint _tmp5_;
				gint _tmp6_;
				gchar* name = NULL;
				GPtrArray* _tmp7_;
				gconstpointer _tmp8_;
				const gchar* _tmp9_;
				const gchar* _tmp10_;
				gchar* _tmp11_;
				const gchar* _tmp12_;
				const gchar* _tmp13_;
				gchar* _tmp14_;
				gchar* _tmp15_;
				gboolean _tmp16_;
				gint name_len = 0;
				const gchar* _tmp17_;
				gint _tmp18_;
				gint _tmp19_;
				DcMentionMember* m = NULL;
				GPtrArray* _tmp20_;
				gconstpointer _tmp21_;
				DcMentionMember* _tmp22_;
				DcMentionSpan* span = NULL;
				DcMentionSpan* _tmp23_;
				DcMentionSpan* _tmp24_;
				DcMentionSpan* _tmp25_;
				gboolean _tmp26_ = FALSE;
				DcMentionMember* _tmp27_;
				gboolean _tmp28_;
				gboolean _tmp29_;
				DcMentionSpan* _tmp33_;
				DcMentionSpan* _tmp34_;
				DcMentionMember* _tmp35_;
				const gchar* _tmp36_;
				const gchar* _tmp37_;
				gchar* _tmp38_;
				DcMentionSpan* _tmp39_;
				DcMentionMember* _tmp40_;
				gint _tmp41_;
				gint _tmp42_;
				gchar* _tmp43_;
				if (!_tmp2_) {
					gint _tmp3_;
					_tmp3_ = i;
					i = _tmp3_ + 1;
				}
				_tmp2_ = FALSE;
				_tmp4_ = candidates;
				_tmp5_ = vala_g_ptr_array_get_length (_tmp4_);
				_tmp6_ = _tmp5_;
				if (!(i < _tmp6_)) {
					break;
				}
				_tmp7_ = candidates;
				_tmp8_ = g_ptr_array_index (_tmp7_, (guint) i);
				_tmp9_ = dc_mention_member_get_display_name ((DcMentionMember*) _tmp8_);
				_tmp10_ = _tmp9_;
				_tmp11_ = g_strdup (_tmp10_);
				name = _tmp11_;
				_tmp12_ = rest_down;
				_tmp13_ = name;
				_tmp14_ = g_utf8_strdown (_tmp13_, (gssize) -1);
				_tmp15_ = _tmp14_;
				_tmp16_ = !g_str_has_prefix (_tmp12_, _tmp15_);
				_g_free0 (_tmp15_);
				if (_tmp16_) {
					_g_free0 (name);
					continue;
				}
				_tmp17_ = name;
				_tmp18_ = strlen (_tmp17_);
				_tmp19_ = _tmp18_;
				name_len = _tmp19_;
				if (!dc_mention_roster_boundary_after (rest, name_len)) {
					_g_free0 (name);
					continue;
				}
				_tmp20_ = candidates;
				_tmp21_ = g_ptr_array_index (_tmp20_, (guint) i);
				_tmp22_ = _g_object_ref0 ((DcMentionMember*) _tmp21_);
				m = _tmp22_;
				_tmp23_ = dc_mention_span_new ();
				span = _tmp23_;
				_tmp24_ = span;
				_tmp24_->start = at;
				_tmp25_ = span;
				_tmp25_->end = (at + 1) + name_len;
				_tmp27_ = m;
				_tmp28_ = dc_mention_member_get_is_self (_tmp27_);
				_tmp29_ = _tmp28_;
				if (_tmp29_) {
					_tmp26_ = TRUE;
				} else {
					const gchar* _tmp30_;
					gchar* _tmp31_;
					gchar* _tmp32_;
					_tmp30_ = name;
					_tmp31_ = g_utf8_strdown (_tmp30_, (gssize) -1);
					_tmp32_ = _tmp31_;
					_tmp26_ = dc_mention_roster_key_is_self (self, _tmp32_);
					_g_free0 (_tmp32_);
				}
				_tmp33_ = span;
				_tmp33_->is_self = _tmp26_;
				_tmp34_ = span;
				_tmp35_ = m;
				_tmp36_ = dc_mention_member_get_display_name (_tmp35_);
				_tmp37_ = _tmp36_;
				_tmp38_ = g_strdup (_tmp37_);
				_g_free0 (_tmp34_->display);
				_tmp34_->display = _tmp38_;
				_tmp39_ = span;
				_tmp40_ = m;
				_tmp41_ = dc_mention_member_get_contact_id (_tmp40_);
				_tmp42_ = _tmp41_;
				_tmp43_ = g_strdup_printf ("parla-mention:cid=%d", _tmp42_);
				_g_free0 (_tmp39_->href);
				_tmp39_->href = _tmp43_;
				result = span;
				_g_object_unref0 (m);
				_g_free0 (name);
				_g_free0 (rest_down);
				_g_ptr_array_unref0 (candidates);
				return result;
			}
		}
	}
	result = NULL;
	_g_free0 (rest_down);
	_g_ptr_array_unref0 (candidates);
	return result;
}

static DcMentionSpan*
dc_mention_roster_resolve_self_name (DcMentionRoster* self,
                                     const gchar* raw,
                                     gint at,
                                     const gchar* rest)
{
	gchar* rest_down = NULL;
	gchar* _tmp0_;
	gint best = 0;
	DcMentionSpan* span = NULL;
	DcMentionSpan* _tmp29_;
	DcMentionSpan* _tmp30_;
	DcMentionSpan* _tmp31_;
	DcMentionSpan* _tmp32_;
	DcMentionSpan* _tmp33_;
	gchar* _tmp34_;
	gchar* _tmp35_;
	gchar* _tmp36_;
	gint _tmp37_ = 0;
	DcMentionMember* _tmp38_;
	DcMentionSpan* _tmp42_;
	gchar* _tmp43_;
	DcMentionSpan* result;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (raw != NULL, NULL);
	g_return_val_if_fail (rest != NULL, NULL);
	_tmp0_ = g_utf8_strdown (rest, (gssize) -1);
	rest_down = _tmp0_;
	best = 0;
	{
		gint i = 0;
		i = 0;
		{
			gboolean _tmp1_ = FALSE;
			_tmp1_ = TRUE;
			while (TRUE) {
				GPtrArray* _tmp3_;
				gint _tmp4_;
				gint _tmp5_;
				gchar* key = NULL;
				GPtrArray* _tmp6_;
				gconstpointer _tmp7_;
				gchar* _tmp8_;
				gboolean _tmp9_ = FALSE;
				const gchar* _tmp10_;
				gint _tmp11_;
				gint _tmp12_;
				const gchar* _tmp18_;
				gint _tmp19_;
				gint _tmp20_;
				const gchar* _tmp21_;
				const gchar* _tmp22_;
				const gchar* _tmp23_;
				gint _tmp24_;
				gint _tmp25_;
				const gchar* _tmp26_;
				gint _tmp27_;
				gint _tmp28_;
				if (!_tmp1_) {
					gint _tmp2_;
					_tmp2_ = i;
					i = _tmp2_ + 1;
				}
				_tmp1_ = FALSE;
				_tmp3_ = self->priv->self_keys;
				_tmp4_ = vala_g_ptr_array_get_length (_tmp3_);
				_tmp5_ = _tmp4_;
				if (!(i < _tmp5_)) {
					break;
				}
				_tmp6_ = self->priv->self_keys;
				_tmp7_ = g_ptr_array_index (_tmp6_, (guint) i);
				_tmp8_ = g_strdup ((const gchar*) _tmp7_);
				key = _tmp8_;
				_tmp10_ = key;
				_tmp11_ = strlen (_tmp10_);
				_tmp12_ = _tmp11_;
				if (_tmp12_ == 0) {
					_tmp9_ = TRUE;
				} else {
					const gchar* _tmp13_;
					gint _tmp14_;
					gint _tmp15_;
					gint _tmp16_;
					gint _tmp17_;
					_tmp13_ = key;
					_tmp14_ = strlen (_tmp13_);
					_tmp15_ = _tmp14_;
					_tmp16_ = strlen (rest);
					_tmp17_ = _tmp16_;
					_tmp9_ = _tmp15_ > _tmp17_;
				}
				if (_tmp9_) {
					_g_free0 (key);
					continue;
				}
				_tmp18_ = key;
				_tmp19_ = strlen (_tmp18_);
				_tmp20_ = _tmp19_;
				if (_tmp20_ <= best) {
					_g_free0 (key);
					continue;
				}
				_tmp21_ = rest_down;
				_tmp22_ = key;
				if (!g_str_has_prefix (_tmp21_, _tmp22_)) {
					_g_free0 (key);
					continue;
				}
				_tmp23_ = key;
				_tmp24_ = strlen (_tmp23_);
				_tmp25_ = _tmp24_;
				if (!dc_mention_roster_boundary_after (rest, _tmp25_)) {
					_g_free0 (key);
					continue;
				}
				_tmp26_ = key;
				_tmp27_ = strlen (_tmp26_);
				_tmp28_ = _tmp27_;
				best = _tmp28_;
				_g_free0 (key);
			}
		}
	}
	if (best == 0) {
		result = NULL;
		_g_free0 (rest_down);
		return result;
	}
	_tmp29_ = dc_mention_span_new ();
	span = _tmp29_;
	_tmp30_ = span;
	_tmp30_->start = at;
	_tmp31_ = span;
	_tmp31_->end = (at + 1) + best;
	_tmp32_ = span;
	_tmp32_->is_self = TRUE;
	_tmp33_ = span;
	_tmp34_ = string_substring (rest, (glong) 0, (glong) best);
	_tmp35_ = _tmp34_;
	_tmp36_ = dc_mention_roster_self_display (self, _tmp35_);
	_g_free0 (_tmp33_->display);
	_tmp33_->display = _tmp36_;
	_g_free0 (_tmp35_);
	_tmp38_ = self->priv->self_member;
	if (_tmp38_ != NULL) {
		DcMentionMember* _tmp39_;
		gint _tmp40_;
		gint _tmp41_;
		_tmp39_ = self->priv->self_member;
		_tmp40_ = dc_mention_member_get_contact_id (_tmp39_);
		_tmp41_ = _tmp40_;
		_tmp37_ = _tmp41_;
	} else {
		_tmp37_ = 1;
	}
	_tmp42_ = span;
	_tmp43_ = g_strdup_printf ("parla-mention:cid=%d", _tmp37_);
	_g_free0 (_tmp42_->href);
	_tmp42_->href = _tmp43_;
	result = span;
	_g_free0 (rest_down);
	return result;
}

gboolean
dc_mention_roster_boundary_after (const gchar* s,
                                  gint pos)
{
	gint _tmp0_;
	gint _tmp1_;
	gunichar c = 0U;
	gint idx = 0;
	gunichar _tmp2_ = 0U;
	gboolean _tmp3_;
	gboolean _tmp4_ = FALSE;
	gunichar next = 0U;
	gint after = 0;
	gunichar _tmp5_ = 0U;
	gboolean _tmp6_;
	gboolean _tmp7_ = FALSE;
	gboolean _tmp8_ = FALSE;
	gboolean result;
	g_return_val_if_fail (s != NULL, FALSE);
	_tmp0_ = strlen (s);
	_tmp1_ = _tmp0_;
	if (pos >= _tmp1_) {
		result = TRUE;
		return result;
	}
	idx = pos;
	_tmp3_ = string_get_next_char (s, &idx, &_tmp2_);
	c = _tmp2_;
	if (!_tmp3_) {
		result = TRUE;
		return result;
	}
	if (g_unichar_isalnum (c)) {
		_tmp4_ = TRUE;
	} else {
		_tmp4_ = c == ((gunichar) '_');
	}
	if (_tmp4_) {
		result = FALSE;
		return result;
	}
	if (!dc_mention_roster_is_name_joiner (c)) {
		result = TRUE;
		return result;
	}
	after = idx;
	_tmp6_ = string_get_next_char (s, &after, &_tmp5_);
	next = _tmp5_;
	if (!_tmp6_) {
		result = TRUE;
		return result;
	}
	if (g_unichar_isalnum (next)) {
		_tmp8_ = TRUE;
	} else {
		_tmp8_ = next == ((gunichar) '_');
	}
	if (_tmp8_) {
		_tmp7_ = TRUE;
	} else {
		_tmp7_ = dc_mention_roster_is_name_joiner (next);
	}
	result = !_tmp7_;
	return result;
}

static gboolean
dc_mention_roster_is_name_joiner (gunichar c)
{
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	gboolean result;
	if (c == ((gunichar) '-')) {
		_tmp1_ = TRUE;
	} else {
		_tmp1_ = c == ((gunichar) '.');
	}
	if (_tmp1_) {
		_tmp0_ = TRUE;
	} else {
		_tmp0_ = c == ((gunichar) '+');
	}
	result = _tmp0_;
	return result;
}

static gchar
string_get (const gchar* self,
            glong index)
{
	gchar _tmp0_;
	gchar result;
	g_return_val_if_fail (self != NULL, '\0');
	_tmp0_ = ((gchar*) self)[index];
	result = _tmp0_;
	return result;
}

static gchar*
dc_mention_roster_trim_trailing_punct (const gchar* s)
{
	gchar* _result_ = NULL;
	gchar* _tmp0_;
	gchar* result;
	g_return_val_if_fail (s != NULL, NULL);
	_tmp0_ = g_strdup (s);
	_result_ = _tmp0_;
	while (TRUE) {
		const gchar* _tmp1_;
		gint _tmp2_;
		gint _tmp3_;
		gchar last = '\0';
		const gchar* _tmp4_;
		const gchar* _tmp5_;
		gint _tmp6_;
		gint _tmp7_;
		gboolean _tmp8_ = FALSE;
		gboolean _tmp9_ = FALSE;
		gboolean _tmp10_ = FALSE;
		gboolean _tmp11_ = FALSE;
		gboolean _tmp12_ = FALSE;
		gboolean _tmp13_ = FALSE;
		gboolean _tmp14_ = FALSE;
		gboolean _tmp15_ = FALSE;
		gboolean _tmp16_ = FALSE;
		gboolean _tmp17_ = FALSE;
		gboolean _tmp18_ = FALSE;
		_tmp1_ = _result_;
		_tmp2_ = strlen (_tmp1_);
		_tmp3_ = _tmp2_;
		if (!(_tmp3_ > 0)) {
			break;
		}
		_tmp4_ = _result_;
		_tmp5_ = _result_;
		_tmp6_ = strlen (_tmp5_);
		_tmp7_ = _tmp6_;
		last = string_get (_tmp4_, (glong) (_tmp7_ - 1));
		if (last == '.') {
			_tmp18_ = TRUE;
		} else {
			_tmp18_ = last == ',';
		}
		if (_tmp18_) {
			_tmp17_ = TRUE;
		} else {
			_tmp17_ = last == ';';
		}
		if (_tmp17_) {
			_tmp16_ = TRUE;
		} else {
			_tmp16_ = last == ':';
		}
		if (_tmp16_) {
			_tmp15_ = TRUE;
		} else {
			_tmp15_ = last == '!';
		}
		if (_tmp15_) {
			_tmp14_ = TRUE;
		} else {
			_tmp14_ = last == '?';
		}
		if (_tmp14_) {
			_tmp13_ = TRUE;
		} else {
			_tmp13_ = last == ')';
		}
		if (_tmp13_) {
			_tmp12_ = TRUE;
		} else {
			_tmp12_ = last == ']';
		}
		if (_tmp12_) {
			_tmp11_ = TRUE;
		} else {
			_tmp11_ = last == '}';
		}
		if (_tmp11_) {
			_tmp10_ = TRUE;
		} else {
			_tmp10_ = last == '"';
		}
		if (_tmp10_) {
			_tmp9_ = TRUE;
		} else {
			_tmp9_ = last == '\'';
		}
		if (_tmp9_) {
			_tmp8_ = TRUE;
		} else {
			_tmp8_ = last == '>';
		}
		if (_tmp8_) {
			const gchar* _tmp19_;
			const gchar* _tmp20_;
			gint _tmp21_;
			gint _tmp22_;
			gchar* _tmp23_;
			_tmp19_ = _result_;
			_tmp20_ = _result_;
			_tmp21_ = strlen (_tmp20_);
			_tmp22_ = _tmp21_;
			_tmp23_ = string_substring (_tmp19_, (glong) 0, (glong) (_tmp22_ - 1));
			_g_free0 (_result_);
			_result_ = _tmp23_;
		} else {
			break;
		}
	}
	result = _result_;
	return result;
}

DcMentionRoster*
dc_mention_roster_construct (GType object_type)
{
	DcMentionRoster * self = NULL;
	self = (DcMentionRoster*) g_object_new (object_type, NULL);
	return self;
}

DcMentionRoster*
dc_mention_roster_new (void)
{
	return dc_mention_roster_construct (DC_TYPE_MENTION_ROSTER);
}

static void
dc_mention_roster_class_init (DcMentionRosterClass * klass,
                              gpointer klass_data)
{
	dc_mention_roster_parent_class = g_type_class_peek_parent (klass);
	g_type_class_adjust_private_offset (klass, &DcMentionRoster_private_offset);
	G_OBJECT_CLASS (klass)->finalize = dc_mention_roster_finalize;
}

static void
dc_mention_roster_instance_init (DcMentionRoster * self,
                                 gpointer klass)
{
	GPtrArray* _tmp0_;
	GHashFunc _tmp1_;
	GEqualFunc _tmp2_;
	GHashTable* _tmp3_;
	GPtrArray* _tmp4_;
	self->priv = dc_mention_roster_get_instance_private (self);
	_tmp0_ = g_ptr_array_new_full ((guint) 0, _g_object_unref0_);
	self->members = _tmp0_;
	_tmp1_ = g_str_hash;
	_tmp2_ = g_str_equal;
	_tmp3_ = g_hash_table_new_full (_tmp1_, _tmp2_, _g_free0_, _g_object_unref0_);
	self->priv->by_address = _tmp3_;
	self->priv->name_sorted = NULL;
	_tmp4_ = g_ptr_array_new_full ((guint) 0, _g_free0_);
	self->priv->self_keys = _tmp4_;
	self->priv->self_member = NULL;
}

static void
dc_mention_roster_finalize (GObject * obj)
{
	DcMentionRoster * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, DC_TYPE_MENTION_ROSTER, DcMentionRoster);
	_g_ptr_array_unref0 (self->members);
	_g_hash_table_unref0 (self->priv->by_address);
	_g_ptr_array_unref0 (self->priv->name_sorted);
	_g_ptr_array_unref0 (self->priv->self_keys);
	_g_object_unref0 (self->priv->self_member);
	G_OBJECT_CLASS (dc_mention_roster_parent_class)->finalize (obj);
}

/**
     * Mentions are a Parla-only convention layered on plain message text (Delta
     * Chat core has no mention feature). Two token forms are recognized, both
     * only at a word boundary (start of text or after whitespace):
     *
     *   @Display Name          — matched against the chat's member names
     *   @localpart@domain      — matched against known contact addresses
     *
     * A name may contain spaces, so name matching is a longest-prefix match
     * against the roster. Address matching resolves against every known contact
     * (the portable form other clients can resolve if they have the contact).
     * Unresolved tokens are left as plain text.
     */
static GType
dc_mention_roster_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (DcMentionRosterClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) dc_mention_roster_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (DcMentionRoster), 0, (GInstanceInitFunc) dc_mention_roster_instance_init, NULL };
	GType dc_mention_roster_type_id;
	dc_mention_roster_type_id = g_type_register_static (G_TYPE_OBJECT, "DcMentionRoster", &g_define_type_info, 0);
	DcMentionRoster_private_offset = g_type_add_instance_private (dc_mention_roster_type_id, sizeof (DcMentionRosterPrivate));
	return dc_mention_roster_type_id;
}

GType
dc_mention_roster_get_type (void)
{
	static volatile gsize dc_mention_roster_type_id__once = 0;
	if (g_once_init_enter (&dc_mention_roster_type_id__once)) {
		GType dc_mention_roster_type_id;
		dc_mention_roster_type_id = dc_mention_roster_get_type_once ();
		g_once_init_leave (&dc_mention_roster_type_id__once, dc_mention_roster_type_id);
	}
	return dc_mention_roster_type_id__once;
}

void
dc_mentions_set_accent (const gchar* hex)
{
	const gchar* _tmp0_ = NULL;
	gboolean _tmp1_ = FALSE;
	gchar* _tmp4_;
	if (hex != NULL) {
		gint _tmp2_;
		gint _tmp3_;
		_tmp2_ = strlen (hex);
		_tmp3_ = _tmp2_;
		_tmp1_ = _tmp3_ > 0;
	} else {
		_tmp1_ = FALSE;
	}
	if (_tmp1_) {
		_tmp0_ = hex;
	} else {
		_tmp0_ = NULL;
	}
	_tmp4_ = g_strdup (_tmp0_);
	_g_free0 (dc_mentions_accent_override);
	dc_mentions_accent_override = _tmp4_;
}

static gchar*
dc_mentions_accent (void)
{
	const gchar* _tmp0_ = NULL;
	const gchar* _tmp1_;
	gchar* _tmp2_;
	gchar* result;
	_tmp1_ = dc_mentions_accent_override;
	_tmp0_ = _tmp1_;
	if (_tmp0_ == NULL) {
		_tmp0_ = DC_MENTIONS_DEFAULT_ACCENT;
	}
	_tmp2_ = g_strdup (_tmp0_);
	result = _tmp2_;
	return result;
}

/**
         * Locate every resolvable mention in `raw`, in order. Only tokens that
         * begin at the start of the text or right after whitespace are
         * considered.
         */
GPtrArray*
dc_mentions_find_mentions (const gchar* raw,
                           DcMentionRoster* roster)
{
	GPtrArray* spans = NULL;
	GPtrArray* _tmp0_;
	gint i = 0;
	gunichar c = 0U;
	gboolean prev_is_boundary = FALSE;
	GPtrArray* result;
	g_return_val_if_fail (raw != NULL, NULL);
	g_return_val_if_fail (roster != NULL, NULL);
	_tmp0_ = g_ptr_array_new_full ((guint) 0, _g_object_unref0_);
	spans = _tmp0_;
	i = 0;
	prev_is_boundary = TRUE;
	while (TRUE) {
		gint at = 0;
		gunichar _tmp1_ = 0U;
		gboolean _tmp2_;
		gboolean _tmp3_ = FALSE;
		at = i;
		_tmp2_ = string_get_next_char (raw, &i, &_tmp1_);
		c = _tmp1_;
		if (!_tmp2_) {
			break;
		}
		if (c == ((gunichar) '@')) {
			_tmp3_ = prev_is_boundary;
		} else {
			_tmp3_ = FALSE;
		}
		if (_tmp3_) {
			DcMentionSpan* span = NULL;
			DcMentionSpan* _tmp4_;
			DcMentionSpan* _tmp5_;
			_tmp4_ = dc_mention_roster_resolve_at (roster, raw, at);
			span = _tmp4_;
			_tmp5_ = span;
			if (_tmp5_ != NULL) {
				GPtrArray* _tmp6_;
				DcMentionSpan* _tmp7_;
				DcMentionSpan* _tmp8_;
				DcMentionSpan* _tmp9_;
				_tmp6_ = spans;
				_tmp7_ = span;
				_tmp8_ = _g_object_ref0 (_tmp7_);
				g_ptr_array_add (_tmp6_, _tmp8_);
				_tmp9_ = span;
				i = _tmp9_->end;
				prev_is_boundary = FALSE;
				_g_object_unref0 (span);
				continue;
			}
			_g_object_unref0 (span);
		}
		prev_is_boundary = g_unichar_isspace (c);
	}
	result = spans;
	return result;
}

/**
         * Render message body text to Pango markup with mentions turned into
         * clickable links. Mentions are protected with markdown-inert sentinels
         * so the existing Markdown.format pipeline (escaping, bold/italic,
         * tables, URL linkify) never touches them, then substituted back in.
         */
static gchar*
string_replace (const gchar* self,
                const gchar* old,
                const gchar* replacement)
{
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	GError* _inner_error0_ = NULL;
	gchar* result;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (old != NULL, NULL);
	g_return_val_if_fail (replacement != NULL, NULL);
	if ((*((gchar*) self)) == '\0') {
		_tmp1_ = TRUE;
	} else {
		_tmp1_ = (*((gchar*) old)) == '\0';
	}
	if (_tmp1_) {
		_tmp0_ = TRUE;
	} else {
		_tmp0_ = g_strcmp0 (old, replacement) == 0;
	}
	if (_tmp0_) {
		gchar* _tmp2_;
		_tmp2_ = g_strdup (self);
		result = _tmp2_;
		return result;
	}
	{
		GRegex* regex = NULL;
		gchar* _tmp3_;
		gchar* _tmp4_;
		GRegex* _tmp5_;
		GRegex* _tmp6_;
		gchar* _tmp7_ = NULL;
		GRegex* _tmp8_;
		gchar* _tmp9_;
		gchar* _tmp10_;
		_tmp3_ = g_regex_escape_string (old, -1);
		_tmp4_ = _tmp3_;
		_tmp5_ = g_regex_new (_tmp4_, 0, 0, &_inner_error0_);
		_tmp6_ = _tmp5_;
		_g_free0 (_tmp4_);
		regex = _tmp6_;
		if (G_UNLIKELY (_inner_error0_ != NULL)) {
			if (_inner_error0_->domain == G_REGEX_ERROR) {
				goto __catch0_g_regex_error;
			}
			g_critical ("file %s: line %d: unexpected error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return NULL;
		}
		_tmp8_ = regex;
		_tmp9_ = g_regex_replace_literal (_tmp8_, self, (gssize) -1, 0, replacement, 0, &_inner_error0_);
		_tmp7_ = _tmp9_;
		if (G_UNLIKELY (_inner_error0_ != NULL)) {
			_g_regex_unref0 (regex);
			if (_inner_error0_->domain == G_REGEX_ERROR) {
				goto __catch0_g_regex_error;
			}
			g_critical ("file %s: line %d: unexpected error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return NULL;
		}
		_tmp10_ = _tmp7_;
		_tmp7_ = NULL;
		result = _tmp10_;
		_g_free0 (_tmp7_);
		_g_regex_unref0 (regex);
		return result;
	}
	goto __finally0;
	__catch0_g_regex_error:
	{
		g_clear_error (&_inner_error0_);
		g_assert_not_reached ();
	}
	__finally0:
	g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
	g_clear_error (&_inner_error0_);
	return NULL;
}

gchar*
dc_mentions_render_markup (const gchar* raw,
                           DcMentionRoster* roster)
{
	GPtrArray* spans = NULL;
	GPtrArray* _tmp1_;
	GPtrArray* _tmp2_;
	gint _tmp3_;
	gint _tmp4_;
	GString* protected_text = NULL;
	GString* _tmp6_;
	GPtrArray* anchors = NULL;
	GPtrArray* _tmp7_;
	gint cursor = 0;
	gint _tmp33_;
	gint _tmp34_;
	gchar* markup = NULL;
	GString* _tmp38_;
	const gchar* _tmp39_;
	gchar* _tmp40_;
	gchar* result;
	g_return_val_if_fail (raw != NULL, NULL);
	if (roster == NULL) {
		gchar* _tmp0_;
		_tmp0_ = dc_markdown_format (raw);
		result = _tmp0_;
		return result;
	}
	_tmp1_ = dc_mentions_find_mentions (raw, roster);
	spans = _tmp1_;
	_tmp2_ = spans;
	_tmp3_ = vala_g_ptr_array_get_length (_tmp2_);
	_tmp4_ = _tmp3_;
	if (_tmp4_ == 0) {
		gchar* _tmp5_;
		_tmp5_ = dc_markdown_format (raw);
		result = _tmp5_;
		_g_ptr_array_unref0 (spans);
		return result;
	}
	_tmp6_ = g_string_new ("");
	protected_text = _tmp6_;
	_tmp7_ = g_ptr_array_new_full ((guint) 0, _g_free0_);
	anchors = _tmp7_;
	cursor = 0;
	{
		gint s = 0;
		s = 0;
		{
			gboolean _tmp8_ = FALSE;
			_tmp8_ = TRUE;
			while (TRUE) {
				GPtrArray* _tmp10_;
				gint _tmp11_;
				gint _tmp12_;
				DcMentionSpan* span = NULL;
				GPtrArray* _tmp13_;
				gconstpointer _tmp14_;
				DcMentionSpan* _tmp15_;
				DcMentionSpan* _tmp16_;
				gint idx = 0;
				GPtrArray* _tmp21_;
				gint _tmp22_;
				gint _tmp23_;
				GPtrArray* _tmp24_;
				DcMentionSpan* _tmp25_;
				gchar* _tmp26_;
				GString* _tmp27_;
				GString* _tmp28_;
				gchar* _tmp29_;
				gchar* _tmp30_;
				GString* _tmp31_;
				DcMentionSpan* _tmp32_;
				if (!_tmp8_) {
					gint _tmp9_;
					_tmp9_ = s;
					s = _tmp9_ + 1;
				}
				_tmp8_ = FALSE;
				_tmp10_ = spans;
				_tmp11_ = vala_g_ptr_array_get_length (_tmp10_);
				_tmp12_ = _tmp11_;
				if (!(s < _tmp12_)) {
					break;
				}
				_tmp13_ = spans;
				_tmp14_ = g_ptr_array_index (_tmp13_, (guint) s);
				_tmp15_ = _g_object_ref0 ((DcMentionSpan*) _tmp14_);
				span = _tmp15_;
				_tmp16_ = span;
				if (_tmp16_->start > cursor) {
					GString* _tmp17_;
					DcMentionSpan* _tmp18_;
					gchar* _tmp19_;
					gchar* _tmp20_;
					_tmp17_ = protected_text;
					_tmp18_ = span;
					_tmp19_ = string_substring (raw, (glong) cursor, (glong) (_tmp18_->start - cursor));
					_tmp20_ = _tmp19_;
					g_string_append (_tmp17_, _tmp20_);
					_g_free0 (_tmp20_);
				}
				_tmp21_ = anchors;
				_tmp22_ = vala_g_ptr_array_get_length (_tmp21_);
				_tmp23_ = _tmp22_;
				idx = _tmp23_;
				_tmp24_ = anchors;
				_tmp25_ = span;
				_tmp26_ = dc_mentions_anchor_markup (_tmp25_);
				g_ptr_array_add (_tmp24_, _tmp26_);
				_tmp27_ = protected_text;
				g_string_append (_tmp27_, DC_MENTIONS_SENTINEL);
				_tmp28_ = protected_text;
				_tmp29_ = g_strdup_printf ("%i", idx);
				_tmp30_ = _tmp29_;
				g_string_append (_tmp28_, _tmp30_);
				_g_free0 (_tmp30_);
				_tmp31_ = protected_text;
				g_string_append (_tmp31_, DC_MENTIONS_SENTINEL);
				_tmp32_ = span;
				cursor = _tmp32_->end;
				_g_object_unref0 (span);
			}
		}
	}
	_tmp33_ = strlen (raw);
	_tmp34_ = _tmp33_;
	if (cursor < _tmp34_) {
		GString* _tmp35_;
		gchar* _tmp36_;
		gchar* _tmp37_;
		_tmp35_ = protected_text;
		_tmp36_ = string_substring (raw, (glong) cursor, (glong) -1);
		_tmp37_ = _tmp36_;
		g_string_append (_tmp35_, _tmp37_);
		_g_free0 (_tmp37_);
	}
	_tmp38_ = protected_text;
	_tmp39_ = _tmp38_->str;
	_tmp40_ = dc_markdown_format (_tmp39_);
	markup = _tmp40_;
	{
		gint a = 0;
		a = 0;
		{
			gboolean _tmp41_ = FALSE;
			_tmp41_ = TRUE;
			while (TRUE) {
				GPtrArray* _tmp43_;
				gint _tmp44_;
				gint _tmp45_;
				const gchar* _tmp46_;
				gchar* _tmp47_;
				gchar* _tmp48_;
				gchar* _tmp49_;
				gchar* _tmp50_;
				gchar* _tmp51_;
				gchar* _tmp52_;
				GPtrArray* _tmp53_;
				gconstpointer _tmp54_;
				gchar* _tmp55_;
				if (!_tmp41_) {
					gint _tmp42_;
					_tmp42_ = a;
					a = _tmp42_ + 1;
				}
				_tmp41_ = FALSE;
				_tmp43_ = anchors;
				_tmp44_ = vala_g_ptr_array_get_length (_tmp43_);
				_tmp45_ = _tmp44_;
				if (!(a < _tmp45_)) {
					break;
				}
				_tmp46_ = markup;
				_tmp47_ = g_strdup_printf ("%i", a);
				_tmp48_ = _tmp47_;
				_tmp49_ = g_strconcat (DC_MENTIONS_SENTINEL, _tmp48_, NULL);
				_tmp50_ = _tmp49_;
				_tmp51_ = g_strconcat (_tmp50_, DC_MENTIONS_SENTINEL, NULL);
				_tmp52_ = _tmp51_;
				_tmp53_ = anchors;
				_tmp54_ = g_ptr_array_index (_tmp53_, (guint) a);
				_tmp55_ = string_replace (_tmp46_, _tmp52_, (const gchar*) _tmp54_);
				_g_free0 (markup);
				markup = _tmp55_;
				_g_free0 (_tmp52_);
				_g_free0 (_tmp50_);
				_g_free0 (_tmp48_);
			}
		}
	}
	result = markup;
	_g_ptr_array_unref0 (anchors);
	_g_string_free0 (protected_text);
	_g_ptr_array_unref0 (spans);
	return result;
}

static gchar*
dc_mentions_anchor_markup (DcMentionSpan* span)
{
	gchar* href = NULL;
	const gchar* _tmp0_;
	gchar* _tmp1_;
	gchar* label = NULL;
	const gchar* _tmp2_;
	gchar* _tmp3_;
	gchar* _tmp4_;
	gchar* _tmp5_;
	gchar* _tmp6_;
	const gchar* _tmp15_;
	const gchar* _tmp16_;
	gchar* _tmp17_;
	gchar* result;
	g_return_val_if_fail (span != NULL, NULL);
	_tmp0_ = span->href;
	_tmp1_ = g_markup_escape_text (_tmp0_, (gssize) -1);
	href = _tmp1_;
	_tmp2_ = span->display;
	_tmp3_ = g_strconcat ("@", _tmp2_, NULL);
	_tmp4_ = _tmp3_;
	_tmp5_ = g_markup_escape_text (_tmp4_, (gssize) -1);
	_tmp6_ = _tmp5_;
	_g_free0 (_tmp4_);
	label = _tmp6_;
	if (span->is_self) {
		const gchar* _tmp7_;
		gchar* _tmp8_;
		gchar* _tmp9_;
		gchar* _tmp10_;
		gchar* _tmp11_;
		const gchar* _tmp12_;
		gchar* _tmp13_;
		gchar* _tmp14_;
		_tmp7_ = href;
		_tmp8_ = dc_mentions_accent ();
		_tmp9_ = _tmp8_;
		_tmp10_ = g_markup_escape_text (_tmp9_, (gssize) -1);
		_tmp11_ = _tmp10_;
		_tmp12_ = label;
		_tmp13_ = g_strdup_printf ("<a href=\"%s\"><span background=\"%s\" " "bgalpha=\"35%%\"><b>%s</b></span></a>", _tmp7_, _tmp11_, _tmp12_);
		_tmp14_ = _tmp13_;
		_g_free0 (_tmp11_);
		_g_free0 (_tmp9_);
		result = _tmp14_;
		_g_free0 (label);
		_g_free0 (href);
		return result;
	}
	_tmp15_ = href;
	_tmp16_ = label;
	_tmp17_ = g_strdup_printf ("<a href=\"%s\"><b>%s</b></a>", _tmp15_, _tmp16_);
	result = _tmp17_;
	_g_free0 (label);
	_g_free0 (href);
	return result;
}

/**
         * True when `raw` contains a mention of the local user that `roster`
         * can resolve. Used to tint the bubble of a message that mentions you.
         */
gboolean
dc_mentions_has_self_mention (const gchar* raw,
                              DcMentionRoster* roster)
{
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	GPtrArray* spans = NULL;
	GPtrArray* _tmp4_;
	gboolean result;
	if (raw == NULL) {
		_tmp1_ = TRUE;
	} else {
		gint _tmp2_;
		gint _tmp3_;
		_tmp2_ = strlen (raw);
		_tmp3_ = _tmp2_;
		_tmp1_ = _tmp3_ == 0;
	}
	if (_tmp1_) {
		_tmp0_ = TRUE;
	} else {
		_tmp0_ = roster == NULL;
	}
	if (_tmp0_) {
		result = FALSE;
		return result;
	}
	_tmp4_ = dc_mentions_find_mentions (raw, roster);
	spans = _tmp4_;
	{
		gint i = 0;
		i = 0;
		{
			gboolean _tmp5_ = FALSE;
			_tmp5_ = TRUE;
			while (TRUE) {
				GPtrArray* _tmp7_;
				gint _tmp8_;
				gint _tmp9_;
				GPtrArray* _tmp10_;
				gconstpointer _tmp11_;
				if (!_tmp5_) {
					gint _tmp6_;
					_tmp6_ = i;
					i = _tmp6_ + 1;
				}
				_tmp5_ = FALSE;
				_tmp7_ = spans;
				_tmp8_ = vala_g_ptr_array_get_length (_tmp7_);
				_tmp9_ = _tmp8_;
				if (!(i < _tmp9_)) {
					break;
				}
				_tmp10_ = spans;
				_tmp11_ = g_ptr_array_index (_tmp10_, (guint) i);
				if (((DcMentionSpan*) _tmp11_)->is_self) {
					result = TRUE;
					_g_ptr_array_unref0 (spans);
					return result;
				}
			}
		}
	}
	result = FALSE;
	_g_ptr_array_unref0 (spans);
	return result;
}

/**
         * True when `text` mentions the local user. `self_keys` are down-cased
         * identifiers (display name and/or transport addresses). Independent of
         * a roster so it can run on notifications for any account.
         */
gboolean
dc_mentions_mentions_self (const gchar* text,
                           gchar** self_keys,
                           gint self_keys_length1)
{
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	gint i = 0;
	gunichar c = 0U;
	gboolean prev_is_boundary = FALSE;
	gboolean result;
	if (text == NULL) {
		_tmp1_ = TRUE;
	} else {
		gint _tmp2_;
		gint _tmp3_;
		_tmp2_ = strlen (text);
		_tmp3_ = _tmp2_;
		_tmp1_ = _tmp3_ == 0;
	}
	if (_tmp1_) {
		_tmp0_ = TRUE;
	} else {
		_tmp0_ = self_keys_length1 == 0;
	}
	if (_tmp0_) {
		result = FALSE;
		return result;
	}
	i = 0;
	prev_is_boundary = TRUE;
	while (TRUE) {
		gint at = 0;
		gunichar _tmp4_ = 0U;
		gboolean _tmp5_;
		gboolean _tmp6_ = FALSE;
		at = i;
		_tmp5_ = string_get_next_char (text, &i, &_tmp4_);
		c = _tmp4_;
		if (!_tmp5_) {
			break;
		}
		if (c == ((gunichar) '@')) {
			_tmp6_ = prev_is_boundary;
		} else {
			_tmp6_ = FALSE;
		}
		if (_tmp6_) {
			if (dc_mentions_matches_self_key_at (text, at + 1, self_keys, (gint) self_keys_length1)) {
				result = TRUE;
				return result;
			}
		}
		prev_is_boundary = g_unichar_isspace (c);
	}
	result = FALSE;
	return result;
}

static gboolean
dc_mentions_matches_self_key_at (const gchar* text,
                                 gint after,
                                 gchar** self_keys,
                                 gint self_keys_length1)
{
	gint _tmp0_;
	gint _tmp1_;
	gchar* rest = NULL;
	gchar* _tmp2_;
	gchar* _tmp3_;
	gchar* _tmp4_;
	gchar* _tmp5_;
	gboolean result;
	g_return_val_if_fail (text != NULL, FALSE);
	_tmp0_ = strlen (text);
	_tmp1_ = _tmp0_;
	if (after > _tmp1_) {
		result = FALSE;
		return result;
	}
	_tmp2_ = string_substring (text, (glong) after, (glong) -1);
	_tmp3_ = _tmp2_;
	_tmp4_ = g_utf8_strdown (_tmp3_, (gssize) -1);
	_tmp5_ = _tmp4_;
	_g_free0 (_tmp3_);
	rest = _tmp5_;
	{
		gchar** key_collection = NULL;
		gint key_collection_length1 = 0;
		gint _key_collection_size_ = 0;
		gint key_it = 0;
		key_collection = self_keys;
		key_collection_length1 = self_keys_length1;
		for (key_it = 0; key_it < key_collection_length1; key_it = key_it + 1) {
			gchar* _tmp6_;
			gchar* key = NULL;
			_tmp6_ = g_strdup (key_collection[key_it]);
			key = _tmp6_;
			{
				const gchar* _tmp7_;
				gint _tmp8_;
				gint _tmp9_;
				const gchar* _tmp10_;
				const gchar* _tmp11_;
				gint end = 0;
				const gchar* _tmp12_;
				gint _tmp13_;
				gint _tmp14_;
				const gchar* _tmp15_;
				gint _tmp16_;
				gint _tmp17_;
				gunichar c = 0U;
				gint idx = 0;
				const gchar* _tmp18_;
				gunichar _tmp19_ = 0U;
				gboolean _tmp20_;
				const gchar* _tmp21_;
				_tmp7_ = key;
				_tmp8_ = strlen (_tmp7_);
				_tmp9_ = _tmp8_;
				if (_tmp9_ == 0) {
					_g_free0 (key);
					continue;
				}
				_tmp10_ = rest;
				_tmp11_ = key;
				if (!g_str_has_prefix (_tmp10_, _tmp11_)) {
					_g_free0 (key);
					continue;
				}
				_tmp12_ = key;
				_tmp13_ = strlen (_tmp12_);
				_tmp14_ = _tmp13_;
				end = _tmp14_;
				_tmp15_ = rest;
				_tmp16_ = strlen (_tmp15_);
				_tmp17_ = _tmp16_;
				if (end >= _tmp17_) {
					result = TRUE;
					_g_free0 (key);
					_g_free0 (rest);
					return result;
				}
				idx = end;
				_tmp18_ = rest;
				_tmp20_ = string_get_next_char (_tmp18_, &idx, &_tmp19_);
				c = _tmp19_;
				if (!_tmp20_) {
					result = TRUE;
					_g_free0 (key);
					_g_free0 (rest);
					return result;
				}
				_tmp21_ = key;
				if (string_contains (_tmp21_, "@")) {
					gboolean _tmp22_ = FALSE;
					if (g_unichar_isspace (c)) {
						_tmp22_ = TRUE;
					} else {
						_tmp22_ = dc_mentions_is_addr_terminator (c);
					}
					if (_tmp22_) {
						result = TRUE;
						_g_free0 (key);
						_g_free0 (rest);
						return result;
					}
				} else {
					const gchar* _tmp23_;
					_tmp23_ = rest;
					if (dc_mention_roster_boundary_after (_tmp23_, end)) {
						result = TRUE;
						_g_free0 (key);
						_g_free0 (rest);
						return result;
					}
				}
				_g_free0 (key);
			}
		}
	}
	result = FALSE;
	_g_free0 (rest);
	return result;
}

static gboolean
dc_mentions_is_addr_terminator (gunichar c)
{
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	gboolean _tmp2_ = FALSE;
	gboolean _tmp3_ = FALSE;
	gboolean _tmp4_ = FALSE;
	gboolean _tmp5_ = FALSE;
	gboolean _tmp6_ = FALSE;
	gboolean _tmp7_ = FALSE;
	gboolean _tmp8_ = FALSE;
	gboolean result;
	if (c == ((gunichar) ',')) {
		_tmp8_ = TRUE;
	} else {
		_tmp8_ = c == ((gunichar) ';');
	}
	if (_tmp8_) {
		_tmp7_ = TRUE;
	} else {
		_tmp7_ = c == ((gunichar) ':');
	}
	if (_tmp7_) {
		_tmp6_ = TRUE;
	} else {
		_tmp6_ = c == ((gunichar) '!');
	}
	if (_tmp6_) {
		_tmp5_ = TRUE;
	} else {
		_tmp5_ = c == ((gunichar) '?');
	}
	if (_tmp5_) {
		_tmp4_ = TRUE;
	} else {
		_tmp4_ = c == ((gunichar) ')');
	}
	if (_tmp4_) {
		_tmp3_ = TRUE;
	} else {
		_tmp3_ = c == ((gunichar) ']');
	}
	if (_tmp3_) {
		_tmp2_ = TRUE;
	} else {
		_tmp2_ = c == ((gunichar) '}');
	}
	if (_tmp2_) {
		_tmp1_ = TRUE;
	} else {
		_tmp1_ = c == ((gunichar) '"');
	}
	if (_tmp1_) {
		_tmp0_ = TRUE;
	} else {
		_tmp0_ = c == ((gunichar) '\'');
	}
	result = _tmp0_;
	return result;
}

DcMentions*
dc_mentions_construct (GType object_type)
{
	DcMentions* self = NULL;
	self = (DcMentions*) g_type_create_instance (object_type);
	return self;
}

DcMentions*
dc_mentions_new (void)
{
	return dc_mentions_construct (DC_TYPE_MENTIONS);
}

static void
dc_value_mentions_init (GValue* value)
{
	value->data[0].v_pointer = NULL;
}

static void
dc_value_mentions_free_value (GValue* value)
{
	if (value->data[0].v_pointer) {
		dc_mentions_unref (value->data[0].v_pointer);
	}
}

static void
dc_value_mentions_copy_value (const GValue* src_value,
                              GValue* dest_value)
{
	if (src_value->data[0].v_pointer) {
		dest_value->data[0].v_pointer = dc_mentions_ref (src_value->data[0].v_pointer);
	} else {
		dest_value->data[0].v_pointer = NULL;
	}
}

static gpointer
dc_value_mentions_peek_pointer (const GValue* value)
{
	return value->data[0].v_pointer;
}

static gchar*
dc_value_mentions_collect_value (GValue* value,
                                 guint n_collect_values,
                                 GTypeCValue* collect_values,
                                 guint collect_flags)
{
	if (collect_values[0].v_pointer) {
		DcMentions * object;
		object = collect_values[0].v_pointer;
		if (object->parent_instance.g_class == NULL) {
			return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
		} else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) {
			return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
		}
		value->data[0].v_pointer = dc_mentions_ref (object);
	} else {
		value->data[0].v_pointer = NULL;
	}
	return NULL;
}

static gchar*
dc_value_mentions_lcopy_value (const GValue* value,
                               guint n_collect_values,
                               GTypeCValue* collect_values,
                               guint collect_flags)
{
	DcMentions ** object_p;
	object_p = collect_values[0].v_pointer;
	if (!object_p) {
		return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
	}
	if (!value->data[0].v_pointer) {
		*object_p = NULL;
	} else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
		*object_p = value->data[0].v_pointer;
	} else {
		*object_p = dc_mentions_ref (value->data[0].v_pointer);
	}
	return NULL;
}

GParamSpec*
dc_param_spec_mentions (const gchar* name,
                        const gchar* nick,
                        const gchar* blurb,
                        GType object_type,
                        GParamFlags flags)
{
	DcParamSpecMentions* spec;
	g_return_val_if_fail (g_type_is_a (object_type, DC_TYPE_MENTIONS), NULL);
	spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags);
	G_PARAM_SPEC (spec)->value_type = object_type;
	return G_PARAM_SPEC (spec);
}

gpointer
dc_value_get_mentions (const GValue* value)
{
	g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, DC_TYPE_MENTIONS), NULL);
	return value->data[0].v_pointer;
}

void
dc_value_set_mentions (GValue* value,
                       gpointer v_object)
{
	DcMentions * old;
	g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, DC_TYPE_MENTIONS));
	old = value->data[0].v_pointer;
	if (v_object) {
		g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, DC_TYPE_MENTIONS));
		g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
		value->data[0].v_pointer = v_object;
		dc_mentions_ref (value->data[0].v_pointer);
	} else {
		value->data[0].v_pointer = NULL;
	}
	if (old) {
		dc_mentions_unref (old);
	}
}

void
dc_value_take_mentions (GValue* value,
                        gpointer v_object)
{
	DcMentions * old;
	g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, DC_TYPE_MENTIONS));
	old = value->data[0].v_pointer;
	if (v_object) {
		g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, DC_TYPE_MENTIONS));
		g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
		value->data[0].v_pointer = v_object;
	} else {
		value->data[0].v_pointer = NULL;
	}
	if (old) {
		dc_mentions_unref (old);
	}
}

static void
dc_mentions_class_init (DcMentionsClass * klass,
                        gpointer klass_data)
{
	dc_mentions_parent_class = g_type_class_peek_parent (klass);
	((DcMentionsClass *) klass)->finalize = dc_mentions_finalize;
}

static void
dc_mentions_instance_init (DcMentions * self,
                           gpointer klass)
{
	self->ref_count = 1;
}

static void
dc_mentions_finalize (DcMentions * obj)
{
	DcMentions * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, DC_TYPE_MENTIONS, DcMentions);
	g_signal_handlers_destroy (self);
}

static GType
dc_mentions_get_type_once (void)
{
	static const GTypeValueTable g_define_type_value_table = { dc_value_mentions_init, dc_value_mentions_free_value, dc_value_mentions_copy_value, dc_value_mentions_peek_pointer, "p", dc_value_mentions_collect_value, "p", dc_value_mentions_lcopy_value };
	static const GTypeInfo g_define_type_info = { sizeof (DcMentionsClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) dc_mentions_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (DcMentions), 0, (GInstanceInitFunc) dc_mentions_instance_init, &g_define_type_value_table };
	static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) };
	GType dc_mentions_type_id;
	dc_mentions_type_id = g_type_register_fundamental (g_type_fundamental_next (), "DcMentions", &g_define_type_info, &g_define_type_fundamental_info, 0);
	return dc_mentions_type_id;
}

GType
dc_mentions_get_type (void)
{
	static volatile gsize dc_mentions_type_id__once = 0;
	if (g_once_init_enter (&dc_mentions_type_id__once)) {
		GType dc_mentions_type_id;
		dc_mentions_type_id = dc_mentions_get_type_once ();
		g_once_init_leave (&dc_mentions_type_id__once, dc_mentions_type_id);
	}
	return dc_mentions_type_id__once;
}

gpointer
dc_mentions_ref (gpointer instance)
{
	DcMentions * self;
	self = instance;
	g_atomic_int_inc (&self->ref_count);
	return instance;
}

void
dc_mentions_unref (gpointer instance)
{
	DcMentions * self;
	self = instance;
	if (g_atomic_int_dec_and_test (&self->ref_count)) {
		DC_MENTIONS_GET_CLASS (self)->finalize (self);
		g_type_free_instance ((GTypeInstance *) self);
	}
}

static inline gpointer
_vala_memdup2 (gconstpointer mem,
               gsize byte_size)
{
	gpointer new_mem;
	if (mem && byte_size != 0) {
		new_mem = g_malloc (byte_size);
		memcpy (new_mem, mem, byte_size);
	} else {
		new_mem = NULL;
	}
	return new_mem;
}

