[BACK]Return to utf8-combined.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tmux

Annotation of src/usr.bin/tmux/utf8-combined.c, Revision 1.2

1.2     ! nicm        1: /* $OpenBSD: utf8-combined.c,v 1.1 2023/09/01 14:29:11 nicm Exp $ */
1.1       nicm        2:
                      3: /*
                      4:  * Copyright (c) 2023 Nicholas Marriott <nicholas.marriott@gmail.com>
                      5:  *
                      6:  * Permission to use, copy, modify, and distribute this software for any
                      7:  * purpose with or without fee is hereby granted, provided that the above
                      8:  * copyright notice and this permission notice appear in all copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14:  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
                     15:  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
                     16:  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17:  */
                     18:
                     19: #include <sys/types.h>
                     20:
                     21: #include <stdlib.h>
                     22: #include <string.h>
                     23: #include <wchar.h>
                     24:
                     25: #include "tmux.h"
                     26:
                     27: static const struct {
                     28:        wchar_t first;
                     29:        wchar_t second;
                     30: } utf8_combined_table[] = {
                     31:        { 0x1F1E6, 0x1F1E8 }, /* flag: Ascension Island */
                     32:        { 0x1F1E6, 0x1F1E9 }, /* flag: Andorra */
                     33:        { 0x1F1E6, 0x1F1EA }, /* flag: United Arab Emirates */
                     34:        { 0x1F1E6, 0x1F1EB }, /* flag: Afghanistan */
                     35:        { 0x1F1E6, 0x1F1EC }, /* flag: Antigua & Barbuda */
                     36:        { 0x1F1E6, 0x1F1EE }, /* flag: Anguilla */
                     37:        { 0x1F1E6, 0x1F1F1 }, /* flag: Albania */
                     38:        { 0x1F1E6, 0x1F1F2 }, /* flag: Armenia */
                     39:        { 0x1F1E6, 0x1F1F4 }, /* flag: Angola */
                     40:        { 0x1F1E6, 0x1F1F6 }, /* flag: Antarctica */
                     41:        { 0x1F1E6, 0x1F1F7 }, /* flag: Argentina */
                     42:        { 0x1F1E6, 0x1F1F8 }, /* flag: American Samoa */
                     43:        { 0x1F1E6, 0x1F1F9 }, /* flag: Austria */
                     44:        { 0x1F1E6, 0x1F1FA }, /* flag: Australia */
                     45:        { 0x1F1E6, 0x1F1FC }, /* flag: Aruba */
                     46:        { 0x1F1E6, 0x1F1FD }, /* flag: Aland Islands */
                     47:        { 0x1F1E6, 0x1F1FF }, /* flag: Azerbaijan */
                     48:        { 0x1F1E7, 0x1F1E6 }, /* flag: Bosnia & Herzegovina */
                     49:        { 0x1F1E7, 0x1F1E7 }, /* flag: Barbados */
                     50:        { 0x1F1E7, 0x1F1E9 }, /* flag: Bangladesh */
                     51:        { 0x1F1E7, 0x1F1EA }, /* flag: Belgium */
                     52:        { 0x1F1E7, 0x1F1EB }, /* flag: Burkina Faso */
                     53:        { 0x1F1E7, 0x1F1EC }, /* flag: Bulgaria */
                     54:        { 0x1F1E7, 0x1F1ED }, /* flag: Bahrain */
                     55:        { 0x1F1E7, 0x1F1EE }, /* flag: Burundi */
                     56:        { 0x1F1E7, 0x1F1EF }, /* flag: Benin */
                     57:        { 0x1F1E7, 0x1F1F1 }, /* flag: St. Barthelemy */
                     58:        { 0x1F1E7, 0x1F1F2 }, /* flag: Bermuda */
                     59:        { 0x1F1E7, 0x1F1F3 }, /* flag: Brunei */
                     60:        { 0x1F1E7, 0x1F1F4 }, /* flag: Bolivia */
                     61:        { 0x1F1E7, 0x1F1F6 }, /* flag: Caribbean Netherlands */
                     62:        { 0x1F1E7, 0x1F1F7 }, /* flag: Brazil */
                     63:        { 0x1F1E7, 0x1F1F8 }, /* flag: Bahamas */
                     64:        { 0x1F1E7, 0x1F1F9 }, /* flag: Bhutan */
                     65:        { 0x1F1E7, 0x1F1FB }, /* flag: Bouvet Island */
                     66:        { 0x1F1E7, 0x1F1FC }, /* flag: Botswana */
                     67:        { 0x1F1E7, 0x1F1FE }, /* flag: Belarus */
                     68:        { 0x1F1E7, 0x1F1FF }, /* flag: Belize */
                     69:        { 0x1F1E8, 0x1F1E6 }, /* flag: Canada */
                     70:        { 0x1F1E8, 0x1F1E8 }, /* flag: Cocos (Keeling) Islands */
                     71:        { 0x1F1E8, 0x1F1E9 }, /* flag: Congo - Kinshasa */
                     72:        { 0x1F1E8, 0x1F1EB }, /* flag: Central African Republic */
                     73:        { 0x1F1E8, 0x1F1EC }, /* flag: Congo - Brazzaville */
                     74:        { 0x1F1E8, 0x1F1ED }, /* flag: Switzerland */
                     75:        { 0x1F1E8, 0x1F1EE }, /* flag: Cote d'Ivoire */
                     76:        { 0x1F1E8, 0x1F1F0 }, /* flag: Cook Islands */
                     77:        { 0x1F1E8, 0x1F1F1 }, /* flag: Chile */
                     78:        { 0x1F1E8, 0x1F1F2 }, /* flag: Cameroon */
                     79:        { 0x1F1E8, 0x1F1F3 }, /* flag: China */
                     80:        { 0x1F1E8, 0x1F1F4 }, /* flag: Colombia */
                     81:        { 0x1F1E8, 0x1F1F5 }, /* flag: Clipperton Island */
                     82:        { 0x1F1E8, 0x1F1F7 }, /* flag: Costa Rica */
                     83:        { 0x1F1E8, 0x1F1FA }, /* flag: Cuba */
                     84:        { 0x1F1E8, 0x1F1FB }, /* flag: Cape Verde */
                     85:        { 0x1F1E8, 0x1F1FC }, /* flag: Curacao */
                     86:        { 0x1F1E8, 0x1F1FD }, /* flag: Christmas Island */
                     87:        { 0x1F1E8, 0x1F1FE }, /* flag: Cyprus */
                     88:        { 0x1F1E8, 0x1F1FF }, /* flag: Czechia */
                     89:        { 0x1F1E9, 0x1F1EA }, /* flag: Germany */
                     90:        { 0x1F1E9, 0x1F1EC }, /* flag: Diego Garcia */
                     91:        { 0x1F1E9, 0x1F1EF }, /* flag: Djibouti */
                     92:        { 0x1F1E9, 0x1F1F0 }, /* flag: Denmark */
                     93:        { 0x1F1E9, 0x1F1F2 }, /* flag: Dominica */
                     94:        { 0x1F1E9, 0x1F1F4 }, /* flag: Dominican Republic */
                     95:        { 0x1F1E9, 0x1F1FF }, /* flag: Algeria */
                     96:        { 0x1F1EA, 0x1F1E6 }, /* flag: Ceuta & Melilla */
                     97:        { 0x1F1EA, 0x1F1E8 }, /* flag: Ecuador */
                     98:        { 0x1F1EA, 0x1F1EA }, /* flag: Estonia */
                     99:        { 0x1F1EA, 0x1F1EC }, /* flag: Egypt */
                    100:        { 0x1F1EA, 0x1F1ED }, /* flag: Western Sahara */
                    101:        { 0x1F1EA, 0x1F1F7 }, /* flag: Eritrea */
                    102:        { 0x1F1EA, 0x1F1F8 }, /* flag: Spain */
                    103:        { 0x1F1EA, 0x1F1F9 }, /* flag: Ethiopia */
                    104:        { 0x1F1EA, 0x1F1FA }, /* flag: European Union */
                    105:        { 0x1F1EB, 0x1F1EE }, /* flag: Finland */
                    106:        { 0x1F1EB, 0x1F1EF }, /* flag: Fiji */
                    107:        { 0x1F1EB, 0x1F1F0 }, /* flag: Falkland Islands */
                    108:        { 0x1F1EB, 0x1F1F2 }, /* flag: Micronesia */
                    109:        { 0x1F1EB, 0x1F1F4 }, /* flag: Faroe Islands */
                    110:        { 0x1F1EB, 0x1F1F7 }, /* flag: France */
                    111:        { 0x1F1EC, 0x1F1E6 }, /* flag: Gabon */
                    112:        { 0x1F1EC, 0x1F1E7 }, /* flag: United Kingdom */
                    113:        { 0x1F1EC, 0x1F1E9 }, /* flag: Grenada */
                    114:        { 0x1F1EC, 0x1F1EA }, /* flag: Georgia */
                    115:        { 0x1F1EC, 0x1F1EB }, /* flag: French Guiana */
                    116:        { 0x1F1EC, 0x1F1EC }, /* flag: Guernsey */
                    117:        { 0x1F1EC, 0x1F1ED }, /* flag: Ghana */
                    118:        { 0x1F1EC, 0x1F1EE }, /* flag: Gibraltar */
                    119:        { 0x1F1EC, 0x1F1F1 }, /* flag: Greenland */
                    120:        { 0x1F1EC, 0x1F1F2 }, /* flag: Gambia */
                    121:        { 0x1F1EC, 0x1F1F3 }, /* flag: Guinea */
                    122:        { 0x1F1EC, 0x1F1F5 }, /* flag: Guadeloupe */
                    123:        { 0x1F1EC, 0x1F1F6 }, /* flag: Equatorial Guinea */
                    124:        { 0x1F1EC, 0x1F1F7 }, /* flag: Greece */
                    125:        { 0x1F1EC, 0x1F1F8 }, /* flag: South Georgia & South Sandwich Islands */
                    126:        { 0x1F1EC, 0x1F1F9 }, /* flag: Guatemala */
                    127:        { 0x1F1EC, 0x1F1FA }, /* flag: Guam */
                    128:        { 0x1F1EC, 0x1F1FC }, /* flag: Guinea-Bissau */
                    129:        { 0x1F1EC, 0x1F1FE }, /* flag: Guyana */
                    130:        { 0x1F1ED, 0x1F1F0 }, /* flag: Hong Kong SAR China */
                    131:        { 0x1F1ED, 0x1F1F2 }, /* flag: Heard & McDonald Islands */
                    132:        { 0x1F1ED, 0x1F1F3 }, /* flag: Honduras */
                    133:        { 0x1F1ED, 0x1F1F7 }, /* flag: Croatia */
                    134:        { 0x1F1ED, 0x1F1F9 }, /* flag: Haiti */
                    135:        { 0x1F1ED, 0x1F1FA }, /* flag: Hungary */
                    136:        { 0x1F1EE, 0x1F1E8 }, /* flag: Canary Islands */
                    137:        { 0x1F1EE, 0x1F1E9 }, /* flag: Indonesia */
                    138:        { 0x1F1EE, 0x1F1EA }, /* flag: Ireland */
                    139:        { 0x1F1EE, 0x1F1F1 }, /* flag: Israel */
                    140:        { 0x1F1EE, 0x1F1F2 }, /* flag: Isle of Man */
                    141:        { 0x1F1EE, 0x1F1F3 }, /* flag: India */
                    142:        { 0x1F1EE, 0x1F1F4 }, /* flag: British Indian Ocean Territory */
                    143:        { 0x1F1EE, 0x1F1F6 }, /* flag: Iraq */
                    144:        { 0x1F1EE, 0x1F1F7 }, /* flag: Iran */
                    145:        { 0x1F1EE, 0x1F1F8 }, /* flag: Iceland */
                    146:        { 0x1F1EE, 0x1F1F9 }, /* flag: Italy */
                    147:        { 0x1F1EF, 0x1F1EA }, /* flag: Jersey */
                    148:        { 0x1F1EF, 0x1F1F2 }, /* flag: Jamaica */
                    149:        { 0x1F1EF, 0x1F1F4 }, /* flag: Jordan */
                    150:        { 0x1F1EF, 0x1F1F5 }, /* flag: Japan */
                    151:        { 0x1F1F0, 0x1F1EA }, /* flag: Kenya */
                    152:        { 0x1F1F0, 0x1F1EC }, /* flag: Kyrgyzstan */
                    153:        { 0x1F1F0, 0x1F1ED }, /* flag: Cambodia */
                    154:        { 0x1F1F0, 0x1F1EE }, /* flag: Kiribati */
                    155:        { 0x1F1F0, 0x1F1F2 }, /* flag: Comoros */
                    156:        { 0x1F1F0, 0x1F1F3 }, /* flag: St. Kitts & Nevis */
                    157:        { 0x1F1F0, 0x1F1F5 }, /* flag: North Korea */
                    158:        { 0x1F1F0, 0x1F1F7 }, /* flag: South Korea */
                    159:        { 0x1F1F0, 0x1F1FC }, /* flag: Kuwait */
                    160:        { 0x1F1F0, 0x1F1FE }, /* flag: Cayman Islands */
                    161:        { 0x1F1F0, 0x1F1FF }, /* flag: Kazakhstan */
                    162:        { 0x1F1F1, 0x1F1E6 }, /* flag: Laos */
                    163:        { 0x1F1F1, 0x1F1E7 }, /* flag: Lebanon */
                    164:        { 0x1F1F1, 0x1F1E8 }, /* flag: St. Lucia */
                    165:        { 0x1F1F1, 0x1F1EE }, /* flag: Liechtenstein */
                    166:        { 0x1F1F1, 0x1F1F0 }, /* flag: Sri Lanka */
                    167:        { 0x1F1F1, 0x1F1F7 }, /* flag: Liberia */
                    168:        { 0x1F1F1, 0x1F1F8 }, /* flag: Lesotho */
                    169:        { 0x1F1F1, 0x1F1F9 }, /* flag: Lithuania */
                    170:        { 0x1F1F1, 0x1F1FA }, /* flag: Luxembourg */
                    171:        { 0x1F1F1, 0x1F1FB }, /* flag: Latvia */
                    172:        { 0x1F1F1, 0x1F1FE }, /* flag: Libya */
                    173:        { 0x1F1F2, 0x1F1E6 }, /* flag: Morocco */
                    174:        { 0x1F1F2, 0x1F1E8 }, /* flag: Monaco */
                    175:        { 0x1F1F2, 0x1F1E9 }, /* flag: Moldova */
                    176:        { 0x1F1F2, 0x1F1EA }, /* flag: Montenegro */
                    177:        { 0x1F1F2, 0x1F1EB }, /* flag: St. Martin */
                    178:        { 0x1F1F2, 0x1F1EC }, /* flag: Madagascar */
                    179:        { 0x1F1F2, 0x1F1ED }, /* flag: Marshall Islands */
                    180:        { 0x1F1F2, 0x1F1F0 }, /* flag: North Macedonia */
                    181:        { 0x1F1F2, 0x1F1F1 }, /* flag: Mali */
                    182:        { 0x1F1F2, 0x1F1F2 }, /* flag: Myanmar (Burma */
                    183:        { 0x1F1F2, 0x1F1F3 }, /* flag: Mongolia */
                    184:        { 0x1F1F2, 0x1F1F4 }, /* flag: Macao SAR China */
                    185:        { 0x1F1F2, 0x1F1F5 }, /* flag: Northern Mariana Islands */
                    186:        { 0x1F1F2, 0x1F1F6 }, /* flag: Martinique */
                    187:        { 0x1F1F2, 0x1F1F7 }, /* flag: Mauritania */
                    188:        { 0x1F1F2, 0x1F1F8 }, /* flag: Montserrat */
                    189:        { 0x1F1F2, 0x1F1F9 }, /* flag: Malta */
                    190:        { 0x1F1F2, 0x1F1FA }, /* flag: Mauritius */
                    191:        { 0x1F1F2, 0x1F1FB }, /* flag: Maldives */
                    192:        { 0x1F1F2, 0x1F1FC }, /* flag: Malawi */
                    193:        { 0x1F1F2, 0x1F1FD }, /* flag: Mexico */
                    194:        { 0x1F1F2, 0x1F1FE }, /* flag: Malaysia */
                    195:        { 0x1F1F2, 0x1F1FF }, /* flag: Mozambique */
                    196:        { 0x1F1F3, 0x1F1E6 }, /* flag: Namibia */
                    197:        { 0x1F1F3, 0x1F1E8 }, /* flag: New Caledonia */
                    198:        { 0x1F1F3, 0x1F1EA }, /* flag: Niger */
                    199:        { 0x1F1F3, 0x1F1EB }, /* flag: Norfolk Island */
                    200:        { 0x1F1F3, 0x1F1EC }, /* flag: Nigeria */
                    201:        { 0x1F1F3, 0x1F1EE }, /* flag: Nicaragua */
                    202:        { 0x1F1F3, 0x1F1F1 }, /* flag: Netherlands */
                    203:        { 0x1F1F3, 0x1F1F4 }, /* flag: Norway */
                    204:        { 0x1F1F3, 0x1F1F5 }, /* flag: Nepal */
                    205:        { 0x1F1F3, 0x1F1F7 }, /* flag: Nauru */
                    206:        { 0x1F1F3, 0x1F1FA }, /* flag: Niue */
                    207:        { 0x1F1F3, 0x1F1FF }, /* flag: New Zealand */
                    208:        { 0x1F1F4, 0x1F1F2 }, /* flag: Oman */
                    209:        { 0x1F1F5, 0x1F1E6 }, /* flag: Panama */
                    210:        { 0x1F1F5, 0x1F1EA }, /* flag: Peru */
                    211:        { 0x1F1F5, 0x1F1EB }, /* flag: French Polynesia */
                    212:        { 0x1F1F5, 0x1F1EC }, /* flag: Papua New Guinea */
                    213:        { 0x1F1F5, 0x1F1ED }, /* flag: Philippines */
                    214:        { 0x1F1F5, 0x1F1F0 }, /* flag: Pakistan */
                    215:        { 0x1F1F5, 0x1F1F1 }, /* flag: Poland */
                    216:        { 0x1F1F5, 0x1F1F2 }, /* flag: St. Pierre & Miquelon */
                    217:        { 0x1F1F5, 0x1F1F3 }, /* flag: Pitcairn Islands */
                    218:        { 0x1F1F5, 0x1F1F7 }, /* flag: Puerto Rico */
                    219:        { 0x1F1F5, 0x1F1F8 }, /* flag: Palestinian Territories */
                    220:        { 0x1F1F5, 0x1F1F9 }, /* flag: Portugal */
                    221:        { 0x1F1F5, 0x1F1FC }, /* flag: Palau */
                    222:        { 0x1F1F5, 0x1F1FE }, /* flag: Paraguay */
                    223:        { 0x1F1F6, 0x1F1E6 }, /* flag: Qatar */
                    224:        { 0x1F1F7, 0x1F1EA }, /* flag: Reunion */
                    225:        { 0x1F1F7, 0x1F1F4 }, /* flag: Romania */
                    226:        { 0x1F1F7, 0x1F1F8 }, /* flag: Serbia */
                    227:        { 0x1F1F7, 0x1F1FA }, /* flag: Russia */
                    228:        { 0x1F1F7, 0x1F1FC }, /* flag: Rwanda */
                    229:        { 0x1F1F8, 0x1F1E6 }, /* flag: Saudi Arabia */
                    230:        { 0x1F1F8, 0x1F1E7 }, /* flag: Solomon Islands */
                    231:        { 0x1F1F8, 0x1F1E8 }, /* flag: Seychelles */
                    232:        { 0x1F1F8, 0x1F1E9 }, /* flag: Sudan */
                    233:        { 0x1F1F8, 0x1F1EA }, /* flag: Sweden */
                    234:        { 0x1F1F8, 0x1F1EC }, /* flag: Singapore */
                    235:        { 0x1F1F8, 0x1F1ED }, /* flag: St. Helena */
                    236:        { 0x1F1F8, 0x1F1EE }, /* flag: Slovenia */
                    237:        { 0x1F1F8, 0x1F1EF }, /* flag: Svalbard & Jan Mayen */
                    238:        { 0x1F1F8, 0x1F1F0 }, /* flag: Slovakia */
                    239:        { 0x1F1F8, 0x1F1F1 }, /* flag: Sierra Leone */
                    240:        { 0x1F1F8, 0x1F1F2 }, /* flag: San Marino */
                    241:        { 0x1F1F8, 0x1F1F3 }, /* flag: Senegal */
                    242:        { 0x1F1F8, 0x1F1F4 }, /* flag: Somalia */
                    243:        { 0x1F1F8, 0x1F1F7 }, /* flag: Suriname */
                    244:        { 0x1F1F8, 0x1F1F8 }, /* flag: South Sudan */
                    245:        { 0x1F1F8, 0x1F1F9 }, /* flag: Sao Tome & Principe */
                    246:        { 0x1F1F8, 0x1F1FB }, /* flag: El Salvador */
                    247:        { 0x1F1F8, 0x1F1FD }, /* flag: Sint Maarten */
                    248:        { 0x1F1F8, 0x1F1FE }, /* flag: Syria */
                    249:        { 0x1F1F8, 0x1F1FF }, /* flag: Eswatini */
                    250:        { 0x1F1F9, 0x1F1E6 }, /* flag: Tristan da Cunha */
                    251:        { 0x1F1F9, 0x1F1E8 }, /* flag: Turks & Caicos Islands */
                    252:        { 0x1F1F9, 0x1F1E9 }, /* flag: Chad */
                    253:        { 0x1F1F9, 0x1F1EB }, /* flag: French Southern Territories */
                    254:        { 0x1F1F9, 0x1F1EC }, /* flag: Togo */
                    255:        { 0x1F1F9, 0x1F1ED }, /* flag: Thailand */
                    256:        { 0x1F1F9, 0x1F1EF }, /* flag: Tajikistan */
                    257:        { 0x1F1F9, 0x1F1F0 }, /* flag: Tokelau */
                    258:        { 0x1F1F9, 0x1F1F1 }, /* flag: Timor-Leste */
                    259:        { 0x1F1F9, 0x1F1F2 }, /* flag: Turkmenistan */
                    260:        { 0x1F1F9, 0x1F1F3 }, /* flag: Tunisia */
                    261:        { 0x1F1F9, 0x1F1F4 }, /* flag: Tonga */
                    262:        { 0x1F1F9, 0x1F1F7 }, /* flag: Turkey */
                    263:        { 0x1F1F9, 0x1F1F9 }, /* flag: Trinidad & Tobago */
                    264:        { 0x1F1F9, 0x1F1FB }, /* flag: Tuvalu */
                    265:        { 0x1F1F9, 0x1F1FC }, /* flag: Taiwan */
                    266:        { 0x1F1F9, 0x1F1FF }, /* flag: Tanzania */
                    267:        { 0x1F1FA, 0x1F1E6 }, /* flag: Ukraine */
                    268:        { 0x1F1FA, 0x1F1EC }, /* flag: Uganda */
                    269:        { 0x1F1FA, 0x1F1F2 }, /* flag: U.S. Outlying Islands */
                    270:        { 0x1F1FA, 0x1F1F3 }, /* flag: United Nations */
                    271:        { 0x1F1FA, 0x1F1F8 }, /* flag: United States */
                    272:        { 0x1F1FA, 0x1F1FE }, /* flag: Uruguay */
                    273:        { 0x1F1FA, 0x1F1FF }, /* flag: Uzbekistan */
                    274:        { 0x1F1FB, 0x1F1E6 }, /* flag: Vatican City */
                    275:        { 0x1F1FB, 0x1F1E8 }, /* flag: St. Vincent & Grenadines */
                    276:        { 0x1F1FB, 0x1F1EA }, /* flag: Venezuela */
                    277:        { 0x1F1FB, 0x1F1EC }, /* flag: British Virgin Islands */
                    278:        { 0x1F1FB, 0x1F1EE }, /* flag: U.S. Virgin Islands */
                    279:        { 0x1F1FB, 0x1F1F3 }, /* flag: Vietnam */
                    280:        { 0x1F1FB, 0x1F1FA }, /* flag: Vanuatu */
                    281:        { 0x1F1FC, 0x1F1EB }, /* flag: Wallis & Futuna */
                    282:        { 0x1F1FC, 0x1F1F8 }, /* flag: Samoa */
                    283:        { 0x1F1FD, 0x1F1F0 }, /* flag: Kosovo */
                    284:        { 0x1F1FE, 0x1F1EA }, /* flag: Yemen */
                    285:        { 0x1F1FE, 0x1F1F9 }, /* flag: Mayotte */
                    286:        { 0x1F1FF, 0x1F1E6 }, /* flag: South Africa */
                    287:        { 0x1F1FF, 0x1F1F2 }, /* flag: Zambia */
                    288:        { 0x1F1FF, 0x1F1FC }, /* flag: Zimbabwe */
                    289:        { 0x0261D, 0x1F3FB }, /* index pointing up: light skin tone */
                    290:        { 0x0261D, 0x1F3FC }, /* index pointing up: medium-light skin tone */
                    291:        { 0x0261D, 0x1F3FD }, /* index pointing up: medium skin tone */
                    292:        { 0x0261D, 0x1F3FE }, /* index pointing up: medium-dark skin tone */
                    293:        { 0x0261D, 0x1F3FF }, /* index pointing up: dark skin tone */
                    294:        { 0x026F9, 0x1F3FB }, /* person bouncing ball: light skin tone */
                    295:        { 0x026F9, 0x1F3FC }, /* person bouncing ball: medium-light skin tone */
                    296:        { 0x026F9, 0x1F3FD }, /* person bouncing ball: medium skin tone */
                    297:        { 0x026F9, 0x1F3FE }, /* person bouncing ball: medium-dark skin tone */
                    298:        { 0x026F9, 0x1F3FF }, /* person bouncing ball: dark skin tone */
                    299:        { 0x0270A, 0x1F3FB }, /* raised fist: light skin tone */
                    300:        { 0x0270A, 0x1F3FC }, /* raised fist: medium-light skin tone */
                    301:        { 0x0270A, 0x1F3FD }, /* raised fist: medium skin tone */
                    302:        { 0x0270A, 0x1F3FE }, /* raised fist: medium-dark skin tone */
                    303:        { 0x0270A, 0x1F3FF }, /* raised fist: dark skin tone */
                    304:        { 0x0270B, 0x1F3FB }, /* raised hand: light skin tone */
                    305:        { 0x0270B, 0x1F3FC }, /* raised hand: medium-light skin tone */
                    306:        { 0x0270B, 0x1F3FD }, /* raised hand: medium skin tone */
                    307:        { 0x0270B, 0x1F3FE }, /* raised hand: medium-dark skin tone */
                    308:        { 0x0270B, 0x1F3FF }, /* raised hand: dark skin tone */
                    309:        { 0x0270C, 0x1F3FB }, /* victory hand: light skin tone */
                    310:        { 0x0270C, 0x1F3FC }, /* victory hand: medium-light skin tone */
                    311:        { 0x0270C, 0x1F3FD }, /* victory hand: medium skin tone */
                    312:        { 0x0270C, 0x1F3FE }, /* victory hand: medium-dark skin tone */
                    313:        { 0x0270C, 0x1F3FF }, /* victory hand: dark skin tone */
                    314:        { 0x0270D, 0x1F3FB }, /* writing hand: light skin tone */
                    315:        { 0x0270D, 0x1F3FC }, /* writing hand: medium-light skin tone */
                    316:        { 0x0270D, 0x1F3FD }, /* writing hand: medium skin tone */
                    317:        { 0x0270D, 0x1F3FE }, /* writing hand: medium-dark skin tone */
                    318:        { 0x0270D, 0x1F3FF }, /* writing hand: dark skin tone */
                    319:        { 0x1F385, 0x1F3FB }, /* Santa Claus: light skin tone */
                    320:        { 0x1F385, 0x1F3FC }, /* Santa Claus: medium-light skin tone */
                    321:        { 0x1F385, 0x1F3FD }, /* Santa Claus: medium skin tone */
                    322:        { 0x1F385, 0x1F3FE }, /* Santa Claus: medium-dark skin tone */
                    323:        { 0x1F385, 0x1F3FF }, /* Santa Claus: dark skin tone */
                    324:        { 0x1F3C2, 0x1F3FB }, /* snowboarder: light skin tone */
                    325:        { 0x1F3C2, 0x1F3FC }, /* snowboarder: medium-light skin tone */
                    326:        { 0x1F3C2, 0x1F3FD }, /* snowboarder: medium skin tone */
                    327:        { 0x1F3C2, 0x1F3FE }, /* snowboarder: medium-dark skin tone */
                    328:        { 0x1F3C2, 0x1F3FF }, /* snowboarder: dark skin tone */
                    329:        { 0x1F3C3, 0x1F3FB }, /* person running: light skin tone */
                    330:        { 0x1F3C3, 0x1F3FC }, /* person running: medium-light skin tone */
                    331:        { 0x1F3C3, 0x1F3FD }, /* person running: medium skin tone */
                    332:        { 0x1F3C3, 0x1F3FE }, /* person running: medium-dark skin tone */
                    333:        { 0x1F3C3, 0x1F3FF }, /* person running: dark skin tone */
                    334:        { 0x1F3C4, 0x1F3FB }, /* person surfing: light skin tone */
                    335:        { 0x1F3C4, 0x1F3FC }, /* person surfing: medium-light skin tone */
                    336:        { 0x1F3C4, 0x1F3FD }, /* person surfing: medium skin tone */
                    337:        { 0x1F3C4, 0x1F3FE }, /* person surfing: medium-dark skin tone */
                    338:        { 0x1F3C4, 0x1F3FF }, /* person surfing: dark skin tone */
                    339:        { 0x1F3C7, 0x1F3FB }, /* horse racing: light skin tone */
                    340:        { 0x1F3C7, 0x1F3FC }, /* horse racing: medium-light skin tone */
                    341:        { 0x1F3C7, 0x1F3FD }, /* horse racing: medium skin tone */
                    342:        { 0x1F3C7, 0x1F3FE }, /* horse racing: medium-dark skin tone */
                    343:        { 0x1F3C7, 0x1F3FF }, /* horse racing: dark skin tone */
                    344:        { 0x1F3CA, 0x1F3FB }, /* person swimming: light skin tone */
                    345:        { 0x1F3CA, 0x1F3FC }, /* person swimming: medium-light skin tone */
                    346:        { 0x1F3CA, 0x1F3FD }, /* person swimming: medium skin tone */
                    347:        { 0x1F3CA, 0x1F3FE }, /* person swimming: medium-dark skin tone */
                    348:        { 0x1F3CA, 0x1F3FF }, /* person swimming: dark skin tone */
                    349:        { 0x1F3CB, 0x1F3FB }, /* person lifting weights: light skin tone */
                    350:        { 0x1F3CB, 0x1F3FC }, /* person lifting weights: medium-light skin tone */
                    351:        { 0x1F3CB, 0x1F3FD }, /* person lifting weights: medium skin tone */
                    352:        { 0x1F3CB, 0x1F3FE }, /* person lifting weights: medium-dark skin tone */
                    353:        { 0x1F3CB, 0x1F3FF }, /* person lifting weights: dark skin tone */
                    354:        { 0x1F3CC, 0x1F3FB }, /* person golfing: light skin tone */
                    355:        { 0x1F3CC, 0x1F3FC }, /* person golfing: medium-light skin tone */
                    356:        { 0x1F3CC, 0x1F3FD }, /* person golfing: medium skin tone */
                    357:        { 0x1F3CC, 0x1F3FE }, /* person golfing: medium-dark skin tone */
                    358:        { 0x1F3CC, 0x1F3FF }, /* person golfing: dark skin tone */
                    359:        { 0x1F442, 0x1F3FB }, /* ear: light skin tone */
                    360:        { 0x1F442, 0x1F3FC }, /* ear: medium-light skin tone */
                    361:        { 0x1F442, 0x1F3FD }, /* ear: medium skin tone */
                    362:        { 0x1F442, 0x1F3FE }, /* ear: medium-dark skin tone */
                    363:        { 0x1F442, 0x1F3FF }, /* ear: dark skin tone */
                    364:        { 0x1F443, 0x1F3FB }, /* nose: light skin tone */
                    365:        { 0x1F443, 0x1F3FC }, /* nose: medium-light skin tone */
                    366:        { 0x1F443, 0x1F3FD }, /* nose: medium skin tone */
                    367:        { 0x1F443, 0x1F3FE }, /* nose: medium-dark skin tone */
                    368:        { 0x1F443, 0x1F3FF }, /* nose: dark skin tone */
                    369:        { 0x1F446, 0x1F3FB }, /* backhand index pointing up: light skin tone */
                    370:        { 0x1F446, 0x1F3FC }, /* backhand index pointing up: medium-light skin tone */
                    371:        { 0x1F446, 0x1F3FD }, /* backhand index pointing up: medium skin tone */
                    372:        { 0x1F446, 0x1F3FE }, /* backhand index pointing up: medium-dark skin tone */
                    373:        { 0x1F446, 0x1F3FF }, /* backhand index pointing up: dark skin tone */
                    374:        { 0x1F447, 0x1F3FB }, /* backhand index pointing down: light skin tone */
                    375:        { 0x1F447, 0x1F3FC }, /* backhand index pointing down: medium-light skin tone */
                    376:        { 0x1F447, 0x1F3FD }, /* backhand index pointing down: medium skin tone */
                    377:        { 0x1F447, 0x1F3FE }, /* backhand index pointing down: medium-dark skin tone */
                    378:        { 0x1F447, 0x1F3FF }, /* backhand index pointing down: dark skin tone */
                    379:        { 0x1F448, 0x1F3FB }, /* backhand index pointing left: light skin tone */
                    380:        { 0x1F448, 0x1F3FC }, /* backhand index pointing left: medium-light skin tone */
                    381:        { 0x1F448, 0x1F3FD }, /* backhand index pointing left: medium skin tone */
                    382:        { 0x1F448, 0x1F3FE }, /* backhand index pointing left: medium-dark skin tone */
                    383:        { 0x1F448, 0x1F3FF }, /* backhand index pointing left: dark skin tone */
                    384:        { 0x1F449, 0x1F3FB }, /* backhand index pointing right: light skin tone */
                    385:        { 0x1F449, 0x1F3FC }, /* backhand index pointing right: medium-light skin tone */
                    386:        { 0x1F449, 0x1F3FD }, /* backhand index pointing right: medium skin tone */
                    387:        { 0x1F449, 0x1F3FE }, /* backhand index pointing right: medium-dark skin tone */
                    388:        { 0x1F449, 0x1F3FF }, /* backhand index pointing right: dark skin tone */
                    389:        { 0x1F44A, 0x1F3FB }, /* oncoming fist: light skin tone */
                    390:        { 0x1F44A, 0x1F3FC }, /* oncoming fist: medium-light skin tone */
                    391:        { 0x1F44A, 0x1F3FD }, /* oncoming fist: medium skin tone */
                    392:        { 0x1F44A, 0x1F3FE }, /* oncoming fist: medium-dark skin tone */
                    393:        { 0x1F44A, 0x1F3FF }, /* oncoming fist: dark skin tone */
                    394:        { 0x1F44B, 0x1F3FB }, /* waving hand: light skin tone */
                    395:        { 0x1F44B, 0x1F3FC }, /* waving hand: medium-light skin tone */
                    396:        { 0x1F44B, 0x1F3FD }, /* waving hand: medium skin tone */
                    397:        { 0x1F44B, 0x1F3FE }, /* waving hand: medium-dark skin tone */
                    398:        { 0x1F44B, 0x1F3FF }, /* waving hand: dark skin tone */
                    399:        { 0x1F44C, 0x1F3FB }, /* OK hand: light skin tone */
                    400:        { 0x1F44C, 0x1F3FC }, /* OK hand: medium-light skin tone */
                    401:        { 0x1F44C, 0x1F3FD }, /* OK hand: medium skin tone */
                    402:        { 0x1F44C, 0x1F3FE }, /* OK hand: medium-dark skin tone */
                    403:        { 0x1F44C, 0x1F3FF }, /* OK hand: dark skin tone */
                    404:        { 0x1F44D, 0x1F3FB }, /* thumbs up: light skin tone */
                    405:        { 0x1F44D, 0x1F3FC }, /* thumbs up: medium-light skin tone */
                    406:        { 0x1F44D, 0x1F3FD }, /* thumbs up: medium skin tone */
                    407:        { 0x1F44D, 0x1F3FE }, /* thumbs up: medium-dark skin tone */
                    408:        { 0x1F44D, 0x1F3FF }, /* thumbs up: dark skin tone */
                    409:        { 0x1F44E, 0x1F3FB }, /* thumbs down: light skin tone */
                    410:        { 0x1F44E, 0x1F3FC }, /* thumbs down: medium-light skin tone */
                    411:        { 0x1F44E, 0x1F3FD }, /* thumbs down: medium skin tone */
                    412:        { 0x1F44E, 0x1F3FE }, /* thumbs down: medium-dark skin tone */
                    413:        { 0x1F44E, 0x1F3FF }, /* thumbs down: dark skin tone */
                    414:        { 0x1F44F, 0x1F3FB }, /* clapping hands: light skin tone */
                    415:        { 0x1F44F, 0x1F3FC }, /* clapping hands: medium-light skin tone */
                    416:        { 0x1F44F, 0x1F3FD }, /* clapping hands: medium skin tone */
                    417:        { 0x1F44F, 0x1F3FE }, /* clapping hands: medium-dark skin tone */
                    418:        { 0x1F44F, 0x1F3FF }, /* clapping hands: dark skin tone */
                    419:        { 0x1F450, 0x1F3FB }, /* open hands: light skin tone */
                    420:        { 0x1F450, 0x1F3FC }, /* open hands: medium-light skin tone */
                    421:        { 0x1F450, 0x1F3FD }, /* open hands: medium skin tone */
                    422:        { 0x1F450, 0x1F3FE }, /* open hands: medium-dark skin tone */
                    423:        { 0x1F450, 0x1F3FF }, /* open hands: dark skin tone */
                    424:        { 0x1F466, 0x1F3FB }, /* boy: light skin tone */
                    425:        { 0x1F466, 0x1F3FC }, /* boy: medium-light skin tone */
                    426:        { 0x1F466, 0x1F3FD }, /* boy: medium skin tone */
                    427:        { 0x1F466, 0x1F3FE }, /* boy: medium-dark skin tone */
                    428:        { 0x1F466, 0x1F3FF }, /* boy: dark skin tone */
                    429:        { 0x1F467, 0x1F3FB }, /* girl: light skin tone */
                    430:        { 0x1F467, 0x1F3FC }, /* girl: medium-light skin tone */
                    431:        { 0x1F467, 0x1F3FD }, /* girl: medium skin tone */
                    432:        { 0x1F467, 0x1F3FE }, /* girl: medium-dark skin tone */
                    433:        { 0x1F467, 0x1F3FF }, /* girl: dark skin tone */
                    434:        { 0x1F468, 0x1F3FB }, /* man: light skin tone */
                    435:        { 0x1F468, 0x1F3FC }, /* man: medium-light skin tone */
                    436:        { 0x1F468, 0x1F3FD }, /* man: medium skin tone */
                    437:        { 0x1F468, 0x1F3FE }, /* man: medium-dark skin tone */
                    438:        { 0x1F468, 0x1F3FF }, /* man: dark skin tone */
                    439:        { 0x1F469, 0x1F3FB }, /* woman: light skin tone */
                    440:        { 0x1F469, 0x1F3FC }, /* woman: medium-light skin tone */
                    441:        { 0x1F469, 0x1F3FD }, /* woman: medium skin tone */
                    442:        { 0x1F469, 0x1F3FE }, /* woman: medium-dark skin tone */
                    443:        { 0x1F469, 0x1F3FF }, /* woman: dark skin tone */
                    444:        { 0x1F46B, 0x1F3FB }, /* woman and man holding hands: light skin tone */
                    445:        { 0x1F46B, 0x1F3FC }, /* woman and man holding hands: medium-light skin tone */
                    446:        { 0x1F46B, 0x1F3FD }, /* woman and man holding hands: medium skin tone */
                    447:        { 0x1F46B, 0x1F3FE }, /* woman and man holding hands: medium-dark skin tone */
                    448:        { 0x1F46B, 0x1F3FF }, /* woman and man holding hands: dark skin tone */
                    449:        { 0x1F46C, 0x1F3FB }, /* men holding hands: light skin tone */
                    450:        { 0x1F46C, 0x1F3FC }, /* men holding hands: medium-light skin tone */
                    451:        { 0x1F46C, 0x1F3FD }, /* men holding hands: medium skin tone */
                    452:        { 0x1F46C, 0x1F3FE }, /* men holding hands: medium-dark skin tone */
                    453:        { 0x1F46C, 0x1F3FF }, /* men holding hands: dark skin tone */
                    454:        { 0x1F46D, 0x1F3FB }, /* women holding hands: light skin tone */
                    455:        { 0x1F46D, 0x1F3FC }, /* women holding hands: medium-light skin tone */
                    456:        { 0x1F46D, 0x1F3FD }, /* women holding hands: medium skin tone */
                    457:        { 0x1F46D, 0x1F3FE }, /* women holding hands: medium-dark skin tone */
                    458:        { 0x1F46D, 0x1F3FF }, /* women holding hands: dark skin tone */
                    459:        { 0x1F46E, 0x1F3FB }, /* police officer: light skin tone */
                    460:        { 0x1F46E, 0x1F3FC }, /* police officer: medium-light skin tone */
                    461:        { 0x1F46E, 0x1F3FD }, /* police officer: medium skin tone */
                    462:        { 0x1F46E, 0x1F3FE }, /* police officer: medium-dark skin tone */
                    463:        { 0x1F46E, 0x1F3FF }, /* police officer: dark skin tone */
                    464:        { 0x1F470, 0x1F3FB }, /* person with veil: light skin tone */
                    465:        { 0x1F470, 0x1F3FC }, /* person with veil: medium-light skin tone */
                    466:        { 0x1F470, 0x1F3FD }, /* person with veil: medium skin tone */
                    467:        { 0x1F470, 0x1F3FE }, /* person with veil: medium-dark skin tone */
                    468:        { 0x1F470, 0x1F3FF }, /* person with veil: dark skin tone */
                    469:        { 0x1F471, 0x1F3FB }, /* person: light skin tone, blond hair */
                    470:        { 0x1F471, 0x1F3FC }, /* person: medium-light skin tone, blond hair */
                    471:        { 0x1F471, 0x1F3FD }, /* person: medium skin tone, blond hair */
                    472:        { 0x1F471, 0x1F3FE }, /* person: medium-dark skin tone, blond hair */
                    473:        { 0x1F471, 0x1F3FF }, /* person: dark skin tone, blond hair */
                    474:        { 0x1F472, 0x1F3FB }, /* person with skullcap: light skin tone */
                    475:        { 0x1F472, 0x1F3FC }, /* person with skullcap: medium-light skin tone */
                    476:        { 0x1F472, 0x1F3FD }, /* person with skullcap: medium skin tone */
                    477:        { 0x1F472, 0x1F3FE }, /* person with skullcap: medium-dark skin tone */
                    478:        { 0x1F472, 0x1F3FF }, /* person with skullcap: dark skin tone */
                    479:        { 0x1F473, 0x1F3FB }, /* person wearing turban: light skin tone */
                    480:        { 0x1F473, 0x1F3FC }, /* person wearing turban: medium-light skin tone */
                    481:        { 0x1F473, 0x1F3FD }, /* person wearing turban: medium skin tone */
                    482:        { 0x1F473, 0x1F3FE }, /* person wearing turban: medium-dark skin tone */
                    483:        { 0x1F473, 0x1F3FF }, /* person wearing turban: dark skin tone */
                    484:        { 0x1F474, 0x1F3FB }, /* old man: light skin tone */
                    485:        { 0x1F474, 0x1F3FC }, /* old man: medium-light skin tone */
                    486:        { 0x1F474, 0x1F3FD }, /* old man: medium skin tone */
                    487:        { 0x1F474, 0x1F3FE }, /* old man: medium-dark skin tone */
                    488:        { 0x1F474, 0x1F3FF }, /* old man: dark skin tone */
                    489:        { 0x1F475, 0x1F3FB }, /* old woman: light skin tone */
                    490:        { 0x1F475, 0x1F3FC }, /* old woman: medium-light skin tone */
                    491:        { 0x1F475, 0x1F3FD }, /* old woman: medium skin tone */
                    492:        { 0x1F475, 0x1F3FE }, /* old woman: medium-dark skin tone */
                    493:        { 0x1F475, 0x1F3FF }, /* old woman: dark skin tone */
                    494:        { 0x1F476, 0x1F3FB }, /* baby: light skin tone */
                    495:        { 0x1F476, 0x1F3FC }, /* baby: medium-light skin tone */
                    496:        { 0x1F476, 0x1F3FD }, /* baby: medium skin tone */
                    497:        { 0x1F476, 0x1F3FE }, /* baby: medium-dark skin tone */
                    498:        { 0x1F476, 0x1F3FF }, /* baby: dark skin tone */
                    499:        { 0x1F477, 0x1F3FB }, /* construction worker: light skin tone */
                    500:        { 0x1F477, 0x1F3FC }, /* construction worker: medium-light skin tone */
                    501:        { 0x1F477, 0x1F3FD }, /* construction worker: medium skin tone */
                    502:        { 0x1F477, 0x1F3FE }, /* construction worker: medium-dark skin tone */
                    503:        { 0x1F477, 0x1F3FF }, /* construction worker: dark skin tone */
                    504:        { 0x1F478, 0x1F3FB }, /* princess: light skin tone */
                    505:        { 0x1F478, 0x1F3FC }, /* princess: medium-light skin tone */
                    506:        { 0x1F478, 0x1F3FD }, /* princess: medium skin tone */
                    507:        { 0x1F478, 0x1F3FE }, /* princess: medium-dark skin tone */
                    508:        { 0x1F478, 0x1F3FF }, /* princess: dark skin tone */
                    509:        { 0x1F47C, 0x1F3FB }, /* baby angel: light skin tone */
                    510:        { 0x1F47C, 0x1F3FC }, /* baby angel: medium-light skin tone */
                    511:        { 0x1F47C, 0x1F3FD }, /* baby angel: medium skin tone */
                    512:        { 0x1F47C, 0x1F3FE }, /* baby angel: medium-dark skin tone */
                    513:        { 0x1F47C, 0x1F3FF }, /* baby angel: dark skin tone */
                    514:        { 0x1F481, 0x1F3FB }, /* person tipping hand: light skin tone */
                    515:        { 0x1F481, 0x1F3FC }, /* person tipping hand: medium-light skin tone */
                    516:        { 0x1F481, 0x1F3FD }, /* person tipping hand: medium skin tone */
                    517:        { 0x1F481, 0x1F3FE }, /* person tipping hand: medium-dark skin tone */
                    518:        { 0x1F481, 0x1F3FF }, /* person tipping hand: dark skin tone */
                    519:        { 0x1F482, 0x1F3FB }, /* guard: light skin tone */
                    520:        { 0x1F482, 0x1F3FC }, /* guard: medium-light skin tone */
                    521:        { 0x1F482, 0x1F3FD }, /* guard: medium skin tone */
                    522:        { 0x1F482, 0x1F3FE }, /* guard: medium-dark skin tone */
                    523:        { 0x1F482, 0x1F3FF }, /* guard: dark skin tone */
                    524:        { 0x1F483, 0x1F3FB }, /* woman dancing: light skin tone */
                    525:        { 0x1F483, 0x1F3FC }, /* woman dancing: medium-light skin tone */
                    526:        { 0x1F483, 0x1F3FD }, /* woman dancing: medium skin tone */
                    527:        { 0x1F483, 0x1F3FE }, /* woman dancing: medium-dark skin tone */
                    528:        { 0x1F483, 0x1F3FF }, /* woman dancing: dark skin tone */
                    529:        { 0x1F485, 0x1F3FB }, /* nail polish: light skin tone */
                    530:        { 0x1F485, 0x1F3FC }, /* nail polish: medium-light skin tone */
                    531:        { 0x1F485, 0x1F3FD }, /* nail polish: medium skin tone */
                    532:        { 0x1F485, 0x1F3FE }, /* nail polish: medium-dark skin tone */
                    533:        { 0x1F485, 0x1F3FF }, /* nail polish: dark skin tone */
                    534:        { 0x1F486, 0x1F3FB }, /* person getting massage: light skin tone */
                    535:        { 0x1F486, 0x1F3FC }, /* person getting massage: medium-light skin tone */
                    536:        { 0x1F486, 0x1F3FD }, /* person getting massage: medium skin tone */
                    537:        { 0x1F486, 0x1F3FE }, /* person getting massage: medium-dark skin tone */
                    538:        { 0x1F486, 0x1F3FF }, /* person getting massage: dark skin tone */
                    539:        { 0x1F487, 0x1F3FB }, /* person getting haircut: light skin tone */
                    540:        { 0x1F487, 0x1F3FC }, /* person getting haircut: medium-light skin tone */
                    541:        { 0x1F487, 0x1F3FD }, /* person getting haircut: medium skin tone */
                    542:        { 0x1F487, 0x1F3FE }, /* person getting haircut: medium-dark skin tone */
                    543:        { 0x1F487, 0x1F3FF }, /* person getting haircut: dark skin tone */
                    544:        { 0x1F48F, 0x1F3FB }, /* kiss: light skin tone */
                    545:        { 0x1F48F, 0x1F3FC }, /* kiss: medium-light skin tone */
                    546:        { 0x1F48F, 0x1F3FD }, /* kiss: medium skin tone */
                    547:        { 0x1F48F, 0x1F3FE }, /* kiss: medium-dark skin tone */
                    548:        { 0x1F48F, 0x1F3FF }, /* kiss: dark skin tone */
                    549:        { 0x1F491, 0x1F3FB }, /* couple with heart: light skin tone */
                    550:        { 0x1F491, 0x1F3FC }, /* couple with heart: medium-light skin tone */
                    551:        { 0x1F491, 0x1F3FD }, /* couple with heart: medium skin tone */
                    552:        { 0x1F491, 0x1F3FE }, /* couple with heart: medium-dark skin tone */
                    553:        { 0x1F491, 0x1F3FF }, /* couple with heart: dark skin tone */
                    554:        { 0x1F4AA, 0x1F3FB }, /* flexed biceps: light skin tone */
                    555:        { 0x1F4AA, 0x1F3FC }, /* flexed biceps: medium-light skin tone */
                    556:        { 0x1F4AA, 0x1F3FD }, /* flexed biceps: medium skin tone */
                    557:        { 0x1F4AA, 0x1F3FE }, /* flexed biceps: medium-dark skin tone */
                    558:        { 0x1F4AA, 0x1F3FF }, /* flexed biceps: dark skin tone */
                    559:        { 0x1F574, 0x1F3FB }, /* person in suit levitating: light skin tone */
                    560:        { 0x1F574, 0x1F3FC }, /* person in suit levitating: medium-light skin tone */
                    561:        { 0x1F574, 0x1F3FD }, /* person in suit levitating: medium skin tone */
                    562:        { 0x1F574, 0x1F3FE }, /* person in suit levitating: medium-dark skin tone */
                    563:        { 0x1F574, 0x1F3FF }, /* person in suit levitating: dark skin tone */
                    564:        { 0x1F575, 0x1F3FB }, /* detective: light skin tone */
                    565:        { 0x1F575, 0x1F3FC }, /* detective: medium-light skin tone */
                    566:        { 0x1F575, 0x1F3FD }, /* detective: medium skin tone */
                    567:        { 0x1F575, 0x1F3FE }, /* detective: medium-dark skin tone */
                    568:        { 0x1F575, 0x1F3FF }, /* detective: dark skin tone */
                    569:        { 0x1F57A, 0x1F3FB }, /* man dancing: light skin tone */
                    570:        { 0x1F57A, 0x1F3FC }, /* man dancing: medium-light skin tone */
                    571:        { 0x1F57A, 0x1F3FD }, /* man dancing: medium skin tone */
                    572:        { 0x1F57A, 0x1F3FE }, /* man dancing: medium-dark skin tone */
                    573:        { 0x1F57A, 0x1F3FF }, /* man dancing: dark skin tone */
                    574:        { 0x1F590, 0x1F3FB }, /* hand with fingers splayed: light skin tone */
                    575:        { 0x1F590, 0x1F3FC }, /* hand with fingers splayed: medium-light skin tone */
                    576:        { 0x1F590, 0x1F3FD }, /* hand with fingers splayed: medium skin tone */
                    577:        { 0x1F590, 0x1F3FE }, /* hand with fingers splayed: medium-dark skin tone */
                    578:        { 0x1F590, 0x1F3FF }, /* hand with fingers splayed: dark skin tone */
                    579:        { 0x1F595, 0x1F3FB }, /* middle finger: light skin tone */
                    580:        { 0x1F595, 0x1F3FC }, /* middle finger: medium-light skin tone */
                    581:        { 0x1F595, 0x1F3FD }, /* middle finger: medium skin tone */
                    582:        { 0x1F595, 0x1F3FE }, /* middle finger: medium-dark skin tone */
                    583:        { 0x1F595, 0x1F3FF }, /* middle finger: dark skin tone */
                    584:        { 0x1F596, 0x1F3FB }, /* vulcan salute: light skin tone */
                    585:        { 0x1F596, 0x1F3FC }, /* vulcan salute: medium-light skin tone */
                    586:        { 0x1F596, 0x1F3FD }, /* vulcan salute: medium skin tone */
                    587:        { 0x1F596, 0x1F3FE }, /* vulcan salute: medium-dark skin tone */
                    588:        { 0x1F596, 0x1F3FF }, /* vulcan salute: dark skin tone */
                    589:        { 0x1F645, 0x1F3FB }, /* person gesturing NO: light skin tone */
                    590:        { 0x1F645, 0x1F3FC }, /* person gesturing NO: medium-light skin tone */
                    591:        { 0x1F645, 0x1F3FD }, /* person gesturing NO: medium skin tone */
                    592:        { 0x1F645, 0x1F3FE }, /* person gesturing NO: medium-dark skin tone */
                    593:        { 0x1F645, 0x1F3FF }, /* person gesturing NO: dark skin tone */
                    594:        { 0x1F646, 0x1F3FB }, /* person gesturing OK: light skin tone */
                    595:        { 0x1F646, 0x1F3FC }, /* person gesturing OK: medium-light skin tone */
                    596:        { 0x1F646, 0x1F3FD }, /* person gesturing OK: medium skin tone */
                    597:        { 0x1F646, 0x1F3FE }, /* person gesturing OK: medium-dark skin tone */
                    598:        { 0x1F646, 0x1F3FF }, /* person gesturing OK: dark skin tone */
                    599:        { 0x1F647, 0x1F3FB }, /* person bowing: light skin tone */
                    600:        { 0x1F647, 0x1F3FC }, /* person bowing: medium-light skin tone */
                    601:        { 0x1F647, 0x1F3FD }, /* person bowing: medium skin tone */
                    602:        { 0x1F647, 0x1F3FE }, /* person bowing: medium-dark skin tone */
                    603:        { 0x1F647, 0x1F3FF }, /* person bowing: dark skin tone */
                    604:        { 0x1F64B, 0x1F3FB }, /* person raising hand: light skin tone */
                    605:        { 0x1F64B, 0x1F3FC }, /* person raising hand: medium-light skin tone */
                    606:        { 0x1F64B, 0x1F3FD }, /* person raising hand: medium skin tone */
                    607:        { 0x1F64B, 0x1F3FE }, /* person raising hand: medium-dark skin tone */
                    608:        { 0x1F64B, 0x1F3FF }, /* person raising hand: dark skin tone */
                    609:        { 0x1F64C, 0x1F3FB }, /* raising hands: light skin tone */
                    610:        { 0x1F64C, 0x1F3FC }, /* raising hands: medium-light skin tone */
                    611:        { 0x1F64C, 0x1F3FD }, /* raising hands: medium skin tone */
                    612:        { 0x1F64C, 0x1F3FE }, /* raising hands: medium-dark skin tone */
                    613:        { 0x1F64C, 0x1F3FF }, /* raising hands: dark skin tone */
                    614:        { 0x1F64D, 0x1F3FB }, /* person frowning: light skin tone */
                    615:        { 0x1F64D, 0x1F3FC }, /* person frowning: medium-light skin tone */
                    616:        { 0x1F64D, 0x1F3FD }, /* person frowning: medium skin tone */
                    617:        { 0x1F64D, 0x1F3FE }, /* person frowning: medium-dark skin tone */
                    618:        { 0x1F64D, 0x1F3FF }, /* person frowning: dark skin tone */
                    619:        { 0x1F64E, 0x1F3FB }, /* person pouting: light skin tone */
                    620:        { 0x1F64E, 0x1F3FC }, /* person pouting: medium-light skin tone */
                    621:        { 0x1F64E, 0x1F3FD }, /* person pouting: medium skin tone */
                    622:        { 0x1F64E, 0x1F3FE }, /* person pouting: medium-dark skin tone */
                    623:        { 0x1F64E, 0x1F3FF }, /* person pouting: dark skin tone */
                    624:        { 0x1F64F, 0x1F3FB }, /* folded hands: light skin tone */
                    625:        { 0x1F64F, 0x1F3FC }, /* folded hands: medium-light skin tone */
                    626:        { 0x1F64F, 0x1F3FD }, /* folded hands: medium skin tone */
                    627:        { 0x1F64F, 0x1F3FE }, /* folded hands: medium-dark skin tone */
                    628:        { 0x1F64F, 0x1F3FF }, /* folded hands: dark skin tone */
                    629:        { 0x1F6A3, 0x1F3FB }, /* person rowing boat: light skin tone */
                    630:        { 0x1F6A3, 0x1F3FC }, /* person rowing boat: medium-light skin tone */
                    631:        { 0x1F6A3, 0x1F3FD }, /* person rowing boat: medium skin tone */
                    632:        { 0x1F6A3, 0x1F3FE }, /* person rowing boat: medium-dark skin tone */
                    633:        { 0x1F6A3, 0x1F3FF }, /* person rowing boat: dark skin tone */
                    634:        { 0x1F6B4, 0x1F3FB }, /* person biking: light skin tone */
                    635:        { 0x1F6B4, 0x1F3FC }, /* person biking: medium-light skin tone */
                    636:        { 0x1F6B4, 0x1F3FD }, /* person biking: medium skin tone */
                    637:        { 0x1F6B4, 0x1F3FE }, /* person biking: medium-dark skin tone */
                    638:        { 0x1F6B4, 0x1F3FF }, /* person biking: dark skin tone */
                    639:        { 0x1F6B5, 0x1F3FB }, /* person mountain biking: light skin tone */
                    640:        { 0x1F6B5, 0x1F3FC }, /* person mountain biking: medium-light skin tone */
                    641:        { 0x1F6B5, 0x1F3FD }, /* person mountain biking: medium skin tone */
                    642:        { 0x1F6B5, 0x1F3FE }, /* person mountain biking: medium-dark skin tone */
                    643:        { 0x1F6B5, 0x1F3FF }, /* person mountain biking: dark skin tone */
                    644:        { 0x1F6B6, 0x1F3FB }, /* person walking: light skin tone */
                    645:        { 0x1F6B6, 0x1F3FC }, /* person walking: medium-light skin tone */
                    646:        { 0x1F6B6, 0x1F3FD }, /* person walking: medium skin tone */
                    647:        { 0x1F6B6, 0x1F3FE }, /* person walking: medium-dark skin tone */
                    648:        { 0x1F6B6, 0x1F3FF }, /* person walking: dark skin tone */
                    649:        { 0x1F6C0, 0x1F3FB }, /* person taking bath: light skin tone */
                    650:        { 0x1F6C0, 0x1F3FC }, /* person taking bath: medium-light skin tone */
                    651:        { 0x1F6C0, 0x1F3FD }, /* person taking bath: medium skin tone */
                    652:        { 0x1F6C0, 0x1F3FE }, /* person taking bath: medium-dark skin tone */
                    653:        { 0x1F6C0, 0x1F3FF }, /* person taking bath: dark skin tone */
                    654:        { 0x1F6CC, 0x1F3FB }, /* person in bed: light skin tone */
                    655:        { 0x1F6CC, 0x1F3FC }, /* person in bed: medium-light skin tone */
                    656:        { 0x1F6CC, 0x1F3FD }, /* person in bed: medium skin tone */
                    657:        { 0x1F6CC, 0x1F3FE }, /* person in bed: medium-dark skin tone */
                    658:        { 0x1F6CC, 0x1F3FF }, /* person in bed: dark skin tone */
                    659:        { 0x1F90C, 0x1F3FB }, /* pinched fingers: light skin tone */
                    660:        { 0x1F90C, 0x1F3FC }, /* pinched fingers: medium-light skin tone */
                    661:        { 0x1F90C, 0x1F3FD }, /* pinched fingers: medium skin tone */
                    662:        { 0x1F90C, 0x1F3FE }, /* pinched fingers: medium-dark skin tone */
                    663:        { 0x1F90C, 0x1F3FF }, /* pinched fingers: dark skin tone */
                    664:        { 0x1F90F, 0x1F3FB }, /* pinching hand: light skin tone */
                    665:        { 0x1F90F, 0x1F3FC }, /* pinching hand: medium-light skin tone */
                    666:        { 0x1F90F, 0x1F3FD }, /* pinching hand: medium skin tone */
                    667:        { 0x1F90F, 0x1F3FE }, /* pinching hand: medium-dark skin tone */
                    668:        { 0x1F90F, 0x1F3FF }, /* pinching hand: dark skin tone */
                    669:        { 0x1F918, 0x1F3FB }, /* sign of the horns: light skin tone */
                    670:        { 0x1F918, 0x1F3FC }, /* sign of the horns: medium-light skin tone */
                    671:        { 0x1F918, 0x1F3FD }, /* sign of the horns: medium skin tone */
                    672:        { 0x1F918, 0x1F3FE }, /* sign of the horns: medium-dark skin tone */
                    673:        { 0x1F918, 0x1F3FF }, /* sign of the horns: dark skin tone */
                    674:        { 0x1F919, 0x1F3FB }, /* call me hand: light skin tone */
                    675:        { 0x1F919, 0x1F3FC }, /* call me hand: medium-light skin tone */
                    676:        { 0x1F919, 0x1F3FD }, /* call me hand: medium skin tone */
                    677:        { 0x1F919, 0x1F3FE }, /* call me hand: medium-dark skin tone */
                    678:        { 0x1F919, 0x1F3FF }, /* call me hand: dark skin tone */
                    679:        { 0x1F91A, 0x1F3FB }, /* raised back of hand: light skin tone */
                    680:        { 0x1F91A, 0x1F3FC }, /* raised back of hand: medium-light skin tone */
                    681:        { 0x1F91A, 0x1F3FD }, /* raised back of hand: medium skin tone */
                    682:        { 0x1F91A, 0x1F3FE }, /* raised back of hand: medium-dark skin tone */
                    683:        { 0x1F91A, 0x1F3FF }, /* raised back of hand: dark skin tone */
                    684:        { 0x1F91B, 0x1F3FB }, /* left-facing fist: light skin tone */
                    685:        { 0x1F91B, 0x1F3FC }, /* left-facing fist: medium-light skin tone */
                    686:        { 0x1F91B, 0x1F3FD }, /* left-facing fist: medium skin tone */
                    687:        { 0x1F91B, 0x1F3FE }, /* left-facing fist: medium-dark skin tone */
                    688:        { 0x1F91B, 0x1F3FF }, /* left-facing fist: dark skin tone */
                    689:        { 0x1F91C, 0x1F3FB }, /* right-facing fist: light skin tone */
                    690:        { 0x1F91C, 0x1F3FC }, /* right-facing fist: medium-light skin tone */
                    691:        { 0x1F91C, 0x1F3FD }, /* right-facing fist: medium skin tone */
                    692:        { 0x1F91C, 0x1F3FE }, /* right-facing fist: medium-dark skin tone */
                    693:        { 0x1F91C, 0x1F3FF }, /* right-facing fist: dark skin tone */
                    694:        { 0x1F91D, 0x1F3FB }, /* handshake: light skin tone */
                    695:        { 0x1F91D, 0x1F3FC }, /* handshake: medium-light skin tone */
                    696:        { 0x1F91D, 0x1F3FD }, /* handshake: medium skin tone */
                    697:        { 0x1F91D, 0x1F3FE }, /* handshake: medium-dark skin tone */
                    698:        { 0x1F91D, 0x1F3FF }, /* handshake: dark skin tone */
                    699:        { 0x1F91E, 0x1F3FB }, /* crossed fingers: light skin tone */
                    700:        { 0x1F91E, 0x1F3FC }, /* crossed fingers: medium-light skin tone */
                    701:        { 0x1F91E, 0x1F3FD }, /* crossed fingers: medium skin tone */
                    702:        { 0x1F91E, 0x1F3FE }, /* crossed fingers: medium-dark skin tone */
                    703:        { 0x1F91E, 0x1F3FF }, /* crossed fingers: dark skin tone */
                    704:        { 0x1F91F, 0x1F3FB }, /* love-you gesture: light skin tone */
                    705:        { 0x1F91F, 0x1F3FC }, /* love-you gesture: medium-light skin tone */
                    706:        { 0x1F91F, 0x1F3FD }, /* love-you gesture: medium skin tone */
                    707:        { 0x1F91F, 0x1F3FE }, /* love-you gesture: medium-dark skin tone */
                    708:        { 0x1F91F, 0x1F3FF }, /* love-you gesture: dark skin tone */
                    709:        { 0x1F926, 0x1F3FB }, /* person facepalming: light skin tone */
                    710:        { 0x1F926, 0x1F3FC }, /* person facepalming: medium-light skin tone */
                    711:        { 0x1F926, 0x1F3FD }, /* person facepalming: medium skin tone */
                    712:        { 0x1F926, 0x1F3FE }, /* person facepalming: medium-dark skin tone */
                    713:        { 0x1F926, 0x1F3FF }, /* person facepalming: dark skin tone */
                    714:        { 0x1F930, 0x1F3FB }, /* pregnant woman: light skin tone */
                    715:        { 0x1F930, 0x1F3FC }, /* pregnant woman: medium-light skin tone */
                    716:        { 0x1F930, 0x1F3FD }, /* pregnant woman: medium skin tone */
                    717:        { 0x1F930, 0x1F3FE }, /* pregnant woman: medium-dark skin tone */
                    718:        { 0x1F930, 0x1F3FF }, /* pregnant woman: dark skin tone */
                    719:        { 0x1F931, 0x1F3FB }, /* breast-feeding: light skin tone */
                    720:        { 0x1F931, 0x1F3FC }, /* breast-feeding: medium-light skin tone */
                    721:        { 0x1F931, 0x1F3FD }, /* breast-feeding: medium skin tone */
                    722:        { 0x1F931, 0x1F3FE }, /* breast-feeding: medium-dark skin tone */
                    723:        { 0x1F931, 0x1F3FF }, /* breast-feeding: dark skin tone */
                    724:        { 0x1F932, 0x1F3FB }, /* palms up together: light skin tone */
                    725:        { 0x1F932, 0x1F3FC }, /* palms up together: medium-light skin tone */
                    726:        { 0x1F932, 0x1F3FD }, /* palms up together: medium skin tone */
                    727:        { 0x1F932, 0x1F3FE }, /* palms up together: medium-dark skin tone */
                    728:        { 0x1F932, 0x1F3FF }, /* palms up together: dark skin tone */
                    729:        { 0x1F933, 0x1F3FB }, /* selfie: light skin tone */
                    730:        { 0x1F933, 0x1F3FC }, /* selfie: medium-light skin tone */
                    731:        { 0x1F933, 0x1F3FD }, /* selfie: medium skin tone */
                    732:        { 0x1F933, 0x1F3FE }, /* selfie: medium-dark skin tone */
                    733:        { 0x1F933, 0x1F3FF }, /* selfie: dark skin tone */
                    734:        { 0x1F934, 0x1F3FB }, /* prince: light skin tone */
                    735:        { 0x1F934, 0x1F3FC }, /* prince: medium-light skin tone */
                    736:        { 0x1F934, 0x1F3FD }, /* prince: medium skin tone */
                    737:        { 0x1F934, 0x1F3FE }, /* prince: medium-dark skin tone */
                    738:        { 0x1F934, 0x1F3FF }, /* prince: dark skin tone */
                    739:        { 0x1F935, 0x1F3FB }, /* person in tuxedo: light skin tone */
                    740:        { 0x1F935, 0x1F3FC }, /* person in tuxedo: medium-light skin tone */
                    741:        { 0x1F935, 0x1F3FD }, /* person in tuxedo: medium skin tone */
                    742:        { 0x1F935, 0x1F3FE }, /* person in tuxedo: medium-dark skin tone */
                    743:        { 0x1F935, 0x1F3FF }, /* person in tuxedo: dark skin tone */
                    744:        { 0x1F936, 0x1F3FB }, /* Mrs. Claus: light skin tone */
                    745:        { 0x1F936, 0x1F3FC }, /* Mrs. Claus: medium-light skin tone */
                    746:        { 0x1F936, 0x1F3FD }, /* Mrs. Claus: medium skin tone */
                    747:        { 0x1F936, 0x1F3FE }, /* Mrs. Claus: medium-dark skin tone */
                    748:        { 0x1F936, 0x1F3FF }, /* Mrs. Claus: dark skin tone */
                    749:        { 0x1F937, 0x1F3FB }, /* person shrugging: light skin tone */
                    750:        { 0x1F937, 0x1F3FC }, /* person shrugging: medium-light skin tone */
                    751:        { 0x1F937, 0x1F3FD }, /* person shrugging: medium skin tone */
                    752:        { 0x1F937, 0x1F3FE }, /* person shrugging: medium-dark skin tone */
                    753:        { 0x1F937, 0x1F3FF }, /* person shrugging: dark skin tone */
                    754:        { 0x1F938, 0x1F3FB }, /* person cartwheeling: light skin tone */
                    755:        { 0x1F938, 0x1F3FC }, /* person cartwheeling: medium-light skin tone */
                    756:        { 0x1F938, 0x1F3FD }, /* person cartwheeling: medium skin tone */
                    757:        { 0x1F938, 0x1F3FE }, /* person cartwheeling: medium-dark skin tone */
                    758:        { 0x1F938, 0x1F3FF }, /* person cartwheeling: dark skin tone */
                    759:        { 0x1F939, 0x1F3FB }, /* person juggling: light skin tone */
                    760:        { 0x1F939, 0x1F3FC }, /* person juggling: medium-light skin tone */
                    761:        { 0x1F939, 0x1F3FD }, /* person juggling: medium skin tone */
                    762:        { 0x1F939, 0x1F3FE }, /* person juggling: medium-dark skin tone */
                    763:        { 0x1F939, 0x1F3FF }, /* person juggling: dark skin tone */
                    764:        { 0x1F93D, 0x1F3FB }, /* person playing water polo: light skin tone */
                    765:        { 0x1F93D, 0x1F3FC }, /* person playing water polo: medium-light skin tone */
                    766:        { 0x1F93D, 0x1F3FD }, /* person playing water polo: medium skin tone */
                    767:        { 0x1F93D, 0x1F3FE }, /* person playing water polo: medium-dark skin tone */
                    768:        { 0x1F93D, 0x1F3FF }, /* person playing water polo: dark skin tone */
                    769:        { 0x1F93E, 0x1F3FB }, /* person playing handball: light skin tone */
                    770:        { 0x1F93E, 0x1F3FC }, /* person playing handball: medium-light skin tone */
                    771:        { 0x1F93E, 0x1F3FD }, /* person playing handball: medium skin tone */
                    772:        { 0x1F93E, 0x1F3FE }, /* person playing handball: medium-dark skin tone */
                    773:        { 0x1F93E, 0x1F3FF }, /* person playing handball: dark skin tone */
                    774:        { 0x1F977, 0x1F3FB }, /* ninja: light skin tone */
                    775:        { 0x1F977, 0x1F3FC }, /* ninja: medium-light skin tone */
                    776:        { 0x1F977, 0x1F3FD }, /* ninja: medium skin tone */
                    777:        { 0x1F977, 0x1F3FE }, /* ninja: medium-dark skin tone */
                    778:        { 0x1F977, 0x1F3FF }, /* ninja: dark skin tone */
                    779:        { 0x1F9B5, 0x1F3FB }, /* leg: light skin tone */
                    780:        { 0x1F9B5, 0x1F3FC }, /* leg: medium-light skin tone */
                    781:        { 0x1F9B5, 0x1F3FD }, /* leg: medium skin tone */
                    782:        { 0x1F9B5, 0x1F3FE }, /* leg: medium-dark skin tone */
                    783:        { 0x1F9B5, 0x1F3FF }, /* leg: dark skin tone */
                    784:        { 0x1F9B6, 0x1F3FB }, /* foot: light skin tone */
                    785:        { 0x1F9B6, 0x1F3FC }, /* foot: medium-light skin tone */
                    786:        { 0x1F9B6, 0x1F3FD }, /* foot: medium skin tone */
                    787:        { 0x1F9B6, 0x1F3FE }, /* foot: medium-dark skin tone */
                    788:        { 0x1F9B6, 0x1F3FF }, /* foot: dark skin tone */
                    789:        { 0x1F9B8, 0x1F3FB }, /* superhero: light skin tone */
                    790:        { 0x1F9B8, 0x1F3FC }, /* superhero: medium-light skin tone */
                    791:        { 0x1F9B8, 0x1F3FD }, /* superhero: medium skin tone */
                    792:        { 0x1F9B8, 0x1F3FE }, /* superhero: medium-dark skin tone */
                    793:        { 0x1F9B8, 0x1F3FF }, /* superhero: dark skin tone */
                    794:        { 0x1F9B9, 0x1F3FB }, /* supervillain: light skin tone */
                    795:        { 0x1F9B9, 0x1F3FC }, /* supervillain: medium-light skin tone */
                    796:        { 0x1F9B9, 0x1F3FD }, /* supervillain: medium skin tone */
                    797:        { 0x1F9B9, 0x1F3FE }, /* supervillain: medium-dark skin tone */
                    798:        { 0x1F9B9, 0x1F3FF }, /* supervillain: dark skin tone */
                    799:        { 0x1F9BB, 0x1F3FB }, /* ear with hearing aid: light skin tone */
                    800:        { 0x1F9BB, 0x1F3FC }, /* ear with hearing aid: medium-light skin tone */
                    801:        { 0x1F9BB, 0x1F3FD }, /* ear with hearing aid: medium skin tone */
                    802:        { 0x1F9BB, 0x1F3FE }, /* ear with hearing aid: medium-dark skin tone */
                    803:        { 0x1F9BB, 0x1F3FF }, /* ear with hearing aid: dark skin tone */
                    804:        { 0x1F9CD, 0x1F3FB }, /* person standing: light skin tone */
                    805:        { 0x1F9CD, 0x1F3FC }, /* person standing: medium-light skin tone */
                    806:        { 0x1F9CD, 0x1F3FD }, /* person standing: medium skin tone */
                    807:        { 0x1F9CD, 0x1F3FE }, /* person standing: medium-dark skin tone */
                    808:        { 0x1F9CD, 0x1F3FF }, /* person standing: dark skin tone */
                    809:        { 0x1F9CE, 0x1F3FB }, /* person kneeling: light skin tone */
                    810:        { 0x1F9CE, 0x1F3FC }, /* person kneeling: medium-light skin tone */
                    811:        { 0x1F9CE, 0x1F3FD }, /* person kneeling: medium skin tone */
                    812:        { 0x1F9CE, 0x1F3FE }, /* person kneeling: medium-dark skin tone */
                    813:        { 0x1F9CE, 0x1F3FF }, /* person kneeling: dark skin tone */
                    814:        { 0x1F9CF, 0x1F3FB }, /* deaf person: light skin tone */
                    815:        { 0x1F9CF, 0x1F3FC }, /* deaf person: medium-light skin tone */
                    816:        { 0x1F9CF, 0x1F3FD }, /* deaf person: medium skin tone */
                    817:        { 0x1F9CF, 0x1F3FE }, /* deaf person: medium-dark skin tone */
                    818:        { 0x1F9CF, 0x1F3FF }, /* deaf person: dark skin tone */
                    819:        { 0x1F9D1, 0x1F3FB }, /* person: light skin tone */
                    820:        { 0x1F9D1, 0x1F3FC }, /* person: medium-light skin tone */
                    821:        { 0x1F9D1, 0x1F3FD }, /* person: medium skin tone */
                    822:        { 0x1F9D1, 0x1F3FE }, /* person: medium-dark skin tone */
                    823:        { 0x1F9D1, 0x1F3FF }, /* person: dark skin tone */
                    824:        { 0x1F9D2, 0x1F3FB }, /* child: light skin tone */
                    825:        { 0x1F9D2, 0x1F3FC }, /* child: medium-light skin tone */
                    826:        { 0x1F9D2, 0x1F3FD }, /* child: medium skin tone */
                    827:        { 0x1F9D2, 0x1F3FE }, /* child: medium-dark skin tone */
                    828:        { 0x1F9D2, 0x1F3FF }, /* child: dark skin tone */
                    829:        { 0x1F9D3, 0x1F3FB }, /* older person: light skin tone */
                    830:        { 0x1F9D3, 0x1F3FC }, /* older person: medium-light skin tone */
                    831:        { 0x1F9D3, 0x1F3FD }, /* older person: medium skin tone */
                    832:        { 0x1F9D3, 0x1F3FE }, /* older person: medium-dark skin tone */
                    833:        { 0x1F9D3, 0x1F3FF }, /* older person: dark skin tone */
                    834:        { 0x1F9D4, 0x1F3FB }, /* person: light skin tone, beard */
                    835:        { 0x1F9D4, 0x1F3FC }, /* person: medium-light skin tone, beard */
                    836:        { 0x1F9D4, 0x1F3FD }, /* person: medium skin tone, beard */
                    837:        { 0x1F9D4, 0x1F3FE }, /* person: medium-dark skin tone, beard */
                    838:        { 0x1F9D4, 0x1F3FF }, /* person: dark skin tone, beard */
                    839:        { 0x1F9D5, 0x1F3FB }, /* woman with headscarf: light skin tone */
                    840:        { 0x1F9D5, 0x1F3FC }, /* woman with headscarf: medium-light skin tone */
                    841:        { 0x1F9D5, 0x1F3FD }, /* woman with headscarf: medium skin tone */
                    842:        { 0x1F9D5, 0x1F3FE }, /* woman with headscarf: medium-dark skin tone */
                    843:        { 0x1F9D5, 0x1F3FF }, /* woman with headscarf: dark skin tone */
                    844:        { 0x1F9D6, 0x1F3FB }, /* person in steamy room: light skin tone */
                    845:        { 0x1F9D6, 0x1F3FC }, /* person in steamy room: medium-light skin tone */
                    846:        { 0x1F9D6, 0x1F3FD }, /* person in steamy room: medium skin tone */
                    847:        { 0x1F9D6, 0x1F3FE }, /* person in steamy room: medium-dark skin tone */
                    848:        { 0x1F9D6, 0x1F3FF }, /* person in steamy room: dark skin tone */
                    849:        { 0x1F9D7, 0x1F3FB }, /* person climbing: light skin tone */
                    850:        { 0x1F9D7, 0x1F3FC }, /* person climbing: medium-light skin tone */
                    851:        { 0x1F9D7, 0x1F3FD }, /* person climbing: medium skin tone */
                    852:        { 0x1F9D7, 0x1F3FE }, /* person climbing: medium-dark skin tone */
                    853:        { 0x1F9D7, 0x1F3FF }, /* person climbing: dark skin tone */
                    854:        { 0x1F9D8, 0x1F3FB }, /* person in lotus position: light skin tone */
                    855:        { 0x1F9D8, 0x1F3FC }, /* person in lotus position: medium-light skin tone */
                    856:        { 0x1F9D8, 0x1F3FD }, /* person in lotus position: medium skin tone */
                    857:        { 0x1F9D8, 0x1F3FE }, /* person in lotus position: medium-dark skin tone */
                    858:        { 0x1F9D8, 0x1F3FF }, /* person in lotus position: dark skin tone */
                    859:        { 0x1F9D9, 0x1F3FB }, /* mage: light skin tone */
                    860:        { 0x1F9D9, 0x1F3FC }, /* mage: medium-light skin tone */
                    861:        { 0x1F9D9, 0x1F3FD }, /* mage: medium skin tone */
                    862:        { 0x1F9D9, 0x1F3FE }, /* mage: medium-dark skin tone */
                    863:        { 0x1F9D9, 0x1F3FF }, /* mage: dark skin tone */
                    864:        { 0x1F9DA, 0x1F3FB }, /* fairy: light skin tone */
                    865:        { 0x1F9DA, 0x1F3FC }, /* fairy: medium-light skin tone */
                    866:        { 0x1F9DA, 0x1F3FD }, /* fairy: medium skin tone */
                    867:        { 0x1F9DA, 0x1F3FE }, /* fairy: medium-dark skin tone */
                    868:        { 0x1F9DA, 0x1F3FF }, /* fairy: dark skin tone */
                    869:        { 0x1F9DB, 0x1F3FB }, /* vampire: light skin tone */
                    870:        { 0x1F9DB, 0x1F3FC }, /* vampire: medium-light skin tone */
                    871:        { 0x1F9DB, 0x1F3FD }, /* vampire: medium skin tone */
                    872:        { 0x1F9DB, 0x1F3FE }, /* vampire: medium-dark skin tone */
                    873:        { 0x1F9DB, 0x1F3FF }, /* vampire: dark skin tone */
                    874:        { 0x1F9DC, 0x1F3FB }, /* merperson: light skin tone */
                    875:        { 0x1F9DC, 0x1F3FC }, /* merperson: medium-light skin tone */
                    876:        { 0x1F9DC, 0x1F3FD }, /* merperson: medium skin tone */
                    877:        { 0x1F9DC, 0x1F3FE }, /* merperson: medium-dark skin tone */
                    878:        { 0x1F9DC, 0x1F3FF }, /* merperson: dark skin tone */
                    879:        { 0x1F9DD, 0x1F3FB }, /* elf: light skin tone */
                    880:        { 0x1F9DD, 0x1F3FC }, /* elf: medium-light skin tone */
                    881:        { 0x1F9DD, 0x1F3FD }, /* elf: medium skin tone */
                    882:        { 0x1F9DD, 0x1F3FE }, /* elf: medium-dark skin tone */
                    883:        { 0x1F9DD, 0x1F3FF }, /* elf: dark skin tone */
                    884:        { 0x1FAC3, 0x1F3FB }, /* pregnant man: light skin tone */
                    885:        { 0x1FAC3, 0x1F3FC }, /* pregnant man: medium-light skin tone */
                    886:        { 0x1FAC3, 0x1F3FD }, /* pregnant man: medium skin tone */
                    887:        { 0x1FAC3, 0x1F3FE }, /* pregnant man: medium-dark skin tone */
                    888:        { 0x1FAC3, 0x1F3FF }, /* pregnant man: dark skin tone */
                    889:        { 0x1FAC4, 0x1F3FB }, /* pregnant person: light skin tone */
                    890:        { 0x1FAC4, 0x1F3FC }, /* pregnant person: medium-light skin tone */
                    891:        { 0x1FAC4, 0x1F3FD }, /* pregnant person: medium skin tone */
                    892:        { 0x1FAC4, 0x1F3FE }, /* pregnant person: medium-dark skin tone */
                    893:        { 0x1FAC4, 0x1F3FF }, /* pregnant person: dark skin tone */
                    894:        { 0x1FAC5, 0x1F3FB }, /* person with crown: light skin tone */
                    895:        { 0x1FAC5, 0x1F3FC }, /* person with crown: medium-light skin tone */
                    896:        { 0x1FAC5, 0x1F3FD }, /* person with crown: medium skin tone */
                    897:        { 0x1FAC5, 0x1F3FE }, /* person with crown: medium-dark skin tone */
                    898:        { 0x1FAC5, 0x1F3FF }, /* person with crown: dark skin tone */
                    899:        { 0x1FAF0, 0x1F3FB }, /* hand with index finger and thumb crossed: light skin tone */
                    900:        { 0x1FAF0, 0x1F3FC }, /* hand with index finger and thumb crossed: medium-light skin tone */
                    901:        { 0x1FAF0, 0x1F3FD }, /* hand with index finger and thumb crossed: medium skin tone */
                    902:        { 0x1FAF0, 0x1F3FE }, /* hand with index finger and thumb crossed: medium-dark skin tone */
                    903:        { 0x1FAF0, 0x1F3FF }, /* hand with index finger and thumb crossed: dark skin tone */
                    904:        { 0x1FAF1, 0x1F3FB }, /* rightwards hand: light skin tone */
                    905:        { 0x1FAF1, 0x1F3FC }, /* rightwards hand: medium-light skin tone */
                    906:        { 0x1FAF1, 0x1F3FD }, /* rightwards hand: medium skin tone */
                    907:        { 0x1FAF1, 0x1F3FE }, /* rightwards hand: medium-dark skin tone */
                    908:        { 0x1FAF1, 0x1F3FF }, /* rightwards hand: dark skin tone */
                    909:        { 0x1FAF2, 0x1F3FB }, /* leftwards hand: light skin tone */
                    910:        { 0x1FAF2, 0x1F3FC }, /* leftwards hand: medium-light skin tone */
                    911:        { 0x1FAF2, 0x1F3FD }, /* leftwards hand: medium skin tone */
                    912:        { 0x1FAF2, 0x1F3FE }, /* leftwards hand: medium-dark skin tone */
                    913:        { 0x1FAF2, 0x1F3FF }, /* leftwards hand: dark skin tone */
                    914:        { 0x1FAF3, 0x1F3FB }, /* palm down hand: light skin tone */
                    915:        { 0x1FAF3, 0x1F3FC }, /* palm down hand: medium-light skin tone */
                    916:        { 0x1FAF3, 0x1F3FD }, /* palm down hand: medium skin tone */
                    917:        { 0x1FAF3, 0x1F3FE }, /* palm down hand: medium-dark skin tone */
                    918:        { 0x1FAF3, 0x1F3FF }, /* palm down hand: dark skin tone */
                    919:        { 0x1FAF4, 0x1F3FB }, /* palm up hand: light skin tone */
                    920:        { 0x1FAF4, 0x1F3FC }, /* palm up hand: medium-light skin tone */
                    921:        { 0x1FAF4, 0x1F3FD }, /* palm up hand: medium skin tone */
                    922:        { 0x1FAF4, 0x1F3FE }, /* palm up hand: medium-dark skin tone */
                    923:        { 0x1FAF4, 0x1F3FF }, /* palm up hand: dark skin tone */
                    924:        { 0x1FAF5, 0x1F3FB }, /* index pointing at the viewer: light skin tone */
                    925:        { 0x1FAF5, 0x1F3FC }, /* index pointing at the viewer: medium-light skin tone */
                    926:        { 0x1FAF5, 0x1F3FD }, /* index pointing at the viewer: medium skin tone */
                    927:        { 0x1FAF5, 0x1F3FE }, /* index pointing at the viewer: medium-dark skin tone */
                    928:        { 0x1FAF5, 0x1F3FF }, /* index pointing at the viewer: dark skin tone */
                    929:        { 0x1FAF6, 0x1F3FB }, /* heart hands: light skin tone */
                    930:        { 0x1FAF6, 0x1F3FC }, /* heart hands: medium-light skin tone */
                    931:        { 0x1FAF6, 0x1F3FD }, /* heart hands: medium skin tone */
                    932:        { 0x1FAF6, 0x1F3FE }, /* heart hands: medium-dark skin tone */
                    933:        { 0x1FAF6, 0x1F3FF }, /* heart hands: dark skin tone */
                    934:        { 0x1FAF7, 0x1F3FB }, /* leftwards pushing hand: light skin tone */
                    935:        { 0x1FAF7, 0x1F3FC }, /* leftwards pushing hand: medium-light skin tone */
                    936:        { 0x1FAF7, 0x1F3FD }, /* leftwards pushing hand: medium skin tone */
                    937:        { 0x1FAF7, 0x1F3FE }, /* leftwards pushing hand: medium-dark skin tone */
                    938:        { 0x1FAF7, 0x1F3FF }, /* leftwards pushing hand: dark skin tone */
                    939:        { 0x1FAF8, 0x1F3FB }, /* rightwards pushing hand: light skin tone */
                    940:        { 0x1FAF8, 0x1F3FC }, /* rightwards pushing hand: medium-light skin tone */
                    941:        { 0x1FAF8, 0x1F3FD }, /* rightwards pushing hand: medium skin tone */
                    942:        { 0x1FAF8, 0x1F3FE }, /* rightwards pushing hand: medium-dark skin tone */
                    943:        { 0x1FAF8, 0x1F3FF }, /* rightwards pushing hand: dark skin tone */
                    944: };
                    945:
                    946: struct utf8_combined_first {
                    947:        struct utf8_data                 first;
                    948:
                    949:        struct utf8_data                *second;
                    950:        u_int                            count;
                    951:
                    952:        RB_ENTRY(utf8_combined_first)    entry;
                    953: };
                    954:
                    955: static int
                    956: utf8_combined_first_cmp(struct utf8_combined_first *uf1,
                    957:     struct utf8_combined_first *uf2)
                    958: {
                    959:        struct utf8_data        *ud1 = &uf1->first, *ud2 = &uf2->first;
                    960:
                    961:        if (ud1->size < ud2->size)
                    962:                return (-1);
                    963:        if (ud1->size > ud2->size)
                    964:                return (1);
1.2     ! nicm      965:        return (memcmp(ud1->data, ud2->data, ud1->size));
1.1       nicm      966: }
                    967: RB_HEAD(utf8_combined_tree, utf8_combined_first);
                    968: RB_GENERATE_STATIC(utf8_combined_tree, utf8_combined_first, entry,
                    969:     utf8_combined_first_cmp);
                    970: static struct utf8_combined_tree utf8_combined_tree =
                    971:     RB_INITIALIZER(utf8_combined_tree);
                    972:
                    973: static int
                    974: utf8_combined_second_cmp(const void *vp1, const void *vp2)
                    975: {
                    976:        const struct utf8_data  *ud1 = vp1, *ud2 = vp2;
                    977:
                    978:        if (ud1->size < ud2->size)
                    979:                return (-1);
                    980:        if (ud1->size > ud2->size)
                    981:                return (1);
1.2     ! nicm      982:        return (memcmp(ud1->data, ud2->data, ud1->size));
1.1       nicm      983: }
                    984:
                    985: static int
                    986: utf8_is_zwj(const struct utf8_data *ud)
                    987: {
                    988:        return (ud->size == 3 && memcmp(ud->data, "\342\200\215", 3) == 0);
                    989: }
                    990:
                    991: static struct utf8_data *
                    992: utf8_add_zwj(const struct utf8_data *ud)
                    993: {
                    994:        static struct utf8_data new;
                    995:
                    996:        if (ud->size + 3 > UTF8_SIZE)
                    997:                return (NULL);
                    998:        memset(&new, 0, sizeof new);
                    999:        memcpy(new.data, "\342\200\215", 3);
                   1000:        memcpy(new.data + 3, ud->data, ud->size);
                   1001:        new.size = 3 + ud->size;
                   1002:        new.width = ud->width;
                   1003:        return (&new);
                   1004: }
                   1005:
                   1006: static struct utf8_combined_first *
                   1007: utf8_find_combined_first(const struct utf8_data *first)
                   1008: {
                   1009:        struct utf8_combined_first      uf;
                   1010:
                   1011:        memset(&uf, 0, sizeof uf);
                   1012:        utf8_copy(&uf.first, first);
                   1013:        return (RB_FIND(utf8_combined_tree, &utf8_combined_tree, &uf));
                   1014: }
                   1015:
                   1016: static int
                   1017: utf8_find_combined_second(struct utf8_combined_first *uf,
                   1018:     const struct utf8_data *second)
                   1019: {
                   1020:        return (bsearch(second, uf->second, uf->count, sizeof *uf->second,
                   1021:            utf8_combined_second_cmp) != NULL);
                   1022: }
                   1023:
                   1024: void
                   1025: utf8_build_combined(void)
                   1026: {
                   1027:        struct utf8_data                 first, second;
                   1028:        int                              mlen;
                   1029:        u_int                            i;
                   1030:        wchar_t                          wc;
                   1031:        struct utf8_combined_first      *uf;
                   1032:
                   1033:        for (i = 0; i < nitems(utf8_combined_table); i++) {
                   1034:                memset(&first, 0, sizeof first);
                   1035:                wc = utf8_combined_table[i].first;
                   1036:                mlen = wctomb(first.data, wc);
                   1037:                if (mlen <= 0 || mlen > UTF8_SIZE) {
1.2     ! nicm     1038:                        log_debug("invalid combined character %05X", wc);
1.1       nicm     1039:                        continue;
                   1040:                }
                   1041:                first.size = mlen;
                   1042:
                   1043:                uf = utf8_find_combined_first(&first);
                   1044:                if (uf == NULL) {
                   1045:                        uf = xcalloc(1, sizeof *uf);
                   1046:                        utf8_copy(&uf->first, &first);
                   1047:                        RB_INSERT(utf8_combined_tree, &utf8_combined_tree, uf);
                   1048:                }
                   1049:
                   1050:                memset(&second, 0, sizeof second);
                   1051:                wc = utf8_combined_table[i].second;
                   1052:                mlen = wctomb(second.data, wc);
                   1053:                if (mlen <= 0 || mlen > UTF8_SIZE) {
                   1054:                        log_debug("invalid combined character %05X", wc);
                   1055:                        continue;
                   1056:                }
                   1057:                second.size = mlen;
                   1058:
                   1059:                log_debug("combined character %05X+%05X = %.*s+%.*s",
                   1060:                    utf8_combined_table[i].first, utf8_combined_table[i].second,
                   1061:                    (int)first.size, first.data, (int)second.size, second.data);
                   1062:
                   1063:                uf->second = xreallocarray(uf->second, uf->count + 1,
                   1064:                    sizeof *uf->second);
                   1065:                utf8_copy(&uf->second[uf->count], &second);
                   1066:                uf->count++;
                   1067:        }
                   1068:
                   1069:        RB_FOREACH(uf, utf8_combined_tree, &utf8_combined_tree) {
                   1070:                qsort(uf->second, uf->count, sizeof *uf->second,
                   1071:                    utf8_combined_second_cmp);
                   1072:        }
                   1073: }
                   1074:
                   1075: int
                   1076: utf8_try_combined(const struct utf8_data *ud, const struct utf8_data *last,
                   1077:     const struct utf8_data **combine, u_int *width)
                   1078: {
                   1079:        struct utf8_combined_first      *uf;
                   1080:
                   1081:        /* Use the incoming width by default. */
                   1082:        *width = ud->width;
                   1083:
                   1084:        /*
                   1085:         * If this is a zero width joiner, discard it but try to combine the
                   1086:         * next character.
                   1087:         */
                   1088:        if (utf8_is_zwj(ud))
                   1089:                return (UTF8_DISCARD_MAYBE_COMBINE);
                   1090:
                   1091:        /*
                   1092:         * If there is a previous character to combine and it is a ZWJ,
                   1093:         * combine with the new character and a ZWJ.
                   1094:         */
                   1095:        if (last != NULL && utf8_is_zwj(last)) {
                   1096:                *combine = utf8_add_zwj(ud);
                   1097:                if (*combine == NULL)
                   1098:                        return (UTF8_DISCARD_NOW);
                   1099:                return (UTF8_COMBINE_NOW);
                   1100:        }
                   1101:
                   1102:        /*
                   1103:         * If the width of this character is zero, combine onto the previous
                   1104:         * character.
                   1105:         */
                   1106:        if (ud->width == 0) {
                   1107:                *combine = ud;
                   1108:                return (UTF8_COMBINE_NOW);
                   1109:        }
                   1110:
                   1111:        /*
                   1112:         * Look up the character in the first character list, if it is missing,
                   1113:         * write it immediately. If it is present, write but try to combine
                   1114:         * later; also force the width to two.
                   1115:         */
                   1116:        if (last == NULL) {
                   1117:                if (utf8_find_combined_first(ud) != NULL) {
                   1118:                        *width = 2;
                   1119:                        return (UTF8_WRITE_MAYBE_COMBINE);
                   1120:                }
                   1121:                return (UTF8_WRITE_NOW);
                   1122:        }
                   1123:
                   1124:        /*
                   1125:         * This must be a potential combined character. If both first and
                   1126:         * second characters are on the list, combine.
                   1127:         */
                   1128:        uf = utf8_find_combined_first(last);
                   1129:        if (uf != NULL && utf8_find_combined_second(uf, ud)) {
                   1130:                *combine = ud;
                   1131:                return (UTF8_COMBINE_NOW);
                   1132:        }
                   1133:
                   1134:        return (UTF8_WRITE_NOW);
                   1135: }