summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornicm <nicm>2023-09-15 15:49:05 +0000
committernicm <nicm>2023-09-15 15:49:05 +0000
commitf09cde2542470e5c1a292cc6871c4f0e00cedde5 (patch)
treefa31d93e697ab40131a1c3613f6f63028c0cee8c
parentd394293ba59fc932085eb8c01592822a9b1ec1f7 (diff)
Change UTF-8 combining to inspect the previous character at the cursor
position rather than keeping the last character from the input stream, this is how most terminals work and fixes problems with displaying these characters in vim. GitHub issue 3600.
-rw-r--r--screen-write.c185
-rw-r--r--server.c1
-rw-r--r--tmux.h22
-rw-r--r--tty.c3
-rw-r--r--utf8-combined.c1153
-rw-r--r--utf8.c218
6 files changed, 365 insertions, 1217 deletions
diff --git a/screen-write.c b/screen-write.c
index 1514204d..0fcd156f 100644
--- a/screen-write.c
+++ b/screen-write.c
@@ -32,8 +32,8 @@ static void screen_write_collect_flush(struct screen_write_ctx *, int,
const char *);
static int screen_write_overwrite(struct screen_write_ctx *,
struct grid_cell *, u_int);
-static const struct grid_cell *screen_write_combine(struct screen_write_ctx *,
- const struct utf8_data *, u_int *, u_int *);
+static int screen_write_combine(struct screen_write_ctx *,
+ const struct grid_cell *);
struct screen_write_citem {
u_int x;
@@ -1742,7 +1742,6 @@ screen_write_collect_end(struct screen_write_ctx *ctx)
if (ci->used == 0)
return;
- ctx->flags &= ~SCREEN_WRITE_COMBINE;
before = screen_write_collect_trim(ctx, s->cy, s->cx, ci->used,
&wrapped);
@@ -1841,65 +1840,22 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
{
struct screen *s = ctx->s;
struct grid *gd = s->grid;
- struct grid_cell copy;
- const struct utf8_data *ud = &gc->data, *previous = NULL, *combine;
+ const struct utf8_data *ud = &gc->data;
struct grid_line *gl;
struct grid_cell_entry *gce;
struct grid_cell tmp_gc, now_gc;
struct tty_ctx ttyctx;
u_int sx = screen_size_x(s), sy = screen_size_y(s);
- u_int width = ud->width, xx, last, cx, cy;
+ u_int width = ud->width, xx, not_wrap;
int selected, skip = 1;
/* Ignore padding cells. */
if (gc->flags & GRID_FLAG_PADDING)
return;
- /* Check if this cell needs to be combined with the previous cell. */
- if (ctx->flags & SCREEN_WRITE_COMBINE)
- previous = &ctx->previous;
- switch (utf8_try_combined(ud, previous, &combine, &width)) {
- case UTF8_DISCARD_NOW:
- log_debug("%s: UTF8_DISCARD_NOW (width %u)", __func__, width);
- ctx->flags &= ~SCREEN_WRITE_COMBINE;
+ /* Get the previous cell to check for combining. */
+ if (screen_write_combine(ctx, gc) != 0)
return;
- case UTF8_WRITE_NOW:
- log_debug("%s: UTF8_WRITE_NOW (width %u)", __func__, width);
- ctx->flags &= ~SCREEN_WRITE_COMBINE;
- break;
- case UTF8_COMBINE_NOW:
- log_debug("%s: UTF8_COMBINE_NOW (width %u)", __func__, width);
- screen_write_collect_flush(ctx, 0, __func__);
- gc = screen_write_combine(ctx, combine, &xx, &cx);
- if (gc != NULL) {
- cx = s->cx; cy = s->cy;
- screen_write_set_cursor(ctx, xx, s->cy);
- screen_write_initctx(ctx, &ttyctx, 0);
- ttyctx.cell = gc;
- tty_write(tty_cmd_cell, &ttyctx);
- s->cx = cx; s->cy = cy;
- }
- ctx->flags &= ~SCREEN_WRITE_COMBINE;
- return;
- case UTF8_WRITE_MAYBE_COMBINE:
- log_debug("%s: UTF8_WRITE_MAYBE_COMBINE (width %u)", __func__,
- width);
- utf8_copy(&ctx->previous, ud);
- ctx->flags |= SCREEN_WRITE_COMBINE;
- break;
- case UTF8_DISCARD_MAYBE_COMBINE:
- log_debug("%s: UTF8_DISCARD_MAYBE_COMBINE (width %u)", __func__,
- width);
- utf8_copy(&ctx->previous, ud);
- ctx->flags |= SCREEN_WRITE_COMBINE;
- return;
- }
- if (width != ud->width) {
- memcpy(&copy, gc, sizeof copy);
- copy.data.width = width;
- gc = &copy;
- }
- ud = NULL;
/* Flush any existing scrolling. */
screen_write_collect_flush(ctx, 1, __func__);
@@ -1991,11 +1947,11 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
* Move the cursor. If not wrapping, stick at the last character and
* replace it.
*/
- last = !(s->mode & MODE_WRAP);
- if (s->cx <= sx - last - width)
+ not_wrap = !(s->mode & MODE_WRAP);
+ if (s->cx <= sx - not_wrap - width)
screen_write_set_cursor(ctx, s->cx + width, -1);
else
- screen_write_set_cursor(ctx, sx - last, -1);
+ screen_write_set_cursor(ctx, sx - not_wrap, -1);
/* Create space for character in insert mode. */
if (s->mode & MODE_INSERT) {
@@ -2015,65 +1971,98 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
}
}
-/* Combine a UTF-8 zero-width character onto the previous. */
-static const struct grid_cell *
-screen_write_combine(struct screen_write_ctx *ctx, const struct utf8_data *ud,
- u_int *xx, u_int *cx)
+/* Combine a UTF-8 zero-width character onto the previous if necessary. */
+static int
+screen_write_combine(struct screen_write_ctx *ctx, const struct grid_cell *gc)
{
struct screen *s = ctx->s;
struct grid *gd = s->grid;
- static struct grid_cell gc;
- u_int n, width;
+ const struct utf8_data *ud = &gc->data;
+ u_int n, cx = s->cx, cy = s->cy;
+ struct grid_cell last;
+ struct tty_ctx ttyctx;
+ int force_wide = 0, zero_width = 0;
- /* Can't combine if at 0. */
- if (s->cx == 0) {
- *xx = 0;
- return (NULL);
+ /*
+ * Is this character which makes no sense without being combined? If
+ * this is true then flag it here and discard the character (return 1)
+ * if we cannot combine it.
+ */
+ if (utf8_is_zwj(ud))
+ zero_width = 1;
+ else if (utf8_is_vs(ud))
+ zero_width = force_wide = 1;
+ else if (ud->width == 0)
+ zero_width = 1;
+
+ /* Cannot combine empty character or at left. */
+ if (ud->size < 2 || cx == 0)
+ return (zero_width);
+ log_debug("%s: character %.*s at %u,%u (width %u)", __func__,
+ (int)ud->size, ud->data, cx, cy, ud->width);
+
+ /* Find the cell to combine with. */
+ n = 1;
+ grid_view_get_cell(gd, cx - n, cy, &last);
+ if (cx != 1 && (last.flags & GRID_FLAG_PADDING)) {
+ n = 2;
+ grid_view_get_cell(gd, cx - n, cy, &last);
}
- *xx = s->cx;
-
- /* Empty data is out. */
- if (ud->size == 0)
- fatalx("UTF-8 data empty");
+ if (n != last.data.width || (last.flags & GRID_FLAG_PADDING))
+ return (zero_width);
- /* Retrieve the previous cell. */
- for (n = 1; n <= s->cx; n++) {
- grid_view_get_cell(gd, s->cx - n, s->cy, &gc);
- if (~gc.flags & GRID_FLAG_PADDING)
- break;
+ /*
+ * Check if we need to combine characters. This could be zero width
+ * (zet above), a modifier character (with an existing Unicode
+ * character) or a previous ZWJ.
+ */
+ if (!zero_width) {
+ if (utf8_is_modifier(ud)) {
+ if (last.data.size < 2)
+ return (0);
+ force_wide = 1;
+ } else if (!utf8_has_zwj(&last.data))
+ return (0);
}
- if (n > s->cx)
- return (NULL);
- /* Check there is enough space. */
- if (gc.data.size + ud->size > sizeof gc.data.data)
- return (NULL);
- (*xx) -= n;
+ /* Combining; flush any pending output. */
+ screen_write_collect_flush(ctx, 0, __func__);
- log_debug("%s: %.*s onto %.*s at %u,%u (width %u)", __func__,
- (int)ud->size, ud->data, (int)gc.data.size, gc.data.data, *xx,
- s->cy, gc.data.width);
+ log_debug("%s: %.*s -> %.*s at %u,%u (offset %u, width %u)", __func__,
+ (int)ud->size, ud->data, (int)last.data.size, last.data.data,
+ cx - n, cy, n, last.data.width);
/* Append the data. */
- memcpy(gc.data.data + gc.data.size, ud->data, ud->size);
- gc.data.size += ud->size;
- width = gc.data.width;
-
- /* If this is U+FE0F VARIATION SELECTOR-16, force the width to 2. */
- if (gc.data.width == 1 &&
- ud->size == 3 &&
- memcmp(ud->data, "\357\270\217", 3) == 0) {
- grid_view_set_padding(gd, (*xx) + 1, s->cy);
- gc.data.width = 2;
- width += 2;
- }
+ memcpy(last.data.data + last.data.size, ud->data, ud->size);
+ last.data.size += ud->size;
+
+ /* Force the width to 2 for modifiers and variation selector. */
+ if (last.data.width == 1 && force_wide) {
+ last.data.width = 2;
+ n = 2;
+ cx++;
+ } else
+ force_wide = 0;
/* Set the new cell. */
- grid_view_set_cell(gd, *xx, s->cy, &gc);
+ grid_view_set_cell(gd, cx - n, cy, &last);
+ if (force_wide)
+ grid_view_set_padding(gd, cx, cy);
- *cx = (*xx) + width;
- log_debug("%s: character at %u; cursor at %u", __func__, *xx, *cx);
- return (&gc);
+ /*
+ * Redraw the combined cell. If forcing the cell to width 2, reset the
+ * cached cursor position in the tty, since we don't really know
+ * whether the terminal thought the character was width 1 or width 2
+ * and what it is going to do now.
+ */
+ screen_write_set_cursor(ctx, cx - n, cy);
+ screen_write_initctx(ctx, &ttyctx, 0);
+ ttyctx.cell = &last;
+ ttyctx.num = force_wide; /* reset cached cursor position */
+ tty_write(tty_cmd_cell, &ttyctx);
+ screen_write_set_cursor(ctx, cx, cy);
+
+ return (1);
}
/*
diff --git a/server.c b/server.c
index 3709945d..f1df1aa4 100644
--- a/server.c
+++ b/server.c
@@ -205,7 +205,6 @@ server_start(struct tmuxproc *client, int flags, struct event_base *base,
fatal("pledge failed");
input_key_build();
- utf8_build_combined();
RB_INIT(&windows);
RB_INIT(&all_window_panes);
TAILQ_INIT(&clients);
diff --git a/tmux.h b/tmux.h
index e12903db..9dd97adc 100644
--- a/tmux.h
+++ b/tmux.h
@@ -30,6 +30,7 @@
#include <stdint.h>
#include <stdio.h>
#include <termios.h>
+#include <wchar.h>
#include "tmux-protocol.h"
#include "xmalloc.h"
@@ -619,15 +620,6 @@ enum utf8_state {
UTF8_ERROR
};
-/* UTF-8 combine state. */
-enum utf8_combine_state {
- UTF8_DISCARD_NOW, /* discard immediately */
- UTF8_WRITE_NOW, /* do not combine, write immediately */
- UTF8_COMBINE_NOW, /* combine immediately */
- UTF8_WRITE_MAYBE_COMBINE, /* write but try to combine the next */
- UTF8_DISCARD_MAYBE_COMBINE /* discard but try to combine the next */
-};
-
/* Colour flags. */
#define COLOUR_FLAG_256 0x01000000
#define COLOUR_FLAG_RGB 0x02000000
@@ -900,7 +892,6 @@ struct screen_write_ctx {
int flags;
#define SCREEN_WRITE_SYNC 0x1
-#define SCREEN_WRITE_COMBINE 0x2
screen_write_init_ctx_cb init_ctx_cb;
void *arg;
@@ -908,7 +899,6 @@ struct screen_write_ctx {
struct screen_write_citem *item;
u_int scrolled;
u_int bg;
- struct utf8_data previous;
};
/* Box border lines option. */
@@ -3277,6 +3267,8 @@ u_int session_group_attached_count(struct session_group *);
void session_renumber_windows(struct session *);
/* utf8.c */
+enum utf8_state utf8_towc (const struct utf8_data *, wchar_t *);
+int utf8_in_table(wchar_t, const wchar_t *, u_int);
utf8_char utf8_build_one(u_char);
enum utf8_state utf8_from_data(const struct utf8_data *, utf8_char *);
void utf8_to_data(utf8_char, struct utf8_data *);
@@ -3299,10 +3291,10 @@ char *utf8_rpadcstr(const char *, u_int);
int utf8_cstrhas(const char *, const struct utf8_data *);
/* utf8-combined.c */
-void utf8_build_combined(void);
-int utf8_try_combined(const struct utf8_data *,
- const struct utf8_data *, const struct utf8_data **,
- u_int *width);
+int utf8_has_zwj(const struct utf8_data *);
+int utf8_is_zwj(const struct utf8_data *);
+int utf8_is_vs(const struct utf8_data *);
+int utf8_is_modifier(const struct utf8_data *);
/* procname.c */
char *get_proc_name(int, char *);
diff --git a/tty.c b/tty.c
index 8c576306..8a2dee81 100644
--- a/tty.c
+++ b/tty.c
@@ -2091,6 +2091,9 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
tty_cell(tty, ctx->cell, &ctx->defaults, ctx->palette,
ctx->s->hyperlinks);
+
+ if (ctx->num == 1)
+ tty_invalidate(tty);
}
void
diff --git a/utf8-combined.c b/utf8-combined.c
index 49f7a648..05958d47 100644
--- a/utf8-combined.c
+++ b/utf8-combined.c
@@ -24,1112 +24,77 @@
#include "tmux.h"
-static const struct {
- wchar_t first;
- wchar_t second;
-} utf8_combined_table[] = {
- { 0x1F1E6, 0x1F1E8 }, /* flag: Ascension Island */
- { 0x1F1E6, 0x1F1E9 }, /* flag: Andorra */
- { 0x1F1E6, 0x1F1EA }, /* flag: United Arab Emirates */
- { 0x1F1E6, 0x1F1EB }, /* flag: Afghanistan */
- { 0x1F1E6, 0x1F1EC }, /* flag: Antigua & Barbuda */
- { 0x1F1E6, 0x1F1EE }, /* flag: Anguilla */
- { 0x1F1E6, 0x1F1F1 }, /* flag: Albania */
- { 0x1F1E6, 0x1F1F2 }, /* flag: Armenia */
- { 0x1F1E6, 0x1F1F4 }, /* flag: Angola */
- { 0x1F1E6, 0x1F1F6 }, /* flag: Antarctica */
- { 0x1F1E6, 0x1F1F7 }, /* flag: Argentina */
- { 0x1F1E6, 0x1F1F8 }, /* flag: American Samoa */
- { 0x1F1E6, 0x1F1F9 }, /* flag: Austria */
- { 0x1F1E6, 0x1F1FA }, /* flag: Australia */
- { 0x1F1E6, 0x1F1FC }, /* flag: Aruba */
- { 0x1F1E6, 0x1F1FD }, /* flag: Aland Islands */
- { 0x1F1E6, 0x1F1FF }, /* flag: Azerbaijan */
- { 0x1F1E7, 0x1F1E6 }, /* flag: Bosnia & Herzegovina */
- { 0x1F1E7, 0x1F1E7 }, /* flag: Barbados */
- { 0x1F1E7, 0x1F1E9 }, /* flag: Bangladesh */
- { 0x1F1E7, 0x1F1EA }, /* flag: Belgium */
- { 0x1F1E7, 0x1F1EB }, /* flag: Burkina Faso */
- { 0x1F1E7, 0x1F1EC }, /* flag: Bulgaria */
- { 0x1F1E7, 0x1F1ED }, /* flag: Bahrain */
- { 0x1F1E7, 0x1F1EE }, /* flag: Burundi */
- { 0x1F1E7, 0x1F1EF }, /* flag: Benin */
- { 0x1F1E7, 0x1F1F1 }, /* flag: St. Barthelemy */
- { 0x1F1E7, 0x1F1F2 }, /* flag: Bermuda */
- { 0x1F1E7, 0x1F1F3 }, /* flag: Brunei */
- { 0x1F1E7, 0x1F1F4 }, /* flag: Bolivia */
- { 0x1F1E7, 0x1F1F6 }, /* flag: Caribbean Netherlands */
- { 0x1F1E7, 0x1F1F7 }, /* flag: Brazil */
- { 0x1F1E7, 0x1F1F8 }, /* flag: Bahamas */
- { 0x1F1E7, 0x1F1F9 }, /* flag: Bhutan */
- { 0x1F1E7, 0x1F1FB }, /* flag: Bouvet Island */
- { 0x1F1E7, 0x1F1FC }, /* flag: Botswana */
- { 0x1F1E7, 0x1F1FE }, /* flag: Belarus */
- { 0x1F1E7, 0x1F1FF }, /* flag: Belize */
- { 0x1F1E8, 0x1F1E6 }, /* flag: Canada */
- { 0x1F1E8, 0x1F1E8 }, /* flag: Cocos (Keeling) Islands */
- { 0x1F1E8, 0x1F1E9 }, /* flag: Congo - Kinshasa */
- { 0x1F1E8, 0x1F1EB }, /* flag: Central African Republic */
- { 0x1F1E8, 0x1F1EC }, /* flag: Congo - Brazzaville */
- { 0x1F1E8, 0x1F1ED }, /* flag: Switzerland */
- { 0x1F1E8, 0x1F1EE }, /* flag: Cote d'Ivoire */
- { 0x1F1E8, 0x1F1F0 }, /* flag: Cook Islands */
- { 0x1F1E8, 0x1F1F1 }, /* flag: Chile */
- { 0x1F1E8, 0x1F1F2 }, /* flag: Cameroon */
- { 0x1F1E8, 0x1F1F3 }, /* flag: China */
- { 0x1F1E8, 0x1F1F4 }, /* flag: Colombia */
- { 0x1F1E8, 0x1F1F5 }, /* flag: Clipperton Island */
- { 0x1F1E8, 0x1F1F7 }, /* flag: Costa Rica */
- { 0x1F1E8, 0x1F1FA }, /* flag: Cuba */
- { 0x1F1E8, 0x1F1FB }, /* flag: Cape Verde */
- { 0x1F1E8, 0x1F1FC }, /* flag: Curacao */
- { 0x1F1E8, 0x1F1FD }, /* flag: Christmas Island */
- { 0x1F1E8, 0x1F1FE }, /* flag: Cyprus */
- { 0x1F1E8, 0x1F1FF }, /* flag: Czechia */
- { 0x1F1E9, 0x1F1EA }, /* flag: Germany */
- { 0x1F1E9, 0x1F1EC }, /* flag: Diego Garcia */
- { 0x1F1E9, 0x1F1EF }, /* flag: Djibouti */
- { 0x1F1E9, 0x1F1F0 }, /* flag: Denmark */
- { 0x1F1E9, 0x1F1F2 }, /* flag: Dominica */
- { 0x1F1E9, 0x1F1F4 }, /* flag: Dominican Republic */
- { 0x1F1E9, 0x1F1FF }, /* flag: Algeria */
- { 0x1F1EA, 0x1F1E6 }, /* flag: Ceuta & Melilla */
- { 0x1F1EA, 0x1F1E8 }, /* flag: Ecuador */
- { 0x1F1EA, 0x1F1EA }, /* flag: Estonia */
- { 0x1F1EA, 0x1F1EC }, /* flag: Egypt */
- { 0x1F1EA, 0x1F1ED }, /* flag: Western Sahara */
- { 0x1F1EA, 0x1F1F7 }, /* flag: Eritrea */
- { 0x1F1EA, 0x1F1F8 }, /* flag: Spain */
- { 0x1F1EA, 0x1F1F9 }, /* flag: Ethiopia */
- { 0x1F1EA, 0x1F1FA }, /* flag: European Union */
- { 0x1F1EB, 0x1F1EE }, /* flag: Finland */
- { 0x1F1EB, 0x1F1EF }, /* flag: Fiji */
- { 0x1F1EB, 0x1F1F0 }, /* flag: Falkland Islands */
- { 0x1F1EB, 0x1F1F2 }, /* flag: Micronesia */
- { 0x1F1EB, 0x1F1F4 }, /* flag: Faroe Islands */
- { 0x1F1EB, 0x1F1F7 }, /* flag: France */
- { 0x1F1EC, 0x1F1E6 }, /* flag: Gabon */
- { 0x1F1EC, 0x1F1E7 }, /* flag: United Kingdom */
- { 0x1F1EC, 0x1F1E9 }, /* flag: Grenada */
- { 0x1F1EC, 0x1F1EA }, /* flag: Georgia */
- { 0x1F1EC, 0x1F1EB }, /* flag: French Guiana */
- { 0x1F1EC, 0x1F1EC }, /* flag: Guernsey */
- { 0x1F1EC, 0x1F1ED }, /* flag: Ghana */
- { 0x1F1EC, 0x1F1EE }, /* flag: Gibraltar */
- { 0x1F1EC, 0x1F1F1 }, /* flag: Greenland */
- { 0x1F1EC, 0x1F1F2 }, /* flag: Gambia */
- { 0x1F1EC, 0x1F1F3 }, /* flag: Guinea */
- { 0x1F1EC, 0x1F1F5 }, /* flag: Guadeloupe */
- { 0x1F1EC, 0x1F1F6 }, /* flag: Equatorial Guinea */
- { 0x1F1EC, 0x1F1F7 }, /* flag: Greece */
- { 0x1F1EC, 0x1F1F8 }, /* flag: South Georgia & South Sandwich Islands */
- { 0x1F1EC, 0x1F1F9 }, /* flag: Guatemala */
- { 0x1F1EC, 0x1F1FA }, /* flag: Guam */
- { 0x1F1EC, 0x1F1FC }, /* flag: Guinea-Bissau */
- { 0x1F1EC, 0x1F1FE }, /* flag: Guyana */
- { 0x1F1ED, 0x1F1F0 }, /* flag: Hong Kong SAR China */
- { 0x1F1ED, 0x1F1F2 }, /* flag: Heard & McDonald Islands */
- { 0x1F1ED, 0x1F1F3 }, /* flag: Honduras */
- { 0x1F1ED, 0x1F1F7 }, /* flag: Croatia */
- { 0x1F1ED, 0x1F1F9 }, /* flag: Haiti */
- { 0x1F1ED, 0x1F1FA }, /* flag: Hungary */
- { 0x1F1EE, 0x1F1E8 }, /* flag: Canary Islands */
- { 0x1F1EE, 0x1F1E9 }, /* flag: Indonesia */
- { 0x1F1EE, 0x1F1EA }, /* flag: Ireland */
- { 0x1F1EE, 0x1F1F1 }, /* flag: Israel */
- { 0x1F1EE, 0x1F1F2 }, /* flag: Isle of Man */
- { 0x1F1EE, 0x1F1F3 }, /* flag: India */
- { 0x1F1EE, 0x1F1F4 }, /* flag: British Indian Ocean Territory */
- { 0x1F1EE, 0x1F1F6 }, /* flag: Iraq */
- { 0x1F1EE, 0x1F1F7 }, /* flag: Iran */
- { 0x1F1EE, 0x1F1F8 }, /* flag: Iceland */
- { 0x1F1EE, 0x1F1F9 }, /* flag: Italy */
- { 0x1F1EF, 0x1F1EA }, /* flag: Jersey */
- { 0x1F1EF, 0x1F1F2 }, /* flag: Jamaica */
- { 0x1F1EF, 0x1F1F4 }, /* flag: Jordan */
- { 0x1F1EF, 0x1F1F5 }, /* flag: Japan */
- { 0x1F1F0, 0x1F1EA }, /* flag: Kenya */
- { 0x1F1F0, 0x1F1EC }, /* flag: Kyrgyzstan */
- { 0x1F1F0, 0x1F1ED }, /* flag: Cambodia */
- { 0x1F1F0, 0x1F1EE }, /* flag: Kiribati */
- { 0x1F1F0, 0x1F1F2 }, /* flag: Comoros */
- { 0x1F1F0, 0x1F1F3 }, /* flag: St. Kitts & Nevis */
- { 0x1F1F0, 0x1F1F5 }, /* flag: North Korea */
- { 0x1F1F0, 0x1F1F7 }, /* flag: South Korea */
- { 0x1F1F0, 0x1F1FC }, /* flag: Kuwait */
- { 0x1F1F0, 0x1F1FE }, /* flag: Cayman Islands */
- { 0x1F1F0, 0x1F1FF }, /* flag: Kazakhstan */
- { 0x1F1F1, 0x1F1E6 }, /* flag: Laos */
- { 0x1F1F1, 0x1F1E7 }, /* flag: Lebanon */
- { 0x1F1F1, 0x1F1E8 }, /* flag: St. Lucia */
- { 0x1F1F1, 0x1F1EE }, /* flag: Liechtenstein */
- { 0x1F1F1, 0x1F1F0 }, /* flag: Sri Lanka */
- { 0x1F1F1, 0x1F1F7 }, /* flag: Liberia */
- { 0x1F1F1, 0x1F1F8 }, /* flag: Lesotho */
- { 0x1F1F1, 0x1F1F9 }, /* flag: Lithuania */
- { 0x1F1F1, 0x1F1FA }, /* flag: Luxembourg */
- { 0x1F1F1, 0x1F1FB }, /* flag: Latvia */
- { 0x1F1F1, 0x1F1FE }, /* flag: Libya */
- { 0x1F1F2, 0x1F1E6 }, /* flag: Morocco */
- { 0x1F1F2, 0x1F1E8 }, /* flag: Monaco */
- { 0x1F1F2, 0x1F1E9 }, /* flag: Moldova */
- { 0x1F1F2, 0x1F1EA }, /* flag: Montenegro */
- { 0x1F1F2, 0x1F1EB }, /* flag: St. Martin */
- { 0x1F1F2, 0x1F1EC }, /* flag: Madagascar */
- { 0x1F1F2, 0x1F1ED }, /* flag: Marshall Islands */
- { 0x1F1F2, 0x1F1F0 }, /* flag: North Macedonia */
- { 0x1F1F2, 0x1F1F1 }, /* flag: Mali */
- { 0x1F1F2, 0x1F1F2 }, /* flag: Myanmar (Burma */
- { 0x1F1F2, 0x1F1F3 }, /* flag: Mongolia */
- { 0x1F1F2, 0x1F1F4 }, /* flag: Macao SAR China */
- { 0x1F1F2, 0x1F1F5 }, /* flag: Northern Mariana Islands */
- { 0x1F1F2, 0x1F1F6 }, /* flag: Martinique */
- { 0x1F1F2, 0x1F1F7 }, /* flag: Mauritania */
- { 0x1F1F2, 0x1F1F8 }, /* flag: Montserrat */
- { 0x1F1F2, 0x1F1F9 }, /* flag: Malta */
- { 0x1F1F2, 0x1F1FA }, /* flag: Mauritius */
- { 0x1F1F2, 0x1F1FB }, /* flag: Maldives */
- { 0x1F1F2, 0x1F1FC }, /* flag: Malawi */
- { 0x1F1F2, 0x1F1FD }, /* flag: Mexico */
- { 0x1F1F2, 0x1F1FE }, /* flag: Malaysia */
- { 0x1F1F2, 0x1F1FF }, /* flag: Mozambique */
- { 0x1F1F3, 0x1F1E6 }, /* flag: Namibia */
- { 0x1F1F3, 0x1F1E8 }, /* flag: New Caledonia */
- { 0x1F1F3, 0x1F1EA }, /* flag: Niger */
- { 0x1F1F3, 0x1F1EB }, /* flag: Norfolk Island */
- { 0x1F1F3, 0x1F1EC }, /* flag: Nigeria */
- { 0x1F1F3, 0x1F1EE }, /* flag: Nicaragua */
- { 0x1F1F3, 0x1F1F1 }, /* flag: Netherlands */
- { 0x1F1F3, 0x1F1F4 }, /* flag: Norway */
- { 0x1F1F3, 0x1F1F5 }, /* flag: Nepal */
- { 0x1F1F3, 0x1F1F7 }, /* flag: Nauru */
- { 0x1F1F3, 0x1F1FA }, /* flag: Niue */
- { 0x1F1F3, 0x1F1FF }, /* flag: New Zealand */
- { 0x1F1F4, 0x1F1F2 }, /* flag: Oman */
- { 0x1F1F5, 0x1F1E6 }, /* flag: Panama */
- { 0x1F1F5, 0x1F1EA }, /* flag: Peru */
- { 0x1F1F5, 0x1F1EB }, /* flag: French Polynesia */
- { 0x1F1F5, 0x1F1EC }, /* flag: Papua New Guinea */
- { 0x1F1F5, 0x1F1ED }, /* flag: Philippines */
- { 0x1F1F5, 0x1F1F0 }, /* flag: Pakistan */
- { 0x1F1F5, 0x1F1F1 }, /* flag: Poland */
- { 0x1F1F5, 0x1F1F2 }, /* flag: St. Pierre & Miquelon */
- { 0x1F1F5, 0x1F1F3 }, /* flag: Pitcairn Islands */
- { 0x1F1F5, 0x1F1F7 }, /* flag: Puerto Rico */
- { 0x1F1F5, 0x1F1F8 }, /* flag: Palestinian Territories */
- { 0x1F1F5, 0x1F1F9 }, /* flag: Portugal */
- { 0x1F1F5, 0x1F1FC }, /* flag: Palau */
- { 0x1F1F5, 0x1F1FE }, /* flag: Paraguay */
- { 0x1F1F6, 0x1F1E6 }, /* flag: Qatar */
- { 0x1F1F7, 0x1F1EA }, /* flag: Reunion */
- { 0x1F1F7, 0x1F1F4 }, /* flag: Romania */
- { 0x1F1F7, 0x1F1F8 }, /* flag: Serbia */
- { 0x1F1F7, 0x1F1FA }, /* flag: Russia */
- { 0x1F1F7, 0x1F1FC }, /* flag: Rwanda */
- { 0x1F1F8, 0x1F1E6 }, /* flag: Saudi Arabia */
- { 0x1F1F8, 0x1F1E7 }, /* flag: Solomon Islands */
- { 0x1F1F8, 0x1F1E8 }, /* flag: Seychelles */
- { 0x1F1F8, 0x1F1E9 }, /* flag: Sudan */
- { 0x1F1F8, 0x1F1EA }, /* flag: Sweden */
- { 0x1F1F8, 0x1F1EC }, /* flag: Singapore */
- { 0x1F1F8, 0x1F1ED }, /* flag: St. Helena */
- { 0x1F1F8, 0x1F1EE }, /* flag: Slovenia */
- { 0x1F1F8, 0x1F1EF }, /* flag: Svalbard & Jan Mayen */
- { 0x1F1F8, 0x1F1F0 }, /* flag: Slovakia */
- { 0x1F1F8, 0x1F1F1 }, /* flag: Sierra Leone */
- { 0x1F1F8, 0x1F1F2 }, /* flag: San Marino */
- { 0x1F1F8, 0x1F1F3 }, /* flag: Senegal */
- { 0x1F1F8, 0x1F1F4 }, /* flag: Somalia */
- { 0x1F1F8, 0x1F1F7 }, /* flag: Suriname */
- { 0x1F1F8, 0x1F1F8 }, /* flag: South Sudan */
- { 0x1F1F8, 0x1F1F9 }, /* flag: Sao Tome & Principe */
- { 0x1F1F8, 0x1F1FB }, /* flag: El Salvador */
- { 0x1F1F8, 0x1F1FD }, /* flag: Sint Maarten */
- { 0x1F1F8, 0x1F1FE }, /* flag: Syria */
- { 0x1F1F8, 0x1F1FF }, /* flag: Eswatini */
- { 0x1F1F9, 0x1F1E6 }, /* flag: Tristan da Cunha */
- { 0x1F1F9, 0x1F1E8 }, /* flag: Turks & Caicos Islands */
- { 0x1F1F9, 0x1F1E9 }, /* flag: Chad */
- { 0x1F1F9, 0x1F1EB }, /* flag: French Southern Territories */
- { 0x1F1F9, 0x1F1EC }, /* flag: Togo */
- { 0x1F1F9, 0x1F1ED }, /* flag: Thailand */
- { 0x1F1F9, 0x1F1EF }, /* flag: Tajikistan */
- { 0x1F1F9, 0x1F1F0 }, /* flag: Tokelau */
- { 0x1F1F9, 0x1F1F1 }, /* flag: Timor-Leste */
- { 0x1F1F9, 0x1F1F2 }, /* flag: Turkmenistan */
- { 0x1F1F9, 0x1F1F3 }, /* flag: Tunisia */
- { 0x1F1F9, 0x1F1F4 }, /* flag: Tonga */
- { 0x1F1F9, 0x1F1F7 }, /* flag: Turkey */
- { 0x1F1F9, 0x1F1F9 }, /* flag: Trinidad & Tobago */
- { 0x1F1F9, 0x1F1FB }, /* flag: Tuvalu */
- { 0x1F1F9, 0x1F1FC }, /* flag: Taiwan */
- { 0x1F1F9, 0x1F1FF }, /* flag: Tanzania */
- { 0x1F1FA, 0x1F1E6 }, /* flag: Ukraine */
- { 0x1F1FA, 0x1F1EC }, /* flag: Uganda */
- { 0x1F1FA, 0x1F1F2 }, /* flag: U.S. Outlying Islands */
- { 0x1F1FA, 0x1F1F3 }, /* flag: United Nations */
- { 0x1F1FA, 0x1F1F8 }, /* flag: United States */
- { 0x1F1FA, 0x1F1FE }, /* flag: Uruguay */
- { 0x1F1FA, 0x1F1FF }, /* flag: Uzbekistan */
- { 0x1F1FB, 0x1F1E6 }, /* flag: Vatican City */
- { 0x1F1FB, 0x1F1E8 }, /* flag: St. Vincent & Grenadines */
- { 0x1F1FB, 0x1F1EA }, /* flag: Venezuela */
- { 0x1F1FB, 0x1F1EC }, /* flag: British Virgin Islands */
- { 0x1F1FB, 0x1F1EE }, /* flag: U.S. Virgin Islands */
- { 0x1F1FB, 0x1F1F3 }, /* flag: Vietnam */
- { 0x1F1FB, 0x1F1FA }, /* flag: Vanuatu */
- { 0x1F1FC, 0x1F1EB }, /* flag: Wallis & Futuna */
- { 0x1F1FC, 0x1F1F8 }, /* flag: Samoa */
- { 0x1F1FD, 0x1F1F0 }, /* flag: Kosovo */
- { 0x1F1FE, 0x1F1EA }, /* flag: Yemen */
- { 0x1F1FE, 0x1F1F9 }, /* flag: Mayotte */
- { 0x1F1FF, 0x1F1E6 }, /* flag: South Africa */
- { 0x1F1FF, 0x1F1F2 }, /* flag: Zambia */
- { 0x1F1FF, 0x1F1FC }, /* flag: Zimbabwe */
- { 0x0261D, 0x1F3FB }, /* index pointing up: light skin tone */
- { 0x0261D, 0x1F3FC }, /* index pointing up: medium-light skin tone */
- { 0x0261D, 0x1F3FD }, /* index pointing up: medium skin tone */
- { 0x0261D, 0x1F3FE }, /* index pointing up: medium-dark skin tone */
- { 0x0261D, 0x1F3FF }, /* index pointing up: dark skin tone */
- { 0x026F9, 0x1F3FB }, /* person bouncing ball: light skin tone */
- { 0x026F9, 0x1F3FC }, /* person bouncing ball: medium-light skin tone */
- { 0x026F9, 0x1F3FD }, /* person bouncing ball: medium skin tone */
- { 0x026F9, 0x1F3FE }, /* person bouncing ball: medium-dark skin tone */
- { 0x026F9, 0x1F3FF }, /* person bouncing ball: dark skin tone */
- { 0x0270A, 0x1F3FB }, /* raised fist: light skin tone */
- { 0x0270A, 0x1F3FC }, /* raised fist: medium-light skin tone */
- { 0x0270A, 0x1F3FD }, /* raised fist: medium skin tone */
- { 0x0270A, 0x1F3FE }, /* raised fist: medium-dark skin tone */
- { 0x0270A, 0x1F3FF }, /* raised fist: dark skin tone */
- { 0x0270B, 0x1F3FB }, /* raised hand: light skin tone */
- { 0x0270B, 0x1F3FC }, /* raised hand: medium-light skin tone */
- { 0x0270B, 0x1F3FD }, /* raised hand: medium skin tone */
- { 0x0270B, 0x1F3FE }, /* raised hand: medium-dark skin tone */
- { 0x0270B, 0x1F3FF }, /* raised hand: dark skin tone */
- { 0x0270C, 0x1F3FB }, /* victory hand: light skin tone */
- { 0x0270C, 0x1F3FC }, /* victory hand: medium-light skin tone */
- { 0x0270C, 0x1F3FD }, /* victory hand: medium skin tone */
- { 0x0270C, 0x1F3FE }, /* victory hand: medium-dark skin tone */
- { 0x0270C, 0x1F3FF }, /* victory hand: dark skin tone */
- { 0x0270D, 0x1F3FB }, /* writing hand: light skin tone */
- { 0x0270D, 0x1F3FC }, /* writing hand: medium-light skin tone */
- { 0x0270D, 0x1F3FD }, /* writing hand: medium skin tone */
- { 0x0270D, 0x1F3FE }, /* writing hand: medium-dark skin tone */
- { 0x0270D, 0x1F3FF }, /* writing hand: dark skin tone */
- { 0x1F385, 0x1F3FB }, /* Santa Claus: light skin tone */
- { 0x1F385, 0x1F3FC }, /* Santa Claus: medium-light skin tone */
- { 0x1F385, 0x1F3FD }, /* Santa Claus: medium skin tone */
- { 0x1F385, 0x1F3FE }, /* Santa Claus: medium-dark skin tone */
- { 0x1F385, 0x1F3FF }, /* Santa Claus: dark skin tone */
- { 0x1F3C2, 0x1F3FB }, /* snowboarder: light skin tone */
- { 0x1F3C2, 0x1F3FC }, /* snowboarder: medium-light skin tone */
- { 0x1F3C2, 0x1F3FD }, /* snowboarder: medium skin tone */
- { 0x1F3C2, 0x1F3FE }, /* snowboarder: medium-dark skin tone */
- { 0x1F3C2, 0x1F3FF }, /* snowboarder: dark skin tone */
- { 0x1F3C3, 0x1F3FB }, /* person running: light skin tone */
- { 0x1F3C3, 0x1F3FC }, /* person running: medium-light skin tone */
- { 0x1F3C3, 0x1F3FD }, /* person running: medium skin tone */
- { 0x1F3C3, 0x1F3FE }, /* person running: medium-dark skin tone */
- { 0x1F3C3, 0x1F3FF }, /* person running: dark skin tone */
- { 0x1F3C4, 0x1F3FB }, /* person surfing: light skin tone */
- { 0x1F3C4, 0x1F3FC }, /* person surfing: medium-light skin tone */
- { 0x1F3C4, 0x1F3FD }, /* person surfing: medium skin tone */
- { 0x1F3C4, 0x1F3FE }, /* person surfing: medium-dark skin tone */
- { 0x1F3C4, 0x1F3FF }, /* person surfing: dark skin tone */
- { 0x1F3C7, 0x1F3FB }, /* horse racing: light skin tone */
- { 0x1F3C7, 0x1F3FC }, /* horse racing: medium-light skin tone */
- { 0x1F3C7, 0x1F3FD }, /* horse racing: medium skin tone */
- { 0x1F3C7, 0x1F3FE }, /* horse racing: medium-dark skin tone */
- { 0x1F3C7, 0x1F3FF }, /* horse racing: dark skin tone */
- { 0x1F3CA, 0x1F3FB }, /* person swimming: light skin tone */
- { 0x1F3CA, 0x1F3FC }, /* person swimming: medium-light skin tone */
- { 0x1F3CA, 0x1F3FD }, /* person swimming: medium skin tone */
- { 0x1F3CA, 0x1F3FE }, /* person swimming: medium-dark skin tone */
- { 0x1F3CA, 0x1F3FF }, /* person swimming: dark skin tone */
- { 0x1F3CB, 0x1F3FB }, /* person lifting weights: light skin tone */
- { 0x1F3CB, 0x1F3FC }, /* person lifting weights: medium-light skin tone */
- { 0x1F3CB, 0x1F3FD }, /* person lifting weights: medium skin tone */
- { 0x1F3CB, 0x1F3FE }, /* person lifting weights: medium-dark skin tone */
- { 0x1F3CB, 0x1F3FF }, /* person lifting weights: dark skin tone */
- { 0x1F3CC, 0x1F3FB }, /* person golfing: light skin tone */
- { 0x1F3CC, 0x1F3FC }, /* person golfing: medium-light skin tone */
- { 0x1F3CC, 0x1F3FD }, /* person golfing: medium skin tone */
- { 0x1F3CC, 0x1F3FE }, /* person golfing: medium-dark skin tone */
- { 0x1F3CC, 0x1F3FF }, /* person golfing: dark skin tone */
- { 0x1F442, 0x1F3FB }, /* ear: light skin tone */
- { 0x1F442, 0x1F3FC }, /* ear: medium-light skin tone */
- { 0x1F442, 0x1F3FD }, /* ear: medium skin tone */
- { 0x1F442, 0x1F3FE }, /* ear: medium-dark skin tone */
- { 0x1F442, 0x1F3FF }, /* ear: dark skin tone */
- { 0x1F443, 0x1F3FB }, /* nose: light skin tone */
- { 0x1F443, 0x1F3FC }, /* nose: medium-light skin tone */
- { 0x1F443, 0x1F3FD }, /* nose: medium skin tone */
- { 0x1F443, 0x1F3FE }, /* nose: medium-dark skin tone */
- { 0x1F443, 0x1F3FF }, /* nose: dark skin tone */
- { 0x1F446, 0x1F3FB }, /* backhand index pointing up: light skin tone */
- { 0x1F446, 0x1F3FC }, /* backhand index pointing up: medium-light skin tone */
- { 0x1F446, 0x1F3FD }, /* backhand index pointing up: medium skin tone */
- { 0x1F446, 0x1F3FE }, /* backhand index pointing up: medium-dark skin tone */
- { 0x1F446, 0x1F3FF }, /* backhand index pointing up: dark skin tone */
- { 0x1F447, 0x1F3FB }, /* backhand index pointing down: light skin tone */
- { 0x1F447, 0x1F3FC }, /* backhand index pointing down: medium-light skin tone */
- { 0x1F447, 0x1F3FD }, /* backhand index pointing down: medium skin tone */
- { 0x1F447, 0x1F3FE }, /* backhand index pointing down: medium-dark skin tone */
- { 0x1F447, 0x1F3FF }, /* backhand index pointing down: dark skin tone */
- { 0x1F448, 0x1F3FB }, /* backhand index pointing left: light skin tone */
- { 0x1F448, 0x1F3FC }, /* backhand index pointing left: medium-light skin tone */
- { 0x1F448, 0x1F3FD }, /* backhand index pointing left: medium skin tone */
- { 0x1F448, 0x1F3FE }, /* backhand index pointing left: medium-dark skin tone */
- { 0x1F448, 0x1F3FF }, /* backhand index pointing left: dark skin tone */
- { 0x1F449, 0x1F3FB }, /* backhand index pointing right: light skin tone */
- { 0x1F449, 0x1F3FC }, /* backhand index pointing right: medium-light skin tone */
- { 0x1F449, 0x1F3FD }, /* backhand index pointing right: medium skin tone */
- { 0x1F449, 0x1F3FE }, /* backhand index pointing right: medium-dark skin tone */
- { 0x1F449, 0x1F3FF }, /* backhand index pointing right: dark skin tone */
- { 0x1F44A, 0x1F3FB }, /* oncoming fist: light skin tone */
- { 0x1F44A, 0x1F3FC }, /* oncoming fist: medium-light skin tone */
- { 0x1F44A, 0x1F3FD }, /* oncoming fist: medium skin tone */
- { 0x1F44A, 0x1F3FE }, /* oncoming fist: medium-dark skin tone */
- { 0x1F44A, 0x1F3FF }, /* oncoming fist: dark skin tone */
- { 0x1F44B, 0x1F3FB }, /* waving hand: light skin tone */
- { 0x1F44B, 0x1F3FC }, /* waving hand: medium-light skin tone */
- { 0x1F44B, 0x1F3FD }, /* waving hand: medium skin tone */
- { 0x1F44B, 0x1F3FE }, /* waving hand: medium-dark skin tone */
- { 0x1F44B, 0x1F3FF }, /* waving hand: dark skin tone */
- { 0x1F44C, 0x1F3FB }, /* OK hand: light skin tone */
- { 0x1F44C, 0x1F3FC }, /* OK hand: medium-light skin tone */
- { 0x1F44C, 0x1F3FD }, /* OK hand: medium skin tone */
- { 0x1F44C, 0x1F3FE }, /* OK hand: medium-dark skin tone */
- { 0x1F44C, 0x1F3FF }, /* OK hand: dark skin tone */
- { 0x1F44D, 0x1F3FB }, /* thumbs up: light skin tone */
- { 0x1F44D, 0x1F3FC }, /* thumbs up: medium-light skin tone */
- { 0x1F44D, 0x1F3FD }, /* thumbs up: medium skin tone */
- { 0x1F44D, 0x1F3FE }, /* thumbs up: medium-dark skin tone */
- { 0x1F44D, 0x1F3FF }, /* thumbs up: dark skin tone */
- { 0x1F44E, 0x1F3FB }, /* thumbs down: light skin tone */
- { 0x1F44E, 0x1F3FC }, /* thumbs down: medium-light skin tone */
- { 0x1F44E, 0x1F3FD }, /* thumbs down: medium skin tone */
- { 0x1F44E, 0x1F3FE }, /* thumbs down: medium-dark skin tone */
- { 0x1F44E, 0x1F3FF }, /* thumbs down: dark skin tone */
- { 0x1F44F, 0x1F3FB }, /* clapping hands: light skin tone */
- { 0x1F44F, 0x1F3FC }, /* clapping hands: medium-light skin tone */
- { 0x1F44F, 0x1F3FD }, /* clapping hands: medium skin tone */
- { 0x1F44F, 0x1F3FE }, /* clapping hands: medium-dark skin tone */
- { 0x1F44F, 0x1F3FF }, /* clapping hands: dark skin tone */
- { 0x1F450, 0x1F3FB }, /* open hands: light skin tone */
- { 0x1F450, 0x1F3FC }, /* open hands: medium-light skin tone */
- { 0x1F450, 0x1F3FD }, /* open hands: medium skin tone */
- { 0x1F450, 0x1F3FE }, /* open hands: medium-dark skin tone */
- { 0x1F450, 0x1F3FF }, /* open hands: dark skin tone */
- { 0x1F466, 0x1F3FB }, /* boy: light skin tone */
- { 0x1F466, 0x1F3FC }, /* boy: medium-light skin tone */
- { 0x1F466, 0x1F3FD }, /* boy: medium skin tone */
- { 0x1F466, 0x1F3FE }, /* boy: medium-dark skin tone */
- { 0x1F466, 0x1F3FF }, /* boy: dark skin tone */
- { 0x1F467, 0x1F3FB }, /* girl: light skin tone */
- { 0x1F467, 0x1F3FC }, /* girl: medium-light skin tone */
- { 0x1F467, 0x1F3FD }, /* girl: medium skin tone */
- { 0x1F467, 0x1F3FE }, /* girl: medium-dark skin tone */
- { 0x1F467, 0x1F3FF }, /* girl: dark skin tone */
- { 0x1F468, 0x1F3FB }, /* man: light skin tone */
- { 0x1F468, 0x1F3FC }, /* man: medium-light skin tone */
- { 0x1F468, 0x1F3FD }, /* man: medium skin tone */
- { 0x1F468, 0x1F3FE }, /* man: medium-dark skin tone */
- { 0x1F468, 0x1F3FF }, /* man: dark skin tone */
- { 0x1F469, 0x1F3FB }, /* woman: light skin tone */
- { 0x1F469, 0x1F3FC }, /* woman: medium-light skin tone */
- { 0x1F469, 0x1F3FD }, /* woman: medium skin tone */
- { 0x1F469, 0x1F3FE }, /* woman: medium-dark skin tone */
- { 0x1F469, 0x1F3FF }, /* woman: dark skin tone */
- { 0x1F46B, 0x1F3FB }, /* woman and man holding hands: light skin tone */
- { 0x1F46B, 0x1F3FC }, /* woman and man holding hands: medium-light skin tone */
- { 0x1F46B, 0x1F3FD }, /* woman and man holding hands: medium skin tone */
- { 0x1F46B, 0x1F3FE }, /* woman and man holding hands: medium-dark skin tone */
- { 0x1F46B, 0x1F3FF }, /* woman and man holding hands: dark skin tone */
- { 0x1F46C, 0x1F3FB }, /* men holding hands: light skin tone */
- { 0x1F46C, 0x1F3FC }, /* men holding hands: medium-light skin tone */
- { 0x1F46C, 0x1F3FD }, /* men holding hands: medium skin tone */
- { 0x1F46C, 0x1F3FE }, /* men holding hands: medium-dark skin tone */
- { 0x1F46C, 0x1F3FF }, /* men holding hands: dark skin tone */
- { 0x1F46D, 0x1F3FB }, /* women holding hands: light skin tone */
- { 0x1F46D, 0x1F3FC }, /* women holding hands: medium-light skin tone */
- { 0x1F46D, 0x1F3FD }, /* women holding hands: medium skin tone */
- { 0x1F46D, 0x1F3FE }, /* women holding hands: medium-dark skin tone */
- { 0x1F46D, 0x1F3FF }, /* women holding hands: dark skin tone */
- { 0x1F46E, 0x1F3FB }, /* police officer: light skin tone */
- { 0x1F46E, 0x1F3FC }, /* police officer: medium-light skin tone */
- { 0x1F46E, 0x1F3FD }, /* police officer: medium skin tone */
- { 0x1F46E, 0x1F3FE }, /* police officer: medium-dark skin tone */
- { 0x1F46E, 0x1F3FF }, /* police officer: dark skin tone */
- { 0x1F470, 0x1F3FB }, /* person with veil: light skin tone */
- { 0x1F470, 0x1F3FC }, /* person with veil: medium-light skin tone */
- { 0x1F470, 0x1F3FD }, /* person with veil: medium skin tone */
- { 0x1F470, 0x1F3FE }, /* person with veil: medium-dark skin tone */
- { 0x1F470, 0x1F3FF }, /* person with veil: dark skin tone */
- { 0x1F471, 0x1F3FB }, /* person: light skin tone, blond hair */
- { 0x1F471, 0x1F3FC }, /* person: medium-light skin tone, blond hair */
- { 0x1F471, 0x1F3FD }, /* person: medium skin tone, blond hair */
- { 0x1F471, 0x1F3FE }, /* person: medium-dark skin tone, blond hair */
- { 0x1F471, 0x1F3FF }, /* person: dark skin tone, blond hair */
- { 0x1F472, 0x1F3FB }, /* person with skullcap: light skin tone */
- { 0x1F472, 0x1F3FC }, /* person with skullcap: medium-light skin tone */
- { 0x1F472, 0x1F3FD }, /* person with skullcap: medium skin tone */
- { 0x1F472, 0x1F3FE }, /* person with skullcap: medium-dark skin tone */
- { 0x1F472, 0x1F3FF }, /* person with skullcap: dark skin tone */
- { 0x1F473, 0x1F3FB }, /* person wearing turban: light skin tone */
- { 0x1F473, 0x1F3FC }, /* person wearing turban: medium-light skin tone */
- { 0x1F473, 0x1F3FD }, /* person wearing turban: medium skin tone */
- { 0x1F473, 0x1F3FE }, /* person wearing turban: medium-dark skin tone */
- { 0x1F473, 0x1F3FF }, /* person wearing turban: dark skin tone */
- { 0x1F474, 0x1F3FB }, /* old man: light skin tone */
- { 0x1F474, 0x1F3FC }, /* old man: medium-light skin tone */
- { 0x1F474, 0x1F3FD }, /* old man: medium skin tone */
- { 0x1F474, 0x1F3FE }, /* old man: medium-dark skin tone */
- { 0x1F474, 0x1F3FF }, /* old man: dark skin tone */
- { 0x1F475, 0x1F3FB }, /* old woman: light skin tone */
- { 0x1F475, 0x1F3FC }, /* old woman: medium-light skin tone */
- { 0x1F475, 0x1F3FD }, /* old woman: medium skin tone */
- { 0x1F475, 0x1F3FE }, /* old woman: medium-dark skin tone */
- { 0x1F475, 0x1F3FF }, /* old woman: dark skin tone */
- { 0x1F476, 0x1F3FB }, /* baby: light skin tone */
- { 0x1F476, 0x1F3FC }, /* baby: medium-light skin tone */
- { 0x1F476, 0x1F3FD }, /* baby: medium skin tone */
- { 0x1F476, 0x1F3FE }, /* baby: medium-dark skin tone */
- { 0x1F476, 0x1F3FF }, /* baby: dark skin tone */
- { 0x1F477, 0x1F3FB }, /* construction worker: light skin tone */
- { 0x1F477, 0x1F3FC }, /* construction worker: medium-light skin tone */
- { 0x1F477, 0x1F3FD }, /* construction worker: medium skin tone */
- { 0x1F477, 0x1F3FE }, /* construction worker: medium-dark skin tone */
- { 0x1F477, 0x1F3FF }, /* construction worker: dark skin tone */
- { 0x1F478, 0x1F3FB }, /* princess: light skin tone */
- { 0x1F478, 0x1F3FC }, /* princess: medium-light skin tone */
- { 0x1F478, 0x1F3FD }, /* princess: medium skin tone */
- { 0x1F478, 0x1F3FE }, /* princess: medium-dark skin tone */
- { 0x1F478, 0x1F3FF }, /* princess: dark skin tone */
- { 0x1F47C, 0x1F3FB }, /* baby angel: light skin tone */
- { 0x1F47C, 0x1F3FC }, /* baby angel: medium-light skin tone */
- { 0x1F47C, 0x1F3FD }, /* baby angel: medium skin tone */
- { 0x1F47C, 0x1F3FE }, /* baby angel: medium-dark skin tone */
- { 0x1F47C, 0x1F3FF }, /* baby angel: dark skin tone */
- { 0x1F481, 0x1F3FB }, /* person tipping hand: light skin tone */
- { 0x1F481, 0x1F3FC }, /* person tipping hand: medium-light skin tone */
- { 0x1F481, 0x1F3FD }, /* person tipping hand: medium skin tone */
- { 0x1F481, 0x1F3FE }, /* person tipping hand: medium-dark skin tone */
- { 0x1F481, 0x1F3FF }, /* person tipping hand: dark skin tone */
- { 0x1F482, 0x1F3FB }, /* guard: light s