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: }