diff --git a/dvtm.c b/dvtm.c index 2742a62..f850ec8 100644 --- a/dvtm.c +++ b/dvtm.c @@ -379,13 +379,21 @@ drawbar(void) { wchar_t wbuf[sizeof bar.text]; size_t numchars = mbstowcs(wbuf, bar.text, sizeof bar.text); - if (numchars != (size_t)-1 && (width = wcswidth(wbuf, maxwidth)) != -1) { + width = 0; + for (size_t i = 0; numchars != (size_t)-1 && i < numchars && width != -1; i++) { + int w = vt_wcwidth(wbuf[i]); + width = w < 0 ? -1 : width + w; + if (width > maxwidth) + break; + } + + if (numchars != (size_t)-1 && width != -1) { int pos; for (pos = 0; pos + width < maxwidth; pos++) addch(' '); for (size_t i = 0; i < numchars; i++) { - pos += wcwidth(wbuf[i]); + pos += vt_wcwidth(wbuf[i]); if (pos > maxwidth) break; addnwstr(wbuf+i, 1); diff --git a/test/test-vt.c b/test/test-vt.c index a8f96a6..032b188 100644 --- a/test/test-vt.c +++ b/test/test-vt.c @@ -164,6 +164,25 @@ static void test_device_attributes(void) } } +static void test_wcwidth(void) +{ + term = "WCWIDTH"; + CHECK(vt_wcwidth(L'a') == 1); + CHECK(vt_wcwidth(L'\0') == 0); + CHECK(vt_wcwidth(L'\n') == -1); + CHECK(vt_wcwidth(0x4E2D) == 2); + CHECK(vt_wcwidth(0x1F600) == 2); + CHECK(vt_wcwidth(0x1FAE9) == 2); + CHECK(vt_wcwidth(0x0301) == 0); + CHECK(vt_wcwidth(0x200D) == 0); + CHECK(vt_wcwidth(0x00E9) == 1); + + Vt *t = vt_create(3, 10, 0); + feed(t, "\xf0\x9f\xab\xa9x"); + CHECK(t->buffer->curs_col == 3); + vt_destroy(t); +} + int main(void) { setlocale(LC_CTYPE, "C.UTF-8"); @@ -191,6 +210,7 @@ int main(void) setenv("TERMINFO", dir, 1); test_device_attributes(); + test_wcwidth(); test_term("xterm", COLOR_RED, COLOR_RED, COLOR_BLACK, COLOR_BLACK); test_term("xterm-256color", 196, 196, 16, 16); if (direct) { diff --git a/tools/gen-wcwidth.py b/tools/gen-wcwidth.py new file mode 100755 index 0000000..0337268 --- /dev/null +++ b/tools/gen-wcwidth.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +"""Generate wcwidth_table.h from the Unicode tables of the wcwidth package. + +usage: pip install wcwidth && tools/gen-wcwidth.py > wcwidth_table.h +""" +import wcwidth.table_wide as wide +import wcwidth.table_zero as zero + +version = max(wide.WIDE_EASTASIAN, key=lambda v: tuple(map(int, v.split('.')))) + + +print('typedef struct { unsigned int lo, hi; } WidthRange;\n') + + +def emit(name, ranges): + print(f'static const WidthRange {name}[] = {{') + for lo, hi in ranges: + print(f'\t{{ 0x{lo:04X}, 0x{hi:04X} }},') + print('};\n') + + +emit('wcwidth_zero', [r for r in zero.ZERO_WIDTH[version] if r[1] >= 0x80]) +emit('wcwidth_wide', wide.WIDE_EASTASIAN[version]) diff --git a/vt.c b/vt.c index 93f3691..5894100 100644 --- a/vt.c +++ b/vt.c @@ -41,6 +41,7 @@ #endif #include "vt.h" +#include "wcwidth_table.h" #ifdef _AIX # include "forkpty-aix.c" @@ -1132,6 +1133,35 @@ static void interpret_csi(Vt *t) } } +static bool in_ranges(const WidthRange *r, size_t n, unsigned int c) +{ + size_t lo = 0, hi = n; + while (lo < hi) { + size_t mid = lo + (hi - lo) / 2; + if (c < r[mid].lo) + hi = mid; + else if (c > r[mid].hi) + lo = mid + 1; + else + return true; + } + return false; +} + +int vt_wcwidth(wchar_t wc) +{ + unsigned int c = wc; + if (c < 0x20 || (c >= 0x7f && c < 0xa0)) + return c ? -1 : 0; + if (c < 0x300) + return 1; + if (in_ranges(wcwidth_zero, sizeof wcwidth_zero / sizeof *wcwidth_zero, c)) + return 0; + if (in_ranges(wcwidth_wide, sizeof wcwidth_wide / sizeof *wcwidth_wide, c)) + return 2; + return 1; +} + /* Interpret an 'index' (IND) sequence */ static void interpret_csi_ind(Vt *t) { @@ -1402,7 +1432,7 @@ static void put_wc(Vt *t, wchar_t wc) wc = gc; } width = 1; - } else if ((width = wcwidth(wc)) < 1) { + } else if ((width = vt_wcwidth(wc)) < 1) { width = 1; } Buffer *b = t->buffer; @@ -1576,7 +1606,7 @@ void vt_draw(Vt *t, WINDOW *win, int srow, int scol) size_t len = wcrtomb(buf, cell->text, NULL); if (len != (size_t)-1) { waddnstr(win, buf, len); - if (wcwidth(cell->text) > 1) + if (vt_wcwidth(cell->text) > 1) j++; } } else { diff --git a/vt.h b/vt.h index 5918d39..ed73774 100644 --- a/vt.h +++ b/vt.h @@ -21,6 +21,7 @@ #include #include #include +#include #ifndef NCURSES_MOUSE_VERSION #define mmask_t unsigned long @@ -56,6 +57,7 @@ void vt_dirty(Vt*); void vt_draw(Vt*, WINDOW *win, int startrow, int startcol); int vt_color_get(Vt*, int fg, int bg); int vt_color_reserve(int fg, int bg); +int vt_wcwidth(wchar_t wc); void vt_scroll(Vt*, int rows); void vt_noscroll(Vt*); diff --git a/wcwidth_table.h b/wcwidth_table.h new file mode 100644 index 0000000..d7c4495 --- /dev/null +++ b/wcwidth_table.h @@ -0,0 +1,478 @@ +typedef struct { unsigned int lo, hi; } WidthRange; + +static const WidthRange wcwidth_zero[] = { + { 0x0300, 0x036F }, + { 0x0483, 0x0489 }, + { 0x0591, 0x05BD }, + { 0x05BF, 0x05BF }, + { 0x05C1, 0x05C2 }, + { 0x05C4, 0x05C5 }, + { 0x05C7, 0x05C9 }, + { 0x0610, 0x061A }, + { 0x061C, 0x061C }, + { 0x064B, 0x065F }, + { 0x0670, 0x0670 }, + { 0x06D6, 0x06DC }, + { 0x06DF, 0x06E4 }, + { 0x06E7, 0x06E8 }, + { 0x06EA, 0x06ED }, + { 0x0711, 0x0711 }, + { 0x0730, 0x074A }, + { 0x07A6, 0x07B0 }, + { 0x07EB, 0x07F3 }, + { 0x07FD, 0x07FD }, + { 0x0816, 0x0819 }, + { 0x081B, 0x0823 }, + { 0x0825, 0x0827 }, + { 0x0829, 0x082D }, + { 0x0859, 0x085B }, + { 0x0897, 0x089F }, + { 0x08CA, 0x08E1 }, + { 0x08E3, 0x0903 }, + { 0x093A, 0x093C }, + { 0x093E, 0x094F }, + { 0x0951, 0x0957 }, + { 0x0962, 0x0963 }, + { 0x0981, 0x0983 }, + { 0x09BC, 0x09BC }, + { 0x09BE, 0x09C4 }, + { 0x09C7, 0x09C8 }, + { 0x09CB, 0x09CD }, + { 0x09D7, 0x09D7 }, + { 0x09E2, 0x09E3 }, + { 0x09FE, 0x09FE }, + { 0x0A01, 0x0A03 }, + { 0x0A3C, 0x0A3C }, + { 0x0A3E, 0x0A42 }, + { 0x0A47, 0x0A48 }, + { 0x0A4B, 0x0A4D }, + { 0x0A51, 0x0A51 }, + { 0x0A70, 0x0A71 }, + { 0x0A75, 0x0A75 }, + { 0x0A81, 0x0A83 }, + { 0x0ABC, 0x0ABC }, + { 0x0ABE, 0x0AC5 }, + { 0x0AC7, 0x0AC9 }, + { 0x0ACB, 0x0ACD }, + { 0x0AE2, 0x0AE3 }, + { 0x0AFA, 0x0AFF }, + { 0x0B01, 0x0B03 }, + { 0x0B3C, 0x0B3C }, + { 0x0B3E, 0x0B44 }, + { 0x0B47, 0x0B48 }, + { 0x0B4B, 0x0B4D }, + { 0x0B53, 0x0B57 }, + { 0x0B62, 0x0B63 }, + { 0x0B82, 0x0B82 }, + { 0x0BBE, 0x0BC2 }, + { 0x0BC6, 0x0BC8 }, + { 0x0BCA, 0x0BCD }, + { 0x0BD7, 0x0BD7 }, + { 0x0C00, 0x0C04 }, + { 0x0C3C, 0x0C3C }, + { 0x0C3E, 0x0C44 }, + { 0x0C46, 0x0C48 }, + { 0x0C4A, 0x0C4D }, + { 0x0C55, 0x0C56 }, + { 0x0C62, 0x0C63 }, + { 0x0C81, 0x0C83 }, + { 0x0CBC, 0x0CBC }, + { 0x0CBE, 0x0CC4 }, + { 0x0CC6, 0x0CC8 }, + { 0x0CCA, 0x0CCD }, + { 0x0CD5, 0x0CD6 }, + { 0x0CE2, 0x0CE3 }, + { 0x0CF3, 0x0CF3 }, + { 0x0D00, 0x0D03 }, + { 0x0D3B, 0x0D3C }, + { 0x0D3E, 0x0D44 }, + { 0x0D46, 0x0D48 }, + { 0x0D4A, 0x0D4D }, + { 0x0D57, 0x0D57 }, + { 0x0D62, 0x0D63 }, + { 0x0D81, 0x0D83 }, + { 0x0DCA, 0x0DCA }, + { 0x0DCF, 0x0DD4 }, + { 0x0DD6, 0x0DD6 }, + { 0x0DD8, 0x0DDF }, + { 0x0DF2, 0x0DF3 }, + { 0x0E31, 0x0E31 }, + { 0x0E34, 0x0E3A }, + { 0x0E47, 0x0E4E }, + { 0x0EB1, 0x0EB1 }, + { 0x0EB4, 0x0EBC }, + { 0x0EC8, 0x0ECE }, + { 0x0F18, 0x0F19 }, + { 0x0F35, 0x0F35 }, + { 0x0F37, 0x0F37 }, + { 0x0F39, 0x0F39 }, + { 0x0F3E, 0x0F3F }, + { 0x0F71, 0x0F84 }, + { 0x0F86, 0x0F87 }, + { 0x0F8D, 0x0F97 }, + { 0x0F99, 0x0FBC }, + { 0x0FC6, 0x0FC6 }, + { 0x102B, 0x103E }, + { 0x1056, 0x1059 }, + { 0x105E, 0x1060 }, + { 0x1062, 0x1064 }, + { 0x1067, 0x106D }, + { 0x1071, 0x1074 }, + { 0x1082, 0x108D }, + { 0x108F, 0x108F }, + { 0x109A, 0x109D }, + { 0x1160, 0x11FF }, + { 0x135D, 0x135F }, + { 0x1712, 0x1715 }, + { 0x1732, 0x1734 }, + { 0x1752, 0x1753 }, + { 0x1772, 0x1773 }, + { 0x17B4, 0x17D3 }, + { 0x17DD, 0x17DD }, + { 0x180B, 0x180F }, + { 0x1885, 0x1886 }, + { 0x18A9, 0x18A9 }, + { 0x1920, 0x192B }, + { 0x1930, 0x193B }, + { 0x1A17, 0x1A1B }, + { 0x1A55, 0x1A5E }, + { 0x1A60, 0x1A7C }, + { 0x1A7F, 0x1A7F }, + { 0x1AB0, 0x1AF0 }, + { 0x1B00, 0x1B04 }, + { 0x1B34, 0x1B44 }, + { 0x1B6B, 0x1B73 }, + { 0x1B80, 0x1B82 }, + { 0x1BA1, 0x1BAD }, + { 0x1BE6, 0x1BF3 }, + { 0x1C24, 0x1C37 }, + { 0x1CD0, 0x1CD2 }, + { 0x1CD4, 0x1CE8 }, + { 0x1CED, 0x1CED }, + { 0x1CF4, 0x1CF4 }, + { 0x1CF7, 0x1CF9 }, + { 0x1DC0, 0x1DFF }, + { 0x200B, 0x200F }, + { 0x2028, 0x202E }, + { 0x2060, 0x206F }, + { 0x20D0, 0x20F0 }, + { 0x2CEF, 0x2CF1 }, + { 0x2D7F, 0x2D7F }, + { 0x2DE0, 0x2DFF }, + { 0x302A, 0x302F }, + { 0x3099, 0x309A }, + { 0x3164, 0x3164 }, + { 0xA66F, 0xA672 }, + { 0xA674, 0xA67D }, + { 0xA69E, 0xA69F }, + { 0xA6F0, 0xA6F1 }, + { 0xA802, 0xA802 }, + { 0xA806, 0xA806 }, + { 0xA80B, 0xA80B }, + { 0xA823, 0xA827 }, + { 0xA82C, 0xA82C }, + { 0xA880, 0xA881 }, + { 0xA8B4, 0xA8C5 }, + { 0xA8E0, 0xA8F1 }, + { 0xA8FF, 0xA8FF }, + { 0xA926, 0xA92D }, + { 0xA947, 0xA953 }, + { 0xA980, 0xA983 }, + { 0xA9B3, 0xA9C0 }, + { 0xA9E5, 0xA9E5 }, + { 0xAA29, 0xAA36 }, + { 0xAA43, 0xAA43 }, + { 0xAA4C, 0xAA4D }, + { 0xAA7B, 0xAA7D }, + { 0xAAB0, 0xAAB0 }, + { 0xAAB2, 0xAAB4 }, + { 0xAAB7, 0xAAB8 }, + { 0xAABE, 0xAABF }, + { 0xAAC1, 0xAAC1 }, + { 0xAAEB, 0xAAEF }, + { 0xAAF5, 0xAAF6 }, + { 0xABE3, 0xABEA }, + { 0xABEC, 0xABED }, + { 0xD7B0, 0xD7FF }, + { 0xFB1E, 0xFB1E }, + { 0xFE00, 0xFE0F }, + { 0xFE20, 0xFE2F }, + { 0xFEFF, 0xFEFF }, + { 0xFFA0, 0xFFA0 }, + { 0xFFF0, 0xFFFB }, + { 0x101FD, 0x101FD }, + { 0x102E0, 0x102E0 }, + { 0x10376, 0x1037A }, + { 0x10A01, 0x10A03 }, + { 0x10A05, 0x10A06 }, + { 0x10A0C, 0x10A0F }, + { 0x10A38, 0x10A3A }, + { 0x10A3F, 0x10A3F }, + { 0x10AE5, 0x10AE6 }, + { 0x10D24, 0x10D27 }, + { 0x10D69, 0x10D6D }, + { 0x10EAB, 0x10EAC }, + { 0x10ECB, 0x10ECF }, + { 0x10EF0, 0x10EFF }, + { 0x10F46, 0x10F50 }, + { 0x10F82, 0x10F85 }, + { 0x11000, 0x11002 }, + { 0x11038, 0x11046 }, + { 0x11070, 0x11070 }, + { 0x11073, 0x11074 }, + { 0x1107F, 0x11082 }, + { 0x110B0, 0x110BA }, + { 0x110C2, 0x110C2 }, + { 0x11100, 0x11102 }, + { 0x11127, 0x11134 }, + { 0x11145, 0x11146 }, + { 0x11173, 0x11173 }, + { 0x11180, 0x11182 }, + { 0x111B3, 0x111C0 }, + { 0x111C9, 0x111CC }, + { 0x111CE, 0x111CF }, + { 0x1122C, 0x11237 }, + { 0x1123E, 0x1123E }, + { 0x11241, 0x11241 }, + { 0x112DF, 0x112EA }, + { 0x11300, 0x11303 }, + { 0x1133B, 0x1133C }, + { 0x1133E, 0x11344 }, + { 0x11347, 0x11348 }, + { 0x1134B, 0x1134D }, + { 0x11357, 0x11357 }, + { 0x11362, 0x11363 }, + { 0x11366, 0x1136C }, + { 0x11370, 0x11374 }, + { 0x113B8, 0x113C0 }, + { 0x113C2, 0x113C2 }, + { 0x113C5, 0x113C5 }, + { 0x113C7, 0x113CA }, + { 0x113CC, 0x113D0 }, + { 0x113D2, 0x113D2 }, + { 0x113E1, 0x113E2 }, + { 0x11435, 0x11446 }, + { 0x1145E, 0x1145E }, + { 0x114B0, 0x114C3 }, + { 0x115AF, 0x115B5 }, + { 0x115B8, 0x115C0 }, + { 0x115DC, 0x115DD }, + { 0x11630, 0x11640 }, + { 0x116AB, 0x116B7 }, + { 0x1171D, 0x1172B }, + { 0x1182C, 0x1183A }, + { 0x11930, 0x11935 }, + { 0x11937, 0x11938 }, + { 0x1193B, 0x1193E }, + { 0x11940, 0x11940 }, + { 0x11942, 0x11943 }, + { 0x119D1, 0x119D7 }, + { 0x119DA, 0x119E0 }, + { 0x119E4, 0x119E4 }, + { 0x11A01, 0x11A0A }, + { 0x11A33, 0x11A39 }, + { 0x11A3B, 0x11A3E }, + { 0x11A47, 0x11A47 }, + { 0x11A51, 0x11A5B }, + { 0x11A8A, 0x11A99 }, + { 0x11B60, 0x11B67 }, + { 0x11C2F, 0x11C36 }, + { 0x11C38, 0x11C3F }, + { 0x11C92, 0x11CA7 }, + { 0x11CA9, 0x11CB6 }, + { 0x11D31, 0x11D36 }, + { 0x11D3A, 0x11D3A }, + { 0x11D3C, 0x11D3D }, + { 0x11D3F, 0x11D45 }, + { 0x11D47, 0x11D47 }, + { 0x11D8A, 0x11D8E }, + { 0x11D90, 0x11D91 }, + { 0x11D93, 0x11D97 }, + { 0x11DF0, 0x11DF0 }, + { 0x11EF3, 0x11EF6 }, + { 0x11F00, 0x11F01 }, + { 0x11F03, 0x11F03 }, + { 0x11F34, 0x11F3A }, + { 0x11F3E, 0x11F42 }, + { 0x11F5A, 0x11F5A }, + { 0x13430, 0x13440 }, + { 0x13447, 0x13455 }, + { 0x1611E, 0x1612F }, + { 0x16AF0, 0x16AF4 }, + { 0x16B30, 0x16B36 }, + { 0x16F4F, 0x16F4F }, + { 0x16F51, 0x16F87 }, + { 0x16F8F, 0x16F92 }, + { 0x16FE4, 0x16FE4 }, + { 0x16FF0, 0x16FF1 }, + { 0x1BC9D, 0x1BC9E }, + { 0x1BCA0, 0x1BCA3 }, + { 0x1CF00, 0x1CF2D }, + { 0x1CF30, 0x1CF46 }, + { 0x1D127, 0x1D128 }, + { 0x1D165, 0x1D169 }, + { 0x1D16D, 0x1D182 }, + { 0x1D185, 0x1D18B }, + { 0x1D1AA, 0x1D1AD }, + { 0x1D242, 0x1D244 }, + { 0x1D250, 0x1D252 }, + { 0x1D25B, 0x1D25C }, + { 0x1D25F, 0x1D25F }, + { 0x1D280, 0x1D281 }, + { 0x1DA00, 0x1DA36 }, + { 0x1DA3B, 0x1DA6C }, + { 0x1DA75, 0x1DA75 }, + { 0x1DA84, 0x1DA84 }, + { 0x1DA9B, 0x1DA9F }, + { 0x1DAA1, 0x1DAAF }, + { 0x1E000, 0x1E006 }, + { 0x1E008, 0x1E018 }, + { 0x1E01B, 0x1E021 }, + { 0x1E023, 0x1E024 }, + { 0x1E026, 0x1E02A }, + { 0x1E08F, 0x1E08F }, + { 0x1E130, 0x1E136 }, + { 0x1E2AE, 0x1E2AE }, + { 0x1E2EC, 0x1E2EF }, + { 0x1E4EC, 0x1E4EF }, + { 0x1E5EE, 0x1E5EF }, + { 0x1E6E3, 0x1E6E3 }, + { 0x1E6E6, 0x1E6E6 }, + { 0x1E6EE, 0x1E6EF }, + { 0x1E6F5, 0x1E6F5 }, + { 0x1E8D0, 0x1E8D6 }, + { 0x1E944, 0x1E94A }, + { 0xE0000, 0xE0FFF }, +}; + +static const WidthRange wcwidth_wide[] = { + { 0x1100, 0x115F }, + { 0x231A, 0x231B }, + { 0x2329, 0x232A }, + { 0x23E9, 0x23EC }, + { 0x23F0, 0x23F0 }, + { 0x23F3, 0x23F3 }, + { 0x25FD, 0x25FE }, + { 0x2614, 0x2615 }, + { 0x2630, 0x2637 }, + { 0x2648, 0x2653 }, + { 0x267F, 0x267F }, + { 0x268A, 0x268F }, + { 0x2693, 0x2693 }, + { 0x26A1, 0x26A1 }, + { 0x26AA, 0x26AB }, + { 0x26BD, 0x26BE }, + { 0x26C4, 0x26C5 }, + { 0x26CE, 0x26CE }, + { 0x26D4, 0x26D4 }, + { 0x26EA, 0x26EA }, + { 0x26F2, 0x26F3 }, + { 0x26F5, 0x26F5 }, + { 0x26FA, 0x26FA }, + { 0x26FD, 0x26FD }, + { 0x2705, 0x2705 }, + { 0x270A, 0x270B }, + { 0x2728, 0x2728 }, + { 0x274C, 0x274C }, + { 0x274E, 0x274E }, + { 0x2753, 0x2755 }, + { 0x2757, 0x2757 }, + { 0x2795, 0x2797 }, + { 0x27B0, 0x27B0 }, + { 0x27BF, 0x27BF }, + { 0x2B1B, 0x2B1C }, + { 0x2B50, 0x2B50 }, + { 0x2B55, 0x2B55 }, + { 0x2E80, 0x2E99 }, + { 0x2E9B, 0x2EF3 }, + { 0x2F00, 0x2FD5 }, + { 0x2FF0, 0x3029 }, + { 0x3030, 0x303E }, + { 0x3041, 0x3096 }, + { 0x309B, 0x30FF }, + { 0x3105, 0x312F }, + { 0x3131, 0x3163 }, + { 0x3165, 0x318E }, + { 0x3190, 0x31E5 }, + { 0x31EF, 0x321E }, + { 0x3220, 0x3247 }, + { 0x3250, 0xA48C }, + { 0xA490, 0xA4C6 }, + { 0xA960, 0xA97C }, + { 0xAC00, 0xD7A3 }, + { 0xF900, 0xFAFF }, + { 0xFE10, 0xFE19 }, + { 0xFE30, 0xFE52 }, + { 0xFE54, 0xFE66 }, + { 0xFE68, 0xFE6B }, + { 0xFF01, 0xFF60 }, + { 0xFFE0, 0xFFE6 }, + { 0x16FE0, 0x16FE3 }, + { 0x16FF2, 0x16FF6 }, + { 0x17000, 0x18CDA }, + { 0x18CFF, 0x18D20 }, + { 0x18D80, 0x18DF2 }, + { 0x18E00, 0x19191 }, + { 0x191A0, 0x191D2 }, + { 0x1AFF0, 0x1AFF3 }, + { 0x1AFF5, 0x1AFFB }, + { 0x1AFFD, 0x1AFFE }, + { 0x1B000, 0x1B128 }, + { 0x1B132, 0x1B132 }, + { 0x1B150, 0x1B152 }, + { 0x1B155, 0x1B155 }, + { 0x1B164, 0x1B168 }, + { 0x1B170, 0x1B2FB }, + { 0x1D300, 0x1D356 }, + { 0x1D360, 0x1D376 }, + { 0x1F004, 0x1F004 }, + { 0x1F0CF, 0x1F0CF }, + { 0x1F18E, 0x1F18E }, + { 0x1F191, 0x1F19A }, + { 0x1F1AE, 0x1F1AE }, + { 0x1F1E6, 0x1F202 }, + { 0x1F210, 0x1F23B }, + { 0x1F240, 0x1F248 }, + { 0x1F250, 0x1F251 }, + { 0x1F260, 0x1F265 }, + { 0x1F300, 0x1F320 }, + { 0x1F32D, 0x1F335 }, + { 0x1F337, 0x1F37C }, + { 0x1F37E, 0x1F393 }, + { 0x1F3A0, 0x1F3CA }, + { 0x1F3CF, 0x1F3D3 }, + { 0x1F3E0, 0x1F3F0 }, + { 0x1F3F4, 0x1F3F4 }, + { 0x1F3F8, 0x1F43E }, + { 0x1F440, 0x1F440 }, + { 0x1F442, 0x1F4FC }, + { 0x1F4FF, 0x1F53D }, + { 0x1F54B, 0x1F54E }, + { 0x1F550, 0x1F567 }, + { 0x1F57A, 0x1F57A }, + { 0x1F595, 0x1F596 }, + { 0x1F5A4, 0x1F5A4 }, + { 0x1F5FB, 0x1F64F }, + { 0x1F680, 0x1F6C5 }, + { 0x1F6CC, 0x1F6CC }, + { 0x1F6D0, 0x1F6D2 }, + { 0x1F6D5, 0x1F6D9 }, + { 0x1F6DC, 0x1F6DF }, + { 0x1F6EB, 0x1F6EC }, + { 0x1F6F4, 0x1F6FC }, + { 0x1F7DA, 0x1F7DA }, + { 0x1F7E0, 0x1F7EB }, + { 0x1F7F0, 0x1F7F0 }, + { 0x1F90C, 0x1F93A }, + { 0x1F93C, 0x1F945 }, + { 0x1F947, 0x1F9FF }, + { 0x1FA70, 0x1FA7C }, + { 0x1FA80, 0x1FAC6 }, + { 0x1FAC8, 0x1FAC8 }, + { 0x1FACC, 0x1FADD }, + { 0x1FADF, 0x1FAEB }, + { 0x1FAEF, 0x1FAFA }, + { 0x20000, 0x2FFFD }, + { 0x30000, 0x3FFFD }, +}; +