This commit is contained in:
ssrlive 2022-11-23 07:56:48 -07:00
commit 7655b66d8e
39 changed files with 8048 additions and 2734 deletions

View file

@ -95,6 +95,11 @@ add_executable(test_decode_utf8
target_compile_definitions(test_decode_utf8 PRIVATE TEST)
target_link_libraries(test_decode_utf8 utils ${platform_libraries})
add_executable(test_unicode_norm
utils/unicode-norm.c)
target_compile_definitions(test_unicode_norm PRIVATE TEST)
target_link_libraries(test_unicode_norm utils ${platform_libraries})
add_executable(test_tree234
utils/tree234.c)
target_compile_definitions(test_tree234 PRIVATE TEST)

View file

@ -1,6 +1,7 @@
#cmakedefine NO_IPV6
#cmakedefine NO_GSSAPI
#cmakedefine STATIC_GSSAPI
#cmakedefine NO_SCROLLBACK_COMPRESSION
#cmakedefine NO_MULTIMON

View file

@ -15,6 +15,12 @@ set(PUTTY_FUZZING OFF
CACHE BOOL "Build PuTTY binaries suitable for fuzzing, NOT FOR REAL USE")
set(PUTTY_COVERAGE OFF
CACHE BOOL "Build PuTTY binaries suitable for code coverage analysis")
set(PUTTY_COMPRESS_SCROLLBACK ON
# This is always on in production versions of PuTTY, but downstreams
# of the code have been known to find it a better tradeoff to
# disable it. So there's a #ifdef in terminal.c, and a cmake option
# to enable that ifdef just in case it needs testing or debugging.
CACHE BOOL "Store terminal scrollback in compressed form")
set(STRICT OFF
CACHE BOOL "Enable extra compiler warnings and make them errors")
@ -108,6 +114,9 @@ endif()
if(PUTTY_FUZZING)
add_compile_definitions(FUZZING)
endif()
if(NOT PUTTY_COMPRESS_SCROLLBACK)
set(NO_SCROLLBACK_COMPRESSION ON)
endif()
if(PUTTY_COVERAGE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage -g ")
endif()

View file

@ -1033,12 +1033,14 @@ static bool opensshcert_check_cert(
*/
if (time < ck->valid_after) {
put_fmt(error, "Certificate is not valid until ");
opensshcert_time_to_iso8601(BinarySink_UPCAST(error), time);
opensshcert_time_to_iso8601(BinarySink_UPCAST(error),
ck->valid_after);
goto out;
}
if (time >= ck->valid_before) {
put_fmt(error, "Certificate expired at ");
opensshcert_time_to_iso8601(BinarySink_UPCAST(error), time);
opensshcert_time_to_iso8601(BinarySink_UPCAST(error),
ck->valid_before);
goto out;
}

1
defs.h
View file

@ -91,6 +91,7 @@ typedef struct BinarySink BinarySink;
typedef struct BinarySource BinarySource;
typedef struct stdio_sink stdio_sink;
typedef struct bufchain_sink bufchain_sink;
typedef struct buffer_sink buffer_sink;
typedef struct handle_sink handle_sink;
typedef struct IdempotentCallback IdempotentCallback;

View file

@ -4071,7 +4071,7 @@ at the bottom of the screen, until a space is typed.
\S{supdup-scroll} \q{Terminal scrolling}
This controls whether the terminal will perform scrolling then the
This controls whether the terminal will perform scrolling when the
cursor goes below the last line, or if the cursor will return to the
first line.

View file

@ -156,6 +156,10 @@ struct BinarySink {
#define put_c_string_literal(bs, str) \
BinarySink_put_c_string_literal(BinarySink_UPCAST(bs), str)
/* More complicated function implemented in encode_utf8.c */
#define put_utf8_char(bs, c) \
BinarySink_put_utf8_char(BinarySink_UPCAST(bs), c)
/*
* The underlying real C functions that implement most of those
* macros. Generally you won't want to call these directly, because
@ -185,6 +189,7 @@ void BinarySink_put_mp_ssh2(BinarySink *bs, mp_int *x);
void BinarySink_put_fmt(BinarySink *, const char *fmt, ...) PRINTF_LIKE(2, 3);
void BinarySink_put_fmtv(BinarySink *, const char *fmt, va_list ap);
void BinarySink_put_c_string_literal(BinarySink *, ptrlen);
void BinarySink_put_utf8_char(BinarySink *, unsigned);
/* ---------------------------------------------------------------------- */
@ -353,7 +358,14 @@ struct bufchain_sink {
bufchain *ch;
BinarySink_IMPLEMENTATION;
};
struct buffer_sink {
char *out;
size_t space;
bool overflowed;
BinarySink_IMPLEMENTATION;
};
void stdio_sink_init(stdio_sink *sink, FILE *fp);
void bufchain_sink_init(bufchain_sink *sink, bufchain *ch);
void buffer_sink_init(buffer_sink *sink, void *buffer, size_t len);
#endif /* PUTTY_MARSHAL_H */

19
misc.h
View file

@ -248,26 +248,29 @@ void smemclr(void *b, size_t len);
* by the 'eq' in the name. */
unsigned smemeq(const void *av, const void *bv, size_t len);
/* Encode a single UTF-8 character. Assumes that illegal characters
* (such as things in the surrogate range, or > 0x10FFFF) have already
* been removed. */
size_t encode_utf8(void *output, unsigned long ch);
/* Encode a wide-character string into UTF-8. Tolerates surrogates if
* sizeof(wchar_t) == 2, assuming that in that case the wide string is
* encoded in UTF-16. */
char *encode_wide_string_as_utf8(const wchar_t *wstr);
/* Decode a single UTF-8 character. Returns U+FFFD for any of the
* illegal cases. */
unsigned long decode_utf8(const char **utf8);
* illegal cases. If the source is empty, returns L'\0' (and sets the
* error indicator on the source, of course). */
unsigned decode_utf8(BinarySource *src);
/* Decode a single UTF-8 character to an output buffer of the
* platform's wchar_t. May write a pair of surrogates if
* sizeof(wchar_t) == 2, assuming that in that case the wide string is
* encoded in UTF-16. Otherwise, writes one character. Returns the
* number written. */
size_t decode_utf8_to_wchar(const char **utf8, wchar_t *out);
size_t decode_utf8_to_wchar(BinarySource *src, wchar_t *out);
/* Normalise a UTF-8 string into Normalisation Form C. */
strbuf *utf8_to_nfc(ptrlen input);
/* Determine if a UTF-8 string contains any characters unknown to our
* supported version of Unicode. */
char *utf8_unknown_char(ptrlen input);
/* Write a string out in C string-literal format. */
void write_c_string_literal(FILE *fp, ptrlen str);

View file

@ -367,7 +367,7 @@ typedef enum {
} Mouse_Button;
typedef enum {
MA_NOTHING, MA_CLICK, MA_2CLK, MA_3CLK, MA_DRAG, MA_RELEASE
MA_NOTHING, MA_CLICK, MA_2CLK, MA_3CLK, MA_DRAG, MA_RELEASE, MA_MOVE
} Mouse_Action;
/* Keyboard modifiers -- keys the user is actually holding down */

View file

@ -1023,6 +1023,12 @@ SeatPromptResult verify_ssh_host_key(
text, SDT_PARA, "If you trust this host, %s to add the key to "
"%s's cache and carry on connecting.",
pds->hk_accept_action, appname);
if (key && ssh_key_alg(key)->is_certificate) {
seat_dialog_text_append(
text, SDT_PARA, "(Storing this certified key in the cache "
"will NOT cause its certification authority to be trusted "
"for any other key or host.)");
}
seat_dialog_text_append(
text, SDT_PARA, "If you want to carry on connecting just once, "
"without adding the key to the cache, %s.",

File diff suppressed because it is too large Load diff

View file

@ -398,6 +398,8 @@ static void move_termchar(termline *line, termchar *dest, termchar *src)
#endif
}
#ifndef NO_SCROLLBACK_COMPRESSION
/*
* Compress and decompress a termline into an RLE-based format for
* storing in scrollback. (Since scrollback almost never needs to
@ -688,11 +690,12 @@ static void makeliteral_cc(strbuf *b, termchar *c, unsigned long *state)
typedef struct compressed_scrollback_line {
size_t len;
/* compressed data follows after this */
} compressed_scrollback_line;
static termline *decompressline(compressed_scrollback_line *line);
static termline *decompressline_no_free(compressed_scrollback_line *line);
static compressed_scrollback_line *compressline(termline *ldata)
static compressed_scrollback_line *compressline_no_free(termline *ldata)
{
strbuf *b = strbuf_new();
@ -768,7 +771,7 @@ static compressed_scrollback_line *compressline(termline *ldata)
printf("\n");
#endif
dcl = decompressline(line);
dcl = decompressline_no_free(line);
assert(ldata->cols == dcl->cols);
assert(ldata->lattr == dcl->lattr);
for (i = 0; i < ldata->cols; i++)
@ -788,6 +791,13 @@ static compressed_scrollback_line *compressline(termline *ldata)
return line;
}
static compressed_scrollback_line *compressline_and_free(termline *ldata)
{
compressed_scrollback_line *cline = compressline_no_free(ldata);
freetermline(ldata);
return cline;
}
static void readrle(BinarySource *bs, termline *ldata,
void (*readliteral)(BinarySource *bs, termchar *c,
termline *ldata, unsigned long *state))
@ -921,7 +931,7 @@ static void readliteral_cc(BinarySource *bs, termchar *c, termline *ldata,
}
}
static termline *decompressline(compressed_scrollback_line *line)
static termline *decompressline_no_free(compressed_scrollback_line *line)
{
int ncols, byte, shift;
BinarySource bs[1];
@ -988,6 +998,66 @@ static termline *decompressline(compressed_scrollback_line *line)
return ldata;
}
static inline void free_compressed_line(compressed_scrollback_line *cline)
{
sfree(cline);
}
static termline *decompressline_and_free(compressed_scrollback_line *cline)
{
termline *ldata = decompressline_no_free(cline);
free_compressed_line(cline);
return ldata;
}
#else /* NO_SCROLLBACK_COMPRESSION */
static termline *duptermline(termline *oldline)
{
termline *newline = snew(termline);
*newline = *oldline; /* copy the POD structure fields */
newline->chars = snewn(newline->size, termchar);
for (int j = 0; j < newline->size; j++)
newline->chars[j] = oldline->chars[j];
return newline;
}
typedef termline compressed_scrollback_line;
static inline compressed_scrollback_line *compressline_and_free(
termline *ldata)
{
return ldata;
}
static inline compressed_scrollback_line *compressline_no_free(termline *ldata)
{
return duptermline(ldata);
}
static inline termline *decompressline_no_free(
compressed_scrollback_line *line)
{
/* This will return a line without the 'temporary' flag, which
* means that unlineptr() is already set up to avoid freeing it */
return line;
}
static inline termline *decompressline_and_free(
compressed_scrollback_line *line)
{
/* Same as decompressline_no_free, because the caller will free
* our returned termline, and that does all the freeing necessary */
return line;
}
static inline void free_compressed_line(compressed_scrollback_line *line)
{
freetermline(line);
}
#endif /* NO_SCROLLBACK_COMPRESSION */
/*
* Resize a line to make it `cols' columns wide.
*/
@ -1134,7 +1204,7 @@ static termline *lineptr(Terminal *term, int y, int lineno, int screen)
compressed_scrollback_line *cline = index234(whichtree, treeindex);
if (!cline)
null_line_error(term, y, lineno, whichtree, treeindex, "cline");
line = decompressline(cline);
line = decompressline_no_free(cline);
} else {
line = index234(whichtree, treeindex);
}
@ -1374,6 +1444,8 @@ static void power_on(Terminal *term, bool clear)
term->xterm_mouse = 0;
term->xterm_extended_mouse = false;
term->urxvt_extended_mouse = false;
term->raw_mouse_reported_x = 0;
term->raw_mouse_reported_y = 0;
win_set_raw_mouse_mode(term->win, false);
term->win_pointer_shape_pending = true;
term->win_pointer_shape_raw = false;
@ -2063,12 +2135,13 @@ Terminal *term_init(Conf *myconf, struct unicode_data *ucsdata, TermWin *win)
void term_free(Terminal *term)
{
compressed_scrollback_line *cline;
termline *line;
struct beeptime *beep;
int i;
while ((line = delpos234(term->scrollback, 0)) != NULL)
sfree(line); /* compressed data, not a termline */
while ((cline = delpos234(term->scrollback, 0)) != NULL)
free_compressed_line(cline);
freetree234(term->scrollback);
while ((line = delpos234(term->screen, 0)) != NULL)
freetermline(line);
@ -2192,8 +2265,7 @@ void term_size(Terminal *term, int newrows, int newcols, int newsavelines)
/* Insert a line from the scrollback at the top of the screen. */
assert(sblen >= term->tempsblines);
cline = delpos234(term->scrollback, --sblen);
line = decompressline(cline);
sfree(cline);
line = decompressline_and_free(cline);
line->temporary = false; /* reconstituted line is now real */
term->tempsblines -= 1;
addpos234(term->screen, line, 0);
@ -2217,8 +2289,7 @@ void term_size(Terminal *term, int newrows, int newcols, int newsavelines)
} else {
/* push top row to scrollback */
line = delpos234(term->screen, 0);
addpos234(term->scrollback, compressline(line), sblen++);
freetermline(line);
addpos234(term->scrollback, compressline_and_free(line), sblen++);
term->tempsblines += 1;
term->curs.y -= 1;
term->savecurs.y -= 1;
@ -2594,15 +2665,15 @@ static void scroll(Terminal *term, int topline, int botline,
* the scrollback is full.
*/
if (sblen == term->savelines) {
unsigned char *cline;
compressed_scrollback_line *cline;
sblen--;
cline = delpos234(term->scrollback, 0);
sfree(cline);
free_compressed_line(cline);
} else
term->tempsblines += 1;
addpos234(term->scrollback, compressline(line), sblen);
addpos234(term->scrollback, compressline_no_free(line), sblen);
/* now `line' itself can be reused as the bottom line */
@ -3067,6 +3138,10 @@ static void toggle_mode(Terminal *term, int mode, int query, bool state)
term->xterm_mouse = state ? 2 : 0;
term_update_raw_mouse_mode(term);
break;
case 1003: /* xterm mouse any-event tracking */
term->xterm_mouse = state ? 3 : 0;
term_update_raw_mouse_mode(term);
break;
case 1006: /* xterm extended mouse */
term->xterm_extended_mouse = state;
break;
@ -3398,8 +3473,7 @@ static strbuf *term_input_data_from_unicode(
}
}
char utf8_chr[6];
put_data(buf, utf8_chr, encode_utf8(utf8_chr, ch));
put_utf8_char(buf, ch);
}
} else {
/*
@ -7054,6 +7128,13 @@ void term_mouse(Terminal *term, Mouse_Button braw, Mouse_Button bcooked,
!(term->mouse_override && shift));
int default_seltype;
// Don't do anything if mouse movement events weren't requested;
// Note: return early to avoid doing all of this code on every mouse move
// event only to throw it away.
if (a == MA_MOVE && (!raw_mouse || term->xterm_mouse < 3)) {
return;
}
if (y < 0) {
y = 0;
if (a == MA_DRAG && !raw_mouse)
@ -7140,6 +7221,11 @@ void term_mouse(Terminal *term, Mouse_Button braw, Mouse_Button bcooked,
encstate = 0x41;
wheel = true;
break;
case MBT_NOTHING:
assert( a == MA_MOVE );
encstate = 0x03; // release; no buttons pressed
wheel = false;
break;
default:
return;
}
@ -7154,7 +7240,21 @@ void term_mouse(Terminal *term, Mouse_Button braw, Mouse_Button bcooked,
case MA_DRAG:
if (term->xterm_mouse == 1)
return;
encstate += 0x20;
encstate += 0x20; // motion indicator
break;
case MA_MOVE: // mouse move without buttons
assert( braw == MBT_NOTHING && bcooked == MBT_NOTHING );
if (term->xterm_mouse < 3)
return;
if (selpoint.x == term->raw_mouse_reported_x &&
selpoint.y == term->raw_mouse_reported_y)
return;
term->raw_mouse_reported_x = x;
term->raw_mouse_reported_y = y;
encstate += 0x20; // motion indicator
break;
case MA_RELEASE:
/* If multiple extensions are enabled, the xterm 1006 is used, so it's okay to check for only that */

View file

@ -155,6 +155,8 @@ struct terminal_tag {
bool xterm_extended_mouse;
bool urxvt_extended_mouse;
int mouse_is_down; /* used while tracking mouse buttons */
int raw_mouse_reported_x;
int raw_mouse_reported_y;
bool bracketed_paste, bracketed_paste_active;

View file

@ -1613,13 +1613,8 @@ static void process_line(BinarySource *in, strbuf *out)
#define FUNC_INNER(outtype, fname, realname, ...) \
DISPATCH_INTERNAL(#fname,handle_##fname);
#define ARG1(type, arg)
#define ARGN(type, arg)
#define VOID
#include "testcrypt-func.h"
#undef FUNC_INNER
#undef ARG
#undef VOID
#undef DISPATCH_INTERNAL

View file

@ -0,0 +1,189 @@
/*
* Autogenerated by read_ucd.py from The Unicode Standard 15.0.0
*
* Identify Unicode characters that are width-ambiguous: some regimes
* regard them as occupying two adjacent character cells in a terminal,
* and others do not.
*
* Used by utils/wcwidth.c.
*/
{0x00a1, 0x00a1},
{0x00a4, 0x00a4},
{0x00a7, 0x00a8},
{0x00aa, 0x00aa},
{0x00ad, 0x00ae},
{0x00b0, 0x00b4},
{0x00b6, 0x00ba},
{0x00bc, 0x00bf},
{0x00c6, 0x00c6},
{0x00d0, 0x00d0},
{0x00d7, 0x00d8},
{0x00de, 0x00e1},
{0x00e6, 0x00e6},
{0x00e8, 0x00ea},
{0x00ec, 0x00ed},
{0x00f0, 0x00f0},
{0x00f2, 0x00f3},
{0x00f7, 0x00fa},
{0x00fc, 0x00fc},
{0x00fe, 0x00fe},
{0x0101, 0x0101},
{0x0111, 0x0111},
{0x0113, 0x0113},
{0x011b, 0x011b},
{0x0126, 0x0127},
{0x012b, 0x012b},
{0x0131, 0x0133},
{0x0138, 0x0138},
{0x013f, 0x0142},
{0x0144, 0x0144},
{0x0148, 0x014b},
{0x014d, 0x014d},
{0x0152, 0x0153},
{0x0166, 0x0167},
{0x016b, 0x016b},
{0x01ce, 0x01ce},
{0x01d0, 0x01d0},
{0x01d2, 0x01d2},
{0x01d4, 0x01d4},
{0x01d6, 0x01d6},
{0x01d8, 0x01d8},
{0x01da, 0x01da},
{0x01dc, 0x01dc},
{0x0251, 0x0251},
{0x0261, 0x0261},
{0x02c4, 0x02c4},
{0x02c7, 0x02c7},
{0x02c9, 0x02cb},
{0x02cd, 0x02cd},
{0x02d0, 0x02d0},
{0x02d8, 0x02db},
{0x02dd, 0x02dd},
{0x02df, 0x02df},
{0x0300, 0x036f},
{0x0391, 0x03a1},
{0x03a3, 0x03a9},
{0x03b1, 0x03c1},
{0x03c3, 0x03c9},
{0x0401, 0x0401},
{0x0410, 0x044f},
{0x0451, 0x0451},
{0x2010, 0x2010},
{0x2013, 0x2016},
{0x2018, 0x2019},
{0x201c, 0x201d},
{0x2020, 0x2022},
{0x2024, 0x2027},
{0x2030, 0x2030},
{0x2032, 0x2033},
{0x2035, 0x2035},
{0x203b, 0x203b},
{0x203e, 0x203e},
{0x2074, 0x2074},
{0x207f, 0x207f},
{0x2081, 0x2084},
{0x20ac, 0x20ac},
{0x2103, 0x2103},
{0x2105, 0x2105},
{0x2109, 0x2109},
{0x2113, 0x2113},
{0x2116, 0x2116},
{0x2121, 0x2122},
{0x2126, 0x2126},
{0x212b, 0x212b},
{0x2153, 0x2154},
{0x215b, 0x215e},
{0x2160, 0x216b},
{0x2170, 0x2179},
{0x2189, 0x2189},
{0x2190, 0x2199},
{0x21b8, 0x21b9},
{0x21d2, 0x21d2},
{0x21d4, 0x21d4},
{0x21e7, 0x21e7},
{0x2200, 0x2200},
{0x2202, 0x2203},
{0x2207, 0x2208},
{0x220b, 0x220b},
{0x220f, 0x220f},
{0x2211, 0x2211},
{0x2215, 0x2215},
{0x221a, 0x221a},
{0x221d, 0x2220},
{0x2223, 0x2223},
{0x2225, 0x2225},
{0x2227, 0x222c},
{0x222e, 0x222e},
{0x2234, 0x2237},
{0x223c, 0x223d},
{0x2248, 0x2248},
{0x224c, 0x224c},
{0x2252, 0x2252},
{0x2260, 0x2261},
{0x2264, 0x2267},
{0x226a, 0x226b},
{0x226e, 0x226f},
{0x2282, 0x2283},
{0x2286, 0x2287},
{0x2295, 0x2295},
{0x2299, 0x2299},
{0x22a5, 0x22a5},
{0x22bf, 0x22bf},
{0x2312, 0x2312},
{0x2460, 0x24e9},
{0x24eb, 0x254b},
{0x2550, 0x2573},
{0x2580, 0x258f},
{0x2592, 0x2595},
{0x25a0, 0x25a1},
{0x25a3, 0x25a9},
{0x25b2, 0x25b3},
{0x25b6, 0x25b7},
{0x25bc, 0x25bd},
{0x25c0, 0x25c1},
{0x25c6, 0x25c8},
{0x25cb, 0x25cb},
{0x25ce, 0x25d1},
{0x25e2, 0x25e5},
{0x25ef, 0x25ef},
{0x2605, 0x2606},
{0x2609, 0x2609},
{0x260e, 0x260f},
{0x261c, 0x261c},
{0x261e, 0x261e},
{0x2640, 0x2640},
{0x2642, 0x2642},
{0x2660, 0x2661},
{0x2663, 0x2665},
{0x2667, 0x266a},
{0x266c, 0x266d},
{0x266f, 0x266f},
{0x269e, 0x269f},
{0x26bf, 0x26bf},
{0x26c6, 0x26cd},
{0x26cf, 0x26d3},
{0x26d5, 0x26e1},
{0x26e3, 0x26e3},
{0x26e8, 0x26e9},
{0x26eb, 0x26f1},
{0x26f4, 0x26f4},
{0x26f6, 0x26f9},
{0x26fb, 0x26fc},
{0x26fe, 0x26ff},
{0x273d, 0x273d},
{0x2776, 0x277f},
{0x2b56, 0x2b59},
{0x3248, 0x324f},
{0xe000, 0xf8ff},
{0xfe00, 0xfe0f},
{0xfffd, 0xfffd},
{0x1f100, 0x1f10a},
{0x1f110, 0x1f12d},
{0x1f130, 0x1f169},
{0x1f170, 0x1f18d},
{0x1f18f, 0x1f190},
{0x1f19b, 0x1f1ac},
{0xe0100, 0xe01ef},
{0xf0000, 0xffffd},
{0x100000, 0x10fffd},

139
unicode/bidi_brackets.h Normal file
View file

@ -0,0 +1,139 @@
/*
* Autogenerated by read_ucd.py from The Unicode Standard 15.0.0
*
* Identify Unicode characters that count as brackets for the purposes of
* bidirectional text layout. For each one, indicate whether it's an open
* or closed bracket, and identify up to two characters that can act as
* its counterpart.
*
* Used by terminal/bidi.c.
*/
{0x0028, {0x0029, 0x0000, BT_OPEN}},
{0x0029, {0x0028, 0x0000, BT_CLOSE}},
{0x005b, {0x005d, 0x0000, BT_OPEN}},
{0x005d, {0x005b, 0x0000, BT_CLOSE}},
{0x007b, {0x007d, 0x0000, BT_OPEN}},
{0x007d, {0x007b, 0x0000, BT_CLOSE}},
{0x0f3a, {0x0f3b, 0x0000, BT_OPEN}},
{0x0f3b, {0x0f3a, 0x0000, BT_CLOSE}},
{0x0f3c, {0x0f3d, 0x0000, BT_OPEN}},
{0x0f3d, {0x0f3c, 0x0000, BT_CLOSE}},
{0x169b, {0x169c, 0x0000, BT_OPEN}},
{0x169c, {0x169b, 0x0000, BT_CLOSE}},
{0x2045, {0x2046, 0x0000, BT_OPEN}},
{0x2046, {0x2045, 0x0000, BT_CLOSE}},
{0x207d, {0x207e, 0x0000, BT_OPEN}},
{0x207e, {0x207d, 0x0000, BT_CLOSE}},
{0x208d, {0x208e, 0x0000, BT_OPEN}},
{0x208e, {0x208d, 0x0000, BT_CLOSE}},
{0x2308, {0x2309, 0x0000, BT_OPEN}},
{0x2309, {0x2308, 0x0000, BT_CLOSE}},
{0x230a, {0x230b, 0x0000, BT_OPEN}},
{0x230b, {0x230a, 0x0000, BT_CLOSE}},
{0x2329, {0x232a, 0x3009, BT_OPEN}},
{0x232a, {0x2329, 0x3008, BT_CLOSE}},
{0x2768, {0x2769, 0x0000, BT_OPEN}},
{0x2769, {0x2768, 0x0000, BT_CLOSE}},
{0x276a, {0x276b, 0x0000, BT_OPEN}},
{0x276b, {0x276a, 0x0000, BT_CLOSE}},
{0x276c, {0x276d, 0x0000, BT_OPEN}},
{0x276d, {0x276c, 0x0000, BT_CLOSE}},
{0x276e, {0x276f, 0x0000, BT_OPEN}},
{0x276f, {0x276e, 0x0000, BT_CLOSE}},
{0x2770, {0x2771, 0x0000, BT_OPEN}},
{0x2771, {0x2770, 0x0000, BT_CLOSE}},
{0x2772, {0x2773, 0x0000, BT_OPEN}},
{0x2773, {0x2772, 0x0000, BT_CLOSE}},
{0x2774, {0x2775, 0x0000, BT_OPEN}},
{0x2775, {0x2774, 0x0000, BT_CLOSE}},
{0x27c5, {0x27c6, 0x0000, BT_OPEN}},
{0x27c6, {0x27c5, 0x0000, BT_CLOSE}},
{0x27e6, {0x27e7, 0x0000, BT_OPEN}},
{0x27e7, {0x27e6, 0x0000, BT_CLOSE}},
{0x27e8, {0x27e9, 0x0000, BT_OPEN}},
{0x27e9, {0x27e8, 0x0000, BT_CLOSE}},
{0x27ea, {0x27eb, 0x0000, BT_OPEN}},
{0x27eb, {0x27ea, 0x0000, BT_CLOSE}},
{0x27ec, {0x27ed, 0x0000, BT_OPEN}},
{0x27ed, {0x27ec, 0x0000, BT_CLOSE}},
{0x27ee, {0x27ef, 0x0000, BT_OPEN}},
{0x27ef, {0x27ee, 0x0000, BT_CLOSE}},
{0x2983, {0x2984, 0x0000, BT_OPEN}},
{0x2984, {0x2983, 0x0000, BT_CLOSE}},
{0x2985, {0x2986, 0x0000, BT_OPEN}},
{0x2986, {0x2985, 0x0000, BT_CLOSE}},
{0x2987, {0x2988, 0x0000, BT_OPEN}},
{0x2988, {0x2987, 0x0000, BT_CLOSE}},
{0x2989, {0x298a, 0x0000, BT_OPEN}},
{0x298a, {0x2989, 0x0000, BT_CLOSE}},
{0x298b, {0x298c, 0x0000, BT_OPEN}},
{0x298c, {0x298b, 0x0000, BT_CLOSE}},
{0x298d, {0x2990, 0x0000, BT_OPEN}},
{0x298e, {0x298f, 0x0000, BT_CLOSE}},
{0x298f, {0x298e, 0x0000, BT_OPEN}},
{0x2990, {0x298d, 0x0000, BT_CLOSE}},
{0x2991, {0x2992, 0x0000, BT_OPEN}},
{0x2992, {0x2991, 0x0000, BT_CLOSE}},
{0x2993, {0x2994, 0x0000, BT_OPEN}},
{0x2994, {0x2993, 0x0000, BT_CLOSE}},
{0x2995, {0x2996, 0x0000, BT_OPEN}},
{0x2996, {0x2995, 0x0000, BT_CLOSE}},
{0x2997, {0x2998, 0x0000, BT_OPEN}},
{0x2998, {0x2997, 0x0000, BT_CLOSE}},
{0x29d8, {0x29d9, 0x0000, BT_OPEN}},
{0x29d9, {0x29d8, 0x0000, BT_CLOSE}},
{0x29da, {0x29db, 0x0000, BT_OPEN}},
{0x29db, {0x29da, 0x0000, BT_CLOSE}},
{0x29fc, {0x29fd, 0x0000, BT_OPEN}},
{0x29fd, {0x29fc, 0x0000, BT_CLOSE}},
{0x2e22, {0x2e23, 0x0000, BT_OPEN}},
{0x2e23, {0x2e22, 0x0000, BT_CLOSE}},
{0x2e24, {0x2e25, 0x0000, BT_OPEN}},
{0x2e25, {0x2e24, 0x0000, BT_CLOSE}},
{0x2e26, {0x2e27, 0x0000, BT_OPEN}},
{0x2e27, {0x2e26, 0x0000, BT_CLOSE}},
{0x2e28, {0x2e29, 0x0000, BT_OPEN}},
{0x2e29, {0x2e28, 0x0000, BT_CLOSE}},
{0x2e55, {0x2e56, 0x0000, BT_OPEN}},
{0x2e56, {0x2e55, 0x0000, BT_CLOSE}},
{0x2e57, {0x2e58, 0x0000, BT_OPEN}},
{0x2e58, {0x2e57, 0x0000, BT_CLOSE}},
{0x2e59, {0x2e5a, 0x0000, BT_OPEN}},
{0x2e5a, {0x2e59, 0x0000, BT_CLOSE}},
{0x2e5b, {0x2e5c, 0x0000, BT_OPEN}},
{0x2e5c, {0x2e5b, 0x0000, BT_CLOSE}},
{0x3008, {0x3009, 0x232a, BT_OPEN}},
{0x3009, {0x3008, 0x2329, BT_CLOSE}},
{0x300a, {0x300b, 0x0000, BT_OPEN}},
{0x300b, {0x300a, 0x0000, BT_CLOSE}},
{0x300c, {0x300d, 0x0000, BT_OPEN}},
{0x300d, {0x300c, 0x0000, BT_CLOSE}},
{0x300e, {0x300f, 0x0000, BT_OPEN}},
{0x300f, {0x300e, 0x0000, BT_CLOSE}},
{0x3010, {0x3011, 0x0000, BT_OPEN}},
{0x3011, {0x3010, 0x0000, BT_CLOSE}},
{0x3014, {0x3015, 0x0000, BT_OPEN}},
{0x3015, {0x3014, 0x0000, BT_CLOSE}},
{0x3016, {0x3017, 0x0000, BT_OPEN}},
{0x3017, {0x3016, 0x0000, BT_CLOSE}},
{0x3018, {0x3019, 0x0000, BT_OPEN}},
{0x3019, {0x3018, 0x0000, BT_CLOSE}},
{0x301a, {0x301b, 0x0000, BT_OPEN}},
{0x301b, {0x301a, 0x0000, BT_CLOSE}},
{0xfe59, {0xfe5a, 0x0000, BT_OPEN}},
{0xfe5a, {0xfe59, 0x0000, BT_CLOSE}},
{0xfe5b, {0xfe5c, 0x0000, BT_OPEN}},
{0xfe5c, {0xfe5b, 0x0000, BT_CLOSE}},
{0xfe5d, {0xfe5e, 0x0000, BT_OPEN}},
{0xfe5e, {0xfe5d, 0x0000, BT_CLOSE}},
{0xff08, {0xff09, 0x0000, BT_OPEN}},
{0xff09, {0xff08, 0x0000, BT_CLOSE}},
{0xff3b, {0xff3d, 0x0000, BT_OPEN}},
{0xff3d, {0xff3b, 0x0000, BT_CLOSE}},
{0xff5b, {0xff5d, 0x0000, BT_OPEN}},
{0xff5d, {0xff5b, 0x0000, BT_CLOSE}},
{0xff5f, {0xff60, 0x0000, BT_OPEN}},
{0xff60, {0xff5f, 0x0000, BT_CLOSE}},
{0xff62, {0xff63, 0x0000, BT_OPEN}},
{0xff63, {0xff62, 0x0000, BT_CLOSE}},

437
unicode/bidi_mirror.h Normal file
View file

@ -0,0 +1,437 @@
/*
* Autogenerated by read_ucd.py from The Unicode Standard 15.0.0
*
* Map each Unicode character to its mirrored form when printing right to
* left.
*
* Used by terminal/bidi.c.
*/
{0x0028, 0x0029},
{0x0029, 0x0028},
{0x003c, 0x003e},
{0x003e, 0x003c},
{0x005b, 0x005d},
{0x005d, 0x005b},
{0x007b, 0x007d},
{0x007d, 0x007b},
{0x00ab, 0x00bb},
{0x00bb, 0x00ab},
{0x0f3a, 0x0f3b},
{0x0f3b, 0x0f3a},
{0x0f3c, 0x0f3d},
{0x0f3d, 0x0f3c},
{0x169b, 0x169c},
{0x169c, 0x169b},
{0x2039, 0x203a},
{0x203a, 0x2039},
{0x2045, 0x2046},
{0x2046, 0x2045},
{0x207d, 0x207e},
{0x207e, 0x207d},
{0x208d, 0x208e},
{0x208e, 0x208d},
{0x2208, 0x220b},
{0x2209, 0x220c},
{0x220a, 0x220d},
{0x220b, 0x2208},
{0x220c, 0x2209},
{0x220d, 0x220a},
{0x2215, 0x29f5},
{0x221f, 0x2bfe},
{0x2220, 0x29a3},
{0x2221, 0x299b},
{0x2222, 0x29a0},
{0x2224, 0x2aee},
{0x223c, 0x223d},
{0x223d, 0x223c},
{0x2243, 0x22cd},
{0x2245, 0x224c},
{0x224c, 0x2245},
{0x2252, 0x2253},
{0x2253, 0x2252},
{0x2254, 0x2255},
{0x2255, 0x2254},
{0x2264, 0x2265},
{0x2265, 0x2264},
{0x2266, 0x2267},
{0x2267, 0x2266},
{0x2268, 0x2269},
{0x2269, 0x2268},
{0x226a, 0x226b},
{0x226b, 0x226a},
{0x226e, 0x226f},
{0x226f, 0x226e},
{0x2270, 0x2271},
{0x2271, 0x2270},
{0x2272, 0x2273},
{0x2273, 0x2272},
{0x2274, 0x2275},
{0x2275, 0x2274},
{0x2276, 0x2277},
{0x2277, 0x2276},
{0x2278, 0x2279},
{0x2279, 0x2278},
{0x227a, 0x227b},
{0x227b, 0x227a},
{0x227c, 0x227d},
{0x227d, 0x227c},
{0x227e, 0x227f},
{0x227f, 0x227e},
{0x2280, 0x2281},
{0x2281, 0x2280},
{0x2282, 0x2283},
{0x2283, 0x2282},
{0x2284, 0x2285},
{0x2285, 0x2284},
{0x2286, 0x2287},
{0x2287, 0x2286},
{0x2288, 0x2289},
{0x2289, 0x2288},
{0x228a, 0x228b},
{0x228b, 0x228a},
{0x228f, 0x2290},
{0x2290, 0x228f},
{0x2291, 0x2292},
{0x2292, 0x2291},
{0x2298, 0x29b8},
{0x22a2, 0x22a3},
{0x22a3, 0x22a2},
{0x22a6, 0x2ade},
{0x22a8, 0x2ae4},
{0x22a9, 0x2ae3},
{0x22ab, 0x2ae5},
{0x22b0, 0x22b1},
{0x22b1, 0x22b0},
{0x22b2, 0x22b3},
{0x22b3, 0x22b2},
{0x22b4, 0x22b5},
{0x22b5, 0x22b4},
{0x22b6, 0x22b7},
{0x22b7, 0x22b6},
{0x22b8, 0x27dc},
{0x22c9, 0x22ca},
{0x22ca, 0x22c9},
{0x22cb, 0x22cc},
{0x22cc, 0x22cb},
{0x22cd, 0x2243},
{0x22d0, 0x22d1},
{0x22d1, 0x22d0},
{0x22d6, 0x22d7},
{0x22d7, 0x22d6},
{0x22d8, 0x22d9},
{0x22d9, 0x22d8},
{0x22da, 0x22db},
{0x22db, 0x22da},
{0x22dc, 0x22dd},
{0x22dd, 0x22dc},
{0x22de, 0x22df},
{0x22df, 0x22de},
{0x22e0, 0x22e1},
{0x22e1, 0x22e0},
{0x22e2, 0x22e3},
{0x22e3, 0x22e2},
{0x22e4, 0x22e5},
{0x22e5, 0x22e4},
{0x22e6, 0x22e7},
{0x22e7, 0x22e6},
{0x22e8, 0x22e9},
{0x22e9, 0x22e8},
{0x22ea, 0x22eb},
{0x22eb, 0x22ea},
{0x22ec, 0x22ed},
{0x22ed, 0x22ec},
{0x22f0, 0x22f1},
{0x22f1, 0x22f0},
{0x22f2, 0x22fa},
{0x22f3, 0x22fb},
{0x22f4, 0x22fc},
{0x22f6, 0x22fd},
{0x22f7, 0x22fe},
{0x22fa, 0x22f2},
{0x22fb, 0x22f3},
{0x22fc, 0x22f4},
{0x22fd, 0x22f6},
{0x22fe, 0x22f7},
{0x2308, 0x2309},
{0x2309, 0x2308},
{0x230a, 0x230b},
{0x230b, 0x230a},
{0x2329, 0x232a},
{0x232a, 0x2329},
{0x2768, 0x2769},
{0x2769, 0x2768},
{0x276a, 0x276b},
{0x276b, 0x276a},
{0x276c, 0x276d},
{0x276d, 0x276c},
{0x276e, 0x276f},
{0x276f, 0x276e},
{0x2770, 0x2771},
{0x2771, 0x2770},
{0x2772, 0x2773},
{0x2773, 0x2772},
{0x2774, 0x2775},
{0x2775, 0x2774},
{0x27c3, 0x27c4},
{0x27c4, 0x27c3},
{0x27c5, 0x27c6},
{0x27c6, 0x27c5},
{0x27c8, 0x27c9},
{0x27c9, 0x27c8},
{0x27cb, 0x27cd},
{0x27cd, 0x27cb},
{0x27d5, 0x27d6},
{0x27d6, 0x27d5},
{0x27dc, 0x22b8},
{0x27dd, 0x27de},
{0x27de, 0x27dd},
{0x27e2, 0x27e3},
{0x27e3, 0x27e2},
{0x27e4, 0x27e5},
{0x27e5, 0x27e4},
{0x27e6, 0x27e7},
{0x27e7, 0x27e6},
{0x27e8, 0x27e9},
{0x27e9, 0x27e8},
{0x27ea, 0x27eb},
{0x27eb, 0x27ea},
{0x27ec, 0x27ed},
{0x27ed, 0x27ec},
{0x27ee, 0x27ef},
{0x27ef, 0x27ee},
{0x2983, 0x2984},
{0x2984, 0x2983},
{0x2985, 0x2986},
{0x2986, 0x2985},
{0x2987, 0x2988},
{0x2988, 0x2987},
{0x2989, 0x298a},
{0x298a, 0x2989},
{0x298b, 0x298c},
{0x298c, 0x298b},
{0x298d, 0x2990},
{0x298e, 0x298f},
{0x298f, 0x298e},
{0x2990, 0x298d},
{0x2991, 0x2992},
{0x2992, 0x2991},
{0x2993, 0x2994},
{0x2994, 0x2993},
{0x2995, 0x2996},
{0x2996, 0x2995},
{0x2997, 0x2998},
{0x2998, 0x2997},
{0x299b, 0x2221},
{0x29a0, 0x2222},
{0x29a3, 0x2220},
{0x29a4, 0x29a5},
{0x29a5, 0x29a4},
{0x29a8, 0x29a9},
{0x29a9, 0x29a8},
{0x29aa, 0x29ab},
{0x29ab, 0x29aa},
{0x29ac, 0x29ad},
{0x29ad, 0x29ac},
{0x29ae, 0x29af},
{0x29af, 0x29ae},
{0x29b8, 0x2298},
{0x29c0, 0x29c1},
{0x29c1, 0x29c0},
{0x29c4, 0x29c5},
{0x29c5, 0x29c4},
{0x29cf, 0x29d0},
{0x29d0, 0x29cf},
{0x29d1, 0x29d2},
{0x29d2, 0x29d1},
{0x29d4, 0x29d5},
{0x29d5, 0x29d4},
{0x29d8, 0x29d9},
{0x29d9, 0x29d8},
{0x29da, 0x29db},
{0x29db, 0x29da},
{0x29e8, 0x29e9},
{0x29e9, 0x29e8},
{0x29f5, 0x2215},
{0x29f8, 0x29f9},
{0x29f9, 0x29f8},
{0x29fc, 0x29fd},
{0x29fd, 0x29fc},
{0x2a2b, 0x2a2c},
{0x2a2c, 0x2a2b},
{0x2a2d, 0x2a2e},
{0x2a2e, 0x2a2d},
{0x2a34, 0x2a35},
{0x2a35, 0x2a34},
{0x2a3c, 0x2a3d},
{0x2a3d, 0x2a3c},
{0x2a64, 0x2a65},
{0x2a65, 0x2a64},
{0x2a79, 0x2a7a},
{0x2a7a, 0x2a79},
{0x2a7b, 0x2a7c},
{0x2a7c, 0x2a7b},
{0x2a7d, 0x2a7e},
{0x2a7e, 0x2a7d},
{0x2a7f, 0x2a80},
{0x2a80, 0x2a7f},
{0x2a81, 0x2a82},
{0x2a82, 0x2a81},
{0x2a83, 0x2a84},
{0x2a84, 0x2a83},
{0x2a85, 0x2a86},
{0x2a86, 0x2a85},
{0x2a87, 0x2a88},
{0x2a88, 0x2a87},
{0x2a89, 0x2a8a},
{0x2a8a, 0x2a89},
{0x2a8b, 0x2a8c},
{0x2a8c, 0x2a8b},
{0x2a8d, 0x2a8e},
{0x2a8e, 0x2a8d},
{0x2a8f, 0x2a90},
{0x2a90, 0x2a8f},
{0x2a91, 0x2a92},
{0x2a92, 0x2a91},
{0x2a93, 0x2a94},
{0x2a94, 0x2a93},
{0x2a95, 0x2a96},
{0x2a96, 0x2a95},
{0x2a97, 0x2a98},
{0x2a98, 0x2a97},
{0x2a99, 0x2a9a},
{0x2a9a, 0x2a99},
{0x2a9b, 0x2a9c},
{0x2a9c, 0x2a9b},
{0x2a9d, 0x2a9e},
{0x2a9e, 0x2a9d},
{0x2a9f, 0x2aa0},
{0x2aa0, 0x2a9f},
{0x2aa1, 0x2aa2},
{0x2aa2, 0x2aa1},
{0x2aa6, 0x2aa7},
{0x2aa7, 0x2aa6},
{0x2aa8, 0x2aa9},
{0x2aa9, 0x2aa8},
{0x2aaa, 0x2aab},
{0x2aab, 0x2aaa},
{0x2aac, 0x2aad},
{0x2aad, 0x2aac},
{0x2aaf, 0x2ab0},
{0x2ab0, 0x2aaf},
{0x2ab1, 0x2ab2},
{0x2ab2, 0x2ab1},
{0x2ab3, 0x2ab4},
{0x2ab4, 0x2ab3},
{0x2ab5, 0x2ab6},
{0x2ab6, 0x2ab5},
{0x2ab7, 0x2ab8},
{0x2ab8, 0x2ab7},
{0x2ab9, 0x2aba},
{0x2aba, 0x2ab9},
{0x2abb, 0x2abc},
{0x2abc, 0x2abb},
{0x2abd, 0x2abe},
{0x2abe, 0x2abd},
{0x2abf, 0x2ac0},
{0x2ac0, 0x2abf},
{0x2ac1, 0x2ac2},
{0x2ac2, 0x2ac1},
{0x2ac3, 0x2ac4},
{0x2ac4, 0x2ac3},
{0x2ac5, 0x2ac6},
{0x2ac6, 0x2ac5},
{0x2ac7, 0x2ac8},
{0x2ac8, 0x2ac7},
{0x2ac9, 0x2aca},
{0x2aca, 0x2ac9},
{0x2acb, 0x2acc},
{0x2acc, 0x2acb},
{0x2acd, 0x2ace},
{0x2ace, 0x2acd},
{0x2acf, 0x2ad0},
{0x2ad0, 0x2acf},
{0x2ad1, 0x2ad2},
{0x2ad2, 0x2ad1},
{0x2ad3, 0x2ad4},
{0x2ad4, 0x2ad3},
{0x2ad5, 0x2ad6},
{0x2ad6, 0x2ad5},
{0x2ade, 0x22a6},
{0x2ae3, 0x22a9},
{0x2ae4, 0x22a8},
{0x2ae5, 0x22ab},
{0x2aec, 0x2aed},
{0x2aed, 0x2aec},
{0x2aee, 0x2224},
{0x2af7, 0x2af8},
{0x2af8, 0x2af7},
{0x2af9, 0x2afa},
{0x2afa, 0x2af9},
{0x2bfe, 0x221f},
{0x2e02, 0x2e03},
{0x2e03, 0x2e02},
{0x2e04, 0x2e05},
{0x2e05, 0x2e04},
{0x2e09, 0x2e0a},
{0x2e0a, 0x2e09},
{0x2e0c, 0x2e0d},
{0x2e0d, 0x2e0c},
{0x2e1c, 0x2e1d},
{0x2e1d, 0x2e1c},
{0x2e20, 0x2e21},
{0x2e21, 0x2e20},
{0x2e22, 0x2e23},
{0x2e23, 0x2e22},
{0x2e24, 0x2e25},
{0x2e25, 0x2e24},
{0x2e26, 0x2e27},
{0x2e27, 0x2e26},
{0x2e28, 0x2e29},
{0x2e29, 0x2e28},
{0x2e55, 0x2e56},
{0x2e56, 0x2e55},
{0x2e57, 0x2e58},
{0x2e58, 0x2e57},
{0x2e59, 0x2e5a},
{0x2e5a, 0x2e59},
{0x2e5b, 0x2e5c},
{0x2e5c, 0x2e5b},
{0x3008, 0x3009},
{0x3009, 0x3008},
{0x300a, 0x300b},
{0x300b, 0x300a},
{0x300c, 0x300d},
{0x300d, 0x300c},
{0x300e, 0x300f},
{0x300f, 0x300e},
{0x3010, 0x3011},
{0x3011, 0x3010},
{0x3014, 0x3015},
{0x3015, 0x3014},
{0x3016, 0x3017},
{0x3017, 0x3016},
{0x3018, 0x3019},
{0x3019, 0x3018},
{0x301a, 0x301b},
{0x301b, 0x301a},
{0xfe59, 0xfe5a},
{0xfe5a, 0xfe59},
{0xfe5b, 0xfe5c},
{0xfe5c, 0xfe5b},
{0xfe5d, 0xfe5e},
{0xfe5e, 0xfe5d},
{0xfe64, 0xfe65},
{0xfe65, 0xfe64},
{0xff08, 0xff09},
{0xff09, 0xff08},
{0xff1c, 0xff1e},
{0xff1e, 0xff1c},
{0xff3b, 0xff3d},
{0xff3d, 0xff3b},
{0xff5b, 0xff5d},
{0xff5d, 0xff5b},
{0xff5f, 0xff60},
{0xff60, 0xff5f},
{0xff62, 0xff63},
{0xff63, 0xff62},

1331
unicode/bidi_type.h Normal file

File diff suppressed because it is too large Load diff

950
unicode/canonical_comp.h Normal file
View file

@ -0,0 +1,950 @@
/*
* Autogenerated by read_ucd.py from The Unicode Standard 15.0.0
*
* List the pairs of Unicode characters that canonically recompose to a
* single character in NFC.
*
* Used by utils/unicode-norm.c.
*/
{0x003c, 0x0338, 0x226e},
{0x003d, 0x0338, 0x2260},
{0x003e, 0x0338, 0x226f},
{0x0041, 0x0300, 0x00c0},
{0x0041, 0x0301, 0x00c1},
{0x0041, 0x0302, 0x00c2},
{0x0041, 0x0303, 0x00c3},
{0x0041, 0x0304, 0x0100},
{0x0041, 0x0306, 0x0102},
{0x0041, 0x0307, 0x0226},
{0x0041, 0x0308, 0x00c4},
{0x0041, 0x0309, 0x1ea2},
{0x0041, 0x030a, 0x00c5},
{0x0041, 0x030c, 0x01cd},
{0x0041, 0x030f, 0x0200},
{0x0041, 0x0311, 0x0202},
{0x0041, 0x0323, 0x1ea0},
{0x0041, 0x0325, 0x1e00},
{0x0041, 0x0328, 0x0104},
{0x0042, 0x0307, 0x1e02},
{0x0042, 0x0323, 0x1e04},
{0x0042, 0x0331, 0x1e06},
{0x0043, 0x0301, 0x0106},
{0x0043, 0x0302, 0x0108},
{0x0043, 0x0307, 0x010a},
{0x0043, 0x030c, 0x010c},
{0x0043, 0x0327, 0x00c7},
{0x0044, 0x0307, 0x1e0a},
{0x0044, 0x030c, 0x010e},
{0x0044, 0x0323, 0x1e0c},
{0x0044, 0x0327, 0x1e10},
{0x0044, 0x032d, 0x1e12},
{0x0044, 0x0331, 0x1e0e},
{0x0045, 0x0300, 0x00c8},
{0x0045, 0x0301, 0x00c9},
{0x0045, 0x0302, 0x00ca},
{0x0045, 0x0303, 0x1ebc},
{0x0045, 0x0304, 0x0112},
{0x0045, 0x0306, 0x0114},
{0x0045, 0x0307, 0x0116},
{0x0045, 0x0308, 0x00cb},
{0x0045, 0x0309, 0x1eba},
{0x0045, 0x030c, 0x011a},
{0x0045, 0x030f, 0x0204},
{0x0045, 0x0311, 0x0206},
{0x0045, 0x0323, 0x1eb8},
{0x0045, 0x0327, 0x0228},
{0x0045, 0x0328, 0x0118},
{0x0045, 0x032d, 0x1e18},
{0x0045, 0x0330, 0x1e1a},
{0x0046, 0x0307, 0x1e1e},
{0x0047, 0x0301, 0x01f4},
{0x0047, 0x0302, 0x011c},
{0x0047, 0x0304, 0x1e20},
{0x0047, 0x0306, 0x011e},
{0x0047, 0x0307, 0x0120},
{0x0047, 0x030c, 0x01e6},
{0x0047, 0x0327, 0x0122},
{0x0048, 0x0302, 0x0124},
{0x0048, 0x0307, 0x1e22},
{0x0048, 0x0308, 0x1e26},
{0x0048, 0x030c, 0x021e},
{0x0048, 0x0323, 0x1e24},
{0x0048, 0x0327, 0x1e28},
{0x0048, 0x032e, 0x1e2a},
{0x0049, 0x0300, 0x00cc},
{0x0049, 0x0301, 0x00cd},
{0x0049, 0x0302, 0x00ce},
{0x0049, 0x0303, 0x0128},
{0x0049, 0x0304, 0x012a},
{0x0049, 0x0306, 0x012c},
{0x0049, 0x0307, 0x0130},
{0x0049, 0x0308, 0x00cf},
{0x0049, 0x0309, 0x1ec8},
{0x0049, 0x030c, 0x01cf},
{0x0049, 0x030f, 0x0208},
{0x0049, 0x0311, 0x020a},
{0x0049, 0x0323, 0x1eca},
{0x0049, 0x0328, 0x012e},
{0x0049, 0x0330, 0x1e2c},
{0x004a, 0x0302, 0x0134},
{0x004b, 0x0301, 0x1e30},
{0x004b, 0x030c, 0x01e8},
{0x004b, 0x0323, 0x1e32},
{0x004b, 0x0327, 0x0136},
{0x004b, 0x0331, 0x1e34},
{0x004c, 0x0301, 0x0139},
{0x004c, 0x030c, 0x013d},
{0x004c, 0x0323, 0x1e36},
{0x004c, 0x0327, 0x013b},
{0x004c, 0x032d, 0x1e3c},
{0x004c, 0x0331, 0x1e3a},
{0x004d, 0x0301, 0x1e3e},
{0x004d, 0x0307, 0x1e40},
{0x004d, 0x0323, 0x1e42},
{0x004e, 0x0300, 0x01f8},
{0x004e, 0x0301, 0x0143},
{0x004e, 0x0303, 0x00d1},
{0x004e, 0x0307, 0x1e44},
{0x004e, 0x030c, 0x0147},
{0x004e, 0x0323, 0x1e46},
{0x004e, 0x0327, 0x0145},
{0x004e, 0x032d, 0x1e4a},
{0x004e, 0x0331, 0x1e48},
{0x004f, 0x0300, 0x00d2},
{0x004f, 0x0301, 0x00d3},
{0x004f, 0x0302, 0x00d4},
{0x004f, 0x0303, 0x00d5},
{0x004f, 0x0304, 0x014c},
{0x004f, 0x0306, 0x014e},
{0x004f, 0x0307, 0x022e},
{0x004f, 0x0308, 0x00d6},
{0x004f, 0x0309, 0x1ece},
{0x004f, 0x030b, 0x0150},
{0x004f, 0x030c, 0x01d1},
{0x004f, 0x030f, 0x020c},
{0x004f, 0x0311, 0x020e},
{0x004f, 0x031b, 0x01a0},
{0x004f, 0x0323, 0x1ecc},
{0x004f, 0x0328, 0x01ea},
{0x0050, 0x0301, 0x1e54},
{0x0050, 0x0307, 0x1e56},
{0x0052, 0x0301, 0x0154},
{0x0052, 0x0307, 0x1e58},
{0x0052, 0x030c, 0x0158},
{0x0052, 0x030f, 0x0210},
{0x0052, 0x0311, 0x0212},
{0x0052, 0x0323, 0x1e5a},
{0x0052, 0x0327, 0x0156},
{0x0052, 0x0331, 0x1e5e},
{0x0053, 0x0301, 0x015a},
{0x0053, 0x0302, 0x015c},
{0x0053, 0x0307, 0x1e60},
{0x0053, 0x030c, 0x0160},
{0x0053, 0x0323, 0x1e62},
{0x0053, 0x0326, 0x0218},
{0x0053, 0x0327, 0x015e},
{0x0054, 0x0307, 0x1e6a},
{0x0054, 0x030c, 0x0164},
{0x0054, 0x0323, 0x1e6c},
{0x0054, 0x0326, 0x021a},
{0x0054, 0x0327, 0x0162},
{0x0054, 0x032d, 0x1e70},
{0x0054, 0x0331, 0x1e6e},
{0x0055, 0x0300, 0x00d9},
{0x0055, 0x0301, 0x00da},
{0x0055, 0x0302, 0x00db},
{0x0055, 0x0303, 0x0168},
{0x0055, 0x0304, 0x016a},
{0x0055, 0x0306, 0x016c},
{0x0055, 0x0308, 0x00dc},
{0x0055, 0x0309, 0x1ee6},
{0x0055, 0x030a, 0x016e},
{0x0055, 0x030b, 0x0170},
{0x0055, 0x030c, 0x01d3},
{0x0055, 0x030f, 0x0214},
{0x0055, 0x0311, 0x0216},
{0x0055, 0x031b, 0x01af},
{0x0055, 0x0323, 0x1ee4},
{0x0055, 0x0324, 0x1e72},
{0x0055, 0x0328, 0x0172},
{0x0055, 0x032d, 0x1e76},
{0x0055, 0x0330, 0x1e74},
{0x0056, 0x0303, 0x1e7c},
{0x0056, 0x0323, 0x1e7e},
{0x0057, 0x0300, 0x1e80},
{0x0057, 0x0301, 0x1e82},
{0x0057, 0x0302, 0x0174},
{0x0057, 0x0307, 0x1e86},
{0x0057, 0x0308, 0x1e84},
{0x0057, 0x0323, 0x1e88},
{0x0058, 0x0307, 0x1e8a},
{0x0058, 0x0308, 0x1e8c},
{0x0059, 0x0300, 0x1ef2},
{0x0059, 0x0301, 0x00dd},
{0x0059, 0x0302, 0x0176},
{0x0059, 0x0303, 0x1ef8},
{0x0059, 0x0304, 0x0232},
{0x0059, 0x0307, 0x1e8e},
{0x0059, 0x0308, 0x0178},
{0x0059, 0x0309, 0x1ef6},
{0x0059, 0x0323, 0x1ef4},
{0x005a, 0x0301, 0x0179},
{0x005a, 0x0302, 0x1e90},
{0x005a, 0x0307, 0x017b},
{0x005a, 0x030c, 0x017d},
{0x005a, 0x0323, 0x1e92},
{0x005a, 0x0331, 0x1e94},
{0x0061, 0x0300, 0x00e0},
{0x0061, 0x0301, 0x00e1},
{0x0061, 0x0302, 0x00e2},
{0x0061, 0x0303, 0x00e3},
{0x0061, 0x0304, 0x0101},
{0x0061, 0x0306, 0x0103},
{0x0061, 0x0307, 0x0227},
{0x0061, 0x0308, 0x00e4},
{0x0061, 0x0309, 0x1ea3},
{0x0061, 0x030a, 0x00e5},
{0x0061, 0x030c, 0x01ce},
{0x0061, 0x030f, 0x0201},
{0x0061, 0x0311, 0x0203},
{0x0061, 0x0323, 0x1ea1},
{0x0061, 0x0325, 0x1e01},
{0x0061, 0x0328, 0x0105},
{0x0062, 0x0307, 0x1e03},
{0x0062, 0x0323, 0x1e05},
{0x0062, 0x0331, 0x1e07},
{0x0063, 0x0301, 0x0107},
{0x0063, 0x0302, 0x0109},
{0x0063, 0x0307, 0x010b},
{0x0063, 0x030c, 0x010d},
{0x0063, 0x0327, 0x00e7},
{0x0064, 0x0307, 0x1e0b},
{0x0064, 0x030c, 0x010f},
{0x0064, 0x0323, 0x1e0d},
{0x0064, 0x0327, 0x1e11},
{0x0064, 0x032d, 0x1e13},
{0x0064, 0x0331, 0x1e0f},
{0x0065, 0x0300, 0x00e8},
{0x0065, 0x0301, 0x00e9},
{0x0065, 0x0302, 0x00ea},
{0x0065, 0x0303, 0x1ebd},
{0x0065, 0x0304, 0x0113},
{0x0065, 0x0306, 0x0115},
{0x0065, 0x0307, 0x0117},
{0x0065, 0x0308, 0x00eb},
{0x0065, 0x0309, 0x1ebb},
{0x0065, 0x030c, 0x011b},
{0x0065, 0x030f, 0x0205},
{0x0065, 0x0311, 0x0207},
{0x0065, 0x0323, 0x1eb9},
{0x0065, 0x0327, 0x0229},
{0x0065, 0x0328, 0x0119},
{0x0065, 0x032d, 0x1e19},
{0x0065, 0x0330, 0x1e1b},
{0x0066, 0x0307, 0x1e1f},
{0x0067, 0x0301, 0x01f5},
{0x0067, 0x0302, 0x011d},
{0x0067, 0x0304, 0x1e21},
{0x0067, 0x0306, 0x011f},
{0x0067, 0x0307, 0x0121},
{0x0067, 0x030c, 0x01e7},
{0x0067, 0x0327, 0x0123},
{0x0068, 0x0302, 0x0125},
{0x0068, 0x0307, 0x1e23},
{0x0068, 0x0308, 0x1e27},
{0x0068, 0x030c, 0x021f},
{0x0068, 0x0323, 0x1e25},
{0x0068, 0x0327, 0x1e29},
{0x0068, 0x032e, 0x1e2b},
{0x0068, 0x0331, 0x1e96},
{0x0069, 0x0300, 0x00ec},
{0x0069, 0x0301, 0x00ed},
{0x0069, 0x0302, 0x00ee},
{0x0069, 0x0303, 0x0129},
{0x0069, 0x0304, 0x012b},
{0x0069, 0x0306, 0x012d},
{0x0069, 0x0308, 0x00ef},
{0x0069, 0x0309, 0x1ec9},
{0x0069, 0x030c, 0x01d0},
{0x0069, 0x030f, 0x0209},
{0x0069, 0x0311, 0x020b},
{0x0069, 0x0323, 0x1ecb},
{0x0069, 0x0328, 0x012f},
{0x0069, 0x0330, 0x1e2d},
{0x006a, 0x0302, 0x0135},
{0x006a, 0x030c, 0x01f0},
{0x006b, 0x0301, 0x1e31},
{0x006b, 0x030c, 0x01e9},
{0x006b, 0x0323, 0x1e33},
{0x006b, 0x0327, 0x0137},
{0x006b, 0x0331, 0x1e35},
{0x006c, 0x0301, 0x013a},
{0x006c, 0x030c, 0x013e},
{0x006c, 0x0323, 0x1e37},
{0x006c, 0x0327, 0x013c},
{0x006c, 0x032d, 0x1e3d},
{0x006c, 0x0331, 0x1e3b},
{0x006d, 0x0301, 0x1e3f},
{0x006d, 0x0307, 0x1e41},
{0x006d, 0x0323, 0x1e43},
{0x006e, 0x0300, 0x01f9},
{0x006e, 0x0301, 0x0144},
{0x006e, 0x0303, 0x00f1},
{0x006e, 0x0307, 0x1e45},
{0x006e, 0x030c, 0x0148},
{0x006e, 0x0323, 0x1e47},
{0x006e, 0x0327, 0x0146},
{0x006e, 0x032d, 0x1e4b},
{0x006e, 0x0331, 0x1e49},
{0x006f, 0x0300, 0x00f2},
{0x006f, 0x0301, 0x00f3},
{0x006f, 0x0302, 0x00f4},
{0x006f, 0x0303, 0x00f5},
{0x006f, 0x0304, 0x014d},
{0x006f, 0x0306, 0x014f},
{0x006f, 0x0307, 0x022f},
{0x006f, 0x0308, 0x00f6},
{0x006f, 0x0309, 0x1ecf},
{0x006f, 0x030b, 0x0151},
{0x006f, 0x030c, 0x01d2},
{0x006f, 0x030f, 0x020d},
{0x006f, 0x0311, 0x020f},
{0x006f, 0x031b, 0x01a1},
{0x006f, 0x0323, 0x1ecd},
{0x006f, 0x0328, 0x01eb},
{0x0070, 0x0301, 0x1e55},
{0x0070, 0x0307, 0x1e57},
{0x0072, 0x0301, 0x0155},
{0x0072, 0x0307, 0x1e59},
{0x0072, 0x030c, 0x0159},
{0x0072, 0x030f, 0x0211},
{0x0072, 0x0311, 0x0213},
{0x0072, 0x0323, 0x1e5b},
{0x0072, 0x0327, 0x0157},
{0x0072, 0x0331, 0x1e5f},
{0x0073, 0x0301, 0x015b},
{0x0073, 0x0302, 0x015d},
{0x0073, 0x0307, 0x1e61},
{0x0073, 0x030c, 0x0161},
{0x0073, 0x0323, 0x1e63},
{0x0073, 0x0326, 0x0219},
{0x0073, 0x0327, 0x015f},
{0x0074, 0x0307, 0x1e6b},
{0x0074, 0x0308, 0x1e97},
{0x0074, 0x030c, 0x0165},
{0x0074, 0x0323, 0x1e6d},
{0x0074, 0x0326, 0x021b},
{0x0074, 0x0327, 0x0163},
{0x0074, 0x032d, 0x1e71},
{0x0074, 0x0331, 0x1e6f},
{0x0075, 0x0300, 0x00f9},
{0x0075, 0x0301, 0x00fa},
{0x0075, 0x0302, 0x00fb},
{0x0075, 0x0303, 0x0169},
{0x0075, 0x0304, 0x016b},
{0x0075, 0x0306, 0x016d},
{0x0075, 0x0308, 0x00fc},
{0x0075, 0x0309, 0x1ee7},
{0x0075, 0x030a, 0x016f},
{0x0075, 0x030b, 0x0171},
{0x0075, 0x030c, 0x01d4},
{0x0075, 0x030f, 0x0215},
{0x0075, 0x0311, 0x0217},
{0x0075, 0x031b, 0x01b0},
{0x0075, 0x0323, 0x1ee5},
{0x0075, 0x0324, 0x1e73},
{0x0075, 0x0328, 0x0173},
{0x0075, 0x032d, 0x1e77},
{0x0075, 0x0330, 0x1e75},
{0x0076, 0x0303, 0x1e7d},
{0x0076, 0x0323, 0x1e7f},
{0x0077, 0x0300, 0x1e81},
{0x0077, 0x0301, 0x1e83},
{0x0077, 0x0302, 0x0175},
{0x0077, 0x0307, 0x1e87},
{0x0077, 0x0308, 0x1e85},
{0x0077, 0x030a, 0x1e98},
{0x0077, 0x0323, 0x1e89},
{0x0078, 0x0307, 0x1e8b},
{0x0078, 0x0308, 0x1e8d},
{0x0079, 0x0300, 0x1ef3},
{0x0079, 0x0301, 0x00fd},
{0x0079, 0x0302, 0x0177},
{0x0079, 0x0303, 0x1ef9},
{0x0079, 0x0304, 0x0233},
{0x0079, 0x0307, 0x1e8f},
{0x0079, 0x0308, 0x00ff},
{0x0079, 0x0309, 0x1ef7},
{0x0079, 0x030a, 0x1e99},
{0x0079, 0x0323, 0x1ef5},
{0x007a, 0x0301, 0x017a},
{0x007a, 0x0302, 0x1e91},
{0x007a, 0x0307, 0x017c},
{0x007a, 0x030c, 0x017e},
{0x007a, 0x0323, 0x1e93},
{0x007a, 0x0331, 0x1e95},
{0x00a8, 0x0300, 0x1fed},
{0x00a8, 0x0301, 0x0385},
{0x00a8, 0x0342, 0x1fc1},
{0x00c2, 0x0300, 0x1ea6},
{0x00c2, 0x0301, 0x1ea4},
{0x00c2, 0x0303, 0x1eaa},
{0x00c2, 0x0309, 0x1ea8},
{0x00c4, 0x0304, 0x01de},
{0x00c5, 0x0301, 0x01fa},
{0x00c6, 0x0301, 0x01fc},
{0x00c6, 0x0304, 0x01e2},
{0x00c7, 0x0301, 0x1e08},
{0x00ca, 0x0300, 0x1ec0},
{0x00ca, 0x0301, 0x1ebe},
{0x00ca, 0x0303, 0x1ec4},
{0x00ca, 0x0309, 0x1ec2},
{0x00cf, 0x0301, 0x1e2e},
{0x00d4, 0x0300, 0x1ed2},
{0x00d4, 0x0301, 0x1ed0},
{0x00d4, 0x0303, 0x1ed6},
{0x00d4, 0x0309, 0x1ed4},
{0x00d5, 0x0301, 0x1e4c},
{0x00d5, 0x0304, 0x022c},
{0x00d5, 0x0308, 0x1e4e},
{0x00d6, 0x0304, 0x022a},
{0x00d8, 0x0301, 0x01fe},
{0x00dc, 0x0300, 0x01db},
{0x00dc, 0x0301, 0x01d7},
{0x00dc, 0x0304, 0x01d5},
{0x00dc, 0x030c, 0x01d9},
{0x00e2, 0x0300, 0x1ea7},
{0x00e2, 0x0301, 0x1ea5},
{0x00e2, 0x0303, 0x1eab},
{0x00e2, 0x0309, 0x1ea9},
{0x00e4, 0x0304, 0x01df},
{0x00e5, 0x0301, 0x01fb},
{0x00e6, 0x0301, 0x01fd},
{0x00e6, 0x0304, 0x01e3},
{0x00e7, 0x0301, 0x1e09},
{0x00ea, 0x0300, 0x1ec1},
{0x00ea, 0x0301, 0x1ebf},
{0x00ea, 0x0303, 0x1ec5},
{0x00ea, 0x0309, 0x1ec3},
{0x00ef, 0x0301, 0x1e2f},
{0x00f4, 0x0300, 0x1ed3},
{0x00f4, 0x0301, 0x1ed1},
{0x00f4, 0x0303, 0x1ed7},
{0x00f4, 0x0309, 0x1ed5},
{0x00f5, 0x0301, 0x1e4d},
{0x00f5, 0x0304, 0x022d},
{0x00f5, 0x0308, 0x1e4f},
{0x00f6, 0x0304, 0x022b},
{0x00f8, 0x0301, 0x01ff},
{0x00fc, 0x0300, 0x01dc},
{0x00fc, 0x0301, 0x01d8},
{0x00fc, 0x0304, 0x01d6},
{0x00fc, 0x030c, 0x01da},
{0x0102, 0x0300, 0x1eb0},
{0x0102, 0x0301, 0x1eae},
{0x0102, 0x0303, 0x1eb4},
{0x0102, 0x0309, 0x1eb2},
{0x0103, 0x0300, 0x1eb1},
{0x0103, 0x0301, 0x1eaf},
{0x0103, 0x0303, 0x1eb5},
{0x0103, 0x0309, 0x1eb3},
{0x0112, 0x0300, 0x1e14},
{0x0112, 0x0301, 0x1e16},
{0x0113, 0x0300, 0x1e15},
{0x0113, 0x0301, 0x1e17},
{0x014c, 0x0300, 0x1e50},
{0x014c, 0x0301, 0x1e52},
{0x014d, 0x0300, 0x1e51},
{0x014d, 0x0301, 0x1e53},
{0x015a, 0x0307, 0x1e64},
{0x015b, 0x0307, 0x1e65},
{0x0160, 0x0307, 0x1e66},
{0x0161, 0x0307, 0x1e67},
{0x0168, 0x0301, 0x1e78},
{0x0169, 0x0301, 0x1e79},
{0x016a, 0x0308, 0x1e7a},
{0x016b, 0x0308, 0x1e7b},
{0x017f, 0x0307, 0x1e9b},
{0x01a0, 0x0300, 0x1edc},
{0x01a0, 0x0301, 0x1eda},
{0x01a0, 0x0303, 0x1ee0},
{0x01a0, 0x0309, 0x1ede},
{0x01a0, 0x0323, 0x1ee2},
{0x01a1, 0x0300, 0x1edd},
{0x01a1, 0x0301, 0x1edb},
{0x01a1, 0x0303, 0x1ee1},
{0x01a1, 0x0309, 0x1edf},
{0x01a1, 0x0323, 0x1ee3},
{0x01af, 0x0300, 0x1eea},
{0x01af, 0x0301, 0x1ee8},
{0x01af, 0x0303, 0x1eee},
{0x01af, 0x0309, 0x1eec},
{0x01af, 0x0323, 0x1ef0},
{0x01b0, 0x0300, 0x1eeb},
{0x01b0, 0x0301, 0x1ee9},
{0x01b0, 0x0303, 0x1eef},
{0x01b0, 0x0309, 0x1eed},
{0x01b0, 0x0323, 0x1ef1},
{0x01b7, 0x030c, 0x01ee},
{0x01ea, 0x0304, 0x01ec},
{0x01eb, 0x0304, 0x01ed},
{0x0226, 0x0304, 0x01e0},
{0x0227, 0x0304, 0x01e1},
{0x0228, 0x0306, 0x1e1c},
{0x0229, 0x0306, 0x1e1d},
{0x022e, 0x0304, 0x0230},
{0x022f, 0x0304, 0x0231},
{0x0292, 0x030c, 0x01ef},
{0x0391, 0x0300, 0x1fba},
{0x0391, 0x0301, 0x0386},
{0x0391, 0x0304, 0x1fb9},
{0x0391, 0x0306, 0x1fb8},
{0x0391, 0x0313, 0x1f08},
{0x0391, 0x0314, 0x1f09},
{0x0391, 0x0345, 0x1fbc},
{0x0395, 0x0300, 0x1fc8},
{0x0395, 0x0301, 0x0388},
{0x0395, 0x0313, 0x1f18},
{0x0395, 0x0314, 0x1f19},
{0x0397, 0x0300, 0x1fca},
{0x0397, 0x0301, 0x0389},
{0x0397, 0x0313, 0x1f28},
{0x0397, 0x0314, 0x1f29},
{0x0397, 0x0345, 0x1fcc},
{0x0399, 0x0300, 0x1fda},
{0x0399, 0x0301, 0x038a},
{0x0399, 0x0304, 0x1fd9},
{0x0399, 0x0306, 0x1fd8},
{0x0399, 0x0308, 0x03aa},
{0x0399, 0x0313, 0x1f38},
{0x0399, 0x0314, 0x1f39},
{0x039f, 0x0300, 0x1ff8},
{0x039f, 0x0301, 0x038c},
{0x039f, 0x0313, 0x1f48},
{0x039f, 0x0314, 0x1f49},
{0x03a1, 0x0314, 0x1fec},
{0x03a5, 0x0300, 0x1fea},
{0x03a5, 0x0301, 0x038e},
{0x03a5, 0x0304, 0x1fe9},
{0x03a5, 0x0306, 0x1fe8},
{0x03a5, 0x0308, 0x03ab},
{0x03a5, 0x0314, 0x1f59},
{0x03a9, 0x0300, 0x1ffa},
{0x03a9, 0x0301, 0x038f},
{0x03a9, 0x0313, 0x1f68},
{0x03a9, 0x0314, 0x1f69},
{0x03a9, 0x0345, 0x1ffc},
{0x03ac, 0x0345, 0x1fb4},
{0x03ae, 0x0345, 0x1fc4},
{0x03b1, 0x0300, 0x1f70},
{0x03b1, 0x0301, 0x03ac},
{0x03b1, 0x0304, 0x1fb1},
{0x03b1, 0x0306, 0x1fb0},
{0x03b1, 0x0313, 0x1f00},
{0x03b1, 0x0314, 0x1f01},
{0x03b1, 0x0342, 0x1fb6},
{0x03b1, 0x0345, 0x1fb3},
{0x03b5, 0x0300, 0x1f72},
{0x03b5, 0x0301, 0x03ad},
{0x03b5, 0x0313, 0x1f10},
{0x03b5, 0x0314, 0x1f11},
{0x03b7, 0x0300, 0x1f74},
{0x03b7, 0x0301, 0x03ae},
{0x03b7, 0x0313, 0x1f20},
{0x03b7, 0x0314, 0x1f21},
{0x03b7, 0x0342, 0x1fc6},
{0x03b7, 0x0345, 0x1fc3},
{0x03b9, 0x0300, 0x1f76},
{0x03b9, 0x0301, 0x03af},
{0x03b9, 0x0304, 0x1fd1},
{0x03b9, 0x0306, 0x1fd0},
{0x03b9, 0x0308, 0x03ca},
{0x03b9, 0x0313, 0x1f30},
{0x03b9, 0x0314, 0x1f31},
{0x03b9, 0x0342, 0x1fd6},
{0x03bf, 0x0300, 0x1f78},
{0x03bf, 0x0301, 0x03cc},
{0x03bf, 0x0313, 0x1f40},
{0x03bf, 0x0314, 0x1f41},
{0x03c1, 0x0313, 0x1fe4},
{0x03c1, 0x0314, 0x1fe5},
{0x03c5, 0x0300, 0x1f7a},
{0x03c5, 0x0301, 0x03cd},
{0x03c5, 0x0304, 0x1fe1},
{0x03c5, 0x0306, 0x1fe0},
{0x03c5, 0x0308, 0x03cb},
{0x03c5, 0x0313, 0x1f50},
{0x03c5, 0x0314, 0x1f51},
{0x03c5, 0x0342, 0x1fe6},
{0x03c9, 0x0300, 0x1f7c},
{0x03c9, 0x0301, 0x03ce},
{0x03c9, 0x0313, 0x1f60},
{0x03c9, 0x0314, 0x1f61},
{0x03c9, 0x0342, 0x1ff6},
{0x03c9, 0x0345, 0x1ff3},
{0x03ca, 0x0300, 0x1fd2},
{0x03ca, 0x0301, 0x0390},
{0x03ca, 0x0342, 0x1fd7},
{0x03cb, 0x0300, 0x1fe2},
{0x03cb, 0x0301, 0x03b0},
{0x03cb, 0x0342, 0x1fe7},
{0x03ce, 0x0345, 0x1ff4},
{0x03d2, 0x0301, 0x03d3},
{0x03d2, 0x0308, 0x03d4},
{0x0406, 0x0308, 0x0407},
{0x0410, 0x0306, 0x04d0},
{0x0410, 0x0308, 0x04d2},
{0x0413, 0x0301, 0x0403},
{0x0415, 0x0300, 0x0400},
{0x0415, 0x0306, 0x04d6},
{0x0415, 0x0308, 0x0401},
{0x0416, 0x0306, 0x04c1},
{0x0416, 0x0308, 0x04dc},
{0x0417, 0x0308, 0x04de},
{0x0418, 0x0300, 0x040d},
{0x0418, 0x0304, 0x04e2},
{0x0418, 0x0306, 0x0419},
{0x0418, 0x0308, 0x04e4},
{0x041a, 0x0301, 0x040c},
{0x041e, 0x0308, 0x04e6},
{0x0423, 0x0304, 0x04ee},
{0x0423, 0x0306, 0x040e},
{0x0423, 0x0308, 0x04f0},
{0x0423, 0x030b, 0x04f2},
{0x0427, 0x0308, 0x04f4},
{0x042b, 0x0308, 0x04f8},
{0x042d, 0x0308, 0x04ec},
{0x0430, 0x0306, 0x04d1},
{0x0430, 0x0308, 0x04d3},
{0x0433, 0x0301, 0x0453},
{0x0435, 0x0300, 0x0450},
{0x0435, 0x0306, 0x04d7},
{0x0435, 0x0308, 0x0451},
{0x0436, 0x0306, 0x04c2},
{0x0436, 0x0308, 0x04dd},
{0x0437, 0x0308, 0x04df},
{0x0438, 0x0300, 0x045d},
{0x0438, 0x0304, 0x04e3},
{0x0438, 0x0306, 0x0439},
{0x0438, 0x0308, 0x04e5},
{0x043a, 0x0301, 0x045c},
{0x043e, 0x0308, 0x04e7},
{0x0443, 0x0304, 0x04ef},
{0x0443, 0x0306, 0x045e},
{0x0443, 0x0308, 0x04f1},
{0x0443, 0x030b, 0x04f3},
{0x0447, 0x0308, 0x04f5},
{0x044b, 0x0308, 0x04f9},
{0x044d, 0x0308, 0x04ed},
{0x0456, 0x0308, 0x0457},
{0x0474, 0x030f, 0x0476},
{0x0475, 0x030f, 0x0477},
{0x04d8, 0x0308, 0x04da},
{0x04d9, 0x0308, 0x04db},
{0x04e8, 0x0308, 0x04ea},
{0x04e9, 0x0308, 0x04eb},
{0x0627, 0x0653, 0x0622},
{0x0627, 0x0654, 0x0623},
{0x0627, 0x0655, 0x0625},
{0x0648, 0x0654, 0x0624},
{0x064a, 0x0654, 0x0626},
{0x06c1, 0x0654, 0x06c2},
{0x06d2, 0x0654, 0x06d3},
{0x06d5, 0x0654, 0x06c0},
{0x0928, 0x093c, 0x0929},
{0x0930, 0x093c, 0x0931},
{0x0933, 0x093c, 0x0934},
{0x09c7, 0x09be, 0x09cb},
{0x09c7, 0x09d7, 0x09cc},
{0x0b47, 0x0b3e, 0x0b4b},
{0x0b47, 0x0b56, 0x0b48},
{0x0b47, 0x0b57, 0x0b4c},
{0x0b92, 0x0bd7, 0x0b94},
{0x0bc6, 0x0bbe, 0x0bca},
{0x0bc6, 0x0bd7, 0x0bcc},
{0x0bc7, 0x0bbe, 0x0bcb},
{0x0c46, 0x0c56, 0x0c48},
{0x0cbf, 0x0cd5, 0x0cc0},
{0x0cc6, 0x0cc2, 0x0cca},
{0x0cc6, 0x0cd5, 0x0cc7},
{0x0cc6, 0x0cd6, 0x0cc8},
{0x0cca, 0x0cd5, 0x0ccb},
{0x0d46, 0x0d3e, 0x0d4a},
{0x0d46, 0x0d57, 0x0d4c},
{0x0d47, 0x0d3e, 0x0d4b},
{0x0dd9, 0x0dca, 0x0dda},
{0x0dd9, 0x0dcf, 0x0ddc},
{0x0dd9, 0x0ddf, 0x0dde},
{0x0ddc, 0x0dca, 0x0ddd},
{0x1025, 0x102e, 0x1026},
{0x1b05, 0x1b35, 0x1b06},
{0x1b07, 0x1b35, 0x1b08},
{0x1b09, 0x1b35, 0x1b0a},
{0x1b0b, 0x1b35, 0x1b0c},
{0x1b0d, 0x1b35, 0x1b0e},
{0x1b11, 0x1b35, 0x1b12},
{0x1b3a, 0x1b35, 0x1b3b},
{0x1b3c, 0x1b35, 0x1b3d},
{0x1b3e, 0x1b35, 0x1b40},
{0x1b3f, 0x1b35, 0x1b41},
{0x1b42, 0x1b35, 0x1b43},
{0x1e36, 0x0304, 0x1e38},
{0x1e37, 0x0304, 0x1e39},
{0x1e5a, 0x0304, 0x1e5c},
{0x1e5b, 0x0304, 0x1e5d},
{0x1e62, 0x0307, 0x1e68},
{0x1e63, 0x0307, 0x1e69},
{0x1ea0, 0x0302, 0x1eac},
{0x1ea0, 0x0306, 0x1eb6},
{0x1ea1, 0x0302, 0x1ead},
{0x1ea1, 0x0306, 0x1eb7},
{0x1eb8, 0x0302, 0x1ec6},
{0x1eb9, 0x0302, 0x1ec7},
{0x1ecc, 0x0302, 0x1ed8},
{0x1ecd, 0x0302, 0x1ed9},
{0x1f00, 0x0300, 0x1f02},
{0x1f00, 0x0301, 0x1f04},
{0x1f00, 0x0342, 0x1f06},
{0x1f00, 0x0345, 0x1f80},
{0x1f01, 0x0300, 0x1f03},
{0x1f01, 0x0301, 0x1f05},
{0x1f01, 0x0342, 0x1f07},
{0x1f01, 0x0345, 0x1f81},
{0x1f02, 0x0345, 0x1f82},
{0x1f03, 0x0345, 0x1f83},
{0x1f04, 0x0345, 0x1f84},
{0x1f05, 0x0345, 0x1f85},
{0x1f06, 0x0345, 0x1f86},
{0x1f07, 0x0345, 0x1f87},
{0x1f08, 0x0300, 0x1f0a},
{0x1f08, 0x0301, 0x1f0c},
{0x1f08, 0x0342, 0x1f0e},
{0x1f08, 0x0345, 0x1f88},
{0x1f09, 0x0300, 0x1f0b},
{0x1f09, 0x0301, 0x1f0d},
{0x1f09, 0x0342, 0x1f0f},
{0x1f09, 0x0345, 0x1f89},
{0x1f0a, 0x0345, 0x1f8a},
{0x1f0b, 0x0345, 0x1f8b},
{0x1f0c, 0x0345, 0x1f8c},
{0x1f0d, 0x0345, 0x1f8d},
{0x1f0e, 0x0345, 0x1f8e},
{0x1f0f, 0x0345, 0x1f8f},
{0x1f10, 0x0300, 0x1f12},
{0x1f10, 0x0301, 0x1f14},
{0x1f11, 0x0300, 0x1f13},
{0x1f11, 0x0301, 0x1f15},
{0x1f18, 0x0300, 0x1f1a},
{0x1f18, 0x0301, 0x1f1c},
{0x1f19, 0x0300, 0x1f1b},
{0x1f19, 0x0301, 0x1f1d},
{0x1f20, 0x0300, 0x1f22},
{0x1f20, 0x0301, 0x1f24},
{0x1f20, 0x0342, 0x1f26},
{0x1f20, 0x0345, 0x1f90},
{0x1f21, 0x0300, 0x1f23},
{0x1f21, 0x0301, 0x1f25},
{0x1f21, 0x0342, 0x1f27},
{0x1f21, 0x0345, 0x1f91},
{0x1f22, 0x0345, 0x1f92},
{0x1f23, 0x0345, 0x1f93},
{0x1f24, 0x0345, 0x1f94},
{0x1f25, 0x0345, 0x1f95},
{0x1f26, 0x0345, 0x1f96},
{0x1f27, 0x0345, 0x1f97},
{0x1f28, 0x0300, 0x1f2a},
{0x1f28, 0x0301, 0x1f2c},
{0x1f28, 0x0342, 0x1f2e},
{0x1f28, 0x0345, 0x1f98},
{0x1f29, 0x0300, 0x1f2b},
{0x1f29, 0x0301, 0x1f2d},
{0x1f29, 0x0342, 0x1f2f},
{0x1f29, 0x0345, 0x1f99},
{0x1f2a, 0x0345, 0x1f9a},
{0x1f2b, 0x0345, 0x1f9b},
{0x1f2c, 0x0345, 0x1f9c},
{0x1f2d, 0x0345, 0x1f9d},
{0x1f2e, 0x0345, 0x1f9e},
{0x1f2f, 0x0345, 0x1f9f},
{0x1f30, 0x0300, 0x1f32},
{0x1f30, 0x0301, 0x1f34},
{0x1f30, 0x0342, 0x1f36},
{0x1f31, 0x0300, 0x1f33},
{0x1f31, 0x0301, 0x1f35},
{0x1f31, 0x0342, 0x1f37},
{0x1f38, 0x0300, 0x1f3a},
{0x1f38, 0x0301, 0x1f3c},
{0x1f38, 0x0342, 0x1f3e},
{0x1f39, 0x0300, 0x1f3b},
{0x1f39, 0x0301, 0x1f3d},
{0x1f39, 0x0342, 0x1f3f},
{0x1f40, 0x0300, 0x1f42},
{0x1f40, 0x0301, 0x1f44},
{0x1f41, 0x0300, 0x1f43},
{0x1f41, 0x0301, 0x1f45},
{0x1f48, 0x0300, 0x1f4a},
{0x1f48, 0x0301, 0x1f4c},
{0x1f49, 0x0300, 0x1f4b},
{0x1f49, 0x0301, 0x1f4d},
{0x1f50, 0x0300, 0x1f52},
{0x1f50, 0x0301, 0x1f54},
{0x1f50, 0x0342, 0x1f56},
{0x1f51, 0x0300, 0x1f53},
{0x1f51, 0x0301, 0x1f55},
{0x1f51, 0x0342, 0x1f57},
{0x1f59, 0x0300, 0x1f5b},
{0x1f59, 0x0301, 0x1f5d},
{0x1f59, 0x0342, 0x1f5f},
{0x1f60, 0x0300, 0x1f62},
{0x1f60, 0x0301, 0x1f64},
{0x1f60, 0x0342, 0x1f66},
{0x1f60, 0x0345, 0x1fa0},
{0x1f61, 0x0300, 0x1f63},
{0x1f61, 0x0301, 0x1f65},
{0x1f61, 0x0342, 0x1f67},
{0x1f61, 0x0345, 0x1fa1},
{0x1f62, 0x0345, 0x1fa2},
{0x1f63, 0x0345, 0x1fa3},
{0x1f64, 0x0345, 0x1fa4},
{0x1f65, 0x0345, 0x1fa5},
{0x1f66, 0x0345, 0x1fa6},
{0x1f67, 0x0345, 0x1fa7},
{0x1f68, 0x0300, 0x1f6a},
{0x1f68, 0x0301, 0x1f6c},
{0x1f68, 0x0342, 0x1f6e},
{0x1f68, 0x0345, 0x1fa8},
{0x1f69, 0x0300, 0x1f6b},
{0x1f69, 0x0301, 0x1f6d},
{0x1f69, 0x0342, 0x1f6f},
{0x1f69, 0x0345, 0x1fa9},
{0x1f6a, 0x0345, 0x1faa},
{0x1f6b, 0x0345, 0x1fab},
{0x1f6c, 0x0345, 0x1fac},
{0x1f6d, 0x0345, 0x1fad},
{0x1f6e, 0x0345, 0x1fae},
{0x1f6f, 0x0345, 0x1faf},
{0x1f70, 0x0345, 0x1fb2},
{0x1f74, 0x0345, 0x1fc2},
{0x1f7c, 0x0345, 0x1ff2},
{0x1fb6, 0x0345, 0x1fb7},
{0x1fbf, 0x0300, 0x1fcd},
{0x1fbf, 0x0301, 0x1fce},
{0x1fbf, 0x0342, 0x1fcf},
{0x1fc6, 0x0345, 0x1fc7},
{0x1ff6, 0x0345, 0x1ff7},
{0x1ffe, 0x0300, 0x1fdd},
{0x1ffe, 0x0301, 0x1fde},
{0x1ffe, 0x0342, 0x1fdf},
{0x2190, 0x0338, 0x219a},
{0x2192, 0x0338, 0x219b},
{0x2194, 0x0338, 0x21ae},
{0x21d0, 0x0338, 0x21cd},
{0x21d2, 0x0338, 0x21cf},
{0x21d4, 0x0338, 0x21ce},
{0x2203, 0x0338, 0x2204},
{0x2208, 0x0338, 0x2209},
{0x220b, 0x0338, 0x220c},
{0x2223, 0x0338, 0x2224},
{0x2225, 0x0338, 0x2226},
{0x223c, 0x0338, 0x2241},
{0x2243, 0x0338, 0x2244},
{0x2245, 0x0338, 0x2247},
{0x2248, 0x0338, 0x2249},
{0x224d, 0x0338, 0x226d},
{0x2261, 0x0338, 0x2262},
{0x2264, 0x0338, 0x2270},
{0x2265, 0x0338, 0x2271},
{0x2272, 0x0338, 0x2274},
{0x2273, 0x0338, 0x2275},
{0x2276, 0x0338, 0x2278},
{0x2277, 0x0338, 0x2279},
{0x227a, 0x0338, 0x2280},
{0x227b, 0x0338, 0x2281},
{0x227c, 0x0338, 0x22e0},
{0x227d, 0x0338, 0x22e1},
{0x2282, 0x0338, 0x2284},
{0x2283, 0x0338, 0x2285},
{0x2286, 0x0338, 0x2288},
{0x2287, 0x0338, 0x2289},
{0x2291, 0x0338, 0x22e2},
{0x2292, 0x0338, 0x22e3},
{0x22a2, 0x0338, 0x22ac},
{0x22a8, 0x0338, 0x22ad},
{0x22a9, 0x0338, 0x22ae},
{0x22ab, 0x0338, 0x22af},
{0x22b2, 0x0338, 0x22ea},
{0x22b3, 0x0338, 0x22eb},
{0x22b4, 0x0338, 0x22ec},
{0x22b5, 0x0338, 0x22ed},
{0x3046, 0x3099, 0x3094},
{0x304b, 0x3099, 0x304c},
{0x304d, 0x3099, 0x304e},
{0x304f, 0x3099, 0x3050},
{0x3051, 0x3099, 0x3052},
{0x3053, 0x3099, 0x3054},
{0x3055, 0x3099, 0x3056},
{0x3057, 0x3099, 0x3058},
{0x3059, 0x3099, 0x305a},
{0x305b, 0x3099, 0x305c},
{0x305d, 0x3099, 0x305e},
{0x305f, 0x3099, 0x3060},
{0x3061, 0x3099, 0x3062},
{0x3064, 0x3099, 0x3065},
{0x3066, 0x3099, 0x3067},
{0x3068, 0x3099, 0x3069},
{0x306f, 0x3099, 0x3070},
{0x306f, 0x309a, 0x3071},
{0x3072, 0x3099, 0x3073},
{0x3072, 0x309a, 0x3074},
{0x3075, 0x3099, 0x3076},
{0x3075, 0x309a, 0x3077},
{0x3078, 0x3099, 0x3079},
{0x3078, 0x309a, 0x307a},
{0x307b, 0x3099, 0x307c},
{0x307b, 0x309a, 0x307d},
{0x309d, 0x3099, 0x309e},
{0x30a6, 0x3099, 0x30f4},
{0x30ab, 0x3099, 0x30ac},
{0x30ad, 0x3099, 0x30ae},
{0x30af, 0x3099, 0x30b0},
{0x30b1, 0x3099, 0x30b2},
{0x30b3, 0x3099, 0x30b4},
{0x30b5, 0x3099, 0x30b6},
{0x30b7, 0x3099, 0x30b8},
{0x30b9, 0x3099, 0x30ba},
{0x30bb, 0x3099, 0x30bc},
{0x30bd, 0x3099, 0x30be},
{0x30bf, 0x3099, 0x30c0},
{0x30c1, 0x3099, 0x30c2},
{0x30c4, 0x3099, 0x30c5},
{0x30c6, 0x3099, 0x30c7},
{0x30c8, 0x3099, 0x30c9},
{0x30cf, 0x3099, 0x30d0},
{0x30cf, 0x309a, 0x30d1},
{0x30d2, 0x3099, 0x30d3},
{0x30d2, 0x309a, 0x30d4},
{0x30d5, 0x3099, 0x30d6},
{0x30d5, 0x309a, 0x30d7},
{0x30d8, 0x3099, 0x30d9},
{0x30d8, 0x309a, 0x30da},
{0x30db, 0x3099, 0x30dc},
{0x30db, 0x309a, 0x30dd},
{0x30ef, 0x3099, 0x30f7},
{0x30f0, 0x3099, 0x30f8},
{0x30f1, 0x3099, 0x30f9},
{0x30f2, 0x3099, 0x30fa},
{0x30fd, 0x3099, 0x30fe},
{0x11099, 0x110ba, 0x1109a},
{0x1109b, 0x110ba, 0x1109c},
{0x110a5, 0x110ba, 0x110ab},
{0x11131, 0x11127, 0x1112e},
{0x11132, 0x11127, 0x1112f},
{0x11347, 0x1133e, 0x1134b},
{0x11347, 0x11357, 0x1134c},
{0x114b9, 0x114b0, 0x114bc},
{0x114b9, 0x114ba, 0x114bb},
{0x114b9, 0x114bd, 0x114be},
{0x115b8, 0x115af, 0x115ba},
{0x115b9, 0x115af, 0x115bb},
{0x11935, 0x11930, 0x11938},

2071
unicode/canonical_decomp.h Normal file

File diff suppressed because it is too large Load diff

398
unicode/combining_classes.h Normal file
View file

@ -0,0 +1,398 @@
/*
* Autogenerated by read_ucd.py from The Unicode Standard 15.0.0
*
* List the canonical combining class of each Unicode character, if it is
* not zero. This controls how combining marks can be reordered by the
* Unicode normalisation algorithms.
*
* Used by utils/unicode-norm.c.
*/
{0x0300, 0x0314, 230},
{0x0315, 0x0315, 232},
{0x0316, 0x0319, 220},
{0x031a, 0x031a, 232},
{0x031b, 0x031b, 216},
{0x031c, 0x0320, 220},
{0x0321, 0x0322, 202},
{0x0323, 0x0326, 220},
{0x0327, 0x0328, 202},
{0x0329, 0x0333, 220},
{0x0334, 0x0338, 1},
{0x0339, 0x033c, 220},
{0x033d, 0x0344, 230},
{0x0345, 0x0345, 240},
{0x0346, 0x0346, 230},
{0x0347, 0x0349, 220},
{0x034a, 0x034c, 230},
{0x034d, 0x034e, 220},
{0x0350, 0x0352, 230},
{0x0353, 0x0356, 220},
{0x0357, 0x0357, 230},
{0x0358, 0x0358, 232},
{0x0359, 0x035a, 220},
{0x035b, 0x035b, 230},
{0x035c, 0x035c, 233},
{0x035d, 0x035e, 234},
{0x035f, 0x035f, 233},
{0x0360, 0x0361, 234},
{0x0362, 0x0362, 233},
{0x0363, 0x036f, 230},
{0x0483, 0x0487, 230},
{0x0591, 0x0591, 220},
{0x0592, 0x0595, 230},
{0x0596, 0x0596, 220},
{0x0597, 0x0599, 230},
{0x059a, 0x059a, 222},
{0x059b, 0x059b, 220},
{0x059c, 0x05a1, 230},
{0x05a2, 0x05a7, 220},
{0x05a8, 0x05a9, 230},
{0x05aa, 0x05aa, 220},
{0x05ab, 0x05ac, 230},
{0x05ad, 0x05ad, 222},
{0x05ae, 0x05ae, 228},
{0x05af, 0x05af, 230},
{0x05b0, 0x05b0, 10},
{0x05b1, 0x05b1, 11},
{0x05b2, 0x05b2, 12},
{0x05b3, 0x05b3, 13},
{0x05b4, 0x05b4, 14},
{0x05b5, 0x05b5, 15},
{0x05b6, 0x05b6, 16},
{0x05b7, 0x05b7, 17},
{0x05b8, 0x05b8, 18},
{0x05b9, 0x05ba, 19},
{0x05bb, 0x05bb, 20},
{0x05bc, 0x05bc, 21},
{0x05bd, 0x05bd, 22},
{0x05bf, 0x05bf, 23},
{0x05c1, 0x05c1, 24},
{0x05c2, 0x05c2, 25},
{0x05c4, 0x05c4, 230},
{0x05c5, 0x05c5, 220},
{0x05c7, 0x05c7, 18},
{0x0610, 0x0617, 230},
{0x0618, 0x0618, 30},
{0x0619, 0x0619, 31},
{0x061a, 0x061a, 32},
{0x064b, 0x064b, 27},
{0x064c, 0x064c, 28},
{0x064d, 0x064d, 29},
{0x064e, 0x064e, 30},
{0x064f, 0x064f, 31},
{0x0650, 0x0650, 32},
{0x0651, 0x0651, 33},
{0x0652, 0x0652, 34},
{0x0653, 0x0654, 230},
{0x0655, 0x0656, 220},
{0x0657, 0x065b, 230},
{0x065c, 0x065c, 220},
{0x065d, 0x065e, 230},
{0x065f, 0x065f, 220},
{0x0670, 0x0670, 35},
{0x06d6, 0x06dc, 230},
{0x06df, 0x06e2, 230},
{0x06e3, 0x06e3, 220},
{0x06e4, 0x06e4, 230},
{0x06e7, 0x06e8, 230},
{0x06ea, 0x06ea, 220},
{0x06eb, 0x06ec, 230},
{0x06ed, 0x06ed, 220},
{0x0711, 0x0711, 36},
{0x0730, 0x0730, 230},
{0x0731, 0x0731, 220},
{0x0732, 0x0733, 230},
{0x0734, 0x0734, 220},
{0x0735, 0x0736, 230},
{0x0737, 0x0739, 220},
{0x073a, 0x073a, 230},
{0x073b, 0x073c, 220},
{0x073d, 0x073d, 230},
{0x073e, 0x073e, 220},
{0x073f, 0x0741, 230},
{0x0742, 0x0742, 220},
{0x0743, 0x0743, 230},
{0x0744, 0x0744, 220},
{0x0745, 0x0745, 230},
{0x0746, 0x0746, 220},
{0x0747, 0x0747, 230},
{0x0748, 0x0748, 220},
{0x0749, 0x074a, 230},
{0x07eb, 0x07f1, 230},
{0x07f2, 0x07f2, 220},
{0x07f3, 0x07f3, 230},
{0x07fd, 0x07fd, 220},
{0x0816, 0x0819, 230},
{0x081b, 0x0823, 230},
{0x0825, 0x0827, 230},
{0x0829, 0x082d, 230},
{0x0859, 0x085b, 220},
{0x0898, 0x0898, 230},
{0x0899, 0x089b, 220},
{0x089c, 0x089f, 230},
{0x08ca, 0x08ce, 230},
{0x08cf, 0x08d3, 220},
{0x08d4, 0x08e1, 230},
{0x08e3, 0x08e3, 220},
{0x08e4, 0x08e5, 230},
{0x08e6, 0x08e6, 220},
{0x08e7, 0x08e8, 230},
{0x08e9, 0x08e9, 220},
{0x08ea, 0x08ec, 230},
{0x08ed, 0x08ef, 220},
{0x08f0, 0x08f0, 27},
{0x08f1, 0x08f1, 28},
{0x08f2, 0x08f2, 29},
{0x08f3, 0x08f5, 230},
{0x08f6, 0x08f6, 220},
{0x08f7, 0x08f8, 230},
{0x08f9, 0x08fa, 220},
{0x08fb, 0x08ff, 230},
{0x093c, 0x093c, 7},
{0x094d, 0x094d, 9},
{0x0951, 0x0951, 230},
{0x0952, 0x0952, 220},
{0x0953, 0x0954, 230},
{0x09bc, 0x09bc, 7},
{0x09cd, 0x09cd, 9},
{0x09fe, 0x09fe, 230},
{0x0a3c, 0x0a3c, 7},
{0x0a4d, 0x0a4d, 9},
{0x0abc, 0x0abc, 7},
{0x0acd, 0x0acd, 9},
{0x0b3c, 0x0b3c, 7},
{0x0b4d, 0x0b4d, 9},
{0x0bcd, 0x0bcd, 9},
{0x0c3c, 0x0c3c, 7},
{0x0c4d, 0x0c4d, 9},
{0x0c55, 0x0c55, 84},
{0x0c56, 0x0c56, 91},
{0x0cbc, 0x0cbc, 7},
{0x0ccd, 0x0ccd, 9},
{0x0d3b, 0x0d3c, 9},
{0x0d4d, 0x0d4d, 9},
{0x0dca, 0x0dca, 9},
{0x0e38, 0x0e39, 103},
{0x0e3a, 0x0e3a, 9},
{0x0e48, 0x0e4b, 107},
{0x0eb8, 0x0eb9, 118},
{0x0eba, 0x0eba, 9},
{0x0ec8, 0x0ecb, 122},
{0x0f18, 0x0f19, 220},
{0x0f35, 0x0f35, 220},
{0x0f37, 0x0f37, 220},
{0x0f39, 0x0f39, 216},
{0x0f71, 0x0f71, 129},
{0x0f72, 0x0f72, 130},
{0x0f74, 0x0f74, 132},
{0x0f7a, 0x0f7d, 130},
{0x0f80, 0x0f80, 130},
{0x0f82, 0x0f83, 230},
{0x0f84, 0x0f84, 9},
{0x0f86, 0x0f87, 230},
{0x0fc6, 0x0fc6, 220},
{0x1037, 0x1037, 7},
{0x1039, 0x103a, 9},
{0x108d, 0x108d, 220},
{0x135d, 0x135f, 230},
{0x1714, 0x1715, 9},
{0x1734, 0x1734, 9},
{0x17d2, 0x17d2, 9},
{0x17dd, 0x17dd, 230},
{0x18a9, 0x18a9, 228},
{0x1939, 0x1939, 222},
{0x193a, 0x193a, 230},
{0x193b, 0x193b, 220},
{0x1a17, 0x1a17, 230},
{0x1a18, 0x1a18, 220},
{0x1a60, 0x1a60, 9},
{0x1a75, 0x1a7c, 230},
{0x1a7f, 0x1a7f, 220},
{0x1ab0, 0x1ab4, 230},
{0x1ab5, 0x1aba, 220},
{0x1abb, 0x1abc, 230},
{0x1abd, 0x1abd, 220},
{0x1abf, 0x1ac0, 220},
{0x1ac1, 0x1ac2, 230},
{0x1ac3, 0x1ac4, 220},
{0x1ac5, 0x1ac9, 230},
{0x1aca, 0x1aca, 220},
{0x1acb, 0x1ace, 230},
{0x1b34, 0x1b34, 7},
{0x1b44, 0x1b44, 9},
{0x1b6b, 0x1b6b, 230},
{0x1b6c, 0x1b6c, 220},
{0x1b6d, 0x1b73, 230},
{0x1baa, 0x1bab, 9},
{0x1be6, 0x1be6, 7},
{0x1bf2, 0x1bf3, 9},
{0x1c37, 0x1c37, 7},
{0x1cd0, 0x1cd2, 230},
{0x1cd4, 0x1cd4, 1},
{0x1cd5, 0x1cd9, 220},
{0x1cda, 0x1cdb, 230},
{0x1cdc, 0x1cdf, 220},
{0x1ce0, 0x1ce0, 230},
{0x1ce2, 0x1ce8, 1},
{0x1ced, 0x1ced, 220},
{0x1cf4, 0x1cf4, 230},
{0x1cf8, 0x1cf9, 230},
{0x1dc0, 0x1dc1, 230},
{0x1dc2, 0x1dc2, 220},
{0x1dc3, 0x1dc9, 230},
{0x1dca, 0x1dca, 220},
{0x1dcb, 0x1dcc, 230},
{0x1dcd, 0x1dcd, 234},
{0x1dce, 0x1dce, 214},
{0x1dcf, 0x1dcf, 220},
{0x1dd0, 0x1dd0, 202},
{0x1dd1, 0x1df5, 230},
{0x1df6, 0x1df6, 232},
{0x1df7, 0x1df8, 228},
{0x1df9, 0x1df9, 220},
{0x1dfa, 0x1dfa, 218},
{0x1dfb, 0x1dfb, 230},
{0x1dfc, 0x1dfc, 233},
{0x1dfd, 0x1dfd, 220},
{0x1dfe, 0x1dfe, 230},
{0x1dff, 0x1dff, 220},
{0x20d0, 0x20d1, 230},
{0x20d2, 0x20d3, 1},
{0x20d4, 0x20d7, 230},
{0x20d8, 0x20da, 1},
{0x20db, 0x20dc, 230},
{0x20e1, 0x20e1, 230},
{0x20e5, 0x20e6, 1},
{0x20e7, 0x20e7, 230},
{0x20e8, 0x20e8, 220},
{0x20e9, 0x20e9, 230},
{0x20ea, 0x20eb, 1},
{0x20ec, 0x20ef, 220},
{0x20f0, 0x20f0, 230},
{0x2cef, 0x2cf1, 230},
{0x2d7f, 0x2d7f, 9},
{0x2de0, 0x2dff, 230},
{0x302a, 0x302a, 218},
{0x302b, 0x302b, 228},
{0x302c, 0x302c, 232},
{0x302d, 0x302d, 222},
{0x302e, 0x302f, 224},
{0x3099, 0x309a, 8},
{0xa66f, 0xa66f, 230},
{0xa674, 0xa67d, 230},
{0xa69e, 0xa69f, 230},
{0xa6f0, 0xa6f1, 230},
{0xa806, 0xa806, 9},
{0xa82c, 0xa82c, 9},
{0xa8c4, 0xa8c4, 9},
{0xa8e0, 0xa8f1, 230},
{0xa92b, 0xa92d, 220},
{0xa953, 0xa953, 9},
{0xa9b3, 0xa9b3, 7},
{0xa9c0, 0xa9c0, 9},
{0xaab0, 0xaab0, 230},
{0xaab2, 0xaab3, 230},
{0xaab4, 0xaab4, 220},
{0xaab7, 0xaab8, 230},
{0xaabe, 0xaabf, 230},
{0xaac1, 0xaac1, 230},
{0xaaf6, 0xaaf6, 9},
{0xabed, 0xabed, 9},
{0xfb1e, 0xfb1e, 26},
{0xfe20, 0xfe26, 230},
{0xfe27, 0xfe2d, 220},
{0xfe2e, 0xfe2f, 230},
{0x101fd, 0x101fd, 220},
{0x102e0, 0x102e0, 220},
{0x10376, 0x1037a, 230},
{0x10a0d, 0x10a0d, 220},
{0x10a0f, 0x10a0f, 230},
{0x10a38, 0x10a38, 230},
{0x10a39, 0x10a39, 1},
{0x10a3a, 0x10a3a, 220},
{0x10a3f, 0x10a3f, 9},
{0x10ae5, 0x10ae5, 230},
{0x10ae6, 0x10ae6, 220},
{0x10d24, 0x10d27, 230},
{0x10eab, 0x10eac, 230},
{0x10efd, 0x10eff, 220},
{0x10f46, 0x10f47, 220},
{0x10f48, 0x10f4a, 230},
{0x10f4b, 0x10f4b, 220},
{0x10f4c, 0x10f4c, 230},
{0x10f4d, 0x10f50, 220},
{0x10f82, 0x10f82, 230},
{0x10f83, 0x10f83, 220},
{0x10f84, 0x10f84, 230},
{0x10f85, 0x10f85, 220},
{0x11046, 0x11046, 9},
{0x11070, 0x11070, 9},
{0x1107f, 0x1107f, 9},
{0x110b9, 0x110b9, 9},
{0x110ba, 0x110ba, 7},
{0x11100, 0x11102, 230},
{0x11133, 0x11134, 9},
{0x11173, 0x11173, 7},
{0x111c0, 0x111c0, 9},
{0x111ca, 0x111ca, 7},
{0x11235, 0x11235, 9},
{0x11236, 0x11236, 7},
{0x112e9, 0x112e9, 7},
{0x112ea, 0x112ea, 9},
{0x1133b, 0x1133c, 7},
{0x1134d, 0x1134d, 9},
{0x11366, 0x1136c, 230},
{0x11370, 0x11374, 230},
{0x11442, 0x11442, 9},
{0x11446, 0x11446, 7},
{0x1145e, 0x1145e, 230},
{0x114c2, 0x114c2, 9},
{0x114c3, 0x114c3, 7},
{0x115bf, 0x115bf, 9},
{0x115c0, 0x115c0, 7},
{0x1163f, 0x1163f, 9},
{0x116b6, 0x116b6, 9},
{0x116b7, 0x116b7, 7},
{0x1172b, 0x1172b, 9},
{0x11839, 0x11839, 9},
{0x1183a, 0x1183a, 7},
{0x1193d, 0x1193e, 9},
{0x11943, 0x11943, 7},
{0x119e0, 0x119e0, 9},
{0x11a34, 0x11a34, 9},
{0x11a47, 0x11a47, 9},
{0x11a99, 0x11a99, 9},
{0x11c3f, 0x11c3f, 9},
{0x11d42, 0x11d42, 7},
{0x11d44, 0x11d45, 9},
{0x11d97, 0x11d97, 9},
{0x11f41, 0x11f42, 9},
{0x16af0, 0x16af4, 1},
{0x16b30, 0x16b36, 230},
{0x16ff0, 0x16ff1, 6},
{0x1bc9e, 0x1bc9e, 1},
{0x1d165, 0x1d166, 216},
{0x1d167, 0x1d169, 1},
{0x1d16d, 0x1d16d, 226},
{0x1d16e, 0x1d172, 216},
{0x1d17b, 0x1d182, 220},
{0x1d185, 0x1d189, 230},
{0x1d18a, 0x1d18b, 220},
{0x1d1aa, 0x1d1ad, 230},
{0x1d242, 0x1d244, 230},
{0x1e000, 0x1e006, 230},
{0x1e008, 0x1e018, 230},
{0x1e01b, 0x1e021, 230},
{0x1e023, 0x1e024, 230},
{0x1e026, 0x1e02a, 230},
{0x1e08f, 0x1e08f, 230},
{0x1e130, 0x1e136, 230},
{0x1e2ae, 0x1e2ae, 230},
{0x1e2ec, 0x1e2ef, 230},
{0x1e4ec, 0x1e4ed, 232},
{0x1e4ee, 0x1e4ee, 220},
{0x1e4ef, 0x1e4ef, 230},
{0x1e8d0, 0x1e8d6, 220},
{0x1e944, 0x1e949, 230},
{0x1e94a, 0x1e94a, 7},

716
unicode/known_chars.h Normal file
View file

@ -0,0 +1,716 @@
/*
* Autogenerated by read_ucd.py from The Unicode Standard 15.0.0
*
* List the Unicode code points that are known to this version of the
* standard at all.
*
* Used by utils/unicode-known.c.
*/
{0x0000, 0x0377},
{0x037a, 0x037f},
{0x0384, 0x038a},
{0x038c, 0x038c},
{0x038e, 0x03a1},
{0x03a3, 0x052f},
{0x0531, 0x0556},
{0x0559, 0x058a},
{0x058d, 0x058f},
{0x0591, 0x05c7},
{0x05d0, 0x05ea},
{0x05ef, 0x05f4},
{0x0600, 0x070d},
{0x070f, 0x074a},
{0x074d, 0x07b1},
{0x07c0, 0x07fa},
{0x07fd, 0x082d},
{0x0830, 0x083e},
{0x0840, 0x085b},
{0x085e, 0x085e},
{0x0860, 0x086a},
{0x0870, 0x088e},
{0x0890, 0x0891},
{0x0898, 0x0983},
{0x0985, 0x098c},
{0x098f, 0x0990},
{0x0993, 0x09a8},
{0x09aa, 0x09b0},
{0x09b2, 0x09b2},
{0x09b6, 0x09b9},
{0x09bc, 0x09c4},
{0x09c7, 0x09c8},
{0x09cb, 0x09ce},
{0x09d7, 0x09d7},
{0x09dc, 0x09dd},
{0x09df, 0x09e3},
{0x09e6, 0x09fe},
{0x0a01, 0x0a03},
{0x0a05, 0x0a0a},
{0x0a0f, 0x0a10},
{0x0a13, 0x0a28},
{0x0a2a, 0x0a30},
{0x0a32, 0x0a33},
{0x0a35, 0x0a36},
{0x0a38, 0x0a39},
{0x0a3c, 0x0a3c},
{0x0a3e, 0x0a42},
{0x0a47, 0x0a48},
{0x0a4b, 0x0a4d},
{0x0a51, 0x0a51},
{0x0a59, 0x0a5c},
{0x0a5e, 0x0a5e},
{0x0a66, 0x0a76},
{0x0a81, 0x0a83},
{0x0a85, 0x0a8d},
{0x0a8f, 0x0a91},
{0x0a93, 0x0aa8},
{0x0aaa, 0x0ab0},
{0x0ab2, 0x0ab3},
{0x0ab5, 0x0ab9},
{0x0abc, 0x0ac5},
{0x0ac7, 0x0ac9},
{0x0acb, 0x0acd},
{0x0ad0, 0x0ad0},
{0x0ae0, 0x0ae3},
{0x0ae6, 0x0af1},
{0x0af9, 0x0aff},
{0x0b01, 0x0b03},
{0x0b05, 0x0b0c},
{0x0b0f, 0x0b10},
{0x0b13, 0x0b28},
{0x0b2a, 0x0b30},
{0x0b32, 0x0b33},
{0x0b35, 0x0b39},
{0x0b3c, 0x0b44},
{0x0b47, 0x0b48},
{0x0b4b, 0x0b4d},
{0x0b55, 0x0b57},
{0x0b5c, 0x0b5d},
{0x0b5f, 0x0b63},
{0x0b66, 0x0b77},
{0x0b82, 0x0b83},
{0x0b85, 0x0b8a},
{0x0b8e, 0x0b90},
{0x0b92, 0x0b95},
{0x0b99, 0x0b9a},
{0x0b9c, 0x0b9c},
{0x0b9e, 0x0b9f},
{0x0ba3, 0x0ba4},
{0x0ba8, 0x0baa},
{0x0bae, 0x0bb9},
{0x0bbe, 0x0bc2},
{0x0bc6, 0x0bc8},
{0x0bca, 0x0bcd},
{0x0bd0, 0x0bd0},
{0x0bd7, 0x0bd7},
{0x0be6, 0x0bfa},
{0x0c00, 0x0c0c},
{0x0c0e, 0x0c10},
{0x0c12, 0x0c28},
{0x0c2a, 0x0c39},
{0x0c3c, 0x0c44},
{0x0c46, 0x0c48},
{0x0c4a, 0x0c4d},
{0x0c55, 0x0c56},
{0x0c58, 0x0c5a},
{0x0c5d, 0x0c5d},
{0x0c60, 0x0c63},
{0x0c66, 0x0c6f},
{0x0c77, 0x0c8c},
{0x0c8e, 0x0c90},
{0x0c92, 0x0ca8},
{0x0caa, 0x0cb3},
{0x0cb5, 0x0cb9},
{0x0cbc, 0x0cc4},
{0x0cc6, 0x0cc8},
{0x0cca, 0x0ccd},
{0x0cd5, 0x0cd6},
{0x0cdd, 0x0cde},
{0x0ce0, 0x0ce3},
{0x0ce6, 0x0cef},
{0x0cf1, 0x0cf3},
{0x0d00, 0x0d0c},
{0x0d0e, 0x0d10},
{0x0d12, 0x0d44},
{0x0d46, 0x0d48},
{0x0d4a, 0x0d4f},
{0x0d54, 0x0d63},
{0x0d66, 0x0d7f},
{0x0d81, 0x0d83},
{0x0d85, 0x0d96},
{0x0d9a, 0x0db1},
{0x0db3, 0x0dbb},
{0x0dbd, 0x0dbd},
{0x0dc0, 0x0dc6},
{0x0dca, 0x0dca},
{0x0dcf, 0x0dd4},
{0x0dd6, 0x0dd6},
{0x0dd8, 0x0ddf},
{0x0de6, 0x0def},
{0x0df2, 0x0df4},
{0x0e01, 0x0e3a},
{0x0e3f, 0x0e5b},
{0x0e81, 0x0e82},
{0x0e84, 0x0e84},
{0x0e86, 0x0e8a},
{0x0e8c, 0x0ea3},
{0x0ea5, 0x0ea5},
{0x0ea7, 0x0ebd},
{0x0ec0, 0x0ec4},
{0x0ec6, 0x0ec6},
{0x0ec8, 0x0ece},
{0x0ed0, 0x0ed9},
{0x0edc, 0x0edf},
{0x0f00, 0x0f47},
{0x0f49, 0x0f6c},
{0x0f71, 0x0f97},
{0x0f99, 0x0fbc},
{0x0fbe, 0x0fcc},
{0x0fce, 0x0fda},
{0x1000, 0x10c5},
{0x10c7, 0x10c7},
{0x10cd, 0x10cd},
{0x10d0, 0x1248},
{0x124a, 0x124d},
{0x1250, 0x1256},
{0x1258, 0x1258},
{0x125a, 0x125d},
{0x1260, 0x1288},
{0x128a, 0x128d},
{0x1290, 0x12b0},
{0x12b2, 0x12b5},
{0x12b8, 0x12be},
{0x12c0, 0x12c0},
{0x12c2, 0x12c5},
{0x12c8, 0x12d6},
{0x12d8, 0x1310},
{0x1312, 0x1315},
{0x1318, 0x135a},
{0x135d, 0x137c},
{0x1380, 0x1399},
{0x13a0, 0x13f5},
{0x13f8, 0x13fd},
{0x1400, 0x169c},
{0x16a0, 0x16f8},
{0x1700, 0x1715},
{0x171f, 0x1736},
{0x1740, 0x1753},
{0x1760, 0x176c},
{0x176e, 0x1770},
{0x1772, 0x1773},
{0x1780, 0x17dd},
{0x17e0, 0x17e9},
{0x17f0, 0x17f9},
{0x1800, 0x1819},
{0x1820, 0x1878},
{0x1880, 0x18aa},
{0x18b0, 0x18f5},
{0x1900, 0x191e},
{0x1920, 0x192b},
{0x1930, 0x193b},
{0x1940, 0x1940},
{0x1944, 0x196d},
{0x1970, 0x1974},
{0x1980, 0x19ab},
{0x19b0, 0x19c9},
{0x19d0, 0x19da},
{0x19de, 0x1a1b},
{0x1a1e, 0x1a5e},
{0x1a60, 0x1a7c},
{0x1a7f, 0x1a89},
{0x1a90, 0x1a99},
{0x1aa0, 0x1aad},
{0x1ab0, 0x1ace},
{0x1b00, 0x1b4c},
{0x1b50, 0x1b7e},
{0x1b80, 0x1bf3},
{0x1bfc, 0x1c37},
{0x1c3b, 0x1c49},
{0x1c4d, 0x1c88},
{0x1c90, 0x1cba},
{0x1cbd, 0x1cc7},
{0x1cd0, 0x1cfa},
{0x1d00, 0x1f15},
{0x1f18, 0x1f1d},
{0x1f20, 0x1f45},
{0x1f48, 0x1f4d},
{0x1f50, 0x1f57},
{0x1f59, 0x1f59},
{0x1f5b, 0x1f5b},
{0x1f5d, 0x1f5d},
{0x1f5f, 0x1f7d},
{0x1f80, 0x1fb4},
{0x1fb6, 0x1fc4},
{0x1fc6, 0x1fd3},
{0x1fd6, 0x1fdb},
{0x1fdd, 0x1fef},
{0x1ff2, 0x1ff4},
{0x1ff6, 0x1ffe},
{0x2000, 0x2064},
{0x2066, 0x2071},
{0x2074, 0x208e},
{0x2090, 0x209c},
{0x20a0, 0x20c0},
{0x20d0, 0x20f0},
{0x2100, 0x218b},
{0x2190, 0x2426},
{0x2440, 0x244a},
{0x2460, 0x2b73},
{0x2b76, 0x2b95},
{0x2b97, 0x2cf3},
{0x2cf9, 0x2d25},
{0x2d27, 0x2d27},
{0x2d2d, 0x2d2d},
{0x2d30, 0x2d67},
{0x2d6f, 0x2d70},
{0x2d7f, 0x2d96},
{0x2da0, 0x2da6},
{0x2da8, 0x2dae},
{0x2db0, 0x2db6},
{0x2db8, 0x2dbe},
{0x2dc0, 0x2dc6},
{0x2dc8, 0x2dce},
{0x2dd0, 0x2dd6},
{0x2dd8, 0x2dde},
{0x2de0, 0x2e5d},
{0x2e80, 0x2e99},
{0x2e9b, 0x2ef3},
{0x2f00, 0x2fd5},
{0x2ff0, 0x2ffb},
{0x3000, 0x303f},
{0x3041, 0x3096},
{0x3099, 0x30ff},
{0x3105, 0x312f},
{0x3131, 0x318e},
{0x3190, 0x31e3},
{0x31f0, 0x321e},
{0x3220, 0xa48c},
{0xa490, 0xa4c6},
{0xa4d0, 0xa62b},
{0xa640, 0xa6f7},
{0xa700, 0xa7ca},
{0xa7d0, 0xa7d1},
{0xa7d3, 0xa7d3},
{0xa7d5, 0xa7d9},
{0xa7f2, 0xa82c},
{0xa830, 0xa839},
{0xa840, 0xa877},
{0xa880, 0xa8c5},
{0xa8ce, 0xa8d9},
{0xa8e0, 0xa953},
{0xa95f, 0xa97c},
{0xa980, 0xa9cd},
{0xa9cf, 0xa9d9},
{0xa9de, 0xa9fe},
{0xaa00, 0xaa36},
{0xaa40, 0xaa4d},
{0xaa50, 0xaa59},
{0xaa5c, 0xaac2},
{0xaadb, 0xaaf6},
{0xab01, 0xab06},
{0xab09, 0xab0e},
{0xab11, 0xab16},
{0xab20, 0xab26},
{0xab28, 0xab2e},
{0xab30, 0xab6b},
{0xab70, 0xabed},
{0xabf0, 0xabf9},
{0xac00, 0xd7a3},
{0xd7b0, 0xd7c6},
{0xd7cb, 0xd7fb},
{0xd800, 0xfa6d},
{0xfa70, 0xfad9},
{0xfb00, 0xfb06},
{0xfb13, 0xfb17},
{0xfb1d, 0xfb36},
{0xfb38, 0xfb3c},
{0xfb3e, 0xfb3e},
{0xfb40, 0xfb41},
{0xfb43, 0xfb44},
{0xfb46, 0xfbc2},
{0xfbd3, 0xfd8f},
{0xfd92, 0xfdc7},
{0xfdcf, 0xfdcf},
{0xfdf0, 0xfe19},
{0xfe20, 0xfe52},
{0xfe54, 0xfe66},
{0xfe68, 0xfe6b},
{0xfe70, 0xfe74},
{0xfe76, 0xfefc},
{0xfeff, 0xfeff},
{0xff01, 0xffbe},
{0xffc2, 0xffc7},
{0xffca, 0xffcf},
{0xffd2, 0xffd7},
{0xffda, 0xffdc},
{0xffe0, 0xffe6},
{0xffe8, 0xffee},
{0xfff9, 0xfffd},
{0x10000, 0x1000b},
{0x1000d, 0x10026},
{0x10028, 0x1003a},
{0x1003c, 0x1003d},
{0x1003f, 0x1004d},
{0x10050, 0x1005d},
{0x10080, 0x100fa},
{0x10100, 0x10102},
{0x10107, 0x10133},
{0x10137, 0x1018e},
{0x10190, 0x1019c},
{0x101a0, 0x101a0},
{0x101d0, 0x101fd},
{0x10280, 0x1029c},
{0x102a0, 0x102d0},
{0x102e0, 0x102fb},
{0x10300, 0x10323},
{0x1032d, 0x1034a},
{0x10350, 0x1037a},
{0x10380, 0x1039d},
{0x1039f, 0x103c3},
{0x103c8, 0x103d5},
{0x10400, 0x1049d},
{0x104a0, 0x104a9},
{0x104b0, 0x104d3},
{0x104d8, 0x104fb},
{0x10500, 0x10527},
{0x10530, 0x10563},
{0x1056f, 0x1057a},
{0x1057c, 0x1058a},
{0x1058c, 0x10592},
{0x10594, 0x10595},
{0x10597, 0x105a1},
{0x105a3, 0x105b1},
{0x105b3, 0x105b9},
{0x105bb, 0x105bc},
{0x10600, 0x10736},
{0x10740, 0x10755},
{0x10760, 0x10767},
{0x10780, 0x10785},
{0x10787, 0x107b0},
{0x107b2, 0x107ba},
{0x10800, 0x10805},
{0x10808, 0x10808},
{0x1080a, 0x10835},
{0x10837, 0x10838},
{0x1083c, 0x1083c},
{0x1083f, 0x10855},
{0x10857, 0x1089e},
{0x108a7, 0x108af},
{0x108e0, 0x108f2},
{0x108f4, 0x108f5},
{0x108fb, 0x1091b},
{0x1091f, 0x10939},
{0x1093f, 0x1093f},
{0x10980, 0x109b7},
{0x109bc, 0x109cf},
{0x109d2, 0x10a03},
{0x10a05, 0x10a06},
{0x10a0c, 0x10a13},
{0x10a15, 0x10a17},
{0x10a19, 0x10a35},
{0x10a38, 0x10a3a},
{0x10a3f, 0x10a48},
{0x10a50, 0x10a58},
{0x10a60, 0x10a9f},
{0x10ac0, 0x10ae6},
{0x10aeb, 0x10af6},
{0x10b00, 0x10b35},
{0x10b39, 0x10b55},
{0x10b58, 0x10b72},
{0x10b78, 0x10b91},
{0x10b99, 0x10b9c},
{0x10ba9, 0x10baf},
{0x10c00, 0x10c48},
{0x10c80, 0x10cb2},
{0x10cc0, 0x10cf2},
{0x10cfa, 0x10d27},
{0x10d30, 0x10d39},
{0x10e60, 0x10e7e},
{0x10e80, 0x10ea9},
{0x10eab, 0x10ead},
{0x10eb0, 0x10eb1},
{0x10efd, 0x10f27},
{0x10f30, 0x10f59},
{0x10f70, 0x10f89},
{0x10fb0, 0x10fcb},
{0x10fe0, 0x10ff6},
{0x11000, 0x1104d},
{0x11052, 0x11075},
{0x1107f, 0x110c2},
{0x110cd, 0x110cd},
{0x110d0, 0x110e8},
{0x110f0, 0x110f9},
{0x11100, 0x11134},
{0x11136, 0x11147},
{0x11150, 0x11176},
{0x11180, 0x111df},
{0x111e1, 0x111f4},
{0x11200, 0x11211},
{0x11213, 0x11241},
{0x11280, 0x11286},
{0x11288, 0x11288},
{0x1128a, 0x1128d},
{0x1128f, 0x1129d},
{0x1129f, 0x112a9},
{0x112b0, 0x112ea},
{0x112f0, 0x112f9},
{0x11300, 0x11303},
{0x11305, 0x1130c},
{0x1130f, 0x11310},
{0x11313, 0x11328},
{0x1132a, 0x11330},
{0x11332, 0x11333},
{0x11335, 0x11339},
{0x1133b, 0x11344},
{0x11347, 0x11348},
{0x1134b, 0x1134d},
{0x11350, 0x11350},
{0x11357, 0x11357},
{0x1135d, 0x11363},
{0x11366, 0x1136c},
{0x11370, 0x11374},
{0x11400, 0x1145b},
{0x1145d, 0x11461},
{0x11480, 0x114c7},
{0x114d0, 0x114d9},
{0x11580, 0x115b5},
{0x115b8, 0x115dd},
{0x11600, 0x11644},
{0x11650, 0x11659},
{0x11660, 0x1166c},
{0x11680, 0x116b9},
{0x116c0, 0x116c9},
{0x11700, 0x1171a},
{0x1171d, 0x1172b},
{0x11730, 0x11746},
{0x11800, 0x1183b},
{0x118a0, 0x118f2},
{0x118ff, 0x11906},
{0x11909, 0x11909},
{0x1190c, 0x11913},
{0x11915, 0x11916},
{0x11918, 0x11935},
{0x11937, 0x11938},
{0x1193b, 0x11946},
{0x11950, 0x11959},
{0x119a0, 0x119a7},
{0x119aa, 0x119d7},
{0x119da, 0x119e4},
{0x11a00, 0x11a47},
{0x11a50, 0x11aa2},
{0x11ab0, 0x11af8},
{0x11b00, 0x11b09},
{0x11c00, 0x11c08},
{0x11c0a, 0x11c36},
{0x11c38, 0x11c45},
{0x11c50, 0x11c6c},
{0x11c70, 0x11c8f},
{0x11c92, 0x11ca7},
{0x11ca9, 0x11cb6},
{0x11d00, 0x11d06},
{0x11d08, 0x11d09},
{0x11d0b, 0x11d36},
{0x11d3a, 0x11d3a},
{0x11d3c, 0x11d3d},
{0x11d3f, 0x11d47},
{0x11d50, 0x11d59},
{0x11d60, 0x11d65},
{0x11d67, 0x11d68},
{0x11d6a, 0x11d8e},
{0x11d90, 0x11d91},
{0x11d93, 0x11d98},
{0x11da0, 0x11da9},
{0x11ee0, 0x11ef8},
{0x11f00, 0x11f10},
{0x11f12, 0x11f3a},
{0x11f3e, 0x11f59},
{0x11fb0, 0x11fb0},
{0x11fc0, 0x11ff1},
{0x11fff, 0x12399},
{0x12400, 0x1246e},
{0x12470, 0x12474},
{0x12480, 0x12543},
{0x12f90, 0x12ff2},
{0x13000, 0x13455},
{0x14400, 0x14646},
{0x16800, 0x16a38},
{0x16a40, 0x16a5e},
{0x16a60, 0x16a69},
{0x16a6e, 0x16abe},
{0x16ac0, 0x16ac9},
{0x16ad0, 0x16aed},
{0x16af0, 0x16af5},
{0x16b00, 0x16b45},
{0x16b50, 0x16b59},
{0x16b5b, 0x16b61},
{0x16b63, 0x16b77},
{0x16b7d, 0x16b8f},
{0x16e40, 0x16e9a},
{0x16f00, 0x16f4a},
{0x16f4f, 0x16f87},
{0x16f8f, 0x16f9f},
{0x16fe0, 0x16fe4},
{0x16ff0, 0x16ff1},
{0x17000, 0x187f7},
{0x18800, 0x18cd5},
{0x18d00, 0x18d08},
{0x1aff0, 0x1aff3},
{0x1aff5, 0x1affb},
{0x1affd, 0x1affe},
{0x1b000, 0x1b122},
{0x1b132, 0x1b132},
{0x1b150, 0x1b152},
{0x1b155, 0x1b155},
{0x1b164, 0x1b167},
{0x1b170, 0x1b2fb},
{0x1bc00, 0x1bc6a},
{0x1bc70, 0x1bc7c},
{0x1bc80, 0x1bc88},
{0x1bc90, 0x1bc99},
{0x1bc9c, 0x1bca3},
{0x1cf00, 0x1cf2d},
{0x1cf30, 0x1cf46},
{0x1cf50, 0x1cfc3},
{0x1d000, 0x1d0f5},
{0x1d100, 0x1d126},
{0x1d129, 0x1d1ea},
{0x1d200, 0x1d245},
{0x1d2c0, 0x1d2d3},
{0x1d2e0, 0x1d2f3},
{0x1d300, 0x1d356},
{0x1d360, 0x1d378},
{0x1d400, 0x1d454},
{0x1d456, 0x1d49c},
{0x1d49e, 0x1d49f},
{0x1d4a2, 0x1d4a2},
{0x1d4a5, 0x1d4a6},
{0x1d4a9, 0x1d4ac},
{0x1d4ae, 0x1d4b9},
{0x1d4bb, 0x1d4bb},
{0x1d4bd, 0x1d4c3},
{0x1d4c5, 0x1d505},
{0x1d507, 0x1d50a},
{0x1d50d, 0x1d514},
{0x1d516, 0x1d51c},
{0x1d51e, 0x1d539},
{0x1d53b, 0x1d53e},
{0x1d540, 0x1d544},
{0x1d546, 0x1d546},
{0x1d54a, 0x1d550},
{0x1d552, 0x1d6a5},
{0x1d6a8, 0x1d7cb},
{0x1d7ce, 0x1da8b},
{0x1da9b, 0x1da9f},
{0x1daa1, 0x1daaf},
{0x1df00, 0x1df1e},
{0x1df25, 0x1df2a},
{0x1e000, 0x1e006},
{0x1e008, 0x1e018},
{0x1e01b, 0x1e021},
{0x1e023, 0x1e024},
{0x1e026, 0x1e02a},
{0x1e030, 0x1e06d},
{0x1e08f, 0x1e08f},
{0x1e100, 0x1e12c},
{0x1e130, 0x1e13d},
{0x1e140, 0x1e149},
{0x1e14e, 0x1e14f},
{0x1e290, 0x1e2ae},
{0x1e2c0, 0x1e2f9},
{0x1e2ff, 0x1e2ff},
{0x1e4d0, 0x1e4f9},
{0x1e7e0, 0x1e7e6},
{0x1e7e8, 0x1e7eb},
{0x1e7ed, 0x1e7ee},
{0x1e7f0, 0x1e7fe},
{0x1e800, 0x1e8c4},
{0x1e8c7, 0x1e8d6},
{0x1e900, 0x1e94b},
{0x1e950, 0x1e959},
{0x1e95e, 0x1e95f},
{0x1ec71, 0x1ecb4},
{0x1ed01, 0x1ed3d},
{0x1ee00, 0x1ee03},
{0x1ee05, 0x1ee1f},
{0x1ee21, 0x1ee22},
{0x1ee24, 0x1ee24},
{0x1ee27, 0x1ee27},
{0x1ee29, 0x1ee32},
{0x1ee34, 0x1ee37},
{0x1ee39, 0x1ee39},
{0x1ee3b, 0x1ee3b},
{0x1ee42, 0x1ee42},
{0x1ee47, 0x1ee47},
{0x1ee49, 0x1ee49},
{0x1ee4b, 0x1ee4b},
{0x1ee4d, 0x1ee4f},
{0x1ee51, 0x1ee52},
{0x1ee54, 0x1ee54},
{0x1ee57, 0x1ee57},
{0x1ee59, 0x1ee59},
{0x1ee5b, 0x1ee5b},
{0x1ee5d, 0x1ee5d},
{0x1ee5f, 0x1ee5f},
{0x1ee61, 0x1ee62},
{0x1ee64, 0x1ee64},
{0x1ee67, 0x1ee6a},
{0x1ee6c, 0x1ee72},
{0x1ee74, 0x1ee77},
{0x1ee79, 0x1ee7c},
{0x1ee7e, 0x1ee7e},
{0x1ee80, 0x1ee89},
{0x1ee8b, 0x1ee9b},
{0x1eea1, 0x1eea3},
{0x1eea5, 0x1eea9},
{0x1eeab, 0x1eebb},
{0x1eef0, 0x1eef1},
{0x1f000, 0x1f02b},
{0x1f030, 0x1f093},
{0x1f0a0, 0x1f0ae},
{0x1f0b1, 0x1f0bf},
{0x1f0c1, 0x1f0cf},
{0x1f0d1, 0x1f0f5},
{0x1f100, 0x1f1ad},
{0x1f1e6, 0x1f202},
{0x1f210, 0x1f23b},
{0x1f240, 0x1f248},
{0x1f250, 0x1f251},
{0x1f260, 0x1f265},
{0x1f300, 0x1f6d7},
{0x1f6dc, 0x1f6ec},
{0x1f6f0, 0x1f6fc},
{0x1f700, 0x1f776},
{0x1f77b, 0x1f7d9},
{0x1f7e0, 0x1f7eb},
{0x1f7f0, 0x1f7f0},
{0x1f800, 0x1f80b},
{0x1f810, 0x1f847},
{0x1f850, 0x1f859},
{0x1f860, 0x1f887},
{0x1f890, 0x1f8ad},
{0x1f8b0, 0x1f8b1},
{0x1f900, 0x1fa53},
{0x1fa60, 0x1fa6d},
{0x1fa70, 0x1fa7c},
{0x1fa80, 0x1fa88},
{0x1fa90, 0x1fabd},
{0x1fabf, 0x1fac5},
{0x1face, 0x1fadb},
{0x1fae0, 0x1fae8},
{0x1faf0, 0x1faf8},
{0x1fb00, 0x1fb92},
{0x1fb94, 0x1fbca},
{0x1fbf0, 0x1fbf9},
{0x20000, 0x2a6df},
{0x2a700, 0x2b739},
{0x2b740, 0x2b81d},
{0x2b820, 0x2cea1},
{0x2ceb0, 0x2ebe0},
{0x2f800, 0x2fa1d},
{0x30000, 0x3134a},
{0x31350, 0x323af},
{0xe0001, 0xe0001},
{0xe0020, 0xe007f},
{0xe0100, 0xe01ef},
{0xf0000, 0xffffd},
{0x100000, 0x10fffd},

366
unicode/nonspacing_chars.h Normal file
View file

@ -0,0 +1,366 @@
/*
* Autogenerated by read_ucd.py from The Unicode Standard 15.0.0
*
* Identify Unicode characters that occupy no character cells of a
* terminal.
*
* Used by utils/wcwidth.c.
*/
{0x0300, 0x036f},
{0x0483, 0x0489},
{0x0591, 0x05bd},
{0x05bf, 0x05bf},
{0x05c1, 0x05c2},
{0x05c4, 0x05c5},
{0x05c7, 0x05c7},
{0x0600, 0x0605},
{0x0610, 0x061a},
{0x061c, 0x061c},
{0x064b, 0x065f},
{0x0670, 0x0670},
{0x06d6, 0x06dd},
{0x06df, 0x06e4},
{0x06e7, 0x06e8},
{0x06ea, 0x06ed},
{0x070f, 0x070f},
{0x0711, 0x0711},
{0x0730, 0x074a},
{0x07a6, 0x07b0},
{0x07eb, 0x07f3},
{0x07fd, 0x07fd},
{0x0816, 0x0819},
{0x081b, 0x0823},
{0x0825, 0x0827},
{0x0829, 0x082d},
{0x0859, 0x085b},
{0x0890, 0x0891},
{0x0898, 0x089f},
{0x08ca, 0x0902},
{0x093a, 0x093a},
{0x093c, 0x093c},
{0x0941, 0x0948},
{0x094d, 0x094d},
{0x0951, 0x0957},
{0x0962, 0x0963},
{0x0981, 0x0981},
{0x09bc, 0x09bc},
{0x09c1, 0x09c4},
{0x09cd, 0x09cd},
{0x09e2, 0x09e3},
{0x09fe, 0x09fe},
{0x0a01, 0x0a02},
{0x0a3c, 0x0a3c},
{0x0a41, 0x0a42},
{0x0a47, 0x0a48},
{0x0a4b, 0x0a4d},
{0x0a51, 0x0a51},
{0x0a70, 0x0a71},
{0x0a75, 0x0a75},
{0x0a81, 0x0a82},
{0x0abc, 0x0abc},
{0x0ac1, 0x0ac5},
{0x0ac7, 0x0ac8},
{0x0acd, 0x0acd},
{0x0ae2, 0x0ae3},
{0x0afa, 0x0aff},
{0x0b01, 0x0b01},
{0x0b3c, 0x0b3c},
{0x0b3f, 0x0b3f},
{0x0b41, 0x0b44},
{0x0b4d, 0x0b4d},
{0x0b55, 0x0b56},
{0x0b62, 0x0b63},
{0x0b82, 0x0b82},
{0x0bc0, 0x0bc0},
{0x0bcd, 0x0bcd},
{0x0c00, 0x0c00},
{0x0c04, 0x0c04},
{0x0c3c, 0x0c3c},
{0x0c3e, 0x0c40},
{0x0c46, 0x0c48},
{0x0c4a, 0x0c4d},
{0x0c55, 0x0c56},
{0x0c62, 0x0c63},
{0x0c81, 0x0c81},
{0x0cbc, 0x0cbc},
{0x0cbf, 0x0cbf},
{0x0cc6, 0x0cc6},
{0x0ccc, 0x0ccd},
{0x0ce2, 0x0ce3},
{0x0d00, 0x0d01},
{0x0d3b, 0x0d3c},
{0x0d41, 0x0d44},
{0x0d4d, 0x0d4d},
{0x0d62, 0x0d63},
{0x0d81, 0x0d81},
{0x0dca, 0x0dca},
{0x0dd2, 0x0dd4},
{0x0dd6, 0x0dd6},
{0x0e31, 0x0e31},
{0x0e34, 0x0e3a},
{0x0e47, 0x0e4e},
{0x0eb1, 0x0eb1},
{0x0eb4, 0x0ebc},
{0x0ec8, 0x0ece},
{0x0f18, 0x0f19},
{0x0f35, 0x0f35},
{0x0f37, 0x0f37},
{0x0f39, 0x0f39},
{0x0f71, 0x0f7e},
{0x0f80, 0x0f84},
{0x0f86, 0x0f87},
{0x0f8d, 0x0f97},
{0x0f99, 0x0fbc},
{0x0fc6, 0x0fc6},
{0x102d, 0x1030},
{0x1032, 0x1037},
{0x1039, 0x103a},
{0x103d, 0x103e},
{0x1058, 0x1059},
{0x105e, 0x1060},
{0x1071, 0x1074},
{0x1082, 0x1082},
{0x1085, 0x1086},
{0x108d, 0x108d},
{0x109d, 0x109d},
{0x1160, 0x11ff},
{0x135d, 0x135f},
{0x1712, 0x1714},
{0x1732, 0x1733},
{0x1752, 0x1753},
{0x1772, 0x1773},
{0x17b4, 0x17b5},
{0x17b7, 0x17bd},
{0x17c6, 0x17c6},
{0x17c9, 0x17d3},
{0x17dd, 0x17dd},
{0x180b, 0x180f},
{0x1885, 0x1886},
{0x18a9, 0x18a9},
{0x1920, 0x1922},
{0x1927, 0x1928},
{0x1932, 0x1932},
{0x1939, 0x193b},
{0x1a17, 0x1a18},
{0x1a1b, 0x1a1b},
{0x1a56, 0x1a56},
{0x1a58, 0x1a5e},
{0x1a60, 0x1a60},
{0x1a62, 0x1a62},
{0x1a65, 0x1a6c},
{0x1a73, 0x1a7c},
{0x1a7f, 0x1a7f},
{0x1ab0, 0x1ace},
{0x1b00, 0x1b03},
{0x1b34, 0x1b34},
{0x1b36, 0x1b3a},
{0x1b3c, 0x1b3c},
{0x1b42, 0x1b42},
{0x1b6b, 0x1b73},
{0x1b80, 0x1b81},
{0x1ba2, 0x1ba5},
{0x1ba8, 0x1ba9},
{0x1bab, 0x1bad},
{0x1be6, 0x1be6},
{0x1be8, 0x1be9},
{0x1bed, 0x1bed},
{0x1bef, 0x1bf1},
{0x1c2c, 0x1c33},
{0x1c36, 0x1c37},
{0x1cd0, 0x1cd2},
{0x1cd4, 0x1ce0},
{0x1ce2, 0x1ce8},
{0x1ced, 0x1ced},
{0x1cf4, 0x1cf4},
{0x1cf8, 0x1cf9},
{0x1dc0, 0x1dff},
{0x200b, 0x200f},
{0x202a, 0x202e},
{0x2060, 0x2064},
{0x2066, 0x206f},
{0x20d0, 0x20f0},
{0x2cef, 0x2cf1},
{0x2d7f, 0x2d7f},
{0x2de0, 0x2dff},
{0x302a, 0x302d},
{0x3099, 0x309a},
{0xa66f, 0xa672},
{0xa674, 0xa67d},
{0xa69e, 0xa69f},
{0xa6f0, 0xa6f1},
{0xa802, 0xa802},
{0xa806, 0xa806},
{0xa80b, 0xa80b},
{0xa825, 0xa826},
{0xa82c, 0xa82c},
{0xa8c4, 0xa8c5},
{0xa8e0, 0xa8f1},
{0xa8ff, 0xa8ff},
{0xa926, 0xa92d},
{0xa947, 0xa951},
{0xa980, 0xa982},
{0xa9b3, 0xa9b3},
{0xa9b6, 0xa9b9},
{0xa9bc, 0xa9bd},
{0xa9e5, 0xa9e5},
{0xaa29, 0xaa2e},
{0xaa31, 0xaa32},
{0xaa35, 0xaa36},
{0xaa43, 0xaa43},
{0xaa4c, 0xaa4c},
{0xaa7c, 0xaa7c},
{0xaab0, 0xaab0},
{0xaab2, 0xaab4},
{0xaab7, 0xaab8},
{0xaabe, 0xaabf},
{0xaac1, 0xaac1},
{0xaaec, 0xaaed},
{0xaaf6, 0xaaf6},
{0xabe5, 0xabe5},
{0xabe8, 0xabe8},
{0xabed, 0xabed},
{0xfb1e, 0xfb1e},
{0xfe00, 0xfe0f},
{0xfe20, 0xfe2f},
{0xfeff, 0xfeff},
{0xfff9, 0xfffb},
{0x101fd, 0x101fd},
{0x102e0, 0x102e0},
{0x10376, 0x1037a},
{0x10a01, 0x10a03},
{0x10a05, 0x10a06},
{0x10a0c, 0x10a0f},
{0x10a38, 0x10a3a},
{0x10a3f, 0x10a3f},
{0x10ae5, 0x10ae6},
{0x10d24, 0x10d27},
{0x10eab, 0x10eac},
{0x10efd, 0x10eff},
{0x10f46, 0x10f50},
{0x10f82, 0x10f85},
{0x11001, 0x11001},
{0x11038, 0x11046},
{0x11070, 0x11070},
{0x11073, 0x11074},
{0x1107f, 0x11081},
{0x110b3, 0x110b6},
{0x110b9, 0x110ba},
{0x110bd, 0x110bd},
{0x110c2, 0x110c2},
{0x110cd, 0x110cd},
{0x11100, 0x11102},
{0x11127, 0x1112b},
{0x1112d, 0x11134},
{0x11173, 0x11173},
{0x11180, 0x11181},
{0x111b6, 0x111be},
{0x111c9, 0x111cc},
{0x111cf, 0x111cf},
{0x1122f, 0x11231},
{0x11234, 0x11234},
{0x11236, 0x11237},
{0x1123e, 0x1123e},
{0x11241, 0x11241},
{0x112df, 0x112df},
{0x112e3, 0x112ea},
{0x11300, 0x11301},
{0x1133b, 0x1133c},
{0x11340, 0x11340},
{0x11366, 0x1136c},
{0x11370, 0x11374},
{0x11438, 0x1143f},
{0x11442, 0x11444},
{0x11446, 0x11446},
{0x1145e, 0x1145e},
{0x114b3, 0x114b8},
{0x114ba, 0x114ba},
{0x114bf, 0x114c0},
{0x114c2, 0x114c3},
{0x115b2, 0x115b5},
{0x115bc, 0x115bd},
{0x115bf, 0x115c0},
{0x115dc, 0x115dd},
{0x11633, 0x1163a},
{0x1163d, 0x1163d},
{0x1163f, 0x11640},
{0x116ab, 0x116ab},
{0x116ad, 0x116ad},
{0x116b0, 0x116b5},
{0x116b7, 0x116b7},
{0x1171d, 0x1171f},
{0x11722, 0x11725},
{0x11727, 0x1172b},
{0x1182f, 0x11837},
{0x11839, 0x1183a},
{0x1193b, 0x1193c},
{0x1193e, 0x1193e},
{0x11943, 0x11943},
{0x119d4, 0x119d7},
{0x119da, 0x119db},
{0x119e0, 0x119e0},
{0x11a01, 0x11a0a},
{0x11a33, 0x11a38},
{0x11a3b, 0x11a3e},
{0x11a47, 0x11a47},
{0x11a51, 0x11a56},
{0x11a59, 0x11a5b},
{0x11a8a, 0x11a96},
{0x11a98, 0x11a99},
{0x11c30, 0x11c36},
{0x11c38, 0x11c3d},
{0x11c3f, 0x11c3f},
{0x11c92, 0x11ca7},
{0x11caa, 0x11cb0},
{0x11cb2, 0x11cb3},
{0x11cb5, 0x11cb6},
{0x11d31, 0x11d36},
{0x11d3a, 0x11d3a},
{0x11d3c, 0x11d3d},
{0x11d3f, 0x11d45},
{0x11d47, 0x11d47},
{0x11d90, 0x11d91},
{0x11d95, 0x11d95},
{0x11d97, 0x11d97},
{0x11ef3, 0x11ef4},
{0x11f00, 0x11f01},
{0x11f36, 0x11f3a},
{0x11f40, 0x11f40},
{0x11f42, 0x11f42},
{0x13430, 0x13440},
{0x13447, 0x13455},
{0x16af0, 0x16af4},
{0x16b30, 0x16b36},
{0x16f4f, 0x16f4f},
{0x16f8f, 0x16f92},
{0x16fe4, 0x16fe4},
{0x1bc9d, 0x1bc9e},
{0x1bca0, 0x1bca3},
{0x1cf00, 0x1cf2d},
{0x1cf30, 0x1cf46},
{0x1d167, 0x1d169},
{0x1d173, 0x1d182},
{0x1d185, 0x1d18b},
{0x1d1aa, 0x1d1ad},
{0x1d242, 0x1d244},
{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},
{0x1e8d0, 0x1e8d6},
{0x1e944, 0x1e94a},
{0xe0001, 0xe0001},
{0xe0020, 0xe007f},
{0xe0100, 0xe01ef},

510
unicode/read_ucd.py Executable file
View file

@ -0,0 +1,510 @@
#!/usr/bin/env python3
# Tool to read various files from the Unicode character database and
# generate headers containing derived arrays and lookup tables needed
# by PuTTY.
#
# The aim is to have this be a single tool which you can easily re-run
# against a new version of Unicode, simply by pointing it at an
# appropriate UCD.zip or a directory containing the same files
# unpacked.
import argparse
import collections
import io
import os
import string
import sys
import zipfile
UCDRecord = collections.namedtuple('UCDRecord', [
'c',
'General_Category',
'Canonical_Combining_Class',
'Bidi_Class',
'Decomposition_Type',
'Decomposition_Mapping',
])
def to_ranges(iterable):
"""Collect together adjacent ranges in a list of (key, value) pairs.
The input iterable should deliver a sequence of (key, value) pairs
in which the keys are integers in sorted order. The output is a
sequence of tuples with structure ((start, end), value), each
indicating that all the keys [start, start+1, ..., end] go with
that value.
"""
start = end = val = None
for k, v in iterable:
if (k-1, v) == (end, val):
end = k
else:
if start is not None:
yield (start, end), val
start, end, val = k, k, v
if start is not None:
yield (start, end), val
def map_to_ranges(m):
"""Convert an integer-keyed map into a list of (range, value) pairs."""
yield from to_ranges(sorted(m.items()))
def set_to_ranges(s):
"""Convert a set into a list of ranges."""
for r, _ in to_ranges((x, None) for x in sorted(s)):
yield r
def lines(iterable, keep_comments=False):
"""Deliver the lines of a Unicode data file.
The input iterable should yield raw lines of the file: for
example, it can be the file handle itself. The output values have
their newlines removed, comments and trailing spaces deleted, and
blank lines discarded.
"""
for line in iter(iterable):
line = line.rstrip("\r\n")
if not keep_comments:
line = line.split("#", 1)[0]
line = line.rstrip(" \t")
if line == "":
continue
yield line
class Main:
def run(self):
"Parse arguments and generate all the output files."
parser = argparse.ArgumentParser(
description='Build UCD-derived source files.')
parser.add_argument("ucd", help="UCD to work from, either UCD.zip or "
"a directory full of unpacked files.")
args = parser.parse_args()
if os.path.isdir(args.ucd):
ucd_dir = args.ucd
self.open_ucd_file = lambda filename: (
open(os.path.join(ucd_dir, filename)))
else:
ucd_zip = zipfile.ZipFile(args.ucd)
self.open_ucd_file = lambda filename: (
io.TextIOWrapper(ucd_zip.open(filename)))
self.find_unicode_version()
with open("version.h", "w") as fh:
self.write_version_header(fh)
with open("bidi_type.h", "w") as fh:
self.write_bidi_type_table(fh)
with open("bidi_mirror.h", "w") as fh:
self.write_bidi_mirroring_table(fh)
with open("bidi_brackets.h", "w") as fh:
self.write_bidi_brackets_table(fh)
with open("nonspacing_chars.h", "w") as fh:
self.write_nonspacing_chars_list(fh)
with open("wide_chars.h", "w") as fh:
self.write_wide_chars_list(fh)
with open("ambiguous_wide_chars.h", "w") as fh:
self.write_ambiguous_wide_chars_list(fh)
with open("known_chars.h", "w") as fh:
self.write_known_chars_table(fh)
with open("combining_classes.h", "w") as fh:
self.write_combining_class_table(fh)
with open("canonical_decomp.h", "w") as fh:
self.write_canonical_decomp_table(fh)
with open("canonical_comp.h", "w") as fh:
self.write_canonical_comp_table(fh)
def find_unicode_version(self):
"""Find out the version of Unicode.
This is read from the top of NamesList.txt, which has the
closest thing to a machine-readable statement of the version
number that I found in the whole collection of files.
"""
with self.open_ucd_file("NamesList.txt") as fh:
for line in lines(fh):
if line.startswith("@@@\t"):
self.unicode_version_full = line[4:]
self.unicode_version_short = " ".join(
w for w in self.unicode_version_full.split(" ")
if any(c in string.digits for c in w))
return
@property
def UnicodeData(self):
"""Records from UnicodeData.txt.
Each yielded item is a UCDRecord tuple.
"""
with self.open_ucd_file("UnicodeData.txt") as fh:
for line in lines(fh):
# Split up the line into its raw fields.
(
codepoint, name, category, cclass, bidiclass, decomp,
num6, num7, num8, bidimirrored, obsolete_unicode1_name,
obsolete_comment, uppercase, lowercase, titlecase,
) = line.split(";")
# By default, we expect that this record describes
# just one code point.
codepoints = [int(codepoint, 16)]
# Spot the special markers where consecutive lines say
# <Foo, First> and <Foo, Last>, indicating that the
# entire range of code points in between are treated
# the same. If so, we replace 'codepoints' with a
# range object.
if "<" in name:
assert name.startswith("<") and name.endswith(">"), (
"Confusing < in character name: {!r}".format(line))
name_pieces = [piece.strip(" \t") for piece in
name.lstrip("<").rstrip(">").split(",")]
if "First" in name_pieces:
assert isinstance(codepoints, list)
prev_line_was_first = True
prev_codepoint = codepoints[0]
continue
elif "Last" in name_pieces:
assert prev_line_was_first
codepoints = range(prev_codepoint, codepoints[0]+1)
del prev_codepoint
prev_line_was_first = False
# Decode some of the raw fields into more cooked
# forms.
cclass = int(cclass)
# Separate the decomposition field into decomposition
# type and mapping.
if decomp == "":
dtype = decomp = None
elif "<" not in decomp:
dtype = 'canonical'
else:
assert decomp.startswith("<")
dtype, decomp = decomp[1:].split(">", 1)
decomp = decomp.lstrip(" ")
# And decode the mapping part from hex strings to integers.
if decomp is not None:
decomp = [int(w, 16) for w in decomp.split(" ")]
# And yield a UCDRecord for each code point in our
# range.
for codepoint in codepoints:
yield UCDRecord(
c=codepoint,
General_Category=category,
Canonical_Combining_Class=cclass,
Bidi_Class=bidiclass,
Decomposition_Type=dtype,
Decomposition_Mapping=decomp,
)
@property
def BidiMirroring(self):
"""Parsed character pairs from BidiMirroring.txt.
Each yielded tuple is a pair of Unicode code points.
"""
with self.open_ucd_file("BidiMirroring.txt") as fh:
for line in lines(fh):
cs1, cs2 = line.split(";")
c1 = int(cs1, 16)
c2 = int(cs2, 16)
yield c1, c2
@property
def BidiBrackets(self):
"""Bracket pairs from BidiBrackets.txt.
Each yielded tuple is a pair of Unicode code points, followed
by either 'o', 'c' or 'n' to indicate whether the first one is
an open or closing parenthesis or neither.
"""
with self.open_ucd_file("BidiBrackets.txt") as fh:
for line in lines(fh):
cs1, cs2, kind = line.split(";")
c1 = int(cs1, 16)
c2 = int(cs2, 16)
kind = kind.strip(" \t")
yield c1, c2, kind
@property
def EastAsianWidth(self):
"""East Asian width types from EastAsianWidth.txt.
Each yielded tuple is (code point, width type).
"""
with self.open_ucd_file("EastAsianWidth.txt") as fh:
for line in lines(fh):
fields = line.split(";")
if ".." in fields[0]:
start, end = [int(s, 16) for s in fields[0].split("..")]
cs = range(start, end+1)
else:
cs = [int(fields[0], 16)]
for c in cs:
yield c, fields[1]
@property
def CompositionExclusions(self):
"""Composition exclusions from CompositionExclusions.txt.
Each yielded item is just a code point.
"""
with self.open_ucd_file("CompositionExclusions.txt") as fh:
for line in lines(fh):
yield int(line, 16)
def write_file_header_comment(self, fh, description):
print("/*", file=fh)
print(" * Autogenerated by read_ucd.py from",
self.unicode_version_full, file=fh)
print(" *", file=fh)
for line in description.strip("\n").split("\n"):
print(" *" + (" " if line != "" else "") + line, file=fh)
print(" */", file=fh)
print(file=fh)
def write_version_header(self, fh):
self.write_file_header_comment(fh, """
String literals giving the currently supported version of Unicode.
Useful for error messages and 'about' boxes.
""")
assert all(0x20 <= ord(c) < 0x7F and c != '"'
for c in self.unicode_version_full)
print("#define UNICODE_VERSION_FULL \"{}\"".format(
self.unicode_version_full), file=fh)
print("#define UNICODE_VERSION_SHORT \"{}\"".format(
self.unicode_version_short), file=fh)
def write_bidi_type_table(self, fh):
self.write_file_header_comment(fh, """
Bidirectional type of every Unicode character, excluding those with
type ON.
Used by terminal/bidi.c, whose associated lookup function returns ON
by default for anything not in this list.
""")
types = {}
for rec in self.UnicodeData:
if rec.Bidi_Class != "ON":
types[rec.c] = rec.Bidi_Class
for (start, end), t in map_to_ranges(types):
print(f"{{0x{start:04x}, 0x{end:04x}, {t}}},", file=fh)
def write_bidi_mirroring_table(self, fh):
self.write_file_header_comment(fh, """
Map each Unicode character to its mirrored form when printing right to
left.
Used by terminal/bidi.c.
""")
bidi_mirror = {}
for c1, c2 in self.BidiMirroring:
assert bidi_mirror.get(c1, c2) == c2, f"Clash at {c1:%04X}"
bidi_mirror[c1] = c2
assert bidi_mirror.get(c2, c1) == c1, f"Clash at {c2:%04X}"
bidi_mirror[c2] = c1
for c1, c2 in sorted(bidi_mirror.items()):
print("{{0x{:04x}, 0x{:04x}}},".format(c1, c2), file=fh)
def write_bidi_brackets_table(self, fh):
self.write_file_header_comment(fh, """
Identify Unicode characters that count as brackets for the purposes of
bidirectional text layout. For each one, indicate whether it's an open
or closed bracket, and identify up to two characters that can act as
its counterpart.
Used by terminal/bidi.c.
""")
bracket_map = {}
for c1, c2, kind in self.BidiBrackets:
bracket_map[c1] = kind, c2
equivalents = {}
for rec in self.UnicodeData:
if (rec.Decomposition_Type == 'canonical' and
len(rec.Decomposition_Mapping) == 1):
c = rec.c
c2 = rec.Decomposition_Mapping[0]
equivalents[c] = c2
equivalents[c2] = c
for src, (kind, dst) in sorted(bracket_map.items()):
dsteq = equivalents.get(dst, 0)
# UCD claims there's an 'n' kind possible, but as of UCD
# 14, no instances of it exist
enumval = {'o': 'BT_OPEN', 'c': 'BT_CLOSE'}[kind]
print("{{0x{:04x}, {{0x{:04x}, 0x{:04x}, {}}}}},".format(
src, dst, dsteq, enumval), file=fh)
def write_nonspacing_chars_list(self, fh):
self.write_file_header_comment(fh, """
Identify Unicode characters that occupy no character cells of a
terminal.
Used by utils/wcwidth.c.
""")
cs = set()
for rec in self.UnicodeData:
nonspacing = rec.General_Category in {"Me", "Mn", "Cf"}
if rec.c == 0xAD:
# In typography this is a SOFT HYPHEN and counts as
# discardable. But it's also an ISO 8859-1 printing
# character, and all of those occupy one character
# cell in a terminal.
nonspacing = False
if 0x1160 <= rec.c <= 0x11FF:
# Medial (vowel) and final (consonant) jamo for
# decomposed Hangul characters. These are regarded as
# non-spacing on the grounds that they compose with
# the preceding initial consonant.
nonspacing = True
if nonspacing:
cs.add(rec.c)
for start, end in set_to_ranges(cs):
print(f"{{0x{start:04x}, 0x{end:04x}}},", file=fh)
def write_width_table(self, fh, accept):
cs = set()
for c, wid in self.EastAsianWidth:
if wid in accept:
cs.add(c)
for start, end in set_to_ranges(cs):
print(f"{{0x{start:04x}, 0x{end:04x}}},", file=fh)
def write_wide_chars_list(self, fh):
self.write_file_header_comment(fh, """
Identify Unicode characters that occupy two adjacent character cells
in a terminal.
Used by utils/wcwidth.c.
""")
self.write_width_table(fh, {'W', 'F'})
def write_ambiguous_wide_chars_list(self, fh):
self.write_file_header_comment(fh, """
Identify Unicode characters that are width-ambiguous: some regimes
regard them as occupying two adjacent character cells in a terminal,
and others do not.
Used by utils/wcwidth.c.
""")
self.write_width_table(fh, {'A'})
def write_known_chars_table(self, fh):
self.write_file_header_comment(fh, """
List the Unicode code points that are known to this version of the
standard at all.
Used by utils/unicode-known.c.
""")
chars = set(rec.c for rec in self.UnicodeData)
for start, end in set_to_ranges(chars):
print(f"{{0x{start:04x}, 0x{end:04x}}},", file=fh)
def write_combining_class_table(self, fh):
self.write_file_header_comment(fh, """
List the canonical combining class of each Unicode character, if it is
not zero. This controls how combining marks can be reordered by the
Unicode normalisation algorithms.
Used by utils/unicode-norm.c.
""")
cclasses = {}
for rec in self.UnicodeData:
cc = rec.Canonical_Combining_Class
if cc != 0:
cclasses[rec.c] = cc
for (start, end), cclass in map_to_ranges(cclasses):
print(f"{{0x{start:04x}, 0x{end:04x}, {cclass:d}}},", file=fh)
def write_canonical_decomp_table(self, fh):
self.write_file_header_comment(fh, """
List the canonical decomposition of every Unicode character that has
one. This consists of up to two characters, but those may need
decomposition in turn.
Used by utils/unicode-norm.c.
""")
decomps = {}
for rec in self.UnicodeData:
if rec.Decomposition_Type != 'canonical':
continue
# Fill in a zero code point as the second character, if
# it's only one character long
decomps[rec.c] = (rec.Decomposition_Mapping + [0])[:2]
for c, (d1, d2) in sorted(decomps.items()):
d2s = f"0x{d2:04x}" if d2 else "0"
print(f"{{0x{c:04x}, 0x{d1:04x}, {d2s}}},", file=fh)
def write_canonical_comp_table(self, fh):
self.write_file_header_comment(fh, """
List the pairs of Unicode characters that canonically recompose to a
single character in NFC.
Used by utils/unicode-norm.c.
""")
exclusions = set(self.CompositionExclusions)
nonstarters = set(rec.c for rec in self.UnicodeData
if rec.Canonical_Combining_Class != 0)
decomps = {}
for rec in self.UnicodeData:
if rec.Decomposition_Type != 'canonical':
continue # we don't want compatibility decompositions
if len(rec.Decomposition_Mapping) != 2:
continue # we don't want singletons either
if rec.c in exclusions:
continue # we don't want anything explicitly excluded
if (rec.c in nonstarters or
rec.Decomposition_Mapping[0] in nonstarters):
continue # we don't want non-starter decompositions
decomps[tuple(rec.Decomposition_Mapping)] = rec.c
for (d0, d1), c in sorted(decomps.items()):
print(f"{{0x{d0:04x}, 0x{d1:04x}, 0x{c:04x}}},", file=fh)
if __name__ == '__main__':
Main().run()

9
unicode/version.h Normal file
View file

@ -0,0 +1,9 @@
/*
* Autogenerated by read_ucd.py from The Unicode Standard 15.0.0
*
* String literals giving the currently supported version of Unicode.
* Useful for error messages and 'about' boxes.
*/
#define UNICODE_VERSION_FULL "The Unicode Standard 15.0.0"
#define UNICODE_VERSION_SHORT "15.0.0"

130
unicode/wide_chars.h Normal file
View file

@ -0,0 +1,130 @@
/*
* Autogenerated by read_ucd.py from The Unicode Standard 15.0.0
*
* Identify Unicode characters that occupy two adjacent character cells
* in a terminal.
*
* Used by utils/wcwidth.c.
*/
{0x1100, 0x115f},
{0x231a, 0x231b},
{0x2329, 0x232a},
{0x23e9, 0x23ec},
{0x23f0, 0x23f0},
{0x23f3, 0x23f3},
{0x25fd, 0x25fe},
{0x2614, 0x2615},
{0x2648, 0x2653},
{0x267f, 0x267f},
{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, 0x2ffb},
{0x3000, 0x303e},
{0x3041, 0x3096},
{0x3099, 0x30ff},
{0x3105, 0x312f},
{0x3131, 0x318e},
{0x3190, 0x31e3},
{0x31f0, 0x321e},
{0x3220, 0x3247},
{0x3250, 0x4dbf},
{0x4e00, 0xa48c},
{0xa490, 0xa4c6},
{0xa960, 0xa97c},
{0xac00, 0xd7a3},
{0xf900, 0xfaff},
{0xfe10, 0xfe19},
{0xfe30, 0xfe52},
{0xfe54, 0xfe66},
{0xfe68, 0xfe6b},
{0xff01, 0xff60},
{0xffe0, 0xffe6},
{0x16fe0, 0x16fe4},
{0x16ff0, 0x16ff1},
{0x17000, 0x187f7},
{0x18800, 0x18cd5},
{0x18d00, 0x18d08},
{0x1aff0, 0x1aff3},
{0x1aff5, 0x1affb},
{0x1affd, 0x1affe},
{0x1b000, 0x1b122},
{0x1b132, 0x1b132},
{0x1b150, 0x1b152},
{0x1b155, 0x1b155},
{0x1b164, 0x1b167},
{0x1b170, 0x1b2fb},
{0x1f004, 0x1f004},
{0x1f0cf, 0x1f0cf},
{0x1f18e, 0x1f18e},
{0x1f191, 0x1f19a},
{0x1f200, 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, 0x1f6d7},
{0x1f6dc, 0x1f6df},
{0x1f6eb, 0x1f6ec},
{0x1f6f4, 0x1f6fc},
{0x1f7e0, 0x1f7eb},
{0x1f7f0, 0x1f7f0},
{0x1f90c, 0x1f93a},
{0x1f93c, 0x1f945},
{0x1f947, 0x1f9ff},
{0x1fa70, 0x1fa7c},
{0x1fa80, 0x1fa88},
{0x1fa90, 0x1fabd},
{0x1fabf, 0x1fac5},
{0x1face, 0x1fadb},
{0x1fae0, 0x1fae8},
{0x1faf0, 0x1faf8},
{0x20000, 0x2fffd},
{0x30000, 0x3fffd},

View file

@ -502,6 +502,8 @@ static Mouse_Button translate_button(Mouse_Button button)
return MBT_PASTE;
if (button == MBT_RIGHT)
return MBT_EXTEND;
if (button == MBT_NOTHING)
return MBT_NOTHING;
return 0; /* shouldn't happen */
}
@ -786,10 +788,11 @@ static void drawing_area_setup(GtkFrontend *inst, int width, int height)
inst->drawing_area_setup_called = true;
if (inst->term)
term_size(inst->term, h, w, conf_get_int(inst->conf, CONF_savelines));
if (inst->win_resize_pending) {
if (inst->term_resize_notification_required)
term_resize_request_completed(inst->term);
if (inst->win_resize_pending)
inst->win_resize_pending = false;
}
if (!inst->drawing_area_setup_needed)
return;
@ -2305,7 +2308,9 @@ gint motion_event(GtkWidget *widget, GdkEventMotion *event, gpointer data)
{
GtkFrontend *inst = (GtkFrontend *)data;
bool shift, ctrl, alt;
int x, y, button;
Mouse_Action action = MA_DRAG;
Mouse_Button button = MBT_NOTHING;
int x, y;
/* Remember the timestamp. */
inst->input_event_time = event->time;
@ -2325,12 +2330,12 @@ gint motion_event(GtkWidget *widget, GdkEventMotion *event, gpointer data)
else if (event->state & GDK_BUTTON3_MASK)
button = MBT_RIGHT;
else
return false; /* don't even know what button! */
action = MA_MOVE;
x = (event->x - inst->window_border) / inst->font_width;
y = (event->y - inst->window_border) / inst->font_height;
term_mouse(inst->term, button, translate_button(button), MA_DRAG,
term_mouse(inst->term, button, translate_button(button), action,
x, y, shift, ctrl, alt);
return true;

View file

@ -65,6 +65,8 @@ add_sources_from_current_dir(utils
stripctrl.c
tempseat.c
tree234.c
unicode-known.c
unicode-norm.c
validate_manual_hostkey.c
version.c
wcwidth.c

View file

@ -5,9 +5,11 @@
#include "putty.h"
#include "misc.h"
unsigned long decode_utf8(const char **utf8)
unsigned decode_utf8(BinarySource *src)
{
unsigned char c = (unsigned char)*(*utf8)++;
/* If the source has no byte available, this will return 0, which
* we'll return immediately and is a reasonable error return anyway */
unsigned char c = get_byte(src);
/* One-byte cases. */
if (c < 0x80) {
@ -33,10 +35,13 @@ unsigned long decode_utf8(const char **utf8)
}
while (ncont-- > 0) {
unsigned char cont = (unsigned char)**utf8;
if (!(0x80 <= cont && cont < 0xC0))
if (!get_avail(src))
return 0xFFFD; /* sequence terminated by end of data */
unsigned char cont = get_byte(src);
if (!(0x80 <= cont && cont < 0xC0)) {
BinarySource_REWIND_TO(src, src->pos - 1);
return 0xFFFD; /* short sequence */
(*utf8)++;
}
wc = (wc << 6) | (cont & 0x3F);
}
@ -54,23 +59,28 @@ unsigned long decode_utf8(const char **utf8)
#include <stdio.h>
bool dotest(const char *file, int line, const char *input,
void out_of_memory(void)
{
fprintf(stderr, "out of memory!\n");
exit(2);
}
bool dotest(const char *file, int line, const char *input, size_t ninput,
const unsigned long *chars, size_t nchars)
{
const char *start = input;
const char *end = input + strlen(input) + 1;
BinarySource src[1];
BinarySource_BARE_INIT(src, input, ninput);
size_t noutput = 0;
printf("%s:%d: test start\n", file, line);
while (input < end) {
const char *before = input;
unsigned long wc = decode_utf8(&input);
while (get_avail(src)) {
size_t before = src->pos;
unsigned long wc = decode_utf8(src);
printf("%s:%d in+%"SIZEu" out+%"SIZEu":",
file, line, (size_t)(before-start), noutput);
while (before < input)
printf(" %02x", (unsigned)(unsigned char)(*before++));
printf("%s:%d in+%"SIZEu" out+%"SIZEu":", file, line, before, noutput);
while (before < src->pos)
printf(" %02x", (unsigned)(unsigned char)(input[before++]));
printf(" -> U-%08lx\n", wc);
if (noutput >= nchars) {
@ -97,9 +107,10 @@ bool dotest(const char *file, int line, const char *input,
}
#define DOTEST(input, ...) do { \
static const unsigned long chars[] = { __VA_ARGS__, 0 }; \
static const unsigned long chars[] = { __VA_ARGS__ }; \
ntest++; \
if (dotest(__FILE__, __LINE__, input, chars, lenof(chars))) \
if (dotest(__FILE__, __LINE__, input, sizeof(input)-1, \
chars, lenof(chars))) \
npass++; \
} while (0)
@ -110,8 +121,8 @@ int main(void)
DOTEST("\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5",
0x03BA, 0x1F79, 0x03C3, 0x03BC, 0x03B5);
/* First sequence of each length (not counting NUL, which is
* tested anyway by the string-termination handling in every test) */
/* First sequence of each length */
DOTEST("\x00", 0x0000);
DOTEST("\xC2\x80", 0x0080);
DOTEST("\xE0\xA0\x80", 0x0800);
DOTEST("\xF0\x90\x80\x80", 0x00010000);
@ -128,7 +139,7 @@ int main(void)
/* Endpoints of the surrogate range */
DOTEST("\xED\x9F\xBF", 0xD7FF);
DOTEST("\xED\xA0\x00", 0xFFFD); /* would be 0xD800 */
DOTEST("\xED\xA0\x80", 0xFFFD); /* would be 0xD800 */
DOTEST("\xED\xBF\xBF", 0xFFFD); /* would be 0xDFFF */
DOTEST("\xEE\x80\x80", 0xE000);

View file

@ -5,10 +5,10 @@
#include "putty.h"
#include "misc.h"
size_t decode_utf8_to_wchar(const char **utf8, wchar_t *out)
size_t decode_utf8_to_wchar(BinarySource *src, wchar_t *out)
{
size_t outlen = 0;
unsigned wc = decode_utf8(utf8);
unsigned wc = decode_utf8(src);
if (sizeof(wchar_t) > 2 || wc < 0x10000) {
out[outlen++] = wc;
} else {

View file

@ -5,25 +5,22 @@
#include "defs.h"
#include "misc.h"
size_t encode_utf8(void *output, unsigned long ch)
void BinarySink_put_utf8_char(BinarySink *output, unsigned ch)
{
unsigned char *start = (unsigned char *)output, *p = start;
if (ch < 0x80) {
*p++ = ch;
put_byte(output, ch);
} else if (ch < 0x800) {
*p++ = 0xC0 | (ch >> 6);
*p++ = 0x80 | (ch & 0x3F);
put_byte(output, 0xC0 | (ch >> 6));
put_byte(output, 0x80 | (ch & 0x3F));
} else if (ch < 0x10000) {
*p++ = 0xE0 | (ch >> 12);
*p++ = 0x80 | ((ch >> 6) & 0x3F);
*p++ = 0x80 | (ch & 0x3F);
put_byte(output, 0xE0 | (ch >> 12));
put_byte(output, 0x80 | ((ch >> 6) & 0x3F));
put_byte(output, 0x80 | (ch & 0x3F));
} else {
assert(ch <= 0x10FFFF);
*p++ = 0xF0 | (ch >> 18);
*p++ = 0x80 | ((ch >> 12) & 0x3F);
*p++ = 0x80 | ((ch >> 6) & 0x3F);
*p++ = 0x80 | (ch & 0x3F);
put_byte(output, 0xF0 | (ch >> 18));
put_byte(output, 0x80 | ((ch >> 12) & 0x3F));
put_byte(output, 0x80 | ((ch >> 6) & 0x3F));
put_byte(output, 0x80 | (ch & 0x3F));
}
return p - start;
}

View file

@ -17,9 +17,7 @@ char *encode_wide_string_as_utf8(const wchar_t *ws)
} else if (IS_SURROGATE(ch)) {
ch = 0xfffd; /* illegal UTF-16 -> REPLACEMENT CHARACTER */
}
char utf8[6];
size_t size = encode_utf8(utf8, ch);
put_data(sb, utf8, size);
put_utf8_char(sb, ch);
}
return strbuf_to_str(sb);
}

View file

@ -336,3 +336,23 @@ void bufchain_sink_init(bufchain_sink *sink, bufchain *ch)
sink->ch = ch;
BinarySink_INIT(sink, bufchain_sink_write);
}
static void buffer_sink_write(BinarySink *bs, const void *data, size_t len)
{
buffer_sink *sink = BinarySink_DOWNCAST(bs, buffer_sink);
if (len > sink->space) {
len = sink->space;
sink->overflowed = true;
}
memcpy(sink->out, data, len);
sink->space -= len;
sink->out += len;
}
void buffer_sink_init(buffer_sink *sink, void *buffer, size_t len)
{
sink->out = buffer;
sink->space = len;
sink->overflowed = false;
BinarySink_INIT(sink, buffer_sink_write);
}

View file

@ -217,9 +217,6 @@ static inline void stripctrl_term_put_wc(
if (prefix.len)
put_datapl(scc->bs_out, prefix);
char outbuf[6];
size_t produced;
/*
* The Terminal implementation encodes 7-bit ASCII characters in
* UTF-8 mode, and all printing characters in non-UTF-8 (i.e.
@ -232,14 +229,10 @@ static inline void stripctrl_term_put_wc(
wc &= 0xFF;
if (in_utf(scc->term)) {
produced = encode_utf8(outbuf, wc);
put_utf8_char(scc->bs_out, wc);
} else {
outbuf[0] = wc;
produced = 1;
put_byte(scc->bs_out, wc);
}
if (produced > 0)
put_data(scc->bs_out, outbuf, produced);
}
static inline size_t stripctrl_locale_try_consume(

53
utils/unicode-known.c Normal file
View file

@ -0,0 +1,53 @@
/*
* Check a UTF-8 string to ensure every character in it is part of the
* version of Unicode that we understand.
*
* (If it isn't, then we don't know what combining properties it has,
* so we can't safely NFC it and rely on the result not changing when
* we later update our Unicode version.)
*/
#include "misc.h"
#include "unicode/version.h"
static bool known(unsigned c)
{
struct range {
unsigned start, end;
};
static const struct range ranges[] = {
#include "unicode/known_chars.h"
};
const struct range *start = ranges, *end = start + lenof(ranges);
while (end > start) {
const struct range *curr = start + (end-start) / 2;
if (c < curr->start)
end = curr;
else if (c > curr->end)
start = curr + 1;
else
return true;
}
return false;
};
char *utf8_unknown_char(ptrlen input)
{
BinarySource src[1];
BinarySource_BARE_INIT_PL(src, input);
for (size_t nchars = 0; get_avail(src); nchars++) {
unsigned c = decode_utf8(src);
if (!known(c))
return dupprintf(
"cannot stably normalise this string: code point %04X "
"(at character position %"SIZEu", byte position %"SIZEu") "
"is not in Unicode %s", c, nchars, src->pos,
UNICODE_VERSION_SHORT);
}
return NULL;
}

453
utils/unicode-norm.c Normal file
View file

@ -0,0 +1,453 @@
#include <stdio.h>
#include <string.h>
#include "misc.h"
typedef uint32_t uchar;
typedef int cclass_t;
/* A local uchar-oriented analogue of strbuf */
typedef struct ucharbuf {
uchar *buf;
size_t len, size;
} ucharbuf;
static ucharbuf *ucharbuf_new(void)
{
ucharbuf *ub = snew(ucharbuf);
ub->buf = NULL;
ub->len = ub->size = 0;
return ub;
}
static void ucharbuf_append(ucharbuf *ub, uchar c)
{
/* Use the _nm variant because this is used for passphrases */
sgrowarray_nm(ub->buf, ub->size, ub->len);
ub->buf[ub->len++] = c;
}
static void ucharbuf_free(ucharbuf *ub)
{
if (ub->buf) {
memset(ub->buf, 0, ub->size * sizeof(*ub->buf));
sfree(ub->buf);
}
sfree(ub);
}
/*
* Constants relating to the arithmetic decomposition mapping of
* Hangul to jamo, from section 3.12 of Unicode 15.0.0. The following
* constant names match those in the spec.
*/
enum {
SBase = 0xAC00, /* base index for precomposed Hangul */
LBase = 0x1100, /* base index for L (leading consonant) jamo */
VBase = 0x1161, /* base index for V (vowel) jamo */
TBase = 0x11A7, /* base index for T (trailing consonant) jamo */
LCount = 19, /* number of L jamo */
VCount = 21, /* number of V jamo */
TCount = 28, /* number of T jamo, including not having one at all */
NCount = VCount * TCount, /* number of Hangul for each L jamo */
SCount = LCount * NCount, /* number of Hangul in total */
};
static cclass_t combining_class(uchar c)
{
struct range {
uchar start, end;
cclass_t cclass;
};
static const struct range ranges[] = {
#include "unicode/combining_classes.h"
};
const struct range *start = ranges, *end = start + lenof(ranges);
while (end > start) {
const struct range *curr = start + (end-start) / 2;
if (c < curr->start)
end = curr;
else if (c > curr->end)
start = curr + 1;
else
return curr->cclass;
}
return 0;
};
static unsigned decompose_char(uchar c, uchar *out)
{
struct decomp {
uchar composed, dec0, dec1;
};
static const struct decomp decomps[] = {
#include "unicode/canonical_decomp.h"
};
if (c - SBase < SCount) {
/* Arithmetically decompose a Hangul character into jamo */
uchar SIndex = c - SBase;
uchar LIndex = SIndex / NCount;
uchar VIndex = SIndex % NCount / TCount;
uchar TIndex = SIndex % TCount;
unsigned n = 0;
out[n++] = LBase + LIndex;
out[n++] = VBase + VIndex;
if (TIndex)
out[n++] = TBase + TIndex;
return n;
}
const struct decomp *start = decomps, *end = start + lenof(decomps);
while (end > start) {
const struct decomp *curr = start + (end-start) / 2;
if (c < curr->composed)
end = curr;
else if (c > curr->composed)
start = curr + 1;
else {
out[0] = curr->dec0;
if (curr->dec1) {
out[1] = curr->dec1;
return 2;
} else {
return 1;
}
}
}
return 0;
};
static uchar compose_chars(uchar S, uchar C)
{
struct comp {
uchar dec0, dec1, composed;
};
static const struct comp comps[] = {
#include "unicode/canonical_comp.h"
};
if (S - LBase < LCount && C - VBase < VCount) {
/* Arithmetically compose an L and V jamo into a Hangul LV
* character */
return SBase + (S - LBase) * NCount + (C - VBase) * TCount;
}
if (S - SBase < SCount && (S - SBase) % TCount == 0 &&
C - TBase < TCount) {
/* Arithmetically compose an LV Hangul character and a T jamo
* into a Hangul LVT character */
return S + C - TBase;
}
const struct comp *start = comps, *end = start + lenof(comps);
while (end > start) {
const struct comp *curr = start + (end-start) / 2;
if (S < curr->dec0)
end = curr;
else if (S > curr->dec0)
start = curr + 1;
else if (C < curr->dec1)
end = curr;
else if (C > curr->dec1)
start = curr + 1;
else
return curr->composed;
}
return 0;
};
/*
* Recursively decompose a sequence of Unicode characters. The output
* is written to 'out', as a sequence of native-byte-order uchar.
*/
static void recursively_decompose(const uchar *str, size_t len, ucharbuf *out)
{
uchar decomposed[3];
while (len-- > 0) {
uchar c = *str++;
unsigned n = decompose_char(c, decomposed);
if (n == 0) {
/* This character is indecomposable */
ucharbuf_append(out, c);
} else {
/* This character has been decomposed into up to 3
* characters, so we must now recursively decompose those */
recursively_decompose(decomposed, n, out);
}
}
}
/*
* Reorder combining marks according to the Canonical Ordering
* Algorithm (definition D109 in Unicode 15.0.0 section 3.11).
*
* The algorithm is phrased mechanistically, but the essence is: among
* any contiguous sequence of combining marks (that is, characters
* with cclass > 0), sort them by their cclass - but _stably_, i.e.
* breaking ties in cclass by preserving the original order of the
* characters in question.
*/
static void canonical_ordering(uchar *str, size_t len)
{
for (size_t i = 1; i < len; i++) {
cclass_t cclass = combining_class(str[i]);
if (cclass == 0)
continue;
size_t j = i;
while (j > 0 && combining_class(str[j-1]) > cclass) {
uchar tmp = str[j-1];
str[j-1] = str[j];
str[j] = tmp;
j--;
}
}
}
/*
* Canonically recompose characters according to the Canonical
* Composition Algorithm (definition D117 in Unicode 15.0.0 section
* 3.11).
*/
static size_t canonical_composition(uchar *str, size_t len)
{
const uchar *in = str;
uchar *out = str;
uchar *last_starter = NULL;
cclass_t highest_cclass_between = -1;
while (len > 0) {
len--;
uchar c = *in++;
cclass_t cclass = combining_class(c);
if (last_starter && highest_cclass_between < cclass) {
uchar composed = compose_chars(*last_starter, c);
if (composed) {
*last_starter = composed;
continue;
}
}
if (cclass == 0) {
last_starter = out;
highest_cclass_between = -1;
} else if (cclass > highest_cclass_between) {
highest_cclass_between = cclass;
}
*out++ = c;
}
return out - str;
}
/*
* Render a string into NFD.
*/
static ucharbuf *nfd(ucharbuf *input)
{
ucharbuf *output = ucharbuf_new();
/*
* Definition D118 in Unicode 15.0.0 section 3.11, referring to
* D68 in section 3.7: recursively decompose characters, then
* reorder combining marks.
*/
recursively_decompose(input->buf, input->len, output);
canonical_ordering(output->buf, output->len);
return output;
}
/*
* Render a string into NFC.
*/
static ucharbuf *nfc(ucharbuf *input)
{
/*
* Definition D120 in Unicode 15.0.0 section 3.11: render the
* string into NFD, then apply the canonical composition algorithm.
*/
ucharbuf *output = nfd(input);
output->len = canonical_composition(output->buf, output->len);
return output;
}
/*
* Convert a UTF-8 string into NFC, returning it as UTF-8 again.
*/
strbuf *utf8_to_nfc(ptrlen input)
{
BinarySource src[1];
BinarySource_BARE_INIT_PL(src, input);
ucharbuf *inbuf = ucharbuf_new();
while (get_avail(src))
ucharbuf_append(inbuf, decode_utf8(src));
ucharbuf *outbuf = nfc(inbuf);
strbuf *output = strbuf_new_nm();
for (size_t i = 0; i < outbuf->len; i++)
put_utf8_char(output, outbuf->buf[i]);
ucharbuf_free(inbuf);
ucharbuf_free(outbuf);
return output;
}
#ifdef TEST
void out_of_memory(void)
{
fprintf(stderr, "out of memory!\n");
exit(2);
}
static int pass, fail;
static void subtest(const char *filename, int lineno, const char *subdesc,
char nftype, ucharbuf *input, ucharbuf *expected)
{
/*
* Convert input into either NFC or NFD, and check it's equal to
* expected
*/
ucharbuf *nf;
switch (nftype) {
case 'C':
nf = nfc(input);
break;
case 'D':
nf = nfd(input);
break;
default:
unreachable("bad nftype");
}
if (nf->len == expected->len && !memcmp(nf->buf, expected->buf, nf->len)) {
pass++;
} else {
printf("%s:%d: failed %s: NF%c([", filename, lineno, subdesc, nftype);
for (size_t pos = 0; pos < input->len; pos += sizeof(uchar))
printf("%s%04X", pos ? " " : "", (unsigned)input->buf[pos]);
printf("]) -> [");
for (size_t pos = 0; pos < nf->len; pos += sizeof(uchar))
printf("%s%04X", pos ? " " : "", (unsigned)nf->buf[pos]);
printf("] != [");
for (size_t pos = 0; pos < expected->len; pos += sizeof(uchar))
printf("%s%04X", pos ? " " : "", (unsigned)expected->buf[pos]);
printf("]\n");
fail++;
}
ucharbuf_free(nf);
}
static void run_tests(const char *filename, FILE *fp)
{
for (int lineno = 1;; lineno++) {
char *line = chomp(fgetline(fp));
if (!line)
break;
/* Strip section dividers which begin with @ */
if (*line == '@') {
sfree(line);
continue;
}
/* Strip comments, if any */
ptrlen pl = ptrlen_from_asciz(line);
{
const char *p = memchr(pl.ptr, '#', pl.len);
if (p)
pl.len = p - (const char *)pl.ptr;
}
/* Strip trailing space */
while (pl.len > 0 &&
(((char *)pl.ptr)[pl.len-1] == ' ' ||
((char *)pl.ptr)[pl.len-1] == '\t'))
pl.len--;
/* Skip empty lines */
if (!pl.len) {
sfree(line);
continue;
}
/* Break up at semicolons, expecting five fields, each of
* which we decode into hex code points */
ucharbuf *fields[5];
for (size_t i = 0; i < lenof(fields); i++) {
ptrlen field = ptrlen_get_word(&pl, ";");
fields[i] = ucharbuf_new();
ptrlen chr;
while ((chr = ptrlen_get_word(&field, " ")).len) {
char *chrstr = mkstr(chr);
uchar c = strtoul(chrstr, NULL, 16);
sfree(chrstr);
ucharbuf_append(fields[i], c);
}
}
subtest(filename, lineno, "NFC(c1) = c2", 'C', fields[0], fields[1]);
subtest(filename, lineno, "NFC(c2) = c2", 'C', fields[1], fields[1]);
subtest(filename, lineno, "NFC(c3) = c2", 'C', fields[2], fields[1]);
subtest(filename, lineno, "NFC(c4) = c4", 'C', fields[3], fields[3]);
subtest(filename, lineno, "NFC(c5) = c4", 'C', fields[4], fields[3]);
subtest(filename, lineno, "NFD(c1) = c3", 'D', fields[0], fields[2]);
subtest(filename, lineno, "NFD(c2) = c3", 'D', fields[1], fields[2]);
subtest(filename, lineno, "NFD(c3) = c3", 'D', fields[2], fields[2]);
subtest(filename, lineno, "NFD(c4) = c5", 'D', fields[3], fields[4]);
subtest(filename, lineno, "NFD(c5) = c5", 'D', fields[4], fields[4]);
for (size_t i = 0; i < lenof(fields); i++)
ucharbuf_free(fields[i]);
sfree(line);
}
}
int main(int argc, char **argv)
{
if (argc != 2) {
fprintf(stderr, "test_unicode_norm: give an input file "
"of tests or '-'\n");
return 1;
}
const char *filename = argv[1];
if (!strcmp(filename, "-")) {
run_tests("<standard input>", stdin);
} else {
FILE *fp = fopen(filename, "r");
if (!fp) {
fprintf(stderr, "test_unicode_norm: unable to open '%s'\n",
filename);
return 1;
}
run_tests(filename, fp);
fclose(fp);
}
printf("pass %d fail %d total %d\n", pass, fail, pass + fail);
return fail != 0;
}
#endif

View file

@ -124,509 +124,13 @@ static bool bisearch(unsigned int ucs, const struct interval *table, int max) {
int mk_wcwidth(unsigned int ucs)
{
/* sorted list of non-overlapping intervals of non-spacing characters */
/* generated by the following Perl
* from the Unicode 14.0.0 data files available at:
* https://www.unicode.org/Public/14.0.0/ucd/
open DATA, "<", "UnicodeData.txt" || die "$!";
while (<DATA>) {
@fields = split /;/;
$chr = hex $fields[0];
$cat = $fields[2];
$include = ($cat eq "Me" || $cat eq "Mn" || $cat eq "Cf");
$include = 0 if ($chr == 0x00AD);
$include = 1 if (0x1160 <= $chr && $chr <= 0x11FF);
$include = 1 if ($chr == 0x200B);
$chrs{$chr} = $include;
}
close DATA;
for ($chr = 0; $chr < 0x110000; $chr++) {
if ($chrs{$chr}) {
$start = $chr;
$chr++ while $chrs{$chr};
printf " { 0x%04X, 0x%04X },\n", $start, $chr-1;
}
}
*/
static const struct interval combining[] = {
{ 0x0300, 0x036F },
{ 0x0483, 0x0489 },
{ 0x0591, 0x05BD },
{ 0x05BF, 0x05BF },
{ 0x05C1, 0x05C2 },
{ 0x05C4, 0x05C5 },
{ 0x05C7, 0x05C7 },
{ 0x0600, 0x0605 },
{ 0x0610, 0x061A },
{ 0x061C, 0x061C },
{ 0x064B, 0x065F },
{ 0x0670, 0x0670 },
{ 0x06D6, 0x06DD },
{ 0x06DF, 0x06E4 },
{ 0x06E7, 0x06E8 },
{ 0x06EA, 0x06ED },
{ 0x070F, 0x070F },
{ 0x0711, 0x0711 },
{ 0x0730, 0x074A },
{ 0x07A6, 0x07B0 },
{ 0x07EB, 0x07F3 },
{ 0x07FD, 0x07FD },
{ 0x0816, 0x0819 },
{ 0x081B, 0x0823 },
{ 0x0825, 0x0827 },
{ 0x0829, 0x082D },
{ 0x0859, 0x085B },
{ 0x0890, 0x0891 },
{ 0x0898, 0x089F },
{ 0x08CA, 0x0902 },
{ 0x093A, 0x093A },
{ 0x093C, 0x093C },
{ 0x0941, 0x0948 },
{ 0x094D, 0x094D },
{ 0x0951, 0x0957 },
{ 0x0962, 0x0963 },
{ 0x0981, 0x0981 },
{ 0x09BC, 0x09BC },
{ 0x09C1, 0x09C4 },
{ 0x09CD, 0x09CD },
{ 0x09E2, 0x09E3 },
{ 0x09FE, 0x09FE },
{ 0x0A01, 0x0A02 },
{ 0x0A3C, 0x0A3C },
{ 0x0A41, 0x0A42 },
{ 0x0A47, 0x0A48 },
{ 0x0A4B, 0x0A4D },
{ 0x0A51, 0x0A51 },
{ 0x0A70, 0x0A71 },
{ 0x0A75, 0x0A75 },
{ 0x0A81, 0x0A82 },
{ 0x0ABC, 0x0ABC },
{ 0x0AC1, 0x0AC5 },
{ 0x0AC7, 0x0AC8 },
{ 0x0ACD, 0x0ACD },
{ 0x0AE2, 0x0AE3 },
{ 0x0AFA, 0x0AFF },
{ 0x0B01, 0x0B01 },
{ 0x0B3C, 0x0B3C },
{ 0x0B3F, 0x0B3F },
{ 0x0B41, 0x0B44 },
{ 0x0B4D, 0x0B4D },
{ 0x0B55, 0x0B56 },
{ 0x0B62, 0x0B63 },
{ 0x0B82, 0x0B82 },
{ 0x0BC0, 0x0BC0 },
{ 0x0BCD, 0x0BCD },
{ 0x0C00, 0x0C00 },
{ 0x0C04, 0x0C04 },
{ 0x0C3C, 0x0C3C },
{ 0x0C3E, 0x0C40 },
{ 0x0C46, 0x0C48 },
{ 0x0C4A, 0x0C4D },
{ 0x0C55, 0x0C56 },
{ 0x0C62, 0x0C63 },
{ 0x0C81, 0x0C81 },
{ 0x0CBC, 0x0CBC },
{ 0x0CBF, 0x0CBF },
{ 0x0CC6, 0x0CC6 },
{ 0x0CCC, 0x0CCD },
{ 0x0CE2, 0x0CE3 },
{ 0x0D00, 0x0D01 },
{ 0x0D3B, 0x0D3C },
{ 0x0D41, 0x0D44 },
{ 0x0D4D, 0x0D4D },
{ 0x0D62, 0x0D63 },
{ 0x0D81, 0x0D81 },
{ 0x0DCA, 0x0DCA },
{ 0x0DD2, 0x0DD4 },
{ 0x0DD6, 0x0DD6 },
{ 0x0E31, 0x0E31 },
{ 0x0E34, 0x0E3A },
{ 0x0E47, 0x0E4E },
{ 0x0EB1, 0x0EB1 },
{ 0x0EB4, 0x0EBC },
{ 0x0EC8, 0x0ECD },
{ 0x0F18, 0x0F19 },
{ 0x0F35, 0x0F35 },
{ 0x0F37, 0x0F37 },
{ 0x0F39, 0x0F39 },
{ 0x0F71, 0x0F7E },
{ 0x0F80, 0x0F84 },
{ 0x0F86, 0x0F87 },
{ 0x0F8D, 0x0F97 },
{ 0x0F99, 0x0FBC },
{ 0x0FC6, 0x0FC6 },
{ 0x102D, 0x1030 },
{ 0x1032, 0x1037 },
{ 0x1039, 0x103A },
{ 0x103D, 0x103E },
{ 0x1058, 0x1059 },
{ 0x105E, 0x1060 },
{ 0x1071, 0x1074 },
{ 0x1082, 0x1082 },
{ 0x1085, 0x1086 },
{ 0x108D, 0x108D },
{ 0x109D, 0x109D },
{ 0x1160, 0x11FF },
{ 0x135D, 0x135F },
{ 0x1712, 0x1714 },
{ 0x1732, 0x1733 },
{ 0x1752, 0x1753 },
{ 0x1772, 0x1773 },
{ 0x17B4, 0x17B5 },
{ 0x17B7, 0x17BD },
{ 0x17C6, 0x17C6 },
{ 0x17C9, 0x17D3 },
{ 0x17DD, 0x17DD },
{ 0x180B, 0x180F },
{ 0x1885, 0x1886 },
{ 0x18A9, 0x18A9 },
{ 0x1920, 0x1922 },
{ 0x1927, 0x1928 },
{ 0x1932, 0x1932 },
{ 0x1939, 0x193B },
{ 0x1A17, 0x1A18 },
{ 0x1A1B, 0x1A1B },
{ 0x1A56, 0x1A56 },
{ 0x1A58, 0x1A5E },
{ 0x1A60, 0x1A60 },
{ 0x1A62, 0x1A62 },
{ 0x1A65, 0x1A6C },
{ 0x1A73, 0x1A7C },
{ 0x1A7F, 0x1A7F },
{ 0x1AB0, 0x1ACE },
{ 0x1B00, 0x1B03 },
{ 0x1B34, 0x1B34 },
{ 0x1B36, 0x1B3A },
{ 0x1B3C, 0x1B3C },
{ 0x1B42, 0x1B42 },
{ 0x1B6B, 0x1B73 },
{ 0x1B80, 0x1B81 },
{ 0x1BA2, 0x1BA5 },
{ 0x1BA8, 0x1BA9 },
{ 0x1BAB, 0x1BAD },
{ 0x1BE6, 0x1BE6 },
{ 0x1BE8, 0x1BE9 },
{ 0x1BED, 0x1BED },
{ 0x1BEF, 0x1BF1 },
{ 0x1C2C, 0x1C33 },
{ 0x1C36, 0x1C37 },
{ 0x1CD0, 0x1CD2 },
{ 0x1CD4, 0x1CE0 },
{ 0x1CE2, 0x1CE8 },
{ 0x1CED, 0x1CED },
{ 0x1CF4, 0x1CF4 },
{ 0x1CF8, 0x1CF9 },
{ 0x1DC0, 0x1DFF },
{ 0x200B, 0x200F },
{ 0x202A, 0x202E },
{ 0x2060, 0x2064 },
{ 0x2066, 0x206F },
{ 0x20D0, 0x20F0 },
{ 0x2CEF, 0x2CF1 },
{ 0x2D7F, 0x2D7F },
{ 0x2DE0, 0x2DFF },
{ 0x302A, 0x302D },
{ 0x3099, 0x309A },
{ 0xA66F, 0xA672 },
{ 0xA674, 0xA67D },
{ 0xA69E, 0xA69F },
{ 0xA6F0, 0xA6F1 },
{ 0xA802, 0xA802 },
{ 0xA806, 0xA806 },
{ 0xA80B, 0xA80B },
{ 0xA825, 0xA826 },
{ 0xA82C, 0xA82C },
{ 0xA8C4, 0xA8C5 },
{ 0xA8E0, 0xA8F1 },
{ 0xA8FF, 0xA8FF },
{ 0xA926, 0xA92D },
{ 0xA947, 0xA951 },
{ 0xA980, 0xA982 },
{ 0xA9B3, 0xA9B3 },
{ 0xA9B6, 0xA9B9 },
{ 0xA9BC, 0xA9BD },
{ 0xA9E5, 0xA9E5 },
{ 0xAA29, 0xAA2E },
{ 0xAA31, 0xAA32 },
{ 0xAA35, 0xAA36 },
{ 0xAA43, 0xAA43 },
{ 0xAA4C, 0xAA4C },
{ 0xAA7C, 0xAA7C },
{ 0xAAB0, 0xAAB0 },
{ 0xAAB2, 0xAAB4 },
{ 0xAAB7, 0xAAB8 },
{ 0xAABE, 0xAABF },
{ 0xAAC1, 0xAAC1 },
{ 0xAAEC, 0xAAED },
{ 0xAAF6, 0xAAF6 },
{ 0xABE5, 0xABE5 },
{ 0xABE8, 0xABE8 },
{ 0xABED, 0xABED },
{ 0xFB1E, 0xFB1E },
{ 0xFE00, 0xFE0F },
{ 0xFE20, 0xFE2F },
{ 0xFEFF, 0xFEFF },
{ 0xFFF9, 0xFFFB },
{ 0x101FD, 0x101FD },
{ 0x102E0, 0x102E0 },
{ 0x10376, 0x1037A },
{ 0x10A01, 0x10A03 },
{ 0x10A05, 0x10A06 },
{ 0x10A0C, 0x10A0F },
{ 0x10A38, 0x10A3A },
{ 0x10A3F, 0x10A3F },
{ 0x10AE5, 0x10AE6 },
{ 0x10D24, 0x10D27 },
{ 0x10EAB, 0x10EAC },
{ 0x10F46, 0x10F50 },
{ 0x10F82, 0x10F85 },
{ 0x11001, 0x11001 },
{ 0x11038, 0x11046 },
{ 0x11070, 0x11070 },
{ 0x11073, 0x11074 },
{ 0x1107F, 0x11081 },
{ 0x110B3, 0x110B6 },
{ 0x110B9, 0x110BA },
{ 0x110BD, 0x110BD },
{ 0x110C2, 0x110C2 },
{ 0x110CD, 0x110CD },
{ 0x11100, 0x11102 },
{ 0x11127, 0x1112B },
{ 0x1112D, 0x11134 },
{ 0x11173, 0x11173 },
{ 0x11180, 0x11181 },
{ 0x111B6, 0x111BE },
{ 0x111C9, 0x111CC },
{ 0x111CF, 0x111CF },
{ 0x1122F, 0x11231 },
{ 0x11234, 0x11234 },
{ 0x11236, 0x11237 },
{ 0x1123E, 0x1123E },
{ 0x112DF, 0x112DF },
{ 0x112E3, 0x112EA },
{ 0x11300, 0x11301 },
{ 0x1133B, 0x1133C },
{ 0x11340, 0x11340 },
{ 0x11366, 0x1136C },
{ 0x11370, 0x11374 },
{ 0x11438, 0x1143F },
{ 0x11442, 0x11444 },
{ 0x11446, 0x11446 },
{ 0x1145E, 0x1145E },
{ 0x114B3, 0x114B8 },
{ 0x114BA, 0x114BA },
{ 0x114BF, 0x114C0 },
{ 0x114C2, 0x114C3 },
{ 0x115B2, 0x115B5 },
{ 0x115BC, 0x115BD },
{ 0x115BF, 0x115C0 },
{ 0x115DC, 0x115DD },
{ 0x11633, 0x1163A },
{ 0x1163D, 0x1163D },
{ 0x1163F, 0x11640 },
{ 0x116AB, 0x116AB },
{ 0x116AD, 0x116AD },
{ 0x116B0, 0x116B5 },
{ 0x116B7, 0x116B7 },
{ 0x1171D, 0x1171F },
{ 0x11722, 0x11725 },
{ 0x11727, 0x1172B },
{ 0x1182F, 0x11837 },
{ 0x11839, 0x1183A },
{ 0x1193B, 0x1193C },
{ 0x1193E, 0x1193E },
{ 0x11943, 0x11943 },
{ 0x119D4, 0x119D7 },
{ 0x119DA, 0x119DB },
{ 0x119E0, 0x119E0 },
{ 0x11A01, 0x11A0A },
{ 0x11A33, 0x11A38 },
{ 0x11A3B, 0x11A3E },
{ 0x11A47, 0x11A47 },
{ 0x11A51, 0x11A56 },
{ 0x11A59, 0x11A5B },
{ 0x11A8A, 0x11A96 },
{ 0x11A98, 0x11A99 },
{ 0x11C30, 0x11C36 },
{ 0x11C38, 0x11C3D },
{ 0x11C3F, 0x11C3F },
{ 0x11C92, 0x11CA7 },
{ 0x11CAA, 0x11CB0 },
{ 0x11CB2, 0x11CB3 },
{ 0x11CB5, 0x11CB6 },
{ 0x11D31, 0x11D36 },
{ 0x11D3A, 0x11D3A },
{ 0x11D3C, 0x11D3D },
{ 0x11D3F, 0x11D45 },
{ 0x11D47, 0x11D47 },
{ 0x11D90, 0x11D91 },
{ 0x11D95, 0x11D95 },
{ 0x11D97, 0x11D97 },
{ 0x11EF3, 0x11EF4 },
{ 0x13430, 0x13438 },
{ 0x16AF0, 0x16AF4 },
{ 0x16B30, 0x16B36 },
{ 0x16F4F, 0x16F4F },
{ 0x16F8F, 0x16F92 },
{ 0x16FE4, 0x16FE4 },
{ 0x1BC9D, 0x1BC9E },
{ 0x1BCA0, 0x1BCA3 },
{ 0x1CF00, 0x1CF2D },
{ 0x1CF30, 0x1CF46 },
{ 0x1D167, 0x1D169 },
{ 0x1D173, 0x1D182 },
{ 0x1D185, 0x1D18B },
{ 0x1D1AA, 0x1D1AD },
{ 0x1D242, 0x1D244 },
{ 0x1DA00, 0x1DA36 },
{ 0x1DA3B, 0x1DA6C },
{ 0x1DA75, 0x1DA75 },
{ 0x1DA84, 0x1DA84 },
{ 0x1DA9B, 0x1DA9F },
{ 0x1DAA1, 0x1DAAF },
{ 0x1E000, 0x1E006 },
{ 0x1E008, 0x1E018 },
{ 0x1E01B, 0x1E021 },
{ 0x1E023, 0x1E024 },
{ 0x1E026, 0x1E02A },
{ 0x1E130, 0x1E136 },
{ 0x1E2AE, 0x1E2AE },
{ 0x1E2EC, 0x1E2EF },
{ 0x1E8D0, 0x1E8D6 },
{ 0x1E944, 0x1E94A },
{ 0xE0001, 0xE0001 },
{ 0xE0020, 0xE007F },
{ 0xE0100, 0xE01EF },
#include "unicode/nonspacing_chars.h"
};
/* A sorted list of intervals of double-width characters generated by:
* https://raw.githubusercontent.com/GNOME/glib/37d4c2941bd0326b8b6e6bb22c81bd424fcc040b/glib/gen-unicode-tables.pl
* from the Unicode 14.0.0 data files available at:
* https://www.unicode.org/Public/14.0.0/ucd/
*/
/* A sorted list of intervals of double-width characters */
static const struct interval wide[] = {
{0x1100, 0x115F},
{0x231A, 0x231B},
{0x2329, 0x232A},
{0x23E9, 0x23EC},
{0x23F0, 0x23F0},
{0x23F3, 0x23F3},
{0x25FD, 0x25FE},
{0x2614, 0x2615},
{0x2648, 0x2653},
{0x267F, 0x267F},
{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, 0x2FFB},
{0x3000, 0x303E},
{0x3041, 0x3096},
{0x3099, 0x30FF},
{0x3105, 0x312F},
{0x3131, 0x318E},
{0x3190, 0x31E3},
{0x31F0, 0x321E},
{0x3220, 0x3247},
{0x3250, 0x4DBF},
{0x4E00, 0xA48C},
{0xA490, 0xA4C6},
{0xA960, 0xA97C},
{0xAC00, 0xD7A3},
{0xF900, 0xFAFF},
{0xFE10, 0xFE19},
{0xFE30, 0xFE52},
{0xFE54, 0xFE66},
{0xFE68, 0xFE6B},
{0xFF01, 0xFF60},
{0xFFE0, 0xFFE6},
{0x16FE0, 0x16FE4},
{0x16FF0, 0x16FF1},
{0x17000, 0x187F7},
{0x18800, 0x18CD5},
{0x18D00, 0x18D08},
{0x1AFF0, 0x1AFF3},
{0x1AFF5, 0x1AFFB},
{0x1AFFD, 0x1AFFE},
{0x1B000, 0x1B122},
{0x1B150, 0x1B152},
{0x1B164, 0x1B167},
{0x1B170, 0x1B2FB},
{0x1F004, 0x1F004},
{0x1F0CF, 0x1F0CF},
{0x1F18E, 0x1F18E},
{0x1F191, 0x1F19A},
{0x1F200, 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, 0x1F6D7},
{0x1F6DD, 0x1F6DF},
{0x1F6EB, 0x1F6EC},
{0x1F6F4, 0x1F6FC},
{0x1F7E0, 0x1F7EB},
{0x1F7F0, 0x1F7F0},
{0x1F90C, 0x1F93A},
{0x1F93C, 0x1F945},
{0x1F947, 0x1F9FF},
{0x1FA70, 0x1FA74},
{0x1FA78, 0x1FA7C},
{0x1FA80, 0x1FA86},
{0x1FA90, 0x1FAAC},
{0x1FAB0, 0x1FABA},
{0x1FAC0, 0x1FAC5},
{0x1FAD0, 0x1FAD9},
{0x1FAE0, 0x1FAE7},
{0x1FAF0, 0x1FAF6},
{0x20000, 0x2FFFD},
{0x30000, 0x3FFFD},
#include "unicode/wide_chars.h"
};
/* test for 8-bit control characters */
@ -677,191 +181,9 @@ int mk_wcswidth(const unsigned int *pwcs, size_t n)
*/
int mk_wcwidth_cjk(unsigned int ucs)
{
/* A sorted list of intervals of ambiguous width characters generated by:
* https://raw.githubusercontent.com/GNOME/glib/37d4c2941bd0326b8b6e6bb22c81bd424fcc040b/glib/gen-unicode-tables.pl
* from the Unicode 9.0.0 data files available at:
* http://www.unicode.org/Public/9.0.0/ucd/
*/
/* A sorted list of intervals of ambiguous width characters */
static const struct interval ambiguous[] = {
{0x00A1, 0x00A1},
{0x00A4, 0x00A4},
{0x00A7, 0x00A8},
{0x00AA, 0x00AA},
{0x00AD, 0x00AE},
{0x00B0, 0x00B4},
{0x00B6, 0x00BA},
{0x00BC, 0x00BF},
{0x00C6, 0x00C6},
{0x00D0, 0x00D0},
{0x00D7, 0x00D8},
{0x00DE, 0x00E1},
{0x00E6, 0x00E6},
{0x00E8, 0x00EA},
{0x00EC, 0x00ED},
{0x00F0, 0x00F0},
{0x00F2, 0x00F3},
{0x00F7, 0x00FA},
{0x00FC, 0x00FC},
{0x00FE, 0x00FE},
{0x0101, 0x0101},
{0x0111, 0x0111},
{0x0113, 0x0113},
{0x011B, 0x011B},
{0x0126, 0x0127},
{0x012B, 0x012B},
{0x0131, 0x0133},
{0x0138, 0x0138},
{0x013F, 0x0142},
{0x0144, 0x0144},
{0x0148, 0x014B},
{0x014D, 0x014D},
{0x0152, 0x0153},
{0x0166, 0x0167},
{0x016B, 0x016B},
{0x01CE, 0x01CE},
{0x01D0, 0x01D0},
{0x01D2, 0x01D2},
{0x01D4, 0x01D4},
{0x01D6, 0x01D6},
{0x01D8, 0x01D8},
{0x01DA, 0x01DA},
{0x01DC, 0x01DC},
{0x0251, 0x0251},
{0x0261, 0x0261},
{0x02C4, 0x02C4},
{0x02C7, 0x02C7},
{0x02C9, 0x02CB},
{0x02CD, 0x02CD},
{0x02D0, 0x02D0},
{0x02D8, 0x02DB},
{0x02DD, 0x02DD},
{0x02DF, 0x02DF},
{0x0300, 0x036F},
{0x0391, 0x03A1},
{0x03A3, 0x03A9},
{0x03B1, 0x03C1},
{0x03C3, 0x03C9},
{0x0401, 0x0401},
{0x0410, 0x044F},
{0x0451, 0x0451},
{0x2010, 0x2010},
{0x2013, 0x2016},
{0x2018, 0x2019},
{0x201C, 0x201D},
{0x2020, 0x2022},
{0x2024, 0x2027},
{0x2030, 0x2030},
{0x2032, 0x2033},
{0x2035, 0x2035},
{0x203B, 0x203B},
{0x203E, 0x203E},
{0x2074, 0x2074},
{0x207F, 0x207F},
{0x2081, 0x2084},
{0x20AC, 0x20AC},
{0x2103, 0x2103},
{0x2105, 0x2105},
{0x2109, 0x2109},
{0x2113, 0x2113},
{0x2116, 0x2116},
{0x2121, 0x2122},
{0x2126, 0x2126},
{0x212B, 0x212B},
{0x2153, 0x2154},
{0x215B, 0x215E},
{0x2160, 0x216B},
{0x2170, 0x2179},
{0x2189, 0x2189},
{0x2190, 0x2199},
{0x21B8, 0x21B9},
{0x21D2, 0x21D2},
{0x21D4, 0x21D4},
{0x21E7, 0x21E7},
{0x2200, 0x2200},
{0x2202, 0x2203},
{0x2207, 0x2208},
{0x220B, 0x220B},
{0x220F, 0x220F},
{0x2211, 0x2211},
{0x2215, 0x2215},
{0x221A, 0x221A},
{0x221D, 0x2220},
{0x2223, 0x2223},
{0x2225, 0x2225},
{0x2227, 0x222C},
{0x222E, 0x222E},
{0x2234, 0x2237},
{0x223C, 0x223D},
{0x2248, 0x2248},
{0x224C, 0x224C},
{0x2252, 0x2252},
{0x2260, 0x2261},
{0x2264, 0x2267},
{0x226A, 0x226B},
{0x226E, 0x226F},
{0x2282, 0x2283},
{0x2286, 0x2287},
{0x2295, 0x2295},
{0x2299, 0x2299},
{0x22A5, 0x22A5},
{0x22BF, 0x22BF},
{0x2312, 0x2312},
{0x2460, 0x24E9},
{0x24EB, 0x254B},
{0x2550, 0x2573},
{0x2580, 0x258F},
{0x2592, 0x2595},
{0x25A0, 0x25A1},
{0x25A3, 0x25A9},
{0x25B2, 0x25B3},
{0x25B6, 0x25B7},
{0x25BC, 0x25BD},
{0x25C0, 0x25C1},
{0x25C6, 0x25C8},
{0x25CB, 0x25CB},
{0x25CE, 0x25D1},
{0x25E2, 0x25E5},
{0x25EF, 0x25EF},
{0x2605, 0x2606},
{0x2609, 0x2609},
{0x260E, 0x260F},
{0x261C, 0x261C},
{0x261E, 0x261E},
{0x2640, 0x2640},
{0x2642, 0x2642},
{0x2660, 0x2661},
{0x2663, 0x2665},
{0x2667, 0x266A},
{0x266C, 0x266D},
{0x266F, 0x266F},
{0x269E, 0x269F},
{0x26BF, 0x26BF},
{0x26C6, 0x26CD},
{0x26CF, 0x26D3},
{0x26D5, 0x26E1},
{0x26E3, 0x26E3},
{0x26E8, 0x26E9},
{0x26EB, 0x26F1},
{0x26F4, 0x26F4},
{0x26F6, 0x26F9},
{0x26FB, 0x26FC},
{0x26FE, 0x26FF},
{0x273D, 0x273D},
{0x2776, 0x277F},
{0x2B56, 0x2B59},
{0x3248, 0x324F},
{0xE000, 0xF8FF},
{0xFE00, 0xFE0F},
{0xFFFD, 0xFFFD},
{0x1F100, 0x1F10A},
{0x1F110, 0x1F12D},
{0x1F130, 0x1F169},
{0x1F170, 0x1F18D},
{0x1F18F, 0x1F190},
{0x1F19B, 0x1F1AC},
{0xE0100, 0xE01EF},
{0xF0000, 0xFFFFD},
{0x100000, 0x10FFFD},
#include "unicode/ambiguous_wide_chars.h"
};
/* binary search in table of non-spacing characters */

View file

@ -1290,8 +1290,8 @@ int wc_to_mb(int codepage, int flags, const wchar_t *wcstr, int wclen,
* the codepage is UTF-8, we can do the translation ourselves.
*/
if (codepage == CP_UTF8 && mblen > 0 && wclen > 0) {
size_t remaining = mblen;
char *p = mbstr;
buffer_sink bs[1];
buffer_sink_init(bs, mbstr, mblen);
while (wclen > 0) {
unsigned long wc = (wclen--, *wcstr++);
@ -1300,18 +1300,13 @@ int wc_to_mb(int codepage, int flags, const wchar_t *wcstr, int wclen,
wclen--, wcstr++;
}
char utfbuf[6];
size_t utflen = encode_utf8(utfbuf, wc);
if (utflen <= remaining) {
memcpy(p, utfbuf, utflen);
p += utflen;
remaining -= utflen;
} else {
return p - mbstr;
}
const char *prev_ptr = bs->out;
put_utf8_char(bs, wc);
if (bs->overflowed)
return prev_ptr - mbstr;
}
return p - mbstr;
return bs->out - mbstr;
}
#endif
@ -1362,18 +1357,15 @@ int mb_to_wc(int codepage, int flags, const char *mbstr, int mblen,
* codepage is UTF-8, we can do the translation ourselves.
*/
if (codepage == CP_UTF8 && mblen > 0 && wclen > 0) {
BinarySource src[1];
BinarySource_BARE_INIT(src, mbstr, mblen);
size_t remaining = wclen;
wchar_t *p = wcstr;
while (mblen > 0) {
char utfbuf[7];
int thissize = mblen < 6 ? mblen : 6;
memcpy(utfbuf, mbstr, thissize);
utfbuf[thissize] = '\0';
const char *utfptr = utfbuf;
while (get_avail(src)) {
wchar_t wcbuf[2];
size_t nwc = decode_utf8_to_wchar(&utfptr, wcbuf);
size_t nwc = decode_utf8_to_wchar(src, wcbuf);
for (size_t i = 0; i < nwc; i++) {
if (remaining > 0) {
@ -1383,9 +1375,6 @@ int mb_to_wc(int codepage, int flags, const char *mbstr, int mblen,
return p - wcstr;
}
}
mbstr += (utfptr - utfbuf);
mblen -= (utfptr - utfbuf);
}
return p - wcstr;

View file

@ -513,6 +513,8 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
/*
* Process the command line.
* (If the command line doesn't provide enough info to start a
* session, this will detour via the config box.)
*/
gui_term_process_cmdline(wgs->conf, cmdline);
@ -1656,20 +1658,27 @@ static void wintw_request_resize(TermWin *tw, int w, int h)
WinGuiSeat *wgs = container_of(tw, WinGuiSeat, termwin);
const struct BackendVtable *vt;
int width, height;
int resize_action = conf_get_int(wgs->conf, CONF_resize_action);
bool deny_resize = false;
/* If the window is maximized suppress resizing attempts */
if (IsZoomed(wgs->term_hwnd)) {
if (conf_get_int(wgs->conf, CONF_resize_action) == RESIZE_TERM) {
/* Suppress server-originated resizing attempts if local resizing
* is disabled entirely, or if it's supposed to change
* rows/columns but the window is maximised. */
if (resize_action == RESIZE_DISABLED
|| (resize_action == RESIZE_TERM && IsZoomed(wgs->term_hwnd))) {
deny_resize = true;
}
vt = backend_vt_from_proto(be_default_protocol);
if (vt && vt->flags & BACKEND_RESIZE_FORBIDDEN)
deny_resize = true;
if (h == wgs->term->rows && w == wgs->term->cols) deny_resize = true;
/* We still need to acknowledge a suppressed resize attempt. */
if (deny_resize) {
term_resize_request_completed(wgs->term);
return;
}
}
if (conf_get_int(wgs->conf, CONF_resize_action) == RESIZE_DISABLED) return;
vt = backend_vt_from_proto(be_default_protocol);
if (vt && vt->flags & BACKEND_RESIZE_FORBIDDEN)
return;
if (h == wgs->term->rows && w == wgs->term->cols) return;
/* Sanity checks ... */
{
@ -1690,8 +1699,7 @@ static void wintw_request_resize(TermWin *tw, int w, int h)
}
}
if (conf_get_int(wgs->conf, CONF_resize_action) != RESIZE_FONT &&
!IsZoomed(wgs->term_hwnd)) {
if (resize_action != RESIZE_FONT && !IsZoomed(wgs->term_hwnd)) {
width = extra_width + font_width * w;
height = extra_height + font_height * h;
@ -2721,6 +2729,11 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
TO_CHR_X(X_POS(lParam)),
TO_CHR_Y(Y_POS(lParam)), wParam & MK_SHIFT,
wParam & MK_CONTROL, is_alt_pressed());
} else {
term_mouse(wgs->term, MBT_NOTHING, MBT_NOTHING, MA_MOVE,
TO_CHR_X(X_POS(lParam)),
TO_CHR_Y(Y_POS(lParam)), false,
false, false);
}
return 0;
}