public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
From: Takao Fujiwara <tfujiwar@redhat.com>
To: git-commits@fedoraproject.org
Subject: [rpms/ibus] autotool: Dropped nodejs-emojione-json and import unicode-emoji instead
Date: Sun, 31 May 2026 02:06:32 GMT	[thread overview]
Message-ID: <178019319260.1.16822556303133795888.rpms-ibus-8dd4dc1c86fb@fedoraproject.org> (raw)

            A new commit has been pushed.

            Repo   : rpms/ibus
            Branch : autotool
            Commit : 8dd4dc1c86fb516325ebc1a97a707a874a3d6d19
            Author : Takao Fujiwara <tfujiwar@redhat.com>
            Date   : 2017-05-09T15:21:22+09:00
            Stats  : +6992/-12 in 3 file(s)
            URL    : https://src.fedoraproject.org/rpms/ibus/c/8dd4dc1c86fb516325ebc1a97a707a874a3d6d19?branch=autotool

            Log:
            Dropped nodejs-emojione-json and import unicode-emoji instead

- Created emoji tab in ibus-setup
- Set default emoji font size from gsettings in ibus emoji command
- Added an option of emoji partial match in ibus-setup
- Hid emoji variants by default
- Added ibus-emoji man page
- emoji favorites category is updated by selecting emoji

---
diff --git a/emoji-test.txt b/emoji-test.txt
new file mode 100644
index 0000000..533739f
--- /dev/null
+++ b/emoji-test.txt
@@ -0,0 +1,3033 @@
+# emoji-test.txt
+# Date: 2016-11-16, 18:29:53 GMT
+# © 2016 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/terms_of_use.html
+#
+# Emoji Keyboard/Display Test Data for UTR #51
+# Version: 4.0
+#
+# For documentation and usage, see http://www.unicode.org/reports/tr51
+#
+# This file provides data for testing which emoji forms should be in keyboards and which should also be displayed/processed.
+# Format
+#   Code points; status # emoji name
+#     Status
+#       keyboard — see “Emoji Implementation Notes” in UTR#51
+#       process — see “Emoji Implementation Notes” in UTR#51
+# Notes:
+#   • This currently omits the 12 keycap bases, the 5 modifier characters, and 26 singleton Regional Indicator characters
+#   • The file is in CLDR order, not codepoint order. This is recommended (but not required!) for keyboard palettes.
+#   • The groups and subgroups are purely illustrative. See the Emoji Order chart for more information.
+
+# group: Smileys & People
+
+# subgroup: face-positive
+1F600                                      ; fully-qualified     # 😀 grinning face
+1F601                                      ; fully-qualified     # 😁 grinning face with smiling eyes
+1F602                                      ; fully-qualified     # 😂 face with tears of joy
+1F923                                      ; fully-qualified     # 🤣 rolling on the floor laughing
+1F603                                      ; fully-qualified     # 😃 smiling face with open mouth
+1F604                                      ; fully-qualified     # 😄 smiling face with open mouth & smiling eyes
+1F605                                      ; fully-qualified     # 😅 smiling face with open mouth & cold sweat
+1F606                                      ; fully-qualified     # 😆 smiling face with open mouth & closed eyes
+1F609                                      ; fully-qualified     # 😉 winking face
+1F60A                                      ; fully-qualified     # 😊 smiling face with smiling eyes
+1F60B                                      ; fully-qualified     # 😋 face savouring delicious food
+1F60E                                      ; fully-qualified     # 😎 smiling face with sunglasses
+1F60D                                      ; fully-qualified     # 😍 smiling face with heart-eyes
+1F618                                      ; fully-qualified     # 😘 face blowing a kiss
+1F617                                      ; fully-qualified     # 😗 kissing face
+1F619                                      ; fully-qualified     # 😙 kissing face with smiling eyes
+1F61A                                      ; fully-qualified     # 😚 kissing face with closed eyes
+263A FE0F                                  ; fully-qualified     # ☺️ smiling face
+1F642                                      ; fully-qualified     # 🙂 slightly smiling face
+1F917                                      ; fully-qualified     # 🤗 hugging face
+
+# subgroup: face-neutral
+1F914                                      ; fully-qualified     # 🤔 thinking face
+1F610                                      ; fully-qualified     # 😐 neutral face
+1F611                                      ; fully-qualified     # 😑 expressionless face
+1F636                                      ; fully-qualified     # 😶 face without mouth
+1F644                                      ; fully-qualified     # 🙄 face with rolling eyes
+1F60F                                      ; fully-qualified     # 😏 smirking face
+1F623                                      ; fully-qualified     # 😣 persevering face
+1F625                                      ; fully-qualified     # 😥 disappointed but relieved face
+1F62E                                      ; fully-qualified     # 😮 face with open mouth
+1F910                                      ; fully-qualified     # 🤐 zipper-mouth face
+1F62F                                      ; fully-qualified     # 😯 hushed face
+1F62A                                      ; fully-qualified     # 😪 sleepy face
+1F62B                                      ; fully-qualified     # 😫 tired face
+1F634                                      ; fully-qualified     # 😴 sleeping face
+1F60C                                      ; fully-qualified     # 😌 relieved face
+1F913                                      ; fully-qualified     # 🤓 nerd face
+1F61B                                      ; fully-qualified     # 😛 face with stuck-out tongue
+1F61C                                      ; fully-qualified     # 😜 face with stuck-out tongue & winking eye
+1F61D                                      ; fully-qualified     # 😝 face with stuck-out tongue & closed eyes
+1F924                                      ; fully-qualified     # 🤤 drooling face
+1F612                                      ; fully-qualified     # 😒 unamused face
+1F613                                      ; fully-qualified     # 😓 face with cold sweat
+1F614                                      ; fully-qualified     # 😔 pensive face
+1F615                                      ; fully-qualified     # 😕 confused face
+1F643                                      ; fully-qualified     # 🙃 upside-down face
+1F911                                      ; fully-qualified     # 🤑 money-mouth face
+1F632                                      ; fully-qualified     # 😲 astonished face
+
+# subgroup: face-negative
+2639 FE0F                                  ; fully-qualified     # ☹️ frowning face
+1F641                                      ; fully-qualified     # 🙁 slightly frowning face
+1F616                                      ; fully-qualified     # 😖 confounded face
+1F61E                                      ; fully-qualified     # 😞 disappointed face
+1F61F                                      ; fully-qualified     # 😟 worried face
+1F624                                      ; fully-qualified     # 😤 face with steam from nose
+1F622                                      ; fully-qualified     # 😢 crying face
+1F62D                                      ; fully-qualified     # 😭 loudly crying face
+1F626                                      ; fully-qualified     # 😦 frowning face with open mouth
+1F627                                      ; fully-qualified     # 😧 anguished face
+1F628                                      ; fully-qualified     # 😨 fearful face
+1F629                                      ; fully-qualified     # 😩 weary face
+1F62C                                      ; fully-qualified     # 😬 grimacing face
+1F630                                      ; fully-qualified     # 😰 face with open mouth & cold sweat
+1F631                                      ; fully-qualified     # 😱 face screaming in fear
+1F633                                      ; fully-qualified     # 😳 flushed face
+1F635                                      ; fully-qualified     # 😵 dizzy face
+1F621                                      ; fully-qualified     # 😡 pouting face
+1F620                                      ; fully-qualified     # 😠 angry face
+
+# subgroup: face-role
+1F607                                      ; fully-qualified     # 😇 smiling face with halo
+1F920                                      ; fully-qualified     # 🤠 cowboy hat face
+1F921                                      ; fully-qualified     # 🤡 clown face
+1F925                                      ; fully-qualified     # 🤥 lying face
+
+# subgroup: face-sick
+1F637                                      ; fully-qualified     # 😷 face with medical mask
+1F912                                      ; fully-qualified     # 🤒 face with thermometer
+1F915                                      ; fully-qualified     # 🤕 face with head-bandage
+1F922                                      ; fully-qualified     # 🤢 nauseated face
+1F927                                      ; fully-qualified     # 🤧 sneezing face
+
+# subgroup: creature-face
+1F608                                      ; fully-qualified     # 😈 smiling face with horns
+1F47F                                      ; fully-qualified     # 👿 angry face with horns
+1F479                                      ; fully-qualified     # 👹 ogre
+1F47A                                      ; fully-qualified     # 👺 goblin
+1F480                                      ; fully-qualified     # 💀 skull
+2620 FE0F                                  ; fully-qualified     # ☠️ skull and crossbones
+1F47B                                      ; fully-qualified     # 👻 ghost
+1F47D                                      ; fully-qualified     # 👽 alien
+1F47E                                      ; fully-qualified     # 👾 alien monster
+1F916                                      ; fully-qualified     # 🤖 robot face
+1F4A9                                      ; fully-qualified     # 💩 pile of poo
+
+# subgroup: cat-face
+1F63A                                      ; fully-qualified     # 😺 smiling cat face with open mouth
+1F638                                      ; fully-qualified     # 😸 grinning cat face with smiling eyes
+1F639                                      ; fully-qualified     # 😹 cat face with tears of joy
+1F63B                                      ; fully-qualified     # 😻 smiling cat face with heart-eyes
+1F63C                                      ; fully-qualified     # 😼 cat face with wry smile
+1F63D                                      ; fully-qualified     # 😽 kissing cat face with closed eyes
+1F640                                      ; fully-qualified     # 🙀 weary cat face
+1F63F                                      ; fully-qualified     # 😿 crying cat face
+1F63E                                      ; fully-qualified     # 😾 pouting cat face
+
+# subgroup: monkey-face
+1F648                                      ; fully-qualified     # 🙈 see-no-evil monkey
+1F649                                      ; fully-qualified     # 🙉 hear-no-evil monkey
+1F64A                                      ; fully-qualified     # 🙊 speak-no-evil monkey
+
+# subgroup: person
+1F466                                      ; fully-qualified     # 👦 boy
+1F466 1F3FB                                ; fully-qualified     # 👦🏻 boy: light skin tone
+1F466 1F3FC                                ; fully-qualified     # 👦🏼 boy: medium-light skin tone
+1F466 1F3FD                                ; fully-qualified     # 👦🏽 boy: medium skin tone
+1F466 1F3FE                                ; fully-qualified     # 👦🏾 boy: medium-dark skin tone
+1F466 1F3FF                                ; fully-qualified     # 👦🏿 boy: dark skin tone
+1F467                                      ; fully-qualified     # 👧 girl
+1F467 1F3FB                                ; fully-qualified     # 👧🏻 girl: light skin tone
+1F467 1F3FC                                ; fully-qualified     # 👧🏼 girl: medium-light skin tone
+1F467 1F3FD                                ; fully-qualified     # 👧🏽 girl: medium skin tone
+1F467 1F3FE                                ; fully-qualified     # 👧🏾 girl: medium-dark skin tone
+1F467 1F3FF                                ; fully-qualified     # 👧🏿 girl: dark skin tone
+1F468                                      ; fully-qualified     # 👨 man
+1F468 1F3FB                                ; fully-qualified     # 👨🏻 man: light skin tone
+1F468 1F3FC                                ; fully-qualified     # 👨🏼 man: medium-light skin tone
+1F468 1F3FD                                ; fully-qualified     # 👨🏽 man: medium skin tone
+1F468 1F3FE                                ; fully-qualified     # 👨🏾 man: medium-dark skin tone
+1F468 1F3FF                                ; fully-qualified     # 👨🏿 man: dark skin tone
+1F469                                      ; fully-qualified     # 👩 woman
+1F469 1F3FB                                ; fully-qualified     # 👩🏻 woman: light skin tone
+1F469 1F3FC                                ; fully-qualified     # 👩🏼 woman: medium-light skin tone
+1F469 1F3FD                                ; fully-qualified     # 👩🏽 woman: medium skin tone
+1F469 1F3FE                                ; fully-qualified     # 👩🏾 woman: medium-dark skin tone
+1F469 1F3FF                                ; fully-qualified     # 👩🏿 woman: dark skin tone
+1F474                                      ; fully-qualified     # 👴 old man
+1F474 1F3FB                                ; fully-qualified     # 👴🏻 old man: light skin tone
+1F474 1F3FC                                ; fully-qualified     # 👴🏼 old man: medium-light skin tone
+1F474 1F3FD                                ; fully-qualified     # 👴🏽 old man: medium skin tone
+1F474 1F3FE                                ; fully-qualified     # 👴🏾 old man: medium-dark skin tone
+1F474 1F3FF                                ; fully-qualified     # 👴🏿 old man: dark skin tone
+1F475                                      ; fully-qualified     # 👵 old woman
+1F475 1F3FB                                ; fully-qualified     # 👵🏻 old woman: light skin tone
+1F475 1F3FC                                ; fully-qualified     # 👵🏼 old woman: medium-light skin tone
+1F475 1F3FD                                ; fully-qualified     # 👵🏽 old woman: medium skin tone
+1F475 1F3FE                                ; fully-qualified     # 👵🏾 old woman: medium-dark skin tone
+1F475 1F3FF                                ; fully-qualified     # 👵🏿 old woman: dark skin tone
+1F476                                      ; fully-qualified     # 👶 baby
+1F476 1F3FB                                ; fully-qualified     # 👶🏻 baby: light skin tone
+1F476 1F3FC                                ; fully-qualified     # 👶🏼 baby: medium-light skin tone
+1F476 1F3FD                                ; fully-qualified     # 👶🏽 baby: medium skin tone
+1F476 1F3FE                                ; fully-qualified     # 👶🏾 baby: medium-dark skin tone
+1F476 1F3FF                                ; fully-qualified     # 👶🏿 baby: dark skin tone
+1F47C                                      ; fully-qualified     # 👼 baby angel
+1F47C 1F3FB                                ; fully-qualified     # 👼🏻 baby angel: light skin tone
+1F47C 1F3FC                                ; fully-qualified     # 👼🏼 baby angel: medium-light skin tone
+1F47C 1F3FD                                ; fully-qualified     # 👼🏽 baby angel: medium skin tone
+1F47C 1F3FE                                ; fully-qualified     # 👼🏾 baby angel: medium-dark skin tone
+1F47C 1F3FF                                ; fully-qualified     # 👼🏿 baby angel: dark skin tone
+
+# subgroup: person-role
+1F468 200D 2695 FE0F                       ; fully-qualified     # 👨‍⚕️ man health worker
+1F468 200D 2695                            ; non-fully-qualified # 👨‍⚕ man health worker
+1F468 1F3FB 200D 2695 FE0F                 ; fully-qualified     # 👨🏻‍⚕️ man health worker: light skin tone
+1F468 1F3FB 200D 2695                      ; non-fully-qualified # 👨🏻‍⚕ man health worker: light skin tone
+1F468 1F3FC 200D 2695 FE0F                 ; fully-qualified     # 👨🏼‍⚕️ man health worker: medium-light skin tone
+1F468 1F3FC 200D 2695                      ; non-fully-qualified # 👨🏼‍⚕ man health worker: medium-light skin tone
+1F468 1F3FD 200D 2695 FE0F                 ; fully-qualified     # 👨🏽‍⚕️ man health worker: medium skin tone
+1F468 1F3FD 200D 2695                      ; non-fully-qualified # 👨🏽‍⚕ man health worker: medium skin tone
+1F468 1F3FE 200D 2695 FE0F                 ; fully-qualified     # 👨🏾‍⚕️ man health worker: medium-dark skin tone
+1F468 1F3FE 200D 2695                      ; non-fully-qualified # 👨🏾‍⚕ man health worker: medium-dark skin tone
+1F468 1F3FF 200D 2695 FE0F                 ; fully-qualified     # 👨🏿‍⚕️ man health worker: dark skin tone
+1F468 1F3FF 200D 2695                      ; non-fully-qualified # 👨🏿‍⚕ man health worker: dark skin tone
+1F469 200D 2695 FE0F                       ; fully-qualified     # 👩‍⚕️ woman health worker
+1F469 200D 2695                            ; non-fully-qualified # 👩‍⚕ woman health worker
+1F469 1F3FB 200D 2695 FE0F                 ; fully-qualified     # 👩🏻‍⚕️ woman health worker: light skin tone
+1F469 1F3FB 200D 2695                      ; non-fully-qualified # 👩🏻‍⚕ woman health worker: light skin tone
+1F469 1F3FC 200D 2695 FE0F                 ; fully-qualified     # 👩🏼‍⚕️ woman health worker: medium-light skin tone
+1F469 1F3FC 200D 2695                      ; non-fully-qualified # 👩🏼‍⚕ woman health worker: medium-light skin tone
+1F469 1F3FD 200D 2695 FE0F                 ; fully-qualified     # 👩🏽‍⚕️ woman health worker: medium skin tone
+1F469 1F3FD 200D 2695                      ; non-fully-qualified # 👩🏽‍⚕ woman health worker: medium skin tone
+1F469 1F3FE 200D 2695 FE0F                 ; fully-qualified     # 👩🏾‍⚕️ woman health worker: medium-dark skin tone
+1F469 1F3FE 200D 2695                      ; non-fully-qualified # 👩🏾‍⚕ woman health worker: medium-dark skin tone
+1F469 1F3FF 200D 2695 FE0F                 ; fully-qualified     # 👩🏿‍⚕️ woman health worker: dark skin tone
+1F469 1F3FF 200D 2695                      ; non-fully-qualified # 👩🏿‍⚕ woman health worker: dark skin tone
+1F468 200D 1F393                           ; fully-qualified     # 👨‍🎓 man student
+1F468 1F3FB 200D 1F393                     ; fully-qualified     # 👨🏻‍🎓 man student: light skin tone
+1F468 1F3FC 200D 1F393                     ; fully-qualified     # 👨🏼‍🎓 man student: medium-light skin tone
+1F468 1F3FD 200D 1F393                     ; fully-qualified     # 👨🏽‍🎓 man student: medium skin tone
+1F468 1F3FE 200D 1F393                     ; fully-qualified     # 👨🏾‍🎓 man student: medium-dark skin tone
+1F468 1F3FF 200D 1F393                     ; fully-qualified     # 👨🏿‍🎓 man student: dark skin tone
+1F469 200D 1F393                           ; fully-qualified     # 👩‍🎓 woman student
+1F469 1F3FB 200D 1F393                     ; fully-qualified     # 👩🏻‍🎓 woman student: light skin tone
+1F469 1F3FC 200D 1F393                     ; fully-qualified     # 👩🏼‍🎓 woman student: medium-light skin tone
+1F469 1F3FD 200D 1F393                     ; fully-qualified     # 👩🏽‍🎓 woman student: medium skin tone
+1F469 1F3FE 200D 1F393                     ; fully-qualified     # 👩🏾‍🎓 woman student: medium-dark skin tone
+1F469 1F3FF 200D 1F393                     ; fully-qualified     # 👩🏿‍🎓 woman student: dark skin tone
+1F468 200D 1F3EB                           ; fully-qualified     # 👨‍🏫 man teacher
+1F468 1F3FB 200D 1F3EB                     ; fully-qualified     # 👨🏻‍🏫 man teacher: light skin tone
+1F468 1F3FC 200D 1F3EB                     ; fully-qualified     # 👨🏼‍🏫 man teacher: medium-light skin tone
+1F468 1F3FD 200D 1F3EB                     ; fully-qualified     # 👨🏽‍🏫 man teacher: medium skin tone
+1F468 1F3FE 200D 1F3EB                     ; fully-qualified     # 👨🏾‍🏫 man teacher: medium-dark skin tone
+1F468 1F3FF 200D 1F3EB                     ; fully-qualified     # 👨🏿‍🏫 man teacher: dark skin tone
+1F469 200D 1F3EB                           ; fully-qualified     # 👩‍🏫 woman teacher
+1F469 1F3FB 200D 1F3EB                     ; fully-qualified     # 👩🏻‍🏫 woman teacher: light skin tone
+1F469 1F3FC 200D 1F3EB                     ; fully-qualified     # 👩🏼‍🏫 woman teacher: medium-light skin tone
+1F469 1F3FD 200D 1F3EB                     ; fully-qualified     # 👩🏽‍🏫 woman teacher: medium skin tone
+1F469 1F3FE 200D 1F3EB                     ; fully-qualified     # 👩🏾‍🏫 woman teacher: medium-dark skin tone
+1F469 1F3FF 200D 1F3EB                     ; fully-qualified     # 👩🏿‍🏫 woman teacher: dark skin tone
+1F468 200D 2696 FE0F                       ; fully-qualified     # 👨‍⚖️ man judge
+1F468 200D 2696                            ; non-fully-qualified # 👨‍⚖ man judge
+1F468 1F3FB 200D 2696 FE0F                 ; fully-qualified     # 👨🏻‍⚖️ man judge: light skin tone
+1F468 1F3FB 200D 2696                      ; non-fully-qualified # 👨🏻‍⚖ man judge: light skin tone
+1F468 1F3FC 200D 2696 FE0F                 ; fully-qualified     # 👨🏼‍⚖️ man judge: medium-light skin tone
+1F468 1F3FC 200D 2696                      ; non-fully-qualified # 👨🏼‍⚖ man judge: medium-light skin tone
+1F468 1F3FD 200D 2696 FE0F                 ; fully-qualified     # 👨🏽‍⚖️ man judge: medium skin tone
+1F468 1F3FD 200D 2696                      ; non-fully-qualified # 👨🏽‍⚖ man judge: medium skin tone
+1F468 1F3FE 200D 2696 FE0F                 ; fully-qualified     # 👨🏾‍⚖️ man judge: medium-dark skin tone
+1F468 1F3FE 200D 2696                      ; non-fully-qualified # 👨🏾‍⚖ man judge: medium-dark skin tone
+1F468 1F3FF 200D 2696 FE0F                 ; fully-qualified     # 👨🏿‍⚖️ man judge: dark skin tone
+1F468 1F3FF 200D 2696                      ; non-fully-qualified # 👨🏿‍⚖ man judge: dark skin tone
+1F469 200D 2696 FE0F                       ; fully-qualified     # 👩‍⚖️ woman judge
+1F469 200D 2696                            ; non-fully-qualified # 👩‍⚖ woman judge
+1F469 1F3FB 200D 2696 FE0F                 ; fully-qualified     # 👩🏻‍⚖️ woman judge: light skin tone
+1F469 1F3FB 200D 2696                      ; non-fully-qualified # 👩🏻‍⚖ woman judge: light skin tone
+1F469 1F3FC 200D 2696 FE0F                 ; fully-qualified     # 👩🏼‍⚖️ woman judge: medium-light skin tone
+1F469 1F3FC 200D 2696                      ; non-fully-qualified # 👩🏼‍⚖ woman judge: medium-light skin tone
+1F469 1F3FD 200D 2696 FE0F                 ; fully-qualified     # 👩🏽‍⚖️ woman judge: medium skin tone
+1F469 1F3FD 200D 2696                      ; non-fully-qualified # 👩🏽‍⚖ woman judge: medium skin tone
+1F469 1F3FE 200D 2696 FE0F                 ; fully-qualified     # 👩🏾‍⚖️ woman judge: medium-dark skin tone
+1F469 1F3FE 200D 2696                      ; non-fully-qualified # 👩🏾‍⚖ woman judge: medium-dark skin tone
+1F469 1F3FF 200D 2696 FE0F                 ; fully-qualified     # 👩🏿‍⚖️ woman judge: dark skin tone
+1F469 1F3FF 200D 2696                      ; non-fully-qualified # 👩🏿‍⚖ woman judge: dark skin tone
+1F468 200D 1F33E                           ; fully-qualified     # 👨‍🌾 man farmer
+1F468 1F3FB 200D 1F33E                     ; fully-qualified     # 👨🏻‍🌾 man farmer: light skin tone
+1F468 1F3FC 200D 1F33E                     ; fully-qualified     # 👨🏼‍🌾 man farmer: medium-light skin tone
+1F468 1F3FD 200D 1F33E                     ; fully-qualified     # 👨🏽‍🌾 man farmer: medium skin tone
+1F468 1F3FE 200D 1F33E                     ; fully-qualified     # 👨🏾‍🌾 man farmer: medium-dark skin tone
+1F468 1F3FF 200D 1F33E                     ; fully-qualified     # 👨🏿‍🌾 man farmer: dark skin tone
+1F469 200D 1F33E                           ; fully-qualified     # 👩‍🌾 woman farmer
+1F469 1F3FB 200D 1F33E                     ; fully-qualified     # 👩🏻‍🌾 woman farmer: light skin tone
+1F469 1F3FC 200D 1F33E                     ; fully-qualified     # 👩🏼‍🌾 woman farmer: medium-light skin tone
+1F469 1F3FD 200D 1F33E                     ; fully-qualified     # 👩🏽‍🌾 woman farmer: medium skin tone
+1F469 1F3FE 200D 1F33E                     ; fully-qualified     # 👩🏾‍🌾 woman farmer: medium-dark skin tone
+1F469 1F3FF 200D 1F33E                     ; fully-qualified     # 👩🏿‍🌾 woman farmer: dark skin tone
+1F468 200D 1F373                           ; fully-qualified     # 👨‍🍳 man cook
+1F468 1F3FB 200D 1F373                     ; fully-qualified     # 👨🏻‍🍳 man cook: light skin tone
+1F468 1F3FC 200D 1F373                     ; fully-qualified     # 👨🏼‍🍳 man cook: medium-light skin tone
+1F468 1F3FD 200D 1F373                     ; fully-qualified     # 👨🏽‍🍳 man cook: medium skin tone
+1F468 1F3FE 200D 1F373                     ; fully-qualified     # 👨🏾‍🍳 man cook: medium-dark skin tone
+1F468 1F3FF 200D 1F373                     ; fully-qualified     # 👨🏿‍🍳 man cook: dark skin tone
+1F469 200D 1F373                           ; fully-qualified     # 👩‍🍳 woman cook
+1F469 1F3FB 200D 1F373                     ; fully-qualified     # 👩🏻‍🍳 woman cook: light skin tone
+1F469 1F3FC 200D 1F373                     ; fully-qualified     # 👩🏼‍🍳 woman cook: medium-light skin tone
+1F469 1F3FD 200D 1F373                     ; fully-qualified     # 👩🏽‍🍳 woman cook: medium skin tone
+1F469 1F3FE 200D 1F373                     ; fully-qualified     # 👩🏾‍🍳 woman cook: medium-dark skin tone
+1F469 1F3FF 200D 1F373                     ; fully-qualified     # 👩🏿‍🍳 woman cook: dark skin tone
+1F468 200D 1F527                           ; fully-qualified     # 👨‍🔧 man mechanic
+1F468 1F3FB 200D 1F527                     ; fully-qualified     # 👨🏻‍🔧 man mechanic: light skin tone
+1F468 1F3FC 200D 1F527                     ; fully-qualified     # 👨🏼‍🔧 man mechanic: medium-light skin tone
+1F468 1F3FD 200D 1F527                     ; fully-qualified     # 👨🏽‍🔧 man mechanic: medium skin tone
+1F468 1F3FE 200D 1F527                     ; fully-qualified     # 👨🏾‍🔧 man mechanic: medium-dark skin tone
+1F468 1F3FF 200D 1F527                     ; fully-qualified     # 👨🏿‍🔧 man mechanic: dark skin tone
+1F469 200D 1F527                           ; fully-qualified     # 👩‍🔧 woman mechanic
+1F469 1F3FB 200D 1F527                     ; fully-qualified     # 👩🏻‍🔧 woman mechanic: light skin tone
+1F469 1F3FC 200D 1F527                     ; fully-qualified     # 👩🏼‍🔧 woman mechanic: medium-light skin tone
+1F469 1F3FD 200D 1F527                     ; fully-qualified     # 👩🏽‍🔧 woman mechanic: medium skin tone
+1F469 1F3FE 200D 1F527                     ; fully-qualified     # 👩🏾‍🔧 woman mechanic: medium-dark skin tone
+1F469 1F3FF 200D 1F527                     ; fully-qualified     # 👩🏿‍🔧 woman mechanic: dark skin tone
+1F468 200D 1F3ED                           ; fully-qualified     # 👨‍🏭 man factory worker
+1F468 1F3FB 200D 1F3ED                     ; fully-qualified     # 👨🏻‍🏭 man factory worker: light skin tone
+1F468 1F3FC 200D 1F3ED                     ; fully-qualified     # 👨🏼‍🏭 man factory worker: medium-light skin tone
+1F468 1F3FD 200D 1F3ED                     ; fully-qualified     # 👨🏽‍🏭 man factory worker: medium skin tone
+1F468 1F3FE 200D 1F3ED                     ; fully-qualified     # 👨🏾‍🏭 man factory worker: medium-dark skin tone
+1F468 1F3FF 200D 1F3ED                     ; fully-qualified     # 👨🏿‍🏭 man factory worker: dark skin tone
+1F469 200D 1F3ED                           ; fully-qualified     # 👩‍🏭 woman factory worker
+1F469 1F3FB 200D 1F3ED                     ; fully-qualified     # 👩🏻‍🏭 woman factory worker: light skin tone
+1F469 1F3FC 200D 1F3ED                     ; fully-qualified     # 👩🏼‍🏭 woman factory worker: medium-light skin tone
+1F469 1F3FD 200D 1F3ED                     ; fully-qualified     # 👩🏽‍🏭 woman factory worker: medium skin tone
+1F469 1F3FE 200D 1F3ED                     ; fully-qualified     # 👩🏾‍🏭 woman factory worker: medium-dark skin tone
+1F469 1F3FF 200D 1F3ED                     ; fully-qualified     # 👩🏿‍🏭 woman factory worker: dark skin tone
+1F468 200D 1F4BC                           ; fully-qualified     # 👨‍💼 man office worker
+1F468 1F3FB 200D 1F4BC                     ; fully-qualified     # 👨🏻‍💼 man office worker: light skin tone
+1F468 1F3FC 200D 1F4BC                     ; fully-qualified     # 👨🏼‍💼 man office worker: medium-light skin tone
+1F468 1F3FD 200D 1F4BC                     ; fully-qualified     # 👨🏽‍💼 man office worker: medium skin tone
+1F468 1F3FE 200D 1F4BC                     ; fully-qualified     # 👨🏾‍💼 man office worker: medium-dark skin tone
+1F468 1F3FF 200D 1F4BC                     ; fully-qualified     # 👨🏿‍💼 man office worker: dark skin tone
+1F469 200D 1F4BC                           ; fully-qualified     # 👩‍💼 woman office worker
+1F469 1F3FB 200D 1F4BC                     ; fully-qualified     # 👩🏻‍💼 woman office worker: light skin tone
+1F469 1F3FC 200D 1F4BC                     ; fully-qualified     # 👩🏼‍💼 woman office worker: medium-light skin tone
+1F469 1F3FD 200D 1F4BC                     ; fully-qualified     # 👩🏽‍💼 woman office worker: medium skin tone
+1F469 1F3FE 200D 1F4BC                     ; fully-qualified     # 👩🏾‍💼 woman office worker: medium-dark skin tone
+1F469 1F3FF 200D 1F4BC                     ; fully-qualified     # 👩🏿‍💼 woman office worker: dark skin tone
+1F468 200D 1F52C                           ; fully-qualified     # 👨‍🔬 man scientist
+1F468 1F3FB 200D 1F52C                     ; fully-qualified     # 👨🏻‍🔬 man scientist: light skin tone
+1F468 1F3FC 200D 1F52C                     ; fully-qualified     # 👨🏼‍🔬 man scientist: medium-light skin tone
+1F468 1F3FD 200D 1F52C                     ; fully-qualified     # 👨🏽‍🔬 man scientist: medium skin tone
+1F468 1F3FE 200D 1F52C                     ; fully-qualified     # 👨🏾‍🔬 man scientist: medium-dark skin tone
+1F468 1F3FF 200D 1F52C                     ; fully-qualified     # 👨🏿‍🔬 man scientist: dark skin tone
+1F469 200D 1F52C                           ; fully-qualified     # 👩‍🔬 woman scientist
+1F469 1F3FB 200D 1F52C                     ; fully-qualified     # 👩🏻‍🔬 woman scientist: light skin tone
+1F469 1F3FC 200D 1F52C                     ; fully-qualified     # 👩🏼‍🔬 woman scientist: medium-light skin tone
+1F469 1F3FD 200D 1F52C                     ; fully-qualified     # 👩🏽‍🔬 woman scientist: medium skin tone
+1F469 1F3FE 200D 1F52C                     ; fully-qualified     # 👩🏾‍🔬 woman scientist: medium-dark skin tone
+1F469 1F3FF 200D 1F52C                     ; fully-qualified     # 👩🏿‍🔬 woman scientist: dark skin tone
+1F468 200D 1F4BB                           ; fully-qualified     # 👨‍💻 man technologist
+1F468 1F3FB 200D 1F4BB                     ; fully-qualified     # 👨🏻‍💻 man technologist: light skin tone
+1F468 1F3FC 200D 1F4BB                     ; fully-qualified     # 👨🏼‍💻 man technologist: medium-light skin tone
+1F468 1F3FD 200D 1F4BB                     ; fully-qualified     # 👨🏽‍💻 man technologist: medium skin tone
+1F468 1F3FE 200D 1F4BB                     ; fully-qualified     # 👨🏾‍💻 man technologist: medium-dark skin tone
+1F468 1F3FF 200D 1F4BB                     ; fully-qualified     # 👨🏿‍💻 man technologist: dark skin tone
+1F469 200D 1F4BB                           ; fully-qualified     # 👩‍💻 woman technologist
+1F469 1F3FB 200D 1F4BB                     ; fully-qualified     # 👩🏻‍💻 woman technologist: light skin tone
+1F469 1F3FC 200D 1F4BB                     ; fully-qualified     # 👩🏼‍💻 woman technologist: medium-light skin tone
+1F469 1F3FD 200D 1F4BB                     ; fully-qualified     # 👩🏽‍💻 woman technologist: medium skin tone
+1F469 1F3FE 200D 1F4BB                     ; fully-qualified     # 👩🏾‍💻 woman technologist: medium-dark skin tone
+1F469 1F3FF 200D 1F4BB                     ; fully-qualified     # 👩🏿‍💻 woman technologist: dark skin tone
+1F468 200D 1F3A4                           ; fully-qualified     # 👨‍🎤 man singer
+1F468 1F3FB 200D 1F3A4                     ; fully-qualified     # 👨🏻‍🎤 man singer: light skin tone
+1F468 1F3FC 200D 1F3A4                     ; fully-qualified     # 👨🏼‍🎤 man singer: medium-light skin tone
+1F468 1F3FD 200D 1F3A4                     ; fully-qualified     # 👨🏽‍🎤 man singer: medium skin tone
+1F468 1F3FE 200D 1F3A4                     ; fully-qualified     # 👨🏾‍🎤 man singer: medium-dark skin tone
+1F468 1F3FF 200D 1F3A4                     ; fully-qualified     # 👨🏿‍🎤 man singer: dark skin tone
+1F469 200D 1F3A4                           ; fully-qualified     # 👩‍🎤 woman singer
+1F469 1F3FB 200D 1F3A4                     ; fully-qualified     # 👩🏻‍🎤 woman singer: light skin tone
+1F469 1F3FC 200D 1F3A4                     ; fully-qualified     # 👩🏼‍🎤 woman singer: medium-light skin tone
+1F469 1F3FD 200D 1F3A4                     ; fully-qualified     # 👩🏽‍🎤 woman singer: medium skin tone
+1F469 1F3FE 200D 1F3A4                     ; fully-qualified     # 👩🏾‍🎤 woman singer: medium-dark skin tone
+1F469 1F3FF 200D 1F3A4                     ; fully-qualified     # 👩🏿‍🎤 woman singer: dark skin tone
+1F468 200D 1F3A8                           ; fully-qualified     # 👨‍🎨 man artist
+1F468 1F3FB 200D 1F3A8                     ; fully-qualified     # 👨🏻‍🎨 man artist: light skin tone
+1F468 1F3FC 200D 1F3A8                     ; fully-qualified     # 👨🏼‍🎨 man artist: medium-light skin tone
+1F468 1F3FD 200D 1F3A8                     ; fully-qualified     # 👨🏽‍🎨 man artist: medium skin tone
+1F468 1F3FE 200D 1F3A8                     ; fully-qualified     # 👨🏾‍🎨 man artist: medium-dark skin tone
+1F468 1F3FF 200D 1F3A8                     ; fully-qualified     # 👨🏿‍🎨 man artist: dark skin tone
+1F469 200D 1F3A8                           ; fully-qualified     # 👩‍🎨 woman artist
+1F469 1F3FB 200D 1F3A8                     ; fully-qualified     # 👩🏻‍🎨 woman artist: light skin tone
+1F469 1F3FC 200D 1F3A8                     ; fully-qualified     # 👩🏼‍🎨 woman artist: medium-light skin tone
+1F469 1F3FD 200D 1F3A8                     ; fully-qualified     # 👩🏽‍🎨 woman artist: medium skin tone
+1F469 1F3FE 200D 1F3A8                     ; fully-qualified     # 👩🏾‍🎨 woman artist: medium-dark skin tone
+1F469 1F3FF 200D 1F3A8                     ; fully-qualified     # 👩🏿‍🎨 woman artist: dark skin tone
+1F468 200D 2708 FE0F                       ; fully-qualified     # 👨‍✈️ man pilot
+1F468 200D 2708                            ; non-fully-qualified # 👨‍✈ man pilot
+1F468 1F3FB 200D 2708 FE0F                 ; fully-qualified     # 👨🏻‍✈️ man pilot: light skin tone
+1F468 1F3FB 200D 2708                      ; non-fully-qualified # 👨🏻‍✈ man pilot: light skin tone
+1F468 1F3FC 200D 2708 FE0F                 ; fully-qualified     # 👨🏼‍✈️ man pilot: medium-light skin tone
+1F468 1F3FC 200D 2708                      ; non-fully-qualified # 👨🏼‍✈ man pilot: medium-light skin tone
+1F468 1F3FD 200D 2708 FE0F                 ; fully-qualified     # 👨🏽‍✈️ man pilot: medium skin tone
+1F468 1F3FD 200D 2708                      ; non-fully-qualified # 👨🏽‍✈ man pilot: medium skin tone
+1F468 1F3FE 200D 2708 FE0F                 ; fully-qualified     # 👨🏾‍✈️ man pilot: medium-dark skin tone
+1F468 1F3FE 200D 2708                      ; non-fully-qualified # 👨🏾‍✈ man pilot: medium-dark skin tone
+1F468 1F3FF 200D 2708 FE0F                 ; fully-qualified     # 👨🏿‍✈️ man pilot: dark skin tone
+1F468 1F3FF 200D 2708                      ; non-fully-qualified # 👨🏿‍✈ man pilot: dark skin tone
+1F469 200D 2708 FE0F                       ; fully-qualified     # 👩‍✈️ woman pilot
+1F469 200D 2708                            ; non-fully-qualified # 👩‍✈ woman pilot
+1F469 1F3FB 200D 2708 FE0F                 ; fully-qualified     # 👩🏻‍✈️ woman pilot: light skin tone
+1F469 1F3FB 200D 2708                      ; non-fully-qualified # 👩🏻‍✈ woman pilot: light skin tone
+1F469 1F3FC 200D 2708 FE0F                 ; fully-qualified     # 👩🏼‍✈️ woman pilot: medium-light skin tone
+1F469 1F3FC 200D 2708                      ; non-fully-qualified # 👩🏼‍✈ woman pilot: medium-light skin tone
+1F469 1F3FD 200D 2708 FE0F                 ; fully-qualified     # 👩🏽‍✈️ woman pilot: medium skin tone
+1F469 1F3FD 200D 2708                      ; non-fully-qualified # 👩🏽‍✈ woman pilot: medium skin tone
+1F469 1F3FE 200D 2708 FE0F                 ; fully-qualified     # 👩🏾‍✈️ woman pilot: medium-dark skin tone
+1F469 1F3FE 200D 2708                      ; non-fully-qualified # 👩🏾‍✈ woman pilot: medium-dark skin tone
+1F469 1F3FF 200D 2708 FE0F                 ; fully-qualified     # 👩🏿‍✈️ woman pilot: dark skin tone
+1F469 1F3FF 200D 2708                      ; non-fully-qualified # 👩🏿‍✈ woman pilot: dark skin tone
+1F468 200D 1F680                           ; fully-qualified     # 👨‍🚀 man astronaut
+1F468 1F3FB 200D 1F680                     ; fully-qualified     # 👨🏻‍🚀 man astronaut: light skin tone
+1F468 1F3FC 200D 1F680                     ; fully-qualified     # 👨🏼‍🚀 man astronaut: medium-light skin tone
+1F468 1F3FD 200D 1F680                     ; fully-qualified     # 👨🏽‍🚀 man astronaut: medium skin tone
+1F468 1F3FE 200D 1F680                     ; fully-qualified     # 👨🏾‍🚀 man astronaut: medium-dark skin tone
+1F468 1F3FF 200D 1F680                     ; fully-qualified     # 👨🏿‍🚀 man astronaut: dark skin tone
+1F469 200D 1F680                           ; fully-qualified     # 👩‍🚀 woman astronaut
+1F469 1F3FB 200D 1F680                     ; fully-qualified     # 👩🏻‍🚀 woman astronaut: light skin tone
+1F469 1F3FC 200D 1F680                     ; fully-qualified     # 👩🏼‍🚀 woman astronaut: medium-light skin tone
+1F469 1F3FD 200D 1F680                     ; fully-qualified     # 👩🏽‍🚀 woman astronaut: medium skin tone
+1F469 1F3FE 200D 1F680                     ; fully-qualified     # 👩🏾‍🚀 woman astronaut: medium-dark skin tone
+1F469 1F3FF 200D 1F680                     ; fully-qualified     # 👩🏿‍🚀 woman astronaut: dark skin tone
+1F468 200D 1F692                           ; fully-qualified     # 👨‍🚒 man firefighter
+1F468 1F3FB 200D 1F692                     ; fully-qualified     # 👨🏻‍🚒 man firefighter: light skin tone
+1F468 1F3FC 200D 1F692                     ; fully-qualified     # 👨🏼‍🚒 man firefighter: medium-light skin tone
+1F468 1F3FD 200D 1F692                     ; fully-qualified     # 👨🏽‍🚒 man firefighter: medium skin tone
+1F468 1F3FE 200D 1F692                     ; fully-qualified     # 👨🏾‍🚒 man firefighter: medium-dark skin tone
+1F468 1F3FF 200D 1F692                     ; fully-qualified     # 👨🏿‍🚒 man firefighter: dark skin tone
+1F469 200D 1F692                           ; fully-qualified     # 👩‍🚒 woman firefighter
+1F469 1F3FB 200D 1F692                     ; fully-qualified     # 👩🏻‍🚒 woman firefighter: light skin tone
+1F469 1F3FC 200D 1F692                     ; fully-qualified     # 👩🏼‍🚒 woman firefighter: medium-light skin tone
+1F469 1F3FD 200D 1F692                     ; fully-qualified     # 👩🏽‍🚒 woman firefighter: medium skin tone
+1F469 1F3FE 200D 1F692                     ; fully-qualified     # 👩🏾‍🚒 woman firefighter: medium-dark skin tone
+1F469 1F3FF 200D 1F692                     ; fully-qualified     # 👩🏿‍🚒 woman firefighter: dark skin tone
+1F46E                                      ; fully-qualified     # 👮 police officer
+1F46E 1F3FB                                ; fully-qualified     # 👮🏻 police officer: light skin tone
+1F46E 1F3FC                                ; fully-qualified     # 👮🏼 police officer: medium-light skin tone
+1F46E 1F3FD                                ; fully-qualified     # 👮🏽 police officer: medium skin tone
+1F46E 1F3FE                                ; fully-qualified     # 👮🏾 police officer: medium-dark skin tone
+1F46E 1F3FF                                ; fully-qualified     # 👮🏿 police officer: dark skin tone
+1F46E 200D 2642 FE0F                       ; fully-qualified     # 👮‍♂️ man police officer
+1F46E 200D 2642                            ; non-fully-qualified # 👮‍♂ man police officer
+1F46E 1F3FB 200D 2642 FE0F                 ; fully-qualified     # 👮🏻‍♂️ man police officer: light skin tone
+1F46E 1F3FB 200D 2642                      ; non-fully-qualified # 👮🏻‍♂ man police officer: light skin tone
+1F46E 1F3FC 200D 2642 FE0F                 ; fully-qualified     # 👮🏼‍♂️ man police officer: medium-light skin tone
+1F46E 1F3FC 200D 2642                      ; non-fully-qualified # 👮🏼‍♂ man police officer: medium-light skin tone
+1F46E 1F3FD 200D 2642 FE0F                 ; fully-qualified     # 👮🏽‍♂️ man police officer: medium skin tone
+1F46E 1F3FD 200D 2642                      ; non-fully-qualified # 👮🏽‍♂ man police officer: medium skin tone
+1F46E 1F3FE 200D 2642 FE0F                 ; fully-qualified     # 👮🏾‍♂️ man police officer: medium-dark skin tone
+1F46E 1F3FE 200D 2642                      ; non-fully-qualified # 👮🏾‍♂ man police officer: medium-dark skin tone
+1F46E 1F3FF 200D 2642 FE0F                 ; fully-qualified     # 👮🏿‍♂️ man police officer: dark skin tone
+1F46E 1F3FF 200D 2642                      ; non-fully-qualified # 👮🏿‍♂ man police officer: dark skin tone
+1F46E 200D 2640 FE0F                       ; fully-qualified     # 👮‍♀️ woman police officer
+1F46E 200D 2640                            ; non-fully-qualified # 👮‍♀ woman police officer
+1F46E 1F3FB 200D 2640 FE0F                 ; fully-qualified     # 👮🏻‍♀️ woman police officer: light skin tone
+1F46E 1F3FB 200D 2640                      ; non-fully-qualified # 👮🏻‍♀ woman police officer: light skin tone
+1F46E 1F3FC 200D 2640 FE0F                 ; fully-qualified     # 👮🏼‍♀️ woman police officer: medium-light skin tone
+1F46E 1F3FC 200D 2640                      ; non-fully-qualified # 👮🏼‍♀ woman police officer: medium-light skin tone
+1F46E 1F3FD 200D 2640 FE0F                 ; fully-qualified     # 👮🏽‍♀️ woman police officer: medium skin tone
+1F46E 1F3FD 200D 2640                      ; non-fully-qualified # 👮🏽‍♀ woman police officer: medium skin tone
+1F46E 1F3FE 200D 2640 FE0F                 ; fully-qualified     # 👮🏾‍♀️ woman police officer: medium-dark skin tone
+1F46E 1F3FE 200D 2640                      ; non-fully-qualified # 👮🏾‍♀ woman police officer: medium-dark skin tone
+1F46E 1F3FF 200D 2640 FE0F                 ; fully-qualified     # 👮🏿‍♀️ woman police officer: dark skin tone
+1F46E 1F3FF 200D 2640                      ; non-fully-qualified # 👮🏿‍♀ woman police officer: dark skin tone
+1F575 FE0F                                 ; fully-qualified     # 🕵️ detective
+1F575 1F3FB                                ; fully-qualified     # 🕵🏻 detective: light skin tone
+1F575 1F3FC                                ; fully-qualified     # 🕵🏼 detective: medium-light skin tone
+1F575 1F3FD                                ; fully-qualified     # 🕵🏽 detective: medium skin tone
+1F575 1F3FE                                ; fully-qualified     # 🕵🏾 detective: medium-dark skin tone
+1F575 1F3FF                                ; fully-qualified     # 🕵🏿 detective: dark skin tone
+1F575 FE0F 200D 2642 FE0F                  ; fully-qualified     # 🕵️‍♂️ man detective
+1F575 200D 2642                            ; non-fully-qualified # 🕵‍♂ man detective
+1F575 FE0F 200D 2642                       ; non-fully-qualified # 🕵️‍♂ man detective
+1F575 200D 2642 FE0F                       ; non-fully-qualified # 🕵‍♂️ man detective
+1F575 1F3FB 200D 2642 FE0F                 ; fully-qualified     # 🕵🏻‍♂️ man detective: light skin tone
+1F575 1F3FB 200D 2642                      ; non-fully-qualified # 🕵🏻‍♂ man detective: light skin tone
+1F575 1F3FC 200D 2642 FE0F                 ; fully-qualified     # 🕵🏼‍♂️ man detective: medium-light skin tone
+1F575 1F3FC 200D 2642                      ; non-fully-qualified # 🕵🏼‍♂ man detective: medium-light skin tone
+1F575 1F3FD 200D 2642 FE0F                 ; fully-qualified     # 🕵🏽‍♂️ man detective: medium skin tone
+1F575 1F3FD 200D 2642                      ; non-fully-qualified # 🕵🏽‍♂ man detective: medium skin tone
+1F575 1F3FE 200D 2642 FE0F                 ; fully-qualified     # 🕵🏾‍♂️ man detective: medium-dark skin tone
+1F575 1F3FE 200D 2642                      ; non-fully-qualified # 🕵🏾‍♂ man detective: medium-dark skin tone
+1F575 1F3FF 200D 2642 FE0F                 ; fully-qualified     # 🕵🏿‍♂️ man detective: dark skin tone
+1F575 1F3FF 200D 2642                      ; non-fully-qualified # 🕵🏿‍♂ man detective: dark skin tone
+1F575 FE0F 200D 2640 FE0F                  ; fully-qualified     # 🕵️‍♀️ woman detective
+1F575 200D 2640                            ; non-fully-qualified # 🕵‍♀ woman detective
+1F575 FE0F 200D 2640                       ; non-fully-qualified # 🕵️‍♀ woman detective
+1F575 200D 2640 FE0F                       ; non-fully-qualified # 🕵‍♀️ woman detective
+1F575 1F3FB 200D 2640 FE0F                 ; fully-qualified     # 🕵🏻‍♀️ woman detective: light skin tone
+1F575 1F3FB 200D 2640                      ; non-fully-qualified # 🕵🏻‍♀ woman detective: light skin tone
+1F575 1F3FC 200D 2640 FE0F                 ; fully-qualified     # 🕵🏼‍♀️ woman detective: medium-light skin tone
+1F575 1F3FC 200D 2640                      ; non-fully-qualified # 🕵🏼‍♀ woman detective: medium-light skin tone
+1F575 1F3FD 200D 2640 FE0F                 ; fully-qualified     # 🕵🏽‍♀️ woman detective: medium skin tone
+1F575 1F3FD 200D 2640                      ; non-fully-qualified # 🕵🏽‍♀ woman detective: medium skin tone
+1F575 1F3FE 200D 2640 FE0F                 ; fully-qualified     # 🕵🏾‍♀️ woman detective: medium-dark skin tone
+1F575 1F3FE 200D 2640                      ; non-fully-qualified # 🕵🏾‍♀ woman detective: medium-dark skin tone
+1F575 1F3FF 200D 2640 FE0F                 ; fully-qualified     # 🕵🏿‍♀️ woman detective: dark skin tone
+1F575 1F3FF 200D 2640                      ; non-fully-qualified # 🕵🏿‍♀ woman detective: dark skin tone
+1F482                                      ; fully-qualified     # 💂 guard
+1F482 1F3FB                                ; fully-qualified     # 💂🏻 guard: light skin tone
+1F482 1F3FC                                ; fully-qualified     # 💂🏼 guard: medium-light skin tone
+1F482 1F3FD                                ; fully-qualified     # 💂🏽 guard: medium skin tone
+1F482 1F3FE                                ; fully-qualified     # 💂🏾 guard: medium-dark skin tone
+1F482 1F3FF                                ; fully-qualified     # 💂🏿 guard: dark skin tone
+1F482 200D 2642 FE0F                       ; fully-qualified     # 💂‍♂️ man guard
+1F482 200D 2642                            ; non-fully-qualified # 💂‍♂ man guard
+1F482 1F3FB 200D 2642 FE0F                 ; fully-qualified     # 💂🏻‍♂️ man guard: light skin tone
+1F482 1F3FB 200D 2642                      ; non-fully-qualified # 💂🏻‍♂ man guard: light skin tone
+1F482 1F3FC 200D 2642 FE0F                 ; fully-qualified     # 💂🏼‍♂️ man guard: medium-light skin tone
+1F482 1F3FC 200D 2642                      ; non-fully-qualified # 💂🏼‍♂ man guard: medium-light skin tone
+1F482 1F3FD 200D 2642 FE0F                 ; fully-qualified     # 💂🏽‍♂️ man guard: medium skin tone
+1F482 1F3FD 200D 2642                      ; non-fully-qualified # 💂🏽‍♂ man guard: medium skin tone
+1F482 1F3FE 200D 2642 FE0F                 ; fully-qualified     # 💂🏾‍♂️ man guard: medium-dark skin tone
+1F482 1F3FE 200D 2642                      ; non-fully-qualified # 💂🏾‍♂ man guard: medium-dark skin tone
+1F482 1F3FF 200D 2642 FE0F                 ; fully-qualified     # 💂🏿‍♂️ man guard: dark skin tone
+1F482 1F3FF 200D 2642                      ; non-fully-qualified # 💂🏿‍♂ man guard: dark skin tone
+1F482 200D 2640 FE0F                       ; fully-qualified     # 💂‍♀️ woman guard
+1F482 200D 2640                            ; non-fully-qualified # 💂‍♀ woman guard
+1F482 1F3FB 200D 2640 FE0F                 ; fully-qualified     # 💂🏻‍♀️ woman guard: light skin tone
+1F482 1F3FB 200D 2640                      ; non-fully-qualified # 💂🏻‍♀ woman guard: light skin tone
+1F482 1F3FC 200D 2640 FE0F                 ; fully-qualified     # 💂🏼‍♀️ woman guard: medium-light skin tone
+1F482 1F3FC 200D 2640                      ; non-fully-qualified # 💂🏼‍♀ woman guard: medium-light skin tone
+1F482 1F3FD 200D 2640 FE0F                 ; fully-qualified     # 💂🏽‍♀️ woman guard: medium skin tone
+1F482 1F3FD 200D 2640                      ; non-fully-qualified # 💂🏽‍♀ woman guard: medium skin tone
+1F482 1F3FE 200D 2640 FE0F                 ; fully-qualified     # 💂🏾‍♀️ woman guard: medium-dark skin tone
+1F482 1F3FE 200D 2640                      ; non-fully-qualified # 💂🏾‍♀ woman guard: medium-dark skin tone
+1F482 1F3FF 200D 2640 FE0F                 ; fully-qualified     # 💂🏿‍♀️ woman guard: dark skin tone
+1F482 1F3FF 200D 2640                      ; non-fully-qualified # 💂🏿‍♀ woman guard: dark skin tone
+1F477                                      ; fully-qualified     # 👷 construction worker
+1F477 1F3FB                                ; fully-qualified     # 👷🏻 construction worker: light skin tone
+1F477 1F3FC                                ; fully-qualified     # 👷🏼 construction worker: medium-light skin tone
+1F477 1F3FD                                ; fully-qualified     # 👷🏽 construction worker: medium skin tone
+1F477 1F3FE                                ; fully-qualified     # 👷🏾 construction worker: medium-dark skin tone
+1F477 1F3FF                                ; fully-qualified     # 👷🏿 construction worker: dark skin tone
+1F477 200D 2642 FE0F                       ; fully-qualified     # 👷‍♂️ man construction worker
+1F477 200D 2642                            ; non-fully-qualified # 👷‍♂ man construction worker
+1F477 1F3FB 200D 2642 FE0F                 ; fully-qualified     # 👷🏻‍♂️ man construction worker: light skin tone
+1F477 1F3FB 200D 2642                      ; non-fully-qualified # 👷🏻‍♂ man construction worker: light skin tone
+1F477 1F3FC 200D 2642 FE0F                 ; fully-qualified     # 👷🏼‍♂️ man construction worker: medium-light skin tone
+1F477 1F3FC 200D 2642                      ; non-fully-qualified # 👷🏼‍♂ man construction worker: medium-light skin tone
+1F477 1F3FD 200D 2642 FE0F                 ; fully-qualified     # 👷🏽‍♂️ man construction worker: medium skin tone
+1F477 1F3FD 200D 2642                      ; non-fully-qualified # 👷🏽‍♂ man construction worker: medium skin tone
+1F477 1F3FE 200D 2642 FE0F                 ; fully-qualified     # 👷🏾‍♂️ man construction worker: medium-dark skin tone
+1F477 1F3FE 200D 2642                      ; non-fully-qualified # 👷🏾‍♂ man construction worker: medium-dark skin tone
+1F477 1F3FF 200D 2642 FE0F                 ; fully-qualified     # 👷🏿‍♂️ man construction worker: dark skin tone
+1F477 1F3FF 200D 2642                      ; non-fully-qualified # 👷🏿‍♂ man construction worker: dark skin tone
+1F477 200D 2640 FE0F                       ; fully-qualified     # 👷‍♀️ woman construction worker
+1F477 200D 2640                            ; non-fully-qualified # 👷‍♀ woman construction worker
+1F477 1F3FB 200D 2640 FE0F                 ; fully-qualified     # 👷🏻‍♀️ woman construction worker: light skin tone
+1F477 1F3FB 200D 2640                      ; non-fully-qualified # 👷🏻‍♀ woman construction worker: light skin tone
+1F477 1F3FC 200D 2640 FE0F                 ; fully-qualified     # 👷🏼‍♀️ woman construction worker: medium-light skin tone
+1F477 1F3FC 200D 2640                      ; non-fully-qualified # 👷🏼‍♀ woman construction worker: medium-light skin tone
+1F477 1F3FD 200D 2640 FE0F                 ; fully-qualified     # 👷🏽‍♀️ woman construction worker: medium skin tone
+1F477 1F3FD 200D 2640                      ; non-fully-qualified # 👷🏽‍♀ woman construction worker: medium skin tone
+1F477 1F3FE 200D 2640 FE0F                 ; fully-qualified     # 👷🏾‍♀️ woman construction worker: medium-dark skin tone
+1F477 1F3FE 200D 2640                      ; non-fully-qualified # 👷🏾‍♀ woman construction worker: medium-dark skin tone
+1F477 1F3FF 200D 2640 FE0F                 ; fully-qualified     # 👷🏿‍♀️ woman construction worker: dark skin tone
+1F477 1F3FF 200D 2640                      ; non-fully-qualified # 👷🏿‍♀ woman construction worker: dark skin tone
+1F473                                      ; fully-qualified     # 👳 person wearing turban
+1F473 1F3FB                                ; fully-qualified     # 👳🏻 person wearing turban: light skin tone
+1F473 1F3FC                                ; fully-qualified     # 👳🏼 person wearing turban: medium-light skin tone
+1F473 1F3FD                                ; fully-qualified     # 👳🏽 person wearing turban: medium skin tone
+1F473 1F3FE                                ; fully-qualified     # 👳🏾 person wearing turban: medium-dark skin tone
+1F473 1F3FF                                ; fully-qualified     # 👳🏿 person wearing turban: dark skin tone
+1F473 200D 2642 FE0F                       ; fully-qualified     # 👳‍♂️ man wearing turban
+1F473 200D 2642                            ; non-fully-qualified # 👳‍♂ man wearing turban
+1F473 1F3FB 200D 2642 FE0F                 ; fully-qualified     # 👳🏻‍♂️ man wearing turban: light skin tone
+1F473 1F3FB 200D 2642                      ; non-fully-qualified # 👳🏻‍♂ man wearing turban: light skin tone
+1F473 1F3FC 200D 2642 FE0F                 ; fully-qualified     # 👳🏼‍♂️ man wearing turban: medium-light skin tone
+1F473 1F3FC 200D 2642                      ; non-fully-qualified # 👳🏼‍♂ man wearing turban: medium-light skin tone
+1F473 1F3FD 200D 2642 FE0F                 ; fully-qualified     # 👳🏽‍♂️ man wearing turban: medium skin tone
+1F473 1F3FD 200D 2642                      ; non-fully-qualified # 👳🏽‍♂ man wearing turban: medium skin tone
+1F473 1F3FE 200D 2642 FE0F                 ; fully-qualified     # 👳🏾‍♂️ man wearing turban: medium-dark skin tone
+1F473 1F3FE 200D 2642                      ; non-fully-qualified # 👳🏾‍♂ man wearing turban: medium-dark skin tone
+1F473 1F3FF 200D 2642 FE0F                 ; fully-qualified     # 👳🏿‍♂️ man wearing turban: dark skin tone
+1F473 1F3FF 200D 2642                      ; non-fully-qualified # 👳🏿‍♂ man wearing turban: dark skin tone
+1F473 200D 2640 FE0F                       ; fully-qualified     # 👳‍♀️ woman wearing turban
+1F473 200D 2640                            ; non-fully-qualified # 👳‍♀ woman wearing turban
+1F473 1F3FB 200D 2640 FE0F                 ; fully-qualified     # 👳🏻‍♀️ woman wearing turban: light skin tone
+1F473 1F3FB 200D 2640                      ; non-fully-qualified # 👳🏻‍♀ woman wearing turban: light skin tone
+1F473 1F3FC 200D 2640 FE0F                 ; fully-qualified     # 👳🏼‍♀️ woman wearing turban: medium-light skin tone
+1F473 1F3FC 200D 2640                      ; non-fully-qualified # 👳🏼‍♀ woman wearing turban: medium-light skin tone
+1F473 1F3FD 200D 2640 FE0F                 ; fully-qualified     # 👳🏽‍♀️ woman wearing turban: medium skin tone
+1F473 1F3FD 200D 2640                      ; non-fully-qualified # 👳🏽‍♀ woman wearing turban: medium skin tone
+1F473 1F3FE 200D 2640 FE0F                 ; fully-qualified     # 👳🏾‍♀️ woman wearing turban: medium-dark skin tone
+1F473 1F3FE 200D 2640                      ; non-fully-qualified # 👳🏾‍♀ woman wearing turban: medium-dark skin tone
+1F473 1F3FF 200D 2640 FE0F                 ; fully-qualified     # 👳🏿‍♀️ woman wearing turban: dark skin tone
+1F473 1F3FF 200D 2640                      ; non-fully-qualified # 👳🏿‍♀ woman wearing turban: dark skin tone
+1F471                                      ; fully-qualified     # 👱 blond-haired person
+1F471 1F3FB                                ; fully-qualified     # 👱🏻 blond-haired person: light skin tone
+1F471 1F3FC                                ; fully-qualified     # 👱🏼 blond-haired person: medium-light skin tone
+1F471 1F3FD                                ; fully-qualified     # 👱🏽 blond-haired person: medium skin tone
+1F471 1F3FE                                ; fully-qualified     # 👱🏾 blond-haired person: medium-dark skin tone
+1F471 1F3FF                                ; fully-qualified     # 👱🏿 blond-haired person: dark skin tone
+1F471 200D 2642 FE0F                       ; fully-qualified     # 👱‍♂️ blond-haired man
+1F471 200D 2642                            ; non-fully-qualified # 👱‍♂ blond-haired man
+1F471 1F3FB 200D 2642 FE0F                 ; fully-qualified     # 👱🏻‍♂️ blond-haired man: light skin tone
+1F471 1F3FB 200D 2642                      ; non-fully-qualified # 👱🏻‍♂ blond-haired man: light skin tone
+1F471 1F3FC 200D 2642 FE0F                 ; fully-qualified     # 👱🏼‍♂️ blond-haired man: medium-light skin tone
+1F471 1F3FC 200D 2642                      ; non-fully-qualified # 👱🏼‍♂ blond-haired man: medium-light skin tone
+1F471 1F3FD 200D 2642 FE0F                 ; fully-qualified     # 👱🏽‍♂️ blond-haired man: medium skin tone
+1F471 1F3FD 200D 2642                      ; non-fully-qualified # 👱🏽‍♂ blond-haired man: medium skin tone
+1F471 1F3FE 200D 2642 FE0F                 ; fully-qualified     # 👱🏾‍♂️ blond-haired man: medium-dark skin tone
+1F471 1F3FE 200D 2642                      ; non-fully-qualified # 👱🏾‍♂ blond-haired man: medium-dark skin tone
+1F471 1F3FF 200D 2642 FE0F                 ; fully-qualified     # 👱🏿‍♂️ blond-haired man: dark skin tone
+1F471 1F3FF 200D 2642                      ; non-fully-qualified # 👱🏿‍♂ blond-haired man: dark skin tone
+1F471 200D 2640 FE0F                       ; fully-qualified     # 👱‍♀️ blond-haired woman
+1F471 200D 2640                            ; non-fully-qualified # 👱‍♀ blond-haired woman
+1F471 1F3FB 200D 2640 FE0F                 ; fully-qualified     # 👱🏻‍♀️ blond-haired woman: light skin tone
+1F471 1F3FB 200D 2640                      ; non-fully-qualified # 👱🏻‍♀ blond-haired woman: light skin tone
+1F471 1F3FC 200D 2640 FE0F                 ; fully-qualified     # 👱🏼‍♀️ blond-haired woman: medium-light skin tone
+1F471 1F3FC 200D 2640                      ; non-fully-qualified # 👱🏼‍♀ blond-haired woman: medium-light skin tone
+1F471 1F3FD 200D 2640 FE0F                 ; fully-qualified     # 👱🏽‍♀️ blond-haired woman: medium skin tone
+1F471 1F3FD 200D 2640                      ; non-fully-qualified # 👱🏽‍♀ blond-haired woman: medium skin tone
+1F471 1F3FE 200D 2640 FE0F                 ; fully-qualified     # 👱🏾‍♀️ blond-haired woman: medium-dark skin tone
+1F471 1F3FE 200D 2640                      ; non-fully-qualified # 👱🏾‍♀ blond-haired woman: medium-dark skin tone
+1F471 1F3FF 200D 2640 FE0F                 ; fully-qualified     # 👱🏿‍♀️ blond-haired woman: dark skin tone
+1F471 1F3FF 200D 2640                      ; non-fully-qualified # 👱🏿‍♀ blond-haired woman: dark skin tone
+1F385                                      ; fully-qualified     # 🎅 Santa Claus
+1F385 1F3FB                                ; fully-qualified     # 🎅🏻 Santa Claus: light skin tone
+1F385 1F3FC                                ; fully-qualified     # 🎅🏼 Santa Claus: medium-light skin tone
+1F385 1F3FD                                ; fully-qualified     # 🎅🏽 Santa Claus: medium skin tone
+1F385 1F3FE                                ; fully-qualified     # 🎅🏾 Santa Claus: medium-dark skin tone
+1F385 1F3FF                                ; fully-qualified     # 🎅🏿 Santa Claus: dark skin tone
+1F936                                      ; fully-qualified     # 🤶 Mrs. Claus
+1F936 1F3FB                                ; fully-qualified     # 🤶🏻 Mrs. Claus: light skin tone
+1F936 1F3FC                                ; fully-qualified     # 🤶🏼 Mrs. Claus: medium-light skin tone
+1F936 1F3FD                                ; fully-qualified     # 🤶🏽 Mrs. Claus: medium skin tone
+1F936 1F3FE                                ; fully-qualified     # 🤶🏾 Mrs. Claus: medium-dark skin tone
+1F936 1F3FF                                ; fully-qualified     # 🤶🏿 Mrs. Claus: dark skin tone
+1F478                                      ; fully-qualified     # 👸 princess
+1F478 1F3FB                                ; fully-qualified     # 👸🏻 princess: light skin tone
+1F478 1F3FC                                ; fully-qualified     # 👸🏼 princess: medium-light skin tone
+1F478 1F3FD                                ; fully-qualified     # 👸🏽 princess: medium skin tone
+1F478 1F3FE                                ; fully-qualified     # 👸🏾 princess: medium-dark skin tone
+1F478 1F3FF                                ; fully-qualified     # 👸🏿 princess: dark skin tone
+1F934                                      ; fully-qualified     # 🤴 prince
+1F934 1F3FB                                ; fully-qualified     # 🤴🏻 prince: light skin tone
+1F934 1F3FC                                ; fully-qualified     # 🤴🏼 prince: medium-light skin tone
+1F934 1F3FD                                ; fully-qualified     # 🤴🏽 prince: medium skin tone
+1F934 1F3FE                                ; fully-qualified     # 🤴🏾 prince: medium-dark skin tone
+1F934 1F3FF                                ; fully-qualified     # 🤴🏿 prince: dark skin tone
+1F470                                      ; fully-qualified     # 👰 bride with veil
+1F470 1F3FB                                ; fully-qualified     # 👰🏻 bride with veil: light skin tone
+1F470 1F3FC                                ; fully-qualified     # 👰🏼 bride with veil: medium-light skin tone
+1F470 1F3FD                                ; fully-qualified     # 👰🏽 bride with veil: medium skin tone
+1F470 1F3FE                                ; fully-qualified     # 👰🏾 bride with veil: medium-dark skin tone
+1F470 1F3FF                                ; fully-qualified     # 👰🏿 bride with veil: dark skin tone
+1F935                                      ; fully-qualified     # 🤵 man in tuxedo
+1F935 1F3FB                                ; fully-qualified     # 🤵🏻 man in tuxedo: light skin tone
+1F935 1F3FC                                ; fully-qualified     # 🤵🏼 man in tuxedo: medium-light skin tone
+1F935 1F3FD                                ; fully-qualified     # 🤵🏽 man in tuxedo: medium skin tone
+1F935 1F3FE                                ; fully-qualified     # 🤵🏾 man in tuxedo: medium-dark skin tone
+1F935 1F3FF                                ; fully-qualified     # 🤵🏿 man in tuxedo: dark skin tone
+1F930                                      ; fully-qualified     # 🤰 pregnant woman
+1F930 1F3FB                                ; fully-qualified     # 🤰🏻 pregnant woman: light skin tone
+1F930 1F3FC                                ; fully-qualified     # 🤰🏼 pregnant woman: medium-light skin tone
+1F930 1F3FD                                ; fully-qualified     # 🤰🏽 pregnant woman: medium skin tone
+1F930 1F3FE                                ; fully-qualified     # 🤰🏾 pregnant woman: medium-dark skin tone
+1F930 1F3FF                                ; fully-qualified     # 🤰🏿 pregnant woman: dark skin tone
+1F472                                      ; fully-qualified     # 👲 man with Chinese cap
+1F472 1F3FB                                ; fully-qualified     # 👲🏻 man with Chinese cap: light skin tone
+1F472 1F3FC                                ; fully-qualified     # 👲🏼 man with Chinese cap: medium-light skin tone
+1F472 1F3FD                                ; fully-qualified     # 👲🏽 man with Chinese cap: medium skin tone
+1F472 1F3FE                                ; fully-qualified     # 👲🏾 man with Chinese cap: medium-dark skin tone
+1F472 1F3FF                                ; fully-qualified     # 👲🏿 man with Chinese cap: dark skin tone
+
+# subgroup: person-gesture
+1F64D                                      ; fully-qualified     # 🙍 person frowning
+1F64D 1F3FB                                ; fully-qualified     # 🙍🏻 person frowning: light skin tone
+1F64D 1F3FC                                ; fully-qualified     # 🙍🏼 person frowning: medium-light skin tone
+1F64D 1F3FD                                ; fully-qualified     # 🙍🏽 person frowning: medium skin tone
+1F64D 1F3FE                                ; fully-qualified     # 🙍🏾 person frowning: medium-dark skin tone
+1F64D 1F3FF                                ; fully-qualified     # 🙍🏿 person frowning: dark skin tone
+1F64D 200D 2642 FE0F                       ; fully-qualified     # 🙍‍♂️ man frowning
+1F64D 200D 2642                            ; non-fully-qualified # 🙍‍♂ man frowning
+1F64D 1F3FB 200D 2642 FE0F                 ; fully-qualified     # 🙍🏻‍♂️ man frowning: light skin tone
+1F64D 1F3FB 200D 2642                      ; non-fully-qualified # 🙍🏻‍♂ man frowning: light skin tone
+1F64D 1F3FC 200D 2642 FE0F                 ; fully-qualified     # 🙍🏼‍♂️ man frowning: medium-light skin tone
+1F64D 1F3FC 200D 2642                      ; non-fully-qualified # 🙍🏼‍♂ man frowning: medium-light skin tone
+1F64D 1F3FD 200D 2642 FE0F                 ; fully-qualified     # 🙍🏽‍♂️ man frowning: medium skin tone
+1F64D 1F3FD 200D 2642                      ; non-fully-qualified # 🙍🏽‍♂ man frowning: medium skin tone
+1F64D 1F3FE 200D 2642 FE0F                 ; fully-qualified     # 🙍🏾‍♂️ man frowning: medium-dark skin tone
+1F64D 1F3FE 200D 2642                      ; non-fully-qualified # 🙍🏾‍♂ man frowning: medium-dark skin tone
+1F64D 1F3FF 200D 2642 FE0F                 ; fully-qualified     # 🙍🏿‍♂️ man frowning: dark skin tone
+1F64D 1F3FF 200D 2642                      ; non-fully-qualified # 🙍🏿‍♂ man frowning: dark skin tone
+1F64D 200D 2640 FE0F                       ; fully-qualified     # 🙍‍♀️ woman frowning
+1F64D 200D 2640                            ; non-fully-qualified # 🙍‍♀ woman frowning
+1F64D 1F3FB 200D 2640 FE0F                 ; fully-qualified     # 🙍🏻‍♀️ woman frowning: light skin tone
+1F64D 1F3FB 200D 2640                      ; non-fully-qualified # 🙍🏻‍♀ woman frowning: light skin tone
+1F64D 1F3FC 200D 2640 FE0F                 ; fully-qualified     # 🙍🏼‍♀️ woman frowning: medium-light skin tone
+1F64D 1F3FC 200D 2640                      ; non-fully-qualified # 🙍🏼‍♀ woman frowning: medium-light skin tone
+1F64D 1F3FD 200D 2640 FE0F                 ; fully-qualified     # 🙍🏽‍♀️ woman frowning: medium skin tone
+1F64D 1F3FD 200D 2640                      ; non-fully-qualified # 🙍🏽‍♀ woman frowning: medium skin tone
+1F64D 1F3FE 200D 2640 FE0F                 ; fully-qualified     # 🙍🏾‍♀️ woman frowning: medium-dark skin tone
+1F64D 1F3FE 200D 2640                      ; non-fully-qualified # 🙍🏾‍♀ woman frowning: medium-dark skin tone
+1F64D 1F3FF 200D 2640 FE0F                 ; fully-qualified     # 🙍🏿‍♀️ woman frowning: dark skin tone
+1F64D 1F3FF 200D 2640                      ; non-fully-qualified # 🙍🏿‍♀ woman frowning: dark skin tone
+1F64E                                      ; fully-qualified     # 🙎 person pouting
+1F64E 1F3FB                                ; fully-qualified     # 🙎🏻 person pouting: light skin tone
+1F64E 1F3FC                                ; fully-qualified     # 🙎🏼 person pouting: medium-light skin tone
+1F64E 1F3FD                                ; fully-qualified     # 🙎🏽 person pouting: medium skin tone
+1F64E 1F3FE                                ; fully-qualified     # 🙎🏾 person pouting: medium-dark skin tone
+1F64E 1F3FF                                ; fully-qualified     # 🙎🏿 person pouting: dark skin tone
+1F64E 200D 2642 FE0F                       ; fully-qualified     # 🙎‍♂️ man pouting
+1F64E 200D 2642                            ; non-fully-qualified # 🙎‍♂ man pouting
+1F64E 1F3FB 200D 2642 FE0F                 ; fully-qualified     # 🙎🏻‍♂️ man pouting: light skin tone
+1F64E 1F3FB 200D 2642                      ; non-fully-qualified # 🙎🏻‍♂ man pouting: light skin tone
+1F64E 1F3FC 200D 2642 FE0F                 ; fully-qualified     # 🙎🏼‍♂️ man pouting: medium-light skin tone
+1F64E 1F3FC 200D 2642                      ; non-fully-qualified # 🙎🏼‍♂ man pouting: medium-light skin tone
+1F64E 1F3FD 200D 2642 FE0F                 ; fully-qualified     # 🙎🏽‍♂️ man pouting: medium skin tone
+1F64E 1F3FD 200D 2642                      ; non-fully-qualified # 🙎🏽‍♂ man pouting: medium skin tone
+1F64E 1F3FE 200D 2642 FE0F                 ; fully-qualified     # 🙎🏾‍♂️ man pouting: medium-dark skin tone
+1F64E 1F3FE 200D 2642                      ; non-fully-qualified # 🙎🏾‍♂ man pouting: medium-dark skin tone
+1F64E 1F3FF 200D 2642 FE0F                 ; fully-qualified     # 🙎🏿‍♂️ man pouting: dark skin tone
+1F64E 1F3FF 200D 2642                      ; non-fully-qualified # 🙎🏿‍♂ man pouting: dark skin tone
+1F64E 200D 2640 FE0F                       ; fully-qualified     # 🙎‍♀️ woman pouting
+1F64E 200D 2640                            ; non-fully-qualified # 🙎‍♀ woman pouting
+1F64E 1F3FB 200D 2640 FE0F                 ; fully-qualified     # 🙎🏻‍♀️ woman pouting: light skin tone
+1F64E 1F3FB 200D 2640                      ; non-fully-qualified # 🙎🏻‍♀ woman pouting: light skin tone
+1F64E 1F3FC 200D 2640 FE0F                 ; fully-qualified     # 🙎🏼‍♀️ woman pouting: medium-light skin tone
+1F64E 1F3FC 200D 2640                      ; non-fully-qualified # 🙎🏼‍♀ woman pouting: medium-light skin tone
+1F64E 1F3FD 200D 2640 FE0F                 ; fully-qualified     # 🙎🏽‍♀️ woman pouting: medium skin tone
+1F64E 1F3FD 200D 2640                      ; non-fully-qualified # 🙎🏽‍♀ woman pouting: medium skin tone
+1F64E 1F3FE 200D 2640 FE0F                 ; fully-qualified     # 🙎🏾‍♀️ woman pouting: medium-dark skin tone
+1F64E 1F3FE 200D 2640                      ; non-fully-qualified # 🙎🏾‍♀ woman pouting: medium-dark skin tone
+1F64E 1F3FF 200D 2640 FE0F                 ; fully-qualified     # 🙎🏿‍♀️ woman pouting: dark skin tone
+1F64E 1F3FF 200D 2640                      ; non-fully-qualified # 🙎🏿‍♀ woman pouting: dark skin tone
+1F645                                      ; fully-qualified     # 🙅 person gesturing NO
+1F645 1F3FB                                ; fully-qualified     # 🙅🏻 person gesturing NO: light skin tone
+1F645 1F3FC                                ; fully-qualified     # 🙅🏼 person gesturing NO: medium-light skin tone
+1F645 1F3FD                                ; fully-qualified     # 🙅🏽 person gesturing NO: medium skin tone
+1F645 1F3FE                                ; fully-qualified     # 🙅🏾 person gesturing NO: medium-dark skin tone
+1F645 1F3FF                                ; fully-qualified     # 🙅🏿 person gesturing NO: dark skin tone
+1F645 200D 2642 FE0F                       ; fully-qualified     # 🙅‍♂️ man gesturing NO
+1F645 200D 2642                            ; non-fully-qualified # 🙅‍♂ man gesturing NO
+1F645 1F3FB 200D 2642 FE0F                 ; fully-qualified     # 🙅🏻‍♂️ man gesturing NO: light skin tone
+1F645 1F3FB 200D 2642                      ; non-fully-qualified # 🙅🏻‍♂ man gesturing NO: light skin tone
+1F645 1F3FC 200D 2642 FE0F                 ; fully-qualified     # 🙅🏼‍♂️ man gesturing NO: medium-light skin tone
+1F645 1F3FC 200D 2642                      ; non-fully-qualified # 🙅🏼‍♂ man gesturing NO: medium-light skin tone
+1F645 1F3FD 200D 2642 FE0F                 ; fully-qualified     # 🙅🏽‍♂️ man gesturing NO: medium skin tone
+1F645 1F3FD 200D 2642                      ; non-fully-qualified # 🙅🏽‍♂ man gesturing NO: medium skin tone
+1F645 1F3FE 200D 2642 FE0F                 ; fully-qualified     # 🙅🏾‍♂️ man gesturing NO: medium-dark skin tone
+1F645 1F3FE 200D 2642                      ; non-fully-qualified # 🙅🏾‍♂ man gesturing NO: medium-dark skin tone
+1F645 1F3FF 200D 2642 FE0F                 ; fully-qualified     # 🙅🏿‍♂️ man gesturing NO: dark skin tone
+1F645 1F3FF 200D 2642                      ; non-fully-qualified # 🙅🏿‍♂ man gesturing NO: dark skin tone
+1F645 200D 2640 FE0F                       ; fully-qualified     # 🙅‍♀️ woman gesturing NO
+1F645 200D 2640                            ; non-fully-qualified # 🙅‍♀ woman gesturing NO
+1F645 1F3FB 200D 2640 FE0F                 ; fully-qualified     # 🙅🏻‍♀️ woman gesturing NO: light skin tone
+1F645 1F3FB 200D 2640                      ; non-fully-qualified # 🙅🏻‍♀ woman gesturing NO: light skin tone
+1F645 1F3FC 200D 2640 FE0F                 ; fully-qualified     # 🙅🏼‍♀️ woman gesturing NO: medium-light skin tone
+1F645 1F3FC 200D 2640                      ; non-fully-qualified # 🙅🏼‍♀ woman gesturing NO: medium-light skin tone
+1F645 1F3FD 200D 2640 FE0F                 ; fully-qualified     # 🙅🏽‍♀️ woman gesturing NO: medium skin tone
+1F645 1F3FD 200D 2640                      ; non-fully-qualified # 🙅🏽‍♀ woman gesturing NO: medium skin tone
+1F645 1F3FE 200D 2640 FE0F                 ; fully-qualified     # 🙅🏾‍♀️ woman gesturing NO: medium-dark skin tone
+1F645 1F3FE 200D 2640                      ; non-fully-qualified # 🙅🏾‍♀ woman gesturing NO: medium-dark skin tone
+1F645 1F3FF 200D 2640 FE0F                 ; fully-qualified     # 🙅🏿‍♀️ woman gesturing NO: dark skin tone
+1F645 1F3FF 200D 2640                      ; non-fully-qualified # 🙅🏿‍♀ woman gesturing NO: dark skin tone
+1F646                                      ; fully-qualified     # 🙆 person gesturing OK
+1F646 1F3FB                                ; fully-qualified     # 🙆🏻 person gesturing OK: light skin tone
+1F646 1F3FC                                ; fully-qualified     # 🙆🏼 person gesturing OK: medium-light skin tone
+1F646 1F3FD                                ; fully-qualified     # 🙆🏽 person gesturing OK: medium skin tone
+1F646 1F3FE                                ; fully-qualified     # 🙆🏾 person gesturing OK: medium-dark skin tone
+1F646 1F3FF                                ; fully-qualified     # 🙆🏿 person gesturing OK: dark skin tone
+1F646 200D 2642 FE0F                       ; fully-qualified     # 🙆‍♂️ man gesturing OK
+1F646 200D 2642                            ; non-fully-qualified # 🙆‍♂ man gesturing OK
+1F646 1F3FB 200D 2642 FE0F                 ; fully-qualified     # 🙆🏻‍♂️ man gesturing OK: light skin tone
+1F646 1F3FB 200D 2642                      ; non-fully-qualified # 🙆🏻‍♂ man gesturing OK: light skin tone
+1F646 1F3FC 200D 2642 FE0F                 ; fully-qualified     # 🙆🏼‍♂️ man gesturing OK: medium-light skin tone
+1F646 1F3FC 200D 2642                      ; non-fully-qualified # 🙆🏼‍♂ man gesturing OK: medium-light skin tone
+1F646 1F3FD 200D 2642 FE0F                 ; fully-qualified     # 🙆🏽‍♂️ man gesturing OK: medium skin tone
+1F646 1F3FD 200D 2642                      ; non-fully-qualified # 🙆🏽‍♂ man gesturing OK: medium skin tone
+1F646 1F3FE 200D 2642 FE0F                 ; fully-qualified     # 🙆🏾‍♂️ man gesturing OK: medium-dark skin tone
+1F646 1F3FE 200D 2642                      ; non-fully-qualified # 🙆🏾‍♂ man gesturing OK: medium-dark skin tone
+1F646 1F3FF 200D 2642 FE0F                 ; fully-qualified     # 🙆🏿‍♂️ man gesturing OK: dark skin tone
+1F646 1F3FF 200D 2642                      ; non-fully-qualified # 🙆🏿‍♂ man gesturing OK: dark skin tone
+1F646 200D 2640 FE0F                       ; fully-qualified     # 🙆‍♀️ woman gesturing OK
+1F646 200D 2640                            ; non-fully-qualified # 🙆‍♀ woman gesturing OK
+1F646 1F3FB 200D 2640 FE0F                 ; fully-qualified     # 🙆🏻‍♀️ woman gesturing OK: light skin tone
+1F646 1F3FB 200D 2640                      ; non-fully-qualified # 🙆🏻‍♀ woman gesturing OK: light skin tone
+1F646 1F3FC 200D 2640 FE0F                 ; fully-qualified     # 🙆🏼‍♀️ woman gesturing OK: medium-light skin tone
+1F646 1F3FC 200D 2640                      ; non-fully-qualified # 🙆🏼‍♀ woman gesturing OK: medium-light skin tone
+1F646 1F3FD 200D 2640 FE0F                 ; fully-qualified     # 🙆🏽‍♀️ woman gesturing OK: medium skin tone
+1F646 1F3FD 200D 2640                      ; non-fully-qualified # 🙆🏽‍♀ woman gesturing OK: medium skin tone
+1F646 1F3FE 200D 2640 FE0F                 ; fully-qualified     # 🙆🏾‍♀️ woman gesturing OK: medium-dark skin tone
+1F646 1F3FE 200D 2640                      ; non-fully-qualified # 🙆🏾‍♀ woman gesturing OK: medium-dark skin tone
+1F646 1F3FF 200D 2640 FE0F                 ; fully-qualified     # 🙆🏿‍♀️ woman gesturing OK: dark skin tone
+1F646 1F3FF 200D 2640                      ; non-fully-qualified # 🙆🏿‍♀ woman gesturing OK: dark skin tone
+1F481                                      ; fully-qualified     # 💁 person tipping hand
+1F481 1F3FB                                ; fully-qualified     # 💁🏻 person tipping hand: light skin tone
+1F481 1F3FC                                ; fully-qualified     # 💁🏼 person tipping hand: medium-light skin tone
+1F481 1F3FD                                ; fully-qualified     # 💁🏽 person tipping hand: medium skin tone
+1F481 1F3FE                                ; fully-qualified     # 💁🏾 person tipping hand: medium-dark skin tone
+1F481 1F3FF                                ; fully-qualified     # 💁🏿 person tipping hand: dark skin tone
+1F481 200D 2642 FE0F                       ; fully-qualified     # 💁‍♂️ man tipping hand
+1F481 200D 2642                            ; non-fully-qualified # 💁‍♂ man tipping hand
+1F481 1F3FB 200D 2642 FE0F                 ; fully-qualified     # 💁🏻‍♂️ man tipping hand: light skin tone
+1F481 1F3FB 200D 2642                      ; non-fully-qualified # 💁🏻‍♂ man tipping hand: light skin tone
+1F481 1F3FC 200D 2642 FE0F                 ; fully-qualified     # 💁🏼‍♂️ man tipping hand: medium-light skin tone
+1F481 1F3FC 200D 2642                      ; non-fully-qualified # 💁🏼‍♂ man tipping hand: medium-light skin tone
+1F481 1F3FD 200D 2642 FE0F                 ; fully-qualified     # 💁🏽‍♂️ man tipping hand: medium skin tone
+1F481 1F3FD 200D 2642                      ; non-fully-qualified # 💁🏽‍♂ man tipping hand: medium skin tone
+1F481 1F3FE 200D 2642 FE0F                 ; fully-qualified     # 💁🏾‍♂️ man tipping hand: medium-dark skin tone
+1F481 1F3FE 200D 2642                      ; non-fully-qualified # 💁🏾‍♂ man tipping hand: medium-dark skin tone
+1F481 1F3FF 200D 2642 FE0F                 ; fully-qualified     # 💁🏿‍♂️ man tipping hand: dark skin tone
+1F481 1F3FF 200D 2642                      ; non-fully-qualified # 💁🏿‍♂ man tipping hand: dark skin tone
+1F481 200D 2640 FE0F                       ; fully-qualified     # 💁‍♀️ woman tipping hand
+1F481 200D 2640                            ; non-fully-qualified # 💁‍♀ woman tipping hand
+1F481 1F3FB 200D 2640 FE0F                 ; fully-qualified     # 💁🏻‍♀️ woman tipping hand: light skin tone
+1F481 1F3FB 200D 2640                      ; non-fully-qualified # 💁🏻‍♀ woman tipping hand: light skin tone
+1F481 1F3FC 200D 2640 FE0F                 ; fully-qualified     # 💁🏼‍♀️ woman tipping hand: medium-light skin tone
+1F481 1F3FC 200D 2640                      ; non-fully-qualified # 💁🏼‍♀ woman tipping hand: medium-light skin tone
+1F481 1F3FD 200D 2640 FE0F                 ; fully-qualified     # 💁🏽‍♀️ woman tipping hand: medium skin tone
+1F481 1F3FD 200D 2640                      ; non-fully-qualified # 💁🏽‍♀ woman tipping hand: medium skin tone
+1F481 1F3FE 200D 2640 FE0F                 ; fully-qualified     # 💁🏾‍♀️ woman tipping hand: medium-dark skin tone
+1F481 1F3FE 200D 2640                      ; non-fully-qualified # 💁🏾‍♀ woman tipping hand: medium-dark skin tone
+1F481 1F3FF 200D 2640 FE0F                 ; fully-qualified     # 💁🏿‍♀️ woman tipping hand: dark skin tone
+1F481 1F3FF 200D 2640                      ; non-fully-qualified # 💁🏿‍♀ woman tipping hand: dark skin tone
+1F64B                                      ; fully-qualified     # 🙋 person raising hand
+1F64B 1F3FB                                ; fully-qualified     # 🙋🏻 person raising hand: light skin tone
+1F64B 1F3FC                                ; fully-qualified     # 🙋🏼 person raising hand: medium-light skin tone
+1F64B 1F3FD                                ; fully-qualified     # 🙋🏽 person raising hand: medium skin tone
+1F64B 1F3FE                                ; fully-qualified     # 🙋🏾 person raising hand: medium-dark skin tone
+1F64B 1F3FF                                ; fully-qualified     # 🙋🏿 person raising hand: dark skin tone
+1F64B 200D 2642 FE0F                       ; fully-qualified     # 🙋‍♂️ man raising hand
+1F64B 200D 2642                            ; non-fully-qualified # 🙋‍♂ man raising hand
+1F64B 1F3FB 200D 2642 FE0F                 ; fully-qualified     # 🙋🏻‍♂️ man raising hand: light skin tone
+1F64B 1F3FB 200D 2642                      ; non-fully-qualified # 🙋🏻‍♂ man raising hand: light skin tone
+1F64B 1F3FC 200D 2642 FE0F                 ; fully-qualified     # 🙋🏼‍♂️ man raising hand: medium-light skin tone
+1F64B 1F3FC 200D 2642                      ; non-fully-qualified # 🙋🏼‍♂ man raising hand: medium-light skin tone
+1F64B 1F3FD 200D 2642 FE0F                 ; fully-qualified     # 🙋🏽‍♂️ man raising hand: medium skin tone
+1F64B 1F3FD 200D 2642                      ; non-fully-qualified # 🙋🏽‍♂ man raising hand: medium skin tone
+1F64B 1F3FE 200D 2642 FE0F                 ; fully-qualified     # 🙋🏾‍♂️ man raising hand: medium-dark skin tone
+1F64B 1F3FE 200D 2642                      ; non-fully-qualified # 🙋🏾‍♂ man raising hand: medium-dark skin tone
+1F64B 1F3FF 200D 2642 FE0F                 ; fully-qualified     # 🙋🏿‍♂️ man raising hand: dark skin tone
+1F64B 1F3FF 200D 2642                      ; non-fully-qualified # 🙋🏿‍♂ man raising hand: dark skin tone
+1F64B 200D 2640 FE0F                       ; fully-qualified     # 🙋‍♀️ woman raising hand
+1F64B 200D 2640                            ; non-fully-qualified # 🙋‍♀ woman raising hand
+1F64B 1F3FB 200D 2640 FE0F                 ; fully-qualified     # 🙋🏻‍♀️ woman raising hand: light skin tone
+1F64B 1F3FB 200D 2640                      ; non-fully-qualified # 🙋🏻‍♀ woman raising hand: light skin tone
+1F64B 1F3FC 200D 2640 FE0F                 ; fully-qualified     # 🙋🏼‍♀️ woman raising hand: medium-light skin tone
+1F64B 1F3FC 200D 2640                      ; non-fully-qualified # 🙋🏼‍♀ woman raising hand: medium-light skin tone
+1F64B 1F3FD 200D 2640 FE0F                 ; fully-qualified     # 🙋🏽‍♀️ woman raising hand: medium skin tone
+1F64B 1F3FD 200D 2640                      ; non-fully-qualified # 🙋🏽‍♀ woman raising hand: medium skin tone
+1F64B 1F3FE 200D 2640 FE0F                 ; fully-qualified     # 🙋🏾‍♀️ woman raising hand: medium-dark skin tone
+1F64B 1F3FE 200D 2640                      ; non-fully-qualified # 🙋🏾‍♀ woman raising hand: medium-dark skin tone
+1F64B 1F3FF 200D 2640 FE0F                 ; fully-qualified     # 🙋🏿‍♀️ woman raising hand: dark skin tone
+1F64B 1F3FF 200D 2640                      ; non-fully-qualified # 🙋🏿‍♀ woman raising hand: dark skin tone
+1F647                                      ; fully-qualified     # 🙇 person bowing
+1F647 1F3FB                                ; fully-qualified     # 🙇🏻 person bowing: light skin tone
+1F647 1F3FC                                ; fully-qualified     # 🙇🏼 person bowing: medium-light skin tone
+1F647 1F3FD                                ; fully-qualified     # 🙇🏽 person bowing: medium skin tone
+1F647 1F3FE                                ; fully-qualified     # 🙇🏾 person bowing: medium-dark skin tone
+1F647 1F3FF                                ; fully-qualified     # 🙇🏿 person bowing: dark skin tone
+1F647 200D 2642 FE0F                       ; fully-qualified     # 🙇‍♂️ man bowing
+1F647 200D 2642                            ; non-fully-qualified # 🙇‍♂ man bowing
+1F647 1F3FB 200D 2642 FE0F                 ; fully-qualified     # 🙇🏻‍♂️ man bowing: light skin tone
+1F647 1F3FB 200D 2642                      ; non-fully-qualified # 🙇🏻‍♂ man bowing: light skin tone
+1F647 1F3FC 200D 2642 FE0F                 ; fully-qualified     # 🙇🏼‍♂️ man bowing: medium-light skin tone
+1F647 1F3FC 200D 2642                      ; non-fully-qualified # 🙇🏼‍♂ man bowing: medium-light skin tone
+1F647 1F3FD 200D 2642 FE0F                 ; fully-qualified     # 🙇🏽‍♂️ man bowing: medium skin tone
+1F647 1F3FD 200D 2642                      ; non-fully-qualified # 🙇🏽‍♂ man bowing: medium skin tone
+1F647 1F3FE 200D 2642 FE0F                 ; fully-qualified     # 🙇🏾‍♂️ man bowing: medium-dark skin tone
+1F647 1F3FE 200D 2642                      ; non-fully-qualified # 🙇🏾‍♂ man bowing: medium-dark skin tone
+1F647 1F3FF 200D 2642 FE0F                 ; fully-qualified     # 🙇🏿‍♂️ man bowing: dark skin tone
+1F647 1F3FF 200D 2642                      ; non-fully-qualified # 🙇🏿‍♂ man bowing: dark skin tone
+1F647 200D 2640 FE0F                       ; fully-qualified     # 🙇‍♀️ woman bowing
+1F647 200D 2640                            ; non-fully-qualified # 🙇‍♀ woman bowing
+1F647 1F3FB 200D 2640 FE0F                 ; fully-qualified     # 🙇🏻‍♀️ woman bowing: light skin tone
+1F647 1F3FB 200D 2640                      ; non-fully-qualified # 🙇🏻‍♀ woman bowing: light skin tone
+1F647 1F3FC 200D 2640 FE0F                 ; fully-qualified     # 🙇🏼‍♀️ woman bowing: medium-light skin tone
+1F647 1F3FC 200D 2640                      ; non-fully-qualified # 🙇🏼‍♀ woman bowing: medium-light skin tone
+1F647 1F3FD 200D 2640 FE0F                 ; fully-qualified     # 🙇🏽‍♀️ woman bowing: medium skin tone
+1F647 1F3FD 200D 2640                      ; non-fully-qualified # 🙇🏽‍♀ woman bowing: medium skin tone
+1F647 1F3FE 200D 2640 FE0F                 ; fully-qualified     # 🙇🏾‍♀️ woman bowing: medium-dark skin tone
+1F647 1F3FE 200D 2640                      ; non-fully-qualified # 🙇🏾‍♀ woman bowing: medium-dark skin tone
+1F647 1F3FF 200D 2640 FE0F                 ; fully-qualified     # 🙇🏿‍♀️ woman bowing: dark skin tone
+1F647 1F3FF 200D 2640                      ; non-fully-qualified # 🙇🏿‍♀ woman bowing: dark skin tone
+1F926                                      ; fully-qualified     # 🤦 person facepalming
+1F926 1F3FB                                ; fully-qualified     # 🤦🏻 person facepalming: light skin tone
+1F926 1F3FC                                ; fully-qualified     # 🤦🏼 person facepalming: medium-light skin tone
+1F926 1F3FD                                ; fully-qualified     # 🤦🏽 person facepalming: medium skin tone
+1F926 1F3FE                                ; fully-qualified     # 🤦🏾 person facepalming: medium-dark skin tone
+1F926 1F3FF                                ; fully-qualified     # 🤦🏿 person facepalming: dark skin tone
+1F926 200D 2642 FE0F                       ; fully-qualified     # 🤦‍♂️ man facepalming
+1F926 200D 2642                            ; non-fully-qualified # 🤦‍♂ man facepalming
+1F926 1F3FB 200D 2642 FE0F                 ; fully-qualified     # 🤦🏻‍♂️ man facepalming: light skin tone
+1F926 1F3FB 200D 2642                      ; non-fully-qualified # 🤦🏻‍♂ man facepalming: light skin tone
+1F926 1F3FC 200D 2642 FE0F                 ; fully-qualified     # 🤦🏼‍♂️ man facepalming: medium-light skin tone
+1F926 1F3FC 200D 2642                      ; non-fully-qualified # 🤦🏼‍♂ man facepalming: medium-light skin tone
+1F926 1F3FD 200D 2642 FE0F                 ; fully-qualified     # 🤦🏽‍♂️ man facepalming: medium skin tone
+1F926 1F3FD 200D 2642                      ; non-fully-qualified # 🤦🏽‍♂ man facepalming: medium skin tone
+1F926 1F3FE 200D 2642 FE0F                 ; fully-qualified     # 🤦🏾‍♂️ man facepalming: medium-dark skin tone
+1F926 1F3FE 200D 2642                      ; non-fully-qualified # 🤦🏾‍♂ man facepalming: medium-dark skin tone
+1F926 1F3FF 200D 2642 FE0F                 ; fully-qualified     # 🤦🏿‍♂️ man facepalming: dark skin tone
+1F926 1F3FF 200D 2642                      ; non-fully-qualified # 🤦🏿‍♂ man facepalming: dark skin tone
+1F926 200D 2640 FE0F                       ; fully-qualified     # 🤦‍♀️ woman facepalming
+1F926 200D 2640                            ; non-fully-qualified # 🤦‍♀ woman facepalming
+1F926 1F3FB 200D 2640 FE0F                 ; fully-qualified     # 🤦🏻‍♀️ woman facepalming: light skin tone
+1F926 1F3FB 200D 2640                      ; non-fully-qualified # 🤦🏻‍♀ woman facepalming: light skin tone
+1F926 1F3FC 200D 2640 FE0F                 ; fully-qualified     # 🤦🏼‍♀️ woman facepalming: medium-light skin tone
+1F926 1F3FC 200D 2640                      ; non-fully-qualified # 🤦🏼‍♀ woman facepalming: medium-light skin tone
+1F926 1F3FD 200D 2640 FE0F                 ; fully-qualified     # 🤦🏽‍♀️ woman facepalming: medium skin tone
+1F926 1F3FD 200D 2640                      ; non-fully-qualified # 🤦🏽‍♀ woman facepalming: medium skin tone
+1F926 1F3FE 200D 2640 FE0F                 ; fully-qualified     # 🤦🏾‍♀️ woman facepalming: medium-dark skin tone
+1F926 1F3FE 200D 2640                      ; non-fully-qualified # 🤦🏾‍♀ woman facepalming: medium-dark skin tone
+1F926 1F3FF 200D 2640 FE0F                 ; fully-qualified     # 🤦🏿‍♀️ woman facepalming: dark skin tone
+1F926 1F3FF 200D 2640                      ; non-fully-qualified # 🤦🏿‍♀ woman facepalming: dark skin tone
+1F937                                      ; fully-qualified     # 🤷 person shrugging
+1F937 1F3FB                                ; fully-qualified     # 🤷🏻 person shrugging: light skin tone
+1F937 1F3FC                                ; fully-qualified     # 🤷🏼 person shrugging: medium-light skin tone
+1F937 1F3FD                                ; fully-qualified     # 🤷🏽 person shrugging: medium skin tone
+1F937 1F3FE                                ; fully-qualified     # 🤷🏾 person shrugging: medium-dark skin tone
+1F937 1F3FF                                ; fully-qualified     # 🤷🏿 person shrugging: dark skin tone
+1F937 200D 2642 FE0F                       ; fully-qualified     # 🤷‍♂️ man shrugging
+1F937 200D 2642                            ; non-fully-qualified # 🤷‍♂ man shrugging
+1F937 1F3FB 200D 2642 FE0F                 ; fully-qualified     # 🤷🏻‍♂️ man shrugging: light skin tone
+1F937 1F3FB 200D 2642                      ; non-fully-qualified # 🤷🏻‍♂ man shrugging: light skin tone
+1F937 1F3FC 200D 2642 FE0F                 ; fully-qualified     # 🤷🏼‍♂️ man shrugging: medium-light skin tone
+1F937 1F3FC 200D 2642                      ; non-fully-qualified # 🤷🏼‍♂ man shrugging: medium-light skin tone
+1F937 1F3FD 200D 2642 FE0F                 ; fully-qualified     # 🤷🏽‍♂️ man shrugging: medium skin tone
+1F937 1F3FD 200D 2642                      ; non-fully-qualified # 🤷🏽‍♂ man shrugging: medium skin tone
+1F937 1F3FE 200D 2642 FE0F                 ; fully-qualified     # 🤷🏾‍♂️ man shrugging: medium-dark skin tone
+1F937 1F3FE 200D 2642                      ; non-fully-qualified # 🤷🏾‍♂ man shrugging: medium-dark skin tone
+1F937 1F3FF 200D 2642 FE0F                 ; fully-qualified     # 🤷🏿‍♂️ man shrugging: dark skin tone
+1F937 1F3FF 200D 2642                      ; non-fully-qualified # 🤷🏿‍♂ man shrugging: dark skin tone
+1F937 200D 2640 FE0F                       ; fully-qualified     # 🤷‍♀️ woman shrugging
+1F937 200D 2640                            ; non-fully-qualified # 🤷‍♀ woman shrugging
+1F937 1F3FB 200D 2640 FE0F                 ; fully-qualified     # 🤷🏻‍♀️ woman shrugging: light skin tone
+1F937 1F3FB 200D 2640                      ; non-fully-qualified # 🤷🏻‍♀ woman shrugging: light skin tone
+1F937 1F3FC 200D 2640 FE0F                 ; fully-qualified     # 🤷🏼‍♀️ woman shrugging: medium-light skin tone
+1F937 1F3FC 200D 2640                      ; non-fully-qualified # 🤷🏼‍♀ woman shrugging: medium-light skin tone
+1F937 1F3FD 200D 2640 FE0F                 ; fully-qualified     # 🤷🏽‍♀️ woman shrugging: medium skin tone
+1F937 1F3FD 200D 2640                      ; non-fully-qualified # 🤷🏽‍♀ woman shrugging: medium skin tone
+1F937 1F3FE 200D 2640 FE0F                 ; fully-qualified     # 🤷🏾‍♀️ woman shrugging: medium-dark skin tone
+1F937 1F3FE 200D 2640                      ; non-fully-qualified # 🤷🏾‍♀ woman shrugging: medium-dark skin tone
+1F937 1F3FF 200D 2640 FE0F                 ; fully-qualified     # 🤷🏿‍♀️ woman shrugging: dark skin tone
+1F937 1F3FF 200D 2640                      ; non-fully-qualified # 🤷🏿‍♀ woman shrugging: dark skin tone
+
+# subgroup: person-activity
+1F486                                      ; fully-qualified     # 💆 person getting massage
+1F486 1F3FB                                ; fully-qualified     # 💆🏻 person getting massage: light skin tone
+1F486 1F3FC                                ; fully-qualified     # 💆🏼 person getting massage: medium-light skin tone
+1F486 1F3FD                                ; fully-qualified     # 💆🏽 person getting massage: medium skin tone
+1F486 1F3FE                                ; fully-qualified     # 💆🏾 person getting massage: medium-dark skin tone
+1F486 1F3FF                                ; fully-qualified     # 💆🏿 person getting massage: dark skin tone
+1F486 200D 2642 FE0F                       ; fully-qualified     # 💆‍♂️ man getting massage
+1F486 200D 2642                            ; non-fully-qualified # 💆‍♂ man getting massage
+1F486 1F3FB 200D 2642 FE0F                 ; fully-qualified     # 💆🏻‍♂️ man getting massage: light skin tone
+1F486 1F3FB 200D 2642                      ; non-fully-qualified # 💆🏻‍♂ man getting massage: light skin tone
+1F486 1F3FC 200D 2642 FE0F                 ; fully-qualified     # 💆🏼‍♂️ man getting massage: medium-light skin tone
+1F486 1F3FC 200D 2642                      ; non-fully-qualified # 💆🏼‍♂ man getting massage: medium-light skin tone
+1F486 1F3FD 200D 2642 FE0F                 ; fully-qualified     # 💆🏽‍♂️ man getting massage: medium skin tone
+1F486 1F3FD 200D 2642                      ; non-fully-qualified # 💆🏽‍♂ man getting massage: medium skin tone
+1F486 1F3FE 200D 2642 FE0F                 ; fully-qualified     # 💆🏾‍♂️ man getting massage: medium-dark skin tone
+1F486 1F3FE 200D 2642                      ; non-fully-qualified # 💆🏾‍♂ man getting massage: medium-dark skin tone
+1F486 1F3FF 200D 2642 FE0F                 ; fully-qualified     # 💆🏿‍♂️ man getting massage: dark skin tone
+1F486 1F3FF 200D 2642                      ; non-fully-qualified # 💆🏿‍♂ man getting massage: dark skin tone
+1F486 200D 2640 FE0F                       ; fully-qualified     # 💆‍♀️ woman getting massage
+1F486 200D 2640                            ; non-fully-qualified # 💆‍♀ woman getting massage
+1F486 1F3FB 200D 2640 FE0F                 ; fully-qualified     # 💆🏻‍♀️ woman getting massage: light skin tone
+1F486 1F3FB 200D 2640                      ; non-fully-qualified # 💆🏻‍♀ woman getting massage: light skin tone
+1F486 1F3FC 200D 2640 FE0F                 ; fully-qualified     # 💆🏼‍♀️ woman getting massage: medium-light skin tone
+1F486 1F3FC 200D 2640                      ; non-fully-qualified # 💆🏼‍♀ woman getting massage: medium-light skin tone
+1F486 1F3FD 200D 2640 FE0F                 ; fully-qualified     # 💆🏽‍♀️ woman getting massage: medium skin tone
+1F486 1F3FD 200D 2640                      ; non-fully-qualified # 💆🏽‍♀ woman getting massage: medium skin tone
+1F486 1F3FE 200D 2640 FE0F                 ; fully-qualified     # 💆🏾‍♀️ woman getting massage: medium-dark skin tone
+1F486 1F3FE 200D 2640                      ; non-fully-qualified # 💆🏾‍♀ woman getting massage: medium-dark skin tone
+1F486 1F3FF 200D 2640 FE0F                 ; fully-qualified     # 💆🏿‍♀️ woman getting massage: dark skin tone
+1F486 1F3FF 200D 2640                      ; non-fully-qualified # 💆🏿‍♀ woman getting massage: dark skin tone
+1F487                                      ; fully-qualified     # 💇 person getting haircut
+1F487 1F3FB                                ; fully-qualified     # 💇🏻 person getting haircut: light skin tone
+1F487 1F3FC                                ; fully-qualified     # 💇🏼 person getting haircut: medium-light skin tone
+1F487 1F3FD                                ; fully-qualified     # 💇🏽 person getting haircut: medium skin tone
+1F487 1F3FE                                ; fully-qualified     # 💇🏾 person getting haircut: medium-dark skin tone
+1F487 1F3FF                                ; fully-qualified     # 💇🏿 person getting haircut: dark skin tone
+1F487 200D 2642 FE0F                       ; fully-qualified     # 💇‍♂️ man getting haircut
+1F487 200D 2642                            ; non-fully-qualified # 💇‍♂ man getting haircut
+1F487 1F3FB 200D 2642 FE0F                 ; fully-qualified     # 💇🏻‍♂️ man getting haircut: light skin tone
+1F487 1F3FB 200D 2642                      ; non-fully-qualified # 💇🏻‍♂ man getting haircut: light skin tone
+1F487 1F3FC 200D 2642 FE0F                 ; fully-qualified     # 💇🏼‍♂️ man getting haircut: medium-light skin tone
+1F487 1F3FC 200D 2642                      ; non-fully-qualified # 💇🏼‍♂ man getting haircut: medium-light skin tone
+1F487 1F3FD 200D 2642 FE0F                 ; fully-qualified     # 💇🏽‍♂️ man getting haircut: medium skin tone
+1F487 1F3FD 200D 2642                      ; non-fully-qualified # 💇🏽‍♂ man getting haircut: medium skin tone
+1F487 1F3FE 200D 2642 FE0F                 ; fully-qualified     # 💇🏾‍♂️ man getting haircut: medium-dark skin tone
+1F487 1F3FE 200D 2642                      ; non-fully-qualified # 💇🏾‍♂ man getting haircut: medium-dark skin tone
+1F487 1F3FF 200D 2642 FE0F                 ; fully-qualified     # 💇🏿‍♂️ man getting haircut: dark skin tone
+1F487 1F3FF 200D 2642                      ; non-fully-qualified # 💇🏿‍♂ man getting haircut: dark skin tone
+1F487 200D 2640 FE0F                       ; fully-qualified     # 💇‍♀️ woman getting haircut
+1F487 200D 2640                            ; non-fully-qualified # 💇‍♀ woman getting haircut
+1F487 1F3FB 200D 2640 FE0F                 ; fully-qualified     # 💇🏻‍♀️ woman getting haircut: light skin tone
+1F487 1F3FB 200D 2640                      ; non-fully-qualified # 💇🏻‍♀ woman getting haircut: light skin tone
+1F487 1F3FC 200D 2640 FE0F                 ; fully-qualified     # 💇🏼‍♀️ woman getting haircut: medium-light skin tone
+1F487 1F3FC 200D 2640                      ; non-fully-qualified # 💇🏼‍♀ woman getting haircut: medium-light skin tone
+1F487 1F3FD 200D 2640 FE0F                 ; fully-qualified     # 💇🏽‍♀️ woman getting haircut: medium skin tone
+1F487 1F3FD 200D 2640                      ; non-fully-qualified # 💇🏽‍♀ woman getting haircut: medium skin tone
+1F487 1F3FE 200D 2640 FE0F                 ; fully-qualified     # 💇🏾‍♀️ woman getting haircut: medium-dark skin tone
+1F487 1F3FE 200D 2640                      ; non-fully-qualified # 💇🏾‍♀ woman getting haircut: medium-dark skin tone
+1F487 1F3FF 200D 2640 FE0F                 ; fully-qualified     # 💇🏿‍♀️ woman getting haircut: dark skin tone
+1F487 1F3FF 200D 2640                      ; non-fully-qualified # 💇🏿‍♀ woman getting haircut: dark skin tone
+1F6B6                                      ; fully-qualified     # 🚶 person walking
+1F6B6 1F3FB                                ; fully-qualified     # 🚶🏻 person walking: light skin tone
+1F6B6 1F3FC                                ; fully-qualified     # 🚶🏼 person walking: medium-light skin tone
+1F6B6 1F3FD                                ; fully-qualified     # 🚶🏽 person walking: medium skin tone
+1F6B6 1F3FE                                ; fully-qualified     # 🚶🏾 person walking: medium-dark skin tone
+1F6B6 1F3FF                                ; fully-qualified     # 🚶🏿 person walking: dark skin tone
+1F6B6 200D 2642 FE0F                       ; fully-qualified     # 🚶‍♂️ man walking
+1F6B6 200D 2642                            ; non-fully-qualified # 🚶‍♂ man walking
+1F6B6 1F3FB 200D 2642 FE0F                 ; fully-qualified     # 🚶🏻‍♂️ man walking: light skin tone
+1F6B6 1F3FB 200D 2642                      ; non-fully-qualified # 🚶🏻‍♂ man walking: light skin tone
+1F6B6 1F3FC 200D 2642 FE0F                 ; fully-qualified     # 🚶🏼‍♂️ man walking: medium-light skin tone
+1F6B6 1F3FC 200D 2642                      ; non-fully-qualified # 🚶🏼‍♂ man walking: medium-light skin tone
+1F6B6 1F3FD 200D 2642 FE0F                 ; fully-qualified     # 🚶🏽‍♂️ man walking: medium skin tone
+1F6B6 1F3FD 200D 2642                      ; non-fully-qualified # 🚶🏽‍♂ man walking: medium skin tone
+1F6B6 1F3FE 200D 2642 FE0F                 ; fully-qualified     # 🚶🏾‍♂️ man walking: medium-dark skin tone
+1F6B6 1F3FE 200D 2642                      ; non-fully-qualified # 🚶🏾‍♂ man walking: medium-dark skin tone
+1F6B6 1F3FF 200D 2642 FE0F                 ; fully-qualified     # 🚶🏿‍♂️ man walking: dark skin tone
+1F6B6 1F3FF 200D 2642                      ; non-fully-qualified # 🚶🏿‍♂ man walking: dark skin tone
+1F6B6 200D 2640 FE0F                       ; fully-qualified     # 🚶‍♀️ woman walking
+1F6B6 200D 2640                            ; non-fully-qualified # 🚶‍♀ woman walking
+1F6B6 1F3FB 200D 2640 FE0F                 ; fully-qualified     # 🚶🏻‍♀️ woman walking: light skin tone
+1F6B6 1F3FB 200D 2640                      ; non-fully-qualified # 🚶🏻‍♀ woman walking: light skin tone
+1F6B6 1F3FC 200D 2640 FE0F                 ; fully-qualified     # 🚶🏼‍♀️ woman walking: medium-light skin tone
+1F6B6 1F3FC 200D 2640                      ; non-fully-qualified # 🚶🏼‍♀ woman walking: medium-light skin tone
+1F6B6 1F3FD 200D 2640 FE0F                 ; fully-qualified     # 🚶🏽‍♀️ woman walking: medium skin tone
+1F6B6 1F3FD 200D 2640                      ; non-fully-qualified # 🚶🏽‍♀ woman walking: medium skin tone
+1F6B6 1F3FE 200D 2640 FE0F                 ; fully-qualified     # 🚶🏾‍♀️ woman walking: medium-dark skin tone
+1F6B6 1F3FE 200D 2640                      ; non-fully-qualified # 🚶🏾‍♀ woman walking: medium-dark skin tone
+1F6B6 1F3FF 200D 2640 FE0F                 ; fully-qualified     # 🚶🏿‍♀️ woman walking: dark skin tone
+1F6B6 1F3FF 200D 2640                      ; non-fully-qualified # 🚶🏿‍♀ woman walking: dark skin tone
+1F3C3                                      ; fully-qualified     # 🏃 person running
+1F3C3 1F3FB                                ; fully-qualified     # 🏃🏻 person running: light skin tone
+1F3C3 1F3FC                                ; fully-qualified     # 🏃🏼 person running: medium-light skin tone
+1F3C3 1F3FD                                ; fully-qualified     # 🏃🏽 person running: medium skin tone
+1F3C3 1F3FE                                ; fully-qualified     # 🏃🏾 person running: medium-dark skin tone
+1F3C3 1F3FF                                ; fully-qualified     # 🏃🏿 person running: dark skin tone
+1F3C3 200D 2642 FE0F                       ; fully-qualified     # 🏃‍♂️ man running
+1F3C3 200D 2642                            ; non-fully-qualified # 🏃‍♂ man running
+1F3C3 1F3FB 200D 2642 FE0F                 ; fully-qualified     # 🏃🏻‍♂️ man running: light skin tone
+1F3C3 1F3FB 200D 2642                      ; non-fully-qualified # 🏃🏻‍♂ man running: light skin tone
+1F3C3 1F3FC 200D 2642 FE0F                 ; fully-qualified     # 🏃🏼‍♂️ man running: medium-light skin tone
+1F3C3 1F3FC 200D 2642                      ; non-fully-qualified # 🏃🏼‍♂ man running: medium-light skin tone
+1F3C3 1F3FD 200D 2642 FE0F                 ; fully-qualified     # 🏃🏽‍♂️ man running: medium skin tone
+1F3C3 1F3FD 200D 2642                      ; non-fully-qualified # 🏃🏽‍♂ man running: medium skin tone
+1F3C3 1F3FE 200D 2642 FE0F                 ; fully-qualified     # 🏃🏾‍♂️ man running: medium-dark skin tone
+1F3C3 1F3FE 200D 2642                      ; non-fully-qualified # 🏃🏾‍♂ man running: medium-dark skin tone
+1F3C3 1F3FF 200D 2642 FE0F                 ; fully-qualified     # 🏃🏿‍♂️ man running: dark skin tone
+1F3C3 1F3FF 200D 2642                      ; non-fully-qualified # 🏃🏿‍♂ man running: dark skin tone
+1F3C3 200D 2640 FE0F                       ; fully-qualified     # 🏃‍♀️ woman running
+1F3C3 200D 2640                            ; non-fully-qualified # 🏃‍♀ woman running
+1F3C3 1F3FB 200D 2640 FE0F                 ; fully-qualified     # 🏃🏻‍♀️ woman running: light skin tone
+1F3C3 1F3FB 200D 2640                      ; non-fully-qualified # 🏃🏻‍♀ woman running: light skin tone
+1F3C3 1F3FC 200D 2640 FE0F                 ; fully-qualified     # 🏃🏼‍♀️ woman running: medium-light skin tone
+1F3C3 1F3FC 200D 2640                      ; non-fully-qualified # 🏃🏼‍♀ woman running: medium-light skin tone
+1F3C3 1F3FD 200D 2640 FE0F                 ; fully-qualified     # 🏃🏽‍♀️ woman running: medium skin tone
+1F3C3 1F3FD 200D 2640                      ; non-fully-qualified # 🏃🏽‍♀ woman running: medium skin tone
+1F3C3 1F3FE 200D 2640 FE0F                 ; fully-qualified     # 🏃🏾‍♀️ woman running: medium-dark skin tone
+1F3C3 1F3FE 200D 2640                      ; non-fully-qualified # 🏃🏾‍♀ woman running: medium-dark skin tone
+1F3C3 1F3FF 200D 2640 FE0F                 ; fully-qualified     # 🏃🏿‍♀️ woman running: dark skin tone
+1F3C3 1F3FF 200D 2640                      ; non-fully-qualified # 🏃🏿‍♀ woman running: dark skin tone
+1F483                                      ; fully-qualified     # 💃 woman dancing
+1F483 1F3FB                                ; fully-qualified     # 💃🏻 woman dancing: light skin tone
+1F483 1F3FC                                ; fully-qualified     # 💃🏼 woman dancing: medium-light skin tone
+1F483 1F3FD                                ; fully-qualified     # 💃🏽 woman dancing: medium skin tone
+1F483 1F3FE                                ; fully-qualified     # 💃🏾 woman dancing: medium-dark skin tone
+1F483 1F3FF                                ; fully-qualified     # 💃🏿 woman dancing: dark skin tone
+1F57A                                      ; fully-qualified     # 🕺 man dancing
+1F57A 1F3FB                                ; fully-qualified     # 🕺🏻 man dancing: light skin tone
+1F57A 1F3FC                                ; fully-qualified     # 🕺🏼 man dancing: medium-light skin tone
+1F57A 1F3FD                                ; fully-qualified     # 🕺🏽 man dancing: medium skin tone
+1F57A 1F3FE                                ; fully-qualified     # 🕺🏾 man dancing: medium-dark skin tone
+1F57A 1F3FF                                ; fully-qualified     # 🕺🏿 man dancing: dark skin tone
+1F46F                                      ; fully-qualified     # 👯 people with bunny ears partying
+1F46F 200D 2642 FE0F                       ; fully-qualified     # 👯‍♂️ men with bunny ears partying
+1F46F 200D 2642                            ; non-fully-qualified # 👯‍♂ men with bunny ears partying
+1F46F 200D 2640 FE0F                       ; fully-qualified     # 👯‍♀️ women with bunny ears partying
+1F46F 200D 2640                            ; non-fully-qualified # 👯‍♀ women with bunny ears partying
+1F574 FE0F                                 ; fully-qualified     # 🕴️ man in business suit levitating
+1F574 1F3FB                                ; fully-qualified     # 🕴🏻 man in business suit levitating: light skin tone
+1F574 1F3FC                                ; fully-qualified     # 🕴🏼 man in business suit levitating: medium-light skin tone
+1F574 1F3FD                                ; fully-qualified     # 🕴🏽 man in business suit levitating: medium skin tone
+1F574 1F3FE                                ; fully-qualified     # 🕴🏾 man in business suit levitating: medium-dark skin tone
+1F574 1F3FF                                ; fully-qualified     # 🕴🏿 man in business suit levitating: dark skin tone
+1F5E3 FE0F                                 ; fully-qualified     # 🗣️ speaking head
+1F464                                      ; fully-qualified     # 👤 bust in silhouette
+1F465                                      ; fully-qualified     # 👥 busts in silhouette
+
+# subgroup: person-sport
+1F93A                                      ; fully-qualified     # 🤺 person fencing
+1F3C7                                      ; fully-qualified     # 🏇 horse racing
+1F3C7 1F3FB                                ; fully-qualified     # 🏇🏻 horse racing: light skin tone
+1F3C7 1F3FC                                ; fully-qualified     # 🏇🏼 horse racing: medium-light skin tone
+1F3C7 1F3FD                                ; fully-qualified     # 🏇🏽 horse racing: medium skin tone
+1F3C7 1F3FE                                ; fully-qualified     # 🏇🏾 horse racing: medium-dark skin tone
+1F3C7 1F3FF                                ; fully-qualified     # 🏇🏿 horse racing: dark skin tone
+26F7 FE0F                                  ; fully-qualified     # ⛷️ skier
+1F3C2                                      ; fully-qualified     # 🏂 snowboarder
+1F3C2 1F3FB                                ; fully-qualified     # 🏂🏻 snowboarder: light skin tone
+1F3C2 1F3FC                                ; fully-qualified     # 🏂🏼 snowboarder: medium-light skin tone
+1F3C2 1F3FD                                ; fully-qualified     # 🏂🏽 snowboarder: medium skin tone
+1F3C2 1F3FE                                ; fully-qualified     # 🏂🏾 snowboarder: medium-dark skin tone
+1F3C2 1F3FF                                ; fully-qualified     # 🏂🏿 snowboarder: dark skin tone
+1F3CC FE0F                                 ; fully-qualified     # 🏌️ person golfing
+1F3CC 1F3FB                                ; fully-qualified     # 🏌🏻 person golfing: light skin tone
+1F3CC 1F3FC                                ; fully-qualified     # 🏌🏼 person golfing: medium-light skin tone
+1F3CC 1F3FD                                ; fully-qualified     # 🏌🏽 person golfing: medium skin tone
+1F3CC 1F3FE                                ; fully-qualified     # 🏌🏾 person golfing: medium-dark skin tone
+1F3CC 1F3FF                                ; fully-qualified     # 🏌🏿 person golfing: dark skin tone
+1F3CC FE0F 200D 2642 FE0F                  ; fully-qualified     # 🏌️‍♂️ man golfing
+1F3CC 200D 2642                            ; non-fully-qualified # 🏌‍♂ man golfing
+1F3CC FE0F 200D 2642                       ; non-fully-qualified # 🏌️‍♂ man golfing
+1F3CC 200D 2642 FE0F                       ; non-fully-qualified # 🏌‍♂️ man golfing
+1F3CC 1F3FB 200D 2642 FE0F                 ; fully-qualified     # 🏌🏻‍♂️ man golfing: light skin tone
+1F3CC 1F3FB 200D 2642                      ; non-fully-qualified # 🏌🏻‍♂ man golfing: light skin tone
+1F3CC 1F3FC 200D 2642 FE0F                 ; fully-qualified     # 🏌🏼‍♂️ man golfing: medium-light skin tone
+1F3CC 1F3FC 200D 2642                      ; non-fully-qualified # 🏌🏼‍♂ man golfing: medium-light skin tone
+1F3CC 1F3FD 200D 2642 FE0F                 ; fully-qualified     # 🏌🏽‍♂️ man golfing: medium skin tone
+1F3CC 1F3FD 200D 2642                      ; non-fully-qualified # 🏌🏽‍♂ man golfing: medium skin tone
+1F3CC 1F3FE 200D 2642 FE0F                 ; fully-qualified     # 🏌🏾‍♂️ man golfing: medium-dark skin tone
+1F3CC 1F3FE 200D 2642                      ; non-fully-qualified # 🏌🏾‍♂ man golfing: medium-dark skin tone
+1F3CC 1F3FF 200D 2642 FE0F                 ; fully-qualified     # 🏌🏿‍♂️ man golfing: dark skin tone
+1F3CC 1F3FF 200D 2642                      ; non-fully-qualified # 🏌🏿‍♂ man golfing: dark skin tone
+1F3CC FE0F 200D 2640 FE0F                  ; fully-qualified     # 🏌️‍♀️ woman golfing
+1F3CC 200D 2640                            ; non-fully-qualified # 🏌‍♀ woman golfing
+1F3CC FE0F 200D 2640                       ; non-fully-qualified # 🏌️‍♀ woman golfing
+1F3CC 200D 2640 FE0F                       ; non-fully-qualified # 🏌‍♀️ woman golfing
+1F3CC 1F3FB 200D 2640 FE0F                 ; fully-qualified     # 🏌🏻‍♀️ woman golfing: light skin tone
+1F3CC 1F3FB 200D 2640                      ; non-fully-qualified # 🏌🏻‍♀ woman golfing: light skin tone
+1F3CC 1F3FC 200D 2640 FE0F                 ; fully-qualified     # 🏌🏼‍♀️ woman golfing: medium-light skin tone
+1F3CC 1F3FC 200D 2640                      ; non-fully-qualified # 🏌🏼‍♀ woman golfing: medium-light skin tone
+1F3CC 1F3FD 200D 2640 FE0F                 ; fully-qualified     # 🏌🏽‍♀️ woman golfing: medium skin tone
+1F3CC 1F3FD 200D 2640                      ; non-fully-qualified # 🏌🏽‍♀ woman golfing: medium skin tone
+1F3CC 1F3FE 200D 2640 FE0F                 ; fully-qualified     # 🏌🏾‍♀️ woman golfing: medium-dark skin tone
+1F3CC 1F3FE 200D 2640                      ; non-fully-qualified # 🏌🏾‍♀ woman golfing: medium-dark skin tone
+1F3CC 1F3FF 200D 2640 FE0F                 ; fully-qualified     # 🏌🏿‍♀️ woman golfing: dark skin tone
+1F3CC 1F3FF 200D 2640                      ; non-fully-qualified # 🏌🏿‍♀ woman golfing: dark skin tone
+1F3C4                                      ; fully-qualified     # 🏄 person surfing
+1F3C4 1F3FB                                ; fully-qualified     # 🏄🏻 person surfing: light skin tone
+1F3C4 1F3FC                                ; fully-qualified     # 🏄🏼 person surfing: medium-light skin tone
+1F3C4 1F3FD                                ; fully-qualified     # 🏄🏽 person surfing: medium skin tone
+1F3C4 1F3FE                                ; fully-qualified     # 🏄🏾 person surfing: medium-dark skin tone
+1F3C4 1F3FF                                ; fully-qualified     # 🏄🏿 person surfing: dark skin tone
+1F3C4 200D 2642 FE0F                       ; fully-qualified     # 🏄‍♂️ man surfing
+1F3C4 200D 2642                            ; non-fully-qualified # 🏄‍♂ man surfing
+1F3C4 1F3FB 200D 2642 FE0F                 ; fully-qualified     # 🏄🏻‍♂️ man surfing: light skin tone
+1F3C4 1F3FB 200D 2642                      ; non-fully-qualified # 🏄🏻‍♂ man surfing: light skin tone
+1F3C4 1F3FC 200D 2642 FE0F                 ; fully-qualified     # 🏄🏼‍♂️ man surfing: medium-light skin tone
+1F3C4 1F3FC 200D 2642                      ; non-fully-qualified # 🏄🏼‍♂ man surfing: medium-light skin tone
+1F3C4 1F3FD 200D 2642 FE0F                 ; fully-qualified     # 🏄🏽‍♂️ man surfing: medium skin tone
+1F3C4 1F3FD 200D 2642                      ; non-fully-qualified # 🏄🏽‍♂ man surfing: medium skin tone
+1F3C4 1F3FE 200D 2642 FE0F                 ; fully-qualified     # 🏄🏾‍♂️ man surfing: medium-dark skin tone
+1F3C4 1F3FE 200D 2642                      ; non-fully-qualified # 🏄🏾‍♂ man surfing: medium-dark skin tone
+1F3C4 1F3FF 200D 2642 FE0F                 ; fully-qualified     # 🏄🏿‍♂️ man surfing: dark skin tone
+1F3C4 1F3FF 200D 2642                      ; non-fully-qualified # 🏄🏿‍♂ man surfing: dark skin tone
+1F3C4 200D 2640 FE0F                       ; fully-qualified     # 🏄‍♀️ woman surfing
+1F3C4 200D 2640                            ; non-fully-qualified # 🏄‍♀ woman surfing
+1F3C4 1F3FB 200D 2640 FE0F                 ; fully-qualified     # 🏄🏻‍♀️ woman surfing: light skin tone
+1F3C4 1F3FB 200D 2640                      ; non-fully-qualified # 🏄🏻‍♀ woman surfing: light skin tone
+1F3C4 1F3FC 200D 2640 FE0F                 ; fully-qualified     # 🏄🏼‍♀️ woman surfing: medium-light skin tone
+1F3C4 1F3FC 200D 2640                      ; non-fully-qualified # 🏄🏼‍♀ woman surfing: medium-light skin tone
+1F3C4 1F3FD 200D 2640 FE0F                 ; fully-qualified     # 🏄🏽‍♀️ woman surfing: medium skin tone
+1F3C4 1F3FD 200D 2640                      ; non-fully-qualified # 🏄🏽‍♀ woman surfing: medium skin tone
+1F3C4 1F3FE 200D 2640 FE0F                 ; fully-qualified     # 🏄🏾‍♀️ woman surfing: medium-dark skin tone
+1F3C4 1F3FE 200D 2640                      ; non-fully-qualified # 🏄🏾‍♀ woman surfing: medium-dark skin tone
+1F3C4 1F3FF 200D 2640 FE0F                 ; fully-qualified     # 🏄🏿‍♀️ woman surfing: dark skin tone
+1F3C4 1F3FF 200D 2640                      ; non-fully-qualified # 🏄🏿‍♀ woman surfing: dark skin tone
+1F6A3                                      ; fully-qualified     # 🚣 person rowing boat
+1F6A3 1F3FB                                ; fully-qualified     # 🚣🏻 person rowing boat: light skin tone
+1F6A3 1F3FC                                ; fully-qualified     # 🚣🏼 person rowing boat: medium-light skin tone
+1F6A3 1F3FD                                ; fully-qualified     # 🚣🏽 person rowing boat: medium skin tone
+1F6A3 1F3FE                                ; fully-qualified     # 🚣🏾 person rowing boat: medium-dark skin tone
+1F6A3 1F3FF                                ; fully-qualified     # 🚣🏿 person rowing boat: dark skin tone
+1F6A3 200D 2642 FE0F                       ; fully-qualified     # 🚣‍♂️ man rowing boat
+1F6A3 200D 2642                            ; non-fully-qualified # 🚣‍♂ man rowing boat
+1F6A3 1F3FB 200D 2642 FE0F                 ; fully-qualified     # 🚣🏻‍♂️ man rowing boat: light skin tone
+1F6A3 1F3FB 200D 2642                      ; non-fully-qualified # 🚣🏻‍♂ man rowing boat: light skin tone
+1F6A3 1F3FC 200D 2642 FE0F                 ; fully-qualified     # 🚣🏼‍♂️ man rowing boat: medium-light skin tone
+1F6A3 1F3FC 200D 2642                      ; non-fully-qualified # 🚣🏼‍♂ man rowing boat: medium-light skin tone
+1F6A3 1F3FD 200D 2642 FE0F                 ; fully-qualified     # 🚣🏽‍♂️ man rowing boat: medium skin tone
+1F6A3 1F3FD 200D 2642                      ; non-fully-qualified # 🚣🏽‍♂ man rowing boat: medium skin tone
+1F6A3 1F3FE 200D 2642 FE0F                 ; fully-qualified     # 🚣🏾‍♂️ man rowing boat: medium-dark skin tone
+1F6A3 1F3FE 200D 2642                      ; non-fully-qualified # 🚣🏾‍♂ man rowing boat: medium-dark skin tone
+1F6A3 1F3FF 200D 2642 FE0F                 ; fully-qualified     # 🚣🏿‍♂️ man rowing boat: dark skin tone
+1F6A3 1F3FF 200D 2642                      ; non-fully-qualified # 🚣🏿‍♂ man rowing boat: dark skin tone
+1F6A3 200D 2640 FE0F                       ; fully-qualified     # 🚣‍♀️ woman rowing boat
+1F6A3 200D 2640                            ; non-fully-qualified # 🚣‍♀ woman rowing boat
+1F6A3 1F3FB 200D 2640 FE0F                 ; fully-qualified     # 🚣🏻‍♀️ woman rowing boat: light skin tone
+1F6A3 1F3FB 200D 2640                      ; non-fully-qualified # 🚣🏻‍♀ woman rowing boat: light skin tone
+1F6A3 1F3FC 200D 2640 FE0F                 ; fully-qualified     # 🚣🏼‍♀️ woman rowing boat: medium-light skin tone
+1F6A3 1F3FC 200D 2640                      ; non-fully-qualified # 🚣🏼‍♀ woman rowing boat: medium-light skin tone
+1F6A3 1F3FD 200D 2640 FE0F                 ; fully-qualified     # 🚣🏽‍♀️ woman rowing boat: medium skin tone
+1F6A3 1F3FD 200D 2640                      ; non-fully-qualified # 🚣🏽‍♀ woman rowing boat: medium skin tone
+1F6A3 1F3FE 200D 2640 FE0F                 ; fully-qualified     # 🚣🏾‍♀️ woman rowing boat: medium-dark skin tone
+1F6A3 1F3FE 200D 2640                      ; non-fully-qualified # 🚣🏾‍♀ woman rowing boat: medium-dark skin tone
+1F6A3 1F3FF 200D 2640 FE0F                 ; fully-qualified     # 🚣🏿‍♀️ woman rowing boat: dark skin tone
+1F6A3 1F3FF 200D 2640                      ; non-fully-qualified # 🚣🏿‍♀ woman rowing boat: dark skin tone
+1F3CA                                      ; fully-qualified     # 🏊 person swimming
+1F3CA 1F3FB                                ; fully-qualified     # 🏊🏻 person swimming: light skin tone
+1F3CA 1F3FC                                ; fully-qualified     # 🏊🏼 person swimming: medium-light skin tone
+1F3CA 1F3FD                                ; fully-qualified     # 🏊🏽 person swimming: medium skin tone
+1F3CA 1F3FE                                ; fully-qualified     # 🏊🏾 person swimming: medium-dark skin tone
+1F3CA 1F3FF                                ; fully-qualified     # 🏊🏿 person swimming: dark skin tone
+1F3CA 200D 2642 FE0F                       ; fully-qualified     # 🏊‍♂️ man swimming
+1F3CA 200D 2642                            ; non-fully-qualified # 🏊‍♂ man swimming
+1F3CA 1F3FB 200D 2642 FE0F                 ; fully-qualified     # 🏊🏻‍♂️ man swimming: light skin tone
+1F3CA 1F3FB 200D 2642                      ; non-fully-qualified # 🏊🏻‍♂ man swimming: light skin tone
+1F3CA 1F3FC 200D 2642 FE0F                 ; fully-qualified     # 🏊🏼‍♂️ man swimming: medium-light skin tone
+1F3CA 1F3FC 200D 2642                      ; non-fully-qualified # 🏊🏼‍♂ man swimming: medium-light skin tone
+1F3CA 1F3FD 200D 2642 FE0F                 ; fully-qualified     # 🏊🏽‍♂️ man swimming: medium skin tone
+1F3CA 1F3FD 200D 2642                      ; non-fully-qualified # 🏊🏽‍♂ man swimming: medium skin tone
+1F3CA 1F3FE 200D 2642 FE0F                 ; fully-qualified     # 🏊🏾‍♂️ man swimming: medium-dark skin tone
+1F3CA 1F3FE 200D 2642                      ; non-fully-qualified # 🏊🏾‍♂ man swimming: medium-dark skin tone
+1F3CA 1F3FF 200D 2642 FE0F                 ; fully-qualified     # 🏊🏿‍♂️ man swimming: dark skin tone
+1F3CA 1F3FF 200D 2642                      ; non-fully-qualified # 🏊🏿‍♂ man swimming: dark skin tone
+1F3CA 200D 2640 FE0F                       ; fully-qualified     # 🏊‍♀️ woman swimming
+1F3CA 200D 2640                            ; non-fully-qualified # 🏊‍♀ woman swimming
+1F3CA 1F3FB 200D 2640 FE0F                 ; fully-qualified     # 🏊🏻‍♀️ woman swimming: light skin tone
+1F3CA 1F3FB 200D 2640                      ; non-fully-qualified # 🏊🏻‍♀ woman swimming: light skin tone
+1F3CA 1F3FC 200D 2640 FE0F                 ; fully-qualified     # 🏊🏼‍♀️ woman swimming: medium-light skin tone
+1F3CA 1F3FC 200D 2640                      ; non-fully-qualified # 🏊🏼‍♀ woman swimming: medium-light skin tone
+1F3CA 1F3FD 200D 2640 FE0F                 ; fully-qualified     # 🏊🏽‍♀️ woman swimming: medium skin tone
+1F3CA 1F3FD 200D 2640                      ; non-fully-qualified # 🏊🏽‍♀ woman swimming: medium skin tone
+1F3CA 1F3FE 200D 2640 FE0F                 ; fully-qualified     # 🏊🏾‍♀️ woman swimming: medium-dark skin tone
+1F3CA 1F3FE 200D 2640                      ; non-fully-qualified # 🏊🏾‍♀ woman swimming: medium-dark skin tone
+1F3CA 1F3FF 200D 2640 FE0F                 ; fully-qualified     # 🏊🏿‍♀️ woman swimming: dark skin tone
+1F3CA 1F3FF 200D 2640                      ; non-fully-qualified # 🏊🏿‍♀ woman swimming: dark skin tone
+26F9 FE0F                                  ; fully-qualified     # ⛹️ person bouncing ball
+26F9 1F3FB                                 ; fully-qualified     # ⛹🏻 person bouncing ball: light skin tone
+26F9 1F3FC                                 ; fully-qualified     # ⛹🏼 person bouncing ball: medium-light skin tone
+26F9 1F3FD                                 ; fully-qualified     # ⛹🏽 person bouncing ball: medium skin tone
+26F9 1F3FE                                 ; fully-qualified     # ⛹🏾 person bouncing ball: medium-dark skin tone
+26F9 1F3FF                                 ; fully-qualified     # ⛹🏿 person bouncing ball: dark skin tone
+26F9 FE0F 200D 2642 FE0F                   ; fully-qualified     # ⛹️‍♂️ man bouncing ball
+26F9 200D 2642                             ; non-fully-qualified # ⛹‍♂ man bouncing ball
+26F9 FE0F 200D 2642                        ; non-fully-qualified # ⛹️‍♂ man bouncing ball
+26F9 200D 2642 FE0F                        ; non-fully-qualified # ⛹‍♂️ man bouncing ball
+26F9 1F3FB 200D 2642 FE0F                  ; fully-qualified     # ⛹🏻‍♂️ man bouncing ball: light skin tone
+26F9 1F3FB 200D 2642                       ; non-fully-qualified # ⛹🏻‍♂ man bouncing ball: light skin tone
+26F9 1F3FC 200D 2642 FE0F                  ; fully-qualified     # ⛹🏼‍♂️ man bouncing ball: medium-light skin tone
+26F9 1F3FC 200D 2642                       ; non-fully-qualified # ⛹🏼‍♂ man bouncing ball: medium-light skin tone
+26F9 1F3FD 200D 2642 FE0F                  ; fully-qualified     # ⛹🏽‍♂️ man bouncing ball: medium skin tone
+26F9 1F3FD 200D 2642                       ; non-fully-qualified # ⛹🏽‍♂ man bouncing ball: medium skin tone
+26F9 1F3FE 200D 2642 FE0F                  ; fully-qualified     # ⛹🏾‍♂️ man bouncing ball: medium-dark skin tone
+26F9 1F3FE 200D 2642                       ; non-fully-qualified # ⛹🏾‍♂ man bouncing ball: medium-dark skin tone
+26F9 1F3FF 200D 2642 FE0F                  ; fully-qualified     # ⛹🏿‍♂️ man bouncing ball: dark skin tone
+26F9 1F3FF 200D 2642                       ; non-fully-qualified # ⛹🏿‍♂ man bouncing ball: dark skin tone
+26F9 FE0F 200D 2640 FE0F                   ; fully-qualified     # ⛹️‍♀️ woman bouncing ball
+26F9 200D 2640                             ; non-fully-qualified # ⛹‍♀ woman bouncing ball
+26F9 FE0F 200D 2640                        ; non-fully-qualified # ⛹️‍♀ woman bouncing ball
+26F9 200D 2640 FE0F                        ; non-fully-qualified # ⛹‍♀️ woman bouncing ball
+26F9 1F3FB 200D 2640 FE0F                  ; fully-qualified     # ⛹🏻‍♀️ woman bouncing ball: light skin tone
+26F9 1F3FB 200D 2640                       ; non-fully-qualified # ⛹🏻‍♀ woman bouncing ball: light skin tone
+26F9 1F3FC 200D 2640 FE0F                  ; fully-qualified     # ⛹🏼‍♀️ woman bouncing ball: medium-light skin tone
+26F9 1F3FC 200D 2640                       ; non-fully-qualified # ⛹🏼‍♀ woman bouncing ball: medium-light skin tone
+26F9 1F3FD 200D 2640 FE0F                  ; fully-qualified     # ⛹🏽‍♀️ woman bouncing ball: medium skin tone
+26F9 1F3FD 200D 2640                       ; non-fully-qualified # ⛹🏽‍♀ woman bouncing ball: medium skin tone
+26F9 1F3FE 200D 2640 FE0F                  ; fully-qualified     # ⛹🏾‍♀️ woman bouncing ball: medium-dark skin tone
+26F9 1F3FE 200D 2640                       ; non-fully-qualified # ⛹🏾‍♀ woman bouncing ball: medium-dark skin tone
+26F9 1F3FF 200D 2640 FE0F                  ; fully-qualified     # ⛹🏿‍♀️ woman bouncing ball: dark skin tone
+26F9 1F3FF 200D 2640                       ; non-fully-qualified # ⛹🏿‍♀ woman bouncing ball: dark skin tone
+1F3CB FE0F                                 ; fully-qualified     # 🏋️ person lifting weights
+1F3CB 1F3FB                                ; fully-qualified     # 🏋🏻 person lifting weights: light skin tone
+1F3CB 1F3FC                                ; fully-qualified     # 🏋🏼 person lifting weights: medium-light skin tone
+1F3CB 1F3FD                                ; fully-qualified     # 🏋🏽 person lifting weights: medium skin tone
+1F3CB 1F3FE                                ; fully-qualified     # 🏋🏾 person lifting weights: medium-dark skin tone
+1F3CB 1F3FF                                ; fully-qualified     # 🏋🏿 person lifting weights: dark skin tone
+1F3CB FE0F 200D 2642 FE0F                  ; fully-qualified     # 🏋️‍♂️ man lifting weights
+1F3CB 200D 2642                            ; non-fully-qualified # 🏋‍♂ man lifting weights
+1F3CB FE0F 200D 2642                       ; non-fully-qualified # 🏋️‍♂ man lifting weights
+1F3CB 200D 2642 FE0F                       ; non-fully-qualified # 🏋‍♂️ man lifting weights
+1F3CB 1F3FB 200D 2642 FE0F                 ; fully-qualified     # 🏋🏻‍♂️ man lifting weights: light skin tone
+1F3CB 1F3FB 200D 2642                      ; non-fully-qualified # 🏋🏻‍♂ man lifting weights: light skin tone
+1F3CB 1F3FC 200D 2642 FE0F                 ; fully-qualified     # 🏋🏼‍♂️ man lifting weights: medium-light skin tone
+1F3CB 1F3FC 200D 2642                      ; non-fully-qualified # 🏋🏼‍♂ man lifting weights: medium-light skin tone
+1F3CB 1F3FD 200D 2642 FE0F                 ; fully-qualified     # 🏋🏽‍♂️ man lifting weights: medium skin tone
+1F3CB 1F3FD 200D 2642                      ; non-fully-qualified # 🏋🏽‍♂ man lifting weights: medium skin tone
+1F3CB 1F3FE 200D 2642 FE0F                 ; fully-qualified     # 🏋🏾‍♂️ man lifting weights: medium-dark skin tone
+1F3CB 1F3FE 200D 2642                      ; non-fully-qualified # 🏋🏾‍♂ man lifting weights: medium-dark skin tone
+1F3CB 1F3FF 200D 2642 FE0F                 ; fully-qualified     # 🏋🏿‍♂️ man lifting weights: dark skin tone
+1F3CB 1F3FF 200D 2642                      ; non-fully-qualified # 🏋🏿‍♂ man lifting weights: dark skin tone
+1F3CB FE0F 200D 2640 FE0F                  ; fully-qualified     # 🏋️‍♀️ woman lifting weights
+1F3CB 200D 2640                            ; non-fully-qualified # 🏋‍♀ woman lifting weights
+1F3CB FE0F 200D 2640                       ; non-fully-qualified # 🏋️‍♀ woman lifting weights
+1F3CB 200D 2640 FE0F                       ; non-fully-qualified # 🏋‍♀️ woman lifting weights
+1F3CB 1F3FB 200D 2640 FE0F                 ; fully-qualified     # 🏋🏻‍♀️ woman lifting weights: light skin tone
+1F3CB 1F3FB 200D 2640                      ; non-fully-qualified # 🏋🏻‍♀ woman lifting weights: light skin tone
+1F3CB 1F3FC 200D 2640 FE0F                 ; fully-qualified     # 🏋🏼‍♀️ woman lifting weights: medium-light skin tone
+1F3CB 1F3FC 200D 2640                      ; non-fully-qualified # 🏋🏼‍♀ woman lifting weights: medium-light skin tone
+1F3CB 1F3FD 200D 2640 FE0F                 ; fully-qualified     # 🏋🏽‍♀️ woman lifting weights: medium skin tone
+1F3CB 1F3FD 200D 2640                      ; non-fully-qualified # 🏋🏽‍♀ woman lifting weights: medium skin tone
+1F3CB 1F3FE 200D 2640 FE0F                 ; fully-qualified     # 🏋🏾‍♀️ woman lifting weights: medium-dark skin tone
+1F3CB 1F3FE 200D 2640                      ; non-fully-qualified # 🏋🏾‍♀ woman lifting weights: medium-dark skin tone
+1F3CB 1F3FF 200D 2640 FE0F                 ; fully-qualified     # 🏋🏿‍♀️ woman lifting weights: dark skin tone
+1F3CB 1F3FF 200D 2640                      ; non-fully-qualified # 🏋🏿‍♀ woman lifting weights: dark skin tone
+1F6B4                                      ; fully-qualified     # 🚴 person biking
+1F6B4 1F3FB                                ; fully-qualified     # 🚴🏻 person biking: light skin tone
+1F6B4 1F3FC                                ; fully-qualified     # 🚴🏼 person biking: medium-light skin tone
+1F6B4 1F3FD                                ; fully-qualified     # 🚴🏽 person biking: medium skin tone
+1F6B4 1F3FE                                ; fully-qualified     # 🚴🏾 person biking: medium-dark skin tone
+1F6B4 1F3FF                                ; fully-qualified     # 🚴🏿 person biking: dark skin tone
+1F6B4 200D 2642 FE0F                       ; fully-qualified     # 🚴‍♂️ man biking
+1F6B4 200D 2642                            ; non-fully-qualified # 🚴‍♂ man biking
+1F6B4 1F3FB 200D 2642 FE0F                 ; fully-qualified     # 🚴🏻‍♂️ man biking: light skin tone
+1F6B4 1F3FB 200D 2642                      ; non-fully-qualified # 🚴🏻‍♂ man biking: light skin tone
+1F6B4 1F3FC 200D 2642 FE0F                 ; fully-qualified     # 🚴🏼‍♂️ man biking: medium-light skin tone
+1F6B4 1F3FC 200D 2642                      ; non-fully-qualified # 🚴🏼‍♂ man biking: medium-light skin tone
+1F6B4 1F3FD 200D 2642 FE0F                 ; fully-qualified     # 🚴🏽‍♂️ man biking: medium skin tone
+1F6B4 1F3FD 200D 2642                      ; non-fully-qualified # 🚴🏽‍♂ man biking: medium skin tone
+1F6B4 1F3FE 200D 2642 FE0F                 ; fully-qualified     # 🚴🏾‍♂️ man biking: medium-dark skin tone
+1F6B4 1F3FE 200D 2642                      ; non-fully-qualified # 🚴🏾‍♂ man biking: medium-dark skin tone
+1F6B4 1F3FF 200D 2642 FE0F                 ; fully-qualified     # 🚴🏿‍♂️ man biking: dark skin tone
+1F6B4 1F3FF 200D 2642                      ; non-fully-qualified # 🚴🏿‍♂ man biking: dark skin tone
+1F6B4 200D 2640 FE0F                       ; fully-qualified     # 🚴‍♀️ woman biking
+1F6B4 200D 2640                            ; non-fully-qualified # 🚴‍♀ woman biking
+1F6B4 1F3FB 200D 2640 FE0F                 ; fully-qualified     # 🚴🏻‍♀️ woman biking: light skin tone
+1F6B4 1F3FB 200D 2640                      ; non-fully-qualified # 🚴🏻‍♀ woman biking: light skin tone
+1F6B4 1F3FC 200D 2640 FE0F                 ; fully-qualified     # 🚴🏼‍♀️ woman biking: medium-light skin tone
+1F6B4 1F3FC 200D 2640                      ; non-fully-qualified # 🚴🏼‍♀ woman biking: medium-light skin tone
+1F6B4 1F3FD 200D 2640 FE0F                 ; fully-qualified     # 🚴🏽‍♀️ woman biking: medium skin tone
+1F6B4 1F3FD 200D 2640                      ; non-fully-qualified # 🚴🏽‍♀ woman biking: medium skin tone
+1F6B4 1F3FE 200D 2640 FE0F                 ; fully-qualified     # 🚴🏾‍♀️ woman biking: medium-dark skin tone
+1F6B4 1F3FE 200D 2640                      ; non-fully-qualified # 🚴🏾‍♀ woman biking: medium-dark skin tone
+1F6B4 1F3FF 200D 2640 FE0F                 ; fully-qualified     # 🚴🏿‍♀️ woman biking: dark skin tone
+1F6B4 1F3FF 200D 2640                      ; non-fully-qualified # 🚴🏿‍♀ woman biking: dark skin tone
+1F6B5                                      ; fully-qualified     # 🚵 person mountain biking
+1F6B5 1F3FB                                ; fully-qualified     # 🚵🏻 person mountain biking: light skin tone
+1F6B5 1F3FC                                ; fully-qualified     # 🚵🏼 person mountain biking: medium-light skin tone
+1F6B5 1F3FD                                ; fully-qualified     # 🚵🏽 person mountain biking: medium skin tone
+1F6B5 1F3FE                                ; fully-qualified     # 🚵🏾 person mountain biking: medium-dark skin tone
+1F6B5 1F3FF                                ; fully-qualified     # 🚵🏿 person mountain biking: dark skin tone
+1F6B5 200D 2642 FE0F                       ; fully-qualified     # 🚵‍♂️ man mountain biking
+1F6B5 200D 2642                            ; non-fully-qualified # 🚵‍♂ man mountain biking
+1F6B5 1F3FB 200D 2642 FE0F                 ; fully-qualified     # 🚵🏻‍♂️ man mountain biking: light skin tone
+1F6B5 1F3FB 200D 2642                      ; non-fully-qualified # 🚵🏻‍♂ man mountain biking: light skin tone
+1F6B5 1F3FC 200D 2642 FE0F                 ; fully-qualified     # 🚵🏼‍♂️ man mountain biking: medium-light skin tone
+1F6B5 1F3FC 200D 2642                      ; non-fully-qualified # 🚵🏼‍♂ man mountain biking: medium-light skin tone
+1F6B5 1F3FD 200D 2642 FE0F                 ; fully-qualified     # 🚵🏽‍♂️ man mountain biking: medium skin tone
+1F6B5 1F3FD 200D 2642                      ; non-fully-qualified # 🚵🏽‍♂ man mountain biking: medium skin tone
+1F6B5 1F3FE 200D 2642 FE0F                 ; fully-qualified     # 🚵🏾‍♂️ man mountain biking: medium-dark skin tone
+1F6B5 1F3FE 200D 2642                      ; non-fully-qualified # 🚵🏾‍♂ man mountain biking: medium-dark skin tone
+1F6B5 1F3FF 200D 2642 FE0F                 ; fully-qualified     # 🚵🏿‍♂️ man mountain biking: dark skin tone
+1F6B5 1F3FF 200D 2642                      ; non-fully-qualified # 🚵🏿‍♂ man mountain biking: dark skin tone
+1F6B5 200D 2640 FE0F                       ; fully-qualified     # 🚵‍♀️ woman mountain biking
+1F6B5 200D 2640                            ; non-fully-qualified # 🚵‍♀ woman mountain biking
+1F6B5 1F3FB 200D 2640 FE0F                 ; fully-qualified     # 🚵🏻‍♀️ woman mountain biking: light skin tone
+1F6B5 1F3FB 200D 2640                      ; non-fully-qualified # 🚵🏻‍♀ woman mountain biking: light skin tone
+1F6B5 1F3FC 200D 2640 FE0F                 ; fully-qualified     # 🚵🏼‍♀️ woman mountain biking: medium-light skin tone
+1F6B5 1F3FC 200D 2640                      ; non-fully-qualified # 🚵🏼‍♀ woman mountain biking: medium-light skin tone
+1F6B5 1F3FD 200D 2640 FE0F                 ; fully-qualified     # 🚵🏽‍♀️ woman mountain biking: medium skin tone
+1F6B5 1F3FD 200D 2640                      ; non-fully-qualified # 🚵🏽‍♀ woman mountain biking: medium skin tone
+1F6B5 1F3FE 200D 2640 FE0F                 ; fully-qualified     # 🚵🏾‍♀️ woman mountain biking: medium-dark skin tone
+1F6B5 1F3FE 200D 2640                      ; non-fully-qualified # 🚵🏾‍♀ woman mountain biking: medium-dark skin tone
+1F6B5 1F3FF 200D 2640 FE0F                 ; fully-qualified     # 🚵🏿‍♀️ woman mountain biking: dark skin tone
+1F6B5 1F3FF 200D 2640                      ; non-fully-qualified # 🚵🏿‍♀ woman mountain biking: dark skin tone
+1F3CE FE0F                                 ; fully-qualified     # 🏎️ racing car
+1F3CD FE0F                                 ; fully-qualified     # 🏍️ motorcycle
+1F938                                      ; fully-qualified     # 🤸 person cartwheeling
+1F938 1F3FB                                ; fully-qualified     # 🤸🏻 person cartwheeling: light skin tone
+1F938 1F3FC                                ; fully-qualified     # 🤸🏼 person cartwheeling: medium-light skin tone
+1F938 1F3FD                                ; fully-qualified     # 🤸🏽 person cartwheeling: medium skin tone
+1F938 1F3FE                                ; fully-qualified     # 🤸🏾 person cartwheeling: medium-dark skin tone
+1F938 1F3FF                                ; fully-qualified     # 🤸🏿 person cartwheeling: dark skin tone
+1F938 200D 2642 FE0F                       ; fully-qualified     # 🤸‍♂️ man cartwheeling
+1F938 200D 2642                            ; non-fully-qualified # 🤸‍♂ man cartwheeling
+1F938 1F3FB 200D 2642 FE0F                 ; fully-qualified     # 🤸🏻‍♂️ man cartwheeling: light skin tone
+1F938 1F3FB 200D 2642                      ; non-fully-qualified # 🤸🏻‍♂ man cartwheeling: light skin tone
+1F938 1F3FC 200D 2642 FE0F                 ; fully-qualified     # 🤸🏼‍♂️ man cartwheeling: medium-light skin tone
+1F938 1F3FC 200D 2642                      ; non-fully-qualified # 🤸🏼‍♂ man cartwheeling: medium-light skin tone
+1F938 1F3FD 200D 2642 FE0F                 ; fully-qualified     # 🤸🏽‍♂️ man cartwheeling: medium skin tone
+1F938 1F3FD 200D 2642                      ; non-fully-qualified # 🤸🏽‍♂ man cartwheeling: medium skin tone
+1F938 1F3FE 200D 2642 FE0F                 ; fully-qualified     # 🤸🏾‍♂️ man cartwheeling: medium-dark skin tone
+1F938 1F3FE 200D 2642                      ; non-fully-qualified # 🤸🏾‍♂ man cartwheeling: medium-dark skin tone
+1F938 1F3FF 200D 2642 FE0F                 ; fully-qualified     # 🤸🏿‍♂️ man cartwheeling: dark skin tone
+1F938 1F3FF 200D 2642                      ; non-fully-qualified # 🤸🏿‍♂ man cartwheeling: dark skin tone
+1F938 200D 2640 FE0F                       ; fully-qualified     # 🤸‍♀️ woman cartwheeling
+1F938 200D 2640                            ; non-fully-qualified # 🤸‍♀ woman cartwheeling
+1F938 1F3FB 200D 2640 FE0F                 ; fully-qualified     # 🤸🏻‍♀️ woman cartwheeling: light skin tone
+1F938 1F3FB 200D 2640                      ; non-fully-qualified # 🤸🏻‍♀ woman cartwheeling: light skin tone
+1F938 1F3FC 200D 2640 FE0F                 ; fully-qualified     # 🤸🏼‍♀️ woman cartwheeling: medium-light skin tone
+1F938 1F3FC 200D 2640                      ; non-fully-qualified # 🤸🏼‍♀ woman cartwheeling: medium-light skin tone
+1F938 1F3FD 200D 2640 FE0F                 ; fully-qualified     # 🤸🏽‍♀️ woman cartwheeling: medium skin tone
+1F938 1F3FD 200D 2640                      ; non-fully-qualified # 🤸🏽‍♀ woman cartwheeling: medium skin tone
+1F938 1F3FE 200D 2640 FE0F                 ; fully-qualified     # 🤸🏾‍♀️ woman cartwheeling: medium-dark skin tone
+1F938 1F3FE 200D 2640                      ; non-fully-qualified # 🤸🏾‍♀ woman cartwheeling: medium-dark skin tone
+1F938 1F3FF 200D 2640 FE0F                 ; fully-qualified     # 🤸🏿‍♀️ woman cartwheeling: dark skin tone
+1F938 1F3FF 200D 2640                      ; non-fully-qualified # 🤸🏿‍♀ woman cartwheeling: dark skin tone
+1F93C                                      ; fully-qualified     # 🤼 people wrestling
+1F93C 200D 2642 FE0F                       ; fully-qualified     # 🤼‍♂️ men wrestling
+1F93C 200D 2642                            ; non-fully-qualified # 🤼‍♂ men wrestling
+1F93C 200D 2640 FE0F                       ; fully-qualified     # 🤼‍♀️ women wrestling
+1F93C 200D 2640                            ; non-fully-qualified # 🤼‍♀ women wrestling
+1F93D                                      ; fully-qualified     # 🤽 person playing water polo
+1F93D 1F3FB                                ; fully-qualified     # 🤽🏻 person playing water polo: light skin tone
+1F93D 1F3FC                                ; fully-qualified     # 🤽🏼 person playing water polo: medium-light skin tone
+1F93D 1F3FD                                ; fully-qualified     # 🤽🏽 person playing water polo: medium skin tone
+1F93D 1F3FE                                ; fully-qualified     # 🤽🏾 person playing water polo: medium-dark skin tone
+1F93D 1F3FF                                ; fully-qualified     # 🤽🏿 person playing water polo: dark skin tone
+1F93D 200D 2642 FE0F                       ; fully-qualified     # 🤽‍♂️ man playing water polo
+1F93D 200D 2642                            ; non-fully-qualified # 🤽‍♂ man playing water polo
+1F93D 1F3FB 200D 2642 FE0F                 ; fully-qualified     # 🤽🏻‍♂️ man playing water polo: light skin tone
+1F93D 1F3FB 200D 2642                      ; non-fully-qualified # 🤽🏻‍♂ man playing water polo: light skin tone
+1F93D 1F3FC 200D 2642 FE0F                 ; fully-qualified     # 🤽🏼‍♂️ man playing water polo: medium-light skin tone
+1F93D 1F3FC 200D 2642                      ; non-fully-qualified # 🤽🏼‍♂ man playing water polo: medium-light skin tone
+1F93D 1F3FD 200D 2642 FE0F                 ; fully-qualified     # 🤽🏽‍♂️ man playing water polo: medium skin tone
+1F93D 1F3FD 200D 2642                      ; non-fully-qualified # 🤽🏽‍♂ man playing water polo: medium skin tone
+1F93D 1F3FE 200D 2642 FE0F                 ; fully-qualified     # 🤽🏾‍♂️ man playing water polo: medium-dark skin tone
+1F93D 1F3FE 200D 2642                      ; non-fully-qualified # 🤽🏾‍♂ man playing water polo: medium-dark skin tone
+1F93D 1F3FF 200D 2642 FE0F                 ; fully-qualified     # 🤽🏿‍♂️ man playing water polo: dark skin tone
+1F93D 1F3FF 200D 2642                      ; non-fully-qualified # 🤽🏿‍♂ man playing water polo: dark skin tone
+1F93D 200D 2640 FE0F                       ; fully-qualified     # 🤽‍♀️ woman playing water polo
+1F93D 200D 2640                            ; non-fully-qualified # 🤽‍♀ woman playing water polo
+1F93D 1F3FB 200D 2640 FE0F                 ; fully-qualified     # 🤽🏻‍♀️ woman playing water polo: light skin tone
+1F93D 1F3FB 200D 2640                      ; non-fully-qualified # 🤽🏻‍♀ woman playing water polo: light skin tone
+1F93D 1F3FC 200D 2640 FE0F                 ; fully-qualified     # 🤽🏼‍♀️ woman playing water polo: medium-light skin tone
+1F93D 1F3FC 200D 2640                      ; non-fully-qualified # 🤽🏼‍♀ woman playing water polo: medium-light skin tone
+1F93D 1F3FD 200D 2640 FE0F                 ; fully-qualified     # 🤽🏽‍♀️ woman playing water polo: medium skin tone
+1F93D 1F3FD 200D 2640                      ; non-fully-qualified # 🤽🏽‍♀ woman playing water polo: medium skin tone
+1F93D 1F3FE 200D 2640 FE0F                 ; fully-qualified     # 🤽🏾‍♀️ woman playing water polo: medium-dark skin tone
+1F93D 1F3FE 200D 2640                      ; non-fully-qualified # 🤽🏾‍♀ woman playing water polo: medium-dark skin tone
+1F93D 1F3FF 200D 2640 FE0F                 ; fully-qualified     # 🤽🏿‍♀️ woman playing water polo: dark skin tone
+1F93D 1F3FF 200D 2640                      ; non-fully-qualified # 🤽🏿‍♀ woman playing water polo: dark skin tone
+1F93E                                      ; fully-qualified     # 🤾 person playing handball
+1F93E 1F3FB                                ; fully-qualified     # 🤾🏻 person playing handball: light skin tone
+1F93E 1F3FC                                ; fully-qualified     # 🤾🏼 person playing handball: medium-light skin tone
+1F93E 1F3FD                                ; fully-qualified     # 🤾🏽 person playing handball: medium skin tone
+1F93E 1F3FE                                ; fully-qualified     # 🤾🏾 person playing handball: medium-dark skin tone
+1F93E 1F3FF                                ; fully-qualified     # 🤾🏿 person playing handball: dark skin tone
+1F93E 200D 2642 FE0F                       ; fully-qualified     # 🤾‍♂️ man playing handball
+1F93E 200D 2642                            ; non-fully-qualified # 🤾‍♂ man playing handball
+1F93E 1F3FB 200D 2642 FE0F                 ; fully-qualified     # 🤾🏻‍♂️ man playing handball: light skin tone
+1F93E 1F3FB 200D 2642                      ; non-fully-qualified # 🤾🏻‍♂ man playing handball: light skin tone
+1F93E 1F3FC 200D 2642 FE0F                 ; fully-qualified     # 🤾🏼‍♂️ man playing handball: medium-light skin tone
+1F93E 1F3FC 200D 2642                      ; non-fully-qualified # 🤾🏼‍♂ man playing handball: medium-light skin tone
+1F93E 1F3FD 200D 2642 FE0F                 ; fully-qualified     # 🤾🏽‍♂️ man playing handball: medium skin tone
+1F93E 1F3FD 200D 2642                      ; non-fully-qualified # 🤾🏽‍♂ man playing handball: medium skin tone
+1F93E 1F3FE 200D 2642 FE0F                 ; fully-qualified     # 🤾🏾‍♂️ man playing handball: medium-dark skin tone
+1F93E 1F3FE 200D 2642                      ; non-fully-qualified # 🤾🏾‍♂ man playing handball: medium-dark skin tone
+1F93E 1F3FF 200D 2642 FE0F                 ; fully-qualified     # 🤾🏿‍♂️ man playing handball: dark skin tone
+1F93E 1F3FF 200D 2642                      ; non-fully-qualified # 🤾🏿‍♂ man playing handball: dark skin tone
+1F93E 200D 2640 FE0F                       ; fully-qualified     # 🤾‍♀️ woman playing handball
+1F93E 200D 2640                            ; non-fully-qualified # 🤾‍♀ woman playing handball
+1F93E 1F3FB 200D 2640 FE0F                 ; fully-qualified     # 🤾🏻‍♀️ woman playing handball: light skin tone
+1F93E 1F3FB 200D 2640                      ; non-fully-qualified # 🤾🏻‍♀ woman playing handball: light skin tone
+1F93E 1F3FC 200D 2640 FE0F                 ; fully-qualified     # 🤾🏼‍♀️ woman playing handball: medium-light skin tone
+1F93E 1F3FC 200D 2640                      ; non-fully-qualified # 🤾🏼‍♀ woman playing handball: medium-light skin tone
+1F93E 1F3FD 200D 2640 FE0F                 ; fully-qualified     # 🤾🏽‍♀️ woman playing handball: medium skin tone
+1F93E 1F3FD 200D 2640                      ; non-fully-qualified # 🤾🏽‍♀ woman playing handball: medium skin tone
+1F93E 1F3FE 200D 2640 FE0F                 ; fully-qualified     # 🤾🏾‍♀️ woman playing handball: medium-dark skin tone
+1F93E 1F3FE 200D 2640                      ; non-fully-qualified # 🤾🏾‍♀ woman playing handball: medium-dark skin tone
+1F93E 1F3FF 200D 2640 FE0F                 ; fully-qualified     # 🤾🏿‍♀️ woman playing handball: dark skin tone
+1F93E 1F3FF 200D 2640                      ; non-fully-qualified # 🤾🏿‍♀ woman playing handball: dark skin tone
+1F939                                      ; fully-qualified     # 🤹 person juggling
+1F939 1F3FB                                ; fully-qualified     # 🤹🏻 person juggling: light skin tone
+1F939 1F3FC                                ; fully-qualified     # 🤹🏼 person juggling: medium-light skin tone
+1F939 1F3FD                                ; fully-qualified     # 🤹🏽 person juggling: medium skin tone
+1F939 1F3FE                                ; fully-qualified     # 🤹🏾 person juggling: medium-dark skin tone
+1F939 1F3FF                                ; fully-qualified     # 🤹🏿 person juggling: dark skin tone
+1F939 200D 2642 FE0F                       ; fully-qualified     # 🤹‍♂️ man juggling
+1F939 200D 2642                            ; non-fully-qualified # 🤹‍♂ man juggling
+1F939 1F3FB 200D 2642 FE0F                 ; fully-qualified     # 🤹🏻‍♂️ man juggling: light skin tone
+1F939 1F3FB 200D 2642                      ; non-fully-qualified # 🤹🏻‍♂ man juggling: light skin tone
+1F939 1F3FC 200D 2642 FE0F                 ; fully-qualified     # 🤹🏼‍♂️ man juggling: medium-light skin tone
+1F939 1F3FC 200D 2642                      ; non-fully-qualified # 🤹🏼‍♂ man juggling: medium-light skin tone
+1F939 1F3FD 200D 2642 FE0F                 ; fully-qualified     # 🤹🏽‍♂️ man juggling: medium skin tone
+1F939 1F3FD 200D 2642                      ; non-fully-qualified # 🤹🏽‍♂ man juggling: medium skin tone
+1F939 1F3FE 200D 2642 FE0F                 ; fully-qualified     # 🤹🏾‍♂️ man juggling: medium-dark skin tone
+1F939 1F3FE 200D 2642                      ; non-fully-qualified # 🤹🏾‍♂ man juggling: medium-dark skin tone
+1F939 1F3FF 200D 2642 FE0F                 ; fully-qualified     # 🤹🏿‍♂️ man juggling: dark skin tone
+1F939 1F3FF 200D 2642                      ; non-fully-qualified # 🤹🏿‍♂ man juggling: dark skin tone
+1F939 200D 2640 FE0F                       ; fully-qualified     # 🤹‍♀️ woman juggling
+1F939 200D 2640                            ; non-fully-qualified # 🤹‍♀ woman juggling
+1F939 1F3FB 200D 2640 FE0F                 ; fully-qualified     # 🤹🏻‍♀️ woman juggling: light skin tone
+1F939 1F3FB 200D 2640                      ; non-fully-qualified # 🤹🏻‍♀ woman juggling: light skin tone
+1F939 1F3FC 200D 2640 FE0F                 ; fully-qualified     # 🤹🏼‍♀️ woman juggling: medium-light skin tone
+1F939 1F3FC 200D 2640                      ; non-fully-qualified # 🤹🏼‍♀ woman juggling: medium-light skin tone
+1F939 1F3FD 200D 2640 FE0F                 ; fully-qualified     # 🤹🏽‍♀️ woman juggling: medium skin tone
+1F939 1F3FD 200D 2640                      ; non-fully-qualified # 🤹🏽‍♀ woman juggling: medium skin tone
+1F939 1F3FE 200D 2640 FE0F                 ; fully-qualified     # 🤹🏾‍♀️ woman juggling: medium-dark skin tone
+1F939 1F3FE 200D 2640                      ; non-fully-qualified # 🤹🏾‍♀ woman juggling: medium-dark skin tone
+1F939 1F3FF 200D 2640 FE0F                 ; fully-qualified     # 🤹🏿‍♀️ woman juggling: dark skin tone
+1F939 1F3FF 200D 2640                      ; non-fully-qualified # 🤹🏿‍♀ woman juggling: dark skin tone
+
+# subgroup: family
+1F46B                                      ; fully-qualified     # 👫 man and woman holding hands
+1F46C                                      ; fully-qualified     # 👬 two men holding hands
+1F46D                                      ; fully-qualified     # 👭 two women holding hands
+1F48F                                      ; fully-qualified     # 💏 kiss
+1F469 200D 2764 FE0F 200D 1F48B 200D 1F468 ; fully-qualified     # 👩‍❤️‍💋‍👨 kiss: woman, man
+1F469 200D 2764 200D 1F48B 200D 1F468      ; non-fully-qualified # 👩‍❤‍💋‍👨 kiss: woman, man
+1F468 200D 2764 FE0F 200D 1F48B 200D 1F468 ; fully-qualified     # 👨‍❤️‍💋‍👨 kiss: man, man
+1F468 200D 2764 200D 1F48B 200D 1F468      ; non-fully-qualified # 👨‍❤‍💋‍👨 kiss: man, man
+1F469 200D 2764 FE0F 200D 1F48B 200D 1F469 ; fully-qualified     # 👩‍❤️‍💋‍👩 kiss: woman, woman
+1F469 200D 2764 200D 1F48B 200D 1F469      ; non-fully-qualified # 👩‍❤‍💋‍👩 kiss: woman, woman
+1F491                                      ; fully-qualified     # 💑 couple with heart
+1F469 200D 2764 FE0F 200D 1F468            ; fully-qualified     # 👩‍❤️‍👨 couple with heart: woman, man
+1F469 200D 2764 200D 1F468                 ; non-fully-qualified # 👩‍❤‍👨 couple with heart: woman, man
+1F468 200D 2764 FE0F 200D 1F468            ; fully-qualified     # 👨‍❤️‍👨 couple with heart: man, man
+1F468 200D 2764 200D 1F468                 ; non-fully-qualified # 👨‍❤‍👨 couple with heart: man, man
+1F469 200D 2764 FE0F 200D 1F469            ; fully-qualified     # 👩‍❤️‍👩 couple with heart: woman, woman
+1F469 200D 2764 200D 1F469                 ; non-fully-qualified # 👩‍❤‍👩 couple with heart: woman, woman
+1F46A                                      ; fully-qualified     # 👪 family
+1F468 200D 1F469 200D 1F466                ; fully-qualified     # 👨‍👩‍👦 family: man, woman, boy
+1F468 200D 1F469 200D 1F467                ; fully-qualified     # 👨‍👩‍👧 family: man, woman, girl
+1F468 200D 1F469 200D 1F467 200D 1F466     ; fully-qualified     # 👨‍👩‍👧‍👦 family: man, woman, girl, boy
+1F468 200D 1F469 200D 1F466 200D 1F466     ; fully-qualified     # 👨‍👩‍👦‍👦 family: man, woman, boy, boy
+1F468 200D 1F469 200D 1F467 200D 1F467     ; fully-qualified     # 👨‍👩‍👧‍👧 family: man, woman, girl, girl
+1F468 200D 1F468 200D 1F466                ; fully-qualified     # 👨‍👨‍👦 family: man, man, boy
+1F468 200D 1F468 200D 1F467                ; fully-qualified     # 👨‍👨‍👧 family: man, man, girl
+1F468 200D 1F468 200D 1F467 200D 1F466     ; fully-qualified     # 👨‍👨‍👧‍👦 family: man, man, girl, boy
+1F468 200D 1F468 200D 1F466 200D 1F466     ; fully-qualified     # 👨‍👨‍👦‍👦 family: man, man, boy, boy
+1F468 200D 1F468 200D 1F467 200D 1F467     ; fully-qualified     # 👨‍👨‍👧‍👧 family: man, man, girl, girl
+1F469 200D 1F469 200D 1F466                ; fully-qualified     # 👩‍👩‍👦 family: woman, woman, boy
+1F469 200D 1F469 200D 1F467                ; fully-qualified     # 👩‍👩‍👧 family: woman, woman, girl
+1F469 200D 1F469 200D 1F467 200D 1F466     ; fully-qualified     # 👩‍👩‍👧‍👦 family: woman, woman, girl, boy
+1F469 200D 1F469 200D 1F466 200D 1F466     ; fully-qualified     # 👩‍👩‍👦‍👦 family: woman, woman, boy, boy
+1F469 200D 1F469 200D 1F467 200D 1F467     ; fully-qualified     # 👩‍👩‍👧‍👧 family: woman, woman, girl, girl
+1F468 200D 1F466                           ; fully-qualified     # 👨‍👦 family: man, boy
+1F468 200D 1F466 200D 1F466                ; fully-qualified     # 👨‍👦‍👦 family: man, boy, boy
+1F468 200D 1F467                           ; fully-qualified     # 👨‍👧 family: man, girl
+1F468 200D 1F467 200D 1F466                ; fully-qualified     # 👨‍👧‍👦 family: man, girl, boy
+1F468 200D 1F467 200D 1F467                ; fully-qualified     # 👨‍👧‍👧 family: man, girl, girl
+1F469 200D 1F466                           ; fully-qualified     # 👩‍👦 family: woman, boy
+1F469 200D 1F466 200D 1F466                ; fully-qualified     # 👩‍👦‍👦 family: woman, boy, boy
+1F469 200D 1F467                           ; fully-qualified     # 👩‍👧 family: woman, girl
+1F469 200D 1F467 200D 1F466                ; fully-qualified     # 👩‍👧‍👦 family: woman, girl, boy
+1F469 200D 1F467 200D 1F467                ; fully-qualified     # 👩‍👧‍👧 family: woman, girl, girl
+
+# subgroup: body
+1F4AA                                      ; fully-qualified     # 💪 flexed biceps
+1F4AA 1F3FB                                ; fully-qualified     # 💪🏻 flexed biceps: light skin tone
+1F4AA 1F3FC                                ; fully-qualified     # 💪🏼 flexed biceps: medium-light skin tone
+1F4AA 1F3FD                                ; fully-qualified     # 💪🏽 flexed biceps: medium skin tone
+1F4AA 1F3FE                                ; fully-qualified     # 💪🏾 flexed biceps: medium-dark skin tone
+1F4AA 1F3FF                                ; fully-qualified     # 💪🏿 flexed biceps: dark skin tone
+1F933                                      ; fully-qualified     # 🤳 selfie
+1F933 1F3FB                                ; fully-qualified     # 🤳🏻 selfie: light skin tone
+1F933 1F3FC                                ; fully-qualified     # 🤳🏼 selfie: medium-light skin tone
+1F933 1F3FD                                ; fully-qualified     # 🤳🏽 selfie: medium skin tone
+1F933 1F3FE                                ; fully-qualified     # 🤳🏾 selfie: medium-dark skin tone
+1F933 1F3FF                                ; fully-qualified     # 🤳🏿 selfie: dark skin tone
+1F448                                      ; fully-qualified     # 👈 backhand index pointing left
+1F448 1F3FB                                ; fully-qualified     # 👈🏻 backhand index pointing left: light skin tone
+1F448 1F3FC                                ; fully-qualified     # 👈🏼 backhand index pointing left: medium-light skin tone
+1F448 1F3FD                                ; fully-qualified     # 👈🏽 backhand index pointing left: medium skin tone
+1F448 1F3FE                                ; fully-qualified     # 👈🏾 backhand index pointing left: medium-dark skin tone
+1F448 1F3FF                                ; fully-qualified     # 👈🏿 backhand index pointing left: dark skin tone
+1F449                                      ; fully-qualified     # 👉 backhand index pointing right
+1F449 1F3FB                                ; fully-qualified     # 👉🏻 backhand index pointing right: light skin tone
+1F449 1F3FC                                ; fully-qualified     # 👉🏼 backhand index pointing right: medium-light skin tone
+1F449 1F3FD                                ; fully-qualified     # 👉🏽 backhand index pointing right: medium skin tone
+1F449 1F3FE                                ; fully-qualified     # 👉🏾 backhand index pointing right: medium-dark skin tone
+1F449 1F3FF                                ; fully-qualified     # 👉🏿 backhand index pointing right: dark skin tone
+261D FE0F                                  ; fully-qualified     # ☝️ index pointing up
+261D 1F3FB                                 ; fully-qualified     # ☝🏻 index pointing up: light skin tone
+261D 1F3FC                                 ; fully-qualified     # ☝🏼 index pointing up: medium-light skin tone
+261D 1F3FD                                 ; fully-qualified     # ☝🏽 index pointing up: medium skin tone
+261D 1F3FE                                 ; fully-qualified     # ☝🏾 index pointing up: medium-dark skin tone
+261D 1F3FF                                 ; fully-qualified     # ☝🏿 index pointing up: dark skin tone
+1F446                                      ; fully-qualified     # 👆 backhand index pointing up
+1F446 1F3FB                                ; fully-qualified     # 👆🏻 backhand index pointing up: light skin tone
+1F446 1F3FC                                ; fully-qualified     # 👆🏼 backhand index pointing up: medium-light skin tone
+1F446 1F3FD                                ; fully-qualified     # 👆🏽 backhand index pointing up: medium skin tone
+1F446 1F3FE                                ; fully-qualified     # 👆🏾 backhand index pointing up: medium-dark skin tone
+1F446 1F3FF                                ; fully-qualified     # 👆🏿 backhand index pointing up: dark skin tone
+1F595                                      ; fully-qualified     # 🖕 middle finger
+1F595 1F3FB                                ; fully-qualified     # 🖕🏻 middle finger: light skin tone
+1F595 1F3FC                                ; fully-qualified     # 🖕🏼 middle finger: medium-light skin tone
+1F595 1F3FD                                ; fully-qualified     # 🖕🏽 middle finger: medium skin tone
+1F595 1F3FE                                ; fully-qualified     # 🖕🏾 middle finger: medium-dark skin tone
+1F595 1F3FF                                ; fully-qualified     # 🖕🏿 middle finger: dark skin tone
+1F447                                      ; fully-qualified     # 👇 backhand index pointing down
+1F447 1F3FB                                ; fully-qualified     # 👇🏻 backhand index pointing down: light skin tone
+1F447 1F3FC                                ; fully-qualified     # 👇🏼 backhand index pointing down: medium-light skin tone
+1F447 1F3FD                                ; fully-qualified     # 👇🏽 backhand index pointing down: medium skin tone
+1F447 1F3FE                                ; fully-qualified     # 👇🏾 backhand index pointing down: medium-dark skin tone
+1F447 1F3FF                                ; fully-qualified     # 👇🏿 backhand index pointing down: dark skin tone
+270C FE0F                                  ; fully-qualified     # ✌️ victory hand
+270C 1F3FB                                 ; fully-qualified     # ✌🏻 victory hand: light skin tone
+270C 1F3FC                                 ; fully-qualified     # ✌🏼 victory hand: medium-light skin tone
+270C 1F3FD                                 ; fully-qualified     # ✌🏽 victory hand: medium skin tone
+270C 1F3FE                                 ; fully-qualified     # ✌🏾 victory hand: medium-dark skin tone
+270C 1F3FF                                 ; fully-qualified     # ✌🏿 victory hand: dark skin tone
+1F91E                                      ; fully-qualified     # 🤞 crossed fingers
+1F91E 1F3FB                                ; fully-qualified     # 🤞🏻 crossed fingers: light skin tone
+1F91E 1F3FC                                ; fully-qualified     # 🤞🏼 crossed fingers: medium-light skin tone
+1F91E 1F3FD                                ; fully-qualified     # 🤞🏽 crossed fingers: medium skin tone
+1F91E 1F3FE                                ; fully-qualified     # 🤞🏾 crossed fingers: medium-dark skin tone
+1F91E 1F3FF                                ; fully-qualified     # 🤞🏿 crossed fingers: dark skin tone
+1F596                                      ; fully-qualified     # 🖖 vulcan salute
+1F596 1F3FB                                ; fully-qualified     # 🖖🏻 vulcan salute: light skin tone
+1F596 1F3FC                                ; fully-qualified     # 🖖🏼 vulcan salute: medium-light skin tone
+1F596 1F3FD                                ; fully-qualified     # 🖖🏽 vulcan salute: medium skin tone
+1F596 1F3FE                                ; fully-qualified     # 🖖🏾 vulcan salute: medium-dark skin tone
+1F596 1F3FF                                ; fully-qualified     # 🖖🏿 vulcan salute: dark skin tone
+1F918                                      ; fully-qualified     # 🤘 sign of the horns
+1F918 1F3FB                                ; fully-qualified     # 🤘🏻 sign of the horns: light skin tone
+1F918 1F3FC                                ; fully-qualified     # 🤘🏼 sign of the horns: medium-light skin tone
+1F918 1F3FD                                ; fully-qualified     # 🤘🏽 sign of the horns: medium skin tone
+1F918 1F3FE                                ; fully-qualified     # 🤘🏾 sign of the horns: medium-dark skin tone
+1F918 1F3FF                                ; fully-qualified     # 🤘🏿 sign of the horns: dark skin tone
+1F919                                      ; fully-qualified     # 🤙 call me hand
+1F919 1F3FB                                ; fully-qualified     # 🤙🏻 call me hand: light skin tone
+1F919 1F3FC                                ; fully-qualified     # 🤙🏼 call me hand: medium-light skin tone
+1F919 1F3FD                                ; fully-qualified     # 🤙🏽 call me hand: medium skin tone
+1F919 1F3FE                                ; fully-qualified     # 🤙🏾 call me hand: medium-dark skin tone
+1F919 1F3FF                                ; fully-qualified     # 🤙🏿 call me hand: dark skin tone
+1F590 FE0F                                 ; fully-qualified     # 🖐️ raised hand with fingers splayed
+1F590 1F3FB                                ; fully-qualified     # 🖐🏻 raised hand with fingers splayed: light skin tone
+1F590 1F3FC                                ; fully-qualified     # 🖐🏼 raised hand with fingers splayed: medium-light skin tone
+1F590 1F3FD                                ; fully-qualified     # 🖐🏽 raised hand with fingers splayed: medium skin tone
+1F590 1F3FE                                ; fully-qualified     # 🖐🏾 raised hand with fingers splayed: medium-dark skin tone
+1F590 1F3FF                                ; fully-qualified     # 🖐🏿 raised hand with fingers splayed: dark skin tone
+270B                                       ; fully-qualified     # ✋ raised hand
+270B 1F3FB                                 ; fully-qualified     # ✋🏻 raised hand: light skin tone
+270B 1F3FC                                 ; fully-qualified     # ✋🏼 raised hand: medium-light skin tone
+270B 1F3FD                                 ; fully-qualified     # ✋🏽 raised hand: medium skin tone
+270B 1F3FE                                 ; fully-qualified     # ✋🏾 raised hand: medium-dark skin tone
+270B 1F3FF                                 ; fully-qualified     # ✋🏿 raised hand: dark skin tone
+1F44C                                      ; fully-qualified     # 👌 OK hand
+1F44C 1F3FB                                ; fully-qualified     # 👌🏻 OK hand: light skin tone
+1F44C 1F3FC                                ; fully-qualified     # 👌🏼 OK hand: medium-light skin tone
+1F44C 1F3FD                                ; fully-qualified     # 👌🏽 OK hand: medium skin tone
+1F44C 1F3FE                                ; fully-qualified     # 👌🏾 OK hand: medium-dark skin tone
+1F44C 1F3FF                                ; fully-qualified     # 👌🏿 OK hand: dark skin tone
+1F44D                                      ; fully-qualified     # 👍 thumbs up
+1F44D 1F3FB                                ; fully-qualified     # 👍🏻 thumbs up: light skin tone
+1F44D 1F3FC                                ; fully-qualified     # 👍🏼 thumbs up: medium-light skin tone
+1F44D 1F3FD                                ; fully-qualified     # 👍🏽 thumbs up: medium skin tone
+1F44D 1F3FE                                ; fully-qualified     # 👍🏾 thumbs up: medium-dark skin tone
+1F44D 1F3FF                                ; fully-qualified     # 👍🏿 thumbs up: dark skin tone
+1F44E                                      ; fully-qualified     # 👎 thumbs down
+1F44E 1F3FB                                ; fully-qualified     # 👎🏻 thumbs down: light skin tone
+1F44E 1F3FC                                ; fully-qualified     # 👎🏼 thumbs down: medium-light skin tone
+1F44E 1F3FD                                ; fully-qualified     # 👎🏽 thumbs down: medium skin tone
+1F44E 1F3FE                                ; fully-qualified     # 👎🏾 thumbs down: medium-dark skin tone
+1F44E 1F3FF                                ; fully-qualified     # 👎🏿 thumbs down: dark skin tone
+270A                                       ; fully-qualified     # ✊ raised fist
+270A 1F3FB                                 ; fully-qualified     # ✊🏻 raised fist: light skin tone
+270A 1F3FC                                 ; fully-qualified     # ✊🏼 raised fist: medium-light skin tone
+270A 1F3FD                                 ; fully-qualified     # ✊🏽 raised fist: medium skin tone
+270A 1F3FE                                 ; fully-qualified     # ✊🏾 raised fist: medium-dark skin tone
+270A 1F3FF                                 ; fully-qualified     # ✊🏿 raised fist: dark skin tone
+1F44A                                      ; fully-qualified     # 👊 oncoming fist
+1F44A 1F3FB                                ; fully-qualified     # 👊🏻 oncoming fist: light skin tone
+1F44A 1F3FC                                ; fully-qualified     # 👊🏼 oncoming fist: medium-light skin tone
+1F44A 1F3FD                                ; fully-qualified     # 👊🏽 oncoming fist: medium skin tone
+1F44A 1F3FE                                ; fully-qualified     # 👊🏾 oncoming fist: medium-dark skin tone
+1F44A 1F3FF                                ; fully-qualified     # 👊🏿 oncoming fist: dark skin tone
+1F91B                                      ; fully-qualified     # 🤛 left-facing fist
+1F91B 1F3FB                                ; fully-qualified     # 🤛🏻 left-facing fist: light skin tone
+1F91B 1F3FC                                ; fully-qualified     # 🤛🏼 left-facing fist: medium-light skin tone
+1F91B 1F3FD                                ; fully-qualified     # 🤛🏽 left-facing fist: medium skin tone
+1F91B 1F3FE                                ; fully-qualified     # 🤛🏾 left-facing fist: medium-dark skin tone
+1F91B 1F3FF                                ; fully-qualified     # 🤛🏿 left-facing fist: dark skin tone
+1F91C                                      ; fully-qualified     # 🤜 right-facing fist
+1F91C 1F3FB                                ; fully-qualified     # 🤜🏻 right-facing fist: light skin tone
+1F91C 1F3FC                                ; fully-qualified     # 🤜🏼 right-facing fist: medium-light skin tone
+1F91C 1F3FD                                ; fully-qualified     # 🤜🏽 right-facing fist: medium skin tone
+1F91C 1F3FE                                ; fully-qualified     # 🤜🏾 right-facing fist: medium-dark skin tone
+1F91C 1F3FF                                ; fully-qualified     # 🤜🏿 right-facing fist: dark skin tone
+1F91A                                      ; fully-qualified     # 🤚 raised back of hand
+1F91A 1F3FB                                ; fully-qualified     # 🤚🏻 raised back of hand: light skin tone
+1F91A 1F3FC                                ; fully-qualified     # 🤚🏼 raised back of hand: medium-light skin tone
+1F91A 1F3FD                                ; fully-qualified     # 🤚🏽 raised back of hand: medium skin tone
+1F91A 1F3FE                                ; fully-qualified     # 🤚🏾 raised back of hand: medium-dark skin tone
+1F91A 1F3FF                                ; fully-qualified     # 🤚🏿 raised back of hand: dark skin tone
+1F44B                                      ; fully-qualified     # 👋 waving hand
+1F44B 1F3FB                                ; fully-qualified     # 👋🏻 waving hand: light skin tone
+1F44B 1F3FC                                ; fully-qualified     # 👋🏼 waving hand: medium-light skin tone
+1F44B 1F3FD                                ; fully-qualified     # 👋🏽 waving hand: medium skin tone
+1F44B 1F3FE                                ; fully-qualified     # 👋🏾 waving hand: medium-dark skin tone
+1F44B 1F3FF                                ; fully-qualified     # 👋🏿 waving hand: dark skin tone
+1F44F                                      ; fully-qualified     # 👏 clapping hands
+1F44F 1F3FB                                ; fully-qualified     # 👏🏻 clapping hands: light skin tone
+1F44F 1F3FC                                ; fully-qualified     # 👏🏼 clapping hands: medium-light skin tone
+1F44F 1F3FD                                ; fully-qualified     # 👏🏽 clapping hands: medium skin tone
+1F44F 1F3FE                                ; fully-qualified     # 👏🏾 clapping hands: medium-dark skin tone
+1F44F 1F3FF                                ; fully-qualified     # 👏🏿 clapping hands: dark skin tone
+270D FE0F                                  ; fully-qualified     # ✍️ writing hand
+270D 1F3FB                                 ; fully-qualified     # ✍🏻 writing hand: light skin tone
+270D 1F3FC                                 ; fully-qualified     # ✍🏼 writing hand: medium-light skin tone
+270D 1F3FD                                 ; fully-qualified     # ✍🏽 writing hand: medium skin tone
+270D 1F3FE                                 ; fully-qualified     # ✍🏾 writing hand: medium-dark skin tone
+270D 1F3FF                                 ; fully-qualified     # ✍🏿 writing hand: dark skin tone
+1F450                                      ; fully-qualified     # 👐 open hands
+1F450 1F3FB                                ; fully-qualified     # 👐🏻 open hands: light skin tone
+1F450 1F3FC                                ; fully-qualified     # 👐🏼 open hands: medium-light skin tone
+1F450 1F3FD                                ; fully-qualified     # 👐🏽 open hands: medium skin tone
+1F450 1F3FE                                ; fully-qualified     # 👐🏾 open hands: medium-dark skin tone
+1F450 1F3FF                                ; fully-qualified     # 👐🏿 open hands: dark skin tone
+1F64C                                      ; fully-qualified     # 🙌 raising hands
+1F64C 1F3FB                                ; fully-qualified     # 🙌🏻 raising hands: light skin tone
+1F64C 1F3FC                                ; fully-qualified     # 🙌🏼 raising hands: medium-light skin tone
+1F64C 1F3FD                                ; fully-qualified     # 🙌🏽 raising hands: medium skin tone
+1F64C 1F3FE                                ; fully-qualified     # 🙌🏾 raising hands: medium-dark skin tone
+1F64C 1F3FF                                ; fully-qualified     # 🙌🏿 raising hands: dark skin tone
+1F64F                                      ; fully-qualified     # 🙏 folded hands
+1F64F 1F3FB                                ; fully-qualified     # 🙏🏻 folded hands: light skin tone
+1F64F 1F3FC                                ; fully-qualified     # 🙏🏼 folded hands: medium-light skin tone
+1F64F 1F3FD                                ; fully-qualified     # 🙏🏽 folded hands: medium skin tone
+1F64F 1F3FE                                ; fully-qualified     # 🙏🏾 folded hands: medium-dark skin tone
+1F64F 1F3FF                                ; fully-qualified     # 🙏🏿 folded hands: dark skin tone
+1F91D                                      ; fully-qualified     # 🤝 handshake
+1F485                                      ; fully-qualified     # 💅 nail polish
+1F485 1F3FB                                ; fully-qualified     # 💅🏻 nail polish: light skin tone
+1F485 1F3FC                                ; fully-qualified     # 💅🏼 nail polish: medium-light skin tone
+1F485 1F3FD                                ; fully-qualified     # 💅🏽 nail polish: medium skin tone
+1F485 1F3FE                                ; fully-qualified     # 💅🏾 nail polish: medium-dark skin tone
+1F485 1F3FF                                ; fully-qualified     # 💅🏿 nail polish: dark skin tone
+1F442                                      ; fully-qualified     # 👂 ear
+1F442 1F3FB                                ; fully-qualified     # 👂🏻 ear: light skin tone
+1F442 1F3FC                                ; fully-qualified     # 👂🏼 ear: medium-light skin tone
+1F442 1F3FD                                ; fully-qualified     # 👂🏽 ear: medium skin tone
+1F442 1F3FE                                ; fully-qualified     # 👂🏾 ear: medium-dark skin tone
+1F442 1F3FF                                ; fully-qualified     # 👂🏿 ear: dark skin tone
+1F443                                      ; fully-qualified     # 👃 nose
+1F443 1F3FB                                ; fully-qualified     # 👃🏻 nose: light skin tone
+1F443 1F3FC                                ; fully-qualified     # 👃🏼 nose: medium-light skin tone
+1F443 1F3FD                                ; fully-qualified     # 👃🏽 nose: medium skin tone
+1F443 1F3FE                                ; fully-qualified     # 👃🏾 nose: medium-dark skin tone
+1F443 1F3FF                                ; fully-qualified     # 👃🏿 nose: dark skin tone
+1F463                                      ; fully-qualified     # 👣 footprints
+1F440                                      ; fully-qualified     # 👀 eyes
+1F441 FE0F                                 ; fully-qualified     # 👁️ eye
+1F441 FE0F 200D 1F5E8 FE0F                 ; fully-qualified     # 👁️‍🗨️ eye in speech bubble
+1F441 200D 1F5E8                           ; non-fully-qualified # 👁‍🗨 eye in speech bubble
+1F441 FE0F 200D 1F5E8                      ; non-fully-qualified # 👁️‍🗨 eye in speech bubble
+1F441 200D 1F5E8 FE0F                      ; non-fully-qualified # 👁‍🗨️ eye in speech bubble
+1F445                                      ; fully-qualified     # 👅 tongue
+1F444                                      ; fully-qualified     # 👄 mouth
+
+# subgroup: emotion
+1F48B                                      ; fully-qualified     # 💋 kiss mark
+1F498                                      ; fully-qualified     # 💘 heart with arrow
+2764 FE0F                                  ; fully-qualified     # ❤️ red heart
+1F493                                      ; fully-qualified     # 💓 beating heart
+1F494                                      ; fully-qualified     # 💔 broken heart
+1F495                                      ; fully-qualified     # 💕 two hearts
+1F496                                      ; fully-qualified     # 💖 sparkling heart
+1F497                                      ; fully-qualified     # 💗 growing heart
+1F499                                      ; fully-qualified     # 💙 blue heart
+1F49A                                      ; fully-qualified     # 💚 green heart
+1F49B                                      ; fully-qualified     # 💛 yellow heart
+1F49C                                      ; fully-qualified     # 💜 purple heart
+1F5A4                                      ; fully-qualified     # 🖤 black heart
+1F49D                                      ; fully-qualified     # 💝 heart with ribbon
+1F49E                                      ; fully-qualified     # 💞 revolving hearts
+1F49F                                      ; fully-qualified     # 💟 heart decoration
+2763 FE0F                                  ; fully-qualified     # ❣️ heavy heart exclamation
+1F48C                                      ; fully-qualified     # 💌 love letter
+1F4A4                                      ; fully-qualified     # 💤 zzz
+1F4A2                                      ; fully-qualified     # 💢 anger symbol
+1F4A3                                      ; fully-qualified     # 💣 bomb
+1F4A5                                      ; fully-qualified     # 💥 collision
+1F4A6                                      ; fully-qualified     # 💦 sweat droplets
+1F4A8                                      ; fully-qualified     # 💨 dashing away
+1F4AB                                      ; fully-qualified     # 💫 dizzy
+1F4AC                                      ; fully-qualified     # 💬 speech balloon
+1F5E8 FE0F                                 ; fully-qualified     # 🗨️ left speech bubble
+1F5EF FE0F                                 ; fully-qualified     # 🗯️ right anger bubble
+1F4AD                                      ; fully-qualified     # 💭 thought balloon
+1F573 FE0F                                 ; fully-qualified     # 🕳️ hole
+
+# subgroup: clothing
+1F453                                      ; fully-qualified     # 👓 glasses
+1F576 FE0F                                 ; fully-qualified     # 🕶️ sunglasses
+1F454                                      ; fully-qualified     # 👔 necktie
+1F455                                      ; fully-qualified     # 👕 t-shirt
+1F456                                      ; fully-qualified     # 👖 jeans
+1F457                                      ; fully-qualified     # 👗 dress
+1F458                                      ; fully-qualified     # 👘 kimono
+1F459                                      ; fully-qualified     # 👙 bikini
+1F45A                                      ; fully-qualified     # 👚 woman’s clothes
+1F45B                                      ; fully-qualified     # 👛 purse
+1F45C                                      ; fully-qualified     # 👜 handbag
+1F45D                                      ; fully-qualified     # 👝 clutch bag
+1F6CD FE0F                                 ; fully-qualified     # 🛍️ shopping bags
+1F392                                      ; fully-qualified     # 🎒 school backpack
+1F45E                                      ; fully-qualified     # 👞 man’s shoe
+1F45F                                      ; fully-qualified     # 👟 running shoe
+1F460                                      ; fully-qualified     # 👠 high-heeled shoe
+1F461                                      ; fully-qualified     # 👡 woman’s sandal
+1F462                                      ; fully-qualified     # 👢 woman’s boot
+1F451                                      ; fully-qualified     # 👑 crown
+1F452                                      ; fully-qualified     # 👒 woman’s hat
+1F3A9                                      ; fully-qualified     # 🎩 top hat
+1F393                                      ; fully-qualified     # 🎓 graduation cap
+26D1 FE0F                                  ; fully-qualified     # ⛑️ rescue worker’s helmet
+1F4FF                                      ; fully-qualified     # 📿 prayer beads
+1F484                                      ; fully-qualified     # 💄 lipstick
+1F48D                                      ; fully-qualified     # 💍 ring
+1F48E                                      ; fully-qualified     # 💎 gem stone
+
+# Smileys & People subtotal:		1281
+# Smileys & People subtotal:		391	w/o modifiers
+
+# group: Animals & Nature
+
+# subgroup: animal-mammal
+1F435                                      ; fully-qualified     # 🐵 monkey face
+1F412                                      ; fully-qualified     # 🐒 monkey
+1F98D                                      ; fully-qualified     # 🦍 gorilla
+1F436                                      ; fully-qualified     # 🐶 dog face
+1F415                                      ; fully-qualified     # 🐕 dog
+1F429                                      ; fully-qualified     # 🐩 poodle
+1F43A                                      ; fully-qualified     # 🐺 wolf face
+1F98A                                      ; fully-qualified     # 🦊 fox face
+1F431                                      ; fully-qualified     # 🐱 cat face
+1F408                                      ; fully-qualified     # 🐈 cat
+1F981                                      ; fully-qualified     # 🦁 lion face
+1F42F                                      ; fully-qualified     # 🐯 tiger face
+1F405                                      ; fully-qualified     # 🐅 tiger
+1F406                                      ; fully-qualified     # 🐆 leopard
+1F434                                      ; fully-qualified     # 🐴 horse face
+1F40E                                      ; fully-qualified     # 🐎 horse
+1F98C                                      ; fully-qualified     # 🦌 deer
+1F984                                      ; fully-qualified     # 🦄 unicorn face
+1F42E                                      ; fully-qualified     # 🐮 cow face
+1F402                                      ; fully-qualified     # 🐂 ox
+1F403                                      ; fully-qualified     # 🐃 water buffalo
+1F404                                      ; fully-qualified     # 🐄 cow
+1F437                                      ; fully-qualified     # 🐷 pig face
+1F416                                      ; fully-qualified     # 🐖 pig
+1F417                                      ; fully-qualified     # 🐗 boar
+1F43D                                      ; fully-qualified     # 🐽 pig nose
+1F40F                                      ; fully-qualified     # 🐏 ram
+1F411                                      ; fully-qualified     # 🐑 sheep
+1F410                                      ; fully-qualified     # 🐐 goat
+1F42A                                      ; fully-qualified     # 🐪 camel
+1F42B                                      ; fully-qualified     # 🐫 two-hump camel
+1F418                                      ; fully-qualified     # 🐘 elephant
+1F98F                                      ; fully-qualified     # 🦏 rhinoceros
+1F42D                                      ; fully-qualified     # 🐭 mouse face
+1F401                                      ; fully-qualified     # 🐁 mouse
+1F400                                      ; fully-qualified     # 🐀 rat
+1F439                                      ; fully-qualified     # 🐹 hamster face
+1F430                                      ; fully-qualified     # 🐰 rabbit face
+1F407                                      ; fully-qualified     # 🐇 rabbit
+1F43F FE0F                                 ; fully-qualified     # 🐿️ chipmunk
+1F987                                      ; fully-qualified     # 🦇 bat
+1F43B                                      ; fully-qualified     # 🐻 bear face
+1F428                                      ; fully-qualified     # 🐨 koala
+1F43C                                      ; fully-qualified     # 🐼 panda face
+1F43E                                      ; fully-qualified     # 🐾 paw prints
+
+# subgroup: animal-bird
+1F983                                      ; fully-qualified     # 🦃 turkey
+1F414                                      ; fully-qualified     # 🐔 chicken
+1F413                                      ; fully-qualified     # 🐓 rooster
+1F423                                      ; fully-qualified     # 🐣 hatching chick
+1F424                                      ; fully-qualified     # 🐤 baby chick
+1F425                                      ; fully-qualified     # 🐥 front-facing baby chick
+1F426                                      ; fully-qualified     # 🐦 bird
+1F427                                      ; fully-qualified     # 🐧 penguin
+1F54A FE0F                                 ; fully-qualified     # 🕊️ dove
+1F985                                      ; fully-qualified     # 🦅 eagle
+1F986                                      ; fully-qualified     # 🦆 duck
+1F989                                      ; fully-qualified     # 🦉 owl
+
+# subgroup: animal-amphibian
+1F438                                      ; fully-qualified     # 🐸 frog face
+
+# subgroup: animal-reptile
+1F40A                                      ; fully-qualified     # 🐊 crocodile
+1F422                                      ; fully-qualified     # 🐢 turtle
+1F98E                                      ; fully-qualified     # 🦎 lizard
+1F40D                                      ; fully-qualified     # 🐍 snake
+1F432                                      ; fully-qualified     # 🐲 dragon face
+1F409                                      ; fully-qualified     # 🐉 dragon
+
+# subgroup: animal-marine
+1F433                                      ; fully-qualified     # 🐳 spouting whale
+1F40B                                      ; fully-qualified     # 🐋 whale
+1F42C                                      ; fully-qualified     # 🐬 dolphin
+1F41F                                      ; fully-qualified     # 🐟 fish
+1F420                                      ; fully-qualified     # 🐠 tropical fish
+1F421                                      ; fully-qualified     # 🐡 blowfish
+1F988                                      ; fully-qualified     # 🦈 shark
+1F419                                      ; fully-qualified     # 🐙 octopus
+1F41A                                      ; fully-qualified     # 🐚 spiral shell
+1F980                                      ; fully-qualified     # 🦀 crab
+1F990                                      ; fully-qualified     # 🦐 shrimp
+1F991                                      ; fully-qualified     # 🦑 squid
+
+# subgroup: animal-bug
+1F98B                                      ; fully-qualified     # 🦋 butterfly
+1F40C                                      ; fully-qualified     # 🐌 snail
+1F41B                                      ; fully-qualified     # 🐛 bug
+1F41C                                      ; fully-qualified     # 🐜 ant
+1F41D                                      ; fully-qualified     # 🐝 honeybee
+1F41E                                      ; fully-qualified     # 🐞 lady beetle
+1F577 FE0F                                 ; fully-qualified     # 🕷️ spider
+1F578 FE0F                                 ; fully-qualified     # 🕸️ spider web
+1F982                                      ; fully-qualified     # 🦂 scorpion
+
+# subgroup: plant-flower
+1F490                                      ; fully-qualified     # 💐 bouquet
+1F338                                      ; fully-qualified     # 🌸 cherry blossom
+1F4AE                                      ; fully-qualified     # 💮 white flower
+1F3F5 FE0F                                 ; fully-qualified     # 🏵️ rosette
+1F339                                      ; fully-qualified     # 🌹 rose
+1F940                                      ; fully-qualified     # 🥀 wilted flower
+1F33A                                      ; fully-qualified     # 🌺 hibiscus
+1F33B                                      ; fully-qualified     # 🌻 sunflower
+1F33C                                      ; fully-qualified     # 🌼 blossom
+1F337                                      ; fully-qualified     # 🌷 tulip
+
+# subgroup: plant-other
+1F331                                      ; fully-qualified     # 🌱 seedling
+1F332                                      ; fully-qualified     # 🌲 evergreen tree
+1F333                                      ; fully-qualified     # 🌳 deciduous tree
+1F334                                      ; fully-qualified     # 🌴 palm tree
+1F335                                      ; fully-qualified     # 🌵 cactus
+1F33E                                      ; fully-qualified     # 🌾 sheaf of rice
+1F33F                                      ; fully-qualified     # 🌿 herb
+2618 FE0F                                  ; fully-qualified     # ☘️ shamrock
+1F340                                      ; fully-qualified     # 🍀 four leaf clover
+1F341                                      ; fully-qualified     # 🍁 maple leaf
+1F342                                      ; fully-qualified     # 🍂 fallen leaf
+1F343                                      ; fully-qualified     # 🍃 leaf fluttering in wind
+
+# Animals & Nature subtotal:		107
+# Animals & Nature subtotal:		107	w/o modifiers
+
+# group: Food & Drink
+
+# subgroup: food-fruit
+1F347                                      ; fully-qualified     # 🍇 grapes
+1F348                                      ; fully-qualified     # 🍈 melon
+1F349                                      ; fully-qualified     # 🍉 watermelon
+1F34A                                      ; fully-qualified     # 🍊 tangerine
+1F34B                                      ; fully-qualified     # 🍋 lemon
+1F34C                                      ; fully-qualified     # 🍌 banana
+1F34D                                      ; fully-qualified     # 🍍 pineapple
+1F34E                                      ; fully-qualified     # 🍎 red apple
+1F34F                                      ; fully-qualified     # 🍏 green apple
+1F350                                      ; fully-qualified     # 🍐 pear
+1F351                                      ; fully-qualified     # 🍑 peach
+1F352                                      ; fully-qualified     # 🍒 cherries
+1F353                                      ; fully-qualified     # 🍓 strawberry
+1F95D                                      ; fully-qualified     # 🥝 kiwi fruit
+1F345                                      ; fully-qualified     # 🍅 tomato
+
+# subgroup: food-vegetable
+1F951                                      ; fully-qualified     # 🥑 avocado
+1F346                                      ; fully-qualified     # 🍆 eggplant
+1F954                                      ; fully-qualified     # 🥔 potato
+1F955                                      ; fully-qualified     # 🥕 carrot
+1F33D                                      ; fully-qualified     # 🌽 ear of corn
+1F336 FE0F                                 ; fully-qualified     # 🌶️ hot pepper
+1F952                                      ; fully-qualified     # 🥒 cucumber
+1F344                                      ; fully-qualified     # 🍄 mushroom
+1F95C                                      ; fully-qualified     # 🥜 peanuts
+1F330                                      ; fully-qualified     # 🌰 chestnut
+
+# subgroup: food-prepared
+1F35E                                      ; fully-qualified     # 🍞 bread
+1F950                                      ; fully-qualified     # 🥐 croissant
+1F956                                      ; fully-qualified     # 🥖 baguette bread
+1F95E                                      ; fully-qualified     # 🥞 pancakes
+1F9C0                                      ; fully-qualified     # 🧀 cheese wedge
+1F356                                      ; fully-qualified     # 🍖 meat on bone
+1F357                                      ; fully-qualified     # 🍗 poultry leg
+1F953                                      ; fully-qualified     # 🥓 bacon
+1F354                                      ; fully-qualified     # 🍔 hamburger
+1F35F                                      ; fully-qualified     # 🍟 french fries
+1F355                                      ; fully-qualified     # 🍕 pizza
+1F32D                                      ; fully-qualified     # 🌭 hot dog
+1F32E                                      ; fully-qualified     # 🌮 taco
+1F32F                                      ; fully-qualified     # 🌯 burrito
+1F959                                      ; fully-qualified     # 🥙 stuffed flatbread
+1F95A                                      ; fully-qualified     # 🥚 egg
+1F373                                      ; fully-qualified     # 🍳 cooking
+1F958                                      ; fully-qualified     # 🥘 shallow pan of food
+1F372                                      ; fully-qualified     # 🍲 pot of food
+1F957                                      ; fully-qualified     # 🥗 green salad
+1F37F                                      ; fully-qualified     # 🍿 popcorn
+
+# subgroup: food-asian
+1F371                                      ; fully-qualified     # 🍱 bento box
+1F358                                      ; fully-qualified     # 🍘 rice cracker
+1F359                                      ; fully-qualified     # 🍙 rice ball
+1F35A                                      ; fully-qualified     # 🍚 cooked rice
+1F35B                                      ; fully-qualified     # 🍛 curry rice
+1F35C                                      ; fully-qualified     # 🍜 steaming bowl
+1F35D                                      ; fully-qualified     # 🍝 spaghetti
+1F360                                      ; fully-qualified     # 🍠 roasted sweet potato
+1F362                                      ; fully-qualified     # 🍢 oden
+1F363                                      ; fully-qualified     # 🍣 sushi
+1F364                                      ; fully-qualified     # 🍤 fried shrimp
+1F365                                      ; fully-qualified     # 🍥 fish cake with swirl
+1F361                                      ; fully-qualified     # 🍡 dango
+
+# subgroup: food-sweet
+1F366                                      ; fully-qualified     # 🍦 soft ice cream
+1F367                                      ; fully-qualified     # 🍧 shaved ice
+1F368                                      ; fully-qualified     # 🍨 ice cream
+1F369                                      ; fully-qualified     # 🍩 doughnut
+1F36A                                      ; fully-qualified     # 🍪 cookie
+1F382                                      ; fully-qualified     # 🎂 birthday cake
+1F370                                      ; fully-qualified     # 🍰 shortcake
+1F36B                                      ; fully-qualified     # 🍫 chocolate bar
+1F36C                                      ; fully-qualified     # 🍬 candy
+1F36D                                      ; fully-qualified     # 🍭 lollipop
+1F36E                                      ; fully-qualified     # 🍮 custard
+1F36F                                      ; fully-qualified     # 🍯 honey pot
+
+# subgroup: drink
+1F37C                                      ; fully-qualified     # 🍼 baby bottle
+1F95B                                      ; fully-qualified     # 🥛 glass of milk
+2615                                       ; fully-qualified     # ☕ hot beverage
+1F375                                      ; fully-qualified     # 🍵 teacup without handle
+1F376                                      ; fully-qualified     # 🍶 sake
+1F37E                                      ; fully-qualified     # 🍾 bottle with popping cork
+1F377                                      ; fully-qualified     # 🍷 wine glass
+1F378                                      ; fully-qualified     # 🍸 cocktail glass
+1F379                                      ; fully-qualified     # 🍹 tropical drink
+1F37A                                      ; fully-qualified     # 🍺 beer mug
+1F37B                                      ; fully-qualified     # 🍻 clinking beer mugs
+1F942                                      ; fully-qualified     # 🥂 clinking glasses
+1F943                                      ; fully-qualified     # 🥃 tumbler glass
+
+# subgroup: dishware
+1F37D FE0F                                 ; fully-qualified     # 🍽️ fork and knife with plate
+1F374                                      ; fully-qualified     # 🍴 fork and knife
+1F944                                      ; fully-qualified     # 🥄 spoon
+1F52A                                      ; fully-qualified     # 🔪 kitchen knife
+1F3FA                                      ; fully-qualified     # 🏺 amphora
+
+# Food & Drink subtotal:		89
+# Food & Drink subtotal:		89	w/o modifiers
+
+# group: Travel & Places
+
+# subgroup: place-map
+1F30D                                      ; fully-qualified     # 🌍 globe showing Europe-Africa
+1F30E                                      ; fully-qualified     # 🌎 globe showing Americas
+1F30F                                      ; fully-qualified     # 🌏 globe showing Asia-Australia
+1F310                                      ; fully-qualified     # 🌐 globe with meridians
+1F5FA FE0F                                 ; fully-qualified     # 🗺️ world map
+1F5FE                                      ; fully-qualified     # 🗾 map of Japan
+
+# subgroup: place-geographic
+1F3D4 FE0F                                 ; fully-qualified     # 🏔️ snow-capped mountain
+26F0 FE0F                                  ; fully-qualified     # ⛰️ mountain
+1F30B                                      ; fully-qualified     # 🌋 volcano
+1F5FB                                      ; fully-qualified     # 🗻 mount fuji
+1F3D5 FE0F                                 ; fully-qualified     # 🏕️ camping
+1F3D6 FE0F                                 ; fully-qualified     # 🏖️ beach with umbrella
+1F3DC FE0F                                 ; fully-qualified     # 🏜️ desert
+1F3DD FE0F                                 ; fully-qualified     # 🏝️ desert island
+1F3DE FE0F                                 ; fully-qualified     # 🏞️ national park
+
+# subgroup: place-building
+1F3DF FE0F                                 ; fully-qualified     # 🏟️ stadium
+1F3DB FE0F                                 ; fully-qualified     # 🏛️ classical building
+1F3D7 FE0F                                 ; fully-qualified     # 🏗️ building construction
+1F3D8 FE0F                                 ; fully-qualified     # 🏘️ house
+1F3D9 FE0F                                 ; fully-qualified     # 🏙️ cityscape
+1F3DA FE0F                                 ; fully-qualified     # 🏚️ derelict house
+1F3E0                                      ; fully-qualified     # 🏠 house
+1F3E1                                      ; fully-qualified     # 🏡 house with garden
+1F3E2                                      ; fully-qualified     # 🏢 office building
+1F3E3                                      ; fully-qualified     # 🏣 Japanese post office
+1F3E4                                      ; fully-qualified     # 🏤 post office
+1F3E5                                      ; fully-qualified     # 🏥 hospital
+1F3E6                                      ; fully-qualified     # 🏦 bank
+1F3E8                                      ; fully-qualified     # 🏨 hotel
+1F3E9                                      ; fully-qualified     # 🏩 love hotel
+1F3EA                                      ; fully-qualified     # 🏪 convenience store
+1F3EB                                      ; fully-qualified     # 🏫 school
+1F3EC                                      ; fully-qualified     # 🏬 department store
+1F3ED                                      ; fully-qualified     # 🏭 factory
+1F3EF                                      ; fully-qualified     # 🏯 Japanese castle
+1F3F0                                      ; fully-qualified     # 🏰 castle
+1F492                                      ; fully-qualified     # 💒 wedding
+1F5FC                                      ; fully-qualified     # 🗼 Tokyo tower
+1F5FD                                      ; fully-qualified     # 🗽 Statue of Liberty
+
+# subgroup: place-religious
+26EA                                       ; fully-qualified     # ⛪ church
+1F54C                                      ; fully-qualified     # 🕌 mosque
+1F54D                                      ; fully-qualified     # 🕍 synagogue
+26E9 FE0F                                  ; fully-qualified     # ⛩️ shinto shrine
+1F54B                                      ; fully-qualified     # 🕋 kaaba
+
+# subgroup: place-other
+26F2                                       ; fully-qualified     # ⛲ fountain
+26FA                                       ; fully-qualified     # ⛺ tent
+1F301                                      ; fully-qualified     # 🌁 foggy
+1F303                                      ; fully-qualified     # 🌃 night with stars
+1F304                                      ; fully-qualified     # 🌄 sunrise over mountains
+1F305                                      ; fully-qualified     # 🌅 sunrise
+1F306                                      ; fully-qualified     # 🌆 cityscape at dusk
+1F307                                      ; fully-qualified     # 🌇 sunset
+1F309                                      ; fully-qualified     # 🌉 bridge at night
+2668 FE0F                                  ; fully-qualified     # ♨️ hot springs
+1F30C                                      ; fully-qualified     # 🌌 milky way
+1F3A0                                      ; fully-qualified     # 🎠 carousel horse
+1F3A1                                      ; fully-qualified     # 🎡 ferris wheel
+1F3A2                                      ; fully-qualified     # 🎢 roller coaster
+1F488                                      ; fully-qualified     # 💈 barber pole
+1F3AA                                      ; fully-qualified     # 🎪 circus tent
+1F3AD                                      ; fully-qualified     # 🎭 performing arts
+1F5BC FE0F                                 ; fully-qualified     # 🖼️ framed picture
+1F3A8                                      ; fully-qualified     # 🎨 artist palette
+1F3B0                                      ; fully-qualified     # 🎰 slot machine
+
+# subgroup: transport-ground
+1F682                                      ; fully-qualified     # 🚂 locomotive
+1F683                                      ; fully-qualified     # 🚃 railway car
+1F684                                      ; fully-qualified     # 🚄 high-speed train
+1F685                                      ; fully-qualified     # 🚅 high-speed train with bullet nose
+1F686                                      ; fully-qualified     # 🚆 train
+1F687                                      ; fully-qualified     # 🚇 metro
+1F688                                      ; fully-qualified     # 🚈 light rail
+1F689                                      ; fully-qualified     # 🚉 station
+1F68A                                      ; fully-qualified     # 🚊 tram
+1F69D                                      ; fully-qualified     # 🚝 monorail
+1F69E                                      ; fully-qualified     # 🚞 mountain railway
+1F68B                                      ; fully-qualified     # 🚋 tram car
+1F68C                                      ; fully-qualified     # 🚌 bus
+1F68D                                      ; fully-qualified     # 🚍 oncoming bus
+1F68E                                      ; fully-qualified     # 🚎 trolleybus
+1F690                                      ; fully-qualified     # 🚐 minibus
+1F691                                      ; fully-qualified     # 🚑 ambulance
+1F692                                      ; fully-qualified     # 🚒 fire engine
+1F693                                      ; fully-qualified     # 🚓 police car
+1F694                                      ; fully-qualified     # 🚔 oncoming police car
+1F695                                      ; fully-qualified     # 🚕 taxi
+1F696                                      ; fully-qualified     # 🚖 oncoming taxi
+1F697                                      ; fully-qualified     # 🚗 automobile
+1F698                                      ; fully-qualified     # 🚘 oncoming automobile
+1F699                                      ; fully-qualified     # 🚙 sport utility vehicle
+1F69A                                      ; fully-qualified     # 🚚 delivery truck
+1F69B                                      ; fully-qualified     # 🚛 articulated lorry
+1F69C                                      ; fully-qualified     # 🚜 tractor
+1F6B2                                      ; fully-qualified     # 🚲 bicycle
+1F6F4                                      ; fully-qualified     # 🛴 kick scooter
+1F6F5                                      ; fully-qualified     # 🛵 motor scooter
+1F68F                                      ; fully-qualified     # 🚏 bus stop
+1F6E3 FE0F                                 ; fully-qualified     # 🛣️ motorway
+1F6E4 FE0F                                 ; fully-qualified     # 🛤️ railway track
+26FD                                       ; fully-qualified     # ⛽ fuel pump
+1F6A8                                      ; fully-qualified     # 🚨 police car light
+1F6A5                                      ; fully-qualified     # 🚥 horizontal traffic light
+1F6A6                                      ; fully-qualified     # 🚦 vertical traffic light
+1F6A7                                      ; fully-qualified     # 🚧 construction
+1F6D1                                      ; fully-qualified     # 🛑 stop sign
+
+# subgroup: transport-water
+2693                                       ; fully-qualified     # ⚓ anchor
+26F5                                       ; fully-qualified     # ⛵ sailboat
+1F6F6                                      ; fully-qualified     # 🛶 canoe
+1F6A4                                      ; fully-qualified     # 🚤 speedboat
+1F6F3 FE0F                                 ; fully-qualified     # 🛳️ passenger ship
+26F4 FE0F                                  ; fully-qualified     # ⛴️ ferry
+1F6E5 FE0F                                 ; fully-qualified     # 🛥️ motor boat
+1F6A2                                      ; fully-qualified     # 🚢 ship
+
+# subgroup: transport-air
+2708 FE0F                                  ; fully-qualified     # ✈️ airplane
+1F6E9 FE0F                                 ; fully-qualified     # 🛩️ small airplane
+1F6EB                                      ; fully-qualified     # 🛫 airplane departure
+1F6EC                                      ; fully-qualified     # 🛬 airplane arrival
+1F4BA                                      ; fully-qualified     # 💺 seat
+1F681                                      ; fully-qualified     # 🚁 helicopter
+1F69F                                      ; fully-qualified     # 🚟 suspension railway
+1F6A0                                      ; fully-qualified     # 🚠 mountain cableway
+1F6A1                                      ; fully-qualified     # 🚡 aerial tramway
+1F680                                      ; fully-qualified     # 🚀 rocket
+1F6F0 FE0F                                 ; fully-qualified     # 🛰️ satellite
+
+# subgroup: hotel
+1F6CE FE0F                                 ; fully-qualified     # 🛎️ bellhop bell
+1F6AA                                      ; fully-qualified     # 🚪 door
+1F6CC                                      ; fully-qualified     # 🛌 person in bed
+1F6CC 1F3FB                                ; fully-qualified     # 🛌🏻 person in bed: light skin tone
+1F6CC 1F3FC                                ; fully-qualified     # 🛌🏼 person in bed: medium-light skin tone
+1F6CC 1F3FD                                ; fully-qualified     # 🛌🏽 person in bed: medium skin tone
+1F6CC 1F3FE                                ; fully-qualified     # 🛌🏾 person in bed: medium-dark skin tone
+1F6CC 1F3FF                                ; fully-qualified     # 🛌🏿 person in bed: dark skin tone
+1F6CF FE0F                                 ; fully-qualified     # 🛏️ bed
+1F6CB FE0F                                 ; fully-qualified     # 🛋️ couch and lamp
+1F6BD                                      ; fully-qualified     # 🚽 toilet
+1F6BF                                      ; fully-qualified     # 🚿 shower
+1F6C0                                      ; fully-qualified     # 🛀 person taking bath
+1F6C0 1F3FB                                ; fully-qualified     # 🛀🏻 person taking bath: light skin tone
+1F6C0 1F3FC                                ; fully-qualified     # 🛀🏼 person taking bath: medium-light skin tone
+1F6C0 1F3FD                                ; fully-qualified     # 🛀🏽 person taking bath: medium skin tone
+1F6C0 1F3FE                                ; fully-qualified     # 🛀🏾 person taking bath: medium-dark skin tone
+1F6C0 1F3FF                                ; fully-qualified     # 🛀🏿 person taking bath: dark skin tone
+1F6C1                                      ; fully-qualified     # 🛁 bathtub
+
+# subgroup: time
+231B                                       ; fully-qualified     # ⌛ hourglass
+23F3                                       ; fully-qualified     # ⏳ hourglass with flowing sand
+231A                                       ; fully-qualified     # ⌚ watch
+23F0                                       ; fully-qualified     # ⏰ alarm clock
+23F1 FE0F                                  ; fully-qualified     # ⏱️ stopwatch
+23F2 FE0F                                  ; fully-qualified     # ⏲️ timer clock
+1F570 FE0F                                 ; fully-qualified     # 🕰️ mantelpiece clock
+1F55B                                      ; fully-qualified     # 🕛 twelve o’clock
+1F567                                      ; fully-qualified     # 🕧 twelve-thirty
+1F550                                      ; fully-qualified     # 🕐 one o’clock
+1F55C                                      ; fully-qualified     # 🕜 one-thirty
+1F551                                      ; fully-qualified     # 🕑 two o’clock
+1F55D                                      ; fully-qualified     # 🕝 two-thirty
+1F552                                      ; fully-qualified     # 🕒 three o’clock
+1F55E                                      ; fully-qualified     # 🕞 three-thirty
+1F553                                      ; fully-qualified     # 🕓 four o’clock
+1F55F                                      ; fully-qualified     # 🕟 four-thirty
+1F554                                      ; fully-qualified     # 🕔 five o’clock
+1F560                                      ; fully-qualified     # 🕠 five-thirty
+1F555                                      ; fully-qualified     # 🕕 six o’clock
+1F561                                      ; fully-qualified     # 🕡 six-thirty
+1F556                                      ; fully-qualified     # 🕖 seven o’clock
+1F562                                      ; fully-qualified     # 🕢 seven-thirty
+1F557                                      ; fully-qualified     # 🕗 eight o’clock
+1F563                                      ; fully-qualified     # 🕣 eight-thirty
+1F558                                      ; fully-qualified     # 🕘 nine o’clock
+1F564                                      ; fully-qualified     # 🕤 nine-thirty
+1F559                                      ; fully-qualified     # 🕙 ten o’clock
+1F565                                      ; fully-qualified     # 🕥 ten-thirty
+1F55A                                      ; fully-qualified     # 🕚 eleven o’clock
+1F566                                      ; fully-qualified     # 🕦 eleven-thirty
+
+# subgroup: sky & weather
+1F311                                      ; fully-qualified     # 🌑 new moon
+1F312                                      ; fully-qualified     # 🌒 waxing crescent moon
+1F313                                      ; fully-qualified     # 🌓 first quarter moon
+1F314                                      ; fully-qualified     # 🌔 waxing gibbous moon
+1F315                                      ; fully-qualified     # 🌕 full moon
+1F316                                      ; fully-qualified     # 🌖 waning gibbous moon
+1F317                                      ; fully-qualified     # 🌗 last quarter moon
+1F318                                      ; fully-qualified     # 🌘 waning crescent moon
+1F319                                      ; fully-qualified     # 🌙 crescent moon
+1F31A                                      ; fully-qualified     # 🌚 new moon face
+1F31B                                      ; fully-qualified     # 🌛 first quarter moon with face
+1F31C                                      ; fully-qualified     # 🌜 last quarter moon with face
+1F321 FE0F                                 ; fully-qualified     # 🌡️ thermometer
+2600 FE0F                                  ; fully-qualified     # ☀️ sun
+1F31D                                      ; fully-qualified     # 🌝 full moon with face
+1F31E                                      ; fully-qualified     # 🌞 sun with face
+2B50                                       ; fully-qualified     # ⭐ white medium star
+1F31F                                      ; fully-qualified     # 🌟 glowing star
+1F320                                      ; fully-qualified     # 🌠 shooting star
+2601 FE0F                                  ; fully-qualified     # ☁️ cloud
+26C5                                       ; fully-qualified     # ⛅ sun behind cloud
+26C8 FE0F                                  ; fully-qualified     # ⛈️ cloud with lightning and rain
+1F324 FE0F                                 ; fully-qualified     # 🌤️ sun behind small cloud
+1F325 FE0F                                 ; fully-qualified     # 🌥️ sun behind large cloud
+1F326 FE0F                                 ; fully-qualified     # 🌦️ sun behind rain cloud
+1F327 FE0F                                 ; fully-qualified     # 🌧️ cloud with rain
+1F328 FE0F                                 ; fully-qualified     # 🌨️ cloud with snow
+1F329 FE0F                                 ; fully-qualified     # 🌩️ cloud with lightning
+1F32A FE0F                                 ; fully-qualified     # 🌪️ tornado
+1F32B FE0F                                 ; fully-qualified     # 🌫️ fog
+1F32C FE0F                                 ; fully-qualified     # 🌬️ wind face
+1F300                                      ; fully-qualified     # 🌀 cyclone
+1F308                                      ; fully-qualified     # 🌈 rainbow
+1F302                                      ; fully-qualified     # 🌂 closed umbrella
+2602 FE0F                                  ; fully-qualified     # ☂️ umbrella
+2614                                       ; fully-qualified     # ☔ umbrella with rain drops
+26F1 FE0F                                  ; fully-qualified     # ⛱️ umbrella on ground
+26A1                                       ; fully-qualified     # ⚡ high voltage
+2744 FE0F                                  ; fully-qualified     # ❄️ snowflake
+2603 FE0F                                  ; fully-qualified     # ☃️ snowman
+26C4                                       ; fully-qualified     # ⛄ snowman without snow
+2604 FE0F                                  ; fully-qualified     # ☄️ comet
+1F525                                      ; fully-qualified     # 🔥 fire
+1F4A7                                      ; fully-qualified     # 💧 droplet
+1F30A                                      ; fully-qualified     # 🌊 water wave
+
+# Travel & Places subtotal:		218
+# Travel & Places subtotal:		208	w/o modifiers
+
+# group: Activities
+
+# subgroup: event
+1F383                                      ; fully-qualified     # 🎃 jack-o-lantern
+1F384                                      ; fully-qualified     # 🎄 Christmas tree
+1F386                                      ; fully-qualified     # 🎆 fireworks
+1F387                                      ; fully-qualified     # 🎇 sparkler
+2728                                       ; fully-qualified     # ✨ sparkles
+1F388                                      ; fully-qualified     # 🎈 balloon
+1F389                                      ; fully-qualified     # 🎉 party popper
+1F38A                                      ; fully-qualified     # 🎊 confetti ball
+1F38B                                      ; fully-qualified     # 🎋 tanabata tree
+1F38D                                      ; fully-qualified     # 🎍 pine decoration
+1F38E                                      ; fully-qualified     # 🎎 Japanese dolls
+1F38F                                      ; fully-qualified     # 🎏 carp streamer
+1F390                                      ; fully-qualified     # 🎐 wind chime
+1F391                                      ; fully-qualified     # 🎑 moon viewing ceremony
+1F380                                      ; fully-qualified     # 🎀 ribbon
+1F381                                      ; fully-qualified     # 🎁 wrapped gift
+1F397 FE0F                                 ; fully-qualified     # 🎗️ reminder ribbon
+1F39F FE0F                                 ; fully-qualified     # 🎟️ admission tickets
+1F3AB                                      ; fully-qualified     # 🎫 ticket
+
+# subgroup: award-medal
+1F396 FE0F                                 ; fully-qualified     # 🎖️ military medal
+1F3C6                                      ; fully-qualified     # 🏆 trophy
+1F3C5                                      ; fully-qualified     # 🏅 sports medal
+1F947                                      ; fully-qualified     # 🥇 1st place medal
+1F948                                      ; fully-qualified     # 🥈 2nd place medal
+1F949                                      ; fully-qualified     # 🥉 3rd place medal
+
+# subgroup: sport
+26BD                                       ; fully-qualified     # ⚽ soccer ball
+26BE                                       ; fully-qualified     # ⚾ baseball
+1F3C0                                      ; fully-qualified     # 🏀 basketball
+1F3D0                                      ; fully-qualified     # 🏐 volleyball
+1F3C8                                      ; fully-qualified     # 🏈 american football
+1F3C9                                      ; fully-qualified     # 🏉 rugby football
+1F3BE                                      ; fully-qualified     # 🎾 tennis
+1F3B1                                      ; fully-qualified     # 🎱 pool 8 ball
+1F3B3                                      ; fully-qualified     # 🎳 bowling
+1F3CF                                      ; fully-qualified     # 🏏 cricket
+1F3D1                                      ; fully-qualified     # 🏑 field hockey
+1F3D2                                      ; fully-qualified     # 🏒 ice hockey
+1F3D3                                      ; fully-qualified     # 🏓 ping pong
+1F3F8                                      ; fully-qualified     # 🏸 badminton
+1F94A                                      ; fully-qualified     # 🥊 boxing glove
+1F94B                                      ; fully-qualified     # 🥋 martial arts uniform
+1F945                                      ; fully-qualified     # 🥅 goal net
+1F3AF                                      ; fully-qualified     # 🎯 direct hit
+26F3                                       ; fully-qualified     # ⛳ flag in hole
+26F8 FE0F                                  ; fully-qualified     # ⛸️ ice skate
+1F3A3                                      ; fully-qualified     # 🎣 fishing pole
+1F3BD                                      ; fully-qualified     # 🎽 running shirt
+1F3BF                                      ; fully-qualified     # 🎿 skis
+
+# subgroup: game
+1F3AE                                      ; fully-qualified     # 🎮 video game
+1F579 FE0F                                 ; fully-qualified     # 🕹️ joystick
+1F3B2                                      ; fully-qualified     # 🎲 game die
+2660 FE0F                                  ; fully-qualified     # ♠️ spade suit
+2665 FE0F                                  ; fully-qualified     # ♥️ heart suit
+2666 FE0F                                  ; fully-qualified     # ♦️ diamond suit
+2663 FE0F                                  ; fully-qualified     # ♣️ club suit
+1F0CF                                      ; fully-qualified     # 🃏 joker
+1F004                                      ; fully-qualified     # 🀄 mahjong red dragon
+1F3B4                                      ; fully-qualified     # 🎴 flower playing cards
+
+# Activities subtotal:		58
+# Activities subtotal:		58	w/o modifiers
+
+# group: Objects
+
+# subgroup: sound
+1F507                                      ; fully-qualified     # 🔇 muted speaker
+1F508                                      ; fully-qualified     # 🔈 speaker low volume
+1F509                                      ; fully-qualified     # 🔉 speaker medium volume
+1F50A                                      ; fully-qualified     # 🔊 speaker high volume
+1F4E2                                      ; fully-qualified     # 📢 loudspeaker
+1F4E3                                      ; fully-qualified     # 📣 megaphone
+1F4EF                                      ; fully-qualified     # 📯 postal horn
+1F514                                      ; fully-qualified     # 🔔 bell
+1F515                                      ; fully-qualified     # 🔕 bell with slash
+
+# subgroup: music
+1F3BC                                      ; fully-qualified     # 🎼 musical score
+1F3B5                                      ; fully-qualified     # 🎵 musical note
+1F3B6                                      ; fully-qualified     # 🎶 musical notes
+1F399 FE0F                                 ; fully-qualified     # 🎙️ studio microphone
+1F39A FE0F                                 ; fully-qualified     # 🎚️ level slider
+1F39B FE0F                                 ; fully-qualified     # 🎛️ control knobs
+1F3A4                                      ; fully-qualified     # 🎤 microphone
+1F3A7                                      ; fully-qualified     # 🎧 headphone
+1F4FB                                      ; fully-qualified     # 📻 radio
+
+# subgroup: musical-instrument
+1F3B7                                      ; fully-qualified     # 🎷 saxophone
+1F3B8                                      ; fully-qualified     # 🎸 guitar
+1F3B9                                      ; fully-qualified     # 🎹 musical keyboard
+1F3BA                                      ; fully-qualified     # 🎺 trumpet
+1F3BB                                      ; fully-qualified     # 🎻 violin
+1F941                                      ; fully-qualified     # 🥁 drum
+
+# subgroup: phone
+1F4F1                                      ; fully-qualified     # 📱 mobile phone
+1F4F2                                      ; fully-qualified     # 📲 mobile phone with arrow
+260E FE0F                                  ; fully-qualified     # ☎️ telephone
+1F4DE                                      ; fully-qualified     # 📞 telephone receiver
+1F4DF                                      ; fully-qualified     # 📟 pager
+1F4E0                                      ; fully-qualified     # 📠 fax machine
+
+# subgroup: computer
+1F50B                                      ; fully-qualified     # 🔋 battery
+1F50C                                      ; fully-qualified     # 🔌 electric plug
+1F4BB                                      ; fully-qualified     # 💻 laptop computer
+1F5A5 FE0F                                 ; fully-qualified     # 🖥️ desktop computer
+1F5A8 FE0F                                 ; fully-qualified     # 🖨️ printer
+2328 FE0F                                  ; fully-qualified     # ⌨️ keyboard
+1F5B1 FE0F                                 ; fully-qualified     # 🖱️ computer mouse
+1F5B2 FE0F                                 ; fully-qualified     # 🖲️ trackball
+1F4BD                                      ; fully-qualified     # 💽 computer disk
+1F4BE                                      ; fully-qualified     # 💾 floppy disk
+1F4BF                                      ; fully-qualified     # 💿 optical disk
+1F4C0                                      ; fully-qualified     # 📀 dvd
+
+# subgroup: light & video
+1F3A5                                      ; fully-qualified     # 🎥 movie camera
+1F39E FE0F                                 ; fully-qualified     # 🎞️ film frames
+1F4FD FE0F                                 ; fully-qualified     # 📽️ film projector
+1F3AC                                      ; fully-qualified     # 🎬 clapper board
+1F4FA                                      ; fully-qualified     # 📺 television
+1F4F7                                      ; fully-qualified     # 📷 camera
+1F4F8                                      ; fully-qualified     # 📸 camera with flash
+1F4F9                                      ; fully-qualified     # 📹 video camera
+1F4FC                                      ; fully-qualified     # 📼 videocassette
+1F50D                                      ; fully-qualified     # 🔍 left-pointing magnifying glass
+1F50E                                      ; fully-qualified     # 🔎 right-pointing magnifying glass
+1F52C                                      ; fully-qualified     # 🔬 microscope
+1F52D                                      ; fully-qualified     # 🔭 telescope
+1F4E1                                      ; fully-qualified     # 📡 satellite antenna
+1F56F FE0F                                 ; fully-qualified     # 🕯️ candle
+1F4A1                                      ; fully-qualified     # 💡 light bulb
+1F526                                      ; fully-qualified     # 🔦 flashlight
+1F3EE                                      ; fully-qualified     # 🏮 red paper lantern
+
+# subgroup: book-paper
+1F4D4                                      ; fully-qualified     # 📔 notebook with decorative cover
+1F4D5                                      ; fully-qualified     # 📕 closed book
+1F4D6                                      ; fully-qualified     # 📖 open book
+1F4D7                                      ; fully-qualified     # 📗 green book
+1F4D8                                      ; fully-qualified     # 📘 blue book
+1F4D9                                      ; fully-qualified     # 📙 orange book
+1F4DA                                      ; fully-qualified     # 📚 books
+1F4D3                                      ; fully-qualified     # 📓 notebook
+1F4D2                                      ; fully-qualified     # 📒 ledger
+1F4C3                                      ; fully-qualified     # 📃 page with curl
+1F4DC                                      ; fully-qualified     # 📜 scroll
+1F4C4                                      ; fully-qualified     # 📄 page facing up
+1F4F0                                      ; fully-qualified     # 📰 newspaper
+1F5DE FE0F                                 ; fully-qualified     # 🗞️ rolled-up newspaper
+1F4D1                                      ; fully-qualified     # 📑 bookmark tabs
+1F516                                      ; fully-qualified     # 🔖 bookmark
+1F3F7 FE0F                                 ; fully-qualified     # 🏷️ label
+
+# subgroup: money
+1F4B0                                      ; fully-qualified     # 💰 money bag
+1F4B4                                      ; fully-qualified     # 💴 yen banknote
+1F4B5                                      ; fully-qualified     # 💵 dollar banknote
+1F4B6                                      ; fully-qualified     # 💶 euro banknote
+1F4B7                                      ; fully-qualified     # 💷 pound banknote
+1F4B8                                      ; fully-qualified     # 💸 money with wings
+1F4B3                                      ; fully-qualified     # 💳 credit card
+1F4B9                                      ; fully-qualified     # 💹 chart increasing with yen
+1F4B1                                      ; fully-qualified     # 💱 currency exchange
+1F4B2                                      ; fully-qualified     # 💲 heavy dollar sign
+
+# subgroup: mail
+2709 FE0F                                  ; fully-qualified     # ✉️ envelope
+1F4E7                                      ; fully-qualified     # 📧 e-mail
+1F4E8                                      ; fully-qualified     # 📨 incoming envelope
+1F4E9                                      ; fully-qualified     # 📩 envelope with arrow
+1F4E4                                      ; fully-qualified     # 📤 outbox tray
+1F4E5                                      ; fully-qualified     # 📥 inbox tray
+1F4E6                                      ; fully-qualified     # 📦 package
+1F4EB                                      ; fully-qualified     # 📫 closed mailbox with raised flag
+1F4EA                                      ; fully-qualified     # 📪 closed mailbox with lowered flag
+1F4EC                                      ; fully-qualified     # 📬 open mailbox with raised flag
+1F4ED                                      ; fully-qualified     # 📭 open mailbox with lowered flag
+1F4EE                                      ; fully-qualified     # 📮 postbox
+1F5F3 FE0F                                 ; fully-qualified     # 🗳️ ballot box with ballot
+
+# subgroup: writing
+270F FE0F                                  ; fully-qualified     # ✏️ pencil
+2712 FE0F                                  ; fully-qualified     # ✒️ black nib
+1F58B FE0F                                 ; fully-qualified     # 🖋️ fountain pen
+1F58A FE0F                                 ; fully-qualified     # 🖊️ pen
+1F58C FE0F                                 ; fully-qualified     # 🖌️ paintbrush
+1F58D FE0F                                 ; fully-qualified     # 🖍️ crayon
+1F4DD                                      ; fully-qualified     # 📝 memo
+
+# subgroup: office
+1F4BC                                      ; fully-qualified     # 💼 briefcase
+1F4C1                                      ; fully-qualified     # 📁 file folder
+1F4C2                                      ; fully-qualified     # 📂 open file folder
+1F5C2 FE0F                                 ; fully-qualified     # 🗂️ card index dividers
+1F4C5                                      ; fully-qualified     # 📅 calendar
+1F4C6                                      ; fully-qualified     # 📆 tear-off calendar
+1F5D2 FE0F                                 ; fully-qualified     # 🗒️ spiral notepad
+1F5D3 FE0F                                 ; fully-qualified     # 🗓️ spiral calendar
+1F4C7                                      ; fully-qualified     # 📇 card index
+1F4C8                                      ; fully-qualified     # 📈 chart increasing
+1F4C9                                      ; fully-qualified     # 📉 chart decreasing
+1F4CA                                      ; fully-qualified     # 📊 bar chart
+1F4CB                                      ; fully-qualified     # 📋 clipboard
+1F4CC                                      ; fully-qualified     # 📌 pushpin
+1F4CD                                      ; fully-qualified     # 📍 round pushpin
+1F4CE                                      ; fully-qualified     # 📎 paperclip
+1F587 FE0F                                 ; fully-qualified     # 🖇️ linked paperclips
+1F4CF                                      ; fully-qualified     # 📏 straight ruler
+1F4D0                                      ; fully-qualified     # 📐 triangular ruler
+2702 FE0F                                  ; fully-qualified     # ✂️ scissors
+1F5C3 FE0F                                 ; fully-qualified     # 🗃️ card file box
+1F5C4 FE0F                                 ; fully-qualified     # 🗄️ file cabinet
+1F5D1 FE0F                                 ; fully-qualified     # 🗑️ wastebasket
+
+# subgroup: lock
+1F512                                      ; fully-qualified     # 🔒 locked
+1F513                                      ; fully-qualified     # 🔓 unlocked
+1F50F                                      ; fully-qualified     # 🔏 locked with pen
+1F510                                      ; fully-qualified     # 🔐 locked with key
+1F511                                      ; fully-qualified     # 🔑 key
+1F5DD FE0F                                 ; fully-qualified     # 🗝️ old key
+
+# subgroup: tool
+1F528                                      ; fully-qualified     # 🔨 hammer
+26CF FE0F                                  ; fully-qualified     # ⛏️ pick
+2692 FE0F                                  ; fully-qualified     # ⚒️ hammer and pick
+1F6E0 FE0F                                 ; fully-qualified     # 🛠️ hammer and wrench
+1F5E1 FE0F                                 ; fully-qualified     # 🗡️ dagger
+2694 FE0F                                  ; fully-qualified     # ⚔️ crossed swords
+1F52B                                      ; fully-qualified     # 🔫 pistol
+1F3F9                                      ; fully-qualified     # 🏹 bow and arrow
+1F6E1 FE0F                                 ; fully-qualified     # 🛡️ shield
+1F527                                      ; fully-qualified     # 🔧 wrench
+1F529                                      ; fully-qualified     # 🔩 nut and bolt
+2699 FE0F                                  ; fully-qualified     # ⚙️ gear
+1F5DC FE0F                                 ; fully-qualified     # 🗜️ clamp
+2697 FE0F                                  ; fully-qualified     # ⚗️ alembic
+2696 FE0F                                  ; fully-qualified     # ⚖️ balance scale
+1F517                                      ; fully-qualified     # 🔗 link
+26D3 FE0F                                  ; fully-qualified     # ⛓️ chains
+
+# subgroup: medical
+1F489                                      ; fully-qualified     # 💉 syringe
+1F48A                                      ; fully-qualified     # 💊 pill
+
+# subgroup: other-object
+1F6AC                                      ; fully-qualified     # 🚬 cigarette
+26B0 FE0F                                  ; fully-qualified     # ⚰️ coffin
+26B1 FE0F                                  ; fully-qualified     # ⚱️ funeral urn
+1F5FF                                      ; fully-qualified     # 🗿 moai
+1F6E2 FE0F                                 ; fully-qualified     # 🛢️ oil drum
+1F52E                                      ; fully-qualified     # 🔮 crystal ball
+1F6D2                                      ; fully-qualified     # 🛒 shopping cart
+
+# Objects subtotal:		162
+# Objects subtotal:		162	w/o modifiers
+
+# group: Symbols
+
+# subgroup: transport-sign
+1F3E7                                      ; fully-qualified     # 🏧 ATM sign
+1F6AE                                      ; fully-qualified     # 🚮 litter in bin sign
+1F6B0                                      ; fully-qualified     # 🚰 potable water
+267F                                       ; fully-qualified     # ♿ wheelchair symbol
+1F6B9                                      ; fully-qualified     # 🚹 men’s room
+1F6BA                                      ; fully-qualified     # 🚺 women’s room
+1F6BB                                      ; fully-qualified     # 🚻 restroom
+1F6BC                                      ; fully-qualified     # 🚼 baby symbol
+1F6BE                                      ; fully-qualified     # 🚾 water closet
+1F6C2                                      ; fully-qualified     # 🛂 passport control
+1F6C3                                      ; fully-qualified     # 🛃 customs
+1F6C4                                      ; fully-qualified     # 🛄 baggage claim
+1F6C5                                      ; fully-qualified     # 🛅 left luggage
+
+# subgroup: warning
+26A0 FE0F                                  ; fully-qualified     # ⚠️ warning
+1F6B8                                      ; fully-qualified     # 🚸 children crossing
+26D4                                       ; fully-qualified     # ⛔ no entry
+1F6AB                                      ; fully-qualified     # 🚫 prohibited
+1F6B3                                      ; fully-qualified     # 🚳 no bicycles
+1F6AD                                      ; fully-qualified     # 🚭 no smoking
+1F6AF                                      ; fully-qualified     # 🚯 no littering
+1F6B1                                      ; fully-qualified     # 🚱 non-potable water
+1F6B7                                      ; fully-qualified     # 🚷 no pedestrians
+1F4F5                                      ; fully-qualified     # 📵 no mobile phones
+1F51E                                      ; fully-qualified     # 🔞 no one under eighteen
+2622 FE0F                                  ; fully-qualified     # ☢️ radioactive
+2623 FE0F                                  ; fully-qualified     # ☣️ biohazard
+
+# subgroup: arrow
+2B06 FE0F                                  ; fully-qualified     # ⬆️ up arrow
+2197 FE0F                                  ; fully-qualified     # ↗️ up-right arrow
+27A1 FE0F                                  ; fully-qualified     # ➡️ right arrow
+2198 FE0F                                  ; fully-qualified     # ↘️ down-right arrow
+2B07 FE0F                                  ; fully-qualified     # ⬇️ down arrow
+2199 FE0F                                  ; fully-qualified     # ↙️ down-left arrow
+2B05 FE0F                                  ; fully-qualified     # ⬅️ left arrow
+2196 FE0F                                  ; fully-qualified     # ↖️ up-left arrow
+2195 FE0F                                  ; fully-qualified     # ↕️ up-down arrow
+2194 FE0F                                  ; fully-qualified     # ↔️ left-right arrow
+21A9 FE0F                                  ; fully-qualified     # ↩️ right arrow curving left
+21AA FE0F                                  ; fully-qualified     # ↪️ left arrow curving right
+2934 FE0F                                  ; fully-qualified     # ⤴️ right arrow curving up
+2935 FE0F                                  ; fully-qualified     # ⤵️ right arrow curving down
+1F503                                      ; fully-qualified     # 🔃 clockwise vertical arrows
+1F504                                      ; fully-qualified     # 🔄 anticlockwise arrows button
+1F519                                      ; fully-qualified     # 🔙 BACK arrow
+1F51A                                      ; fully-qualified     # 🔚 END arrow
+1F51B                                      ; fully-qualified     # 🔛 ON! arrow
+1F51C                                      ; fully-qualified     # 🔜 SOON arrow
+1F51D                                      ; fully-qualified     # 🔝 TOP arrow
+
+# subgroup: religion
+1F6D0                                      ; fully-qualified     # 🛐 place of worship
+269B FE0F                                  ; fully-qualified     # ⚛️ atom symbol
+1F549 FE0F                                 ; fully-qualified     # 🕉️ om
+2721 FE0F                                  ; fully-qualified     # ✡️ star of David
+2638 FE0F                                  ; fully-qualified     # ☸️ wheel of dharma
+262F FE0F                                  ; fully-qualified     # ☯️ yin yang
+271D FE0F                                  ; fully-qualified     # ✝️ latin cross
+2626 FE0F                                  ; fully-qualified     # ☦️ orthodox cross
+262A FE0F                                  ; fully-qualified     # ☪️ star and crescent
+262E FE0F                                  ; fully-qualified     # ☮️ peace symbol
+1F54E                                      ; fully-qualified     # 🕎 menorah
+1F52F                                      ; fully-qualified     # 🔯 dotted six-pointed star
+
+# subgroup: zodiac
+2648                                       ; fully-qualified     # ♈ Aries
+2649                                       ; fully-qualified     # ♉ Taurus
+264A                                       ; fully-qualified     # ♊ Gemini
+264B                                       ; fully-qualified     # ♋ Cancer
+264C                                       ; fully-qualified     # ♌ Leo
+264D                                       ; fully-qualified     # ♍ Virgo
+264E                                       ; fully-qualified     # ♎ Libra
+264F                                       ; fully-qualified     # ♏ Scorpius
+2650                                       ; fully-qualified     # ♐ Sagittarius
+2651                                       ; fully-qualified     # ♑ Capricorn
+2652                                       ; fully-qualified     # ♒ Aquarius
+2653                                       ; fully-qualified     # ♓ Pisces
+26CE                                       ; fully-qualified     # ⛎ Ophiuchus
+
+# subgroup: av-symbol
+1F500                                      ; fully-qualified     # 🔀 shuffle tracks button
+1F501                                      ; fully-qualified     # 🔁 repeat button
+1F502                                      ; fully-qualified     # 🔂 repeat single button
+25B6 FE0F                                  ; fully-qualified     # ▶️ play button
+23E9                                       ; fully-qualified     # ⏩ fast-forward button
+23ED FE0F                                  ; fully-qualified     # ⏭️ next track button
+23EF FE0F                                  ; fully-qualified     # ⏯️ play or pause button
+25C0 FE0F                                  ; fully-qualified     # ◀️ reverse button
+23EA                                       ; fully-qualified     # ⏪ fast reverse button
+23EE FE0F                                  ; fully-qualified     # ⏮️ last track button
+1F53C                                      ; fully-qualified     # 🔼 up button
+23EB                                       ; fully-qualified     # ⏫ fast up button
+1F53D                                      ; fully-qualified     # 🔽 down button
+23EC                                       ; fully-qualified     # ⏬ fast down button
+23F8 FE0F                                  ; fully-qualified     # ⏸️ pause button
+23F9 FE0F                                  ; fully-qualified     # ⏹️ stop button
+23FA FE0F                                  ; fully-qualified     # ⏺️ record button
+23CF FE0F                                  ; fully-qualified     # ⏏️ eject button
+1F3A6                                      ; fully-qualified     # 🎦 cinema
+1F505                                      ; fully-qualified     # 🔅 dim button
+1F506                                      ; fully-qualified     # 🔆 bright button
+1F4F6                                      ; fully-qualified     # 📶 antenna bars
+1F4F3                                      ; fully-qualified     # 📳 vibration mode
+1F4F4                                      ; fully-qualified     # 📴 mobile phone off
+
+# subgroup: other-symbol
+267B FE0F                                  ; fully-qualified     # ♻️ recycling symbol
+1F4DB                                      ; fully-qualified     # 📛 name badge
+269C FE0F                                  ; fully-qualified     # ⚜️ fleur-de-lis
+1F530                                      ; fully-qualified     # 🔰 Japanese symbol for beginner
+1F531                                      ; fully-qualified     # 🔱 trident emblem
+2B55                                       ; fully-qualified     # ⭕ heavy large circle
+2705                                       ; fully-qualified     # ✅ white heavy check mark
+2611 FE0F                                  ; fully-qualified     # ☑️ ballot box with check
+2714 FE0F                                  ; fully-qualified     # ✔️ heavy check mark
+2716 FE0F                                  ; fully-qualified     # ✖️ heavy multiplication x
+274C                                       ; fully-qualified     # ❌ cross mark
+274E                                       ; fully-qualified     # ❎ cross mark button
+2795                                       ; fully-qualified     # ➕ heavy plus sign
+2640 FE0F                                  ; fully-qualified     # ♀️ female sign
+2642 FE0F                                  ; fully-qualified     # ♂️ male sign
+2695 FE0F                                  ; fully-qualified     # ⚕️ medical symbol
+2796                                       ; fully-qualified     # ➖ heavy minus sign
+2797                                       ; fully-qualified     # ➗ heavy division sign
+27B0                                       ; fully-qualified     # ➰ curly loop
+27BF                                       ; fully-qualified     # ➿ double curly loop
+303D FE0F                                  ; fully-qualified     # 〽️ part alternation mark
+2733 FE0F                                  ; fully-qualified     # ✳️ eight-spoked asterisk
+2734 FE0F                                  ; fully-qualified     # ✴️ eight-pointed star
+2747 FE0F                                  ; fully-qualified     # ❇️ sparkle
+203C FE0F                                  ; fully-qualified     # ‼️ double exclamation mark
+2049 FE0F                                  ; fully-qualified     # ⁉️ exclamation question mark
+2753                                       ; fully-qualified     # ❓ question mark
+2754                                       ; fully-qualified     # ❔ white question mark
+2755                                       ; fully-qualified     # ❕ white exclamation mark
+2757                                       ; fully-qualified     # ❗ exclamation mark
+3030 FE0F                                  ; fully-qualified     # 〰️ wavy dash
+00A9 FE0F                                  ; fully-qualified     # ©️ copyright
+00AE FE0F                                  ; fully-qualified     # ®️ registered
+2122 FE0F                                  ; fully-qualified     # ™️ trade mark
+
+# subgroup: keycap
+0023 FE0F 20E3                             ; fully-qualified     # #️⃣ keycap: #
+002A FE0F 20E3                             ; fully-qualified     # *️⃣ keycap: *
+0030 FE0F 20E3                             ; fully-qualified     # 0️⃣ keycap: 0
+0031 FE0F 20E3                             ; fully-qualified     # 1️⃣ keycap: 1
+0032 FE0F 20E3                             ; fully-qualified     # 2️⃣ keycap: 2
+0033 FE0F 20E3                             ; fully-qualified     # 3️⃣ keycap: 3
+0034 FE0F 20E3                             ; fully-qualified     # 4️⃣ keycap: 4
+0035 FE0F 20E3                             ; fully-qualified     # 5️⃣ keycap: 5
+0036 FE0F 20E3                             ; fully-qualified     # 6️⃣ keycap: 6
+0037 FE0F 20E3                             ; fully-qualified     # 7️⃣ keycap: 7
+0038 FE0F 20E3                             ; fully-qualified     # 8️⃣ keycap: 8
+0039 FE0F 20E3                             ; fully-qualified     # 9️⃣ keycap: 9
+1F51F                                      ; fully-qualified     # 🔟 keycap 10
+
+# subgroup: alphanum
+1F4AF                                      ; fully-qualified     # 💯 hundred points
+1F520                                      ; fully-qualified     # 🔠 input latin uppercase
+1F521                                      ; fully-qualified     # 🔡 input latin lowercase
+1F522                                      ; fully-qualified     # 🔢 input numbers
+1F523                                      ; fully-qualified     # 🔣 input symbols
+1F524                                      ; fully-qualified     # 🔤 input latin letters
+1F170 FE0F                                 ; fully-qualified     # 🅰️ A button (blood type)
+1F18E                                      ; fully-qualified     # 🆎 AB button (blood type)
+1F171 FE0F                                 ; fully-qualified     # 🅱️ B button (blood type)
+1F191                                      ; fully-qualified     # 🆑 CL button
+1F192                                      ; fully-qualified     # 🆒 COOL button
+1F193                                      ; fully-qualified     # 🆓 FREE button
+2139 FE0F                                  ; fully-qualified     # ℹ️ information
+1F194                                      ; fully-qualified     # 🆔 ID button
+24C2 FE0F                                  ; fully-qualified     # Ⓜ️ circled M
+1F195                                      ; fully-qualified     # 🆕 NEW button
+1F196                                      ; fully-qualified     # 🆖 NG button
+1F17E FE0F                                 ; fully-qualified     # 🅾️ O button (blood type)
+1F197                                      ; fully-qualified     # 🆗 OK button
+1F17F FE0F                                 ; fully-qualified     # 🅿️ P button
+1F198                                      ; fully-qualified     # 🆘 SOS button
+1F199                                      ; fully-qualified     # 🆙 UP! button
+1F19A                                      ; fully-qualified     # 🆚 VS button
+1F201                                      ; fully-qualified     # 🈁 Japanese “here” button
+1F202 FE0F                                 ; fully-qualified     # 🈂️ Japanese “service charge” button
+1F237 FE0F                                 ; fully-qualified     # 🈷️ Japanese “monthly amount” button
+1F236                                      ; fully-qualified     # 🈶 Japanese “not free of charge” button
+1F22F                                      ; fully-qualified     # 🈯 Japanese “reserved” button
+1F250                                      ; fully-qualified     # 🉐 Japanese “bargain” button
+1F239                                      ; fully-qualified     # 🈹 Japanese “discount” button
+1F21A                                      ; fully-qualified     # 🈚 Japanese “free of charge” button
+1F232                                      ; fully-qualified     # 🈲 Japanese “prohibited” button
+1F251                                      ; fully-qualified     # 🉑 Japanese “acceptable” button
+1F238                                      ; fully-qualified     # 🈸 Japanese “application” button
+1F234                                      ; fully-qualified     # 🈴 Japanese “passing grade” button
+1F233                                      ; fully-qualified     # 🈳 Japanese “vacancy” button
+3297 FE0F                                  ; fully-qualified     # ㊗️ Japanese “congratulations” button
+3299 FE0F                                  ; fully-qualified     # ㊙️ Japanese “secret” button
+1F23A                                      ; fully-qualified     # 🈺 Japanese “open for business” button
+1F235                                      ; fully-qualified     # 🈵 Japanese “no vacancy” button
+
+# subgroup: geometric
+25AA FE0F                                  ; fully-qualified     # ▪️ black small square
+25AB FE0F                                  ; fully-qualified     # ▫️ white small square
+25FB FE0F                                  ; fully-qualified     # ◻️ white medium square
+25FC FE0F                                  ; fully-qualified     # ◼️ black medium square
+25FD                                       ; fully-qualified     # ◽ white medium-small square
+25FE                                       ; fully-qualified     # ◾ black medium-small square
+2B1B                                       ; fully-qualified     # ⬛ black large square
+2B1C                                       ; fully-qualified     # ⬜ white large square
+1F536                                      ; fully-qualified     # 🔶 large orange diamond
+1F537                                      ; fully-qualified     # 🔷 large blue diamond
+1F538                                      ; fully-qualified     # 🔸 small orange diamond
+1F539                                      ; fully-qualified     # 🔹 small blue diamond
+1F53A                                      ; fully-qualified     # 🔺 red triangle pointed up
+1F53B                                      ; fully-qualified     # 🔻 red triangle pointed down
+1F4A0                                      ; fully-qualified     # 💠 diamond with a dot
+1F518                                      ; fully-qualified     # 🔘 radio button
+1F532                                      ; fully-qualified     # 🔲 black square button
+1F533                                      ; fully-qualified     # 🔳 white square button
+26AA                                       ; fully-qualified     # ⚪ white circle
+26AB                                       ; fully-qualified     # ⚫ black circle
+1F534                                      ; fully-qualified     # 🔴 red circle
+1F535                                      ; fully-qualified     # 🔵 blue circle
+
+# Symbols subtotal:		205
+# Symbols subtotal:		205	w/o modifiers
+
+# group: Flags
+
+# subgroup: flag
+1F3C1                                      ; fully-qualified     # 🏁 chequered flag
+1F6A9                                      ; fully-qualified     # 🚩 triangular flag
+1F38C                                      ; fully-qualified     # 🎌 crossed flags
+1F3F4                                      ; fully-qualified     # 🏴 black flag
+1F3F3 FE0F                                 ; fully-qualified     # 🏳️ white flag
+1F3F3 FE0F 200D 1F308                      ; fully-qualified     # 🏳️‍🌈 rainbow flag
+1F3F3 200D 1F308                           ; non-fully-qualified # 🏳‍🌈 rainbow flag
+
+# subgroup: country-flag
+1F1E6 1F1E8                                ; fully-qualified     # 🇦🇨 Ascension Island
+1F1E6 1F1E9                                ; fully-qualified     # 🇦🇩 Andorra
+1F1E6 1F1EA                                ; fully-qualified     # 🇦🇪 United Arab Emirates
+1F1E6 1F1EB                                ; fully-qualified     # 🇦🇫 Afghanistan
+1F1E6 1F1EC                                ; fully-qualified     # 🇦🇬 Antigua & Barbuda
+1F1E6 1F1EE                                ; fully-qualified     # 🇦🇮 Anguilla
+1F1E6 1F1F1                                ; fully-qualified     # 🇦🇱 Albania
+1F1E6 1F1F2                                ; fully-qualified     # 🇦🇲 Armenia
+1F1E6 1F1F4                                ; fully-qualified     # 🇦🇴 Angola
+1F1E6 1F1F6                                ; fully-qualified     # 🇦🇶 Antarctica
+1F1E6 1F1F7                                ; fully-qualified     # 🇦🇷 Argentina
+1F1E6 1F1F8                                ; fully-qualified     # 🇦🇸 American Samoa
+1F1E6 1F1F9                                ; fully-qualified     # 🇦🇹 Austria
+1F1E6 1F1FA                                ; fully-qualified     # 🇦🇺 Australia
+1F1E6 1F1FC                                ; fully-qualified     # 🇦🇼 Aruba
+1F1E6 1F1FD                                ; fully-qualified     # 🇦🇽 Åland Islands
+1F1E6 1F1FF                                ; fully-qualified     # 🇦🇿 Azerbaijan
+1F1E7 1F1E6                                ; fully-qualified     # 🇧🇦 Bosnia & Herzegovina
+1F1E7 1F1E7                                ; fully-qualified     # 🇧🇧 Barbados
+1F1E7 1F1E9                                ; fully-qualified     # 🇧🇩 Bangladesh
+1F1E7 1F1EA                                ; fully-qualified     # 🇧🇪 Belgium
+1F1E7 1F1EB                                ; fully-qualified     # 🇧🇫 Burkina Faso
+1F1E7 1F1EC                                ; fully-qualified     # 🇧🇬 Bulgaria
+1F1E7 1F1ED                                ; fully-qualified     # 🇧🇭 Bahrain
+1F1E7 1F1EE                                ; fully-qualified     # 🇧🇮 Burundi
+1F1E7 1F1EF                                ; fully-qualified     # 🇧🇯 Benin
+1F1E7 1F1F1                                ; fully-qualified     # 🇧🇱 St. Barthélemy
+1F1E7 1F1F2                                ; fully-qualified     # 🇧🇲 Bermuda
+1F1E7 1F1F3                                ; fully-qualified     # 🇧🇳 Brunei
+1F1E7 1F1F4                                ; fully-qualified     # 🇧🇴 Bolivia
+1F1E7 1F1F6                                ; fully-qualified     # 🇧🇶 Caribbean Netherlands
+1F1E7 1F1F7                                ; fully-qualified     # 🇧🇷 Brazil
+1F1E7 1F1F8                                ; fully-qualified     # 🇧🇸 Bahamas
+1F1E7 1F1F9                                ; fully-qualified     # 🇧🇹 Bhutan
+1F1E7 1F1FB                                ; fully-qualified     # 🇧🇻 Bouvet Island
+1F1E7 1F1FC                                ; fully-qualified     # 🇧🇼 Botswana
+1F1E7 1F1FE                                ; fully-qualified     # 🇧🇾 Belarus
+1F1E7 1F1FF                                ; fully-qualified     # 🇧🇿 Belize
+1F1E8 1F1E6                                ; fully-qualified     # 🇨🇦 Canada
+1F1E8 1F1E8                                ; fully-qualified     # 🇨🇨 Cocos (Keeling) Islands
+1F1E8 1F1E9                                ; fully-qualified     # 🇨🇩 Congo - Kinshasa
+1F1E8 1F1EB                                ; fully-qualified     # 🇨🇫 Central African Republic
+1F1E8 1F1EC                                ; fully-qualified     # 🇨🇬 Congo - Brazzaville
+1F1E8 1F1ED                                ; fully-qualified     # 🇨🇭 Switzerland
+1F1E8 1F1EE                                ; fully-qualified     # 🇨🇮 Côte d’Ivoire
+1F1E8 1F1F0                                ; fully-qualified     # 🇨🇰 Cook Islands
+1F1E8 1F1F1                                ; fully-qualified     # 🇨🇱 Chile
+1F1E8 1F1F2                                ; fully-qualified     # 🇨🇲 Cameroon
+1F1E8 1F1F3                                ; fully-qualified     # 🇨🇳 China
+1F1E8 1F1F4                                ; fully-qualified     # 🇨🇴 Colombia
+1F1E8 1F1F5                                ; fully-qualified     # 🇨🇵 Clipperton Island
+1F1E8 1F1F7                                ; fully-qualified     # 🇨🇷 Costa Rica
+1F1E8 1F1FA                                ; fully-qualified     # 🇨🇺 Cuba
+1F1E8 1F1FB                                ; fully-qualified     # 🇨🇻 Cape Verde
+1F1E8 1F1FC                                ; fully-qualified     # 🇨🇼 Curaçao
+1F1E8 1F1FD                                ; fully-qualified     # 🇨🇽 Christmas Island
+1F1E8 1F1FE                                ; fully-qualified     # 🇨🇾 Cyprus
+1F1E8 1F1FF                                ; fully-qualified     # 🇨🇿 Czech Republic
+1F1E9 1F1EA                                ; fully-qualified     # 🇩🇪 Germany
+1F1E9 1F1EC                                ; fully-qualified     # 🇩🇬 Diego Garcia
+1F1E9 1F1EF                                ; fully-qualified     # 🇩🇯 Djibouti
+1F1E9 1F1F0                                ; fully-qualified     # 🇩🇰 Denmark
+1F1E9 1F1F2                                ; fully-qualified     # 🇩🇲 Dominica
+1F1E9 1F1F4                                ; fully-qualified     # 🇩🇴 Dominican Republic
+1F1E9 1F1FF                                ; fully-qualified     # 🇩🇿 Algeria
+1F1EA 1F1E6                                ; fully-qualified     # 🇪🇦 Ceuta & Melilla
+1F1EA 1F1E8                                ; fully-qualified     # 🇪🇨 Ecuador
+1F1EA 1F1EA                                ; fully-qualified     # 🇪🇪 Estonia
+1F1EA 1F1EC                                ; fully-qualified     # 🇪🇬 Egypt
+1F1EA 1F1ED                                ; fully-qualified     # 🇪🇭 Western Sahara
+1F1EA 1F1F7                                ; fully-qualified     # 🇪🇷 Eritrea
+1F1EA 1F1F8                                ; fully-qualified     # 🇪🇸 Spain
+1F1EA 1F1F9                                ; fully-qualified     # 🇪🇹 Ethiopia
+1F1EA 1F1FA                                ; fully-qualified     # 🇪🇺 European Union
+1F1EB 1F1EE                                ; fully-qualified     # 🇫🇮 Finland
+1F1EB 1F1EF                                ; fully-qualified     # 🇫🇯 Fiji
+1F1EB 1F1F0                                ; fully-qualified     # 🇫🇰 Falkland Islands
+1F1EB 1F1F2                                ; fully-qualified     # 🇫🇲 Micronesia
+1F1EB 1F1F4                                ; fully-qualified     # 🇫🇴 Faroe Islands
+1F1EB 1F1F7                                ; fully-qualified     # 🇫🇷 France
+1F1EC 1F1E6                                ; fully-qualified     # 🇬🇦 Gabon
+1F1EC 1F1E7                                ; fully-qualified     # 🇬🇧 United Kingdom
+1F1EC 1F1E9                                ; fully-qualified     # 🇬🇩 Grenada
+1F1EC 1F1EA                                ; fully-qualified     # 🇬🇪 Georgia
+1F1EC 1F1EB                                ; fully-qualified     # 🇬🇫 French Guiana
+1F1EC 1F1EC                                ; fully-qualified     # 🇬🇬 Guernsey
+1F1EC 1F1ED                                ; fully-qualified     # 🇬🇭 Ghana
+1F1EC 1F1EE                                ; fully-qualified     # 🇬🇮 Gibraltar
+1F1EC 1F1F1                                ; fully-qualified     # 🇬🇱 Greenland
+1F1EC 1F1F2                                ; fully-qualified     # 🇬🇲 Gambia
+1F1EC 1F1F3                                ; fully-qualified     # 🇬🇳 Guinea
+1F1EC 1F1F5                                ; fully-qualified     # 🇬🇵 Guadeloupe
+1F1EC 1F1F6                                ; fully-qualified     # 🇬🇶 Equatorial Guinea
+1F1EC 1F1F7                                ; fully-qualified     # 🇬🇷 Greece
+1F1EC 1F1F8                                ; fully-qualified     # 🇬🇸 South Georgia & South Sandwich Islands
+1F1EC 1F1F9                                ; fully-qualified     # 🇬🇹 Guatemala
+1F1EC 1F1FA                                ; fully-qualified     # 🇬🇺 Guam
+1F1EC 1F1FC                                ; fully-qualified     # 🇬🇼 Guinea-Bissau
+1F1EC 1F1FE                                ; fully-qualified     # 🇬🇾 Guyana
+1F1ED 1F1F0                                ; fully-qualified     # 🇭🇰 Hong Kong SAR China
+1F1ED 1F1F2                                ; fully-qualified     # 🇭🇲 Heard & McDonald Islands
+1F1ED 1F1F3                                ; fully-qualified     # 🇭🇳 Honduras
+1F1ED 1F1F7                                ; fully-qualified     # 🇭🇷 Croatia
+1F1ED 1F1F9                                ; fully-qualified     # 🇭🇹 Haiti
+1F1ED 1F1FA                                ; fully-qualified     # 🇭🇺 Hungary
+1F1EE 1F1E8                                ; fully-qualified     # 🇮🇨 Canary Islands
+1F1EE 1F1E9                                ; fully-qualified     # 🇮🇩 Indonesia
+1F1EE 1F1EA                                ; fully-qualified     # 🇮🇪 Ireland
+1F1EE 1F1F1                                ; fully-qualified     # 🇮🇱 Israel
+1F1EE 1F1F2                                ; fully-qualified     # 🇮🇲 Isle of Man
+1F1EE 1F1F3                                ; fully-qualified     # 🇮🇳 India
+1F1EE 1F1F4                                ; fully-qualified     # 🇮🇴 British Indian Ocean Territory
+1F1EE 1F1F6                                ; fully-qualified     # 🇮🇶 Iraq
+1F1EE 1F1F7                                ; fully-qualified     # 🇮🇷 Iran
+1F1EE 1F1F8                                ; fully-qualified     # 🇮🇸 Iceland
+1F1EE 1F1F9                                ; fully-qualified     # 🇮🇹 Italy
+1F1EF 1F1EA                                ; fully-qualified     # 🇯🇪 Jersey
+1F1EF 1F1F2                                ; fully-qualified     # 🇯🇲 Jamaica
+1F1EF 1F1F4                                ; fully-qualified     # 🇯🇴 Jordan
+1F1EF 1F1F5                                ; fully-qualified     # 🇯🇵 Japan
+1F1F0 1F1EA                                ; fully-qualified     # 🇰🇪 Kenya
+1F1F0 1F1EC                                ; fully-qualified     # 🇰🇬 Kyrgyzstan
+1F1F0 1F1ED                                ; fully-qualified     # 🇰🇭 Cambodia
+1F1F0 1F1EE                                ; fully-qualified     # 🇰🇮 Kiribati
+1F1F0 1F1F2                                ; fully-qualified     # 🇰🇲 Comoros
+1F1F0 1F1F3                                ; fully-qualified     # 🇰🇳 St. Kitts & Nevis
+1F1F0 1F1F5                                ; fully-qualified     # 🇰🇵 North Korea
+1F1F0 1F1F7                                ; fully-qualified     # 🇰🇷 South Korea
+1F1F0 1F1FC                                ; fully-qualified     # 🇰🇼 Kuwait
+1F1F0 1F1FE                                ; fully-qualified     # 🇰🇾 Cayman Islands
+1F1F0 1F1FF                                ; fully-qualified     # 🇰🇿 Kazakhstan
+1F1F1 1F1E6                                ; fully-qualified     # 🇱🇦 Laos
+1F1F1 1F1E7                                ; fully-qualified     # 🇱🇧 Lebanon
+1F1F1 1F1E8                                ; fully-qualified     # 🇱🇨 St. Lucia
+1F1F1 1F1EE                                ; fully-qualified     # 🇱🇮 Liechtenstein
+1F1F1 1F1F0                                ; fully-qualified     # 🇱🇰 Sri Lanka
+1F1F1 1F1F7                                ; fully-qualified     # 🇱🇷 Liberia
+1F1F1 1F1F8                                ; fully-qualified     # 🇱🇸 Lesotho
+1F1F1 1F1F9                                ; fully-qualified     # 🇱🇹 Lithuania
+1F1F1 1F1FA                                ; fully-qualified     # 🇱🇺 Luxembourg
+1F1F1 1F1FB                                ; fully-qualified     # 🇱🇻 Latvia
+1F1F1 1F1FE                                ; fully-qualified     # 🇱🇾 Libya
+1F1F2 1F1E6                                ; fully-qualified     # 🇲🇦 Morocco
+1F1F2 1F1E8                                ; fully-qualified     # 🇲🇨 Monaco
+1F1F2 1F1E9                                ; fully-qualified     # 🇲🇩 Moldova
+1F1F2 1F1EA                                ; fully-qualified     # 🇲🇪 Montenegro
+1F1F2 1F1EB                                ; fully-qualified     # 🇲🇫 St. Martin
+1F1F2 1F1EC                                ; fully-qualified     # 🇲🇬 Madagascar
+1F1F2 1F1ED                                ; fully-qualified     # 🇲🇭 Marshall Islands
+1F1F2 1F1F0                                ; fully-qualified     # 🇲🇰 Macedonia
+1F1F2 1F1F1                                ; fully-qualified     # 🇲🇱 Mali
+1F1F2 1F1F2                                ; fully-qualified     # 🇲🇲 Myanmar (Burma)
+1F1F2 1F1F3                                ; fully-qualified     # 🇲🇳 Mongolia
+1F1F2 1F1F4                                ; fully-qualified     # 🇲🇴 Macau SAR China
+1F1F2 1F1F5                                ; fully-qualified     # 🇲🇵 Northern Mariana Islands
+1F1F2 1F1F6                                ; fully-qualified     # 🇲🇶 Martinique
+1F1F2 1F1F7                                ; fully-qualified     # 🇲🇷 Mauritania
+1F1F2 1F1F8                                ; fully-qualified     # 🇲🇸 Montserrat
+1F1F2 1F1F9                                ; fully-qualified     # 🇲🇹 Malta
+1F1F2 1F1FA                                ; fully-qualified     # 🇲🇺 Mauritius
+1F1F2 1F1FB                                ; fully-qualified     # 🇲🇻 Maldives
+1F1F2 1F1FC                                ; fully-qualified     # 🇲🇼 Malawi
+1F1F2 1F1FD                                ; fully-qualified     # 🇲🇽 Mexico
+1F1F2 1F1FE                                ; fully-qualified     # 🇲🇾 Malaysia
+1F1F2 1F1FF                                ; fully-qualified     # 🇲🇿 Mozambique
+1F1F3 1F1E6                                ; fully-qualified     # 🇳🇦 Namibia
+1F1F3 1F1E8                                ; fully-qualified     # 🇳🇨 New Caledonia
+1F1F3 1F1EA                                ; fully-qualified     # 🇳🇪 Niger
+1F1F3 1F1EB                                ; fully-qualified     # 🇳🇫 Norfolk Island
+1F1F3 1F1EC                                ; fully-qualified     # 🇳🇬 Nigeria
+1F1F3 1F1EE                                ; fully-qualified     # 🇳🇮 Nicaragua
+1F1F3 1F1F1                                ; fully-qualified     # 🇳🇱 Netherlands
+1F1F3 1F1F4                                ; fully-qualified     # 🇳🇴 Norway
+1F1F3 1F1F5                                ; fully-qualified     # 🇳🇵 Nepal
+1F1F3 1F1F7                                ; fully-qualified     # 🇳🇷 Nauru
+1F1F3 1F1FA                                ; fully-qualified     # 🇳🇺 Niue
+1F1F3 1F1FF                                ; fully-qualified     # 🇳🇿 New Zealand
+1F1F4 1F1F2                                ; fully-qualified     # 🇴🇲 Oman
+1F1F5 1F1E6                                ; fully-qualified     # 🇵🇦 Panama
+1F1F5 1F1EA                                ; fully-qualified     # 🇵🇪 Peru
+1F1F5 1F1EB                                ; fully-qualified     # 🇵🇫 French Polynesia
+1F1F5 1F1EC                                ; fully-qualified     # 🇵🇬 Papua New Guinea
+1F1F5 1F1ED                                ; fully-qualified     # 🇵🇭 Philippines
+1F1F5 1F1F0                                ; fully-qualified     # 🇵🇰 Pakistan
+1F1F5 1F1F1                                ; fully-qualified     # 🇵🇱 Poland
+1F1F5 1F1F2                                ; fully-qualified     # 🇵🇲 St. Pierre & Miquelon
+1F1F5 1F1F3                                ; fully-qualified     # 🇵🇳 Pitcairn Islands
+1F1F5 1F1F7                                ; fully-qualified     # 🇵🇷 Puerto Rico
+1F1F5 1F1F8                                ; fully-qualified     # 🇵🇸 Palestinian Territories
+1F1F5 1F1F9                                ; fully-qualified     # 🇵🇹 Portugal
+1F1F5 1F1FC                                ; fully-qualified     # 🇵🇼 Palau
+1F1F5 1F1FE                                ; fully-qualified     # 🇵🇾 Paraguay
+1F1F6 1F1E6                                ; fully-qualified     # 🇶🇦 Qatar
+1F1F7 1F1EA                                ; fully-qualified     # 🇷🇪 Réunion
+1F1F7 1F1F4                                ; fully-qualified     # 🇷🇴 Romania
+1F1F7 1F1F8                                ; fully-qualified     # 🇷🇸 Serbia
+1F1F7 1F1FA                                ; fully-qualified     # 🇷🇺 Russia
+1F1F7 1F1FC                                ; fully-qualified     # 🇷🇼 Rwanda
+1F1F8 1F1E6                                ; fully-qualified     # 🇸🇦 Saudi Arabia
+1F1F8 1F1E7                                ; fully-qualified     # 🇸🇧 Solomon Islands
+1F1F8 1F1E8                                ; fully-qualified     # 🇸🇨 Seychelles
+1F1F8 1F1E9                                ; fully-qualified     # 🇸🇩 Sudan
+1F1F8 1F1EA                                ; fully-qualified     # 🇸🇪 Sweden
+1F1F8 1F1EC                                ; fully-qualified     # 🇸🇬 Singapore
+1F1F8 1F1ED                                ; fully-qualified     # 🇸🇭 St. Helena
+1F1F8 1F1EE                                ; fully-qualified     # 🇸🇮 Slovenia
+1F1F8 1F1EF                                ; fully-qualified     # 🇸🇯 Svalbard & Jan Mayen
+1F1F8 1F1F0                                ; fully-qualified     # 🇸🇰 Slovakia
+1F1F8 1F1F1                                ; fully-qualified     # 🇸🇱 Sierra Leone
+1F1F8 1F1F2                                ; fully-qualified     # 🇸🇲 San Marino
+1F1F8 1F1F3                                ; fully-qualified     # 🇸🇳 Senegal
+1F1F8 1F1F4                                ; fully-qualified     # 🇸🇴 Somalia
+1F1F8 1F1F7                                ; fully-qualified     # 🇸🇷 Suriname
+1F1F8 1F1F8                                ; fully-qualified     # 🇸🇸 South Sudan
+1F1F8 1F1F9                                ; fully-qualified     # 🇸🇹 São Tomé & Príncipe
+1F1F8 1F1FB                                ; fully-qualified     # 🇸🇻 El Salvador
+1F1F8 1F1FD                                ; fully-qualified     # 🇸🇽 Sint Maarten
+1F1F8 1F1FE                                ; fully-qualified     # 🇸🇾 Syria
+1F1F8 1F1FF                                ; fully-qualified     # 🇸🇿 Swaziland
+1F1F9 1F1E6                                ; fully-qualified     # 🇹🇦 Tristan da Cunha
+1F1F9 1F1E8                                ; fully-qualified     # 🇹🇨 Turks & Caicos Islands
+1F1F9 1F1E9                                ; fully-qualified     # 🇹🇩 Chad
+1F1F9 1F1EB                                ; fully-qualified     # 🇹🇫 French Southern Territories
+1F1F9 1F1EC                                ; fully-qualified     # 🇹🇬 Togo
+1F1F9 1F1ED                                ; fully-qualified     # 🇹🇭 Thailand
+1F1F9 1F1EF                                ; fully-qualified     # 🇹🇯 Tajikistan
+1F1F9 1F1F0                                ; fully-qualified     # 🇹🇰 Tokelau
+1F1F9 1F1F1                                ; fully-qualified     # 🇹🇱 Timor-Leste
+1F1F9 1F1F2                                ; fully-qualified     # 🇹🇲 Turkmenistan
+1F1F9 1F1F3                                ; fully-qualified     # 🇹🇳 Tunisia
+1F1F9 1F1F4                                ; fully-qualified     # 🇹🇴 Tonga
+1F1F9 1F1F7                                ; fully-qualified     # 🇹🇷 Turkey
+1F1F9 1F1F9                                ; fully-qualified     # 🇹🇹 Trinidad & Tobago
+1F1F9 1F1FB                                ; fully-qualified     # 🇹🇻 Tuvalu
+1F1F9 1F1FC                                ; fully-qualified     # 🇹🇼 Taiwan
+1F1F9 1F1FF                                ; fully-qualified     # 🇹🇿 Tanzania
+1F1FA 1F1E6                                ; fully-qualified     # 🇺🇦 Ukraine
+1F1FA 1F1EC                                ; fully-qualified     # 🇺🇬 Uganda
+1F1FA 1F1F2                                ; fully-qualified     # 🇺🇲 U.S. Outlying Islands
+1F1FA 1F1F3                                ; fully-qualified     # 🇺🇳 United Nations
+1F1FA 1F1F8                                ; fully-qualified     # 🇺🇸 United States
+1F1FA 1F1FE                                ; fully-qualified     # 🇺🇾 Uruguay
+1F1FA 1F1FF                                ; fully-qualified     # 🇺🇿 Uzbekistan
+1F1FB 1F1E6                                ; fully-qualified     # 🇻🇦 Vatican City
+1F1FB 1F1E8                                ; fully-qualified     # 🇻🇨 St. Vincent & Grenadines
+1F1FB 1F1EA                                ; fully-qualified     # 🇻🇪 Venezuela
+1F1FB 1F1EC                                ; fully-qualified     # 🇻🇬 British Virgin Islands
+1F1FB 1F1EE                                ; fully-qualified     # 🇻🇮 U.S. Virgin Islands
+1F1FB 1F1F3                                ; fully-qualified     # 🇻🇳 Vietnam
+1F1FB 1F1FA                                ; fully-qualified     # 🇻🇺 Vanuatu
+1F1FC 1F1EB                                ; fully-qualified     # 🇼🇫 Wallis & Futuna
+1F1FC 1F1F8                                ; fully-qualified     # 🇼🇸 Samoa
+1F1FD 1F1F0                                ; fully-qualified     # 🇽🇰 Kosovo
+1F1FE 1F1EA                                ; fully-qualified     # 🇾🇪 Yemen
+1F1FE 1F1F9                                ; fully-qualified     # 🇾🇹 Mayotte
+1F1FF 1F1E6                                ; fully-qualified     # 🇿🇦 South Africa
+1F1FF 1F1F2                                ; fully-qualified     # 🇿🇲 Zambia
+1F1FF 1F1FC                                ; fully-qualified     # 🇿🇼 Zimbabwe
+
+# Flags subtotal:		264
+# Flags subtotal:		264	w/o modifiers
+
+#EOF

diff --git a/ibus-HEAD.patch b/ibus-HEAD.patch
index 4038949..6f1dcb0 100644
--- a/ibus-HEAD.patch
+++ b/ibus-HEAD.patch
@@ -5996,11 +5996,17 @@ index 7350dcc..2375734 100644
 -- 
 2.9.3
 
-From 39744bf98c4d6c2677b1e44cdb40cde7d0029a25 Mon Sep 17 00:00:00 2001
+From aba81ace1487bea57e80406413ae31cbb37ac7d2 Mon Sep 17 00:00:00 2001
 From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Wed, 19 Apr 2017 15:47:36 +0900
+Date: Thu, 20 Apr 2017 12:10:47 +0900
 Subject: [PATCH] ui/gtk3: Fix build failures
 
+Add-on fix to 290f786
+if /usr/share/vala*/vapi/ibus-emoji-dialog*.vapi does not exist.
+
+R=Shawn.P.Huang@gmail.com
+
+Review URL: https://codereview.appspot.com/323780043
 ---
  ui/gtk3/Makefile.am | 8 +-------
  1 file changed, 1 insertion(+), 7 deletions(-)
@@ -6027,3 +6033,3939 @@ index 6f0fb62..d2ae0d6 100644
 -- 
 2.9.3
 
+From 61fa8eabd812a75b3cadd883ad4a4e92cf6877d3 Mon Sep 17 00:00:00 2001
+From: fujiwarat <takao.fujiwara1@gmail.com>
+Date: Tue, 25 Apr 2017 12:10:00 +0900
+Subject: [PATCH] ui/gtk3: Get emoji font size from gsettings
+
+If Emojier CLI does not specify the font size likes
+--font 'Noto Emoji Color Regular', get the default size from GSettings.
+
+R=Shawn.P.Huang@gmail.com, alexepico@gmail.com
+
+Review URL: https://codereview.appspot.com/317540043
+---
+ setup/setup.ui          |  2 +-
+ ui/gtk3/emojier.vala    | 41 ++++++++++++++++++++++++++---------------
+ ui/gtk3/emojierapp.vala | 14 ++++++++++----
+ ui/gtk3/panel.vala      |  2 +-
+ 4 files changed, 38 insertions(+), 21 deletions(-)
+
+diff --git a/setup/setup.ui b/setup/setup.ui
+index 4ef3423..54ef916 100644
+--- a/setup/setup.ui
++++ b/setup/setup.ui
+@@ -137,7 +137,7 @@
+                             <property name="can_focus">False</property>
+                             <property name="tooltip_text" translatable="yes">The shortcut keys for showing emoji dialog</property>
+                             <property name="halign">start</property>
+-                            <property name="label" translatable="yes">Emoji dialog:</property>
++                            <property name="label" translatable="yes">Emoji choice:</property>
+                           </object>
+                           <packing>
+                             <property name="top_attach">5</property>
+diff --git a/ui/gtk3/emojier.vala b/ui/gtk3/emojier.vala
+index 5a9bf8f..76dca6c 100644
+--- a/ui/gtk3/emojier.vala
++++ b/ui/gtk3/emojier.vala
+@@ -166,13 +166,14 @@ class IBusEmojier : Gtk.Window {
+         BACKWARD,
+     }
+ 
+-    private static const uint EMOJI_GRID_PAGE = 10;
++    private const uint EMOJI_GRID_PAGE = 10;
+ 
+     // Set the actual default values in the constructor
+     // because these fields are used for class_init() and static functions,
+     // e.g. set_emoji_font(), can be called before class_init() is called.
+     private static string m_current_lang_id;
+-    private static string m_emoji_font;
++    private static string m_emoji_font_family;
++    private static int m_emoji_font_size;
+     private static string[] m_favorites;
+     private static int m_emoji_max_seq_len;
+     private static GLib.HashTable<string, GLib.SList>?
+@@ -220,8 +221,10 @@ class IBusEmojier : Gtk.Window {
+ 
+         if (m_current_lang_id == null)
+             m_current_lang_id = "en";
+-        if (m_emoji_font == null)
+-            m_emoji_font = "Monospace 16";
++        if (m_emoji_font_family == null)
++            m_emoji_font_family = "Monospace";
++        if (m_emoji_font_size == 0)
++            m_emoji_font_size = 16;
+         if (m_favorites == null)
+             m_favorites = {};
+ 
+@@ -242,6 +245,8 @@ class IBusEmojier : Gtk.Window {
+                 "#IBusEmojierWhiteLabel { background-color: " +
+                         "rgba(%u, %u, %u, %lf); ".printf(
+                         bg_red, bg_green, bg_blue, bg_alpha) +
++                "font-family: %s; font-size: %dpt; ".printf(
++                        m_emoji_font_family, m_emoji_font_size) +
+                 "border-width: 4px; border-radius: 3px; } ";
+ 
+         uint fg_red = (uint)(m_rgba.selected_fg.red * 255);
+@@ -255,6 +260,8 @@ class IBusEmojier : Gtk.Window {
+         data += "#IBusEmojierSelectedLabel { color: " +
+                         "rgba(%u, %u, %u, %lf); ".printf(
+                         fg_red, fg_green, fg_blue, fg_alpha) +
++                "font-family: %s; font-size: %dpt; ".printf(
++                        m_emoji_font_family, m_emoji_font_size) +
+                 "background-color: " +
+                         "rgba(%u, %u, %u, %lf); ".printf(
+                         bg_red, bg_green, bg_blue, bg_alpha) +
+@@ -273,7 +280,7 @@ class IBusEmojier : Gtk.Window {
+                 css_provider,
+                 Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
+ 
+-        m_title = new ETitleLabelBox(_("Emoji Chooser"));
++        m_title = new ETitleLabelBox(_("Emoji Choice"));
+         set_titlebar(m_title);
+         m_vbox = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
+         add(m_vbox);
+@@ -734,17 +741,14 @@ class IBusEmojier : Gtk.Window {
+                 label = new ESelectedLabel(candidate.text) as Gtk.Label;
+             else
+                 label = new EWhiteLabel(candidate.text) as Gtk.Label;
+-            string emoji_font = m_emoji_font;
+             if (candidate.text.char_count() > 2) {
+-                Pango.FontDescription font_desc =
+-                        Pango.FontDescription.from_string(emoji_font);
+-                string font_family = font_desc.get_family();
+-                int font_size = font_desc.get_size() / Pango.SCALE;
+-                emoji_font = "%s %d".printf(font_family, font_size -2);
++                string font_family = m_emoji_font_family;
++                int font_size = m_emoji_font_size - 2;
++                string emoji_font = "%s %d".printf(font_family, font_size);
++                string markup = "<span font=\"%s\">%s</span>".
++                        printf(emoji_font, candidate.get_text());
++                label.set_markup(markup);
+             }
+-            string markup = "<span font=\"%s\">%s</span>".
+-                    printf(emoji_font, candidate.get_text());
+-            label.set_markup(markup);
+             label.set_halign(Gtk.Align.FILL);
+             label.set_valign(Gtk.Align.FILL);
+             Gtk.EventBox candidate_ebox = new Gtk.EventBox();
+@@ -1268,7 +1272,14 @@ class IBusEmojier : Gtk.Window {
+ 
+     public static void set_emoji_font(string? emoji_font) {
+         return_if_fail(emoji_font != null && emoji_font != "");
+-        m_emoji_font = emoji_font;
++        Pango.FontDescription font_desc =
++                Pango.FontDescription.from_string(emoji_font);
++        string font_family = font_desc.get_family();
++        if (font_family != null)
++            m_emoji_font_family = font_family;
++        int font_size = font_desc.get_size() / Pango.SCALE;
++        if (font_size != 0)
++            m_emoji_font_size = font_size;
+     }
+ 
+ 
+diff --git a/ui/gtk3/emojierapp.vala b/ui/gtk3/emojierapp.vala
+index 4564a25..cbdd8ba 100644
+--- a/ui/gtk3/emojierapp.vala
++++ b/ui/gtk3/emojierapp.vala
+@@ -60,6 +60,9 @@ public class EmojiApplication : Application {
+ 
+ 
+     private int _command_line (ApplicationCommandLine command_line) {
++        // Set default font size
++        IBusEmojier.set_emoji_font(m_settings_emoji.get_string("font"));
++
+         const OptionEntry[] options = {
+             { "font", 0, 0, OptionArg.STRING, out emoji_font,
+                 /* TRANSLATORS: "FONT" should be capital and translatable.
+@@ -88,6 +91,10 @@ public class EmojiApplication : Application {
+             _args[i] = args[i];
+         }
+ 
++        // Need to initialize for the second instance.
++        emoji_font = null;
++        annotation_lang = null;
++
+         try {
+             unowned string[] tmp = _args;
+             option.parse(ref tmp);
+@@ -101,13 +108,12 @@ public class EmojiApplication : Application {
+             return Posix.EXIT_SUCCESS;
+         }
+ 
+-        if (emoji_font == null)
+-            emoji_font = m_settings_emoji.get_string("font");
+         if (annotation_lang == null)
+             annotation_lang = m_settings_emoji.get_string("lang");
+-
+         IBusEmojier.set_annotation_lang(annotation_lang);
+-        IBusEmojier.set_emoji_font(emoji_font);
++
++        if (emoji_font != null)
++            IBusEmojier.set_emoji_font(emoji_font);
+ 
+         activate_dialog(command_line);
+ 
+diff --git a/ui/gtk3/panel.vala b/ui/gtk3/panel.vala
+index 2375734..745489b 100644
+--- a/ui/gtk3/panel.vala
++++ b/ui/gtk3/panel.vala
+@@ -1239,7 +1239,7 @@ class Panel : IBus.PanelService {
+             m_sys_menu.append(item);
+ 
+ #if EMOJI_DICT
+-            item = new Gtk.MenuItem.with_label(_("Emoji Dialog"));
++            item = new Gtk.MenuItem.with_label(_("Emoji Choice"));
+             item.activate.connect((i) => {
+                 Gdk.Event event = new Gdk.Event(Gdk.EventType.KEY_PRESS);
+                 handle_emoji_typing(event);
+-- 
+2.9.3
+
+From 2f73064d03481c9f34d278dd19d1a4427d6ecb27 Mon Sep 17 00:00:00 2001
+From: fujiwarat <takao.fujiwara1@gmail.com>
+Date: Fri, 28 Apr 2017 13:10:03 +0900
+Subject: [PATCH] Change to use Unicode Emoji files instead of EmojiOne
+ files
+
+EmojiOne Json file have changed the file format since 3.0 [1]
+Now IBus migrated to use Unicode Emoji files since the EmojiOne file
+had been used for the emoji categories but it can be done with
+Unicode emoji-test.txt [2]
+Use Unicode Emoji 4.0 until 5.0 will be released officially.
+Unicode Emoji 5.0 is available but fonts does not support it yet.
+
+[1] https://github.com/Ranks/emojione/releases/tag/v3.0.0
+[2] http://www.unicode.org/Public/emoji/4.0/
+
+Review URL: https://codereview.appspot.com/321860043
+---
+ bindings/vala/Makefile.am     |   3 +-
+ configure.ac                  |  27 +-
+ data/annotations/Makefile.am  |   3 +-
+ data/annotations/en_ascii.xml |  56 ++++
+ po/POTFILES.in                |   3 +-
+ po/POTFILES.skip              |   2 +-
+ src/Makefile.am               |  17 +-
+ src/emoji-parser.c            | 632 ++++++++++++++++++++++++++++++++++++++----
+ src/ibusemoji.c               |  47 +---
+ src/ibusemoji.h               |  14 -
+ src/ibusemojigen.h            |  39 +++
+ ui/gtk3/Makefile.am           |   5 +-
+ ui/gtk3/emojier.vala          | 106 +++++--
+ 13 files changed, 780 insertions(+), 174 deletions(-)
+ create mode 100644 data/annotations/en_ascii.xml
+ create mode 100644 src/ibusemojigen.h
+
+diff --git a/bindings/vala/Makefile.am b/bindings/vala/Makefile.am
+index f3eb0d4..4e34afc 100644
+--- a/bindings/vala/Makefile.am
++++ b/bindings/vala/Makefile.am
+@@ -43,8 +43,7 @@ vapidir = $(datadir)/vala/vapi
+ vapi_DATA = $(VAPIGEN_VAPIS) $(VAPIGEN_VAPIS:.vapi=.deps)
+ 
+ MAINTAINERCLEANFILES = $(VAPIGEN_VAPIS)
+-# for make distclean
+-CONFIG_CLEAN_FILES = $(VAPIGEN_VAPIS)
++DISTCLEANFILES = $(VAPIGEN_VAPIS)
+ 
+ EXTRA_DIST = \
+ 	$(VAPIGEN_VAPIS) \
+diff --git a/configure.ac b/configure.ac
+index 0a5f2d5..ea568a0 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -612,14 +612,14 @@ AC_ARG_ENABLE(emoji-dict,
+ )
+ AM_CONDITIONAL([ENABLE_EMOJI_DICT], [test x"$enable_emoji_dict" = x"yes"])
+ 
+-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_ARG_WITH(unicode-emoji-dir,
++    AS_HELP_STRING([--with-unicode-emoji-dir[=DIR]],
++        [Set the directory of Unicode Emoji.
++         (default: "/usr/share/unicode/emoji")]),
++    UNICODE_EMOJI_DIR=$with_unicode_emoji_dir,
++    UNICODE_EMOJI_DIR="/usr/share/unicode/emoji"
+ )
+-AC_SUBST(EMOJI_JSON_FILE)
++AC_SUBST(UNICODE_EMOJI_DIR)
+ 
+ AC_ARG_WITH(emoji-annotation-dir,
+     AS_HELP_STRING([--with-emoji-annotation-dir[=DIR]],
+@@ -631,17 +631,14 @@ AC_ARG_WITH(emoji-annotation-dir,
+ AC_SUBST(EMOJI_ANNOTATION_DIR)
+ 
+ if test x"$enable_emoji_dict" = x"yes"; then
+-    if test ! -f $EMOJI_JSON_FILE ; then
+-        AC_MSG_ERROR(Not found $EMOJI_JSON_FILE. You can get emoji.json \
+-with "npm install -g emojione".)
++    if test ! -f $UNICODE_EMOJI_DIR/emoji-test.txt ; then
++        AC_MSG_ERROR(Not found $UNICODE_EMOJI_DIR/emoji-test.txt. You can get \
++the emoji files from http://www.unicode.org/Public/emoji/4.0/)
+     fi
+     if test ! -f $EMOJI_ANNOTATION_DIR/en.xml ; then
+         AC_MSG_ERROR(Not found $EMOJI_ANNOTATION_DIR/en.xml. You can get \
+ https://github.com/fujiwarat/cldr-emoji-annotation)
+     fi
+-    PKG_CHECK_MODULES(JSON_GLIB1, [
+-        json-glib-1.0
+-    ])
+     enable_emoji_dict="yes (enabled, use --disable-emoji-dict to disable)"
+ fi
+ 
+@@ -730,8 +727,8 @@ Build options:
+   Enable surrounding-text       $enable_surrounding_text
+   Enable libnotify              $enable_libnotify
+   Enable Emoji dict             $enable_emoji_dict
+-  emoji.json path               $EMOJI_JSON_FILE
+-  CLDR annotation dir           $EMOJI_ANNOTATION_DIR
++  Uicode Emoji directory        $UNICODE_EMOJI_DIR
++  CLDR annotation directory     $EMOJI_ANNOTATION_DIR
+   Run test cases                $enable_tests
+ ])
+ 
+diff --git a/data/annotations/Makefile.am b/data/annotations/Makefile.am
+index d87b933..0b7779b 100644
+--- a/data/annotations/Makefile.am
++++ b/data/annotations/Makefile.am
+@@ -2,7 +2,7 @@
+ #
+ # ibus - The Input Bus
+ #
+-# Copyright (c) 2016 Takao Fujiwara <takao.fujiwara1@gmail.com>
++# Copyright (c) 2016-2017 Takao Fujiwara <takao.fujiwara1@gmail.com>
+ # Copyright (c) 2016 Red Hat, Inc.
+ #
+ # This library is free software; you can redistribute it and/or
+@@ -22,6 +22,7 @@
+ 
+ EXTRA_DIST = \
+ 	en.xml \
++	en_ascii.xml \
+ 	$(NULL)
+ 
+ -include $(top_srcdir)/git.mk
+diff --git a/data/annotations/en_ascii.xml b/data/annotations/en_ascii.xml
+new file mode 100644
+index 0000000..f1bdcbb
+--- /dev/null
++++ b/data/annotations/en_ascii.xml
+@@ -0,0 +1,56 @@
++<?xml version='1.0' encoding='UTF-8' ?>
++<!DOCTYPE ldml SYSTEM '../../common/dtd/ldml.dtd'>
++<!-- vim:set et sts=4: -->
++<!--
++    Copyright (C) 2017 Takao Fujiwara <takao.fujiwara1@gmail.com>
++    Copyright (C) 2017 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
++ -->
++<ldml>
++    <identity>
++        <version number="$Revision: 1 $"/>
++        <language type='en'/>
++    </identity>
++    <annotations>
++        <annotation cp="😂">:') | :'-)</annotation>
++        <annotation cp="😃">:D | :-D | =D</annotation>
++        <annotation cp="😅">':) | ':-) | '=) | ':D | ':-D | '=D</annotation>
++        <annotation cp="😆">&gt;:) | &gt;;) | &gt;:-) | &gt;=)</annotation>
++        <annotation cp="😉">;) | ;-) | *-) | *) | ;-] | ;] | ;D | ;^)</annotation>
++        <annotation cp="😎">B-) | B) | 8) | 8-) | B-D | 8-D</annotation>
++        <annotation cp="😘">:* | :-* | =* | :^*</annotation>
++        <annotation cp="🙂">:) | :-) | =] | =) | :]</annotation>
++        <annotation cp="😑">-_- | -__- | -___-</annotation>
++        <annotation cp="😶">:-X | :X | :-# | :# | =X | =x | :x | :-x | =#</annotation>
++        <annotation cp="😣">&gt;.&lt;</annotation>
++        <annotation cp="😮">:-O | :O | :-o | :o | O_O | &gt;:O</annotation>
++        <annotation cp="😛">:P | :-P | =P | :-p | :p | =p | :-Þ | :Þ | :þ | :-þ | :-b | :b | d:</annotation>
++        <annotation cp="😜">&gt;:P | X-P | x-p</annotation>
++        <annotation cp="😓">':( | ':-( | '=(</annotation>
++        <annotation cp="😕">&gt;:\ | &gt;:/ | :-/ | :-. | :/ | :\ | =/ | =\ | :L | =L</annotation>
++        <annotation cp="😞">&gt;:[ | :-( | :( | :-[ | :[ | =(</annotation>
++        <annotation cp="😢">:'( | :'-( | ;( | ;-(</annotation>
++        <annotation cp="😨">D:</annotation>
++        <annotation cp="😳">:$ | =$</annotation>
++        <annotation cp="😵">#-) | #) | %-) | %) | X) | X-)</annotation>
++        <annotation cp="😠">&gt;:( | &gt;:-( | :@</annotation>
++        <annotation cp="😇">O:-) | 0:-3 | 0:3 | 0:-) | 0:) | 0;^) | O:) | O;-) | O=) | 0;-) | O:-3 | O:3</annotation>
++        <annotation cp="🙆">*\0/* | \0/ | *\O/* | \O/</annotation>
++        <annotation cp="❤">&lt;3</annotation>
++        <annotation cp="💔">&lt;/3</annotation>
++    </annotations>
++</ldml>
+diff --git a/po/POTFILES.in b/po/POTFILES.in
+index 25be4f4..00f7c7f 100644
+--- a/po/POTFILES.in
++++ b/po/POTFILES.in
+@@ -41,6 +41,7 @@ setup/keyboardshortcut.py
+ setup/main.py
+ src/ibusbus.c
+ src/ibusconfig.c
++src/ibusemojigen.h
+ src/ibusengine.c
+ src/ibusfactory.c
+ src/ibushotkey.c
+@@ -57,6 +58,7 @@ ui/gtk3/application.vala
+ ui/gtk3/candidatearea.vala
+ ui/gtk3/candidatepanel.vala
+ ui/gtk3/emojier.vala
++ui/gtk3/emojierapp.vala
+ ui/gtk3/handle.vala
+ ui/gtk3/iconwidget.vala
+ ui/gtk3/keybindingmanager.vala
+@@ -66,4 +68,3 @@ ui/gtk3/property.vala
+ ui/gtk3/propertypanel.vala
+ ui/gtk3/separator.vala
+ ui/gtk3/switcher.vala
+-ui/gtk3/emojierapp.vala
+diff --git a/po/POTFILES.skip b/po/POTFILES.skip
+index 891d2cc..7190221 100644
+--- a/po/POTFILES.skip
++++ b/po/POTFILES.skip
+@@ -12,6 +12,7 @@ ui/gtk3/application.c
+ ui/gtk3/candidatearea.c
+ ui/gtk3/candidatepanel.c
+ ui/gtk3/emojier.c
++ui/gtk3/emojierapp.c
+ ui/gtk3/handle.c
+ ui/gtk3/iconwidget.c
+ ui/gtk3/keybindingmanager.c
+@@ -21,4 +22,3 @@ ui/gtk3/property.c
+ ui/gtk3/propertypanel.c
+ ui/gtk3/separator.c
+ ui/gtk3/switcher.c
+-ui/gtk3/emojierapp.c
+diff --git a/src/Makefile.am b/src/Makefile.am
+index 7053e3e..27cd168 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -166,6 +166,7 @@ ibusinclude_HEADERS =       \
+ ibus_private_headers =          \
+     gtkimcontextsimpleseqs.h    \
+     ibuscomposetable.h          \
++    ibusemojigen.h              \
+     ibusenginesimpleprivate.h   \
+     ibusinternal.h              \
+     keyname-table.h             \
+@@ -247,17 +248,26 @@ dicts/emoji-en.dict: emoji-parser
+ 	    echo "WARNING: Not found $(EMOJI_ANNOTATION_DIR)/en.xml" 1>&2; \
+ 	fi; \
+ 	for f in $(LANG_FILES) ; do \
++	    if test -f \
++	    "$(EMOJI_ANNOTATION_DIR)/../annotationsDerived/$$f.xml" ; then \
++	        xml_derived_option="--xml-derived $(EMOJI_ANNOTATION_DIR)/../annotationsDerived/$$f.xml"; \
++	        plus_comment="derived"; \
++	    fi; \
+ 	    if test x"$$f" = xen ; then \
+ 	        $(builddir)/emoji-parser \
++	            --unicode-emoji-dir $(UNICODE_EMOJI_DIR) \
+ 	            --xml $(EMOJI_ANNOTATION_DIR)/$$f.xml \
+-	            --json $(EMOJI_JSON_FILE) \
++	            $$xml_derived_option \
++	            --xml-ascii $(top_srcdir)/data/annotations/en_ascii.xml \
++	            --out-category ibusemojigen.h \
+ 	            --out $@; \
+ 	    else \
+ 	        $(builddir)/emoji-parser \
+ 	            --xml $(EMOJI_ANNOTATION_DIR)/$$f.xml \
++	            $$xml_derived_option \
+ 	            --out dicts/emoji-$$f.dict; \
+ 	    fi; \
+-	    echo "Generated dicts/emoji-$$f.dict"; \
++	    echo "Generated $$plus_comment dicts/emoji-$$f.dict"; \
+ 	done
+ 
+ install-data-hook: $(dict_DATA)
+@@ -301,11 +311,9 @@ emoji_parser_SOURCES =          \
+     $(NULL)
+ emoji_parser_CFLAGS =           \
+     $(GLIB2_CFLAGS)             \
+-    $(JSON_GLIB1_CFLAGS)        \
+     $(NULL)
+ emoji_parser_LDADD =            \
+     $(GLIB2_LIBS)               \
+-    $(JSON_GLIB1_LIBS)          \
+     $(libibus)                  \
+     $(NULL)
+ 
+@@ -329,6 +337,7 @@ CLEANFILES +=                   \
+     $(NULL)
+ 
+ DISTCLEANFILES =                \
++    ibusemojigen.h              \
+     ibusversion.h               \
+     $(NULL)
+ 
+diff --git a/src/emoji-parser.c b/src/emoji-parser.c
+index e5dce3f..5e6155b 100644
+--- a/src/emoji-parser.c
++++ b/src/emoji-parser.c
+@@ -21,34 +21,52 @@
+  */
+ 
+ /* Convert /usr/share/unicode/cldr/common/annotations/\*.xml and
+- * /usr/lib/node_modules/emojione/emoji.json
++ * /usr/share/unicode/emoji/emoji-test.txt
+  * to the dictionary file which look up the Emoji from the annotation.
+  * Get *.xml from https://github.com/fujiwarat/cldr-emoji-annotation
+  * or http://www.unicode.org/repos/cldr/trunk/common/annotations .
+- * 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".
++ * Get emoji-test.txt from http://unicode.org/Public/emoji/4.0/ .
++ * en.xml is used for the Unicode annotations and emoji-test.txt is used
++ * for the category, e.g. "Smileys & People".
++ * ASCII emoji annotations are saved in ../data/annotations/en_ascii.xml
+  */
+ 
+ #include <glib.h>
++
++#ifdef HAVE_JSON_GLIB1
+ #include <json-glib/json-glib.h>
++#endif
+ 
+ #include <string.h>
+ 
+ #include "ibusemoji.h"
+ 
++/* This file has 21 lines about the license at the top of the file. */
++#define LICENSE_LINES 21
++
++typedef enum {
++  EMOJI_STRICT,
++  EMOJI_VARIANT,
++  EMOJI_NOVARIANT
++} EmojiDataSearchType;
++
+ typedef struct _EmojiData EmojiData;
+ struct _EmojiData {
+-    gchar      *emoji;
+-    gchar      *emoji_alternates;
+-    GSList     *annotations;
+-    gboolean    is_annotation;
+-    gchar      *description;
+-    gboolean    is_tts;
+-    gchar      *category;
+-    GSList     *list;
++    gchar              *emoji;
++    gchar              *emoji_alternates;
++    GSList             *annotations;
++    gboolean            is_annotation;
++    gchar              *description;
++    gboolean            is_tts;
++    gchar              *category;
++    gchar              *subcategory;
++    gboolean            is_derived;
++    GSList             *list;
++    EmojiDataSearchType search_type;
+ };
+ 
++static gchar *unicode_emoji_version;
++
+ static void
+ reset_emoji_element (EmojiData *data)
+ {
+@@ -59,68 +77,175 @@ reset_emoji_element (EmojiData *data)
+     g_slist_free_full (data->annotations, g_free);
+     data->annotations = NULL;
+     g_clear_pointer (&data->description, g_free);
+-    g_clear_pointer (&data->category, g_free);
++}
++
++gint
++strcmp_novariant (const gchar *a,
++                  const gchar *b,
++                  gunichar     a_variant,
++                  gunichar     b_variant)
++{
++    gint retval;
++    gchar *p = NULL;
++    GString *buff = NULL;;
++    gchar *substr = NULL;
++
++    if (a_variant > 0) {
++        if ((p = g_utf8_strchr (a, -1, a_variant)) != NULL) {
++            buff = g_string_new (NULL);
++            if (a != p) {
++                substr = g_strndup (a, p - a);
++                g_string_append (buff, substr);
++                g_free (substr);
++            }
++            p = g_utf8_next_char (p);
++            if (*p != '\0')
++                g_string_append (buff, p);
++            retval = g_strcmp0 (buff->str, b);
++            g_string_free (buff, TRUE);
++            return retval;
++        } else {
++            return -1;
++        }
++    } else if (b_variant > 0) {
++        if ((p = g_utf8_strchr (b, -1, b_variant)) != NULL) {
++            buff = g_string_new (NULL);
++            if (b != p) {
++                substr = g_strndup (b, p - b);
++                g_string_append (buff, substr);
++                g_free (substr);
++            }
++            p = g_utf8_next_char (p);
++            if (*p != '\0')
++                g_string_append (buff, p);
++            retval = g_strcmp0 (a, buff->str);
++            g_string_free (buff, TRUE);
++            return retval;
++        } else {
++            return -1;
++        }
++    }
++    return g_strcmp0 (a, b);
+ }
+ 
+ gint
+ find_emoji_data_list (IBusEmojiData *a,
+-                      const gchar   *b)
++                      EmojiData     *b)
+ {
+-   g_return_val_if_fail (IBUS_IS_EMOJI_DATA (a), 0);
+-   return g_strcmp0 (ibus_emoji_data_get_emoji (a), b);
++    const gchar *a_str;
++
++    g_return_val_if_fail (IBUS_IS_EMOJI_DATA (a), 0);
++
++    a_str = ibus_emoji_data_get_emoji (a);
++    switch (b->search_type) {
++    case EMOJI_VARIANT:
++        if (strcmp_novariant (a_str, b->emoji, 0xfe0e, 0) == 0)
++            return 0;
++        else if (strcmp_novariant (a_str, b->emoji, 0xfe0f, 0) == 0)
++            return 0;
++        else
++            return g_strcmp0 (a_str, b->emoji);
++        break;
++    case EMOJI_NOVARIANT:
++        if (strcmp_novariant (a_str, b->emoji, 0, 0xfe0e) == 0)
++            return 0;
++        else if (strcmp_novariant (a_str, b->emoji, 0, 0xfe0f) == 0)
++            return 0;
++        else
++            return g_strcmp0 (a_str, b->emoji);
++        break;
++    default:;
++    }
++    return g_strcmp0 (a_str, b->emoji);
+ }
+ 
+ static void
+-update_emoji_list (EmojiData *data)
++emoji_data_update_object (EmojiData     *data,
++                          IBusEmojiData *emoji)
+ {
+-    GSList *list = g_slist_find_custom (
+-            data->list,
+-            data->emoji,
+-            (GCompareFunc) find_emoji_data_list);
+-    if (list) {
+-        IBusEmojiData *emoji = list->data;
+-        GSList *src_annotations = data->annotations;
+-        GSList *dest_annotations = ibus_emoji_data_get_annotations (emoji);
+-        GSList *l;
+-        gboolean updated_annotations = FALSE;
+-        for (l = src_annotations; l; l = l->next) {
+-            GSList *duplicated = g_slist_find_custom (dest_annotations,
+-                                                      l->data,
+-                                                      (GCompareFunc) g_strcmp0);
+-            if (duplicated == NULL) {
+-                dest_annotations = g_slist_append (dest_annotations,
+-                                                   g_strdup (l->data));
+-                updated_annotations = TRUE;
+-            }
++    GSList *src_annotations = data->annotations;
++    GSList *dest_annotations = ibus_emoji_data_get_annotations (emoji);
++    GSList *l;
++    gboolean updated_annotations = FALSE;
++    for (l = src_annotations; l; l = l->next) {
++        GSList *duplicated = g_slist_find_custom (dest_annotations,
++                                                  l->data,
++                                                  (GCompareFunc) g_strcmp0);
++        if (duplicated == NULL) {
++            dest_annotations = g_slist_append (dest_annotations,
++                                               g_strdup (l->data));
++            updated_annotations = TRUE;
+         }
+-        if (updated_annotations) {
+-            ibus_emoji_data_set_annotations (
++    }
++    if (updated_annotations) {
++        ibus_emoji_data_set_annotations (
+                     emoji,
+                     g_slist_copy_deep (dest_annotations,
+                                        (GCopyFunc) g_strdup,
+                                        NULL));
++    }
++    if (data->description)
++        ibus_emoji_data_set_description (emoji, data->description);
++}
++
++static void
++emoji_data_new_object (EmojiData *data)
++{
++    IBusEmojiData *emoji =
++            ibus_emoji_data_new ("emoji",
++                                 data->emoji,
++                                 "annotations",
++                                 data->annotations,
++                                 "description",
++                                 data->description ? data->description
++                                         : g_strdup (""),
++                                 "category",
++                                 data->category ? data->category
++                                         : g_strdup (""),
++                                 NULL);
++    data->list = g_slist_append (data->list, emoji);
++}
++
++static void
++update_emoji_list (EmojiData *data,
++                   gboolean   base_update)
++{
++    GSList *list;
++    data->search_type = EMOJI_STRICT;
++    list = g_slist_find_custom (
++            data->list,
++            data,
++            (GCompareFunc) find_emoji_data_list);
++    if (list) {
++        emoji_data_update_object (data, list->data);
++        return;
++    } else if (base_update) {
++        emoji_data_new_object (data);
++        return;
++    }
++    if (g_utf8_strchr (data->emoji, -1, 0xfe0e) == NULL &&
++        g_utf8_strchr (data->emoji, -1, 0xfe0f) == NULL) {
++        data->search_type = EMOJI_VARIANT;
++        list = g_slist_find_custom (
++                data->list,
++                data,
++                (GCompareFunc) find_emoji_data_list);
++        if (list) {
++            emoji_data_update_object (data, list->data);
++            return;
+         }
+-        if (data->description)
+-            ibus_emoji_data_set_description (emoji, data->description);
+     } else {
+-        IBusEmojiData *emoji =
+-                ibus_emoji_data_new ("emoji",
+-                                     data->emoji,
+-                                     "annotations",
+-                                     data->annotations,
+-                                     "description",
+-                                     data->description ? data->description
+-                                             : g_strdup (""),
+-                                     "category",
+-                                     data->category ? data->category
+-                                             : g_strdup (""),
+-                                     "emoji-alternates",
+-                                     data->emoji_alternates
+-                                             ? data->emoji_alternates
+-                                             : g_strdup (""),
+-                                     NULL);
+-        data->list = g_slist_append (data->list, emoji);
++        data->search_type = EMOJI_NOVARIANT;
++        list = g_slist_find_custom (
++                data->list,
++                data,
++                (GCompareFunc) find_emoji_data_list);
++        if (list) {
++            emoji_data_update_object (data, list->data);
++            return;
++        }
+     }
++    emoji_data_new_object (data);
+ }
+ 
+ static void
+@@ -183,7 +308,7 @@ unicode_annotations_end_element_cb (GMarkupParseContext *context,
+     if (!data->is_annotation)
+         return;
+ 
+-    update_emoji_list (data);
++    update_emoji_list (data, FALSE);
+     data->is_annotation = FALSE;
+     data->is_tts = FALSE;
+ }
+@@ -227,7 +352,8 @@ unicode_annotations_text_cb (GMarkupParseContext *context,
+ 
+ static gboolean
+ unicode_annotations_parse_xml_file (const gchar  *filename,
+-                                    GSList      **list)
++                                    GSList      **list,
++                                    gboolean      is_derived)
+ {
+     gchar *content = NULL;
+     gsize length = 0;
+@@ -251,6 +377,7 @@ unicode_annotations_parse_xml_file (const gchar  *filename,
+     }
+ 
+     data.list = *list;
++    data.is_derived = is_derived;
+ 
+     context = g_markup_parse_context_new (&parser, 0, &data, NULL);
+     if (!g_markup_parse_context_parse (context, content, length, &error)) {
+@@ -276,6 +403,233 @@ failed_to_parse_unicode_annotations:
+ }
+ 
+ static gboolean
++unicode_emoji_test_parse_unicode (const gchar *line,
++                                  EmojiData   *data)
++{
++    GString *emoji = NULL;
++    gchar *endptr = NULL;
++    guint32 uch;
++    static gchar outbuf[8] = { 0, };
++
++    g_return_val_if_fail (line != NULL, FALSE);
++
++    emoji = g_string_new (NULL);
++    while (line && *line) {
++        uch = g_ascii_strtoull (line, &endptr, 16);
++        outbuf[g_unichar_to_utf8 (uch, outbuf)] = '\0';
++        g_string_append (emoji, outbuf);
++        if (*endptr == '\0') {
++            break;
++        }
++        line = endptr + 1;
++        while (*line == ' ')
++            line++;
++        endptr = NULL;
++    }
++
++    data->emoji = g_string_free (emoji, FALSE);
++    return TRUE;
++}
++
++static gboolean
++unicode_emoji_test_parse_description (const gchar *line,
++                                      EmojiData   *data)
++{
++    g_return_val_if_fail (line != NULL, FALSE);
++
++    /* skip spaces */
++    while (*line == ' ')
++        line++;
++    /* skip emoji */
++    while (*line != ' ')
++        line++;
++    /* skip spaces */
++    while (*line == ' ')
++        line++;
++    if (*line == '\0')
++        return FALSE;
++    data->description = g_strdup (line);
++    return TRUE;
++}
++
++#define EMOJI_VERSION_TAG "# Version: "
++#define EMOJI_GROUP_TAG "# group: "
++#define EMOJI_SUBGROUP_TAG "# subgroup: "
++#define EMOJI_NON_FULLY_QUALIFIED_TAG "non-fully-qualified"
++
++static gboolean
++unicode_emoji_test_parse_line (const gchar *line,
++                               EmojiData   *data)
++{
++    int tag_length;
++    gchar **segments = NULL;
++
++    g_return_val_if_fail (line != NULL, FALSE);
++
++    tag_length = strlen (EMOJI_VERSION_TAG);
++    if (strlen (line) > tag_length &&
++        g_ascii_strncasecmp (line, EMOJI_VERSION_TAG, tag_length) == 0) {
++        unicode_emoji_version = g_strdup (line + tag_length);
++        return TRUE;
++    }
++    tag_length = strlen (EMOJI_GROUP_TAG);
++    if (strlen (line) > tag_length &&
++        g_ascii_strncasecmp (line, EMOJI_GROUP_TAG, tag_length) == 0) {
++        g_free (data->category);
++        g_clear_pointer (&data->subcategory, g_free);
++        data->category = g_strdup (line + tag_length);
++        return TRUE;
++    }
++    tag_length = strlen (EMOJI_SUBGROUP_TAG);
++    if (strlen (line) > tag_length &&
++        g_ascii_strncasecmp (line, EMOJI_SUBGROUP_TAG, tag_length) == 0) {
++        g_free (data->subcategory);
++        data->subcategory = g_strdup (line + tag_length);
++        return TRUE;
++    }
++    if (*line == '#')
++        return TRUE;
++    segments = g_strsplit (line, "; ", 2);
++    if (segments[1] == NULL) {
++        g_warning ("No qualified line\n");
++        goto failed_to_parse_unicode_emoji_test_line;
++        return FALSE;
++    }
++    tag_length = strlen (EMOJI_NON_FULLY_QUALIFIED_TAG);
++    /* Ignore the non-fully-qualified emoji */
++    if (g_ascii_strncasecmp (segments[1], EMOJI_NON_FULLY_QUALIFIED_TAG,
++                             tag_length) == 0) {
++        g_strfreev (segments);
++        return TRUE;
++    }
++    unicode_emoji_test_parse_unicode (segments[0], data);
++    g_strfreev (segments);
++    segments = g_strsplit (line, "# ", 2);
++    if (segments[1] == NULL) {
++        g_warning ("No description line\n");
++        goto failed_to_parse_unicode_emoji_test_line;
++        return FALSE;
++    }
++    unicode_emoji_test_parse_description (segments[1], data);
++    g_strfreev (segments);
++    if (data->annotations == NULL) {
++        if (data->subcategory) {
++            int i;
++            gchar *amp;
++            segments = g_strsplit(data->subcategory, "-", -1);
++            for (i = 0; segments[i]; i++) {
++                if ((amp = strchr (segments[i], '&')) != NULL) {
++                    if (amp - segments[i] <= 1) {
++                        g_warning ("Wrong ampersand");
++                        goto failed_to_parse_unicode_emoji_test_line;
++                    }
++                    data->annotations = g_slist_append (
++                            data->annotations,
++                            g_strndup (segments[i], amp - segments[i] - 1));
++                    data->annotations = g_slist_append (
++                            data->annotations,
++                            g_strdup (amp + 1));
++                    continue;
++                }
++                data->annotations = g_slist_append (data->annotations,
++                                                    g_strdup (segments[i]));
++            }
++            g_strfreev (segments);
++        } else {
++            g_warning ("No subcategory line\n");
++            goto failed_to_parse_unicode_emoji_test_line;
++        }
++    }
++    update_emoji_list (data, TRUE);
++    reset_emoji_element (data);
++    return TRUE;
++
++failed_to_parse_unicode_emoji_test_line:
++    if (segments)
++        g_strfreev (segments);
++    reset_emoji_element (data);
++    return FALSE;
++}
++
++#undef EMOJI_VERSION_TAG
++#undef EMOJI_GROUP_TAG
++#undef EMOJI_SUBGROUP_TAG
++#undef EMOJI_NON_FULLY_QUALIFIED_TAG
++
++static gboolean
++unicode_emoji_test_parse_file (const gchar *filename,
++                               GSList      **list)
++{
++    gchar *content = NULL;
++    gsize length = 0;
++    GError *error = NULL;
++    gchar *head, *end, *line;
++    int n = 1;
++    EmojiData data = { 0, };
++
++    g_return_val_if_fail (filename != NULL, FALSE);
++    g_return_val_if_fail (list != 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_emoji_test;
++    }
++    head = end = content;
++    while (*end == '\n' && end - content < length) {
++        end++;
++        n++;
++    }
++    head = end;
++    data.list = *list;
++    while (end - content < length) {
++        while (*end != '\n' && end - content < length)
++            end++;
++        if (end - content >= length)
++            break;
++        line = g_strndup (head, end - head);
++        if (!unicode_emoji_test_parse_line (line, &data))
++            g_warning ("parse error #%d in %s version %s: %s",
++                       n, filename,
++                       unicode_emoji_version ? unicode_emoji_version : "(null)",
++                       line);
++        while (*end == '\n' && end - content < length) {
++            end++;
++            n++;
++        }
++        g_free (line);
++        head = end;
++    }
++    g_free (content);
++    g_free (unicode_emoji_version);
++    *list = data.list;
++    return TRUE;
++
++failed_to_parse_unicode_emoji_test:
++    if (error)
++        g_error_free (error);
++    g_clear_pointer (&content, g_free);
++    return FALSE;
++}
++
++static gboolean 
++unicode_emoji_parse_dir (const gchar *dirname,
++                         GSList      **list)
++{
++    gchar *filename = NULL;
++    g_return_val_if_fail (dirname != NULL, FALSE);
++    g_return_val_if_fail (list != NULL, FALSE);
++
++    filename = g_build_path ("/", dirname, "emoji-test.txt", NULL);
++    if (!unicode_emoji_test_parse_file (filename, list)) {
++        g_free (filename);
++        return FALSE;
++    }
++    g_free (filename);
++    return TRUE;
++}
++
++#ifdef HAVE_JSON_GLIB1
++static gboolean
+ parse_emojione_unicode (JsonNode  *node,
+                         EmojiData *data,
+                         gboolean   is_alternates)
+@@ -426,6 +780,31 @@ parse_emojione_category (JsonNode  *node,
+     return TRUE;
+ }
+ 
++#ifdef EMOJIONE_ALIASES_ASCII_PRINT
++static gchar *
++text_to_entity (const gchar *text)
++{
++    gchar *p;
++    GString *buff = g_string_new (NULL);
++    for (p = text; *p; p++) {
++        switch (*p) {
++        case '<':
++            g_string_append (buff, "&lt;");
++            break;
++        case '>':
++            g_string_append (buff, "&gt;");
++            break;
++        case '&':
++            g_string_append (buff, "&amp;");
++            break;
++        default:
++            g_string_append_c (buff, *p);
++        }
++    }
++    g_string_free (buff, FALSE);
++}
++#endif
++
+ static gboolean
+ parse_emojione_aliases_ascii (JsonNode  *node,
+                               EmojiData *data)
+@@ -441,11 +820,23 @@ parse_emojione_aliases_ascii (JsonNode  *node,
+     aliases_ascii = json_node_get_array (node);
+     length = json_array_get_length (aliases_ascii);
+     for (i = 0; i < length; i++) {
++#ifdef EMOJIONE_ALIASES_ASCII_PRINT
++        if (i == 0)
++            printf ("        <annotation cp=\"%s\">", data->emoji);
++#endif
+         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) {
++#ifdef EMOJIONE_ALIASES_ASCII_PRINT
++            gchar *entity = text_to_entity (alias);
++            if (i != length - 1)
++                printf ("%s | ", entity);
++            else
++                printf ("%s</annotation>\n", entity);
++            g_free (entity);
++#endif
+             data->annotations = g_slist_prepend (data->annotations,
+                                                  g_strdup (alias));
+         }
+@@ -535,7 +926,7 @@ parse_emojione_element (JsonNode  *node,
+     }
+     g_list_free (members);
+ 
+-    update_emoji_list (data);
++    update_emoji_list (data, TRUE);
+ 
+     return TRUE;
+ }
+@@ -591,27 +982,136 @@ fail_to_json_file:
+     g_object_unref (parser);
+     return FALSE;
+ }
++#endif /* HAVE_JSON_GLIB1 */
++
++static void
++emoji_data_list_unify_categories (IBusEmojiData  *data,
++                                  GSList        **list)
++{
++    g_return_if_fail (IBUS_IS_EMOJI_DATA (data));
++    g_return_if_fail (list != NULL);
++
++    const gchar *category = ibus_emoji_data_get_category (data);
++    if (*category == '\0')
++        return;
++    if (g_slist_find_custom (*list, category, (GCompareFunc)g_strcmp0) == NULL)
++        *list = g_slist_append (*list, g_strdup (category));
++}
++
++static void
++category_list_dump (const gchar *category,
++                    GString     *buff)
++{
++    g_return_if_fail (buff != NULL);
++
++    const gchar *line = g_strdup_printf ("    N_(\"%s\"),\n", category);
++    g_string_append (buff, line);
++}
++
++static void
++category_file_save (const gchar *filename,
++                    GSList      *list)
++{
++    gchar *content = NULL;
++    gsize length = 0;
++    GError *error = NULL;
++    gchar *p;
++    GString *buff = NULL;
++    int i;
++    GSList *list_categories = NULL;
++
++    g_return_if_fail (filename != NULL);
++    g_return_if_fail (list != NULL);
++
++    g_slist_foreach (list, (GFunc)emoji_data_list_unify_categories, &list_categories);
++    if (list_categories == NULL) {
++        g_warning ("Not found categories in IBusEmojiData list");
++        return;
++    }
++
++    if (!g_file_get_contents (__FILE__, &content, &length, &error)) {
++        g_warning ("Failed to load %s: %s", __FILE__, error->message);
++        g_clear_pointer (&error, g_error_free);
++    }
++    buff = g_string_new (NULL);
++    p = content;
++    for (i = 0; i < LICENSE_LINES; i++, p++) {
++        if ((p = strchr (p, '\n')) == NULL)
++            break;
++    }
++    if (p != NULL) {
++        g_string_append (buff, g_strndup (content, p - content));
++        g_string_append_c (buff, '\n');
++    }
++    g_clear_pointer (&content, g_free);
++
++    g_string_append (buff, g_strdup ("\n"));
++    g_string_append (buff, g_strdup_printf ("/* This file is generated by %s. */", __FILE__));
++    g_string_append (buff, g_strdup ("\n"));
++    g_string_append (buff, g_strdup ("include <glib/gi18n.h>\n"));
++    g_string_append (buff, g_strdup ("\n"));
++    g_string_append (buff, g_strdup ("#ifndef __IBUS_EMOJI_GEN_H_\n"));
++    g_string_append (buff, g_strdup ("#define __IBUS_EMOJI_GEN_H_\n"));
++    g_string_append (buff, g_strdup ("const static char *unicode_emoji_categories[] = {\n"));
++    list_categories = g_slist_sort (list_categories, (GCompareFunc)g_strcmp0);
++    g_slist_foreach (list_categories, (GFunc)category_list_dump, buff);
++    g_slist_free (list_categories);
++    g_string_append (buff, g_strdup ("};\n"));
++    g_string_append (buff, g_strdup ("#endif\n"));
++
++    if (!g_file_set_contents (filename, buff->str, -1, &error)) {
++        g_warning ("Failed to save emoji category file %s: %s", filename, error->message);
++        g_error_free (error);
++    }
++
++    g_string_free (buff, TRUE);
++}
+ 
+ int
+ main (int argc, char *argv[])
+ {
+     gchar *prgname;
++#ifdef HAVE_JSON_GLIB1
+     gchar *json_file = NULL;
++#endif
++    gchar *emoji_dir = NULL;
+     gchar *xml_file = NULL;
++    gchar *xml_derived_file = NULL;
++    gchar *xml_ascii_file = NULL;
+     gchar *output = NULL;
++    gchar *output_category = NULL;
+     GOptionEntry     entries[] = {
++#ifdef HAVE_JSON_GLIB1
+         { "json", 'j', 0, G_OPTION_ARG_STRING, &json_file,
+           "Parse Emoji One JSON file",
+           "JSON"
+         },
++#endif
++        { "unicode-emoji-dir", 'd', 0, G_OPTION_ARG_STRING, &emoji_dir,
++          "Parse Emoji files in DIRECTORY which includes emoji-test.txt " \
++          "emoji-sequences.txt emoji-zwj-sequences.txt in unicode.org",
++          "DIRECTORY"
++        },
+         { "out", 'o', 0, G_OPTION_ARG_STRING, &output,
+           "Save the emoji data as FILE",
+           "FILE"
+         },
++        { "out-category", 'C', 0, G_OPTION_ARG_STRING, &output_category,
++          "Save the translatable categories as FILE",
++          "FILE"
++        },
+         { "xml", 'x', 0, G_OPTION_ARG_STRING, &xml_file,
+           "Parse Unocode.org ANNOTATIONS file",
+           "ANNOTATIONS"
+         },
++        { "xml-derived", 'X', 0, G_OPTION_ARG_STRING, &xml_derived_file,
++          "Parse Unocode.org derived ANNOTATIONS file",
++          "ANNOTATIONS"
++        },
++        { "xml-ascii", 'A', 0, G_OPTION_ARG_STRING, &xml_ascii_file,
++          "Parse ASCII ANNOTATIONS file",
++          "ANNOTATIONS"
++        },
+         { NULL }
+     };
+     GOptionContext *context;
+@@ -638,12 +1138,22 @@ main (int argc, char *argv[])
+     }
+     g_option_context_free (context);
+ 
++#ifdef HAVE_JSON_GLIB1
+     if (json_file)
+         emojione_parse_json_file (json_file, &list);
++#endif
++    if (emoji_dir)
++        unicode_emoji_parse_dir (emoji_dir, &list);
+     if (xml_file)
+-        unicode_annotations_parse_xml_file (xml_file, &list);
++        unicode_annotations_parse_xml_file (xml_file, &list, FALSE);
++    if (xml_derived_file)
++        unicode_annotations_parse_xml_file (xml_derived_file, &list, TRUE);
++    if (xml_ascii_file)
++        unicode_annotations_parse_xml_file (xml_ascii_file, &list, FALSE);
+     if (list != NULL && output)
+         ibus_emoji_data_save (output, list);
++    if (list != NULL && output_category)
++        category_file_save (output_category, list);
+     if (list)
+         g_slist_free (list);
+ 
+diff --git a/src/ibusemoji.c b/src/ibusemoji.c
+index 4be092a..d2e16c5 100644
+--- a/src/ibusemoji.c
++++ b/src/ibusemoji.c
+@@ -29,7 +29,7 @@
+ #include "ibusinternal.h"
+ 
+ #define IBUS_EMOJI_DATA_MAGIC "IBusEmojiData"
+-#define IBUS_EMOJI_DATA_VERSION (3)
++#define IBUS_EMOJI_DATA_VERSION (4)
+ 
+ enum {
+     PROP_0 = 0,
+@@ -37,7 +37,6 @@ enum {
+     PROP_ANNOTATIONS,
+     PROP_DESCRIPTION,
+     PROP_CATEGORY,
+-    PROP_EMOJI_ALTERNATES
+ };
+ 
+ struct _IBusEmojiDataPrivate {
+@@ -45,7 +44,6 @@ struct _IBusEmojiDataPrivate {
+     GSList     *annotations;
+     gchar      *description;
+     gchar      *category;
+-    gchar      *emoji_alternates;
+ };
+ 
+ #define IBUS_EMOJI_DATA_GET_PRIVATE(o)  \
+@@ -108,7 +106,7 @@ ibus_emoji_data_class_init (IBusEmojiDataClass *class)
+                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ 
+     /**
+-     * IBusEmojiData:annotations:
++     * IBusEmojiData:annotations: (transfer container) (element-type utf8):
+      *
+      * The emoji annotations
+      */
+@@ -117,7 +115,7 @@ ibus_emoji_data_class_init (IBusEmojiDataClass *class)
+                     g_param_spec_pointer ("annotations",
+                         "emoji annotations",
+                         "The emoji annotation list",
+-                        G_PARAM_READWRITE));
++                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ 
+     /**
+      * IBusEmojiData:description:
+@@ -130,7 +128,7 @@ ibus_emoji_data_class_init (IBusEmojiDataClass *class)
+                         "emoji description",
+                         "The emoji description",
+                         "",
+-                        G_PARAM_READWRITE));
++                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ 
+     /**
+      * IBusEmojiData:category:
+@@ -144,19 +142,6 @@ ibus_emoji_data_class_init (IBusEmojiDataClass *class)
+                         "The emoji category",
+                         "",
+                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+-
+-    /**
+-     * IBusEmojiData:emoji_alternates:
+-     *
+-     * The emoji alternate characters
+-     */
+-    g_object_class_install_property (gobject_class,
+-                    PROP_EMOJI_ALTERNATES,
+-                    g_param_spec_string ("emoji-alternates",
+-                        "emoji alternate charasters",
+-                        "The emoji alternate characters UTF-8",
+-                        "",
+-                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ }
+ 
+ static void
+@@ -209,10 +194,6 @@ ibus_emoji_data_set_property (IBusEmojiData *emoji,
+         g_assert (emoji->priv->category == NULL);
+         emoji->priv->category = g_value_dup_string (value);
+         break;
+-    case PROP_EMOJI_ALTERNATES:
+-        g_assert (emoji->priv->emoji_alternates == NULL);
+-        emoji->priv->emoji_alternates = g_value_dup_string (value);
+-        break;
+     default:
+         G_OBJECT_WARN_INVALID_PROPERTY_ID (emoji, prop_id, pspec);
+     }
+@@ -240,9 +221,6 @@ ibus_emoji_data_get_property (IBusEmojiData *emoji,
+     case PROP_CATEGORY:
+         g_value_set_string (value, ibus_emoji_data_get_category (emoji));
+         break;
+-    case PROP_EMOJI_ALTERNATES:
+-        g_value_set_string (value, ibus_emoji_data_get_emoji_alternates(emoji));
+-        break;
+     default:
+         G_OBJECT_WARN_INVALID_PROPERTY_ID (emoji, prop_id, pspec);
+     }
+@@ -270,8 +248,6 @@ ibus_emoji_data_serialize (IBusEmojiData   *emoji,
+     }
+     g_variant_builder_add (builder, "s", NOTNULL (emoji->priv->description));
+     g_variant_builder_add (builder, "s", NOTNULL (emoji->priv->category));
+-    g_variant_builder_add (builder, "s",
+-                           NOTNULL (emoji->priv->emoji_alternates));
+ #undef NOTNULL
+     return TRUE;
+ }
+@@ -303,10 +279,6 @@ ibus_emoji_data_deserialize (IBusEmojiData *emoji,
+                                      &emoji->priv->description);
+     ibus_g_variant_get_child_string (variant, retval++,
+                                      &emoji->priv->category);
+-    if (g_variant_n_children (variant) < retval + 1)
+-        return retval;
+-    ibus_g_variant_get_child_string (variant, retval++,
+-                                     &emoji->priv->emoji_alternates);
+     return retval;
+ }
+ 
+@@ -325,7 +297,6 @@ ibus_emoji_data_copy (IBusEmojiData       *dest,
+                                                       NULL);
+     dest->priv->description      = g_strdup (src->priv->description);
+     dest->priv->category         = g_strdup (src->priv->category);
+-    dest->priv->emoji_alternates = g_strdup (src->priv->emoji_alternates);
+     return TRUE;
+ }
+ 
+@@ -345,7 +316,6 @@ ibus_emoji_data_new (const gchar *first_property_name, ...)
+     g_assert (emoji->priv->emoji != NULL);
+     g_assert (emoji->priv->description != NULL);
+     g_assert (emoji->priv->category != NULL);
+-    g_assert (emoji->priv->emoji_alternates != NULL);
+     return emoji;
+ }
+ 
+@@ -402,15 +372,6 @@ ibus_emoji_data_get_category (IBusEmojiData *emoji)
+     return emoji->priv->category;
+ }
+ 
+-const gchar *
+-ibus_emoji_data_get_emoji_alternates (IBusEmojiData *emoji)
+-{
+-    g_return_val_if_fail (IBUS_IS_EMOJI_DATA (emoji), NULL);
+-
+-    return emoji->priv->emoji_alternates;
+-}
+-
+-
+ static void
+ variant_foreach_add_emoji (IBusEmojiData   *emoji,
+                            GVariantBuilder *builder)
+diff --git a/src/ibusemoji.h b/src/ibusemoji.h
+index 233cadd..eb24fdd 100644
+--- a/src/ibusemoji.h
++++ b/src/ibusemoji.h
+@@ -156,20 +156,6 @@ const gchar *   ibus_emoji_data_get_category    (IBusEmojiData *emoji);
+ 
+ 
+ /**
+- * ibus_emoji_data_get_emoji_alternates:
+- * @emoji : An #IBusEmojiData
+- *
+- * Gets the emoji alternate characters in #IBusEmojiData. It should not be
+- * freed. The alternates are defined in "unicode_alt" in EmojiOne json.
+- *
+- * Returns: emoji alternates property in #IBusEmojiData
+- *
+- */
+-const gchar *   ibus_emoji_data_get_emoji_alternates
+-                                                (IBusEmojiData *emoji);
+-
+-
+-/**
+  * ibus_emoji_dict_save:
+  * @path: A path of the saved dictionary file.
+  * @dict: (element-type utf8 gpointer) (transfer none): An Emoji dictionary
+diff --git a/src/ibusemojigen.h b/src/ibusemojigen.h
+new file mode 100644
+index 0000000..74a6015
+--- /dev/null
++++ b/src/ibusemojigen.h
+@@ -0,0 +1,39 @@
++/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
++/* vim:set et sts=4: */
++/* ibus - The Input Bus
++ * Copyright (C) 2016-2017 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
++ */
++
++
++/* This file is generated by emoji-parser.c. */
++include <glib/gi18n.h>
++
++#ifndef __IBUS_EMOJI_GEN_H_
++#define __IBUS_EMOJI_GEN_H_
++const static char *unicode_emoji_categories[] = {
++    N_("Activities"),
++    N_("Animals & Nature"),
++    N_("Flags"),
++    N_("Food & Drink"),
++    N_("Objects"),
++    N_("Smileys & People"),
++    N_("Symbols"),
++    N_("Travel & Places"),
++};
++#endif
+diff --git a/ui/gtk3/Makefile.am b/ui/gtk3/Makefile.am
+index d2ae0d6..c557474 100644
+--- a/ui/gtk3/Makefile.am
++++ b/ui/gtk3/Makefile.am
+@@ -82,7 +82,7 @@ AM_VALAFLAGS = \
+ 	$(NULL)
+ 
+ MAINTAINERCLEANFILES =
+-CONFIG_CLEAN_FILES =
++DISTCLEANFILES =
+ noinst_DATA =
+ 
+ if ENABLE_LIBNOTIFY
+@@ -250,8 +250,7 @@ vapidir = $(datadir)/vala/vapi
+ noinst_DATA += $(VAPIGEN_VAPIS) $(VAPIGEN_VAPIS:.vapi=.deps)
+ 
+ MAINTAINERCLEANFILES += $(VAPIGEN_VAPIS)
+-# for make distclean
+-CONFIG_CLEAN_FILES += $(VAPIGEN_VAPIS)
++DISTCLEANFILES += $(VAPIGEN_VAPIS)
+ EXTRA_DIST += $(VAPIGEN_VAPIS)
+ 
+ endif
+diff --git a/ui/gtk3/emojier.vala b/ui/gtk3/emojier.vala
+index 76dca6c..8f55bd4 100644
+--- a/ui/gtk3/emojier.vala
++++ b/ui/gtk3/emojier.vala
+@@ -167,6 +167,7 @@ class IBusEmojier : Gtk.Window {
+     }
+ 
+     private const uint EMOJI_GRID_PAGE = 10;
++    private const string EMOJI_CATEGORY_OTHERS = N_("Others");
+ 
+     // Set the actual default values in the constructor
+     // because these fields are used for class_init() and static functions,
+@@ -372,8 +373,7 @@ class IBusEmojier : Gtk.Window {
+ 
+ 
+     private static void update_annotation_to_emojis_dict(IBus.EmojiData data) {
+-        string emoji = (data.get_emoji_alternates() != "") ?
+-                data.get_emoji_alternates() : data.get_emoji();
++        string emoji = data.get_emoji();
+         unowned GLib.SList<string> annotations = data.get_annotations();
+         foreach (string annotation in annotations) {
+             bool has_emoji = false;
+@@ -434,23 +434,70 @@ class IBusEmojier : Gtk.Window {
+     }
+ 
+ 
++    private static string utf8_entity(string str) {
++        GLib.StringBuilder buff = new GLib.StringBuilder();
++        int length = str.char_count();
++        for (int i = 0; i < length; i++) {
++            unichar ch = str.get_char(0);
++            switch(ch) {
++            case '<':
++                buff.append("&lt;");
++                break;
++            case '>':
++                buff.append("&gt;");
++                break;
++            case '&':
++                buff.append("&amp;");
++                break;
++            default:
++                buff.append_unichar(ch);
++                break;
++            }
++            str = str.next_char();
++        }
++        return buff.str;
++    }
++
++
++    private static void
++    update_annotations_with_description (IBus.EmojiData data,
++                                         string         description) {
++        unowned GLib.SList<string> annotations = data.get_annotations();
++        bool update_annotations = false;
++        string former = null;
++        string later = null;
++        int index = description.index_of(": ");
++        if (index > 0) {
++            former = description.substring(0, index);
++            if (annotations.find_custom(former, GLib.strcmp) == null) {
++                annotations.append(former);
++                update_annotations = true;
++            }
++            later = description.substring(index + 2);
++        } else {
++            later = description.dup();
++        }
++        var words = later.split(" ");
++        // If the description has less than 3 words, add it to annotations
++        // FIXME: How to cast GLib.CompareFunc<string> to strcmp?
++        if (words.length < 3 &&
++            annotations.find_custom(
++                    later,
++                    GLib.strcmp) == null) {
++            annotations.append(later);
++            update_annotations = true;
++        }
++        if (update_annotations)
++            data.set_annotations(annotations.copy_deep(GLib.strdup));
++    }
++
++
+     private static void update_emoji_to_data_dict(IBus.EmojiData data,
+                                                   string         lang) {
+-        string emoji = (data.get_emoji_alternates() != "") ?
+-                data.get_emoji_alternates() : data.get_emoji();
++        string emoji = data.get_emoji();
+         if (lang == "en") {
+             string description = utf8_down(data.get_description());
+-            unowned GLib.SList<string> annotations = data.get_annotations();
+-            var words = description.split(" ");
+-            // If the description has less than 3 words, add it to annotations
+-            // FIXME: How to cast GLib.CompareFunc<string> to strcmp?
+-            if (words.length < 3 &&
+-                annotations.find_custom(
+-                        description,
+-                        GLib.strcmp) == null) {
+-                annotations.append(description);
+-                data.set_annotations(annotations.copy_deep(GLib.strdup));
+-            }
++            update_annotations_with_description (data, description);
+             m_emoji_to_data_dict.replace(emoji, data);
+         } else {
+             unowned IBus.EmojiData? en_data =
+@@ -462,16 +509,8 @@ class IBusEmojier : Gtk.Window {
+             string trans_description = data.get_description();
+             en_data.set_description(trans_description);
+             trans_description = utf8_down(trans_description);
++            update_annotations_with_description (data, trans_description);
+             unowned GLib.SList<string> annotations = data.get_annotations();
+-            var words = trans_description.split(" ");
+-            // If the description has less than 3 words, add it to annotations
+-            // FIXME: How to cast GLib.CompareFunc<string> to strcmp?
+-            if (words.length < 3 &&
+-                annotations.find_custom(
+-                        trans_description,
+-                        GLib.strcmp) == null) {
+-                annotations.append(trans_description);
+-            }
+             unowned GLib.SList<string> en_annotations
+                 = en_data.get_annotations();
+             foreach (string annotation in en_annotations) {
+@@ -489,10 +528,11 @@ class IBusEmojier : Gtk.Window {
+ 
+     private static void update_category_to_emojis_dict(IBus.EmojiData data,
+                                                        string         lang) {
+-        string emoji = (data.get_emoji_alternates() != "") ?
+-                data.get_emoji_alternates() : data.get_emoji();
++        string emoji = data.get_emoji();
+         string category = data.get_category();
+-        if (lang == "en" && category != "") {
++        if (category == "")
++            category = EMOJI_CATEGORY_OTHERS;
++        if (lang == "en") {
+             bool has_emoji = false;
+             unowned GLib.SList<string> hits =
+                     m_category_to_emojis_dict.lookup(category);
+@@ -562,9 +602,17 @@ class IBusEmojier : Gtk.Window {
+                 m_category_to_emojis_dict.get_keys();
+         // FIXME: How to cast GLib.CompareFunc<string> to strcmp?
+         categories.sort((a, b) => {
++            if (a == EMOJI_CATEGORY_OTHERS && b != EMOJI_CATEGORY_OTHERS)
++                return 1;
++            else if (a != EMOJI_CATEGORY_OTHERS && b == EMOJI_CATEGORY_OTHERS)
++                return -1;
+             return GLib.strcmp(_(a), _(b));
+         });
+         foreach (unowned string category in categories) {
++            // "Others" category includes next unicode chars and fonts do not support
++            // the base and varints yet.
++            if (category == EMOJI_CATEGORY_OTHERS)
++               continue;
+             EBoxRow row = new EBoxRow(category);
+             string locale_category = _(category);
+             EPaddedLabelBox widget =
+@@ -718,7 +766,7 @@ class IBusEmojier : Gtk.Window {
+         uint page_end_pos = uint.min(page_start_pos + page_size, ncandidates);
+         if (m_backward != null) {
+             string backward_desc =
+-                    "%s (%u / %u)".printf(m_backward, cursor, ncandidates - 1);
++                    "%s (%u / %u)".printf(_(m_backward), cursor, ncandidates - 1);
+             EPaddedLabelBox label =
+                     new EPaddedLabelBox(backward_desc,
+                                         Gtk.Align.CENTER,
+@@ -746,7 +794,7 @@ class IBusEmojier : Gtk.Window {
+                 int font_size = m_emoji_font_size - 2;
+                 string emoji_font = "%s %d".printf(font_family, font_size);
+                 string markup = "<span font=\"%s\">%s</span>".
+-                        printf(emoji_font, candidate.get_text());
++                        printf(emoji_font, utf8_entity(candidate.get_text()));
+                 label.set_markup(markup);
+             }
+             label.set_halign(Gtk.Align.FILL);
+-- 
+2.9.3
+
+From 0836c3ffd6764969dfaa9953f52a24c1cbf2c983 Mon Sep 17 00:00:00 2001
+From: fujiwarat <takao.fujiwara1@gmail.com>
+Date: Sat, 6 May 2017 00:22:50 +0900
+Subject: [PATCH] Support to match emoji annotations with partial string
+
+Now ibus-setup has a new tab of "Emoji" and it provides
+the options to choose a condtion and length to match
+emoji annotations partically.
+
+R=alexepico@gmail.com, penghuang@google.com
+
+Review URL: https://codereview.appspot.com/319700043
+---
+ data/ibus.schemas.in    |  39 ++++
+ setup/main.py           | 121 ++++++++++--
+ setup/setup.ui          | 491 ++++++++++++++++++++++++++++++------------------
+ ui/gtk3/emojier.vala    |  64 ++++++-
+ ui/gtk3/emojierapp.vala |  52 ++++-
+ ui/gtk3/panel.vala      |  22 +++
+ 6 files changed, 582 insertions(+), 207 deletions(-)
+
+diff --git a/data/ibus.schemas.in b/data/ibus.schemas.in
+index 096dd71..0647004 100644
+--- a/data/ibus.schemas.in
++++ b/data/ibus.schemas.in
+@@ -404,6 +404,45 @@
+       </locale>
+     </schema>
+     <schema>
++      <key>/schemas/desktop/ibus/panel/emoji/has-partial-match</key>
++      <applyto>/desktop/ibus/panel/emoji/has-partial-match</applyto>
++      <owner>ibus</owner>
++      <type>bool</type>
++      <default>false</default>
++      <locale name="C">
++        <short>Whether emoji annotaions can be match partially or not</short>
++	    <long>Whether emoji annotations can be matched with a partial
++                  string instead of the exact match or not.</long>
++      </locale>
++    </schema>
++    <schema>
++      <key>/schemas/desktop/ibus/panel/emoji/partial-match-length</key>
++      <applyto>/desktop/ibus/panel/emoji/partial-match-length</applyto>
++      <owner>ibus</owner>
++      <type>int</type>
++      <default>3</default>
++      <locale name="C">
++        <short>Match emoji annotaions with the specified length</short>
++	    <long>Match emoji annotations partially with more than
++                  the specified number of characters instead of
++                  the exact match.</long>
++      </locale>
++    </schema>
++    <schema>
++      <key>/schemas/desktop/ibus/panel/emoji/partial-match-condition</key>
++      <applyto>/desktop/ibus/panel/emoji/partial-match-condition</applyto>
++      <owner>ibus</owner>
++      <type>int</type>
++      <default>0</default>
++      <locale name="C">
++        <short>Choose a condition to match emoji annotations partially</short>
++	    <long>Choose one of the following conditions to match emoji
++	          annotations partially:
++                  0 == Prefix match, 1 == Suffix match, 2 == Containing match
++                  </long>
++      </locale>
++    </schema>
++    <schema>
+       <key>/schemas/desktop/ibus/general/embed_preedit_text</key>
+       <applyto>/desktop/ibus/general/embed_preedit_text</applyto>
+       <owner>ibus</owner>
+diff --git a/setup/main.py b/setup/main.py
+index 7839cea..f0eee99 100644
+--- a/setup/main.py
++++ b/setup/main.py
+@@ -187,19 +187,6 @@ class Setup(object):
+                                     self.__fontbutton_custom_font,
+                                    'sensitive',
+                                    Gio.SettingsBindFlags.GET)
+-        self.__fontbutton_emoji_font = self.__builder.get_object(
+-                'fontbutton_emoji_font')
+-        self.__fontbutton_emoji_font.set_preview_text('🙂🍎🚃💓📧⚽🐳');
+-        self.__settings_emoji.bind('font',
+-                                    self.__fontbutton_emoji_font,
+-                                   'font-name',
+-                                   Gio.SettingsBindFlags.DEFAULT)
+-        self.__button_emoji_lang = self.__builder.get_object(
+-                'button_emoji_lang')
+-        self.__settings_emoji.bind('lang',
+-                                    self.__button_emoji_lang,
+-                                   'lang',
+-                                   Gio.SettingsBindFlags.DEFAULT)
+ 
+         # show icon on system tray
+         self.__checkbutton_show_icon_on_systray = self.__builder.get_object(
+@@ -287,6 +274,113 @@ class Setup(object):
+         self.__treeview.connect("notify::active-engine", self.__treeview_notify_cb)
+         self.__treeview.connect("notify::engines", self.__treeview_notify_cb)
+ 
++    def __init_emoji(self):
++        self.__fontbutton_emoji_font = self.__builder.get_object(
++                'fontbutton_emoji_font')
++        self.__fontbutton_emoji_font.set_preview_text('🙂🍎🚃💓📧⚽🐳');
++        self.__settings_emoji.bind('font',
++                                    self.__fontbutton_emoji_font,
++                                   'font-name',
++                                   Gio.SettingsBindFlags.DEFAULT)
++        self.__button_emoji_lang = self.__builder.get_object(
++                'button_emoji_lang')
++        self.__settings_emoji.bind('lang',
++                                    self.__button_emoji_lang,
++                                   'lang',
++                                   Gio.SettingsBindFlags.DEFAULT)
++        self.__checkbutton_emoji_partial_match = self.__builder.get_object(
++                'checkbutton_emoji_partial_match')
++        checkbutton_label = self.__checkbutton_emoji_partial_match.get_child()
++        if type(checkbutton_label) == Gtk.Label:
++            checkbutton_label.set_property('wrap', True)
++            checkbutton_label.set_property('max-width-chars', 74)
++        self.__spinbutton_emoji_partial_match = self.__builder.get_object(
++                'spinbutton_emoji_partial_match')
++        self.__settings_emoji.bind('has-partial-match',
++                                   self.__checkbutton_emoji_partial_match,
++                                   'active',
++                                   Gio.SettingsBindFlags.DEFAULT)
++        self.__settings_emoji.bind('has-partial-match',
++                                   self.__spinbutton_emoji_partial_match,
++                                   'sensitive',
++                                   Gio.SettingsBindFlags.GET)
++
++        def adjustment_value_changed_cb(obj):
++            key = 'partial-match-length'
++            value = int(adjustment.get_value())
++            if value == self.__settings_emoji.get_int(key):
++                return
++            self.__settings_emoji.set_int(key, value)
++        def settings_emoji_partial_match_length_cb(settings, key):
++            value = self.__settings_emoji.get_int(key)
++            old_value = int(self.__spinbutton_emoji_partial_match.get_value())
++            if value == old_value:
++                return
++            self.__spinbutton_emoji_partial_match.set_value(value)
++        settings_emoji_partial_match_length_cb(None, 'partial-match-length')
++        adjustment = self.__spinbutton_emoji_partial_match.get_adjustment()
++        adjustment.connect('value-changed', adjustment_value_changed_cb)
++        self.__settings_emoji.connect('changed::partial-match-length',
++                                      settings_emoji_partial_match_length_cb)
++
++        self.__hbox_emoji_partial_match = self.__builder.get_object(
++                'hbox_emoji_partial_match')
++        self.__settings_emoji.bind('has-partial-match',
++                                   self.__hbox_emoji_partial_match,
++                                   'sensitive',
++                                   Gio.SettingsBindFlags.GET)
++        self.__radiobutton_emoji_prefix_match = self.__builder.get_object(
++                'radiobutton_emoji_prefix_match')
++        self.__radiobutton_emoji_suffix_match = self.__builder.get_object(
++                'radiobutton_emoji_suffix_match')
++        self.__radiobutton_emoji_contain_match = self.__builder.get_object(
++                'radiobutton_emoji_contain_match')
++
++        def radiobuton_emoji_partial_match_cb(obj):
++            key = 'partial-match-condition'
++            condition = 0
++            if not obj.get_active():
++                return
++            if obj == self.__radiobutton_emoji_prefix_match:
++                condition = 0
++            elif obj == self.__radiobutton_emoji_suffix_match:
++                condition = 1
++            elif obj == self.__radiobutton_emoji_contain_match:
++                condition = 2
++            else:
++                print('Wrong emoji partial match object')
++                return
++            self.__settings_emoji.set_int(key, condition)
++        def settings_emoji_partial_match_condition_cb(settings, key):
++            value = self.__settings_emoji.get_int(key)
++            obj = None
++            if value == 0:
++                obj = self.__radiobutton_emoji_prefix_match
++            elif value == 1:
++                obj = self.__radiobutton_emoji_suffix_match
++            elif value == 2:
++                obj = self.__radiobutton_emoji_contain_match
++            else:
++                print('Wrong emoji partial match condition')
++                return
++            if obj.get_active():
++                return
++            obj.set_active(True)
++
++        settings_emoji_partial_match_condition_cb(None,
++                                                  'partial-match-condition')
++        self.__radiobutton_emoji_prefix_match.connect(
++                'toggled',
++                radiobuton_emoji_partial_match_cb)
++        self.__radiobutton_emoji_suffix_match.connect(
++                'toggled',
++                radiobuton_emoji_partial_match_cb)
++        self.__radiobutton_emoji_contain_match.connect(
++                'toggled',
++                radiobuton_emoji_partial_match_cb)
++        self.__settings_emoji.connect('changed::partial-match-condition',
++                                      settings_emoji_partial_match_condition_cb)
++
+     def __init_ui(self):
+         # add icon search path
+         self.__window = self.__builder.get_object("window_preferences")
+@@ -306,6 +400,7 @@ class Setup(object):
+         self.__init_hotkeys()
+         self.__init_panel()
+         self.__init_general()
++        self.__init_emoji()
+ 
+     def __gdk_window_set_cb(self, object, pspec):
+         window = object.get_window()
+diff --git a/setup/setup.ui b/setup/setup.ui
+index 54ef916..322f514 100644
+--- a/setup/setup.ui
++++ b/setup/setup.ui
+@@ -55,6 +55,14 @@
+       </row>
+     </data>
+   </object>
++  <object class="GtkAdjustment" id="adjustment_emoji_partial_match">
++    <property name="value">3.0</property>
++    <property name="lower">1.0</property>
++    <property name="upper">255.0</property>
++    <property name="step-increment">1.0</property>
++    <property name="page-increment">10.0</property>
++    <property name="page-size">10.0</property>
++  </object>
+   <object class="GtkWindow" id="window_preferences">
+     <property name="can_focus">False</property>
+     <property name="border_width">12</property>
+@@ -109,8 +117,6 @@
+                             <property name="label" translatable="yes">Next input method:</property>
+                           </object>
+                           <packing>
+-                            <property name="top_attach">3</property>
+-                            <property name="bottom_attach">4</property>
+                             <property name="x_options">GTK_FILL</property>
+                             <property name="y_options">GTK_FILL</property>
+                           </packing>
+@@ -125,69 +131,13 @@
+                             <property name="label" translatable="yes">Previous input method:</property>
+                           </object>
+                           <packing>
+-                            <property name="top_attach">4</property>
+-                            <property name="bottom_attach">5</property>
+-                            <property name="x_options">GTK_FILL</property>
+-                            <property name="y_options">GTK_FILL</property>
+-                          </packing>
+-                        </child>
+-                        <child>
+-                          <object class="GtkLabel" id="emoji_label">
+-                            <property name="visible">True</property>
+-                            <property name="can_focus">False</property>
+-                            <property name="tooltip_text" translatable="yes">The shortcut keys for showing emoji dialog</property>
+-                            <property name="halign">start</property>
+-                            <property name="label" translatable="yes">Emoji choice:</property>
+-                          </object>
+-                          <packing>
+-                            <property name="top_attach">5</property>
+-                            <property name="bottom_attach">6</property>
++                            <property name="top_attach">1</property>
++                            <property name="bottom_attach">2</property>
+                             <property name="x_options">GTK_FILL</property>
+                             <property name="y_options">GTK_FILL</property>
+                           </packing>
+                         </child>
+                         <child>
+-                          <object class="GtkBox" id="hbox4">
+-                            <property name="orientation">horizontal</property>
+-                            <property name="no_show_all">True</property>
+-                            <property name="can_focus">False</property>
+-                            <property name="spacing">6</property>
+-                            <child>
+-                              <object class="GtkEntry" id="entry_trigger">
+-                                <property name="visible">True</property>
+-                                <property name="can_focus">True</property>
+-                                <property name="editable">False</property>
+-                              </object>
+-                              <packing>
+-                                <property name="expand">True</property>
+-                                <property name="fill">True</property>
+-                                <property name="position">0</property>
+-                              </packing>
+-                            </child>
+-                            <child>
+-                              <object class="GtkButton" id="button_trigger">
+-                                <property name="label" translatable="yes">...</property>
+-                                <property name="use_action_appearance">False</property>
+-                                <property name="visible">True</property>
+-                                <property name="can_focus">True</property>
+-                                <property name="receives_default">False</property>
+-                                <property name="use_action_appearance">False</property>
+-                                <property name="use_underline">True</property>
+-                              </object>
+-                              <packing>
+-                                <property name="expand">False</property>
+-                                <property name="fill">True</property>
+-                                <property name="position">1</property>
+-                              </packing>
+-                            </child>
+-                          </object>
+-                          <packing>
+-                            <property name="left_attach">1</property>
+-                            <property name="right_attach">2</property>
+-                            <property name="y_options">GTK_FILL</property>
+-                          </packing>
+-                        </child>
+-                        <child>
+                           <object class="GtkBox" id="hbox5">
+                             <property name="orientation">horizontal</property>
+                             <property name="visible">True</property>
+@@ -225,8 +175,6 @@
+                           <packing>
+                             <property name="left_attach">1</property>
+                             <property name="right_attach">2</property>
+-                            <property name="top_attach">3</property>
+-                            <property name="bottom_attach">4</property>
+                             <property name="y_options">GTK_FILL</property>
+                           </packing>
+                         </child>
+@@ -270,51 +218,8 @@
+                           <packing>
+                             <property name="left_attach">1</property>
+                             <property name="right_attach">2</property>
+-                            <property name="top_attach">4</property>
+-                            <property name="bottom_attach">5</property>
+-                            <property name="y_options">GTK_FILL</property>
+-                          </packing>
+-                        </child>
+-                        <child>
+-                          <object class="GtkBox" id="emoji_hbox">
+-                            <property name="orientation">horizontal</property>
+-                            <property name="visible">True</property>
+-                            <property name="can_focus">False</property>
+-                            <property name="spacing">6</property>
+-                            <child>
+-                              <object class="GtkEntry" id="entry_emoji_dialog">
+-                                <property name="visible">True</property>
+-                                <property name="can_focus">True</property>
+-                                <property name="editable">False</property>
+-                              </object>
+-                              <packing>
+-                                <property name="expand">True</property>
+-                                <property name="fill">True</property>
+-                                <property name="position">0</property>
+-                              </packing>
+-                            </child>
+-                            <child>
+-                              <object class="GtkButton" id="button_emoji_dialog">
+-                                <property name="label" translatable="yes">...</property>
+-                                <property name="use_action_appearance">False</property>
+-                                <property name="visible">True</property>
+-                                <property name="can_focus">True</property>
+-                                <property name="receives_default">False</property>
+-                                <property name="use_action_appearance">False</property>
+-                                <property name="use_underline">True</property>
+-                              </object>
+-                              <packing>
+-                                <property name="expand">False</property>
+-                                <property name="fill">True</property>
+-                                <property name="position">1</property>
+-                              </packing>
+-                            </child>
+-                          </object>
+-                          <packing>
+-                            <property name="left_attach">1</property>
+-                            <property name="right_attach">2</property>
+-                            <property name="top_attach">5</property>
+-                            <property name="bottom_attach">6</property>
++                            <property name="top_attach">1</property>
++                            <property name="bottom_attach">2</property>
+                             <property name="y_options">GTK_FILL</property>
+                           </packing>
+                         </child>
+@@ -327,6 +232,8 @@
+                             <property name="label" translatable="yes">Enable or disable:</property>
+                           </object>
+                           <packing>
++                            <property name="top_attach">2</property>
++                            <property name="bottom_attach">3</property>
+                             <property name="x_options">GTK_FILL</property>
+                             <property name="y_options">GTK_FILL</property>
+                           </packing>
+@@ -339,8 +246,8 @@
+                             <property name="label" translatable="yes">Enable:</property>
+                           </object>
+                           <packing>
+-                            <property name="top_attach">1</property>
+-                            <property name="bottom_attach">2</property>
++                            <property name="top_attach">3</property>
++                            <property name="bottom_attach">4</property>
+                             <property name="x_options">GTK_FILL</property>
+                             <property name="y_options">GTK_FILL</property>
+                           </packing>
+@@ -383,8 +290,8 @@
+                           <packing>
+                             <property name="left_attach">1</property>
+                             <property name="right_attach">2</property>
+-                            <property name="top_attach">1</property>
+-                            <property name="bottom_attach">2</property>
++                            <property name="top_attach">3</property>
++                            <property name="bottom_attach">4</property>
+                             <property name="y_options">GTK_FILL</property>
+                           </packing>
+                         </child>
+@@ -396,8 +303,8 @@
+                             <property name="label" translatable="yes">Disable:</property>
+                           </object>
+                           <packing>
+-                            <property name="top_attach">2</property>
+-                            <property name="bottom_attach">3</property>
++                            <property name="top_attach">4</property>
++                            <property name="bottom_attach">5</property>
+                             <property name="x_options">GTK_FILL</property>
+                             <property name="y_options">GTK_FILL</property>
+                           </packing>
+@@ -440,8 +347,8 @@
+                           <packing>
+                             <property name="left_attach">1</property>
+                             <property name="right_attach">2</property>
+-                            <property name="top_attach">2</property>
+-                            <property name="bottom_attach">3</property>
++                            <property name="top_attach">4</property>
++                            <property name="bottom_attach">5</property>
+                             <property name="y_options">GTK_FILL</property>
+                           </packing>
+                         </child>
+@@ -675,68 +582,6 @@
+                             <property name="y_options">GTK_FILL</property>
+                           </packing>
+                         </child>
+-                        <child>
+-                          <object class="GtkLabel" id="label_emoji_font">
+-                            <property name="visible">True</property>
+-                            <property name="can_focus">False</property>
+-                            <property name="tooltip_text" translatable="yes">Set a font of emoji candidates on the emoji dialog</property>
+-                            <property name="halign">start</property>
+-                            <property name="label" translatable="yes">Emoji font:</property>
+-                            <property name="justify">right</property>
+-                          </object>
+-                          <packing>
+-                            <property name="top_attach">7</property>
+-                            <property name="bottom_attach">8</property>
+-                            <property name="x_options">GTK_FILL</property>
+-                            <property name="y_options">GTK_FILL</property>
+-                          </packing>
+-                        </child>
+-                        <child>
+-                          <object class="GtkFontButton" id="fontbutton_emoji_font">
+-                            <property name="visible">True</property>
+-                            <property name="can_focus">True</property>
+-                            <property name="receives_default">True</property>
+-                            <property name="use_action_appearance">False</property>
+-                          </object>
+-                          <packing>
+-                            <property name="left_attach">1</property>
+-                            <property name="right_attach">2</property>
+-                            <property name="top_attach">7</property>
+-                            <property name="bottom_attach">8</property>
+-                            <property name="y_options">GTK_FILL</property>
+-                          </packing>
+-                        </child>
+-                        <child>
+-                          <object class="GtkLabel" id="label_emoji_lang">
+-                            <property name="visible">True</property>
+-                            <property name="can_focus">False</property>
+-                            <property name="tooltip_text" translatable="yes">Set a language of emoji annotations on the emoji dialog</property>
+-                            <property name="halign">start</property>
+-                            <property name="label" translatable="yes">Emoji annotation language:</property>
+-                            <property name="justify">right</property>
+-                          </object>
+-                          <packing>
+-                            <property name="top_attach">8</property>
+-                            <property name="bottom_attach">9</property>
+-                            <property name="x_options">GTK_FILL</property>
+-                            <property name="y_options">GTK_FILL</property>
+-                          </packing>
+-                        </child>
+-                        <child>
+-                          <object class="EmojiLangButton" id="button_emoji_lang">
+-                            <property name="visible">True</property>
+-                            <property name="can_focus">True</property>
+-                            <property name="receives_default">True</property>
+-                            <property name="use_action_appearance">False</property>
+-                          </object>
+-                          <packing>
+-                            <property name="left_attach">1</property>
+-                            <property name="right_attach">2</property>
+-                            <property name="top_attach">8</property>
+-                            <property name="bottom_attach">9</property>
+-                            <property name="y_options">GTK_FILL</property>
+-                          </packing>
+-                        </child>
+                       </object>
+                     </child>
+                     <child type="label">
+@@ -1027,6 +872,292 @@
+               </packing>
+             </child>
+             <child>
++              <object class="GtkBox" id="vbox_emoji1">
++                <property name="orientation">vertical</property>
++                <property name="visible">True</property>
++                <property name="can_focus">False</property>
++                <property name="spacing">18</property>
++                <property name="margin_top">12</property>
++                <property name="margin_bottom">12</property>
++                <property name="margin_left">12</property>
++                <property name="margin_right">12</property>
++                <child>
++                  <object class="GtkFrame" id="frame_emoji1">
++                    <property name="visible">True</property>
++                    <property name="can_focus">False</property>
++                    <property name="label_xalign">0</property>
++                    <property name="shadow_type">none</property>
++                    <child>
++                      <object class="GtkTable" id="table_emoji1">
++                        <property name="visible">True</property>
++                        <property name="can_focus">False</property>
++                        <property name="n_rows">5</property>
++                        <property name="n_columns">2</property>
++                        <property name="column_spacing">12</property>
++                        <property name="row_spacing">6</property>
++                        <property name="margin_top">6</property>
++                        <property name="margin_left">12</property>
++                        <child>
++                          <object class="GtkLabel" id="label_emoji1">
++                            <property name="visible">True</property>
++                            <property name="can_focus">False</property>
++                            <property name="tooltip_text" translatable="yes">The shortcut keys for showing emoji dialog</property>
++                            <property name="halign">start</property>
++                            <property name="label" translatable="yes">Emoji choice:</property>
++                          </object>
++                          <packing>
++                            <property name="x_options">GTK_FILL</property>
++                            <property name="y_options">GTK_FILL</property>
++                          </packing>
++                        </child>
++                        <child>
++                          <object class="GtkBox" id="hbox_emoji1">
++                            <property name="orientation">horizontal</property>
++                            <property name="visible">True</property>
++                            <property name="can_focus">False</property>
++                            <property name="spacing">6</property>
++                            <child>
++                              <object class="GtkEntry" id="entry_emoji_dialog">
++                                <property name="visible">True</property>
++                                <property name="can_focus">True</property>
++                                <property name="editable">False</property>
++                              </object>
++                              <packing>
++                                <property name="expand">True</property>
++                                <property name="fill">True</property>
++                                <property name="position">0</property>
++                              </packing>
++                            </child>
++                            <child>
++                              <object class="GtkButton" id="button_emoji_dialog">
++                                <property name="label" translatable="yes">...</property>
++                                <property name="use_action_appearance">False</property>
++                                <property name="visible">True</property>
++                                <property name="can_focus">True</property>
++                                <property name="receives_default">False</property>
++                                <property name="use_action_appearance">False</property>
++                                <property name="use_underline">True</property>
++                              </object>
++                              <packing>
++                                <property name="expand">False</property>
++                                <property name="fill">True</property>
++                                <property name="position">1</property>
++                              </packing>
++                            </child>
++                          </object>
++                          <packing>
++                            <property name="left_attach">1</property>
++                            <property name="right_attach">2</property>
++                            <property name="y_options">GTK_FILL</property>
++                          </packing>
++                        </child>
++                      </object>
++                    </child>
++                    <child type="label">
++                      <object class="GtkLabel" id="label_emoji2">
++                        <property name="visible">True</property>
++                        <property name="can_focus">False</property>
++                        <property name="label" translatable="yes">&lt;b&gt;Keyboard Shortcuts&lt;/b&gt;</property>
++                        <property name="use_markup">True</property>
++                      </object>
++                    </child>
++                  </object>
++                  <packing>
++                    <property name="expand">False</property>
++                    <property name="fill">True</property>
++                    <property name="position">0</property>
++                  </packing>
++                </child>
++                <child>
++                  <object class="GtkFrame" id="frame_emoji2">
++                    <property name="visible">True</property>
++                    <property name="can_focus">False</property>
++                    <property name="label_xalign">0</property>
++                    <property name="shadow_type">none</property>
++                    <child>
++                      <object class="GtkGrid" id="table_emoji2">
++                        <property name="visible">True</property>
++                        <property name="can_focus">False</property>
++                        <property name="column_spacing">12</property>
++                        <property name="row_spacing">6</property>
++                        <property name="margin_top">6</property>
++                        <property name="margin_left">12</property>
++                        <property name="row_homogeneous">false</property>
++                        <child>
++                          <object class="GtkLabel" id="label_emoji_font">
++                            <property name="visible">True</property>
++                            <property name="can_focus">False</property>
++                            <property name="tooltip_text" translatable="yes">Set a font of emoji candidates on the emoji dialog</property>
++                            <property name="halign">start</property>
++                            <property name="label" translatable="yes">Emoji font:</property>
++                            <property name="justify">right</property>
++                          </object>
++                          <packing>
++                            <property name="left_attach">0</property>
++                          </packing>
++                        </child>
++                        <child>
++                          <object class="GtkFontButton" id="fontbutton_emoji_font">
++                            <property name="visible">True</property>
++                            <property name="can_focus">True</property>
++                            <property name="receives_default">True</property>
++                            <property name="use_action_appearance">False</property>
++                          </object>
++                          <packing>
++                            <property name="left_attach">1</property>
++                            <!-- property name="right_attach">2</property -->
++                          </packing>
++                        </child>
++                        <child>
++                          <object class="GtkLabel" id="label_emoji_lang">
++                            <property name="visible">True</property>
++                            <property name="can_focus">False</property>
++                            <property name="tooltip_text" translatable="yes">Set a language of emoji annotations on the emoji dialog</property>
++                            <property name="halign">start</property>
++                            <property name="label" translatable="yes">Emoji annotation language:</property>
++                            <property name="justify">right</property>
++                          </object>
++                          <packing>
++                            <property name="left_attach">0</property>
++                            <property name="top_attach">1</property>
++                          </packing>
++                        </child>
++                        <child>
++                          <object class="EmojiLangButton" id="button_emoji_lang">
++                            <property name="visible">True</property>
++                            <property name="can_focus">True</property>
++                            <property name="receives_default">True</property>
++                            <property name="use_action_appearance">False</property>
++                          </object>
++                          <packing>
++                            <property name="left_attach">1</property>
++                            <property name="top_attach">1</property>
++                          </packing>
++                        </child>
++                        <child>
++                          <object class="GtkCheckButton" id="checkbutton_emoji_partial_match">
++                            <property name="label" translatable="yes">Match emoji annotations partially with the following condition and more than the number of characters:</property>
++                            <property name="use_action_appearance">False</property>
++                            <property name="visible">True</property>
++                            <property name="can_focus">True</property>
++                            <property name="receives_default">False</property>
++                            <property name="tooltip_text" translatable="yes">If emoji annotations can be matched with a partial string instead of the exact match</property>
++                            <property name="use_action_appearance">False</property>
++                            <property name="valign">start</property>
++                            <property name="draw_indicator">True</property>
++                          </object>
++                          <packing>
++                            <property name="left_attach">0</property>
++                            <property name="width">2</property>
++                            <property name="top_attach">2</property>
++                          </packing>
++                        </child>
++                        <child>
++                          <object class="GtkSpinButton" id="spinbutton_emoji_partial_match">
++                            <property name="adjustment">adjustment_emoji_partial_match</property>
++                            <property name="value">3.0</property>
++                            <property name="visible">True</property>
++                            <property name="can_focus">True</property>
++                            <property name="receives_default">False</property>
++                            <property name="halign">start</property>
++                          </object>
++                          <packing>
++                            <property name="left_attach">0</property>
++                            <property name="width">2</property>
++                            <property name="top_attach">3</property>
++                          </packing>
++                        </child>
++                        <child>
++                          <object class="GtkBox" id="hbox_emoji_partial_match">
++                            <property name="orientation">horizontal</property>
++                            <property name="visible">True</property>
++                            <property name="can_focus">False</property>
++                            <property name="spacing">6</property>
++                            <child>
++                              <object class="GtkRadioButton" id="radiobutton_emoji_prefix_match">
++                                <property name="label" translatable="yes">Prefix match</property>
++                                <property name="visible">True</property>
++                                <property name="can_focus">True</property>
++                                <property name="receives_default">False</property>
++                                <property name="halign">start</property>
++                              </object>
++                              <packing>
++                                <property name="expand">False</property>
++                                <property name="fill">True</property>
++                                <property name="position">0</property>
++                              </packing>
++                            </child>
++                            <child>
++                              <object class="GtkRadioButton" id="radiobutton_emoji_suffix_match">
++                                <property name="label" translatable="yes">Suffix match</property>
++                                <property name="group">radiobutton_emoji_prefix_match</property>
++                                <property name="visible">True</property>
++                                <property name="can_focus">True</property>
++                                <property name="receives_default">False</property>
++                                <property name="halign">start</property>
++                              </object>
++                              <packing>
++                                <property name="expand">False</property>
++                                <property name="fill">True</property>
++                                <property name="position">1</property>
++                              </packing>
++                            </child>
++                            <child>
++                              <object class="GtkRadioButton" id="radiobutton_emoji_contain_match">
++                                <property name="label" translatable="yes">Containing match</property>
++                                <property name="group">radiobutton_emoji_prefix_match</property>
++                                <property name="visible">True</property>
++                                <property name="can_focus">True</property>
++                                <property name="receives_default">False</property>
++                                <property name="halign">start</property>
++                              </object>
++                              <packing>
++                                <property name="expand">False</property>
++                                <property name="fill">True</property>
++                                <property name="position">2</property>
++                              </packing>
++                            </child>
++                          </object>
++                          <packing>
++                            <property name="left_attach">0</property>
++                            <property name="width">2</property>
++                            <property name="top_attach">4</property>
++                          </packing>
++                        </child>
++                      </object>
++                    </child>
++                    <child type="label">
++                      <object class="GtkLabel" id="label_emoji3">
++                        <property name="visible">True</property>
++                        <property name="can_focus">False</property>
++                        <property name="label" translatable="yes">&lt;b&gt;Font and Style&lt;/b&gt;</property>
++                        <property name="use_markup">True</property>
++                      </object>
++                    </child>
++                  </object>
++                  <packing>
++                    <property name="expand">False</property>
++                    <property name="fill">True</property>
++                    <property name="position">1</property>
++                  </packing>
++                </child>
++              </object>
++              <packing>
++                <property name="position">2</property>
++              </packing>
++            </child>
++            <child type="tab">
++              <object class="GtkLabel" id="emoji_tab">
++                <property name="visible">True</property>
++                <property name="can_focus">False</property>
++                <property name="label" translatable="yes">Emoji</property>
++              </object>
++              <packing>
++                <property name="position">2</property>
++                <property name="tab_fill">False</property>
++              </packing>
++            </child>
++            <child>
+               <object class="GtkBox" id="vbox7">
+                 <property name="orientation">vertical</property>
+                 <property name="visible">True</property>
+@@ -1134,7 +1265,7 @@
+                 </child>
+               </object>
+               <packing>
+-                <property name="position">2</property>
++                <property name="position">3</property>
+               </packing>
+             </child>
+             <child type="tab">
+@@ -1214,7 +1345,7 @@ Homepage: https://github.com/ibus/ibus/wiki
+                 </child>
+               </object>
+               <packing>
+-                <property name="position">3</property>
++                <property name="position">4</property>
+               </packing>
+             </child>
+             <child type="tab">
+@@ -1224,7 +1355,7 @@ Homepage: https://github.com/ibus/ibus/wiki
+                 <property name="label" translatable="yes">About</property>
+               </object>
+               <packing>
+-                <property name="position">3</property>
++                <property name="position">4</property>
+                 <property name="tab_fill">False</property>
+               </packing>
+             </child>
+diff --git a/ui/gtk3/emojier.vala b/ui/gtk3/emojier.vala
+index 8f55bd4..76d5fed 100644
+--- a/ui/gtk3/emojier.vala
++++ b/ui/gtk3/emojier.vala
+@@ -177,6 +177,9 @@ class IBusEmojier : Gtk.Window {
+     private static int m_emoji_font_size;
+     private static string[] m_favorites;
+     private static int m_emoji_max_seq_len;
++    private static bool m_has_partial_match;
++    private static uint m_partial_match_length;
++    private static uint m_partial_match_condition;
+     private static GLib.HashTable<string, GLib.SList>?
+             m_annotation_to_emojis_dict;
+     private static GLib.HashTable<string, IBus.EmojiData>?
+@@ -738,16 +741,53 @@ class IBusEmojier : Gtk.Window {
+         }
+         // Call check_unicode_point() to get m_unicode_point
+         check_unicode_point();
+-        unowned GLib.SList<string>? emojis =
+-            m_annotation_to_emojis_dict.lookup(annotation);
+-        if (emojis == null && m_unicode_point == null) {
++        GLib.SList<string>? total_emojis = null;
++        unowned GLib.SList<string>? sub_emojis = null;
++        int length = annotation.length;
++        if (m_has_partial_match && length >= m_partial_match_length) {
++            foreach (unowned string key in
++                     m_annotation_to_emojis_dict.get_keys()) {
++                if (key.length < length)
++                    continue;
++                bool matched = false;
++                switch(m_partial_match_condition) {
++                case 0:
++                    if (key.has_prefix(annotation))
++                        matched = true;
++                    break;
++                case 1:
++                    if (key.has_suffix(annotation))
++                        matched = true;
++                    break;
++                case 2:
++                    if (key.str(annotation) != null)
++                        matched = true;
++                    break;
++                default:
++                    break;
++                }
++                if (!matched)
++                    continue;
++                sub_emojis = m_annotation_to_emojis_dict.lookup(key);
++                foreach (unowned string emoji in sub_emojis) {
++                    if (total_emojis.find_custom(emoji, GLib.strcmp) == null) {
++                        total_emojis.append(emoji);
++                    }
++                }
++            }
++        } else {
++            sub_emojis = m_annotation_to_emojis_dict.lookup(annotation);
++            foreach (unowned string emoji in sub_emojis)
++                total_emojis.append(emoji);
++        }
++        if (total_emojis == null && m_unicode_point == null) {
+             hide_candidate_panel();
+             return;
+         }
+         m_lookup_table.clear();
+         // Call check_unicode_point() to update m_lookup_table
+         check_unicode_point();
+-        foreach (unowned string emoji in emojis) {
++        foreach (unowned string emoji in total_emojis) {
+             IBus.Text text = new IBus.Text.from_string(emoji);
+             m_lookup_table.append_candidate(text);
+         }
+@@ -1331,6 +1371,22 @@ class IBusEmojier : Gtk.Window {
+     }
+ 
+ 
++    public static void set_partial_match(bool has_partial_match) {
++        m_has_partial_match = has_partial_match;
++    }
++
++    public static void set_partial_match_length(int length) {
++        if (length < 1)
++            return;
++        m_partial_match_length = length;
++    }
++
++    public static void set_partial_match_condition(int condition) {
++        if (condition < 0)
++            return;
++        m_partial_match_condition = condition;
++    }
++
+     public static void set_favorites(string[]? unowned_favorites) {
+         m_favorites = {};
+         foreach (string favorite in unowned_favorites) {
+diff --git a/ui/gtk3/emojierapp.vala b/ui/gtk3/emojierapp.vala
+index cbdd8ba..dbdbc27 100644
+--- a/ui/gtk3/emojierapp.vala
++++ b/ui/gtk3/emojierapp.vala
+@@ -22,6 +22,9 @@
+ 
+ string emoji_font = null;
+ string annotation_lang = null;
++bool partial_match = false;
++int partial_match_length = -1;
++int partial_match_condition = -1;
+ 
+ public class EmojiApplication : Application {
+     private IBusEmojier? m_emojier;
+@@ -65,17 +68,28 @@ public class EmojiApplication : Application {
+ 
+         const OptionEntry[] options = {
+             { "font", 0, 0, OptionArg.STRING, out emoji_font,
+-                /* TRANSLATORS: "FONT" should be capital and translatable.
+-                 * It's used for an argument command --font=FONT
+-                 */
+-                N_("\"FONT\" for emoji chracters on emoji dialog"),
+-                N_("FONT") },
++              /* TRANSLATORS: "FONT" should be capital and translatable.
++               * It's used for an argument command --font=FONT
++               */
++              N_("\"FONT\" for emoji chracters on emoji dialog"),
++              N_("FONT") },
+             { "lang", 0, 0, OptionArg.STRING, out annotation_lang,
+-                /* TRANSLATORS: "LANG" should be capital and translatable.
+-                 * It's used for an argument command --lang=LANG
+-                 */
+-                N_("\"LANG\" for annotations on emoji dialog. E.g. \"en\""),
+-                N_("LANG") },
++              /* TRANSLATORS: "LANG" should be capital and translatable.
++               * It's used for an argument command --lang=LANG
++               */
++              N_("\"LANG\" for annotations on emoji dialog. E.g. \"en\""),
++              N_("LANG") },
++            { "partial-match", 0, 0, OptionArg.NONE, out partial_match,
++              N_("Emoji annotaions can be match partially"),
++              null },
++            { "partial-match-length", 0, 0, OptionArg.INT,
++              out partial_match_length,
++              N_("Match with the length of the specified integer"),
++              null },
++            { "partial-match-condition", 0, 0, OptionArg.INT,
++              out partial_match_condition,
++              N_("Match with the condition of the specified integer"),
++              null },
+             { null }
+         };
+ 
+@@ -111,6 +125,24 @@ public class EmojiApplication : Application {
+         if (annotation_lang == null)
+             annotation_lang = m_settings_emoji.get_string("lang");
+         IBusEmojier.set_annotation_lang(annotation_lang);
++        IBusEmojier.set_partial_match(partial_match);
++        if (partial_match_length > 0) {
++            IBusEmojier.set_partial_match_length(partial_match_length);
++        } else {
++            IBusEmojier.set_partial_match_length(
++                    m_settings_emoji.get_int("partial-match-length"));
++        }
++        if (partial_match_condition > 2) {
++            warning("Need condition between 0 and 2.");
++            IBusEmojier.set_partial_match_condition(
++                    m_settings_emoji.get_int("partial-match-condition"));
++        }
++        else if (partial_match_condition >= 0) {
++            IBusEmojier.set_partial_match_condition(partial_match_condition);
++        } else {
++            IBusEmojier.set_partial_match_condition(
++                    m_settings_emoji.get_int("partial-match-condition"));
++        }
+ 
+         if (emoji_font != null)
+             IBusEmojier.set_emoji_font(emoji_font);
+diff --git a/ui/gtk3/panel.vala b/ui/gtk3/panel.vala
+index 745489b..5f0009e 100644
+--- a/ui/gtk3/panel.vala
++++ b/ui/gtk3/panel.vala
+@@ -248,6 +248,18 @@ class Panel : IBus.PanelService {
+         m_settings_emoji.changed["lang"].connect((key) => {
+                 set_emoji_lang();
+         });
++
++        m_settings_emoji.changed["has-partial-match"].connect((key) => {
++                set_emoji_partial_match();
++        });
++
++        m_settings_emoji.changed["partial-match-length"].connect((key) => {
++                set_emoji_partial_match();
++        });
++
++        m_settings_emoji.changed["partial-match-condition"].connect((key) => {
++                set_emoji_partial_match();
++        });
+     }
+ 
+ #if INDICATOR
+@@ -782,6 +794,15 @@ class Panel : IBus.PanelService {
+         });
+     }
+ 
++    private void set_emoji_partial_match() {
++        IBusEmojier.set_partial_match(
++                m_settings_emoji.get_boolean("has-partial-match"));
++        IBusEmojier.set_partial_match_length(
++                m_settings_emoji.get_int("partial-match-length"));
++        IBusEmojier.set_partial_match_condition(
++                m_settings_emoji.get_int("partial-match-condition"));
++    }
++
+     private int compare_versions(string version1, string version2) {
+         string[] version1_list = version1.split(".");
+         string[] version2_list = version2.split(".");
+@@ -897,6 +918,7 @@ class Panel : IBus.PanelService {
+         set_property_icon_delay_time();
+         set_emoji_favorites();
+         set_emoji_lang();
++        set_emoji_partial_match();
+     }
+ 
+     private void engine_contexts_insert(IBus.EngineDesc engine) {
+-- 
+2.9.3
+
+From edcb4a0259d2833904e7d1aac7c74e1aa49cea5b Mon Sep 17 00:00:00 2001
+From: fujiwarat <takao.fujiwara1@gmail.com>
+Date: Mon, 8 May 2017 12:25:54 +0900
+Subject: [PATCH] ui/gtk3: Hide emoji variants by default
+
+The emoji variants, i.e. skin colors and additional items, would not
+be used in most cases and it is nice to hide it by default.
+Now added GtkMenu and changed GtkWindow to GtkApplicationWindow
+for the menu.
+
+R=penghuang@google.com
+
+Review URL: https://codereview.appspot.com/322970043
+---
+ ui/gtk3/emojier.vala | 299 ++++++++++++++++++++++++++++++++++++---------------
+ 1 file changed, 211 insertions(+), 88 deletions(-)
+
+diff --git a/ui/gtk3/emojier.vala b/ui/gtk3/emojier.vala
+index 76d5fed..db7520a 100644
+--- a/ui/gtk3/emojier.vala
++++ b/ui/gtk3/emojier.vala
+@@ -20,7 +20,7 @@
+  * USA
+  */
+ 
+-class IBusEmojier : Gtk.Window {
++class IBusEmojier : Gtk.ApplicationWindow {
+     private class EEntry : Gtk.SearchEntry {
+         public EEntry() {
+             GLib.Object(
+@@ -97,6 +97,15 @@ class IBusEmojier : Gtk.Window {
+                 set_label(text);
+         }
+     }
++    private class EGoldLabel : Gtk.Label {
++        public EGoldLabel(string text) {
++            GLib.Object(
++                name : "IBusEmojierGoldLabel"
++            );
++            if (text != "")
++                set_label(text);
++        }
++    }
+     private class EPaddedLabel : Gtk.Label {
+         public EPaddedLabel(string          text,
+                             Gtk.Align       align) {
+@@ -150,11 +159,21 @@ class IBusEmojier : Gtk.Window {
+             var vbox = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
+             set_custom_title(vbox);
+             var label = new Gtk.Label(title);
+-            label.get_style_context().add_class("title");
++            label.get_style_context().add_class(Gtk.STYLE_CLASS_TITLE);
+             vbox.pack_start(label, true, false, 0);
+             m_lang_label = new Gtk.Label(null);
+-            m_lang_label.get_style_context().add_class("subtitle");
++            m_lang_label.get_style_context().add_class(
++                    Gtk.STYLE_CLASS_SUBTITLE);
+             vbox.pack_start(m_lang_label, true, false, 0);
++
++            var menu = new GLib.Menu();
++            menu.append(_("Show emoji variants"), "win.variant");
++            var menu_button = new Gtk.MenuButton();
++            menu_button.set_direction(Gtk.ArrowType.NONE);
++            menu_button.set_valign(Gtk.Align.CENTER);
++            menu_button.set_menu_model(menu);
++            menu_button.set_tooltip_text(_("Menu"));
++            pack_end(menu_button);
+         }
+         public void set_lang_label(string str) {
+             m_lang_label.set_text(str);
+@@ -167,7 +186,13 @@ class IBusEmojier : Gtk.Window {
+     }
+ 
+     private const uint EMOJI_GRID_PAGE = 10;
++    private const string EMOJI_CATEGORY_FAVORITES = N_("Favorites");
+     private const string EMOJI_CATEGORY_OTHERS = N_("Others");
++    private const unichar[] EMOJI_VARIANT_LIST = {
++            0x1f3fb, 0x1f3fc, 0x1f3fd, 0x1f3fe, 0x1f3ff, 0x200d };
++    private const GLib.ActionEntry[] m_action_entries = {
++        { "variant", check_action_variant_cb, null, "false", null }
++    };
+ 
+     // Set the actual default values in the constructor
+     // because these fields are used for class_init() and static functions,
+@@ -180,18 +205,22 @@ class IBusEmojier : Gtk.Window {
+     private static bool m_has_partial_match;
+     private static uint m_partial_match_length;
+     private static uint m_partial_match_condition;
+-    private static GLib.HashTable<string, GLib.SList>?
++    private static bool m_show_emoji_variant = false;
++    private static GLib.HashTable<string, GLib.SList<string>>?
+             m_annotation_to_emojis_dict;
+     private static GLib.HashTable<string, IBus.EmojiData>?
+             m_emoji_to_data_dict;
+-    private static GLib.HashTable<string, GLib.SList>?
++    private static GLib.HashTable<string, GLib.SList<string>>?
+             m_category_to_emojis_dict;
++    private static GLib.HashTable<string, GLib.SList<string>>?
++            m_emoji_to_emoji_variants_dict;
+ 
+     private ThemedRGBA m_rgba;
+     private Gtk.Box m_vbox;
+     private ETitleLabelBox m_title;
+     private EEntry m_entry;
+     private string? m_backward;
++    private int m_backward_index = -1;
+     private EScrolledWindow? m_scrolled_window = null;
+     private EListBox m_list_box;
+     private bool m_is_running = false;
+@@ -200,7 +229,7 @@ class IBusEmojier : Gtk.Window {
+     private string? m_result;
+     private string? m_unicode_point = null;
+     private bool m_candidate_panel_is_visible;
+-    int m_category_active_index;
++    private int m_category_active_index;
+     private IBus.LookupTable m_lookup_table;
+     private Gtk.Label[] m_candidates;
+     private bool m_enter_notify_enable = true;
+@@ -223,6 +252,7 @@ class IBusEmojier : Gtk.Window {
+             focus_visible : true
+         );
+ 
++        add_action_entries(m_action_entries, this);
+         if (m_current_lang_id == null)
+             m_current_lang_id = "en";
+         if (m_emoji_font_family == null)
+@@ -270,6 +300,13 @@ class IBusEmojier : Gtk.Window {
+                         "rgba(%u, %u, %u, %lf); ".printf(
+                         bg_red, bg_green, bg_blue, bg_alpha) +
+                 "border-width: 4px; border-radius: 3px; }";
++        data += "#IBusEmojierGoldLabel { color: " +
++                        "rgba(%u, %u, %u, %lf); ".printf(
++                        fg_red, fg_green, fg_blue, fg_alpha) +
++                "font-family: %s; font-size: %dpt; ".printf(
++                        m_emoji_font_family, m_emoji_font_size) +
++                "background-color: #b09c5f; " +
++                "border-width: 4px; border-radius: 3px; }";
+ 
+         Gtk.CssProvider css_provider = new Gtk.CssProvider();
+         try {
+@@ -317,10 +354,7 @@ class IBusEmojier : Gtk.Window {
+         });
+ 
+         candidate_clicked.connect((i, b, s) => {
+-            IBus.Text candidate = m_lookup_table.get_candidate(i);
+-            m_result = candidate.text;
+-            m_loop.quit();
+-            hide_candidate_panel();
++            candidate_panel_select_index(i);
+         });
+ 
+         if (m_annotation_to_emojis_dict == null) {
+@@ -345,14 +379,17 @@ class IBusEmojier : Gtk.Window {
+ 
+     private static void init_emoji_dict() {
+         m_annotation_to_emojis_dict =
+-                new GLib.HashTable<string, GLib.SList>(GLib.str_hash,
+-                                                       GLib.str_equal);
++                new GLib.HashTable<string, GLib.SList<string>>(GLib.str_hash,
++                                                               GLib.str_equal);
+         m_emoji_to_data_dict =
+                 new GLib.HashTable<string, IBus.EmojiData>(GLib.str_hash,
+                                                            GLib.str_equal);
+         m_category_to_emojis_dict =
+-                new GLib.HashTable<string, GLib.SList>(GLib.str_hash,
+-                                                       GLib.str_equal);
++                new GLib.HashTable<string, GLib.SList<string>>(GLib.str_hash,
++                                                               GLib.str_equal);
++        m_emoji_to_emoji_variants_dict =
++                new GLib.HashTable<string, GLib.SList<string>>(GLib.str_hash,
++                                                               GLib.str_equal);
+     }
+ 
+ 
+@@ -390,14 +427,16 @@ class IBusEmojier : Gtk.Window {
+             }
+             if (!has_emoji) {
+                 hits.append(emoji);
+-                m_annotation_to_emojis_dict.replace(annotation, hits.copy());
++                m_annotation_to_emojis_dict.replace(
++                        annotation,
++                        hits.copy_deep(GLib.strdup));
+             }
+         }
+     }
+ 
+ 
+     private static string utf8_down(string str) {
+-        GLib.StringBuilder buff = new GLib.StringBuilder();
++        var buff = new GLib.StringBuilder();
+         int length = str.char_count();
+         for (int i = 0; i < length; i++) {
+             buff.append_unichar(str.get_char(0).tolower());
+@@ -407,23 +446,8 @@ class IBusEmojier : Gtk.Window {
+     }
+ 
+ 
+-    private static string utf8_title(string str) {
+-        StringBuilder buff = new StringBuilder();
+-        int length = str.char_count();
+-        for (int i = 0; i < length; i++) {
+-            unichar ch = str.get_char(0);
+-            if (i == 0)
+-                buff.append_unichar(ch.toupper());
+-            else
+-                buff.append_unichar(ch);
+-            str = str.next_char();
+-        }
+-        return buff.str;
+-    }
+-
+-
+     private static string utf8_code_point(string str) {
+-        StringBuilder buff = new StringBuilder();
++        var buff = new GLib.StringBuilder();
+         int length = str.char_count();
+         for (int i = 0; i < length; i++) {
+             unichar ch = str.get_char(0);
+@@ -438,7 +462,7 @@ class IBusEmojier : Gtk.Window {
+ 
+ 
+     private static string utf8_entity(string str) {
+-        GLib.StringBuilder buff = new GLib.StringBuilder();
++        var buff = new GLib.StringBuilder();
+         int length = str.char_count();
+         for (int i = 0; i < length; i++) {
+             unichar ch = str.get_char(0);
+@@ -503,8 +527,19 @@ class IBusEmojier : Gtk.Window {
+             update_annotations_with_description (data, description);
+             m_emoji_to_data_dict.replace(emoji, data);
+         } else {
+-            unowned IBus.EmojiData? en_data =
+-                    m_emoji_to_data_dict.lookup(emoji);
++            unowned IBus.EmojiData? en_data = null;
++            // If emoji presentation (+= 0xfe0f) is already saved in dict,
++            // update it instead of no presentation.
++            // emoji-test.txt has all emoji presentations but $lang.xml has
++            // some no emoji presentations.
++            if (emoji.chr(-1, 0xfe0f) == null) {
++                var buff = new GLib.StringBuilder();
++                buff.append(emoji);
++                buff.append_unichar(0xfe0f);
++                en_data = m_emoji_to_data_dict.lookup(buff.str);
++            }
++            if (en_data == null)
++                en_data = m_emoji_to_data_dict.lookup(emoji);
+             if (en_data == null) {
+                 m_emoji_to_data_dict.insert(emoji, data);
+                 return;
+@@ -536,6 +571,36 @@ class IBusEmojier : Gtk.Window {
+         if (category == "")
+             category = EMOJI_CATEGORY_OTHERS;
+         if (lang == "en") {
++            bool has_variant = false;
++            foreach (unichar ch in EMOJI_VARIANT_LIST) {
++                if (emoji.chr(-1, ch) != null) {
++                    has_variant = true;
++                    break;
++                }
++            }
++            // If emoji includes variants (skin colors and items),
++            // it's escaped in m_emoji_to_emoji_variants_dict and
++            // not shown by default.
++            if (has_variant) {
++                unichar base_ch = emoji.get_char();
++                string base_emoji  = base_ch.to_string();
++                var buff = new GLib.StringBuilder();
++                buff.append_unichar(base_ch);
++                buff.append_unichar(0xfe0f);
++                if (m_emoji_to_data_dict.lookup(buff.str) != null)
++                    base_emoji = buff.str;
++                unowned GLib.SList<string>? variants =
++                    m_emoji_to_emoji_variants_dict.lookup(base_emoji);
++                if (variants.find_custom(emoji, GLib.strcmp) == null) {
++                    if (variants == null)
++                        variants.append(base_emoji);
++                    variants.append(emoji);
++                    m_emoji_to_emoji_variants_dict.replace(
++                            base_emoji,
++                            variants.copy_deep(GLib.strdup));
++                }
++                return;
++            }
+             bool has_emoji = false;
+             unowned GLib.SList<string> hits =
+                     m_category_to_emojis_dict.lookup(category);
+@@ -547,7 +612,8 @@ class IBusEmojier : Gtk.Window {
+             }
+             if (!has_emoji) {
+                 hits.append(emoji);
+-                m_category_to_emojis_dict.replace(category, hits.copy());
++                m_category_to_emojis_dict.replace(category,
++                                                  hits.copy_deep(GLib.strdup));
+             }
+         }
+     }
+@@ -588,14 +654,15 @@ class IBusEmojier : Gtk.Window {
+         m_list_box.row_activated.connect((box, gtkrow) => {
+             m_category_active_index = 0;
+             EBoxRow row = gtkrow as EBoxRow;
+-            show_emoji_for_category(row);
++            show_emoji_for_category(row.text);
+         });
+ 
+         uint n = 1;
+         if (m_favorites.length > 0) {
+-            EBoxRow row = new EBoxRow("@favorites");
++            EBoxRow row = new EBoxRow(EMOJI_CATEGORY_FAVORITES);
+             EPaddedLabelBox widget =
+-                    new EPaddedLabelBox(_("Favorites"), Gtk.Align.CENTER);
++                    new EPaddedLabelBox(_(EMOJI_CATEGORY_FAVORITES),
++                                        Gtk.Align.CENTER);
+             row.add(widget);
+             m_list_box.add(row);
+             if (n++ == m_category_active_index)
+@@ -617,10 +684,8 @@ class IBusEmojier : Gtk.Window {
+             if (category == EMOJI_CATEGORY_OTHERS)
+                continue;
+             EBoxRow row = new EBoxRow(category);
+-            string locale_category = _(category);
+             EPaddedLabelBox widget =
+-                    new EPaddedLabelBox(utf8_title(locale_category),
+-                                        Gtk.Align.CENTER);
++                    new EPaddedLabelBox(_(category), Gtk.Align.CENTER);
+             row.add(widget);
+             m_list_box.add(row);
+             if (n++ == m_category_active_index)
+@@ -635,23 +700,40 @@ class IBusEmojier : Gtk.Window {
+     }
+ 
+ 
+-    private void show_emoji_for_category(EBoxRow row) {
+-        if (row.text == "@favorites") {
++    private void show_emoji_for_category(string category) {
++        if (category == EMOJI_CATEGORY_FAVORITES) {
+             m_lookup_table.clear();
+             foreach (unowned string favorate in m_favorites) {
+                 IBus.Text text = new IBus.Text.from_string(favorate);
+                 m_lookup_table.append_candidate(text);
+             }
+-            m_backward = _("Favorites");
++            m_backward = category;
+         } else {
+             unowned GLib.SList<unowned string> emojis =
+-                    m_category_to_emojis_dict.lookup(row.text);
++                    m_category_to_emojis_dict.lookup(category);
+             m_lookup_table.clear();
+             foreach (unowned string emoji in emojis) {
+                 IBus.Text text = new IBus.Text.from_string(emoji);
+                 m_lookup_table.append_candidate(text);
+             }
+-            m_backward = utf8_title(row.text);
++            m_backward = category;
++        }
++        // Restore the cursor position before the special table of
++        // emoji variants is shown.
++        if (m_backward_index >= 0) {
++            m_lookup_table.set_cursor_pos((uint)m_backward_index);
++            m_backward_index = -1;
++        }
++        show_candidate_panel();
++    }
++
++
++    private void show_emoji_variants(GLib.SList<string>? emojis) {
++        m_backward_index = (int)m_lookup_table.get_cursor_pos();
++        m_lookup_table.clear();
++        foreach (unowned string emoji in emojis) {
++            IBus.Text text = new IBus.Text.from_string(emoji);
++            m_lookup_table.append_candidate(text);
+         }
+         show_candidate_panel();
+     }
+@@ -696,8 +778,8 @@ class IBusEmojier : Gtk.Window {
+     private bool check_unicode_point() {
+         string annotation = m_entry.get_text();
+         m_unicode_point = null;
+-        GLib.StringBuilder buff = new GLib.StringBuilder();
+-        GLib.StringBuilder retval = new GLib.StringBuilder();
++        var buff = new GLib.StringBuilder();
++        var retval = new GLib.StringBuilder();
+         for (int i = 0; i < annotation.char_count(); i++) {
+             unichar ch = annotation.get_char(i);
+             if (ch == 0)
+@@ -727,7 +809,7 @@ class IBusEmojier : Gtk.Window {
+     }
+ 
+ 
+-    public void update_candidate_window() {
++    private void update_candidate_window() {
+         string annotation = m_entry.get_text();
+         if (annotation.length == 0) {
+             hide_candidate_panel();
+@@ -795,6 +877,22 @@ class IBusEmojier : Gtk.Window {
+     }
+ 
+ 
++    private void show_code_point_description(string text) {
++        EPaddedLabelBox widget_code = new EPaddedLabelBox(
++                    _("Code point: %s").printf(utf8_code_point(text)),
++                    Gtk.Align.START);
++        m_vbox.add(widget_code);
++        widget_code.show_all();
++        if (m_emoji_to_emoji_variants_dict.lookup(text) != null) {
++            EPaddedLabelBox widget_has_variant = new EPaddedLabelBox(
++                    _("Has emoji variants"),
++                    Gtk.Align.START);
++            m_vbox.add(widget_has_variant);
++            widget_has_variant.show_all();
++        }
++    }
++
++
+     private void show_candidate_panel() {
+         remove_all_children();
+         set_fixed_size();
+@@ -823,18 +921,27 @@ class IBusEmojier : Gtk.Window {
+         EGrid grid = new EGrid();
+         int n = 0;
+         for (uint i = page_start_pos; i < page_end_pos; i++) {
+-            IBus.Text candidate = m_lookup_table.get_candidate(i);
++            string text = m_lookup_table.get_candidate(i).text;
++            bool has_variant =
++                    (m_emoji_to_emoji_variants_dict.lookup(text) != null);
+             Gtk.Label label;
+-            if (i == cursor)
+-                label = new ESelectedLabel(candidate.text) as Gtk.Label;
+-            else
+-                label = new EWhiteLabel(candidate.text) as Gtk.Label;
+-            if (candidate.text.char_count() > 2) {
++            // If 'i' is the cursor position, use the selected color.
++            // If the emoji has emoji variants, use the gold color.
++            // Otherwise the white color.
++            if (i == cursor) {
++                label = new ESelectedLabel(text) as Gtk.Label;
++            } else if (m_show_emoji_variant && has_variant &&
++                       m_backward_index < 0) {
++                label = new EGoldLabel(text) as Gtk.Label;
++            } else {
++                label = new EWhiteLabel(text) as Gtk.Label;
++            }
++            if (text.char_count() > 2) {
+                 string font_family = m_emoji_font_family;
+                 int font_size = m_emoji_font_size - 2;
+                 string emoji_font = "%s %d".printf(font_family, font_size);
+                 string markup = "<span font=\"%s\">%s</span>".
+-                        printf(emoji_font, utf8_entity(candidate.get_text()));
++                        printf(emoji_font, utf8_entity(text));
+                 label.set_markup(markup);
+             }
+             label.set_halign(Gtk.Align.FILL);
+@@ -879,9 +986,8 @@ class IBusEmojier : Gtk.Window {
+             show_arrow_buttons();
+             m_vbox.add(grid);
+             grid.show_all();
+-            IBus.Text candidate = m_lookup_table.get_candidate(cursor);
+-            unowned IBus.EmojiData? data =
+-                    m_emoji_to_data_dict.lookup(candidate.text);
++            string text = m_lookup_table.get_candidate(cursor).text;
++            unowned IBus.EmojiData? data = m_emoji_to_data_dict.lookup(text);
+             if (data == null) {
+                 // TODO: Provide a custom description and annotation for
+                 // the favorite emojis.
+@@ -890,12 +996,7 @@ class IBusEmojier : Gtk.Window {
+                         Gtk.Align.START);
+                 m_vbox.add(widget);
+                 widget.show_all();
+-                EPaddedLabelBox widget_code = new EPaddedLabelBox(
+-                        _("Code point: %s").printf(
+-                                utf8_code_point(candidate.text)),
+-                        Gtk.Align.START);
+-                m_vbox.add(widget_code);
+-                widget_code.show_all();
++                show_code_point_description(text);
+                 return;
+             } else {
+                 unowned string description = data.get_description();
+@@ -907,7 +1008,7 @@ class IBusEmojier : Gtk.Window {
+             }
+             unowned GLib.SList<unowned string>? annotations =
+                     data.get_annotations();
+-            GLib.StringBuilder buff = new GLib.StringBuilder();
++            var buff = new GLib.StringBuilder();
+             int i = 0;
+             foreach (unowned string annotation in annotations) {
+                 if (i++ == 0)
+@@ -929,12 +1030,7 @@ class IBusEmojier : Gtk.Window {
+                 m_vbox.add(widget);
+                 widget.show_all();
+             }
+-            EPaddedLabelBox widget_code = new EPaddedLabelBox(
+-                    _("Code point: %s").printf(
+-                            utf8_code_point(candidate.text)),
+-                    Gtk.Align.START);
+-            m_vbox.add(widget_code);
+-            widget_code.show_all();
++            show_code_point_description(text);
+         }
+     }
+ 
+@@ -961,6 +1057,20 @@ class IBusEmojier : Gtk.Window {
+     }
+ 
+ 
++    private void candidate_panel_select_index(uint index) {
++        string text = m_lookup_table.get_candidate(index).text;
++        unowned GLib.SList<string>? emojis =
++                m_emoji_to_emoji_variants_dict.lookup(text);
++        if (m_show_emoji_variant && emojis != null &&
++            m_backward_index < 0) {
++            show_emoji_variants(emojis);
++        } else {
++            m_result = text;
++            m_loop.quit();
++            hide_candidate_panel();
++        }
++    }
++
+     private void candidate_panel_cursor_down() {
+         enter_notify_disable_with_timer();
+         uint ncandidates = m_lookup_table.get_number_of_candidates();
+@@ -1094,8 +1204,11 @@ class IBusEmojier : Gtk.Window {
+     }
+ 
+ 
+-    private bool key_press_cursor_escape() {
+-        if (m_candidate_panel_is_visible) {
++    private bool key_press_escape() {
++        if (m_backward_index >= 0 && m_backward != null) {
++            show_emoji_for_category(m_backward);
++            return true;
++        } else if (m_candidate_panel_is_visible) {
+             hide_candidate_panel();
+             return true;
+         } else if (m_entry.get_text().length == 0) {
+@@ -1108,6 +1221,19 @@ class IBusEmojier : Gtk.Window {
+     }
+ 
+ 
++    private bool key_press_enter() {
++        if (m_candidate_panel_is_visible) {
++            uint index = m_lookup_table.get_cursor_pos();
++            candidate_panel_select_index(index);
++        } else if (m_category_active_index > 0) {
++            Gtk.ListBoxRow gtkrow = m_list_box.get_selected_row();
++            EBoxRow row = gtkrow as EBoxRow;
++            show_emoji_for_category(row.text);
++        }
++        return true;
++    }
++
++
+     private void entry_enter_keyval(uint keyval) {
+         unichar ch = IBus.keyval_to_unicode(keyval);
+         if (ch.iscntrl())
+@@ -1130,6 +1256,13 @@ class IBusEmojier : Gtk.Window {
+     }
+ 
+ 
++    private void check_action_variant_cb(GLib.SimpleAction action,
++                                         GLib.Variant?     parameter) {
++        m_show_emoji_variant = !action.get_state().get_boolean();
++        action.set_state(new GLib.Variant.boolean(m_show_emoji_variant));
++    }
++
++
+     public string run(string input_context_path) {
+         assert (m_loop == null);
+ 
+@@ -1187,21 +1320,11 @@ class IBusEmojier : Gtk.Window {
+          */
+         switch (keyval) {
+         case Gdk.Key.Escape:
+-            if (key_press_cursor_escape())
++            if (key_press_escape())
+                 return true;
+             break;
+         case Gdk.Key.Return:
+-            if (m_candidate_panel_is_visible) {
+-                uint index = m_lookup_table.get_cursor_pos();
+-                IBus.Text text = m_lookup_table.get_candidate(index);
+-                m_result = text.text;
+-                m_loop.quit();
+-                hide_candidate_panel();
+-            } else if (m_category_active_index > 0) {
+-                Gtk.ListBoxRow gtkrow = m_list_box.get_selected_row();
+-                EBoxRow row = gtkrow as EBoxRow;
+-                show_emoji_for_category(row);
+-            }
++            key_press_enter();
+             return true;
+         case Gdk.Key.BackSpace:
+             if (m_entry.get_text().len() > 0) {
+@@ -1283,7 +1406,7 @@ class IBusEmojier : Gtk.Window {
+                     return true;
+                 break;
+             case Gdk.Key.u:
+-                if (key_press_cursor_escape())
++                if (key_press_escape())
+                     return true;
+                 break;
+             case Gdk.Key.a:
+-- 
+2.9.3
+
+From 5f653d3102ada9139a2bc7504d6beaee1bc9984b Mon Sep 17 00:00:00 2001
+From: fujiwarat <takao.fujiwara1@gmail.com>
+Date: Tue, 9 May 2017 13:54:01 +0900
+Subject: [PATCH] ui/gtk3: Add ibus-emoji man mapge
+
+R=Shawn.P.Huang@gmail.com
+
+Review URL: https://codereview.appspot.com/323810043
+---
+ setup/ibus-setup.1.in   | 21 +++++++++++--
+ tools/ibus.1.in         | 20 ++++++++++--
+ ui/gtk3/Makefile.am     | 22 ++++++++++++++
+ ui/gtk3/ibus-emoji.1.in | 81 +++++++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 140 insertions(+), 4 deletions(-)
+ create mode 100644 ui/gtk3/ibus-emoji.1.in
+
+diff --git a/setup/ibus-setup.1.in b/setup/ibus-setup.1.in
+index dab032e..f9b5f71 100644
+--- a/setup/ibus-setup.1.in
++++ b/setup/ibus-setup.1.in
+@@ -1,10 +1,10 @@
+ .\" This file is distributed under the same license as the ibus
+ .\" package.
+ .\" Copyright (C) LI Daobing <lidaobing@gmail.com>, 2008.
+-.\" Copyright (C) Takao Fujiwara <takao.fujiwara1@gmail.com>, 2013-2015.
++.\" Copyright (C) Takao Fujiwara <takao.fujiwara1@gmail.com>, 2013-2017.
+ .\" Copyright (c) Peng Huang <shawn.p.huang@gmail.com>, 2013.
+ .\"
+-.TH "IBUS-SETUP" 1 "November 2008" "@VERSION@" "User Commands"
++.TH "IBUS-SETUP" 1 "November 2017" "@VERSION@" "User Commands"
+ .SH NAME
+ .B ibus-setup
+ \- configuration program for ibus
+@@ -26,6 +26,23 @@ is the configuration program for IBus.
+ .PP
+ Homepage: https://github.com/ibus/ibus/wiki
+ 
++.SH "ADVANCED"
++.TP
++\fBUse system keyboard layout\fR
++If this option is enabled, use your system keymap instead and IBus
++does not change it with any input method engines. The system keymap is
++decided by your desktop session. IBus calls
++.B setxkbmap (1)
++command internally to set the selected keymap and override the
++system keymap if this options is disabled.
++You can check the current keymap with
++.B setxkbmap -query
++command.
++.TP
++\fBShare the same input method among all applications\fR
++If this option is disabled, You can choose an input metod engine
++by input context.
++
+ .SH BUGS
+ If you find a bug, please report it at http://code.google.com/p/ibus/issues/list
+ 
+diff --git a/tools/ibus.1.in b/tools/ibus.1.in
+index a420567..d34a77a 100644
+--- a/tools/ibus.1.in
++++ b/tools/ibus.1.in
+@@ -1,9 +1,9 @@
+ .\" This file is distributed under the same license as the ibus
+ .\" package.
+-.\" Copyright (C) Takao Fujiwara <takao.fujiwara1@gmail.com>, 2013.
++.\" Copyright (C) Takao Fujiwara <takao.fujiwara1@gmail.com>, 2013-2017.
+ .\" Copyright (c) Peng Huang <shawn.p.huang@gmail.com>, 2013.
+ .\"
+-.TH "IBUS" 1 "May 2013" "@VERSION@" "User Commands"
++.TH "IBUS" 1 "May 2017" "@VERSION@" "User Commands"
+ .SH NAME
+ .B ibus
+ \- command line utility for ibus
+@@ -95,6 +95,22 @@ configuration file.
+ \fBwatch\fR
+ Under construction.
+ .TP
++\fBemoji\fR [\fB\-\-font=FONT|\-\-lang=LANG|\-\-help|\-\-partial\-match\fR]
++Launch IBus Emojier (
++.B ibus\-emoji (1)
++) and save the selected emoji to your clipboard. Can choose an emoji font with
++.B \-\-font
++option. Can choose a language of emoji annotations with
++.B \-\-lang
++option. If LANG="en", IBus Emojier loads /usr/share/ibus/dicts/emoji-en.dict .
++.B \-\-partial\-match
++option enables to match annotations with a partial string. These settings
++are avaiable with
++.B ibus\-setup (1)
++utility.
+ 
+ .SH BUGS
+ If you find a bug, please report it at https://github.com/ibus/ibus/issues
++
++.SH "SEE ALSO"
++.BR ibus-emoji (1)
+diff --git a/ui/gtk3/Makefile.am b/ui/gtk3/Makefile.am
+index c557474..270ad1c 100644
+--- a/ui/gtk3/Makefile.am
++++ b/ui/gtk3/Makefile.am
+@@ -148,6 +148,8 @@ emoji_headers =         \
+     ibusemojidialog.h   \
+     $(NULL)
+ 
++man_one_in_files = ibus-emoji.1.in
++
+ # References:
+ # libappindicator/src/notification-item.xml
+ # libappindicator/src/notification-watcher.xml
+@@ -155,6 +157,7 @@ emoji_headers =         \
+ # kdelibs/kdeui/knotifications/src/org.kde.StatusNotifierWatcher.xml
+ EXTRA_DIST =                            \
+     $(emoji_headers)                    \
++    $(man_one_in_files)                 \
+     IBusEmojiDialog-1.0.metadata        \
+     gtkpanel.xml.in                     \
+     ibus-emoji-dialog-1.0.deps          \
+@@ -253,8 +256,27 @@ MAINTAINERCLEANFILES += $(VAPIGEN_VAPIS)
+ DISTCLEANFILES += $(VAPIGEN_VAPIS)
+ EXTRA_DIST += $(VAPIGEN_VAPIS)
+ 
++# end of ENABLE_VAPIGEN
+ endif
++# end of HAVE_INTROSPECTION
+ endif
++
++man_one_files = $(man_one_in_files:.1.in=.1)
++man_one_DATA =$(man_one_files:.1=.1.gz)
++man_onedir = $(mandir)/man1
++%.1: %.1.in
++	$(AM_V_GEN) sed \
++	    -e 's|@VERSION[@]|$(VERSION)|g' $< > $@.tmp && \
++	    mv $@.tmp $@
++%.1.gz: %.1
++	$(AM_V_GEN) gzip -c $< > $@.tmp && mv $@.tmp $@
++
++CLEANFILES += \
++    $(man_one_DATA) \
++    $(man_one_files) \
++    $(NULL)
++
++# end of ENABLE_EMOJI_DICT
+ endif
+ 
+ -include $(top_srcdir)/git.mk
+diff --git a/ui/gtk3/ibus-emoji.1.in b/ui/gtk3/ibus-emoji.1.in
+new file mode 100644
+index 0000000..3523271
+--- /dev/null
++++ b/ui/gtk3/ibus-emoji.1.in
+@@ -0,0 +1,81 @@
++.\" This file is distributed under the same license as the ibus
++.\" package.
++.\" Copyright (C) Takao Fujiwara <takao.fujiwara1@gmail.com>, 2017.
++.\"
++.TH "IBUS EMOJI" 1 "May 2017" "@VERSION@" "User Commands"
++.SH NAME
++.B ibus emoji utility
++\- Call the IBus emoji utility by
++.B IBus Emojier
++
++.SH "SYNOPSIS"
++.B /usr/libexec/ibus\-ui\-emojier
++[\fIOPTION\fR]...
++
++.SH "DESCRIPTION"
++
++.PP
++IBus Emojier provides a GUI to select an emoji by typing an emoji annotaion
++or choosing a character with mouse click and it's designed to work as
++an extended IBus lookup window using Space, Enter, and Arrow keys.
++The text entry accepts an emoji annotation or Unicode points.
++If IBus panel is launched, IBus panel calls IBus Emojier with a
++shortcut key or the right click menu and output the selected emoji
++on the previous focused text on an application.
++If IBus panel is not available likes GNOME desktop, You can still use
++.B ibus emoji
++command to launch IBus Emojier and it saves the selected emoji in
++your clipboard and you can paste the emoji by a paste key likes
++Control\-v.
++
++.PP
++Refer
++.B emoji
++section in
++.B ibus (1)
++for the command line options.
++
++.PP
++Homepage: https://github.com/ibus/ibus/wiki
++
++.SH "SETTINGS"
++.TP
++\fBANNOTATION LANGUAGE\fR
++You can choose a language of emoji annotations with
++.B ibus\-setup (1).
++.TP
++\fBFONT\fR
++You can choose an emoji font with
++.B ibus\-setup (1).
++E.g. "Noto Color Emoji", "Android Emoji" font.
++
++.SH "KEYBOARD OPERATIONS"
++.TP
++\fBControl-Shift-e\fR
++Launch IBus Emojier. The shortcut key can be customized by
++.B ibus\-setup (1).
++.TP
++\fBLeft or right arrow\fR
++Move the selected category or emoji if an annotation is not typed.
++Otherwise move the cursor in typed annotation.
++.TP
++\fBDown or up arrow\fR
++Move the selected category or emoji.
++.TP
++\fBEnter\fR
++Commit the selected emoji.
++.TP
++\fBEscape\fR
++Go back to the category list from emoji list, erase a typed annotation,
++and close IBus Emojier.
++.TP
++\fBSpace\fR
++Move the selected category or emoji. If Shift\-Space is typed,
++a space chararacter can be inserted between words in an annotation or
++Unicode points. E.g. 1f466 Shift\-Space 1f3fb
++.TP
++\fBPageDown or PageUp\fR
++Move to the next or previous page in emoji list.
++
++.SH BUGS
++If you find a bug, please report it at https://github.com/ibus/ibus/issues
+-- 
+2.9.3
+
+From 1159093dea3fdb8ceb62157f06b3560f8fc28378 Mon Sep 17 00:00:00 2001
+From: fujiwarat <takao.fujiwara1@gmail.com>
+Date: Tue, 9 May 2017 13:58:02 +0900
+Subject: [PATCH] Update favorites category automatically by selecting
+ emoji
+
+When you commit an emoji with Emojier, Favorite category
+will be shown on GUI.
+Now a custom annotation also can be assigned to a favorite emoji
+by gsetting command.
+
+R=penghuang@google.com
+
+Review URL: https://codereview.appspot.com/312660043
+---
+ data/ibus.schemas.in      | 13 ++++++++++
+ src/ibusemoji.h           |  2 +-
+ ui/gtk3/emojier.vala      | 63 +++++++++++++++++++++++++++++++++++++++++++++--
+ ui/gtk3/emojierapp.vala   | 18 ++++++++++++++
+ ui/gtk3/ibusemojidialog.h | 20 ++++++++++-----
+ ui/gtk3/panel.vala        | 21 +++++++++++++++-
+ 6 files changed, 127 insertions(+), 10 deletions(-)
+
+diff --git a/data/ibus.schemas.in b/data/ibus.schemas.in
+index 0647004..09b6b2c 100644
+--- a/data/ibus.schemas.in
++++ b/data/ibus.schemas.in
+@@ -404,6 +404,19 @@
+       </locale>
+     </schema>
+     <schema>
++      <key>/schemas/desktop/ibus/panel/emoji/favorite-annotations</key>
++      <applyto>/desktop/ibus/panel/emoji/favorite-annotations</applyto>
++      <owner>ibus</owner>
++      <type>list</type>
++      <default>[]</default>
++      <list_type>string</list_type>
++      <locale name="C">
++        <short>favorite emoji annotation list on emoji dialog</short>
++	    <long>You can assign an annotation for a favorite emoji
++                  in this list.</long>
++      </locale>
++    </schema>
++    <schema>
+       <key>/schemas/desktop/ibus/panel/emoji/has-partial-match</key>
+       <applyto>/desktop/ibus/panel/emoji/has-partial-match</applyto>
+       <owner>ibus</owner>
+diff --git a/src/ibusemoji.h b/src/ibusemoji.h
+index eb24fdd..4edee72 100644
+--- a/src/ibusemoji.h
++++ b/src/ibusemoji.h
+@@ -188,7 +188,7 @@ GHashTable *    ibus_emoji_dict_load            (const gchar    *path);
+  * @dict: (element-type utf8 IBusEmojiData) (transfer full): An Emoji dictionary
+  * @emoji: an emoji character
+  *
+- * Returns: An #IBusEmojiData of @emoji.
++ * Returns: (transfer none): An #IBusEmojiData of @emoji.
+  * This API was prepared for the old dict foramat with Gir and Vala
+  * but no longer needed.
+  * Use ibus_emoji_data_load() instead.
+diff --git a/ui/gtk3/emojier.vala b/ui/gtk3/emojier.vala
+index db7520a..4169550 100644
+--- a/ui/gtk3/emojier.vala
++++ b/ui/gtk3/emojier.vala
+@@ -201,6 +201,7 @@ class IBusEmojier : Gtk.ApplicationWindow {
+     private static string m_emoji_font_family;
+     private static int m_emoji_font_size;
+     private static string[] m_favorites;
++    private static string[] m_favorite_annotations;
+     private static int m_emoji_max_seq_len;
+     private static bool m_has_partial_match;
+     private static uint m_partial_match_length;
+@@ -261,6 +262,8 @@ class IBusEmojier : Gtk.ApplicationWindow {
+             m_emoji_font_size = 16;
+         if (m_favorites == null)
+             m_favorites = {};
++        if (m_favorite_annotations == null)
++            m_favorite_annotations = {};
+ 
+         Gdk.Display display = Gdk.Display.get_default();
+         Gdk.Screen screen = (display != null) ?
+@@ -374,6 +377,7 @@ class IBusEmojier : Gtk.ApplicationWindow {
+             }
+             make_emoji_dict(m_current_lang_id);
+         }
++        update_favorite_emoji_dict();
+     }
+ 
+ 
+@@ -1263,6 +1267,49 @@ class IBusEmojier : Gtk.ApplicationWindow {
+     }
+ 
+ 
++    public static void update_favorite_emoji_dict() {
++        if (m_emoji_to_data_dict == null ||
++            m_annotation_to_emojis_dict == null)
++            return;
++
++        for(int i = 0; i < m_favorites.length; i++) {
++            var favorite = m_favorites[i];
++
++            string? annotation = "";
++            if (i < m_favorite_annotations.length) {
++                annotation = m_favorite_annotations[i];
++            }
++            if (annotation == "")
++                continue;
++            unowned IBus.EmojiData? data =
++                    m_emoji_to_data_dict.lookup(favorite);
++            if (data == null) {
++                GLib.SList<string> new_annotations = new GLib.SList<string>();
++                new_annotations.append(annotation);
++                IBus.EmojiData new_data = GLib.Object.new(
++                            typeof(IBus.EmojiData),
++                            "emoji", favorite.dup(),
++                            "annotations", new_annotations,
++                            "description", annotation.dup()
++                    ) as IBus.EmojiData;
++                m_emoji_to_data_dict.insert(favorite, new_data);
++            } else {
++                unowned GLib.SList<string> annotations = data.get_annotations();
++                if (annotations.find_custom(annotation, GLib.strcmp) == null) {
++                    annotations.append(annotation);
++                    data.set_annotations(annotations.copy());
++                }
++            }
++            unowned GLib.SList<string> emojis =
++                    m_annotation_to_emojis_dict.lookup(annotation);
++            if (emojis.find_custom(favorite, GLib.strcmp) == null) {
++                emojis.append(favorite);
++                m_annotation_to_emojis_dict.replace(annotation, emojis.copy());
++            }
++        }
++    }
++
++
+     public string run(string input_context_path) {
+         assert (m_loop == null);
+ 
+@@ -1510,10 +1557,22 @@ class IBusEmojier : Gtk.ApplicationWindow {
+         m_partial_match_condition = condition;
+     }
+ 
+-    public static void set_favorites(string[]? unowned_favorites) {
++    public static void set_favorites(string[]? unowned_favorites,
++                                     string[]? unowned_favorite_annotations) {
+         m_favorites = {};
+-        foreach (string favorite in unowned_favorites) {
++        m_favorite_annotations = {};
++        for(int i = 0; i < unowned_favorites.length; i++) {
++            string? favorite = unowned_favorites[i];
++            // Avoid gsetting value error by manual setting
++            GLib.return_if_fail(favorite != null);
++            GLib.return_if_fail(favorite != "");
+             m_favorites += favorite;
+         }
++        for(int i = 0; i < unowned_favorite_annotations.length; i++) {
++            string? favorite_annotation = unowned_favorite_annotations[i];
++            GLib.return_if_fail(favorite_annotation != null);
++            m_favorite_annotations += favorite_annotation;
++        }
++        update_favorite_emoji_dict();
+     }
+ }
+diff --git a/ui/gtk3/emojierapp.vala b/ui/gtk3/emojierapp.vala
+index dbdbc27..24816bb 100644
+--- a/ui/gtk3/emojierapp.vala
++++ b/ui/gtk3/emojierapp.vala
+@@ -50,6 +50,20 @@ public class EmojiApplication : Application {
+         Gtk.Clipboard clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD);
+         clipboard.set_text(emoji, -1);
+         clipboard.store();
++
++        var emojier_favorites = m_settings_emoji.get_strv("favorites");
++        bool has_favorite = false;
++        foreach (unowned string favorite in emojier_favorites) {
++            if (favorite == emoji) {
++                has_favorite = true;
++                break;
++            }
++        }
++        if (!has_favorite) {
++            emojier_favorites += emoji;
++            m_settings_emoji.set_strv("favorites", emojier_favorites);
++        }
++
+         m_emojier = null;
+         command_line.print("%s\n", _("Copied an emoji to your clipboard."));
+     }
+@@ -147,6 +161,10 @@ public class EmojiApplication : Application {
+         if (emoji_font != null)
+             IBusEmojier.set_emoji_font(emoji_font);
+ 
++        IBusEmojier.set_favorites(
++                m_settings_emoji.get_strv("favorites"),
++                m_settings_emoji.get_strv("favorite-annotations"));
++
+         activate_dialog(command_line);
+ 
+         return Posix.EXIT_SUCCESS;
+diff --git a/ui/gtk3/ibusemojidialog.h b/ui/gtk3/ibusemojidialog.h
+index 1499a3c..fb0f5a6 100644
+--- a/ui/gtk3/ibusemojidialog.h
++++ b/ui/gtk3/ibusemojidialog.h
+@@ -145,18 +145,26 @@ void          ibus_emojier_set_annotation_lang    (const gchar* lang);
+  */
+ void          ibus_emojier_set_emoji_font         (const gchar* emoji_font);
+ 
+-#if 0
+-/* TODO: set customized annotations */
+ /**
+  * ibus_emojier_set_favorites:
+  * @favorites: (array length=favorites_length): A custom emoji list.
+  * @favorites_length: A length of @favorites
+- *
+- * Set emoji font on the emoji dialog
++ * @favorite_annotations: (array length=favorite_annotations_length):
++ *                        (nullable):
++ *                        A custom annotation listfor @favorites.
++ * @favorite_annotations_length: A length of @favorite_annotations
++ *
++ * Set custom emojis on the emoji dialog. @favorite_annotations
++ * can be null. If you don't assign an annotation for a specific emoji,
++ * you can pass the annotation as "", e.g.
++ * favorite_annotations = { "", "", "my annotation" };
+  */
+ void          ibus_emojier_set_favorites          (gchar**      favorites,
+                                                    int
+-                                                             favorites_length);
+-#endif
++                                                   favorites_length,
++                                                   gchar**
++                                                   favorite_annotations,
++                                                   int
++                                                   favorite_annotations_length);
+ G_END_DECLS
+ #endif
+diff --git a/ui/gtk3/panel.vala b/ui/gtk3/panel.vala
+index 5f0009e..e4936df 100644
+--- a/ui/gtk3/panel.vala
++++ b/ui/gtk3/panel.vala
+@@ -76,6 +76,7 @@ class Panel : IBus.PanelService {
+     private IBusEmojier? m_emojier;
+     private uint m_emojier_set_emoji_lang_id;
+     private uint m_emojier_focus_commit_text_id;
++    private string[] m_emojier_favorites = {};
+     private PropertyManager m_property_manager;
+     private PropertyPanel m_property_panel;
+     private GLib.Pid m_setup_pid = 0;
+@@ -245,6 +246,10 @@ class Panel : IBus.PanelService {
+                 set_emoji_favorites();
+         });
+ 
++        m_settings_emoji.changed["favorite-annotations"].connect((key) => {
++                set_emoji_favorites();
++        });
++
+         m_settings_emoji.changed["lang"].connect((key) => {
+                 set_emoji_lang();
+         });
+@@ -778,7 +783,10 @@ class Panel : IBus.PanelService {
+     }
+ 
+     private void set_emoji_favorites() {
+-        IBusEmojier.set_favorites(m_settings_emoji.get_strv("favorites"));
++        m_emojier_favorites = m_settings_emoji.get_strv("favorites");
++        IBusEmojier.set_favorites(
++                m_emojier_favorites,
++                m_settings_emoji.get_strv("favorite-annotations"));
+     }
+ 
+     private void set_emoji_lang() {
+@@ -1437,6 +1445,17 @@ class Panel : IBus.PanelService {
+             IBus.Text text = new IBus.Text.from_string(selected_string);
+             commit_text(text);
+             m_emojier = null;
++            bool has_favorite = false;
++            foreach (unowned string favorite in m_emojier_favorites) {
++                if (favorite == selected_string) {
++                    has_favorite = true;
++                    break;
++                }
++            }
++            if (!has_favorite) {
++                m_emojier_favorites += selected_string;
++                m_settings_emoji.set_strv("favorites", m_emojier_favorites);
++            }
+             return true;
+         }
+ 
+-- 
+2.9.3
+
+From a897dab2957568f842b78d54dc40dd294fb6191f Mon Sep 17 00:00:00 2001
+From: fujiwarat <takao.fujiwara1@gmail.com>
+Date: Tue, 9 May 2017 14:47:08 +0900
+Subject: [PATCH] ui/gtk3: Rename ibus-emoji.1.in to ibus-emoji.7.in
+
+---
+ tools/ibus.1.in                              |  2 +-
+ ui/gtk3/Makefile.am                          | 18 +++++++++---------
+ ui/gtk3/{ibus-emoji.1.in => ibus-emoji.7.in} |  0
+ 3 files changed, 10 insertions(+), 10 deletions(-)
+ rename ui/gtk3/{ibus-emoji.1.in => ibus-emoji.7.in} (100%)
+
+diff --git a/tools/ibus.1.in b/tools/ibus.1.in
+index d34a77a..9275abb 100644
+--- a/tools/ibus.1.in
++++ b/tools/ibus.1.in
+@@ -113,4 +113,4 @@ utility.
+ If you find a bug, please report it at https://github.com/ibus/ibus/issues
+ 
+ .SH "SEE ALSO"
+-.BR ibus-emoji (1)
++.BR ibus-emoji (7)
+diff --git a/ui/gtk3/Makefile.am b/ui/gtk3/Makefile.am
+index 270ad1c..c79641a 100644
+--- a/ui/gtk3/Makefile.am
++++ b/ui/gtk3/Makefile.am
+@@ -148,7 +148,7 @@ emoji_headers =         \
+     ibusemojidialog.h   \
+     $(NULL)
+ 
+-man_one_in_files = ibus-emoji.1.in
++man_seven_in_files = ibus-emoji.7.in
+ 
+ # References:
+ # libappindicator/src/notification-item.xml
+@@ -157,7 +157,7 @@ man_one_in_files = ibus-emoji.1.in
+ # kdelibs/kdeui/knotifications/src/org.kde.StatusNotifierWatcher.xml
+ EXTRA_DIST =                            \
+     $(emoji_headers)                    \
+-    $(man_one_in_files)                 \
++    $(man_seven_in_files)               \
+     IBusEmojiDialog-1.0.metadata        \
+     gtkpanel.xml.in                     \
+     ibus-emoji-dialog-1.0.deps          \
+@@ -261,19 +261,19 @@ endif
+ # end of HAVE_INTROSPECTION
+ endif
+ 
+-man_one_files = $(man_one_in_files:.1.in=.1)
+-man_one_DATA =$(man_one_files:.1=.1.gz)
+-man_onedir = $(mandir)/man1
+-%.1: %.1.in
++man_seven_files = $(man_seven_in_files:.7.in=.7)
++man_seven_DATA =$(man_seven_files:.7=.7.gz)
++man_sevendir = $(mandir)/man7
++%.7: %.7.in
+ 	$(AM_V_GEN) sed \
+ 	    -e 's|@VERSION[@]|$(VERSION)|g' $< > $@.tmp && \
+ 	    mv $@.tmp $@
+-%.1.gz: %.1
++%.7.gz: %.7
+ 	$(AM_V_GEN) gzip -c $< > $@.tmp && mv $@.tmp $@
+ 
+ CLEANFILES += \
+-    $(man_one_DATA) \
+-    $(man_one_files) \
++    $(man_seven_DATA) \
++    $(man_seven_files) \
+     $(NULL)
+ 
+ # end of ENABLE_EMOJI_DICT
+diff --git a/ui/gtk3/ibus-emoji.1.in b/ui/gtk3/ibus-emoji.7.in
+similarity index 100%
+rename from ui/gtk3/ibus-emoji.1.in
+rename to ui/gtk3/ibus-emoji.7.in
+-- 
+2.9.3
+

diff --git a/ibus.spec b/ibus.spec
index f39c857..bdecd45 100644
--- a/ibus.spec
+++ b/ibus.spec
@@ -28,7 +28,7 @@
 
 Name:           ibus
 Version:        1.5.15
-Release:        7%{?dist}
+Release:        8%{?dist}
 Summary:        Intelligent Input Bus for Linux OS
 License:        LGPLv2+
 Group:          System Environment/Libraries
@@ -36,6 +36,8 @@ URL:            https://github.com/ibus/%name/wiki
 Source0:        https://github.com/ibus/%name/releases/download/%{version}/%{name}-%{version}.tar.gz
 Source1:        %{name}-xinput
 Source2:        %{name}.conf.5
+# FIXME: Use unicode-emoji package
+Source3:        http://www.unicode.org/Public/emoji/4.0/emoji-test.txt
 # Will remove the annotation tarball once the rpm is available on Fedora
 # Upstreamed patches.
 # Patch0:         %%{name}-HEAD.patch
@@ -68,10 +70,6 @@ BuildRequires:  libwayland-client-devel
 %if %with_kde5
 BuildRequires:  qt5-qtbase-devel
 %endif
-%ifarch %{nodejs_arches}
-BuildRequires:  nodejs-emojione-json
-BuildRequires:  json-glib-devel
-%endif
 BuildRequires:  cldr-emoji-annotation
 
 Requires:       %{name}-libs%{?_isa}   = %{version}-%{release}
@@ -232,6 +230,7 @@ The ibus-devel-docs package contains developer documentation for IBus
 # %%patch0 -p1
 # cp client/gtk2/ibusimcontext.c client/gtk3/ibusimcontext.c ||
 %patch0 -p1
+cp %SOURCE3 data/annotations
 
 %build
 #autoreconf -f -i -v
@@ -254,9 +253,7 @@ autoreconf -f -i -v
     --disable-appindicator \
 %endif
     --enable-introspection \
-%ifnarch %{nodejs_arches}
-    --disable-emoji-dict \
-%endif
+    --with-unicode-emoji-dir=$PWD/data/annotations \
     %{nil}
 
 make -C ui/gtk3 maintainer-clean-generic
@@ -359,15 +356,14 @@ gtk-query-immodules-3.0-%{__isa_bits} --update-cache &> /dev/null || :
 %{_datadir}/GConf/gsettings/*
 %{_datadir}/glib-2.0/schemas/*.xml
 %{_datadir}/ibus/component
-%ifarch %{nodejs_arches}
 %{_datadir}/ibus/dicts
-%endif
 %{_datadir}/ibus/engine
 %{_datadir}/ibus/keymaps
 %{_datadir}/icons/hicolor/*/apps/*
 %{_datadir}/man/man1/ibus.1.gz
 %{_datadir}/man/man1/ibus-daemon.1.gz
 %{_datadir}/man/man5/ibus.conf.5.gz
+%{_datadir}/man/man7/ibus-emoji.7.gz
 %{_libexecdir}/ibus-engine-simple
 %{_libexecdir}/ibus-dconf
 %{_libexecdir}/ibus-ui-emojier
@@ -428,6 +424,15 @@ gtk-query-immodules-3.0-%{__isa_bits} --update-cache &> /dev/null || :
 %{_datadir}/gtk-doc/html/*
 
 %changelog
+* Tue May 09 2017 Takao Fujiwara <tfujiwar@redhat.com> - 1.5.15-8
+- Dropped nodejs-emojione-json and import unicode-emoji instead
+- Created emoji tab in ibus-setup
+- Set default emoji font size from gsettings in ibus emoji command
+- Added an option of emoji partial match in ibus-setup
+- Hid emoji variants by default
+- Added ibus-emoji man page
+- emoji favorites category is updated by selecting emoji
+
 * Thu Apr 13 2017 Takao Fujiwara <tfujiwar@redhat.com> - 1.5.15-7
 - Supported ibus emoji command on Wayland
 - Changed modal dialog to modeless dialog

                 reply	other threads:[~2026-05-31  2:06 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=178019319260.1.16822556303133795888.rpms-ibus-8dd4dc1c86fb@fedoraproject.org \
    --to=tfujiwar@redhat.com \
    --cc=git-commits@fedoraproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox