public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/ibus] autotool: Delete ibus-HEAD.patch to bump tarball
@ 2026-05-31  2:06 Takao Fujiwara
  0 siblings, 0 replies; only message in thread
From: Takao Fujiwara @ 2026-05-31  2:06 UTC (permalink / raw)
  To: git-commits

A new commit has been pushed.

Repo   : rpms/ibus
Branch : autotool
Commit : 800c4039597b0f01d01c31f3031f87c0f660a0ec
Author : Takao Fujiwara <tfujiwar@redhat.com>
Date   : 2016-08-05T15:20:04+09:00
Stats  : +0/-3695 in 1 file(s)
URL    : https://src.fedoraproject.org/rpms/ibus/c/800c4039597b0f01d01c31f3031f87c0f660a0ec?branch=autotool

Log:
Delete ibus-HEAD.patch to bump tarball

---
diff --git a/ibus-HEAD.patch b/ibus-HEAD.patch
deleted file mode 100644
index 89a27b3..0000000
--- a/ibus-HEAD.patch
+++ /dev/null
@@ -1,3695 +0,0 @@
-From 0432aa66b8728bc266da3c2cca84587bc44b3557 Mon Sep 17 00:00:00 2001
-From: Matthias Clasen <mclasen@redhat.com>
-Date: Tue, 8 Mar 2016 11:16:24 +0900
-Subject: [PATCH] Don't warn if DISPLAY is not set
-
-This is normal under Wayland, and not worth warning about.
-The warnings disrupt unit tests in GNOME continuous, which
-treat warnings as fatal.
-
-BUG=https://github.com/ibus/ibus/pull/1844
-R=shawn.p.huang@gmail.com
-
-Review URL: https://codereview.appspot.com/289430043
-
-Patch from Matthias Clasen <mclasen@redhat.com>.
----
- src/ibusshare.c | 5 +----
- 1 file changed, 1 insertion(+), 4 deletions(-)
-
-diff --git a/src/ibusshare.c b/src/ibusshare.c
-index 63800a6..b793a96 100644
---- a/src/ibusshare.c
-+++ b/src/ibusshare.c
-@@ -113,10 +113,7 @@ ibus_get_socket_path (void)
-             display = g_strdup (_display);
-         }
- 
--        if (display == NULL) {
--            g_warning ("DISPLAY is empty! We use default DISPLAY (:0.0)");
--        }
--        else {
-+        if (display) {
-             p = display;
-             hostname = display;
-             for (; *p != ':' && *p != '\0'; p++);
--- 
-2.7.4
-
-From 84c18f1d382548c52138822a11473d2dac79e485 Mon Sep 17 00:00:00 2001
-From: Rui Matos <tiagomatos@gmail.com>
-Date: Wed, 25 May 2016 11:21:09 +0900
-Subject: [PATCH] Install a DBus service file
-
-With the transition to user scoped DBus sessions (vs. login sessions)
-there's a need to start ibus-daemon via DBus activation so that the
-process gets properly tracked and disposed of when the login session
-ends. Otherwise the ibus-daemon process lingers on and keeps the whole
-login session up.
-
-We already connect and own a well known name on DBus. The remaining
-missing piece is the DBus service file which we introduce here.
-
-BUG=https://github.com/ibus/ibus/pull/1853
-R=Shawn.P.Huang@gmail.com
-
-Review URL: https://codereview.appspot.com/295340043
-
-Patch from Rui Matos <tiagomatos@gmail.com>.
----
- bus/Makefile.am                     | 11 +++++++++++
- bus/org.freedesktop.IBus.service.in |  3 +++
- 2 files changed, 14 insertions(+)
- create mode 100644 bus/org.freedesktop.IBus.service.in
-
-diff --git a/bus/Makefile.am b/bus/Makefile.am
-index 26cb2f8..4dabacf 100644
---- a/bus/Makefile.am
-+++ b/bus/Makefile.am
-@@ -174,4 +174,15 @@ man_onedir = $(mandir)/man1
- %.1.gz: %.1
- 	$(AM_V_GEN) gzip -c $< > $@.tmp && mv $@.tmp $@
- 
-+
-+dbusservice_in_files = org.freedesktop.IBus.service.in
-+dbusservice_DATA = $(dbusservice_in_files:.service.in=.service)
-+dbusservicedir=${datadir}/dbus-1/services
-+
-+org.freedesktop.IBus.service: org.freedesktop.IBus.service.in
-+	$(AM_V_GEN) sed -e "s|\@bindir\@|$(bindir)|" $< > $@.tmp && mv $@.tmp $@
-+
-+EXTRA_DIST += $(dbusservice_in_files)
-+CLEANFILES += $(dbusservice_DATA)
-+
- -include $(top_srcdir)/git.mk
-diff --git a/bus/org.freedesktop.IBus.service.in b/bus/org.freedesktop.IBus.service.in
-new file mode 100644
-index 0000000..cc88834
---- /dev/null
-+++ b/bus/org.freedesktop.IBus.service.in
-@@ -0,0 +1,3 @@
-+[D-BUS Service]
-+Name=org.freedesktop.IBus
-+Exec=@bindir@/ibus-daemon --replace --xim --panel disable
--- 
-2.7.4
-
-From 3ef21fef0135f7b4fe9611d201f15611734f6c51 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Fri, 3 Jun 2016 11:52:29 +0900
-Subject: [PATCH] client/gtk2: Fix SEGV with Wayland display
-
-Delete gdk_display_get_name() in GTK clients because ibus-daemon
-does not use gdk_display_get_name().
-GdkX11Dislay and GdkX11Window does not work with Wayland.
-
-BUG=https://github.com/ibus/ibus/issues/1859
-R=Shawn.P.Huang@gmail.com
-
-Review URL: https://codereview.appspot.com/301760043
----
- client/gtk2/ibusimcontext.c | 5 -----
- setup/main.py               | 7 +++++--
- 2 files changed, 5 insertions(+), 7 deletions(-)
-
-diff --git a/client/gtk2/ibusimcontext.c b/client/gtk2/ibusimcontext.c
-index 9d927e6..0df0062 100644
---- a/client/gtk2/ibusimcontext.c
-+++ b/client/gtk2/ibusimcontext.c
-@@ -583,11 +583,6 @@ ibus_im_context_class_init (IBusIMContextClass *class)
- 
-     /* init bus object */
-     if (_bus == NULL) {
--        const gchar *dname = gdk_display_get_name (gdk_display_get_default ());
--        /* ibus-daemon uses DISPLAY variable. */
--        if (g_strcmp0 (dname, "Wayland") == 0)
--            dname = g_getenv ("DISPLAY");
--        ibus_set_display (dname);
-         _bus = ibus_bus_new_async ();
- 
-         /* init the global fake context */
-diff --git a/setup/main.py b/setup/main.py
-index 26c2b0f..e1f7a9d 100644
---- a/setup/main.py
-+++ b/setup/main.py
-@@ -275,8 +275,11 @@ class Setup(object):
-         self.__init_general()
- 
-     def __gdk_window_set_cb(self, object, pspec):
--        str = '%u' % GdkX11.X11Window.get_xid(object.get_window())
--        GLib.setenv('IBUS_SETUP_XID', str, True)
-+        window = object.get_window()
-+        if type(window) != GdkX11.X11Window:
-+            return
-+        s = '%u' % GdkX11.X11Window.get_xid(window)
-+        GLib.setenv('IBUS_SETUP_XID', s, True)
- 
-     def __combobox_notify_active_engine_cb(self, combobox, property):
-         engine = self.__combobox.get_active_engine()
--- 
-2.7.4
-
-From a598ae29223d1ca25e76bf7d7de9703f63ea337e Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Fri, 3 Jun 2016 19:44:11 +0900
-Subject: [PATCH] ui/gtk3: Fix panel CSS format for GTK 3.20
-
-CSS node names have been changed since GTK 3.20 and the font size and
-widget color no longer work with the previous node names.
-
-BUG=https://github.com/ibus/ibus/issues/1856
-
-Review URL: https://codereview.appspot.com/297380043
----
- ui/gtk3/candidatearea.vala | 16 +++++++++++++---
- ui/gtk3/handle.vala        | 10 ++++++++--
- ui/gtk3/panel.vala         |  9 +++++++--
- 3 files changed, 28 insertions(+), 7 deletions(-)
-
-diff --git a/ui/gtk3/candidatearea.vala b/ui/gtk3/candidatearea.vala
-index c969312..3848f0d 100644
---- a/ui/gtk3/candidatearea.vala
-+++ b/ui/gtk3/candidatearea.vala
-@@ -3,7 +3,7 @@
-  * ibus - The Input Bus
-  *
-  * Copyright(c) 2011-2015 Peng Huang <shawn.p.huang@gmail.com>
-- * Copyright(c) 2015 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+ * Copyright(c) 2015-2016 Takao Fujiwara <takao.fujiwara1@gmail.com>
-  *
-  * This library is free software; you can redistribute it and/or
-  * modify it under the terms of the GNU Lesser General Public
-@@ -31,6 +31,10 @@ class CandidateArea : Gtk.Box {
-     private uint m_focus_candidate;
-     private bool m_show_cursor;
- 
-+    private bool m_use_latest_css_format =
-+            ((Gtk.MAJOR_VERSION > 3) ||
-+             (Gtk.MAJOR_VERSION == 3) && (Gtk.MINOR_VERSION >= 20));
-+
-     private const string LABELS[] = {
-         "1.", "2.", "3.", "4.", "5.", "6.", "7.", "8.",
-         "9.", "0.", "a.", "b.", "c.", "d.", "e.", "f."
-@@ -103,7 +107,8 @@ class CandidateArea : Gtk.Box {
-                 Pango.AttrList attrs = get_pango_attr_list_from_ibus_text(candidates[i]);
-                 if (i == focus_candidate && show_cursor) {
-                     Gtk.StyleContext context = m_candidates[i].get_style_context();
--                    Gdk.RGBA color = context.get_color(Gtk.StateFlags.SELECTED);
-+                    Gdk.RGBA *color = null;
-+                    context.get(Gtk.StateFlags.SELECTED, "color", out color);
-                     Pango.Attribute pango_attr = Pango.attr_foreground_new(
-                             (uint16)(color.red * uint16.MAX),
-                             (uint16)(color.green * uint16.MAX),
-@@ -112,7 +117,12 @@ class CandidateArea : Gtk.Box {
-                     pango_attr.end_index = candidates[i].get_text().length;
-                     attrs.insert((owned)pango_attr);
- 
--                    color = context.get_background_color(Gtk.StateFlags.SELECTED);
-+                    color = null;
-+                    string bg_prop =
-+                            m_use_latest_css_format
-+                            ? "-gtk-secondary-caret-color"
-+                            : "background-color";
-+                    context.get(Gtk.StateFlags.SELECTED, bg_prop, out color);
-                     pango_attr = Pango.attr_background_new(
-                             (uint16)(color.red * uint16.MAX),
-                             (uint16)(color.green * uint16.MAX),
-diff --git a/ui/gtk3/handle.vala b/ui/gtk3/handle.vala
-index 1edb537..bef5e8b 100644
---- a/ui/gtk3/handle.vala
-+++ b/ui/gtk3/handle.vala
-@@ -2,7 +2,8 @@
-  *
-  * ibus - The Input Bus
-  *
-- * Copyright(c) 2011-2015 Peng Huang <shawn.p.huang@gmail.com>
-+ * Copyright(c) 2011-2016 Peng Huang <shawn.p.huang@gmail.com>
-+ * Copyright(c) 2016 Takao Fujiwara <takao.fujiwara1@gmail.com>
-  *
-  * This library is free software; you can redistribute it and/or
-  * modify it under the terms of the GNU Lesser General Public
-@@ -29,6 +30,11 @@ class Handle : Gtk.EventBox {
-     public signal void move_end();
- 
-     public Handle() {
-+        // Call base class constructor
-+        GLib.Object(
-+            name : "IBusHandle"
-+        );
-+
-         set_size_request(6, -1);
-         Gdk.EventMask mask = Gdk.EventMask.EXPOSURE_MASK |
-                              Gdk.EventMask.BUTTON_PRESS_MASK |
-@@ -42,7 +48,7 @@ class Handle : Gtk.EventBox {
-         Gtk.CssProvider css_provider = new Gtk.CssProvider();
-         try {
-             css_provider.load_from_data(
--                    "GtkEventBox { background-color: gray }", -1);
-+                    "#IBusHandle { background-color: gray }", -1);
-         } catch (GLib.Error error) {
-             warning("Parse error in Handle: %s", error.message);
-         }
-diff --git a/ui/gtk3/panel.vala b/ui/gtk3/panel.vala
-index 2ca3a5e..cc19350 100644
---- a/ui/gtk3/panel.vala
-+++ b/ui/gtk3/panel.vala
-@@ -3,7 +3,7 @@
-  * ibus - The Input Bus
-  *
-  * Copyright(c) 2011-2014 Peng Huang <shawn.p.huang@gmail.com>
-- * Copyright(c) 2015 Takao Fujwiara <takao.fujiwara1@gmail.com>
-+ * Copyright(c) 2015-2016 Takao Fujwiara <takao.fujiwara1@gmail.com>
-  *
-  * This library is free software; you can redistribute it and/or
-  * modify it under the terms of the GNU Lesser General Public
-@@ -543,7 +543,12 @@ class Panel : IBus.PanelService {
-             return;
-         }
- 
--        string data_format = "GtkLabel { font: %s; }";
-+        string data_format = "label { font: %s; }";
-+        if (Gtk.MAJOR_VERSION < 3 ||
-+            (Gtk.MAJOR_VERSION == 3 && Gtk.MINOR_VERSION < 20)) {
-+            data_format = "GtkLabel { font: %s; }";
-+        }
-+
-         string data = data_format.printf(font_name);
-         m_css_provider = new Gtk.CssProvider();
- 
--- 
-2.7.4
-
-From 160d3c975af91eea6b8271b757be769b8ceef98d Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Tue, 21 Jun 2016 18:10:21 +0900
-Subject: [PATCH 1/4] engine: Implement Emoji typing with XKB engines
-
-Now Ctrl+Shift+e can convert an Emoji annotation to the Emoji characters
-likes Ctrl+Shift+u.
-The annotations are described as "Keywords" in the Unicode Emoji Data:
-http://www.unicode.org/emoji/charts/emoji-list.html
-'emoji-parser' compiles 'emoji-list.html' and generates 'emoji.dict'
-
-Review URL: https://codereview.appspot.com/295610043
----
- configure.ac           |  16 ++
- src/Makefile.am        |  31 ++++
- src/emoji-parser.c     | 217 ++++++++++++++++++++++++
- src/ibusenginesimple.c | 443 ++++++++++++++++++++++++++++++++++++++++++++-----
- src/ibusutil.c         | 193 ++++++++++++++++++++-
- src/ibusutil.h         |  31 +++-
- 6 files changed, 890 insertions(+), 41 deletions(-)
- create mode 100644 src/emoji-parser.c
-
-diff --git a/configure.ac b/configure.ac
-index 1e1f5dd..3128ef9 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -599,6 +599,21 @@ if test x"$enable_libnotify" = x"yes"; then
-     enable_libnotify="yes (enabled, use --disable-libnotify to disable)"
- fi
- 
-+# --disable-emoji-dict option.
-+AC_ARG_ENABLE(emoji-dict,
-+    AS_HELP_STRING([--disable-emoji-dict],
-+                   [Do not build Emoji dict files]),
-+    [enable_emoji_dict=$enableval],
-+    [enable_emoji_dict=yes]
-+)
-+AM_CONDITIONAL([ENABLE_EMOJI_DICT], [test x"$enable_emoji_dict" = x"yes"])
-+if test x"$enable_emoji_dict" = x"yes"; then
-+    PKG_CHECK_MODULES(LIBXML2, [
-+        libxml-2.0
-+    ])
-+    enable_emoji_dict="yes (enabled, use --disable-emoji-dict to disable)"
-+fi
-+
- # Check iso-codes.
- PKG_CHECK_MODULES(ISOCODES, [
-     iso-codes
-@@ -682,6 +697,7 @@ Build options:
-   Panel icon                    "$IBUS_ICON_KEYBOARD"
-   Enable surrounding-text       $enable_surrounding_text
-   Enable libnotify              $enable_libnotify
-+  Enable Emoji dict             $enable_emoji_dict
-   Run test cases                $enable_tests
- ])
- 
-diff --git a/src/Makefile.am b/src/Makefile.am
-index adaebe9..a33b67d 100644
---- a/src/Makefile.am
-+++ b/src/Makefile.am
-@@ -231,7 +231,38 @@ ibusmarshalers.c: ibusmarshalers.h ibusmarshalers.list
- 	$(GLIB_GENMARSHAL) --prefix=_ibus_marshal $(srcdir)/ibusmarshalers.list --body --internal) > $@.tmp && \
- 	mv $@.tmp $@
- 
-+if ENABLE_EMOJI_DICT
-+AM_CPPFLAGS += -DENABLE_EMOJI_DICT
-+
-+dictdir = $(pkgdatadir)/dicts
-+dict_DATA = emoji.dict
-+
-+noinst_PROGRAMS = emoji-parser
-+
-+emoji.dict: emoji-parser emoji-list.html
-+	$(builddir)/emoji-parser emoji-list.html $@
-+
-+emoji_parser_SOURCES =          \
-+    emoji-parser.c              \
-+    $(NULL)
-+emoji_parser_CFLAGS =           \
-+    $(GLIB2_CFLAGS)             \
-+    $(LIBXML2_CFLAGS)           \
-+    $(NULL)
-+emoji_parser_LDADD =            \
-+    $(GLIB2_LIBS)               \
-+    $(LIBXML2_LIBS)             \
-+    $(libibus)                  \
-+    $(NULL)
-+
-+CLEANFILES +=                   \
-+    $(dict_DATA)                \
-+    $(NULL)
-+endif
-+
- EXTRA_DIST =                    \
-+    emoji-list.html             \
-+    emoji-parser.c              \
-     ibusversion.h.in            \
-     ibusmarshalers.list         \
-     ibusenumtypes.h.template    \
-diff --git a/src/emoji-parser.c b/src/emoji-parser.c
-new file mode 100644
-index 0000000..cf92fee
---- /dev/null
-+++ b/src/emoji-parser.c
-@@ -0,0 +1,217 @@
-+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
-+/* vim:set et sts=4: */
-+/* ibus - The Input Bus
-+ * Copyright (C) 2016 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+ * Copyright (C) 2016 Red Hat, Inc.
-+ *
-+ * This library is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU Lesser General Public
-+ * License as published by the Free Software Foundation; either
-+ * version 2.1 of the License, or (at your option) any later version.
-+ *
-+ * This library is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+ * Lesser General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU Lesser General Public
-+ * License along with this library; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
-+ * USA
-+ */
-+
-+/* Convert http://www.unicode.org/emoji/charts/emoji-list.html
-+ * to the dictionary file which look up the Emoji from the annotation.
-+ */
-+
-+#include <glib.h>
-+#include <libxml/HTMLparser.h>
-+#include <libgen.h>
-+
-+#include "ibusutil.h"
-+
-+typedef struct _EmojiData EmojiData;
-+struct _EmojiData {
-+    gchar      *class;
-+    gchar      *emoji;
-+    GSList     *annotates;
-+    GSList     *prev_annotates;
-+    GHashTable *dict;
-+};
-+
-+const gchar *progname;
-+
-+static gboolean         parse_node             (xmlNode     *node,
-+                                                gboolean     is_child,
-+                                                const gchar *prop_name,
-+                                                EmojiData   *data);
-+
-+static void
-+usage (void)
-+{
-+    g_print ("%s emoji-list.html emoji.dict\n", progname);
-+}
-+
-+static void
-+reset_emoji_element (EmojiData *data)
-+{
-+    g_clear_pointer (&data->class, g_free);
-+    g_clear_pointer (&data->emoji, g_free);
-+    if (data->annotates) {
-+        g_slist_free_full (data->prev_annotates, g_free);
-+        data->prev_annotates = data->annotates;
-+        data->annotates = NULL;
-+    }
-+}
-+
-+static void
-+free_dict_words (gpointer list)
-+{
-+    g_slist_free_full (list, g_free);
-+}
-+
-+static gboolean
-+parse_attr (xmlAttr   *attr,
-+            EmojiData *data)
-+{
-+    if (g_strcmp0 ((const gchar *) attr->name, "class") == 0 && attr->children)
-+        parse_node (attr->children, TRUE, (const gchar *) attr->name, data);
-+    if (g_strcmp0 ((const gchar *) attr->name, "target") == 0 && attr->children)
-+        parse_node (attr->children, TRUE, (const gchar *) attr->name, data);
-+    if (attr->next)
-+        parse_attr (attr->next, data);
-+    return TRUE;
-+}
-+
-+static gboolean
-+parse_node (xmlNode     *node,
-+            gboolean     is_child,
-+            const gchar *prop_name,
-+            EmojiData   *data)
-+{
-+    if (g_strcmp0 ((const gchar *) node->name, "tr") == 0) {
-+        GSList *annotates = data->annotates;
-+        while (annotates) {
-+            GSList *emojis = g_hash_table_lookup (data->dict, annotates->data);
-+            if (emojis) {
-+                emojis = g_slist_copy_deep (emojis, (GCopyFunc) g_strdup, NULL);
-+            }
-+            emojis = g_slist_append (emojis, g_strdup (data->emoji));
-+            g_hash_table_replace (data->dict,
-+                                  g_strdup (annotates->data),
-+                                  emojis);
-+            annotates = annotates->next;
-+        }
-+        reset_emoji_element (data);
-+    }
-+    /* if node->name is "text" and is_child is FALSE,
-+     * it's '\n' or Space between <td> and <td>.
-+     */
-+    if (g_strcmp0 ((const gchar *) node->name, "text") == 0 && is_child) {
-+        /* Get "chars" in <td class="chars"> */
-+        if (g_strcmp0 (prop_name, "class") == 0) {
-+            if (g_strcmp0 (data->class, (const gchar *) node->content) != 0) {
-+                g_clear_pointer (&data->class, g_free);
-+                data->class = g_strdup ((const gchar *) node->content);
-+            }
-+        }
-+        /* Get "annotate" in <td class="name"><a target="annotate"> */
-+        if (g_strcmp0 (prop_name, "target") == 0 &&
-+            g_strcmp0 (data->class, "name") == 0) {
-+            g_clear_pointer (&data->class, g_free);
-+            data->class = g_strdup ((const gchar *) node->content);
-+        }
-+        /* Get "emoji" in <td class="chars">emoji</td> */
-+        if (g_strcmp0 (prop_name, "td") == 0 &&
-+            g_strcmp0 (data->class, "chars") == 0) {
-+            data->emoji = g_strdup ((const gchar *) node->content);
-+        }
-+        /* We ignore "NAME" for <td class="name">NAME</td> but
-+         * takes "ANNOTATE" for
-+         * <td class="name"><a target="annotate">ANNOTATE</a></td>
-+         */
-+        if (g_strcmp0 (prop_name, "td") == 0 &&
-+            g_strcmp0 (data->class, "name") == 0) {
-+            g_slist_free_full (data->annotates, g_free);
-+            data->annotates = NULL;
-+        }
-+        /* Get "ANNOTATE" in
-+         * <td class="name"><a target="annotate">ANNOTATE</a></td>
-+         */
-+        if (g_strcmp0 (prop_name, "a") == 0 &&
-+            g_strcmp0 (data->class, "annotate") == 0) {
-+            data->annotates =
-+                    g_slist_append (data->annotates,
-+                                    g_strdup ((const gchar *) node->content));
-+        }
-+    }
-+    /* Get "foo" in <td class="foo"> */
-+    if (g_strcmp0 ((const gchar *) node->name, "td") == 0 &&
-+        node->properties != NULL) {
-+        parse_attr (node->properties, data);
-+    }
-+    /* Get "foo" in <a target="foo"> */
-+    if (g_strcmp0 ((const gchar *) node->name, "a") == 0 &&
-+        node->properties != NULL) {
-+        parse_attr (node->properties, data);
-+    }
-+    if (node->children) {
-+        parse_node (node->children, TRUE, (const gchar *) node->name, data);
-+    } else {
-+        /* If annotate is NULL likes <td class="name"></td>,
-+         * the previous emoji cell has the same annotate.
-+         */
-+        if (g_strcmp0 ((const gchar *) node->name, "td") == 0 &&
-+            g_strcmp0 (data->class, "name") == 0) {
-+            data->annotates = g_slist_copy_deep (data->prev_annotates,
-+                                                 (GCopyFunc) g_strdup,
-+                                                 NULL);
-+        }
-+    }
-+    if (node->next)
-+        parse_node (node->next, FALSE, (const gchar *) node->name, data);
-+
-+    return TRUE;
-+}
-+
-+static GHashTable *
-+parse_html (const gchar *filename)
-+{
-+    xmlDoc *doc = htmlParseFile (filename, "utf-8");
-+    EmojiData data = { 0, };
-+
-+    if (doc == NULL || doc->children == NULL) {
-+        g_warning ("Parse Error in document type: %x",
-+                   doc ? doc->type : 0);
-+        return FALSE;
-+    }
-+
-+    data.dict = g_hash_table_new_full (g_str_hash,
-+                                       g_str_equal,
-+                                       g_free,
-+                                       free_dict_words);
-+    parse_node (doc->children, TRUE, (const gchar *) doc->name, &data);
-+
-+    reset_emoji_element (&data);
-+    g_slist_free_full (data.prev_annotates, g_free);
-+
-+    return data.dict;
-+}
-+
-+int
-+main (int argc, char *argv[])
-+{
-+    GHashTable *dict;
-+    progname = basename (argv[0]);
-+
-+    if (argc < 3) {
-+        usage ();
-+        return -1;
-+    }
-+
-+    dict = parse_html (argv[1]);
-+    ibus_emoji_dict_save (argv[2], dict);
-+    g_hash_table_destroy (dict);
-+
-+    return 0;
-+}
-diff --git a/src/ibusenginesimple.c b/src/ibusenginesimple.c
-index 1b688b0..8efe5a9 100644
---- a/src/ibusenginesimple.c
-+++ b/src/ibusenginesimple.c
-@@ -3,7 +3,7 @@
- /* ibus - The Input Bus
-  * Copyright (C) 2014 Peng Huang <shawn.p.huang@gmail.com>
-  * Copyright (C) 2015-2016 Takao Fujiwara <takao.fujiwara1@gmail.com>
-- * Copyright (C) 2014 Red Hat, Inc.
-+ * Copyright (C) 2014-2016 Red Hat, Inc.
-  *
-  * This library is free software; you can redistribute it and/or
-  * modify it under the terms of the GNU Lesser General Public
-@@ -31,6 +31,7 @@
- 
- #include "ibuskeys.h"
- #include "ibuskeysyms.h"
-+#include "ibusutil.h"
- 
- /* This file contains the table of the compose sequences,
-  * static const guint16 gtk_compose_seqs_compact[] = {}
-@@ -42,16 +43,27 @@
- #include <stdlib.h>
- 
- #define X11_DATADIR X11_DATA_PREFIX "/share/X11/locale"
-+#define EMOJI_SOURCE_LEN 100
- #define IBUS_ENGINE_SIMPLE_GET_PRIVATE(o)  \
-    (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_ENGINE_SIMPLE, IBusEngineSimplePrivate))
- 
--struct _IBusEngineSimplePrivate {
--    guint16     compose_buffer[IBUS_MAX_COMPOSE_LEN + 1];
--    gunichar    tentative_match;
--    gint        tentative_match_len;
-+typedef struct {
-+    GHashTable *dict;
-+    int         max_seq_len;
-+} IBusEngineDict;
- 
--    guint       in_hex_sequence : 1;
--    guint       modifiers_dropped : 1;
-+struct _IBusEngineSimplePrivate {
-+    guint16             compose_buffer[EMOJI_SOURCE_LEN];
-+    gunichar            tentative_match;
-+    gchar              *tentative_emoji;
-+    gint                tentative_match_len;
-+
-+    guint               in_hex_sequence : 1;
-+    guint               in_emoji_sequence : 1;
-+    guint               modifiers_dropped : 1;
-+    IBusEngineDict     *emoji_dict;
-+    IBusLookupTable    *lookup_table;
-+    gboolean            lookup_table_visible;
- };
- 
- /* From the values below, the value 30 means the number of different first keysyms
-@@ -97,6 +109,8 @@ static gboolean ibus_engine_simple_process_key_event
-                                                  guint               modifiers);
- static void     ibus_engine_simple_commit_char (IBusEngineSimple    *simple,
-                                                 gunichar             ch);
-+static void     ibus_engine_simple_commit_str  (IBusEngineSimple    *simple,
-+                                                const gchar         *str);
- static void     ibus_engine_simple_update_preedit_text
-                                                (IBusEngineSimple    *simple);
- 
-@@ -128,6 +142,18 @@ ibus_engine_simple_init (IBusEngineSimple *simple)
- static void
- ibus_engine_simple_destroy (IBusEngineSimple *simple)
- {
-+    IBusEngineSimplePrivate *priv = simple->priv;
-+
-+    if (priv->emoji_dict) {
-+        if (priv->emoji_dict->dict)
-+            g_clear_pointer (&priv->emoji_dict->dict, g_hash_table_destroy);
-+        g_slice_free (IBusEngineDict, priv->emoji_dict);
-+        priv->emoji_dict = NULL;
-+    }
-+
-+    g_clear_pointer (&priv->lookup_table, g_object_unref);
-+    g_clear_pointer (&priv->tentative_emoji, g_free);
-+
-     IBUS_OBJECT_CLASS(ibus_engine_simple_parent_class)->destroy (
-         IBUS_OBJECT (simple));
- }
-@@ -146,6 +172,11 @@ ibus_engine_simple_reset (IBusEngine *engine)
-         priv->tentative_match_len = 0;
-         ibus_engine_hide_preedit_text ((IBusEngine *)simple);
-     }
-+    if (priv->tentative_emoji || priv->in_emoji_sequence) {
-+        priv->in_emoji_sequence = FALSE;
-+        g_clear_pointer (&priv->tentative_emoji, g_free);
-+        ibus_engine_hide_preedit_text ((IBusEngine *)simple);
-+    }
- }
- 
- static void
-@@ -162,23 +193,60 @@ ibus_engine_simple_commit_char (IBusEngineSimple *simple,
-         priv->tentative_match_len = 0;
-         ibus_engine_simple_update_preedit_text (simple);
-     }
-+    if (priv->tentative_emoji || priv->in_emoji_sequence) {
-+        priv->in_emoji_sequence = FALSE;
-+        g_clear_pointer (&priv->tentative_emoji, g_free);
-+        ibus_engine_simple_update_preedit_text (simple);
-+    }
- 
-     ibus_engine_commit_text ((IBusEngine *)simple,
-             ibus_text_new_from_unichar (ch));
- }
- 
- static void
-+ibus_engine_simple_commit_str (IBusEngineSimple *simple,
-+                               const gchar      *str)
-+{
-+    IBusEngineSimplePrivate *priv = simple->priv;
-+    gchar *backup_str;
-+
-+    g_return_if_fail (str && *str);
-+
-+    backup_str = g_strdup (str);
-+
-+    if (priv->tentative_match || priv->in_hex_sequence) {
-+        priv->in_hex_sequence = FALSE;
-+        priv->tentative_match = 0;
-+        priv->tentative_match_len = 0;
-+        ibus_engine_simple_update_preedit_text (simple);
-+    }
-+    if (priv->tentative_emoji || priv->in_emoji_sequence) {
-+        priv->in_emoji_sequence = FALSE;
-+        g_clear_pointer (&priv->tentative_emoji, g_free);
-+        ibus_engine_simple_update_preedit_text (simple);
-+    }
-+
-+    ibus_engine_commit_text ((IBusEngine *)simple,
-+            ibus_text_new_from_string (backup_str));
-+    g_free (backup_str);
-+}
-+
-+static void
- ibus_engine_simple_update_preedit_text (IBusEngineSimple *simple)
- {
-     IBusEngineSimplePrivate *priv = simple->priv;
- 
--    gunichar outbuf[IBUS_MAX_COMPOSE_LEN + 2];
-+    gunichar outbuf[EMOJI_SOURCE_LEN + 1];
-     int len = 0;
- 
--    if (priv->in_hex_sequence) {
-+    if (priv->in_hex_sequence || priv->in_emoji_sequence) {
-         int hexchars = 0;
- 
--        outbuf[0] = L'u';
-+        if (priv->in_hex_sequence)
-+            outbuf[0] = L'u';
-+        else
-+            outbuf[0] = L'@';
-+
-         len = 1;
- 
-         while (priv->compose_buffer[hexchars] != 0) {
-@@ -187,10 +255,22 @@ ibus_engine_simple_update_preedit_text (IBusEngineSimple *simple)
-             ++len;
-             ++hexchars;
-         }
--        g_assert (len <= IBUS_MAX_COMPOSE_LEN + 1);
-+
-+        if (priv->in_hex_sequence)
-+            g_assert (len <= IBUS_MAX_COMPOSE_LEN + 1);
-+        else
-+            g_assert (len <= EMOJI_SOURCE_LEN + 1);
-     }
--    else if (priv->tentative_match)
-+    else if (priv->tentative_match) {
-         outbuf[len++] = priv->tentative_match;
-+    } else if (priv->tentative_emoji && *priv->tentative_emoji) {
-+        IBusText *text = ibus_text_new_from_string (priv->tentative_emoji);
-+        len = strlen (priv->tentative_emoji);
-+        ibus_text_append_attribute (text,
-+                IBUS_ATTR_TYPE_UNDERLINE, IBUS_ATTR_UNDERLINE_SINGLE, 0, len);
-+        ibus_engine_update_preedit_text ((IBusEngine *)simple, text, len, TRUE);
-+        return;
-+    }
- 
-     outbuf[len] = L'\0';
-     if (len == 0) {
-@@ -277,6 +357,104 @@ check_hex (IBusEngineSimple *simple,
-     return TRUE;
- }
- 
-+static IBusEngineDict *
-+load_emoji_dict ()
-+{
-+    IBusEngineDict *emoji_dict;
-+    GList *keys;
-+    int max_length = 0;
-+
-+    emoji_dict = g_slice_new0 (IBusEngineDict);
-+    emoji_dict->dict = ibus_emoji_dict_load (IBUS_DATA_DIR "/dicts/emoji.dict");
-+    if (!emoji_dict->dict)
-+        return emoji_dict;
-+
-+    keys = g_hash_table_get_keys (emoji_dict->dict);
-+    for (; keys; keys = keys->next) {
-+        int length = strlen (keys->data);
-+        if (max_length < length)
-+            max_length = length;
-+    }
-+    emoji_dict->max_seq_len = max_length;
-+
-+    return emoji_dict;
-+}
-+
-+static gboolean
-+check_emoji_table (IBusEngineSimple       *simple,
-+                   gint                    n_compose,
-+                   gint                    index)
-+{
-+    IBusEngineSimplePrivate *priv = simple->priv;
-+    IBusEngineDict *emoji_dict = priv->emoji_dict;
-+    GString *str = NULL;
-+    gint i;
-+    gchar buf[7];
-+    GSList *words = NULL;
-+
-+    g_assert (IBUS_IS_ENGINE_SIMPLE (simple));
-+
-+    if (priv->lookup_table == NULL) {
-+        priv->lookup_table = ibus_lookup_table_new (10, 0, TRUE, TRUE);
-+        g_object_ref_sink (priv->lookup_table);
-+    }
-+    if (emoji_dict == NULL)
-+        emoji_dict = priv->emoji_dict = load_emoji_dict (simple);
-+
-+    if (emoji_dict == NULL || emoji_dict->dict == NULL)
-+        return FALSE;
-+
-+    if (n_compose > emoji_dict->max_seq_len)
-+        return FALSE;
-+
-+    str = g_string_new (NULL);
-+    priv->lookup_table_visible = FALSE;
-+
-+    i = 0;
-+    while (i < n_compose) {
-+        gunichar ch;
-+
-+        ch = ibus_keyval_to_unicode (priv->compose_buffer[i]);
-+
-+        if (ch == 0)
-+            return FALSE;
-+
-+        if (!g_unichar_isprint (ch))
-+            return FALSE;
-+
-+        buf[g_unichar_to_utf8 (ch, buf)] = '\0';
-+
-+        g_string_append (str, buf);
-+
-+        ++i;
-+    }
-+
-+    if (str->str) {
-+        words = g_hash_table_lookup (emoji_dict->dict, str->str);
-+    }
-+    g_string_free (str, TRUE);
-+
-+    if (words != NULL) {
-+        int i = 0;
-+        ibus_lookup_table_clear (priv->lookup_table);
-+        priv->lookup_table_visible = TRUE;
-+
-+        while (words) {
-+            if (i == index) {
-+                g_clear_pointer (&priv->tentative_emoji, g_free);
-+                priv->tentative_emoji = g_strdup (words->data);
-+            }
-+            IBusText *text = ibus_text_new_from_string (words->data);
-+            ibus_lookup_table_append_candidate (priv->lookup_table, text);
-+            words = words->next;
-+            i++;
-+        }
-+        return TRUE;
-+    }
-+
-+    return FALSE;
-+}
-+
- static int
- compare_seq_index (const void *key, const void *value)
- {
-@@ -626,10 +804,10 @@ ibus_check_algorithmically (const guint16 *compose_buffer,
- 
- static gboolean
- no_sequence_matches (IBusEngineSimple *simple,
--                     gint                 n_compose,
--                     guint                keyval,
--                     guint                keycode,
--                     guint                modifiers)
-+                     gint              n_compose,
-+                     guint             keyval,
-+                     guint             keycode,
-+                     guint             modifiers)
- {
-     IBusEngineSimplePrivate *priv = simple->priv;
- 
-@@ -642,8 +820,7 @@ no_sequence_matches (IBusEngineSimple *simple,
-         gint len = priv->tentative_match_len;
-         int i;
- 
--        ibus_engine_simple_commit_char (simple,
--                                            priv->tentative_match);
-+        ibus_engine_simple_commit_char (simple, priv->tentative_match);
-         priv->compose_buffer[0] = 0;
- 
-         for (i=0; i < n_compose - len - 1; i++) {
-@@ -655,8 +832,11 @@ no_sequence_matches (IBusEngineSimple *simple,
- 
-         return ibus_engine_simple_process_key_event (
-                 (IBusEngine *)simple, keyval, keycode, modifiers);
--    }
--    else {
-+    } else if (priv->tentative_emoji && *priv->tentative_emoji) {
-+        ibus_engine_simple_commit_str (simple, priv->tentative_emoji);
-+        g_clear_pointer (&priv->tentative_emoji, g_free);
-+        priv->compose_buffer[0] = 0;
-+    } else {
-         priv->compose_buffer[0] = 0;
-         if (n_compose > 1) {
-             /* Invalid sequence */
-@@ -676,6 +856,7 @@ no_sequence_matches (IBusEngineSimple *simple,
-         else
-             return FALSE;
-     }
-+    return FALSE;
- }
- 
- static gboolean
-@@ -687,6 +868,39 @@ is_hex_keyval (guint keyval)
- }
- 
- static gboolean
-+is_graph_keyval (guint keyval)
-+{
-+  gunichar ch = ibus_keyval_to_unicode (keyval);
-+
-+  return g_unichar_isgraph (ch);
-+}
-+
-+static void
-+ibus_engine_simple_update_lookup_and_aux_table (IBusEngineSimple *simple)
-+{
-+    IBusEngineSimplePrivate *priv;
-+    guint index, candidates;
-+    gchar *aux_label = NULL;
-+    IBusText *text = NULL;
-+
-+    g_return_if_fail (IBUS_IS_ENGINE_SIMPLE (simple));
-+
-+    priv = simple->priv;
-+    index = ibus_lookup_table_get_cursor_pos (priv->lookup_table) + 1;
-+    candidates = ibus_lookup_table_get_number_of_candidates(priv->lookup_table);
-+    aux_label = g_strdup_printf ("(%u / %u)", index, candidates);
-+    text = ibus_text_new_from_string (aux_label);
-+    g_free (aux_label);
-+
-+    ibus_engine_update_auxiliary_text (IBUS_ENGINE (simple),
-+                                       text,
-+                                       priv->lookup_table_visible);
-+    ibus_engine_update_lookup_table (IBUS_ENGINE (simple),
-+                                     priv->lookup_table,
-+                                     priv->lookup_table_visible);
-+}
-+
-+static gboolean
- ibus_engine_simple_process_key_event (IBusEngine *engine,
-                                       guint       keyval,
-                                       guint       keycode,
-@@ -697,10 +911,13 @@ ibus_engine_simple_process_key_event (IBusEngine *engine,
-     gint n_compose = 0;
-     gboolean have_hex_mods;
-     gboolean is_hex_start;
-+    gboolean is_emoji_start = FALSE;
-     gboolean is_hex_end;
-+    gboolean is_space;
-     gboolean is_backspace;
-     gboolean is_escape;
-     guint hex_keyval;
-+    guint printable_keyval;
-     gint i;
-     gboolean compose_finish;
-     gunichar output_char;
-@@ -714,17 +931,16 @@ ibus_engine_simple_process_key_event (IBusEngine *engine,
-              keyval == IBUS_KEY_Shift_L || keyval == IBUS_KEY_Shift_R)) {
-             if (priv->tentative_match &&
-                 g_unichar_validate (priv->tentative_match)) {
--                ibus_engine_simple_commit_char (simple,
--                                                    priv->tentative_match);
--            }
--            else if (n_compose == 0) {
-+                ibus_engine_simple_commit_char (simple, priv->tentative_match);
-+            } else if (n_compose == 0) {
-                 priv->modifiers_dropped = TRUE;
--            }
--            else {
-+            } else {
-                 /* invalid hex sequence */
-                 /* FIXME beep_window (event->window); */
-                 priv->tentative_match = 0;
-+                g_clear_pointer (&priv->tentative_emoji, g_free);
-                 priv->in_hex_sequence = FALSE;
-+                priv->in_emoji_sequence = FALSE;
-                 priv->compose_buffer[0] = 0;
- 
-                 ibus_engine_simple_update_preedit_text (simple);
-@@ -732,6 +948,26 @@ ibus_engine_simple_process_key_event (IBusEngine *engine,
- 
-             return TRUE;
-         }
-+        /* Handle Shift + Space */
-+        else if (priv->in_emoji_sequence &&
-+            (keyval == IBUS_KEY_Control_L || keyval == IBUS_KEY_Control_R)) {
-+            if (priv->tentative_emoji && *priv->tentative_emoji) {
-+                ibus_engine_simple_commit_str (simple, priv->tentative_emoji);
-+                g_clear_pointer (&priv->tentative_emoji, g_free);
-+            } else if (n_compose == 0) {
-+                priv->modifiers_dropped = TRUE;
-+            } else {
-+                /* invalid hex sequence */
-+                /* FIXME beep_window (event->window); */
-+                priv->tentative_match = 0;
-+                g_clear_pointer (&priv->tentative_emoji, g_free);
-+                priv->in_hex_sequence = FALSE;
-+                priv->in_emoji_sequence = FALSE;
-+                priv->compose_buffer[0] = 0;
-+
-+                ibus_engine_simple_update_preedit_text (simple);
-+            }
-+        }
-         else
-             return FALSE;
-     }
-@@ -741,25 +977,33 @@ ibus_engine_simple_process_key_event (IBusEngine *engine,
-         if (keyval == ibus_compose_ignore[i])
-             return FALSE;
- 
--    if (priv->in_hex_sequence && priv->modifiers_dropped)
-+    if ((priv->in_hex_sequence || priv->in_emoji_sequence)
-+        && priv->modifiers_dropped) {
-         have_hex_mods = TRUE;
--    else
-+    } else {
-         have_hex_mods = (modifiers & (HEX_MOD_MASK)) == HEX_MOD_MASK;
-+    }
- 
-     is_hex_start = keyval == IBUS_KEY_U;
-+#ifdef ENABLE_EMOJI_DICT
-+    is_emoji_start = keyval == IBUS_KEY_E;
-+#endif
-     is_hex_end = (keyval == IBUS_KEY_space ||
-                   keyval == IBUS_KEY_KP_Space ||
-                   keyval == IBUS_KEY_Return ||
-                   keyval == IBUS_KEY_ISO_Enter ||
-                   keyval == IBUS_KEY_KP_Enter);
-+    is_space = (keyval == IBUS_KEY_space || keyval == IBUS_KEY_KP_Space);
-     is_backspace = keyval == IBUS_KEY_BackSpace;
-     is_escape = keyval == IBUS_KEY_Escape;
-     hex_keyval = is_hex_keyval (keyval) ? keyval : 0;
-+    printable_keyval = is_graph_keyval (keyval) ? keyval : 0;
- 
-     /* gtkimcontextsimple causes a buffer overflow in priv->compose_buffer.
-      * Add the check code here.
-      */
--    if (n_compose >= IBUS_MAX_COMPOSE_LEN) {
-+    if ((n_compose >= IBUS_MAX_COMPOSE_LEN && priv->in_hex_sequence) ||
-+        (n_compose >= EMOJI_SOURCE_LEN && priv->in_emoji_sequence)) {
-         if (is_backspace) {
-             priv->compose_buffer[--n_compose] = 0;
-         }
-@@ -767,7 +1011,9 @@ ibus_engine_simple_process_key_event (IBusEngine *engine,
-             /* invalid hex sequence */
-             // beep_window (event->window);
-             priv->tentative_match = 0;
-+            g_clear_pointer (&priv->tentative_emoji, g_free);
-             priv->in_hex_sequence = FALSE;
-+            priv->in_emoji_sequence = FALSE;
-             priv->compose_buffer[0] = 0;
-         }
-         else if (is_escape) {
-@@ -789,12 +1035,16 @@ ibus_engine_simple_process_key_event (IBusEngine *engine,
-      * ISO_Level3_Switch.
-      */
-     if (!have_hex_mods ||
--        (n_compose > 0 && !priv->in_hex_sequence) ||
--        (n_compose == 0 && !priv->in_hex_sequence && !is_hex_start) ||
-+        (n_compose > 0 && !priv->in_hex_sequence && !priv->in_emoji_sequence) ||
-+        (n_compose == 0 && !priv->in_hex_sequence && !is_hex_start &&
-+         !priv->in_emoji_sequence && !is_emoji_start) ||
-         (priv->in_hex_sequence && !hex_keyval &&
--         !is_hex_start && !is_hex_end && !is_escape && !is_backspace)) {
-+         !is_hex_start && !is_hex_end && !is_escape && !is_backspace) ||
-+        (priv->in_emoji_sequence && !printable_keyval &&
-+         !is_emoji_start && !is_hex_end && !is_escape && !is_backspace)) {
-         if (modifiers & (IBUS_MOD1_MASK | IBUS_CONTROL_MASK) ||
--            (priv->in_hex_sequence && priv->modifiers_dropped &&
-+            ((priv->in_hex_sequence || priv->in_emoji_sequence) &&
-+             priv->modifiers_dropped &&
-              (keyval == IBUS_KEY_Return ||
-               keyval == IBUS_KEY_ISO_Enter ||
-               keyval == IBUS_KEY_KP_Enter))) {
-@@ -816,6 +1066,20 @@ ibus_engine_simple_process_key_event (IBusEngine *engine,
- 
-         return TRUE;
-     }
-+    if (priv->in_emoji_sequence && have_hex_mods && is_backspace) {
-+        if (n_compose > 0) {
-+            n_compose--;
-+            priv->compose_buffer[n_compose] = 0;
-+            check_emoji_table (simple, n_compose, -1);
-+            ibus_engine_simple_update_lookup_and_aux_table (simple);
-+        } else {
-+            priv->in_emoji_sequence = FALSE;
-+        }
-+
-+        ibus_engine_simple_update_preedit_text (simple);
-+
-+        return TRUE;
-+    }
- 
-     /* Check for hex sequence restart */
-     if (priv->in_hex_sequence && have_hex_mods && is_hex_start) {
-@@ -833,13 +1097,41 @@ ibus_engine_simple_process_key_event (IBusEngine *engine,
-             }
-         }
-     }
-+    if (priv->in_emoji_sequence && have_hex_mods && is_emoji_start) {
-+        if (priv->tentative_emoji && *priv->tentative_emoji) {
-+            ibus_engine_simple_commit_str (simple, priv->tentative_emoji);
-+            g_clear_pointer (&priv->tentative_emoji, g_free);
-+        }
-+        else {
-+            if (n_compose > 0) {
-+                g_clear_pointer (&priv->tentative_emoji, g_free);
-+                priv->in_emoji_sequence = FALSE;
-+                priv->compose_buffer[0] = 0;
-+            }
-+        }
-+    }
- 
-     /* Check for hex sequence start */
-     if (!priv->in_hex_sequence && have_hex_mods && is_hex_start) {
-         priv->compose_buffer[0] = 0;
-         priv->in_hex_sequence = TRUE;
-+        priv->in_emoji_sequence = FALSE;
-         priv->modifiers_dropped = FALSE;
-         priv->tentative_match = 0;
-+        g_clear_pointer (&priv->tentative_emoji, g_free);
-+
-+        // g_debug ("Start HEX MODE");
-+
-+        ibus_engine_simple_update_preedit_text (simple);
-+
-+        return TRUE;
-+    } else if (!priv->in_emoji_sequence && have_hex_mods && is_emoji_start) {
-+        priv->compose_buffer[0] = 0;
-+        priv->in_hex_sequence = FALSE;
-+        priv->in_emoji_sequence = TRUE;
-+        priv->modifiers_dropped = FALSE;
-+        priv->tentative_match = 0;
-+        g_clear_pointer (&priv->tentative_emoji, g_free);
- 
-         // g_debug ("Start HEX MODE");
- 
-@@ -864,9 +1156,20 @@ ibus_engine_simple_process_key_event (IBusEngine *engine,
-             // beep_window (event->window);
-             return TRUE;
-         }
--    }
--    else
-+    } else if (priv->in_emoji_sequence) {
-+        if (printable_keyval) {
-+            priv->compose_buffer[n_compose++] = printable_keyval;
-+        }
-+        else if (is_space && (modifiers & IBUS_SHIFT_MASK)) {
-+            priv->compose_buffer[n_compose++] = IBUS_KEY_space;
-+        }
-+        else if (is_escape) {
-+            ibus_engine_simple_reset (engine);
-+            return TRUE;
-+        }
-+    } else {
-         priv->compose_buffer[n_compose++] = keyval;
-+    }
- 
-     priv->compose_buffer[n_compose] = 0;
- 
-@@ -880,8 +1183,7 @@ ibus_engine_simple_process_key_event (IBusEngine *engine,
-                     ibus_engine_simple_commit_char (simple,
-                             priv->tentative_match);
-                     priv->compose_buffer[0] = 0;
--                }
--                else {
-+                } else {
-                     // FIXME
-                     /* invalid hex sequence */
-                     // beep_window (event->window);
-@@ -899,6 +1201,73 @@ ibus_engine_simple_process_key_event (IBusEngine *engine,
-             return TRUE;
-         }
-     }
-+    else if (priv->in_emoji_sequence) {
-+        if (have_hex_mods && n_compose > 0) {
-+            gboolean update_lookup_table = FALSE;
-+
-+            if (priv->lookup_table_visible) {
-+                switch (keyval) {
-+                case IBUS_KEY_space:
-+                case IBUS_KEY_KP_Space:
-+                    if ((modifiers & IBUS_SHIFT_MASK) == 0) {
-+                        ibus_lookup_table_cursor_down (priv->lookup_table);
-+                        update_lookup_table = TRUE;
-+                    }
-+                    break;
-+                case IBUS_KEY_Down:
-+                    ibus_lookup_table_cursor_down (priv->lookup_table);
-+                    update_lookup_table = TRUE;
-+                    break;
-+                case IBUS_KEY_Up:
-+                    ibus_lookup_table_cursor_up (priv->lookup_table);
-+                    update_lookup_table = TRUE;
-+                    break;
-+                case IBUS_KEY_Page_Down:
-+                    ibus_lookup_table_page_down (priv->lookup_table);
-+                    update_lookup_table = TRUE;
-+                    break;
-+                case IBUS_KEY_Page_Up:
-+                    ibus_lookup_table_page_up (priv->lookup_table);
-+                    update_lookup_table = TRUE;
-+                    break;
-+                default:;
-+                }
-+            }
-+
-+            if (!update_lookup_table) {
-+                if (is_hex_end && !is_space) {
-+                    if (priv->lookup_table) {
-+                        int index = (int) ibus_lookup_table_get_cursor_pos (
-+                                priv->lookup_table);
-+                        check_emoji_table (simple, n_compose, index);
-+                        priv->lookup_table_visible = FALSE;
-+                        update_lookup_table = TRUE;
-+                    }
-+                }
-+                else if (check_emoji_table (simple, n_compose, -1)) {
-+                    update_lookup_table = TRUE;
-+                }
-+            }
-+
-+            if (update_lookup_table)
-+                ibus_engine_simple_update_lookup_and_aux_table (simple);
-+            if (is_hex_end && !is_space) {
-+                if (priv->tentative_emoji && *priv->tentative_emoji) {
-+                    ibus_engine_simple_commit_str (simple,
-+                            priv->tentative_emoji);
-+                    priv->compose_buffer[0] = 0;
-+                } else {
-+                    g_clear_pointer (&priv->tentative_emoji, g_free);
-+                    priv->in_emoji_sequence = FALSE;
-+                    priv->compose_buffer[0] = 0;
-+                }
-+            }
-+
-+            ibus_engine_simple_update_preedit_text (simple);
-+
-+            return TRUE;
-+        }
-+    }
-     else {
-         GSList *list = global_tables;
-         while (list) {
-diff --git a/src/ibusutil.c b/src/ibusutil.c
-index b9f3fdd..bfaa4f4 100644
---- a/src/ibusutil.c
-+++ b/src/ibusutil.c
-@@ -2,8 +2,8 @@
- /* vim:set et sts=4: */
- /* bus - The Input Bus
-  * Copyright (C) 2008-2015 Peng Huang <shawn.p.huang@gmail.com>
-- * Copyright (C) 2010-2015 Takao Fujiwara <takao.fujiwara1@gmail.com>
-- * Copyright (C) 2008-2015 Red Hat, Inc.
-+ * Copyright (C) 2010-2016 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+ * Copyright (C) 2008-2016 Red Hat, Inc.
-  *
-  * This library is free software; you can redistribute it and/or
-  * modify it under the terms of the GNU Lesser General Public
-@@ -34,6 +34,9 @@
- #include <libintl.h>
- #endif
- 
-+#define IBUS_DICT_MAGIC "IBusDict"
-+#define IBUS_DICT_VERSION (1)
-+
- /* gettext macro */
- #define N_(t) t
- 
-@@ -125,6 +128,74 @@ _load_lang()
-     ibus_xml_free (node);
- }
- 
-+static void
-+free_dict_words (gpointer list)
-+{
-+    g_slist_free_full (list, g_free);
-+}
-+
-+static void
-+variant_foreach_add_emoji (gchar           *annotation,
-+                           GSList          *emojis,
-+                           GVariantBuilder *builder)
-+{
-+    int i;
-+    int length = (int) g_slist_length (emojis);
-+    gchar **buff = g_new0 (gchar *, length);
-+    GSList *l = emojis;
-+
-+    for (i = 0; i < length; i++, l = l->next)
-+        buff[i] = (gchar *) l->data;
-+
-+    g_variant_builder_add (builder,
-+                           "{sv}",
-+                           annotation,
-+                           g_variant_new_strv ((const gchar * const  *) buff,
-+                                               length));
-+    g_free (buff);
-+}
-+
-+static GVariant *
-+ibus_emoji_dict_serialize (GHashTable *dict)
-+{
-+    GVariantBuilder builder;
-+
-+    g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
-+    g_hash_table_foreach (dict,  (GHFunc) variant_foreach_add_emoji, &builder);
-+    return g_variant_builder_end (&builder);
-+}
-+
-+static GHashTable *
-+ibus_emoji_dict_deserialize (GVariant *variant)
-+{
-+    GHashTable *dict = NULL;
-+    GVariantIter iter;
-+    gchar *annotate = NULL;
-+    GVariant *emojis_variant = NULL;
-+
-+    dict = g_hash_table_new_full (g_str_hash,
-+                                  g_str_equal,
-+                                  g_free,
-+                                  free_dict_words);
-+
-+    g_variant_iter_init (&iter, variant);
-+    while (g_variant_iter_loop (&iter, "{sv}", &annotate, &emojis_variant)) {
-+        gsize i;
-+        gsize length = 0;
-+        const gchar **array = g_variant_get_strv (emojis_variant, &length);
-+        GSList *emojis = NULL;
-+
-+        for (i = 0; i < length; i++) {
-+            emojis = g_slist_append (emojis, g_strdup (array[i]));
-+        }
-+        g_hash_table_insert (dict, annotate, emojis);
-+        annotate = NULL;
-+        g_clear_pointer (&emojis_variant, g_variant_unref);
-+    }
-+
-+    return dict;
-+}
-+
- const gchar *
- ibus_get_untranslated_language_name (const gchar *_locale)
- {
-@@ -171,3 +242,121 @@ ibus_g_variant_get_child_string (GVariant *variant, gsize index, char **str)
-     g_free (*str);
-     g_variant_get_child (variant, index, "s", str);
- }
-+
-+void
-+ibus_emoji_dict_save (const gchar *path, GHashTable *dict)
-+{
-+    GVariant *variant;
-+    const gchar *header = IBUS_DICT_MAGIC;
-+    const guint16 version = IBUS_DICT_VERSION;
-+    const gchar *contents;
-+    gsize length;
-+    GError *error = NULL;
-+
-+    variant = g_variant_new ("(sqv)",
-+                             header,
-+                             version,
-+                             ibus_emoji_dict_serialize (dict));
-+
-+    contents =  g_variant_get_data (variant);
-+    length =  g_variant_get_size (variant);
-+
-+    if (!g_file_set_contents (path, contents, length, &error)) {
-+        g_warning ("Failed to save emoji dict %s: %s", path, error->message);
-+        g_error_free (error);
-+    }
-+
-+    g_variant_unref (variant);
-+}
-+
-+GHashTable *
-+ibus_emoji_dict_load (const gchar *path)
-+{
-+    gchar *contents = NULL;
-+    gsize length = 0;
-+    GError *error = NULL;
-+    GVariant *variant_table = NULL;
-+    GVariant *variant = NULL;
-+    const gchar *header = NULL;
-+    guint16 version = 0;
-+    GHashTable *retval = NULL;
-+
-+    if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
-+        g_warning ("Emoji dict does not exist: %s", path);
-+        goto out_load_cache;
-+    }
-+
-+    if (!g_file_get_contents (path, &contents, &length, &error)) {
-+        g_warning ("Failed to get dict content %s: %s", path, error->message);
-+        g_error_free (error);
-+        goto out_load_cache;
-+    }
-+
-+    variant_table = g_variant_new_from_data (G_VARIANT_TYPE ("(sq)"),
-+                                             contents,
-+                                             length,
-+                                             FALSE,
-+                                             NULL,
-+                                             NULL);
-+
-+    if (variant_table == NULL) {
-+        g_warning ("cache table is broken.");
-+        goto out_load_cache;
-+    }
-+
-+    g_variant_get (variant_table, "(&sq)", &header, &version);
-+
-+    if (g_strcmp0 (header, IBUS_DICT_MAGIC) != 0) {
-+        g_warning ("cache is not IBusDict.");
-+        goto out_load_cache;
-+    }
-+
-+    if (version != IBUS_DICT_VERSION) {
-+        g_warning ("cache version is different: %u != %u",
-+                   version, IBUS_DICT_VERSION);
-+        goto out_load_cache;
-+    }
-+
-+    version = 0;
-+    header = NULL;
-+    g_variant_unref (variant_table);
-+
-+    variant_table = g_variant_new_from_data (G_VARIANT_TYPE ("(sqv)"),
-+                                             contents,
-+                                             length,
-+                                             FALSE,
-+                                             NULL,
-+                                             NULL);
-+
-+    if (variant_table == NULL) {
-+        g_warning ("cache table is broken.");
-+        goto out_load_cache;
-+    }
-+
-+    g_variant_get (variant_table, "(&sqv)",
-+                   NULL,
-+                   NULL,
-+                   &variant);
-+
-+    if (variant == NULL) {
-+        g_warning ("cache dict is broken.");
-+        goto out_load_cache;
-+    }
-+
-+    retval = ibus_emoji_dict_deserialize (variant);
-+
-+out_load_cache:
-+    if (variant)
-+        g_variant_unref (variant);
-+    if (variant_table)
-+        g_variant_unref (variant_table);
-+
-+    return retval;
-+}
-+
-+GSList *
-+ibus_emoji_dict_lookup (GHashTable  *dict,
-+                        const gchar *annotation)
-+{
-+    return (GSList *) g_hash_table_lookup (dict, annotation);
-+}
-diff --git a/src/ibusutil.h b/src/ibusutil.h
-index 2c1360c..e619b67 100644
---- a/src/ibusutil.h
-+++ b/src/ibusutil.h
-@@ -2,8 +2,8 @@
- /* vim:set et sts=4: */
- /* bus - The Input Bus
-  * Copyright (C) 2008-2015 Peng Huang <shawn.p.huang@gmail.com>
-- * Copyright (C) 2010-2015 Takao Fujiwara <takao.fujiwara1@gmail.com>
-- * Copyright (C) 2008-2015 Red Hat, Inc.
-+ * Copyright (C) 2010-2016 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+ * Copyright (C) 2008-2016 Red Hat, Inc.
-  *
-  * This library is free software; you can redistribute it and/or
-  * modify it under the terms of the GNU Lesser General Public
-@@ -53,4 +53,31 @@ const gchar *    ibus_get_untranslated_language_name
-  */
- const gchar *    ibus_get_language_name         (const gchar    *_locale);
- 
-+/**
-+ * ibus_emoji_dict_save:
-+ * @path: A path of the saved dictionary file.
-+ * @dict: (element-type utf8 gpointer) (transfer none): An Emoji dictionary
-+ *
-+ * Save the Emoji dictionary to the cache file.
-+ */
-+void             ibus_emoji_dict_save           (const gchar    *path,
-+                                                 GHashTable     *dict);
-+/**
-+ * ibus_emoji_dict_load:
-+ * @path: A path of the saved dictionary file.
-+ *
-+ * Returns: (element-type utf8 gpointer) (transfer none): An Emoji dictionary file loaded from the saved cache file.
-+ */
-+GHashTable *     ibus_emoji_dict_load           (const gchar    *path);
-+
-+/**
-+ * ibus_emoji_dict_lookup:
-+ * @dict: (element-type utf8 gpointer) (transfer none): An Emoji dictionary
-+ * @annotation: Annotation for Emoji characters
-+ *
-+ * Returns: (element-type utf8) (transfer none): List of Emoji characters
-+ * This API is for gobject-introspection.
-+ */
-+GSList *         ibus_emoji_dict_lookup         (GHashTable     *dict,
-+                                                 const gchar    *annotation);
- #endif
--- 
-2.7.4
-
-From 0ed644cd2b6c1d15bdba0d1c6d45d162b9b34806 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Thu, 23 Jun 2016 11:52:48 +0900
-Subject: [PATCH 2/4] engine: Add emoji-list.html
-
-Now we copied http://unicode.org/emoji/charts/emoji-list.html to
-http://ibus.github.io/files/ibus/emoji-list.html
-and download the file in the build time.
-We don't save emoji-list.html in the tarball because the file size is
-more than 5MB.
-We always don't get the latest emoji-list.html to avoid the build error.
-
-BUG=https://github.com/ibus/ibus/pull/1864
-R=shawn.p.huang@gmail.com
-
-Review URL: https://codereview.appspot.com/298580043
----
- src/Makefile.am | 23 ++++++++++++++++++++++-
- 1 file changed, 22 insertions(+), 1 deletion(-)
-
-diff --git a/src/Makefile.am b/src/Makefile.am
-index a33b67d..22e031f 100644
---- a/src/Makefile.am
-+++ b/src/Makefile.am
-@@ -29,6 +29,15 @@ endif
- 
- SUBDIRS = . $(TESTS_DIR)
- 
-+IBUS_V_wget = $(ibus__v_wget_@AM_V@)
-+ibus__v_wget_ = $(ibus__v_wget_@AM_DEFAULT_V@)
-+ibus__v_wget_0 = -nv
-+ibus__v_wget_1 =
-+IBUS_V_diff = $(ibus__v_diff_@AM_V@)
-+ibus__v_diff_ = $(ibus__v_diff_@AM_DEFAULT_V@)
-+ibus__v_diff_0 = -q
-+ibus__v_diff_1 =
-+
- # libibus = libibus-@IBUS_API_VERSION@.la
- libibus = libibus-1.0.la
- 
-@@ -239,6 +248,18 @@ dict_DATA = emoji.dict
- 
- noinst_PROGRAMS = emoji-parser
- 
-+emoji-list.html:
-+	$(AM_V_at)wget $(IBUS_V_wget) \
-+                http://ibus.github.io/files/ibus/emoji-list.html
-+	$(AM_V_at)wget $(IBUS_V_wget) \
-+                http://unicode.org/emoji/charts/emoji-list.html \
-+	        -O latest-emoji-list.html
-+	$(AM_V_at)diff $(IBUS_V_diff) emoji-list.html latest-emoji-list.html; \
-+	if test $$? -ne 0; then \
-+	    echo "#### WARNING: emoji-list.html is old." >&2; \
-+	fi; \
-+	rm latest-emoji-list.html;
-+
- emoji.dict: emoji-parser emoji-list.html
- 	$(builddir)/emoji-parser emoji-list.html $@
- 
-@@ -257,11 +278,11 @@ emoji_parser_LDADD =            \
- 
- CLEANFILES +=                   \
-     $(dict_DATA)                \
-+    emoji-list.html             \
-     $(NULL)
- endif
- 
- EXTRA_DIST =                    \
--    emoji-list.html             \
-     emoji-parser.c              \
-     ibusversion.h.in            \
-     ibusmarshalers.list         \
--- 
-2.7.4
-
-From 0ee1896a2b3e75494f8f9fd9d04c27436f0877b8 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Thu, 7 Jul 2016 12:47:34 +0900
-Subject: [PATCH 3/4] engine: Use annotations/en.xml from unocode.org but not
- emoji-list.html
-
-Downloading emoji-list would cause a different build by build site.
-Now save annotations/en.xml from unicode.org and get emoji.json from
-Emoji One.
-en.xml is used for Unicode annotations and emoji.json is used for
-aliases_ascii, e.g. ":)", and category, e.g. "people".
-
-BUG=https://github.com/ibus/ibus/issues/1865
-R=Shawn.P.Huang@gmail.com
-
-Review URL: https://codereview.appspot.com/299530044
----
- COPYING.unicode              |   52 +++
- Makefile.am                  |    1 +
- configure.ac                 |   14 +-
- data/Makefile.am             |    5 +-
- data/annotations/Makefile.am |   27 ++
- data/annotations/en.xml      | 1042 ++++++++++++++++++++++++++++++++++++++++++
- ibus.spec.in                 |   14 +
- src/Makefile.am              |   31 +-
- src/emoji-parser.c           |  605 +++++++++++++++++++-----
- 9 files changed, 1634 insertions(+), 157 deletions(-)
- create mode 100644 COPYING.unicode
- create mode 100644 data/annotations/Makefile.am
- create mode 100644 data/annotations/en.xml
-
-diff --git a/COPYING.unicode b/COPYING.unicode
-new file mode 100644
-index 0000000..28d3060
---- /dev/null
-+++ b/COPYING.unicode
-@@ -0,0 +1,52 @@
-+(Apply to data/annotations/en.xml)
-+
-+UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE
-+
-+    Unicode Data Files include all data files under the directories
-+http://www.unicode.org/Public/, http://www.unicode.org/reports/, and
-+http://www.unicode.org/cldr/data/. Unicode Data Files do not include PDF
-+online code charts under the directory http://www.unicode.org/Public/.
-+Software includes any source code published in the Unicode Standard or under
-+the directories http://www.unicode.org/Public/,
-+http://www.unicode.org/reports/, and http://www.unicode.org/cldr/data/.
-+
-+    NOTICE TO USER: Carefully read the following legal agreement. BY
-+DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S DATA FILES
-+("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), YOU UNEQUIVOCALLY ACCEPT, AND
-+AGREE TO BE BOUND BY, ALL OF THE TERMS AND CONDITIONS OF THIS AGREEMENT. IF
-+YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA
-+FILES OR SOFTWARE.
-+
-+    COPYRIGHT AND PERMISSION NOTICE
-+
-+    Copyright © 1991-2016 Unicode, Inc. All rights reserved. Distributed under
-+the Terms of Use in http://www.unicode.org/copyright.html.
-+
-+    Permission is hereby granted, free of charge, to any person obtaining a
-+copy of the Unicode data files and any associated documentation (the "Data
-+Files") or Unicode software and any associated documentation (the "Software")
-+to deal in the Data Files or Software without restriction, including without
-+limitation the rights to use, copy, modify, merge, publish, distribute, and/or
-+sell copies of the Data Files or Software, and to permit persons to whom the
-+Data Files or Software are furnished to do so, provided that (a) the above
-+copyright notice(s) and this permission notice appear with all copies of the
-+Data Files or Software, (b) both the above copyright notice(s) and this
-+permission notice appear in associated documentation, and (c) there is clear
-+notice in each modified Data File or in the Software as well as in the
-+documentation associated with the Data File(s) or Software that the data or
-+software has been modified.
-+
-+    THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
-+KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD
-+PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
-+THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
-+DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
-+PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
-+ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE
-+DATA FILES OR SOFTWARE.
-+
-+    Except as contained in this notice, the name of a copyright holder shall
-+not be used in advertising or otherwise to promote the sale, use or other
-+dealings in these Data Files or Software without prior written authorization
-+of the copyright holder.
-diff --git a/Makefile.am b/Makefile.am
-index 3c4702c..425d1ec 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -69,6 +69,7 @@ pkgconfig_DATA = ibus-@IBUS_API_VERSION@.pc
- 
- ibus_pc_in = ibus-@IBUS_API_VERSION@.pc.in
- EXTRA_DIST = \
-+	COPYING.unicode \
- 	autogen.sh \
- 	$(ibus_pc_in) \
- 	ibus.spec.in \
-diff --git a/configure.ac b/configure.ac
-index 3128ef9..f789819 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -608,12 +608,20 @@ AC_ARG_ENABLE(emoji-dict,
- )
- AM_CONDITIONAL([ENABLE_EMOJI_DICT], [test x"$enable_emoji_dict" = x"yes"])
- if test x"$enable_emoji_dict" = x"yes"; then
--    PKG_CHECK_MODULES(LIBXML2, [
--        libxml-2.0
-+    PKG_CHECK_MODULES(JSON_GLIB1, [
-+        json-glib-1.0
-     ])
-     enable_emoji_dict="yes (enabled, use --disable-emoji-dict to disable)"
- fi
- 
-+AC_ARG_WITH(emoji-json-file,
-+    AS_HELP_STRING([--with-emoji-json-file[=DIR/emoji.json]],
-+        [Set emoji.json. (default: "/usr/lib/node_modules/emojione/emoji.json")]),
-+    EMOJI_JSON_FILE=$with_emoji_json_file,
-+    EMOJI_JSON_FILE="/usr/lib/node_modules/emojione/emoji.json"
-+)
-+AC_SUBST(EMOJI_JSON_FILE)
-+
- # Check iso-codes.
- PKG_CHECK_MODULES(ISOCODES, [
-     iso-codes
-@@ -639,6 +647,7 @@ engine/Makefile
- util/Makefile
- util/IMdkit/Makefile
- data/Makefile
-+data/annotations/Makefile.am
- data/icons/Makefile
- data/keymaps/Makefile
- data/dconf/Makefile
-@@ -698,6 +707,7 @@ Build options:
-   Enable surrounding-text       $enable_surrounding_text
-   Enable libnotify              $enable_libnotify
-   Enable Emoji dict             $enable_emoji_dict
-+  emoji.json path               $EMOJI_JSON_FILE
-   Run test cases                $enable_tests
- ])
- 
-diff --git a/data/Makefile.am b/data/Makefile.am
-index e41c9a2..d9d613f 100644
---- a/data/Makefile.am
-+++ b/data/Makefile.am
-@@ -2,8 +2,8 @@
- #
- # ibus - The Input Bus
- #
--# Copyright (c) 2007-2010 Peng Huang <shawn.p.huang@gmail.com>
--# Copyright (c) 2007-2010 Red Hat, Inc.
-+# Copyright (c) 2007-2016 Peng Huang <shawn.p.huang@gmail.com>
-+# Copyright (c) 2007-2016 Red Hat, Inc.
- #
- # This library is free software; you can redistribute it and/or
- # modify it under the terms of the GNU Lesser General Public
-@@ -21,6 +21,7 @@
- # USA
- 
- SUBDIRS = \
-+	annotations \
- 	icons \
- 	keymaps \
- 	$(NULL)
-diff --git a/data/annotations/Makefile.am b/data/annotations/Makefile.am
-new file mode 100644
-index 0000000..d87b933
---- /dev/null
-+++ b/data/annotations/Makefile.am
-@@ -0,0 +1,27 @@
-+# vim:set noet ts=4:
-+#
-+# ibus - The Input Bus
-+#
-+# Copyright (c) 2016 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+# Copyright (c) 2016 Red Hat, Inc.
-+#
-+# This library is free software; you can redistribute it and/or
-+# modify it under the terms of the GNU Lesser General Public
-+# License as published by the Free Software Foundation; either
-+# version 2.1 of the License, or (at your option) any later version.
-+#
-+# This library is distributed in the hope that it will be useful,
-+# but WITHOUT ANY WARRANTY; without even the implied warranty of
-+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+# Lesser General Public License for more details.
-+#
-+# You should have received a copy of the GNU Lesser General Public
-+# License along with this library; if not, write to the Free Software
-+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
-+# USA
-+
-+EXTRA_DIST = \
-+	en.xml \
-+	$(NULL)
-+
-+-include $(top_srcdir)/git.mk
-diff --git a/data/annotations/en.xml b/data/annotations/en.xml
-new file mode 100644
-index 0000000..ff7aa89
---- /dev/null
-+++ b/data/annotations/en.xml
-@@ -0,0 +1,1042 @@
-+<?xml version='1.0' encoding='UTF-8' ?>
-+<!DOCTYPE ldml SYSTEM '../../common/dtd/ldml.dtd'>
-+<!--	© 1991-2015 Unicode, Inc.
-+	Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
-+	For terms of use, see http://www.unicode.org/copyright.html
-+	CLDR data files are interpreted according to the LDML specification (http://unicode.org/reports/tr35/)
-+
-+	DO NOT CHANGE MANUALLY! Generated by: GenerateOtherAnnotations
-+ -->
-+<ldml>
-+	<identity>
-+		<version number="$Revision: 12320 $"/>
-+		<language type='en'/>
-+	</identity>
-+	<annotations>
-+		<annotation cp='[😀]' tts='grinning face'>face; grin</annotation>
-+		<annotation cp='[😁]' tts='grinning face with smiling eyes'>eye; face; grin; smile</annotation>
-+		<annotation cp='[😂]' tts='face with tears of joy'>face; joy; laugh; tear</annotation>
-+		<annotation cp='[😃]' tts='smiling face with open mouth'>face; mouth; open; smile</annotation>
-+		<annotation cp='[😄]' tts='smiling face with open mouth and smiling eyes'>eye; face; mouth; open; smile</annotation>
-+		<annotation cp='[😅]' tts='smiling face with open mouth and cold sweat'>cold; face; open; smile; sweat</annotation>
-+		<annotation cp='[😆]' tts='smiling face with open mouth and tightly-closed eyes'>face; laugh; mouth; open; satisfied; smile</annotation>
-+		<annotation cp='[😉]' tts='winking face'>face; wink</annotation>
-+		<annotation cp='[😊]' tts='smiling face with smiling eyes'>blush; eye; face; smile</annotation>
-+		<annotation cp='[😋]' tts='face savouring delicious food'>delicious; face; savouring; smile; um; yum</annotation>
-+		<annotation cp='[😎]' tts='smiling face with sunglasses'>bright; cool; eye; eyewear; face; glasses; smile; sun; sunglasses; weather</annotation>
-+		<annotation cp='[😍]' tts='smiling face with heart-shaped eyes'>eye; face; heart; love; smile</annotation>
-+		<annotation cp='[😘]' tts='face throwing a kiss'>face; heart; kiss</annotation>
-+		<annotation cp='[😗]' tts='kissing face'>face; kiss</annotation>
-+		<annotation cp='[😙]' tts='kissing face with smiling eyes'>eye; face; kiss; smile</annotation>
-+		<annotation cp='[😚]' tts='kissing face with closed eyes'>closed; eye; face; kiss</annotation>
-+		<annotation cp='[☺]' tts='smiling face'>face; outlined; relaxed; smile</annotation>
-+		<annotation cp='[🙂]' tts='slightly smiling face'>face; smile</annotation>
-+		<annotation cp='[🤗]' tts='hugging face'>face; hug; hugging</annotation>
-+		<annotation cp='[😇]' tts='smiling face with halo'>angel; face; fairy tale; fantasy; halo; innocent; smile</annotation>
-+		<annotation cp='[🤔]' tts='thinking face'>face; thinking</annotation>
-+		<annotation cp='[😐]' tts='neutral face'>deadpan; face; neutral</annotation>
-+		<annotation cp='[😑]' tts='expressionless face'>expressionless; face; inexpressive; unexpressive</annotation>
-+		<annotation cp='[😶]' tts='face without mouth'>face; mouth; quiet; silent</annotation>
-+		<annotation cp='[🙄]' tts='face with rolling eyes'>eyes; face; rolling</annotation>
-+		<annotation cp='[😏]' tts='smirking face'>face; smirk</annotation>
-+		<annotation cp='[😣]' tts='persevering face'>face; persevere</annotation>
-+		<annotation cp='[😥]' tts='disappointed but relieved face'>disappointed; face; relieved; whew</annotation>
-+		<annotation cp='[😮]' tts='face with open mouth'>face; mouth; open; sympathy</annotation>
-+		<annotation cp='[🤐]' tts='zipper-mouth face'>face; mouth; zipper</annotation>
-+		<annotation cp='[😯]' tts='hushed face'>face; hushed; stunned; surprised</annotation>
-+		<annotation cp='[😪]' tts='sleepy face'>face; sleep</annotation>
-+		<annotation cp='[😫]' tts='tired face'>face; tired</annotation>
-+		<annotation cp='[😴]' tts='sleeping face'>face; sleep; zzz</annotation>
-+		<annotation cp='[😌]' tts='relieved face'>face; relieved</annotation>
-+		<annotation cp='[🤓]' tts='nerd face'>face; geek; nerd</annotation>
-+		<annotation cp='[😛]' tts='face with stuck-out tongue'>face; tongue</annotation>
-+		<annotation cp='[😜]' tts='face with stuck-out tongue and winking eye'>eye; face; joke; tongue; wink</annotation>
-+		<annotation cp='[😝]' tts='face with stuck-out tongue and tightly-closed eyes'>eye; face; horrible; taste; tongue</annotation>
-+		<annotation cp='[☹]' tts='frowning face'>face; frown</annotation>
-+		<annotation cp='[🙁]' tts='slightly frowning face'>face; frown</annotation>
-+		<annotation cp='[😒]' tts='unamused face'>face; unamused; unhappy</annotation>
-+		<annotation cp='[😓]' tts='face with cold sweat'>cold; face; sweat</annotation>
-+		<annotation cp='[😔]' tts='pensive face'>dejected; face; pensive</annotation>
-+		<annotation cp='[😕]' tts='confused face'>confused; face</annotation>
-+		<annotation cp='[😖]' tts='confounded face'>confounded; face</annotation>
-+		<annotation cp='[🙃]' tts='upside-down face'>face; upside-down</annotation>
-+		<annotation cp='[😷]' tts='face with medical mask'>cold; doctor; face; mask; medicine; sick</annotation>
-+		<annotation cp='[🤒]' tts='face with thermometer'>face; ill; sick; thermometer</annotation>
-+		<annotation cp='[🤕]' tts='face with head-bandage'>bandage; face; hurt; injury</annotation>
-+		<annotation cp='[🤑]' tts='money-mouth face'>face; money; mouth</annotation>
-+		<annotation cp='[😲]' tts='astonished face'>astonished; face; shocked; totally</annotation>
-+		<annotation cp='[😞]' tts='disappointed face'>disappointed; face</annotation>
-+		<annotation cp='[😟]' tts='worried face'>face; worried</annotation>
-+		<annotation cp='[😤]' tts='face with steam from nose'>face; triumph; won</annotation>
-+		<annotation cp='[😢]' tts='crying face'>cry; face; sad; tear</annotation>
-+		<annotation cp='[😭]' tts='loudly crying face'>cry; face; sad; sob; tear</annotation>
-+		<annotation cp='[😦]' tts='frowning face with open mouth'>face; frown; mouth; open</annotation>
-+		<annotation cp='[😧]' tts='anguished face'>anguished; face</annotation>
-+		<annotation cp='[😨]' tts='fearful face'>face; fear; fearful; scared</annotation>
-+		<annotation cp='[😩]' tts='weary face'>face; tired; weary</annotation>
-+		<annotation cp='[😬]' tts='grimacing face'>face; grimace</annotation>
-+		<annotation cp='[😰]' tts='face with open mouth and cold sweat'>blue; cold; face; mouth; open; rushed; sweat</annotation>
-+		<annotation cp='[😱]' tts='face screaming in fear'>face; fear; fearful; munch; scared; scream</annotation>
-+		<annotation cp='[😳]' tts='flushed face'>dazed; face; flushed</annotation>
-+		<annotation cp='[😵]' tts='dizzy face'>dizzy; face</annotation>
-+		<annotation cp='[😡]' tts='pouting face'>angry; face; mad; pouting; rage; red</annotation>
-+		<annotation cp='[😠]' tts='angry face'>angry; face; mad</annotation>
-+		<annotation cp='[😈]' tts='smiling face with horns'>face; fairy tale; fantasy; horns; smile</annotation>
-+		<annotation cp='[👿]' tts='imp'>demon; devil; face; fairy tale; fantasy</annotation>
-+		<annotation cp='[👹]' tts='ogre'>creature; face; fairy tale; fantasy; japanese; monster</annotation>
-+		<annotation cp='[👺]' tts='goblin'>creature; face; fairy tale; fantasy; japanese; monster</annotation>
-+		<annotation cp='[💀]' tts='skull'>body; death; face; fairy tale; monster</annotation>
-+		<annotation cp='[☠]' tts='skull and crossbones'>body; crossbones; death; face; monster; skull</annotation>
-+		<annotation cp='[👻]' tts='ghost'>creature; face; fairy tale; fantasy; monster</annotation>
-+		<annotation cp='[👽]' tts='alien'>creature; extraterrestrial; face; fairy tale; fantasy; monster; space; ufo</annotation>
-+		<annotation cp='[👾]' tts='alien monster'>alien; creature; extraterrestrial; face; fairy tale; fantasy; monster; space; ufo</annotation>
-+		<annotation cp='[🤖]' tts='robot face'>face; monster; robot</annotation>
-+		<annotation cp='[💩]' tts='pile of poo'>comic; dung; face; monster; poo; poop</annotation>
-+		<annotation cp='[😺]' tts='smiling cat face with open mouth'>cat; face; mouth; open; smile</annotation>
-+		<annotation cp='[😸]' tts='grinning cat face with smiling eyes'>cat; eye; face; grin; smile</annotation>
-+		<annotation cp='[😹]' tts='cat face with tears of joy'>cat; face; joy; tear</annotation>
-+		<annotation cp='[😻]' tts='smiling cat face with heart-shaped eyes'>cat; eye; face; heart; love; smile</annotation>
-+		<annotation cp='[😼]' tts='cat face with wry smile'>cat; face; ironic; smile; wry</annotation>
-+		<annotation cp='[😽]' tts='kissing cat face with closed eyes'>cat; eye; face; kiss</annotation>
-+		<annotation cp='[🙀]' tts='weary cat face'>cat; face; oh; surprised; weary</annotation>
-+		<annotation cp='[😿]' tts='crying cat face'>cat; cry; face; sad; tear</annotation>
-+		<annotation cp='[😾]' tts='pouting cat face'>cat; face; pouting</annotation>
-+		<annotation cp='[🙈]' tts='see-no-evil'>evil; face; forbidden; gesture; monkey; no; not; prohibited; see</annotation>
-+		<annotation cp='[🙉]' tts='hear-no-evil'>evil; face; forbidden; gesture; hear; monkey; no; not; prohibited</annotation>
-+		<annotation cp='[🙊]' tts='speak-no-evil'>evil; face; forbidden; gesture; monkey; no; not; prohibited; speak</annotation>
-+		<annotation cp='[👦]' tts='boy'>boy</annotation>
-+		<annotation cp='[👧]' tts='girl'>maiden; virgin; virgo; zodiac</annotation>
-+		<annotation cp='[👨]' tts='man'>man</annotation>
-+		<annotation cp='[👩]' tts='woman'>woman</annotation>
-+		<annotation cp='[👴]' tts='old man'>man; old</annotation>
-+		<annotation cp='[👵]' tts='old woman'>old; woman</annotation>
-+		<annotation cp='[👶]' tts='baby'>baby</annotation>
-+		<annotation cp='[👱]' tts='person with blond hair'>blond</annotation>
-+		<annotation cp='[👮]' tts='police officer'>cop; officer; police</annotation>
-+		<annotation cp='[👲]' tts='man with chinese cap'>gua pi mao; hat; man</annotation>
-+		<annotation cp='[👳]' tts='man with turban'>man; turban</annotation>
-+		<annotation cp='[👷]' tts='construction worker'>construction; hat; worker</annotation>
-+		<annotation cp='[⛑]' tts='helmet with white cross'>aid; cross; face; hat; helmet</annotation>
-+		<annotation cp='[👸]' tts='princess'>fairy tale; fantasy</annotation>
-+		<annotation cp='[💂]' tts='guardsman'>guard</annotation>
-+		<annotation cp='[🕵]' tts='detective'>sleuth; spy</annotation>
-+		<annotation cp='[🎅]' tts='santa claus'>celebration; christmas; fairy tale; fantasy; father; santa</annotation>
-+		<annotation cp='[👼]' tts='baby angel'>angel; baby; face; fairy tale; fantasy</annotation>
-+		<annotation cp='[💆]' tts='face massage'>massage; salon</annotation>
-+		<annotation cp='[💇]' tts='haircut'>barber; beauty; parlor</annotation>
-+		<annotation cp='[👰]' tts='bride with veil'>bride; veil; wedding</annotation>
-+		<annotation cp='[🙍]' tts='person frowning'>frown; gesture</annotation>
-+		<annotation cp='[🙎]' tts='person pouting'>gesture; pouting</annotation>
-+		<annotation cp='[🙅]' tts='gesturing no'>forbidden; gesture; hand; no; not; prohibited</annotation>
-+		<annotation cp='[🙆]' tts='gesturing ok'>gesture; hand; ok</annotation>
-+		<annotation cp='[💁]' tts='information desk person'>hand; help; information; sassy</annotation>
-+		<annotation cp='[🙋]' tts='happy person raising hand'>gesture; hand; happy; raised</annotation>
-+		<annotation cp='[🙇]' tts='person bowing'>apology; bow; gesture; sorry</annotation>
-+		<annotation cp='[🙌]' tts='person raising hands'>body; celebration; gesture; hand; hooray; raised</annotation>
-+		<annotation cp='[🙏]' tts='folded hands'>ask; body; bow; folded; gesture; hand; please; pray; thanks</annotation>
-+		<annotation cp='[🗣]' tts='speaking head'>face; head; silhouette; speak; speaking</annotation>
-+		<annotation cp='[👤]' tts='bust in silhouette'>bust; silhouette</annotation>
-+		<annotation cp='[👥]' tts='busts in silhouette'>bust; silhouette</annotation>
-+		<annotation cp='[🚶]' tts='pedestrian'>hike; walk; walking</annotation>
-+		<annotation cp='[🏃]' tts='runner'>marathon; running</annotation>
-+		<annotation cp='[👯]' tts='women partying'>bunny; dancer; ear; girl; woman</annotation>
-+		<annotation cp='[💃]' tts='dancer'>dancer</annotation>
-+		<annotation cp='[🕴]' tts='man in business suit levitating'>business; man; suit</annotation>
-+		<annotation cp='[💏]' tts='kiss'>couple; romance</annotation>
-+		<annotation cp='[💑]' tts='couple with heart'>couple; heart; love; romance</annotation>
-+		<annotation cp='[👪]' tts='family'>child; father; mother</annotation>
-+		<annotation cp='[👫]' tts='man and woman holding hands'>couple; hand; hold; man; woman</annotation>
-+		<annotation cp='[👬]' tts='two men holding hands'>couple; gemini; hand; hold; man; twins; zodiac</annotation>
-+		<annotation cp='[👭]' tts='two women holding hands'>couple; hand; hold; woman</annotation>
-+		<annotation cp='[🏻]' tts='skin type-1-2'>emoji modifier; fitzpatrick; skin; tone</annotation>
-+		<annotation cp='[🏼]' tts='skin type-3'>emoji modifier; fitzpatrick; skin; tone</annotation>
-+		<annotation cp='[🏽]' tts='skin type-4'>emoji modifier; fitzpatrick; skin; tone</annotation>
-+		<annotation cp='[🏾]' tts='skin type-5'>emoji modifier; fitzpatrick; skin; tone</annotation>
-+		<annotation cp='[🏿]' tts='skin type-6'>emoji modifier; fitzpatrick; skin; tone</annotation>
-+		<annotation cp='[💪]' tts='flexed biceps'>biceps; body; comic; flex; muscle</annotation>
-+		<annotation cp='[👈]' tts='backhand index pointing left'>backhand; body; finger; hand; index; point</annotation>
-+		<annotation cp='[👉]' tts='backhand index pointing right'>backhand; body; finger; hand; index; point</annotation>
-+		<annotation cp='[☝]' tts='index pointing up'>body; finger; hand; index; point; up</annotation>
-+		<annotation cp='[👆]' tts='backhand index pointing up'>backhand; body; finger; hand; index; point; up</annotation>
-+		<annotation cp='[🖕]' tts='middle finger'>body; finger; hand</annotation>
-+		<annotation cp='[👇]' tts='backhand index pointing down'>backhand; body; down; finger; hand; index; point</annotation>
-+		<annotation cp='[✌]' tts='victory hand'>body; hand; v; victory</annotation>
-+		<annotation cp='[🖖]' tts='vulcan salute'>body; finger; hand; spock; vulcan</annotation>
-+		<annotation cp='[🤘]' tts='sign of the horns'>body; finger; hand; horns; rock-on</annotation>
-+		<annotation cp='[🖐]' tts='raised hand with fingers splayed'>body; finger; hand; splayed</annotation>
-+		<annotation cp='[✋]' tts='raised hand'>body; hand</annotation>
-+		<annotation cp='[👌]' tts='ok hand'>body; hand; ok</annotation>
-+		<annotation cp='[👍]' tts='thumbs up'>+1; body; hand; thumb; up</annotation>
-+		<annotation cp='[👎]' tts='thumbs down'>-1; body; down; hand; thumb</annotation>
-+		<annotation cp='[✊]' tts='raised fist'>body; clenched; fist; hand; punch</annotation>
-+		<annotation cp='[👊]' tts='oncoming fist'>body; clenched; fist; hand; punch</annotation>
-+		<annotation cp='[👋]' tts='waving hand'>body; hand; wave; waving</annotation>
-+		<annotation cp='[👏]' tts='clapping hands'>body; clap; hand</annotation>
-+		<annotation cp='[👐]' tts='open hands'>body; hand; open</annotation>
-+		<annotation cp='[✍]' tts='writing hand'>body; hand; write</annotation>
-+		<annotation cp='[💅]' tts='nail polish'>body; care; cosmetics; manicure; nail; polish</annotation>
-+		<annotation cp='[👂]' tts='ear'>body</annotation>
-+		<annotation cp='[👃]' tts='nose'>body</annotation>
-+		<annotation cp='[👣]' tts='footprints'>body; clothing; footprint; print</annotation>
-+		<annotation cp='[👀]' tts='eyes'>body; eye; face</annotation>
-+		<annotation cp='[👁]' tts='eye'>body</annotation>
-+		<annotation cp='[👅]' tts='tongue'>body</annotation>
-+		<annotation cp='[👄]' tts='mouth'>body; lips</annotation>
-+		<annotation cp='[💋]' tts='kiss mark'>heart; kiss; lips; mark; romance</annotation>
-+		<annotation cp='[💘]' tts='heart with arrow'>arrow; cupid; heart; romance</annotation>
-+		<annotation cp='[❤]' tts='red heart'>heart</annotation>
-+		<annotation cp='[💓]' tts='beating heart'>beating; heart; heartbeat; pulsating</annotation>
-+		<annotation cp='[💔]' tts='broken heart'>break; broken; heart</annotation>
-+		<annotation cp='[💕]' tts='two hearts'>heart; love</annotation>
-+		<annotation cp='[💖]' tts='sparkling heart'>excited; heart; sparkle</annotation>
-+		<annotation cp='[💗]' tts='growing heart'>excited; growing; heart; heartpulse; nervous</annotation>
-+		<annotation cp='[💙]' tts='blue heart'>blue; heart</annotation>
-+		<annotation cp='[💚]' tts='green heart'>green; heart</annotation>
-+		<annotation cp='[💛]' tts='yellow heart'>heart; yellow</annotation>
-+		<annotation cp='[💜]' tts='purple heart'>heart; purple</annotation>
-+		<annotation cp='[💝]' tts='heart with ribbon'>heart; ribbon; valentine</annotation>
-+		<annotation cp='[💞]' tts='revolving hearts'>heart; revolving</annotation>
-+		<annotation cp='[💟]' tts='heart decoration'>heart</annotation>
-+		<annotation cp='[❣]' tts='heavy heart exclamation mark ornament'>exclamation; heart; mark; punctuation</annotation>
-+		<annotation cp='[💌]' tts='love letter'>heart; letter; love; mail; romance</annotation>
-+		<annotation cp='[💤]' tts='zzz'>comic; sleep</annotation>
-+		<annotation cp='[💢]' tts='anger symbol'>angry; comic; mad</annotation>
-+		<annotation cp='[💣]' tts='bomb'>comic</annotation>
-+		<annotation cp='[💥]' tts='collision'>boom; comic</annotation>
-+		<annotation cp='[💦]' tts='sweat droplets'>comic; splashing; sweat</annotation>
-+		<annotation cp='[💨]' tts='dashing'>comic; dash; running</annotation>
-+		<annotation cp='[💫]' tts='dizzy'>comic; star</annotation>
-+		<annotation cp='[💬]' tts='speech balloon'>balloon; bubble; comic; dialog; speech</annotation>
-+		<annotation cp='[🗨]' tts='left speech bubble'>dialog; speech</annotation>
-+		<annotation cp='[🗯]' tts='right anger bubble'>angry; balloon; bubble; mad</annotation>
-+		<annotation cp='[💭]' tts='thought balloon'>balloon; bubble; comic; thought</annotation>
-+		<annotation cp='[🕳]' tts='hole'>hole</annotation>
-+		<annotation cp='[👓]' tts='glasses'>clothing; eye; eyeglasses; eyewear</annotation>
-+		<annotation cp='[🕶]' tts='sunglasses'>dark; eye; eyewear; glasses</annotation>
-+		<annotation cp='[👔]' tts='necktie'>clothing</annotation>
-+		<annotation cp='[👕]' tts='t-shirt'>clothing; shirt; tshirt</annotation>
-+		<annotation cp='[👖]' tts='jeans'>clothing; pants; trousers</annotation>
-+		<annotation cp='[👗]' tts='dress'>clothing</annotation>
-+		<annotation cp='[👘]' tts='kimono'>clothing</annotation>
-+		<annotation cp='[👙]' tts='bikini'>clothing; swim</annotation>
-+		<annotation cp='[👚]' tts='woman’s clothes'>clothing; woman</annotation>
-+		<annotation cp='[👛]' tts='purse'>clothing; coin</annotation>
-+		<annotation cp='[👜]' tts='handbag'>bag; clothing</annotation>
-+		<annotation cp='[👝]' tts='pouch'>bag; clothing</annotation>
-+		<annotation cp='[🛍]' tts='shopping bags'>bag; hotel; shopping</annotation>
-+		<annotation cp='[🎒]' tts='school backpack'>bag; satchel; school</annotation>
-+		<annotation cp='[👞]' tts='man’s shoe'>clothing; man; shoe</annotation>
-+		<annotation cp='[👟]' tts='running shoe'>athletic; clothing; shoe; sneaker</annotation>
-+		<annotation cp='[👠]' tts='high-heeled shoe'>clothing; heel; shoe; woman</annotation>
-+		<annotation cp='[👡]' tts='woman’s sandal'>clothing; sandal; shoe; woman</annotation>
-+		<annotation cp='[👢]' tts='woman’s boot'>boot; clothing; shoe; woman</annotation>
-+		<annotation cp='[👑]' tts='crown'>clothing; king; queen</annotation>
-+		<annotation cp='[👒]' tts='woman’s hat'>clothing; hat; woman</annotation>
-+		<annotation cp='[🎩]' tts='top hat'>clothing; hat; top; tophat</annotation>
-+		<annotation cp='[🎓]' tts='graduation cap'>cap; celebration; clothing; graduation; hat</annotation>
-+		<annotation cp='[📿]' tts='prayer beads'>beads; clothing; necklace; prayer; religion</annotation>
-+		<annotation cp='[💄]' tts='lipstick'>cosmetics; makeup</annotation>
-+		<annotation cp='[💍]' tts='ring'>diamond; romance</annotation>
-+		<annotation cp='[💎]' tts='gem stone'>diamond; gem; jewel; romance</annotation>
-+		<annotation cp='[🐵]' tts='monkey face'>face; monkey</annotation>
-+		<annotation cp='[🐒]' tts='monkey'>monkey</annotation>
-+		<annotation cp='[🐶]' tts='dog face'>dog; face; pet</annotation>
-+		<annotation cp='[🐕]' tts='dog'>pet</annotation>
-+		<annotation cp='[🐩]' tts='poodle'>dog</annotation>
-+		<annotation cp='[🐺]' tts='wolf face'>face; wolf</annotation>
-+		<annotation cp='[🐱]' tts='cat face'>cat; face; pet</annotation>
-+		<annotation cp='[🐈]' tts='cat'>pet</annotation>
-+		<annotation cp='[🦁]' tts='lion face'>face; leo; lion; zodiac</annotation>
-+		<annotation cp='[🐯]' tts='tiger face'>face; tiger</annotation>
-+		<annotation cp='[🐅]' tts='tiger'>tiger</annotation>
-+		<annotation cp='[🐆]' tts='leopard'>leopard</annotation>
-+		<annotation cp='[🐴]' tts='horse face'>face; horse</annotation>
-+		<annotation cp='[🐎]' tts='horse'>racehorse; racing</annotation>
-+		<annotation cp='[🦄]' tts='unicorn face'>face; unicorn</annotation>
-+		<annotation cp='[🐮]' tts='cow face'>cow; face</annotation>
-+		<annotation cp='[🐂]' tts='ox'>bull; taurus; zodiac</annotation>
-+		<annotation cp='[🐃]' tts='water buffalo'>buffalo; water</annotation>
-+		<annotation cp='[🐄]' tts='cow'>cow</annotation>
-+		<annotation cp='[🐷]' tts='pig face'>face; pig</annotation>
-+		<annotation cp='[🐖]' tts='pig'>sow</annotation>
-+		<annotation cp='[🐗]' tts='boar'>pig</annotation>
-+		<annotation cp='[🐽]' tts='pig nose'>face; nose; pig</annotation>
-+		<annotation cp='[🐏]' tts='ram'>aries; sheep; zodiac</annotation>
-+		<annotation cp='[🐑]' tts='sheep'>ewe</annotation>
-+		<annotation cp='[🐐]' tts='goat'>capricorn; zodiac</annotation>
-+		<annotation cp='[🐪]' tts='camel'>dromedary; hump</annotation>
-+		<annotation cp='[🐫]' tts='two-hump camel'>bactrian; camel; hump</annotation>
-+		<annotation cp='[🐘]' tts='elephant'>elephant</annotation>
-+		<annotation cp='[🐭]' tts='mouse face'>face; mouse</annotation>
-+		<annotation cp='[🐁]' tts='mouse'>mouse</annotation>
-+		<annotation cp='[🐀]' tts='rat'>rat</annotation>
-+		<annotation cp='[🐹]' tts='hamster face'>face; hamster; pet</annotation>
-+		<annotation cp='[🐰]' tts='rabbit face'>bunny; face; pet; rabbit</annotation>
-+		<annotation cp='[🐇]' tts='rabbit'>bunny; pet</annotation>
-+		<annotation cp='[🐿]' tts='chipmunk'>chipmunk</annotation>
-+		<annotation cp='[🐻]' tts='bear face'>bear; face</annotation>
-+		<annotation cp='[🐨]' tts='koala'>bear</annotation>
-+		<annotation cp='[🐼]' tts='panda face'>face; panda</annotation>
-+		<annotation cp='[🐾]' tts='paw prints'>feet; paw; print</annotation>
-+		<annotation cp='[🦃]' tts='turkey'>turkey</annotation>
-+		<annotation cp='[🐔]' tts='chicken'>chicken</annotation>
-+		<annotation cp='[🐓]' tts='rooster'>rooster</annotation>
-+		<annotation cp='[🐣]' tts='hatching chick'>baby; chick; hatching</annotation>
-+		<annotation cp='[🐤]' tts='baby chick'>baby; chick</annotation>
-+		<annotation cp='[🐥]' tts='front-facing baby chick'>baby; chick</annotation>
-+		<annotation cp='[🐦]' tts='bird'>bird</annotation>
-+		<annotation cp='[🐧]' tts='penguin'>penguin</annotation>
-+		<annotation cp='[🕊]' tts='dove'>bird; fly; peace</annotation>
-+		<annotation cp='[🐸]' tts='frog face'>face; frog</annotation>
-+		<annotation cp='[🐊]' tts='crocodile'>crocodile</annotation>
-+		<annotation cp='[🐢]' tts='turtle'>turtle</annotation>
-+		<annotation cp='[🐍]' tts='snake'>bearer; ophiuchus; serpent; zodiac</annotation>
-+		<annotation cp='[🐲]' tts='dragon face'>dragon; face; fairy tale</annotation>
-+		<annotation cp='[🐉]' tts='dragon'>fairy tale</annotation>
-+		<annotation cp='[🐳]' tts='spouting whale'>face; spouting; whale</annotation>
-+		<annotation cp='[🐋]' tts='whale'>whale</annotation>
-+		<annotation cp='[🐬]' tts='dolphin'>flipper</annotation>
-+		<annotation cp='[🐟]' tts='fish'>pisces; zodiac</annotation>
-+		<annotation cp='[🐠]' tts='tropical fish'>fish; tropical</annotation>
-+		<annotation cp='[🐡]' tts='blowfish'>fish</annotation>
-+		<annotation cp='[🐙]' tts='octopus'>octopus</annotation>
-+		<annotation cp='[🐚]' tts='spiral shell'>shell; spiral</annotation>
-+		<annotation cp='[🦀]' tts='crab'>cancer; zodiac</annotation>
-+		<annotation cp='[🐌]' tts='snail'>snail</annotation>
-+		<annotation cp='[🐛]' tts='bug'>insect</annotation>
-+		<annotation cp='[🐜]' tts='ant'>insect</annotation>
-+		<annotation cp='[🐝]' tts='honeybee'>bee; insect</annotation>
-+		<annotation cp='[🐞]' tts='lady beetle'>beetle; insect; ladybird; ladybug</annotation>
-+		<annotation cp='[🕷]' tts='spider'>insect</annotation>
-+		<annotation cp='[🕸]' tts='spider web'>spider; web</annotation>
-+		<annotation cp='[🦂]' tts='scorpion'>scorpio; scorpius; zodiac</annotation>
-+		<annotation cp='[💐]' tts='bouquet'>flower; plant; romance</annotation>
-+		<annotation cp='[🌸]' tts='cherry blossom'>blossom; cherry; flower; plant</annotation>
-+		<annotation cp='[💮]' tts='white flower'>flower</annotation>
-+		<annotation cp='[🏵]' tts='rosette'>plant</annotation>
-+		<annotation cp='[🌹]' tts='rose'>flower; plant</annotation>
-+		<annotation cp='[🌺]' tts='hibiscus'>flower; plant</annotation>
-+		<annotation cp='[🌻]' tts='sunflower'>flower; plant; sun</annotation>
-+		<annotation cp='[🌼]' tts='blossom'>flower; plant</annotation>
-+		<annotation cp='[🌷]' tts='tulip'>flower; plant</annotation>
-+		<annotation cp='[🌱]' tts='seedling'>plant; young</annotation>
-+		<annotation cp='[🌲]' tts='evergreen'>plant; tree</annotation>
-+		<annotation cp='[🌳]' tts='deciduous tree'>deciduous; plant; shedding; tree</annotation>
-+		<annotation cp='[🌴]' tts='palm tree'>palm; plant; tree</annotation>
-+		<annotation cp='[🌵]' tts='cactus'>plant</annotation>
-+		<annotation cp='[🌾]' tts='sheaf of rice'>ear; plant; rice</annotation>
-+		<annotation cp='[🌿]' tts='herb'>leaf; plant</annotation>
-+		<annotation cp='[☘]' tts='shamrock'>plant</annotation>
-+		<annotation cp='[🍀]' tts='four leaf clover'>4; clover; four; leaf; plant</annotation>
-+		<annotation cp='[🍁]' tts='maple leaf'>falling; leaf; maple; plant</annotation>
-+		<annotation cp='[🍂]' tts='fallen leaf'>falling; leaf; plant</annotation>
-+		<annotation cp='[🍃]' tts='leaf fluttering in wind'>blow; flutter; leaf; plant; wind</annotation>
-+		<annotation cp='[🍇]' tts='grapes'>fruit; grape; plant</annotation>
-+		<annotation cp='[🍈]' tts='melon'>fruit; plant</annotation>
-+		<annotation cp='[🍉]' tts='watermelon'>fruit; plant</annotation>
-+		<annotation cp='[🍊]' tts='tangerine'>fruit; orange; plant</annotation>
-+		<annotation cp='[🍋]' tts='lemon'>citrus; fruit; plant</annotation>
-+		<annotation cp='[🍌]' tts='banana'>fruit; plant</annotation>
-+		<annotation cp='[🍍]' tts='pineapple'>fruit; plant</annotation>
-+		<annotation cp='[🍎]' tts='red apple'>apple; fruit; plant; red</annotation>
-+		<annotation cp='[🍏]' tts='green apple'>apple; fruit; green; plant</annotation>
-+		<annotation cp='[🍐]' tts='pear'>fruit; plant</annotation>
-+		<annotation cp='[🍑]' tts='peach'>fruit; plant</annotation>
-+		<annotation cp='[🍒]' tts='cherries'>cherry; fruit; plant</annotation>
-+		<annotation cp='[🍓]' tts='strawberry'>berry; fruit; plant</annotation>
-+		<annotation cp='[🍅]' tts='tomato'>plant; vegetable</annotation>
-+		<annotation cp='[🍆]' tts='eggplant'>aubergine; plant; vegetable</annotation>
-+		<annotation cp='[🌽]' tts='ear of corn'>corn; ear; maize; maze; plant</annotation>
-+		<annotation cp='[🌶]' tts='hot pepper'>hot; pepper; plant</annotation>
-+		<annotation cp='[🍄]' tts='mushroom'>plant</annotation>
-+		<annotation cp='[🌰]' tts='chestnut'>plant</annotation>
-+		<annotation cp='[🍞]' tts='bread'>loaf</annotation>
-+		<annotation cp='[🧀]' tts='cheese wedge'>cheese</annotation>
-+		<annotation cp='[🍖]' tts='meat on bone'>bone; meat</annotation>
-+		<annotation cp='[🍗]' tts='poultry leg'>bone; chicken; leg; poultry</annotation>
-+		<annotation cp='[🍔]' tts='hamburger'>burger</annotation>
-+		<annotation cp='[🍟]' tts='french fries'>french; fries</annotation>
-+		<annotation cp='[🍕]' tts='pizza'>cheese; slice</annotation>
-+		<annotation cp='[🌭]' tts='hot dog'>frankfurter; hotdog; sausage</annotation>
-+		<annotation cp='[🌮]' tts='taco'>mexican</annotation>
-+		<annotation cp='[🌯]' tts='burrito'>mexican</annotation>
-+		<annotation cp='[🍿]' tts='popcorn'>popcorn</annotation>
-+		<annotation cp='[🍲]' tts='pot of food'>pot; stew</annotation>
-+		<annotation cp='[🍱]' tts='bento box'>bento; box</annotation>
-+		<annotation cp='[🍘]' tts='rice cracker'>cracker; rice</annotation>
-+		<annotation cp='[🍙]' tts='rice ball'>ball; japanese; rice</annotation>
-+		<annotation cp='[🍚]' tts='cooked rice'>cooked; rice</annotation>
-+		<annotation cp='[🍛]' tts='curry rice'>curry; rice</annotation>
-+		<annotation cp='[🍜]' tts='steaming bowl'>bowl; noodle; ramen; steaming</annotation>
-+		<annotation cp='[🍝]' tts='spaghetti'>pasta</annotation>
-+		<annotation cp='[🍠]' tts='roasted sweet potato'>potato; roasted; sweet</annotation>
-+		<annotation cp='[🍢]' tts='oden'>kebab; seafood; skewer; stick</annotation>
-+		<annotation cp='[🍣]' tts='sushi'>sushi</annotation>
-+		<annotation cp='[🍤]' tts='fried shrimp'>fried; prawn; shrimp; tempura</annotation>
-+		<annotation cp='[🍥]' tts='fish cake with swirl'>cake; fish; pastry; swirl</annotation>
-+		<annotation cp='[🍡]' tts='dango'>dessert; japanese; skewer; stick; sweet</annotation>
-+		<annotation cp='[🍦]' tts='soft ice cream'>cream; dessert; ice; icecream; soft; sweet</annotation>
-+		<annotation cp='[🍧]' tts='shaved ice'>dessert; ice; shaved; sweet</annotation>
-+		<annotation cp='[🍨]' tts='ice cream'>cream; dessert; ice; sweet</annotation>
-+		<annotation cp='[🍩]' tts='doughnut'>dessert; donut; sweet</annotation>
-+		<annotation cp='[🍪]' tts='cookie'>dessert; sweet</annotation>
-+		<annotation cp='[🎂]' tts='birthday cake'>birthday; cake; celebration; dessert; pastry; sweet</annotation>
-+		<annotation cp='[🍰]' tts='shortcake'>cake; dessert; pastry; slice; sweet</annotation>
-+		<annotation cp='[🍫]' tts='chocolate bar'>bar; chocolate; dessert; sweet</annotation>
-+		<annotation cp='[🍬]' tts='candy'>dessert; sweet</annotation>
-+		<annotation cp='[🍭]' tts='lollipop'>candy; dessert; sweet</annotation>
-+		<annotation cp='[🍮]' tts='custard'>dessert; pudding; sweet</annotation>
-+		<annotation cp='[🍯]' tts='honey pot'>honey; honeypot; pot; sweet</annotation>
-+		<annotation cp='[🍼]' tts='baby bottle'>baby; bottle; drink; milk</annotation>
-+		<annotation cp='[☕]' tts='hot beverage'>beverage; coffee; drink; hot; steaming; tea</annotation>
-+		<annotation cp='[🍵]' tts='teacup without handle'>beverage; cup; drink; tea; teacup</annotation>
-+		<annotation cp='[🍶]' tts='sake'>bar; beverage; bottle; cup; drink</annotation>
-+		<annotation cp='[🍾]' tts='bottle with popping cork'>bar; bottle; cork; drink; popping</annotation>
-+		<annotation cp='[🍷]' tts='wine glass'>bar; beverage; drink; glass; wine</annotation>
-+		<annotation cp='[🍸]' tts='cocktail glass'>bar; cocktail; drink; glass</annotation>
-+		<annotation cp='[🍹]' tts='tropical drink'>bar; drink; tropical</annotation>
-+		<annotation cp='[🍺]' tts='beer mug'>bar; beer; drink; mug</annotation>
-+		<annotation cp='[🍻]' tts='clinking beer mugs'>bar; beer; clink; drink; mug</annotation>
-+		<annotation cp='[🍽]' tts='fork and knife with plate'>cooking; fork; knife; plate</annotation>
-+		<annotation cp='[🍴]' tts='fork and knife'>cooking; fork; knife</annotation>
-+		<annotation cp='[🍳]' tts='cooking'>egg; frying; pan</annotation>
-+		<annotation cp='[🏺]' tts='amphora'>aquarius; cooking; drink; jug; tool; weapon; zodiac</annotation>
-+		<annotation cp='[🌍]' tts='globe showing europe-africa'>africa; earth; europe; globe; world</annotation>
-+		<annotation cp='[🌎]' tts='globe showing americas'>americas; earth; globe; world</annotation>
-+		<annotation cp='[🌏]' tts='globe showing asia-australia'>asia; australia; earth; globe; world</annotation>
-+		<annotation cp='[🌐]' tts='globe with meridians'>earth; globe; meridians; world</annotation>
-+		<annotation cp='[🗺]' tts='world map'>map; world</annotation>
-+		<annotation cp='[🏔]' tts='snow-capped mountain'>cold; mountain; snow</annotation>
-+		<annotation cp='[⛰]' tts='mountain'>mountain</annotation>
-+		<annotation cp='[🌋]' tts='volcano'>eruption; mountain; weather</annotation>
-+		<annotation cp='[🗻]' tts='mount fuji'>fuji; mountain</annotation>
-+		<annotation cp='[🏕]' tts='camping'>camping</annotation>
-+		<annotation cp='[🏖]' tts='beach with umbrella'>beach; umbrella</annotation>
-+		<annotation cp='[🏜]' tts='desert'>desert</annotation>
-+		<annotation cp='[🏝]' tts='desert island'>desert; island</annotation>
-+		<annotation cp='[🏞]' tts='national park'>park</annotation>
-+		<annotation cp='[🏟]' tts='stadium'>stadium</annotation>
-+		<annotation cp='[🏛]' tts='classical building'>building; classical</annotation>
-+		<annotation cp='[🏗]' tts='building construction'>building; construction</annotation>
-+		<annotation cp='[🏘]' tts='house buildings'>building; house</annotation>
-+		<annotation cp='[🏙]' tts='cityscape'>building; city</annotation>
-+		<annotation cp='[🏚]' tts='derelict house building'>building; derelict; house</annotation>
-+		<annotation cp='[🏠]' tts='house building'>building; home; house</annotation>
-+		<annotation cp='[🏡]' tts='house with garden'>building; garden; home; house</annotation>
-+		<annotation cp='[⛪]' tts='church'>building; christian; cross; religion</annotation>
-+		<annotation cp='[🕋]' tts='kaaba'>islam; muslim; religion</annotation>
-+		<annotation cp='[🕌]' tts='mosque'>islam; muslim; religion</annotation>
-+		<annotation cp='[🕍]' tts='synagogue'>jew; jewish; religion; temple</annotation>
-+		<annotation cp='[⛩]' tts='shinto shrine'>religion; shinto; shrine</annotation>
-+		<annotation cp='[🏢]' tts='office building'>building</annotation>
-+		<annotation cp='[🏣]' tts='japanese post office'>building; japanese; post</annotation>
-+		<annotation cp='[🏤]' tts='post office'>building; european; post</annotation>
-+		<annotation cp='[🏥]' tts='hospital'>building; doctor; medicine</annotation>
-+		<annotation cp='[🏦]' tts='bank'>building</annotation>
-+		<annotation cp='[🏨]' tts='hotel'>building</annotation>
-+		<annotation cp='[🏩]' tts='love hotel'>building; hotel; love</annotation>
-+		<annotation cp='[🏪]' tts='convenience store'>building; convenience; store</annotation>
-+		<annotation cp='[🏫]' tts='school'>building</annotation>
-+		<annotation cp='[🏬]' tts='department store'>building; department; store</annotation>
-+		<annotation cp='[🏭]' tts='factory'>building</annotation>
-+		<annotation cp='[🏯]' tts='japanese castle'>building; castle; japanese</annotation>
-+		<annotation cp='[🏰]' tts='castle'>building; european</annotation>
-+		<annotation cp='[💒]' tts='wedding'>chapel; romance</annotation>
-+		<annotation cp='[🗼]' tts='tokyo tower'>tokyo; tower</annotation>
-+		<annotation cp='[🗽]' tts='statue of liberty'>liberty; statue</annotation>
-+		<annotation cp='[🗾]' tts='map of japan'>japan; map</annotation>
-+		<annotation cp='[⛲]' tts='fountain'>fountain</annotation>
-+		<annotation cp='[⛺]' tts='tent'>camping</annotation>
-+		<annotation cp='[🌁]' tts='foggy'>fog; weather</annotation>
-+		<annotation cp='[🌃]' tts='night with stars'>night; star; weather</annotation>
-+		<annotation cp='[🌄]' tts='sunrise over mountains'>morning; mountain; sun; sunrise; weather</annotation>
-+		<annotation cp='[🌅]' tts='sunrise'>morning; sun; weather</annotation>
-+		<annotation cp='[🌆]' tts='cityscape at dusk'>building; city; dusk; evening; landscape; sun; sunset; weather</annotation>
-+		<annotation cp='[🌇]' tts='sunset'>building; dusk; sun; weather</annotation>
-+		<annotation cp='[🌉]' tts='bridge at night'>bridge; night; weather</annotation>
-+		<annotation cp='[♨]' tts='hot springs'>hot; hotsprings; springs; steaming</annotation>
-+		<annotation cp='[🌌]' tts='milky way'>space; weather</annotation>
-+		<annotation cp='[🎠]' tts='carousel horse'>carousel; horse</annotation>
-+		<annotation cp='[🎡]' tts='ferris wheel'>amusement park; ferris; wheel</annotation>
-+		<annotation cp='[🎢]' tts='roller coaster'>amusement park; coaster; roller</annotation>
-+		<annotation cp='[💈]' tts='barber pole'>barber; haircut; pole</annotation>
-+		<annotation cp='[🎪]' tts='circus tent'>circus; tent</annotation>
-+		<annotation cp='[🎭]' tts='performing arts'>art; mask; performing; theater; theatre</annotation>
-+		<annotation cp='[🖼]' tts='frame with picture'>art; frame; museum; painting; picture</annotation>
-+		<annotation cp='[🎨]' tts='artist palette'>art; museum; painting; palette</annotation>
-+		<annotation cp='[🎰]' tts='slot machine'>game; slot</annotation>
-+		<annotation cp='[🚂]' tts='locomotive'>engine; railway; steam; train; vehicle</annotation>
-+		<annotation cp='[🚃]' tts='railway car'>car; electric; railway; train; tram; trolleybus; vehicle</annotation>
-+		<annotation cp='[🚄]' tts='high-speed train'>railway; shinkansen; speed; train; vehicle</annotation>
-+		<annotation cp='[🚅]' tts='high-speed train with bullet nose'>bullet; railway; shinkansen; speed; train; vehicle</annotation>
-+		<annotation cp='[🚆]' tts='train'>railway; vehicle</annotation>
-+		<annotation cp='[🚇]' tts='metro'>subway; vehicle</annotation>
-+		<annotation cp='[🚈]' tts='light rail'>railway; vehicle</annotation>
-+		<annotation cp='[🚉]' tts='station'>railway; train; vehicle</annotation>
-+		<annotation cp='[🚊]' tts='tram'>trolleybus; vehicle</annotation>
-+		<annotation cp='[🚝]' tts='monorail'>vehicle</annotation>
-+		<annotation cp='[🚞]' tts='mountain railway'>car; mountain; railway; vehicle</annotation>
-+		<annotation cp='[🚋]' tts='tram car'>car; tram; trolleybus; vehicle</annotation>
-+		<annotation cp='[🚌]' tts='bus'>vehicle</annotation>
-+		<annotation cp='[🚍]' tts='oncoming bus'>bus; oncoming; vehicle</annotation>
-+		<annotation cp='[🚎]' tts='trolleybus'>bus; tram; trolley; vehicle</annotation>
-+		<annotation cp='[🚏]' tts='bus stop'>bus; busstop; stop</annotation>
-+		<annotation cp='[🚐]' tts='minibus'>bus; vehicle</annotation>
-+		<annotation cp='[🚑]' tts='ambulance'>vehicle</annotation>
-+		<annotation cp='[🚒]' tts='fire engine'>engine; fire; truck; vehicle</annotation>
-+		<annotation cp='[🚓]' tts='police car'>car; patrol; police; vehicle</annotation>
-+		<annotation cp='[🚔]' tts='oncoming police car'>car; oncoming; police; vehicle</annotation>
-+		<annotation cp='[🚕]' tts='taxi'>vehicle</annotation>
-+		<annotation cp='[🚖]' tts='oncoming taxi'>oncoming; taxi; vehicle</annotation>
-+		<annotation cp='[🚗]' tts='automobile'>car; vehicle</annotation>
-+		<annotation cp='[🚘]' tts='oncoming automobile'>automobile; car; oncoming; vehicle</annotation>
-+		<annotation cp='[🚙]' tts='recreational vehicle'>recreational; rv; vehicle</annotation>
-+		<annotation cp='[🚚]' tts='delivery truck'>delivery; truck; vehicle</annotation>
-+		<annotation cp='[🚛]' tts='articulated lorry'>lorry; semi; truck; vehicle</annotation>
-+		<annotation cp='[🚜]' tts='tractor'>vehicle</annotation>
-+		<annotation cp='[🚲]' tts='bicycle'>bike; vehicle</annotation>
-+		<annotation cp='[⛽]' tts='fuel pump'>fuel; fuelpump; gas; pump; station</annotation>
-+		<annotation cp='[🛣]' tts='motorway'>highway; road</annotation>
-+		<annotation cp='[🛤]' tts='railway track'>railway; train</annotation>
-+		<annotation cp='[🚨]' tts='police car’s light'>beacon; car; light; police; revolving; vehicle</annotation>
-+		<annotation cp='[🚥]' tts='horizontal traffic light'>light; signal; traffic</annotation>
-+		<annotation cp='[🚦]' tts='vertical traffic light'>light; signal; traffic</annotation>
-+		<annotation cp='[🚧]' tts='construction'>barrier</annotation>
-+		<annotation cp='[⚓]' tts='anchor'>ship; tool</annotation>
-+		<annotation cp='[⛵]' tts='sailboat'>boat; resort; sea; vehicle; yacht</annotation>
-+		<annotation cp='[🚣]' tts='rowboat'>boat; vehicle</annotation>
-+		<annotation cp='[🚤]' tts='speedboat'>boat; vehicle</annotation>
-+		<annotation cp='[🛳]' tts='passenger ship'>passenger; ship; vehicle</annotation>
-+		<annotation cp='[⛴]' tts='ferry'>boat</annotation>
-+		<annotation cp='[🛥]' tts='motor boat'>boat; motorboat; vehicle</annotation>
-+		<annotation cp='[🚢]' tts='ship'>vehicle</annotation>
-+		<annotation cp='[✈]' tts='airplane'>vehicle</annotation>
-+		<annotation cp='[🛩]' tts='small airplane'>airplane; vehicle</annotation>
-+		<annotation cp='[🛫]' tts='airplane departure'>airplane; check-in; departure; departures; vehicle</annotation>
-+		<annotation cp='[🛬]' tts='airplane arrival'>airplane; arrivals; arriving; landing; vehicle</annotation>
-+		<annotation cp='[💺]' tts='seat'>chair</annotation>
-+		<annotation cp='[🚁]' tts='helicopter'>vehicle</annotation>
-+		<annotation cp='[🚟]' tts='suspension railway'>railway; suspension; vehicle</annotation>
-+		<annotation cp='[🚠]' tts='mountain cableway'>cable; gondola; mountain; vehicle</annotation>
-+		<annotation cp='[🚡]' tts='aerial tramway'>aerial; cable; car; gondola; ropeway; tramway; vehicle</annotation>
-+		<annotation cp='[🚀]' tts='rocket'>space; vehicle</annotation>
-+		<annotation cp='[🛰]' tts='satellite'>space; vehicle</annotation>
-+		<annotation cp='[🛎]' tts='bellhop bell'>bell; bellhop; hotel</annotation>
-+		<annotation cp='[🚪]' tts='door'>door</annotation>
-+		<annotation cp='[🛌]' tts='person in bed'>hotel; sleep</annotation>
-+		<annotation cp='[🛏]' tts='bed'>hotel; sleep</annotation>
-+		<annotation cp='[🛋]' tts='couch and lamp'>couch; hotel; lamp</annotation>
-+		<annotation cp='[🚽]' tts='toilet'>toilet</annotation>
-+		<annotation cp='[🚿]' tts='shower'>water</annotation>
-+		<annotation cp='[🛀]' tts='person taking bath'>bathtub; bath</annotation>
-+		<annotation cp='[🛁]' tts='bathtub'>bath</annotation>
-+		<annotation cp='[⌛]' tts='hourglass'>sand; timer</annotation>
-+		<annotation cp='[⏳]' tts='hourglass with flowing sand'>hourglass; sand; timer</annotation>
-+		<annotation cp='[⌚]' tts='watch'>clock</annotation>
-+		<annotation cp='[⏰]' tts='alarm clock'>alarm; clock</annotation>
-+		<annotation cp='[⏱]' tts='stopwatch'>clock</annotation>
-+		<annotation cp='[⏲]' tts='timer clock'>clock; timer</annotation>
-+		<annotation cp='[🕰]' tts='mantelpiece clock'>clock</annotation>
-+		<annotation cp='[🕛]' tts='twelve o’clock'>00; 12; 12:00; clock; o’clock; twelve</annotation>
-+		<annotation cp='[🕧]' tts='twelve-thirty'>12; 12:30; 30; clock; thirty; twelve</annotation>
-+		<annotation cp='[🕐]' tts='one o’clock'>00; 1; 1:00; clock; o’clock; one</annotation>
-+		<annotation cp='[🕜]' tts='one-thirty'>1; 1:30; 30; clock; one; thirty</annotation>
-+		<annotation cp='[🕑]' tts='two o’clock'>00; 2; 2:00; clock; o’clock; two</annotation>
-+		<annotation cp='[🕝]' tts='two-thirty'>2; 2:30; 30; clock; thirty; two</annotation>
-+		<annotation cp='[🕒]' tts='three o’clock'>00; 3; 3:00; clock; o’clock; three</annotation>
-+		<annotation cp='[🕞]' tts='three-thirty'>3; 3:30; 30; clock; thirty; three</annotation>
-+		<annotation cp='[🕓]' tts='four o’clock'>00; 4; 4:00; clock; four; o’clock</annotation>
-+		<annotation cp='[🕟]' tts='four-thirty'>30; 4; 4:30; clock; four; thirty</annotation>
-+		<annotation cp='[🕔]' tts='five o’clock'>00; 5; 5:00; clock; five; o’clock</annotation>
-+		<annotation cp='[🕠]' tts='five-thirty'>30; 5; 5:30; clock; five; thirty</annotation>
-+		<annotation cp='[🕕]' tts='six o’clock'>00; 6; 6:00; clock; o’clock; six</annotation>
-+		<annotation cp='[🕡]' tts='six-thirty'>30; 6; 6:30; clock; six; thirty</annotation>
-+		<annotation cp='[🕖]' tts='seven o’clock'>00; 7; 7:00; clock; o’clock; seven</annotation>
-+		<annotation cp='[🕢]' tts='seven-thirty'>30; 7; 7:30; clock; seven; thirty</annotation>
-+		<annotation cp='[🕗]' tts='eight o’clock'>00; 8; 8:00; clock; eight; o’clock</annotation>
-+		<annotation cp='[🕣]' tts='eight-thirty'>30; 8; 8:30; clock; eight; thirty</annotation>
-+		<annotation cp='[🕘]' tts='nine o’clock'>00; 9; 9:00; clock; nine; o’clock</annotation>
-+		<annotation cp='[🕤]' tts='nine-thirty'>30; 9; 9:30; clock; nine; thirty</annotation>
-+		<annotation cp='[🕙]' tts='ten o’clock'>00; 10; 10:00; clock; o’clock; ten</annotation>
-+		<annotation cp='[🕥]' tts='ten-thirty'>10; 10:30; 30; clock; ten; thirty</annotation>
-+		<annotation cp='[🕚]' tts='eleven o’clock'>00; 11; 11:00; clock; eleven; o’clock</annotation>
-+		<annotation cp='[🕦]' tts='eleven-thirty'>11; 11:30; 30; clock; eleven; thirty</annotation>
-+		<annotation cp='[🌑]' tts='new moon'>dark; moon; space; weather</annotation>
-+		<annotation cp='[🌒]' tts='waxing crescent moon'>crescent; moon; space; waxing; weather</annotation>
-+		<annotation cp='[🌓]' tts='first quarter moon'>moon; quarter; space; weather</annotation>
-+		<annotation cp='[🌔]' tts='waxing gibbous moon'>gibbous; moon; space; waxing; weather</annotation>
-+		<annotation cp='[🌕]' tts='full moon'>full; moon; space; weather</annotation>
-+		<annotation cp='[🌖]' tts='waning gibbous moon'>gibbous; moon; space; waning; weather</annotation>
-+		<annotation cp='[🌗]' tts='last quarter moon'>moon; quarter; space; weather</annotation>
-+		<annotation cp='[🌘]' tts='waning crescent moon'>crescent; moon; space; waning; weather</annotation>
-+		<annotation cp='[🌙]' tts='crescent moon'>crescent; moon; space; weather</annotation>
-+		<annotation cp='[🌚]' tts='new moon face'>face; moon; space; weather</annotation>
-+		<annotation cp='[🌛]' tts='first quarter moon with face'>face; moon; quarter; space; weather</annotation>
-+		<annotation cp='[🌜]' tts='last quarter moon with face'>face; moon; quarter; space; weather</annotation>
-+		<annotation cp='[🌡]' tts='thermometer'>weather</annotation>
-+		<annotation cp='[☀]' tts='sun'>bright; rays; space; sunny; weather</annotation>
-+		<annotation cp='[🌝]' tts='full moon with face'>bright; face; full; moon; space; weather</annotation>
-+		<annotation cp='[🌞]' tts='sun with face'>bright; face; space; sun; weather</annotation>
-+		<annotation cp='[⭐]' tts='white medium star'>star</annotation>
-+		<annotation cp='[🌟]' tts='glowing star'>glittery; glow; shining; sparkle; star</annotation>
-+		<annotation cp='[🌠]' tts='shooting star'>falling; shooting; space; star</annotation>
-+		<annotation cp='[☁]' tts='cloud'>weather</annotation>
-+		<annotation cp='[⛅]' tts='sun behind cloud'>cloud; sun; weather</annotation>
-+		<annotation cp='[⛈]' tts='cloud with lightning and rain'>cloud; rain; thunder; weather</annotation>
-+		<annotation cp='[🌤]' tts='sun behind small cloud'>cloud; sun; weather</annotation>
-+		<annotation cp='[🌥]' tts='sun behind large cloud'>cloud; sun; weather</annotation>
-+		<annotation cp='[🌦]' tts='sun behind cloud with rain'>cloud; rain; sun; weather</annotation>
-+		<annotation cp='[🌧]' tts='cloud with rain'>cloud; rain; weather</annotation>
-+		<annotation cp='[🌨]' tts='cloud with snow'>cloud; cold; snow; weather</annotation>
-+		<annotation cp='[🌩]' tts='cloud with lightning'>cloud; lightning; weather</annotation>
-+		<annotation cp='[🌪]' tts='tornado'>cloud; weather; whirlwind</annotation>
-+		<annotation cp='[🌫]' tts='fog'>cloud; weather</annotation>
-+		<annotation cp='[🌬]' tts='wind face'>blow; cloud; face; weather; wind</annotation>
-+		<annotation cp='[🌀]' tts='cyclone'>dizzy; twister; typhoon; weather</annotation>
-+		<annotation cp='[🌈]' tts='rainbow'>rain; weather</annotation>
-+		<annotation cp='[🌂]' tts='closed umbrella'>clothing; rain; umbrella; weather</annotation>
-+		<annotation cp='[☂]' tts='umbrella'>clothing; rain; weather</annotation>
-+		<annotation cp='[☔]' tts='umbrella with rain drops'>clothing; drop; rain; umbrella; weather</annotation>
-+		<annotation cp='[⛱]' tts='umbrella on ground'>rain; sun; umbrella; weather</annotation>
-+		<annotation cp='[⚡]' tts='high voltage'>danger; electric; electricity; lightning; voltage; zap</annotation>
-+		<annotation cp='[❄]' tts='snowflake'>cold; snow; weather</annotation>
-+		<annotation cp='[☃]' tts='snowman'>cold; snow; weather</annotation>
-+		<annotation cp='[⛄]' tts='snowman without snow'>cold; snow; snowman; weather</annotation>
-+		<annotation cp='[☄]' tts='comet'>space</annotation>
-+		<annotation cp='[🔥]' tts='fire'>flame; tool</annotation>
-+		<annotation cp='[💧]' tts='droplet'>cold; comic; drop; sweat; weather</annotation>
-+		<annotation cp='[🌊]' tts='water wave'>ocean; water; wave; weather</annotation>
-+		<annotation cp='[🎃]' tts='jack-o-lantern'>celebration; halloween; jack; lantern</annotation>
-+		<annotation cp='[🎄]' tts='christmas tree'>celebration; christmas; tree</annotation>
-+		<annotation cp='[🎆]' tts='fireworks'>celebration</annotation>
-+		<annotation cp='[🎇]' tts='sparkler'>celebration; fireworks; sparkle</annotation>
-+		<annotation cp='[✨]' tts='sparkles'>sparkle; star</annotation>
-+		<annotation cp='[🎈]' tts='balloon'>celebration</annotation>
-+		<annotation cp='[🎉]' tts='party popper'>celebration; party; popper; tada</annotation>
-+		<annotation cp='[🎊]' tts='confetti ball'>ball; celebration; confetti</annotation>
-+		<annotation cp='[🎋]' tts='tanabata tree'>banner; celebration; japanese; tree</annotation>
-+		<annotation cp='[🎌]' tts='crossed flags'>celebration; cross; crossed; japanese</annotation>
-+		<annotation cp='[🎍]' tts='pine decoration'>bamboo; celebration; japanese; pine; plant</annotation>
-+		<annotation cp='[🎎]' tts='japanese dolls'>celebration; doll; festival; japanese</annotation>
-+		<annotation cp='[🎏]' tts='carp streamer'>carp; celebration; streamer</annotation>
-+		<annotation cp='[🎐]' tts='wind chime'>bell; celebration; chime; wind</annotation>
-+		<annotation cp='[🎑]' tts='moon ceremony'>celebration; ceremony; moon</annotation>
-+		<annotation cp='[🎀]' tts='ribbon'>celebration</annotation>
-+		<annotation cp='[🎁]' tts='wrapped present'>box; celebration; gift; present; wrapped</annotation>
-+		<annotation cp='[🎖]' tts='military medal'>celebration; medal; military</annotation>
-+		<annotation cp='[🎗]' tts='reminder ribbon'>celebration; reminder; ribbon</annotation>
-+		<annotation cp='[🎞]' tts='film frames'>cinema; film; frames; movie</annotation>
-+		<annotation cp='[🎟]' tts='admission tickets'>admission; ticket</annotation>
-+		<annotation cp='[🎫]' tts='ticket'>admission</annotation>
-+		<annotation cp='[🏷]' tts='label'>label</annotation>
-+		<annotation cp='[⚽]' tts='soccer ball'>ball; soccer</annotation>
-+		<annotation cp='[⚾]' tts='baseball'>ball</annotation>
-+		<annotation cp='[🏀]' tts='basketball'>ball; hoop</annotation>
-+		<annotation cp='[🏈]' tts='american football'>american; ball; football</annotation>
-+		<annotation cp='[🏉]' tts='rugby football'>ball; football; rugby</annotation>
-+		<annotation cp='[🎾]' tts='tennis'>ball; racquet</annotation>
-+		<annotation cp='[🎱]' tts='billiards'>8; 8 ball; ball; billiard; eight; game</annotation>
-+		<annotation cp='[🎳]' tts='bowling'>ball; game</annotation>
-+		<annotation cp='[⛳]' tts='flag in hole'>golf; hole</annotation>
-+		<annotation cp='[🏌]' tts='golfer'>ball; golf</annotation>
-+		<annotation cp='[⛸]' tts='ice skate'>ice; skate</annotation>
-+		<annotation cp='[🎣]' tts='fishing pole'>fish; pole</annotation>
-+		<annotation cp='[🎽]' tts='running shirt'>running; sash; shirt</annotation>
-+		<annotation cp='[🎿]' tts='skis'>ski; snow</annotation>
-+		<annotation cp='[⛷]' tts='skier'>ski; snow</annotation>
-+		<annotation cp='[🏂]' tts='snowboarder'>ski; snow; snowboard</annotation>
-+		<annotation cp='[🏄]' tts='surfer'>surfing</annotation>
-+		<annotation cp='[🏇]' tts='horse racing'>horse; jockey; racehorse; racing</annotation>
-+		<annotation cp='[🏊]' tts='swimmer'>swim</annotation>
-+		<annotation cp='[⛹]' tts='person with ball'>ball</annotation>
-+		<annotation cp='[🏋]' tts='weight lifter'>lifter; weight</annotation>
-+		<annotation cp='[🚴]' tts='bicyclist'>bicycle; bike; cyclist</annotation>
-+		<annotation cp='[🚵]' tts='mountain biker'>bicycle; bicyclist; bike; cyclist; mountain</annotation>
-+		<annotation cp='[🏎]' tts='racing car'>car; racing</annotation>
-+		<annotation cp='[🏍]' tts='motorcycle'>racing</annotation>
-+		<annotation cp='[🏅]' tts='sports medal'>medal</annotation>
-+		<annotation cp='[🏆]' tts='trophy'>prize</annotation>
-+		<annotation cp='[🏏]' tts='cricket'>ball; bat; game</annotation>
-+		<annotation cp='[🏐]' tts='volleyball'>ball; game</annotation>
-+		<annotation cp='[🏑]' tts='field hockey'>ball; field; game; hockey; stick</annotation>
-+		<annotation cp='[🏒]' tts='ice hockey stick and puck'>game; hockey; ice; puck; stick</annotation>
-+		<annotation cp='[🏓]' tts='ping pong'>ball; bat; game; paddle; table tennis</annotation>
-+		<annotation cp='[🏸]' tts='badminton'>birdie; game; racquet; shuttlecock</annotation>
-+		<annotation cp='[🎯]' tts='direct hit'>bull; bullseye; dart; eye; game; hit; target</annotation>
-+		<annotation cp='[🎮]' tts='video game'>controller; game</annotation>
-+		<annotation cp='[🕹]' tts='joystick'>game; video game</annotation>
-+		<annotation cp='[🎲]' tts='game die'>dice; die; game</annotation>
-+		<annotation cp='[♠]' tts='spade suit'>card; game; spade; suit</annotation>
-+		<annotation cp='[♥]' tts='heart suit'>card; game; heart; hearts; suit</annotation>
-+		<annotation cp='[♦]' tts='diamond suit'>card; diamond; diamonds; game; suit</annotation>
-+		<annotation cp='[♣]' tts='club suit'>card; club; clubs; game; suit</annotation>
-+		<annotation cp='[🃏]' tts='joker'>card; game; playing</annotation>
-+		<annotation cp='[🀄]' tts='mahjong red dragon'>game; mahjong; red</annotation>
-+		<annotation cp='[🎴]' tts='flower playing cards'>card; flower; game; japanese; playing</annotation>
-+		<annotation cp='[🔇]' tts='speaker off'>mute; quiet; silent; speaker; volume</annotation>
-+		<annotation cp='[🔈]' tts='speaker'>volume</annotation>
-+		<annotation cp='[🔉]' tts='speaker on'>low; speaker; volume; wave</annotation>
-+		<annotation cp='[🔊]' tts='speaker loud'>3; high; loud; speaker; three; volume</annotation>
-+		<annotation cp='[📢]' tts='loudspeaker'>loud; public address</annotation>
-+		<annotation cp='[📣]' tts='megaphone'>cheering</annotation>
-+		<annotation cp='[📯]' tts='postal horn'>horn; post; postal</annotation>
-+		<annotation cp='[🔔]' tts='bell'>bell</annotation>
-+		<annotation cp='[🔕]' tts='bell with slash'>bell; forbidden; mute; no; not; prohibited; quiet; silent</annotation>
-+		<annotation cp='[🎼]' tts='musical score'>music; score</annotation>
-+		<annotation cp='[🎵]' tts='musical note'>music; note</annotation>
-+		<annotation cp='[🎶]' tts='musical notes'>music; note; notes</annotation>
-+		<annotation cp='[🎙]' tts='studio microphone'>mic; microphone; music; studio</annotation>
-+		<annotation cp='[🎚]' tts='level slider'>level; music; slider</annotation>
-+		<annotation cp='[🎛]' tts='control knobs'>control; knobs; music</annotation>
-+		<annotation cp='[🎤]' tts='microphone'>karaoke; mic</annotation>
-+		<annotation cp='[🎧]' tts='headphone'>earbud</annotation>
-+		<annotation cp='[🎷]' tts='saxophone'>instrument; music; sax</annotation>
-+		<annotation cp='[🎸]' tts='guitar'>instrument; music</annotation>
-+		<annotation cp='[🎹]' tts='musical keyboard'>instrument; keyboard; music; piano</annotation>
-+		<annotation cp='[🎺]' tts='trumpet'>instrument; music</annotation>
-+		<annotation cp='[🎻]' tts='violin'>instrument; music</annotation>
-+		<annotation cp='[📻]' tts='radio'>video</annotation>
-+		<annotation cp='[📱]' tts='mobile phone'>cell; mobile; phone; telephone</annotation>
-+		<annotation cp='[📲]' tts='mobile phone with arrow'>arrow; call; cell; mobile; phone; receive; telephone</annotation>
-+		<annotation cp='[☎]' tts='telephone'>phone</annotation>
-+		<annotation cp='[📞]' tts='telephone receiver'>phone; receiver; telephone</annotation>
-+		<annotation cp='[📟]' tts='pager'>pager</annotation>
-+		<annotation cp='[📠]' tts='fax machine'>fax</annotation>
-+		<annotation cp='[🔋]' tts='battery'>battery</annotation>
-+		<annotation cp='[🔌]' tts='electric plug'>electric; electricity; plug</annotation>
-+		<annotation cp='[💻]' tts='laptop computer'>computer; pc; personal</annotation>
-+		<annotation cp='[🖥]' tts='desktop computer'>computer; desktop</annotation>
-+		<annotation cp='[🖨]' tts='printer'>computer</annotation>
-+		<annotation cp='[⌨]' tts='keyboard'>computer</annotation>
-+		<annotation cp='[🖱]' tts='computer mouse'>3; button; computer; mouse; three</annotation>
-+		<annotation cp='[🖲]' tts='trackball'>computer</annotation>
-+		<annotation cp='[💽]' tts='minidisc'>computer; disk; minidisk; optical</annotation>
-+		<annotation cp='[💾]' tts='floppy disk'>computer; disk; floppy</annotation>
-+		<annotation cp='[💿]' tts='optical disc'>dvd; blu-ray; cd; computer; disk; optical</annotation>
-+		<annotation cp='[📀]' tts='dvd'>blu-ray; cd; computer; disk; optical</annotation>
-+		<annotation cp='[🎥]' tts='movie camera'>camera; cinema; movie</annotation>
-+		<annotation cp='[🎬]' tts='clapper board'>clapper; movie</annotation>
-+		<annotation cp='[📽]' tts='film projector'>cinema; film; movie; projector; video</annotation>
-+		<annotation cp='[📺]' tts='television'>tv; video</annotation>
-+		<annotation cp='[📷]' tts='camera'>video</annotation>
-+		<annotation cp='[📸]' tts='camera with flash'>camera; flash; video</annotation>
-+		<annotation cp='[📹]' tts='video camera'>camera; video</annotation>
-+		<annotation cp='[📼]' tts='videocassette'>tape; vhs; video</annotation>
-+		<annotation cp='[🔍]' tts='left-pointing magnifying glass'>glass; magnifying; search; tool</annotation>
-+		<annotation cp='[🔎]' tts='right-pointing magnifying glass'>glass; magnifying; search; tool</annotation>
-+		<annotation cp='[🔬]' tts='microscope'>tool</annotation>
-+		<annotation cp='[🔭]' tts='telescope'>tool</annotation>
-+		<annotation cp='[📡]' tts='satellite antenna'>antenna; dish; satellite</annotation>
-+		<annotation cp='[🕯]' tts='candle'>light</annotation>
-+		<annotation cp='[💡]' tts='light bulb'>bulb; comic; electric; idea; light</annotation>
-+		<annotation cp='[🔦]' tts='flashlight'>electric; light; tool; torch</annotation>
-+		<annotation cp='[🏮]' tts='red paper lantern'>bar; japanese; lantern; light; red</annotation>
-+		<annotation cp='[📔]' tts='notebook with decorative cover'>book; cover; decorated; notebook</annotation>
-+		<annotation cp='[📕]' tts='closed book'>book; closed</annotation>
-+		<annotation cp='[📖]' tts='open book'>book; open</annotation>
-+		<annotation cp='[📗]' tts='green book'>book; green</annotation>
-+		<annotation cp='[📘]' tts='blue book'>blue; book</annotation>
-+		<annotation cp='[📙]' tts='orange book'>book; orange</annotation>
-+		<annotation cp='[📚]' tts='books'>book</annotation>
-+		<annotation cp='[📓]' tts='notebook'>notebook</annotation>
-+		<annotation cp='[📒]' tts='ledger'>notebook</annotation>
-+		<annotation cp='[📃]' tts='page with curl'>curl; document; page</annotation>
-+		<annotation cp='[📜]' tts='scroll'>paper</annotation>
-+		<annotation cp='[📄]' tts='page facing up'>document; page</annotation>
-+		<annotation cp='[📰]' tts='newspaper'>news; paper</annotation>
-+		<annotation cp='[🗞]' tts='rolled-up newspaper'>news; newspaper; paper; rolled</annotation>
-+		<annotation cp='[📑]' tts='bookmark tabs'>bookmark; mark; marker; tabs</annotation>
-+		<annotation cp='[🔖]' tts='bookmark'>mark</annotation>
-+		<annotation cp='[💰]' tts='money bag'>bag; dollar; money; moneybag</annotation>
-+		<annotation cp='[💴]' tts='yen banknote'>bank; banknote; bill; currency; money; note; yen</annotation>
-+		<annotation cp='[💵]' tts='dollar banknote'>bank; banknote; bill; currency; dollar; money; note</annotation>
-+		<annotation cp='[💶]' tts='euro banknote'>bank; banknote; bill; currency; euro; money; note</annotation>
-+		<annotation cp='[💷]' tts='pound banknote'>bank; banknote; bill; currency; money; note; pound</annotation>
-+		<annotation cp='[💸]' tts='money with wings'>bank; banknote; bill; dollar; fly; money; note; wings</annotation>
-+		<annotation cp='[💳]' tts='credit card'>bank; card; credit; money</annotation>
-+		<annotation cp='[💹]' tts='chart increasing with yen'>bank; chart; currency; graph; growth; market; money; rise; trend; upward; yen</annotation>
-+		<annotation cp='[✉]' tts='envelope'>e-mail; email</annotation>
-+		<annotation cp='[📧]' tts='e-mail'>email; letter; mail</annotation>
-+		<annotation cp='[📨]' tts='incoming envelope'>e-mail; email; envelope; incoming; letter; mail; receive</annotation>
-+		<annotation cp='[📩]' tts='envelope with arrow'>arrow; down; e-mail; email; envelope; letter; mail; outgoing; sent</annotation>
-+		<annotation cp='[📤]' tts='outbox tray'>box; letter; mail; outbox; sent; tray</annotation>
-+		<annotation cp='[📥]' tts='inbox tray'>box; inbox; letter; mail; receive; tray</annotation>
-+		<annotation cp='[📦]' tts='package'>box; parcel</annotation>
-+		<annotation cp='[📫]' tts='closed mailbox with raised flag'>closed; mail; mailbox; postbox</annotation>
-+		<annotation cp='[📪]' tts='closed mailbox with lowered flag'>closed; lowered; mail; mailbox; postbox</annotation>
-+		<annotation cp='[📬]' tts='open mailbox with raised flag'>mail; mailbox; open; postbox</annotation>
-+		<annotation cp='[📭]' tts='open mailbox with lowered flag'>lowered; mail; mailbox; open; postbox</annotation>
-+		<annotation cp='[📮]' tts='postbox'>mail; mailbox</annotation>
-+		<annotation cp='[🗳]' tts='ballot box with ballot'>ballot; box</annotation>
-+		<annotation cp='[✏]' tts='pencil'>pencil</annotation>
-+		<annotation cp='[✒]' tts='black nib'>nib; pen</annotation>
-+		<annotation cp='[🖋]' tts='fountain pen'>fountain; pen</annotation>
-+		<annotation cp='[🖊]' tts='pen'>ballpoint</annotation>
-+		<annotation cp='[🖌]' tts='paintbrush'>painting</annotation>
-+		<annotation cp='[🖍]' tts='crayon'>crayon</annotation>
-+		<annotation cp='[📝]' tts='memo'>pencil</annotation>
-+		<annotation cp='[💼]' tts='briefcase'>briefcase</annotation>
-+		<annotation cp='[📁]' tts='file folder'>file; folder</annotation>
-+		<annotation cp='[📂]' tts='open file folder'>file; folder; open</annotation>
-+		<annotation cp='[🗂]' tts='card index dividers'>card; dividers; index</annotation>
-+		<annotation cp='[📅]' tts='calendar'>date</annotation>
-+		<annotation cp='[📆]' tts='tear-off calendar'>calendar</annotation>
-+		<annotation cp='[🗒]' tts='spiral notepad'>note; pad; spiral</annotation>
-+		<annotation cp='[🗓]' tts='spiral calendar'>calendar; pad; spiral</annotation>
-+		<annotation cp='[📇]' tts='card index'>card; index; rolodex</annotation>
-+		<annotation cp='[📈]' tts='chart increasing'>chart; graph; growth; trend; upward</annotation>
-+		<annotation cp='[📉]' tts='chart decreasing'>chart; down; graph; trend</annotation>
-+		<annotation cp='[📊]' tts='bar chart'>bar; chart; graph</annotation>
-+		<annotation cp='[📋]' tts='clipboard'>clipboard</annotation>
-+		<annotation cp='[📌]' tts='pushpin'>pin</annotation>
-+		<annotation cp='[📍]' tts='round pushpin'>pin; pushpin</annotation>
-+		<annotation cp='[📎]' tts='paperclip'>paperclip</annotation>
-+		<annotation cp='[🖇]' tts='linked paperclips'>link; paperclip</annotation>
-+		<annotation cp='[📏]' tts='straight ruler'>ruler; straight edge</annotation>
-+		<annotation cp='[📐]' tts='triangular ruler'>ruler; set; triangle</annotation>
-+		<annotation cp='[✂]' tts='scissors'>tool</annotation>
-+		<annotation cp='[🗃]' tts='card file box'>box; card; file</annotation>
-+		<annotation cp='[🗄]' tts='file cabinet'>cabinet; file</annotation>
-+		<annotation cp='[🗑]' tts='wastebasket'>wastebasket</annotation>
-+		<annotation cp='[🔒]' tts='lock'>closed</annotation>
-+		<annotation cp='[🔓]' tts='open lock'>lock; open; unlock</annotation>
-+		<annotation cp='[🔏]' tts='lock with pen'>ink; lock; nib; pen; privacy</annotation>
-+		<annotation cp='[🔐]' tts='closed lock with key'>closed; key; lock; secure</annotation>
-+		<annotation cp='[🔑]' tts='key'>lock; password</annotation>
-+		<annotation cp='[🗝]' tts='old key'>clue; key; lock; old</annotation>
-+		<annotation cp='[🔨]' tts='hammer'>tool</annotation>
-+		<annotation cp='[⛏]' tts='pick'>mining; tool</annotation>
-+		<annotation cp='[⚒]' tts='hammer and pick'>hammer; pick; tool</annotation>
-+		<annotation cp='[🛠]' tts='hammer and wrench'>hammer; tool; wrench</annotation>
-+		<annotation cp='[🔧]' tts='wrench'>tool</annotation>
-+		<annotation cp='[🔩]' tts='nut and bolt'>bolt; nut; tool</annotation>
-+		<annotation cp='[⚙]' tts='gear'>tool</annotation>
-+		<annotation cp='[🗜]' tts='compression'>tool; vice</annotation>
-+		<annotation cp='[⚗]' tts='alembic'>chemistry; tool</annotation>
-+		<annotation cp='[⚖]' tts='balance scale'>balance; justice; libra; scales; tool; weight; zodiac</annotation>
-+		<annotation cp='[🔗]' tts='link'>link</annotation>
-+		<annotation cp='[⛓]' tts='chains'>chain</annotation>
-+		<annotation cp='[💉]' tts='syringe'>doctor; medicine; needle; shot; sick; tool</annotation>
-+		<annotation cp='[💊]' tts='pill'>doctor; medicine; sick</annotation>
-+		<annotation cp='[🗡]' tts='dagger'>knife; weapon</annotation>
-+		<annotation cp='[🔪]' tts='kitchen knife'>cooking; hocho; knife; tool; weapon</annotation>
-+		<annotation cp='[⚔]' tts='crossed swords'>crossed; swords; weapon</annotation>
-+		<annotation cp='[🔫]' tts='pistol'>gun; handgun; revolver; tool; weapon</annotation>
-+		<annotation cp='[🛡]' tts='shield'>weapon</annotation>
-+		<annotation cp='[🏹]' tts='bow and arrow'>archer; arrow; bow; sagittarius; tool; weapon; zodiac</annotation>
-+		<annotation cp='[🏁]' tts='chequered flag'>checkered; chequered; racing</annotation>
-+		<annotation cp='[🏳]' tts='waving white flag'>waving</annotation>
-+		<annotation cp='[🏴]' tts='waving black flag'>waving</annotation>
-+		<annotation cp='[🚩]' tts='triangular flag'>post</annotation>
-+		<annotation cp='[🚬]' tts='smoking'>smoking</annotation>
-+		<annotation cp='[⚰]' tts='coffin'>death</annotation>
-+		<annotation cp='[⚱]' tts='funeral urn'>death; funeral; urn</annotation>
-+		<annotation cp='[🗿]' tts='moai'>face; moyai; statue</annotation>
-+		<annotation cp='[🛢]' tts='oil drum'>drum; oil</annotation>
-+		<annotation cp='[🔮]' tts='crystal ball'>ball; crystal; fairy tale; fantasy; fortune; tool</annotation>
-+		<annotation cp='[🏧]' tts='ATM sign'>atm; automated; bank; teller</annotation>
-+		<annotation cp='[🚮]' tts='litter in bin sign'>litter; litterbox</annotation>
-+		<annotation cp='[🚰]' tts='potable water'>drink; potable; water</annotation>
-+		<annotation cp='[♿]' tts='wheelchair'>access</annotation>
-+		<annotation cp='[🚹]' tts='men’s room'>lavatory; man; restroom; wc</annotation>
-+		<annotation cp='[🚺]' tts='women’s room'>lavatory; restroom; wc; woman</annotation>
-+		<annotation cp='[🚻]' tts='restroom'>lavatory; wc</annotation>
-+		<annotation cp='[🚼]' tts='baby symbol'>baby; changing</annotation>
-+		<annotation cp='[🚾]' tts='water closet'>closet; lavatory; restroom; water; wc</annotation>
-+		<annotation cp='[🛂]' tts='passport control'>control; passport</annotation>
-+		<annotation cp='[🛃]' tts='customs'>customs</annotation>
-+		<annotation cp='[🛄]' tts='baggage claim'>baggage; claim</annotation>
-+		<annotation cp='[🛅]' tts='left luggage'>baggage; locker; luggage</annotation>
-+		<annotation cp='[⚠]' tts='warning'>warning</annotation>
-+		<annotation cp='[🚸]' tts='children crossing'>child; crossing; pedestrian; traffic</annotation>
-+		<annotation cp='[⛔]' tts='no entry'>entry; forbidden; no; not; prohibited; traffic</annotation>
-+		<annotation cp='[🚫]' tts='prohibited'>entry; forbidden; no; not</annotation>
-+		<annotation cp='[🚳]' tts='no bicycles'>bicycle; bike; forbidden; no; not; prohibited; vehicle</annotation>
-+		<annotation cp='[🚭]' tts='no smoking'>forbidden; no; not; prohibited; smoking</annotation>
-+		<annotation cp='[🚯]' tts='no littering'>forbidden; litter; no; not; prohibited</annotation>
-+		<annotation cp='[🚱]' tts='non-potable water'>drink; forbidden; no; not; potable; prohibited; water</annotation>
-+		<annotation cp='[🚷]' tts='no pedestrians'>forbidden; no; not; pedestrian; prohibited</annotation>
-+		<annotation cp='[☢]' tts='radioactive'>radioactive</annotation>
-+		<annotation cp='[☣]' tts='biohazard'>biohazard</annotation>
-+		<annotation cp='[⬆]' tts='up arrow'>arrow; cardinal; direction; north</annotation>
-+		<annotation cp='[↗]' tts='up-right arrow'>arrow; direction; intercardinal; northeast</annotation>
-+		<annotation cp='[➡]' tts='right arrow'>arrow; cardinal; direction; east</annotation>
-+		<annotation cp='[↘]' tts='down-right arrow'>arrow; direction; intercardinal; southeast</annotation>
-+		<annotation cp='[⬇]' tts='down arrow'>arrow; cardinal; direction; down; south</annotation>
-+		<annotation cp='[↙]' tts='down-left arrow'>arrow; direction; intercardinal; southwest</annotation>
-+		<annotation cp='[⬅]' tts='left arrow'>arrow; cardinal; direction; west</annotation>
-+		<annotation cp='[↖]' tts='up-left arrow'>arrow; direction; intercardinal; northwest</annotation>
-+		<annotation cp='[↕]' tts='up-down arrow'>arrow</annotation>
-+		<annotation cp='[↔]' tts='left-right arrow'>arrow</annotation>
-+		<annotation cp='[↩]' tts='right arrow curving left'>arrow</annotation>
-+		<annotation cp='[↪]' tts='left arrow curving right'>arrow</annotation>
-+		<annotation cp='[⤴]' tts='right arrow curving up'>arrow</annotation>
-+		<annotation cp='[⤵]' tts='right arrow curving down'>arrow; down</annotation>
-+		<annotation cp='[🔃]' tts='clockwise vertical arrows'>arrow; clockwise; reload</annotation>
-+		<annotation cp='[🔄]' tts='anticlockwise arrows button'>anticlockwise; arrow; counterclockwise; withershins</annotation>
-+		<annotation cp='[🔙]' tts='back arrow'>arrow; back</annotation>
-+		<annotation cp='[🔚]' tts='end arrow'>arrow; end</annotation>
-+		<annotation cp='[🔛]' tts='on! arrow'>arrow; mark; on</annotation>
-+		<annotation cp='[🔜]' tts='soon arrow'>arrow; soon</annotation>
-+		<annotation cp='[🔝]' tts='top arrow'>arrow; top; up</annotation>
-+		<annotation cp='[🛐]' tts='place of worship'>religion; worship</annotation>
-+		<annotation cp='[⚛]' tts='atom symbol'>atheist; atom</annotation>
-+		<annotation cp='[🕉]' tts='om'>hindu; religion</annotation>
-+		<annotation cp='[✡]' tts='star of david'>david; jew; jewish; religion; star</annotation>
-+		<annotation cp='[☸]' tts='wheel of dharma'>buddhist; dharma; religion; wheel</annotation>
-+		<annotation cp='[☯]' tts='yin yang'>religion; tao; taoist; yang; yin</annotation>
-+		<annotation cp='[✝]' tts='latin cross'>christian; cross; religion</annotation>
-+		<annotation cp='[☦]' tts='orthodox cross'>christian; cross; religion</annotation>
-+		<annotation cp='[☪]' tts='star and crescent'>islam; muslim; religion</annotation>
-+		<annotation cp='[☮]' tts='peace symbol'>peace</annotation>
-+		<annotation cp='[🕎]' tts='menorah'>candelabrum; candlestick; religion</annotation>
-+		<annotation cp='[🔯]' tts='dotted six-pointed star'>fortune; star</annotation>
-+		<annotation cp='[♻]' tts='recycling symbol'>recycle</annotation>
-+		<annotation cp='[📛]' tts='name badge'>badge; name</annotation>
-+		<annotation cp='[⚜]' tts='fleur-de-lis'>fleur-de-lis</annotation>
-+		<annotation cp='[🔰]' tts='japanese symbol for beginner'>beginner; chevron; green; japanese; leaf; tool; yellow</annotation>
-+		<annotation cp='[🔱]' tts='trident emblem'>anchor; emblem; ship; tool; trident</annotation>
-+		<annotation cp='[⭕]' tts='heavy large circle'>circle; o</annotation>
-+		<annotation cp='[✅]' tts='white heavy check mark'>check; mark</annotation>
-+		<annotation cp='[☑]' tts='ballot box with check'>ballot; box; check</annotation>
-+		<annotation cp='[✔]' tts='heavy check mark'>check; mark</annotation>
-+		<annotation cp='[✖]' tts='heavy multiplication x'>cancel; multiplication; multiply; x</annotation>
-+		<annotation cp='[❌]' tts='cross mark'>cancel; mark; multiplication; multiply; x</annotation>
-+		<annotation cp='[❎]' tts='cross mark button'>mark; square</annotation>
-+		<annotation cp='[➕]' tts='heavy plus sign'>math; plus</annotation>
-+		<annotation cp='[➖]' tts='heavy minus sign'>math; minus</annotation>
-+		<annotation cp='[➗]' tts='heavy division sign'>division; math</annotation>
-+		<annotation cp='[➰]' tts='curly loop'>curl; loop</annotation>
-+		<annotation cp='[➿]' tts='double curly loop'>curl; double; loop</annotation>
-+		<annotation cp='[〽]' tts='part alternation mark'>mark; part</annotation>
-+		<annotation cp='[✳]' tts='eight-spoked asterisk'>asterisk</annotation>
-+		<annotation cp='[✴]' tts='eight-pointed star'>star</annotation>
-+		<annotation cp='[❇]' tts='sparkle'>sparkle</annotation>
-+		<annotation cp='[💱]' tts='currency exchange'>bank; currency; exchange; money</annotation>
-+		<annotation cp='[💲]' tts='heavy dollar sign'>currency; dollar; money</annotation>
-+		<annotation cp='[‼]' tts='double exclamation mark'>bangbang; exclamation; mark; punctuation</annotation>
-+		<annotation cp='[⁉]' tts='exclamation question mark'>exclamation; interrobang; mark; punctuation; question</annotation>
-+		<annotation cp='[❓]' tts='question mark'>mark; punctuation; question</annotation>
-+		<annotation cp='[❔]' tts='white question mark'>mark; outlined; punctuation; question</annotation>
-+		<annotation cp='[❕]' tts='white exclamation mark'>exclamation; mark; outlined; punctuation</annotation>
-+		<annotation cp='[❗]' tts='exclamation mark'>exclamation; mark; punctuation</annotation>
-+		<annotation cp='[〰]' tts='wavy dash'>dash; punctuation; wavy</annotation>
-+		<annotation cp='[©]' tts='copyright'>copyright</annotation>
-+		<annotation cp='[®]' tts='registered'>registered</annotation>
-+		<annotation cp='[™]' tts='trade mark'>mark; tm; trademark</annotation>
-+		<annotation cp='[♈]' tts='aries'>ram; zodiac</annotation>
-+		<annotation cp='[♉]' tts='taurus'>bull; ox; zodiac</annotation>
-+		<annotation cp='[♊]' tts='gemini'>twins; zodiac</annotation>
-+		<annotation cp='[♋]' tts='cancer'>crab; zodiac</annotation>
-+		<annotation cp='[♌]' tts='leo'>lion; zodiac</annotation>
-+		<annotation cp='[♍]' tts='virgo'>maiden; virgin; zodiac</annotation>
-+		<annotation cp='[♎]' tts='libra'>balance; justice; scales; zodiac</annotation>
-+		<annotation cp='[♏]' tts='scorpius'>scorpio; scorpion; zodiac</annotation>
-+		<annotation cp='[♐]' tts='sagittarius'>archer; zodiac</annotation>
-+		<annotation cp='[♑]' tts='capricorn'>goat; zodiac</annotation>
-+		<annotation cp='[♒]' tts='aquarius'>bearer; water; zodiac</annotation>
-+		<annotation cp='[♓]' tts='pisces'>fish; zodiac</annotation>
-+		<annotation cp='[⛎]' tts='ophiuchus'>bearer; serpent; snake; zodiac</annotation>
-+		<annotation cp='[🔀]' tts='shuffle tracks button'>arrow; crossed</annotation>
-+		<annotation cp='[🔁]' tts='repeat button'>arrow; clockwise; repeat</annotation>
-+		<annotation cp='[🔂]' tts='repeat single button'>arrow; clockwise; once</annotation>
-+		<annotation cp='[▶]' tts='play button'>arrow; play; right; triangle</annotation>
-+		<annotation cp='[⏩]' tts='fast-forword button'>arrow; double; fast; forward</annotation>
-+		<annotation cp='[⏭]' tts='next track button'>arrow; next scene; next track; triangle</annotation>
-+		<annotation cp='[⏯]' tts='play or pause button'>arrow; pause; play; right; triangle</annotation>
-+		<annotation cp='[◀]' tts='reverse button'>arrow; left; reverse; triangle</annotation>
-+		<annotation cp='[⏪]' tts='fast reverse button'>arrow; double; rewind</annotation>
-+		<annotation cp='[⏮]' tts='last track button'>arrow; previous scene; previous track; triangle</annotation>
-+		<annotation cp='[🔼]' tts='up button'>arrow; button; red</annotation>
-+		<annotation cp='[⏫]' tts='fast up button'>arrow; double</annotation>
-+		<annotation cp='[🔽]' tts='down button'>arrow; button; down; red</annotation>
-+		<annotation cp='[⏬]' tts='fast down button'>arrow; double; down</annotation>
-+		<annotation cp='[⏸]' tts='pause button'>bar; double; pause; vertical</annotation>
-+		<annotation cp='[⏹]' tts='stop button'>square; stop</annotation>
-+		<annotation cp='[⏺]' tts='record button'>circle; record</annotation>
-+		<annotation cp='[⏏]' tts='eject button'>eject</annotation>
-+		<annotation cp='[🎦]' tts='cinema'>camera; film; movie</annotation>
-+		<annotation cp='[🔅]' tts='dim button'>brightness; dim; low</annotation>
-+		<annotation cp='[🔆]' tts='bright button'>bright; brightness</annotation>
-+		<annotation cp='[📶]' tts='antenna bars'>antenna; bar; cell; mobile; phone; signal; telephone</annotation>
-+		<annotation cp='[📵]' tts='no mobile phones'>cell; forbidden; mobile; no; not; phone; prohibited; telephone</annotation>
-+		<annotation cp='[📳]' tts='vibration mode'>cell; mobile; mode; phone; telephone; vibration</annotation>
-+		<annotation cp='[📴]' tts='mobile phone off'>cell; mobile; off; phone; telephone</annotation>
-+		<annotation cp='[{#⃣}]' tts='keycap number'>hash; keycap; pound</annotation>
-+		<annotation cp='[{*⃣}]' tts='keycap asterisk'>asterisk; keycap; star</annotation>
-+		<annotation cp='[{0⃣}]' tts='keycap digit zero'>0; keycap; zero</annotation>
-+		<annotation cp='[{1⃣}]' tts='keycap digit one'>1; keycap; one</annotation>
-+		<annotation cp='[{2⃣}]' tts='keycap digit two'>2; keycap; two</annotation>
-+		<annotation cp='[{3⃣}]' tts='keycap digit three'>3; keycap; three</annotation>
-+		<annotation cp='[{4⃣}]' tts='keycap digit four'>4; four; keycap</annotation>
-+		<annotation cp='[{5⃣}]' tts='keycap digit five'>5; five; keycap</annotation>
-+		<annotation cp='[{6⃣}]' tts='keycap digit six'>6; keycap; six</annotation>
-+		<annotation cp='[{7⃣}]' tts='keycap digit seven'>7; keycap; seven</annotation>
-+		<annotation cp='[{8⃣}]' tts='keycap digit eight'>8; eight; keycap</annotation>
-+		<annotation cp='[{9⃣}]' tts='keycap digit nine'>9; keycap; nine</annotation>
-+		<annotation cp='[🔟]' tts='keycap ten'>10; keycap; ten</annotation>
-+		<annotation cp='[💯]' tts='hundred points'>100; full; hundred; score</annotation>
-+		<annotation cp='[🔞]' tts='no one under eighteen'>18; age restriction; eighteen; forbidden; no; not; prohibited; underage</annotation>
-+		<annotation cp='[🔠]' tts='input latin uppercase'>input; latin; letters; uppercase</annotation>
-+		<annotation cp='[🔡]' tts='input latin lowercase'>abcd; input; latin; letters; lowercase</annotation>
-+		<annotation cp='[🔢]' tts='input numbers'>1234; input; numbers</annotation>
-+		<annotation cp='[🔣]' tts='input symbols'>input</annotation>
-+		<annotation cp='[🔤]' tts='input latin letters'>abc; alphabet; input; latin; letters</annotation>
-+		<annotation cp='[🅰]' tts='a button'>a; blood</annotation>
-+		<annotation cp='[🆎]' tts='ab button'>ab; blood</annotation>
-+		<annotation cp='[🅱]' tts='b button'>b; blood</annotation>
-+		<annotation cp='[🆑]' tts='squared cl'>cl</annotation>
-+		<annotation cp='[🆒]' tts='squared cool'>cool</annotation>
-+		<annotation cp='[🆓]' tts='squared free'>free</annotation>
-+		<annotation cp='[ℹ]' tts='information source'>i; information</annotation>
-+		<annotation cp='[🆔]' tts='squared id'>id; identity</annotation>
-+		<annotation cp='[Ⓜ]' tts='circled letter m'>circle; m</annotation>
-+		<annotation cp='[🆕]' tts='squared new'>new</annotation>
-+		<annotation cp='[🆖]' tts='squared ng'>ng</annotation>
-+		<annotation cp='[🅾]' tts='o button'>blood; o</annotation>
-+		<annotation cp='[🆗]' tts='squared ok'>ok</annotation>
-+		<annotation cp='[🅿]' tts='p button'>parking</annotation>
-+		<annotation cp='[🆘]' tts='squared sos'>help; sos</annotation>
-+		<annotation cp='[🆙]' tts='up! button'>mark; up</annotation>
-+		<annotation cp='[🆚]' tts='squared vs'>versus; vs</annotation>
-+		<annotation cp='[🈁]' tts='squared katakana koko'>japanese</annotation>
-+		<annotation cp='[🈂]' tts='squared katakana sa'>japanese</annotation>
-+		<annotation cp='[🈷]' tts='squared moon ideograph'>japanese</annotation>
-+		<annotation cp='[🈶]' tts='squared exist ideograph'>japanese</annotation>
-+		<annotation cp='[🈯]' tts='squared finger ideograph'>japanese</annotation>
-+		<annotation cp='[🉐]' tts='circled advantage ideograph'>japanese</annotation>
-+		<annotation cp='[🈹]' tts='squared divide ideograph'>japanese</annotation>
-+		<annotation cp='[🈚]' tts='squared negation ideograph'>japanese</annotation>
-+		<annotation cp='[🈲]' tts='squared prohibit ideograph'>japanese</annotation>
-+		<annotation cp='[🉑]' tts='circled accept ideograph'>chinese</annotation>
-+		<annotation cp='[🈸]' tts='squared apply ideograph'>chinese</annotation>
-+		<annotation cp='[🈴]' tts='squared together ideograph'>chinese</annotation>
-+		<annotation cp='[🈳]' tts='squared empty ideograph'>chinese</annotation>
-+		<annotation cp='[㊗]' tts='circled congratulate ideograph'>chinese; congratulation; congratulations; ideograph</annotation>
-+		<annotation cp='[㊙]' tts='circled secret ideograph'>chinese; ideograph; secret</annotation>
-+		<annotation cp='[🈺]' tts='squared operating ideograph'>chinese</annotation>
-+		<annotation cp='[🈵]' tts='squared fullness ideograph'>chinese</annotation>
-+		<annotation cp='[▪]' tts='black small square'>geometric; square</annotation>
-+		<annotation cp='[▫]' tts='white small square'>geometric; square</annotation>
-+		<annotation cp='[◻]' tts='white medium square'>geometric; square</annotation>
-+		<annotation cp='[◼]' tts='black medium square'>geometric; square</annotation>
-+		<annotation cp='[◽]' tts='white medium-small square'>geometric; square</annotation>
-+		<annotation cp='[◾]' tts='black medium-small square'>geometric; square</annotation>
-+		<annotation cp='[⬛]' tts='black large square'>geometric; square</annotation>
-+		<annotation cp='[⬜]' tts='white large square'>geometric; square</annotation>
-+		<annotation cp='[🔶]' tts='large orange diamond'>diamond; geometric; orange</annotation>
-+		<annotation cp='[🔷]' tts='large blue diamond'>blue; diamond; geometric</annotation>
-+		<annotation cp='[🔸]' tts='small orange diamond'>diamond; geometric; orange</annotation>
-+		<annotation cp='[🔹]' tts='small blue diamond'>blue; diamond; geometric</annotation>
-+		<annotation cp='[🔺]' tts='red triangle pointed up'>geometric; red</annotation>
-+		<annotation cp='[🔻]' tts='red triangle pointed down'>down; geometric; red</annotation>
-+		<annotation cp='[💠]' tts='diamond with a dot'>comic; diamond; geometric; inside</annotation>
-+		<annotation cp='[🔘]' tts='radio button'>button; geometric; radio</annotation>
-+		<annotation cp='[🔲]' tts='black square button'>button; geometric; square</annotation>
-+		<annotation cp='[🔳]' tts='white square button'>button; geometric; outlined; square</annotation>
-+		<annotation cp='[⚪]' tts='white circle'>circle; geometric</annotation>
-+		<annotation cp='[⚫]' tts='black circle'>circle; geometric</annotation>
-+		<annotation cp='[🔴]' tts='red circle'>circle; geometric; red</annotation>
-+		<annotation cp='[🔵]' tts='blue circle'>blue; circle; geometric</annotation>
-+	</annotations>
-+</ldml>
-\ No newline at end of file
-diff --git a/ibus.spec.in b/ibus.spec.in
-index 7fdaccb..40aead1 100644
---- a/ibus.spec.in
-+++ b/ibus.spec.in
-@@ -5,6 +5,7 @@
- 
- # Build flags
- %define build_python_library 0
-+%define build_emoji_dictionary 1
- 
- %define glib_ver %([ -a %{_libdir}/pkgconfig/glib-2.0.pc ] && pkg-config --modversion glib-2.0 | cut -d. -f 1,2 || echo -n "999")
- %define gconf2_version 2.12.0
-@@ -40,6 +41,10 @@ BuildRequires:  dconf-devel
- BuildRequires:  pygobject2-devel
- BuildRequires:  intltool
- BuildRequires:  iso-codes-devel
-+%if %build_emoji_dictionary
-+BuildRequires:  nodejs-emojione
-+BuildRequires:  json-glib
-+%endif
- 
- Requires:   %{name}-libs = %{version}-%{release}
- Requires:   %{name}-gtk2 = %{version}-%{release}
-@@ -151,6 +156,12 @@ OPTIONS="$OPTIONS --enable-python-library"
- %else
- OPTIONS="$OPTIONS --disable-python-library"
- %endif
-+%if %build_emoji_dictionary
-+OPTIONS="$OPTIONS --enable-emoji-dict"
-+%else
-+OPTIONS="$OPTIONS --disable-emoji-dict"
-+%endif
-+
- 
- %configure $OPTIONS
- 
-@@ -258,6 +269,9 @@ dconf update &> /dev/null || :
- %{_bindir}/ibus-setup
- %{_datadir}/ibus/component/gtkpanel.xml
- %{_datadir}/ibus/component/simple.xml
-+%if %build_emoji_dictionary
-+%{_datadir}/ibus/dicts
-+%endif
- %{_datadir}/ibus/keymaps/*
- %{_datadir}/ibus/setup/*
- 
-diff --git a/src/Makefile.am b/src/Makefile.am
-index 22e031f..b58ab95 100644
---- a/src/Makefile.am
-+++ b/src/Makefile.am
-@@ -29,15 +29,6 @@ endif
- 
- SUBDIRS = . $(TESTS_DIR)
- 
--IBUS_V_wget = $(ibus__v_wget_@AM_V@)
--ibus__v_wget_ = $(ibus__v_wget_@AM_DEFAULT_V@)
--ibus__v_wget_0 = -nv
--ibus__v_wget_1 =
--IBUS_V_diff = $(ibus__v_diff_@AM_V@)
--ibus__v_diff_ = $(ibus__v_diff_@AM_DEFAULT_V@)
--ibus__v_diff_0 = -q
--ibus__v_diff_1 =
--
- # libibus = libibus-@IBUS_API_VERSION@.la
- libibus = libibus-1.0.la
- 
-@@ -248,37 +239,25 @@ dict_DATA = emoji.dict
- 
- noinst_PROGRAMS = emoji-parser
- 
--emoji-list.html:
--	$(AM_V_at)wget $(IBUS_V_wget) \
--                http://ibus.github.io/files/ibus/emoji-list.html
--	$(AM_V_at)wget $(IBUS_V_wget) \
--                http://unicode.org/emoji/charts/emoji-list.html \
--	        -O latest-emoji-list.html
--	$(AM_V_at)diff $(IBUS_V_diff) emoji-list.html latest-emoji-list.html; \
--	if test $$? -ne 0; then \
--	    echo "#### WARNING: emoji-list.html is old." >&2; \
--	fi; \
--	rm latest-emoji-list.html;
--
--emoji.dict: emoji-parser emoji-list.html
--	$(builddir)/emoji-parser emoji-list.html $@
-+emoji.dict: emoji-parser
-+	$(builddir)/emoji-parser --xml $(srcdir)/../data/annotations/en.xml \
-+	--json $(EMOJI_JSON_FILE) --out $@
- 
- emoji_parser_SOURCES =          \
-     emoji-parser.c              \
-     $(NULL)
- emoji_parser_CFLAGS =           \
-     $(GLIB2_CFLAGS)             \
--    $(LIBXML2_CFLAGS)           \
-+    $(JSON_GLIB1_CFLAGS)        \
-     $(NULL)
- emoji_parser_LDADD =            \
-     $(GLIB2_LIBS)               \
--    $(LIBXML2_LIBS)             \
-+    $(JSON_GLIB1_LIBS)          \
-     $(libibus)                  \
-     $(NULL)
- 
- CLEANFILES +=                   \
-     $(dict_DATA)                \
--    emoji-list.html             \
-     $(NULL)
- endif
- 
-diff --git a/src/emoji-parser.c b/src/emoji-parser.c
-index cf92fee..e97f266 100644
---- a/src/emoji-parser.c
-+++ b/src/emoji-parser.c
-@@ -20,47 +20,59 @@
-  * USA
-  */
- 
--/* Convert http://www.unicode.org/emoji/charts/emoji-list.html
-+/* Convert ../data/annotations/en.xml and
-+ * /usr/lib/node_modules/emojione/emoji.json
-  * to the dictionary file which look up the Emoji from the annotation.
-+ * Get emoji.json with 'npm install -g emojione'.
-+ * en.xml is used for the Unicode annotations and emoji.json is used
-+ * for the aliases_ascii, e.g. ":)", and category, e.g. "people".
-  */
- 
- #include <glib.h>
--#include <libxml/HTMLparser.h>
--#include <libgen.h>
-+#include <json-glib/json-glib.h>
-+
-+#include <string.h>
- 
- #include "ibusutil.h"
- 
- typedef struct _EmojiData EmojiData;
- struct _EmojiData {
--    gchar      *class;
-     gchar      *emoji;
--    GSList     *annotates;
--    GSList     *prev_annotates;
-+    GSList     *annotations;
-+    gboolean    is_annotation;
-     GHashTable *dict;
- };
- 
--const gchar *progname;
--
--static gboolean         parse_node             (xmlNode     *node,
--                                                gboolean     is_child,
--                                                const gchar *prop_name,
--                                                EmojiData   *data);
--
- static void
--usage (void)
-+reset_emoji_element (EmojiData *data)
- {
--    g_print ("%s emoji-list.html emoji.dict\n", progname);
-+    g_assert (data != NULL);
-+
-+    g_clear_pointer (&data->emoji, g_free);
-+    g_slist_free_full (data->annotations, g_free);
-+    data->annotations = NULL;
- }
- 
- static void
--reset_emoji_element (EmojiData *data)
-+update_emoji_dict (EmojiData *data)
- {
--    g_clear_pointer (&data->class, g_free);
--    g_clear_pointer (&data->emoji, g_free);
--    if (data->annotates) {
--        g_slist_free_full (data->prev_annotates, g_free);
--        data->prev_annotates = data->annotates;
--        data->annotates = NULL;
-+    GSList *annotations = data->annotations;
-+    while (annotations) {
-+        const gchar *annotation = (const gchar *) annotations->data;
-+        GSList *emojis = g_hash_table_lookup (data->dict, annotation);
-+        if (emojis) {
-+            GSList *duplicated = g_slist_find_custom (emojis,
-+                                                      data->emoji,
-+                                                      (GCompareFunc) g_strcmp0);
-+            if (duplicated != NULL)
-+                 continue;
-+            emojis = g_slist_copy_deep (emojis, (GCopyFunc) g_strdup, NULL);
-+        }
-+        emojis = g_slist_append (emojis, g_strdup (data->emoji));
-+        g_hash_table_replace (data->dict,
-+                              g_strdup (annotation),
-+                              emojis);
-+        annotations = annotations->next;
-     }
- }
- 
-@@ -70,147 +82,486 @@ free_dict_words (gpointer list)
-     g_slist_free_full (list, g_free);
- }
- 
--static gboolean
--parse_attr (xmlAttr   *attr,
--            EmojiData *data)
--{
--    if (g_strcmp0 ((const gchar *) attr->name, "class") == 0 && attr->children)
--        parse_node (attr->children, TRUE, (const gchar *) attr->name, data);
--    if (g_strcmp0 ((const gchar *) attr->name, "target") == 0 && attr->children)
--        parse_node (attr->children, TRUE, (const gchar *) attr->name, data);
--    if (attr->next)
--        parse_attr (attr->next, data);
--    return TRUE;
--}
-+static void
-+unicode_annotations_start_element_cb (GMarkupParseContext *context,
-+                                      const gchar         *element_name,
-+                                      const gchar        **attribute_names,
-+                                      const gchar        **attribute_values,
-+                                      gpointer             user_data,
-+                                      GError             **error)
-+{
-+    EmojiData *data = (EmojiData *) user_data;
-+    int i;
-+    const gchar *attribute;
-+    const gchar *value;
- 
--static gboolean
--parse_node (xmlNode     *node,
--            gboolean     is_child,
--            const gchar *prop_name,
--            EmojiData   *data)
--{
--    if (g_strcmp0 ((const gchar *) node->name, "tr") == 0) {
--        GSList *annotates = data->annotates;
--        while (annotates) {
--            GSList *emojis = g_hash_table_lookup (data->dict, annotates->data);
--            if (emojis) {
--                emojis = g_slist_copy_deep (emojis, (GCopyFunc) g_strdup, NULL);
-+    g_assert (data != NULL);
-+
-+    if (g_strcmp0 (element_name, "annotation") != 0)
-+        return;
-+
-+    reset_emoji_element (data);
-+
-+    for (i = 0; (attribute = attribute_names[i]) != NULL; i++) {
-+        value = attribute_values[i];
-+
-+        if (g_strcmp0 (attribute, "cp") == 0) {
-+            if (value == NULL || *value == '\0') {
-+                g_warning ("cp='' in unicode.org annotations file");
-+                return;
-+            } else if (value[0] != '[' || value[strlen(value) - 1] != ']') {
-+                g_warning ("cp!='[emoji]' in unicode.org annotations file");
-+                return;
-             }
--            emojis = g_slist_append (emojis, g_strdup (data->emoji));
--            g_hash_table_replace (data->dict,
--                                  g_strdup (annotates->data),
--                                  emojis);
--            annotates = annotates->next;
-+            data->emoji = g_strndup (value + 1, strlen(value) - 2);
-         }
--        reset_emoji_element (data);
--    }
--    /* if node->name is "text" and is_child is FALSE,
--     * it's '\n' or Space between <td> and <td>.
--     */
--    if (g_strcmp0 ((const gchar *) node->name, "text") == 0 && is_child) {
--        /* Get "chars" in <td class="chars"> */
--        if (g_strcmp0 (prop_name, "class") == 0) {
--            if (g_strcmp0 (data->class, (const gchar *) node->content) != 0) {
--                g_clear_pointer (&data->class, g_free);
--                data->class = g_strdup ((const gchar *) node->content);
-+        else if (g_strcmp0 (attribute, "tts") == 0) {
-+            GSList *duplicated = g_slist_find_custom (data->annotations,
-+                                                      value,
-+                                                      (GCompareFunc) g_strcmp0);
-+            if (duplicated == NULL) {
-+                data->annotations = g_slist_prepend (data->annotations,
-+                                                     g_strdup (value));
-             }
-         }
--        /* Get "annotate" in <td class="name"><a target="annotate"> */
--        if (g_strcmp0 (prop_name, "target") == 0 &&
--            g_strcmp0 (data->class, "name") == 0) {
--            g_clear_pointer (&data->class, g_free);
--            data->class = g_strdup ((const gchar *) node->content);
--        }
--        /* Get "emoji" in <td class="chars">emoji</td> */
--        if (g_strcmp0 (prop_name, "td") == 0 &&
--            g_strcmp0 (data->class, "chars") == 0) {
--            data->emoji = g_strdup ((const gchar *) node->content);
--        }
--        /* We ignore "NAME" for <td class="name">NAME</td> but
--         * takes "ANNOTATE" for
--         * <td class="name"><a target="annotate">ANNOTATE</a></td>
--         */
--        if (g_strcmp0 (prop_name, "td") == 0 &&
--            g_strcmp0 (data->class, "name") == 0) {
--            g_slist_free_full (data->annotates, g_free);
--            data->annotates = NULL;
-+    }
-+
-+    data->is_annotation = TRUE;
-+}
-+
-+static void
-+unicode_annotations_end_element_cb (GMarkupParseContext *context,
-+                                    const gchar         *element_name,
-+                                    gpointer             user_data,
-+                                    GError             **error)
-+{
-+    EmojiData *data = (EmojiData *) user_data;
-+
-+    g_assert (data != NULL);
-+    if (!data->is_annotation)
-+        return;
-+
-+    update_emoji_dict (data);
-+    data->is_annotation = FALSE;
-+}
-+
-+void
-+unicode_annotations_text_cb (GMarkupParseContext *context,
-+                             const gchar         *text,
-+                             gsize                text_len,
-+                             gpointer             user_data,
-+                             GError             **error)
-+{
-+    EmojiData *data = (EmojiData *) user_data;
-+    gchar **annotations = NULL;
-+    const gchar *annotation;
-+    int i;
-+
-+    g_assert (data != NULL);
-+    if (!data->is_annotation)
-+        return;
-+    annotations = g_strsplit (text, "; ", -1);
-+    for (i = 0; (annotation = annotations[i]) != NULL; i++) {
-+        GSList *duplicated = g_slist_find_custom (data->annotations,
-+                                                  annotation,
-+                                                  (GCompareFunc) g_strcmp0);
-+        if (duplicated == NULL) {
-+            data->annotations = g_slist_prepend (data->annotations,
-+                                                 g_strdup (annotation));
-         }
--        /* Get "ANNOTATE" in
--         * <td class="name"><a target="annotate">ANNOTATE</a></td>
--         */
--        if (g_strcmp0 (prop_name, "a") == 0 &&
--            g_strcmp0 (data->class, "annotate") == 0) {
--            data->annotates =
--                    g_slist_append (data->annotates,
--                                    g_strdup ((const gchar *) node->content));
-+    }
-+    g_strfreev (annotations);
-+}
-+
-+static gboolean
-+unicode_annotations_parse_xml_file (const gchar *filename,
-+                                    GHashTable  *dict)
-+{
-+    gchar *content = NULL;
-+    gsize length = 0;
-+    GError *error = NULL;
-+    const static GMarkupParser parser = {
-+        unicode_annotations_start_element_cb,
-+        unicode_annotations_end_element_cb,
-+        unicode_annotations_text_cb,
-+        NULL,
-+        NULL
-+    };
-+    GMarkupParseContext *context = NULL;
-+    EmojiData data = { 0, };
-+
-+    g_return_val_if_fail (filename != NULL, FALSE);
-+    g_return_val_if_fail (dict != NULL, FALSE);
-+
-+    if (!g_file_get_contents (filename, &content, &length, &error)) {
-+        g_warning ("Failed to load %s: %s", filename, error->message);
-+        goto failed_to_parse_unicode_annotations;
-+    }
-+
-+    data.dict = dict;
-+
-+    context = g_markup_parse_context_new (&parser, 0, &data, NULL);
-+    if (!g_markup_parse_context_parse (context, content, length, &error)) {
-+        g_warning ("Failed to parse %s: %s", filename, error->message);
-+        goto failed_to_parse_unicode_annotations;
-+    }
-+
-+    reset_emoji_element (&data);
-+    g_markup_parse_context_free (context);
-+    g_free (content);
-+    return TRUE;
-+
-+failed_to_parse_unicode_annotations:
-+    if (error)
-+        g_error_free (error);
-+    if (data.dict)
-+        g_hash_table_destroy (data.dict);
-+    if (context)
-+        g_markup_parse_context_free (context);
-+    g_free (content);
-+    return FALSE;
-+}
-+
-+static gboolean
-+parse_emojione_unicode (JsonNode  *node,
-+                        EmojiData *data)
-+{
-+    const gchar *str, *unicode;
-+    gchar *endptr = NULL;
-+    guint32 uch;
-+    static gchar outbuf[8] = { 0, };
-+    GString *emoji;
-+
-+    if (json_node_get_node_type (node) != JSON_NODE_VALUE) {
-+        g_warning ("'unicode' element is not string");
-+        return FALSE;
-+    }
-+
-+    emoji = g_string_new (NULL);
-+    str = unicode = json_node_get_string (node);
-+    while (str && *str) {
-+        uch = g_ascii_strtoull (str, &endptr, 16);
-+        outbuf[g_unichar_to_utf8 (uch, outbuf)] = '\0';
-+        g_string_append (emoji, outbuf);
-+        if (*endptr == '\0') {
-+            break;
-+        } else {
-+            switch (*endptr) {
-+            case '-':
-+                endptr++;
-+                break;
-+            default:
-+                g_warning ("Failed to parse unicode %s", unicode);
-+            }
-         }
-+        str = endptr;
-+        endptr = NULL;
-+    }
-+
-+    data->emoji = g_string_free (emoji, FALSE);
-+
-+    return TRUE;
-+}
-+
-+static gboolean
-+parse_emojione_shortname (JsonNode  *node,
-+                          EmojiData *data)
-+{
-+#if 0
-+    const gchar *shortname;
-+    gchar *head, *s;
-+    int length;
-+    GSList *duplicated;
-+
-+    if (json_node_get_node_type (node) != JSON_NODE_VALUE) {
-+        g_warning ("'shortname' element is not string");
-+        return FALSE;
-     }
--    /* Get "foo" in <td class="foo"> */
--    if (g_strcmp0 ((const gchar *) node->name, "td") == 0 &&
--        node->properties != NULL) {
--        parse_attr (node->properties, data);
-+
-+    /* The format is ':short_name:' */
-+    shortname = json_node_get_string (node);
-+    if (shortname == 0 || *shortname == '\0')
-+        return TRUE;
-+    if (*shortname != ':') {
-+        g_warning ("'shortname' format is different: %s", shortname);
-+        return FALSE;
-     }
--    /* Get "foo" in <a target="foo"> */
--    if (g_strcmp0 ((const gchar *) node->name, "a") == 0 &&
--        node->properties != NULL) {
--        parse_attr (node->properties, data);
-+
-+    length = strlen (shortname);
-+    head  = g_new0 (gchar, length);
-+    strcpy (head, shortname + 1);
-+    for (s = head; *s; s++) {
-+        if (*s == ':') {
-+            *s = '\0';
-+            break;
-+        } else if (*s == '_') {
-+            *s = ' ';
-+        }
-     }
--    if (node->children) {
--        parse_node (node->children, TRUE, (const gchar *) node->name, data);
-+
-+    if (head == NULL || *head == '\0') {
-+        g_warning ("'shortname' format is different: %s", shortname);
-+        g_free (head);
-+        return FALSE;
-+    }
-+
-+    duplicated = g_slist_find_custom (data->annotations,
-+                                      head,
-+                                      (GCompareFunc) g_strcmp0);
-+    if (duplicated == NULL) {
-+        data->annotations = g_slist_prepend (data->annotations,
-+                                             head);
-     } else {
--        /* If annotate is NULL likes <td class="name"></td>,
--         * the previous emoji cell has the same annotate.
--         */
--        if (g_strcmp0 ((const gchar *) node->name, "td") == 0 &&
--            g_strcmp0 (data->class, "name") == 0) {
--            data->annotates = g_slist_copy_deep (data->prev_annotates,
--                                                 (GCopyFunc) g_strdup,
--                                                 NULL);
-+       g_free (head);
-+    }
-+
-+#endif
-+    return TRUE;
-+}
-+
-+static gboolean
-+parse_emojione_category (JsonNode  *node,
-+                         EmojiData *data)
-+{
-+    const gchar *category;
-+    GSList *duplicated;
-+
-+    if (json_node_get_node_type (node) != JSON_NODE_VALUE) {
-+        g_warning ("'category' element is not string");
-+        return FALSE;
-+    }
-+
-+    category = json_node_get_string (node);
-+
-+    if (category == NULL || *category == '\0')
-+        return TRUE;
-+
-+    duplicated = g_slist_find_custom (data->annotations,
-+                                      category,
-+                                      (GCompareFunc) g_strcmp0);
-+    if (duplicated == NULL) {
-+        data->annotations = g_slist_prepend (data->annotations,
-+                                             g_strdup (category));
-+    }
-+
-+    return TRUE;
-+}
-+
-+static gboolean
-+parse_emojione_aliases_ascii (JsonNode  *node,
-+                              EmojiData *data)
-+{
-+    JsonArray *aliases_ascii;
-+    guint i, length;
-+
-+    if (json_node_get_node_type (node) != JSON_NODE_ARRAY) {
-+        g_warning ("'aliases_ascii' element is not array");
-+        return FALSE;
-+    }
-+
-+    aliases_ascii = json_node_get_array (node);
-+    length = json_array_get_length (aliases_ascii);
-+    for (i = 0; i < length; i++) {
-+        const gchar *alias = json_array_get_string_element (aliases_ascii, i);
-+        GSList *duplicated = g_slist_find_custom (data->annotations,
-+                                                  alias,
-+                                                  (GCompareFunc) g_strcmp0);
-+        if (duplicated == NULL) {
-+            data->annotations = g_slist_prepend (data->annotations,
-+                                                 g_strdup (alias));
-         }
-     }
--    if (node->next)
--        parse_node (node->next, FALSE, (const gchar *) node->name, data);
- 
-     return TRUE;
- }
- 
--static GHashTable *
--parse_html (const gchar *filename)
-+static gboolean
-+parse_emojione_keywords (JsonNode  *node,
-+                         EmojiData *data)
- {
--    xmlDoc *doc = htmlParseFile (filename, "utf-8");
--    EmojiData data = { 0, };
-+#if 0
-+    JsonArray *keywords;
-+    guint i, length;
- 
--    if (doc == NULL || doc->children == NULL) {
--        g_warning ("Parse Error in document type: %x",
--                   doc ? doc->type : 0);
-+    if (json_node_get_node_type (node) != JSON_NODE_ARRAY) {
-+        g_warning ("'keywords' element is not array");
-         return FALSE;
-     }
- 
--    data.dict = g_hash_table_new_full (g_str_hash,
--                                       g_str_equal,
--                                       g_free,
--                                       free_dict_words);
--    parse_node (doc->children, TRUE, (const gchar *) doc->name, &data);
-+    keywords = json_node_get_array (node);
-+    length = json_array_get_length (keywords);
-+    for (i = 0; i < length; i++) {
-+        const gchar *keyword = json_array_get_string_element (keywords, i);
-+        GSList *duplicated = g_slist_find_custom (data->annotations,
-+                                                  keyword,
-+                                                  (GCompareFunc) g_strcmp0);
-+        if (duplicated == NULL) {
-+            data->annotations = g_slist_prepend (data->annotations,
-+                                                 g_strdup (keyword));
-+        }
-+    }
- 
-+#endif
-+    return TRUE;
-+}
-+
-+static gboolean
-+parse_emojione_emoji_data (JsonNode    *node,
-+                           const gchar *member,
-+                           EmojiData   *data)
-+{
-+    if (g_strcmp0 (member, "unicode") == 0)
-+        return parse_emojione_unicode (node, data);
-+    else if (g_strcmp0 (member, "shortname") == 0)
-+        return parse_emojione_shortname (node, data);
-+    else if (g_strcmp0 (member, "category") == 0)
-+        return parse_emojione_category (node, data);
-+    else if (g_strcmp0 (member, "aliases_ascii") == 0)
-+        return parse_emojione_aliases_ascii (node, data);
-+    else if (g_strcmp0 (member, "keywords") == 0)
-+        return parse_emojione_keywords (node, data);
-+    return TRUE;
-+}
-+
-+static gboolean
-+parse_emojione_element (JsonNode  *node,
-+                        EmojiData *data)
-+{
-+    JsonObject *object;
-+    GList *members, *m;
-+
-+    if (json_node_get_node_type (node) != JSON_NODE_OBJECT) {
-+            return FALSE;
-+    }
-+
-+    reset_emoji_element (data);
-+
-+    object = json_node_get_object (node);
-+    m = members = json_object_get_members (object);
-+    while (m) {
-+       const gchar *member = (const gchar *) m->data;
-+       if (!parse_emojione_emoji_data (json_object_get_member (object, member),
-+                                       member,
-+                                       data)) {
-+           g_list_free (members);
-+           return FALSE;
-+       }
-+       m = m->next;
-+    }
-+    g_list_free (members);
-+
-+    update_emoji_dict (data);
-+
-+    return TRUE;
-+}
-+
-+static gboolean
-+emojione_parse_json_file (const gchar *filename,
-+                          GHashTable  *dict)
-+{
-+    JsonParser *parser = json_parser_new ();
-+    JsonNode *node;
-+    JsonObject *object;
-+    GList *members, *m;
-+    GError *error = NULL;
-+    EmojiData data = { 0, };
-+
-+    g_return_val_if_fail (filename != NULL, FALSE);
-+    g_return_val_if_fail (dict != NULL, FALSE);
-+
-+    if (!json_parser_load_from_file (parser, filename, &error)) {
-+        g_error ("%s", error->message);
-+        g_error_free (error);
-+        goto fail_to_json_file;
-+    }
-+
-+    node = json_parser_get_root (parser);
-+    if (json_node_get_node_type (node) != JSON_NODE_OBJECT) {
-+        g_warning ("Json file does not have Json object %s", filename);
-+        goto fail_to_json_file;
-+    }
-+
-+    object = json_node_get_object (node);
-+    members = json_object_get_members (object);
-+    data.dict = dict;
-+
-+    m = members;
-+    while (m) {
-+       const gchar *member = (const gchar *) m->data;
-+       if (!parse_emojione_element (json_object_get_member (object, member),
-+                                    &data)) {
-+           g_warning ("Failed to parse member '%s' in %s", member, filename);
-+       }
-+       m = m->next;
-+    }
-+
-+    g_list_free (members);
-     reset_emoji_element (&data);
--    g_slist_free_full (data.prev_annotates, g_free);
-+    g_object_unref (parser);
-+
-+    return TRUE;
- 
--    return data.dict;
-+fail_to_json_file:
-+    g_object_unref (parser);
-+    return FALSE;
- }
- 
- int
- main (int argc, char *argv[])
- {
-+    gchar *prgname;
-+    gchar *json_file = NULL;
-+    gchar *xml_file = NULL;
-+    gchar *output = NULL;
-+    GOptionEntry     entries[] = {
-+        { "json", 'j', 0, G_OPTION_ARG_STRING, &json_file,
-+          "Parse Emoji One JSON file",
-+          "JSON"
-+        },
-+        { "out", 'o', 0, G_OPTION_ARG_STRING, &output,
-+          "Save the emoji dictionary as FILE",
-+          "FILE"
-+        },
-+        { "xml", 'x', 0, G_OPTION_ARG_STRING, &xml_file,
-+          "Parse Unocode.org ANNOTATIONS file",
-+          "ANNOTATIONS"
-+        },
-+        { NULL }
-+    };
-+    GOptionContext *context;
-+    GError *error = NULL;
-     GHashTable *dict;
--    progname = basename (argv[0]);
-+
-+    prgname = g_path_get_basename (argv[0]);
-+    g_set_prgname (prgname);
-+    g_free (prgname);
-+
-+    context = g_option_context_new (NULL);
-+    g_option_context_add_main_entries (context, entries, NULL);
- 
-     if (argc < 3) {
--        usage ();
-+        g_print ("%s", g_option_context_get_help (context, TRUE, NULL));
-+        g_option_context_free (context);
-+        return -1;
-+    }
-+
-+    if (!g_option_context_parse (context, &argc, &argv, &error)) {
-+        g_warning ("Failed options: %s", error->message);
-+        g_error_free (error);
-         return -1;
-     }
-+    g_option_context_free (context);
- 
--    dict = parse_html (argv[1]);
--    ibus_emoji_dict_save (argv[2], dict);
-+    dict = g_hash_table_new_full (g_str_hash,
-+                                  g_str_equal,
-+                                  g_free,
-+                                  free_dict_words);
-+    if (xml_file)
-+        unicode_annotations_parse_xml_file (xml_file, dict);
-+    if (json_file)
-+        emojione_parse_json_file (json_file, dict);
-+    if (g_hash_table_size (dict) > 0 && output)
-+        ibus_emoji_dict_save (output, dict);
-     g_hash_table_destroy (dict);
- 
-     return 0;
--- 
-2.7.4
-
-From f88c48750538eaaf7c7b182ba3763b45c2745074 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Wed, 20 Jul 2016 11:43:49 +0900
-Subject: [PATCH 4/4] Fix typo in configure.ac
-
-R=shawn.p.huang@gmail.com
-
-Review URL: https://codereview.appspot.com/303110043
----
- configure.ac | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/configure.ac b/configure.ac
-index f789819..76897f0 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -647,7 +647,7 @@ engine/Makefile
- util/Makefile
- util/IMdkit/Makefile
- data/Makefile
--data/annotations/Makefile.am
-+data/annotations/Makefile
- data/icons/Makefile
- data/keymaps/Makefile
- data/dconf/Makefile
--- 
-2.7.4
-

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-05-31  2:06 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-05-31  2:06 [rpms/ibus] autotool: Delete ibus-HEAD.patch to bump tarball Takao Fujiwara

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox