Blame src/ibusemoji.c

Packit Service 1d8f1c
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
Packit Service 1d8f1c
/* vim:set et sts=4: */
Packit Service 1d8f1c
/* bus - The Input Bus
Packit Service 1d8f1c
 * Copyright (C) 2017 Takao Fujiwara <takao.fujiwara1@gmail.com>
Packit Service 1d8f1c
 * Copyright (C) 2017 Red Hat, Inc.
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * This library is free software; you can redistribute it and/or
Packit Service 1d8f1c
 * modify it under the terms of the GNU Lesser General Public
Packit Service 1d8f1c
 * License as published by the Free Software Foundation; either
Packit Service 1d8f1c
 * version 2.1 of the License, or (at your option) any later version.
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * This library is distributed in the hope that it will be useful,
Packit Service 1d8f1c
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 1d8f1c
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 1d8f1c
 * Lesser General Public License for more details.
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * You should have received a copy of the GNU Lesser General Public
Packit Service 1d8f1c
 * License along with this library; if not, write to the Free Software
Packit Service 1d8f1c
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
Packit Service 1d8f1c
 * USA
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
#ifdef HAVE_CONFIG_H
Packit Service 1d8f1c
#include <config.h>
Packit Service 1d8f1c
#endif
Packit Service 1d8f1c
Packit Service 1d8f1c
#include <glib.h>
Packit Service 1d8f1c
#include <glib/gstdio.h>
Packit Service 1d8f1c
#include "ibusemoji.h"
Packit Service 1d8f1c
#include "ibusinternal.h"
Packit Service 1d8f1c
Packit Service 1d8f1c
#define IBUS_EMOJI_DATA_MAGIC "IBusEmojiData"
Packit Service 1d8f1c
#define IBUS_EMOJI_DATA_VERSION (5)
Packit Service 1d8f1c
Packit Service 1d8f1c
enum {
Packit Service 1d8f1c
    PROP_0 = 0,
Packit Service 1d8f1c
    PROP_EMOJI,
Packit Service 1d8f1c
    PROP_ANNOTATIONS,
Packit Service 1d8f1c
    PROP_DESCRIPTION,
Packit Service 1d8f1c
    PROP_CATEGORY,
Packit Service 1d8f1c
};
Packit Service 1d8f1c
Packit Service 1d8f1c
struct _IBusEmojiDataPrivate {
Packit Service 1d8f1c
    gchar      *emoji;
Packit Service 1d8f1c
    GSList     *annotations;
Packit Service 1d8f1c
    gchar      *description;
Packit Service 1d8f1c
    gchar      *category;
Packit Service 1d8f1c
};
Packit Service 1d8f1c
Packit Service 1d8f1c
#define IBUS_EMOJI_DATA_GET_PRIVATE(o)  \
Packit Service 1d8f1c
   (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
Packit Service 1d8f1c
    IBUS_TYPE_EMOJI_DATA, \
Packit Service 1d8f1c
    IBusEmojiDataPrivate))
Packit Service 1d8f1c
Packit Service 1d8f1c
/* functions prototype */
Packit Service 1d8f1c
static void      ibus_emoji_data_set_property  (IBusEmojiData       *emoji,
Packit Service 1d8f1c
                                                guint                prop_id,
Packit Service 1d8f1c
                                                const GValue        *value,
Packit Service 1d8f1c
                                                GParamSpec          *pspec);
Packit Service 1d8f1c
static void      ibus_emoji_data_get_property  (IBusEmojiData       *emoji,
Packit Service 1d8f1c
                                                guint                prop_id,
Packit Service 1d8f1c
                                                GValue              *value,
Packit Service 1d8f1c
                                                GParamSpec          *pspec);
Packit Service 1d8f1c
static void      ibus_emoji_data_destroy       (IBusEmojiData       *emoji);
Packit Service 1d8f1c
static gboolean  ibus_emoji_data_serialize     (IBusEmojiData       *emoji,
Packit Service 1d8f1c
                                                GVariantBuilder     *builder);
Packit Service 1d8f1c
static gint      ibus_emoji_data_deserialize   (IBusEmojiData       *emoji,
Packit Service 1d8f1c
                                                GVariant            *variant);
Packit Service 1d8f1c
static gboolean  ibus_emoji_data_copy          (IBusEmojiData       *emoji,
Packit Service 1d8f1c
                                                const IBusEmojiData *src);
Packit Service 1d8f1c
Packit Service 1d8f1c
G_DEFINE_TYPE (IBusEmojiData, ibus_emoji_data, IBUS_TYPE_SERIALIZABLE)
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
ibus_emoji_data_class_init (IBusEmojiDataClass *class)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    IBusObjectClass *object_class = IBUS_OBJECT_CLASS (class);
Packit Service 1d8f1c
    GObjectClass *gobject_class = G_OBJECT_CLASS (class);
Packit Service 1d8f1c
    IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (class);
Packit Service 1d8f1c
Packit Service 1d8f1c
    object_class->destroy = (IBusObjectDestroyFunc) ibus_emoji_data_destroy;
Packit Service 1d8f1c
    gobject_class->set_property =
Packit Service 1d8f1c
            (GObjectSetPropertyFunc) ibus_emoji_data_set_property;
Packit Service 1d8f1c
    gobject_class->get_property =
Packit Service 1d8f1c
            (GObjectGetPropertyFunc) ibus_emoji_data_get_property;
Packit Service 1d8f1c
    serializable_class->serialize   =
Packit Service 1d8f1c
            (IBusSerializableSerializeFunc) ibus_emoji_data_serialize;
Packit Service 1d8f1c
    serializable_class->deserialize =
Packit Service 1d8f1c
            (IBusSerializableDeserializeFunc) ibus_emoji_data_deserialize;
Packit Service 1d8f1c
    serializable_class->copy        =
Packit Service 1d8f1c
            (IBusSerializableCopyFunc) ibus_emoji_data_copy;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_type_class_add_private (class, sizeof (IBusEmojiDataPrivate));
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* install properties */
Packit Service 1d8f1c
    /**
Packit Service 1d8f1c
     * IBusEmojiData:emoji:
Packit Service 1d8f1c
     *
Packit Service 1d8f1c
     * The emoji character
Packit Service 1d8f1c
     */
Packit Service 1d8f1c
    g_object_class_install_property (gobject_class,
Packit Service 1d8f1c
                    PROP_EMOJI,
Packit Service 1d8f1c
                    g_param_spec_string ("emoji",
Packit Service 1d8f1c
                        "emoji character",
Packit Service 1d8f1c
                        "The emoji character UTF-8",
Packit Service 1d8f1c
                        NULL,
Packit Service 1d8f1c
                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
Packit Service 1d8f1c
Packit Service 1d8f1c
    /**
Packit Service 1d8f1c
     * IBusEmojiData:annotations: (transfer container) (element-type utf8):
Packit Service 1d8f1c
     *
Packit Service 1d8f1c
     * The emoji annotations
Packit Service 1d8f1c
     */
Packit Service 1d8f1c
    g_object_class_install_property (gobject_class,
Packit Service 1d8f1c
                    PROP_ANNOTATIONS,
Packit Service 1d8f1c
                    g_param_spec_pointer ("annotations",
Packit Service 1d8f1c
                        "emoji annotations",
Packit Service 1d8f1c
                        "The emoji annotation list",
Packit Service 1d8f1c
                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
Packit Service 1d8f1c
Packit Service 1d8f1c
    /**
Packit Service 1d8f1c
     * IBusEmojiData:description:
Packit Service 1d8f1c
     *
Packit Service 1d8f1c
     * The emoji description
Packit Service 1d8f1c
     */
Packit Service 1d8f1c
    g_object_class_install_property (gobject_class,
Packit Service 1d8f1c
                    PROP_DESCRIPTION,
Packit Service 1d8f1c
                    g_param_spec_string ("description",
Packit Service 1d8f1c
                        "emoji description",
Packit Service 1d8f1c
                        "The emoji description",
Packit Service 1d8f1c
                        "",
Packit Service 1d8f1c
                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
Packit Service 1d8f1c
Packit Service 1d8f1c
    /**
Packit Service 1d8f1c
     * IBusEmojiData:category:
Packit Service 1d8f1c
     *
Packit Service 1d8f1c
     * The emoji category
Packit Service 1d8f1c
     */
Packit Service 1d8f1c
    g_object_class_install_property (gobject_class,
Packit Service 1d8f1c
                    PROP_CATEGORY,
Packit Service 1d8f1c
                    g_param_spec_string ("category",
Packit Service 1d8f1c
                        "emoji category",
Packit Service 1d8f1c
                        "The emoji category",
Packit Service 1d8f1c
                        "",
Packit Service 1d8f1c
                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
ibus_emoji_data_init (IBusEmojiData *emoji)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    emoji->priv = IBUS_EMOJI_DATA_GET_PRIVATE (emoji);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
free_dict_words (gpointer list)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_slist_free_full (list, g_free);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
ibus_emoji_data_destroy (IBusEmojiData *emoji)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_clear_pointer (&emoji->priv->emoji, g_free);
Packit Service 1d8f1c
    g_clear_pointer (&emoji->priv->annotations, free_dict_words);
Packit Service 1d8f1c
    g_clear_pointer (&emoji->priv->description, g_free);
Packit Service 1d8f1c
    g_clear_pointer (&emoji->priv->category, g_free);
Packit Service 1d8f1c
Packit Service 1d8f1c
    IBUS_OBJECT_CLASS (ibus_emoji_data_parent_class)->
Packit Service 1d8f1c
            destroy (IBUS_OBJECT (emoji));
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
ibus_emoji_data_set_property (IBusEmojiData *emoji,
Packit Service 1d8f1c
                              guint          prop_id,
Packit Service 1d8f1c
                              const GValue  *value,
Packit Service 1d8f1c
                              GParamSpec    *pspec)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    switch (prop_id) {
Packit Service 1d8f1c
    case PROP_EMOJI:
Packit Service 1d8f1c
        g_assert (emoji->priv->emoji == NULL);
Packit Service 1d8f1c
        emoji->priv->emoji = g_value_dup_string (value);
Packit Service 1d8f1c
        break;
Packit Service 1d8f1c
    case PROP_ANNOTATIONS:
Packit Service 1d8f1c
        if (emoji->priv->annotations)
Packit Service 1d8f1c
            g_slist_free_full (emoji->priv->annotations, g_free);
Packit Service 1d8f1c
        emoji->priv->annotations =
Packit Service 1d8f1c
                g_slist_copy_deep (g_value_get_pointer (value),
Packit Service 1d8f1c
                                   (GCopyFunc) g_strdup, NULL);
Packit Service 1d8f1c
        break;
Packit Service 1d8f1c
    case PROP_DESCRIPTION:
Packit Service 1d8f1c
        g_free (emoji->priv->description);
Packit Service 1d8f1c
        emoji->priv->description = g_value_dup_string (value);
Packit Service 1d8f1c
        break;
Packit Service 1d8f1c
    case PROP_CATEGORY:
Packit Service 1d8f1c
        g_assert (emoji->priv->category == NULL);
Packit Service 1d8f1c
        emoji->priv->category = g_value_dup_string (value);
Packit Service 1d8f1c
        break;
Packit Service 1d8f1c
    default:
Packit Service 1d8f1c
        G_OBJECT_WARN_INVALID_PROPERTY_ID (emoji, prop_id, pspec);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
ibus_emoji_data_get_property (IBusEmojiData *emoji,
Packit Service 1d8f1c
                              guint          prop_id,
Packit Service 1d8f1c
                              GValue        *value,
Packit Service 1d8f1c
                              GParamSpec    *pspec)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    switch (prop_id) {
Packit Service 1d8f1c
    case PROP_EMOJI:
Packit Service 1d8f1c
        g_value_set_string (value, ibus_emoji_data_get_emoji (emoji));
Packit Service 1d8f1c
        break;
Packit Service 1d8f1c
    case PROP_ANNOTATIONS:
Packit Service 1d8f1c
        g_value_set_pointer (
Packit Service 1d8f1c
                value,
Packit Service 1d8f1c
                g_slist_copy_deep (ibus_emoji_data_get_annotations (emoji),
Packit Service 1d8f1c
                                   (GCopyFunc) g_strdup, NULL));
Packit Service 1d8f1c
        break;
Packit Service 1d8f1c
    case PROP_DESCRIPTION:
Packit Service 1d8f1c
        g_value_set_string (value, ibus_emoji_data_get_description (emoji));
Packit Service 1d8f1c
        break;
Packit Service 1d8f1c
    case PROP_CATEGORY:
Packit Service 1d8f1c
        g_value_set_string (value, ibus_emoji_data_get_category (emoji));
Packit Service 1d8f1c
        break;
Packit Service 1d8f1c
    default:
Packit Service 1d8f1c
        G_OBJECT_WARN_INVALID_PROPERTY_ID (emoji, prop_id, pspec);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
ibus_emoji_data_serialize (IBusEmojiData   *emoji,
Packit Service 1d8f1c
                           GVariantBuilder *builder)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GSList *l;
Packit Service 1d8f1c
    gboolean retval = IBUS_SERIALIZABLE_CLASS (ibus_emoji_data_parent_class)->
Packit Service 1d8f1c
            serialize ((IBusSerializable *)emoji, builder);
Packit Service 1d8f1c
    g_return_val_if_fail (retval, FALSE);
Packit Service 1d8f1c
Packit Service 1d8f1c
#define NOTNULL(s) ((s) != NULL ? (s) : "")
Packit Service 1d8f1c
    /* If you will add a new property, you can append it at the end and
Packit Service 1d8f1c
     * you should not change the serialized order of name, longname,
Packit Service 1d8f1c
     * description, ... because the order is also used in other applications
Packit Service 1d8f1c
     * likes ibus-qt. */
Packit Service 1d8f1c
    g_variant_builder_add (builder, "s", NOTNULL (emoji->priv->emoji));
Packit Service 1d8f1c
    g_variant_builder_add (builder, "u",
Packit Service 1d8f1c
                           g_slist_length (emoji->priv->annotations));
Packit Service 1d8f1c
    for (l = emoji->priv->annotations; l != NULL; l = l->next) {
Packit Service 1d8f1c
        g_variant_builder_add (builder, "s", NOTNULL (l->data));
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    g_variant_builder_add (builder, "s", NOTNULL (emoji->priv->description));
Packit Service 1d8f1c
    g_variant_builder_add (builder, "s", NOTNULL (emoji->priv->category));
Packit Service 1d8f1c
#undef NOTNULL
Packit Service 1d8f1c
    return TRUE;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gint
Packit Service 1d8f1c
ibus_emoji_data_deserialize (IBusEmojiData *emoji,
Packit Service 1d8f1c
                             GVariant      *variant)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    guint length, i;
Packit Service 1d8f1c
    GSList *annotations = NULL;
Packit Service 1d8f1c
    gint retval = IBUS_SERIALIZABLE_CLASS (ibus_emoji_data_parent_class)->
Packit Service 1d8f1c
            deserialize ((IBusSerializable *)emoji, variant);
Packit Service 1d8f1c
    g_return_val_if_fail (retval, 0);
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* If you will add a new property, you can append it at the end and
Packit Service 1d8f1c
     * you should not change the serialized order of name, longname,
Packit Service 1d8f1c
     * description, ... because the order is also used in other applications
Packit Service 1d8f1c
     * likes ibus-qt. */
Packit Service 1d8f1c
    ibus_g_variant_get_child_string (variant, retval++,
Packit Service 1d8f1c
                                     &emoji->priv->emoji);
Packit Service 1d8f1c
    g_variant_get_child (variant, retval++, "u", &length);
Packit Service 1d8f1c
    for (i = 0; i < length; i++) {
Packit Service 1d8f1c
        gchar *s = NULL;
Packit Service 1d8f1c
        g_variant_get_child (variant, retval++, "s", &s);
Packit Service 1d8f1c
        annotations = g_slist_append (annotations, s);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    emoji->priv->annotations = annotations;
Packit Service 1d8f1c
    ibus_g_variant_get_child_string (variant, retval++,
Packit Service 1d8f1c
                                     &emoji->priv->description);
Packit Service 1d8f1c
    ibus_g_variant_get_child_string (variant, retval++,
Packit Service 1d8f1c
                                     &emoji->priv->category);
Packit Service 1d8f1c
    return retval;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
ibus_emoji_data_copy (IBusEmojiData       *dest,
Packit Service 1d8f1c
                      const IBusEmojiData *src)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    gboolean retval = IBUS_SERIALIZABLE_CLASS (ibus_emoji_data_parent_class)->
Packit Service 1d8f1c
            copy ((IBusSerializable *)dest,
Packit Service 1d8f1c
                  (IBusSerializable *)src);
Packit Service 1d8f1c
    g_return_val_if_fail (retval, FALSE);
Packit Service 1d8f1c
Packit Service 1d8f1c
    dest->priv->emoji            = g_strdup (src->priv->emoji);
Packit Service 1d8f1c
    dest->priv->annotations      = g_slist_copy_deep (src->priv->annotations,
Packit Service 1d8f1c
                                                      (GCopyFunc) g_strdup,
Packit Service 1d8f1c
                                                      NULL);
Packit Service 1d8f1c
    dest->priv->description      = g_strdup (src->priv->description);
Packit Service 1d8f1c
    dest->priv->category         = g_strdup (src->priv->category);
Packit Service 1d8f1c
    return TRUE;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
IBusEmojiData *
Packit Service 1d8f1c
ibus_emoji_data_new (const gchar *first_property_name, ...)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    va_list var_args;
Packit Service 1d8f1c
    IBusEmojiData *emoji;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_assert (first_property_name != NULL);
Packit Service 1d8f1c
    va_start (var_args, first_property_name);
Packit Service 1d8f1c
    emoji = (IBusEmojiData *) g_object_new_valist (IBUS_TYPE_EMOJI_DATA,
Packit Service 1d8f1c
                                                   first_property_name,
Packit Service 1d8f1c
                                                   var_args);
Packit Service 1d8f1c
    va_end (var_args);
Packit Service 1d8f1c
    /* emoji is required. Other properties are set in class_init by default. */
Packit Service 1d8f1c
    g_assert (emoji->priv->emoji != NULL);
Packit Service 1d8f1c
    g_assert (emoji->priv->description != NULL);
Packit Service 1d8f1c
    g_assert (emoji->priv->category != NULL);
Packit Service 1d8f1c
    return emoji;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
const gchar *
Packit Service 1d8f1c
ibus_emoji_data_get_emoji (IBusEmojiData *emoji)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_return_val_if_fail (IBUS_IS_EMOJI_DATA (emoji), NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    return emoji->priv->emoji;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
GSList *
Packit Service 1d8f1c
ibus_emoji_data_get_annotations (IBusEmojiData *emoji)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_return_val_if_fail (IBUS_IS_EMOJI_DATA (emoji), NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    return emoji->priv->annotations;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
void
Packit Service 1d8f1c
ibus_emoji_data_set_annotations (IBusEmojiData *emoji,
Packit Service 1d8f1c
                                 GSList        *annotations)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_return_if_fail (IBUS_IS_EMOJI_DATA (emoji));
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (emoji->priv->annotations)
Packit Service 1d8f1c
        g_slist_free_full (emoji->priv->annotations, g_free);
Packit Service 1d8f1c
    emoji->priv->annotations = annotations;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
const gchar *
Packit Service 1d8f1c
ibus_emoji_data_get_description (IBusEmojiData *emoji)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_return_val_if_fail (IBUS_IS_EMOJI_DATA (emoji), NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    return emoji->priv->description;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
void
Packit Service 1d8f1c
ibus_emoji_data_set_description (IBusEmojiData *emoji,
Packit Service 1d8f1c
                                 const gchar   *description)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_return_if_fail (IBUS_IS_EMOJI_DATA (emoji));
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_free (emoji->priv->description);
Packit Service 1d8f1c
    emoji->priv->description = g_strdup (description);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
const gchar *
Packit Service 1d8f1c
ibus_emoji_data_get_category (IBusEmojiData *emoji)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_return_val_if_fail (IBUS_IS_EMOJI_DATA (emoji), NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    return emoji->priv->category;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
variant_foreach_add_emoji (IBusEmojiData   *emoji,
Packit Service 1d8f1c
                           GVariantBuilder *builder)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_variant_builder_add (
Packit Service 1d8f1c
            builder, "v",
Packit Service 1d8f1c
            ibus_serializable_serialize (IBUS_SERIALIZABLE (emoji)));
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static GVariant *
Packit Service 1d8f1c
ibus_emoji_data_list_serialize (GSList *list)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GVariantBuilder builder;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
Packit Service 1d8f1c
    g_slist_foreach (list,  (GFunc) variant_foreach_add_emoji, &builder);
Packit Service 1d8f1c
    return g_variant_builder_end (&builder);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static GSList *
Packit Service 1d8f1c
ibus_emoji_data_list_deserialize (GVariant           *variant)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GSList *list = NULL;
Packit Service 1d8f1c
    GVariantIter iter;
Packit Service 1d8f1c
    GVariant *emoji_variant = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_variant_iter_init (&iter, variant);
Packit Service 1d8f1c
    while (g_variant_iter_loop (&iter, "v", &emoji_variant)) {
Packit Service 1d8f1c
        IBusEmojiData *data =
Packit Service 1d8f1c
                IBUS_EMOJI_DATA (ibus_serializable_deserialize (emoji_variant));
Packit Service 1d8f1c
        list = g_slist_append (list, data);
Packit Service 1d8f1c
        g_clear_pointer (&emoji_variant, g_variant_unref);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    return list;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
void
Packit Service 1d8f1c
ibus_emoji_dict_save (const gchar *path,
Packit Service 1d8f1c
                      GHashTable  *dict)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GList *values, *v;
Packit Service 1d8f1c
    GSList *list_for_save = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_return_if_fail (path != NULL);
Packit Service 1d8f1c
    g_return_if_fail (dict != NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    values = g_hash_table_get_values (dict);
Packit Service 1d8f1c
    for (v = values; v; v = v->next) {
Packit Service 1d8f1c
        IBusEmojiData *data = v->data;
Packit Service 1d8f1c
        if (!IBUS_IS_EMOJI_DATA (data)) {
Packit Service 1d8f1c
            g_warning ("Your dict format of { annotation char, emoji GSList "
Packit Service 1d8f1c
                       "} is no longer supported.\n"
Packit Service 1d8f1c
                       "{ emoji char, IBusEmojiData GSList } is expected.");
Packit Service 1d8f1c
            return;
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        list_for_save = g_slist_append (list_for_save, data);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    ibus_emoji_data_save (path, list_for_save);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
GHashTable *
Packit Service 1d8f1c
ibus_emoji_dict_load (const gchar *path)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GSList *list = ibus_emoji_data_load (path);
Packit Service 1d8f1c
    GSList *l;
Packit Service 1d8f1c
    GHashTable *dict = g_hash_table_new_full (g_str_hash,
Packit Service 1d8f1c
                                              g_str_equal,
Packit Service 1d8f1c
                                              g_free,
Packit Service 1d8f1c
                                              g_object_unref);
Packit Service 1d8f1c
Packit Service 1d8f1c
    for (l = list; l; l = l->next) {
Packit Service 1d8f1c
        IBusEmojiData *data = l->data;
Packit Service 1d8f1c
        if (!IBUS_IS_EMOJI_DATA (data)) {
Packit Service 1d8f1c
            g_warning ("Your dict format is no longer supported.\n"
Packit Service 1d8f1c
                       "Need to create the dictionaries again.");
Packit Service 1d8f1c
            return NULL;
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        g_hash_table_insert (dict,
Packit Service 1d8f1c
                             g_strdup (ibus_emoji_data_get_emoji (data)),
Packit Service 1d8f1c
                             g_object_ref_sink (data));
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_slist_free (list);
Packit Service 1d8f1c
Packit Service 1d8f1c
    return dict;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
Packit Service 1d8f1c
IBusEmojiData *
Packit Service 1d8f1c
ibus_emoji_dict_lookup (GHashTable  *dict,
Packit Service 1d8f1c
                        const gchar *emoji)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    return (IBusEmojiData *) g_hash_table_lookup (dict, emoji);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
void
Packit Service 1d8f1c
ibus_emoji_data_save (const gchar *path,
Packit Service 1d8f1c
                      GSList      *list)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GVariant *variant;
Packit Service 1d8f1c
    const gchar *header = IBUS_EMOJI_DATA_MAGIC;
Packit Service 1d8f1c
    const guint16 version = IBUS_EMOJI_DATA_VERSION;
Packit Service 1d8f1c
    const gchar *contents;
Packit Service 1d8f1c
    gsize length;
Packit Service 1d8f1c
    gchar *dir;
Packit Service 1d8f1c
    GStatBuf buf = { 0, };
Packit Service 1d8f1c
    GError *error = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_return_if_fail (path != NULL);
Packit Service 1d8f1c
    g_return_if_fail (list != NULL);
Packit Service 1d8f1c
    if (list->data == NULL) {
Packit Service 1d8f1c
        g_warning ("Failed to save IBus emoji data: Need a list data.");
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    variant = g_variant_new ("(sqv)",
Packit Service 1d8f1c
                             header,
Packit Service 1d8f1c
                             version,
Packit Service 1d8f1c
                             ibus_emoji_data_list_serialize (list));
Packit Service 1d8f1c
Packit Service 1d8f1c
    contents =  g_variant_get_data (variant);
Packit Service 1d8f1c
    length =  g_variant_get_size (variant);
Packit Service 1d8f1c
Packit Service 1d8f1c
    dir = g_path_get_dirname (path);
Packit Service 1d8f1c
    if (g_strcmp0 (dir, ".") != 0 && g_stat (dir, &buf) != 0) {
Packit Service 1d8f1c
        g_mkdir_with_parents (dir, 0777);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    g_free (dir);
Packit Service 1d8f1c
    if (!g_file_set_contents (path, contents, length, &error)) {
Packit Service 1d8f1c
        g_warning ("Failed to save emoji dict %s: %s", path, error->message);
Packit Service 1d8f1c
        g_error_free (error);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_variant_unref (variant);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
GSList *
Packit Service 1d8f1c
ibus_emoji_data_load (const gchar *path)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    gchar *contents = NULL;
Packit Service 1d8f1c
    gsize length = 0;
Packit Service 1d8f1c
    GError *error = NULL;
Packit Service 1d8f1c
    GVariant *variant_table = NULL;
Packit Service 1d8f1c
    GVariant *variant = NULL;
Packit Service 1d8f1c
    const gchar *header = NULL;
Packit Service 1d8f1c
    guint16 version = 0;
Packit Service 1d8f1c
    GSList *retval = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
Packit Service 1d8f1c
        g_warning ("Emoji dict does not exist: %s", path);
Packit Service 1d8f1c
        goto out_load_cache;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (!g_file_get_contents (path, &contents, &length, &error)) {
Packit Service 1d8f1c
        g_warning ("Failed to get dict content %s: %s", path, error->message);
Packit Service 1d8f1c
        g_error_free (error);
Packit Service 1d8f1c
        goto out_load_cache;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    variant_table = g_variant_new_from_data (G_VARIANT_TYPE ("(sq)"),
Packit Service 1d8f1c
                                             contents,
Packit Service 1d8f1c
                                             length,
Packit Service 1d8f1c
                                             FALSE,
Packit Service 1d8f1c
                                             NULL,
Packit Service 1d8f1c
                                             NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (variant_table == NULL) {
Packit Service 1d8f1c
        g_warning ("cache table is broken.");
Packit Service 1d8f1c
        goto out_load_cache;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_variant_get (variant_table, "(&sq)", &header, &version);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (g_strcmp0 (header, IBUS_EMOJI_DATA_MAGIC) != 0) {
Packit Service 1d8f1c
        g_warning ("cache is not IBusEmojiData.");
Packit Service 1d8f1c
        goto out_load_cache;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (version > IBUS_EMOJI_DATA_VERSION) {
Packit Service 1d8f1c
        g_warning ("cache version is different: %u != %u",
Packit Service 1d8f1c
                   version, IBUS_EMOJI_DATA_VERSION);
Packit Service 1d8f1c
        goto out_load_cache;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    version = 0;
Packit Service 1d8f1c
    header = NULL;
Packit Service 1d8f1c
    g_variant_unref (variant_table);
Packit Service 1d8f1c
Packit Service 1d8f1c
    variant_table = g_variant_new_from_data (G_VARIANT_TYPE ("(sqv)"),
Packit Service 1d8f1c
                                             contents,
Packit Service 1d8f1c
                                             length,
Packit Service 1d8f1c
                                             FALSE,
Packit Service 1d8f1c
                                             NULL,
Packit Service 1d8f1c
                                             NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (variant_table == NULL) {
Packit Service 1d8f1c
        g_warning ("cache table is broken.");
Packit Service 1d8f1c
        goto out_load_cache;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_variant_get (variant_table, "(&sqv)",
Packit Service 1d8f1c
                   NULL,
Packit Service 1d8f1c
                   NULL,
Packit Service 1d8f1c
                   &variant);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (variant == NULL) {
Packit Service 1d8f1c
        g_warning ("cache dict is broken.");
Packit Service 1d8f1c
        goto out_load_cache;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    retval = ibus_emoji_data_list_deserialize (variant);
Packit Service 1d8f1c
Packit Service 1d8f1c
out_load_cache:
Packit Service 1d8f1c
    if (variant)
Packit Service 1d8f1c
        g_variant_unref (variant);
Packit Service 1d8f1c
    if (variant_table)
Packit Service 1d8f1c
        g_variant_unref (variant_table);
Packit Service 1d8f1c
    g_free (contents);
Packit Service 1d8f1c
Packit Service 1d8f1c
    return retval;
Packit Service 1d8f1c
}