From d97ea9b0bc212589dc5f8cceb7dc398aa65ce337 Mon Sep 17 00:00:00 2001 From: gryf Date: Tue, 31 Mar 2020 17:15:23 +0200 Subject: [PATCH] Initial import --- .gitignore | 1 + LICENSE | 674 + README.rst | 26 + ebook_converter/__init__.py | 681 + ebook_converter/constants.py | 343 + ebook_converter/css_selectors/__init__.py | 12 + ebook_converter/css_selectors/errors.py | 18 + ebook_converter/css_selectors/ordered_set.py | 133 + ebook_converter/css_selectors/parser.py | 791 + ebook_converter/css_selectors/select.py | 694 + ebook_converter/css_selectors/tests.py | 843 + ebook_converter/customize/__init__.py | 759 + ebook_converter/customize/builtins.py | 1973 ++ ebook_converter/customize/conversion.py | 376 + ebook_converter/customize/profiles.py | 873 + ebook_converter/customize/ui.py | 835 + ebook_converter/customize/zipplugin.py | 320 + ebook_converter/devices/__init__.py | 216 + ebook_converter/devices/interface.py | 787 + ebook_converter/ebooks/BeautifulSoup.py | 41 + ebook_converter/ebooks/__init__.py | 248 + ebook_converter/ebooks/chardet.py | 189 + .../ebooks/compression/__init__.py | 6 + ebook_converter/ebooks/compression/palmdoc.c | 238 + ebook_converter/ebooks/compression/palmdoc.py | 96 + ebook_converter/ebooks/conversion/__init__.py | 30 + ebook_converter/ebooks/conversion/cli.py | 428 + .../ebooks/conversion/plugins/__init__.py | 10 + .../ebooks/conversion/plugins/azw4_input.py | 29 + .../ebooks/conversion/plugins/chm_input.py | 202 + .../ebooks/conversion/plugins/comic_input.py | 310 + .../ebooks/conversion/plugins/djvu_input.py | 67 + .../ebooks/conversion/plugins/docx_input.py | 34 + .../ebooks/conversion/plugins/docx_output.py | 93 + .../ebooks/conversion/plugins/epub_input.py | 438 + .../ebooks/conversion/plugins/epub_output.py | 548 + .../ebooks/conversion/plugins/fb2_input.py | 179 + .../ebooks/conversion/plugins/fb2_output.py | 203 + .../ebooks/conversion/plugins/html_input.py | 316 + .../ebooks/conversion/plugins/html_output.py | 226 + .../ebooks/conversion/plugins/htmlz_input.py | 133 + .../ebooks/conversion/plugins/htmlz_output.py | 136 + .../ebooks/conversion/plugins/lit_input.py | 64 + .../ebooks/conversion/plugins/lit_output.py | 38 + .../ebooks/conversion/plugins/lrf_input.py | 82 + .../ebooks/conversion/plugins/lrf_output.py | 196 + .../ebooks/conversion/plugins/mobi_input.py | 66 + .../ebooks/conversion/plugins/mobi_output.py | 337 + .../ebooks/conversion/plugins/odt_input.py | 25 + .../ebooks/conversion/plugins/oeb_output.py | 122 + .../ebooks/conversion/plugins/pdb_input.py | 37 + .../ebooks/conversion/plugins/pdb_output.py | 64 + .../ebooks/conversion/plugins/pdf_input.py | 82 + .../ebooks/conversion/plugins/pdf_output.py | 256 + .../ebooks/conversion/plugins/pml_input.py | 165 + .../ebooks/conversion/plugins/pml_output.py | 77 + .../ebooks/conversion/plugins/rb_input.py | 28 + .../ebooks/conversion/plugins/rb_output.py | 45 + .../ebooks/conversion/plugins/recipe_input.py | 169 + .../ebooks/conversion/plugins/rtf_input.py | 323 + .../ebooks/conversion/plugins/rtf_output.py | 40 + .../ebooks/conversion/plugins/snb_input.py | 122 + .../ebooks/conversion/plugins/snb_output.py | 269 + .../ebooks/conversion/plugins/tcr_input.py | 39 + .../ebooks/conversion/plugins/tcr_output.py | 56 + .../ebooks/conversion/plugins/txt_input.py | 308 + .../ebooks/conversion/plugins/txt_output.py | 165 + ebook_converter/ebooks/conversion/plumber.py | 1330 ++ .../ebooks/conversion/preprocess.py | 646 + ebook_converter/ebooks/conversion/utils.py | 881 + ebook_converter/ebooks/docx/__init__.py | 11 + ebook_converter/ebooks/docx/block_styles.py | 478 + ebook_converter/ebooks/docx/char_styles.py | 302 + ebook_converter/ebooks/docx/cleanup.py | 235 + ebook_converter/ebooks/docx/container.py | 268 + ebook_converter/ebooks/docx/fields.py | 276 + ebook_converter/ebooks/docx/fonts.py | 197 + ebook_converter/ebooks/docx/footnotes.py | 65 + ebook_converter/ebooks/docx/images.py | 343 + ebook_converter/ebooks/docx/index.py | 273 + ebook_converter/ebooks/docx/names.py | 144 + ebook_converter/ebooks/docx/numbering.py | 388 + ebook_converter/ebooks/docx/settings.py | 21 + ebook_converter/ebooks/docx/styles.py | 504 + ebook_converter/ebooks/docx/tables.py | 700 + ebook_converter/ebooks/docx/theme.py | 29 + ebook_converter/ebooks/docx/to_html.py | 839 + ebook_converter/ebooks/docx/toc.py | 143 + ebook_converter/ebooks/html/__init__.py | 7 + ebook_converter/ebooks/html/input.py | 258 + ebook_converter/ebooks/html/to_zip.py | 122 + ebook_converter/ebooks/html_entities.py | 2152 ++ ebook_converter/ebooks/lrf/__init__.py | 115 + ebook_converter/ebooks/lrf/fonts.py | 33 + ebook_converter/ebooks/lrf/html/__init__.py | 10 + ebook_converter/ebooks/lrf/html/color_map.py | 115 + .../ebooks/lrf/html/convert_from.py | 1951 ++ ebook_converter/ebooks/lrf/html/table.py | 386 + ebook_converter/ebooks/lrf/pylrs/__init__.py | 7 + ebook_converter/ebooks/lrf/pylrs/elements.py | 78 + ebook_converter/ebooks/lrf/pylrs/pylrf.py | 773 + ebook_converter/ebooks/lrf/pylrs/pylrfopt.py | 44 + ebook_converter/ebooks/lrf/pylrs/pylrs.py | 2442 +++ ebook_converter/ebooks/metadata/__init__.py | 440 + ebook_converter/ebooks/metadata/archive.py | 203 + .../ebooks/metadata/book/__init__.py | 132 + ebook_converter/ebooks/metadata/book/base.py | 841 + .../ebooks/metadata/book/formatter.py | 46 + .../ebooks/metadata/book/json_codec.py | 218 + ebook_converter/ebooks/metadata/html.py | 412 + ebook_converter/ebooks/metadata/meta.py | 243 + ebook_converter/ebooks/metadata/odt.py | 302 + ebook_converter/ebooks/metadata/opf2.py | 1829 ++ ebook_converter/ebooks/metadata/opf3.py | 1118 ++ ebook_converter/ebooks/metadata/rtf.py | 251 + ebook_converter/ebooks/metadata/toc.py | 296 + ebook_converter/ebooks/metadata/utils.py | 104 + ebook_converter/ebooks/mobi/__init__.py | 15 + ebook_converter/ebooks/mobi/huffcdic.py | 108 + ebook_converter/ebooks/mobi/langcodes.py | 355 + .../ebooks/mobi/reader/__init__.py | 10 + .../ebooks/mobi/reader/containers.py | 49 + ebook_converter/ebooks/mobi/reader/headers.py | 355 + ebook_converter/ebooks/mobi/reader/index.py | 277 + ebook_converter/ebooks/mobi/reader/markup.py | 373 + ebook_converter/ebooks/mobi/reader/mobi6.py | 935 + ebook_converter/ebooks/mobi/reader/mobi8.py | 590 + ebook_converter/ebooks/mobi/reader/ncx.py | 100 + ebook_converter/ebooks/mobi/tweak.py | 109 + ebook_converter/ebooks/mobi/utils.py | 646 + .../ebooks/mobi/writer2/__init__.py | 14 + .../ebooks/mobi/writer2/resources.py | 158 + ebook_converter/ebooks/odt/__init__.py | 10 + ebook_converter/ebooks/odt/input.py | 305 + ebook_converter/ebooks/oeb/__init__.py | 4 + ebook_converter/ebooks/oeb/base.py | 2023 ++ ebook_converter/ebooks/oeb/normalize_css.py | 437 + ebook_converter/ebooks/oeb/parse_utils.py | 389 + ebook_converter/ebooks/oeb/polish/__init__.py | 10 + .../ebooks/oeb/polish/container.py | 1552 ++ ebook_converter/ebooks/oeb/polish/errors.py | 23 + ebook_converter/ebooks/oeb/polish/opf.py | 52 + ebook_converter/ebooks/oeb/polish/parsing.py | 99 + ebook_converter/ebooks/oeb/polish/pretty.py | 252 + ebook_converter/ebooks/oeb/polish/toc.py | 891 + ebook_converter/ebooks/oeb/polish/utils.py | 231 + ebook_converter/ebooks/oeb/reader.py | 720 + ebook_converter/ebooks/oeb/stylizer.py | 808 + .../ebooks/oeb/transforms/__init__.py | 7 + .../ebooks/oeb/transforms/data_url.py | 52 + .../ebooks/oeb/transforms/flatcss.py | 684 + .../ebooks/oeb/transforms/guide.py | 55 + .../ebooks/oeb/transforms/jacket.py | 395 + .../ebooks/oeb/transforms/metadata.py | 218 + .../ebooks/oeb/transforms/page_margin.py | 189 + .../ebooks/oeb/transforms/structure.py | 324 + .../ebooks/oeb/transforms/trimmanifest.py | 73 + ebook_converter/ebooks/oeb/writer.py | 78 + ebook_converter/ebooks/pdb/__init__.py | 106 + .../ebooks/pdb/ereader/__init__.py | 30 + ebook_converter/ebooks/pdb/ereader/reader.py | 37 + .../ebooks/pdb/ereader/reader132.py | 221 + .../ebooks/pdb/ereader/reader202.py | 169 + ebook_converter/ebooks/pdb/formatreader.py | 19 + ebook_converter/ebooks/pdb/haodoo/__init__.py | 10 + ebook_converter/ebooks/pdb/haodoo/reader.py | 157 + ebook_converter/ebooks/pdb/header.py | 91 + .../ebooks/pdb/palmdoc/__init__.py | 0 ebook_converter/ebooks/pdb/palmdoc/reader.py | 74 + ebook_converter/ebooks/pdb/pdf/__init__.py | 0 ebook_converter/ebooks/pdb/pdf/reader.py | 43 + .../ebooks/pdb/plucker/__init__.py | 0 ebook_converter/ebooks/pdb/plucker/reader.py | 737 + ebook_converter/ebooks/pdb/ztxt/__init__.py | 10 + ebook_converter/ebooks/pdb/ztxt/reader.py | 94 + ebook_converter/ebooks/rtf/__init__.py | 1 + ebook_converter/ebooks/rtf/input.py | 39 + ebook_converter/ebooks/rtf2xml/ParseRtf.py | 573 + ebook_converter/ebooks/rtf2xml/__init__.py | 12 + .../ebooks/rtf2xml/add_brackets.py | 232 + ebook_converter/ebooks/rtf2xml/body_styles.py | 84 + .../ebooks/rtf2xml/border_parse.py | 191 + ebook_converter/ebooks/rtf2xml/char_set.py | 16709 ++++++++++++++++ .../ebooks/rtf2xml/check_brackets.py | 62 + .../ebooks/rtf2xml/check_encoding.py | 42 + ebook_converter/ebooks/rtf2xml/colors.py | 258 + .../ebooks/rtf2xml/combine_borders.py | 93 + .../ebooks/rtf2xml/convert_to_tags.py | 284 + ebook_converter/ebooks/rtf2xml/copy.py | 63 + .../ebooks/rtf2xml/default_encoding.py | 188 + ebook_converter/ebooks/rtf2xml/delete_info.py | 212 + .../ebooks/rtf2xml/field_strings.py | 816 + .../ebooks/rtf2xml/fields_large.py | 378 + .../ebooks/rtf2xml/fields_small.py | 460 + ebook_converter/ebooks/rtf2xml/fonts.py | 226 + ebook_converter/ebooks/rtf2xml/footnote.py | 264 + .../ebooks/rtf2xml/get_char_map.py | 62 + .../ebooks/rtf2xml/group_borders.py | 306 + .../ebooks/rtf2xml/group_styles.py | 252 + ebook_converter/ebooks/rtf2xml/header.py | 261 + .../ebooks/rtf2xml/headings_to_sections.py | 227 + ebook_converter/ebooks/rtf2xml/hex_2_utf8.py | 589 + ebook_converter/ebooks/rtf2xml/info.py | 285 + ebook_converter/ebooks/rtf2xml/inline.py | 427 + .../ebooks/rtf2xml/line_endings.py | 56 + .../ebooks/rtf2xml/list_numbers.py | 201 + ebook_converter/ebooks/rtf2xml/list_table.py | 447 + ebook_converter/ebooks/rtf2xml/make_lists.py | 465 + ebook_converter/ebooks/rtf2xml/old_rtf.py | 146 + ebook_converter/ebooks/rtf2xml/output.py | 121 + .../ebooks/rtf2xml/override_table.py | 209 + .../ebooks/rtf2xml/paragraph_def.py | 763 + ebook_converter/ebooks/rtf2xml/paragraphs.py | 263 + ebook_converter/ebooks/rtf2xml/pict.py | 182 + .../ebooks/rtf2xml/preamble_div.py | 591 + .../ebooks/rtf2xml/preamble_rest.py | 157 + .../ebooks/rtf2xml/process_tokens.py | 837 + ebook_converter/ebooks/rtf2xml/sections.py | 538 + ebook_converter/ebooks/rtf2xml/styles.py | 723 + ebook_converter/ebooks/rtf2xml/table.py | 568 + ebook_converter/ebooks/rtf2xml/table_info.py | 88 + ebook_converter/ebooks/rtf2xml/tokenize.py | 218 + ebook_converter/ebooks/txt/__init__.py | 10 + ebook_converter/ebooks/txt/processor.py | 345 + .../ebooks/unihandecode/__init__.py | 52 + .../ebooks/unihandecode/jacodepoints.py | 5252 +++++ .../ebooks/unihandecode/jadecoder.py | 43 + .../ebooks/unihandecode/krcodepoints.py | 5252 +++++ .../ebooks/unihandecode/krdecoder.py | 25 + .../ebooks/unihandecode/unicodepoints.py | 1799 ++ .../ebooks/unihandecode/unidecoder.py | 110 + .../ebooks/unihandecode/vncodepoints.py | 5252 +++++ .../ebooks/unihandecode/vndecoder.py | 24 + .../ebooks/unihandecode/zhcodepoints.py | 5252 +++++ ebook_converter/library/__init__.py | 87 + ebook_converter/library/catalogs/__init__.py | 30 + ebook_converter/library/catalogs/bibtex.py | 402 + ebook_converter/library/catalogs/csv_xml.py | 241 + ebook_converter/library/catalogs/epub_mobi.py | 506 + ebook_converter/library/comments.py | 174 + ebook_converter/library/field_metadata.py | 702 + ebook_converter/polyglot/__init__.py | 0 ebook_converter/polyglot/binary.py | 58 + ebook_converter/polyglot/builtins.py | 202 + ebook_converter/polyglot/functools.py | 13 + ebook_converter/polyglot/html_entities.py | 10 + ebook_converter/polyglot/urllib.py | 52 + ebook_converter/ptempfile.py | 295 + ebook_converter/spell/__init__.py | 40 + ebook_converter/startup.py | 301 + ebook_converter/tinycss/__init__.py | 52 + ebook_converter/tinycss/color3.py | 382 + ebook_converter/tinycss/css21.py | 830 + ebook_converter/tinycss/decoding.py | 255 + ebook_converter/tinycss/fonts3.py | 225 + ebook_converter/tinycss/media3.py | 106 + ebook_converter/tinycss/page3.py | 163 + ebook_converter/tinycss/parsing.py | 165 + ebook_converter/tinycss/tests/__init__.py | 37 + ebook_converter/tinycss/tests/color3.py | 198 + ebook_converter/tinycss/tests/css21.py | 336 + ebook_converter/tinycss/tests/decoding.py | 71 + ebook_converter/tinycss/tests/fonts3.py | 66 + ebook_converter/tinycss/tests/main.py | 56 + ebook_converter/tinycss/tests/media3.py | 65 + ebook_converter/tinycss/tests/page3.py | 86 + ebook_converter/tinycss/tests/tokenizing.py | 269 + ebook_converter/tinycss/token_data.py | 450 + ebook_converter/tinycss/tokenizer.c | 504 + ebook_converter/tinycss/tokenizer.py | 216 + ebook_converter/tinycss/version.py | 1 + ebook_converter/translations/__init__.py | 1 + ebook_converter/translations/dynamic.py | 39 + ebook_converter/utils/__init__.py | 56 + ebook_converter/utils/cleantext.py | 98 + ebook_converter/utils/config.py | 464 + ebook_converter/utils/config_base.py | 674 + ebook_converter/utils/date.py | 485 + ebook_converter/utils/default_tweaks.py | 568 + ebook_converter/utils/filenames.py | 642 + ebook_converter/utils/fonts/__init__.py | 7 + ebook_converter/utils/fonts/metadata.py | 122 + ebook_converter/utils/fonts/scanner.py | 412 + ebook_converter/utils/fonts/utils.py | 503 + ebook_converter/utils/formatter.py | 416 + ebook_converter/utils/formatter_functions.py | 1692 ++ ebook_converter/utils/html2text.py | 42 + ebook_converter/utils/icu.py | 323 + ebook_converter/utils/img.py | 690 + ebook_converter/utils/imghdr.py | 263 + ebook_converter/utils/ipc/__init__.py | 83 + ebook_converter/utils/ipc/launch.py | 237 + ebook_converter/utils/ipc/simple_worker.py | 348 + ebook_converter/utils/iso8601.py | 65 + ebook_converter/utils/localization.py | 548 + ebook_converter/utils/localunzip.py | 340 + ebook_converter/utils/lock.py | 205 + ebook_converter/utils/logging.py | 275 + ebook_converter/utils/monotonic.py | 13 + ebook_converter/utils/mreplace.py | 44 + ebook_converter/utils/resources.py | 106 + ebook_converter/utils/serialize.py | 139 + ebook_converter/utils/shared_file.py | 222 + ebook_converter/utils/short_uuid.py | 61 + ebook_converter/utils/smartypants.py | 888 + ebook_converter/utils/speedups.py | 205 + ebook_converter/utils/terminal.py | 443 + ebook_converter/utils/titlecase.py | 109 + ebook_converter/utils/wordcount.py | 95 + ebook_converter/utils/xml_parse.py | 67 + ebook_converter/utils/zipfile.py | 1694 ++ 311 files changed, 131419 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.rst create mode 100644 ebook_converter/__init__.py create mode 100644 ebook_converter/constants.py create mode 100644 ebook_converter/css_selectors/__init__.py create mode 100644 ebook_converter/css_selectors/errors.py create mode 100644 ebook_converter/css_selectors/ordered_set.py create mode 100644 ebook_converter/css_selectors/parser.py create mode 100644 ebook_converter/css_selectors/select.py create mode 100644 ebook_converter/css_selectors/tests.py create mode 100644 ebook_converter/customize/__init__.py create mode 100644 ebook_converter/customize/builtins.py create mode 100644 ebook_converter/customize/conversion.py create mode 100644 ebook_converter/customize/profiles.py create mode 100644 ebook_converter/customize/ui.py create mode 100644 ebook_converter/customize/zipplugin.py create mode 100644 ebook_converter/devices/__init__.py create mode 100644 ebook_converter/devices/interface.py create mode 100644 ebook_converter/ebooks/BeautifulSoup.py create mode 100644 ebook_converter/ebooks/__init__.py create mode 100644 ebook_converter/ebooks/chardet.py create mode 100644 ebook_converter/ebooks/compression/__init__.py create mode 100644 ebook_converter/ebooks/compression/palmdoc.c create mode 100644 ebook_converter/ebooks/compression/palmdoc.py create mode 100644 ebook_converter/ebooks/conversion/__init__.py create mode 100644 ebook_converter/ebooks/conversion/cli.py create mode 100644 ebook_converter/ebooks/conversion/plugins/__init__.py create mode 100644 ebook_converter/ebooks/conversion/plugins/azw4_input.py create mode 100644 ebook_converter/ebooks/conversion/plugins/chm_input.py create mode 100644 ebook_converter/ebooks/conversion/plugins/comic_input.py create mode 100644 ebook_converter/ebooks/conversion/plugins/djvu_input.py create mode 100644 ebook_converter/ebooks/conversion/plugins/docx_input.py create mode 100644 ebook_converter/ebooks/conversion/plugins/docx_output.py create mode 100644 ebook_converter/ebooks/conversion/plugins/epub_input.py create mode 100644 ebook_converter/ebooks/conversion/plugins/epub_output.py create mode 100644 ebook_converter/ebooks/conversion/plugins/fb2_input.py create mode 100644 ebook_converter/ebooks/conversion/plugins/fb2_output.py create mode 100644 ebook_converter/ebooks/conversion/plugins/html_input.py create mode 100644 ebook_converter/ebooks/conversion/plugins/html_output.py create mode 100644 ebook_converter/ebooks/conversion/plugins/htmlz_input.py create mode 100644 ebook_converter/ebooks/conversion/plugins/htmlz_output.py create mode 100644 ebook_converter/ebooks/conversion/plugins/lit_input.py create mode 100644 ebook_converter/ebooks/conversion/plugins/lit_output.py create mode 100644 ebook_converter/ebooks/conversion/plugins/lrf_input.py create mode 100644 ebook_converter/ebooks/conversion/plugins/lrf_output.py create mode 100644 ebook_converter/ebooks/conversion/plugins/mobi_input.py create mode 100644 ebook_converter/ebooks/conversion/plugins/mobi_output.py create mode 100644 ebook_converter/ebooks/conversion/plugins/odt_input.py create mode 100644 ebook_converter/ebooks/conversion/plugins/oeb_output.py create mode 100644 ebook_converter/ebooks/conversion/plugins/pdb_input.py create mode 100644 ebook_converter/ebooks/conversion/plugins/pdb_output.py create mode 100644 ebook_converter/ebooks/conversion/plugins/pdf_input.py create mode 100644 ebook_converter/ebooks/conversion/plugins/pdf_output.py create mode 100644 ebook_converter/ebooks/conversion/plugins/pml_input.py create mode 100644 ebook_converter/ebooks/conversion/plugins/pml_output.py create mode 100644 ebook_converter/ebooks/conversion/plugins/rb_input.py create mode 100644 ebook_converter/ebooks/conversion/plugins/rb_output.py create mode 100644 ebook_converter/ebooks/conversion/plugins/recipe_input.py create mode 100644 ebook_converter/ebooks/conversion/plugins/rtf_input.py create mode 100644 ebook_converter/ebooks/conversion/plugins/rtf_output.py create mode 100644 ebook_converter/ebooks/conversion/plugins/snb_input.py create mode 100644 ebook_converter/ebooks/conversion/plugins/snb_output.py create mode 100644 ebook_converter/ebooks/conversion/plugins/tcr_input.py create mode 100644 ebook_converter/ebooks/conversion/plugins/tcr_output.py create mode 100644 ebook_converter/ebooks/conversion/plugins/txt_input.py create mode 100644 ebook_converter/ebooks/conversion/plugins/txt_output.py create mode 100644 ebook_converter/ebooks/conversion/plumber.py create mode 100644 ebook_converter/ebooks/conversion/preprocess.py create mode 100644 ebook_converter/ebooks/conversion/utils.py create mode 100644 ebook_converter/ebooks/docx/__init__.py create mode 100644 ebook_converter/ebooks/docx/block_styles.py create mode 100644 ebook_converter/ebooks/docx/char_styles.py create mode 100644 ebook_converter/ebooks/docx/cleanup.py create mode 100644 ebook_converter/ebooks/docx/container.py create mode 100644 ebook_converter/ebooks/docx/fields.py create mode 100644 ebook_converter/ebooks/docx/fonts.py create mode 100644 ebook_converter/ebooks/docx/footnotes.py create mode 100644 ebook_converter/ebooks/docx/images.py create mode 100644 ebook_converter/ebooks/docx/index.py create mode 100644 ebook_converter/ebooks/docx/names.py create mode 100644 ebook_converter/ebooks/docx/numbering.py create mode 100644 ebook_converter/ebooks/docx/settings.py create mode 100644 ebook_converter/ebooks/docx/styles.py create mode 100644 ebook_converter/ebooks/docx/tables.py create mode 100644 ebook_converter/ebooks/docx/theme.py create mode 100644 ebook_converter/ebooks/docx/to_html.py create mode 100644 ebook_converter/ebooks/docx/toc.py create mode 100644 ebook_converter/ebooks/html/__init__.py create mode 100644 ebook_converter/ebooks/html/input.py create mode 100644 ebook_converter/ebooks/html/to_zip.py create mode 100644 ebook_converter/ebooks/html_entities.py create mode 100644 ebook_converter/ebooks/lrf/__init__.py create mode 100644 ebook_converter/ebooks/lrf/fonts.py create mode 100644 ebook_converter/ebooks/lrf/html/__init__.py create mode 100644 ebook_converter/ebooks/lrf/html/color_map.py create mode 100644 ebook_converter/ebooks/lrf/html/convert_from.py create mode 100644 ebook_converter/ebooks/lrf/html/table.py create mode 100644 ebook_converter/ebooks/lrf/pylrs/__init__.py create mode 100644 ebook_converter/ebooks/lrf/pylrs/elements.py create mode 100644 ebook_converter/ebooks/lrf/pylrs/pylrf.py create mode 100644 ebook_converter/ebooks/lrf/pylrs/pylrfopt.py create mode 100644 ebook_converter/ebooks/lrf/pylrs/pylrs.py create mode 100644 ebook_converter/ebooks/metadata/__init__.py create mode 100644 ebook_converter/ebooks/metadata/archive.py create mode 100644 ebook_converter/ebooks/metadata/book/__init__.py create mode 100644 ebook_converter/ebooks/metadata/book/base.py create mode 100644 ebook_converter/ebooks/metadata/book/formatter.py create mode 100644 ebook_converter/ebooks/metadata/book/json_codec.py create mode 100644 ebook_converter/ebooks/metadata/html.py create mode 100644 ebook_converter/ebooks/metadata/meta.py create mode 100644 ebook_converter/ebooks/metadata/odt.py create mode 100644 ebook_converter/ebooks/metadata/opf2.py create mode 100644 ebook_converter/ebooks/metadata/opf3.py create mode 100644 ebook_converter/ebooks/metadata/rtf.py create mode 100644 ebook_converter/ebooks/metadata/toc.py create mode 100644 ebook_converter/ebooks/metadata/utils.py create mode 100644 ebook_converter/ebooks/mobi/__init__.py create mode 100644 ebook_converter/ebooks/mobi/huffcdic.py create mode 100644 ebook_converter/ebooks/mobi/langcodes.py create mode 100644 ebook_converter/ebooks/mobi/reader/__init__.py create mode 100644 ebook_converter/ebooks/mobi/reader/containers.py create mode 100644 ebook_converter/ebooks/mobi/reader/headers.py create mode 100644 ebook_converter/ebooks/mobi/reader/index.py create mode 100644 ebook_converter/ebooks/mobi/reader/markup.py create mode 100644 ebook_converter/ebooks/mobi/reader/mobi6.py create mode 100644 ebook_converter/ebooks/mobi/reader/mobi8.py create mode 100644 ebook_converter/ebooks/mobi/reader/ncx.py create mode 100644 ebook_converter/ebooks/mobi/tweak.py create mode 100644 ebook_converter/ebooks/mobi/utils.py create mode 100644 ebook_converter/ebooks/mobi/writer2/__init__.py create mode 100644 ebook_converter/ebooks/mobi/writer2/resources.py create mode 100644 ebook_converter/ebooks/odt/__init__.py create mode 100644 ebook_converter/ebooks/odt/input.py create mode 100644 ebook_converter/ebooks/oeb/__init__.py create mode 100644 ebook_converter/ebooks/oeb/base.py create mode 100644 ebook_converter/ebooks/oeb/normalize_css.py create mode 100644 ebook_converter/ebooks/oeb/parse_utils.py create mode 100644 ebook_converter/ebooks/oeb/polish/__init__.py create mode 100644 ebook_converter/ebooks/oeb/polish/container.py create mode 100644 ebook_converter/ebooks/oeb/polish/errors.py create mode 100644 ebook_converter/ebooks/oeb/polish/opf.py create mode 100644 ebook_converter/ebooks/oeb/polish/parsing.py create mode 100644 ebook_converter/ebooks/oeb/polish/pretty.py create mode 100644 ebook_converter/ebooks/oeb/polish/toc.py create mode 100644 ebook_converter/ebooks/oeb/polish/utils.py create mode 100644 ebook_converter/ebooks/oeb/reader.py create mode 100644 ebook_converter/ebooks/oeb/stylizer.py create mode 100644 ebook_converter/ebooks/oeb/transforms/__init__.py create mode 100644 ebook_converter/ebooks/oeb/transforms/data_url.py create mode 100644 ebook_converter/ebooks/oeb/transforms/flatcss.py create mode 100644 ebook_converter/ebooks/oeb/transforms/guide.py create mode 100644 ebook_converter/ebooks/oeb/transforms/jacket.py create mode 100644 ebook_converter/ebooks/oeb/transforms/metadata.py create mode 100644 ebook_converter/ebooks/oeb/transforms/page_margin.py create mode 100644 ebook_converter/ebooks/oeb/transforms/structure.py create mode 100644 ebook_converter/ebooks/oeb/transforms/trimmanifest.py create mode 100644 ebook_converter/ebooks/oeb/writer.py create mode 100644 ebook_converter/ebooks/pdb/__init__.py create mode 100644 ebook_converter/ebooks/pdb/ereader/__init__.py create mode 100644 ebook_converter/ebooks/pdb/ereader/reader.py create mode 100644 ebook_converter/ebooks/pdb/ereader/reader132.py create mode 100644 ebook_converter/ebooks/pdb/ereader/reader202.py create mode 100644 ebook_converter/ebooks/pdb/formatreader.py create mode 100644 ebook_converter/ebooks/pdb/haodoo/__init__.py create mode 100644 ebook_converter/ebooks/pdb/haodoo/reader.py create mode 100644 ebook_converter/ebooks/pdb/header.py create mode 100644 ebook_converter/ebooks/pdb/palmdoc/__init__.py create mode 100644 ebook_converter/ebooks/pdb/palmdoc/reader.py create mode 100644 ebook_converter/ebooks/pdb/pdf/__init__.py create mode 100644 ebook_converter/ebooks/pdb/pdf/reader.py create mode 100644 ebook_converter/ebooks/pdb/plucker/__init__.py create mode 100644 ebook_converter/ebooks/pdb/plucker/reader.py create mode 100644 ebook_converter/ebooks/pdb/ztxt/__init__.py create mode 100644 ebook_converter/ebooks/pdb/ztxt/reader.py create mode 100644 ebook_converter/ebooks/rtf/__init__.py create mode 100644 ebook_converter/ebooks/rtf/input.py create mode 100644 ebook_converter/ebooks/rtf2xml/ParseRtf.py create mode 100644 ebook_converter/ebooks/rtf2xml/__init__.py create mode 100644 ebook_converter/ebooks/rtf2xml/add_brackets.py create mode 100644 ebook_converter/ebooks/rtf2xml/body_styles.py create mode 100644 ebook_converter/ebooks/rtf2xml/border_parse.py create mode 100644 ebook_converter/ebooks/rtf2xml/char_set.py create mode 100644 ebook_converter/ebooks/rtf2xml/check_brackets.py create mode 100644 ebook_converter/ebooks/rtf2xml/check_encoding.py create mode 100644 ebook_converter/ebooks/rtf2xml/colors.py create mode 100644 ebook_converter/ebooks/rtf2xml/combine_borders.py create mode 100644 ebook_converter/ebooks/rtf2xml/convert_to_tags.py create mode 100644 ebook_converter/ebooks/rtf2xml/copy.py create mode 100644 ebook_converter/ebooks/rtf2xml/default_encoding.py create mode 100644 ebook_converter/ebooks/rtf2xml/delete_info.py create mode 100644 ebook_converter/ebooks/rtf2xml/field_strings.py create mode 100644 ebook_converter/ebooks/rtf2xml/fields_large.py create mode 100644 ebook_converter/ebooks/rtf2xml/fields_small.py create mode 100644 ebook_converter/ebooks/rtf2xml/fonts.py create mode 100644 ebook_converter/ebooks/rtf2xml/footnote.py create mode 100644 ebook_converter/ebooks/rtf2xml/get_char_map.py create mode 100644 ebook_converter/ebooks/rtf2xml/group_borders.py create mode 100644 ebook_converter/ebooks/rtf2xml/group_styles.py create mode 100644 ebook_converter/ebooks/rtf2xml/header.py create mode 100644 ebook_converter/ebooks/rtf2xml/headings_to_sections.py create mode 100644 ebook_converter/ebooks/rtf2xml/hex_2_utf8.py create mode 100644 ebook_converter/ebooks/rtf2xml/info.py create mode 100644 ebook_converter/ebooks/rtf2xml/inline.py create mode 100644 ebook_converter/ebooks/rtf2xml/line_endings.py create mode 100644 ebook_converter/ebooks/rtf2xml/list_numbers.py create mode 100644 ebook_converter/ebooks/rtf2xml/list_table.py create mode 100644 ebook_converter/ebooks/rtf2xml/make_lists.py create mode 100644 ebook_converter/ebooks/rtf2xml/old_rtf.py create mode 100644 ebook_converter/ebooks/rtf2xml/output.py create mode 100644 ebook_converter/ebooks/rtf2xml/override_table.py create mode 100644 ebook_converter/ebooks/rtf2xml/paragraph_def.py create mode 100644 ebook_converter/ebooks/rtf2xml/paragraphs.py create mode 100644 ebook_converter/ebooks/rtf2xml/pict.py create mode 100644 ebook_converter/ebooks/rtf2xml/preamble_div.py create mode 100644 ebook_converter/ebooks/rtf2xml/preamble_rest.py create mode 100644 ebook_converter/ebooks/rtf2xml/process_tokens.py create mode 100644 ebook_converter/ebooks/rtf2xml/sections.py create mode 100644 ebook_converter/ebooks/rtf2xml/styles.py create mode 100644 ebook_converter/ebooks/rtf2xml/table.py create mode 100644 ebook_converter/ebooks/rtf2xml/table_info.py create mode 100644 ebook_converter/ebooks/rtf2xml/tokenize.py create mode 100644 ebook_converter/ebooks/txt/__init__.py create mode 100644 ebook_converter/ebooks/txt/processor.py create mode 100644 ebook_converter/ebooks/unihandecode/__init__.py create mode 100644 ebook_converter/ebooks/unihandecode/jacodepoints.py create mode 100644 ebook_converter/ebooks/unihandecode/jadecoder.py create mode 100644 ebook_converter/ebooks/unihandecode/krcodepoints.py create mode 100644 ebook_converter/ebooks/unihandecode/krdecoder.py create mode 100644 ebook_converter/ebooks/unihandecode/unicodepoints.py create mode 100644 ebook_converter/ebooks/unihandecode/unidecoder.py create mode 100644 ebook_converter/ebooks/unihandecode/vncodepoints.py create mode 100644 ebook_converter/ebooks/unihandecode/vndecoder.py create mode 100644 ebook_converter/ebooks/unihandecode/zhcodepoints.py create mode 100644 ebook_converter/library/__init__.py create mode 100644 ebook_converter/library/catalogs/__init__.py create mode 100644 ebook_converter/library/catalogs/bibtex.py create mode 100644 ebook_converter/library/catalogs/csv_xml.py create mode 100644 ebook_converter/library/catalogs/epub_mobi.py create mode 100644 ebook_converter/library/comments.py create mode 100644 ebook_converter/library/field_metadata.py create mode 100644 ebook_converter/polyglot/__init__.py create mode 100644 ebook_converter/polyglot/binary.py create mode 100644 ebook_converter/polyglot/builtins.py create mode 100644 ebook_converter/polyglot/functools.py create mode 100644 ebook_converter/polyglot/html_entities.py create mode 100644 ebook_converter/polyglot/urllib.py create mode 100644 ebook_converter/ptempfile.py create mode 100644 ebook_converter/spell/__init__.py create mode 100644 ebook_converter/startup.py create mode 100644 ebook_converter/tinycss/__init__.py create mode 100644 ebook_converter/tinycss/color3.py create mode 100644 ebook_converter/tinycss/css21.py create mode 100644 ebook_converter/tinycss/decoding.py create mode 100644 ebook_converter/tinycss/fonts3.py create mode 100644 ebook_converter/tinycss/media3.py create mode 100644 ebook_converter/tinycss/page3.py create mode 100644 ebook_converter/tinycss/parsing.py create mode 100644 ebook_converter/tinycss/tests/__init__.py create mode 100644 ebook_converter/tinycss/tests/color3.py create mode 100644 ebook_converter/tinycss/tests/css21.py create mode 100644 ebook_converter/tinycss/tests/decoding.py create mode 100644 ebook_converter/tinycss/tests/fonts3.py create mode 100644 ebook_converter/tinycss/tests/main.py create mode 100644 ebook_converter/tinycss/tests/media3.py create mode 100644 ebook_converter/tinycss/tests/page3.py create mode 100644 ebook_converter/tinycss/tests/tokenizing.py create mode 100644 ebook_converter/tinycss/token_data.py create mode 100644 ebook_converter/tinycss/tokenizer.c create mode 100644 ebook_converter/tinycss/tokenizer.py create mode 100644 ebook_converter/tinycss/version.py create mode 100644 ebook_converter/translations/__init__.py create mode 100644 ebook_converter/translations/dynamic.py create mode 100644 ebook_converter/utils/__init__.py create mode 100644 ebook_converter/utils/cleantext.py create mode 100644 ebook_converter/utils/config.py create mode 100644 ebook_converter/utils/config_base.py create mode 100644 ebook_converter/utils/date.py create mode 100644 ebook_converter/utils/default_tweaks.py create mode 100644 ebook_converter/utils/filenames.py create mode 100644 ebook_converter/utils/fonts/__init__.py create mode 100644 ebook_converter/utils/fonts/metadata.py create mode 100644 ebook_converter/utils/fonts/scanner.py create mode 100644 ebook_converter/utils/fonts/utils.py create mode 100644 ebook_converter/utils/formatter.py create mode 100644 ebook_converter/utils/formatter_functions.py create mode 100644 ebook_converter/utils/html2text.py create mode 100644 ebook_converter/utils/icu.py create mode 100644 ebook_converter/utils/img.py create mode 100644 ebook_converter/utils/imghdr.py create mode 100644 ebook_converter/utils/ipc/__init__.py create mode 100644 ebook_converter/utils/ipc/launch.py create mode 100644 ebook_converter/utils/ipc/simple_worker.py create mode 100644 ebook_converter/utils/iso8601.py create mode 100644 ebook_converter/utils/localization.py create mode 100644 ebook_converter/utils/localunzip.py create mode 100644 ebook_converter/utils/lock.py create mode 100644 ebook_converter/utils/logging.py create mode 100644 ebook_converter/utils/monotonic.py create mode 100644 ebook_converter/utils/mreplace.py create mode 100644 ebook_converter/utils/resources.py create mode 100644 ebook_converter/utils/serialize.py create mode 100644 ebook_converter/utils/shared_file.py create mode 100644 ebook_converter/utils/short_uuid.py create mode 100644 ebook_converter/utils/smartypants.py create mode 100644 ebook_converter/utils/speedups.py create mode 100644 ebook_converter/utils/terminal.py create mode 100644 ebook_converter/utils/titlecase.py create mode 100644 ebook_converter/utils/wordcount.py create mode 100644 ebook_converter/utils/xml_parse.py create mode 100644 ebook_converter/utils/zipfile.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bee8a64 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e600086 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..5fd4206 --- /dev/null +++ b/README.rst @@ -0,0 +1,26 @@ +=============== +Ebook converter +=============== + +This is impudent ripoff of the bits from `Calibre project`_, and is aimed only +for converter thing. + +My motivation is to have only converter for ebooks run from commandline, +without all of those bells and whistles Calibre have, and with cleanest more +*pythonic* approach. + + +Installation +------------ + +TBD. + + +License +------- + +This work is licensed on GPL3 license, like the original work. See LICENSE file +for details. + + +.. _Calibre project: https://calibre-ebook.com/ diff --git a/ebook_converter/__init__.py b/ebook_converter/__init__.py new file mode 100644 index 0000000..30d38f6 --- /dev/null +++ b/ebook_converter/__init__.py @@ -0,0 +1,681 @@ +from __future__ import unicode_literals, print_function +''' E-book management software''' +__license__ = 'GPL v3' +__copyright__ = '2008, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import sys, os, re, time, random, warnings +from polyglot.builtins import codepoint_to_chr, unicode_type, range, hasenv, native_string_type +from math import floor +from functools import partial + +if not hasenv('CALIBRE_SHOW_DEPRECATION_WARNINGS'): + warnings.simplefilter('ignore', DeprecationWarning) +try: + os.getcwd() +except EnvironmentError: + os.chdir(os.path.expanduser('~')) + +from calibre.constants import (iswindows, isosx, islinux, isfrozen, + isbsd, preferred_encoding, __appname__, __version__, __author__, + win32event, win32api, winerror, fcntl, ispy3, + filesystem_encoding, plugins, config_dir) +from calibre.startup import winutil, winutilerror +from calibre.utils.icu import safe_chr + +if False: + # Prevent pyflakes from complaining + winutil, winutilerror, __appname__, islinux, __version__ + fcntl, win32event, isfrozen, __author__ + winerror, win32api, isbsd, config_dir + +_mt_inited = False + + +def _init_mimetypes(): + global _mt_inited + import mimetypes + mimetypes.init([P('mime.types')]) + _mt_inited = True + + +def guess_type(*args, **kwargs): + import mimetypes + if not _mt_inited: + _init_mimetypes() + return mimetypes.guess_type(*args, **kwargs) + + +def guess_all_extensions(*args, **kwargs): + import mimetypes + if not _mt_inited: + _init_mimetypes() + return mimetypes.guess_all_extensions(*args, **kwargs) + + +def guess_extension(*args, **kwargs): + import mimetypes + if not _mt_inited: + _init_mimetypes() + ext = mimetypes.guess_extension(*args, **kwargs) + if not ext and args and args[0] == 'application/x-palmreader': + ext = '.pdb' + return ext + + +def get_types_map(): + import mimetypes + if not _mt_inited: + _init_mimetypes() + return mimetypes.types_map + + +def to_unicode(raw, encoding='utf-8', errors='strict'): + if isinstance(raw, unicode_type): + return raw + return raw.decode(encoding, errors) + + +def patheq(p1, p2): + p = os.path + d = lambda x : p.normcase(p.normpath(p.realpath(p.normpath(x)))) + if not p1 or not p2: + return False + return d(p1) == d(p2) + + +def unicode_path(path, abs=False): + if isinstance(path, bytes): + path = path.decode(filesystem_encoding) + if abs: + path = os.path.abspath(path) + return path + + +def osx_version(): + if isosx: + import platform + src = platform.mac_ver()[0] + m = re.match(r'(\d+)\.(\d+)\.(\d+)', src) + if m: + return int(m.group(1)), int(m.group(2)), int(m.group(3)) + + +def confirm_config_name(name): + return name + '_again' + + +_filename_sanitize_unicode = frozenset(('\\', '|', '?', '*', '<', # no2to3 + '"', ':', '>', '+', '/') + tuple(map(codepoint_to_chr, range(32)))) # no2to3 + + +def sanitize_file_name(name, substitute='_'): + ''' + Sanitize the filename `name`. All invalid characters are replaced by `substitute`. + The set of invalid characters is the union of the invalid characters in Windows, + macOS and Linux. Also removes leading and trailing whitespace. + **WARNING:** This function also replaces path separators, so only pass file names + and not full paths to it. + ''' + if isbytestring(name): + name = name.decode(filesystem_encoding, 'replace') + if isbytestring(substitute): + substitute = substitute.decode(filesystem_encoding, 'replace') + chars = (substitute if c in _filename_sanitize_unicode else c for c in name) + one = ''.join(chars) + one = re.sub(r'\s', ' ', one).strip() + bname, ext = os.path.splitext(one) + one = re.sub(r'^\.+$', '_', bname) + one = one.replace('..', substitute) + one += ext + # Windows doesn't like path components that end with a period or space + if one and one[-1] in ('.', ' '): + one = one[:-1]+'_' + # Names starting with a period are hidden on Unix + if one.startswith('.'): + one = '_' + one[1:] + return one + + +sanitize_file_name2 = sanitize_file_name_unicode = sanitize_file_name + + +def prints(*args, **kwargs): + ''' + Print unicode arguments safely by encoding them to preferred_encoding + Has the same signature as the print function from Python 3, except for the + additional keyword argument safe_encode, which if set to True will cause the + function to use repr when encoding fails. + + Returns the number of bytes written. + ''' + file = kwargs.get('file', sys.stdout) + file = getattr(file, 'buffer', file) + enc = 'utf-8' if hasenv('CALIBRE_WORKER') else preferred_encoding + sep = kwargs.get('sep', ' ') + if not isinstance(sep, bytes): + sep = sep.encode(enc) + end = kwargs.get('end', '\n') + if not isinstance(end, bytes): + end = end.encode(enc) + safe_encode = kwargs.get('safe_encode', False) + count = 0 + for i, arg in enumerate(args): + if isinstance(arg, unicode_type): + if iswindows: + from calibre.utils.terminal import Detect + cs = Detect(file) + if cs.is_console: + cs.write_unicode_text(arg) + count += len(arg) + if i != len(args)-1: + file.write(sep) + count += len(sep) + continue + try: + arg = arg.encode(enc) + except UnicodeEncodeError: + try: + arg = arg.encode('utf-8') + except: + if not safe_encode: + raise + arg = repr(arg) + if not isinstance(arg, bytes): + try: + arg = native_string_type(arg) + except ValueError: + arg = unicode_type(arg) + if isinstance(arg, unicode_type): + try: + arg = arg.encode(enc) + except UnicodeEncodeError: + try: + arg = arg.encode('utf-8') + except: + if not safe_encode: + raise + arg = repr(arg) + + try: + file.write(arg) + count += len(arg) + except: + from polyglot import reprlib + arg = reprlib.repr(arg) + file.write(arg) + count += len(arg) + if i != len(args)-1: + file.write(sep) + count += len(sep) + file.write(end) + count += len(end) + return count + + +class CommandLineError(Exception): + pass + + +def setup_cli_handlers(logger, level): + import logging + if hasenv('CALIBRE_WORKER') and logger.handlers: + return + logger.setLevel(level) + if level == logging.WARNING: + handler = logging.StreamHandler(sys.stdout) + handler.setFormatter(logging.Formatter('%(levelname)s: %(message)s')) + handler.setLevel(logging.WARNING) + elif level == logging.INFO: + handler = logging.StreamHandler(sys.stdout) + handler.setFormatter(logging.Formatter()) + handler.setLevel(logging.INFO) + elif level == logging.DEBUG: + handler = logging.StreamHandler(sys.stderr) + handler.setLevel(logging.DEBUG) + handler.setFormatter(logging.Formatter('[%(levelname)s] %(filename)s:%(lineno)s: %(message)s')) + + logger.addHandler(handler) + + +def load_library(name, cdll): + if iswindows: + return cdll.LoadLibrary(name) + if isosx: + name += '.dylib' + if hasattr(sys, 'frameworks_dir'): + return cdll.LoadLibrary(os.path.join(getattr(sys, 'frameworks_dir'), name)) + return cdll.LoadLibrary(name) + return cdll.LoadLibrary(name+'.so') + + +def extract(path, dir): + extractor = None + # First use the file header to identify its type + with open(path, 'rb') as f: + id_ = f.read(3) + if id_ == b'Rar': + from calibre.utils.unrar import extract as rarextract + extractor = rarextract + elif id_.startswith(b'PK'): + from calibre.libunzip import extract as zipextract + extractor = zipextract + if extractor is None: + # Fallback to file extension + ext = os.path.splitext(path)[1][1:].lower() + if ext in ['zip', 'cbz', 'epub', 'oebzip']: + from calibre.libunzip import extract as zipextract + extractor = zipextract + elif ext in ['cbr', 'rar']: + from calibre.utils.unrar import extract as rarextract + extractor = rarextract + if extractor is None: + raise Exception('Unknown archive type') + extractor(path, dir) + + +def get_proxies(debug=True): + from polyglot.urllib import getproxies + proxies = getproxies() + for key, proxy in list(proxies.items()): + if not proxy or '..' in proxy or key == 'auto': + del proxies[key] + continue + if proxy.startswith(key+'://'): + proxy = proxy[len(key)+3:] + if key == 'https' and proxy.startswith('http://'): + proxy = proxy[7:] + if proxy.endswith('/'): + proxy = proxy[:-1] + if len(proxy) > 4: + proxies[key] = proxy + else: + prints('Removing invalid', key, 'proxy:', proxy) + del proxies[key] + + if proxies and debug: + prints('Using proxies:', proxies) + return proxies + + +def get_parsed_proxy(typ='http', debug=True): + proxies = get_proxies(debug) + proxy = proxies.get(typ, None) + if proxy: + pattern = re.compile(( + '(?:ptype://)?' + '(?:(?P\\w+):(?P.*)@)?' + '(?P[\\w\\-\\.]+)' + '(?::(?P\\d+))?').replace('ptype', typ) + ) + + match = pattern.match(proxies[typ]) + if match: + try: + ans = { + 'host' : match.group('host'), + 'port' : match.group('port'), + 'user' : match.group('user'), + 'pass' : match.group('pass') + } + if ans['port']: + ans['port'] = int(ans['port']) + except: + if debug: + import traceback + traceback.print_exc() + else: + if debug: + prints('Using http proxy', unicode_type(ans)) + return ans + + +def get_proxy_info(proxy_scheme, proxy_string): + ''' + Parse all proxy information from a proxy string (as returned by + get_proxies). The returned dict will have members set to None when the info + is not available in the string. If an exception occurs parsing the string + this method returns None. + ''' + from polyglot.urllib import urlparse + try: + proxy_url = '%s://%s'%(proxy_scheme, proxy_string) + urlinfo = urlparse(proxy_url) + ans = { + 'scheme': urlinfo.scheme, + 'hostname': urlinfo.hostname, + 'port': urlinfo.port, + 'username': urlinfo.username, + 'password': urlinfo.password, + } + except Exception: + return None + return ans + + +# IE 11 on windows 7 +USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko' +USER_AGENT_MOBILE = 'Mozilla/5.0 (Windows; U; Windows CE 5.1; rv:1.8.1a3) Gecko/20060610 Minimo/0.016' + + +def is_mobile_ua(ua): + return 'Mobile/' in ua or 'Mobile ' in ua + + +def random_user_agent(choose=None, allow_ie=True): + from calibre.utils.random_ua import common_user_agents + ua_list = common_user_agents() + ua_list = [x for x in ua_list if not is_mobile_ua(x)] + if not allow_ie: + ua_list = [x for x in ua_list if 'Trident/' not in x and 'Edge/' not in x] + return random.choice(ua_list) if choose is None else ua_list[choose] + + +def browser(honor_time=True, max_time=2, mobile_browser=False, user_agent=None, verify_ssl_certificates=True, handle_refresh=True): + ''' + Create a mechanize browser for web scraping. The browser handles cookies, + refresh requests and ignores robots.txt. Also uses proxy if available. + + :param honor_time: If True honors pause time in refresh requests + :param max_time: Maximum time in seconds to wait during a refresh request + :param verify_ssl_certificates: If false SSL certificates errors are ignored + ''' + from calibre.utils.browser import Browser + opener = Browser(verify_ssl=verify_ssl_certificates) + opener.set_handle_refresh(handle_refresh, max_time=max_time, honor_time=honor_time) + opener.set_handle_robots(False) + if user_agent is None: + user_agent = USER_AGENT_MOBILE if mobile_browser else USER_AGENT + opener.addheaders = [('User-agent', user_agent)] + proxies = get_proxies() + to_add = {} + http_proxy = proxies.get('http', None) + if http_proxy: + to_add['http'] = http_proxy + https_proxy = proxies.get('https', None) + if https_proxy: + to_add['https'] = https_proxy + if to_add: + opener.set_proxies(to_add) + + return opener + + +def fit_image(width, height, pwidth, pheight): + ''' + Fit image in box of width pwidth and height pheight. + @param width: Width of image + @param height: Height of image + @param pwidth: Width of box + @param pheight: Height of box + @return: scaled, new_width, new_height. scaled is True iff new_width and/or new_height is different from width or height. + ''' + scaled = height > pheight or width > pwidth + if height > pheight: + corrf = pheight / float(height) + width, height = floor(corrf*width), pheight + if width > pwidth: + corrf = pwidth / float(width) + width, height = pwidth, floor(corrf*height) + if height > pheight: + corrf = pheight / float(height) + width, height = floor(corrf*width), pheight + + return scaled, int(width), int(height) + + +class CurrentDir(object): + + def __init__(self, path): + self.path = path + self.cwd = None + + def __enter__(self, *args): + self.cwd = os.getcwd() + os.chdir(self.path) + return self.cwd + + def __exit__(self, *args): + try: + os.chdir(self.cwd) + except EnvironmentError: + # The previous CWD no longer exists + pass + + +_ncpus = None + + +if ispy3: + def detect_ncpus(): + global _ncpus + if _ncpus is None: + _ncpus = max(1, os.cpu_count() or 1) + return _ncpus +else: + def detect_ncpus(): + """Detects the number of effective CPUs in the system""" + global _ncpus + if _ncpus is None: + if iswindows: + import win32api + ans = win32api.GetSystemInfo()[5] + else: + import multiprocessing + ans = -1 + try: + ans = multiprocessing.cpu_count() + except Exception: + from PyQt5.Qt import QThread + ans = QThread.idealThreadCount() + _ncpus = max(1, ans) + return _ncpus + + +relpath = os.path.relpath + + +def walk(dir): + ''' A nice interface to os.walk ''' + for record in os.walk(dir): + for f in record[-1]: + yield os.path.join(record[0], f) + + +def strftime(fmt, t=None): + ''' A version of strftime that returns unicode strings and tries to handle dates + before 1900 ''' + if not fmt: + return '' + if t is None: + t = time.localtime() + if hasattr(t, 'timetuple'): + t = t.timetuple() + early_year = t[0] < 1900 + if early_year: + replacement = 1900 if t[0]%4 == 0 else 1901 + fmt = fmt.replace('%Y', '_early year hack##') + t = list(t) + orig_year = t[0] + t[0] = replacement + t = time.struct_time(t) + ans = None + if iswindows: + if isinstance(fmt, bytes): + fmt = fmt.decode('mbcs', 'replace') + fmt = fmt.replace('%e', '%#d') + ans = plugins['winutil'][0].strftime(fmt, t) + else: + ans = time.strftime(fmt, t) + if isinstance(ans, bytes): + ans = ans.decode(preferred_encoding, 'replace') + if early_year: + ans = ans.replace('_early year hack##', unicode_type(orig_year)) + return ans + + +def my_unichr(num): + try: + return safe_chr(num) + except (ValueError, OverflowError): + return '?' + + +def entity_to_unicode(match, exceptions=[], encoding='cp1252', + result_exceptions={}): + ''' + :param match: A match object such that '&'+match.group(1)';' is the entity. + + :param exceptions: A list of entities to not convert (Each entry is the name of the entity, for e.g. 'apos' or '#1234' + + :param encoding: The encoding to use to decode numeric entities between 128 and 256. + If None, the Unicode UCS encoding is used. A common encoding is cp1252. + + :param result_exceptions: A mapping of characters to entities. If the result + is in result_exceptions, result_exception[result] is returned instead. + Convenient way to specify exception for things like < or > that can be + specified by various actual entities. + ''' + def check(ch): + return result_exceptions.get(ch, ch) + + ent = match.group(1) + if ent in exceptions: + return '&'+ent+';' + if ent in {'apos', 'squot'}: # squot is generated by some broken CMS software + return check("'") + if ent == 'hellips': + ent = 'hellip' + if ent.startswith('#'): + try: + if ent[1] in ('x', 'X'): + num = int(ent[2:], 16) + else: + num = int(ent[1:]) + except: + return '&'+ent+';' + if encoding is None or num > 255: + return check(my_unichr(num)) + try: + return check(bytes(bytearray((num,))).decode(encoding)) + except UnicodeDecodeError: + return check(my_unichr(num)) + from calibre.ebooks.html_entities import html5_entities + try: + return check(html5_entities[ent]) + except KeyError: + pass + from polyglot.html_entities import name2codepoint + try: + return check(my_unichr(name2codepoint[ent])) + except KeyError: + return '&'+ent+';' + + +_ent_pat = re.compile(r'&(\S+?);') +xml_entity_to_unicode = partial(entity_to_unicode, result_exceptions={ + '"' : '"', + "'" : ''', + '<' : '<', + '>' : '>', + '&' : '&'}) + + +def replace_entities(raw, encoding='cp1252'): + return _ent_pat.sub(partial(entity_to_unicode, encoding=encoding), raw) + + +def xml_replace_entities(raw, encoding='cp1252'): + return _ent_pat.sub(partial(xml_entity_to_unicode, encoding=encoding), raw) + + +def prepare_string_for_xml(raw, attribute=False): + raw = _ent_pat.sub(entity_to_unicode, raw) + raw = raw.replace('&', '&').replace('<', '<').replace('>', '>') + if attribute: + raw = raw.replace('"', '"').replace("'", ''') + return raw + + +def isbytestring(obj): + return isinstance(obj, bytes) + + +def force_unicode(obj, enc=preferred_encoding): + if isbytestring(obj): + try: + obj = obj.decode(enc) + except Exception: + try: + obj = obj.decode(filesystem_encoding if enc == + preferred_encoding else preferred_encoding) + except Exception: + try: + obj = obj.decode('utf-8') + except Exception: + obj = repr(obj) + if isbytestring(obj): + obj = obj.decode('utf-8') + return obj + + +def as_unicode(obj, enc=preferred_encoding): + if not isbytestring(obj): + try: + obj = unicode_type(obj) + except Exception: + try: + obj = native_string_type(obj) + except Exception: + obj = repr(obj) + return force_unicode(obj, enc=enc) + + +def url_slash_cleaner(url): + ''' + Removes redundant /'s from url's. + ''' + return re.sub(r'(? -1: + size = size[:size.find(".")+2] + if size.endswith('.0'): + size = size[:-2] + return size + sep + suffix + + +def ipython(user_ns=None): + from calibre.utils.ipython import ipython + ipython(user_ns=user_ns) + + +def fsync(fileobj): + fileobj.flush() + os.fsync(fileobj.fileno()) + if islinux and getattr(fileobj, 'name', None): + # On Linux kernels after 5.1.9 and 4.19.50 using fsync without any + # following activity causes Kindles to eject. Instead of fixing this in + # the obvious way, which is to have the kernel send some harmless + # filesystem activity after the FSYNC, the kernel developers seem to + # think the correct solution is to disable FSYNC using a mount flag + # which users will have to turn on manually. So instead we create some + # harmless filesystem activity, and who cares about performance. + # See https://bugs.launchpad.net/calibre/+bug/1834641 + # and https://bugzilla.kernel.org/show_bug.cgi?id=203973 + # To check for the existence of the bug, simply run: + # python -c "p = '/run/media/kovid/Kindle/driveinfo.calibre'; f = open(p, 'r+b'); os.fsync(f.fileno());" + # this will cause the Kindle to disconnect. + try: + os.utime(fileobj.name, None) + except Exception: + import traceback + traceback.print_exc() diff --git a/ebook_converter/constants.py b/ebook_converter/constants.py new file mode 100644 index 0000000..83b89fd --- /dev/null +++ b/ebook_converter/constants.py @@ -0,0 +1,343 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +# License: GPLv3 Copyright: 2015, Kovid Goyal +from __future__ import print_function, unicode_literals +from polyglot.builtins import map, unicode_type, environ_item, hasenv, getenv, as_unicode, native_string_type +import sys, locale, codecs, os, importlib, collections + +__appname__ = 'calibre' +numeric_version = (4, 12, 0) +__version__ = '.'.join(map(unicode_type, numeric_version)) +git_version = None +__author__ = "Kovid Goyal " + +''' +Various run time constants. +''' + + +_plat = sys.platform.lower() +iswindows = 'win32' in _plat or 'win64' in _plat +isosx = 'darwin' in _plat +isnewosx = isosx and getattr(sys, 'new_app_bundle', False) +isfreebsd = 'freebsd' in _plat +isnetbsd = 'netbsd' in _plat +isdragonflybsd = 'dragonfly' in _plat +isbsd = isfreebsd or isnetbsd or isdragonflybsd +ishaiku = 'haiku1' in _plat +islinux = not(iswindows or isosx or isbsd or ishaiku) +isfrozen = hasattr(sys, 'frozen') +isunix = isosx or islinux or ishaiku +isportable = hasenv('CALIBRE_PORTABLE_BUILD') +ispy3 = sys.version_info.major > 2 +isxp = isoldvista = False +if iswindows: + wver = sys.getwindowsversion() + isxp = wver.major < 6 + isoldvista = wver.build < 6002 +is64bit = sys.maxsize > (1 << 32) +isworker = hasenv('CALIBRE_WORKER') or hasenv('CALIBRE_SIMPLE_WORKER') +if isworker: + os.environ.pop(environ_item('CALIBRE_FORCE_ANSI'), None) +FAKE_PROTOCOL, FAKE_HOST = 'clbr', 'internal.invalid' +VIEWER_APP_UID = 'com.calibre-ebook.viewer' +EDITOR_APP_UID = 'com.calibre-ebook.edit-book' +MAIN_APP_UID = 'com.calibre-ebook.main-gui' +STORE_DIALOG_APP_UID = 'com.calibre-ebook.store-dialog' +TOC_DIALOG_APP_UID = 'com.calibre-ebook.toc-editor' +try: + preferred_encoding = locale.getpreferredencoding() + codecs.lookup(preferred_encoding) +except: + preferred_encoding = 'utf-8' + +win32event = importlib.import_module('win32event') if iswindows else None +winerror = importlib.import_module('winerror') if iswindows else None +win32api = importlib.import_module('win32api') if iswindows else None +fcntl = None if iswindows else importlib.import_module('fcntl') +dark_link_color = '#6cb4ee' + +_osx_ver = None + + +def get_osx_version(): + global _osx_ver + if _osx_ver is None: + import platform + from collections import namedtuple + OSX = namedtuple('OSX', 'major minor tertiary') + try: + ver = platform.mac_ver()[0].split('.') + if len(ver) == 2: + ver.append(0) + _osx_ver = OSX(*map(int, ver)) # no2to3 + except Exception: + _osx_ver = OSX(0, 0, 0) + return _osx_ver + + +filesystem_encoding = sys.getfilesystemencoding() +if filesystem_encoding is None: + filesystem_encoding = 'utf-8' +else: + try: + if codecs.lookup(filesystem_encoding).name == 'ascii': + filesystem_encoding = 'utf-8' + # On linux, unicode arguments to os file functions are coerced to an ascii + # bytestring if sys.getfilesystemencoding() == 'ascii', which is + # just plain dumb. This is fixed by the icu.py module which, when + # imported changes ascii to utf-8 + except Exception: + filesystem_encoding = 'utf-8' + + +DEBUG = hasenv('CALIBRE_DEBUG') + + +def debug(): + global DEBUG + DEBUG = True + + +def _get_cache_dir(): + import errno + confcache = os.path.join(config_dir, 'caches') + try: + os.makedirs(confcache) + except EnvironmentError as err: + if err.errno != errno.EEXIST: + raise + if isportable: + return confcache + ccd = getenv('CALIBRE_CACHE_DIRECTORY') + if ccd is not None: + ans = os.path.abspath(ccd) + try: + os.makedirs(ans) + return ans + except EnvironmentError as err: + if err.errno == errno.EEXIST: + return ans + + if iswindows: + w = plugins['winutil'][0] + try: + candidate = os.path.join(w.special_folder_path(w.CSIDL_LOCAL_APPDATA), '%s-cache'%__appname__) + except ValueError: + return confcache + elif isosx: + candidate = os.path.join(os.path.expanduser('~/Library/Caches'), __appname__) + else: + candidate = getenv('XDG_CACHE_HOME', '~/.cache') + candidate = os.path.join(os.path.expanduser(candidate), + __appname__) + if isinstance(candidate, bytes): + try: + candidate = candidate.decode(filesystem_encoding) + except ValueError: + candidate = confcache + try: + os.makedirs(candidate) + except EnvironmentError as err: + if err.errno != errno.EEXIST: + candidate = confcache + return candidate + + +def cache_dir(): + ans = getattr(cache_dir, 'ans', None) + if ans is None: + ans = cache_dir.ans = os.path.realpath(_get_cache_dir()) + return ans + + +plugins_loc = sys.extensions_location +if ispy3: + plugins_loc = os.path.join(plugins_loc, '3') + + +# plugins {{{ + + +class Plugins(collections.Mapping): + + def __init__(self): + self._plugins = {} + plugins = [ + 'pictureflow', + 'lzx', + 'msdes', + 'podofo', + 'cPalmdoc', + 'progress_indicator', + 'chmlib', + 'icu', + 'speedup', + 'html_as_json', + 'unicode_names', + 'html_syntax_highlighter', + 'hyphen', + 'freetype', + 'imageops', + 'hunspell', + '_patiencediff_c', + 'bzzdec', + 'matcher', + 'tokenizer', + 'certgen', + 'lzma_binding', + ] + if not ispy3: + plugins.extend([ + 'monotonic', + 'zlib2', + ]) + if iswindows: + plugins.extend(['winutil', 'wpd', 'winfonts']) + if isosx: + plugins.append('usbobserver') + plugins.append('cocoa') + if isfreebsd or ishaiku or islinux or isosx: + plugins.append('libusb') + plugins.append('libmtp') + self.plugins = frozenset(plugins) + + def load_plugin(self, name): + if name in self._plugins: + return + sys.path.insert(0, plugins_loc) + try: + del sys.modules[name] + except KeyError: + pass + plugin_err = '' + try: + p = importlib.import_module(name) + except Exception as err: + p = None + try: + plugin_err = unicode_type(err) + except Exception: + plugin_err = as_unicode(native_string_type(err), encoding=preferred_encoding, errors='replace') + self._plugins[name] = p, plugin_err + sys.path.remove(plugins_loc) + + def __iter__(self): + return iter(self.plugins) + + def __len__(self): + return len(self.plugins) + + def __contains__(self, name): + return name in self.plugins + + def __getitem__(self, name): + if name not in self.plugins: + raise KeyError('No plugin named %r'%name) + self.load_plugin(name) + return self._plugins[name] + + +plugins = None +if plugins is None: + plugins = Plugins() +# }}} + +# config_dir {{{ + +CONFIG_DIR_MODE = 0o700 + +cconfd = getenv('CALIBRE_CONFIG_DIRECTORY') +if cconfd is not None: + config_dir = os.path.abspath(cconfd) +elif iswindows: + if plugins['winutil'][0] is None: + raise Exception(plugins['winutil'][1]) + try: + config_dir = plugins['winutil'][0].special_folder_path(plugins['winutil'][0].CSIDL_APPDATA) + except ValueError: + config_dir = None + if not config_dir or not os.access(config_dir, os.W_OK|os.X_OK): + config_dir = os.path.expanduser('~') + config_dir = os.path.join(config_dir, 'calibre') +elif isosx: + config_dir = os.path.expanduser('~/Library/Preferences/calibre') +else: + bdir = os.path.abspath(os.path.expanduser(getenv('XDG_CONFIG_HOME', '~/.config'))) + config_dir = os.path.join(bdir, 'calibre') + try: + os.makedirs(config_dir, mode=CONFIG_DIR_MODE) + except: + pass + if not os.path.exists(config_dir) or \ + not os.access(config_dir, os.W_OK) or not \ + os.access(config_dir, os.X_OK): + print('No write acces to', config_dir, 'using a temporary dir instead') + import tempfile, atexit + config_dir = tempfile.mkdtemp(prefix='calibre-config-') + + def cleanup_cdir(): + try: + import shutil + shutil.rmtree(config_dir) + except: + pass + atexit.register(cleanup_cdir) +# }}} + + +dv = getenv('CALIBRE_DEVELOP_FROM') +is_running_from_develop = bool(getattr(sys, 'frozen', False) and dv and os.path.abspath(dv) in sys.path) +del dv + + +def get_version(): + '''Return version string for display to user ''' + if git_version is not None: + v = git_version + else: + v = __version__ + if numeric_version[-1] == 0: + v = v[:-2] + if is_running_from_develop: + v += '*' + if iswindows and is64bit: + v += ' [64bit]' + + return v + + +def get_portable_base(): + 'Return path to the directory that contains calibre-portable.exe or None' + if isportable: + return os.path.dirname(os.path.dirname(getenv('CALIBRE_PORTABLE_BUILD'))) + + +def get_windows_username(): + ''' + Return the user name of the currently logged in user as a unicode string. + Note that usernames on windows are case insensitive, the case of the value + returned depends on what the user typed into the login box at login time. + ''' + username = plugins['winutil'][0].username + return username() + + +def get_windows_temp_path(): + temp_path = plugins['winutil'][0].temp_path + return temp_path() + + +def get_windows_user_locale_name(): + locale_name = plugins['winutil'][0].locale_name + return locale_name() + + +def get_windows_number_formats(): + ans = getattr(get_windows_number_formats, 'ans', None) + if ans is None: + localeconv = plugins['winutil'][0].localeconv + d = localeconv() + thousands_sep, decimal_point = d['thousands_sep'], d['decimal_point'] + ans = get_windows_number_formats.ans = thousands_sep, decimal_point + return ans diff --git a/ebook_converter/css_selectors/__init__.py b/ebook_converter/css_selectors/__init__.py new file mode 100644 index 0000000..24e1322 --- /dev/null +++ b/ebook_converter/css_selectors/__init__.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2015, Kovid Goyal ' + +from css_selectors.parser import parse +from css_selectors.select import Select, INAPPROPRIATE_PSEUDO_CLASSES +from css_selectors.errors import SelectorError, SelectorSyntaxError, ExpressionError + +__all__ = ['parse', 'Select', 'INAPPROPRIATE_PSEUDO_CLASSES', 'SelectorError', 'SelectorSyntaxError', 'ExpressionError'] diff --git a/ebook_converter/css_selectors/errors.py b/ebook_converter/css_selectors/errors.py new file mode 100644 index 0000000..070965c --- /dev/null +++ b/ebook_converter/css_selectors/errors.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2015, Kovid Goyal ' + +class SelectorError(ValueError): + + """Common parent for SelectorSyntaxError and ExpressionError""" + +class SelectorSyntaxError(SelectorError): + + """Parsing a selector that does not match the grammar.""" + +class ExpressionError(SelectorError): + + """Unknown or unsupported selector (eg. pseudo-class).""" diff --git a/ebook_converter/css_selectors/ordered_set.py b/ebook_converter/css_selectors/ordered_set.py new file mode 100644 index 0000000..448a4a7 --- /dev/null +++ b/ebook_converter/css_selectors/ordered_set.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2015, Kovid Goyal ' + +import collections +from polyglot.builtins import string_or_bytes + +SLICE_ALL = slice(None) + + +def is_iterable(obj): + """ + Are we being asked to look up a list of things, instead of a single thing? + We check for the `__iter__` attribute so that this can cover types that + don't have to be known by this module, such as NumPy arrays. + + Strings, however, should be considered as atomic values to look up, not + iterables. + """ + return hasattr(obj, '__iter__') and not isinstance(obj, string_or_bytes) + + +class OrderedSet(collections.MutableSet): + """ + An OrderedSet is a custom MutableSet that remembers its order, so that + every entry has an index that can be looked up. + """ + def __init__(self, iterable=None): + self.items = [] + self.map = {} + if iterable is not None: + for item in iterable: + idx = self.map.get(item) + if idx is None: + self.map[item] = len(self.items) + self.items.append(item) + + def __len__(self): + return len(self.items) + + def __getitem__(self, index): + """ + Get the item at a given index. + + If `index` is a slice, you will get back that slice of items. If it's + the slice [:], exactly the same object is returned. (If you want an + independent copy of an OrderedSet, use `OrderedSet.copy()`.) + + If `index` is an iterable, you'll get the OrderedSet of items + corresponding to those indices. This is similar to NumPy's + "fancy indexing". + """ + if index == SLICE_ALL: + return self + elif hasattr(index, '__index__') or isinstance(index, slice): + result = self.items[index] + if isinstance(result, list): + return OrderedSet(result) + else: + return result + elif is_iterable(index): + return OrderedSet([self.items[i] for i in index]) + else: + raise TypeError("Don't know how to index an OrderedSet by %r" % + index) + + def copy(self): + return OrderedSet(self) + + def __getstate__(self): + return tuple(self) + + def __setstate__(self, state): + self.__init__(state) + + def __contains__(self, key): + return key in self.map + + def add(self, key): + """ + Add `key` as an item to this OrderedSet, then return its index. + + If `key` is already in the OrderedSet, return the index it already + had. + """ + index = self.map.get(key) + if index is None: + self.map[key] = index = len(self.items) + self.items.append(key) + return index + + def index(self, key): + """ + Get the index of a given entry, raising an IndexError if it's not + present. + + `key` can be an iterable of entries that is not a string, in which case + this returns a list of indices. + """ + if is_iterable(key): + return [self.index(subkey) for subkey in key] + return self.map[key] + + def discard(self, key): + index = self.map.get(key) + if index is not None: + self.items.pop(index) + for item in self.items[index:]: + self.map[item] -= 1 + return True + return False + + def __iter__(self): + return iter(self.items) + + def __reversed__(self): + return reversed(self.items) + + def __repr__(self): + if not self: + return '%s()' % (self.__class__.__name__,) + return '%s(%r)' % (self.__class__.__name__, list(self)) + + def __eq__(self, other): + if isinstance(other, OrderedSet): + return len(self) == len(other) and self.items == other.items + try: + return type(other)(self.map) == other + except TypeError: + return False diff --git a/ebook_converter/css_selectors/parser.py b/ebook_converter/css_selectors/parser.py new file mode 100644 index 0000000..4ea3e11 --- /dev/null +++ b/ebook_converter/css_selectors/parser.py @@ -0,0 +1,791 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +""" + Tokenizer, parser and parsed objects for CSS selectors. + + :copyright: (c) 2007-2012 Ian Bicking and contributors. + See AUTHORS for more details. + :license: BSD, see LICENSE for more details. + +""" + +import sys +import re +import operator +import string + +from css_selectors.errors import SelectorSyntaxError, ExpressionError +from polyglot.builtins import unicode_type, codepoint_to_chr, range + + +utab = {c:c+32 for c in range(ord(u'A'), ord(u'Z')+1)} + +if sys.version_info.major < 3: + tab = string.maketrans(string.ascii_uppercase, string.ascii_lowercase) + + def ascii_lower(string): + """Lower-case, but only in the ASCII range.""" + return string.translate(utab if isinstance(string, unicode_type) else tab) + + def urepr(x): + if isinstance(x, list): + return '[%s]' % ', '.join((map(urepr, x))) + ans = repr(x) + if ans.startswith("u'") or ans.startswith('u"'): + ans = ans[1:] + return ans + + +else: + + def ascii_lower(x): + return x.translate(utab) + + urepr = repr + + +# Parsed objects + +class Selector(object): + + """ + Represents a parsed selector. + """ + + def __init__(self, tree, pseudo_element=None): + self.parsed_tree = tree + if pseudo_element is not None and not isinstance( + pseudo_element, FunctionalPseudoElement): + pseudo_element = ascii_lower(pseudo_element) + #: A :class:`FunctionalPseudoElement`, + #: or the identifier for the pseudo-element as a string, + # or ``None``. + #: + #: +-------------------------+----------------+--------------------------------+ + #: | | Selector | Pseudo-element | + #: +=========================+================+================================+ + #: | CSS3 syntax | ``a::before`` | ``'before'`` | + #: +-------------------------+----------------+--------------------------------+ + #: | Older syntax | ``a:before`` | ``'before'`` | + #: +-------------------------+----------------+--------------------------------+ + #: | From the Lists3_ draft, | ``li::marker`` | ``'marker'`` | + #: | not in Selectors3 | | | + #: +-------------------------+----------------+--------------------------------+ + #: | Invalid pseudo-class | ``li:marker`` | ``None`` | + #: +-------------------------+----------------+--------------------------------+ + #: | Functinal | ``a::foo(2)`` | ``FunctionalPseudoElement(…)`` | + #: +-------------------------+----------------+--------------------------------+ + #: + # : .. _Lists3: http://www.w3.org/TR/2011/WD-css3-lists-20110524/#marker-pseudoelement + self.pseudo_element = pseudo_element + + def __repr__(self): + if isinstance(self.pseudo_element, FunctionalPseudoElement): + pseudo_element = repr(self.pseudo_element) + if self.pseudo_element: + pseudo_element = '::%s' % self.pseudo_element + else: + pseudo_element = '' + return '%s[%r%s]' % ( + self.__class__.__name__, self.parsed_tree, pseudo_element) + + def specificity(self): + """Return the specificity_ of this selector as a tuple of 3 integers. + + .. _specificity: http://www.w3.org/TR/selectors/#specificity + + """ + a, b, c = self.parsed_tree.specificity() + if self.pseudo_element: + c += 1 + return a, b, c + + +class Class(object): + + """ + Represents selector.class_name + """ + def __init__(self, selector, class_name): + self.selector = selector + self.class_name = class_name + + def __repr__(self): + return '%s[%r.%s]' % ( + self.__class__.__name__, self.selector, self.class_name) + + def specificity(self): + a, b, c = self.selector.specificity() + b += 1 + return a, b, c + + +class FunctionalPseudoElement(object): + + """ + Represents selector::name(arguments) + + .. attribute:: name + + The name (identifier) of the pseudo-element, as a string. + + .. attribute:: arguments + + The arguments of the pseudo-element, as a list of tokens. + + **Note:** tokens are not part of the public API, + and may change between versions. + Use at your own risks. + + """ + def __init__(self, name, arguments): + self.name = ascii_lower(name) + self.arguments = arguments + + def __repr__(self): + return '%s[::%s(%s)]' % ( + self.__class__.__name__, self.name, + urepr([token.value for token in self.arguments])) + + def argument_types(self): + return [token.type for token in self.arguments] + + def specificity(self): + a, b, c = self.selector.specificity() + b += 1 + return a, b, c + + +class Function(object): + + """ + Represents selector:name(expr) + """ + def __init__(self, selector, name, arguments): + self.selector = selector + self.name = ascii_lower(name) + self.arguments = arguments + self._parsed_arguments = None + + def __repr__(self): + return '%s[%r:%s(%s)]' % ( + self.__class__.__name__, self.selector, self.name, + urepr([token.value for token in self.arguments])) + + def argument_types(self): + return [token.type for token in self.arguments] + + @property + def parsed_arguments(self): + if self._parsed_arguments is None: + try: + self._parsed_arguments = parse_series(self.arguments) + except ValueError: + raise ExpressionError("Invalid series: '%r'" % self.arguments) + return self._parsed_arguments + + def parse_arguments(self): + if not self.arguments_parsed: + self.arguments_parsed = True + + def specificity(self): + a, b, c = self.selector.specificity() + b += 1 + return a, b, c + + +class Pseudo(object): + + """ + Represents selector:ident + """ + def __init__(self, selector, ident): + self.selector = selector + self.ident = ascii_lower(ident) + + def __repr__(self): + return '%s[%r:%s]' % ( + self.__class__.__name__, self.selector, self.ident) + + def specificity(self): + a, b, c = self.selector.specificity() + b += 1 + return a, b, c + + +class Negation(object): + + """ + Represents selector:not(subselector) + """ + def __init__(self, selector, subselector): + self.selector = selector + self.subselector = subselector + + def __repr__(self): + return '%s[%r:not(%r)]' % ( + self.__class__.__name__, self.selector, self.subselector) + + def specificity(self): + a1, b1, c1 = self.selector.specificity() + a2, b2, c2 = self.subselector.specificity() + return a1 + a2, b1 + b2, c1 + c2 + + +class Attrib(object): + + """ + Represents selector[namespace|attrib operator value] + """ + def __init__(self, selector, namespace, attrib, operator, value): + self.selector = selector + self.namespace = namespace + self.attrib = attrib + self.operator = operator + self.value = value + + def __repr__(self): + if self.namespace: + attrib = '%s|%s' % (self.namespace, self.attrib) + else: + attrib = self.attrib + if self.operator == 'exists': + return '%s[%r[%s]]' % ( + self.__class__.__name__, self.selector, attrib) + else: + return '%s[%r[%s %s %s]]' % ( + self.__class__.__name__, self.selector, attrib, + self.operator, urepr(self.value)) + + def specificity(self): + a, b, c = self.selector.specificity() + b += 1 + return a, b, c + + +class Element(object): + + """ + Represents namespace|element + + `None` is for the universal selector '*' + + """ + def __init__(self, namespace=None, element=None): + self.namespace = namespace + self.element = element + + def __repr__(self): + element = self.element or '*' + if self.namespace: + element = '%s|%s' % (self.namespace, element) + return '%s[%s]' % (self.__class__.__name__, element) + + def specificity(self): + if self.element: + return 0, 0, 1 + else: + return 0, 0, 0 + + +class Hash(object): + + """ + Represents selector#id + """ + def __init__(self, selector, id): + self.selector = selector + self.id = id + + def __repr__(self): + return '%s[%r#%s]' % ( + self.__class__.__name__, self.selector, self.id) + + def specificity(self): + a, b, c = self.selector.specificity() + a += 1 + return a, b, c + + +class CombinedSelector(object): + + def __init__(self, selector, combinator, subselector): + assert selector is not None + self.selector = selector + self.combinator = combinator + self.subselector = subselector + + def __repr__(self): + if self.combinator == ' ': + comb = '' + else: + comb = self.combinator + return '%s[%r %s %r]' % ( + self.__class__.__name__, self.selector, comb, self.subselector) + + def specificity(self): + a1, b1, c1 = self.selector.specificity() + a2, b2, c2 = self.subselector.specificity() + return a1 + a2, b1 + b2, c1 + c2 + + +# Parser + +# foo +_el_re = re.compile(r'^[ \t\r\n\f]*([a-zA-Z]+)[ \t\r\n\f]*$') + +# foo#bar or #bar +_id_re = re.compile(r'^[ \t\r\n\f]*([a-zA-Z]*)#([a-zA-Z0-9_-]+)[ \t\r\n\f]*$') + +# foo.bar or .bar +_class_re = re.compile( + r'^[ \t\r\n\f]*([a-zA-Z]*)\.([a-zA-Z][a-zA-Z0-9_-]*)[ \t\r\n\f]*$') + + +def parse(css): + """Parse a CSS *group of selectors*. + + :param css: + A *group of selectors* as an Unicode string. + :raises: + :class:`SelectorSyntaxError` on invalid selectors. + :returns: + A list of parsed :class:`Selector` objects, one for each + selector in the comma-separated group. + + """ + # Fast path for simple cases + match = _el_re.match(css) + if match: + return [Selector(Element(element=match.group(1)))] + match = _id_re.match(css) + if match is not None: + return [Selector(Hash(Element(element=match.group(1) or None), + match.group(2)))] + match = _class_re.match(css) + if match is not None: + return [Selector(Class(Element(element=match.group(1) or None), + match.group(2)))] + + stream = TokenStream(tokenize(css)) + stream.source = css + return list(parse_selector_group(stream)) +# except SelectorSyntaxError: +# e = sys.exc_info()[1] +# message = "%s at %s -> %r" % ( +# e, stream.used, stream.peek()) +# e.msg = message +# e.args = tuple([message]) +# raise + + +def parse_selector_group(stream): + stream.skip_whitespace() + while 1: + yield Selector(*parse_selector(stream)) + if stream.peek() == ('DELIM', ','): + stream.next() + stream.skip_whitespace() + else: + break + + +def parse_selector(stream): + result, pseudo_element = parse_simple_selector(stream) + while 1: + stream.skip_whitespace() + peek = stream.peek() + if peek in (('EOF', None), ('DELIM', ',')): + break + if pseudo_element: + raise SelectorSyntaxError( + 'Got pseudo-element ::%s not at the end of a selector' + % pseudo_element) + if peek.is_delim('+', '>', '~'): + # A combinator + combinator = stream.next().value + stream.skip_whitespace() + else: + # By exclusion, the last parse_simple_selector() ended + # at peek == ' ' + combinator = ' ' + next_selector, pseudo_element = parse_simple_selector(stream) + result = CombinedSelector(result, combinator, next_selector) + return result, pseudo_element + + +special_pseudo_elements = ( + 'first-line', 'first-letter', 'before', 'after') + + +def parse_simple_selector(stream, inside_negation=False): + stream.skip_whitespace() + selector_start = len(stream.used) + peek = stream.peek() + if peek.type == 'IDENT' or peek == ('DELIM', '*'): + if peek.type == 'IDENT': + namespace = stream.next().value + else: + stream.next() + namespace = None + if stream.peek() == ('DELIM', '|'): + stream.next() + element = stream.next_ident_or_star() + else: + element = namespace + namespace = None + else: + element = namespace = None + result = Element(namespace, element) + pseudo_element = None + while 1: + peek = stream.peek() + if peek.type in ('S', 'EOF') or peek.is_delim(',', '+', '>', '~') or ( + inside_negation and peek == ('DELIM', ')')): + break + if pseudo_element: + raise SelectorSyntaxError( + 'Got pseudo-element ::%s not at the end of a selector' + % pseudo_element) + if peek.type == 'HASH': + result = Hash(result, stream.next().value) + elif peek == ('DELIM', '.'): + stream.next() + result = Class(result, stream.next_ident()) + elif peek == ('DELIM', '['): + stream.next() + result = parse_attrib(result, stream) + elif peek == ('DELIM', ':'): + stream.next() + if stream.peek() == ('DELIM', ':'): + stream.next() + pseudo_element = stream.next_ident() + if stream.peek() == ('DELIM', '('): + stream.next() + pseudo_element = FunctionalPseudoElement( + pseudo_element, parse_arguments(stream)) + continue + ident = stream.next_ident() + if ident.lower() in special_pseudo_elements: + # Special case: CSS 2.1 pseudo-elements can have a single ':' + # Any new pseudo-element must have two. + pseudo_element = unicode_type(ident) + continue + if stream.peek() != ('DELIM', '('): + result = Pseudo(result, ident) + continue + stream.next() + stream.skip_whitespace() + if ident.lower() == 'not': + if inside_negation: + raise SelectorSyntaxError('Got nested :not()') + argument, argument_pseudo_element = parse_simple_selector( + stream, inside_negation=True) + next = stream.next() + if argument_pseudo_element: + raise SelectorSyntaxError( + 'Got pseudo-element ::%s inside :not() at %s' + % (argument_pseudo_element, next.pos)) + if next != ('DELIM', ')'): + raise SelectorSyntaxError("Expected ')', got %s" % (next,)) + result = Negation(result, argument) + else: + result = Function(result, ident, parse_arguments(stream)) + else: + raise SelectorSyntaxError( + "Expected selector, got %s" % (peek,)) + if len(stream.used) == selector_start: + raise SelectorSyntaxError( + "Expected selector, got %s" % (stream.peek(),)) + return result, pseudo_element + + +def parse_arguments(stream): + arguments = [] + while 1: + stream.skip_whitespace() + next = stream.next() + if next.type in ('IDENT', 'STRING', 'NUMBER') or next in [ + ('DELIM', '+'), ('DELIM', '-')]: + arguments.append(next) + elif next == ('DELIM', ')'): + return arguments + else: + raise SelectorSyntaxError( + "Expected an argument, got %s" % (next,)) + + +def parse_attrib(selector, stream): + stream.skip_whitespace() + attrib = stream.next_ident_or_star() + if attrib is None and stream.peek() != ('DELIM', '|'): + raise SelectorSyntaxError( + "Expected '|', got %s" % (stream.peek(),)) + if stream.peek() == ('DELIM', '|'): + stream.next() + if stream.peek() == ('DELIM', '='): + namespace = None + stream.next() + op = '|=' + else: + namespace = attrib + attrib = stream.next_ident() + op = None + else: + namespace = op = None + if op is None: + stream.skip_whitespace() + next = stream.next() + if next == ('DELIM', ']'): + return Attrib(selector, namespace, attrib, 'exists', None) + elif next == ('DELIM', '='): + op = '=' + elif next.is_delim('^', '$', '*', '~', '|', '!') and ( + stream.peek() == ('DELIM', '=')): + op = next.value + '=' + stream.next() + else: + raise SelectorSyntaxError( + "Operator expected, got %s" % (next,)) + stream.skip_whitespace() + value = stream.next() + if value.type not in ('IDENT', 'STRING'): + raise SelectorSyntaxError( + "Expected string or ident, got %s" % (value,)) + stream.skip_whitespace() + next = stream.next() + if next != ('DELIM', ']'): + raise SelectorSyntaxError( + "Expected ']', got %s" % (next,)) + return Attrib(selector, namespace, attrib, op, value.value) + + +def parse_series(tokens): + """ + Parses the arguments for :nth-child() and friends. + + :raises: A list of tokens + :returns: :``(a, b)`` + + """ + for token in tokens: + if token.type == 'STRING': + raise ValueError('String tokens not allowed in series.') + s = ''.join(token.value for token in tokens).strip() + if s == 'odd': + return (2, 1) + elif s == 'even': + return (2, 0) + elif s == 'n': + return (1, 0) + if 'n' not in s: + # Just b + return (0, int(s)) + a, b = s.split('n', 1) + if not a: + a = 1 + elif a == '-' or a == '+': + a = int(a+'1') + else: + a = int(a) + if not b: + b = 0 + else: + b = int(b) + return (a, b) + + +# Token objects + +class Token(tuple): + + def __new__(cls, type_, value, pos): + obj = tuple.__new__(cls, (type_, value)) + obj.pos = pos + return obj + + def __repr__(self): + return "<%s '%s' at %i>" % (self.type, self.value, self.pos) + + def is_delim(self, *values): + return self.type == 'DELIM' and self.value in values + + type = property(operator.itemgetter(0)) + value = property(operator.itemgetter(1)) + + +class EOFToken(Token): + + def __new__(cls, pos): + return Token.__new__(cls, 'EOF', None, pos) + + def __repr__(self): + return '<%s at %i>' % (self.type, self.pos) + + +# Tokenizer + + +class TokenMacros: + unicode_escape = r'\\([0-9a-f]{1,6})(?:\r\n|[ \n\r\t\f])?' + escape = unicode_escape + r'|\\[^\n\r\f0-9a-f]' + string_escape = r'\\(?:\n|\r\n|\r|\f)|' + escape + nonascii = r'[^\0-\177]' + nmchar = '[_a-z0-9-]|%s|%s' % (escape, nonascii) + nmstart = '[_a-z]|%s|%s' % (escape, nonascii) + + +def _compile(pattern): + return re.compile(pattern % vars(TokenMacros), re.IGNORECASE).match + + +_match_whitespace = _compile(r'[ \t\r\n\f]+') +_match_number = _compile(r'[+-]?(?:[0-9]*\.[0-9]+|[0-9]+)') +_match_hash = _compile('#(?:%(nmchar)s)+') +_match_ident = _compile('-?(?:%(nmstart)s)(?:%(nmchar)s)*') +_match_string_by_quote = { + "'": _compile(r"([^\n\r\f\\']|%(string_escape)s)*"), + '"': _compile(r'([^\n\r\f\\"]|%(string_escape)s)*'), +} + +_sub_simple_escape = re.compile(r'\\(.)').sub +_sub_unicode_escape = re.compile(TokenMacros.unicode_escape, re.I).sub +_sub_newline_escape =re.compile(r'\\(?:\n|\r\n|\r|\f)').sub + +# Same as r'\1', but faster on CPython +if hasattr(operator, 'methodcaller'): + # Python 2.6+ + _replace_simple = operator.methodcaller('group', 1) +else: + def _replace_simple(match): + return match.group(1) + + +def _replace_unicode(match): + codepoint = int(match.group(1), 16) + if codepoint > sys.maxunicode: + codepoint = 0xFFFD + return codepoint_to_chr(codepoint) + + +def unescape_ident(value): + value = _sub_unicode_escape(_replace_unicode, value) + value = _sub_simple_escape(_replace_simple, value) + return value + + +def tokenize(s): + pos = 0 + len_s = len(s) + while pos < len_s: + match = _match_whitespace(s, pos=pos) + if match: + yield Token('S', ' ', pos) + pos = match.end() + continue + + match = _match_ident(s, pos=pos) + if match: + value = _sub_simple_escape(_replace_simple, + _sub_unicode_escape(_replace_unicode, match.group())) + yield Token('IDENT', value, pos) + pos = match.end() + continue + + match = _match_hash(s, pos=pos) + if match: + value = _sub_simple_escape(_replace_simple, + _sub_unicode_escape(_replace_unicode, match.group()[1:])) + yield Token('HASH', value, pos) + pos = match.end() + continue + + quote = s[pos] + if quote in _match_string_by_quote: + match = _match_string_by_quote[quote](s, pos=pos + 1) + assert match, 'Should have found at least an empty match' + end_pos = match.end() + if end_pos == len_s: + raise SelectorSyntaxError('Unclosed string at %s' % pos) + if s[end_pos] != quote: + raise SelectorSyntaxError('Invalid string at %s' % pos) + value = _sub_simple_escape(_replace_simple, + _sub_unicode_escape(_replace_unicode, + _sub_newline_escape('', match.group()))) + yield Token('STRING', value, pos) + pos = end_pos + 1 + continue + + match = _match_number(s, pos=pos) + if match: + value = match.group() + yield Token('NUMBER', value, pos) + pos = match.end() + continue + + pos2 = pos + 2 + if s[pos:pos2] == '/*': + pos = s.find('*/', pos2) + if pos == -1: + pos = len_s + else: + pos += 2 + continue + + yield Token('DELIM', s[pos], pos) + pos += 1 + + assert pos == len_s + yield EOFToken(pos) + + +class TokenStream(object): + + def __init__(self, tokens, source=None): + self.used = [] + self.tokens = iter(tokens) + self.source = source + self.peeked = None + self._peeking = False + try: + self.next_token = self.tokens.next + except AttributeError: + # Python 3 + self.next_token = self.tokens.__next__ + + def next(self): + if self._peeking: + self._peeking = False + self.used.append(self.peeked) + return self.peeked + else: + next = self.next_token() + self.used.append(next) + return next + + def peek(self): + if not self._peeking: + self.peeked = self.next_token() + self._peeking = True + return self.peeked + + def next_ident(self): + next = self.next() + if next.type != 'IDENT': + raise SelectorSyntaxError('Expected ident, got %s' % (next,)) + return next.value + + def next_ident_or_star(self): + next = self.next() + if next.type == 'IDENT': + return next.value + elif next == ('DELIM', '*'): + return None + else: + raise SelectorSyntaxError( + "Expected ident or '*', got %s" % (next,)) + + def skip_whitespace(self): + peek = self.peek() + if peek.type == 'S': + self.next() diff --git a/ebook_converter/css_selectors/select.py b/ebook_converter/css_selectors/select.py new file mode 100644 index 0000000..b6e2a18 --- /dev/null +++ b/ebook_converter/css_selectors/select.py @@ -0,0 +1,694 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2015, Kovid Goyal ' + +import re, itertools +from collections import OrderedDict, defaultdict +from functools import wraps +from itertools import chain + +from lxml import etree + +from css_selectors.errors import ExpressionError +from css_selectors.parser import parse, ascii_lower, Element, FunctionalPseudoElement +from css_selectors.ordered_set import OrderedSet + +from polyglot.builtins import iteritems, itervalues + +PARSE_CACHE_SIZE = 200 +parse_cache = OrderedDict() +XPATH_CACHE_SIZE = 30 +xpath_cache = OrderedDict() + +# Test that the string is not empty and does not contain whitespace +is_non_whitespace = re.compile(r'^[^ \t\r\n\f]+$').match + + +def get_parsed_selector(raw): + try: + return parse_cache[raw] + except KeyError: + parse_cache[raw] = ans = parse(raw) + if len(parse_cache) > PARSE_CACHE_SIZE: + parse_cache.pop(next(iter(parse_cache))) + return ans + + +def get_compiled_xpath(expr): + try: + return xpath_cache[expr] + except KeyError: + xpath_cache[expr] = ans = etree.XPath(expr) + if len(xpath_cache) > XPATH_CACHE_SIZE: + xpath_cache.pop(next(iter(xpath_cache))) + return ans + + +class AlwaysIn(object): + + def __contains__(self, x): + return True + + +always_in = AlwaysIn() + + +def trace_wrapper(func): + @wraps(func) + def trace(*args, **kwargs): + targs = args[1:] if args and isinstance(args[0], Select) else args + print('Called:', func.__name__, 'with args:', targs, kwargs or '') + return func(*args, **kwargs) + return trace + + +def normalize_language_tag(tag): + """Return a list of normalized combinations for a `BCP 47` language tag. + + Example: + + >>> normalize_language_tag('de_AT-1901') + ['de-at-1901', 'de-at', 'de-1901', 'de'] + """ + # normalize: + tag = ascii_lower(tag).replace('_','-') + # split (except singletons, which mark the following tag as non-standard): + tag = re.sub(r'-([a-zA-Z0-9])-', r'-\1_', tag) + subtags = [subtag.replace('_', '-') for subtag in tag.split('-')] + base_tag = (subtags.pop(0),) + taglist = {base_tag[0]} + # find all combinations of subtags + for n in range(len(subtags), 0, -1): + for tags in itertools.combinations(subtags, n): + taglist.add('-'.join(base_tag + tags)) + return taglist + + +INAPPROPRIATE_PSEUDO_CLASSES = frozenset(( + 'active', 'after', 'disabled', 'visited', 'link', 'before', 'focus', 'first-letter', 'enabled', 'first-line', 'hover', 'checked', 'target')) + + +class Select(object): + + ''' + + This class implements CSS Level 3 selectors + (http://www.w3.org/TR/css3-selectors) on an lxml tree, with caching for + performance. To use: + + >>> from css_selectors import Select + >>> select = Select(root) # Where root is an lxml document + >>> print(tuple(select('p.myclass'))) + + Tags are returned in document order. Note that attribute and tag names are + matched case-insensitively. Class and id values are also matched + case-insensitively. Also namespaces are ignored (this is for performance of + the common case). The UI related selectors are not implemented, such as + :enabled, :disabled, :checked, :hover, etc. Similarly, the non-element + related selectors such as ::first-line, ::first-letter, ::before, etc. are + not implemented. + + WARNING: This class uses internal caches. You *must not* make any changes + to the lxml tree. If you do make some changes, either create a new Select + object or call :meth:`invalidate_caches`. + + This class can be easily sub-classed to work with tree implementations + other than lxml. Simply override the methods in the ``Tree Integration`` + block below. + + The caching works by maintaining internal maps from classes/ids/tag + names/etc. to node sets. These caches are populated as needed, and used + for all subsequent selections. Thus, for best performance you should use + the same selector object for finding the matching nodes for multiple + queries. Of course, remember not to change the tree in between queries. + + ''' + + combinator_mapping = { + ' ': 'descendant', + '>': 'child', + '+': 'direct_adjacent', + '~': 'indirect_adjacent', + } + + attribute_operator_mapping = { + 'exists': 'exists', + '=': 'equals', + '~=': 'includes', + '|=': 'dashmatch', + '^=': 'prefixmatch', + '$=': 'suffixmatch', + '*=': 'substringmatch', + } + + def __init__(self, root, default_lang=None, ignore_inappropriate_pseudo_classes=False, dispatch_map=None, trace=False): + if hasattr(root, 'getroot'): + root = root.getroot() + self.root = root + self.dispatch_map = dispatch_map or default_dispatch_map + self.invalidate_caches() + self.default_lang = default_lang + if trace: + self.dispatch_map = {k:trace_wrapper(v) for k, v in iteritems(self.dispatch_map)} + if ignore_inappropriate_pseudo_classes: + self.ignore_inappropriate_pseudo_classes = INAPPROPRIATE_PSEUDO_CLASSES + else: + self.ignore_inappropriate_pseudo_classes = frozenset() + + # External API {{{ + def invalidate_caches(self): + 'Invalidate all caches. You must call this before using this object if you have made changes to the HTML tree' + self._element_map = None + self._id_map = None + self._class_map = None + self._attrib_map = None + self._attrib_space_map = None + self._lang_map = None + self.map_tag_name = ascii_lower + if '{' in self.root.tag: + def map_tag_name(x): + return ascii_lower(x.rpartition('}')[2]) + self.map_tag_name = map_tag_name + + def __call__(self, selector, root=None): + ''' Return an iterator over all matching tags, in document order. + Normally, all matching tags in the document are returned, is you + specify root, then only tags that are root or descendants of root are + returned. Note that this can be very expensive if root has a lot of + descendants. ''' + seen = set() + if root is not None: + root = frozenset(self.itertag(root)) + for parsed_selector in get_parsed_selector(selector): + for item in self.iterparsedselector(parsed_selector): + if item not in seen and (root is None or item in root): + yield item + seen.add(item) + + def has_matches(self, selector, root=None): + 'Return True iff selector matches at least one item in the tree' + for elem in self(selector, root=root): + return True + return False + # }}} + + def iterparsedselector(self, parsed_selector): + type_name = type(parsed_selector).__name__ + try: + func = self.dispatch_map[ascii_lower(type_name)] + except KeyError: + raise ExpressionError('%s is not supported' % type_name) + for item in func(self, parsed_selector): + yield item + + @property + def element_map(self): + if self._element_map is None: + self._element_map = em = defaultdict(OrderedSet) + for tag in self.itertag(): + em[self.map_tag_name(tag.tag)].add(tag) + return self._element_map + + @property + def id_map(self): + if self._id_map is None: + self._id_map = im = defaultdict(OrderedSet) + lower = ascii_lower + for elem in self.iteridtags(): + im[lower(elem.get('id'))].add(elem) + return self._id_map + + @property + def class_map(self): + if self._class_map is None: + self._class_map = cm = defaultdict(OrderedSet) + lower = ascii_lower + for elem in self.iterclasstags(): + for cls in elem.get('class').split(): + cm[lower(cls)].add(elem) + return self._class_map + + @property + def attrib_map(self): + if self._attrib_map is None: + self._attrib_map = am = defaultdict(lambda : defaultdict(OrderedSet)) + map_attrib_name = ascii_lower + if '{' in self.root.tag: + def map_attrib_name(x): + return ascii_lower(x.rpartition('}')[2]) + for tag in self.itertag(): + for attr, val in iteritems(tag.attrib): + am[map_attrib_name(attr)][val].add(tag) + return self._attrib_map + + @property + def attrib_space_map(self): + if self._attrib_space_map is None: + self._attrib_space_map = am = defaultdict(lambda : defaultdict(OrderedSet)) + map_attrib_name = ascii_lower + if '{' in self.root.tag: + def map_attrib_name(x): + return ascii_lower(x.rpartition('}')[2]) + for tag in self.itertag(): + for attr, val in iteritems(tag.attrib): + for v in val.split(): + am[map_attrib_name(attr)][v].add(tag) + return self._attrib_space_map + + @property + def lang_map(self): + if self._lang_map is None: + self._lang_map = lm = defaultdict(OrderedSet) + dl = normalize_language_tag(self.default_lang) if self.default_lang else None + lmap = {tag:dl for tag in self.itertag()} if dl else {} + for tag in self.itertag(): + lang = None + for attr in ('{http://www.w3.org/XML/1998/namespace}lang', 'lang'): + lang = tag.get(attr) + if lang: + lang = normalize_language_tag(lang) + for dtag in self.itertag(tag): + lmap[dtag] = lang + for tag, langs in iteritems(lmap): + for lang in langs: + lm[lang].add(tag) + return self._lang_map + + # Tree Integration {{{ + def itertag(self, tag=None): + return (self.root if tag is None else tag).iter('*') + + def iterdescendants(self, tag=None): + return (self.root if tag is None else tag).iterdescendants('*') + + def iterchildren(self, tag=None): + return (self.root if tag is None else tag).iterchildren('*') + + def itersiblings(self, tag=None, preceding=False): + return (self.root if tag is None else tag).itersiblings('*', preceding=preceding) + + def iteridtags(self): + return get_compiled_xpath('//*[@id]')(self.root) + + def iterclasstags(self): + return get_compiled_xpath('//*[@class]')(self.root) + + def sibling_count(self, child, before=True, same_type=False): + ' Return the number of siblings before or after child or raise ValueError if child has no parent. ' + parent = child.getparent() + if parent is None: + raise ValueError('Child has no parent') + if same_type: + siblings = OrderedSet(child.itersiblings(preceding=before)) + return len(self.element_map[self.map_tag_name(child.tag)] & siblings) + else: + if before: + return parent.index(child) + return len(parent) - parent.index(child) - 1 + + def all_sibling_count(self, child, same_type=False): + ' Return the number of siblings of child or raise ValueError if child has no parent ' + parent = child.getparent() + if parent is None: + raise ValueError('Child has no parent') + if same_type: + siblings = OrderedSet(chain(child.itersiblings(preceding=False), child.itersiblings(preceding=True))) + return len(self.element_map[self.map_tag_name(child.tag)] & siblings) + else: + return len(parent) - 1 + + def is_empty(self, elem): + ' Return True iff elem has no child tags and no text content ' + for child in elem: + # Check for comment/PI nodes with tail text + if child.tail: + return False + return len(tuple(elem.iterchildren('*'))) == 0 and not elem.text + + # }}} + +# Combinators {{{ + + +def select_combinedselector(cache, combined): + """Translate a combined selector.""" + combinator = cache.combinator_mapping[combined.combinator] + # Fast path for when the sub-selector is all elements + right = None if isinstance(combined.subselector, Element) and ( + combined.subselector.element or '*') == '*' else cache.iterparsedselector(combined.subselector) + for item in cache.dispatch_map[combinator](cache, cache.iterparsedselector(combined.selector), right): + yield item + + +def select_descendant(cache, left, right): + """right is a child, grand-child or further descendant of left""" + right = always_in if right is None else frozenset(right) + for ancestor in left: + for descendant in cache.iterdescendants(ancestor): + if descendant in right: + yield descendant + + +def select_child(cache, left, right): + """right is an immediate child of left""" + right = always_in if right is None else frozenset(right) + for parent in left: + for child in cache.iterchildren(parent): + if child in right: + yield child + + +def select_direct_adjacent(cache, left, right): + """right is a sibling immediately after left""" + right = always_in if right is None else frozenset(right) + for parent in left: + for sibling in cache.itersiblings(parent): + if sibling in right: + yield sibling + break + + +def select_indirect_adjacent(cache, left, right): + """right is a sibling after left, immediately or not""" + right = always_in if right is None else frozenset(right) + for parent in left: + for sibling in cache.itersiblings(parent): + if sibling in right: + yield sibling +# }}} + + +def select_element(cache, selector): + """A type or universal selector.""" + element = selector.element + if not element or element == '*': + for elem in cache.itertag(): + yield elem + else: + for elem in cache.element_map[ascii_lower(element)]: + yield elem + + +def select_hash(cache, selector): + 'An id selector' + items = cache.id_map[ascii_lower(selector.id)] + if len(items) > 0: + for elem in cache.iterparsedselector(selector.selector): + if elem in items: + yield elem + + +def select_class(cache, selector): + 'A class selector' + items = cache.class_map[ascii_lower(selector.class_name)] + if items: + for elem in cache.iterparsedselector(selector.selector): + if elem in items: + yield elem + + +def select_negation(cache, selector): + 'Implement :not()' + exclude = frozenset(cache.iterparsedselector(selector.subselector)) + for item in cache.iterparsedselector(selector.selector): + if item not in exclude: + yield item + +# Attribute selectors {{{ + + +def select_attrib(cache, selector): + operator = cache.attribute_operator_mapping[selector.operator] + items = frozenset(cache.dispatch_map[operator](cache, ascii_lower(selector.attrib), selector.value)) + for item in cache.iterparsedselector(selector.selector): + if item in items: + yield item + + +def select_exists(cache, attrib, value=None): + for elem_set in itervalues(cache.attrib_map[attrib]): + for elem in elem_set: + yield elem + + +def select_equals(cache, attrib, value): + for elem in cache.attrib_map[attrib][value]: + yield elem + + +def select_includes(cache, attrib, value): + if is_non_whitespace(value): + for elem in cache.attrib_space_map[attrib][value]: + yield elem + + +def select_dashmatch(cache, attrib, value): + if value: + for val, elem_set in iteritems(cache.attrib_map[attrib]): + if val == value or val.startswith(value + '-'): + for elem in elem_set: + yield elem + + +def select_prefixmatch(cache, attrib, value): + if value: + for val, elem_set in iteritems(cache.attrib_map[attrib]): + if val.startswith(value): + for elem in elem_set: + yield elem + + +def select_suffixmatch(cache, attrib, value): + if value: + for val, elem_set in iteritems(cache.attrib_map[attrib]): + if val.endswith(value): + for elem in elem_set: + yield elem + + +def select_substringmatch(cache, attrib, value): + if value: + for val, elem_set in iteritems(cache.attrib_map[attrib]): + if value in val: + for elem in elem_set: + yield elem + +# }}} + +# Function selectors {{{ + + +def select_function(cache, function): + """Select with a functional pseudo-class.""" + fname = function.name.replace('-', '_') + try: + func = cache.dispatch_map[fname] + except KeyError: + raise ExpressionError( + "The pseudo-class :%s() is unknown" % function.name) + if fname == 'lang': + items = frozenset(func(cache, function)) + for item in cache.iterparsedselector(function.selector): + if item in items: + yield item + else: + for item in cache.iterparsedselector(function.selector): + if func(cache, function, item): + yield item + + +def select_lang(cache, function): + ' Implement :lang() ' + if function.argument_types() not in (['STRING'], ['IDENT']): + raise ExpressionError("Expected a single string or ident for :lang(), got %r" % function.arguments) + lang = function.arguments[0].value + if lang: + lang = ascii_lower(lang) + lp = lang + '-' + for tlang, elem_set in iteritems(cache.lang_map): + if tlang == lang or (tlang is not None and tlang.startswith(lp)): + for elem in elem_set: + yield elem + + +def select_nth_child(cache, function, elem): + ' Implement :nth-child() ' + a, b = function.parsed_arguments + try: + num = cache.sibling_count(elem) + 1 + except ValueError: + return False + if a == 0: + return num == b + n = (num - b) / a + return n.is_integer() and n > -1 + + +def select_nth_last_child(cache, function, elem): + ' Implement :nth-last-child() ' + a, b = function.parsed_arguments + try: + num = cache.sibling_count(elem, before=False) + 1 + except ValueError: + return False + if a == 0: + return num == b + n = (num - b) / a + return n.is_integer() and n > -1 + + +def select_nth_of_type(cache, function, elem): + ' Implement :nth-of-type() ' + a, b = function.parsed_arguments + try: + num = cache.sibling_count(elem, same_type=True) + 1 + except ValueError: + return False + if a == 0: + return num == b + n = (num - b) / a + return n.is_integer() and n > -1 + + +def select_nth_last_of_type(cache, function, elem): + ' Implement :nth-last-of-type() ' + a, b = function.parsed_arguments + try: + num = cache.sibling_count(elem, before=False, same_type=True) + 1 + except ValueError: + return False + if a == 0: + return num == b + n = (num - b) / a + return n.is_integer() and n > -1 + +# }}} + +# Pseudo elements {{{ + + +def pseudo_func(f): + f.is_pseudo = True + return f + + +@pseudo_func +def allow_all(cache, item): + return True + + +def get_func_for_pseudo(cache, ident): + try: + func = cache.dispatch_map[ident.replace('-', '_')] + except KeyError: + if ident in cache.ignore_inappropriate_pseudo_classes: + func = allow_all + else: + raise ExpressionError( + "The pseudo-class :%s is not supported" % ident) + + try: + func.is_pseudo + except AttributeError: + raise ExpressionError( + "The pseudo-class :%s is invalid" % ident) + return func + + +def select_selector(cache, selector): + if selector.pseudo_element is None: + for item in cache.iterparsedselector(selector.parsed_tree): + yield item + return + if isinstance(selector.pseudo_element, FunctionalPseudoElement): + raise ExpressionError( + "The pseudo-element ::%s is not supported" % selector.pseudo_element.name) + func = get_func_for_pseudo(cache, selector.pseudo_element) + for item in cache.iterparsedselector(selector.parsed_tree): + if func(cache, item): + yield item + + +def select_pseudo(cache, pseudo): + func = get_func_for_pseudo(cache, pseudo.ident) + if func is select_root: + yield cache.root + return + + for item in cache.iterparsedselector(pseudo.selector): + if func(cache, item): + yield item + + +@pseudo_func +def select_root(cache, elem): + return elem is cache.root + + +@pseudo_func +def select_first_child(cache, elem): + try: + return cache.sibling_count(elem) == 0 + except ValueError: + return False + + +@pseudo_func +def select_last_child(cache, elem): + try: + return cache.sibling_count(elem, before=False) == 0 + except ValueError: + return False + + +@pseudo_func +def select_only_child(cache, elem): + try: + return cache.all_sibling_count(elem) == 0 + except ValueError: + return False + + +@pseudo_func +def select_first_of_type(cache, elem): + try: + return cache.sibling_count(elem, same_type=True) == 0 + except ValueError: + return False + + +@pseudo_func +def select_last_of_type(cache, elem): + try: + return cache.sibling_count(elem, before=False, same_type=True) == 0 + except ValueError: + return False + + +@pseudo_func +def select_only_of_type(cache, elem): + try: + return cache.all_sibling_count(elem, same_type=True) == 0 + except ValueError: + return False + + +@pseudo_func +def select_empty(cache, elem): + return cache.is_empty(elem) + + +# }}} + +default_dispatch_map = {name.partition('_')[2]:obj for name, obj in globals().items() if name.startswith('select_') and callable(obj)} + +if __name__ == '__main__': + from pprint import pprint + root = etree.fromstring( + '

', + parser=etree.XMLParser(recover=True, no_network=True, resolve_entities=False)) + select = Select(root, ignore_inappropriate_pseudo_classes=True, trace=True) + pprint(list(select('p:disabled'))) diff --git a/ebook_converter/css_selectors/tests.py b/ebook_converter/css_selectors/tests.py new file mode 100644 index 0000000..0176f1d --- /dev/null +++ b/ebook_converter/css_selectors/tests.py @@ -0,0 +1,843 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2015, Kovid Goyal ' + +import unittest, sys, argparse + +from lxml import etree, html + +from css_selectors.errors import SelectorSyntaxError, ExpressionError +from css_selectors.parser import tokenize, parse +from css_selectors.select import Select + + +class TestCSSSelectors(unittest.TestCase): + + # Test data {{{ + HTML_IDS = ''' + + + + +
+ + + + link +
    +
  1. content
  2. +
  3. +
    +
    +
  4. +
  5. +
  6. +
  7. +
  8. +
  9. +
+

+ hi there + guy + + + + + + + +

+ + +
+

+
    +
+ + + + +
+
+ +''' + HTML_SHAKESPEARE = ''' + + + + + + +
+
+

As You Like It

+
+by William Shakespeare +
+
+

ACT I, SCENE III. A room in the palace.

+
+
Enter CELIA and ROSALIND
+
+
CELIA
+
+
Why, cousin! why, Rosalind! Cupid have mercy! not a word?
+
+
ROSALIND
+
+
Not one to throw at a dog.
+
+
CELIA
+
+
No, thy words are too precious to be cast away upon
+
curs; throw some of them at me; come, lame me with reasons.
+
+
ROSALIND
+
CELIA
+
+
But is all this for your father?
+
+
+
Then there were two cousins laid up; when the one
+
should be lamed with reasons and the other mad
+
without any.
+
+
ROSALIND
+
+
No, some of it is for my child's father. O, how
+
full of briers is this working-day world!
+
+
CELIA
+
+
They are but burs, cousin, thrown upon thee in
+
holiday foolery: if we walk not in the trodden
+
paths our very petticoats will catch them.
+
+
ROSALIND
+
+
I could shake them off my coat: these burs are in my heart.
+
+
CELIA
+
+
Hem them away.
+
+
ROSALIND
+
+
I would try, if I could cry 'hem' and have him.
+
+
CELIA
+
+
Come, come, wrestle with thy affections.
+
+
ROSALIND
+
+
O, they take the part of a better wrestler than myself!
+
+
CELIA
+
+
O, a good wish upon you! you will try in time, in
+
despite of a fall. But, turning these jests out of
+
service, let us talk in good earnest: is it
+
possible, on such a sudden, you should fall into so
+
strong a liking with old Sir Rowland's youngest son?
+
+
ROSALIND
+
+
The duke my father loved his father dearly.
+
+
CELIA
+
+
Doth it therefore ensue that you should love his son
+
dearly? By this kind of chase, I should hate him,
+
for my father hated his father dearly; yet I hate
+
not Orlando.
+
+
ROSALIND
+
+
No, faith, hate him not, for my sake.
+
+
CELIA
+
+
Why should I not? doth he not deserve well?
+
+
ROSALIND
+
+
Let me love him for that, and do you love him
+
because I do. Look, here comes the duke.
+
+
CELIA
+
+
With his eyes full of anger.
+
Enter DUKE FREDERICK, with Lords
+
+
DUKE FREDERICK
+
+
Mistress, dispatch you with your safest haste
+
And get you from our court.
+
+
ROSALIND
+
+
Me, uncle?
+
+
DUKE FREDERICK
+
+
You, cousin
+
Within these ten days if that thou be'st found
+
So near our public court as twenty miles,
+
Thou diest for it.
+
+
ROSALIND
+
+
I do beseech your grace,
+
Let me the knowledge of my fault bear with me:
+
If with myself I hold intelligence
+
Or have acquaintance with mine own desires,
+
If that I do not dream or be not frantic,--
+
As I do trust I am not--then, dear uncle,
+
Never so much as in a thought unborn
+
Did I offend your highness.
+
+
DUKE FREDERICK
+
+
Thus do all traitors:
+
If their purgation did consist in words,
+
They are as innocent as grace itself:
+
Let it suffice thee that I trust thee not.
+
+
ROSALIND
+
+
Yet your mistrust cannot make me a traitor:
+
Tell me whereon the likelihood depends.
+
+
DUKE FREDERICK
+
+
Thou art thy father's daughter; there's enough.
+
+
ROSALIND
+
+
So was I when your highness took his dukedom;
+
So was I when your highness banish'd him:
+
Treason is not inherited, my lord;
+
Or, if we did derive it from our friends,
+
What's that to me? my father was no traitor:
+
Then, good my liege, mistake me not so much
+
To think my poverty is treacherous.
+
+
CELIA
+
+
Dear sovereign, hear me speak.
+
+
DUKE FREDERICK
+
+
Ay, Celia; we stay'd her for your sake,
+
Else had she with her father ranged along.
+
+
CELIA
+
+
I did not then entreat to have her stay;
+
It was your pleasure and your own remorse:
+
I was too young that time to value her;
+
But now I know her: if she be a traitor,
+
Why so am I; we still have slept together,
+
Rose at an instant, learn'd, play'd, eat together,
+
And wheresoever we went, like Juno's swans,
+
Still we went coupled and inseparable.
+
+
DUKE FREDERICK
+
+
She is too subtle for thee; and her smoothness,
+
Her very silence and her patience
+
Speak to the people, and they pity her.
+
Thou art a fool: she robs thee of thy name;
+
And thou wilt show more bright and seem more virtuous
+
When she is gone. Then open not thy lips:
+
Firm and irrevocable is my doom
+
Which I have pass'd upon her; she is banish'd.
+
+
CELIA
+
+
Pronounce that sentence then on me, my liege:
+
I cannot live out of her company.
+
+
DUKE FREDERICK
+
+
You are a fool. You, niece, provide yourself:
+
If you outstay the time, upon mine honour,
+
And in the greatness of my word, you die.
+
Exeunt DUKE FREDERICK and Lords
+
+
CELIA
+
+
O my poor Rosalind, whither wilt thou go?
+
Wilt thou change fathers? I will give thee mine.
+
I charge thee, be not thou more grieved than I am.
+
+
ROSALIND
+
+
I have more cause.
+
+
CELIA
+
+
Thou hast not, cousin;
+
Prithee be cheerful: know'st thou not, the duke
+
Hath banish'd me, his daughter?
+
+
ROSALIND
+
+
That he hath not.
+
+
CELIA
+
+
No, hath not? Rosalind lacks then the love
+
Which teacheth thee that thou and I am one:
+
Shall we be sunder'd? shall we part, sweet girl?
+
No: let my father seek another heir.
+
Therefore devise with me how we may fly,
+
Whither to go and what to bear with us;
+
And do not seek to take your change upon you,
+
To bear your griefs yourself and leave me out;
+
For, by this heaven, now at our sorrows pale,
+
Say what thou canst, I'll go along with thee.
+
+
ROSALIND
+
+
Why, whither shall we go?
+
+
CELIA
+
+
To seek my uncle in the forest of Arden.
+
+
ROSALIND
+
+
Alas, what danger will it be to us,
+
Maids as we are, to travel forth so far!
+
Beauty provoketh thieves sooner than gold.
+
+
CELIA
+
+
I'll put myself in poor and mean attire
+
And with a kind of umber smirch my face;
+
The like do you: so shall we pass along
+
And never stir assailants.
+
+
ROSALIND
+
+
Were it not better,
+
Because that I am more than common tall,
+
That I did suit me all points like a man?
+
A gallant curtle-axe upon my thigh,
+
A boar-spear in my hand; and--in my heart
+
Lie there what hidden woman's fear there will--
+
We'll have a swashing and a martial outside,
+
As many other mannish cowards have
+
That do outface it with their semblances.
+
+
CELIA
+
+
What shall I call thee when thou art a man?
+
+
ROSALIND
+
+
I'll have no worse a name than Jove's own page;
+
And therefore look you call me Ganymede.
+
But what will you be call'd?
+
+
CELIA
+
+
Something that hath a reference to my state
+
No longer Celia, but Aliena.
+
+
ROSALIND
+
+
But, cousin, what if we assay'd to steal
+
The clownish fool out of your father's court?
+
Would he not be a comfort to our travel?
+
+
CELIA
+
+
He'll go along o'er the wide world with me;
+
Leave me alone to woo him. Let's away,
+
And get our jewels and our wealth together,
+
Devise the fittest time and safest way
+
To hide us from pursuit that will be made
+
After my flight. Now go we in content
+
To liberty and not to banishment.
+
Exeunt
+
+
+
+
+ + +''' + + +# }}} + + ae = unittest.TestCase.assertEqual + + def test_tokenizer(self): # {{{ + tokens = [ + type('')(item) for item in tokenize( + r'E\ é > f [a~="y\"x"]:nth(/* fu /]* */-3.7)')] + self.ae(tokens, [ + "", + "", + "' at 5>", + "", + # the no-break space is not whitespace in CSS + "", # f\xa0 + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + ]) + # }}} + + def test_parser(self): # {{{ + def repr_parse(css): + selectors = parse(css) + for selector in selectors: + assert selector.pseudo_element is None + return [repr(selector.parsed_tree).replace("(u'", "('") + for selector in selectors] + + def parse_many(first, *others): + result = repr_parse(first) + for other in others: + assert repr_parse(other) == result + return result + + assert parse_many('*') == ['Element[*]'] + assert parse_many('*|*') == ['Element[*]'] + assert parse_many('*|foo') == ['Element[foo]'] + assert parse_many('foo|*') == ['Element[foo|*]'] + assert parse_many('foo|bar') == ['Element[foo|bar]'] + # This will never match, but it is valid: + assert parse_many('#foo#bar') == ['Hash[Hash[Element[*]#foo]#bar]'] + assert parse_many( + 'div>.foo', + 'div> .foo', + 'div >.foo', + 'div > .foo', + 'div \n> \t \t .foo', 'div\r>\n\n\n.foo', 'div\f>\f.foo' + ) == ['CombinedSelector[Element[div] > Class[Element[*].foo]]'] + assert parse_many('td.foo,.bar', + 'td.foo, .bar', + 'td.foo\t\r\n\f ,\t\r\n\f .bar' + ) == [ + 'Class[Element[td].foo]', + 'Class[Element[*].bar]' + ] + assert parse_many('div, td.foo, div.bar span') == [ + 'Element[div]', + 'Class[Element[td].foo]', + 'CombinedSelector[Class[Element[div].bar] ' + ' Element[span]]'] + assert parse_many('div > p') == [ + 'CombinedSelector[Element[div] > Element[p]]'] + assert parse_many('td:first') == [ + 'Pseudo[Element[td]:first]'] + assert parse_many('td:first') == [ + 'Pseudo[Element[td]:first]'] + assert parse_many('td :first') == [ + 'CombinedSelector[Element[td] ' + ' Pseudo[Element[*]:first]]'] + assert parse_many('td :first') == [ + 'CombinedSelector[Element[td] ' + ' Pseudo[Element[*]:first]]'] + assert parse_many('a[name]', 'a[ name\t]') == [ + 'Attrib[Element[a][name]]'] + assert parse_many('a [name]') == [ + 'CombinedSelector[Element[a] Attrib[Element[*][name]]]'] + self.ae(parse_many('a[rel="include"]', 'a[rel = include]'), [ + "Attrib[Element[a][rel = 'include']]"]) + assert parse_many("a[hreflang |= 'en']", "a[hreflang|=en]") == [ + "Attrib[Element[a][hreflang |= 'en']]"] + self.ae(parse_many('div:nth-child(10)'), [ + "Function[Element[div]:nth-child(['10'])]"]) + assert parse_many(':nth-child(2n+2)') == [ + "Function[Element[*]:nth-child(['2', 'n', '+2'])]"] + assert parse_many('div:nth-of-type(10)') == [ + "Function[Element[div]:nth-of-type(['10'])]"] + assert parse_many('div div:nth-of-type(10) .aclass') == [ + 'CombinedSelector[CombinedSelector[Element[div] ' + "Function[Element[div]:nth-of-type(['10'])]] " + ' Class[Element[*].aclass]]'] + assert parse_many('label:only') == [ + 'Pseudo[Element[label]:only]'] + assert parse_many('a:lang(fr)') == [ + "Function[Element[a]:lang(['fr'])]"] + assert parse_many('div:contains("foo")') == [ + "Function[Element[div]:contains(['foo'])]"] + assert parse_many('div#foobar') == [ + 'Hash[Element[div]#foobar]'] + assert parse_many('div:not(div.foo)') == [ + 'Negation[Element[div]:not(Class[Element[div].foo])]'] + assert parse_many('td ~ th') == [ + 'CombinedSelector[Element[td] ~ Element[th]]'] + # }}} + + def test_pseudo_elements(self): # {{{ + def parse_pseudo(css): + result = [] + for selector in parse(css): + pseudo = selector.pseudo_element + pseudo = type('')(pseudo) if pseudo else pseudo + # No Symbol here + assert pseudo is None or isinstance(pseudo, type('')) + selector = repr(selector.parsed_tree).replace("(u'", "('") + result.append((selector, pseudo)) + return result + + def parse_one(css): + result = parse_pseudo(css) + assert len(result) == 1 + return result[0] + + self.ae(parse_one('foo'), ('Element[foo]', None)) + self.ae(parse_one('*'), ('Element[*]', None)) + self.ae(parse_one(':empty'), ('Pseudo[Element[*]:empty]', None)) + + # Special cases for CSS 2.1 pseudo-elements + self.ae(parse_one(':BEfore'), ('Element[*]', 'before')) + self.ae(parse_one(':aftER'), ('Element[*]', 'after')) + self.ae(parse_one(':First-Line'), ('Element[*]', 'first-line')) + self.ae(parse_one(':First-Letter'), ('Element[*]', 'first-letter')) + + self.ae(parse_one('::befoRE'), ('Element[*]', 'before')) + self.ae(parse_one('::AFter'), ('Element[*]', 'after')) + self.ae(parse_one('::firsT-linE'), ('Element[*]', 'first-line')) + self.ae(parse_one('::firsT-letteR'), ('Element[*]', 'first-letter')) + + self.ae(parse_one('::text-content'), ('Element[*]', 'text-content')) + self.ae(parse_one('::attr(name)'), ( + "Element[*]", "FunctionalPseudoElement[::attr(['name'])]")) + + self.ae(parse_one('::Selection'), ('Element[*]', 'selection')) + self.ae(parse_one('foo:after'), ('Element[foo]', 'after')) + self.ae(parse_one('foo::selection'), ('Element[foo]', 'selection')) + self.ae(parse_one('lorem#ipsum ~ a#b.c[href]:empty::selection'), ( + 'CombinedSelector[Hash[Element[lorem]#ipsum] ~ ' + 'Pseudo[Attrib[Class[Hash[Element[a]#b].c][href]]:empty]]', + 'selection')) + + parse_pseudo('foo:before, bar, baz:after') == [ + ('Element[foo]', 'before'), + ('Element[bar]', None), + ('Element[baz]', 'after')] + # }}} + + def test_specificity(self): # {{{ + def specificity(css): + selectors = parse(css) + assert len(selectors) == 1 + return selectors[0].specificity() + + assert specificity('*') == (0, 0, 0) + assert specificity(' foo') == (0, 0, 1) + assert specificity(':empty ') == (0, 1, 0) + assert specificity(':before') == (0, 0, 1) + assert specificity('*:before') == (0, 0, 1) + assert specificity(':nth-child(2)') == (0, 1, 0) + assert specificity('.bar') == (0, 1, 0) + assert specificity('[baz]') == (0, 1, 0) + assert specificity('[baz="4"]') == (0, 1, 0) + assert specificity('[baz^="4"]') == (0, 1, 0) + assert specificity('#lipsum') == (1, 0, 0) + + assert specificity(':not(*)') == (0, 0, 0) + assert specificity(':not(foo)') == (0, 0, 1) + assert specificity(':not(.foo)') == (0, 1, 0) + assert specificity(':not([foo])') == (0, 1, 0) + assert specificity(':not(:empty)') == (0, 1, 0) + assert specificity(':not(#foo)') == (1, 0, 0) + + assert specificity('foo:empty') == (0, 1, 1) + assert specificity('foo:before') == (0, 0, 2) + assert specificity('foo::before') == (0, 0, 2) + assert specificity('foo:empty::before') == (0, 1, 2) + + assert specificity('#lorem + foo#ipsum:first-child > bar:first-line' + ) == (2, 1, 3) + # }}} + + def test_parse_errors(self): # {{{ + def get_error(css): + try: + parse(css) + except SelectorSyntaxError: + # Py2, Py3, ... + return str(sys.exc_info()[1]).replace("(u'", "('") + + self.ae(get_error('attributes(href)/html/body/a'), ( + "Expected selector, got ")) + assert get_error('attributes(href)') == ( + "Expected selector, got ") + assert get_error('html/body/a') == ( + "Expected selector, got ") + assert get_error(' ') == ( + "Expected selector, got ") + assert get_error('div, ') == ( + "Expected selector, got ") + assert get_error(' , div') == ( + "Expected selector, got ") + assert get_error('p, , div') == ( + "Expected selector, got ") + assert get_error('div > ') == ( + "Expected selector, got ") + assert get_error(' > div') == ( + "Expected selector, got ' at 2>") + assert get_error('foo|#bar') == ( + "Expected ident or '*', got ") + assert get_error('#.foo') == ( + "Expected selector, got ") + assert get_error('.#foo') == ( + "Expected ident, got ") + assert get_error(':#foo') == ( + "Expected ident, got ") + assert get_error('[*]') == ( + "Expected '|', got ") + assert get_error('[foo|]') == ( + "Expected ident, got ") + assert get_error('[#]') == ( + "Expected ident or '*', got ") + assert get_error('[foo=#]') == ( + "Expected string or ident, got ") + assert get_error('[href]a') == ( + "Expected selector, got ") + assert get_error('[rel=stylesheet]') is None + assert get_error('[rel:stylesheet]') == ( + "Operator expected, got ") + assert get_error('[rel=stylesheet') == ( + "Expected ']', got ") + assert get_error(':lang(fr)') is None + assert get_error(':lang(fr') == ( + "Expected an argument, got ") + assert get_error(':contains("foo') == ( + "Unclosed string at 10") + assert get_error('foo!') == ( + "Expected selector, got ") + + # Mis-placed pseudo-elements + assert get_error('a:before:empty') == ( + "Got pseudo-element ::before not at the end of a selector") + assert get_error('li:before a') == ( + "Got pseudo-element ::before not at the end of a selector") + assert get_error(':not(:before)') == ( + "Got pseudo-element ::before inside :not() at 12") + assert get_error(':not(:not(a))') == ( + "Got nested :not()") + # }}} + + def test_select(self): # {{{ + document = etree.fromstring(self.HTML_IDS, parser=etree.XMLParser(recover=True, no_network=True, resolve_entities=False)) + select = Select(document) + + def select_ids(selector): + for elem in select(selector): + yield elem.get('id') + + def pcss(main, *selectors, **kwargs): + result = list(select_ids(main)) + for selector in selectors: + self.ae(list(select_ids(selector)), result) + return result + all_ids = pcss('*') + self.ae(all_ids[:6], [ + 'html', None, 'link-href', 'link-nohref', None, 'outer-div']) + self.ae(all_ids[-1:], ['foobar-span']) + self.ae(pcss('div'), ['outer-div', 'li-div', 'foobar-div']) + self.ae(pcss('DIV'), [ + 'outer-div', 'li-div', 'foobar-div']) # case-insensitive in HTML + self.ae(pcss('div div'), ['li-div']) + self.ae(pcss('div, div div'), ['outer-div', 'li-div', 'foobar-div']) + self.ae(pcss('a[name]'), ['name-anchor']) + self.ae(pcss('a[NAme]'), ['name-anchor']) # case-insensitive in HTML: + self.ae(pcss('a[rel]'), ['tag-anchor', 'nofollow-anchor']) + self.ae(pcss('a[rel="tag"]'), ['tag-anchor']) + self.ae(pcss('a[href*="localhost"]'), ['tag-anchor']) + self.ae(pcss('a[href*=""]'), []) + self.ae(pcss('a[href^="http"]'), ['tag-anchor', 'nofollow-anchor']) + self.ae(pcss('a[href^="http:"]'), ['tag-anchor']) + self.ae(pcss('a[href^=""]'), []) + self.ae(pcss('a[href$="org"]'), ['nofollow-anchor']) + self.ae(pcss('a[href$=""]'), []) + self.ae(pcss('div[foobar~="bc"]', 'div[foobar~="cde"]', skip_webkit=True), ['foobar-div']) + self.ae(pcss('[foobar~="ab bc"]', '[foobar~=""]', '[foobar~=" \t"]'), []) + self.ae(pcss('div[foobar~="cd"]'), []) + self.ae(pcss('*[lang|="En"]', '[lang|="En-us"]'), ['second-li']) + # Attribute values are case sensitive + self.ae(pcss('*[lang|="en"]', '[lang|="en-US"]', skip_webkit=True), []) + self.ae(pcss('*[lang|="e"]'), []) + self.ae(pcss(':lang("EN")', '*:lang(en-US)', skip_webkit=True), ['second-li', 'li-div']) + self.ae(pcss(':lang("e")'), []) + self.ae(pcss('li:nth-child(1)', 'li:first-child'), ['first-li']) + self.ae(pcss('li:nth-child(3)', '#first-li ~ :nth-child(3)'), ['third-li']) + self.ae(pcss('li:nth-child(10)'), []) + self.ae(pcss('li:nth-child(2n)', 'li:nth-child(even)', 'li:nth-child(2n+0)'), ['second-li', 'fourth-li', 'sixth-li']) + self.ae(pcss('li:nth-child(+2n+1)', 'li:nth-child(odd)'), ['first-li', 'third-li', 'fifth-li', 'seventh-li']) + self.ae(pcss('li:nth-child(2n+4)'), ['fourth-li', 'sixth-li']) + self.ae(pcss('li:nth-child(3n+1)'), ['first-li', 'fourth-li', 'seventh-li']) + self.ae(pcss('li:nth-last-child(0)'), []) + self.ae(pcss('li:nth-last-child(1)', 'li:last-child'), ['seventh-li']) + self.ae(pcss('li:nth-last-child(2n)', 'li:nth-last-child(even)'), ['second-li', 'fourth-li', 'sixth-li']) + self.ae(pcss('li:nth-last-child(2n+2)'), ['second-li', 'fourth-li', 'sixth-li']) + self.ae(pcss('ol:first-of-type'), ['first-ol']) + self.ae(pcss('ol:nth-child(1)'), []) + self.ae(pcss('ol:nth-of-type(2)'), ['second-ol']) + self.ae(pcss('ol:nth-last-of-type(1)'), ['second-ol']) + self.ae(pcss('span:only-child'), ['foobar-span']) + self.ae(pcss('li div:only-child'), ['li-div']) + self.ae(pcss('div *:only-child'), ['li-div', 'foobar-span']) + self.ae(pcss('p *:only-of-type', skip_webkit=True), ['p-em', 'fieldset']) + self.ae(pcss('p:only-of-type', skip_webkit=True), ['paragraph']) + self.ae(pcss('a:empty', 'a:EMpty'), ['name-anchor']) + self.ae(pcss('li:empty'), ['third-li', 'fourth-li', 'fifth-li', 'sixth-li']) + self.ae(pcss(':root', 'html:root', 'li:root'), ['html']) + self.ae(pcss('* :root', 'p *:root'), []) + self.ae(pcss('.a', '.b', '*.a', 'ol.a'), ['first-ol']) + self.ae(pcss('.c', '*.c'), ['first-ol', 'third-li', 'fourth-li']) + self.ae(pcss('ol *.c', 'ol li.c', 'li ~ li.c', 'ol > li.c'), [ + 'third-li', 'fourth-li']) + self.ae(pcss('#first-li', 'li#first-li', '*#first-li'), ['first-li']) + self.ae(pcss('li div', 'li > div', 'div div'), ['li-div']) + self.ae(pcss('div > div'), []) + self.ae(pcss('div>.c', 'div > .c'), ['first-ol']) + self.ae(pcss('div + div'), ['foobar-div']) + self.ae(pcss('a ~ a'), ['tag-anchor', 'nofollow-anchor']) + self.ae(pcss('a[rel="tag"] ~ a'), ['nofollow-anchor']) + self.ae(pcss('ol#first-ol li:last-child'), ['seventh-li']) + self.ae(pcss('ol#first-ol *:last-child'), ['li-div', 'seventh-li']) + self.ae(pcss('#outer-div:first-child'), ['outer-div']) + self.ae(pcss('#outer-div :first-child'), [ + 'name-anchor', 'first-li', 'li-div', 'p-b', + 'checkbox-fieldset-disabled', 'area-href']) + self.ae(pcss('a[href]'), ['tag-anchor', 'nofollow-anchor']) + self.ae(pcss(':not(*)'), []) + self.ae(pcss('a:not([href])'), ['name-anchor']) + self.ae(pcss('ol :Not(li[class])', skip_webkit=True), [ + 'first-li', 'second-li', 'li-div', + 'fifth-li', 'sixth-li', 'seventh-li']) + self.ae(pcss(r'di\a0 v', r'div\['), []) + self.ae(pcss(r'[h\a0 ref]', r'[h\]ref]'), []) + + self.assertRaises(ExpressionError, lambda : tuple(select('body:nth-child'))) + + select = Select(document, ignore_inappropriate_pseudo_classes=True) + self.assertGreater(len(tuple(select('p:hover'))), 0) + + def test_select_shakespeare(self): + document = html.document_fromstring(self.HTML_SHAKESPEARE) + select = Select(document) + count = lambda s: sum(1 for r in select(s)) + + # Data borrowed from http://mootools.net/slickspeed/ + + # Changed from original; probably because I'm only + self.ae(count('*'), 249) + assert count('div:only-child') == 22 # ? + assert count('div:nth-child(even)') == 106 + assert count('div:nth-child(2n)') == 106 + assert count('div:nth-child(odd)') == 137 + assert count('div:nth-child(2n+1)') == 137 + assert count('div:nth-child(n)') == 243 + assert count('div:last-child') == 53 + assert count('div:first-child') == 51 + assert count('div > div') == 242 + assert count('div + div') == 190 + assert count('div ~ div') == 190 + assert count('body') == 1 + assert count('body div') == 243 + assert count('div') == 243 + assert count('div div') == 242 + assert count('div div div') == 241 + assert count('div, div, div') == 243 + assert count('div, a, span') == 243 + assert count('.dialog') == 51 + assert count('div.dialog') == 51 + assert count('div .dialog') == 51 + assert count('div.character, div.dialog') == 99 + assert count('div.direction.dialog') == 0 + assert count('div.dialog.direction') == 0 + assert count('div.dialog.scene') == 1 + assert count('div.scene.scene') == 1 + assert count('div.scene .scene') == 0 + assert count('div.direction .dialog ') == 0 + assert count('div .dialog .direction') == 4 + assert count('div.dialog .dialog .direction') == 4 + assert count('#speech5') == 1 + assert count('div#speech5') == 1 + assert count('div #speech5') == 1 + assert count('div.scene div.dialog') == 49 + assert count('div#scene1 div.dialog div') == 142 + assert count('#scene1 #speech1') == 1 + assert count('div[class]') == 103 + assert count('div[class=dialog]') == 50 + assert count('div[class^=dia]') == 51 + assert count('div[class$=log]') == 50 + assert count('div[class*=sce]') == 1 + assert count('div[class|=dialog]') == 50 # ? Seems right + assert count('div[class~=dialog]') == 51 # ? Seems right + + # }}} + + +# Run tests {{{ +def find_tests(): + return unittest.defaultTestLoader.loadTestsFromTestCase(TestCSSSelectors) + + +def run_tests(find_tests=find_tests, for_build=False): + if not for_build: + parser = argparse.ArgumentParser() + parser.add_argument('name', nargs='?', default=None, + help='The name of the test to run') + args = parser.parse_args() + if not for_build and args.name and args.name.startswith('.'): + tests = find_tests() + q = args.name[1:] + if not q.startswith('test_'): + q = 'test_' + q + ans = None + try: + for test in tests: + if test._testMethodName == q: + ans = test + raise StopIteration() + except StopIteration: + pass + if ans is None: + print('No test named %s found' % args.name) + raise SystemExit(1) + tests = ans + else: + tests = unittest.defaultTestLoader.loadTestsFromName(args.name) if not for_build and args.name else find_tests() + r = unittest.TextTestRunner + if for_build: + r = r(verbosity=0, buffer=True, failfast=True) + else: + r = r(verbosity=4) + result = r.run(tests) + if for_build and result.errors or result.failures: + raise SystemExit(1) + + +if __name__ == '__main__': + run_tests() +# }}} diff --git a/ebook_converter/customize/__init__.py b/ebook_converter/customize/__init__.py new file mode 100644 index 0000000..8878fb8 --- /dev/null +++ b/ebook_converter/customize/__init__.py @@ -0,0 +1,759 @@ +from __future__ import absolute_import, division, print_function, unicode_literals +__license__ = 'GPL v3' +__copyright__ = '2008, Kovid Goyal ' + +import os, sys, zipfile, importlib + +from calibre.constants import numeric_version, iswindows, isosx +from calibre.ptempfile import PersistentTemporaryFile +from polyglot.builtins import unicode_type + +platform = 'linux' +if iswindows: + platform = 'windows' +elif isosx: + platform = 'osx' + + +class PluginNotFound(ValueError): + pass + + +class InvalidPlugin(ValueError): + pass + + +class Plugin(object): # {{{ + ''' + A calibre plugin. Useful members include: + + * ``self.plugin_path``: Stores path to the ZIP file that contains + this plugin or None if it is a builtin + plugin + * ``self.site_customization``: Stores a customization string entered + by the user. + + Methods that should be overridden in sub classes: + + * :meth:`initialize` + * :meth:`customization_help` + + Useful methods: + + * :meth:`temporary_file` + * :meth:`__enter__` + * :meth:`load_resources` + + ''' + #: List of platforms this plugin works on. + #: For example: ``['windows', 'osx', 'linux']`` + supported_platforms = [] + + #: The name of this plugin. You must set it something other + #: than Trivial Plugin for it to work. + name = 'Trivial Plugin' + + #: The version of this plugin as a 3-tuple (major, minor, revision) + version = (1, 0, 0) + + #: A short string describing what this plugin does + description = _('Does absolutely nothing') + + #: The author of this plugin + author = _('Unknown') + + #: When more than one plugin exists for a filetype, + #: the plugins are run in order of decreasing priority. + #: Plugins with higher priority will be run first. + #: The highest possible priority is ``sys.maxsize``. + #: Default priority is 1. + priority = 1 + + #: The earliest version of calibre this plugin requires + minimum_calibre_version = (0, 4, 118) + + #: If False, the user will not be able to disable this plugin. Use with + #: care. + can_be_disabled = True + + #: The type of this plugin. Used for categorizing plugins in the + #: GUI + type = _('Base') + + def __init__(self, plugin_path): + self.plugin_path = plugin_path + self.site_customization = None + + def initialize(self): + ''' + Called once when calibre plugins are initialized. Plugins are + re-initialized every time a new plugin is added. Also note that if the + plugin is run in a worker process, such as for adding books, then the + plugin will be initialized for every new worker process. + + Perform any plugin specific initialization here, such as extracting + resources from the plugin ZIP file. The path to the ZIP file is + available as ``self.plugin_path``. + + Note that ``self.site_customization`` is **not** available at this point. + ''' + pass + + def config_widget(self): + ''' + Implement this method and :meth:`save_settings` in your plugin to + use a custom configuration dialog, rather then relying on the simple + string based default customization. + + This method, if implemented, must return a QWidget. The widget can have + an optional method validate() that takes no arguments and is called + immediately after the user clicks OK. Changes are applied if and only + if the method returns True. + + If for some reason you cannot perform the configuration at this time, + return a tuple of two strings (message, details), these will be + displayed as a warning dialog to the user and the process will be + aborted. + ''' + raise NotImplementedError() + + def save_settings(self, config_widget): + ''' + Save the settings specified by the user with config_widget. + + :param config_widget: The widget returned by :meth:`config_widget`. + + ''' + raise NotImplementedError() + + def do_user_config(self, parent=None): + ''' + This method shows a configuration dialog for this plugin. It returns + True if the user clicks OK, False otherwise. The changes are + automatically applied. + ''' + from PyQt5.Qt import QDialog, QDialogButtonBox, QVBoxLayout, \ + QLabel, Qt, QLineEdit + from calibre.gui2 import gprefs + + prefname = 'plugin config dialog:'+self.type + ':' + self.name + geom = gprefs.get(prefname, None) + + config_dialog = QDialog(parent) + button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) + v = QVBoxLayout(config_dialog) + + def size_dialog(): + if geom is None: + config_dialog.resize(config_dialog.sizeHint()) + else: + from PyQt5.Qt import QApplication + QApplication.instance().safe_restore_geometry(config_dialog, geom) + + button_box.accepted.connect(config_dialog.accept) + button_box.rejected.connect(config_dialog.reject) + config_dialog.setWindowTitle(_('Customize') + ' ' + self.name) + try: + config_widget = self.config_widget() + except NotImplementedError: + config_widget = None + + if isinstance(config_widget, tuple): + from calibre.gui2 import warning_dialog + warning_dialog(parent, _('Cannot configure'), config_widget[0], + det_msg=config_widget[1], show=True) + return False + + if config_widget is not None: + v.addWidget(config_widget) + v.addWidget(button_box) + size_dialog() + config_dialog.exec_() + + if config_dialog.result() == QDialog.Accepted: + if hasattr(config_widget, 'validate'): + if config_widget.validate(): + self.save_settings(config_widget) + else: + self.save_settings(config_widget) + else: + from calibre.customize.ui import plugin_customization, \ + customize_plugin + help_text = self.customization_help(gui=True) + help_text = QLabel(help_text, config_dialog) + help_text.setWordWrap(True) + help_text.setTextInteractionFlags(Qt.LinksAccessibleByMouse | Qt.LinksAccessibleByKeyboard) + help_text.setOpenExternalLinks(True) + v.addWidget(help_text) + sc = plugin_customization(self) + if not sc: + sc = '' + sc = sc.strip() + sc = QLineEdit(sc, config_dialog) + v.addWidget(sc) + v.addWidget(button_box) + size_dialog() + config_dialog.exec_() + + if config_dialog.result() == QDialog.Accepted: + sc = unicode_type(sc.text()).strip() + customize_plugin(self, sc) + + geom = bytearray(config_dialog.saveGeometry()) + gprefs[prefname] = geom + + return config_dialog.result() + + def load_resources(self, names): + ''' + If this plugin comes in a ZIP file (user added plugin), this method + will allow you to load resources from the ZIP file. + + For example to load an image:: + + pixmap = QPixmap() + pixmap.loadFromData(self.load_resources(['images/icon.png'])['images/icon.png']) + icon = QIcon(pixmap) + + :param names: List of paths to resources in the ZIP file using / as separator + + :return: A dictionary of the form ``{name: file_contents}``. Any names + that were not found in the ZIP file will not be present in the + dictionary. + + ''' + if self.plugin_path is None: + raise ValueError('This plugin was not loaded from a ZIP file') + ans = {} + with zipfile.ZipFile(self.plugin_path, 'r') as zf: + for candidate in zf.namelist(): + if candidate in names: + ans[candidate] = zf.read(candidate) + return ans + + def customization_help(self, gui=False): + ''' + Return a string giving help on how to customize this plugin. + By default raise a :class:`NotImplementedError`, which indicates that + the plugin does not require customization. + + If you re-implement this method in your subclass, the user will + be asked to enter a string as customization for this plugin. + The customization string will be available as + ``self.site_customization``. + + Site customization could be anything, for example, the path to + a needed binary on the user's computer. + + :param gui: If True return HTML help, otherwise return plain text help. + + ''' + raise NotImplementedError() + + def temporary_file(self, suffix): + ''' + Return a file-like object that is a temporary file on the file system. + This file will remain available even after being closed and will only + be removed on interpreter shutdown. Use the ``name`` member of the + returned object to access the full path to the created temporary file. + + :param suffix: The suffix that the temporary file will have. + ''' + return PersistentTemporaryFile(suffix) + + def is_customizable(self): + try: + self.customization_help() + return True + except NotImplementedError: + return False + + def __enter__(self, *args): + ''' + Add this plugin to the python path so that it's contents become directly importable. + Useful when bundling large python libraries into the plugin. Use it like this:: + with plugin: + import something + ''' + if self.plugin_path is not None: + from calibre.utils.zipfile import ZipFile + zf = ZipFile(self.plugin_path) + extensions = {x.rpartition('.')[-1].lower() for x in + zf.namelist()} + zip_safe = True + for ext in ('pyd', 'so', 'dll', 'dylib'): + if ext in extensions: + zip_safe = False + break + if zip_safe: + sys.path.insert(0, self.plugin_path) + self.sys_insertion_path = self.plugin_path + else: + from calibre.ptempfile import TemporaryDirectory + self._sys_insertion_tdir = TemporaryDirectory('plugin_unzip') + self.sys_insertion_path = self._sys_insertion_tdir.__enter__(*args) + zf.extractall(self.sys_insertion_path) + sys.path.insert(0, self.sys_insertion_path) + zf.close() + + def __exit__(self, *args): + ip, it = getattr(self, 'sys_insertion_path', None), getattr(self, + '_sys_insertion_tdir', None) + if ip in sys.path: + sys.path.remove(ip) + if hasattr(it, '__exit__'): + it.__exit__(*args) + + def cli_main(self, args): + ''' + This method is the main entry point for your plugins command line + interface. It is called when the user does: calibre-debug -r "Plugin + Name". Any arguments passed are present in the args variable. + ''' + raise NotImplementedError('The %s plugin has no command line interface' + %self.name) + +# }}} + + +class FileTypePlugin(Plugin): # {{{ + ''' + A plugin that is associated with a particular set of file types. + ''' + + #: Set of file types for which this plugin should be run. + #: Use '*' for all file types. + #: For example: ``{'lit', 'mobi', 'prc'}`` + file_types = set() + + #: If True, this plugin is run when books are added + #: to the database + on_import = False + + #: If True, this plugin is run after books are added + #: to the database. In this case the postimport and postadd + #: methods of the plugin are called. + on_postimport = False + + #: If True, this plugin is run just before a conversion + on_preprocess = False + + #: If True, this plugin is run after conversion + #: on the final file produced by the conversion output plugin. + on_postprocess = False + + type = _('File type') + + def run(self, path_to_ebook): + ''' + Run the plugin. Must be implemented in subclasses. + It should perform whatever modifications are required + on the e-book and return the absolute path to the + modified e-book. If no modifications are needed, it should + return the path to the original e-book. If an error is encountered + it should raise an Exception. The default implementation + simply return the path to the original e-book. Note that the path to + the original file (before any file type plugins are run, is available as + self.original_path_to_file). + + The modified e-book file should be created with the + :meth:`temporary_file` method. + + :param path_to_ebook: Absolute path to the e-book. + + :return: Absolute path to the modified e-book. + ''' + # Default implementation does nothing + return path_to_ebook + + def postimport(self, book_id, book_format, db): + ''' + Called post import, i.e., after the book file has been added to the database. Note that + this is different from :meth:`postadd` which is called when the book record is created for + the first time. This method is called whenever a new file is added to a book record. It is + useful for modifying the book record based on the contents of the newly added file. + + :param book_id: Database id of the added book. + :param book_format: The file type of the book that was added. + :param db: Library database. + ''' + pass # Default implementation does nothing + + def postadd(self, book_id, fmt_map, db): + ''' + Called post add, i.e. after a book has been added to the db. Note that + this is different from :meth:`postimport`, which is called after a single book file + has been added to a book. postadd() is called only when an entire book record + with possibly more than one book file has been created for the first time. + This is useful if you wish to modify the book record in the database when the + book is first added to calibre. + + :param book_id: Database id of the added book. + :param fmt_map: Map of file format to path from which the file format + was added. Note that this might or might not point to an actual + existing file, as sometimes files are added as streams. In which case + it might be a dummy value or a non-existent path. + :param db: Library database + ''' + pass # Default implementation does nothing + +# }}} + + +class MetadataReaderPlugin(Plugin): # {{{ + ''' + A plugin that implements reading metadata from a set of file types. + ''' + #: Set of file types for which this plugin should be run. + #: For example: ``set(['lit', 'mobi', 'prc'])`` + file_types = set() + + supported_platforms = ['windows', 'osx', 'linux'] + version = numeric_version + author = 'Kovid Goyal' + + type = _('Metadata reader') + + def __init__(self, *args, **kwargs): + Plugin.__init__(self, *args, **kwargs) + self.quick = False + + def get_metadata(self, stream, type): + ''' + Return metadata for the file represented by stream (a file like object + that supports reading). Raise an exception when there is an error + with the input data. + + :param type: The type of file. Guaranteed to be one of the entries + in :attr:`file_types`. + :return: A :class:`calibre.ebooks.metadata.book.Metadata` object + ''' + return None +# }}} + + +class MetadataWriterPlugin(Plugin): # {{{ + ''' + A plugin that implements reading metadata from a set of file types. + ''' + #: Set of file types for which this plugin should be run. + #: For example: ``set(['lit', 'mobi', 'prc'])`` + file_types = set() + + supported_platforms = ['windows', 'osx', 'linux'] + version = numeric_version + author = 'Kovid Goyal' + + type = _('Metadata writer') + + def __init__(self, *args, **kwargs): + Plugin.__init__(self, *args, **kwargs) + self.apply_null = False + + def set_metadata(self, stream, mi, type): + ''' + Set metadata for the file represented by stream (a file like object + that supports reading). Raise an exception when there is an error + with the input data. + + :param type: The type of file. Guaranteed to be one of the entries + in :attr:`file_types`. + :param mi: A :class:`calibre.ebooks.metadata.book.Metadata` object + ''' + pass + +# }}} + + +class CatalogPlugin(Plugin): # {{{ + ''' + A plugin that implements a catalog generator. + ''' + + resources_path = None + + #: Output file type for which this plugin should be run. + #: For example: 'epub' or 'xml' + file_types = set() + + type = _('Catalog generator') + + #: CLI parser options specific to this plugin, declared as namedtuple Option: + #: + #: from collections import namedtuple + #: Option = namedtuple('Option', 'option, default, dest, help') + #: cli_options = [Option('--catalog-title', default = 'My Catalog', + #: dest = 'catalog_title', help = (_('Title of generated catalog. \nDefault:') + " '" + '%default' + "'"))] + #: cli_options parsed in calibre.db.cli.cmd_catalog:option_parser() + #: + cli_options = [] + + def _field_sorter(self, key): + ''' + Custom fields sort after standard fields + ''' + if key.startswith('#'): + return '~%s' % key[1:] + else: + return key + + def search_sort_db(self, db, opts): + + db.search(opts.search_text) + + if opts.sort_by: + # 2nd arg = ascending + db.sort(opts.sort_by, True) + return db.get_data_as_dict(ids=opts.ids) + + def get_output_fields(self, db, opts): + # Return a list of requested fields + all_std_fields = {'author_sort','authors','comments','cover','formats', + 'id','isbn','library_name','ondevice','pubdate','publisher', + 'rating','series_index','series','size','tags','timestamp', + 'title_sort','title','uuid','languages','identifiers'} + all_custom_fields = set(db.custom_field_keys()) + for field in list(all_custom_fields): + fm = db.field_metadata[field] + if fm['datatype'] == 'series': + all_custom_fields.add(field+'_index') + all_fields = all_std_fields.union(all_custom_fields) + + if opts.fields != 'all': + # Make a list from opts.fields + of = [x.strip() for x in opts.fields.split(',')] + requested_fields = set(of) + + # Validate requested_fields + if requested_fields - all_fields: + from calibre.library import current_library_name + invalid_fields = sorted(list(requested_fields - all_fields)) + print("invalid --fields specified: %s" % ', '.join(invalid_fields)) + print("available fields in '%s': %s" % + (current_library_name(), ', '.join(sorted(list(all_fields))))) + raise ValueError("unable to generate catalog with specified fields") + + fields = [x for x in of if x in all_fields] + else: + fields = sorted(all_fields, key=self._field_sorter) + + if not opts.connected_device['is_device_connected'] and 'ondevice' in fields: + fields.pop(int(fields.index('ondevice'))) + + return fields + + def initialize(self): + ''' + If plugin is not a built-in, copy the plugin's .ui and .py files from + the ZIP file to $TMPDIR. + Tab will be dynamically generated and added to the Catalog Options dialog in + calibre.gui2.dialogs.catalog.py:Catalog + ''' + from calibre.customize.builtins import plugins as builtin_plugins + from calibre.customize.ui import config + from calibre.ptempfile import PersistentTemporaryDirectory + + if not type(self) in builtin_plugins and self.name not in config['disabled_plugins']: + files_to_copy = ["%s.%s" % (self.name.lower(),ext) for ext in ["ui","py"]] + resources = zipfile.ZipFile(self.plugin_path,'r') + + if self.resources_path is None: + self.resources_path = PersistentTemporaryDirectory('_plugin_resources', prefix='') + + for file in files_to_copy: + try: + resources.extract(file, self.resources_path) + except: + print(" customize:__init__.initialize(): %s not found in %s" % (file, os.path.basename(self.plugin_path))) + continue + resources.close() + + def run(self, path_to_output, opts, db, ids, notification=None): + ''' + Run the plugin. Must be implemented in subclasses. + It should generate the catalog in the format specified + in file_types, returning the absolute path to the + generated catalog file. If an error is encountered + it should raise an Exception. + + The generated catalog file should be created with the + :meth:`temporary_file` method. + + :param path_to_output: Absolute path to the generated catalog file. + :param opts: A dictionary of keyword arguments + :param db: A LibraryDatabase2 object + ''' + # Default implementation does nothing + raise NotImplementedError('CatalogPlugin.generate_catalog() default ' + 'method, should be overridden in subclass') + +# }}} + + +class InterfaceActionBase(Plugin): # {{{ + + supported_platforms = ['windows', 'osx', 'linux'] + author = 'Kovid Goyal' + type = _('User interface action') + can_be_disabled = False + + actual_plugin = None + + def __init__(self, *args, **kwargs): + Plugin.__init__(self, *args, **kwargs) + self.actual_plugin_ = None + + def load_actual_plugin(self, gui): + ''' + This method must return the actual interface action plugin object. + ''' + ac = self.actual_plugin_ + if ac is None: + mod, cls = self.actual_plugin.split(':') + ac = getattr(importlib.import_module(mod), cls)(gui, + self.site_customization) + self.actual_plugin_ = ac + return ac + +# }}} + + +class PreferencesPlugin(Plugin): # {{{ + + ''' + A plugin representing a widget displayed in the Preferences dialog. + + This plugin has only one important method :meth:`create_widget`. The + various fields of the plugin control how it is categorized in the UI. + ''' + + supported_platforms = ['windows', 'osx', 'linux'] + author = 'Kovid Goyal' + type = _('Preferences') + can_be_disabled = False + + #: Import path to module that contains a class named ConfigWidget + #: which implements the ConfigWidgetInterface. Used by + #: :meth:`create_widget`. + config_widget = None + + #: Where in the list of categories the :attr:`category` of this plugin should be. + category_order = 100 + + #: Where in the list of names in a category, the :attr:`gui_name` of this + #: plugin should be + name_order = 100 + + #: The category this plugin should be in + category = None + + #: The category name displayed to the user for this plugin + gui_category = None + + #: The name displayed to the user for this plugin + gui_name = None + + #: The icon for this plugin, should be an absolute path + icon = None + + #: The description used for tooltips and the like + description = None + + def create_widget(self, parent=None): + ''' + Create and return the actual Qt widget used for setting this group of + preferences. The widget must implement the + :class:`calibre.gui2.preferences.ConfigWidgetInterface`. + + The default implementation uses :attr:`config_widget` to instantiate + the widget. + ''' + base, _, wc = self.config_widget.partition(':') + if not wc: + wc = 'ConfigWidget' + base = importlib.import_module(base) + widget = getattr(base, wc) + return widget(parent) + +# }}} + + +class StoreBase(Plugin): # {{{ + + supported_platforms = ['windows', 'osx', 'linux'] + author = 'John Schember' + type = _('Store') + # Information about the store. Should be in the primary language + # of the store. This should not be translatable when set by + # a subclass. + description = _('An e-book store.') + minimum_calibre_version = (0, 8, 0) + version = (1, 0, 1) + + actual_plugin = None + + # Does the store only distribute e-books without DRM. + drm_free_only = False + # This is the 2 letter country code for the corporate + # headquarters of the store. + headquarters = '' + # All formats the store distributes e-books in. + formats = [] + # Is this store on an affiliate program? + affiliate = False + + def load_actual_plugin(self, gui): + ''' + This method must return the actual interface action plugin object. + ''' + mod, cls = self.actual_plugin.split(':') + self.actual_plugin_object = getattr(importlib.import_module(mod), cls)(gui, self.name) + return self.actual_plugin_object + + def customization_help(self, gui=False): + if getattr(self, 'actual_plugin_object', None) is not None: + return self.actual_plugin_object.customization_help(gui) + raise NotImplementedError() + + def config_widget(self): + if getattr(self, 'actual_plugin_object', None) is not None: + return self.actual_plugin_object.config_widget() + raise NotImplementedError() + + def save_settings(self, config_widget): + if getattr(self, 'actual_plugin_object', None) is not None: + return self.actual_plugin_object.save_settings(config_widget) + raise NotImplementedError() + +# }}} + + +class EditBookToolPlugin(Plugin): # {{{ + + type = _('Edit book tool') + minimum_calibre_version = (1, 46, 0) + +# }}} + + +class LibraryClosedPlugin(Plugin): # {{{ + ''' + LibraryClosedPlugins are run when a library is closed, either at shutdown, + when the library is changed, or when a library is used in some other way. + At the moment these plugins won't be called by the CLI functions. + ''' + type = _('Library closed') + + # minimum version 2.54 because that is when support was added + minimum_calibre_version = (2, 54, 0) + + def run(self, db): + ''' + The db will be a reference to the new_api (db.cache.py). + + The plugin must run to completion. It must not use the GUI, threads, or + any signals. + ''' + raise NotImplementedError('LibraryClosedPlugin ' + 'run method must be overridden in subclass') +# }}} diff --git a/ebook_converter/customize/builtins.py b/ebook_converter/customize/builtins.py new file mode 100644 index 0000000..4a3af02 --- /dev/null +++ b/ebook_converter/customize/builtins.py @@ -0,0 +1,1973 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2008, Kovid Goyal ' + +import os, glob, re +from calibre import guess_type +from calibre.customize import (FileTypePlugin, MetadataReaderPlugin, + MetadataWriterPlugin, PreferencesPlugin, InterfaceActionBase, StoreBase) +from calibre.constants import numeric_version +from calibre.ebooks.metadata.archive import ArchiveExtract, KPFExtract, get_comic_metadata +from calibre.ebooks.html.to_zip import HTML2ZIP + +plugins = [] + +# To archive plugins {{{ + + +class PML2PMLZ(FileTypePlugin): + name = 'PML to PMLZ' + author = 'John Schember' + description = _('Create a PMLZ archive containing the PML file ' + 'and all images in the directory pmlname_img or images. ' + 'This plugin is run every time you add ' + 'a PML file to the library.') + version = numeric_version + file_types = {'pml'} + supported_platforms = ['windows', 'osx', 'linux'] + on_import = True + + def run(self, pmlfile): + import zipfile + + of = self.temporary_file('_plugin_pml2pmlz.pmlz') + pmlz = zipfile.ZipFile(of.name, 'w') + pmlz.write(pmlfile, os.path.basename(pmlfile), zipfile.ZIP_DEFLATED) + + pml_img = os.path.splitext(pmlfile)[0] + '_img' + i_img = os.path.join(os.path.dirname(pmlfile),'images') + img_dir = pml_img if os.path.isdir(pml_img) else i_img if \ + os.path.isdir(i_img) else '' + if img_dir: + for image in glob.glob(os.path.join(img_dir, '*.png')): + pmlz.write(image, os.path.join('images', (os.path.basename(image)))) + pmlz.close() + + return of.name + + +class TXT2TXTZ(FileTypePlugin): + name = 'TXT to TXTZ' + author = 'John Schember' + description = _('Create a TXTZ archive when a TXT file is imported ' + 'containing Markdown or Textile references to images. The referenced ' + 'images as well as the TXT file are added to the archive.') + version = numeric_version + file_types = {'txt', 'text'} + supported_platforms = ['windows', 'osx', 'linux'] + on_import = True + + def _get_image_references(self, txt, base_dir): + from calibre.ebooks.oeb.base import OEB_IMAGES + + images = [] + + # Textile + for m in re.finditer(r'(?mu)(?:[\[{])?\!(?:\. )?(?P[^\s(!]+)\s?(?:\(([^\)]+)\))?\!(?::(\S+))?(?:[\]}]|(?=\s|$))', txt): + path = m.group('path') + if path and not os.path.isabs(path) and guess_type(path)[0] in OEB_IMAGES and os.path.exists(os.path.join(base_dir, path)): + images.append(path) + + # Markdown inline + for m in re.finditer(r'(?mu)\!\[([^\]\[]*(\[[^\]\[]*(\[[^\]\[]*(\[[^\]\[]*(\[[^\]\[]*(\[[^\]\[]*(\[[^\]\[]*\])*[^\]\[]*\])*[^\]\[]*\])*[^\]\[]*\])*[^\]\[]*\])*[^\]\[]*\])*[^\]\[]*)\]\s*\((?P[^\)]*)\)', txt): # noqa + path = m.group('path') + if path and not os.path.isabs(path) and guess_type(path)[0] in OEB_IMAGES and os.path.exists(os.path.join(base_dir, path)): + images.append(path) + + # Markdown reference + refs = {} + for m in re.finditer(r'(?mu)^(\ ?\ ?\ ?)\[(?P[^\]]*)\]:\s*(?P[^\s]*)$', txt): + if m.group('id') and m.group('path'): + refs[m.group('id')] = m.group('path') + for m in re.finditer(r'(?mu)\!\[([^\]\[]*(\[[^\]\[]*(\[[^\]\[]*(\[[^\]\[]*(\[[^\]\[]*(\[[^\]\[]*(\[[^\]\[]*\])*[^\]\[]*\])*[^\]\[]*\])*[^\]\[]*\])*[^\]\[]*\])*[^\]\[]*\])*[^\]\[]*)\]\s*\[(?P[^\]]*)\]', txt): # noqa + path = refs.get(m.group('id'), None) + if path and not os.path.isabs(path) and guess_type(path)[0] in OEB_IMAGES and os.path.exists(os.path.join(base_dir, path)): + images.append(path) + + # Remove duplicates + return list(set(images)) + + def run(self, path_to_ebook): + from calibre.ebooks.metadata.opf2 import metadata_to_opf + + with open(path_to_ebook, 'rb') as ebf: + txt = ebf.read().decode('utf-8', 'replace') + base_dir = os.path.dirname(path_to_ebook) + images = self._get_image_references(txt, base_dir) + + if images: + # Create TXTZ and put file plus images inside of it. + import zipfile + of = self.temporary_file('_plugin_txt2txtz.txtz') + txtz = zipfile.ZipFile(of.name, 'w') + # Add selected TXT file to archive. + txtz.write(path_to_ebook, os.path.basename(path_to_ebook), zipfile.ZIP_DEFLATED) + # metadata.opf + if os.path.exists(os.path.join(base_dir, 'metadata.opf')): + txtz.write(os.path.join(base_dir, 'metadata.opf'), 'metadata.opf', zipfile.ZIP_DEFLATED) + else: + from calibre.ebooks.metadata.txt import get_metadata + with open(path_to_ebook, 'rb') as ebf: + mi = get_metadata(ebf) + opf = metadata_to_opf(mi) + txtz.writestr('metadata.opf', opf, zipfile.ZIP_DEFLATED) + # images + for image in images: + txtz.write(os.path.join(base_dir, image), image) + txtz.close() + + return of.name + else: + # No images so just import the TXT file. + return path_to_ebook + + +plugins += [HTML2ZIP, PML2PMLZ, TXT2TXTZ, ArchiveExtract, KPFExtract] +# }}} + +# Metadata reader plugins {{{ + + +class ComicMetadataReader(MetadataReaderPlugin): + + name = 'Read comic metadata' + file_types = {'cbr', 'cbz'} + description = _('Extract cover from comic files') + + def customization_help(self, gui=False): + return 'Read series number from volume or issue number. Default is volume, set this to issue to use issue number instead.' + + def get_metadata(self, stream, ftype): + if hasattr(stream, 'seek') and hasattr(stream, 'tell'): + pos = stream.tell() + id_ = stream.read(3) + stream.seek(pos) + if id_ == b'Rar': + ftype = 'cbr' + elif id_.startswith(b'PK'): + ftype = 'cbz' + if ftype == 'cbr': + from calibre.utils.unrar import extract_cover_image + else: + from calibre.libunzip import extract_cover_image + from calibre.ebooks.metadata import MetaInformation + ret = extract_cover_image(stream) + mi = MetaInformation(None, None) + stream.seek(0) + if ftype in {'cbr', 'cbz'}: + series_index = self.site_customization + if series_index not in {'volume', 'issue'}: + series_index = 'volume' + try: + mi.smart_update(get_comic_metadata(stream, ftype, series_index=series_index)) + except: + pass + if ret is not None: + path, data = ret + ext = os.path.splitext(path)[1][1:] + mi.cover_data = (ext.lower(), data) + return mi + + +class CHMMetadataReader(MetadataReaderPlugin): + + name = 'Read CHM metadata' + file_types = {'chm'} + description = _('Read metadata from %s files') % 'CHM' + + def get_metadata(self, stream, ftype): + from calibre.ebooks.chm.metadata import get_metadata + return get_metadata(stream) + + +class EPUBMetadataReader(MetadataReaderPlugin): + + name = 'Read EPUB metadata' + file_types = {'epub'} + description = _('Read metadata from %s files')%'EPUB' + + def get_metadata(self, stream, ftype): + from calibre.ebooks.metadata.epub import get_metadata, get_quick_metadata + if self.quick: + return get_quick_metadata(stream) + return get_metadata(stream) + + +class FB2MetadataReader(MetadataReaderPlugin): + + name = 'Read FB2 metadata' + file_types = {'fb2', 'fbz'} + description = _('Read metadata from %s files')%'FB2' + + def get_metadata(self, stream, ftype): + from calibre.ebooks.metadata.fb2 import get_metadata + return get_metadata(stream) + + +class HTMLMetadataReader(MetadataReaderPlugin): + + name = 'Read HTML metadata' + file_types = {'html'} + description = _('Read metadata from %s files')%'HTML' + + def get_metadata(self, stream, ftype): + from calibre.ebooks.metadata.html import get_metadata + return get_metadata(stream) + + +class HTMLZMetadataReader(MetadataReaderPlugin): + + name = 'Read HTMLZ metadata' + file_types = {'htmlz'} + description = _('Read metadata from %s files') % 'HTMLZ' + author = 'John Schember' + + def get_metadata(self, stream, ftype): + from calibre.ebooks.metadata.extz import get_metadata + return get_metadata(stream) + + +class IMPMetadataReader(MetadataReaderPlugin): + + name = 'Read IMP metadata' + file_types = {'imp'} + description = _('Read metadata from %s files')%'IMP' + author = 'Ashish Kulkarni' + + def get_metadata(self, stream, ftype): + from calibre.ebooks.metadata.imp import get_metadata + return get_metadata(stream) + + +class LITMetadataReader(MetadataReaderPlugin): + + name = 'Read LIT metadata' + file_types = {'lit'} + description = _('Read metadata from %s files')%'LIT' + + def get_metadata(self, stream, ftype): + from calibre.ebooks.metadata.lit import get_metadata + return get_metadata(stream) + + +class LRFMetadataReader(MetadataReaderPlugin): + + name = 'Read LRF metadata' + file_types = {'lrf'} + description = _('Read metadata from %s files')%'LRF' + + def get_metadata(self, stream, ftype): + from calibre.ebooks.lrf.meta import get_metadata + return get_metadata(stream) + + +class LRXMetadataReader(MetadataReaderPlugin): + + name = 'Read LRX metadata' + file_types = {'lrx'} + description = _('Read metadata from %s files')%'LRX' + + def get_metadata(self, stream, ftype): + from calibre.ebooks.metadata.lrx import get_metadata + return get_metadata(stream) + + +class MOBIMetadataReader(MetadataReaderPlugin): + + name = 'Read MOBI metadata' + file_types = {'mobi', 'prc', 'azw', 'azw3', 'azw4', 'pobi'} + description = _('Read metadata from %s files')%'MOBI' + + def get_metadata(self, stream, ftype): + from calibre.ebooks.metadata.mobi import get_metadata + return get_metadata(stream) + + +class ODTMetadataReader(MetadataReaderPlugin): + + name = 'Read ODT metadata' + file_types = {'odt'} + description = _('Read metadata from %s files')%'ODT' + + def get_metadata(self, stream, ftype): + from calibre.ebooks.metadata.odt import get_metadata + return get_metadata(stream) + + +class DocXMetadataReader(MetadataReaderPlugin): + + name = 'Read DOCX metadata' + file_types = {'docx'} + description = _('Read metadata from %s files')%'DOCX' + + def get_metadata(self, stream, ftype): + from calibre.ebooks.metadata.docx import get_metadata + return get_metadata(stream) + + +class OPFMetadataReader(MetadataReaderPlugin): + + name = 'Read OPF metadata' + file_types = {'opf'} + description = _('Read metadata from %s files')%'OPF' + + def get_metadata(self, stream, ftype): + from calibre.ebooks.metadata.opf import get_metadata + return get_metadata(stream)[0] + + +class PDBMetadataReader(MetadataReaderPlugin): + + name = 'Read PDB metadata' + file_types = {'pdb', 'updb'} + description = _('Read metadata from %s files') % 'PDB' + author = 'John Schember' + + def get_metadata(self, stream, ftype): + from calibre.ebooks.metadata.pdb import get_metadata + return get_metadata(stream) + + +class PDFMetadataReader(MetadataReaderPlugin): + + name = 'Read PDF metadata' + file_types = {'pdf'} + description = _('Read metadata from %s files')%'PDF' + + def get_metadata(self, stream, ftype): + from calibre.ebooks.metadata.pdf import get_metadata, get_quick_metadata + if self.quick: + return get_quick_metadata(stream) + return get_metadata(stream) + + +class PMLMetadataReader(MetadataReaderPlugin): + + name = 'Read PML metadata' + file_types = {'pml', 'pmlz'} + description = _('Read metadata from %s files') % 'PML' + author = 'John Schember' + + def get_metadata(self, stream, ftype): + from calibre.ebooks.metadata.pml import get_metadata + return get_metadata(stream) + + +class RARMetadataReader(MetadataReaderPlugin): + + name = 'Read RAR metadata' + file_types = {'rar'} + description = _('Read metadata from e-books in RAR archives') + + def get_metadata(self, stream, ftype): + from calibre.ebooks.metadata.rar import get_metadata + return get_metadata(stream) + + +class RBMetadataReader(MetadataReaderPlugin): + + name = 'Read RB metadata' + file_types = {'rb'} + description = _('Read metadata from %s files')%'RB' + author = 'Ashish Kulkarni' + + def get_metadata(self, stream, ftype): + from calibre.ebooks.metadata.rb import get_metadata + return get_metadata(stream) + + +class RTFMetadataReader(MetadataReaderPlugin): + + name = 'Read RTF metadata' + file_types = {'rtf'} + description = _('Read metadata from %s files')%'RTF' + + def get_metadata(self, stream, ftype): + from calibre.ebooks.metadata.rtf import get_metadata + return get_metadata(stream) + + +class SNBMetadataReader(MetadataReaderPlugin): + + name = 'Read SNB metadata' + file_types = {'snb'} + description = _('Read metadata from %s files') % 'SNB' + author = 'Li Fanxi' + + def get_metadata(self, stream, ftype): + from calibre.ebooks.metadata.snb import get_metadata + return get_metadata(stream) + + +class TOPAZMetadataReader(MetadataReaderPlugin): + + name = 'Read Topaz metadata' + file_types = {'tpz', 'azw1'} + description = _('Read metadata from %s files')%'MOBI' + + def get_metadata(self, stream, ftype): + from calibre.ebooks.metadata.topaz import get_metadata + return get_metadata(stream) + + +class TXTMetadataReader(MetadataReaderPlugin): + + name = 'Read TXT metadata' + file_types = {'txt'} + description = _('Read metadata from %s files') % 'TXT' + author = 'John Schember' + + def get_metadata(self, stream, ftype): + from calibre.ebooks.metadata.txt import get_metadata + return get_metadata(stream) + + +class TXTZMetadataReader(MetadataReaderPlugin): + + name = 'Read TXTZ metadata' + file_types = {'txtz'} + description = _('Read metadata from %s files') % 'TXTZ' + author = 'John Schember' + + def get_metadata(self, stream, ftype): + from calibre.ebooks.metadata.extz import get_metadata + return get_metadata(stream) + + +class ZipMetadataReader(MetadataReaderPlugin): + + name = 'Read ZIP metadata' + file_types = {'zip', 'oebzip'} + description = _('Read metadata from e-books in ZIP archives') + + def get_metadata(self, stream, ftype): + from calibre.ebooks.metadata.zip import get_metadata + return get_metadata(stream) + + +plugins += [x for x in list(locals().values()) if isinstance(x, type) and + x.__name__.endswith('MetadataReader')] + +# }}} + +# Metadata writer plugins {{{ + + +class EPUBMetadataWriter(MetadataWriterPlugin): + + name = 'Set EPUB metadata' + file_types = {'epub'} + description = _('Set metadata in %s files')%'EPUB' + + def set_metadata(self, stream, mi, type): + from calibre.ebooks.metadata.epub import set_metadata + q = self.site_customization or '' + set_metadata(stream, mi, apply_null=self.apply_null, force_identifiers=self.force_identifiers, add_missing_cover='disable-add-missing-cover' != q) + + def customization_help(self, gui=False): + h = 'disable-add-missing-cover' + if gui: + h = '' + h + '' + return _('Enter {0} below to have the EPUB metadata writer plugin not' + ' add cover images to EPUB files that have no existing cover image.').format(h) + + +class FB2MetadataWriter(MetadataWriterPlugin): + + name = 'Set FB2 metadata' + file_types = {'fb2', 'fbz'} + description = _('Set metadata in %s files')%'FB2' + + def set_metadata(self, stream, mi, type): + from calibre.ebooks.metadata.fb2 import set_metadata + set_metadata(stream, mi, apply_null=self.apply_null) + + +class HTMLZMetadataWriter(MetadataWriterPlugin): + + name = 'Set HTMLZ metadata' + file_types = {'htmlz'} + description = _('Set metadata from %s files') % 'HTMLZ' + author = 'John Schember' + + def set_metadata(self, stream, mi, type): + from calibre.ebooks.metadata.extz import set_metadata + set_metadata(stream, mi) + + +class LRFMetadataWriter(MetadataWriterPlugin): + + name = 'Set LRF metadata' + file_types = {'lrf'} + description = _('Set metadata in %s files')%'LRF' + + def set_metadata(self, stream, mi, type): + from calibre.ebooks.lrf.meta import set_metadata + set_metadata(stream, mi) + + +class MOBIMetadataWriter(MetadataWriterPlugin): + + name = 'Set MOBI metadata' + file_types = {'mobi', 'prc', 'azw', 'azw3', 'azw4'} + description = _('Set metadata in %s files')%'MOBI' + author = 'Marshall T. Vandegrift' + + def set_metadata(self, stream, mi, type): + from calibre.ebooks.metadata.mobi import set_metadata + set_metadata(stream, mi) + + +class PDBMetadataWriter(MetadataWriterPlugin): + + name = 'Set PDB metadata' + file_types = {'pdb'} + description = _('Set metadata from %s files') % 'PDB' + author = 'John Schember' + + def set_metadata(self, stream, mi, type): + from calibre.ebooks.metadata.pdb import set_metadata + set_metadata(stream, mi) + + +class PDFMetadataWriter(MetadataWriterPlugin): + + name = 'Set PDF metadata' + file_types = {'pdf'} + description = _('Set metadata in %s files') % 'PDF' + author = 'Kovid Goyal' + + def set_metadata(self, stream, mi, type): + from calibre.ebooks.metadata.pdf import set_metadata + set_metadata(stream, mi) + + +class RTFMetadataWriter(MetadataWriterPlugin): + + name = 'Set RTF metadata' + file_types = {'rtf'} + description = _('Set metadata in %s files')%'RTF' + + def set_metadata(self, stream, mi, type): + from calibre.ebooks.metadata.rtf import set_metadata + set_metadata(stream, mi) + + +class TOPAZMetadataWriter(MetadataWriterPlugin): + + name = 'Set TOPAZ metadata' + file_types = {'tpz', 'azw1'} + description = _('Set metadata in %s files')%'TOPAZ' + author = 'Greg Riker' + + def set_metadata(self, stream, mi, type): + from calibre.ebooks.metadata.topaz import set_metadata + set_metadata(stream, mi) + + +class TXTZMetadataWriter(MetadataWriterPlugin): + + name = 'Set TXTZ metadata' + file_types = {'txtz'} + description = _('Set metadata from %s files') % 'TXTZ' + author = 'John Schember' + + def set_metadata(self, stream, mi, type): + from calibre.ebooks.metadata.extz import set_metadata + set_metadata(stream, mi) + + +class ODTMetadataWriter(MetadataWriterPlugin): + + name = 'Set ODT metadata' + file_types = {'odt'} + description = _('Set metadata from %s files')%'ODT' + + def set_metadata(self, stream, mi, type): + from calibre.ebooks.metadata.odt import set_metadata + return set_metadata(stream, mi) + + +class DocXMetadataWriter(MetadataWriterPlugin): + + name = 'Set DOCX metadata' + file_types = {'docx'} + description = _('Set metadata from %s files')%'DOCX' + + def set_metadata(self, stream, mi, type): + from calibre.ebooks.metadata.docx import set_metadata + return set_metadata(stream, mi) + + +plugins += [x for x in list(locals().values()) if isinstance(x, type) and + x.__name__.endswith('MetadataWriter')] + +# }}} + +# Conversion plugins {{{ +from calibre.ebooks.conversion.plugins.comic_input import ComicInput +from calibre.ebooks.conversion.plugins.djvu_input import DJVUInput +from calibre.ebooks.conversion.plugins.epub_input import EPUBInput +from calibre.ebooks.conversion.plugins.fb2_input import FB2Input +from calibre.ebooks.conversion.plugins.html_input import HTMLInput +from calibre.ebooks.conversion.plugins.htmlz_input import HTMLZInput +from calibre.ebooks.conversion.plugins.lit_input import LITInput +from calibre.ebooks.conversion.plugins.mobi_input import MOBIInput +from calibre.ebooks.conversion.plugins.odt_input import ODTInput +from calibre.ebooks.conversion.plugins.pdb_input import PDBInput +from calibre.ebooks.conversion.plugins.azw4_input import AZW4Input +from calibre.ebooks.conversion.plugins.pdf_input import PDFInput +from calibre.ebooks.conversion.plugins.pml_input import PMLInput +from calibre.ebooks.conversion.plugins.rb_input import RBInput +from calibre.ebooks.conversion.plugins.recipe_input import RecipeInput +from calibre.ebooks.conversion.plugins.rtf_input import RTFInput +from calibre.ebooks.conversion.plugins.tcr_input import TCRInput +from calibre.ebooks.conversion.plugins.txt_input import TXTInput +from calibre.ebooks.conversion.plugins.lrf_input import LRFInput +from calibre.ebooks.conversion.plugins.chm_input import CHMInput +from calibre.ebooks.conversion.plugins.snb_input import SNBInput +from calibre.ebooks.conversion.plugins.docx_input import DOCXInput + +from calibre.ebooks.conversion.plugins.epub_output import EPUBOutput +from calibre.ebooks.conversion.plugins.fb2_output import FB2Output +from calibre.ebooks.conversion.plugins.lit_output import LITOutput +from calibre.ebooks.conversion.plugins.lrf_output import LRFOutput +from calibre.ebooks.conversion.plugins.mobi_output import (MOBIOutput, + AZW3Output) +from calibre.ebooks.conversion.plugins.oeb_output import OEBOutput +from calibre.ebooks.conversion.plugins.pdb_output import PDBOutput +from calibre.ebooks.conversion.plugins.pdf_output import PDFOutput +from calibre.ebooks.conversion.plugins.pml_output import PMLOutput +from calibre.ebooks.conversion.plugins.rb_output import RBOutput +from calibre.ebooks.conversion.plugins.rtf_output import RTFOutput +from calibre.ebooks.conversion.plugins.tcr_output import TCROutput +from calibre.ebooks.conversion.plugins.txt_output import TXTOutput, TXTZOutput +from calibre.ebooks.conversion.plugins.html_output import HTMLOutput +from calibre.ebooks.conversion.plugins.htmlz_output import HTMLZOutput +from calibre.ebooks.conversion.plugins.snb_output import SNBOutput +from calibre.ebooks.conversion.plugins.docx_output import DOCXOutput + +plugins += [ + ComicInput, + DJVUInput, + EPUBInput, + FB2Input, + HTMLInput, + HTMLZInput, + LITInput, + MOBIInput, + ODTInput, + PDBInput, + AZW4Input, + PDFInput, + PMLInput, + RBInput, + RecipeInput, + RTFInput, + TCRInput, + TXTInput, + LRFInput, + CHMInput, + SNBInput, + DOCXInput, +] +plugins += [ + EPUBOutput, + DOCXOutput, + FB2Output, + LITOutput, + LRFOutput, + MOBIOutput, AZW3Output, + OEBOutput, + PDBOutput, + PDFOutput, + PMLOutput, + RBOutput, + RTFOutput, + TCROutput, + TXTOutput, + TXTZOutput, + HTMLOutput, + HTMLZOutput, + SNBOutput, +] +# }}} + +# Catalog plugins {{{ +from calibre.library.catalogs.csv_xml import CSV_XML +from calibre.library.catalogs.bibtex import BIBTEX +from calibre.library.catalogs.epub_mobi import EPUB_MOBI +plugins += [CSV_XML, BIBTEX, EPUB_MOBI] +# }}} + +# Profiles {{{ +from calibre.customize.profiles import input_profiles, output_profiles +plugins += input_profiles + output_profiles +# }}} + +# Device driver plugins {{{ +from calibre.devices.hanlin.driver import HANLINV3, HANLINV5, BOOX, SPECTRA +from calibre.devices.blackberry.driver import BLACKBERRY, PLAYBOOK +from calibre.devices.cybook.driver import CYBOOK, ORIZON, MUSE, DIVA +from calibre.devices.eb600.driver import (EB600, COOL_ER, SHINEBOOK, TOLINO, + POCKETBOOK360, GER2, ITALICA, ECLICTO, DBOOK, INVESBOOK, + BOOQ, ELONEX, POCKETBOOK301, MENTOR, POCKETBOOK602, + POCKETBOOK701, POCKETBOOK740, POCKETBOOK360P, PI2, POCKETBOOK622, + POCKETBOOKHD) +from calibre.devices.iliad.driver import ILIAD +from calibre.devices.irexdr.driver import IREXDR1000, IREXDR800 +from calibre.devices.jetbook.driver import (JETBOOK, MIBUK, JETBOOK_MINI, + JETBOOK_COLOR) +from calibre.devices.kindle.driver import (KINDLE, KINDLE2, KINDLE_DX, + KINDLE_FIRE) +from calibre.devices.nook.driver import NOOK, NOOK_COLOR +from calibre.devices.prs505.driver import PRS505 +from calibre.devices.prst1.driver import PRST1 +from calibre.devices.user_defined.driver import USER_DEFINED +from calibre.devices.android.driver import ANDROID, S60, WEBOS +from calibre.devices.nokia.driver import N770, N810, E71X, E52 +from calibre.devices.eslick.driver import ESLICK, EBK52 +from calibre.devices.nuut2.driver import NUUT2 +from calibre.devices.iriver.driver import IRIVER_STORY +from calibre.devices.binatone.driver import README +from calibre.devices.hanvon.driver import (N516, EB511, ALEX, AZBOOKA, THEBOOK, + LIBREAIR, ODYSSEY, KIBANO) +from calibre.devices.edge.driver import EDGE +from calibre.devices.teclast.driver import (TECLAST_K3, NEWSMY, IPAPYRUS, + SOVOS, PICO, SUNSTECH_EB700, ARCHOS7O, STASH, WEXLER) +from calibre.devices.sne.driver import SNE +from calibre.devices.misc import ( + PALMPRE, AVANT, SWEEX, PDNOVEL, GEMEI, VELOCITYMICRO, PDNOVEL_KOBO, + LUMIREAD, ALURATEK_COLOR, TREKSTOR, EEEREADER, NEXTBOOK, ADAM, MOOVYBOOK, + COBY, EX124G, WAYTEQ, WOXTER, POCKETBOOK626, SONYDPTS1, CERVANTES) +from calibre.devices.folder_device.driver import FOLDER_DEVICE_FOR_CONFIG +from calibre.devices.kobo.driver import KOBO, KOBOTOUCH +from calibre.devices.boeye.driver import BOEYE_BEX, BOEYE_BDX +from calibre.devices.smart_device_app.driver import SMART_DEVICE_APP +from calibre.devices.mtp.driver import MTP_DEVICE + +# Order here matters. The first matched device is the one used. +plugins += [ + HANLINV3, + HANLINV5, + BLACKBERRY, PLAYBOOK, + CYBOOK, ORIZON, MUSE, DIVA, + ILIAD, + IREXDR1000, + IREXDR800, + JETBOOK, JETBOOK_MINI, MIBUK, JETBOOK_COLOR, + SHINEBOOK, + POCKETBOOK360, POCKETBOOK301, POCKETBOOK602, POCKETBOOK701, POCKETBOOK360P, + POCKETBOOK622, PI2, POCKETBOOKHD, POCKETBOOK740, + KINDLE, KINDLE2, KINDLE_DX, KINDLE_FIRE, + NOOK, NOOK_COLOR, + PRS505, PRST1, + ANDROID, S60, WEBOS, + N770, + E71X, + E52, + N810, + COOL_ER, + ESLICK, + EBK52, + NUUT2, + IRIVER_STORY, + GER2, + ITALICA, + ECLICTO, + DBOOK, + INVESBOOK, + BOOX, + BOOQ, + EB600, TOLINO, + README, + N516, KIBANO, + THEBOOK, LIBREAIR, + EB511, + ELONEX, + TECLAST_K3, + NEWSMY, + PICO, SUNSTECH_EB700, ARCHOS7O, SOVOS, STASH, WEXLER, + IPAPYRUS, + EDGE, + SNE, + ALEX, ODYSSEY, + PALMPRE, + KOBO, KOBOTOUCH, + AZBOOKA, + FOLDER_DEVICE_FOR_CONFIG, + AVANT, CERVANTES, + MENTOR, + SWEEX, + PDNOVEL, + SPECTRA, + GEMEI, + VELOCITYMICRO, + PDNOVEL_KOBO, + LUMIREAD, + ALURATEK_COLOR, + TREKSTOR, + EEEREADER, + NEXTBOOK, + ADAM, + MOOVYBOOK, COBY, EX124G, WAYTEQ, WOXTER, POCKETBOOK626, SONYDPTS1, + BOEYE_BEX, + BOEYE_BDX, + MTP_DEVICE, + SMART_DEVICE_APP, + USER_DEFINED, +] + + +# }}} + +# New metadata download plugins {{{ +from calibre.ebooks.metadata.sources.google import GoogleBooks +from calibre.ebooks.metadata.sources.amazon import Amazon +from calibre.ebooks.metadata.sources.edelweiss import Edelweiss +from calibre.ebooks.metadata.sources.openlibrary import OpenLibrary +from calibre.ebooks.metadata.sources.overdrive import OverDrive +from calibre.ebooks.metadata.sources.douban import Douban +from calibre.ebooks.metadata.sources.ozon import Ozon +from calibre.ebooks.metadata.sources.google_images import GoogleImages +from calibre.ebooks.metadata.sources.big_book_search import BigBookSearch + +plugins += [GoogleBooks, GoogleImages, Amazon, Edelweiss, OpenLibrary, OverDrive, Douban, Ozon, BigBookSearch] + +# }}} + +# Interface Actions {{{ + + +class ActionAdd(InterfaceActionBase): + name = 'Add Books' + actual_plugin = 'calibre.gui2.actions.add:AddAction' + description = _('Add books to calibre or the connected device') + + +class ActionFetchAnnotations(InterfaceActionBase): + name = 'Fetch Annotations' + actual_plugin = 'calibre.gui2.actions.annotate:FetchAnnotationsAction' + description = _('Fetch annotations from a connected Kindle (experimental)') + + +class ActionGenerateCatalog(InterfaceActionBase): + name = 'Generate Catalog' + actual_plugin = 'calibre.gui2.actions.catalog:GenerateCatalogAction' + description = _('Generate a catalog of the books in your calibre library') + + +class ActionConvert(InterfaceActionBase): + name = 'Convert Books' + actual_plugin = 'calibre.gui2.actions.convert:ConvertAction' + description = _('Convert books to various e-book formats') + + +class ActionPolish(InterfaceActionBase): + name = 'Polish Books' + actual_plugin = 'calibre.gui2.actions.polish:PolishAction' + description = _('Fine tune your e-books') + + +class ActionEditToC(InterfaceActionBase): + name = 'Edit ToC' + actual_plugin = 'calibre.gui2.actions.toc_edit:ToCEditAction' + description = _('Edit the Table of Contents in your books') + + +class ActionDelete(InterfaceActionBase): + name = 'Remove Books' + actual_plugin = 'calibre.gui2.actions.delete:DeleteAction' + description = _('Delete books from your calibre library or connected device') + + +class ActionEmbed(InterfaceActionBase): + name = 'Embed Metadata' + actual_plugin = 'calibre.gui2.actions.embed:EmbedAction' + description = _('Embed updated metadata into the actual book files in your calibre library') + + +class ActionEditMetadata(InterfaceActionBase): + name = 'Edit Metadata' + actual_plugin = 'calibre.gui2.actions.edit_metadata:EditMetadataAction' + description = _('Edit the metadata of books in your calibre library') + + +class ActionView(InterfaceActionBase): + name = 'View' + actual_plugin = 'calibre.gui2.actions.view:ViewAction' + description = _('Read books in your calibre library') + + +class ActionFetchNews(InterfaceActionBase): + name = 'Fetch News' + actual_plugin = 'calibre.gui2.actions.fetch_news:FetchNewsAction' + description = _('Download news from the internet in e-book form') + + +class ActionQuickview(InterfaceActionBase): + name = 'Quickview' + actual_plugin = 'calibre.gui2.actions.show_quickview:ShowQuickviewAction' + description = _('Show a list of related books quickly') + + +class ActionTagMapper(InterfaceActionBase): + name = 'Tag Mapper' + actual_plugin = 'calibre.gui2.actions.tag_mapper:TagMapAction' + description = _('Filter/transform the tags for books in the library') + + +class ActionAuthorMapper(InterfaceActionBase): + name = 'Author Mapper' + actual_plugin = 'calibre.gui2.actions.author_mapper:AuthorMapAction' + description = _('Transform the authors for books in the library') + + +class ActionTemplateTester(InterfaceActionBase): + name = 'Template Tester' + actual_plugin = 'calibre.gui2.actions.show_template_tester:ShowTemplateTesterAction' + description = _('Show an editor for testing templates') + + +class ActionSaveToDisk(InterfaceActionBase): + name = 'Save To Disk' + actual_plugin = 'calibre.gui2.actions.save_to_disk:SaveToDiskAction' + description = _('Export books from your calibre library to the hard disk') + + +class ActionShowBookDetails(InterfaceActionBase): + name = 'Show Book Details' + actual_plugin = 'calibre.gui2.actions.show_book_details:ShowBookDetailsAction' + description = _('Show Book details in a separate popup') + + +class ActionRestart(InterfaceActionBase): + name = 'Restart' + actual_plugin = 'calibre.gui2.actions.restart:RestartAction' + description = _('Restart calibre') + + +class ActionOpenFolder(InterfaceActionBase): + name = 'Open Folder' + actual_plugin = 'calibre.gui2.actions.open:OpenFolderAction' + description = _('Open the folder that contains the book files in your' + ' calibre library') + + +class ActionSendToDevice(InterfaceActionBase): + name = 'Send To Device' + actual_plugin = 'calibre.gui2.actions.device:SendToDeviceAction' + description = _('Send books to the connected device') + + +class ActionConnectShare(InterfaceActionBase): + name = 'Connect Share' + actual_plugin = 'calibre.gui2.actions.device:ConnectShareAction' + description = _('Send books via email or the web. Also connect to' + ' folders on your computer as if they are devices') + + +class ActionHelp(InterfaceActionBase): + name = 'Help' + actual_plugin = 'calibre.gui2.actions.help:HelpAction' + description = _('Browse the calibre User Manual') + + +class ActionPreferences(InterfaceActionBase): + name = 'Preferences' + actual_plugin = 'calibre.gui2.actions.preferences:PreferencesAction' + description = _('Customize calibre') + + +class ActionSimilarBooks(InterfaceActionBase): + name = 'Similar Books' + actual_plugin = 'calibre.gui2.actions.similar_books:SimilarBooksAction' + description = _('Easily find books similar to the currently selected one') + + +class ActionChooseLibrary(InterfaceActionBase): + name = 'Choose Library' + actual_plugin = 'calibre.gui2.actions.choose_library:ChooseLibraryAction' + description = _('Switch between different calibre libraries and perform' + ' maintenance on them') + + +class ActionAddToLibrary(InterfaceActionBase): + name = 'Add To Library' + actual_plugin = 'calibre.gui2.actions.add_to_library:AddToLibraryAction' + description = _('Copy books from the device to your calibre library') + + +class ActionEditCollections(InterfaceActionBase): + name = 'Edit Collections' + actual_plugin = 'calibre.gui2.actions.edit_collections:EditCollectionsAction' + description = _('Edit the collections in which books are placed on your device') + + +class ActionMatchBooks(InterfaceActionBase): + name = 'Match Books' + actual_plugin = 'calibre.gui2.actions.match_books:MatchBookAction' + description = _('Match book on the devices to books in the library') + + +class ActionCopyToLibrary(InterfaceActionBase): + name = 'Copy To Library' + actual_plugin = 'calibre.gui2.actions.copy_to_library:CopyToLibraryAction' + description = _('Copy a book from one calibre library to another') + + +class ActionTweakEpub(InterfaceActionBase): + name = 'Tweak ePub' + actual_plugin = 'calibre.gui2.actions.tweak_epub:TweakEpubAction' + description = _('Edit e-books in the EPUB or AZW3 formats') + + +class ActionUnpackBook(InterfaceActionBase): + name = 'Unpack Book' + actual_plugin = 'calibre.gui2.actions.unpack_book:UnpackBookAction' + description = _('Make small changes to EPUB or HTMLZ files in your calibre library') + + +class ActionNextMatch(InterfaceActionBase): + name = 'Next Match' + actual_plugin = 'calibre.gui2.actions.next_match:NextMatchAction' + description = _('Find the next or previous match when searching in ' + 'your calibre library in highlight mode') + + +class ActionPickRandom(InterfaceActionBase): + name = 'Pick Random Book' + actual_plugin = 'calibre.gui2.actions.random:PickRandomAction' + description = _('Choose a random book from your calibre library') + + +class ActionSortBy(InterfaceActionBase): + name = 'Sort By' + actual_plugin = 'calibre.gui2.actions.sort:SortByAction' + description = _('Sort the list of books') + + +class ActionMarkBooks(InterfaceActionBase): + name = 'Mark Books' + actual_plugin = 'calibre.gui2.actions.mark_books:MarkBooksAction' + description = _('Temporarily mark books') + + +class ActionVirtualLibrary(InterfaceActionBase): + name = 'Virtual Library' + actual_plugin = 'calibre.gui2.actions.virtual_library:VirtualLibraryAction' + description = _('Change the current Virtual library') + + +class ActionStore(InterfaceActionBase): + name = 'Store' + author = 'John Schember' + actual_plugin = 'calibre.gui2.actions.store:StoreAction' + description = _('Search for books from different book sellers') + + def customization_help(self, gui=False): + return 'Customize the behavior of the store search.' + + def config_widget(self): + from calibre.gui2.store.config.store import config_widget as get_cw + return get_cw() + + def save_settings(self, config_widget): + from calibre.gui2.store.config.store import save_settings as save + save(config_widget) + + +class ActionPluginUpdater(InterfaceActionBase): + name = 'Plugin Updater' + author = 'Grant Drake' + description = _('Get new calibre plugins or update your existing ones') + actual_plugin = 'calibre.gui2.actions.plugin_updates:PluginUpdaterAction' + + +plugins += [ActionAdd, ActionFetchAnnotations, ActionGenerateCatalog, + ActionConvert, ActionDelete, ActionEditMetadata, ActionView, + ActionFetchNews, ActionSaveToDisk, ActionQuickview, ActionPolish, + ActionShowBookDetails,ActionRestart, ActionOpenFolder, ActionConnectShare, + ActionSendToDevice, ActionHelp, ActionPreferences, ActionSimilarBooks, + ActionAddToLibrary, ActionEditCollections, ActionMatchBooks, ActionChooseLibrary, + ActionCopyToLibrary, ActionTweakEpub, ActionUnpackBook, ActionNextMatch, ActionStore, + ActionPluginUpdater, ActionPickRandom, ActionEditToC, ActionSortBy, + ActionMarkBooks, ActionEmbed, ActionTemplateTester, ActionTagMapper, ActionAuthorMapper, + ActionVirtualLibrary] + +# }}} + +# Preferences Plugins {{{ + + +class LookAndFeel(PreferencesPlugin): + name = 'Look & Feel' + icon = I('lookfeel.png') + gui_name = _('Look & feel') + category = 'Interface' + gui_category = _('Interface') + category_order = 1 + name_order = 1 + config_widget = 'calibre.gui2.preferences.look_feel' + description = _('Adjust the look and feel of the calibre interface' + ' to suit your tastes') + + +class Behavior(PreferencesPlugin): + name = 'Behavior' + icon = I('config.png') + gui_name = _('Behavior') + category = 'Interface' + gui_category = _('Interface') + category_order = 1 + name_order = 2 + config_widget = 'calibre.gui2.preferences.behavior' + description = _('Change the way calibre behaves') + + +class Columns(PreferencesPlugin): + name = 'Custom Columns' + icon = I('column.png') + gui_name = _('Add your own columns') + category = 'Interface' + gui_category = _('Interface') + category_order = 1 + name_order = 3 + config_widget = 'calibre.gui2.preferences.columns' + description = _('Add/remove your own columns to the calibre book list') + + +class Toolbar(PreferencesPlugin): + name = 'Toolbar' + icon = I('wizard.png') + gui_name = _('Toolbars & menus') + category = 'Interface' + gui_category = _('Interface') + category_order = 1 + name_order = 4 + config_widget = 'calibre.gui2.preferences.toolbar' + description = _('Customize the toolbars and context menus, changing which' + ' actions are available in each') + + +class Search(PreferencesPlugin): + name = 'Search' + icon = I('search.png') + gui_name = _('Searching') + category = 'Interface' + gui_category = _('Interface') + category_order = 1 + name_order = 5 + config_widget = 'calibre.gui2.preferences.search' + description = _('Customize the way searching for books works in calibre') + + +class InputOptions(PreferencesPlugin): + name = 'Input Options' + icon = I('arrow-down.png') + gui_name = _('Input options') + category = 'Conversion' + gui_category = _('Conversion') + category_order = 2 + name_order = 1 + config_widget = 'calibre.gui2.preferences.conversion:InputOptions' + description = _('Set conversion options specific to each input format') + + def create_widget(self, *args, **kwargs): + # The DOC Input plugin tries to override this + self.config_widget = 'calibre.gui2.preferences.conversion:InputOptions' + return PreferencesPlugin.create_widget(self, *args, **kwargs) + + +class CommonOptions(PreferencesPlugin): + name = 'Common Options' + icon = I('convert.png') + gui_name = _('Common options') + category = 'Conversion' + gui_category = _('Conversion') + category_order = 2 + name_order = 2 + config_widget = 'calibre.gui2.preferences.conversion:CommonOptions' + description = _('Set conversion options common to all formats') + + +class OutputOptions(PreferencesPlugin): + name = 'Output Options' + icon = I('arrow-up.png') + gui_name = _('Output options') + category = 'Conversion' + gui_category = _('Conversion') + category_order = 2 + name_order = 3 + config_widget = 'calibre.gui2.preferences.conversion:OutputOptions' + description = _('Set conversion options specific to each output format') + + +class Adding(PreferencesPlugin): + name = 'Adding' + icon = I('add_book.png') + gui_name = _('Adding books') + category = 'Import/Export' + gui_category = _('Import/export') + category_order = 3 + name_order = 1 + config_widget = 'calibre.gui2.preferences.adding' + description = _('Control how calibre reads metadata from files when ' + 'adding books') + + +class Saving(PreferencesPlugin): + name = 'Saving' + icon = I('save.png') + gui_name = _('Saving books to disk') + category = 'Import/Export' + gui_category = _('Import/export') + category_order = 3 + name_order = 2 + config_widget = 'calibre.gui2.preferences.saving' + description = _('Control how calibre exports files from its database ' + 'to disk when using Save to disk') + + +class Sending(PreferencesPlugin): + name = 'Sending' + icon = I('sync.png') + gui_name = _('Sending books to devices') + category = 'Import/Export' + gui_category = _('Import/export') + category_order = 3 + name_order = 3 + config_widget = 'calibre.gui2.preferences.sending' + description = _('Control how calibre transfers files to your ' + 'e-book reader') + + +class Plugboard(PreferencesPlugin): + name = 'Plugboard' + icon = I('plugboard.png') + gui_name = _('Metadata plugboards') + category = 'Import/Export' + gui_category = _('Import/export') + category_order = 3 + name_order = 4 + config_widget = 'calibre.gui2.preferences.plugboard' + description = _('Change metadata fields before saving/sending') + + +class TemplateFunctions(PreferencesPlugin): + name = 'TemplateFunctions' + icon = I('template_funcs.png') + gui_name = _('Template functions') + category = 'Advanced' + gui_category = _('Advanced') + category_order = 5 + name_order = 5 + config_widget = 'calibre.gui2.preferences.template_functions' + description = _('Create your own template functions') + + +class Email(PreferencesPlugin): + name = 'Email' + icon = I('mail.png') + gui_name = _('Sharing books by email') + category = 'Sharing' + gui_category = _('Sharing') + category_order = 4 + name_order = 1 + config_widget = 'calibre.gui2.preferences.emailp' + description = _('Setup sharing of books via email. Can be used ' + 'for automatic sending of downloaded news to your devices') + + +class Server(PreferencesPlugin): + name = 'Server' + icon = I('network-server.png') + gui_name = _('Sharing over the net') + category = 'Sharing' + gui_category = _('Sharing') + category_order = 4 + name_order = 2 + config_widget = 'calibre.gui2.preferences.server' + description = _('Setup the calibre Content server which will ' + 'give you access to your calibre library from anywhere, ' + 'on any device, over the internet') + + +class MetadataSources(PreferencesPlugin): + name = 'Metadata download' + icon = I('download-metadata.png') + gui_name = _('Metadata download') + category = 'Sharing' + gui_category = _('Sharing') + category_order = 4 + name_order = 3 + config_widget = 'calibre.gui2.preferences.metadata_sources' + description = _('Control how calibre downloads e-book metadata from the net') + + +class IgnoredDevices(PreferencesPlugin): + name = 'Ignored Devices' + icon = I('reader.png') + gui_name = _('Ignored devices') + category = 'Sharing' + gui_category = _('Sharing') + category_order = 4 + name_order = 4 + config_widget = 'calibre.gui2.preferences.ignored_devices' + description = _('Control which devices calibre will ignore when they are connected ' + 'to the computer.') + + +class Plugins(PreferencesPlugin): + name = 'Plugins' + icon = I('plugins.png') + gui_name = _('Plugins') + category = 'Advanced' + gui_category = _('Advanced') + category_order = 5 + name_order = 1 + config_widget = 'calibre.gui2.preferences.plugins' + description = _('Add/remove/customize various bits of calibre ' + 'functionality') + + +class Tweaks(PreferencesPlugin): + name = 'Tweaks' + icon = I('tweaks.png') + gui_name = _('Tweaks') + category = 'Advanced' + gui_category = _('Advanced') + category_order = 5 + name_order = 2 + config_widget = 'calibre.gui2.preferences.tweaks' + description = _('Fine tune how calibre behaves in various contexts') + + +class Keyboard(PreferencesPlugin): + name = 'Keyboard' + icon = I('keyboard-prefs.png') + gui_name = _('Shortcuts') + category = 'Advanced' + gui_category = _('Advanced') + category_order = 5 + name_order = 4 + config_widget = 'calibre.gui2.preferences.keyboard' + description = _('Customize the keyboard shortcuts used by calibre') + + +class Misc(PreferencesPlugin): + name = 'Misc' + icon = I('exec.png') + gui_name = _('Miscellaneous') + category = 'Advanced' + gui_category = _('Advanced') + category_order = 5 + name_order = 3 + config_widget = 'calibre.gui2.preferences.misc' + description = _('Miscellaneous advanced configuration') + + +plugins += [LookAndFeel, Behavior, Columns, Toolbar, Search, InputOptions, + CommonOptions, OutputOptions, Adding, Saving, Sending, Plugboard, + Email, Server, Plugins, Tweaks, Misc, TemplateFunctions, + MetadataSources, Keyboard, IgnoredDevices] + +# }}} + +# Store plugins {{{ + + +class StoreAmazonKindleStore(StoreBase): + name = 'Amazon Kindle' + description = 'Kindle books from Amazon.' + actual_plugin = 'calibre.gui2.store.stores.amazon_plugin:AmazonKindleStore' + + headquarters = 'US' + formats = ['KINDLE'] + affiliate = False + + +class StoreAmazonAUKindleStore(StoreBase): + name = 'Amazon AU Kindle' + author = 'Kovid Goyal' + description = 'Kindle books from Amazon.' + actual_plugin = 'calibre.gui2.store.stores.amazon_au_plugin:AmazonKindleStore' + + headquarters = 'AU' + formats = ['KINDLE'] + + +class StoreAmazonCAKindleStore(StoreBase): + name = 'Amazon CA Kindle' + author = 'Kovid Goyal' + description = 'Kindle books from Amazon.' + actual_plugin = 'calibre.gui2.store.stores.amazon_ca_plugin:AmazonKindleStore' + + headquarters = 'CA' + formats = ['KINDLE'] + + +class StoreAmazonINKindleStore(StoreBase): + name = 'Amazon IN Kindle' + author = 'Kovid Goyal' + description = 'Kindle books from Amazon.' + actual_plugin = 'calibre.gui2.store.stores.amazon_in_plugin:AmazonKindleStore' + + headquarters = 'IN' + formats = ['KINDLE'] + + +class StoreAmazonDEKindleStore(StoreBase): + name = 'Amazon DE Kindle' + author = 'Kovid Goyal' + description = 'Kindle Bücher von Amazon.' + actual_plugin = 'calibre.gui2.store.stores.amazon_de_plugin:AmazonKindleStore' + + headquarters = 'DE' + formats = ['KINDLE'] + + +class StoreAmazonFRKindleStore(StoreBase): + name = 'Amazon FR Kindle' + author = 'Kovid Goyal' + description = 'Tous les e-books Kindle' + actual_plugin = 'calibre.gui2.store.stores.amazon_fr_plugin:AmazonKindleStore' + + headquarters = 'FR' + formats = ['KINDLE'] + + +class StoreAmazonITKindleStore(StoreBase): + name = 'Amazon IT Kindle' + author = 'Kovid Goyal' + description = 'e-book Kindle a prezzi incredibili' + actual_plugin = 'calibre.gui2.store.stores.amazon_it_plugin:AmazonKindleStore' + + headquarters = 'IT' + formats = ['KINDLE'] + + +class StoreAmazonESKindleStore(StoreBase): + name = 'Amazon ES Kindle' + author = 'Kovid Goyal' + description = 'e-book Kindle en España' + actual_plugin = 'calibre.gui2.store.stores.amazon_es_plugin:AmazonKindleStore' + + headquarters = 'ES' + formats = ['KINDLE'] + + +class StoreAmazonUKKindleStore(StoreBase): + name = 'Amazon UK Kindle' + author = 'Kovid Goyal' + description = 'Kindle books from Amazon\'s UK web site. Also, includes French language e-books.' + actual_plugin = 'calibre.gui2.store.stores.amazon_uk_plugin:AmazonKindleStore' + + headquarters = 'UK' + formats = ['KINDLE'] + + +class StoreArchiveOrgStore(StoreBase): + name = 'Archive.org' + description = 'An Internet library offering permanent access for researchers, historians, scholars, people with disabilities, and the general public to historical collections that exist in digital format.' # noqa + actual_plugin = 'calibre.gui2.store.stores.archive_org_plugin:ArchiveOrgStore' + + drm_free_only = True + headquarters = 'US' + formats = ['DAISY', 'DJVU', 'EPUB', 'MOBI', 'PDF', 'TXT'] + + +class StoreBubokPublishingStore(StoreBase): + name = 'Bubok Spain' + description = 'Bubok Publishing is a publisher, library and store of books of authors from all around the world. They have a big amount of books of a lot of topics' # noqa + actual_plugin = 'calibre.gui2.store.stores.bubok_publishing_plugin:BubokPublishingStore' + + drm_free_only = True + headquarters = 'ES' + formats = ['EPUB', 'PDF'] + + +class StoreBubokPortugalStore(StoreBase): + name = 'Bubok Portugal' + description = 'Bubok Publishing Portugal is a publisher, library and store of books of authors from Portugal. They have a big amount of books of a lot of topics' # noqa + actual_plugin = 'calibre.gui2.store.stores.bubok_portugal_plugin:BubokPortugalStore' + + drm_free_only = True + headquarters = 'PT' + formats = ['EPUB', 'PDF'] + + +class StoreBaenWebScriptionStore(StoreBase): + name = 'Baen Ebooks' + description = 'Sci-Fi & Fantasy brought to you by Jim Baen.' + actual_plugin = 'calibre.gui2.store.stores.baen_webscription_plugin:BaenWebScriptionStore' + + drm_free_only = True + headquarters = 'US' + formats = ['EPUB', 'LIT', 'LRF', 'MOBI', 'RB', 'RTF', 'ZIP'] + + +class StoreBNStore(StoreBase): + name = 'Barnes and Noble' + description = 'The world\'s largest book seller. As the ultimate destination for book lovers, Barnes & Noble.com offers an incredible array of content.' + actual_plugin = 'calibre.gui2.store.stores.bn_plugin:BNStore' + + headquarters = 'US' + formats = ['NOOK'] + + +class StoreBeamEBooksDEStore(StoreBase): + name = 'Beam EBooks DE' + author = 'Charles Haley' + description = 'Bei uns finden Sie: Tausende deutschsprachige e-books; Alle e-books ohne hartes DRM; PDF, ePub und Mobipocket Format; Sofortige Verfügbarkeit - 24 Stunden am Tag; Günstige Preise; e-books für viele Lesegeräte, PC,Mac und Smartphones; Viele Gratis e-books' # noqa + actual_plugin = 'calibre.gui2.store.stores.beam_ebooks_de_plugin:BeamEBooksDEStore' + + drm_free_only = True + headquarters = 'DE' + formats = ['EPUB', 'MOBI', 'PDF'] + + +class StoreBiblioStore(StoreBase): + name = 'Библио.бг' + author = 'Alex Stanev' + description = 'Електронна книжарница за книги и списания във формати ePUB и PDF. Част от заглавията са с активна DRM защита.' + actual_plugin = 'calibre.gui2.store.stores.biblio_plugin:BiblioStore' + + headquarters = 'BG' + formats = ['EPUB, PDF'] + + +class StoreChitankaStore(StoreBase): + name = 'Моята библиотека' + author = 'Alex Stanev' + description = 'Независим сайт за DRM свободна литература на български език' + actual_plugin = 'calibre.gui2.store.stores.chitanka_plugin:ChitankaStore' + + drm_free_only = True + headquarters = 'BG' + formats = ['FB2', 'EPUB', 'TXT', 'SFB'] + + +class StoreEbookNLStore(StoreBase): + name = 'eBook.nl' + description = 'De eBookwinkel van Nederland' + actual_plugin = 'calibre.gui2.store.stores.ebook_nl_plugin:EBookNLStore' + + headquarters = 'NL' + formats = ['EPUB', 'PDF'] + affiliate = False + + +class StoreEbookpointStore(StoreBase): + name = 'Ebookpoint' + author = 'Tomasz Długosz' + description = 'E-booki wolne od DRM, 3 formaty w pakiecie, wysyłanie na Kindle' + actual_plugin = 'calibre.gui2.store.stores.ebookpoint_plugin:EbookpointStore' + + drm_free_only = True + headquarters = 'PL' + formats = ['EPUB', 'MOBI', 'PDF'] + affiliate = True + + +class StoreEbookscomStore(StoreBase): + name = 'eBooks.com' + description = 'Sells books in multiple electronic formats in all categories. Technical infrastructure is cutting edge, robust and scalable, with servers in the US and Europe.' # noqa + actual_plugin = 'calibre.gui2.store.stores.ebooks_com_plugin:EbookscomStore' + + headquarters = 'US' + formats = ['EPUB', 'LIT', 'MOBI', 'PDF'] + affiliate = True + + +class StoreEbooksGratuitsStore(StoreBase): + name = 'EbooksGratuits.com' + description = 'Ebooks Libres et Gratuits' + actual_plugin = 'calibre.gui2.store.stores.ebooksgratuits_plugin:EbooksGratuitsStore' + + headquarters = 'FR' + formats = ['EPUB', 'MOBI', 'PDF', 'PDB'] + drm_free_only = True + +# class StoreEBookShoppeUKStore(StoreBase): +# name = 'ebookShoppe UK' +# author = 'Charles Haley' +# description = 'We made this website in an attempt to offer the widest range of UK eBooks possible across and as many formats as we could manage.' +# actual_plugin = 'calibre.gui2.store.stores.ebookshoppe_uk_plugin:EBookShoppeUKStore' +# +# headquarters = 'UK' +# formats = ['EPUB', 'PDF'] +# affiliate = True + + +class StoreEKnigiStore(StoreBase): + name = 'еКниги' + author = 'Alex Stanev' + description = 'Онлайн книжарница за електронни книги и аудио риалити романи' + actual_plugin = 'calibre.gui2.store.stores.eknigi_plugin:eKnigiStore' + + headquarters = 'BG' + formats = ['EPUB', 'PDF', 'HTML'] + affiliate = True + + +class StoreEmpikStore(StoreBase): + name = 'Empik' + author = 'Tomasz Długosz' + description = 'Empik to marka o unikalnym dziedzictwie i legendarne miejsce, dawne “okno na świat”. Jest obecna w polskim krajobrazie kulturalnym od 60 lat (wcześniej jako Kluby Międzynarodowej Prasy i Książki).' # noqa + actual_plugin = 'calibre.gui2.store.stores.empik_plugin:EmpikStore' + + headquarters = 'PL' + formats = ['EPUB', 'MOBI', 'PDF'] + affiliate = True + + +class StoreFeedbooksStore(StoreBase): + name = 'Feedbooks' + description = 'Feedbooks is a cloud publishing and distribution service, connected to a large ecosystem of reading systems and social networks. Provides a variety of genres from independent and classic books.' # noqa + actual_plugin = 'calibre.gui2.store.stores.feedbooks_plugin:FeedbooksStore' + + headquarters = 'FR' + formats = ['EPUB', 'MOBI', 'PDF'] + + +class StoreGoogleBooksStore(StoreBase): + name = 'Google Books' + description = 'Google Books' + actual_plugin = 'calibre.gui2.store.stores.google_books_plugin:GoogleBooksStore' + + headquarters = 'US' + formats = ['EPUB', 'PDF', 'TXT'] + + +class StoreGutenbergStore(StoreBase): + name = 'Project Gutenberg' + description = 'The first producer of free e-books. Free in the United States because their copyright has expired. They may not be free of copyright in other countries. Readers outside of the United States must check the copyright laws of their countries before downloading or redistributing our e-books.' # noqa + actual_plugin = 'calibre.gui2.store.stores.gutenberg_plugin:GutenbergStore' + + drm_free_only = True + headquarters = 'US' + formats = ['EPUB', 'HTML', 'MOBI', 'PDB', 'TXT'] + + +class StoreKoboStore(StoreBase): + name = 'Kobo' + description = 'With over 2.3 million e-books to browse we have engaged readers in over 200 countries in Kobo eReading. Our e-book listings include New York Times Bestsellers, award winners, classics and more!' # noqa + actual_plugin = 'calibre.gui2.store.stores.kobo_plugin:KoboStore' + + headquarters = 'CA' + formats = ['EPUB'] + affiliate = True + + +class StoreLegimiStore(StoreBase): + name = 'Legimi' + author = 'Tomasz Długosz' + description = 'E-booki w formacie EPUB, MOBI i PDF' + actual_plugin = 'calibre.gui2.store.stores.legimi_plugin:LegimiStore' + + headquarters = 'PL' + formats = ['EPUB', 'PDF', 'MOBI'] + affiliate = True + + +class StoreLibreDEStore(StoreBase): + name = 'ebook.de' + author = 'Charles Haley' + description = 'All Ihre Bücher immer dabei. Suchen, finden, kaufen: so einfach wie nie. ebook.de war libre.de' + actual_plugin = 'calibre.gui2.store.stores.libri_de_plugin:LibreDEStore' + + headquarters = 'DE' + formats = ['EPUB', 'PDF'] + affiliate = True + + +class StoreLitResStore(StoreBase): + name = 'LitRes' + description = 'e-books from LitRes.ru' + actual_plugin = 'calibre.gui2.store.stores.litres_plugin:LitResStore' + author = 'Roman Mukhin' + + drm_free_only = False + headquarters = 'RU' + formats = ['EPUB', 'TXT', 'RTF', 'HTML', 'FB2', 'LRF', 'PDF', 'MOBI', 'LIT', 'ISILO3', 'JAR', 'RB', 'PRC'] + affiliate = True + + +class StoreManyBooksStore(StoreBase): + name = 'ManyBooks' + description = 'Public domain and creative commons works from many sources.' + actual_plugin = 'calibre.gui2.store.stores.manybooks_plugin:ManyBooksStore' + + drm_free_only = True + headquarters = 'US' + formats = ['EPUB', 'FB2', 'JAR', 'LIT', 'LRF', 'MOBI', 'PDB', 'PDF', 'RB', 'RTF', 'TCR', 'TXT', 'ZIP'] + + +class StoreMillsBoonUKStore(StoreBase): + name = 'Mills and Boon UK' + author = 'Charles Haley' + description = '"Bring Romance to Life" "[A] hallmark for romantic fiction, recognised around the world."' + actual_plugin = 'calibre.gui2.store.stores.mills_boon_uk_plugin:MillsBoonUKStore' + + headquarters = 'UK' + formats = ['EPUB'] + affiliate = False + + +class StoreMobileReadStore(StoreBase): + name = 'MobileRead' + description = 'E-books handcrafted with the utmost care.' + actual_plugin = 'calibre.gui2.store.stores.mobileread.mobileread_plugin:MobileReadStore' + + drm_free_only = True + headquarters = 'CH' + formats = ['EPUB', 'IMP', 'LRF', 'LIT', 'MOBI', 'PDF'] + + +class StoreNextoStore(StoreBase): + name = 'Nexto' + author = 'Tomasz Długosz' + description = 'Największy w Polsce sklep internetowy z audiobookami mp3, ebookami pdf oraz prasą do pobrania on-line.' + actual_plugin = 'calibre.gui2.store.stores.nexto_plugin:NextoStore' + + headquarters = 'PL' + formats = ['EPUB', 'MOBI', 'PDF'] + affiliate = True + + +class StoreOzonRUStore(StoreBase): + name = 'OZON.ru' + description = 'e-books from OZON.ru' + actual_plugin = 'calibre.gui2.store.stores.ozon_ru_plugin:OzonRUStore' + author = 'Roman Mukhin' + + drm_free_only = True + headquarters = 'RU' + formats = ['TXT', 'PDF', 'DJVU', 'RTF', 'DOC', 'JAR', 'FB2'] + affiliate = True + + +class StorePragmaticBookshelfStore(StoreBase): + name = 'Pragmatic Bookshelf' + description = 'The Pragmatic Bookshelf\'s collection of programming and tech books avaliable as e-books.' + actual_plugin = 'calibre.gui2.store.stores.pragmatic_bookshelf_plugin:PragmaticBookshelfStore' + + drm_free_only = True + headquarters = 'US' + formats = ['EPUB', 'MOBI', 'PDF'] + + +class StorePublioStore(StoreBase): + name = 'Publio' + description = 'Publio.pl to księgarnia internetowa, w której mogą Państwo nabyć e-booki i audiobooki.' + actual_plugin = 'calibre.gui2.store.stores.publio_plugin:PublioStore' + author = 'Tomasz Długosz' + + headquarters = 'PL' + formats = ['EPUB', 'MOBI', 'PDF'] + affiliate = True + + +class StoreRW2010Store(StoreBase): + name = 'RW2010' + description = 'Polski serwis self-publishingowy. Pliki PDF, EPUB i MOBI.' + actual_plugin = 'calibre.gui2.store.stores.rw2010_plugin:RW2010Store' + author = 'Tomasz Długosz' + + drm_free_only = True + headquarters = 'PL' + formats = ['EPUB', 'MOBI', 'PDF'] + + +class StoreSmashwordsStore(StoreBase): + name = 'Smashwords' + description = 'An e-book publishing and distribution platform for e-book authors, publishers and readers. Covers many genres and formats.' + actual_plugin = 'calibre.gui2.store.stores.smashwords_plugin:SmashwordsStore' + + drm_free_only = True + headquarters = 'US' + formats = ['EPUB', 'HTML', 'LRF', 'MOBI', 'PDB', 'RTF', 'TXT'] + affiliate = True + + +class StoreSwiatEbookowStore(StoreBase): + name = 'Świat Ebooków' + author = 'Tomasz Długosz' + description = 'Ebooki maje tę zaletę, że są zawsze i wszędzie tam, gdzie tylko nas dopadnie ochota na czytanie.' + actual_plugin = 'calibre.gui2.store.stores.swiatebookow_plugin:SwiatEbookowStore' + + drm_free_only = True + headquarters = 'PL' + formats = ['EPUB', 'MOBI', 'PDF'] + affiliate = True + + +class StoreVirtualoStore(StoreBase): + name = 'Virtualo' + author = 'Tomasz Długosz' + description = 'Księgarnia internetowa, która oferuje bezpieczny i szeroki dostęp do książek w formie cyfrowej.' + actual_plugin = 'calibre.gui2.store.stores.virtualo_plugin:VirtualoStore' + + headquarters = 'PL' + formats = ['EPUB', 'MOBI', 'PDF'] + affiliate = True + + +class StoreWeightlessBooksStore(StoreBase): + name = 'Weightless Books' + description = 'An independent DRM-free e-book site devoted to e-books of all sorts.' + actual_plugin = 'calibre.gui2.store.stores.weightless_books_plugin:WeightlessBooksStore' + + drm_free_only = True + headquarters = 'US' + formats = ['EPUB', 'HTML', 'LIT', 'MOBI', 'PDF'] + + +class StoreWHSmithUKStore(StoreBase): + name = 'WH Smith UK' + author = 'Charles Haley' + description = u"Shop for savings on Books, discounted Magazine subscriptions and great prices on Stationery, Toys & Games" + actual_plugin = 'calibre.gui2.store.stores.whsmith_uk_plugin:WHSmithUKStore' + + headquarters = 'UK' + formats = ['EPUB', 'PDF'] + + +class StoreWolneLekturyStore(StoreBase): + name = 'Wolne Lektury' + author = 'Tomasz Długosz' + description = 'Wolne Lektury to biblioteka internetowa czynna 24 godziny na dobę, 365 dni w roku, której zasoby dostępne są całkowicie za darmo. Wszystkie dzieła są odpowiednio opracowane - opatrzone przypisami, motywami i udostępnione w kilku formatach - HTML, TXT, PDF, EPUB, MOBI, FB2.' # noqa + actual_plugin = 'calibre.gui2.store.stores.wolnelektury_plugin:WolneLekturyStore' + + headquarters = 'PL' + formats = ['EPUB', 'MOBI', 'PDF', 'TXT', 'FB2'] + + +class StoreWoblinkStore(StoreBase): + name = 'Woblink' + author = 'Tomasz Długosz' + description = 'Czytanie zdarza się wszędzie!' + actual_plugin = 'calibre.gui2.store.stores.woblink_plugin:WoblinkStore' + + headquarters = 'PL' + formats = ['EPUB', 'MOBI', 'PDF', 'WOBLINK'] + affiliate = True + + +class XinXiiStore(StoreBase): + name = 'XinXii' + description = '' + actual_plugin = 'calibre.gui2.store.stores.xinxii_plugin:XinXiiStore' + + headquarters = 'DE' + formats = ['EPUB', 'PDF'] + + +plugins += [ + StoreArchiveOrgStore, + StoreBubokPublishingStore, + StoreBubokPortugalStore, + StoreAmazonKindleStore, + StoreAmazonAUKindleStore, + StoreAmazonCAKindleStore, + StoreAmazonINKindleStore, + StoreAmazonDEKindleStore, + StoreAmazonESKindleStore, + StoreAmazonFRKindleStore, + StoreAmazonITKindleStore, + StoreAmazonUKKindleStore, + StoreBaenWebScriptionStore, + StoreBNStore, + StoreBeamEBooksDEStore, + StoreBiblioStore, + StoreChitankaStore, + StoreEbookNLStore, + StoreEbookpointStore, + StoreEbookscomStore, + StoreEbooksGratuitsStore, + StoreEKnigiStore, + StoreEmpikStore, + StoreFeedbooksStore, + StoreGoogleBooksStore, + StoreGutenbergStore, + StoreKoboStore, + StoreLegimiStore, + StoreLibreDEStore, + StoreLitResStore, + StoreManyBooksStore, + StoreMillsBoonUKStore, + StoreMobileReadStore, + StoreNextoStore, + StoreOzonRUStore, + StorePragmaticBookshelfStore, + StorePublioStore, + StoreRW2010Store, + StoreSmashwordsStore, + StoreSwiatEbookowStore, + StoreVirtualoStore, + StoreWeightlessBooksStore, + StoreWHSmithUKStore, + StoreWolneLekturyStore, + StoreWoblinkStore, + XinXiiStore +] + +# }}} + +if __name__ == '__main__': + # Test load speed + import subprocess, textwrap + try: + subprocess.check_call(['python', '-c', textwrap.dedent( + ''' + import init_calibre # noqa + + def doit(): + import calibre.customize.builtins as b # noqa + + def show_stats(): + from pstats import Stats + s = Stats('/tmp/calibre_stats') + s.sort_stats('cumulative') + s.print_stats(30) + + import cProfile + cProfile.run('doit()', '/tmp/calibre_stats') + show_stats() + + ''' + )]) + except subprocess.CalledProcessError: + raise SystemExit(1) + try: + subprocess.check_call(['python', '-c', textwrap.dedent( + ''' + from __future__ import print_function + import time, sys, init_calibre + st = time.time() + import calibre.customize.builtins + t = time.time() - st + ret = 0 + + for x in ('lxml', 'calibre.ebooks.BeautifulSoup', 'uuid', + 'calibre.utils.terminal', 'calibre.utils.img', 'PIL', 'Image', + 'sqlite3', 'mechanize', 'httplib', 'xml', 'inspect', 'urllib', + 'calibre.utils.date', 'calibre.utils.config', 'platform', + 'calibre.utils.zipfile', 'calibre.utils.formatter', + ): + if x in sys.modules: + ret = 1 + print (x, 'has been loaded by a plugin') + if ret: + print ('\\nA good way to track down what is loading something is to run' + ' python -c "import init_calibre; import calibre.customize.builtins"') + print() + print ('Time taken to import all plugins: %.2f'%t) + sys.exit(ret) + + ''')]) + except subprocess.CalledProcessError: + raise SystemExit(1) diff --git a/ebook_converter/customize/conversion.py b/ebook_converter/customize/conversion.py new file mode 100644 index 0000000..ba8112f --- /dev/null +++ b/ebook_converter/customize/conversion.py @@ -0,0 +1,376 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals +''' +Defines the plugin system for conversions. +''' +import re, os, shutil, numbers + +from calibre import CurrentDir +from calibre.customize import Plugin +from polyglot.builtins import unicode_type + + +class ConversionOption(object): + + ''' + Class representing conversion options + ''' + + def __init__(self, name=None, help=None, long_switch=None, + short_switch=None, choices=None): + self.name = name + self.help = help + self.long_switch = long_switch + self.short_switch = short_switch + self.choices = choices + + if self.long_switch is None: + self.long_switch = self.name.replace('_', '-') + + self.validate_parameters() + + def validate_parameters(self): + ''' + Validate the parameters passed to :meth:`__init__`. + ''' + if re.match(r'[a-zA-Z_]([a-zA-Z0-9_])*', self.name) is None: + raise ValueError(self.name + ' is not a valid Python identifier') + if not self.help: + raise ValueError('You must set the help text') + + def __hash__(self): + return hash(self.name) + + def __eq__(self, other): + return self.name == getattr(other, 'name', other) + + def clone(self): + return ConversionOption(name=self.name, help=self.help, + long_switch=self.long_switch, short_switch=self.short_switch, + choices=self.choices) + + +class OptionRecommendation(object): + LOW = 1 + MED = 2 + HIGH = 3 + + def __init__(self, recommended_value=None, level=LOW, **kwargs): + ''' + An option recommendation. That is, an option as well as its recommended + value and the level of the recommendation. + ''' + self.level = level + self.recommended_value = recommended_value + self.option = kwargs.pop('option', None) + if self.option is None: + self.option = ConversionOption(**kwargs) + + self.validate_parameters() + + @property + def help(self): + return self.option.help + + def clone(self): + return OptionRecommendation(recommended_value=self.recommended_value, + level=self.level, option=self.option.clone()) + + def validate_parameters(self): + if self.option.choices and self.recommended_value not in \ + self.option.choices: + raise ValueError('OpRec: %s: Recommended value not in choices'% + self.option.name) + if not (isinstance(self.recommended_value, (numbers.Number, bytes, unicode_type)) or self.recommended_value is None): + raise ValueError('OpRec: %s:'%self.option.name + repr( + self.recommended_value) + ' is not a string or a number') + + +class DummyReporter(object): + + def __init__(self): + self.cancel_requested = False + + def __call__(self, percent, msg=''): + pass + + +def gui_configuration_widget(name, parent, get_option_by_name, + get_option_help, db, book_id, for_output=True): + import importlib + + def widget_factory(cls): + return cls(parent, get_option_by_name, + get_option_help, db, book_id) + + if for_output: + try: + output_widget = importlib.import_module( + 'calibre.gui2.convert.'+name) + pw = output_widget.PluginWidget + pw.ICON = I('back.png') + pw.HELP = _('Options specific to the output format.') + return widget_factory(pw) + except ImportError: + pass + else: + try: + input_widget = importlib.import_module( + 'calibre.gui2.convert.'+name) + pw = input_widget.PluginWidget + pw.ICON = I('forward.png') + pw.HELP = _('Options specific to the input format.') + return widget_factory(pw) + except ImportError: + pass + return None + + +class InputFormatPlugin(Plugin): + + ''' + InputFormatPlugins are responsible for converting a document into + HTML+OPF+CSS+etc. + The results of the conversion *must* be encoded in UTF-8. + The main action happens in :meth:`convert`. + ''' + + type = _('Conversion input') + can_be_disabled = False + supported_platforms = ['windows', 'osx', 'linux'] + commit_name = None # unique name under which options for this plugin are saved + ui_data = None + + #: Set of file types for which this plugin should be run + #: For example: ``set(['azw', 'mobi', 'prc'])`` + file_types = set() + + #: If True, this input plugin generates a collection of images, + #: one per HTML file. This can be set dynamically, in the convert method + #: if the input files can be both image collections and non-image collections. + #: If you set this to True, you must implement the get_images() method that returns + #: a list of images. + is_image_collection = False + + #: Number of CPU cores used by this plugin. + #: A value of -1 means that it uses all available cores + core_usage = 1 + + #: If set to True, the input plugin will perform special processing + #: to make its output suitable for viewing + for_viewer = False + + #: The encoding that this input plugin creates files in. A value of + #: None means that the encoding is undefined and must be + #: detected individually + output_encoding = 'utf-8' + + #: Options shared by all Input format plugins. Do not override + #: in sub-classes. Use :attr:`options` instead. Every option must be an + #: instance of :class:`OptionRecommendation`. + common_options = { + OptionRecommendation(name='input_encoding', + recommended_value=None, level=OptionRecommendation.LOW, + help=_('Specify the character encoding of the input document. If ' + 'set this option will override any encoding declared by the ' + 'document itself. Particularly useful for documents that ' + 'do not declare an encoding or that have erroneous ' + 'encoding declarations.') + )} + + #: Options to customize the behavior of this plugin. Every option must be an + #: instance of :class:`OptionRecommendation`. + options = set() + + #: A set of 3-tuples of the form + #: (option_name, recommended_value, recommendation_level) + recommendations = set() + + def __init__(self, *args): + Plugin.__init__(self, *args) + self.report_progress = DummyReporter() + + def get_images(self): + ''' + Return a list of absolute paths to the images, if this input plugin + represents an image collection. The list of images is in the same order + as the spine and the TOC. + ''' + raise NotImplementedError() + + def convert(self, stream, options, file_ext, log, accelerators): + ''' + This method must be implemented in sub-classes. It must return + the path to the created OPF file or an :class:`OEBBook` instance. + All output should be contained in the current directory. + If this plugin creates files outside the current + directory they must be deleted/marked for deletion before this method + returns. + + :param stream: A file like object that contains the input file. + :param options: Options to customize the conversion process. + Guaranteed to have attributes corresponding + to all the options declared by this plugin. In + addition, it will have a verbose attribute that + takes integral values from zero upwards. Higher numbers + mean be more verbose. Another useful attribute is + ``input_profile`` that is an instance of + :class:`calibre.customize.profiles.InputProfile`. + :param file_ext: The extension (without the .) of the input file. It + is guaranteed to be one of the `file_types` supported + by this plugin. + :param log: A :class:`calibre.utils.logging.Log` object. All output + should use this object. + :param accelarators: A dictionary of various information that the input + plugin can get easily that would speed up the + subsequent stages of the conversion. + + ''' + raise NotImplementedError() + + def __call__(self, stream, options, file_ext, log, + accelerators, output_dir): + try: + log('InputFormatPlugin: %s running'%self.name) + if hasattr(stream, 'name'): + log('on', stream.name) + except: + # In case stdout is broken + pass + + with CurrentDir(output_dir): + for x in os.listdir('.'): + shutil.rmtree(x) if os.path.isdir(x) else os.remove(x) + + ret = self.convert(stream, options, file_ext, + log, accelerators) + + return ret + + def postprocess_book(self, oeb, opts, log): + ''' + Called to allow the input plugin to perform postprocessing after + the book has been parsed. + ''' + pass + + def specialize(self, oeb, opts, log, output_fmt): + ''' + Called to allow the input plugin to specialize the parsed book + for a particular output format. Called after postprocess_book + and before any transforms are performed on the parsed book. + ''' + pass + + def gui_configuration_widget(self, parent, get_option_by_name, + get_option_help, db, book_id=None): + ''' + Called to create the widget used for configuring this plugin in the + calibre GUI. The widget must be an instance of the PluginWidget class. + See the builtin input plugins for examples. + ''' + name = self.name.lower().replace(' ', '_') + return gui_configuration_widget(name, parent, get_option_by_name, + get_option_help, db, book_id, for_output=False) + + +class OutputFormatPlugin(Plugin): + + ''' + OutputFormatPlugins are responsible for converting an OEB document + (OPF+HTML) into an output e-book. + + The OEB document can be assumed to be encoded in UTF-8. + The main action happens in :meth:`convert`. + ''' + + type = _('Conversion output') + can_be_disabled = False + supported_platforms = ['windows', 'osx', 'linux'] + commit_name = None # unique name under which options for this plugin are saved + ui_data = None + + #: The file type (extension without leading period) that this + #: plugin outputs + file_type = None + + #: Options shared by all Input format plugins. Do not override + #: in sub-classes. Use :attr:`options` instead. Every option must be an + #: instance of :class:`OptionRecommendation`. + common_options = { + OptionRecommendation(name='pretty_print', + recommended_value=False, level=OptionRecommendation.LOW, + help=_('If specified, the output plugin will try to create output ' + 'that is as human readable as possible. May not have any effect ' + 'for some output plugins.') + )} + + #: Options to customize the behavior of this plugin. Every option must be an + #: instance of :class:`OptionRecommendation`. + options = set() + + #: A set of 3-tuples of the form + #: (option_name, recommended_value, recommendation_level) + recommendations = set() + + @property + def description(self): + return _('Convert e-books to the %s format')%self.file_type + + def __init__(self, *args): + Plugin.__init__(self, *args) + self.report_progress = DummyReporter() + + def convert(self, oeb_book, output, input_plugin, opts, log): + ''' + Render the contents of `oeb_book` (which is an instance of + :class:`calibre.ebooks.oeb.OEBBook`) to the file specified by output. + + :param output: Either a file like object or a string. If it is a string + it is the path to a directory that may or may not exist. The output + plugin should write its output into that directory. If it is a file like + object, the output plugin should write its output into the file. + :param input_plugin: The input plugin that was used at the beginning of + the conversion pipeline. + :param opts: Conversion options. Guaranteed to have attributes + corresponding to the OptionRecommendations of this plugin. + :param log: The logger. Print debug/info messages etc. using this. + + ''' + raise NotImplementedError() + + @property + def is_periodical(self): + return self.oeb.metadata.publication_type and \ + unicode_type(self.oeb.metadata.publication_type[0]).startswith('periodical:') + + def specialize_options(self, log, opts, input_fmt): + ''' + Can be used to change the values of conversion options, as used by the + conversion pipeline. + ''' + pass + + def specialize_css_for_output(self, log, opts, item, stylizer): + ''' + Can be used to make changes to the css during the CSS flattening + process. + + :param item: The item (HTML file) being processed + :param stylizer: A Stylizer object containing the flattened styles for + item. You can get the style for any element by + stylizer.style(element). + + ''' + pass + + def gui_configuration_widget(self, parent, get_option_by_name, + get_option_help, db, book_id=None): + ''' + Called to create the widget used for configuring this plugin in the + calibre GUI. The widget must be an instance of the PluginWidget class. + See the builtin output plugins for examples. + ''' + name = self.name.lower().replace(' ', '_') + return gui_configuration_widget(name, parent, get_option_by_name, + get_option_help, db, book_id, for_output=True) diff --git a/ebook_converter/customize/profiles.py b/ebook_converter/customize/profiles.py new file mode 100644 index 0000000..0bc7892 --- /dev/null +++ b/ebook_converter/customize/profiles.py @@ -0,0 +1,873 @@ +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals +__license__ = 'GPL 3' +__copyright__ = '2009, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +from calibre.customize import Plugin as _Plugin +from polyglot.builtins import zip + +FONT_SIZES = [('xx-small', 1), + ('x-small', None), + ('small', 2), + ('medium', 3), + ('large', 4), + ('x-large', 5), + ('xx-large', 6), + (None, 7)] + + +class Plugin(_Plugin): + + fbase = 12 + fsizes = [5, 7, 9, 12, 13.5, 17, 20, 22, 24] + screen_size = (1600, 1200) + dpi = 100 + + def __init__(self, *args, **kwargs): + _Plugin.__init__(self, *args, **kwargs) + self.width, self.height = self.screen_size + fsizes = list(self.fsizes) + self.fkey = list(self.fsizes) + self.fsizes = [] + for (name, num), size in zip(FONT_SIZES, fsizes): + self.fsizes.append((name, num, float(size))) + self.fnames = dict((name, sz) for name, _, sz in self.fsizes if name) + self.fnums = dict((num, sz) for _, num, sz in self.fsizes if num) + self.width_pts = self.width * 72./self.dpi + self.height_pts = self.height * 72./self.dpi + +# Input profiles {{{ + + +class InputProfile(Plugin): + + author = 'Kovid Goyal' + supported_platforms = {'windows', 'osx', 'linux'} + can_be_disabled = False + type = _('Input profile') + + name = 'Default Input Profile' + short_name = 'default' # Used in the CLI so dont use spaces etc. in it + description = _('This profile tries to provide sane defaults and is useful ' + 'if you know nothing about the input document.') + + +class SonyReaderInput(InputProfile): + + name = 'Sony Reader' + short_name = 'sony' + description = _('This profile is intended for the SONY PRS line. ' + 'The 500/505/600/700 etc.') + + screen_size = (584, 754) + dpi = 168.451 + fbase = 12 + fsizes = [7.5, 9, 10, 12, 15.5, 20, 22, 24] + + +class SonyReader300Input(SonyReaderInput): + + name = 'Sony Reader 300' + short_name = 'sony300' + description = _('This profile is intended for the SONY PRS 300.') + + dpi = 200 + + +class SonyReader900Input(SonyReaderInput): + + author = 'John Schember' + name = 'Sony Reader 900' + short_name = 'sony900' + description = _('This profile is intended for the SONY PRS-900.') + + screen_size = (584, 978) + + +class MSReaderInput(InputProfile): + + name = 'Microsoft Reader' + short_name = 'msreader' + description = _('This profile is intended for the Microsoft Reader.') + + screen_size = (480, 652) + dpi = 96 + fbase = 13 + fsizes = [10, 11, 13, 16, 18, 20, 22, 26] + + +class MobipocketInput(InputProfile): + + name = 'Mobipocket Books' + short_name = 'mobipocket' + description = _('This profile is intended for the Mobipocket books.') + + # Unfortunately MOBI books are not narrowly targeted, so this information is + # quite likely to be spurious + screen_size = (600, 800) + dpi = 96 + fbase = 18 + fsizes = [14, 14, 16, 18, 20, 22, 24, 26] + + +class HanlinV3Input(InputProfile): + + name = 'Hanlin V3' + short_name = 'hanlinv3' + description = _('This profile is intended for the Hanlin V3 and its clones.') + + # Screen size is a best guess + screen_size = (584, 754) + dpi = 168.451 + fbase = 16 + fsizes = [12, 12, 14, 16, 18, 20, 22, 24] + + +class HanlinV5Input(HanlinV3Input): + + name = 'Hanlin V5' + short_name = 'hanlinv5' + description = _('This profile is intended for the Hanlin V5 and its clones.') + + # Screen size is a best guess + screen_size = (584, 754) + dpi = 200 + + +class CybookG3Input(InputProfile): + + name = 'Cybook G3' + short_name = 'cybookg3' + description = _('This profile is intended for the Cybook G3.') + + # Screen size is a best guess + screen_size = (600, 800) + dpi = 168.451 + fbase = 16 + fsizes = [12, 12, 14, 16, 18, 20, 22, 24] + + +class CybookOpusInput(InputProfile): + + author = 'John Schember' + name = 'Cybook Opus' + short_name = 'cybook_opus' + description = _('This profile is intended for the Cybook Opus.') + + # Screen size is a best guess + screen_size = (600, 800) + dpi = 200 + fbase = 16 + fsizes = [12, 12, 14, 16, 18, 20, 22, 24] + + +class KindleInput(InputProfile): + + name = 'Kindle' + short_name = 'kindle' + description = _('This profile is intended for the Amazon Kindle.') + + # Screen size is a best guess + screen_size = (525, 640) + dpi = 168.451 + fbase = 16 + fsizes = [12, 12, 14, 16, 18, 20, 22, 24] + + +class IlliadInput(InputProfile): + + name = 'Illiad' + short_name = 'illiad' + description = _('This profile is intended for the Irex Illiad.') + + screen_size = (760, 925) + dpi = 160.0 + fbase = 12 + fsizes = [7.5, 9, 10, 12, 15.5, 20, 22, 24] + + +class IRexDR1000Input(InputProfile): + + author = 'John Schember' + name = 'IRex Digital Reader 1000' + short_name = 'irexdr1000' + description = _('This profile is intended for the IRex Digital Reader 1000.') + + # Screen size is a best guess + screen_size = (1024, 1280) + dpi = 160 + fbase = 16 + fsizes = [12, 14, 16, 18, 20, 22, 24] + + +class IRexDR800Input(InputProfile): + + author = 'Eric Cronin' + name = 'IRex Digital Reader 800' + short_name = 'irexdr800' + description = _('This profile is intended for the IRex Digital Reader 800.') + + screen_size = (768, 1024) + dpi = 160 + fbase = 16 + fsizes = [12, 14, 16, 18, 20, 22, 24] + + +class NookInput(InputProfile): + + author = 'John Schember' + name = 'Nook' + short_name = 'nook' + description = _('This profile is intended for the B&N Nook.') + + # Screen size is a best guess + screen_size = (600, 800) + dpi = 167 + fbase = 16 + fsizes = [12, 12, 14, 16, 18, 20, 22, 24] + + +input_profiles = [InputProfile, SonyReaderInput, SonyReader300Input, + SonyReader900Input, MSReaderInput, MobipocketInput, HanlinV3Input, + HanlinV5Input, CybookG3Input, CybookOpusInput, KindleInput, IlliadInput, + IRexDR1000Input, IRexDR800Input, NookInput] + +input_profiles.sort(key=lambda x: x.name.lower()) + +# }}} + + +class OutputProfile(Plugin): + + author = 'Kovid Goyal' + supported_platforms = {'windows', 'osx', 'linux'} + can_be_disabled = False + type = _('Output profile') + + name = 'Default Output Profile' + short_name = 'default' # Used in the CLI so dont use spaces etc. in it + description = _('This profile tries to provide sane defaults and is useful ' + 'if you want to produce a document intended to be read at a ' + 'computer or on a range of devices.') + + #: The image size for comics + comic_screen_size = (584, 754) + + #: If True the MOBI renderer on the device supports MOBI indexing + supports_mobi_indexing = False + + #: If True output should be optimized for a touchscreen interface + touchscreen = False + touchscreen_news_css = '' + #: A list of extra (beyond CSS 2.1) modules supported by the device + #: Format is a css_parser profile dictionary (see iPad for example) + extra_css_modules = [] + #: If True, the date is appended to the title of downloaded news + periodical_date_in_title = True + + #: Characters used in jackets and catalogs + ratings_char = '*' + empty_ratings_char = ' ' + + #: Unsupported unicode characters to be replaced during preprocessing + unsupported_unicode_chars = [] + + #: Number of ems that the left margin of a blockquote is rendered as + mobi_ems_per_blockquote = 1.0 + + #: Special periodical formatting needed in EPUB + epub_periodical_format = None + + +class iPadOutput(OutputProfile): + + name = 'iPad' + short_name = 'ipad' + description = _('Intended for the iPad and similar devices with a ' + 'resolution of 768x1024') + screen_size = (768, 1024) + comic_screen_size = (768, 1024) + dpi = 132.0 + extra_css_modules = [ + { + 'name':'webkit', + 'props': {'-webkit-border-bottom-left-radius':'{length}', + '-webkit-border-bottom-right-radius':'{length}', + '-webkit-border-top-left-radius':'{length}', + '-webkit-border-top-right-radius':'{length}', + '-webkit-border-radius': r'{border-width}(\s+{border-width}){0,3}|inherit', + }, + 'macros': {'border-width': '{length}|medium|thick|thin'} + } + ] + + ratings_char = '\u2605' # filled star + empty_ratings_char = '\u2606' # hollow star + + touchscreen = True + # touchscreen_news_css {{{ + touchscreen_news_css = ''' + /* hr used in articles */ + .article_articles_list { + width:18%; + } + .article_link { + color: #593f29; + font-style: italic; + } + .article_next { + -webkit-border-top-right-radius:4px; + -webkit-border-bottom-right-radius:4px; + font-style: italic; + width:32%; + } + + .article_prev { + -webkit-border-top-left-radius:4px; + -webkit-border-bottom-left-radius:4px; + font-style: italic; + width:32%; + } + .article_sections_list { + width:18%; + } + .articles_link { + font-weight: bold; + } + .sections_link { + font-weight: bold; + } + + + .caption_divider { + border:#ccc 1px solid; + } + + .touchscreen_navbar { + background:#c3bab2; + border:#ccc 0px solid; + border-collapse:separate; + border-spacing:1px; + margin-left: 5%; + margin-right: 5%; + page-break-inside:avoid; + width: 90%; + -webkit-border-radius:4px; + } + .touchscreen_navbar td { + background:#fff; + font-family:Helvetica; + font-size:80%; + /* UI touchboxes use 8px padding */ + padding: 6px; + text-align:center; + } + + .touchscreen_navbar td a:link { + color: #593f29; + text-decoration: none; + } + + /* Index formatting */ + .publish_date { + text-align:center; + } + .divider { + border-bottom:1em solid white; + border-top:1px solid gray; + } + + hr.caption_divider { + border-color:black; + border-style:solid; + border-width:1px; + } + + /* Feed summary formatting */ + .article_summary { + display:inline-block; + padding-bottom:0.5em; + } + .feed { + font-family:sans-serif; + font-weight:bold; + font-size:larger; + } + + .feed_link { + font-style: italic; + } + + .feed_next { + -webkit-border-top-right-radius:4px; + -webkit-border-bottom-right-radius:4px; + font-style: italic; + width:40%; + } + + .feed_prev { + -webkit-border-top-left-radius:4px; + -webkit-border-bottom-left-radius:4px; + font-style: italic; + width:40%; + } + + .feed_title { + text-align: center; + font-size: 160%; + } + + .feed_up { + font-weight: bold; + width:20%; + } + + .summary_headline { + font-weight:bold; + text-align:left; + } + + .summary_byline { + text-align:left; + font-family:monospace; + } + + .summary_text { + text-align:left; + } + + ''' + # }}} + + +class iPad3Output(iPadOutput): + + screen_size = comic_screen_size = (2048, 1536) + dpi = 264.0 + name = 'iPad 3' + short_name = 'ipad3' + description = _('Intended for the iPad 3 and similar devices with a ' + 'resolution of 1536x2048') + + +class TabletOutput(iPadOutput): + name = 'Tablet' + short_name = 'tablet' + description = _('Intended for generic tablet devices, does no resizing of images') + + screen_size = (10000, 10000) + comic_screen_size = (10000, 10000) + + +class SamsungGalaxy(TabletOutput): + name = 'Samsung Galaxy' + short_name = 'galaxy' + description = _('Intended for the Samsung Galaxy and similar tablet devices with ' + 'a resolution of 600x1280') + screen_size = comic_screen_size = (600, 1280) + + +class NookHD(TabletOutput): + name = 'Nook HD+' + short_name = 'nook_hd_plus' + description = _('Intended for the Nook HD+ and similar tablet devices with ' + 'a resolution of 1280x1920') + screen_size = comic_screen_size = (1280, 1920) + + +class SonyReaderOutput(OutputProfile): + + name = 'Sony Reader' + short_name = 'sony' + description = _('This profile is intended for the SONY PRS line. ' + 'The 500/505/600/700 etc.') + + screen_size = (590, 775) + dpi = 168.451 + fbase = 12 + fsizes = [7.5, 9, 10, 12, 15.5, 20, 22, 24] + unsupported_unicode_chars = [u'\u201f', u'\u201b'] + + epub_periodical_format = 'sony' + # periodical_date_in_title = False + + +class KoboReaderOutput(OutputProfile): + + name = 'Kobo Reader' + short_name = 'kobo' + + description = _('This profile is intended for the Kobo Reader.') + + screen_size = (536, 710) + comic_screen_size = (536, 710) + dpi = 168.451 + fbase = 12 + fsizes = [7.5, 9, 10, 12, 15.5, 20, 22, 24] + + +class SonyReader300Output(SonyReaderOutput): + + author = 'John Schember' + name = 'Sony Reader 300' + short_name = 'sony300' + description = _('This profile is intended for the SONY PRS-300.') + + dpi = 200 + + +class SonyReader900Output(SonyReaderOutput): + + author = 'John Schember' + name = 'Sony Reader 900' + short_name = 'sony900' + description = _('This profile is intended for the SONY PRS-900.') + + screen_size = (600, 999) + comic_screen_size = screen_size + + +class SonyReaderT3Output(SonyReaderOutput): + + author = 'Kovid Goyal' + name = 'Sony Reader T3' + short_name = 'sonyt3' + description = _('This profile is intended for the SONY PRS-T3.') + + screen_size = (758, 934) + comic_screen_size = screen_size + + +class GenericEink(SonyReaderOutput): + + name = 'Generic e-ink' + short_name = 'generic_eink' + description = _('Suitable for use with any e-ink device') + epub_periodical_format = None + + +class GenericEinkLarge(GenericEink): + + name = 'Generic e-ink large' + short_name = 'generic_eink_large' + description = _('Suitable for use with any large screen e-ink device') + + screen_size = (600, 999) + comic_screen_size = screen_size + + +class GenericEinkHD(GenericEink): + + name = 'Generic e-ink HD' + short_name = 'generic_eink_hd' + description = _('Suitable for use with any modern high resolution e-ink device') + + screen_size = (10000, 10000) + comic_screen_size = (10000, 10000) + + +class JetBook5Output(OutputProfile): + + name = 'JetBook 5-inch' + short_name = 'jetbook5' + description = _('This profile is intended for the 5-inch JetBook.') + + screen_size = (480, 640) + dpi = 168.451 + + +class SonyReaderLandscapeOutput(SonyReaderOutput): + + name = 'Sony Reader Landscape' + short_name = 'sony-landscape' + description = _('This profile is intended for the SONY PRS line. ' + 'The 500/505/700 etc, in landscape mode. Mainly useful ' + 'for comics.') + + screen_size = (784, 1012) + comic_screen_size = (784, 1012) + + +class MSReaderOutput(OutputProfile): + + name = 'Microsoft Reader' + short_name = 'msreader' + description = _('This profile is intended for the Microsoft Reader.') + + screen_size = (480, 652) + dpi = 96 + fbase = 13 + fsizes = [10, 11, 13, 16, 18, 20, 22, 26] + + +class MobipocketOutput(OutputProfile): + + name = 'Mobipocket Books' + short_name = 'mobipocket' + description = _('This profile is intended for the Mobipocket books.') + + # Unfortunately MOBI books are not narrowly targeted, so this information is + # quite likely to be spurious + screen_size = (600, 800) + dpi = 96 + fbase = 18 + fsizes = [14, 14, 16, 18, 20, 22, 24, 26] + + +class HanlinV3Output(OutputProfile): + + name = 'Hanlin V3' + short_name = 'hanlinv3' + description = _('This profile is intended for the Hanlin V3 and its clones.') + + # Screen size is a best guess + screen_size = (584, 754) + dpi = 168.451 + fbase = 16 + fsizes = [12, 12, 14, 16, 18, 20, 22, 24] + + +class HanlinV5Output(HanlinV3Output): + + name = 'Hanlin V5' + short_name = 'hanlinv5' + description = _('This profile is intended for the Hanlin V5 and its clones.') + + dpi = 200 + + +class CybookG3Output(OutputProfile): + + name = 'Cybook G3' + short_name = 'cybookg3' + description = _('This profile is intended for the Cybook G3.') + + # Screen size is a best guess + screen_size = (600, 800) + comic_screen_size = (600, 757) + dpi = 168.451 + fbase = 16 + fsizes = [12, 12, 14, 16, 18, 20, 22, 24] + + +class CybookOpusOutput(SonyReaderOutput): + + author = 'John Schember' + name = 'Cybook Opus' + short_name = 'cybook_opus' + description = _('This profile is intended for the Cybook Opus.') + + # Screen size is a best guess + dpi = 200 + fbase = 16 + fsizes = [12, 12, 14, 16, 18, 20, 22, 24] + + epub_periodical_format = None + + +class KindleOutput(OutputProfile): + + name = 'Kindle' + short_name = 'kindle' + description = _('This profile is intended for the Amazon Kindle.') + + # Screen size is a best guess + screen_size = (525, 640) + dpi = 168.451 + fbase = 16 + fsizes = [12, 12, 14, 16, 18, 20, 22, 24] + supports_mobi_indexing = True + periodical_date_in_title = False + + empty_ratings_char = '\u2606' + ratings_char = '\u2605' + + mobi_ems_per_blockquote = 2.0 + + +class KindleDXOutput(OutputProfile): + + name = 'Kindle DX' + short_name = 'kindle_dx' + description = _('This profile is intended for the Amazon Kindle DX.') + + # Screen size is a best guess + screen_size = (744, 1022) + dpi = 150.0 + comic_screen_size = (771, 1116) + # comic_screen_size = (741, 1022) + supports_mobi_indexing = True + periodical_date_in_title = False + empty_ratings_char = '\u2606' + ratings_char = '\u2605' + mobi_ems_per_blockquote = 2.0 + + +class KindlePaperWhiteOutput(KindleOutput): + + name = 'Kindle PaperWhite' + short_name = 'kindle_pw' + description = _('This profile is intended for the Amazon Kindle PaperWhite 1 and 2') + + # Screen size is a best guess + screen_size = (658, 940) + dpi = 212.0 + comic_screen_size = screen_size + + +class KindleVoyageOutput(KindleOutput): + + name = 'Kindle Voyage' + short_name = 'kindle_voyage' + description = _('This profile is intended for the Amazon Kindle Voyage') + + # Screen size is currently just the spec size, actual renderable area will + # depend on someone with the device doing tests. + screen_size = (1080, 1430) + dpi = 300.0 + comic_screen_size = screen_size + + +class KindlePaperWhite3Output(KindleVoyageOutput): + + name = 'Kindle PaperWhite 3' + short_name = 'kindle_pw3' + description = _('This profile is intended for the Amazon Kindle PaperWhite 3 and above') + # Screen size is currently just the spec size, actual renderable area will + # depend on someone with the device doing tests. + screen_size = (1072, 1430) + dpi = 300.0 + comic_screen_size = screen_size + + +class KindleOasisOutput(KindlePaperWhite3Output): + + name = 'Kindle Oasis' + short_name = 'kindle_oasis' + description = _('This profile is intended for the Amazon Kindle Oasis 2017 and above') + # Screen size is currently just the spec size, actual renderable area will + # depend on someone with the device doing tests. + screen_size = (1264, 1680) + dpi = 300.0 + comic_screen_size = screen_size + + +class KindleFireOutput(KindleDXOutput): + + name = 'Kindle Fire' + short_name = 'kindle_fire' + description = _('This profile is intended for the Amazon Kindle Fire.') + + screen_size = (570, 1016) + dpi = 169.0 + comic_screen_size = (570, 1016) + + +class IlliadOutput(OutputProfile): + + name = 'Illiad' + short_name = 'illiad' + description = _('This profile is intended for the Irex Illiad.') + + screen_size = (760, 925) + comic_screen_size = (760, 925) + dpi = 160.0 + fbase = 12 + fsizes = [7.5, 9, 10, 12, 15.5, 20, 22, 24] + + +class IRexDR1000Output(OutputProfile): + + author = 'John Schember' + name = 'IRex Digital Reader 1000' + short_name = 'irexdr1000' + description = _('This profile is intended for the IRex Digital Reader 1000.') + + # Screen size is a best guess + screen_size = (1024, 1280) + comic_screen_size = (996, 1241) + dpi = 160 + fbase = 16 + fsizes = [12, 14, 16, 18, 20, 22, 24] + + +class IRexDR800Output(OutputProfile): + + author = 'Eric Cronin' + name = 'IRex Digital Reader 800' + short_name = 'irexdr800' + description = _('This profile is intended for the IRex Digital Reader 800.') + + # Screen size is a best guess + screen_size = (768, 1024) + comic_screen_size = (768, 1024) + dpi = 160 + fbase = 16 + fsizes = [12, 14, 16, 18, 20, 22, 24] + + +class NookOutput(OutputProfile): + + author = 'John Schember' + name = 'Nook' + short_name = 'nook' + description = _('This profile is intended for the B&N Nook.') + + # Screen size is a best guess + screen_size = (600, 730) + comic_screen_size = (584, 730) + dpi = 167 + fbase = 16 + fsizes = [12, 12, 14, 16, 18, 20, 22, 24] + + +class NookColorOutput(NookOutput): + name = 'Nook Color' + short_name = 'nook_color' + description = _('This profile is intended for the B&N Nook Color.') + + screen_size = (600, 900) + comic_screen_size = (594, 900) + dpi = 169 + + +class PocketBook900Output(OutputProfile): + + author = 'Chris Lockfort' + name = 'PocketBook Pro 900' + short_name = 'pocketbook_900' + description = _('This profile is intended for the PocketBook Pro 900 series of devices.') + + screen_size = (810, 1180) + dpi = 150.0 + comic_screen_size = screen_size + + +class PocketBookPro912Output(OutputProfile): + + author = 'Daniele Pizzolli' + name = 'PocketBook Pro 912' + short_name = 'pocketbook_pro_912' + description = _('This profile is intended for the PocketBook Pro 912 series of devices.') + + # According to http://download.pocketbook-int.com/user-guides/E_Ink/912/User_Guide_PocketBook_912(EN).pdf + screen_size = (825, 1200) + dpi = 155.0 + comic_screen_size = screen_size + + +output_profiles = [ + OutputProfile, SonyReaderOutput, SonyReader300Output, SonyReader900Output, + SonyReaderT3Output, MSReaderOutput, MobipocketOutput, HanlinV3Output, + HanlinV5Output, CybookG3Output, CybookOpusOutput, KindleOutput, iPadOutput, + iPad3Output, KoboReaderOutput, TabletOutput, SamsungGalaxy, + SonyReaderLandscapeOutput, KindleDXOutput, IlliadOutput, NookHD, + IRexDR1000Output, IRexDR800Output, JetBook5Output, NookOutput, + NookColorOutput, PocketBook900Output, + PocketBookPro912Output, GenericEink, GenericEinkLarge, GenericEinkHD, + KindleFireOutput, KindlePaperWhiteOutput, KindleVoyageOutput, + KindlePaperWhite3Output, KindleOasisOutput +] + +output_profiles.sort(key=lambda x: x.name.lower()) diff --git a/ebook_converter/customize/ui.py b/ebook_converter/customize/ui.py new file mode 100644 index 0000000..53cdfd1 --- /dev/null +++ b/ebook_converter/customize/ui.py @@ -0,0 +1,835 @@ +from __future__ import absolute_import, division, print_function, unicode_literals +__license__ = 'GPL v3' +__copyright__ = '2008, Kovid Goyal ' + +import os, shutil, traceback, functools, sys +from collections import defaultdict +from itertools import chain + +from calibre.customize import (CatalogPlugin, FileTypePlugin, PluginNotFound, + MetadataReaderPlugin, MetadataWriterPlugin, + InterfaceActionBase as InterfaceAction, + PreferencesPlugin, platform, InvalidPlugin, + StoreBase as Store, EditBookToolPlugin, + LibraryClosedPlugin) +from calibre.customize.conversion import InputFormatPlugin, OutputFormatPlugin +from calibre.customize.zipplugin import loader +from calibre.customize.profiles import InputProfile, OutputProfile +from calibre.customize.builtins import plugins as builtin_plugins +from calibre.devices.interface import DevicePlugin +from calibre.ebooks.metadata import MetaInformation +from calibre.utils.config import (make_config_dir, Config, ConfigProxy, + plugin_dir, OptionParser) +from calibre.ebooks.metadata.sources.base import Source +from calibre.constants import DEBUG, numeric_version +from polyglot.builtins import iteritems, itervalues, unicode_type + +builtin_names = frozenset(p.name for p in builtin_plugins) +BLACKLISTED_PLUGINS = frozenset({'Marvin XD', 'iOS reader applications'}) + + +class NameConflict(ValueError): + pass + + +def _config(): + c = Config('customize') + c.add_opt('plugins', default={}, help=_('Installed plugins')) + c.add_opt('filetype_mapping', default={}, help=_('Mapping for filetype plugins')) + c.add_opt('plugin_customization', default={}, help=_('Local plugin customization')) + c.add_opt('disabled_plugins', default=set(), help=_('Disabled plugins')) + c.add_opt('enabled_plugins', default=set(), help=_('Enabled plugins')) + + return ConfigProxy(c) + + +config = _config() + + +def find_plugin(name): + for plugin in _initialized_plugins: + if plugin.name == name: + return plugin + + +def load_plugin(path_to_zip_file): # {{{ + ''' + Load plugin from ZIP file or raise InvalidPlugin error + + :return: A :class:`Plugin` instance. + ''' + return loader.load(path_to_zip_file) + +# }}} + +# Enable/disable plugins {{{ + + +def disable_plugin(plugin_or_name): + x = getattr(plugin_or_name, 'name', plugin_or_name) + plugin = find_plugin(x) + if not plugin.can_be_disabled: + raise ValueError('Plugin %s cannot be disabled'%x) + dp = config['disabled_plugins'] + dp.add(x) + config['disabled_plugins'] = dp + ep = config['enabled_plugins'] + if x in ep: + ep.remove(x) + config['enabled_plugins'] = ep + + +def enable_plugin(plugin_or_name): + x = getattr(plugin_or_name, 'name', plugin_or_name) + dp = config['disabled_plugins'] + if x in dp: + dp.remove(x) + config['disabled_plugins'] = dp + ep = config['enabled_plugins'] + ep.add(x) + config['enabled_plugins'] = ep + + +def restore_plugin_state_to_default(plugin_or_name): + x = getattr(plugin_or_name, 'name', plugin_or_name) + dp = config['disabled_plugins'] + if x in dp: + dp.remove(x) + config['disabled_plugins'] = dp + ep = config['enabled_plugins'] + if x in ep: + ep.remove(x) + config['enabled_plugins'] = ep + + +default_disabled_plugins = { + 'Overdrive', 'Douban Books', 'OZON.ru', 'Edelweiss', 'Google Images', 'Big Book Search', +} + + +def is_disabled(plugin): + if plugin.name in config['enabled_plugins']: + return False + return plugin.name in config['disabled_plugins'] or \ + plugin.name in default_disabled_plugins +# }}} + +# File type plugins {{{ + + +_on_import = {} +_on_postimport = {} +_on_preprocess = {} +_on_postprocess = {} +_on_postadd = [] + + +def reread_filetype_plugins(): + global _on_import, _on_postimport, _on_preprocess, _on_postprocess, _on_postadd + _on_import = defaultdict(list) + _on_postimport = defaultdict(list) + _on_preprocess = defaultdict(list) + _on_postprocess = defaultdict(list) + _on_postadd = [] + + for plugin in _initialized_plugins: + if isinstance(plugin, FileTypePlugin): + for ft in plugin.file_types: + if plugin.on_import: + _on_import[ft].append(plugin) + if plugin.on_postimport: + _on_postimport[ft].append(plugin) + _on_postadd.append(plugin) + if plugin.on_preprocess: + _on_preprocess[ft].append(plugin) + if plugin.on_postprocess: + _on_postprocess[ft].append(plugin) + + +def plugins_for_ft(ft, occasion): + op = { + 'import':_on_import, 'preprocess':_on_preprocess, 'postprocess':_on_postprocess, 'postimport':_on_postimport, + }[occasion] + for p in chain(op.get(ft, ()), op.get('*', ())): + if not is_disabled(p): + yield p + + +def _run_filetype_plugins(path_to_file, ft=None, occasion='preprocess'): + customization = config['plugin_customization'] + if ft is None: + ft = os.path.splitext(path_to_file)[-1].lower().replace('.', '') + nfp = path_to_file + for plugin in plugins_for_ft(ft, occasion): + plugin.site_customization = customization.get(plugin.name, '') + oo, oe = sys.stdout, sys.stderr # Some file type plugins out there override the output streams with buggy implementations + with plugin: + try: + plugin.original_path_to_file = path_to_file + except Exception: + pass + try: + nfp = plugin.run(nfp) or nfp + except: + print('Running file type plugin %s failed with traceback:'%plugin.name, file=oe) + traceback.print_exc(file=oe) + sys.stdout, sys.stderr = oo, oe + x = lambda j: os.path.normpath(os.path.normcase(j)) + if occasion == 'postprocess' and x(nfp) != x(path_to_file): + shutil.copyfile(nfp, path_to_file) + nfp = path_to_file + return nfp + + +run_plugins_on_import = functools.partial(_run_filetype_plugins, occasion='import') +run_plugins_on_preprocess = functools.partial(_run_filetype_plugins, occasion='preprocess') +run_plugins_on_postprocess = functools.partial(_run_filetype_plugins, occasion='postprocess') + + +def run_plugins_on_postimport(db, book_id, fmt): + customization = config['plugin_customization'] + fmt = fmt.lower() + for plugin in plugins_for_ft(fmt, 'postimport'): + plugin.site_customization = customization.get(plugin.name, '') + with plugin: + try: + plugin.postimport(book_id, fmt, db) + except: + print('Running file type plugin %s failed with traceback:'% + plugin.name) + traceback.print_exc() + + +def run_plugins_on_postadd(db, book_id, fmt_map): + customization = config['plugin_customization'] + for plugin in _on_postadd: + if is_disabled(plugin): + continue + plugin.site_customization = customization.get(plugin.name, '') + with plugin: + try: + plugin.postadd(book_id, fmt_map, db) + except Exception: + print('Running file type plugin %s failed with traceback:'% + plugin.name) + traceback.print_exc() + +# }}} + +# Plugin customization {{{ + + +def customize_plugin(plugin, custom): + d = config['plugin_customization'] + d[plugin.name] = custom.strip() + config['plugin_customization'] = d + + +def plugin_customization(plugin): + return config['plugin_customization'].get(plugin.name, '') + +# }}} + +# Input/Output profiles {{{ + + +def input_profiles(): + for plugin in _initialized_plugins: + if isinstance(plugin, InputProfile): + yield plugin + + +def output_profiles(): + for plugin in _initialized_plugins: + if isinstance(plugin, OutputProfile): + yield plugin +# }}} + +# Interface Actions # {{{ + + +def interface_actions(): + customization = config['plugin_customization'] + for plugin in _initialized_plugins: + if isinstance(plugin, InterfaceAction): + if not is_disabled(plugin): + plugin.site_customization = customization.get(plugin.name, '') + yield plugin +# }}} + +# Preferences Plugins # {{{ + + +def preferences_plugins(): + customization = config['plugin_customization'] + for plugin in _initialized_plugins: + if isinstance(plugin, PreferencesPlugin): + if not is_disabled(plugin): + plugin.site_customization = customization.get(plugin.name, '') + yield plugin +# }}} + +# Library Closed Plugins # {{{ + + +def available_library_closed_plugins(): + customization = config['plugin_customization'] + for plugin in _initialized_plugins: + if isinstance(plugin, LibraryClosedPlugin): + if not is_disabled(plugin): + plugin.site_customization = customization.get(plugin.name, '') + yield plugin + + +def has_library_closed_plugins(): + for plugin in _initialized_plugins: + if isinstance(plugin, LibraryClosedPlugin): + if not is_disabled(plugin): + return True + return False +# }}} + +# Store Plugins # {{{ + + +def store_plugins(): + customization = config['plugin_customization'] + for plugin in _initialized_plugins: + if isinstance(plugin, Store): + plugin.site_customization = customization.get(plugin.name, '') + yield plugin + + +def available_store_plugins(): + for plugin in store_plugins(): + if not is_disabled(plugin): + yield plugin + + +def stores(): + stores = set() + for plugin in store_plugins(): + stores.add(plugin.name) + return stores + + +def available_stores(): + stores = set() + for plugin in available_store_plugins(): + stores.add(plugin.name) + return stores + +# }}} + +# Metadata read/write {{{ + + +_metadata_readers = {} +_metadata_writers = {} + + +def reread_metadata_plugins(): + global _metadata_readers + global _metadata_writers + _metadata_readers = defaultdict(list) + _metadata_writers = defaultdict(list) + for plugin in _initialized_plugins: + if isinstance(plugin, MetadataReaderPlugin): + for ft in plugin.file_types: + _metadata_readers[ft].append(plugin) + elif isinstance(plugin, MetadataWriterPlugin): + for ft in plugin.file_types: + _metadata_writers[ft].append(plugin) + + # Ensure custom metadata plugins are used in preference to builtin + # ones for a given filetype + def key(plugin): + return (1 if plugin.plugin_path is None else 0), plugin.name + + for group in (_metadata_readers, _metadata_writers): + for plugins in itervalues(group): + if len(plugins) > 1: + plugins.sort(key=key) + + +def metadata_readers(): + ans = set() + for plugins in _metadata_readers.values(): + for plugin in plugins: + ans.add(plugin) + return ans + + +def metadata_writers(): + ans = set() + for plugins in _metadata_writers.values(): + for plugin in plugins: + ans.add(plugin) + return ans + + +class QuickMetadata(object): + + def __init__(self): + self.quick = False + + def __enter__(self): + self.quick = True + + def __exit__(self, *args): + self.quick = False + + +quick_metadata = QuickMetadata() + + +class ApplyNullMetadata(object): + + def __init__(self): + self.apply_null = False + + def __enter__(self): + self.apply_null = True + + def __exit__(self, *args): + self.apply_null = False + + +apply_null_metadata = ApplyNullMetadata() + + +class ForceIdentifiers(object): + + def __init__(self): + self.force_identifiers = False + + def __enter__(self): + self.force_identifiers = True + + def __exit__(self, *args): + self.force_identifiers = False + + +force_identifiers = ForceIdentifiers() + + +def get_file_type_metadata(stream, ftype): + mi = MetaInformation(None, None) + + ftype = ftype.lower().strip() + if ftype in _metadata_readers: + for plugin in _metadata_readers[ftype]: + if not is_disabled(plugin): + with plugin: + try: + plugin.quick = quick_metadata.quick + if hasattr(stream, 'seek'): + stream.seek(0) + mi = plugin.get_metadata(stream, ftype.lower().strip()) + break + except: + traceback.print_exc() + continue + return mi + + +def set_file_type_metadata(stream, mi, ftype, report_error=None): + ftype = ftype.lower().strip() + if ftype in _metadata_writers: + customization = config['plugin_customization'] + for plugin in _metadata_writers[ftype]: + if not is_disabled(plugin): + with plugin: + try: + plugin.apply_null = apply_null_metadata.apply_null + plugin.force_identifiers = force_identifiers.force_identifiers + plugin.site_customization = customization.get(plugin.name, '') + plugin.set_metadata(stream, mi, ftype.lower().strip()) + break + except: + if report_error is None: + from calibre import prints + prints('Failed to set metadata for the', ftype.upper(), 'format of:', getattr(mi, 'title', ''), file=sys.stderr) + traceback.print_exc() + else: + report_error(mi, ftype, traceback.format_exc()) + + +def can_set_metadata(ftype): + ftype = ftype.lower().strip() + for plugin in _metadata_writers.get(ftype, ()): + if not is_disabled(plugin): + return True + return False + +# }}} + +# Add/remove plugins {{{ + + +def add_plugin(path_to_zip_file): + make_config_dir() + plugin = load_plugin(path_to_zip_file) + if plugin.name in builtin_names: + raise NameConflict( + 'A builtin plugin with the name %r already exists' % plugin.name) + plugin = initialize_plugin(plugin, path_to_zip_file) + plugins = config['plugins'] + zfp = os.path.join(plugin_dir, plugin.name+'.zip') + if os.path.exists(zfp): + os.remove(zfp) + shutil.copyfile(path_to_zip_file, zfp) + plugins[plugin.name] = zfp + config['plugins'] = plugins + initialize_plugins() + return plugin + + +def remove_plugin(plugin_or_name): + name = getattr(plugin_or_name, 'name', plugin_or_name) + plugins = config['plugins'] + removed = False + if name in plugins: + removed = True + try: + zfp = os.path.join(plugin_dir, name+'.zip') + if os.path.exists(zfp): + os.remove(zfp) + zfp = plugins[name] + if os.path.exists(zfp): + os.remove(zfp) + except: + pass + plugins.pop(name) + config['plugins'] = plugins + initialize_plugins() + return removed + +# }}} + +# Input/Output format plugins {{{ + + +def input_format_plugins(): + for plugin in _initialized_plugins: + if isinstance(plugin, InputFormatPlugin): + yield plugin + + +def plugin_for_input_format(fmt): + customization = config['plugin_customization'] + for plugin in input_format_plugins(): + if fmt.lower() in plugin.file_types: + plugin.site_customization = customization.get(plugin.name, None) + return plugin + + +def all_input_formats(): + formats = set() + for plugin in input_format_plugins(): + for format in plugin.file_types: + formats.add(format) + return formats + + +def available_input_formats(): + formats = set() + for plugin in input_format_plugins(): + if not is_disabled(plugin): + for format in plugin.file_types: + formats.add(format) + formats.add('zip'), formats.add('rar') + return formats + + +def output_format_plugins(): + for plugin in _initialized_plugins: + if isinstance(plugin, OutputFormatPlugin): + yield plugin + + +def plugin_for_output_format(fmt): + customization = config['plugin_customization'] + for plugin in output_format_plugins(): + if fmt.lower() == plugin.file_type: + plugin.site_customization = customization.get(plugin.name, None) + return plugin + + +def available_output_formats(): + formats = set() + for plugin in output_format_plugins(): + if not is_disabled(plugin): + formats.add(plugin.file_type) + return formats + +# }}} + +# Catalog plugins {{{ + + +def catalog_plugins(): + for plugin in _initialized_plugins: + if isinstance(plugin, CatalogPlugin): + yield plugin + + +def available_catalog_formats(): + formats = set() + for plugin in catalog_plugins(): + if not is_disabled(plugin): + for format in plugin.file_types: + formats.add(format) + return formats + + +def plugin_for_catalog_format(fmt): + for plugin in catalog_plugins(): + if fmt.lower() in plugin.file_types: + return plugin + +# }}} + +# Device plugins {{{ + + +def device_plugins(include_disabled=False): + for plugin in _initialized_plugins: + if isinstance(plugin, DevicePlugin): + if include_disabled or not is_disabled(plugin): + if platform in plugin.supported_platforms: + if getattr(plugin, 'plugin_needs_delayed_initialization', + False): + plugin.do_delayed_plugin_initialization() + yield plugin + + +def disabled_device_plugins(): + for plugin in _initialized_plugins: + if isinstance(plugin, DevicePlugin): + if is_disabled(plugin): + if platform in plugin.supported_platforms: + yield plugin +# }}} + +# Metadata sources2 {{{ + + +def metadata_plugins(capabilities): + capabilities = frozenset(capabilities) + for plugin in all_metadata_plugins(): + if plugin.capabilities.intersection(capabilities) and \ + not is_disabled(plugin): + yield plugin + + +def all_metadata_plugins(): + for plugin in _initialized_plugins: + if isinstance(plugin, Source): + yield plugin + + +def patch_metadata_plugins(possibly_updated_plugins): + patches = {} + for i, plugin in enumerate(_initialized_plugins): + if isinstance(plugin, Source) and plugin.name in builtin_names: + pup = possibly_updated_plugins.get(plugin.name) + if pup is not None: + if pup.version > plugin.version and pup.minimum_calibre_version <= numeric_version: + patches[i] = pup(None) + # Metadata source plugins dont use initialize() but that + # might change in the future, so be safe. + patches[i].initialize() + for i, pup in iteritems(patches): + _initialized_plugins[i] = pup +# }}} + +# Editor plugins {{{ + + +def all_edit_book_tool_plugins(): + for plugin in _initialized_plugins: + if isinstance(plugin, EditBookToolPlugin): + yield plugin +# }}} + +# Initialize plugins {{{ + + +_initialized_plugins = [] + + +def initialize_plugin(plugin, path_to_zip_file): + try: + p = plugin(path_to_zip_file) + p.initialize() + return p + except Exception: + print('Failed to initialize plugin:', plugin.name, plugin.version) + tb = traceback.format_exc() + raise InvalidPlugin((_('Initialization of plugin %s failed with traceback:') + %tb) + '\n'+tb) + + +def has_external_plugins(): + 'True if there are updateable (ZIP file based) plugins' + return bool(config['plugins']) + + +def initialize_plugins(perf=False): + global _initialized_plugins + _initialized_plugins = [] + conflicts = [name for name in config['plugins'] if name in + builtin_names] + for p in conflicts: + remove_plugin(p) + external_plugins = config['plugins'].copy() + for name in BLACKLISTED_PLUGINS: + external_plugins.pop(name, None) + ostdout, ostderr = sys.stdout, sys.stderr + if perf: + from collections import defaultdict + import time + times = defaultdict(lambda:0) + for zfp in list(external_plugins) + builtin_plugins: + try: + if not isinstance(zfp, type): + # We have a plugin name + pname = zfp + zfp = os.path.join(plugin_dir, zfp+'.zip') + if not os.path.exists(zfp): + zfp = external_plugins[pname] + try: + plugin = load_plugin(zfp) if not isinstance(zfp, type) else zfp + except PluginNotFound: + continue + if perf: + st = time.time() + plugin = initialize_plugin(plugin, None if isinstance(zfp, type) else zfp) + if perf: + times[plugin.name] = time.time() - st + _initialized_plugins.append(plugin) + except: + print('Failed to initialize plugin:', repr(zfp)) + if DEBUG: + traceback.print_exc() + # Prevent a custom plugin from overriding stdout/stderr as this breaks + # ipython + sys.stdout, sys.stderr = ostdout, ostderr + if perf: + for x in sorted(times, key=lambda x: times[x]): + print('%50s: %.3f'%(x, times[x])) + _initialized_plugins.sort(key=lambda x: x.priority, reverse=True) + reread_filetype_plugins() + reread_metadata_plugins() + + +initialize_plugins() + + +def initialized_plugins(): + for plugin in _initialized_plugins: + yield plugin + +# }}} + +# CLI {{{ + + +def build_plugin(path): + from calibre import prints + from calibre.ptempfile import PersistentTemporaryFile + from calibre.utils.zipfile import ZipFile, ZIP_STORED + path = unicode_type(path) + names = frozenset(os.listdir(path)) + if '__init__.py' not in names: + prints(path, ' is not a valid plugin') + raise SystemExit(1) + t = PersistentTemporaryFile(u'.zip') + with ZipFile(t, 'w', ZIP_STORED) as zf: + zf.add_dir(path, simple_filter=lambda x:x in {'.git', '.bzr', '.svn', '.hg'}) + t.close() + plugin = add_plugin(t.name) + os.remove(t.name) + prints('Plugin updated:', plugin.name, plugin.version) + + +def option_parser(): + parser = OptionParser(usage=_('''\ + %prog options + + Customize calibre by loading external plugins. + ''')) + parser.add_option('-a', '--add-plugin', default=None, + help=_('Add a plugin by specifying the path to the ZIP file containing it.')) + parser.add_option('-b', '--build-plugin', default=None, + help=_('For plugin developers: Path to the directory where you are' + ' developing the plugin. This command will automatically zip ' + 'up the plugin and update it in calibre.')) + parser.add_option('-r', '--remove-plugin', default=None, + help=_('Remove a custom plugin by name. Has no effect on builtin plugins')) + parser.add_option('--customize-plugin', default=None, + help=_('Customize plugin. Specify name of plugin and customization string separated by a comma.')) + parser.add_option('-l', '--list-plugins', default=False, action='store_true', + help=_('List all installed plugins')) + parser.add_option('--enable-plugin', default=None, + help=_('Enable the named plugin')) + parser.add_option('--disable-plugin', default=None, + help=_('Disable the named plugin')) + return parser + + +def main(args=sys.argv): + parser = option_parser() + if len(args) < 2: + parser.print_help() + return 1 + opts, args = parser.parse_args(args) + if opts.add_plugin is not None: + plugin = add_plugin(opts.add_plugin) + print('Plugin added:', plugin.name, plugin.version) + if opts.build_plugin is not None: + build_plugin(opts.build_plugin) + if opts.remove_plugin is not None: + if remove_plugin(opts.remove_plugin): + print('Plugin removed') + else: + print('No custom plugin named', opts.remove_plugin) + if opts.customize_plugin is not None: + name, custom = opts.customize_plugin.split(',') + plugin = find_plugin(name.strip()) + if plugin is None: + print('No plugin with the name %s exists'%name) + return 1 + customize_plugin(plugin, custom) + if opts.enable_plugin is not None: + enable_plugin(opts.enable_plugin.strip()) + if opts.disable_plugin is not None: + disable_plugin(opts.disable_plugin.strip()) + if opts.list_plugins: + type_len = name_len = 0 + for plugin in initialized_plugins(): + type_len, name_len = max(type_len, len(plugin.type)), max(name_len, len(plugin.name)) + fmt = '%-{}s%-{}s%-15s%-15s%s'.format(type_len+1, name_len+1) + print(fmt%tuple(('Type|Name|Version|Disabled|Site Customization'.split('|')))) + print() + for plugin in initialized_plugins(): + print(fmt%( + plugin.type, plugin.name, + plugin.version, is_disabled(plugin), + plugin_customization(plugin) + )) + print('\t', plugin.description) + if plugin.is_customizable(): + try: + print('\t', plugin.customization_help()) + except NotImplementedError: + pass + print() + + return 0 + + +if __name__ == '__main__': + sys.exit(main()) +# }}} diff --git a/ebook_converter/customize/zipplugin.py b/ebook_converter/customize/zipplugin.py new file mode 100644 index 0000000..1ed5020 --- /dev/null +++ b/ebook_converter/customize/zipplugin.py @@ -0,0 +1,320 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2011, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import os, zipfile, posixpath, importlib, threading, re, imp, sys +from collections import OrderedDict +from functools import partial + +from calibre import as_unicode +from calibre.constants import ispy3 +from calibre.customize import (Plugin, numeric_version, platform, + InvalidPlugin, PluginNotFound) +from polyglot.builtins import (itervalues, map, string_or_bytes, + unicode_type, reload) + +# PEP 302 based plugin loading mechanism, works around the bug in zipimport in +# python 2.x that prevents importing from zip files in locations whose paths +# have non ASCII characters + + +def get_resources(zfp, name_or_list_of_names): + ''' + Load resources from the plugin zip file + + :param name_or_list_of_names: List of paths to resources in the zip file using / as + separator, or a single path + + :return: A dictionary of the form ``{name : file_contents}``. Any names + that were not found in the zip file will not be present in the + dictionary. If a single path is passed in the return value will + be just the bytes of the resource or None if it wasn't found. + ''' + names = name_or_list_of_names + if isinstance(names, string_or_bytes): + names = [names] + ans = {} + with zipfile.ZipFile(zfp) as zf: + for name in names: + try: + ans[name] = zf.read(name) + except: + import traceback + traceback.print_exc() + if len(names) == 1: + ans = ans.pop(names[0], None) + + return ans + + +def get_icons(zfp, name_or_list_of_names): + ''' + Load icons from the plugin zip file + + :param name_or_list_of_names: List of paths to resources in the zip file using / as + separator, or a single path + + :return: A dictionary of the form ``{name : QIcon}``. Any names + that were not found in the zip file will be null QIcons. + If a single path is passed in the return value will + be A QIcon. + ''' + from PyQt5.Qt import QIcon, QPixmap + names = name_or_list_of_names + ans = get_resources(zfp, names) + if isinstance(names, string_or_bytes): + names = [names] + if ans is None: + ans = {} + if isinstance(ans, string_or_bytes): + ans = dict([(names[0], ans)]) + + ians = {} + for name in names: + p = QPixmap() + raw = ans.get(name, None) + if raw: + p.loadFromData(raw) + ians[name] = QIcon(p) + if len(names) == 1: + ians = ians.pop(names[0]) + return ians + + +_translations_cache = {} + + +def load_translations(namespace, zfp): + null = object() + trans = _translations_cache.get(zfp, null) + if trans is None: + return + if trans is null: + from calibre.utils.localization import get_lang + lang = get_lang() + if not lang or lang == 'en': # performance optimization + _translations_cache[zfp] = None + return + with zipfile.ZipFile(zfp) as zf: + try: + mo = zf.read('translations/%s.mo' % lang) + except KeyError: + mo = None # No translations for this language present + if mo is None: + _translations_cache[zfp] = None + return + from gettext import GNUTranslations + from io import BytesIO + trans = _translations_cache[zfp] = GNUTranslations(BytesIO(mo)) + + namespace['_'] = getattr(trans, 'gettext' if ispy3 else 'ugettext') + namespace['ngettext'] = getattr(trans, 'ngettext' if ispy3 else 'ungettext') + + +class PluginLoader(object): + + def __init__(self): + self.loaded_plugins = {} + self._lock = threading.RLock() + self._identifier_pat = re.compile(r'[a-zA-Z][_0-9a-zA-Z]*') + + def _get_actual_fullname(self, fullname): + parts = fullname.split('.') + if parts[0] == 'calibre_plugins': + if len(parts) == 1: + return parts[0], None + plugin_name = parts[1] + with self._lock: + names = self.loaded_plugins.get(plugin_name, None) + if names is None: + raise ImportError('No plugin named %r loaded'%plugin_name) + names = names[1] + fullname = '.'.join(parts[2:]) + if not fullname: + fullname = '__init__' + if fullname in names: + return fullname, plugin_name + if fullname+'.__init__' in names: + return fullname+'.__init__', plugin_name + return None, None + + def find_module(self, fullname, path=None): + fullname, plugin_name = self._get_actual_fullname(fullname) + if fullname is None and plugin_name is None: + return None + return self + + def load_module(self, fullname): + import_name, plugin_name = self._get_actual_fullname(fullname) + if import_name is None and plugin_name is None: + raise ImportError('No plugin named %r is loaded'%fullname) + mod = sys.modules.setdefault(fullname, imp.new_module(fullname)) + mod.__file__ = "" + mod.__loader__ = self + + if import_name.endswith('.__init__') or import_name in ('__init__', + 'calibre_plugins'): + # We have a package + mod.__path__ = [] + + if plugin_name is not None: + # We have some actual code to load + with self._lock: + zfp, names = self.loaded_plugins.get(plugin_name, (None, None)) + if names is None: + raise ImportError('No plugin named %r loaded'%plugin_name) + zinfo = names.get(import_name, None) + if zinfo is None: + raise ImportError('Plugin %r has no module named %r' % + (plugin_name, import_name)) + with zipfile.ZipFile(zfp) as zf: + try: + code = zf.read(zinfo) + except: + # Maybe the zip file changed from under us + code = zf.read(zinfo.filename) + compiled = compile(code, 'calibre_plugins.%s.%s'%(plugin_name, + import_name), 'exec', dont_inherit=True) + mod.__dict__['get_resources'] = partial(get_resources, zfp) + mod.__dict__['get_icons'] = partial(get_icons, zfp) + mod.__dict__['load_translations'] = partial(load_translations, mod.__dict__, zfp) + exec(compiled, mod.__dict__) + + return mod + + def load(self, path_to_zip_file): + if not os.access(path_to_zip_file, os.R_OK): + raise PluginNotFound('Cannot access %r'%path_to_zip_file) + + with zipfile.ZipFile(path_to_zip_file) as zf: + plugin_name = self._locate_code(zf, path_to_zip_file) + + try: + ans = None + plugin_module = 'calibre_plugins.%s'%plugin_name + m = sys.modules.get(plugin_module, None) + if m is not None: + reload(m) + else: + m = importlib.import_module(plugin_module) + plugin_classes = [] + for obj in itervalues(m.__dict__): + if isinstance(obj, type) and issubclass(obj, Plugin) and \ + obj.name != 'Trivial Plugin': + plugin_classes.append(obj) + if not plugin_classes: + raise InvalidPlugin('No plugin class found in %s:%s'%( + as_unicode(path_to_zip_file), plugin_name)) + if len(plugin_classes) > 1: + plugin_classes.sort(key=lambda c:(getattr(c, '__module__', None) or '').count('.')) + + ans = plugin_classes[0] + + if ans.minimum_calibre_version > numeric_version: + raise InvalidPlugin( + 'The plugin at %s needs a version of calibre >= %s' % + (as_unicode(path_to_zip_file), '.'.join(map(unicode_type, + ans.minimum_calibre_version)))) + + if platform not in ans.supported_platforms: + raise InvalidPlugin( + 'The plugin at %s cannot be used on %s' % + (as_unicode(path_to_zip_file), platform)) + + return ans + except: + with self._lock: + del self.loaded_plugins[plugin_name] + raise + + def _locate_code(self, zf, path_to_zip_file): + names = [x if isinstance(x, unicode_type) else x.decode('utf-8') for x in + zf.namelist()] + names = [x[1:] if x[0] == '/' else x for x in names] + + plugin_name = None + for name in names: + name, ext = posixpath.splitext(name) + if name.startswith('plugin-import-name-') and ext == '.txt': + plugin_name = name.rpartition('-')[-1] + + if plugin_name is None: + c = 0 + while True: + c += 1 + plugin_name = 'dummy%d'%c + if plugin_name not in self.loaded_plugins: + break + else: + if self._identifier_pat.match(plugin_name) is None: + raise InvalidPlugin(( + 'The plugin at %r uses an invalid import name: %r' % + (path_to_zip_file, plugin_name))) + + pynames = [x for x in names if x.endswith('.py')] + + candidates = [posixpath.dirname(x) for x in pynames if + x.endswith('/__init__.py')] + candidates.sort(key=lambda x: x.count('/')) + valid_packages = set() + + for candidate in candidates: + parts = candidate.split('/') + parent = '.'.join(parts[:-1]) + if parent and parent not in valid_packages: + continue + valid_packages.add('.'.join(parts)) + + names = OrderedDict() + + for candidate in pynames: + parts = posixpath.splitext(candidate)[0].split('/') + package = '.'.join(parts[:-1]) + if package and package not in valid_packages: + continue + name = '.'.join(parts) + names[name] = zf.getinfo(candidate) + + # Legacy plugins + if '__init__' not in names: + for name in tuple(names): + if '.' not in name and name.endswith('plugin'): + names['__init__'] = names[name] + break + + if '__init__' not in names: + raise InvalidPlugin(('The plugin in %r is invalid. It does not ' + 'contain a top-level __init__.py file') + % path_to_zip_file) + + with self._lock: + self.loaded_plugins[plugin_name] = (path_to_zip_file, names) + + return plugin_name + + +loader = PluginLoader() +sys.meta_path.insert(0, loader) + + +if __name__ == '__main__': + from tempfile import NamedTemporaryFile + from calibre.customize.ui import add_plugin + from calibre import CurrentDir + path = sys.argv[-1] + with NamedTemporaryFile(suffix='.zip') as f: + with zipfile.ZipFile(f, 'w') as zf: + with CurrentDir(path): + for x in os.listdir('.'): + if x[0] != '.': + print('Adding', x) + zf.write(x) + if os.path.isdir(x): + for y in os.listdir(x): + zf.write(os.path.join(x, y)) + add_plugin(f.name) + print('Added plugin from', sys.argv[-1]) diff --git a/ebook_converter/devices/__init__.py b/ebook_converter/devices/__init__.py new file mode 100644 index 0000000..a32fd45 --- /dev/null +++ b/ebook_converter/devices/__init__.py @@ -0,0 +1,216 @@ +from __future__ import absolute_import, division, print_function, unicode_literals +__license__ = 'GPL v3' +__copyright__ = '2008, Kovid Goyal ' + +''' +Device drivers. +''' + +import sys, time, pprint +from functools import partial +from polyglot.builtins import zip, unicode_type + +DAY_MAP = dict(Sun=0, Mon=1, Tue=2, Wed=3, Thu=4, Fri=5, Sat=6) +MONTH_MAP = dict(Jan=1, Feb=2, Mar=3, Apr=4, May=5, Jun=6, Jul=7, Aug=8, Sep=9, Oct=10, Nov=11, Dec=12) +INVERSE_DAY_MAP = dict(zip(DAY_MAP.values(), DAY_MAP.keys())) +INVERSE_MONTH_MAP = dict(zip(MONTH_MAP.values(), MONTH_MAP.keys())) + + +def strptime(src): + src = src.strip() + src = src.split() + src[0] = unicode_type(DAY_MAP[src[0][:-1]])+',' + src[2] = unicode_type(MONTH_MAP[src[2]]) + return time.strptime(' '.join(src), '%w, %d %m %Y %H:%M:%S %Z') + + +def strftime(epoch, zone=time.gmtime): + src = time.strftime("%w, %d %m %Y %H:%M:%S GMT", zone(epoch)).split() + src[0] = INVERSE_DAY_MAP[int(src[0][:-1])]+',' + src[2] = INVERSE_MONTH_MAP[int(src[2])] + return ' '.join(src) + + +def get_connected_device(): + from calibre.customize.ui import device_plugins + from calibre.devices.scanner import DeviceScanner + dev = None + scanner = DeviceScanner() + scanner.scan() + connected_devices = [] + for d in device_plugins(): + ok, det = scanner.is_device_connected(d) + if ok: + dev = d + dev.reset(log_packets=False, detected_device=det) + connected_devices.append((det, dev)) + + if dev is None: + print('Unable to find a connected ebook reader.', file=sys.stderr) + return + + for det, d in connected_devices: + try: + d.open(det, None) + except: + continue + else: + dev = d + break + return dev + + +def debug(ioreg_to_tmp=False, buf=None, plugins=None, + disabled_plugins=None): + ''' + If plugins is None, then this method calls startup and shutdown on the + device plugins. So if you are using it in a context where startup could + already have been called (for example in the main GUI), pass in the list of + device plugins as the plugins parameter. + ''' + import textwrap + from calibre.customize.ui import device_plugins, disabled_device_plugins + from calibre.debug import print_basic_debug_info + from calibre.devices.scanner import DeviceScanner + from calibre.constants import iswindows, isosx + from calibre import prints + from polyglot.io import PolyglotBytesIO + oldo, olde = sys.stdout, sys.stderr + + if buf is None: + buf = PolyglotBytesIO() + sys.stdout = sys.stderr = buf + out = partial(prints, file=buf) + + devplugins = device_plugins() if plugins is None else plugins + devplugins = list(sorted(devplugins, key=lambda x: x.__class__.__name__)) + if plugins is None: + for d in devplugins: + try: + d.startup() + except: + out('Startup failed for device plugin: %s'%d) + + if disabled_plugins is None: + disabled_plugins = list(disabled_device_plugins()) + + try: + print_basic_debug_info(out=buf) + s = DeviceScanner() + s.scan() + devices = (s.devices) + if not iswindows: + devices = [list(x) for x in devices] + for d in devices: + for i in range(3): + d[i] = hex(d[i]) + out('USB devices on system:') + out(pprint.pformat(devices)) + + ioreg = None + if isosx: + from calibre.devices.usbms.device import Device + mount = '\n'.join(repr(x) for x in Device.osx_run_mount().splitlines()) + drives = pprint.pformat(Device.osx_get_usb_drives()) + ioreg = 'Output from mount:\n'+mount+'\n\n' + ioreg += 'Output from osx_get_usb_drives:\n'+drives+'\n\n' + ioreg += Device.run_ioreg() + connected_devices = [] + if disabled_plugins: + out('\nDisabled plugins:', textwrap.fill(' '.join([x.__class__.__name__ for x in + disabled_plugins]))) + out(' ') + else: + out('\nNo disabled plugins') + found_dev = False + for dev in devplugins: + if not dev.MANAGES_DEVICE_PRESENCE: + continue + out('Looking for devices of type:', dev.__class__.__name__) + if dev.debug_managed_device_detection(s.devices, buf): + found_dev = True + break + out(' ') + + if not found_dev: + out('Looking for devices...') + for dev in devplugins: + if dev.MANAGES_DEVICE_PRESENCE: + continue + connected, det = s.is_device_connected(dev, debug=True) + if connected: + out('\t\tDetected possible device', dev.__class__.__name__) + connected_devices.append((dev, det)) + + out(' ') + errors = {} + success = False + out('Devices possibly connected:', end=' ') + for dev, det in connected_devices: + out(dev.name, end=', ') + if not connected_devices: + out('None', end='') + out(' ') + for dev, det in connected_devices: + out('Trying to open', dev.name, '...', end=' ') + dev.do_device_debug = True + try: + dev.reset(detected_device=det) + dev.open(det, None) + out('OK') + except: + import traceback + errors[dev] = traceback.format_exc() + out('failed') + continue + dev.do_device_debug = False + success = True + if hasattr(dev, '_main_prefix'): + out('Main memory:', repr(dev._main_prefix)) + out('Total space:', dev.total_space()) + break + if not success and errors: + out('Opening of the following devices failed') + for dev,msg in errors.items(): + out(dev) + out(msg) + out(' ') + + if ioreg is not None: + ioreg = 'IOREG Output\n'+ioreg + out(' ') + if ioreg_to_tmp: + lopen('/tmp/ioreg.txt', 'wb').write(ioreg) + out('Dont forget to send the contents of /tmp/ioreg.txt') + out('You can open it with the command: open /tmp/ioreg.txt') + else: + out(ioreg) + + if hasattr(buf, 'getvalue'): + return buf.getvalue().decode('utf-8', 'replace') + finally: + sys.stdout = oldo + sys.stderr = olde + if plugins is None: + for d in devplugins: + try: + d.shutdown() + except: + pass + + +def device_info(ioreg_to_tmp=False, buf=None): + from calibre.devices.scanner import DeviceScanner + + res = {} + res['device_set'] = device_set = set() + res['device_details'] = device_details = {} + + s = DeviceScanner() + s.scan() + devices = s.devices + devices = [tuple(x) for x in devices] + for dev in devices: + device_set.add(dev) + device_details[dev] = dev[0:3] + return res diff --git a/ebook_converter/devices/interface.py b/ebook_converter/devices/interface.py new file mode 100644 index 0000000..b74e255 --- /dev/null +++ b/ebook_converter/devices/interface.py @@ -0,0 +1,787 @@ +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2008, Kovid Goyal ' +import os +from collections import namedtuple + +from calibre import prints +from calibre.constants import iswindows +from calibre.customize import Plugin + + +class DevicePlugin(Plugin): + """ + Defines the interface that should be implemented by backends that + communicate with an e-book reader. + """ + type = _('Device interface') + + #: Ordered list of supported formats + FORMATS = ["lrf", "rtf", "pdf", "txt"] + # If True, the config dialog will not show the formats box + HIDE_FORMATS_CONFIG_BOX = False + + #: VENDOR_ID can be either an integer, a list of integers or a dictionary + #: If it is a dictionary, it must be a dictionary of dictionaries, + #: of the form:: + #: + #: { + #: integer_vendor_id : { product_id : [list of BCDs], ... }, + #: ... + #: } + #: + VENDOR_ID = 0x0000 + + #: An integer or a list of integers + PRODUCT_ID = 0x0000 + #: BCD can be either None to not distinguish between devices based on BCD, or + #: it can be a list of the BCD numbers of all devices supported by this driver. + BCD = None + + #: Height for thumbnails on the device + THUMBNAIL_HEIGHT = 68 + + #: Compression quality for thumbnails. Set this closer to 100 to have better + #: quality thumbnails with fewer compression artifacts. Of course, the + #: thumbnails get larger as well. + THUMBNAIL_COMPRESSION_QUALITY = 75 + + #: Set this to True if the device supports updating cover thumbnails during + #: sync_booklists. Setting it to true will ask device.py to refresh the + #: cover thumbnails during book matching + WANTS_UPDATED_THUMBNAILS = False + + #: Whether the metadata on books can be set via the GUI. + CAN_SET_METADATA = ['title', 'authors', 'collections'] + + #: Whether the device can handle device_db metadata plugboards + CAN_DO_DEVICE_DB_PLUGBOARD = False + + # Set this to None if the books on the device are files that the GUI can + # access in order to add the books from the device to the library + BACKLOADING_ERROR_MESSAGE = _('Cannot get files from this device') + + #: Path separator for paths to books on device + path_sep = os.sep + + #: Icon for this device + icon = I('reader.png') + + # Encapsulates an annotation fetched from the device + UserAnnotation = namedtuple('Annotation','type, value') + + #: GUI displays this as a message if not None. Useful if opening can take a + #: long time + OPEN_FEEDBACK_MESSAGE = None + + #: Set of extensions that are "virtual books" on the device + #: and therefore cannot be viewed/saved/added to library. + #: For example: ``frozenset(['kobo'])`` + VIRTUAL_BOOK_EXTENSIONS = frozenset() + + #: Message to display to user for virtual book extensions. + VIRTUAL_BOOK_EXTENSION_MESSAGE = None + + #: Whether to nuke comments in the copy of the book sent to the device. If + #: not None this should be short string that the comments will be replaced + #: by. + NUKE_COMMENTS = None + + #: If True indicates that this driver completely manages device detection, + #: ejecting and so forth. If you set this to True, you *must* implement the + #: detect_managed_devices and debug_managed_device_detection methods. + #: A driver with this set to true is responsible for detection of devices, + #: managing a blacklist of devices, a list of ejected devices and so forth. + #: calibre will periodically call the detect_managed_devices() method and + #: if it returns a detected device, calibre will call open(). open() will + #: be called every time a device is returned even if previous calls to open() + #: failed, therefore the driver must maintain its own blacklist of failed + #: devices. Similarly, when ejecting, calibre will call eject() and then + #: assuming the next call to detect_managed_devices() returns None, it will + #: call post_yank_cleanup(). + MANAGES_DEVICE_PRESENCE = False + + #: If set the True, calibre will call the :meth:`get_driveinfo()` method + #: after the books lists have been loaded to get the driveinfo. + SLOW_DRIVEINFO = False + + #: If set to True, calibre will ask the user if they want to manage the + #: device with calibre, the first time it is detected. If you set this to + #: True you must implement :meth:`get_device_uid()` and + #: :meth:`ignore_connected_device()` and + #: :meth:`get_user_blacklisted_devices` and + #: :meth:`set_user_blacklisted_devices` + ASK_TO_ALLOW_CONNECT = False + + #: Set this to a dictionary of the form {'title':title, 'msg':msg, 'det_msg':detailed_msg} to have calibre popup + #: a message to the user after some callbacks are run (currently only upload_books). + #: Be careful to not spam the user with too many messages. This variable is checked after *every* callback, + #: so only set it when you really need to. + user_feedback_after_callback = None + + @classmethod + def get_gui_name(cls): + if hasattr(cls, 'gui_name'): + return cls.gui_name + if hasattr(cls, '__name__'): + return cls.__name__ + return cls.name + + # Device detection {{{ + def test_bcd(self, bcdDevice, bcd): + if bcd is None or len(bcd) == 0: + return True + for c in bcd: + if c == bcdDevice: + return True + return False + + def is_usb_connected(self, devices_on_system, debug=False, only_presence=False): + ''' + Return True, device_info if a device handled by this plugin is currently connected. + + :param devices_on_system: List of devices currently connected + + ''' + vendors_on_system = {x[0] for x in devices_on_system} + vendors = set(self.VENDOR_ID) if hasattr(self.VENDOR_ID, '__len__') else {self.VENDOR_ID} + if hasattr(self.VENDOR_ID, 'keys'): + products = [] + for ven in self.VENDOR_ID: + products.extend(self.VENDOR_ID[ven].keys()) + else: + products = self.PRODUCT_ID if hasattr(self.PRODUCT_ID, '__len__') else [self.PRODUCT_ID] + + ch = self.can_handle_windows if iswindows else self.can_handle + for vid in vendors_on_system.intersection(vendors): + for dev in devices_on_system: + cvid, pid, bcd = dev[:3] + if cvid == vid: + if pid in products: + if hasattr(self.VENDOR_ID, 'keys'): + try: + cbcd = self.VENDOR_ID[vid][pid] + except KeyError: + # Vendor vid does not have product pid, pid + # exists for some other vendor in this + # device + continue + else: + cbcd = self.BCD + if self.test_bcd(bcd, cbcd): + if debug: + prints(dev) + if ch(dev, debug=debug): + return True, dev + return False, None + + def detect_managed_devices(self, devices_on_system, force_refresh=False): + ''' + Called only if MANAGES_DEVICE_PRESENCE is True. + + Scan for devices that this driver can handle. Should return a device + object if a device is found. This object will be passed to the open() + method as the connected_device. If no device is found, return None. The + returned object can be anything, calibre does not use it, it is only + passed to open(). + + This method is called periodically by the GUI, so make sure it is not + too resource intensive. Use a cache to avoid repeatedly scanning the + system. + + :param devices_on_system: Set of USB devices found on the system. + + :param force_refresh: If True and the driver uses a cache to prevent + repeated scanning, the cache must be flushed. + + ''' + raise NotImplementedError() + + def debug_managed_device_detection(self, devices_on_system, output): + ''' + Called only if MANAGES_DEVICE_PRESENCE is True. + + Should write information about the devices detected on the system to + output, which is a file like object. + + Should return True if a device was detected and successfully opened, + otherwise False. + ''' + raise NotImplementedError() + + # }}} + + def reset(self, key='-1', log_packets=False, report_progress=None, + detected_device=None): + """ + :param key: The key to unlock the device + :param log_packets: If true the packet stream to/from the device is logged + :param report_progress: Function that is called with a % progress + (number between 0 and 100) for various tasks + If it is called with -1 that means that the + task does not have any progress information + :param detected_device: Device information from the device scanner + + """ + raise NotImplementedError() + + def can_handle_windows(self, usbdevice, debug=False): + ''' + Optional method to perform further checks on a device to see if this driver + is capable of handling it. If it is not it should return False. This method + is only called after the vendor, product ids and the bcd have matched, so + it can do some relatively time intensive checks. The default implementation + returns True. This method is called only on Windows. See also + :meth:`can_handle`. + + Note that for devices based on USBMS this method by default delegates + to :meth:`can_handle`. So you only need to override :meth:`can_handle` + in your subclass of USBMS. + + :param usbdevice: A usbdevice as returned by :func:`calibre.devices.winusb.scan_usb_devices` + ''' + return True + + def can_handle(self, device_info, debug=False): + ''' + Unix version of :meth:`can_handle_windows`. + + :param device_info: Is a tuple of (vid, pid, bcd, manufacturer, product, + serial number) + + ''' + + return True + can_handle.is_base_class_implementation = True + + def open(self, connected_device, library_uuid): + ''' + Perform any device specific initialization. Called after the device is + detected but before any other functions that communicate with the device. + For example: For devices that present themselves as USB Mass storage + devices, this method would be responsible for mounting the device or + if the device has been automounted, for finding out where it has been + mounted. The method :meth:`calibre.devices.usbms.device.Device.open` has + an implementation of + this function that should serve as a good example for USB Mass storage + devices. + + This method can raise an OpenFeedback exception to display a message to + the user. + + :param connected_device: The device that we are trying to open. It is + a tuple of (vendor id, product id, bcd, manufacturer name, product + name, device serial number). However, some devices have no serial + number and on windows only the first three fields are present, the + rest are None. + + :param library_uuid: The UUID of the current calibre library. Can be + None if there is no library (for example when used from the command + line). + + ''' + raise NotImplementedError() + + def eject(self): + ''' + Un-mount / eject the device from the OS. This does not check if there + are pending GUI jobs that need to communicate with the device. + + NOTE: That this method may not be called on the same thread as the rest + of the device methods. + ''' + raise NotImplementedError() + + def post_yank_cleanup(self): + ''' + Called if the user yanks the device without ejecting it first. + ''' + raise NotImplementedError() + + def set_progress_reporter(self, report_progress): + ''' + Set a function to report progress information. + + :param report_progress: Function that is called with a % progress + (number between 0 and 100) for various tasks + If it is called with -1 that means that the + task does not have any progress information + + ''' + raise NotImplementedError() + + def get_device_information(self, end_session=True): + """ + Ask device for device information. See L{DeviceInfoQuery}. + + :return: (device name, device version, software version on device, mime type) + The tuple can optionally have a fifth element, which is a + drive information dictionary. See usbms.driver for an example. + + """ + raise NotImplementedError() + + def get_driveinfo(self): + ''' + Return the driveinfo dictionary. Usually called from + get_device_information(), but if loading the driveinfo is slow for this + driver, then it should set SLOW_DRIVEINFO. In this case, this method + will be called by calibre after the book lists have been loaded. Note + that it is not called on the device thread, so the driver should cache + the drive info in the books() method and this function should return + the cached data. + ''' + return {} + + def card_prefix(self, end_session=True): + ''' + Return a 2 element list of the prefix to paths on the cards. + If no card is present None is set for the card's prefix. + E.G. + ('/place', '/place2') + (None, 'place2') + ('place', None) + (None, None) + ''' + raise NotImplementedError() + + def total_space(self, end_session=True): + """ + Get total space available on the mountpoints: + 1. Main memory + 2. Memory Card A + 3. Memory Card B + + :return: A 3 element list with total space in bytes of (1, 2, 3). If a + particular device doesn't have any of these locations it should return 0. + + """ + raise NotImplementedError() + + def free_space(self, end_session=True): + """ + Get free space available on the mountpoints: + 1. Main memory + 2. Card A + 3. Card B + + :return: A 3 element list with free space in bytes of (1, 2, 3). If a + particular device doesn't have any of these locations it should return -1. + + """ + raise NotImplementedError() + + def books(self, oncard=None, end_session=True): + """ + Return a list of e-books on the device. + + :param oncard: If 'carda' or 'cardb' return a list of e-books on the + specific storage card, otherwise return list of e-books + in main memory of device. If a card is specified and no + books are on the card return empty list. + + :return: A BookList. + + """ + raise NotImplementedError() + + def upload_books(self, files, names, on_card=None, end_session=True, + metadata=None): + ''' + Upload a list of books to the device. If a file already + exists on the device, it should be replaced. + This method should raise a :class:`FreeSpaceError` if there is not enough + free space on the device. The text of the FreeSpaceError must contain the + word "card" if ``on_card`` is not None otherwise it must contain the word "memory". + + :param files: A list of paths + :param names: A list of file names that the books should have + once uploaded to the device. len(names) == len(files) + :param metadata: If not None, it is a list of :class:`Metadata` objects. + The idea is to use the metadata to determine where on the device to + put the book. len(metadata) == len(files). Apart from the regular + cover (path to cover), there may also be a thumbnail attribute, which should + be used in preference. The thumbnail attribute is of the form + (width, height, cover_data as jpeg). + + :return: A list of 3-element tuples. The list is meant to be passed + to :meth:`add_books_to_metadata`. + ''' + raise NotImplementedError() + + @classmethod + def add_books_to_metadata(cls, locations, metadata, booklists): + ''' + Add locations to the booklists. This function must not communicate with + the device. + + :param locations: Result of a call to L{upload_books} + :param metadata: List of :class:`Metadata` objects, same as for + :meth:`upload_books`. + :param booklists: A tuple containing the result of calls to + (:meth:`books(oncard=None)`, + :meth:`books(oncard='carda')`, + :meth`books(oncard='cardb')`). + + ''' + raise NotImplementedError() + + def delete_books(self, paths, end_session=True): + ''' + Delete books at paths on device. + ''' + raise NotImplementedError() + + @classmethod + def remove_books_from_metadata(cls, paths, booklists): + ''' + Remove books from the metadata list. This function must not communicate + with the device. + + :param paths: paths to books on the device. + :param booklists: A tuple containing the result of calls to + (:meth:`books(oncard=None)`, + :meth:`books(oncard='carda')`, + :meth`books(oncard='cardb')`). + + ''' + raise NotImplementedError() + + def sync_booklists(self, booklists, end_session=True): + ''' + Update metadata on device. + + :param booklists: A tuple containing the result of calls to + (:meth:`books(oncard=None)`, + :meth:`books(oncard='carda')`, + :meth`books(oncard='cardb')`). + + ''' + raise NotImplementedError() + + def get_file(self, path, outfile, end_session=True): + ''' + Read the file at ``path`` on the device and write it to outfile. + + :param outfile: file object like ``sys.stdout`` or the result of an + :func:`open` call. + + ''' + raise NotImplementedError() + + @classmethod + def config_widget(cls): + ''' + Should return a QWidget. The QWidget contains the settings for the + device interface + ''' + raise NotImplementedError() + + @classmethod + def save_settings(cls, settings_widget): + ''' + Should save settings to disk. Takes the widget created in + :meth:`config_widget` and saves all settings to disk. + ''' + raise NotImplementedError() + + @classmethod + def settings(cls): + ''' + Should return an opts object. The opts object should have at least one + attribute `format_map` which is an ordered list of formats for the + device. + ''' + raise NotImplementedError() + + def set_plugboards(self, plugboards, pb_func): + ''' + provide the driver the current set of plugboards and a function to + select a specific plugboard. This method is called immediately before + add_books and sync_booklists. + + pb_func is a callable with the following signature:: + def pb_func(device_name, format, plugboards) + + You give it the current device name (either the class name or + DEVICE_PLUGBOARD_NAME), the format you are interested in (a 'real' + format or 'device_db'), and the plugboards (you were given those by + set_plugboards, the same place you got this method). + + :return: None or a single plugboard instance. + + ''' + pass + + def set_driveinfo_name(self, location_code, name): + ''' + Set the device name in the driveinfo file to 'name'. This setting will + persist until the file is re-created or the name is changed again. + + Non-disk devices should implement this method based on the location + codes returned by the get_device_information() method. + ''' + pass + + def prepare_addable_books(self, paths): + ''' + Given a list of paths, returns another list of paths. These paths + point to addable versions of the books. + + If there is an error preparing a book, then instead of a path, the + position in the returned list for that book should be a three tuple: + (original_path, the exception instance, traceback) + ''' + return paths + + def startup(self): + ''' + Called when calibre is starting the device. Do any initialization + required. Note that multiple instances of the class can be instantiated, + and thus __init__ can be called multiple times, but only one instance + will have this method called. This method is called on the device + thread, not the GUI thread. + ''' + pass + + def shutdown(self): + ''' + Called when calibre is shutting down, either for good or in preparation + to restart. Do any cleanup required. This method is called on the + device thread, not the GUI thread. + ''' + pass + + def get_device_uid(self): + ''' + Must return a unique id for the currently connected device (this is + called immediately after a successful call to open()). You must + implement this method if you set ASK_TO_ALLOW_CONNECT = True + ''' + raise NotImplementedError() + + def ignore_connected_device(self, uid): + ''' + Should ignore the device identified by uid (the result of a call to + get_device_uid()) in the future. You must implement this method if you + set ASK_TO_ALLOW_CONNECT = True. Note that this function is called + immediately after open(), so if open() caches some state, the driver + should reset that state. + ''' + raise NotImplementedError() + + def get_user_blacklisted_devices(self): + ''' + Return map of device uid to friendly name for all devices that the user + has asked to be ignored. + ''' + return {} + + def set_user_blacklisted_devices(self, devices): + ''' + Set the list of device uids that should be ignored by this driver. + ''' + pass + + def specialize_global_preferences(self, device_prefs): + ''' + Implement this method if your device wants to override a particular + preference. You must ensure that all call sites that want a preference + that can be overridden use device_prefs['something'] instead + of prefs['something']. Your + method should call device_prefs.set_overrides(pref=val, pref=val, ...). + Currently used for: + metadata management (prefs['manage_device_metadata']) + ''' + device_prefs.set_overrides() + + def set_library_info(self, library_name, library_uuid, field_metadata): + ''' + Implement this method if you want information about the current calibre + library. This method is called at startup and when the calibre library + changes while connected. + ''' + pass + + # Dynamic control interface. + # The following methods are probably called on the GUI thread. Any driver + # that implements these methods must take pains to be thread safe, because + # the device_manager might be using the driver at the same time that one of + # these methods is called. + + def is_dynamically_controllable(self): + ''' + Called by the device manager when starting plugins. If this method returns + a string, then a) it supports the device manager's dynamic control + interface, and b) that name is to be used when talking to the plugin. + + This method can be called on the GUI thread. A driver that implements + this method must be thread safe. + ''' + return None + + def start_plugin(self): + ''' + This method is called to start the plugin. The plugin should begin + to accept device connections however it does that. If the plugin is + already accepting connections, then do nothing. + + This method can be called on the GUI thread. A driver that implements + this method must be thread safe. + ''' + pass + + def stop_plugin(self): + ''' + This method is called to stop the plugin. The plugin should no longer + accept connections, and should cleanup behind itself. It is likely that + this method should call shutdown. If the plugin is already not accepting + connections, then do nothing. + + This method can be called on the GUI thread. A driver that implements + this method must be thread safe. + ''' + pass + + def get_option(self, opt_string, default=None): + ''' + Return the value of the option indicated by opt_string. This method can + be called when the plugin is not started. Return None if the option does + not exist. + + This method can be called on the GUI thread. A driver that implements + this method must be thread safe. + ''' + return default + + def set_option(self, opt_string, opt_value): + ''' + Set the value of the option indicated by opt_string. This method can + be called when the plugin is not started. + + This method can be called on the GUI thread. A driver that implements + this method must be thread safe. + ''' + pass + + def is_running(self): + ''' + Return True if the plugin is started, otherwise false + + This method can be called on the GUI thread. A driver that implements + this method must be thread safe. + ''' + return False + + def synchronize_with_db(self, db, book_id, book_metadata, first_call): + ''' + Called during book matching when a book on the device is matched with + a book in calibre's db. The method is responsible for syncronizing + data from the device to calibre's db (if needed). + + The method must return a two-value tuple. The first value is a set of + calibre book ids changed if calibre's database was changed or None if the + database was not changed. If the first value is an empty set then the + metadata for the book on the device is updated with calibre's metadata + and given back to the device, but no GUI refresh of that book is done. + This is useful when the calibre data is correct but must be sent to the + device. + + The second value is itself a 2-value tuple. The first value in the tuple + specifies whether a book format should be sent to the device. The intent + is to permit verifying that the book on the device is the same as the + book in calibre. This value must be None if no book is to be sent, + otherwise return the base file name on the device (a string like + foobar.epub). Be sure to include the extension in the name. The device + subsystem will construct a send_books job for all books with not- None + returned values. Note: other than to later retrieve the extension, the + name is ignored in cases where the device uses a template to generate + the file name, which most do. The second value in the returned tuple + indicated whether the format is future-dated. Return True if it is, + otherwise return False. calibre will display a dialog to the user + listing all future dated books. + + Extremely important: this method is called on the GUI thread. It must + be threadsafe with respect to the device manager's thread. + + book_id: the calibre id for the book in the database. + book_metadata: the Metadata object for the book coming from the device. + first_call: True if this is the first call during a sync, False otherwise + ''' + return (None, (None, False)) + + +class BookList(list): + ''' + A list of books. Each Book object must have the fields + + #. title + #. authors + #. size (file size of the book) + #. datetime (a UTC time tuple) + #. path (path on the device to the book) + #. thumbnail (can be None) thumbnail is either a str/bytes object with the + image data or it should have an attribute image_path that stores an + absolute (platform native) path to the image + #. tags (a list of strings, can be empty). + + ''' + + __getslice__ = None + __setslice__ = None + + def __init__(self, oncard, prefix, settings): + pass + + def supports_collections(self): + ''' Return True if the device supports collections for this book list. ''' + raise NotImplementedError() + + def add_book(self, book, replace_metadata): + ''' + Add the book to the booklist. Intent is to maintain any device-internal + metadata. Return True if booklists must be sync'ed + ''' + raise NotImplementedError() + + def remove_book(self, book): + ''' + Remove a book from the booklist. Correct any device metadata at the + same time + ''' + raise NotImplementedError() + + def get_collections(self, collection_attributes): + ''' + Return a dictionary of collections created from collection_attributes. + Each entry in the dictionary is of the form collection name:[list of + books] + + The list of books is sorted by book title, except for collections + created from series, in which case series_index is used. + + :param collection_attributes: A list of attributes of the Book object + + ''' + raise NotImplementedError() + + +class CurrentlyConnectedDevice(object): + + def __init__(self): + self._device = None + + @property + def device(self): + return self._device + + +# A device driver can check if a device is currently connected to calibre using +# the following code:: +# from calibre.device.interface import currently_connected_device +# if currently_connected_device.device is None: +# # no device connected +# The device attribute will be either None or the device driver object +# (DevicePlugin instance) for the currently connected device. +currently_connected_device = CurrentlyConnectedDevice() diff --git a/ebook_converter/ebooks/BeautifulSoup.py b/ebook_converter/ebooks/BeautifulSoup.py new file mode 100644 index 0000000..76d8683 --- /dev/null +++ b/ebook_converter/ebooks/BeautifulSoup.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +# License: GPLv3 Copyright: 2019, Kovid Goyal + +from __future__ import absolute_import, division, print_function, unicode_literals + +import bs4 +from bs4 import ( # noqa + CData, Comment, Declaration, NavigableString, ProcessingInstruction, + SoupStrainer, Tag, __version__ +) + +from polyglot.builtins import unicode_type + + +def parse_html(markup): + from calibre.ebooks.chardet import strip_encoding_declarations, xml_to_unicode, substitute_entites + from calibre.utils.cleantext import clean_xml_chars + if isinstance(markup, unicode_type): + markup = strip_encoding_declarations(markup) + markup = substitute_entites(markup) + else: + markup = xml_to_unicode(markup, strip_encoding_pats=True, resolve_entities=True)[0] + markup = clean_xml_chars(markup) + from html5_parser.soup import parse + return parse(markup, return_root=False) + + +def prettify(soup): + ans = soup.prettify() + if isinstance(ans, bytes): + ans = ans.decode('utf-8') + return ans + + +def BeautifulSoup(markup='', *a, **kw): + return parse_html(markup) + + +def BeautifulStoneSoup(markup='', *a, **kw): + return bs4.BeautifulSoup(markup, 'xml') diff --git a/ebook_converter/ebooks/__init__.py b/ebook_converter/ebooks/__init__.py new file mode 100644 index 0000000..a88f751 --- /dev/null +++ b/ebook_converter/ebooks/__init__.py @@ -0,0 +1,248 @@ +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2008, Kovid Goyal ' + +''' +Code for the conversion of ebook formats and the reading of metadata +from various formats. +''' + +import os, re, numbers, sys +from calibre import prints +from calibre.ebooks.chardet import xml_to_unicode +from polyglot.builtins import unicode_type + + +class ConversionError(Exception): + + def __init__(self, msg, only_msg=False): + Exception.__init__(self, msg) + self.only_msg = only_msg + + +class UnknownFormatError(Exception): + pass + + +class DRMError(ValueError): + pass + + +class ParserError(ValueError): + pass + + +BOOK_EXTENSIONS = ['lrf', 'rar', 'zip', 'rtf', 'lit', 'txt', 'txtz', 'text', 'htm', 'xhtm', + 'html', 'htmlz', 'xhtml', 'pdf', 'pdb', 'updb', 'pdr', 'prc', 'mobi', 'azw', 'doc', + 'epub', 'fb2', 'fbz', 'djv', 'djvu', 'lrx', 'cbr', 'cbz', 'cbc', 'oebzip', + 'rb', 'imp', 'odt', 'chm', 'tpz', 'azw1', 'pml', 'pmlz', 'mbp', 'tan', 'snb', + 'xps', 'oxps', 'azw4', 'book', 'zbf', 'pobi', 'docx', 'docm', 'md', + 'textile', 'markdown', 'ibook', 'ibooks', 'iba', 'azw3', 'ps', 'kepub', 'kfx', 'kpf'] + + +def return_raster_image(path): + from calibre.utils.imghdr import what + if os.access(path, os.R_OK): + with open(path, 'rb') as f: + raw = f.read() + if what(None, raw) not in (None, 'svg'): + return raw + + +def extract_cover_from_embedded_svg(html, base, log): + from calibre.ebooks.oeb.base import XPath, SVG, XLINK + from calibre.utils.xml_parse import safe_xml_fromstring + root = safe_xml_fromstring(html) + + svg = XPath('//svg:svg')(root) + if len(svg) == 1 and len(svg[0]) == 1 and svg[0][0].tag == SVG('image'): + image = svg[0][0] + href = image.get(XLINK('href'), None) + if href: + path = os.path.join(base, *href.split('/')) + return return_raster_image(path) + + +def extract_calibre_cover(raw, base, log): + from calibre.ebooks.BeautifulSoup import BeautifulSoup + soup = BeautifulSoup(raw) + matches = soup.find(name=['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'span', + 'font', 'br']) + images = soup.findAll('img', src=True) + if matches is None and len(images) == 1 and \ + images[0].get('alt', '').lower()=='cover': + img = images[0] + img = os.path.join(base, *img['src'].split('/')) + q = return_raster_image(img) + if q is not None: + return q + + # Look for a simple cover, i.e. a body with no text and only one tag + if matches is None: + body = soup.find('body') + if body is not None: + text = u''.join(map(unicode_type, body.findAll(text=True))) + if text.strip(): + # Body has text, abort + return + images = body.findAll('img', src=True) + if len(images) == 1: + img = os.path.join(base, *images[0]['src'].split('/')) + return return_raster_image(img) + + +def render_html_svg_workaround(path_to_html, log, width=590, height=750): + from calibre.ebooks.oeb.base import SVG_NS + with open(path_to_html, 'rb') as f: + raw = f.read() + raw = xml_to_unicode(raw, strip_encoding_pats=True)[0] + data = None + if SVG_NS in raw: + try: + data = extract_cover_from_embedded_svg(raw, + os.path.dirname(path_to_html), log) + except Exception: + pass + if data is None: + try: + data = extract_calibre_cover(raw, os.path.dirname(path_to_html), log) + except Exception: + pass + + if data is None: + data = render_html_data(path_to_html, width, height) + return data + + +def render_html_data(path_to_html, width, height): + from calibre.ptempfile import TemporaryDirectory + from calibre.utils.ipc.simple_worker import fork_job, WorkerError + result = {} + + def report_error(text=''): + prints('Failed to render', path_to_html, 'with errors:', file=sys.stderr) + if text: + prints(text, file=sys.stderr) + if result and result['stdout_stderr']: + with open(result['stdout_stderr'], 'rb') as f: + prints(f.read(), file=sys.stderr) + + with TemporaryDirectory('-render-html') as tdir: + try: + result = fork_job('calibre.ebooks.render_html', 'main', args=(path_to_html, tdir, 'jpeg')) + except WorkerError as e: + report_error(e.orig_tb) + else: + if result['result']: + with open(os.path.join(tdir, 'rendered.jpeg'), 'rb') as f: + return f.read() + else: + report_error() + + +def check_ebook_format(stream, current_guess): + ans = current_guess + if current_guess.lower() in ('prc', 'mobi', 'azw', 'azw1', 'azw3'): + stream.seek(0) + if stream.read(3) == b'TPZ': + ans = 'tpz' + stream.seek(0) + return ans + + +def normalize(x): + if isinstance(x, unicode_type): + import unicodedata + x = unicodedata.normalize('NFC', x) + return x + + +def calibre_cover(title, author_string, series_string=None, + output_format='jpg', title_size=46, author_size=36, logo_path=None): + title = normalize(title) + author_string = normalize(author_string) + series_string = normalize(series_string) + from calibre.ebooks.covers import calibre_cover2 + from calibre.utils.img import image_to_data + ans = calibre_cover2(title, author_string or '', series_string or '', logo_path=logo_path, as_qimage=True) + return image_to_data(ans, fmt=output_format) + + +UNIT_RE = re.compile(r'^(-*[0-9]*[.]?[0-9]*)\s*(%|em|ex|en|px|mm|cm|in|pt|pc|rem|q)$') + + +def unit_convert(value, base, font, dpi, body_font_size=12): + ' Return value in pts' + if isinstance(value, numbers.Number): + return value + try: + return float(value) * 72.0 / dpi + except: + pass + result = value + m = UNIT_RE.match(value) + if m is not None and m.group(1): + value = float(m.group(1)) + unit = m.group(2) + if unit == '%': + result = (value / 100.0) * base + elif unit == 'px': + result = value * 72.0 / dpi + elif unit == 'in': + result = value * 72.0 + elif unit == 'pt': + result = value + elif unit == 'em': + result = value * font + elif unit in ('ex', 'en'): + # This is a hack for ex since we have no way to know + # the x-height of the font + font = font + result = value * font * 0.5 + elif unit == 'pc': + result = value * 12.0 + elif unit == 'mm': + result = value * 2.8346456693 + elif unit == 'cm': + result = value * 28.346456693 + elif unit == 'rem': + result = value * body_font_size + elif unit == 'q': + result = value * 0.708661417325 + return result + + +def parse_css_length(value): + try: + m = UNIT_RE.match(value) + except TypeError: + return None, None + if m is not None and m.group(1): + value = float(m.group(1)) + unit = m.group(2) + return value, unit.lower() + return None, None + + +def generate_masthead(title, output_path=None, width=600, height=60): + from calibre.ebooks.conversion.config import load_defaults + recs = load_defaults('mobi_output') + masthead_font_family = recs.get('masthead_font', None) + from calibre.ebooks.covers import generate_masthead + return generate_masthead(title, output_path=output_path, width=width, height=height, font_family=masthead_font_family) + + +def escape_xpath_attr(value): + if '"' in value: + if "'" in value: + parts = re.split('("+)', value) + ans = [] + for x in parts: + if x: + q = "'" if '"' in x else '"' + ans.append(q + x + q) + return 'concat(%s)' % ', '.join(ans) + else: + return "'%s'" % value + return '"%s"' % value diff --git a/ebook_converter/ebooks/chardet.py b/ebook_converter/ebooks/chardet.py new file mode 100644 index 0000000..8abe1ff --- /dev/null +++ b/ebook_converter/ebooks/chardet.py @@ -0,0 +1,189 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2009, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import re, codecs +from polyglot.builtins import unicode_type + +_encoding_pats = ( + # XML declaration + r'<\?[^<>]+encoding\s*=\s*[\'"](.*?)[\'"][^<>]*>', + # HTML 5 charset + r''']*>(?:\s*){0,1}''', + # HTML 4 Pragma directive + r''']*?content\s*=\s*['"][^'"]*?charset=([-_a-z0-9]+)[^'"]*?['"][^<>]*>(?:\s*){0,1}''', +) + + +def compile_pats(binary): + for raw in _encoding_pats: + if binary: + raw = raw.encode('ascii') + yield re.compile(raw, flags=re.IGNORECASE) + + +class LazyEncodingPats(object): + + def __call__(self, binary=False): + attr = 'binary_pats' if binary else 'unicode_pats' + pats = getattr(self, attr, None) + if pats is None: + pats = tuple(compile_pats(binary)) + setattr(self, attr, pats) + for pat in pats: + yield pat + + +lazy_encoding_pats = LazyEncodingPats() +ENTITY_PATTERN = re.compile(r'&(\S+?);') + + +def strip_encoding_declarations(raw, limit=50*1024, preserve_newlines=False): + prefix = raw[:limit] + suffix = raw[limit:] + is_binary = isinstance(raw, bytes) + if preserve_newlines: + if is_binary: + sub = lambda m: b'\n' * m.group().count(b'\n') + else: + sub = lambda m: '\n' * m.group().count('\n') + else: + sub = b'' if is_binary else u'' + for pat in lazy_encoding_pats(is_binary): + prefix = pat.sub(sub, prefix) + raw = prefix + suffix + return raw + + +def replace_encoding_declarations(raw, enc='utf-8', limit=50*1024): + prefix = raw[:limit] + suffix = raw[limit:] + changed = [False] + is_binary = isinstance(raw, bytes) + if is_binary: + if not isinstance(enc, bytes): + enc = enc.encode('ascii') + else: + if isinstance(enc, bytes): + enc = enc.decode('ascii') + + def sub(m): + ans = m.group() + if m.group(1).lower() != enc.lower(): + changed[0] = True + start, end = m.start(1) - m.start(0), m.end(1) - m.end(0) + ans = ans[:start] + enc + ans[end:] + return ans + + for pat in lazy_encoding_pats(is_binary): + prefix = pat.sub(sub, prefix) + raw = prefix + suffix + return raw, changed[0] + + +def find_declared_encoding(raw, limit=50*1024): + prefix = raw[:limit] + is_binary = isinstance(raw, bytes) + for pat in lazy_encoding_pats(is_binary): + m = pat.search(prefix) + if m is not None: + ans = m.group(1) + if is_binary: + ans = ans.decode('ascii', 'replace') + return ans + + +def substitute_entites(raw): + from calibre import xml_entity_to_unicode + return ENTITY_PATTERN.sub(xml_entity_to_unicode, raw) + + +_CHARSET_ALIASES = {"macintosh" : "mac-roman", + "x-sjis" : "shift-jis"} + + +def detect(*args, **kwargs): + from chardet import detect + return detect(*args, **kwargs) + + +def force_encoding(raw, verbose, assume_utf8=False): + from calibre.constants import preferred_encoding + + try: + chardet = detect(raw[:1024*50]) + except: + chardet = {'encoding':preferred_encoding, 'confidence':0} + encoding = chardet['encoding'] + if chardet['confidence'] < 1 and assume_utf8: + encoding = 'utf-8' + if chardet['confidence'] < 1 and verbose: + print('WARNING: Encoding detection confidence for %s is %d%%'%( + chardet['encoding'], chardet['confidence']*100)) + if not encoding: + encoding = preferred_encoding + encoding = encoding.lower() + encoding = _CHARSET_ALIASES.get(encoding, encoding) + if encoding == 'ascii': + encoding = 'utf-8' + return encoding + + +def detect_xml_encoding(raw, verbose=False, assume_utf8=False): + if not raw or isinstance(raw, unicode_type): + return raw, None + for x in ('utf8', 'utf-16-le', 'utf-16-be'): + bom = getattr(codecs, 'BOM_'+x.upper().replace('-16', '16').replace( + '-', '_')) + if raw.startswith(bom): + return raw[len(bom):], x + encoding = None + for pat in lazy_encoding_pats(True): + match = pat.search(raw) + if match: + encoding = match.group(1) + encoding = encoding.decode('ascii', 'replace') + break + if encoding is None: + encoding = force_encoding(raw, verbose, assume_utf8=assume_utf8) + if encoding.lower().strip() == 'macintosh': + encoding = 'mac-roman' + if encoding.lower().replace('_', '-').strip() in ( + 'gb2312', 'chinese', 'csiso58gb231280', 'euc-cn', 'euccn', + 'eucgb2312-cn', 'gb2312-1980', 'gb2312-80', 'iso-ir-58'): + # Microsoft Word exports to HTML with encoding incorrectly set to + # gb2312 instead of gbk. gbk is a superset of gb2312, anyway. + encoding = 'gbk' + try: + codecs.lookup(encoding) + except LookupError: + encoding = 'utf-8' + + return raw, encoding + + +def xml_to_unicode(raw, verbose=False, strip_encoding_pats=False, + resolve_entities=False, assume_utf8=False): + ''' + Force conversion of byte string to unicode. Tries to look for XML/HTML + encoding declaration first, if not found uses the chardet library and + prints a warning if detection confidence is < 100% + @return: (unicode, encoding used) + ''' + if not raw: + return '', None + raw, encoding = detect_xml_encoding(raw, verbose=verbose, + assume_utf8=assume_utf8) + if not isinstance(raw, unicode_type): + raw = raw.decode(encoding, 'replace') + + if strip_encoding_pats: + raw = strip_encoding_declarations(raw) + if resolve_entities: + raw = substitute_entites(raw) + + return raw, encoding diff --git a/ebook_converter/ebooks/compression/__init__.py b/ebook_converter/ebooks/compression/__init__.py new file mode 100644 index 0000000..c2b7016 --- /dev/null +++ b/ebook_converter/ebooks/compression/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL 3' +__copyright__ = '2009, John Schember ' +__docformat__ = 'restructuredtext en' diff --git a/ebook_converter/ebooks/compression/palmdoc.c b/ebook_converter/ebooks/compression/palmdoc.c new file mode 100644 index 0000000..e415f37 --- /dev/null +++ b/ebook_converter/ebooks/compression/palmdoc.c @@ -0,0 +1,238 @@ +/* +:mod:`cPalmdoc` -- Palmdoc compression/decompression +===================================================== + +.. module:: cPalmdoc + :platform: All + :synopsis: Compression decompression of Palmdoc implemented in C for speed + +.. moduleauthor:: Kovid Goyal Copyright 2009 + +*/ + +#define PY_SSIZE_T_CLEAN +#include +#include + +#define BUFFER 6000 + +#define MIN(x, y) ( ((x) < (y)) ? (x) : (y) ) +#define MAX(x, y) ( ((x) > (y)) ? (x) : (y) ) + +typedef unsigned short int Byte; +typedef struct { + Byte *data; + Py_ssize_t len; +} buffer; + +#ifdef bool +#undef bool +#endif +#define bool int + +#ifdef false +#undef false +#endif +#define false 0 + +#ifdef true +#undef true +#endif +#define true 1 + +#define CHAR(x) (( (x) > 127 ) ? (x)-256 : (x)) + +#if PY_MAJOR_VERSION >= 3 + #define BUFFER_FMT "y#" + #define BYTES_FMT "y#" +#else + #define BUFFER_FMT "t#" + #define BYTES_FMT "s#" +#endif + +static PyObject * +cpalmdoc_decompress(PyObject *self, PyObject *args) { + const char *_input = NULL; Py_ssize_t input_len = 0; + Byte *input; char *output; Byte c; PyObject *ans; + Py_ssize_t i = 0, o = 0, j = 0, di, n; + if (!PyArg_ParseTuple(args, BUFFER_FMT, &_input, &input_len)) + return NULL; + input = (Byte *) PyMem_Malloc(sizeof(Byte)*input_len); + if (input == NULL) return PyErr_NoMemory(); + // Map chars to bytes + for (j = 0; j < input_len; j++) + input[j] = (_input[j] < 0) ? _input[j]+256 : _input[j]; + output = (char *)PyMem_Malloc(sizeof(char)*(MAX(BUFFER, 8*input_len))); + if (output == NULL) return PyErr_NoMemory(); + + while (i < input_len) { + c = input[i++]; + if (c >= 1 && c <= 8) // copy 'c' bytes + while (c--) output[o++] = (char)input[i++]; + + else if (c <= 0x7F) // 0, 09-7F = self + output[o++] = (char)c; + + else if (c >= 0xC0) { // space + ASCII char + output[o++] = ' '; + output[o++] = c ^ 0x80; + } + else { // 80-BF repeat sequences + c = (c << 8) + input[i++]; + di = (c & 0x3FFF) >> 3; + for ( n = (c & 7) + 3; n--; ++o ) + output[o] = output[o - di]; + } + } + ans = Py_BuildValue(BYTES_FMT, output, o); + if (output != NULL) PyMem_Free(output); + if (input != NULL) PyMem_Free(input); + return ans; +} + +static bool +cpalmdoc_memcmp( Byte *a, Byte *b, Py_ssize_t len) { + Py_ssize_t i; + for (i = 0; i < len; i++) if (a[i] != b[i]) return false; + return true; +} + +static Py_ssize_t +cpalmdoc_rfind(Byte *data, Py_ssize_t pos, Py_ssize_t chunk_length) { + Py_ssize_t i; + for (i = pos - chunk_length; i > -1; i--) + if (cpalmdoc_memcmp(data+i, data+pos, chunk_length)) return i; + return pos; +} + + +static Py_ssize_t +cpalmdoc_do_compress(buffer *b, char *output) { + Py_ssize_t i = 0, j, chunk_len, dist; + unsigned int compound; + Byte c, n; + bool found; + char *head; + buffer temp; + head = output; + temp.data = (Byte *)PyMem_Malloc(sizeof(Byte)*8); temp.len = 0; + if (temp.data == NULL) return 0; + while (i < b->len) { + c = b->data[i]; + //do repeats + if ( i > 10 && (b->len - i) > 10) { + found = false; + for (chunk_len = 10; chunk_len > 2; chunk_len--) { + j = cpalmdoc_rfind(b->data, i, chunk_len); + dist = i - j; + if (j < i && dist <= 2047) { + found = true; + compound = (unsigned int)((dist << 3) + chunk_len-3); + *(output++) = CHAR(0x80 + (compound >> 8 )); + *(output++) = CHAR(compound & 0xFF); + i += chunk_len; + break; + } + } + if (found) continue; + } + + //write single character + i++; + if (c == 32 && i < b->len) { + n = b->data[i]; + if ( n >= 0x40 && n <= 0x7F) { + *(output++) = CHAR(n^0x80); i++; continue; + } + } + if (c == 0 || (c > 8 && c < 0x80)) + *(output++) = CHAR(c); + else { // Write binary data + j = i; + temp.data[0] = c; temp.len = 1; + while (j < b->len && temp.len < 8) { + c = b->data[j]; + if (c == 0 || (c > 8 && c < 0x80)) break; + temp.data[temp.len++] = c; j++; + } + i += temp.len - 1; + *(output++) = (char)temp.len; + for (j=0; j < temp.len; j++) *(output++) = (char)temp.data[j]; + } + } + PyMem_Free(temp.data); + return output - head; +} + +static PyObject * +cpalmdoc_compress(PyObject *self, PyObject *args) { + const char *_input = NULL; Py_ssize_t input_len = 0; + char *output; PyObject *ans; + Py_ssize_t j = 0; + buffer b; + if (!PyArg_ParseTuple(args, BUFFER_FMT, &_input, &input_len)) + return NULL; + b.data = (Byte *)PyMem_Malloc(sizeof(Byte)*input_len); + if (b.data == NULL) return PyErr_NoMemory(); + // Map chars to bytes + for (j = 0; j < input_len; j++) + b.data[j] = (_input[j] < 0) ? _input[j]+256 : _input[j]; + b.len = input_len; + // Make the output buffer larger than the input as sometimes + // compression results in a larger block + output = (char *)PyMem_Malloc(sizeof(char) * (int)(1.25*b.len)); + if (output == NULL) return PyErr_NoMemory(); + j = cpalmdoc_do_compress(&b, output); + if ( j == 0) return PyErr_NoMemory(); + ans = Py_BuildValue(BYTES_FMT, output, j); + PyMem_Free(output); + PyMem_Free(b.data); + return ans; +} + +static char cPalmdoc_doc[] = "Compress and decompress palmdoc strings."; + +static PyMethodDef cPalmdoc_methods[] = { + {"decompress", cpalmdoc_decompress, METH_VARARGS, + "decompress(bytestring) -> decompressed bytestring\n\n" + "Decompress a palmdoc compressed byte string. " + }, + + {"compress", cpalmdoc_compress, METH_VARARGS, + "compress(bytestring) -> compressed bytestring\n\n" + "Palmdoc compress a byte string. " + }, + {NULL, NULL, 0, NULL} +}; + +#if PY_MAJOR_VERSION >= 3 +#define INITERROR return NULL +#define INITMODULE PyModule_Create(&cPalmdoc_module) +static struct PyModuleDef cPalmdoc_module = { + /* m_base */ PyModuleDef_HEAD_INIT, + /* m_name */ "cPalmdoc", + /* m_doc */ cPalmdoc_doc, + /* m_size */ -1, + /* m_methods */ cPalmdoc_methods, + /* m_slots */ 0, + /* m_traverse */ 0, + /* m_clear */ 0, + /* m_free */ 0, +}; +CALIBRE_MODINIT_FUNC PyInit_cPalmdoc(void) { +#else +#define INITERROR return +#define INITMODULE Py_InitModule3("cPalmdoc", cPalmdoc_methods, cPalmdoc_doc) +CALIBRE_MODINIT_FUNC initcPalmdoc(void) { +#endif + + PyObject *m; + m = INITMODULE; + if (m == NULL) { + INITERROR; + } + +#if PY_MAJOR_VERSION >= 3 + return m; +#endif +} diff --git a/ebook_converter/ebooks/compression/palmdoc.py b/ebook_converter/ebooks/compression/palmdoc.py new file mode 100644 index 0000000..6ce6ac5 --- /dev/null +++ b/ebook_converter/ebooks/compression/palmdoc.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2008, Kovid Goyal ' + +import io +from struct import pack + +from calibre.constants import plugins +from polyglot.builtins import range +cPalmdoc = plugins['cPalmdoc'][0] +if not cPalmdoc: + raise RuntimeError(('Failed to load required cPalmdoc module: ' + '%s')%plugins['cPalmdoc'][1]) + + +def decompress_doc(data): + return cPalmdoc.decompress(data) + + +def compress_doc(data): + return cPalmdoc.compress(data) if data else b'' + + +def py_compress_doc(data): + out = io.BytesIO() + i = 0 + ldata = len(data) + while i < ldata: + if i > 10 and (ldata - i) > 10: + chunk = b'' + match = -1 + for j in range(10, 2, -1): + chunk = data[i:i+j] + try: + match = data.rindex(chunk, 0, i) + except ValueError: + continue + if (i - match) <= 2047: + break + match = -1 + if match >= 0: + n = len(chunk) + m = i - match + code = 0x8000 + ((m << 3) & 0x3ff8) + (n - 3) + out.write(pack('>H', code)) + i += n + continue + ch = data[i:i+1] + och = ord(ch) + i += 1 + if ch == b' ' and (i + 1) < ldata: + onch = ord(data[i:i+1]) + if onch >= 0x40 and onch < 0x80: + out.write(pack('>B', onch ^ 0x80)) + i += 1 + continue + if och == 0 or (och > 8 and och < 0x80): + out.write(ch) + else: + j = i + binseq = [ch] + while j < ldata and len(binseq) < 8: + ch = data[j:j+1] + och = ord(ch) + if och == 0 or (och > 8 and och < 0x80): + break + binseq.append(ch) + j += 1 + out.write(pack('>B', len(binseq))) + out.write(b''.join(binseq)) + i += len(binseq) - 1 + return out.getvalue() + + +def find_tests(): + import unittest + + class Test(unittest.TestCase): + + def test_palmdoc_compression(self): + for test in [ + b'abc\x03\x04\x05\x06ms', # Test binary writing + b'a b c \xfed ', # Test encoding of spaces + b'0123456789axyz2bxyz2cdfgfo9iuyerh', + b'0123456789asd0123456789asd|yyzzxxffhhjjkk', + (b'ciewacnaq eiu743 r787q 0w% ; sa fd\xef\ffdxosac wocjp acoiecowei ' + b'owaic jociowapjcivcjpoivjporeivjpoavca; p9aw8743y6r74%$^$^%8 ') + ]: + x = compress_doc(test) + self.assertEqual(py_compress_doc(test), x) + self.assertEqual(decompress_doc(x), test) + + return unittest.defaultTestLoader.loadTestsFromTestCase(Test) diff --git a/ebook_converter/ebooks/conversion/__init__.py b/ebook_converter/ebooks/conversion/__init__.py new file mode 100644 index 0000000..be49b37 --- /dev/null +++ b/ebook_converter/ebooks/conversion/__init__.py @@ -0,0 +1,30 @@ +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2011, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +from polyglot.builtins import native_string_type + + +class ConversionUserFeedBack(Exception): + + def __init__(self, title, msg, level='info', det_msg=''): + ''' Show a simple message to the user + + :param title: The title (very short description) + :param msg: The message to show the user + :param level: Must be one of 'info', 'warn' or 'error' + :param det_msg: Optional detailed message to show the user + ''' + import json + Exception.__init__(self, json.dumps({'msg':msg, 'level':level, + 'det_msg':det_msg, 'title':title})) + self.title, self.msg, self.det_msg = title, msg, det_msg + self.level = level + + +# Ensure exception uses fully qualified name as this is used to detect it in +# the GUI. +ConversionUserFeedBack.__name__ = native_string_type('calibre.ebooks.conversion.ConversionUserFeedBack') diff --git a/ebook_converter/ebooks/conversion/cli.py b/ebook_converter/ebooks/conversion/cli.py new file mode 100644 index 0000000..ce706ae --- /dev/null +++ b/ebook_converter/ebooks/conversion/cli.py @@ -0,0 +1,428 @@ +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL 3' +__copyright__ = '2009, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +''' +Command line interface to conversion sub-system +''' + +import sys, os, numbers +from optparse import OptionGroup, Option +from collections import OrderedDict + +from calibre.utils.config import OptionParser +from calibre.utils.logging import Log +from calibre.customize.conversion import OptionRecommendation +from calibre import patheq +from calibre.ebooks.conversion import ConversionUserFeedBack +from calibre.utils.localization import localize_user_manual_link +from polyglot.builtins import iteritems + +USAGE = '%prog ' + _('''\ +input_file output_file [options] + +Convert an e-book from one format to another. + +input_file is the input and output_file is the output. Both must be \ +specified as the first two arguments to the command. + +The output e-book format is guessed from the file extension of \ +output_file. output_file can also be of the special format .EXT where \ +EXT is the output file extension. In this case, the name of the output \ +file is derived from the name of the input file. Note that the filenames must \ +not start with a hyphen. Finally, if output_file has no extension, then \ +it is treated as a directory and an "open e-book" (OEB) consisting of HTML \ +files is written to that directory. These files are the files that would \ +normally have been passed to the output plugin. + +After specifying the input \ +and output file you can customize the conversion by specifying various \ +options. The available options depend on the input and output file types. \ +To get help on them specify the input and output file and then use the -h \ +option. + +For full documentation of the conversion system see +''') + localize_user_manual_link('https://manual.calibre-ebook.com/conversion.html') + +HEURISTIC_OPTIONS = ['markup_chapter_headings', + 'italicize_common_cases', 'fix_indents', + 'html_unwrap_factor', 'unwrap_lines', + 'delete_blank_paragraphs', 'format_scene_breaks', + 'dehyphenate', 'renumber_headings', + 'replace_scene_breaks'] + +DEFAULT_TRUE_OPTIONS = HEURISTIC_OPTIONS + ['remove_fake_margins'] + + +def print_help(parser, log): + parser.print_help() + + +def check_command_line_options(parser, args, log): + if len(args) < 3 or args[1].startswith('-') or args[2].startswith('-'): + print_help(parser, log) + log.error('\n\nYou must specify the input AND output files') + raise SystemExit(1) + + input = os.path.abspath(args[1]) + if not input.endswith('.recipe') and not os.access(input, os.R_OK) and not \ + ('-h' in args or '--help' in args): + log.error('Cannot read from', input) + raise SystemExit(1) + if input.endswith('.recipe') and not os.access(input, os.R_OK): + input = args[1] + + output = args[2] + if (output.startswith('.') and output[:2] not in {'..', '.'} and '/' not in + output and '\\' not in output): + output = os.path.splitext(os.path.basename(input))[0]+output + output = os.path.abspath(output) + + return input, output + + +def option_recommendation_to_cli_option(add_option, rec): + opt = rec.option + switches = ['-'+opt.short_switch] if opt.short_switch else [] + switches.append('--'+opt.long_switch) + attrs = dict(dest=opt.name, help=opt.help, + choices=opt.choices, default=rec.recommended_value) + if isinstance(rec.recommended_value, type(True)): + attrs['action'] = 'store_false' if rec.recommended_value else \ + 'store_true' + else: + if isinstance(rec.recommended_value, numbers.Integral): + attrs['type'] = 'int' + if isinstance(rec.recommended_value, numbers.Real): + attrs['type'] = 'float' + + if opt.long_switch == 'verbose': + attrs['action'] = 'count' + attrs.pop('type', '') + if opt.name == 'read_metadata_from_opf': + switches.append('--from-opf') + if opt.name == 'transform_css_rules': + attrs['help'] = _( + 'Path to a file containing rules to transform the CSS styles' + ' in this book. The easiest way to create such a file is to' + ' use the wizard for creating rules in the calibre GUI. Access' + ' it in the "Look & feel->Transform styles" section of the conversion' + ' dialog. Once you create the rules, you can use the "Export" button' + ' to save them to a file.' + ) + if opt.name in DEFAULT_TRUE_OPTIONS and rec.recommended_value is True: + switches = ['--disable-'+opt.long_switch] + add_option(Option(*switches, **attrs)) + + +def group_titles(): + return _('INPUT OPTIONS'), _('OUTPUT OPTIONS') + + +def recipe_test(option, opt_str, value, parser): + assert value is None + value = [] + + def floatable(s): + try: + float(s) + return True + except ValueError: + return False + + for arg in parser.rargs: + # stop on --foo like options + if arg[:2] == "--": + break + # stop on -a, but not on -3 or -3.0 + if arg[:1] == "-" and len(arg) > 1 and not floatable(arg): + break + try: + value.append(int(arg)) + except (TypeError, ValueError, AttributeError): + break + if len(value) == 2: + break + del parser.rargs[:len(value)] + + while len(value) < 2: + value.append(2) + + setattr(parser.values, option.dest, tuple(value)) + + +def add_input_output_options(parser, plumber): + input_options, output_options = \ + plumber.input_options, plumber.output_options + + def add_options(group, options): + for opt in options: + if plumber.input_fmt == 'recipe' and opt.option.long_switch == 'test': + group(Option('--test', dest='test', action='callback', callback=recipe_test)) + else: + option_recommendation_to_cli_option(group, opt) + + if input_options: + title = group_titles()[0] + io = OptionGroup(parser, title, _('Options to control the processing' + ' of the input %s file')%plumber.input_fmt) + add_options(io.add_option, input_options) + parser.add_option_group(io) + + if output_options: + title = group_titles()[1] + oo = OptionGroup(parser, title, _('Options to control the processing' + ' of the output %s')%plumber.output_fmt) + add_options(oo.add_option, output_options) + parser.add_option_group(oo) + + +def add_pipeline_options(parser, plumber): + groups = OrderedDict(( + ('' , ('', + [ + 'input_profile', + 'output_profile', + ] + )), + (_('LOOK AND FEEL') , ( + _('Options to control the look and feel of the output'), + [ + 'base_font_size', 'disable_font_rescaling', + 'font_size_mapping', 'embed_font_family', + 'subset_embedded_fonts', 'embed_all_fonts', + 'line_height', 'minimum_line_height', + 'linearize_tables', + 'extra_css', 'filter_css', 'transform_css_rules', 'expand_css', + 'smarten_punctuation', 'unsmarten_punctuation', + 'margin_top', 'margin_left', 'margin_right', + 'margin_bottom', 'change_justification', + 'insert_blank_line', 'insert_blank_line_size', + 'remove_paragraph_spacing', + 'remove_paragraph_spacing_indent_size', + 'asciiize', 'keep_ligatures', + ] + )), + + (_('HEURISTIC PROCESSING') , ( + _('Modify the document text and structure using common' + ' patterns. Disabled by default. Use %(en)s to enable. ' + ' Individual actions can be disabled with the %(dis)s options.') + % dict(en='--enable-heuristics', dis='--disable-*'), + ['enable_heuristics'] + HEURISTIC_OPTIONS + )), + + (_('SEARCH AND REPLACE') , ( + _('Modify the document text and structure using user defined patterns.'), + [ + 'sr1_search', 'sr1_replace', + 'sr2_search', 'sr2_replace', + 'sr3_search', 'sr3_replace', + 'search_replace', + ] + )), + + (_('STRUCTURE DETECTION') , ( + _('Control auto-detection of document structure.'), + [ + 'chapter', 'chapter_mark', + 'prefer_metadata_cover', 'remove_first_image', + 'insert_metadata', 'page_breaks_before', + 'remove_fake_margins', 'start_reading_at', + ] + )), + + (_('TABLE OF CONTENTS') , ( + _('Control the automatic generation of a Table of Contents. By ' + 'default, if the source file has a Table of Contents, it will ' + 'be used in preference to the automatically generated one.'), + [ + 'level1_toc', 'level2_toc', 'level3_toc', + 'toc_threshold', 'max_toc_links', 'no_chapters_in_toc', + 'use_auto_toc', 'toc_filter', 'duplicate_links_in_toc', + ] + )), + + (_('METADATA') , (_('Options to set metadata in the output'), + plumber.metadata_option_names + ['read_metadata_from_opf'], + )), + (_('DEBUG'), (_('Options to help with debugging the conversion'), + [ + 'verbose', + 'debug_pipeline', + ])), + + )) + + for group, (desc, options) in iteritems(groups): + if group: + group = OptionGroup(parser, group, desc) + parser.add_option_group(group) + add_option = group.add_option if group != '' else parser.add_option + + for name in options: + rec = plumber.get_option_by_name(name) + if rec.level < rec.HIGH: + option_recommendation_to_cli_option(add_option, rec) + + +def option_parser(): + parser = OptionParser(usage=USAGE) + parser.add_option('--list-recipes', default=False, action='store_true', + help=_('List builtin recipe names. You can create an e-book from ' + 'a builtin recipe like this: ebook-convert "Recipe Name.recipe" ' + 'output.epub')) + return parser + + +class ProgressBar(object): + + def __init__(self, log): + self.log = log + + def __call__(self, frac, msg=''): + if msg: + percent = int(frac*100) + self.log('%d%% %s'%(percent, msg)) + + +def create_option_parser(args, log): + if '--version' in args: + from calibre.constants import __appname__, __version__, __author__ + log(os.path.basename(args[0]), '('+__appname__, __version__+')') + log('Created by:', __author__) + raise SystemExit(0) + if '--list-recipes' in args: + from calibre.web.feeds.recipes.collection import get_builtin_recipe_titles + log('Available recipes:') + titles = sorted(get_builtin_recipe_titles()) + for title in titles: + try: + log('\t'+title) + except: + log('\t'+repr(title)) + log('%d recipes available'%len(titles)) + raise SystemExit(0) + + parser = option_parser() + if len(args) < 3: + print_help(parser, log) + if any(x in args for x in ('-h', '--help')): + raise SystemExit(0) + else: + raise SystemExit(1) + + input, output = check_command_line_options(parser, args, log) + + from calibre.ebooks.conversion.plumber import Plumber + + reporter = ProgressBar(log) + if patheq(input, output): + raise ValueError('Input file is the same as the output file') + + plumber = Plumber(input, output, log, reporter) + add_input_output_options(parser, plumber) + add_pipeline_options(parser, plumber) + + return parser, plumber + + +def abspath(x): + if x.startswith('http:') or x.startswith('https:'): + return x + return os.path.abspath(os.path.expanduser(x)) + + +def escape_sr_pattern(exp): + return exp.replace('\n', '\ue123') + + +def read_sr_patterns(path, log=None): + import json, re + pats = [] + with open(path, 'rb') as f: + lines = f.read().decode('utf-8').splitlines() + pat = None + for line in lines: + if pat is None: + if not line.strip(): + continue + line = line.replace('\ue123', '\n') + try: + re.compile(line) + except: + msg = 'Invalid regular expression: %r from file: %r'%( + line, path) + if log is not None: + log.error(msg) + raise SystemExit(1) + else: + raise ValueError(msg) + pat = line + else: + pats.append((pat, line)) + pat = None + return json.dumps(pats) + + +def main(args=sys.argv): + log = Log() + parser, plumber = create_option_parser(args, log) + opts, leftover_args = parser.parse_args(args) + if len(leftover_args) > 3: + log.error('Extra arguments not understood:', u', '.join(leftover_args[3:])) + return 1 + for x in ('read_metadata_from_opf', 'cover'): + if getattr(opts, x, None) is not None: + setattr(opts, x, abspath(getattr(opts, x))) + if opts.search_replace: + opts.search_replace = read_sr_patterns(opts.search_replace, log) + if opts.transform_css_rules: + from calibre.ebooks.css_transform_rules import import_rules, validate_rule + with open(opts.transform_css_rules, 'rb') as tcr: + opts.transform_css_rules = rules = list(import_rules(tcr.read())) + for rule in rules: + title, msg = validate_rule(rule) + if title and msg: + log.error('Failed to parse CSS transform rules') + log.error(title) + log.error(msg) + return 1 + + recommendations = [(n.dest, getattr(opts, n.dest), + OptionRecommendation.HIGH) + for n in parser.options_iter() + if n.dest] + plumber.merge_ui_recommendations(recommendations) + + try: + plumber.run() + except ConversionUserFeedBack as e: + ll = {'info': log.info, 'warn': log.warn, + 'error':log.error}.get(e.level, log.info) + ll(e.title) + if e.det_msg: + log.debug(e.detmsg) + ll(e.msg) + raise SystemExit(1) + + log(_('Output saved to'), ' ', plumber.output) + + return 0 + + +def manual_index_strings(): + return _('''\ +The options and default values for the options change depending on both the +input and output formats, so you should always check with:: + + %s + +Below are the options that are common to all conversion, followed by the +options specific to every input and output format.''') + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/ebook_converter/ebooks/conversion/plugins/__init__.py b/ebook_converter/ebooks/conversion/plugins/__init__.py new file mode 100644 index 0000000..357137f --- /dev/null +++ b/ebook_converter/ebooks/conversion/plugins/__init__.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2012, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + + + diff --git a/ebook_converter/ebooks/conversion/plugins/azw4_input.py b/ebook_converter/ebooks/conversion/plugins/azw4_input.py new file mode 100644 index 0000000..d3a7e6a --- /dev/null +++ b/ebook_converter/ebooks/conversion/plugins/azw4_input.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2011, John Schember ' +__docformat__ = 'restructuredtext en' + +from calibre.customize.conversion import InputFormatPlugin +from polyglot.builtins import getcwd + + +class AZW4Input(InputFormatPlugin): + + name = 'AZW4 Input' + author = 'John Schember' + description = 'Convert AZW4 to HTML' + file_types = {'azw4'} + commit_name = 'azw4_input' + + def convert(self, stream, options, file_ext, log, + accelerators): + from calibre.ebooks.pdb.header import PdbHeaderReader + from calibre.ebooks.azw4.reader import Reader + + header = PdbHeaderReader(stream) + reader = Reader(header, stream, log, options) + opf = reader.extract_content(getcwd()) + + return opf diff --git a/ebook_converter/ebooks/conversion/plugins/chm_input.py b/ebook_converter/ebooks/conversion/plugins/chm_input.py new file mode 100644 index 0000000..44f5de5 --- /dev/null +++ b/ebook_converter/ebooks/conversion/plugins/chm_input.py @@ -0,0 +1,202 @@ +from __future__ import absolute_import, division, print_function, unicode_literals + +''' CHM File decoding support ''' +__license__ = 'GPL v3' +__copyright__ = '2008, Kovid Goyal ,' \ + ' and Alex Bramley .' + +import os + +from calibre.customize.conversion import InputFormatPlugin +from calibre.ptempfile import TemporaryDirectory +from calibre.constants import filesystem_encoding +from polyglot.builtins import unicode_type, as_bytes + + +class CHMInput(InputFormatPlugin): + + name = 'CHM Input' + author = 'Kovid Goyal and Alex Bramley' + description = 'Convert CHM files to OEB' + file_types = {'chm'} + commit_name = 'chm_input' + + def _chmtohtml(self, output_dir, chm_path, no_images, log, debug_dump=False): + from calibre.ebooks.chm.reader import CHMReader + log.debug('Opening CHM file') + rdr = CHMReader(chm_path, log, input_encoding=self.opts.input_encoding) + log.debug('Extracting CHM to %s' % output_dir) + rdr.extract_content(output_dir, debug_dump=debug_dump) + self._chm_reader = rdr + return rdr.hhc_path + + def convert(self, stream, options, file_ext, log, accelerators): + from calibre.ebooks.chm.metadata import get_metadata_from_reader + from calibre.customize.ui import plugin_for_input_format + self.opts = options + + log.debug('Processing CHM...') + with TemporaryDirectory('_chm2oeb') as tdir: + if not isinstance(tdir, unicode_type): + tdir = tdir.decode(filesystem_encoding) + html_input = plugin_for_input_format('html') + for opt in html_input.options: + setattr(options, opt.option.name, opt.recommended_value) + no_images = False # options.no_images + chm_name = stream.name + # chm_data = stream.read() + + # closing stream so CHM can be opened by external library + stream.close() + log.debug('tdir=%s' % tdir) + log.debug('stream.name=%s' % stream.name) + debug_dump = False + odi = options.debug_pipeline + if odi: + debug_dump = os.path.join(odi, 'input') + mainname = self._chmtohtml(tdir, chm_name, no_images, log, + debug_dump=debug_dump) + mainpath = os.path.join(tdir, mainname) + + try: + metadata = get_metadata_from_reader(self._chm_reader) + except Exception: + log.exception('Failed to read metadata, using filename') + from calibre.ebooks.metadata.book.base import Metadata + metadata = Metadata(os.path.basename(chm_name)) + encoding = self._chm_reader.get_encoding() or options.input_encoding or 'cp1252' + self._chm_reader.CloseCHM() + # print((tdir, mainpath)) + # from calibre import ipython + # ipython() + + options.debug_pipeline = None + options.input_encoding = 'utf-8' + uenc = encoding + if os.path.abspath(mainpath) in self._chm_reader.re_encoded_files: + uenc = 'utf-8' + htmlpath, toc = self._create_html_root(mainpath, log, uenc) + oeb = self._create_oebbook_html(htmlpath, tdir, options, log, metadata) + options.debug_pipeline = odi + if toc.count() > 1: + oeb.toc = self.parse_html_toc(oeb.spine[0]) + oeb.manifest.remove(oeb.spine[0]) + oeb.auto_generated_toc = False + return oeb + + def parse_html_toc(self, item): + from calibre.ebooks.oeb.base import TOC, XPath + dx = XPath('./h:div') + ax = XPath('./h:a[1]') + + def do_node(parent, div): + for child in dx(div): + a = ax(child)[0] + c = parent.add(a.text, a.attrib['href']) + do_node(c, child) + + toc = TOC() + root = XPath('//h:div[1]')(item.data)[0] + do_node(toc, root) + return toc + + def _create_oebbook_html(self, htmlpath, basedir, opts, log, mi): + # use HTMLInput plugin to generate book + from calibre.customize.builtins import HTMLInput + opts.breadth_first = True + htmlinput = HTMLInput(None) + oeb = htmlinput.create_oebbook(htmlpath, basedir, opts, log, mi) + return oeb + + def _create_html_root(self, hhcpath, log, encoding): + from lxml import html + from polyglot.urllib import unquote as _unquote + from calibre.ebooks.oeb.base import urlquote + from calibre.ebooks.chardet import xml_to_unicode + hhcdata = self._read_file(hhcpath) + hhcdata = hhcdata.decode(encoding) + hhcdata = xml_to_unicode(hhcdata, verbose=True, + strip_encoding_pats=True, resolve_entities=True)[0] + hhcroot = html.fromstring(hhcdata) + toc = self._process_nodes(hhcroot) + # print("=============================") + # print("Printing hhcroot") + # print(etree.tostring(hhcroot, pretty_print=True)) + # print("=============================") + log.debug('Found %d section nodes' % toc.count()) + htmlpath = os.path.splitext(hhcpath)[0] + ".html" + base = os.path.dirname(os.path.abspath(htmlpath)) + + def unquote(x): + if isinstance(x, unicode_type): + x = x.encode('utf-8') + return _unquote(x).decode('utf-8') + + def unquote_path(x): + y = unquote(x) + if (not os.path.exists(os.path.join(base, x)) and os.path.exists(os.path.join(base, y))): + x = y + return x + + def donode(item, parent, base, subpath): + for child in item: + title = child.title + if not title: + continue + raw = unquote_path(child.href or '') + rsrcname = os.path.basename(raw) + rsrcpath = os.path.join(subpath, rsrcname) + if (not os.path.exists(os.path.join(base, rsrcpath)) and os.path.exists(os.path.join(base, raw))): + rsrcpath = raw + + if '%' not in rsrcpath: + rsrcpath = urlquote(rsrcpath) + if not raw: + rsrcpath = '' + c = DIV(A(title, href=rsrcpath)) + donode(child, c, base, subpath) + parent.append(c) + + with open(htmlpath, 'wb') as f: + if toc.count() > 1: + from lxml.html.builder import HTML, BODY, DIV, A + path0 = toc[0].href + path0 = unquote_path(path0) + subpath = os.path.dirname(path0) + base = os.path.dirname(f.name) + root = DIV() + donode(toc, root, base, subpath) + raw = html.tostring(HTML(BODY(root)), encoding='utf-8', + pretty_print=True) + f.write(raw) + else: + f.write(as_bytes(hhcdata)) + return htmlpath, toc + + def _read_file(self, name): + with lopen(name, 'rb') as f: + data = f.read() + return data + + def add_node(self, node, toc, ancestor_map): + from calibre.ebooks.chm.reader import match_string + if match_string(node.attrib.get('type', ''), 'text/sitemap'): + p = node.xpath('ancestor::ul[1]/ancestor::li[1]/object[1]') + parent = p[0] if p else None + toc = ancestor_map.get(parent, toc) + title = href = '' + for param in node.xpath('./param'): + if match_string(param.attrib['name'], 'name'): + title = param.attrib['value'] + elif match_string(param.attrib['name'], 'local'): + href = param.attrib['value'] + child = toc.add(title or _('Unknown'), href) + ancestor_map[node] = child + + def _process_nodes(self, root): + from calibre.ebooks.oeb.base import TOC + toc = TOC() + ancestor_map = {} + for node in root.xpath('//object'): + self.add_node(node, toc, ancestor_map) + return toc diff --git a/ebook_converter/ebooks/conversion/plugins/comic_input.py b/ebook_converter/ebooks/conversion/plugins/comic_input.py new file mode 100644 index 0000000..079e12b --- /dev/null +++ b/ebook_converter/ebooks/conversion/plugins/comic_input.py @@ -0,0 +1,310 @@ +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net' +__docformat__ = 'restructuredtext en' + +''' +Based on ideas from comiclrf created by FangornUK. +''' + +import shutil, textwrap, codecs, os + +from calibre.customize.conversion import InputFormatPlugin, OptionRecommendation +from calibre import CurrentDir +from calibre.ptempfile import PersistentTemporaryDirectory +from polyglot.builtins import getcwd, map + + +class ComicInput(InputFormatPlugin): + + name = 'Comic Input' + author = 'Kovid Goyal' + description = 'Optimize comic files (.cbz, .cbr, .cbc) for viewing on portable devices' + file_types = {'cbz', 'cbr', 'cbc'} + is_image_collection = True + commit_name = 'comic_input' + core_usage = -1 + + options = { + OptionRecommendation(name='colors', recommended_value=0, + help=_('Reduce the number of colors used in the image. This works only' + ' if you choose the PNG output format. It is useful to reduce file sizes.' + ' Set to zero to turn off. Maximum value is 256. It is off by default.')), + OptionRecommendation(name='dont_normalize', recommended_value=False, + help=_('Disable normalize (improve contrast) color range ' + 'for pictures. Default: False')), + OptionRecommendation(name='keep_aspect_ratio', recommended_value=False, + help=_('Maintain picture aspect ratio. Default is to fill the screen.')), + OptionRecommendation(name='dont_sharpen', recommended_value=False, + help=_('Disable sharpening.')), + OptionRecommendation(name='disable_trim', recommended_value=False, + help=_('Disable trimming of comic pages. For some comics, ' + 'trimming might remove content as well as borders.')), + OptionRecommendation(name='landscape', recommended_value=False, + help=_("Don't split landscape images into two portrait images")), + OptionRecommendation(name='wide', recommended_value=False, + help=_("Keep aspect ratio and scale image using screen height as " + "image width for viewing in landscape mode.")), + OptionRecommendation(name='right2left', recommended_value=False, + help=_('Used for right-to-left publications like manga. ' + 'Causes landscape pages to be split into portrait pages ' + 'from right to left.')), + OptionRecommendation(name='despeckle', recommended_value=False, + help=_('Enable Despeckle. Reduces speckle noise. ' + 'May greatly increase processing time.')), + OptionRecommendation(name='no_sort', recommended_value=False, + help=_("Don't sort the files found in the comic " + "alphabetically by name. Instead use the order they were " + "added to the comic.")), + OptionRecommendation(name='output_format', choices=['png', 'jpg'], + recommended_value='png', help=_('The format that images in the created e-book ' + 'are converted to. You can experiment to see which format gives ' + 'you optimal size and look on your device.')), + OptionRecommendation(name='no_process', recommended_value=False, + help=_("Apply no processing to the image")), + OptionRecommendation(name='dont_grayscale', recommended_value=False, + help=_('Do not convert the image to grayscale (black and white)')), + OptionRecommendation(name='comic_image_size', recommended_value=None, + help=_('Specify the image size as widthxheight pixels. Normally,' + ' an image size is automatically calculated from the output ' + 'profile, this option overrides it.')), + OptionRecommendation(name='dont_add_comic_pages_to_toc', recommended_value=False, + help=_('When converting a CBC do not add links to each page to' + ' the TOC. Note this only applies if the TOC has more than one' + ' section')), + } + + recommendations = { + ('margin_left', 0, OptionRecommendation.HIGH), + ('margin_top', 0, OptionRecommendation.HIGH), + ('margin_right', 0, OptionRecommendation.HIGH), + ('margin_bottom', 0, OptionRecommendation.HIGH), + ('insert_blank_line', False, OptionRecommendation.HIGH), + ('remove_paragraph_spacing', False, OptionRecommendation.HIGH), + ('change_justification', 'left', OptionRecommendation.HIGH), + ('dont_split_on_pagebreaks', True, OptionRecommendation.HIGH), + ('chapter', None, OptionRecommendation.HIGH), + ('page_breaks_brefore', None, OptionRecommendation.HIGH), + ('use_auto_toc', False, OptionRecommendation.HIGH), + ('page_breaks_before', None, OptionRecommendation.HIGH), + ('disable_font_rescaling', True, OptionRecommendation.HIGH), + ('linearize_tables', False, OptionRecommendation.HIGH), + } + + def get_comics_from_collection(self, stream): + from calibre.libunzip import extract as zipextract + tdir = PersistentTemporaryDirectory('_comic_collection') + zipextract(stream, tdir) + comics = [] + with CurrentDir(tdir): + if not os.path.exists('comics.txt'): + raise ValueError(( + '%s is not a valid comic collection' + ' no comics.txt was found in the file') + %stream.name) + with open('comics.txt', 'rb') as f: + raw = f.read() + if raw.startswith(codecs.BOM_UTF16_BE): + raw = raw.decode('utf-16-be')[1:] + elif raw.startswith(codecs.BOM_UTF16_LE): + raw = raw.decode('utf-16-le')[1:] + elif raw.startswith(codecs.BOM_UTF8): + raw = raw.decode('utf-8')[1:] + else: + raw = raw.decode('utf-8') + for line in raw.splitlines(): + line = line.strip() + if not line: + continue + fname, title = line.partition(':')[0], line.partition(':')[-1] + fname = fname.replace('#', '_') + fname = os.path.join(tdir, *fname.split('/')) + if not title: + title = os.path.basename(fname).rpartition('.')[0] + if os.access(fname, os.R_OK): + comics.append([title, fname]) + if not comics: + raise ValueError('%s has no comics'%stream.name) + return comics + + def get_pages(self, comic, tdir2): + from calibre.ebooks.comic.input import (extract_comic, process_pages, + find_pages) + tdir = extract_comic(comic) + new_pages = find_pages(tdir, sort_on_mtime=self.opts.no_sort, + verbose=self.opts.verbose) + thumbnail = None + if not new_pages: + raise ValueError('Could not find any pages in the comic: %s' + %comic) + if self.opts.no_process: + n2 = [] + for i, page in enumerate(new_pages): + n2.append(os.path.join(tdir2, '{} - {}' .format(i, os.path.basename(page)))) + shutil.copyfile(page, n2[-1]) + new_pages = n2 + else: + new_pages, failures = process_pages(new_pages, self.opts, + self.report_progress, tdir2) + if failures: + self.log.warning('Could not process the following pages ' + '(run with --verbose to see why):') + for f in failures: + self.log.warning('\t', f) + if not new_pages: + raise ValueError('Could not find any valid pages in comic: %s' + % comic) + thumbnail = os.path.join(tdir2, + 'thumbnail.'+self.opts.output_format.lower()) + if not os.access(thumbnail, os.R_OK): + thumbnail = None + return new_pages + + def get_images(self): + return self._images + + def convert(self, stream, opts, file_ext, log, accelerators): + from calibre.ebooks.metadata import MetaInformation + from calibre.ebooks.metadata.opf2 import OPFCreator + from calibre.ebooks.metadata.toc import TOC + + self.opts, self.log= opts, log + if file_ext == 'cbc': + comics_ = self.get_comics_from_collection(stream) + else: + comics_ = [['Comic', os.path.abspath(stream.name)]] + stream.close() + comics = [] + for i, x in enumerate(comics_): + title, fname = x + cdir = 'comic_%d'%(i+1) if len(comics_) > 1 else '.' + cdir = os.path.abspath(cdir) + if not os.path.exists(cdir): + os.makedirs(cdir) + pages = self.get_pages(fname, cdir) + if not pages: + continue + if self.for_viewer: + comics.append((title, pages, [self.create_viewer_wrapper(pages)])) + else: + wrappers = self.create_wrappers(pages) + comics.append((title, pages, wrappers)) + + if not comics: + raise ValueError('No comic pages found in %s'%stream.name) + + mi = MetaInformation(os.path.basename(stream.name).rpartition('.')[0], + [_('Unknown')]) + opf = OPFCreator(getcwd(), mi) + entries = [] + + def href(x): + if len(comics) == 1: + return os.path.basename(x) + return '/'.join(x.split(os.sep)[-2:]) + + cover_href = None + for comic in comics: + pages, wrappers = comic[1:] + page_entries = [(x, None) for x in map(href, pages)] + entries += [(w, None) for w in map(href, wrappers)] + page_entries + if cover_href is None and page_entries: + cover_href = page_entries[0][0] + opf.create_manifest(entries) + spine = [] + for comic in comics: + spine.extend(map(href, comic[2])) + self._images = [] + for comic in comics: + self._images.extend(comic[1]) + opf.create_spine(spine) + if self.for_viewer and cover_href: + opf.guide.set_cover(cover_href) + toc = TOC() + if len(comics) == 1: + wrappers = comics[0][2] + for i, x in enumerate(wrappers): + toc.add_item(href(x), None, _('Page')+' %d'%(i+1), + play_order=i) + else: + po = 0 + for comic in comics: + po += 1 + wrappers = comic[2] + stoc = toc.add_item(href(wrappers[0]), + None, comic[0], play_order=po) + if not opts.dont_add_comic_pages_to_toc: + for i, x in enumerate(wrappers): + stoc.add_item(href(x), None, + _('Page')+' %d'%(i+1), play_order=po) + po += 1 + opf.set_toc(toc) + with open('metadata.opf', 'wb') as m, open('toc.ncx', 'wb') as n: + opf.render(m, n, 'toc.ncx') + return os.path.abspath('metadata.opf') + + def create_wrappers(self, pages): + from calibre.ebooks.oeb.base import XHTML_NS + wrappers = [] + WRAPPER = textwrap.dedent('''\ + + + + Page #%d + + + +
+ comic page #%d +
+ + + ''') + dir = os.path.dirname(pages[0]) + for i, page in enumerate(pages): + wrapper = WRAPPER%(XHTML_NS, i+1, os.path.basename(page), i+1) + page = os.path.join(dir, 'page_%d.xhtml'%(i+1)) + with open(page, 'wb') as f: + f.write(wrapper.encode('utf-8')) + wrappers.append(page) + return wrappers + + def create_viewer_wrapper(self, pages): + from calibre.ebooks.oeb.base import XHTML_NS + + def page(src): + return ''.format(os.path.basename(src)) + + pages = '\n'.join(map(page, pages)) + base = os.path.dirname(pages[0]) + wrapper = ''' + + + + + + + %s + + + ''' % (XHTML_NS, pages) + path = os.path.join(base, 'wrapper.xhtml') + with open(path, 'wb') as f: + f.write(wrapper.encode('utf-8')) + return path diff --git a/ebook_converter/ebooks/conversion/plugins/djvu_input.py b/ebook_converter/ebooks/conversion/plugins/djvu_input.py new file mode 100644 index 0000000..ed61ff0 --- /dev/null +++ b/ebook_converter/ebooks/conversion/plugins/djvu_input.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- + +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL 3' +__copyright__ = '2011, Anthon van der Neut ' +__docformat__ = 'restructuredtext en' + +import os +from io import BytesIO + +from calibre.customize.conversion import InputFormatPlugin +from polyglot.builtins import getcwd + + +class DJVUInput(InputFormatPlugin): + + name = 'DJVU Input' + author = 'Anthon van der Neut' + description = 'Convert OCR-ed DJVU files (.djvu) to HTML' + file_types = {'djvu', 'djv'} + commit_name = 'djvu_input' + + def convert(self, stream, options, file_ext, log, accelerators): + from calibre.ebooks.txt.processor import convert_basic + + stdout = BytesIO() + from calibre.ebooks.djvu.djvu import DJVUFile + x = DJVUFile(stream) + x.get_text(stdout) + raw_text = stdout.getvalue() + if not raw_text: + raise ValueError('The DJVU file contains no text, only images, probably page scans.' + ' calibre only supports conversion of DJVU files with actual text in them.') + + html = convert_basic(raw_text.replace(b"\n", b' ').replace( + b'\037', b'\n\n')) + # Run the HTMLized text through the html processing plugin. + from calibre.customize.ui import plugin_for_input_format + html_input = plugin_for_input_format('html') + for opt in html_input.options: + setattr(options, opt.option.name, opt.recommended_value) + options.input_encoding = 'utf-8' + base = getcwd() + htmlfile = os.path.join(base, 'index.html') + c = 0 + while os.path.exists(htmlfile): + c += 1 + htmlfile = os.path.join(base, 'index%d.html'%c) + with open(htmlfile, 'wb') as f: + f.write(html.encode('utf-8')) + odi = options.debug_pipeline + options.debug_pipeline = None + # Generate oeb from html conversion. + with open(htmlfile, 'rb') as f: + oeb = html_input.convert(f, options, 'html', log, + {}) + options.debug_pipeline = odi + os.remove(htmlfile) + + # Set metadata from file. + from calibre.customize.ui import get_file_type_metadata + from calibre.ebooks.oeb.transforms.metadata import meta_info_to_oeb_metadata + mi = get_file_type_metadata(stream, file_ext) + meta_info_to_oeb_metadata(mi, oeb.metadata, log) + + return oeb diff --git a/ebook_converter/ebooks/conversion/plugins/docx_input.py b/ebook_converter/ebooks/conversion/plugins/docx_input.py new file mode 100644 index 0000000..2ba157e --- /dev/null +++ b/ebook_converter/ebooks/conversion/plugins/docx_input.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2013, Kovid Goyal ' + +from calibre.customize.conversion import InputFormatPlugin, OptionRecommendation + + +class DOCXInput(InputFormatPlugin): + name = 'DOCX Input' + author = 'Kovid Goyal' + description = _('Convert DOCX files (.docx and .docm) to HTML') + file_types = {'docx', 'docm'} + commit_name = 'docx_input' + + options = { + OptionRecommendation(name='docx_no_cover', recommended_value=False, + help=_('Normally, if a large image is present at the start of the document that looks like a cover, ' + 'it will be removed from the document and used as the cover for created e-book. This option ' + 'turns off that behavior.')), + OptionRecommendation(name='docx_no_pagebreaks_between_notes', recommended_value=False, + help=_('Do not insert a page break after every endnote.')), + OptionRecommendation(name='docx_inline_subsup', recommended_value=False, + help=_('Render superscripts and subscripts so that they do not affect the line height.')), + } + + recommendations = {('page_breaks_before', '/', OptionRecommendation.MED)} + + def convert(self, stream, options, file_ext, log, accelerators): + from calibre.ebooks.docx.to_html import Convert + return Convert(stream, detect_cover=not options.docx_no_cover, log=log, notes_nopb=options.docx_no_pagebreaks_between_notes, + nosupsub=options.docx_inline_subsup)() diff --git a/ebook_converter/ebooks/conversion/plugins/docx_output.py b/ebook_converter/ebooks/conversion/plugins/docx_output.py new file mode 100644 index 0000000..ab65e87 --- /dev/null +++ b/ebook_converter/ebooks/conversion/plugins/docx_output.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2013, Kovid Goyal ' + +from calibre.customize.conversion import OutputFormatPlugin, OptionRecommendation + +PAGE_SIZES = ['a0', 'a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'b0', 'b1', + 'b2', 'b3', 'b4', 'b5', 'b6', 'legal', 'letter'] + + +class DOCXOutput(OutputFormatPlugin): + + name = 'DOCX Output' + author = 'Kovid Goyal' + file_type = 'docx' + commit_name = 'docx_output' + ui_data = {'page_sizes': PAGE_SIZES} + + options = { + OptionRecommendation(name='docx_page_size', recommended_value='letter', + level=OptionRecommendation.LOW, choices=PAGE_SIZES, + help=_('The size of the page. Default is letter. Choices ' + 'are %s') % PAGE_SIZES), + + OptionRecommendation(name='docx_custom_page_size', recommended_value=None, + help=_('Custom size of the document. Use the form widthxheight ' + 'EG. `123x321` to specify the width and height (in pts). ' + 'This overrides any specified page-size.')), + + OptionRecommendation(name='docx_no_cover', recommended_value=False, + help=_('Do not insert the book cover as an image at the start of the document.' + ' If you use this option, the book cover will be discarded.')), + + OptionRecommendation(name='preserve_cover_aspect_ratio', recommended_value=False, + help=_('Preserve the aspect ratio of the cover image instead of stretching' + ' it out to cover the entire page.')), + + OptionRecommendation(name='docx_no_toc', recommended_value=False, + help=_('Do not insert the table of contents as a page at the start of the document.')), + + OptionRecommendation(name='extract_to', + help=_('Extract the contents of the generated %s file to the ' + 'specified directory. The contents of the directory are first ' + 'deleted, so be careful.') % 'DOCX'), + + OptionRecommendation(name='docx_page_margin_left', recommended_value=72.0, + level=OptionRecommendation.LOW, + help=_('The size of the left page margin, in pts. Default is 72pt.' + ' Overrides the common left page margin setting.') + ), + + OptionRecommendation(name='docx_page_margin_top', recommended_value=72.0, + level=OptionRecommendation.LOW, + help=_('The size of the top page margin, in pts. Default is 72pt.' + ' Overrides the common top page margin setting, unless set to zero.') + ), + + OptionRecommendation(name='docx_page_margin_right', recommended_value=72.0, + level=OptionRecommendation.LOW, + help=_('The size of the right page margin, in pts. Default is 72pt.' + ' Overrides the common right page margin setting, unless set to zero.') + ), + + OptionRecommendation(name='docx_page_margin_bottom', recommended_value=72.0, + level=OptionRecommendation.LOW, + help=_('The size of the bottom page margin, in pts. Default is 72pt.' + ' Overrides the common bottom page margin setting, unless set to zero.') + ), + + } + + def convert_metadata(self, oeb): + from lxml import etree + from calibre.ebooks.oeb.base import OPF, OPF2_NS + from calibre.ebooks.metadata.opf2 import OPF as ReadOPF + from io import BytesIO + package = etree.Element(OPF('package'), attrib={'version': '2.0'}, nsmap={None: OPF2_NS}) + oeb.metadata.to_opf2(package) + self.mi = ReadOPF(BytesIO(etree.tostring(package, encoding='utf-8')), populate_spine=False, try_to_guess_cover=False).to_book_metadata() + + def convert(self, oeb, output_path, input_plugin, opts, log): + from calibre.ebooks.docx.writer.container import DOCX + from calibre.ebooks.docx.writer.from_html import Convert + docx = DOCX(opts, log) + self.convert_metadata(oeb) + Convert(oeb, docx, self.mi, not opts.docx_no_cover, not opts.docx_no_toc)() + docx.write(output_path, self.mi) + if opts.extract_to: + from calibre.ebooks.docx.dump import do_dump + do_dump(output_path, opts.extract_to) diff --git a/ebook_converter/ebooks/conversion/plugins/epub_input.py b/ebook_converter/ebooks/conversion/plugins/epub_input.py new file mode 100644 index 0000000..7c60b0e --- /dev/null +++ b/ebook_converter/ebooks/conversion/plugins/epub_input.py @@ -0,0 +1,438 @@ +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL 3' +__copyright__ = '2009, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import os, re, posixpath +from itertools import cycle + +from calibre.customize.conversion import InputFormatPlugin, OptionRecommendation +from polyglot.builtins import getcwd + +ADOBE_OBFUSCATION = 'http://ns.adobe.com/pdf/enc#RC' +IDPF_OBFUSCATION = 'http://www.idpf.org/2008/embedding' + + +def decrypt_font_data(key, data, algorithm): + is_adobe = algorithm == ADOBE_OBFUSCATION + crypt_len = 1024 if is_adobe else 1040 + crypt = bytearray(data[:crypt_len]) + key = cycle(iter(bytearray(key))) + decrypt = bytes(bytearray(x^next(key) for x in crypt)) + return decrypt + data[crypt_len:] + + +def decrypt_font(key, path, algorithm): + with lopen(path, 'r+b') as f: + data = decrypt_font_data(key, f.read(), algorithm) + f.seek(0), f.truncate(), f.write(data) + + +class EPUBInput(InputFormatPlugin): + + name = 'EPUB Input' + author = 'Kovid Goyal' + description = 'Convert EPUB files (.epub) to HTML' + file_types = {'epub'} + output_encoding = None + commit_name = 'epub_input' + + recommendations = {('page_breaks_before', '/', OptionRecommendation.MED)} + + def process_encryption(self, encfile, opf, log): + from lxml import etree + import uuid, hashlib + idpf_key = opf.raw_unique_identifier + if idpf_key: + idpf_key = re.sub('[\u0020\u0009\u000d\u000a]', '', idpf_key) + idpf_key = hashlib.sha1(idpf_key.encode('utf-8')).digest() + key = None + for item in opf.identifier_iter(): + scheme = None + for xkey in item.attrib.keys(): + if xkey.endswith('scheme'): + scheme = item.get(xkey) + if (scheme and scheme.lower() == 'uuid') or \ + (item.text and item.text.startswith('urn:uuid:')): + try: + key = item.text.rpartition(':')[-1] + key = uuid.UUID(key).bytes + except: + import traceback + traceback.print_exc() + key = None + + try: + root = etree.parse(encfile) + for em in root.xpath('descendant::*[contains(name(), "EncryptionMethod")]'): + algorithm = em.get('Algorithm', '') + if algorithm not in {ADOBE_OBFUSCATION, IDPF_OBFUSCATION}: + return False + cr = em.getparent().xpath('descendant::*[contains(name(), "CipherReference")]')[0] + uri = cr.get('URI') + path = os.path.abspath(os.path.join(os.path.dirname(encfile), '..', *uri.split('/'))) + tkey = (key if algorithm == ADOBE_OBFUSCATION else idpf_key) + if (tkey and os.path.exists(path)): + self._encrypted_font_uris.append(uri) + decrypt_font(tkey, path, algorithm) + return True + except: + import traceback + traceback.print_exc() + return False + + def set_guide_type(self, opf, gtype, href=None, title=''): + # Set the specified guide entry + for elem in list(opf.iterguide()): + if elem.get('type', '').lower() == gtype: + elem.getparent().remove(elem) + + if href is not None: + t = opf.create_guide_item(gtype, title, href) + for guide in opf.root.xpath('./*[local-name()="guide"]'): + guide.append(t) + return + guide = opf.create_guide_element() + opf.root.append(guide) + guide.append(t) + return t + + def rationalize_cover3(self, opf, log): + ''' If there is a reference to the cover/titlepage via manifest properties, convert to + entries in the so that the rest of the pipeline picks it up. ''' + from calibre.ebooks.metadata.opf3 import items_with_property + removed = guide_titlepage_href = guide_titlepage_id = None + + # Look for titlepages incorrectly marked in the as covers + guide_cover, guide_elem = None, None + for guide_elem in opf.iterguide(): + if guide_elem.get('type', '').lower() == 'cover': + guide_cover = guide_elem.get('href', '').partition('#')[0] + break + if guide_cover: + spine = list(opf.iterspine()) + if spine: + idref = spine[0].get('idref', '') + for x in opf.itermanifest(): + if x.get('id') == idref and x.get('href') == guide_cover: + guide_titlepage_href = guide_cover + guide_titlepage_id = idref + break + + raster_cover_href = opf.epub3_raster_cover or opf.raster_cover + if raster_cover_href: + self.set_guide_type(opf, 'cover', raster_cover_href, 'Cover Image') + titlepage_id = titlepage_href = None + for item in items_with_property(opf.root, 'calibre:title-page'): + tid, href = item.get('id'), item.get('href') + if href and tid: + titlepage_id, titlepage_href = tid, href.partition('#')[0] + break + if titlepage_href is None: + titlepage_href, titlepage_id = guide_titlepage_href, guide_titlepage_id + if titlepage_href is not None: + self.set_guide_type(opf, 'titlepage', titlepage_href, 'Title Page') + spine = list(opf.iterspine()) + if len(spine) > 1: + for item in spine: + if item.get('idref') == titlepage_id: + log('Found HTML cover', titlepage_href) + if self.for_viewer: + item.attrib.pop('linear', None) + else: + item.getparent().remove(item) + removed = titlepage_href + return removed + + def rationalize_cover2(self, opf, log): + ''' Ensure that the cover information in the guide is correct. That + means, at most one entry with type="cover" that points to a raster + cover and at most one entry with type="titlepage" that points to an + HTML titlepage. ''' + from calibre.ebooks.oeb.base import OPF + removed = None + from lxml import etree + guide_cover, guide_elem = None, None + for guide_elem in opf.iterguide(): + if guide_elem.get('type', '').lower() == 'cover': + guide_cover = guide_elem.get('href', '').partition('#')[0] + break + if not guide_cover: + raster_cover = opf.raster_cover + if raster_cover: + if guide_elem is None: + g = opf.root.makeelement(OPF('guide')) + opf.root.append(g) + else: + g = guide_elem.getparent() + guide_cover = raster_cover + guide_elem = g.makeelement(OPF('reference'), attrib={'href':raster_cover, 'type':'cover'}) + g.append(guide_elem) + return + spine = list(opf.iterspine()) + if not spine: + return + # Check if the cover specified in the guide is also + # the first element in spine + idref = spine[0].get('idref', '') + manifest = list(opf.itermanifest()) + if not manifest: + return + elem = [x for x in manifest if x.get('id', '') == idref] + if not elem or elem[0].get('href', None) != guide_cover: + return + log('Found HTML cover', guide_cover) + + # Remove from spine as covers must be treated + # specially + if not self.for_viewer: + if len(spine) == 1: + log.warn('There is only a single spine item and it is marked as the cover. Removing cover marking.') + for guide_elem in tuple(opf.iterguide()): + if guide_elem.get('type', '').lower() == 'cover': + guide_elem.getparent().remove(guide_elem) + return + else: + spine[0].getparent().remove(spine[0]) + removed = guide_cover + else: + # Ensure the cover is displayed as the first item in the book, some + # epub files have it set with linear='no' which causes the cover to + # display in the end + spine[0].attrib.pop('linear', None) + opf.spine[0].is_linear = True + # Ensure that the guide has a cover entry pointing to a raster cover + # and a titlepage entry pointing to the html titlepage. The titlepage + # entry will be used by the epub output plugin, the raster cover entry + # by other output plugins. + + # Search for a raster cover identified in the OPF + raster_cover = opf.raster_cover + + # Set the cover guide entry + if raster_cover is not None: + guide_elem.set('href', raster_cover) + else: + # Render the titlepage to create a raster cover + from calibre.ebooks import render_html_svg_workaround + guide_elem.set('href', 'calibre_raster_cover.jpg') + t = etree.SubElement( + elem[0].getparent(), OPF('item'), href=guide_elem.get('href'), id='calibre_raster_cover') + t.set('media-type', 'image/jpeg') + if os.path.exists(guide_cover): + renderer = render_html_svg_workaround(guide_cover, log) + if renderer is not None: + with lopen('calibre_raster_cover.jpg', 'wb') as f: + f.write(renderer) + + # Set the titlepage guide entry + self.set_guide_type(opf, 'titlepage', guide_cover, 'Title Page') + return removed + + def find_opf(self): + from calibre.utils.xml_parse import safe_xml_fromstring + + def attr(n, attr): + for k, v in n.attrib.items(): + if k.endswith(attr): + return v + try: + with lopen('META-INF/container.xml', 'rb') as f: + root = safe_xml_fromstring(f.read()) + for r in root.xpath('//*[local-name()="rootfile"]'): + if attr(r, 'media-type') != "application/oebps-package+xml": + continue + path = attr(r, 'full-path') + if not path: + continue + path = os.path.join(getcwd(), *path.split('/')) + if os.path.exists(path): + return path + except Exception: + import traceback + traceback.print_exc() + + def convert(self, stream, options, file_ext, log, accelerators): + from calibre.utils.zipfile import ZipFile + from calibre import walk + from calibre.ebooks import DRMError + from calibre.ebooks.metadata.opf2 import OPF + try: + zf = ZipFile(stream) + zf.extractall(getcwd()) + except: + log.exception('EPUB appears to be invalid ZIP file, trying a' + ' more forgiving ZIP parser') + from calibre.utils.localunzip import extractall + stream.seek(0) + extractall(stream) + encfile = os.path.abspath(os.path.join('META-INF', 'encryption.xml')) + opf = self.find_opf() + if opf is None: + for f in walk('.'): + if f.lower().endswith('.opf') and '__MACOSX' not in f and \ + not os.path.basename(f).startswith('.'): + opf = os.path.abspath(f) + break + path = getattr(stream, 'name', 'stream') + + if opf is None: + raise ValueError('%s is not a valid EPUB file (could not find opf)'%path) + + opf = os.path.relpath(opf, getcwd()) + parts = os.path.split(opf) + opf = OPF(opf, os.path.dirname(os.path.abspath(opf))) + + self._encrypted_font_uris = [] + if os.path.exists(encfile): + if not self.process_encryption(encfile, opf, log): + raise DRMError(os.path.basename(path)) + self.encrypted_fonts = self._encrypted_font_uris + + if len(parts) > 1 and parts[0]: + delta = '/'.join(parts[:-1])+'/' + + def normpath(x): + return posixpath.normpath(delta + elem.get('href')) + + for elem in opf.itermanifest(): + elem.set('href', normpath(elem.get('href'))) + for elem in opf.iterguide(): + elem.set('href', normpath(elem.get('href'))) + + f = self.rationalize_cover3 if opf.package_version >= 3.0 else self.rationalize_cover2 + self.removed_cover = f(opf, log) + if self.removed_cover: + self.removed_items_to_ignore = (self.removed_cover,) + epub3_nav = opf.epub3_nav + if epub3_nav is not None: + self.convert_epub3_nav(epub3_nav, opf, log, options) + + for x in opf.itermanifest(): + if x.get('media-type', '') == 'application/x-dtbook+xml': + raise ValueError( + 'EPUB files with DTBook markup are not supported') + + not_for_spine = set() + for y in opf.itermanifest(): + id_ = y.get('id', None) + if id_: + mt = y.get('media-type', None) + if mt in { + 'application/vnd.adobe-page-template+xml', + 'application/vnd.adobe.page-template+xml', + 'application/adobe-page-template+xml', + 'application/adobe.page-template+xml', + 'application/text' + }: + not_for_spine.add(id_) + ext = y.get('href', '').rpartition('.')[-1].lower() + if mt == 'text/plain' and ext in {'otf', 'ttf'}: + # some epub authoring software sets font mime types to + # text/plain + not_for_spine.add(id_) + y.set('media-type', 'application/font') + + seen = set() + for x in list(opf.iterspine()): + ref = x.get('idref', None) + if not ref or ref in not_for_spine or ref in seen: + x.getparent().remove(x) + continue + seen.add(ref) + + if len(list(opf.iterspine())) == 0: + raise ValueError('No valid entries in the spine of this EPUB') + + with lopen('content.opf', 'wb') as nopf: + nopf.write(opf.render()) + + return os.path.abspath('content.opf') + + def convert_epub3_nav(self, nav_path, opf, log, opts): + from lxml import etree + from calibre.ebooks.chardet import xml_to_unicode + from calibre.ebooks.oeb.polish.parsing import parse + from calibre.ebooks.oeb.base import EPUB_NS, XHTML, NCX_MIME, NCX, urlnormalize, urlunquote, serialize + from calibre.ebooks.oeb.polish.toc import first_child + from calibre.utils.xml_parse import safe_xml_fromstring + from tempfile import NamedTemporaryFile + with lopen(nav_path, 'rb') as f: + raw = f.read() + raw = xml_to_unicode(raw, strip_encoding_pats=True, assume_utf8=True)[0] + root = parse(raw, log=log) + ncx = safe_xml_fromstring('') + navmap = ncx[0] + et = '{%s}type' % EPUB_NS + bn = os.path.basename(nav_path) + + def add_from_li(li, parent): + href = text = None + for x in li.iterchildren(XHTML('a'), XHTML('span')): + text = etree.tostring( + x, method='text', encoding='unicode', with_tail=False).strip() or ' '.join( + x.xpath('descendant-or-self::*/@title')).strip() + href = x.get('href') + if href: + if href.startswith('#'): + href = bn + href + break + np = parent.makeelement(NCX('navPoint')) + parent.append(np) + np.append(np.makeelement(NCX('navLabel'))) + np[0].append(np.makeelement(NCX('text'))) + np[0][0].text = text + if href: + np.append(np.makeelement(NCX('content'), attrib={'src':href})) + return np + + def process_nav_node(node, toc_parent): + for li in node.iterchildren(XHTML('li')): + child = add_from_li(li, toc_parent) + ol = first_child(li, XHTML('ol')) + if child is not None and ol is not None: + process_nav_node(ol, child) + + for nav in root.iterdescendants(XHTML('nav')): + if nav.get(et) == 'toc': + ol = first_child(nav, XHTML('ol')) + if ol is not None: + process_nav_node(ol, navmap) + break + else: + return + + with NamedTemporaryFile(suffix='.ncx', dir=os.path.dirname(nav_path), delete=False) as f: + f.write(etree.tostring(ncx, encoding='utf-8')) + ncx_href = os.path.relpath(f.name, getcwd()).replace(os.sep, '/') + ncx_id = opf.create_manifest_item(ncx_href, NCX_MIME, append=True).get('id') + for spine in opf.root.xpath('//*[local-name()="spine"]'): + spine.set('toc', ncx_id) + opts.epub3_nav_href = urlnormalize(os.path.relpath(nav_path).replace(os.sep, '/')) + opts.epub3_nav_parsed = root + if getattr(self, 'removed_cover', None): + changed = False + base_path = os.path.dirname(nav_path) + for elem in root.xpath('//*[@href]'): + href, frag = elem.get('href').partition('#')[::2] + link_path = os.path.relpath(os.path.join(base_path, urlunquote(href)), base_path) + abs_href = urlnormalize(link_path) + if abs_href == self.removed_cover: + changed = True + elem.set('data-calibre-removed-titlepage', '1') + if changed: + with lopen(nav_path, 'wb') as f: + f.write(serialize(root, 'application/xhtml+xml')) + + def postprocess_book(self, oeb, opts, log): + rc = getattr(self, 'removed_cover', None) + if rc: + cover_toc_item = None + for item in oeb.toc.iterdescendants(): + if item.href and item.href.partition('#')[0] == rc: + cover_toc_item = item + break + spine = {x.href for x in oeb.spine} + if (cover_toc_item is not None and cover_toc_item not in spine): + oeb.toc.item_that_refers_to_cover = cover_toc_item diff --git a/ebook_converter/ebooks/conversion/plugins/epub_output.py b/ebook_converter/ebooks/conversion/plugins/epub_output.py new file mode 100644 index 0000000..2265508 --- /dev/null +++ b/ebook_converter/ebooks/conversion/plugins/epub_output.py @@ -0,0 +1,548 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2009, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import os, shutil, re + +from calibre.customize.conversion import (OutputFormatPlugin, + OptionRecommendation) +from calibre.ptempfile import TemporaryDirectory +from calibre import CurrentDir +from polyglot.builtins import unicode_type, filter, map, zip, range, as_bytes + +block_level_tags = ( + 'address', + 'body', + 'blockquote', + 'center', + 'dir', + 'div', + 'dl', + 'fieldset', + 'form', + 'h1', + 'h2', + 'h3', + 'h4', + 'h5', + 'h6', + 'hr', + 'isindex', + 'menu', + 'noframes', + 'noscript', + 'ol', + 'p', + 'pre', + 'table', + 'ul', +) + + +class EPUBOutput(OutputFormatPlugin): + + name = 'EPUB Output' + author = 'Kovid Goyal' + file_type = 'epub' + commit_name = 'epub_output' + ui_data = {'versions': ('2', '3')} + + options = { + OptionRecommendation(name='extract_to', + help=_('Extract the contents of the generated %s file to the ' + 'specified directory. The contents of the directory are first ' + 'deleted, so be careful.') % 'EPUB'), + + OptionRecommendation(name='dont_split_on_page_breaks', + recommended_value=False, level=OptionRecommendation.LOW, + help=_('Turn off splitting at page breaks. Normally, input ' + 'files are automatically split at every page break into ' + 'two files. This gives an output e-book that can be ' + 'parsed faster and with less resources. However, ' + 'splitting is slow and if your source file contains a ' + 'very large number of page breaks, you should turn off ' + 'splitting on page breaks.' + ) + ), + + OptionRecommendation(name='flow_size', recommended_value=260, + help=_('Split all HTML files larger than this size (in KB). ' + 'This is necessary as most EPUB readers cannot handle large ' + 'file sizes. The default of %defaultKB is the size required ' + 'for Adobe Digital Editions. Set to 0 to disable size based splitting.') + ), + + OptionRecommendation(name='no_default_epub_cover', recommended_value=False, + help=_('Normally, if the input file has no cover and you don\'t' + ' specify one, a default cover is generated with the title, ' + 'authors, etc. This option disables the generation of this cover.') + ), + + OptionRecommendation(name='no_svg_cover', recommended_value=False, + help=_('Do not use SVG for the book cover. Use this option if ' + 'your EPUB is going to be used on a device that does not ' + 'support SVG, like the iPhone or the JetBook Lite. ' + 'Without this option, such devices will display the cover ' + 'as a blank page.') + ), + + OptionRecommendation(name='preserve_cover_aspect_ratio', + recommended_value=False, help=_( + 'When using an SVG cover, this option will cause the cover to scale ' + 'to cover the available screen area, but still preserve its aspect ratio ' + '(ratio of width to height). That means there may be white borders ' + 'at the sides or top and bottom of the image, but the image will ' + 'never be distorted. Without this option the image may be slightly ' + 'distorted, but there will be no borders.' + ) + ), + + OptionRecommendation(name='epub_flatten', recommended_value=False, + help=_('This option is needed only if you intend to use the EPUB' + ' with FBReaderJ. It will flatten the file system inside the' + ' EPUB, putting all files into the top level.') + ), + + OptionRecommendation(name='epub_inline_toc', recommended_value=False, + help=_('Insert an inline Table of Contents that will appear as part of the main book content.') + ), + + OptionRecommendation(name='epub_toc_at_end', recommended_value=False, + help=_('Put the inserted inline Table of Contents at the end of the book instead of the start.') + ), + + OptionRecommendation(name='toc_title', recommended_value=None, + help=_('Title for any generated in-line table of contents.') + ), + + OptionRecommendation(name='epub_version', recommended_value='2', choices=ui_data['versions'], + help=_('The version of the EPUB file to generate. EPUB 2 is the' + ' most widely compatible, only use EPUB 3 if you know you' + ' actually need it.') + ), + + } + + recommendations = {('pretty_print', True, OptionRecommendation.HIGH)} + + def workaround_webkit_quirks(self): # {{{ + from calibre.ebooks.oeb.base import XPath + for x in self.oeb.spine: + root = x.data + body = XPath('//h:body')(root) + if body: + body = body[0] + + if not hasattr(body, 'xpath'): + continue + + for pre in XPath('//h:pre')(body): + if not pre.text and len(pre) == 0: + pre.tag = 'div' + # }}} + + def upshift_markup(self): # {{{ + 'Upgrade markup to comply with XHTML 1.1 where possible' + from calibre.ebooks.oeb.base import XPath, XML + for x in self.oeb.spine: + root = x.data + if (not root.get(XML('lang'))) and (root.get('lang')): + root.set(XML('lang'), root.get('lang')) + body = XPath('//h:body')(root) + if body: + body = body[0] + + if not hasattr(body, 'xpath'): + continue + for u in XPath('//h:u')(root): + u.tag = 'span' + + seen_ids, seen_names = set(), set() + for x in XPath('//*[@id or @name]')(root): + eid, name = x.get('id', None), x.get('name', None) + if eid: + if eid in seen_ids: + del x.attrib['id'] + else: + seen_ids.add(eid) + if name: + if name in seen_names: + del x.attrib['name'] + else: + seen_names.add(name) + + # }}} + + def convert(self, oeb, output_path, input_plugin, opts, log): + self.log, self.opts, self.oeb = log, opts, oeb + + if self.opts.epub_inline_toc: + from calibre.ebooks.mobi.writer8.toc import TOCAdder + opts.mobi_toc_at_start = not opts.epub_toc_at_end + opts.mobi_passthrough = False + opts.no_inline_toc = False + TOCAdder(oeb, opts, replace_previous_inline_toc=True, ignore_existing_toc=True) + + if self.opts.epub_flatten: + from calibre.ebooks.oeb.transforms.filenames import FlatFilenames + FlatFilenames()(oeb, opts) + else: + from calibre.ebooks.oeb.transforms.filenames import UniqueFilenames + UniqueFilenames()(oeb, opts) + + self.workaround_ade_quirks() + self.workaround_webkit_quirks() + self.upshift_markup() + from calibre.ebooks.oeb.transforms.rescale import RescaleImages + RescaleImages(check_colorspaces=True)(oeb, opts) + + from calibre.ebooks.oeb.transforms.split import Split + split = Split(not self.opts.dont_split_on_page_breaks, + max_flow_size=self.opts.flow_size*1024 + ) + split(self.oeb, self.opts) + + from calibre.ebooks.oeb.transforms.cover import CoverManager + cm = CoverManager( + no_default_cover=self.opts.no_default_epub_cover, + no_svg_cover=self.opts.no_svg_cover, + preserve_aspect_ratio=self.opts.preserve_cover_aspect_ratio) + cm(self.oeb, self.opts, self.log) + + self.workaround_sony_quirks() + + if self.oeb.toc.count() == 0: + self.log.warn('This EPUB file has no Table of Contents. ' + 'Creating a default TOC') + first = next(iter(self.oeb.spine)) + self.oeb.toc.add(_('Start'), first.href) + + from calibre.ebooks.oeb.base import OPF + identifiers = oeb.metadata['identifier'] + uuid = None + for x in identifiers: + if x.get(OPF('scheme'), None).lower() == 'uuid' or unicode_type(x).startswith('urn:uuid:'): + uuid = unicode_type(x).split(':')[-1] + break + encrypted_fonts = getattr(input_plugin, 'encrypted_fonts', []) + + if uuid is None: + self.log.warn('No UUID identifier found') + from uuid import uuid4 + uuid = unicode_type(uuid4()) + oeb.metadata.add('identifier', uuid, scheme='uuid', id=uuid) + + if encrypted_fonts and not uuid.startswith('urn:uuid:'): + # Apparently ADE requires this value to start with urn:uuid: + # for some absurd reason, or it will throw a hissy fit and refuse + # to use the obfuscated fonts. + for x in identifiers: + if unicode_type(x) == uuid: + x.content = 'urn:uuid:'+uuid + + with TemporaryDirectory('_epub_output') as tdir: + from calibre.customize.ui import plugin_for_output_format + metadata_xml = None + extra_entries = [] + if self.is_periodical: + if self.opts.output_profile.epub_periodical_format == 'sony': + from calibre.ebooks.epub.periodical import sony_metadata + metadata_xml, atom_xml = sony_metadata(oeb) + extra_entries = [('atom.xml', 'application/atom+xml', atom_xml)] + oeb_output = plugin_for_output_format('oeb') + oeb_output.convert(oeb, tdir, input_plugin, opts, log) + opf = [x for x in os.listdir(tdir) if x.endswith('.opf')][0] + self.condense_ncx([os.path.join(tdir, x) for x in os.listdir(tdir) + if x.endswith('.ncx')][0]) + if self.opts.epub_version == '3': + self.upgrade_to_epub3(tdir, opf) + encryption = None + if encrypted_fonts: + encryption = self.encrypt_fonts(encrypted_fonts, tdir, uuid) + + from calibre.ebooks.epub import initialize_container + with initialize_container(output_path, os.path.basename(opf), + extra_entries=extra_entries) as epub: + epub.add_dir(tdir) + if encryption is not None: + epub.writestr('META-INF/encryption.xml', as_bytes(encryption)) + if metadata_xml is not None: + epub.writestr('META-INF/metadata.xml', + metadata_xml.encode('utf-8')) + if opts.extract_to is not None: + from calibre.utils.zipfile import ZipFile + if os.path.exists(opts.extract_to): + if os.path.isdir(opts.extract_to): + shutil.rmtree(opts.extract_to) + else: + os.remove(opts.extract_to) + os.mkdir(opts.extract_to) + with ZipFile(output_path) as zf: + zf.extractall(path=opts.extract_to) + self.log.info('EPUB extracted to', opts.extract_to) + + def upgrade_to_epub3(self, tdir, opf): + self.log.info('Upgrading to EPUB 3...') + from calibre.ebooks.epub import simple_container_xml + from calibre.ebooks.oeb.polish.cover import fix_conversion_titlepage_links_in_nav + try: + os.mkdir(os.path.join(tdir, 'META-INF')) + except EnvironmentError: + pass + with open(os.path.join(tdir, 'META-INF', 'container.xml'), 'wb') as f: + f.write(simple_container_xml(os.path.basename(opf)).encode('utf-8')) + from calibre.ebooks.oeb.polish.container import EpubContainer + container = EpubContainer(tdir, self.log) + from calibre.ebooks.oeb.polish.upgrade import epub_2_to_3 + existing_nav = getattr(self.opts, 'epub3_nav_parsed', None) + nav_href = getattr(self.opts, 'epub3_nav_href', None) + previous_nav = (nav_href, existing_nav) if existing_nav and nav_href else None + epub_2_to_3(container, self.log.info, previous_nav=previous_nav) + fix_conversion_titlepage_links_in_nav(container) + container.commit() + os.remove(f.name) + try: + os.rmdir(os.path.join(tdir, 'META-INF')) + except EnvironmentError: + pass + + def encrypt_fonts(self, uris, tdir, uuid): # {{{ + from polyglot.binary import from_hex_bytes + + key = re.sub(r'[^a-fA-F0-9]', '', uuid) + if len(key) < 16: + raise ValueError('UUID identifier %r is invalid'%uuid) + key = bytearray(from_hex_bytes((key + key)[:32])) + paths = [] + with CurrentDir(tdir): + paths = [os.path.join(*x.split('/')) for x in uris] + uris = dict(zip(uris, paths)) + fonts = [] + for uri in list(uris.keys()): + path = uris[uri] + if not os.path.exists(path): + uris.pop(uri) + continue + self.log.debug('Encrypting font:', uri) + with lopen(path, 'r+b') as f: + data = f.read(1024) + if len(data) >= 1024: + data = bytearray(data) + f.seek(0) + f.write(bytes(bytearray(data[i] ^ key[i%16] for i in range(1024)))) + else: + self.log.warn('Font', path, 'is invalid, ignoring') + if not isinstance(uri, unicode_type): + uri = uri.decode('utf-8') + fonts.append(''' + + + + + + + '''%(uri.replace('"', '\\"'))) + if fonts: + ans = ''' + ''' + ans += '\n'.join(fonts) + ans += '\n' + return ans + # }}} + + def condense_ncx(self, ncx_path): # {{{ + from lxml import etree + if not self.opts.pretty_print: + tree = etree.parse(ncx_path) + for tag in tree.getroot().iter(tag=etree.Element): + if tag.text: + tag.text = tag.text.strip() + if tag.tail: + tag.tail = tag.tail.strip() + compressed = etree.tostring(tree.getroot(), encoding='utf-8') + with open(ncx_path, 'wb') as f: + f.write(compressed) + # }}} + + def workaround_ade_quirks(self): # {{{ + ''' + Perform various markup transforms to get the output to render correctly + in the quirky ADE. + ''' + from calibre.ebooks.oeb.base import XPath, XHTML, barename, urlunquote + + stylesheet = self.oeb.manifest.main_stylesheet + + # ADE cries big wet tears when it encounters an invalid fragment + # identifier in the NCX toc. + frag_pat = re.compile(r'[-A-Za-z0-9_:.]+$') + for node in self.oeb.toc.iter(): + href = getattr(node, 'href', None) + if hasattr(href, 'partition'): + base, _, frag = href.partition('#') + frag = urlunquote(frag) + if frag and frag_pat.match(frag) is None: + self.log.warn( + 'Removing fragment identifier %r from TOC as Adobe Digital Editions cannot handle it'%frag) + node.href = base + + for x in self.oeb.spine: + root = x.data + body = XPath('//h:body')(root) + if body: + body = body[0] + + if hasattr(body, 'xpath'): + # remove tags with empty src elements + bad = [] + for x in XPath('//h:img')(body): + src = x.get('src', '').strip() + if src in ('', '#') or src.startswith('http:'): + bad.append(x) + for img in bad: + img.getparent().remove(img) + + # Add id attribute to tags that have name + for x in XPath('//h:a[@name]')(body): + if not x.get('id', False): + x.set('id', x.get('name')) + # The delightful epubcheck has started complaining about tags that + # have name attributes. + x.attrib.pop('name') + + # Replace
that are children of as ADE doesn't handle them + for br in XPath('./h:br')(body): + if br.getparent() is None: + continue + try: + prior = next(br.itersiblings(preceding=True)) + priortag = barename(prior.tag) + priortext = prior.tail + except: + priortag = 'body' + priortext = body.text + if priortext: + priortext = priortext.strip() + br.tag = XHTML('p') + br.text = '\u00a0' + style = br.get('style', '').split(';') + style = list(filter(None, map(lambda x: x.strip(), style))) + style.append('margin:0pt; border:0pt') + # If the prior tag is a block (including a
we replaced) + # then this
replacement should have a 1-line height. + # Otherwise it should have no height. + if not priortext and priortag in block_level_tags: + style.append('height:1em') + else: + style.append('height:0pt') + br.set('style', '; '.join(style)) + + for tag in XPath('//h:embed')(root): + tag.getparent().remove(tag) + for tag in XPath('//h:object')(root): + if tag.get('type', '').lower().strip() in {'image/svg+xml', 'application/svg+xml'}: + continue + tag.getparent().remove(tag) + + for tag in XPath('//h:title|//h:style')(root): + if not tag.text: + tag.getparent().remove(tag) + for tag in XPath('//h:script')(root): + if (not tag.text and not tag.get('src', False) and tag.get('type', None) != 'text/x-mathjax-config'): + tag.getparent().remove(tag) + for tag in XPath('//h:body/descendant::h:script')(root): + tag.getparent().remove(tag) + + formchildren = XPath('./h:input|./h:button|./h:textarea|' + './h:label|./h:fieldset|./h:legend') + for tag in XPath('//h:form')(root): + if formchildren(tag): + tag.getparent().remove(tag) + else: + # Not a real form + tag.tag = XHTML('div') + + for tag in XPath('//h:center')(root): + tag.tag = XHTML('div') + tag.set('style', 'text-align:center') + # ADE can't handle & in an img url + for tag in XPath('//h:img[@src]')(root): + tag.set('src', tag.get('src', '').replace('&', '')) + + # ADE whimpers in fright when it encounters a outside a + # + in_table = XPath('ancestor::h:table') + for tag in XPath('//h:td|//h:tr|//h:th')(root): + if not in_table(tag): + tag.tag = XHTML('div') + + # ADE fails to render non breaking hyphens/soft hyphens/zero width spaces + special_chars = re.compile('[\u200b\u00ad]') + for elem in root.iterdescendants('*'): + if elem.text: + elem.text = special_chars.sub('', elem.text) + elem.text = elem.text.replace('\u2011', '-') + if elem.tail: + elem.tail = special_chars.sub('', elem.tail) + elem.tail = elem.tail.replace('\u2011', '-') + + if stylesheet is not None: + # ADE doesn't render lists correctly if they have left margins + from css_parser.css import CSSRule + for lb in XPath('//h:ul[@class]|//h:ol[@class]')(root): + sel = '.'+lb.get('class') + for rule in stylesheet.data.cssRules.rulesOfType(CSSRule.STYLE_RULE): + if sel == rule.selectorList.selectorText: + rule.style.removeProperty('margin-left') + # padding-left breaks rendering in webkit and gecko + rule.style.removeProperty('padding-left') + # Change whitespace:pre to pre-wrap to accommodate readers that + # cannot scroll horizontally + for rule in stylesheet.data.cssRules.rulesOfType(CSSRule.STYLE_RULE): + style = rule.style + ws = style.getPropertyValue('white-space') + if ws == 'pre': + style.setProperty('white-space', 'pre-wrap') + + # }}} + + def workaround_sony_quirks(self): # {{{ + ''' + Perform toc link transforms to alleviate slow loading. + ''' + from calibre.ebooks.oeb.base import urldefrag, XPath + from calibre.ebooks.oeb.polish.toc import item_at_top + + def frag_is_at_top(root, frag): + elem = XPath('//*[@id="%s" or @name="%s"]'%(frag, frag))(root) + if elem: + elem = elem[0] + else: + return False + return item_at_top(elem) + + def simplify_toc_entry(toc): + if toc.href: + href, frag = urldefrag(toc.href) + if frag: + for x in self.oeb.spine: + if x.href == href: + if frag_is_at_top(x.data, frag): + self.log.debug('Removing anchor from TOC href:', + href+'#'+frag) + toc.href = href + break + for x in toc: + simplify_toc_entry(x) + + if self.oeb.toc: + simplify_toc_entry(self.oeb.toc) + + # }}} diff --git a/ebook_converter/ebooks/conversion/plugins/fb2_input.py b/ebook_converter/ebooks/conversion/plugins/fb2_input.py new file mode 100644 index 0000000..d82220d --- /dev/null +++ b/ebook_converter/ebooks/conversion/plugins/fb2_input.py @@ -0,0 +1,179 @@ +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2008, Anatoly Shipitsin ' +""" +Convert .fb2 files to .lrf +""" +import os, re + +from calibre.customize.conversion import InputFormatPlugin, OptionRecommendation +from calibre import guess_type +from polyglot.builtins import iteritems, getcwd + +FB2NS = 'http://www.gribuser.ru/xml/fictionbook/2.0' +FB21NS = 'http://www.gribuser.ru/xml/fictionbook/2.1' + + +class FB2Input(InputFormatPlugin): + + name = 'FB2 Input' + author = 'Anatoly Shipitsin' + description = 'Convert FB2 and FBZ files to HTML' + file_types = {'fb2', 'fbz'} + commit_name = 'fb2_input' + + recommendations = { + ('level1_toc', '//h:h1', OptionRecommendation.MED), + ('level2_toc', '//h:h2', OptionRecommendation.MED), + ('level3_toc', '//h:h3', OptionRecommendation.MED), + } + + options = { + OptionRecommendation(name='no_inline_fb2_toc', + recommended_value=False, level=OptionRecommendation.LOW, + help=_('Do not insert a Table of Contents at the beginning of the book.' + ) + )} + + def convert(self, stream, options, file_ext, log, + accelerators): + from lxml import etree + from calibre.utils.xml_parse import safe_xml_fromstring + from calibre.ebooks.metadata.fb2 import ensure_namespace, get_fb2_data + from calibre.ebooks.metadata.opf2 import OPFCreator + from calibre.ebooks.metadata.meta import get_metadata + from calibre.ebooks.oeb.base import XLINK_NS, XHTML_NS + from calibre.ebooks.chardet import xml_to_unicode + self.log = log + log.debug('Parsing XML...') + raw = get_fb2_data(stream)[0] + raw = raw.replace(b'\0', b'') + raw = xml_to_unicode(raw, strip_encoding_pats=True, + assume_utf8=True, resolve_entities=True)[0] + try: + doc = safe_xml_fromstring(raw) + except etree.XMLSyntaxError: + doc = safe_xml_fromstring(raw.replace('& ', '&')) + if doc is None: + raise ValueError('The FB2 file is not valid XML') + doc = ensure_namespace(doc) + try: + fb_ns = doc.nsmap[doc.prefix] + except Exception: + fb_ns = FB2NS + + NAMESPACES = {'f':fb_ns, 'l':XLINK_NS} + stylesheets = doc.xpath('//*[local-name() = "stylesheet" and @type="text/css"]') + css = '' + for s in stylesheets: + css += etree.tostring(s, encoding='unicode', method='text', + with_tail=False) + '\n\n' + if css: + import css_parser, logging + parser = css_parser.CSSParser(fetcher=None, + log=logging.getLogger('calibre.css')) + + XHTML_CSS_NAMESPACE = '@namespace "%s";\n' % XHTML_NS + text = XHTML_CSS_NAMESPACE + css + log.debug('Parsing stylesheet...') + stylesheet = parser.parseString(text) + stylesheet.namespaces['h'] = XHTML_NS + css = stylesheet.cssText + if isinstance(css, bytes): + css = css.decode('utf-8', 'replace') + css = css.replace('h|style', 'h|span') + css = re.sub(r'name\s*=\s*', 'class=', css) + self.extract_embedded_content(doc) + log.debug('Converting XML to HTML...') + with open(P('templates/fb2.xsl'), 'rb') as f: + ss = f.read().decode('utf-8') + ss = ss.replace("__FB_NS__", fb_ns) + if options.no_inline_fb2_toc: + log('Disabling generation of inline FB2 TOC') + ss = re.compile(r'.*', + re.DOTALL).sub('', ss) + + styledoc = safe_xml_fromstring(ss) + + transform = etree.XSLT(styledoc) + result = transform(doc) + + # Handle links of type note and cite + notes = {a.get('href')[1:]: a for a in result.xpath('//a[@link_note and @href]') if a.get('href').startswith('#')} + cites = {a.get('link_cite'): a for a in result.xpath('//a[@link_cite]') if not a.get('href', '')} + all_ids = {x for x in result.xpath('//*/@id')} + for cite, a in iteritems(cites): + note = notes.get(cite, None) + if note: + c = 1 + while 'cite%d' % c in all_ids: + c += 1 + if not note.get('id', None): + note.set('id', 'cite%d' % c) + all_ids.add(note.get('id')) + a.set('href', '#%s' % note.get('id')) + for x in result.xpath('//*[@link_note or @link_cite]'): + x.attrib.pop('link_note', None) + x.attrib.pop('link_cite', None) + + for img in result.xpath('//img[@src]'): + src = img.get('src') + img.set('src', self.binary_map.get(src, src)) + index = transform.tostring(result) + with open('index.xhtml', 'wb') as f: + f.write(index.encode('utf-8')) + with open('inline-styles.css', 'wb') as f: + f.write(css.encode('utf-8')) + stream.seek(0) + mi = get_metadata(stream, 'fb2') + if not mi.title: + mi.title = _('Unknown') + if not mi.authors: + mi.authors = [_('Unknown')] + cpath = None + if mi.cover_data and mi.cover_data[1]: + with open('fb2_cover_calibre_mi.jpg', 'wb') as f: + f.write(mi.cover_data[1]) + cpath = os.path.abspath('fb2_cover_calibre_mi.jpg') + else: + for img in doc.xpath('//f:coverpage/f:image', namespaces=NAMESPACES): + href = img.get('{%s}href'%XLINK_NS, img.get('href', None)) + if href is not None: + if href.startswith('#'): + href = href[1:] + cpath = os.path.abspath(href) + break + + opf = OPFCreator(getcwd(), mi) + entries = [(f2, guess_type(f2)[0]) for f2 in os.listdir(u'.')] + opf.create_manifest(entries) + opf.create_spine(['index.xhtml']) + if cpath: + opf.guide.set_cover(cpath) + with open('metadata.opf', 'wb') as f: + opf.render(f) + return os.path.join(getcwd(), 'metadata.opf') + + def extract_embedded_content(self, doc): + from calibre.ebooks.fb2 import base64_decode + self.binary_map = {} + for elem in doc.xpath('./*'): + if elem.text and 'binary' in elem.tag and 'id' in elem.attrib: + ct = elem.get('content-type', '') + fname = elem.attrib['id'] + ext = ct.rpartition('/')[-1].lower() + if ext in ('png', 'jpeg', 'jpg'): + if fname.lower().rpartition('.')[-1] not in {'jpg', 'jpeg', + 'png'}: + fname += '.' + ext + self.binary_map[elem.get('id')] = fname + raw = elem.text.strip() + try: + data = base64_decode(raw) + except TypeError: + self.log.exception('Binary data with id=%s is corrupted, ignoring'%( + elem.get('id'))) + else: + with open(fname, 'wb') as f: + f.write(data) diff --git a/ebook_converter/ebooks/conversion/plugins/fb2_output.py b/ebook_converter/ebooks/conversion/plugins/fb2_output.py new file mode 100644 index 0000000..ce99457 --- /dev/null +++ b/ebook_converter/ebooks/conversion/plugins/fb2_output.py @@ -0,0 +1,203 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL 3' +__copyright__ = '2009, John Schember ' +__docformat__ = 'restructuredtext en' + +import os + +from calibre.customize.conversion import OutputFormatPlugin, OptionRecommendation + + +class FB2Output(OutputFormatPlugin): + + name = 'FB2 Output' + author = 'John Schember' + file_type = 'fb2' + commit_name = 'fb2_output' + + FB2_GENRES = [ + # Science Fiction & Fantasy + 'sf_history', # Alternative history + 'sf_action', # Action + 'sf_epic', # Epic + 'sf_heroic', # Heroic + 'sf_detective', # Detective + 'sf_cyberpunk', # Cyberpunk + 'sf_space', # Space + 'sf_social', # Social#philosophical + 'sf_horror', # Horror & mystic + 'sf_humor', # Humor + 'sf_fantasy', # Fantasy + 'sf', # Science Fiction + # Detectives & Thrillers + 'det_classic', # Classical detectives + 'det_police', # Police Stories + 'det_action', # Action + 'det_irony', # Ironical detectives + 'det_history', # Historical detectives + 'det_espionage', # Espionage detectives + 'det_crime', # Crime detectives + 'det_political', # Political detectives + 'det_maniac', # Maniacs + 'det_hard', # Hard#boiled + 'thriller', # Thrillers + 'detective', # Detectives + # Prose + 'prose_classic', # Classics prose + 'prose_history', # Historical prose + 'prose_contemporary', # Contemporary prose + 'prose_counter', # Counterculture + 'prose_rus_classic', # Russial classics prose + 'prose_su_classics', # Soviet classics prose + # Romance + 'love_contemporary', # Contemporary Romance + 'love_history', # Historical Romance + 'love_detective', # Detective Romance + 'love_short', # Short Romance + 'love_erotica', # Erotica + # Adventure + 'adv_western', # Western + 'adv_history', # History + 'adv_indian', # Indians + 'adv_maritime', # Maritime Fiction + 'adv_geo', # Travel & geography + 'adv_animal', # Nature & animals + 'adventure', # Other + # Children's + 'child_tale', # Fairy Tales + 'child_verse', # Verses + 'child_prose', # Prose + 'child_sf', # Science Fiction + 'child_det', # Detectives & Thrillers + 'child_adv', # Adventures + 'child_education', # Educational + 'children', # Other + # Poetry & Dramaturgy + 'poetry', # Poetry + 'dramaturgy', # Dramaturgy + # Antique literature + 'antique_ant', # Antique + 'antique_european', # European + 'antique_russian', # Old russian + 'antique_east', # Old east + 'antique_myths', # Myths. Legends. Epos + 'antique', # Other + # Scientific#educational + 'sci_history', # History + 'sci_psychology', # Psychology + 'sci_culture', # Cultural science + 'sci_religion', # Religious studies + 'sci_philosophy', # Philosophy + 'sci_politics', # Politics + 'sci_business', # Business literature + 'sci_juris', # Jurisprudence + 'sci_linguistic', # Linguistics + 'sci_medicine', # Medicine + 'sci_phys', # Physics + 'sci_math', # Mathematics + 'sci_chem', # Chemistry + 'sci_biology', # Biology + 'sci_tech', # Technical + 'science', # Other + # Computers & Internet + 'comp_www', # Internet + 'comp_programming', # Programming + 'comp_hard', # Hardware + 'comp_soft', # Software + 'comp_db', # Databases + 'comp_osnet', # OS & Networking + 'computers', # Other + # Reference + 'ref_encyc', # Encyclopedias + 'ref_dict', # Dictionaries + 'ref_ref', # Reference + 'ref_guide', # Guidebooks + 'reference', # Other + # Nonfiction + 'nonf_biography', # Biography & Memoirs + 'nonf_publicism', # Publicism + 'nonf_criticism', # Criticism + 'design', # Art & design + 'nonfiction', # Other + # Religion & Inspiration + 'religion_rel', # Religion + 'religion_esoterics', # Esoterics + 'religion_self', # Self#improvement + 'religion', # Other + # Humor + 'humor_anecdote', # Anecdote (funny stories) + 'humor_prose', # Prose + 'humor_verse', # Verses + 'humor', # Other + # Home & Family + 'home_cooking', # Cooking + 'home_pets', # Pets + 'home_crafts', # Hobbies & Crafts + 'home_entertain', # Entertaining + 'home_health', # Health + 'home_garden', # Garden + 'home_diy', # Do it yourself + 'home_sport', # Sports + 'home_sex', # Erotica & sex + 'home', # Other + ] + ui_data = { + 'sectionize': { + 'toc': _('Section per entry in the ToC'), + 'files': _('Section per file'), + 'nothing': _('A single section') + }, + 'genres': FB2_GENRES, + } + + options = { + OptionRecommendation(name='sectionize', + recommended_value='files', level=OptionRecommendation.LOW, + choices=list(ui_data['sectionize']), + help=_('Specify how sections are created:\n' + ' * nothing: {nothing}\n' + ' * files: {files}\n' + ' * toc: {toc}\n' + 'If ToC based generation fails, adjust the "Structure detection" and/or "Table of Contents" settings ' + '(turn on "Force use of auto-generated Table of Contents").').format(**ui_data['sectionize']) + ), + OptionRecommendation(name='fb2_genre', + recommended_value='antique', level=OptionRecommendation.LOW, + choices=FB2_GENRES, + help=(_('Genre for the book. Choices: %s\n\n See: ') % ', '.join(FB2_GENRES) + ) + 'http://www.fictionbook.org/index.php/Eng:FictionBook_2.1_genres ' + _('for a complete list with descriptions.')), + } + + def convert(self, oeb_book, output_path, input_plugin, opts, log): + from calibre.ebooks.oeb.transforms.jacket import linearize_jacket + from calibre.ebooks.oeb.transforms.rasterize import SVGRasterizer, Unavailable + from calibre.ebooks.fb2.fb2ml import FB2MLizer + + try: + rasterizer = SVGRasterizer() + rasterizer(oeb_book, opts) + except Unavailable: + log.warn('SVG rasterizer unavailable, SVG will not be converted') + + linearize_jacket(oeb_book) + + fb2mlizer = FB2MLizer(log) + fb2_content = fb2mlizer.extract_content(oeb_book, opts) + + close = False + if not hasattr(output_path, 'write'): + close = True + if not os.path.exists(os.path.dirname(output_path)) and os.path.dirname(output_path) != '': + os.makedirs(os.path.dirname(output_path)) + out_stream = lopen(output_path, 'wb') + else: + out_stream = output_path + + out_stream.seek(0) + out_stream.truncate() + out_stream.write(fb2_content.encode('utf-8', 'replace')) + + if close: + out_stream.close() diff --git a/ebook_converter/ebooks/conversion/plugins/html_input.py b/ebook_converter/ebooks/conversion/plugins/html_input.py new file mode 100644 index 0000000..b74cfba --- /dev/null +++ b/ebook_converter/ebooks/conversion/plugins/html_input.py @@ -0,0 +1,316 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2012, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import re, tempfile, os +from functools import partial + +from calibre.constants import islinux, isbsd +from calibre.customize.conversion import (InputFormatPlugin, + OptionRecommendation) +from calibre.utils.localization import get_lang +from calibre.utils.filenames import ascii_filename +from calibre.utils.imghdr import what +from polyglot.builtins import unicode_type, zip, getcwd, as_unicode + + +def sanitize_file_name(x): + ans = re.sub(r'\s+', ' ', re.sub(r'[?&=;#]', '_', ascii_filename(x))).strip().rstrip('.') + ans, ext = ans.rpartition('.')[::2] + return (ans.strip() + '.' + ext.strip()).rstrip('.') + + +class HTMLInput(InputFormatPlugin): + + name = 'HTML Input' + author = 'Kovid Goyal' + description = 'Convert HTML and OPF files to an OEB' + file_types = {'opf', 'html', 'htm', 'xhtml', 'xhtm', 'shtm', 'shtml'} + commit_name = 'html_input' + + options = { + OptionRecommendation(name='breadth_first', + recommended_value=False, level=OptionRecommendation.LOW, + help=_('Traverse links in HTML files breadth first. Normally, ' + 'they are traversed depth first.' + ) + ), + + OptionRecommendation(name='max_levels', + recommended_value=5, level=OptionRecommendation.LOW, + help=_('Maximum levels of recursion when following links in ' + 'HTML files. Must be non-negative. 0 implies that no ' + 'links in the root HTML file are followed. Default is ' + '%default.' + ) + ), + + OptionRecommendation(name='dont_package', + recommended_value=False, level=OptionRecommendation.LOW, + help=_('Normally this input plugin re-arranges all the input ' + 'files into a standard folder hierarchy. Only use this option ' + 'if you know what you are doing as it can result in various ' + 'nasty side effects in the rest of the conversion pipeline.' + ) + ), + + } + + def convert(self, stream, opts, file_ext, log, + accelerators): + self._is_case_sensitive = None + basedir = getcwd() + self.opts = opts + + fname = None + if hasattr(stream, 'name'): + basedir = os.path.dirname(stream.name) + fname = os.path.basename(stream.name) + + if file_ext != 'opf': + if opts.dont_package: + raise ValueError('The --dont-package option is not supported for an HTML input file') + from calibre.ebooks.metadata.html import get_metadata + mi = get_metadata(stream) + if fname: + from calibre.ebooks.metadata.meta import metadata_from_filename + fmi = metadata_from_filename(fname) + fmi.smart_update(mi) + mi = fmi + oeb = self.create_oebbook(stream.name, basedir, opts, log, mi) + return oeb + + from calibre.ebooks.conversion.plumber import create_oebbook + return create_oebbook(log, stream.name, opts, + encoding=opts.input_encoding) + + def is_case_sensitive(self, path): + if getattr(self, '_is_case_sensitive', None) is not None: + return self._is_case_sensitive + if not path or not os.path.exists(path): + return islinux or isbsd + self._is_case_sensitive = not (os.path.exists(path.lower()) and os.path.exists(path.upper())) + return self._is_case_sensitive + + def create_oebbook(self, htmlpath, basedir, opts, log, mi): + import uuid + from calibre.ebooks.conversion.plumber import create_oebbook + from calibre.ebooks.oeb.base import (DirContainer, + rewrite_links, urlnormalize, urldefrag, BINARY_MIME, OEB_STYLES, + xpath, urlquote) + from calibre import guess_type + from calibre.ebooks.oeb.transforms.metadata import \ + meta_info_to_oeb_metadata + from calibre.ebooks.html.input import get_filelist + from calibre.ebooks.metadata import string_to_authors + from calibre.utils.localization import canonicalize_lang + import css_parser, logging + css_parser.log.setLevel(logging.WARN) + self.OEB_STYLES = OEB_STYLES + oeb = create_oebbook(log, None, opts, self, + encoding=opts.input_encoding, populate=False) + self.oeb = oeb + + metadata = oeb.metadata + meta_info_to_oeb_metadata(mi, metadata, log) + if not metadata.language: + l = canonicalize_lang(getattr(opts, 'language', None)) + if not l: + oeb.logger.warn('Language not specified') + l = get_lang().replace('_', '-') + metadata.add('language', l) + if not metadata.creator: + a = getattr(opts, 'authors', None) + if a: + a = string_to_authors(a) + if not a: + oeb.logger.warn('Creator not specified') + a = [self.oeb.translate(__('Unknown'))] + for aut in a: + metadata.add('creator', aut) + if not metadata.title: + oeb.logger.warn('Title not specified') + metadata.add('title', self.oeb.translate(__('Unknown'))) + bookid = unicode_type(uuid.uuid4()) + metadata.add('identifier', bookid, id='uuid_id', scheme='uuid') + for ident in metadata.identifier: + if 'id' in ident.attrib: + self.oeb.uid = metadata.identifier[0] + break + + filelist = get_filelist(htmlpath, basedir, opts, log) + filelist = [f for f in filelist if not f.is_binary] + htmlfile_map = {} + for f in filelist: + path = f.path + oeb.container = DirContainer(os.path.dirname(path), log, + ignore_opf=True) + bname = os.path.basename(path) + id, href = oeb.manifest.generate(id='html', href=sanitize_file_name(bname)) + htmlfile_map[path] = href + item = oeb.manifest.add(id, href, 'text/html') + if path == htmlpath and '%' in path: + bname = urlquote(bname) + item.html_input_href = bname + oeb.spine.add(item, True) + + self.added_resources = {} + self.log = log + self.log('Normalizing filename cases') + for path, href in htmlfile_map.items(): + if not self.is_case_sensitive(path): + path = path.lower() + self.added_resources[path] = href + self.urlnormalize, self.DirContainer = urlnormalize, DirContainer + self.urldefrag = urldefrag + self.guess_type, self.BINARY_MIME = guess_type, BINARY_MIME + + self.log('Rewriting HTML links') + for f in filelist: + path = f.path + dpath = os.path.dirname(path) + oeb.container = DirContainer(dpath, log, ignore_opf=True) + href = htmlfile_map[path] + try: + item = oeb.manifest.hrefs[href] + except KeyError: + item = oeb.manifest.hrefs[urlnormalize(href)] + rewrite_links(item.data, partial(self.resource_adder, base=dpath)) + + for item in oeb.manifest.values(): + if item.media_type in self.OEB_STYLES: + dpath = None + for path, href in self.added_resources.items(): + if href == item.href: + dpath = os.path.dirname(path) + break + css_parser.replaceUrls(item.data, + partial(self.resource_adder, base=dpath)) + + toc = self.oeb.toc + self.oeb.auto_generated_toc = True + titles = [] + headers = [] + for item in self.oeb.spine: + if not item.linear: + continue + html = item.data + title = ''.join(xpath(html, '/h:html/h:head/h:title/text()')) + title = re.sub(r'\s+', ' ', title.strip()) + if title: + titles.append(title) + headers.append('(unlabled)') + for tag in ('h1', 'h2', 'h3', 'h4', 'h5', 'strong'): + expr = '/h:html/h:body//h:%s[position()=1]/text()' + header = ''.join(xpath(html, expr % tag)) + header = re.sub(r'\s+', ' ', header.strip()) + if header: + headers[-1] = header + break + use = titles + if len(titles) > len(set(titles)): + use = headers + for title, item in zip(use, self.oeb.spine): + if not item.linear: + continue + toc.add(title, item.href) + + oeb.container = DirContainer(getcwd(), oeb.log, ignore_opf=True) + return oeb + + def link_to_local_path(self, link_, base=None): + from calibre.ebooks.html.input import Link + if not isinstance(link_, unicode_type): + try: + link_ = link_.decode('utf-8', 'error') + except: + self.log.warn('Failed to decode link %r. Ignoring'%link_) + return None, None + try: + l = Link(link_, base if base else getcwd()) + except: + self.log.exception('Failed to process link: %r'%link_) + return None, None + if l.path is None: + # Not a local resource + return None, None + link = l.path.replace('/', os.sep).strip() + frag = l.fragment + if not link: + return None, None + return link, frag + + def resource_adder(self, link_, base=None): + from polyglot.urllib import quote + link, frag = self.link_to_local_path(link_, base=base) + if link is None: + return link_ + try: + if base and not os.path.isabs(link): + link = os.path.join(base, link) + link = os.path.abspath(link) + except: + return link_ + if not os.access(link, os.R_OK): + return link_ + if os.path.isdir(link): + self.log.warn(link_, 'is a link to a directory. Ignoring.') + return link_ + if not self.is_case_sensitive(tempfile.gettempdir()): + link = link.lower() + if link not in self.added_resources: + bhref = os.path.basename(link) + id, href = self.oeb.manifest.generate(id='added', href=sanitize_file_name(bhref)) + guessed = self.guess_type(href)[0] + media_type = guessed or self.BINARY_MIME + if media_type == 'text/plain': + self.log.warn('Ignoring link to text file %r'%link_) + return None + if media_type == self.BINARY_MIME: + # Check for the common case, images + try: + img = what(link) + except EnvironmentError: + pass + else: + if img: + media_type = self.guess_type('dummy.'+img)[0] or self.BINARY_MIME + + self.oeb.log.debug('Added', link) + self.oeb.container = self.DirContainer(os.path.dirname(link), + self.oeb.log, ignore_opf=True) + # Load into memory + item = self.oeb.manifest.add(id, href, media_type) + # bhref refers to an already existing file. The read() method of + # DirContainer will call unquote on it before trying to read the + # file, therefore we quote it here. + if isinstance(bhref, unicode_type): + bhref = bhref.encode('utf-8') + item.html_input_href = as_unicode(quote(bhref)) + if guessed in self.OEB_STYLES: + item.override_css_fetch = partial( + self.css_import_handler, os.path.dirname(link)) + item.data + self.added_resources[link] = href + + nlink = self.added_resources[link] + if frag: + nlink = '#'.join((nlink, frag)) + return nlink + + def css_import_handler(self, base, href): + link, frag = self.link_to_local_path(href, base=base) + if link is None or not os.access(link, os.R_OK) or os.path.isdir(link): + return (None, None) + try: + with open(link, 'rb') as f: + raw = f.read().decode('utf-8', 'replace') + raw = self.oeb.css_preprocessor(raw, add_namespace=False) + except: + self.log.exception('Failed to read CSS file: %r'%link) + return (None, None) + return (None, raw) diff --git a/ebook_converter/ebooks/conversion/plugins/html_output.py b/ebook_converter/ebooks/conversion/plugins/html_output.py new file mode 100644 index 0000000..b45c3c6 --- /dev/null +++ b/ebook_converter/ebooks/conversion/plugins/html_output.py @@ -0,0 +1,226 @@ +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL 3' +__copyright__ = '2010, Fabian Grassl ' +__docformat__ = 'restructuredtext en' + +import os, re, shutil +from os.path import dirname, abspath, relpath as _relpath, exists, basename + +from calibre.customize.conversion import OutputFormatPlugin, OptionRecommendation +from calibre import CurrentDir +from calibre.ptempfile import PersistentTemporaryDirectory +from polyglot.builtins import unicode_type + + +def relpath(*args): + return _relpath(*args).replace(os.sep, '/') + + +class HTMLOutput(OutputFormatPlugin): + + name = 'HTML Output' + author = 'Fabian Grassl' + file_type = 'zip' + commit_name = 'html_output' + + options = { + OptionRecommendation(name='template_css', + help=_('CSS file used for the output instead of the default file')), + + OptionRecommendation(name='template_html_index', + help=_('Template used for generation of the HTML index file instead of the default file')), + + OptionRecommendation(name='template_html', + help=_('Template used for the generation of the HTML contents of the book instead of the default file')), + + OptionRecommendation(name='extract_to', + help=_('Extract the contents of the generated ZIP file to the ' + 'specified directory. WARNING: The contents of the directory ' + 'will be deleted.') + ), + } + + recommendations = {('pretty_print', True, OptionRecommendation.HIGH)} + + def generate_toc(self, oeb_book, ref_url, output_dir): + ''' + Generate table of contents + ''' + from lxml import etree + from polyglot.urllib import unquote + + from calibre.ebooks.oeb.base import element + from calibre.utils.cleantext import clean_xml_chars + with CurrentDir(output_dir): + def build_node(current_node, parent=None): + if parent is None: + parent = etree.Element('ul') + elif len(current_node.nodes): + parent = element(parent, ('ul')) + for node in current_node.nodes: + point = element(parent, 'li') + href = relpath(abspath(unquote(node.href)), dirname(ref_url)) + if isinstance(href, bytes): + href = href.decode('utf-8') + link = element(point, 'a', href=clean_xml_chars(href)) + title = node.title + if isinstance(title, bytes): + title = title.decode('utf-8') + if title: + title = re.sub(r'\s+', ' ', title) + link.text = clean_xml_chars(title) + build_node(node, point) + return parent + wrap = etree.Element('div') + wrap.append(build_node(oeb_book.toc)) + return wrap + + def generate_html_toc(self, oeb_book, ref_url, output_dir): + from lxml import etree + + root = self.generate_toc(oeb_book, ref_url, output_dir) + return etree.tostring(root, pretty_print=True, encoding='unicode', + xml_declaration=False) + + def convert(self, oeb_book, output_path, input_plugin, opts, log): + from lxml import etree + from calibre.utils import zipfile + from templite import Templite + from polyglot.urllib import unquote + from calibre.ebooks.html.meta import EasyMeta + + # read template files + if opts.template_html_index is not None: + with open(opts.template_html_index, 'rb') as f: + template_html_index_data = f.read() + else: + template_html_index_data = P('templates/html_export_default_index.tmpl', data=True) + + if opts.template_html is not None: + with open(opts.template_html, 'rb') as f: + template_html_data = f.read() + else: + template_html_data = P('templates/html_export_default.tmpl', data=True) + + if opts.template_css is not None: + with open(opts.template_css, 'rb') as f: + template_css_data = f.read() + else: + template_css_data = P('templates/html_export_default.css', data=True) + + template_html_index_data = template_html_index_data.decode('utf-8') + template_html_data = template_html_data.decode('utf-8') + template_css_data = template_css_data.decode('utf-8') + + self.log = log + self.opts = opts + meta = EasyMeta(oeb_book.metadata) + + tempdir = os.path.realpath(PersistentTemporaryDirectory()) + output_file = os.path.join(tempdir, + basename(re.sub(r'\.zip', '', output_path)+'.html')) + output_dir = re.sub(r'\.html', '', output_file)+'_files' + + if not exists(output_dir): + os.makedirs(output_dir) + + css_path = output_dir+os.sep+'calibreHtmlOutBasicCss.css' + with open(css_path, 'wb') as f: + f.write(template_css_data.encode('utf-8')) + + with open(output_file, 'wb') as f: + html_toc = self.generate_html_toc(oeb_book, output_file, output_dir) + templite = Templite(template_html_index_data) + nextLink = oeb_book.spine[0].href + nextLink = relpath(output_dir+os.sep+nextLink, dirname(output_file)) + cssLink = relpath(abspath(css_path), dirname(output_file)) + tocUrl = relpath(output_file, dirname(output_file)) + t = templite.render(has_toc=bool(oeb_book.toc.count()), + toc=html_toc, meta=meta, nextLink=nextLink, + tocUrl=tocUrl, cssLink=cssLink, + firstContentPageLink=nextLink) + if isinstance(t, unicode_type): + t = t.encode('utf-8') + f.write(t) + + with CurrentDir(output_dir): + for item in oeb_book.manifest: + path = abspath(unquote(item.href)) + dir = dirname(path) + if not exists(dir): + os.makedirs(dir) + if item.spine_position is not None: + with open(path, 'wb') as f: + pass + else: + with open(path, 'wb') as f: + f.write(item.bytes_representation) + item.unload_data_from_memory(memory=path) + + for item in oeb_book.spine: + path = abspath(unquote(item.href)) + dir = dirname(path) + root = item.data.getroottree() + + # get & clean HTML -data + head = root.xpath('//h:head', namespaces={'h': 'http://www.w3.org/1999/xhtml'})[0] + head_content = etree.tostring(head, pretty_print=True, encoding='unicode') + head_content = re.sub(r'\<\/?head.*\>', '', head_content) + head_content = re.sub(re.compile(r'\', re.M|re.S), '', head_content) + head_content = re.sub(r'<(title)([^>]*)/>', r'<\1\2>', head_content) + + # get & clean HTML -data + body = root.xpath('//h:body', namespaces={'h': 'http://www.w3.org/1999/xhtml'})[0] + ebook_content = etree.tostring(body, pretty_print=True, encoding='unicode') + ebook_content = re.sub(r'\<\/?body.*\>', '', ebook_content) + ebook_content = re.sub(r'<(div|a|span)([^>]*)/>', r'<\1\2>', ebook_content) + + # generate link to next page + if item.spine_position+1 < len(oeb_book.spine): + nextLink = oeb_book.spine[item.spine_position+1].href + nextLink = relpath(abspath(nextLink), dir) + else: + nextLink = None + + # generate link to previous page + if item.spine_position > 0: + prevLink = oeb_book.spine[item.spine_position-1].href + prevLink = relpath(abspath(prevLink), dir) + else: + prevLink = None + + cssLink = relpath(abspath(css_path), dir) + tocUrl = relpath(output_file, dir) + firstContentPageLink = oeb_book.spine[0].href + + # render template + templite = Templite(template_html_data) + toc = lambda: self.generate_html_toc(oeb_book, path, output_dir) + t = templite.render(ebookContent=ebook_content, + prevLink=prevLink, nextLink=nextLink, + has_toc=bool(oeb_book.toc.count()), toc=toc, + tocUrl=tocUrl, head_content=head_content, + meta=meta, cssLink=cssLink, + firstContentPageLink=firstContentPageLink) + + # write html to file + with open(path, 'wb') as f: + f.write(t.encode('utf-8')) + item.unload_data_from_memory(memory=path) + + zfile = zipfile.ZipFile(output_path, "w") + zfile.add_dir(output_dir, basename(output_dir)) + zfile.write(output_file, basename(output_file), zipfile.ZIP_DEFLATED) + + if opts.extract_to: + if os.path.exists(opts.extract_to): + shutil.rmtree(opts.extract_to) + os.makedirs(opts.extract_to) + zfile.extractall(opts.extract_to) + self.log('Zip file extracted to', opts.extract_to) + + zfile.close() + + # cleanup temp dir + shutil.rmtree(tempdir) diff --git a/ebook_converter/ebooks/conversion/plugins/htmlz_input.py b/ebook_converter/ebooks/conversion/plugins/htmlz_input.py new file mode 100644 index 0000000..baed0c1 --- /dev/null +++ b/ebook_converter/ebooks/conversion/plugins/htmlz_input.py @@ -0,0 +1,133 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + + +__license__ = 'GPL 3' +__copyright__ = '2011, John Schember ' +__docformat__ = 'restructuredtext en' + +import os + +from calibre import guess_type +from calibre.customize.conversion import InputFormatPlugin +from polyglot.builtins import getcwd + + +class HTMLZInput(InputFormatPlugin): + + name = 'HTLZ Input' + author = 'John Schember' + description = 'Convert HTML files to HTML' + file_types = {'htmlz'} + commit_name = 'htmlz_input' + + def convert(self, stream, options, file_ext, log, + accelerators): + from calibre.ebooks.chardet import xml_to_unicode + from calibre.ebooks.metadata.opf2 import OPF + from calibre.utils.zipfile import ZipFile + + self.log = log + html = u'' + top_levels = [] + + # Extract content from zip archive. + zf = ZipFile(stream) + zf.extractall() + + # Find the HTML file in the archive. It needs to be + # top level. + index = u'' + multiple_html = False + # Get a list of all top level files in the archive. + for x in os.listdir(u'.'): + if os.path.isfile(x): + top_levels.append(x) + # Try to find an index. file. + for x in top_levels: + if x.lower() in (u'index.html', u'index.xhtml', u'index.htm'): + index = x + break + # Look for multiple HTML files in the archive. We look at the + # top level files only as only they matter in HTMLZ. + for x in top_levels: + if os.path.splitext(x)[1].lower() in (u'.html', u'.xhtml', u'.htm'): + # Set index to the first HTML file found if it's not + # called index. + if not index: + index = x + else: + multiple_html = True + # Warn the user if there multiple HTML file in the archive. HTMLZ + # supports a single HTML file. A conversion with a multiple HTML file + # HTMLZ archive probably won't turn out as the user expects. With + # Multiple HTML files ZIP input should be used in place of HTMLZ. + if multiple_html: + log.warn(_('Multiple HTML files found in the archive. Only %s will be used.') % index) + + if index: + with open(index, 'rb') as tf: + html = tf.read() + else: + raise Exception(_('No top level HTML file found.')) + + if not html: + raise Exception(_('Top level HTML file %s is empty') % index) + + # Encoding + if options.input_encoding: + ienc = options.input_encoding + else: + ienc = xml_to_unicode(html[:4096])[-1] + html = html.decode(ienc, 'replace') + + # Run the HTML through the html processing plugin. + from calibre.customize.ui import plugin_for_input_format + html_input = plugin_for_input_format('html') + for opt in html_input.options: + setattr(options, opt.option.name, opt.recommended_value) + options.input_encoding = 'utf-8' + base = getcwd() + htmlfile = os.path.join(base, u'index.html') + c = 0 + while os.path.exists(htmlfile): + c += 1 + htmlfile = u'index%d.html'%c + with open(htmlfile, 'wb') as f: + f.write(html.encode('utf-8')) + odi = options.debug_pipeline + options.debug_pipeline = None + # Generate oeb from html conversion. + with open(htmlfile, 'rb') as f: + oeb = html_input.convert(f, options, 'html', log, + {}) + options.debug_pipeline = odi + os.remove(htmlfile) + + # Set metadata from file. + from calibre.customize.ui import get_file_type_metadata + from calibre.ebooks.oeb.transforms.metadata import meta_info_to_oeb_metadata + mi = get_file_type_metadata(stream, file_ext) + meta_info_to_oeb_metadata(mi, oeb.metadata, log) + + # Get the cover path from the OPF. + cover_path = None + opf = None + for x in top_levels: + if os.path.splitext(x)[1].lower() == u'.opf': + opf = x + break + if opf: + opf = OPF(opf, basedir=getcwd()) + cover_path = opf.raster_cover or opf.cover + # Set the cover. + if cover_path: + cdata = None + with open(os.path.join(getcwd(), cover_path), 'rb') as cf: + cdata = cf.read() + cover_name = os.path.basename(cover_path) + id, href = oeb.manifest.generate('cover', cover_name) + oeb.manifest.add(id, href, guess_type(cover_name)[0], data=cdata) + oeb.guide.add('cover', 'Cover', href) + + return oeb diff --git a/ebook_converter/ebooks/conversion/plugins/htmlz_output.py b/ebook_converter/ebooks/conversion/plugins/htmlz_output.py new file mode 100644 index 0000000..c72fd09 --- /dev/null +++ b/ebook_converter/ebooks/conversion/plugins/htmlz_output.py @@ -0,0 +1,136 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + + +__license__ = 'GPL 3' +__copyright__ = '2011, John Schember ' +__docformat__ = 'restructuredtext en' + +import io +import os + +from calibre.customize.conversion import OutputFormatPlugin, \ + OptionRecommendation +from calibre.ptempfile import TemporaryDirectory +from polyglot.builtins import unicode_type + + +class HTMLZOutput(OutputFormatPlugin): + + name = 'HTMLZ Output' + author = 'John Schember' + file_type = 'htmlz' + commit_name = 'htmlz_output' + ui_data = { + 'css_choices': { + 'class': _('Use CSS classes'), + 'inline': _('Use the style attribute'), + 'tag': _('Use HTML tags wherever possible') + }, + 'sheet_choices': { + 'external': _('Use an external CSS file'), + 'inline': _('Use a )', re.IGNORECASE|re.DOTALL), + strip_style_comments), + + # Remove self closing script tags as they also mess up BeautifulSoup + (re.compile(r'(?i)]+?/>'), lambda match: ''), + + # BeautifulSoup treats self closing
tags as open
tags + (re.compile(r'(?i)<\s*div([^>]*)/\s*>'), + lambda match: '
'%match.group(1)) + + ] + # Fix Baen markup + BAEN = [ + (re.compile(r'page-break-before:\s*\w+([\s;\}])', re.IGNORECASE), + lambda match: match.group(1)), + (re.compile(r'

\s*(\s*)\s*

', re.IGNORECASE), + lambda match: match.group(1)), + (re.compile(r'<\s*a\s+id="p[0-9]+"\s+name="p[0-9]+"\s*>\s*', re.IGNORECASE), + lambda match: ''), + ] + # Fix pdftohtml markup + PDFTOHTML = [ + # Remove
tags + (re.compile(r'', re.IGNORECASE), lambda match: '
'), + # Remove page numbers + (re.compile(r'\d+
', re.IGNORECASE), lambda match: ''), + # Remove
and replace

with

+ (re.compile(r'\s*', re.IGNORECASE), lambda match: '

'), + (re.compile(r'(.*)', re.IGNORECASE), + lambda match: match.group() if re.match('<', match.group(1).lstrip()) or len(match.group(1)) < 40 + else match.group(1)), + # Remove hyphenation + (re.compile(r'-\n\r?'), lambda match: ''), + + ] + + # Fix Book Designer markup + BOOK_DESIGNER = [ + # HR + (re.compile('


', re.IGNORECASE), + lambda match : ' '), + # Create header tags + (re.compile(r'<]*?id=BookTitle[^><]*?(align=)*(?(1)(\w+))*[^><]*?>[^><]*?', re.IGNORECASE), + lambda match : '

%s

'%(match.group(2) if match.group(2) else 'center', match.group(3))), + (re.compile(r'<]*?id=BookAuthor[^><]*?(align=)*(?(1)(\w+))*[^><]*?>[^><]*?', re.IGNORECASE), + lambda match : '

%s

'%(match.group(2) if match.group(2) else 'center', match.group(3))), + (re.compile(r'<]*?id=title[^><]*?>(.*?)', re.IGNORECASE|re.DOTALL), + lambda match : '

%s

'%(match.group(1),)), + (re.compile(r'<]*?id=subtitle[^><]*?>(.*?)', re.IGNORECASE|re.DOTALL), + lambda match : '

%s

'%(match.group(1),)), + # Blank lines + (re.compile(r'<]*?>( ){4}
', re.IGNORECASE), + lambda match : '

'), + ] + + def __hasattr__(self, attr): + if hasattr(self.options, attr): + return True + return object.__hasattr__(self, attr) + + def __getattr__(self, attr): + if hasattr(self.options, attr): + return getattr(self.options, attr) + return object.__getattribute__(self, attr) + + def __setattr__(self, attr, val): + if hasattr(self.options, attr): + setattr(self.options, attr, val) + else: + object.__setattr__(self, attr, val) + + CSS = { + 'h1' : {"font-size" : "xx-large", "font-weight":"bold", 'text-indent':'0pt'}, + 'h2' : {"font-size" : "x-large", "font-weight":"bold", 'text-indent':'0pt'}, + 'h3' : {"font-size" : "large", "font-weight":"bold", 'text-indent':'0pt'}, + 'h4' : {"font-size" : "large", 'text-indent':'0pt'}, + 'h5' : {"font-weight" : "bold", 'text-indent':'0pt'}, + 'b' : {"font-weight" : "bold"}, + 'strong' : {"font-weight" : "bold"}, + 'i' : {"font-style" : "italic"}, + 'cite' : {'font-style' : 'italic'}, + 'em' : {"font-style" : "italic"}, + 'small' : {'font-size' : 'small'}, + 'pre' : {'font-family' : 'monospace', 'white-space': 'pre'}, + 'code' : {'font-family' : 'monospace'}, + 'tt' : {'font-family' : 'monospace'}, + 'center' : {'text-align' : 'center'}, + 'th' : {'font-size' : 'large', 'font-weight':'bold'}, + 'big' : {'font-size' : 'large', 'font-weight':'bold'}, + '.libprs500_dropcaps' : {'font-size': 'xx-large'}, + 'u' : {'text-decoration': 'underline'}, + 'sup' : {'vertical-align': 'super', 'font-size': '60%'}, + 'sub' : {'vertical-align': 'sub', 'font-size': '60%'}, + } + + def __init__(self, book, fonts, options, logger, paths): + ''' + Convert HTML files at C{paths} and add to C{book}. After creating + the object, you must call L{self.writeto} to output the LRF/S file. + + @param book: The LRF book + @type book: L{lrf.pylrs.Book} + @param fonts: dict specifying the font families to use + ''' + # Defaults for various formatting tags + object.__setattr__(self, 'options', options) + self.log = logger + self.fonts = fonts # : dict specifying font families to use + # Memory + self.scaled_images = {} #: Temporary files with scaled version of images + self.rotated_images = {} #: Temporary files with rotated version of images + self.text_styles = [] #: Keep track of already used textstyles + self.block_styles = [] #: Keep track of already used blockstyles + self.images = {} #: Images referenced in the HTML document + self.targets = {} #: and id elements + self.links = deque() # : elements + self.processed_files = [] + self.extra_toc_entries = [] # : TOC entries gleaned from semantic information + self.image_memory = [] + self.id_counter = 0 + self.unused_target_blocks = [] # : Used to remove extra TextBlocks + self.link_level = 0 #: Current link level + self.memory = [] #: Used to ensure that duplicate CSS unhandled erros are not reported + self.tops = {} #: element representing the top of each HTML file in the LRF file + self.previous_text = '' # : Used to figure out when to lstrip + self.stripped_space = '' + self.preserve_block_style = False # : Used so that

tags in

elements are handled properly + self.avoid_page_break = False + self.current_page = book.create_page() + + # Styles + self.blockquote_style = book.create_block_style(sidemargin=60, + topskip=20, footskip=20) + self.unindented_style = book.create_text_style(parindent=0) + + self.in_table = False + # List processing + self.list_level = 0 + self.list_indent = 20 + self.list_counter = 1 + + self.book = book #: The Book object representing a BBeB book + + self.override_css = {} + self.override_pcss = {} + + if self._override_css is not None: + if os.access(self._override_css, os.R_OK): + with open(self._override_css, 'rb') as f: + src = f.read() + else: + src = self._override_css + if isinstance(src, bytes): + src = src.decode('utf-8', 'replace') + match = self.PAGE_BREAK_PAT.search(src) + if match and not re.match('avoid', match.group(1), re.IGNORECASE): + self.page_break_found = True + ncss, npcss = self.parse_css(src) + if ncss: + update_css(ncss, self.override_css) + if npcss: + update_css(npcss, self.override_pcss) + + paths = [os.path.abspath(path) for path in paths] + paths = [path.decode(sys.getfilesystemencoding()) if not isinstance(path, unicode_type) else path for path in paths] + + while len(paths) > 0 and self.link_level <= self.link_levels: + for path in paths: + if path in self.processed_files: + continue + try: + self.add_file(path) + except KeyboardInterrupt: + raise + except: + if self.link_level == 0: # Die on errors in the first level + raise + for link in self.links: + if link['path'] == path: + self.links.remove(link) + break + self.log.warn('Could not process '+path) + if self.verbose: + self.log.exception(' ') + self.links = self.process_links() + self.link_level += 1 + paths = [link['path'] for link in self.links] + + if self.current_page is not None and self.current_page.has_text(): + self.book.append(self.current_page) + + for text, tb in self.extra_toc_entries: + self.book.addTocEntry(text, tb) + + if self.base_font_size > 0: + self.log.info('\tRationalizing font sizes...') + self.book.rationalize_font_sizes(self.base_font_size) + + def is_baen(self, soup): + return bool(soup.find('meta', attrs={'name':'Publisher', + 'content':re.compile('Baen', re.IGNORECASE)})) + + def is_book_designer(self, raw): + return bool(re.search('<]*id=BookTitle', raw)) + + def preprocess(self, raw): + nmassage = [] + nmassage.extend(HTMLConverter.MARKUP_MASSAGE) + + if not self.book_designer and self.is_book_designer(raw): + self.book_designer = True + self.log.info(_('\tBook Designer file detected.')) + + self.log.info(_('\tParsing HTML...')) + + if self.baen: + nmassage.extend(HTMLConverter.BAEN) + + if self.pdftohtml: + nmassage.extend(HTMLConverter.PDFTOHTML) + if self.book_designer: + nmassage.extend(HTMLConverter.BOOK_DESIGNER) + if isinstance(raw, bytes): + raw = xml_to_unicode(raw, replace_entities=True)[0] + for pat, repl in nmassage: + raw = pat.sub(repl, raw) + soup = BeautifulSoup(raw) + if not self.baen and self.is_baen(soup): + self.baen = True + self.log.info(_('\tBaen file detected. Re-parsing...')) + return self.preprocess(raw) + if self.book_designer: + t = soup.find(id='BookTitle') + if t: + self.book.set_title(self.get_text(t)) + a = soup.find(id='BookAuthor') + if a: + self.book.set_author(self.get_text(a)) + if self.verbose: + tdir = tempfile.gettempdir() + if not os.path.exists(tdir): + os.makedirs(tdir) + try: + with open(os.path.join(tdir, 'html2lrf-verbose.html'), 'wb') as f: + f.write(unicode_type(soup).encode('utf-8')) + self.log.info(_('Written preprocessed HTML to ')+f.name) + except: + pass + + return soup + + def add_file(self, path): + self.css = HTMLConverter.CSS.copy() + self.pseudo_css = self.override_pcss.copy() + for selector in self.override_css: + if selector in self.css: + self.css[selector].update(self.override_css[selector]) + else: + self.css[selector] = self.override_css[selector] + + self.file_name = os.path.basename(path) + self.log.info(_('Processing %s')%(path if self.verbose else self.file_name)) + + if not os.path.exists(path): + path = path.replace('&', '%26') # convertlit replaces & with %26 in file names + with open(path, 'rb') as f: + raw = f.read() + if self.pdftohtml: # Bug in pdftohtml that causes it to output invalid UTF-8 files + raw = raw.decode('utf-8', 'ignore') + elif self.encoding is not None: + raw = raw.decode(self.encoding, 'ignore') + else: + raw = xml_to_unicode(raw, self.verbose)[0] + soup = self.preprocess(raw) + self.log.info(_('\tConverting to BBeB...')) + self.current_style = {} + self.page_break_found = False + if not isinstance(path, unicode_type): + path = path.decode(sys.getfilesystemencoding()) + self.target_prefix = path + self.previous_text = '\n' + self.tops[path] = self.parse_file(soup) + self.processed_files.append(path) + + def parse_css(self, style): + """ + Parse the contents of a \n' + format = 'inline' + dir = None + fname = None + else: + # css - assume as standalone css file + typ = 'css' + format = 'file' + dir = "styles" + fname = nstr + '.css' + + self.flows[j] = flowpart + self.flowinfo.append(FlowInfo(typ, format, dir, fname)) + + def get_file_info(self, pos): + ''' Get information about the part (file) that exists at pos in + the raw markup ''' + for part in self.partinfo: + if pos >= part.start and pos < part.end: + return part + return Part(*repeat(None, len(Part._fields))) + + def get_id_tag_by_pos_fid(self, posfid, offset): + # first convert kindle:pos:fid and offset info to position in file + insertpos, idtext, filenum, seqnm, startpos, length = self.elems[posfid] + pos = insertpos + offset + fi = self.get_file_info(pos) + # an existing "id=" must exist in original xhtml otherwise it would not + # have worked for linking. Amazon seems to have added its own + # additional "aid=" inside tags whose contents seem to represent some + # position information encoded into Base32 name. + + # so find the closest "id=" before position the file by actually + # searching in that file + idtext = self.get_id_tag(pos) + return '%s/%s'%(fi.type, fi.filename), idtext + + def get_id_tag(self, pos): + # Find the first tag with a named anchor (name or id attribute) before + # pos + fi = self.get_file_info(pos) + if fi.num is None and fi.start is None: + raise ValueError('No file contains pos: %d'%pos) + textblock = self.parts[fi.num] + npos = pos - fi.start + pgt = textblock.find(b'>', npos) + plt = textblock.find(b'<', npos) + # if npos inside a tag then search all text before the its end of tag marker + # else not in a tag need to search the preceding tag + if plt == npos or pgt < plt: + npos = pgt + 1 + textblock = textblock[0:npos] + for tag in reverse_tag_iter(textblock): + m = self.id_re.match(tag) or self.name_re.match(tag) + if m is not None: + return m.group(1) + # For some files, kindlegen apparently creates links to tags + # without HTML anchors, using the AID instead. See + # See https://www.mobileread.com/forums/showthread.php?t=259557 + m = self.aid_re.match(tag) + if m is not None: + self.linked_aids.add(m.group(1)) + return m.group(1) + b'-' + self.aid_anchor_suffix + + # No tag found, link to start of file + return b'' + + def create_guide(self): + guide = Guide() + has_start = False + for ref_type, ref_title, pos_fid in self.guide: + try: + if len(pos_fid) != 2: + continue + except TypeError: + continue # thumbnailstandard record, ignore it + linktgt, idtext = self.get_id_tag_by_pos_fid(*pos_fid) + if idtext: + if isinstance(idtext, bytes): + idtext = idtext.decode(self.header.codec) + linktgt += '#' + idtext + g = Guide.Reference(linktgt, getcwd()) + g.title, g.type = ref_title, ref_type + if g.title == 'start' or g.type == 'text': + has_start = True + guide.append(g) + + so = self.header.exth.start_offset + if so not in {None, NULL_INDEX} and not has_start: + fi = self.get_file_info(so) + if fi.filename is not None: + idtext = self.get_id_tag(so).decode(self.header.codec) + linktgt = fi.filename + if idtext: + linktgt += '#' + idtext + g = Guide.Reference('%s/%s'%(fi.type, linktgt), getcwd()) + g.title, g.type = 'start', 'text' + guide.append(g) + + return guide + + def create_ncx(self): + index_entries = read_ncx(self.kf8_sections, self.header.ncxidx, + self.header.codec) + remove = [] + + # Add href and anchor info to the index entries + for entry in index_entries: + pos_fid = entry['pos_fid'] + if pos_fid is None: + pos = entry['pos'] + fi = self.get_file_info(pos) + if fi.filename is None: + raise ValueError('Index entry has invalid pos: %d'%pos) + idtag = self.get_id_tag(pos) + href = '%s/%s'%(fi.type, fi.filename) + else: + try: + href, idtag = self.get_id_tag_by_pos_fid(*pos_fid) + except ValueError: + self.log.warn('Invalid entry in NCX (title: %s), ignoring' + %entry['text']) + remove.append(entry) + continue + + entry['href'] = href + entry['idtag'] = as_unicode(idtag, self.header.codec or 'utf-8') + + for e in remove: + index_entries.remove(e) + + # Build the TOC object + return build_toc(index_entries) + + def extract_resources(self, sections): + from calibre.ebooks.mobi.writer2.resources import PLACEHOLDER_GIF + resource_map = [] + container = None + for x in ('fonts', 'images'): + os.mkdir(x) + + for start, end in self.resource_offsets: + for i, sec in enumerate(sections[start:end]): + fname_idx = i+1 + data = sec[0] + typ = data[:4] + href = None + if typ in {b'FLIS', b'FCIS', b'SRCS', b'\xe9\x8e\r\n', b'BOUN', + b'FDST', b'DATP', b'AUDI', b'VIDE', b'RESC', b'CMET', b'PAGE'}: + pass # Ignore these records + elif typ == b'FONT': + font = read_font_record(data) + href = "fonts/%05d.%s" % (fname_idx, font['ext']) + if font['err']: + self.log.warn('Reading font record %d failed: %s'%( + fname_idx, font['err'])) + if font['headers']: + self.log.debug('Font record headers: %s'%font['headers']) + with open(href.replace('/', os.sep), 'wb') as f: + f.write(font['font_data'] if font['font_data'] else + font['raw_data']) + if font['encrypted']: + self.encrypted_fonts.append(href) + elif typ == b'CONT': + if data == b'CONTBOUNDARY': + container = None + continue + container = Container(data) + elif typ == b'CRES': + data, imgtype = container.load_image(data) + if data is not None: + href = 'images/%05d.%s'%(container.resource_index, imgtype) + with open(href.replace('/', os.sep), 'wb') as f: + f.write(data) + elif typ == b'\xa0\xa0\xa0\xa0' and len(data) == 4 and container is not None: + container.resource_index += 1 + elif container is None: + if not (len(data) == len(PLACEHOLDER_GIF) and data == PLACEHOLDER_GIF): + imgtype = find_imgtype(data) + href = 'images/%05d.%s'%(fname_idx, imgtype) + with open(href.replace('/', os.sep), 'wb') as f: + f.write(data) + + resource_map.append(href) + + return resource_map + + def expand_text(self, resource_map): + return expand_mobi8_markup(self, resource_map, self.log) + + def write_opf(self, guide, toc, spine, resource_map): + mi = self.header.exth.mi + if (self.cover_offset is not None and self.cover_offset < + len(resource_map)): + mi.cover = resource_map[self.cover_offset] + + if len(list(toc)) < 2: + self.log.warn('KF8 has no metadata Table of Contents') + + for ref in guide: + if ref.type == 'toc': + href = ref.href() + href, frag = urldefrag(href) + if os.path.exists(href.replace('/', os.sep)): + try: + toc = self.read_inline_toc(href, frag) + except: + self.log.exception('Failed to read inline ToC') + + opf = OPFCreator(getcwd(), mi) + opf.guide = guide + + def exclude(path): + return os.path.basename(path) == 'debug-raw.html' + + # If there are no images then the azw3 input plugin dumps all + # binary records as .unknown images, remove them + if self.for_tweak and os.path.exists('images') and os.path.isdir('images'): + files = os.listdir('images') + unknown = [x for x in files if x.endswith('.unknown')] + if len(files) == len(unknown): + [os.remove('images/'+f) for f in files] + + if self.for_tweak: + try: + os.remove('debug-raw.html') + except: + pass + + opf.create_manifest_from_files_in([getcwd()], exclude=exclude) + for entry in opf.manifest: + if entry.mime_type == 'text/html': + entry.mime_type = 'application/xhtml+xml' + opf.create_spine(spine) + opf.set_toc(toc) + ppd = getattr(self.header.exth, 'page_progression_direction', None) + if ppd in {'ltr', 'rtl', 'default'}: + opf.page_progression_direction = ppd + pwm = getattr(self.header.exth, 'primary_writing_mode', None) + if pwm is not None: + opf.primary_writing_mode = pwm + + with open('metadata.opf', 'wb') as of, open('toc.ncx', 'wb') as ncx: + opf.render(of, ncx, 'toc.ncx') + return 'metadata.opf' + + def read_inline_toc(self, href, frag): + ans = TOC() + base_href = '/'.join(href.split('/')[:-1]) + with open(href.replace('/', os.sep), 'rb') as f: + raw = f.read().decode(self.header.codec) + root = parse_html(raw, log=self.log) + body = XPath('//h:body')(root) + reached = False + if body: + start = body[0] + else: + start = None + reached = True + if frag: + elems = XPath('//*[@id="%s"]'%frag)(root) + if elems: + start = elems[0] + + def node_depth(elem): + ans = 0 + parent = elem.getparent() + while parent is not None: + parent = parent.getparent() + ans += 1 + return ans + + # Layer the ToC based on nesting order in the source HTML + current_depth = None + parent = ans + seen = set() + links = [] + for elem in root.iterdescendants(etree.Element): + if reached and elem.tag == XHTML('a') and elem.get('href', + False): + href = elem.get('href') + href, frag = urldefrag(href) + href = base_href + '/' + href + text = xml2text(elem).strip() + if (text, href, frag) in seen: + continue + seen.add((text, href, frag)) + links.append((text, href, frag, node_depth(elem))) + elif elem is start: + reached = True + + depths = sorted(set(x[-1] for x in links)) + depth_map = {x:i for i, x in enumerate(depths)} + for text, href, frag, depth in links: + depth = depth_map[depth] + if current_depth is None: + current_depth = 0 + parent.add_item(href, frag, text) + elif current_depth == depth: + parent.add_item(href, frag, text) + elif current_depth < depth: + parent = parent[-1] if len(parent) > 0 else parent + parent.add_item(href, frag, text) + current_depth += 1 + else: + delta = current_depth - depth + while delta > 0 and parent.parent is not None: + parent = parent.parent + delta -= 1 + parent.add_item(href, frag, text) + current_depth = depth + return ans diff --git a/ebook_converter/ebooks/mobi/reader/ncx.py b/ebook_converter/ebooks/mobi/reader/ncx.py new file mode 100644 index 0000000..6f49e1c --- /dev/null +++ b/ebook_converter/ebooks/mobi/reader/ncx.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2012, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +from calibre import replace_entities +from calibre.ebooks.metadata.toc import TOC +from calibre.ebooks.mobi.reader.headers import NULL_INDEX +from calibre.ebooks.mobi.reader.index import read_index +from polyglot.builtins import iteritems, getcwd + +tag_fieldname_map = { + 1: ['pos',0], + 2: ['len',0], + 3: ['noffs',0], + 4: ['hlvl',0], + 5: ['koffs',0], + 6: ['pos_fid',0], + 21: ['parent',0], + 22: ['child1',0], + 23: ['childn',0], + 69: ['image_index',0], + 70 : ['desc_offset', 0], # 'Description offset in cncx' + 71 : ['author_offset', 0], # 'Author offset in cncx' + 72 : ['image_caption_offset', 0], # 'Image caption offset in cncx', + 73 : ['image_attr_offset', 0], # 'Image attribution offset in cncx', + +} + +default_entry = { + 'pos': -1, + 'len': 0, + 'noffs': -1, + 'text' : "Unknown Text", + 'hlvl' : -1, + 'kind' : "Unknown Class", + 'pos_fid' : None, + 'parent' : -1, + 'child1' : -1, + 'childn' : -1, + 'description': None, + 'author': None, + 'image_caption': None, + 'image_attribution': None, +} + + +def read_ncx(sections, index, codec): + index_entries = [] + + if index != NULL_INDEX: + table, cncx = read_index(sections, index, codec) + + for num, x in enumerate(iteritems(table)): + text, tag_map = x + entry = default_entry.copy() + entry['name'] = text + entry['num'] = num + + for tag in tag_fieldname_map: + fieldname, i = tag_fieldname_map[tag] + if tag in tag_map: + fieldvalue = tag_map[tag][i] + if tag == 6: + # Appears to be an idx into the KF8 elems table with an + # offset + fieldvalue = tuple(tag_map[tag]) + entry[fieldname] = fieldvalue + for which, name in iteritems({3:'text', 5:'kind', 70:'description', + 71:'author', 72:'image_caption', + 73:'image_attribution'}): + if tag == which: + entry[name] = cncx.get(fieldvalue, + default_entry[name]) + index_entries.append(entry) + + return index_entries + + +def build_toc(index_entries): + ans = TOC(base_path=getcwd()) + levels = {x['hlvl'] for x in index_entries} + num_map = {-1: ans} + level_map = {l:[x for x in index_entries if x['hlvl'] == l] for l in + levels} + for lvl in sorted(levels): + for item in level_map[lvl]: + parent = num_map[item['parent']] + child = parent.add_item(item['href'], item['idtag'], + replace_entities(item['text'], encoding=None)) + num_map[item['num']] = child + + # Set play orders in depth first order + for i, item in enumerate(ans.flat()): + item.play_order = i + + return ans diff --git a/ebook_converter/ebooks/mobi/tweak.py b/ebook_converter/ebooks/mobi/tweak.py new file mode 100644 index 0000000..82ee5f5 --- /dev/null +++ b/ebook_converter/ebooks/mobi/tweak.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2012, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import os, glob + +from calibre import CurrentDir +from calibre.ebooks.mobi import MobiError +from calibre.ebooks.mobi.reader.mobi6 import MobiReader +from calibre.ebooks.mobi.reader.headers import MetadataHeader +from calibre.utils.logging import default_log +from calibre.ebooks import DRMError +from calibre.ebooks.mobi.reader.mobi8 import Mobi8Reader +from calibre.ebooks.conversion.plumber import Plumber, create_oebbook +from calibre.customize.ui import (plugin_for_input_format, + plugin_for_output_format) +from calibre.utils.ipc.simple_worker import fork_job + + +class BadFormat(ValueError): + pass + + +def do_explode(path, dest): + with open(path, 'rb') as stream: + mr = MobiReader(stream, default_log, None, None) + + with CurrentDir(dest): + mr = Mobi8Reader(mr, default_log) + opf = os.path.abspath(mr()) + try: + os.remove('debug-raw.html') + except: + pass + + return opf + + +def explode(path, dest, question=lambda x:True): + with open(path, 'rb') as stream: + raw = stream.read(3) + stream.seek(0) + if raw == b'TPZ': + raise BadFormat(_('This is not a MOBI file. It is a Topaz file.')) + + try: + header = MetadataHeader(stream, default_log) + except MobiError: + raise BadFormat(_('This is not a MOBI file.')) + + if header.encryption_type != 0: + raise DRMError(_('This file is locked with DRM. It cannot be tweaked.')) + + kf8_type = header.kf8_type + + if kf8_type is None: + raise BadFormat(_('This MOBI file does not contain a KF8 format ' + 'book. KF8 is the new format from Amazon. calibre can ' + 'only tweak MOBI files that contain KF8 books. Older ' + 'MOBI files without KF8 are not tweakable.')) + + if kf8_type == 'joint': + if not question(_('This MOBI file contains both KF8 and ' + 'older Mobi6 data. Tweaking it will remove the Mobi6 data, which ' + 'means the file will not be usable on older Kindles. Are you ' + 'sure?')): + return None + + return fork_job('calibre.ebooks.mobi.tweak', 'do_explode', args=(path, + dest), no_output=True)['result'] + + +def set_cover(oeb): + if 'cover' not in oeb.guide or oeb.metadata['cover']: + return + cover = oeb.guide['cover'] + if cover.href in oeb.manifest.hrefs: + item = oeb.manifest.hrefs[cover.href] + oeb.metadata.clear('cover') + oeb.metadata.add('cover', item.id) + + +def do_rebuild(opf, dest_path): + plumber = Plumber(opf, dest_path, default_log) + plumber.setup_options() + inp = plugin_for_input_format('azw3') + outp = plugin_for_output_format('azw3') + + plumber.opts.mobi_passthrough = True + oeb = create_oebbook(default_log, opf, plumber.opts) + set_cover(oeb) + outp.convert(oeb, dest_path, inp, plumber.opts, default_log) + + +def rebuild(src_dir, dest_path): + opf = glob.glob(os.path.join(src_dir, '*.opf')) + if not opf: + raise ValueError('No OPF file found in %s'%src_dir) + opf = opf[0] + # For debugging, uncomment the following two lines + # def fork_job(a, b, args=None, no_output=True): + # do_rebuild(*args) + fork_job('calibre.ebooks.mobi.tweak', 'do_rebuild', args=(opf, dest_path), + no_output=True) + diff --git a/ebook_converter/ebooks/mobi/utils.py b/ebook_converter/ebooks/mobi/utils.py new file mode 100644 index 0000000..0121777 --- /dev/null +++ b/ebook_converter/ebooks/mobi/utils.py @@ -0,0 +1,646 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2011, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import struct, string, zlib, os +from collections import OrderedDict +from io import BytesIO + +from calibre.utils.img import save_cover_data_to, scale_image, image_to_data, image_from_data, resize_image, png_data_to_gif_data +from calibre.utils.imghdr import what +from calibre.ebooks import normalize +from polyglot.builtins import unicode_type, range, as_bytes, map +from tinycss.color3 import parse_color_string + +IMAGE_MAX_SIZE = 10 * 1024 * 1024 +RECORD_SIZE = 0x1000 # 4096 (Text record size (uncompressed)) + + +class PolyglotDict(dict): + + def __setitem__(self, key, val): + if isinstance(key, unicode_type): + key = key.encode('utf-8') + dict.__setitem__(self, key, val) + + def __getitem__(self, key): + if isinstance(key, unicode_type): + key = key.encode('utf-8') + return dict.__getitem__(self, key) + + def __contains__(self, key): + if isinstance(key, unicode_type): + key = key.encode('utf-8') + return dict.__contains__(self, key) + + +def decode_string(raw, codec='utf-8', ordt_map=None): + length, = struct.unpack(b'>B', raw[0:1]) + raw = raw[1:1+length] + consumed = length+1 + if ordt_map: + return ''.join(ordt_map[x] for x in bytearray(raw)), consumed + return raw.decode(codec), consumed + + +def decode_hex_number(raw, codec='utf-8'): + ''' + Return a variable length number encoded using hexadecimal encoding. These + numbers have the first byte which tells the number of bytes that follow. + The bytes that follow are simply the hexadecimal representation of the + number. + + :param raw: Raw binary data as a bytestring + + :return: The number and the number of bytes from raw that the number + occupies. + ''' + raw, consumed = decode_string(raw, codec=codec) + return int(raw, 16), consumed + + +def encode_string(raw): + ans = bytearray(as_bytes(raw)) + ans.insert(0, len(ans)) + return bytes(ans) + + +def encode_number_as_hex(num): + ''' + Encode num as a variable length encoded hexadecimal number. Returns the + bytestring containing the encoded number. These + numbers have the first byte which tells the number of bytes that follow. + The bytes that follow are simply the hexadecimal representation of the + number. + ''' + num = hex(num)[2:].upper().encode('ascii') + nlen = len(num) + if nlen % 2 != 0: + num = b'0'+num + return encode_string(num) + + +def encint(value, forward=True): + ''' + Some parts of the Mobipocket format encode data as variable-width integers. + These integers are represented big-endian with 7 bits per byte in bits 1-7. + They may be either forward-encoded, in which case only the first byte has bit 8 set, + or backward-encoded, in which case only the last byte has bit 8 set. + For example, the number 0x11111 = 0b10001000100010001 would be represented + forward-encoded as: + + 0x04 0x22 0x91 = 0b100 0b100010 0b10010001 + + And backward-encoded as: + + 0x84 0x22 0x11 = 0b10000100 0b100010 0b10001 + + This function encodes the integer ``value`` as a variable width integer and + returns the bytestring corresponding to it. + + If forward is True the bytes returned are suitable for prepending to the + output buffer, otherwise they must be append to the output buffer. + ''' + if value < 0: + raise ValueError('Cannot encode negative numbers as vwi') + # Encode vwi + byts = bytearray() + while True: + b = value & 0b01111111 + value >>= 7 # shift value to the right by 7 bits + + byts.append(b) + if value == 0: + break + byts[0 if forward else -1] |= 0b10000000 + byts.reverse() + return bytes(byts) + + +def decint(raw, forward=True): + ''' + Read a variable width integer from the bytestring or bytearray raw and return the + integer and the number of bytes read. If forward is True bytes are read + from the start of raw, otherwise from the end of raw. + + This function is the inverse of encint above, see its docs for more + details. + ''' + val = 0 + byts = bytearray() + src = bytearray(raw) + if not forward: + src.reverse() + for bnum in src: + byts.append(bnum & 0b01111111) + if bnum & 0b10000000: + break + if not forward: + byts.reverse() + for byte in byts: + val <<= 7 # Shift value to the left by 7 bits + val |= byte + + return val, len(byts) + + +def test_decint(num): + for d in (True, False): + raw = encint(num, forward=d) + sz = len(raw) + if (num, sz) != decint(raw, forward=d): + raise ValueError('Failed for num %d, forward=%r: %r != %r' % ( + num, d, (num, sz), decint(raw, forward=d))) + + +def rescale_image(data, maxsizeb=IMAGE_MAX_SIZE, dimen=None): + ''' + Convert image setting all transparent pixels to white and changing format + to JPEG. Ensure the resultant image has a byte size less than + maxsizeb. + + If dimen is not None, generate a thumbnail of + width=dimen, height=dimen or width, height = dimen (depending on the type + of dimen) + + Returns the image as a bytestring + ''' + if dimen is not None: + if hasattr(dimen, '__len__'): + width, height = dimen + else: + width = height = dimen + data = scale_image(data, width=width, height=height, compression_quality=90)[-1] + else: + # Replace transparent pixels with white pixels and convert to JPEG + data = save_cover_data_to(data) + if len(data) <= maxsizeb: + return data + orig_data = data # save it in case compression fails + quality = 90 + while len(data) > maxsizeb and quality >= 5: + data = image_to_data(image_from_data(orig_data), compression_quality=quality) + quality -= 5 + if len(data) <= maxsizeb: + return data + orig_data = data + + scale = 0.9 + while len(data) > maxsizeb and scale >= 0.05: + img = image_from_data(data) + w, h = img.width(), img.height() + img = resize_image(img, int(scale*w), int(scale*h)) + data = image_to_data(img, compression_quality=quality) + scale -= 0.05 + return data + + +def get_trailing_data(record, extra_data_flags): + ''' + Given a text record as a bytestring and the extra data flags from the MOBI + header, return the trailing data as a dictionary, mapping bit number to + data as bytestring. Also returns the record - all trailing data. + + :return: Trailing data, record - trailing data + ''' + data = OrderedDict() + flags = extra_data_flags >> 1 + + num = 0 + while flags: + num += 1 + if flags & 0b1: + sz, consumed = decint(record, forward=False) + if sz > consumed: + data[num] = record[-sz:-consumed] + record = record[:-sz] + flags >>= 1 + # Read multibyte chars if any + if extra_data_flags & 0b1: + # Only the first two bits are used for the size since there can + # never be more than 3 trailing multibyte chars + sz = (ord(record[-1:]) & 0b11) + 1 + consumed = 1 + if sz > consumed: + data[0] = record[-sz:-consumed] + record = record[:-sz] + return data, record + + +def encode_trailing_data(raw): + ''' + Given some data in the bytestring raw, return a bytestring of the form + + + + where size is a backwards encoded vwi whose value is the length of the + entire returned bytestring. data is the bytestring passed in as raw. + + This is the encoding used for trailing data entries at the end of text + records. See get_trailing_data() for details. + ''' + lsize = 1 + while True: + encoded = encint(len(raw) + lsize, forward=False) + if len(encoded) == lsize: + break + lsize += 1 + return raw + encoded + + +def encode_fvwi(val, flags, flag_size=4): + ''' + Encode the value val and the flag_size bits from flags as a fvwi. This encoding is + used in the trailing byte sequences for indexing. Returns encoded + bytestring. + ''' + ans = val << flag_size + for i in range(flag_size): + ans |= (flags & (1 << i)) + return encint(ans) + + +def decode_fvwi(byts, flag_size=4): + ''' + Decode encoded fvwi. Returns number, flags, consumed + ''' + arg, consumed = decint(bytes(byts)) + val = arg >> flag_size + flags = 0 + for i in range(flag_size): + flags |= (arg & (1 << i)) + return val, flags, consumed + + +def decode_tbs(byts, flag_size=4): + ''' + Trailing byte sequences for indexing consists of series of fvwi numbers. + This function reads the fvwi number and its associated flags. It then uses + the flags to read any more numbers that belong to the series. The flags are + the lowest 4 bits of the vwi (see the encode_fvwi function above). + + Returns the fvwi number, a dictionary mapping flags bits to the associated + data and the number of bytes consumed. + ''' + byts = bytes(byts) + val, flags, consumed = decode_fvwi(byts, flag_size=flag_size) + extra = {} + byts = byts[consumed:] + if flags & 0b1000 and flag_size > 3: + extra[0b1000] = True + if flags & 0b0010: + x, consumed2 = decint(byts) + byts = byts[consumed2:] + extra[0b0010] = x + consumed += consumed2 + if flags & 0b0100: + extra[0b0100] = ord(byts[0:1]) + byts = byts[1:] + consumed += 1 + if flags & 0b0001: + x, consumed2 = decint(byts) + byts = byts[consumed2:] + extra[0b0001] = x + consumed += consumed2 + return val, extra, consumed + + +def encode_tbs(val, extra, flag_size=4): + ''' + Encode the number val and the extra data in the extra dict as an fvwi. See + decode_tbs above. + ''' + flags = 0 + for flag in extra: + flags |= flag + ans = encode_fvwi(val, flags, flag_size=flag_size) + + if 0b0010 in extra: + ans += encint(extra[0b0010]) + if 0b0100 in extra: + ans += bytes(bytearray([extra[0b0100]])) + if 0b0001 in extra: + ans += encint(extra[0b0001]) + return ans + + +def utf8_text(text): + ''' + Convert a possibly null string to utf-8 bytes, guaranteeing to return a non + empty, normalized bytestring. + ''' + if text and text.strip(): + text = text.strip() + if not isinstance(text, unicode_type): + text = text.decode('utf-8', 'replace') + text = normalize(text).encode('utf-8') + else: + text = _('Unknown').encode('utf-8') + return text + + +def align_block(raw, multiple=4, pad=b'\0'): + ''' + Return raw with enough pad bytes append to ensure its length is a multiple + of 4. + ''' + extra = len(raw) % multiple + if extra == 0: + return raw + return raw + pad*(multiple - extra) + + +def detect_periodical(toc, log=None): + ''' + Detect if the TOC object toc contains a periodical that conforms to the + structure required by kindlegen to generate a periodical. + ''' + if toc.count() < 1 or not toc[0].klass == 'periodical': + return False + for node in toc.iterdescendants(): + if node.depth() == 1 and node.klass != 'article': + if log is not None: + log.debug( + 'Not a periodical: Deepest node does not have ' + 'class="article"') + return False + if node.depth() == 2 and node.klass != 'section': + if log is not None: + log.debug( + 'Not a periodical: Second deepest node does not have' + ' class="section"') + return False + if node.depth() == 3 and node.klass != 'periodical': + if log is not None: + log.debug('Not a periodical: Third deepest node' + ' does not have class="periodical"') + return False + if node.depth() > 3: + if log is not None: + log.debug('Not a periodical: Has nodes of depth > 3') + return False + return True + + +def count_set_bits(num): + if num < 0: + num = -num + ans = 0 + while num > 0: + ans += (num & 0b1) + num >>= 1 + return ans + + +def to_base(num, base=32, min_num_digits=None): + digits = string.digits + string.ascii_uppercase + sign = 1 if num >= 0 else -1 + if num == 0: + return ('0' if min_num_digits is None else '0'*min_num_digits) + num *= sign + ans = [] + while num: + ans.append(digits[(num % base)]) + num //= base + if min_num_digits is not None and len(ans) < min_num_digits: + ans.extend('0'*(min_num_digits - len(ans))) + if sign < 0: + ans.append('-') + ans.reverse() + return ''.join(ans) + + +def mobify_image(data): + 'Convert PNG images to GIF as the idiotic Kindle cannot display some PNG' + fmt = what(None, data) + if fmt == 'png': + data = png_data_to_gif_data(data) + return data + +# Font records {{{ + + +def read_font_record(data, extent=1040): + ''' + Return the font encoded in the MOBI FONT record represented by data. + The return value in a dict with fields raw_data, font_data, err, ext, + headers. + + :param extent: The number of obfuscated bytes. So far I have only + encountered files with 1040 obfuscated bytes. If you encounter an + obfuscated record for which this function fails, try different extent + values (easily automated). + + raw_data is the raw data in the font record + font_data is the decoded font_data or None if an error occurred + err is not None if some error occurred + ext is the font type (ttf for TrueType, dat for unknown and failed if an + error occurred) + headers is the list of decoded headers from the font record or None if + decoding failed + ''' + # Format: + # bytes 0 - 3: 'FONT' + # bytes 4 - 7: Uncompressed size + # bytes 8 - 11: flags + # bit 1 - zlib compression + # bit 2 - XOR obfuscated + # bytes 12 - 15: offset to start of compressed data + # bytes 16 - 19: length of XOR string + # bytes 19 - 23: offset to start of XOR data + # The zlib compressed data begins with 2 bytes of header and + # has 4 bytes of checksum at the end + ans = {'raw_data':data, 'font_data':None, 'err':None, 'ext':'failed', + 'headers':None, 'encrypted':False} + + try: + usize, flags, dstart, xor_len, xor_start = struct.unpack_from( + b'>LLLLL', data, 4) + except: + ans['err'] = 'Failed to read font record header fields' + return ans + font_data = data[dstart:] + ans['headers'] = {'usize':usize, 'flags':bin(flags), 'xor_len':xor_len, + 'xor_start':xor_start, 'dstart':dstart} + + if flags & 0b10: + # De-obfuscate the data + key = bytearray(data[xor_start:xor_start+xor_len]) + buf = bytearray(font_data) + extent = len(font_data) if extent is None else extent + extent = min(extent, len(font_data)) + + for n in range(extent): + buf[n] ^= key[n%xor_len] # XOR of buf and key + + font_data = bytes(buf) + ans['encrypted'] = True + + if flags & 0b1: + # ZLIB compressed data + try: + font_data = zlib.decompress(font_data) + except Exception as e: + ans['err'] = 'Failed to zlib decompress font data (%s)'%e + return ans + + if len(font_data) != usize: + ans['err'] = 'Uncompressed font size mismatch' + return ans + + ans['font_data'] = font_data + sig = font_data[:4] + ans['ext'] = ('ttf' if sig in {b'\0\1\0\0', b'true', b'ttcf'} + else 'otf' if sig == b'OTTO' else 'dat') + + return ans + + +def write_font_record(data, obfuscate=True, compress=True): + ''' + Write the ttf/otf font represented by data into a font record. See + read_font_record() for details on the format of the record. + ''' + + flags = 0 + key_len = 20 + usize = len(data) + xor_key = b'' + if compress: + flags |= 0b1 + data = zlib.compress(data, 9) + if obfuscate and len(data) >= 1040: + flags |= 0b10 + xor_key = os.urandom(key_len) + key = bytearray(xor_key) + data = bytearray(data) + for i in range(1040): + data[i] ^= key[i%key_len] + data = bytes(data) + + key_start = struct.calcsize(b'>5L') + 4 + data_start = key_start + len(xor_key) + + header = b'FONT' + struct.pack(b'>5L', usize, flags, data_start, + len(xor_key), key_start) + + return header + xor_key + data + +# }}} + + +def create_text_record(text): + ''' + Return a Palmdoc record of size RECORD_SIZE from the text file object. + In case the record ends in the middle of a multibyte character return + the overlap as well. + + Returns data, overlap: where both are byte strings. overlap is the + extra bytes needed to complete the truncated multibyte character. + ''' + opos = text.tell() + text.seek(0, 2) + # npos is the position of the next record + npos = min((opos + RECORD_SIZE, text.tell())) + # Number of bytes from the next record needed to complete the last + # character in this record + extra = 0 + + last = b'' + while not last.decode('utf-8', 'ignore'): + # last contains no valid utf-8 characters + size = len(last) + 1 + text.seek(npos - size) + last = text.read(size) + + # last now has one valid utf-8 char and possibly some bytes that belong + # to a truncated char + + try: + last.decode('utf-8', 'strict') + except UnicodeDecodeError: + # There are some truncated bytes in last + prev = len(last) + while True: + text.seek(npos - prev) + last = text.read(len(last) + 1) + try: + last.decode('utf-8') + except UnicodeDecodeError: + pass + else: + break + extra = len(last) - prev + + text.seek(opos) + data = text.read(RECORD_SIZE) + overlap = text.read(extra) + text.seek(npos) + + return data, overlap + + +class CNCX(object): # {{{ + + ''' + Create the CNCX records. These are records containing all the strings from + an index. Each record is of the form: + ''' + + MAX_STRING_LENGTH = 500 + + def __init__(self, strings=()): + self.strings = OrderedDict((s, 0) for s in strings) + + self.records = [] + offset = 0 + buf = BytesIO() + RECORD_LIMIT = 0x10000 - 1024 # kindlegen appears to use 1024, PDB limit is 0x10000 + for key in self.strings: + utf8 = utf8_text(key[:self.MAX_STRING_LENGTH]) + l = len(utf8) + sz_bytes = encint(l) + raw = sz_bytes + utf8 + if buf.tell() + len(raw) > RECORD_LIMIT: + self.records.append(align_block(buf.getvalue())) + buf.seek(0), buf.truncate(0) + offset = len(self.records) * 0x10000 + buf.write(raw) + self.strings[key] = offset + offset += len(raw) + + val = buf.getvalue() + if val: + self.records.append(align_block(val)) + + def __getitem__(self, string): + return self.strings[string] + + def __bool__(self): + return bool(self.records) + __nonzero__ = __bool__ + + def __len__(self): + return len(self.records) + +# }}} + + +def is_guide_ref_start(ref): + return (ref.title.lower() == 'start' or + (ref.type and ref.type.lower() in {'start', + 'other.start', 'text'})) + + +def convert_color_for_font_tag(val): + rgba = parse_color_string(unicode_type(val or '')) + if rgba is None or rgba == 'currentColor': + return val + clamp = lambda x: min(x, max(0, x), 1) + rgb = map(clamp, rgba[:3]) + return '#' + ''.join(map(lambda x:'%02x' % int(x * 255), rgb)) diff --git a/ebook_converter/ebooks/mobi/writer2/__init__.py b/ebook_converter/ebooks/mobi/writer2/__init__.py new file mode 100644 index 0000000..3a2b08b --- /dev/null +++ b/ebook_converter/ebooks/mobi/writer2/__init__.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2011, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + + +UNCOMPRESSED = 1 +PALMDOC = 2 +HUFFDIC = 17480 +PALM_MAX_IMAGE_SIZE = 63 * 1024 + diff --git a/ebook_converter/ebooks/mobi/writer2/resources.py b/ebook_converter/ebooks/mobi/writer2/resources.py new file mode 100644 index 0000000..7db0fe3 --- /dev/null +++ b/ebook_converter/ebooks/mobi/writer2/resources.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2012, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import os + +from calibre.ebooks.mobi import MAX_THUMB_DIMEN, MAX_THUMB_SIZE +from calibre.ebooks.mobi.utils import (rescale_image, mobify_image, + write_font_record) +from calibre.ebooks import generate_masthead +from calibre.ebooks.oeb.base import OEB_RASTER_IMAGES +from calibre.ptempfile import PersistentTemporaryFile +from calibre.utils.imghdr import what +from polyglot.builtins import iteritems, unicode_type + +PLACEHOLDER_GIF = b'GIF89a\x01\x00\x01\x00\xf0\x00\x00\x00\x00\x00\xff\xff\xff!\xf9\x04\x01\x00\x00\x00\x00!\xfe calibre-placeholder-gif-for-azw3\x00,\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02D\x01\x00;' # noqa + + +class Resources(object): + + def __init__(self, oeb, opts, is_periodical, add_fonts=False, + process_images=True): + self.oeb, self.log, self.opts = oeb, oeb.log, opts + self.is_periodical = is_periodical + self.process_images = process_images + + self.item_map = {} + self.records = [] + self.mime_map = {} + self.masthead_offset = 0 + self.used_image_indices = set() + self.image_indices = set() + self.cover_offset = self.thumbnail_offset = None + self.has_fonts = False + + self.add_resources(add_fonts) + + def process_image(self, data): + if not self.process_images: + return data + func = mobify_image if self.opts.mobi_keep_original_images else rescale_image + try: + return func(data) + except Exception: + if 'png' != what(None, data): + raise + with PersistentTemporaryFile(suffix='.png') as pt: + pt.write(data) + try: + from calibre.utils.img import optimize_png + optimize_png(pt.name) + data = lopen(pt.name, 'rb').read() + finally: + os.remove(pt.name) + return func(data) + + def add_resources(self, add_fonts): + oeb = self.oeb + oeb.logger.info('Serializing resources...') + index = 1 + + mh_href = None + if 'masthead' in oeb.guide and oeb.guide['masthead'].href: + mh_href = oeb.guide['masthead'].href + self.records.append(None) + index += 1 + self.used_image_indices.add(0) + self.image_indices.add(0) + elif self.is_periodical: + # Generate a default masthead + data = generate_masthead(unicode_type(self.oeb.metadata['title'][0])) + self.records.append(data) + self.used_image_indices.add(0) + self.image_indices.add(0) + index += 1 + + cover_href = self.cover_offset = self.thumbnail_offset = None + if (oeb.metadata.cover and + unicode_type(oeb.metadata.cover[0]) in oeb.manifest.ids): + cover_id = unicode_type(oeb.metadata.cover[0]) + item = oeb.manifest.ids[cover_id] + cover_href = item.href + + for item in self.oeb.manifest.values(): + if item.media_type not in OEB_RASTER_IMAGES: + continue + try: + data = self.process_image(item.data) + except: + self.log.warn('Bad image file %r' % item.href) + continue + else: + if mh_href and item.href == mh_href: + self.records[0] = data + continue + + self.image_indices.add(len(self.records)) + self.records.append(data) + self.item_map[item.href] = index + self.mime_map[item.href] = 'image/%s'%what(None, data) + index += 1 + + if cover_href and item.href == cover_href: + self.cover_offset = self.item_map[item.href] - 1 + self.used_image_indices.add(self.cover_offset) + try: + data = rescale_image(item.data, dimen=MAX_THUMB_DIMEN, + maxsizeb=MAX_THUMB_SIZE) + except: + self.log.warn('Failed to generate thumbnail') + else: + self.image_indices.add(len(self.records)) + self.records.append(data) + self.thumbnail_offset = index - 1 + self.used_image_indices.add(self.thumbnail_offset) + index += 1 + finally: + item.unload_data_from_memory() + + if add_fonts: + for item in self.oeb.manifest.values(): + if item.href and item.href.rpartition('.')[-1].lower() in { + 'ttf', 'otf'} and isinstance(item.data, bytes): + self.records.append(write_font_record(item.data)) + self.item_map[item.href] = len(self.records) + self.has_fonts = True + + def add_extra_images(self): + ''' + Add any images that were created after the call to add_resources() + ''' + for item in self.oeb.manifest.values(): + if (item.media_type not in OEB_RASTER_IMAGES or item.href in self.item_map): + continue + try: + data = self.process_image(item.data) + except: + self.log.warn('Bad image file %r' % item.href) + else: + self.records.append(data) + self.item_map[item.href] = len(self.records) + finally: + item.unload_data_from_memory() + + def serialize(self, records, used_images): + used_image_indices = self.used_image_indices | { + v-1 for k, v in iteritems(self.item_map) if k in used_images} + for i in self.image_indices-used_image_indices: + self.records[i] = PLACEHOLDER_GIF + records.extend(self.records) + + def __bool__(self): + return bool(self.records) + __nonzero__ = __bool__ diff --git a/ebook_converter/ebooks/odt/__init__.py b/ebook_converter/ebooks/odt/__init__.py new file mode 100644 index 0000000..8a2513c --- /dev/null +++ b/ebook_converter/ebooks/odt/__init__.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python2 +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net' +__docformat__ = 'restructuredtext en' + +''' +Handle the Open Document Format +''' diff --git a/ebook_converter/ebooks/odt/input.py b/ebook_converter/ebooks/odt/input.py new file mode 100644 index 0000000..00121cf --- /dev/null +++ b/ebook_converter/ebooks/odt/input.py @@ -0,0 +1,305 @@ +from __future__ import print_function, unicode_literals, absolute_import, division +__license__ = 'GPL v3' +__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net' +__docformat__ = 'restructuredtext en' + +''' +Convert an ODT file into a Open Ebook +''' +import os, logging + +from lxml import etree +from css_parser import CSSParser +from css_parser.css import CSSRule + +from odf.odf2xhtml import ODF2XHTML +from odf.opendocument import load as odLoad +from odf.draw import Frame as odFrame, Image as odImage +from odf.namespaces import TEXTNS as odTEXTNS + +from calibre import CurrentDir, walk +from calibre.ebooks.oeb.base import _css_logger +from calibre.utils.xml_parse import safe_xml_fromstring +from polyglot.builtins import unicode_type, string_or_bytes, filter, getcwd, as_bytes + + +class Extract(ODF2XHTML): + + def extract_pictures(self, zf): + if not os.path.exists('Pictures'): + os.makedirs('Pictures') + for name in zf.namelist(): + if name.startswith('Pictures') and name not in {'Pictures', 'Pictures/'}: + data = zf.read(name) + with open(name, 'wb') as f: + f.write(data) + + def apply_list_starts(self, root, log): + if not self.list_starts: + return + list_starts = frozenset(self.list_starts) + for ol in root.xpath('//*[local-name() = "ol" and @class]'): + classes = {'.' + x for x in ol.get('class', '').split()} + found = classes & list_starts + if found: + val = self.list_starts[next(iter(found))] + ol.set('start', val) + + def fix_markup(self, html, log): + root = safe_xml_fromstring(html) + self.filter_css(root, log) + self.extract_css(root, log) + self.epubify_markup(root, log) + self.apply_list_starts(root, log) + html = etree.tostring(root, encoding='utf-8', + xml_declaration=True) + return html + + def extract_css(self, root, log): + ans = [] + for s in root.xpath('//*[local-name() = "style" and @type="text/css"]'): + ans.append(s.text) + s.getparent().remove(s) + + head = root.xpath('//*[local-name() = "head"]') + if head: + head = head[0] + ns = head.nsmap.get(None, '') + if ns: + ns = '{%s}'%ns + etree.SubElement(head, ns+'link', {'type':'text/css', + 'rel':'stylesheet', 'href':'odfpy.css'}) + + css = u'\n\n'.join(ans) + parser = CSSParser(loglevel=logging.WARNING, + log=_css_logger) + self.css = parser.parseString(css, validate=False) + + with open('odfpy.css', 'wb') as f: + f.write(css.encode('utf-8')) + + def get_css_for_class(self, cls): + if not cls: + return None + for rule in self.css.cssRules.rulesOfType(CSSRule.STYLE_RULE): + for sel in rule.selectorList: + q = sel.selectorText + if q == '.' + cls: + return rule + + def epubify_markup(self, root, log): + from calibre.ebooks.oeb.base import XPath, XHTML + # Fix empty title tags + for t in XPath('//h:title')(root): + if not t.text: + t.text = u' ' + # Fix

constructs as the asinine epubchecker complains + # about them + pdiv = XPath('//h:p/h:div') + for div in pdiv(root): + div.getparent().tag = XHTML('div') + + # Remove the position:relative as it causes problems with some epub + # renderers. Remove display: block on an image inside a div as it is + # redundant and prevents text-align:center from working in ADE + # Also ensure that the img is contained in its containing div + imgpath = XPath('//h:div/h:img[@style]') + for img in imgpath(root): + div = img.getparent() + if len(div) == 1: + style = div.attrib.get('style', '') + if style and not style.endswith(';'): + style = style + ';' + style += 'position:static' # Ensures position of containing div is static + # Ensure that the img is always contained in its frame + div.attrib['style'] = style + img.attrib['style'] = 'max-width: 100%; max-height: 100%' + + # Handle anchored images. The default markup + CSS produced by + # odf2xhtml works with WebKit but not with ADE. So we convert the + # common cases of left/right/center aligned block images to work on + # both webkit and ADE. We detect the case of setting the side margins + # to auto and map it to an appropriate text-align directive, which + # works in both WebKit and ADE. + # https://bugs.launchpad.net/bugs/1063207 + # https://bugs.launchpad.net/calibre/+bug/859343 + imgpath = XPath('descendant::h:div/h:div/h:img') + for img in imgpath(root): + div2 = img.getparent() + div1 = div2.getparent() + if (len(div1), len(div2)) != (1, 1): + continue + cls = div1.get('class', '') + first_rules = list(filter(None, [self.get_css_for_class(x) for x in + cls.split()])) + has_align = False + for r in first_rules: + if r.style.getProperty(u'text-align') is not None: + has_align = True + ml = mr = None + if not has_align: + aval = None + cls = div2.get(u'class', u'') + rules = list(filter(None, [self.get_css_for_class(x) for x in + cls.split()])) + for r in rules: + ml = r.style.getPropertyCSSValue(u'margin-left') or ml + mr = r.style.getPropertyCSSValue(u'margin-right') or mr + ml = getattr(ml, 'value', None) + mr = getattr(mr, 'value', None) + if ml == mr == u'auto': + aval = u'center' + elif ml == u'auto' and mr != u'auto': + aval = 'right' + elif ml != u'auto' and mr == u'auto': + aval = 'left' + if aval is not None: + style = div1.attrib.get('style', '').strip() + if style and not style.endswith(';'): + style = style + ';' + style += 'text-align:%s'%aval + has_align = True + div1.attrib['style'] = style + + if has_align: + # This is needed for ADE, without it the text-align has no + # effect + style = div2.attrib['style'] + div2.attrib['style'] = 'display:inline;'+style + + def filter_css(self, root, log): + style = root.xpath('//*[local-name() = "style" and @type="text/css"]') + if style: + style = style[0] + css = style.text + if css: + css, sel_map = self.do_filter_css(css) + if not isinstance(css, unicode_type): + css = css.decode('utf-8', 'ignore') + style.text = css + for x in root.xpath('//*[@class]'): + extra = [] + orig = x.get('class') + for cls in orig.split(): + extra.extend(sel_map.get(cls, [])) + if extra: + x.set('class', orig + ' ' + ' '.join(extra)) + + def do_filter_css(self, css): + from css_parser import parseString + from css_parser.css import CSSRule + sheet = parseString(css, validate=False) + rules = list(sheet.cssRules.rulesOfType(CSSRule.STYLE_RULE)) + sel_map = {} + count = 0 + for r in rules: + # Check if we have only class selectors for this rule + nc = [x for x in r.selectorList if not + x.selectorText.startswith('.')] + if len(r.selectorList) > 1 and not nc: + # Replace all the class selectors with a single class selector + # This will be added to the class attribute of all elements + # that have one of these selectors. + replace_name = 'c_odt%d'%count + count += 1 + for sel in r.selectorList: + s = sel.selectorText[1:] + if s not in sel_map: + sel_map[s] = [] + sel_map[s].append(replace_name) + r.selectorText = '.'+replace_name + return sheet.cssText, sel_map + + def search_page_img(self, mi, log): + for frm in self.document.topnode.getElementsByType(odFrame): + try: + if frm.getAttrNS(odTEXTNS,u'anchor-type') == 'page': + log.warn('Document has Pictures anchored to Page, will all end up before first page!') + break + except ValueError: + pass + + def filter_cover(self, mi, log): + # filter the Element tree (remove the detected cover) + if mi.cover and mi.odf_cover_frame: + for frm in self.document.topnode.getElementsByType(odFrame): + # search the right frame + if frm.getAttribute('name') == mi.odf_cover_frame: + img = frm.getElementsByType(odImage) + # only one draw:image allowed in the draw:frame + if len(img) == 1 and img[0].getAttribute('href') == mi.cover: + # ok, this is the right frame with the right image + # check if there are more childs + if len(frm.childNodes) != 1: + break + # check if the parent paragraph more childs + para = frm.parentNode + if para.tagName != 'text:p' or len(para.childNodes) != 1: + break + # now it should be safe to remove the text:p + parent = para.parentNode + parent.removeChild(para) + log("Removed cover image paragraph from document...") + break + + def filter_load(self, odffile, mi, log): + """ This is an adaption from ODF2XHTML. It adds a step between + load and parse of the document where the Element tree can be + modified. + """ + # first load the odf structure + self.lines = [] + self._wfunc = self._wlines + if isinstance(odffile, string_or_bytes) \ + or hasattr(odffile, 'read'): # Added by Kovid + self.document = odLoad(odffile) + else: + self.document = odffile + # filter stuff + self.search_page_img(mi, log) + try: + self.filter_cover(mi, log) + except: + pass + # parse the modified tree and generate xhtml + self._walknode(self.document.topnode) + + def __call__(self, stream, odir, log): + from calibre.utils.zipfile import ZipFile + from calibre.ebooks.metadata.odt import get_metadata + from calibre.ebooks.metadata.opf2 import OPFCreator + + if not os.path.exists(odir): + os.makedirs(odir) + with CurrentDir(odir): + log('Extracting ODT file...') + stream.seek(0) + mi = get_metadata(stream, 'odt') + if not mi.title: + mi.title = _('Unknown') + if not mi.authors: + mi.authors = [_('Unknown')] + self.filter_load(stream, mi, log) + html = self.xhtml() + # A blanket img specification like this causes problems + # with EPUB output as the containing element often has + # an absolute height and width set that is larger than + # the available screen real estate + html = html.replace('img { width: 100%; height: 100%; }', '') + # odf2xhtml creates empty title tag + html = html.replace('','%s'%(mi.title,)) + try: + html = self.fix_markup(html, log) + except: + log.exception('Failed to filter CSS, conversion may be slow') + with open('index.xhtml', 'wb') as f: + f.write(as_bytes(html)) + zf = ZipFile(stream, 'r') + self.extract_pictures(zf) + opf = OPFCreator(os.path.abspath(getcwd()), mi) + opf.create_manifest([(os.path.abspath(f2), None) for f2 in + walk(getcwd())]) + opf.create_spine([os.path.abspath('index.xhtml')]) + with open('metadata.opf', 'wb') as f: + opf.render(f) + return os.path.abspath('metadata.opf') diff --git a/ebook_converter/ebooks/oeb/__init__.py b/ebook_converter/ebooks/oeb/__init__.py new file mode 100644 index 0000000..57af319 --- /dev/null +++ b/ebook_converter/ebooks/oeb/__init__.py @@ -0,0 +1,4 @@ +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2008, Marshall T. Vandegrift ' diff --git a/ebook_converter/ebooks/oeb/base.py b/ebook_converter/ebooks/oeb/base.py new file mode 100644 index 0000000..e415d0a --- /dev/null +++ b/ebook_converter/ebooks/oeb/base.py @@ -0,0 +1,2023 @@ +from __future__ import absolute_import, division, print_function, unicode_literals +''' +Basic support for manipulating OEB 1.x/2.0 content and metadata. +''' + +__license__ = 'GPL v3' +__copyright__ = '2008, Marshall T. Vandegrift ' +__docformat__ = 'restructuredtext en' + +import os, re, logging, sys, numbers +from collections import defaultdict +from itertools import count +from operator import attrgetter + +from lxml import etree, html +from calibre import force_unicode +from calibre.constants import filesystem_encoding, __version__, ispy3 +from calibre.translations.dynamic import translate +from calibre.utils.xml_parse import safe_xml_fromstring +from calibre.ebooks.chardet import xml_to_unicode +from calibre.ebooks.conversion.preprocess import CSSPreProcessor +from calibre import (isbytestring, as_unicode, get_types_map) +from calibre.ebooks.oeb.parse_utils import barename, XHTML_NS, namespace, XHTML, parse_html, NotHTML +from calibre.utils.cleantext import clean_xml_chars +from calibre.utils.short_uuid import uuid4 +from polyglot.builtins import iteritems, unicode_type, string_or_bytes, range, itervalues, filter, codepoint_to_chr +from polyglot.urllib import unquote as urlunquote, urldefrag, urljoin, urlparse, urlunparse +from calibre.utils.icu import numeric_sort_key + +XML_NS = 'http://www.w3.org/XML/1998/namespace' +OEB_DOC_NS = 'http://openebook.org/namespaces/oeb-document/1.0/' +OPF1_NS = 'http://openebook.org/namespaces/oeb-package/1.0/' +OPF2_NS = 'http://www.idpf.org/2007/opf' +OPF_NSES = {OPF1_NS, OPF2_NS} +DC09_NS = 'http://purl.org/metadata/dublin_core' +DC10_NS = 'http://purl.org/dc/elements/1.0/' +DC11_NS = 'http://purl.org/dc/elements/1.1/' +DC_NSES = {DC09_NS, DC10_NS, DC11_NS} +XSI_NS = 'http://www.w3.org/2001/XMLSchema-instance' +DCTERMS_NS = 'http://purl.org/dc/terms/' +NCX_NS = 'http://www.daisy.org/z3986/2005/ncx/' +SVG_NS = 'http://www.w3.org/2000/svg' +XLINK_NS = 'http://www.w3.org/1999/xlink' +CALIBRE_NS = 'http://calibre.kovidgoyal.net/2009/metadata' +RE_NS = 'http://exslt.org/regular-expressions' +MBP_NS = 'http://www.mobipocket.com' +EPUB_NS = 'http://www.idpf.org/2007/ops' +MATHML_NS = 'http://www.w3.org/1998/Math/MathML' + +XPNSMAP = { + 'h': XHTML_NS, 'o1': OPF1_NS, 'o2': OPF2_NS, 'd09': DC09_NS, + 'd10': DC10_NS, 'd11': DC11_NS, 'xsi': XSI_NS, 'dt': DCTERMS_NS, + 'ncx': NCX_NS, 'svg': SVG_NS, 'xl': XLINK_NS, 're': RE_NS, + 'mathml': MATHML_NS, 'mbp': MBP_NS, 'calibre': CALIBRE_NS, + 'epub':EPUB_NS +} + +OPF1_NSMAP = {'dc': DC11_NS, 'oebpackage': OPF1_NS} +OPF2_NSMAP = {'opf': OPF2_NS, 'dc': DC11_NS, 'dcterms': DCTERMS_NS, + 'xsi': XSI_NS, 'calibre': CALIBRE_NS} + + +def XML(name): + return '{%s}%s' % (XML_NS, name) + + +def OPF(name): + return '{%s}%s' % (OPF2_NS, name) + + +def DC(name): + return '{%s}%s' % (DC11_NS, name) + + +def XSI(name): + return '{%s}%s' % (XSI_NS, name) + + +def DCTERMS(name): + return '{%s}%s' % (DCTERMS_NS, name) + + +def NCX(name): + return '{%s}%s' % (NCX_NS, name) + + +def SVG(name): + return '{%s}%s' % (SVG_NS, name) + + +def XLINK(name): + return '{%s}%s' % (XLINK_NS, name) + + +def CALIBRE(name): + return '{%s}%s' % (CALIBRE_NS, name) + + +_css_url_re = re.compile(r'url\s*\([\'"]{0,1}(.*?)[\'"]{0,1}\)', re.I) +_css_import_re = re.compile(r'@import "(.*?)"') +_archive_re = re.compile(r'[^ ]+') + +# Tags that should not be self closed in epub output +self_closing_bad_tags = {'a', 'abbr', 'address', 'article', 'aside', 'audio', 'b', +'bdo', 'blockquote', 'body', 'button', 'cite', 'code', 'dd', 'del', 'details', +'dfn', 'div', 'dl', 'dt', 'em', 'fieldset', 'figcaption', 'figure', 'footer', +'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup', 'i', 'iframe', 'ins', 'kbd', +'label', 'legend', 'li', 'map', 'mark', 'meter', 'nav', 'ol', 'output', 'p', +'pre', 'progress', 'q', 'rp', 'rt', 'samp', 'section', 'select', 'small', +'span', 'strong', 'sub', 'summary', 'sup', 'textarea', 'time', 'ul', 'var', +'video', 'title', 'script', 'style'} + + +def css_text(x): + ans = x.cssText + if isinstance(ans, bytes): + ans = ans.decode('utf-8', 'replace') + return ans + + +def as_string_type(pat, for_unicode): + if for_unicode: + if isinstance(pat, bytes): + pat = pat.decode('utf-8') + else: + if isinstance(pat, unicode_type): + pat = pat.encode('utf-8') + return pat + + +def self_closing_pat(for_unicode): + attr = 'unicode_ans' if for_unicode else 'bytes_ans' + ans = getattr(self_closing_pat, attr, None) + if ans is None: + sub = '|'.join(self_closing_bad_tags) + template = r'<(?P%s)(?=[\s/])(?P[^>]*)/>' + pat = template % sub + pat = as_string_type(pat, for_unicode) + ans = re.compile(pat, flags=re.IGNORECASE) + setattr(self_closing_pat, attr, ans) + return ans + + +def close_self_closing_tags(raw): + for_unicode = isinstance(raw, unicode_type) + repl = as_string_type(r'<\g\g>>', for_unicode) + pat = self_closing_pat(for_unicode) + return pat.sub(repl, raw) + + +def uuid_id(): + return 'u' + uuid4() + + +def itercsslinks(raw): + for match in _css_url_re.finditer(raw): + yield match.group(1), match.start(1) + for match in _css_import_re.finditer(raw): + yield match.group(1), match.start(1) + + +_link_attrs = set(html.defs.link_attrs) | {XLINK('href'), 'poster'} + + +def iterlinks(root, find_links_in_css=True): + ''' + Iterate over all links in a OEB Document. + + :param root: A valid lxml.etree element. + ''' + assert etree.iselement(root) + + for el in root.iter('*'): + try: + tag = barename(el.tag).lower() + except Exception: + continue + attribs = el.attrib + + if tag == 'object': + codebase = None + # tags have attributes that are relative to + # codebase + if 'codebase' in attribs: + codebase = el.get('codebase') + yield (el, 'codebase', codebase, 0) + for attrib in 'classid', 'data': + if attrib in attribs: + value = el.get(attrib) + if codebase is not None: + value = urljoin(codebase, value) + yield (el, attrib, value, 0) + if 'archive' in attribs: + for match in _archive_re.finditer(el.get('archive')): + value = match.group(0) + if codebase is not None: + value = urljoin(codebase, value) + yield (el, 'archive', value, match.start()) + else: + for attr in attribs: + if attr in _link_attrs: + yield (el, attr, attribs[attr], 0) + + if not find_links_in_css: + continue + if tag == 'style' and el.text: + for match in _css_url_re.finditer(el.text): + yield (el, None, match.group(1), match.start(1)) + for match in _css_import_re.finditer(el.text): + yield (el, None, match.group(1), match.start(1)) + if 'style' in attribs: + for match in _css_url_re.finditer(attribs['style']): + yield (el, 'style', match.group(1), match.start(1)) + + +def make_links_absolute(root, base_url): + ''' + Make all links in the document absolute, given the + ``base_url`` for the document (the full URL where the document + came from) + ''' + def link_repl(href): + return urljoin(base_url, href) + rewrite_links(root, link_repl) + + +def resolve_base_href(root): + base_href = None + basetags = root.xpath('//base[@href]|//h:base[@href]', + namespaces=XPNSMAP) + for b in basetags: + base_href = b.get('href') + b.drop_tree() + if not base_href: + return + make_links_absolute(root, base_href, resolve_base_href=False) + + +def rewrite_links(root, link_repl_func, resolve_base_href=False): + ''' + Rewrite all the links in the document. For each link + ``link_repl_func(link)`` will be called, and the return value + will replace the old link. + + Note that links may not be absolute (unless you first called + ``make_links_absolute()``), and may be internal (e.g., + ``'#anchor'``). They can also be values like + ``'mailto:email'`` or ``'javascript:expr'``. + + If the ``link_repl_func`` returns None, the attribute or + tag text will be removed completely. + ''' + from css_parser import replaceUrls, log, CSSParser + log.setLevel(logging.WARN) + log.raiseExceptions = False + + if resolve_base_href: + resolve_base_href(root) + for el, attrib, link, pos in iterlinks(root, find_links_in_css=False): + new_link = link_repl_func(link.strip()) + if new_link == link: + continue + if new_link is None: + # Remove the attribute or element content + if attrib is None: + el.text = '' + else: + del el.attrib[attrib] + continue + if attrib is None: + new = el.text[:pos] + new_link + el.text[pos+len(link):] + el.text = new + else: + cur = el.attrib[attrib] + if not pos and len(cur) == len(link): + # Most common case + el.attrib[attrib] = new_link + else: + new = cur[:pos] + new_link + cur[pos+len(link):] + el.attrib[attrib] = new + + parser = CSSParser(raiseExceptions=False, log=_css_logger, + fetcher=lambda x:(None, None)) + for el in root.iter(etree.Element): + try: + tag = el.tag + except UnicodeDecodeError: + continue + + if tag == XHTML('style') and el.text and \ + (_css_url_re.search(el.text) is not None or '@import' in + el.text): + stylesheet = parser.parseString(el.text, validate=False) + replaceUrls(stylesheet, link_repl_func) + repl = css_text(stylesheet) + el.text = '\n'+ clean_xml_chars(repl) + '\n' + + text = el.get('style') + if text and _css_url_re.search(text) is not None: + try: + stext = parser.parseStyle(text, validate=False) + except Exception: + # Parsing errors are raised by css_parser + continue + replaceUrls(stext, link_repl_func) + repl = css_text(stext).replace('\n', ' ').replace('\r', + ' ') + el.set('style', repl) + + +types_map = get_types_map() +EPUB_MIME = types_map['.epub'] +XHTML_MIME = types_map['.xhtml'] +CSS_MIME = types_map['.css'] +NCX_MIME = types_map['.ncx'] +OPF_MIME = types_map['.opf'] +PAGE_MAP_MIME = 'application/oebps-page-map+xml' +OEB_DOC_MIME = 'text/x-oeb1-document' +OEB_CSS_MIME = 'text/x-oeb1-css' +OPENTYPE_MIME = types_map['.otf'] +GIF_MIME = types_map['.gif'] +JPEG_MIME = types_map['.jpeg'] +PNG_MIME = types_map['.png'] +SVG_MIME = types_map['.svg'] +BINARY_MIME = 'application/octet-stream' + +XHTML_CSS_NAMESPACE = '@namespace "%s";\n' % XHTML_NS + +OEB_STYLES = {CSS_MIME, OEB_CSS_MIME, 'text/x-oeb-css', 'xhtml/css'} +OEB_DOCS = {XHTML_MIME, 'text/html', OEB_DOC_MIME, + 'text/x-oeb-document'} +OEB_RASTER_IMAGES = {GIF_MIME, JPEG_MIME, PNG_MIME} +OEB_IMAGES = {GIF_MIME, JPEG_MIME, PNG_MIME, SVG_MIME} + +MS_COVER_TYPE = 'other.ms-coverimage-standard' + +ENTITY_RE = re.compile(r'&([a-zA-Z_:][a-zA-Z0-9.-_:]+);') +COLLAPSE_RE = re.compile(r'[ \t\r\n\v]+') +QNAME_RE = re.compile(r'^[{][^{}]+[}][^{}]+$') +PREFIXNAME_RE = re.compile(r'^[^:]+[:][^:]+') +XMLDECL_RE = re.compile(r'^\s*<[?]xml.*?[?]>') +CSSURL_RE = re.compile(r'''url[(](?P["']?)(?P[^)]+)(?P=q)[)]''') + + +def element(parent, *args, **kwargs): + if parent is not None: + return etree.SubElement(parent, *args, **kwargs) + return etree.Element(*args, **kwargs) + + +def prefixname(name, nsrmap): + if not isqname(name): + return name + ns = namespace(name) + if ns not in nsrmap: + return name + prefix = nsrmap[ns] + if not prefix: + return barename(name) + return ':'.join((prefix, barename(name))) + + +def isprefixname(name): + return name and PREFIXNAME_RE.match(name) is not None + + +def qname(name, nsmap): + if not isprefixname(name): + return name + prefix, local = name.split(':', 1) + if prefix not in nsmap: + return name + return '{%s}%s' % (nsmap[prefix], local) + + +def isqname(name): + return name and QNAME_RE.match(name) is not None + + +def XPath(expr): + return etree.XPath(expr, namespaces=XPNSMAP) + + +def xpath(elem, expr): + return elem.xpath(expr, namespaces=XPNSMAP) + + +def xml2str(root, pretty_print=False, strip_comments=False, with_tail=True): + if not strip_comments: + # -- in comments trips up adobe digital editions + for x in root.iterdescendants(etree.Comment): + if x.text and '--' in x.text: + x.text = x.text.replace('--', '__') + ans = etree.tostring(root, encoding='utf-8', xml_declaration=True, + pretty_print=pretty_print, with_tail=with_tail) + + if strip_comments: + ans = re.compile(br'', re.DOTALL).sub(b'', ans) + + return ans + + +def xml2text(elem, pretty_print=False, method='text'): + return etree.tostring(elem, method=method, encoding='unicode', with_tail=False, pretty_print=pretty_print) + + +def escape_cdata(root): + pat = re.compile(r'[<>&]') + for elem in root.iterdescendants('{%s}style' % XHTML_NS, '{%s}script' % XHTML_NS): + if elem.text and pat.search(elem.text) is not None: + elem.text = etree.CDATA(elem.text.replace(']]>', r'\]\]\>')) + + +def serialize(data, media_type, pretty_print=False): + if isinstance(data, etree._Element): + is_oeb_doc = media_type in OEB_DOCS + if is_oeb_doc: + escape_cdata(data) + ans = xml2str(data, pretty_print=pretty_print) + if is_oeb_doc: + # Convert self closing div|span|a|video|audio|iframe|etc tags + # to normally closed ones, as they are interpreted + # incorrectly by some browser based renderers + ans = close_self_closing_tags(ans) + return ans + if isinstance(data, unicode_type): + return data.encode('utf-8') + if hasattr(data, 'cssText'): + data = data.cssText + if isinstance(data, unicode_type): + data = data.encode('utf-8') + return data + b'\n' + return bytes(data) + + +ASCII_CHARS = frozenset(codepoint_to_chr(x) for x in range(128)) +UNIBYTE_CHARS = frozenset(x.encode('ascii') for x in ASCII_CHARS) +USAFE = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ' + 'abcdefghijklmnopqrstuvwxyz' + '0123456789' '_.-/~') +URL_SAFE = frozenset(USAFE) +URL_SAFE_BYTES = frozenset(USAFE.encode('ascii')) +URL_UNSAFE = [ASCII_CHARS - URL_SAFE, UNIBYTE_CHARS - URL_SAFE_BYTES] +del USAFE + + +def urlquote(href): + """ Quote URL-unsafe characters, allowing IRI-safe characters. + That is, this function returns valid IRIs not valid URIs. In particular, + IRIs can contain non-ascii characters. """ + result = [] + isbytes = isinstance(href, bytes) + unsafe = URL_UNSAFE[int(isbytes)] + esc, join = "%%%02x", '' + if isbytes: + esc, join = esc.encode('ascii'), b'' + for char in href: + if char in unsafe: + char = esc % ord(char) + result.append(char) + return join.join(result) + + +def urlnormalize(href): + """Convert a URL into normalized form, with all and only URL-unsafe + characters URL quoted. + """ + try: + parts = urlparse(href) + except ValueError as e: + raise ValueError('Failed to parse the URL: %r with underlying error: %s' % (href, as_unicode(e))) + if not parts.scheme or parts.scheme == 'file': + path, frag = urldefrag(href) + parts = ('', '', path, '', '', frag) + parts = (part.replace('\\', '/') for part in parts) + parts = (urlunquote(part) for part in parts) + parts = (urlquote(part) for part in parts) + return urlunparse(parts) + + +def extract(elem): + """ + Removes this element from the tree, including its children and + text. The tail text is joined to the previous element or + parent. + """ + parent = elem.getparent() + if parent is not None: + if elem.tail: + previous = elem.getprevious() + if previous is None: + parent.text = (parent.text or '') + elem.tail + else: + previous.tail = (previous.tail or '') + elem.tail + parent.remove(elem) + + +class DummyHandler(logging.Handler): + + def __init__(self): + logging.Handler.__init__(self, logging.WARNING) + self.setFormatter(logging.Formatter('%(message)s')) + self.log = None + + def emit(self, record): + if self.log is not None: + msg = self.format(record) + f = self.log.error if record.levelno >= logging.ERROR \ + else self.log.warn + f(msg) + + +_css_logger = logging.getLogger('calibre.css') +_css_logger.setLevel(logging.WARNING) +_css_log_handler = DummyHandler() +_css_logger.addHandler(_css_log_handler) + + +class OEBError(Exception): + """Generic OEB-processing error.""" + pass + + +class NullContainer(object): + """An empty container. + + For use with book formats which do not support container-like access. + """ + + def __init__(self, log): + self.log = log + + def read(self, path): + raise OEBError('Attempt to read from NullContainer') + + def write(self, path): + raise OEBError('Attempt to write to NullContainer') + + def exists(self, path): + return False + + def namelist(self): + return [] + + +class DirContainer(object): + """Filesystem directory container.""" + + def __init__(self, path, log, ignore_opf=False): + self.log = log + if isbytestring(path): + path = path.decode(filesystem_encoding) + self.opfname = None + ext = os.path.splitext(path)[1].lower() + if ext == '.opf': + self.opfname = os.path.basename(path) + self.rootdir = os.path.dirname(path) + return + self.rootdir = path + if not ignore_opf: + for path in self.namelist(): + ext = os.path.splitext(path)[1].lower() + if ext == '.opf': + self.opfname = path + return + + def _unquote(self, path): + # unquote must run on a bytestring and will return a bytestring + # If it runs on a unicode object, it returns a double encoded unicode + # string: unquote(u'%C3%A4') != unquote(b'%C3%A4').decode('utf-8') + # and the latter is correct + if isinstance(path, unicode_type): + path = path.encode('utf-8') + return urlunquote(path).decode('utf-8') + + def read(self, path): + if path is None: + path = self.opfname + path = os.path.join(self.rootdir, self._unquote(path)) + with lopen(path, 'rb') as f: + return f.read() + + def write(self, path, data): + path = os.path.join(self.rootdir, self._unquote(path)) + dir = os.path.dirname(path) + if not os.path.isdir(dir): + os.makedirs(dir) + with lopen(path, 'wb') as f: + return f.write(data) + + def exists(self, path): + if not path: + return False + try: + path = os.path.join(self.rootdir, self._unquote(path)) + except ValueError: # Happens if path contains quoted special chars + return False + try: + return os.path.isfile(path) + except UnicodeEncodeError: + # On linux, if LANG is unset, the os.stat call tries to encode the + # unicode path using ASCII + # To replicate try: + # LANG=en_US.ASCII python -c "import os; os.stat(u'Espa\xf1a')" + return os.path.isfile(path.encode(filesystem_encoding)) + + def namelist(self): + names = [] + base = self.rootdir + for root, dirs, files in os.walk(base): + for fname in files: + fname = os.path.join(root, fname) + if isinstance(fname, bytes): + try: + fname = fname.decode(filesystem_encoding) + except Exception: + try: + fname = fname.decode('utf-8') + except Exception: + continue + fname = fname.replace('\\', '/') + names.append(fname) + return names + + +class Metadata(object): + """A collection of OEB data model metadata. + + Provides access to the list of items associated with a particular metadata + term via the term's local name using either Python container or attribute + syntax. Return an empty list for any terms with no currently associated + metadata items. + """ + + DC_TERMS = {'contributor', 'coverage', 'creator', 'date', + 'description', 'format', 'identifier', 'language', + 'publisher', 'relation', 'rights', 'source', + 'subject', 'title', 'type'} + CALIBRE_TERMS = {'series', 'series_index', 'rating', 'timestamp', + 'publication_type', 'title_sort'} + OPF_ATTRS = {'role': OPF('role'), 'file-as': OPF('file-as'), + 'scheme': OPF('scheme'), 'event': OPF('event'), + 'type': XSI('type'), 'lang': XML('lang'), 'id': 'id'} + OPF1_NSMAP = {'dc': DC11_NS, 'oebpackage': OPF1_NS} + OPF2_NSMAP = {'opf': OPF2_NS, 'dc': DC11_NS, 'dcterms': DCTERMS_NS, + 'xsi': XSI_NS, 'calibre': CALIBRE_NS} + + class Item(object): + """An item of OEB data model metadata. + + The metadata term or name may be accessed via the :attr:`term` or + :attr:`name` attributes. The metadata value or content may be accessed + via the :attr:`value` or :attr:`content` attributes, or via Unicode or + string representations of the object. + + OEB data model metadata attributes may be accessed either via their + fully-qualified names using the Python container access syntax, or via + their local names using Python attribute syntax. Only attributes + allowed by the OPF 2.0 specification are supported. + """ + class Attribute(object): + """Smart accessor for allowed OEB metadata item attributes.""" + + def __init__(self, attr, allowed=None): + if not callable(attr): + attr_, attr = attr, lambda term: attr_ + self.attr = attr + self.allowed = allowed + + def term_attr(self, obj): + term = obj.term + if namespace(term) != DC11_NS: + term = OPF('meta') + allowed = self.allowed + if allowed is not None and term not in allowed: + raise AttributeError( + 'attribute %r not valid for metadata term %r' % ( + self.attr(term), barename(obj.term))) + return self.attr(term) + + def __get__(self, obj, cls): + if obj is None: + return None + return obj.attrib.get(self.term_attr(obj), '') + + def __set__(self, obj, value): + obj.attrib[self.term_attr(obj)] = value + + def __init__(self, term, value, attrib={}, nsmap={}, **kwargs): + self.attrib = attrib = dict(attrib) + self.nsmap = nsmap = dict(nsmap) + attrib.update(kwargs) + if namespace(term) == OPF2_NS: + term = barename(term) + ns = namespace(term) + local = barename(term).lower() + if local in Metadata.DC_TERMS and (not ns or ns in DC_NSES): + # Anything looking like Dublin Core is coerced + term = DC(local) + elif local in Metadata.CALIBRE_TERMS and ns in (CALIBRE_NS, ''): + # Ditto for Calibre-specific metadata + term = CALIBRE(local) + self.term = term + self.value = value + for attr, value in tuple(iteritems(attrib)): + if isprefixname(value): + attrib[attr] = qname(value, nsmap) + nsattr = Metadata.OPF_ATTRS.get(attr, attr) + if nsattr == OPF('scheme') and namespace(term) != DC11_NS: + # The opf:meta element takes @scheme, not @opf:scheme + nsattr = 'scheme' + if attr != nsattr: + attrib[nsattr] = attrib.pop(attr) + + @property + def name(self): + return self.term + + @property + def content(self): + return self.value + + @content.setter + def content(self, value): + self.value = value + + scheme = Attribute(lambda term: 'scheme' if + term == OPF('meta') else OPF('scheme'), + [DC('identifier'), OPF('meta')]) + file_as = Attribute(OPF('file-as'), [DC('creator'), DC('contributor'), + DC('title')]) + role = Attribute(OPF('role'), [DC('creator'), DC('contributor')]) + event = Attribute(OPF('event'), [DC('date')]) + id = Attribute('id') + type = Attribute(XSI('type'), [DC('date'), DC('format'), + DC('type')]) + lang = Attribute(XML('lang'), [DC('contributor'), DC('coverage'), + DC('creator'), DC('publisher'), + DC('relation'), DC('rights'), + DC('source'), DC('subject'), + OPF('meta')]) + + def __getitem__(self, key): + return self.attrib[key] + + def __setitem__(self, key, value): + self.attrib[key] = value + + def __contains__(self, key): + return key in self.attrib + + def get(self, key, default=None): + return self.attrib.get(key, default) + + def __repr__(self): + return 'Item(term=%r, value=%r, attrib=%r)' \ + % (barename(self.term), self.value, self.attrib) + + if ispy3: + def __str__(self): + return as_unicode(self.value) + else: + def __str__(self): + return unicode_type(self.value).encode('ascii', 'xmlcharrefreplace') + + def __unicode__(self): + return as_unicode(self.value) + + def to_opf1(self, dcmeta=None, xmeta=None, nsrmap={}): + attrib = {} + for key, value in self.attrib.items(): + if namespace(key) == OPF2_NS: + key = barename(key) + attrib[key] = prefixname(value, nsrmap) + if namespace(self.term) == DC11_NS: + name = DC(icu_title(barename(self.term))) + elem = element(dcmeta, name, attrib=attrib) + elem.text = self.value + else: + elem = element(xmeta, 'meta', attrib=attrib) + elem.attrib['name'] = prefixname(self.term, nsrmap) + elem.attrib['content'] = prefixname(self.value, nsrmap) + return elem + + def to_opf2(self, parent=None, nsrmap={}): + attrib = {} + for key, value in self.attrib.items(): + attrib[key] = prefixname(value, nsrmap) + if namespace(self.term) == DC11_NS: + elem = element(parent, self.term, attrib=attrib) + try: + elem.text = self.value + except: + elem.text = repr(self.value) + else: + elem = element(parent, OPF('meta'), attrib=attrib) + elem.attrib['name'] = prefixname(self.term, nsrmap) + elem.attrib['content'] = prefixname(self.value, nsrmap) + return elem + + def __init__(self, oeb): + self.oeb = oeb + self.items = defaultdict(list) + self.primary_writing_mode = None + + def add(self, term, value, attrib={}, nsmap={}, **kwargs): + """Add a new metadata item.""" + item = self.Item(term, value, attrib, nsmap, **kwargs) + items = self.items[barename(item.term)] + items.append(item) + return item + + def iterkeys(self): + for key in self.items: + yield key + __iter__ = iterkeys + + def clear(self, key): + l = self.items[key] + for x in list(l): + l.remove(x) + + def filter(self, key, predicate): + l = self.items[key] + for x in list(l): + if predicate(x): + l.remove(x) + + def __getitem__(self, key): + return self.items[key] + + def __contains__(self, key): + return key in self.items + + def __getattr__(self, term): + return self.items[term] + + @property + def _nsmap(self): + nsmap = {} + for term in self.items: + for item in self.items[term]: + nsmap.update(item.nsmap) + return nsmap + + @property + def _opf1_nsmap(self): + nsmap = self._nsmap + for key, value in nsmap.items(): + if value in OPF_NSES or value in DC_NSES: + del nsmap[key] + return nsmap + + @property + def _opf2_nsmap(self): + nsmap = self._nsmap + nsmap.update(OPF2_NSMAP) + return nsmap + + def to_opf1(self, parent=None): + nsmap = self._opf1_nsmap + nsrmap = {value: key for key, value in iteritems(nsmap)} + elem = element(parent, 'metadata', nsmap=nsmap) + dcmeta = element(elem, 'dc-metadata', nsmap=OPF1_NSMAP) + xmeta = element(elem, 'x-metadata') + for term in self.items: + for item in self.items[term]: + item.to_opf1(dcmeta, xmeta, nsrmap=nsrmap) + if 'ms-chaptertour' not in self.items: + chaptertour = self.Item('ms-chaptertour', 'chaptertour') + chaptertour.to_opf1(dcmeta, xmeta, nsrmap=nsrmap) + return elem + + def to_opf2(self, parent=None): + nsmap = self._opf2_nsmap + nsrmap = {value: key for key, value in iteritems(nsmap)} + elem = element(parent, OPF('metadata'), nsmap=nsmap) + for term in self.items: + for item in self.items[term]: + item.to_opf2(elem, nsrmap=nsrmap) + if self.primary_writing_mode: + elem.append(elem.makeelement(OPF('meta'), attrib={'name':'primary-writing-mode', 'content':self.primary_writing_mode})) + return elem + + +class Manifest(object): + """Collection of files composing an OEB data model book. + + Provides access to the content of the files composing the book and + attributes associated with those files, including their internal paths, + unique identifiers, and MIME types. + + Itself acts as a :class:`set` of manifest items, and provides the following + instance data member for dictionary-like access: + + :attr:`ids`: A dictionary in which the keys are the unique identifiers of + the manifest items and the values are the items themselves. + :attr:`hrefs`: A dictionary in which the keys are the internal paths of the + manifest items and the values are the items themselves. + """ + + class Item(object): + """An OEB data model book content file. + + Provides the following data members for accessing the file content and + metadata associated with this particular file. + + :attr:`id`: Unique identifier. + :attr:`href`: Book-internal path. + :attr:`media_type`: MIME type of the file content. + :attr:`fallback`: Unique id of any fallback manifest item associated + with this manifest item. + :attr:`spine_position`: Display/reading order index for book textual + content. `None` for manifest items which are not part of the + book's textual content. + :attr:`linear`: `True` for textual content items which are part of the + primary linear reading order and `False` for textual content items + which are not (such as footnotes). Meaningless for items which + have a :attr:`spine_position` of `None`. + """ + + def __init__(self, oeb, id, href, media_type, + fallback=None, loader=unicode_type, data=None): + if href: + href = unicode_type(href) + self.oeb = oeb + self.id = id + self.href = self.path = urlnormalize(href) + self.media_type = media_type + self.fallback = fallback + self.override_css_fetch = None + self.spine_position = None + self.linear = True + if loader is None and data is None: + loader = oeb.container.read + self._loader = loader + self._data = data + + def __repr__(self): + return 'Item(id=%r, href=%r, media_type=%r)' \ + % (self.id, self.href, self.media_type) + + # Parsing {{{ + def _parse_xml(self, data): + if not data: + return + data = xml_to_unicode(data, strip_encoding_pats=True, + assume_utf8=True, resolve_entities=True)[0] + return safe_xml_fromstring(data) + + def _parse_xhtml(self, data): + orig_data = data + fname = urlunquote(self.href) + self.oeb.log.debug('Parsing', fname, '...') + self.oeb.html_preprocessor.current_href = self.href + try: + data = parse_html(data, log=self.oeb.log, + decoder=self.oeb.decode, + preprocessor=self.oeb.html_preprocessor, + filename=fname, non_html_file_tags={'ncx'}) + except NotHTML: + return self._parse_xml(orig_data) + return data + + def _parse_txt(self, data): + has_html = '' + if isinstance(data, bytes): + has_html = has_html.encode('ascii') + if has_html in data: + return self._parse_xhtml(data) + + self.oeb.log.debug('Converting', self.href, '...') + + from calibre.ebooks.txt.processor import convert_markdown + + title = self.oeb.metadata.title + if title: + title = unicode_type(title[0]) + else: + title = _('Unknown') + + return self._parse_xhtml(convert_markdown(data, title=title)) + + def _parse_css(self, data): + from css_parser import CSSParser, log, resolveImports + from css_parser.css import CSSRule + log.setLevel(logging.WARN) + log.raiseExceptions = False + self.oeb.log.debug('Parsing', self.href, '...') + data = self.oeb.decode(data) + data = self.oeb.css_preprocessor(data, add_namespace=False) + parser = CSSParser(loglevel=logging.WARNING, + fetcher=self.override_css_fetch or self._fetch_css, + log=_css_logger) + data = parser.parseString(data, href=self.href, validate=False) + data = resolveImports(data) + for rule in tuple(data.cssRules.rulesOfType(CSSRule.PAGE_RULE)): + data.cssRules.remove(rule) + return data + + def _fetch_css(self, path): + hrefs = self.oeb.manifest.hrefs + if path not in hrefs: + self.oeb.logger.warn('CSS import of missing file %r' % path) + return (None, None) + item = hrefs[path] + if item.media_type not in OEB_STYLES: + self.oeb.logger.warn('CSS import of non-CSS file %r' % path) + return (None, None) + data = item.data.cssText + enc = None if isinstance(data, unicode_type) else 'utf-8' + return (enc, data) + + # }}} + + @property + def data(self): + """Provides MIME type sensitive access to the manifest + entry's associated content. + + - XHTML, HTML, and variant content is parsed as necessary to + convert and return as an lxml.etree element in the XHTML + namespace. + - XML content is parsed and returned as an lxml.etree element. + - CSS and CSS-variant content is parsed and returned as a css_parser + CSS DOM stylesheet. + - All other content is returned as a :class:`str` or :class:`bytes` + object with no special parsing. + """ + data = self._data + if data is None: + if self._loader is None: + return None + data = self._loader(getattr(self, 'html_input_href', + self.href)) + try: + mt = self.media_type.lower() + except Exception: + mt = 'application/octet-stream' + if not isinstance(data, string_or_bytes): + pass # already parsed + elif mt in OEB_DOCS: + data = self._parse_xhtml(data) + elif mt[-4:] in ('+xml', '/xml'): + data = self._parse_xml(data) + elif mt in OEB_STYLES: + data = self._parse_css(data) + elif mt == 'text/plain': + self.oeb.log.warn('%s contains data in TXT format'%self.href, + 'converting to HTML') + data = self._parse_txt(data) + self.media_type = XHTML_MIME + self._data = data + return data + + @data.setter + def data(self, value): + self._data = value + + @data.deleter + def data(self): + self._data = None + + def unload_data_from_memory(self, memory=None): + if isinstance(self._data, bytes): + if memory is None: + from calibre.ptempfile import PersistentTemporaryFile + pt = PersistentTemporaryFile(suffix='_oeb_base_mem_unloader.img') + with pt: + pt.write(self._data) + self.oeb._temp_files.append(pt.name) + + def loader(*args): + with open(pt.name, 'rb') as f: + ans = f.read() + os.remove(pt.name) + return ans + self._loader = loader + else: + def loader2(*args): + with open(memory, 'rb') as f: + ans = f.read() + return ans + self._loader = loader2 + self._data = None + + @property + def unicode_representation(self): + data = self.data + if isinstance(data, etree._Element): + return xml2text(data, pretty_print=self.oeb.pretty_print) + if isinstance(data, unicode_type): + return data + if hasattr(data, 'cssText'): + return css_text(data) + return unicode_type(data) + + @property + def bytes_representation(self): + return serialize(self.data, self.media_type, pretty_print=self.oeb.pretty_print) + + if ispy3: + def __str__(self): + return self.unicode_representation + else: + def __unicode__(self): + return self.unicode_representation + + def __str__(self): + return self.bytes_representation + + def __eq__(self, other): + return self is other + + def __ne__(self, other): + return self is not other + + def __hash__(self): + return id(self) + + @property + def sort_key(self): + href = self.href + if isinstance(href, bytes): + href = force_unicode(href) + sp = self.spine_position if isinstance(self.spine_position, numbers.Number) else sys.maxsize + return sp, (self.media_type or '').lower(), numeric_sort_key(href), self.id + + def relhref(self, href): + """Convert the URL provided in :param:`href` from a book-absolute + reference to a reference relative to this manifest item. + """ + return rel_href(self.href, href) + + def abshref(self, href): + """Convert the URL provided in :param:`href` from a reference + relative to this manifest item to a book-absolute reference. + """ + try: + purl = urlparse(href) + except ValueError: + return href + scheme = purl.scheme + if scheme and scheme != 'file': + return href + purl = list(purl) + purl[0] = '' + href = urlunparse(purl) + path, frag = urldefrag(href) + if not path: + if frag: + return '#'.join((self.href, frag)) + else: + return self.href + if '/' not in self.href: + return href + dirname = os.path.dirname(self.href) + href = os.path.join(dirname, href) + href = os.path.normpath(href).replace('\\', '/') + return href + + def __init__(self, oeb): + self.oeb = oeb + self.items = set() + self.ids = {} + self.hrefs = {} + + def add(self, id, href, media_type, fallback=None, loader=None, data=None): + """Add a new item to the book manifest. + + The item's :param:`id`, :param:`href`, and :param:`media_type` are all + required. A :param:`fallback` item-id is required for any items with a + MIME type which is not one of the OPS core media types. Either the + item's data itself may be provided with :param:`data`, or a loader + function for the data may be provided with :param:`loader`, or the + item's data may later be set manually via the :attr:`data` attribute. + """ + item = self.Item( + self.oeb, id, href, media_type, fallback, loader, data) + self.items.add(item) + self.ids[item.id] = item + self.hrefs[item.href] = item + return item + + def remove(self, item): + """Removes :param:`item` from the manifest.""" + if item in self.ids: + item = self.ids[item] + del self.ids[item.id] + if item.href in self.hrefs: + del self.hrefs[item.href] + self.items.remove(item) + if item in self.oeb.spine: + self.oeb.spine.remove(item) + + def remove_duplicate_item(self, item): + if item in self.ids: + item = self.ids[item] + del self.ids[item.id] + self.items.remove(item) + + def generate(self, id=None, href=None): + """Generate a new unique identifier and/or internal path for use in + creating a new manifest item, using the provided :param:`id` and/or + :param:`href` as bases. + + Returns an two-tuple of the new id and path. If either :param:`id` or + :param:`href` are `None` then the corresponding item in the return + tuple will also be `None`. + """ + if id is not None: + base = id + index = 1 + while id in self.ids: + id = base + unicode_type(index) + index += 1 + if href is not None: + href = urlnormalize(href) + base, ext = os.path.splitext(href) + index = 1 + lhrefs = {x.lower() for x in self.hrefs} + while href.lower() in lhrefs: + href = base + unicode_type(index) + ext + index += 1 + return id, unicode_type(href) + + def __iter__(self): + for item in self.items: + yield item + + def __len__(self): + return len(self.items) + + def values(self): + return list(self.items) + + def __contains__(self, item): + return item in self.items + + def to_opf1(self, parent=None): + elem = element(parent, 'manifest') + for item in self.items: + media_type = item.media_type + if media_type in OEB_DOCS: + media_type = OEB_DOC_MIME + elif media_type in OEB_STYLES: + media_type = OEB_CSS_MIME + attrib = {'id': item.id, 'href': urlunquote(item.href), + 'media-type': media_type} + if item.fallback: + attrib['fallback'] = item.fallback + element(elem, 'item', attrib=attrib) + return elem + + def to_opf2(self, parent=None): + elem = element(parent, OPF('manifest')) + for item in sorted(self.items, key=attrgetter('sort_key')): + media_type = item.media_type + if media_type in OEB_DOCS: + media_type = XHTML_MIME + elif media_type in OEB_STYLES: + media_type = CSS_MIME + attrib = {'id': item.id, 'href': urlunquote(item.href), + 'media-type': media_type} + if item.fallback: + attrib['fallback'] = item.fallback + element(elem, OPF('item'), attrib=attrib) + return elem + + @property + def main_stylesheet(self): + ans = getattr(self, '_main_stylesheet', None) + if ans is None: + for item in self: + if item.media_type.lower() in OEB_STYLES: + ans = item + break + return ans + + @main_stylesheet.setter + def main_stylesheet(self, item): + self._main_stylesheet = item + + +class Spine(object): + """Collection of manifest items composing an OEB data model book's main + textual content. + + The spine manages which manifest items compose the book's main textual + content and the sequence in which they appear. Provides Python container + access as a list-like object. + """ + + def __init__(self, oeb): + self.oeb = oeb + self.items = [] + self.page_progression_direction = None + + def _linear(self, linear): + if isinstance(linear, string_or_bytes): + linear = linear.lower() + if linear is None or linear in ('yes', 'true'): + linear = True + elif linear in ('no', 'false'): + linear = False + return linear + + def add(self, item, linear=None): + """Append :param:`item` to the end of the `Spine`.""" + item.linear = self._linear(linear) + item.spine_position = len(self.items) + self.items.append(item) + return item + + def insert(self, index, item, linear): + """Insert :param:`item` at position :param:`index` in the `Spine`.""" + item.linear = self._linear(linear) + item.spine_position = index + self.items.insert(index, item) + for i in range(index, len(self.items)): + self.items[i].spine_position = i + return item + + def remove(self, item): + """Remove :param:`item` from the `Spine`.""" + index = item.spine_position + self.items.pop(index) + for i in range(index, len(self.items)): + self.items[i].spine_position = i + item.spine_position = None + + def index(self, item): + for i, x in enumerate(self): + if item == x: + return i + return -1 + + def __iter__(self): + for item in self.items: + yield item + + def __getitem__(self, index): + return self.items[index] + + def __len__(self): + return len(self.items) + + def __contains__(self, item): + return (item in self.items) + + def to_opf1(self, parent=None): + elem = element(parent, 'spine') + for item in self.items: + if item.linear: + element(elem, 'itemref', attrib={'idref': item.id}) + return elem + + def to_opf2(self, parent=None): + elem = element(parent, OPF('spine')) + for item in self.items: + attrib = {'idref': item.id} + if not item.linear: + attrib['linear'] = 'no' + element(elem, OPF('itemref'), attrib=attrib) + return elem + + +class Guide(object): + """Collection of references to standard frequently-occurring sections + within an OEB data model book. + + Provides dictionary-like access, in which the keys are the OEB reference + type identifiers and the values are `Reference` objects. + """ + + class Reference(object): + """Reference to a standard book section. + + Provides the following instance data members: + + :attr:`type`: Reference type identifier, as chosen from the list + allowed in the OPF 2.0 specification. + :attr:`title`: Human-readable section title. + :attr:`href`: Book-internal URL of the referenced section. May include + a fragment identifier. + """ + _TYPES_TITLES = [('cover', __('Cover')), + ('title-page', __('Title page')), + ('toc', __('Table of Contents')), + ('index', __('Index')), + ('glossary', __('Glossary')), + ('acknowledgements', __('Acknowledgements')), + ('bibliography', __('Bibliography')), + ('colophon', __('Colophon')), + ('copyright-page', __('Copyright')), + ('dedication', __('Dedication')), + ('epigraph', __('Epigraph')), + ('foreword', __('Foreword')), + ('loi', __('List of illustrations')), + ('lot', __('List of tables')), + ('notes', __('Notes')), + ('preface', __('Preface')), + ('text', __('Main text'))] + TITLES = dict(_TYPES_TITLES) + TYPES = frozenset(TITLES) + ORDER = {t: i for i, (t, _) in enumerate(_TYPES_TITLES)} + + def __init__(self, oeb, type, title, href): + self.oeb = oeb + if type.lower() in self.TYPES: + type = type.lower() + elif type not in self.TYPES and \ + not type.startswith('other.'): + type = 'other.' + type + if not title and type in self.TITLES: + title = oeb.translate(self.TITLES[type]) + self.type = type + self.title = title + self.href = urlnormalize(href) + + def __repr__(self): + return 'Reference(type=%r, title=%r, href=%r)' \ + % (self.type, self.title, self.href) + + @property + def item(self): + """The manifest item associated with this reference.""" + path = urldefrag(self.href)[0] + hrefs = self.oeb.manifest.hrefs + return hrefs.get(path, None) + + def __init__(self, oeb): + self.oeb = oeb + self.refs = {} + + def add(self, type, title, href): + """Add a new reference to the `Guide`.""" + if href: + href = unicode_type(href) + ref = self.Reference(self.oeb, type, title, href) + self.refs[type] = ref + return ref + + def remove(self, type): + return self.refs.pop(type, None) + + def remove_by_href(self, href): + remove = [r for r, i in iteritems(self.refs) if i.href == href] + for r in remove: + self.remove(r) + + def iterkeys(self): + for type in self.refs: + yield type + __iter__ = iterkeys + + def values(self): + return sorted(itervalues(self.refs), key=lambda ref: ref.ORDER.get(ref.type, 10000)) + + def items(self): + for type, ref in self.refs.items(): + yield type, ref + + def __getitem__(self, key): + return self.refs[key] + + def get(self, key): + return self.refs.get(key) + + def __delitem__(self, key): + del self.refs[key] + + def __contains__(self, key): + return key in self.refs + + def __len__(self): + return len(self.refs) + + def to_opf1(self, parent=None): + elem = element(parent, 'guide') + for ref in self.refs.values(): + attrib = {'type': ref.type, 'href': urlunquote(ref.href)} + if ref.title: + attrib['title'] = ref.title + element(elem, 'reference', attrib=attrib) + return elem + + def to_opf2(self, parent=None): + if not len(self): + return + elem = element(parent, OPF('guide')) + for ref in self.refs.values(): + attrib = {'type': ref.type, 'href': urlunquote(ref.href)} + if ref.title: + attrib['title'] = ref.title + element(elem, OPF('reference'), attrib=attrib) + return elem + + +class TOC(object): + """Represents a hierarchical table of contents or navigation tree for + accessing arbitrary semantic sections within an OEB data model book. + + Acts as a node within the navigation tree. Provides list-like access to + sub-nodes. Provides the follow node instance data attributes: + + :attr:`title`: The title of this navigation node. + :attr:`href`: Book-internal URL referenced by this node. + :attr:`klass`: Optional semantic class referenced by this node. + :attr:`id`: Option unique identifier for this node. + :attr:`author`: Optional author attribution for periodicals + :attr:`description`: Optional description attribute for periodicals + :attr:`toc_thumbnail`: Optional toc thumbnail image + """ + + def __init__(self, title=None, href=None, klass=None, id=None, + play_order=None, author=None, description=None, toc_thumbnail=None): + self.title = title + self.href = urlnormalize(href) if href else href + self.klass = klass + self.id = id + self.nodes = [] + self.play_order = 0 + if play_order is None: + play_order = self.next_play_order() + self.play_order = play_order + self.author = author + self.description = description + self.toc_thumbnail = toc_thumbnail + + def add(self, title, href, klass=None, id=None, play_order=0, author=None, description=None, toc_thumbnail=None): + """Create and return a new sub-node of this node.""" + node = TOC(title, href, klass, id, play_order, author, description, toc_thumbnail) + self.nodes.append(node) + return node + + def remove(self, node): + for child in self.nodes: + if child is node: + self.nodes.remove(child) + return True + else: + if child.remove(node): + return True + return False + + def iter(self): + """Iterate over this node and all descendants in depth-first order.""" + yield self + for child in self.nodes: + for node in child.iter(): + yield node + + def count(self): + return len(list(self.iter())) - 1 + + def next_play_order(self): + entries = [x.play_order for x in self.iter()] + base = max(entries) if entries else 0 + return base+1 + + def has_href(self, href): + for x in self.iter(): + if x.href == href: + return True + return False + + def has_text(self, text): + for x in self.iter(): + if x.title and x.title.lower() == text.lower(): + return True + return False + + def iterdescendants(self, breadth_first=False): + """Iterate over all descendant nodes in depth-first order.""" + if breadth_first: + for child in self.nodes: + yield child + for child in self.nodes: + for node in child.iterdescendants(breadth_first=True): + yield node + else: + for child in self.nodes: + for node in child.iter(): + yield node + + def __iter__(self): + """Iterate over all immediate child nodes.""" + for node in self.nodes: + yield node + + def __getitem__(self, index): + return self.nodes[index] + + def autolayer(self): + """Make sequences of children pointing to the same content file into + children of the first node referencing that file. + """ + prev = None + for node in list(self.nodes): + if prev and urldefrag(prev.href)[0] == urldefrag(node.href)[0]: + self.nodes.remove(node) + prev.nodes.append(node) + else: + prev = node + + def depth(self): + """The maximum depth of the navigation tree rooted at this node.""" + try: + return max(node.depth() for node in self.nodes) + 1 + except ValueError: + return 1 + + def get_lines(self, lvl=0): + ans = [('\t'*lvl) + 'TOC: %s --> %s'%(self.title, self.href)] + for child in self: + ans.extend(child.get_lines(lvl+1)) + return ans + + if ispy3: + def __str__(self): + return '\n'.join(self.get_lines()) + else: + def __unicode__(self): + return '\n'.join(self.get_lines()) + + def __str__(self): + return b'\n'.join([x.encode('utf-8') for x in self.get_lines()]) + + def to_opf1(self, tour): + for node in self.nodes: + element(tour, 'site', attrib={ + 'title': node.title, 'href': urlunquote(node.href)}) + node.to_opf1(tour) + return tour + + def to_ncx(self, parent=None): + if parent is None: + parent = etree.Element(NCX('navMap')) + for node in self.nodes: + id = node.id or uuid_id() + po = node.play_order + if po == 0: + po = 1 + attrib = {'id': id, 'playOrder': unicode_type(po)} + if node.klass: + attrib['class'] = node.klass + point = element(parent, NCX('navPoint'), attrib=attrib) + label = etree.SubElement(point, NCX('navLabel')) + title = node.title + if title: + title = re.sub(r'\s+', ' ', title) + element(label, NCX('text')).text = title + # Do not unescape this URL as ADE requires it to be escaped to + # handle semi colons and other special characters in the file names + element(point, NCX('content'), src=node.href) + node.to_ncx(point) + return parent + + def rationalize_play_orders(self): + ''' + Ensure that all nodes with the same play_order have the same href and + with different play_orders have different hrefs. + ''' + def po_node(n): + for x in self.iter(): + if x is n: + return + if x.play_order == n.play_order: + return x + + def href_node(n): + for x in self.iter(): + if x is n: + return + if x.href == n.href: + return x + + for x in self.iter(): + y = po_node(x) + if y is not None: + if x.href != y.href: + x.play_order = getattr(href_node(x), 'play_order', + self.next_play_order()) + y = href_node(x) + if y is not None: + x.play_order = y.play_order + + +class PageList(object): + """Collection of named "pages" to mapped positions within an OEB data model + book's textual content. + + Provides list-like access to the pages. + """ + + class Page(object): + """Represents a mapping between a page name and a position within + the book content. + + Provides the following instance data attributes: + + :attr:`name`: The name of this page. Generally a number. + :attr:`href`: Book-internal URL at which point this page begins. + :attr:`type`: Must be one of 'front' (for prefatory pages, as commonly + labeled in print with small-case Roman numerals), 'normal' (for + standard pages, as commonly labeled in print with Arabic numerals), + or 'special' (for other pages, as commonly not labeled in any + fashion in print, such as the cover and title pages). + :attr:`klass`: Optional semantic class of this page. + :attr:`id`: Optional unique identifier for this page. + """ + TYPES = {'front', 'normal', 'special'} + + def __init__(self, name, href, type='normal', klass=None, id=None): + self.name = unicode_type(name) + self.href = urlnormalize(href) + self.type = type if type in self.TYPES else 'normal' + self.id = id + self.klass = klass + + def __init__(self): + self.pages = [] + + def add(self, name, href, type='normal', klass=None, id=None): + """Create a new page and add it to the `PageList`.""" + page = self.Page(name, href, type, klass, id) + self.pages.append(page) + return page + + def __len__(self): + return len(self.pages) + + def __iter__(self): + for page in self.pages: + yield page + + def __getitem__(self, index): + return self.pages[index] + + def pop(self, index=-1): + return self.pages.pop(index) + + def remove(self, page): + return self.pages.remove(page) + + def to_ncx(self, parent=None): + plist = element(parent, NCX('pageList'), id=uuid_id()) + values = {t: count(1) for t in ('front', 'normal', 'special')} + for page in self.pages: + id = page.id or uuid_id() + type = page.type + value = unicode_type(next(values[type])) + attrib = {'id': id, 'value': value, 'type': type, 'playOrder': '0'} + if page.klass: + attrib['class'] = page.klass + ptarget = element(plist, NCX('pageTarget'), attrib=attrib) + label = element(ptarget, NCX('navLabel')) + element(label, NCX('text')).text = page.name + element(ptarget, NCX('content'), src=page.href) + return plist + + def to_page_map(self): + pmap = etree.Element(OPF('page-map'), nsmap={None: OPF2_NS}) + for page in self.pages: + element(pmap, OPF('page'), name=page.name, href=page.href) + return pmap + + +class OEBBook(object): + """Representation of a book in the IDPF OEB data model.""" + + COVER_SVG_XP = XPath('h:body//svg:svg[position() = 1]') + COVER_OBJECT_XP = XPath('h:body//h:object[@data][position() = 1]') + + def __init__(self, logger, + html_preprocessor, + css_preprocessor=CSSPreProcessor(), + encoding='utf-8', pretty_print=False, + input_encoding='utf-8'): + """Create empty book. Arguments: + + :param:`encoding`: Default encoding for textual content read + from an external container. + :param:`pretty_print`: Whether or not the canonical string form + of XML markup is pretty-printed. + :param html_preprocessor: A callable that takes a unicode object + and returns a unicode object. Will be called on all html files + before they are parsed. + :param css_preprocessor: A callable that takes a unicode object + and returns a unicode object. Will be called on all CSS files + before they are parsed. + :param:`logger`: A Log object to use for logging all messages + related to the processing of this book. It is accessible + via the instance data members :attr:`logger,log`. + + It provides the following public instance data members for + accessing various parts of the OEB data model: + + :attr:`metadata`: Metadata such as title, author name(s), etc. + :attr:`manifest`: Manifest of all files included in the book, + including MIME types and fallback information. + :attr:`spine`: In-order list of manifest items which compose + the textual content of the book. + :attr:`guide`: Collection of references to standard positions + within the text, such as the cover, preface, etc. + :attr:`toc`: Hierarchical table of contents. + :attr:`pages`: List of "pages," such as indexed to a print edition of + the same text. + """ + _css_log_handler.log = logger + self.encoding = encoding + self.input_encoding = input_encoding + self.html_preprocessor = html_preprocessor + self.css_preprocessor = css_preprocessor + self.pretty_print = pretty_print + self.logger = self.log = logger + self.version = '2.0' + self.container = NullContainer(self.log) + self.metadata = Metadata(self) + self.uid = None + self.manifest = Manifest(self) + self.spine = Spine(self) + self.guide = Guide(self) + self.toc = TOC() + self.pages = PageList() + self.auto_generated_toc = True + self._temp_files = [] + + def clean_temp_files(self): + for path in self._temp_files: + try: + os.remove(path) + except: + pass + + @classmethod + def generate(cls, opts): + """Generate an OEBBook instance from command-line options.""" + encoding = opts.encoding + pretty_print = opts.pretty_print + return cls(encoding=encoding, pretty_print=pretty_print) + + def translate(self, text): + """Translate :param:`text` into the book's primary language.""" + lang = unicode_type(self.metadata.language[0]) + lang = lang.split('-', 1)[0].lower() + return translate(lang, text) + + def decode(self, data): + """Automatically decode :param:`data` into a `unicode` object.""" + def fix_data(d): + return d.replace('\r\n', '\n').replace('\r', '\n') + if isinstance(data, unicode_type): + return fix_data(data) + bom_enc = None + if data[:4] in (b'\0\0\xfe\xff', b'\xff\xfe\0\0'): + bom_enc = {b'\0\0\xfe\xff':'utf-32-be', + b'\xff\xfe\0\0':'utf-32-le'}[data[:4]] + data = data[4:] + elif data[:2] in (b'\xff\xfe', b'\xfe\xff'): + bom_enc = {b'\xff\xfe':'utf-16-le', 'b\xfe\xff':'utf-16-be'}[data[:2]] + data = data[2:] + elif data[:3] == b'\xef\xbb\xbf': + bom_enc = 'utf-8' + data = data[3:] + if bom_enc is not None: + try: + return fix_data(data.decode(bom_enc)) + except UnicodeDecodeError: + pass + if self.input_encoding: + try: + return fix_data(data.decode(self.input_encoding, 'replace')) + except UnicodeDecodeError: + pass + try: + return fix_data(data.decode('utf-8')) + except UnicodeDecodeError: + pass + data, _ = xml_to_unicode(data) + return fix_data(data) + + def to_opf1(self): + """Produce OPF 1.2 representing the book's metadata and structure. + + Returns a dictionary in which the keys are MIME types and the values + are tuples of (default) filenames and lxml.etree element structures. + """ + package = etree.Element('package', + attrib={'unique-identifier': self.uid.id}) + self.metadata.to_opf1(package) + self.manifest.to_opf1(package) + self.spine.to_opf1(package) + tours = element(package, 'tours') + tour = element(tours, 'tour', + attrib={'id': 'chaptertour', 'title': 'Chapter Tour'}) + self.toc.to_opf1(tour) + self.guide.to_opf1(package) + return {OPF_MIME: ('content.opf', package)} + + def _update_playorder(self, ncx): + hrefs = set(map(urlnormalize, xpath(ncx, '//ncx:content/@src'))) + playorder = {} + next = 1 + selector = XPath('h:body//*[@id or @name]') + for item in self.spine: + base = item.href + if base in hrefs: + playorder[base] = next + next += 1 + for elem in selector(item.data): + added = False + for attr in ('id', 'name'): + id = elem.get(attr) + if not id: + continue + href = '#'.join([base, id]) + if href in hrefs: + playorder[href] = next + added = True + if added: + next += 1 + selector = XPath('ncx:content/@src') + for i, elem in enumerate(xpath(ncx, '//*[@playOrder and ./ncx:content[@src]]')): + href = urlnormalize(selector(elem)[0]) + order = playorder.get(href, i) + elem.attrib['playOrder'] = unicode_type(order) + return + + def _to_ncx(self): + lang = unicode_type(self.metadata.language[0]) + lang = lang.replace('_', '-') + ncx = etree.Element(NCX('ncx'), + attrib={'version': '2005-1', XML('lang'): lang}, + nsmap={None: NCX_NS}) + head = etree.SubElement(ncx, NCX('head')) + etree.SubElement(head, NCX('meta'), + name='dtb:uid', content=unicode_type(self.uid)) + etree.SubElement(head, NCX('meta'), + name='dtb:depth', content=unicode_type(self.toc.depth())) + generator = ''.join(['calibre (', __version__, ')']) + etree.SubElement(head, NCX('meta'), + name='dtb:generator', content=generator) + etree.SubElement(head, NCX('meta'), + name='dtb:totalPageCount', content=unicode_type(len(self.pages))) + maxpnum = etree.SubElement(head, NCX('meta'), + name='dtb:maxPageNumber', content='0') + title = etree.SubElement(ncx, NCX('docTitle')) + text = etree.SubElement(title, NCX('text')) + text.text = unicode_type(self.metadata.title[0]) + navmap = etree.SubElement(ncx, NCX('navMap')) + self.toc.to_ncx(navmap) + if len(self.pages) > 0: + plist = self.pages.to_ncx(ncx) + value = max(int(x) for x in xpath(plist, '//@value')) + maxpnum.attrib['content'] = unicode_type(value) + self._update_playorder(ncx) + return ncx + + def to_opf2(self, page_map=False): + """Produce OPF 2.0 representing the book's metadata and structure. + + Returns a dictionary in which the keys are MIME types and the values + are tuples of (default) filenames and lxml.etree element structures. + """ + results = {} + package = etree.Element(OPF('package'), + attrib={'version': '2.0', 'unique-identifier': self.uid.id}, + nsmap={None: OPF2_NS}) + self.metadata.to_opf2(package) + manifest = self.manifest.to_opf2(package) + spine = self.spine.to_opf2(package) + self.guide.to_opf2(package) + results[OPF_MIME] = ('content.opf', package) + id, href = self.manifest.generate('ncx', 'toc.ncx') + etree.SubElement(manifest, OPF('item'), id=id, href=href, + attrib={'media-type': NCX_MIME}) + spine.attrib['toc'] = id + results[NCX_MIME] = (href, self._to_ncx()) + if page_map and len(self.pages) > 0: + id, href = self.manifest.generate('page-map', 'page-map.xml') + etree.SubElement(manifest, OPF('item'), id=id, href=href, + attrib={'media-type': PAGE_MAP_MIME}) + spine.attrib['page-map'] = id + results[PAGE_MAP_MIME] = (href, self.pages.to_page_map()) + if self.spine.page_progression_direction in {'ltr', 'rtl'}: + spine.attrib['page-progression-direction'] = self.spine.page_progression_direction + return results + + +def rel_href(base_href, href): + """Convert the URL provided in :param:`href` to a URL relative to the URL + in :param:`base_href` """ + if urlparse(href).scheme: + return href + if '/' not in base_href: + return href + base = list(filter(lambda x: x and x != '.', os.path.dirname(os.path.normpath(base_href)).replace(os.sep, '/').split('/'))) + while True: + try: + idx = base.index('..') + except ValueError: + break + if idx > 0: + del base[idx-1:idx+1] + else: + break + if not base: + return href + target, frag = urldefrag(href) + target = target.split('/') + index = 0 + for index in range(min(len(base), len(target))): + if base[index] != target[index]: + break + else: + index += 1 + relhref = (['..'] * (len(base) - index)) + target[index:] + relhref = '/'.join(relhref) + if frag: + relhref = '#'.join((relhref, frag)) + return relhref diff --git a/ebook_converter/ebooks/oeb/normalize_css.py b/ebook_converter/ebooks/oeb/normalize_css.py new file mode 100644 index 0000000..c550bd4 --- /dev/null +++ b/ebook_converter/ebooks/oeb/normalize_css.py @@ -0,0 +1,437 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2013, Kovid Goyal ' + +import numbers +from functools import wraps + +from css_parser.css import PropertyValue +from css_parser import profile as cssprofiles, CSSParser +from tinycss.fonts3 import parse_font, serialize_font_family +from calibre.ebooks.oeb.base import css_text +from polyglot.builtins import iteritems, string_or_bytes, unicode_type, zip + +DEFAULTS = {'azimuth': 'center', 'background-attachment': 'scroll', # {{{ + 'background-color': 'transparent', 'background-image': 'none', + 'background-position': '0% 0%', 'background-repeat': 'repeat', + 'border-bottom-color': 'currentColor', 'border-bottom-style': + 'none', 'border-bottom-width': 'medium', 'border-collapse': + 'separate', 'border-left-color': 'currentColor', + 'border-left-style': 'none', 'border-left-width': 'medium', + 'border-right-color': 'currentColor', 'border-right-style': 'none', + 'border-right-width': 'medium', 'border-spacing': 0, + 'border-top-color': 'currentColor', 'border-top-style': 'none', + 'border-top-width': 'medium', 'bottom': 'auto', 'caption-side': + 'top', 'clear': 'none', 'clip': 'auto', 'color': 'black', + 'content': 'normal', 'counter-increment': 'none', 'counter-reset': + 'none', 'cue-after': 'none', 'cue-before': 'none', 'cursor': + 'auto', 'direction': 'ltr', 'display': 'inline', 'elevation': + 'level', 'empty-cells': 'show', 'float': 'none', 'font-family': + 'serif', 'font-size': 'medium', 'font-stretch': 'normal', 'font-style': 'normal', + 'font-variant': 'normal', 'font-weight': 'normal', 'height': + 'auto', 'left': 'auto', 'letter-spacing': 'normal', 'line-height': + 'normal', 'list-style-image': 'none', 'list-style-position': + 'outside', 'list-style-type': 'disc', 'margin-bottom': 0, + 'margin-left': 0, 'margin-right': 0, 'margin-top': 0, 'max-height': + 'none', 'max-width': 'none', 'min-height': 0, 'min-width': 0, + 'orphans': '2', 'outline-color': 'invert', 'outline-style': 'none', + 'outline-width': 'medium', 'overflow': 'visible', 'padding-bottom': + 0, 'padding-left': 0, 'padding-right': 0, 'padding-top': 0, + 'page-break-after': 'auto', 'page-break-before': 'auto', + 'page-break-inside': 'auto', 'pause-after': 0, 'pause-before': 0, + 'pitch': 'medium', 'pitch-range': '50', 'play-during': 'auto', + 'position': 'static', 'quotes': u"'“' '”' '‘' '’'", 'richness': + '50', 'right': 'auto', 'speak': 'normal', 'speak-header': 'once', + 'speak-numeral': 'continuous', 'speak-punctuation': 'none', + 'speech-rate': 'medium', 'stress': '50', 'table-layout': 'auto', + 'text-align': 'auto', 'text-decoration': 'none', 'text-indent': 0, + 'text-shadow': 'none', 'text-transform': 'none', 'top': 'auto', + 'unicode-bidi': 'normal', 'vertical-align': 'baseline', + 'visibility': 'visible', 'voice-family': 'default', 'volume': + 'medium', 'white-space': 'normal', 'widows': '2', 'width': 'auto', + 'word-spacing': 'normal', 'z-index': 'auto'} +# }}} + +EDGES = ('top', 'right', 'bottom', 'left') +BORDER_PROPS = ('color', 'style', 'width') + + +def normalize_edge(name, cssvalue): + style = {} + if isinstance(cssvalue, PropertyValue): + primitives = [css_text(v) for v in cssvalue] + else: + primitives = [css_text(cssvalue)] + if len(primitives) == 1: + value, = primitives + values = (value, value, value, value) + elif len(primitives) == 2: + vert, horiz = primitives + values = (vert, horiz, vert, horiz) + elif len(primitives) == 3: + top, horiz, bottom = primitives + values = (top, horiz, bottom, horiz) + else: + values = primitives[:4] + if '-' in name: + l, _, r = name.partition('-') + for edge, value in zip(EDGES, values): + style['%s-%s-%s' % (l, edge, r)] = value + else: + for edge, value in zip(EDGES, values): + style['%s-%s' % (name, edge)] = value + return style + + +def simple_normalizer(prefix, names, check_inherit=True): + composition = tuple('%s-%s' %(prefix, n) for n in names) + + @wraps(normalize_simple_composition) + def wrapper(name, cssvalue): + return normalize_simple_composition(name, cssvalue, composition, check_inherit=check_inherit) + return wrapper + + +def normalize_simple_composition(name, cssvalue, composition, check_inherit=True): + if check_inherit and css_text(cssvalue) == 'inherit': + style = {k:'inherit' for k in composition} + else: + style = {k:DEFAULTS[k] for k in composition} + try: + primitives = [css_text(v) for v in cssvalue] + except TypeError: + primitives = [css_text(cssvalue)] + while primitives: + value = primitives.pop() + for key in composition: + if cssprofiles.validate(key, value): + style[key] = value + break + return style + + +font_composition = ('font-style', 'font-variant', 'font-weight', 'font-size', 'line-height', 'font-family') + + +def normalize_font(cssvalue, font_family_as_list=False): + # See https://developer.mozilla.org/en-US/docs/Web/CSS/font + composition = font_composition + val = css_text(cssvalue) + if val == 'inherit': + ans = {k:'inherit' for k in composition} + elif val in {'caption', 'icon', 'menu', 'message-box', 'small-caption', 'status-bar'}: + ans = {k:DEFAULTS[k] for k in composition} + else: + ans = {k:DEFAULTS[k] for k in composition} + ans.update(parse_font(val)) + if font_family_as_list: + if isinstance(ans['font-family'], string_or_bytes): + ans['font-family'] = [x.strip() for x in ans['font-family'].split(',')] + else: + if not isinstance(ans['font-family'], string_or_bytes): + ans['font-family'] = serialize_font_family(ans['font-family']) + return ans + + +def normalize_border(name, cssvalue): + style = normalizers['border-' + EDGES[0]]('border-' + EDGES[0], cssvalue) + vals = style.copy() + for edge in EDGES[1:]: + style.update({k.replace(EDGES[0], edge):v for k, v in iteritems(vals)}) + return style + + +normalizers = { + 'list-style': simple_normalizer('list-style', ('type', 'position', 'image')), + 'font': lambda prop, v: normalize_font(v), + 'border': normalize_border, +} + +for x in ('margin', 'padding', 'border-style', 'border-width', 'border-color'): + normalizers[x] = normalize_edge + +for x in EDGES: + name = 'border-' + x + normalizers[name] = simple_normalizer(name, BORDER_PROPS, check_inherit=False) + +SHORTHAND_DEFAULTS = { + 'margin': '0', 'padding': '0', 'border-style': 'none', 'border-width': '0', 'border-color': 'currentColor', + 'border':'none', 'border-left': 'none', 'border-right':'none', 'border-top': 'none', 'border-bottom': 'none', + 'list-style': 'inherit', 'font': 'inherit', +} + +_safe_parser = None + + +def safe_parser(): + global _safe_parser + if _safe_parser is None: + import logging + _safe_parser = CSSParser(loglevel=logging.CRITICAL, validate=False) + return _safe_parser + + +def normalize_filter_css(props): + ans = set() + p = safe_parser() + for prop in props: + n = normalizers.get(prop, None) + ans.add(prop) + if n is not None and prop in SHORTHAND_DEFAULTS: + dec = p.parseStyle('%s: %s' % (prop, SHORTHAND_DEFAULTS[prop])) + cssvalue = dec.getPropertyCSSValue(dec.item(0)) + ans |= set(n(prop, cssvalue)) + return ans + + +def condense_edge(vals): + edges = {x.name.rpartition('-')[-1]:x.value for x in vals} + if len(edges) != 4 or set(edges) != {'left', 'top', 'right', 'bottom'}: + return + ce = {} + for (x, y) in [('left', 'right'), ('top', 'bottom')]: + if edges[x] == edges[y]: + ce[x] = edges[x] + else: + ce[x], ce[y] = edges[x], edges[y] + if len(ce) == 4: + return ' '.join(ce[x] for x in ('top', 'right', 'bottom', 'left')) + if len(ce) == 3: + if 'right' in ce: + return ' '.join(ce[x] for x in ('top', 'right', 'top', 'left')) + return ' '.join(ce[x] for x in ('top', 'left', 'bottom')) + if len(ce) == 2: + if ce['top'] == ce['left']: + return ce['top'] + return ' '.join(ce[x] for x in ('top', 'left')) + + +def simple_condenser(prefix, func): + @wraps(func) + def condense_simple(style, props): + cp = func(props) + if cp is not None: + for prop in props: + style.removeProperty(prop.name) + style.setProperty(prefix, cp) + return condense_simple + + +def condense_border(style, props): + prop_map = {p.name:p for p in props} + edge_vals = [] + for edge in EDGES: + name = 'border-%s' % edge + vals = [] + for prop in BORDER_PROPS: + x = prop_map.get('%s-%s' % (name, prop), None) + if x is not None: + vals.append(x) + if len(vals) == 3: + for prop in vals: + style.removeProperty(prop.name) + style.setProperty(name, ' '.join(x.value for x in vals)) + prop_map[name] = style.getProperty(name) + x = prop_map.get(name, None) + if x is not None: + edge_vals.append(x) + if len(edge_vals) == 4 and len({x.value for x in edge_vals}) == 1: + for prop in edge_vals: + style.removeProperty(prop.name) + style.setProperty('border', edge_vals[0].value) + + +condensers = {'margin': simple_condenser('margin', condense_edge), 'padding': simple_condenser('padding', condense_edge), 'border': condense_border} + + +def condense_rule(style): + expanded = {'margin-':[], 'padding-':[], 'border-':[]} + for prop in style.getProperties(): + for x in expanded: + if prop.name and prop.name.startswith(x): + expanded[x].append(prop) + break + for prefix, vals in iteritems(expanded): + if len(vals) > 1 and {x.priority for x in vals} == {''}: + condensers[prefix[:-1]](style, vals) + + +def condense_sheet(sheet): + for rule in sheet.cssRules: + if rule.type == rule.STYLE_RULE: + condense_rule(rule.style) + + +def test_normalization(return_tests=False): # {{{ + import unittest + from css_parser import parseStyle + from itertools import product + + class TestNormalization(unittest.TestCase): + longMessage = True + maxDiff = None + + def test_font_normalization(self): + def font_dict(expected): + ans = {k:DEFAULTS[k] for k in font_composition} if expected else {} + ans.update(expected) + return ans + + for raw, expected in iteritems({ + 'some_font': {'font-family':'some_font'}, 'inherit':{k:'inherit' for k in font_composition}, + '1.2pt/1.4 A_Font': {'font-family':'A_Font', 'font-size':'1.2pt', 'line-height':'1.4'}, + 'bad font': {'font-family':'"bad font"'}, '10% serif': {'font-family':'serif', 'font-size':'10%'}, + '12px "My Font", serif': {'font-family':'"My Font", serif', 'font-size': '12px'}, + 'normal 0.6em/135% arial,sans-serif': {'font-family': 'arial, sans-serif', 'font-size': '0.6em', 'line-height':'135%', 'font-style':'normal'}, + 'bold italic large serif': {'font-family':'serif', 'font-weight':'bold', 'font-style':'italic', 'font-size':'large'}, + 'bold italic small-caps larger/normal serif': + {'font-family':'serif', 'font-weight':'bold', 'font-style':'italic', 'font-size':'larger', + 'line-height':'normal', 'font-variant':'small-caps'}, + '2em A B': {'font-family': '"A B"', 'font-size': '2em'}, + }): + val = tuple(parseStyle('font: %s' % raw, validate=False))[0].cssValue + style = normalizers['font']('font', val) + self.assertDictEqual(font_dict(expected), style, raw) + + def test_border_normalization(self): + def border_edge_dict(expected, edge='right'): + ans = {'border-%s-%s' % (edge, x): DEFAULTS['border-%s-%s' % (edge, x)] for x in ('style', 'width', 'color')} + for x, v in iteritems(expected): + ans['border-%s-%s' % (edge, x)] = v + return ans + + def border_dict(expected): + ans = {} + for edge in EDGES: + ans.update(border_edge_dict(expected, edge)) + return ans + + def border_val_dict(expected, val='color'): + ans = {'border-%s-%s' % (edge, val): DEFAULTS['border-%s-%s' % (edge, val)] for edge in EDGES} + for edge in EDGES: + ans['border-%s-%s' % (edge, val)] = expected + return ans + + for raw, expected in iteritems({ + 'solid 1px red': {'color':'red', 'width':'1px', 'style':'solid'}, + '1px': {'width': '1px'}, '#aaa': {'color': '#aaa'}, + '2em groove': {'width':'2em', 'style':'groove'}, + }): + for edge in EDGES: + br = 'border-%s' % edge + val = tuple(parseStyle('%s: %s' % (br, raw), validate=False))[0].cssValue + self.assertDictEqual(border_edge_dict(expected, edge), normalizers[br](br, val)) + + for raw, expected in iteritems({ + 'solid 1px red': {'color':'red', 'width':'1px', 'style':'solid'}, + '1px': {'width': '1px'}, '#aaa': {'color': '#aaa'}, + 'thin groove': {'width':'thin', 'style':'groove'}, + }): + val = tuple(parseStyle('%s: %s' % ('border', raw), validate=False))[0].cssValue + self.assertDictEqual(border_dict(expected), normalizers['border']('border', val)) + + for name, val in iteritems({ + 'width': '10%', 'color': 'rgb(0, 1, 1)', 'style': 'double', + }): + cval = tuple(parseStyle('border-%s: %s' % (name, val), validate=False))[0].cssValue + self.assertDictEqual(border_val_dict(val, name), normalizers['border-'+name]('border-'+name, cval)) + + def test_edge_normalization(self): + def edge_dict(prefix, expected): + return {'%s-%s' % (prefix, edge) : x for edge, x in zip(EDGES, expected)} + for raw, expected in iteritems({ + '2px': ('2px', '2px', '2px', '2px'), + '1em 2em': ('1em', '2em', '1em', '2em'), + '1em 2em 3em': ('1em', '2em', '3em', '2em'), + '1 2 3 4': ('1', '2', '3', '4'), + }): + for prefix in ('margin', 'padding'): + cval = tuple(parseStyle('%s: %s' % (prefix, raw), validate=False))[0].cssValue + self.assertDictEqual(edge_dict(prefix, expected), normalizers[prefix](prefix, cval)) + + def test_list_style_normalization(self): + def ls_dict(expected): + ans = {'list-style-%s' % x : DEFAULTS['list-style-%s' % x] for x in ('type', 'image', 'position')} + for k, v in iteritems(expected): + ans['list-style-%s' % k] = v + return ans + for raw, expected in iteritems({ + 'url(http://www.example.com/images/list.png)': {'image': 'url(http://www.example.com/images/list.png)'}, + 'inside square': {'position':'inside', 'type':'square'}, + 'upper-roman url(img) outside': {'position':'outside', 'type':'upper-roman', 'image':'url(img)'}, + }): + cval = tuple(parseStyle('list-style: %s' % raw, validate=False))[0].cssValue + self.assertDictEqual(ls_dict(expected), normalizers['list-style']('list-style', cval)) + + def test_filter_css_normalization(self): + ae = self.assertEqual + ae({'font'} | set(font_composition), normalize_filter_css({'font'})) + for p in ('margin', 'padding'): + ae({p} | {p + '-' + x for x in EDGES}, normalize_filter_css({p})) + bvals = {'border-%s-%s' % (edge, x) for edge in EDGES for x in BORDER_PROPS} + ae(bvals | {'border'}, normalize_filter_css({'border'})) + for x in BORDER_PROPS: + sbvals = {'border-%s-%s' % (e, x) for e in EDGES} + ae(sbvals | {'border-%s' % x}, normalize_filter_css({'border-%s' % x})) + for e in EDGES: + sbvals = {'border-%s-%s' % (e, x) for x in BORDER_PROPS} + ae(sbvals | {'border-%s' % e}, normalize_filter_css({'border-%s' % e})) + ae({'list-style', 'list-style-image', 'list-style-type', 'list-style-position'}, normalize_filter_css({'list-style'})) + + def test_edge_condensation(self): + for s, v in iteritems({ + (1, 1, 3) : None, + (1, 2, 3, 4) : '2pt 3pt 4pt 1pt', + (1, 2, 3, 2) : '2pt 3pt 2pt 1pt', + (1, 2, 1, 3) : '2pt 1pt 3pt', + (1, 2, 1, 2) : '2pt 1pt', + (1, 1, 1, 1) : '1pt', + ('2%', '2%', '2%', '2%') : '2%', + tuple('0 0 0 0'.split()) : '0', + }): + for prefix in ('margin', 'padding'): + css = {'%s-%s' % (prefix, x) : unicode_type(y)+'pt' if isinstance(y, numbers.Number) else y + for x, y in zip(('left', 'top', 'right', 'bottom'), s)} + css = '; '.join(('%s:%s' % (k, v) for k, v in iteritems(css))) + style = parseStyle(css) + condense_rule(style) + val = getattr(style.getProperty(prefix), 'value', None) + self.assertEqual(v, val) + if val is not None: + for edge in EDGES: + self.assertFalse(getattr(style.getProperty('%s-%s' % (prefix, edge)), 'value', None)) + + def test_border_condensation(self): + vals = 'red solid 5px' + css = '; '.join('border-%s-%s: %s' % (edge, p, v) for edge in EDGES for p, v in zip(BORDER_PROPS, vals.split())) + style = parseStyle(css) + condense_rule(style) + for e, p in product(EDGES, BORDER_PROPS): + self.assertFalse(style.getProperty('border-%s-%s' % (e, p))) + self.assertFalse(style.getProperty('border-%s' % e)) + self.assertFalse(style.getProperty('border-%s' % p)) + self.assertEqual(style.getProperty('border').value, vals) + css = '; '.join('border-%s-%s: %s' % (edge, p, v) for edge in ('top',) for p, v in zip(BORDER_PROPS, vals.split())) + style = parseStyle(css) + condense_rule(style) + self.assertEqual(css_text(style), 'border-top: %s' % vals) + css += ';' + '; '.join('border-%s-%s: %s' % (edge, p, v) for edge in ('right', 'left', 'bottom') for p, v in + zip(BORDER_PROPS, vals.replace('red', 'green').split())) + style = parseStyle(css) + condense_rule(style) + self.assertEqual(len(style.getProperties()), 4) + self.assertEqual(style.getProperty('border-top').value, vals) + self.assertEqual(style.getProperty('border-left').value, vals.replace('red', 'green')) + + tests = unittest.defaultTestLoader.loadTestsFromTestCase(TestNormalization) + if return_tests: + return tests + unittest.TextTestRunner(verbosity=4).run(tests) +# }}} + + +if __name__ == '__main__': + test_normalization() diff --git a/ebook_converter/ebooks/oeb/parse_utils.py b/ebook_converter/ebooks/oeb/parse_utils.py new file mode 100644 index 0000000..0db0bc7 --- /dev/null +++ b/ebook_converter/ebooks/oeb/parse_utils.py @@ -0,0 +1,389 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2011, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import re + +from lxml import etree, html + +from calibre import xml_replace_entities, force_unicode +from calibre.utils.xml_parse import safe_xml_fromstring +from calibre.constants import filesystem_encoding +from calibre.ebooks.chardet import xml_to_unicode, strip_encoding_declarations +from polyglot.builtins import iteritems, itervalues, unicode_type, string_or_bytes, map + +RECOVER_PARSER = etree.XMLParser(recover=True, no_network=True, resolve_entities=False) +XHTML_NS = 'http://www.w3.org/1999/xhtml' +XMLNS_NS = 'http://www.w3.org/2000/xmlns/' + + +class NotHTML(Exception): + + def __init__(self, root_tag): + Exception.__init__(self, 'Data is not HTML') + self.root_tag = root_tag + + +def barename(name): + return name.rpartition('}')[-1] + + +def namespace(name): + return name.rpartition('}')[0][1:] + + +def XHTML(name): + return '{%s}%s' % (XHTML_NS, name) + + +def xpath(elem, expr): + return elem.xpath(expr, namespaces={'h':XHTML_NS}) + + +def XPath(expr): + return etree.XPath(expr, namespaces={'h':XHTML_NS}) + + +META_XP = XPath('/h:html/h:head/h:meta[@http-equiv="Content-Type"]') + + +def merge_multiple_html_heads_and_bodies(root, log=None): + heads, bodies = xpath(root, '//h:head'), xpath(root, '//h:body') + if not (len(heads) > 1 or len(bodies) > 1): + return root + for child in root: + root.remove(child) + head = root.makeelement(XHTML('head')) + body = root.makeelement(XHTML('body')) + for h in heads: + for x in h: + head.append(x) + for b in bodies: + for x in b: + body.append(x) + tuple(map(root.append, (head, body))) + if log is not None: + log.warn('Merging multiple and sections') + return root + + +def clone_element(elem, nsmap={}, in_context=True): + if in_context: + maker = elem.getroottree().getroot().makeelement + else: + maker = etree.Element + nelem = maker(elem.tag, attrib=elem.attrib, + nsmap=nsmap) + nelem.text, nelem.tail = elem.text, elem.tail + nelem.extend(elem) + return nelem + + +def node_depth(node): + ans = 0 + p = node.getparent() + while p is not None: + ans += 1 + p = p.getparent() + return ans + + +def html5_parse(data, max_nesting_depth=100): + from html5_parser import parse + from calibre.utils.cleantext import clean_xml_chars + data = parse(clean_xml_chars(data), maybe_xhtml=True, keep_doctype=False, sanitize_names=True) + # Check that the asinine HTML 5 algorithm did not result in a tree with + # insane nesting depths + for x in data.iterdescendants(): + if isinstance(x.tag, string_or_bytes) and not len(x): # Leaf node + depth = node_depth(x) + if depth > max_nesting_depth: + raise ValueError('HTML 5 parsing resulted in a tree with nesting' + ' depth > %d'%max_nesting_depth) + return data + + +def _html4_parse(data): + data = html.fromstring(data) + data.attrib.pop('xmlns', None) + for elem in data.iter(tag=etree.Comment): + if elem.text: + elem.text = elem.text.strip('-') + data = etree.tostring(data, encoding='unicode') + + data = safe_xml_fromstring(data) + return data + + +def clean_word_doc(data, log): + prefixes = [] + for match in re.finditer(r'xmlns:(\S+?)=".*?microsoft.*?"', data): + prefixes.append(match.group(1)) + if prefixes: + log.warn('Found microsoft markup, cleaning...') + # Remove empty tags as they are not rendered by browsers + # but can become renderable HTML tags like

if the + # document is parsed by an HTML parser + pat = re.compile( + r'<(%s):([a-zA-Z0-9]+)[^>/]*?>'%('|'.join(prefixes)), + re.DOTALL) + data = pat.sub('', data) + pat = re.compile( + r'<(%s):([a-zA-Z0-9]+)[^>/]*?/>'%('|'.join(prefixes))) + data = pat.sub('', data) + return data + + +def ensure_namespace_prefixes(node, nsmap): + namespace_uris = frozenset(itervalues(nsmap)) + fnsmap = {k:v for k, v in iteritems(node.nsmap) if v not in namespace_uris} + fnsmap.update(nsmap) + if fnsmap != dict(node.nsmap): + node = clone_element(node, nsmap=fnsmap, in_context=False) + return node + + +class HTML5Doc(ValueError): + pass + + +def check_for_html5(prefix, root): + if re.search(r'', prefix, re.IGNORECASE) is not None: + if root.xpath('//svg'): + raise HTML5Doc('This document appears to be un-namespaced HTML 5, should be parsed by the HTML 5 parser') + + +def parse_html(data, log=None, decoder=None, preprocessor=None, + filename='', non_html_file_tags=frozenset()): + if log is None: + from calibre.utils.logging import default_log + log = default_log + + filename = force_unicode(filename, enc=filesystem_encoding) + + if not isinstance(data, unicode_type): + if decoder is not None: + data = decoder(data) + else: + data = xml_to_unicode(data)[0] + + data = strip_encoding_declarations(data) + # Remove DOCTYPE declaration as it messes up parsing + # In particular, it causes tostring to insert xmlns + # declarations, which messes up the coercing logic + pre = '' + idx = data.find(' -1: + pre = data[:idx] + data = data[idx:] + if ']+HTML\s+4.0[^.]+>', pre) is not None + # Process private entities + user_entities = {} + for match in re.finditer(r']+)', pre): + val = match.group(2) + if val.startswith('"') and val.endswith('"'): + val = val[1:-1] + user_entities[match.group(1)] = val + if user_entities: + pat = re.compile(r'&(%s);'%('|'.join(list(user_entities.keys())))) + data = pat.sub(lambda m:user_entities[m.group(1)], data) + + if preprocessor is not None: + data = preprocessor(data) + + # There could be null bytes in data if it had � entities in it + data = data.replace('\0', '') + data = raw = clean_word_doc(data, log) + + # Try with more & more drastic measures to parse + try: + data = safe_xml_fromstring(data, recover=False) + check_for_html5(pre, data) + except (HTML5Doc, etree.XMLSyntaxError): + log.debug('Initial parse failed, using more' + ' forgiving parsers') + raw = data = xml_replace_entities(raw) + try: + data = safe_xml_fromstring(data, recover=False) + check_for_html5(pre, data) + except (HTML5Doc, etree.XMLSyntaxError): + log.debug('Parsing %s as HTML' % filename) + data = raw + try: + data = html5_parse(data) + except Exception: + log.exception( + 'HTML 5 parsing failed, falling back to older parsers') + data = _html4_parse(data) + + if has_html4_doctype or data.tag == 'HTML' or (len(data) and (data[-1].get('LANG') or data[-1].get('DIR'))): + # Lower case all tag and attribute names + data.tag = data.tag.lower() + for x in data.iterdescendants(): + try: + x.tag = x.tag.lower() + for key, val in list(iteritems(x.attrib)): + del x.attrib[key] + key = key.lower() + x.attrib[key] = val + except: + pass + + if barename(data.tag) != 'html': + if barename(data.tag) in non_html_file_tags: + raise NotHTML(data.tag) + log.warn('File %r does not appear to be (X)HTML'%filename) + nroot = safe_xml_fromstring('') + has_body = False + for child in list(data): + if isinstance(child.tag, (unicode_type, bytes)) and barename(child.tag) == 'body': + has_body = True + break + parent = nroot + if not has_body: + log.warn('File %r appears to be a HTML fragment'%filename) + nroot = safe_xml_fromstring('') + parent = nroot[0] + for child in list(data.iter()): + oparent = child.getparent() + if oparent is not None: + oparent.remove(child) + parent.append(child) + data = nroot + + # Force into the XHTML namespace + if not namespace(data.tag): + log.warn('Forcing', filename, 'into XHTML namespace') + data.attrib['xmlns'] = XHTML_NS + data = etree.tostring(data, encoding='unicode') + + try: + data = safe_xml_fromstring(data, recover=False) + except: + data = data.replace(':=', '=').replace(':>', '>') + data = data.replace('', '') + try: + data = safe_xml_fromstring(data, recover=False) + except etree.XMLSyntaxError: + log.warn('Stripping comments from %s'% + filename) + data = re.compile(r'', re.DOTALL).sub('', + data) + data = data.replace( + "", + '') + data = data.replace("", '') + try: + data = safe_xml_fromstring(data) + except etree.XMLSyntaxError: + log.warn('Stripping meta tags from %s'% filename) + data = re.sub(r']+?>', '', data) + data = safe_xml_fromstring(data) + elif namespace(data.tag) != XHTML_NS: + # OEB_DOC_NS, but possibly others + ns = namespace(data.tag) + attrib = dict(data.attrib) + nroot = etree.Element(XHTML('html'), + nsmap={None: XHTML_NS}, attrib=attrib) + for elem in data.iterdescendants(): + if isinstance(elem.tag, string_or_bytes) and \ + namespace(elem.tag) == ns: + elem.tag = XHTML(barename(elem.tag)) + for elem in data: + nroot.append(elem) + data = nroot + + # Remove non default prefixes referring to the XHTML namespace + data = ensure_namespace_prefixes(data, {None: XHTML_NS}) + + data = merge_multiple_html_heads_and_bodies(data, log) + # Ensure has a + head = xpath(data, '/h:html/h:head') + head = head[0] if head else None + if head is None: + log.warn('File %s missing element' % filename) + head = etree.Element(XHTML('head')) + data.insert(0, head) + title = etree.SubElement(head, XHTML('title')) + title.text = _('Unknown') + elif not xpath(data, '/h:html/h:head/h:title'): + title = etree.SubElement(head, XHTML('title')) + title.text = _('Unknown') + # Ensure is not empty + title = xpath(data, '/h:html/h:head/h:title')[0] + if not title.text or not title.text.strip(): + title.text = _('Unknown') + # Remove any encoding-specifying <meta/> elements + for meta in META_XP(data): + meta.getparent().remove(meta) + meta = etree.SubElement(head, XHTML('meta'), + attrib={'http-equiv': 'Content-Type'}) + meta.set('content', 'text/html; charset=utf-8') # Ensure content is second attribute + + # Ensure has a <body/> + if not xpath(data, '/h:html/h:body'): + body = xpath(data, '//h:body') + if body: + body = body[0] + body.getparent().remove(body) + data.append(body) + else: + log.warn('File %s missing <body/> element' % filename) + etree.SubElement(data, XHTML('body')) + + # Remove microsoft office markup + r = [x for x in data.iterdescendants(etree.Element) if 'microsoft-com' in x.tag] + for x in r: + x.tag = XHTML('span') + + def remove_elem(a): + p = a.getparent() + idx = p.index(a) -1 + p.remove(a) + if a.tail: + if idx < 0: + if p.text is None: + p.text = '' + p.text += a.tail + else: + if p[idx].tail is None: + p[idx].tail = '' + p[idx].tail += a.tail + + # Remove hyperlinks with no content as they cause rendering + # artifacts in browser based renderers + # Also remove empty <b>, <u> and <i> tags + for a in xpath(data, '//h:a[@href]|//h:i|//h:b|//h:u'): + if a.get('id', None) is None and a.get('name', None) is None \ + and len(a) == 0 and not a.text: + remove_elem(a) + + # Convert <br>s with content into paragraphs as ADE can't handle + # them + for br in xpath(data, '//h:br'): + if len(br) > 0 or br.text: + br.tag = XHTML('div') + + # Remove any stray text in the <head> section and format it nicely + data.text = '\n ' + head = xpath(data, '//h:head') + if head: + head = head[0] + head.text = '\n ' + head.tail = '\n ' + for child in head: + child.tail = '\n ' + child.tail = '\n ' + + return data diff --git a/ebook_converter/ebooks/oeb/polish/__init__.py b/ebook_converter/ebooks/oeb/polish/__init__.py new file mode 100644 index 0000000..64be92c --- /dev/null +++ b/ebook_converter/ebooks/oeb/polish/__init__.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:fdm=marker:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>' +__docformat__ = 'restructuredtext en' + + + diff --git a/ebook_converter/ebooks/oeb/polish/container.py b/ebook_converter/ebooks/oeb/polish/container.py new file mode 100644 index 0000000..aba74c2 --- /dev/null +++ b/ebook_converter/ebooks/oeb/polish/container.py @@ -0,0 +1,1552 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:fdm=marker:ai +# License: GPLv3 Copyright: 2013, Kovid Goyal <kovid at kovidgoyal.net> +from __future__ import absolute_import, division, print_function, unicode_literals + +import errno +import hashlib +import logging +import os +import re +import shutil +import sys +import time +import unicodedata +import uuid +from collections import defaultdict +from io import BytesIO +from itertools import count + +from css_parser import getUrls, replaceUrls + +from calibre import CurrentDir, walk +from calibre.constants import iswindows +from calibre.customize.ui import plugin_for_input_format, plugin_for_output_format +from calibre.ebooks import escape_xpath_attr +from calibre.ebooks.chardet import xml_to_unicode +from calibre.ebooks.conversion.plugins.epub_input import ( + ADOBE_OBFUSCATION, IDPF_OBFUSCATION, decrypt_font_data +) +from calibre.ebooks.conversion.preprocess import ( + CSSPreProcessor as cssp, HTMLPreProcessor +) +from calibre.ebooks.metadata.opf3 import ( + CALIBRE_PREFIX, ensure_prefix, items_with_property, read_prefixes +) +from calibre.ebooks.metadata.utils import parse_opf_version +from calibre.ebooks.mobi import MobiError +from calibre.ebooks.mobi.reader.headers import MetadataHeader +from calibre.ebooks.mobi.tweak import set_cover +from calibre.ebooks.oeb.base import ( + DC11_NS, OEB_DOCS, OEB_STYLES, OPF, OPF2_NS, Manifest, itercsslinks, iterlinks, + rewrite_links, serialize, urlquote, urlunquote +) +from calibre.ebooks.oeb.parse_utils import NotHTML, parse_html +from calibre.ebooks.oeb.polish.errors import DRMError, InvalidBook +from calibre.ebooks.oeb.polish.parsing import parse as parse_html_tweak +from calibre.ebooks.oeb.polish.utils import ( + CommentFinder, PositionFinder, guess_type, parse_css +) +from calibre.ptempfile import PersistentTemporaryDirectory, PersistentTemporaryFile +from calibre.utils.filenames import hardlink_file, nlinks_file +from calibre.utils.ipc.simple_worker import WorkerError, fork_job +from calibre.utils.logging import default_log +from calibre.utils.xml_parse import safe_xml_fromstring +from calibre.utils.zipfile import ZipFile +from polyglot.builtins import iteritems, map, unicode_type, zip +from polyglot.urllib import urlparse + +exists, join, relpath = os.path.exists, os.path.join, os.path.relpath + +OEB_FONTS = {guess_type('a.ttf'), guess_type('b.otf'), guess_type('a.woff'), 'application/x-font-ttf', 'application/x-font-otf', 'application/font-sfnt'} +OPF_NAMESPACES = {'opf':OPF2_NS, 'dc':DC11_NS} +null = object() + + +class CSSPreProcessor(cssp): + + def __call__(self, data): + return self.MS_PAT.sub(self.ms_sub, data) + + +def clone_dir(src, dest): + ' Clone a directory using hard links for the files, dest must already exist ' + for x in os.listdir(src): + dpath = os.path.join(dest, x) + spath = os.path.join(src, x) + if os.path.isdir(spath): + os.mkdir(dpath) + clone_dir(spath, dpath) + else: + try: + hardlink_file(spath, dpath) + except: + shutil.copy2(spath, dpath) + + +def clone_container(container, dest_dir): + ' Efficiently clone a container using hard links ' + dest_dir = os.path.abspath(os.path.realpath(dest_dir)) + clone_data = container.clone_data(dest_dir) + cls = type(container) + if cls is Container: + return cls(None, None, container.log, clone_data=clone_data) + return cls(None, container.log, clone_data=clone_data) + + +def name_to_abspath(name, root): + return os.path.abspath(join(root, *name.split('/'))) + + +def abspath_to_name(path, root): + return relpath(os.path.abspath(path), root).replace(os.sep, '/') + + +def name_to_href(name, root, base=None, quote=urlquote): + fullpath = name_to_abspath(name, root) + basepath = root if base is None else os.path.dirname(name_to_abspath(base, root)) + path = relpath(fullpath, basepath).replace(os.sep, '/') + return quote(path) + + +def href_to_name(href, root, base=None): + base = root if base is None else os.path.dirname(name_to_abspath(base, root)) + try: + purl = urlparse(href) + except ValueError: + return None + if purl.scheme or not purl.path: + return None + href = urlunquote(purl.path) + if iswindows and ':' in href: + # path manipulations on windows fail for paths with : in them, so we + # assume all such paths are invalid/absolute paths. + return None + fullpath = os.path.join(base, *href.split('/')) + return unicodedata.normalize('NFC', abspath_to_name(fullpath, root)) + + +class ContainerBase(object): # {{{ + ''' + A base class that implements just the parsing methods. Useful to create + virtual containers for testing. + ''' + + #: The mode used to parse HTML and CSS (polishing uses tweak_mode=False and the editor uses tweak_mode=True) + tweak_mode = False + + def __init__(self, log): + self.log = log + self.parsed_cache = {} + self.mime_map = {} + self.encoding_map = {} + self.html_preprocessor = HTMLPreProcessor() + self.css_preprocessor = CSSPreProcessor() + + def guess_type(self, name): + ' Return the expected mimetype for the specified file name based on its extension. ' + # epubcheck complains if the mimetype for text documents is set to + # text/html in EPUB 2 books. Sigh. + ans = guess_type(name) + if ans == 'text/html': + ans = 'application/xhtml+xml' + if ans in {'application/x-font-truetype', 'application/vnd.ms-opentype'}: + opfversion = self.opf_version_parsed[:2] + if opfversion > (3, 0): + return 'application/font-sfnt' + if opfversion >= (3, 0): + # bloody epubcheck has recently decided it likes this mimetype + # for ttf files + return 'application/vnd.ms-opentype' + return ans + + def decode(self, data, normalize_to_nfc=True): + """ + Automatically decode ``data`` into a ``unicode`` object. + + :param normalize_to_nfc: Normalize returned unicode to the NFC normal form as is required by both the EPUB and AZW3 formats. + """ + def fix_data(d): + return d.replace('\r\n', '\n').replace('\r', '\n') + if isinstance(data, unicode_type): + return fix_data(data) + bom_enc = None + if data[:4] in {b'\0\0\xfe\xff', b'\xff\xfe\0\0'}: + bom_enc = {b'\0\0\xfe\xff':'utf-32-be', + b'\xff\xfe\0\0':'utf-32-le'}[data[:4]] + data = data[4:] + elif data[:2] in {b'\xff\xfe', b'\xfe\xff'}: + bom_enc = {b'\xff\xfe':'utf-16-le', b'\xfe\xff':'utf-16-be'}[data[:2]] + data = data[2:] + elif data[:3] == b'\xef\xbb\xbf': + bom_enc = 'utf-8' + data = data[3:] + if bom_enc is not None: + try: + self.used_encoding = bom_enc + return fix_data(data.decode(bom_enc)) + except UnicodeDecodeError: + pass + try: + self.used_encoding = 'utf-8' + return fix_data(data.decode('utf-8')) + except UnicodeDecodeError: + pass + data, self.used_encoding = xml_to_unicode(data) + if normalize_to_nfc: + data = unicodedata.normalize('NFC', data) + return fix_data(data) + + def parse_xml(self, data): + data, self.used_encoding = xml_to_unicode( + data, strip_encoding_pats=True, assume_utf8=True, resolve_entities=True) + data = unicodedata.normalize('NFC', data) + return safe_xml_fromstring(data) + + def parse_xhtml(self, data, fname='<string>', force_html5_parse=False): + if self.tweak_mode: + return parse_html_tweak(data, log=self.log, decoder=self.decode, force_html5_parse=force_html5_parse) + else: + try: + return parse_html( + data, log=self.log, decoder=self.decode, + preprocessor=self.html_preprocessor, filename=fname, + non_html_file_tags={'ncx'}) + except NotHTML: + return self.parse_xml(data) + + def parse_css(self, data, fname='<string>', is_declaration=False): + return parse_css(data, fname=fname, is_declaration=is_declaration, decode=self.decode, log_level=logging.WARNING, + css_preprocessor=(None if self.tweak_mode else self.css_preprocessor)) +# }}} + + +class Container(ContainerBase): # {{{ + + ''' + A container represents an Open E-Book as a directory full of files and an + opf file. There are two important concepts: + + * The root directory. This is the base of the e-book. All the e-books + files are inside this directory or in its sub-directories. + + * Names: These are paths to the books' files relative to the root + directory. They always contain POSIX separators and are unquoted. They + can be thought of as canonical identifiers for files in the book. + Most methods on the container object work with names. Names are always + in the NFC unicode normal form. + + * Clones: the container object supports efficient on-disk cloning, which is used to + implement checkpoints in the e-book editor. In order to make this work, you should + never access files on the filesystem directly. Instead, use :meth:`raw_data` or + :meth:`open` to read/write to component files in the book. + + When converting between hrefs and names use the methods provided by this + class, they assume all hrefs are quoted. + ''' + + #: The type of book (epub for EPUB files and azw3 for AZW3 files) + book_type = 'oeb' + #: If this container represents an unzipped book (a directory) + is_dir = False + + SUPPORTS_TITLEPAGES = True + SUPPORTS_FILENAMES = True + + def __init__(self, rootpath, opfpath, log, clone_data=None): + ContainerBase.__init__(self, log) + self.root = clone_data['root'] if clone_data is not None else os.path.abspath(rootpath) + + self.name_path_map = {} + self.dirtied = set() + self.pretty_print = set() + self.cloned = False + self.cache_names = ('parsed_cache', 'mime_map', 'name_path_map', 'encoding_map', 'dirtied', 'pretty_print') + self.href_to_name_cache = {} + + if clone_data is not None: + self.cloned = True + for x in ('name_path_map', 'opf_name', 'mime_map', 'pretty_print', 'encoding_map', 'tweak_mode'): + setattr(self, x, clone_data[x]) + self.opf_dir = os.path.dirname(self.name_path_map[self.opf_name]) + return + + # Map of relative paths with '/' separators from root of unzipped ePub + # to absolute paths on filesystem with os-specific separators + opfpath = os.path.abspath(os.path.realpath(opfpath)) + for dirpath, _dirnames, filenames in os.walk(self.root): + for f in filenames: + path = join(dirpath, f) + name = self.abspath_to_name(path) + self.name_path_map[name] = path + self.mime_map[name] = guess_type(path) + # Special case if we have stumbled onto the opf + if path == opfpath: + self.opf_name = name + self.opf_dir = os.path.dirname(path) + self.mime_map[name] = guess_type('a.opf') + + if not hasattr(self, 'opf_name'): + raise InvalidBook('Could not locate opf file: %r'%opfpath) + + # Update mime map with data from the OPF + self.refresh_mime_map() + + def refresh_mime_map(self): + for item in self.opf_xpath('//opf:manifest/opf:item[@href and @media-type]'): + href = item.get('href') + name = self.href_to_name(href, self.opf_name) + if name in self.mime_map and name != self.opf_name: + # some epubs include the opf in the manifest with an incorrect mime type + self.mime_map[name] = item.get('media-type') + + def data_for_clone(self, dest_dir=None): + dest_dir = dest_dir or self.root + return { + 'root': dest_dir, + 'opf_name': self.opf_name, + 'mime_map': self.mime_map.copy(), + 'pretty_print': set(self.pretty_print), + 'encoding_map': self.encoding_map.copy(), + 'tweak_mode': self.tweak_mode, + 'name_path_map': { + name:os.path.join(dest_dir, os.path.relpath(path, self.root)) + for name, path in iteritems(self.name_path_map)} + } + + def clone_data(self, dest_dir): + Container.commit(self, keep_parsed=True) + self.cloned = True + clone_dir(self.root, dest_dir) + return self.data_for_clone(dest_dir) + + def add_name_to_manifest(self, name, process_manifest_item=None): + ' Add an entry to the manifest for a file with the specified name. Returns the manifest id. ' + all_ids = {x.get('id') for x in self.opf_xpath('//*[@id]')} + c = 0 + item_id = 'id' + while item_id in all_ids: + c += 1 + item_id = 'id' + '%d'%c + manifest = self.opf_xpath('//opf:manifest')[0] + href = self.name_to_href(name, self.opf_name) + item = manifest.makeelement(OPF('item'), + id=item_id, href=href) + item.set('media-type', self.mime_map[name]) + self.insert_into_xml(manifest, item) + if process_manifest_item is not None: + process_manifest_item(item) + self.dirty(self.opf_name) + return item_id + + def manifest_has_name(self, name): + ''' Return True if the manifest has an entry corresponding to name ''' + all_names = {self.href_to_name(x.get('href'), self.opf_name) for x in self.opf_xpath('//opf:manifest/opf:item[@href]')} + return name in all_names + + def make_name_unique(self, name): + ''' Ensure that `name` does not already exist in this book. If it does, return a modified version that does not exist. ''' + counter = count() + while self.has_name_case_insensitive(name) or self.manifest_has_name(name): + c = next(counter) + 1 + base, ext = name.rpartition('.')[::2] + if c > 1: + base = base.rpartition('-')[0] + name = '%s-%d.%s' % (base, c, ext) + return name + + def add_file(self, name, data, media_type=None, spine_index=None, modify_name_if_needed=False, process_manifest_item=None): + ''' Add a file to this container. Entries for the file are + automatically created in the OPF manifest and spine + (if the file is a text document) ''' + if '..' in name: + raise ValueError('Names are not allowed to have .. in them') + href = self.name_to_href(name, self.opf_name) + if self.has_name_case_insensitive(name) or self.manifest_has_name(name): + if not modify_name_if_needed: + raise ValueError(('A file with the name %s already exists' % name) if self.has_name_case_insensitive(name) else + ('An item with the href %s already exists in the manifest' % href)) + name = self.make_name_unique(name) + href = self.name_to_href(name, self.opf_name) + path = self.name_to_abspath(name) + base = os.path.dirname(path) + if not os.path.exists(base): + os.makedirs(base) + with lopen(path, 'wb') as f: + if hasattr(data, 'read'): + shutil.copyfileobj(data, f) + else: + f.write(data) + mt = media_type or self.guess_type(name) + self.name_path_map[name] = path + self.mime_map[name] = mt + if self.ok_to_be_unmanifested(name): + return name + item_id = self.add_name_to_manifest(name, process_manifest_item=process_manifest_item) + if mt in OEB_DOCS: + manifest = self.opf_xpath('//opf:manifest')[0] + spine = self.opf_xpath('//opf:spine')[0] + si = manifest.makeelement(OPF('itemref'), idref=item_id) + self.insert_into_xml(spine, si, index=spine_index) + return name + + def rename(self, current_name, new_name): + ''' Renames a file from current_name to new_name. It automatically + rebases all links inside the file if the directory the file is in + changes. Note however, that links are not updated in the other files + that could reference this file. This is for performance, such updates + should be done once, in bulk. ''' + if current_name in self.names_that_must_not_be_changed: + raise ValueError('Renaming of %s is not allowed' % current_name) + if self.exists(new_name) and (new_name == current_name or new_name.lower() != current_name.lower()): + # The destination exists and does not differ from the current name only by case + raise ValueError('Cannot rename %s to %s as %s already exists' % (current_name, new_name, new_name)) + new_path = self.name_to_abspath(new_name) + base = os.path.dirname(new_path) + if os.path.isfile(base): + raise ValueError('Cannot rename %s to %s as %s is a file' % (current_name, new_name, base)) + if not os.path.exists(base): + os.makedirs(base) + old_path = parent_dir = self.name_to_abspath(current_name) + self.commit_item(current_name) + os.rename(old_path, new_path) + # Remove empty directories + while parent_dir: + parent_dir = os.path.dirname(parent_dir) + try: + os.rmdir(parent_dir) + except EnvironmentError: + break + + for x in ('mime_map', 'encoding_map'): + x = getattr(self, x) + if current_name in x: + x[new_name] = x[current_name] + self.name_path_map[new_name] = new_path + for x in self.cache_names: + x = getattr(self, x) + try: + x.pop(current_name, None) + except TypeError: + x.discard(current_name) + if current_name == self.opf_name: + self.opf_name = new_name + if os.path.dirname(old_path) != os.path.dirname(new_path): + from calibre.ebooks.oeb.polish.replace import LinkRebaser + repl = LinkRebaser(self, current_name, new_name) + self.replace_links(new_name, repl) + self.dirty(new_name) + + def replace_links(self, name, replace_func): + ''' Replace all links in name using replace_func, which must be a + callable that accepts a URL and returns the replaced URL. It must also + have a 'replaced' attribute that is set to True if any actual + replacement is done. Convenient ways of creating such callables are + using the :class:`LinkReplacer` and :class:`LinkRebaser` classes. ''' + media_type = self.mime_map.get(name, guess_type(name)) + if name == self.opf_name: + replace_func.file_type = 'opf' + for elem in self.opf_xpath('//*[@href]'): + elem.set('href', replace_func(elem.get('href'))) + elif media_type.lower() in OEB_DOCS: + replace_func.file_type = 'text' + rewrite_links(self.parsed(name), replace_func) + elif media_type.lower() in OEB_STYLES: + replace_func.file_type = 'style' + replaceUrls(self.parsed(name), replace_func) + elif media_type.lower() == guess_type('toc.ncx'): + replace_func.file_type = 'ncx' + for elem in self.parsed(name).xpath('//*[@src]'): + elem.set('src', replace_func(elem.get('src'))) + + if replace_func.replaced: + self.dirty(name) + return replace_func.replaced + + def iterlinks(self, name, get_line_numbers=True): + ''' Iterate over all links in name. If get_line_numbers is True the + yields results of the form (link, line_number, offset). Where + line_number is the line_number at which the link occurs and offset is + the number of characters from the start of the line. Note that offset + could actually encompass several lines if not zero. ''' + media_type = self.mime_map.get(name, guess_type(name)) + if name == self.opf_name: + for elem in self.opf_xpath('//*[@href]'): + yield (elem.get('href'), elem.sourceline, 0) if get_line_numbers else elem.get('href') + elif media_type.lower() in OEB_DOCS: + for el, attr, link, pos in iterlinks(self.parsed(name)): + yield (link, el.sourceline, pos) if get_line_numbers else link + elif media_type.lower() in OEB_STYLES: + if get_line_numbers: + with self.open(name, 'rb') as f: + raw = self.decode(f.read()).replace('\r\n', '\n').replace('\r', '\n') + position = PositionFinder(raw) + is_in_comment = CommentFinder(raw) + for link, offset in itercsslinks(raw): + if not is_in_comment(offset): + lnum, col = position(offset) + yield link, lnum, col + else: + for link in getUrls(self.parsed(name)): + yield link + elif media_type.lower() == guess_type('toc.ncx'): + for elem in self.parsed(name).xpath('//*[@src]'): + yield (elem.get('src'), elem.sourceline, 0) if get_line_numbers else elem.get('src') + + def abspath_to_name(self, fullpath, root=None): + ''' + Convert an absolute path to a canonical name relative to :attr:`root` + + :param root: The base directory. By default the root for this container object is used. + ''' + # OS X silently changes all file names to NFD form. The EPUB + # spec requires all text including filenames to be in NFC form. + # The proper fix is to implement a VFS that maps between + # canonical names and their file system representation, however, + # I dont have the time for that now. Note that the container + # ensures that all text files are normalized to NFC when + # decoding them anyway, so there should be no mismatch between + # names in the text and NFC canonical file names. + return unicodedata.normalize('NFC', abspath_to_name(fullpath, root or self.root)) + + def name_to_abspath(self, name): + ' Convert a canonical name to an absolute OS dependant path ' + return name_to_abspath(name, self.root) + + def exists(self, name): + ''' True iff a file/directory corresponding to the canonical name exists. Note + that this function suffers from the limitations of the underlying OS + filesystem, in particular case (in)sensitivity. So on a case + insensitive filesystem this will return True even if the case of name + is different from the case of the underlying filesystem file. See also :meth:`has_name`''' + return os.path.exists(self.name_to_abspath(name)) + + def href_to_name(self, href, base=None): + ''' + Convert an href (relative to base) to a name. base must be a name or + None, in which case self.root is used. + ''' + key = href, base + ans = self.href_to_name_cache.get(key, null) + if ans is null: + ans = self.href_to_name_cache[key] = href_to_name(href, self.root, base=base) + return ans + + def name_to_href(self, name, base=None): + '''Convert a name to a href relative to base, which must be a name or + None in which case self.root is used as the base''' + return name_to_href(name, self.root, base=base) + + def opf_xpath(self, expr): + ' Convenience method to evaluate an XPath expression on the OPF file, has the opf: and dc: namespace prefixes pre-defined. ' + return self.opf.xpath(expr, namespaces=OPF_NAMESPACES) + + def has_name(self, name): + ''' Return True iff a file with the same canonical name as that specified exists. Unlike :meth:`exists` this method is always case-sensitive. ''' + return name and name in self.name_path_map + + def has_name_and_is_not_empty(self, name): + if not self.has_name(name): + return False + return os.path.getsize(self.name_path_map[name]) > 0 + + def has_name_case_insensitive(self, name): + if not name: + return False + name = name.lower() + for q in self.name_path_map: + if q.lower() == name: + return True + return False + + def relpath(self, path, base=None): + '''Convert an absolute path (with os separators) to a path relative to + base (defaults to self.root). The relative path is *not* a name. Use + :meth:`abspath_to_name` for that.''' + return relpath(path, base or self.root) + + def ok_to_be_unmanifested(self, name): + return name in self.names_that_need_not_be_manifested + + @property + def names_that_need_not_be_manifested(self): + ' Set of names that are allowed to be missing from the manifest. Depends on the e-book file format. ' + return {self.opf_name} + + @property + def names_that_must_not_be_removed(self): + ' Set of names that must never be deleted from the container. Depends on the e-book file format. ' + return {self.opf_name} + + @property + def names_that_must_not_be_changed(self): + ' Set of names that must never be renamed. Depends on the e-book file format. ' + return set() + + def parse(self, path, mime): + with lopen(path, 'rb') as src: + data = src.read() + if mime in OEB_DOCS: + data = self.parse_xhtml(data, self.relpath(path)) + elif mime[-4:] in {'+xml', '/xml'}: + data = self.parse_xml(data) + elif mime in OEB_STYLES: + data = self.parse_css(data, self.relpath(path)) + return data + + def raw_data(self, name, decode=True, normalize_to_nfc=True): + ''' + Return the raw data corresponding to the file specified by name + + :param decode: If True and the file has a text based mimetype, decode it and return a unicode object instead of raw bytes. + :param normalize_to_nfc: If True the returned unicode object is normalized to the NFC normal form as is required for the EPUB and AZW3 file formats. + ''' + ans = self.open(name).read() + mime = self.mime_map.get(name, guess_type(name)) + if decode and (mime in OEB_STYLES or mime in OEB_DOCS or mime == 'text/plain' or mime[-4:] in {'+xml', '/xml'}): + ans = self.decode(ans, normalize_to_nfc=normalize_to_nfc) + return ans + + def parsed(self, name): + ''' Return a parsed representation of the file specified by name. For + HTML and XML files an lxml tree is returned. For CSS files a css_parser + stylesheet is returned. Note that parsed objects are cached for + performance. If you make any changes to the parsed object, you must + call :meth:`dirty` so that the container knows to update the cache. See also :meth:`replace`.''' + ans = self.parsed_cache.get(name, None) + if ans is None: + self.used_encoding = None + mime = self.mime_map.get(name, guess_type(name)) + ans = self.parse(self.name_path_map[name], mime) + self.parsed_cache[name] = ans + self.encoding_map[name] = self.used_encoding + return ans + + def replace(self, name, obj): + ''' + Replace the parsed object corresponding to name with obj, which must be + a similar object, i.e. an lxml tree for HTML/XML or a css_parser + stylesheet for a CSS file. + ''' + self.parsed_cache[name] = obj + self.dirty(name) + + @property + def opf(self): + ' The parsed OPF file ' + return self.parsed(self.opf_name) + + @property + def mi(self): + ''' The metadata of this book as a Metadata object. Note that this + object is constructed on the fly every time this property is requested, + so use it sparingly. ''' + from calibre.ebooks.metadata.opf2 import OPF as O + mi = self.serialize_item(self.opf_name) + return O(BytesIO(mi), basedir=self.opf_dir, unquote_urls=False, + populate_spine=False).to_book_metadata() + + @property + def opf_version(self): + ' The version set on the OPF\'s <package> element ' + try: + return self.opf_xpath('//opf:package/@version')[0] + except IndexError: + return '' + + @property + def opf_version_parsed(self): + ' The version set on the OPF\'s <package> element as a tuple of integers ' + return parse_opf_version(self.opf_version) + + @property + def manifest_id_map(self): + ' Mapping of manifest id to canonical names ' + return {item.get('id'):self.href_to_name(item.get('href'), self.opf_name) + for item in self.opf_xpath('//opf:manifest/opf:item[@href and @id]')} + + @property + def manifest_type_map(self): + ' Mapping of manifest media-type to list of canonical names of that media-type ' + ans = defaultdict(list) + for item in self.opf_xpath('//opf:manifest/opf:item[@href and @media-type]'): + ans[item.get('media-type').lower()].append(self.href_to_name( + item.get('href'), self.opf_name)) + return {mt:tuple(v) for mt, v in iteritems(ans)} + + def manifest_items_with_property(self, property_name): + ' All manifest items that have the specified property ' + prefixes = read_prefixes(self.opf) + for item in items_with_property(self.opf, property_name, prefixes): + href = item.get('href') + if href: + yield self.href_to_name(item.get('href'), self.opf_name) + + def manifest_items_of_type(self, predicate): + ''' The names of all manifest items whose media-type matches predicate. + `predicate` can be a set, a list, a string or a function taking a single + argument, which will be called with the media-type. ''' + if isinstance(predicate, unicode_type): + predicate = predicate.__eq__ + elif hasattr(predicate, '__contains__'): + predicate = predicate.__contains__ + for mt, names in iteritems(self.manifest_type_map): + if predicate(mt): + for name in names: + yield name + + def apply_unique_properties(self, name, *properties): + ''' Ensure that the specified properties are set on only the manifest item + identified by name. You can pass None as the name to remove the + property from all items. ''' + properties = frozenset(properties) + removed_names, added_names = [], [] + for p in properties: + if p.startswith('calibre:'): + ensure_prefix(self.opf, None, 'calibre', CALIBRE_PREFIX) + break + + for item in self.opf_xpath('//opf:manifest/opf:item'): + iname = self.href_to_name(item.get('href'), self.opf_name) + props = (item.get('properties') or '').split() + lprops = {p.lower() for p in props} + for prop in properties: + if prop.lower() in lprops: + if name != iname: + removed_names.append(iname) + props = [p for p in props if p.lower() != prop] + if props: + item.set('properties', ' '.join(props)) + else: + del item.attrib['properties'] + else: + if name == iname: + added_names.append(iname) + props.append(prop) + item.set('properties', ' '.join(props)) + self.dirty(self.opf_name) + return removed_names, added_names + + def add_properties(self, name, *properties): + ''' Add the specified properties to the manifest item identified by name. ''' + properties = frozenset(properties) + if not properties: + return True + for p in properties: + if p.startswith('calibre:'): + ensure_prefix(self.opf, None, 'calibre', CALIBRE_PREFIX) + break + for item in self.opf_xpath('//opf:manifest/opf:item'): + iname = self.href_to_name(item.get('href'), self.opf_name) + if name == iname: + props = frozenset((item.get('properties') or '').split()) | properties + item.set('properties', ' '.join(props)) + return True + return False + + @property + def guide_type_map(self): + ' Mapping of guide type to canonical name ' + return {item.get('type', ''):self.href_to_name(item.get('href'), self.opf_name) + for item in self.opf_xpath('//opf:guide/opf:reference[@href and @type]')} + + @property + def spine_iter(self): + ''' An iterator that yields item, name is_linear for every item in the + books' spine. item is the lxml element, name is the canonical file name + and is_linear is True if the item is linear. See also: :attr:`spine_names` and :attr:`spine_items`. ''' + manifest_id_map = self.manifest_id_map + non_linear = [] + for item in self.opf_xpath('//opf:spine/opf:itemref[@idref]'): + idref = item.get('idref') + name = manifest_id_map.get(idref, None) + path = self.name_path_map.get(name, None) + if path: + if item.get('linear', 'yes') == 'yes': + yield item, name, True + else: + non_linear.append((item, name)) + for item, name in non_linear: + yield item, name, False + + def index_in_spine(self, name): + manifest_id_map = self.manifest_id_map + for i, item in enumerate(self.opf_xpath('//opf:spine/opf:itemref[@idref]')): + idref = item.get('idref') + q = manifest_id_map.get(idref, None) + if q == name: + return i + + @property + def spine_names(self): + ''' An iterator yielding name and is_linear for every item in the + books' spine. See also: :attr:`spine_iter` and :attr:`spine_items`. ''' + for item, name, linear in self.spine_iter: + yield name, linear + + @property + def spine_items(self): + ''' An iterator yielding the path for every item in the + books' spine. See also: :attr:`spine_iter` and :attr:`spine_items`. ''' + for name, linear in self.spine_names: + yield self.name_path_map[name] + + def remove_from_spine(self, spine_items, remove_if_no_longer_in_spine=True): + ''' + Remove the specified items (by canonical name) from the spine. If ``remove_if_no_longer_in_spine`` + is True, the items are also deleted from the book, not just from the spine. + ''' + nixed = set() + for (name, remove), (item, xname, linear) in zip(spine_items, self.spine_iter): + if remove and name == xname: + self.remove_from_xml(item) + nixed.add(name) + if remove_if_no_longer_in_spine: + # Remove from the book if no longer in spine + nixed -= {name for name, linear in self.spine_names} + for name in nixed: + self.remove_item(name) + + def set_spine(self, spine_items): + ''' Set the spine to be spine_items where spine_items is an iterable of + the form (name, linear). Will raise an error if one of the names is not + present in the manifest. ''' + imap = self.manifest_id_map + imap = {name:item_id for item_id, name in iteritems(imap)} + items = [item for item, name, linear in self.spine_iter] + tail, last_tail = (items[0].tail, items[-1].tail) if items else ('\n ', '\n ') + tuple(map(self.remove_from_xml, items)) + spine = self.opf_xpath('//opf:spine')[0] + spine.text = tail + for name, linear in spine_items: + i = spine.makeelement('{%s}itemref' % OPF_NAMESPACES['opf'], nsmap={'opf':OPF_NAMESPACES['opf']}) + i.tail = tail + i.set('idref', imap[name]) + spine.append(i) + if not linear: + i.set('linear', 'no') + if len(spine) > 0: + spine[-1].tail = last_tail + self.dirty(self.opf_name) + + def remove_item(self, name, remove_from_guide=True): + ''' + Remove the item identified by name from this container. This removes all + references to the item in the OPF manifest, guide and spine as well as from + any internal caches. + ''' + removed = set() + for elem in self.opf_xpath('//opf:manifest/opf:item[@href]'): + if self.href_to_name(elem.get('href'), self.opf_name) == name: + id_ = elem.get('id', None) + if id_ is not None: + removed.add(id_) + self.remove_from_xml(elem) + self.dirty(self.opf_name) + if removed: + for spine in self.opf_xpath('//opf:spine'): + tocref = spine.attrib.get('toc', None) + if tocref and tocref in removed: + spine.attrib.pop('toc', None) + self.dirty(self.opf_name) + + for item in self.opf_xpath('//opf:spine/opf:itemref[@idref]'): + idref = item.get('idref') + if idref in removed: + self.remove_from_xml(item) + self.dirty(self.opf_name) + + for meta in self.opf_xpath('//opf:meta[@name="cover" and @content]'): + if meta.get('content') in removed: + self.remove_from_xml(meta) + self.dirty(self.opf_name) + + if remove_from_guide: + for item in self.opf_xpath('//opf:guide/opf:reference[@href]'): + if self.href_to_name(item.get('href'), self.opf_name) == name: + self.remove_from_xml(item) + self.dirty(self.opf_name) + + path = self.name_path_map.pop(name, None) + if path and os.path.exists(path): + os.remove(path) + self.mime_map.pop(name, None) + self.parsed_cache.pop(name, None) + self.dirtied.discard(name) + + def dirty(self, name): + ''' Mark the parsed object corresponding to name as dirty. See also: :meth:`parsed`. ''' + self.dirtied.add(name) + + def remove_from_xml(self, item): + 'Removes item from parent, fixing indentation (works only with self closing items)' + parent = item.getparent() + idx = parent.index(item) + if idx == 0: + # We are removing the first item - only care about adjusting + # the tail if this was the only child + if len(parent) == 1: + parent.text = item.tail + else: + # Make sure the preceding item has this tail + parent[idx-1].tail = item.tail + parent.remove(item) + return item + + def insert_into_xml(self, parent, item, index=None): + '''Insert item into parent (or append if index is None), fixing + indentation. Only works with self closing items.''' + if index is None: + parent.append(item) + else: + parent.insert(index, item) + idx = parent.index(item) + if idx == 0: + item.tail = parent.text + # If this is the only child of this parent element, we need a + # little extra work as we have gone from a self-closing <foo /> + # element to <foo><item /></foo> + if len(parent) == 1: + sibling = parent.getprevious() + if sibling is None: + # Give up! + return + parent.text = sibling.text + item.tail = sibling.tail + else: + item.tail = parent[idx-1].tail + if idx == len(parent)-1: + parent[idx-1].tail = parent.text + + def opf_get_or_create(self, name): + ''' Convenience method to either return the first XML element with the + specified name or create it under the opf:package element and then + return it, if it does not already exist. ''' + ans = self.opf_xpath('//opf:'+name) + if ans: + return ans[0] + self.dirty(self.opf_name) + package = self.opf_xpath('//opf:package')[0] + item = package.makeelement(OPF(name)) + item.tail = '\n' + package.append(item) + return item + + def generate_item(self, name, id_prefix=None, media_type=None, unique_href=True): + '''Add an item to the manifest with href derived from the given + name. Ensures uniqueness of href and id automatically. Returns + generated item.''' + id_prefix = id_prefix or 'id' + media_type = media_type or guess_type(name) + if unique_href: + name = self.make_name_unique(name) + href = self.name_to_href(name, self.opf_name) + base, ext = href.rpartition('.')[0::2] + all_ids = {x.get('id') for x in self.opf_xpath('//*[@id]')} + c = 0 + item_id = id_prefix + while item_id in all_ids: + c += 1 + item_id = id_prefix + '%d'%c + + manifest = self.opf_xpath('//opf:manifest')[0] + item = manifest.makeelement(OPF('item'), + id=item_id, href=href) + item.set('media-type', media_type) + self.insert_into_xml(manifest, item) + self.dirty(self.opf_name) + name = self.href_to_name(href, self.opf_name) + self.name_path_map[name] = path = self.name_to_abspath(name) + self.mime_map[name] = media_type + # Ensure that the file corresponding to the newly created item exists + # otherwise cloned containers will fail when they try to get the number + # of links to the file + base = os.path.dirname(path) + if not os.path.exists(base): + os.makedirs(base) + lopen(path, 'wb').close() + return item + + def format_opf(self): + try: + mdata = self.opf_xpath('//opf:metadata')[0] + except IndexError: + pass + else: + mdata.text = '\n ' + remove = set() + for child in mdata: + child.tail = '\n ' + try: + if (child.get('name', '').startswith('calibre:' + ) and child.get('content', '').strip() in {'{}', ''}): + remove.add(child) + except AttributeError: + continue # Happens for XML comments + for child in remove: + mdata.remove(child) + if len(mdata) > 0: + mdata[-1].tail = '\n ' + # Ensure name comes before content, needed for Nooks + for meta in self.opf_xpath('//opf:meta[@name="cover"]'): + if 'content' in meta.attrib: + meta.set('content', meta.attrib.pop('content')) + + def serialize_item(self, name): + ''' Convert a parsed object (identified by canonical name) into a bytestring. See :meth:`parsed`. ''' + data = root = self.parsed(name) + if name == self.opf_name: + self.format_opf() + data = serialize(data, self.mime_map[name], pretty_print=name in + self.pretty_print) + if name == self.opf_name and root.nsmap.get(None) == OPF2_NS: + # Needed as I can't get lxml to output opf:role and + # not output <opf:metadata> as well + data = re.sub(br'(<[/]{0,1})opf:', r'\1', data) + return data + + def commit_item(self, name, keep_parsed=False): + ''' Commit a parsed object to disk (it is serialized and written to the + underlying file). If ``keep_parsed`` is True the parsed representation + is retained in the cache. See also: :meth:`parsed` ''' + if name not in self.parsed_cache: + return + data = self.serialize_item(name) + self.dirtied.discard(name) + if not keep_parsed: + self.parsed_cache.pop(name) + dest = self.name_path_map[name] + if self.cloned and nlinks_file(dest) > 1: + # Decouple this file from its links + os.unlink(dest) + with lopen(dest, 'wb') as f: + f.write(data) + + def filesize(self, name): + ''' Return the size in bytes of the file represented by the specified + canonical name. Automatically handles dirtied parsed objects. See also: + :meth:`parsed` ''' + if name in self.dirtied: + self.commit_item(name, keep_parsed=True) + path = self.name_to_abspath(name) + return os.path.getsize(path) + + def get_file_path_for_processing(self, name, allow_modification=True): + ''' Similar to open() except that it returns a file path, instead of an open file object. ''' + if name in self.dirtied: + self.commit_item(name) + self.parsed_cache.pop(name, False) + path = self.name_to_abspath(name) + base = os.path.dirname(path) + if not os.path.exists(base): + os.makedirs(base) + else: + if self.cloned and allow_modification and os.path.exists(path) and nlinks_file(path) > 1: + # Decouple this file from its links + temp = path + 'xxx' + shutil.copyfile(path, temp) + try: + os.unlink(path) + except EnvironmentError: + if not iswindows: + raise + time.sleep(1) # Wait for whatever has locked the file to release it + os.unlink(path) + os.rename(temp, path) + return path + + def open(self, name, mode='rb'): + ''' Open the file pointed to by name for direct read/write. Note that + this will commit the file if it is dirtied and remove it from the parse + cache. You must finish with this file before accessing the parsed + version of it again, or bad things will happen. ''' + return lopen(self.get_file_path_for_processing(name, mode not in {'r', 'rb'}), mode) + + def commit(self, outpath=None, keep_parsed=False): + ''' + Commit all dirtied parsed objects to the filesystem and write out the e-book file at outpath. + + :param output: The path to write the saved e-book file to. If None, the path of the original book file is used. + :param keep_parsed: If True the parsed representations of committed items are kept in the cache. + ''' + for name in tuple(self.dirtied): + self.commit_item(name, keep_parsed=keep_parsed) + + def compare_to(self, other): + if set(self.name_path_map) != set(other.name_path_map): + return 'Set of files is not the same' + mismatches = [] + for name, path in iteritems(self.name_path_map): + opath = other.name_path_map[name] + with lopen(path, 'rb') as f1, lopen(opath, 'rb') as f2: + if f1.read() != f2.read(): + mismatches.append('The file %s is not the same'%name) + return '\n'.join(mismatches) +# }}} + +# EPUB {{{ + + +class InvalidEpub(InvalidBook): + pass + + +class ObfuscationKeyMissing(InvalidEpub): + pass + + +OCF_NS = 'urn:oasis:names:tc:opendocument:xmlns:container' +VCS_IGNORE_FILES = frozenset('.gitignore .hgignore .agignore .bzrignore'.split()) +VCS_DIRS = frozenset(('.git', '.hg', '.svn', '.bzr')) + + +def walk_dir(basedir): + for dirpath, dirnames, filenames in os.walk(basedir): + for vcsdir in VCS_DIRS: + try: + dirnames.remove(vcsdir) + except Exception: + pass + is_root = os.path.abspath(os.path.normcase(dirpath)) == os.path.abspath(os.path.normcase(basedir)) + yield is_root, dirpath, None + for fname in filenames: + if fname not in VCS_IGNORE_FILES: + yield is_root, dirpath, fname + + +class EpubContainer(Container): + + book_type = 'epub' + + META_INF = { + 'container.xml': True, + 'manifest.xml': False, + 'encryption.xml': False, + 'metadata.xml': False, + 'signatures.xml': False, + 'rights.xml': False, + } + + def __init__(self, pathtoepub, log, clone_data=None, tdir=None): + if clone_data is not None: + super(EpubContainer, self).__init__(None, None, log, clone_data=clone_data) + for x in ('pathtoepub', 'obfuscated_fonts', 'is_dir'): + setattr(self, x, clone_data[x]) + return + + self.pathtoepub = pathtoepub + if tdir is None: + tdir = PersistentTemporaryDirectory('_epub_container') + tdir = os.path.abspath(os.path.realpath(tdir)) + self.root = tdir + self.is_dir = os.path.isdir(pathtoepub) + if self.is_dir: + for is_root, dirpath, fname in walk_dir(self.pathtoepub): + if is_root: + base = tdir + else: + base = os.path.join(tdir, os.path.relpath(dirpath, self.pathtoepub)) + if fname is None: + os.mkdir(base) + if fname is not None: + shutil.copy(os.path.join(dirpath, fname), os.path.join(base, fname)) + else: + with lopen(self.pathtoepub, 'rb') as stream: + try: + zf = ZipFile(stream) + zf.extractall(tdir) + except: + log.exception('EPUB appears to be invalid ZIP file, trying a' + ' more forgiving ZIP parser') + from calibre.utils.localunzip import extractall + stream.seek(0) + extractall(stream, path=tdir) + try: + os.remove(join(tdir, 'mimetype')) + except EnvironmentError: + pass + # Ensure all filenames are in NFC normalized form + # has no effect on HFS+ filesystems as they always store filenames + # in NFD form + for filename in walk(self.root): + n = unicodedata.normalize('NFC', filename) + if n != filename: + s = filename + 'suff1x' + os.rename(filename, s) + os.rename(s, n) + + container_path = join(self.root, 'META-INF', 'container.xml') + if not exists(container_path): + raise InvalidEpub('No META-INF/container.xml in epub') + container = safe_xml_fromstring(open(container_path, 'rb').read()) + opf_files = container.xpath(( + r'child::ocf:rootfiles/ocf:rootfile' + '[@media-type="%s" and @full-path]'%guess_type('a.opf') + ), namespaces={'ocf':OCF_NS} + ) + if not opf_files: + raise InvalidEpub('META-INF/container.xml contains no link to OPF file') + opf_path = os.path.join(self.root, *(urlunquote(opf_files[0].get('full-path')).split('/'))) + if not exists(opf_path): + raise InvalidEpub('OPF file does not exist at location pointed to' + ' by META-INF/container.xml') + + super(EpubContainer, self).__init__(tdir, opf_path, log) + + self.obfuscated_fonts = {} + if 'META-INF/encryption.xml' in self.name_path_map: + self.process_encryption() + self.parsed_cache['META-INF/container.xml'] = container + + def clone_data(self, dest_dir): + ans = super(EpubContainer, self).clone_data(dest_dir) + ans['pathtoepub'] = self.pathtoepub + ans['obfuscated_fonts'] = self.obfuscated_fonts.copy() + ans['is_dir'] = self.is_dir + return ans + + def rename(self, old_name, new_name): + is_opf = old_name == self.opf_name + super(EpubContainer, self).rename(old_name, new_name) + if is_opf: + for elem in self.parsed('META-INF/container.xml').xpath(( + r'child::ocf:rootfiles/ocf:rootfile' + '[@media-type="%s" and @full-path]'%guess_type('a.opf') + ), namespaces={'ocf':OCF_NS} + ): + # The asinine epubcheck cannot handle quoted filenames in + # container.xml + elem.set('full-path', self.opf_name) + self.dirty('META-INF/container.xml') + if old_name in self.obfuscated_fonts: + self.obfuscated_fonts[new_name] = self.obfuscated_fonts.pop(old_name) + enc = self.parsed('META-INF/encryption.xml') + for cr in enc.xpath('//*[local-name()="CipherReference" and @URI]'): + if self.href_to_name(cr.get('URI')) == old_name: + cr.set('URI', self.name_to_href(new_name)) + self.dirty('META-INF/encryption.xml') + + @property + def names_that_need_not_be_manifested(self): + return super(EpubContainer, self).names_that_need_not_be_manifested | {'META-INF/' + x for x in self.META_INF} + + def ok_to_be_unmanifested(self, name): + return name in self.names_that_need_not_be_manifested or name.startswith('META-INF/') + + @property + def names_that_must_not_be_removed(self): + return super(EpubContainer, self).names_that_must_not_be_removed | {'META-INF/container.xml'} + + @property + def names_that_must_not_be_changed(self): + return super(EpubContainer, self).names_that_must_not_be_changed | {'META-INF/' + x for x in self.META_INF} + + def remove_item(self, name, remove_from_guide=True): + # Handle removal of obfuscated fonts + if name == 'META-INF/encryption.xml': + self.obfuscated_fonts.clear() + if name in self.obfuscated_fonts: + self.obfuscated_fonts.pop(name, None) + enc = self.parsed('META-INF/encryption.xml') + for em in enc.xpath('//*[local-name()="EncryptionMethod" and @Algorithm]'): + alg = em.get('Algorithm') + if alg not in {ADOBE_OBFUSCATION, IDPF_OBFUSCATION}: + continue + try: + cr = em.getparent().xpath('descendant::*[local-name()="CipherReference" and @URI]')[0] + except (IndexError, ValueError, KeyError): + continue + if name == self.href_to_name(cr.get('URI')): + self.remove_from_xml(em.getparent()) + self.dirty('META-INF/encryption.xml') + super(EpubContainer, self).remove_item(name, remove_from_guide=remove_from_guide) + + def process_encryption(self): + fonts = {} + enc = self.parsed('META-INF/encryption.xml') + for em in enc.xpath('//*[local-name()="EncryptionMethod" and @Algorithm]'): + alg = em.get('Algorithm') + if alg not in {ADOBE_OBFUSCATION, IDPF_OBFUSCATION}: + raise DRMError() + try: + cr = em.getparent().xpath('descendant::*[local-name()="CipherReference" and @URI]')[0] + except (IndexError, ValueError, KeyError): + continue + name = self.href_to_name(cr.get('URI')) + path = self.name_path_map.get(name, None) + if path is not None: + fonts[name] = alg + if not fonts: + return + + package_id = raw_unique_identifier = idpf_key = None + for attrib, val in iteritems(self.opf.attrib): + if attrib.endswith('unique-identifier'): + package_id = val + break + if package_id is not None: + for elem in self.opf_xpath('//*[@id=%s]'%escape_xpath_attr(package_id)): + if elem.text: + raw_unique_identifier = elem.text + break + if raw_unique_identifier is not None: + idpf_key = raw_unique_identifier + idpf_key = re.sub('[\u0020\u0009\u000d\u000a]', '', idpf_key) + idpf_key = hashlib.sha1(idpf_key.encode('utf-8')).digest() + key = None + for item in self.opf_xpath('//*[local-name()="metadata"]/*' + '[local-name()="identifier"]'): + scheme = None + for xkey in item.attrib.keys(): + if xkey.endswith('scheme'): + scheme = item.get(xkey) + if (scheme and scheme.lower() == 'uuid') or \ + (item.text and item.text.startswith('urn:uuid:')): + try: + key = item.text.rpartition(':')[-1] + key = uuid.UUID(key).bytes + except Exception: + self.log.exception('Failed to parse obfuscation key') + key = None + + for font, alg in iteritems(fonts): + tkey = key if alg == ADOBE_OBFUSCATION else idpf_key + if not tkey: + raise ObfuscationKeyMissing('Failed to find obfuscation key') + raw = self.raw_data(font, decode=False) + raw = decrypt_font_data(tkey, raw, alg) + with self.open(font, 'wb') as f: + f.write(raw) + self.obfuscated_fonts[font] = (alg, tkey) + + def update_modified_timestamp(self): + from calibre.ebooks.metadata.opf3 import set_last_modified_in_opf + set_last_modified_in_opf(self.opf) + self.dirty(self.opf_name) + + def commit(self, outpath=None, keep_parsed=False): + if self.opf_version_parsed.major == 3: + self.update_modified_timestamp() + super(EpubContainer, self).commit(keep_parsed=keep_parsed) + container_path = join(self.root, 'META-INF', 'container.xml') + if not exists(container_path): + raise InvalidEpub('No META-INF/container.xml in EPUB, this typically happens if the temporary files calibre' + ' is using are deleted by some other program while calibre is running') + restore_fonts = {} + for name in self.obfuscated_fonts: + if name not in self.name_path_map: + continue + alg, key = self.obfuscated_fonts[name] + # Decrypting and encrypting are the same operation (XOR with key) + restore_fonts[name] = data = self.raw_data(name, decode=False) + with self.open(name, 'wb') as f: + f.write(decrypt_font_data(key, data, alg)) + if outpath is None: + outpath = self.pathtoepub + if self.is_dir: + # First remove items from the source dir that do not exist any more + for is_root, dirpath, fname in walk_dir(self.pathtoepub): + if fname is not None: + if is_root and fname == 'mimetype': + continue + base = self.root if is_root else os.path.join(self.root, os.path.relpath(dirpath, self.pathtoepub)) + fpath = os.path.join(base, fname) + if not os.path.exists(fpath): + os.remove(os.path.join(dirpath, fname)) + try: + os.rmdir(dirpath) + except EnvironmentError as err: + if err.errno != errno.ENOTEMPTY: + raise + # Now copy over everything from root to source dir + for dirpath, dirnames, filenames in os.walk(self.root): + is_root = os.path.abspath(os.path.normcase(dirpath)) == os.path.abspath(os.path.normcase(self.root)) + base = self.pathtoepub if is_root else os.path.join(self.pathtoepub, os.path.relpath(dirpath, self.root)) + try: + os.mkdir(base) + except EnvironmentError as err: + if err.errno != errno.EEXIST: + raise + for fname in filenames: + with lopen(os.path.join(dirpath, fname), 'rb') as src, lopen(os.path.join(base, fname), 'wb') as dest: + shutil.copyfileobj(src, dest) + + else: + from calibre.ebooks.tweak import zip_rebuilder + with lopen(join(self.root, 'mimetype'), 'wb') as f: + et = guess_type('a.epub') + if not isinstance(et, bytes): + et = et.encode('ascii') + f.write(et) + zip_rebuilder(self.root, outpath) + for name, data in iteritems(restore_fonts): + with self.open(name, 'wb') as f: + f.write(data) + + @property + def path_to_ebook(self): + return self.pathtoepub + + @path_to_ebook.setter + def path_to_ebook(self, val): + self.pathtoepub = val + +# }}} + +# AZW3 {{{ + + +class InvalidMobi(InvalidBook): + pass + + +def do_explode(path, dest): + from calibre.ebooks.mobi.reader.mobi6 import MobiReader + from calibre.ebooks.mobi.reader.mobi8 import Mobi8Reader + with lopen(path, 'rb') as stream: + mr = MobiReader(stream, default_log, None, None) + + with CurrentDir(dest): + mr = Mobi8Reader(mr, default_log, for_tweak=True) + opf = os.path.abspath(mr()) + obfuscated_fonts = mr.encrypted_fonts + + return opf, obfuscated_fonts + + +def opf_to_azw3(opf, outpath, container): + from calibre.ebooks.conversion.plumber import Plumber, create_oebbook + + class Item(Manifest.Item): + + def _parse_css(self, data): + # The default CSS parser used by oeb.base inserts the h namespace + # and resolves all @import rules. We dont want that. + return container.parse_css(data) + + def specialize(oeb): + oeb.manifest.Item = Item + + plumber = Plumber(opf, outpath, container.log) + plumber.setup_options() + inp = plugin_for_input_format('azw3') + outp = plugin_for_output_format('azw3') + plumber.opts.mobi_passthrough = True + oeb = create_oebbook(container.log, opf, plumber.opts, specialize=specialize) + set_cover(oeb) + outp.convert(oeb, outpath, inp, plumber.opts, container.log) + + +def epub_to_azw3(epub, outpath=None): + container = get_container(epub, tweak_mode=True) + outpath = outpath or (epub.rpartition('.')[0] + '.azw3') + opf_to_azw3(container.name_to_abspath(container.opf_name), outpath, container) + + +class AZW3Container(Container): + + book_type = 'azw3' + SUPPORTS_TITLEPAGES = False + SUPPORTS_FILENAMES = False + + def __init__(self, pathtoazw3, log, clone_data=None, tdir=None): + if clone_data is not None: + super(AZW3Container, self).__init__(None, None, log, clone_data=clone_data) + for x in ('pathtoazw3', 'obfuscated_fonts'): + setattr(self, x, clone_data[x]) + return + + self.pathtoazw3 = pathtoazw3 + if tdir is None: + tdir = PersistentTemporaryDirectory('_azw3_container') + tdir = os.path.abspath(os.path.realpath(tdir)) + self.root = tdir + with lopen(pathtoazw3, 'rb') as stream: + raw = stream.read(3) + if raw == b'TPZ': + raise InvalidMobi(_('This is not a MOBI file. It is a Topaz file.')) + + try: + header = MetadataHeader(stream, default_log) + except MobiError: + raise InvalidMobi(_('This is not a MOBI file.')) + + if header.encryption_type != 0: + raise DRMError() + + kf8_type = header.kf8_type + + if kf8_type is None: + raise InvalidMobi(_('This MOBI file does not contain a KF8 format ' + 'book. KF8 is the new format from Amazon. calibre can ' + 'only edit MOBI files that contain KF8 books. Older ' + 'MOBI files without KF8 are not editable.')) + + if kf8_type == 'joint': + raise InvalidMobi(_('This MOBI file contains both KF8 and ' + 'older Mobi6 data. calibre can only edit MOBI files ' + 'that contain only KF8 data.')) + + try: + opf_path, obfuscated_fonts = fork_job( + 'calibre.ebooks.oeb.polish.container', 'do_explode', + args=(pathtoazw3, tdir), no_output=True)['result'] + except WorkerError as e: + log(e.orig_tb) + raise InvalidMobi('Failed to explode MOBI') + super(AZW3Container, self).__init__(tdir, opf_path, log) + self.obfuscated_fonts = {x.replace(os.sep, '/') for x in obfuscated_fonts} + + def clone_data(self, dest_dir): + ans = super(AZW3Container, self).clone_data(dest_dir) + ans['pathtoazw3'] = self.pathtoazw3 + ans['obfuscated_fonts'] = self.obfuscated_fonts.copy() + return ans + + def commit(self, outpath=None, keep_parsed=False): + super(AZW3Container, self).commit(keep_parsed=keep_parsed) + if outpath is None: + outpath = self.pathtoazw3 + opf_to_azw3(self.name_path_map[self.opf_name], outpath, self) + + @property + def path_to_ebook(self): + return self.pathtoazw3 + + @path_to_ebook.setter + def path_to_ebook(self, val): + self.pathtoazw3 = val + + @property + def names_that_must_not_be_changed(self): + return set(self.name_path_map) +# }}} + + +def get_container(path, log=None, tdir=None, tweak_mode=False): + if log is None: + log = default_log + try: + isdir = os.path.isdir(path) + except Exception: + isdir = False + ebook = (AZW3Container if path.rpartition('.')[-1].lower() in {'azw3', 'mobi', 'original_azw3', 'original_mobi'} and not isdir + else EpubContainer)(path, log, tdir=tdir) + ebook.tweak_mode = tweak_mode + return ebook + + +def test_roundtrip(): + ebook = get_container(sys.argv[-1]) + p = PersistentTemporaryFile(suffix='.'+sys.argv[-1].rpartition('.')[-1]) + p.close() + ebook.commit(outpath=p.name) + ebook2 = get_container(p.name) + ebook3 = get_container(p.name) + diff = ebook3.compare_to(ebook2) + if diff is not None: + print(diff) + + +if __name__ == '__main__': + test_roundtrip() diff --git a/ebook_converter/ebooks/oeb/polish/errors.py b/ebook_converter/ebooks/oeb/polish/errors.py new file mode 100644 index 0000000..d394627 --- /dev/null +++ b/ebook_converter/ebooks/oeb/polish/errors.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:fdm=marker:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>' +__docformat__ = 'restructuredtext en' + +from calibre.ebooks import DRMError as _DRMError + + +class InvalidBook(ValueError): + pass + + +class DRMError(_DRMError): + + def __init__(self): + super(DRMError, self).__init__(_('This file is locked with DRM. It cannot be edited.')) + + +class MalformedMarkup(ValueError): + pass diff --git a/ebook_converter/ebooks/oeb/polish/opf.py b/ebook_converter/ebooks/oeb/polish/opf.py new file mode 100644 index 0000000..b5aa6df --- /dev/null +++ b/ebook_converter/ebooks/oeb/polish/opf.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2014, Kovid Goyal <kovid at kovidgoyal.net>' + +from lxml import etree + +from calibre.ebooks.oeb.polish.container import OPF_NAMESPACES +from calibre.utils.localization import canonicalize_lang + + +def get_book_language(container): + for lang in container.opf_xpath('//dc:language'): + raw = lang.text + if raw: + code = canonicalize_lang(raw.split(',')[0].strip()) + if code: + return code + + +def set_guide_item(container, item_type, title, name, frag=None): + ref_tag = '{%s}reference' % OPF_NAMESPACES['opf'] + href = None + if name: + href = container.name_to_href(name, container.opf_name) + if frag: + href += '#' + frag + + guides = container.opf_xpath('//opf:guide') + if not guides and href: + g = container.opf.makeelement('{%s}guide' % OPF_NAMESPACES['opf'], nsmap={'opf':OPF_NAMESPACES['opf']}) + container.insert_into_xml(container.opf, g) + guides = [g] + + for guide in guides: + matches = [] + for child in guide.iterchildren(etree.Element): + if child.tag == ref_tag and child.get('type', '').lower() == item_type.lower(): + matches.append(child) + if not matches and href: + r = guide.makeelement(ref_tag, type=item_type, nsmap={'opf':OPF_NAMESPACES['opf']}) + container.insert_into_xml(guide, r) + matches.append(r) + for m in matches: + if href: + m.set('title', title), m.set('href', href), m.set('type', item_type) + else: + container.remove_from_xml(m) + container.dirty(container.opf_name) + diff --git a/ebook_converter/ebooks/oeb/polish/parsing.py b/ebook_converter/ebooks/oeb/polish/parsing.py new file mode 100644 index 0000000..2d0ee7d --- /dev/null +++ b/ebook_converter/ebooks/oeb/polish/parsing.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>' + +import re + +from lxml.etree import Element as LxmlElement +import html5_parser + +from calibre import xml_replace_entities +from calibre.utils.xml_parse import safe_xml_fromstring +from calibre.ebooks.chardet import xml_to_unicode, strip_encoding_declarations +from calibre.utils.cleantext import clean_xml_chars +from polyglot.builtins import unicode_type + +XHTML_NS = 'http://www.w3.org/1999/xhtml' + + +def parse_html5(raw, decoder=None, log=None, discard_namespaces=False, line_numbers=True, linenumber_attribute=None, replace_entities=True, fix_newlines=True): + if isinstance(raw, bytes): + raw = xml_to_unicode(raw)[0] if decoder is None else decoder(raw) + if replace_entities: + raw = xml_replace_entities(raw) + if fix_newlines: + raw = raw.replace('\r\n', '\n').replace('\r', '\n') + raw = clean_xml_chars(raw) + root = html5_parser.parse(raw, maybe_xhtml=not discard_namespaces, line_number_attr=linenumber_attribute, keep_doctype=False, sanitize_names=True) + if (discard_namespaces and root.tag != 'html') or ( + not discard_namespaces and (root.tag != '{%s}%s' % (XHTML_NS, 'html') or root.prefix)): + raise ValueError('Failed to parse correctly, root has tag: %s and prefix: %s' % (root.tag, root.prefix)) + return root + + +def handle_private_entities(data): + # Process private entities + pre = '' + idx = data.find('<html') + if idx == -1: + idx = data.find('<HTML') + if idx > -1: + pre = data[:idx] + num_of_nl_in_pre = pre.count('\n') + if '<!DOCTYPE' in pre: # Handle user defined entities + user_entities = {} + for match in re.finditer(r'<!ENTITY\s+(\S+)\s+([^>]+)', pre): + val = match.group(2) + if val.startswith('"') and val.endswith('"'): + val = val[1:-1] + user_entities[match.group(1)] = val + if user_entities: + data = ('\n' * num_of_nl_in_pre) + data[idx:] + pat = re.compile(r'&(%s);'%('|'.join(user_entities.keys()))) + data = pat.sub(lambda m:user_entities[m.group(1)], data) + return data + + +def parse(raw, decoder=None, log=None, line_numbers=True, linenumber_attribute=None, replace_entities=True, force_html5_parse=False): + if isinstance(raw, bytes): + raw = xml_to_unicode(raw)[0] if decoder is None else decoder(raw) + raw = handle_private_entities(raw) + if replace_entities: + raw = xml_replace_entities(raw).replace('\0', '') # Handle � + raw = raw.replace('\r\n', '\n').replace('\r', '\n') + + # Remove any preamble before the opening html tag as it can cause problems, + # especially doctypes, preserve the original linenumbers by inserting + # newlines at the start + pre = raw[:2048] + for match in re.finditer(r'<\s*html', pre, flags=re.I): + newlines = raw.count('\n', 0, match.start()) + raw = ('\n' * newlines) + raw[match.start():] + break + + raw = strip_encoding_declarations(raw, limit=10*1024, preserve_newlines=True) + if force_html5_parse: + return parse_html5(raw, log=log, line_numbers=line_numbers, linenumber_attribute=linenumber_attribute, replace_entities=False, fix_newlines=False) + try: + ans = safe_xml_fromstring(raw, recover=False) + if ans.tag != '{%s}html' % XHTML_NS: + raise ValueError('Root tag is not <html> in the XHTML namespace') + if linenumber_attribute: + for elem in ans.iter(LxmlElement): + if elem.sourceline is not None: + elem.set(linenumber_attribute, unicode_type(elem.sourceline)) + return ans + except Exception: + if log is not None: + log.exception('Failed to parse as XML, parsing as tag soup') + return parse_html5(raw, log=log, line_numbers=line_numbers, linenumber_attribute=linenumber_attribute, replace_entities=False, fix_newlines=False) + + +if __name__ == '__main__': + from lxml import etree + root = parse_html5('\n<html><head><title>a\n

 \nb', discard_namespaces=False) + print(etree.tostring(root, encoding='utf-8')) + print() diff --git a/ebook_converter/ebooks/oeb/polish/pretty.py b/ebook_converter/ebooks/oeb/polish/pretty.py new file mode 100644 index 0000000..e2e55dd --- /dev/null +++ b/ebook_converter/ebooks/oeb/polish/pretty.py @@ -0,0 +1,252 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2013, Kovid Goyal ' + +import textwrap +from polyglot.builtins import iteritems, map + +# from lxml.etree import Element + +from calibre import force_unicode +from calibre.ebooks.oeb.base import ( + serialize, OEB_DOCS, barename, OEB_STYLES, XPNSMAP, XHTML, SVG) +from calibre.ebooks.oeb.polish.container import OPF_NAMESPACES +from calibre.ebooks.oeb.polish.utils import guess_type +from calibre.utils.icu import sort_key + + +def isspace(x): + return not x.strip('\u0009\u000a\u000c\u000d\u0020') + + +def pretty_xml_tree(elem, level=0, indent=' '): + ''' XML beautifier, assumes that elements that have children do not have + textual content. Also assumes that there is no text immediately after + closing tags. These are true for opf/ncx and container.xml files. If either + of the assumptions are violated, there should be no data loss, but pretty + printing wont produce optimal results.''' + if (not elem.text and len(elem) > 0) or (elem.text and isspace(elem.text)): + elem.text = '\n' + (indent * (level+1)) + for i, child in enumerate(elem): + pretty_xml_tree(child, level=level+1, indent=indent) + if not child.tail or isspace(child.tail): + l = level + 1 + if i == len(elem) - 1: + l -= 1 + child.tail = '\n' + (indent * l) + + +def pretty_opf(root): + # Put all dc: tags first starting with title and author. Preserve order for + # the rest. + def dckey(x): + return {'title':0, 'creator':1}.get(barename(x.tag), 2) + for metadata in root.xpath('//opf:metadata', namespaces=OPF_NAMESPACES): + dc_tags = metadata.xpath('./*[namespace-uri()="%s"]' % OPF_NAMESPACES['dc']) + dc_tags.sort(key=dckey) + for x in reversed(dc_tags): + metadata.insert(0, x) + + # Group items in the manifest + spine_ids = root.xpath('//opf:spine/opf:itemref/@idref', namespaces=OPF_NAMESPACES) + spine_ids = {x:i for i, x in enumerate(spine_ids)} + + def manifest_key(x): + mt = x.get('media-type', '') + href = x.get('href', '') + ext = href.rpartition('.')[-1].lower() + cat = 1000 + if mt in OEB_DOCS: + cat = 0 + elif mt == guess_type('a.ncx'): + cat = 1 + elif mt in OEB_STYLES: + cat = 2 + elif mt.startswith('image/'): + cat = 3 + elif ext in {'otf', 'ttf', 'woff'}: + cat = 4 + elif mt.startswith('audio/'): + cat = 5 + elif mt.startswith('video/'): + cat = 6 + + if cat == 0: + i = spine_ids.get(x.get('id', None), 1000000000) + else: + i = sort_key(href) + return (cat, i) + + for manifest in root.xpath('//opf:manifest', namespaces=OPF_NAMESPACES): + try: + children = sorted(manifest, key=manifest_key) + except AttributeError: + continue # There are comments so dont sort since that would mess up the comments + for x in reversed(children): + manifest.insert(0, x) + + +SVG_TAG = SVG('svg') +BLOCK_TAGS = frozenset(map(XHTML, ( + 'address', 'article', 'aside', 'audio', 'blockquote', 'body', 'canvas', 'col', 'colgroup', 'dd', + 'div', 'dl', 'dt', 'fieldset', 'figcaption', 'figure', 'footer', 'form', + 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup', 'hr', 'li', + 'noscript', 'ol', 'output', 'p', 'pre', 'script', 'section', 'style', 'table', 'tbody', 'td', + 'tfoot', 'th', 'thead', 'tr', 'ul', 'video', 'img'))) | {SVG_TAG} + + +def isblock(x): + if callable(x.tag) or not x.tag: + return True + if x.tag in BLOCK_TAGS: + return True + return False + + +def has_only_blocks(x): + if hasattr(x.tag, 'split') and len(x) == 0: + # Tag with no children, + return False + if x.text and not isspace(x.text): + return False + for child in x: + if not isblock(child) or (child.tail and not isspace(child.tail)): + return False + return True + + +def indent_for_tag(x): + prev = x.getprevious() + x = x.getparent().text if prev is None else prev.tail + if not x: + return '' + s = x.rpartition('\n')[-1] + return s if isspace(s) else '' + + +def set_indent(elem, attr, indent): + x = getattr(elem, attr) + if not x: + x = indent + else: + lines = x.splitlines() + if isspace(lines[-1]): + lines[-1] = indent + else: + lines.append(indent) + x = '\n'.join(lines) + setattr(elem, attr, x) + + +def pretty_block(parent, level=1, indent=' '): + ''' Surround block tags with blank lines and recurse into child block tags + that contain only other block tags ''' + if not parent.text or isspace(parent.text): + parent.text = '' + nn = '\n' if hasattr(parent.tag, 'strip') and barename(parent.tag) in {'tr', 'td', 'th'} else '\n\n' + parent.text = parent.text + nn + (indent * level) + for i, child in enumerate(parent): + if isblock(child) and has_only_blocks(child): + pretty_block(child, level=level+1, indent=indent) + elif child.tag == SVG_TAG: + pretty_xml_tree(child, level=level, indent=indent) + l = level + if i == len(parent) - 1: + l -= 1 + if not child.tail or isspace(child.tail): + child.tail = '' + child.tail = child.tail + nn + (indent * l) + + +def pretty_script_or_style(container, child): + if child.text: + indent = indent_for_tag(child) + if child.tag.endswith('style'): + child.text = force_unicode(pretty_css(container, '', child.text), 'utf-8') + child.text = textwrap.dedent(child.text) + child.text = '\n' + '\n'.join([(indent + x) if x else '' for x in child.text.splitlines()]) + set_indent(child, 'text', indent) + + +def pretty_html_tree(container, root): + root.text = '\n\n' + for child in root: + child.tail = '\n\n' + if hasattr(child.tag, 'endswith') and child.tag.endswith('}head'): + pretty_xml_tree(child) + for body in root.findall('h:body', namespaces=XPNSMAP): + pretty_block(body) + # Special case the handling of a body that contains a single block tag + # with all content. In this case we prettify the containing block tag + # even if it has non block children. + if (len(body) == 1 and not callable(body[0].tag) and isblock(body[0]) and not has_only_blocks( + body[0]) and barename(body[0].tag) not in ( + 'pre', 'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6') and len(body[0]) > 0): + pretty_block(body[0], level=2) + + if container is not None: + # Handle

``, ``

`` and ``

`` tags. + ''' + tocroot = TOC() + xpaths = [XPath(xp) for xp in xpaths] + + # Find those levels that have no elements in all spine items + maps = OrderedDict() + empty_levels = {i+1 for i, xp in enumerate(xpaths)} + for spinepath in container.spine_items: + name = container.abspath_to_name(spinepath) + root = container.parsed(name) + level_item_map = maps[name] = {i+1:frozenset(xp(root)) for i, xp in enumerate(xpaths)} + for lvl, elems in iteritems(level_item_map): + if elems: + empty_levels.discard(lvl) + # Remove empty levels from all level_maps + if empty_levels: + for name, lmap in tuple(iteritems(maps)): + lmap = {lvl:items for lvl, items in iteritems(lmap) if lvl not in empty_levels} + lmap = sorted(iteritems(lmap), key=itemgetter(0)) + lmap = {i+1:items for i, (l, items) in enumerate(lmap)} + maps[name] = lmap + + node_level_map = {tocroot: 0} + + def parent_for_level(child_level): + limit = child_level - 1 + + def process_node(node): + child = node.last_child + if child is None: + return node + lvl = node_level_map[child] + return node if lvl > limit else child if lvl == limit else process_node(child) + + return process_node(tocroot) + + for name, level_item_map in iteritems(maps): + root = container.parsed(name) + item_level_map = {e:i for i, elems in iteritems(level_item_map) for e in elems} + item_dirtied = False + all_ids = set(root.xpath('//*/@id')) + + for item in root.iterdescendants(etree.Element): + lvl = item_level_map.get(item, None) + if lvl is None: + continue + text = elem_to_toc_text(item) + parent = parent_for_level(lvl) + if item_at_top(item): + dirtied, elem_id = False, None + else: + dirtied, elem_id = ensure_id(item, all_ids) + item_dirtied = dirtied or item_dirtied + toc = parent.add(text, name, elem_id) + node_level_map[toc] = lvl + toc.dest_exists = True + + if item_dirtied: + container.commit_item(name, keep_parsed=True) + + return tocroot + + +def from_links(container): + ''' + Generate a Table of Contents from links in the book. + ''' + toc = TOC() + link_path = XPath('//h:a[@href]') + seen_titles, seen_dests = set(), set() + for name, is_linear in container.spine_names: + root = container.parsed(name) + for a in link_path(root): + href = a.get('href') + if not href or not href.strip(): + continue + frag = None + if href.startswith('#'): + dest = name + frag = href[1:] + else: + href, _, frag = href.partition('#') + dest = container.href_to_name(href, base=name) + frag = frag or None + if (dest, frag) in seen_dests: + continue + seen_dests.add((dest, frag)) + text = elem_to_toc_text(a) + if text in seen_titles: + continue + seen_titles.add(text) + toc.add(text, dest, frag=frag) + verify_toc_destinations(container, toc) + for child in toc: + if not child.dest_exists: + toc.remove(child) + return toc + + +def find_text(node): + LIMIT = 200 + pat = re.compile(r'\s+') + for child in node: + if isinstance(child, etree._Element): + text = xml2text(child).strip() + text = pat.sub(' ', text) + if len(text) < 1: + continue + if len(text) > LIMIT: + # Look for less text in a child of this node, recursively + ntext = find_text(child) + return ntext or (text[:LIMIT] + '...') + else: + return text + + +def from_files(container): + ''' + Generate a Table of Contents from files in the book. + ''' + toc = TOC() + for i, spinepath in enumerate(container.spine_items): + name = container.abspath_to_name(spinepath) + root = container.parsed(name) + body = XPath('//h:body')(root) + if not body: + continue + text = find_text(body[0]) + if not text: + text = name.rpartition('/')[-1] + if i == 0 and text.rpartition('.')[0].lower() in {'titlepage', 'cover'}: + text = _('Cover') + toc.add(text, name) + return toc + + +def node_from_loc(root, locs, totals=None): + node = root.xpath('//*[local-name()="body"]')[0] + for i, loc in enumerate(locs): + children = tuple(node.iterchildren(etree.Element)) + if totals is not None and totals[i] != len(children): + raise MalformedMarkup() + node = children[loc] + return node + + +def add_id(container, name, loc, totals=None): + root = container.parsed(name) + try: + node = node_from_loc(root, loc, totals=totals) + except MalformedMarkup: + # The webkit HTML parser and the container parser have yielded + # different node counts, this can happen if the file is valid XML + # but contains constructs like nested

tags. So force parse it + # with the HTML 5 parser and try again. + raw = container.raw_data(name) + root = container.parse_xhtml(raw, fname=name, force_html5_parse=True) + try: + node = node_from_loc(root, loc, totals=totals) + except MalformedMarkup: + raise MalformedMarkup(_('The file %s has malformed markup. Try running the Fix HTML tool' + ' before editing.') % name) + container.replace(name, root) + + if not node.get('id'): + ensure_id(node, set(root.xpath('//*/@id'))) + container.commit_item(name, keep_parsed=True) + return node.get('id') + + +def create_ncx(toc, to_href, btitle, lang, uid): + lang = lang.replace('_', '-') + ncx = etree.Element(NCX('ncx'), + attrib={'version': '2005-1', XML('lang'): lang}, + nsmap={None: NCX_NS}) + head = etree.SubElement(ncx, NCX('head')) + etree.SubElement(head, NCX('meta'), + name='dtb:uid', content=unicode_type(uid)) + etree.SubElement(head, NCX('meta'), + name='dtb:depth', content=unicode_type(toc.depth)) + generator = ''.join(['calibre (', __version__, ')']) + etree.SubElement(head, NCX('meta'), + name='dtb:generator', content=generator) + etree.SubElement(head, NCX('meta'), name='dtb:totalPageCount', content='0') + etree.SubElement(head, NCX('meta'), name='dtb:maxPageNumber', content='0') + title = etree.SubElement(ncx, NCX('docTitle')) + text = etree.SubElement(title, NCX('text')) + text.text = btitle + navmap = etree.SubElement(ncx, NCX('navMap')) + spat = re.compile(r'\s+') + + play_order = Counter() + + def process_node(xml_parent, toc_parent): + for child in toc_parent: + play_order['c'] += 1 + point = etree.SubElement(xml_parent, NCX('navPoint'), id='num_%d' % play_order['c'], + playOrder=unicode_type(play_order['c'])) + label = etree.SubElement(point, NCX('navLabel')) + title = child.title + if title: + title = spat.sub(' ', title) + etree.SubElement(label, NCX('text')).text = title + if child.dest: + href = to_href(child.dest) + if child.frag: + href += '#'+child.frag + etree.SubElement(point, NCX('content'), src=href) + process_node(point, child) + + process_node(navmap, toc) + return ncx + + +def commit_ncx_toc(container, toc, lang=None, uid=None): + tocname = find_existing_ncx_toc(container) + if tocname is None: + item = container.generate_item('toc.ncx', id_prefix='toc') + tocname = container.href_to_name(item.get('href'), base=container.opf_name) + ncx_id = item.get('id') + [s.set('toc', ncx_id) for s in container.opf_xpath('//opf:spine')] + if not lang: + lang = get_lang() + for l in container.opf_xpath('//dc:language'): + l = canonicalize_lang(xml2text(l).strip()) + if l: + lang = l + lang = lang_as_iso639_1(l) or l + break + lang = lang_as_iso639_1(lang) or lang + if not uid: + uid = uuid_id() + eid = container.opf.get('unique-identifier', None) + if eid: + m = container.opf_xpath('//*[@id="%s"]'%eid) + if m: + uid = xml2text(m[0]) + + title = _('Table of Contents') + m = container.opf_xpath('//dc:title') + if m: + x = xml2text(m[0]).strip() + title = x or title + + to_href = partial(container.name_to_href, base=tocname) + root = create_ncx(toc, to_href, title, lang, uid) + container.replace(tocname, root) + container.pretty_print.add(tocname) + + +def ensure_single_nav_of_type(root, ntype='toc'): + et = '{%s}type' % EPUB_NS + navs = [n for n in root.iterdescendants(XHTML('nav')) if n.get(et) == ntype] + for x in navs[1:]: + extract(x) + if navs: + nav = navs[0] + tail = nav.tail + attrib = dict(nav.attrib) + nav.clear() + nav.attrib.update(attrib) + nav.tail = tail + else: + nav = root.makeelement(XHTML('nav')) + first_child(root, XHTML('body')).append(nav) + nav.set('{%s}type' % EPUB_NS, ntype) + return nav + + +def commit_nav_toc(container, toc, lang=None, landmarks=None, previous_nav=None): + from calibre.ebooks.oeb.polish.pretty import pretty_xml_tree + tocname = find_existing_nav_toc(container) + if previous_nav is not None: + nav_name = container.href_to_name(previous_nav[0]) + if nav_name and container.exists(nav_name): + tocname = nav_name + container.apply_unique_properties(tocname, 'nav') + if tocname is None: + item = container.generate_item('nav.xhtml', id_prefix='nav') + item.set('properties', 'nav') + tocname = container.href_to_name(item.get('href'), base=container.opf_name) + if previous_nav is not None: + root = previous_nav[1] + else: + root = container.parse_xhtml(P('templates/new_nav.html', data=True).decode('utf-8')) + container.replace(tocname, root) + else: + root = container.parsed(tocname) + if lang: + lang = lang_as_iso639_1(lang) or lang + root.set('lang', lang) + root.set('{%s}lang' % XML_NS, lang) + nav = ensure_single_nav_of_type(root, 'toc') + if toc.toc_title: + nav.append(nav.makeelement(XHTML('h1'))) + nav[-1].text = toc.toc_title + + rnode = nav.makeelement(XHTML('ol')) + nav.append(rnode) + to_href = partial(container.name_to_href, base=tocname) + spat = re.compile(r'\s+') + + def process_node(xml_parent, toc_parent): + for child in toc_parent: + li = xml_parent.makeelement(XHTML('li')) + xml_parent.append(li) + title = child.title or '' + title = spat.sub(' ', title).strip() + a = li.makeelement(XHTML('a' if child.dest else 'span')) + a.text = title + li.append(a) + if child.dest: + href = to_href(child.dest) + if child.frag: + href += '#'+child.frag + a.set('href', href) + if len(child): + ol = li.makeelement(XHTML('ol')) + li.append(ol) + process_node(ol, child) + process_node(rnode, toc) + pretty_xml_tree(nav) + + def collapse_li(parent): + for li in parent.iterdescendants(XHTML('li')): + if len(li) == 1: + li.text = None + li[0].tail = None + collapse_li(nav) + nav.tail = '\n' + + def create_li(ol, entry): + li = ol.makeelement(XHTML('li')) + ol.append(li) + a = li.makeelement(XHTML('a')) + li.append(a) + href = container.name_to_href(entry['dest'], tocname) + if entry['frag']: + href += '#' + entry['frag'] + a.set('href', href) + return a + + if landmarks is not None: + nav = ensure_single_nav_of_type(root, 'landmarks') + nav.set('hidden', '') + ol = nav.makeelement(XHTML('ol')) + nav.append(ol) + for entry in landmarks: + if entry['type'] and container.has_name(entry['dest']) and container.mime_map[entry['dest']] in OEB_DOCS: + a = create_li(ol, entry) + a.set('{%s}type' % EPUB_NS, entry['type']) + a.text = entry['title'] or None + pretty_xml_tree(nav) + collapse_li(nav) + + if toc.page_list: + nav = ensure_single_nav_of_type(root, 'page-list') + nav.set('hidden', '') + ol = nav.makeelement(XHTML('ol')) + nav.append(ol) + for entry in toc.page_list: + if container.has_name(entry['dest']) and container.mime_map[entry['dest']] in OEB_DOCS: + a = create_li(ol, entry) + a.text = unicode_type(entry['pagenum']) + pretty_xml_tree(nav) + collapse_li(nav) + container.replace(tocname, root) + + +def commit_toc(container, toc, lang=None, uid=None): + commit_ncx_toc(container, toc, lang=lang, uid=uid) + if container.opf_version_parsed.major > 2: + commit_nav_toc(container, toc, lang=lang) + + +def remove_names_from_toc(container, names): + changed = [] + names = frozenset(names) + for find_toc, parse_toc, commit_toc in ( + (find_existing_ncx_toc, parse_ncx, commit_ncx_toc), + (find_existing_nav_toc, parse_nav, commit_nav_toc), + ): + toc = get_x_toc(container, find_toc, parse_toc, verify_destinations=False) + if len(toc) > 0: + remove = [] + for node in toc.iterdescendants(): + if node.dest in names: + remove.append(node) + if remove: + for node in reversed(remove): + node.remove_from_parent() + commit_toc(container, toc) + changed.append(find_toc(container)) + return changed + + +def find_inline_toc(container): + for name, linear in container.spine_names: + if container.parsed(name).xpath('//*[local-name()="body" and @id="calibre_generated_inline_toc"]'): + return name + + +def toc_to_html(toc, container, toc_name, title, lang=None): + + def process_node(html_parent, toc, level=1, indent=' ', style_level=2): + li = html_parent.makeelement(XHTML('li')) + li.tail = '\n'+ (indent*level) + html_parent.append(li) + name, frag = toc.dest, toc.frag + href = '#' + if name: + href = container.name_to_href(name, toc_name) + if frag: + href += '#' + frag + a = li.makeelement(XHTML('a'), href=href) + a.text = toc.title + li.append(a) + if len(toc) > 0: + parent = li.makeelement(XHTML('ul')) + parent.set('class', 'level%d' % (style_level)) + li.append(parent) + a.tail = '\n\n' + (indent*(level+2)) + parent.text = '\n'+(indent*(level+3)) + parent.tail = '\n\n' + (indent*(level+1)) + for child in toc: + process_node(parent, child, level+3, style_level=style_level + 1) + parent[-1].tail = '\n' + (indent*(level+2)) + + E = ElementMaker(namespace=XHTML_NS, nsmap={None:XHTML_NS}) + html = E.html( + E.head( + E.title(title), + E.style(P('templates/inline_toc_styles.css', data=True), type='text/css'), + ), + E.body( + E.h2(title), + E.ul(), + id="calibre_generated_inline_toc", + ) + ) + + ul = html[1][1] + ul.set('class', 'level1') + for child in toc: + process_node(ul, child) + if lang: + html.set('lang', lang) + pretty_html_tree(container, html) + return html + + +def create_inline_toc(container, title=None): + ''' + Create an inline (HTML) Table of Contents from an existing NCX Table of Contents. + + :param title: The title for this table of contents. + ''' + lang = get_book_language(container) + default_title = 'Table of Contents' + if lang: + lang = lang_as_iso639_1(lang) or lang + default_title = translate(lang, default_title) + title = title or default_title + toc = get_toc(container) + if len(toc) == 0: + return None + toc_name = find_inline_toc(container) + + name = toc_name + html = toc_to_html(toc, container, name, title, lang) + raw = serialize(html, 'text/html') + if name is None: + name, c = 'toc.xhtml', 0 + while container.has_name(name): + c += 1 + name = 'toc%d.xhtml' % c + container.add_file(name, raw, spine_index=0) + else: + with container.open(name, 'wb') as f: + f.write(raw) + set_guide_item(container, 'toc', title, name, frag='calibre_generated_inline_toc') + return name diff --git a/ebook_converter/ebooks/oeb/polish/utils.py b/ebook_converter/ebooks/oeb/polish/utils.py new file mode 100644 index 0000000..b502578 --- /dev/null +++ b/ebook_converter/ebooks/oeb/polish/utils.py @@ -0,0 +1,231 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2013, Kovid Goyal ' + +import re, os +from bisect import bisect + +from calibre import guess_type as _guess_type, replace_entities +from polyglot.builtins import filter + + +def guess_type(x): + return _guess_type(x)[0] or 'application/octet-stream' + + +def setup_css_parser_serialization(tab_width=2): + import css_parser + prefs = css_parser.ser.prefs + prefs.indent = tab_width * ' ' + prefs.indentClosingBrace = False + prefs.omitLastSemicolon = False + + +def actual_case_for_name(container, name): + from calibre.utils.filenames import samefile + if not container.exists(name): + raise ValueError('Cannot get actual case for %s as it does not exist' % name) + parts = name.split('/') + base = '' + ans = [] + for i, x in enumerate(parts): + base = '/'.join(ans + [x]) + path = container.name_to_abspath(base) + pdir = os.path.dirname(path) + candidates = {os.path.join(pdir, q) for q in os.listdir(pdir)} + if x in candidates: + correctx = x + else: + for q in candidates: + if samefile(q, path): + correctx = os.path.basename(q) + break + else: + raise RuntimeError('Something bad happened') + ans.append(correctx) + return '/'.join(ans) + + +def corrected_case_for_name(container, name): + parts = name.split('/') + ans = [] + base = '' + for i, x in enumerate(parts): + base = '/'.join(ans + [x]) + if container.exists(base): + correctx = x + else: + try: + candidates = {q for q in os.listdir(os.path.dirname(container.name_to_abspath(base)))} + except EnvironmentError: + return None # one of the non-terminal components of name is a file instead of a directory + for q in candidates: + if q.lower() == x.lower(): + correctx = q + break + else: + return None + ans.append(correctx) + return '/'.join(ans) + + +class PositionFinder(object): + + def __init__(self, raw): + pat = br'\n' if isinstance(raw, bytes) else r'\n' + self.new_lines = tuple(m.start() + 1 for m in re.finditer(pat, raw)) + + def __call__(self, pos): + lnum = bisect(self.new_lines, pos) + try: + offset = abs(pos - self.new_lines[lnum - 1]) + except IndexError: + offset = pos + return (lnum + 1, offset) + + +class CommentFinder(object): + + def __init__(self, raw, pat=r'(?s)/\*.*?\*/'): + self.starts, self.ends = [], [] + for m in re.finditer(pat, raw): + start, end = m.span() + self.starts.append(start), self.ends.append(end) + + def __call__(self, offset): + if not self.starts: + return False + q = bisect(self.starts, offset) - 1 + return q >= 0 and self.starts[q] <= offset <= self.ends[q] + + +def link_stylesheets(container, names, sheets, remove=False, mtype='text/css'): + from calibre.ebooks.oeb.base import XPath, XHTML + changed_names = set() + snames = set(sheets) + lp = XPath('//h:link[@href]') + hp = XPath('//h:head') + for name in names: + root = container.parsed(name) + if remove: + for link in lp(root): + if (link.get('type', mtype) or mtype) == mtype: + container.remove_from_xml(link) + changed_names.add(name) + container.dirty(name) + existing = {container.href_to_name(l.get('href'), name) for l in lp(root) if (l.get('type', mtype) or mtype) == mtype} + extra = snames - existing + if extra: + changed_names.add(name) + try: + parent = hp(root)[0] + except (TypeError, IndexError): + parent = root.makeelement(XHTML('head')) + container.insert_into_xml(root, parent, index=0) + for sheet in sheets: + if sheet in extra: + container.insert_into_xml( + parent, parent.makeelement(XHTML('link'), rel='stylesheet', type=mtype, + href=container.name_to_href(sheet, name))) + container.dirty(name) + + return changed_names + + +def lead_text(top_elem, num_words=10): + ''' Return the leading text contained in top_elem (including descendants) + up to a maximum of num_words words. More efficient than using + etree.tostring(method='text') as it does not have to serialize the entire + sub-tree rooted at top_elem.''' + pat = re.compile(r'\s+', flags=re.UNICODE) + words = [] + + def get_text(x, attr='text'): + ans = getattr(x, attr) + if ans: + words.extend(filter(None, pat.split(ans))) + + stack = [(top_elem, 'text')] + while stack and len(words) < num_words: + elem, attr = stack.pop() + get_text(elem, attr) + if attr == 'text': + if elem is not top_elem: + stack.append((elem, 'tail')) + stack.extend(reversed(list((c, 'text') for c in elem.iterchildren('*')))) + return ' '.join(words[:num_words]) + + +def parse_css(data, fname='', is_declaration=False, decode=None, log_level=None, css_preprocessor=None): + if log_level is None: + import logging + log_level = logging.WARNING + from css_parser import CSSParser, log + from calibre.ebooks.oeb.base import _css_logger + log.setLevel(log_level) + log.raiseExceptions = False + data = data or '' + if isinstance(data, bytes): + data = data.decode('utf-8') if decode is None else decode(data) + if css_preprocessor is not None: + data = css_preprocessor(data) + parser = CSSParser(loglevel=log_level, + # We dont care about @import rules + fetcher=lambda x: (None, None), log=_css_logger) + if is_declaration: + data = parser.parseStyle(data, validate=False) + else: + data = parser.parseString(data, href=fname, validate=False) + return data + + +def handle_entities(text, func): + return func(replace_entities(text)) + + +def apply_func_to_match_groups(match, func=icu_upper, handle_entities=handle_entities): + '''Apply the specified function to individual groups in the match object (the result of re.search() or + the whole match if no groups were defined. Returns the replaced string.''' + found_groups = False + i = 0 + parts, pos = [], match.start() + f = lambda text:handle_entities(text, func) + while True: + i += 1 + try: + start, end = match.span(i) + except IndexError: + break + found_groups = True + if start > -1: + parts.append(match.string[pos:start]) + parts.append(f(match.string[start:end])) + pos = end + if not found_groups: + return f(match.group()) + parts.append(match.string[pos:match.end()]) + return ''.join(parts) + + +def apply_func_to_html_text(match, func=icu_upper, handle_entities=handle_entities): + ''' Apply the specified function only to text between HTML tag definitions. ''' + f = lambda text:handle_entities(text, func) + parts = re.split(r'(<[^>]+>)', match.group()) + parts = (x if x.startswith('<') else f(x) for x in parts) + return ''.join(parts) + + +def extract(elem): + ''' Remove an element from the tree, keeping elem.tail ''' + p = elem.getparent() + if p is not None: + idx = p.index(elem) + p.remove(elem) + if elem.tail: + if idx > 0: + p[idx-1].tail = (p[idx-1].tail or '') + elem.tail + else: + p.text = (p.text or '') + elem.tail diff --git a/ebook_converter/ebooks/oeb/reader.py b/ebook_converter/ebooks/oeb/reader.py new file mode 100644 index 0000000..2c248a8 --- /dev/null +++ b/ebook_converter/ebooks/oeb/reader.py @@ -0,0 +1,720 @@ +""" +Container-/OPF-based input OEBBook reader. +""" +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2008, Marshall T. Vandegrift ' + +import sys, os, uuid, copy, re, io +from collections import defaultdict + +from lxml import etree + +from calibre.ebooks.oeb.base import OPF1_NS, OPF2_NS, OPF2_NSMAP, DC11_NS, \ + DC_NSES, OPF, xml2text, XHTML_MIME +from calibre.ebooks.oeb.base import OEB_DOCS, OEB_STYLES, OEB_IMAGES, \ + PAGE_MAP_MIME, JPEG_MIME, NCX_MIME, SVG_MIME +from calibre.ebooks.oeb.base import XMLDECL_RE, COLLAPSE_RE, \ + MS_COVER_TYPE, iterlinks +from calibre.ebooks.oeb.base import namespace, barename, XPath, xpath, \ + urlnormalize, BINARY_MIME, \ + OEBError, OEBBook, DirContainer +from calibre.ebooks.oeb.writer import OEBWriter +from calibre.utils.xml_parse import safe_xml_fromstring +from calibre.utils.cleantext import clean_xml_chars +from calibre.utils.localization import get_lang +from calibre.ptempfile import TemporaryDirectory +from calibre.constants import __appname__, __version__ +from calibre import guess_type, xml_replace_entities +from polyglot.builtins import unicode_type, zip +from polyglot.urllib import unquote, urldefrag, urlparse + +__all__ = ['OEBReader'] + + +class OEBReader(object): + """Read an OEBPS 1.x or OPF/OPS 2.0 file collection.""" + + COVER_SVG_XP = XPath('h:body//svg:svg[position() = 1]') + COVER_OBJECT_XP = XPath('h:body//h:object[@data][position() = 1]') + + Container = DirContainer + """Container type used to access book files. Override in sub-classes.""" + + DEFAULT_PROFILE = 'PRS505' + """Default renderer profile for content read with this Reader.""" + + TRANSFORMS = [] + """List of transforms to apply to content read with this Reader.""" + + @classmethod + def config(cls, cfg): + """Add any book-reading options to the :class:`Config` object + :param:`cfg`. + """ + return + + @classmethod + def generate(cls, opts): + """Generate a Reader instance from command-line options.""" + return cls() + + def __call__(self, oeb, path): + """Read the book at :param:`path` into the :class:`OEBBook` object + :param:`oeb`. + """ + self.oeb = oeb + self.logger = self.log = oeb.logger + oeb.container = self.Container(path, self.logger) + oeb.container.log = oeb.log + opf = self._read_opf() + self._all_from_opf(opf) + return oeb + + def _clean_opf(self, opf): + nsmap = {} + for elem in opf.iter(tag=etree.Element): + nsmap.update(elem.nsmap) + for elem in opf.iter(tag=etree.Element): + if namespace(elem.tag) in ('', OPF1_NS) and ':' not in barename(elem.tag): + elem.tag = OPF(barename(elem.tag)) + nsmap.update(OPF2_NSMAP) + attrib = dict(opf.attrib) + nroot = etree.Element(OPF('package'), + nsmap={None: OPF2_NS}, attrib=attrib) + metadata = etree.SubElement(nroot, OPF('metadata'), nsmap=nsmap) + ignored = (OPF('dc-metadata'), OPF('x-metadata')) + for elem in xpath(opf, 'o2:metadata//*'): + if elem.tag in ignored: + continue + if namespace(elem.tag) in DC_NSES: + tag = barename(elem.tag).lower() + elem.tag = '{%s}%s' % (DC11_NS, tag) + if elem.tag.startswith('dc:'): + tag = elem.tag.partition(':')[-1].lower() + elem.tag = '{%s}%s' % (DC11_NS, tag) + metadata.append(elem) + for element in xpath(opf, 'o2:metadata//o2:meta'): + metadata.append(element) + for tag in ('o2:manifest', 'o2:spine', 'o2:tours', 'o2:guide'): + for element in xpath(opf, tag): + nroot.append(element) + return nroot + + def _read_opf(self): + data = self.oeb.container.read(None) + data = self.oeb.decode(data) + data = XMLDECL_RE.sub('', data) + data = re.sub(r'http://openebook.org/namespaces/oeb-package/1.0(/*)', + OPF1_NS, data) + try: + opf = safe_xml_fromstring(data) + except etree.XMLSyntaxError: + data = xml_replace_entities(clean_xml_chars(data), encoding=None) + try: + opf = safe_xml_fromstring(data) + self.logger.warn('OPF contains invalid HTML named entities') + except etree.XMLSyntaxError: + data = re.sub(r'(?is).+', '', data) + data = data.replace('', + '') + opf = safe_xml_fromstring(data) + self.logger.warn('OPF contains invalid tours section') + + ns = namespace(opf.tag) + if ns not in ('', OPF1_NS, OPF2_NS): + raise OEBError('Invalid namespace %r for OPF document' % ns) + opf = self._clean_opf(opf) + return opf + + def _metadata_from_opf(self, opf): + from calibre.ebooks.metadata.opf2 import OPF + from calibre.ebooks.oeb.transforms.metadata import meta_info_to_oeb_metadata + stream = io.BytesIO(etree.tostring(opf, xml_declaration=True, encoding='utf-8')) + o = OPF(stream) + pwm = o.primary_writing_mode + if pwm: + self.oeb.metadata.primary_writing_mode = pwm + mi = o.to_book_metadata() + if not mi.language: + mi.language = get_lang().replace('_', '-') + self.oeb.metadata.add('language', mi.language) + if not mi.book_producer: + mi.book_producer = '%(a)s (%(v)s) [http://%(a)s-ebook.com]'%\ + dict(a=__appname__, v=__version__) + meta_info_to_oeb_metadata(mi, self.oeb.metadata, self.logger) + m = self.oeb.metadata + m.add('identifier', unicode_type(uuid.uuid4()), id='uuid_id', scheme='uuid') + self.oeb.uid = self.oeb.metadata.identifier[-1] + if not m.title: + m.add('title', self.oeb.translate(__('Unknown'))) + has_aut = False + for x in m.creator: + if getattr(x, 'role', '').lower() in ('', 'aut'): + has_aut = True + break + if not has_aut: + m.add('creator', self.oeb.translate(__('Unknown')), role='aut') + + def _manifest_prune_invalid(self): + ''' + Remove items from manifest that contain invalid data. This prevents + catastrophic conversion failure, when a few files contain corrupted + data. + ''' + bad = [] + check = OEB_DOCS.union(OEB_STYLES) + for item in list(self.oeb.manifest.values()): + if item.media_type in check: + try: + item.data + except KeyboardInterrupt: + raise + except: + self.logger.exception('Failed to parse content in %s'% + item.href) + bad.append(item) + self.oeb.manifest.remove(item) + return bad + + def _manifest_add_missing(self, invalid): + import css_parser + manifest = self.oeb.manifest + known = set(manifest.hrefs) + unchecked = set(manifest.values()) + cdoc = OEB_DOCS|OEB_STYLES + invalid = set() + while unchecked: + new = set() + for item in unchecked: + data = None + if (item.media_type in cdoc or item.media_type[-4:] in ('/xml', '+xml')): + try: + data = item.data + except: + self.oeb.log.exception('Failed to read from manifest ' + 'entry with id: %s, ignoring'%item.id) + invalid.add(item) + continue + if data is None: + continue + + if (item.media_type in OEB_DOCS or item.media_type[-4:] in ('/xml', '+xml')): + hrefs = [r[2] for r in iterlinks(data)] + for href in hrefs: + if isinstance(href, bytes): + href = href.decode('utf-8') + href, _ = urldefrag(href) + if not href: + continue + try: + href = item.abshref(urlnormalize(href)) + scheme = urlparse(href).scheme + except: + self.oeb.log.exception( + 'Skipping invalid href: %r'%href) + continue + if not scheme and href not in known: + new.add(href) + elif item.media_type in OEB_STYLES: + try: + urls = list(css_parser.getUrls(data)) + except: + urls = [] + for url in urls: + href, _ = urldefrag(url) + href = item.abshref(urlnormalize(href)) + scheme = urlparse(href).scheme + if not scheme and href not in known: + new.add(href) + unchecked.clear() + warned = set() + for href in new: + known.add(href) + is_invalid = False + for item in invalid: + if href == item.abshref(urlnormalize(href)): + is_invalid = True + break + if is_invalid: + continue + if not self.oeb.container.exists(href): + if href not in warned: + self.logger.warn('Referenced file %r not found' % href) + warned.add(href) + continue + if href not in warned: + self.logger.warn('Referenced file %r not in manifest' % href) + warned.add(href) + id, _ = manifest.generate(id='added') + guessed = guess_type(href)[0] + media_type = guessed or BINARY_MIME + added = manifest.add(id, href, media_type) + unchecked.add(added) + + for item in invalid: + self.oeb.manifest.remove(item) + + def _manifest_from_opf(self, opf): + manifest = self.oeb.manifest + for elem in xpath(opf, '/o2:package/o2:manifest/o2:item'): + id = elem.get('id') + href = elem.get('href') + media_type = elem.get('media-type', None) + if media_type is None: + media_type = elem.get('mediatype', None) + if not media_type or media_type == 'text/xml': + guessed = guess_type(href)[0] + media_type = guessed or media_type or BINARY_MIME + if hasattr(media_type, 'lower'): + media_type = media_type.lower() + fallback = elem.get('fallback') + if href in manifest.hrefs: + self.logger.warn('Duplicate manifest entry for %r' % href) + continue + if not self.oeb.container.exists(href): + self.logger.warn('Manifest item %r not found' % href) + continue + if id in manifest.ids: + self.logger.warn('Duplicate manifest id %r' % id) + id, href = manifest.generate(id, href) + manifest.add(id, href, media_type, fallback) + invalid = self._manifest_prune_invalid() + self._manifest_add_missing(invalid) + + def _spine_add_extra(self): + manifest = self.oeb.manifest + spine = self.oeb.spine + unchecked = set(spine) + selector = XPath('h:body//h:a/@href') + extras = set() + while unchecked: + new = set() + for item in unchecked: + if item.media_type not in OEB_DOCS: + # TODO: handle fallback chains + continue + for href in selector(item.data): + href, _ = urldefrag(href) + if not href: + continue + try: + href = item.abshref(urlnormalize(href)) + except ValueError: # Malformed URL + continue + if href not in manifest.hrefs: + continue + found = manifest.hrefs[href] + if found.media_type not in OEB_DOCS or \ + found in spine or found in extras: + continue + new.add(found) + extras.update(new) + unchecked = new + version = int(self.oeb.version[0]) + removed_items_to_ignore = getattr(self.oeb, 'removed_items_to_ignore', ()) + for item in sorted(extras): + if item.href in removed_items_to_ignore: + continue + if version >= 2: + self.logger.warn( + 'Spine-referenced file %r not in spine' % item.href) + spine.add(item, linear=False) + + def _spine_from_opf(self, opf): + spine = self.oeb.spine + manifest = self.oeb.manifest + for elem in xpath(opf, '/o2:package/o2:spine/o2:itemref'): + idref = elem.get('idref') + if idref not in manifest.ids: + self.logger.warn('Spine item %r not found' % idref) + continue + item = manifest.ids[idref] + if item.media_type.lower() in OEB_DOCS and hasattr(item.data, 'xpath') and not getattr(item.data, 'tag', '').endswith('}ncx'): + spine.add(item, elem.get('linear')) + else: + if hasattr(item.data, 'tag') and item.data.tag and item.data.tag.endswith('}html'): + item.media_type = XHTML_MIME + spine.add(item, elem.get('linear')) + else: + self.oeb.log.warn('The item %s is not a XML document.' + ' Removing it from spine.'%item.href) + if len(spine) == 0: + raise OEBError("Spine is empty") + self._spine_add_extra() + for val in xpath(opf, '/o2:package/o2:spine/@page-progression-direction'): + if val in {'ltr', 'rtl'}: + spine.page_progression_direction = val + + def _guide_from_opf(self, opf): + guide = self.oeb.guide + manifest = self.oeb.manifest + for elem in xpath(opf, '/o2:package/o2:guide/o2:reference'): + ref_href = elem.get('href') + path = urlnormalize(urldefrag(ref_href)[0]) + if path not in manifest.hrefs: + corrected_href = None + for href in manifest.hrefs: + if href.lower() == path.lower(): + corrected_href = href + break + if corrected_href is None: + self.logger.warn('Guide reference %r not found' % ref_href) + continue + ref_href = corrected_href + typ = elem.get('type') + if typ not in guide: + guide.add(typ, elem.get('title'), ref_href) + + def _find_ncx(self, opf): + result = xpath(opf, '/o2:package/o2:spine/@toc') + if result: + id = result[0] + if id not in self.oeb.manifest.ids: + return None + item = self.oeb.manifest.ids[id] + self.oeb.manifest.remove(item) + return item + for item in self.oeb.manifest.values(): + if item.media_type == NCX_MIME: + self.oeb.manifest.remove(item) + return item + return None + + def _toc_from_navpoint(self, item, toc, navpoint): + children = xpath(navpoint, 'ncx:navPoint') + for child in children: + title = ''.join(xpath(child, 'ncx:navLabel/ncx:text/text()')) + title = COLLAPSE_RE.sub(' ', title.strip()) + href = xpath(child, 'ncx:content/@src') + if not title: + self._toc_from_navpoint(item, toc, child) + continue + if (not href or not href[0]) and not xpath(child, 'ncx:navPoint'): + # This node is useless + continue + href = item.abshref(urlnormalize(href[0])) if href and href[0] else '' + path, _ = urldefrag(href) + if path and path not in self.oeb.manifest.hrefs: + path = urlnormalize(path) + if href and path not in self.oeb.manifest.hrefs: + self.logger.warn('TOC reference %r not found' % href) + gc = xpath(child, 'ncx:navPoint') + if not gc: + # This node is useless + continue + id = child.get('id') + klass = child.get('class', 'chapter') + + try: + po = int(child.get('playOrder', self.oeb.toc.next_play_order())) + except: + po = self.oeb.toc.next_play_order() + + authorElement = xpath(child, + 'descendant::calibre:meta[@name = "author"]') + if authorElement: + author = authorElement[0].text + else: + author = None + + descriptionElement = xpath(child, + 'descendant::calibre:meta[@name = "description"]') + if descriptionElement: + description = etree.tostring(descriptionElement[0], + method='text', encoding='unicode').strip() + if not description: + description = None + else: + description = None + + index_image = xpath(child, + 'descendant::calibre:meta[@name = "toc_thumbnail"]') + toc_thumbnail = (index_image[0].text if index_image else None) + if not toc_thumbnail or not toc_thumbnail.strip(): + toc_thumbnail = None + + node = toc.add(title, href, id=id, klass=klass, + play_order=po, description=description, author=author, + toc_thumbnail=toc_thumbnail) + + self._toc_from_navpoint(item, node, child) + + def _toc_from_ncx(self, item): + if (item is None) or (item.data is None): + return False + self.log.debug('Reading TOC from NCX...') + ncx = item.data + title = ''.join(xpath(ncx, 'ncx:docTitle/ncx:text/text()')) + title = COLLAPSE_RE.sub(' ', title.strip()) + title = title or unicode_type(self.oeb.metadata.title[0]) + toc = self.oeb.toc + toc.title = title + navmaps = xpath(ncx, 'ncx:navMap') + for navmap in navmaps: + self._toc_from_navpoint(item, toc, navmap) + return True + + def _toc_from_tour(self, opf): + result = xpath(opf, 'o2:tours/o2:tour') + if not result: + return False + self.log.debug('Reading TOC from tour...') + tour = result[0] + toc = self.oeb.toc + toc.title = tour.get('title') + sites = xpath(tour, 'o2:site') + for site in sites: + title = site.get('title') + href = site.get('href') + if not title or not href: + continue + path, _ = urldefrag(urlnormalize(href)) + if path not in self.oeb.manifest.hrefs: + self.logger.warn('TOC reference %r not found' % href) + continue + id = site.get('id') + toc.add(title, href, id=id) + return True + + def _toc_from_html(self, opf): + if 'toc' not in self.oeb.guide: + return False + self.log.debug('Reading TOC from HTML...') + itempath, frag = urldefrag(self.oeb.guide['toc'].href) + item = self.oeb.manifest.hrefs[itempath] + html = item.data + if frag: + elems = xpath(html, './/*[@id="%s"]' % frag) + if not elems: + elems = xpath(html, './/*[@name="%s"]' % frag) + elem = elems[0] if elems else html + while elem != html and not xpath(elem, './/h:a[@href]'): + elem = elem.getparent() + html = elem + titles = defaultdict(list) + order = [] + for anchor in xpath(html, './/h:a[@href]'): + href = anchor.attrib['href'] + href = item.abshref(urlnormalize(href)) + path, frag = urldefrag(href) + if path not in self.oeb.manifest.hrefs: + continue + title = xml2text(anchor) + title = COLLAPSE_RE.sub(' ', title.strip()) + if href not in titles: + order.append(href) + titles[href].append(title) + toc = self.oeb.toc + for href in order: + toc.add(' '.join(titles[href]), href) + return True + + def _toc_from_spine(self, opf): + self.log.warn('Generating default TOC from spine...') + toc = self.oeb.toc + titles = [] + headers = [] + for item in self.oeb.spine: + if not item.linear: + continue + html = item.data + title = ''.join(xpath(html, '/h:html/h:head/h:title/text()')) + title = COLLAPSE_RE.sub(' ', title.strip()) + if title: + titles.append(title) + headers.append('(unlabled)') + for tag in ('h1', 'h2', 'h3', 'h4', 'h5', 'strong'): + expr = '/h:html/h:body//h:%s[position()=1]/text()' + header = ''.join(xpath(html, expr % tag)) + header = COLLAPSE_RE.sub(' ', header.strip()) + if header: + headers[-1] = header + break + use = titles + if len(titles) > len(set(titles)): + use = headers + for title, item in zip(use, self.oeb.spine): + if not item.linear: + continue + toc.add(title, item.href) + return True + + def _toc_from_opf(self, opf, item): + self.oeb.auto_generated_toc = False + if self._toc_from_ncx(item): + return + # Prefer HTML to tour based TOC, since several LIT files + # have good HTML TOCs but bad tour based TOCs + if self._toc_from_html(opf): + return + if self._toc_from_tour(opf): + return + self._toc_from_spine(opf) + self.oeb.auto_generated_toc = True + + def _pages_from_ncx(self, opf, item): + if item is None: + return False + ncx = item.data + if ncx is None: + return False + ptargets = xpath(ncx, 'ncx:pageList/ncx:pageTarget') + if not ptargets: + return False + pages = self.oeb.pages + for ptarget in ptargets: + name = ''.join(xpath(ptarget, 'ncx:navLabel/ncx:text/text()')) + name = COLLAPSE_RE.sub(' ', name.strip()) + href = xpath(ptarget, 'ncx:content/@src') + if not href: + continue + href = item.abshref(urlnormalize(href[0])) + id = ptarget.get('id') + type = ptarget.get('type', 'normal') + klass = ptarget.get('class') + pages.add(name, href, type=type, id=id, klass=klass) + return True + + def _find_page_map(self, opf): + result = xpath(opf, '/o2:package/o2:spine/@page-map') + if result: + id = result[0] + if id not in self.oeb.manifest.ids: + return None + item = self.oeb.manifest.ids[id] + self.oeb.manifest.remove(item) + return item + for item in self.oeb.manifest.values(): + if item.media_type == PAGE_MAP_MIME: + self.oeb.manifest.remove(item) + return item + return None + + def _pages_from_page_map(self, opf): + item = self._find_page_map(opf) + if item is None: + return False + pmap = item.data + pages = self.oeb.pages + for page in xpath(pmap, 'o2:page'): + name = page.get('name', '') + href = page.get('href') + if not href: + continue + name = COLLAPSE_RE.sub(' ', name.strip()) + href = item.abshref(urlnormalize(href)) + type = 'normal' + if not name: + type = 'special' + elif name.lower().strip('ivxlcdm') == '': + type = 'front' + pages.add(name, href, type=type) + return True + + def _pages_from_opf(self, opf, item): + if self._pages_from_ncx(opf, item): + return + if self._pages_from_page_map(opf): + return + return + + def _cover_from_html(self, hcover): + from calibre.ebooks import render_html_svg_workaround + with TemporaryDirectory('_html_cover') as tdir: + writer = OEBWriter() + writer(self.oeb, tdir) + path = os.path.join(tdir, unquote(hcover.href)) + data = render_html_svg_workaround(path, self.logger) + if not data: + data = b'' + id, href = self.oeb.manifest.generate('cover', 'cover.jpg') + item = self.oeb.manifest.add(id, href, JPEG_MIME, data=data) + return item + + def _locate_cover_image(self): + if self.oeb.metadata.cover: + id = unicode_type(self.oeb.metadata.cover[0]) + item = self.oeb.manifest.ids.get(id, None) + if item is not None and item.media_type in OEB_IMAGES: + return item + else: + self.logger.warn('Invalid cover image @id %r' % id) + hcover = self.oeb.spine[0] + if 'cover' in self.oeb.guide: + href = self.oeb.guide['cover'].href + item = self.oeb.manifest.hrefs[href] + media_type = item.media_type + if media_type in OEB_IMAGES: + return item + elif media_type in OEB_DOCS: + hcover = item + html = hcover.data + if MS_COVER_TYPE in self.oeb.guide: + href = self.oeb.guide[MS_COVER_TYPE].href + item = self.oeb.manifest.hrefs.get(href, None) + if item is not None and item.media_type in OEB_IMAGES: + return item + if self.COVER_SVG_XP(html): + svg = copy.deepcopy(self.COVER_SVG_XP(html)[0]) + href = os.path.splitext(hcover.href)[0] + '.svg' + id, href = self.oeb.manifest.generate(hcover.id, href) + item = self.oeb.manifest.add(id, href, SVG_MIME, data=svg) + return item + if self.COVER_OBJECT_XP(html): + object = self.COVER_OBJECT_XP(html)[0] + href = hcover.abshref(object.get('data')) + item = self.oeb.manifest.hrefs.get(href, None) + if item is not None and item.media_type in OEB_IMAGES: + return item + return self._cover_from_html(hcover) + + def _ensure_cover_image(self): + cover = self._locate_cover_image() + if self.oeb.metadata.cover: + self.oeb.metadata.cover[0].value = cover.id + return + self.oeb.metadata.add('cover', cover.id) + + def _manifest_remove_duplicates(self): + seen = set() + dups = set() + for item in self.oeb.manifest: + if item.href in seen: + dups.add(item.href) + seen.add(item.href) + + for href in dups: + items = [x for x in self.oeb.manifest if x.href == href] + for x in items: + if x not in self.oeb.spine: + self.oeb.log.warn('Removing duplicate manifest item with id:', x.id) + self.oeb.manifest.remove_duplicate_item(x) + + def _all_from_opf(self, opf): + self.oeb.version = opf.get('version', '1.2') + self._metadata_from_opf(opf) + self._manifest_from_opf(opf) + self._spine_from_opf(opf) + self._manifest_remove_duplicates() + self._guide_from_opf(opf) + item = self._find_ncx(opf) + self._toc_from_opf(opf, item) + self._pages_from_opf(opf, item) + # self._ensure_cover_image() + + +def main(argv=sys.argv): + reader = OEBReader() + for arg in argv[1:]: + oeb = reader(OEBBook(), arg) + for name, doc in oeb.to_opf1().values(): + print(etree.tostring(doc, pretty_print=True)) + for name, doc in oeb.to_opf2(page_map=True).values(): + print(etree.tostring(doc, pretty_print=True)) + return 0 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/ebook_converter/ebooks/oeb/stylizer.py b/ebook_converter/ebooks/oeb/stylizer.py new file mode 100644 index 0000000..109cccd --- /dev/null +++ b/ebook_converter/ebooks/oeb/stylizer.py @@ -0,0 +1,808 @@ +# -*- encoding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +''' +CSS property propagation class. +''' + +__license__ = 'GPL v3' +__copyright__ = '2008, Marshall T. Vandegrift ' + +import os, re, logging, copy, unicodedata, numbers +from operator import itemgetter +from weakref import WeakKeyDictionary +from xml.dom import SyntaxErr as CSSSyntaxError +from css_parser.css import (CSSStyleRule, CSSPageRule, CSSFontFaceRule, + cssproperties) +from css_parser import (profile as cssprofiles, parseString, parseStyle, log as + css_parser_log, CSSParser, profiles, replaceUrls) +from calibre import force_unicode, as_unicode +from calibre.ebooks import unit_convert +from calibre.ebooks.oeb.base import XHTML, XHTML_NS, CSS_MIME, OEB_STYLES, xpath, urlnormalize +from calibre.ebooks.oeb.normalize_css import DEFAULTS, normalizers +from css_selectors import Select, SelectorError, INAPPROPRIATE_PSEUDO_CLASSES +from polyglot.builtins import iteritems, unicode_type, filter +from tinycss.media3 import CSSMedia3Parser + +css_parser_log.setLevel(logging.WARN) + +_html_css_stylesheet = None + + +def html_css_stylesheet(): + global _html_css_stylesheet + if _html_css_stylesheet is None: + with open(P('templates/html.css'), 'rb') as f: + html_css = f.read().decode('utf-8') + _html_css_stylesheet = parseString(html_css, validate=False) + return _html_css_stylesheet + + +INHERITED = { + 'azimuth', 'border-collapse', 'border-spacing', 'caption-side', 'color', + 'cursor', 'direction', 'elevation', 'empty-cells', 'font-family', + 'font-size', 'font-style', 'font-variant', 'font-weight', 'letter-spacing', + 'line-height', 'list-style-image', 'list-style-position', + 'list-style-type', 'orphans', 'page-break-inside', 'pitch-range', 'pitch', + 'quotes', 'richness', 'speak-header', 'speak-numeral', 'speak-punctuation', + 'speak', 'speech-rate', 'stress', 'text-align', 'text-indent', + 'text-transform', 'visibility', 'voice-family', 'volume', 'white-space', + 'widows', 'word-spacing', 'text-shadow', +} + +FONT_SIZE_NAMES = { + 'xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large' +} + +ALLOWED_MEDIA_TYPES = frozenset({'screen', 'all', 'aural', 'amzn-kf8'}) +IGNORED_MEDIA_FEATURES = frozenset('width min-width max-width height min-height max-height device-width min-device-width max-device-width device-height min-device-height max-device-height aspect-ratio min-aspect-ratio max-aspect-ratio device-aspect-ratio min-device-aspect-ratio max-device-aspect-ratio color min-color max-color color-index min-color-index max-color-index monochrome min-monochrome max-monochrome -webkit-min-device-pixel-ratio resolution min-resolution max-resolution scan grid'.split()) # noqa + + +def media_ok(raw): + if not raw: + return True + if raw == 'amzn-mobi': # Optimization for the common case + return False + + def query_ok(mq): + matched = True + if mq.media_type not in ALLOWED_MEDIA_TYPES: + matched = False + # Media queries that test for device specific features always fail + for media_feature, expr in mq.expressions: + if media_feature in IGNORED_MEDIA_FEATURES: + matched = False + return mq.negated ^ matched + + try: + for mq in CSSMedia3Parser().parse_stylesheet('@media %s {}' % raw).rules[0].media: + if query_ok(mq): + return True + return False + except Exception: + pass + return True + + +def test_media_ok(): + assert media_ok(None) + assert media_ok('') + assert not media_ok('amzn-mobi') + assert media_ok('amzn-kf8') + assert media_ok('screen') + assert media_ok('only screen') + assert not media_ok('not screen') + assert not media_ok('(device-width:10px)') + assert media_ok('screen, (device-width:10px)') + assert not media_ok('screen and (device-width:10px)') + + +class StylizerRules(object): + + def __init__(self, opts, profile, stylesheets): + self.opts, self.profile, self.stylesheets = opts, profile, stylesheets + + index = 0 + self.rules = [] + self.page_rule = {} + self.font_face_rules = [] + for sheet_index, stylesheet in enumerate(stylesheets): + href = stylesheet.href + for rule in stylesheet.cssRules: + if rule.type == rule.MEDIA_RULE: + if media_ok(rule.media.mediaText): + for subrule in rule.cssRules: + self.rules.extend(self.flatten_rule(subrule, href, index, is_user_agent_sheet=sheet_index==0)) + index += 1 + else: + self.rules.extend(self.flatten_rule(rule, href, index, is_user_agent_sheet=sheet_index==0)) + index = index + 1 + self.rules.sort(key=itemgetter(0)) # sort by specificity + + def flatten_rule(self, rule, href, index, is_user_agent_sheet=False): + results = [] + sheet_index = 0 if is_user_agent_sheet else 1 + if isinstance(rule, CSSStyleRule): + style = self.flatten_style(rule.style) + for selector in rule.selectorList: + specificity = (sheet_index,) + selector.specificity + (index,) + text = selector.selectorText + selector = list(selector.seq) + results.append((specificity, selector, style, text, href)) + elif isinstance(rule, CSSPageRule): + style = self.flatten_style(rule.style) + self.page_rule.update(style) + elif isinstance(rule, CSSFontFaceRule): + if rule.style.length > 1: + # Ignore the meaningless font face rules generated by the + # benighted MS Word that contain only a font-family declaration + # and nothing else + self.font_face_rules.append(rule) + return results + + def flatten_style(self, cssstyle): + style = {} + for prop in cssstyle: + name = prop.name + normalizer = normalizers.get(name, None) + if normalizer is not None: + style.update(normalizer(name, prop.cssValue)) + elif name == 'text-align': + style['text-align'] = self._apply_text_align(prop.value) + else: + style[name] = prop.value + if 'font-size' in style: + size = style['font-size'] + if size == 'normal': + size = 'medium' + if size == 'smallest': + size = 'xx-small' + if size in FONT_SIZE_NAMES: + style['font-size'] = "%.1frem" % (self.profile.fnames[size] / float(self.profile.fbase)) + if '-epub-writing-mode' in style: + for x in ('-webkit-writing-mode', 'writing-mode'): + style[x] = style.get(x, style['-epub-writing-mode']) + return style + + def _apply_text_align(self, text): + if text in ('left', 'justify') and self.opts.change_justification in ('left', 'justify'): + text = self.opts.change_justification + return text + + def same_rules(self, opts, profile, stylesheets): + if self.opts != opts: + # it's unlikely to happen, but better safe than sorry + return False + if self.profile != profile: + return False + if len(self.stylesheets) != len(stylesheets): + return False + for index, stylesheet in enumerate(self.stylesheets): + if stylesheet != stylesheets[index]: + return False + return True + + +class Stylizer(object): + STYLESHEETS = WeakKeyDictionary() + + def __init__(self, tree, path, oeb, opts, profile=None, + extra_css='', user_css='', base_css=''): + self.oeb, self.opts = oeb, opts + self.profile = profile + if self.profile is None: + # Use the default profile. This should really be using + # opts.output_profile, but I don't want to risk changing it, as + # doing so might well have hard to debug font size effects. + from calibre.customize.ui import output_profiles + for x in output_profiles(): + if x.short_name == 'default': + self.profile = x + break + if self.profile is None: + # Just in case the default profile is removed in the future :) + self.profile = opts.output_profile + self.body_font_size = self.profile.fbase + self.logger = oeb.logger + item = oeb.manifest.hrefs[path] + basename = os.path.basename(path) + cssname = os.path.splitext(basename)[0] + '.css' + stylesheets = [html_css_stylesheet()] + if base_css: + stylesheets.append(parseString(base_css, validate=False)) + style_tags = xpath(tree, '//*[local-name()="style" or local-name()="link"]') + + # Add css_parser parsing profiles from output_profile + for profile in self.opts.output_profile.extra_css_modules: + cssprofiles.addProfile(profile['name'], + profile['props'], + profile['macros']) + + parser = CSSParser(fetcher=self._fetch_css_file, + log=logging.getLogger('calibre.css')) + for elem in style_tags: + if (elem.tag == XHTML('style') and elem.get('type', CSS_MIME) in OEB_STYLES and media_ok(elem.get('media'))): + text = elem.text if elem.text else '' + for x in elem: + t = getattr(x, 'text', None) + if t: + text += '\n\n' + force_unicode(t, 'utf-8') + t = getattr(x, 'tail', None) + if t: + text += '\n\n' + force_unicode(t, 'utf-8') + if text: + text = oeb.css_preprocessor(text) + # We handle @import rules separately + parser.setFetcher(lambda x: ('utf-8', b'')) + stylesheet = parser.parseString(text, href=cssname, + validate=False) + parser.setFetcher(self._fetch_css_file) + for rule in stylesheet.cssRules: + if rule.type == rule.IMPORT_RULE: + ihref = item.abshref(rule.href) + if not media_ok(rule.media.mediaText): + continue + hrefs = self.oeb.manifest.hrefs + if ihref not in hrefs: + self.logger.warn('Ignoring missing stylesheet in @import rule:', rule.href) + continue + sitem = hrefs[ihref] + if sitem.media_type not in OEB_STYLES: + self.logger.warn('CSS @import of non-CSS file %r' % rule.href) + continue + stylesheets.append(sitem.data) + # Make links to resources absolute, since these rules will + # be folded into a stylesheet at the root + replaceUrls(stylesheet, item.abshref, + ignoreImportRules=True) + stylesheets.append(stylesheet) + elif (elem.tag == XHTML('link') and elem.get('href') and elem.get( + 'rel', 'stylesheet').lower() == 'stylesheet' and elem.get( + 'type', CSS_MIME).lower() in OEB_STYLES and media_ok(elem.get('media')) + ): + href = urlnormalize(elem.attrib['href']) + path = item.abshref(href) + sitem = oeb.manifest.hrefs.get(path, None) + if sitem is None: + self.logger.warn( + 'Stylesheet %r referenced by file %r not in manifest' % + (path, item.href)) + continue + if not hasattr(sitem.data, 'cssRules'): + self.logger.warn( + 'Stylesheet %r referenced by file %r is not CSS'%(path, + item.href)) + continue + stylesheets.append(sitem.data) + csses = {'extra_css':extra_css, 'user_css':user_css} + for w, x in csses.items(): + if x: + try: + text = x + stylesheet = parser.parseString(text, href=cssname, + validate=False) + stylesheets.append(stylesheet) + except Exception: + self.logger.exception('Failed to parse %s, ignoring.'%w) + self.logger.debug('Bad css: ') + self.logger.debug(x) + + # using oeb to store the rules, page rule and font face rules + # and generating them again if opts, profile or stylesheets are different + if (not hasattr(self.oeb, 'stylizer_rules')) \ + or not self.oeb.stylizer_rules.same_rules(self.opts, self.profile, stylesheets): + self.oeb.stylizer_rules = StylizerRules(self.opts, self.profile, stylesheets) + self.rules = self.oeb.stylizer_rules.rules + self.page_rule = self.oeb.stylizer_rules.page_rule + self.font_face_rules = self.oeb.stylizer_rules.font_face_rules + self.flatten_style = self.oeb.stylizer_rules.flatten_style + + self._styles = {} + pseudo_pat = re.compile(':{1,2}(%s)' % ('|'.join(INAPPROPRIATE_PSEUDO_CLASSES)), re.I) + select = Select(tree, ignore_inappropriate_pseudo_classes=True) + + for _, _, cssdict, text, _ in self.rules: + fl = pseudo_pat.search(text) + try: + matches = tuple(select(text)) + except SelectorError as err: + self.logger.error('Ignoring CSS rule with invalid selector: %r (%s)' % (text, as_unicode(err))) + continue + + if fl is not None: + fl = fl.group(1) + if fl == 'first-letter' and getattr(self.oeb, + 'plumber_output_format', '').lower() in {'mobi', 'docx'}: + # Fake first-letter + for elem in matches: + for x in elem.iter('*'): + if x.text: + punctuation_chars = [] + text = unicode_type(x.text) + while text: + category = unicodedata.category(text[0]) + if category[0] not in {'P', 'Z'}: + break + punctuation_chars.append(text[0]) + text = text[1:] + + special_text = ''.join(punctuation_chars) + \ + (text[0] if text else '') + span = x.makeelement('{%s}span' % XHTML_NS) + span.text = special_text + span.set('data-fake-first-letter', '1') + span.tail = text[1:] + x.text = None + x.insert(0, span) + self.style(span)._update_cssdict(cssdict) + break + else: # Element pseudo-class + for elem in matches: + self.style(elem)._update_pseudo_class(fl, cssdict) + else: + for elem in matches: + self.style(elem)._update_cssdict(cssdict) + for elem in xpath(tree, '//h:*[@style]'): + self.style(elem)._apply_style_attr(url_replacer=item.abshref) + num_pat = re.compile(r'[0-9.]+$') + for elem in xpath(tree, '//h:img[@width or @height]'): + style = self.style(elem) + # Check if either height or width is not default + is_styled = style._style.get('width', 'auto') != 'auto' or \ + style._style.get('height', 'auto') != 'auto' + if not is_styled: + # Update img style dimension using width and height + upd = {} + for prop in ('width', 'height'): + val = elem.get(prop, '').strip() + try: + del elem.attrib[prop] + except: + pass + if val: + if num_pat.match(val) is not None: + val += 'px' + upd[prop] = val + if upd: + style._update_cssdict(upd) + + def _fetch_css_file(self, path): + hrefs = self.oeb.manifest.hrefs + if path not in hrefs: + self.logger.warn('CSS import of missing file %r' % path) + return (None, None) + item = hrefs[path] + if item.media_type not in OEB_STYLES: + self.logger.warn('CSS import of non-CSS file %r' % path) + return (None, None) + data = item.data.cssText + if not isinstance(data, bytes): + data = data.encode('utf-8') + return ('utf-8', data) + + def style(self, element): + try: + return self._styles[element] + except KeyError: + return Style(element, self) + + def stylesheet(self, name, font_scale=None): + rules = [] + for _, _, style, selector, href in self.rules: + if href != name: + continue + if font_scale and 'font-size' in style and \ + style['font-size'].endswith('pt'): + style = copy.copy(style) + size = float(style['font-size'][:-2]) + style['font-size'] = "%.2fpt" % (size * font_scale) + style = ';\n '.join(': '.join(item) for item in style.items()) + rules.append('%s {\n %s;\n}' % (selector, style)) + return '\n'.join(rules) + + +class Style(object): + MS_PAT = re.compile(r'^\s*(mso-|panose-|text-underline|tab-interval)') + + def __init__(self, element, stylizer): + self._element = element + self._profile = stylizer.profile + self._stylizer = stylizer + self._style = {} + self._fontSize = None + self._width = None + self._height = None + self._lineHeight = None + self._bgcolor = None + self._pseudo_classes = {} + stylizer._styles[element] = self + + def set(self, prop, val): + self._style[prop] = val + + def drop(self, prop, default=None): + return self._style.pop(prop, default) + + def _update_cssdict(self, cssdict): + self._style.update(cssdict) + + def _update_pseudo_class(self, name, cssdict): + orig = self._pseudo_classes.get(name, {}) + orig.update(cssdict) + self._pseudo_classes[name] = orig + + def _apply_style_attr(self, url_replacer=None): + attrib = self._element.attrib + if 'style' not in attrib: + return + css = attrib['style'].split(';') + css = filter(None, (x.strip() for x in css)) + css = [y.strip() for y in css] + css = [y for y in css if self.MS_PAT.match(y) is None] + css = '; '.join(css) + try: + style = parseStyle(css, validate=False) + except CSSSyntaxError: + return + if url_replacer is not None: + replaceUrls(style, url_replacer, ignoreImportRules=True) + self._style.update(self._stylizer.flatten_style(style)) + + def _has_parent(self): + try: + return self._element.getparent() is not None + except AttributeError: + return False # self._element is None + + def _get_parent(self): + elem = self._element.getparent() + if elem is None: + return None + return self._stylizer.style(elem) + + def __getitem__(self, name): + domname = cssproperties._toDOMname(name) + if hasattr(self, domname): + return getattr(self, domname) + return self._unit_convert(self._get(name)) + + def _get(self, name): + result = None + if name in self._style: + result = self._style[name] + if (result == 'inherit' or (result is None and name in INHERITED and self._has_parent())): + stylizer = self._stylizer + result = stylizer.style(self._element.getparent())._get(name) + if result is None: + result = DEFAULTS[name] + return result + + def get(self, name, default=None): + return self._style.get(name, default) + + def _unit_convert(self, value, base=None, font=None): + 'Return value in pts' + if base is None: + base = self.width + if not font and font != 0: + font = self.fontSize + return unit_convert(value, base, font, self._profile.dpi, body_font_size=self._stylizer.body_font_size) + + def pt_to_px(self, value): + return (self._profile.dpi / 72) * value + + @property + def backgroundColor(self): + ''' + Return the background color by parsing both the background-color and + background shortcut properties. Note that inheritance/default values + are not used. None is returned if no background color is set. + ''' + + def validate_color(col): + return cssprofiles.validateWithProfile('color', + col, + profiles=[profiles.Profiles.CSS_LEVEL_2])[1] + + if self._bgcolor is None: + col = None + val = self._style.get('background-color', None) + if val and validate_color(val): + col = val + else: + val = self._style.get('background', None) + if val is not None: + try: + style = parseStyle('background: '+val, validate=False) + val = style.getProperty('background').cssValue + try: + val = list(val) + except: + # val is CSSPrimitiveValue + val = [val] + for c in val: + c = c.cssText + if isinstance(c, bytes): + c = c.decode('utf-8', 'replace') + if validate_color(c): + col = c + break + except: + pass + if col is None: + self._bgcolor = False + else: + self._bgcolor = col + return self._bgcolor if self._bgcolor else None + + @property + def fontSize(self): + def normalize_fontsize(value, base): + value = value.replace('"', '').replace("'", '') + result = None + factor = None + if value == 'inherit': + value = base + if value in FONT_SIZE_NAMES: + result = self._profile.fnames[value] + elif value == 'smaller': + factor = 1.0/1.2 + for _, _, size in self._profile.fsizes: + if base <= size: + break + factor = None + result = size + elif value == 'larger': + factor = 1.2 + for _, _, size in reversed(self._profile.fsizes): + if base >= size: + break + factor = None + result = size + else: + result = self._unit_convert(value, base=base, font=base) + if not isinstance(result, numbers.Number): + return base + if result < 0: + result = normalize_fontsize("smaller", base) + if factor: + result = factor * base + return result + if self._fontSize is None: + result = None + parent = self._get_parent() + if parent is not None: + base = parent.fontSize + else: + base = self._profile.fbase + if 'font-size' in self._style: + size = self._style['font-size'] + result = normalize_fontsize(size, base) + else: + result = base + self._fontSize = result + return self._fontSize + + def img_dimension(self, attr, img_size): + ans = None + parent = self._get_parent() + if parent is not None: + base = getattr(parent, attr) + else: + base = getattr(self._profile, attr + '_pts') + x = self._style.get(attr) + if x is not None: + if x == 'auto': + ans = self._unit_convert(unicode_type(img_size) + 'px', base=base) + else: + x = self._unit_convert(x, base=base) + if isinstance(x, numbers.Number): + ans = x + if ans is None: + x = self._element.get(attr) + if x is not None: + x = self._unit_convert(x + 'px', base=base) + if isinstance(x, numbers.Number): + ans = x + if ans is None: + ans = self._unit_convert(unicode_type(img_size) + 'px', base=base) + maa = self._style.get('max-' + attr) + if maa is not None: + x = self._unit_convert(maa, base=base) + if isinstance(x, numbers.Number) and (ans is None or x < ans): + ans = x + return ans + + def img_size(self, width, height): + ' Return the final size of an given that it points to an image of size widthxheight ' + w, h = self._get('width'), self._get('height') + answ, ansh = self.img_dimension('width', width), self.img_dimension('height', height) + if w == 'auto' and h != 'auto': + answ = (float(width)/height) * ansh + elif h == 'auto' and w != 'auto': + ansh = (float(height)/width) * answ + return answ, ansh + + @property + def width(self): + if self._width is None: + width = None + base = None + parent = self._get_parent() + if parent is not None: + base = parent.width + else: + base = self._profile.width_pts + if 'width' in self._element.attrib: + width = self._element.attrib['width'] + elif 'width' in self._style: + width = self._style['width'] + if not width or width == 'auto': + result = base + else: + result = self._unit_convert(width, base=base) + if isinstance(result, (unicode_type, bytes)): + result = self._profile.width + self._width = result + if 'max-width' in self._style: + result = self._unit_convert(self._style['max-width'], base=base) + if isinstance(result, (unicode_type, bytes)): + result = self._width + if result < self._width: + self._width = result + + return self._width + + @property + def parent_width(self): + parent = self._get_parent() + if parent is None: + return self.width + return parent.width + + @property + def height(self): + if self._height is None: + height = None + base = None + parent = self._get_parent() + if parent is not None: + base = parent.height + else: + base = self._profile.height_pts + if 'height' in self._element.attrib: + height = self._element.attrib['height'] + elif 'height' in self._style: + height = self._style['height'] + if not height or height == 'auto': + result = base + else: + result = self._unit_convert(height, base=base) + if isinstance(result, (unicode_type, bytes)): + result = self._profile.height + self._height = result + if 'max-height' in self._style: + result = self._unit_convert(self._style['max-height'], base=base) + if isinstance(result, (unicode_type, bytes)): + result = self._height + if result < self._height: + self._height = result + + return self._height + + @property + def lineHeight(self): + if self._lineHeight is None: + result = None + parent = self._get_parent() + if 'line-height' in self._style: + lineh = self._style['line-height'] + if lineh == 'normal': + lineh = '1.2' + try: + result = float(lineh) * self.fontSize + except ValueError: + result = self._unit_convert(lineh, base=self.fontSize) + elif parent is not None: + # TODO: proper inheritance + result = parent.lineHeight + else: + result = 1.2 * self.fontSize + self._lineHeight = result + return self._lineHeight + + @property + def effective_text_decoration(self): + ''' + Browsers do this creepy thing with text-decoration where even though the + property is not inherited, it looks like it is because containing + blocks apply it. The actual algorithm is utterly ridiculous, see + http://reference.sitepoint.com/css/text-decoration + This matters for MOBI output, where text-decoration is mapped to + and tags. Trying to implement the actual algorithm is too much + work, so we just use a simple fake that should cover most cases. + ''' + css = self._style.get('text-decoration', None) + pcss = None + parent = self._get_parent() + if parent is not None: + pcss = parent._style.get('text-decoration', None) + if css in ('none', None, 'inherit') and pcss not in (None, 'none'): + return pcss + return css + + @property + def first_vertical_align(self): + ''' For docx output where tags are not nested, we cannot directly + simulate the HTML vertical-align rendering model. Instead use the + approximation of considering the first non-default vertical-align ''' + val = self['vertical-align'] + if val != 'baseline': + raw_val = self._get('vertical-align') + if '%' in raw_val: + val = self._unit_convert(raw_val, base=self['line-height']) + return val + parent = self._get_parent() + if parent is not None and 'inline' in parent['display']: + return parent.first_vertical_align + + @property + def marginTop(self): + return self._unit_convert( + self._get('margin-top'), base=self.parent_width) + + @property + def marginBottom(self): + return self._unit_convert( + self._get('margin-bottom'), base=self.parent_width) + + @property + def marginLeft(self): + return self._unit_convert( + self._get('margin-left'), base=self.parent_width) + + @property + def marginRight(self): + return self._unit_convert( + self._get('margin-right'), base=self.parent_width) + + @property + def paddingTop(self): + return self._unit_convert( + self._get('padding-top'), base=self.parent_width) + + @property + def paddingBottom(self): + return self._unit_convert( + self._get('padding-bottom'), base=self.parent_width) + + @property + def paddingLeft(self): + return self._unit_convert( + self._get('padding-left'), base=self.parent_width) + + @property + def paddingRight(self): + return self._unit_convert( + self._get('padding-right'), base=self.parent_width) + + def __str__(self): + items = sorted(iteritems(self._style)) + return '; '.join("%s: %s" % (key, val) for key, val in items) + + def cssdict(self): + return dict(self._style) + + def pseudo_classes(self, filter_css): + if filter_css: + css = copy.deepcopy(self._pseudo_classes) + for psel, cssdict in iteritems(css): + for k in filter_css: + cssdict.pop(k, None) + else: + css = self._pseudo_classes + return {k:v for k, v in iteritems(css) if v} + + @property + def is_hidden(self): + return self._style.get('display') == 'none' or self._style.get('visibility') == 'hidden' diff --git a/ebook_converter/ebooks/oeb/transforms/__init__.py b/ebook_converter/ebooks/oeb/transforms/__init__.py new file mode 100644 index 0000000..720ff71 --- /dev/null +++ b/ebook_converter/ebooks/oeb/transforms/__init__.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2009, Kovid Goyal ' +__docformat__ = 'restructuredtext en' diff --git a/ebook_converter/ebooks/oeb/transforms/data_url.py b/ebook_converter/ebooks/oeb/transforms/data_url.py new file mode 100644 index 0000000..829354c --- /dev/null +++ b/ebook_converter/ebooks/oeb/transforms/data_url.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2014, Kovid Goyal ' + +import re +from calibre.ebooks.oeb.base import XPath, urlunquote +from polyglot.builtins import as_bytes + + +class DataURL(object): + + def __call__(self, oeb, opts): + from calibre.utils.imghdr import what + self.log = oeb.log + attr_path = XPath('//h:img[@src]') + for item in oeb.spine: + root = item.data + if not hasattr(root, 'xpath'): + continue + for img in attr_path(root): + raw = img.get('src', '') + if not raw.startswith('data:'): + continue + header, data = raw.partition(',')[0::2] + if not header.startswith('data:image/') or not data: + continue + if ';base64' in header: + data = re.sub(r'\s+', '', data) + from polyglot.binary import from_base64_bytes + try: + data = from_base64_bytes(data) + except Exception: + self.log.error('Found invalid base64 encoded data URI, ignoring it') + continue + else: + data = urlunquote(data) + data = as_bytes(data) + fmt = what(None, data) + if not fmt: + self.log.warn('Image encoded as data URL has unknown format, ignoring') + continue + img.set('src', item.relhref(self.convert_image_data_uri(data, fmt, oeb))) + + def convert_image_data_uri(self, data, fmt, oeb): + self.log('Found image encoded as data URI converting it to normal image') + from calibre import guess_type + item_id, item_href = oeb.manifest.generate('data-url-image', 'data-url-image.' + fmt) + oeb.manifest.add(item_id, item_href, guess_type(item_href)[0], data=data) + return item_href diff --git a/ebook_converter/ebooks/oeb/transforms/flatcss.py b/ebook_converter/ebooks/oeb/transforms/flatcss.py new file mode 100644 index 0000000..43c2b19 --- /dev/null +++ b/ebook_converter/ebooks/oeb/transforms/flatcss.py @@ -0,0 +1,684 @@ +''' +CSS flattening transform. +''' +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2008, Marshall T. Vandegrift ' + +import re, operator, math, numbers +from collections import defaultdict +from xml.dom import SyntaxErr + +from lxml import etree +import css_parser +from css_parser.css import Property + +from calibre import guess_type +from calibre.ebooks import unit_convert +from calibre.ebooks.oeb.base import (XHTML, XHTML_NS, CSS_MIME, OEB_STYLES, + namespace, barename, XPath, css_text) +from calibre.ebooks.oeb.stylizer import Stylizer +from calibre.utils.filenames import ascii_filename, ascii_text +from calibre.utils.icu import numeric_sort_key +from polyglot.builtins import iteritems, unicode_type, string_or_bytes, map + +COLLAPSE = re.compile(r'[ \t\r\n\v]+') +STRIPNUM = re.compile(r'[-0-9]+$') + + +def asfloat(value, default): + if not isinstance(value, numbers.Number): + value = default + return float(value) + + +class KeyMapper(object): + + def __init__(self, sbase, dbase, dkey): + self.sbase = float(sbase) + self.dprop = [(self.relate(x, dbase), float(x)) for x in dkey] + self.cache = {} + + @staticmethod + def relate(size, base): + if size == 0: + return base + size = float(size) + base = float(base) + if abs(size - base) < 0.1: + return 0 + sign = -1 if size < base else 1 + endp = 0 if size < base else 36 + diff = (abs(base - size) * 3) + ((36 - size) / 100) + logb = abs(base - endp) + if logb == 1.0: + logb = 1.1 + try: + result = sign * math.log(diff, logb) + except ValueError: + if diff < 0: + # Size is both very large and close to base + return 0 + if logb == 0: + logb = 1e-6 + if diff == 0: + diff = 1e-6 + result = sign * math.log(diff, logb) + return result + + def __getitem__(self, ssize): + ssize = asfloat(ssize, 0) + if ssize in self.cache: + return self.cache[ssize] + dsize = self.map(ssize) + self.cache[ssize] = dsize + return dsize + + def map(self, ssize): + sbase = self.sbase + prop = self.relate(ssize, sbase) + diff = [(abs(prop - p), s) for p, s in self.dprop] + dsize = min(diff)[1] + return dsize + + +class ScaleMapper(object): + + def __init__(self, sbase, dbase): + self.dscale = float(dbase) / float(sbase) + + def __getitem__(self, ssize): + ssize = asfloat(ssize, 0) + dsize = ssize * self.dscale + return dsize + + +class NullMapper(object): + + def __init__(self): + pass + + def __getitem__(self, ssize): + return ssize + + +def FontMapper(sbase=None, dbase=None, dkey=None): + if sbase and dbase and dkey: + return KeyMapper(sbase, dbase, dkey) + elif sbase and dbase: + return ScaleMapper(sbase, dbase) + else: + return NullMapper() + + +class EmbedFontsCSSRules(object): + + def __init__(self, body_font_family, rules): + self.body_font_family, self.rules = body_font_family, rules + self.href = None + + def __call__(self, oeb): + if not self.body_font_family: + return None + if not self.href: + iid, href = oeb.manifest.generate('page_styles', 'page_styles.css') + rules = [css_text(x) for x in self.rules] + rules = '\n\n'.join(rules) + sheet = css_parser.parseString(rules, validate=False) + self.href = oeb.manifest.add(iid, href, guess_type(href)[0], + data=sheet).href + return self.href + + +class CSSFlattener(object): + + def __init__(self, fbase=None, fkey=None, lineh=None, unfloat=False, + untable=False, page_break_on_body=False, specializer=None, + transform_css_rules=()): + self.fbase = fbase + self.transform_css_rules = transform_css_rules + if self.transform_css_rules: + from calibre.ebooks.css_transform_rules import compile_rules + self.transform_css_rules = compile_rules(self.transform_css_rules) + self.fkey = fkey + self.lineh = lineh + self.unfloat = unfloat + self.untable = untable + self.specializer = specializer + self.page_break_on_body = page_break_on_body + + @classmethod + def config(cls, cfg): + return cfg + + @classmethod + def generate(cls, opts): + return cls() + + def __call__(self, oeb, context): + oeb.logger.info('Flattening CSS and remapping font sizes...') + self.context = self.opts = context + self.oeb = oeb + self.items = list(self.oeb.spine) + titlepage = self.oeb.guide.get('titlepage') + if titlepage is not None: + titlepage = titlepage.item + if titlepage is not None and titlepage not in self.items: + self.items.append(titlepage) + epub3_nav = None + if getattr(self.opts, 'epub3_nav_href', None): + epub3_nav = self.oeb.manifest.hrefs.get(self.opts.epub3_nav_href) + if epub3_nav is not None and epub3_nav not in self.items: + self.items.append(epub3_nav) + + self.filter_css = frozenset() + if self.opts.filter_css: + try: + self.filter_css = {x.strip().lower() for x in + self.opts.filter_css.split(',')} + except: + self.oeb.log.warning('Failed to parse filter_css, ignoring') + else: + from calibre.ebooks.oeb.normalize_css import normalize_filter_css + self.filter_css = frozenset(normalize_filter_css(self.filter_css)) + self.oeb.log.debug('Filtering CSS properties: %s'% + ', '.join(self.filter_css)) + + for item in oeb.manifest.values(): + # Make all links to resources absolute, as these sheets will be + # consolidated into a single stylesheet at the root of the document + if item.media_type in OEB_STYLES: + css_parser.replaceUrls(item.data, item.abshref, + ignoreImportRules=True) + + self.body_font_family, self.embed_font_rules = self.get_embed_font_info( + self.opts.embed_font_family) + # Store for use in output plugins/transforms that generate content, + # like the AZW3 output inline ToC. + self.oeb.store_embed_font_rules = EmbedFontsCSSRules(self.body_font_family, + self.embed_font_rules) + self.stylize_spine() + self.sbase = self.baseline_spine() if self.fbase else None + self.fmap = FontMapper(self.sbase, self.fbase, self.fkey) + self.flatten_spine() + if epub3_nav is not None: + self.opts.epub3_nav_parsed = epub3_nav.data + + self.store_page_margins() + + def store_page_margins(self): + self.opts._stored_page_margins = {} + for item, stylizer in iteritems(self.stylizers): + margins = self.opts._stored_page_margins[item.href] = {} + for prop, val in stylizer.page_rule.items(): + p, w = prop.partition('-')[::2] + if p == 'margin': + margins[w] = unit_convert( + val, stylizer.profile.width_pts, stylizer.body_font_size, + stylizer.profile.dpi, body_font_size=stylizer.body_font_size) + + def get_embed_font_info(self, family, failure_critical=True): + efi = [] + body_font_family = None + if not family: + return body_font_family, efi + from calibre.utils.fonts.scanner import font_scanner, NoFonts + from calibre.utils.fonts.utils import panose_to_css_generic_family + try: + faces = font_scanner.fonts_for_family(family) + except NoFonts: + msg = ('No embeddable fonts found for family: %r'%family) + if failure_critical: + raise ValueError(msg) + self.oeb.log.warn(msg) + return body_font_family, efi + if not faces: + msg = ('No embeddable fonts found for family: %r'%family) + if failure_critical: + raise ValueError(msg) + self.oeb.log.warn(msg) + return body_font_family, efi + + for i, font in enumerate(faces): + ext = 'otf' if font['is_otf'] else 'ttf' + fid, href = self.oeb.manifest.generate(id=u'font', + href='fonts/%s.%s'%(ascii_filename(font['full_name']).replace(' ', '-'), ext)) + item = self.oeb.manifest.add(fid, href, + guess_type('dummy.'+ext)[0], + data=font_scanner.get_font_data(font)) + item.unload_data_from_memory() + + cfont = { + 'font-family': '"%s"'%font['font-family'], + 'panose-1': ' '.join(map(unicode_type, font['panose'])), + 'src': 'url(%s)'%item.href, + } + + if i == 0: + generic_family = panose_to_css_generic_family(font['panose']) + body_font_family = "'%s',%s"%(font['font-family'], generic_family) + self.oeb.log('Embedding font: %s'%font['font-family']) + for k in ('font-weight', 'font-style', 'font-stretch'): + if font[k] != 'normal': + cfont[k] = font[k] + rule = '@font-face { %s }'%('; '.join('%s:%s'%(k, v) for k, v in + iteritems(cfont))) + rule = css_parser.parseString(rule) + efi.append(rule) + + return body_font_family, efi + + def stylize_spine(self): + self.stylizers = {} + profile = self.context.source + css = '' + for item in self.items: + html = item.data + body = html.find(XHTML('body')) + if 'style' in html.attrib: + b = body.attrib.get('style', '') + body.set('style', html.get('style') + ';' + b) + del html.attrib['style'] + bs = body.get('style', '').split(';') + bs.append('margin-top: 0pt') + bs.append('margin-bottom: 0pt') + if float(self.context.margin_left) >= 0: + bs.append('margin-left : %gpt'% + float(self.context.margin_left)) + if float(self.context.margin_right) >= 0: + bs.append('margin-right : %gpt'% + float(self.context.margin_right)) + bs.extend(['padding-left: 0pt', 'padding-right: 0pt']) + if self.page_break_on_body: + bs.extend(['page-break-before: always']) + if self.context.change_justification != 'original': + bs.append('text-align: '+ self.context.change_justification) + if self.body_font_family: + bs.append('font-family: '+self.body_font_family) + body.set('style', '; '.join(bs)) + stylizer = Stylizer(html, item.href, self.oeb, self.context, profile, + user_css=self.context.extra_css, + extra_css=css) + self.stylizers[item] = stylizer + + def baseline_node(self, node, stylizer, sizes, csize): + csize = stylizer.style(node)['font-size'] + if node.text: + sizes[csize] += len(COLLAPSE.sub(' ', node.text)) + for child in node: + self.baseline_node(child, stylizer, sizes, csize) + if child.tail: + sizes[csize] += len(COLLAPSE.sub(' ', child.tail)) + + def baseline_spine(self): + sizes = defaultdict(float) + for item in self.items: + html = item.data + stylizer = self.stylizers[item] + body = html.find(XHTML('body')) + fsize = self.context.source.fbase + self.baseline_node(body, stylizer, sizes, fsize) + try: + sbase = max(list(sizes.items()), key=operator.itemgetter(1))[0] + except: + sbase = 12.0 + self.oeb.logger.info( + "Source base font size is %0.05fpt" % sbase) + return sbase + + def clean_edges(self, cssdict, style, fsize): + slineh = self.sbase * 1.26 + dlineh = self.lineh + for kind in ('margin', 'padding'): + for edge in ('bottom', 'top'): + property = "%s-%s" % (kind, edge) + if property not in cssdict: + continue + if '%' in cssdict[property]: + continue + value = style[property] + if value == 0: + continue + elif value <= slineh: + cssdict[property] = "%0.5fem" % (dlineh / fsize) + else: + try: + value = round(value / slineh) * dlineh + except: + self.oeb.logger.warning( + 'Invalid length:', value) + value = 0.0 + cssdict[property] = "%0.5fem" % (value / fsize) + + def flatten_node(self, node, stylizer, names, styles, pseudo_styles, psize, item_id, recurse=True): + if not isinstance(node.tag, string_or_bytes) \ + or namespace(node.tag) != XHTML_NS: + return + tag = barename(node.tag) + style = stylizer.style(node) + cssdict = style.cssdict() + try: + font_size = style['font-size'] + except: + font_size = self.sbase if self.sbase is not None else \ + self.context.source.fbase + if tag == 'body' and isinstance(font_size, numbers.Number): + stylizer.body_font_size = font_size + if 'align' in node.attrib: + if tag != 'img': + cssdict['text-align'] = node.attrib['align'] + if cssdict['text-align'] == 'center': + # align=center causes tables to be center aligned, + # which text-align does not. And the ever trustworthy Word + # uses this construct in its HTML output. See + # https://bugs.launchpad.net/bugs/1569583 + if tag == 'table': + if 'margin-left' not in cssdict and 'margin-right' not in cssdict: + cssdict['margin-left'] = cssdict['margin-right'] = 'auto' + else: + for table in node.iterchildren(XHTML("table")): + ts = stylizer.style(table) + if ts.get('margin-left') is None and ts.get('margin-right') is None: + ts.set('margin-left', 'auto') + ts.set('margin-right', 'auto') + else: + val = node.attrib['align'] + if val in ('middle', 'bottom', 'top'): + cssdict['vertical-align'] = val + elif val in ('left', 'right'): + cssdict['float'] = val + del node.attrib['align'] + if 'valign' in node.attrib and tag == 'td': + if cssdict.get('vertical-align') == 'inherit': + cssdict['vertical-align'] = node.attrib['valign'] + del node.attrib['valign'] + if node.tag == XHTML('font'): + tags = ['descendant::h:%s'%x for x in ('p', 'div', 'table', 'h1', + 'h2', 'h3', 'h4', 'h5', 'h6', 'ol', 'ul', 'dl', 'blockquote')] + tag = 'div' if XPath('|'.join(tags))(node) else 'span' + node.tag = XHTML(tag) + if 'size' in node.attrib: + def force_int(raw): + return int(re.search(r'([0-9+-]+)', raw).group(1)) + size = node.attrib['size'].strip() + if size: + fnums = self.context.source.fnums + if size[0] in ('+', '-'): + # Oh, the warcrimes + try: + esize = 3 + force_int(size) + except: + esize = 3 + if esize < 1: + esize = 1 + if esize > 7: + esize = 7 + font_size = fnums[esize] + else: + try: + font_size = fnums[force_int(size)] + except: + font_size = fnums[3] + cssdict['font-size'] = '%.1fpt'%font_size + del node.attrib['size'] + if 'face' in node.attrib: + cssdict['font-family'] = node.attrib['face'] + del node.attrib['face'] + if 'color' in node.attrib: + try: + cssdict['color'] = Property('color', node.attrib['color']).value + except (ValueError, SyntaxErr): + pass + del node.attrib['color'] + if 'bgcolor' in node.attrib: + try: + cssdict['background-color'] = Property('background-color', node.attrib['bgcolor']).value + except (ValueError, SyntaxErr): + pass + del node.attrib['bgcolor'] + if tag == 'ol' and 'type' in node.attrib: + del node.attrib['type'] + if cssdict.get('font-weight', '').lower() == 'medium': + cssdict['font-weight'] = 'normal' # ADE chokes on font-weight medium + + fsize = font_size + is_drop_cap = (cssdict.get('float', None) == 'left' and 'font-size' in cssdict and len(node) == 0 and node.text and ( + len(node.text) == 1 or (len(node.text) == 2 and 0x2000 <= ord(node.text[0]) <= 0x206f))) + # Detect drop caps generated by the docx input plugin + if node.tag and node.tag.endswith('}p') and len(node) == 0 and node.text and len(node.text.strip()) == 1 and \ + not node.tail and 'line-height' in cssdict and 'font-size' in cssdict: + dp = node.getparent() + if dp.tag and dp.tag.endswith('}div') and len(dp) == 1 and not dp.text: + if stylizer.style(dp).cssdict().get('float', None) == 'left': + is_drop_cap = True + if not self.context.disable_font_rescaling and not is_drop_cap: + _sbase = self.sbase if self.sbase is not None else \ + self.context.source.fbase + dyn_rescale = node.attrib.pop('data-calibre-rescale', None) + if dyn_rescale is not None: + try: + dyn_rescale = float(dyn_rescale) / 100 + except Exception: + dyn_rescale = 1 + fsize = self.fmap[_sbase] + fsize *= dyn_rescale + cssdict['font-size'] = '%0.5fem'%(fsize/psize) + psize = fsize + elif 'font-size' in cssdict or tag == 'body': + fsize = self.fmap[font_size] + try: + cssdict['font-size'] = "%0.5fem" % (fsize / psize) + except ZeroDivisionError: + cssdict['font-size'] = '%.1fpt'%fsize + psize = fsize + + try: + minlh = self.context.minimum_line_height / 100. + slh = style['line-height'] + if not is_drop_cap and isinstance(slh, numbers.Number) and slh < minlh * fsize: + cssdict['line-height'] = unicode_type(minlh) + except Exception: + self.oeb.logger.exception('Failed to set minimum line-height') + + if cssdict: + for x in self.filter_css: + popval = cssdict.pop(x, None) + if self.body_font_family and popval and x == 'font-family' \ + and popval.partition(',')[0][1:-1] == self.body_font_family.partition(',')[0][1:-1]: + cssdict[x] = popval + + if cssdict: + if self.lineh and self.fbase and tag != 'body': + self.clean_edges(cssdict, style, psize) + if 'display' in cssdict and cssdict['display'] == 'in-line': + cssdict['display'] = 'inline' + if self.unfloat and 'float' in cssdict \ + and cssdict.get('display', 'none') != 'none': + del cssdict['display'] + if self.untable and 'display' in cssdict \ + and cssdict['display'].startswith('table'): + display = cssdict['display'] + if display == 'table-cell': + cssdict['display'] = 'inline' + else: + cssdict['display'] = 'block' + if 'vertical-align' in cssdict \ + and cssdict['vertical-align'] == 'sup': + cssdict['vertical-align'] = 'super' + if self.lineh and 'line-height' not in cssdict: + lineh = self.lineh / psize + cssdict['line-height'] = "%0.5fem" % lineh + + if (self.context.remove_paragraph_spacing or self.context.insert_blank_line) and tag in ('p', 'div'): + if item_id != 'calibre_jacket' or self.context.output_profile.name == 'Kindle': + for prop in ('margin', 'padding', 'border'): + for edge in ('top', 'bottom'): + cssdict['%s-%s'%(prop, edge)] = '0pt' + if self.context.insert_blank_line: + cssdict['margin-top'] = cssdict['margin-bottom'] = \ + '%fem'%self.context.insert_blank_line_size + indent_size = self.context.remove_paragraph_spacing_indent_size + keep_indents = indent_size < 0.0 + if (self.context.remove_paragraph_spacing and not keep_indents and cssdict.get('text-align', None) not in ('center', 'right')): + cssdict['text-indent'] = "%1.1fem" % indent_size + + pseudo_classes = style.pseudo_classes(self.filter_css) + if cssdict or pseudo_classes: + keep_classes = set() + + if cssdict: + items = sorted(iteritems(cssdict)) + css = ';\n'.join(u'%s: %s' % (key, val) for key, val in items) + classes = node.get('class', '').strip() or 'calibre' + classes_list = classes.split() + # lower() because otherwise if the document uses the same class + # name with different case, both cases will apply, leading + # to incorrect results. + klass = ascii_text(STRIPNUM.sub('', classes_list[0])).lower().strip().replace(' ', '_') + if css in styles: + match = styles[css] + else: + match = klass + unicode_type(names[klass] or '') + styles[css] = match + names[klass] += 1 + node.attrib['class'] = match + keep_classes.add(match) + + for psel, cssdict in iteritems(pseudo_classes): + items = sorted(iteritems(cssdict)) + css = ';\n'.join('%s: %s' % (key, val) for key, val in items) + pstyles = pseudo_styles[psel] + if css in pstyles: + match = pstyles[css] + else: + # We have to use a different class for each psel as + # otherwise you can have incorrect styles for a situation + # like: a:hover { color: red } a:link { color: blue } a.x:hover { color: green } + # If the pcalibre class for a:hover and a:link is the same, + # then the class attribute for a.x tags will contain both + # that class and the class for a.x:hover, which is wrong. + klass = 'pcalibre' + match = klass + unicode_type(names[klass] or '') + pstyles[css] = match + names[klass] += 1 + keep_classes.add(match) + node.attrib['class'] = ' '.join(keep_classes) + + elif 'class' in node.attrib: + del node.attrib['class'] + if 'style' in node.attrib: + del node.attrib['style'] + if recurse: + for child in node: + self.flatten_node(child, stylizer, names, styles, pseudo_styles, psize, item_id) + + def flatten_head(self, item, href, global_href): + html = item.data + head = html.find(XHTML('head')) + + def safe_lower(x): + try: + x = x.lower() + except Exception: + pass + return x + + for node in html.xpath('//*[local-name()="style" or local-name()="link"]'): + if node.tag == XHTML('link') \ + and safe_lower(node.get('rel', 'stylesheet')) == 'stylesheet' \ + and safe_lower(node.get('type', CSS_MIME)) in OEB_STYLES: + node.getparent().remove(node) + elif node.tag == XHTML('style') \ + and node.get('type', CSS_MIME) in OEB_STYLES: + node.getparent().remove(node) + href = item.relhref(href) + l = etree.SubElement(head, XHTML('link'), + rel='stylesheet', type=CSS_MIME, href=href) + l.tail='\n' + if global_href: + href = item.relhref(global_href) + l = etree.SubElement(head, XHTML('link'), + rel='stylesheet', type=CSS_MIME, href=href) + l.tail = '\n' + + def replace_css(self, css): + manifest = self.oeb.manifest + for item in manifest.values(): + if item.media_type in OEB_STYLES: + manifest.remove(item) + id, href = manifest.generate('css', 'stylesheet.css') + sheet = css_parser.parseString(css, validate=False) + if self.transform_css_rules: + from calibre.ebooks.css_transform_rules import transform_sheet + transform_sheet(self.transform_css_rules, sheet) + item = manifest.add(id, href, CSS_MIME, data=sheet) + self.oeb.manifest.main_stylesheet = item + return href + + def collect_global_css(self): + global_css = defaultdict(list) + for item in self.items: + stylizer = self.stylizers[item] + if float(self.context.margin_top) >= 0: + stylizer.page_rule['margin-top'] = '%gpt'%\ + float(self.context.margin_top) + if float(self.context.margin_bottom) >= 0: + stylizer.page_rule['margin-bottom'] = '%gpt'%\ + float(self.context.margin_bottom) + items = sorted(stylizer.page_rule.items()) + css = ';\n'.join("%s: %s" % (key, val) for key, val in items) + css = ('@page {\n%s\n}\n'%css) if items else '' + rules = [css_text(r) for r in stylizer.font_face_rules + self.embed_font_rules] + raw = '\n\n'.join(rules) + css += '\n\n' + raw + global_css[css].append(item) + + gc_map = {} + manifest = self.oeb.manifest + for css in global_css: + href = None + if css.strip(): + id_, href = manifest.generate('page_css', 'page_styles.css') + sheet = css_parser.parseString(css, validate=False) + if self.transform_css_rules: + from calibre.ebooks.css_transform_rules import transform_sheet + transform_sheet(self.transform_css_rules, sheet) + manifest.add(id_, href, CSS_MIME, data=sheet) + gc_map[css] = href + + ans = {} + for css, items in iteritems(global_css): + for item in items: + ans[item] = gc_map[css] + return ans + + def flatten_spine(self): + names = defaultdict(int) + styles, pseudo_styles = {}, defaultdict(dict) + for item in self.items: + html = item.data + stylizer = self.stylizers[item] + if self.specializer is not None: + self.specializer(item, stylizer) + fsize = self.context.dest.fbase + self.flatten_node(html, stylizer, names, styles, pseudo_styles, fsize, item.id, recurse=False) + self.flatten_node(html.find(XHTML('body')), stylizer, names, styles, pseudo_styles, fsize, item.id) + items = sorted(((key, val) for (val, key) in iteritems(styles)), key=lambda x:numeric_sort_key(x[0])) + # :hover must come after link and :active must come after :hover + psels = sorted(pseudo_styles, key=lambda x : + {'hover':1, 'active':2}.get(x, 0)) + for psel in psels: + styles = pseudo_styles[psel] + if not styles: + continue + x = sorted(((k+':'+psel, v) for v, k in iteritems(styles))) + items.extend(x) + + css = ''.join(".%s {\n%s;\n}\n\n" % (key, val) for key, val in items) + + href = self.replace_css(css) + global_css = self.collect_global_css() + for item in self.items: + stylizer = self.stylizers[item] + self.flatten_head(item, href, global_css[item]) diff --git a/ebook_converter/ebooks/oeb/transforms/guide.py b/ebook_converter/ebooks/oeb/transforms/guide.py new file mode 100644 index 0000000..e935d79 --- /dev/null +++ b/ebook_converter/ebooks/oeb/transforms/guide.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2009, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + + +class Clean(object): + '''Clean up guide, leaving only known values ''' + + def __call__(self, oeb, opts): + self.oeb, self.log, self.opts = oeb, oeb.log, opts + + if 'cover' not in self.oeb.guide: + covers = [] + for x in ('other.ms-coverimage-standard', 'coverimagestandard', + 'other.ms-titleimage-standard', 'other.ms-titleimage', + 'other.ms-coverimage', 'other.ms-thumbimage-standard', + 'other.ms-thumbimage', 'thumbimagestandard'): + if x in self.oeb.guide: + href = self.oeb.guide[x].href + try: + item = self.oeb.manifest.hrefs[href] + except KeyError: + continue + else: + covers.append([self.oeb.guide[x], len(item.data)]) + + covers.sort(key=lambda x: x[1], reverse=True) + if covers: + ref = covers[0][0] + if len(covers) > 1: + self.log('Choosing %s:%s as the cover'%(ref.type, ref.href)) + ref.type = 'cover' + self.oeb.guide.refs['cover'] = ref + + if ('start' in self.oeb.guide and 'text' not in self.oeb.guide): + # Prefer text to start as per the OPF 2.0 spec + x = self.oeb.guide['start'] + self.oeb.guide.add('text', x.title, x.href) + self.oeb.guide.remove('start') + + for x in list(self.oeb.guide): + if x.lower() not in { + 'cover', 'titlepage', 'masthead', 'toc', 'title-page', + 'copyright-page', 'text', 'index', 'glossary', + 'acknowledgements', 'bibliography', 'colophon', + 'copyright-page', 'dedication', 'epigraph', 'foreword', + 'loi', 'lot', 'notes', 'preface'}: + item = self.oeb.guide[x] + if item.title and item.title.lower() == 'start': + continue + self.oeb.guide.remove(x) diff --git a/ebook_converter/ebooks/oeb/transforms/jacket.py b/ebook_converter/ebooks/oeb/transforms/jacket.py new file mode 100644 index 0000000..24f1aa9 --- /dev/null +++ b/ebook_converter/ebooks/oeb/transforms/jacket.py @@ -0,0 +1,395 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2009, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import sys, os, re +from xml.sax.saxutils import escape +from string import Formatter + +from calibre import guess_type, strftime +from calibre.constants import iswindows +from calibre.ebooks.oeb.base import XPath, XHTML_NS, XHTML, xml2text, urldefrag, urlnormalize +from calibre.library.comments import comments_to_html, markdown +from calibre.utils.date import is_date_undefined, as_local_time +from calibre.utils.icu import sort_key +from calibre.ebooks.chardet import strip_encoding_declarations +from calibre.ebooks.metadata import fmt_sidx, rating_to_stars +from polyglot.builtins import unicode_type, map + +JACKET_XPATH = '//h:meta[@name="calibre-content" and @content="jacket"]' + + +class SafeFormatter(Formatter): + + def get_value(self, *args, **kwargs): + try: + return Formatter.get_value(self, *args, **kwargs) + except KeyError: + return '' + + +class Base(object): + + def remove_images(self, item, limit=1): + path = XPath('//h:img[@src]') + removed = 0 + for img in path(item.data): + if removed >= limit: + break + href = item.abshref(img.get('src')) + image = self.oeb.manifest.hrefs.get(href) + if image is None: + href = urlnormalize(href) + image = self.oeb.manifest.hrefs.get(href) + if image is not None: + self.oeb.manifest.remove(image) + self.oeb.guide.remove_by_href(href) + img.getparent().remove(img) + removed += 1 + return removed + + +class RemoveFirstImage(Base): + + def remove_first_image(self): + deleted_item = None + for item in self.oeb.spine: + if XPath(JACKET_XPATH)(item.data): + continue + removed = self.remove_images(item) + if removed > 0: + self.log('Removed first image') + body = XPath('//h:body')(item.data) + if body: + raw = xml2text(body[0]).strip() + imgs = XPath('//h:img|//svg:svg')(item.data) + if not raw and not imgs: + self.log('Removing %s as it has no content'%item.href) + self.oeb.manifest.remove(item) + deleted_item = item + break + else: + self.log.warn('Could not find first image to remove') + if deleted_item is not None: + for item in list(self.oeb.toc): + href = urldefrag(item.href)[0] + if href == deleted_item.href: + self.oeb.toc.remove(item) + self.oeb.guide.remove_by_href(deleted_item.href) + + def __call__(self, oeb, opts, metadata): + ''' + Add metadata in jacket.xhtml if specified in opts + If not specified, remove previous jacket instance + ''' + self.oeb, self.opts, self.log = oeb, opts, oeb.log + if opts.remove_first_image: + self.remove_first_image() + + +class Jacket(Base): + ''' + Book jacket manipulation. Remove first image and insert comments at start of + book. + ''' + + def insert_metadata(self, mi): + self.log('Inserting metadata into book...') + + try: + tags = list(map(unicode_type, self.oeb.metadata.subject)) + except Exception: + tags = [] + + try: + comments = unicode_type(self.oeb.metadata.description[0]) + except: + comments = '' + + try: + title = unicode_type(self.oeb.metadata.title[0]) + except: + title = _('Unknown') + + try: + authors = list(map(unicode_type, self.oeb.metadata.creator)) + except: + authors = [_('Unknown')] + + root = render_jacket(mi, self.opts.output_profile, + alt_title=title, alt_tags=tags, alt_authors=authors, + alt_comments=comments, rescale_fonts=True) + id, href = self.oeb.manifest.generate('calibre_jacket', 'jacket.xhtml') + + jacket = self.oeb.manifest.add(id, href, guess_type(href)[0], data=root) + self.oeb.spine.insert(0, jacket, True) + self.oeb.inserted_metadata_jacket = jacket + for img, path in referenced_images(root): + self.oeb.log('Embedding referenced image %s into jacket' % path) + ext = path.rpartition('.')[-1].lower() + item_id, href = self.oeb.manifest.generate('jacket_image', 'jacket_img.'+ext) + with open(path, 'rb') as f: + item = self.oeb.manifest.add(item_id, href, guess_type(href)[0], data=f.read()) + item.unload_data_from_memory() + img.set('src', jacket.relhref(item.href)) + + def remove_existing_jacket(self): + for x in self.oeb.spine[:4]: + if XPath(JACKET_XPATH)(x.data): + self.remove_images(x, limit=sys.maxsize) + self.oeb.manifest.remove(x) + self.log('Removed existing jacket') + break + + def __call__(self, oeb, opts, metadata): + ''' + Add metadata in jacket.xhtml if specified in opts + If not specified, remove previous jacket instance + ''' + self.oeb, self.opts, self.log = oeb, opts, oeb.log + self.remove_existing_jacket() + if opts.insert_metadata: + self.insert_metadata(metadata) + +# Render Jacket {{{ + + +def get_rating(rating, rchar, e_rchar): + ans = '' + try: + num = float(rating)/2 + except: + return ans + num = max(0, num) + num = min(num, 5) + if num < 1: + return ans + + ans = ("%s%s") % (rchar * int(num), e_rchar * (5 - int(num))) + return ans + + +class Series(unicode_type): + + def __new__(self, series, series_index): + if series and series_index is not None: + roman = _('{1} of {0}').format( + escape(series), escape(fmt_sidx(series_index, use_roman=True))) + combined = _('{1} of {0}').format( + escape(series), escape(fmt_sidx(series_index, use_roman=False))) + else: + combined = roman = escape(series or u'') + s = unicode_type.__new__(self, combined) + s.roman = roman + s.name = escape(series or '') + s.number = escape(fmt_sidx(series_index or 1.0, use_roman=False)) + s.roman_number = escape(fmt_sidx(series_index or 1.0, use_roman=True)) + return s + + +class Tags(unicode_type): + + def __new__(self, tags, output_profile): + tags = [escape(x) for x in tags or ()] + t = unicode_type.__new__(self, ', '.join(tags)) + t.alphabetical = ', '.join(sorted(tags, key=sort_key)) + t.tags_list = tags + return t + + +def postprocess_jacket(root, output_profile, has_data): + # Post-process the generated html to strip out empty header items + + def extract(tag): + parent = tag.getparent() + idx = parent.index(tag) + parent.remove(tag) + if tag.tail: + if idx == 0: + parent.text = (parent.text or '') + tag.tail + else: + if idx >= len(parent): + idx = -1 + parent[-1].tail = (parent[-1].tail or '') + tag.tail + + def extract_class(cls): + for tag in root.xpath('//*[@class="_"]'.replace('_', cls)): + extract(tag) + + for key in 'series rating tags'.split(): + if not has_data[key]: + extract_class('cbj_' + key) + if not has_data['pubdate']: + extract_class('cbj_pubdata') + if output_profile.short_name != 'kindle': + extract_class('cbj_kindle_banner_hr') + + +def render_jacket(mi, output_profile, + alt_title=_('Unknown'), alt_tags=[], alt_comments='', + alt_publisher='', rescale_fonts=False, alt_authors=None): + css = P('jacket/stylesheet.css', data=True).decode('utf-8') + template = P('jacket/template.xhtml', data=True).decode('utf-8') + + template = re.sub(r'', '', template, flags=re.DOTALL) + css = re.sub(r'/\*.*?\*/', '', css, flags=re.DOTALL) + + try: + title_str = alt_title if mi.is_null('title') else mi.title + except: + title_str = _('Unknown') + title_str = escape(title_str) + title = '%s' % title_str + + series = Series(mi.series, mi.series_index) + try: + publisher = mi.publisher if not mi.is_null('publisher') else alt_publisher + except: + publisher = '' + publisher = escape(publisher) + + try: + if is_date_undefined(mi.pubdate): + pubdate = '' + else: + dt = as_local_time(mi.pubdate) + pubdate = strftime('%Y', dt.timetuple()) + except: + pubdate = '' + + rating = get_rating(mi.rating, output_profile.ratings_char, output_profile.empty_ratings_char) + + tags = Tags((mi.tags if mi.tags else alt_tags), output_profile) + + comments = mi.comments if mi.comments else alt_comments + comments = comments.strip() + if comments: + comments = comments_to_html(comments) + + orig = mi.authors + if mi.is_null('authors'): + mi.authors = list(alt_authors or (_('Unknown'),)) + try: + author = mi.format_authors() + except: + author = '' + mi.authors = orig + author = escape(author) + has_data = {} + + def generate_html(comments): + args = dict(xmlns=XHTML_NS, + title_str=title_str, + css=css, + title=title, + author=author, + publisher=publisher, + pubdate_label=_('Published'), pubdate=pubdate, + series_label=_('Series'), series=series, + rating_label=_('Rating'), rating=rating, + tags_label=_('Tags'), tags=tags, + comments=comments, + footer='', + searchable_tags=' '.join(escape(t)+'ttt' for t in tags.tags_list), + ) + for key in mi.custom_field_keys(): + m = mi.get_user_metadata(key, False) or {} + try: + display_name, val = mi.format_field_extended(key)[:2] + dkey = key.replace('#', '_') + dt = m.get('datatype') + if dt == 'series': + args[dkey] = Series(mi.get(key), mi.get(key + '_index')) + elif dt == 'rating': + args[dkey] = rating_to_stars(mi.get(key), m.get('display', {}).get('allow_half_stars', False)) + elif dt == 'comments': + val = val or '' + display = m.get('display', {}) + ctype = display.get('interpret_as') or 'html' + if ctype == 'long-text': + val = '

%s
' % escape(val) + elif ctype == 'short-text': + val = '%s' % escape(val) + elif ctype == 'markdown': + val = markdown(val) + else: + val = comments_to_html(val) + args[dkey] = val + else: + args[dkey] = escape(val) + args[dkey+'_label'] = escape(display_name) + except Exception: + # if the val (custom column contents) is None, don't add to args + pass + + if False: + print("Custom column values available in jacket template:") + for key in args.keys(): + if key.startswith('_') and not key.endswith('_label'): + print(" %s: %s" % ('#' + key[1:], args[key])) + + # Used in the comment describing use of custom columns in templates + # Don't change this unless you also change it in template.xhtml + args['_genre_label'] = args.get('_genre_label', '{_genre_label}') + args['_genre'] = args.get('_genre', '{_genre}') + + formatter = SafeFormatter() + generated_html = formatter.format(template, **args) + has_data['series'] = bool(series) + has_data['tags'] = bool(tags) + has_data['rating'] = bool(rating) + has_data['pubdate'] = bool(pubdate) + + return strip_encoding_declarations(generated_html) + + from calibre.ebooks.oeb.polish.parsing import parse + raw = generate_html(comments) + root = parse(raw, line_numbers=False, force_html5_parse=True) + + if rescale_fonts: + # We ensure that the conversion pipeline will set the font sizes for + # text in the jacket to the same size as the font sizes for the rest of + # the text in the book. That means that as long as the jacket uses + # relative font sizes (em or %), the post conversion font size will be + # the same as for text in the main book. So text with size x em will + # be rescaled to the same value in both the jacket and the main content. + # + # We cannot use data-calibre-rescale 100 on the body tag as that will just + # give the body tag a font size of 1em, which is useless. + for body in root.xpath('//*[local-name()="body"]'): + fw = body.makeelement(XHTML('div')) + fw.set('data-calibre-rescale', '100') + for child in body: + fw.append(child) + body.append(fw) + postprocess_jacket(root, output_profile, has_data) + from calibre.ebooks.oeb.polish.pretty import pretty_html_tree + pretty_html_tree(None, root) + return root + +# }}} + + +def linearize_jacket(oeb): + for x in oeb.spine[:4]: + if XPath(JACKET_XPATH)(x.data): + for e in XPath('//h:table|//h:tr|//h:th')(x.data): + e.tag = XHTML('div') + for e in XPath('//h:td')(x.data): + e.tag = XHTML('span') + break + + +def referenced_images(root): + for img in XPath('//h:img[@src]')(root): + src = img.get('src') + if src.startswith('file://'): + path = src[7:] + if iswindows and path.startswith('/'): + path = path[1:] + if os.path.exists(path): + yield img, path diff --git a/ebook_converter/ebooks/oeb/transforms/metadata.py b/ebook_converter/ebooks/oeb/transforms/metadata.py new file mode 100644 index 0000000..71c3a7e --- /dev/null +++ b/ebook_converter/ebooks/oeb/transforms/metadata.py @@ -0,0 +1,218 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2009, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import os, re +from calibre.utils.date import isoformat, now +from calibre import guess_type +from polyglot.builtins import iteritems + + +def meta_info_to_oeb_metadata(mi, m, log, override_input_metadata=False): + from calibre.ebooks.oeb.base import OPF + if not mi.is_null('title'): + m.clear('title') + m.add('title', mi.title) + if mi.title_sort: + if not m.title: + m.add('title', mi.title_sort) + m.clear('title_sort') + m.add('title_sort', mi.title_sort) + if not mi.is_null('authors'): + m.filter('creator', lambda x : x.role.lower() in ['aut', '']) + for a in mi.authors: + attrib = {'role':'aut'} + if mi.author_sort: + attrib[OPF('file-as')] = mi.author_sort + m.add('creator', a, attrib=attrib) + if not mi.is_null('book_producer'): + m.filter('contributor', lambda x : x.role.lower() == 'bkp') + m.add('contributor', mi.book_producer, role='bkp') + elif override_input_metadata: + m.filter('contributor', lambda x : x.role.lower() == 'bkp') + if not mi.is_null('comments'): + m.clear('description') + m.add('description', mi.comments) + elif override_input_metadata: + m.clear('description') + if not mi.is_null('publisher'): + m.clear('publisher') + m.add('publisher', mi.publisher) + elif override_input_metadata: + m.clear('publisher') + if not mi.is_null('series'): + m.clear('series') + m.add('series', mi.series) + elif override_input_metadata: + m.clear('series') + identifiers = mi.get_identifiers() + set_isbn = False + for typ, val in iteritems(identifiers): + has = False + if typ.lower() == 'isbn': + set_isbn = True + for x in m.identifier: + if x.scheme.lower() == typ.lower(): + x.content = val + has = True + if not has: + m.add('identifier', val, scheme=typ.upper()) + if override_input_metadata and not set_isbn: + m.filter('identifier', lambda x: x.scheme.lower() == 'isbn') + if not mi.is_null('languages'): + m.clear('language') + for lang in mi.languages: + if lang and lang.lower() not in ('und', ''): + m.add('language', lang) + if not mi.is_null('series_index'): + m.clear('series_index') + m.add('series_index', mi.format_series_index()) + elif override_input_metadata: + m.clear('series_index') + if not mi.is_null('rating'): + m.clear('rating') + m.add('rating', '%.2f'%mi.rating) + elif override_input_metadata: + m.clear('rating') + if not mi.is_null('tags'): + m.clear('subject') + for t in mi.tags: + m.add('subject', t) + elif override_input_metadata: + m.clear('subject') + if not mi.is_null('pubdate'): + m.clear('date') + m.add('date', isoformat(mi.pubdate)) + if not mi.is_null('timestamp'): + m.clear('timestamp') + m.add('timestamp', isoformat(mi.timestamp)) + if not mi.is_null('rights'): + m.clear('rights') + m.add('rights', mi.rights) + if not mi.is_null('publication_type'): + m.clear('publication_type') + m.add('publication_type', mi.publication_type) + + if not m.timestamp: + m.add('timestamp', isoformat(now())) + + +class MergeMetadata(object): + 'Merge in user metadata, including cover' + + def __call__(self, oeb, mi, opts, override_input_metadata=False): + self.oeb, self.log = oeb, oeb.log + m = self.oeb.metadata + self.log('Merging user specified metadata...') + meta_info_to_oeb_metadata(mi, m, oeb.log, + override_input_metadata=override_input_metadata) + cover_id = self.set_cover(mi, opts.prefer_metadata_cover) + m.clear('cover') + if cover_id is not None: + m.add('cover', cover_id) + if mi.uuid is not None: + m.filter('identifier', lambda x:x.id=='uuid_id') + self.oeb.metadata.add('identifier', mi.uuid, id='uuid_id', + scheme='uuid') + self.oeb.uid = self.oeb.metadata.identifier[-1] + if mi.application_id is not None: + m.filter('identifier', lambda x:x.scheme=='calibre') + self.oeb.metadata.add('identifier', mi.application_id, scheme='calibre') + + def set_cover(self, mi, prefer_metadata_cover): + cdata, ext = b'', 'jpg' + if mi.cover and os.access(mi.cover, os.R_OK): + with open(mi.cover, 'rb') as f: + cdata = f.read() + ext = mi.cover.rpartition('.')[-1].lower().strip() + elif mi.cover_data and mi.cover_data[-1]: + cdata = mi.cover_data[1] + ext = mi.cover_data[0] + if ext not in ('png', 'jpg', 'jpeg'): + ext = 'jpg' + id = old_cover = None + if 'cover' in self.oeb.guide: + old_cover = self.oeb.guide['cover'] + if prefer_metadata_cover and old_cover is not None: + cdata = b'' + if cdata: + self.oeb.guide.remove('cover') + self.oeb.guide.remove('titlepage') + elif self.oeb.plumber_output_format in {'mobi', 'azw3'} and old_cover is not None: + # The amazon formats dont support html cover pages, so remove them + # even if no cover was specified. + self.oeb.guide.remove('titlepage') + do_remove_old_cover = False + if old_cover is not None: + if old_cover.href in self.oeb.manifest.hrefs: + item = self.oeb.manifest.hrefs[old_cover.href] + if not cdata: + return item.id + do_remove_old_cover = True + elif not cdata: + id = self.oeb.manifest.generate(id='cover')[0] + self.oeb.manifest.add(id, old_cover.href, 'image/jpeg') + return id + new_cover_item = None + if cdata: + id, href = self.oeb.manifest.generate('cover', 'cover.'+ext) + new_cover_item = self.oeb.manifest.add(id, href, guess_type('cover.'+ext)[0], data=cdata) + self.oeb.guide.add('cover', 'Cover', href) + if do_remove_old_cover: + self.remove_old_cover(item, new_cover_item.href) + return id + + def remove_old_cover(self, cover_item, new_cover_href=None): + from calibre.ebooks.oeb.base import XPath, XLINK + from lxml import etree + + self.oeb.manifest.remove(cover_item) + + # Remove any references to the cover in the HTML + affected_items = set() + xp = XPath('//h:img[@src]|//svg:image[@xl:href]') + for i, item in enumerate(self.oeb.spine): + try: + images = xp(item.data) + except Exception: + images = () + removed = False + for img in images: + href = img.get('src') or img.get(XLINK('href')) + try: + href = item.abshref(href) + except Exception: + continue # Invalid URL, ignore + if href == cover_item.href: + if new_cover_href is not None: + replacement_href = item.relhref(new_cover_href) + attr = 'src' if img.tag.endswith('img') else XLINK('href') + img.set(attr, replacement_href) + else: + p = img.getparent() + if p.tag.endswith('}svg'): + p.getparent().remove(p) + else: + p.remove(img) + removed = True + if removed: + affected_items.add(item) + + # Check if the resulting HTML has no content, if so remove it + for item in affected_items: + body = XPath('//h:body')(item.data) + if body: + text = etree.tostring(body[0], method='text', encoding='unicode') + else: + text = '' + text = re.sub(r'\s+', '', text) + if not text and not XPath('//h:img|//svg:svg')(item.data): + self.log('Removing %s as it is a wrapper around' + ' the cover image'%item.href) + self.oeb.spine.remove(item) + self.oeb.manifest.remove(item) + self.oeb.guide.remove_by_href(item.href) diff --git a/ebook_converter/ebooks/oeb/transforms/page_margin.py b/ebook_converter/ebooks/oeb/transforms/page_margin.py new file mode 100644 index 0000000..6f42afc --- /dev/null +++ b/ebook_converter/ebooks/oeb/transforms/page_margin.py @@ -0,0 +1,189 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2011, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import numbers +from collections import Counter + +from calibre.ebooks.oeb.base import barename, XPath +from polyglot.builtins import iteritems + + +class RemoveAdobeMargins(object): + ''' + Remove margins specified in Adobe's page templates. + ''' + + def __call__(self, oeb, log, opts): + self.oeb, self.opts, self.log = oeb, opts, log + + for item in self.oeb.manifest: + if item.media_type in { + 'application/vnd.adobe-page-template+xml', 'application/vnd.adobe.page-template+xml', + 'application/adobe-page-template+xml', 'application/adobe.page-template+xml', + } and hasattr(item.data, 'xpath'): + self.log('Removing page margins specified in the' + ' Adobe page template') + for elem in item.data.xpath( + '//*[@margin-bottom or @margin-top ' + 'or @margin-left or @margin-right]'): + for margin in ('left', 'right', 'top', 'bottom'): + attr = 'margin-'+margin + elem.attrib.pop(attr, None) + + +class NegativeTextIndent(Exception): + pass + + +class RemoveFakeMargins(object): + + ''' + Remove left and right margins from paragraph/divs if the same margin is specified + on almost all the elements at that level. + + Must be called only after CSS flattening + ''' + + def __call__(self, oeb, log, opts): + if not opts.remove_fake_margins: + return + self.oeb, self.log, self.opts = oeb, log, opts + stylesheet = None + self.levels = {} + self.stats = {} + self.selector_map = {} + + stylesheet = self.oeb.manifest.main_stylesheet + if stylesheet is None: + return + + self.log('Removing fake margins...') + + stylesheet = stylesheet.data + + from css_parser.css import CSSRule + for rule in stylesheet.cssRules.rulesOfType(CSSRule.STYLE_RULE): + self.selector_map[rule.selectorList.selectorText] = rule.style + + self.find_levels() + + for level in self.levels: + try: + self.process_level(level) + except NegativeTextIndent: + self.log.debug('Negative text indent detected at level ' + ' %s, ignoring this level'%level) + + def get_margins(self, elem): + cls = elem.get('class', None) + if cls: + style = self.selector_map.get('.'+cls, None) + if style: + try: + ti = style['text-indent'] + except: + pass + else: + if ((hasattr(ti, 'startswith') and ti.startswith('-')) or + isinstance(ti, numbers.Number) and ti < 0): + raise NegativeTextIndent() + return style.marginLeft, style.marginRight, style + return '', '', None + + def process_level(self, level): + elems = self.levels[level] + self.stats[level+'_left'] = Counter() + self.stats[level+'_right'] = Counter() + + for elem in elems: + lm, rm = self.get_margins(elem)[:2] + self.stats[level+'_left'][lm] += 1 + self.stats[level+'_right'][rm] += 1 + + self.log.debug(level, ' left margin stats:', self.stats[level+'_left']) + self.log.debug(level, ' right margin stats:', self.stats[level+'_right']) + + remove_left = self.analyze_stats(self.stats[level+'_left']) + remove_right = self.analyze_stats(self.stats[level+'_right']) + + if remove_left: + mcl = self.stats[level+'_left'].most_common(1)[0][0] + self.log('Removing level %s left margin of:'%level, mcl) + + if remove_right: + mcr = self.stats[level+'_right'].most_common(1)[0][0] + self.log('Removing level %s right margin of:'%level, mcr) + + if remove_left or remove_right: + for elem in elems: + lm, rm, style = self.get_margins(elem) + if remove_left and lm == mcl: + style.removeProperty('margin-left') + if remove_right and rm == mcr: + style.removeProperty('margin-right') + + def find_levels(self): + + def level_of(elem, body): + ans = 1 + while elem.getparent() is not body: + ans += 1 + elem = elem.getparent() + return ans + + paras = XPath('descendant::h:p|descendant::h:div') + + for item in self.oeb.spine: + body = XPath('//h:body')(item.data) + if not body: + continue + body = body[0] + + for p in paras(body): + level = level_of(p, body) + level = '%s_%d'%(barename(p.tag), level) + if level not in self.levels: + self.levels[level] = [] + self.levels[level].append(p) + + remove = set() + for k, v in iteritems(self.levels): + num = len(v) + self.log.debug('Found %d items of level:'%num, k) + level = int(k.split('_')[-1]) + tag = k.split('_')[0] + if tag == 'p' and num < 25: + remove.add(k) + if tag == 'div': + if level > 2 and num < 25: + remove.add(k) + elif level < 3: + # Check each level < 3 element and only keep those + # that have many child paras + for elem in list(v): + children = len(paras(elem)) + if children < 5: + v.remove(elem) + + for k in remove: + self.levels.pop(k) + self.log.debug('Ignoring level', k) + + def analyze_stats(self, stats): + if not stats: + return False + mc = stats.most_common(1) + if len(mc) > 1: + return False + mc = mc[0] + most_common, most_common_count = mc + if not most_common or most_common == '0': + return False + total = sum(stats.values()) + # True if greater than 95% of elements have the same margin + return most_common_count/total > 0.95 diff --git a/ebook_converter/ebooks/oeb/transforms/structure.py b/ebook_converter/ebooks/oeb/transforms/structure.py new file mode 100644 index 0000000..cd5211c --- /dev/null +++ b/ebook_converter/ebooks/oeb/transforms/structure.py @@ -0,0 +1,324 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2009, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import re, uuid + +from lxml import etree +from collections import OrderedDict, Counter + +from calibre.ebooks.oeb.base import XPNSMAP, TOC, XHTML, xml2text, barename +from calibre.ebooks import ConversionError +from polyglot.builtins import itervalues, unicode_type +from polyglot.urllib import urlparse + + +def XPath(x): + try: + return etree.XPath(x, namespaces=XPNSMAP) + except etree.XPathSyntaxError: + raise ConversionError( + 'The syntax of the XPath expression %s is invalid.' % repr(x)) + + +def isspace(x): + return not x or x.replace('\xa0', '').isspace() + + +def at_start(elem): + ' Return True if there is no content before elem ' + body = XPath('ancestor-or-self::h:body')(elem) + if not body: + return True + body = body[0] + ancestors = frozenset(XPath('ancestor::*')(elem)) + for x in body.iter(): + if x is elem: + return True + if hasattr(getattr(x, 'tag', None), 'rpartition') and x.tag.rpartition('}')[-1] in {'img', 'svg'}: + return False + if isspace(getattr(x, 'text', None)) and (x in ancestors or isspace(getattr(x, 'tail', None))): + continue + return False + return False + + +class DetectStructure(object): + + def __call__(self, oeb, opts): + self.log = oeb.log + self.oeb = oeb + self.opts = opts + self.log('Detecting structure...') + + self.detect_chapters() + if self.oeb.auto_generated_toc or opts.use_auto_toc: + orig_toc = self.oeb.toc + self.oeb.toc = TOC() + self.create_level_based_toc() + if self.oeb.toc.count() < 1: + if not opts.no_chapters_in_toc and self.detected_chapters: + self.create_toc_from_chapters() + if self.oeb.toc.count() < opts.toc_threshold: + self.create_toc_from_links() + if self.oeb.toc.count() < 2 and orig_toc.count() > 2: + self.oeb.toc = orig_toc + else: + self.oeb.auto_generated_toc = True + self.log('Auto generated TOC with %d entries.' % + self.oeb.toc.count()) + + if opts.toc_filter is not None: + regexp = re.compile(opts.toc_filter) + for node in list(self.oeb.toc.iter()): + if not node.title or regexp.search(node.title) is not None: + self.log('Filtering', node.title if node.title else + 'empty node', 'from TOC') + self.oeb.toc.remove(node) + + if opts.page_breaks_before is not None: + pb_xpath = XPath(opts.page_breaks_before) + for item in oeb.spine: + for elem in pb_xpath(item.data): + try: + prev = next(elem.itersiblings(tag=etree.Element, + preceding=True)) + if (barename(elem.tag) in {'h1', 'h2'} and barename( + prev.tag) in {'h1', 'h2'} and (not prev.tail or + not prev.tail.split())): + # We have two adjacent headings, do not put a page + # break on the second one + continue + except StopIteration: + pass + + style = elem.get('style', '') + if style: + style += '; ' + elem.set('style', style+'page-break-before:always') + + for node in self.oeb.toc.iter(): + if not node.title or not node.title.strip(): + node.title = _('Unnamed') + + if self.opts.start_reading_at: + self.detect_start_reading() + + def detect_start_reading(self): + expr = self.opts.start_reading_at + try: + expr = XPath(expr) + except: + self.log.warn( + 'Invalid start reading at XPath expression, ignoring: %s'%expr) + return + for item in self.oeb.spine: + if not hasattr(item.data, 'xpath'): + continue + matches = expr(item.data) + if matches: + elem = matches[0] + eid = elem.get('id', None) + if not eid: + eid = 'start_reading_at_'+unicode_type(uuid.uuid4()).replace('-', '') + elem.set('id', eid) + if 'text' in self.oeb.guide: + self.oeb.guide.remove('text') + self.oeb.guide.add('text', 'Start', item.href+'#'+eid) + self.log('Setting start reading at position to %s in %s'%( + self.opts.start_reading_at, item.href)) + return + self.log.warn("Failed to find start reading at position: %s"% + self.opts.start_reading_at) + + def get_toc_parts_for_xpath(self, expr): + # if an attribute is selected by the xpath expr then truncate it + # from the path and instead return it as where to find the title text + title_attribute_regex = re.compile(r'/@([-\w]+)$') + match = title_attribute_regex.search(expr) + if match is not None: + return expr[0:match.start()], match.group(1) + + return expr, None + + def detect_chapters(self): + self.detected_chapters = [] + self.chapter_title_attribute = None + + def find_matches(expr, doc): + try: + ans = XPath(expr)(doc) + len(ans) + return ans + except: + self.log.warn('Invalid chapter expression, ignoring: %s'%expr) + return [] + + if self.opts.chapter: + chapter_path, title_attribute = self.get_toc_parts_for_xpath(self.opts.chapter) + self.chapter_title_attribute = title_attribute + for item in self.oeb.spine: + for x in find_matches(chapter_path, item.data): + self.detected_chapters.append((item, x)) + + chapter_mark = self.opts.chapter_mark + page_break_before = 'display: block; page-break-before: always' + page_break_after = 'display: block; page-break-after: always' + c = Counter() + for item, elem in self.detected_chapters: + c[item] += 1 + text = xml2text(elem).strip() + text = re.sub(r'\s+', ' ', text.strip()) + self.log('\tDetected chapter:', text[:50]) + if chapter_mark == 'none': + continue + if chapter_mark == 'rule': + mark = elem.makeelement(XHTML('hr')) + elif chapter_mark == 'pagebreak': + if c[item] < 3 and at_start(elem): + # For the first two elements in this item, check if they + # are at the start of the file, in which case inserting a + # page break in unnecessary and can lead to extra blank + # pages in the PDF Output plugin. We need to use two as + # feedbooks epubs match both a heading tag and its + # containing div with the default chapter expression. + continue + mark = elem.makeelement(XHTML('div'), style=page_break_after) + else: # chapter_mark == 'both': + mark = elem.makeelement(XHTML('hr'), style=page_break_before) + try: + elem.addprevious(mark) + except TypeError: + self.log.exception('Failed to mark chapter') + + def create_level_based_toc(self): + if self.opts.level1_toc is not None: + self.add_leveled_toc_items() + + def create_toc_from_chapters(self): + counter = self.oeb.toc.next_play_order() + for item, elem in self.detected_chapters: + text, href = self.elem_to_link(item, elem, self.chapter_title_attribute, counter) + self.oeb.toc.add(text, href, play_order=counter) + counter += 1 + + def create_toc_from_links(self): + num = 0 + for item in self.oeb.spine: + for a in XPath('//h:a[@href]')(item.data): + href = a.get('href') + try: + purl = urlparse(href) + except ValueError: + self.log.warning('Ignoring malformed URL:', href) + continue + if not purl[0] or purl[0] == 'file': + href, frag = purl.path, purl.fragment + href = item.abshref(href) + if frag: + href = '#'.join((href, frag)) + if not self.oeb.toc.has_href(href): + text = xml2text(a) + text = text[:100].strip() + if (not self.opts.duplicate_links_in_toc and + self.oeb.toc.has_text(text)): + continue + try: + self.oeb.toc.add(text, href, + play_order=self.oeb.toc.next_play_order()) + num += 1 + except ValueError: + self.oeb.log.exception('Failed to process link: %r' % href) + continue # Most likely an incorrectly URL encoded link + if self.opts.max_toc_links > 0 and \ + num >= self.opts.max_toc_links: + self.log('Maximum TOC links reached, stopping.') + return + + def elem_to_link(self, item, elem, title_attribute, counter): + text = '' + if title_attribute is not None: + text = elem.get(title_attribute, '') + if not text: + text = xml2text(elem).strip() + if not text: + text = elem.get('title', '') + if not text: + text = elem.get('alt', '') + text = re.sub(r'\s+', ' ', text.strip()) + text = text[:1000].strip() + id = elem.get('id', 'calibre_toc_%d'%counter) + elem.set('id', id) + href = '#'.join((item.href, id)) + return text, href + + def add_leveled_toc_items(self): + added = OrderedDict() + added2 = OrderedDict() + counter = 1 + + def find_matches(expr, doc): + try: + ans = XPath(expr)(doc) + len(ans) + return ans + except: + self.log.warn('Invalid ToC expression, ignoring: %s'%expr) + return [] + + for document in self.oeb.spine: + previous_level1 = list(itervalues(added))[-1] if added else None + previous_level2 = list(itervalues(added2))[-1] if added2 else None + + level1_toc, level1_title = self.get_toc_parts_for_xpath(self.opts.level1_toc) + for elem in find_matches(level1_toc, document.data): + text, _href = self.elem_to_link(document, elem, level1_title, counter) + counter += 1 + if text: + node = self.oeb.toc.add(text, _href, + play_order=self.oeb.toc.next_play_order()) + added[elem] = node + # node.add(_('Top'), _href) + + if self.opts.level2_toc is not None and added: + level2_toc, level2_title = self.get_toc_parts_for_xpath(self.opts.level2_toc) + for elem in find_matches(level2_toc, document.data): + level1 = None + for item in document.data.iterdescendants(): + if item in added: + level1 = added[item] + elif item == elem: + if level1 is None: + if previous_level1 is None: + break + level1 = previous_level1 + text, _href = self.elem_to_link(document, elem, level2_title, counter) + counter += 1 + if text: + added2[elem] = level1.add(text, _href, + play_order=self.oeb.toc.next_play_order()) + break + + if self.opts.level3_toc is not None and added2: + level3_toc, level3_title = self.get_toc_parts_for_xpath(self.opts.level3_toc) + for elem in find_matches(level3_toc, document.data): + level2 = None + for item in document.data.iterdescendants(): + if item in added2: + level2 = added2[item] + elif item == elem: + if level2 is None: + if previous_level2 is None: + break + level2 = previous_level2 + text, _href = \ + self.elem_to_link(document, elem, level3_title, counter) + counter += 1 + if text: + level2.add(text, _href, + play_order=self.oeb.toc.next_play_order()) + break diff --git a/ebook_converter/ebooks/oeb/transforms/trimmanifest.py b/ebook_converter/ebooks/oeb/transforms/trimmanifest.py new file mode 100644 index 0000000..d67f0e4 --- /dev/null +++ b/ebook_converter/ebooks/oeb/transforms/trimmanifest.py @@ -0,0 +1,73 @@ +''' +OPF manifest trimming transform. +''' +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2008, Marshall T. Vandegrift ' + +from calibre.ebooks.oeb.base import CSS_MIME, OEB_DOCS +from calibre.ebooks.oeb.base import urlnormalize, iterlinks +from polyglot.urllib import urldefrag + + +class ManifestTrimmer(object): + + @classmethod + def config(cls, cfg): + return cfg + + @classmethod + def generate(cls, opts): + return cls() + + def __call__(self, oeb, context): + import css_parser + oeb.logger.info('Trimming unused files from manifest...') + self.opts = context + used = set() + for term in oeb.metadata: + for item in oeb.metadata[term]: + if item.value in oeb.manifest.hrefs: + used.add(oeb.manifest.hrefs[item.value]) + elif item.value in oeb.manifest.ids: + used.add(oeb.manifest.ids[item.value]) + for ref in oeb.guide.values(): + path, _ = urldefrag(ref.href) + if path in oeb.manifest.hrefs: + used.add(oeb.manifest.hrefs[path]) + # TOC items are required to be in the spine + for item in oeb.spine: + used.add(item) + unchecked = used + while unchecked: + new = set() + for item in unchecked: + if (item.media_type in OEB_DOCS or + item.media_type[-4:] in ('/xml', '+xml')) and \ + item.data is not None: + hrefs = [r[2] for r in iterlinks(item.data)] + for href in hrefs: + if isinstance(href, bytes): + href = href.decode('utf-8') + try: + href = item.abshref(urlnormalize(href)) + except: + continue + if href in oeb.manifest.hrefs: + found = oeb.manifest.hrefs[href] + if found not in used: + new.add(found) + elif item.media_type == CSS_MIME: + for href in css_parser.getUrls(item.data): + href = item.abshref(urlnormalize(href)) + if href in oeb.manifest.hrefs: + found = oeb.manifest.hrefs[href] + if found not in used: + new.add(found) + used.update(new) + unchecked = new + for item in oeb.manifest.values(): + if item not in used: + oeb.logger.info('Trimming %r from manifest' % item.href) + oeb.manifest.remove(item) diff --git a/ebook_converter/ebooks/oeb/writer.py b/ebook_converter/ebooks/oeb/writer.py new file mode 100644 index 0000000..953c492 --- /dev/null +++ b/ebook_converter/ebooks/oeb/writer.py @@ -0,0 +1,78 @@ +''' +Directory output OEBBook writer. +''' +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2008, Marshall T. Vandegrift ' + +import os +from calibre.ebooks.oeb.base import OPF_MIME, xml2str +from calibre.ebooks.oeb.base import DirContainer, OEBError + +__all__ = ['OEBWriter'] + + +class OEBWriter(object): + DEFAULT_PROFILE = 'PRS505' + """Default renderer profile for content written with this Writer.""" + + TRANSFORMS = [] + """List of transforms to apply to content written with this Writer.""" + + def __init__(self, version='2.0', page_map=False, pretty_print=False): + self.version = version + self.page_map = page_map + self.pretty_print = pretty_print + + @classmethod + def config(cls, cfg): + """Add any book-writing options to the :class:`Config` object + :param:`cfg`. + """ + oeb = cfg.add_group('oeb', _('OPF/NCX/etc. generation options.')) + versions = ['1.2', '2.0'] + oeb('opf_version', ['--opf-version'], default='2.0', choices=versions, + help=_('OPF version to generate. Default is %default.')) + oeb('adobe_page_map', ['--adobe-page-map'], default=False, + help=_('Generate an Adobe "page-map" file if pagination ' + 'information is available.')) + return cfg + + @classmethod + def generate(cls, opts): + """Generate a Writer instance from command-line options.""" + version = opts.opf_version + page_map = opts.adobe_page_map + pretty_print = opts.pretty_print + return cls(version=version, page_map=page_map, + pretty_print=pretty_print) + + def __call__(self, oeb, path): + """ + Write the book in the :class:`OEBBook` object :param:`oeb` to a folder + at :param:`path`. + """ + version = int(self.version[0]) + opfname = None + if os.path.splitext(path)[1].lower() == '.opf': + opfname = os.path.basename(path) + path = os.path.dirname(path) + if not os.path.isdir(path): + os.mkdir(path) + output = DirContainer(path, oeb.log) + for item in oeb.manifest.values(): + output.write(item.href, item.bytes_representation) + + if version == 1: + metadata = oeb.to_opf1() + elif version == 2: + metadata = oeb.to_opf2(page_map=self.page_map) + else: + raise OEBError("Unrecognized OPF version %r" % self.version) + pretty_print = self.pretty_print + for mime, (href, data) in metadata.items(): + if opfname and mime == OPF_MIME: + href = opfname + output.write(href, xml2str(data, pretty_print=pretty_print)) + return diff --git a/ebook_converter/ebooks/pdb/__init__.py b/ebook_converter/ebooks/pdb/__init__.py new file mode 100644 index 0000000..599744f --- /dev/null +++ b/ebook_converter/ebooks/pdb/__init__.py @@ -0,0 +1,106 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2009, John Schember ' +__docformat__ = 'restructuredtext en' + + +class PDBError(Exception): + pass + + +FORMAT_READERS = None + + +def _import_readers(): + global FORMAT_READERS + from calibre.ebooks.pdb.ereader.reader import Reader as ereader_reader + from calibre.ebooks.pdb.palmdoc.reader import Reader as palmdoc_reader + from calibre.ebooks.pdb.ztxt.reader import Reader as ztxt_reader + from calibre.ebooks.pdb.pdf.reader import Reader as pdf_reader + from calibre.ebooks.pdb.plucker.reader import Reader as plucker_reader + from calibre.ebooks.pdb.haodoo.reader import Reader as haodoo_reader + + FORMAT_READERS = { + 'PNPdPPrs': ereader_reader, + 'PNRdPPrs': ereader_reader, + 'zTXTGPlm': ztxt_reader, + 'TEXtREAd': palmdoc_reader, + '.pdfADBE': pdf_reader, + 'DataPlkr': plucker_reader, + 'BOOKMTIT': haodoo_reader, + 'BOOKMTIU': haodoo_reader, + } + + +ALL_FORMAT_WRITERS = {'doc', 'ztxt', 'ereader'} +FORMAT_WRITERS = None + + +def _import_writers(): + global FORMAT_WRITERS + from calibre.ebooks.pdb.palmdoc.writer import Writer as palmdoc_writer + from calibre.ebooks.pdb.ztxt.writer import Writer as ztxt_writer + from calibre.ebooks.pdb.ereader.writer import Writer as ereader_writer + + FORMAT_WRITERS = { + 'doc': palmdoc_writer, + 'ztxt': ztxt_writer, + 'ereader': ereader_writer, + } + + +IDENTITY_TO_NAME = { + 'PNPdPPrs': 'eReader', + 'PNRdPPrs': 'eReader', + 'zTXTGPlm': 'zTXT', + 'TEXtREAd': 'PalmDOC', + '.pdfADBE': 'Adobe Reader', + 'DataPlkr': 'Plucker', + 'BOOKMTIT': 'Haodoo.net', + 'BOOKMTIU': 'Haodoo.net', + + 'BVokBDIC': 'BDicty', + 'DB99DBOS': 'DB (Database program)', + 'vIMGView': 'FireViewer (ImageViewer)', + 'PmDBPmDB': 'HanDBase', + 'InfoINDB': 'InfoView', + 'ToGoToGo': 'iSilo', + 'SDocSilX': 'iSilo 3', + 'JbDbJBas': 'JFile', + 'JfDbJFil': 'JFile Pro', + 'DATALSdb': 'LIST', + 'Mdb1Mdb1': 'MobileDB', + 'BOOKMOBI': 'MobiPocket', + 'DataSprd': 'QuickSheet', + 'SM01SMem': 'SuperMemo', + 'TEXtTlDc': 'TealDoc', + 'InfoTlIf': 'TealInfo', + 'DataTlMl': 'TealMeal', + 'DataTlPt': 'TealPaint', + 'dataTDBP': 'ThinkDB', + 'TdatTide': 'Tides', + 'ToRaTRPW': 'TomeRaider', + 'BDOCWrdS': 'WordSmith', +} + + +def get_reader(identity): + ''' + Returns None if no reader is found for the identity. + ''' + global FORMAT_READERS + if FORMAT_READERS is None: + _import_readers() + return FORMAT_READERS.get(identity, None) + + +def get_writer(extension): + ''' + Returns None if no writer is found for extension. + ''' + global FORMAT_WRITERS + if FORMAT_WRITERS is None: + _import_writers() + return FORMAT_WRITERS.get(extension, None) diff --git a/ebook_converter/ebooks/pdb/ereader/__init__.py b/ebook_converter/ebooks/pdb/ereader/__init__.py new file mode 100644 index 0000000..84661e8 --- /dev/null +++ b/ebook_converter/ebooks/pdb/ereader/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2009, John Schember ' +__docformat__ = 'restructuredtext en' + +import os + + +class EreaderError(Exception): + pass + + +def image_name(name, taken_names=()): + name = os.path.basename(name) + + if len(name) > 32: + cut = len(name) - 32 + names = name[:10] + namee = name[10+cut:] + name = '%s%s.png' % (names, namee) + + i = 0 + base_name, ext = os.path.splitext(name) + while name in taken_names: + i += 1 + name = '%s%s%s' % (base_name, i, ext) + + return name.ljust(32, '\x00')[:32] diff --git a/ebook_converter/ebooks/pdb/ereader/reader.py b/ebook_converter/ebooks/pdb/ereader/reader.py new file mode 100644 index 0000000..bd2bb97 --- /dev/null +++ b/ebook_converter/ebooks/pdb/ereader/reader.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +''' +Read content from ereader pdb file. +''' + +__license__ = 'GPL v3' +__copyright__ = '2009, John Schember ' +__docformat__ = 'restructuredtext en' + +from calibre.ebooks.pdb.ereader import EreaderError +from calibre.ebooks.pdb.formatreader import FormatReader +from calibre.ebooks.pdb.ereader.reader132 import Reader132 +from calibre.ebooks.pdb.ereader.reader202 import Reader202 + + +class Reader(FormatReader): + + def __init__(self, header, stream, log, options): + record0_size = len(header.section_data(0)) + + if record0_size == 132: + self.reader = Reader132(header, stream, log, options) + elif record0_size in (116, 202): + self.reader = Reader202(header, stream, log, options) + else: + raise EreaderError('Size mismatch. eReader header record size %s KB is not supported.' % record0_size) + + def extract_content(self, output_dir): + return self.reader.extract_content(output_dir) + + def dump_pml(self): + return self.reader.dump_pml() + + def dump_images(self, out_dir): + return self.reader.dump_images(out_dir) diff --git a/ebook_converter/ebooks/pdb/ereader/reader132.py b/ebook_converter/ebooks/pdb/ereader/reader132.py new file mode 100644 index 0000000..b98c5e8 --- /dev/null +++ b/ebook_converter/ebooks/pdb/ereader/reader132.py @@ -0,0 +1,221 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +''' +Read content from ereader pdb file with a 132 byte header created by Dropbook. +''' + +__license__ = 'GPL v3' +__copyright__ = '2009, John Schember ' +__docformat__ = 'restructuredtext en' + +import os +import re +import struct +import zlib + +from calibre import CurrentDir +from calibre.ebooks import DRMError +from calibre.ebooks.metadata.opf2 import OPFCreator +from calibre.ebooks.pdb.ereader import EreaderError +from calibre.ebooks.pdb.formatreader import FormatReader +from polyglot.builtins import unicode_type, range + + +class HeaderRecord(object): + ''' + The first record in the file is always the header record. It holds + information related to the location of text, images, and so on + in the file. This is used in conjunction with the sections + defined in the file header. + ''' + + def __init__(self, raw): + self.compression, = struct.unpack('>H', raw[0:2]) + self.non_text_offset, = struct.unpack('>H', raw[12:14]) + self.chapter_count, = struct.unpack('>H', raw[14:16]) + self.image_count, = struct.unpack('>H', raw[20:22]) + self.link_count, = struct.unpack('>H', raw[22:24]) + self.has_metadata, = struct.unpack('>H', raw[24:26]) + self.footnote_count, = struct.unpack('>H', raw[28:30]) + self.sidebar_count, = struct.unpack('>H', raw[30:32]) + self.chapter_offset, = struct.unpack('>H', raw[32:34]) + self.small_font_page_offset, = struct.unpack('>H', raw[36:38]) + self.large_font_page_offset, = struct.unpack('>H', raw[38:40]) + self.image_data_offset, = struct.unpack('>H', raw[40:42]) + self.link_offset, = struct.unpack('>H', raw[42:44]) + self.metadata_offset, = struct.unpack('>H', raw[44:46]) + self.footnote_offset, = struct.unpack('>H', raw[48:50]) + self.sidebar_offset, = struct.unpack('>H', raw[50:52]) + self.last_data_offset, = struct.unpack('>H', raw[52:54]) + + self.num_text_pages = self.non_text_offset - 1 + self.num_image_pages = self.metadata_offset - self.image_data_offset + + +class Reader132(FormatReader): + + def __init__(self, header, stream, log, options): + self.log = log + self.encoding = options.input_encoding + + self.log.debug('132 byte header version found.') + + self.sections = [] + for i in range(header.num_sections): + self.sections.append(header.section_data(i)) + + self.header_record = HeaderRecord(self.section_data(0)) + + if self.header_record.compression not in (2, 10): + if self.header_record.compression in (260, 272): + raise DRMError('eReader DRM is not supported.') + else: + raise EreaderError('Unknown book compression %i.' % self.header_record.compression) + + from calibre.ebooks.metadata.pdb import get_metadata + self.mi = get_metadata(stream, False) + + def section_data(self, number): + return self.sections[number] + + def decompress_text(self, number): + if self.header_record.compression == 2: + from calibre.ebooks.compression.palmdoc import decompress_doc + return decompress_doc(self.section_data(number)).decode('cp1252' if self.encoding is None else self.encoding, 'replace') + if self.header_record.compression == 10: + return zlib.decompress(self.section_data(number)).decode('cp1252' if self.encoding is None else self.encoding, 'replace') + + def get_image(self, number): + if number < self.header_record.image_data_offset or number > self.header_record.image_data_offset + self.header_record.num_image_pages - 1: + return 'empty', b'' + data = self.section_data(number) + name = data[4:4 + 32].strip(b'\x00').decode(self.encoding or 'cp1252') + img = data[62:] + return name, img + + def get_text_page(self, number): + ''' + Only palmdoc and zlib compressed are supported. The text is + assumed to be encoded as Windows-1252. The encoding is part of + the eReader file spec and should always be this encoding. + ''' + if not (1 <= number <= self.header_record.num_text_pages): + return '' + + return self.decompress_text(number) + + def extract_content(self, output_dir): + from calibre.ebooks.pml.pmlconverter import footnote_to_html, sidebar_to_html + from calibre.ebooks.pml.pmlconverter import PML_HTMLizer + + output_dir = os.path.abspath(output_dir) + + if not os.path.exists(output_dir): + os.makedirs(output_dir) + + title = self.mi.title + if not isinstance(title, unicode_type): + title = title.decode('utf-8', 'replace') + html = '%s' % title + + pml = '' + for i in range(1, self.header_record.num_text_pages + 1): + self.log.debug('Extracting text page %i' % i) + pml += self.get_text_page(i) + hizer = PML_HTMLizer() + html += hizer.parse_pml(pml, 'index.html') + toc = hizer.get_toc() + + if self.header_record.footnote_count > 0: + html += '

%s

' % _('Footnotes') + footnoteids = re.findall( + '\\w+(?=\x00)', self.section_data(self.header_record.footnote_offset).decode('cp1252' if self.encoding is None else self.encoding)) + for fid, i in enumerate(range(self.header_record.footnote_offset + 1, self.header_record.footnote_offset + self.header_record.footnote_count)): + self.log.debug('Extracting footnote page %i' % i) + if fid < len(footnoteids): + fid = footnoteids[fid] + else: + fid = '' + html += footnote_to_html(fid, self.decompress_text(i)) + + if self.header_record.sidebar_count > 0: + html += '

%s

' % _('Sidebar') + sidebarids = re.findall( + '\\w+(?=\x00)', self.section_data(self.header_record.sidebar_offset).decode('cp1252' if self.encoding is None else self.encoding)) + for sid, i in enumerate(range(self.header_record.sidebar_offset + 1, self.header_record.sidebar_offset + self.header_record.sidebar_count)): + self.log.debug('Extracting sidebar page %i' % i) + if sid < len(sidebarids): + sid = sidebarids[sid] + else: + sid = '' + html += sidebar_to_html(sid, self.decompress_text(i)) + + html += '' + + with CurrentDir(output_dir): + with open('index.html', 'wb') as index: + self.log.debug('Writing text to index.html') + index.write(html.encode('utf-8')) + + if not os.path.exists(os.path.join(output_dir, 'images/')): + os.makedirs(os.path.join(output_dir, 'images/')) + images = [] + with CurrentDir(os.path.join(output_dir, 'images/')): + for i in range(0, self.header_record.num_image_pages): + name, img = self.get_image(self.header_record.image_data_offset + i) + images.append(name) + with open(name, 'wb') as imgf: + self.log.debug('Writing image %s to images/' % name) + imgf.write(img) + + opf_path = self.create_opf(output_dir, images, toc) + + return opf_path + + def create_opf(self, output_dir, images, toc): + with CurrentDir(output_dir): + if 'cover.png' in images: + self.mi.cover = os.path.join('images', 'cover.png') + + opf = OPFCreator(output_dir, self.mi) + + manifest = [('index.html', None)] + + for i in images: + manifest.append((os.path.join('images', i), None)) + + opf.create_manifest(manifest) + opf.create_spine(['index.html']) + opf.set_toc(toc) + with open('metadata.opf', 'wb') as opffile: + with open('toc.ncx', 'wb') as tocfile: + opf.render(opffile, tocfile, 'toc.ncx') + + return os.path.join(output_dir, 'metadata.opf') + + def dump_pml(self): + ''' + This is primarily used for debugging and 3rd party tools to + get the plm markup that comprises the text in the file. + ''' + pml = '' + + for i in range(1, self.header_record.num_text_pages + 1): + pml += self.get_text_page(i) + + return pml + + def dump_images(self, output_dir): + ''' + This is primarily used for debugging and 3rd party tools to + get the images in the file. + ''' + if not os.path.exists(output_dir): + os.makedirs(output_dir) + + with CurrentDir(output_dir): + for i in range(0, self.header_record.num_image_pages): + name, img = self.get_image(self.header_record.image_data_offset + i) + with open(name, 'wb') as imgf: + imgf.write(img) diff --git a/ebook_converter/ebooks/pdb/ereader/reader202.py b/ebook_converter/ebooks/pdb/ereader/reader202.py new file mode 100644 index 0000000..fd69b19 --- /dev/null +++ b/ebook_converter/ebooks/pdb/ereader/reader202.py @@ -0,0 +1,169 @@ +# -*- coding: utf-8 -*- + +from __future__ import absolute_import, division, print_function, unicode_literals + +''' +Read content from ereader pdb file with a 116 and 202 byte header created by Makebook. +''' +__license__ = 'GPL v3' +__copyright__ = '2009, John Schember ' +__docformat__ = 'restructuredtext en' + +import os +import struct + +from calibre import CurrentDir +from calibre.ebooks.metadata.opf2 import OPFCreator +from calibre.ebooks.pdb.formatreader import FormatReader +from calibre.ebooks.pdb.ereader import EreaderError +from polyglot.builtins import unicode_type, range + + +class HeaderRecord(object): + ''' + The first record in the file is always the header record. It holds + information related to the location of text, images, and so on + in the file. This is used in conjunction with the sections + defined in the file header. + ''' + + def __init__(self, raw): + self.version, = struct.unpack('>H', raw[0:2]) + self.non_text_offset, = struct.unpack('>H', raw[8:10]) + + self.num_text_pages = self.non_text_offset - 1 + + +class Reader202(FormatReader): + + def __init__(self, header, stream, log, options): + self.log = log + self.encoding = options.input_encoding + + self.log.debug('202 byte header version found.') + + self.sections = [] + for i in range(header.num_sections): + self.sections.append(header.section_data(i)) + + self.header_record = HeaderRecord(self.section_data(0)) + + if self.header_record.version not in (2, 4): + raise EreaderError('Unknown book version %i.' % self.header_record.version) + + from calibre.ebooks.metadata.pdb import get_metadata + self.mi = get_metadata(stream, False) + + def section_data(self, number): + return self.sections[number] + + def decompress_text(self, number): + from calibre.ebooks.compression.palmdoc import decompress_doc + data = bytearray(self.section_data(number)) + data = bytes(bytearray(x ^ 0xA5 for x in data)) + return decompress_doc(data).decode(self.encoding or 'cp1252', 'replace') + + def get_image(self, number): + name = None + img = None + + data = self.section_data(number) + if data.startswith(b'PNG'): + name = data[4:4 + 32].strip(b'\x00') + img = data[62:] + + return name, img + + def get_text_page(self, number): + ''' + Only palmdoc compression is supported. The text is xored with 0xA5 and + assumed to be encoded as Windows-1252. The encoding is part of + the eReader file spec and should always be this encoding. + ''' + if not (1 <= number <= self.header_record.num_text_pages): + return '' + + return self.decompress_text(number) + + def extract_content(self, output_dir): + from calibre.ebooks.pml.pmlconverter import pml_to_html + + output_dir = os.path.abspath(output_dir) + + if not os.path.exists(output_dir): + os.makedirs(output_dir) + + pml = '' + for i in range(1, self.header_record.num_text_pages + 1): + self.log.debug('Extracting text page %i' % i) + pml += self.get_text_page(i) + + title = self.mi.title + if not isinstance(title, unicode_type): + title = title.decode('utf-8', 'replace') + + html = '%s%s' % \ + (title, pml_to_html(pml)) + + with CurrentDir(output_dir): + with open('index.html', 'wb') as index: + self.log.debug('Writing text to index.html') + index.write(html.encode('utf-8')) + + if not os.path.exists(os.path.join(output_dir, 'images/')): + os.makedirs(os.path.join(output_dir, 'images/')) + images = [] + with CurrentDir(os.path.join(output_dir, 'images/')): + for i in range(self.header_record.non_text_offset, len(self.sections)): + name, img = self.get_image(i) + if name: + images.append(name) + with open(name, 'wb') as imgf: + self.log.debug('Writing image %s to images/' % name) + imgf.write(img) + + opf_path = self.create_opf(output_dir, images) + + return opf_path + + def create_opf(self, output_dir, images): + with CurrentDir(output_dir): + opf = OPFCreator(output_dir, self.mi) + + manifest = [('index.html', None)] + + for i in images: + manifest.append((os.path.join('images/', i), None)) + + opf.create_manifest(manifest) + opf.create_spine(['index.html']) + with open('metadata.opf', 'wb') as opffile: + opf.render(opffile) + + return os.path.join(output_dir, 'metadata.opf') + + def dump_pml(self): + ''' + This is primarily used for debugging and 3rd party tools to + get the plm markup that comprises the text in the file. + ''' + pml = '' + + for i in range(1, self.header_record.num_text_pages + 1): + pml += self.get_text_page(i) + + return pml + + def dump_images(self, output_dir): + ''' + This is primarily used for debugging and 3rd party tools to + get the images in the file. + ''' + if not os.path.exists(output_dir): + os.makedirs(output_dir) + + with CurrentDir(output_dir): + for i in range(0, self.header_record.num_image_pages): + name, img = self.get_image(self.header_record.image_data_offset + i) + with open(name, 'wb') as imgf: + imgf.write(img) diff --git a/ebook_converter/ebooks/pdb/formatreader.py b/ebook_converter/ebooks/pdb/formatreader.py new file mode 100644 index 0000000..1d14c63 --- /dev/null +++ b/ebook_converter/ebooks/pdb/formatreader.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +''' +Interface defining the necessary public functions for a pdb format reader. +''' + +__license__ = 'GPL v3' +__copyright__ = '2009, John Schember ' +__docformat__ = 'restructuredtext en' + + +class FormatReader(object): + + def __init__(self, header, stream, log, options): + raise NotImplementedError() + + def extract_content(self, output_dir): + raise NotImplementedError() diff --git a/ebook_converter/ebooks/pdb/haodoo/__init__.py b/ebook_converter/ebooks/pdb/haodoo/__init__.py new file mode 100644 index 0000000..357137f --- /dev/null +++ b/ebook_converter/ebooks/pdb/haodoo/__init__.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2012, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + + + diff --git a/ebook_converter/ebooks/pdb/haodoo/reader.py b/ebook_converter/ebooks/pdb/haodoo/reader.py new file mode 100644 index 0000000..dc4497f --- /dev/null +++ b/ebook_converter/ebooks/pdb/haodoo/reader.py @@ -0,0 +1,157 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +''' +Read content from Haodoo.net pdb file. +''' + +__license__ = 'GPL v3' +__copyright__ = '2012, Kan-Ru Chen ' +__docformat__ = 'restructuredtext en' + + +import struct +import os + +from calibre import prepare_string_for_xml +from calibre.ebooks.pdb.formatreader import FormatReader +from calibre.ebooks.metadata import MetaInformation +from calibre.ebooks.txt.processor import opf_writer, HTML_TEMPLATE +from polyglot.builtins import range, map + +BPDB_IDENT = b'BOOKMTIT' +UPDB_IDENT = b'BOOKMTIU' + +punct_table = { + u"︵": u"(", + u"︶": u")", + u"︷": u"{", + u"︸": u"}", + u"︹": u"〔", + u"︺": u"〕", + u"︻": u"【", + u"︼": u"】", + u"︗": u"〖", + u"︘": u"〗", + u"﹇": u"[]", + u"﹈": u"[]", + u"︽": u"《", + u"︾": u"》", + u"︿": u"〈", + u"﹀": u"〉", + u"﹁": u"「", + u"﹂": u"」", + u"﹃": u"『", + u"﹄": u"』", + u"|": u"—", + u"︙": u"…", + u"ⸯ": u"~", + u"│": u"…", + u"¦": u"…", + u" ": u" ", + } + + +def fix_punct(line): + for (key, value) in punct_table.items(): + line = line.replace(key, value) + return line + + +class LegacyHeaderRecord(object): + + def __init__(self, raw): + fields = raw.lstrip().replace(b'\x1b\x1b\x1b', b'\x1b').split(b'\x1b') + self.title = fix_punct(fields[0].decode('cp950', 'replace')) + self.num_records = int(fields[1]) + self.chapter_titles = list(map( + lambda x: fix_punct(x.decode('cp950', 'replace').rstrip('\x00')), + fields[2:])) + + +class UnicodeHeaderRecord(object): + + def __init__(self, raw): + fields = raw.lstrip().replace(b'\x1b\x00\x1b\x00\x1b\x00', + b'\x1b\x00').split(b'\x1b\x00') + self.title = fix_punct(fields[0].decode('utf_16_le', 'ignore')) + self.num_records = int(fields[1]) + self.chapter_titles = list(map( + lambda x: fix_punct(x.decode('utf_16_le', 'replace').rstrip('\x00')), + fields[2].split(b'\r\x00\n\x00'))) + + +class Reader(FormatReader): + + def __init__(self, header, stream, log, options): + self.stream = stream + self.log = log + + self.sections = [] + for i in range(header.num_sections): + self.sections.append(header.section_data(i)) + + if header.ident == BPDB_IDENT: + self.header_record = LegacyHeaderRecord(self.section_data(0)) + self.encoding = 'cp950' + else: + self.header_record = UnicodeHeaderRecord(self.section_data(0)) + self.encoding = 'utf_16_le' + + def author(self): + self.stream.seek(35) + version = struct.unpack('>b', self.stream.read(1))[0] + if version == 2: + self.stream.seek(0) + author = self.stream.read(35).rstrip(b'\x00').decode(self.encoding, 'replace') + return author + else: + return 'Unknown' + + def get_metadata(self): + mi = MetaInformation(self.header_record.title, + [self.author()]) + mi.language = 'zh-tw' + + return mi + + def section_data(self, number): + return self.sections[number] + + def decompress_text(self, number): + return self.section_data(number).decode(self.encoding, + 'replace').rstrip('\x00') + + def extract_content(self, output_dir): + txt = '' + + self.log.info(u'Decompressing text...') + for i in range(1, self.header_record.num_records + 1): + self.log.debug(u'\tDecompressing text section %i' % i) + title = self.header_record.chapter_titles[i-1] + lines = [] + title_added = False + for line in self.decompress_text(i).splitlines(): + line = fix_punct(line) + line = line.strip() + if not title_added and title in line: + line = '

' + line + '

\n' + title_added = True + else: + line = prepare_string_for_xml(line) + lines.append('

%s

' % line) + if not title_added: + lines.insert(0, '

' + title + '

\n') + txt += '\n'.join(lines) + + self.log.info(u'Converting text to OEB...') + html = HTML_TEMPLATE % (self.header_record.title, txt) + with open(os.path.join(output_dir, 'index.html'), 'wb') as index: + index.write(html.encode('utf-8')) + + mi = self.get_metadata() + manifest = [('index.html', None)] + spine = ['index.html'] + opf_writer(output_dir, 'metadata.opf', manifest, spine, mi) + + return os.path.join(output_dir, 'metadata.opf') diff --git a/ebook_converter/ebooks/pdb/header.py b/ebook_converter/ebooks/pdb/header.py new file mode 100644 index 0000000..afe7fda --- /dev/null +++ b/ebook_converter/ebooks/pdb/header.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- + +from __future__ import absolute_import, division, print_function, unicode_literals + +''' +Read the header data from a pdb file. +''' + +__license__ = 'GPL v3' +__copyright__ = '2009, John Schember ' +__docformat__ = 'restructuredtext en' + +import re +import struct +import time +from polyglot.builtins import long_type + + +class PdbHeaderReader(object): + + def __init__(self, stream): + self.stream = stream + self.ident = self.identity() + self.num_sections = self.section_count() + self.title = self.name() + + def identity(self): + self.stream.seek(60) + ident = self.stream.read(8) + return ident.decode('utf-8') + + def section_count(self): + self.stream.seek(76) + return struct.unpack('>H', self.stream.read(2))[0] + + def name(self): + self.stream.seek(0) + return re.sub(b'[^-A-Za-z0-9 ]+', b'_', self.stream.read(32).replace(b'\x00', b'')) + + def full_section_info(self, number): + if not (0 <= number < self.num_sections): + raise ValueError('Not a valid section number %i' % number) + + self.stream.seek(78 + number * 8) + offset, a1, a2, a3, a4 = struct.unpack('>LBBBB', self.stream.read(8))[0] + flags, val = a1, a2 << 16 | a3 << 8 | a4 + return (offset, flags, val) + + def section_offset(self, number): + if not (0 <= number < self.num_sections): + raise ValueError('Not a valid section number %i' % number) + + self.stream.seek(78 + number * 8) + return struct.unpack('>LBBBB', self.stream.read(8))[0] + + def section_data(self, number): + if not (0 <= number < self.num_sections): + raise ValueError('Not a valid section number %i' % number) + + start = self.section_offset(number) + if number == self.num_sections -1: + self.stream.seek(0, 2) + end = self.stream.tell() + else: + end = self.section_offset(number + 1) + self.stream.seek(start) + return self.stream.read(end - start) + + +class PdbHeaderBuilder(object): + + def __init__(self, identity, title): + self.identity = identity.ljust(3, '\x00')[:8].encode('utf-8') + self.title = b'%s\x00' % re.sub('[^-A-Za-z0-9 ]+', '_', title).ljust(31, '\x00')[:31].encode('ascii', 'replace') + + def build_header(self, section_lengths, out_stream): + ''' + section_lengths = Lenght of each section in file. + ''' + + now = int(time.time()) + nrecords = len(section_lengths) + + out_stream.write(self.title + struct.pack('>HHIIIIII', 0, 0, now, now, 0, 0, 0, 0)) + out_stream.write(self.identity + struct.pack('>IIH', nrecords, 0, nrecords)) + + offset = 78 + (8 * nrecords) + 2 + for id, record in enumerate(section_lengths): + out_stream.write(struct.pack('>LBBBB', long_type(offset), 0, 0, 0, 0)) + offset += record + out_stream.write(b'\x00\x00') diff --git a/ebook_converter/ebooks/pdb/palmdoc/__init__.py b/ebook_converter/ebooks/pdb/palmdoc/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ebook_converter/ebooks/pdb/palmdoc/reader.py b/ebook_converter/ebooks/pdb/palmdoc/reader.py new file mode 100644 index 0000000..8f84dc7 --- /dev/null +++ b/ebook_converter/ebooks/pdb/palmdoc/reader.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +''' +Read content from palmdoc pdb file. +''' + +__license__ = 'GPL v3' +__copyright__ = '2009, John Schember ' +__docformat__ = 'restructuredtext en' + +import struct, io + + +from calibre.ebooks.pdb.formatreader import FormatReader + + +class HeaderRecord(object): + ''' + The first record in the file is always the header record. It holds + information related to the location of text, images, and so on + in the file. This is used in conjunction with the sections + defined in the file header. + ''' + + def __init__(self, raw): + self.compression, = struct.unpack('>H', raw[0:2]) + self.num_records, = struct.unpack('>H', raw[8:10]) + + +class Reader(FormatReader): + + def __init__(self, header, stream, log, options): + self.stream = stream + self.log = log + self.options = options + + self.sections = [] + for i in range(header.num_sections): + self.sections.append(header.section_data(i)) + + self.header_record = HeaderRecord(self.section_data(0)) + + def section_data(self, number): + return self.sections[number] + + def decompress_text(self, number): + if self.header_record.compression == 1: + return self.section_data(number) + if self.header_record.compression == 2 or self.header_record.compression == 258: + from calibre.ebooks.compression.palmdoc import decompress_doc + return decompress_doc(self.section_data(number)) + return b'' + + def extract_content(self, output_dir): + raw_txt = b'' + + self.log.info('Decompressing text...') + for i in range(1, self.header_record.num_records + 1): + self.log.debug('\tDecompressing text section %i' % i) + raw_txt += self.decompress_text(i) + + self.log.info('Converting text to OEB...') + stream = io.BytesIO(raw_txt) + + from calibre.customize.ui import plugin_for_input_format + + txt_plugin = plugin_for_input_format('txt') + for opt in txt_plugin.options: + if not hasattr(self.options, opt.option.name): + setattr(self.options, opt.option.name, opt.recommended_value) + + stream.seek(0) + return txt_plugin.convert(stream, self.options, 'txt', self.log, {}) diff --git a/ebook_converter/ebooks/pdb/pdf/__init__.py b/ebook_converter/ebooks/pdb/pdf/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ebook_converter/ebooks/pdb/pdf/reader.py b/ebook_converter/ebooks/pdb/pdf/reader.py new file mode 100644 index 0000000..df0af2c --- /dev/null +++ b/ebook_converter/ebooks/pdb/pdf/reader.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +''' +Read content from palmdoc pdb file. +''' + +__license__ = 'GPL v3' +__copyright__ = '2010, John Schember ' +__docformat__ = 'restructuredtext en' + + +from calibre.ebooks.pdb.formatreader import FormatReader +from calibre.ptempfile import PersistentTemporaryFile +from polyglot.builtins import range + + +class Reader(FormatReader): + + def __init__(self, header, stream, log, options): + self.header = header + self.stream = stream + self.log = log + self.options = options + + def extract_content(self, output_dir): + self.log.info('Extracting PDF...') + + pdf = PersistentTemporaryFile('.pdf') + pdf.close() + pdf = open(pdf, 'wb') + for x in range(self.header.section_count()): + pdf.write(self.header.section_data(x)) + pdf.close() + + from calibre.customize.ui import plugin_for_input_format + + pdf_plugin = plugin_for_input_format('pdf') + for opt in pdf_plugin.options: + if not hasattr(self.options, opt.option.name): + setattr(self.options, opt.option.name, opt.recommended_value) + + return pdf_plugin.convert(open(pdf, 'rb'), self.options, 'pdf', self.log, {}) diff --git a/ebook_converter/ebooks/pdb/plucker/__init__.py b/ebook_converter/ebooks/pdb/plucker/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ebook_converter/ebooks/pdb/plucker/reader.py b/ebook_converter/ebooks/pdb/plucker/reader.py new file mode 100644 index 0000000..76555dc --- /dev/null +++ b/ebook_converter/ebooks/pdb/plucker/reader.py @@ -0,0 +1,737 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + + +__license__ = 'GPL v3' +__copyright__ = '20011, John Schember ' +__docformat__ = 'restructuredtext en' + +import os +import struct +import zlib + +from collections import OrderedDict + +from calibre import CurrentDir +from calibre.ebooks.pdb.formatreader import FormatReader +from calibre.ebooks.compression.palmdoc import decompress_doc +from calibre.utils.imghdr import identify +from calibre.utils.img import save_cover_data_to, Canvas, image_from_data +from polyglot.builtins import codepoint_to_chr, range + +DATATYPE_PHTML = 0 +DATATYPE_PHTML_COMPRESSED = 1 +DATATYPE_TBMP = 2 +DATATYPE_TBMP_COMPRESSED = 3 +DATATYPE_MAILTO = 4 +DATATYPE_LINK_INDEX = 5 +DATATYPE_LINKS = 6 +DATATYPE_LINKS_COMPRESSED = 7 +DATATYPE_BOOKMARKS = 8 +DATATYPE_CATEGORY = 9 +DATATYPE_METADATA = 10 +DATATYPE_STYLE_SHEET = 11 +DATATYPE_FONT_PAGE = 12 +DATATYPE_TABLE = 13 +DATATYPE_TABLE_COMPRESSED = 14 +DATATYPE_COMPOSITE_IMAGE = 15 +DATATYPE_PAGELIST_METADATA = 16 +DATATYPE_SORTED_URL_INDEX = 17 +DATATYPE_SORTED_URL = 18 +DATATYPE_SORTED_URL_COMPRESSED = 19 +DATATYPE_EXT_ANCHOR_INDEX = 20 +DATATYPE_EXT_ANCHOR = 21 +DATATYPE_EXT_ANCHOR_COMPRESSED = 22 + +# IETF IANA MIBenum value for the character set. +# See the http://www.iana.org/assignments/character-sets for valid values. +# Not all character sets are handled by Python. This is a small subset that +# the MIBenum maps to Python standard encodings +# from http://docs.python.org/library/codecs.html#standard-encodings +MIBNUM_TO_NAME = { + 3: 'ascii', + 4: 'latin_1', + 5: 'iso8859_2', + 6: 'iso8859_3', + 7: 'iso8859_4', + 8: 'iso8859_5', + 9: 'iso8859_6', + 10: 'iso8859_7', + 11: 'iso8859_8', + 12: 'iso8859_9', + 13: 'iso8859_10', + 17: 'shift_jis', + 18: 'euc_jp', + 27: 'utf_7', + 36: 'euc_kr', + 37: 'iso2022_kr', + 38: 'euc_kr', + 39: 'iso2022_jp', + 40: 'iso2022_jp_2', + 106: 'utf-8', + 109: 'iso8859_13', + 110: 'iso8859_14', + 111: 'iso8859_15', + 112: 'iso8859_16', + 1013: 'utf_16_be', + 1014: 'utf_16_le', + 1015: 'utf_16', + 2009: 'cp850', + 2010: 'cp852', + 2011: 'cp437', + 2013: 'cp862', + 2025: 'gb2312', + 2026: 'big5', + 2028: 'cp037', + 2043: 'cp424', + 2044: 'cp500', + 2046: 'cp855', + 2047: 'cp857', + 2048: 'cp860', + 2049: 'cp861', + 2050: 'cp863', + 2051: 'cp864', + 2052: 'cp865', + 2054: 'cp869', + 2063: 'cp1026', + 2085: 'hz', + 2086: 'cp866', + 2087: 'cp775', + 2089: 'cp858', + 2091: 'cp1140', + 2102: 'big5hkscs', + 2250: 'cp1250', + 2251: 'cp1251', + 2252: 'cp1252', + 2253: 'cp1253', + 2254: 'cp1254', + 2255: 'cp1255', + 2256: 'cp1256', + 2257: 'cp1257', + 2258: 'cp1258', +} + + +class HeaderRecord(object): + ''' + Plucker header. PDB record 0. + ''' + + def __init__(self, raw): + self.uid, = struct.unpack('>H', raw[0:2]) + # This is labled version in the spec. + # 2 is ZLIB compressed, + # 1 is DOC compressed + self.compression, = struct.unpack('>H', raw[2:4]) + self.records, = struct.unpack('>H', raw[4:6]) + # uid of the first html file. This should link + # to other files which in turn may link to others. + self.home_html = None + + self.reserved = {} + for i in range(self.records): + adv = 4*i + name, = struct.unpack('>H', raw[6+adv:8+adv]) + id, = struct.unpack('>H', raw[8+adv:10+adv]) + self.reserved[id] = name + if name == 0: + self.home_html = id + + +class SectionHeader(object): + ''' + Every sections (record) has this header. It gives + details about the section such as it's uid. + ''' + + def __init__(self, raw): + self.uid, = struct.unpack('>H', raw[0:2]) + self.paragraphs, = struct.unpack('>H', raw[2:4]) + self.size, = struct.unpack('>H', raw[4:6]) + self.type, = struct.unpack('>B', raw[6]) + self.flags, = struct.unpack('>B', raw[7]) + + +class SectionHeaderText(object): + ''' + Sub header for text records. + ''' + + def __init__(self, section_header, raw): + # The uncompressed size of each paragraph. + self.sizes = [] + # uncompressed offset of each paragraph starting + # at the beginning of the PHTML. + self.paragraph_offsets = [] + # Paragraph attributes. + self.attributes = [] + + for i in range(section_header.paragraphs): + adv = 4*i + self.sizes.append(struct.unpack('>H', raw[adv:2+adv])[0]) + self.attributes.append(struct.unpack('>H', raw[2+adv:4+adv])[0]) + + running_offset = 0 + for size in self.sizes: + running_offset += size + self.paragraph_offsets.append(running_offset) + + +class SectionMetadata(object): + ''' + Metadata. + + This does not store metadata such as title, or author. + That metadata would be best retrieved with the PDB (plucker) + metdata reader. + + This stores document specific information such as the + text encoding. + + Note: There is a default encoding but each text section + can be assigned a different encoding. + ''' + + def __init__(self, raw): + self.default_encoding = 'latin-1' + self.exceptional_uid_encodings = {} + self.owner_id = None + + record_count, = struct.unpack('>H', raw[0:2]) + + adv = 0 + for i in range(record_count): + try: + type, length = struct.unpack_from('>HH', raw, 2 + adv) + except struct.error: + break + + # CharSet + if type == 1: + val, = struct.unpack('>H', raw[6+adv:8+adv]) + self.default_encoding = MIBNUM_TO_NAME.get(val, 'latin-1') + # ExceptionalCharSets + elif type == 2: + ii_adv = 0 + for ii in range(length / 2): + uid, = struct.unpack('>H', raw[6+adv+ii_adv:8+adv+ii_adv]) + mib, = struct.unpack('>H', raw[8+adv+ii_adv:10+adv+ii_adv]) + self.exceptional_uid_encodings[uid] = MIBNUM_TO_NAME.get(mib, 'latin-1') + ii_adv += 4 + # OwnerID + elif type == 3: + self.owner_id = struct.unpack('>I', raw[6+adv:10+adv]) + # Author, Title, PubDate + # Ignored here. The metadata reader plugin + # will get this info because if it's missing + # the metadata reader plugin will use fall + # back data from elsewhere in the file. + elif type in (4, 5, 6): + pass + # Linked Documents + elif type == 7: + pass + + adv += 2*length + + +class SectionText(object): + ''' + Text data. Stores a text section header and the PHTML. + ''' + + def __init__(self, section_header, raw): + self.header = SectionHeaderText(section_header, raw) + self.data = raw[section_header.paragraphs * 4:] + + +class SectionCompositeImage(object): + ''' + A composite image consists of a 2D array + of rows and columns. The entries in the array + are uid's. + ''' + + def __init__(self, raw): + self.columns, = struct.unpack('>H', raw[0:2]) + self.rows, = struct.unpack('>H', raw[2:4]) + + # [ + # [uid, uid, uid, ...], + # [uid, uid, uid, ...], + # ... + # ] + # + # Each item in the layout is in it's + # correct position in the final + # composite. + # + # Each item in the layout is a uid + # to an image record. + self.layout = [] + offset = 4 + for i in range(self.rows): + col = [] + for j in range(self.columns): + col.append(struct.unpack('>H', raw[offset:offset+2])[0]) + offset += 2 + self.layout.append(col) + + +class Reader(FormatReader): + ''' + Convert a plucker archive into HTML. + + TODO: + * UTF 16 and 32 characters. + * Margins. + * Alignment. + * Font color. + * DATATYPE_MAILTO + * DATATYPE_TABLE(_COMPRESSED) + * DATATYPE_EXT_ANCHOR_INDEX + * DATATYPE_EXT_ANCHOR(_COMPRESSED) + ''' + + def __init__(self, header, stream, log, options): + self.stream = stream + self.log = log + self.options = options + + # Mapping of section uid to our internal + # list of sections. + self.uid_section_number = OrderedDict() + self.uid_text_secion_number = OrderedDict() + self.uid_text_secion_encoding = {} + self.uid_image_section_number = {} + self.uid_composite_image_section_number = {} + self.metadata_section_number = None + self.default_encoding = 'latin-1' + self.owner_id = None + self.sections = [] + + # The Plucker record0 header + self.header_record = HeaderRecord(header.section_data(0)) + + for i in range(1, header.num_sections): + section_number = len(self.sections) + # The length of the section header. + # Where the actual data in the section starts. + start = 8 + section = None + + raw_data = header.section_data(i) + # Every sections has a section header. + section_header = SectionHeader(raw_data) + + # Store sections we care able. + if section_header.type in (DATATYPE_PHTML, DATATYPE_PHTML_COMPRESSED): + self.uid_text_secion_number[section_header.uid] = section_number + section = SectionText(section_header, raw_data[start:]) + elif section_header.type in (DATATYPE_TBMP, DATATYPE_TBMP_COMPRESSED): + self.uid_image_section_number[section_header.uid] = section_number + section = raw_data[start:] + elif section_header.type == DATATYPE_METADATA: + self.metadata_section_number = section_number + section = SectionMetadata(raw_data[start:]) + elif section_header.type == DATATYPE_COMPOSITE_IMAGE: + self.uid_composite_image_section_number[section_header.uid] = section_number + section = SectionCompositeImage(raw_data[start:]) + + # Store the section. + if section: + self.uid_section_number[section_header.uid] = section_number + self.sections.append((section_header, section)) + + # Store useful information from the metadata section locally + # to make access easier. + if self.metadata_section_number: + mdata_section = self.sections[self.metadata_section_number][1] + for k, v in mdata_section.exceptional_uid_encodings.items(): + self.uid_text_secion_encoding[k] = v + self.default_encoding = mdata_section.default_encoding + self.owner_id = mdata_section.owner_id + + # Get the metadata (tile, author, ...) with the metadata reader. + from calibre.ebooks.metadata.pdb import get_metadata + self.mi = get_metadata(stream, False) + + def extract_content(self, output_dir): + # Each text record is independent (unless the continuation + # value is set in the previous record). Put each converted + # text recored into a separate file. We will reference the + # home.html file as the first file and let the HTML input + # plugin assemble the order based on hyperlinks. + with CurrentDir(output_dir): + for uid, num in self.uid_text_secion_number.items(): + self.log.debug('Writing record with uid: %s as %s.html' % (uid, uid)) + with open('%s.html' % uid, 'wb') as htmlf: + html = u'' + section_header, section_data = self.sections[num] + if section_header.type == DATATYPE_PHTML: + html += self.process_phtml(section_data.data, section_data.header.paragraph_offsets) + elif section_header.type == DATATYPE_PHTML_COMPRESSED: + d = self.decompress_phtml(section_data.data) + html += self.process_phtml(d, section_data.header.paragraph_offsets).decode(self.get_text_uid_encoding(section_header.uid), 'replace') + html += '' + htmlf.write(html.encode('utf-8')) + + # Images. + # Cache the image sizes in case they are used by a composite image. + images = set() + if not os.path.exists(os.path.join(output_dir, 'images/')): + os.makedirs(os.path.join(output_dir, 'images/')) + with CurrentDir(os.path.join(output_dir, 'images/')): + # Single images. + for uid, num in self.uid_image_section_number.items(): + section_header, section_data = self.sections[num] + if section_data: + idata = None + if section_header.type == DATATYPE_TBMP: + idata = section_data + elif section_header.type == DATATYPE_TBMP_COMPRESSED: + if self.header_record.compression == 1: + idata = decompress_doc(section_data) + elif self.header_record.compression == 2: + idata = zlib.decompress(section_data) + try: + save_cover_data_to(idata, '%s.jpg' % uid, compression_quality=70) + images.add(uid) + self.log.debug('Wrote image with uid %s to images/%s.jpg' % (uid, uid)) + except Exception as e: + self.log.error('Failed to write image with uid %s: %s' % (uid, e)) + else: + self.log.error('Failed to write image with uid %s: No data.' % uid) + # Composite images. + # We're going to use the already compressed .jpg images here. + for uid, num in self.uid_composite_image_section_number.items(): + try: + section_header, section_data = self.sections[num] + # Get the final width and height. + width = 0 + height = 0 + for row in section_data.layout: + row_width = 0 + col_height = 0 + for col in row: + if col not in images: + raise Exception('Image with uid: %s missing.' % col) + w, h = identify(lopen('%s.jpg' % col, 'rb'))[1:] + row_width += w + if col_height < h: + col_height = h + if width < row_width: + width = row_width + height += col_height + # Create a new image the total size of all image + # parts. Put the parts into the new image. + with Canvas(width, height) as canvas: + y_off = 0 + for row in section_data.layout: + x_off = 0 + largest_height = 0 + for col in row: + im = image_from_data(lopen('%s.jpg' % col, 'rb').read()) + canvas.compose(im, x_off, y_off) + w, h = im.width(), im.height() + x_off += w + if largest_height < h: + largest_height = h + y_off += largest_height + with lopen('%s.jpg' % uid) as out: + out.write(canvas.export(compression_quality=70)) + self.log.debug('Wrote composite image with uid %s to images/%s.jpg' % (uid, uid)) + except Exception as e: + self.log.error('Failed to write composite image with uid %s: %s' % (uid, e)) + + # Run the HTML through the html processing plugin. + from calibre.customize.ui import plugin_for_input_format + html_input = plugin_for_input_format('html') + for opt in html_input.options: + setattr(self.options, opt.option.name, opt.recommended_value) + self.options.input_encoding = 'utf-8' + odi = self.options.debug_pipeline + self.options.debug_pipeline = None + # Determine the home.html record uid. This should be set in the + # reserved values in the metadata recored. home.html is the first + # text record (should have hyper link references to other records) + # in the document. + try: + home_html = self.header_record.home_html + if not home_html: + home_html = self.uid_text_secion_number.items()[0][0] + except: + raise Exception('Could not determine home.html') + # Generate oeb from html conversion. + oeb = html_input.convert(open('%s.html' % home_html, 'rb'), self.options, 'html', self.log, {}) + self.options.debug_pipeline = odi + + return oeb + + def decompress_phtml(self, data): + if self.header_record.compression == 2: + if self.owner_id: + raise NotImplementedError + return zlib.decompress(data) + elif self.header_record.compression == 1: + from calibre.ebooks.compression.palmdoc import decompress_doc + return decompress_doc(data) + + def process_phtml(self, d, paragraph_offsets=[]): + html = u'

' + offset = 0 + paragraph_open = True + link_open = False + need_set_p_id = False + p_num = 1 + font_specifier_close = '' + + while offset < len(d): + if not paragraph_open: + if need_set_p_id: + html += u'

' % p_num + p_num += 1 + need_set_p_id = False + else: + html += u'

' + paragraph_open = True + + c = ord(d[offset:offset+1]) + # PHTML "functions" + if c == 0x0: + offset += 1 + c = ord(d[offset:offset+1]) + # Page link begins + # 2 Bytes + # record ID + if c == 0x0a: + offset += 1 + id = struct.unpack('>H', d[offset:offset+2])[0] + if id in self.uid_text_secion_number: + html += '' % id + link_open = True + offset += 1 + # Targeted page link begins + # 3 Bytes + # record ID, target + elif c == 0x0b: + offset += 3 + # Paragraph link begins + # 4 Bytes + # record ID, paragraph number + elif c == 0x0c: + offset += 1 + id = struct.unpack('>H', d[offset:offset+2])[0] + offset += 2 + pid = struct.unpack('>H', d[offset:offset+2])[0] + if id in self.uid_text_secion_number: + html += '' % (id, pid) + link_open = True + offset += 1 + # Targeted paragraph link begins + # 5 Bytes + # record ID, paragraph number, target + elif c == 0x0d: + offset += 5 + # Link ends + # 0 Bytes + elif c == 0x08: + if link_open: + html += '' + link_open = False + # Set font + # 1 Bytes + # font specifier + elif c == 0x11: + offset += 1 + specifier = d[offset] + html += font_specifier_close + # Regular text + if specifier == 0: + font_specifier_close = '' + # h1 + elif specifier == 1: + html += '

' + font_specifier_close = '

' + # h2 + elif specifier == 2: + html += '

' + font_specifier_close = '

' + # h3 + elif specifier == 3: + html += '' + font_specifier_close = '

' + # h4 + elif specifier == 4: + html += '

' + font_specifier_close = '

' + # h5 + elif specifier == 5: + html += '
' + font_specifier_close = '
' + # h6 + elif specifier == 6: + html += '
' + font_specifier_close = '
' + # Bold + elif specifier == 7: + html += '' + font_specifier_close = '' + # Fixed-width + elif specifier == 8: + html += '' + font_specifier_close = '' + # Small + elif specifier == 9: + html += '' + font_specifier_close = '' + # Subscript + elif specifier == 10: + html += '' + font_specifier_close = '' + # Superscript + elif specifier == 11: + html += '' + font_specifier_close = '' + # Embedded image + # 2 Bytes + # image record ID + elif c == 0x1a: + offset += 1 + uid = struct.unpack('>H', d[offset:offset+2])[0] + html += '' % uid + offset += 1 + # Set margin + # 2 Bytes + # left margin, right margin + elif c == 0x22: + offset += 2 + # Alignment of text + # 1 Bytes + # alignment + elif c == 0x29: + offset += 1 + # Horizontal rule + # 3 Bytes + # 8-bit height, 8-bit width (pixels), 8-bit width (%, 1-100) + elif c == 0x33: + offset += 3 + if paragraph_open: + html += u'

' + paragraph_open = False + html += u'
' + # New line + # 0 Bytes + elif c == 0x38: + if paragraph_open: + html += u'

\n' + paragraph_open = False + # Italic text begins + # 0 Bytes + elif c == 0x40: + html += u'' + # Italic text ends + # 0 Bytes + elif c == 0x48: + html += u'' + # Set text color + # 3 Bytes + # 8-bit red, 8-bit green, 8-bit blue + elif c == 0x53: + offset += 3 + # Multiple embedded image + # 4 Bytes + # alternate image record ID, image record ID + elif c == 0x5c: + offset += 3 + uid = struct.unpack('>H', d[offset:offset+2])[0] + html += '' % uid + offset += 1 + # Underline text begins + # 0 Bytes + elif c == 0x60: + html += u'' + # Underline text ends + # 0 Bytes + elif c == 0x68: + html += u'' + # Strike-through text begins + # 0 Bytes + elif c == 0x70: + html += u'' + # Strike-through text ends + # 0 Bytes + elif c == 0x78: + html += u'' + # 16-bit Unicode character + # 3 Bytes + # alternate text length, 16-bit unicode character + elif c == 0x83: + offset += 3 + # 32-bit Unicode character + # 5 Bytes + # alternate text length, 32-bit unicode character + elif c == 0x85: + offset += 5 + # Begin custom font span + # 6 Bytes + # font page record ID, X page position, Y page position + elif c == 0x8e: + offset += 6 + # Adjust custom font glyph position + # 4 Bytes + # X page position, Y page position + elif c == 0x8c: + offset += 4 + # Change font page + # 2 Bytes + # font record ID + elif c == 0x8a: + offset += 2 + # End custom font span + # 0 Bytes + elif c == 0x88: + pass + # Begin new table row + # 0 Bytes + elif c == 0x90: + pass + # Insert table (or table link) + # 2 Bytes + # table record ID + elif c == 0x92: + offset += 2 + # Table cell data + # 7 Bytes + # 8-bit alignment, 16-bit image record ID, 8-bit columns, 8-bit rows, 16-bit text length + elif c == 0x97: + offset += 7 + # Exact link modifier + # 2 Bytes + # Paragraph Offset (The Exact Link Modifier modifies a Paragraph Link or + # Targeted Paragraph Link function to specify an exact byte offset within + # the paragraph. This function must be followed immediately by the + # function it modifies). + elif c == 0x9a: + offset += 2 + elif c == 0xa0: + html += ' ' + else: + html += codepoint_to_chr(c) + offset += 1 + if offset in paragraph_offsets: + need_set_p_id = True + if paragraph_open: + html += u'

\n' + paragraph_open = False + + if paragraph_open: + html += u'

' + + return html + + def get_text_uid_encoding(self, uid): + # Return the user sepcified input encoding, + # otherwise return the alternate encoding specified for the uid, + # otherwise retur the default encoding for the document. + return self.options.input_encoding if self.options.input_encoding else self.uid_text_secion_encoding.get(uid, self.default_encoding) diff --git a/ebook_converter/ebooks/pdb/ztxt/__init__.py b/ebook_converter/ebooks/pdb/ztxt/__init__.py new file mode 100644 index 0000000..18d4da9 --- /dev/null +++ b/ebook_converter/ebooks/pdb/ztxt/__init__.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2009, John Schember ' +__docformat__ = 'restructuredtext en' + + +class zTXTError(Exception): + pass diff --git a/ebook_converter/ebooks/pdb/ztxt/reader.py b/ebook_converter/ebooks/pdb/ztxt/reader.py new file mode 100644 index 0000000..a1c36cf --- /dev/null +++ b/ebook_converter/ebooks/pdb/ztxt/reader.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +''' +Read content from ztxt pdb file. +''' + +__license__ = 'GPL v3' +__copyright__ = '2009, John Schember ' +__docformat__ = 'restructuredtext en' + +import struct +import zlib +import io + + +from calibre.ebooks.pdb.formatreader import FormatReader +from calibre.ebooks.pdb.ztxt import zTXTError + +SUPPORTED_VERSION = (1, 40) + + +class HeaderRecord(object): + ''' + The first record in the file is always the header record. It holds + information related to the location of text, images, and so on + in the file. This is used in conjunction with the sections + defined in the file header. + ''' + + def __init__(self, raw): + self.version, = struct.unpack('>H', raw[0:2]) + self.num_records, = struct.unpack('>H', raw[2:4]) + self.size, = struct.unpack('>L', raw[4:8]) + self.record_size, = struct.unpack('>H', raw[8:10]) + self.flags, = struct.unpack('>B', raw[18:19]) + + +class Reader(FormatReader): + + def __init__(self, header, stream, log, options): + self.stream = stream + self.log = log + self.options = options + + self.sections = [] + for i in range(header.num_sections): + self.sections.append(header.section_data(i)) + + self.header_record = HeaderRecord(self.section_data(0)) + + vmajor = (self.header_record.version & 0x0000FF00) >> 8 + vminor = self.header_record.version & 0x000000FF + if vmajor < 1 or (vmajor == 1 and vminor < 40): + raise zTXTError('Unsupported ztxt version (%i.%i). Only versions newer than %i.%i are supported.' % + (vmajor, vminor, SUPPORTED_VERSION[0], SUPPORTED_VERSION[1])) + + if (self.header_record.flags & 0x01) == 0: + raise zTXTError('Only compression method 1 (random access) is supported') + + self.log.debug('Foud ztxt version: %i.%i' % (vmajor, vminor)) + + # Initalize the decompressor + self.uncompressor = zlib.decompressobj() + self.uncompressor.decompress(self.section_data(1)) + + def section_data(self, number): + return self.sections[number] + + def decompress_text(self, number): + if number == 1: + self.uncompressor = zlib.decompressobj() + return self.uncompressor.decompress(self.section_data(number)) + + def extract_content(self, output_dir): + raw_txt = b'' + + self.log.info('Decompressing text...') + for i in range(1, self.header_record.num_records + 1): + self.log.debug('\tDecompressing text section %i' % i) + raw_txt += self.decompress_text(i) + + self.log.info('Converting text to OEB...') + stream = io.BytesIO(raw_txt) + + from calibre.customize.ui import plugin_for_input_format + + txt_plugin = plugin_for_input_format('txt') + for opt in txt_plugin.options: + if not hasattr(self.options, opt.option.name): + setattr(self.options, opt.option.name, opt.recommended_value) + + stream.seek(0) + return txt_plugin.convert(stream, self.options, 'txt', self.log, {}) diff --git a/ebook_converter/ebooks/rtf/__init__.py b/ebook_converter/ebooks/rtf/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/ebook_converter/ebooks/rtf/__init__.py @@ -0,0 +1 @@ + diff --git a/ebook_converter/ebooks/rtf/input.py b/ebook_converter/ebooks/rtf/input.py new file mode 100644 index 0000000..075eaaa --- /dev/null +++ b/ebook_converter/ebooks/rtf/input.py @@ -0,0 +1,39 @@ +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2008, Kovid Goyal ' + + +from lxml import etree + + +class InlineClass(etree.XSLTExtension): + + FMTS = ('italics', 'bold', 'strike-through', 'small-caps') + + def __init__(self, log): + etree.XSLTExtension.__init__(self) + self.log = log + self.font_sizes = [] + self.colors = [] + + def execute(self, context, self_node, input_node, output_parent): + classes = ['none'] + for x in self.FMTS: + if input_node.get(x, None) == 'true': + classes.append(x) + # underlined is special + if input_node.get('underlined', 'false') != 'false': + classes.append('underlined') + fs = input_node.get('font-size', False) + if fs: + if fs not in self.font_sizes: + self.font_sizes.append(fs) + classes.append('fs%d'%self.font_sizes.index(fs)) + fc = input_node.get('font-color', False) + if fc: + if fc not in self.colors: + self.colors.append(fc) + classes.append('col%d'%self.colors.index(fc)) + + output_parent.text = ' '.join(classes) diff --git a/ebook_converter/ebooks/rtf2xml/ParseRtf.py b/ebook_converter/ebooks/rtf2xml/ParseRtf.py new file mode 100644 index 0000000..164e706 --- /dev/null +++ b/ebook_converter/ebooks/rtf2xml/ParseRtf.py @@ -0,0 +1,573 @@ +from __future__ import absolute_import, division, print_function, unicode_literals +######################################################################### +# # +# # +# copyright 2002 Paul Henry Tremblay # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # +# General Public License for more details. # +# # +# # +######################################################################### +# $Revision: 1.41 $ +# $Date: 2006/03/24 23:50:07 $ +import sys, os + +from calibre.ebooks.rtf2xml import headings_to_sections, \ + line_endings, footnote, fields_small, default_encoding, \ + make_lists, preamble_div, header, colors, group_borders, \ + check_encoding, add_brackets, table, combine_borders, \ + fields_large, process_tokens, hex_2_utf8, tokenize, \ + delete_info, sections, check_brackets, styles, \ + paragraph_def, convert_to_tags, output, copy, \ + list_numbers, info, pict, table_info, fonts, paragraphs, \ + body_styles, preamble_rest, group_styles, \ + inline +from calibre.ebooks.rtf2xml.old_rtf import OldRtf +from polyglot.builtins import unicode_type + +from . import open_for_read, open_for_write + +""" +Here is an example script using the ParseRTF module directly +#!/usr/bin/env python2 + +def Handle_Main(): + # Handles options and creates a parse object + parse_obj =ParseRtf.ParseRtf( + in_file = 'in.rtf', + # All values from here on are optional + # determine the output file + out_file = 'out.xml', + # determine the run level. The default is 1. + run_level = 3, + # The name of a debug directory, if you are running at + # run level 3 or higer. + debug = 'debug_dir', + # Convert RTF caps to real caps. + # Default is 1. + convert_caps = 1, + # Indent resulting XML. + # Default is 0 (no indent). + indent = 1, + # Form lists from RTF. Default is 1. + form_lists = 1, + # Convert headings to sections. Default is 0. + headings_to_sections = 1, + # Group paragraphs with the same style name. Default is 1. + group_styles = 1, + # Group borders. Default is 1. + group_borders = 1, + # Write or do not write paragraphs. Default is 0. + empty_paragraphs = 0, + # Allow to use a custom default encoding as fallback + default_encoding = 'cp1252', + ) + try: + parse_obj.parse_rtf() + except ParseRtf.InvalidRtfException, msg: + sys.stderr.write(msg) + except ParseRtf.RtfInvalidCodeException, msg: + sys.stderr.write(msg) +""" + + +class InvalidRtfException(Exception): + """ + handle invalid RTF + """ + pass + + +class RtfInvalidCodeException(Exception): + """ + handle bugs in program + """ + pass + + +class ParseRtf: + """ + Main class for controlling the rest of the parsing. + """ + + def __init__(self, + in_file, + out_file='', + out_dir=None, + dtd='', + deb_dir=None, + convert_symbol=None, + convert_wingdings=None, + convert_zapf=None, + convert_caps=None, + run_level=1, + indent=None, + replace_illegals=1, + form_lists=1, + headings_to_sections=1, + group_styles=1, + group_borders=1, + empty_paragraphs=1, + no_dtd=0, + char_data='', + default_encoding='cp1252', + ): + """ + Requires: + 'file' --file to parse + 'char_data' --file containing character maps + 'dtd' --path to dtd + Possible parameters, but not necessary: + 'output' --a file to output the parsed file. (Default is standard + output.) + 'temp_dir' --directory for temporary output (If not provided, the + script tries to output to directory where is script is exectued.) + 'deb_dir' --debug directory. If a debug_dir is provided, the script + will copy each run through as a file to examine in the debug_dir + 'check_brackets' -- make sure the brackets match up after each run + through a file. Only for debugging. + Returns: Nothing + """ + + self.__file = in_file + self.__out_file = out_file + self.__out_dir = out_dir + self.__temp_dir = out_dir + self.__dtd_path = dtd + self.__check_file(in_file,"file_to_parse") + self.__char_data = char_data + self.__debug_dir = deb_dir + self.__check_dir(self.__temp_dir) + self.__copy = self.__check_dir(self.__debug_dir) + self.__convert_caps = convert_caps + self.__convert_symbol = convert_symbol + self.__convert_wingdings = convert_wingdings + self.__convert_zapf = convert_zapf + self.__run_level = run_level + self.__exit_level = 0 + self.__indent = indent + self.__replace_illegals = replace_illegals + self.__form_lists = form_lists + self.__headings_to_sections = headings_to_sections + self.__group_styles = group_styles + self.__group_borders = group_borders + self.__empty_paragraphs = empty_paragraphs + self.__no_dtd = no_dtd + self.__default_encoding = default_encoding + + def __check_file(self, the_file, type): + """Check to see if files exist""" + if hasattr(the_file, 'read'): + return + if the_file is None: + if type == "file_to_parse": + msg = "\nYou must provide a file for the script to work" + raise RtfInvalidCodeException(msg) + elif os.path.exists(the_file): + pass # do nothing + else: + msg = "\nThe file '%s' cannot be found" % the_file + raise RtfInvalidCodeException(msg) + + def __check_dir(self, the_dir): + """Check to see if directory exists""" + if not the_dir : + return + dir_exists = os.path.isdir(the_dir) + if not dir_exists: + msg = "\n%s is not a directory" % the_dir + raise RtfInvalidCodeException(msg) + return 1 + + def parse_rtf(self): + """ + Parse the file by calling on other classes. + Requires: + Nothing + Returns: + A parsed file in XML, either to standard output or to a file, + depending on the value of 'output' when the instance was created. + """ + self.__temp_file = self.__make_temp_file(self.__file) + # if the self.__deb_dir is true, then create a copy object, + # set the directory to write to, remove files, and copy + # the new temporary file to this directory + if self.__debug_dir: + copy_obj = copy.Copy( + bug_handler=RtfInvalidCodeException, + ) + copy_obj.set_dir(self.__debug_dir) + copy_obj.remove_files() + copy_obj.copy_file(self.__temp_file, "original_file") + # Function to check if bracket are well handled + if self.__debug_dir or self.__run_level > 2: + self.__check_brack_obj = check_brackets.CheckBrackets( + file=self.__temp_file, + bug_handler=RtfInvalidCodeException, + ) + # convert Macintosh and Windows line endings to Unix line endings + # why do this if you don't wb after? + line_obj = line_endings.FixLineEndings( + in_file=self.__temp_file, + bug_handler=RtfInvalidCodeException, + copy=self.__copy, + run_level=self.__run_level, + replace_illegals=self.__replace_illegals, + ) + return_value = line_obj.fix_endings() # calibre return what? + self.__return_code(return_value) + tokenize_obj = tokenize.Tokenize( + bug_handler=RtfInvalidCodeException, + in_file=self.__temp_file, + copy=self.__copy, + run_level=self.__run_level) + tokenize_obj.tokenize() + process_tokens_obj = process_tokens.ProcessTokens( + in_file=self.__temp_file, + bug_handler=RtfInvalidCodeException, + copy=self.__copy, + run_level=self.__run_level, + exception_handler=InvalidRtfException, + ) + try: + return_value = process_tokens_obj.process_tokens() + except InvalidRtfException as msg: + # Check to see if the file is correctly encoded + encode_obj = default_encoding.DefaultEncoding( + in_file=self.__temp_file, + run_level=self.__run_level, + bug_handler=RtfInvalidCodeException, + check_raw=True, + default_encoding=self.__default_encoding, + ) + platform, code_page, default_font_num = encode_obj.find_default_encoding() + check_encoding_obj = check_encoding.CheckEncoding( + bug_handler=RtfInvalidCodeException, + ) + enc = encode_obj.get_codepage() + # TODO: to check if cp is a good idea or if I should use a dict to convert + enc = 'cp' + enc + msg = '%s\nException in token processing' % unicode_type(msg) + if check_encoding_obj.check_encoding(self.__file, enc): + file_name = self.__file if isinstance(self.__file, bytes) \ + else self.__file.encode('utf-8') + msg +='\nFile %s does not appear to be correctly encoded.\n' % file_name + try: + os.remove(self.__temp_file) + except OSError: + pass + raise InvalidRtfException(msg) + delete_info_obj = delete_info.DeleteInfo( + in_file=self.__temp_file, + copy=self.__copy, + bug_handler=RtfInvalidCodeException, + run_level=self.__run_level,) + # found destination means {\*\destination + # if found, the RTF should be newer RTF + found_destination = delete_info_obj.delete_info() + self.__bracket_match('delete_data_info') + # put picts in a separate file + pict_obj = pict.Pict( + in_file=self.__temp_file, + bug_handler=RtfInvalidCodeException, + copy=self.__copy, + orig_file=self.__file, + out_file=self.__out_file, + run_level=self.__run_level, + ) + pict_obj.process_pict() + self.__bracket_match('pict_data_info') + combine_obj = combine_borders.CombineBorders( + in_file=self.__temp_file, + bug_handler=RtfInvalidCodeException, + copy=self.__copy, + run_level=self.__run_level,) + combine_obj.combine_borders() + self.__bracket_match('combine_borders_info') + footnote_obj = footnote.Footnote( + in_file=self.__temp_file, + bug_handler=RtfInvalidCodeException, + copy=self.__copy, + run_level=self.__run_level, + ) + footnote_obj.separate_footnotes() + self.__bracket_match('separate_footnotes_info') + header_obj = header.Header( + in_file=self.__temp_file, + bug_handler=RtfInvalidCodeException, + copy=self.__copy, + run_level=self.__run_level, + ) + header_obj.separate_headers() + self.__bracket_match('separate_headers_info') + list_numbers_obj = list_numbers.ListNumbers( + in_file=self.__temp_file, + bug_handler=RtfInvalidCodeException, + copy=self.__copy, + run_level=self.__run_level, + ) + list_numbers_obj.fix_list_numbers() + self.__bracket_match('list_number_info') + preamble_div_obj = preamble_div.PreambleDiv( + in_file=self.__temp_file, + bug_handler=RtfInvalidCodeException, + copy=self.__copy, + run_level=self.__run_level, + ) + list_of_lists = preamble_div_obj.make_preamble_divisions() + self.__bracket_match('make_preamble_divisions') + encode_obj = default_encoding.DefaultEncoding( + in_file=self.__temp_file, + run_level=self.__run_level, + bug_handler=RtfInvalidCodeException, + default_encoding=self.__default_encoding, + ) + platform, code_page, default_font_num = encode_obj.find_default_encoding() + hex2utf_obj = hex_2_utf8.Hex2Utf8( + in_file=self.__temp_file, + copy=self.__copy, + area_to_convert='preamble', + char_file=self.__char_data, + default_char_map=code_page, + run_level=self.__run_level, + bug_handler=RtfInvalidCodeException, + invalid_rtf_handler=InvalidRtfException, + ) + hex2utf_obj.convert_hex_2_utf8() + self.__bracket_match('hex_2_utf_preamble') + fonts_obj = fonts.Fonts( + in_file=self.__temp_file, + bug_handler=RtfInvalidCodeException, + copy=self.__copy, + default_font_num=default_font_num, + run_level=self.__run_level, + ) + special_font_dict = fonts_obj.convert_fonts() + self.__bracket_match('fonts_info') + color_obj = colors.Colors( + in_file=self.__temp_file, + copy=self.__copy, + bug_handler=RtfInvalidCodeException, + run_level=self.__run_level, + ) + color_obj.convert_colors() + self.__bracket_match('colors_info') + style_obj = styles.Styles( + in_file=self.__temp_file, + bug_handler=RtfInvalidCodeException, + copy=self.__copy, + run_level=self.__run_level, + ) + style_obj.convert_styles() + self.__bracket_match('styles_info') + info_obj = info.Info( + in_file=self.__temp_file, + bug_handler=RtfInvalidCodeException, + copy=self.__copy, + run_level=self.__run_level, + ) + info_obj.fix_info() + default_font = special_font_dict.get('default-font') + preamble_rest_obj = preamble_rest.Preamble( + file=self.__temp_file, copy=self.__copy, + bug_handler=RtfInvalidCodeException, + platform=platform, default_font=default_font, + code_page=code_page) + preamble_rest_obj.fix_preamble() + self.__bracket_match('preamble_rest_info') + old_rtf_obj = OldRtf( + in_file=self.__temp_file, + bug_handler=RtfInvalidCodeException, + run_level=self.__run_level, + ) + # RTF can actually have destination groups and old RTF. + # BAH! + old_rtf = old_rtf_obj.check_if_old_rtf() + if old_rtf: + if self.__run_level > 5: + msg = 'Older RTF\n' \ + 'self.__run_level is "%s"\n' % self.__run_level + raise RtfInvalidCodeException(msg) + if self.__run_level > 1: + sys.stderr.write('File could be older RTF...\n') + if found_destination: + if self.__run_level > 1: + sys.stderr.write( + 'File also has newer RTF.\n' + 'Will do the best to convert...\n' + ) + add_brackets_obj = add_brackets.AddBrackets( + in_file=self.__temp_file, + bug_handler=RtfInvalidCodeException, + copy=self.__copy, + run_level=self.__run_level, + ) + add_brackets_obj.add_brackets() + fields_small_obj = fields_small.FieldsSmall( + in_file=self.__temp_file, + copy=self.__copy, + bug_handler=RtfInvalidCodeException, + run_level=self.__run_level,) + fields_small_obj.fix_fields() + self.__bracket_match('fix_small_fields_info') + fields_large_obj = fields_large.FieldsLarge( + in_file=self.__temp_file, + copy=self.__copy, + bug_handler=RtfInvalidCodeException, + run_level=self.__run_level) + fields_large_obj.fix_fields() + self.__bracket_match('fix_large_fields_info') + sections_obj = sections.Sections( + in_file=self.__temp_file, + bug_handler=RtfInvalidCodeException, + copy=self.__copy, + run_level=self.__run_level,) + sections_obj.make_sections() + self.__bracket_match('sections_info') + paragraphs_obj = paragraphs.Paragraphs( + in_file=self.__temp_file, + bug_handler=RtfInvalidCodeException, + copy=self.__copy, + write_empty_para=self.__empty_paragraphs, + run_level=self.__run_level,) + paragraphs_obj.make_paragraphs() + self.__bracket_match('paragraphs_info') + default_font = special_font_dict['default-font'] + paragraph_def_obj = paragraph_def.ParagraphDef( + in_file=self.__temp_file, + bug_handler=RtfInvalidCodeException, + copy=self.__copy, + default_font=default_font, + run_level=self.__run_level,) + list_of_styles = paragraph_def_obj.make_paragraph_def() + body_styles_obj = body_styles.BodyStyles( + in_file=self.__temp_file, + bug_handler=RtfInvalidCodeException, + copy=self.__copy, + list_of_styles=list_of_styles, + run_level=self.__run_level,) + body_styles_obj.insert_info() + self.__bracket_match('body_styles_info') + self.__bracket_match('paragraph_def_info') + table_obj = table.Table( + in_file=self.__temp_file, + bug_handler=RtfInvalidCodeException, + copy=self.__copy, + run_level=self.__run_level,) + table_data = table_obj.make_table() + self.__bracket_match('table_info') + table_info_obj = table_info.TableInfo( + in_file=self.__temp_file, + bug_handler=RtfInvalidCodeException, + copy=self.__copy, + table_data=table_data, + run_level=self.__run_level,) + table_info_obj.insert_info() + self.__bracket_match('table__data_info') + if self.__form_lists: + make_list_obj = make_lists.MakeLists( + in_file=self.__temp_file, + bug_handler=RtfInvalidCodeException, + copy=self.__copy, + headings_to_sections=self.__headings_to_sections, + run_level=self.__run_level, + list_of_lists=list_of_lists, + ) + make_list_obj.make_lists() + self.__bracket_match('form_lists_info') + if self.__headings_to_sections: + headings_to_sections_obj = headings_to_sections.HeadingsToSections( + in_file=self.__temp_file, + bug_handler=RtfInvalidCodeException, + copy=self.__copy, + run_level=self.__run_level,) + headings_to_sections_obj.make_sections() + self.__bracket_match('headings_to_sections_info') + if self.__group_styles: + group_styles_obj = group_styles.GroupStyles( + in_file=self.__temp_file, + bug_handler=RtfInvalidCodeException, + copy=self.__copy, + wrap=1, + run_level=self.__run_level,) + group_styles_obj.group_styles() + self.__bracket_match('group_styles_info') + if self.__group_borders: + group_borders_obj = group_borders.GroupBorders( + in_file=self.__temp_file, + bug_handler=RtfInvalidCodeException, + copy=self.__copy, + wrap=1, + run_level=self.__run_level,) + group_borders_obj.group_borders() + self.__bracket_match('group_borders_info') + inline_obj = inline.Inline( + in_file=self.__temp_file, + bug_handler=RtfInvalidCodeException, + copy=self.__copy, + run_level=self.__run_level,) + inline_obj.form_tags() + self.__bracket_match('inline_info') + hex2utf_obj.update_values(file=self.__temp_file, + area_to_convert='body', + copy=self.__copy, + char_file=self.__char_data, + convert_caps=self.__convert_caps, + convert_symbol=self.__convert_symbol, + convert_wingdings=self.__convert_wingdings, + convert_zapf=self.__convert_zapf, + symbol=1, + wingdings=1, + dingbats=1, + ) + hex2utf_obj.convert_hex_2_utf8() + header_obj.join_headers() + footnote_obj.join_footnotes() + tags_obj = convert_to_tags.ConvertToTags( + in_file=self.__temp_file, + copy=self.__copy, + dtd_path=self.__dtd_path, + indent=self.__indent, + run_level=self.__run_level, + no_dtd=self.__no_dtd, + encoding=encode_obj.get_codepage(), + bug_handler=RtfInvalidCodeException, + ) + tags_obj.convert_to_tags() + output_obj = output.Output( + file=self.__temp_file, + orig_file=self.__file, + output_dir=self.__out_dir, + out_file=self.__out_file, + ) + output_obj.output() + os.remove(self.__temp_file) + return self.__exit_level + + def __bracket_match(self, file_name): + if self.__run_level > 2: + good_br, msg = self.__check_brack_obj.check_brackets() + if good_br: + pass + # sys.stderr.write( msg + ' in ' + file_name + "\n") + else: + msg = '%s in file %s' % (msg, file_name) + print(msg, file=sys.stderr) + + def __return_code(self, num): + if num is None: + return + if int(num) > self.__exit_level: + self.__exit_level = num + + def __make_temp_file(self,file): + """Make a temporary file to parse""" + write_file="rtf_write_file" + read_obj = file if hasattr(file, 'read') else open_for_read(file) + with open_for_write(write_file) as write_obj: + for line in read_obj: + write_obj.write(line) + return write_file diff --git a/ebook_converter/ebooks/rtf2xml/__init__.py b/ebook_converter/ebooks/rtf2xml/__init__.py new file mode 100644 index 0000000..a106fe9 --- /dev/null +++ b/ebook_converter/ebooks/rtf2xml/__init__.py @@ -0,0 +1,12 @@ +from __future__ import unicode_literals, absolute_import, print_function, division + +import io + + +def open_for_read(path): + return io.open(path, encoding='utf-8', errors='replace') + + +def open_for_write(path, append=False): + mode = 'a' if append else 'w' + return io.open(path, mode, encoding='utf-8', errors='replace', newline='') diff --git a/ebook_converter/ebooks/rtf2xml/add_brackets.py b/ebook_converter/ebooks/rtf2xml/add_brackets.py new file mode 100644 index 0000000..3f991d5 --- /dev/null +++ b/ebook_converter/ebooks/rtf2xml/add_brackets.py @@ -0,0 +1,232 @@ +from __future__ import unicode_literals, absolute_import, print_function, division +######################################################################### +# # +# # +# copyright 2002 Paul Henry Tremblay # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # +# General Public License for more details. # +# # +# # +# # +######################################################################### +import sys, os + +from calibre.ebooks.rtf2xml import copy, check_brackets +from calibre.ptempfile import better_mktemp +from polyglot.builtins import iteritems +from . import open_for_read, open_for_write + + +class AddBrackets: + """ + Add brackets for old RTF. + Logic: + When control words without their own brackets are encountered + and in the list of allowed words, this will add brackets + to facilitate the treatment of the file + """ + + def __init__(self, in_file, + bug_handler, + copy=None, + run_level=1, + ): + """ + Required: + 'file'--file to parse + Optional: + 'copy'-- whether to make a copy of result for debugging + 'temp_dir' --where to output temporary results (default is + directory from which the script is run.) + Returns: + nothing + """ + self.__file = in_file + self.__bug_handler = bug_handler + self.__copy = copy + self.__write_to = better_mktemp() + self.__run_level = run_level + self.__state_dict = { + 'before_body' : self.__before_body_func, + 'in_body' : self.__in_body_func, + 'after_control_word' : self.__after_control_word_func, + 'in_ignore' : self.__ignore_func, + } + self.__accept = [ + 'cw 0: + sys.stderr.write( + 'Sorry, but this files has a mix of old and new RTF.\n' + 'Some characteristics cannot be converted.\n') + os.remove(self.__write_to) diff --git a/ebook_converter/ebooks/rtf2xml/body_styles.py b/ebook_converter/ebooks/rtf2xml/body_styles.py new file mode 100644 index 0000000..ec78443 --- /dev/null +++ b/ebook_converter/ebooks/rtf2xml/body_styles.py @@ -0,0 +1,84 @@ +from __future__ import unicode_literals, absolute_import, print_function, division +######################################################################### +# # +# # +# copyright 2002 Paul Henry Tremblay # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # +# General Public License for more details. # +# # +# # +######################################################################### +import os +from calibre.ebooks.rtf2xml import copy +from calibre.ptempfile import better_mktemp +from . import open_for_read, open_for_write + +""" +Simply write the list of strings after style table +""" + + +class BodyStyles: + """ + Insert table data for tables. + Logic: + """ + + def __init__(self, + in_file, + list_of_styles, + bug_handler, + copy=None, + run_level=1,): + """ + Required: + 'file'--file to parse + 'table_data' -- a dictionary for each table. + Optional: + 'copy'-- whether to make a copy of result for debugging + 'temp_dir' --where to output temporary results (default is + directory from which the script is run.) + Returns: + nothing + """ + self.__file = in_file + self.__bug_handler = bug_handler + self.__copy = copy + self.__list_of_styles = list_of_styles + self.__run_level = run_level + self.__write_to = better_mktemp() + # self.__write_to = 'table_info.data' + + def insert_info(self): + """ + """ + read_obj = open_for_read(self.__file) + self.__write_obj = open_for_write(self.__write_to) + line_to_read = 1 + while line_to_read: + line_to_read = read_obj.readline() + line = line_to_read + if line == 'mi 0: + self.__write_obj.write('mi 3: + msg = 'Not enough data for each table\n' + raise self.__bug_handler(msg) + # why was this line even here? + # self.__write_obj.write('mi bt + 'bdr-li-wid' : 'line-width', + 'bdr-sp-wid' : 'padding', + 'bdr-color_' : 'color', + } + self.__border_style_dict = { + 'bdr-single' : 'single', + 'bdr-doubtb' : 'double-thickness-border', + 'bdr-shadow' : 'shadowed-border', + 'bdr-double' : 'double-border', + 'bdr-dotted' : 'dotted-border', + 'bdr-dashed' : 'dashed', + 'bdr-hair__' : 'hairline', + 'bdr-inset_' : 'inset', + 'bdr-das-sm' : 'dash-small', + 'bdr-dot-sm' : 'dot-dash', + 'bdr-dot-do' : 'dot-dot-dash', + 'bdr-outset' : 'outset', + 'bdr-trippl' : 'tripple', + 'bdr-thsm__' : 'thick-thin-small', + 'bdr-htsm__' : 'thin-thick-small', + 'bdr-hthsm_' : 'thin-thick-thin-small', + 'bdr-thm___' : 'thick-thin-medium', + 'bdr-htm___' : 'thin-thick-medium', + 'bdr-hthm__' : 'thin-thick-thin-medium', + 'bdr-thl___' : 'thick-thin-large', + 'bdr-hthl__' : 'thin-thick-thin-large', + 'bdr-wavy__' : 'wavy', + 'bdr-d-wav_' : 'double-wavy', + 'bdr-strip_' : 'striped', + 'bdr-embos_' : 'emboss', + 'bdr-engra_' : 'engrave', + 'bdr-frame_' : 'frame', + } + + def parse_border(self, line): + """ + Requires: + line -- line with border definition in it + Returns: + ? + Logic: + """ + border_dict = {} + border_style_dict = {} + border_style_list = [] + border_type = self.__border_dict.get(line[6:16]) + if not border_type: + sys.stderr.write( + 'module is border_parse.py\n' + 'function is parse_border\n' + 'token does not have a dictionary value\n' + 'token is "%s"' % line + ) + return border_dict + att_line = line[20:-1] + atts = att_line.split('|') + # cw +NON-BREAKING HYPEHN:_:8290:‑ +LEFT DOUBLE QUOTATION MARK:ldblquote:8220:“ +RIGHT DOUBLE QUOTATION MARK:rdblquote:8221:” +LEFT SINGLE QUOTATION MARK:lquote:8216:‘ +RIGHT SINGLE QUOTATION MARK:rquote:8217:’ +EN DASH:endash:8211:– +EM DASH:emdash:8212:— +MIDDLE DOT:bullet:183:· +:tab:9: +NO-BREAK SPACE:~:160:  +SOFT-HYPHEN:-:173:­ + + +REGISTERED SIGN:ldblquote:174:® +COPYRIGHT SIGN:rdblquote:169:© +N-ARY PRODUCT:rquote:8719:∏ +TRADE MARK SIGN:lquote:8482:™ +ANGLE:emdash:8736:∠ +WHITE DOWN-POINTING TRIANGLE:endash:9661:▽ +INFINITY:bullet:8734:∞ +:tab:9: +NO-BREAK SPACE:~:160:  +NON-BREAKING HYPEHN:_:8209:‑ + + +DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT NINE:10130:ldblquote:➒ +DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT TEN:rdblquote:10131:➓ +HEAVY WIDE-HEADED RIGHTWARDS ARROW:lquote:10132:➔ +RIGHTWARDS ARROW:rquote:8594:→ +DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SEVEN:endash:10128:➐ +DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT EIGHT:emdash:10129:➑ +ROTATED HEAVY BLACK HEART BULLET:bullet:10085:❥ +DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ONE:~:10122:➊ +WRITING HAND:_:9997:✍ + + +:tab:9: +PROPOSE "HEDERA UPPER RIGHT":ldblquote:none: +PROPOSE "HEDERA LOWER LEFT":rdblquote:none: +PROPOSE "HEDERA LOWER RIGHT":lquote:none: +ERASE TO THE LEFT:rquote:9003:⌫ +AMPERSAND:endash:38:& +PROPOSE "HEDERA UPPER LEFT":emdash:none: +SUN:bullet:9737:☉ +PROPOSE "NOTCHED RIGHTWARDS DOUBLE ARROW WITH TIP DOWNWARDS":~:none: +PROPOSE "MAIL FLAG UP":_:none: + + +NULL (NUL):'00:0:� +START OF HEADING (SOH):'01:1: +START OF TEXT (STX):'02:2: +END OF TEXT (ETX):'03:3: +END OF TRANSMISSION (EOT):'04:4: +ENQUIRY (ENQ):'05:5: +ACKNOWLEDGE (ACK):'06:6: +BELL (BEL):'07:7: +BACKSPACE (BS):'08:8: +LINE TABULATION (VT):'0B:11: +FORM FEED (FF):'0C:12: +SHIFT OUT (SO):'0E:14: +SHIFT IN (SI):'0F:15: +DATALINK ESCAPE (DLE):'10:16: +DEVICE CONTROL ONE (DC1):'11:17: +DEVICE CONTROL TWO (DC2):'12:18: +DEVICE CONTROL THREE (DC3):'13:19: +DEVICE CONTROL FOUR (DC4):'14:20: +NEGATIVE ACKNOWLEDGE (NAK):'15:21: +SYNCHRONOUS IDLE (SYN):'16:22: +END OF TRANSMISSION BLOCK (ETB):'17:23: +CANCEL (CAN):'18:24: +END OF MEDIUM (EM):'19:25: +SUBSTITUTE (SUB):'1A:26: +ESCAPE (ESC):'1B:27: +FILE SEPARATOR (IS4):'1C:28: +GROUP SEPARATOR (IS3):'1D:29: +RECORD SEPARATOR (IS2):'1E:30: +UNIT SEPARATOR (IS1):'1F:31: + + +CHARACTER TABULATION (HT):'09:9: +LINE FEED (LF):'0A:10: +CARRIAGE RETURN (CR):'0D:13: +SPACE:'20:32: +EXCLAMATION MARK:'21:33:! +QUOTATION MARK:'22:34:" +NUMBER SIGN:'23:35:# +DOLLAR SIGN:'24:36:$ +PERCENT SIGN:'25:37:% +AMPERSAND:'26:38:& +APOSTROPHE:'27:39:' +LEFT PARENTHESIS:'28:40:( +RIGHT PARENTHESIS:'29:41:) +ASTERISK:'2A:42:* +PLUS SIGN:'2B:43:+ +COMMA:'2C:44:, +HYPHEN-MINUS:'2D:45:- +FULL STOP:'2E:46:. +SOLIDUS:'2F:47:/ +DIGIT ZERO:'30:48:0 +DIGIT ONE:'31:49:1 +DIGIT TWO:'32:50:2 +DIGIT THREE:'33:51:3 +DIGIT FOUR:'34:52:4 +DIGIT FIVE:'35:53:5 +DIGIT SIX:'36:54:6 +DIGIT SEVEN:'37:55:7 +DIGIT EIGHT:'38:56:8 +DIGIT NINE:'39:57:9 +COLON:'3A:58:\\colon +SEMICOLON:'3B:59:; +LESS-THAN SIGN:'3C:60:< +EQUALS SIGN:'3D:61:= +GREATER-THAN SIGN:'3E:62:> +QUESTION MARK:'3F:63:? +COMMERCIAL AT:'40:64:@ +LATIN CAPITAL LETTER A:'41:65:A +LATIN CAPITAL LETTER B:'42:66:B +LATIN CAPITAL LETTER C:'43:67:C +LATIN CAPITAL LETTER D:'44:68:D +LATIN CAPITAL LETTER E:'45:69:E +LATIN CAPITAL LETTER F:'46:70:F +LATIN CAPITAL LETTER G:'47:71:G +LATIN CAPITAL LETTER H:'48:72:H +LATIN CAPITAL LETTER I:'49:73:I +LATIN CAPITAL LETTER J:'4A:74:J +LATIN CAPITAL LETTER K:'4B:75:K +LATIN CAPITAL LETTER L:'4C:76:L +LATIN CAPITAL LETTER M:'4D:77:M +LATIN CAPITAL LETTER N:'4E:78:N +LATIN CAPITAL LETTER O:'4F:79:O +LATIN CAPITAL LETTER P:'50:80:P +LATIN CAPITAL LETTER Q:'51:81:Q +LATIN CAPITAL LETTER R:'52:82:R +LATIN CAPITAL LETTER S:'53:83:S +LATIN CAPITAL LETTER T:'54:84:T +LATIN CAPITAL LETTER U:'55:85:U +LATIN CAPITAL LETTER V:'56:86:V +LATIN CAPITAL LETTER W:'57:87:W +LATIN CAPITAL LETTER X:'58:88:X +LATIN CAPITAL LETTER Y:'59:89:Y +LATIN CAPITAL LETTER Z:'5A:90:Z +LEFT SQUARE BRACKET:'5B:91:[ +REVERSE SOLIDUS:'5C:92:\ +RIGHT SQUARE BRACKET:'5D:93:] +CIRCUMFLEX ACCENT:'5E:94:^ +LOW LINE:'5F:95:_ +GRAVE ACCENT:'60:96:` +LATIN SMALL LETTER A:'61:97:a +LATIN SMALL LETTER B:'62:98:b +LATIN SMALL LETTER C:'63:99:c +LATIN SMALL LETTER D:'64:100:d +LATIN SMALL LETTER E:'65:101:e +LATIN SMALL LETTER F:'66:102:f +LATIN SMALL LETTER G:'67:103:g +LATIN SMALL LETTER H:'68:104:h +LATIN SMALL LETTER I:'69:105:i +LATIN SMALL LETTER J:'6A:106:j +LATIN SMALL LETTER K:'6B:107:k +LATIN SMALL LETTER L:'6C:108:l +LATIN SMALL LETTER M:'6D:109:m +LATIN SMALL LETTER N:'6E:110:n +LATIN SMALL LETTER O:'6F:111:o +LATIN SMALL LETTER P:'70:112:p +LATIN SMALL LETTER Q:'71:113:q +LATIN SMALL LETTER R:'72:114:r +LATIN SMALL LETTER S:'73:115:s +LATIN SMALL LETTER T:'74:116:t +LATIN SMALL LETTER U:'75:117:u +LATIN SMALL LETTER V:'76:118:v +LATIN SMALL LETTER W:'77:119:w +LATIN SMALL LETTER X:'78:120:x +LATIN SMALL LETTER Y:'79:121:y +LATIN SMALL LETTER Z:'7A:122:z +LEFT CURLY BRACKET:'7B:123:{ +VERTICAL LINE:'7C:124:| +RIGHT CURLY BRACKET:'7D:125:} +TILDE:'7E:126:~ +DELETE (DEL):'7F:127: + + +NULL (NUL):'00:0:� +START OF HEADING (SOH):'01:1: +START OF TEXT (STX):'02:2: +END OF TEXT (ETX):'03:3: +END OF TRANSMISSION (EOT):'04:4: +ENQUIRY (ENQ):'05:5: +ACKNOWLEDGE (ACK):'06:6: +BELL (BEL):'07:7: +BACKSPACE (BS):'08:8: +CHARACTER TABULATION (HT):'09:9: +LINE FEED (LF):'0A:10: +LINE TABULATION (VT):'0B:11: +FORM FEED (FF):'0C:12: +CARRIAGE RETURN (CR):'0D:13: +SHIFT OUT (SO):'0E:14: +SHIFT IN (SI):'0F:15: +DATALINK ESCAPE (DLE):'10:16: +DEVICE CONTROL ONE (DC1):'11:17: +DEVICE CONTROL TWO (DC2):'12:18: +DEVICE CONTROL THREE (DC3):'13:19: +DEVICE CONTROL FOUR (DC4):'14:20: +NEGATIVE ACKNOWLEDGE (NAK):'15:21: +SYNCHRONOUS IDLE (SYN):'16:22: +END OF TRANSMISSION BLOCK (ETB):'17:23: +CANCEL (CAN):'18:24: +END OF MEDIUM (EM):'19:25: +SUBSTITUTE (SUB):'1A:26: +ESCAPE (ESC):'1B:27: +FILE SEPARATOR (IS4):'1C:28: +GROUP SEPARATOR (IS3):'1D:29: +RECORD SEPARATOR (IS2):'1E:30: +UNIT SEPARATOR (IS1):'1F:31: +SPACE:'20:32: +EXCLAMATION MARK:'21:33:! +QUOTATION MARK:'22:34:" +NUMBER SIGN:'23:35:# +DOLLAR SIGN:'24:36:$ +PERCENT SIGN:'25:37:% +AMPERSAND:'26:38:& +APOSTROPHE:'27:39:' +LEFT PARENTHESIS:'28:40:( +RIGHT PARENTHESIS:'29:41:) +ASTERISK:'2A:42:* +PLUS SIGN:'2B:43:+ +COMMA:'2C:44:, +HYPHEN-MINUS:'2D:45:- +FULL STOP:'2E:46:. +SOLIDUS:'2F:47:/ +DIGIT ZERO:'30:48:0 +DIGIT ONE:'31:49:1 +DIGIT TWO:'32:50:2 +DIGIT THREE:'33:51:3 +DIGIT FOUR:'34:52:4 +DIGIT FIVE:'35:53:5 +DIGIT SIX:'36:54:6 +DIGIT SEVEN:'37:55:7 +DIGIT EIGHT:'38:56:8 +DIGIT NINE:'39:57:9 +COLON:'3A:58:: +SEMICOLON:'3B:59:; +LESS-THAN SIGN:'3C:60:< +EQUALS SIGN:'3D:61:= +GREATER-THAN SIGN:'3E:62:> +QUESTION MARK:'3F:63:? +COMMERCIAL AT:'40:64:@ +LATIN CAPITAL LETTER A:'41:65:A +LATIN CAPITAL LETTER B:'42:66:B +LATIN CAPITAL LETTER C:'43:67:C +LATIN CAPITAL LETTER D:'44:68:D +LATIN CAPITAL LETTER E:'45:69:E +LATIN CAPITAL LETTER F:'46:70:F +LATIN CAPITAL LETTER G:'47:71:G +LATIN CAPITAL LETTER H:'48:72:H +LATIN CAPITAL LETTER I:'49:73:I +LATIN CAPITAL LETTER J:'4A:74:J +LATIN CAPITAL LETTER K:'4B:75:K +LATIN CAPITAL LETTER L:'4C:76:L +LATIN CAPITAL LETTER M:'4D:77:M +LATIN CAPITAL LETTER N:'4E:78:N +LATIN CAPITAL LETTER O:'4F:79:O +LATIN CAPITAL LETTER P:'50:80:P +LATIN CAPITAL LETTER Q:'51:81:Q +LATIN CAPITAL LETTER R:'52:82:R +LATIN CAPITAL LETTER S:'53:83:S +LATIN CAPITAL LETTER T:'54:84:T +LATIN CAPITAL LETTER U:'55:85:U +LATIN CAPITAL LETTER V:'56:86:V +LATIN CAPITAL LETTER W:'57:87:W +LATIN CAPITAL LETTER X:'58:88:X +LATIN CAPITAL LETTER Y:'59:89:Y +LATIN CAPITAL LETTER Z:'5A:90:Z +LEFT SQUARE BRACKET:'5B:91:[ +REVERSE SOLIDUS:'5C:92:\ +RIGHT SQUARE BRACKET:'5D:93:] +CIRCUMFLEX ACCENT:'5E:94:^ +LOW LINE:'5F:95:_ +GRAVE ACCENT:'60:96:` +LATIN SMALL LETTER A:'61:97:a +LATIN SMALL LETTER B:'62:98:b +LATIN SMALL LETTER C:'63:99:c +LATIN SMALL LETTER D:'64:100:d +LATIN SMALL LETTER E:'65:101:e +LATIN SMALL LETTER F:'66:102:f +LATIN SMALL LETTER G:'67:103:g +LATIN SMALL LETTER H:'68:104:h +LATIN SMALL LETTER I:'69:105:i +LATIN SMALL LETTER J:'6A:106:j +LATIN SMALL LETTER K:'6B:107:k +LATIN SMALL LETTER L:'6C:108:l +LATIN SMALL LETTER M:'6D:109:m +LATIN SMALL LETTER N:'6E:110:n +LATIN SMALL LETTER O:'6F:111:o +LATIN SMALL LETTER P:'70:112:p +LATIN SMALL LETTER Q:'71:113:q +LATIN SMALL LETTER R:'72:114:r +LATIN SMALL LETTER S:'73:115:s +LATIN SMALL LETTER T:'74:116:t +LATIN SMALL LETTER U:'75:117:u +LATIN SMALL LETTER V:'76:118:v +LATIN SMALL LETTER W:'77:119:w +LATIN SMALL LETTER X:'78:120:x +LATIN SMALL LETTER Y:'79:121:y +LATIN SMALL LETTER Z:'7A:122:z + + +DBCS LEAD BYTE:'81:129: +DBCS LEAD BYTE:'82:130: +DBCS LEAD BYTE:'83:131: +DBCS LEAD BYTE:'84:132: +DBCS LEAD BYTE:'85:133: +DBCS LEAD BYTE:'86:134: +DBCS LEAD BYTE:'87:135: +DBCS LEAD BYTE:'88:136: +DBCS LEAD BYTE:'89:137: +DBCS LEAD BYTE:'8A:138: +DBCS LEAD BYTE:'8B:139: +DBCS LEAD BYTE:'8C:140: +DBCS LEAD BYTE:'8D:141: +DBCS LEAD BYTE:'8E:142: +DBCS LEAD BYTE:'8F:143: +DBCS LEAD BYTE:'90:144: +DBCS LEAD BYTE:'91:145: +DBCS LEAD BYTE:'92:146: +DBCS LEAD BYTE:'93:147: +DBCS LEAD BYTE:'94:148: +DBCS LEAD BYTE:'95:149: +DBCS LEAD BYTE:'96:150: +DBCS LEAD BYTE:'97:151: +DBCS LEAD BYTE:'98:152: +DBCS LEAD BYTE:'99:153: +DBCS LEAD BYTE:'9A:154: +DBCS LEAD BYTE:'9B:155: +DBCS LEAD BYTE:'9C:156: +DBCS LEAD BYTE:'9D:157: +DBCS LEAD BYTE:'9E:158: +DBCS LEAD BYTE:'9F:159: +DBCS LEAD BYTE:'A0:160: +DBCS LEAD BYTE:'A1:161: +DBCS LEAD BYTE:'A2:162: +DBCS LEAD BYTE:'A3:163: +DBCS LEAD BYTE:'A4:164: +DBCS LEAD BYTE:'A5:165: +DBCS LEAD BYTE:'A6:166: +DBCS LEAD BYTE:'A7:167: +DBCS LEAD BYTE:'A8:168: +DBCS LEAD BYTE:'A9:169: +DBCS LEAD BYTE:'AA:170: +DBCS LEAD BYTE:'AB:171: +DBCS LEAD BYTE:'AC:172: +DBCS LEAD BYTE:'AD:173: +DBCS LEAD BYTE:'AE:174: +DBCS LEAD BYTE:'AF:175: +DBCS LEAD BYTE:'B0:176: +DBCS LEAD BYTE:'B1:177: +DBCS LEAD BYTE:'B2:178: +DBCS LEAD BYTE:'B3:179: +DBCS LEAD BYTE:'B4:180: +DBCS LEAD BYTE:'B5:181: +DBCS LEAD BYTE:'B6:182: +DBCS LEAD BYTE:'B7:183: +DBCS LEAD BYTE:'B8:184: +DBCS LEAD BYTE:'B9:185: +DBCS LEAD BYTE:'BA:186: +DBCS LEAD BYTE:'BB:187: +DBCS LEAD BYTE:'BC:188: +DBCS LEAD BYTE:'BD:189: +DBCS LEAD BYTE:'BE:190: +DBCS LEAD BYTE:'BF:191: +DBCS LEAD BYTE:'C0:192: +DBCS LEAD BYTE:'C1:193: +DBCS LEAD BYTE:'C2:194: +DBCS LEAD BYTE:'C3:195: +DBCS LEAD BYTE:'C4:196: +DBCS LEAD BYTE:'C5:197: +DBCS LEAD BYTE:'C6:198: +DBCS LEAD BYTE:'C7:199: +DBCS LEAD BYTE:'C8:200: +DBCS LEAD BYTE:'C9:201: +DBCS LEAD BYTE:'CA:202: +DBCS LEAD BYTE:'CB:203: +DBCS LEAD BYTE:'CC:204: +DBCS LEAD BYTE:'CD:205: +DBCS LEAD BYTE:'CE:206: +DBCS LEAD BYTE:'CF:207: +DBCS LEAD BYTE:'D0:208: +DBCS LEAD BYTE:'D1:209: +DBCS LEAD BYTE:'D2:210: +DBCS LEAD BYTE:'D3:211: +DBCS LEAD BYTE:'D4:212: +DBCS LEAD BYTE:'D5:213: +DBCS LEAD BYTE:'D6:214: +DBCS LEAD BYTE:'D7:215: +DBCS LEAD BYTE:'D8:216: +DBCS LEAD BYTE:'D9:217: +DBCS LEAD BYTE:'DA:218: +DBCS LEAD BYTE:'DB:219: +DBCS LEAD BYTE:'DC:220: +DBCS LEAD BYTE:'DD:221: +DBCS LEAD BYTE:'DE:222: +DBCS LEAD BYTE:'DF:223: +DBCS LEAD BYTE:'E0:224: +DBCS LEAD BYTE:'E1:225: +DBCS LEAD BYTE:'E2:226: +DBCS LEAD BYTE:'E3:227: +DBCS LEAD BYTE:'E4:228: +DBCS LEAD BYTE:'E5:229: +DBCS LEAD BYTE:'E6:230: +DBCS LEAD BYTE:'E7:231: +DBCS LEAD BYTE:'E8:232: +DBCS LEAD BYTE:'E9:233: +DBCS LEAD BYTE:'EA:234: +DBCS LEAD BYTE:'EB:235: +DBCS LEAD BYTE:'EC:236: +DBCS LEAD BYTE:'ED:237: +DBCS LEAD BYTE:'EE:238: +DBCS LEAD BYTE:'EF:239: +DBCS LEAD BYTE:'F0:240: +DBCS LEAD BYTE:'F1:241: +DBCS LEAD BYTE:'F2:242: +DBCS LEAD BYTE:'F3:243: +DBCS LEAD BYTE:'F4:244: +DBCS LEAD BYTE:'F5:245: +DBCS LEAD BYTE:'F6:246: +DBCS LEAD BYTE:'F7:247: +DBCS LEAD BYTE:'F8:248: +DBCS LEAD BYTE:'F9:249: +DBCS LEAD BYTE:'FA:250: +DBCS LEAD BYTE:'FB:251: +DBCS LEAD BYTE:'FC:252: +DBCS LEAD BYTE:'FD:253: +DBCS LEAD BYTE:'FE:254: +IDEOGRAPHIC SPACE:'A140:41280:  +FULLWIDTH COMMA:'A141:41281:, +IDEOGRAPHIC COMMA:'A142:41282:、 +IDEOGRAPHIC FULL STOP:'A143:41283:。 +FULLWIDTH FULL STOP:'A144:41284:. +HYPHENATION POINT:'A145:41285:‧ +FULLWIDTH SEMICOLON:'A146:41286:; +FULLWIDTH COLON:'A147:41287:: +FULLWIDTH QUESTION MARK:'A148:41288:? +FULLWIDTH EXCLAMATION MARK:'A149:41289:! +PRESENTATION FORM FOR VERTICAL TWO DOT LEADER:'A14A:41290:︰ +HORIZONTAL ELLIPSIS:'A14B:41291:… +TWO DOT LEADER:'A14C:41292:‥ +SMALL COMMA:'A14D:41293:﹐ +SMALL IDEOGRAPHIC COMMA:'A14E:41294:﹑ +SMALL FULL STOP:'A14F:41295:﹒ +MIDDLE DOT:'A150:41296:· +SMALL SEMICOLON:'A151:41297:﹔ +SMALL COLON:'A152:41298:﹕ +SMALL QUESTION MARK:'A153:41299:﹖ +SMALL EXCLAMATION MARK:'A154:41300:﹗ +FULLWIDTH VERTICAL LINE:'A155:41301:| +EN DASH:'A156:41302:– +PRESENTATION FORM FOR VERTICAL EM DASH:'A157:41303:︱ +EM DASH:'A158:41304:— +PRESENTATION FORM FOR VERTICAL LOW LINE:'A159:41305:︳ +BOX DRAWINGS LIGHT LEFT:'A15A:41306:╴ +PRESENTATION FORM FOR VERTICAL WAVY LOW LINE:'A15B:41307:︴ +WAVY LOW LINE:'A15C:41308:﹏ +FULLWIDTH LEFT PARENTHESIS:'A15D:41309:( +FULLWIDTH RIGHT PARENTHESIS:'A15E:41310:) +PRESENTATION FORM FOR VERTICAL LEFT PARENTHESIS:'A15F:41311:︵ +PRESENTATION FORM FOR VERTICAL RIGHT PARENTHESIS:'A160:41312:︶ +FULLWIDTH LEFT CURLY BRACKET:'A161:41313:{ +FULLWIDTH RIGHT CURLY BRACKET:'A162:41314:} +PRESENTATION FORM FOR VERTICAL LEFT CURLY BRACKET:'A163:41315:︷ +PRESENTATION FORM FOR VERTICAL RIGHT CURLY BRACKET:'A164:41316:︸ +LEFT TORTOISE SHELL BRACKET:'A165:41317:〔 +RIGHT TORTOISE SHELL BRACKET:'A166:41318:〕 +PRESENTATION FORM FOR VERTICAL LEFT TORTOISE SHELL BRACKET:'A167:41319:︹ +PRESENTATION FORM FOR VERTICAL RIGHT TORTOISE SHELL BRACKET:'A168:41320:︺ +LEFT BLACK LENTICULAR BRACKET:'A169:41321:【 +RIGHT BLACK LENTICULAR BRACKET:'A16A:41322:】 +PRESENTATION FORM FOR VERTICAL LEFT BLACK LENTICULAR BRACKET:'A16B:41323:︻ +PRESENTATION FORM FOR VERTICAL RIGHT BLACK LENTICULAR BRACKET:'A16C:41324:︼ +LEFT DOUBLE ANGLE BRACKET:'A16D:41325:《 +RIGHT DOUBLE ANGLE BRACKET:'A16E:41326:》 +PRESENTATION FORM FOR VERTICAL LEFT DOUBLE ANGLE BRACKET:'A16F:41327:︽ +PRESENTATION FORM FOR VERTICAL RIGHT DOUBLE ANGLE BRACKET:'A170:41328:︾ +LEFT ANGLE BRACKET:'A171:41329:〈 +RIGHT ANGLE BRACKET:'A172:41330:〉 +PRESENTATION FORM FOR VERTICAL LEFT ANGLE BRACKET:'A173:41331:︿ +PRESENTATION FORM FOR VERTICAL RIGHT ANGLE BRACKET:'A174:41332:﹀ +LEFT CORNER BRACKET:'A175:41333:「 +RIGHT CORNER BRACKET:'A176:41334:」 +PRESENTATION FORM FOR VERTICAL LEFT CORNER BRACKET:'A177:41335:﹁ +PRESENTATION FORM FOR VERTICAL RIGHT CORNER BRACKET:'A178:41336:﹂ +LEFT WHITE CORNER BRACKET:'A179:41337:『 +RIGHT WHITE CORNER BRACKET:'A17A:41338:』 +PRESENTATION FORM FOR VERTICAL LEFT WHITE CORNER BRACKET:'A17B:41339:﹃ +PRESENTATION FORM FOR VERTICAL RIGHT WHITE CORNER BRACKET:'A17C:41340:﹄ +SMALL LEFT PARENTHESIS:'A17D:41341:﹙ +SMALL RIGHT PARENTHESIS:'A17E:41342:﹚ +SMALL LEFT CURLY BRACKET:'A1A1:41377:﹛ +SMALL RIGHT CURLY BRACKET:'A1A2:41378:﹜ +SMALL LEFT TORTOISE SHELL BRACKET:'A1A3:41379:﹝ +SMALL RIGHT TORTOISE SHELL BRACKET:'A1A4:41380:﹞ +LEFT SINGLE QUOTATION MARK:'A1A5:41381:‘ +RIGHT SINGLE QUOTATION MARK:'A1A6:41382:’ +LEFT DOUBLE QUOTATION MARK:'A1A7:41383:“ +RIGHT DOUBLE QUOTATION MARK:'A1A8:41384:” +REVERSED DOUBLE PRIME QUOTATION MARK:'A1A9:41385:〝 +DOUBLE PRIME QUOTATION MARK:'A1AA:41386:〞 +REVERSED PRIME:'A1AB:41387:‵ +PRIME:'A1AC:41388:′ +FULLWIDTH NUMBER SIGN:'A1AD:41389:# +FULLWIDTH AMPERSAND:'A1AE:41390:& +FULLWIDTH ASTERISK:'A1AF:41391:* +REFERENCE MARK:'A1B0:41392:※ +SECTION SIGN:'A1B1:41393:§ +DITTO MARK:'A1B2:41394:〃 +WHITE CIRCLE:'A1B3:41395:○ +BLACK CIRCLE:'A1B4:41396:● +WHITE UP-POINTING TRIANGLE:'A1B5:41397:△ +BLACK UP-POINTING TRIANGLE:'A1B6:41398:▲ +BULLSEYE:'A1B7:41399:◎ +WHITE STAR:'A1B8:41400:☆ +BLACK STAR:'A1B9:41401:★ +WHITE DIAMOND:'A1BA:41402:◇ +BLACK DIAMOND:'A1BB:41403:◆ +WHITE SQUARE:'A1BC:41404:□ +BLACK SQUARE:'A1BD:41405:■ +WHITE DOWN-POINTING TRIANGLE:'A1BE:41406:▽ +BLACK DOWN-POINTING TRIANGLE:'A1BF:41407:▼ +CIRCLED IDEOGRAPH CORRECT:'A1C0:41408:㊣ +CARE OF:'A1C1:41409:℅ +MACRON:'A1C2:41410:¯ +FULLWIDTH MACRON:'A1C3:41411: ̄ +FULLWIDTH LOW LINE:'A1C4:41412:_ +MODIFIER LETTER LOW MACRON:'A1C5:41413:ˍ +DASHED OVERLINE:'A1C6:41414:﹉ +CENTRELINE OVERLINE:'A1C7:41415:﹊ +DASHED LOW LINE:'A1C8:41416:﹍ +CENTRELINE LOW LINE:'A1C9:41417:﹎ +WAVY OVERLINE:'A1CA:41418:﹋ +DOUBLE WAVY OVERLINE:'A1CB:41419:﹌ +SMALL NUMBER SIGN:'A1CC:41420:﹟ +SMALL AMPERSAND:'A1CD:41421:﹠ +SMALL ASTERISK:'A1CE:41422:﹡ +FULLWIDTH PLUS SIGN:'A1CF:41423:+ +FULLWIDTH HYPHEN-MINUS:'A1D0:41424:- +MULTIPLICATION SIGN:'A1D1:41425:× +DIVISION SIGN:'A1D2:41426:÷ +PLUS-MINUS SIGN:'A1D3:41427:± +SQUARE ROOT:'A1D4:41428:√ +FULLWIDTH LESS-THAN SIGN:'A1D5:41429:< +FULLWIDTH GREATER-THAN SIGN:'A1D6:41430:> +FULLWIDTH EQUALS SIGN:'A1D7:41431:= +LESS-THAN OVER EQUAL TO:'A1D8:41432:≦ +GREATER-THAN OVER EQUAL TO:'A1D9:41433:≧ +NOT EQUAL TO:'A1DA:41434:≠ +INFINITY:'A1DB:41435:∞ +APPROXIMATELY EQUAL TO OR THE IMAGE OF:'A1DC:41436:≒ +IDENTICAL TO:'A1DD:41437:≡ +SMALL PLUS SIGN:'A1DE:41438:﹢ +SMALL HYPHEN-MINUS:'A1DF:41439:﹣ +SMALL LESS-THAN SIGN:'A1E0:41440:﹤ +SMALL GREATER-THAN SIGN:'A1E1:41441:﹥ +SMALL EQUALS SIGN:'A1E2:41442:﹦ +FULLWIDTH TILDE:'A1E3:41443:~ +INTERSECTION:'A1E4:41444:∩ +UNION:'A1E5:41445:∪ +UP TACK:'A1E6:41446:⊥ +ANGLE:'A1E7:41447:∠ +RIGHT ANGLE:'A1E8:41448:∟ +RIGHT TRIANGLE:'A1E9:41449:⊿ +SQUARE LOG:'A1EA:41450:㏒ +SQUARE LN:'A1EB:41451:㏑ +INTEGRAL:'A1EC:41452:∫ +CONTOUR INTEGRAL:'A1ED:41453:∮ +BECAUSE:'A1EE:41454:∵ +THEREFORE:'A1EF:41455:∴ +FEMALE SIGN:'A1F0:41456:♀ +MALE SIGN:'A1F1:41457:♂ +CIRCLED PLUS:'A1F2:41458:⊕ +CIRCLED DOT OPERATOR:'A1F3:41459:⊙ +UPWARDS ARROW:'A1F4:41460:↑ +DOWNWARDS ARROW:'A1F5:41461:↓ +LEFTWARDS ARROW:'A1F6:41462:← +RIGHTWARDS ARROW:'A1F7:41463:→ +NORTH WEST ARROW:'A1F8:41464:↖ +NORTH EAST ARROW:'A1F9:41465:↗ +SOUTH WEST ARROW:'A1FA:41466:↙ +SOUTH EAST ARROW:'A1FB:41467:↘ +PARALLEL TO:'A1FC:41468:∥ +DIVIDES:'A1FD:41469:∣ +FULLWIDTH SOLIDUS:'A1FE:41470:/ +FULLWIDTH REVERSE SOLIDUS:'A240:41536:\ +DIVISION SLASH:'A241:41537:∕ +SMALL REVERSE SOLIDUS:'A242:41538:﹨ +FULLWIDTH DOLLAR SIGN:'A243:41539:$ +FULLWIDTH YEN SIGN:'A244:41540:¥ +POSTAL MARK:'A245:41541:〒 +FULLWIDTH CENT SIGN:'A246:41542:¢ +FULLWIDTH POUND SIGN:'A247:41543:£ +FULLWIDTH PERCENT SIGN:'A248:41544:% +FULLWIDTH COMMERCIAL AT:'A249:41545:@ +DEGREE CELSIUS:'A24A:41546:℃ +DEGREE FAHRENHEIT:'A24B:41547:℉ +SMALL DOLLAR SIGN:'A24C:41548:﹩ +SMALL PERCENT SIGN:'A24D:41549:﹪ +SMALL COMMERCIAL AT:'A24E:41550:﹫ +SQUARE MIL:'A24F:41551:㏕ +SQUARE MM:'A250:41552:㎜ +SQUARE CM:'A251:41553:㎝ +SQUARE KM:'A252:41554:㎞ +SQUARE KM CAPITAL:'A253:41555:㏎ +SQUARE M SQUARED:'A254:41556:㎡ +SQUARE MG:'A255:41557:㎎ +SQUARE KG:'A256:41558:㎏ +SQUARE CC:'A257:41559:㏄ +DEGREE SIGN:'A258:41560:° +CJK UNIFIED IDEOGRAPH:'A259:41561:兙 +CJK UNIFIED IDEOGRAPH:'A25A:41562:兛 +CJK UNIFIED IDEOGRAPH:'A25B:41563:兞 +CJK UNIFIED IDEOGRAPH:'A25C:41564:兝 +CJK UNIFIED IDEOGRAPH:'A25D:41565:兡 +CJK UNIFIED IDEOGRAPH:'A25E:41566:兣 +CJK UNIFIED IDEOGRAPH:'A25F:41567:嗧 +CJK UNIFIED IDEOGRAPH:'A260:41568:瓩 +CJK UNIFIED IDEOGRAPH:'A261:41569:糎 +LOWER ONE EIGHTH BLOCK:'A262:41570:▁ +LOWER ONE QUARTER BLOCK:'A263:41571:▂ +LOWER THREE EIGHTHS BLOCK:'A264:41572:▃ +LOWER HALF BLOCK:'A265:41573:▄ +LOWER FIVE EIGHTHS BLOCK:'A266:41574:▅ +LOWER THREE QUARTERS BLOCK:'A267:41575:▆ +LOWER SEVEN EIGHTHS BLOCK:'A268:41576:▇ +FULL BLOCK:'A269:41577:█ +LEFT ONE EIGHTH BLOCK:'A26A:41578:▏ +LEFT ONE QUARTER BLOCK:'A26B:41579:▎ +LEFT THREE EIGHTHS BLOCK:'A26C:41580:▍ +LEFT HALF BLOCK:'A26D:41581:▌ +LEFT FIVE EIGHTHS BLOCK:'A26E:41582:▋ +LEFT THREE QUARTERS BLOCK:'A26F:41583:▊ +LEFT SEVEN EIGHTHS BLOCK:'A270:41584:▉ +BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL:'A271:41585:┼ +BOX DRAWINGS LIGHT UP AND HORIZONTAL:'A272:41586:┴ +BOX DRAWINGS LIGHT DOWN AND HORIZONTAL:'A273:41587:┬ +BOX DRAWINGS LIGHT VERTICAL AND LEFT:'A274:41588:┤ +BOX DRAWINGS LIGHT VERTICAL AND RIGHT:'A275:41589:├ +UPPER ONE EIGHTH BLOCK:'A276:41590:▔ +BOX DRAWINGS LIGHT HORIZONTAL:'A277:41591:─ +BOX DRAWINGS LIGHT VERTICAL:'A278:41592:│ +RIGHT ONE EIGHTH BLOCK:'A279:41593:▕ +BOX DRAWINGS LIGHT DOWN AND RIGHT:'A27A:41594:┌ +BOX DRAWINGS LIGHT DOWN AND LEFT:'A27B:41595:┐ +BOX DRAWINGS LIGHT UP AND RIGHT:'A27C:41596:└ +BOX DRAWINGS LIGHT UP AND LEFT:'A27D:41597:┘ +BOX DRAWINGS LIGHT ARC DOWN AND RIGHT:'A27E:41598:╭ +BOX DRAWINGS LIGHT ARC DOWN AND LEFT:'A2A1:41633:╮ +BOX DRAWINGS LIGHT ARC UP AND RIGHT:'A2A2:41634:╰ +BOX DRAWINGS LIGHT ARC UP AND LEFT:'A2A3:41635:╯ +BOX DRAWINGS DOUBLE HORIZONTAL:'A2A4:41636:═ +BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE:'A2A5:41637:╞ +BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE:'A2A6:41638:╪ +BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE:'A2A7:41639:╡ +BLACK LOWER RIGHT TRIANGLE:'A2A8:41640:◢ +BLACK LOWER LEFT TRIANGLE:'A2A9:41641:◣ +BLACK UPPER RIGHT TRIANGLE:'A2AA:41642:◥ +BLACK UPPER LEFT TRIANGLE:'A2AB:41643:◤ +BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT:'A2AC:41644:╱ +BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT:'A2AD:41645:╲ +BOX DRAWINGS LIGHT DIAGONAL CROSS:'A2AE:41646:╳ +FULLWIDTH DIGIT ZERO:'A2AF:41647:0 +FULLWIDTH DIGIT ONE:'A2B0:41648:1 +FULLWIDTH DIGIT TWO:'A2B1:41649:2 +FULLWIDTH DIGIT THREE:'A2B2:41650:3 +FULLWIDTH DIGIT FOUR:'A2B3:41651:4 +FULLWIDTH DIGIT FIVE:'A2B4:41652:5 +FULLWIDTH DIGIT SIX:'A2B5:41653:6 +FULLWIDTH DIGIT SEVEN:'A2B6:41654:7 +FULLWIDTH DIGIT EIGHT:'A2B7:41655:8 +FULLWIDTH DIGIT NINE:'A2B8:41656:9 +ROMAN NUMERAL ONE:'A2B9:41657:Ⅰ +ROMAN NUMERAL TWO:'A2BA:41658:Ⅱ +ROMAN NUMERAL THREE:'A2BB:41659:Ⅲ +ROMAN NUMERAL FOUR:'A2BC:41660:Ⅳ +ROMAN NUMERAL FIVE:'A2BD:41661:Ⅴ +ROMAN NUMERAL SIX:'A2BE:41662:Ⅵ +ROMAN NUMERAL SEVEN:'A2BF:41663:Ⅶ +ROMAN NUMERAL EIGHT:'A2C0:41664:Ⅷ +ROMAN NUMERAL NINE:'A2C1:41665:Ⅸ +ROMAN NUMERAL TEN:'A2C2:41666:Ⅹ +HANGZHOU NUMERAL ONE:'A2C3:41667:〡 +HANGZHOU NUMERAL TWO:'A2C4:41668:〢 +HANGZHOU NUMERAL THREE:'A2C5:41669:〣 +HANGZHOU NUMERAL FOUR:'A2C6:41670:〤 +HANGZHOU NUMERAL FIVE:'A2C7:41671:〥 +HANGZHOU NUMERAL SIX:'A2C8:41672:〦 +HANGZHOU NUMERAL SEVEN:'A2C9:41673:〧 +HANGZHOU NUMERAL EIGHT:'A2CA:41674:〨 +HANGZHOU NUMERAL NINE:'A2CB:41675:〩 +CJK UNIFIED IDEOGRAPH:'A2CC:41676:十 +CJK UNIFIED IDEOGRAPH:'A2CD:41677:卄 +CJK UNIFIED IDEOGRAPH:'A2CE:41678:卅 +FULLWIDTH LATIN CAPITAL LETTER A:'A2CF:41679:A +FULLWIDTH LATIN CAPITAL LETTER B:'A2D0:41680:B +FULLWIDTH LATIN CAPITAL LETTER C:'A2D1:41681:C +FULLWIDTH LATIN CAPITAL LETTER D:'A2D2:41682:D +FULLWIDTH LATIN CAPITAL LETTER E:'A2D3:41683:E +FULLWIDTH LATIN CAPITAL LETTER F:'A2D4:41684:F +FULLWIDTH LATIN CAPITAL LETTER G:'A2D5:41685:G +FULLWIDTH LATIN CAPITAL LETTER H:'A2D6:41686:H +FULLWIDTH LATIN CAPITAL LETTER I:'A2D7:41687:I +FULLWIDTH LATIN CAPITAL LETTER J:'A2D8:41688:J +FULLWIDTH LATIN CAPITAL LETTER K:'A2D9:41689:K +FULLWIDTH LATIN CAPITAL LETTER L:'A2DA:41690:L +FULLWIDTH LATIN CAPITAL LETTER M:'A2DB:41691:M +FULLWIDTH LATIN CAPITAL LETTER N:'A2DC:41692:N +FULLWIDTH LATIN CAPITAL LETTER O:'A2DD:41693:O +FULLWIDTH LATIN CAPITAL LETTER P:'A2DE:41694:P +FULLWIDTH LATIN CAPITAL LETTER Q:'A2DF:41695:Q +FULLWIDTH LATIN CAPITAL LETTER R:'A2E0:41696:R +FULLWIDTH LATIN CAPITAL LETTER S:'A2E1:41697:S +FULLWIDTH LATIN CAPITAL LETTER T:'A2E2:41698:T +FULLWIDTH LATIN CAPITAL LETTER U:'A2E3:41699:U +FULLWIDTH LATIN CAPITAL LETTER V:'A2E4:41700:V +FULLWIDTH LATIN CAPITAL LETTER W:'A2E5:41701:W +FULLWIDTH LATIN CAPITAL LETTER X:'A2E6:41702:X +FULLWIDTH LATIN CAPITAL LETTER Y:'A2E7:41703:Y +FULLWIDTH LATIN CAPITAL LETTER Z:'A2E8:41704:Z +FULLWIDTH LATIN SMALL LETTER A:'A2E9:41705:a +FULLWIDTH LATIN SMALL LETTER B:'A2EA:41706:b +FULLWIDTH LATIN SMALL LETTER C:'A2EB:41707:c +FULLWIDTH LATIN SMALL LETTER D:'A2EC:41708:d +FULLWIDTH LATIN SMALL LETTER E:'A2ED:41709:e +FULLWIDTH LATIN SMALL LETTER F:'A2EE:41710:f +FULLWIDTH LATIN SMALL LETTER G:'A2EF:41711:g +FULLWIDTH LATIN SMALL LETTER H:'A2F0:41712:h +FULLWIDTH LATIN SMALL LETTER I:'A2F1:41713:i +FULLWIDTH LATIN SMALL LETTER J:'A2F2:41714:j +FULLWIDTH LATIN SMALL LETTER K:'A2F3:41715:k +FULLWIDTH LATIN SMALL LETTER L:'A2F4:41716:l +FULLWIDTH LATIN SMALL LETTER M:'A2F5:41717:m +FULLWIDTH LATIN SMALL LETTER N:'A2F6:41718:n +FULLWIDTH LATIN SMALL LETTER O:'A2F7:41719:o +FULLWIDTH LATIN SMALL LETTER P:'A2F8:41720:p +FULLWIDTH LATIN SMALL LETTER Q:'A2F9:41721:q +FULLWIDTH LATIN SMALL LETTER R:'A2FA:41722:r +FULLWIDTH LATIN SMALL LETTER S:'A2FB:41723:s +FULLWIDTH LATIN SMALL LETTER T:'A2FC:41724:t +FULLWIDTH LATIN SMALL LETTER U:'A2FD:41725:u +FULLWIDTH LATIN SMALL LETTER V:'A2FE:41726:v +FULLWIDTH LATIN SMALL LETTER W:'A340:41792:w +FULLWIDTH LATIN SMALL LETTER X:'A341:41793:x +FULLWIDTH LATIN SMALL LETTER Y:'A342:41794:y +FULLWIDTH LATIN SMALL LETTER Z:'A343:41795:z +GREEK CAPITAL LETTER ALPHA:'A344:41796:Α +GREEK CAPITAL LETTER BETA:'A345:41797:Β +GREEK CAPITAL LETTER GAMMA:'A346:41798:Γ +GREEK CAPITAL LETTER DELTA:'A347:41799:Δ +GREEK CAPITAL LETTER EPSILON:'A348:41800:Ε +GREEK CAPITAL LETTER ZETA:'A349:41801:Ζ +GREEK CAPITAL LETTER ETA:'A34A:41802:Η +GREEK CAPITAL LETTER THETA:'A34B:41803:Θ +GREEK CAPITAL LETTER IOTA:'A34C:41804:Ι +GREEK CAPITAL LETTER KAPPA:'A34D:41805:Κ +GREEK CAPITAL LETTER LAMDA:'A34E:41806:Λ +GREEK CAPITAL LETTER MU:'A34F:41807:Μ +GREEK CAPITAL LETTER NU:'A350:41808:Ν +GREEK CAPITAL LETTER XI:'A351:41809:Ξ +GREEK CAPITAL LETTER OMICRON:'A352:41810:Ο +GREEK CAPITAL LETTER PI:'A353:41811:Π +GREEK CAPITAL LETTER RHO:'A354:41812:Ρ +GREEK CAPITAL LETTER SIGMA:'A355:41813:Σ +GREEK CAPITAL LETTER TAU:'A356:41814:Τ +GREEK CAPITAL LETTER UPSILON:'A357:41815:Υ +GREEK CAPITAL LETTER PHI:'A358:41816:Φ +GREEK CAPITAL LETTER CHI:'A359:41817:Χ +GREEK CAPITAL LETTER PSI:'A35A:41818:Ψ +GREEK CAPITAL LETTER OMEGA:'A35B:41819:Ω +GREEK SMALL LETTER ALPHA:'A35C:41820:α +GREEK SMALL LETTER BETA:'A35D:41821:β +GREEK SMALL LETTER GAMMA:'A35E:41822:γ +GREEK SMALL LETTER DELTA:'A35F:41823:δ +GREEK SMALL LETTER EPSILON:'A360:41824:ε +GREEK SMALL LETTER ZETA:'A361:41825:ζ +GREEK SMALL LETTER ETA:'A362:41826:η +GREEK SMALL LETTER THETA:'A363:41827:θ +GREEK SMALL LETTER IOTA:'A364:41828:ι +GREEK SMALL LETTER KAPPA:'A365:41829:κ +GREEK SMALL LETTER LAMDA:'A366:41830:λ +GREEK SMALL LETTER MU:'A367:41831:μ +GREEK SMALL LETTER NU:'A368:41832:ν +GREEK SMALL LETTER XI:'A369:41833:ξ +GREEK SMALL LETTER OMICRON:'A36A:41834:ο +GREEK SMALL LETTER PI:'A36B:41835:π +GREEK SMALL LETTER RHO:'A36C:41836:ρ +GREEK SMALL LETTER SIGMA:'A36D:41837:σ +GREEK SMALL LETTER TAU:'A36E:41838:τ +GREEK SMALL LETTER UPSILON:'A36F:41839:υ +GREEK SMALL LETTER PHI:'A370:41840:φ +GREEK SMALL LETTER CHI:'A371:41841:χ +GREEK SMALL LETTER PSI:'A372:41842:ψ +GREEK SMALL LETTER OMEGA:'A373:41843:ω +BOPOMOFO LETTER B:'A374:41844:ㄅ +BOPOMOFO LETTER P:'A375:41845:ㄆ +BOPOMOFO LETTER M:'A376:41846:ㄇ +BOPOMOFO LETTER F:'A377:41847:ㄈ +BOPOMOFO LETTER D:'A378:41848:ㄉ +BOPOMOFO LETTER T:'A379:41849:ㄊ +BOPOMOFO LETTER N:'A37A:41850:ㄋ +BOPOMOFO LETTER L:'A37B:41851:ㄌ +BOPOMOFO LETTER G:'A37C:41852:ㄍ +BOPOMOFO LETTER K:'A37D:41853:ㄎ +BOPOMOFO LETTER H:'A37E:41854:ㄏ +BOPOMOFO LETTER J:'A3A1:41889:ㄐ +BOPOMOFO LETTER Q:'A3A2:41890:ㄑ +BOPOMOFO LETTER X:'A3A3:41891:ㄒ +BOPOMOFO LETTER ZH:'A3A4:41892:ㄓ +BOPOMOFO LETTER CH:'A3A5:41893:ㄔ +BOPOMOFO LETTER SH:'A3A6:41894:ㄕ +BOPOMOFO LETTER R:'A3A7:41895:ㄖ +BOPOMOFO LETTER Z:'A3A8:41896:ㄗ +BOPOMOFO LETTER C:'A3A9:41897:ㄘ +BOPOMOFO LETTER S:'A3AA:41898:ㄙ +BOPOMOFO LETTER A:'A3AB:41899:ㄚ +BOPOMOFO LETTER O:'A3AC:41900:ㄛ +BOPOMOFO LETTER E:'A3AD:41901:ㄜ +BOPOMOFO LETTER EH:'A3AE:41902:ㄝ +BOPOMOFO LETTER AI:'A3AF:41903:ㄞ +BOPOMOFO LETTER EI:'A3B0:41904:ㄟ +BOPOMOFO LETTER AU:'A3B1:41905:ㄠ +BOPOMOFO LETTER OU:'A3B2:41906:ㄡ +BOPOMOFO LETTER AN:'A3B3:41907:ㄢ +BOPOMOFO LETTER EN:'A3B4:41908:ㄣ +BOPOMOFO LETTER ANG:'A3B5:41909:ㄤ +BOPOMOFO LETTER ENG:'A3B6:41910:ㄥ +BOPOMOFO LETTER ER:'A3B7:41911:ㄦ +BOPOMOFO LETTER I:'A3B8:41912:ㄧ +BOPOMOFO LETTER U:'A3B9:41913:ㄨ +BOPOMOFO LETTER IU:'A3BA:41914:ㄩ +DOT ABOVE:'A3BB:41915:˙ +MODIFIER LETTER MACRON:'A3BC:41916:ˉ +MODIFIER LETTER ACUTE ACCENT:'A3BD:41917:ˊ +CARON:'A3BE:41918:ˇ +MODIFIER LETTER GRAVE ACCENT:'A3BF:41919:ˋ +EURO SIGN:'A3E1:41953:€ +CJK UNIFIED IDEOGRAPH:'A440:42048:一 +CJK UNIFIED IDEOGRAPH:'A441:42049:乙 +CJK UNIFIED IDEOGRAPH:'A442:42050:丁 +CJK UNIFIED IDEOGRAPH:'A443:42051:七 +CJK UNIFIED IDEOGRAPH:'A444:42052:乃 +CJK UNIFIED IDEOGRAPH:'A445:42053:九 +CJK UNIFIED IDEOGRAPH:'A446:42054:了 +CJK UNIFIED IDEOGRAPH:'A447:42055:二 +CJK UNIFIED IDEOGRAPH:'A448:42056:人 +CJK UNIFIED IDEOGRAPH:'A449:42057:儿 +CJK UNIFIED IDEOGRAPH:'A44A:42058:入 +CJK UNIFIED IDEOGRAPH:'A44B:42059:八 +CJK UNIFIED IDEOGRAPH:'A44C:42060:几 +CJK UNIFIED IDEOGRAPH:'A44D:42061:刀 +CJK UNIFIED IDEOGRAPH:'A44E:42062:刁 +CJK UNIFIED IDEOGRAPH:'A44F:42063:力 +CJK UNIFIED IDEOGRAPH:'A450:42064:匕 +CJK UNIFIED IDEOGRAPH:'A451:42065:十 +CJK UNIFIED IDEOGRAPH:'A452:42066:卜 +CJK UNIFIED IDEOGRAPH:'A453:42067:又 +CJK UNIFIED IDEOGRAPH:'A454:42068:三 +CJK UNIFIED IDEOGRAPH:'A455:42069:下 +CJK UNIFIED IDEOGRAPH:'A456:42070:丈 +CJK UNIFIED IDEOGRAPH:'A457:42071:上 +CJK UNIFIED IDEOGRAPH:'A458:42072:丫 +CJK UNIFIED IDEOGRAPH:'A459:42073:丸 +CJK UNIFIED IDEOGRAPH:'A45A:42074:凡 +CJK UNIFIED IDEOGRAPH:'A45B:42075:久 +CJK UNIFIED IDEOGRAPH:'A45C:42076:么 +CJK UNIFIED IDEOGRAPH:'A45D:42077:也 +CJK UNIFIED IDEOGRAPH:'A45E:42078:乞 +CJK UNIFIED IDEOGRAPH:'A45F:42079:于 +CJK UNIFIED IDEOGRAPH:'A460:42080:亡 +CJK UNIFIED IDEOGRAPH:'A461:42081:兀 +CJK UNIFIED IDEOGRAPH:'A462:42082:刃 +CJK UNIFIED IDEOGRAPH:'A463:42083:勺 +CJK UNIFIED IDEOGRAPH:'A464:42084:千 +CJK UNIFIED IDEOGRAPH:'A465:42085:叉 +CJK UNIFIED IDEOGRAPH:'A466:42086:口 +CJK UNIFIED IDEOGRAPH:'A467:42087:土 +CJK UNIFIED IDEOGRAPH:'A468:42088:士 +CJK UNIFIED IDEOGRAPH:'A469:42089:夕 +CJK UNIFIED IDEOGRAPH:'A46A:42090:大 +CJK UNIFIED IDEOGRAPH:'A46B:42091:女 +CJK UNIFIED IDEOGRAPH:'A46C:42092:子 +CJK UNIFIED IDEOGRAPH:'A46D:42093:孑 +CJK UNIFIED IDEOGRAPH:'A46E:42094:孓 +CJK UNIFIED IDEOGRAPH:'A46F:42095:寸 +CJK UNIFIED IDEOGRAPH:'A470:42096:小 +CJK UNIFIED IDEOGRAPH:'A471:42097:尢 +CJK UNIFIED IDEOGRAPH:'A472:42098:尸 +CJK UNIFIED IDEOGRAPH:'A473:42099:山 +CJK UNIFIED IDEOGRAPH:'A474:42100:川 +CJK UNIFIED IDEOGRAPH:'A475:42101:工 +CJK UNIFIED IDEOGRAPH:'A476:42102:己 +CJK UNIFIED IDEOGRAPH:'A477:42103:已 +CJK UNIFIED IDEOGRAPH:'A478:42104:巳 +CJK UNIFIED IDEOGRAPH:'A479:42105:巾 +CJK UNIFIED IDEOGRAPH:'A47A:42106:干 +CJK UNIFIED IDEOGRAPH:'A47B:42107:廾 +CJK UNIFIED IDEOGRAPH:'A47C:42108:弋 +CJK UNIFIED IDEOGRAPH:'A47D:42109:弓 +CJK UNIFIED IDEOGRAPH:'A47E:42110:才 +CJK UNIFIED IDEOGRAPH:'A4A1:42145:丑 +CJK UNIFIED IDEOGRAPH:'A4A2:42146:丐 +CJK UNIFIED IDEOGRAPH:'A4A3:42147:不 +CJK UNIFIED IDEOGRAPH:'A4A4:42148:中 +CJK UNIFIED IDEOGRAPH:'A4A5:42149:丰 +CJK UNIFIED IDEOGRAPH:'A4A6:42150:丹 +CJK UNIFIED IDEOGRAPH:'A4A7:42151:之 +CJK UNIFIED IDEOGRAPH:'A4A8:42152:尹 +CJK UNIFIED IDEOGRAPH:'A4A9:42153:予 +CJK UNIFIED IDEOGRAPH:'A4AA:42154:云 +CJK UNIFIED IDEOGRAPH:'A4AB:42155:井 +CJK UNIFIED IDEOGRAPH:'A4AC:42156:互 +CJK UNIFIED IDEOGRAPH:'A4AD:42157:五 +CJK UNIFIED IDEOGRAPH:'A4AE:42158:亢 +CJK UNIFIED IDEOGRAPH:'A4AF:42159:仁 +CJK UNIFIED IDEOGRAPH:'A4B0:42160:什 +CJK UNIFIED IDEOGRAPH:'A4B1:42161:仃 +CJK UNIFIED IDEOGRAPH:'A4B2:42162:仆 +CJK UNIFIED IDEOGRAPH:'A4B3:42163:仇 +CJK UNIFIED IDEOGRAPH:'A4B4:42164:仍 +CJK UNIFIED IDEOGRAPH:'A4B5:42165:今 +CJK UNIFIED IDEOGRAPH:'A4B6:42166:介 +CJK UNIFIED IDEOGRAPH:'A4B7:42167:仄 +CJK UNIFIED IDEOGRAPH:'A4B8:42168:元 +CJK UNIFIED IDEOGRAPH:'A4B9:42169:允 +CJK UNIFIED IDEOGRAPH:'A4BA:42170:內 +CJK UNIFIED IDEOGRAPH:'A4BB:42171:六 +CJK UNIFIED IDEOGRAPH:'A4BC:42172:兮 +CJK UNIFIED IDEOGRAPH:'A4BD:42173:公 +CJK UNIFIED IDEOGRAPH:'A4BE:42174:冗 +CJK UNIFIED IDEOGRAPH:'A4BF:42175:凶 +CJK UNIFIED IDEOGRAPH:'A4C0:42176:分 +CJK UNIFIED IDEOGRAPH:'A4C1:42177:切 +CJK UNIFIED IDEOGRAPH:'A4C2:42178:刈 +CJK UNIFIED IDEOGRAPH:'A4C3:42179:勻 +CJK UNIFIED IDEOGRAPH:'A4C4:42180:勾 +CJK UNIFIED IDEOGRAPH:'A4C5:42181:勿 +CJK UNIFIED IDEOGRAPH:'A4C6:42182:化 +CJK UNIFIED IDEOGRAPH:'A4C7:42183:匹 +CJK UNIFIED IDEOGRAPH:'A4C8:42184:午 +CJK UNIFIED IDEOGRAPH:'A4C9:42185:升 +CJK UNIFIED IDEOGRAPH:'A4CA:42186:卅 +CJK UNIFIED IDEOGRAPH:'A4CB:42187:卞 +CJK UNIFIED IDEOGRAPH:'A4CC:42188:厄 +CJK UNIFIED IDEOGRAPH:'A4CD:42189:友 +CJK UNIFIED IDEOGRAPH:'A4CE:42190:及 +CJK UNIFIED IDEOGRAPH:'A4CF:42191:反 +CJK UNIFIED IDEOGRAPH:'A4D0:42192:壬 +CJK UNIFIED IDEOGRAPH:'A4D1:42193:天 +CJK UNIFIED IDEOGRAPH:'A4D2:42194:夫 +CJK UNIFIED IDEOGRAPH:'A4D3:42195:太 +CJK UNIFIED IDEOGRAPH:'A4D4:42196:夭 +CJK UNIFIED IDEOGRAPH:'A4D5:42197:孔 +CJK UNIFIED IDEOGRAPH:'A4D6:42198:少 +CJK UNIFIED IDEOGRAPH:'A4D7:42199:尤 +CJK UNIFIED IDEOGRAPH:'A4D8:42200:尺 +CJK UNIFIED IDEOGRAPH:'A4D9:42201:屯 +CJK UNIFIED IDEOGRAPH:'A4DA:42202:巴 +CJK UNIFIED IDEOGRAPH:'A4DB:42203:幻 +CJK UNIFIED IDEOGRAPH:'A4DC:42204:廿 +CJK UNIFIED IDEOGRAPH:'A4DD:42205:弔 +CJK UNIFIED IDEOGRAPH:'A4DE:42206:引 +CJK UNIFIED IDEOGRAPH:'A4DF:42207:心 +CJK UNIFIED IDEOGRAPH:'A4E0:42208:戈 +CJK UNIFIED IDEOGRAPH:'A4E1:42209:戶 +CJK UNIFIED IDEOGRAPH:'A4E2:42210:手 +CJK UNIFIED IDEOGRAPH:'A4E3:42211:扎 +CJK UNIFIED IDEOGRAPH:'A4E4:42212:支 +CJK UNIFIED IDEOGRAPH:'A4E5:42213:文 +CJK UNIFIED IDEOGRAPH:'A4E6:42214:斗 +CJK UNIFIED IDEOGRAPH:'A4E7:42215:斤 +CJK UNIFIED IDEOGRAPH:'A4E8:42216:方 +CJK UNIFIED IDEOGRAPH:'A4E9:42217:日 +CJK UNIFIED IDEOGRAPH:'A4EA:42218:曰 +CJK UNIFIED IDEOGRAPH:'A4EB:42219:月 +CJK UNIFIED IDEOGRAPH:'A4EC:42220:木 +CJK UNIFIED IDEOGRAPH:'A4ED:42221:欠 +CJK UNIFIED IDEOGRAPH:'A4EE:42222:止 +CJK UNIFIED IDEOGRAPH:'A4EF:42223:歹 +CJK UNIFIED IDEOGRAPH:'A4F0:42224:毋 +CJK UNIFIED IDEOGRAPH:'A4F1:42225:比 +CJK UNIFIED IDEOGRAPH:'A4F2:42226:毛 +CJK UNIFIED IDEOGRAPH:'A4F3:42227:氏 +CJK UNIFIED IDEOGRAPH:'A4F4:42228:水 +CJK UNIFIED IDEOGRAPH:'A4F5:42229:火 +CJK UNIFIED IDEOGRAPH:'A4F6:42230:爪 +CJK UNIFIED IDEOGRAPH:'A4F7:42231:父 +CJK UNIFIED IDEOGRAPH:'A4F8:42232:爻 +CJK UNIFIED IDEOGRAPH:'A4F9:42233:片 +CJK UNIFIED IDEOGRAPH:'A4FA:42234:牙 +CJK UNIFIED IDEOGRAPH:'A4FB:42235:牛 +CJK UNIFIED IDEOGRAPH:'A4FC:42236:犬 +CJK UNIFIED IDEOGRAPH:'A4FD:42237:王 +CJK UNIFIED IDEOGRAPH:'A4FE:42238:丙 +CJK UNIFIED IDEOGRAPH:'A540:42304:世 +CJK UNIFIED IDEOGRAPH:'A541:42305:丕 +CJK UNIFIED IDEOGRAPH:'A542:42306:且 +CJK UNIFIED IDEOGRAPH:'A543:42307:丘 +CJK UNIFIED IDEOGRAPH:'A544:42308:主 +CJK UNIFIED IDEOGRAPH:'A545:42309:乍 +CJK UNIFIED IDEOGRAPH:'A546:42310:乏 +CJK UNIFIED IDEOGRAPH:'A547:42311:乎 +CJK UNIFIED IDEOGRAPH:'A548:42312:以 +CJK UNIFIED IDEOGRAPH:'A549:42313:付 +CJK UNIFIED IDEOGRAPH:'A54A:42314:仔 +CJK UNIFIED IDEOGRAPH:'A54B:42315:仕 +CJK UNIFIED IDEOGRAPH:'A54C:42316:他 +CJK UNIFIED IDEOGRAPH:'A54D:42317:仗 +CJK UNIFIED IDEOGRAPH:'A54E:42318:代 +CJK UNIFIED IDEOGRAPH:'A54F:42319:令 +CJK UNIFIED IDEOGRAPH:'A550:42320:仙 +CJK UNIFIED IDEOGRAPH:'A551:42321:仞 +CJK UNIFIED IDEOGRAPH:'A552:42322:充 +CJK UNIFIED IDEOGRAPH:'A553:42323:兄 +CJK UNIFIED IDEOGRAPH:'A554:42324:冉 +CJK UNIFIED IDEOGRAPH:'A555:42325:冊 +CJK UNIFIED IDEOGRAPH:'A556:42326:冬 +CJK UNIFIED IDEOGRAPH:'A557:42327:凹 +CJK UNIFIED IDEOGRAPH:'A558:42328:出 +CJK UNIFIED IDEOGRAPH:'A559:42329:凸 +CJK UNIFIED IDEOGRAPH:'A55A:42330:刊 +CJK UNIFIED IDEOGRAPH:'A55B:42331:加 +CJK UNIFIED IDEOGRAPH:'A55C:42332:功 +CJK UNIFIED IDEOGRAPH:'A55D:42333:包 +CJK UNIFIED IDEOGRAPH:'A55E:42334:匆 +CJK UNIFIED IDEOGRAPH:'A55F:42335:北 +CJK UNIFIED IDEOGRAPH:'A560:42336:匝 +CJK UNIFIED IDEOGRAPH:'A561:42337:仟 +CJK UNIFIED IDEOGRAPH:'A562:42338:半 +CJK UNIFIED IDEOGRAPH:'A563:42339:卉 +CJK UNIFIED IDEOGRAPH:'A564:42340:卡 +CJK UNIFIED IDEOGRAPH:'A565:42341:占 +CJK UNIFIED IDEOGRAPH:'A566:42342:卯 +CJK UNIFIED IDEOGRAPH:'A567:42343:卮 +CJK UNIFIED IDEOGRAPH:'A568:42344:去 +CJK UNIFIED IDEOGRAPH:'A569:42345:可 +CJK UNIFIED IDEOGRAPH:'A56A:42346:古 +CJK UNIFIED IDEOGRAPH:'A56B:42347:右 +CJK UNIFIED IDEOGRAPH:'A56C:42348:召 +CJK UNIFIED IDEOGRAPH:'A56D:42349:叮 +CJK UNIFIED IDEOGRAPH:'A56E:42350:叩 +CJK UNIFIED IDEOGRAPH:'A56F:42351:叨 +CJK UNIFIED IDEOGRAPH:'A570:42352:叼 +CJK UNIFIED IDEOGRAPH:'A571:42353:司 +CJK UNIFIED IDEOGRAPH:'A572:42354:叵 +CJK UNIFIED IDEOGRAPH:'A573:42355:叫 +CJK UNIFIED IDEOGRAPH:'A574:42356:另 +CJK UNIFIED IDEOGRAPH:'A575:42357:只 +CJK UNIFIED IDEOGRAPH:'A576:42358:史 +CJK UNIFIED IDEOGRAPH:'A577:42359:叱 +CJK UNIFIED IDEOGRAPH:'A578:42360:台 +CJK UNIFIED IDEOGRAPH:'A579:42361:句 +CJK UNIFIED IDEOGRAPH:'A57A:42362:叭 +CJK UNIFIED IDEOGRAPH:'A57B:42363:叻 +CJK UNIFIED IDEOGRAPH:'A57C:42364:四 +CJK UNIFIED IDEOGRAPH:'A57D:42365:囚 +CJK UNIFIED IDEOGRAPH:'A57E:42366:外 +CJK UNIFIED IDEOGRAPH:'A5A1:42401:央 +CJK UNIFIED IDEOGRAPH:'A5A2:42402:失 +CJK UNIFIED IDEOGRAPH:'A5A3:42403:奴 +CJK UNIFIED IDEOGRAPH:'A5A4:42404:奶 +CJK UNIFIED IDEOGRAPH:'A5A5:42405:孕 +CJK UNIFIED IDEOGRAPH:'A5A6:42406:它 +CJK UNIFIED IDEOGRAPH:'A5A7:42407:尼 +CJK UNIFIED IDEOGRAPH:'A5A8:42408:巨 +CJK UNIFIED IDEOGRAPH:'A5A9:42409:巧 +CJK UNIFIED IDEOGRAPH:'A5AA:42410:左 +CJK UNIFIED IDEOGRAPH:'A5AB:42411:市 +CJK UNIFIED IDEOGRAPH:'A5AC:42412:布 +CJK UNIFIED IDEOGRAPH:'A5AD:42413:平 +CJK UNIFIED IDEOGRAPH:'A5AE:42414:幼 +CJK UNIFIED IDEOGRAPH:'A5AF:42415:弁 +CJK UNIFIED IDEOGRAPH:'A5B0:42416:弘 +CJK UNIFIED IDEOGRAPH:'A5B1:42417:弗 +CJK UNIFIED IDEOGRAPH:'A5B2:42418:必 +CJK UNIFIED IDEOGRAPH:'A5B3:42419:戊 +CJK UNIFIED IDEOGRAPH:'A5B4:42420:打 +CJK UNIFIED IDEOGRAPH:'A5B5:42421:扔 +CJK UNIFIED IDEOGRAPH:'A5B6:42422:扒 +CJK UNIFIED IDEOGRAPH:'A5B7:42423:扑 +CJK UNIFIED IDEOGRAPH:'A5B8:42424:斥 +CJK UNIFIED IDEOGRAPH:'A5B9:42425:旦 +CJK UNIFIED IDEOGRAPH:'A5BA:42426:朮 +CJK UNIFIED IDEOGRAPH:'A5BB:42427:本 +CJK UNIFIED IDEOGRAPH:'A5BC:42428:未 +CJK UNIFIED IDEOGRAPH:'A5BD:42429:末 +CJK UNIFIED IDEOGRAPH:'A5BE:42430:札 +CJK UNIFIED IDEOGRAPH:'A5BF:42431:正 +CJK UNIFIED IDEOGRAPH:'A5C0:42432:母 +CJK UNIFIED IDEOGRAPH:'A5C1:42433:民 +CJK UNIFIED IDEOGRAPH:'A5C2:42434:氐 +CJK UNIFIED IDEOGRAPH:'A5C3:42435:永 +CJK UNIFIED IDEOGRAPH:'A5C4:42436:汁 +CJK UNIFIED IDEOGRAPH:'A5C5:42437:汀 +CJK UNIFIED IDEOGRAPH:'A5C6:42438:氾 +CJK UNIFIED IDEOGRAPH:'A5C7:42439:犯 +CJK UNIFIED IDEOGRAPH:'A5C8:42440:玄 +CJK UNIFIED IDEOGRAPH:'A5C9:42441:玉 +CJK UNIFIED IDEOGRAPH:'A5CA:42442:瓜 +CJK UNIFIED IDEOGRAPH:'A5CB:42443:瓦 +CJK UNIFIED IDEOGRAPH:'A5CC:42444:甘 +CJK UNIFIED IDEOGRAPH:'A5CD:42445:生 +CJK UNIFIED IDEOGRAPH:'A5CE:42446:用 +CJK UNIFIED IDEOGRAPH:'A5CF:42447:甩 +CJK UNIFIED IDEOGRAPH:'A5D0:42448:田 +CJK UNIFIED IDEOGRAPH:'A5D1:42449:由 +CJK UNIFIED IDEOGRAPH:'A5D2:42450:甲 +CJK UNIFIED IDEOGRAPH:'A5D3:42451:申 +CJK UNIFIED IDEOGRAPH:'A5D4:42452:疋 +CJK UNIFIED IDEOGRAPH:'A5D5:42453:白 +CJK UNIFIED IDEOGRAPH:'A5D6:42454:皮 +CJK UNIFIED IDEOGRAPH:'A5D7:42455:皿 +CJK UNIFIED IDEOGRAPH:'A5D8:42456:目 +CJK UNIFIED IDEOGRAPH:'A5D9:42457:矛 +CJK UNIFIED IDEOGRAPH:'A5DA:42458:矢 +CJK UNIFIED IDEOGRAPH:'A5DB:42459:石 +CJK UNIFIED IDEOGRAPH:'A5DC:42460:示 +CJK UNIFIED IDEOGRAPH:'A5DD:42461:禾 +CJK UNIFIED IDEOGRAPH:'A5DE:42462:穴 +CJK UNIFIED IDEOGRAPH:'A5DF:42463:立 +CJK UNIFIED IDEOGRAPH:'A5E0:42464:丞 +CJK UNIFIED IDEOGRAPH:'A5E1:42465:丟 +CJK UNIFIED IDEOGRAPH:'A5E2:42466:乒 +CJK UNIFIED IDEOGRAPH:'A5E3:42467:乓 +CJK UNIFIED IDEOGRAPH:'A5E4:42468:乩 +CJK UNIFIED IDEOGRAPH:'A5E5:42469:亙 +CJK UNIFIED IDEOGRAPH:'A5E6:42470:交 +CJK UNIFIED IDEOGRAPH:'A5E7:42471:亦 +CJK UNIFIED IDEOGRAPH:'A5E8:42472:亥 +CJK UNIFIED IDEOGRAPH:'A5E9:42473:仿 +CJK UNIFIED IDEOGRAPH:'A5EA:42474:伉 +CJK UNIFIED IDEOGRAPH:'A5EB:42475:伙 +CJK UNIFIED IDEOGRAPH:'A5EC:42476:伊 +CJK UNIFIED IDEOGRAPH:'A5ED:42477:伕 +CJK UNIFIED IDEOGRAPH:'A5EE:42478:伍 +CJK UNIFIED IDEOGRAPH:'A5EF:42479:伐 +CJK UNIFIED IDEOGRAPH:'A5F0:42480:休 +CJK UNIFIED IDEOGRAPH:'A5F1:42481:伏 +CJK UNIFIED IDEOGRAPH:'A5F2:42482:仲 +CJK UNIFIED IDEOGRAPH:'A5F3:42483:件 +CJK UNIFIED IDEOGRAPH:'A5F4:42484:任 +CJK UNIFIED IDEOGRAPH:'A5F5:42485:仰 +CJK UNIFIED IDEOGRAPH:'A5F6:42486:仳 +CJK UNIFIED IDEOGRAPH:'A5F7:42487:份 +CJK UNIFIED IDEOGRAPH:'A5F8:42488:企 +CJK UNIFIED IDEOGRAPH:'A5F9:42489:伋 +CJK UNIFIED IDEOGRAPH:'A5FA:42490:光 +CJK UNIFIED IDEOGRAPH:'A5FB:42491:兇 +CJK UNIFIED IDEOGRAPH:'A5FC:42492:兆 +CJK UNIFIED IDEOGRAPH:'A5FD:42493:先 +CJK UNIFIED IDEOGRAPH:'A5FE:42494:全 +CJK UNIFIED IDEOGRAPH:'A640:42560:共 +CJK UNIFIED IDEOGRAPH:'A641:42561:再 +CJK UNIFIED IDEOGRAPH:'A642:42562:冰 +CJK UNIFIED IDEOGRAPH:'A643:42563:列 +CJK UNIFIED IDEOGRAPH:'A644:42564:刑 +CJK UNIFIED IDEOGRAPH:'A645:42565:划 +CJK UNIFIED IDEOGRAPH:'A646:42566:刎 +CJK UNIFIED IDEOGRAPH:'A647:42567:刖 +CJK UNIFIED IDEOGRAPH:'A648:42568:劣 +CJK UNIFIED IDEOGRAPH:'A649:42569:匈 +CJK UNIFIED IDEOGRAPH:'A64A:42570:匡 +CJK UNIFIED IDEOGRAPH:'A64B:42571:匠 +CJK UNIFIED IDEOGRAPH:'A64C:42572:印 +CJK UNIFIED IDEOGRAPH:'A64D:42573:危 +CJK UNIFIED IDEOGRAPH:'A64E:42574:吉 +CJK UNIFIED IDEOGRAPH:'A64F:42575:吏 +CJK UNIFIED IDEOGRAPH:'A650:42576:同 +CJK UNIFIED IDEOGRAPH:'A651:42577:吊 +CJK UNIFIED IDEOGRAPH:'A652:42578:吐 +CJK UNIFIED IDEOGRAPH:'A653:42579:吁 +CJK UNIFIED IDEOGRAPH:'A654:42580:吋 +CJK UNIFIED IDEOGRAPH:'A655:42581:各 +CJK UNIFIED IDEOGRAPH:'A656:42582:向 +CJK UNIFIED IDEOGRAPH:'A657:42583:名 +CJK UNIFIED IDEOGRAPH:'A658:42584:合 +CJK UNIFIED IDEOGRAPH:'A659:42585:吃 +CJK UNIFIED IDEOGRAPH:'A65A:42586:后 +CJK UNIFIED IDEOGRAPH:'A65B:42587:吆 +CJK UNIFIED IDEOGRAPH:'A65C:42588:吒 +CJK UNIFIED IDEOGRAPH:'A65D:42589:因 +CJK UNIFIED IDEOGRAPH:'A65E:42590:回 +CJK UNIFIED IDEOGRAPH:'A65F:42591:囝 +CJK UNIFIED IDEOGRAPH:'A660:42592:圳 +CJK UNIFIED IDEOGRAPH:'A661:42593:地 +CJK UNIFIED IDEOGRAPH:'A662:42594:在 +CJK UNIFIED IDEOGRAPH:'A663:42595:圭 +CJK UNIFIED IDEOGRAPH:'A664:42596:圬 +CJK UNIFIED IDEOGRAPH:'A665:42597:圯 +CJK UNIFIED IDEOGRAPH:'A666:42598:圩 +CJK UNIFIED IDEOGRAPH:'A667:42599:夙 +CJK UNIFIED IDEOGRAPH:'A668:42600:多 +CJK UNIFIED IDEOGRAPH:'A669:42601:夷 +CJK UNIFIED IDEOGRAPH:'A66A:42602:夸 +CJK UNIFIED IDEOGRAPH:'A66B:42603:妄 +CJK UNIFIED IDEOGRAPH:'A66C:42604:奸 +CJK UNIFIED IDEOGRAPH:'A66D:42605:妃 +CJK UNIFIED IDEOGRAPH:'A66E:42606:好 +CJK UNIFIED IDEOGRAPH:'A66F:42607:她 +CJK UNIFIED IDEOGRAPH:'A670:42608:如 +CJK UNIFIED IDEOGRAPH:'A671:42609:妁 +CJK UNIFIED IDEOGRAPH:'A672:42610:字 +CJK UNIFIED IDEOGRAPH:'A673:42611:存 +CJK UNIFIED IDEOGRAPH:'A674:42612:宇 +CJK UNIFIED IDEOGRAPH:'A675:42613:守 +CJK UNIFIED IDEOGRAPH:'A676:42614:宅 +CJK UNIFIED IDEOGRAPH:'A677:42615:安 +CJK UNIFIED IDEOGRAPH:'A678:42616:寺 +CJK UNIFIED IDEOGRAPH:'A679:42617:尖 +CJK UNIFIED IDEOGRAPH:'A67A:42618:屹 +CJK UNIFIED IDEOGRAPH:'A67B:42619:州 +CJK UNIFIED IDEOGRAPH:'A67C:42620:帆 +CJK UNIFIED IDEOGRAPH:'A67D:42621:并 +CJK UNIFIED IDEOGRAPH:'A67E:42622:年 +CJK UNIFIED IDEOGRAPH:'A6A1:42657:式 +CJK UNIFIED IDEOGRAPH:'A6A2:42658:弛 +CJK UNIFIED IDEOGRAPH:'A6A3:42659:忙 +CJK UNIFIED IDEOGRAPH:'A6A4:42660:忖 +CJK UNIFIED IDEOGRAPH:'A6A5:42661:戎 +CJK UNIFIED IDEOGRAPH:'A6A6:42662:戌 +CJK UNIFIED IDEOGRAPH:'A6A7:42663:戍 +CJK UNIFIED IDEOGRAPH:'A6A8:42664:成 +CJK UNIFIED IDEOGRAPH:'A6A9:42665:扣 +CJK UNIFIED IDEOGRAPH:'A6AA:42666:扛 +CJK UNIFIED IDEOGRAPH:'A6AB:42667:托 +CJK UNIFIED IDEOGRAPH:'A6AC:42668:收 +CJK UNIFIED IDEOGRAPH:'A6AD:42669:早 +CJK UNIFIED IDEOGRAPH:'A6AE:42670:旨 +CJK UNIFIED IDEOGRAPH:'A6AF:42671:旬 +CJK UNIFIED IDEOGRAPH:'A6B0:42672:旭 +CJK UNIFIED IDEOGRAPH:'A6B1:42673:曲 +CJK UNIFIED IDEOGRAPH:'A6B2:42674:曳 +CJK UNIFIED IDEOGRAPH:'A6B3:42675:有 +CJK UNIFIED IDEOGRAPH:'A6B4:42676:朽 +CJK UNIFIED IDEOGRAPH:'A6B5:42677:朴 +CJK UNIFIED IDEOGRAPH:'A6B6:42678:朱 +CJK UNIFIED IDEOGRAPH:'A6B7:42679:朵 +CJK UNIFIED IDEOGRAPH:'A6B8:42680:次 +CJK UNIFIED IDEOGRAPH:'A6B9:42681:此 +CJK UNIFIED IDEOGRAPH:'A6BA:42682:死 +CJK UNIFIED IDEOGRAPH:'A6BB:42683:氖 +CJK UNIFIED IDEOGRAPH:'A6BC:42684:汝 +CJK UNIFIED IDEOGRAPH:'A6BD:42685:汗 +CJK UNIFIED IDEOGRAPH:'A6BE:42686:汙 +CJK UNIFIED IDEOGRAPH:'A6BF:42687:江 +CJK UNIFIED IDEOGRAPH:'A6C0:42688:池 +CJK UNIFIED IDEOGRAPH:'A6C1:42689:汐 +CJK UNIFIED IDEOGRAPH:'A6C2:42690:汕 +CJK UNIFIED IDEOGRAPH:'A6C3:42691:污 +CJK UNIFIED IDEOGRAPH:'A6C4:42692:汛 +CJK UNIFIED IDEOGRAPH:'A6C5:42693:汍 +CJK UNIFIED IDEOGRAPH:'A6C6:42694:汎 +CJK UNIFIED IDEOGRAPH:'A6C7:42695:灰 +CJK UNIFIED IDEOGRAPH:'A6C8:42696:牟 +CJK UNIFIED IDEOGRAPH:'A6C9:42697:牝 +CJK UNIFIED IDEOGRAPH:'A6CA:42698:百 +CJK UNIFIED IDEOGRAPH:'A6CB:42699:竹 +CJK UNIFIED IDEOGRAPH:'A6CC:42700:米 +CJK UNIFIED IDEOGRAPH:'A6CD:42701:糸 +CJK UNIFIED IDEOGRAPH:'A6CE:42702:缶 +CJK UNIFIED IDEOGRAPH:'A6CF:42703:羊 +CJK UNIFIED IDEOGRAPH:'A6D0:42704:羽 +CJK UNIFIED IDEOGRAPH:'A6D1:42705:老 +CJK UNIFIED IDEOGRAPH:'A6D2:42706:考 +CJK UNIFIED IDEOGRAPH:'A6D3:42707:而 +CJK UNIFIED IDEOGRAPH:'A6D4:42708:耒 +CJK UNIFIED IDEOGRAPH:'A6D5:42709:耳 +CJK UNIFIED IDEOGRAPH:'A6D6:42710:聿 +CJK UNIFIED IDEOGRAPH:'A6D7:42711:肉 +CJK UNIFIED IDEOGRAPH:'A6D8:42712:肋 +CJK UNIFIED IDEOGRAPH:'A6D9:42713:肌 +CJK UNIFIED IDEOGRAPH:'A6DA:42714:臣 +CJK UNIFIED IDEOGRAPH:'A6DB:42715:自 +CJK UNIFIED IDEOGRAPH:'A6DC:42716:至 +CJK UNIFIED IDEOGRAPH:'A6DD:42717:臼 +CJK UNIFIED IDEOGRAPH:'A6DE:42718:舌 +CJK UNIFIED IDEOGRAPH:'A6DF:42719:舛 +CJK UNIFIED IDEOGRAPH:'A6E0:42720:舟 +CJK UNIFIED IDEOGRAPH:'A6E1:42721:艮 +CJK UNIFIED IDEOGRAPH:'A6E2:42722:色 +CJK UNIFIED IDEOGRAPH:'A6E3:42723:艾 +CJK UNIFIED IDEOGRAPH:'A6E4:42724:虫 +CJK UNIFIED IDEOGRAPH:'A6E5:42725:血 +CJK UNIFIED IDEOGRAPH:'A6E6:42726:行 +CJK UNIFIED IDEOGRAPH:'A6E7:42727:衣 +CJK UNIFIED IDEOGRAPH:'A6E8:42728:西 +CJK UNIFIED IDEOGRAPH:'A6E9:42729:阡 +CJK UNIFIED IDEOGRAPH:'A6EA:42730:串 +CJK UNIFIED IDEOGRAPH:'A6EB:42731:亨 +CJK UNIFIED IDEOGRAPH:'A6EC:42732:位 +CJK UNIFIED IDEOGRAPH:'A6ED:42733:住 +CJK UNIFIED IDEOGRAPH:'A6EE:42734:佇 +CJK UNIFIED IDEOGRAPH:'A6EF:42735:佗 +CJK UNIFIED IDEOGRAPH:'A6F0:42736:佞 +CJK UNIFIED IDEOGRAPH:'A6F1:42737:伴 +CJK UNIFIED IDEOGRAPH:'A6F2:42738:佛 +CJK UNIFIED IDEOGRAPH:'A6F3:42739:何 +CJK UNIFIED IDEOGRAPH:'A6F4:42740:估 +CJK UNIFIED IDEOGRAPH:'A6F5:42741:佐 +CJK UNIFIED IDEOGRAPH:'A6F6:42742:佑 +CJK UNIFIED IDEOGRAPH:'A6F7:42743:伽 +CJK UNIFIED IDEOGRAPH:'A6F8:42744:伺 +CJK UNIFIED IDEOGRAPH:'A6F9:42745:伸 +CJK UNIFIED IDEOGRAPH:'A6FA:42746:佃 +CJK UNIFIED IDEOGRAPH:'A6FB:42747:佔 +CJK UNIFIED IDEOGRAPH:'A6FC:42748:似 +CJK UNIFIED IDEOGRAPH:'A6FD:42749:但 +CJK UNIFIED IDEOGRAPH:'A6FE:42750:佣 +CJK UNIFIED IDEOGRAPH:'A740:42816:作 +CJK UNIFIED IDEOGRAPH:'A741:42817:你 +CJK UNIFIED IDEOGRAPH:'A742:42818:伯 +CJK UNIFIED IDEOGRAPH:'A743:42819:低 +CJK UNIFIED IDEOGRAPH:'A744:42820:伶 +CJK UNIFIED IDEOGRAPH:'A745:42821:余 +CJK UNIFIED IDEOGRAPH:'A746:42822:佝 +CJK UNIFIED IDEOGRAPH:'A747:42823:佈 +CJK UNIFIED IDEOGRAPH:'A748:42824:佚 +CJK UNIFIED IDEOGRAPH:'A749:42825:兌 +CJK UNIFIED IDEOGRAPH:'A74A:42826:克 +CJK UNIFIED IDEOGRAPH:'A74B:42827:免 +CJK UNIFIED IDEOGRAPH:'A74C:42828:兵 +CJK UNIFIED IDEOGRAPH:'A74D:42829:冶 +CJK UNIFIED IDEOGRAPH:'A74E:42830:冷 +CJK UNIFIED IDEOGRAPH:'A74F:42831:別 +CJK UNIFIED IDEOGRAPH:'A750:42832:判 +CJK UNIFIED IDEOGRAPH:'A751:42833:利 +CJK UNIFIED IDEOGRAPH:'A752:42834:刪 +CJK UNIFIED IDEOGRAPH:'A753:42835:刨 +CJK UNIFIED IDEOGRAPH:'A754:42836:劫 +CJK UNIFIED IDEOGRAPH:'A755:42837:助 +CJK UNIFIED IDEOGRAPH:'A756:42838:努 +CJK UNIFIED IDEOGRAPH:'A757:42839:劬 +CJK UNIFIED IDEOGRAPH:'A758:42840:匣 +CJK UNIFIED IDEOGRAPH:'A759:42841:即 +CJK UNIFIED IDEOGRAPH:'A75A:42842:卵 +CJK UNIFIED IDEOGRAPH:'A75B:42843:吝 +CJK UNIFIED IDEOGRAPH:'A75C:42844:吭 +CJK UNIFIED IDEOGRAPH:'A75D:42845:吞 +CJK UNIFIED IDEOGRAPH:'A75E:42846:吾 +CJK UNIFIED IDEOGRAPH:'A75F:42847:否 +CJK UNIFIED IDEOGRAPH:'A760:42848:呎 +CJK UNIFIED IDEOGRAPH:'A761:42849:吧 +CJK UNIFIED IDEOGRAPH:'A762:42850:呆 +CJK UNIFIED IDEOGRAPH:'A763:42851:呃 +CJK UNIFIED IDEOGRAPH:'A764:42852:吳 +CJK UNIFIED IDEOGRAPH:'A765:42853:呈 +CJK UNIFIED IDEOGRAPH:'A766:42854:呂 +CJK UNIFIED IDEOGRAPH:'A767:42855:君 +CJK UNIFIED IDEOGRAPH:'A768:42856:吩 +CJK UNIFIED IDEOGRAPH:'A769:42857:告 +CJK UNIFIED IDEOGRAPH:'A76A:42858:吹 +CJK UNIFIED IDEOGRAPH:'A76B:42859:吻 +CJK UNIFIED IDEOGRAPH:'A76C:42860:吸 +CJK UNIFIED IDEOGRAPH:'A76D:42861:吮 +CJK UNIFIED IDEOGRAPH:'A76E:42862:吵 +CJK UNIFIED IDEOGRAPH:'A76F:42863:吶 +CJK UNIFIED IDEOGRAPH:'A770:42864:吠 +CJK UNIFIED IDEOGRAPH:'A771:42865:吼 +CJK UNIFIED IDEOGRAPH:'A772:42866:呀 +CJK UNIFIED IDEOGRAPH:'A773:42867:吱 +CJK UNIFIED IDEOGRAPH:'A774:42868:含 +CJK UNIFIED IDEOGRAPH:'A775:42869:吟 +CJK UNIFIED IDEOGRAPH:'A776:42870:听 +CJK UNIFIED IDEOGRAPH:'A777:42871:囪 +CJK UNIFIED IDEOGRAPH:'A778:42872:困 +CJK UNIFIED IDEOGRAPH:'A779:42873:囤 +CJK UNIFIED IDEOGRAPH:'A77A:42874:囫 +CJK UNIFIED IDEOGRAPH:'A77B:42875:坊 +CJK UNIFIED IDEOGRAPH:'A77C:42876:坑 +CJK UNIFIED IDEOGRAPH:'A77D:42877:址 +CJK UNIFIED IDEOGRAPH:'A77E:42878:坍 +CJK UNIFIED IDEOGRAPH:'A7A1:42913:均 +CJK UNIFIED IDEOGRAPH:'A7A2:42914:坎 +CJK UNIFIED IDEOGRAPH:'A7A3:42915:圾 +CJK UNIFIED IDEOGRAPH:'A7A4:42916:坐 +CJK UNIFIED IDEOGRAPH:'A7A5:42917:坏 +CJK UNIFIED IDEOGRAPH:'A7A6:42918:圻 +CJK UNIFIED IDEOGRAPH:'A7A7:42919:壯 +CJK UNIFIED IDEOGRAPH:'A7A8:42920:夾 +CJK UNIFIED IDEOGRAPH:'A7A9:42921:妝 +CJK UNIFIED IDEOGRAPH:'A7AA:42922:妒 +CJK UNIFIED IDEOGRAPH:'A7AB:42923:妨 +CJK UNIFIED IDEOGRAPH:'A7AC:42924:妞 +CJK UNIFIED IDEOGRAPH:'A7AD:42925:妣 +CJK UNIFIED IDEOGRAPH:'A7AE:42926:妙 +CJK UNIFIED IDEOGRAPH:'A7AF:42927:妖 +CJK UNIFIED IDEOGRAPH:'A7B0:42928:妍 +CJK UNIFIED IDEOGRAPH:'A7B1:42929:妤 +CJK UNIFIED IDEOGRAPH:'A7B2:42930:妓 +CJK UNIFIED IDEOGRAPH:'A7B3:42931:妊 +CJK UNIFIED IDEOGRAPH:'A7B4:42932:妥 +CJK UNIFIED IDEOGRAPH:'A7B5:42933:孝 +CJK UNIFIED IDEOGRAPH:'A7B6:42934:孜 +CJK UNIFIED IDEOGRAPH:'A7B7:42935:孚 +CJK UNIFIED IDEOGRAPH:'A7B8:42936:孛 +CJK UNIFIED IDEOGRAPH:'A7B9:42937:完 +CJK UNIFIED IDEOGRAPH:'A7BA:42938:宋 +CJK UNIFIED IDEOGRAPH:'A7BB:42939:宏 +CJK UNIFIED IDEOGRAPH:'A7BC:42940:尬 +CJK UNIFIED IDEOGRAPH:'A7BD:42941:局 +CJK UNIFIED IDEOGRAPH:'A7BE:42942:屁 +CJK UNIFIED IDEOGRAPH:'A7BF:42943:尿 +CJK UNIFIED IDEOGRAPH:'A7C0:42944:尾 +CJK UNIFIED IDEOGRAPH:'A7C1:42945:岐 +CJK UNIFIED IDEOGRAPH:'A7C2:42946:岑 +CJK UNIFIED IDEOGRAPH:'A7C3:42947:岔 +CJK UNIFIED IDEOGRAPH:'A7C4:42948:岌 +CJK UNIFIED IDEOGRAPH:'A7C5:42949:巫 +CJK UNIFIED IDEOGRAPH:'A7C6:42950:希 +CJK UNIFIED IDEOGRAPH:'A7C7:42951:序 +CJK UNIFIED IDEOGRAPH:'A7C8:42952:庇 +CJK UNIFIED IDEOGRAPH:'A7C9:42953:床 +CJK UNIFIED IDEOGRAPH:'A7CA:42954:廷 +CJK UNIFIED IDEOGRAPH:'A7CB:42955:弄 +CJK UNIFIED IDEOGRAPH:'A7CC:42956:弟 +CJK UNIFIED IDEOGRAPH:'A7CD:42957:彤 +CJK UNIFIED IDEOGRAPH:'A7CE:42958:形 +CJK UNIFIED IDEOGRAPH:'A7CF:42959:彷 +CJK UNIFIED IDEOGRAPH:'A7D0:42960:役 +CJK UNIFIED IDEOGRAPH:'A7D1:42961:忘 +CJK UNIFIED IDEOGRAPH:'A7D2:42962:忌 +CJK UNIFIED IDEOGRAPH:'A7D3:42963:志 +CJK UNIFIED IDEOGRAPH:'A7D4:42964:忍 +CJK UNIFIED IDEOGRAPH:'A7D5:42965:忱 +CJK UNIFIED IDEOGRAPH:'A7D6:42966:快 +CJK UNIFIED IDEOGRAPH:'A7D7:42967:忸 +CJK UNIFIED IDEOGRAPH:'A7D8:42968:忪 +CJK UNIFIED IDEOGRAPH:'A7D9:42969:戒 +CJK UNIFIED IDEOGRAPH:'A7DA:42970:我 +CJK UNIFIED IDEOGRAPH:'A7DB:42971:抄 +CJK UNIFIED IDEOGRAPH:'A7DC:42972:抗 +CJK UNIFIED IDEOGRAPH:'A7DD:42973:抖 +CJK UNIFIED IDEOGRAPH:'A7DE:42974:技 +CJK UNIFIED IDEOGRAPH:'A7DF:42975:扶 +CJK UNIFIED IDEOGRAPH:'A7E0:42976:抉 +CJK UNIFIED IDEOGRAPH:'A7E1:42977:扭 +CJK UNIFIED IDEOGRAPH:'A7E2:42978:把 +CJK UNIFIED IDEOGRAPH:'A7E3:42979:扼 +CJK UNIFIED IDEOGRAPH:'A7E4:42980:找 +CJK UNIFIED IDEOGRAPH:'A7E5:42981:批 +CJK UNIFIED IDEOGRAPH:'A7E6:42982:扳 +CJK UNIFIED IDEOGRAPH:'A7E7:42983:抒 +CJK UNIFIED IDEOGRAPH:'A7E8:42984:扯 +CJK UNIFIED IDEOGRAPH:'A7E9:42985:折 +CJK UNIFIED IDEOGRAPH:'A7EA:42986:扮 +CJK UNIFIED IDEOGRAPH:'A7EB:42987:投 +CJK UNIFIED IDEOGRAPH:'A7EC:42988:抓 +CJK UNIFIED IDEOGRAPH:'A7ED:42989:抑 +CJK UNIFIED IDEOGRAPH:'A7EE:42990:抆 +CJK UNIFIED IDEOGRAPH:'A7EF:42991:改 +CJK UNIFIED IDEOGRAPH:'A7F0:42992:攻 +CJK UNIFIED IDEOGRAPH:'A7F1:42993:攸 +CJK UNIFIED IDEOGRAPH:'A7F2:42994:旱 +CJK UNIFIED IDEOGRAPH:'A7F3:42995:更 +CJK UNIFIED IDEOGRAPH:'A7F4:42996:束 +CJK UNIFIED IDEOGRAPH:'A7F5:42997:李 +CJK UNIFIED IDEOGRAPH:'A7F6:42998:杏 +CJK UNIFIED IDEOGRAPH:'A7F7:42999:材 +CJK UNIFIED IDEOGRAPH:'A7F8:43000:村 +CJK UNIFIED IDEOGRAPH:'A7F9:43001:杜 +CJK UNIFIED IDEOGRAPH:'A7FA:43002:杖 +CJK UNIFIED IDEOGRAPH:'A7FB:43003:杞 +CJK UNIFIED IDEOGRAPH:'A7FC:43004:杉 +CJK UNIFIED IDEOGRAPH:'A7FD:43005:杆 +CJK UNIFIED IDEOGRAPH:'A7FE:43006:杠 +CJK UNIFIED IDEOGRAPH:'A840:43072:杓 +CJK UNIFIED IDEOGRAPH:'A841:43073:杗 +CJK UNIFIED IDEOGRAPH:'A842:43074:步 +CJK UNIFIED IDEOGRAPH:'A843:43075:每 +CJK UNIFIED IDEOGRAPH:'A844:43076:求 +CJK UNIFIED IDEOGRAPH:'A845:43077:汞 +CJK UNIFIED IDEOGRAPH:'A846:43078:沙 +CJK UNIFIED IDEOGRAPH:'A847:43079:沁 +CJK UNIFIED IDEOGRAPH:'A848:43080:沈 +CJK UNIFIED IDEOGRAPH:'A849:43081:沉 +CJK UNIFIED IDEOGRAPH:'A84A:43082:沅 +CJK UNIFIED IDEOGRAPH:'A84B:43083:沛 +CJK UNIFIED IDEOGRAPH:'A84C:43084:汪 +CJK UNIFIED IDEOGRAPH:'A84D:43085:決 +CJK UNIFIED IDEOGRAPH:'A84E:43086:沐 +CJK UNIFIED IDEOGRAPH:'A84F:43087:汰 +CJK UNIFIED IDEOGRAPH:'A850:43088:沌 +CJK UNIFIED IDEOGRAPH:'A851:43089:汨 +CJK UNIFIED IDEOGRAPH:'A852:43090:沖 +CJK UNIFIED IDEOGRAPH:'A853:43091:沒 +CJK UNIFIED IDEOGRAPH:'A854:43092:汽 +CJK UNIFIED IDEOGRAPH:'A855:43093:沃 +CJK UNIFIED IDEOGRAPH:'A856:43094:汲 +CJK UNIFIED IDEOGRAPH:'A857:43095:汾 +CJK UNIFIED IDEOGRAPH:'A858:43096:汴 +CJK UNIFIED IDEOGRAPH:'A859:43097:沆 +CJK UNIFIED IDEOGRAPH:'A85A:43098:汶 +CJK UNIFIED IDEOGRAPH:'A85B:43099:沍 +CJK UNIFIED IDEOGRAPH:'A85C:43100:沔 +CJK UNIFIED IDEOGRAPH:'A85D:43101:沘 +CJK UNIFIED IDEOGRAPH:'A85E:43102:沂 +CJK UNIFIED IDEOGRAPH:'A85F:43103:灶 +CJK UNIFIED IDEOGRAPH:'A860:43104:灼 +CJK UNIFIED IDEOGRAPH:'A861:43105:災 +CJK UNIFIED IDEOGRAPH:'A862:43106:灸 +CJK UNIFIED IDEOGRAPH:'A863:43107:牢 +CJK UNIFIED IDEOGRAPH:'A864:43108:牡 +CJK UNIFIED IDEOGRAPH:'A865:43109:牠 +CJK UNIFIED IDEOGRAPH:'A866:43110:狄 +CJK UNIFIED IDEOGRAPH:'A867:43111:狂 +CJK UNIFIED IDEOGRAPH:'A868:43112:玖 +CJK UNIFIED IDEOGRAPH:'A869:43113:甬 +CJK UNIFIED IDEOGRAPH:'A86A:43114:甫 +CJK UNIFIED IDEOGRAPH:'A86B:43115:男 +CJK UNIFIED IDEOGRAPH:'A86C:43116:甸 +CJK UNIFIED IDEOGRAPH:'A86D:43117:皂 +CJK UNIFIED IDEOGRAPH:'A86E:43118:盯 +CJK UNIFIED IDEOGRAPH:'A86F:43119:矣 +CJK UNIFIED IDEOGRAPH:'A870:43120:私 +CJK UNIFIED IDEOGRAPH:'A871:43121:秀 +CJK UNIFIED IDEOGRAPH:'A872:43122:禿 +CJK UNIFIED IDEOGRAPH:'A873:43123:究 +CJK UNIFIED IDEOGRAPH:'A874:43124:系 +CJK UNIFIED IDEOGRAPH:'A875:43125:罕 +CJK UNIFIED IDEOGRAPH:'A876:43126:肖 +CJK UNIFIED IDEOGRAPH:'A877:43127:肓 +CJK UNIFIED IDEOGRAPH:'A878:43128:肝 +CJK UNIFIED IDEOGRAPH:'A879:43129:肘 +CJK UNIFIED IDEOGRAPH:'A87A:43130:肛 +CJK UNIFIED IDEOGRAPH:'A87B:43131:肚 +CJK UNIFIED IDEOGRAPH:'A87C:43132:育 +CJK UNIFIED IDEOGRAPH:'A87D:43133:良 +CJK UNIFIED IDEOGRAPH:'A87E:43134:芒 +CJK UNIFIED IDEOGRAPH:'A8A1:43169:芋 +CJK UNIFIED IDEOGRAPH:'A8A2:43170:芍 +CJK UNIFIED IDEOGRAPH:'A8A3:43171:見 +CJK UNIFIED IDEOGRAPH:'A8A4:43172:角 +CJK UNIFIED IDEOGRAPH:'A8A5:43173:言 +CJK UNIFIED IDEOGRAPH:'A8A6:43174:谷 +CJK UNIFIED IDEOGRAPH:'A8A7:43175:豆 +CJK UNIFIED IDEOGRAPH:'A8A8:43176:豕 +CJK UNIFIED IDEOGRAPH:'A8A9:43177:貝 +CJK UNIFIED IDEOGRAPH:'A8AA:43178:赤 +CJK UNIFIED IDEOGRAPH:'A8AB:43179:走 +CJK UNIFIED IDEOGRAPH:'A8AC:43180:足 +CJK UNIFIED IDEOGRAPH:'A8AD:43181:身 +CJK UNIFIED IDEOGRAPH:'A8AE:43182:車 +CJK UNIFIED IDEOGRAPH:'A8AF:43183:辛 +CJK UNIFIED IDEOGRAPH:'A8B0:43184:辰 +CJK UNIFIED IDEOGRAPH:'A8B1:43185:迂 +CJK UNIFIED IDEOGRAPH:'A8B2:43186:迆 +CJK UNIFIED IDEOGRAPH:'A8B3:43187:迅 +CJK UNIFIED IDEOGRAPH:'A8B4:43188:迄 +CJK UNIFIED IDEOGRAPH:'A8B5:43189:巡 +CJK UNIFIED IDEOGRAPH:'A8B6:43190:邑 +CJK UNIFIED IDEOGRAPH:'A8B7:43191:邢 +CJK UNIFIED IDEOGRAPH:'A8B8:43192:邪 +CJK UNIFIED IDEOGRAPH:'A8B9:43193:邦 +CJK UNIFIED IDEOGRAPH:'A8BA:43194:那 +CJK UNIFIED IDEOGRAPH:'A8BB:43195:酉 +CJK UNIFIED IDEOGRAPH:'A8BC:43196:釆 +CJK UNIFIED IDEOGRAPH:'A8BD:43197:里 +CJK UNIFIED IDEOGRAPH:'A8BE:43198:防 +CJK UNIFIED IDEOGRAPH:'A8BF:43199:阮 +CJK UNIFIED IDEOGRAPH:'A8C0:43200:阱 +CJK UNIFIED IDEOGRAPH:'A8C1:43201:阪 +CJK UNIFIED IDEOGRAPH:'A8C2:43202:阬 +CJK UNIFIED IDEOGRAPH:'A8C3:43203:並 +CJK UNIFIED IDEOGRAPH:'A8C4:43204:乖 +CJK UNIFIED IDEOGRAPH:'A8C5:43205:乳 +CJK UNIFIED IDEOGRAPH:'A8C6:43206:事 +CJK UNIFIED IDEOGRAPH:'A8C7:43207:些 +CJK UNIFIED IDEOGRAPH:'A8C8:43208:亞 +CJK UNIFIED IDEOGRAPH:'A8C9:43209:享 +CJK UNIFIED IDEOGRAPH:'A8CA:43210:京 +CJK UNIFIED IDEOGRAPH:'A8CB:43211:佯 +CJK UNIFIED IDEOGRAPH:'A8CC:43212:依 +CJK UNIFIED IDEOGRAPH:'A8CD:43213:侍 +CJK UNIFIED IDEOGRAPH:'A8CE:43214:佳 +CJK UNIFIED IDEOGRAPH:'A8CF:43215:使 +CJK UNIFIED IDEOGRAPH:'A8D0:43216:佬 +CJK UNIFIED IDEOGRAPH:'A8D1:43217:供 +CJK UNIFIED IDEOGRAPH:'A8D2:43218:例 +CJK UNIFIED IDEOGRAPH:'A8D3:43219:來 +CJK UNIFIED IDEOGRAPH:'A8D4:43220:侃 +CJK UNIFIED IDEOGRAPH:'A8D5:43221:佰 +CJK UNIFIED IDEOGRAPH:'A8D6:43222:併 +CJK UNIFIED IDEOGRAPH:'A8D7:43223:侈 +CJK UNIFIED IDEOGRAPH:'A8D8:43224:佩 +CJK UNIFIED IDEOGRAPH:'A8D9:43225:佻 +CJK UNIFIED IDEOGRAPH:'A8DA:43226:侖 +CJK UNIFIED IDEOGRAPH:'A8DB:43227:佾 +CJK UNIFIED IDEOGRAPH:'A8DC:43228:侏 +CJK UNIFIED IDEOGRAPH:'A8DD:43229:侑 +CJK UNIFIED IDEOGRAPH:'A8DE:43230:佺 +CJK UNIFIED IDEOGRAPH:'A8DF:43231:兔 +CJK UNIFIED IDEOGRAPH:'A8E0:43232:兒 +CJK UNIFIED IDEOGRAPH:'A8E1:43233:兕 +CJK UNIFIED IDEOGRAPH:'A8E2:43234:兩 +CJK UNIFIED IDEOGRAPH:'A8E3:43235:具 +CJK UNIFIED IDEOGRAPH:'A8E4:43236:其 +CJK UNIFIED IDEOGRAPH:'A8E5:43237:典 +CJK UNIFIED IDEOGRAPH:'A8E6:43238:冽 +CJK UNIFIED IDEOGRAPH:'A8E7:43239:函 +CJK UNIFIED IDEOGRAPH:'A8E8:43240:刻 +CJK UNIFIED IDEOGRAPH:'A8E9:43241:券 +CJK UNIFIED IDEOGRAPH:'A8EA:43242:刷 +CJK UNIFIED IDEOGRAPH:'A8EB:43243:刺 +CJK UNIFIED IDEOGRAPH:'A8EC:43244:到 +CJK UNIFIED IDEOGRAPH:'A8ED:43245:刮 +CJK UNIFIED IDEOGRAPH:'A8EE:43246:制 +CJK UNIFIED IDEOGRAPH:'A8EF:43247:剁 +CJK UNIFIED IDEOGRAPH:'A8F0:43248:劾 +CJK UNIFIED IDEOGRAPH:'A8F1:43249:劻 +CJK UNIFIED IDEOGRAPH:'A8F2:43250:卒 +CJK UNIFIED IDEOGRAPH:'A8F3:43251:協 +CJK UNIFIED IDEOGRAPH:'A8F4:43252:卓 +CJK UNIFIED IDEOGRAPH:'A8F5:43253:卑 +CJK UNIFIED IDEOGRAPH:'A8F6:43254:卦 +CJK UNIFIED IDEOGRAPH:'A8F7:43255:卷 +CJK UNIFIED IDEOGRAPH:'A8F8:43256:卸 +CJK UNIFIED IDEOGRAPH:'A8F9:43257:卹 +CJK UNIFIED IDEOGRAPH:'A8FA:43258:取 +CJK UNIFIED IDEOGRAPH:'A8FB:43259:叔 +CJK UNIFIED IDEOGRAPH:'A8FC:43260:受 +CJK UNIFIED IDEOGRAPH:'A8FD:43261:味 +CJK UNIFIED IDEOGRAPH:'A8FE:43262:呵 +CJK UNIFIED IDEOGRAPH:'A940:43328:咖 +CJK UNIFIED IDEOGRAPH:'A941:43329:呸 +CJK UNIFIED IDEOGRAPH:'A942:43330:咕 +CJK UNIFIED IDEOGRAPH:'A943:43331:咀 +CJK UNIFIED IDEOGRAPH:'A944:43332:呻 +CJK UNIFIED IDEOGRAPH:'A945:43333:呷 +CJK UNIFIED IDEOGRAPH:'A946:43334:咄 +CJK UNIFIED IDEOGRAPH:'A947:43335:咒 +CJK UNIFIED IDEOGRAPH:'A948:43336:咆 +CJK UNIFIED IDEOGRAPH:'A949:43337:呼 +CJK UNIFIED IDEOGRAPH:'A94A:43338:咐 +CJK UNIFIED IDEOGRAPH:'A94B:43339:呱 +CJK UNIFIED IDEOGRAPH:'A94C:43340:呶 +CJK UNIFIED IDEOGRAPH:'A94D:43341:和 +CJK UNIFIED IDEOGRAPH:'A94E:43342:咚 +CJK UNIFIED IDEOGRAPH:'A94F:43343:呢 +CJK UNIFIED IDEOGRAPH:'A950:43344:周 +CJK UNIFIED IDEOGRAPH:'A951:43345:咋 +CJK UNIFIED IDEOGRAPH:'A952:43346:命 +CJK UNIFIED IDEOGRAPH:'A953:43347:咎 +CJK UNIFIED IDEOGRAPH:'A954:43348:固 +CJK UNIFIED IDEOGRAPH:'A955:43349:垃 +CJK UNIFIED IDEOGRAPH:'A956:43350:坷 +CJK UNIFIED IDEOGRAPH:'A957:43351:坪 +CJK UNIFIED IDEOGRAPH:'A958:43352:坩 +CJK UNIFIED IDEOGRAPH:'A959:43353:坡 +CJK UNIFIED IDEOGRAPH:'A95A:43354:坦 +CJK UNIFIED IDEOGRAPH:'A95B:43355:坤 +CJK UNIFIED IDEOGRAPH:'A95C:43356:坼 +CJK UNIFIED IDEOGRAPH:'A95D:43357:夜 +CJK UNIFIED IDEOGRAPH:'A95E:43358:奉 +CJK UNIFIED IDEOGRAPH:'A95F:43359:奇 +CJK UNIFIED IDEOGRAPH:'A960:43360:奈 +CJK UNIFIED IDEOGRAPH:'A961:43361:奄 +CJK UNIFIED IDEOGRAPH:'A962:43362:奔 +CJK UNIFIED IDEOGRAPH:'A963:43363:妾 +CJK UNIFIED IDEOGRAPH:'A964:43364:妻 +CJK UNIFIED IDEOGRAPH:'A965:43365:委 +CJK UNIFIED IDEOGRAPH:'A966:43366:妹 +CJK UNIFIED IDEOGRAPH:'A967:43367:妮 +CJK UNIFIED IDEOGRAPH:'A968:43368:姑 +CJK UNIFIED IDEOGRAPH:'A969:43369:姆 +CJK UNIFIED IDEOGRAPH:'A96A:43370:姐 +CJK UNIFIED IDEOGRAPH:'A96B:43371:姍 +CJK UNIFIED IDEOGRAPH:'A96C:43372:始 +CJK UNIFIED IDEOGRAPH:'A96D:43373:姓 +CJK UNIFIED IDEOGRAPH:'A96E:43374:姊 +CJK UNIFIED IDEOGRAPH:'A96F:43375:妯 +CJK UNIFIED IDEOGRAPH:'A970:43376:妳 +CJK UNIFIED IDEOGRAPH:'A971:43377:姒 +CJK UNIFIED IDEOGRAPH:'A972:43378:姅 +CJK UNIFIED IDEOGRAPH:'A973:43379:孟 +CJK UNIFIED IDEOGRAPH:'A974:43380:孤 +CJK UNIFIED IDEOGRAPH:'A975:43381:季 +CJK UNIFIED IDEOGRAPH:'A976:43382:宗 +CJK UNIFIED IDEOGRAPH:'A977:43383:定 +CJK UNIFIED IDEOGRAPH:'A978:43384:官 +CJK UNIFIED IDEOGRAPH:'A979:43385:宜 +CJK UNIFIED IDEOGRAPH:'A97A:43386:宙 +CJK UNIFIED IDEOGRAPH:'A97B:43387:宛 +CJK UNIFIED IDEOGRAPH:'A97C:43388:尚 +CJK UNIFIED IDEOGRAPH:'A97D:43389:屈 +CJK UNIFIED IDEOGRAPH:'A97E:43390:居 +CJK UNIFIED IDEOGRAPH:'A9A1:43425:屆 +CJK UNIFIED IDEOGRAPH:'A9A2:43426:岷 +CJK UNIFIED IDEOGRAPH:'A9A3:43427:岡 +CJK UNIFIED IDEOGRAPH:'A9A4:43428:岸 +CJK UNIFIED IDEOGRAPH:'A9A5:43429:岩 +CJK UNIFIED IDEOGRAPH:'A9A6:43430:岫 +CJK UNIFIED IDEOGRAPH:'A9A7:43431:岱 +CJK UNIFIED IDEOGRAPH:'A9A8:43432:岳 +CJK UNIFIED IDEOGRAPH:'A9A9:43433:帘 +CJK UNIFIED IDEOGRAPH:'A9AA:43434:帚 +CJK UNIFIED IDEOGRAPH:'A9AB:43435:帖 +CJK UNIFIED IDEOGRAPH:'A9AC:43436:帕 +CJK UNIFIED IDEOGRAPH:'A9AD:43437:帛 +CJK UNIFIED IDEOGRAPH:'A9AE:43438:帑 +CJK UNIFIED IDEOGRAPH:'A9AF:43439:幸 +CJK UNIFIED IDEOGRAPH:'A9B0:43440:庚 +CJK UNIFIED IDEOGRAPH:'A9B1:43441:店 +CJK UNIFIED IDEOGRAPH:'A9B2:43442:府 +CJK UNIFIED IDEOGRAPH:'A9B3:43443:底 +CJK UNIFIED IDEOGRAPH:'A9B4:43444:庖 +CJK UNIFIED IDEOGRAPH:'A9B5:43445:延 +CJK UNIFIED IDEOGRAPH:'A9B6:43446:弦 +CJK UNIFIED IDEOGRAPH:'A9B7:43447:弧 +CJK UNIFIED IDEOGRAPH:'A9B8:43448:弩 +CJK UNIFIED IDEOGRAPH:'A9B9:43449:往 +CJK UNIFIED IDEOGRAPH:'A9BA:43450:征 +CJK UNIFIED IDEOGRAPH:'A9BB:43451:彿 +CJK UNIFIED IDEOGRAPH:'A9BC:43452:彼 +CJK UNIFIED IDEOGRAPH:'A9BD:43453:忝 +CJK UNIFIED IDEOGRAPH:'A9BE:43454:忠 +CJK UNIFIED IDEOGRAPH:'A9BF:43455:忽 +CJK UNIFIED IDEOGRAPH:'A9C0:43456:念 +CJK UNIFIED IDEOGRAPH:'A9C1:43457:忿 +CJK UNIFIED IDEOGRAPH:'A9C2:43458:怏 +CJK UNIFIED IDEOGRAPH:'A9C3:43459:怔 +CJK UNIFIED IDEOGRAPH:'A9C4:43460:怯 +CJK UNIFIED IDEOGRAPH:'A9C5:43461:怵 +CJK UNIFIED IDEOGRAPH:'A9C6:43462:怖 +CJK UNIFIED IDEOGRAPH:'A9C7:43463:怪 +CJK UNIFIED IDEOGRAPH:'A9C8:43464:怕 +CJK UNIFIED IDEOGRAPH:'A9C9:43465:怡 +CJK UNIFIED IDEOGRAPH:'A9CA:43466:性 +CJK UNIFIED IDEOGRAPH:'A9CB:43467:怩 +CJK UNIFIED IDEOGRAPH:'A9CC:43468:怫 +CJK UNIFIED IDEOGRAPH:'A9CD:43469:怛 +CJK UNIFIED IDEOGRAPH:'A9CE:43470:或 +CJK UNIFIED IDEOGRAPH:'A9CF:43471:戕 +CJK UNIFIED IDEOGRAPH:'A9D0:43472:房 +CJK UNIFIED IDEOGRAPH:'A9D1:43473:戾 +CJK UNIFIED IDEOGRAPH:'A9D2:43474:所 +CJK UNIFIED IDEOGRAPH:'A9D3:43475:承 +CJK UNIFIED IDEOGRAPH:'A9D4:43476:拉 +CJK UNIFIED IDEOGRAPH:'A9D5:43477:拌 +CJK UNIFIED IDEOGRAPH:'A9D6:43478:拄 +CJK UNIFIED IDEOGRAPH:'A9D7:43479:抿 +CJK UNIFIED IDEOGRAPH:'A9D8:43480:拂 +CJK UNIFIED IDEOGRAPH:'A9D9:43481:抹 +CJK UNIFIED IDEOGRAPH:'A9DA:43482:拒 +CJK UNIFIED IDEOGRAPH:'A9DB:43483:招 +CJK UNIFIED IDEOGRAPH:'A9DC:43484:披 +CJK UNIFIED IDEOGRAPH:'A9DD:43485:拓 +CJK UNIFIED IDEOGRAPH:'A9DE:43486:拔 +CJK UNIFIED IDEOGRAPH:'A9DF:43487:拋 +CJK UNIFIED IDEOGRAPH:'A9E0:43488:拈 +CJK UNIFIED IDEOGRAPH:'A9E1:43489:抨 +CJK UNIFIED IDEOGRAPH:'A9E2:43490:抽 +CJK UNIFIED IDEOGRAPH:'A9E3:43491:押 +CJK UNIFIED IDEOGRAPH:'A9E4:43492:拐 +CJK UNIFIED IDEOGRAPH:'A9E5:43493:拙 +CJK UNIFIED IDEOGRAPH:'A9E6:43494:拇 +CJK UNIFIED IDEOGRAPH:'A9E7:43495:拍 +CJK UNIFIED IDEOGRAPH:'A9E8:43496:抵 +CJK UNIFIED IDEOGRAPH:'A9E9:43497:拚 +CJK UNIFIED IDEOGRAPH:'A9EA:43498:抱 +CJK UNIFIED IDEOGRAPH:'A9EB:43499:拘 +CJK UNIFIED IDEOGRAPH:'A9EC:43500:拖 +CJK UNIFIED IDEOGRAPH:'A9ED:43501:拗 +CJK UNIFIED IDEOGRAPH:'A9EE:43502:拆 +CJK UNIFIED IDEOGRAPH:'A9EF:43503:抬 +CJK UNIFIED IDEOGRAPH:'A9F0:43504:拎 +CJK UNIFIED IDEOGRAPH:'A9F1:43505:放 +CJK UNIFIED IDEOGRAPH:'A9F2:43506:斧 +CJK UNIFIED IDEOGRAPH:'A9F3:43507:於 +CJK UNIFIED IDEOGRAPH:'A9F4:43508:旺 +CJK UNIFIED IDEOGRAPH:'A9F5:43509:昔 +CJK UNIFIED IDEOGRAPH:'A9F6:43510:易 +CJK UNIFIED IDEOGRAPH:'A9F7:43511:昌 +CJK UNIFIED IDEOGRAPH:'A9F8:43512:昆 +CJK UNIFIED IDEOGRAPH:'A9F9:43513:昂 +CJK UNIFIED IDEOGRAPH:'A9FA:43514:明 +CJK UNIFIED IDEOGRAPH:'A9FB:43515:昀 +CJK UNIFIED IDEOGRAPH:'A9FC:43516:昏 +CJK UNIFIED IDEOGRAPH:'A9FD:43517:昕 +CJK UNIFIED IDEOGRAPH:'A9FE:43518:昊 +CJK UNIFIED IDEOGRAPH:'AA40:43584:昇 +CJK UNIFIED IDEOGRAPH:'AA41:43585:服 +CJK UNIFIED IDEOGRAPH:'AA42:43586:朋 +CJK UNIFIED IDEOGRAPH:'AA43:43587:杭 +CJK UNIFIED IDEOGRAPH:'AA44:43588:枋 +CJK UNIFIED IDEOGRAPH:'AA45:43589:枕 +CJK UNIFIED IDEOGRAPH:'AA46:43590:東 +CJK UNIFIED IDEOGRAPH:'AA47:43591:果 +CJK UNIFIED IDEOGRAPH:'AA48:43592:杳 +CJK UNIFIED IDEOGRAPH:'AA49:43593:杷 +CJK UNIFIED IDEOGRAPH:'AA4A:43594:枇 +CJK UNIFIED IDEOGRAPH:'AA4B:43595:枝 +CJK UNIFIED IDEOGRAPH:'AA4C:43596:林 +CJK UNIFIED IDEOGRAPH:'AA4D:43597:杯 +CJK UNIFIED IDEOGRAPH:'AA4E:43598:杰 +CJK UNIFIED IDEOGRAPH:'AA4F:43599:板 +CJK UNIFIED IDEOGRAPH:'AA50:43600:枉 +CJK UNIFIED IDEOGRAPH:'AA51:43601:松 +CJK UNIFIED IDEOGRAPH:'AA52:43602:析 +CJK UNIFIED IDEOGRAPH:'AA53:43603:杵 +CJK UNIFIED IDEOGRAPH:'AA54:43604:枚 +CJK UNIFIED IDEOGRAPH:'AA55:43605:枓 +CJK UNIFIED IDEOGRAPH:'AA56:43606:杼 +CJK UNIFIED IDEOGRAPH:'AA57:43607:杪 +CJK UNIFIED IDEOGRAPH:'AA58:43608:杲 +CJK UNIFIED IDEOGRAPH:'AA59:43609:欣 +CJK UNIFIED IDEOGRAPH:'AA5A:43610:武 +CJK UNIFIED IDEOGRAPH:'AA5B:43611:歧 +CJK UNIFIED IDEOGRAPH:'AA5C:43612:歿 +CJK UNIFIED IDEOGRAPH:'AA5D:43613:氓 +CJK UNIFIED IDEOGRAPH:'AA5E:43614:氛 +CJK UNIFIED IDEOGRAPH:'AA5F:43615:泣 +CJK UNIFIED IDEOGRAPH:'AA60:43616:注 +CJK UNIFIED IDEOGRAPH:'AA61:43617:泳 +CJK UNIFIED IDEOGRAPH:'AA62:43618:沱 +CJK UNIFIED IDEOGRAPH:'AA63:43619:泌 +CJK UNIFIED IDEOGRAPH:'AA64:43620:泥 +CJK UNIFIED IDEOGRAPH:'AA65:43621:河 +CJK UNIFIED IDEOGRAPH:'AA66:43622:沽 +CJK UNIFIED IDEOGRAPH:'AA67:43623:沾 +CJK UNIFIED IDEOGRAPH:'AA68:43624:沼 +CJK UNIFIED IDEOGRAPH:'AA69:43625:波 +CJK UNIFIED IDEOGRAPH:'AA6A:43626:沫 +CJK UNIFIED IDEOGRAPH:'AA6B:43627:法 +CJK UNIFIED IDEOGRAPH:'AA6C:43628:泓 +CJK UNIFIED IDEOGRAPH:'AA6D:43629:沸 +CJK UNIFIED IDEOGRAPH:'AA6E:43630:泄 +CJK UNIFIED IDEOGRAPH:'AA6F:43631:油 +CJK UNIFIED IDEOGRAPH:'AA70:43632:況 +CJK UNIFIED IDEOGRAPH:'AA71:43633:沮 +CJK UNIFIED IDEOGRAPH:'AA72:43634:泗 +CJK UNIFIED IDEOGRAPH:'AA73:43635:泅 +CJK UNIFIED IDEOGRAPH:'AA74:43636:泱 +CJK UNIFIED IDEOGRAPH:'AA75:43637:沿 +CJK UNIFIED IDEOGRAPH:'AA76:43638:治 +CJK UNIFIED IDEOGRAPH:'AA77:43639:泡 +CJK UNIFIED IDEOGRAPH:'AA78:43640:泛 +CJK UNIFIED IDEOGRAPH:'AA79:43641:泊 +CJK UNIFIED IDEOGRAPH:'AA7A:43642:沬 +CJK UNIFIED IDEOGRAPH:'AA7B:43643:泯 +CJK UNIFIED IDEOGRAPH:'AA7C:43644:泜 +CJK UNIFIED IDEOGRAPH:'AA7D:43645:泖 +CJK UNIFIED IDEOGRAPH:'AA7E:43646:泠 +CJK UNIFIED IDEOGRAPH:'AAA1:43681:炕 +CJK UNIFIED IDEOGRAPH:'AAA2:43682:炎 +CJK UNIFIED IDEOGRAPH:'AAA3:43683:炒 +CJK UNIFIED IDEOGRAPH:'AAA4:43684:炊 +CJK UNIFIED IDEOGRAPH:'AAA5:43685:炙 +CJK UNIFIED IDEOGRAPH:'AAA6:43686:爬 +CJK UNIFIED IDEOGRAPH:'AAA7:43687:爭 +CJK UNIFIED IDEOGRAPH:'AAA8:43688:爸 +CJK UNIFIED IDEOGRAPH:'AAA9:43689:版 +CJK UNIFIED IDEOGRAPH:'AAAA:43690:牧 +CJK UNIFIED IDEOGRAPH:'AAAB:43691:物 +CJK UNIFIED IDEOGRAPH:'AAAC:43692:狀 +CJK UNIFIED IDEOGRAPH:'AAAD:43693:狎 +CJK UNIFIED IDEOGRAPH:'AAAE:43694:狙 +CJK UNIFIED IDEOGRAPH:'AAAF:43695:狗 +CJK UNIFIED IDEOGRAPH:'AAB0:43696:狐 +CJK UNIFIED IDEOGRAPH:'AAB1:43697:玩 +CJK UNIFIED IDEOGRAPH:'AAB2:43698:玨 +CJK UNIFIED IDEOGRAPH:'AAB3:43699:玟 +CJK UNIFIED IDEOGRAPH:'AAB4:43700:玫 +CJK UNIFIED IDEOGRAPH:'AAB5:43701:玥 +CJK UNIFIED IDEOGRAPH:'AAB6:43702:甽 +CJK UNIFIED IDEOGRAPH:'AAB7:43703:疝 +CJK UNIFIED IDEOGRAPH:'AAB8:43704:疙 +CJK UNIFIED IDEOGRAPH:'AAB9:43705:疚 +CJK UNIFIED IDEOGRAPH:'AABA:43706:的 +CJK UNIFIED IDEOGRAPH:'AABB:43707:盂 +CJK UNIFIED IDEOGRAPH:'AABC:43708:盲 +CJK UNIFIED IDEOGRAPH:'AABD:43709:直 +CJK UNIFIED IDEOGRAPH:'AABE:43710:知 +CJK UNIFIED IDEOGRAPH:'AABF:43711:矽 +CJK UNIFIED IDEOGRAPH:'AAC0:43712:社 +CJK UNIFIED IDEOGRAPH:'AAC1:43713:祀 +CJK UNIFIED IDEOGRAPH:'AAC2:43714:祁 +CJK UNIFIED IDEOGRAPH:'AAC3:43715:秉 +CJK UNIFIED IDEOGRAPH:'AAC4:43716:秈 +CJK UNIFIED IDEOGRAPH:'AAC5:43717:空 +CJK UNIFIED IDEOGRAPH:'AAC6:43718:穹 +CJK UNIFIED IDEOGRAPH:'AAC7:43719:竺 +CJK UNIFIED IDEOGRAPH:'AAC8:43720:糾 +CJK UNIFIED IDEOGRAPH:'AAC9:43721:罔 +CJK UNIFIED IDEOGRAPH:'AACA:43722:羌 +CJK UNIFIED IDEOGRAPH:'AACB:43723:羋 +CJK UNIFIED IDEOGRAPH:'AACC:43724:者 +CJK UNIFIED IDEOGRAPH:'AACD:43725:肺 +CJK UNIFIED IDEOGRAPH:'AACE:43726:肥 +CJK UNIFIED IDEOGRAPH:'AACF:43727:肢 +CJK UNIFIED IDEOGRAPH:'AAD0:43728:肱 +CJK UNIFIED IDEOGRAPH:'AAD1:43729:股 +CJK UNIFIED IDEOGRAPH:'AAD2:43730:肫 +CJK UNIFIED IDEOGRAPH:'AAD3:43731:肩 +CJK UNIFIED IDEOGRAPH:'AAD4:43732:肴 +CJK UNIFIED IDEOGRAPH:'AAD5:43733:肪 +CJK UNIFIED IDEOGRAPH:'AAD6:43734:肯 +CJK UNIFIED IDEOGRAPH:'AAD7:43735:臥 +CJK UNIFIED IDEOGRAPH:'AAD8:43736:臾 +CJK UNIFIED IDEOGRAPH:'AAD9:43737:舍 +CJK UNIFIED IDEOGRAPH:'AADA:43738:芳 +CJK UNIFIED IDEOGRAPH:'AADB:43739:芝 +CJK UNIFIED IDEOGRAPH:'AADC:43740:芙 +CJK UNIFIED IDEOGRAPH:'AADD:43741:芭 +CJK UNIFIED IDEOGRAPH:'AADE:43742:芽 +CJK UNIFIED IDEOGRAPH:'AADF:43743:芟 +CJK UNIFIED IDEOGRAPH:'AAE0:43744:芹 +CJK UNIFIED IDEOGRAPH:'AAE1:43745:花 +CJK UNIFIED IDEOGRAPH:'AAE2:43746:芬 +CJK UNIFIED IDEOGRAPH:'AAE3:43747:芥 +CJK UNIFIED IDEOGRAPH:'AAE4:43748:芯 +CJK UNIFIED IDEOGRAPH:'AAE5:43749:芸 +CJK UNIFIED IDEOGRAPH:'AAE6:43750:芣 +CJK UNIFIED IDEOGRAPH:'AAE7:43751:芰 +CJK UNIFIED IDEOGRAPH:'AAE8:43752:芾 +CJK UNIFIED IDEOGRAPH:'AAE9:43753:芷 +CJK UNIFIED IDEOGRAPH:'AAEA:43754:虎 +CJK UNIFIED IDEOGRAPH:'AAEB:43755:虱 +CJK UNIFIED IDEOGRAPH:'AAEC:43756:初 +CJK UNIFIED IDEOGRAPH:'AAED:43757:表 +CJK UNIFIED IDEOGRAPH:'AAEE:43758:軋 +CJK UNIFIED IDEOGRAPH:'AAEF:43759:迎 +CJK UNIFIED IDEOGRAPH:'AAF0:43760:返 +CJK UNIFIED IDEOGRAPH:'AAF1:43761:近 +CJK UNIFIED IDEOGRAPH:'AAF2:43762:邵 +CJK UNIFIED IDEOGRAPH:'AAF3:43763:邸 +CJK UNIFIED IDEOGRAPH:'AAF4:43764:邱 +CJK UNIFIED IDEOGRAPH:'AAF5:43765:邶 +CJK UNIFIED IDEOGRAPH:'AAF6:43766:采 +CJK UNIFIED IDEOGRAPH:'AAF7:43767:金 +CJK UNIFIED IDEOGRAPH:'AAF8:43768:長 +CJK UNIFIED IDEOGRAPH:'AAF9:43769:門 +CJK UNIFIED IDEOGRAPH:'AAFA:43770:阜 +CJK UNIFIED IDEOGRAPH:'AAFB:43771:陀 +CJK UNIFIED IDEOGRAPH:'AAFC:43772:阿 +CJK UNIFIED IDEOGRAPH:'AAFD:43773:阻 +CJK UNIFIED IDEOGRAPH:'AAFE:43774:附 +CJK UNIFIED IDEOGRAPH:'AB40:43840:陂 +CJK UNIFIED IDEOGRAPH:'AB41:43841:隹 +CJK UNIFIED IDEOGRAPH:'AB42:43842:雨 +CJK UNIFIED IDEOGRAPH:'AB43:43843:青 +CJK UNIFIED IDEOGRAPH:'AB44:43844:非 +CJK UNIFIED IDEOGRAPH:'AB45:43845:亟 +CJK UNIFIED IDEOGRAPH:'AB46:43846:亭 +CJK UNIFIED IDEOGRAPH:'AB47:43847:亮 +CJK UNIFIED IDEOGRAPH:'AB48:43848:信 +CJK UNIFIED IDEOGRAPH:'AB49:43849:侵 +CJK UNIFIED IDEOGRAPH:'AB4A:43850:侯 +CJK UNIFIED IDEOGRAPH:'AB4B:43851:便 +CJK UNIFIED IDEOGRAPH:'AB4C:43852:俠 +CJK UNIFIED IDEOGRAPH:'AB4D:43853:俑 +CJK UNIFIED IDEOGRAPH:'AB4E:43854:俏 +CJK UNIFIED IDEOGRAPH:'AB4F:43855:保 +CJK UNIFIED IDEOGRAPH:'AB50:43856:促 +CJK UNIFIED IDEOGRAPH:'AB51:43857:侶 +CJK UNIFIED IDEOGRAPH:'AB52:43858:俘 +CJK UNIFIED IDEOGRAPH:'AB53:43859:俟 +CJK UNIFIED IDEOGRAPH:'AB54:43860:俊 +CJK UNIFIED IDEOGRAPH:'AB55:43861:俗 +CJK UNIFIED IDEOGRAPH:'AB56:43862:侮 +CJK UNIFIED IDEOGRAPH:'AB57:43863:俐 +CJK UNIFIED IDEOGRAPH:'AB58:43864:俄 +CJK UNIFIED IDEOGRAPH:'AB59:43865:係 +CJK UNIFIED IDEOGRAPH:'AB5A:43866:俚 +CJK UNIFIED IDEOGRAPH:'AB5B:43867:俎 +CJK UNIFIED IDEOGRAPH:'AB5C:43868:俞 +CJK UNIFIED IDEOGRAPH:'AB5D:43869:侷 +CJK UNIFIED IDEOGRAPH:'AB5E:43870:兗 +CJK UNIFIED IDEOGRAPH:'AB5F:43871:冒 +CJK UNIFIED IDEOGRAPH:'AB60:43872:冑 +CJK UNIFIED IDEOGRAPH:'AB61:43873:冠 +CJK UNIFIED IDEOGRAPH:'AB62:43874:剎 +CJK UNIFIED IDEOGRAPH:'AB63:43875:剃 +CJK UNIFIED IDEOGRAPH:'AB64:43876:削 +CJK UNIFIED IDEOGRAPH:'AB65:43877:前 +CJK UNIFIED IDEOGRAPH:'AB66:43878:剌 +CJK UNIFIED IDEOGRAPH:'AB67:43879:剋 +CJK UNIFIED IDEOGRAPH:'AB68:43880:則 +CJK UNIFIED IDEOGRAPH:'AB69:43881:勇 +CJK UNIFIED IDEOGRAPH:'AB6A:43882:勉 +CJK UNIFIED IDEOGRAPH:'AB6B:43883:勃 +CJK UNIFIED IDEOGRAPH:'AB6C:43884:勁 +CJK UNIFIED IDEOGRAPH:'AB6D:43885:匍 +CJK UNIFIED IDEOGRAPH:'AB6E:43886:南 +CJK UNIFIED IDEOGRAPH:'AB6F:43887:卻 +CJK UNIFIED IDEOGRAPH:'AB70:43888:厚 +CJK UNIFIED IDEOGRAPH:'AB71:43889:叛 +CJK UNIFIED IDEOGRAPH:'AB72:43890:咬 +CJK UNIFIED IDEOGRAPH:'AB73:43891:哀 +CJK UNIFIED IDEOGRAPH:'AB74:43892:咨 +CJK UNIFIED IDEOGRAPH:'AB75:43893:哎 +CJK UNIFIED IDEOGRAPH:'AB76:43894:哉 +CJK UNIFIED IDEOGRAPH:'AB77:43895:咸 +CJK UNIFIED IDEOGRAPH:'AB78:43896:咦 +CJK UNIFIED IDEOGRAPH:'AB79:43897:咳 +CJK UNIFIED IDEOGRAPH:'AB7A:43898:哇 +CJK UNIFIED IDEOGRAPH:'AB7B:43899:哂 +CJK UNIFIED IDEOGRAPH:'AB7C:43900:咽 +CJK UNIFIED IDEOGRAPH:'AB7D:43901:咪 +CJK UNIFIED IDEOGRAPH:'AB7E:43902:品 +CJK UNIFIED IDEOGRAPH:'ABA1:43937:哄 +CJK UNIFIED IDEOGRAPH:'ABA2:43938:哈 +CJK UNIFIED IDEOGRAPH:'ABA3:43939:咯 +CJK UNIFIED IDEOGRAPH:'ABA4:43940:咫 +CJK UNIFIED IDEOGRAPH:'ABA5:43941:咱 +CJK UNIFIED IDEOGRAPH:'ABA6:43942:咻 +CJK UNIFIED IDEOGRAPH:'ABA7:43943:咩 +CJK UNIFIED IDEOGRAPH:'ABA8:43944:咧 +CJK UNIFIED IDEOGRAPH:'ABA9:43945:咿 +CJK UNIFIED IDEOGRAPH:'ABAA:43946:囿 +CJK UNIFIED IDEOGRAPH:'ABAB:43947:垂 +CJK UNIFIED IDEOGRAPH:'ABAC:43948:型 +CJK UNIFIED IDEOGRAPH:'ABAD:43949:垠 +CJK UNIFIED IDEOGRAPH:'ABAE:43950:垣 +CJK UNIFIED IDEOGRAPH:'ABAF:43951:垢 +CJK UNIFIED IDEOGRAPH:'ABB0:43952:城 +CJK UNIFIED IDEOGRAPH:'ABB1:43953:垮 +CJK UNIFIED IDEOGRAPH:'ABB2:43954:垓 +CJK UNIFIED IDEOGRAPH:'ABB3:43955:奕 +CJK UNIFIED IDEOGRAPH:'ABB4:43956:契 +CJK UNIFIED IDEOGRAPH:'ABB5:43957:奏 +CJK UNIFIED IDEOGRAPH:'ABB6:43958:奎 +CJK UNIFIED IDEOGRAPH:'ABB7:43959:奐 +CJK UNIFIED IDEOGRAPH:'ABB8:43960:姜 +CJK UNIFIED IDEOGRAPH:'ABB9:43961:姘 +CJK UNIFIED IDEOGRAPH:'ABBA:43962:姿 +CJK UNIFIED IDEOGRAPH:'ABBB:43963:姣 +CJK UNIFIED IDEOGRAPH:'ABBC:43964:姨 +CJK UNIFIED IDEOGRAPH:'ABBD:43965:娃 +CJK UNIFIED IDEOGRAPH:'ABBE:43966:姥 +CJK UNIFIED IDEOGRAPH:'ABBF:43967:姪 +CJK UNIFIED IDEOGRAPH:'ABC0:43968:姚 +CJK UNIFIED IDEOGRAPH:'ABC1:43969:姦 +CJK UNIFIED IDEOGRAPH:'ABC2:43970:威 +CJK UNIFIED IDEOGRAPH:'ABC3:43971:姻 +CJK UNIFIED IDEOGRAPH:'ABC4:43972:孩 +CJK UNIFIED IDEOGRAPH:'ABC5:43973:宣 +CJK UNIFIED IDEOGRAPH:'ABC6:43974:宦 +CJK UNIFIED IDEOGRAPH:'ABC7:43975:室 +CJK UNIFIED IDEOGRAPH:'ABC8:43976:客 +CJK UNIFIED IDEOGRAPH:'ABC9:43977:宥 +CJK UNIFIED IDEOGRAPH:'ABCA:43978:封 +CJK UNIFIED IDEOGRAPH:'ABCB:43979:屎 +CJK UNIFIED IDEOGRAPH:'ABCC:43980:屏 +CJK UNIFIED IDEOGRAPH:'ABCD:43981:屍 +CJK UNIFIED IDEOGRAPH:'ABCE:43982:屋 +CJK UNIFIED IDEOGRAPH:'ABCF:43983:峙 +CJK UNIFIED IDEOGRAPH:'ABD0:43984:峒 +CJK UNIFIED IDEOGRAPH:'ABD1:43985:巷 +CJK UNIFIED IDEOGRAPH:'ABD2:43986:帝 +CJK UNIFIED IDEOGRAPH:'ABD3:43987:帥 +CJK UNIFIED IDEOGRAPH:'ABD4:43988:帟 +CJK UNIFIED IDEOGRAPH:'ABD5:43989:幽 +CJK UNIFIED IDEOGRAPH:'ABD6:43990:庠 +CJK UNIFIED IDEOGRAPH:'ABD7:43991:度 +CJK UNIFIED IDEOGRAPH:'ABD8:43992:建 +CJK UNIFIED IDEOGRAPH:'ABD9:43993:弈 +CJK UNIFIED IDEOGRAPH:'ABDA:43994:弭 +CJK UNIFIED IDEOGRAPH:'ABDB:43995:彥 +CJK UNIFIED IDEOGRAPH:'ABDC:43996:很 +CJK UNIFIED IDEOGRAPH:'ABDD:43997:待 +CJK UNIFIED IDEOGRAPH:'ABDE:43998:徊 +CJK UNIFIED IDEOGRAPH:'ABDF:43999:律 +CJK UNIFIED IDEOGRAPH:'ABE0:44000:徇 +CJK UNIFIED IDEOGRAPH:'ABE1:44001:後 +CJK UNIFIED IDEOGRAPH:'ABE2:44002:徉 +CJK UNIFIED IDEOGRAPH:'ABE3:44003:怒 +CJK UNIFIED IDEOGRAPH:'ABE4:44004:思 +CJK UNIFIED IDEOGRAPH:'ABE5:44005:怠 +CJK UNIFIED IDEOGRAPH:'ABE6:44006:急 +CJK UNIFIED IDEOGRAPH:'ABE7:44007:怎 +CJK UNIFIED IDEOGRAPH:'ABE8:44008:怨 +CJK UNIFIED IDEOGRAPH:'ABE9:44009:恍 +CJK UNIFIED IDEOGRAPH:'ABEA:44010:恰 +CJK UNIFIED IDEOGRAPH:'ABEB:44011:恨 +CJK UNIFIED IDEOGRAPH:'ABEC:44012:恢 +CJK UNIFIED IDEOGRAPH:'ABED:44013:恆 +CJK UNIFIED IDEOGRAPH:'ABEE:44014:恃 +CJK UNIFIED IDEOGRAPH:'ABEF:44015:恬 +CJK UNIFIED IDEOGRAPH:'ABF0:44016:恫 +CJK UNIFIED IDEOGRAPH:'ABF1:44017:恪 +CJK UNIFIED IDEOGRAPH:'ABF2:44018:恤 +CJK UNIFIED IDEOGRAPH:'ABF3:44019:扁 +CJK UNIFIED IDEOGRAPH:'ABF4:44020:拜 +CJK UNIFIED IDEOGRAPH:'ABF5:44021:挖 +CJK UNIFIED IDEOGRAPH:'ABF6:44022:按 +CJK UNIFIED IDEOGRAPH:'ABF7:44023:拼 +CJK UNIFIED IDEOGRAPH:'ABF8:44024:拭 +CJK UNIFIED IDEOGRAPH:'ABF9:44025:持 +CJK UNIFIED IDEOGRAPH:'ABFA:44026:拮 +CJK UNIFIED IDEOGRAPH:'ABFB:44027:拽 +CJK UNIFIED IDEOGRAPH:'ABFC:44028:指 +CJK UNIFIED IDEOGRAPH:'ABFD:44029:拱 +CJK UNIFIED IDEOGRAPH:'ABFE:44030:拷 +CJK UNIFIED IDEOGRAPH:'AC40:44096:拯 +CJK UNIFIED IDEOGRAPH:'AC41:44097:括 +CJK UNIFIED IDEOGRAPH:'AC42:44098:拾 +CJK UNIFIED IDEOGRAPH:'AC43:44099:拴 +CJK UNIFIED IDEOGRAPH:'AC44:44100:挑 +CJK UNIFIED IDEOGRAPH:'AC45:44101:挂 +CJK UNIFIED IDEOGRAPH:'AC46:44102:政 +CJK UNIFIED IDEOGRAPH:'AC47:44103:故 +CJK UNIFIED IDEOGRAPH:'AC48:44104:斫 +CJK UNIFIED IDEOGRAPH:'AC49:44105:施 +CJK UNIFIED IDEOGRAPH:'AC4A:44106:既 +CJK UNIFIED IDEOGRAPH:'AC4B:44107:春 +CJK UNIFIED IDEOGRAPH:'AC4C:44108:昭 +CJK UNIFIED IDEOGRAPH:'AC4D:44109:映 +CJK UNIFIED IDEOGRAPH:'AC4E:44110:昧 +CJK UNIFIED IDEOGRAPH:'AC4F:44111:是 +CJK UNIFIED IDEOGRAPH:'AC50:44112:星 +CJK UNIFIED IDEOGRAPH:'AC51:44113:昨 +CJK UNIFIED IDEOGRAPH:'AC52:44114:昱 +CJK UNIFIED IDEOGRAPH:'AC53:44115:昤 +CJK UNIFIED IDEOGRAPH:'AC54:44116:曷 +CJK UNIFIED IDEOGRAPH:'AC55:44117:柿 +CJK UNIFIED IDEOGRAPH:'AC56:44118:染 +CJK UNIFIED IDEOGRAPH:'AC57:44119:柱 +CJK UNIFIED IDEOGRAPH:'AC58:44120:柔 +CJK UNIFIED IDEOGRAPH:'AC59:44121:某 +CJK UNIFIED IDEOGRAPH:'AC5A:44122:柬 +CJK UNIFIED IDEOGRAPH:'AC5B:44123:架 +CJK UNIFIED IDEOGRAPH:'AC5C:44124:枯 +CJK UNIFIED IDEOGRAPH:'AC5D:44125:柵 +CJK UNIFIED IDEOGRAPH:'AC5E:44126:柩 +CJK UNIFIED IDEOGRAPH:'AC5F:44127:柯 +CJK UNIFIED IDEOGRAPH:'AC60:44128:柄 +CJK UNIFIED IDEOGRAPH:'AC61:44129:柑 +CJK UNIFIED IDEOGRAPH:'AC62:44130:枴 +CJK UNIFIED IDEOGRAPH:'AC63:44131:柚 +CJK UNIFIED IDEOGRAPH:'AC64:44132:查 +CJK UNIFIED IDEOGRAPH:'AC65:44133:枸 +CJK UNIFIED IDEOGRAPH:'AC66:44134:柏 +CJK UNIFIED IDEOGRAPH:'AC67:44135:柞 +CJK UNIFIED IDEOGRAPH:'AC68:44136:柳 +CJK UNIFIED IDEOGRAPH:'AC69:44137:枰 +CJK UNIFIED IDEOGRAPH:'AC6A:44138:柙 +CJK UNIFIED IDEOGRAPH:'AC6B:44139:柢 +CJK UNIFIED IDEOGRAPH:'AC6C:44140:柝 +CJK UNIFIED IDEOGRAPH:'AC6D:44141:柒 +CJK UNIFIED IDEOGRAPH:'AC6E:44142:歪 +CJK UNIFIED IDEOGRAPH:'AC6F:44143:殃 +CJK UNIFIED IDEOGRAPH:'AC70:44144:殆 +CJK UNIFIED IDEOGRAPH:'AC71:44145:段 +CJK UNIFIED IDEOGRAPH:'AC72:44146:毒 +CJK UNIFIED IDEOGRAPH:'AC73:44147:毗 +CJK UNIFIED IDEOGRAPH:'AC74:44148:氟 +CJK UNIFIED IDEOGRAPH:'AC75:44149:泉 +CJK UNIFIED IDEOGRAPH:'AC76:44150:洋 +CJK UNIFIED IDEOGRAPH:'AC77:44151:洲 +CJK UNIFIED IDEOGRAPH:'AC78:44152:洪 +CJK UNIFIED IDEOGRAPH:'AC79:44153:流 +CJK UNIFIED IDEOGRAPH:'AC7A:44154:津 +CJK UNIFIED IDEOGRAPH:'AC7B:44155:洌 +CJK UNIFIED IDEOGRAPH:'AC7C:44156:洱 +CJK UNIFIED IDEOGRAPH:'AC7D:44157:洞 +CJK UNIFIED IDEOGRAPH:'AC7E:44158:洗 +CJK UNIFIED IDEOGRAPH:'ACA1:44193:活 +CJK UNIFIED IDEOGRAPH:'ACA2:44194:洽 +CJK UNIFIED IDEOGRAPH:'ACA3:44195:派 +CJK UNIFIED IDEOGRAPH:'ACA4:44196:洶 +CJK UNIFIED IDEOGRAPH:'ACA5:44197:洛 +CJK UNIFIED IDEOGRAPH:'ACA6:44198:泵 +CJK UNIFIED IDEOGRAPH:'ACA7:44199:洹 +CJK UNIFIED IDEOGRAPH:'ACA8:44200:洧 +CJK UNIFIED IDEOGRAPH:'ACA9:44201:洸 +CJK UNIFIED IDEOGRAPH:'ACAA:44202:洩 +CJK UNIFIED IDEOGRAPH:'ACAB:44203:洮 +CJK UNIFIED IDEOGRAPH:'ACAC:44204:洵 +CJK UNIFIED IDEOGRAPH:'ACAD:44205:洎 +CJK UNIFIED IDEOGRAPH:'ACAE:44206:洫 +CJK UNIFIED IDEOGRAPH:'ACAF:44207:炫 +CJK UNIFIED IDEOGRAPH:'ACB0:44208:為 +CJK UNIFIED IDEOGRAPH:'ACB1:44209:炳 +CJK UNIFIED IDEOGRAPH:'ACB2:44210:炬 +CJK UNIFIED IDEOGRAPH:'ACB3:44211:炯 +CJK UNIFIED IDEOGRAPH:'ACB4:44212:炭 +CJK UNIFIED IDEOGRAPH:'ACB5:44213:炸 +CJK UNIFIED IDEOGRAPH:'ACB6:44214:炮 +CJK UNIFIED IDEOGRAPH:'ACB7:44215:炤 +CJK UNIFIED IDEOGRAPH:'ACB8:44216:爰 +CJK UNIFIED IDEOGRAPH:'ACB9:44217:牲 +CJK UNIFIED IDEOGRAPH:'ACBA:44218:牯 +CJK UNIFIED IDEOGRAPH:'ACBB:44219:牴 +CJK UNIFIED IDEOGRAPH:'ACBC:44220:狩 +CJK UNIFIED IDEOGRAPH:'ACBD:44221:狠 +CJK UNIFIED IDEOGRAPH:'ACBE:44222:狡 +CJK UNIFIED IDEOGRAPH:'ACBF:44223:玷 +CJK UNIFIED IDEOGRAPH:'ACC0:44224:珊 +CJK UNIFIED IDEOGRAPH:'ACC1:44225:玻 +CJK UNIFIED IDEOGRAPH:'ACC2:44226:玲 +CJK UNIFIED IDEOGRAPH:'ACC3:44227:珍 +CJK UNIFIED IDEOGRAPH:'ACC4:44228:珀 +CJK UNIFIED IDEOGRAPH:'ACC5:44229:玳 +CJK UNIFIED IDEOGRAPH:'ACC6:44230:甚 +CJK UNIFIED IDEOGRAPH:'ACC7:44231:甭 +CJK UNIFIED IDEOGRAPH:'ACC8:44232:畏 +CJK UNIFIED IDEOGRAPH:'ACC9:44233:界 +CJK UNIFIED IDEOGRAPH:'ACCA:44234:畎 +CJK UNIFIED IDEOGRAPH:'ACCB:44235:畋 +CJK UNIFIED IDEOGRAPH:'ACCC:44236:疫 +CJK UNIFIED IDEOGRAPH:'ACCD:44237:疤 +CJK UNIFIED IDEOGRAPH:'ACCE:44238:疥 +CJK UNIFIED IDEOGRAPH:'ACCF:44239:疢 +CJK UNIFIED IDEOGRAPH:'ACD0:44240:疣 +CJK UNIFIED IDEOGRAPH:'ACD1:44241:癸 +CJK UNIFIED IDEOGRAPH:'ACD2:44242:皆 +CJK UNIFIED IDEOGRAPH:'ACD3:44243:皇 +CJK UNIFIED IDEOGRAPH:'ACD4:44244:皈 +CJK UNIFIED IDEOGRAPH:'ACD5:44245:盈 +CJK UNIFIED IDEOGRAPH:'ACD6:44246:盆 +CJK UNIFIED IDEOGRAPH:'ACD7:44247:盃 +CJK UNIFIED IDEOGRAPH:'ACD8:44248:盅 +CJK UNIFIED IDEOGRAPH:'ACD9:44249:省 +CJK UNIFIED IDEOGRAPH:'ACDA:44250:盹 +CJK UNIFIED IDEOGRAPH:'ACDB:44251:相 +CJK UNIFIED IDEOGRAPH:'ACDC:44252:眉 +CJK UNIFIED IDEOGRAPH:'ACDD:44253:看 +CJK UNIFIED IDEOGRAPH:'ACDE:44254:盾 +CJK UNIFIED IDEOGRAPH:'ACDF:44255:盼 +CJK UNIFIED IDEOGRAPH:'ACE0:44256:眇 +CJK UNIFIED IDEOGRAPH:'ACE1:44257:矜 +CJK UNIFIED IDEOGRAPH:'ACE2:44258:砂 +CJK UNIFIED IDEOGRAPH:'ACE3:44259:研 +CJK UNIFIED IDEOGRAPH:'ACE4:44260:砌 +CJK UNIFIED IDEOGRAPH:'ACE5:44261:砍 +CJK UNIFIED IDEOGRAPH:'ACE6:44262:祆 +CJK UNIFIED IDEOGRAPH:'ACE7:44263:祉 +CJK UNIFIED IDEOGRAPH:'ACE8:44264:祈 +CJK UNIFIED IDEOGRAPH:'ACE9:44265:祇 +CJK UNIFIED IDEOGRAPH:'ACEA:44266:禹 +CJK UNIFIED IDEOGRAPH:'ACEB:44267:禺 +CJK UNIFIED IDEOGRAPH:'ACEC:44268:科 +CJK UNIFIED IDEOGRAPH:'ACED:44269:秒 +CJK UNIFIED IDEOGRAPH:'ACEE:44270:秋 +CJK UNIFIED IDEOGRAPH:'ACEF:44271:穿 +CJK UNIFIED IDEOGRAPH:'ACF0:44272:突 +CJK UNIFIED IDEOGRAPH:'ACF1:44273:竿 +CJK UNIFIED IDEOGRAPH:'ACF2:44274:竽 +CJK UNIFIED IDEOGRAPH:'ACF3:44275:籽 +CJK UNIFIED IDEOGRAPH:'ACF4:44276:紂 +CJK UNIFIED IDEOGRAPH:'ACF5:44277:紅 +CJK UNIFIED IDEOGRAPH:'ACF6:44278:紀 +CJK UNIFIED IDEOGRAPH:'ACF7:44279:紉 +CJK UNIFIED IDEOGRAPH:'ACF8:44280:紇 +CJK UNIFIED IDEOGRAPH:'ACF9:44281:約 +CJK UNIFIED IDEOGRAPH:'ACFA:44282:紆 +CJK UNIFIED IDEOGRAPH:'ACFB:44283:缸 +CJK UNIFIED IDEOGRAPH:'ACFC:44284:美 +CJK UNIFIED IDEOGRAPH:'ACFD:44285:羿 +CJK UNIFIED IDEOGRAPH:'ACFE:44286:耄 +CJK UNIFIED IDEOGRAPH:'AD40:44352:耐 +CJK UNIFIED IDEOGRAPH:'AD41:44353:耍 +CJK UNIFIED IDEOGRAPH:'AD42:44354:耑 +CJK UNIFIED IDEOGRAPH:'AD43:44355:耶 +CJK UNIFIED IDEOGRAPH:'AD44:44356:胖 +CJK UNIFIED IDEOGRAPH:'AD45:44357:胥 +CJK UNIFIED IDEOGRAPH:'AD46:44358:胚 +CJK UNIFIED IDEOGRAPH:'AD47:44359:胃 +CJK UNIFIED IDEOGRAPH:'AD48:44360:胄 +CJK UNIFIED IDEOGRAPH:'AD49:44361:背 +CJK UNIFIED IDEOGRAPH:'AD4A:44362:胡 +CJK UNIFIED IDEOGRAPH:'AD4B:44363:胛 +CJK UNIFIED IDEOGRAPH:'AD4C:44364:胎 +CJK UNIFIED IDEOGRAPH:'AD4D:44365:胞 +CJK UNIFIED IDEOGRAPH:'AD4E:44366:胤 +CJK UNIFIED IDEOGRAPH:'AD4F:44367:胝 +CJK UNIFIED IDEOGRAPH:'AD50:44368:致 +CJK UNIFIED IDEOGRAPH:'AD51:44369:舢 +CJK UNIFIED IDEOGRAPH:'AD52:44370:苧 +CJK UNIFIED IDEOGRAPH:'AD53:44371:范 +CJK UNIFIED IDEOGRAPH:'AD54:44372:茅 +CJK UNIFIED IDEOGRAPH:'AD55:44373:苣 +CJK UNIFIED IDEOGRAPH:'AD56:44374:苛 +CJK UNIFIED IDEOGRAPH:'AD57:44375:苦 +CJK UNIFIED IDEOGRAPH:'AD58:44376:茄 +CJK UNIFIED IDEOGRAPH:'AD59:44377:若 +CJK UNIFIED IDEOGRAPH:'AD5A:44378:茂 +CJK UNIFIED IDEOGRAPH:'AD5B:44379:茉 +CJK UNIFIED IDEOGRAPH:'AD5C:44380:苒 +CJK UNIFIED IDEOGRAPH:'AD5D:44381:苗 +CJK UNIFIED IDEOGRAPH:'AD5E:44382:英 +CJK UNIFIED IDEOGRAPH:'AD5F:44383:茁 +CJK UNIFIED IDEOGRAPH:'AD60:44384:苜 +CJK UNIFIED IDEOGRAPH:'AD61:44385:苔 +CJK UNIFIED IDEOGRAPH:'AD62:44386:苑 +CJK UNIFIED IDEOGRAPH:'AD63:44387:苞 +CJK UNIFIED IDEOGRAPH:'AD64:44388:苓 +CJK UNIFIED IDEOGRAPH:'AD65:44389:苟 +CJK UNIFIED IDEOGRAPH:'AD66:44390:苯 +CJK UNIFIED IDEOGRAPH:'AD67:44391:茆 +CJK UNIFIED IDEOGRAPH:'AD68:44392:虐 +CJK UNIFIED IDEOGRAPH:'AD69:44393:虹 +CJK UNIFIED IDEOGRAPH:'AD6A:44394:虻 +CJK UNIFIED IDEOGRAPH:'AD6B:44395:虺 +CJK UNIFIED IDEOGRAPH:'AD6C:44396:衍 +CJK UNIFIED IDEOGRAPH:'AD6D:44397:衫 +CJK UNIFIED IDEOGRAPH:'AD6E:44398:要 +CJK UNIFIED IDEOGRAPH:'AD6F:44399:觔 +CJK UNIFIED IDEOGRAPH:'AD70:44400:計 +CJK UNIFIED IDEOGRAPH:'AD71:44401:訂 +CJK UNIFIED IDEOGRAPH:'AD72:44402:訃 +CJK UNIFIED IDEOGRAPH:'AD73:44403:貞 +CJK UNIFIED IDEOGRAPH:'AD74:44404:負 +CJK UNIFIED IDEOGRAPH:'AD75:44405:赴 +CJK UNIFIED IDEOGRAPH:'AD76:44406:赳 +CJK UNIFIED IDEOGRAPH:'AD77:44407:趴 +CJK UNIFIED IDEOGRAPH:'AD78:44408:軍 +CJK UNIFIED IDEOGRAPH:'AD79:44409:軌 +CJK UNIFIED IDEOGRAPH:'AD7A:44410:述 +CJK UNIFIED IDEOGRAPH:'AD7B:44411:迦 +CJK UNIFIED IDEOGRAPH:'AD7C:44412:迢 +CJK UNIFIED IDEOGRAPH:'AD7D:44413:迪 +CJK UNIFIED IDEOGRAPH:'AD7E:44414:迥 +CJK UNIFIED IDEOGRAPH:'ADA1:44449:迭 +CJK UNIFIED IDEOGRAPH:'ADA2:44450:迫 +CJK UNIFIED IDEOGRAPH:'ADA3:44451:迤 +CJK UNIFIED IDEOGRAPH:'ADA4:44452:迨 +CJK UNIFIED IDEOGRAPH:'ADA5:44453:郊 +CJK UNIFIED IDEOGRAPH:'ADA6:44454:郎 +CJK UNIFIED IDEOGRAPH:'ADA7:44455:郁 +CJK UNIFIED IDEOGRAPH:'ADA8:44456:郃 +CJK UNIFIED IDEOGRAPH:'ADA9:44457:酋 +CJK UNIFIED IDEOGRAPH:'ADAA:44458:酊 +CJK UNIFIED IDEOGRAPH:'ADAB:44459:重 +CJK UNIFIED IDEOGRAPH:'ADAC:44460:閂 +CJK UNIFIED IDEOGRAPH:'ADAD:44461:限 +CJK UNIFIED IDEOGRAPH:'ADAE:44462:陋 +CJK UNIFIED IDEOGRAPH:'ADAF:44463:陌 +CJK UNIFIED IDEOGRAPH:'ADB0:44464:降 +CJK UNIFIED IDEOGRAPH:'ADB1:44465:面 +CJK UNIFIED IDEOGRAPH:'ADB2:44466:革 +CJK UNIFIED IDEOGRAPH:'ADB3:44467:韋 +CJK UNIFIED IDEOGRAPH:'ADB4:44468:韭 +CJK UNIFIED IDEOGRAPH:'ADB5:44469:音 +CJK UNIFIED IDEOGRAPH:'ADB6:44470:頁 +CJK UNIFIED IDEOGRAPH:'ADB7:44471:風 +CJK UNIFIED IDEOGRAPH:'ADB8:44472:飛 +CJK UNIFIED IDEOGRAPH:'ADB9:44473:食 +CJK UNIFIED IDEOGRAPH:'ADBA:44474:首 +CJK UNIFIED IDEOGRAPH:'ADBB:44475:香 +CJK UNIFIED IDEOGRAPH:'ADBC:44476:乘 +CJK UNIFIED IDEOGRAPH:'ADBD:44477:亳 +CJK UNIFIED IDEOGRAPH:'ADBE:44478:倌 +CJK UNIFIED IDEOGRAPH:'ADBF:44479:倍 +CJK UNIFIED IDEOGRAPH:'ADC0:44480:倣 +CJK UNIFIED IDEOGRAPH:'ADC1:44481:俯 +CJK UNIFIED IDEOGRAPH:'ADC2:44482:倦 +CJK UNIFIED IDEOGRAPH:'ADC3:44483:倥 +CJK UNIFIED IDEOGRAPH:'ADC4:44484:俸 +CJK UNIFIED IDEOGRAPH:'ADC5:44485:倩 +CJK UNIFIED IDEOGRAPH:'ADC6:44486:倖 +CJK UNIFIED IDEOGRAPH:'ADC7:44487:倆 +CJK UNIFIED IDEOGRAPH:'ADC8:44488:值 +CJK UNIFIED IDEOGRAPH:'ADC9:44489:借 +CJK UNIFIED IDEOGRAPH:'ADCA:44490:倚 +CJK UNIFIED IDEOGRAPH:'ADCB:44491:倒 +CJK UNIFIED IDEOGRAPH:'ADCC:44492:們 +CJK UNIFIED IDEOGRAPH:'ADCD:44493:俺 +CJK UNIFIED IDEOGRAPH:'ADCE:44494:倀 +CJK UNIFIED IDEOGRAPH:'ADCF:44495:倔 +CJK UNIFIED IDEOGRAPH:'ADD0:44496:倨 +CJK UNIFIED IDEOGRAPH:'ADD1:44497:俱 +CJK UNIFIED IDEOGRAPH:'ADD2:44498:倡 +CJK UNIFIED IDEOGRAPH:'ADD3:44499:個 +CJK UNIFIED IDEOGRAPH:'ADD4:44500:候 +CJK UNIFIED IDEOGRAPH:'ADD5:44501:倘 +CJK UNIFIED IDEOGRAPH:'ADD6:44502:俳 +CJK UNIFIED IDEOGRAPH:'ADD7:44503:修 +CJK UNIFIED IDEOGRAPH:'ADD8:44504:倭 +CJK UNIFIED IDEOGRAPH:'ADD9:44505:倪 +CJK UNIFIED IDEOGRAPH:'ADDA:44506:俾 +CJK UNIFIED IDEOGRAPH:'ADDB:44507:倫 +CJK UNIFIED IDEOGRAPH:'ADDC:44508:倉 +CJK UNIFIED IDEOGRAPH:'ADDD:44509:兼 +CJK UNIFIED IDEOGRAPH:'ADDE:44510:冤 +CJK UNIFIED IDEOGRAPH:'ADDF:44511:冥 +CJK UNIFIED IDEOGRAPH:'ADE0:44512:冢 +CJK UNIFIED IDEOGRAPH:'ADE1:44513:凍 +CJK UNIFIED IDEOGRAPH:'ADE2:44514:凌 +CJK UNIFIED IDEOGRAPH:'ADE3:44515:准 +CJK UNIFIED IDEOGRAPH:'ADE4:44516:凋 +CJK UNIFIED IDEOGRAPH:'ADE5:44517:剖 +CJK UNIFIED IDEOGRAPH:'ADE6:44518:剜 +CJK UNIFIED IDEOGRAPH:'ADE7:44519:剔 +CJK UNIFIED IDEOGRAPH:'ADE8:44520:剛 +CJK UNIFIED IDEOGRAPH:'ADE9:44521:剝 +CJK UNIFIED IDEOGRAPH:'ADEA:44522:匪 +CJK UNIFIED IDEOGRAPH:'ADEB:44523:卿 +CJK UNIFIED IDEOGRAPH:'ADEC:44524:原 +CJK UNIFIED IDEOGRAPH:'ADED:44525:厝 +CJK UNIFIED IDEOGRAPH:'ADEE:44526:叟 +CJK UNIFIED IDEOGRAPH:'ADEF:44527:哨 +CJK UNIFIED IDEOGRAPH:'ADF0:44528:唐 +CJK UNIFIED IDEOGRAPH:'ADF1:44529:唁 +CJK UNIFIED IDEOGRAPH:'ADF2:44530:唷 +CJK UNIFIED IDEOGRAPH:'ADF3:44531:哼 +CJK UNIFIED IDEOGRAPH:'ADF4:44532:哥 +CJK UNIFIED IDEOGRAPH:'ADF5:44533:哲 +CJK UNIFIED IDEOGRAPH:'ADF6:44534:唆 +CJK UNIFIED IDEOGRAPH:'ADF7:44535:哺 +CJK UNIFIED IDEOGRAPH:'ADF8:44536:唔 +CJK UNIFIED IDEOGRAPH:'ADF9:44537:哩 +CJK UNIFIED IDEOGRAPH:'ADFA:44538:哭 +CJK UNIFIED IDEOGRAPH:'ADFB:44539:員 +CJK UNIFIED IDEOGRAPH:'ADFC:44540:唉 +CJK UNIFIED IDEOGRAPH:'ADFD:44541:哮 +CJK UNIFIED IDEOGRAPH:'ADFE:44542:哪 +CJK UNIFIED IDEOGRAPH:'AE40:44608:哦 +CJK UNIFIED IDEOGRAPH:'AE41:44609:唧 +CJK UNIFIED IDEOGRAPH:'AE42:44610:唇 +CJK UNIFIED IDEOGRAPH:'AE43:44611:哽 +CJK UNIFIED IDEOGRAPH:'AE44:44612:唏 +CJK UNIFIED IDEOGRAPH:'AE45:44613:圃 +CJK UNIFIED IDEOGRAPH:'AE46:44614:圄 +CJK UNIFIED IDEOGRAPH:'AE47:44615:埂 +CJK UNIFIED IDEOGRAPH:'AE48:44616:埔 +CJK UNIFIED IDEOGRAPH:'AE49:44617:埋 +CJK UNIFIED IDEOGRAPH:'AE4A:44618:埃 +CJK UNIFIED IDEOGRAPH:'AE4B:44619:堉 +CJK UNIFIED IDEOGRAPH:'AE4C:44620:夏 +CJK UNIFIED IDEOGRAPH:'AE4D:44621:套 +CJK UNIFIED IDEOGRAPH:'AE4E:44622:奘 +CJK UNIFIED IDEOGRAPH:'AE4F:44623:奚 +CJK UNIFIED IDEOGRAPH:'AE50:44624:娑 +CJK UNIFIED IDEOGRAPH:'AE51:44625:娘 +CJK UNIFIED IDEOGRAPH:'AE52:44626:娜 +CJK UNIFIED IDEOGRAPH:'AE53:44627:娟 +CJK UNIFIED IDEOGRAPH:'AE54:44628:娛 +CJK UNIFIED IDEOGRAPH:'AE55:44629:娓 +CJK UNIFIED IDEOGRAPH:'AE56:44630:姬 +CJK UNIFIED IDEOGRAPH:'AE57:44631:娠 +CJK UNIFIED IDEOGRAPH:'AE58:44632:娣 +CJK UNIFIED IDEOGRAPH:'AE59:44633:娩 +CJK UNIFIED IDEOGRAPH:'AE5A:44634:娥 +CJK UNIFIED IDEOGRAPH:'AE5B:44635:娌 +CJK UNIFIED IDEOGRAPH:'AE5C:44636:娉 +CJK UNIFIED IDEOGRAPH:'AE5D:44637:孫 +CJK UNIFIED IDEOGRAPH:'AE5E:44638:屘 +CJK UNIFIED IDEOGRAPH:'AE5F:44639:宰 +CJK UNIFIED IDEOGRAPH:'AE60:44640:害 +CJK UNIFIED IDEOGRAPH:'AE61:44641:家 +CJK UNIFIED IDEOGRAPH:'AE62:44642:宴 +CJK UNIFIED IDEOGRAPH:'AE63:44643:宮 +CJK UNIFIED IDEOGRAPH:'AE64:44644:宵 +CJK UNIFIED IDEOGRAPH:'AE65:44645:容 +CJK UNIFIED IDEOGRAPH:'AE66:44646:宸 +CJK UNIFIED IDEOGRAPH:'AE67:44647:射 +CJK UNIFIED IDEOGRAPH:'AE68:44648:屑 +CJK UNIFIED IDEOGRAPH:'AE69:44649:展 +CJK UNIFIED IDEOGRAPH:'AE6A:44650:屐 +CJK UNIFIED IDEOGRAPH:'AE6B:44651:峭 +CJK UNIFIED IDEOGRAPH:'AE6C:44652:峽 +CJK UNIFIED IDEOGRAPH:'AE6D:44653:峻 +CJK UNIFIED IDEOGRAPH:'AE6E:44654:峪 +CJK UNIFIED IDEOGRAPH:'AE6F:44655:峨 +CJK UNIFIED IDEOGRAPH:'AE70:44656:峰 +CJK UNIFIED IDEOGRAPH:'AE71:44657:島 +CJK UNIFIED IDEOGRAPH:'AE72:44658:崁 +CJK UNIFIED IDEOGRAPH:'AE73:44659:峴 +CJK UNIFIED IDEOGRAPH:'AE74:44660:差 +CJK UNIFIED IDEOGRAPH:'AE75:44661:席 +CJK UNIFIED IDEOGRAPH:'AE76:44662:師 +CJK UNIFIED IDEOGRAPH:'AE77:44663:庫 +CJK UNIFIED IDEOGRAPH:'AE78:44664:庭 +CJK UNIFIED IDEOGRAPH:'AE79:44665:座 +CJK UNIFIED IDEOGRAPH:'AE7A:44666:弱 +CJK UNIFIED IDEOGRAPH:'AE7B:44667:徒 +CJK UNIFIED IDEOGRAPH:'AE7C:44668:徑 +CJK UNIFIED IDEOGRAPH:'AE7D:44669:徐 +CJK UNIFIED IDEOGRAPH:'AE7E:44670:恙 +CJK UNIFIED IDEOGRAPH:'AEA1:44705:恣 +CJK UNIFIED IDEOGRAPH:'AEA2:44706:恥 +CJK UNIFIED IDEOGRAPH:'AEA3:44707:恐 +CJK UNIFIED IDEOGRAPH:'AEA4:44708:恕 +CJK UNIFIED IDEOGRAPH:'AEA5:44709:恭 +CJK UNIFIED IDEOGRAPH:'AEA6:44710:恩 +CJK UNIFIED IDEOGRAPH:'AEA7:44711:息 +CJK UNIFIED IDEOGRAPH:'AEA8:44712:悄 +CJK UNIFIED IDEOGRAPH:'AEA9:44713:悟 +CJK UNIFIED IDEOGRAPH:'AEAA:44714:悚 +CJK UNIFIED IDEOGRAPH:'AEAB:44715:悍 +CJK UNIFIED IDEOGRAPH:'AEAC:44716:悔 +CJK UNIFIED IDEOGRAPH:'AEAD:44717:悌 +CJK UNIFIED IDEOGRAPH:'AEAE:44718:悅 +CJK UNIFIED IDEOGRAPH:'AEAF:44719:悖 +CJK UNIFIED IDEOGRAPH:'AEB0:44720:扇 +CJK UNIFIED IDEOGRAPH:'AEB1:44721:拳 +CJK UNIFIED IDEOGRAPH:'AEB2:44722:挈 +CJK UNIFIED IDEOGRAPH:'AEB3:44723:拿 +CJK UNIFIED IDEOGRAPH:'AEB4:44724:捎 +CJK UNIFIED IDEOGRAPH:'AEB5:44725:挾 +CJK UNIFIED IDEOGRAPH:'AEB6:44726:振 +CJK UNIFIED IDEOGRAPH:'AEB7:44727:捕 +CJK UNIFIED IDEOGRAPH:'AEB8:44728:捂 +CJK UNIFIED IDEOGRAPH:'AEB9:44729:捆 +CJK UNIFIED IDEOGRAPH:'AEBA:44730:捏 +CJK UNIFIED IDEOGRAPH:'AEBB:44731:捉 +CJK UNIFIED IDEOGRAPH:'AEBC:44732:挺 +CJK UNIFIED IDEOGRAPH:'AEBD:44733:捐 +CJK UNIFIED IDEOGRAPH:'AEBE:44734:挽 +CJK UNIFIED IDEOGRAPH:'AEBF:44735:挪 +CJK UNIFIED IDEOGRAPH:'AEC0:44736:挫 +CJK UNIFIED IDEOGRAPH:'AEC1:44737:挨 +CJK UNIFIED IDEOGRAPH:'AEC2:44738:捍 +CJK UNIFIED IDEOGRAPH:'AEC3:44739:捌 +CJK UNIFIED IDEOGRAPH:'AEC4:44740:效 +CJK UNIFIED IDEOGRAPH:'AEC5:44741:敉 +CJK UNIFIED IDEOGRAPH:'AEC6:44742:料 +CJK UNIFIED IDEOGRAPH:'AEC7:44743:旁 +CJK UNIFIED IDEOGRAPH:'AEC8:44744:旅 +CJK UNIFIED IDEOGRAPH:'AEC9:44745:時 +CJK UNIFIED IDEOGRAPH:'AECA:44746:晉 +CJK UNIFIED IDEOGRAPH:'AECB:44747:晏 +CJK UNIFIED IDEOGRAPH:'AECC:44748:晃 +CJK UNIFIED IDEOGRAPH:'AECD:44749:晒 +CJK UNIFIED IDEOGRAPH:'AECE:44750:晌 +CJK UNIFIED IDEOGRAPH:'AECF:44751:晅 +CJK UNIFIED IDEOGRAPH:'AED0:44752:晁 +CJK UNIFIED IDEOGRAPH:'AED1:44753:書 +CJK UNIFIED IDEOGRAPH:'AED2:44754:朔 +CJK UNIFIED IDEOGRAPH:'AED3:44755:朕 +CJK UNIFIED IDEOGRAPH:'AED4:44756:朗 +CJK UNIFIED IDEOGRAPH:'AED5:44757:校 +CJK UNIFIED IDEOGRAPH:'AED6:44758:核 +CJK UNIFIED IDEOGRAPH:'AED7:44759:案 +CJK UNIFIED IDEOGRAPH:'AED8:44760:框 +CJK UNIFIED IDEOGRAPH:'AED9:44761:桓 +CJK UNIFIED IDEOGRAPH:'AEDA:44762:根 +CJK UNIFIED IDEOGRAPH:'AEDB:44763:桂 +CJK UNIFIED IDEOGRAPH:'AEDC:44764:桔 +CJK UNIFIED IDEOGRAPH:'AEDD:44765:栩 +CJK UNIFIED IDEOGRAPH:'AEDE:44766:梳 +CJK UNIFIED IDEOGRAPH:'AEDF:44767:栗 +CJK UNIFIED IDEOGRAPH:'AEE0:44768:桌 +CJK UNIFIED IDEOGRAPH:'AEE1:44769:桑 +CJK UNIFIED IDEOGRAPH:'AEE2:44770:栽 +CJK UNIFIED IDEOGRAPH:'AEE3:44771:柴 +CJK UNIFIED IDEOGRAPH:'AEE4:44772:桐 +CJK UNIFIED IDEOGRAPH:'AEE5:44773:桀 +CJK UNIFIED IDEOGRAPH:'AEE6:44774:格 +CJK UNIFIED IDEOGRAPH:'AEE7:44775:桃 +CJK UNIFIED IDEOGRAPH:'AEE8:44776:株 +CJK UNIFIED IDEOGRAPH:'AEE9:44777:桅 +CJK UNIFIED IDEOGRAPH:'AEEA:44778:栓 +CJK UNIFIED IDEOGRAPH:'AEEB:44779:栘 +CJK UNIFIED IDEOGRAPH:'AEEC:44780:桁 +CJK UNIFIED IDEOGRAPH:'AEED:44781:殊 +CJK UNIFIED IDEOGRAPH:'AEEE:44782:殉 +CJK UNIFIED IDEOGRAPH:'AEEF:44783:殷 +CJK UNIFIED IDEOGRAPH:'AEF0:44784:氣 +CJK UNIFIED IDEOGRAPH:'AEF1:44785:氧 +CJK UNIFIED IDEOGRAPH:'AEF2:44786:氨 +CJK UNIFIED IDEOGRAPH:'AEF3:44787:氦 +CJK UNIFIED IDEOGRAPH:'AEF4:44788:氤 +CJK UNIFIED IDEOGRAPH:'AEF5:44789:泰 +CJK UNIFIED IDEOGRAPH:'AEF6:44790:浪 +CJK UNIFIED IDEOGRAPH:'AEF7:44791:涕 +CJK UNIFIED IDEOGRAPH:'AEF8:44792:消 +CJK UNIFIED IDEOGRAPH:'AEF9:44793:涇 +CJK UNIFIED IDEOGRAPH:'AEFA:44794:浦 +CJK UNIFIED IDEOGRAPH:'AEFB:44795:浸 +CJK UNIFIED IDEOGRAPH:'AEFC:44796:海 +CJK UNIFIED IDEOGRAPH:'AEFD:44797:浙 +CJK UNIFIED IDEOGRAPH:'AEFE:44798:涓 +CJK UNIFIED IDEOGRAPH:'AF40:44864:浬 +CJK UNIFIED IDEOGRAPH:'AF41:44865:涉 +CJK UNIFIED IDEOGRAPH:'AF42:44866:浮 +CJK UNIFIED IDEOGRAPH:'AF43:44867:浚 +CJK UNIFIED IDEOGRAPH:'AF44:44868:浴 +CJK UNIFIED IDEOGRAPH:'AF45:44869:浩 +CJK UNIFIED IDEOGRAPH:'AF46:44870:涌 +CJK UNIFIED IDEOGRAPH:'AF47:44871:涊 +CJK UNIFIED IDEOGRAPH:'AF48:44872:浹 +CJK UNIFIED IDEOGRAPH:'AF49:44873:涅 +CJK UNIFIED IDEOGRAPH:'AF4A:44874:浥 +CJK UNIFIED IDEOGRAPH:'AF4B:44875:涔 +CJK UNIFIED IDEOGRAPH:'AF4C:44876:烊 +CJK UNIFIED IDEOGRAPH:'AF4D:44877:烘 +CJK UNIFIED IDEOGRAPH:'AF4E:44878:烤 +CJK UNIFIED IDEOGRAPH:'AF4F:44879:烙 +CJK UNIFIED IDEOGRAPH:'AF50:44880:烈 +CJK UNIFIED IDEOGRAPH:'AF51:44881:烏 +CJK UNIFIED IDEOGRAPH:'AF52:44882:爹 +CJK UNIFIED IDEOGRAPH:'AF53:44883:特 +CJK UNIFIED IDEOGRAPH:'AF54:44884:狼 +CJK UNIFIED IDEOGRAPH:'AF55:44885:狹 +CJK UNIFIED IDEOGRAPH:'AF56:44886:狽 +CJK UNIFIED IDEOGRAPH:'AF57:44887:狸 +CJK UNIFIED IDEOGRAPH:'AF58:44888:狷 +CJK UNIFIED IDEOGRAPH:'AF59:44889:玆 +CJK UNIFIED IDEOGRAPH:'AF5A:44890:班 +CJK UNIFIED IDEOGRAPH:'AF5B:44891:琉 +CJK UNIFIED IDEOGRAPH:'AF5C:44892:珮 +CJK UNIFIED IDEOGRAPH:'AF5D:44893:珠 +CJK UNIFIED IDEOGRAPH:'AF5E:44894:珪 +CJK UNIFIED IDEOGRAPH:'AF5F:44895:珞 +CJK UNIFIED IDEOGRAPH:'AF60:44896:畔 +CJK UNIFIED IDEOGRAPH:'AF61:44897:畝 +CJK UNIFIED IDEOGRAPH:'AF62:44898:畜 +CJK UNIFIED IDEOGRAPH:'AF63:44899:畚 +CJK UNIFIED IDEOGRAPH:'AF64:44900:留 +CJK UNIFIED IDEOGRAPH:'AF65:44901:疾 +CJK UNIFIED IDEOGRAPH:'AF66:44902:病 +CJK UNIFIED IDEOGRAPH:'AF67:44903:症 +CJK UNIFIED IDEOGRAPH:'AF68:44904:疲 +CJK UNIFIED IDEOGRAPH:'AF69:44905:疳 +CJK UNIFIED IDEOGRAPH:'AF6A:44906:疽 +CJK UNIFIED IDEOGRAPH:'AF6B:44907:疼 +CJK UNIFIED IDEOGRAPH:'AF6C:44908:疹 +CJK UNIFIED IDEOGRAPH:'AF6D:44909:痂 +CJK UNIFIED IDEOGRAPH:'AF6E:44910:疸 +CJK UNIFIED IDEOGRAPH:'AF6F:44911:皋 +CJK UNIFIED IDEOGRAPH:'AF70:44912:皰 +CJK UNIFIED IDEOGRAPH:'AF71:44913:益 +CJK UNIFIED IDEOGRAPH:'AF72:44914:盍 +CJK UNIFIED IDEOGRAPH:'AF73:44915:盎 +CJK UNIFIED IDEOGRAPH:'AF74:44916:眩 +CJK UNIFIED IDEOGRAPH:'AF75:44917:真 +CJK UNIFIED IDEOGRAPH:'AF76:44918:眠 +CJK UNIFIED IDEOGRAPH:'AF77:44919:眨 +CJK UNIFIED IDEOGRAPH:'AF78:44920:矩 +CJK UNIFIED IDEOGRAPH:'AF79:44921:砰 +CJK UNIFIED IDEOGRAPH:'AF7A:44922:砧 +CJK UNIFIED IDEOGRAPH:'AF7B:44923:砸 +CJK UNIFIED IDEOGRAPH:'AF7C:44924:砝 +CJK UNIFIED IDEOGRAPH:'AF7D:44925:破 +CJK UNIFIED IDEOGRAPH:'AF7E:44926:砷 +CJK UNIFIED IDEOGRAPH:'AFA1:44961:砥 +CJK UNIFIED IDEOGRAPH:'AFA2:44962:砭 +CJK UNIFIED IDEOGRAPH:'AFA3:44963:砠 +CJK UNIFIED IDEOGRAPH:'AFA4:44964:砟 +CJK UNIFIED IDEOGRAPH:'AFA5:44965:砲 +CJK UNIFIED IDEOGRAPH:'AFA6:44966:祕 +CJK UNIFIED IDEOGRAPH:'AFA7:44967:祐 +CJK UNIFIED IDEOGRAPH:'AFA8:44968:祠 +CJK UNIFIED IDEOGRAPH:'AFA9:44969:祟 +CJK UNIFIED IDEOGRAPH:'AFAA:44970:祖 +CJK UNIFIED IDEOGRAPH:'AFAB:44971:神 +CJK UNIFIED IDEOGRAPH:'AFAC:44972:祝 +CJK UNIFIED IDEOGRAPH:'AFAD:44973:祗 +CJK UNIFIED IDEOGRAPH:'AFAE:44974:祚 +CJK UNIFIED IDEOGRAPH:'AFAF:44975:秤 +CJK UNIFIED IDEOGRAPH:'AFB0:44976:秣 +CJK UNIFIED IDEOGRAPH:'AFB1:44977:秧 +CJK UNIFIED IDEOGRAPH:'AFB2:44978:租 +CJK UNIFIED IDEOGRAPH:'AFB3:44979:秦 +CJK UNIFIED IDEOGRAPH:'AFB4:44980:秩 +CJK UNIFIED IDEOGRAPH:'AFB5:44981:秘 +CJK UNIFIED IDEOGRAPH:'AFB6:44982:窄 +CJK UNIFIED IDEOGRAPH:'AFB7:44983:窈 +CJK UNIFIED IDEOGRAPH:'AFB8:44984:站 +CJK UNIFIED IDEOGRAPH:'AFB9:44985:笆 +CJK UNIFIED IDEOGRAPH:'AFBA:44986:笑 +CJK UNIFIED IDEOGRAPH:'AFBB:44987:粉 +CJK UNIFIED IDEOGRAPH:'AFBC:44988:紡 +CJK UNIFIED IDEOGRAPH:'AFBD:44989:紗 +CJK UNIFIED IDEOGRAPH:'AFBE:44990:紋 +CJK UNIFIED IDEOGRAPH:'AFBF:44991:紊 +CJK UNIFIED IDEOGRAPH:'AFC0:44992:素 +CJK UNIFIED IDEOGRAPH:'AFC1:44993:索 +CJK UNIFIED IDEOGRAPH:'AFC2:44994:純 +CJK UNIFIED IDEOGRAPH:'AFC3:44995:紐 +CJK UNIFIED IDEOGRAPH:'AFC4:44996:紕 +CJK UNIFIED IDEOGRAPH:'AFC5:44997:級 +CJK UNIFIED IDEOGRAPH:'AFC6:44998:紜 +CJK UNIFIED IDEOGRAPH:'AFC7:44999:納 +CJK UNIFIED IDEOGRAPH:'AFC8:45000:紙 +CJK UNIFIED IDEOGRAPH:'AFC9:45001:紛 +CJK UNIFIED IDEOGRAPH:'AFCA:45002:缺 +CJK UNIFIED IDEOGRAPH:'AFCB:45003:罟 +CJK UNIFIED IDEOGRAPH:'AFCC:45004:羔 +CJK UNIFIED IDEOGRAPH:'AFCD:45005:翅 +CJK UNIFIED IDEOGRAPH:'AFCE:45006:翁 +CJK UNIFIED IDEOGRAPH:'AFCF:45007:耆 +CJK UNIFIED IDEOGRAPH:'AFD0:45008:耘 +CJK UNIFIED IDEOGRAPH:'AFD1:45009:耕 +CJK UNIFIED IDEOGRAPH:'AFD2:45010:耙 +CJK UNIFIED IDEOGRAPH:'AFD3:45011:耗 +CJK UNIFIED IDEOGRAPH:'AFD4:45012:耽 +CJK UNIFIED IDEOGRAPH:'AFD5:45013:耿 +CJK UNIFIED IDEOGRAPH:'AFD6:45014:胱 +CJK UNIFIED IDEOGRAPH:'AFD7:45015:脂 +CJK UNIFIED IDEOGRAPH:'AFD8:45016:胰 +CJK UNIFIED IDEOGRAPH:'AFD9:45017:脅 +CJK UNIFIED IDEOGRAPH:'AFDA:45018:胭 +CJK UNIFIED IDEOGRAPH:'AFDB:45019:胴 +CJK UNIFIED IDEOGRAPH:'AFDC:45020:脆 +CJK UNIFIED IDEOGRAPH:'AFDD:45021:胸 +CJK UNIFIED IDEOGRAPH:'AFDE:45022:胳 +CJK UNIFIED IDEOGRAPH:'AFDF:45023:脈 +CJK UNIFIED IDEOGRAPH:'AFE0:45024:能 +CJK UNIFIED IDEOGRAPH:'AFE1:45025:脊 +CJK UNIFIED IDEOGRAPH:'AFE2:45026:胼 +CJK UNIFIED IDEOGRAPH:'AFE3:45027:胯 +CJK UNIFIED IDEOGRAPH:'AFE4:45028:臭 +CJK UNIFIED IDEOGRAPH:'AFE5:45029:臬 +CJK UNIFIED IDEOGRAPH:'AFE6:45030:舀 +CJK UNIFIED IDEOGRAPH:'AFE7:45031:舐 +CJK UNIFIED IDEOGRAPH:'AFE8:45032:航 +CJK UNIFIED IDEOGRAPH:'AFE9:45033:舫 +CJK UNIFIED IDEOGRAPH:'AFEA:45034:舨 +CJK UNIFIED IDEOGRAPH:'AFEB:45035:般 +CJK UNIFIED IDEOGRAPH:'AFEC:45036:芻 +CJK UNIFIED IDEOGRAPH:'AFED:45037:茫 +CJK UNIFIED IDEOGRAPH:'AFEE:45038:荒 +CJK UNIFIED IDEOGRAPH:'AFEF:45039:荔 +CJK UNIFIED IDEOGRAPH:'AFF0:45040:荊 +CJK UNIFIED IDEOGRAPH:'AFF1:45041:茸 +CJK UNIFIED IDEOGRAPH:'AFF2:45042:荐 +CJK UNIFIED IDEOGRAPH:'AFF3:45043:草 +CJK UNIFIED IDEOGRAPH:'AFF4:45044:茵 +CJK UNIFIED IDEOGRAPH:'AFF5:45045:茴 +CJK UNIFIED IDEOGRAPH:'AFF6:45046:荏 +CJK UNIFIED IDEOGRAPH:'AFF7:45047:茲 +CJK UNIFIED IDEOGRAPH:'AFF8:45048:茹 +CJK UNIFIED IDEOGRAPH:'AFF9:45049:茶 +CJK UNIFIED IDEOGRAPH:'AFFA:45050:茗 +CJK UNIFIED IDEOGRAPH:'AFFB:45051:荀 +CJK UNIFIED IDEOGRAPH:'AFFC:45052:茱 +CJK UNIFIED IDEOGRAPH:'AFFD:45053:茨 +CJK UNIFIED IDEOGRAPH:'AFFE:45054:荃 +CJK UNIFIED IDEOGRAPH:'B040:45120:虔 +CJK UNIFIED IDEOGRAPH:'B041:45121:蚊 +CJK UNIFIED IDEOGRAPH:'B042:45122:蚪 +CJK UNIFIED IDEOGRAPH:'B043:45123:蚓 +CJK UNIFIED IDEOGRAPH:'B044:45124:蚤 +CJK UNIFIED IDEOGRAPH:'B045:45125:蚩 +CJK UNIFIED IDEOGRAPH:'B046:45126:蚌 +CJK UNIFIED IDEOGRAPH:'B047:45127:蚣 +CJK UNIFIED IDEOGRAPH:'B048:45128:蚜 +CJK UNIFIED IDEOGRAPH:'B049:45129:衰 +CJK UNIFIED IDEOGRAPH:'B04A:45130:衷 +CJK UNIFIED IDEOGRAPH:'B04B:45131:袁 +CJK UNIFIED IDEOGRAPH:'B04C:45132:袂 +CJK UNIFIED IDEOGRAPH:'B04D:45133:衽 +CJK UNIFIED IDEOGRAPH:'B04E:45134:衹 +CJK UNIFIED IDEOGRAPH:'B04F:45135:記 +CJK UNIFIED IDEOGRAPH:'B050:45136:訐 +CJK UNIFIED IDEOGRAPH:'B051:45137:討 +CJK UNIFIED IDEOGRAPH:'B052:45138:訌 +CJK UNIFIED IDEOGRAPH:'B053:45139:訕 +CJK UNIFIED IDEOGRAPH:'B054:45140:訊 +CJK UNIFIED IDEOGRAPH:'B055:45141:託 +CJK UNIFIED IDEOGRAPH:'B056:45142:訓 +CJK UNIFIED IDEOGRAPH:'B057:45143:訖 +CJK UNIFIED IDEOGRAPH:'B058:45144:訏 +CJK UNIFIED IDEOGRAPH:'B059:45145:訑 +CJK UNIFIED IDEOGRAPH:'B05A:45146:豈 +CJK UNIFIED IDEOGRAPH:'B05B:45147:豺 +CJK UNIFIED IDEOGRAPH:'B05C:45148:豹 +CJK UNIFIED IDEOGRAPH:'B05D:45149:財 +CJK UNIFIED IDEOGRAPH:'B05E:45150:貢 +CJK UNIFIED IDEOGRAPH:'B05F:45151:起 +CJK UNIFIED IDEOGRAPH:'B060:45152:躬 +CJK UNIFIED IDEOGRAPH:'B061:45153:軒 +CJK UNIFIED IDEOGRAPH:'B062:45154:軔 +CJK UNIFIED IDEOGRAPH:'B063:45155:軏 +CJK UNIFIED IDEOGRAPH:'B064:45156:辱 +CJK UNIFIED IDEOGRAPH:'B065:45157:送 +CJK UNIFIED IDEOGRAPH:'B066:45158:逆 +CJK UNIFIED IDEOGRAPH:'B067:45159:迷 +CJK UNIFIED IDEOGRAPH:'B068:45160:退 +CJK UNIFIED IDEOGRAPH:'B069:45161:迺 +CJK UNIFIED IDEOGRAPH:'B06A:45162:迴 +CJK UNIFIED IDEOGRAPH:'B06B:45163:逃 +CJK UNIFIED IDEOGRAPH:'B06C:45164:追 +CJK UNIFIED IDEOGRAPH:'B06D:45165:逅 +CJK UNIFIED IDEOGRAPH:'B06E:45166:迸 +CJK UNIFIED IDEOGRAPH:'B06F:45167:邕 +CJK UNIFIED IDEOGRAPH:'B070:45168:郡 +CJK UNIFIED IDEOGRAPH:'B071:45169:郝 +CJK UNIFIED IDEOGRAPH:'B072:45170:郢 +CJK UNIFIED IDEOGRAPH:'B073:45171:酒 +CJK UNIFIED IDEOGRAPH:'B074:45172:配 +CJK UNIFIED IDEOGRAPH:'B075:45173:酌 +CJK UNIFIED IDEOGRAPH:'B076:45174:釘 +CJK UNIFIED IDEOGRAPH:'B077:45175:針 +CJK UNIFIED IDEOGRAPH:'B078:45176:釗 +CJK UNIFIED IDEOGRAPH:'B079:45177:釜 +CJK UNIFIED IDEOGRAPH:'B07A:45178:釙 +CJK UNIFIED IDEOGRAPH:'B07B:45179:閃 +CJK UNIFIED IDEOGRAPH:'B07C:45180:院 +CJK UNIFIED IDEOGRAPH:'B07D:45181:陣 +CJK UNIFIED IDEOGRAPH:'B07E:45182:陡 +CJK UNIFIED IDEOGRAPH:'B0A1:45217:陛 +CJK UNIFIED IDEOGRAPH:'B0A2:45218:陝 +CJK UNIFIED IDEOGRAPH:'B0A3:45219:除 +CJK UNIFIED IDEOGRAPH:'B0A4:45220:陘 +CJK UNIFIED IDEOGRAPH:'B0A5:45221:陞 +CJK UNIFIED IDEOGRAPH:'B0A6:45222:隻 +CJK UNIFIED IDEOGRAPH:'B0A7:45223:飢 +CJK UNIFIED IDEOGRAPH:'B0A8:45224:馬 +CJK UNIFIED IDEOGRAPH:'B0A9:45225:骨 +CJK UNIFIED IDEOGRAPH:'B0AA:45226:高 +CJK UNIFIED IDEOGRAPH:'B0AB:45227:鬥 +CJK UNIFIED IDEOGRAPH:'B0AC:45228:鬲 +CJK UNIFIED IDEOGRAPH:'B0AD:45229:鬼 +CJK UNIFIED IDEOGRAPH:'B0AE:45230:乾 +CJK UNIFIED IDEOGRAPH:'B0AF:45231:偺 +CJK UNIFIED IDEOGRAPH:'B0B0:45232:偽 +CJK UNIFIED IDEOGRAPH:'B0B1:45233:停 +CJK UNIFIED IDEOGRAPH:'B0B2:45234:假 +CJK UNIFIED IDEOGRAPH:'B0B3:45235:偃 +CJK UNIFIED IDEOGRAPH:'B0B4:45236:偌 +CJK UNIFIED IDEOGRAPH:'B0B5:45237:做 +CJK UNIFIED IDEOGRAPH:'B0B6:45238:偉 +CJK UNIFIED IDEOGRAPH:'B0B7:45239:健 +CJK UNIFIED IDEOGRAPH:'B0B8:45240:偶 +CJK UNIFIED IDEOGRAPH:'B0B9:45241:偎 +CJK UNIFIED IDEOGRAPH:'B0BA:45242:偕 +CJK UNIFIED IDEOGRAPH:'B0BB:45243:偵 +CJK UNIFIED IDEOGRAPH:'B0BC:45244:側 +CJK UNIFIED IDEOGRAPH:'B0BD:45245:偷 +CJK UNIFIED IDEOGRAPH:'B0BE:45246:偏 +CJK UNIFIED IDEOGRAPH:'B0BF:45247:倏 +CJK UNIFIED IDEOGRAPH:'B0C0:45248:偯 +CJK UNIFIED IDEOGRAPH:'B0C1:45249:偭 +CJK UNIFIED IDEOGRAPH:'B0C2:45250:兜 +CJK UNIFIED IDEOGRAPH:'B0C3:45251:冕 +CJK UNIFIED IDEOGRAPH:'B0C4:45252:凰 +CJK UNIFIED IDEOGRAPH:'B0C5:45253:剪 +CJK UNIFIED IDEOGRAPH:'B0C6:45254:副 +CJK UNIFIED IDEOGRAPH:'B0C7:45255:勒 +CJK UNIFIED IDEOGRAPH:'B0C8:45256:務 +CJK UNIFIED IDEOGRAPH:'B0C9:45257:勘 +CJK UNIFIED IDEOGRAPH:'B0CA:45258:動 +CJK UNIFIED IDEOGRAPH:'B0CB:45259:匐 +CJK UNIFIED IDEOGRAPH:'B0CC:45260:匏 +CJK UNIFIED IDEOGRAPH:'B0CD:45261:匙 +CJK UNIFIED IDEOGRAPH:'B0CE:45262:匿 +CJK UNIFIED IDEOGRAPH:'B0CF:45263:區 +CJK UNIFIED IDEOGRAPH:'B0D0:45264:匾 +CJK UNIFIED IDEOGRAPH:'B0D1:45265:參 +CJK UNIFIED IDEOGRAPH:'B0D2:45266:曼 +CJK UNIFIED IDEOGRAPH:'B0D3:45267:商 +CJK UNIFIED IDEOGRAPH:'B0D4:45268:啪 +CJK UNIFIED IDEOGRAPH:'B0D5:45269:啦 +CJK UNIFIED IDEOGRAPH:'B0D6:45270:啄 +CJK UNIFIED IDEOGRAPH:'B0D7:45271:啞 +CJK UNIFIED IDEOGRAPH:'B0D8:45272:啡 +CJK UNIFIED IDEOGRAPH:'B0D9:45273:啃 +CJK UNIFIED IDEOGRAPH:'B0DA:45274:啊 +CJK UNIFIED IDEOGRAPH:'B0DB:45275:唱 +CJK UNIFIED IDEOGRAPH:'B0DC:45276:啖 +CJK UNIFIED IDEOGRAPH:'B0DD:45277:問 +CJK UNIFIED IDEOGRAPH:'B0DE:45278:啕 +CJK UNIFIED IDEOGRAPH:'B0DF:45279:唯 +CJK UNIFIED IDEOGRAPH:'B0E0:45280:啤 +CJK UNIFIED IDEOGRAPH:'B0E1:45281:唸 +CJK UNIFIED IDEOGRAPH:'B0E2:45282:售 +CJK UNIFIED IDEOGRAPH:'B0E3:45283:啜 +CJK UNIFIED IDEOGRAPH:'B0E4:45284:唬 +CJK UNIFIED IDEOGRAPH:'B0E5:45285:啣 +CJK UNIFIED IDEOGRAPH:'B0E6:45286:唳 +CJK UNIFIED IDEOGRAPH:'B0E7:45287:啁 +CJK UNIFIED IDEOGRAPH:'B0E8:45288:啗 +CJK UNIFIED IDEOGRAPH:'B0E9:45289:圈 +CJK UNIFIED IDEOGRAPH:'B0EA:45290:國 +CJK UNIFIED IDEOGRAPH:'B0EB:45291:圉 +CJK UNIFIED IDEOGRAPH:'B0EC:45292:域 +CJK UNIFIED IDEOGRAPH:'B0ED:45293:堅 +CJK UNIFIED IDEOGRAPH:'B0EE:45294:堊 +CJK UNIFIED IDEOGRAPH:'B0EF:45295:堆 +CJK UNIFIED IDEOGRAPH:'B0F0:45296:埠 +CJK UNIFIED IDEOGRAPH:'B0F1:45297:埤 +CJK UNIFIED IDEOGRAPH:'B0F2:45298:基 +CJK UNIFIED IDEOGRAPH:'B0F3:45299:堂 +CJK UNIFIED IDEOGRAPH:'B0F4:45300:堵 +CJK UNIFIED IDEOGRAPH:'B0F5:45301:執 +CJK UNIFIED IDEOGRAPH:'B0F6:45302:培 +CJK UNIFIED IDEOGRAPH:'B0F7:45303:夠 +CJK UNIFIED IDEOGRAPH:'B0F8:45304:奢 +CJK UNIFIED IDEOGRAPH:'B0F9:45305:娶 +CJK UNIFIED IDEOGRAPH:'B0FA:45306:婁 +CJK UNIFIED IDEOGRAPH:'B0FB:45307:婉 +CJK UNIFIED IDEOGRAPH:'B0FC:45308:婦 +CJK UNIFIED IDEOGRAPH:'B0FD:45309:婪 +CJK UNIFIED IDEOGRAPH:'B0FE:45310:婀 +CJK UNIFIED IDEOGRAPH:'B140:45376:娼 +CJK UNIFIED IDEOGRAPH:'B141:45377:婢 +CJK UNIFIED IDEOGRAPH:'B142:45378:婚 +CJK UNIFIED IDEOGRAPH:'B143:45379:婆 +CJK UNIFIED IDEOGRAPH:'B144:45380:婊 +CJK UNIFIED IDEOGRAPH:'B145:45381:孰 +CJK UNIFIED IDEOGRAPH:'B146:45382:寇 +CJK UNIFIED IDEOGRAPH:'B147:45383:寅 +CJK UNIFIED IDEOGRAPH:'B148:45384:寄 +CJK UNIFIED IDEOGRAPH:'B149:45385:寂 +CJK UNIFIED IDEOGRAPH:'B14A:45386:宿 +CJK UNIFIED IDEOGRAPH:'B14B:45387:密 +CJK UNIFIED IDEOGRAPH:'B14C:45388:尉 +CJK UNIFIED IDEOGRAPH:'B14D:45389:專 +CJK UNIFIED IDEOGRAPH:'B14E:45390:將 +CJK UNIFIED IDEOGRAPH:'B14F:45391:屠 +CJK UNIFIED IDEOGRAPH:'B150:45392:屜 +CJK UNIFIED IDEOGRAPH:'B151:45393:屝 +CJK UNIFIED IDEOGRAPH:'B152:45394:崇 +CJK UNIFIED IDEOGRAPH:'B153:45395:崆 +CJK UNIFIED IDEOGRAPH:'B154:45396:崎 +CJK UNIFIED IDEOGRAPH:'B155:45397:崛 +CJK UNIFIED IDEOGRAPH:'B156:45398:崖 +CJK UNIFIED IDEOGRAPH:'B157:45399:崢 +CJK UNIFIED IDEOGRAPH:'B158:45400:崑 +CJK UNIFIED IDEOGRAPH:'B159:45401:崩 +CJK UNIFIED IDEOGRAPH:'B15A:45402:崔 +CJK UNIFIED IDEOGRAPH:'B15B:45403:崙 +CJK UNIFIED IDEOGRAPH:'B15C:45404:崤 +CJK UNIFIED IDEOGRAPH:'B15D:45405:崧 +CJK UNIFIED IDEOGRAPH:'B15E:45406:崗 +CJK UNIFIED IDEOGRAPH:'B15F:45407:巢 +CJK UNIFIED IDEOGRAPH:'B160:45408:常 +CJK UNIFIED IDEOGRAPH:'B161:45409:帶 +CJK UNIFIED IDEOGRAPH:'B162:45410:帳 +CJK UNIFIED IDEOGRAPH:'B163:45411:帷 +CJK UNIFIED IDEOGRAPH:'B164:45412:康 +CJK UNIFIED IDEOGRAPH:'B165:45413:庸 +CJK UNIFIED IDEOGRAPH:'B166:45414:庶 +CJK UNIFIED IDEOGRAPH:'B167:45415:庵 +CJK UNIFIED IDEOGRAPH:'B168:45416:庾 +CJK UNIFIED IDEOGRAPH:'B169:45417:張 +CJK UNIFIED IDEOGRAPH:'B16A:45418:強 +CJK UNIFIED IDEOGRAPH:'B16B:45419:彗 +CJK UNIFIED IDEOGRAPH:'B16C:45420:彬 +CJK UNIFIED IDEOGRAPH:'B16D:45421:彩 +CJK UNIFIED IDEOGRAPH:'B16E:45422:彫 +CJK UNIFIED IDEOGRAPH:'B16F:45423:得 +CJK UNIFIED IDEOGRAPH:'B170:45424:徙 +CJK UNIFIED IDEOGRAPH:'B171:45425:從 +CJK UNIFIED IDEOGRAPH:'B172:45426:徘 +CJK UNIFIED IDEOGRAPH:'B173:45427:御 +CJK UNIFIED IDEOGRAPH:'B174:45428:徠 +CJK UNIFIED IDEOGRAPH:'B175:45429:徜 +CJK UNIFIED IDEOGRAPH:'B176:45430:恿 +CJK UNIFIED IDEOGRAPH:'B177:45431:患 +CJK UNIFIED IDEOGRAPH:'B178:45432:悉 +CJK UNIFIED IDEOGRAPH:'B179:45433:悠 +CJK UNIFIED IDEOGRAPH:'B17A:45434:您 +CJK UNIFIED IDEOGRAPH:'B17B:45435:惋 +CJK UNIFIED IDEOGRAPH:'B17C:45436:悴 +CJK UNIFIED IDEOGRAPH:'B17D:45437:惦 +CJK UNIFIED IDEOGRAPH:'B17E:45438:悽 +CJK UNIFIED IDEOGRAPH:'B1A1:45473:情 +CJK UNIFIED IDEOGRAPH:'B1A2:45474:悻 +CJK UNIFIED IDEOGRAPH:'B1A3:45475:悵 +CJK UNIFIED IDEOGRAPH:'B1A4:45476:惜 +CJK UNIFIED IDEOGRAPH:'B1A5:45477:悼 +CJK UNIFIED IDEOGRAPH:'B1A6:45478:惘 +CJK UNIFIED IDEOGRAPH:'B1A7:45479:惕 +CJK UNIFIED IDEOGRAPH:'B1A8:45480:惆 +CJK UNIFIED IDEOGRAPH:'B1A9:45481:惟 +CJK UNIFIED IDEOGRAPH:'B1AA:45482:悸 +CJK UNIFIED IDEOGRAPH:'B1AB:45483:惚 +CJK UNIFIED IDEOGRAPH:'B1AC:45484:惇 +CJK UNIFIED IDEOGRAPH:'B1AD:45485:戚 +CJK UNIFIED IDEOGRAPH:'B1AE:45486:戛 +CJK UNIFIED IDEOGRAPH:'B1AF:45487:扈 +CJK UNIFIED IDEOGRAPH:'B1B0:45488:掠 +CJK UNIFIED IDEOGRAPH:'B1B1:45489:控 +CJK UNIFIED IDEOGRAPH:'B1B2:45490:捲 +CJK UNIFIED IDEOGRAPH:'B1B3:45491:掖 +CJK UNIFIED IDEOGRAPH:'B1B4:45492:探 +CJK UNIFIED IDEOGRAPH:'B1B5:45493:接 +CJK UNIFIED IDEOGRAPH:'B1B6:45494:捷 +CJK UNIFIED IDEOGRAPH:'B1B7:45495:捧 +CJK UNIFIED IDEOGRAPH:'B1B8:45496:掘 +CJK UNIFIED IDEOGRAPH:'B1B9:45497:措 +CJK UNIFIED IDEOGRAPH:'B1BA:45498:捱 +CJK UNIFIED IDEOGRAPH:'B1BB:45499:掩 +CJK UNIFIED IDEOGRAPH:'B1BC:45500:掉 +CJK UNIFIED IDEOGRAPH:'B1BD:45501:掃 +CJK UNIFIED IDEOGRAPH:'B1BE:45502:掛 +CJK UNIFIED IDEOGRAPH:'B1BF:45503:捫 +CJK UNIFIED IDEOGRAPH:'B1C0:45504:推 +CJK UNIFIED IDEOGRAPH:'B1C1:45505:掄 +CJK UNIFIED IDEOGRAPH:'B1C2:45506:授 +CJK UNIFIED IDEOGRAPH:'B1C3:45507:掙 +CJK UNIFIED IDEOGRAPH:'B1C4:45508:採 +CJK UNIFIED IDEOGRAPH:'B1C5:45509:掬 +CJK UNIFIED IDEOGRAPH:'B1C6:45510:排 +CJK UNIFIED IDEOGRAPH:'B1C7:45511:掏 +CJK UNIFIED IDEOGRAPH:'B1C8:45512:掀 +CJK UNIFIED IDEOGRAPH:'B1C9:45513:捻 +CJK UNIFIED IDEOGRAPH:'B1CA:45514:捩 +CJK UNIFIED IDEOGRAPH:'B1CB:45515:捨 +CJK UNIFIED IDEOGRAPH:'B1CC:45516:捺 +CJK UNIFIED IDEOGRAPH:'B1CD:45517:敝 +CJK UNIFIED IDEOGRAPH:'B1CE:45518:敖 +CJK UNIFIED IDEOGRAPH:'B1CF:45519:救 +CJK UNIFIED IDEOGRAPH:'B1D0:45520:教 +CJK UNIFIED IDEOGRAPH:'B1D1:45521:敗 +CJK UNIFIED IDEOGRAPH:'B1D2:45522:啟 +CJK UNIFIED IDEOGRAPH:'B1D3:45523:敏 +CJK UNIFIED IDEOGRAPH:'B1D4:45524:敘 +CJK UNIFIED IDEOGRAPH:'B1D5:45525:敕 +CJK UNIFIED IDEOGRAPH:'B1D6:45526:敔 +CJK UNIFIED IDEOGRAPH:'B1D7:45527:斜 +CJK UNIFIED IDEOGRAPH:'B1D8:45528:斛 +CJK UNIFIED IDEOGRAPH:'B1D9:45529:斬 +CJK UNIFIED IDEOGRAPH:'B1DA:45530:族 +CJK UNIFIED IDEOGRAPH:'B1DB:45531:旋 +CJK UNIFIED IDEOGRAPH:'B1DC:45532:旌 +CJK UNIFIED IDEOGRAPH:'B1DD:45533:旎 +CJK UNIFIED IDEOGRAPH:'B1DE:45534:晝 +CJK UNIFIED IDEOGRAPH:'B1DF:45535:晚 +CJK UNIFIED IDEOGRAPH:'B1E0:45536:晤 +CJK UNIFIED IDEOGRAPH:'B1E1:45537:晨 +CJK UNIFIED IDEOGRAPH:'B1E2:45538:晦 +CJK UNIFIED IDEOGRAPH:'B1E3:45539:晞 +CJK UNIFIED IDEOGRAPH:'B1E4:45540:曹 +CJK UNIFIED IDEOGRAPH:'B1E5:45541:勗 +CJK UNIFIED IDEOGRAPH:'B1E6:45542:望 +CJK UNIFIED IDEOGRAPH:'B1E7:45543:梁 +CJK UNIFIED IDEOGRAPH:'B1E8:45544:梯 +CJK UNIFIED IDEOGRAPH:'B1E9:45545:梢 +CJK UNIFIED IDEOGRAPH:'B1EA:45546:梓 +CJK UNIFIED IDEOGRAPH:'B1EB:45547:梵 +CJK UNIFIED IDEOGRAPH:'B1EC:45548:桿 +CJK UNIFIED IDEOGRAPH:'B1ED:45549:桶 +CJK UNIFIED IDEOGRAPH:'B1EE:45550:梱 +CJK UNIFIED IDEOGRAPH:'B1EF:45551:梧 +CJK UNIFIED IDEOGRAPH:'B1F0:45552:梗 +CJK UNIFIED IDEOGRAPH:'B1F1:45553:械 +CJK UNIFIED IDEOGRAPH:'B1F2:45554:梃 +CJK UNIFIED IDEOGRAPH:'B1F3:45555:棄 +CJK UNIFIED IDEOGRAPH:'B1F4:45556:梭 +CJK UNIFIED IDEOGRAPH:'B1F5:45557:梆 +CJK UNIFIED IDEOGRAPH:'B1F6:45558:梅 +CJK UNIFIED IDEOGRAPH:'B1F7:45559:梔 +CJK UNIFIED IDEOGRAPH:'B1F8:45560:條 +CJK UNIFIED IDEOGRAPH:'B1F9:45561:梨 +CJK UNIFIED IDEOGRAPH:'B1FA:45562:梟 +CJK UNIFIED IDEOGRAPH:'B1FB:45563:梡 +CJK UNIFIED IDEOGRAPH:'B1FC:45564:梂 +CJK UNIFIED IDEOGRAPH:'B1FD:45565:欲 +CJK UNIFIED IDEOGRAPH:'B1FE:45566:殺 +CJK UNIFIED IDEOGRAPH:'B240:45632:毫 +CJK UNIFIED IDEOGRAPH:'B241:45633:毬 +CJK UNIFIED IDEOGRAPH:'B242:45634:氫 +CJK UNIFIED IDEOGRAPH:'B243:45635:涎 +CJK UNIFIED IDEOGRAPH:'B244:45636:涼 +CJK UNIFIED IDEOGRAPH:'B245:45637:淳 +CJK UNIFIED IDEOGRAPH:'B246:45638:淙 +CJK UNIFIED IDEOGRAPH:'B247:45639:液 +CJK UNIFIED IDEOGRAPH:'B248:45640:淡 +CJK UNIFIED IDEOGRAPH:'B249:45641:淌 +CJK UNIFIED IDEOGRAPH:'B24A:45642:淤 +CJK UNIFIED IDEOGRAPH:'B24B:45643:添 +CJK UNIFIED IDEOGRAPH:'B24C:45644:淺 +CJK UNIFIED IDEOGRAPH:'B24D:45645:清 +CJK UNIFIED IDEOGRAPH:'B24E:45646:淇 +CJK UNIFIED IDEOGRAPH:'B24F:45647:淋 +CJK UNIFIED IDEOGRAPH:'B250:45648:涯 +CJK UNIFIED IDEOGRAPH:'B251:45649:淑 +CJK UNIFIED IDEOGRAPH:'B252:45650:涮 +CJK UNIFIED IDEOGRAPH:'B253:45651:淞 +CJK UNIFIED IDEOGRAPH:'B254:45652:淹 +CJK UNIFIED IDEOGRAPH:'B255:45653:涸 +CJK UNIFIED IDEOGRAPH:'B256:45654:混 +CJK UNIFIED IDEOGRAPH:'B257:45655:淵 +CJK UNIFIED IDEOGRAPH:'B258:45656:淅 +CJK UNIFIED IDEOGRAPH:'B259:45657:淒 +CJK UNIFIED IDEOGRAPH:'B25A:45658:渚 +CJK UNIFIED IDEOGRAPH:'B25B:45659:涵 +CJK UNIFIED IDEOGRAPH:'B25C:45660:淚 +CJK UNIFIED IDEOGRAPH:'B25D:45661:淫 +CJK UNIFIED IDEOGRAPH:'B25E:45662:淘 +CJK UNIFIED IDEOGRAPH:'B25F:45663:淪 +CJK UNIFIED IDEOGRAPH:'B260:45664:深 +CJK UNIFIED IDEOGRAPH:'B261:45665:淮 +CJK UNIFIED IDEOGRAPH:'B262:45666:淨 +CJK UNIFIED IDEOGRAPH:'B263:45667:淆 +CJK UNIFIED IDEOGRAPH:'B264:45668:淄 +CJK UNIFIED IDEOGRAPH:'B265:45669:涪 +CJK UNIFIED IDEOGRAPH:'B266:45670:淬 +CJK UNIFIED IDEOGRAPH:'B267:45671:涿 +CJK UNIFIED IDEOGRAPH:'B268:45672:淦 +CJK UNIFIED IDEOGRAPH:'B269:45673:烹 +CJK UNIFIED IDEOGRAPH:'B26A:45674:焉 +CJK UNIFIED IDEOGRAPH:'B26B:45675:焊 +CJK UNIFIED IDEOGRAPH:'B26C:45676:烽 +CJK UNIFIED IDEOGRAPH:'B26D:45677:烯 +CJK UNIFIED IDEOGRAPH:'B26E:45678:爽 +CJK UNIFIED IDEOGRAPH:'B26F:45679:牽 +CJK UNIFIED IDEOGRAPH:'B270:45680:犁 +CJK UNIFIED IDEOGRAPH:'B271:45681:猜 +CJK UNIFIED IDEOGRAPH:'B272:45682:猛 +CJK UNIFIED IDEOGRAPH:'B273:45683:猖 +CJK UNIFIED IDEOGRAPH:'B274:45684:猓 +CJK UNIFIED IDEOGRAPH:'B275:45685:猙 +CJK UNIFIED IDEOGRAPH:'B276:45686:率 +CJK UNIFIED IDEOGRAPH:'B277:45687:琅 +CJK UNIFIED IDEOGRAPH:'B278:45688:琊 +CJK UNIFIED IDEOGRAPH:'B279:45689:球 +CJK UNIFIED IDEOGRAPH:'B27A:45690:理 +CJK UNIFIED IDEOGRAPH:'B27B:45691:現 +CJK UNIFIED IDEOGRAPH:'B27C:45692:琍 +CJK UNIFIED IDEOGRAPH:'B27D:45693:瓠 +CJK UNIFIED IDEOGRAPH:'B27E:45694:瓶 +CJK UNIFIED IDEOGRAPH:'B2A1:45729:瓷 +CJK UNIFIED IDEOGRAPH:'B2A2:45730:甜 +CJK UNIFIED IDEOGRAPH:'B2A3:45731:產 +CJK UNIFIED IDEOGRAPH:'B2A4:45732:略 +CJK UNIFIED IDEOGRAPH:'B2A5:45733:畦 +CJK UNIFIED IDEOGRAPH:'B2A6:45734:畢 +CJK UNIFIED IDEOGRAPH:'B2A7:45735:異 +CJK UNIFIED IDEOGRAPH:'B2A8:45736:疏 +CJK UNIFIED IDEOGRAPH:'B2A9:45737:痔 +CJK UNIFIED IDEOGRAPH:'B2AA:45738:痕 +CJK UNIFIED IDEOGRAPH:'B2AB:45739:疵 +CJK UNIFIED IDEOGRAPH:'B2AC:45740:痊 +CJK UNIFIED IDEOGRAPH:'B2AD:45741:痍 +CJK UNIFIED IDEOGRAPH:'B2AE:45742:皎 +CJK UNIFIED IDEOGRAPH:'B2AF:45743:盔 +CJK UNIFIED IDEOGRAPH:'B2B0:45744:盒 +CJK UNIFIED IDEOGRAPH:'B2B1:45745:盛 +CJK UNIFIED IDEOGRAPH:'B2B2:45746:眷 +CJK UNIFIED IDEOGRAPH:'B2B3:45747:眾 +CJK UNIFIED IDEOGRAPH:'B2B4:45748:眼 +CJK UNIFIED IDEOGRAPH:'B2B5:45749:眶 +CJK UNIFIED IDEOGRAPH:'B2B6:45750:眸 +CJK UNIFIED IDEOGRAPH:'B2B7:45751:眺 +CJK UNIFIED IDEOGRAPH:'B2B8:45752:硫 +CJK UNIFIED IDEOGRAPH:'B2B9:45753:硃 +CJK UNIFIED IDEOGRAPH:'B2BA:45754:硎 +CJK UNIFIED IDEOGRAPH:'B2BB:45755:祥 +CJK UNIFIED IDEOGRAPH:'B2BC:45756:票 +CJK UNIFIED IDEOGRAPH:'B2BD:45757:祭 +CJK UNIFIED IDEOGRAPH:'B2BE:45758:移 +CJK UNIFIED IDEOGRAPH:'B2BF:45759:窒 +CJK UNIFIED IDEOGRAPH:'B2C0:45760:窕 +CJK UNIFIED IDEOGRAPH:'B2C1:45761:笠 +CJK UNIFIED IDEOGRAPH:'B2C2:45762:笨 +CJK UNIFIED IDEOGRAPH:'B2C3:45763:笛 +CJK UNIFIED IDEOGRAPH:'B2C4:45764:第 +CJK UNIFIED IDEOGRAPH:'B2C5:45765:符 +CJK UNIFIED IDEOGRAPH:'B2C6:45766:笙 +CJK UNIFIED IDEOGRAPH:'B2C7:45767:笞 +CJK UNIFIED IDEOGRAPH:'B2C8:45768:笮 +CJK UNIFIED IDEOGRAPH:'B2C9:45769:粒 +CJK UNIFIED IDEOGRAPH:'B2CA:45770:粗 +CJK UNIFIED IDEOGRAPH:'B2CB:45771:粕 +CJK UNIFIED IDEOGRAPH:'B2CC:45772:絆 +CJK UNIFIED IDEOGRAPH:'B2CD:45773:絃 +CJK UNIFIED IDEOGRAPH:'B2CE:45774:統 +CJK UNIFIED IDEOGRAPH:'B2CF:45775:紮 +CJK UNIFIED IDEOGRAPH:'B2D0:45776:紹 +CJK UNIFIED IDEOGRAPH:'B2D1:45777:紼 +CJK UNIFIED IDEOGRAPH:'B2D2:45778:絀 +CJK UNIFIED IDEOGRAPH:'B2D3:45779:細 +CJK UNIFIED IDEOGRAPH:'B2D4:45780:紳 +CJK UNIFIED IDEOGRAPH:'B2D5:45781:組 +CJK UNIFIED IDEOGRAPH:'B2D6:45782:累 +CJK UNIFIED IDEOGRAPH:'B2D7:45783:終 +CJK UNIFIED IDEOGRAPH:'B2D8:45784:紲 +CJK UNIFIED IDEOGRAPH:'B2D9:45785:紱 +CJK UNIFIED IDEOGRAPH:'B2DA:45786:缽 +CJK UNIFIED IDEOGRAPH:'B2DB:45787:羞 +CJK UNIFIED IDEOGRAPH:'B2DC:45788:羚 +CJK UNIFIED IDEOGRAPH:'B2DD:45789:翌 +CJK UNIFIED IDEOGRAPH:'B2DE:45790:翎 +CJK UNIFIED IDEOGRAPH:'B2DF:45791:習 +CJK UNIFIED IDEOGRAPH:'B2E0:45792:耜 +CJK UNIFIED IDEOGRAPH:'B2E1:45793:聊 +CJK UNIFIED IDEOGRAPH:'B2E2:45794:聆 +CJK UNIFIED IDEOGRAPH:'B2E3:45795:脯 +CJK UNIFIED IDEOGRAPH:'B2E4:45796:脖 +CJK UNIFIED IDEOGRAPH:'B2E5:45797:脣 +CJK UNIFIED IDEOGRAPH:'B2E6:45798:脫 +CJK UNIFIED IDEOGRAPH:'B2E7:45799:脩 +CJK UNIFIED IDEOGRAPH:'B2E8:45800:脰 +CJK UNIFIED IDEOGRAPH:'B2E9:45801:脤 +CJK UNIFIED IDEOGRAPH:'B2EA:45802:舂 +CJK UNIFIED IDEOGRAPH:'B2EB:45803:舵 +CJK UNIFIED IDEOGRAPH:'B2EC:45804:舷 +CJK UNIFIED IDEOGRAPH:'B2ED:45805:舶 +CJK UNIFIED IDEOGRAPH:'B2EE:45806:船 +CJK UNIFIED IDEOGRAPH:'B2EF:45807:莎 +CJK UNIFIED IDEOGRAPH:'B2F0:45808:莞 +CJK UNIFIED IDEOGRAPH:'B2F1:45809:莘 +CJK UNIFIED IDEOGRAPH:'B2F2:45810:荸 +CJK UNIFIED IDEOGRAPH:'B2F3:45811:莢 +CJK UNIFIED IDEOGRAPH:'B2F4:45812:莖 +CJK UNIFIED IDEOGRAPH:'B2F5:45813:莽 +CJK UNIFIED IDEOGRAPH:'B2F6:45814:莫 +CJK UNIFIED IDEOGRAPH:'B2F7:45815:莒 +CJK UNIFIED IDEOGRAPH:'B2F8:45816:莊 +CJK UNIFIED IDEOGRAPH:'B2F9:45817:莓 +CJK UNIFIED IDEOGRAPH:'B2FA:45818:莉 +CJK UNIFIED IDEOGRAPH:'B2FB:45819:莠 +CJK UNIFIED IDEOGRAPH:'B2FC:45820:荷 +CJK UNIFIED IDEOGRAPH:'B2FD:45821:荻 +CJK UNIFIED IDEOGRAPH:'B2FE:45822:荼 +CJK UNIFIED IDEOGRAPH:'B340:45888:莆 +CJK UNIFIED IDEOGRAPH:'B341:45889:莧 +CJK UNIFIED IDEOGRAPH:'B342:45890:處 +CJK UNIFIED IDEOGRAPH:'B343:45891:彪 +CJK UNIFIED IDEOGRAPH:'B344:45892:蛇 +CJK UNIFIED IDEOGRAPH:'B345:45893:蛀 +CJK UNIFIED IDEOGRAPH:'B346:45894:蚶 +CJK UNIFIED IDEOGRAPH:'B347:45895:蛄 +CJK UNIFIED IDEOGRAPH:'B348:45896:蚵 +CJK UNIFIED IDEOGRAPH:'B349:45897:蛆 +CJK UNIFIED IDEOGRAPH:'B34A:45898:蛋 +CJK UNIFIED IDEOGRAPH:'B34B:45899:蚱 +CJK UNIFIED IDEOGRAPH:'B34C:45900:蚯 +CJK UNIFIED IDEOGRAPH:'B34D:45901:蛉 +CJK UNIFIED IDEOGRAPH:'B34E:45902:術 +CJK UNIFIED IDEOGRAPH:'B34F:45903:袞 +CJK UNIFIED IDEOGRAPH:'B350:45904:袈 +CJK UNIFIED IDEOGRAPH:'B351:45905:被 +CJK UNIFIED IDEOGRAPH:'B352:45906:袒 +CJK UNIFIED IDEOGRAPH:'B353:45907:袖 +CJK UNIFIED IDEOGRAPH:'B354:45908:袍 +CJK UNIFIED IDEOGRAPH:'B355:45909:袋 +CJK UNIFIED IDEOGRAPH:'B356:45910:覓 +CJK UNIFIED IDEOGRAPH:'B357:45911:規 +CJK UNIFIED IDEOGRAPH:'B358:45912:訪 +CJK UNIFIED IDEOGRAPH:'B359:45913:訝 +CJK UNIFIED IDEOGRAPH:'B35A:45914:訣 +CJK UNIFIED IDEOGRAPH:'B35B:45915:訥 +CJK UNIFIED IDEOGRAPH:'B35C:45916:許 +CJK UNIFIED IDEOGRAPH:'B35D:45917:設 +CJK UNIFIED IDEOGRAPH:'B35E:45918:訟 +CJK UNIFIED IDEOGRAPH:'B35F:45919:訛 +CJK UNIFIED IDEOGRAPH:'B360:45920:訢 +CJK UNIFIED IDEOGRAPH:'B361:45921:豉 +CJK UNIFIED IDEOGRAPH:'B362:45922:豚 +CJK UNIFIED IDEOGRAPH:'B363:45923:販 +CJK UNIFIED IDEOGRAPH:'B364:45924:責 +CJK UNIFIED IDEOGRAPH:'B365:45925:貫 +CJK UNIFIED IDEOGRAPH:'B366:45926:貨 +CJK UNIFIED IDEOGRAPH:'B367:45927:貪 +CJK UNIFIED IDEOGRAPH:'B368:45928:貧 +CJK UNIFIED IDEOGRAPH:'B369:45929:赧 +CJK UNIFIED IDEOGRAPH:'B36A:45930:赦 +CJK UNIFIED IDEOGRAPH:'B36B:45931:趾 +CJK UNIFIED IDEOGRAPH:'B36C:45932:趺 +CJK UNIFIED IDEOGRAPH:'B36D:45933:軛 +CJK UNIFIED IDEOGRAPH:'B36E:45934:軟 +CJK UNIFIED IDEOGRAPH:'B36F:45935:這 +CJK UNIFIED IDEOGRAPH:'B370:45936:逍 +CJK UNIFIED IDEOGRAPH:'B371:45937:通 +CJK UNIFIED IDEOGRAPH:'B372:45938:逗 +CJK UNIFIED IDEOGRAPH:'B373:45939:連 +CJK UNIFIED IDEOGRAPH:'B374:45940:速 +CJK UNIFIED IDEOGRAPH:'B375:45941:逝 +CJK UNIFIED IDEOGRAPH:'B376:45942:逐 +CJK UNIFIED IDEOGRAPH:'B377:45943:逕 +CJK UNIFIED IDEOGRAPH:'B378:45944:逞 +CJK UNIFIED IDEOGRAPH:'B379:45945:造 +CJK UNIFIED IDEOGRAPH:'B37A:45946:透 +CJK UNIFIED IDEOGRAPH:'B37B:45947:逢 +CJK UNIFIED IDEOGRAPH:'B37C:45948:逖 +CJK UNIFIED IDEOGRAPH:'B37D:45949:逛 +CJK UNIFIED IDEOGRAPH:'B37E:45950:途 +CJK UNIFIED IDEOGRAPH:'B3A1:45985:部 +CJK UNIFIED IDEOGRAPH:'B3A2:45986:郭 +CJK UNIFIED IDEOGRAPH:'B3A3:45987:都 +CJK UNIFIED IDEOGRAPH:'B3A4:45988:酗 +CJK UNIFIED IDEOGRAPH:'B3A5:45989:野 +CJK UNIFIED IDEOGRAPH:'B3A6:45990:釵 +CJK UNIFIED IDEOGRAPH:'B3A7:45991:釦 +CJK UNIFIED IDEOGRAPH:'B3A8:45992:釣 +CJK UNIFIED IDEOGRAPH:'B3A9:45993:釧 +CJK UNIFIED IDEOGRAPH:'B3AA:45994:釭 +CJK UNIFIED IDEOGRAPH:'B3AB:45995:釩 +CJK UNIFIED IDEOGRAPH:'B3AC:45996:閉 +CJK UNIFIED IDEOGRAPH:'B3AD:45997:陪 +CJK UNIFIED IDEOGRAPH:'B3AE:45998:陵 +CJK UNIFIED IDEOGRAPH:'B3AF:45999:陳 +CJK UNIFIED IDEOGRAPH:'B3B0:46000:陸 +CJK UNIFIED IDEOGRAPH:'B3B1:46001:陰 +CJK UNIFIED IDEOGRAPH:'B3B2:46002:陴 +CJK UNIFIED IDEOGRAPH:'B3B3:46003:陶 +CJK UNIFIED IDEOGRAPH:'B3B4:46004:陷 +CJK UNIFIED IDEOGRAPH:'B3B5:46005:陬 +CJK UNIFIED IDEOGRAPH:'B3B6:46006:雀 +CJK UNIFIED IDEOGRAPH:'B3B7:46007:雪 +CJK UNIFIED IDEOGRAPH:'B3B8:46008:雩 +CJK UNIFIED IDEOGRAPH:'B3B9:46009:章 +CJK UNIFIED IDEOGRAPH:'B3BA:46010:竟 +CJK UNIFIED IDEOGRAPH:'B3BB:46011:頂 +CJK UNIFIED IDEOGRAPH:'B3BC:46012:頃 +CJK UNIFIED IDEOGRAPH:'B3BD:46013:魚 +CJK UNIFIED IDEOGRAPH:'B3BE:46014:鳥 +CJK UNIFIED IDEOGRAPH:'B3BF:46015:鹵 +CJK UNIFIED IDEOGRAPH:'B3C0:46016:鹿 +CJK UNIFIED IDEOGRAPH:'B3C1:46017:麥 +CJK UNIFIED IDEOGRAPH:'B3C2:46018:麻 +CJK UNIFIED IDEOGRAPH:'B3C3:46019:傢 +CJK UNIFIED IDEOGRAPH:'B3C4:46020:傍 +CJK UNIFIED IDEOGRAPH:'B3C5:46021:傅 +CJK UNIFIED IDEOGRAPH:'B3C6:46022:備 +CJK UNIFIED IDEOGRAPH:'B3C7:46023:傑 +CJK UNIFIED IDEOGRAPH:'B3C8:46024:傀 +CJK UNIFIED IDEOGRAPH:'B3C9:46025:傖 +CJK UNIFIED IDEOGRAPH:'B3CA:46026:傘 +CJK UNIFIED IDEOGRAPH:'B3CB:46027:傚 +CJK UNIFIED IDEOGRAPH:'B3CC:46028:最 +CJK UNIFIED IDEOGRAPH:'B3CD:46029:凱 +CJK UNIFIED IDEOGRAPH:'B3CE:46030:割 +CJK UNIFIED IDEOGRAPH:'B3CF:46031:剴 +CJK UNIFIED IDEOGRAPH:'B3D0:46032:創 +CJK UNIFIED IDEOGRAPH:'B3D1:46033:剩 +CJK UNIFIED IDEOGRAPH:'B3D2:46034:勞 +CJK UNIFIED IDEOGRAPH:'B3D3:46035:勝 +CJK UNIFIED IDEOGRAPH:'B3D4:46036:勛 +CJK UNIFIED IDEOGRAPH:'B3D5:46037:博 +CJK UNIFIED IDEOGRAPH:'B3D6:46038:厥 +CJK UNIFIED IDEOGRAPH:'B3D7:46039:啻 +CJK UNIFIED IDEOGRAPH:'B3D8:46040:喀 +CJK UNIFIED IDEOGRAPH:'B3D9:46041:喧 +CJK UNIFIED IDEOGRAPH:'B3DA:46042:啼 +CJK UNIFIED IDEOGRAPH:'B3DB:46043:喊 +CJK UNIFIED IDEOGRAPH:'B3DC:46044:喝 +CJK UNIFIED IDEOGRAPH:'B3DD:46045:喘 +CJK UNIFIED IDEOGRAPH:'B3DE:46046:喂 +CJK UNIFIED IDEOGRAPH:'B3DF:46047:喜 +CJK UNIFIED IDEOGRAPH:'B3E0:46048:喪 +CJK UNIFIED IDEOGRAPH:'B3E1:46049:喔 +CJK UNIFIED IDEOGRAPH:'B3E2:46050:喇 +CJK UNIFIED IDEOGRAPH:'B3E3:46051:喋 +CJK UNIFIED IDEOGRAPH:'B3E4:46052:喃 +CJK UNIFIED IDEOGRAPH:'B3E5:46053:喳 +CJK UNIFIED IDEOGRAPH:'B3E6:46054:單 +CJK UNIFIED IDEOGRAPH:'B3E7:46055:喟 +CJK UNIFIED IDEOGRAPH:'B3E8:46056:唾 +CJK UNIFIED IDEOGRAPH:'B3E9:46057:喲 +CJK UNIFIED IDEOGRAPH:'B3EA:46058:喚 +CJK UNIFIED IDEOGRAPH:'B3EB:46059:喻 +CJK UNIFIED IDEOGRAPH:'B3EC:46060:喬 +CJK UNIFIED IDEOGRAPH:'B3ED:46061:喱 +CJK UNIFIED IDEOGRAPH:'B3EE:46062:啾 +CJK UNIFIED IDEOGRAPH:'B3EF:46063:喉 +CJK UNIFIED IDEOGRAPH:'B3F0:46064:喫 +CJK UNIFIED IDEOGRAPH:'B3F1:46065:喙 +CJK UNIFIED IDEOGRAPH:'B3F2:46066:圍 +CJK UNIFIED IDEOGRAPH:'B3F3:46067:堯 +CJK UNIFIED IDEOGRAPH:'B3F4:46068:堪 +CJK UNIFIED IDEOGRAPH:'B3F5:46069:場 +CJK UNIFIED IDEOGRAPH:'B3F6:46070:堤 +CJK UNIFIED IDEOGRAPH:'B3F7:46071:堰 +CJK UNIFIED IDEOGRAPH:'B3F8:46072:報 +CJK UNIFIED IDEOGRAPH:'B3F9:46073:堡 +CJK UNIFIED IDEOGRAPH:'B3FA:46074:堝 +CJK UNIFIED IDEOGRAPH:'B3FB:46075:堠 +CJK UNIFIED IDEOGRAPH:'B3FC:46076:壹 +CJK UNIFIED IDEOGRAPH:'B3FD:46077:壺 +CJK UNIFIED IDEOGRAPH:'B3FE:46078:奠 +CJK UNIFIED IDEOGRAPH:'B440:46144:婷 +CJK UNIFIED IDEOGRAPH:'B441:46145:媚 +CJK UNIFIED IDEOGRAPH:'B442:46146:婿 +CJK UNIFIED IDEOGRAPH:'B443:46147:媒 +CJK UNIFIED IDEOGRAPH:'B444:46148:媛 +CJK UNIFIED IDEOGRAPH:'B445:46149:媧 +CJK UNIFIED IDEOGRAPH:'B446:46150:孳 +CJK UNIFIED IDEOGRAPH:'B447:46151:孱 +CJK UNIFIED IDEOGRAPH:'B448:46152:寒 +CJK UNIFIED IDEOGRAPH:'B449:46153:富 +CJK UNIFIED IDEOGRAPH:'B44A:46154:寓 +CJK UNIFIED IDEOGRAPH:'B44B:46155:寐 +CJK UNIFIED IDEOGRAPH:'B44C:46156:尊 +CJK UNIFIED IDEOGRAPH:'B44D:46157:尋 +CJK UNIFIED IDEOGRAPH:'B44E:46158:就 +CJK UNIFIED IDEOGRAPH:'B44F:46159:嵌 +CJK UNIFIED IDEOGRAPH:'B450:46160:嵐 +CJK UNIFIED IDEOGRAPH:'B451:46161:崴 +CJK UNIFIED IDEOGRAPH:'B452:46162:嵇 +CJK UNIFIED IDEOGRAPH:'B453:46163:巽 +CJK UNIFIED IDEOGRAPH:'B454:46164:幅 +CJK UNIFIED IDEOGRAPH:'B455:46165:帽 +CJK UNIFIED IDEOGRAPH:'B456:46166:幀 +CJK UNIFIED IDEOGRAPH:'B457:46167:幃 +CJK UNIFIED IDEOGRAPH:'B458:46168:幾 +CJK UNIFIED IDEOGRAPH:'B459:46169:廊 +CJK UNIFIED IDEOGRAPH:'B45A:46170:廁 +CJK UNIFIED IDEOGRAPH:'B45B:46171:廂 +CJK UNIFIED IDEOGRAPH:'B45C:46172:廄 +CJK UNIFIED IDEOGRAPH:'B45D:46173:弼 +CJK UNIFIED IDEOGRAPH:'B45E:46174:彭 +CJK UNIFIED IDEOGRAPH:'B45F:46175:復 +CJK UNIFIED IDEOGRAPH:'B460:46176:循 +CJK UNIFIED IDEOGRAPH:'B461:46177:徨 +CJK UNIFIED IDEOGRAPH:'B462:46178:惑 +CJK UNIFIED IDEOGRAPH:'B463:46179:惡 +CJK UNIFIED IDEOGRAPH:'B464:46180:悲 +CJK UNIFIED IDEOGRAPH:'B465:46181:悶 +CJK UNIFIED IDEOGRAPH:'B466:46182:惠 +CJK UNIFIED IDEOGRAPH:'B467:46183:愜 +CJK UNIFIED IDEOGRAPH:'B468:46184:愣 +CJK UNIFIED IDEOGRAPH:'B469:46185:惺 +CJK UNIFIED IDEOGRAPH:'B46A:46186:愕 +CJK UNIFIED IDEOGRAPH:'B46B:46187:惰 +CJK UNIFIED IDEOGRAPH:'B46C:46188:惻 +CJK UNIFIED IDEOGRAPH:'B46D:46189:惴 +CJK UNIFIED IDEOGRAPH:'B46E:46190:慨 +CJK UNIFIED IDEOGRAPH:'B46F:46191:惱 +CJK UNIFIED IDEOGRAPH:'B470:46192:愎 +CJK UNIFIED IDEOGRAPH:'B471:46193:惶 +CJK UNIFIED IDEOGRAPH:'B472:46194:愉 +CJK UNIFIED IDEOGRAPH:'B473:46195:愀 +CJK UNIFIED IDEOGRAPH:'B474:46196:愒 +CJK UNIFIED IDEOGRAPH:'B475:46197:戟 +CJK UNIFIED IDEOGRAPH:'B476:46198:扉 +CJK UNIFIED IDEOGRAPH:'B477:46199:掣 +CJK UNIFIED IDEOGRAPH:'B478:46200:掌 +CJK UNIFIED IDEOGRAPH:'B479:46201:描 +CJK UNIFIED IDEOGRAPH:'B47A:46202:揀 +CJK UNIFIED IDEOGRAPH:'B47B:46203:揩 +CJK UNIFIED IDEOGRAPH:'B47C:46204:揉 +CJK UNIFIED IDEOGRAPH:'B47D:46205:揆 +CJK UNIFIED IDEOGRAPH:'B47E:46206:揍 +CJK UNIFIED IDEOGRAPH:'B4A1:46241:插 +CJK UNIFIED IDEOGRAPH:'B4A2:46242:揣 +CJK UNIFIED IDEOGRAPH:'B4A3:46243:提 +CJK UNIFIED IDEOGRAPH:'B4A4:46244:握 +CJK UNIFIED IDEOGRAPH:'B4A5:46245:揖 +CJK UNIFIED IDEOGRAPH:'B4A6:46246:揭 +CJK UNIFIED IDEOGRAPH:'B4A7:46247:揮 +CJK UNIFIED IDEOGRAPH:'B4A8:46248:捶 +CJK UNIFIED IDEOGRAPH:'B4A9:46249:援 +CJK UNIFIED IDEOGRAPH:'B4AA:46250:揪 +CJK UNIFIED IDEOGRAPH:'B4AB:46251:換 +CJK UNIFIED IDEOGRAPH:'B4AC:46252:摒 +CJK UNIFIED IDEOGRAPH:'B4AD:46253:揚 +CJK UNIFIED IDEOGRAPH:'B4AE:46254:揹 +CJK UNIFIED IDEOGRAPH:'B4AF:46255:敞 +CJK UNIFIED IDEOGRAPH:'B4B0:46256:敦 +CJK UNIFIED IDEOGRAPH:'B4B1:46257:敢 +CJK UNIFIED IDEOGRAPH:'B4B2:46258:散 +CJK UNIFIED IDEOGRAPH:'B4B3:46259:斑 +CJK UNIFIED IDEOGRAPH:'B4B4:46260:斐 +CJK UNIFIED IDEOGRAPH:'B4B5:46261:斯 +CJK UNIFIED IDEOGRAPH:'B4B6:46262:普 +CJK UNIFIED IDEOGRAPH:'B4B7:46263:晰 +CJK UNIFIED IDEOGRAPH:'B4B8:46264:晴 +CJK UNIFIED IDEOGRAPH:'B4B9:46265:晶 +CJK UNIFIED IDEOGRAPH:'B4BA:46266:景 +CJK UNIFIED IDEOGRAPH:'B4BB:46267:暑 +CJK UNIFIED IDEOGRAPH:'B4BC:46268:智 +CJK UNIFIED IDEOGRAPH:'B4BD:46269:晾 +CJK UNIFIED IDEOGRAPH:'B4BE:46270:晷 +CJK UNIFIED IDEOGRAPH:'B4BF:46271:曾 +CJK UNIFIED IDEOGRAPH:'B4C0:46272:替 +CJK UNIFIED IDEOGRAPH:'B4C1:46273:期 +CJK UNIFIED IDEOGRAPH:'B4C2:46274:朝 +CJK UNIFIED IDEOGRAPH:'B4C3:46275:棺 +CJK UNIFIED IDEOGRAPH:'B4C4:46276:棕 +CJK UNIFIED IDEOGRAPH:'B4C5:46277:棠 +CJK UNIFIED IDEOGRAPH:'B4C6:46278:棘 +CJK UNIFIED IDEOGRAPH:'B4C7:46279:棗 +CJK UNIFIED IDEOGRAPH:'B4C8:46280:椅 +CJK UNIFIED IDEOGRAPH:'B4C9:46281:棟 +CJK UNIFIED IDEOGRAPH:'B4CA:46282:棵 +CJK UNIFIED IDEOGRAPH:'B4CB:46283:森 +CJK UNIFIED IDEOGRAPH:'B4CC:46284:棧 +CJK UNIFIED IDEOGRAPH:'B4CD:46285:棹 +CJK UNIFIED IDEOGRAPH:'B4CE:46286:棒 +CJK UNIFIED IDEOGRAPH:'B4CF:46287:棲 +CJK UNIFIED IDEOGRAPH:'B4D0:46288:棣 +CJK UNIFIED IDEOGRAPH:'B4D1:46289:棋 +CJK UNIFIED IDEOGRAPH:'B4D2:46290:棍 +CJK UNIFIED IDEOGRAPH:'B4D3:46291:植 +CJK UNIFIED IDEOGRAPH:'B4D4:46292:椒 +CJK UNIFIED IDEOGRAPH:'B4D5:46293:椎 +CJK UNIFIED IDEOGRAPH:'B4D6:46294:棉 +CJK UNIFIED IDEOGRAPH:'B4D7:46295:棚 +CJK UNIFIED IDEOGRAPH:'B4D8:46296:楮 +CJK UNIFIED IDEOGRAPH:'B4D9:46297:棻 +CJK UNIFIED IDEOGRAPH:'B4DA:46298:款 +CJK UNIFIED IDEOGRAPH:'B4DB:46299:欺 +CJK UNIFIED IDEOGRAPH:'B4DC:46300:欽 +CJK UNIFIED IDEOGRAPH:'B4DD:46301:殘 +CJK UNIFIED IDEOGRAPH:'B4DE:46302:殖 +CJK UNIFIED IDEOGRAPH:'B4DF:46303:殼 +CJK UNIFIED IDEOGRAPH:'B4E0:46304:毯 +CJK UNIFIED IDEOGRAPH:'B4E1:46305:氮 +CJK UNIFIED IDEOGRAPH:'B4E2:46306:氯 +CJK UNIFIED IDEOGRAPH:'B4E3:46307:氬 +CJK UNIFIED IDEOGRAPH:'B4E4:46308:港 +CJK UNIFIED IDEOGRAPH:'B4E5:46309:游 +CJK UNIFIED IDEOGRAPH:'B4E6:46310:湔 +CJK UNIFIED IDEOGRAPH:'B4E7:46311:渡 +CJK UNIFIED IDEOGRAPH:'B4E8:46312:渲 +CJK UNIFIED IDEOGRAPH:'B4E9:46313:湧 +CJK UNIFIED IDEOGRAPH:'B4EA:46314:湊 +CJK UNIFIED IDEOGRAPH:'B4EB:46315:渠 +CJK UNIFIED IDEOGRAPH:'B4EC:46316:渥 +CJK UNIFIED IDEOGRAPH:'B4ED:46317:渣 +CJK UNIFIED IDEOGRAPH:'B4EE:46318:減 +CJK UNIFIED IDEOGRAPH:'B4EF:46319:湛 +CJK UNIFIED IDEOGRAPH:'B4F0:46320:湘 +CJK UNIFIED IDEOGRAPH:'B4F1:46321:渤 +CJK UNIFIED IDEOGRAPH:'B4F2:46322:湖 +CJK UNIFIED IDEOGRAPH:'B4F3:46323:湮 +CJK UNIFIED IDEOGRAPH:'B4F4:46324:渭 +CJK UNIFIED IDEOGRAPH:'B4F5:46325:渦 +CJK UNIFIED IDEOGRAPH:'B4F6:46326:湯 +CJK UNIFIED IDEOGRAPH:'B4F7:46327:渴 +CJK UNIFIED IDEOGRAPH:'B4F8:46328:湍 +CJK UNIFIED IDEOGRAPH:'B4F9:46329:渺 +CJK UNIFIED IDEOGRAPH:'B4FA:46330:測 +CJK UNIFIED IDEOGRAPH:'B4FB:46331:湃 +CJK UNIFIED IDEOGRAPH:'B4FC:46332:渝 +CJK UNIFIED IDEOGRAPH:'B4FD:46333:渾 +CJK UNIFIED IDEOGRAPH:'B4FE:46334:滋 +CJK UNIFIED IDEOGRAPH:'B540:46400:溉 +CJK UNIFIED IDEOGRAPH:'B541:46401:渙 +CJK UNIFIED IDEOGRAPH:'B542:46402:湎 +CJK UNIFIED IDEOGRAPH:'B543:46403:湣 +CJK UNIFIED IDEOGRAPH:'B544:46404:湄 +CJK UNIFIED IDEOGRAPH:'B545:46405:湲 +CJK UNIFIED IDEOGRAPH:'B546:46406:湩 +CJK UNIFIED IDEOGRAPH:'B547:46407:湟 +CJK UNIFIED IDEOGRAPH:'B548:46408:焙 +CJK UNIFIED IDEOGRAPH:'B549:46409:焚 +CJK UNIFIED IDEOGRAPH:'B54A:46410:焦 +CJK UNIFIED IDEOGRAPH:'B54B:46411:焰 +CJK UNIFIED IDEOGRAPH:'B54C:46412:無 +CJK UNIFIED IDEOGRAPH:'B54D:46413:然 +CJK UNIFIED IDEOGRAPH:'B54E:46414:煮 +CJK UNIFIED IDEOGRAPH:'B54F:46415:焜 +CJK UNIFIED IDEOGRAPH:'B550:46416:牌 +CJK UNIFIED IDEOGRAPH:'B551:46417:犄 +CJK UNIFIED IDEOGRAPH:'B552:46418:犀 +CJK UNIFIED IDEOGRAPH:'B553:46419:猶 +CJK UNIFIED IDEOGRAPH:'B554:46420:猥 +CJK UNIFIED IDEOGRAPH:'B555:46421:猴 +CJK UNIFIED IDEOGRAPH:'B556:46422:猩 +CJK UNIFIED IDEOGRAPH:'B557:46423:琺 +CJK UNIFIED IDEOGRAPH:'B558:46424:琪 +CJK UNIFIED IDEOGRAPH:'B559:46425:琳 +CJK UNIFIED IDEOGRAPH:'B55A:46426:琢 +CJK UNIFIED IDEOGRAPH:'B55B:46427:琥 +CJK UNIFIED IDEOGRAPH:'B55C:46428:琵 +CJK UNIFIED IDEOGRAPH:'B55D:46429:琶 +CJK UNIFIED IDEOGRAPH:'B55E:46430:琴 +CJK UNIFIED IDEOGRAPH:'B55F:46431:琯 +CJK UNIFIED IDEOGRAPH:'B560:46432:琛 +CJK UNIFIED IDEOGRAPH:'B561:46433:琦 +CJK UNIFIED IDEOGRAPH:'B562:46434:琨 +CJK UNIFIED IDEOGRAPH:'B563:46435:甥 +CJK UNIFIED IDEOGRAPH:'B564:46436:甦 +CJK UNIFIED IDEOGRAPH:'B565:46437:畫 +CJK UNIFIED IDEOGRAPH:'B566:46438:番 +CJK UNIFIED IDEOGRAPH:'B567:46439:痢 +CJK UNIFIED IDEOGRAPH:'B568:46440:痛 +CJK UNIFIED IDEOGRAPH:'B569:46441:痣 +CJK UNIFIED IDEOGRAPH:'B56A:46442:痙 +CJK UNIFIED IDEOGRAPH:'B56B:46443:痘 +CJK UNIFIED IDEOGRAPH:'B56C:46444:痞 +CJK UNIFIED IDEOGRAPH:'B56D:46445:痠 +CJK UNIFIED IDEOGRAPH:'B56E:46446:登 +CJK UNIFIED IDEOGRAPH:'B56F:46447:發 +CJK UNIFIED IDEOGRAPH:'B570:46448:皖 +CJK UNIFIED IDEOGRAPH:'B571:46449:皓 +CJK UNIFIED IDEOGRAPH:'B572:46450:皴 +CJK UNIFIED IDEOGRAPH:'B573:46451:盜 +CJK UNIFIED IDEOGRAPH:'B574:46452:睏 +CJK UNIFIED IDEOGRAPH:'B575:46453:短 +CJK UNIFIED IDEOGRAPH:'B576:46454:硝 +CJK UNIFIED IDEOGRAPH:'B577:46455:硬 +CJK UNIFIED IDEOGRAPH:'B578:46456:硯 +CJK UNIFIED IDEOGRAPH:'B579:46457:稍 +CJK UNIFIED IDEOGRAPH:'B57A:46458:稈 +CJK UNIFIED IDEOGRAPH:'B57B:46459:程 +CJK UNIFIED IDEOGRAPH:'B57C:46460:稅 +CJK UNIFIED IDEOGRAPH:'B57D:46461:稀 +CJK UNIFIED IDEOGRAPH:'B57E:46462:窘 +CJK UNIFIED IDEOGRAPH:'B5A1:46497:窗 +CJK UNIFIED IDEOGRAPH:'B5A2:46498:窖 +CJK UNIFIED IDEOGRAPH:'B5A3:46499:童 +CJK UNIFIED IDEOGRAPH:'B5A4:46500:竣 +CJK UNIFIED IDEOGRAPH:'B5A5:46501:等 +CJK UNIFIED IDEOGRAPH:'B5A6:46502:策 +CJK UNIFIED IDEOGRAPH:'B5A7:46503:筆 +CJK UNIFIED IDEOGRAPH:'B5A8:46504:筐 +CJK UNIFIED IDEOGRAPH:'B5A9:46505:筒 +CJK UNIFIED IDEOGRAPH:'B5AA:46506:答 +CJK UNIFIED IDEOGRAPH:'B5AB:46507:筍 +CJK UNIFIED IDEOGRAPH:'B5AC:46508:筋 +CJK UNIFIED IDEOGRAPH:'B5AD:46509:筏 +CJK UNIFIED IDEOGRAPH:'B5AE:46510:筑 +CJK UNIFIED IDEOGRAPH:'B5AF:46511:粟 +CJK UNIFIED IDEOGRAPH:'B5B0:46512:粥 +CJK UNIFIED IDEOGRAPH:'B5B1:46513:絞 +CJK UNIFIED IDEOGRAPH:'B5B2:46514:結 +CJK UNIFIED IDEOGRAPH:'B5B3:46515:絨 +CJK UNIFIED IDEOGRAPH:'B5B4:46516:絕 +CJK UNIFIED IDEOGRAPH:'B5B5:46517:紫 +CJK UNIFIED IDEOGRAPH:'B5B6:46518:絮 +CJK UNIFIED IDEOGRAPH:'B5B7:46519:絲 +CJK UNIFIED IDEOGRAPH:'B5B8:46520:絡 +CJK UNIFIED IDEOGRAPH:'B5B9:46521:給 +CJK UNIFIED IDEOGRAPH:'B5BA:46522:絢 +CJK UNIFIED IDEOGRAPH:'B5BB:46523:絰 +CJK UNIFIED IDEOGRAPH:'B5BC:46524:絳 +CJK UNIFIED IDEOGRAPH:'B5BD:46525:善 +CJK UNIFIED IDEOGRAPH:'B5BE:46526:翔 +CJK UNIFIED IDEOGRAPH:'B5BF:46527:翕 +CJK UNIFIED IDEOGRAPH:'B5C0:46528:耋 +CJK UNIFIED IDEOGRAPH:'B5C1:46529:聒 +CJK UNIFIED IDEOGRAPH:'B5C2:46530:肅 +CJK UNIFIED IDEOGRAPH:'B5C3:46531:腕 +CJK UNIFIED IDEOGRAPH:'B5C4:46532:腔 +CJK UNIFIED IDEOGRAPH:'B5C5:46533:腋 +CJK UNIFIED IDEOGRAPH:'B5C6:46534:腑 +CJK UNIFIED IDEOGRAPH:'B5C7:46535:腎 +CJK UNIFIED IDEOGRAPH:'B5C8:46536:脹 +CJK UNIFIED IDEOGRAPH:'B5C9:46537:腆 +CJK UNIFIED IDEOGRAPH:'B5CA:46538:脾 +CJK UNIFIED IDEOGRAPH:'B5CB:46539:腌 +CJK UNIFIED IDEOGRAPH:'B5CC:46540:腓 +CJK UNIFIED IDEOGRAPH:'B5CD:46541:腴 +CJK UNIFIED IDEOGRAPH:'B5CE:46542:舒 +CJK UNIFIED IDEOGRAPH:'B5CF:46543:舜 +CJK UNIFIED IDEOGRAPH:'B5D0:46544:菩 +CJK UNIFIED IDEOGRAPH:'B5D1:46545:萃 +CJK UNIFIED IDEOGRAPH:'B5D2:46546:菸 +CJK UNIFIED IDEOGRAPH:'B5D3:46547:萍 +CJK UNIFIED IDEOGRAPH:'B5D4:46548:菠 +CJK UNIFIED IDEOGRAPH:'B5D5:46549:菅 +CJK UNIFIED IDEOGRAPH:'B5D6:46550:萋 +CJK UNIFIED IDEOGRAPH:'B5D7:46551:菁 +CJK UNIFIED IDEOGRAPH:'B5D8:46552:華 +CJK UNIFIED IDEOGRAPH:'B5D9:46553:菱 +CJK UNIFIED IDEOGRAPH:'B5DA:46554:菴 +CJK UNIFIED IDEOGRAPH:'B5DB:46555:著 +CJK UNIFIED IDEOGRAPH:'B5DC:46556:萊 +CJK UNIFIED IDEOGRAPH:'B5DD:46557:菰 +CJK UNIFIED IDEOGRAPH:'B5DE:46558:萌 +CJK UNIFIED IDEOGRAPH:'B5DF:46559:菌 +CJK UNIFIED IDEOGRAPH:'B5E0:46560:菽 +CJK UNIFIED IDEOGRAPH:'B5E1:46561:菲 +CJK UNIFIED IDEOGRAPH:'B5E2:46562:菊 +CJK UNIFIED IDEOGRAPH:'B5E3:46563:萸 +CJK UNIFIED IDEOGRAPH:'B5E4:46564:萎 +CJK UNIFIED IDEOGRAPH:'B5E5:46565:萄 +CJK UNIFIED IDEOGRAPH:'B5E6:46566:菜 +CJK UNIFIED IDEOGRAPH:'B5E7:46567:萇 +CJK UNIFIED IDEOGRAPH:'B5E8:46568:菔 +CJK UNIFIED IDEOGRAPH:'B5E9:46569:菟 +CJK UNIFIED IDEOGRAPH:'B5EA:46570:虛 +CJK UNIFIED IDEOGRAPH:'B5EB:46571:蛟 +CJK UNIFIED IDEOGRAPH:'B5EC:46572:蛙 +CJK UNIFIED IDEOGRAPH:'B5ED:46573:蛭 +CJK UNIFIED IDEOGRAPH:'B5EE:46574:蛔 +CJK UNIFIED IDEOGRAPH:'B5EF:46575:蛛 +CJK UNIFIED IDEOGRAPH:'B5F0:46576:蛤 +CJK UNIFIED IDEOGRAPH:'B5F1:46577:蛐 +CJK UNIFIED IDEOGRAPH:'B5F2:46578:蛞 +CJK UNIFIED IDEOGRAPH:'B5F3:46579:街 +CJK UNIFIED IDEOGRAPH:'B5F4:46580:裁 +CJK UNIFIED IDEOGRAPH:'B5F5:46581:裂 +CJK UNIFIED IDEOGRAPH:'B5F6:46582:袱 +CJK UNIFIED IDEOGRAPH:'B5F7:46583:覃 +CJK UNIFIED IDEOGRAPH:'B5F8:46584:視 +CJK UNIFIED IDEOGRAPH:'B5F9:46585:註 +CJK UNIFIED IDEOGRAPH:'B5FA:46586:詠 +CJK UNIFIED IDEOGRAPH:'B5FB:46587:評 +CJK UNIFIED IDEOGRAPH:'B5FC:46588:詞 +CJK UNIFIED IDEOGRAPH:'B5FD:46589:証 +CJK UNIFIED IDEOGRAPH:'B5FE:46590:詁 +CJK UNIFIED IDEOGRAPH:'B640:46656:詔 +CJK UNIFIED IDEOGRAPH:'B641:46657:詛 +CJK UNIFIED IDEOGRAPH:'B642:46658:詐 +CJK UNIFIED IDEOGRAPH:'B643:46659:詆 +CJK UNIFIED IDEOGRAPH:'B644:46660:訴 +CJK UNIFIED IDEOGRAPH:'B645:46661:診 +CJK UNIFIED IDEOGRAPH:'B646:46662:訶 +CJK UNIFIED IDEOGRAPH:'B647:46663:詖 +CJK UNIFIED IDEOGRAPH:'B648:46664:象 +CJK UNIFIED IDEOGRAPH:'B649:46665:貂 +CJK UNIFIED IDEOGRAPH:'B64A:46666:貯 +CJK UNIFIED IDEOGRAPH:'B64B:46667:貼 +CJK UNIFIED IDEOGRAPH:'B64C:46668:貳 +CJK UNIFIED IDEOGRAPH:'B64D:46669:貽 +CJK UNIFIED IDEOGRAPH:'B64E:46670:賁 +CJK UNIFIED IDEOGRAPH:'B64F:46671:費 +CJK UNIFIED IDEOGRAPH:'B650:46672:賀 +CJK UNIFIED IDEOGRAPH:'B651:46673:貴 +CJK UNIFIED IDEOGRAPH:'B652:46674:買 +CJK UNIFIED IDEOGRAPH:'B653:46675:貶 +CJK UNIFIED IDEOGRAPH:'B654:46676:貿 +CJK UNIFIED IDEOGRAPH:'B655:46677:貸 +CJK UNIFIED IDEOGRAPH:'B656:46678:越 +CJK UNIFIED IDEOGRAPH:'B657:46679:超 +CJK UNIFIED IDEOGRAPH:'B658:46680:趁 +CJK UNIFIED IDEOGRAPH:'B659:46681:跎 +CJK UNIFIED IDEOGRAPH:'B65A:46682:距 +CJK UNIFIED IDEOGRAPH:'B65B:46683:跋 +CJK UNIFIED IDEOGRAPH:'B65C:46684:跚 +CJK UNIFIED IDEOGRAPH:'B65D:46685:跑 +CJK UNIFIED IDEOGRAPH:'B65E:46686:跌 +CJK UNIFIED IDEOGRAPH:'B65F:46687:跛 +CJK UNIFIED IDEOGRAPH:'B660:46688:跆 +CJK UNIFIED IDEOGRAPH:'B661:46689:軻 +CJK UNIFIED IDEOGRAPH:'B662:46690:軸 +CJK UNIFIED IDEOGRAPH:'B663:46691:軼 +CJK UNIFIED IDEOGRAPH:'B664:46692:辜 +CJK UNIFIED IDEOGRAPH:'B665:46693:逮 +CJK UNIFIED IDEOGRAPH:'B666:46694:逵 +CJK UNIFIED IDEOGRAPH:'B667:46695:週 +CJK UNIFIED IDEOGRAPH:'B668:46696:逸 +CJK UNIFIED IDEOGRAPH:'B669:46697:進 +CJK UNIFIED IDEOGRAPH:'B66A:46698:逶 +CJK UNIFIED IDEOGRAPH:'B66B:46699:鄂 +CJK UNIFIED IDEOGRAPH:'B66C:46700:郵 +CJK UNIFIED IDEOGRAPH:'B66D:46701:鄉 +CJK UNIFIED IDEOGRAPH:'B66E:46702:郾 +CJK UNIFIED IDEOGRAPH:'B66F:46703:酣 +CJK UNIFIED IDEOGRAPH:'B670:46704:酥 +CJK UNIFIED IDEOGRAPH:'B671:46705:量 +CJK UNIFIED IDEOGRAPH:'B672:46706:鈔 +CJK UNIFIED IDEOGRAPH:'B673:46707:鈕 +CJK UNIFIED IDEOGRAPH:'B674:46708:鈣 +CJK UNIFIED IDEOGRAPH:'B675:46709:鈉 +CJK UNIFIED IDEOGRAPH:'B676:46710:鈞 +CJK UNIFIED IDEOGRAPH:'B677:46711:鈍 +CJK UNIFIED IDEOGRAPH:'B678:46712:鈐 +CJK UNIFIED IDEOGRAPH:'B679:46713:鈇 +CJK UNIFIED IDEOGRAPH:'B67A:46714:鈑 +CJK UNIFIED IDEOGRAPH:'B67B:46715:閔 +CJK UNIFIED IDEOGRAPH:'B67C:46716:閏 +CJK UNIFIED IDEOGRAPH:'B67D:46717:開 +CJK UNIFIED IDEOGRAPH:'B67E:46718:閑 +CJK UNIFIED IDEOGRAPH:'B6A1:46753:間 +CJK UNIFIED IDEOGRAPH:'B6A2:46754:閒 +CJK UNIFIED IDEOGRAPH:'B6A3:46755:閎 +CJK UNIFIED IDEOGRAPH:'B6A4:46756:隊 +CJK UNIFIED IDEOGRAPH:'B6A5:46757:階 +CJK UNIFIED IDEOGRAPH:'B6A6:46758:隋 +CJK UNIFIED IDEOGRAPH:'B6A7:46759:陽 +CJK UNIFIED IDEOGRAPH:'B6A8:46760:隅 +CJK UNIFIED IDEOGRAPH:'B6A9:46761:隆 +CJK UNIFIED IDEOGRAPH:'B6AA:46762:隍 +CJK UNIFIED IDEOGRAPH:'B6AB:46763:陲 +CJK UNIFIED IDEOGRAPH:'B6AC:46764:隄 +CJK UNIFIED IDEOGRAPH:'B6AD:46765:雁 +CJK UNIFIED IDEOGRAPH:'B6AE:46766:雅 +CJK UNIFIED IDEOGRAPH:'B6AF:46767:雄 +CJK UNIFIED IDEOGRAPH:'B6B0:46768:集 +CJK UNIFIED IDEOGRAPH:'B6B1:46769:雇 +CJK UNIFIED IDEOGRAPH:'B6B2:46770:雯 +CJK UNIFIED IDEOGRAPH:'B6B3:46771:雲 +CJK UNIFIED IDEOGRAPH:'B6B4:46772:韌 +CJK UNIFIED IDEOGRAPH:'B6B5:46773:項 +CJK UNIFIED IDEOGRAPH:'B6B6:46774:順 +CJK UNIFIED IDEOGRAPH:'B6B7:46775:須 +CJK UNIFIED IDEOGRAPH:'B6B8:46776:飧 +CJK UNIFIED IDEOGRAPH:'B6B9:46777:飪 +CJK UNIFIED IDEOGRAPH:'B6BA:46778:飯 +CJK UNIFIED IDEOGRAPH:'B6BB:46779:飩 +CJK UNIFIED IDEOGRAPH:'B6BC:46780:飲 +CJK UNIFIED IDEOGRAPH:'B6BD:46781:飭 +CJK UNIFIED IDEOGRAPH:'B6BE:46782:馮 +CJK UNIFIED IDEOGRAPH:'B6BF:46783:馭 +CJK UNIFIED IDEOGRAPH:'B6C0:46784:黃 +CJK UNIFIED IDEOGRAPH:'B6C1:46785:黍 +CJK UNIFIED IDEOGRAPH:'B6C2:46786:黑 +CJK UNIFIED IDEOGRAPH:'B6C3:46787:亂 +CJK UNIFIED IDEOGRAPH:'B6C4:46788:傭 +CJK UNIFIED IDEOGRAPH:'B6C5:46789:債 +CJK UNIFIED IDEOGRAPH:'B6C6:46790:傲 +CJK UNIFIED IDEOGRAPH:'B6C7:46791:傳 +CJK UNIFIED IDEOGRAPH:'B6C8:46792:僅 +CJK UNIFIED IDEOGRAPH:'B6C9:46793:傾 +CJK UNIFIED IDEOGRAPH:'B6CA:46794:催 +CJK UNIFIED IDEOGRAPH:'B6CB:46795:傷 +CJK UNIFIED IDEOGRAPH:'B6CC:46796:傻 +CJK UNIFIED IDEOGRAPH:'B6CD:46797:傯 +CJK UNIFIED IDEOGRAPH:'B6CE:46798:僇 +CJK UNIFIED IDEOGRAPH:'B6CF:46799:剿 +CJK UNIFIED IDEOGRAPH:'B6D0:46800:剷 +CJK UNIFIED IDEOGRAPH:'B6D1:46801:剽 +CJK UNIFIED IDEOGRAPH:'B6D2:46802:募 +CJK UNIFIED IDEOGRAPH:'B6D3:46803:勦 +CJK UNIFIED IDEOGRAPH:'B6D4:46804:勤 +CJK UNIFIED IDEOGRAPH:'B6D5:46805:勢 +CJK UNIFIED IDEOGRAPH:'B6D6:46806:勣 +CJK UNIFIED IDEOGRAPH:'B6D7:46807:匯 +CJK UNIFIED IDEOGRAPH:'B6D8:46808:嗟 +CJK UNIFIED IDEOGRAPH:'B6D9:46809:嗨 +CJK UNIFIED IDEOGRAPH:'B6DA:46810:嗓 +CJK UNIFIED IDEOGRAPH:'B6DB:46811:嗦 +CJK UNIFIED IDEOGRAPH:'B6DC:46812:嗎 +CJK UNIFIED IDEOGRAPH:'B6DD:46813:嗜 +CJK UNIFIED IDEOGRAPH:'B6DE:46814:嗇 +CJK UNIFIED IDEOGRAPH:'B6DF:46815:嗑 +CJK UNIFIED IDEOGRAPH:'B6E0:46816:嗣 +CJK UNIFIED IDEOGRAPH:'B6E1:46817:嗤 +CJK UNIFIED IDEOGRAPH:'B6E2:46818:嗯 +CJK UNIFIED IDEOGRAPH:'B6E3:46819:嗚 +CJK UNIFIED IDEOGRAPH:'B6E4:46820:嗡 +CJK UNIFIED IDEOGRAPH:'B6E5:46821:嗅 +CJK UNIFIED IDEOGRAPH:'B6E6:46822:嗆 +CJK UNIFIED IDEOGRAPH:'B6E7:46823:嗥 +CJK UNIFIED IDEOGRAPH:'B6E8:46824:嗉 +CJK UNIFIED IDEOGRAPH:'B6E9:46825:園 +CJK UNIFIED IDEOGRAPH:'B6EA:46826:圓 +CJK UNIFIED IDEOGRAPH:'B6EB:46827:塞 +CJK UNIFIED IDEOGRAPH:'B6EC:46828:塑 +CJK UNIFIED IDEOGRAPH:'B6ED:46829:塘 +CJK UNIFIED IDEOGRAPH:'B6EE:46830:塗 +CJK UNIFIED IDEOGRAPH:'B6EF:46831:塚 +CJK UNIFIED IDEOGRAPH:'B6F0:46832:塔 +CJK UNIFIED IDEOGRAPH:'B6F1:46833:填 +CJK UNIFIED IDEOGRAPH:'B6F2:46834:塌 +CJK UNIFIED IDEOGRAPH:'B6F3:46835:塭 +CJK UNIFIED IDEOGRAPH:'B6F4:46836:塊 +CJK UNIFIED IDEOGRAPH:'B6F5:46837:塢 +CJK UNIFIED IDEOGRAPH:'B6F6:46838:塒 +CJK UNIFIED IDEOGRAPH:'B6F7:46839:塋 +CJK UNIFIED IDEOGRAPH:'B6F8:46840:奧 +CJK UNIFIED IDEOGRAPH:'B6F9:46841:嫁 +CJK UNIFIED IDEOGRAPH:'B6FA:46842:嫉 +CJK UNIFIED IDEOGRAPH:'B6FB:46843:嫌 +CJK UNIFIED IDEOGRAPH:'B6FC:46844:媾 +CJK UNIFIED IDEOGRAPH:'B6FD:46845:媽 +CJK UNIFIED IDEOGRAPH:'B6FE:46846:媼 +CJK UNIFIED IDEOGRAPH:'B740:46912:媳 +CJK UNIFIED IDEOGRAPH:'B741:46913:嫂 +CJK UNIFIED IDEOGRAPH:'B742:46914:媲 +CJK UNIFIED IDEOGRAPH:'B743:46915:嵩 +CJK UNIFIED IDEOGRAPH:'B744:46916:嵯 +CJK UNIFIED IDEOGRAPH:'B745:46917:幌 +CJK UNIFIED IDEOGRAPH:'B746:46918:幹 +CJK UNIFIED IDEOGRAPH:'B747:46919:廉 +CJK UNIFIED IDEOGRAPH:'B748:46920:廈 +CJK UNIFIED IDEOGRAPH:'B749:46921:弒 +CJK UNIFIED IDEOGRAPH:'B74A:46922:彙 +CJK UNIFIED IDEOGRAPH:'B74B:46923:徬 +CJK UNIFIED IDEOGRAPH:'B74C:46924:微 +CJK UNIFIED IDEOGRAPH:'B74D:46925:愚 +CJK UNIFIED IDEOGRAPH:'B74E:46926:意 +CJK UNIFIED IDEOGRAPH:'B74F:46927:慈 +CJK UNIFIED IDEOGRAPH:'B750:46928:感 +CJK UNIFIED IDEOGRAPH:'B751:46929:想 +CJK UNIFIED IDEOGRAPH:'B752:46930:愛 +CJK UNIFIED IDEOGRAPH:'B753:46931:惹 +CJK UNIFIED IDEOGRAPH:'B754:46932:愁 +CJK UNIFIED IDEOGRAPH:'B755:46933:愈 +CJK UNIFIED IDEOGRAPH:'B756:46934:慎 +CJK UNIFIED IDEOGRAPH:'B757:46935:慌 +CJK UNIFIED IDEOGRAPH:'B758:46936:慄 +CJK UNIFIED IDEOGRAPH:'B759:46937:慍 +CJK UNIFIED IDEOGRAPH:'B75A:46938:愾 +CJK UNIFIED IDEOGRAPH:'B75B:46939:愴 +CJK UNIFIED IDEOGRAPH:'B75C:46940:愧 +CJK UNIFIED IDEOGRAPH:'B75D:46941:愍 +CJK UNIFIED IDEOGRAPH:'B75E:46942:愆 +CJK UNIFIED IDEOGRAPH:'B75F:46943:愷 +CJK UNIFIED IDEOGRAPH:'B760:46944:戡 +CJK UNIFIED IDEOGRAPH:'B761:46945:戢 +CJK UNIFIED IDEOGRAPH:'B762:46946:搓 +CJK UNIFIED IDEOGRAPH:'B763:46947:搾 +CJK UNIFIED IDEOGRAPH:'B764:46948:搞 +CJK UNIFIED IDEOGRAPH:'B765:46949:搪 +CJK UNIFIED IDEOGRAPH:'B766:46950:搭 +CJK UNIFIED IDEOGRAPH:'B767:46951:搽 +CJK UNIFIED IDEOGRAPH:'B768:46952:搬 +CJK UNIFIED IDEOGRAPH:'B769:46953:搏 +CJK UNIFIED IDEOGRAPH:'B76A:46954:搜 +CJK UNIFIED IDEOGRAPH:'B76B:46955:搔 +CJK UNIFIED IDEOGRAPH:'B76C:46956:損 +CJK UNIFIED IDEOGRAPH:'B76D:46957:搶 +CJK UNIFIED IDEOGRAPH:'B76E:46958:搖 +CJK UNIFIED IDEOGRAPH:'B76F:46959:搗 +CJK UNIFIED IDEOGRAPH:'B770:46960:搆 +CJK UNIFIED IDEOGRAPH:'B771:46961:敬 +CJK UNIFIED IDEOGRAPH:'B772:46962:斟 +CJK UNIFIED IDEOGRAPH:'B773:46963:新 +CJK UNIFIED IDEOGRAPH:'B774:46964:暗 +CJK UNIFIED IDEOGRAPH:'B775:46965:暉 +CJK UNIFIED IDEOGRAPH:'B776:46966:暇 +CJK UNIFIED IDEOGRAPH:'B777:46967:暈 +CJK UNIFIED IDEOGRAPH:'B778:46968:暖 +CJK UNIFIED IDEOGRAPH:'B779:46969:暄 +CJK UNIFIED IDEOGRAPH:'B77A:46970:暘 +CJK UNIFIED IDEOGRAPH:'B77B:46971:暍 +CJK UNIFIED IDEOGRAPH:'B77C:46972:會 +CJK UNIFIED IDEOGRAPH:'B77D:46973:榔 +CJK UNIFIED IDEOGRAPH:'B77E:46974:業 +CJK UNIFIED IDEOGRAPH:'B7A1:47009:楚 +CJK UNIFIED IDEOGRAPH:'B7A2:47010:楷 +CJK UNIFIED IDEOGRAPH:'B7A3:47011:楠 +CJK UNIFIED IDEOGRAPH:'B7A4:47012:楔 +CJK UNIFIED IDEOGRAPH:'B7A5:47013:極 +CJK UNIFIED IDEOGRAPH:'B7A6:47014:椰 +CJK UNIFIED IDEOGRAPH:'B7A7:47015:概 +CJK UNIFIED IDEOGRAPH:'B7A8:47016:楊 +CJK UNIFIED IDEOGRAPH:'B7A9:47017:楨 +CJK UNIFIED IDEOGRAPH:'B7AA:47018:楫 +CJK UNIFIED IDEOGRAPH:'B7AB:47019:楞 +CJK UNIFIED IDEOGRAPH:'B7AC:47020:楓 +CJK UNIFIED IDEOGRAPH:'B7AD:47021:楹 +CJK UNIFIED IDEOGRAPH:'B7AE:47022:榆 +CJK UNIFIED IDEOGRAPH:'B7AF:47023:楝 +CJK UNIFIED IDEOGRAPH:'B7B0:47024:楣 +CJK UNIFIED IDEOGRAPH:'B7B1:47025:楛 +CJK UNIFIED IDEOGRAPH:'B7B2:47026:歇 +CJK UNIFIED IDEOGRAPH:'B7B3:47027:歲 +CJK UNIFIED IDEOGRAPH:'B7B4:47028:毀 +CJK UNIFIED IDEOGRAPH:'B7B5:47029:殿 +CJK UNIFIED IDEOGRAPH:'B7B6:47030:毓 +CJK UNIFIED IDEOGRAPH:'B7B7:47031:毽 +CJK UNIFIED IDEOGRAPH:'B7B8:47032:溢 +CJK UNIFIED IDEOGRAPH:'B7B9:47033:溯 +CJK UNIFIED IDEOGRAPH:'B7BA:47034:滓 +CJK UNIFIED IDEOGRAPH:'B7BB:47035:溶 +CJK UNIFIED IDEOGRAPH:'B7BC:47036:滂 +CJK UNIFIED IDEOGRAPH:'B7BD:47037:源 +CJK UNIFIED IDEOGRAPH:'B7BE:47038:溝 +CJK UNIFIED IDEOGRAPH:'B7BF:47039:滇 +CJK UNIFIED IDEOGRAPH:'B7C0:47040:滅 +CJK UNIFIED IDEOGRAPH:'B7C1:47041:溥 +CJK UNIFIED IDEOGRAPH:'B7C2:47042:溘 +CJK UNIFIED IDEOGRAPH:'B7C3:47043:溼 +CJK UNIFIED IDEOGRAPH:'B7C4:47044:溺 +CJK UNIFIED IDEOGRAPH:'B7C5:47045:溫 +CJK UNIFIED IDEOGRAPH:'B7C6:47046:滑 +CJK UNIFIED IDEOGRAPH:'B7C7:47047:準 +CJK UNIFIED IDEOGRAPH:'B7C8:47048:溜 +CJK UNIFIED IDEOGRAPH:'B7C9:47049:滄 +CJK UNIFIED IDEOGRAPH:'B7CA:47050:滔 +CJK UNIFIED IDEOGRAPH:'B7CB:47051:溪 +CJK UNIFIED IDEOGRAPH:'B7CC:47052:溧 +CJK UNIFIED IDEOGRAPH:'B7CD:47053:溴 +CJK UNIFIED IDEOGRAPH:'B7CE:47054:煎 +CJK UNIFIED IDEOGRAPH:'B7CF:47055:煙 +CJK UNIFIED IDEOGRAPH:'B7D0:47056:煩 +CJK UNIFIED IDEOGRAPH:'B7D1:47057:煤 +CJK UNIFIED IDEOGRAPH:'B7D2:47058:煉 +CJK UNIFIED IDEOGRAPH:'B7D3:47059:照 +CJK UNIFIED IDEOGRAPH:'B7D4:47060:煜 +CJK UNIFIED IDEOGRAPH:'B7D5:47061:煬 +CJK UNIFIED IDEOGRAPH:'B7D6:47062:煦 +CJK UNIFIED IDEOGRAPH:'B7D7:47063:煌 +CJK UNIFIED IDEOGRAPH:'B7D8:47064:煥 +CJK UNIFIED IDEOGRAPH:'B7D9:47065:煞 +CJK UNIFIED IDEOGRAPH:'B7DA:47066:煆 +CJK UNIFIED IDEOGRAPH:'B7DB:47067:煨 +CJK UNIFIED IDEOGRAPH:'B7DC:47068:煖 +CJK UNIFIED IDEOGRAPH:'B7DD:47069:爺 +CJK UNIFIED IDEOGRAPH:'B7DE:47070:牒 +CJK UNIFIED IDEOGRAPH:'B7DF:47071:猷 +CJK UNIFIED IDEOGRAPH:'B7E0:47072:獅 +CJK UNIFIED IDEOGRAPH:'B7E1:47073:猿 +CJK UNIFIED IDEOGRAPH:'B7E2:47074:猾 +CJK UNIFIED IDEOGRAPH:'B7E3:47075:瑯 +CJK UNIFIED IDEOGRAPH:'B7E4:47076:瑚 +CJK UNIFIED IDEOGRAPH:'B7E5:47077:瑕 +CJK UNIFIED IDEOGRAPH:'B7E6:47078:瑟 +CJK UNIFIED IDEOGRAPH:'B7E7:47079:瑞 +CJK UNIFIED IDEOGRAPH:'B7E8:47080:瑁 +CJK UNIFIED IDEOGRAPH:'B7E9:47081:琿 +CJK UNIFIED IDEOGRAPH:'B7EA:47082:瑙 +CJK UNIFIED IDEOGRAPH:'B7EB:47083:瑛 +CJK UNIFIED IDEOGRAPH:'B7EC:47084:瑜 +CJK UNIFIED IDEOGRAPH:'B7ED:47085:當 +CJK UNIFIED IDEOGRAPH:'B7EE:47086:畸 +CJK UNIFIED IDEOGRAPH:'B7EF:47087:瘀 +CJK UNIFIED IDEOGRAPH:'B7F0:47088:痰 +CJK UNIFIED IDEOGRAPH:'B7F1:47089:瘁 +CJK UNIFIED IDEOGRAPH:'B7F2:47090:痲 +CJK UNIFIED IDEOGRAPH:'B7F3:47091:痱 +CJK UNIFIED IDEOGRAPH:'B7F4:47092:痺 +CJK UNIFIED IDEOGRAPH:'B7F5:47093:痿 +CJK UNIFIED IDEOGRAPH:'B7F6:47094:痴 +CJK UNIFIED IDEOGRAPH:'B7F7:47095:痳 +CJK UNIFIED IDEOGRAPH:'B7F8:47096:盞 +CJK UNIFIED IDEOGRAPH:'B7F9:47097:盟 +CJK UNIFIED IDEOGRAPH:'B7FA:47098:睛 +CJK UNIFIED IDEOGRAPH:'B7FB:47099:睫 +CJK UNIFIED IDEOGRAPH:'B7FC:47100:睦 +CJK UNIFIED IDEOGRAPH:'B7FD:47101:睞 +CJK UNIFIED IDEOGRAPH:'B7FE:47102:督 +CJK UNIFIED IDEOGRAPH:'B840:47168:睹 +CJK UNIFIED IDEOGRAPH:'B841:47169:睪 +CJK UNIFIED IDEOGRAPH:'B842:47170:睬 +CJK UNIFIED IDEOGRAPH:'B843:47171:睜 +CJK UNIFIED IDEOGRAPH:'B844:47172:睥 +CJK UNIFIED IDEOGRAPH:'B845:47173:睨 +CJK UNIFIED IDEOGRAPH:'B846:47174:睢 +CJK UNIFIED IDEOGRAPH:'B847:47175:矮 +CJK UNIFIED IDEOGRAPH:'B848:47176:碎 +CJK UNIFIED IDEOGRAPH:'B849:47177:碰 +CJK UNIFIED IDEOGRAPH:'B84A:47178:碗 +CJK UNIFIED IDEOGRAPH:'B84B:47179:碘 +CJK UNIFIED IDEOGRAPH:'B84C:47180:碌 +CJK UNIFIED IDEOGRAPH:'B84D:47181:碉 +CJK UNIFIED IDEOGRAPH:'B84E:47182:硼 +CJK UNIFIED IDEOGRAPH:'B84F:47183:碑 +CJK UNIFIED IDEOGRAPH:'B850:47184:碓 +CJK UNIFIED IDEOGRAPH:'B851:47185:硿 +CJK UNIFIED IDEOGRAPH:'B852:47186:祺 +CJK UNIFIED IDEOGRAPH:'B853:47187:祿 +CJK UNIFIED IDEOGRAPH:'B854:47188:禁 +CJK UNIFIED IDEOGRAPH:'B855:47189:萬 +CJK UNIFIED IDEOGRAPH:'B856:47190:禽 +CJK UNIFIED IDEOGRAPH:'B857:47191:稜 +CJK UNIFIED IDEOGRAPH:'B858:47192:稚 +CJK UNIFIED IDEOGRAPH:'B859:47193:稠 +CJK UNIFIED IDEOGRAPH:'B85A:47194:稔 +CJK UNIFIED IDEOGRAPH:'B85B:47195:稟 +CJK UNIFIED IDEOGRAPH:'B85C:47196:稞 +CJK UNIFIED IDEOGRAPH:'B85D:47197:窟 +CJK UNIFIED IDEOGRAPH:'B85E:47198:窠 +CJK UNIFIED IDEOGRAPH:'B85F:47199:筷 +CJK UNIFIED IDEOGRAPH:'B860:47200:節 +CJK UNIFIED IDEOGRAPH:'B861:47201:筠 +CJK UNIFIED IDEOGRAPH:'B862:47202:筮 +CJK UNIFIED IDEOGRAPH:'B863:47203:筧 +CJK UNIFIED IDEOGRAPH:'B864:47204:粱 +CJK UNIFIED IDEOGRAPH:'B865:47205:粳 +CJK UNIFIED IDEOGRAPH:'B866:47206:粵 +CJK UNIFIED IDEOGRAPH:'B867:47207:經 +CJK UNIFIED IDEOGRAPH:'B868:47208:絹 +CJK UNIFIED IDEOGRAPH:'B869:47209:綑 +CJK UNIFIED IDEOGRAPH:'B86A:47210:綁 +CJK UNIFIED IDEOGRAPH:'B86B:47211:綏 +CJK UNIFIED IDEOGRAPH:'B86C:47212:絛 +CJK UNIFIED IDEOGRAPH:'B86D:47213:置 +CJK UNIFIED IDEOGRAPH:'B86E:47214:罩 +CJK UNIFIED IDEOGRAPH:'B86F:47215:罪 +CJK UNIFIED IDEOGRAPH:'B870:47216:署 +CJK UNIFIED IDEOGRAPH:'B871:47217:義 +CJK UNIFIED IDEOGRAPH:'B872:47218:羨 +CJK UNIFIED IDEOGRAPH:'B873:47219:群 +CJK UNIFIED IDEOGRAPH:'B874:47220:聖 +CJK UNIFIED IDEOGRAPH:'B875:47221:聘 +CJK UNIFIED IDEOGRAPH:'B876:47222:肆 +CJK UNIFIED IDEOGRAPH:'B877:47223:肄 +CJK UNIFIED IDEOGRAPH:'B878:47224:腱 +CJK UNIFIED IDEOGRAPH:'B879:47225:腰 +CJK UNIFIED IDEOGRAPH:'B87A:47226:腸 +CJK UNIFIED IDEOGRAPH:'B87B:47227:腥 +CJK UNIFIED IDEOGRAPH:'B87C:47228:腮 +CJK UNIFIED IDEOGRAPH:'B87D:47229:腳 +CJK UNIFIED IDEOGRAPH:'B87E:47230:腫 +CJK UNIFIED IDEOGRAPH:'B8A1:47265:腹 +CJK UNIFIED IDEOGRAPH:'B8A2:47266:腺 +CJK UNIFIED IDEOGRAPH:'B8A3:47267:腦 +CJK UNIFIED IDEOGRAPH:'B8A4:47268:舅 +CJK UNIFIED IDEOGRAPH:'B8A5:47269:艇 +CJK UNIFIED IDEOGRAPH:'B8A6:47270:蒂 +CJK UNIFIED IDEOGRAPH:'B8A7:47271:葷 +CJK UNIFIED IDEOGRAPH:'B8A8:47272:落 +CJK UNIFIED IDEOGRAPH:'B8A9:47273:萱 +CJK UNIFIED IDEOGRAPH:'B8AA:47274:葵 +CJK UNIFIED IDEOGRAPH:'B8AB:47275:葦 +CJK UNIFIED IDEOGRAPH:'B8AC:47276:葫 +CJK UNIFIED IDEOGRAPH:'B8AD:47277:葉 +CJK UNIFIED IDEOGRAPH:'B8AE:47278:葬 +CJK UNIFIED IDEOGRAPH:'B8AF:47279:葛 +CJK UNIFIED IDEOGRAPH:'B8B0:47280:萼 +CJK UNIFIED IDEOGRAPH:'B8B1:47281:萵 +CJK UNIFIED IDEOGRAPH:'B8B2:47282:葡 +CJK UNIFIED IDEOGRAPH:'B8B3:47283:董 +CJK UNIFIED IDEOGRAPH:'B8B4:47284:葩 +CJK UNIFIED IDEOGRAPH:'B8B5:47285:葭 +CJK UNIFIED IDEOGRAPH:'B8B6:47286:葆 +CJK UNIFIED IDEOGRAPH:'B8B7:47287:虞 +CJK UNIFIED IDEOGRAPH:'B8B8:47288:虜 +CJK UNIFIED IDEOGRAPH:'B8B9:47289:號 +CJK UNIFIED IDEOGRAPH:'B8BA:47290:蛹 +CJK UNIFIED IDEOGRAPH:'B8BB:47291:蜓 +CJK UNIFIED IDEOGRAPH:'B8BC:47292:蜈 +CJK UNIFIED IDEOGRAPH:'B8BD:47293:蜇 +CJK UNIFIED IDEOGRAPH:'B8BE:47294:蜀 +CJK UNIFIED IDEOGRAPH:'B8BF:47295:蛾 +CJK UNIFIED IDEOGRAPH:'B8C0:47296:蛻 +CJK UNIFIED IDEOGRAPH:'B8C1:47297:蜂 +CJK UNIFIED IDEOGRAPH:'B8C2:47298:蜃 +CJK UNIFIED IDEOGRAPH:'B8C3:47299:蜆 +CJK UNIFIED IDEOGRAPH:'B8C4:47300:蜊 +CJK UNIFIED IDEOGRAPH:'B8C5:47301:衙 +CJK UNIFIED IDEOGRAPH:'B8C6:47302:裟 +CJK UNIFIED IDEOGRAPH:'B8C7:47303:裔 +CJK UNIFIED IDEOGRAPH:'B8C8:47304:裙 +CJK UNIFIED IDEOGRAPH:'B8C9:47305:補 +CJK UNIFIED IDEOGRAPH:'B8CA:47306:裘 +CJK UNIFIED IDEOGRAPH:'B8CB:47307:裝 +CJK UNIFIED IDEOGRAPH:'B8CC:47308:裡 +CJK UNIFIED IDEOGRAPH:'B8CD:47309:裊 +CJK UNIFIED IDEOGRAPH:'B8CE:47310:裕 +CJK UNIFIED IDEOGRAPH:'B8CF:47311:裒 +CJK UNIFIED IDEOGRAPH:'B8D0:47312:覜 +CJK UNIFIED IDEOGRAPH:'B8D1:47313:解 +CJK UNIFIED IDEOGRAPH:'B8D2:47314:詫 +CJK UNIFIED IDEOGRAPH:'B8D3:47315:該 +CJK UNIFIED IDEOGRAPH:'B8D4:47316:詳 +CJK UNIFIED IDEOGRAPH:'B8D5:47317:試 +CJK UNIFIED IDEOGRAPH:'B8D6:47318:詩 +CJK UNIFIED IDEOGRAPH:'B8D7:47319:詰 +CJK UNIFIED IDEOGRAPH:'B8D8:47320:誇 +CJK UNIFIED IDEOGRAPH:'B8D9:47321:詼 +CJK UNIFIED IDEOGRAPH:'B8DA:47322:詣 +CJK UNIFIED IDEOGRAPH:'B8DB:47323:誠 +CJK UNIFIED IDEOGRAPH:'B8DC:47324:話 +CJK UNIFIED IDEOGRAPH:'B8DD:47325:誅 +CJK UNIFIED IDEOGRAPH:'B8DE:47326:詭 +CJK UNIFIED IDEOGRAPH:'B8DF:47327:詢 +CJK UNIFIED IDEOGRAPH:'B8E0:47328:詮 +CJK UNIFIED IDEOGRAPH:'B8E1:47329:詬 +CJK UNIFIED IDEOGRAPH:'B8E2:47330:詹 +CJK UNIFIED IDEOGRAPH:'B8E3:47331:詻 +CJK UNIFIED IDEOGRAPH:'B8E4:47332:訾 +CJK UNIFIED IDEOGRAPH:'B8E5:47333:詨 +CJK UNIFIED IDEOGRAPH:'B8E6:47334:豢 +CJK UNIFIED IDEOGRAPH:'B8E7:47335:貊 +CJK UNIFIED IDEOGRAPH:'B8E8:47336:貉 +CJK UNIFIED IDEOGRAPH:'B8E9:47337:賊 +CJK UNIFIED IDEOGRAPH:'B8EA:47338:資 +CJK UNIFIED IDEOGRAPH:'B8EB:47339:賈 +CJK UNIFIED IDEOGRAPH:'B8EC:47340:賄 +CJK UNIFIED IDEOGRAPH:'B8ED:47341:貲 +CJK UNIFIED IDEOGRAPH:'B8EE:47342:賃 +CJK UNIFIED IDEOGRAPH:'B8EF:47343:賂 +CJK UNIFIED IDEOGRAPH:'B8F0:47344:賅 +CJK UNIFIED IDEOGRAPH:'B8F1:47345:跡 +CJK UNIFIED IDEOGRAPH:'B8F2:47346:跟 +CJK UNIFIED IDEOGRAPH:'B8F3:47347:跨 +CJK UNIFIED IDEOGRAPH:'B8F4:47348:路 +CJK UNIFIED IDEOGRAPH:'B8F5:47349:跳 +CJK UNIFIED IDEOGRAPH:'B8F6:47350:跺 +CJK UNIFIED IDEOGRAPH:'B8F7:47351:跪 +CJK UNIFIED IDEOGRAPH:'B8F8:47352:跤 +CJK UNIFIED IDEOGRAPH:'B8F9:47353:跦 +CJK UNIFIED IDEOGRAPH:'B8FA:47354:躲 +CJK UNIFIED IDEOGRAPH:'B8FB:47355:較 +CJK UNIFIED IDEOGRAPH:'B8FC:47356:載 +CJK UNIFIED IDEOGRAPH:'B8FD:47357:軾 +CJK UNIFIED IDEOGRAPH:'B8FE:47358:輊 +CJK UNIFIED IDEOGRAPH:'B940:47424:辟 +CJK UNIFIED IDEOGRAPH:'B941:47425:農 +CJK UNIFIED IDEOGRAPH:'B942:47426:運 +CJK UNIFIED IDEOGRAPH:'B943:47427:遊 +CJK UNIFIED IDEOGRAPH:'B944:47428:道 +CJK UNIFIED IDEOGRAPH:'B945:47429:遂 +CJK UNIFIED IDEOGRAPH:'B946:47430:達 +CJK UNIFIED IDEOGRAPH:'B947:47431:逼 +CJK UNIFIED IDEOGRAPH:'B948:47432:違 +CJK UNIFIED IDEOGRAPH:'B949:47433:遐 +CJK UNIFIED IDEOGRAPH:'B94A:47434:遇 +CJK UNIFIED IDEOGRAPH:'B94B:47435:遏 +CJK UNIFIED IDEOGRAPH:'B94C:47436:過 +CJK UNIFIED IDEOGRAPH:'B94D:47437:遍 +CJK UNIFIED IDEOGRAPH:'B94E:47438:遑 +CJK UNIFIED IDEOGRAPH:'B94F:47439:逾 +CJK UNIFIED IDEOGRAPH:'B950:47440:遁 +CJK UNIFIED IDEOGRAPH:'B951:47441:鄒 +CJK UNIFIED IDEOGRAPH:'B952:47442:鄗 +CJK UNIFIED IDEOGRAPH:'B953:47443:酬 +CJK UNIFIED IDEOGRAPH:'B954:47444:酪 +CJK UNIFIED IDEOGRAPH:'B955:47445:酩 +CJK UNIFIED IDEOGRAPH:'B956:47446:釉 +CJK UNIFIED IDEOGRAPH:'B957:47447:鈷 +CJK UNIFIED IDEOGRAPH:'B958:47448:鉗 +CJK UNIFIED IDEOGRAPH:'B959:47449:鈸 +CJK UNIFIED IDEOGRAPH:'B95A:47450:鈽 +CJK UNIFIED IDEOGRAPH:'B95B:47451:鉀 +CJK UNIFIED IDEOGRAPH:'B95C:47452:鈾 +CJK UNIFIED IDEOGRAPH:'B95D:47453:鉛 +CJK UNIFIED IDEOGRAPH:'B95E:47454:鉋 +CJK UNIFIED IDEOGRAPH:'B95F:47455:鉤 +CJK UNIFIED IDEOGRAPH:'B960:47456:鉑 +CJK UNIFIED IDEOGRAPH:'B961:47457:鈴 +CJK UNIFIED IDEOGRAPH:'B962:47458:鉉 +CJK UNIFIED IDEOGRAPH:'B963:47459:鉍 +CJK UNIFIED IDEOGRAPH:'B964:47460:鉅 +CJK UNIFIED IDEOGRAPH:'B965:47461:鈹 +CJK UNIFIED IDEOGRAPH:'B966:47462:鈿 +CJK UNIFIED IDEOGRAPH:'B967:47463:鉚 +CJK UNIFIED IDEOGRAPH:'B968:47464:閘 +CJK UNIFIED IDEOGRAPH:'B969:47465:隘 +CJK UNIFIED IDEOGRAPH:'B96A:47466:隔 +CJK UNIFIED IDEOGRAPH:'B96B:47467:隕 +CJK UNIFIED IDEOGRAPH:'B96C:47468:雍 +CJK UNIFIED IDEOGRAPH:'B96D:47469:雋 +CJK UNIFIED IDEOGRAPH:'B96E:47470:雉 +CJK UNIFIED IDEOGRAPH:'B96F:47471:雊 +CJK UNIFIED IDEOGRAPH:'B970:47472:雷 +CJK UNIFIED IDEOGRAPH:'B971:47473:電 +CJK UNIFIED IDEOGRAPH:'B972:47474:雹 +CJK UNIFIED IDEOGRAPH:'B973:47475:零 +CJK UNIFIED IDEOGRAPH:'B974:47476:靖 +CJK UNIFIED IDEOGRAPH:'B975:47477:靴 +CJK UNIFIED IDEOGRAPH:'B976:47478:靶 +CJK UNIFIED IDEOGRAPH:'B977:47479:預 +CJK UNIFIED IDEOGRAPH:'B978:47480:頑 +CJK UNIFIED IDEOGRAPH:'B979:47481:頓 +CJK UNIFIED IDEOGRAPH:'B97A:47482:頊 +CJK UNIFIED IDEOGRAPH:'B97B:47483:頒 +CJK UNIFIED IDEOGRAPH:'B97C:47484:頌 +CJK UNIFIED IDEOGRAPH:'B97D:47485:飼 +CJK UNIFIED IDEOGRAPH:'B97E:47486:飴 +CJK UNIFIED IDEOGRAPH:'B9A1:47521:飽 +CJK UNIFIED IDEOGRAPH:'B9A2:47522:飾 +CJK UNIFIED IDEOGRAPH:'B9A3:47523:馳 +CJK UNIFIED IDEOGRAPH:'B9A4:47524:馱 +CJK UNIFIED IDEOGRAPH:'B9A5:47525:馴 +CJK UNIFIED IDEOGRAPH:'B9A6:47526:髡 +CJK UNIFIED IDEOGRAPH:'B9A7:47527:鳩 +CJK UNIFIED IDEOGRAPH:'B9A8:47528:麂 +CJK UNIFIED IDEOGRAPH:'B9A9:47529:鼎 +CJK UNIFIED IDEOGRAPH:'B9AA:47530:鼓 +CJK UNIFIED IDEOGRAPH:'B9AB:47531:鼠 +CJK UNIFIED IDEOGRAPH:'B9AC:47532:僧 +CJK UNIFIED IDEOGRAPH:'B9AD:47533:僮 +CJK UNIFIED IDEOGRAPH:'B9AE:47534:僥 +CJK UNIFIED IDEOGRAPH:'B9AF:47535:僖 +CJK UNIFIED IDEOGRAPH:'B9B0:47536:僭 +CJK UNIFIED IDEOGRAPH:'B9B1:47537:僚 +CJK UNIFIED IDEOGRAPH:'B9B2:47538:僕 +CJK UNIFIED IDEOGRAPH:'B9B3:47539:像 +CJK UNIFIED IDEOGRAPH:'B9B4:47540:僑 +CJK UNIFIED IDEOGRAPH:'B9B5:47541:僱 +CJK UNIFIED IDEOGRAPH:'B9B6:47542:僎 +CJK UNIFIED IDEOGRAPH:'B9B7:47543:僩 +CJK UNIFIED IDEOGRAPH:'B9B8:47544:兢 +CJK UNIFIED IDEOGRAPH:'B9B9:47545:凳 +CJK UNIFIED IDEOGRAPH:'B9BA:47546:劃 +CJK UNIFIED IDEOGRAPH:'B9BB:47547:劂 +CJK UNIFIED IDEOGRAPH:'B9BC:47548:匱 +CJK UNIFIED IDEOGRAPH:'B9BD:47549:厭 +CJK UNIFIED IDEOGRAPH:'B9BE:47550:嗾 +CJK UNIFIED IDEOGRAPH:'B9BF:47551:嘀 +CJK UNIFIED IDEOGRAPH:'B9C0:47552:嘛 +CJK UNIFIED IDEOGRAPH:'B9C1:47553:嘗 +CJK UNIFIED IDEOGRAPH:'B9C2:47554:嗽 +CJK UNIFIED IDEOGRAPH:'B9C3:47555:嘔 +CJK UNIFIED IDEOGRAPH:'B9C4:47556:嘆 +CJK UNIFIED IDEOGRAPH:'B9C5:47557:嘉 +CJK UNIFIED IDEOGRAPH:'B9C6:47558:嘍 +CJK UNIFIED IDEOGRAPH:'B9C7:47559:嘎 +CJK UNIFIED IDEOGRAPH:'B9C8:47560:嗷 +CJK UNIFIED IDEOGRAPH:'B9C9:47561:嘖 +CJK UNIFIED IDEOGRAPH:'B9CA:47562:嘟 +CJK UNIFIED IDEOGRAPH:'B9CB:47563:嘈 +CJK UNIFIED IDEOGRAPH:'B9CC:47564:嘐 +CJK UNIFIED IDEOGRAPH:'B9CD:47565:嗶 +CJK UNIFIED IDEOGRAPH:'B9CE:47566:團 +CJK UNIFIED IDEOGRAPH:'B9CF:47567:圖 +CJK UNIFIED IDEOGRAPH:'B9D0:47568:塵 +CJK UNIFIED IDEOGRAPH:'B9D1:47569:塾 +CJK UNIFIED IDEOGRAPH:'B9D2:47570:境 +CJK UNIFIED IDEOGRAPH:'B9D3:47571:墓 +CJK UNIFIED IDEOGRAPH:'B9D4:47572:墊 +CJK UNIFIED IDEOGRAPH:'B9D5:47573:塹 +CJK UNIFIED IDEOGRAPH:'B9D6:47574:墅 +CJK UNIFIED IDEOGRAPH:'B9D7:47575:塽 +CJK UNIFIED IDEOGRAPH:'B9D8:47576:壽 +CJK UNIFIED IDEOGRAPH:'B9D9:47577:夥 +CJK UNIFIED IDEOGRAPH:'B9DA:47578:夢 +CJK UNIFIED IDEOGRAPH:'B9DB:47579:夤 +CJK UNIFIED IDEOGRAPH:'B9DC:47580:奪 +CJK UNIFIED IDEOGRAPH:'B9DD:47581:奩 +CJK UNIFIED IDEOGRAPH:'B9DE:47582:嫡 +CJK UNIFIED IDEOGRAPH:'B9DF:47583:嫦 +CJK UNIFIED IDEOGRAPH:'B9E0:47584:嫩 +CJK UNIFIED IDEOGRAPH:'B9E1:47585:嫗 +CJK UNIFIED IDEOGRAPH:'B9E2:47586:嫖 +CJK UNIFIED IDEOGRAPH:'B9E3:47587:嫘 +CJK UNIFIED IDEOGRAPH:'B9E4:47588:嫣 +CJK UNIFIED IDEOGRAPH:'B9E5:47589:孵 +CJK UNIFIED IDEOGRAPH:'B9E6:47590:寞 +CJK UNIFIED IDEOGRAPH:'B9E7:47591:寧 +CJK UNIFIED IDEOGRAPH:'B9E8:47592:寡 +CJK UNIFIED IDEOGRAPH:'B9E9:47593:寥 +CJK UNIFIED IDEOGRAPH:'B9EA:47594:實 +CJK UNIFIED IDEOGRAPH:'B9EB:47595:寨 +CJK UNIFIED IDEOGRAPH:'B9EC:47596:寢 +CJK UNIFIED IDEOGRAPH:'B9ED:47597:寤 +CJK UNIFIED IDEOGRAPH:'B9EE:47598:察 +CJK UNIFIED IDEOGRAPH:'B9EF:47599:對 +CJK UNIFIED IDEOGRAPH:'B9F0:47600:屢 +CJK UNIFIED IDEOGRAPH:'B9F1:47601:嶄 +CJK UNIFIED IDEOGRAPH:'B9F2:47602:嶇 +CJK UNIFIED IDEOGRAPH:'B9F3:47603:幛 +CJK UNIFIED IDEOGRAPH:'B9F4:47604:幣 +CJK UNIFIED IDEOGRAPH:'B9F5:47605:幕 +CJK UNIFIED IDEOGRAPH:'B9F6:47606:幗 +CJK UNIFIED IDEOGRAPH:'B9F7:47607:幔 +CJK UNIFIED IDEOGRAPH:'B9F8:47608:廓 +CJK UNIFIED IDEOGRAPH:'B9F9:47609:廖 +CJK UNIFIED IDEOGRAPH:'B9FA:47610:弊 +CJK UNIFIED IDEOGRAPH:'B9FB:47611:彆 +CJK UNIFIED IDEOGRAPH:'B9FC:47612:彰 +CJK UNIFIED IDEOGRAPH:'B9FD:47613:徹 +CJK UNIFIED IDEOGRAPH:'B9FE:47614:慇 +CJK UNIFIED IDEOGRAPH:'BA40:47680:愿 +CJK UNIFIED IDEOGRAPH:'BA41:47681:態 +CJK UNIFIED IDEOGRAPH:'BA42:47682:慷 +CJK UNIFIED IDEOGRAPH:'BA43:47683:慢 +CJK UNIFIED IDEOGRAPH:'BA44:47684:慣 +CJK UNIFIED IDEOGRAPH:'BA45:47685:慟 +CJK UNIFIED IDEOGRAPH:'BA46:47686:慚 +CJK UNIFIED IDEOGRAPH:'BA47:47687:慘 +CJK UNIFIED IDEOGRAPH:'BA48:47688:慵 +CJK UNIFIED IDEOGRAPH:'BA49:47689:截 +CJK UNIFIED IDEOGRAPH:'BA4A:47690:撇 +CJK UNIFIED IDEOGRAPH:'BA4B:47691:摘 +CJK UNIFIED IDEOGRAPH:'BA4C:47692:摔 +CJK UNIFIED IDEOGRAPH:'BA4D:47693:撤 +CJK UNIFIED IDEOGRAPH:'BA4E:47694:摸 +CJK UNIFIED IDEOGRAPH:'BA4F:47695:摟 +CJK UNIFIED IDEOGRAPH:'BA50:47696:摺 +CJK UNIFIED IDEOGRAPH:'BA51:47697:摑 +CJK UNIFIED IDEOGRAPH:'BA52:47698:摧 +CJK UNIFIED IDEOGRAPH:'BA53:47699:搴 +CJK UNIFIED IDEOGRAPH:'BA54:47700:摭 +CJK UNIFIED IDEOGRAPH:'BA55:47701:摻 +CJK UNIFIED IDEOGRAPH:'BA56:47702:敲 +CJK UNIFIED IDEOGRAPH:'BA57:47703:斡 +CJK UNIFIED IDEOGRAPH:'BA58:47704:旗 +CJK UNIFIED IDEOGRAPH:'BA59:47705:旖 +CJK UNIFIED IDEOGRAPH:'BA5A:47706:暢 +CJK UNIFIED IDEOGRAPH:'BA5B:47707:暨 +CJK UNIFIED IDEOGRAPH:'BA5C:47708:暝 +CJK UNIFIED IDEOGRAPH:'BA5D:47709:榜 +CJK UNIFIED IDEOGRAPH:'BA5E:47710:榨 +CJK UNIFIED IDEOGRAPH:'BA5F:47711:榕 +CJK UNIFIED IDEOGRAPH:'BA60:47712:槁 +CJK UNIFIED IDEOGRAPH:'BA61:47713:榮 +CJK UNIFIED IDEOGRAPH:'BA62:47714:槓 +CJK UNIFIED IDEOGRAPH:'BA63:47715:構 +CJK UNIFIED IDEOGRAPH:'BA64:47716:榛 +CJK UNIFIED IDEOGRAPH:'BA65:47717:榷 +CJK UNIFIED IDEOGRAPH:'BA66:47718:榻 +CJK UNIFIED IDEOGRAPH:'BA67:47719:榫 +CJK UNIFIED IDEOGRAPH:'BA68:47720:榴 +CJK UNIFIED IDEOGRAPH:'BA69:47721:槐 +CJK UNIFIED IDEOGRAPH:'BA6A:47722:槍 +CJK UNIFIED IDEOGRAPH:'BA6B:47723:榭 +CJK UNIFIED IDEOGRAPH:'BA6C:47724:槌 +CJK UNIFIED IDEOGRAPH:'BA6D:47725:榦 +CJK UNIFIED IDEOGRAPH:'BA6E:47726:槃 +CJK UNIFIED IDEOGRAPH:'BA6F:47727:榣 +CJK UNIFIED IDEOGRAPH:'BA70:47728:歉 +CJK UNIFIED IDEOGRAPH:'BA71:47729:歌 +CJK UNIFIED IDEOGRAPH:'BA72:47730:氳 +CJK UNIFIED IDEOGRAPH:'BA73:47731:漳 +CJK UNIFIED IDEOGRAPH:'BA74:47732:演 +CJK UNIFIED IDEOGRAPH:'BA75:47733:滾 +CJK UNIFIED IDEOGRAPH:'BA76:47734:漓 +CJK UNIFIED IDEOGRAPH:'BA77:47735:滴 +CJK UNIFIED IDEOGRAPH:'BA78:47736:漩 +CJK UNIFIED IDEOGRAPH:'BA79:47737:漾 +CJK UNIFIED IDEOGRAPH:'BA7A:47738:漠 +CJK UNIFIED IDEOGRAPH:'BA7B:47739:漬 +CJK UNIFIED IDEOGRAPH:'BA7C:47740:漏 +CJK UNIFIED IDEOGRAPH:'BA7D:47741:漂 +CJK UNIFIED IDEOGRAPH:'BA7E:47742:漢 +CJK UNIFIED IDEOGRAPH:'BAA1:47777:滿 +CJK UNIFIED IDEOGRAPH:'BAA2:47778:滯 +CJK UNIFIED IDEOGRAPH:'BAA3:47779:漆 +CJK UNIFIED IDEOGRAPH:'BAA4:47780:漱 +CJK UNIFIED IDEOGRAPH:'BAA5:47781:漸 +CJK UNIFIED IDEOGRAPH:'BAA6:47782:漲 +CJK UNIFIED IDEOGRAPH:'BAA7:47783:漣 +CJK UNIFIED IDEOGRAPH:'BAA8:47784:漕 +CJK UNIFIED IDEOGRAPH:'BAA9:47785:漫 +CJK UNIFIED IDEOGRAPH:'BAAA:47786:漯 +CJK UNIFIED IDEOGRAPH:'BAAB:47787:澈 +CJK UNIFIED IDEOGRAPH:'BAAC:47788:漪 +CJK UNIFIED IDEOGRAPH:'BAAD:47789:滬 +CJK UNIFIED IDEOGRAPH:'BAAE:47790:漁 +CJK UNIFIED IDEOGRAPH:'BAAF:47791:滲 +CJK UNIFIED IDEOGRAPH:'BAB0:47792:滌 +CJK UNIFIED IDEOGRAPH:'BAB1:47793:滷 +CJK UNIFIED IDEOGRAPH:'BAB2:47794:熔 +CJK UNIFIED IDEOGRAPH:'BAB3:47795:熙 +CJK UNIFIED IDEOGRAPH:'BAB4:47796:煽 +CJK UNIFIED IDEOGRAPH:'BAB5:47797:熊 +CJK UNIFIED IDEOGRAPH:'BAB6:47798:熄 +CJK UNIFIED IDEOGRAPH:'BAB7:47799:熒 +CJK UNIFIED IDEOGRAPH:'BAB8:47800:爾 +CJK UNIFIED IDEOGRAPH:'BAB9:47801:犒 +CJK UNIFIED IDEOGRAPH:'BABA:47802:犖 +CJK UNIFIED IDEOGRAPH:'BABB:47803:獄 +CJK UNIFIED IDEOGRAPH:'BABC:47804:獐 +CJK UNIFIED IDEOGRAPH:'BABD:47805:瑤 +CJK UNIFIED IDEOGRAPH:'BABE:47806:瑣 +CJK UNIFIED IDEOGRAPH:'BABF:47807:瑪 +CJK UNIFIED IDEOGRAPH:'BAC0:47808:瑰 +CJK UNIFIED IDEOGRAPH:'BAC1:47809:瑭 +CJK UNIFIED IDEOGRAPH:'BAC2:47810:甄 +CJK UNIFIED IDEOGRAPH:'BAC3:47811:疑 +CJK UNIFIED IDEOGRAPH:'BAC4:47812:瘧 +CJK UNIFIED IDEOGRAPH:'BAC5:47813:瘍 +CJK UNIFIED IDEOGRAPH:'BAC6:47814:瘋 +CJK UNIFIED IDEOGRAPH:'BAC7:47815:瘉 +CJK UNIFIED IDEOGRAPH:'BAC8:47816:瘓 +CJK UNIFIED IDEOGRAPH:'BAC9:47817:盡 +CJK UNIFIED IDEOGRAPH:'BACA:47818:監 +CJK UNIFIED IDEOGRAPH:'BACB:47819:瞄 +CJK UNIFIED IDEOGRAPH:'BACC:47820:睽 +CJK UNIFIED IDEOGRAPH:'BACD:47821:睿 +CJK UNIFIED IDEOGRAPH:'BACE:47822:睡 +CJK UNIFIED IDEOGRAPH:'BACF:47823:磁 +CJK UNIFIED IDEOGRAPH:'BAD0:47824:碟 +CJK UNIFIED IDEOGRAPH:'BAD1:47825:碧 +CJK UNIFIED IDEOGRAPH:'BAD2:47826:碳 +CJK UNIFIED IDEOGRAPH:'BAD3:47827:碩 +CJK UNIFIED IDEOGRAPH:'BAD4:47828:碣 +CJK UNIFIED IDEOGRAPH:'BAD5:47829:禎 +CJK UNIFIED IDEOGRAPH:'BAD6:47830:福 +CJK UNIFIED IDEOGRAPH:'BAD7:47831:禍 +CJK UNIFIED IDEOGRAPH:'BAD8:47832:種 +CJK UNIFIED IDEOGRAPH:'BAD9:47833:稱 +CJK UNIFIED IDEOGRAPH:'BADA:47834:窪 +CJK UNIFIED IDEOGRAPH:'BADB:47835:窩 +CJK UNIFIED IDEOGRAPH:'BADC:47836:竭 +CJK UNIFIED IDEOGRAPH:'BADD:47837:端 +CJK UNIFIED IDEOGRAPH:'BADE:47838:管 +CJK UNIFIED IDEOGRAPH:'BADF:47839:箕 +CJK UNIFIED IDEOGRAPH:'BAE0:47840:箋 +CJK UNIFIED IDEOGRAPH:'BAE1:47841:筵 +CJK UNIFIED IDEOGRAPH:'BAE2:47842:算 +CJK UNIFIED IDEOGRAPH:'BAE3:47843:箝 +CJK UNIFIED IDEOGRAPH:'BAE4:47844:箔 +CJK UNIFIED IDEOGRAPH:'BAE5:47845:箏 +CJK UNIFIED IDEOGRAPH:'BAE6:47846:箸 +CJK UNIFIED IDEOGRAPH:'BAE7:47847:箇 +CJK UNIFIED IDEOGRAPH:'BAE8:47848:箄 +CJK UNIFIED IDEOGRAPH:'BAE9:47849:粹 +CJK UNIFIED IDEOGRAPH:'BAEA:47850:粽 +CJK UNIFIED IDEOGRAPH:'BAEB:47851:精 +CJK UNIFIED IDEOGRAPH:'BAEC:47852:綻 +CJK UNIFIED IDEOGRAPH:'BAED:47853:綰 +CJK UNIFIED IDEOGRAPH:'BAEE:47854:綜 +CJK UNIFIED IDEOGRAPH:'BAEF:47855:綽 +CJK UNIFIED IDEOGRAPH:'BAF0:47856:綾 +CJK UNIFIED IDEOGRAPH:'BAF1:47857:綠 +CJK UNIFIED IDEOGRAPH:'BAF2:47858:緊 +CJK UNIFIED IDEOGRAPH:'BAF3:47859:綴 +CJK UNIFIED IDEOGRAPH:'BAF4:47860:網 +CJK UNIFIED IDEOGRAPH:'BAF5:47861:綱 +CJK UNIFIED IDEOGRAPH:'BAF6:47862:綺 +CJK UNIFIED IDEOGRAPH:'BAF7:47863:綢 +CJK UNIFIED IDEOGRAPH:'BAF8:47864:綿 +CJK UNIFIED IDEOGRAPH:'BAF9:47865:綵 +CJK UNIFIED IDEOGRAPH:'BAFA:47866:綸 +CJK UNIFIED IDEOGRAPH:'BAFB:47867:維 +CJK UNIFIED IDEOGRAPH:'BAFC:47868:緒 +CJK UNIFIED IDEOGRAPH:'BAFD:47869:緇 +CJK UNIFIED IDEOGRAPH:'BAFE:47870:綬 +CJK UNIFIED IDEOGRAPH:'BB40:47936:罰 +CJK UNIFIED IDEOGRAPH:'BB41:47937:翠 +CJK UNIFIED IDEOGRAPH:'BB42:47938:翡 +CJK UNIFIED IDEOGRAPH:'BB43:47939:翟 +CJK UNIFIED IDEOGRAPH:'BB44:47940:聞 +CJK UNIFIED IDEOGRAPH:'BB45:47941:聚 +CJK UNIFIED IDEOGRAPH:'BB46:47942:肇 +CJK UNIFIED IDEOGRAPH:'BB47:47943:腐 +CJK UNIFIED IDEOGRAPH:'BB48:47944:膀 +CJK UNIFIED IDEOGRAPH:'BB49:47945:膏 +CJK UNIFIED IDEOGRAPH:'BB4A:47946:膈 +CJK UNIFIED IDEOGRAPH:'BB4B:47947:膊 +CJK UNIFIED IDEOGRAPH:'BB4C:47948:腿 +CJK UNIFIED IDEOGRAPH:'BB4D:47949:膂 +CJK UNIFIED IDEOGRAPH:'BB4E:47950:臧 +CJK UNIFIED IDEOGRAPH:'BB4F:47951:臺 +CJK UNIFIED IDEOGRAPH:'BB50:47952:與 +CJK UNIFIED IDEOGRAPH:'BB51:47953:舔 +CJK UNIFIED IDEOGRAPH:'BB52:47954:舞 +CJK UNIFIED IDEOGRAPH:'BB53:47955:艋 +CJK UNIFIED IDEOGRAPH:'BB54:47956:蓉 +CJK UNIFIED IDEOGRAPH:'BB55:47957:蒿 +CJK UNIFIED IDEOGRAPH:'BB56:47958:蓆 +CJK UNIFIED IDEOGRAPH:'BB57:47959:蓄 +CJK UNIFIED IDEOGRAPH:'BB58:47960:蒙 +CJK UNIFIED IDEOGRAPH:'BB59:47961:蒞 +CJK UNIFIED IDEOGRAPH:'BB5A:47962:蒲 +CJK UNIFIED IDEOGRAPH:'BB5B:47963:蒜 +CJK UNIFIED IDEOGRAPH:'BB5C:47964:蓋 +CJK UNIFIED IDEOGRAPH:'BB5D:47965:蒸 +CJK UNIFIED IDEOGRAPH:'BB5E:47966:蓀 +CJK UNIFIED IDEOGRAPH:'BB5F:47967:蓓 +CJK UNIFIED IDEOGRAPH:'BB60:47968:蒐 +CJK UNIFIED IDEOGRAPH:'BB61:47969:蒼 +CJK UNIFIED IDEOGRAPH:'BB62:47970:蓑 +CJK UNIFIED IDEOGRAPH:'BB63:47971:蓊 +CJK UNIFIED IDEOGRAPH:'BB64:47972:蜿 +CJK UNIFIED IDEOGRAPH:'BB65:47973:蜜 +CJK UNIFIED IDEOGRAPH:'BB66:47974:蜻 +CJK UNIFIED IDEOGRAPH:'BB67:47975:蜢 +CJK UNIFIED IDEOGRAPH:'BB68:47976:蜥 +CJK UNIFIED IDEOGRAPH:'BB69:47977:蜴 +CJK UNIFIED IDEOGRAPH:'BB6A:47978:蜘 +CJK UNIFIED IDEOGRAPH:'BB6B:47979:蝕 +CJK UNIFIED IDEOGRAPH:'BB6C:47980:蜷 +CJK UNIFIED IDEOGRAPH:'BB6D:47981:蜩 +CJK UNIFIED IDEOGRAPH:'BB6E:47982:裳 +CJK UNIFIED IDEOGRAPH:'BB6F:47983:褂 +CJK UNIFIED IDEOGRAPH:'BB70:47984:裴 +CJK UNIFIED IDEOGRAPH:'BB71:47985:裹 +CJK UNIFIED IDEOGRAPH:'BB72:47986:裸 +CJK UNIFIED IDEOGRAPH:'BB73:47987:製 +CJK UNIFIED IDEOGRAPH:'BB74:47988:裨 +CJK UNIFIED IDEOGRAPH:'BB75:47989:褚 +CJK UNIFIED IDEOGRAPH:'BB76:47990:裯 +CJK UNIFIED IDEOGRAPH:'BB77:47991:誦 +CJK UNIFIED IDEOGRAPH:'BB78:47992:誌 +CJK UNIFIED IDEOGRAPH:'BB79:47993:語 +CJK UNIFIED IDEOGRAPH:'BB7A:47994:誣 +CJK UNIFIED IDEOGRAPH:'BB7B:47995:認 +CJK UNIFIED IDEOGRAPH:'BB7C:47996:誡 +CJK UNIFIED IDEOGRAPH:'BB7D:47997:誓 +CJK UNIFIED IDEOGRAPH:'BB7E:47998:誤 +CJK UNIFIED IDEOGRAPH:'BBA1:48033:說 +CJK UNIFIED IDEOGRAPH:'BBA2:48034:誥 +CJK UNIFIED IDEOGRAPH:'BBA3:48035:誨 +CJK UNIFIED IDEOGRAPH:'BBA4:48036:誘 +CJK UNIFIED IDEOGRAPH:'BBA5:48037:誑 +CJK UNIFIED IDEOGRAPH:'BBA6:48038:誚 +CJK UNIFIED IDEOGRAPH:'BBA7:48039:誧 +CJK UNIFIED IDEOGRAPH:'BBA8:48040:豪 +CJK UNIFIED IDEOGRAPH:'BBA9:48041:貍 +CJK UNIFIED IDEOGRAPH:'BBAA:48042:貌 +CJK UNIFIED IDEOGRAPH:'BBAB:48043:賓 +CJK UNIFIED IDEOGRAPH:'BBAC:48044:賑 +CJK UNIFIED IDEOGRAPH:'BBAD:48045:賒 +CJK UNIFIED IDEOGRAPH:'BBAE:48046:赫 +CJK UNIFIED IDEOGRAPH:'BBAF:48047:趙 +CJK UNIFIED IDEOGRAPH:'BBB0:48048:趕 +CJK UNIFIED IDEOGRAPH:'BBB1:48049:跼 +CJK UNIFIED IDEOGRAPH:'BBB2:48050:輔 +CJK UNIFIED IDEOGRAPH:'BBB3:48051:輒 +CJK UNIFIED IDEOGRAPH:'BBB4:48052:輕 +CJK UNIFIED IDEOGRAPH:'BBB5:48053:輓 +CJK UNIFIED IDEOGRAPH:'BBB6:48054:辣 +CJK UNIFIED IDEOGRAPH:'BBB7:48055:遠 +CJK UNIFIED IDEOGRAPH:'BBB8:48056:遘 +CJK UNIFIED IDEOGRAPH:'BBB9:48057:遜 +CJK UNIFIED IDEOGRAPH:'BBBA:48058:遣 +CJK UNIFIED IDEOGRAPH:'BBBB:48059:遙 +CJK UNIFIED IDEOGRAPH:'BBBC:48060:遞 +CJK UNIFIED IDEOGRAPH:'BBBD:48061:遢 +CJK UNIFIED IDEOGRAPH:'BBBE:48062:遝 +CJK UNIFIED IDEOGRAPH:'BBBF:48063:遛 +CJK UNIFIED IDEOGRAPH:'BBC0:48064:鄙 +CJK UNIFIED IDEOGRAPH:'BBC1:48065:鄘 +CJK UNIFIED IDEOGRAPH:'BBC2:48066:鄞 +CJK UNIFIED IDEOGRAPH:'BBC3:48067:酵 +CJK UNIFIED IDEOGRAPH:'BBC4:48068:酸 +CJK UNIFIED IDEOGRAPH:'BBC5:48069:酷 +CJK UNIFIED IDEOGRAPH:'BBC6:48070:酴 +CJK UNIFIED IDEOGRAPH:'BBC7:48071:鉸 +CJK UNIFIED IDEOGRAPH:'BBC8:48072:銀 +CJK UNIFIED IDEOGRAPH:'BBC9:48073:銅 +CJK UNIFIED IDEOGRAPH:'BBCA:48074:銘 +CJK UNIFIED IDEOGRAPH:'BBCB:48075:銖 +CJK UNIFIED IDEOGRAPH:'BBCC:48076:鉻 +CJK UNIFIED IDEOGRAPH:'BBCD:48077:銓 +CJK UNIFIED IDEOGRAPH:'BBCE:48078:銜 +CJK UNIFIED IDEOGRAPH:'BBCF:48079:銨 +CJK UNIFIED IDEOGRAPH:'BBD0:48080:鉼 +CJK UNIFIED IDEOGRAPH:'BBD1:48081:銑 +CJK UNIFIED IDEOGRAPH:'BBD2:48082:閡 +CJK UNIFIED IDEOGRAPH:'BBD3:48083:閨 +CJK UNIFIED IDEOGRAPH:'BBD4:48084:閩 +CJK UNIFIED IDEOGRAPH:'BBD5:48085:閣 +CJK UNIFIED IDEOGRAPH:'BBD6:48086:閥 +CJK UNIFIED IDEOGRAPH:'BBD7:48087:閤 +CJK UNIFIED IDEOGRAPH:'BBD8:48088:隙 +CJK UNIFIED IDEOGRAPH:'BBD9:48089:障 +CJK UNIFIED IDEOGRAPH:'BBDA:48090:際 +CJK UNIFIED IDEOGRAPH:'BBDB:48091:雌 +CJK UNIFIED IDEOGRAPH:'BBDC:48092:雒 +CJK UNIFIED IDEOGRAPH:'BBDD:48093:需 +CJK UNIFIED IDEOGRAPH:'BBDE:48094:靼 +CJK UNIFIED IDEOGRAPH:'BBDF:48095:鞅 +CJK UNIFIED IDEOGRAPH:'BBE0:48096:韶 +CJK UNIFIED IDEOGRAPH:'BBE1:48097:頗 +CJK UNIFIED IDEOGRAPH:'BBE2:48098:領 +CJK UNIFIED IDEOGRAPH:'BBE3:48099:颯 +CJK UNIFIED IDEOGRAPH:'BBE4:48100:颱 +CJK UNIFIED IDEOGRAPH:'BBE5:48101:餃 +CJK UNIFIED IDEOGRAPH:'BBE6:48102:餅 +CJK UNIFIED IDEOGRAPH:'BBE7:48103:餌 +CJK UNIFIED IDEOGRAPH:'BBE8:48104:餉 +CJK UNIFIED IDEOGRAPH:'BBE9:48105:駁 +CJK UNIFIED IDEOGRAPH:'BBEA:48106:骯 +CJK UNIFIED IDEOGRAPH:'BBEB:48107:骰 +CJK UNIFIED IDEOGRAPH:'BBEC:48108:髦 +CJK UNIFIED IDEOGRAPH:'BBED:48109:魁 +CJK UNIFIED IDEOGRAPH:'BBEE:48110:魂 +CJK UNIFIED IDEOGRAPH:'BBEF:48111:鳴 +CJK UNIFIED IDEOGRAPH:'BBF0:48112:鳶 +CJK UNIFIED IDEOGRAPH:'BBF1:48113:鳳 +CJK UNIFIED IDEOGRAPH:'BBF2:48114:麼 +CJK UNIFIED IDEOGRAPH:'BBF3:48115:鼻 +CJK UNIFIED IDEOGRAPH:'BBF4:48116:齊 +CJK UNIFIED IDEOGRAPH:'BBF5:48117:億 +CJK UNIFIED IDEOGRAPH:'BBF6:48118:儀 +CJK UNIFIED IDEOGRAPH:'BBF7:48119:僻 +CJK UNIFIED IDEOGRAPH:'BBF8:48120:僵 +CJK UNIFIED IDEOGRAPH:'BBF9:48121:價 +CJK UNIFIED IDEOGRAPH:'BBFA:48122:儂 +CJK UNIFIED IDEOGRAPH:'BBFB:48123:儈 +CJK UNIFIED IDEOGRAPH:'BBFC:48124:儉 +CJK UNIFIED IDEOGRAPH:'BBFD:48125:儅 +CJK UNIFIED IDEOGRAPH:'BBFE:48126:凜 +CJK UNIFIED IDEOGRAPH:'BC40:48192:劇 +CJK UNIFIED IDEOGRAPH:'BC41:48193:劈 +CJK UNIFIED IDEOGRAPH:'BC42:48194:劉 +CJK UNIFIED IDEOGRAPH:'BC43:48195:劍 +CJK UNIFIED IDEOGRAPH:'BC44:48196:劊 +CJK UNIFIED IDEOGRAPH:'BC45:48197:勰 +CJK UNIFIED IDEOGRAPH:'BC46:48198:厲 +CJK UNIFIED IDEOGRAPH:'BC47:48199:嘮 +CJK UNIFIED IDEOGRAPH:'BC48:48200:嘻 +CJK UNIFIED IDEOGRAPH:'BC49:48201:嘹 +CJK UNIFIED IDEOGRAPH:'BC4A:48202:嘲 +CJK UNIFIED IDEOGRAPH:'BC4B:48203:嘿 +CJK UNIFIED IDEOGRAPH:'BC4C:48204:嘴 +CJK UNIFIED IDEOGRAPH:'BC4D:48205:嘩 +CJK UNIFIED IDEOGRAPH:'BC4E:48206:噓 +CJK UNIFIED IDEOGRAPH:'BC4F:48207:噎 +CJK UNIFIED IDEOGRAPH:'BC50:48208:噗 +CJK UNIFIED IDEOGRAPH:'BC51:48209:噴 +CJK UNIFIED IDEOGRAPH:'BC52:48210:嘶 +CJK UNIFIED IDEOGRAPH:'BC53:48211:嘯 +CJK UNIFIED IDEOGRAPH:'BC54:48212:嘰 +CJK UNIFIED IDEOGRAPH:'BC55:48213:墀 +CJK UNIFIED IDEOGRAPH:'BC56:48214:墟 +CJK UNIFIED IDEOGRAPH:'BC57:48215:增 +CJK UNIFIED IDEOGRAPH:'BC58:48216:墳 +CJK UNIFIED IDEOGRAPH:'BC59:48217:墜 +CJK UNIFIED IDEOGRAPH:'BC5A:48218:墮 +CJK UNIFIED IDEOGRAPH:'BC5B:48219:墩 +CJK UNIFIED IDEOGRAPH:'BC5C:48220:墦 +CJK UNIFIED IDEOGRAPH:'BC5D:48221:奭 +CJK UNIFIED IDEOGRAPH:'BC5E:48222:嬉 +CJK UNIFIED IDEOGRAPH:'BC5F:48223:嫻 +CJK UNIFIED IDEOGRAPH:'BC60:48224:嬋 +CJK UNIFIED IDEOGRAPH:'BC61:48225:嫵 +CJK UNIFIED IDEOGRAPH:'BC62:48226:嬌 +CJK UNIFIED IDEOGRAPH:'BC63:48227:嬈 +CJK UNIFIED IDEOGRAPH:'BC64:48228:寮 +CJK UNIFIED IDEOGRAPH:'BC65:48229:寬 +CJK UNIFIED IDEOGRAPH:'BC66:48230:審 +CJK UNIFIED IDEOGRAPH:'BC67:48231:寫 +CJK UNIFIED IDEOGRAPH:'BC68:48232:層 +CJK UNIFIED IDEOGRAPH:'BC69:48233:履 +CJK UNIFIED IDEOGRAPH:'BC6A:48234:嶝 +CJK UNIFIED IDEOGRAPH:'BC6B:48235:嶔 +CJK UNIFIED IDEOGRAPH:'BC6C:48236:幢 +CJK UNIFIED IDEOGRAPH:'BC6D:48237:幟 +CJK UNIFIED IDEOGRAPH:'BC6E:48238:幡 +CJK UNIFIED IDEOGRAPH:'BC6F:48239:廢 +CJK UNIFIED IDEOGRAPH:'BC70:48240:廚 +CJK UNIFIED IDEOGRAPH:'BC71:48241:廟 +CJK UNIFIED IDEOGRAPH:'BC72:48242:廝 +CJK UNIFIED IDEOGRAPH:'BC73:48243:廣 +CJK UNIFIED IDEOGRAPH:'BC74:48244:廠 +CJK UNIFIED IDEOGRAPH:'BC75:48245:彈 +CJK UNIFIED IDEOGRAPH:'BC76:48246:影 +CJK UNIFIED IDEOGRAPH:'BC77:48247:德 +CJK UNIFIED IDEOGRAPH:'BC78:48248:徵 +CJK UNIFIED IDEOGRAPH:'BC79:48249:慶 +CJK UNIFIED IDEOGRAPH:'BC7A:48250:慧 +CJK UNIFIED IDEOGRAPH:'BC7B:48251:慮 +CJK UNIFIED IDEOGRAPH:'BC7C:48252:慝 +CJK UNIFIED IDEOGRAPH:'BC7D:48253:慕 +CJK UNIFIED IDEOGRAPH:'BC7E:48254:憂 +CJK UNIFIED IDEOGRAPH:'BCA1:48289:慼 +CJK UNIFIED IDEOGRAPH:'BCA2:48290:慰 +CJK UNIFIED IDEOGRAPH:'BCA3:48291:慫 +CJK UNIFIED IDEOGRAPH:'BCA4:48292:慾 +CJK UNIFIED IDEOGRAPH:'BCA5:48293:憧 +CJK UNIFIED IDEOGRAPH:'BCA6:48294:憐 +CJK UNIFIED IDEOGRAPH:'BCA7:48295:憫 +CJK UNIFIED IDEOGRAPH:'BCA8:48296:憎 +CJK UNIFIED IDEOGRAPH:'BCA9:48297:憬 +CJK UNIFIED IDEOGRAPH:'BCAA:48298:憚 +CJK UNIFIED IDEOGRAPH:'BCAB:48299:憤 +CJK UNIFIED IDEOGRAPH:'BCAC:48300:憔 +CJK UNIFIED IDEOGRAPH:'BCAD:48301:憮 +CJK UNIFIED IDEOGRAPH:'BCAE:48302:戮 +CJK UNIFIED IDEOGRAPH:'BCAF:48303:摩 +CJK UNIFIED IDEOGRAPH:'BCB0:48304:摯 +CJK UNIFIED IDEOGRAPH:'BCB1:48305:摹 +CJK UNIFIED IDEOGRAPH:'BCB2:48306:撞 +CJK UNIFIED IDEOGRAPH:'BCB3:48307:撲 +CJK UNIFIED IDEOGRAPH:'BCB4:48308:撈 +CJK UNIFIED IDEOGRAPH:'BCB5:48309:撐 +CJK UNIFIED IDEOGRAPH:'BCB6:48310:撰 +CJK UNIFIED IDEOGRAPH:'BCB7:48311:撥 +CJK UNIFIED IDEOGRAPH:'BCB8:48312:撓 +CJK UNIFIED IDEOGRAPH:'BCB9:48313:撕 +CJK UNIFIED IDEOGRAPH:'BCBA:48314:撩 +CJK UNIFIED IDEOGRAPH:'BCBB:48315:撒 +CJK UNIFIED IDEOGRAPH:'BCBC:48316:撮 +CJK UNIFIED IDEOGRAPH:'BCBD:48317:播 +CJK UNIFIED IDEOGRAPH:'BCBE:48318:撫 +CJK UNIFIED IDEOGRAPH:'BCBF:48319:撚 +CJK UNIFIED IDEOGRAPH:'BCC0:48320:撬 +CJK UNIFIED IDEOGRAPH:'BCC1:48321:撙 +CJK UNIFIED IDEOGRAPH:'BCC2:48322:撢 +CJK UNIFIED IDEOGRAPH:'BCC3:48323:撳 +CJK UNIFIED IDEOGRAPH:'BCC4:48324:敵 +CJK UNIFIED IDEOGRAPH:'BCC5:48325:敷 +CJK UNIFIED IDEOGRAPH:'BCC6:48326:數 +CJK UNIFIED IDEOGRAPH:'BCC7:48327:暮 +CJK UNIFIED IDEOGRAPH:'BCC8:48328:暫 +CJK UNIFIED IDEOGRAPH:'BCC9:48329:暴 +CJK UNIFIED IDEOGRAPH:'BCCA:48330:暱 +CJK UNIFIED IDEOGRAPH:'BCCB:48331:樣 +CJK UNIFIED IDEOGRAPH:'BCCC:48332:樟 +CJK UNIFIED IDEOGRAPH:'BCCD:48333:槨 +CJK UNIFIED IDEOGRAPH:'BCCE:48334:樁 +CJK UNIFIED IDEOGRAPH:'BCCF:48335:樞 +CJK UNIFIED IDEOGRAPH:'BCD0:48336:標 +CJK UNIFIED IDEOGRAPH:'BCD1:48337:槽 +CJK UNIFIED IDEOGRAPH:'BCD2:48338:模 +CJK UNIFIED IDEOGRAPH:'BCD3:48339:樓 +CJK UNIFIED IDEOGRAPH:'BCD4:48340:樊 +CJK UNIFIED IDEOGRAPH:'BCD5:48341:槳 +CJK UNIFIED IDEOGRAPH:'BCD6:48342:樂 +CJK UNIFIED IDEOGRAPH:'BCD7:48343:樅 +CJK UNIFIED IDEOGRAPH:'BCD8:48344:槭 +CJK UNIFIED IDEOGRAPH:'BCD9:48345:樑 +CJK UNIFIED IDEOGRAPH:'BCDA:48346:歐 +CJK UNIFIED IDEOGRAPH:'BCDB:48347:歎 +CJK UNIFIED IDEOGRAPH:'BCDC:48348:殤 +CJK UNIFIED IDEOGRAPH:'BCDD:48349:毅 +CJK UNIFIED IDEOGRAPH:'BCDE:48350:毆 +CJK UNIFIED IDEOGRAPH:'BCDF:48351:漿 +CJK UNIFIED IDEOGRAPH:'BCE0:48352:潼 +CJK UNIFIED IDEOGRAPH:'BCE1:48353:澄 +CJK UNIFIED IDEOGRAPH:'BCE2:48354:潑 +CJK UNIFIED IDEOGRAPH:'BCE3:48355:潦 +CJK UNIFIED IDEOGRAPH:'BCE4:48356:潔 +CJK UNIFIED IDEOGRAPH:'BCE5:48357:澆 +CJK UNIFIED IDEOGRAPH:'BCE6:48358:潭 +CJK UNIFIED IDEOGRAPH:'BCE7:48359:潛 +CJK UNIFIED IDEOGRAPH:'BCE8:48360:潸 +CJK UNIFIED IDEOGRAPH:'BCE9:48361:潮 +CJK UNIFIED IDEOGRAPH:'BCEA:48362:澎 +CJK UNIFIED IDEOGRAPH:'BCEB:48363:潺 +CJK UNIFIED IDEOGRAPH:'BCEC:48364:潰 +CJK UNIFIED IDEOGRAPH:'BCED:48365:潤 +CJK UNIFIED IDEOGRAPH:'BCEE:48366:澗 +CJK UNIFIED IDEOGRAPH:'BCEF:48367:潘 +CJK UNIFIED IDEOGRAPH:'BCF0:48368:滕 +CJK UNIFIED IDEOGRAPH:'BCF1:48369:潯 +CJK UNIFIED IDEOGRAPH:'BCF2:48370:潠 +CJK UNIFIED IDEOGRAPH:'BCF3:48371:潟 +CJK UNIFIED IDEOGRAPH:'BCF4:48372:熟 +CJK UNIFIED IDEOGRAPH:'BCF5:48373:熬 +CJK UNIFIED IDEOGRAPH:'BCF6:48374:熱 +CJK UNIFIED IDEOGRAPH:'BCF7:48375:熨 +CJK UNIFIED IDEOGRAPH:'BCF8:48376:牖 +CJK UNIFIED IDEOGRAPH:'BCF9:48377:犛 +CJK UNIFIED IDEOGRAPH:'BCFA:48378:獎 +CJK UNIFIED IDEOGRAPH:'BCFB:48379:獗 +CJK UNIFIED IDEOGRAPH:'BCFC:48380:瑩 +CJK UNIFIED IDEOGRAPH:'BCFD:48381:璋 +CJK UNIFIED IDEOGRAPH:'BCFE:48382:璃 +CJK UNIFIED IDEOGRAPH:'BD40:48448:瑾 +CJK UNIFIED IDEOGRAPH:'BD41:48449:璀 +CJK UNIFIED IDEOGRAPH:'BD42:48450:畿 +CJK UNIFIED IDEOGRAPH:'BD43:48451:瘠 +CJK UNIFIED IDEOGRAPH:'BD44:48452:瘩 +CJK UNIFIED IDEOGRAPH:'BD45:48453:瘟 +CJK UNIFIED IDEOGRAPH:'BD46:48454:瘤 +CJK UNIFIED IDEOGRAPH:'BD47:48455:瘦 +CJK UNIFIED IDEOGRAPH:'BD48:48456:瘡 +CJK UNIFIED IDEOGRAPH:'BD49:48457:瘢 +CJK UNIFIED IDEOGRAPH:'BD4A:48458:皚 +CJK UNIFIED IDEOGRAPH:'BD4B:48459:皺 +CJK UNIFIED IDEOGRAPH:'BD4C:48460:盤 +CJK UNIFIED IDEOGRAPH:'BD4D:48461:瞎 +CJK UNIFIED IDEOGRAPH:'BD4E:48462:瞇 +CJK UNIFIED IDEOGRAPH:'BD4F:48463:瞌 +CJK UNIFIED IDEOGRAPH:'BD50:48464:瞑 +CJK UNIFIED IDEOGRAPH:'BD51:48465:瞋 +CJK UNIFIED IDEOGRAPH:'BD52:48466:磋 +CJK UNIFIED IDEOGRAPH:'BD53:48467:磅 +CJK UNIFIED IDEOGRAPH:'BD54:48468:確 +CJK UNIFIED IDEOGRAPH:'BD55:48469:磊 +CJK UNIFIED IDEOGRAPH:'BD56:48470:碾 +CJK UNIFIED IDEOGRAPH:'BD57:48471:磕 +CJK UNIFIED IDEOGRAPH:'BD58:48472:碼 +CJK UNIFIED IDEOGRAPH:'BD59:48473:磐 +CJK UNIFIED IDEOGRAPH:'BD5A:48474:稿 +CJK UNIFIED IDEOGRAPH:'BD5B:48475:稼 +CJK UNIFIED IDEOGRAPH:'BD5C:48476:穀 +CJK UNIFIED IDEOGRAPH:'BD5D:48477:稽 +CJK UNIFIED IDEOGRAPH:'BD5E:48478:稷 +CJK UNIFIED IDEOGRAPH:'BD5F:48479:稻 +CJK UNIFIED IDEOGRAPH:'BD60:48480:窯 +CJK UNIFIED IDEOGRAPH:'BD61:48481:窮 +CJK UNIFIED IDEOGRAPH:'BD62:48482:箭 +CJK UNIFIED IDEOGRAPH:'BD63:48483:箱 +CJK UNIFIED IDEOGRAPH:'BD64:48484:範 +CJK UNIFIED IDEOGRAPH:'BD65:48485:箴 +CJK UNIFIED IDEOGRAPH:'BD66:48486:篆 +CJK UNIFIED IDEOGRAPH:'BD67:48487:篇 +CJK UNIFIED IDEOGRAPH:'BD68:48488:篁 +CJK UNIFIED IDEOGRAPH:'BD69:48489:箠 +CJK UNIFIED IDEOGRAPH:'BD6A:48490:篌 +CJK UNIFIED IDEOGRAPH:'BD6B:48491:糊 +CJK UNIFIED IDEOGRAPH:'BD6C:48492:締 +CJK UNIFIED IDEOGRAPH:'BD6D:48493:練 +CJK UNIFIED IDEOGRAPH:'BD6E:48494:緯 +CJK UNIFIED IDEOGRAPH:'BD6F:48495:緻 +CJK UNIFIED IDEOGRAPH:'BD70:48496:緘 +CJK UNIFIED IDEOGRAPH:'BD71:48497:緬 +CJK UNIFIED IDEOGRAPH:'BD72:48498:緝 +CJK UNIFIED IDEOGRAPH:'BD73:48499:編 +CJK UNIFIED IDEOGRAPH:'BD74:48500:緣 +CJK UNIFIED IDEOGRAPH:'BD75:48501:線 +CJK UNIFIED IDEOGRAPH:'BD76:48502:緞 +CJK UNIFIED IDEOGRAPH:'BD77:48503:緩 +CJK UNIFIED IDEOGRAPH:'BD78:48504:綞 +CJK UNIFIED IDEOGRAPH:'BD79:48505:緙 +CJK UNIFIED IDEOGRAPH:'BD7A:48506:緲 +CJK UNIFIED IDEOGRAPH:'BD7B:48507:緹 +CJK UNIFIED IDEOGRAPH:'BD7C:48508:罵 +CJK UNIFIED IDEOGRAPH:'BD7D:48509:罷 +CJK UNIFIED IDEOGRAPH:'BD7E:48510:羯 +CJK UNIFIED IDEOGRAPH:'BDA1:48545:翩 +CJK UNIFIED IDEOGRAPH:'BDA2:48546:耦 +CJK UNIFIED IDEOGRAPH:'BDA3:48547:膛 +CJK UNIFIED IDEOGRAPH:'BDA4:48548:膜 +CJK UNIFIED IDEOGRAPH:'BDA5:48549:膝 +CJK UNIFIED IDEOGRAPH:'BDA6:48550:膠 +CJK UNIFIED IDEOGRAPH:'BDA7:48551:膚 +CJK UNIFIED IDEOGRAPH:'BDA8:48552:膘 +CJK UNIFIED IDEOGRAPH:'BDA9:48553:蔗 +CJK UNIFIED IDEOGRAPH:'BDAA:48554:蔽 +CJK UNIFIED IDEOGRAPH:'BDAB:48555:蔚 +CJK UNIFIED IDEOGRAPH:'BDAC:48556:蓮 +CJK UNIFIED IDEOGRAPH:'BDAD:48557:蔬 +CJK UNIFIED IDEOGRAPH:'BDAE:48558:蔭 +CJK UNIFIED IDEOGRAPH:'BDAF:48559:蔓 +CJK UNIFIED IDEOGRAPH:'BDB0:48560:蔑 +CJK UNIFIED IDEOGRAPH:'BDB1:48561:蔣 +CJK UNIFIED IDEOGRAPH:'BDB2:48562:蔡 +CJK UNIFIED IDEOGRAPH:'BDB3:48563:蔔 +CJK UNIFIED IDEOGRAPH:'BDB4:48564:蓬 +CJK UNIFIED IDEOGRAPH:'BDB5:48565:蔥 +CJK UNIFIED IDEOGRAPH:'BDB6:48566:蓿 +CJK UNIFIED IDEOGRAPH:'BDB7:48567:蔆 +CJK UNIFIED IDEOGRAPH:'BDB8:48568:螂 +CJK UNIFIED IDEOGRAPH:'BDB9:48569:蝴 +CJK UNIFIED IDEOGRAPH:'BDBA:48570:蝶 +CJK UNIFIED IDEOGRAPH:'BDBB:48571:蝠 +CJK UNIFIED IDEOGRAPH:'BDBC:48572:蝦 +CJK UNIFIED IDEOGRAPH:'BDBD:48573:蝸 +CJK UNIFIED IDEOGRAPH:'BDBE:48574:蝨 +CJK UNIFIED IDEOGRAPH:'BDBF:48575:蝙 +CJK UNIFIED IDEOGRAPH:'BDC0:48576:蝗 +CJK UNIFIED IDEOGRAPH:'BDC1:48577:蝌 +CJK UNIFIED IDEOGRAPH:'BDC2:48578:蝓 +CJK UNIFIED IDEOGRAPH:'BDC3:48579:衛 +CJK UNIFIED IDEOGRAPH:'BDC4:48580:衝 +CJK UNIFIED IDEOGRAPH:'BDC5:48581:褐 +CJK UNIFIED IDEOGRAPH:'BDC6:48582:複 +CJK UNIFIED IDEOGRAPH:'BDC7:48583:褒 +CJK UNIFIED IDEOGRAPH:'BDC8:48584:褓 +CJK UNIFIED IDEOGRAPH:'BDC9:48585:褕 +CJK UNIFIED IDEOGRAPH:'BDCA:48586:褊 +CJK UNIFIED IDEOGRAPH:'BDCB:48587:誼 +CJK UNIFIED IDEOGRAPH:'BDCC:48588:諒 +CJK UNIFIED IDEOGRAPH:'BDCD:48589:談 +CJK UNIFIED IDEOGRAPH:'BDCE:48590:諄 +CJK UNIFIED IDEOGRAPH:'BDCF:48591:誕 +CJK UNIFIED IDEOGRAPH:'BDD0:48592:請 +CJK UNIFIED IDEOGRAPH:'BDD1:48593:諸 +CJK UNIFIED IDEOGRAPH:'BDD2:48594:課 +CJK UNIFIED IDEOGRAPH:'BDD3:48595:諉 +CJK UNIFIED IDEOGRAPH:'BDD4:48596:諂 +CJK UNIFIED IDEOGRAPH:'BDD5:48597:調 +CJK UNIFIED IDEOGRAPH:'BDD6:48598:誰 +CJK UNIFIED IDEOGRAPH:'BDD7:48599:論 +CJK UNIFIED IDEOGRAPH:'BDD8:48600:諍 +CJK UNIFIED IDEOGRAPH:'BDD9:48601:誶 +CJK UNIFIED IDEOGRAPH:'BDDA:48602:誹 +CJK UNIFIED IDEOGRAPH:'BDDB:48603:諛 +CJK UNIFIED IDEOGRAPH:'BDDC:48604:豌 +CJK UNIFIED IDEOGRAPH:'BDDD:48605:豎 +CJK UNIFIED IDEOGRAPH:'BDDE:48606:豬 +CJK UNIFIED IDEOGRAPH:'BDDF:48607:賠 +CJK UNIFIED IDEOGRAPH:'BDE0:48608:賞 +CJK UNIFIED IDEOGRAPH:'BDE1:48609:賦 +CJK UNIFIED IDEOGRAPH:'BDE2:48610:賤 +CJK UNIFIED IDEOGRAPH:'BDE3:48611:賬 +CJK UNIFIED IDEOGRAPH:'BDE4:48612:賭 +CJK UNIFIED IDEOGRAPH:'BDE5:48613:賢 +CJK UNIFIED IDEOGRAPH:'BDE6:48614:賣 +CJK UNIFIED IDEOGRAPH:'BDE7:48615:賜 +CJK UNIFIED IDEOGRAPH:'BDE8:48616:質 +CJK UNIFIED IDEOGRAPH:'BDE9:48617:賡 +CJK UNIFIED IDEOGRAPH:'BDEA:48618:赭 +CJK UNIFIED IDEOGRAPH:'BDEB:48619:趟 +CJK UNIFIED IDEOGRAPH:'BDEC:48620:趣 +CJK UNIFIED IDEOGRAPH:'BDED:48621:踫 +CJK UNIFIED IDEOGRAPH:'BDEE:48622:踐 +CJK UNIFIED IDEOGRAPH:'BDEF:48623:踝 +CJK UNIFIED IDEOGRAPH:'BDF0:48624:踢 +CJK UNIFIED IDEOGRAPH:'BDF1:48625:踏 +CJK UNIFIED IDEOGRAPH:'BDF2:48626:踩 +CJK UNIFIED IDEOGRAPH:'BDF3:48627:踟 +CJK UNIFIED IDEOGRAPH:'BDF4:48628:踡 +CJK UNIFIED IDEOGRAPH:'BDF5:48629:踞 +CJK UNIFIED IDEOGRAPH:'BDF6:48630:躺 +CJK UNIFIED IDEOGRAPH:'BDF7:48631:輝 +CJK UNIFIED IDEOGRAPH:'BDF8:48632:輛 +CJK UNIFIED IDEOGRAPH:'BDF9:48633:輟 +CJK UNIFIED IDEOGRAPH:'BDFA:48634:輩 +CJK UNIFIED IDEOGRAPH:'BDFB:48635:輦 +CJK UNIFIED IDEOGRAPH:'BDFC:48636:輪 +CJK UNIFIED IDEOGRAPH:'BDFD:48637:輜 +CJK UNIFIED IDEOGRAPH:'BDFE:48638:輞 +CJK UNIFIED IDEOGRAPH:'BE40:48704:輥 +CJK UNIFIED IDEOGRAPH:'BE41:48705:適 +CJK UNIFIED IDEOGRAPH:'BE42:48706:遮 +CJK UNIFIED IDEOGRAPH:'BE43:48707:遨 +CJK UNIFIED IDEOGRAPH:'BE44:48708:遭 +CJK UNIFIED IDEOGRAPH:'BE45:48709:遷 +CJK UNIFIED IDEOGRAPH:'BE46:48710:鄰 +CJK UNIFIED IDEOGRAPH:'BE47:48711:鄭 +CJK UNIFIED IDEOGRAPH:'BE48:48712:鄧 +CJK UNIFIED IDEOGRAPH:'BE49:48713:鄱 +CJK UNIFIED IDEOGRAPH:'BE4A:48714:醇 +CJK UNIFIED IDEOGRAPH:'BE4B:48715:醉 +CJK UNIFIED IDEOGRAPH:'BE4C:48716:醋 +CJK UNIFIED IDEOGRAPH:'BE4D:48717:醃 +CJK UNIFIED IDEOGRAPH:'BE4E:48718:鋅 +CJK UNIFIED IDEOGRAPH:'BE4F:48719:銻 +CJK UNIFIED IDEOGRAPH:'BE50:48720:銷 +CJK UNIFIED IDEOGRAPH:'BE51:48721:鋪 +CJK UNIFIED IDEOGRAPH:'BE52:48722:銬 +CJK UNIFIED IDEOGRAPH:'BE53:48723:鋤 +CJK UNIFIED IDEOGRAPH:'BE54:48724:鋁 +CJK UNIFIED IDEOGRAPH:'BE55:48725:銳 +CJK UNIFIED IDEOGRAPH:'BE56:48726:銼 +CJK UNIFIED IDEOGRAPH:'BE57:48727:鋒 +CJK UNIFIED IDEOGRAPH:'BE58:48728:鋇 +CJK UNIFIED IDEOGRAPH:'BE59:48729:鋰 +CJK UNIFIED IDEOGRAPH:'BE5A:48730:銲 +CJK UNIFIED IDEOGRAPH:'BE5B:48731:閭 +CJK UNIFIED IDEOGRAPH:'BE5C:48732:閱 +CJK UNIFIED IDEOGRAPH:'BE5D:48733:霄 +CJK UNIFIED IDEOGRAPH:'BE5E:48734:霆 +CJK UNIFIED IDEOGRAPH:'BE5F:48735:震 +CJK UNIFIED IDEOGRAPH:'BE60:48736:霉 +CJK UNIFIED IDEOGRAPH:'BE61:48737:靠 +CJK UNIFIED IDEOGRAPH:'BE62:48738:鞍 +CJK UNIFIED IDEOGRAPH:'BE63:48739:鞋 +CJK UNIFIED IDEOGRAPH:'BE64:48740:鞏 +CJK UNIFIED IDEOGRAPH:'BE65:48741:頡 +CJK UNIFIED IDEOGRAPH:'BE66:48742:頫 +CJK UNIFIED IDEOGRAPH:'BE67:48743:頜 +CJK UNIFIED IDEOGRAPH:'BE68:48744:颳 +CJK UNIFIED IDEOGRAPH:'BE69:48745:養 +CJK UNIFIED IDEOGRAPH:'BE6A:48746:餓 +CJK UNIFIED IDEOGRAPH:'BE6B:48747:餒 +CJK UNIFIED IDEOGRAPH:'BE6C:48748:餘 +CJK UNIFIED IDEOGRAPH:'BE6D:48749:駝 +CJK UNIFIED IDEOGRAPH:'BE6E:48750:駐 +CJK UNIFIED IDEOGRAPH:'BE6F:48751:駟 +CJK UNIFIED IDEOGRAPH:'BE70:48752:駛 +CJK UNIFIED IDEOGRAPH:'BE71:48753:駑 +CJK UNIFIED IDEOGRAPH:'BE72:48754:駕 +CJK UNIFIED IDEOGRAPH:'BE73:48755:駒 +CJK UNIFIED IDEOGRAPH:'BE74:48756:駙 +CJK UNIFIED IDEOGRAPH:'BE75:48757:骷 +CJK UNIFIED IDEOGRAPH:'BE76:48758:髮 +CJK UNIFIED IDEOGRAPH:'BE77:48759:髯 +CJK UNIFIED IDEOGRAPH:'BE78:48760:鬧 +CJK UNIFIED IDEOGRAPH:'BE79:48761:魅 +CJK UNIFIED IDEOGRAPH:'BE7A:48762:魄 +CJK UNIFIED IDEOGRAPH:'BE7B:48763:魷 +CJK UNIFIED IDEOGRAPH:'BE7C:48764:魯 +CJK UNIFIED IDEOGRAPH:'BE7D:48765:鴆 +CJK UNIFIED IDEOGRAPH:'BE7E:48766:鴉 +CJK UNIFIED IDEOGRAPH:'BEA1:48801:鴃 +CJK UNIFIED IDEOGRAPH:'BEA2:48802:麩 +CJK UNIFIED IDEOGRAPH:'BEA3:48803:麾 +CJK UNIFIED IDEOGRAPH:'BEA4:48804:黎 +CJK UNIFIED IDEOGRAPH:'BEA5:48805:墨 +CJK UNIFIED IDEOGRAPH:'BEA6:48806:齒 +CJK UNIFIED IDEOGRAPH:'BEA7:48807:儒 +CJK UNIFIED IDEOGRAPH:'BEA8:48808:儘 +CJK UNIFIED IDEOGRAPH:'BEA9:48809:儔 +CJK UNIFIED IDEOGRAPH:'BEAA:48810:儐 +CJK UNIFIED IDEOGRAPH:'BEAB:48811:儕 +CJK UNIFIED IDEOGRAPH:'BEAC:48812:冀 +CJK UNIFIED IDEOGRAPH:'BEAD:48813:冪 +CJK UNIFIED IDEOGRAPH:'BEAE:48814:凝 +CJK UNIFIED IDEOGRAPH:'BEAF:48815:劑 +CJK UNIFIED IDEOGRAPH:'BEB0:48816:劓 +CJK UNIFIED IDEOGRAPH:'BEB1:48817:勳 +CJK UNIFIED IDEOGRAPH:'BEB2:48818:噙 +CJK UNIFIED IDEOGRAPH:'BEB3:48819:噫 +CJK UNIFIED IDEOGRAPH:'BEB4:48820:噹 +CJK UNIFIED IDEOGRAPH:'BEB5:48821:噩 +CJK UNIFIED IDEOGRAPH:'BEB6:48822:噤 +CJK UNIFIED IDEOGRAPH:'BEB7:48823:噸 +CJK UNIFIED IDEOGRAPH:'BEB8:48824:噪 +CJK UNIFIED IDEOGRAPH:'BEB9:48825:器 +CJK UNIFIED IDEOGRAPH:'BEBA:48826:噥 +CJK UNIFIED IDEOGRAPH:'BEBB:48827:噱 +CJK UNIFIED IDEOGRAPH:'BEBC:48828:噯 +CJK UNIFIED IDEOGRAPH:'BEBD:48829:噬 +CJK UNIFIED IDEOGRAPH:'BEBE:48830:噢 +CJK UNIFIED IDEOGRAPH:'BEBF:48831:噶 +CJK UNIFIED IDEOGRAPH:'BEC0:48832:壁 +CJK UNIFIED IDEOGRAPH:'BEC1:48833:墾 +CJK UNIFIED IDEOGRAPH:'BEC2:48834:壇 +CJK UNIFIED IDEOGRAPH:'BEC3:48835:壅 +CJK UNIFIED IDEOGRAPH:'BEC4:48836:奮 +CJK UNIFIED IDEOGRAPH:'BEC5:48837:嬝 +CJK UNIFIED IDEOGRAPH:'BEC6:48838:嬴 +CJK UNIFIED IDEOGRAPH:'BEC7:48839:學 +CJK UNIFIED IDEOGRAPH:'BEC8:48840:寰 +CJK UNIFIED IDEOGRAPH:'BEC9:48841:導 +CJK UNIFIED IDEOGRAPH:'BECA:48842:彊 +CJK UNIFIED IDEOGRAPH:'BECB:48843:憲 +CJK UNIFIED IDEOGRAPH:'BECC:48844:憑 +CJK UNIFIED IDEOGRAPH:'BECD:48845:憩 +CJK UNIFIED IDEOGRAPH:'BECE:48846:憊 +CJK UNIFIED IDEOGRAPH:'BECF:48847:懍 +CJK UNIFIED IDEOGRAPH:'BED0:48848:憶 +CJK UNIFIED IDEOGRAPH:'BED1:48849:憾 +CJK UNIFIED IDEOGRAPH:'BED2:48850:懊 +CJK UNIFIED IDEOGRAPH:'BED3:48851:懈 +CJK UNIFIED IDEOGRAPH:'BED4:48852:戰 +CJK UNIFIED IDEOGRAPH:'BED5:48853:擅 +CJK UNIFIED IDEOGRAPH:'BED6:48854:擁 +CJK UNIFIED IDEOGRAPH:'BED7:48855:擋 +CJK UNIFIED IDEOGRAPH:'BED8:48856:撻 +CJK UNIFIED IDEOGRAPH:'BED9:48857:撼 +CJK UNIFIED IDEOGRAPH:'BEDA:48858:據 +CJK UNIFIED IDEOGRAPH:'BEDB:48859:擄 +CJK UNIFIED IDEOGRAPH:'BEDC:48860:擇 +CJK UNIFIED IDEOGRAPH:'BEDD:48861:擂 +CJK UNIFIED IDEOGRAPH:'BEDE:48862:操 +CJK UNIFIED IDEOGRAPH:'BEDF:48863:撿 +CJK UNIFIED IDEOGRAPH:'BEE0:48864:擒 +CJK UNIFIED IDEOGRAPH:'BEE1:48865:擔 +CJK UNIFIED IDEOGRAPH:'BEE2:48866:撾 +CJK UNIFIED IDEOGRAPH:'BEE3:48867:整 +CJK UNIFIED IDEOGRAPH:'BEE4:48868:曆 +CJK UNIFIED IDEOGRAPH:'BEE5:48869:曉 +CJK UNIFIED IDEOGRAPH:'BEE6:48870:暹 +CJK UNIFIED IDEOGRAPH:'BEE7:48871:曄 +CJK UNIFIED IDEOGRAPH:'BEE8:48872:曇 +CJK UNIFIED IDEOGRAPH:'BEE9:48873:暸 +CJK UNIFIED IDEOGRAPH:'BEEA:48874:樽 +CJK UNIFIED IDEOGRAPH:'BEEB:48875:樸 +CJK UNIFIED IDEOGRAPH:'BEEC:48876:樺 +CJK UNIFIED IDEOGRAPH:'BEED:48877:橙 +CJK UNIFIED IDEOGRAPH:'BEEE:48878:橫 +CJK UNIFIED IDEOGRAPH:'BEEF:48879:橘 +CJK UNIFIED IDEOGRAPH:'BEF0:48880:樹 +CJK UNIFIED IDEOGRAPH:'BEF1:48881:橄 +CJK UNIFIED IDEOGRAPH:'BEF2:48882:橢 +CJK UNIFIED IDEOGRAPH:'BEF3:48883:橡 +CJK UNIFIED IDEOGRAPH:'BEF4:48884:橋 +CJK UNIFIED IDEOGRAPH:'BEF5:48885:橇 +CJK UNIFIED IDEOGRAPH:'BEF6:48886:樵 +CJK UNIFIED IDEOGRAPH:'BEF7:48887:機 +CJK UNIFIED IDEOGRAPH:'BEF8:48888:橈 +CJK UNIFIED IDEOGRAPH:'BEF9:48889:歙 +CJK UNIFIED IDEOGRAPH:'BEFA:48890:歷 +CJK UNIFIED IDEOGRAPH:'BEFB:48891:氅 +CJK UNIFIED IDEOGRAPH:'BEFC:48892:濂 +CJK UNIFIED IDEOGRAPH:'BEFD:48893:澱 +CJK UNIFIED IDEOGRAPH:'BEFE:48894:澡 +CJK UNIFIED IDEOGRAPH:'BF40:48960:濃 +CJK UNIFIED IDEOGRAPH:'BF41:48961:澤 +CJK UNIFIED IDEOGRAPH:'BF42:48962:濁 +CJK UNIFIED IDEOGRAPH:'BF43:48963:澧 +CJK UNIFIED IDEOGRAPH:'BF44:48964:澳 +CJK UNIFIED IDEOGRAPH:'BF45:48965:激 +CJK UNIFIED IDEOGRAPH:'BF46:48966:澹 +CJK UNIFIED IDEOGRAPH:'BF47:48967:澶 +CJK UNIFIED IDEOGRAPH:'BF48:48968:澦 +CJK UNIFIED IDEOGRAPH:'BF49:48969:澠 +CJK UNIFIED IDEOGRAPH:'BF4A:48970:澴 +CJK UNIFIED IDEOGRAPH:'BF4B:48971:熾 +CJK UNIFIED IDEOGRAPH:'BF4C:48972:燉 +CJK UNIFIED IDEOGRAPH:'BF4D:48973:燐 +CJK UNIFIED IDEOGRAPH:'BF4E:48974:燒 +CJK UNIFIED IDEOGRAPH:'BF4F:48975:燈 +CJK UNIFIED IDEOGRAPH:'BF50:48976:燕 +CJK UNIFIED IDEOGRAPH:'BF51:48977:熹 +CJK UNIFIED IDEOGRAPH:'BF52:48978:燎 +CJK UNIFIED IDEOGRAPH:'BF53:48979:燙 +CJK UNIFIED IDEOGRAPH:'BF54:48980:燜 +CJK UNIFIED IDEOGRAPH:'BF55:48981:燃 +CJK UNIFIED IDEOGRAPH:'BF56:48982:燄 +CJK UNIFIED IDEOGRAPH:'BF57:48983:獨 +CJK UNIFIED IDEOGRAPH:'BF58:48984:璜 +CJK UNIFIED IDEOGRAPH:'BF59:48985:璣 +CJK UNIFIED IDEOGRAPH:'BF5A:48986:璘 +CJK UNIFIED IDEOGRAPH:'BF5B:48987:璟 +CJK UNIFIED IDEOGRAPH:'BF5C:48988:璞 +CJK UNIFIED IDEOGRAPH:'BF5D:48989:瓢 +CJK UNIFIED IDEOGRAPH:'BF5E:48990:甌 +CJK UNIFIED IDEOGRAPH:'BF5F:48991:甍 +CJK UNIFIED IDEOGRAPH:'BF60:48992:瘴 +CJK UNIFIED IDEOGRAPH:'BF61:48993:瘸 +CJK UNIFIED IDEOGRAPH:'BF62:48994:瘺 +CJK UNIFIED IDEOGRAPH:'BF63:48995:盧 +CJK UNIFIED IDEOGRAPH:'BF64:48996:盥 +CJK UNIFIED IDEOGRAPH:'BF65:48997:瞠 +CJK UNIFIED IDEOGRAPH:'BF66:48998:瞞 +CJK UNIFIED IDEOGRAPH:'BF67:48999:瞟 +CJK UNIFIED IDEOGRAPH:'BF68:49000:瞥 +CJK UNIFIED IDEOGRAPH:'BF69:49001:磨 +CJK UNIFIED IDEOGRAPH:'BF6A:49002:磚 +CJK UNIFIED IDEOGRAPH:'BF6B:49003:磬 +CJK UNIFIED IDEOGRAPH:'BF6C:49004:磧 +CJK UNIFIED IDEOGRAPH:'BF6D:49005:禦 +CJK UNIFIED IDEOGRAPH:'BF6E:49006:積 +CJK UNIFIED IDEOGRAPH:'BF6F:49007:穎 +CJK UNIFIED IDEOGRAPH:'BF70:49008:穆 +CJK UNIFIED IDEOGRAPH:'BF71:49009:穌 +CJK UNIFIED IDEOGRAPH:'BF72:49010:穋 +CJK UNIFIED IDEOGRAPH:'BF73:49011:窺 +CJK UNIFIED IDEOGRAPH:'BF74:49012:篙 +CJK UNIFIED IDEOGRAPH:'BF75:49013:簑 +CJK UNIFIED IDEOGRAPH:'BF76:49014:築 +CJK UNIFIED IDEOGRAPH:'BF77:49015:篤 +CJK UNIFIED IDEOGRAPH:'BF78:49016:篛 +CJK UNIFIED IDEOGRAPH:'BF79:49017:篡 +CJK UNIFIED IDEOGRAPH:'BF7A:49018:篩 +CJK UNIFIED IDEOGRAPH:'BF7B:49019:篦 +CJK UNIFIED IDEOGRAPH:'BF7C:49020:糕 +CJK UNIFIED IDEOGRAPH:'BF7D:49021:糖 +CJK UNIFIED IDEOGRAPH:'BF7E:49022:縊 +CJK UNIFIED IDEOGRAPH:'BFA1:49057:縑 +CJK UNIFIED IDEOGRAPH:'BFA2:49058:縈 +CJK UNIFIED IDEOGRAPH:'BFA3:49059:縛 +CJK UNIFIED IDEOGRAPH:'BFA4:49060:縣 +CJK UNIFIED IDEOGRAPH:'BFA5:49061:縞 +CJK UNIFIED IDEOGRAPH:'BFA6:49062:縝 +CJK UNIFIED IDEOGRAPH:'BFA7:49063:縉 +CJK UNIFIED IDEOGRAPH:'BFA8:49064:縐 +CJK UNIFIED IDEOGRAPH:'BFA9:49065:罹 +CJK UNIFIED IDEOGRAPH:'BFAA:49066:羲 +CJK UNIFIED IDEOGRAPH:'BFAB:49067:翰 +CJK UNIFIED IDEOGRAPH:'BFAC:49068:翱 +CJK UNIFIED IDEOGRAPH:'BFAD:49069:翮 +CJK UNIFIED IDEOGRAPH:'BFAE:49070:耨 +CJK UNIFIED IDEOGRAPH:'BFAF:49071:膳 +CJK UNIFIED IDEOGRAPH:'BFB0:49072:膩 +CJK UNIFIED IDEOGRAPH:'BFB1:49073:膨 +CJK UNIFIED IDEOGRAPH:'BFB2:49074:臻 +CJK UNIFIED IDEOGRAPH:'BFB3:49075:興 +CJK UNIFIED IDEOGRAPH:'BFB4:49076:艘 +CJK UNIFIED IDEOGRAPH:'BFB5:49077:艙 +CJK UNIFIED IDEOGRAPH:'BFB6:49078:蕊 +CJK UNIFIED IDEOGRAPH:'BFB7:49079:蕙 +CJK UNIFIED IDEOGRAPH:'BFB8:49080:蕈 +CJK UNIFIED IDEOGRAPH:'BFB9:49081:蕨 +CJK UNIFIED IDEOGRAPH:'BFBA:49082:蕩 +CJK UNIFIED IDEOGRAPH:'BFBB:49083:蕃 +CJK UNIFIED IDEOGRAPH:'BFBC:49084:蕉 +CJK UNIFIED IDEOGRAPH:'BFBD:49085:蕭 +CJK UNIFIED IDEOGRAPH:'BFBE:49086:蕪 +CJK UNIFIED IDEOGRAPH:'BFBF:49087:蕞 +CJK UNIFIED IDEOGRAPH:'BFC0:49088:螃 +CJK UNIFIED IDEOGRAPH:'BFC1:49089:螟 +CJK UNIFIED IDEOGRAPH:'BFC2:49090:螞 +CJK UNIFIED IDEOGRAPH:'BFC3:49091:螢 +CJK UNIFIED IDEOGRAPH:'BFC4:49092:融 +CJK UNIFIED IDEOGRAPH:'BFC5:49093:衡 +CJK UNIFIED IDEOGRAPH:'BFC6:49094:褪 +CJK UNIFIED IDEOGRAPH:'BFC7:49095:褲 +CJK UNIFIED IDEOGRAPH:'BFC8:49096:褥 +CJK UNIFIED IDEOGRAPH:'BFC9:49097:褫 +CJK UNIFIED IDEOGRAPH:'BFCA:49098:褡 +CJK UNIFIED IDEOGRAPH:'BFCB:49099:親 +CJK UNIFIED IDEOGRAPH:'BFCC:49100:覦 +CJK UNIFIED IDEOGRAPH:'BFCD:49101:諦 +CJK UNIFIED IDEOGRAPH:'BFCE:49102:諺 +CJK UNIFIED IDEOGRAPH:'BFCF:49103:諫 +CJK UNIFIED IDEOGRAPH:'BFD0:49104:諱 +CJK UNIFIED IDEOGRAPH:'BFD1:49105:謀 +CJK UNIFIED IDEOGRAPH:'BFD2:49106:諜 +CJK UNIFIED IDEOGRAPH:'BFD3:49107:諧 +CJK UNIFIED IDEOGRAPH:'BFD4:49108:諮 +CJK UNIFIED IDEOGRAPH:'BFD5:49109:諾 +CJK UNIFIED IDEOGRAPH:'BFD6:49110:謁 +CJK UNIFIED IDEOGRAPH:'BFD7:49111:謂 +CJK UNIFIED IDEOGRAPH:'BFD8:49112:諷 +CJK UNIFIED IDEOGRAPH:'BFD9:49113:諭 +CJK UNIFIED IDEOGRAPH:'BFDA:49114:諳 +CJK UNIFIED IDEOGRAPH:'BFDB:49115:諶 +CJK UNIFIED IDEOGRAPH:'BFDC:49116:諼 +CJK UNIFIED IDEOGRAPH:'BFDD:49117:豫 +CJK UNIFIED IDEOGRAPH:'BFDE:49118:豭 +CJK UNIFIED IDEOGRAPH:'BFDF:49119:貓 +CJK UNIFIED IDEOGRAPH:'BFE0:49120:賴 +CJK UNIFIED IDEOGRAPH:'BFE1:49121:蹄 +CJK UNIFIED IDEOGRAPH:'BFE2:49122:踱 +CJK UNIFIED IDEOGRAPH:'BFE3:49123:踴 +CJK UNIFIED IDEOGRAPH:'BFE4:49124:蹂 +CJK UNIFIED IDEOGRAPH:'BFE5:49125:踹 +CJK UNIFIED IDEOGRAPH:'BFE6:49126:踵 +CJK UNIFIED IDEOGRAPH:'BFE7:49127:輻 +CJK UNIFIED IDEOGRAPH:'BFE8:49128:輯 +CJK UNIFIED IDEOGRAPH:'BFE9:49129:輸 +CJK UNIFIED IDEOGRAPH:'BFEA:49130:輳 +CJK UNIFIED IDEOGRAPH:'BFEB:49131:辨 +CJK UNIFIED IDEOGRAPH:'BFEC:49132:辦 +CJK UNIFIED IDEOGRAPH:'BFED:49133:遵 +CJK UNIFIED IDEOGRAPH:'BFEE:49134:遴 +CJK UNIFIED IDEOGRAPH:'BFEF:49135:選 +CJK UNIFIED IDEOGRAPH:'BFF0:49136:遲 +CJK UNIFIED IDEOGRAPH:'BFF1:49137:遼 +CJK UNIFIED IDEOGRAPH:'BFF2:49138:遺 +CJK UNIFIED IDEOGRAPH:'BFF3:49139:鄴 +CJK UNIFIED IDEOGRAPH:'BFF4:49140:醒 +CJK UNIFIED IDEOGRAPH:'BFF5:49141:錠 +CJK UNIFIED IDEOGRAPH:'BFF6:49142:錶 +CJK UNIFIED IDEOGRAPH:'BFF7:49143:鋸 +CJK UNIFIED IDEOGRAPH:'BFF8:49144:錳 +CJK UNIFIED IDEOGRAPH:'BFF9:49145:錯 +CJK UNIFIED IDEOGRAPH:'BFFA:49146:錢 +CJK UNIFIED IDEOGRAPH:'BFFB:49147:鋼 +CJK UNIFIED IDEOGRAPH:'BFFC:49148:錫 +CJK UNIFIED IDEOGRAPH:'BFFD:49149:錄 +CJK UNIFIED IDEOGRAPH:'BFFE:49150:錚 +CJK UNIFIED IDEOGRAPH:'C040:49216:錐 +CJK UNIFIED IDEOGRAPH:'C041:49217:錦 +CJK UNIFIED IDEOGRAPH:'C042:49218:錡 +CJK UNIFIED IDEOGRAPH:'C043:49219:錕 +CJK UNIFIED IDEOGRAPH:'C044:49220:錮 +CJK UNIFIED IDEOGRAPH:'C045:49221:錙 +CJK UNIFIED IDEOGRAPH:'C046:49222:閻 +CJK UNIFIED IDEOGRAPH:'C047:49223:隧 +CJK UNIFIED IDEOGRAPH:'C048:49224:隨 +CJK UNIFIED IDEOGRAPH:'C049:49225:險 +CJK UNIFIED IDEOGRAPH:'C04A:49226:雕 +CJK UNIFIED IDEOGRAPH:'C04B:49227:霎 +CJK UNIFIED IDEOGRAPH:'C04C:49228:霑 +CJK UNIFIED IDEOGRAPH:'C04D:49229:霖 +CJK UNIFIED IDEOGRAPH:'C04E:49230:霍 +CJK UNIFIED IDEOGRAPH:'C04F:49231:霓 +CJK UNIFIED IDEOGRAPH:'C050:49232:霏 +CJK UNIFIED IDEOGRAPH:'C051:49233:靛 +CJK UNIFIED IDEOGRAPH:'C052:49234:靜 +CJK UNIFIED IDEOGRAPH:'C053:49235:靦 +CJK UNIFIED IDEOGRAPH:'C054:49236:鞘 +CJK UNIFIED IDEOGRAPH:'C055:49237:頰 +CJK UNIFIED IDEOGRAPH:'C056:49238:頸 +CJK UNIFIED IDEOGRAPH:'C057:49239:頻 +CJK UNIFIED IDEOGRAPH:'C058:49240:頷 +CJK UNIFIED IDEOGRAPH:'C059:49241:頭 +CJK UNIFIED IDEOGRAPH:'C05A:49242:頹 +CJK UNIFIED IDEOGRAPH:'C05B:49243:頤 +CJK UNIFIED IDEOGRAPH:'C05C:49244:餐 +CJK UNIFIED IDEOGRAPH:'C05D:49245:館 +CJK UNIFIED IDEOGRAPH:'C05E:49246:餞 +CJK UNIFIED IDEOGRAPH:'C05F:49247:餛 +CJK UNIFIED IDEOGRAPH:'C060:49248:餡 +CJK UNIFIED IDEOGRAPH:'C061:49249:餚 +CJK UNIFIED IDEOGRAPH:'C062:49250:駭 +CJK UNIFIED IDEOGRAPH:'C063:49251:駢 +CJK UNIFIED IDEOGRAPH:'C064:49252:駱 +CJK UNIFIED IDEOGRAPH:'C065:49253:骸 +CJK UNIFIED IDEOGRAPH:'C066:49254:骼 +CJK UNIFIED IDEOGRAPH:'C067:49255:髻 +CJK UNIFIED IDEOGRAPH:'C068:49256:髭 +CJK UNIFIED IDEOGRAPH:'C069:49257:鬨 +CJK UNIFIED IDEOGRAPH:'C06A:49258:鮑 +CJK UNIFIED IDEOGRAPH:'C06B:49259:鴕 +CJK UNIFIED IDEOGRAPH:'C06C:49260:鴣 +CJK UNIFIED IDEOGRAPH:'C06D:49261:鴦 +CJK UNIFIED IDEOGRAPH:'C06E:49262:鴨 +CJK UNIFIED IDEOGRAPH:'C06F:49263:鴒 +CJK UNIFIED IDEOGRAPH:'C070:49264:鴛 +CJK UNIFIED IDEOGRAPH:'C071:49265:默 +CJK UNIFIED IDEOGRAPH:'C072:49266:黔 +CJK UNIFIED IDEOGRAPH:'C073:49267:龍 +CJK UNIFIED IDEOGRAPH:'C074:49268:龜 +CJK UNIFIED IDEOGRAPH:'C075:49269:優 +CJK UNIFIED IDEOGRAPH:'C076:49270:償 +CJK UNIFIED IDEOGRAPH:'C077:49271:儡 +CJK UNIFIED IDEOGRAPH:'C078:49272:儲 +CJK UNIFIED IDEOGRAPH:'C079:49273:勵 +CJK UNIFIED IDEOGRAPH:'C07A:49274:嚎 +CJK UNIFIED IDEOGRAPH:'C07B:49275:嚀 +CJK UNIFIED IDEOGRAPH:'C07C:49276:嚐 +CJK UNIFIED IDEOGRAPH:'C07D:49277:嚅 +CJK UNIFIED IDEOGRAPH:'C07E:49278:嚇 +CJK UNIFIED IDEOGRAPH:'C0A1:49313:嚏 +CJK UNIFIED IDEOGRAPH:'C0A2:49314:壕 +CJK UNIFIED IDEOGRAPH:'C0A3:49315:壓 +CJK UNIFIED IDEOGRAPH:'C0A4:49316:壑 +CJK UNIFIED IDEOGRAPH:'C0A5:49317:壎 +CJK UNIFIED IDEOGRAPH:'C0A6:49318:嬰 +CJK UNIFIED IDEOGRAPH:'C0A7:49319:嬪 +CJK UNIFIED IDEOGRAPH:'C0A8:49320:嬤 +CJK UNIFIED IDEOGRAPH:'C0A9:49321:孺 +CJK UNIFIED IDEOGRAPH:'C0AA:49322:尷 +CJK UNIFIED IDEOGRAPH:'C0AB:49323:屨 +CJK UNIFIED IDEOGRAPH:'C0AC:49324:嶼 +CJK UNIFIED IDEOGRAPH:'C0AD:49325:嶺 +CJK UNIFIED IDEOGRAPH:'C0AE:49326:嶽 +CJK UNIFIED IDEOGRAPH:'C0AF:49327:嶸 +CJK UNIFIED IDEOGRAPH:'C0B0:49328:幫 +CJK UNIFIED IDEOGRAPH:'C0B1:49329:彌 +CJK UNIFIED IDEOGRAPH:'C0B2:49330:徽 +CJK UNIFIED IDEOGRAPH:'C0B3:49331:應 +CJK UNIFIED IDEOGRAPH:'C0B4:49332:懂 +CJK UNIFIED IDEOGRAPH:'C0B5:49333:懇 +CJK UNIFIED IDEOGRAPH:'C0B6:49334:懦 +CJK UNIFIED IDEOGRAPH:'C0B7:49335:懋 +CJK UNIFIED IDEOGRAPH:'C0B8:49336:戲 +CJK UNIFIED IDEOGRAPH:'C0B9:49337:戴 +CJK UNIFIED IDEOGRAPH:'C0BA:49338:擎 +CJK UNIFIED IDEOGRAPH:'C0BB:49339:擊 +CJK UNIFIED IDEOGRAPH:'C0BC:49340:擘 +CJK UNIFIED IDEOGRAPH:'C0BD:49341:擠 +CJK UNIFIED IDEOGRAPH:'C0BE:49342:擰 +CJK UNIFIED IDEOGRAPH:'C0BF:49343:擦 +CJK UNIFIED IDEOGRAPH:'C0C0:49344:擬 +CJK UNIFIED IDEOGRAPH:'C0C1:49345:擱 +CJK UNIFIED IDEOGRAPH:'C0C2:49346:擢 +CJK UNIFIED IDEOGRAPH:'C0C3:49347:擭 +CJK UNIFIED IDEOGRAPH:'C0C4:49348:斂 +CJK UNIFIED IDEOGRAPH:'C0C5:49349:斃 +CJK UNIFIED IDEOGRAPH:'C0C6:49350:曙 +CJK UNIFIED IDEOGRAPH:'C0C7:49351:曖 +CJK UNIFIED IDEOGRAPH:'C0C8:49352:檀 +CJK UNIFIED IDEOGRAPH:'C0C9:49353:檔 +CJK UNIFIED IDEOGRAPH:'C0CA:49354:檄 +CJK UNIFIED IDEOGRAPH:'C0CB:49355:檢 +CJK UNIFIED IDEOGRAPH:'C0CC:49356:檜 +CJK UNIFIED IDEOGRAPH:'C0CD:49357:櫛 +CJK UNIFIED IDEOGRAPH:'C0CE:49358:檣 +CJK UNIFIED IDEOGRAPH:'C0CF:49359:橾 +CJK UNIFIED IDEOGRAPH:'C0D0:49360:檗 +CJK UNIFIED IDEOGRAPH:'C0D1:49361:檐 +CJK UNIFIED IDEOGRAPH:'C0D2:49362:檠 +CJK UNIFIED IDEOGRAPH:'C0D3:49363:歜 +CJK UNIFIED IDEOGRAPH:'C0D4:49364:殮 +CJK UNIFIED IDEOGRAPH:'C0D5:49365:毚 +CJK UNIFIED IDEOGRAPH:'C0D6:49366:氈 +CJK UNIFIED IDEOGRAPH:'C0D7:49367:濘 +CJK UNIFIED IDEOGRAPH:'C0D8:49368:濱 +CJK UNIFIED IDEOGRAPH:'C0D9:49369:濟 +CJK UNIFIED IDEOGRAPH:'C0DA:49370:濠 +CJK UNIFIED IDEOGRAPH:'C0DB:49371:濛 +CJK UNIFIED IDEOGRAPH:'C0DC:49372:濤 +CJK UNIFIED IDEOGRAPH:'C0DD:49373:濫 +CJK UNIFIED IDEOGRAPH:'C0DE:49374:濯 +CJK UNIFIED IDEOGRAPH:'C0DF:49375:澀 +CJK UNIFIED IDEOGRAPH:'C0E0:49376:濬 +CJK UNIFIED IDEOGRAPH:'C0E1:49377:濡 +CJK UNIFIED IDEOGRAPH:'C0E2:49378:濩 +CJK UNIFIED IDEOGRAPH:'C0E3:49379:濕 +CJK UNIFIED IDEOGRAPH:'C0E4:49380:濮 +CJK UNIFIED IDEOGRAPH:'C0E5:49381:濰 +CJK UNIFIED IDEOGRAPH:'C0E6:49382:燧 +CJK UNIFIED IDEOGRAPH:'C0E7:49383:營 +CJK UNIFIED IDEOGRAPH:'C0E8:49384:燮 +CJK UNIFIED IDEOGRAPH:'C0E9:49385:燦 +CJK UNIFIED IDEOGRAPH:'C0EA:49386:燥 +CJK UNIFIED IDEOGRAPH:'C0EB:49387:燭 +CJK UNIFIED IDEOGRAPH:'C0EC:49388:燬 +CJK UNIFIED IDEOGRAPH:'C0ED:49389:燴 +CJK UNIFIED IDEOGRAPH:'C0EE:49390:燠 +CJK UNIFIED IDEOGRAPH:'C0EF:49391:爵 +CJK UNIFIED IDEOGRAPH:'C0F0:49392:牆 +CJK UNIFIED IDEOGRAPH:'C0F1:49393:獰 +CJK UNIFIED IDEOGRAPH:'C0F2:49394:獲 +CJK UNIFIED IDEOGRAPH:'C0F3:49395:璩 +CJK UNIFIED IDEOGRAPH:'C0F4:49396:環 +CJK UNIFIED IDEOGRAPH:'C0F5:49397:璦 +CJK UNIFIED IDEOGRAPH:'C0F6:49398:璨 +CJK UNIFIED IDEOGRAPH:'C0F7:49399:癆 +CJK UNIFIED IDEOGRAPH:'C0F8:49400:療 +CJK UNIFIED IDEOGRAPH:'C0F9:49401:癌 +CJK UNIFIED IDEOGRAPH:'C0FA:49402:盪 +CJK UNIFIED IDEOGRAPH:'C0FB:49403:瞳 +CJK UNIFIED IDEOGRAPH:'C0FC:49404:瞪 +CJK UNIFIED IDEOGRAPH:'C0FD:49405:瞰 +CJK UNIFIED IDEOGRAPH:'C0FE:49406:瞬 +CJK UNIFIED IDEOGRAPH:'C140:49472:瞧 +CJK UNIFIED IDEOGRAPH:'C141:49473:瞭 +CJK UNIFIED IDEOGRAPH:'C142:49474:矯 +CJK UNIFIED IDEOGRAPH:'C143:49475:磷 +CJK UNIFIED IDEOGRAPH:'C144:49476:磺 +CJK UNIFIED IDEOGRAPH:'C145:49477:磴 +CJK UNIFIED IDEOGRAPH:'C146:49478:磯 +CJK UNIFIED IDEOGRAPH:'C147:49479:礁 +CJK UNIFIED IDEOGRAPH:'C148:49480:禧 +CJK UNIFIED IDEOGRAPH:'C149:49481:禪 +CJK UNIFIED IDEOGRAPH:'C14A:49482:穗 +CJK UNIFIED IDEOGRAPH:'C14B:49483:窿 +CJK UNIFIED IDEOGRAPH:'C14C:49484:簇 +CJK UNIFIED IDEOGRAPH:'C14D:49485:簍 +CJK UNIFIED IDEOGRAPH:'C14E:49486:篾 +CJK UNIFIED IDEOGRAPH:'C14F:49487:篷 +CJK UNIFIED IDEOGRAPH:'C150:49488:簌 +CJK UNIFIED IDEOGRAPH:'C151:49489:篠 +CJK UNIFIED IDEOGRAPH:'C152:49490:糠 +CJK UNIFIED IDEOGRAPH:'C153:49491:糜 +CJK UNIFIED IDEOGRAPH:'C154:49492:糞 +CJK UNIFIED IDEOGRAPH:'C155:49493:糢 +CJK UNIFIED IDEOGRAPH:'C156:49494:糟 +CJK UNIFIED IDEOGRAPH:'C157:49495:糙 +CJK UNIFIED IDEOGRAPH:'C158:49496:糝 +CJK UNIFIED IDEOGRAPH:'C159:49497:縮 +CJK UNIFIED IDEOGRAPH:'C15A:49498:績 +CJK UNIFIED IDEOGRAPH:'C15B:49499:繆 +CJK UNIFIED IDEOGRAPH:'C15C:49500:縷 +CJK UNIFIED IDEOGRAPH:'C15D:49501:縲 +CJK UNIFIED IDEOGRAPH:'C15E:49502:繃 +CJK UNIFIED IDEOGRAPH:'C15F:49503:縫 +CJK UNIFIED IDEOGRAPH:'C160:49504:總 +CJK UNIFIED IDEOGRAPH:'C161:49505:縱 +CJK UNIFIED IDEOGRAPH:'C162:49506:繅 +CJK UNIFIED IDEOGRAPH:'C163:49507:繁 +CJK UNIFIED IDEOGRAPH:'C164:49508:縴 +CJK UNIFIED IDEOGRAPH:'C165:49509:縹 +CJK UNIFIED IDEOGRAPH:'C166:49510:繈 +CJK UNIFIED IDEOGRAPH:'C167:49511:縵 +CJK UNIFIED IDEOGRAPH:'C168:49512:縿 +CJK UNIFIED IDEOGRAPH:'C169:49513:縯 +CJK UNIFIED IDEOGRAPH:'C16A:49514:罄 +CJK UNIFIED IDEOGRAPH:'C16B:49515:翳 +CJK UNIFIED IDEOGRAPH:'C16C:49516:翼 +CJK UNIFIED IDEOGRAPH:'C16D:49517:聱 +CJK UNIFIED IDEOGRAPH:'C16E:49518:聲 +CJK UNIFIED IDEOGRAPH:'C16F:49519:聰 +CJK UNIFIED IDEOGRAPH:'C170:49520:聯 +CJK UNIFIED IDEOGRAPH:'C171:49521:聳 +CJK UNIFIED IDEOGRAPH:'C172:49522:臆 +CJK UNIFIED IDEOGRAPH:'C173:49523:臃 +CJK UNIFIED IDEOGRAPH:'C174:49524:膺 +CJK UNIFIED IDEOGRAPH:'C175:49525:臂 +CJK UNIFIED IDEOGRAPH:'C176:49526:臀 +CJK UNIFIED IDEOGRAPH:'C177:49527:膿 +CJK UNIFIED IDEOGRAPH:'C178:49528:膽 +CJK UNIFIED IDEOGRAPH:'C179:49529:臉 +CJK UNIFIED IDEOGRAPH:'C17A:49530:膾 +CJK UNIFIED IDEOGRAPH:'C17B:49531:臨 +CJK UNIFIED IDEOGRAPH:'C17C:49532:舉 +CJK UNIFIED IDEOGRAPH:'C17D:49533:艱 +CJK UNIFIED IDEOGRAPH:'C17E:49534:薪 +CJK UNIFIED IDEOGRAPH:'C1A1:49569:薄 +CJK UNIFIED IDEOGRAPH:'C1A2:49570:蕾 +CJK UNIFIED IDEOGRAPH:'C1A3:49571:薜 +CJK UNIFIED IDEOGRAPH:'C1A4:49572:薑 +CJK UNIFIED IDEOGRAPH:'C1A5:49573:薔 +CJK UNIFIED IDEOGRAPH:'C1A6:49574:薯 +CJK UNIFIED IDEOGRAPH:'C1A7:49575:薛 +CJK UNIFIED IDEOGRAPH:'C1A8:49576:薇 +CJK UNIFIED IDEOGRAPH:'C1A9:49577:薨 +CJK UNIFIED IDEOGRAPH:'C1AA:49578:薊 +CJK UNIFIED IDEOGRAPH:'C1AB:49579:虧 +CJK UNIFIED IDEOGRAPH:'C1AC:49580:蟀 +CJK UNIFIED IDEOGRAPH:'C1AD:49581:蟑 +CJK UNIFIED IDEOGRAPH:'C1AE:49582:螳 +CJK UNIFIED IDEOGRAPH:'C1AF:49583:蟒 +CJK UNIFIED IDEOGRAPH:'C1B0:49584:蟆 +CJK UNIFIED IDEOGRAPH:'C1B1:49585:螫 +CJK UNIFIED IDEOGRAPH:'C1B2:49586:螻 +CJK UNIFIED IDEOGRAPH:'C1B3:49587:螺 +CJK UNIFIED IDEOGRAPH:'C1B4:49588:蟈 +CJK UNIFIED IDEOGRAPH:'C1B5:49589:蟋 +CJK UNIFIED IDEOGRAPH:'C1B6:49590:褻 +CJK UNIFIED IDEOGRAPH:'C1B7:49591:褶 +CJK UNIFIED IDEOGRAPH:'C1B8:49592:襄 +CJK UNIFIED IDEOGRAPH:'C1B9:49593:褸 +CJK UNIFIED IDEOGRAPH:'C1BA:49594:褽 +CJK UNIFIED IDEOGRAPH:'C1BB:49595:覬 +CJK UNIFIED IDEOGRAPH:'C1BC:49596:謎 +CJK UNIFIED IDEOGRAPH:'C1BD:49597:謗 +CJK UNIFIED IDEOGRAPH:'C1BE:49598:謙 +CJK UNIFIED IDEOGRAPH:'C1BF:49599:講 +CJK UNIFIED IDEOGRAPH:'C1C0:49600:謊 +CJK UNIFIED IDEOGRAPH:'C1C1:49601:謠 +CJK UNIFIED IDEOGRAPH:'C1C2:49602:謝 +CJK UNIFIED IDEOGRAPH:'C1C3:49603:謄 +CJK UNIFIED IDEOGRAPH:'C1C4:49604:謐 +CJK UNIFIED IDEOGRAPH:'C1C5:49605:豁 +CJK UNIFIED IDEOGRAPH:'C1C6:49606:谿 +CJK UNIFIED IDEOGRAPH:'C1C7:49607:豳 +CJK UNIFIED IDEOGRAPH:'C1C8:49608:賺 +CJK UNIFIED IDEOGRAPH:'C1C9:49609:賽 +CJK UNIFIED IDEOGRAPH:'C1CA:49610:購 +CJK UNIFIED IDEOGRAPH:'C1CB:49611:賸 +CJK UNIFIED IDEOGRAPH:'C1CC:49612:賻 +CJK UNIFIED IDEOGRAPH:'C1CD:49613:趨 +CJK UNIFIED IDEOGRAPH:'C1CE:49614:蹉 +CJK UNIFIED IDEOGRAPH:'C1CF:49615:蹋 +CJK UNIFIED IDEOGRAPH:'C1D0:49616:蹈 +CJK UNIFIED IDEOGRAPH:'C1D1:49617:蹊 +CJK UNIFIED IDEOGRAPH:'C1D2:49618:轄 +CJK UNIFIED IDEOGRAPH:'C1D3:49619:輾 +CJK UNIFIED IDEOGRAPH:'C1D4:49620:轂 +CJK UNIFIED IDEOGRAPH:'C1D5:49621:轅 +CJK UNIFIED IDEOGRAPH:'C1D6:49622:輿 +CJK UNIFIED IDEOGRAPH:'C1D7:49623:避 +CJK UNIFIED IDEOGRAPH:'C1D8:49624:遽 +CJK UNIFIED IDEOGRAPH:'C1D9:49625:還 +CJK UNIFIED IDEOGRAPH:'C1DA:49626:邁 +CJK UNIFIED IDEOGRAPH:'C1DB:49627:邂 +CJK UNIFIED IDEOGRAPH:'C1DC:49628:邀 +CJK UNIFIED IDEOGRAPH:'C1DD:49629:鄹 +CJK UNIFIED IDEOGRAPH:'C1DE:49630:醣 +CJK UNIFIED IDEOGRAPH:'C1DF:49631:醞 +CJK UNIFIED IDEOGRAPH:'C1E0:49632:醜 +CJK UNIFIED IDEOGRAPH:'C1E1:49633:鍍 +CJK UNIFIED IDEOGRAPH:'C1E2:49634:鎂 +CJK UNIFIED IDEOGRAPH:'C1E3:49635:錨 +CJK UNIFIED IDEOGRAPH:'C1E4:49636:鍵 +CJK UNIFIED IDEOGRAPH:'C1E5:49637:鍊 +CJK UNIFIED IDEOGRAPH:'C1E6:49638:鍥 +CJK UNIFIED IDEOGRAPH:'C1E7:49639:鍋 +CJK UNIFIED IDEOGRAPH:'C1E8:49640:錘 +CJK UNIFIED IDEOGRAPH:'C1E9:49641:鍾 +CJK UNIFIED IDEOGRAPH:'C1EA:49642:鍬 +CJK UNIFIED IDEOGRAPH:'C1EB:49643:鍛 +CJK UNIFIED IDEOGRAPH:'C1EC:49644:鍰 +CJK UNIFIED IDEOGRAPH:'C1ED:49645:鍚 +CJK UNIFIED IDEOGRAPH:'C1EE:49646:鍔 +CJK UNIFIED IDEOGRAPH:'C1EF:49647:闊 +CJK UNIFIED IDEOGRAPH:'C1F0:49648:闋 +CJK UNIFIED IDEOGRAPH:'C1F1:49649:闌 +CJK UNIFIED IDEOGRAPH:'C1F2:49650:闈 +CJK UNIFIED IDEOGRAPH:'C1F3:49651:闆 +CJK UNIFIED IDEOGRAPH:'C1F4:49652:隱 +CJK UNIFIED IDEOGRAPH:'C1F5:49653:隸 +CJK UNIFIED IDEOGRAPH:'C1F6:49654:雖 +CJK UNIFIED IDEOGRAPH:'C1F7:49655:霜 +CJK UNIFIED IDEOGRAPH:'C1F8:49656:霞 +CJK UNIFIED IDEOGRAPH:'C1F9:49657:鞠 +CJK UNIFIED IDEOGRAPH:'C1FA:49658:韓 +CJK UNIFIED IDEOGRAPH:'C1FB:49659:顆 +CJK UNIFIED IDEOGRAPH:'C1FC:49660:颶 +CJK UNIFIED IDEOGRAPH:'C1FD:49661:餵 +CJK UNIFIED IDEOGRAPH:'C1FE:49662:騁 +CJK UNIFIED IDEOGRAPH:'C240:49728:駿 +CJK UNIFIED IDEOGRAPH:'C241:49729:鮮 +CJK UNIFIED IDEOGRAPH:'C242:49730:鮫 +CJK UNIFIED IDEOGRAPH:'C243:49731:鮪 +CJK UNIFIED IDEOGRAPH:'C244:49732:鮭 +CJK UNIFIED IDEOGRAPH:'C245:49733:鴻 +CJK UNIFIED IDEOGRAPH:'C246:49734:鴿 +CJK UNIFIED IDEOGRAPH:'C247:49735:麋 +CJK UNIFIED IDEOGRAPH:'C248:49736:黏 +CJK UNIFIED IDEOGRAPH:'C249:49737:點 +CJK UNIFIED IDEOGRAPH:'C24A:49738:黜 +CJK UNIFIED IDEOGRAPH:'C24B:49739:黝 +CJK UNIFIED IDEOGRAPH:'C24C:49740:黛 +CJK UNIFIED IDEOGRAPH:'C24D:49741:鼾 +CJK UNIFIED IDEOGRAPH:'C24E:49742:齋 +CJK UNIFIED IDEOGRAPH:'C24F:49743:叢 +CJK UNIFIED IDEOGRAPH:'C250:49744:嚕 +CJK UNIFIED IDEOGRAPH:'C251:49745:嚮 +CJK UNIFIED IDEOGRAPH:'C252:49746:壙 +CJK UNIFIED IDEOGRAPH:'C253:49747:壘 +CJK UNIFIED IDEOGRAPH:'C254:49748:嬸 +CJK UNIFIED IDEOGRAPH:'C255:49749:彝 +CJK UNIFIED IDEOGRAPH:'C256:49750:懣 +CJK UNIFIED IDEOGRAPH:'C257:49751:戳 +CJK UNIFIED IDEOGRAPH:'C258:49752:擴 +CJK UNIFIED IDEOGRAPH:'C259:49753:擲 +CJK UNIFIED IDEOGRAPH:'C25A:49754:擾 +CJK UNIFIED IDEOGRAPH:'C25B:49755:攆 +CJK UNIFIED IDEOGRAPH:'C25C:49756:擺 +CJK UNIFIED IDEOGRAPH:'C25D:49757:擻 +CJK UNIFIED IDEOGRAPH:'C25E:49758:擷 +CJK UNIFIED IDEOGRAPH:'C25F:49759:斷 +CJK UNIFIED IDEOGRAPH:'C260:49760:曜 +CJK UNIFIED IDEOGRAPH:'C261:49761:朦 +CJK UNIFIED IDEOGRAPH:'C262:49762:檳 +CJK UNIFIED IDEOGRAPH:'C263:49763:檬 +CJK UNIFIED IDEOGRAPH:'C264:49764:櫃 +CJK UNIFIED IDEOGRAPH:'C265:49765:檻 +CJK UNIFIED IDEOGRAPH:'C266:49766:檸 +CJK UNIFIED IDEOGRAPH:'C267:49767:櫂 +CJK UNIFIED IDEOGRAPH:'C268:49768:檮 +CJK UNIFIED IDEOGRAPH:'C269:49769:檯 +CJK UNIFIED IDEOGRAPH:'C26A:49770:歟 +CJK UNIFIED IDEOGRAPH:'C26B:49771:歸 +CJK UNIFIED IDEOGRAPH:'C26C:49772:殯 +CJK UNIFIED IDEOGRAPH:'C26D:49773:瀉 +CJK UNIFIED IDEOGRAPH:'C26E:49774:瀋 +CJK UNIFIED IDEOGRAPH:'C26F:49775:濾 +CJK UNIFIED IDEOGRAPH:'C270:49776:瀆 +CJK UNIFIED IDEOGRAPH:'C271:49777:濺 +CJK UNIFIED IDEOGRAPH:'C272:49778:瀑 +CJK UNIFIED IDEOGRAPH:'C273:49779:瀏 +CJK UNIFIED IDEOGRAPH:'C274:49780:燻 +CJK UNIFIED IDEOGRAPH:'C275:49781:燼 +CJK UNIFIED IDEOGRAPH:'C276:49782:燾 +CJK UNIFIED IDEOGRAPH:'C277:49783:燸 +CJK UNIFIED IDEOGRAPH:'C278:49784:獷 +CJK UNIFIED IDEOGRAPH:'C279:49785:獵 +CJK UNIFIED IDEOGRAPH:'C27A:49786:璧 +CJK UNIFIED IDEOGRAPH:'C27B:49787:璿 +CJK UNIFIED IDEOGRAPH:'C27C:49788:甕 +CJK UNIFIED IDEOGRAPH:'C27D:49789:癖 +CJK UNIFIED IDEOGRAPH:'C27E:49790:癘 +CJK UNIFIED IDEOGRAPH:'C2A1:49825:癒 +CJK UNIFIED IDEOGRAPH:'C2A2:49826:瞽 +CJK UNIFIED IDEOGRAPH:'C2A3:49827:瞿 +CJK UNIFIED IDEOGRAPH:'C2A4:49828:瞻 +CJK UNIFIED IDEOGRAPH:'C2A5:49829:瞼 +CJK UNIFIED IDEOGRAPH:'C2A6:49830:礎 +CJK UNIFIED IDEOGRAPH:'C2A7:49831:禮 +CJK UNIFIED IDEOGRAPH:'C2A8:49832:穡 +CJK UNIFIED IDEOGRAPH:'C2A9:49833:穢 +CJK UNIFIED IDEOGRAPH:'C2AA:49834:穠 +CJK UNIFIED IDEOGRAPH:'C2AB:49835:竄 +CJK UNIFIED IDEOGRAPH:'C2AC:49836:竅 +CJK UNIFIED IDEOGRAPH:'C2AD:49837:簫 +CJK UNIFIED IDEOGRAPH:'C2AE:49838:簧 +CJK UNIFIED IDEOGRAPH:'C2AF:49839:簪 +CJK UNIFIED IDEOGRAPH:'C2B0:49840:簞 +CJK UNIFIED IDEOGRAPH:'C2B1:49841:簣 +CJK UNIFIED IDEOGRAPH:'C2B2:49842:簡 +CJK UNIFIED IDEOGRAPH:'C2B3:49843:糧 +CJK UNIFIED IDEOGRAPH:'C2B4:49844:織 +CJK UNIFIED IDEOGRAPH:'C2B5:49845:繕 +CJK UNIFIED IDEOGRAPH:'C2B6:49846:繞 +CJK UNIFIED IDEOGRAPH:'C2B7:49847:繚 +CJK UNIFIED IDEOGRAPH:'C2B8:49848:繡 +CJK UNIFIED IDEOGRAPH:'C2B9:49849:繒 +CJK UNIFIED IDEOGRAPH:'C2BA:49850:繙 +CJK UNIFIED IDEOGRAPH:'C2BB:49851:罈 +CJK UNIFIED IDEOGRAPH:'C2BC:49852:翹 +CJK UNIFIED IDEOGRAPH:'C2BD:49853:翻 +CJK UNIFIED IDEOGRAPH:'C2BE:49854:職 +CJK UNIFIED IDEOGRAPH:'C2BF:49855:聶 +CJK UNIFIED IDEOGRAPH:'C2C0:49856:臍 +CJK UNIFIED IDEOGRAPH:'C2C1:49857:臏 +CJK UNIFIED IDEOGRAPH:'C2C2:49858:舊 +CJK UNIFIED IDEOGRAPH:'C2C3:49859:藏 +CJK UNIFIED IDEOGRAPH:'C2C4:49860:薩 +CJK UNIFIED IDEOGRAPH:'C2C5:49861:藍 +CJK UNIFIED IDEOGRAPH:'C2C6:49862:藐 +CJK UNIFIED IDEOGRAPH:'C2C7:49863:藉 +CJK UNIFIED IDEOGRAPH:'C2C8:49864:薰 +CJK UNIFIED IDEOGRAPH:'C2C9:49865:薺 +CJK UNIFIED IDEOGRAPH:'C2CA:49866:薹 +CJK UNIFIED IDEOGRAPH:'C2CB:49867:薦 +CJK UNIFIED IDEOGRAPH:'C2CC:49868:蟯 +CJK UNIFIED IDEOGRAPH:'C2CD:49869:蟬 +CJK UNIFIED IDEOGRAPH:'C2CE:49870:蟲 +CJK UNIFIED IDEOGRAPH:'C2CF:49871:蟠 +CJK UNIFIED IDEOGRAPH:'C2D0:49872:覆 +CJK UNIFIED IDEOGRAPH:'C2D1:49873:覲 +CJK UNIFIED IDEOGRAPH:'C2D2:49874:觴 +CJK UNIFIED IDEOGRAPH:'C2D3:49875:謨 +CJK UNIFIED IDEOGRAPH:'C2D4:49876:謹 +CJK UNIFIED IDEOGRAPH:'C2D5:49877:謬 +CJK UNIFIED IDEOGRAPH:'C2D6:49878:謫 +CJK UNIFIED IDEOGRAPH:'C2D7:49879:豐 +CJK UNIFIED IDEOGRAPH:'C2D8:49880:贅 +CJK UNIFIED IDEOGRAPH:'C2D9:49881:蹙 +CJK UNIFIED IDEOGRAPH:'C2DA:49882:蹣 +CJK UNIFIED IDEOGRAPH:'C2DB:49883:蹦 +CJK UNIFIED IDEOGRAPH:'C2DC:49884:蹤 +CJK UNIFIED IDEOGRAPH:'C2DD:49885:蹟 +CJK UNIFIED IDEOGRAPH:'C2DE:49886:蹕 +CJK UNIFIED IDEOGRAPH:'C2DF:49887:軀 +CJK UNIFIED IDEOGRAPH:'C2E0:49888:轉 +CJK UNIFIED IDEOGRAPH:'C2E1:49889:轍 +CJK UNIFIED IDEOGRAPH:'C2E2:49890:邇 +CJK UNIFIED IDEOGRAPH:'C2E3:49891:邃 +CJK UNIFIED IDEOGRAPH:'C2E4:49892:邈 +CJK UNIFIED IDEOGRAPH:'C2E5:49893:醫 +CJK UNIFIED IDEOGRAPH:'C2E6:49894:醬 +CJK UNIFIED IDEOGRAPH:'C2E7:49895:釐 +CJK UNIFIED IDEOGRAPH:'C2E8:49896:鎔 +CJK UNIFIED IDEOGRAPH:'C2E9:49897:鎊 +CJK UNIFIED IDEOGRAPH:'C2EA:49898:鎖 +CJK UNIFIED IDEOGRAPH:'C2EB:49899:鎢 +CJK UNIFIED IDEOGRAPH:'C2EC:49900:鎳 +CJK UNIFIED IDEOGRAPH:'C2ED:49901:鎮 +CJK UNIFIED IDEOGRAPH:'C2EE:49902:鎬 +CJK UNIFIED IDEOGRAPH:'C2EF:49903:鎰 +CJK UNIFIED IDEOGRAPH:'C2F0:49904:鎘 +CJK UNIFIED IDEOGRAPH:'C2F1:49905:鎚 +CJK UNIFIED IDEOGRAPH:'C2F2:49906:鎗 +CJK UNIFIED IDEOGRAPH:'C2F3:49907:闔 +CJK UNIFIED IDEOGRAPH:'C2F4:49908:闖 +CJK UNIFIED IDEOGRAPH:'C2F5:49909:闐 +CJK UNIFIED IDEOGRAPH:'C2F6:49910:闕 +CJK UNIFIED IDEOGRAPH:'C2F7:49911:離 +CJK UNIFIED IDEOGRAPH:'C2F8:49912:雜 +CJK UNIFIED IDEOGRAPH:'C2F9:49913:雙 +CJK UNIFIED IDEOGRAPH:'C2FA:49914:雛 +CJK UNIFIED IDEOGRAPH:'C2FB:49915:雞 +CJK UNIFIED IDEOGRAPH:'C2FC:49916:霤 +CJK UNIFIED IDEOGRAPH:'C2FD:49917:鞣 +CJK UNIFIED IDEOGRAPH:'C2FE:49918:鞦 +CJK UNIFIED IDEOGRAPH:'C340:49984:鞭 +CJK UNIFIED IDEOGRAPH:'C341:49985:韹 +CJK UNIFIED IDEOGRAPH:'C342:49986:額 +CJK UNIFIED IDEOGRAPH:'C343:49987:顏 +CJK UNIFIED IDEOGRAPH:'C344:49988:題 +CJK UNIFIED IDEOGRAPH:'C345:49989:顎 +CJK UNIFIED IDEOGRAPH:'C346:49990:顓 +CJK UNIFIED IDEOGRAPH:'C347:49991:颺 +CJK UNIFIED IDEOGRAPH:'C348:49992:餾 +CJK UNIFIED IDEOGRAPH:'C349:49993:餿 +CJK UNIFIED IDEOGRAPH:'C34A:49994:餽 +CJK UNIFIED IDEOGRAPH:'C34B:49995:餮 +CJK UNIFIED IDEOGRAPH:'C34C:49996:馥 +CJK UNIFIED IDEOGRAPH:'C34D:49997:騎 +CJK UNIFIED IDEOGRAPH:'C34E:49998:髁 +CJK UNIFIED IDEOGRAPH:'C34F:49999:鬃 +CJK UNIFIED IDEOGRAPH:'C350:50000:鬆 +CJK UNIFIED IDEOGRAPH:'C351:50001:魏 +CJK UNIFIED IDEOGRAPH:'C352:50002:魎 +CJK UNIFIED IDEOGRAPH:'C353:50003:魍 +CJK UNIFIED IDEOGRAPH:'C354:50004:鯊 +CJK UNIFIED IDEOGRAPH:'C355:50005:鯉 +CJK UNIFIED IDEOGRAPH:'C356:50006:鯽 +CJK UNIFIED IDEOGRAPH:'C357:50007:鯈 +CJK UNIFIED IDEOGRAPH:'C358:50008:鯀 +CJK UNIFIED IDEOGRAPH:'C359:50009:鵑 +CJK UNIFIED IDEOGRAPH:'C35A:50010:鵝 +CJK UNIFIED IDEOGRAPH:'C35B:50011:鵠 +CJK UNIFIED IDEOGRAPH:'C35C:50012:黠 +CJK UNIFIED IDEOGRAPH:'C35D:50013:鼕 +CJK UNIFIED IDEOGRAPH:'C35E:50014:鼬 +CJK UNIFIED IDEOGRAPH:'C35F:50015:儳 +CJK UNIFIED IDEOGRAPH:'C360:50016:嚥 +CJK UNIFIED IDEOGRAPH:'C361:50017:壞 +CJK UNIFIED IDEOGRAPH:'C362:50018:壟 +CJK UNIFIED IDEOGRAPH:'C363:50019:壢 +CJK UNIFIED IDEOGRAPH:'C364:50020:寵 +CJK UNIFIED IDEOGRAPH:'C365:50021:龐 +CJK UNIFIED IDEOGRAPH:'C366:50022:廬 +CJK UNIFIED IDEOGRAPH:'C367:50023:懲 +CJK UNIFIED IDEOGRAPH:'C368:50024:懷 +CJK UNIFIED IDEOGRAPH:'C369:50025:懶 +CJK UNIFIED IDEOGRAPH:'C36A:50026:懵 +CJK UNIFIED IDEOGRAPH:'C36B:50027:攀 +CJK UNIFIED IDEOGRAPH:'C36C:50028:攏 +CJK UNIFIED IDEOGRAPH:'C36D:50029:曠 +CJK UNIFIED IDEOGRAPH:'C36E:50030:曝 +CJK UNIFIED IDEOGRAPH:'C36F:50031:櫥 +CJK UNIFIED IDEOGRAPH:'C370:50032:櫝 +CJK UNIFIED IDEOGRAPH:'C371:50033:櫚 +CJK UNIFIED IDEOGRAPH:'C372:50034:櫓 +CJK UNIFIED IDEOGRAPH:'C373:50035:瀛 +CJK UNIFIED IDEOGRAPH:'C374:50036:瀟 +CJK UNIFIED IDEOGRAPH:'C375:50037:瀨 +CJK UNIFIED IDEOGRAPH:'C376:50038:瀚 +CJK UNIFIED IDEOGRAPH:'C377:50039:瀝 +CJK UNIFIED IDEOGRAPH:'C378:50040:瀕 +CJK UNIFIED IDEOGRAPH:'C379:50041:瀘 +CJK UNIFIED IDEOGRAPH:'C37A:50042:爆 +CJK UNIFIED IDEOGRAPH:'C37B:50043:爍 +CJK UNIFIED IDEOGRAPH:'C37C:50044:牘 +CJK UNIFIED IDEOGRAPH:'C37D:50045:犢 +CJK UNIFIED IDEOGRAPH:'C37E:50046:獸 +CJK UNIFIED IDEOGRAPH:'C3A1:50081:獺 +CJK UNIFIED IDEOGRAPH:'C3A2:50082:璽 +CJK UNIFIED IDEOGRAPH:'C3A3:50083:瓊 +CJK UNIFIED IDEOGRAPH:'C3A4:50084:瓣 +CJK UNIFIED IDEOGRAPH:'C3A5:50085:疇 +CJK UNIFIED IDEOGRAPH:'C3A6:50086:疆 +CJK UNIFIED IDEOGRAPH:'C3A7:50087:癟 +CJK UNIFIED IDEOGRAPH:'C3A8:50088:癡 +CJK UNIFIED IDEOGRAPH:'C3A9:50089:矇 +CJK UNIFIED IDEOGRAPH:'C3AA:50090:礙 +CJK UNIFIED IDEOGRAPH:'C3AB:50091:禱 +CJK UNIFIED IDEOGRAPH:'C3AC:50092:穫 +CJK UNIFIED IDEOGRAPH:'C3AD:50093:穩 +CJK UNIFIED IDEOGRAPH:'C3AE:50094:簾 +CJK UNIFIED IDEOGRAPH:'C3AF:50095:簿 +CJK UNIFIED IDEOGRAPH:'C3B0:50096:簸 +CJK UNIFIED IDEOGRAPH:'C3B1:50097:簽 +CJK UNIFIED IDEOGRAPH:'C3B2:50098:簷 +CJK UNIFIED IDEOGRAPH:'C3B3:50099:籀 +CJK UNIFIED IDEOGRAPH:'C3B4:50100:繫 +CJK UNIFIED IDEOGRAPH:'C3B5:50101:繭 +CJK UNIFIED IDEOGRAPH:'C3B6:50102:繹 +CJK UNIFIED IDEOGRAPH:'C3B7:50103:繩 +CJK UNIFIED IDEOGRAPH:'C3B8:50104:繪 +CJK UNIFIED IDEOGRAPH:'C3B9:50105:羅 +CJK UNIFIED IDEOGRAPH:'C3BA:50106:繳 +CJK UNIFIED IDEOGRAPH:'C3BB:50107:羶 +CJK UNIFIED IDEOGRAPH:'C3BC:50108:羹 +CJK UNIFIED IDEOGRAPH:'C3BD:50109:羸 +CJK UNIFIED IDEOGRAPH:'C3BE:50110:臘 +CJK UNIFIED IDEOGRAPH:'C3BF:50111:藩 +CJK UNIFIED IDEOGRAPH:'C3C0:50112:藝 +CJK UNIFIED IDEOGRAPH:'C3C1:50113:藪 +CJK UNIFIED IDEOGRAPH:'C3C2:50114:藕 +CJK UNIFIED IDEOGRAPH:'C3C3:50115:藤 +CJK UNIFIED IDEOGRAPH:'C3C4:50116:藥 +CJK UNIFIED IDEOGRAPH:'C3C5:50117:藷 +CJK UNIFIED IDEOGRAPH:'C3C6:50118:蟻 +CJK UNIFIED IDEOGRAPH:'C3C7:50119:蠅 +CJK UNIFIED IDEOGRAPH:'C3C8:50120:蠍 +CJK UNIFIED IDEOGRAPH:'C3C9:50121:蟹 +CJK UNIFIED IDEOGRAPH:'C3CA:50122:蟾 +CJK UNIFIED IDEOGRAPH:'C3CB:50123:襠 +CJK UNIFIED IDEOGRAPH:'C3CC:50124:襟 +CJK UNIFIED IDEOGRAPH:'C3CD:50125:襖 +CJK UNIFIED IDEOGRAPH:'C3CE:50126:襞 +CJK UNIFIED IDEOGRAPH:'C3CF:50127:譁 +CJK UNIFIED IDEOGRAPH:'C3D0:50128:譜 +CJK UNIFIED IDEOGRAPH:'C3D1:50129:識 +CJK UNIFIED IDEOGRAPH:'C3D2:50130:證 +CJK UNIFIED IDEOGRAPH:'C3D3:50131:譚 +CJK UNIFIED IDEOGRAPH:'C3D4:50132:譎 +CJK UNIFIED IDEOGRAPH:'C3D5:50133:譏 +CJK UNIFIED IDEOGRAPH:'C3D6:50134:譆 +CJK UNIFIED IDEOGRAPH:'C3D7:50135:譙 +CJK UNIFIED IDEOGRAPH:'C3D8:50136:贈 +CJK UNIFIED IDEOGRAPH:'C3D9:50137:贊 +CJK UNIFIED IDEOGRAPH:'C3DA:50138:蹼 +CJK UNIFIED IDEOGRAPH:'C3DB:50139:蹲 +CJK UNIFIED IDEOGRAPH:'C3DC:50140:躇 +CJK UNIFIED IDEOGRAPH:'C3DD:50141:蹶 +CJK UNIFIED IDEOGRAPH:'C3DE:50142:蹬 +CJK UNIFIED IDEOGRAPH:'C3DF:50143:蹺 +CJK UNIFIED IDEOGRAPH:'C3E0:50144:蹴 +CJK UNIFIED IDEOGRAPH:'C3E1:50145:轔 +CJK UNIFIED IDEOGRAPH:'C3E2:50146:轎 +CJK UNIFIED IDEOGRAPH:'C3E3:50147:辭 +CJK UNIFIED IDEOGRAPH:'C3E4:50148:邊 +CJK UNIFIED IDEOGRAPH:'C3E5:50149:邋 +CJK UNIFIED IDEOGRAPH:'C3E6:50150:醱 +CJK UNIFIED IDEOGRAPH:'C3E7:50151:醮 +CJK UNIFIED IDEOGRAPH:'C3E8:50152:鏡 +CJK UNIFIED IDEOGRAPH:'C3E9:50153:鏑 +CJK UNIFIED IDEOGRAPH:'C3EA:50154:鏟 +CJK UNIFIED IDEOGRAPH:'C3EB:50155:鏃 +CJK UNIFIED IDEOGRAPH:'C3EC:50156:鏈 +CJK UNIFIED IDEOGRAPH:'C3ED:50157:鏜 +CJK UNIFIED IDEOGRAPH:'C3EE:50158:鏝 +CJK UNIFIED IDEOGRAPH:'C3EF:50159:鏖 +CJK UNIFIED IDEOGRAPH:'C3F0:50160:鏢 +CJK UNIFIED IDEOGRAPH:'C3F1:50161:鏍 +CJK UNIFIED IDEOGRAPH:'C3F2:50162:鏘 +CJK UNIFIED IDEOGRAPH:'C3F3:50163:鏤 +CJK UNIFIED IDEOGRAPH:'C3F4:50164:鏗 +CJK UNIFIED IDEOGRAPH:'C3F5:50165:鏨 +CJK UNIFIED IDEOGRAPH:'C3F6:50166:關 +CJK UNIFIED IDEOGRAPH:'C3F7:50167:隴 +CJK UNIFIED IDEOGRAPH:'C3F8:50168:難 +CJK UNIFIED IDEOGRAPH:'C3F9:50169:霪 +CJK UNIFIED IDEOGRAPH:'C3FA:50170:霧 +CJK UNIFIED IDEOGRAPH:'C3FB:50171:靡 +CJK UNIFIED IDEOGRAPH:'C3FC:50172:韜 +CJK UNIFIED IDEOGRAPH:'C3FD:50173:韻 +CJK UNIFIED IDEOGRAPH:'C3FE:50174:類 +CJK UNIFIED IDEOGRAPH:'C440:50240:願 +CJK UNIFIED IDEOGRAPH:'C441:50241:顛 +CJK UNIFIED IDEOGRAPH:'C442:50242:颼 +CJK UNIFIED IDEOGRAPH:'C443:50243:饅 +CJK UNIFIED IDEOGRAPH:'C444:50244:饉 +CJK UNIFIED IDEOGRAPH:'C445:50245:騖 +CJK UNIFIED IDEOGRAPH:'C446:50246:騙 +CJK UNIFIED IDEOGRAPH:'C447:50247:鬍 +CJK UNIFIED IDEOGRAPH:'C448:50248:鯨 +CJK UNIFIED IDEOGRAPH:'C449:50249:鯧 +CJK UNIFIED IDEOGRAPH:'C44A:50250:鯖 +CJK UNIFIED IDEOGRAPH:'C44B:50251:鯛 +CJK UNIFIED IDEOGRAPH:'C44C:50252:鶉 +CJK UNIFIED IDEOGRAPH:'C44D:50253:鵡 +CJK UNIFIED IDEOGRAPH:'C44E:50254:鵲 +CJK UNIFIED IDEOGRAPH:'C44F:50255:鵪 +CJK UNIFIED IDEOGRAPH:'C450:50256:鵬 +CJK UNIFIED IDEOGRAPH:'C451:50257:麒 +CJK UNIFIED IDEOGRAPH:'C452:50258:麗 +CJK UNIFIED IDEOGRAPH:'C453:50259:麓 +CJK UNIFIED IDEOGRAPH:'C454:50260:麴 +CJK UNIFIED IDEOGRAPH:'C455:50261:勸 +CJK UNIFIED IDEOGRAPH:'C456:50262:嚨 +CJK UNIFIED IDEOGRAPH:'C457:50263:嚷 +CJK UNIFIED IDEOGRAPH:'C458:50264:嚶 +CJK UNIFIED IDEOGRAPH:'C459:50265:嚴 +CJK UNIFIED IDEOGRAPH:'C45A:50266:嚼 +CJK UNIFIED IDEOGRAPH:'C45B:50267:壤 +CJK UNIFIED IDEOGRAPH:'C45C:50268:孀 +CJK UNIFIED IDEOGRAPH:'C45D:50269:孃 +CJK UNIFIED IDEOGRAPH:'C45E:50270:孽 +CJK UNIFIED IDEOGRAPH:'C45F:50271:寶 +CJK UNIFIED IDEOGRAPH:'C460:50272:巉 +CJK UNIFIED IDEOGRAPH:'C461:50273:懸 +CJK UNIFIED IDEOGRAPH:'C462:50274:懺 +CJK UNIFIED IDEOGRAPH:'C463:50275:攘 +CJK UNIFIED IDEOGRAPH:'C464:50276:攔 +CJK UNIFIED IDEOGRAPH:'C465:50277:攙 +CJK UNIFIED IDEOGRAPH:'C466:50278:曦 +CJK UNIFIED IDEOGRAPH:'C467:50279:朧 +CJK UNIFIED IDEOGRAPH:'C468:50280:櫬 +CJK UNIFIED IDEOGRAPH:'C469:50281:瀾 +CJK UNIFIED IDEOGRAPH:'C46A:50282:瀰 +CJK UNIFIED IDEOGRAPH:'C46B:50283:瀲 +CJK UNIFIED IDEOGRAPH:'C46C:50284:爐 +CJK UNIFIED IDEOGRAPH:'C46D:50285:獻 +CJK UNIFIED IDEOGRAPH:'C46E:50286:瓏 +CJK UNIFIED IDEOGRAPH:'C46F:50287:癢 +CJK UNIFIED IDEOGRAPH:'C470:50288:癥 +CJK UNIFIED IDEOGRAPH:'C471:50289:礦 +CJK UNIFIED IDEOGRAPH:'C472:50290:礪 +CJK UNIFIED IDEOGRAPH:'C473:50291:礬 +CJK UNIFIED IDEOGRAPH:'C474:50292:礫 +CJK UNIFIED IDEOGRAPH:'C475:50293:竇 +CJK UNIFIED IDEOGRAPH:'C476:50294:競 +CJK UNIFIED IDEOGRAPH:'C477:50295:籌 +CJK UNIFIED IDEOGRAPH:'C478:50296:籃 +CJK UNIFIED IDEOGRAPH:'C479:50297:籍 +CJK UNIFIED IDEOGRAPH:'C47A:50298:糯 +CJK UNIFIED IDEOGRAPH:'C47B:50299:糰 +CJK UNIFIED IDEOGRAPH:'C47C:50300:辮 +CJK UNIFIED IDEOGRAPH:'C47D:50301:繽 +CJK UNIFIED IDEOGRAPH:'C47E:50302:繼 +CJK UNIFIED IDEOGRAPH:'C4A1:50337:纂 +CJK UNIFIED IDEOGRAPH:'C4A2:50338:罌 +CJK UNIFIED IDEOGRAPH:'C4A3:50339:耀 +CJK UNIFIED IDEOGRAPH:'C4A4:50340:臚 +CJK UNIFIED IDEOGRAPH:'C4A5:50341:艦 +CJK UNIFIED IDEOGRAPH:'C4A6:50342:藻 +CJK UNIFIED IDEOGRAPH:'C4A7:50343:藹 +CJK UNIFIED IDEOGRAPH:'C4A8:50344:蘑 +CJK UNIFIED IDEOGRAPH:'C4A9:50345:藺 +CJK UNIFIED IDEOGRAPH:'C4AA:50346:蘆 +CJK UNIFIED IDEOGRAPH:'C4AB:50347:蘋 +CJK UNIFIED IDEOGRAPH:'C4AC:50348:蘇 +CJK UNIFIED IDEOGRAPH:'C4AD:50349:蘊 +CJK UNIFIED IDEOGRAPH:'C4AE:50350:蠔 +CJK UNIFIED IDEOGRAPH:'C4AF:50351:蠕 +CJK UNIFIED IDEOGRAPH:'C4B0:50352:襤 +CJK UNIFIED IDEOGRAPH:'C4B1:50353:覺 +CJK UNIFIED IDEOGRAPH:'C4B2:50354:觸 +CJK UNIFIED IDEOGRAPH:'C4B3:50355:議 +CJK UNIFIED IDEOGRAPH:'C4B4:50356:譬 +CJK UNIFIED IDEOGRAPH:'C4B5:50357:警 +CJK UNIFIED IDEOGRAPH:'C4B6:50358:譯 +CJK UNIFIED IDEOGRAPH:'C4B7:50359:譟 +CJK UNIFIED IDEOGRAPH:'C4B8:50360:譫 +CJK UNIFIED IDEOGRAPH:'C4B9:50361:贏 +CJK UNIFIED IDEOGRAPH:'C4BA:50362:贍 +CJK UNIFIED IDEOGRAPH:'C4BB:50363:躉 +CJK UNIFIED IDEOGRAPH:'C4BC:50364:躁 +CJK UNIFIED IDEOGRAPH:'C4BD:50365:躅 +CJK UNIFIED IDEOGRAPH:'C4BE:50366:躂 +CJK UNIFIED IDEOGRAPH:'C4BF:50367:醴 +CJK UNIFIED IDEOGRAPH:'C4C0:50368:釋 +CJK UNIFIED IDEOGRAPH:'C4C1:50369:鐘 +CJK UNIFIED IDEOGRAPH:'C4C2:50370:鐃 +CJK UNIFIED IDEOGRAPH:'C4C3:50371:鏽 +CJK UNIFIED IDEOGRAPH:'C4C4:50372:闡 +CJK UNIFIED IDEOGRAPH:'C4C5:50373:霰 +CJK UNIFIED IDEOGRAPH:'C4C6:50374:飄 +CJK UNIFIED IDEOGRAPH:'C4C7:50375:饒 +CJK UNIFIED IDEOGRAPH:'C4C8:50376:饑 +CJK UNIFIED IDEOGRAPH:'C4C9:50377:馨 +CJK UNIFIED IDEOGRAPH:'C4CA:50378:騫 +CJK UNIFIED IDEOGRAPH:'C4CB:50379:騰 +CJK UNIFIED IDEOGRAPH:'C4CC:50380:騷 +CJK UNIFIED IDEOGRAPH:'C4CD:50381:騵 +CJK UNIFIED IDEOGRAPH:'C4CE:50382:鰓 +CJK UNIFIED IDEOGRAPH:'C4CF:50383:鰍 +CJK UNIFIED IDEOGRAPH:'C4D0:50384:鹹 +CJK UNIFIED IDEOGRAPH:'C4D1:50385:麵 +CJK UNIFIED IDEOGRAPH:'C4D2:50386:黨 +CJK UNIFIED IDEOGRAPH:'C4D3:50387:鼯 +CJK UNIFIED IDEOGRAPH:'C4D4:50388:齟 +CJK UNIFIED IDEOGRAPH:'C4D5:50389:齣 +CJK UNIFIED IDEOGRAPH:'C4D6:50390:齡 +CJK UNIFIED IDEOGRAPH:'C4D7:50391:儷 +CJK UNIFIED IDEOGRAPH:'C4D8:50392:儸 +CJK UNIFIED IDEOGRAPH:'C4D9:50393:囁 +CJK UNIFIED IDEOGRAPH:'C4DA:50394:囀 +CJK UNIFIED IDEOGRAPH:'C4DB:50395:囂 +CJK UNIFIED IDEOGRAPH:'C4DC:50396:夔 +CJK UNIFIED IDEOGRAPH:'C4DD:50397:屬 +CJK UNIFIED IDEOGRAPH:'C4DE:50398:巍 +CJK UNIFIED IDEOGRAPH:'C4DF:50399:懼 +CJK UNIFIED IDEOGRAPH:'C4E0:50400:懾 +CJK UNIFIED IDEOGRAPH:'C4E1:50401:攝 +CJK UNIFIED IDEOGRAPH:'C4E2:50402:攜 +CJK UNIFIED IDEOGRAPH:'C4E3:50403:斕 +CJK UNIFIED IDEOGRAPH:'C4E4:50404:曩 +CJK UNIFIED IDEOGRAPH:'C4E5:50405:櫻 +CJK UNIFIED IDEOGRAPH:'C4E6:50406:欄 +CJK UNIFIED IDEOGRAPH:'C4E7:50407:櫺 +CJK UNIFIED IDEOGRAPH:'C4E8:50408:殲 +CJK UNIFIED IDEOGRAPH:'C4E9:50409:灌 +CJK UNIFIED IDEOGRAPH:'C4EA:50410:爛 +CJK UNIFIED IDEOGRAPH:'C4EB:50411:犧 +CJK UNIFIED IDEOGRAPH:'C4EC:50412:瓖 +CJK UNIFIED IDEOGRAPH:'C4ED:50413:瓔 +CJK UNIFIED IDEOGRAPH:'C4EE:50414:癩 +CJK UNIFIED IDEOGRAPH:'C4EF:50415:矓 +CJK UNIFIED IDEOGRAPH:'C4F0:50416:籐 +CJK UNIFIED IDEOGRAPH:'C4F1:50417:纏 +CJK UNIFIED IDEOGRAPH:'C4F2:50418:續 +CJK UNIFIED IDEOGRAPH:'C4F3:50419:羼 +CJK UNIFIED IDEOGRAPH:'C4F4:50420:蘗 +CJK UNIFIED IDEOGRAPH:'C4F5:50421:蘭 +CJK UNIFIED IDEOGRAPH:'C4F6:50422:蘚 +CJK UNIFIED IDEOGRAPH:'C4F7:50423:蠣 +CJK UNIFIED IDEOGRAPH:'C4F8:50424:蠢 +CJK UNIFIED IDEOGRAPH:'C4F9:50425:蠡 +CJK UNIFIED IDEOGRAPH:'C4FA:50426:蠟 +CJK UNIFIED IDEOGRAPH:'C4FB:50427:襪 +CJK UNIFIED IDEOGRAPH:'C4FC:50428:襬 +CJK UNIFIED IDEOGRAPH:'C4FD:50429:覽 +CJK UNIFIED IDEOGRAPH:'C4FE:50430:譴 +CJK UNIFIED IDEOGRAPH:'C540:50496:護 +CJK UNIFIED IDEOGRAPH:'C541:50497:譽 +CJK UNIFIED IDEOGRAPH:'C542:50498:贓 +CJK UNIFIED IDEOGRAPH:'C543:50499:躊 +CJK UNIFIED IDEOGRAPH:'C544:50500:躍 +CJK UNIFIED IDEOGRAPH:'C545:50501:躋 +CJK UNIFIED IDEOGRAPH:'C546:50502:轟 +CJK UNIFIED IDEOGRAPH:'C547:50503:辯 +CJK UNIFIED IDEOGRAPH:'C548:50504:醺 +CJK UNIFIED IDEOGRAPH:'C549:50505:鐮 +CJK UNIFIED IDEOGRAPH:'C54A:50506:鐳 +CJK UNIFIED IDEOGRAPH:'C54B:50507:鐵 +CJK UNIFIED IDEOGRAPH:'C54C:50508:鐺 +CJK UNIFIED IDEOGRAPH:'C54D:50509:鐸 +CJK UNIFIED IDEOGRAPH:'C54E:50510:鐲 +CJK UNIFIED IDEOGRAPH:'C54F:50511:鐫 +CJK UNIFIED IDEOGRAPH:'C550:50512:闢 +CJK UNIFIED IDEOGRAPH:'C551:50513:霸 +CJK UNIFIED IDEOGRAPH:'C552:50514:霹 +CJK UNIFIED IDEOGRAPH:'C553:50515:露 +CJK UNIFIED IDEOGRAPH:'C554:50516:響 +CJK UNIFIED IDEOGRAPH:'C555:50517:顧 +CJK UNIFIED IDEOGRAPH:'C556:50518:顥 +CJK UNIFIED IDEOGRAPH:'C557:50519:饗 +CJK UNIFIED IDEOGRAPH:'C558:50520:驅 +CJK UNIFIED IDEOGRAPH:'C559:50521:驃 +CJK UNIFIED IDEOGRAPH:'C55A:50522:驀 +CJK UNIFIED IDEOGRAPH:'C55B:50523:騾 +CJK UNIFIED IDEOGRAPH:'C55C:50524:髏 +CJK UNIFIED IDEOGRAPH:'C55D:50525:魔 +CJK UNIFIED IDEOGRAPH:'C55E:50526:魑 +CJK UNIFIED IDEOGRAPH:'C55F:50527:鰭 +CJK UNIFIED IDEOGRAPH:'C560:50528:鰥 +CJK UNIFIED IDEOGRAPH:'C561:50529:鶯 +CJK UNIFIED IDEOGRAPH:'C562:50530:鶴 +CJK UNIFIED IDEOGRAPH:'C563:50531:鷂 +CJK UNIFIED IDEOGRAPH:'C564:50532:鶸 +CJK UNIFIED IDEOGRAPH:'C565:50533:麝 +CJK UNIFIED IDEOGRAPH:'C566:50534:黯 +CJK UNIFIED IDEOGRAPH:'C567:50535:鼙 +CJK UNIFIED IDEOGRAPH:'C568:50536:齜 +CJK UNIFIED IDEOGRAPH:'C569:50537:齦 +CJK UNIFIED IDEOGRAPH:'C56A:50538:齧 +CJK UNIFIED IDEOGRAPH:'C56B:50539:儼 +CJK UNIFIED IDEOGRAPH:'C56C:50540:儻 +CJK UNIFIED IDEOGRAPH:'C56D:50541:囈 +CJK UNIFIED IDEOGRAPH:'C56E:50542:囊 +CJK UNIFIED IDEOGRAPH:'C56F:50543:囉 +CJK UNIFIED IDEOGRAPH:'C570:50544:孿 +CJK UNIFIED IDEOGRAPH:'C571:50545:巔 +CJK UNIFIED IDEOGRAPH:'C572:50546:巒 +CJK UNIFIED IDEOGRAPH:'C573:50547:彎 +CJK UNIFIED IDEOGRAPH:'C574:50548:懿 +CJK UNIFIED IDEOGRAPH:'C575:50549:攤 +CJK UNIFIED IDEOGRAPH:'C576:50550:權 +CJK UNIFIED IDEOGRAPH:'C577:50551:歡 +CJK UNIFIED IDEOGRAPH:'C578:50552:灑 +CJK UNIFIED IDEOGRAPH:'C579:50553:灘 +CJK UNIFIED IDEOGRAPH:'C57A:50554:玀 +CJK UNIFIED IDEOGRAPH:'C57B:50555:瓤 +CJK UNIFIED IDEOGRAPH:'C57C:50556:疊 +CJK UNIFIED IDEOGRAPH:'C57D:50557:癮 +CJK UNIFIED IDEOGRAPH:'C57E:50558:癬 +CJK UNIFIED IDEOGRAPH:'C5A1:50593:禳 +CJK UNIFIED IDEOGRAPH:'C5A2:50594:籠 +CJK UNIFIED IDEOGRAPH:'C5A3:50595:籟 +CJK UNIFIED IDEOGRAPH:'C5A4:50596:聾 +CJK UNIFIED IDEOGRAPH:'C5A5:50597:聽 +CJK UNIFIED IDEOGRAPH:'C5A6:50598:臟 +CJK UNIFIED IDEOGRAPH:'C5A7:50599:襲 +CJK UNIFIED IDEOGRAPH:'C5A8:50600:襯 +CJK UNIFIED IDEOGRAPH:'C5A9:50601:觼 +CJK UNIFIED IDEOGRAPH:'C5AA:50602:讀 +CJK UNIFIED IDEOGRAPH:'C5AB:50603:贖 +CJK UNIFIED IDEOGRAPH:'C5AC:50604:贗 +CJK UNIFIED IDEOGRAPH:'C5AD:50605:躑 +CJK UNIFIED IDEOGRAPH:'C5AE:50606:躓 +CJK UNIFIED IDEOGRAPH:'C5AF:50607:轡 +CJK UNIFIED IDEOGRAPH:'C5B0:50608:酈 +CJK UNIFIED IDEOGRAPH:'C5B1:50609:鑄 +CJK UNIFIED IDEOGRAPH:'C5B2:50610:鑑 +CJK UNIFIED IDEOGRAPH:'C5B3:50611:鑒 +CJK UNIFIED IDEOGRAPH:'C5B4:50612:霽 +CJK UNIFIED IDEOGRAPH:'C5B5:50613:霾 +CJK UNIFIED IDEOGRAPH:'C5B6:50614:韃 +CJK UNIFIED IDEOGRAPH:'C5B7:50615:韁 +CJK UNIFIED IDEOGRAPH:'C5B8:50616:顫 +CJK UNIFIED IDEOGRAPH:'C5B9:50617:饕 +CJK UNIFIED IDEOGRAPH:'C5BA:50618:驕 +CJK UNIFIED IDEOGRAPH:'C5BB:50619:驍 +CJK UNIFIED IDEOGRAPH:'C5BC:50620:髒 +CJK UNIFIED IDEOGRAPH:'C5BD:50621:鬚 +CJK UNIFIED IDEOGRAPH:'C5BE:50622:鱉 +CJK UNIFIED IDEOGRAPH:'C5BF:50623:鰱 +CJK UNIFIED IDEOGRAPH:'C5C0:50624:鰾 +CJK UNIFIED IDEOGRAPH:'C5C1:50625:鰻 +CJK UNIFIED IDEOGRAPH:'C5C2:50626:鷓 +CJK UNIFIED IDEOGRAPH:'C5C3:50627:鷗 +CJK UNIFIED IDEOGRAPH:'C5C4:50628:鼴 +CJK UNIFIED IDEOGRAPH:'C5C5:50629:齬 +CJK UNIFIED IDEOGRAPH:'C5C6:50630:齪 +CJK UNIFIED IDEOGRAPH:'C5C7:50631:龔 +CJK UNIFIED IDEOGRAPH:'C5C8:50632:囌 +CJK UNIFIED IDEOGRAPH:'C5C9:50633:巖 +CJK UNIFIED IDEOGRAPH:'C5CA:50634:戀 +CJK UNIFIED IDEOGRAPH:'C5CB:50635:攣 +CJK UNIFIED IDEOGRAPH:'C5CC:50636:攫 +CJK UNIFIED IDEOGRAPH:'C5CD:50637:攪 +CJK UNIFIED IDEOGRAPH:'C5CE:50638:曬 +CJK UNIFIED IDEOGRAPH:'C5CF:50639:欐 +CJK UNIFIED IDEOGRAPH:'C5D0:50640:瓚 +CJK UNIFIED IDEOGRAPH:'C5D1:50641:竊 +CJK UNIFIED IDEOGRAPH:'C5D2:50642:籤 +CJK UNIFIED IDEOGRAPH:'C5D3:50643:籣 +CJK UNIFIED IDEOGRAPH:'C5D4:50644:籥 +CJK UNIFIED IDEOGRAPH:'C5D5:50645:纓 +CJK UNIFIED IDEOGRAPH:'C5D6:50646:纖 +CJK UNIFIED IDEOGRAPH:'C5D7:50647:纔 +CJK UNIFIED IDEOGRAPH:'C5D8:50648:臢 +CJK UNIFIED IDEOGRAPH:'C5D9:50649:蘸 +CJK UNIFIED IDEOGRAPH:'C5DA:50650:蘿 +CJK UNIFIED IDEOGRAPH:'C5DB:50651:蠱 +CJK UNIFIED IDEOGRAPH:'C5DC:50652:變 +CJK UNIFIED IDEOGRAPH:'C5DD:50653:邐 +CJK UNIFIED IDEOGRAPH:'C5DE:50654:邏 +CJK UNIFIED IDEOGRAPH:'C5DF:50655:鑣 +CJK UNIFIED IDEOGRAPH:'C5E0:50656:鑠 +CJK UNIFIED IDEOGRAPH:'C5E1:50657:鑤 +CJK UNIFIED IDEOGRAPH:'C5E2:50658:靨 +CJK UNIFIED IDEOGRAPH:'C5E3:50659:顯 +CJK UNIFIED IDEOGRAPH:'C5E4:50660:饜 +CJK UNIFIED IDEOGRAPH:'C5E5:50661:驚 +CJK UNIFIED IDEOGRAPH:'C5E6:50662:驛 +CJK UNIFIED IDEOGRAPH:'C5E7:50663:驗 +CJK UNIFIED IDEOGRAPH:'C5E8:50664:髓 +CJK UNIFIED IDEOGRAPH:'C5E9:50665:體 +CJK UNIFIED IDEOGRAPH:'C5EA:50666:髑 +CJK UNIFIED IDEOGRAPH:'C5EB:50667:鱔 +CJK UNIFIED IDEOGRAPH:'C5EC:50668:鱗 +CJK UNIFIED IDEOGRAPH:'C5ED:50669:鱖 +CJK UNIFIED IDEOGRAPH:'C5EE:50670:鷥 +CJK UNIFIED IDEOGRAPH:'C5EF:50671:麟 +CJK UNIFIED IDEOGRAPH:'C5F0:50672:黴 +CJK UNIFIED IDEOGRAPH:'C5F1:50673:囑 +CJK UNIFIED IDEOGRAPH:'C5F2:50674:壩 +CJK UNIFIED IDEOGRAPH:'C5F3:50675:攬 +CJK UNIFIED IDEOGRAPH:'C5F4:50676:灞 +CJK UNIFIED IDEOGRAPH:'C5F5:50677:癱 +CJK UNIFIED IDEOGRAPH:'C5F6:50678:癲 +CJK UNIFIED IDEOGRAPH:'C5F7:50679:矗 +CJK UNIFIED IDEOGRAPH:'C5F8:50680:罐 +CJK UNIFIED IDEOGRAPH:'C5F9:50681:羈 +CJK UNIFIED IDEOGRAPH:'C5FA:50682:蠶 +CJK UNIFIED IDEOGRAPH:'C5FB:50683:蠹 +CJK UNIFIED IDEOGRAPH:'C5FC:50684:衢 +CJK UNIFIED IDEOGRAPH:'C5FD:50685:讓 +CJK UNIFIED IDEOGRAPH:'C5FE:50686:讒 +CJK UNIFIED IDEOGRAPH:'C640:50752:讖 +CJK UNIFIED IDEOGRAPH:'C641:50753:艷 +CJK UNIFIED IDEOGRAPH:'C642:50754:贛 +CJK UNIFIED IDEOGRAPH:'C643:50755:釀 +CJK UNIFIED IDEOGRAPH:'C644:50756:鑪 +CJK UNIFIED IDEOGRAPH:'C645:50757:靂 +CJK UNIFIED IDEOGRAPH:'C646:50758:靈 +CJK UNIFIED IDEOGRAPH:'C647:50759:靄 +CJK UNIFIED IDEOGRAPH:'C648:50760:韆 +CJK UNIFIED IDEOGRAPH:'C649:50761:顰 +CJK UNIFIED IDEOGRAPH:'C64A:50762:驟 +CJK UNIFIED IDEOGRAPH:'C64B:50763:鬢 +CJK UNIFIED IDEOGRAPH:'C64C:50764:魘 +CJK UNIFIED IDEOGRAPH:'C64D:50765:鱟 +CJK UNIFIED IDEOGRAPH:'C64E:50766:鷹 +CJK UNIFIED IDEOGRAPH:'C64F:50767:鷺 +CJK UNIFIED IDEOGRAPH:'C650:50768:鹼 +CJK UNIFIED IDEOGRAPH:'C651:50769:鹽 +CJK UNIFIED IDEOGRAPH:'C652:50770:鼇 +CJK UNIFIED IDEOGRAPH:'C653:50771:齷 +CJK UNIFIED IDEOGRAPH:'C654:50772:齲 +CJK UNIFIED IDEOGRAPH:'C655:50773:廳 +CJK UNIFIED IDEOGRAPH:'C656:50774:欖 +CJK UNIFIED IDEOGRAPH:'C657:50775:灣 +CJK UNIFIED IDEOGRAPH:'C658:50776:籬 +CJK UNIFIED IDEOGRAPH:'C659:50777:籮 +CJK UNIFIED IDEOGRAPH:'C65A:50778:蠻 +CJK UNIFIED IDEOGRAPH:'C65B:50779:觀 +CJK UNIFIED IDEOGRAPH:'C65C:50780:躡 +CJK UNIFIED IDEOGRAPH:'C65D:50781:釁 +CJK UNIFIED IDEOGRAPH:'C65E:50782:鑲 +CJK UNIFIED IDEOGRAPH:'C65F:50783:鑰 +CJK UNIFIED IDEOGRAPH:'C660:50784:顱 +CJK UNIFIED IDEOGRAPH:'C661:50785:饞 +CJK UNIFIED IDEOGRAPH:'C662:50786:髖 +CJK UNIFIED IDEOGRAPH:'C663:50787:鬣 +CJK UNIFIED IDEOGRAPH:'C664:50788:黌 +CJK UNIFIED IDEOGRAPH:'C665:50789:灤 +CJK UNIFIED IDEOGRAPH:'C666:50790:矚 +CJK UNIFIED IDEOGRAPH:'C667:50791:讚 +CJK UNIFIED IDEOGRAPH:'C668:50792:鑷 +CJK UNIFIED IDEOGRAPH:'C669:50793:韉 +CJK UNIFIED IDEOGRAPH:'C66A:50794:驢 +CJK UNIFIED IDEOGRAPH:'C66B:50795:驥 +CJK UNIFIED IDEOGRAPH:'C66C:50796:纜 +CJK UNIFIED IDEOGRAPH:'C66D:50797:讜 +CJK UNIFIED IDEOGRAPH:'C66E:50798:躪 +CJK UNIFIED IDEOGRAPH:'C66F:50799:釅 +CJK UNIFIED IDEOGRAPH:'C670:50800:鑽 +CJK UNIFIED IDEOGRAPH:'C671:50801:鑾 +CJK UNIFIED IDEOGRAPH:'C672:50802:鑼 +CJK UNIFIED IDEOGRAPH:'C673:50803:鱷 +CJK UNIFIED IDEOGRAPH:'C674:50804:鱸 +CJK UNIFIED IDEOGRAPH:'C675:50805:黷 +CJK UNIFIED IDEOGRAPH:'C676:50806:豔 +CJK UNIFIED IDEOGRAPH:'C677:50807:鑿 +CJK UNIFIED IDEOGRAPH:'C678:50808:鸚 +CJK UNIFIED IDEOGRAPH:'C679:50809:爨 +CJK UNIFIED IDEOGRAPH:'C67A:50810:驪 +CJK UNIFIED IDEOGRAPH:'C67B:50811:鬱 +CJK UNIFIED IDEOGRAPH:'C67C:50812:鸛 +CJK UNIFIED IDEOGRAPH:'C67D:50813:鸞 +CJK UNIFIED IDEOGRAPH:'C67E:50814:籲 +CJK UNIFIED IDEOGRAPH:'C940:51520:乂 +CJK UNIFIED IDEOGRAPH:'C941:51521:乜 +CJK UNIFIED IDEOGRAPH:'C942:51522:凵 +CJK UNIFIED IDEOGRAPH:'C943:51523:匚 +CJK UNIFIED IDEOGRAPH:'C944:51524:厂 +CJK UNIFIED IDEOGRAPH:'C945:51525:万 +CJK UNIFIED IDEOGRAPH:'C946:51526:丌 +CJK UNIFIED IDEOGRAPH:'C947:51527:乇 +CJK UNIFIED IDEOGRAPH:'C948:51528:亍 +CJK UNIFIED IDEOGRAPH:'C949:51529:囗 +CJK COMPATIBILITY IDEOGRAPH:'C94A:51530:兀 +CJK UNIFIED IDEOGRAPH:'C94B:51531:屮 +CJK UNIFIED IDEOGRAPH:'C94C:51532:彳 +CJK UNIFIED IDEOGRAPH:'C94D:51533:丏 +CJK UNIFIED IDEOGRAPH:'C94E:51534:冇 +CJK UNIFIED IDEOGRAPH:'C94F:51535:与 +CJK UNIFIED IDEOGRAPH:'C950:51536:丮 +CJK UNIFIED IDEOGRAPH:'C951:51537:亓 +CJK UNIFIED IDEOGRAPH:'C952:51538:仂 +CJK UNIFIED IDEOGRAPH:'C953:51539:仉 +CJK UNIFIED IDEOGRAPH:'C954:51540:仈 +CJK UNIFIED IDEOGRAPH:'C955:51541:冘 +CJK UNIFIED IDEOGRAPH:'C956:51542:勼 +CJK UNIFIED IDEOGRAPH:'C957:51543:卬 +CJK UNIFIED IDEOGRAPH:'C958:51544:厹 +CJK UNIFIED IDEOGRAPH:'C959:51545:圠 +CJK UNIFIED IDEOGRAPH:'C95A:51546:夃 +CJK UNIFIED IDEOGRAPH:'C95B:51547:夬 +CJK UNIFIED IDEOGRAPH:'C95C:51548:尐 +CJK UNIFIED IDEOGRAPH:'C95D:51549:巿 +CJK UNIFIED IDEOGRAPH:'C95E:51550:旡 +CJK UNIFIED IDEOGRAPH:'C95F:51551:殳 +CJK UNIFIED IDEOGRAPH:'C960:51552:毌 +CJK UNIFIED IDEOGRAPH:'C961:51553:气 +CJK UNIFIED IDEOGRAPH:'C962:51554:爿 +CJK UNIFIED IDEOGRAPH:'C963:51555:丱 +CJK UNIFIED IDEOGRAPH:'C964:51556:丼 +CJK UNIFIED IDEOGRAPH:'C965:51557:仨 +CJK UNIFIED IDEOGRAPH:'C966:51558:仜 +CJK UNIFIED IDEOGRAPH:'C967:51559:仩 +CJK UNIFIED IDEOGRAPH:'C968:51560:仡 +CJK UNIFIED IDEOGRAPH:'C969:51561:仝 +CJK UNIFIED IDEOGRAPH:'C96A:51562:仚 +CJK UNIFIED IDEOGRAPH:'C96B:51563:刌 +CJK UNIFIED IDEOGRAPH:'C96C:51564:匜 +CJK UNIFIED IDEOGRAPH:'C96D:51565:卌 +CJK UNIFIED IDEOGRAPH:'C96E:51566:圢 +CJK UNIFIED IDEOGRAPH:'C96F:51567:圣 +CJK UNIFIED IDEOGRAPH:'C970:51568:夗 +CJK UNIFIED IDEOGRAPH:'C971:51569:夯 +CJK UNIFIED IDEOGRAPH:'C972:51570:宁 +CJK UNIFIED IDEOGRAPH:'C973:51571:宄 +CJK UNIFIED IDEOGRAPH:'C974:51572:尒 +CJK UNIFIED IDEOGRAPH:'C975:51573:尻 +CJK UNIFIED IDEOGRAPH:'C976:51574:屴 +CJK UNIFIED IDEOGRAPH:'C977:51575:屳 +CJK UNIFIED IDEOGRAPH:'C978:51576:帄 +CJK UNIFIED IDEOGRAPH:'C979:51577:庀 +CJK UNIFIED IDEOGRAPH:'C97A:51578:庂 +CJK UNIFIED IDEOGRAPH:'C97B:51579:忉 +CJK UNIFIED IDEOGRAPH:'C97C:51580:戉 +CJK UNIFIED IDEOGRAPH:'C97D:51581:扐 +CJK UNIFIED IDEOGRAPH:'C97E:51582:氕 +CJK UNIFIED IDEOGRAPH:'C9A1:51617:氶 +CJK UNIFIED IDEOGRAPH:'C9A2:51618:汃 +CJK UNIFIED IDEOGRAPH:'C9A3:51619:氿 +CJK UNIFIED IDEOGRAPH:'C9A4:51620:氻 +CJK UNIFIED IDEOGRAPH:'C9A5:51621:犮 +CJK UNIFIED IDEOGRAPH:'C9A6:51622:犰 +CJK UNIFIED IDEOGRAPH:'C9A7:51623:玊 +CJK UNIFIED IDEOGRAPH:'C9A8:51624:禸 +CJK UNIFIED IDEOGRAPH:'C9A9:51625:肊 +CJK UNIFIED IDEOGRAPH:'C9AA:51626:阞 +CJK UNIFIED IDEOGRAPH:'C9AB:51627:伎 +CJK UNIFIED IDEOGRAPH:'C9AC:51628:优 +CJK UNIFIED IDEOGRAPH:'C9AD:51629:伬 +CJK UNIFIED IDEOGRAPH:'C9AE:51630:仵 +CJK UNIFIED IDEOGRAPH:'C9AF:51631:伔 +CJK UNIFIED IDEOGRAPH:'C9B0:51632:仱 +CJK UNIFIED IDEOGRAPH:'C9B1:51633:伀 +CJK UNIFIED IDEOGRAPH:'C9B2:51634:价 +CJK UNIFIED IDEOGRAPH:'C9B3:51635:伈 +CJK UNIFIED IDEOGRAPH:'C9B4:51636:伝 +CJK UNIFIED IDEOGRAPH:'C9B5:51637:伂 +CJK UNIFIED IDEOGRAPH:'C9B6:51638:伅 +CJK UNIFIED IDEOGRAPH:'C9B7:51639:伢 +CJK UNIFIED IDEOGRAPH:'C9B8:51640:伓 +CJK UNIFIED IDEOGRAPH:'C9B9:51641:伄 +CJK UNIFIED IDEOGRAPH:'C9BA:51642:仴 +CJK UNIFIED IDEOGRAPH:'C9BB:51643:伒 +CJK UNIFIED IDEOGRAPH:'C9BC:51644:冱 +CJK UNIFIED IDEOGRAPH:'C9BD:51645:刓 +CJK UNIFIED IDEOGRAPH:'C9BE:51646:刉 +CJK UNIFIED IDEOGRAPH:'C9BF:51647:刐 +CJK UNIFIED IDEOGRAPH:'C9C0:51648:劦 +CJK UNIFIED IDEOGRAPH:'C9C1:51649:匢 +CJK UNIFIED IDEOGRAPH:'C9C2:51650:匟 +CJK UNIFIED IDEOGRAPH:'C9C3:51651:卍 +CJK UNIFIED IDEOGRAPH:'C9C4:51652:厊 +CJK UNIFIED IDEOGRAPH:'C9C5:51653:吇 +CJK UNIFIED IDEOGRAPH:'C9C6:51654:囡 +CJK UNIFIED IDEOGRAPH:'C9C7:51655:囟 +CJK UNIFIED IDEOGRAPH:'C9C8:51656:圮 +CJK UNIFIED IDEOGRAPH:'C9C9:51657:圪 +CJK UNIFIED IDEOGRAPH:'C9CA:51658:圴 +CJK UNIFIED IDEOGRAPH:'C9CB:51659:夼 +CJK UNIFIED IDEOGRAPH:'C9CC:51660:妀 +CJK UNIFIED IDEOGRAPH:'C9CD:51661:奼 +CJK UNIFIED IDEOGRAPH:'C9CE:51662:妅 +CJK UNIFIED IDEOGRAPH:'C9CF:51663:奻 +CJK UNIFIED IDEOGRAPH:'C9D0:51664:奾 +CJK UNIFIED IDEOGRAPH:'C9D1:51665:奷 +CJK UNIFIED IDEOGRAPH:'C9D2:51666:奿 +CJK UNIFIED IDEOGRAPH:'C9D3:51667:孖 +CJK UNIFIED IDEOGRAPH:'C9D4:51668:尕 +CJK UNIFIED IDEOGRAPH:'C9D5:51669:尥 +CJK UNIFIED IDEOGRAPH:'C9D6:51670:屼 +CJK UNIFIED IDEOGRAPH:'C9D7:51671:屺 +CJK UNIFIED IDEOGRAPH:'C9D8:51672:屻 +CJK UNIFIED IDEOGRAPH:'C9D9:51673:屾 +CJK UNIFIED IDEOGRAPH:'C9DA:51674:巟 +CJK UNIFIED IDEOGRAPH:'C9DB:51675:幵 +CJK UNIFIED IDEOGRAPH:'C9DC:51676:庄 +CJK UNIFIED IDEOGRAPH:'C9DD:51677:异 +CJK UNIFIED IDEOGRAPH:'C9DE:51678:弚 +CJK UNIFIED IDEOGRAPH:'C9DF:51679:彴 +CJK UNIFIED IDEOGRAPH:'C9E0:51680:忕 +CJK UNIFIED IDEOGRAPH:'C9E1:51681:忔 +CJK UNIFIED IDEOGRAPH:'C9E2:51682:忏 +CJK UNIFIED IDEOGRAPH:'C9E3:51683:扜 +CJK UNIFIED IDEOGRAPH:'C9E4:51684:扞 +CJK UNIFIED IDEOGRAPH:'C9E5:51685:扤 +CJK UNIFIED IDEOGRAPH:'C9E6:51686:扡 +CJK UNIFIED IDEOGRAPH:'C9E7:51687:扦 +CJK UNIFIED IDEOGRAPH:'C9E8:51688:扢 +CJK UNIFIED IDEOGRAPH:'C9E9:51689:扙 +CJK UNIFIED IDEOGRAPH:'C9EA:51690:扠 +CJK UNIFIED IDEOGRAPH:'C9EB:51691:扚 +CJK UNIFIED IDEOGRAPH:'C9EC:51692:扥 +CJK UNIFIED IDEOGRAPH:'C9ED:51693:旯 +CJK UNIFIED IDEOGRAPH:'C9EE:51694:旮 +CJK UNIFIED IDEOGRAPH:'C9EF:51695:朾 +CJK UNIFIED IDEOGRAPH:'C9F0:51696:朹 +CJK UNIFIED IDEOGRAPH:'C9F1:51697:朸 +CJK UNIFIED IDEOGRAPH:'C9F2:51698:朻 +CJK UNIFIED IDEOGRAPH:'C9F3:51699:机 +CJK UNIFIED IDEOGRAPH:'C9F4:51700:朿 +CJK UNIFIED IDEOGRAPH:'C9F5:51701:朼 +CJK UNIFIED IDEOGRAPH:'C9F6:51702:朳 +CJK UNIFIED IDEOGRAPH:'C9F7:51703:氘 +CJK UNIFIED IDEOGRAPH:'C9F8:51704:汆 +CJK UNIFIED IDEOGRAPH:'C9F9:51705:汒 +CJK UNIFIED IDEOGRAPH:'C9FA:51706:汜 +CJK UNIFIED IDEOGRAPH:'C9FB:51707:汏 +CJK UNIFIED IDEOGRAPH:'C9FC:51708:汊 +CJK UNIFIED IDEOGRAPH:'C9FD:51709:汔 +CJK UNIFIED IDEOGRAPH:'C9FE:51710:汋 +CJK UNIFIED IDEOGRAPH:'CA40:51776:汌 +CJK UNIFIED IDEOGRAPH:'CA41:51777:灱 +CJK UNIFIED IDEOGRAPH:'CA42:51778:牞 +CJK UNIFIED IDEOGRAPH:'CA43:51779:犴 +CJK UNIFIED IDEOGRAPH:'CA44:51780:犵 +CJK UNIFIED IDEOGRAPH:'CA45:51781:玎 +CJK UNIFIED IDEOGRAPH:'CA46:51782:甪 +CJK UNIFIED IDEOGRAPH:'CA47:51783:癿 +CJK UNIFIED IDEOGRAPH:'CA48:51784:穵 +CJK UNIFIED IDEOGRAPH:'CA49:51785:网 +CJK UNIFIED IDEOGRAPH:'CA4A:51786:艸 +CJK UNIFIED IDEOGRAPH:'CA4B:51787:艼 +CJK UNIFIED IDEOGRAPH:'CA4C:51788:芀 +CJK UNIFIED IDEOGRAPH:'CA4D:51789:艽 +CJK UNIFIED IDEOGRAPH:'CA4E:51790:艿 +CJK UNIFIED IDEOGRAPH:'CA4F:51791:虍 +CJK UNIFIED IDEOGRAPH:'CA50:51792:襾 +CJK UNIFIED IDEOGRAPH:'CA51:51793:邙 +CJK UNIFIED IDEOGRAPH:'CA52:51794:邗 +CJK UNIFIED IDEOGRAPH:'CA53:51795:邘 +CJK UNIFIED IDEOGRAPH:'CA54:51796:邛 +CJK UNIFIED IDEOGRAPH:'CA55:51797:邔 +CJK UNIFIED IDEOGRAPH:'CA56:51798:阢 +CJK UNIFIED IDEOGRAPH:'CA57:51799:阤 +CJK UNIFIED IDEOGRAPH:'CA58:51800:阠 +CJK UNIFIED IDEOGRAPH:'CA59:51801:阣 +CJK UNIFIED IDEOGRAPH:'CA5A:51802:佖 +CJK UNIFIED IDEOGRAPH:'CA5B:51803:伻 +CJK UNIFIED IDEOGRAPH:'CA5C:51804:佢 +CJK UNIFIED IDEOGRAPH:'CA5D:51805:佉 +CJK UNIFIED IDEOGRAPH:'CA5E:51806:体 +CJK UNIFIED IDEOGRAPH:'CA5F:51807:佤 +CJK UNIFIED IDEOGRAPH:'CA60:51808:伾 +CJK UNIFIED IDEOGRAPH:'CA61:51809:佧 +CJK UNIFIED IDEOGRAPH:'CA62:51810:佒 +CJK UNIFIED IDEOGRAPH:'CA63:51811:佟 +CJK UNIFIED IDEOGRAPH:'CA64:51812:佁 +CJK UNIFIED IDEOGRAPH:'CA65:51813:佘 +CJK UNIFIED IDEOGRAPH:'CA66:51814:伭 +CJK UNIFIED IDEOGRAPH:'CA67:51815:伳 +CJK UNIFIED IDEOGRAPH:'CA68:51816:伿 +CJK UNIFIED IDEOGRAPH:'CA69:51817:佡 +CJK UNIFIED IDEOGRAPH:'CA6A:51818:冏 +CJK UNIFIED IDEOGRAPH:'CA6B:51819:冹 +CJK UNIFIED IDEOGRAPH:'CA6C:51820:刜 +CJK UNIFIED IDEOGRAPH:'CA6D:51821:刞 +CJK UNIFIED IDEOGRAPH:'CA6E:51822:刡 +CJK UNIFIED IDEOGRAPH:'CA6F:51823:劭 +CJK UNIFIED IDEOGRAPH:'CA70:51824:劮 +CJK UNIFIED IDEOGRAPH:'CA71:51825:匉 +CJK UNIFIED IDEOGRAPH:'CA72:51826:卣 +CJK UNIFIED IDEOGRAPH:'CA73:51827:卲 +CJK UNIFIED IDEOGRAPH:'CA74:51828:厎 +CJK UNIFIED IDEOGRAPH:'CA75:51829:厏 +CJK UNIFIED IDEOGRAPH:'CA76:51830:吰 +CJK UNIFIED IDEOGRAPH:'CA77:51831:吷 +CJK UNIFIED IDEOGRAPH:'CA78:51832:吪 +CJK UNIFIED IDEOGRAPH:'CA79:51833:呔 +CJK UNIFIED IDEOGRAPH:'CA7A:51834:呅 +CJK UNIFIED IDEOGRAPH:'CA7B:51835:吙 +CJK UNIFIED IDEOGRAPH:'CA7C:51836:吜 +CJK UNIFIED IDEOGRAPH:'CA7D:51837:吥 +CJK UNIFIED IDEOGRAPH:'CA7E:51838:吘 +CJK UNIFIED IDEOGRAPH:'CAA1:51873:吽 +CJK UNIFIED IDEOGRAPH:'CAA2:51874:呏 +CJK UNIFIED IDEOGRAPH:'CAA3:51875:呁 +CJK UNIFIED IDEOGRAPH:'CAA4:51876:吨 +CJK UNIFIED IDEOGRAPH:'CAA5:51877:吤 +CJK UNIFIED IDEOGRAPH:'CAA6:51878:呇 +CJK UNIFIED IDEOGRAPH:'CAA7:51879:囮 +CJK UNIFIED IDEOGRAPH:'CAA8:51880:囧 +CJK UNIFIED IDEOGRAPH:'CAA9:51881:囥 +CJK UNIFIED IDEOGRAPH:'CAAA:51882:坁 +CJK UNIFIED IDEOGRAPH:'CAAB:51883:坅 +CJK UNIFIED IDEOGRAPH:'CAAC:51884:坌 +CJK UNIFIED IDEOGRAPH:'CAAD:51885:坉 +CJK UNIFIED IDEOGRAPH:'CAAE:51886:坋 +CJK UNIFIED IDEOGRAPH:'CAAF:51887:坒 +CJK UNIFIED IDEOGRAPH:'CAB0:51888:夆 +CJK UNIFIED IDEOGRAPH:'CAB1:51889:奀 +CJK UNIFIED IDEOGRAPH:'CAB2:51890:妦 +CJK UNIFIED IDEOGRAPH:'CAB3:51891:妘 +CJK UNIFIED IDEOGRAPH:'CAB4:51892:妠 +CJK UNIFIED IDEOGRAPH:'CAB5:51893:妗 +CJK UNIFIED IDEOGRAPH:'CAB6:51894:妎 +CJK UNIFIED IDEOGRAPH:'CAB7:51895:妢 +CJK UNIFIED IDEOGRAPH:'CAB8:51896:妐 +CJK UNIFIED IDEOGRAPH:'CAB9:51897:妏 +CJK UNIFIED IDEOGRAPH:'CABA:51898:妧 +CJK UNIFIED IDEOGRAPH:'CABB:51899:妡 +CJK UNIFIED IDEOGRAPH:'CABC:51900:宎 +CJK UNIFIED IDEOGRAPH:'CABD:51901:宒 +CJK UNIFIED IDEOGRAPH:'CABE:51902:尨 +CJK UNIFIED IDEOGRAPH:'CABF:51903:尪 +CJK UNIFIED IDEOGRAPH:'CAC0:51904:岍 +CJK UNIFIED IDEOGRAPH:'CAC1:51905:岏 +CJK UNIFIED IDEOGRAPH:'CAC2:51906:岈 +CJK UNIFIED IDEOGRAPH:'CAC3:51907:岋 +CJK UNIFIED IDEOGRAPH:'CAC4:51908:岉 +CJK UNIFIED IDEOGRAPH:'CAC5:51909:岒 +CJK UNIFIED IDEOGRAPH:'CAC6:51910:岊 +CJK UNIFIED IDEOGRAPH:'CAC7:51911:岆 +CJK UNIFIED IDEOGRAPH:'CAC8:51912:岓 +CJK UNIFIED IDEOGRAPH:'CAC9:51913:岕 +CJK UNIFIED IDEOGRAPH:'CACA:51914:巠 +CJK UNIFIED IDEOGRAPH:'CACB:51915:帊 +CJK UNIFIED IDEOGRAPH:'CACC:51916:帎 +CJK UNIFIED IDEOGRAPH:'CACD:51917:庋 +CJK UNIFIED IDEOGRAPH:'CACE:51918:庉 +CJK UNIFIED IDEOGRAPH:'CACF:51919:庌 +CJK UNIFIED IDEOGRAPH:'CAD0:51920:庈 +CJK UNIFIED IDEOGRAPH:'CAD1:51921:庍 +CJK UNIFIED IDEOGRAPH:'CAD2:51922:弅 +CJK UNIFIED IDEOGRAPH:'CAD3:51923:弝 +CJK UNIFIED IDEOGRAPH:'CAD4:51924:彸 +CJK UNIFIED IDEOGRAPH:'CAD5:51925:彶 +CJK UNIFIED IDEOGRAPH:'CAD6:51926:忒 +CJK UNIFIED IDEOGRAPH:'CAD7:51927:忑 +CJK UNIFIED IDEOGRAPH:'CAD8:51928:忐 +CJK UNIFIED IDEOGRAPH:'CAD9:51929:忭 +CJK UNIFIED IDEOGRAPH:'CADA:51930:忨 +CJK UNIFIED IDEOGRAPH:'CADB:51931:忮 +CJK UNIFIED IDEOGRAPH:'CADC:51932:忳 +CJK UNIFIED IDEOGRAPH:'CADD:51933:忡 +CJK UNIFIED IDEOGRAPH:'CADE:51934:忤 +CJK UNIFIED IDEOGRAPH:'CADF:51935:忣 +CJK UNIFIED IDEOGRAPH:'CAE0:51936:忺 +CJK UNIFIED IDEOGRAPH:'CAE1:51937:忯 +CJK UNIFIED IDEOGRAPH:'CAE2:51938:忷 +CJK UNIFIED IDEOGRAPH:'CAE3:51939:忻 +CJK UNIFIED IDEOGRAPH:'CAE4:51940:怀 +CJK UNIFIED IDEOGRAPH:'CAE5:51941:忴 +CJK UNIFIED IDEOGRAPH:'CAE6:51942:戺 +CJK UNIFIED IDEOGRAPH:'CAE7:51943:抃 +CJK UNIFIED IDEOGRAPH:'CAE8:51944:抌 +CJK UNIFIED IDEOGRAPH:'CAE9:51945:抎 +CJK UNIFIED IDEOGRAPH:'CAEA:51946:抏 +CJK UNIFIED IDEOGRAPH:'CAEB:51947:抔 +CJK UNIFIED IDEOGRAPH:'CAEC:51948:抇 +CJK UNIFIED IDEOGRAPH:'CAED:51949:扱 +CJK UNIFIED IDEOGRAPH:'CAEE:51950:扻 +CJK UNIFIED IDEOGRAPH:'CAEF:51951:扺 +CJK UNIFIED IDEOGRAPH:'CAF0:51952:扰 +CJK UNIFIED IDEOGRAPH:'CAF1:51953:抁 +CJK UNIFIED IDEOGRAPH:'CAF2:51954:抈 +CJK UNIFIED IDEOGRAPH:'CAF3:51955:扷 +CJK UNIFIED IDEOGRAPH:'CAF4:51956:扽 +CJK UNIFIED IDEOGRAPH:'CAF5:51957:扲 +CJK UNIFIED IDEOGRAPH:'CAF6:51958:扴 +CJK UNIFIED IDEOGRAPH:'CAF7:51959:攷 +CJK UNIFIED IDEOGRAPH:'CAF8:51960:旰 +CJK UNIFIED IDEOGRAPH:'CAF9:51961:旴 +CJK UNIFIED IDEOGRAPH:'CAFA:51962:旳 +CJK UNIFIED IDEOGRAPH:'CAFB:51963:旲 +CJK UNIFIED IDEOGRAPH:'CAFC:51964:旵 +CJK UNIFIED IDEOGRAPH:'CAFD:51965:杅 +CJK UNIFIED IDEOGRAPH:'CAFE:51966:杇 +CJK UNIFIED IDEOGRAPH:'CB40:52032:杙 +CJK UNIFIED IDEOGRAPH:'CB41:52033:杕 +CJK UNIFIED IDEOGRAPH:'CB42:52034:杌 +CJK UNIFIED IDEOGRAPH:'CB43:52035:杈 +CJK UNIFIED IDEOGRAPH:'CB44:52036:杝 +CJK UNIFIED IDEOGRAPH:'CB45:52037:杍 +CJK UNIFIED IDEOGRAPH:'CB46:52038:杚 +CJK UNIFIED IDEOGRAPH:'CB47:52039:杋 +CJK UNIFIED IDEOGRAPH:'CB48:52040:毐 +CJK UNIFIED IDEOGRAPH:'CB49:52041:氙 +CJK UNIFIED IDEOGRAPH:'CB4A:52042:氚 +CJK UNIFIED IDEOGRAPH:'CB4B:52043:汸 +CJK UNIFIED IDEOGRAPH:'CB4C:52044:汧 +CJK UNIFIED IDEOGRAPH:'CB4D:52045:汫 +CJK UNIFIED IDEOGRAPH:'CB4E:52046:沄 +CJK UNIFIED IDEOGRAPH:'CB4F:52047:沋 +CJK UNIFIED IDEOGRAPH:'CB50:52048:沏 +CJK UNIFIED IDEOGRAPH:'CB51:52049:汱 +CJK UNIFIED IDEOGRAPH:'CB52:52050:汯 +CJK UNIFIED IDEOGRAPH:'CB53:52051:汩 +CJK UNIFIED IDEOGRAPH:'CB54:52052:沚 +CJK UNIFIED IDEOGRAPH:'CB55:52053:汭 +CJK UNIFIED IDEOGRAPH:'CB56:52054:沇 +CJK UNIFIED IDEOGRAPH:'CB57:52055:沕 +CJK UNIFIED IDEOGRAPH:'CB58:52056:沜 +CJK UNIFIED IDEOGRAPH:'CB59:52057:汦 +CJK UNIFIED IDEOGRAPH:'CB5A:52058:汳 +CJK UNIFIED IDEOGRAPH:'CB5B:52059:汥 +CJK UNIFIED IDEOGRAPH:'CB5C:52060:汻 +CJK UNIFIED IDEOGRAPH:'CB5D:52061:沎 +CJK UNIFIED IDEOGRAPH:'CB5E:52062:灴 +CJK UNIFIED IDEOGRAPH:'CB5F:52063:灺 +CJK UNIFIED IDEOGRAPH:'CB60:52064:牣 +CJK UNIFIED IDEOGRAPH:'CB61:52065:犿 +CJK UNIFIED IDEOGRAPH:'CB62:52066:犽 +CJK UNIFIED IDEOGRAPH:'CB63:52067:狃 +CJK UNIFIED IDEOGRAPH:'CB64:52068:狆 +CJK UNIFIED IDEOGRAPH:'CB65:52069:狁 +CJK UNIFIED IDEOGRAPH:'CB66:52070:犺 +CJK UNIFIED IDEOGRAPH:'CB67:52071:狅 +CJK UNIFIED IDEOGRAPH:'CB68:52072:玕 +CJK UNIFIED IDEOGRAPH:'CB69:52073:玗 +CJK UNIFIED IDEOGRAPH:'CB6A:52074:玓 +CJK UNIFIED IDEOGRAPH:'CB6B:52075:玔 +CJK UNIFIED IDEOGRAPH:'CB6C:52076:玒 +CJK UNIFIED IDEOGRAPH:'CB6D:52077:町 +CJK UNIFIED IDEOGRAPH:'CB6E:52078:甹 +CJK UNIFIED IDEOGRAPH:'CB6F:52079:疔 +CJK UNIFIED IDEOGRAPH:'CB70:52080:疕 +CJK UNIFIED IDEOGRAPH:'CB71:52081:皁 +CJK UNIFIED IDEOGRAPH:'CB72:52082:礽 +CJK UNIFIED IDEOGRAPH:'CB73:52083:耴 +CJK UNIFIED IDEOGRAPH:'CB74:52084:肕 +CJK UNIFIED IDEOGRAPH:'CB75:52085:肙 +CJK UNIFIED IDEOGRAPH:'CB76:52086:肐 +CJK UNIFIED IDEOGRAPH:'CB77:52087:肒 +CJK UNIFIED IDEOGRAPH:'CB78:52088:肜 +CJK UNIFIED IDEOGRAPH:'CB79:52089:芐 +CJK UNIFIED IDEOGRAPH:'CB7A:52090:芏 +CJK UNIFIED IDEOGRAPH:'CB7B:52091:芅 +CJK UNIFIED IDEOGRAPH:'CB7C:52092:芎 +CJK UNIFIED IDEOGRAPH:'CB7D:52093:芑 +CJK UNIFIED IDEOGRAPH:'CB7E:52094:芓 +CJK UNIFIED IDEOGRAPH:'CBA1:52129:芊 +CJK UNIFIED IDEOGRAPH:'CBA2:52130:芃 +CJK UNIFIED IDEOGRAPH:'CBA3:52131:芄 +CJK UNIFIED IDEOGRAPH:'CBA4:52132:豸 +CJK UNIFIED IDEOGRAPH:'CBA5:52133:迉 +CJK UNIFIED IDEOGRAPH:'CBA6:52134:辿 +CJK UNIFIED IDEOGRAPH:'CBA7:52135:邟 +CJK UNIFIED IDEOGRAPH:'CBA8:52136:邡 +CJK UNIFIED IDEOGRAPH:'CBA9:52137:邥 +CJK UNIFIED IDEOGRAPH:'CBAA:52138:邞 +CJK UNIFIED IDEOGRAPH:'CBAB:52139:邧 +CJK UNIFIED IDEOGRAPH:'CBAC:52140:邠 +CJK UNIFIED IDEOGRAPH:'CBAD:52141:阰 +CJK UNIFIED IDEOGRAPH:'CBAE:52142:阨 +CJK UNIFIED IDEOGRAPH:'CBAF:52143:阯 +CJK UNIFIED IDEOGRAPH:'CBB0:52144:阭 +CJK UNIFIED IDEOGRAPH:'CBB1:52145:丳 +CJK UNIFIED IDEOGRAPH:'CBB2:52146:侘 +CJK UNIFIED IDEOGRAPH:'CBB3:52147:佼 +CJK UNIFIED IDEOGRAPH:'CBB4:52148:侅 +CJK UNIFIED IDEOGRAPH:'CBB5:52149:佽 +CJK UNIFIED IDEOGRAPH:'CBB6:52150:侀 +CJK UNIFIED IDEOGRAPH:'CBB7:52151:侇 +CJK UNIFIED IDEOGRAPH:'CBB8:52152:佶 +CJK UNIFIED IDEOGRAPH:'CBB9:52153:佴 +CJK UNIFIED IDEOGRAPH:'CBBA:52154:侉 +CJK UNIFIED IDEOGRAPH:'CBBB:52155:侄 +CJK UNIFIED IDEOGRAPH:'CBBC:52156:佷 +CJK UNIFIED IDEOGRAPH:'CBBD:52157:佌 +CJK UNIFIED IDEOGRAPH:'CBBE:52158:侗 +CJK UNIFIED IDEOGRAPH:'CBBF:52159:佪 +CJK UNIFIED IDEOGRAPH:'CBC0:52160:侚 +CJK UNIFIED IDEOGRAPH:'CBC1:52161:佹 +CJK UNIFIED IDEOGRAPH:'CBC2:52162:侁 +CJK UNIFIED IDEOGRAPH:'CBC3:52163:佸 +CJK UNIFIED IDEOGRAPH:'CBC4:52164:侐 +CJK UNIFIED IDEOGRAPH:'CBC5:52165:侜 +CJK UNIFIED IDEOGRAPH:'CBC6:52166:侔 +CJK UNIFIED IDEOGRAPH:'CBC7:52167:侞 +CJK UNIFIED IDEOGRAPH:'CBC8:52168:侒 +CJK UNIFIED IDEOGRAPH:'CBC9:52169:侂 +CJK UNIFIED IDEOGRAPH:'CBCA:52170:侕 +CJK UNIFIED IDEOGRAPH:'CBCB:52171:佫 +CJK UNIFIED IDEOGRAPH:'CBCC:52172:佮 +CJK UNIFIED IDEOGRAPH:'CBCD:52173:冞 +CJK UNIFIED IDEOGRAPH:'CBCE:52174:冼 +CJK UNIFIED IDEOGRAPH:'CBCF:52175:冾 +CJK UNIFIED IDEOGRAPH:'CBD0:52176:刵 +CJK UNIFIED IDEOGRAPH:'CBD1:52177:刲 +CJK UNIFIED IDEOGRAPH:'CBD2:52178:刳 +CJK UNIFIED IDEOGRAPH:'CBD3:52179:剆 +CJK UNIFIED IDEOGRAPH:'CBD4:52180:刱 +CJK UNIFIED IDEOGRAPH:'CBD5:52181:劼 +CJK UNIFIED IDEOGRAPH:'CBD6:52182:匊 +CJK UNIFIED IDEOGRAPH:'CBD7:52183:匋 +CJK UNIFIED IDEOGRAPH:'CBD8:52184:匼 +CJK UNIFIED IDEOGRAPH:'CBD9:52185:厒 +CJK UNIFIED IDEOGRAPH:'CBDA:52186:厔 +CJK UNIFIED IDEOGRAPH:'CBDB:52187:咇 +CJK UNIFIED IDEOGRAPH:'CBDC:52188:呿 +CJK UNIFIED IDEOGRAPH:'CBDD:52189:咁 +CJK UNIFIED IDEOGRAPH:'CBDE:52190:咑 +CJK UNIFIED IDEOGRAPH:'CBDF:52191:咂 +CJK UNIFIED IDEOGRAPH:'CBE0:52192:咈 +CJK UNIFIED IDEOGRAPH:'CBE1:52193:呫 +CJK UNIFIED IDEOGRAPH:'CBE2:52194:呺 +CJK UNIFIED IDEOGRAPH:'CBE3:52195:呾 +CJK UNIFIED IDEOGRAPH:'CBE4:52196:呥 +CJK UNIFIED IDEOGRAPH:'CBE5:52197:呬 +CJK UNIFIED IDEOGRAPH:'CBE6:52198:呴 +CJK UNIFIED IDEOGRAPH:'CBE7:52199:呦 +CJK UNIFIED IDEOGRAPH:'CBE8:52200:咍 +CJK UNIFIED IDEOGRAPH:'CBE9:52201:呯 +CJK UNIFIED IDEOGRAPH:'CBEA:52202:呡 +CJK UNIFIED IDEOGRAPH:'CBEB:52203:呠 +CJK UNIFIED IDEOGRAPH:'CBEC:52204:咘 +CJK UNIFIED IDEOGRAPH:'CBED:52205:呣 +CJK UNIFIED IDEOGRAPH:'CBEE:52206:呧 +CJK UNIFIED IDEOGRAPH:'CBEF:52207:呤 +CJK UNIFIED IDEOGRAPH:'CBF0:52208:囷 +CJK UNIFIED IDEOGRAPH:'CBF1:52209:囹 +CJK UNIFIED IDEOGRAPH:'CBF2:52210:坯 +CJK UNIFIED IDEOGRAPH:'CBF3:52211:坲 +CJK UNIFIED IDEOGRAPH:'CBF4:52212:坭 +CJK UNIFIED IDEOGRAPH:'CBF5:52213:坫 +CJK UNIFIED IDEOGRAPH:'CBF6:52214:坱 +CJK UNIFIED IDEOGRAPH:'CBF7:52215:坰 +CJK UNIFIED IDEOGRAPH:'CBF8:52216:坶 +CJK UNIFIED IDEOGRAPH:'CBF9:52217:垀 +CJK UNIFIED IDEOGRAPH:'CBFA:52218:坵 +CJK UNIFIED IDEOGRAPH:'CBFB:52219:坻 +CJK UNIFIED IDEOGRAPH:'CBFC:52220:坳 +CJK UNIFIED IDEOGRAPH:'CBFD:52221:坴 +CJK UNIFIED IDEOGRAPH:'CBFE:52222:坢 +CJK UNIFIED IDEOGRAPH:'CC40:52288:坨 +CJK UNIFIED IDEOGRAPH:'CC41:52289:坽 +CJK UNIFIED IDEOGRAPH:'CC42:52290:夌 +CJK UNIFIED IDEOGRAPH:'CC43:52291:奅 +CJK UNIFIED IDEOGRAPH:'CC44:52292:妵 +CJK UNIFIED IDEOGRAPH:'CC45:52293:妺 +CJK UNIFIED IDEOGRAPH:'CC46:52294:姏 +CJK UNIFIED IDEOGRAPH:'CC47:52295:姎 +CJK UNIFIED IDEOGRAPH:'CC48:52296:妲 +CJK UNIFIED IDEOGRAPH:'CC49:52297:姌 +CJK UNIFIED IDEOGRAPH:'CC4A:52298:姁 +CJK UNIFIED IDEOGRAPH:'CC4B:52299:妶 +CJK UNIFIED IDEOGRAPH:'CC4C:52300:妼 +CJK UNIFIED IDEOGRAPH:'CC4D:52301:姃 +CJK UNIFIED IDEOGRAPH:'CC4E:52302:姖 +CJK UNIFIED IDEOGRAPH:'CC4F:52303:妱 +CJK UNIFIED IDEOGRAPH:'CC50:52304:妽 +CJK UNIFIED IDEOGRAPH:'CC51:52305:姀 +CJK UNIFIED IDEOGRAPH:'CC52:52306:姈 +CJK UNIFIED IDEOGRAPH:'CC53:52307:妴 +CJK UNIFIED IDEOGRAPH:'CC54:52308:姇 +CJK UNIFIED IDEOGRAPH:'CC55:52309:孢 +CJK UNIFIED IDEOGRAPH:'CC56:52310:孥 +CJK UNIFIED IDEOGRAPH:'CC57:52311:宓 +CJK UNIFIED IDEOGRAPH:'CC58:52312:宕 +CJK UNIFIED IDEOGRAPH:'CC59:52313:屄 +CJK UNIFIED IDEOGRAPH:'CC5A:52314:屇 +CJK UNIFIED IDEOGRAPH:'CC5B:52315:岮 +CJK UNIFIED IDEOGRAPH:'CC5C:52316:岤 +CJK UNIFIED IDEOGRAPH:'CC5D:52317:岠 +CJK UNIFIED IDEOGRAPH:'CC5E:52318:岵 +CJK UNIFIED IDEOGRAPH:'CC5F:52319:岯 +CJK UNIFIED IDEOGRAPH:'CC60:52320:岨 +CJK UNIFIED IDEOGRAPH:'CC61:52321:岬 +CJK UNIFIED IDEOGRAPH:'CC62:52322:岟 +CJK UNIFIED IDEOGRAPH:'CC63:52323:岣 +CJK UNIFIED IDEOGRAPH:'CC64:52324:岭 +CJK UNIFIED IDEOGRAPH:'CC65:52325:岢 +CJK UNIFIED IDEOGRAPH:'CC66:52326:岪 +CJK UNIFIED IDEOGRAPH:'CC67:52327:岧 +CJK UNIFIED IDEOGRAPH:'CC68:52328:岝 +CJK UNIFIED IDEOGRAPH:'CC69:52329:岥 +CJK UNIFIED IDEOGRAPH:'CC6A:52330:岶 +CJK UNIFIED IDEOGRAPH:'CC6B:52331:岰 +CJK UNIFIED IDEOGRAPH:'CC6C:52332:岦 +CJK UNIFIED IDEOGRAPH:'CC6D:52333:帗 +CJK UNIFIED IDEOGRAPH:'CC6E:52334:帔 +CJK UNIFIED IDEOGRAPH:'CC6F:52335:帙 +CJK UNIFIED IDEOGRAPH:'CC70:52336:弨 +CJK UNIFIED IDEOGRAPH:'CC71:52337:弢 +CJK UNIFIED IDEOGRAPH:'CC72:52338:弣 +CJK UNIFIED IDEOGRAPH:'CC73:52339:弤 +CJK UNIFIED IDEOGRAPH:'CC74:52340:彔 +CJK UNIFIED IDEOGRAPH:'CC75:52341:徂 +CJK UNIFIED IDEOGRAPH:'CC76:52342:彾 +CJK UNIFIED IDEOGRAPH:'CC77:52343:彽 +CJK UNIFIED IDEOGRAPH:'CC78:52344:忞 +CJK UNIFIED IDEOGRAPH:'CC79:52345:忥 +CJK UNIFIED IDEOGRAPH:'CC7A:52346:怭 +CJK UNIFIED IDEOGRAPH:'CC7B:52347:怦 +CJK UNIFIED IDEOGRAPH:'CC7C:52348:怙 +CJK UNIFIED IDEOGRAPH:'CC7D:52349:怲 +CJK UNIFIED IDEOGRAPH:'CC7E:52350:怋 +CJK UNIFIED IDEOGRAPH:'CCA1:52385:怴 +CJK UNIFIED IDEOGRAPH:'CCA2:52386:怊 +CJK UNIFIED IDEOGRAPH:'CCA3:52387:怗 +CJK UNIFIED IDEOGRAPH:'CCA4:52388:怳 +CJK UNIFIED IDEOGRAPH:'CCA5:52389:怚 +CJK UNIFIED IDEOGRAPH:'CCA6:52390:怞 +CJK UNIFIED IDEOGRAPH:'CCA7:52391:怬 +CJK UNIFIED IDEOGRAPH:'CCA8:52392:怢 +CJK UNIFIED IDEOGRAPH:'CCA9:52393:怍 +CJK UNIFIED IDEOGRAPH:'CCAA:52394:怐 +CJK UNIFIED IDEOGRAPH:'CCAB:52395:怮 +CJK UNIFIED IDEOGRAPH:'CCAC:52396:怓 +CJK UNIFIED IDEOGRAPH:'CCAD:52397:怑 +CJK UNIFIED IDEOGRAPH:'CCAE:52398:怌 +CJK UNIFIED IDEOGRAPH:'CCAF:52399:怉 +CJK UNIFIED IDEOGRAPH:'CCB0:52400:怜 +CJK UNIFIED IDEOGRAPH:'CCB1:52401:戔 +CJK UNIFIED IDEOGRAPH:'CCB2:52402:戽 +CJK UNIFIED IDEOGRAPH:'CCB3:52403:抭 +CJK UNIFIED IDEOGRAPH:'CCB4:52404:抴 +CJK UNIFIED IDEOGRAPH:'CCB5:52405:拑 +CJK UNIFIED IDEOGRAPH:'CCB6:52406:抾 +CJK UNIFIED IDEOGRAPH:'CCB7:52407:抪 +CJK UNIFIED IDEOGRAPH:'CCB8:52408:抶 +CJK UNIFIED IDEOGRAPH:'CCB9:52409:拊 +CJK UNIFIED IDEOGRAPH:'CCBA:52410:抮 +CJK UNIFIED IDEOGRAPH:'CCBB:52411:抳 +CJK UNIFIED IDEOGRAPH:'CCBC:52412:抯 +CJK UNIFIED IDEOGRAPH:'CCBD:52413:抻 +CJK UNIFIED IDEOGRAPH:'CCBE:52414:抩 +CJK UNIFIED IDEOGRAPH:'CCBF:52415:抰 +CJK UNIFIED IDEOGRAPH:'CCC0:52416:抸 +CJK UNIFIED IDEOGRAPH:'CCC1:52417:攽 +CJK UNIFIED IDEOGRAPH:'CCC2:52418:斨 +CJK UNIFIED IDEOGRAPH:'CCC3:52419:斻 +CJK UNIFIED IDEOGRAPH:'CCC4:52420:昉 +CJK UNIFIED IDEOGRAPH:'CCC5:52421:旼 +CJK UNIFIED IDEOGRAPH:'CCC6:52422:昄 +CJK UNIFIED IDEOGRAPH:'CCC7:52423:昒 +CJK UNIFIED IDEOGRAPH:'CCC8:52424:昈 +CJK UNIFIED IDEOGRAPH:'CCC9:52425:旻 +CJK UNIFIED IDEOGRAPH:'CCCA:52426:昃 +CJK UNIFIED IDEOGRAPH:'CCCB:52427:昋 +CJK UNIFIED IDEOGRAPH:'CCCC:52428:昍 +CJK UNIFIED IDEOGRAPH:'CCCD:52429:昅 +CJK UNIFIED IDEOGRAPH:'CCCE:52430:旽 +CJK UNIFIED IDEOGRAPH:'CCCF:52431:昑 +CJK UNIFIED IDEOGRAPH:'CCD0:52432:昐 +CJK UNIFIED IDEOGRAPH:'CCD1:52433:曶 +CJK UNIFIED IDEOGRAPH:'CCD2:52434:朊 +CJK UNIFIED IDEOGRAPH:'CCD3:52435:枅 +CJK UNIFIED IDEOGRAPH:'CCD4:52436:杬 +CJK UNIFIED IDEOGRAPH:'CCD5:52437:枎 +CJK UNIFIED IDEOGRAPH:'CCD6:52438:枒 +CJK UNIFIED IDEOGRAPH:'CCD7:52439:杶 +CJK UNIFIED IDEOGRAPH:'CCD8:52440:杻 +CJK UNIFIED IDEOGRAPH:'CCD9:52441:枘 +CJK UNIFIED IDEOGRAPH:'CCDA:52442:枆 +CJK UNIFIED IDEOGRAPH:'CCDB:52443:构 +CJK UNIFIED IDEOGRAPH:'CCDC:52444:杴 +CJK UNIFIED IDEOGRAPH:'CCDD:52445:枍 +CJK UNIFIED IDEOGRAPH:'CCDE:52446:枌 +CJK UNIFIED IDEOGRAPH:'CCDF:52447:杺 +CJK UNIFIED IDEOGRAPH:'CCE0:52448:枟 +CJK UNIFIED IDEOGRAPH:'CCE1:52449:枑 +CJK UNIFIED IDEOGRAPH:'CCE2:52450:枙 +CJK UNIFIED IDEOGRAPH:'CCE3:52451:枃 +CJK UNIFIED IDEOGRAPH:'CCE4:52452:杽 +CJK UNIFIED IDEOGRAPH:'CCE5:52453:极 +CJK UNIFIED IDEOGRAPH:'CCE6:52454:杸 +CJK UNIFIED IDEOGRAPH:'CCE7:52455:杹 +CJK UNIFIED IDEOGRAPH:'CCE8:52456:枔 +CJK UNIFIED IDEOGRAPH:'CCE9:52457:欥 +CJK UNIFIED IDEOGRAPH:'CCEA:52458:殀 +CJK UNIFIED IDEOGRAPH:'CCEB:52459:歾 +CJK UNIFIED IDEOGRAPH:'CCEC:52460:毞 +CJK UNIFIED IDEOGRAPH:'CCED:52461:氝 +CJK UNIFIED IDEOGRAPH:'CCEE:52462:沓 +CJK UNIFIED IDEOGRAPH:'CCEF:52463:泬 +CJK UNIFIED IDEOGRAPH:'CCF0:52464:泫 +CJK UNIFIED IDEOGRAPH:'CCF1:52465:泮 +CJK UNIFIED IDEOGRAPH:'CCF2:52466:泙 +CJK UNIFIED IDEOGRAPH:'CCF3:52467:沶 +CJK UNIFIED IDEOGRAPH:'CCF4:52468:泔 +CJK UNIFIED IDEOGRAPH:'CCF5:52469:沭 +CJK UNIFIED IDEOGRAPH:'CCF6:52470:泧 +CJK UNIFIED IDEOGRAPH:'CCF7:52471:沷 +CJK UNIFIED IDEOGRAPH:'CCF8:52472:泐 +CJK UNIFIED IDEOGRAPH:'CCF9:52473:泂 +CJK UNIFIED IDEOGRAPH:'CCFA:52474:沺 +CJK UNIFIED IDEOGRAPH:'CCFB:52475:泃 +CJK UNIFIED IDEOGRAPH:'CCFC:52476:泆 +CJK UNIFIED IDEOGRAPH:'CCFD:52477:泭 +CJK UNIFIED IDEOGRAPH:'CCFE:52478:泲 +CJK UNIFIED IDEOGRAPH:'CD40:52544:泒 +CJK UNIFIED IDEOGRAPH:'CD41:52545:泝 +CJK UNIFIED IDEOGRAPH:'CD42:52546:沴 +CJK UNIFIED IDEOGRAPH:'CD43:52547:沊 +CJK UNIFIED IDEOGRAPH:'CD44:52548:沝 +CJK UNIFIED IDEOGRAPH:'CD45:52549:沀 +CJK UNIFIED IDEOGRAPH:'CD46:52550:泞 +CJK UNIFIED IDEOGRAPH:'CD47:52551:泀 +CJK UNIFIED IDEOGRAPH:'CD48:52552:洰 +CJK UNIFIED IDEOGRAPH:'CD49:52553:泍 +CJK UNIFIED IDEOGRAPH:'CD4A:52554:泇 +CJK UNIFIED IDEOGRAPH:'CD4B:52555:沰 +CJK UNIFIED IDEOGRAPH:'CD4C:52556:泹 +CJK UNIFIED IDEOGRAPH:'CD4D:52557:泏 +CJK UNIFIED IDEOGRAPH:'CD4E:52558:泩 +CJK UNIFIED IDEOGRAPH:'CD4F:52559:泑 +CJK UNIFIED IDEOGRAPH:'CD50:52560:炔 +CJK UNIFIED IDEOGRAPH:'CD51:52561:炘 +CJK UNIFIED IDEOGRAPH:'CD52:52562:炅 +CJK UNIFIED IDEOGRAPH:'CD53:52563:炓 +CJK UNIFIED IDEOGRAPH:'CD54:52564:炆 +CJK UNIFIED IDEOGRAPH:'CD55:52565:炄 +CJK UNIFIED IDEOGRAPH:'CD56:52566:炑 +CJK UNIFIED IDEOGRAPH:'CD57:52567:炖 +CJK UNIFIED IDEOGRAPH:'CD58:52568:炂 +CJK UNIFIED IDEOGRAPH:'CD59:52569:炚 +CJK UNIFIED IDEOGRAPH:'CD5A:52570:炃 +CJK UNIFIED IDEOGRAPH:'CD5B:52571:牪 +CJK UNIFIED IDEOGRAPH:'CD5C:52572:狖 +CJK UNIFIED IDEOGRAPH:'CD5D:52573:狋 +CJK UNIFIED IDEOGRAPH:'CD5E:52574:狘 +CJK UNIFIED IDEOGRAPH:'CD5F:52575:狉 +CJK UNIFIED IDEOGRAPH:'CD60:52576:狜 +CJK UNIFIED IDEOGRAPH:'CD61:52577:狒 +CJK UNIFIED IDEOGRAPH:'CD62:52578:狔 +CJK UNIFIED IDEOGRAPH:'CD63:52579:狚 +CJK UNIFIED IDEOGRAPH:'CD64:52580:狌 +CJK UNIFIED IDEOGRAPH:'CD65:52581:狑 +CJK UNIFIED IDEOGRAPH:'CD66:52582:玤 +CJK UNIFIED IDEOGRAPH:'CD67:52583:玡 +CJK UNIFIED IDEOGRAPH:'CD68:52584:玭 +CJK UNIFIED IDEOGRAPH:'CD69:52585:玦 +CJK UNIFIED IDEOGRAPH:'CD6A:52586:玢 +CJK UNIFIED IDEOGRAPH:'CD6B:52587:玠 +CJK UNIFIED IDEOGRAPH:'CD6C:52588:玬 +CJK UNIFIED IDEOGRAPH:'CD6D:52589:玝 +CJK UNIFIED IDEOGRAPH:'CD6E:52590:瓝 +CJK UNIFIED IDEOGRAPH:'CD6F:52591:瓨 +CJK UNIFIED IDEOGRAPH:'CD70:52592:甿 +CJK UNIFIED IDEOGRAPH:'CD71:52593:畀 +CJK UNIFIED IDEOGRAPH:'CD72:52594:甾 +CJK UNIFIED IDEOGRAPH:'CD73:52595:疌 +CJK UNIFIED IDEOGRAPH:'CD74:52596:疘 +CJK UNIFIED IDEOGRAPH:'CD75:52597:皯 +CJK UNIFIED IDEOGRAPH:'CD76:52598:盳 +CJK UNIFIED IDEOGRAPH:'CD77:52599:盱 +CJK UNIFIED IDEOGRAPH:'CD78:52600:盰 +CJK UNIFIED IDEOGRAPH:'CD79:52601:盵 +CJK UNIFIED IDEOGRAPH:'CD7A:52602:矸 +CJK UNIFIED IDEOGRAPH:'CD7B:52603:矼 +CJK UNIFIED IDEOGRAPH:'CD7C:52604:矹 +CJK UNIFIED IDEOGRAPH:'CD7D:52605:矻 +CJK UNIFIED IDEOGRAPH:'CD7E:52606:矺 +CJK UNIFIED IDEOGRAPH:'CDA1:52641:矷 +CJK UNIFIED IDEOGRAPH:'CDA2:52642:祂 +CJK UNIFIED IDEOGRAPH:'CDA3:52643:礿 +CJK UNIFIED IDEOGRAPH:'CDA4:52644:秅 +CJK UNIFIED IDEOGRAPH:'CDA5:52645:穸 +CJK UNIFIED IDEOGRAPH:'CDA6:52646:穻 +CJK UNIFIED IDEOGRAPH:'CDA7:52647:竻 +CJK UNIFIED IDEOGRAPH:'CDA8:52648:籵 +CJK UNIFIED IDEOGRAPH:'CDA9:52649:糽 +CJK UNIFIED IDEOGRAPH:'CDAA:52650:耵 +CJK UNIFIED IDEOGRAPH:'CDAB:52651:肏 +CJK UNIFIED IDEOGRAPH:'CDAC:52652:肮 +CJK UNIFIED IDEOGRAPH:'CDAD:52653:肣 +CJK UNIFIED IDEOGRAPH:'CDAE:52654:肸 +CJK UNIFIED IDEOGRAPH:'CDAF:52655:肵 +CJK UNIFIED IDEOGRAPH:'CDB0:52656:肭 +CJK UNIFIED IDEOGRAPH:'CDB1:52657:舠 +CJK UNIFIED IDEOGRAPH:'CDB2:52658:芠 +CJK UNIFIED IDEOGRAPH:'CDB3:52659:苀 +CJK UNIFIED IDEOGRAPH:'CDB4:52660:芫 +CJK UNIFIED IDEOGRAPH:'CDB5:52661:芚 +CJK UNIFIED IDEOGRAPH:'CDB6:52662:芘 +CJK UNIFIED IDEOGRAPH:'CDB7:52663:芛 +CJK UNIFIED IDEOGRAPH:'CDB8:52664:芵 +CJK UNIFIED IDEOGRAPH:'CDB9:52665:芧 +CJK UNIFIED IDEOGRAPH:'CDBA:52666:芮 +CJK UNIFIED IDEOGRAPH:'CDBB:52667:芼 +CJK UNIFIED IDEOGRAPH:'CDBC:52668:芞 +CJK UNIFIED IDEOGRAPH:'CDBD:52669:芺 +CJK UNIFIED IDEOGRAPH:'CDBE:52670:芴 +CJK UNIFIED IDEOGRAPH:'CDBF:52671:芨 +CJK UNIFIED IDEOGRAPH:'CDC0:52672:芡 +CJK UNIFIED IDEOGRAPH:'CDC1:52673:芩 +CJK UNIFIED IDEOGRAPH:'CDC2:52674:苂 +CJK UNIFIED IDEOGRAPH:'CDC3:52675:芤 +CJK UNIFIED IDEOGRAPH:'CDC4:52676:苃 +CJK UNIFIED IDEOGRAPH:'CDC5:52677:芶 +CJK UNIFIED IDEOGRAPH:'CDC6:52678:芢 +CJK UNIFIED IDEOGRAPH:'CDC7:52679:虰 +CJK UNIFIED IDEOGRAPH:'CDC8:52680:虯 +CJK UNIFIED IDEOGRAPH:'CDC9:52681:虭 +CJK UNIFIED IDEOGRAPH:'CDCA:52682:虮 +CJK UNIFIED IDEOGRAPH:'CDCB:52683:豖 +CJK UNIFIED IDEOGRAPH:'CDCC:52684:迒 +CJK UNIFIED IDEOGRAPH:'CDCD:52685:迋 +CJK UNIFIED IDEOGRAPH:'CDCE:52686:迓 +CJK UNIFIED IDEOGRAPH:'CDCF:52687:迍 +CJK UNIFIED IDEOGRAPH:'CDD0:52688:迖 +CJK UNIFIED IDEOGRAPH:'CDD1:52689:迕 +CJK UNIFIED IDEOGRAPH:'CDD2:52690:迗 +CJK UNIFIED IDEOGRAPH:'CDD3:52691:邲 +CJK UNIFIED IDEOGRAPH:'CDD4:52692:邴 +CJK UNIFIED IDEOGRAPH:'CDD5:52693:邯 +CJK UNIFIED IDEOGRAPH:'CDD6:52694:邳 +CJK UNIFIED IDEOGRAPH:'CDD7:52695:邰 +CJK UNIFIED IDEOGRAPH:'CDD8:52696:阹 +CJK UNIFIED IDEOGRAPH:'CDD9:52697:阽 +CJK UNIFIED IDEOGRAPH:'CDDA:52698:阼 +CJK UNIFIED IDEOGRAPH:'CDDB:52699:阺 +CJK UNIFIED IDEOGRAPH:'CDDC:52700:陃 +CJK UNIFIED IDEOGRAPH:'CDDD:52701:俍 +CJK UNIFIED IDEOGRAPH:'CDDE:52702:俅 +CJK UNIFIED IDEOGRAPH:'CDDF:52703:俓 +CJK UNIFIED IDEOGRAPH:'CDE0:52704:侲 +CJK UNIFIED IDEOGRAPH:'CDE1:52705:俉 +CJK UNIFIED IDEOGRAPH:'CDE2:52706:俋 +CJK UNIFIED IDEOGRAPH:'CDE3:52707:俁 +CJK UNIFIED IDEOGRAPH:'CDE4:52708:俔 +CJK UNIFIED IDEOGRAPH:'CDE5:52709:俜 +CJK UNIFIED IDEOGRAPH:'CDE6:52710:俙 +CJK UNIFIED IDEOGRAPH:'CDE7:52711:侻 +CJK UNIFIED IDEOGRAPH:'CDE8:52712:侳 +CJK UNIFIED IDEOGRAPH:'CDE9:52713:俛 +CJK UNIFIED IDEOGRAPH:'CDEA:52714:俇 +CJK UNIFIED IDEOGRAPH:'CDEB:52715:俖 +CJK UNIFIED IDEOGRAPH:'CDEC:52716:侺 +CJK UNIFIED IDEOGRAPH:'CDED:52717:俀 +CJK UNIFIED IDEOGRAPH:'CDEE:52718:侹 +CJK UNIFIED IDEOGRAPH:'CDEF:52719:俬 +CJK UNIFIED IDEOGRAPH:'CDF0:52720:剄 +CJK UNIFIED IDEOGRAPH:'CDF1:52721:剉 +CJK UNIFIED IDEOGRAPH:'CDF2:52722:勀 +CJK UNIFIED IDEOGRAPH:'CDF3:52723:勂 +CJK UNIFIED IDEOGRAPH:'CDF4:52724:匽 +CJK UNIFIED IDEOGRAPH:'CDF5:52725:卼 +CJK UNIFIED IDEOGRAPH:'CDF6:52726:厗 +CJK UNIFIED IDEOGRAPH:'CDF7:52727:厖 +CJK UNIFIED IDEOGRAPH:'CDF8:52728:厙 +CJK UNIFIED IDEOGRAPH:'CDF9:52729:厘 +CJK UNIFIED IDEOGRAPH:'CDFA:52730:咺 +CJK UNIFIED IDEOGRAPH:'CDFB:52731:咡 +CJK UNIFIED IDEOGRAPH:'CDFC:52732:咭 +CJK UNIFIED IDEOGRAPH:'CDFD:52733:咥 +CJK UNIFIED IDEOGRAPH:'CDFE:52734:哏 +CJK UNIFIED IDEOGRAPH:'CE40:52800:哃 +CJK UNIFIED IDEOGRAPH:'CE41:52801:茍 +CJK UNIFIED IDEOGRAPH:'CE42:52802:咷 +CJK UNIFIED IDEOGRAPH:'CE43:52803:咮 +CJK UNIFIED IDEOGRAPH:'CE44:52804:哖 +CJK UNIFIED IDEOGRAPH:'CE45:52805:咶 +CJK UNIFIED IDEOGRAPH:'CE46:52806:哅 +CJK UNIFIED IDEOGRAPH:'CE47:52807:哆 +CJK UNIFIED IDEOGRAPH:'CE48:52808:咠 +CJK UNIFIED IDEOGRAPH:'CE49:52809:呰 +CJK UNIFIED IDEOGRAPH:'CE4A:52810:咼 +CJK UNIFIED IDEOGRAPH:'CE4B:52811:咢 +CJK UNIFIED IDEOGRAPH:'CE4C:52812:咾 +CJK UNIFIED IDEOGRAPH:'CE4D:52813:呲 +CJK UNIFIED IDEOGRAPH:'CE4E:52814:哞 +CJK UNIFIED IDEOGRAPH:'CE4F:52815:咰 +CJK UNIFIED IDEOGRAPH:'CE50:52816:垵 +CJK UNIFIED IDEOGRAPH:'CE51:52817:垞 +CJK UNIFIED IDEOGRAPH:'CE52:52818:垟 +CJK UNIFIED IDEOGRAPH:'CE53:52819:垤 +CJK UNIFIED IDEOGRAPH:'CE54:52820:垌 +CJK UNIFIED IDEOGRAPH:'CE55:52821:垗 +CJK UNIFIED IDEOGRAPH:'CE56:52822:垝 +CJK UNIFIED IDEOGRAPH:'CE57:52823:垛 +CJK UNIFIED IDEOGRAPH:'CE58:52824:垔 +CJK UNIFIED IDEOGRAPH:'CE59:52825:垘 +CJK UNIFIED IDEOGRAPH:'CE5A:52826:垏 +CJK UNIFIED IDEOGRAPH:'CE5B:52827:垙 +CJK UNIFIED IDEOGRAPH:'CE5C:52828:垥 +CJK UNIFIED IDEOGRAPH:'CE5D:52829:垚 +CJK UNIFIED IDEOGRAPH:'CE5E:52830:垕 +CJK UNIFIED IDEOGRAPH:'CE5F:52831:壴 +CJK UNIFIED IDEOGRAPH:'CE60:52832:复 +CJK UNIFIED IDEOGRAPH:'CE61:52833:奓 +CJK UNIFIED IDEOGRAPH:'CE62:52834:姡 +CJK UNIFIED IDEOGRAPH:'CE63:52835:姞 +CJK UNIFIED IDEOGRAPH:'CE64:52836:姮 +CJK UNIFIED IDEOGRAPH:'CE65:52837:娀 +CJK UNIFIED IDEOGRAPH:'CE66:52838:姱 +CJK UNIFIED IDEOGRAPH:'CE67:52839:姝 +CJK UNIFIED IDEOGRAPH:'CE68:52840:姺 +CJK UNIFIED IDEOGRAPH:'CE69:52841:姽 +CJK UNIFIED IDEOGRAPH:'CE6A:52842:姼 +CJK UNIFIED IDEOGRAPH:'CE6B:52843:姶 +CJK UNIFIED IDEOGRAPH:'CE6C:52844:姤 +CJK UNIFIED IDEOGRAPH:'CE6D:52845:姲 +CJK UNIFIED IDEOGRAPH:'CE6E:52846:姷 +CJK UNIFIED IDEOGRAPH:'CE6F:52847:姛 +CJK UNIFIED IDEOGRAPH:'CE70:52848:姩 +CJK UNIFIED IDEOGRAPH:'CE71:52849:姳 +CJK UNIFIED IDEOGRAPH:'CE72:52850:姵 +CJK UNIFIED IDEOGRAPH:'CE73:52851:姠 +CJK UNIFIED IDEOGRAPH:'CE74:52852:姾 +CJK UNIFIED IDEOGRAPH:'CE75:52853:姴 +CJK UNIFIED IDEOGRAPH:'CE76:52854:姭 +CJK UNIFIED IDEOGRAPH:'CE77:52855:宨 +CJK UNIFIED IDEOGRAPH:'CE78:52856:屌 +CJK UNIFIED IDEOGRAPH:'CE79:52857:峐 +CJK UNIFIED IDEOGRAPH:'CE7A:52858:峘 +CJK UNIFIED IDEOGRAPH:'CE7B:52859:峌 +CJK UNIFIED IDEOGRAPH:'CE7C:52860:峗 +CJK UNIFIED IDEOGRAPH:'CE7D:52861:峋 +CJK UNIFIED IDEOGRAPH:'CE7E:52862:峛 +CJK UNIFIED IDEOGRAPH:'CEA1:52897:峞 +CJK UNIFIED IDEOGRAPH:'CEA2:52898:峚 +CJK UNIFIED IDEOGRAPH:'CEA3:52899:峉 +CJK UNIFIED IDEOGRAPH:'CEA4:52900:峇 +CJK UNIFIED IDEOGRAPH:'CEA5:52901:峊 +CJK UNIFIED IDEOGRAPH:'CEA6:52902:峖 +CJK UNIFIED IDEOGRAPH:'CEA7:52903:峓 +CJK UNIFIED IDEOGRAPH:'CEA8:52904:峔 +CJK UNIFIED IDEOGRAPH:'CEA9:52905:峏 +CJK UNIFIED IDEOGRAPH:'CEAA:52906:峈 +CJK UNIFIED IDEOGRAPH:'CEAB:52907:峆 +CJK UNIFIED IDEOGRAPH:'CEAC:52908:峎 +CJK UNIFIED IDEOGRAPH:'CEAD:52909:峟 +CJK UNIFIED IDEOGRAPH:'CEAE:52910:峸 +CJK UNIFIED IDEOGRAPH:'CEAF:52911:巹 +CJK UNIFIED IDEOGRAPH:'CEB0:52912:帡 +CJK UNIFIED IDEOGRAPH:'CEB1:52913:帢 +CJK UNIFIED IDEOGRAPH:'CEB2:52914:帣 +CJK UNIFIED IDEOGRAPH:'CEB3:52915:帠 +CJK UNIFIED IDEOGRAPH:'CEB4:52916:帤 +CJK UNIFIED IDEOGRAPH:'CEB5:52917:庰 +CJK UNIFIED IDEOGRAPH:'CEB6:52918:庤 +CJK UNIFIED IDEOGRAPH:'CEB7:52919:庢 +CJK UNIFIED IDEOGRAPH:'CEB8:52920:庛 +CJK UNIFIED IDEOGRAPH:'CEB9:52921:庣 +CJK UNIFIED IDEOGRAPH:'CEBA:52922:庥 +CJK UNIFIED IDEOGRAPH:'CEBB:52923:弇 +CJK UNIFIED IDEOGRAPH:'CEBC:52924:弮 +CJK UNIFIED IDEOGRAPH:'CEBD:52925:彖 +CJK UNIFIED IDEOGRAPH:'CEBE:52926:徆 +CJK UNIFIED IDEOGRAPH:'CEBF:52927:怷 +CJK UNIFIED IDEOGRAPH:'CEC0:52928:怹 +CJK UNIFIED IDEOGRAPH:'CEC1:52929:恔 +CJK UNIFIED IDEOGRAPH:'CEC2:52930:恲 +CJK UNIFIED IDEOGRAPH:'CEC3:52931:恞 +CJK UNIFIED IDEOGRAPH:'CEC4:52932:恅 +CJK UNIFIED IDEOGRAPH:'CEC5:52933:恓 +CJK UNIFIED IDEOGRAPH:'CEC6:52934:恇 +CJK UNIFIED IDEOGRAPH:'CEC7:52935:恉 +CJK UNIFIED IDEOGRAPH:'CEC8:52936:恛 +CJK UNIFIED IDEOGRAPH:'CEC9:52937:恌 +CJK UNIFIED IDEOGRAPH:'CECA:52938:恀 +CJK UNIFIED IDEOGRAPH:'CECB:52939:恂 +CJK UNIFIED IDEOGRAPH:'CECC:52940:恟 +CJK UNIFIED IDEOGRAPH:'CECD:52941:怤 +CJK UNIFIED IDEOGRAPH:'CECE:52942:恄 +CJK UNIFIED IDEOGRAPH:'CECF:52943:恘 +CJK UNIFIED IDEOGRAPH:'CED0:52944:恦 +CJK UNIFIED IDEOGRAPH:'CED1:52945:恮 +CJK UNIFIED IDEOGRAPH:'CED2:52946:扂 +CJK UNIFIED IDEOGRAPH:'CED3:52947:扃 +CJK UNIFIED IDEOGRAPH:'CED4:52948:拏 +CJK UNIFIED IDEOGRAPH:'CED5:52949:挍 +CJK UNIFIED IDEOGRAPH:'CED6:52950:挋 +CJK UNIFIED IDEOGRAPH:'CED7:52951:拵 +CJK UNIFIED IDEOGRAPH:'CED8:52952:挎 +CJK UNIFIED IDEOGRAPH:'CED9:52953:挃 +CJK UNIFIED IDEOGRAPH:'CEDA:52954:拫 +CJK UNIFIED IDEOGRAPH:'CEDB:52955:拹 +CJK UNIFIED IDEOGRAPH:'CEDC:52956:挏 +CJK UNIFIED IDEOGRAPH:'CEDD:52957:挌 +CJK UNIFIED IDEOGRAPH:'CEDE:52958:拸 +CJK UNIFIED IDEOGRAPH:'CEDF:52959:拶 +CJK UNIFIED IDEOGRAPH:'CEE0:52960:挀 +CJK UNIFIED IDEOGRAPH:'CEE1:52961:挓 +CJK UNIFIED IDEOGRAPH:'CEE2:52962:挔 +CJK UNIFIED IDEOGRAPH:'CEE3:52963:拺 +CJK UNIFIED IDEOGRAPH:'CEE4:52964:挕 +CJK UNIFIED IDEOGRAPH:'CEE5:52965:拻 +CJK UNIFIED IDEOGRAPH:'CEE6:52966:拰 +CJK UNIFIED IDEOGRAPH:'CEE7:52967:敁 +CJK UNIFIED IDEOGRAPH:'CEE8:52968:敃 +CJK UNIFIED IDEOGRAPH:'CEE9:52969:斪 +CJK UNIFIED IDEOGRAPH:'CEEA:52970:斿 +CJK UNIFIED IDEOGRAPH:'CEEB:52971:昶 +CJK UNIFIED IDEOGRAPH:'CEEC:52972:昡 +CJK UNIFIED IDEOGRAPH:'CEED:52973:昲 +CJK UNIFIED IDEOGRAPH:'CEEE:52974:昵 +CJK UNIFIED IDEOGRAPH:'CEEF:52975:昜 +CJK UNIFIED IDEOGRAPH:'CEF0:52976:昦 +CJK UNIFIED IDEOGRAPH:'CEF1:52977:昢 +CJK UNIFIED IDEOGRAPH:'CEF2:52978:昳 +CJK UNIFIED IDEOGRAPH:'CEF3:52979:昫 +CJK UNIFIED IDEOGRAPH:'CEF4:52980:昺 +CJK UNIFIED IDEOGRAPH:'CEF5:52981:昝 +CJK UNIFIED IDEOGRAPH:'CEF6:52982:昴 +CJK UNIFIED IDEOGRAPH:'CEF7:52983:昹 +CJK UNIFIED IDEOGRAPH:'CEF8:52984:昮 +CJK UNIFIED IDEOGRAPH:'CEF9:52985:朏 +CJK UNIFIED IDEOGRAPH:'CEFA:52986:朐 +CJK UNIFIED IDEOGRAPH:'CEFB:52987:柁 +CJK UNIFIED IDEOGRAPH:'CEFC:52988:柲 +CJK UNIFIED IDEOGRAPH:'CEFD:52989:柈 +CJK UNIFIED IDEOGRAPH:'CEFE:52990:枺 +CJK UNIFIED IDEOGRAPH:'CF40:53056:柜 +CJK UNIFIED IDEOGRAPH:'CF41:53057:枻 +CJK UNIFIED IDEOGRAPH:'CF42:53058:柸 +CJK UNIFIED IDEOGRAPH:'CF43:53059:柘 +CJK UNIFIED IDEOGRAPH:'CF44:53060:柀 +CJK UNIFIED IDEOGRAPH:'CF45:53061:枷 +CJK UNIFIED IDEOGRAPH:'CF46:53062:柅 +CJK UNIFIED IDEOGRAPH:'CF47:53063:柫 +CJK UNIFIED IDEOGRAPH:'CF48:53064:柤 +CJK UNIFIED IDEOGRAPH:'CF49:53065:柟 +CJK UNIFIED IDEOGRAPH:'CF4A:53066:枵 +CJK UNIFIED IDEOGRAPH:'CF4B:53067:柍 +CJK UNIFIED IDEOGRAPH:'CF4C:53068:枳 +CJK UNIFIED IDEOGRAPH:'CF4D:53069:柷 +CJK UNIFIED IDEOGRAPH:'CF4E:53070:柶 +CJK UNIFIED IDEOGRAPH:'CF4F:53071:柮 +CJK UNIFIED IDEOGRAPH:'CF50:53072:柣 +CJK UNIFIED IDEOGRAPH:'CF51:53073:柂 +CJK UNIFIED IDEOGRAPH:'CF52:53074:枹 +CJK UNIFIED IDEOGRAPH:'CF53:53075:柎 +CJK UNIFIED IDEOGRAPH:'CF54:53076:柧 +CJK UNIFIED IDEOGRAPH:'CF55:53077:柰 +CJK UNIFIED IDEOGRAPH:'CF56:53078:枲 +CJK UNIFIED IDEOGRAPH:'CF57:53079:柼 +CJK UNIFIED IDEOGRAPH:'CF58:53080:柆 +CJK UNIFIED IDEOGRAPH:'CF59:53081:柭 +CJK UNIFIED IDEOGRAPH:'CF5A:53082:柌 +CJK UNIFIED IDEOGRAPH:'CF5B:53083:枮 +CJK UNIFIED IDEOGRAPH:'CF5C:53084:柦 +CJK UNIFIED IDEOGRAPH:'CF5D:53085:柛 +CJK UNIFIED IDEOGRAPH:'CF5E:53086:柺 +CJK UNIFIED IDEOGRAPH:'CF5F:53087:柉 +CJK UNIFIED IDEOGRAPH:'CF60:53088:柊 +CJK UNIFIED IDEOGRAPH:'CF61:53089:柃 +CJK UNIFIED IDEOGRAPH:'CF62:53090:柪 +CJK UNIFIED IDEOGRAPH:'CF63:53091:柋 +CJK UNIFIED IDEOGRAPH:'CF64:53092:欨 +CJK UNIFIED IDEOGRAPH:'CF65:53093:殂 +CJK UNIFIED IDEOGRAPH:'CF66:53094:殄 +CJK UNIFIED IDEOGRAPH:'CF67:53095:殶 +CJK UNIFIED IDEOGRAPH:'CF68:53096:毖 +CJK UNIFIED IDEOGRAPH:'CF69:53097:毘 +CJK UNIFIED IDEOGRAPH:'CF6A:53098:毠 +CJK UNIFIED IDEOGRAPH:'CF6B:53099:氠 +CJK UNIFIED IDEOGRAPH:'CF6C:53100:氡 +CJK UNIFIED IDEOGRAPH:'CF6D:53101:洨 +CJK UNIFIED IDEOGRAPH:'CF6E:53102:洴 +CJK UNIFIED IDEOGRAPH:'CF6F:53103:洭 +CJK UNIFIED IDEOGRAPH:'CF70:53104:洟 +CJK UNIFIED IDEOGRAPH:'CF71:53105:洼 +CJK UNIFIED IDEOGRAPH:'CF72:53106:洿 +CJK UNIFIED IDEOGRAPH:'CF73:53107:洒 +CJK UNIFIED IDEOGRAPH:'CF74:53108:洊 +CJK UNIFIED IDEOGRAPH:'CF75:53109:泚 +CJK UNIFIED IDEOGRAPH:'CF76:53110:洳 +CJK UNIFIED IDEOGRAPH:'CF77:53111:洄 +CJK UNIFIED IDEOGRAPH:'CF78:53112:洙 +CJK UNIFIED IDEOGRAPH:'CF79:53113:洺 +CJK UNIFIED IDEOGRAPH:'CF7A:53114:洚 +CJK UNIFIED IDEOGRAPH:'CF7B:53115:洑 +CJK UNIFIED IDEOGRAPH:'CF7C:53116:洀 +CJK UNIFIED IDEOGRAPH:'CF7D:53117:洝 +CJK UNIFIED IDEOGRAPH:'CF7E:53118:浂 +CJK UNIFIED IDEOGRAPH:'CFA1:53153:洁 +CJK UNIFIED IDEOGRAPH:'CFA2:53154:洘 +CJK UNIFIED IDEOGRAPH:'CFA3:53155:洷 +CJK UNIFIED IDEOGRAPH:'CFA4:53156:洃 +CJK UNIFIED IDEOGRAPH:'CFA5:53157:洏 +CJK UNIFIED IDEOGRAPH:'CFA6:53158:浀 +CJK UNIFIED IDEOGRAPH:'CFA7:53159:洇 +CJK UNIFIED IDEOGRAPH:'CFA8:53160:洠 +CJK UNIFIED IDEOGRAPH:'CFA9:53161:洬 +CJK UNIFIED IDEOGRAPH:'CFAA:53162:洈 +CJK UNIFIED IDEOGRAPH:'CFAB:53163:洢 +CJK UNIFIED IDEOGRAPH:'CFAC:53164:洉 +CJK UNIFIED IDEOGRAPH:'CFAD:53165:洐 +CJK UNIFIED IDEOGRAPH:'CFAE:53166:炷 +CJK UNIFIED IDEOGRAPH:'CFAF:53167:炟 +CJK UNIFIED IDEOGRAPH:'CFB0:53168:炾 +CJK UNIFIED IDEOGRAPH:'CFB1:53169:炱 +CJK UNIFIED IDEOGRAPH:'CFB2:53170:炰 +CJK UNIFIED IDEOGRAPH:'CFB3:53171:炡 +CJK UNIFIED IDEOGRAPH:'CFB4:53172:炴 +CJK UNIFIED IDEOGRAPH:'CFB5:53173:炵 +CJK UNIFIED IDEOGRAPH:'CFB6:53174:炩 +CJK UNIFIED IDEOGRAPH:'CFB7:53175:牁 +CJK UNIFIED IDEOGRAPH:'CFB8:53176:牉 +CJK UNIFIED IDEOGRAPH:'CFB9:53177:牊 +CJK UNIFIED IDEOGRAPH:'CFBA:53178:牬 +CJK UNIFIED IDEOGRAPH:'CFBB:53179:牰 +CJK UNIFIED IDEOGRAPH:'CFBC:53180:牳 +CJK UNIFIED IDEOGRAPH:'CFBD:53181:牮 +CJK UNIFIED IDEOGRAPH:'CFBE:53182:狊 +CJK UNIFIED IDEOGRAPH:'CFBF:53183:狤 +CJK UNIFIED IDEOGRAPH:'CFC0:53184:狨 +CJK UNIFIED IDEOGRAPH:'CFC1:53185:狫 +CJK UNIFIED IDEOGRAPH:'CFC2:53186:狟 +CJK UNIFIED IDEOGRAPH:'CFC3:53187:狪 +CJK UNIFIED IDEOGRAPH:'CFC4:53188:狦 +CJK UNIFIED IDEOGRAPH:'CFC5:53189:狣 +CJK UNIFIED IDEOGRAPH:'CFC6:53190:玅 +CJK UNIFIED IDEOGRAPH:'CFC7:53191:珌 +CJK UNIFIED IDEOGRAPH:'CFC8:53192:珂 +CJK UNIFIED IDEOGRAPH:'CFC9:53193:珈 +CJK UNIFIED IDEOGRAPH:'CFCA:53194:珅 +CJK UNIFIED IDEOGRAPH:'CFCB:53195:玹 +CJK UNIFIED IDEOGRAPH:'CFCC:53196:玶 +CJK UNIFIED IDEOGRAPH:'CFCD:53197:玵 +CJK UNIFIED IDEOGRAPH:'CFCE:53198:玴 +CJK UNIFIED IDEOGRAPH:'CFCF:53199:珫 +CJK UNIFIED IDEOGRAPH:'CFD0:53200:玿 +CJK UNIFIED IDEOGRAPH:'CFD1:53201:珇 +CJK UNIFIED IDEOGRAPH:'CFD2:53202:玾 +CJK UNIFIED IDEOGRAPH:'CFD3:53203:珃 +CJK UNIFIED IDEOGRAPH:'CFD4:53204:珆 +CJK UNIFIED IDEOGRAPH:'CFD5:53205:玸 +CJK UNIFIED IDEOGRAPH:'CFD6:53206:珋 +CJK UNIFIED IDEOGRAPH:'CFD7:53207:瓬 +CJK UNIFIED IDEOGRAPH:'CFD8:53208:瓮 +CJK UNIFIED IDEOGRAPH:'CFD9:53209:甮 +CJK UNIFIED IDEOGRAPH:'CFDA:53210:畇 +CJK UNIFIED IDEOGRAPH:'CFDB:53211:畈 +CJK UNIFIED IDEOGRAPH:'CFDC:53212:疧 +CJK UNIFIED IDEOGRAPH:'CFDD:53213:疪 +CJK UNIFIED IDEOGRAPH:'CFDE:53214:癹 +CJK UNIFIED IDEOGRAPH:'CFDF:53215:盄 +CJK UNIFIED IDEOGRAPH:'CFE0:53216:眈 +CJK UNIFIED IDEOGRAPH:'CFE1:53217:眃 +CJK UNIFIED IDEOGRAPH:'CFE2:53218:眄 +CJK UNIFIED IDEOGRAPH:'CFE3:53219:眅 +CJK UNIFIED IDEOGRAPH:'CFE4:53220:眊 +CJK UNIFIED IDEOGRAPH:'CFE5:53221:盷 +CJK UNIFIED IDEOGRAPH:'CFE6:53222:盻 +CJK UNIFIED IDEOGRAPH:'CFE7:53223:盺 +CJK UNIFIED IDEOGRAPH:'CFE8:53224:矧 +CJK UNIFIED IDEOGRAPH:'CFE9:53225:矨 +CJK UNIFIED IDEOGRAPH:'CFEA:53226:砆 +CJK UNIFIED IDEOGRAPH:'CFEB:53227:砑 +CJK UNIFIED IDEOGRAPH:'CFEC:53228:砒 +CJK UNIFIED IDEOGRAPH:'CFED:53229:砅 +CJK UNIFIED IDEOGRAPH:'CFEE:53230:砐 +CJK UNIFIED IDEOGRAPH:'CFEF:53231:砏 +CJK UNIFIED IDEOGRAPH:'CFF0:53232:砎 +CJK UNIFIED IDEOGRAPH:'CFF1:53233:砉 +CJK UNIFIED IDEOGRAPH:'CFF2:53234:砃 +CJK UNIFIED IDEOGRAPH:'CFF3:53235:砓 +CJK UNIFIED IDEOGRAPH:'CFF4:53236:祊 +CJK UNIFIED IDEOGRAPH:'CFF5:53237:祌 +CJK UNIFIED IDEOGRAPH:'CFF6:53238:祋 +CJK UNIFIED IDEOGRAPH:'CFF7:53239:祅 +CJK UNIFIED IDEOGRAPH:'CFF8:53240:祄 +CJK UNIFIED IDEOGRAPH:'CFF9:53241:秕 +CJK UNIFIED IDEOGRAPH:'CFFA:53242:种 +CJK UNIFIED IDEOGRAPH:'CFFB:53243:秏 +CJK UNIFIED IDEOGRAPH:'CFFC:53244:秖 +CJK UNIFIED IDEOGRAPH:'CFFD:53245:秎 +CJK UNIFIED IDEOGRAPH:'CFFE:53246:窀 +CJK UNIFIED IDEOGRAPH:'D040:53312:穾 +CJK UNIFIED IDEOGRAPH:'D041:53313:竑 +CJK UNIFIED IDEOGRAPH:'D042:53314:笀 +CJK UNIFIED IDEOGRAPH:'D043:53315:笁 +CJK UNIFIED IDEOGRAPH:'D044:53316:籺 +CJK UNIFIED IDEOGRAPH:'D045:53317:籸 +CJK UNIFIED IDEOGRAPH:'D046:53318:籹 +CJK UNIFIED IDEOGRAPH:'D047:53319:籿 +CJK UNIFIED IDEOGRAPH:'D048:53320:粀 +CJK UNIFIED IDEOGRAPH:'D049:53321:粁 +CJK UNIFIED IDEOGRAPH:'D04A:53322:紃 +CJK UNIFIED IDEOGRAPH:'D04B:53323:紈 +CJK UNIFIED IDEOGRAPH:'D04C:53324:紁 +CJK UNIFIED IDEOGRAPH:'D04D:53325:罘 +CJK UNIFIED IDEOGRAPH:'D04E:53326:羑 +CJK UNIFIED IDEOGRAPH:'D04F:53327:羍 +CJK UNIFIED IDEOGRAPH:'D050:53328:羾 +CJK UNIFIED IDEOGRAPH:'D051:53329:耇 +CJK UNIFIED IDEOGRAPH:'D052:53330:耎 +CJK UNIFIED IDEOGRAPH:'D053:53331:耏 +CJK UNIFIED IDEOGRAPH:'D054:53332:耔 +CJK UNIFIED IDEOGRAPH:'D055:53333:耷 +CJK UNIFIED IDEOGRAPH:'D056:53334:胘 +CJK UNIFIED IDEOGRAPH:'D057:53335:胇 +CJK UNIFIED IDEOGRAPH:'D058:53336:胠 +CJK UNIFIED IDEOGRAPH:'D059:53337:胑 +CJK UNIFIED IDEOGRAPH:'D05A:53338:胈 +CJK UNIFIED IDEOGRAPH:'D05B:53339:胂 +CJK UNIFIED IDEOGRAPH:'D05C:53340:胐 +CJK UNIFIED IDEOGRAPH:'D05D:53341:胅 +CJK UNIFIED IDEOGRAPH:'D05E:53342:胣 +CJK UNIFIED IDEOGRAPH:'D05F:53343:胙 +CJK UNIFIED IDEOGRAPH:'D060:53344:胜 +CJK UNIFIED IDEOGRAPH:'D061:53345:胊 +CJK UNIFIED IDEOGRAPH:'D062:53346:胕 +CJK UNIFIED IDEOGRAPH:'D063:53347:胉 +CJK UNIFIED IDEOGRAPH:'D064:53348:胏 +CJK UNIFIED IDEOGRAPH:'D065:53349:胗 +CJK UNIFIED IDEOGRAPH:'D066:53350:胦 +CJK UNIFIED IDEOGRAPH:'D067:53351:胍 +CJK UNIFIED IDEOGRAPH:'D068:53352:臿 +CJK UNIFIED IDEOGRAPH:'D069:53353:舡 +CJK UNIFIED IDEOGRAPH:'D06A:53354:芔 +CJK UNIFIED IDEOGRAPH:'D06B:53355:苙 +CJK UNIFIED IDEOGRAPH:'D06C:53356:苾 +CJK UNIFIED IDEOGRAPH:'D06D:53357:苹 +CJK UNIFIED IDEOGRAPH:'D06E:53358:茇 +CJK UNIFIED IDEOGRAPH:'D06F:53359:苨 +CJK UNIFIED IDEOGRAPH:'D070:53360:茀 +CJK UNIFIED IDEOGRAPH:'D071:53361:苕 +CJK UNIFIED IDEOGRAPH:'D072:53362:茺 +CJK UNIFIED IDEOGRAPH:'D073:53363:苫 +CJK UNIFIED IDEOGRAPH:'D074:53364:苖 +CJK UNIFIED IDEOGRAPH:'D075:53365:苴 +CJK UNIFIED IDEOGRAPH:'D076:53366:苬 +CJK UNIFIED IDEOGRAPH:'D077:53367:苡 +CJK UNIFIED IDEOGRAPH:'D078:53368:苲 +CJK UNIFIED IDEOGRAPH:'D079:53369:苵 +CJK UNIFIED IDEOGRAPH:'D07A:53370:茌 +CJK UNIFIED IDEOGRAPH:'D07B:53371:苻 +CJK UNIFIED IDEOGRAPH:'D07C:53372:苶 +CJK UNIFIED IDEOGRAPH:'D07D:53373:苰 +CJK UNIFIED IDEOGRAPH:'D07E:53374:苪 +CJK UNIFIED IDEOGRAPH:'D0A1:53409:苤 +CJK UNIFIED IDEOGRAPH:'D0A2:53410:苠 +CJK UNIFIED IDEOGRAPH:'D0A3:53411:苺 +CJK UNIFIED IDEOGRAPH:'D0A4:53412:苳 +CJK UNIFIED IDEOGRAPH:'D0A5:53413:苭 +CJK UNIFIED IDEOGRAPH:'D0A6:53414:虷 +CJK UNIFIED IDEOGRAPH:'D0A7:53415:虴 +CJK UNIFIED IDEOGRAPH:'D0A8:53416:虼 +CJK UNIFIED IDEOGRAPH:'D0A9:53417:虳 +CJK UNIFIED IDEOGRAPH:'D0AA:53418:衁 +CJK UNIFIED IDEOGRAPH:'D0AB:53419:衎 +CJK UNIFIED IDEOGRAPH:'D0AC:53420:衧 +CJK UNIFIED IDEOGRAPH:'D0AD:53421:衪 +CJK UNIFIED IDEOGRAPH:'D0AE:53422:衩 +CJK UNIFIED IDEOGRAPH:'D0AF:53423:觓 +CJK UNIFIED IDEOGRAPH:'D0B0:53424:訄 +CJK UNIFIED IDEOGRAPH:'D0B1:53425:訇 +CJK UNIFIED IDEOGRAPH:'D0B2:53426:赲 +CJK UNIFIED IDEOGRAPH:'D0B3:53427:迣 +CJK UNIFIED IDEOGRAPH:'D0B4:53428:迡 +CJK UNIFIED IDEOGRAPH:'D0B5:53429:迮 +CJK UNIFIED IDEOGRAPH:'D0B6:53430:迠 +CJK UNIFIED IDEOGRAPH:'D0B7:53431:郱 +CJK UNIFIED IDEOGRAPH:'D0B8:53432:邽 +CJK UNIFIED IDEOGRAPH:'D0B9:53433:邿 +CJK UNIFIED IDEOGRAPH:'D0BA:53434:郕 +CJK UNIFIED IDEOGRAPH:'D0BB:53435:郅 +CJK UNIFIED IDEOGRAPH:'D0BC:53436:邾 +CJK UNIFIED IDEOGRAPH:'D0BD:53437:郇 +CJK UNIFIED IDEOGRAPH:'D0BE:53438:郋 +CJK UNIFIED IDEOGRAPH:'D0BF:53439:郈 +CJK UNIFIED IDEOGRAPH:'D0C0:53440:釔 +CJK UNIFIED IDEOGRAPH:'D0C1:53441:釓 +CJK UNIFIED IDEOGRAPH:'D0C2:53442:陔 +CJK UNIFIED IDEOGRAPH:'D0C3:53443:陏 +CJK UNIFIED IDEOGRAPH:'D0C4:53444:陑 +CJK UNIFIED IDEOGRAPH:'D0C5:53445:陓 +CJK UNIFIED IDEOGRAPH:'D0C6:53446:陊 +CJK UNIFIED IDEOGRAPH:'D0C7:53447:陎 +CJK UNIFIED IDEOGRAPH:'D0C8:53448:倞 +CJK UNIFIED IDEOGRAPH:'D0C9:53449:倅 +CJK UNIFIED IDEOGRAPH:'D0CA:53450:倇 +CJK UNIFIED IDEOGRAPH:'D0CB:53451:倓 +CJK UNIFIED IDEOGRAPH:'D0CC:53452:倢 +CJK UNIFIED IDEOGRAPH:'D0CD:53453:倰 +CJK UNIFIED IDEOGRAPH:'D0CE:53454:倛 +CJK UNIFIED IDEOGRAPH:'D0CF:53455:俵 +CJK UNIFIED IDEOGRAPH:'D0D0:53456:俴 +CJK UNIFIED IDEOGRAPH:'D0D1:53457:倳 +CJK UNIFIED IDEOGRAPH:'D0D2:53458:倷 +CJK UNIFIED IDEOGRAPH:'D0D3:53459:倬 +CJK UNIFIED IDEOGRAPH:'D0D4:53460:俶 +CJK UNIFIED IDEOGRAPH:'D0D5:53461:俷 +CJK UNIFIED IDEOGRAPH:'D0D6:53462:倗 +CJK UNIFIED IDEOGRAPH:'D0D7:53463:倜 +CJK UNIFIED IDEOGRAPH:'D0D8:53464:倠 +CJK UNIFIED IDEOGRAPH:'D0D9:53465:倧 +CJK UNIFIED IDEOGRAPH:'D0DA:53466:倵 +CJK UNIFIED IDEOGRAPH:'D0DB:53467:倯 +CJK UNIFIED IDEOGRAPH:'D0DC:53468:倱 +CJK UNIFIED IDEOGRAPH:'D0DD:53469:倎 +CJK UNIFIED IDEOGRAPH:'D0DE:53470:党 +CJK UNIFIED IDEOGRAPH:'D0DF:53471:冔 +CJK UNIFIED IDEOGRAPH:'D0E0:53472:冓 +CJK UNIFIED IDEOGRAPH:'D0E1:53473:凊 +CJK UNIFIED IDEOGRAPH:'D0E2:53474:凄 +CJK UNIFIED IDEOGRAPH:'D0E3:53475:凅 +CJK UNIFIED IDEOGRAPH:'D0E4:53476:凈 +CJK UNIFIED IDEOGRAPH:'D0E5:53477:凎 +CJK UNIFIED IDEOGRAPH:'D0E6:53478:剡 +CJK UNIFIED IDEOGRAPH:'D0E7:53479:剚 +CJK UNIFIED IDEOGRAPH:'D0E8:53480:剒 +CJK UNIFIED IDEOGRAPH:'D0E9:53481:剞 +CJK UNIFIED IDEOGRAPH:'D0EA:53482:剟 +CJK UNIFIED IDEOGRAPH:'D0EB:53483:剕 +CJK UNIFIED IDEOGRAPH:'D0EC:53484:剢 +CJK UNIFIED IDEOGRAPH:'D0ED:53485:勍 +CJK UNIFIED IDEOGRAPH:'D0EE:53486:匎 +CJK UNIFIED IDEOGRAPH:'D0EF:53487:厞 +CJK UNIFIED IDEOGRAPH:'D0F0:53488:唦 +CJK UNIFIED IDEOGRAPH:'D0F1:53489:哢 +CJK UNIFIED IDEOGRAPH:'D0F2:53490:唗 +CJK UNIFIED IDEOGRAPH:'D0F3:53491:唒 +CJK UNIFIED IDEOGRAPH:'D0F4:53492:哧 +CJK UNIFIED IDEOGRAPH:'D0F5:53493:哳 +CJK UNIFIED IDEOGRAPH:'D0F6:53494:哤 +CJK UNIFIED IDEOGRAPH:'D0F7:53495:唚 +CJK UNIFIED IDEOGRAPH:'D0F8:53496:哿 +CJK UNIFIED IDEOGRAPH:'D0F9:53497:唄 +CJK UNIFIED IDEOGRAPH:'D0FA:53498:唈 +CJK UNIFIED IDEOGRAPH:'D0FB:53499:哫 +CJK UNIFIED IDEOGRAPH:'D0FC:53500:唑 +CJK UNIFIED IDEOGRAPH:'D0FD:53501:唅 +CJK UNIFIED IDEOGRAPH:'D0FE:53502:哱 +CJK UNIFIED IDEOGRAPH:'D140:53568:唊 +CJK UNIFIED IDEOGRAPH:'D141:53569:哻 +CJK UNIFIED IDEOGRAPH:'D142:53570:哷 +CJK UNIFIED IDEOGRAPH:'D143:53571:哸 +CJK UNIFIED IDEOGRAPH:'D144:53572:哠 +CJK UNIFIED IDEOGRAPH:'D145:53573:唎 +CJK UNIFIED IDEOGRAPH:'D146:53574:唃 +CJK UNIFIED IDEOGRAPH:'D147:53575:唋 +CJK UNIFIED IDEOGRAPH:'D148:53576:圁 +CJK UNIFIED IDEOGRAPH:'D149:53577:圂 +CJK UNIFIED IDEOGRAPH:'D14A:53578:埌 +CJK UNIFIED IDEOGRAPH:'D14B:53579:堲 +CJK UNIFIED IDEOGRAPH:'D14C:53580:埕 +CJK UNIFIED IDEOGRAPH:'D14D:53581:埒 +CJK UNIFIED IDEOGRAPH:'D14E:53582:垺 +CJK UNIFIED IDEOGRAPH:'D14F:53583:埆 +CJK UNIFIED IDEOGRAPH:'D150:53584:垽 +CJK UNIFIED IDEOGRAPH:'D151:53585:垼 +CJK UNIFIED IDEOGRAPH:'D152:53586:垸 +CJK UNIFIED IDEOGRAPH:'D153:53587:垶 +CJK UNIFIED IDEOGRAPH:'D154:53588:垿 +CJK UNIFIED IDEOGRAPH:'D155:53589:埇 +CJK UNIFIED IDEOGRAPH:'D156:53590:埐 +CJK UNIFIED IDEOGRAPH:'D157:53591:垹 +CJK UNIFIED IDEOGRAPH:'D158:53592:埁 +CJK UNIFIED IDEOGRAPH:'D159:53593:夎 +CJK UNIFIED IDEOGRAPH:'D15A:53594:奊 +CJK UNIFIED IDEOGRAPH:'D15B:53595:娙 +CJK UNIFIED IDEOGRAPH:'D15C:53596:娖 +CJK UNIFIED IDEOGRAPH:'D15D:53597:娭 +CJK UNIFIED IDEOGRAPH:'D15E:53598:娮 +CJK UNIFIED IDEOGRAPH:'D15F:53599:娕 +CJK UNIFIED IDEOGRAPH:'D160:53600:娏 +CJK UNIFIED IDEOGRAPH:'D161:53601:娗 +CJK UNIFIED IDEOGRAPH:'D162:53602:娊 +CJK UNIFIED IDEOGRAPH:'D163:53603:娞 +CJK UNIFIED IDEOGRAPH:'D164:53604:娳 +CJK UNIFIED IDEOGRAPH:'D165:53605:孬 +CJK UNIFIED IDEOGRAPH:'D166:53606:宧 +CJK UNIFIED IDEOGRAPH:'D167:53607:宭 +CJK UNIFIED IDEOGRAPH:'D168:53608:宬 +CJK UNIFIED IDEOGRAPH:'D169:53609:尃 +CJK UNIFIED IDEOGRAPH:'D16A:53610:屖 +CJK UNIFIED IDEOGRAPH:'D16B:53611:屔 +CJK UNIFIED IDEOGRAPH:'D16C:53612:峬 +CJK UNIFIED IDEOGRAPH:'D16D:53613:峿 +CJK UNIFIED IDEOGRAPH:'D16E:53614:峮 +CJK UNIFIED IDEOGRAPH:'D16F:53615:峱 +CJK UNIFIED IDEOGRAPH:'D170:53616:峷 +CJK UNIFIED IDEOGRAPH:'D171:53617:崀 +CJK UNIFIED IDEOGRAPH:'D172:53618:峹 +CJK UNIFIED IDEOGRAPH:'D173:53619:帩 +CJK UNIFIED IDEOGRAPH:'D174:53620:帨 +CJK UNIFIED IDEOGRAPH:'D175:53621:庨 +CJK UNIFIED IDEOGRAPH:'D176:53622:庮 +CJK UNIFIED IDEOGRAPH:'D177:53623:庪 +CJK UNIFIED IDEOGRAPH:'D178:53624:庬 +CJK UNIFIED IDEOGRAPH:'D179:53625:弳 +CJK UNIFIED IDEOGRAPH:'D17A:53626:弰 +CJK UNIFIED IDEOGRAPH:'D17B:53627:彧 +CJK UNIFIED IDEOGRAPH:'D17C:53628:恝 +CJK UNIFIED IDEOGRAPH:'D17D:53629:恚 +CJK UNIFIED IDEOGRAPH:'D17E:53630:恧 +CJK UNIFIED IDEOGRAPH:'D1A1:53665:恁 +CJK UNIFIED IDEOGRAPH:'D1A2:53666:悢 +CJK UNIFIED IDEOGRAPH:'D1A3:53667:悈 +CJK UNIFIED IDEOGRAPH:'D1A4:53668:悀 +CJK UNIFIED IDEOGRAPH:'D1A5:53669:悒 +CJK UNIFIED IDEOGRAPH:'D1A6:53670:悁 +CJK UNIFIED IDEOGRAPH:'D1A7:53671:悝 +CJK UNIFIED IDEOGRAPH:'D1A8:53672:悃 +CJK UNIFIED IDEOGRAPH:'D1A9:53673:悕 +CJK UNIFIED IDEOGRAPH:'D1AA:53674:悛 +CJK UNIFIED IDEOGRAPH:'D1AB:53675:悗 +CJK UNIFIED IDEOGRAPH:'D1AC:53676:悇 +CJK UNIFIED IDEOGRAPH:'D1AD:53677:悜 +CJK UNIFIED IDEOGRAPH:'D1AE:53678:悎 +CJK UNIFIED IDEOGRAPH:'D1AF:53679:戙 +CJK UNIFIED IDEOGRAPH:'D1B0:53680:扆 +CJK UNIFIED IDEOGRAPH:'D1B1:53681:拲 +CJK UNIFIED IDEOGRAPH:'D1B2:53682:挐 +CJK UNIFIED IDEOGRAPH:'D1B3:53683:捖 +CJK UNIFIED IDEOGRAPH:'D1B4:53684:挬 +CJK UNIFIED IDEOGRAPH:'D1B5:53685:捄 +CJK UNIFIED IDEOGRAPH:'D1B6:53686:捅 +CJK UNIFIED IDEOGRAPH:'D1B7:53687:挶 +CJK UNIFIED IDEOGRAPH:'D1B8:53688:捃 +CJK UNIFIED IDEOGRAPH:'D1B9:53689:揤 +CJK UNIFIED IDEOGRAPH:'D1BA:53690:挹 +CJK UNIFIED IDEOGRAPH:'D1BB:53691:捋 +CJK UNIFIED IDEOGRAPH:'D1BC:53692:捊 +CJK UNIFIED IDEOGRAPH:'D1BD:53693:挼 +CJK UNIFIED IDEOGRAPH:'D1BE:53694:挩 +CJK UNIFIED IDEOGRAPH:'D1BF:53695:捁 +CJK UNIFIED IDEOGRAPH:'D1C0:53696:挴 +CJK UNIFIED IDEOGRAPH:'D1C1:53697:捘 +CJK UNIFIED IDEOGRAPH:'D1C2:53698:捔 +CJK UNIFIED IDEOGRAPH:'D1C3:53699:捙 +CJK UNIFIED IDEOGRAPH:'D1C4:53700:挭 +CJK UNIFIED IDEOGRAPH:'D1C5:53701:捇 +CJK UNIFIED IDEOGRAPH:'D1C6:53702:挳 +CJK UNIFIED IDEOGRAPH:'D1C7:53703:捚 +CJK UNIFIED IDEOGRAPH:'D1C8:53704:捑 +CJK UNIFIED IDEOGRAPH:'D1C9:53705:挸 +CJK UNIFIED IDEOGRAPH:'D1CA:53706:捗 +CJK UNIFIED IDEOGRAPH:'D1CB:53707:捀 +CJK UNIFIED IDEOGRAPH:'D1CC:53708:捈 +CJK UNIFIED IDEOGRAPH:'D1CD:53709:敊 +CJK UNIFIED IDEOGRAPH:'D1CE:53710:敆 +CJK UNIFIED IDEOGRAPH:'D1CF:53711:旆 +CJK UNIFIED IDEOGRAPH:'D1D0:53712:旃 +CJK UNIFIED IDEOGRAPH:'D1D1:53713:旄 +CJK UNIFIED IDEOGRAPH:'D1D2:53714:旂 +CJK UNIFIED IDEOGRAPH:'D1D3:53715:晊 +CJK UNIFIED IDEOGRAPH:'D1D4:53716:晟 +CJK UNIFIED IDEOGRAPH:'D1D5:53717:晇 +CJK UNIFIED IDEOGRAPH:'D1D6:53718:晑 +CJK UNIFIED IDEOGRAPH:'D1D7:53719:朒 +CJK UNIFIED IDEOGRAPH:'D1D8:53720:朓 +CJK UNIFIED IDEOGRAPH:'D1D9:53721:栟 +CJK UNIFIED IDEOGRAPH:'D1DA:53722:栚 +CJK UNIFIED IDEOGRAPH:'D1DB:53723:桉 +CJK UNIFIED IDEOGRAPH:'D1DC:53724:栲 +CJK UNIFIED IDEOGRAPH:'D1DD:53725:栳 +CJK UNIFIED IDEOGRAPH:'D1DE:53726:栻 +CJK UNIFIED IDEOGRAPH:'D1DF:53727:桋 +CJK UNIFIED IDEOGRAPH:'D1E0:53728:桏 +CJK UNIFIED IDEOGRAPH:'D1E1:53729:栖 +CJK UNIFIED IDEOGRAPH:'D1E2:53730:栱 +CJK UNIFIED IDEOGRAPH:'D1E3:53731:栜 +CJK UNIFIED IDEOGRAPH:'D1E4:53732:栵 +CJK UNIFIED IDEOGRAPH:'D1E5:53733:栫 +CJK UNIFIED IDEOGRAPH:'D1E6:53734:栭 +CJK UNIFIED IDEOGRAPH:'D1E7:53735:栯 +CJK UNIFIED IDEOGRAPH:'D1E8:53736:桎 +CJK UNIFIED IDEOGRAPH:'D1E9:53737:桄 +CJK UNIFIED IDEOGRAPH:'D1EA:53738:栴 +CJK UNIFIED IDEOGRAPH:'D1EB:53739:栝 +CJK UNIFIED IDEOGRAPH:'D1EC:53740:栒 +CJK UNIFIED IDEOGRAPH:'D1ED:53741:栔 +CJK UNIFIED IDEOGRAPH:'D1EE:53742:栦 +CJK UNIFIED IDEOGRAPH:'D1EF:53743:栨 +CJK UNIFIED IDEOGRAPH:'D1F0:53744:栮 +CJK UNIFIED IDEOGRAPH:'D1F1:53745:桍 +CJK UNIFIED IDEOGRAPH:'D1F2:53746:栺 +CJK UNIFIED IDEOGRAPH:'D1F3:53747:栥 +CJK UNIFIED IDEOGRAPH:'D1F4:53748:栠 +CJK UNIFIED IDEOGRAPH:'D1F5:53749:欬 +CJK UNIFIED IDEOGRAPH:'D1F6:53750:欯 +CJK UNIFIED IDEOGRAPH:'D1F7:53751:欭 +CJK UNIFIED IDEOGRAPH:'D1F8:53752:欱 +CJK UNIFIED IDEOGRAPH:'D1F9:53753:欴 +CJK UNIFIED IDEOGRAPH:'D1FA:53754:歭 +CJK UNIFIED IDEOGRAPH:'D1FB:53755:肂 +CJK UNIFIED IDEOGRAPH:'D1FC:53756:殈 +CJK UNIFIED IDEOGRAPH:'D1FD:53757:毦 +CJK UNIFIED IDEOGRAPH:'D1FE:53758:毤 +CJK UNIFIED IDEOGRAPH:'D240:53824:毨 +CJK UNIFIED IDEOGRAPH:'D241:53825:毣 +CJK UNIFIED IDEOGRAPH:'D242:53826:毢 +CJK UNIFIED IDEOGRAPH:'D243:53827:毧 +CJK UNIFIED IDEOGRAPH:'D244:53828:氥 +CJK UNIFIED IDEOGRAPH:'D245:53829:浺 +CJK UNIFIED IDEOGRAPH:'D246:53830:浣 +CJK UNIFIED IDEOGRAPH:'D247:53831:浤 +CJK UNIFIED IDEOGRAPH:'D248:53832:浶 +CJK UNIFIED IDEOGRAPH:'D249:53833:洍 +CJK UNIFIED IDEOGRAPH:'D24A:53834:浡 +CJK UNIFIED IDEOGRAPH:'D24B:53835:涒 +CJK UNIFIED IDEOGRAPH:'D24C:53836:浘 +CJK UNIFIED IDEOGRAPH:'D24D:53837:浢 +CJK UNIFIED IDEOGRAPH:'D24E:53838:浭 +CJK UNIFIED IDEOGRAPH:'D24F:53839:浯 +CJK UNIFIED IDEOGRAPH:'D250:53840:涑 +CJK UNIFIED IDEOGRAPH:'D251:53841:涍 +CJK UNIFIED IDEOGRAPH:'D252:53842:淯 +CJK UNIFIED IDEOGRAPH:'D253:53843:浿 +CJK UNIFIED IDEOGRAPH:'D254:53844:涆 +CJK UNIFIED IDEOGRAPH:'D255:53845:浞 +CJK UNIFIED IDEOGRAPH:'D256:53846:浧 +CJK UNIFIED IDEOGRAPH:'D257:53847:浠 +CJK UNIFIED IDEOGRAPH:'D258:53848:涗 +CJK UNIFIED IDEOGRAPH:'D259:53849:浰 +CJK UNIFIED IDEOGRAPH:'D25A:53850:浼 +CJK UNIFIED IDEOGRAPH:'D25B:53851:浟 +CJK UNIFIED IDEOGRAPH:'D25C:53852:涂 +CJK UNIFIED IDEOGRAPH:'D25D:53853:涘 +CJK UNIFIED IDEOGRAPH:'D25E:53854:洯 +CJK UNIFIED IDEOGRAPH:'D25F:53855:浨 +CJK UNIFIED IDEOGRAPH:'D260:53856:涋 +CJK UNIFIED IDEOGRAPH:'D261:53857:浾 +CJK UNIFIED IDEOGRAPH:'D262:53858:涀 +CJK UNIFIED IDEOGRAPH:'D263:53859:涄 +CJK UNIFIED IDEOGRAPH:'D264:53860:洖 +CJK UNIFIED IDEOGRAPH:'D265:53861:涃 +CJK UNIFIED IDEOGRAPH:'D266:53862:浻 +CJK UNIFIED IDEOGRAPH:'D267:53863:浽 +CJK UNIFIED IDEOGRAPH:'D268:53864:浵 +CJK UNIFIED IDEOGRAPH:'D269:53865:涐 +CJK UNIFIED IDEOGRAPH:'D26A:53866:烜 +CJK UNIFIED IDEOGRAPH:'D26B:53867:烓 +CJK UNIFIED IDEOGRAPH:'D26C:53868:烑 +CJK UNIFIED IDEOGRAPH:'D26D:53869:烝 +CJK UNIFIED IDEOGRAPH:'D26E:53870:烋 +CJK UNIFIED IDEOGRAPH:'D26F:53871:缹 +CJK UNIFIED IDEOGRAPH:'D270:53872:烢 +CJK UNIFIED IDEOGRAPH:'D271:53873:烗 +CJK UNIFIED IDEOGRAPH:'D272:53874:烒 +CJK UNIFIED IDEOGRAPH:'D273:53875:烞 +CJK UNIFIED IDEOGRAPH:'D274:53876:烠 +CJK UNIFIED IDEOGRAPH:'D275:53877:烔 +CJK UNIFIED IDEOGRAPH:'D276:53878:烍 +CJK UNIFIED IDEOGRAPH:'D277:53879:烅 +CJK UNIFIED IDEOGRAPH:'D278:53880:烆 +CJK UNIFIED IDEOGRAPH:'D279:53881:烇 +CJK UNIFIED IDEOGRAPH:'D27A:53882:烚 +CJK UNIFIED IDEOGRAPH:'D27B:53883:烎 +CJK UNIFIED IDEOGRAPH:'D27C:53884:烡 +CJK UNIFIED IDEOGRAPH:'D27D:53885:牂 +CJK UNIFIED IDEOGRAPH:'D27E:53886:牸 +CJK UNIFIED IDEOGRAPH:'D2A1:53921:牷 +CJK UNIFIED IDEOGRAPH:'D2A2:53922:牶 +CJK UNIFIED IDEOGRAPH:'D2A3:53923:猀 +CJK UNIFIED IDEOGRAPH:'D2A4:53924:狺 +CJK UNIFIED IDEOGRAPH:'D2A5:53925:狴 +CJK UNIFIED IDEOGRAPH:'D2A6:53926:狾 +CJK UNIFIED IDEOGRAPH:'D2A7:53927:狶 +CJK UNIFIED IDEOGRAPH:'D2A8:53928:狳 +CJK UNIFIED IDEOGRAPH:'D2A9:53929:狻 +CJK UNIFIED IDEOGRAPH:'D2AA:53930:猁 +CJK UNIFIED IDEOGRAPH:'D2AB:53931:珓 +CJK UNIFIED IDEOGRAPH:'D2AC:53932:珙 +CJK UNIFIED IDEOGRAPH:'D2AD:53933:珥 +CJK UNIFIED IDEOGRAPH:'D2AE:53934:珖 +CJK UNIFIED IDEOGRAPH:'D2AF:53935:玼 +CJK UNIFIED IDEOGRAPH:'D2B0:53936:珧 +CJK UNIFIED IDEOGRAPH:'D2B1:53937:珣 +CJK UNIFIED IDEOGRAPH:'D2B2:53938:珩 +CJK UNIFIED IDEOGRAPH:'D2B3:53939:珜 +CJK UNIFIED IDEOGRAPH:'D2B4:53940:珒 +CJK UNIFIED IDEOGRAPH:'D2B5:53941:珛 +CJK UNIFIED IDEOGRAPH:'D2B6:53942:珔 +CJK UNIFIED IDEOGRAPH:'D2B7:53943:珝 +CJK UNIFIED IDEOGRAPH:'D2B8:53944:珚 +CJK UNIFIED IDEOGRAPH:'D2B9:53945:珗 +CJK UNIFIED IDEOGRAPH:'D2BA:53946:珘 +CJK UNIFIED IDEOGRAPH:'D2BB:53947:珨 +CJK UNIFIED IDEOGRAPH:'D2BC:53948:瓞 +CJK UNIFIED IDEOGRAPH:'D2BD:53949:瓟 +CJK UNIFIED IDEOGRAPH:'D2BE:53950:瓴 +CJK UNIFIED IDEOGRAPH:'D2BF:53951:瓵 +CJK UNIFIED IDEOGRAPH:'D2C0:53952:甡 +CJK UNIFIED IDEOGRAPH:'D2C1:53953:畛 +CJK UNIFIED IDEOGRAPH:'D2C2:53954:畟 +CJK UNIFIED IDEOGRAPH:'D2C3:53955:疰 +CJK UNIFIED IDEOGRAPH:'D2C4:53956:痁 +CJK UNIFIED IDEOGRAPH:'D2C5:53957:疻 +CJK UNIFIED IDEOGRAPH:'D2C6:53958:痄 +CJK UNIFIED IDEOGRAPH:'D2C7:53959:痀 +CJK UNIFIED IDEOGRAPH:'D2C8:53960:疿 +CJK UNIFIED IDEOGRAPH:'D2C9:53961:疶 +CJK UNIFIED IDEOGRAPH:'D2CA:53962:疺 +CJK UNIFIED IDEOGRAPH:'D2CB:53963:皊 +CJK UNIFIED IDEOGRAPH:'D2CC:53964:盉 +CJK UNIFIED IDEOGRAPH:'D2CD:53965:眝 +CJK UNIFIED IDEOGRAPH:'D2CE:53966:眛 +CJK UNIFIED IDEOGRAPH:'D2CF:53967:眐 +CJK UNIFIED IDEOGRAPH:'D2D0:53968:眓 +CJK UNIFIED IDEOGRAPH:'D2D1:53969:眒 +CJK UNIFIED IDEOGRAPH:'D2D2:53970:眣 +CJK UNIFIED IDEOGRAPH:'D2D3:53971:眑 +CJK UNIFIED IDEOGRAPH:'D2D4:53972:眕 +CJK UNIFIED IDEOGRAPH:'D2D5:53973:眙 +CJK UNIFIED IDEOGRAPH:'D2D6:53974:眚 +CJK UNIFIED IDEOGRAPH:'D2D7:53975:眢 +CJK UNIFIED IDEOGRAPH:'D2D8:53976:眧 +CJK UNIFIED IDEOGRAPH:'D2D9:53977:砣 +CJK UNIFIED IDEOGRAPH:'D2DA:53978:砬 +CJK UNIFIED IDEOGRAPH:'D2DB:53979:砢 +CJK UNIFIED IDEOGRAPH:'D2DC:53980:砵 +CJK UNIFIED IDEOGRAPH:'D2DD:53981:砯 +CJK UNIFIED IDEOGRAPH:'D2DE:53982:砨 +CJK UNIFIED IDEOGRAPH:'D2DF:53983:砮 +CJK UNIFIED IDEOGRAPH:'D2E0:53984:砫 +CJK UNIFIED IDEOGRAPH:'D2E1:53985:砡 +CJK UNIFIED IDEOGRAPH:'D2E2:53986:砩 +CJK UNIFIED IDEOGRAPH:'D2E3:53987:砳 +CJK UNIFIED IDEOGRAPH:'D2E4:53988:砪 +CJK UNIFIED IDEOGRAPH:'D2E5:53989:砱 +CJK UNIFIED IDEOGRAPH:'D2E6:53990:祔 +CJK UNIFIED IDEOGRAPH:'D2E7:53991:祛 +CJK UNIFIED IDEOGRAPH:'D2E8:53992:祏 +CJK UNIFIED IDEOGRAPH:'D2E9:53993:祜 +CJK UNIFIED IDEOGRAPH:'D2EA:53994:祓 +CJK UNIFIED IDEOGRAPH:'D2EB:53995:祒 +CJK UNIFIED IDEOGRAPH:'D2EC:53996:祑 +CJK UNIFIED IDEOGRAPH:'D2ED:53997:秫 +CJK UNIFIED IDEOGRAPH:'D2EE:53998:秬 +CJK UNIFIED IDEOGRAPH:'D2EF:53999:秠 +CJK UNIFIED IDEOGRAPH:'D2F0:54000:秮 +CJK UNIFIED IDEOGRAPH:'D2F1:54001:秭 +CJK UNIFIED IDEOGRAPH:'D2F2:54002:秪 +CJK UNIFIED IDEOGRAPH:'D2F3:54003:秜 +CJK UNIFIED IDEOGRAPH:'D2F4:54004:秞 +CJK UNIFIED IDEOGRAPH:'D2F5:54005:秝 +CJK UNIFIED IDEOGRAPH:'D2F6:54006:窆 +CJK UNIFIED IDEOGRAPH:'D2F7:54007:窉 +CJK UNIFIED IDEOGRAPH:'D2F8:54008:窅 +CJK UNIFIED IDEOGRAPH:'D2F9:54009:窋 +CJK UNIFIED IDEOGRAPH:'D2FA:54010:窌 +CJK UNIFIED IDEOGRAPH:'D2FB:54011:窊 +CJK UNIFIED IDEOGRAPH:'D2FC:54012:窇 +CJK UNIFIED IDEOGRAPH:'D2FD:54013:竘 +CJK UNIFIED IDEOGRAPH:'D2FE:54014:笐 +CJK UNIFIED IDEOGRAPH:'D340:54080:笄 +CJK UNIFIED IDEOGRAPH:'D341:54081:笓 +CJK UNIFIED IDEOGRAPH:'D342:54082:笅 +CJK UNIFIED IDEOGRAPH:'D343:54083:笏 +CJK UNIFIED IDEOGRAPH:'D344:54084:笈 +CJK UNIFIED IDEOGRAPH:'D345:54085:笊 +CJK UNIFIED IDEOGRAPH:'D346:54086:笎 +CJK UNIFIED IDEOGRAPH:'D347:54087:笉 +CJK UNIFIED IDEOGRAPH:'D348:54088:笒 +CJK UNIFIED IDEOGRAPH:'D349:54089:粄 +CJK UNIFIED IDEOGRAPH:'D34A:54090:粑 +CJK UNIFIED IDEOGRAPH:'D34B:54091:粊 +CJK UNIFIED IDEOGRAPH:'D34C:54092:粌 +CJK UNIFIED IDEOGRAPH:'D34D:54093:粈 +CJK UNIFIED IDEOGRAPH:'D34E:54094:粍 +CJK UNIFIED IDEOGRAPH:'D34F:54095:粅 +CJK UNIFIED IDEOGRAPH:'D350:54096:紞 +CJK UNIFIED IDEOGRAPH:'D351:54097:紝 +CJK UNIFIED IDEOGRAPH:'D352:54098:紑 +CJK UNIFIED IDEOGRAPH:'D353:54099:紎 +CJK UNIFIED IDEOGRAPH:'D354:54100:紘 +CJK UNIFIED IDEOGRAPH:'D355:54101:紖 +CJK UNIFIED IDEOGRAPH:'D356:54102:紓 +CJK UNIFIED IDEOGRAPH:'D357:54103:紟 +CJK UNIFIED IDEOGRAPH:'D358:54104:紒 +CJK UNIFIED IDEOGRAPH:'D359:54105:紏 +CJK UNIFIED IDEOGRAPH:'D35A:54106:紌 +CJK UNIFIED IDEOGRAPH:'D35B:54107:罜 +CJK UNIFIED IDEOGRAPH:'D35C:54108:罡 +CJK UNIFIED IDEOGRAPH:'D35D:54109:罞 +CJK UNIFIED IDEOGRAPH:'D35E:54110:罠 +CJK UNIFIED IDEOGRAPH:'D35F:54111:罝 +CJK UNIFIED IDEOGRAPH:'D360:54112:罛 +CJK UNIFIED IDEOGRAPH:'D361:54113:羖 +CJK UNIFIED IDEOGRAPH:'D362:54114:羒 +CJK UNIFIED IDEOGRAPH:'D363:54115:翃 +CJK UNIFIED IDEOGRAPH:'D364:54116:翂 +CJK UNIFIED IDEOGRAPH:'D365:54117:翀 +CJK UNIFIED IDEOGRAPH:'D366:54118:耖 +CJK UNIFIED IDEOGRAPH:'D367:54119:耾 +CJK UNIFIED IDEOGRAPH:'D368:54120:耹 +CJK UNIFIED IDEOGRAPH:'D369:54121:胺 +CJK UNIFIED IDEOGRAPH:'D36A:54122:胲 +CJK UNIFIED IDEOGRAPH:'D36B:54123:胹 +CJK UNIFIED IDEOGRAPH:'D36C:54124:胵 +CJK UNIFIED IDEOGRAPH:'D36D:54125:脁 +CJK UNIFIED IDEOGRAPH:'D36E:54126:胻 +CJK UNIFIED IDEOGRAPH:'D36F:54127:脀 +CJK UNIFIED IDEOGRAPH:'D370:54128:舁 +CJK UNIFIED IDEOGRAPH:'D371:54129:舯 +CJK UNIFIED IDEOGRAPH:'D372:54130:舥 +CJK UNIFIED IDEOGRAPH:'D373:54131:茳 +CJK UNIFIED IDEOGRAPH:'D374:54132:茭 +CJK UNIFIED IDEOGRAPH:'D375:54133:荄 +CJK UNIFIED IDEOGRAPH:'D376:54134:茙 +CJK UNIFIED IDEOGRAPH:'D377:54135:荑 +CJK UNIFIED IDEOGRAPH:'D378:54136:茥 +CJK UNIFIED IDEOGRAPH:'D379:54137:荖 +CJK UNIFIED IDEOGRAPH:'D37A:54138:茿 +CJK UNIFIED IDEOGRAPH:'D37B:54139:荁 +CJK UNIFIED IDEOGRAPH:'D37C:54140:茦 +CJK UNIFIED IDEOGRAPH:'D37D:54141:茜 +CJK UNIFIED IDEOGRAPH:'D37E:54142:茢 +CJK UNIFIED IDEOGRAPH:'D3A1:54177:荂 +CJK UNIFIED IDEOGRAPH:'D3A2:54178:荎 +CJK UNIFIED IDEOGRAPH:'D3A3:54179:茛 +CJK UNIFIED IDEOGRAPH:'D3A4:54180:茪 +CJK UNIFIED IDEOGRAPH:'D3A5:54181:茈 +CJK UNIFIED IDEOGRAPH:'D3A6:54182:茼 +CJK UNIFIED IDEOGRAPH:'D3A7:54183:荍 +CJK UNIFIED IDEOGRAPH:'D3A8:54184:茖 +CJK UNIFIED IDEOGRAPH:'D3A9:54185:茤 +CJK UNIFIED IDEOGRAPH:'D3AA:54186:茠 +CJK UNIFIED IDEOGRAPH:'D3AB:54187:茷 +CJK UNIFIED IDEOGRAPH:'D3AC:54188:茯 +CJK UNIFIED IDEOGRAPH:'D3AD:54189:茩 +CJK UNIFIED IDEOGRAPH:'D3AE:54190:荇 +CJK UNIFIED IDEOGRAPH:'D3AF:54191:荅 +CJK UNIFIED IDEOGRAPH:'D3B0:54192:荌 +CJK UNIFIED IDEOGRAPH:'D3B1:54193:荓 +CJK UNIFIED IDEOGRAPH:'D3B2:54194:茞 +CJK UNIFIED IDEOGRAPH:'D3B3:54195:茬 +CJK UNIFIED IDEOGRAPH:'D3B4:54196:荋 +CJK UNIFIED IDEOGRAPH:'D3B5:54197:茧 +CJK UNIFIED IDEOGRAPH:'D3B6:54198:荈 +CJK UNIFIED IDEOGRAPH:'D3B7:54199:虓 +CJK UNIFIED IDEOGRAPH:'D3B8:54200:虒 +CJK UNIFIED IDEOGRAPH:'D3B9:54201:蚢 +CJK UNIFIED IDEOGRAPH:'D3BA:54202:蚨 +CJK UNIFIED IDEOGRAPH:'D3BB:54203:蚖 +CJK UNIFIED IDEOGRAPH:'D3BC:54204:蚍 +CJK UNIFIED IDEOGRAPH:'D3BD:54205:蚑 +CJK UNIFIED IDEOGRAPH:'D3BE:54206:蚞 +CJK UNIFIED IDEOGRAPH:'D3BF:54207:蚇 +CJK UNIFIED IDEOGRAPH:'D3C0:54208:蚗 +CJK UNIFIED IDEOGRAPH:'D3C1:54209:蚆 +CJK UNIFIED IDEOGRAPH:'D3C2:54210:蚋 +CJK UNIFIED IDEOGRAPH:'D3C3:54211:蚚 +CJK UNIFIED IDEOGRAPH:'D3C4:54212:蚅 +CJK UNIFIED IDEOGRAPH:'D3C5:54213:蚥 +CJK UNIFIED IDEOGRAPH:'D3C6:54214:蚙 +CJK UNIFIED IDEOGRAPH:'D3C7:54215:蚡 +CJK UNIFIED IDEOGRAPH:'D3C8:54216:蚧 +CJK UNIFIED IDEOGRAPH:'D3C9:54217:蚕 +CJK UNIFIED IDEOGRAPH:'D3CA:54218:蚘 +CJK UNIFIED IDEOGRAPH:'D3CB:54219:蚎 +CJK UNIFIED IDEOGRAPH:'D3CC:54220:蚝 +CJK UNIFIED IDEOGRAPH:'D3CD:54221:蚐 +CJK UNIFIED IDEOGRAPH:'D3CE:54222:蚔 +CJK UNIFIED IDEOGRAPH:'D3CF:54223:衃 +CJK UNIFIED IDEOGRAPH:'D3D0:54224:衄 +CJK UNIFIED IDEOGRAPH:'D3D1:54225:衭 +CJK UNIFIED IDEOGRAPH:'D3D2:54226:衵 +CJK UNIFIED IDEOGRAPH:'D3D3:54227:衶 +CJK UNIFIED IDEOGRAPH:'D3D4:54228:衲 +CJK UNIFIED IDEOGRAPH:'D3D5:54229:袀 +CJK UNIFIED IDEOGRAPH:'D3D6:54230:衱 +CJK UNIFIED IDEOGRAPH:'D3D7:54231:衿 +CJK UNIFIED IDEOGRAPH:'D3D8:54232:衯 +CJK UNIFIED IDEOGRAPH:'D3D9:54233:袃 +CJK UNIFIED IDEOGRAPH:'D3DA:54234:衾 +CJK UNIFIED IDEOGRAPH:'D3DB:54235:衴 +CJK UNIFIED IDEOGRAPH:'D3DC:54236:衼 +CJK UNIFIED IDEOGRAPH:'D3DD:54237:訒 +CJK UNIFIED IDEOGRAPH:'D3DE:54238:豇 +CJK UNIFIED IDEOGRAPH:'D3DF:54239:豗 +CJK UNIFIED IDEOGRAPH:'D3E0:54240:豻 +CJK UNIFIED IDEOGRAPH:'D3E1:54241:貤 +CJK UNIFIED IDEOGRAPH:'D3E2:54242:貣 +CJK UNIFIED IDEOGRAPH:'D3E3:54243:赶 +CJK UNIFIED IDEOGRAPH:'D3E4:54244:赸 +CJK UNIFIED IDEOGRAPH:'D3E5:54245:趵 +CJK UNIFIED IDEOGRAPH:'D3E6:54246:趷 +CJK UNIFIED IDEOGRAPH:'D3E7:54247:趶 +CJK UNIFIED IDEOGRAPH:'D3E8:54248:軑 +CJK UNIFIED IDEOGRAPH:'D3E9:54249:軓 +CJK UNIFIED IDEOGRAPH:'D3EA:54250:迾 +CJK UNIFIED IDEOGRAPH:'D3EB:54251:迵 +CJK UNIFIED IDEOGRAPH:'D3EC:54252:适 +CJK UNIFIED IDEOGRAPH:'D3ED:54253:迿 +CJK UNIFIED IDEOGRAPH:'D3EE:54254:迻 +CJK UNIFIED IDEOGRAPH:'D3EF:54255:逄 +CJK UNIFIED IDEOGRAPH:'D3F0:54256:迼 +CJK UNIFIED IDEOGRAPH:'D3F1:54257:迶 +CJK UNIFIED IDEOGRAPH:'D3F2:54258:郖 +CJK UNIFIED IDEOGRAPH:'D3F3:54259:郠 +CJK UNIFIED IDEOGRAPH:'D3F4:54260:郙 +CJK UNIFIED IDEOGRAPH:'D3F5:54261:郚 +CJK UNIFIED IDEOGRAPH:'D3F6:54262:郣 +CJK UNIFIED IDEOGRAPH:'D3F7:54263:郟 +CJK UNIFIED IDEOGRAPH:'D3F8:54264:郥 +CJK UNIFIED IDEOGRAPH:'D3F9:54265:郘 +CJK UNIFIED IDEOGRAPH:'D3FA:54266:郛 +CJK UNIFIED IDEOGRAPH:'D3FB:54267:郗 +CJK UNIFIED IDEOGRAPH:'D3FC:54268:郜 +CJK UNIFIED IDEOGRAPH:'D3FD:54269:郤 +CJK UNIFIED IDEOGRAPH:'D3FE:54270:酐 +CJK UNIFIED IDEOGRAPH:'D440:54336:酎 +CJK UNIFIED IDEOGRAPH:'D441:54337:酏 +CJK UNIFIED IDEOGRAPH:'D442:54338:釕 +CJK UNIFIED IDEOGRAPH:'D443:54339:釢 +CJK UNIFIED IDEOGRAPH:'D444:54340:釚 +CJK UNIFIED IDEOGRAPH:'D445:54341:陜 +CJK UNIFIED IDEOGRAPH:'D446:54342:陟 +CJK UNIFIED IDEOGRAPH:'D447:54343:隼 +CJK UNIFIED IDEOGRAPH:'D448:54344:飣 +CJK UNIFIED IDEOGRAPH:'D449:54345:髟 +CJK UNIFIED IDEOGRAPH:'D44A:54346:鬯 +CJK UNIFIED IDEOGRAPH:'D44B:54347:乿 +CJK UNIFIED IDEOGRAPH:'D44C:54348:偰 +CJK UNIFIED IDEOGRAPH:'D44D:54349:偪 +CJK UNIFIED IDEOGRAPH:'D44E:54350:偡 +CJK UNIFIED IDEOGRAPH:'D44F:54351:偞 +CJK UNIFIED IDEOGRAPH:'D450:54352:偠 +CJK UNIFIED IDEOGRAPH:'D451:54353:偓 +CJK UNIFIED IDEOGRAPH:'D452:54354:偋 +CJK UNIFIED IDEOGRAPH:'D453:54355:偝 +CJK UNIFIED IDEOGRAPH:'D454:54356:偲 +CJK UNIFIED IDEOGRAPH:'D455:54357:偈 +CJK UNIFIED IDEOGRAPH:'D456:54358:偍 +CJK UNIFIED IDEOGRAPH:'D457:54359:偁 +CJK UNIFIED IDEOGRAPH:'D458:54360:偛 +CJK UNIFIED IDEOGRAPH:'D459:54361:偊 +CJK UNIFIED IDEOGRAPH:'D45A:54362:偢 +CJK UNIFIED IDEOGRAPH:'D45B:54363:倕 +CJK UNIFIED IDEOGRAPH:'D45C:54364:偅 +CJK UNIFIED IDEOGRAPH:'D45D:54365:偟 +CJK UNIFIED IDEOGRAPH:'D45E:54366:偩 +CJK UNIFIED IDEOGRAPH:'D45F:54367:偫 +CJK UNIFIED IDEOGRAPH:'D460:54368:偣 +CJK UNIFIED IDEOGRAPH:'D461:54369:偤 +CJK UNIFIED IDEOGRAPH:'D462:54370:偆 +CJK UNIFIED IDEOGRAPH:'D463:54371:偀 +CJK UNIFIED IDEOGRAPH:'D464:54372:偮 +CJK UNIFIED IDEOGRAPH:'D465:54373:偳 +CJK UNIFIED IDEOGRAPH:'D466:54374:偗 +CJK UNIFIED IDEOGRAPH:'D467:54375:偑 +CJK UNIFIED IDEOGRAPH:'D468:54376:凐 +CJK UNIFIED IDEOGRAPH:'D469:54377:剫 +CJK UNIFIED IDEOGRAPH:'D46A:54378:剭 +CJK UNIFIED IDEOGRAPH:'D46B:54379:剬 +CJK UNIFIED IDEOGRAPH:'D46C:54380:剮 +CJK UNIFIED IDEOGRAPH:'D46D:54381:勖 +CJK UNIFIED IDEOGRAPH:'D46E:54382:勓 +CJK UNIFIED IDEOGRAPH:'D46F:54383:匭 +CJK UNIFIED IDEOGRAPH:'D470:54384:厜 +CJK UNIFIED IDEOGRAPH:'D471:54385:啵 +CJK UNIFIED IDEOGRAPH:'D472:54386:啶 +CJK UNIFIED IDEOGRAPH:'D473:54387:唼 +CJK UNIFIED IDEOGRAPH:'D474:54388:啍 +CJK UNIFIED IDEOGRAPH:'D475:54389:啐 +CJK UNIFIED IDEOGRAPH:'D476:54390:唴 +CJK UNIFIED IDEOGRAPH:'D477:54391:唪 +CJK UNIFIED IDEOGRAPH:'D478:54392:啑 +CJK UNIFIED IDEOGRAPH:'D479:54393:啢 +CJK UNIFIED IDEOGRAPH:'D47A:54394:唶 +CJK UNIFIED IDEOGRAPH:'D47B:54395:唵 +CJK UNIFIED IDEOGRAPH:'D47C:54396:唰 +CJK UNIFIED IDEOGRAPH:'D47D:54397:啒 +CJK UNIFIED IDEOGRAPH:'D47E:54398:啅 +CJK UNIFIED IDEOGRAPH:'D4A1:54433:唌 +CJK UNIFIED IDEOGRAPH:'D4A2:54434:唲 +CJK UNIFIED IDEOGRAPH:'D4A3:54435:啥 +CJK UNIFIED IDEOGRAPH:'D4A4:54436:啎 +CJK UNIFIED IDEOGRAPH:'D4A5:54437:唹 +CJK UNIFIED IDEOGRAPH:'D4A6:54438:啈 +CJK UNIFIED IDEOGRAPH:'D4A7:54439:唭 +CJK UNIFIED IDEOGRAPH:'D4A8:54440:唻 +CJK UNIFIED IDEOGRAPH:'D4A9:54441:啀 +CJK UNIFIED IDEOGRAPH:'D4AA:54442:啋 +CJK UNIFIED IDEOGRAPH:'D4AB:54443:圊 +CJK UNIFIED IDEOGRAPH:'D4AC:54444:圇 +CJK UNIFIED IDEOGRAPH:'D4AD:54445:埻 +CJK UNIFIED IDEOGRAPH:'D4AE:54446:堔 +CJK UNIFIED IDEOGRAPH:'D4AF:54447:埢 +CJK UNIFIED IDEOGRAPH:'D4B0:54448:埶 +CJK UNIFIED IDEOGRAPH:'D4B1:54449:埜 +CJK UNIFIED IDEOGRAPH:'D4B2:54450:埴 +CJK UNIFIED IDEOGRAPH:'D4B3:54451:堀 +CJK UNIFIED IDEOGRAPH:'D4B4:54452:埭 +CJK UNIFIED IDEOGRAPH:'D4B5:54453:埽 +CJK UNIFIED IDEOGRAPH:'D4B6:54454:堈 +CJK UNIFIED IDEOGRAPH:'D4B7:54455:埸 +CJK UNIFIED IDEOGRAPH:'D4B8:54456:堋 +CJK UNIFIED IDEOGRAPH:'D4B9:54457:埳 +CJK UNIFIED IDEOGRAPH:'D4BA:54458:埏 +CJK UNIFIED IDEOGRAPH:'D4BB:54459:堇 +CJK UNIFIED IDEOGRAPH:'D4BC:54460:埮 +CJK UNIFIED IDEOGRAPH:'D4BD:54461:埣 +CJK UNIFIED IDEOGRAPH:'D4BE:54462:埲 +CJK UNIFIED IDEOGRAPH:'D4BF:54463:埥 +CJK UNIFIED IDEOGRAPH:'D4C0:54464:埬 +CJK UNIFIED IDEOGRAPH:'D4C1:54465:埡 +CJK UNIFIED IDEOGRAPH:'D4C2:54466:堎 +CJK UNIFIED IDEOGRAPH:'D4C3:54467:埼 +CJK UNIFIED IDEOGRAPH:'D4C4:54468:堐 +CJK UNIFIED IDEOGRAPH:'D4C5:54469:埧 +CJK UNIFIED IDEOGRAPH:'D4C6:54470:堁 +CJK UNIFIED IDEOGRAPH:'D4C7:54471:堌 +CJK UNIFIED IDEOGRAPH:'D4C8:54472:埱 +CJK UNIFIED IDEOGRAPH:'D4C9:54473:埩 +CJK UNIFIED IDEOGRAPH:'D4CA:54474:埰 +CJK UNIFIED IDEOGRAPH:'D4CB:54475:堍 +CJK UNIFIED IDEOGRAPH:'D4CC:54476:堄 +CJK UNIFIED IDEOGRAPH:'D4CD:54477:奜 +CJK UNIFIED IDEOGRAPH:'D4CE:54478:婠 +CJK UNIFIED IDEOGRAPH:'D4CF:54479:婘 +CJK UNIFIED IDEOGRAPH:'D4D0:54480:婕 +CJK UNIFIED IDEOGRAPH:'D4D1:54481:婧 +CJK UNIFIED IDEOGRAPH:'D4D2:54482:婞 +CJK UNIFIED IDEOGRAPH:'D4D3:54483:娸 +CJK UNIFIED IDEOGRAPH:'D4D4:54484:娵 +CJK UNIFIED IDEOGRAPH:'D4D5:54485:婭 +CJK UNIFIED IDEOGRAPH:'D4D6:54486:婐 +CJK UNIFIED IDEOGRAPH:'D4D7:54487:婟 +CJK UNIFIED IDEOGRAPH:'D4D8:54488:婥 +CJK UNIFIED IDEOGRAPH:'D4D9:54489:婬 +CJK UNIFIED IDEOGRAPH:'D4DA:54490:婓 +CJK UNIFIED IDEOGRAPH:'D4DB:54491:婤 +CJK UNIFIED IDEOGRAPH:'D4DC:54492:婗 +CJK UNIFIED IDEOGRAPH:'D4DD:54493:婃 +CJK UNIFIED IDEOGRAPH:'D4DE:54494:婝 +CJK UNIFIED IDEOGRAPH:'D4DF:54495:婒 +CJK UNIFIED IDEOGRAPH:'D4E0:54496:婄 +CJK UNIFIED IDEOGRAPH:'D4E1:54497:婛 +CJK UNIFIED IDEOGRAPH:'D4E2:54498:婈 +CJK UNIFIED IDEOGRAPH:'D4E3:54499:媎 +CJK UNIFIED IDEOGRAPH:'D4E4:54500:娾 +CJK UNIFIED IDEOGRAPH:'D4E5:54501:婍 +CJK UNIFIED IDEOGRAPH:'D4E6:54502:娹 +CJK UNIFIED IDEOGRAPH:'D4E7:54503:婌 +CJK UNIFIED IDEOGRAPH:'D4E8:54504:婰 +CJK UNIFIED IDEOGRAPH:'D4E9:54505:婩 +CJK UNIFIED IDEOGRAPH:'D4EA:54506:婇 +CJK UNIFIED IDEOGRAPH:'D4EB:54507:婑 +CJK UNIFIED IDEOGRAPH:'D4EC:54508:婖 +CJK UNIFIED IDEOGRAPH:'D4ED:54509:婂 +CJK UNIFIED IDEOGRAPH:'D4EE:54510:婜 +CJK UNIFIED IDEOGRAPH:'D4EF:54511:孲 +CJK UNIFIED IDEOGRAPH:'D4F0:54512:孮 +CJK UNIFIED IDEOGRAPH:'D4F1:54513:寁 +CJK UNIFIED IDEOGRAPH:'D4F2:54514:寀 +CJK UNIFIED IDEOGRAPH:'D4F3:54515:屙 +CJK UNIFIED IDEOGRAPH:'D4F4:54516:崞 +CJK UNIFIED IDEOGRAPH:'D4F5:54517:崋 +CJK UNIFIED IDEOGRAPH:'D4F6:54518:崝 +CJK UNIFIED IDEOGRAPH:'D4F7:54519:崚 +CJK UNIFIED IDEOGRAPH:'D4F8:54520:崠 +CJK UNIFIED IDEOGRAPH:'D4F9:54521:崌 +CJK UNIFIED IDEOGRAPH:'D4FA:54522:崨 +CJK UNIFIED IDEOGRAPH:'D4FB:54523:崍 +CJK UNIFIED IDEOGRAPH:'D4FC:54524:崦 +CJK UNIFIED IDEOGRAPH:'D4FD:54525:崥 +CJK UNIFIED IDEOGRAPH:'D4FE:54526:崏 +CJK UNIFIED IDEOGRAPH:'D540:54592:崰 +CJK UNIFIED IDEOGRAPH:'D541:54593:崒 +CJK UNIFIED IDEOGRAPH:'D542:54594:崣 +CJK UNIFIED IDEOGRAPH:'D543:54595:崟 +CJK UNIFIED IDEOGRAPH:'D544:54596:崮 +CJK UNIFIED IDEOGRAPH:'D545:54597:帾 +CJK UNIFIED IDEOGRAPH:'D546:54598:帴 +CJK UNIFIED IDEOGRAPH:'D547:54599:庱 +CJK UNIFIED IDEOGRAPH:'D548:54600:庴 +CJK UNIFIED IDEOGRAPH:'D549:54601:庹 +CJK UNIFIED IDEOGRAPH:'D54A:54602:庲 +CJK UNIFIED IDEOGRAPH:'D54B:54603:庳 +CJK UNIFIED IDEOGRAPH:'D54C:54604:弶 +CJK UNIFIED IDEOGRAPH:'D54D:54605:弸 +CJK UNIFIED IDEOGRAPH:'D54E:54606:徛 +CJK UNIFIED IDEOGRAPH:'D54F:54607:徖 +CJK UNIFIED IDEOGRAPH:'D550:54608:徟 +CJK UNIFIED IDEOGRAPH:'D551:54609:悊 +CJK UNIFIED IDEOGRAPH:'D552:54610:悐 +CJK UNIFIED IDEOGRAPH:'D553:54611:悆 +CJK UNIFIED IDEOGRAPH:'D554:54612:悾 +CJK UNIFIED IDEOGRAPH:'D555:54613:悰 +CJK UNIFIED IDEOGRAPH:'D556:54614:悺 +CJK UNIFIED IDEOGRAPH:'D557:54615:惓 +CJK UNIFIED IDEOGRAPH:'D558:54616:惔 +CJK UNIFIED IDEOGRAPH:'D559:54617:惏 +CJK UNIFIED IDEOGRAPH:'D55A:54618:惤 +CJK UNIFIED IDEOGRAPH:'D55B:54619:惙 +CJK UNIFIED IDEOGRAPH:'D55C:54620:惝 +CJK UNIFIED IDEOGRAPH:'D55D:54621:惈 +CJK UNIFIED IDEOGRAPH:'D55E:54622:悱 +CJK UNIFIED IDEOGRAPH:'D55F:54623:惛 +CJK UNIFIED IDEOGRAPH:'D560:54624:悷 +CJK UNIFIED IDEOGRAPH:'D561:54625:惊 +CJK UNIFIED IDEOGRAPH:'D562:54626:悿 +CJK UNIFIED IDEOGRAPH:'D563:54627:惃 +CJK UNIFIED IDEOGRAPH:'D564:54628:惍 +CJK UNIFIED IDEOGRAPH:'D565:54629:惀 +CJK UNIFIED IDEOGRAPH:'D566:54630:挲 +CJK UNIFIED IDEOGRAPH:'D567:54631:捥 +CJK UNIFIED IDEOGRAPH:'D568:54632:掊 +CJK UNIFIED IDEOGRAPH:'D569:54633:掂 +CJK UNIFIED IDEOGRAPH:'D56A:54634:捽 +CJK UNIFIED IDEOGRAPH:'D56B:54635:掽 +CJK UNIFIED IDEOGRAPH:'D56C:54636:掞 +CJK UNIFIED IDEOGRAPH:'D56D:54637:掭 +CJK UNIFIED IDEOGRAPH:'D56E:54638:掝 +CJK UNIFIED IDEOGRAPH:'D56F:54639:掗 +CJK UNIFIED IDEOGRAPH:'D570:54640:掫 +CJK UNIFIED IDEOGRAPH:'D571:54641:掎 +CJK UNIFIED IDEOGRAPH:'D572:54642:捯 +CJK UNIFIED IDEOGRAPH:'D573:54643:掇 +CJK UNIFIED IDEOGRAPH:'D574:54644:掐 +CJK UNIFIED IDEOGRAPH:'D575:54645:据 +CJK UNIFIED IDEOGRAPH:'D576:54646:掯 +CJK UNIFIED IDEOGRAPH:'D577:54647:捵 +CJK UNIFIED IDEOGRAPH:'D578:54648:掜 +CJK UNIFIED IDEOGRAPH:'D579:54649:捭 +CJK UNIFIED IDEOGRAPH:'D57A:54650:掮 +CJK UNIFIED IDEOGRAPH:'D57B:54651:捼 +CJK UNIFIED IDEOGRAPH:'D57C:54652:掤 +CJK UNIFIED IDEOGRAPH:'D57D:54653:挻 +CJK UNIFIED IDEOGRAPH:'D57E:54654:掟 +CJK UNIFIED IDEOGRAPH:'D5A1:54689:捸 +CJK UNIFIED IDEOGRAPH:'D5A2:54690:掅 +CJK UNIFIED IDEOGRAPH:'D5A3:54691:掁 +CJK UNIFIED IDEOGRAPH:'D5A4:54692:掑 +CJK UNIFIED IDEOGRAPH:'D5A5:54693:掍 +CJK UNIFIED IDEOGRAPH:'D5A6:54694:捰 +CJK UNIFIED IDEOGRAPH:'D5A7:54695:敓 +CJK UNIFIED IDEOGRAPH:'D5A8:54696:旍 +CJK UNIFIED IDEOGRAPH:'D5A9:54697:晥 +CJK UNIFIED IDEOGRAPH:'D5AA:54698:晡 +CJK UNIFIED IDEOGRAPH:'D5AB:54699:晛 +CJK UNIFIED IDEOGRAPH:'D5AC:54700:晙 +CJK UNIFIED IDEOGRAPH:'D5AD:54701:晜 +CJK UNIFIED IDEOGRAPH:'D5AE:54702:晢 +CJK UNIFIED IDEOGRAPH:'D5AF:54703:朘 +CJK UNIFIED IDEOGRAPH:'D5B0:54704:桹 +CJK UNIFIED IDEOGRAPH:'D5B1:54705:梇 +CJK UNIFIED IDEOGRAPH:'D5B2:54706:梐 +CJK UNIFIED IDEOGRAPH:'D5B3:54707:梜 +CJK UNIFIED IDEOGRAPH:'D5B4:54708:桭 +CJK UNIFIED IDEOGRAPH:'D5B5:54709:桮 +CJK UNIFIED IDEOGRAPH:'D5B6:54710:梮 +CJK UNIFIED IDEOGRAPH:'D5B7:54711:梫 +CJK UNIFIED IDEOGRAPH:'D5B8:54712:楖 +CJK UNIFIED IDEOGRAPH:'D5B9:54713:桯 +CJK UNIFIED IDEOGRAPH:'D5BA:54714:梣 +CJK UNIFIED IDEOGRAPH:'D5BB:54715:梬 +CJK UNIFIED IDEOGRAPH:'D5BC:54716:梩 +CJK UNIFIED IDEOGRAPH:'D5BD:54717:桵 +CJK UNIFIED IDEOGRAPH:'D5BE:54718:桴 +CJK UNIFIED IDEOGRAPH:'D5BF:54719:梲 +CJK UNIFIED IDEOGRAPH:'D5C0:54720:梏 +CJK UNIFIED IDEOGRAPH:'D5C1:54721:桷 +CJK UNIFIED IDEOGRAPH:'D5C2:54722:梒 +CJK UNIFIED IDEOGRAPH:'D5C3:54723:桼 +CJK UNIFIED IDEOGRAPH:'D5C4:54724:桫 +CJK UNIFIED IDEOGRAPH:'D5C5:54725:桲 +CJK UNIFIED IDEOGRAPH:'D5C6:54726:梪 +CJK UNIFIED IDEOGRAPH:'D5C7:54727:梀 +CJK UNIFIED IDEOGRAPH:'D5C8:54728:桱 +CJK UNIFIED IDEOGRAPH:'D5C9:54729:桾 +CJK UNIFIED IDEOGRAPH:'D5CA:54730:梛 +CJK UNIFIED IDEOGRAPH:'D5CB:54731:梖 +CJK UNIFIED IDEOGRAPH:'D5CC:54732:梋 +CJK UNIFIED IDEOGRAPH:'D5CD:54733:梠 +CJK UNIFIED IDEOGRAPH:'D5CE:54734:梉 +CJK UNIFIED IDEOGRAPH:'D5CF:54735:梤 +CJK UNIFIED IDEOGRAPH:'D5D0:54736:桸 +CJK UNIFIED IDEOGRAPH:'D5D1:54737:桻 +CJK UNIFIED IDEOGRAPH:'D5D2:54738:梑 +CJK UNIFIED IDEOGRAPH:'D5D3:54739:梌 +CJK UNIFIED IDEOGRAPH:'D5D4:54740:梊 +CJK UNIFIED IDEOGRAPH:'D5D5:54741:桽 +CJK UNIFIED IDEOGRAPH:'D5D6:54742:欶 +CJK UNIFIED IDEOGRAPH:'D5D7:54743:欳 +CJK UNIFIED IDEOGRAPH:'D5D8:54744:欷 +CJK UNIFIED IDEOGRAPH:'D5D9:54745:欸 +CJK UNIFIED IDEOGRAPH:'D5DA:54746:殑 +CJK UNIFIED IDEOGRAPH:'D5DB:54747:殏 +CJK UNIFIED IDEOGRAPH:'D5DC:54748:殍 +CJK UNIFIED IDEOGRAPH:'D5DD:54749:殎 +CJK UNIFIED IDEOGRAPH:'D5DE:54750:殌 +CJK UNIFIED IDEOGRAPH:'D5DF:54751:氪 +CJK UNIFIED IDEOGRAPH:'D5E0:54752:淀 +CJK UNIFIED IDEOGRAPH:'D5E1:54753:涫 +CJK UNIFIED IDEOGRAPH:'D5E2:54754:涴 +CJK UNIFIED IDEOGRAPH:'D5E3:54755:涳 +CJK UNIFIED IDEOGRAPH:'D5E4:54756:湴 +CJK UNIFIED IDEOGRAPH:'D5E5:54757:涬 +CJK UNIFIED IDEOGRAPH:'D5E6:54758:淩 +CJK UNIFIED IDEOGRAPH:'D5E7:54759:淢 +CJK UNIFIED IDEOGRAPH:'D5E8:54760:涷 +CJK UNIFIED IDEOGRAPH:'D5E9:54761:淶 +CJK UNIFIED IDEOGRAPH:'D5EA:54762:淔 +CJK UNIFIED IDEOGRAPH:'D5EB:54763:渀 +CJK UNIFIED IDEOGRAPH:'D5EC:54764:淈 +CJK UNIFIED IDEOGRAPH:'D5ED:54765:淠 +CJK UNIFIED IDEOGRAPH:'D5EE:54766:淟 +CJK UNIFIED IDEOGRAPH:'D5EF:54767:淖 +CJK UNIFIED IDEOGRAPH:'D5F0:54768:涾 +CJK UNIFIED IDEOGRAPH:'D5F1:54769:淥 +CJK UNIFIED IDEOGRAPH:'D5F2:54770:淜 +CJK UNIFIED IDEOGRAPH:'D5F3:54771:淝 +CJK UNIFIED IDEOGRAPH:'D5F4:54772:淛 +CJK UNIFIED IDEOGRAPH:'D5F5:54773:淴 +CJK UNIFIED IDEOGRAPH:'D5F6:54774:淊 +CJK UNIFIED IDEOGRAPH:'D5F7:54775:涽 +CJK UNIFIED IDEOGRAPH:'D5F8:54776:淭 +CJK UNIFIED IDEOGRAPH:'D5F9:54777:淰 +CJK UNIFIED IDEOGRAPH:'D5FA:54778:涺 +CJK UNIFIED IDEOGRAPH:'D5FB:54779:淕 +CJK UNIFIED IDEOGRAPH:'D5FC:54780:淂 +CJK UNIFIED IDEOGRAPH:'D5FD:54781:淏 +CJK UNIFIED IDEOGRAPH:'D5FE:54782:淉 +CJK UNIFIED IDEOGRAPH:'D640:54848:淐 +CJK UNIFIED IDEOGRAPH:'D641:54849:淲 +CJK UNIFIED IDEOGRAPH:'D642:54850:淓 +CJK UNIFIED IDEOGRAPH:'D643:54851:淽 +CJK UNIFIED IDEOGRAPH:'D644:54852:淗 +CJK UNIFIED IDEOGRAPH:'D645:54853:淍 +CJK UNIFIED IDEOGRAPH:'D646:54854:淣 +CJK UNIFIED IDEOGRAPH:'D647:54855:涻 +CJK UNIFIED IDEOGRAPH:'D648:54856:烺 +CJK UNIFIED IDEOGRAPH:'D649:54857:焍 +CJK UNIFIED IDEOGRAPH:'D64A:54858:烷 +CJK UNIFIED IDEOGRAPH:'D64B:54859:焗 +CJK UNIFIED IDEOGRAPH:'D64C:54860:烴 +CJK UNIFIED IDEOGRAPH:'D64D:54861:焌 +CJK UNIFIED IDEOGRAPH:'D64E:54862:烰 +CJK UNIFIED IDEOGRAPH:'D64F:54863:焄 +CJK UNIFIED IDEOGRAPH:'D650:54864:烳 +CJK UNIFIED IDEOGRAPH:'D651:54865:焐 +CJK UNIFIED IDEOGRAPH:'D652:54866:烼 +CJK UNIFIED IDEOGRAPH:'D653:54867:烿 +CJK UNIFIED IDEOGRAPH:'D654:54868:焆 +CJK UNIFIED IDEOGRAPH:'D655:54869:焓 +CJK UNIFIED IDEOGRAPH:'D656:54870:焀 +CJK UNIFIED IDEOGRAPH:'D657:54871:烸 +CJK UNIFIED IDEOGRAPH:'D658:54872:烶 +CJK UNIFIED IDEOGRAPH:'D659:54873:焋 +CJK UNIFIED IDEOGRAPH:'D65A:54874:焂 +CJK UNIFIED IDEOGRAPH:'D65B:54875:焎 +CJK UNIFIED IDEOGRAPH:'D65C:54876:牾 +CJK UNIFIED IDEOGRAPH:'D65D:54877:牻 +CJK UNIFIED IDEOGRAPH:'D65E:54878:牼 +CJK UNIFIED IDEOGRAPH:'D65F:54879:牿 +CJK UNIFIED IDEOGRAPH:'D660:54880:猝 +CJK UNIFIED IDEOGRAPH:'D661:54881:猗 +CJK UNIFIED IDEOGRAPH:'D662:54882:猇 +CJK UNIFIED IDEOGRAPH:'D663:54883:猑 +CJK UNIFIED IDEOGRAPH:'D664:54884:猘 +CJK UNIFIED IDEOGRAPH:'D665:54885:猊 +CJK UNIFIED IDEOGRAPH:'D666:54886:猈 +CJK UNIFIED IDEOGRAPH:'D667:54887:狿 +CJK UNIFIED IDEOGRAPH:'D668:54888:猏 +CJK UNIFIED IDEOGRAPH:'D669:54889:猞 +CJK UNIFIED IDEOGRAPH:'D66A:54890:玈 +CJK UNIFIED IDEOGRAPH:'D66B:54891:珶 +CJK UNIFIED IDEOGRAPH:'D66C:54892:珸 +CJK UNIFIED IDEOGRAPH:'D66D:54893:珵 +CJK UNIFIED IDEOGRAPH:'D66E:54894:琄 +CJK UNIFIED IDEOGRAPH:'D66F:54895:琁 +CJK UNIFIED IDEOGRAPH:'D670:54896:珽 +CJK UNIFIED IDEOGRAPH:'D671:54897:琇 +CJK UNIFIED IDEOGRAPH:'D672:54898:琀 +CJK UNIFIED IDEOGRAPH:'D673:54899:珺 +CJK UNIFIED IDEOGRAPH:'D674:54900:珼 +CJK UNIFIED IDEOGRAPH:'D675:54901:珿 +CJK UNIFIED IDEOGRAPH:'D676:54902:琌 +CJK UNIFIED IDEOGRAPH:'D677:54903:琋 +CJK UNIFIED IDEOGRAPH:'D678:54904:珴 +CJK UNIFIED IDEOGRAPH:'D679:54905:琈 +CJK UNIFIED IDEOGRAPH:'D67A:54906:畤 +CJK UNIFIED IDEOGRAPH:'D67B:54907:畣 +CJK UNIFIED IDEOGRAPH:'D67C:54908:痎 +CJK UNIFIED IDEOGRAPH:'D67D:54909:痒 +CJK UNIFIED IDEOGRAPH:'D67E:54910:痏 +CJK UNIFIED IDEOGRAPH:'D6A1:54945:痋 +CJK UNIFIED IDEOGRAPH:'D6A2:54946:痌 +CJK UNIFIED IDEOGRAPH:'D6A3:54947:痑 +CJK UNIFIED IDEOGRAPH:'D6A4:54948:痐 +CJK UNIFIED IDEOGRAPH:'D6A5:54949:皏 +CJK UNIFIED IDEOGRAPH:'D6A6:54950:皉 +CJK UNIFIED IDEOGRAPH:'D6A7:54951:盓 +CJK UNIFIED IDEOGRAPH:'D6A8:54952:眹 +CJK UNIFIED IDEOGRAPH:'D6A9:54953:眯 +CJK UNIFIED IDEOGRAPH:'D6AA:54954:眭 +CJK UNIFIED IDEOGRAPH:'D6AB:54955:眱 +CJK UNIFIED IDEOGRAPH:'D6AC:54956:眲 +CJK UNIFIED IDEOGRAPH:'D6AD:54957:眴 +CJK UNIFIED IDEOGRAPH:'D6AE:54958:眳 +CJK UNIFIED IDEOGRAPH:'D6AF:54959:眽 +CJK UNIFIED IDEOGRAPH:'D6B0:54960:眥 +CJK UNIFIED IDEOGRAPH:'D6B1:54961:眻 +CJK UNIFIED IDEOGRAPH:'D6B2:54962:眵 +CJK UNIFIED IDEOGRAPH:'D6B3:54963:硈 +CJK UNIFIED IDEOGRAPH:'D6B4:54964:硒 +CJK UNIFIED IDEOGRAPH:'D6B5:54965:硉 +CJK UNIFIED IDEOGRAPH:'D6B6:54966:硍 +CJK UNIFIED IDEOGRAPH:'D6B7:54967:硊 +CJK UNIFIED IDEOGRAPH:'D6B8:54968:硌 +CJK UNIFIED IDEOGRAPH:'D6B9:54969:砦 +CJK UNIFIED IDEOGRAPH:'D6BA:54970:硅 +CJK UNIFIED IDEOGRAPH:'D6BB:54971:硐 +CJK UNIFIED IDEOGRAPH:'D6BC:54972:祤 +CJK UNIFIED IDEOGRAPH:'D6BD:54973:祧 +CJK UNIFIED IDEOGRAPH:'D6BE:54974:祩 +CJK UNIFIED IDEOGRAPH:'D6BF:54975:祪 +CJK UNIFIED IDEOGRAPH:'D6C0:54976:祣 +CJK UNIFIED IDEOGRAPH:'D6C1:54977:祫 +CJK UNIFIED IDEOGRAPH:'D6C2:54978:祡 +CJK UNIFIED IDEOGRAPH:'D6C3:54979:离 +CJK UNIFIED IDEOGRAPH:'D6C4:54980:秺 +CJK UNIFIED IDEOGRAPH:'D6C5:54981:秸 +CJK UNIFIED IDEOGRAPH:'D6C6:54982:秶 +CJK UNIFIED IDEOGRAPH:'D6C7:54983:秷 +CJK UNIFIED IDEOGRAPH:'D6C8:54984:窏 +CJK UNIFIED IDEOGRAPH:'D6C9:54985:窔 +CJK UNIFIED IDEOGRAPH:'D6CA:54986:窐 +CJK UNIFIED IDEOGRAPH:'D6CB:54987:笵 +CJK UNIFIED IDEOGRAPH:'D6CC:54988:筇 +CJK UNIFIED IDEOGRAPH:'D6CD:54989:笴 +CJK UNIFIED IDEOGRAPH:'D6CE:54990:笥 +CJK UNIFIED IDEOGRAPH:'D6CF:54991:笰 +CJK UNIFIED IDEOGRAPH:'D6D0:54992:笢 +CJK UNIFIED IDEOGRAPH:'D6D1:54993:笤 +CJK UNIFIED IDEOGRAPH:'D6D2:54994:笳 +CJK UNIFIED IDEOGRAPH:'D6D3:54995:笘 +CJK UNIFIED IDEOGRAPH:'D6D4:54996:笪 +CJK UNIFIED IDEOGRAPH:'D6D5:54997:笝 +CJK UNIFIED IDEOGRAPH:'D6D6:54998:笱 +CJK UNIFIED IDEOGRAPH:'D6D7:54999:笫 +CJK UNIFIED IDEOGRAPH:'D6D8:55000:笭 +CJK UNIFIED IDEOGRAPH:'D6D9:55001:笯 +CJK UNIFIED IDEOGRAPH:'D6DA:55002:笲 +CJK UNIFIED IDEOGRAPH:'D6DB:55003:笸 +CJK UNIFIED IDEOGRAPH:'D6DC:55004:笚 +CJK UNIFIED IDEOGRAPH:'D6DD:55005:笣 +CJK UNIFIED IDEOGRAPH:'D6DE:55006:粔 +CJK UNIFIED IDEOGRAPH:'D6DF:55007:粘 +CJK UNIFIED IDEOGRAPH:'D6E0:55008:粖 +CJK UNIFIED IDEOGRAPH:'D6E1:55009:粣 +CJK UNIFIED IDEOGRAPH:'D6E2:55010:紵 +CJK UNIFIED IDEOGRAPH:'D6E3:55011:紽 +CJK UNIFIED IDEOGRAPH:'D6E4:55012:紸 +CJK UNIFIED IDEOGRAPH:'D6E5:55013:紶 +CJK UNIFIED IDEOGRAPH:'D6E6:55014:紺 +CJK UNIFIED IDEOGRAPH:'D6E7:55015:絅 +CJK UNIFIED IDEOGRAPH:'D6E8:55016:紬 +CJK UNIFIED IDEOGRAPH:'D6E9:55017:紩 +CJK UNIFIED IDEOGRAPH:'D6EA:55018:絁 +CJK UNIFIED IDEOGRAPH:'D6EB:55019:絇 +CJK UNIFIED IDEOGRAPH:'D6EC:55020:紾 +CJK UNIFIED IDEOGRAPH:'D6ED:55021:紿 +CJK UNIFIED IDEOGRAPH:'D6EE:55022:絊 +CJK UNIFIED IDEOGRAPH:'D6EF:55023:紻 +CJK UNIFIED IDEOGRAPH:'D6F0:55024:紨 +CJK UNIFIED IDEOGRAPH:'D6F1:55025:罣 +CJK UNIFIED IDEOGRAPH:'D6F2:55026:羕 +CJK UNIFIED IDEOGRAPH:'D6F3:55027:羜 +CJK UNIFIED IDEOGRAPH:'D6F4:55028:羝 +CJK UNIFIED IDEOGRAPH:'D6F5:55029:羛 +CJK UNIFIED IDEOGRAPH:'D6F6:55030:翊 +CJK UNIFIED IDEOGRAPH:'D6F7:55031:翋 +CJK UNIFIED IDEOGRAPH:'D6F8:55032:翍 +CJK UNIFIED IDEOGRAPH:'D6F9:55033:翐 +CJK UNIFIED IDEOGRAPH:'D6FA:55034:翑 +CJK UNIFIED IDEOGRAPH:'D6FB:55035:翇 +CJK UNIFIED IDEOGRAPH:'D6FC:55036:翏 +CJK UNIFIED IDEOGRAPH:'D6FD:55037:翉 +CJK UNIFIED IDEOGRAPH:'D6FE:55038:耟 +CJK UNIFIED IDEOGRAPH:'D740:55104:耞 +CJK UNIFIED IDEOGRAPH:'D741:55105:耛 +CJK UNIFIED IDEOGRAPH:'D742:55106:聇 +CJK UNIFIED IDEOGRAPH:'D743:55107:聃 +CJK UNIFIED IDEOGRAPH:'D744:55108:聈 +CJK UNIFIED IDEOGRAPH:'D745:55109:脘 +CJK UNIFIED IDEOGRAPH:'D746:55110:脥 +CJK UNIFIED IDEOGRAPH:'D747:55111:脙 +CJK UNIFIED IDEOGRAPH:'D748:55112:脛 +CJK UNIFIED IDEOGRAPH:'D749:55113:脭 +CJK UNIFIED IDEOGRAPH:'D74A:55114:脟 +CJK UNIFIED IDEOGRAPH:'D74B:55115:脬 +CJK UNIFIED IDEOGRAPH:'D74C:55116:脞 +CJK UNIFIED IDEOGRAPH:'D74D:55117:脡 +CJK UNIFIED IDEOGRAPH:'D74E:55118:脕 +CJK UNIFIED IDEOGRAPH:'D74F:55119:脧 +CJK UNIFIED IDEOGRAPH:'D750:55120:脝 +CJK UNIFIED IDEOGRAPH:'D751:55121:脢 +CJK UNIFIED IDEOGRAPH:'D752:55122:舑 +CJK UNIFIED IDEOGRAPH:'D753:55123:舸 +CJK UNIFIED IDEOGRAPH:'D754:55124:舳 +CJK UNIFIED IDEOGRAPH:'D755:55125:舺 +CJK UNIFIED IDEOGRAPH:'D756:55126:舴 +CJK UNIFIED IDEOGRAPH:'D757:55127:舲 +CJK UNIFIED IDEOGRAPH:'D758:55128:艴 +CJK UNIFIED IDEOGRAPH:'D759:55129:莐 +CJK UNIFIED IDEOGRAPH:'D75A:55130:莣 +CJK UNIFIED IDEOGRAPH:'D75B:55131:莨 +CJK UNIFIED IDEOGRAPH:'D75C:55132:莍 +CJK UNIFIED IDEOGRAPH:'D75D:55133:荺 +CJK UNIFIED IDEOGRAPH:'D75E:55134:荳 +CJK UNIFIED IDEOGRAPH:'D75F:55135:莤 +CJK UNIFIED IDEOGRAPH:'D760:55136:荴 +CJK UNIFIED IDEOGRAPH:'D761:55137:莏 +CJK UNIFIED IDEOGRAPH:'D762:55138:莁 +CJK UNIFIED IDEOGRAPH:'D763:55139:莕 +CJK UNIFIED IDEOGRAPH:'D764:55140:莙 +CJK UNIFIED IDEOGRAPH:'D765:55141:荵 +CJK UNIFIED IDEOGRAPH:'D766:55142:莔 +CJK UNIFIED IDEOGRAPH:'D767:55143:莩 +CJK UNIFIED IDEOGRAPH:'D768:55144:荽 +CJK UNIFIED IDEOGRAPH:'D769:55145:莃 +CJK UNIFIED IDEOGRAPH:'D76A:55146:莌 +CJK UNIFIED IDEOGRAPH:'D76B:55147:莝 +CJK UNIFIED IDEOGRAPH:'D76C:55148:莛 +CJK UNIFIED IDEOGRAPH:'D76D:55149:莪 +CJK UNIFIED IDEOGRAPH:'D76E:55150:莋 +CJK UNIFIED IDEOGRAPH:'D76F:55151:荾 +CJK UNIFIED IDEOGRAPH:'D770:55152:莥 +CJK UNIFIED IDEOGRAPH:'D771:55153:莯 +CJK UNIFIED IDEOGRAPH:'D772:55154:莈 +CJK UNIFIED IDEOGRAPH:'D773:55155:莗 +CJK UNIFIED IDEOGRAPH:'D774:55156:莰 +CJK UNIFIED IDEOGRAPH:'D775:55157:荿 +CJK UNIFIED IDEOGRAPH:'D776:55158:莦 +CJK UNIFIED IDEOGRAPH:'D777:55159:莇 +CJK UNIFIED IDEOGRAPH:'D778:55160:莮 +CJK UNIFIED IDEOGRAPH:'D779:55161:荶 +CJK UNIFIED IDEOGRAPH:'D77A:55162:莚 +CJK UNIFIED IDEOGRAPH:'D77B:55163:虙 +CJK UNIFIED IDEOGRAPH:'D77C:55164:虖 +CJK UNIFIED IDEOGRAPH:'D77D:55165:蚿 +CJK UNIFIED IDEOGRAPH:'D77E:55166:蚷 +CJK UNIFIED IDEOGRAPH:'D7A1:55201:蛂 +CJK UNIFIED IDEOGRAPH:'D7A2:55202:蛁 +CJK UNIFIED IDEOGRAPH:'D7A3:55203:蛅 +CJK UNIFIED IDEOGRAPH:'D7A4:55204:蚺 +CJK UNIFIED IDEOGRAPH:'D7A5:55205:蚰 +CJK UNIFIED IDEOGRAPH:'D7A6:55206:蛈 +CJK UNIFIED IDEOGRAPH:'D7A7:55207:蚹 +CJK UNIFIED IDEOGRAPH:'D7A8:55208:蚳 +CJK UNIFIED IDEOGRAPH:'D7A9:55209:蚸 +CJK UNIFIED IDEOGRAPH:'D7AA:55210:蛌 +CJK UNIFIED IDEOGRAPH:'D7AB:55211:蚴 +CJK UNIFIED IDEOGRAPH:'D7AC:55212:蚻 +CJK UNIFIED IDEOGRAPH:'D7AD:55213:蚼 +CJK UNIFIED IDEOGRAPH:'D7AE:55214:蛃 +CJK UNIFIED IDEOGRAPH:'D7AF:55215:蚽 +CJK UNIFIED IDEOGRAPH:'D7B0:55216:蚾 +CJK UNIFIED IDEOGRAPH:'D7B1:55217:衒 +CJK UNIFIED IDEOGRAPH:'D7B2:55218:袉 +CJK UNIFIED IDEOGRAPH:'D7B3:55219:袕 +CJK UNIFIED IDEOGRAPH:'D7B4:55220:袨 +CJK UNIFIED IDEOGRAPH:'D7B5:55221:袢 +CJK UNIFIED IDEOGRAPH:'D7B6:55222:袪 +CJK UNIFIED IDEOGRAPH:'D7B7:55223:袚 +CJK UNIFIED IDEOGRAPH:'D7B8:55224:袑 +CJK UNIFIED IDEOGRAPH:'D7B9:55225:袡 +CJK UNIFIED IDEOGRAPH:'D7BA:55226:袟 +CJK UNIFIED IDEOGRAPH:'D7BB:55227:袘 +CJK UNIFIED IDEOGRAPH:'D7BC:55228:袧 +CJK UNIFIED IDEOGRAPH:'D7BD:55229:袙 +CJK UNIFIED IDEOGRAPH:'D7BE:55230:袛 +CJK UNIFIED IDEOGRAPH:'D7BF:55231:袗 +CJK UNIFIED IDEOGRAPH:'D7C0:55232:袤 +CJK UNIFIED IDEOGRAPH:'D7C1:55233:袬 +CJK UNIFIED IDEOGRAPH:'D7C2:55234:袌 +CJK UNIFIED IDEOGRAPH:'D7C3:55235:袓 +CJK UNIFIED IDEOGRAPH:'D7C4:55236:袎 +CJK UNIFIED IDEOGRAPH:'D7C5:55237:覂 +CJK UNIFIED IDEOGRAPH:'D7C6:55238:觖 +CJK UNIFIED IDEOGRAPH:'D7C7:55239:觙 +CJK UNIFIED IDEOGRAPH:'D7C8:55240:觕 +CJK UNIFIED IDEOGRAPH:'D7C9:55241:訰 +CJK UNIFIED IDEOGRAPH:'D7CA:55242:訧 +CJK UNIFIED IDEOGRAPH:'D7CB:55243:訬 +CJK UNIFIED IDEOGRAPH:'D7CC:55244:訞 +CJK UNIFIED IDEOGRAPH:'D7CD:55245:谹 +CJK UNIFIED IDEOGRAPH:'D7CE:55246:谻 +CJK UNIFIED IDEOGRAPH:'D7CF:55247:豜 +CJK UNIFIED IDEOGRAPH:'D7D0:55248:豝 +CJK UNIFIED IDEOGRAPH:'D7D1:55249:豽 +CJK UNIFIED IDEOGRAPH:'D7D2:55250:貥 +CJK UNIFIED IDEOGRAPH:'D7D3:55251:赽 +CJK UNIFIED IDEOGRAPH:'D7D4:55252:赻 +CJK UNIFIED IDEOGRAPH:'D7D5:55253:赹 +CJK UNIFIED IDEOGRAPH:'D7D6:55254:趼 +CJK UNIFIED IDEOGRAPH:'D7D7:55255:跂 +CJK UNIFIED IDEOGRAPH:'D7D8:55256:趹 +CJK UNIFIED IDEOGRAPH:'D7D9:55257:趿 +CJK UNIFIED IDEOGRAPH:'D7DA:55258:跁 +CJK UNIFIED IDEOGRAPH:'D7DB:55259:軘 +CJK UNIFIED IDEOGRAPH:'D7DC:55260:軞 +CJK UNIFIED IDEOGRAPH:'D7DD:55261:軝 +CJK UNIFIED IDEOGRAPH:'D7DE:55262:軜 +CJK UNIFIED IDEOGRAPH:'D7DF:55263:軗 +CJK UNIFIED IDEOGRAPH:'D7E0:55264:軠 +CJK UNIFIED IDEOGRAPH:'D7E1:55265:軡 +CJK UNIFIED IDEOGRAPH:'D7E2:55266:逤 +CJK UNIFIED IDEOGRAPH:'D7E3:55267:逋 +CJK UNIFIED IDEOGRAPH:'D7E4:55268:逑 +CJK UNIFIED IDEOGRAPH:'D7E5:55269:逜 +CJK UNIFIED IDEOGRAPH:'D7E6:55270:逌 +CJK UNIFIED IDEOGRAPH:'D7E7:55271:逡 +CJK UNIFIED IDEOGRAPH:'D7E8:55272:郯 +CJK UNIFIED IDEOGRAPH:'D7E9:55273:郪 +CJK UNIFIED IDEOGRAPH:'D7EA:55274:郰 +CJK UNIFIED IDEOGRAPH:'D7EB:55275:郴 +CJK UNIFIED IDEOGRAPH:'D7EC:55276:郲 +CJK UNIFIED IDEOGRAPH:'D7ED:55277:郳 +CJK UNIFIED IDEOGRAPH:'D7EE:55278:郔 +CJK UNIFIED IDEOGRAPH:'D7EF:55279:郫 +CJK UNIFIED IDEOGRAPH:'D7F0:55280:郬 +CJK UNIFIED IDEOGRAPH:'D7F1:55281:郩 +CJK UNIFIED IDEOGRAPH:'D7F2:55282:酖 +CJK UNIFIED IDEOGRAPH:'D7F3:55283:酘 +CJK UNIFIED IDEOGRAPH:'D7F4:55284:酚 +CJK UNIFIED IDEOGRAPH:'D7F5:55285:酓 +CJK UNIFIED IDEOGRAPH:'D7F6:55286:酕 +CJK UNIFIED IDEOGRAPH:'D7F7:55287:釬 +CJK UNIFIED IDEOGRAPH:'D7F8:55288:釴 +CJK UNIFIED IDEOGRAPH:'D7F9:55289:釱 +CJK UNIFIED IDEOGRAPH:'D7FA:55290:釳 +CJK UNIFIED IDEOGRAPH:'D7FB:55291:釸 +CJK UNIFIED IDEOGRAPH:'D7FC:55292:釤 +CJK UNIFIED IDEOGRAPH:'D7FD:55293:釹 +CJK UNIFIED IDEOGRAPH:'D7FE:55294:釪 +CJK UNIFIED IDEOGRAPH:'D840:55360:釫 +CJK UNIFIED IDEOGRAPH:'D841:55361:釷 +CJK UNIFIED IDEOGRAPH:'D842:55362:釨 +CJK UNIFIED IDEOGRAPH:'D843:55363:釮 +CJK UNIFIED IDEOGRAPH:'D844:55364:镺 +CJK UNIFIED IDEOGRAPH:'D845:55365:閆 +CJK UNIFIED IDEOGRAPH:'D846:55366:閈 +CJK UNIFIED IDEOGRAPH:'D847:55367:陼 +CJK UNIFIED IDEOGRAPH:'D848:55368:陭 +CJK UNIFIED IDEOGRAPH:'D849:55369:陫 +CJK UNIFIED IDEOGRAPH:'D84A:55370:陱 +CJK UNIFIED IDEOGRAPH:'D84B:55371:陯 +CJK UNIFIED IDEOGRAPH:'D84C:55372:隿 +CJK UNIFIED IDEOGRAPH:'D84D:55373:靪 +CJK UNIFIED IDEOGRAPH:'D84E:55374:頄 +CJK UNIFIED IDEOGRAPH:'D84F:55375:飥 +CJK UNIFIED IDEOGRAPH:'D850:55376:馗 +CJK UNIFIED IDEOGRAPH:'D851:55377:傛 +CJK UNIFIED IDEOGRAPH:'D852:55378:傕 +CJK UNIFIED IDEOGRAPH:'D853:55379:傔 +CJK UNIFIED IDEOGRAPH:'D854:55380:傞 +CJK UNIFIED IDEOGRAPH:'D855:55381:傋 +CJK UNIFIED IDEOGRAPH:'D856:55382:傣 +CJK UNIFIED IDEOGRAPH:'D857:55383:傃 +CJK UNIFIED IDEOGRAPH:'D858:55384:傌 +CJK UNIFIED IDEOGRAPH:'D859:55385:傎 +CJK UNIFIED IDEOGRAPH:'D85A:55386:傝 +CJK UNIFIED IDEOGRAPH:'D85B:55387:偨 +CJK UNIFIED IDEOGRAPH:'D85C:55388:傜 +CJK UNIFIED IDEOGRAPH:'D85D:55389:傒 +CJK UNIFIED IDEOGRAPH:'D85E:55390:傂 +CJK UNIFIED IDEOGRAPH:'D85F:55391:傇 +CJK UNIFIED IDEOGRAPH:'D860:55392:兟 +CJK UNIFIED IDEOGRAPH:'D861:55393:凔 +CJK UNIFIED IDEOGRAPH:'D862:55394:匒 +CJK UNIFIED IDEOGRAPH:'D863:55395:匑 +CJK UNIFIED IDEOGRAPH:'D864:55396:厤 +CJK UNIFIED IDEOGRAPH:'D865:55397:厧 +CJK UNIFIED IDEOGRAPH:'D866:55398:喑 +CJK UNIFIED IDEOGRAPH:'D867:55399:喨 +CJK UNIFIED IDEOGRAPH:'D868:55400:喥 +CJK UNIFIED IDEOGRAPH:'D869:55401:喭 +CJK UNIFIED IDEOGRAPH:'D86A:55402:啷 +CJK UNIFIED IDEOGRAPH:'D86B:55403:噅 +CJK UNIFIED IDEOGRAPH:'D86C:55404:喢 +CJK UNIFIED IDEOGRAPH:'D86D:55405:喓 +CJK UNIFIED IDEOGRAPH:'D86E:55406:喈 +CJK UNIFIED IDEOGRAPH:'D86F:55407:喏 +CJK UNIFIED IDEOGRAPH:'D870:55408:喵 +CJK UNIFIED IDEOGRAPH:'D871:55409:喁 +CJK UNIFIED IDEOGRAPH:'D872:55410:喣 +CJK UNIFIED IDEOGRAPH:'D873:55411:喒 +CJK UNIFIED IDEOGRAPH:'D874:55412:喤 +CJK UNIFIED IDEOGRAPH:'D875:55413:啽 +CJK UNIFIED IDEOGRAPH:'D876:55414:喌 +CJK UNIFIED IDEOGRAPH:'D877:55415:喦 +CJK UNIFIED IDEOGRAPH:'D878:55416:啿 +CJK UNIFIED IDEOGRAPH:'D879:55417:喕 +CJK UNIFIED IDEOGRAPH:'D87A:55418:喡 +CJK UNIFIED IDEOGRAPH:'D87B:55419:喎 +CJK UNIFIED IDEOGRAPH:'D87C:55420:圌 +CJK UNIFIED IDEOGRAPH:'D87D:55421:堩 +CJK UNIFIED IDEOGRAPH:'D87E:55422:堷 +CJK UNIFIED IDEOGRAPH:'D8A1:55457:堙 +CJK UNIFIED IDEOGRAPH:'D8A2:55458:堞 +CJK UNIFIED IDEOGRAPH:'D8A3:55459:堧 +CJK UNIFIED IDEOGRAPH:'D8A4:55460:堣 +CJK UNIFIED IDEOGRAPH:'D8A5:55461:堨 +CJK UNIFIED IDEOGRAPH:'D8A6:55462:埵 +CJK UNIFIED IDEOGRAPH:'D8A7:55463:塈 +CJK UNIFIED IDEOGRAPH:'D8A8:55464:堥 +CJK UNIFIED IDEOGRAPH:'D8A9:55465:堜 +CJK UNIFIED IDEOGRAPH:'D8AA:55466:堛 +CJK UNIFIED IDEOGRAPH:'D8AB:55467:堳 +CJK UNIFIED IDEOGRAPH:'D8AC:55468:堿 +CJK UNIFIED IDEOGRAPH:'D8AD:55469:堶 +CJK UNIFIED IDEOGRAPH:'D8AE:55470:堮 +CJK UNIFIED IDEOGRAPH:'D8AF:55471:堹 +CJK UNIFIED IDEOGRAPH:'D8B0:55472:堸 +CJK UNIFIED IDEOGRAPH:'D8B1:55473:堭 +CJK UNIFIED IDEOGRAPH:'D8B2:55474:堬 +CJK UNIFIED IDEOGRAPH:'D8B3:55475:堻 +CJK UNIFIED IDEOGRAPH:'D8B4:55476:奡 +CJK UNIFIED IDEOGRAPH:'D8B5:55477:媯 +CJK UNIFIED IDEOGRAPH:'D8B6:55478:媔 +CJK UNIFIED IDEOGRAPH:'D8B7:55479:媟 +CJK UNIFIED IDEOGRAPH:'D8B8:55480:婺 +CJK UNIFIED IDEOGRAPH:'D8B9:55481:媢 +CJK UNIFIED IDEOGRAPH:'D8BA:55482:媞 +CJK UNIFIED IDEOGRAPH:'D8BB:55483:婸 +CJK UNIFIED IDEOGRAPH:'D8BC:55484:媦 +CJK UNIFIED IDEOGRAPH:'D8BD:55485:婼 +CJK UNIFIED IDEOGRAPH:'D8BE:55486:媥 +CJK UNIFIED IDEOGRAPH:'D8BF:55487:媬 +CJK UNIFIED IDEOGRAPH:'D8C0:55488:媕 +CJK UNIFIED IDEOGRAPH:'D8C1:55489:媮 +CJK UNIFIED IDEOGRAPH:'D8C2:55490:娷 +CJK UNIFIED IDEOGRAPH:'D8C3:55491:媄 +CJK UNIFIED IDEOGRAPH:'D8C4:55492:媊 +CJK UNIFIED IDEOGRAPH:'D8C5:55493:媗 +CJK UNIFIED IDEOGRAPH:'D8C6:55494:媃 +CJK UNIFIED IDEOGRAPH:'D8C7:55495:媋 +CJK UNIFIED IDEOGRAPH:'D8C8:55496:媩 +CJK UNIFIED IDEOGRAPH:'D8C9:55497:婻 +CJK UNIFIED IDEOGRAPH:'D8CA:55498:婽 +CJK UNIFIED IDEOGRAPH:'D8CB:55499:媌 +CJK UNIFIED IDEOGRAPH:'D8CC:55500:媜 +CJK UNIFIED IDEOGRAPH:'D8CD:55501:媏 +CJK UNIFIED IDEOGRAPH:'D8CE:55502:媓 +CJK UNIFIED IDEOGRAPH:'D8CF:55503:媝 +CJK UNIFIED IDEOGRAPH:'D8D0:55504:寪 +CJK UNIFIED IDEOGRAPH:'D8D1:55505:寍 +CJK UNIFIED IDEOGRAPH:'D8D2:55506:寋 +CJK UNIFIED IDEOGRAPH:'D8D3:55507:寔 +CJK UNIFIED IDEOGRAPH:'D8D4:55508:寑 +CJK UNIFIED IDEOGRAPH:'D8D5:55509:寊 +CJK UNIFIED IDEOGRAPH:'D8D6:55510:寎 +CJK UNIFIED IDEOGRAPH:'D8D7:55511:尌 +CJK UNIFIED IDEOGRAPH:'D8D8:55512:尰 +CJK UNIFIED IDEOGRAPH:'D8D9:55513:崷 +CJK UNIFIED IDEOGRAPH:'D8DA:55514:嵃 +CJK UNIFIED IDEOGRAPH:'D8DB:55515:嵫 +CJK UNIFIED IDEOGRAPH:'D8DC:55516:嵁 +CJK UNIFIED IDEOGRAPH:'D8DD:55517:嵋 +CJK UNIFIED IDEOGRAPH:'D8DE:55518:崿 +CJK UNIFIED IDEOGRAPH:'D8DF:55519:崵 +CJK UNIFIED IDEOGRAPH:'D8E0:55520:嵑 +CJK UNIFIED IDEOGRAPH:'D8E1:55521:嵎 +CJK UNIFIED IDEOGRAPH:'D8E2:55522:嵕 +CJK UNIFIED IDEOGRAPH:'D8E3:55523:崳 +CJK UNIFIED IDEOGRAPH:'D8E4:55524:崺 +CJK UNIFIED IDEOGRAPH:'D8E5:55525:嵒 +CJK UNIFIED IDEOGRAPH:'D8E6:55526:崽 +CJK UNIFIED IDEOGRAPH:'D8E7:55527:崱 +CJK UNIFIED IDEOGRAPH:'D8E8:55528:嵙 +CJK UNIFIED IDEOGRAPH:'D8E9:55529:嵂 +CJK UNIFIED IDEOGRAPH:'D8EA:55530:崹 +CJK UNIFIED IDEOGRAPH:'D8EB:55531:嵉 +CJK UNIFIED IDEOGRAPH:'D8EC:55532:崸 +CJK UNIFIED IDEOGRAPH:'D8ED:55533:崼 +CJK UNIFIED IDEOGRAPH:'D8EE:55534:崲 +CJK UNIFIED IDEOGRAPH:'D8EF:55535:崶 +CJK UNIFIED IDEOGRAPH:'D8F0:55536:嵀 +CJK UNIFIED IDEOGRAPH:'D8F1:55537:嵅 +CJK UNIFIED IDEOGRAPH:'D8F2:55538:幄 +CJK UNIFIED IDEOGRAPH:'D8F3:55539:幁 +CJK UNIFIED IDEOGRAPH:'D8F4:55540:彘 +CJK UNIFIED IDEOGRAPH:'D8F5:55541:徦 +CJK UNIFIED IDEOGRAPH:'D8F6:55542:徥 +CJK UNIFIED IDEOGRAPH:'D8F7:55543:徫 +CJK UNIFIED IDEOGRAPH:'D8F8:55544:惉 +CJK UNIFIED IDEOGRAPH:'D8F9:55545:悹 +CJK UNIFIED IDEOGRAPH:'D8FA:55546:惌 +CJK UNIFIED IDEOGRAPH:'D8FB:55547:惢 +CJK UNIFIED IDEOGRAPH:'D8FC:55548:惎 +CJK UNIFIED IDEOGRAPH:'D8FD:55549:惄 +CJK UNIFIED IDEOGRAPH:'D8FE:55550:愔 +CJK UNIFIED IDEOGRAPH:'D940:55616:惲 +CJK UNIFIED IDEOGRAPH:'D941:55617:愊 +CJK UNIFIED IDEOGRAPH:'D942:55618:愖 +CJK UNIFIED IDEOGRAPH:'D943:55619:愅 +CJK UNIFIED IDEOGRAPH:'D944:55620:惵 +CJK UNIFIED IDEOGRAPH:'D945:55621:愓 +CJK UNIFIED IDEOGRAPH:'D946:55622:惸 +CJK UNIFIED IDEOGRAPH:'D947:55623:惼 +CJK UNIFIED IDEOGRAPH:'D948:55624:惾 +CJK UNIFIED IDEOGRAPH:'D949:55625:惁 +CJK UNIFIED IDEOGRAPH:'D94A:55626:愃 +CJK UNIFIED IDEOGRAPH:'D94B:55627:愘 +CJK UNIFIED IDEOGRAPH:'D94C:55628:愝 +CJK UNIFIED IDEOGRAPH:'D94D:55629:愐 +CJK UNIFIED IDEOGRAPH:'D94E:55630:惿 +CJK UNIFIED IDEOGRAPH:'D94F:55631:愄 +CJK UNIFIED IDEOGRAPH:'D950:55632:愋 +CJK UNIFIED IDEOGRAPH:'D951:55633:扊 +CJK UNIFIED IDEOGRAPH:'D952:55634:掔 +CJK UNIFIED IDEOGRAPH:'D953:55635:掱 +CJK UNIFIED IDEOGRAPH:'D954:55636:掰 +CJK UNIFIED IDEOGRAPH:'D955:55637:揎 +CJK UNIFIED IDEOGRAPH:'D956:55638:揥 +CJK UNIFIED IDEOGRAPH:'D957:55639:揨 +CJK UNIFIED IDEOGRAPH:'D958:55640:揯 +CJK UNIFIED IDEOGRAPH:'D959:55641:揃 +CJK UNIFIED IDEOGRAPH:'D95A:55642:撝 +CJK UNIFIED IDEOGRAPH:'D95B:55643:揳 +CJK UNIFIED IDEOGRAPH:'D95C:55644:揊 +CJK UNIFIED IDEOGRAPH:'D95D:55645:揠 +CJK UNIFIED IDEOGRAPH:'D95E:55646:揶 +CJK UNIFIED IDEOGRAPH:'D95F:55647:揕 +CJK UNIFIED IDEOGRAPH:'D960:55648:揲 +CJK UNIFIED IDEOGRAPH:'D961:55649:揵 +CJK UNIFIED IDEOGRAPH:'D962:55650:摡 +CJK UNIFIED IDEOGRAPH:'D963:55651:揟 +CJK UNIFIED IDEOGRAPH:'D964:55652:掾 +CJK UNIFIED IDEOGRAPH:'D965:55653:揝 +CJK UNIFIED IDEOGRAPH:'D966:55654:揜 +CJK UNIFIED IDEOGRAPH:'D967:55655:揄 +CJK UNIFIED IDEOGRAPH:'D968:55656:揘 +CJK UNIFIED IDEOGRAPH:'D969:55657:揓 +CJK UNIFIED IDEOGRAPH:'D96A:55658:揂 +CJK UNIFIED IDEOGRAPH:'D96B:55659:揇 +CJK UNIFIED IDEOGRAPH:'D96C:55660:揌 +CJK UNIFIED IDEOGRAPH:'D96D:55661:揋 +CJK UNIFIED IDEOGRAPH:'D96E:55662:揈 +CJK UNIFIED IDEOGRAPH:'D96F:55663:揰 +CJK UNIFIED IDEOGRAPH:'D970:55664:揗 +CJK UNIFIED IDEOGRAPH:'D971:55665:揙 +CJK UNIFIED IDEOGRAPH:'D972:55666:攲 +CJK UNIFIED IDEOGRAPH:'D973:55667:敧 +CJK UNIFIED IDEOGRAPH:'D974:55668:敪 +CJK UNIFIED IDEOGRAPH:'D975:55669:敤 +CJK UNIFIED IDEOGRAPH:'D976:55670:敜 +CJK UNIFIED IDEOGRAPH:'D977:55671:敨 +CJK UNIFIED IDEOGRAPH:'D978:55672:敥 +CJK UNIFIED IDEOGRAPH:'D979:55673:斌 +CJK UNIFIED IDEOGRAPH:'D97A:55674:斝 +CJK UNIFIED IDEOGRAPH:'D97B:55675:斞 +CJK UNIFIED IDEOGRAPH:'D97C:55676:斮 +CJK UNIFIED IDEOGRAPH:'D97D:55677:旐 +CJK UNIFIED IDEOGRAPH:'D97E:55678:旒 +CJK UNIFIED IDEOGRAPH:'D9A1:55713:晼 +CJK UNIFIED IDEOGRAPH:'D9A2:55714:晬 +CJK UNIFIED IDEOGRAPH:'D9A3:55715:晻 +CJK UNIFIED IDEOGRAPH:'D9A4:55716:暀 +CJK UNIFIED IDEOGRAPH:'D9A5:55717:晱 +CJK UNIFIED IDEOGRAPH:'D9A6:55718:晹 +CJK UNIFIED IDEOGRAPH:'D9A7:55719:晪 +CJK UNIFIED IDEOGRAPH:'D9A8:55720:晲 +CJK UNIFIED IDEOGRAPH:'D9A9:55721:朁 +CJK UNIFIED IDEOGRAPH:'D9AA:55722:椌 +CJK UNIFIED IDEOGRAPH:'D9AB:55723:棓 +CJK UNIFIED IDEOGRAPH:'D9AC:55724:椄 +CJK UNIFIED IDEOGRAPH:'D9AD:55725:棜 +CJK UNIFIED IDEOGRAPH:'D9AE:55726:椪 +CJK UNIFIED IDEOGRAPH:'D9AF:55727:棬 +CJK UNIFIED IDEOGRAPH:'D9B0:55728:棪 +CJK UNIFIED IDEOGRAPH:'D9B1:55729:棱 +CJK UNIFIED IDEOGRAPH:'D9B2:55730:椏 +CJK UNIFIED IDEOGRAPH:'D9B3:55731:棖 +CJK UNIFIED IDEOGRAPH:'D9B4:55732:棷 +CJK UNIFIED IDEOGRAPH:'D9B5:55733:棫 +CJK UNIFIED IDEOGRAPH:'D9B6:55734:棤 +CJK UNIFIED IDEOGRAPH:'D9B7:55735:棶 +CJK UNIFIED IDEOGRAPH:'D9B8:55736:椓 +CJK UNIFIED IDEOGRAPH:'D9B9:55737:椐 +CJK UNIFIED IDEOGRAPH:'D9BA:55738:棳 +CJK UNIFIED IDEOGRAPH:'D9BB:55739:棡 +CJK UNIFIED IDEOGRAPH:'D9BC:55740:椇 +CJK UNIFIED IDEOGRAPH:'D9BD:55741:棌 +CJK UNIFIED IDEOGRAPH:'D9BE:55742:椈 +CJK UNIFIED IDEOGRAPH:'D9BF:55743:楰 +CJK UNIFIED IDEOGRAPH:'D9C0:55744:梴 +CJK UNIFIED IDEOGRAPH:'D9C1:55745:椑 +CJK UNIFIED IDEOGRAPH:'D9C2:55746:棯 +CJK UNIFIED IDEOGRAPH:'D9C3:55747:棆 +CJK UNIFIED IDEOGRAPH:'D9C4:55748:椔 +CJK UNIFIED IDEOGRAPH:'D9C5:55749:棸 +CJK UNIFIED IDEOGRAPH:'D9C6:55750:棐 +CJK UNIFIED IDEOGRAPH:'D9C7:55751:棽 +CJK UNIFIED IDEOGRAPH:'D9C8:55752:棼 +CJK UNIFIED IDEOGRAPH:'D9C9:55753:棨 +CJK UNIFIED IDEOGRAPH:'D9CA:55754:椋 +CJK UNIFIED IDEOGRAPH:'D9CB:55755:椊 +CJK UNIFIED IDEOGRAPH:'D9CC:55756:椗 +CJK UNIFIED IDEOGRAPH:'D9CD:55757:棎 +CJK UNIFIED IDEOGRAPH:'D9CE:55758:棈 +CJK UNIFIED IDEOGRAPH:'D9CF:55759:棝 +CJK UNIFIED IDEOGRAPH:'D9D0:55760:棞 +CJK UNIFIED IDEOGRAPH:'D9D1:55761:棦 +CJK UNIFIED IDEOGRAPH:'D9D2:55762:棴 +CJK UNIFIED IDEOGRAPH:'D9D3:55763:棑 +CJK UNIFIED IDEOGRAPH:'D9D4:55764:椆 +CJK UNIFIED IDEOGRAPH:'D9D5:55765:棔 +CJK UNIFIED IDEOGRAPH:'D9D6:55766:棩 +CJK UNIFIED IDEOGRAPH:'D9D7:55767:椕 +CJK UNIFIED IDEOGRAPH:'D9D8:55768:椥 +CJK UNIFIED IDEOGRAPH:'D9D9:55769:棇 +CJK UNIFIED IDEOGRAPH:'D9DA:55770:欹 +CJK UNIFIED IDEOGRAPH:'D9DB:55771:欻 +CJK UNIFIED IDEOGRAPH:'D9DC:55772:欿 +CJK UNIFIED IDEOGRAPH:'D9DD:55773:欼 +CJK UNIFIED IDEOGRAPH:'D9DE:55774:殔 +CJK UNIFIED IDEOGRAPH:'D9DF:55775:殗 +CJK UNIFIED IDEOGRAPH:'D9E0:55776:殙 +CJK UNIFIED IDEOGRAPH:'D9E1:55777:殕 +CJK UNIFIED IDEOGRAPH:'D9E2:55778:殽 +CJK UNIFIED IDEOGRAPH:'D9E3:55779:毰 +CJK UNIFIED IDEOGRAPH:'D9E4:55780:毲 +CJK UNIFIED IDEOGRAPH:'D9E5:55781:毳 +CJK UNIFIED IDEOGRAPH:'D9E6:55782:氰 +CJK UNIFIED IDEOGRAPH:'D9E7:55783:淼 +CJK UNIFIED IDEOGRAPH:'D9E8:55784:湆 +CJK UNIFIED IDEOGRAPH:'D9E9:55785:湇 +CJK UNIFIED IDEOGRAPH:'D9EA:55786:渟 +CJK UNIFIED IDEOGRAPH:'D9EB:55787:湉 +CJK UNIFIED IDEOGRAPH:'D9EC:55788:溈 +CJK UNIFIED IDEOGRAPH:'D9ED:55789:渼 +CJK UNIFIED IDEOGRAPH:'D9EE:55790:渽 +CJK UNIFIED IDEOGRAPH:'D9EF:55791:湅 +CJK UNIFIED IDEOGRAPH:'D9F0:55792:湢 +CJK UNIFIED IDEOGRAPH:'D9F1:55793:渫 +CJK UNIFIED IDEOGRAPH:'D9F2:55794:渿 +CJK UNIFIED IDEOGRAPH:'D9F3:55795:湁 +CJK UNIFIED IDEOGRAPH:'D9F4:55796:湝 +CJK UNIFIED IDEOGRAPH:'D9F5:55797:湳 +CJK UNIFIED IDEOGRAPH:'D9F6:55798:渜 +CJK UNIFIED IDEOGRAPH:'D9F7:55799:渳 +CJK UNIFIED IDEOGRAPH:'D9F8:55800:湋 +CJK UNIFIED IDEOGRAPH:'D9F9:55801:湀 +CJK UNIFIED IDEOGRAPH:'D9FA:55802:湑 +CJK UNIFIED IDEOGRAPH:'D9FB:55803:渻 +CJK UNIFIED IDEOGRAPH:'D9FC:55804:渃 +CJK UNIFIED IDEOGRAPH:'D9FD:55805:渮 +CJK UNIFIED IDEOGRAPH:'D9FE:55806:湞 +CJK UNIFIED IDEOGRAPH:'DA40:55872:湨 +CJK UNIFIED IDEOGRAPH:'DA41:55873:湜 +CJK UNIFIED IDEOGRAPH:'DA42:55874:湡 +CJK UNIFIED IDEOGRAPH:'DA43:55875:渱 +CJK UNIFIED IDEOGRAPH:'DA44:55876:渨 +CJK UNIFIED IDEOGRAPH:'DA45:55877:湠 +CJK UNIFIED IDEOGRAPH:'DA46:55878:湱 +CJK UNIFIED IDEOGRAPH:'DA47:55879:湫 +CJK UNIFIED IDEOGRAPH:'DA48:55880:渹 +CJK UNIFIED IDEOGRAPH:'DA49:55881:渢 +CJK UNIFIED IDEOGRAPH:'DA4A:55882:渰 +CJK UNIFIED IDEOGRAPH:'DA4B:55883:湓 +CJK UNIFIED IDEOGRAPH:'DA4C:55884:湥 +CJK UNIFIED IDEOGRAPH:'DA4D:55885:渧 +CJK UNIFIED IDEOGRAPH:'DA4E:55886:湸 +CJK UNIFIED IDEOGRAPH:'DA4F:55887:湤 +CJK UNIFIED IDEOGRAPH:'DA50:55888:湷 +CJK UNIFIED IDEOGRAPH:'DA51:55889:湕 +CJK UNIFIED IDEOGRAPH:'DA52:55890:湹 +CJK UNIFIED IDEOGRAPH:'DA53:55891:湒 +CJK UNIFIED IDEOGRAPH:'DA54:55892:湦 +CJK UNIFIED IDEOGRAPH:'DA55:55893:渵 +CJK UNIFIED IDEOGRAPH:'DA56:55894:渶 +CJK UNIFIED IDEOGRAPH:'DA57:55895:湚 +CJK UNIFIED IDEOGRAPH:'DA58:55896:焠 +CJK UNIFIED IDEOGRAPH:'DA59:55897:焞 +CJK UNIFIED IDEOGRAPH:'DA5A:55898:焯 +CJK UNIFIED IDEOGRAPH:'DA5B:55899:烻 +CJK UNIFIED IDEOGRAPH:'DA5C:55900:焮 +CJK UNIFIED IDEOGRAPH:'DA5D:55901:焱 +CJK UNIFIED IDEOGRAPH:'DA5E:55902:焣 +CJK UNIFIED IDEOGRAPH:'DA5F:55903:焥 +CJK UNIFIED IDEOGRAPH:'DA60:55904:焢 +CJK UNIFIED IDEOGRAPH:'DA61:55905:焲 +CJK UNIFIED IDEOGRAPH:'DA62:55906:焟 +CJK UNIFIED IDEOGRAPH:'DA63:55907:焨 +CJK UNIFIED IDEOGRAPH:'DA64:55908:焺 +CJK UNIFIED IDEOGRAPH:'DA65:55909:焛 +CJK UNIFIED IDEOGRAPH:'DA66:55910:牋 +CJK UNIFIED IDEOGRAPH:'DA67:55911:牚 +CJK UNIFIED IDEOGRAPH:'DA68:55912:犈 +CJK UNIFIED IDEOGRAPH:'DA69:55913:犉 +CJK UNIFIED IDEOGRAPH:'DA6A:55914:犆 +CJK UNIFIED IDEOGRAPH:'DA6B:55915:犅 +CJK UNIFIED IDEOGRAPH:'DA6C:55916:犋 +CJK UNIFIED IDEOGRAPH:'DA6D:55917:猒 +CJK UNIFIED IDEOGRAPH:'DA6E:55918:猋 +CJK UNIFIED IDEOGRAPH:'DA6F:55919:猰 +CJK UNIFIED IDEOGRAPH:'DA70:55920:猢 +CJK UNIFIED IDEOGRAPH:'DA71:55921:猱 +CJK UNIFIED IDEOGRAPH:'DA72:55922:猳 +CJK UNIFIED IDEOGRAPH:'DA73:55923:猧 +CJK UNIFIED IDEOGRAPH:'DA74:55924:猲 +CJK UNIFIED IDEOGRAPH:'DA75:55925:猭 +CJK UNIFIED IDEOGRAPH:'DA76:55926:猦 +CJK UNIFIED IDEOGRAPH:'DA77:55927:猣 +CJK UNIFIED IDEOGRAPH:'DA78:55928:猵 +CJK UNIFIED IDEOGRAPH:'DA79:55929:猌 +CJK UNIFIED IDEOGRAPH:'DA7A:55930:琮 +CJK UNIFIED IDEOGRAPH:'DA7B:55931:琬 +CJK UNIFIED IDEOGRAPH:'DA7C:55932:琰 +CJK UNIFIED IDEOGRAPH:'DA7D:55933:琫 +CJK UNIFIED IDEOGRAPH:'DA7E:55934:琖 +CJK UNIFIED IDEOGRAPH:'DAA1:55969:琚 +CJK UNIFIED IDEOGRAPH:'DAA2:55970:琡 +CJK UNIFIED IDEOGRAPH:'DAA3:55971:琭 +CJK UNIFIED IDEOGRAPH:'DAA4:55972:琱 +CJK UNIFIED IDEOGRAPH:'DAA5:55973:琤 +CJK UNIFIED IDEOGRAPH:'DAA6:55974:琣 +CJK UNIFIED IDEOGRAPH:'DAA7:55975:琝 +CJK UNIFIED IDEOGRAPH:'DAA8:55976:琩 +CJK UNIFIED IDEOGRAPH:'DAA9:55977:琠 +CJK UNIFIED IDEOGRAPH:'DAAA:55978:琲 +CJK UNIFIED IDEOGRAPH:'DAAB:55979:瓻 +CJK UNIFIED IDEOGRAPH:'DAAC:55980:甯 +CJK UNIFIED IDEOGRAPH:'DAAD:55981:畯 +CJK UNIFIED IDEOGRAPH:'DAAE:55982:畬 +CJK UNIFIED IDEOGRAPH:'DAAF:55983:痧 +CJK UNIFIED IDEOGRAPH:'DAB0:55984:痚 +CJK UNIFIED IDEOGRAPH:'DAB1:55985:痡 +CJK UNIFIED IDEOGRAPH:'DAB2:55986:痦 +CJK UNIFIED IDEOGRAPH:'DAB3:55987:痝 +CJK UNIFIED IDEOGRAPH:'DAB4:55988:痟 +CJK UNIFIED IDEOGRAPH:'DAB5:55989:痤 +CJK UNIFIED IDEOGRAPH:'DAB6:55990:痗 +CJK UNIFIED IDEOGRAPH:'DAB7:55991:皕 +CJK UNIFIED IDEOGRAPH:'DAB8:55992:皒 +CJK UNIFIED IDEOGRAPH:'DAB9:55993:盚 +CJK UNIFIED IDEOGRAPH:'DABA:55994:睆 +CJK UNIFIED IDEOGRAPH:'DABB:55995:睇 +CJK UNIFIED IDEOGRAPH:'DABC:55996:睄 +CJK UNIFIED IDEOGRAPH:'DABD:55997:睍 +CJK UNIFIED IDEOGRAPH:'DABE:55998:睅 +CJK UNIFIED IDEOGRAPH:'DABF:55999:睊 +CJK UNIFIED IDEOGRAPH:'DAC0:56000:睎 +CJK UNIFIED IDEOGRAPH:'DAC1:56001:睋 +CJK UNIFIED IDEOGRAPH:'DAC2:56002:睌 +CJK UNIFIED IDEOGRAPH:'DAC3:56003:矞 +CJK UNIFIED IDEOGRAPH:'DAC4:56004:矬 +CJK UNIFIED IDEOGRAPH:'DAC5:56005:硠 +CJK UNIFIED IDEOGRAPH:'DAC6:56006:硤 +CJK UNIFIED IDEOGRAPH:'DAC7:56007:硥 +CJK UNIFIED IDEOGRAPH:'DAC8:56008:硜 +CJK UNIFIED IDEOGRAPH:'DAC9:56009:硭 +CJK UNIFIED IDEOGRAPH:'DACA:56010:硱 +CJK UNIFIED IDEOGRAPH:'DACB:56011:硪 +CJK UNIFIED IDEOGRAPH:'DACC:56012:确 +CJK UNIFIED IDEOGRAPH:'DACD:56013:硰 +CJK UNIFIED IDEOGRAPH:'DACE:56014:硩 +CJK UNIFIED IDEOGRAPH:'DACF:56015:硨 +CJK UNIFIED IDEOGRAPH:'DAD0:56016:硞 +CJK UNIFIED IDEOGRAPH:'DAD1:56017:硢 +CJK UNIFIED IDEOGRAPH:'DAD2:56018:祴 +CJK UNIFIED IDEOGRAPH:'DAD3:56019:祳 +CJK UNIFIED IDEOGRAPH:'DAD4:56020:祲 +CJK UNIFIED IDEOGRAPH:'DAD5:56021:祰 +CJK UNIFIED IDEOGRAPH:'DAD6:56022:稂 +CJK UNIFIED IDEOGRAPH:'DAD7:56023:稊 +CJK UNIFIED IDEOGRAPH:'DAD8:56024:稃 +CJK UNIFIED IDEOGRAPH:'DAD9:56025:稌 +CJK UNIFIED IDEOGRAPH:'DADA:56026:稄 +CJK UNIFIED IDEOGRAPH:'DADB:56027:窙 +CJK UNIFIED IDEOGRAPH:'DADC:56028:竦 +CJK UNIFIED IDEOGRAPH:'DADD:56029:竤 +CJK UNIFIED IDEOGRAPH:'DADE:56030:筊 +CJK UNIFIED IDEOGRAPH:'DADF:56031:笻 +CJK UNIFIED IDEOGRAPH:'DAE0:56032:筄 +CJK UNIFIED IDEOGRAPH:'DAE1:56033:筈 +CJK UNIFIED IDEOGRAPH:'DAE2:56034:筌 +CJK UNIFIED IDEOGRAPH:'DAE3:56035:筎 +CJK UNIFIED IDEOGRAPH:'DAE4:56036:筀 +CJK UNIFIED IDEOGRAPH:'DAE5:56037:筘 +CJK UNIFIED IDEOGRAPH:'DAE6:56038:筅 +CJK UNIFIED IDEOGRAPH:'DAE7:56039:粢 +CJK UNIFIED IDEOGRAPH:'DAE8:56040:粞 +CJK UNIFIED IDEOGRAPH:'DAE9:56041:粨 +CJK UNIFIED IDEOGRAPH:'DAEA:56042:粡 +CJK UNIFIED IDEOGRAPH:'DAEB:56043:絘 +CJK UNIFIED IDEOGRAPH:'DAEC:56044:絯 +CJK UNIFIED IDEOGRAPH:'DAED:56045:絣 +CJK UNIFIED IDEOGRAPH:'DAEE:56046:絓 +CJK UNIFIED IDEOGRAPH:'DAEF:56047:絖 +CJK UNIFIED IDEOGRAPH:'DAF0:56048:絧 +CJK UNIFIED IDEOGRAPH:'DAF1:56049:絪 +CJK UNIFIED IDEOGRAPH:'DAF2:56050:絏 +CJK UNIFIED IDEOGRAPH:'DAF3:56051:絭 +CJK UNIFIED IDEOGRAPH:'DAF4:56052:絜 +CJK UNIFIED IDEOGRAPH:'DAF5:56053:絫 +CJK UNIFIED IDEOGRAPH:'DAF6:56054:絒 +CJK UNIFIED IDEOGRAPH:'DAF7:56055:絔 +CJK UNIFIED IDEOGRAPH:'DAF8:56056:絩 +CJK UNIFIED IDEOGRAPH:'DAF9:56057:絑 +CJK UNIFIED IDEOGRAPH:'DAFA:56058:絟 +CJK UNIFIED IDEOGRAPH:'DAFB:56059:絎 +CJK UNIFIED IDEOGRAPH:'DAFC:56060:缾 +CJK UNIFIED IDEOGRAPH:'DAFD:56061:缿 +CJK UNIFIED IDEOGRAPH:'DAFE:56062:罥 +CJK UNIFIED IDEOGRAPH:'DB40:56128:罦 +CJK UNIFIED IDEOGRAPH:'DB41:56129:羢 +CJK UNIFIED IDEOGRAPH:'DB42:56130:羠 +CJK UNIFIED IDEOGRAPH:'DB43:56131:羡 +CJK UNIFIED IDEOGRAPH:'DB44:56132:翗 +CJK UNIFIED IDEOGRAPH:'DB45:56133:聑 +CJK UNIFIED IDEOGRAPH:'DB46:56134:聏 +CJK UNIFIED IDEOGRAPH:'DB47:56135:聐 +CJK UNIFIED IDEOGRAPH:'DB48:56136:胾 +CJK UNIFIED IDEOGRAPH:'DB49:56137:胔 +CJK UNIFIED IDEOGRAPH:'DB4A:56138:腃 +CJK UNIFIED IDEOGRAPH:'DB4B:56139:腊 +CJK UNIFIED IDEOGRAPH:'DB4C:56140:腒 +CJK UNIFIED IDEOGRAPH:'DB4D:56141:腏 +CJK UNIFIED IDEOGRAPH:'DB4E:56142:腇 +CJK UNIFIED IDEOGRAPH:'DB4F:56143:脽 +CJK UNIFIED IDEOGRAPH:'DB50:56144:腍 +CJK UNIFIED IDEOGRAPH:'DB51:56145:脺 +CJK UNIFIED IDEOGRAPH:'DB52:56146:臦 +CJK UNIFIED IDEOGRAPH:'DB53:56147:臮 +CJK UNIFIED IDEOGRAPH:'DB54:56148:臷 +CJK UNIFIED IDEOGRAPH:'DB55:56149:臸 +CJK UNIFIED IDEOGRAPH:'DB56:56150:臹 +CJK UNIFIED IDEOGRAPH:'DB57:56151:舄 +CJK UNIFIED IDEOGRAPH:'DB58:56152:舼 +CJK UNIFIED IDEOGRAPH:'DB59:56153:舽 +CJK UNIFIED IDEOGRAPH:'DB5A:56154:舿 +CJK UNIFIED IDEOGRAPH:'DB5B:56155:艵 +CJK UNIFIED IDEOGRAPH:'DB5C:56156:茻 +CJK UNIFIED IDEOGRAPH:'DB5D:56157:菏 +CJK UNIFIED IDEOGRAPH:'DB5E:56158:菹 +CJK UNIFIED IDEOGRAPH:'DB5F:56159:萣 +CJK UNIFIED IDEOGRAPH:'DB60:56160:菀 +CJK UNIFIED IDEOGRAPH:'DB61:56161:菨 +CJK UNIFIED IDEOGRAPH:'DB62:56162:萒 +CJK UNIFIED IDEOGRAPH:'DB63:56163:菧 +CJK UNIFIED IDEOGRAPH:'DB64:56164:菤 +CJK UNIFIED IDEOGRAPH:'DB65:56165:菼 +CJK UNIFIED IDEOGRAPH:'DB66:56166:菶 +CJK UNIFIED IDEOGRAPH:'DB67:56167:萐 +CJK UNIFIED IDEOGRAPH:'DB68:56168:菆 +CJK UNIFIED IDEOGRAPH:'DB69:56169:菈 +CJK UNIFIED IDEOGRAPH:'DB6A:56170:菫 +CJK UNIFIED IDEOGRAPH:'DB6B:56171:菣 +CJK UNIFIED IDEOGRAPH:'DB6C:56172:莿 +CJK UNIFIED IDEOGRAPH:'DB6D:56173:萁 +CJK UNIFIED IDEOGRAPH:'DB6E:56174:菝 +CJK UNIFIED IDEOGRAPH:'DB6F:56175:菥 +CJK UNIFIED IDEOGRAPH:'DB70:56176:菘 +CJK UNIFIED IDEOGRAPH:'DB71:56177:菿 +CJK UNIFIED IDEOGRAPH:'DB72:56178:菡 +CJK UNIFIED IDEOGRAPH:'DB73:56179:菋 +CJK UNIFIED IDEOGRAPH:'DB74:56180:菎 +CJK UNIFIED IDEOGRAPH:'DB75:56181:菖 +CJK UNIFIED IDEOGRAPH:'DB76:56182:菵 +CJK UNIFIED IDEOGRAPH:'DB77:56183:菉 +CJK UNIFIED IDEOGRAPH:'DB78:56184:萉 +CJK UNIFIED IDEOGRAPH:'DB79:56185:萏 +CJK UNIFIED IDEOGRAPH:'DB7A:56186:菞 +CJK UNIFIED IDEOGRAPH:'DB7B:56187:萑 +CJK UNIFIED IDEOGRAPH:'DB7C:56188:萆 +CJK UNIFIED IDEOGRAPH:'DB7D:56189:菂 +CJK UNIFIED IDEOGRAPH:'DB7E:56190:菳 +CJK UNIFIED IDEOGRAPH:'DBA1:56225:菕 +CJK UNIFIED IDEOGRAPH:'DBA2:56226:菺 +CJK UNIFIED IDEOGRAPH:'DBA3:56227:菇 +CJK UNIFIED IDEOGRAPH:'DBA4:56228:菑 +CJK UNIFIED IDEOGRAPH:'DBA5:56229:菪 +CJK UNIFIED IDEOGRAPH:'DBA6:56230:萓 +CJK UNIFIED IDEOGRAPH:'DBA7:56231:菃 +CJK UNIFIED IDEOGRAPH:'DBA8:56232:菬 +CJK UNIFIED IDEOGRAPH:'DBA9:56233:菮 +CJK UNIFIED IDEOGRAPH:'DBAA:56234:菄 +CJK UNIFIED IDEOGRAPH:'DBAB:56235:菻 +CJK UNIFIED IDEOGRAPH:'DBAC:56236:菗 +CJK UNIFIED IDEOGRAPH:'DBAD:56237:菢 +CJK UNIFIED IDEOGRAPH:'DBAE:56238:萛 +CJK UNIFIED IDEOGRAPH:'DBAF:56239:菛 +CJK UNIFIED IDEOGRAPH:'DBB0:56240:菾 +CJK UNIFIED IDEOGRAPH:'DBB1:56241:蛘 +CJK UNIFIED IDEOGRAPH:'DBB2:56242:蛢 +CJK UNIFIED IDEOGRAPH:'DBB3:56243:蛦 +CJK UNIFIED IDEOGRAPH:'DBB4:56244:蛓 +CJK UNIFIED IDEOGRAPH:'DBB5:56245:蛣 +CJK UNIFIED IDEOGRAPH:'DBB6:56246:蛚 +CJK UNIFIED IDEOGRAPH:'DBB7:56247:蛪 +CJK UNIFIED IDEOGRAPH:'DBB8:56248:蛝 +CJK UNIFIED IDEOGRAPH:'DBB9:56249:蛫 +CJK UNIFIED IDEOGRAPH:'DBBA:56250:蛜 +CJK UNIFIED IDEOGRAPH:'DBBB:56251:蛬 +CJK UNIFIED IDEOGRAPH:'DBBC:56252:蛩 +CJK UNIFIED IDEOGRAPH:'DBBD:56253:蛗 +CJK UNIFIED IDEOGRAPH:'DBBE:56254:蛨 +CJK UNIFIED IDEOGRAPH:'DBBF:56255:蛑 +CJK UNIFIED IDEOGRAPH:'DBC0:56256:衈 +CJK UNIFIED IDEOGRAPH:'DBC1:56257:衖 +CJK UNIFIED IDEOGRAPH:'DBC2:56258:衕 +CJK UNIFIED IDEOGRAPH:'DBC3:56259:袺 +CJK UNIFIED IDEOGRAPH:'DBC4:56260:裗 +CJK UNIFIED IDEOGRAPH:'DBC5:56261:袹 +CJK UNIFIED IDEOGRAPH:'DBC6:56262:袸 +CJK UNIFIED IDEOGRAPH:'DBC7:56263:裀 +CJK UNIFIED IDEOGRAPH:'DBC8:56264:袾 +CJK UNIFIED IDEOGRAPH:'DBC9:56265:袶 +CJK UNIFIED IDEOGRAPH:'DBCA:56266:袼 +CJK UNIFIED IDEOGRAPH:'DBCB:56267:袷 +CJK UNIFIED IDEOGRAPH:'DBCC:56268:袽 +CJK UNIFIED IDEOGRAPH:'DBCD:56269:袲 +CJK UNIFIED IDEOGRAPH:'DBCE:56270:褁 +CJK UNIFIED IDEOGRAPH:'DBCF:56271:裉 +CJK UNIFIED IDEOGRAPH:'DBD0:56272:覕 +CJK UNIFIED IDEOGRAPH:'DBD1:56273:覘 +CJK UNIFIED IDEOGRAPH:'DBD2:56274:覗 +CJK UNIFIED IDEOGRAPH:'DBD3:56275:觝 +CJK UNIFIED IDEOGRAPH:'DBD4:56276:觚 +CJK UNIFIED IDEOGRAPH:'DBD5:56277:觛 +CJK UNIFIED IDEOGRAPH:'DBD6:56278:詎 +CJK UNIFIED IDEOGRAPH:'DBD7:56279:詍 +CJK UNIFIED IDEOGRAPH:'DBD8:56280:訹 +CJK UNIFIED IDEOGRAPH:'DBD9:56281:詙 +CJK UNIFIED IDEOGRAPH:'DBDA:56282:詀 +CJK UNIFIED IDEOGRAPH:'DBDB:56283:詗 +CJK UNIFIED IDEOGRAPH:'DBDC:56284:詘 +CJK UNIFIED IDEOGRAPH:'DBDD:56285:詄 +CJK UNIFIED IDEOGRAPH:'DBDE:56286:詅 +CJK UNIFIED IDEOGRAPH:'DBDF:56287:詒 +CJK UNIFIED IDEOGRAPH:'DBE0:56288:詈 +CJK UNIFIED IDEOGRAPH:'DBE1:56289:詑 +CJK UNIFIED IDEOGRAPH:'DBE2:56290:詊 +CJK UNIFIED IDEOGRAPH:'DBE3:56291:詌 +CJK UNIFIED IDEOGRAPH:'DBE4:56292:詏 +CJK UNIFIED IDEOGRAPH:'DBE5:56293:豟 +CJK UNIFIED IDEOGRAPH:'DBE6:56294:貁 +CJK UNIFIED IDEOGRAPH:'DBE7:56295:貀 +CJK UNIFIED IDEOGRAPH:'DBE8:56296:貺 +CJK UNIFIED IDEOGRAPH:'DBE9:56297:貾 +CJK UNIFIED IDEOGRAPH:'DBEA:56298:貰 +CJK UNIFIED IDEOGRAPH:'DBEB:56299:貹 +CJK UNIFIED IDEOGRAPH:'DBEC:56300:貵 +CJK UNIFIED IDEOGRAPH:'DBED:56301:趄 +CJK UNIFIED IDEOGRAPH:'DBEE:56302:趀 +CJK UNIFIED IDEOGRAPH:'DBEF:56303:趉 +CJK UNIFIED IDEOGRAPH:'DBF0:56304:跘 +CJK UNIFIED IDEOGRAPH:'DBF1:56305:跓 +CJK UNIFIED IDEOGRAPH:'DBF2:56306:跍 +CJK UNIFIED IDEOGRAPH:'DBF3:56307:跇 +CJK UNIFIED IDEOGRAPH:'DBF4:56308:跖 +CJK UNIFIED IDEOGRAPH:'DBF5:56309:跜 +CJK UNIFIED IDEOGRAPH:'DBF6:56310:跏 +CJK UNIFIED IDEOGRAPH:'DBF7:56311:跕 +CJK UNIFIED IDEOGRAPH:'DBF8:56312:跙 +CJK UNIFIED IDEOGRAPH:'DBF9:56313:跈 +CJK UNIFIED IDEOGRAPH:'DBFA:56314:跗 +CJK UNIFIED IDEOGRAPH:'DBFB:56315:跅 +CJK UNIFIED IDEOGRAPH:'DBFC:56316:軯 +CJK UNIFIED IDEOGRAPH:'DBFD:56317:軷 +CJK UNIFIED IDEOGRAPH:'DBFE:56318:軺 +CJK UNIFIED IDEOGRAPH:'DC40:56384:軹 +CJK UNIFIED IDEOGRAPH:'DC41:56385:軦 +CJK UNIFIED IDEOGRAPH:'DC42:56386:軮 +CJK UNIFIED IDEOGRAPH:'DC43:56387:軥 +CJK UNIFIED IDEOGRAPH:'DC44:56388:軵 +CJK UNIFIED IDEOGRAPH:'DC45:56389:軧 +CJK UNIFIED IDEOGRAPH:'DC46:56390:軨 +CJK UNIFIED IDEOGRAPH:'DC47:56391:軶 +CJK UNIFIED IDEOGRAPH:'DC48:56392:軫 +CJK UNIFIED IDEOGRAPH:'DC49:56393:軱 +CJK UNIFIED IDEOGRAPH:'DC4A:56394:軬 +CJK UNIFIED IDEOGRAPH:'DC4B:56395:軴 +CJK UNIFIED IDEOGRAPH:'DC4C:56396:軩 +CJK UNIFIED IDEOGRAPH:'DC4D:56397:逭 +CJK UNIFIED IDEOGRAPH:'DC4E:56398:逴 +CJK UNIFIED IDEOGRAPH:'DC4F:56399:逯 +CJK UNIFIED IDEOGRAPH:'DC50:56400:鄆 +CJK UNIFIED IDEOGRAPH:'DC51:56401:鄬 +CJK UNIFIED IDEOGRAPH:'DC52:56402:鄄 +CJK UNIFIED IDEOGRAPH:'DC53:56403:郿 +CJK UNIFIED IDEOGRAPH:'DC54:56404:郼 +CJK UNIFIED IDEOGRAPH:'DC55:56405:鄈 +CJK UNIFIED IDEOGRAPH:'DC56:56406:郹 +CJK UNIFIED IDEOGRAPH:'DC57:56407:郻 +CJK UNIFIED IDEOGRAPH:'DC58:56408:鄁 +CJK UNIFIED IDEOGRAPH:'DC59:56409:鄀 +CJK UNIFIED IDEOGRAPH:'DC5A:56410:鄇 +CJK UNIFIED IDEOGRAPH:'DC5B:56411:鄅 +CJK UNIFIED IDEOGRAPH:'DC5C:56412:鄃 +CJK UNIFIED IDEOGRAPH:'DC5D:56413:酡 +CJK UNIFIED IDEOGRAPH:'DC5E:56414:酤 +CJK UNIFIED IDEOGRAPH:'DC5F:56415:酟 +CJK UNIFIED IDEOGRAPH:'DC60:56416:酢 +CJK UNIFIED IDEOGRAPH:'DC61:56417:酠 +CJK UNIFIED IDEOGRAPH:'DC62:56418:鈁 +CJK UNIFIED IDEOGRAPH:'DC63:56419:鈊 +CJK UNIFIED IDEOGRAPH:'DC64:56420:鈥 +CJK UNIFIED IDEOGRAPH:'DC65:56421:鈃 +CJK UNIFIED IDEOGRAPH:'DC66:56422:鈚 +CJK UNIFIED IDEOGRAPH:'DC67:56423:鈦 +CJK UNIFIED IDEOGRAPH:'DC68:56424:鈏 +CJK UNIFIED IDEOGRAPH:'DC69:56425:鈌 +CJK UNIFIED IDEOGRAPH:'DC6A:56426:鈀 +CJK UNIFIED IDEOGRAPH:'DC6B:56427:鈒 +CJK UNIFIED IDEOGRAPH:'DC6C:56428:釿 +CJK UNIFIED IDEOGRAPH:'DC6D:56429:釽 +CJK UNIFIED IDEOGRAPH:'DC6E:56430:鈆 +CJK UNIFIED IDEOGRAPH:'DC6F:56431:鈄 +CJK UNIFIED IDEOGRAPH:'DC70:56432:鈧 +CJK UNIFIED IDEOGRAPH:'DC71:56433:鈂 +CJK UNIFIED IDEOGRAPH:'DC72:56434:鈜 +CJK UNIFIED IDEOGRAPH:'DC73:56435:鈤 +CJK UNIFIED IDEOGRAPH:'DC74:56436:鈙 +CJK UNIFIED IDEOGRAPH:'DC75:56437:鈗 +CJK UNIFIED IDEOGRAPH:'DC76:56438:鈅 +CJK UNIFIED IDEOGRAPH:'DC77:56439:鈖 +CJK UNIFIED IDEOGRAPH:'DC78:56440:镻 +CJK UNIFIED IDEOGRAPH:'DC79:56441:閍 +CJK UNIFIED IDEOGRAPH:'DC7A:56442:閌 +CJK UNIFIED IDEOGRAPH:'DC7B:56443:閐 +CJK UNIFIED IDEOGRAPH:'DC7C:56444:隇 +CJK UNIFIED IDEOGRAPH:'DC7D:56445:陾 +CJK UNIFIED IDEOGRAPH:'DC7E:56446:隈 +CJK UNIFIED IDEOGRAPH:'DCA1:56481:隉 +CJK UNIFIED IDEOGRAPH:'DCA2:56482:隃 +CJK UNIFIED IDEOGRAPH:'DCA3:56483:隀 +CJK UNIFIED IDEOGRAPH:'DCA4:56484:雂 +CJK UNIFIED IDEOGRAPH:'DCA5:56485:雈 +CJK UNIFIED IDEOGRAPH:'DCA6:56486:雃 +CJK UNIFIED IDEOGRAPH:'DCA7:56487:雱 +CJK UNIFIED IDEOGRAPH:'DCA8:56488:雰 +CJK UNIFIED IDEOGRAPH:'DCA9:56489:靬 +CJK UNIFIED IDEOGRAPH:'DCAA:56490:靰 +CJK UNIFIED IDEOGRAPH:'DCAB:56491:靮 +CJK UNIFIED IDEOGRAPH:'DCAC:56492:頇 +CJK UNIFIED IDEOGRAPH:'DCAD:56493:颩 +CJK UNIFIED IDEOGRAPH:'DCAE:56494:飫 +CJK UNIFIED IDEOGRAPH:'DCAF:56495:鳦 +CJK UNIFIED IDEOGRAPH:'DCB0:56496:黹 +CJK UNIFIED IDEOGRAPH:'DCB1:56497:亃 +CJK UNIFIED IDEOGRAPH:'DCB2:56498:亄 +CJK UNIFIED IDEOGRAPH:'DCB3:56499:亶 +CJK UNIFIED IDEOGRAPH:'DCB4:56500:傽 +CJK UNIFIED IDEOGRAPH:'DCB5:56501:傿 +CJK UNIFIED IDEOGRAPH:'DCB6:56502:僆 +CJK UNIFIED IDEOGRAPH:'DCB7:56503:傮 +CJK UNIFIED IDEOGRAPH:'DCB8:56504:僄 +CJK UNIFIED IDEOGRAPH:'DCB9:56505:僊 +CJK UNIFIED IDEOGRAPH:'DCBA:56506:傴 +CJK UNIFIED IDEOGRAPH:'DCBB:56507:僈 +CJK UNIFIED IDEOGRAPH:'DCBC:56508:僂 +CJK UNIFIED IDEOGRAPH:'DCBD:56509:傰 +CJK UNIFIED IDEOGRAPH:'DCBE:56510:僁 +CJK UNIFIED IDEOGRAPH:'DCBF:56511:傺 +CJK UNIFIED IDEOGRAPH:'DCC0:56512:傱 +CJK UNIFIED IDEOGRAPH:'DCC1:56513:僋 +CJK UNIFIED IDEOGRAPH:'DCC2:56514:僉 +CJK UNIFIED IDEOGRAPH:'DCC3:56515:傶 +CJK UNIFIED IDEOGRAPH:'DCC4:56516:傸 +CJK UNIFIED IDEOGRAPH:'DCC5:56517:凗 +CJK UNIFIED IDEOGRAPH:'DCC6:56518:剺 +CJK UNIFIED IDEOGRAPH:'DCC7:56519:剸 +CJK UNIFIED IDEOGRAPH:'DCC8:56520:剻 +CJK UNIFIED IDEOGRAPH:'DCC9:56521:剼 +CJK UNIFIED IDEOGRAPH:'DCCA:56522:嗃 +CJK UNIFIED IDEOGRAPH:'DCCB:56523:嗛 +CJK UNIFIED IDEOGRAPH:'DCCC:56524:嗌 +CJK UNIFIED IDEOGRAPH:'DCCD:56525:嗐 +CJK UNIFIED IDEOGRAPH:'DCCE:56526:嗋 +CJK UNIFIED IDEOGRAPH:'DCCF:56527:嗊 +CJK UNIFIED IDEOGRAPH:'DCD0:56528:嗝 +CJK UNIFIED IDEOGRAPH:'DCD1:56529:嗀 +CJK UNIFIED IDEOGRAPH:'DCD2:56530:嗔 +CJK UNIFIED IDEOGRAPH:'DCD3:56531:嗄 +CJK UNIFIED IDEOGRAPH:'DCD4:56532:嗩 +CJK UNIFIED IDEOGRAPH:'DCD5:56533:喿 +CJK UNIFIED IDEOGRAPH:'DCD6:56534:嗒 +CJK UNIFIED IDEOGRAPH:'DCD7:56535:喍 +CJK UNIFIED IDEOGRAPH:'DCD8:56536:嗏 +CJK UNIFIED IDEOGRAPH:'DCD9:56537:嗕 +CJK UNIFIED IDEOGRAPH:'DCDA:56538:嗢 +CJK UNIFIED IDEOGRAPH:'DCDB:56539:嗖 +CJK UNIFIED IDEOGRAPH:'DCDC:56540:嗈 +CJK UNIFIED IDEOGRAPH:'DCDD:56541:嗲 +CJK UNIFIED IDEOGRAPH:'DCDE:56542:嗍 +CJK UNIFIED IDEOGRAPH:'DCDF:56543:嗙 +CJK UNIFIED IDEOGRAPH:'DCE0:56544:嗂 +CJK UNIFIED IDEOGRAPH:'DCE1:56545:圔 +CJK UNIFIED IDEOGRAPH:'DCE2:56546:塓 +CJK UNIFIED IDEOGRAPH:'DCE3:56547:塨 +CJK UNIFIED IDEOGRAPH:'DCE4:56548:塤 +CJK UNIFIED IDEOGRAPH:'DCE5:56549:塏 +CJK UNIFIED IDEOGRAPH:'DCE6:56550:塍 +CJK UNIFIED IDEOGRAPH:'DCE7:56551:塉 +CJK UNIFIED IDEOGRAPH:'DCE8:56552:塯 +CJK UNIFIED IDEOGRAPH:'DCE9:56553:塕 +CJK UNIFIED IDEOGRAPH:'DCEA:56554:塎 +CJK UNIFIED IDEOGRAPH:'DCEB:56555:塝 +CJK UNIFIED IDEOGRAPH:'DCEC:56556:塙 +CJK UNIFIED IDEOGRAPH:'DCED:56557:塥 +CJK UNIFIED IDEOGRAPH:'DCEE:56558:塛 +CJK UNIFIED IDEOGRAPH:'DCEF:56559:堽 +CJK UNIFIED IDEOGRAPH:'DCF0:56560:塣 +CJK UNIFIED IDEOGRAPH:'DCF1:56561:塱 +CJK UNIFIED IDEOGRAPH:'DCF2:56562:壼 +CJK UNIFIED IDEOGRAPH:'DCF3:56563:嫇 +CJK UNIFIED IDEOGRAPH:'DCF4:56564:嫄 +CJK UNIFIED IDEOGRAPH:'DCF5:56565:嫋 +CJK UNIFIED IDEOGRAPH:'DCF6:56566:媺 +CJK UNIFIED IDEOGRAPH:'DCF7:56567:媸 +CJK UNIFIED IDEOGRAPH:'DCF8:56568:媱 +CJK UNIFIED IDEOGRAPH:'DCF9:56569:媵 +CJK UNIFIED IDEOGRAPH:'DCFA:56570:媰 +CJK UNIFIED IDEOGRAPH:'DCFB:56571:媿 +CJK UNIFIED IDEOGRAPH:'DCFC:56572:嫈 +CJK UNIFIED IDEOGRAPH:'DCFD:56573:媻 +CJK UNIFIED IDEOGRAPH:'DCFE:56574:嫆 +CJK UNIFIED IDEOGRAPH:'DD40:56640:媷 +CJK UNIFIED IDEOGRAPH:'DD41:56641:嫀 +CJK UNIFIED IDEOGRAPH:'DD42:56642:嫊 +CJK UNIFIED IDEOGRAPH:'DD43:56643:媴 +CJK UNIFIED IDEOGRAPH:'DD44:56644:媶 +CJK UNIFIED IDEOGRAPH:'DD45:56645:嫍 +CJK UNIFIED IDEOGRAPH:'DD46:56646:媹 +CJK UNIFIED IDEOGRAPH:'DD47:56647:媐 +CJK UNIFIED IDEOGRAPH:'DD48:56648:寖 +CJK UNIFIED IDEOGRAPH:'DD49:56649:寘 +CJK UNIFIED IDEOGRAPH:'DD4A:56650:寙 +CJK UNIFIED IDEOGRAPH:'DD4B:56651:尟 +CJK UNIFIED IDEOGRAPH:'DD4C:56652:尳 +CJK UNIFIED IDEOGRAPH:'DD4D:56653:嵱 +CJK UNIFIED IDEOGRAPH:'DD4E:56654:嵣 +CJK UNIFIED IDEOGRAPH:'DD4F:56655:嵊 +CJK UNIFIED IDEOGRAPH:'DD50:56656:嵥 +CJK UNIFIED IDEOGRAPH:'DD51:56657:嵲 +CJK UNIFIED IDEOGRAPH:'DD52:56658:嵬 +CJK UNIFIED IDEOGRAPH:'DD53:56659:嵞 +CJK UNIFIED IDEOGRAPH:'DD54:56660:嵨 +CJK UNIFIED IDEOGRAPH:'DD55:56661:嵧 +CJK UNIFIED IDEOGRAPH:'DD56:56662:嵢 +CJK UNIFIED IDEOGRAPH:'DD57:56663:巰 +CJK UNIFIED IDEOGRAPH:'DD58:56664:幏 +CJK UNIFIED IDEOGRAPH:'DD59:56665:幎 +CJK UNIFIED IDEOGRAPH:'DD5A:56666:幊 +CJK UNIFIED IDEOGRAPH:'DD5B:56667:幍 +CJK UNIFIED IDEOGRAPH:'DD5C:56668:幋 +CJK UNIFIED IDEOGRAPH:'DD5D:56669:廅 +CJK UNIFIED IDEOGRAPH:'DD5E:56670:廌 +CJK UNIFIED IDEOGRAPH:'DD5F:56671:廆 +CJK UNIFIED IDEOGRAPH:'DD60:56672:廋 +CJK UNIFIED IDEOGRAPH:'DD61:56673:廇 +CJK UNIFIED IDEOGRAPH:'DD62:56674:彀 +CJK UNIFIED IDEOGRAPH:'DD63:56675:徯 +CJK UNIFIED IDEOGRAPH:'DD64:56676:徭 +CJK UNIFIED IDEOGRAPH:'DD65:56677:惷 +CJK UNIFIED IDEOGRAPH:'DD66:56678:慉 +CJK UNIFIED IDEOGRAPH:'DD67:56679:慊 +CJK UNIFIED IDEOGRAPH:'DD68:56680:愫 +CJK UNIFIED IDEOGRAPH:'DD69:56681:慅 +CJK UNIFIED IDEOGRAPH:'DD6A:56682:愶 +CJK UNIFIED IDEOGRAPH:'DD6B:56683:愲 +CJK UNIFIED IDEOGRAPH:'DD6C:56684:愮 +CJK UNIFIED IDEOGRAPH:'DD6D:56685:慆 +CJK UNIFIED IDEOGRAPH:'DD6E:56686:愯 +CJK UNIFIED IDEOGRAPH:'DD6F:56687:慏 +CJK UNIFIED IDEOGRAPH:'DD70:56688:愩 +CJK UNIFIED IDEOGRAPH:'DD71:56689:慀 +CJK UNIFIED IDEOGRAPH:'DD72:56690:戠 +CJK UNIFIED IDEOGRAPH:'DD73:56691:酨 +CJK UNIFIED IDEOGRAPH:'DD74:56692:戣 +CJK UNIFIED IDEOGRAPH:'DD75:56693:戥 +CJK UNIFIED IDEOGRAPH:'DD76:56694:戤 +CJK UNIFIED IDEOGRAPH:'DD77:56695:揅 +CJK UNIFIED IDEOGRAPH:'DD78:56696:揱 +CJK UNIFIED IDEOGRAPH:'DD79:56697:揫 +CJK UNIFIED IDEOGRAPH:'DD7A:56698:搐 +CJK UNIFIED IDEOGRAPH:'DD7B:56699:搒 +CJK UNIFIED IDEOGRAPH:'DD7C:56700:搉 +CJK UNIFIED IDEOGRAPH:'DD7D:56701:搠 +CJK UNIFIED IDEOGRAPH:'DD7E:56702:搤 +CJK UNIFIED IDEOGRAPH:'DDA1:56737:搳 +CJK UNIFIED IDEOGRAPH:'DDA2:56738:摃 +CJK UNIFIED IDEOGRAPH:'DDA3:56739:搟 +CJK UNIFIED IDEOGRAPH:'DDA4:56740:搕 +CJK UNIFIED IDEOGRAPH:'DDA5:56741:搘 +CJK UNIFIED IDEOGRAPH:'DDA6:56742:搹 +CJK UNIFIED IDEOGRAPH:'DDA7:56743:搷 +CJK UNIFIED IDEOGRAPH:'DDA8:56744:搢 +CJK UNIFIED IDEOGRAPH:'DDA9:56745:搣 +CJK UNIFIED IDEOGRAPH:'DDAA:56746:搌 +CJK UNIFIED IDEOGRAPH:'DDAB:56747:搦 +CJK UNIFIED IDEOGRAPH:'DDAC:56748:搰 +CJK UNIFIED IDEOGRAPH:'DDAD:56749:搨 +CJK UNIFIED IDEOGRAPH:'DDAE:56750:摁 +CJK UNIFIED IDEOGRAPH:'DDAF:56751:搵 +CJK UNIFIED IDEOGRAPH:'DDB0:56752:搯 +CJK UNIFIED IDEOGRAPH:'DDB1:56753:搊 +CJK UNIFIED IDEOGRAPH:'DDB2:56754:搚 +CJK UNIFIED IDEOGRAPH:'DDB3:56755:摀 +CJK UNIFIED IDEOGRAPH:'DDB4:56756:搥 +CJK UNIFIED IDEOGRAPH:'DDB5:56757:搧 +CJK UNIFIED IDEOGRAPH:'DDB6:56758:搋 +CJK UNIFIED IDEOGRAPH:'DDB7:56759:揧 +CJK UNIFIED IDEOGRAPH:'DDB8:56760:搛 +CJK UNIFIED IDEOGRAPH:'DDB9:56761:搮 +CJK UNIFIED IDEOGRAPH:'DDBA:56762:搡 +CJK UNIFIED IDEOGRAPH:'DDBB:56763:搎 +CJK UNIFIED IDEOGRAPH:'DDBC:56764:敯 +CJK UNIFIED IDEOGRAPH:'DDBD:56765:斒 +CJK UNIFIED IDEOGRAPH:'DDBE:56766:旓 +CJK UNIFIED IDEOGRAPH:'DDBF:56767:暆 +CJK UNIFIED IDEOGRAPH:'DDC0:56768:暌 +CJK UNIFIED IDEOGRAPH:'DDC1:56769:暕 +CJK UNIFIED IDEOGRAPH:'DDC2:56770:暐 +CJK UNIFIED IDEOGRAPH:'DDC3:56771:暋 +CJK UNIFIED IDEOGRAPH:'DDC4:56772:暊 +CJK UNIFIED IDEOGRAPH:'DDC5:56773:暙 +CJK UNIFIED IDEOGRAPH:'DDC6:56774:暔 +CJK UNIFIED IDEOGRAPH:'DDC7:56775:晸 +CJK UNIFIED IDEOGRAPH:'DDC8:56776:朠 +CJK UNIFIED IDEOGRAPH:'DDC9:56777:楦 +CJK UNIFIED IDEOGRAPH:'DDCA:56778:楟 +CJK UNIFIED IDEOGRAPH:'DDCB:56779:椸 +CJK UNIFIED IDEOGRAPH:'DDCC:56780:楎 +CJK UNIFIED IDEOGRAPH:'DDCD:56781:楢 +CJK UNIFIED IDEOGRAPH:'DDCE:56782:楱 +CJK UNIFIED IDEOGRAPH:'DDCF:56783:椿 +CJK UNIFIED IDEOGRAPH:'DDD0:56784:楅 +CJK UNIFIED IDEOGRAPH:'DDD1:56785:楪 +CJK UNIFIED IDEOGRAPH:'DDD2:56786:椹 +CJK UNIFIED IDEOGRAPH:'DDD3:56787:楂 +CJK UNIFIED IDEOGRAPH:'DDD4:56788:楗 +CJK UNIFIED IDEOGRAPH:'DDD5:56789:楙 +CJK UNIFIED IDEOGRAPH:'DDD6:56790:楺 +CJK UNIFIED IDEOGRAPH:'DDD7:56791:楈 +CJK UNIFIED IDEOGRAPH:'DDD8:56792:楉 +CJK UNIFIED IDEOGRAPH:'DDD9:56793:椵 +CJK UNIFIED IDEOGRAPH:'DDDA:56794:楬 +CJK UNIFIED IDEOGRAPH:'DDDB:56795:椳 +CJK UNIFIED IDEOGRAPH:'DDDC:56796:椽 +CJK UNIFIED IDEOGRAPH:'DDDD:56797:楥 +CJK UNIFIED IDEOGRAPH:'DDDE:56798:棰 +CJK UNIFIED IDEOGRAPH:'DDDF:56799:楸 +CJK UNIFIED IDEOGRAPH:'DDE0:56800:椴 +CJK UNIFIED IDEOGRAPH:'DDE1:56801:楩 +CJK UNIFIED IDEOGRAPH:'DDE2:56802:楀 +CJK UNIFIED IDEOGRAPH:'DDE3:56803:楯 +CJK UNIFIED IDEOGRAPH:'DDE4:56804:楄 +CJK UNIFIED IDEOGRAPH:'DDE5:56805:楶 +CJK UNIFIED IDEOGRAPH:'DDE6:56806:楘 +CJK UNIFIED IDEOGRAPH:'DDE7:56807:楁 +CJK UNIFIED IDEOGRAPH:'DDE8:56808:楴 +CJK UNIFIED IDEOGRAPH:'DDE9:56809:楌 +CJK UNIFIED IDEOGRAPH:'DDEA:56810:椻 +CJK UNIFIED IDEOGRAPH:'DDEB:56811:楋 +CJK UNIFIED IDEOGRAPH:'DDEC:56812:椷 +CJK UNIFIED IDEOGRAPH:'DDED:56813:楜 +CJK UNIFIED IDEOGRAPH:'DDEE:56814:楏 +CJK UNIFIED IDEOGRAPH:'DDEF:56815:楑 +CJK UNIFIED IDEOGRAPH:'DDF0:56816:椲 +CJK UNIFIED IDEOGRAPH:'DDF1:56817:楒 +CJK UNIFIED IDEOGRAPH:'DDF2:56818:椯 +CJK UNIFIED IDEOGRAPH:'DDF3:56819:楻 +CJK UNIFIED IDEOGRAPH:'DDF4:56820:椼 +CJK UNIFIED IDEOGRAPH:'DDF5:56821:歆 +CJK UNIFIED IDEOGRAPH:'DDF6:56822:歅 +CJK UNIFIED IDEOGRAPH:'DDF7:56823:歃 +CJK UNIFIED IDEOGRAPH:'DDF8:56824:歂 +CJK UNIFIED IDEOGRAPH:'DDF9:56825:歈 +CJK UNIFIED IDEOGRAPH:'DDFA:56826:歁 +CJK UNIFIED IDEOGRAPH:'DDFB:56827:殛 +CJK COMPATIBILITY IDEOGRAPH:'DDFC:56828:嗀 +CJK UNIFIED IDEOGRAPH:'DDFD:56829:毻 +CJK UNIFIED IDEOGRAPH:'DDFE:56830:毼 +CJK UNIFIED IDEOGRAPH:'DE40:56896:毹 +CJK UNIFIED IDEOGRAPH:'DE41:56897:毷 +CJK UNIFIED IDEOGRAPH:'DE42:56898:毸 +CJK UNIFIED IDEOGRAPH:'DE43:56899:溛 +CJK UNIFIED IDEOGRAPH:'DE44:56900:滖 +CJK UNIFIED IDEOGRAPH:'DE45:56901:滈 +CJK UNIFIED IDEOGRAPH:'DE46:56902:溏 +CJK UNIFIED IDEOGRAPH:'DE47:56903:滀 +CJK UNIFIED IDEOGRAPH:'DE48:56904:溟 +CJK UNIFIED IDEOGRAPH:'DE49:56905:溓 +CJK UNIFIED IDEOGRAPH:'DE4A:56906:溔 +CJK UNIFIED IDEOGRAPH:'DE4B:56907:溠 +CJK UNIFIED IDEOGRAPH:'DE4C:56908:溱 +CJK UNIFIED IDEOGRAPH:'DE4D:56909:溹 +CJK UNIFIED IDEOGRAPH:'DE4E:56910:滆 +CJK UNIFIED IDEOGRAPH:'DE4F:56911:滒 +CJK UNIFIED IDEOGRAPH:'DE50:56912:溽 +CJK UNIFIED IDEOGRAPH:'DE51:56913:滁 +CJK UNIFIED IDEOGRAPH:'DE52:56914:溞 +CJK UNIFIED IDEOGRAPH:'DE53:56915:滉 +CJK UNIFIED IDEOGRAPH:'DE54:56916:溷 +CJK UNIFIED IDEOGRAPH:'DE55:56917:溰 +CJK UNIFIED IDEOGRAPH:'DE56:56918:滍 +CJK UNIFIED IDEOGRAPH:'DE57:56919:溦 +CJK UNIFIED IDEOGRAPH:'DE58:56920:滏 +CJK UNIFIED IDEOGRAPH:'DE59:56921:溲 +CJK UNIFIED IDEOGRAPH:'DE5A:56922:溾 +CJK UNIFIED IDEOGRAPH:'DE5B:56923:滃 +CJK UNIFIED IDEOGRAPH:'DE5C:56924:滜 +CJK UNIFIED IDEOGRAPH:'DE5D:56925:滘 +CJK UNIFIED IDEOGRAPH:'DE5E:56926:溙 +CJK UNIFIED IDEOGRAPH:'DE5F:56927:溒 +CJK UNIFIED IDEOGRAPH:'DE60:56928:溎 +CJK UNIFIED IDEOGRAPH:'DE61:56929:溍 +CJK UNIFIED IDEOGRAPH:'DE62:56930:溤 +CJK UNIFIED IDEOGRAPH:'DE63:56931:溡 +CJK UNIFIED IDEOGRAPH:'DE64:56932:溿 +CJK UNIFIED IDEOGRAPH:'DE65:56933:溳 +CJK UNIFIED IDEOGRAPH:'DE66:56934:滐 +CJK UNIFIED IDEOGRAPH:'DE67:56935:滊 +CJK UNIFIED IDEOGRAPH:'DE68:56936:溗 +CJK UNIFIED IDEOGRAPH:'DE69:56937:溮 +CJK UNIFIED IDEOGRAPH:'DE6A:56938:溣 +CJK UNIFIED IDEOGRAPH:'DE6B:56939:煇 +CJK UNIFIED IDEOGRAPH:'DE6C:56940:煔 +CJK UNIFIED IDEOGRAPH:'DE6D:56941:煒 +CJK UNIFIED IDEOGRAPH:'DE6E:56942:煣 +CJK UNIFIED IDEOGRAPH:'DE6F:56943:煠 +CJK UNIFIED IDEOGRAPH:'DE70:56944:煁 +CJK UNIFIED IDEOGRAPH:'DE71:56945:煝 +CJK UNIFIED IDEOGRAPH:'DE72:56946:煢 +CJK UNIFIED IDEOGRAPH:'DE73:56947:煲 +CJK UNIFIED IDEOGRAPH:'DE74:56948:煸 +CJK UNIFIED IDEOGRAPH:'DE75:56949:煪 +CJK UNIFIED IDEOGRAPH:'DE76:56950:煡 +CJK UNIFIED IDEOGRAPH:'DE77:56951:煂 +CJK UNIFIED IDEOGRAPH:'DE78:56952:煘 +CJK UNIFIED IDEOGRAPH:'DE79:56953:煃 +CJK UNIFIED IDEOGRAPH:'DE7A:56954:煋 +CJK UNIFIED IDEOGRAPH:'DE7B:56955:煰 +CJK UNIFIED IDEOGRAPH:'DE7C:56956:煟 +CJK UNIFIED IDEOGRAPH:'DE7D:56957:煐 +CJK UNIFIED IDEOGRAPH:'DE7E:56958:煓 +CJK UNIFIED IDEOGRAPH:'DEA1:56993:煄 +CJK UNIFIED IDEOGRAPH:'DEA2:56994:煍 +CJK UNIFIED IDEOGRAPH:'DEA3:56995:煚 +CJK UNIFIED IDEOGRAPH:'DEA4:56996:牏 +CJK UNIFIED IDEOGRAPH:'DEA5:56997:犍 +CJK UNIFIED IDEOGRAPH:'DEA6:56998:犌 +CJK UNIFIED IDEOGRAPH:'DEA7:56999:犑 +CJK UNIFIED IDEOGRAPH:'DEA8:57000:犐 +CJK UNIFIED IDEOGRAPH:'DEA9:57001:犎 +CJK UNIFIED IDEOGRAPH:'DEAA:57002:猼 +CJK UNIFIED IDEOGRAPH:'DEAB:57003:獂 +CJK UNIFIED IDEOGRAPH:'DEAC:57004:猻 +CJK UNIFIED IDEOGRAPH:'DEAD:57005:猺 +CJK UNIFIED IDEOGRAPH:'DEAE:57006:獀 +CJK UNIFIED IDEOGRAPH:'DEAF:57007:獊 +CJK UNIFIED IDEOGRAPH:'DEB0:57008:獉 +CJK UNIFIED IDEOGRAPH:'DEB1:57009:瑄 +CJK UNIFIED IDEOGRAPH:'DEB2:57010:瑊 +CJK UNIFIED IDEOGRAPH:'DEB3:57011:瑋 +CJK UNIFIED IDEOGRAPH:'DEB4:57012:瑒 +CJK UNIFIED IDEOGRAPH:'DEB5:57013:瑑 +CJK UNIFIED IDEOGRAPH:'DEB6:57014:瑗 +CJK UNIFIED IDEOGRAPH:'DEB7:57015:瑀 +CJK UNIFIED IDEOGRAPH:'DEB8:57016:瑏 +CJK UNIFIED IDEOGRAPH:'DEB9:57017:瑐 +CJK UNIFIED IDEOGRAPH:'DEBA:57018:瑎 +CJK UNIFIED IDEOGRAPH:'DEBB:57019:瑂 +CJK UNIFIED IDEOGRAPH:'DEBC:57020:瑆 +CJK UNIFIED IDEOGRAPH:'DEBD:57021:瑍 +CJK UNIFIED IDEOGRAPH:'DEBE:57022:瑔 +CJK UNIFIED IDEOGRAPH:'DEBF:57023:瓡 +CJK UNIFIED IDEOGRAPH:'DEC0:57024:瓿 +CJK UNIFIED IDEOGRAPH:'DEC1:57025:瓾 +CJK UNIFIED IDEOGRAPH:'DEC2:57026:瓽 +CJK UNIFIED IDEOGRAPH:'DEC3:57027:甝 +CJK UNIFIED IDEOGRAPH:'DEC4:57028:畹 +CJK UNIFIED IDEOGRAPH:'DEC5:57029:畷 +CJK UNIFIED IDEOGRAPH:'DEC6:57030:榃 +CJK UNIFIED IDEOGRAPH:'DEC7:57031:痯 +CJK UNIFIED IDEOGRAPH:'DEC8:57032:瘏 +CJK UNIFIED IDEOGRAPH:'DEC9:57033:瘃 +CJK UNIFIED IDEOGRAPH:'DECA:57034:痷 +CJK UNIFIED IDEOGRAPH:'DECB:57035:痾 +CJK UNIFIED IDEOGRAPH:'DECC:57036:痼 +CJK UNIFIED IDEOGRAPH:'DECD:57037:痹 +CJK UNIFIED IDEOGRAPH:'DECE:57038:痸 +CJK UNIFIED IDEOGRAPH:'DECF:57039:瘐 +CJK UNIFIED IDEOGRAPH:'DED0:57040:痻 +CJK UNIFIED IDEOGRAPH:'DED1:57041:痶 +CJK UNIFIED IDEOGRAPH:'DED2:57042:痭 +CJK UNIFIED IDEOGRAPH:'DED3:57043:痵 +CJK UNIFIED IDEOGRAPH:'DED4:57044:痽 +CJK UNIFIED IDEOGRAPH:'DED5:57045:皙 +CJK UNIFIED IDEOGRAPH:'DED6:57046:皵 +CJK UNIFIED IDEOGRAPH:'DED7:57047:盝 +CJK UNIFIED IDEOGRAPH:'DED8:57048:睕 +CJK UNIFIED IDEOGRAPH:'DED9:57049:睟 +CJK UNIFIED IDEOGRAPH:'DEDA:57050:睠 +CJK UNIFIED IDEOGRAPH:'DEDB:57051:睒 +CJK UNIFIED IDEOGRAPH:'DEDC:57052:睖 +CJK UNIFIED IDEOGRAPH:'DEDD:57053:睚 +CJK UNIFIED IDEOGRAPH:'DEDE:57054:睩 +CJK UNIFIED IDEOGRAPH:'DEDF:57055:睧 +CJK UNIFIED IDEOGRAPH:'DEE0:57056:睔 +CJK UNIFIED IDEOGRAPH:'DEE1:57057:睙 +CJK UNIFIED IDEOGRAPH:'DEE2:57058:睭 +CJK UNIFIED IDEOGRAPH:'DEE3:57059:矠 +CJK UNIFIED IDEOGRAPH:'DEE4:57060:碇 +CJK UNIFIED IDEOGRAPH:'DEE5:57061:碚 +CJK UNIFIED IDEOGRAPH:'DEE6:57062:碔 +CJK UNIFIED IDEOGRAPH:'DEE7:57063:碏 +CJK UNIFIED IDEOGRAPH:'DEE8:57064:碄 +CJK UNIFIED IDEOGRAPH:'DEE9:57065:碕 +CJK UNIFIED IDEOGRAPH:'DEEA:57066:碅 +CJK UNIFIED IDEOGRAPH:'DEEB:57067:碆 +CJK UNIFIED IDEOGRAPH:'DEEC:57068:碡 +CJK UNIFIED IDEOGRAPH:'DEED:57069:碃 +CJK UNIFIED IDEOGRAPH:'DEEE:57070:硹 +CJK UNIFIED IDEOGRAPH:'DEEF:57071:碙 +CJK UNIFIED IDEOGRAPH:'DEF0:57072:碀 +CJK UNIFIED IDEOGRAPH:'DEF1:57073:碖 +CJK UNIFIED IDEOGRAPH:'DEF2:57074:硻 +CJK UNIFIED IDEOGRAPH:'DEF3:57075:祼 +CJK UNIFIED IDEOGRAPH:'DEF4:57076:禂 +CJK UNIFIED IDEOGRAPH:'DEF5:57077:祽 +CJK UNIFIED IDEOGRAPH:'DEF6:57078:祹 +CJK UNIFIED IDEOGRAPH:'DEF7:57079:稑 +CJK UNIFIED IDEOGRAPH:'DEF8:57080:稘 +CJK UNIFIED IDEOGRAPH:'DEF9:57081:稙 +CJK UNIFIED IDEOGRAPH:'DEFA:57082:稒 +CJK UNIFIED IDEOGRAPH:'DEFB:57083:稗 +CJK UNIFIED IDEOGRAPH:'DEFC:57084:稕 +CJK UNIFIED IDEOGRAPH:'DEFD:57085:稢 +CJK UNIFIED IDEOGRAPH:'DEFE:57086:稓 +CJK UNIFIED IDEOGRAPH:'DF40:57152:稛 +CJK UNIFIED IDEOGRAPH:'DF41:57153:稐 +CJK UNIFIED IDEOGRAPH:'DF42:57154:窣 +CJK UNIFIED IDEOGRAPH:'DF43:57155:窢 +CJK UNIFIED IDEOGRAPH:'DF44:57156:窞 +CJK UNIFIED IDEOGRAPH:'DF45:57157:竫 +CJK UNIFIED IDEOGRAPH:'DF46:57158:筦 +CJK UNIFIED IDEOGRAPH:'DF47:57159:筤 +CJK UNIFIED IDEOGRAPH:'DF48:57160:筭 +CJK UNIFIED IDEOGRAPH:'DF49:57161:筴 +CJK UNIFIED IDEOGRAPH:'DF4A:57162:筩 +CJK UNIFIED IDEOGRAPH:'DF4B:57163:筲 +CJK UNIFIED IDEOGRAPH:'DF4C:57164:筥 +CJK UNIFIED IDEOGRAPH:'DF4D:57165:筳 +CJK UNIFIED IDEOGRAPH:'DF4E:57166:筱 +CJK UNIFIED IDEOGRAPH:'DF4F:57167:筰 +CJK UNIFIED IDEOGRAPH:'DF50:57168:筡 +CJK UNIFIED IDEOGRAPH:'DF51:57169:筸 +CJK UNIFIED IDEOGRAPH:'DF52:57170:筶 +CJK UNIFIED IDEOGRAPH:'DF53:57171:筣 +CJK UNIFIED IDEOGRAPH:'DF54:57172:粲 +CJK UNIFIED IDEOGRAPH:'DF55:57173:粴 +CJK UNIFIED IDEOGRAPH:'DF56:57174:粯 +CJK UNIFIED IDEOGRAPH:'DF57:57175:綈 +CJK UNIFIED IDEOGRAPH:'DF58:57176:綆 +CJK UNIFIED IDEOGRAPH:'DF59:57177:綀 +CJK UNIFIED IDEOGRAPH:'DF5A:57178:綍 +CJK UNIFIED IDEOGRAPH:'DF5B:57179:絿 +CJK UNIFIED IDEOGRAPH:'DF5C:57180:綅 +CJK UNIFIED IDEOGRAPH:'DF5D:57181:絺 +CJK UNIFIED IDEOGRAPH:'DF5E:57182:綎 +CJK UNIFIED IDEOGRAPH:'DF5F:57183:絻 +CJK UNIFIED IDEOGRAPH:'DF60:57184:綃 +CJK UNIFIED IDEOGRAPH:'DF61:57185:絼 +CJK UNIFIED IDEOGRAPH:'DF62:57186:綌 +CJK UNIFIED IDEOGRAPH:'DF63:57187:綔 +CJK UNIFIED IDEOGRAPH:'DF64:57188:綄 +CJK UNIFIED IDEOGRAPH:'DF65:57189:絽 +CJK UNIFIED IDEOGRAPH:'DF66:57190:綒 +CJK UNIFIED IDEOGRAPH:'DF67:57191:罭 +CJK UNIFIED IDEOGRAPH:'DF68:57192:罫 +CJK UNIFIED IDEOGRAPH:'DF69:57193:罧 +CJK UNIFIED IDEOGRAPH:'DF6A:57194:罨 +CJK UNIFIED IDEOGRAPH:'DF6B:57195:罬 +CJK UNIFIED IDEOGRAPH:'DF6C:57196:羦 +CJK UNIFIED IDEOGRAPH:'DF6D:57197:羥 +CJK UNIFIED IDEOGRAPH:'DF6E:57198:羧 +CJK UNIFIED IDEOGRAPH:'DF6F:57199:翛 +CJK UNIFIED IDEOGRAPH:'DF70:57200:翜 +CJK UNIFIED IDEOGRAPH:'DF71:57201:耡 +CJK UNIFIED IDEOGRAPH:'DF72:57202:腤 +CJK UNIFIED IDEOGRAPH:'DF73:57203:腠 +CJK UNIFIED IDEOGRAPH:'DF74:57204:腷 +CJK UNIFIED IDEOGRAPH:'DF75:57205:腜 +CJK UNIFIED IDEOGRAPH:'DF76:57206:腩 +CJK UNIFIED IDEOGRAPH:'DF77:57207:腛 +CJK UNIFIED IDEOGRAPH:'DF78:57208:腢 +CJK UNIFIED IDEOGRAPH:'DF79:57209:腲 +CJK UNIFIED IDEOGRAPH:'DF7A:57210:朡 +CJK UNIFIED IDEOGRAPH:'DF7B:57211:腞 +CJK UNIFIED IDEOGRAPH:'DF7C:57212:腶 +CJK UNIFIED IDEOGRAPH:'DF7D:57213:腧 +CJK UNIFIED IDEOGRAPH:'DF7E:57214:腯 +CJK UNIFIED IDEOGRAPH:'DFA1:57249:腄 +CJK UNIFIED IDEOGRAPH:'DFA2:57250:腡 +CJK UNIFIED IDEOGRAPH:'DFA3:57251:舝 +CJK UNIFIED IDEOGRAPH:'DFA4:57252:艉 +CJK UNIFIED IDEOGRAPH:'DFA5:57253:艄 +CJK UNIFIED IDEOGRAPH:'DFA6:57254:艀 +CJK UNIFIED IDEOGRAPH:'DFA7:57255:艂 +CJK UNIFIED IDEOGRAPH:'DFA8:57256:艅 +CJK UNIFIED IDEOGRAPH:'DFA9:57257:蓱 +CJK UNIFIED IDEOGRAPH:'DFAA:57258:萿 +CJK UNIFIED IDEOGRAPH:'DFAB:57259:葖 +CJK UNIFIED IDEOGRAPH:'DFAC:57260:葶 +CJK UNIFIED IDEOGRAPH:'DFAD:57261:葹 +CJK UNIFIED IDEOGRAPH:'DFAE:57262:蒏 +CJK UNIFIED IDEOGRAPH:'DFAF:57263:蒍 +CJK UNIFIED IDEOGRAPH:'DFB0:57264:葥 +CJK UNIFIED IDEOGRAPH:'DFB1:57265:葑 +CJK UNIFIED IDEOGRAPH:'DFB2:57266:葀 +CJK UNIFIED IDEOGRAPH:'DFB3:57267:蒆 +CJK UNIFIED IDEOGRAPH:'DFB4:57268:葧 +CJK UNIFIED IDEOGRAPH:'DFB5:57269:萰 +CJK UNIFIED IDEOGRAPH:'DFB6:57270:葍 +CJK UNIFIED IDEOGRAPH:'DFB7:57271:葽 +CJK UNIFIED IDEOGRAPH:'DFB8:57272:葚 +CJK UNIFIED IDEOGRAPH:'DFB9:57273:葙 +CJK UNIFIED IDEOGRAPH:'DFBA:57274:葴 +CJK UNIFIED IDEOGRAPH:'DFBB:57275:葳 +CJK UNIFIED IDEOGRAPH:'DFBC:57276:葝 +CJK UNIFIED IDEOGRAPH:'DFBD:57277:蔇 +CJK UNIFIED IDEOGRAPH:'DFBE:57278:葞 +CJK UNIFIED IDEOGRAPH:'DFBF:57279:萷 +CJK UNIFIED IDEOGRAPH:'DFC0:57280:萺 +CJK UNIFIED IDEOGRAPH:'DFC1:57281:萴 +CJK UNIFIED IDEOGRAPH:'DFC2:57282:葺 +CJK UNIFIED IDEOGRAPH:'DFC3:57283:葃 +CJK UNIFIED IDEOGRAPH:'DFC4:57284:葸 +CJK UNIFIED IDEOGRAPH:'DFC5:57285:萲 +CJK UNIFIED IDEOGRAPH:'DFC6:57286:葅 +CJK UNIFIED IDEOGRAPH:'DFC7:57287:萩 +CJK UNIFIED IDEOGRAPH:'DFC8:57288:菙 +CJK UNIFIED IDEOGRAPH:'DFC9:57289:葋 +CJK UNIFIED IDEOGRAPH:'DFCA:57290:萯 +CJK UNIFIED IDEOGRAPH:'DFCB:57291:葂 +CJK UNIFIED IDEOGRAPH:'DFCC:57292:萭 +CJK UNIFIED IDEOGRAPH:'DFCD:57293:葟 +CJK UNIFIED IDEOGRAPH:'DFCE:57294:葰 +CJK UNIFIED IDEOGRAPH:'DFCF:57295:萹 +CJK UNIFIED IDEOGRAPH:'DFD0:57296:葎 +CJK UNIFIED IDEOGRAPH:'DFD1:57297:葌 +CJK UNIFIED IDEOGRAPH:'DFD2:57298:葒 +CJK UNIFIED IDEOGRAPH:'DFD3:57299:葯 +CJK UNIFIED IDEOGRAPH:'DFD4:57300:蓅 +CJK UNIFIED IDEOGRAPH:'DFD5:57301:蒎 +CJK UNIFIED IDEOGRAPH:'DFD6:57302:萻 +CJK UNIFIED IDEOGRAPH:'DFD7:57303:葇 +CJK UNIFIED IDEOGRAPH:'DFD8:57304:萶 +CJK UNIFIED IDEOGRAPH:'DFD9:57305:萳 +CJK UNIFIED IDEOGRAPH:'DFDA:57306:葨 +CJK UNIFIED IDEOGRAPH:'DFDB:57307:葾 +CJK UNIFIED IDEOGRAPH:'DFDC:57308:葄 +CJK UNIFIED IDEOGRAPH:'DFDD:57309:萫 +CJK UNIFIED IDEOGRAPH:'DFDE:57310:葠 +CJK UNIFIED IDEOGRAPH:'DFDF:57311:葔 +CJK UNIFIED IDEOGRAPH:'DFE0:57312:葮 +CJK UNIFIED IDEOGRAPH:'DFE1:57313:葐 +CJK UNIFIED IDEOGRAPH:'DFE2:57314:蜋 +CJK UNIFIED IDEOGRAPH:'DFE3:57315:蜄 +CJK UNIFIED IDEOGRAPH:'DFE4:57316:蛷 +CJK UNIFIED IDEOGRAPH:'DFE5:57317:蜌 +CJK UNIFIED IDEOGRAPH:'DFE6:57318:蛺 +CJK UNIFIED IDEOGRAPH:'DFE7:57319:蛖 +CJK UNIFIED IDEOGRAPH:'DFE8:57320:蛵 +CJK UNIFIED IDEOGRAPH:'DFE9:57321:蝍 +CJK UNIFIED IDEOGRAPH:'DFEA:57322:蛸 +CJK UNIFIED IDEOGRAPH:'DFEB:57323:蜎 +CJK UNIFIED IDEOGRAPH:'DFEC:57324:蜉 +CJK UNIFIED IDEOGRAPH:'DFED:57325:蜁 +CJK UNIFIED IDEOGRAPH:'DFEE:57326:蛶 +CJK UNIFIED IDEOGRAPH:'DFEF:57327:蜍 +CJK UNIFIED IDEOGRAPH:'DFF0:57328:蜅 +CJK UNIFIED IDEOGRAPH:'DFF1:57329:裖 +CJK UNIFIED IDEOGRAPH:'DFF2:57330:裋 +CJK UNIFIED IDEOGRAPH:'DFF3:57331:裍 +CJK UNIFIED IDEOGRAPH:'DFF4:57332:裎 +CJK UNIFIED IDEOGRAPH:'DFF5:57333:裞 +CJK UNIFIED IDEOGRAPH:'DFF6:57334:裛 +CJK UNIFIED IDEOGRAPH:'DFF7:57335:裚 +CJK UNIFIED IDEOGRAPH:'DFF8:57336:裌 +CJK UNIFIED IDEOGRAPH:'DFF9:57337:裐 +CJK UNIFIED IDEOGRAPH:'DFFA:57338:覅 +CJK UNIFIED IDEOGRAPH:'DFFB:57339:覛 +CJK UNIFIED IDEOGRAPH:'DFFC:57340:觟 +CJK UNIFIED IDEOGRAPH:'DFFD:57341:觥 +CJK UNIFIED IDEOGRAPH:'DFFE:57342:觤 +CJK UNIFIED IDEOGRAPH:'E040:57408:觡 +CJK UNIFIED IDEOGRAPH:'E041:57409:觠 +CJK UNIFIED IDEOGRAPH:'E042:57410:觢 +CJK UNIFIED IDEOGRAPH:'E043:57411:觜 +CJK UNIFIED IDEOGRAPH:'E044:57412:触 +CJK UNIFIED IDEOGRAPH:'E045:57413:詶 +CJK UNIFIED IDEOGRAPH:'E046:57414:誆 +CJK UNIFIED IDEOGRAPH:'E047:57415:詿 +CJK UNIFIED IDEOGRAPH:'E048:57416:詡 +CJK UNIFIED IDEOGRAPH:'E049:57417:訿 +CJK UNIFIED IDEOGRAPH:'E04A:57418:詷 +CJK UNIFIED IDEOGRAPH:'E04B:57419:誂 +CJK UNIFIED IDEOGRAPH:'E04C:57420:誄 +CJK UNIFIED IDEOGRAPH:'E04D:57421:詵 +CJK UNIFIED IDEOGRAPH:'E04E:57422:誃 +CJK UNIFIED IDEOGRAPH:'E04F:57423:誁 +CJK UNIFIED IDEOGRAPH:'E050:57424:詴 +CJK UNIFIED IDEOGRAPH:'E051:57425:詺 +CJK UNIFIED IDEOGRAPH:'E052:57426:谼 +CJK UNIFIED IDEOGRAPH:'E053:57427:豋 +CJK UNIFIED IDEOGRAPH:'E054:57428:豊 +CJK UNIFIED IDEOGRAPH:'E055:57429:豥 +CJK UNIFIED IDEOGRAPH:'E056:57430:豤 +CJK UNIFIED IDEOGRAPH:'E057:57431:豦 +CJK UNIFIED IDEOGRAPH:'E058:57432:貆 +CJK UNIFIED IDEOGRAPH:'E059:57433:貄 +CJK UNIFIED IDEOGRAPH:'E05A:57434:貅 +CJK UNIFIED IDEOGRAPH:'E05B:57435:賌 +CJK UNIFIED IDEOGRAPH:'E05C:57436:赨 +CJK UNIFIED IDEOGRAPH:'E05D:57437:赩 +CJK UNIFIED IDEOGRAPH:'E05E:57438:趑 +CJK UNIFIED IDEOGRAPH:'E05F:57439:趌 +CJK UNIFIED IDEOGRAPH:'E060:57440:趎 +CJK UNIFIED IDEOGRAPH:'E061:57441:趏 +CJK UNIFIED IDEOGRAPH:'E062:57442:趍 +CJK UNIFIED IDEOGRAPH:'E063:57443:趓 +CJK UNIFIED IDEOGRAPH:'E064:57444:趔 +CJK UNIFIED IDEOGRAPH:'E065:57445:趐 +CJK UNIFIED IDEOGRAPH:'E066:57446:趒 +CJK UNIFIED IDEOGRAPH:'E067:57447:跰 +CJK UNIFIED IDEOGRAPH:'E068:57448:跠 +CJK UNIFIED IDEOGRAPH:'E069:57449:跬 +CJK UNIFIED IDEOGRAPH:'E06A:57450:跱 +CJK UNIFIED IDEOGRAPH:'E06B:57451:跮 +CJK UNIFIED IDEOGRAPH:'E06C:57452:跐 +CJK UNIFIED IDEOGRAPH:'E06D:57453:跩 +CJK UNIFIED IDEOGRAPH:'E06E:57454:跣 +CJK UNIFIED IDEOGRAPH:'E06F:57455:跢 +CJK UNIFIED IDEOGRAPH:'E070:57456:跧 +CJK UNIFIED IDEOGRAPH:'E071:57457:跲 +CJK UNIFIED IDEOGRAPH:'E072:57458:跫 +CJK UNIFIED IDEOGRAPH:'E073:57459:跴 +CJK UNIFIED IDEOGRAPH:'E074:57460:輆 +CJK UNIFIED IDEOGRAPH:'E075:57461:軿 +CJK UNIFIED IDEOGRAPH:'E076:57462:輁 +CJK UNIFIED IDEOGRAPH:'E077:57463:輀 +CJK UNIFIED IDEOGRAPH:'E078:57464:輅 +CJK UNIFIED IDEOGRAPH:'E079:57465:輇 +CJK UNIFIED IDEOGRAPH:'E07A:57466:輈 +CJK UNIFIED IDEOGRAPH:'E07B:57467:輂 +CJK UNIFIED IDEOGRAPH:'E07C:57468:輋 +CJK UNIFIED IDEOGRAPH:'E07D:57469:遒 +CJK UNIFIED IDEOGRAPH:'E07E:57470:逿 +CJK UNIFIED IDEOGRAPH:'E0A1:57505:遄 +CJK UNIFIED IDEOGRAPH:'E0A2:57506:遉 +CJK UNIFIED IDEOGRAPH:'E0A3:57507:逽 +CJK UNIFIED IDEOGRAPH:'E0A4:57508:鄐 +CJK UNIFIED IDEOGRAPH:'E0A5:57509:鄍 +CJK UNIFIED IDEOGRAPH:'E0A6:57510:鄏 +CJK UNIFIED IDEOGRAPH:'E0A7:57511:鄑 +CJK UNIFIED IDEOGRAPH:'E0A8:57512:鄖 +CJK UNIFIED IDEOGRAPH:'E0A9:57513:鄔 +CJK UNIFIED IDEOGRAPH:'E0AA:57514:鄋 +CJK UNIFIED IDEOGRAPH:'E0AB:57515:鄎 +CJK UNIFIED IDEOGRAPH:'E0AC:57516:酮 +CJK UNIFIED IDEOGRAPH:'E0AD:57517:酯 +CJK UNIFIED IDEOGRAPH:'E0AE:57518:鉈 +CJK UNIFIED IDEOGRAPH:'E0AF:57519:鉒 +CJK UNIFIED IDEOGRAPH:'E0B0:57520:鈰 +CJK UNIFIED IDEOGRAPH:'E0B1:57521:鈺 +CJK UNIFIED IDEOGRAPH:'E0B2:57522:鉦 +CJK UNIFIED IDEOGRAPH:'E0B3:57523:鈳 +CJK UNIFIED IDEOGRAPH:'E0B4:57524:鉥 +CJK UNIFIED IDEOGRAPH:'E0B5:57525:鉞 +CJK UNIFIED IDEOGRAPH:'E0B6:57526:銃 +CJK UNIFIED IDEOGRAPH:'E0B7:57527:鈮 +CJK UNIFIED IDEOGRAPH:'E0B8:57528:鉊 +CJK UNIFIED IDEOGRAPH:'E0B9:57529:鉆 +CJK UNIFIED IDEOGRAPH:'E0BA:57530:鉭 +CJK UNIFIED IDEOGRAPH:'E0BB:57531:鉬 +CJK UNIFIED IDEOGRAPH:'E0BC:57532:鉏 +CJK UNIFIED IDEOGRAPH:'E0BD:57533:鉠 +CJK UNIFIED IDEOGRAPH:'E0BE:57534:鉧 +CJK UNIFIED IDEOGRAPH:'E0BF:57535:鉯 +CJK UNIFIED IDEOGRAPH:'E0C0:57536:鈶 +CJK UNIFIED IDEOGRAPH:'E0C1:57537:鉡 +CJK UNIFIED IDEOGRAPH:'E0C2:57538:鉰 +CJK UNIFIED IDEOGRAPH:'E0C3:57539:鈱 +CJK UNIFIED IDEOGRAPH:'E0C4:57540:鉔 +CJK UNIFIED IDEOGRAPH:'E0C5:57541:鉣 +CJK UNIFIED IDEOGRAPH:'E0C6:57542:鉐 +CJK UNIFIED IDEOGRAPH:'E0C7:57543:鉲 +CJK UNIFIED IDEOGRAPH:'E0C8:57544:鉎 +CJK UNIFIED IDEOGRAPH:'E0C9:57545:鉓 +CJK UNIFIED IDEOGRAPH:'E0CA:57546:鉌 +CJK UNIFIED IDEOGRAPH:'E0CB:57547:鉖 +CJK UNIFIED IDEOGRAPH:'E0CC:57548:鈲 +CJK UNIFIED IDEOGRAPH:'E0CD:57549:閟 +CJK UNIFIED IDEOGRAPH:'E0CE:57550:閜 +CJK UNIFIED IDEOGRAPH:'E0CF:57551:閞 +CJK UNIFIED IDEOGRAPH:'E0D0:57552:閛 +CJK UNIFIED IDEOGRAPH:'E0D1:57553:隒 +CJK UNIFIED IDEOGRAPH:'E0D2:57554:隓 +CJK UNIFIED IDEOGRAPH:'E0D3:57555:隑 +CJK UNIFIED IDEOGRAPH:'E0D4:57556:隗 +CJK UNIFIED IDEOGRAPH:'E0D5:57557:雎 +CJK UNIFIED IDEOGRAPH:'E0D6:57558:雺 +CJK UNIFIED IDEOGRAPH:'E0D7:57559:雽 +CJK UNIFIED IDEOGRAPH:'E0D8:57560:雸 +CJK UNIFIED IDEOGRAPH:'E0D9:57561:雵 +CJK UNIFIED IDEOGRAPH:'E0DA:57562:靳 +CJK UNIFIED IDEOGRAPH:'E0DB:57563:靷 +CJK UNIFIED IDEOGRAPH:'E0DC:57564:靸 +CJK UNIFIED IDEOGRAPH:'E0DD:57565:靲 +CJK UNIFIED IDEOGRAPH:'E0DE:57566:頏 +CJK UNIFIED IDEOGRAPH:'E0DF:57567:頍 +CJK UNIFIED IDEOGRAPH:'E0E0:57568:頎 +CJK UNIFIED IDEOGRAPH:'E0E1:57569:颬 +CJK UNIFIED IDEOGRAPH:'E0E2:57570:飶 +CJK UNIFIED IDEOGRAPH:'E0E3:57571:飹 +CJK UNIFIED IDEOGRAPH:'E0E4:57572:馯 +CJK UNIFIED IDEOGRAPH:'E0E5:57573:馲 +CJK UNIFIED IDEOGRAPH:'E0E6:57574:馰 +CJK UNIFIED IDEOGRAPH:'E0E7:57575:馵 +CJK UNIFIED IDEOGRAPH:'E0E8:57576:骭 +CJK UNIFIED IDEOGRAPH:'E0E9:57577:骫 +CJK UNIFIED IDEOGRAPH:'E0EA:57578:魛 +CJK UNIFIED IDEOGRAPH:'E0EB:57579:鳪 +CJK UNIFIED IDEOGRAPH:'E0EC:57580:鳭 +CJK UNIFIED IDEOGRAPH:'E0ED:57581:鳧 +CJK UNIFIED IDEOGRAPH:'E0EE:57582:麀 +CJK UNIFIED IDEOGRAPH:'E0EF:57583:黽 +CJK UNIFIED IDEOGRAPH:'E0F0:57584:僦 +CJK UNIFIED IDEOGRAPH:'E0F1:57585:僔 +CJK UNIFIED IDEOGRAPH:'E0F2:57586:僗 +CJK UNIFIED IDEOGRAPH:'E0F3:57587:僨 +CJK UNIFIED IDEOGRAPH:'E0F4:57588:僳 +CJK UNIFIED IDEOGRAPH:'E0F5:57589:僛 +CJK UNIFIED IDEOGRAPH:'E0F6:57590:僪 +CJK UNIFIED IDEOGRAPH:'E0F7:57591:僝 +CJK UNIFIED IDEOGRAPH:'E0F8:57592:僤 +CJK UNIFIED IDEOGRAPH:'E0F9:57593:僓 +CJK UNIFIED IDEOGRAPH:'E0FA:57594:僬 +CJK UNIFIED IDEOGRAPH:'E0FB:57595:僰 +CJK UNIFIED IDEOGRAPH:'E0FC:57596:僯 +CJK UNIFIED IDEOGRAPH:'E0FD:57597:僣 +CJK UNIFIED IDEOGRAPH:'E0FE:57598:僠 +CJK UNIFIED IDEOGRAPH:'E140:57664:凘 +CJK UNIFIED IDEOGRAPH:'E141:57665:劀 +CJK UNIFIED IDEOGRAPH:'E142:57666:劁 +CJK UNIFIED IDEOGRAPH:'E143:57667:勩 +CJK UNIFIED IDEOGRAPH:'E144:57668:勫 +CJK UNIFIED IDEOGRAPH:'E145:57669:匰 +CJK UNIFIED IDEOGRAPH:'E146:57670:厬 +CJK UNIFIED IDEOGRAPH:'E147:57671:嘧 +CJK UNIFIED IDEOGRAPH:'E148:57672:嘕 +CJK UNIFIED IDEOGRAPH:'E149:57673:嘌 +CJK UNIFIED IDEOGRAPH:'E14A:57674:嘒 +CJK UNIFIED IDEOGRAPH:'E14B:57675:嗼 +CJK UNIFIED IDEOGRAPH:'E14C:57676:嘏 +CJK UNIFIED IDEOGRAPH:'E14D:57677:嘜 +CJK UNIFIED IDEOGRAPH:'E14E:57678:嘁 +CJK UNIFIED IDEOGRAPH:'E14F:57679:嘓 +CJK UNIFIED IDEOGRAPH:'E150:57680:嘂 +CJK UNIFIED IDEOGRAPH:'E151:57681:嗺 +CJK UNIFIED IDEOGRAPH:'E152:57682:嘝 +CJK UNIFIED IDEOGRAPH:'E153:57683:嘄 +CJK UNIFIED IDEOGRAPH:'E154:57684:嗿 +CJK UNIFIED IDEOGRAPH:'E155:57685:嗹 +CJK UNIFIED IDEOGRAPH:'E156:57686:墉 +CJK UNIFIED IDEOGRAPH:'E157:57687:塼 +CJK UNIFIED IDEOGRAPH:'E158:57688:墐 +CJK UNIFIED IDEOGRAPH:'E159:57689:墘 +CJK UNIFIED IDEOGRAPH:'E15A:57690:墆 +CJK UNIFIED IDEOGRAPH:'E15B:57691:墁 +CJK UNIFIED IDEOGRAPH:'E15C:57692:塿 +CJK UNIFIED IDEOGRAPH:'E15D:57693:塴 +CJK UNIFIED IDEOGRAPH:'E15E:57694:墋 +CJK UNIFIED IDEOGRAPH:'E15F:57695:塺 +CJK UNIFIED IDEOGRAPH:'E160:57696:墇 +CJK UNIFIED IDEOGRAPH:'E161:57697:墑 +CJK UNIFIED IDEOGRAPH:'E162:57698:墎 +CJK UNIFIED IDEOGRAPH:'E163:57699:塶 +CJK UNIFIED IDEOGRAPH:'E164:57700:墂 +CJK UNIFIED IDEOGRAPH:'E165:57701:墈 +CJK UNIFIED IDEOGRAPH:'E166:57702:塻 +CJK UNIFIED IDEOGRAPH:'E167:57703:墔 +CJK UNIFIED IDEOGRAPH:'E168:57704:墏 +CJK UNIFIED IDEOGRAPH:'E169:57705:壾 +CJK UNIFIED IDEOGRAPH:'E16A:57706:奫 +CJK UNIFIED IDEOGRAPH:'E16B:57707:嫜 +CJK UNIFIED IDEOGRAPH:'E16C:57708:嫮 +CJK UNIFIED IDEOGRAPH:'E16D:57709:嫥 +CJK UNIFIED IDEOGRAPH:'E16E:57710:嫕 +CJK UNIFIED IDEOGRAPH:'E16F:57711:嫪 +CJK UNIFIED IDEOGRAPH:'E170:57712:嫚 +CJK UNIFIED IDEOGRAPH:'E171:57713:嫭 +CJK UNIFIED IDEOGRAPH:'E172:57714:嫫 +CJK UNIFIED IDEOGRAPH:'E173:57715:嫳 +CJK UNIFIED IDEOGRAPH:'E174:57716:嫢 +CJK UNIFIED IDEOGRAPH:'E175:57717:嫠 +CJK UNIFIED IDEOGRAPH:'E176:57718:嫛 +CJK UNIFIED IDEOGRAPH:'E177:57719:嫬 +CJK UNIFIED IDEOGRAPH:'E178:57720:嫞 +CJK UNIFIED IDEOGRAPH:'E179:57721:嫝 +CJK UNIFIED IDEOGRAPH:'E17A:57722:嫙 +CJK UNIFIED IDEOGRAPH:'E17B:57723:嫨 +CJK UNIFIED IDEOGRAPH:'E17C:57724:嫟 +CJK UNIFIED IDEOGRAPH:'E17D:57725:孷 +CJK UNIFIED IDEOGRAPH:'E17E:57726:寠 +CJK UNIFIED IDEOGRAPH:'E1A1:57761:寣 +CJK UNIFIED IDEOGRAPH:'E1A2:57762:屣 +CJK UNIFIED IDEOGRAPH:'E1A3:57763:嶂 +CJK UNIFIED IDEOGRAPH:'E1A4:57764:嶀 +CJK UNIFIED IDEOGRAPH:'E1A5:57765:嵽 +CJK UNIFIED IDEOGRAPH:'E1A6:57766:嶆 +CJK UNIFIED IDEOGRAPH:'E1A7:57767:嵺 +CJK UNIFIED IDEOGRAPH:'E1A8:57768:嶁 +CJK UNIFIED IDEOGRAPH:'E1A9:57769:嵷 +CJK UNIFIED IDEOGRAPH:'E1AA:57770:嶊 +CJK UNIFIED IDEOGRAPH:'E1AB:57771:嶉 +CJK UNIFIED IDEOGRAPH:'E1AC:57772:嶈 +CJK UNIFIED IDEOGRAPH:'E1AD:57773:嵾 +CJK UNIFIED IDEOGRAPH:'E1AE:57774:嵼 +CJK UNIFIED IDEOGRAPH:'E1AF:57775:嶍 +CJK UNIFIED IDEOGRAPH:'E1B0:57776:嵹 +CJK UNIFIED IDEOGRAPH:'E1B1:57777:嵿 +CJK UNIFIED IDEOGRAPH:'E1B2:57778:幘 +CJK UNIFIED IDEOGRAPH:'E1B3:57779:幙 +CJK UNIFIED IDEOGRAPH:'E1B4:57780:幓 +CJK UNIFIED IDEOGRAPH:'E1B5:57781:廘 +CJK UNIFIED IDEOGRAPH:'E1B6:57782:廑 +CJK UNIFIED IDEOGRAPH:'E1B7:57783:廗 +CJK UNIFIED IDEOGRAPH:'E1B8:57784:廎 +CJK UNIFIED IDEOGRAPH:'E1B9:57785:廜 +CJK UNIFIED IDEOGRAPH:'E1BA:57786:廕 +CJK UNIFIED IDEOGRAPH:'E1BB:57787:廙 +CJK UNIFIED IDEOGRAPH:'E1BC:57788:廒 +CJK UNIFIED IDEOGRAPH:'E1BD:57789:廔 +CJK UNIFIED IDEOGRAPH:'E1BE:57790:彄 +CJK UNIFIED IDEOGRAPH:'E1BF:57791:彃 +CJK UNIFIED IDEOGRAPH:'E1C0:57792:彯 +CJK UNIFIED IDEOGRAPH:'E1C1:57793:徶 +CJK UNIFIED IDEOGRAPH:'E1C2:57794:愬 +CJK UNIFIED IDEOGRAPH:'E1C3:57795:愨 +CJK UNIFIED IDEOGRAPH:'E1C4:57796:慁 +CJK UNIFIED IDEOGRAPH:'E1C5:57797:慞 +CJK UNIFIED IDEOGRAPH:'E1C6:57798:慱 +CJK UNIFIED IDEOGRAPH:'E1C7:57799:慳 +CJK UNIFIED IDEOGRAPH:'E1C8:57800:慒 +CJK UNIFIED IDEOGRAPH:'E1C9:57801:慓 +CJK UNIFIED IDEOGRAPH:'E1CA:57802:慲 +CJK UNIFIED IDEOGRAPH:'E1CB:57803:慬 +CJK UNIFIED IDEOGRAPH:'E1CC:57804:憀 +CJK UNIFIED IDEOGRAPH:'E1CD:57805:慴 +CJK UNIFIED IDEOGRAPH:'E1CE:57806:慔 +CJK UNIFIED IDEOGRAPH:'E1CF:57807:慺 +CJK UNIFIED IDEOGRAPH:'E1D0:57808:慛 +CJK UNIFIED IDEOGRAPH:'E1D1:57809:慥 +CJK UNIFIED IDEOGRAPH:'E1D2:57810:愻 +CJK UNIFIED IDEOGRAPH:'E1D3:57811:慪 +CJK UNIFIED IDEOGRAPH:'E1D4:57812:慡 +CJK UNIFIED IDEOGRAPH:'E1D5:57813:慖 +CJK UNIFIED IDEOGRAPH:'E1D6:57814:戩 +CJK UNIFIED IDEOGRAPH:'E1D7:57815:戧 +CJK UNIFIED IDEOGRAPH:'E1D8:57816:戫 +CJK UNIFIED IDEOGRAPH:'E1D9:57817:搫 +CJK UNIFIED IDEOGRAPH:'E1DA:57818:摍 +CJK UNIFIED IDEOGRAPH:'E1DB:57819:摛 +CJK UNIFIED IDEOGRAPH:'E1DC:57820:摝 +CJK UNIFIED IDEOGRAPH:'E1DD:57821:摴 +CJK UNIFIED IDEOGRAPH:'E1DE:57822:摶 +CJK UNIFIED IDEOGRAPH:'E1DF:57823:摲 +CJK UNIFIED IDEOGRAPH:'E1E0:57824:摳 +CJK UNIFIED IDEOGRAPH:'E1E1:57825:摽 +CJK UNIFIED IDEOGRAPH:'E1E2:57826:摵 +CJK UNIFIED IDEOGRAPH:'E1E3:57827:摦 +CJK UNIFIED IDEOGRAPH:'E1E4:57828:撦 +CJK UNIFIED IDEOGRAPH:'E1E5:57829:摎 +CJK UNIFIED IDEOGRAPH:'E1E6:57830:撂 +CJK UNIFIED IDEOGRAPH:'E1E7:57831:摞 +CJK UNIFIED IDEOGRAPH:'E1E8:57832:摜 +CJK UNIFIED IDEOGRAPH:'E1E9:57833:摋 +CJK UNIFIED IDEOGRAPH:'E1EA:57834:摓 +CJK UNIFIED IDEOGRAPH:'E1EB:57835:摠 +CJK UNIFIED IDEOGRAPH:'E1EC:57836:摐 +CJK UNIFIED IDEOGRAPH:'E1ED:57837:摿 +CJK UNIFIED IDEOGRAPH:'E1EE:57838:搿 +CJK UNIFIED IDEOGRAPH:'E1EF:57839:摬 +CJK UNIFIED IDEOGRAPH:'E1F0:57840:摫 +CJK UNIFIED IDEOGRAPH:'E1F1:57841:摙 +CJK UNIFIED IDEOGRAPH:'E1F2:57842:摥 +CJK UNIFIED IDEOGRAPH:'E1F3:57843:摷 +CJK UNIFIED IDEOGRAPH:'E1F4:57844:敳 +CJK UNIFIED IDEOGRAPH:'E1F5:57845:斠 +CJK UNIFIED IDEOGRAPH:'E1F6:57846:暡 +CJK UNIFIED IDEOGRAPH:'E1F7:57847:暠 +CJK UNIFIED IDEOGRAPH:'E1F8:57848:暟 +CJK UNIFIED IDEOGRAPH:'E1F9:57849:朅 +CJK UNIFIED IDEOGRAPH:'E1FA:57850:朄 +CJK UNIFIED IDEOGRAPH:'E1FB:57851:朢 +CJK UNIFIED IDEOGRAPH:'E1FC:57852:榱 +CJK UNIFIED IDEOGRAPH:'E1FD:57853:榶 +CJK UNIFIED IDEOGRAPH:'E1FE:57854:槉 +CJK UNIFIED IDEOGRAPH:'E240:57920:榠 +CJK UNIFIED IDEOGRAPH:'E241:57921:槎 +CJK UNIFIED IDEOGRAPH:'E242:57922:榖 +CJK UNIFIED IDEOGRAPH:'E243:57923:榰 +CJK UNIFIED IDEOGRAPH:'E244:57924:榬 +CJK UNIFIED IDEOGRAPH:'E245:57925:榼 +CJK UNIFIED IDEOGRAPH:'E246:57926:榑 +CJK UNIFIED IDEOGRAPH:'E247:57927:榙 +CJK UNIFIED IDEOGRAPH:'E248:57928:榎 +CJK UNIFIED IDEOGRAPH:'E249:57929:榧 +CJK UNIFIED IDEOGRAPH:'E24A:57930:榍 +CJK UNIFIED IDEOGRAPH:'E24B:57931:榩 +CJK UNIFIED IDEOGRAPH:'E24C:57932:榾 +CJK UNIFIED IDEOGRAPH:'E24D:57933:榯 +CJK UNIFIED IDEOGRAPH:'E24E:57934:榿 +CJK UNIFIED IDEOGRAPH:'E24F:57935:槄 +CJK UNIFIED IDEOGRAPH:'E250:57936:榽 +CJK UNIFIED IDEOGRAPH:'E251:57937:榤 +CJK UNIFIED IDEOGRAPH:'E252:57938:槔 +CJK UNIFIED IDEOGRAPH:'E253:57939:榹 +CJK UNIFIED IDEOGRAPH:'E254:57940:槊 +CJK UNIFIED IDEOGRAPH:'E255:57941:榚 +CJK UNIFIED IDEOGRAPH:'E256:57942:槏 +CJK UNIFIED IDEOGRAPH:'E257:57943:榳 +CJK UNIFIED IDEOGRAPH:'E258:57944:榓 +CJK UNIFIED IDEOGRAPH:'E259:57945:榪 +CJK UNIFIED IDEOGRAPH:'E25A:57946:榡 +CJK UNIFIED IDEOGRAPH:'E25B:57947:榞 +CJK UNIFIED IDEOGRAPH:'E25C:57948:槙 +CJK UNIFIED IDEOGRAPH:'E25D:57949:榗 +CJK UNIFIED IDEOGRAPH:'E25E:57950:榐 +CJK UNIFIED IDEOGRAPH:'E25F:57951:槂 +CJK UNIFIED IDEOGRAPH:'E260:57952:榵 +CJK UNIFIED IDEOGRAPH:'E261:57953:榥 +CJK UNIFIED IDEOGRAPH:'E262:57954:槆 +CJK UNIFIED IDEOGRAPH:'E263:57955:歊 +CJK UNIFIED IDEOGRAPH:'E264:57956:歍 +CJK UNIFIED IDEOGRAPH:'E265:57957:歋 +CJK UNIFIED IDEOGRAPH:'E266:57958:殞 +CJK UNIFIED IDEOGRAPH:'E267:57959:殟 +CJK UNIFIED IDEOGRAPH:'E268:57960:殠 +CJK UNIFIED IDEOGRAPH:'E269:57961:毃 +CJK UNIFIED IDEOGRAPH:'E26A:57962:毄 +CJK UNIFIED IDEOGRAPH:'E26B:57963:毾 +CJK UNIFIED IDEOGRAPH:'E26C:57964:滎 +CJK UNIFIED IDEOGRAPH:'E26D:57965:滵 +CJK UNIFIED IDEOGRAPH:'E26E:57966:滱 +CJK UNIFIED IDEOGRAPH:'E26F:57967:漃 +CJK UNIFIED IDEOGRAPH:'E270:57968:漥 +CJK UNIFIED IDEOGRAPH:'E271:57969:滸 +CJK UNIFIED IDEOGRAPH:'E272:57970:漷 +CJK UNIFIED IDEOGRAPH:'E273:57971:滻 +CJK UNIFIED IDEOGRAPH:'E274:57972:漮 +CJK UNIFIED IDEOGRAPH:'E275:57973:漉 +CJK UNIFIED IDEOGRAPH:'E276:57974:潎 +CJK UNIFIED IDEOGRAPH:'E277:57975:漙 +CJK UNIFIED IDEOGRAPH:'E278:57976:漚 +CJK UNIFIED IDEOGRAPH:'E279:57977:漧 +CJK UNIFIED IDEOGRAPH:'E27A:57978:漘 +CJK UNIFIED IDEOGRAPH:'E27B:57979:漻 +CJK UNIFIED IDEOGRAPH:'E27C:57980:漒 +CJK UNIFIED IDEOGRAPH:'E27D:57981:滭 +CJK UNIFIED IDEOGRAPH:'E27E:57982:漊 +CJK UNIFIED IDEOGRAPH:'E2A1:58017:漶 +CJK UNIFIED IDEOGRAPH:'E2A2:58018:潳 +CJK UNIFIED IDEOGRAPH:'E2A3:58019:滹 +CJK UNIFIED IDEOGRAPH:'E2A4:58020:滮 +CJK UNIFIED IDEOGRAPH:'E2A5:58021:漭 +CJK UNIFIED IDEOGRAPH:'E2A6:58022:潀 +CJK UNIFIED IDEOGRAPH:'E2A7:58023:漰 +CJK UNIFIED IDEOGRAPH:'E2A8:58024:漼 +CJK UNIFIED IDEOGRAPH:'E2A9:58025:漵 +CJK UNIFIED IDEOGRAPH:'E2AA:58026:滫 +CJK UNIFIED IDEOGRAPH:'E2AB:58027:漇 +CJK UNIFIED IDEOGRAPH:'E2AC:58028:漎 +CJK UNIFIED IDEOGRAPH:'E2AD:58029:潃 +CJK UNIFIED IDEOGRAPH:'E2AE:58030:漅 +CJK UNIFIED IDEOGRAPH:'E2AF:58031:滽 +CJK UNIFIED IDEOGRAPH:'E2B0:58032:滶 +CJK UNIFIED IDEOGRAPH:'E2B1:58033:漹 +CJK UNIFIED IDEOGRAPH:'E2B2:58034:漜 +CJK UNIFIED IDEOGRAPH:'E2B3:58035:滼 +CJK UNIFIED IDEOGRAPH:'E2B4:58036:漺 +CJK UNIFIED IDEOGRAPH:'E2B5:58037:漟 +CJK UNIFIED IDEOGRAPH:'E2B6:58038:漍 +CJK UNIFIED IDEOGRAPH:'E2B7:58039:漞 +CJK UNIFIED IDEOGRAPH:'E2B8:58040:漈 +CJK UNIFIED IDEOGRAPH:'E2B9:58041:漡 +CJK UNIFIED IDEOGRAPH:'E2BA:58042:熇 +CJK UNIFIED IDEOGRAPH:'E2BB:58043:熐 +CJK UNIFIED IDEOGRAPH:'E2BC:58044:熉 +CJK UNIFIED IDEOGRAPH:'E2BD:58045:熀 +CJK UNIFIED IDEOGRAPH:'E2BE:58046:熅 +CJK UNIFIED IDEOGRAPH:'E2BF:58047:熂 +CJK UNIFIED IDEOGRAPH:'E2C0:58048:熏 +CJK UNIFIED IDEOGRAPH:'E2C1:58049:煻 +CJK UNIFIED IDEOGRAPH:'E2C2:58050:熆 +CJK UNIFIED IDEOGRAPH:'E2C3:58051:熁 +CJK UNIFIED IDEOGRAPH:'E2C4:58052:熗 +CJK UNIFIED IDEOGRAPH:'E2C5:58053:牄 +CJK UNIFIED IDEOGRAPH:'E2C6:58054:牓 +CJK UNIFIED IDEOGRAPH:'E2C7:58055:犗 +CJK UNIFIED IDEOGRAPH:'E2C8:58056:犕 +CJK UNIFIED IDEOGRAPH:'E2C9:58057:犓 +CJK UNIFIED IDEOGRAPH:'E2CA:58058:獃 +CJK UNIFIED IDEOGRAPH:'E2CB:58059:獍 +CJK UNIFIED IDEOGRAPH:'E2CC:58060:獑 +CJK UNIFIED IDEOGRAPH:'E2CD:58061:獌 +CJK UNIFIED IDEOGRAPH:'E2CE:58062:瑢 +CJK UNIFIED IDEOGRAPH:'E2CF:58063:瑳 +CJK UNIFIED IDEOGRAPH:'E2D0:58064:瑱 +CJK UNIFIED IDEOGRAPH:'E2D1:58065:瑵 +CJK UNIFIED IDEOGRAPH:'E2D2:58066:瑲 +CJK UNIFIED IDEOGRAPH:'E2D3:58067:瑧 +CJK UNIFIED IDEOGRAPH:'E2D4:58068:瑮 +CJK UNIFIED IDEOGRAPH:'E2D5:58069:甀 +CJK UNIFIED IDEOGRAPH:'E2D6:58070:甂 +CJK UNIFIED IDEOGRAPH:'E2D7:58071:甃 +CJK UNIFIED IDEOGRAPH:'E2D8:58072:畽 +CJK UNIFIED IDEOGRAPH:'E2D9:58073:疐 +CJK UNIFIED IDEOGRAPH:'E2DA:58074:瘖 +CJK UNIFIED IDEOGRAPH:'E2DB:58075:瘈 +CJK UNIFIED IDEOGRAPH:'E2DC:58076:瘌 +CJK UNIFIED IDEOGRAPH:'E2DD:58077:瘕 +CJK UNIFIED IDEOGRAPH:'E2DE:58078:瘑 +CJK UNIFIED IDEOGRAPH:'E2DF:58079:瘊 +CJK UNIFIED IDEOGRAPH:'E2E0:58080:瘔 +CJK UNIFIED IDEOGRAPH:'E2E1:58081:皸 +CJK UNIFIED IDEOGRAPH:'E2E2:58082:瞁 +CJK UNIFIED IDEOGRAPH:'E2E3:58083:睼 +CJK UNIFIED IDEOGRAPH:'E2E4:58084:瞅 +CJK UNIFIED IDEOGRAPH:'E2E5:58085:瞂 +CJK UNIFIED IDEOGRAPH:'E2E6:58086:睮 +CJK UNIFIED IDEOGRAPH:'E2E7:58087:瞀 +CJK UNIFIED IDEOGRAPH:'E2E8:58088:睯 +CJK UNIFIED IDEOGRAPH:'E2E9:58089:睾 +CJK UNIFIED IDEOGRAPH:'E2EA:58090:瞃 +CJK UNIFIED IDEOGRAPH:'E2EB:58091:碲 +CJK UNIFIED IDEOGRAPH:'E2EC:58092:碪 +CJK UNIFIED IDEOGRAPH:'E2ED:58093:碴 +CJK UNIFIED IDEOGRAPH:'E2EE:58094:碭 +CJK UNIFIED IDEOGRAPH:'E2EF:58095:碨 +CJK UNIFIED IDEOGRAPH:'E2F0:58096:硾 +CJK UNIFIED IDEOGRAPH:'E2F1:58097:碫 +CJK UNIFIED IDEOGRAPH:'E2F2:58098:碞 +CJK UNIFIED IDEOGRAPH:'E2F3:58099:碥 +CJK UNIFIED IDEOGRAPH:'E2F4:58100:碠 +CJK UNIFIED IDEOGRAPH:'E2F5:58101:碬 +CJK UNIFIED IDEOGRAPH:'E2F6:58102:碢 +CJK UNIFIED IDEOGRAPH:'E2F7:58103:碤 +CJK UNIFIED IDEOGRAPH:'E2F8:58104:禘 +CJK UNIFIED IDEOGRAPH:'E2F9:58105:禊 +CJK UNIFIED IDEOGRAPH:'E2FA:58106:禋 +CJK UNIFIED IDEOGRAPH:'E2FB:58107:禖 +CJK UNIFIED IDEOGRAPH:'E2FC:58108:禕 +CJK UNIFIED IDEOGRAPH:'E2FD:58109:禔 +CJK UNIFIED IDEOGRAPH:'E2FE:58110:禓 +CJK UNIFIED IDEOGRAPH:'E340:58176:禗 +CJK UNIFIED IDEOGRAPH:'E341:58177:禈 +CJK UNIFIED IDEOGRAPH:'E342:58178:禒 +CJK UNIFIED IDEOGRAPH:'E343:58179:禐 +CJK UNIFIED IDEOGRAPH:'E344:58180:稫 +CJK UNIFIED IDEOGRAPH:'E345:58181:穊 +CJK UNIFIED IDEOGRAPH:'E346:58182:稰 +CJK UNIFIED IDEOGRAPH:'E347:58183:稯 +CJK UNIFIED IDEOGRAPH:'E348:58184:稨 +CJK UNIFIED IDEOGRAPH:'E349:58185:稦 +CJK UNIFIED IDEOGRAPH:'E34A:58186:窨 +CJK UNIFIED IDEOGRAPH:'E34B:58187:窫 +CJK UNIFIED IDEOGRAPH:'E34C:58188:窬 +CJK UNIFIED IDEOGRAPH:'E34D:58189:竮 +CJK UNIFIED IDEOGRAPH:'E34E:58190:箈 +CJK UNIFIED IDEOGRAPH:'E34F:58191:箜 +CJK UNIFIED IDEOGRAPH:'E350:58192:箊 +CJK UNIFIED IDEOGRAPH:'E351:58193:箑 +CJK UNIFIED IDEOGRAPH:'E352:58194:箐 +CJK UNIFIED IDEOGRAPH:'E353:58195:箖 +CJK UNIFIED IDEOGRAPH:'E354:58196:箍 +CJK UNIFIED IDEOGRAPH:'E355:58197:箌 +CJK UNIFIED IDEOGRAPH:'E356:58198:箛 +CJK UNIFIED IDEOGRAPH:'E357:58199:箎 +CJK UNIFIED IDEOGRAPH:'E358:58200:箅 +CJK UNIFIED IDEOGRAPH:'E359:58201:箘 +CJK UNIFIED IDEOGRAPH:'E35A:58202:劄 +CJK UNIFIED IDEOGRAPH:'E35B:58203:箙 +CJK UNIFIED IDEOGRAPH:'E35C:58204:箤 +CJK UNIFIED IDEOGRAPH:'E35D:58205:箂 +CJK UNIFIED IDEOGRAPH:'E35E:58206:粻 +CJK UNIFIED IDEOGRAPH:'E35F:58207:粿 +CJK UNIFIED IDEOGRAPH:'E360:58208:粼 +CJK UNIFIED IDEOGRAPH:'E361:58209:粺 +CJK UNIFIED IDEOGRAPH:'E362:58210:綧 +CJK UNIFIED IDEOGRAPH:'E363:58211:綷 +CJK UNIFIED IDEOGRAPH:'E364:58212:緂 +CJK UNIFIED IDEOGRAPH:'E365:58213:綣 +CJK UNIFIED IDEOGRAPH:'E366:58214:綪 +CJK UNIFIED IDEOGRAPH:'E367:58215:緁 +CJK UNIFIED IDEOGRAPH:'E368:58216:緀 +CJK UNIFIED IDEOGRAPH:'E369:58217:緅 +CJK UNIFIED IDEOGRAPH:'E36A:58218:綝 +CJK UNIFIED IDEOGRAPH:'E36B:58219:緎 +CJK UNIFIED IDEOGRAPH:'E36C:58220:緄 +CJK UNIFIED IDEOGRAPH:'E36D:58221:緆 +CJK UNIFIED IDEOGRAPH:'E36E:58222:緋 +CJK UNIFIED IDEOGRAPH:'E36F:58223:緌 +CJK UNIFIED IDEOGRAPH:'E370:58224:綯 +CJK UNIFIED IDEOGRAPH:'E371:58225:綹 +CJK UNIFIED IDEOGRAPH:'E372:58226:綖 +CJK UNIFIED IDEOGRAPH:'E373:58227:綼 +CJK UNIFIED IDEOGRAPH:'E374:58228:綟 +CJK UNIFIED IDEOGRAPH:'E375:58229:綦 +CJK UNIFIED IDEOGRAPH:'E376:58230:綮 +CJK UNIFIED IDEOGRAPH:'E377:58231:綩 +CJK UNIFIED IDEOGRAPH:'E378:58232:綡 +CJK UNIFIED IDEOGRAPH:'E379:58233:緉 +CJK UNIFIED IDEOGRAPH:'E37A:58234:罳 +CJK UNIFIED IDEOGRAPH:'E37B:58235:翢 +CJK UNIFIED IDEOGRAPH:'E37C:58236:翣 +CJK UNIFIED IDEOGRAPH:'E37D:58237:翥 +CJK UNIFIED IDEOGRAPH:'E37E:58238:翞 +CJK UNIFIED IDEOGRAPH:'E3A1:58273:耤 +CJK UNIFIED IDEOGRAPH:'E3A2:58274:聝 +CJK UNIFIED IDEOGRAPH:'E3A3:58275:聜 +CJK UNIFIED IDEOGRAPH:'E3A4:58276:膉 +CJK UNIFIED IDEOGRAPH:'E3A5:58277:膆 +CJK UNIFIED IDEOGRAPH:'E3A6:58278:膃 +CJK UNIFIED IDEOGRAPH:'E3A7:58279:膇 +CJK UNIFIED IDEOGRAPH:'E3A8:58280:膍 +CJK UNIFIED IDEOGRAPH:'E3A9:58281:膌 +CJK UNIFIED IDEOGRAPH:'E3AA:58282:膋 +CJK UNIFIED IDEOGRAPH:'E3AB:58283:舕 +CJK UNIFIED IDEOGRAPH:'E3AC:58284:蒗 +CJK UNIFIED IDEOGRAPH:'E3AD:58285:蒤 +CJK UNIFIED IDEOGRAPH:'E3AE:58286:蒡 +CJK UNIFIED IDEOGRAPH:'E3AF:58287:蒟 +CJK UNIFIED IDEOGRAPH:'E3B0:58288:蒺 +CJK UNIFIED IDEOGRAPH:'E3B1:58289:蓎 +CJK UNIFIED IDEOGRAPH:'E3B2:58290:蓂 +CJK UNIFIED IDEOGRAPH:'E3B3:58291:蒬 +CJK UNIFIED IDEOGRAPH:'E3B4:58292:蒮 +CJK UNIFIED IDEOGRAPH:'E3B5:58293:蒫 +CJK UNIFIED IDEOGRAPH:'E3B6:58294:蒹 +CJK UNIFIED IDEOGRAPH:'E3B7:58295:蒴 +CJK UNIFIED IDEOGRAPH:'E3B8:58296:蓁 +CJK UNIFIED IDEOGRAPH:'E3B9:58297:蓍 +CJK UNIFIED IDEOGRAPH:'E3BA:58298:蒪 +CJK UNIFIED IDEOGRAPH:'E3BB:58299:蒚 +CJK UNIFIED IDEOGRAPH:'E3BC:58300:蒱 +CJK UNIFIED IDEOGRAPH:'E3BD:58301:蓐 +CJK UNIFIED IDEOGRAPH:'E3BE:58302:蒝 +CJK UNIFIED IDEOGRAPH:'E3BF:58303:蒧 +CJK UNIFIED IDEOGRAPH:'E3C0:58304:蒻 +CJK UNIFIED IDEOGRAPH:'E3C1:58305:蒢 +CJK UNIFIED IDEOGRAPH:'E3C2:58306:蒔 +CJK UNIFIED IDEOGRAPH:'E3C3:58307:蓇 +CJK UNIFIED IDEOGRAPH:'E3C4:58308:蓌 +CJK UNIFIED IDEOGRAPH:'E3C5:58309:蒛 +CJK UNIFIED IDEOGRAPH:'E3C6:58310:蒩 +CJK UNIFIED IDEOGRAPH:'E3C7:58311:蒯 +CJK UNIFIED IDEOGRAPH:'E3C8:58312:蒨 +CJK UNIFIED IDEOGRAPH:'E3C9:58313:蓖 +CJK UNIFIED IDEOGRAPH:'E3CA:58314:蒘 +CJK UNIFIED IDEOGRAPH:'E3CB:58315:蒶 +CJK UNIFIED IDEOGRAPH:'E3CC:58316:蓏 +CJK UNIFIED IDEOGRAPH:'E3CD:58317:蒠 +CJK UNIFIED IDEOGRAPH:'E3CE:58318:蓗 +CJK UNIFIED IDEOGRAPH:'E3CF:58319:蓔 +CJK UNIFIED IDEOGRAPH:'E3D0:58320:蓒 +CJK UNIFIED IDEOGRAPH:'E3D1:58321:蓛 +CJK UNIFIED IDEOGRAPH:'E3D2:58322:蒰 +CJK UNIFIED IDEOGRAPH:'E3D3:58323:蒑 +CJK UNIFIED IDEOGRAPH:'E3D4:58324:虡 +CJK UNIFIED IDEOGRAPH:'E3D5:58325:蜳 +CJK UNIFIED IDEOGRAPH:'E3D6:58326:蜣 +CJK UNIFIED IDEOGRAPH:'E3D7:58327:蜨 +CJK UNIFIED IDEOGRAPH:'E3D8:58328:蝫 +CJK UNIFIED IDEOGRAPH:'E3D9:58329:蝀 +CJK UNIFIED IDEOGRAPH:'E3DA:58330:蜮 +CJK UNIFIED IDEOGRAPH:'E3DB:58331:蜞 +CJK UNIFIED IDEOGRAPH:'E3DC:58332:蜡 +CJK UNIFIED IDEOGRAPH:'E3DD:58333:蜙 +CJK UNIFIED IDEOGRAPH:'E3DE:58334:蜛 +CJK UNIFIED IDEOGRAPH:'E3DF:58335:蝃 +CJK UNIFIED IDEOGRAPH:'E3E0:58336:蜬 +CJK UNIFIED IDEOGRAPH:'E3E1:58337:蝁 +CJK UNIFIED IDEOGRAPH:'E3E2:58338:蜾 +CJK UNIFIED IDEOGRAPH:'E3E3:58339:蝆 +CJK UNIFIED IDEOGRAPH:'E3E4:58340:蜠 +CJK UNIFIED IDEOGRAPH:'E3E5:58341:蜲 +CJK UNIFIED IDEOGRAPH:'E3E6:58342:蜪 +CJK UNIFIED IDEOGRAPH:'E3E7:58343:蜭 +CJK UNIFIED IDEOGRAPH:'E3E8:58344:蜼 +CJK UNIFIED IDEOGRAPH:'E3E9:58345:蜒 +CJK UNIFIED IDEOGRAPH:'E3EA:58346:蜺 +CJK UNIFIED IDEOGRAPH:'E3EB:58347:蜱 +CJK UNIFIED IDEOGRAPH:'E3EC:58348:蜵 +CJK UNIFIED IDEOGRAPH:'E3ED:58349:蝂 +CJK UNIFIED IDEOGRAPH:'E3EE:58350:蜦 +CJK UNIFIED IDEOGRAPH:'E3EF:58351:蜧 +CJK UNIFIED IDEOGRAPH:'E3F0:58352:蜸 +CJK UNIFIED IDEOGRAPH:'E3F1:58353:蜤 +CJK UNIFIED IDEOGRAPH:'E3F2:58354:蜚 +CJK UNIFIED IDEOGRAPH:'E3F3:58355:蜰 +CJK UNIFIED IDEOGRAPH:'E3F4:58356:蜑 +CJK UNIFIED IDEOGRAPH:'E3F5:58357:裷 +CJK UNIFIED IDEOGRAPH:'E3F6:58358:裧 +CJK UNIFIED IDEOGRAPH:'E3F7:58359:裱 +CJK UNIFIED IDEOGRAPH:'E3F8:58360:裲 +CJK UNIFIED IDEOGRAPH:'E3F9:58361:裺 +CJK UNIFIED IDEOGRAPH:'E3FA:58362:裾 +CJK UNIFIED IDEOGRAPH:'E3FB:58363:裮 +CJK UNIFIED IDEOGRAPH:'E3FC:58364:裼 +CJK UNIFIED IDEOGRAPH:'E3FD:58365:裶 +CJK UNIFIED IDEOGRAPH:'E3FE:58366:裻 +CJK UNIFIED IDEOGRAPH:'E440:58432:裰 +CJK UNIFIED IDEOGRAPH:'E441:58433:裬 +CJK UNIFIED IDEOGRAPH:'E442:58434:裫 +CJK UNIFIED IDEOGRAPH:'E443:58435:覝 +CJK UNIFIED IDEOGRAPH:'E444:58436:覡 +CJK UNIFIED IDEOGRAPH:'E445:58437:覟 +CJK UNIFIED IDEOGRAPH:'E446:58438:覞 +CJK UNIFIED IDEOGRAPH:'E447:58439:觩 +CJK UNIFIED IDEOGRAPH:'E448:58440:觫 +CJK UNIFIED IDEOGRAPH:'E449:58441:觨 +CJK UNIFIED IDEOGRAPH:'E44A:58442:誫 +CJK UNIFIED IDEOGRAPH:'E44B:58443:誙 +CJK UNIFIED IDEOGRAPH:'E44C:58444:誋 +CJK UNIFIED IDEOGRAPH:'E44D:58445:誒 +CJK UNIFIED IDEOGRAPH:'E44E:58446:誏 +CJK UNIFIED IDEOGRAPH:'E44F:58447:誖 +CJK UNIFIED IDEOGRAPH:'E450:58448:谽 +CJK UNIFIED IDEOGRAPH:'E451:58449:豨 +CJK UNIFIED IDEOGRAPH:'E452:58450:豩 +CJK UNIFIED IDEOGRAPH:'E453:58451:賕 +CJK UNIFIED IDEOGRAPH:'E454:58452:賏 +CJK UNIFIED IDEOGRAPH:'E455:58453:賗 +CJK UNIFIED IDEOGRAPH:'E456:58454:趖 +CJK UNIFIED IDEOGRAPH:'E457:58455:踉 +CJK UNIFIED IDEOGRAPH:'E458:58456:踂 +CJK UNIFIED IDEOGRAPH:'E459:58457:跿 +CJK UNIFIED IDEOGRAPH:'E45A:58458:踍 +CJK UNIFIED IDEOGRAPH:'E45B:58459:跽 +CJK UNIFIED IDEOGRAPH:'E45C:58460:踊 +CJK UNIFIED IDEOGRAPH:'E45D:58461:踃 +CJK UNIFIED IDEOGRAPH:'E45E:58462:踇 +CJK UNIFIED IDEOGRAPH:'E45F:58463:踆 +CJK UNIFIED IDEOGRAPH:'E460:58464:踅 +CJK UNIFIED IDEOGRAPH:'E461:58465:跾 +CJK UNIFIED IDEOGRAPH:'E462:58466:踀 +CJK UNIFIED IDEOGRAPH:'E463:58467:踄 +CJK UNIFIED IDEOGRAPH:'E464:58468:輐 +CJK UNIFIED IDEOGRAPH:'E465:58469:輑 +CJK UNIFIED IDEOGRAPH:'E466:58470:輎 +CJK UNIFIED IDEOGRAPH:'E467:58471:輍 +CJK UNIFIED IDEOGRAPH:'E468:58472:鄣 +CJK UNIFIED IDEOGRAPH:'E469:58473:鄜 +CJK UNIFIED IDEOGRAPH:'E46A:58474:鄠 +CJK UNIFIED IDEOGRAPH:'E46B:58475:鄢 +CJK UNIFIED IDEOGRAPH:'E46C:58476:鄟 +CJK UNIFIED IDEOGRAPH:'E46D:58477:鄝 +CJK UNIFIED IDEOGRAPH:'E46E:58478:鄚 +CJK UNIFIED IDEOGRAPH:'E46F:58479:鄤 +CJK UNIFIED IDEOGRAPH:'E470:58480:鄡 +CJK UNIFIED IDEOGRAPH:'E471:58481:鄛 +CJK UNIFIED IDEOGRAPH:'E472:58482:酺 +CJK UNIFIED IDEOGRAPH:'E473:58483:酲 +CJK UNIFIED IDEOGRAPH:'E474:58484:酹 +CJK UNIFIED IDEOGRAPH:'E475:58485:酳 +CJK UNIFIED IDEOGRAPH:'E476:58486:銥 +CJK UNIFIED IDEOGRAPH:'E477:58487:銤 +CJK UNIFIED IDEOGRAPH:'E478:58488:鉶 +CJK UNIFIED IDEOGRAPH:'E479:58489:銛 +CJK UNIFIED IDEOGRAPH:'E47A:58490:鉺 +CJK UNIFIED IDEOGRAPH:'E47B:58491:銠 +CJK UNIFIED IDEOGRAPH:'E47C:58492:銔 +CJK UNIFIED IDEOGRAPH:'E47D:58493:銪 +CJK UNIFIED IDEOGRAPH:'E47E:58494:銍 +CJK UNIFIED IDEOGRAPH:'E4A1:58529:銦 +CJK UNIFIED IDEOGRAPH:'E4A2:58530:銚 +CJK UNIFIED IDEOGRAPH:'E4A3:58531:銫 +CJK UNIFIED IDEOGRAPH:'E4A4:58532:鉹 +CJK UNIFIED IDEOGRAPH:'E4A5:58533:銗 +CJK UNIFIED IDEOGRAPH:'E4A6:58534:鉿 +CJK UNIFIED IDEOGRAPH:'E4A7:58535:銣 +CJK UNIFIED IDEOGRAPH:'E4A8:58536:鋮 +CJK UNIFIED IDEOGRAPH:'E4A9:58537:銎 +CJK UNIFIED IDEOGRAPH:'E4AA:58538:銂 +CJK UNIFIED IDEOGRAPH:'E4AB:58539:銕 +CJK UNIFIED IDEOGRAPH:'E4AC:58540:銢 +CJK UNIFIED IDEOGRAPH:'E4AD:58541:鉽 +CJK UNIFIED IDEOGRAPH:'E4AE:58542:銈 +CJK UNIFIED IDEOGRAPH:'E4AF:58543:銡 +CJK UNIFIED IDEOGRAPH:'E4B0:58544:銊 +CJK UNIFIED IDEOGRAPH:'E4B1:58545:銆 +CJK UNIFIED IDEOGRAPH:'E4B2:58546:銌 +CJK UNIFIED IDEOGRAPH:'E4B3:58547:銙 +CJK UNIFIED IDEOGRAPH:'E4B4:58548:銧 +CJK UNIFIED IDEOGRAPH:'E4B5:58549:鉾 +CJK UNIFIED IDEOGRAPH:'E4B6:58550:銇 +CJK UNIFIED IDEOGRAPH:'E4B7:58551:銩 +CJK UNIFIED IDEOGRAPH:'E4B8:58552:銝 +CJK UNIFIED IDEOGRAPH:'E4B9:58553:銋 +CJK UNIFIED IDEOGRAPH:'E4BA:58554:鈭 +CJK UNIFIED IDEOGRAPH:'E4BB:58555:隞 +CJK UNIFIED IDEOGRAPH:'E4BC:58556:隡 +CJK UNIFIED IDEOGRAPH:'E4BD:58557:雿 +CJK UNIFIED IDEOGRAPH:'E4BE:58558:靘 +CJK UNIFIED IDEOGRAPH:'E4BF:58559:靽 +CJK UNIFIED IDEOGRAPH:'E4C0:58560:靺 +CJK UNIFIED IDEOGRAPH:'E4C1:58561:靾 +CJK UNIFIED IDEOGRAPH:'E4C2:58562:鞃 +CJK UNIFIED IDEOGRAPH:'E4C3:58563:鞀 +CJK UNIFIED IDEOGRAPH:'E4C4:58564:鞂 +CJK UNIFIED IDEOGRAPH:'E4C5:58565:靻 +CJK UNIFIED IDEOGRAPH:'E4C6:58566:鞄 +CJK UNIFIED IDEOGRAPH:'E4C7:58567:鞁 +CJK UNIFIED IDEOGRAPH:'E4C8:58568:靿 +CJK UNIFIED IDEOGRAPH:'E4C9:58569:韎 +CJK UNIFIED IDEOGRAPH:'E4CA:58570:韍 +CJK UNIFIED IDEOGRAPH:'E4CB:58571:頖 +CJK UNIFIED IDEOGRAPH:'E4CC:58572:颭 +CJK UNIFIED IDEOGRAPH:'E4CD:58573:颮 +CJK UNIFIED IDEOGRAPH:'E4CE:58574:餂 +CJK UNIFIED IDEOGRAPH:'E4CF:58575:餀 +CJK UNIFIED IDEOGRAPH:'E4D0:58576:餇 +CJK UNIFIED IDEOGRAPH:'E4D1:58577:馝 +CJK UNIFIED IDEOGRAPH:'E4D2:58578:馜 +CJK UNIFIED IDEOGRAPH:'E4D3:58579:駃 +CJK UNIFIED IDEOGRAPH:'E4D4:58580:馹 +CJK UNIFIED IDEOGRAPH:'E4D5:58581:馻 +CJK UNIFIED IDEOGRAPH:'E4D6:58582:馺 +CJK UNIFIED IDEOGRAPH:'E4D7:58583:駂 +CJK UNIFIED IDEOGRAPH:'E4D8:58584:馽 +CJK UNIFIED IDEOGRAPH:'E4D9:58585:駇 +CJK UNIFIED IDEOGRAPH:'E4DA:58586:骱 +CJK UNIFIED IDEOGRAPH:'E4DB:58587:髣 +CJK UNIFIED IDEOGRAPH:'E4DC:58588:髧 +CJK UNIFIED IDEOGRAPH:'E4DD:58589:鬾 +CJK UNIFIED IDEOGRAPH:'E4DE:58590:鬿 +CJK UNIFIED IDEOGRAPH:'E4DF:58591:魠 +CJK UNIFIED IDEOGRAPH:'E4E0:58592:魡 +CJK UNIFIED IDEOGRAPH:'E4E1:58593:魟 +CJK UNIFIED IDEOGRAPH:'E4E2:58594:鳱 +CJK UNIFIED IDEOGRAPH:'E4E3:58595:鳲 +CJK UNIFIED IDEOGRAPH:'E4E4:58596:鳵 +CJK UNIFIED IDEOGRAPH:'E4E5:58597:麧 +CJK UNIFIED IDEOGRAPH:'E4E6:58598:僿 +CJK UNIFIED IDEOGRAPH:'E4E7:58599:儃 +CJK UNIFIED IDEOGRAPH:'E4E8:58600:儰 +CJK UNIFIED IDEOGRAPH:'E4E9:58601:僸 +CJK UNIFIED IDEOGRAPH:'E4EA:58602:儆 +CJK UNIFIED IDEOGRAPH:'E4EB:58603:儇 +CJK UNIFIED IDEOGRAPH:'E4EC:58604:僶 +CJK UNIFIED IDEOGRAPH:'E4ED:58605:僾 +CJK UNIFIED IDEOGRAPH:'E4EE:58606:儋 +CJK UNIFIED IDEOGRAPH:'E4EF:58607:儌 +CJK UNIFIED IDEOGRAPH:'E4F0:58608:僽 +CJK UNIFIED IDEOGRAPH:'E4F1:58609:儊 +CJK UNIFIED IDEOGRAPH:'E4F2:58610:劋 +CJK UNIFIED IDEOGRAPH:'E4F3:58611:劌 +CJK UNIFIED IDEOGRAPH:'E4F4:58612:勱 +CJK UNIFIED IDEOGRAPH:'E4F5:58613:勯 +CJK UNIFIED IDEOGRAPH:'E4F6:58614:噈 +CJK UNIFIED IDEOGRAPH:'E4F7:58615:噂 +CJK UNIFIED IDEOGRAPH:'E4F8:58616:噌 +CJK UNIFIED IDEOGRAPH:'E4F9:58617:嘵 +CJK UNIFIED IDEOGRAPH:'E4FA:58618:噁 +CJK UNIFIED IDEOGRAPH:'E4FB:58619:噊 +CJK UNIFIED IDEOGRAPH:'E4FC:58620:噉 +CJK UNIFIED IDEOGRAPH:'E4FD:58621:噆 +CJK UNIFIED IDEOGRAPH:'E4FE:58622:噘 +CJK UNIFIED IDEOGRAPH:'E540:58688:噚 +CJK UNIFIED IDEOGRAPH:'E541:58689:噀 +CJK UNIFIED IDEOGRAPH:'E542:58690:嘳 +CJK UNIFIED IDEOGRAPH:'E543:58691:嘽 +CJK UNIFIED IDEOGRAPH:'E544:58692:嘬 +CJK UNIFIED IDEOGRAPH:'E545:58693:嘾 +CJK UNIFIED IDEOGRAPH:'E546:58694:嘸 +CJK UNIFIED IDEOGRAPH:'E547:58695:嘪 +CJK UNIFIED IDEOGRAPH:'E548:58696:嘺 +CJK UNIFIED IDEOGRAPH:'E549:58697:圚 +CJK UNIFIED IDEOGRAPH:'E54A:58698:墫 +CJK UNIFIED IDEOGRAPH:'E54B:58699:墝 +CJK UNIFIED IDEOGRAPH:'E54C:58700:墱 +CJK UNIFIED IDEOGRAPH:'E54D:58701:墠 +CJK UNIFIED IDEOGRAPH:'E54E:58702:墣 +CJK UNIFIED IDEOGRAPH:'E54F:58703:墯 +CJK UNIFIED IDEOGRAPH:'E550:58704:墬 +CJK UNIFIED IDEOGRAPH:'E551:58705:墥 +CJK UNIFIED IDEOGRAPH:'E552:58706:墡 +CJK UNIFIED IDEOGRAPH:'E553:58707:壿 +CJK UNIFIED IDEOGRAPH:'E554:58708:嫿 +CJK UNIFIED IDEOGRAPH:'E555:58709:嫴 +CJK UNIFIED IDEOGRAPH:'E556:58710:嫽 +CJK UNIFIED IDEOGRAPH:'E557:58711:嫷 +CJK UNIFIED IDEOGRAPH:'E558:58712:嫶 +CJK UNIFIED IDEOGRAPH:'E559:58713:嬃 +CJK UNIFIED IDEOGRAPH:'E55A:58714:嫸 +CJK UNIFIED IDEOGRAPH:'E55B:58715:嬂 +CJK UNIFIED IDEOGRAPH:'E55C:58716:嫹 +CJK UNIFIED IDEOGRAPH:'E55D:58717:嬁 +CJK UNIFIED IDEOGRAPH:'E55E:58718:嬇 +CJK UNIFIED IDEOGRAPH:'E55F:58719:嬅 +CJK UNIFIED IDEOGRAPH:'E560:58720:嬏 +CJK UNIFIED IDEOGRAPH:'E561:58721:屧 +CJK UNIFIED IDEOGRAPH:'E562:58722:嶙 +CJK UNIFIED IDEOGRAPH:'E563:58723:嶗 +CJK UNIFIED IDEOGRAPH:'E564:58724:嶟 +CJK UNIFIED IDEOGRAPH:'E565:58725:嶒 +CJK UNIFIED IDEOGRAPH:'E566:58726:嶢 +CJK UNIFIED IDEOGRAPH:'E567:58727:嶓 +CJK UNIFIED IDEOGRAPH:'E568:58728:嶕 +CJK UNIFIED IDEOGRAPH:'E569:58729:嶠 +CJK UNIFIED IDEOGRAPH:'E56A:58730:嶜 +CJK UNIFIED IDEOGRAPH:'E56B:58731:嶡 +CJK UNIFIED IDEOGRAPH:'E56C:58732:嶚 +CJK UNIFIED IDEOGRAPH:'E56D:58733:嶞 +CJK UNIFIED IDEOGRAPH:'E56E:58734:幩 +CJK UNIFIED IDEOGRAPH:'E56F:58735:幝 +CJK UNIFIED IDEOGRAPH:'E570:58736:幠 +CJK UNIFIED IDEOGRAPH:'E571:58737:幜 +CJK UNIFIED IDEOGRAPH:'E572:58738:緳 +CJK UNIFIED IDEOGRAPH:'E573:58739:廛 +CJK UNIFIED IDEOGRAPH:'E574:58740:廞 +CJK UNIFIED IDEOGRAPH:'E575:58741:廡 +CJK UNIFIED IDEOGRAPH:'E576:58742:彉 +CJK UNIFIED IDEOGRAPH:'E577:58743:徲 +CJK UNIFIED IDEOGRAPH:'E578:58744:憋 +CJK UNIFIED IDEOGRAPH:'E579:58745:憃 +CJK UNIFIED IDEOGRAPH:'E57A:58746:慹 +CJK UNIFIED IDEOGRAPH:'E57B:58747:憱 +CJK UNIFIED IDEOGRAPH:'E57C:58748:憰 +CJK UNIFIED IDEOGRAPH:'E57D:58749:憢 +CJK UNIFIED IDEOGRAPH:'E57E:58750:憉 +CJK UNIFIED IDEOGRAPH:'E5A1:58785:憛 +CJK UNIFIED IDEOGRAPH:'E5A2:58786:憓 +CJK UNIFIED IDEOGRAPH:'E5A3:58787:憯 +CJK UNIFIED IDEOGRAPH:'E5A4:58788:憭 +CJK UNIFIED IDEOGRAPH:'E5A5:58789:憟 +CJK UNIFIED IDEOGRAPH:'E5A6:58790:憒 +CJK UNIFIED IDEOGRAPH:'E5A7:58791:憪 +CJK UNIFIED IDEOGRAPH:'E5A8:58792:憡 +CJK UNIFIED IDEOGRAPH:'E5A9:58793:憍 +CJK UNIFIED IDEOGRAPH:'E5AA:58794:慦 +CJK UNIFIED IDEOGRAPH:'E5AB:58795:憳 +CJK UNIFIED IDEOGRAPH:'E5AC:58796:戭 +CJK UNIFIED IDEOGRAPH:'E5AD:58797:摮 +CJK UNIFIED IDEOGRAPH:'E5AE:58798:摰 +CJK UNIFIED IDEOGRAPH:'E5AF:58799:撖 +CJK UNIFIED IDEOGRAPH:'E5B0:58800:撠 +CJK UNIFIED IDEOGRAPH:'E5B1:58801:撅 +CJK UNIFIED IDEOGRAPH:'E5B2:58802:撗 +CJK UNIFIED IDEOGRAPH:'E5B3:58803:撜 +CJK UNIFIED IDEOGRAPH:'E5B4:58804:撏 +CJK UNIFIED IDEOGRAPH:'E5B5:58805:撋 +CJK UNIFIED IDEOGRAPH:'E5B6:58806:撊 +CJK UNIFIED IDEOGRAPH:'E5B7:58807:撌 +CJK UNIFIED IDEOGRAPH:'E5B8:58808:撣 +CJK UNIFIED IDEOGRAPH:'E5B9:58809:撟 +CJK UNIFIED IDEOGRAPH:'E5BA:58810:摨 +CJK UNIFIED IDEOGRAPH:'E5BB:58811:撱 +CJK UNIFIED IDEOGRAPH:'E5BC:58812:撘 +CJK UNIFIED IDEOGRAPH:'E5BD:58813:敶 +CJK UNIFIED IDEOGRAPH:'E5BE:58814:敺 +CJK UNIFIED IDEOGRAPH:'E5BF:58815:敹 +CJK UNIFIED IDEOGRAPH:'E5C0:58816:敻 +CJK UNIFIED IDEOGRAPH:'E5C1:58817:斲 +CJK UNIFIED IDEOGRAPH:'E5C2:58818:斳 +CJK UNIFIED IDEOGRAPH:'E5C3:58819:暵 +CJK UNIFIED IDEOGRAPH:'E5C4:58820:暰 +CJK UNIFIED IDEOGRAPH:'E5C5:58821:暩 +CJK UNIFIED IDEOGRAPH:'E5C6:58822:暲 +CJK UNIFIED IDEOGRAPH:'E5C7:58823:暷 +CJK UNIFIED IDEOGRAPH:'E5C8:58824:暪 +CJK UNIFIED IDEOGRAPH:'E5C9:58825:暯 +CJK UNIFIED IDEOGRAPH:'E5CA:58826:樀 +CJK UNIFIED IDEOGRAPH:'E5CB:58827:樆 +CJK UNIFIED IDEOGRAPH:'E5CC:58828:樗 +CJK UNIFIED IDEOGRAPH:'E5CD:58829:槥 +CJK UNIFIED IDEOGRAPH:'E5CE:58830:槸 +CJK UNIFIED IDEOGRAPH:'E5CF:58831:樕 +CJK UNIFIED IDEOGRAPH:'E5D0:58832:槱 +CJK UNIFIED IDEOGRAPH:'E5D1:58833:槤 +CJK UNIFIED IDEOGRAPH:'E5D2:58834:樠 +CJK UNIFIED IDEOGRAPH:'E5D3:58835:槿 +CJK UNIFIED IDEOGRAPH:'E5D4:58836:槬 +CJK UNIFIED IDEOGRAPH:'E5D5:58837:槢 +CJK UNIFIED IDEOGRAPH:'E5D6:58838:樛 +CJK UNIFIED IDEOGRAPH:'E5D7:58839:樝 +CJK UNIFIED IDEOGRAPH:'E5D8:58840:槾 +CJK UNIFIED IDEOGRAPH:'E5D9:58841:樧 +CJK UNIFIED IDEOGRAPH:'E5DA:58842:槲 +CJK UNIFIED IDEOGRAPH:'E5DB:58843:槮 +CJK UNIFIED IDEOGRAPH:'E5DC:58844:樔 +CJK UNIFIED IDEOGRAPH:'E5DD:58845:槷 +CJK UNIFIED IDEOGRAPH:'E5DE:58846:槧 +CJK UNIFIED IDEOGRAPH:'E5DF:58847:橀 +CJK UNIFIED IDEOGRAPH:'E5E0:58848:樈 +CJK UNIFIED IDEOGRAPH:'E5E1:58849:槦 +CJK UNIFIED IDEOGRAPH:'E5E2:58850:槻 +CJK UNIFIED IDEOGRAPH:'E5E3:58851:樍 +CJK UNIFIED IDEOGRAPH:'E5E4:58852:槼 +CJK UNIFIED IDEOGRAPH:'E5E5:58853:槫 +CJK UNIFIED IDEOGRAPH:'E5E6:58854:樉 +CJK UNIFIED IDEOGRAPH:'E5E7:58855:樄 +CJK UNIFIED IDEOGRAPH:'E5E8:58856:樘 +CJK UNIFIED IDEOGRAPH:'E5E9:58857:樥 +CJK UNIFIED IDEOGRAPH:'E5EA:58858:樏 +CJK UNIFIED IDEOGRAPH:'E5EB:58859:槶 +CJK UNIFIED IDEOGRAPH:'E5EC:58860:樦 +CJK UNIFIED IDEOGRAPH:'E5ED:58861:樇 +CJK UNIFIED IDEOGRAPH:'E5EE:58862:槴 +CJK UNIFIED IDEOGRAPH:'E5EF:58863:樖 +CJK UNIFIED IDEOGRAPH:'E5F0:58864:歑 +CJK UNIFIED IDEOGRAPH:'E5F1:58865:殥 +CJK UNIFIED IDEOGRAPH:'E5F2:58866:殣 +CJK UNIFIED IDEOGRAPH:'E5F3:58867:殢 +CJK UNIFIED IDEOGRAPH:'E5F4:58868:殦 +CJK UNIFIED IDEOGRAPH:'E5F5:58869:氁 +CJK UNIFIED IDEOGRAPH:'E5F6:58870:氀 +CJK UNIFIED IDEOGRAPH:'E5F7:58871:毿 +CJK UNIFIED IDEOGRAPH:'E5F8:58872:氂 +CJK UNIFIED IDEOGRAPH:'E5F9:58873:潁 +CJK UNIFIED IDEOGRAPH:'E5FA:58874:漦 +CJK UNIFIED IDEOGRAPH:'E5FB:58875:潾 +CJK UNIFIED IDEOGRAPH:'E5FC:58876:澇 +CJK UNIFIED IDEOGRAPH:'E5FD:58877:濆 +CJK UNIFIED IDEOGRAPH:'E5FE:58878:澒 +CJK UNIFIED IDEOGRAPH:'E640:58944:澍 +CJK UNIFIED IDEOGRAPH:'E641:58945:澉 +CJK UNIFIED IDEOGRAPH:'E642:58946:澌 +CJK UNIFIED IDEOGRAPH:'E643:58947:潢 +CJK UNIFIED IDEOGRAPH:'E644:58948:潏 +CJK UNIFIED IDEOGRAPH:'E645:58949:澅 +CJK UNIFIED IDEOGRAPH:'E646:58950:潚 +CJK UNIFIED IDEOGRAPH:'E647:58951:澖 +CJK UNIFIED IDEOGRAPH:'E648:58952:潶 +CJK UNIFIED IDEOGRAPH:'E649:58953:潬 +CJK UNIFIED IDEOGRAPH:'E64A:58954:澂 +CJK UNIFIED IDEOGRAPH:'E64B:58955:潕 +CJK UNIFIED IDEOGRAPH:'E64C:58956:潲 +CJK UNIFIED IDEOGRAPH:'E64D:58957:潒 +CJK UNIFIED IDEOGRAPH:'E64E:58958:潐 +CJK UNIFIED IDEOGRAPH:'E64F:58959:潗 +CJK UNIFIED IDEOGRAPH:'E650:58960:澔 +CJK UNIFIED IDEOGRAPH:'E651:58961:澓 +CJK UNIFIED IDEOGRAPH:'E652:58962:潝 +CJK UNIFIED IDEOGRAPH:'E653:58963:漀 +CJK UNIFIED IDEOGRAPH:'E654:58964:潡 +CJK UNIFIED IDEOGRAPH:'E655:58965:潫 +CJK UNIFIED IDEOGRAPH:'E656:58966:潽 +CJK UNIFIED IDEOGRAPH:'E657:58967:潧 +CJK UNIFIED IDEOGRAPH:'E658:58968:澐 +CJK UNIFIED IDEOGRAPH:'E659:58969:潓 +CJK UNIFIED IDEOGRAPH:'E65A:58970:澋 +CJK UNIFIED IDEOGRAPH:'E65B:58971:潩 +CJK UNIFIED IDEOGRAPH:'E65C:58972:潿 +CJK UNIFIED IDEOGRAPH:'E65D:58973:澕 +CJK UNIFIED IDEOGRAPH:'E65E:58974:潣 +CJK UNIFIED IDEOGRAPH:'E65F:58975:潷 +CJK UNIFIED IDEOGRAPH:'E660:58976:潪 +CJK UNIFIED IDEOGRAPH:'E661:58977:潻 +CJK UNIFIED IDEOGRAPH:'E662:58978:熲 +CJK UNIFIED IDEOGRAPH:'E663:58979:熯 +CJK UNIFIED IDEOGRAPH:'E664:58980:熛 +CJK UNIFIED IDEOGRAPH:'E665:58981:熰 +CJK UNIFIED IDEOGRAPH:'E666:58982:熠 +CJK UNIFIED IDEOGRAPH:'E667:58983:熚 +CJK UNIFIED IDEOGRAPH:'E668:58984:熩 +CJK UNIFIED IDEOGRAPH:'E669:58985:熵 +CJK UNIFIED IDEOGRAPH:'E66A:58986:熝 +CJK UNIFIED IDEOGRAPH:'E66B:58987:熥 +CJK UNIFIED IDEOGRAPH:'E66C:58988:熞 +CJK UNIFIED IDEOGRAPH:'E66D:58989:熤 +CJK UNIFIED IDEOGRAPH:'E66E:58990:熡 +CJK UNIFIED IDEOGRAPH:'E66F:58991:熪 +CJK UNIFIED IDEOGRAPH:'E670:58992:熜 +CJK UNIFIED IDEOGRAPH:'E671:58993:熧 +CJK UNIFIED IDEOGRAPH:'E672:58994:熳 +CJK UNIFIED IDEOGRAPH:'E673:58995:犘 +CJK UNIFIED IDEOGRAPH:'E674:58996:犚 +CJK UNIFIED IDEOGRAPH:'E675:58997:獘 +CJK UNIFIED IDEOGRAPH:'E676:58998:獒 +CJK UNIFIED IDEOGRAPH:'E677:58999:獞 +CJK UNIFIED IDEOGRAPH:'E678:59000:獟 +CJK UNIFIED IDEOGRAPH:'E679:59001:獠 +CJK UNIFIED IDEOGRAPH:'E67A:59002:獝 +CJK UNIFIED IDEOGRAPH:'E67B:59003:獛 +CJK UNIFIED IDEOGRAPH:'E67C:59004:獡 +CJK UNIFIED IDEOGRAPH:'E67D:59005:獚 +CJK UNIFIED IDEOGRAPH:'E67E:59006:獙 +CJK UNIFIED IDEOGRAPH:'E6A1:59041:獢 +CJK UNIFIED IDEOGRAPH:'E6A2:59042:璇 +CJK UNIFIED IDEOGRAPH:'E6A3:59043:璉 +CJK UNIFIED IDEOGRAPH:'E6A4:59044:璊 +CJK UNIFIED IDEOGRAPH:'E6A5:59045:璆 +CJK UNIFIED IDEOGRAPH:'E6A6:59046:璁 +CJK UNIFIED IDEOGRAPH:'E6A7:59047:瑽 +CJK UNIFIED IDEOGRAPH:'E6A8:59048:璅 +CJK UNIFIED IDEOGRAPH:'E6A9:59049:璈 +CJK UNIFIED IDEOGRAPH:'E6AA:59050:瑼 +CJK UNIFIED IDEOGRAPH:'E6AB:59051:瑹 +CJK UNIFIED IDEOGRAPH:'E6AC:59052:甈 +CJK UNIFIED IDEOGRAPH:'E6AD:59053:甇 +CJK UNIFIED IDEOGRAPH:'E6AE:59054:畾 +CJK UNIFIED IDEOGRAPH:'E6AF:59055:瘥 +CJK UNIFIED IDEOGRAPH:'E6B0:59056:瘞 +CJK UNIFIED IDEOGRAPH:'E6B1:59057:瘙 +CJK UNIFIED IDEOGRAPH:'E6B2:59058:瘝 +CJK UNIFIED IDEOGRAPH:'E6B3:59059:瘜 +CJK UNIFIED IDEOGRAPH:'E6B4:59060:瘣 +CJK UNIFIED IDEOGRAPH:'E6B5:59061:瘚 +CJK UNIFIED IDEOGRAPH:'E6B6:59062:瘨 +CJK UNIFIED IDEOGRAPH:'E6B7:59063:瘛 +CJK UNIFIED IDEOGRAPH:'E6B8:59064:皜 +CJK UNIFIED IDEOGRAPH:'E6B9:59065:皝 +CJK UNIFIED IDEOGRAPH:'E6BA:59066:皞 +CJK UNIFIED IDEOGRAPH:'E6BB:59067:皛 +CJK UNIFIED IDEOGRAPH:'E6BC:59068:瞍 +CJK UNIFIED IDEOGRAPH:'E6BD:59069:瞏 +CJK UNIFIED IDEOGRAPH:'E6BE:59070:瞉 +CJK UNIFIED IDEOGRAPH:'E6BF:59071:瞈 +CJK UNIFIED IDEOGRAPH:'E6C0:59072:磍 +CJK UNIFIED IDEOGRAPH:'E6C1:59073:碻 +CJK UNIFIED IDEOGRAPH:'E6C2:59074:磏 +CJK UNIFIED IDEOGRAPH:'E6C3:59075:磌 +CJK UNIFIED IDEOGRAPH:'E6C4:59076:磑 +CJK UNIFIED IDEOGRAPH:'E6C5:59077:磎 +CJK UNIFIED IDEOGRAPH:'E6C6:59078:磔 +CJK UNIFIED IDEOGRAPH:'E6C7:59079:磈 +CJK UNIFIED IDEOGRAPH:'E6C8:59080:磃 +CJK UNIFIED IDEOGRAPH:'E6C9:59081:磄 +CJK UNIFIED IDEOGRAPH:'E6CA:59082:磉 +CJK UNIFIED IDEOGRAPH:'E6CB:59083:禚 +CJK UNIFIED IDEOGRAPH:'E6CC:59084:禡 +CJK UNIFIED IDEOGRAPH:'E6CD:59085:禠 +CJK UNIFIED IDEOGRAPH:'E6CE:59086:禜 +CJK UNIFIED IDEOGRAPH:'E6CF:59087:禢 +CJK UNIFIED IDEOGRAPH:'E6D0:59088:禛 +CJK UNIFIED IDEOGRAPH:'E6D1:59089:歶 +CJK UNIFIED IDEOGRAPH:'E6D2:59090:稹 +CJK UNIFIED IDEOGRAPH:'E6D3:59091:窲 +CJK UNIFIED IDEOGRAPH:'E6D4:59092:窴 +CJK UNIFIED IDEOGRAPH:'E6D5:59093:窳 +CJK UNIFIED IDEOGRAPH:'E6D6:59094:箷 +CJK UNIFIED IDEOGRAPH:'E6D7:59095:篋 +CJK UNIFIED IDEOGRAPH:'E6D8:59096:箾 +CJK UNIFIED IDEOGRAPH:'E6D9:59097:箬 +CJK UNIFIED IDEOGRAPH:'E6DA:59098:篎 +CJK UNIFIED IDEOGRAPH:'E6DB:59099:箯 +CJK UNIFIED IDEOGRAPH:'E6DC:59100:箹 +CJK UNIFIED IDEOGRAPH:'E6DD:59101:篊 +CJK UNIFIED IDEOGRAPH:'E6DE:59102:箵 +CJK UNIFIED IDEOGRAPH:'E6DF:59103:糅 +CJK UNIFIED IDEOGRAPH:'E6E0:59104:糈 +CJK UNIFIED IDEOGRAPH:'E6E1:59105:糌 +CJK UNIFIED IDEOGRAPH:'E6E2:59106:糋 +CJK UNIFIED IDEOGRAPH:'E6E3:59107:緷 +CJK UNIFIED IDEOGRAPH:'E6E4:59108:緛 +CJK UNIFIED IDEOGRAPH:'E6E5:59109:緪 +CJK UNIFIED IDEOGRAPH:'E6E6:59110:緧 +CJK UNIFIED IDEOGRAPH:'E6E7:59111:緗 +CJK UNIFIED IDEOGRAPH:'E6E8:59112:緡 +CJK UNIFIED IDEOGRAPH:'E6E9:59113:縃 +CJK UNIFIED IDEOGRAPH:'E6EA:59114:緺 +CJK UNIFIED IDEOGRAPH:'E6EB:59115:緦 +CJK UNIFIED IDEOGRAPH:'E6EC:59116:緶 +CJK UNIFIED IDEOGRAPH:'E6ED:59117:緱 +CJK UNIFIED IDEOGRAPH:'E6EE:59118:緰 +CJK UNIFIED IDEOGRAPH:'E6EF:59119:緮 +CJK UNIFIED IDEOGRAPH:'E6F0:59120:緟 +CJK UNIFIED IDEOGRAPH:'E6F1:59121:罶 +CJK UNIFIED IDEOGRAPH:'E6F2:59122:羬 +CJK UNIFIED IDEOGRAPH:'E6F3:59123:羰 +CJK UNIFIED IDEOGRAPH:'E6F4:59124:羭 +CJK UNIFIED IDEOGRAPH:'E6F5:59125:翭 +CJK UNIFIED IDEOGRAPH:'E6F6:59126:翫 +CJK UNIFIED IDEOGRAPH:'E6F7:59127:翪 +CJK UNIFIED IDEOGRAPH:'E6F8:59128:翬 +CJK UNIFIED IDEOGRAPH:'E6F9:59129:翦 +CJK UNIFIED IDEOGRAPH:'E6FA:59130:翨 +CJK UNIFIED IDEOGRAPH:'E6FB:59131:聤 +CJK UNIFIED IDEOGRAPH:'E6FC:59132:聧 +CJK UNIFIED IDEOGRAPH:'E6FD:59133:膣 +CJK UNIFIED IDEOGRAPH:'E6FE:59134:膟 +CJK UNIFIED IDEOGRAPH:'E740:59200:膞 +CJK UNIFIED IDEOGRAPH:'E741:59201:膕 +CJK UNIFIED IDEOGRAPH:'E742:59202:膢 +CJK UNIFIED IDEOGRAPH:'E743:59203:膙 +CJK UNIFIED IDEOGRAPH:'E744:59204:膗 +CJK UNIFIED IDEOGRAPH:'E745:59205:舖 +CJK UNIFIED IDEOGRAPH:'E746:59206:艏 +CJK UNIFIED IDEOGRAPH:'E747:59207:艓 +CJK UNIFIED IDEOGRAPH:'E748:59208:艒 +CJK UNIFIED IDEOGRAPH:'E749:59209:艐 +CJK UNIFIED IDEOGRAPH:'E74A:59210:艎 +CJK UNIFIED IDEOGRAPH:'E74B:59211:艑 +CJK UNIFIED IDEOGRAPH:'E74C:59212:蔤 +CJK UNIFIED IDEOGRAPH:'E74D:59213:蔻 +CJK UNIFIED IDEOGRAPH:'E74E:59214:蔏 +CJK UNIFIED IDEOGRAPH:'E74F:59215:蔀 +CJK UNIFIED IDEOGRAPH:'E750:59216:蔩 +CJK UNIFIED IDEOGRAPH:'E751:59217:蔎 +CJK UNIFIED IDEOGRAPH:'E752:59218:蔉 +CJK UNIFIED IDEOGRAPH:'E753:59219:蔍 +CJK UNIFIED IDEOGRAPH:'E754:59220:蔟 +CJK UNIFIED IDEOGRAPH:'E755:59221:蔊 +CJK UNIFIED IDEOGRAPH:'E756:59222:蔧 +CJK UNIFIED IDEOGRAPH:'E757:59223:蔜 +CJK UNIFIED IDEOGRAPH:'E758:59224:蓻 +CJK UNIFIED IDEOGRAPH:'E759:59225:蔫 +CJK UNIFIED IDEOGRAPH:'E75A:59226:蓺 +CJK UNIFIED IDEOGRAPH:'E75B:59227:蔈 +CJK UNIFIED IDEOGRAPH:'E75C:59228:蔌 +CJK UNIFIED IDEOGRAPH:'E75D:59229:蓴 +CJK UNIFIED IDEOGRAPH:'E75E:59230:蔪 +CJK UNIFIED IDEOGRAPH:'E75F:59231:蓲 +CJK UNIFIED IDEOGRAPH:'E760:59232:蔕 +CJK UNIFIED IDEOGRAPH:'E761:59233:蓷 +CJK UNIFIED IDEOGRAPH:'E762:59234:蓫 +CJK UNIFIED IDEOGRAPH:'E763:59235:蓳 +CJK UNIFIED IDEOGRAPH:'E764:59236:蓼 +CJK UNIFIED IDEOGRAPH:'E765:59237:蔒 +CJK UNIFIED IDEOGRAPH:'E766:59238:蓪 +CJK UNIFIED IDEOGRAPH:'E767:59239:蓩 +CJK UNIFIED IDEOGRAPH:'E768:59240:蔖 +CJK UNIFIED IDEOGRAPH:'E769:59241:蓾 +CJK UNIFIED IDEOGRAPH:'E76A:59242:蔨 +CJK UNIFIED IDEOGRAPH:'E76B:59243:蔝 +CJK UNIFIED IDEOGRAPH:'E76C:59244:蔮 +CJK UNIFIED IDEOGRAPH:'E76D:59245:蔂 +CJK UNIFIED IDEOGRAPH:'E76E:59246:蓽 +CJK UNIFIED IDEOGRAPH:'E76F:59247:蔞 +CJK UNIFIED IDEOGRAPH:'E770:59248:蓶 +CJK UNIFIED IDEOGRAPH:'E771:59249:蔱 +CJK UNIFIED IDEOGRAPH:'E772:59250:蔦 +CJK UNIFIED IDEOGRAPH:'E773:59251:蓧 +CJK UNIFIED IDEOGRAPH:'E774:59252:蓨 +CJK UNIFIED IDEOGRAPH:'E775:59253:蓰 +CJK UNIFIED IDEOGRAPH:'E776:59254:蓯 +CJK UNIFIED IDEOGRAPH:'E777:59255:蓹 +CJK UNIFIED IDEOGRAPH:'E778:59256:蔘 +CJK UNIFIED IDEOGRAPH:'E779:59257:蔠 +CJK UNIFIED IDEOGRAPH:'E77A:59258:蔰 +CJK UNIFIED IDEOGRAPH:'E77B:59259:蔋 +CJK UNIFIED IDEOGRAPH:'E77C:59260:蔙 +CJK UNIFIED IDEOGRAPH:'E77D:59261:蔯 +CJK UNIFIED IDEOGRAPH:'E77E:59262:虢 +CJK UNIFIED IDEOGRAPH:'E7A1:59297:蝖 +CJK UNIFIED IDEOGRAPH:'E7A2:59298:蝣 +CJK UNIFIED IDEOGRAPH:'E7A3:59299:蝤 +CJK UNIFIED IDEOGRAPH:'E7A4:59300:蝷 +CJK UNIFIED IDEOGRAPH:'E7A5:59301:蟡 +CJK UNIFIED IDEOGRAPH:'E7A6:59302:蝳 +CJK UNIFIED IDEOGRAPH:'E7A7:59303:蝘 +CJK UNIFIED IDEOGRAPH:'E7A8:59304:蝔 +CJK UNIFIED IDEOGRAPH:'E7A9:59305:蝛 +CJK UNIFIED IDEOGRAPH:'E7AA:59306:蝒 +CJK UNIFIED IDEOGRAPH:'E7AB:59307:蝡 +CJK UNIFIED IDEOGRAPH:'E7AC:59308:蝚 +CJK UNIFIED IDEOGRAPH:'E7AD:59309:蝑 +CJK UNIFIED IDEOGRAPH:'E7AE:59310:蝞 +CJK UNIFIED IDEOGRAPH:'E7AF:59311:蝭 +CJK UNIFIED IDEOGRAPH:'E7B0:59312:蝪 +CJK UNIFIED IDEOGRAPH:'E7B1:59313:蝐 +CJK UNIFIED IDEOGRAPH:'E7B2:59314:蝎 +CJK UNIFIED IDEOGRAPH:'E7B3:59315:蝟 +CJK UNIFIED IDEOGRAPH:'E7B4:59316:蝝 +CJK UNIFIED IDEOGRAPH:'E7B5:59317:蝯 +CJK UNIFIED IDEOGRAPH:'E7B6:59318:蝬 +CJK UNIFIED IDEOGRAPH:'E7B7:59319:蝺 +CJK UNIFIED IDEOGRAPH:'E7B8:59320:蝮 +CJK UNIFIED IDEOGRAPH:'E7B9:59321:蝜 +CJK UNIFIED IDEOGRAPH:'E7BA:59322:蝥 +CJK UNIFIED IDEOGRAPH:'E7BB:59323:蝏 +CJK UNIFIED IDEOGRAPH:'E7BC:59324:蝻 +CJK UNIFIED IDEOGRAPH:'E7BD:59325:蝵 +CJK UNIFIED IDEOGRAPH:'E7BE:59326:蝢 +CJK UNIFIED IDEOGRAPH:'E7BF:59327:蝧 +CJK UNIFIED IDEOGRAPH:'E7C0:59328:蝩 +CJK UNIFIED IDEOGRAPH:'E7C1:59329:衚 +CJK UNIFIED IDEOGRAPH:'E7C2:59330:褅 +CJK UNIFIED IDEOGRAPH:'E7C3:59331:褌 +CJK UNIFIED IDEOGRAPH:'E7C4:59332:褔 +CJK UNIFIED IDEOGRAPH:'E7C5:59333:褋 +CJK UNIFIED IDEOGRAPH:'E7C6:59334:褗 +CJK UNIFIED IDEOGRAPH:'E7C7:59335:褘 +CJK UNIFIED IDEOGRAPH:'E7C8:59336:褙 +CJK UNIFIED IDEOGRAPH:'E7C9:59337:褆 +CJK UNIFIED IDEOGRAPH:'E7CA:59338:褖 +CJK UNIFIED IDEOGRAPH:'E7CB:59339:褑 +CJK UNIFIED IDEOGRAPH:'E7CC:59340:褎 +CJK UNIFIED IDEOGRAPH:'E7CD:59341:褉 +CJK UNIFIED IDEOGRAPH:'E7CE:59342:覢 +CJK UNIFIED IDEOGRAPH:'E7CF:59343:覤 +CJK UNIFIED IDEOGRAPH:'E7D0:59344:覣 +CJK UNIFIED IDEOGRAPH:'E7D1:59345:觭 +CJK UNIFIED IDEOGRAPH:'E7D2:59346:觰 +CJK UNIFIED IDEOGRAPH:'E7D3:59347:觬 +CJK UNIFIED IDEOGRAPH:'E7D4:59348:諏 +CJK UNIFIED IDEOGRAPH:'E7D5:59349:諆 +CJK UNIFIED IDEOGRAPH:'E7D6:59350:誸 +CJK UNIFIED IDEOGRAPH:'E7D7:59351:諓 +CJK UNIFIED IDEOGRAPH:'E7D8:59352:諑 +CJK UNIFIED IDEOGRAPH:'E7D9:59353:諔 +CJK UNIFIED IDEOGRAPH:'E7DA:59354:諕 +CJK UNIFIED IDEOGRAPH:'E7DB:59355:誻 +CJK UNIFIED IDEOGRAPH:'E7DC:59356:諗 +CJK UNIFIED IDEOGRAPH:'E7DD:59357:誾 +CJK UNIFIED IDEOGRAPH:'E7DE:59358:諀 +CJK UNIFIED IDEOGRAPH:'E7DF:59359:諅 +CJK UNIFIED IDEOGRAPH:'E7E0:59360:諘 +CJK UNIFIED IDEOGRAPH:'E7E1:59361:諃 +CJK UNIFIED IDEOGRAPH:'E7E2:59362:誺 +CJK UNIFIED IDEOGRAPH:'E7E3:59363:誽 +CJK UNIFIED IDEOGRAPH:'E7E4:59364:諙 +CJK UNIFIED IDEOGRAPH:'E7E5:59365:谾 +CJK UNIFIED IDEOGRAPH:'E7E6:59366:豍 +CJK UNIFIED IDEOGRAPH:'E7E7:59367:貏 +CJK UNIFIED IDEOGRAPH:'E7E8:59368:賥 +CJK UNIFIED IDEOGRAPH:'E7E9:59369:賟 +CJK UNIFIED IDEOGRAPH:'E7EA:59370:賙 +CJK UNIFIED IDEOGRAPH:'E7EB:59371:賨 +CJK UNIFIED IDEOGRAPH:'E7EC:59372:賚 +CJK UNIFIED IDEOGRAPH:'E7ED:59373:賝 +CJK UNIFIED IDEOGRAPH:'E7EE:59374:賧 +CJK UNIFIED IDEOGRAPH:'E7EF:59375:趠 +CJK UNIFIED IDEOGRAPH:'E7F0:59376:趜 +CJK UNIFIED IDEOGRAPH:'E7F1:59377:趡 +CJK UNIFIED IDEOGRAPH:'E7F2:59378:趛 +CJK UNIFIED IDEOGRAPH:'E7F3:59379:踠 +CJK UNIFIED IDEOGRAPH:'E7F4:59380:踣 +CJK UNIFIED IDEOGRAPH:'E7F5:59381:踥 +CJK UNIFIED IDEOGRAPH:'E7F6:59382:踤 +CJK UNIFIED IDEOGRAPH:'E7F7:59383:踮 +CJK UNIFIED IDEOGRAPH:'E7F8:59384:踕 +CJK UNIFIED IDEOGRAPH:'E7F9:59385:踛 +CJK UNIFIED IDEOGRAPH:'E7FA:59386:踖 +CJK UNIFIED IDEOGRAPH:'E7FB:59387:踑 +CJK UNIFIED IDEOGRAPH:'E7FC:59388:踙 +CJK UNIFIED IDEOGRAPH:'E7FD:59389:踦 +CJK UNIFIED IDEOGRAPH:'E7FE:59390:踧 +CJK UNIFIED IDEOGRAPH:'E840:59456:踔 +CJK UNIFIED IDEOGRAPH:'E841:59457:踒 +CJK UNIFIED IDEOGRAPH:'E842:59458:踘 +CJK UNIFIED IDEOGRAPH:'E843:59459:踓 +CJK UNIFIED IDEOGRAPH:'E844:59460:踜 +CJK UNIFIED IDEOGRAPH:'E845:59461:踗 +CJK UNIFIED IDEOGRAPH:'E846:59462:踚 +CJK UNIFIED IDEOGRAPH:'E847:59463:輬 +CJK UNIFIED IDEOGRAPH:'E848:59464:輤 +CJK UNIFIED IDEOGRAPH:'E849:59465:輘 +CJK UNIFIED IDEOGRAPH:'E84A:59466:輚 +CJK UNIFIED IDEOGRAPH:'E84B:59467:輠 +CJK UNIFIED IDEOGRAPH:'E84C:59468:輣 +CJK UNIFIED IDEOGRAPH:'E84D:59469:輖 +CJK UNIFIED IDEOGRAPH:'E84E:59470:輗 +CJK UNIFIED IDEOGRAPH:'E84F:59471:遳 +CJK UNIFIED IDEOGRAPH:'E850:59472:遰 +CJK UNIFIED IDEOGRAPH:'E851:59473:遯 +CJK UNIFIED IDEOGRAPH:'E852:59474:遧 +CJK UNIFIED IDEOGRAPH:'E853:59475:遫 +CJK UNIFIED IDEOGRAPH:'E854:59476:鄯 +CJK UNIFIED IDEOGRAPH:'E855:59477:鄫 +CJK UNIFIED IDEOGRAPH:'E856:59478:鄩 +CJK UNIFIED IDEOGRAPH:'E857:59479:鄪 +CJK UNIFIED IDEOGRAPH:'E858:59480:鄲 +CJK UNIFIED IDEOGRAPH:'E859:59481:鄦 +CJK UNIFIED IDEOGRAPH:'E85A:59482:鄮 +CJK UNIFIED IDEOGRAPH:'E85B:59483:醅 +CJK UNIFIED IDEOGRAPH:'E85C:59484:醆 +CJK UNIFIED IDEOGRAPH:'E85D:59485:醊 +CJK UNIFIED IDEOGRAPH:'E85E:59486:醁 +CJK UNIFIED IDEOGRAPH:'E85F:59487:醂 +CJK UNIFIED IDEOGRAPH:'E860:59488:醄 +CJK UNIFIED IDEOGRAPH:'E861:59489:醀 +CJK UNIFIED IDEOGRAPH:'E862:59490:鋐 +CJK UNIFIED IDEOGRAPH:'E863:59491:鋃 +CJK UNIFIED IDEOGRAPH:'E864:59492:鋄 +CJK UNIFIED IDEOGRAPH:'E865:59493:鋀 +CJK UNIFIED IDEOGRAPH:'E866:59494:鋙 +CJK UNIFIED IDEOGRAPH:'E867:59495:銶 +CJK UNIFIED IDEOGRAPH:'E868:59496:鋏 +CJK UNIFIED IDEOGRAPH:'E869:59497:鋱 +CJK UNIFIED IDEOGRAPH:'E86A:59498:鋟 +CJK UNIFIED IDEOGRAPH:'E86B:59499:鋘 +CJK UNIFIED IDEOGRAPH:'E86C:59500:鋩 +CJK UNIFIED IDEOGRAPH:'E86D:59501:鋗 +CJK UNIFIED IDEOGRAPH:'E86E:59502:鋝 +CJK UNIFIED IDEOGRAPH:'E86F:59503:鋌 +CJK UNIFIED IDEOGRAPH:'E870:59504:鋯 +CJK UNIFIED IDEOGRAPH:'E871:59505:鋂 +CJK UNIFIED IDEOGRAPH:'E872:59506:鋨 +CJK UNIFIED IDEOGRAPH:'E873:59507:鋊 +CJK UNIFIED IDEOGRAPH:'E874:59508:鋈 +CJK UNIFIED IDEOGRAPH:'E875:59509:鋎 +CJK UNIFIED IDEOGRAPH:'E876:59510:鋦 +CJK UNIFIED IDEOGRAPH:'E877:59511:鋍 +CJK UNIFIED IDEOGRAPH:'E878:59512:鋕 +CJK UNIFIED IDEOGRAPH:'E879:59513:鋉 +CJK UNIFIED IDEOGRAPH:'E87A:59514:鋠 +CJK UNIFIED IDEOGRAPH:'E87B:59515:鋞 +CJK UNIFIED IDEOGRAPH:'E87C:59516:鋧 +CJK UNIFIED IDEOGRAPH:'E87D:59517:鋑 +CJK UNIFIED IDEOGRAPH:'E87E:59518:鋓 +CJK UNIFIED IDEOGRAPH:'E8A1:59553:銵 +CJK UNIFIED IDEOGRAPH:'E8A2:59554:鋡 +CJK UNIFIED IDEOGRAPH:'E8A3:59555:鋆 +CJK UNIFIED IDEOGRAPH:'E8A4:59556:銴 +CJK UNIFIED IDEOGRAPH:'E8A5:59557:镼 +CJK UNIFIED IDEOGRAPH:'E8A6:59558:閬 +CJK UNIFIED IDEOGRAPH:'E8A7:59559:閫 +CJK UNIFIED IDEOGRAPH:'E8A8:59560:閮 +CJK UNIFIED IDEOGRAPH:'E8A9:59561:閰 +CJK UNIFIED IDEOGRAPH:'E8AA:59562:隤 +CJK UNIFIED IDEOGRAPH:'E8AB:59563:隢 +CJK UNIFIED IDEOGRAPH:'E8AC:59564:雓 +CJK UNIFIED IDEOGRAPH:'E8AD:59565:霅 +CJK UNIFIED IDEOGRAPH:'E8AE:59566:霈 +CJK UNIFIED IDEOGRAPH:'E8AF:59567:霂 +CJK UNIFIED IDEOGRAPH:'E8B0:59568:靚 +CJK UNIFIED IDEOGRAPH:'E8B1:59569:鞊 +CJK UNIFIED IDEOGRAPH:'E8B2:59570:鞎 +CJK UNIFIED IDEOGRAPH:'E8B3:59571:鞈 +CJK UNIFIED IDEOGRAPH:'E8B4:59572:韐 +CJK UNIFIED IDEOGRAPH:'E8B5:59573:韏 +CJK UNIFIED IDEOGRAPH:'E8B6:59574:頞 +CJK UNIFIED IDEOGRAPH:'E8B7:59575:頝 +CJK UNIFIED IDEOGRAPH:'E8B8:59576:頦 +CJK UNIFIED IDEOGRAPH:'E8B9:59577:頩 +CJK UNIFIED IDEOGRAPH:'E8BA:59578:頨 +CJK UNIFIED IDEOGRAPH:'E8BB:59579:頠 +CJK UNIFIED IDEOGRAPH:'E8BC:59580:頛 +CJK UNIFIED IDEOGRAPH:'E8BD:59581:頧 +CJK UNIFIED IDEOGRAPH:'E8BE:59582:颲 +CJK UNIFIED IDEOGRAPH:'E8BF:59583:餈 +CJK UNIFIED IDEOGRAPH:'E8C0:59584:飺 +CJK UNIFIED IDEOGRAPH:'E8C1:59585:餑 +CJK UNIFIED IDEOGRAPH:'E8C2:59586:餔 +CJK UNIFIED IDEOGRAPH:'E8C3:59587:餖 +CJK UNIFIED IDEOGRAPH:'E8C4:59588:餗 +CJK UNIFIED IDEOGRAPH:'E8C5:59589:餕 +CJK UNIFIED IDEOGRAPH:'E8C6:59590:駜 +CJK UNIFIED IDEOGRAPH:'E8C7:59591:駍 +CJK UNIFIED IDEOGRAPH:'E8C8:59592:駏 +CJK UNIFIED IDEOGRAPH:'E8C9:59593:駓 +CJK UNIFIED IDEOGRAPH:'E8CA:59594:駔 +CJK UNIFIED IDEOGRAPH:'E8CB:59595:駎 +CJK UNIFIED IDEOGRAPH:'E8CC:59596:駉 +CJK UNIFIED IDEOGRAPH:'E8CD:59597:駖 +CJK UNIFIED IDEOGRAPH:'E8CE:59598:駘 +CJK UNIFIED IDEOGRAPH:'E8CF:59599:駋 +CJK UNIFIED IDEOGRAPH:'E8D0:59600:駗 +CJK UNIFIED IDEOGRAPH:'E8D1:59601:駌 +CJK UNIFIED IDEOGRAPH:'E8D2:59602:骳 +CJK UNIFIED IDEOGRAPH:'E8D3:59603:髬 +CJK UNIFIED IDEOGRAPH:'E8D4:59604:髫 +CJK UNIFIED IDEOGRAPH:'E8D5:59605:髳 +CJK UNIFIED IDEOGRAPH:'E8D6:59606:髲 +CJK UNIFIED IDEOGRAPH:'E8D7:59607:髱 +CJK UNIFIED IDEOGRAPH:'E8D8:59608:魆 +CJK UNIFIED IDEOGRAPH:'E8D9:59609:魃 +CJK UNIFIED IDEOGRAPH:'E8DA:59610:魧 +CJK UNIFIED IDEOGRAPH:'E8DB:59611:魴 +CJK UNIFIED IDEOGRAPH:'E8DC:59612:魱 +CJK UNIFIED IDEOGRAPH:'E8DD:59613:魦 +CJK UNIFIED IDEOGRAPH:'E8DE:59614:魶 +CJK UNIFIED IDEOGRAPH:'E8DF:59615:魵 +CJK UNIFIED IDEOGRAPH:'E8E0:59616:魰 +CJK UNIFIED IDEOGRAPH:'E8E1:59617:魨 +CJK UNIFIED IDEOGRAPH:'E8E2:59618:魤 +CJK UNIFIED IDEOGRAPH:'E8E3:59619:魬 +CJK UNIFIED IDEOGRAPH:'E8E4:59620:鳼 +CJK UNIFIED IDEOGRAPH:'E8E5:59621:鳺 +CJK UNIFIED IDEOGRAPH:'E8E6:59622:鳽 +CJK UNIFIED IDEOGRAPH:'E8E7:59623:鳿 +CJK UNIFIED IDEOGRAPH:'E8E8:59624:鳷 +CJK UNIFIED IDEOGRAPH:'E8E9:59625:鴇 +CJK UNIFIED IDEOGRAPH:'E8EA:59626:鴀 +CJK UNIFIED IDEOGRAPH:'E8EB:59627:鳹 +CJK UNIFIED IDEOGRAPH:'E8EC:59628:鳻 +CJK UNIFIED IDEOGRAPH:'E8ED:59629:鴈 +CJK UNIFIED IDEOGRAPH:'E8EE:59630:鴅 +CJK UNIFIED IDEOGRAPH:'E8EF:59631:鴄 +CJK UNIFIED IDEOGRAPH:'E8F0:59632:麃 +CJK UNIFIED IDEOGRAPH:'E8F1:59633:黓 +CJK UNIFIED IDEOGRAPH:'E8F2:59634:鼏 +CJK UNIFIED IDEOGRAPH:'E8F3:59635:鼐 +CJK UNIFIED IDEOGRAPH:'E8F4:59636:儜 +CJK UNIFIED IDEOGRAPH:'E8F5:59637:儓 +CJK UNIFIED IDEOGRAPH:'E8F6:59638:儗 +CJK UNIFIED IDEOGRAPH:'E8F7:59639:儚 +CJK UNIFIED IDEOGRAPH:'E8F8:59640:儑 +CJK UNIFIED IDEOGRAPH:'E8F9:59641:凞 +CJK UNIFIED IDEOGRAPH:'E8FA:59642:匴 +CJK UNIFIED IDEOGRAPH:'E8FB:59643:叡 +CJK UNIFIED IDEOGRAPH:'E8FC:59644:噰 +CJK UNIFIED IDEOGRAPH:'E8FD:59645:噠 +CJK UNIFIED IDEOGRAPH:'E8FE:59646:噮 +CJK UNIFIED IDEOGRAPH:'E940:59712:噳 +CJK UNIFIED IDEOGRAPH:'E941:59713:噦 +CJK UNIFIED IDEOGRAPH:'E942:59714:噣 +CJK UNIFIED IDEOGRAPH:'E943:59715:噭 +CJK UNIFIED IDEOGRAPH:'E944:59716:噲 +CJK UNIFIED IDEOGRAPH:'E945:59717:噞 +CJK UNIFIED IDEOGRAPH:'E946:59718:噷 +CJK UNIFIED IDEOGRAPH:'E947:59719:圜 +CJK UNIFIED IDEOGRAPH:'E948:59720:圛 +CJK UNIFIED IDEOGRAPH:'E949:59721:壈 +CJK UNIFIED IDEOGRAPH:'E94A:59722:墽 +CJK UNIFIED IDEOGRAPH:'E94B:59723:壉 +CJK UNIFIED IDEOGRAPH:'E94C:59724:墿 +CJK UNIFIED IDEOGRAPH:'E94D:59725:墺 +CJK UNIFIED IDEOGRAPH:'E94E:59726:壂 +CJK UNIFIED IDEOGRAPH:'E94F:59727:墼 +CJK UNIFIED IDEOGRAPH:'E950:59728:壆 +CJK UNIFIED IDEOGRAPH:'E951:59729:嬗 +CJK UNIFIED IDEOGRAPH:'E952:59730:嬙 +CJK UNIFIED IDEOGRAPH:'E953:59731:嬛 +CJK UNIFIED IDEOGRAPH:'E954:59732:嬡 +CJK UNIFIED IDEOGRAPH:'E955:59733:嬔 +CJK UNIFIED IDEOGRAPH:'E956:59734:嬓 +CJK UNIFIED IDEOGRAPH:'E957:59735:嬐 +CJK UNIFIED IDEOGRAPH:'E958:59736:嬖 +CJK UNIFIED IDEOGRAPH:'E959:59737:嬨 +CJK UNIFIED IDEOGRAPH:'E95A:59738:嬚 +CJK UNIFIED IDEOGRAPH:'E95B:59739:嬠 +CJK UNIFIED IDEOGRAPH:'E95C:59740:嬞 +CJK UNIFIED IDEOGRAPH:'E95D:59741:寯 +CJK UNIFIED IDEOGRAPH:'E95E:59742:嶬 +CJK UNIFIED IDEOGRAPH:'E95F:59743:嶱 +CJK UNIFIED IDEOGRAPH:'E960:59744:嶩 +CJK UNIFIED IDEOGRAPH:'E961:59745:嶧 +CJK UNIFIED IDEOGRAPH:'E962:59746:嶵 +CJK UNIFIED IDEOGRAPH:'E963:59747:嶰 +CJK UNIFIED IDEOGRAPH:'E964:59748:嶮 +CJK UNIFIED IDEOGRAPH:'E965:59749:嶪 +CJK UNIFIED IDEOGRAPH:'E966:59750:嶨 +CJK UNIFIED IDEOGRAPH:'E967:59751:嶲 +CJK UNIFIED IDEOGRAPH:'E968:59752:嶭 +CJK UNIFIED IDEOGRAPH:'E969:59753:嶯 +CJK UNIFIED IDEOGRAPH:'E96A:59754:嶴 +CJK UNIFIED IDEOGRAPH:'E96B:59755:幧 +CJK UNIFIED IDEOGRAPH:'E96C:59756:幨 +CJK UNIFIED IDEOGRAPH:'E96D:59757:幦 +CJK UNIFIED IDEOGRAPH:'E96E:59758:幯 +CJK UNIFIED IDEOGRAPH:'E96F:59759:廩 +CJK UNIFIED IDEOGRAPH:'E970:59760:廧 +CJK UNIFIED IDEOGRAPH:'E971:59761:廦 +CJK UNIFIED IDEOGRAPH:'E972:59762:廨 +CJK UNIFIED IDEOGRAPH:'E973:59763:廥 +CJK UNIFIED IDEOGRAPH:'E974:59764:彋 +CJK UNIFIED IDEOGRAPH:'E975:59765:徼 +CJK UNIFIED IDEOGRAPH:'E976:59766:憝 +CJK UNIFIED IDEOGRAPH:'E977:59767:憨 +CJK UNIFIED IDEOGRAPH:'E978:59768:憖 +CJK UNIFIED IDEOGRAPH:'E979:59769:懅 +CJK UNIFIED IDEOGRAPH:'E97A:59770:憴 +CJK UNIFIED IDEOGRAPH:'E97B:59771:懆 +CJK UNIFIED IDEOGRAPH:'E97C:59772:懁 +CJK UNIFIED IDEOGRAPH:'E97D:59773:懌 +CJK UNIFIED IDEOGRAPH:'E97E:59774:憺 +CJK UNIFIED IDEOGRAPH:'E9A1:59809:憿 +CJK UNIFIED IDEOGRAPH:'E9A2:59810:憸 +CJK UNIFIED IDEOGRAPH:'E9A3:59811:憌 +CJK UNIFIED IDEOGRAPH:'E9A4:59812:擗 +CJK UNIFIED IDEOGRAPH:'E9A5:59813:擖 +CJK UNIFIED IDEOGRAPH:'E9A6:59814:擐 +CJK UNIFIED IDEOGRAPH:'E9A7:59815:擏 +CJK UNIFIED IDEOGRAPH:'E9A8:59816:擉 +CJK UNIFIED IDEOGRAPH:'E9A9:59817:撽 +CJK UNIFIED IDEOGRAPH:'E9AA:59818:撉 +CJK UNIFIED IDEOGRAPH:'E9AB:59819:擃 +CJK UNIFIED IDEOGRAPH:'E9AC:59820:擛 +CJK UNIFIED IDEOGRAPH:'E9AD:59821:擳 +CJK UNIFIED IDEOGRAPH:'E9AE:59822:擙 +CJK UNIFIED IDEOGRAPH:'E9AF:59823:攳 +CJK UNIFIED IDEOGRAPH:'E9B0:59824:敿 +CJK UNIFIED IDEOGRAPH:'E9B1:59825:敼 +CJK UNIFIED IDEOGRAPH:'E9B2:59826:斢 +CJK UNIFIED IDEOGRAPH:'E9B3:59827:曈 +CJK UNIFIED IDEOGRAPH:'E9B4:59828:暾 +CJK UNIFIED IDEOGRAPH:'E9B5:59829:曀 +CJK UNIFIED IDEOGRAPH:'E9B6:59830:曊 +CJK UNIFIED IDEOGRAPH:'E9B7:59831:曋 +CJK UNIFIED IDEOGRAPH:'E9B8:59832:曏 +CJK UNIFIED IDEOGRAPH:'E9B9:59833:暽 +CJK UNIFIED IDEOGRAPH:'E9BA:59834:暻 +CJK UNIFIED IDEOGRAPH:'E9BB:59835:暺 +CJK UNIFIED IDEOGRAPH:'E9BC:59836:曌 +CJK UNIFIED IDEOGRAPH:'E9BD:59837:朣 +CJK UNIFIED IDEOGRAPH:'E9BE:59838:樴 +CJK UNIFIED IDEOGRAPH:'E9BF:59839:橦 +CJK UNIFIED IDEOGRAPH:'E9C0:59840:橉 +CJK UNIFIED IDEOGRAPH:'E9C1:59841:橧 +CJK UNIFIED IDEOGRAPH:'E9C2:59842:樲 +CJK UNIFIED IDEOGRAPH:'E9C3:59843:橨 +CJK UNIFIED IDEOGRAPH:'E9C4:59844:樾 +CJK UNIFIED IDEOGRAPH:'E9C5:59845:橝 +CJK UNIFIED IDEOGRAPH:'E9C6:59846:橭 +CJK UNIFIED IDEOGRAPH:'E9C7:59847:橶 +CJK UNIFIED IDEOGRAPH:'E9C8:59848:橛 +CJK UNIFIED IDEOGRAPH:'E9C9:59849:橑 +CJK UNIFIED IDEOGRAPH:'E9CA:59850:樨 +CJK UNIFIED IDEOGRAPH:'E9CB:59851:橚 +CJK UNIFIED IDEOGRAPH:'E9CC:59852:樻 +CJK UNIFIED IDEOGRAPH:'E9CD:59853:樿 +CJK UNIFIED IDEOGRAPH:'E9CE:59854:橁 +CJK UNIFIED IDEOGRAPH:'E9CF:59855:橪 +CJK UNIFIED IDEOGRAPH:'E9D0:59856:橤 +CJK UNIFIED IDEOGRAPH:'E9D1:59857:橐 +CJK UNIFIED IDEOGRAPH:'E9D2:59858:橏 +CJK UNIFIED IDEOGRAPH:'E9D3:59859:橔 +CJK UNIFIED IDEOGRAPH:'E9D4:59860:橯 +CJK UNIFIED IDEOGRAPH:'E9D5:59861:橩 +CJK UNIFIED IDEOGRAPH:'E9D6:59862:橠 +CJK UNIFIED IDEOGRAPH:'E9D7:59863:樼 +CJK UNIFIED IDEOGRAPH:'E9D8:59864:橞 +CJK UNIFIED IDEOGRAPH:'E9D9:59865:橖 +CJK UNIFIED IDEOGRAPH:'E9DA:59866:橕 +CJK UNIFIED IDEOGRAPH:'E9DB:59867:橍 +CJK UNIFIED IDEOGRAPH:'E9DC:59868:橎 +CJK UNIFIED IDEOGRAPH:'E9DD:59869:橆 +CJK UNIFIED IDEOGRAPH:'E9DE:59870:歕 +CJK UNIFIED IDEOGRAPH:'E9DF:59871:歔 +CJK UNIFIED IDEOGRAPH:'E9E0:59872:歖 +CJK UNIFIED IDEOGRAPH:'E9E1:59873:殧 +CJK UNIFIED IDEOGRAPH:'E9E2:59874:殪 +CJK UNIFIED IDEOGRAPH:'E9E3:59875:殫 +CJK UNIFIED IDEOGRAPH:'E9E4:59876:毈 +CJK UNIFIED IDEOGRAPH:'E9E5:59877:毇 +CJK UNIFIED IDEOGRAPH:'E9E6:59878:氄 +CJK UNIFIED IDEOGRAPH:'E9E7:59879:氃 +CJK UNIFIED IDEOGRAPH:'E9E8:59880:氆 +CJK UNIFIED IDEOGRAPH:'E9E9:59881:澭 +CJK UNIFIED IDEOGRAPH:'E9EA:59882:濋 +CJK UNIFIED IDEOGRAPH:'E9EB:59883:澣 +CJK UNIFIED IDEOGRAPH:'E9EC:59884:濇 +CJK UNIFIED IDEOGRAPH:'E9ED:59885:澼 +CJK UNIFIED IDEOGRAPH:'E9EE:59886:濎 +CJK UNIFIED IDEOGRAPH:'E9EF:59887:濈 +CJK UNIFIED IDEOGRAPH:'E9F0:59888:潞 +CJK UNIFIED IDEOGRAPH:'E9F1:59889:濄 +CJK UNIFIED IDEOGRAPH:'E9F2:59890:澽 +CJK UNIFIED IDEOGRAPH:'E9F3:59891:澞 +CJK UNIFIED IDEOGRAPH:'E9F4:59892:濊 +CJK UNIFIED IDEOGRAPH:'E9F5:59893:澨 +CJK UNIFIED IDEOGRAPH:'E9F6:59894:瀄 +CJK UNIFIED IDEOGRAPH:'E9F7:59895:澥 +CJK UNIFIED IDEOGRAPH:'E9F8:59896:澮 +CJK UNIFIED IDEOGRAPH:'E9F9:59897:澺 +CJK UNIFIED IDEOGRAPH:'E9FA:59898:澬 +CJK UNIFIED IDEOGRAPH:'E9FB:59899:澪 +CJK UNIFIED IDEOGRAPH:'E9FC:59900:濏 +CJK UNIFIED IDEOGRAPH:'E9FD:59901:澿 +CJK UNIFIED IDEOGRAPH:'E9FE:59902:澸 +CJK UNIFIED IDEOGRAPH:'EA40:59968:澢 +CJK UNIFIED IDEOGRAPH:'EA41:59969:濉 +CJK UNIFIED IDEOGRAPH:'EA42:59970:澫 +CJK UNIFIED IDEOGRAPH:'EA43:59971:濍 +CJK UNIFIED IDEOGRAPH:'EA44:59972:澯 +CJK UNIFIED IDEOGRAPH:'EA45:59973:澲 +CJK UNIFIED IDEOGRAPH:'EA46:59974:澰 +CJK UNIFIED IDEOGRAPH:'EA47:59975:燅 +CJK UNIFIED IDEOGRAPH:'EA48:59976:燂 +CJK UNIFIED IDEOGRAPH:'EA49:59977:熿 +CJK UNIFIED IDEOGRAPH:'EA4A:59978:熸 +CJK UNIFIED IDEOGRAPH:'EA4B:59979:燖 +CJK UNIFIED IDEOGRAPH:'EA4C:59980:燀 +CJK UNIFIED IDEOGRAPH:'EA4D:59981:燁 +CJK UNIFIED IDEOGRAPH:'EA4E:59982:燋 +CJK UNIFIED IDEOGRAPH:'EA4F:59983:燔 +CJK UNIFIED IDEOGRAPH:'EA50:59984:燊 +CJK UNIFIED IDEOGRAPH:'EA51:59985:燇 +CJK UNIFIED IDEOGRAPH:'EA52:59986:燏 +CJK UNIFIED IDEOGRAPH:'EA53:59987:熽 +CJK UNIFIED IDEOGRAPH:'EA54:59988:燘 +CJK UNIFIED IDEOGRAPH:'EA55:59989:熼 +CJK UNIFIED IDEOGRAPH:'EA56:59990:燆 +CJK UNIFIED IDEOGRAPH:'EA57:59991:燚 +CJK UNIFIED IDEOGRAPH:'EA58:59992:燛 +CJK UNIFIED IDEOGRAPH:'EA59:59993:犝 +CJK UNIFIED IDEOGRAPH:'EA5A:59994:犞 +CJK UNIFIED IDEOGRAPH:'EA5B:59995:獩 +CJK UNIFIED IDEOGRAPH:'EA5C:59996:獦 +CJK UNIFIED IDEOGRAPH:'EA5D:59997:獧 +CJK UNIFIED IDEOGRAPH:'EA5E:59998:獬 +CJK UNIFIED IDEOGRAPH:'EA5F:59999:獥 +CJK UNIFIED IDEOGRAPH:'EA60:60000:獫 +CJK UNIFIED IDEOGRAPH:'EA61:60001:獪 +CJK UNIFIED IDEOGRAPH:'EA62:60002:瑿 +CJK UNIFIED IDEOGRAPH:'EA63:60003:璚 +CJK UNIFIED IDEOGRAPH:'EA64:60004:璠 +CJK UNIFIED IDEOGRAPH:'EA65:60005:璔 +CJK UNIFIED IDEOGRAPH:'EA66:60006:璒 +CJK UNIFIED IDEOGRAPH:'EA67:60007:璕 +CJK UNIFIED IDEOGRAPH:'EA68:60008:璡 +CJK UNIFIED IDEOGRAPH:'EA69:60009:甋 +CJK UNIFIED IDEOGRAPH:'EA6A:60010:疀 +CJK UNIFIED IDEOGRAPH:'EA6B:60011:瘯 +CJK UNIFIED IDEOGRAPH:'EA6C:60012:瘭 +CJK UNIFIED IDEOGRAPH:'EA6D:60013:瘱 +CJK UNIFIED IDEOGRAPH:'EA6E:60014:瘽 +CJK UNIFIED IDEOGRAPH:'EA6F:60015:瘳 +CJK UNIFIED IDEOGRAPH:'EA70:60016:瘼 +CJK UNIFIED IDEOGRAPH:'EA71:60017:瘵 +CJK UNIFIED IDEOGRAPH:'EA72:60018:瘲 +CJK UNIFIED IDEOGRAPH:'EA73:60019:瘰 +CJK UNIFIED IDEOGRAPH:'EA74:60020:皻 +CJK UNIFIED IDEOGRAPH:'EA75:60021:盦 +CJK UNIFIED IDEOGRAPH:'EA76:60022:瞚 +CJK UNIFIED IDEOGRAPH:'EA77:60023:瞝 +CJK UNIFIED IDEOGRAPH:'EA78:60024:瞡 +CJK UNIFIED IDEOGRAPH:'EA79:60025:瞜 +CJK UNIFIED IDEOGRAPH:'EA7A:60026:瞛 +CJK UNIFIED IDEOGRAPH:'EA7B:60027:瞢 +CJK UNIFIED IDEOGRAPH:'EA7C:60028:瞣 +CJK UNIFIED IDEOGRAPH:'EA7D:60029:瞕 +CJK UNIFIED IDEOGRAPH:'EA7E:60030:瞙 +CJK UNIFIED IDEOGRAPH:'EAA1:60065:瞗 +CJK UNIFIED IDEOGRAPH:'EAA2:60066:磝 +CJK UNIFIED IDEOGRAPH:'EAA3:60067:磩 +CJK UNIFIED IDEOGRAPH:'EAA4:60068:磥 +CJK UNIFIED IDEOGRAPH:'EAA5:60069:磪 +CJK UNIFIED IDEOGRAPH:'EAA6:60070:磞 +CJK UNIFIED IDEOGRAPH:'EAA7:60071:磣 +CJK UNIFIED IDEOGRAPH:'EAA8:60072:磛 +CJK UNIFIED IDEOGRAPH:'EAA9:60073:磡 +CJK UNIFIED IDEOGRAPH:'EAAA:60074:磢 +CJK UNIFIED IDEOGRAPH:'EAAB:60075:磭 +CJK UNIFIED IDEOGRAPH:'EAAC:60076:磟 +CJK UNIFIED IDEOGRAPH:'EAAD:60077:磠 +CJK UNIFIED IDEOGRAPH:'EAAE:60078:禤 +CJK UNIFIED IDEOGRAPH:'EAAF:60079:穄 +CJK UNIFIED IDEOGRAPH:'EAB0:60080:穈 +CJK UNIFIED IDEOGRAPH:'EAB1:60081:穇 +CJK UNIFIED IDEOGRAPH:'EAB2:60082:窶 +CJK UNIFIED IDEOGRAPH:'EAB3:60083:窸 +CJK UNIFIED IDEOGRAPH:'EAB4:60084:窵 +CJK UNIFIED IDEOGRAPH:'EAB5:60085:窱 +CJK UNIFIED IDEOGRAPH:'EAB6:60086:窷 +CJK UNIFIED IDEOGRAPH:'EAB7:60087:篞 +CJK UNIFIED IDEOGRAPH:'EAB8:60088:篣 +CJK UNIFIED IDEOGRAPH:'EAB9:60089:篧 +CJK UNIFIED IDEOGRAPH:'EABA:60090:篝 +CJK UNIFIED IDEOGRAPH:'EABB:60091:篕 +CJK UNIFIED IDEOGRAPH:'EABC:60092:篥 +CJK UNIFIED IDEOGRAPH:'EABD:60093:篚 +CJK UNIFIED IDEOGRAPH:'EABE:60094:篨 +CJK UNIFIED IDEOGRAPH:'EABF:60095:篹 +CJK UNIFIED IDEOGRAPH:'EAC0:60096:篔 +CJK UNIFIED IDEOGRAPH:'EAC1:60097:篪 +CJK UNIFIED IDEOGRAPH:'EAC2:60098:篢 +CJK UNIFIED IDEOGRAPH:'EAC3:60099:篜 +CJK UNIFIED IDEOGRAPH:'EAC4:60100:篫 +CJK UNIFIED IDEOGRAPH:'EAC5:60101:篘 +CJK UNIFIED IDEOGRAPH:'EAC6:60102:篟 +CJK UNIFIED IDEOGRAPH:'EAC7:60103:糒 +CJK UNIFIED IDEOGRAPH:'EAC8:60104:糔 +CJK UNIFIED IDEOGRAPH:'EAC9:60105:糗 +CJK UNIFIED IDEOGRAPH:'EACA:60106:糐 +CJK UNIFIED IDEOGRAPH:'EACB:60107:糑 +CJK UNIFIED IDEOGRAPH:'EACC:60108:縒 +CJK UNIFIED IDEOGRAPH:'EACD:60109:縡 +CJK UNIFIED IDEOGRAPH:'EACE:60110:縗 +CJK UNIFIED IDEOGRAPH:'EACF:60111:縌 +CJK UNIFIED IDEOGRAPH:'EAD0:60112:縟 +CJK UNIFIED IDEOGRAPH:'EAD1:60113:縠 +CJK UNIFIED IDEOGRAPH:'EAD2:60114:縓 +CJK UNIFIED IDEOGRAPH:'EAD3:60115:縎 +CJK UNIFIED IDEOGRAPH:'EAD4:60116:縜 +CJK UNIFIED IDEOGRAPH:'EAD5:60117:縕 +CJK UNIFIED IDEOGRAPH:'EAD6:60118:縚 +CJK UNIFIED IDEOGRAPH:'EAD7:60119:縢 +CJK UNIFIED IDEOGRAPH:'EAD8:60120:縋 +CJK UNIFIED IDEOGRAPH:'EAD9:60121:縏 +CJK UNIFIED IDEOGRAPH:'EADA:60122:縖 +CJK UNIFIED IDEOGRAPH:'EADB:60123:縍 +CJK UNIFIED IDEOGRAPH:'EADC:60124:縔 +CJK UNIFIED IDEOGRAPH:'EADD:60125:縥 +CJK UNIFIED IDEOGRAPH:'EADE:60126:縤 +CJK UNIFIED IDEOGRAPH:'EADF:60127:罃 +CJK UNIFIED IDEOGRAPH:'EAE0:60128:罻 +CJK UNIFIED IDEOGRAPH:'EAE1:60129:罼 +CJK UNIFIED IDEOGRAPH:'EAE2:60130:罺 +CJK UNIFIED IDEOGRAPH:'EAE3:60131:羱 +CJK UNIFIED IDEOGRAPH:'EAE4:60132:翯 +CJK UNIFIED IDEOGRAPH:'EAE5:60133:耪 +CJK UNIFIED IDEOGRAPH:'EAE6:60134:耩 +CJK UNIFIED IDEOGRAPH:'EAE7:60135:聬 +CJK UNIFIED IDEOGRAPH:'EAE8:60136:膱 +CJK UNIFIED IDEOGRAPH:'EAE9:60137:膦 +CJK UNIFIED IDEOGRAPH:'EAEA:60138:膮 +CJK UNIFIED IDEOGRAPH:'EAEB:60139:膹 +CJK UNIFIED IDEOGRAPH:'EAEC:60140:膵 +CJK UNIFIED IDEOGRAPH:'EAED:60141:膫 +CJK UNIFIED IDEOGRAPH:'EAEE:60142:膰 +CJK UNIFIED IDEOGRAPH:'EAEF:60143:膬 +CJK UNIFIED IDEOGRAPH:'EAF0:60144:膴 +CJK UNIFIED IDEOGRAPH:'EAF1:60145:膲 +CJK UNIFIED IDEOGRAPH:'EAF2:60146:膷 +CJK UNIFIED IDEOGRAPH:'EAF3:60147:膧 +CJK UNIFIED IDEOGRAPH:'EAF4:60148:臲 +CJK UNIFIED IDEOGRAPH:'EAF5:60149:艕 +CJK UNIFIED IDEOGRAPH:'EAF6:60150:艖 +CJK UNIFIED IDEOGRAPH:'EAF7:60151:艗 +CJK UNIFIED IDEOGRAPH:'EAF8:60152:蕖 +CJK UNIFIED IDEOGRAPH:'EAF9:60153:蕅 +CJK UNIFIED IDEOGRAPH:'EAFA:60154:蕫 +CJK UNIFIED IDEOGRAPH:'EAFB:60155:蕍 +CJK UNIFIED IDEOGRAPH:'EAFC:60156:蕓 +CJK UNIFIED IDEOGRAPH:'EAFD:60157:蕡 +CJK UNIFIED IDEOGRAPH:'EAFE:60158:蕘 +CJK UNIFIED IDEOGRAPH:'EB40:60224:蕀 +CJK UNIFIED IDEOGRAPH:'EB41:60225:蕆 +CJK UNIFIED IDEOGRAPH:'EB42:60226:蕤 +CJK UNIFIED IDEOGRAPH:'EB43:60227:蕁 +CJK UNIFIED IDEOGRAPH:'EB44:60228:蕢 +CJK UNIFIED IDEOGRAPH:'EB45:60229:蕄 +CJK UNIFIED IDEOGRAPH:'EB46:60230:蕑 +CJK UNIFIED IDEOGRAPH:'EB47:60231:蕇 +CJK UNIFIED IDEOGRAPH:'EB48:60232:蕣 +CJK UNIFIED IDEOGRAPH:'EB49:60233:蔾 +CJK UNIFIED IDEOGRAPH:'EB4A:60234:蕛 +CJK UNIFIED IDEOGRAPH:'EB4B:60235:蕱 +CJK UNIFIED IDEOGRAPH:'EB4C:60236:蕎 +CJK UNIFIED IDEOGRAPH:'EB4D:60237:蕮 +CJK UNIFIED IDEOGRAPH:'EB4E:60238:蕵 +CJK UNIFIED IDEOGRAPH:'EB4F:60239:蕕 +CJK UNIFIED IDEOGRAPH:'EB50:60240:蕧 +CJK UNIFIED IDEOGRAPH:'EB51:60241:蕠 +CJK UNIFIED IDEOGRAPH:'EB52:60242:薌 +CJK UNIFIED IDEOGRAPH:'EB53:60243:蕦 +CJK UNIFIED IDEOGRAPH:'EB54:60244:蕝 +CJK UNIFIED IDEOGRAPH:'EB55:60245:蕔 +CJK UNIFIED IDEOGRAPH:'EB56:60246:蕥 +CJK UNIFIED IDEOGRAPH:'EB57:60247:蕬 +CJK UNIFIED IDEOGRAPH:'EB58:60248:虣 +CJK UNIFIED IDEOGRAPH:'EB59:60249:虥 +CJK UNIFIED IDEOGRAPH:'EB5A:60250:虤 +CJK UNIFIED IDEOGRAPH:'EB5B:60251:螛 +CJK UNIFIED IDEOGRAPH:'EB5C:60252:螏 +CJK UNIFIED IDEOGRAPH:'EB5D:60253:螗 +CJK UNIFIED IDEOGRAPH:'EB5E:60254:螓 +CJK UNIFIED IDEOGRAPH:'EB5F:60255:螒 +CJK UNIFIED IDEOGRAPH:'EB60:60256:螈 +CJK UNIFIED IDEOGRAPH:'EB61:60257:螁 +CJK UNIFIED IDEOGRAPH:'EB62:60258:螖 +CJK UNIFIED IDEOGRAPH:'EB63:60259:螘 +CJK UNIFIED IDEOGRAPH:'EB64:60260:蝹 +CJK UNIFIED IDEOGRAPH:'EB65:60261:螇 +CJK UNIFIED IDEOGRAPH:'EB66:60262:螣 +CJK UNIFIED IDEOGRAPH:'EB67:60263:螅 +CJK UNIFIED IDEOGRAPH:'EB68:60264:螐 +CJK UNIFIED IDEOGRAPH:'EB69:60265:螑 +CJK UNIFIED IDEOGRAPH:'EB6A:60266:螝 +CJK UNIFIED IDEOGRAPH:'EB6B:60267:螄 +CJK UNIFIED IDEOGRAPH:'EB6C:60268:螔 +CJK UNIFIED IDEOGRAPH:'EB6D:60269:螜 +CJK UNIFIED IDEOGRAPH:'EB6E:60270:螚 +CJK UNIFIED IDEOGRAPH:'EB6F:60271:螉 +CJK UNIFIED IDEOGRAPH:'EB70:60272:褞 +CJK UNIFIED IDEOGRAPH:'EB71:60273:褦 +CJK UNIFIED IDEOGRAPH:'EB72:60274:褰 +CJK UNIFIED IDEOGRAPH:'EB73:60275:褭 +CJK UNIFIED IDEOGRAPH:'EB74:60276:褮 +CJK UNIFIED IDEOGRAPH:'EB75:60277:褧 +CJK UNIFIED IDEOGRAPH:'EB76:60278:褱 +CJK UNIFIED IDEOGRAPH:'EB77:60279:褢 +CJK UNIFIED IDEOGRAPH:'EB78:60280:褩 +CJK UNIFIED IDEOGRAPH:'EB79:60281:褣 +CJK UNIFIED IDEOGRAPH:'EB7A:60282:褯 +CJK UNIFIED IDEOGRAPH:'EB7B:60283:褬 +CJK UNIFIED IDEOGRAPH:'EB7C:60284:褟 +CJK UNIFIED IDEOGRAPH:'EB7D:60285:觱 +CJK UNIFIED IDEOGRAPH:'EB7E:60286:諠 +CJK UNIFIED IDEOGRAPH:'EBA1:60321:諢 +CJK UNIFIED IDEOGRAPH:'EBA2:60322:諲 +CJK UNIFIED IDEOGRAPH:'EBA3:60323:諴 +CJK UNIFIED IDEOGRAPH:'EBA4:60324:諵 +CJK UNIFIED IDEOGRAPH:'EBA5:60325:諝 +CJK UNIFIED IDEOGRAPH:'EBA6:60326:謔 +CJK UNIFIED IDEOGRAPH:'EBA7:60327:諤 +CJK UNIFIED IDEOGRAPH:'EBA8:60328:諟 +CJK UNIFIED IDEOGRAPH:'EBA9:60329:諰 +CJK UNIFIED IDEOGRAPH:'EBAA:60330:諈 +CJK UNIFIED IDEOGRAPH:'EBAB:60331:諞 +CJK UNIFIED IDEOGRAPH:'EBAC:60332:諡 +CJK UNIFIED IDEOGRAPH:'EBAD:60333:諨 +CJK UNIFIED IDEOGRAPH:'EBAE:60334:諿 +CJK UNIFIED IDEOGRAPH:'EBAF:60335:諯 +CJK UNIFIED IDEOGRAPH:'EBB0:60336:諻 +CJK UNIFIED IDEOGRAPH:'EBB1:60337:貑 +CJK UNIFIED IDEOGRAPH:'EBB2:60338:貒 +CJK UNIFIED IDEOGRAPH:'EBB3:60339:貐 +CJK UNIFIED IDEOGRAPH:'EBB4:60340:賵 +CJK UNIFIED IDEOGRAPH:'EBB5:60341:賮 +CJK UNIFIED IDEOGRAPH:'EBB6:60342:賱 +CJK UNIFIED IDEOGRAPH:'EBB7:60343:賰 +CJK UNIFIED IDEOGRAPH:'EBB8:60344:賳 +CJK UNIFIED IDEOGRAPH:'EBB9:60345:赬 +CJK UNIFIED IDEOGRAPH:'EBBA:60346:赮 +CJK UNIFIED IDEOGRAPH:'EBBB:60347:趥 +CJK UNIFIED IDEOGRAPH:'EBBC:60348:趧 +CJK UNIFIED IDEOGRAPH:'EBBD:60349:踳 +CJK UNIFIED IDEOGRAPH:'EBBE:60350:踾 +CJK UNIFIED IDEOGRAPH:'EBBF:60351:踸 +CJK UNIFIED IDEOGRAPH:'EBC0:60352:蹀 +CJK UNIFIED IDEOGRAPH:'EBC1:60353:蹅 +CJK UNIFIED IDEOGRAPH:'EBC2:60354:踶 +CJK UNIFIED IDEOGRAPH:'EBC3:60355:踼 +CJK UNIFIED IDEOGRAPH:'EBC4:60356:踽 +CJK UNIFIED IDEOGRAPH:'EBC5:60357:蹁 +CJK UNIFIED IDEOGRAPH:'EBC6:60358:踰 +CJK UNIFIED IDEOGRAPH:'EBC7:60359:踿 +CJK UNIFIED IDEOGRAPH:'EBC8:60360:躽 +CJK UNIFIED IDEOGRAPH:'EBC9:60361:輶 +CJK UNIFIED IDEOGRAPH:'EBCA:60362:輮 +CJK UNIFIED IDEOGRAPH:'EBCB:60363:輵 +CJK UNIFIED IDEOGRAPH:'EBCC:60364:輲 +CJK UNIFIED IDEOGRAPH:'EBCD:60365:輹 +CJK UNIFIED IDEOGRAPH:'EBCE:60366:輷 +CJK UNIFIED IDEOGRAPH:'EBCF:60367:輴 +CJK UNIFIED IDEOGRAPH:'EBD0:60368:遶 +CJK UNIFIED IDEOGRAPH:'EBD1:60369:遹 +CJK UNIFIED IDEOGRAPH:'EBD2:60370:遻 +CJK UNIFIED IDEOGRAPH:'EBD3:60371:邆 +CJK UNIFIED IDEOGRAPH:'EBD4:60372:郺 +CJK UNIFIED IDEOGRAPH:'EBD5:60373:鄳 +CJK UNIFIED IDEOGRAPH:'EBD6:60374:鄵 +CJK UNIFIED IDEOGRAPH:'EBD7:60375:鄶 +CJK UNIFIED IDEOGRAPH:'EBD8:60376:醓 +CJK UNIFIED IDEOGRAPH:'EBD9:60377:醐 +CJK UNIFIED IDEOGRAPH:'EBDA:60378:醑 +CJK UNIFIED IDEOGRAPH:'EBDB:60379:醍 +CJK UNIFIED IDEOGRAPH:'EBDC:60380:醏 +CJK UNIFIED IDEOGRAPH:'EBDD:60381:錧 +CJK UNIFIED IDEOGRAPH:'EBDE:60382:錞 +CJK UNIFIED IDEOGRAPH:'EBDF:60383:錈 +CJK UNIFIED IDEOGRAPH:'EBE0:60384:錟 +CJK UNIFIED IDEOGRAPH:'EBE1:60385:錆 +CJK UNIFIED IDEOGRAPH:'EBE2:60386:錏 +CJK UNIFIED IDEOGRAPH:'EBE3:60387:鍺 +CJK UNIFIED IDEOGRAPH:'EBE4:60388:錸 +CJK UNIFIED IDEOGRAPH:'EBE5:60389:錼 +CJK UNIFIED IDEOGRAPH:'EBE6:60390:錛 +CJK UNIFIED IDEOGRAPH:'EBE7:60391:錣 +CJK UNIFIED IDEOGRAPH:'EBE8:60392:錒 +CJK UNIFIED IDEOGRAPH:'EBE9:60393:錁 +CJK UNIFIED IDEOGRAPH:'EBEA:60394:鍆 +CJK UNIFIED IDEOGRAPH:'EBEB:60395:錭 +CJK UNIFIED IDEOGRAPH:'EBEC:60396:錎 +CJK UNIFIED IDEOGRAPH:'EBED:60397:錍 +CJK UNIFIED IDEOGRAPH:'EBEE:60398:鋋 +CJK UNIFIED IDEOGRAPH:'EBEF:60399:錝 +CJK UNIFIED IDEOGRAPH:'EBF0:60400:鋺 +CJK UNIFIED IDEOGRAPH:'EBF1:60401:錥 +CJK UNIFIED IDEOGRAPH:'EBF2:60402:錓 +CJK UNIFIED IDEOGRAPH:'EBF3:60403:鋹 +CJK UNIFIED IDEOGRAPH:'EBF4:60404:鋷 +CJK UNIFIED IDEOGRAPH:'EBF5:60405:錴 +CJK UNIFIED IDEOGRAPH:'EBF6:60406:錂 +CJK UNIFIED IDEOGRAPH:'EBF7:60407:錤 +CJK UNIFIED IDEOGRAPH:'EBF8:60408:鋿 +CJK UNIFIED IDEOGRAPH:'EBF9:60409:錩 +CJK UNIFIED IDEOGRAPH:'EBFA:60410:錹 +CJK UNIFIED IDEOGRAPH:'EBFB:60411:錵 +CJK UNIFIED IDEOGRAPH:'EBFC:60412:錪 +CJK UNIFIED IDEOGRAPH:'EBFD:60413:錔 +CJK UNIFIED IDEOGRAPH:'EBFE:60414:錌 +CJK UNIFIED IDEOGRAPH:'EC40:60480:錋 +CJK UNIFIED IDEOGRAPH:'EC41:60481:鋾 +CJK UNIFIED IDEOGRAPH:'EC42:60482:錉 +CJK UNIFIED IDEOGRAPH:'EC43:60483:錀 +CJK UNIFIED IDEOGRAPH:'EC44:60484:鋻 +CJK UNIFIED IDEOGRAPH:'EC45:60485:錖 +CJK UNIFIED IDEOGRAPH:'EC46:60486:閼 +CJK UNIFIED IDEOGRAPH:'EC47:60487:闍 +CJK UNIFIED IDEOGRAPH:'EC48:60488:閾 +CJK UNIFIED IDEOGRAPH:'EC49:60489:閹 +CJK UNIFIED IDEOGRAPH:'EC4A:60490:閺 +CJK UNIFIED IDEOGRAPH:'EC4B:60491:閶 +CJK UNIFIED IDEOGRAPH:'EC4C:60492:閿 +CJK UNIFIED IDEOGRAPH:'EC4D:60493:閵 +CJK UNIFIED IDEOGRAPH:'EC4E:60494:閽 +CJK UNIFIED IDEOGRAPH:'EC4F:60495:隩 +CJK UNIFIED IDEOGRAPH:'EC50:60496:雔 +CJK UNIFIED IDEOGRAPH:'EC51:60497:霋 +CJK UNIFIED IDEOGRAPH:'EC52:60498:霒 +CJK UNIFIED IDEOGRAPH:'EC53:60499:霐 +CJK UNIFIED IDEOGRAPH:'EC54:60500:鞙 +CJK UNIFIED IDEOGRAPH:'EC55:60501:鞗 +CJK UNIFIED IDEOGRAPH:'EC56:60502:鞔 +CJK UNIFIED IDEOGRAPH:'EC57:60503:韰 +CJK UNIFIED IDEOGRAPH:'EC58:60504:韸 +CJK UNIFIED IDEOGRAPH:'EC59:60505:頵 +CJK UNIFIED IDEOGRAPH:'EC5A:60506:頯 +CJK UNIFIED IDEOGRAPH:'EC5B:60507:頲 +CJK UNIFIED IDEOGRAPH:'EC5C:60508:餤 +CJK UNIFIED IDEOGRAPH:'EC5D:60509:餟 +CJK UNIFIED IDEOGRAPH:'EC5E:60510:餧 +CJK UNIFIED IDEOGRAPH:'EC5F:60511:餩 +CJK UNIFIED IDEOGRAPH:'EC60:60512:馞 +CJK UNIFIED IDEOGRAPH:'EC61:60513:駮 +CJK UNIFIED IDEOGRAPH:'EC62:60514:駬 +CJK UNIFIED IDEOGRAPH:'EC63:60515:駥 +CJK UNIFIED IDEOGRAPH:'EC64:60516:駤 +CJK UNIFIED IDEOGRAPH:'EC65:60517:駰 +CJK UNIFIED IDEOGRAPH:'EC66:60518:駣 +CJK UNIFIED IDEOGRAPH:'EC67:60519:駪 +CJK UNIFIED IDEOGRAPH:'EC68:60520:駩 +CJK UNIFIED IDEOGRAPH:'EC69:60521:駧 +CJK UNIFIED IDEOGRAPH:'EC6A:60522:骹 +CJK UNIFIED IDEOGRAPH:'EC6B:60523:骿 +CJK UNIFIED IDEOGRAPH:'EC6C:60524:骴 +CJK UNIFIED IDEOGRAPH:'EC6D:60525:骻 +CJK UNIFIED IDEOGRAPH:'EC6E:60526:髶 +CJK UNIFIED IDEOGRAPH:'EC6F:60527:髺 +CJK UNIFIED IDEOGRAPH:'EC70:60528:髹 +CJK UNIFIED IDEOGRAPH:'EC71:60529:髷 +CJK UNIFIED IDEOGRAPH:'EC72:60530:鬳 +CJK UNIFIED IDEOGRAPH:'EC73:60531:鮀 +CJK UNIFIED IDEOGRAPH:'EC74:60532:鮅 +CJK UNIFIED IDEOGRAPH:'EC75:60533:鮇 +CJK UNIFIED IDEOGRAPH:'EC76:60534:魼 +CJK UNIFIED IDEOGRAPH:'EC77:60535:魾 +CJK UNIFIED IDEOGRAPH:'EC78:60536:魻 +CJK UNIFIED IDEOGRAPH:'EC79:60537:鮂 +CJK UNIFIED IDEOGRAPH:'EC7A:60538:鮓 +CJK UNIFIED IDEOGRAPH:'EC7B:60539:鮒 +CJK UNIFIED IDEOGRAPH:'EC7C:60540:鮐 +CJK UNIFIED IDEOGRAPH:'EC7D:60541:魺 +CJK UNIFIED IDEOGRAPH:'EC7E:60542:鮕 +CJK UNIFIED IDEOGRAPH:'ECA1:60577:魽 +CJK UNIFIED IDEOGRAPH:'ECA2:60578:鮈 +CJK UNIFIED IDEOGRAPH:'ECA3:60579:鴥 +CJK UNIFIED IDEOGRAPH:'ECA4:60580:鴗 +CJK UNIFIED IDEOGRAPH:'ECA5:60581:鴠 +CJK UNIFIED IDEOGRAPH:'ECA6:60582:鴞 +CJK UNIFIED IDEOGRAPH:'ECA7:60583:鴔 +CJK UNIFIED IDEOGRAPH:'ECA8:60584:鴩 +CJK UNIFIED IDEOGRAPH:'ECA9:60585:鴝 +CJK UNIFIED IDEOGRAPH:'ECAA:60586:鴘 +CJK UNIFIED IDEOGRAPH:'ECAB:60587:鴢 +CJK UNIFIED IDEOGRAPH:'ECAC:60588:鴐 +CJK UNIFIED IDEOGRAPH:'ECAD:60589:鴙 +CJK UNIFIED IDEOGRAPH:'ECAE:60590:鴟 +CJK UNIFIED IDEOGRAPH:'ECAF:60591:麈 +CJK UNIFIED IDEOGRAPH:'ECB0:60592:麆 +CJK UNIFIED IDEOGRAPH:'ECB1:60593:麇 +CJK UNIFIED IDEOGRAPH:'ECB2:60594:麮 +CJK UNIFIED IDEOGRAPH:'ECB3:60595:麭 +CJK UNIFIED IDEOGRAPH:'ECB4:60596:黕 +CJK UNIFIED IDEOGRAPH:'ECB5:60597:黖 +CJK UNIFIED IDEOGRAPH:'ECB6:60598:黺 +CJK UNIFIED IDEOGRAPH:'ECB7:60599:鼒 +CJK UNIFIED IDEOGRAPH:'ECB8:60600:鼽 +CJK UNIFIED IDEOGRAPH:'ECB9:60601:儦 +CJK UNIFIED IDEOGRAPH:'ECBA:60602:儥 +CJK UNIFIED IDEOGRAPH:'ECBB:60603:儢 +CJK UNIFIED IDEOGRAPH:'ECBC:60604:儤 +CJK UNIFIED IDEOGRAPH:'ECBD:60605:儠 +CJK UNIFIED IDEOGRAPH:'ECBE:60606:儩 +CJK UNIFIED IDEOGRAPH:'ECBF:60607:勴 +CJK UNIFIED IDEOGRAPH:'ECC0:60608:嚓 +CJK UNIFIED IDEOGRAPH:'ECC1:60609:嚌 +CJK UNIFIED IDEOGRAPH:'ECC2:60610:嚍 +CJK UNIFIED IDEOGRAPH:'ECC3:60611:嚆 +CJK UNIFIED IDEOGRAPH:'ECC4:60612:嚄 +CJK UNIFIED IDEOGRAPH:'ECC5:60613:嚃 +CJK UNIFIED IDEOGRAPH:'ECC6:60614:噾 +CJK UNIFIED IDEOGRAPH:'ECC7:60615:嚂 +CJK UNIFIED IDEOGRAPH:'ECC8:60616:噿 +CJK UNIFIED IDEOGRAPH:'ECC9:60617:嚁 +CJK UNIFIED IDEOGRAPH:'ECCA:60618:壖 +CJK UNIFIED IDEOGRAPH:'ECCB:60619:壔 +CJK UNIFIED IDEOGRAPH:'ECCC:60620:壏 +CJK UNIFIED IDEOGRAPH:'ECCD:60621:壒 +CJK UNIFIED IDEOGRAPH:'ECCE:60622:嬭 +CJK UNIFIED IDEOGRAPH:'ECCF:60623:嬥 +CJK UNIFIED IDEOGRAPH:'ECD0:60624:嬲 +CJK UNIFIED IDEOGRAPH:'ECD1:60625:嬣 +CJK UNIFIED IDEOGRAPH:'ECD2:60626:嬬 +CJK UNIFIED IDEOGRAPH:'ECD3:60627:嬧 +CJK UNIFIED IDEOGRAPH:'ECD4:60628:嬦 +CJK UNIFIED IDEOGRAPH:'ECD5:60629:嬯 +CJK UNIFIED IDEOGRAPH:'ECD6:60630:嬮 +CJK UNIFIED IDEOGRAPH:'ECD7:60631:孻 +CJK UNIFIED IDEOGRAPH:'ECD8:60632:寱 +CJK UNIFIED IDEOGRAPH:'ECD9:60633:寲 +CJK UNIFIED IDEOGRAPH:'ECDA:60634:嶷 +CJK UNIFIED IDEOGRAPH:'ECDB:60635:幬 +CJK UNIFIED IDEOGRAPH:'ECDC:60636:幪 +CJK UNIFIED IDEOGRAPH:'ECDD:60637:徾 +CJK UNIFIED IDEOGRAPH:'ECDE:60638:徻 +CJK UNIFIED IDEOGRAPH:'ECDF:60639:懃 +CJK UNIFIED IDEOGRAPH:'ECE0:60640:憵 +CJK UNIFIED IDEOGRAPH:'ECE1:60641:憼 +CJK UNIFIED IDEOGRAPH:'ECE2:60642:懧 +CJK UNIFIED IDEOGRAPH:'ECE3:60643:懠 +CJK UNIFIED IDEOGRAPH:'ECE4:60644:懥 +CJK UNIFIED IDEOGRAPH:'ECE5:60645:懤 +CJK UNIFIED IDEOGRAPH:'ECE6:60646:懨 +CJK UNIFIED IDEOGRAPH:'ECE7:60647:懞 +CJK UNIFIED IDEOGRAPH:'ECE8:60648:擯 +CJK UNIFIED IDEOGRAPH:'ECE9:60649:擩 +CJK UNIFIED IDEOGRAPH:'ECEA:60650:擣 +CJK UNIFIED IDEOGRAPH:'ECEB:60651:擫 +CJK UNIFIED IDEOGRAPH:'ECEC:60652:擤 +CJK UNIFIED IDEOGRAPH:'ECED:60653:擨 +CJK UNIFIED IDEOGRAPH:'ECEE:60654:斁 +CJK UNIFIED IDEOGRAPH:'ECEF:60655:斀 +CJK UNIFIED IDEOGRAPH:'ECF0:60656:斶 +CJK UNIFIED IDEOGRAPH:'ECF1:60657:旚 +CJK UNIFIED IDEOGRAPH:'ECF2:60658:曒 +CJK UNIFIED IDEOGRAPH:'ECF3:60659:檍 +CJK UNIFIED IDEOGRAPH:'ECF4:60660:檖 +CJK UNIFIED IDEOGRAPH:'ECF5:60661:檁 +CJK UNIFIED IDEOGRAPH:'ECF6:60662:檥 +CJK UNIFIED IDEOGRAPH:'ECF7:60663:檉 +CJK UNIFIED IDEOGRAPH:'ECF8:60664:檟 +CJK UNIFIED IDEOGRAPH:'ECF9:60665:檛 +CJK UNIFIED IDEOGRAPH:'ECFA:60666:檡 +CJK UNIFIED IDEOGRAPH:'ECFB:60667:檞 +CJK UNIFIED IDEOGRAPH:'ECFC:60668:檇 +CJK UNIFIED IDEOGRAPH:'ECFD:60669:檓 +CJK UNIFIED IDEOGRAPH:'ECFE:60670:檎 +CJK UNIFIED IDEOGRAPH:'ED40:60736:檕 +CJK UNIFIED IDEOGRAPH:'ED41:60737:檃 +CJK UNIFIED IDEOGRAPH:'ED42:60738:檨 +CJK UNIFIED IDEOGRAPH:'ED43:60739:檤 +CJK UNIFIED IDEOGRAPH:'ED44:60740:檑 +CJK UNIFIED IDEOGRAPH:'ED45:60741:橿 +CJK UNIFIED IDEOGRAPH:'ED46:60742:檦 +CJK UNIFIED IDEOGRAPH:'ED47:60743:檚 +CJK UNIFIED IDEOGRAPH:'ED48:60744:檅 +CJK UNIFIED IDEOGRAPH:'ED49:60745:檌 +CJK UNIFIED IDEOGRAPH:'ED4A:60746:檒 +CJK UNIFIED IDEOGRAPH:'ED4B:60747:歛 +CJK UNIFIED IDEOGRAPH:'ED4C:60748:殭 +CJK UNIFIED IDEOGRAPH:'ED4D:60749:氉 +CJK UNIFIED IDEOGRAPH:'ED4E:60750:濌 +CJK UNIFIED IDEOGRAPH:'ED4F:60751:澩 +CJK UNIFIED IDEOGRAPH:'ED50:60752:濴 +CJK UNIFIED IDEOGRAPH:'ED51:60753:濔 +CJK UNIFIED IDEOGRAPH:'ED52:60754:濣 +CJK UNIFIED IDEOGRAPH:'ED53:60755:濜 +CJK UNIFIED IDEOGRAPH:'ED54:60756:濭 +CJK UNIFIED IDEOGRAPH:'ED55:60757:濧 +CJK UNIFIED IDEOGRAPH:'ED56:60758:濦 +CJK UNIFIED IDEOGRAPH:'ED57:60759:濞 +CJK UNIFIED IDEOGRAPH:'ED58:60760:濲 +CJK UNIFIED IDEOGRAPH:'ED59:60761:濝 +CJK UNIFIED IDEOGRAPH:'ED5A:60762:濢 +CJK UNIFIED IDEOGRAPH:'ED5B:60763:濨 +CJK UNIFIED IDEOGRAPH:'ED5C:60764:燡 +CJK UNIFIED IDEOGRAPH:'ED5D:60765:燱 +CJK UNIFIED IDEOGRAPH:'ED5E:60766:燨 +CJK UNIFIED IDEOGRAPH:'ED5F:60767:燲 +CJK UNIFIED IDEOGRAPH:'ED60:60768:燤 +CJK UNIFIED IDEOGRAPH:'ED61:60769:燰 +CJK UNIFIED IDEOGRAPH:'ED62:60770:燢 +CJK UNIFIED IDEOGRAPH:'ED63:60771:獳 +CJK UNIFIED IDEOGRAPH:'ED64:60772:獮 +CJK UNIFIED IDEOGRAPH:'ED65:60773:獯 +CJK UNIFIED IDEOGRAPH:'ED66:60774:璗 +CJK UNIFIED IDEOGRAPH:'ED67:60775:璲 +CJK UNIFIED IDEOGRAPH:'ED68:60776:璫 +CJK UNIFIED IDEOGRAPH:'ED69:60777:璐 +CJK UNIFIED IDEOGRAPH:'ED6A:60778:璪 +CJK UNIFIED IDEOGRAPH:'ED6B:60779:璭 +CJK UNIFIED IDEOGRAPH:'ED6C:60780:璱 +CJK UNIFIED IDEOGRAPH:'ED6D:60781:璥 +CJK UNIFIED IDEOGRAPH:'ED6E:60782:璯 +CJK UNIFIED IDEOGRAPH:'ED6F:60783:甐 +CJK UNIFIED IDEOGRAPH:'ED70:60784:甑 +CJK UNIFIED IDEOGRAPH:'ED71:60785:甒 +CJK UNIFIED IDEOGRAPH:'ED72:60786:甏 +CJK UNIFIED IDEOGRAPH:'ED73:60787:疄 +CJK UNIFIED IDEOGRAPH:'ED74:60788:癃 +CJK UNIFIED IDEOGRAPH:'ED75:60789:癈 +CJK UNIFIED IDEOGRAPH:'ED76:60790:癉 +CJK UNIFIED IDEOGRAPH:'ED77:60791:癇 +CJK UNIFIED IDEOGRAPH:'ED78:60792:皤 +CJK UNIFIED IDEOGRAPH:'ED79:60793:盩 +CJK UNIFIED IDEOGRAPH:'ED7A:60794:瞵 +CJK UNIFIED IDEOGRAPH:'ED7B:60795:瞫 +CJK UNIFIED IDEOGRAPH:'ED7C:60796:瞲 +CJK UNIFIED IDEOGRAPH:'ED7D:60797:瞷 +CJK UNIFIED IDEOGRAPH:'ED7E:60798:瞶 +CJK UNIFIED IDEOGRAPH:'EDA1:60833:瞴 +CJK UNIFIED IDEOGRAPH:'EDA2:60834:瞱 +CJK UNIFIED IDEOGRAPH:'EDA3:60835:瞨 +CJK UNIFIED IDEOGRAPH:'EDA4:60836:矰 +CJK UNIFIED IDEOGRAPH:'EDA5:60837:磳 +CJK UNIFIED IDEOGRAPH:'EDA6:60838:磽 +CJK UNIFIED IDEOGRAPH:'EDA7:60839:礂 +CJK UNIFIED IDEOGRAPH:'EDA8:60840:磻 +CJK UNIFIED IDEOGRAPH:'EDA9:60841:磼 +CJK UNIFIED IDEOGRAPH:'EDAA:60842:磲 +CJK UNIFIED IDEOGRAPH:'EDAB:60843:礅 +CJK UNIFIED IDEOGRAPH:'EDAC:60844:磹 +CJK UNIFIED IDEOGRAPH:'EDAD:60845:磾 +CJK UNIFIED IDEOGRAPH:'EDAE:60846:礄 +CJK UNIFIED IDEOGRAPH:'EDAF:60847:禫 +CJK UNIFIED IDEOGRAPH:'EDB0:60848:禨 +CJK UNIFIED IDEOGRAPH:'EDB1:60849:穜 +CJK UNIFIED IDEOGRAPH:'EDB2:60850:穛 +CJK UNIFIED IDEOGRAPH:'EDB3:60851:穖 +CJK UNIFIED IDEOGRAPH:'EDB4:60852:穘 +CJK UNIFIED IDEOGRAPH:'EDB5:60853:穔 +CJK UNIFIED IDEOGRAPH:'EDB6:60854:穚 +CJK UNIFIED IDEOGRAPH:'EDB7:60855:窾 +CJK UNIFIED IDEOGRAPH:'EDB8:60856:竀 +CJK UNIFIED IDEOGRAPH:'EDB9:60857:竁 +CJK UNIFIED IDEOGRAPH:'EDBA:60858:簅 +CJK UNIFIED IDEOGRAPH:'EDBB:60859:簏 +CJK UNIFIED IDEOGRAPH:'EDBC:60860:篲 +CJK UNIFIED IDEOGRAPH:'EDBD:60861:簀 +CJK UNIFIED IDEOGRAPH:'EDBE:60862:篿 +CJK UNIFIED IDEOGRAPH:'EDBF:60863:篻 +CJK UNIFIED IDEOGRAPH:'EDC0:60864:簎 +CJK UNIFIED IDEOGRAPH:'EDC1:60865:篴 +CJK UNIFIED IDEOGRAPH:'EDC2:60866:簋 +CJK UNIFIED IDEOGRAPH:'EDC3:60867:篳 +CJK UNIFIED IDEOGRAPH:'EDC4:60868:簂 +CJK UNIFIED IDEOGRAPH:'EDC5:60869:簉 +CJK UNIFIED IDEOGRAPH:'EDC6:60870:簃 +CJK UNIFIED IDEOGRAPH:'EDC7:60871:簁 +CJK UNIFIED IDEOGRAPH:'EDC8:60872:篸 +CJK UNIFIED IDEOGRAPH:'EDC9:60873:篽 +CJK UNIFIED IDEOGRAPH:'EDCA:60874:簆 +CJK UNIFIED IDEOGRAPH:'EDCB:60875:篰 +CJK UNIFIED IDEOGRAPH:'EDCC:60876:篱 +CJK UNIFIED IDEOGRAPH:'EDCD:60877:簐 +CJK UNIFIED IDEOGRAPH:'EDCE:60878:簊 +CJK UNIFIED IDEOGRAPH:'EDCF:60879:糨 +CJK UNIFIED IDEOGRAPH:'EDD0:60880:縭 +CJK UNIFIED IDEOGRAPH:'EDD1:60881:縼 +CJK UNIFIED IDEOGRAPH:'EDD2:60882:繂 +CJK UNIFIED IDEOGRAPH:'EDD3:60883:縳 +CJK UNIFIED IDEOGRAPH:'EDD4:60884:顈 +CJK UNIFIED IDEOGRAPH:'EDD5:60885:縸 +CJK UNIFIED IDEOGRAPH:'EDD6:60886:縪 +CJK UNIFIED IDEOGRAPH:'EDD7:60887:繉 +CJK UNIFIED IDEOGRAPH:'EDD8:60888:繀 +CJK UNIFIED IDEOGRAPH:'EDD9:60889:繇 +CJK UNIFIED IDEOGRAPH:'EDDA:60890:縩 +CJK UNIFIED IDEOGRAPH:'EDDB:60891:繌 +CJK UNIFIED IDEOGRAPH:'EDDC:60892:縰 +CJK UNIFIED IDEOGRAPH:'EDDD:60893:縻 +CJK UNIFIED IDEOGRAPH:'EDDE:60894:縶 +CJK UNIFIED IDEOGRAPH:'EDDF:60895:繄 +CJK UNIFIED IDEOGRAPH:'EDE0:60896:縺 +CJK UNIFIED IDEOGRAPH:'EDE1:60897:罅 +CJK UNIFIED IDEOGRAPH:'EDE2:60898:罿 +CJK UNIFIED IDEOGRAPH:'EDE3:60899:罾 +CJK UNIFIED IDEOGRAPH:'EDE4:60900:罽 +CJK UNIFIED IDEOGRAPH:'EDE5:60901:翴 +CJK UNIFIED IDEOGRAPH:'EDE6:60902:翲 +CJK UNIFIED IDEOGRAPH:'EDE7:60903:耬 +CJK UNIFIED IDEOGRAPH:'EDE8:60904:膻 +CJK UNIFIED IDEOGRAPH:'EDE9:60905:臄 +CJK UNIFIED IDEOGRAPH:'EDEA:60906:臌 +CJK UNIFIED IDEOGRAPH:'EDEB:60907:臊 +CJK UNIFIED IDEOGRAPH:'EDEC:60908:臅 +CJK UNIFIED IDEOGRAPH:'EDED:60909:臇 +CJK UNIFIED IDEOGRAPH:'EDEE:60910:膼 +CJK UNIFIED IDEOGRAPH:'EDEF:60911:臩 +CJK UNIFIED IDEOGRAPH:'EDF0:60912:艛 +CJK UNIFIED IDEOGRAPH:'EDF1:60913:艚 +CJK UNIFIED IDEOGRAPH:'EDF2:60914:艜 +CJK UNIFIED IDEOGRAPH:'EDF3:60915:薃 +CJK UNIFIED IDEOGRAPH:'EDF4:60916:薀 +CJK UNIFIED IDEOGRAPH:'EDF5:60917:薏 +CJK UNIFIED IDEOGRAPH:'EDF6:60918:薧 +CJK UNIFIED IDEOGRAPH:'EDF7:60919:薕 +CJK UNIFIED IDEOGRAPH:'EDF8:60920:薠 +CJK UNIFIED IDEOGRAPH:'EDF9:60921:薋 +CJK UNIFIED IDEOGRAPH:'EDFA:60922:薣 +CJK UNIFIED IDEOGRAPH:'EDFB:60923:蕻 +CJK UNIFIED IDEOGRAPH:'EDFC:60924:薤 +CJK UNIFIED IDEOGRAPH:'EDFD:60925:薚 +CJK UNIFIED IDEOGRAPH:'EDFE:60926:薞 +CJK UNIFIED IDEOGRAPH:'EE40:60992:蕷 +CJK UNIFIED IDEOGRAPH:'EE41:60993:蕼 +CJK UNIFIED IDEOGRAPH:'EE42:60994:薉 +CJK UNIFIED IDEOGRAPH:'EE43:60995:薡 +CJK UNIFIED IDEOGRAPH:'EE44:60996:蕺 +CJK UNIFIED IDEOGRAPH:'EE45:60997:蕸 +CJK UNIFIED IDEOGRAPH:'EE46:60998:蕗 +CJK UNIFIED IDEOGRAPH:'EE47:60999:薎 +CJK UNIFIED IDEOGRAPH:'EE48:61000:薖 +CJK UNIFIED IDEOGRAPH:'EE49:61001:薆 +CJK UNIFIED IDEOGRAPH:'EE4A:61002:薍 +CJK UNIFIED IDEOGRAPH:'EE4B:61003:薙 +CJK UNIFIED IDEOGRAPH:'EE4C:61004:薝 +CJK UNIFIED IDEOGRAPH:'EE4D:61005:薁 +CJK UNIFIED IDEOGRAPH:'EE4E:61006:薢 +CJK UNIFIED IDEOGRAPH:'EE4F:61007:薂 +CJK UNIFIED IDEOGRAPH:'EE50:61008:薈 +CJK UNIFIED IDEOGRAPH:'EE51:61009:薅 +CJK UNIFIED IDEOGRAPH:'EE52:61010:蕹 +CJK UNIFIED IDEOGRAPH:'EE53:61011:蕶 +CJK UNIFIED IDEOGRAPH:'EE54:61012:薘 +CJK UNIFIED IDEOGRAPH:'EE55:61013:薐 +CJK UNIFIED IDEOGRAPH:'EE56:61014:薟 +CJK UNIFIED IDEOGRAPH:'EE57:61015:虨 +CJK UNIFIED IDEOGRAPH:'EE58:61016:螾 +CJK UNIFIED IDEOGRAPH:'EE59:61017:螪 +CJK UNIFIED IDEOGRAPH:'EE5A:61018:螭 +CJK UNIFIED IDEOGRAPH:'EE5B:61019:蟅 +CJK UNIFIED IDEOGRAPH:'EE5C:61020:螰 +CJK UNIFIED IDEOGRAPH:'EE5D:61021:螬 +CJK UNIFIED IDEOGRAPH:'EE5E:61022:螹 +CJK UNIFIED IDEOGRAPH:'EE5F:61023:螵 +CJK UNIFIED IDEOGRAPH:'EE60:61024:螼 +CJK UNIFIED IDEOGRAPH:'EE61:61025:螮 +CJK UNIFIED IDEOGRAPH:'EE62:61026:蟉 +CJK UNIFIED IDEOGRAPH:'EE63:61027:蟃 +CJK UNIFIED IDEOGRAPH:'EE64:61028:蟂 +CJK UNIFIED IDEOGRAPH:'EE65:61029:蟌 +CJK UNIFIED IDEOGRAPH:'EE66:61030:螷 +CJK UNIFIED IDEOGRAPH:'EE67:61031:螯 +CJK UNIFIED IDEOGRAPH:'EE68:61032:蟄 +CJK UNIFIED IDEOGRAPH:'EE69:61033:蟊 +CJK UNIFIED IDEOGRAPH:'EE6A:61034:螴 +CJK UNIFIED IDEOGRAPH:'EE6B:61035:螶 +CJK UNIFIED IDEOGRAPH:'EE6C:61036:螿 +CJK UNIFIED IDEOGRAPH:'EE6D:61037:螸 +CJK UNIFIED IDEOGRAPH:'EE6E:61038:螽 +CJK UNIFIED IDEOGRAPH:'EE6F:61039:蟞 +CJK UNIFIED IDEOGRAPH:'EE70:61040:螲 +CJK UNIFIED IDEOGRAPH:'EE71:61041:褵 +CJK UNIFIED IDEOGRAPH:'EE72:61042:褳 +CJK UNIFIED IDEOGRAPH:'EE73:61043:褼 +CJK UNIFIED IDEOGRAPH:'EE74:61044:褾 +CJK UNIFIED IDEOGRAPH:'EE75:61045:襁 +CJK UNIFIED IDEOGRAPH:'EE76:61046:襒 +CJK UNIFIED IDEOGRAPH:'EE77:61047:褷 +CJK UNIFIED IDEOGRAPH:'EE78:61048:襂 +CJK UNIFIED IDEOGRAPH:'EE79:61049:覭 +CJK UNIFIED IDEOGRAPH:'EE7A:61050:覯 +CJK UNIFIED IDEOGRAPH:'EE7B:61051:覮 +CJK UNIFIED IDEOGRAPH:'EE7C:61052:觲 +CJK UNIFIED IDEOGRAPH:'EE7D:61053:觳 +CJK UNIFIED IDEOGRAPH:'EE7E:61054:謞 +CJK UNIFIED IDEOGRAPH:'EEA1:61089:謘 +CJK UNIFIED IDEOGRAPH:'EEA2:61090:謖 +CJK UNIFIED IDEOGRAPH:'EEA3:61091:謑 +CJK UNIFIED IDEOGRAPH:'EEA4:61092:謅 +CJK UNIFIED IDEOGRAPH:'EEA5:61093:謋 +CJK UNIFIED IDEOGRAPH:'EEA6:61094:謢 +CJK UNIFIED IDEOGRAPH:'EEA7:61095:謏 +CJK UNIFIED IDEOGRAPH:'EEA8:61096:謒 +CJK UNIFIED IDEOGRAPH:'EEA9:61097:謕 +CJK UNIFIED IDEOGRAPH:'EEAA:61098:謇 +CJK UNIFIED IDEOGRAPH:'EEAB:61099:謍 +CJK UNIFIED IDEOGRAPH:'EEAC:61100:謈 +CJK UNIFIED IDEOGRAPH:'EEAD:61101:謆 +CJK UNIFIED IDEOGRAPH:'EEAE:61102:謜 +CJK UNIFIED IDEOGRAPH:'EEAF:61103:謓 +CJK UNIFIED IDEOGRAPH:'EEB0:61104:謚 +CJK UNIFIED IDEOGRAPH:'EEB1:61105:豏 +CJK UNIFIED IDEOGRAPH:'EEB2:61106:豰 +CJK UNIFIED IDEOGRAPH:'EEB3:61107:豲 +CJK UNIFIED IDEOGRAPH:'EEB4:61108:豱 +CJK UNIFIED IDEOGRAPH:'EEB5:61109:豯 +CJK UNIFIED IDEOGRAPH:'EEB6:61110:貕 +CJK UNIFIED IDEOGRAPH:'EEB7:61111:貔 +CJK UNIFIED IDEOGRAPH:'EEB8:61112:賹 +CJK UNIFIED IDEOGRAPH:'EEB9:61113:赯 +CJK UNIFIED IDEOGRAPH:'EEBA:61114:蹎 +CJK UNIFIED IDEOGRAPH:'EEBB:61115:蹍 +CJK UNIFIED IDEOGRAPH:'EEBC:61116:蹓 +CJK UNIFIED IDEOGRAPH:'EEBD:61117:蹐 +CJK UNIFIED IDEOGRAPH:'EEBE:61118:蹌 +CJK UNIFIED IDEOGRAPH:'EEBF:61119:蹇 +CJK UNIFIED IDEOGRAPH:'EEC0:61120:轃 +CJK UNIFIED IDEOGRAPH:'EEC1:61121:轀 +CJK UNIFIED IDEOGRAPH:'EEC2:61122:邅 +CJK UNIFIED IDEOGRAPH:'EEC3:61123:遾 +CJK UNIFIED IDEOGRAPH:'EEC4:61124:鄸 +CJK UNIFIED IDEOGRAPH:'EEC5:61125:醚 +CJK UNIFIED IDEOGRAPH:'EEC6:61126:醢 +CJK UNIFIED IDEOGRAPH:'EEC7:61127:醛 +CJK UNIFIED IDEOGRAPH:'EEC8:61128:醙 +CJK UNIFIED IDEOGRAPH:'EEC9:61129:醟 +CJK UNIFIED IDEOGRAPH:'EECA:61130:醡 +CJK UNIFIED IDEOGRAPH:'EECB:61131:醝 +CJK UNIFIED IDEOGRAPH:'EECC:61132:醠 +CJK UNIFIED IDEOGRAPH:'EECD:61133:鎡 +CJK UNIFIED IDEOGRAPH:'EECE:61134:鎃 +CJK UNIFIED IDEOGRAPH:'EECF:61135:鎯 +CJK UNIFIED IDEOGRAPH:'EED0:61136:鍤 +CJK UNIFIED IDEOGRAPH:'EED1:61137:鍖 +CJK UNIFIED IDEOGRAPH:'EED2:61138:鍇 +CJK UNIFIED IDEOGRAPH:'EED3:61139:鍼 +CJK UNIFIED IDEOGRAPH:'EED4:61140:鍘 +CJK UNIFIED IDEOGRAPH:'EED5:61141:鍜 +CJK UNIFIED IDEOGRAPH:'EED6:61142:鍶 +CJK UNIFIED IDEOGRAPH:'EED7:61143:鍉 +CJK UNIFIED IDEOGRAPH:'EED8:61144:鍐 +CJK UNIFIED IDEOGRAPH:'EED9:61145:鍑 +CJK UNIFIED IDEOGRAPH:'EEDA:61146:鍠 +CJK UNIFIED IDEOGRAPH:'EEDB:61147:鍭 +CJK UNIFIED IDEOGRAPH:'EEDC:61148:鎏 +CJK UNIFIED IDEOGRAPH:'EEDD:61149:鍌 +CJK UNIFIED IDEOGRAPH:'EEDE:61150:鍪 +CJK UNIFIED IDEOGRAPH:'EEDF:61151:鍹 +CJK UNIFIED IDEOGRAPH:'EEE0:61152:鍗 +CJK UNIFIED IDEOGRAPH:'EEE1:61153:鍕 +CJK UNIFIED IDEOGRAPH:'EEE2:61154:鍒 +CJK UNIFIED IDEOGRAPH:'EEE3:61155:鍏 +CJK UNIFIED IDEOGRAPH:'EEE4:61156:鍱 +CJK UNIFIED IDEOGRAPH:'EEE5:61157:鍷 +CJK UNIFIED IDEOGRAPH:'EEE6:61158:鍻 +CJK UNIFIED IDEOGRAPH:'EEE7:61159:鍡 +CJK UNIFIED IDEOGRAPH:'EEE8:61160:鍞 +CJK UNIFIED IDEOGRAPH:'EEE9:61161:鍣 +CJK UNIFIED IDEOGRAPH:'EEEA:61162:鍧 +CJK UNIFIED IDEOGRAPH:'EEEB:61163:鎀 +CJK UNIFIED IDEOGRAPH:'EEEC:61164:鍎 +CJK UNIFIED IDEOGRAPH:'EEED:61165:鍙 +CJK UNIFIED IDEOGRAPH:'EEEE:61166:闇 +CJK UNIFIED IDEOGRAPH:'EEEF:61167:闀 +CJK UNIFIED IDEOGRAPH:'EEF0:61168:闉 +CJK UNIFIED IDEOGRAPH:'EEF1:61169:闃 +CJK UNIFIED IDEOGRAPH:'EEF2:61170:闅 +CJK UNIFIED IDEOGRAPH:'EEF3:61171:閷 +CJK UNIFIED IDEOGRAPH:'EEF4:61172:隮 +CJK UNIFIED IDEOGRAPH:'EEF5:61173:隰 +CJK UNIFIED IDEOGRAPH:'EEF6:61174:隬 +CJK UNIFIED IDEOGRAPH:'EEF7:61175:霠 +CJK UNIFIED IDEOGRAPH:'EEF8:61176:霟 +CJK UNIFIED IDEOGRAPH:'EEF9:61177:霘 +CJK UNIFIED IDEOGRAPH:'EEFA:61178:霝 +CJK UNIFIED IDEOGRAPH:'EEFB:61179:霙 +CJK UNIFIED IDEOGRAPH:'EEFC:61180:鞚 +CJK UNIFIED IDEOGRAPH:'EEFD:61181:鞡 +CJK UNIFIED IDEOGRAPH:'EEFE:61182:鞜 +CJK UNIFIED IDEOGRAPH:'EF40:61248:鞞 +CJK UNIFIED IDEOGRAPH:'EF41:61249:鞝 +CJK UNIFIED IDEOGRAPH:'EF42:61250:韕 +CJK UNIFIED IDEOGRAPH:'EF43:61251:韔 +CJK UNIFIED IDEOGRAPH:'EF44:61252:韱 +CJK UNIFIED IDEOGRAPH:'EF45:61253:顁 +CJK UNIFIED IDEOGRAPH:'EF46:61254:顄 +CJK UNIFIED IDEOGRAPH:'EF47:61255:顊 +CJK UNIFIED IDEOGRAPH:'EF48:61256:顉 +CJK UNIFIED IDEOGRAPH:'EF49:61257:顅 +CJK UNIFIED IDEOGRAPH:'EF4A:61258:顃 +CJK UNIFIED IDEOGRAPH:'EF4B:61259:餥 +CJK UNIFIED IDEOGRAPH:'EF4C:61260:餫 +CJK UNIFIED IDEOGRAPH:'EF4D:61261:餬 +CJK UNIFIED IDEOGRAPH:'EF4E:61262:餪 +CJK UNIFIED IDEOGRAPH:'EF4F:61263:餳 +CJK UNIFIED IDEOGRAPH:'EF50:61264:餲 +CJK UNIFIED IDEOGRAPH:'EF51:61265:餯 +CJK UNIFIED IDEOGRAPH:'EF52:61266:餭 +CJK UNIFIED IDEOGRAPH:'EF53:61267:餱 +CJK UNIFIED IDEOGRAPH:'EF54:61268:餰 +CJK UNIFIED IDEOGRAPH:'EF55:61269:馘 +CJK UNIFIED IDEOGRAPH:'EF56:61270:馣 +CJK UNIFIED IDEOGRAPH:'EF57:61271:馡 +CJK UNIFIED IDEOGRAPH:'EF58:61272:騂 +CJK UNIFIED IDEOGRAPH:'EF59:61273:駺 +CJK UNIFIED IDEOGRAPH:'EF5A:61274:駴 +CJK UNIFIED IDEOGRAPH:'EF5B:61275:駷 +CJK UNIFIED IDEOGRAPH:'EF5C:61276:駹 +CJK UNIFIED IDEOGRAPH:'EF5D:61277:駸 +CJK UNIFIED IDEOGRAPH:'EF5E:61278:駶 +CJK UNIFIED IDEOGRAPH:'EF5F:61279:駻 +CJK UNIFIED IDEOGRAPH:'EF60:61280:駽 +CJK UNIFIED IDEOGRAPH:'EF61:61281:駾 +CJK UNIFIED IDEOGRAPH:'EF62:61282:駼 +CJK UNIFIED IDEOGRAPH:'EF63:61283:騃 +CJK UNIFIED IDEOGRAPH:'EF64:61284:骾 +CJK UNIFIED IDEOGRAPH:'EF65:61285:髾 +CJK UNIFIED IDEOGRAPH:'EF66:61286:髽 +CJK UNIFIED IDEOGRAPH:'EF67:61287:鬁 +CJK UNIFIED IDEOGRAPH:'EF68:61288:髼 +CJK UNIFIED IDEOGRAPH:'EF69:61289:魈 +CJK UNIFIED IDEOGRAPH:'EF6A:61290:鮚 +CJK UNIFIED IDEOGRAPH:'EF6B:61291:鮨 +CJK UNIFIED IDEOGRAPH:'EF6C:61292:鮞 +CJK UNIFIED IDEOGRAPH:'EF6D:61293:鮛 +CJK UNIFIED IDEOGRAPH:'EF6E:61294:鮦 +CJK UNIFIED IDEOGRAPH:'EF6F:61295:鮡 +CJK UNIFIED IDEOGRAPH:'EF70:61296:鮥 +CJK UNIFIED IDEOGRAPH:'EF71:61297:鮤 +CJK UNIFIED IDEOGRAPH:'EF72:61298:鮆 +CJK UNIFIED IDEOGRAPH:'EF73:61299:鮢 +CJK UNIFIED IDEOGRAPH:'EF74:61300:鮠 +CJK UNIFIED IDEOGRAPH:'EF75:61301:鮯 +CJK UNIFIED IDEOGRAPH:'EF76:61302:鴳 +CJK UNIFIED IDEOGRAPH:'EF77:61303:鵁 +CJK UNIFIED IDEOGRAPH:'EF78:61304:鵧 +CJK UNIFIED IDEOGRAPH:'EF79:61305:鴶 +CJK UNIFIED IDEOGRAPH:'EF7A:61306:鴮 +CJK UNIFIED IDEOGRAPH:'EF7B:61307:鴯 +CJK UNIFIED IDEOGRAPH:'EF7C:61308:鴱 +CJK UNIFIED IDEOGRAPH:'EF7D:61309:鴸 +CJK UNIFIED IDEOGRAPH:'EF7E:61310:鴰 +CJK UNIFIED IDEOGRAPH:'EFA1:61345:鵅 +CJK UNIFIED IDEOGRAPH:'EFA2:61346:鵂 +CJK UNIFIED IDEOGRAPH:'EFA3:61347:鵃 +CJK UNIFIED IDEOGRAPH:'EFA4:61348:鴾 +CJK UNIFIED IDEOGRAPH:'EFA5:61349:鴷 +CJK UNIFIED IDEOGRAPH:'EFA6:61350:鵀 +CJK UNIFIED IDEOGRAPH:'EFA7:61351:鴽 +CJK UNIFIED IDEOGRAPH:'EFA8:61352:翵 +CJK UNIFIED IDEOGRAPH:'EFA9:61353:鴭 +CJK UNIFIED IDEOGRAPH:'EFAA:61354:麊 +CJK UNIFIED IDEOGRAPH:'EFAB:61355:麉 +CJK UNIFIED IDEOGRAPH:'EFAC:61356:麍 +CJK UNIFIED IDEOGRAPH:'EFAD:61357:麰 +CJK UNIFIED IDEOGRAPH:'EFAE:61358:黈 +CJK UNIFIED IDEOGRAPH:'EFAF:61359:黚 +CJK UNIFIED IDEOGRAPH:'EFB0:61360:黻 +CJK UNIFIED IDEOGRAPH:'EFB1:61361:黿 +CJK UNIFIED IDEOGRAPH:'EFB2:61362:鼤 +CJK UNIFIED IDEOGRAPH:'EFB3:61363:鼣 +CJK UNIFIED IDEOGRAPH:'EFB4:61364:鼢 +CJK UNIFIED IDEOGRAPH:'EFB5:61365:齔 +CJK UNIFIED IDEOGRAPH:'EFB6:61366:龠 +CJK UNIFIED IDEOGRAPH:'EFB7:61367:儱 +CJK UNIFIED IDEOGRAPH:'EFB8:61368:儭 +CJK UNIFIED IDEOGRAPH:'EFB9:61369:儮 +CJK UNIFIED IDEOGRAPH:'EFBA:61370:嚘 +CJK UNIFIED IDEOGRAPH:'EFBB:61371:嚜 +CJK UNIFIED IDEOGRAPH:'EFBC:61372:嚗 +CJK UNIFIED IDEOGRAPH:'EFBD:61373:嚚 +CJK UNIFIED IDEOGRAPH:'EFBE:61374:嚝 +CJK UNIFIED IDEOGRAPH:'EFBF:61375:嚙 +CJK UNIFIED IDEOGRAPH:'EFC0:61376:奰 +CJK UNIFIED IDEOGRAPH:'EFC1:61377:嬼 +CJK UNIFIED IDEOGRAPH:'EFC2:61378:屩 +CJK UNIFIED IDEOGRAPH:'EFC3:61379:屪 +CJK UNIFIED IDEOGRAPH:'EFC4:61380:巀 +CJK UNIFIED IDEOGRAPH:'EFC5:61381:幭 +CJK UNIFIED IDEOGRAPH:'EFC6:61382:幮 +CJK UNIFIED IDEOGRAPH:'EFC7:61383:懘 +CJK UNIFIED IDEOGRAPH:'EFC8:61384:懟 +CJK UNIFIED IDEOGRAPH:'EFC9:61385:懭 +CJK UNIFIED IDEOGRAPH:'EFCA:61386:懮 +CJK UNIFIED IDEOGRAPH:'EFCB:61387:懱 +CJK UNIFIED IDEOGRAPH:'EFCC:61388:懪 +CJK UNIFIED IDEOGRAPH:'EFCD:61389:懰 +CJK UNIFIED IDEOGRAPH:'EFCE:61390:懫 +CJK UNIFIED IDEOGRAPH:'EFCF:61391:懖 +CJK UNIFIED IDEOGRAPH:'EFD0:61392:懩 +CJK UNIFIED IDEOGRAPH:'EFD1:61393:擿 +CJK UNIFIED IDEOGRAPH:'EFD2:61394:攄 +CJK UNIFIED IDEOGRAPH:'EFD3:61395:擽 +CJK UNIFIED IDEOGRAPH:'EFD4:61396:擸 +CJK UNIFIED IDEOGRAPH:'EFD5:61397:攁 +CJK UNIFIED IDEOGRAPH:'EFD6:61398:攃 +CJK UNIFIED IDEOGRAPH:'EFD7:61399:擼 +CJK UNIFIED IDEOGRAPH:'EFD8:61400:斔 +CJK UNIFIED IDEOGRAPH:'EFD9:61401:旛 +CJK UNIFIED IDEOGRAPH:'EFDA:61402:曚 +CJK UNIFIED IDEOGRAPH:'EFDB:61403:曛 +CJK UNIFIED IDEOGRAPH:'EFDC:61404:曘 +CJK UNIFIED IDEOGRAPH:'EFDD:61405:櫅 +CJK UNIFIED IDEOGRAPH:'EFDE:61406:檹 +CJK UNIFIED IDEOGRAPH:'EFDF:61407:檽 +CJK UNIFIED IDEOGRAPH:'EFE0:61408:櫡 +CJK UNIFIED IDEOGRAPH:'EFE1:61409:櫆 +CJK UNIFIED IDEOGRAPH:'EFE2:61410:檺 +CJK UNIFIED IDEOGRAPH:'EFE3:61411:檶 +CJK UNIFIED IDEOGRAPH:'EFE4:61412:檷 +CJK UNIFIED IDEOGRAPH:'EFE5:61413:櫇 +CJK UNIFIED IDEOGRAPH:'EFE6:61414:檴 +CJK UNIFIED IDEOGRAPH:'EFE7:61415:檭 +CJK UNIFIED IDEOGRAPH:'EFE8:61416:歞 +CJK UNIFIED IDEOGRAPH:'EFE9:61417:毉 +CJK UNIFIED IDEOGRAPH:'EFEA:61418:氋 +CJK UNIFIED IDEOGRAPH:'EFEB:61419:瀇 +CJK UNIFIED IDEOGRAPH:'EFEC:61420:瀌 +CJK UNIFIED IDEOGRAPH:'EFED:61421:瀍 +CJK UNIFIED IDEOGRAPH:'EFEE:61422:瀁 +CJK UNIFIED IDEOGRAPH:'EFEF:61423:瀅 +CJK UNIFIED IDEOGRAPH:'EFF0:61424:瀔 +CJK UNIFIED IDEOGRAPH:'EFF1:61425:瀎 +CJK UNIFIED IDEOGRAPH:'EFF2:61426:濿 +CJK UNIFIED IDEOGRAPH:'EFF3:61427:瀀 +CJK UNIFIED IDEOGRAPH:'EFF4:61428:濻 +CJK UNIFIED IDEOGRAPH:'EFF5:61429:瀦 +CJK UNIFIED IDEOGRAPH:'EFF6:61430:濼 +CJK UNIFIED IDEOGRAPH:'EFF7:61431:濷 +CJK UNIFIED IDEOGRAPH:'EFF8:61432:瀊 +CJK UNIFIED IDEOGRAPH:'EFF9:61433:爁 +CJK UNIFIED IDEOGRAPH:'EFFA:61434:燿 +CJK UNIFIED IDEOGRAPH:'EFFB:61435:燹 +CJK UNIFIED IDEOGRAPH:'EFFC:61436:爃 +CJK UNIFIED IDEOGRAPH:'EFFD:61437:燽 +CJK UNIFIED IDEOGRAPH:'EFFE:61438:獶 +CJK UNIFIED IDEOGRAPH:'F040:61504:璸 +CJK UNIFIED IDEOGRAPH:'F041:61505:瓀 +CJK UNIFIED IDEOGRAPH:'F042:61506:璵 +CJK UNIFIED IDEOGRAPH:'F043:61507:瓁 +CJK UNIFIED IDEOGRAPH:'F044:61508:璾 +CJK UNIFIED IDEOGRAPH:'F045:61509:璶 +CJK UNIFIED IDEOGRAPH:'F046:61510:璻 +CJK UNIFIED IDEOGRAPH:'F047:61511:瓂 +CJK UNIFIED IDEOGRAPH:'F048:61512:甔 +CJK UNIFIED IDEOGRAPH:'F049:61513:甓 +CJK UNIFIED IDEOGRAPH:'F04A:61514:癜 +CJK UNIFIED IDEOGRAPH:'F04B:61515:癤 +CJK UNIFIED IDEOGRAPH:'F04C:61516:癙 +CJK UNIFIED IDEOGRAPH:'F04D:61517:癐 +CJK UNIFIED IDEOGRAPH:'F04E:61518:癓 +CJK UNIFIED IDEOGRAPH:'F04F:61519:癗 +CJK UNIFIED IDEOGRAPH:'F050:61520:癚 +CJK UNIFIED IDEOGRAPH:'F051:61521:皦 +CJK UNIFIED IDEOGRAPH:'F052:61522:皽 +CJK UNIFIED IDEOGRAPH:'F053:61523:盬 +CJK UNIFIED IDEOGRAPH:'F054:61524:矂 +CJK UNIFIED IDEOGRAPH:'F055:61525:瞺 +CJK UNIFIED IDEOGRAPH:'F056:61526:磿 +CJK UNIFIED IDEOGRAPH:'F057:61527:礌 +CJK UNIFIED IDEOGRAPH:'F058:61528:礓 +CJK UNIFIED IDEOGRAPH:'F059:61529:礔 +CJK UNIFIED IDEOGRAPH:'F05A:61530:礉 +CJK UNIFIED IDEOGRAPH:'F05B:61531:礐 +CJK UNIFIED IDEOGRAPH:'F05C:61532:礒 +CJK UNIFIED IDEOGRAPH:'F05D:61533:礑 +CJK UNIFIED IDEOGRAPH:'F05E:61534:禭 +CJK UNIFIED IDEOGRAPH:'F05F:61535:禬 +CJK UNIFIED IDEOGRAPH:'F060:61536:穟 +CJK UNIFIED IDEOGRAPH:'F061:61537:簜 +CJK UNIFIED IDEOGRAPH:'F062:61538:簩 +CJK UNIFIED IDEOGRAPH:'F063:61539:簙 +CJK UNIFIED IDEOGRAPH:'F064:61540:簠 +CJK UNIFIED IDEOGRAPH:'F065:61541:簟 +CJK UNIFIED IDEOGRAPH:'F066:61542:簭 +CJK UNIFIED IDEOGRAPH:'F067:61543:簝 +CJK UNIFIED IDEOGRAPH:'F068:61544:簦 +CJK UNIFIED IDEOGRAPH:'F069:61545:簨 +CJK UNIFIED IDEOGRAPH:'F06A:61546:簢 +CJK UNIFIED IDEOGRAPH:'F06B:61547:簥 +CJK UNIFIED IDEOGRAPH:'F06C:61548:簰 +CJK UNIFIED IDEOGRAPH:'F06D:61549:繜 +CJK UNIFIED IDEOGRAPH:'F06E:61550:繐 +CJK UNIFIED IDEOGRAPH:'F06F:61551:繖 +CJK UNIFIED IDEOGRAPH:'F070:61552:繣 +CJK UNIFIED IDEOGRAPH:'F071:61553:繘 +CJK UNIFIED IDEOGRAPH:'F072:61554:繢 +CJK UNIFIED IDEOGRAPH:'F073:61555:繟 +CJK UNIFIED IDEOGRAPH:'F074:61556:繑 +CJK UNIFIED IDEOGRAPH:'F075:61557:繠 +CJK UNIFIED IDEOGRAPH:'F076:61558:繗 +CJK UNIFIED IDEOGRAPH:'F077:61559:繓 +CJK UNIFIED IDEOGRAPH:'F078:61560:羵 +CJK UNIFIED IDEOGRAPH:'F079:61561:羳 +CJK UNIFIED IDEOGRAPH:'F07A:61562:翷 +CJK UNIFIED IDEOGRAPH:'F07B:61563:翸 +CJK UNIFIED IDEOGRAPH:'F07C:61564:聵 +CJK UNIFIED IDEOGRAPH:'F07D:61565:臑 +CJK UNIFIED IDEOGRAPH:'F07E:61566:臒 +CJK UNIFIED IDEOGRAPH:'F0A1:61601:臐 +CJK UNIFIED IDEOGRAPH:'F0A2:61602:艟 +CJK UNIFIED IDEOGRAPH:'F0A3:61603:艞 +CJK UNIFIED IDEOGRAPH:'F0A4:61604:薴 +CJK UNIFIED IDEOGRAPH:'F0A5:61605:藆 +CJK UNIFIED IDEOGRAPH:'F0A6:61606:藀 +CJK UNIFIED IDEOGRAPH:'F0A7:61607:藃 +CJK UNIFIED IDEOGRAPH:'F0A8:61608:藂 +CJK UNIFIED IDEOGRAPH:'F0A9:61609:薳 +CJK UNIFIED IDEOGRAPH:'F0AA:61610:薵 +CJK UNIFIED IDEOGRAPH:'F0AB:61611:薽 +CJK UNIFIED IDEOGRAPH:'F0AC:61612:藇 +CJK UNIFIED IDEOGRAPH:'F0AD:61613:藄 +CJK UNIFIED IDEOGRAPH:'F0AE:61614:薿 +CJK UNIFIED IDEOGRAPH:'F0AF:61615:藋 +CJK UNIFIED IDEOGRAPH:'F0B0:61616:藎 +CJK UNIFIED IDEOGRAPH:'F0B1:61617:藈 +CJK UNIFIED IDEOGRAPH:'F0B2:61618:藅 +CJK UNIFIED IDEOGRAPH:'F0B3:61619:薱 +CJK UNIFIED IDEOGRAPH:'F0B4:61620:薶 +CJK UNIFIED IDEOGRAPH:'F0B5:61621:藒 +CJK UNIFIED IDEOGRAPH:'F0B6:61622:蘤 +CJK UNIFIED IDEOGRAPH:'F0B7:61623:薸 +CJK UNIFIED IDEOGRAPH:'F0B8:61624:薷 +CJK UNIFIED IDEOGRAPH:'F0B9:61625:薾 +CJK UNIFIED IDEOGRAPH:'F0BA:61626:虩 +CJK UNIFIED IDEOGRAPH:'F0BB:61627:蟧 +CJK UNIFIED IDEOGRAPH:'F0BC:61628:蟦 +CJK UNIFIED IDEOGRAPH:'F0BD:61629:蟢 +CJK UNIFIED IDEOGRAPH:'F0BE:61630:蟛 +CJK UNIFIED IDEOGRAPH:'F0BF:61631:蟫 +CJK UNIFIED IDEOGRAPH:'F0C0:61632:蟪 +CJK UNIFIED IDEOGRAPH:'F0C1:61633:蟥 +CJK UNIFIED IDEOGRAPH:'F0C2:61634:蟟 +CJK UNIFIED IDEOGRAPH:'F0C3:61635:蟳 +CJK UNIFIED IDEOGRAPH:'F0C4:61636:蟤 +CJK UNIFIED IDEOGRAPH:'F0C5:61637:蟔 +CJK UNIFIED IDEOGRAPH:'F0C6:61638:蟜 +CJK UNIFIED IDEOGRAPH:'F0C7:61639:蟓 +CJK UNIFIED IDEOGRAPH:'F0C8:61640:蟭 +CJK UNIFIED IDEOGRAPH:'F0C9:61641:蟘 +CJK UNIFIED IDEOGRAPH:'F0CA:61642:蟣 +CJK UNIFIED IDEOGRAPH:'F0CB:61643:螤 +CJK UNIFIED IDEOGRAPH:'F0CC:61644:蟗 +CJK UNIFIED IDEOGRAPH:'F0CD:61645:蟙 +CJK UNIFIED IDEOGRAPH:'F0CE:61646:蠁 +CJK UNIFIED IDEOGRAPH:'F0CF:61647:蟴 +CJK UNIFIED IDEOGRAPH:'F0D0:61648:蟨 +CJK UNIFIED IDEOGRAPH:'F0D1:61649:蟝 +CJK UNIFIED IDEOGRAPH:'F0D2:61650:襓 +CJK UNIFIED IDEOGRAPH:'F0D3:61651:襋 +CJK UNIFIED IDEOGRAPH:'F0D4:61652:襏 +CJK UNIFIED IDEOGRAPH:'F0D5:61653:襌 +CJK UNIFIED IDEOGRAPH:'F0D6:61654:襆 +CJK UNIFIED IDEOGRAPH:'F0D7:61655:襐 +CJK UNIFIED IDEOGRAPH:'F0D8:61656:襑 +CJK UNIFIED IDEOGRAPH:'F0D9:61657:襉 +CJK UNIFIED IDEOGRAPH:'F0DA:61658:謪 +CJK UNIFIED IDEOGRAPH:'F0DB:61659:謧 +CJK UNIFIED IDEOGRAPH:'F0DC:61660:謣 +CJK UNIFIED IDEOGRAPH:'F0DD:61661:謳 +CJK UNIFIED IDEOGRAPH:'F0DE:61662:謰 +CJK UNIFIED IDEOGRAPH:'F0DF:61663:謵 +CJK UNIFIED IDEOGRAPH:'F0E0:61664:譇 +CJK UNIFIED IDEOGRAPH:'F0E1:61665:謯 +CJK UNIFIED IDEOGRAPH:'F0E2:61666:謼 +CJK UNIFIED IDEOGRAPH:'F0E3:61667:謾 +CJK UNIFIED IDEOGRAPH:'F0E4:61668:謱 +CJK UNIFIED IDEOGRAPH:'F0E5:61669:謥 +CJK UNIFIED IDEOGRAPH:'F0E6:61670:謷 +CJK UNIFIED IDEOGRAPH:'F0E7:61671:謦 +CJK UNIFIED IDEOGRAPH:'F0E8:61672:謶 +CJK UNIFIED IDEOGRAPH:'F0E9:61673:謮 +CJK UNIFIED IDEOGRAPH:'F0EA:61674:謤 +CJK UNIFIED IDEOGRAPH:'F0EB:61675:謻 +CJK UNIFIED IDEOGRAPH:'F0EC:61676:謽 +CJK UNIFIED IDEOGRAPH:'F0ED:61677:謺 +CJK UNIFIED IDEOGRAPH:'F0EE:61678:豂 +CJK UNIFIED IDEOGRAPH:'F0EF:61679:豵 +CJK UNIFIED IDEOGRAPH:'F0F0:61680:貙 +CJK UNIFIED IDEOGRAPH:'F0F1:61681:貘 +CJK UNIFIED IDEOGRAPH:'F0F2:61682:貗 +CJK UNIFIED IDEOGRAPH:'F0F3:61683:賾 +CJK UNIFIED IDEOGRAPH:'F0F4:61684:贄 +CJK UNIFIED IDEOGRAPH:'F0F5:61685:贂 +CJK UNIFIED IDEOGRAPH:'F0F6:61686:贀 +CJK UNIFIED IDEOGRAPH:'F0F7:61687:蹜 +CJK UNIFIED IDEOGRAPH:'F0F8:61688:蹢 +CJK UNIFIED IDEOGRAPH:'F0F9:61689:蹠 +CJK UNIFIED IDEOGRAPH:'F0FA:61690:蹗 +CJK UNIFIED IDEOGRAPH:'F0FB:61691:蹖 +CJK UNIFIED IDEOGRAPH:'F0FC:61692:蹞 +CJK UNIFIED IDEOGRAPH:'F0FD:61693:蹥 +CJK UNIFIED IDEOGRAPH:'F0FE:61694:蹧 +CJK UNIFIED IDEOGRAPH:'F140:61760:蹛 +CJK UNIFIED IDEOGRAPH:'F141:61761:蹚 +CJK UNIFIED IDEOGRAPH:'F142:61762:蹡 +CJK UNIFIED IDEOGRAPH:'F143:61763:蹝 +CJK UNIFIED IDEOGRAPH:'F144:61764:蹩 +CJK UNIFIED IDEOGRAPH:'F145:61765:蹔 +CJK UNIFIED IDEOGRAPH:'F146:61766:轆 +CJK UNIFIED IDEOGRAPH:'F147:61767:轇 +CJK UNIFIED IDEOGRAPH:'F148:61768:轈 +CJK UNIFIED IDEOGRAPH:'F149:61769:轋 +CJK UNIFIED IDEOGRAPH:'F14A:61770:鄨 +CJK UNIFIED IDEOGRAPH:'F14B:61771:鄺 +CJK UNIFIED IDEOGRAPH:'F14C:61772:鄻 +CJK UNIFIED IDEOGRAPH:'F14D:61773:鄾 +CJK UNIFIED IDEOGRAPH:'F14E:61774:醨 +CJK UNIFIED IDEOGRAPH:'F14F:61775:醥 +CJK UNIFIED IDEOGRAPH:'F150:61776:醧 +CJK UNIFIED IDEOGRAPH:'F151:61777:醯 +CJK UNIFIED IDEOGRAPH:'F152:61778:醪 +CJK UNIFIED IDEOGRAPH:'F153:61779:鎵 +CJK UNIFIED IDEOGRAPH:'F154:61780:鎌 +CJK UNIFIED IDEOGRAPH:'F155:61781:鎒 +CJK UNIFIED IDEOGRAPH:'F156:61782:鎷 +CJK UNIFIED IDEOGRAPH:'F157:61783:鎛 +CJK UNIFIED IDEOGRAPH:'F158:61784:鎝 +CJK UNIFIED IDEOGRAPH:'F159:61785:鎉 +CJK UNIFIED IDEOGRAPH:'F15A:61786:鎧 +CJK UNIFIED IDEOGRAPH:'F15B:61787:鎎 +CJK UNIFIED IDEOGRAPH:'F15C:61788:鎪 +CJK UNIFIED IDEOGRAPH:'F15D:61789:鎞 +CJK UNIFIED IDEOGRAPH:'F15E:61790:鎦 +CJK UNIFIED IDEOGRAPH:'F15F:61791:鎕 +CJK UNIFIED IDEOGRAPH:'F160:61792:鎈 +CJK UNIFIED IDEOGRAPH:'F161:61793:鎙 +CJK UNIFIED IDEOGRAPH:'F162:61794:鎟 +CJK UNIFIED IDEOGRAPH:'F163:61795:鎍 +CJK UNIFIED IDEOGRAPH:'F164:61796:鎱 +CJK UNIFIED IDEOGRAPH:'F165:61797:鎑 +CJK UNIFIED IDEOGRAPH:'F166:61798:鎲 +CJK UNIFIED IDEOGRAPH:'F167:61799:鎤 +CJK UNIFIED IDEOGRAPH:'F168:61800:鎨 +CJK UNIFIED IDEOGRAPH:'F169:61801:鎴 +CJK UNIFIED IDEOGRAPH:'F16A:61802:鎣 +CJK UNIFIED IDEOGRAPH:'F16B:61803:鎥 +CJK UNIFIED IDEOGRAPH:'F16C:61804:闒 +CJK UNIFIED IDEOGRAPH:'F16D:61805:闓 +CJK UNIFIED IDEOGRAPH:'F16E:61806:闑 +CJK UNIFIED IDEOGRAPH:'F16F:61807:隳 +CJK UNIFIED IDEOGRAPH:'F170:61808:雗 +CJK UNIFIED IDEOGRAPH:'F171:61809:雚 +CJK UNIFIED IDEOGRAPH:'F172:61810:巂 +CJK UNIFIED IDEOGRAPH:'F173:61811:雟 +CJK UNIFIED IDEOGRAPH:'F174:61812:雘 +CJK UNIFIED IDEOGRAPH:'F175:61813:雝 +CJK UNIFIED IDEOGRAPH:'F176:61814:霣 +CJK UNIFIED IDEOGRAPH:'F177:61815:霢 +CJK UNIFIED IDEOGRAPH:'F178:61816:霥 +CJK UNIFIED IDEOGRAPH:'F179:61817:鞬 +CJK UNIFIED IDEOGRAPH:'F17A:61818:鞮 +CJK UNIFIED IDEOGRAPH:'F17B:61819:鞨 +CJK UNIFIED IDEOGRAPH:'F17C:61820:鞫 +CJK UNIFIED IDEOGRAPH:'F17D:61821:鞤 +CJK UNIFIED IDEOGRAPH:'F17E:61822:鞪 +CJK UNIFIED IDEOGRAPH:'F1A1:61857:鞢 +CJK UNIFIED IDEOGRAPH:'F1A2:61858:鞥 +CJK UNIFIED IDEOGRAPH:'F1A3:61859:韗 +CJK UNIFIED IDEOGRAPH:'F1A4:61860:韙 +CJK UNIFIED IDEOGRAPH:'F1A5:61861:韖 +CJK UNIFIED IDEOGRAPH:'F1A6:61862:韘 +CJK UNIFIED IDEOGRAPH:'F1A7:61863:韺 +CJK UNIFIED IDEOGRAPH:'F1A8:61864:顐 +CJK UNIFIED IDEOGRAPH:'F1A9:61865:顑 +CJK UNIFIED IDEOGRAPH:'F1AA:61866:顒 +CJK UNIFIED IDEOGRAPH:'F1AB:61867:颸 +CJK UNIFIED IDEOGRAPH:'F1AC:61868:饁 +CJK UNIFIED IDEOGRAPH:'F1AD:61869:餼 +CJK UNIFIED IDEOGRAPH:'F1AE:61870:餺 +CJK UNIFIED IDEOGRAPH:'F1AF:61871:騏 +CJK UNIFIED IDEOGRAPH:'F1B0:61872:騋 +CJK UNIFIED IDEOGRAPH:'F1B1:61873:騉 +CJK UNIFIED IDEOGRAPH:'F1B2:61874:騍 +CJK UNIFIED IDEOGRAPH:'F1B3:61875:騄 +CJK UNIFIED IDEOGRAPH:'F1B4:61876:騑 +CJK UNIFIED IDEOGRAPH:'F1B5:61877:騊 +CJK UNIFIED IDEOGRAPH:'F1B6:61878:騅 +CJK UNIFIED IDEOGRAPH:'F1B7:61879:騇 +CJK UNIFIED IDEOGRAPH:'F1B8:61880:騆 +CJK UNIFIED IDEOGRAPH:'F1B9:61881:髀 +CJK UNIFIED IDEOGRAPH:'F1BA:61882:髜 +CJK UNIFIED IDEOGRAPH:'F1BB:61883:鬈 +CJK UNIFIED IDEOGRAPH:'F1BC:61884:鬄 +CJK UNIFIED IDEOGRAPH:'F1BD:61885:鬅 +CJK UNIFIED IDEOGRAPH:'F1BE:61886:鬩 +CJK UNIFIED IDEOGRAPH:'F1BF:61887:鬵 +CJK UNIFIED IDEOGRAPH:'F1C0:61888:魊 +CJK UNIFIED IDEOGRAPH:'F1C1:61889:魌 +CJK UNIFIED IDEOGRAPH:'F1C2:61890:魋 +CJK UNIFIED IDEOGRAPH:'F1C3:61891:鯇 +CJK UNIFIED IDEOGRAPH:'F1C4:61892:鯆 +CJK UNIFIED IDEOGRAPH:'F1C5:61893:鯃 +CJK UNIFIED IDEOGRAPH:'F1C6:61894:鮿 +CJK UNIFIED IDEOGRAPH:'F1C7:61895:鯁 +CJK UNIFIED IDEOGRAPH:'F1C8:61896:鮵 +CJK UNIFIED IDEOGRAPH:'F1C9:61897:鮸 +CJK UNIFIED IDEOGRAPH:'F1CA:61898:鯓 +CJK UNIFIED IDEOGRAPH:'F1CB:61899:鮶 +CJK UNIFIED IDEOGRAPH:'F1CC:61900:鯄 +CJK UNIFIED IDEOGRAPH:'F1CD:61901:鮹 +CJK UNIFIED IDEOGRAPH:'F1CE:61902:鮽 +CJK UNIFIED IDEOGRAPH:'F1CF:61903:鵜 +CJK UNIFIED IDEOGRAPH:'F1D0:61904:鵓 +CJK UNIFIED IDEOGRAPH:'F1D1:61905:鵏 +CJK UNIFIED IDEOGRAPH:'F1D2:61906:鵊 +CJK UNIFIED IDEOGRAPH:'F1D3:61907:鵛 +CJK UNIFIED IDEOGRAPH:'F1D4:61908:鵋 +CJK UNIFIED IDEOGRAPH:'F1D5:61909:鵙 +CJK UNIFIED IDEOGRAPH:'F1D6:61910:鵖 +CJK UNIFIED IDEOGRAPH:'F1D7:61911:鵌 +CJK UNIFIED IDEOGRAPH:'F1D8:61912:鵗 +CJK UNIFIED IDEOGRAPH:'F1D9:61913:鵒 +CJK UNIFIED IDEOGRAPH:'F1DA:61914:鵔 +CJK UNIFIED IDEOGRAPH:'F1DB:61915:鵟 +CJK UNIFIED IDEOGRAPH:'F1DC:61916:鵘 +CJK UNIFIED IDEOGRAPH:'F1DD:61917:鵚 +CJK UNIFIED IDEOGRAPH:'F1DE:61918:麎 +CJK UNIFIED IDEOGRAPH:'F1DF:61919:麌 +CJK UNIFIED IDEOGRAPH:'F1E0:61920:黟 +CJK UNIFIED IDEOGRAPH:'F1E1:61921:鼁 +CJK UNIFIED IDEOGRAPH:'F1E2:61922:鼀 +CJK UNIFIED IDEOGRAPH:'F1E3:61923:鼖 +CJK UNIFIED IDEOGRAPH:'F1E4:61924:鼥 +CJK UNIFIED IDEOGRAPH:'F1E5:61925:鼫 +CJK UNIFIED IDEOGRAPH:'F1E6:61926:鼪 +CJK UNIFIED IDEOGRAPH:'F1E7:61927:鼩 +CJK UNIFIED IDEOGRAPH:'F1E8:61928:鼨 +CJK UNIFIED IDEOGRAPH:'F1E9:61929:齌 +CJK UNIFIED IDEOGRAPH:'F1EA:61930:齕 +CJK UNIFIED IDEOGRAPH:'F1EB:61931:儴 +CJK UNIFIED IDEOGRAPH:'F1EC:61932:儵 +CJK UNIFIED IDEOGRAPH:'F1ED:61933:劖 +CJK UNIFIED IDEOGRAPH:'F1EE:61934:勷 +CJK UNIFIED IDEOGRAPH:'F1EF:61935:厴 +CJK UNIFIED IDEOGRAPH:'F1F0:61936:嚫 +CJK UNIFIED IDEOGRAPH:'F1F1:61937:嚭 +CJK UNIFIED IDEOGRAPH:'F1F2:61938:嚦 +CJK UNIFIED IDEOGRAPH:'F1F3:61939:嚧 +CJK UNIFIED IDEOGRAPH:'F1F4:61940:嚪 +CJK UNIFIED IDEOGRAPH:'F1F5:61941:嚬 +CJK UNIFIED IDEOGRAPH:'F1F6:61942:壚 +CJK UNIFIED IDEOGRAPH:'F1F7:61943:壝 +CJK UNIFIED IDEOGRAPH:'F1F8:61944:壛 +CJK UNIFIED IDEOGRAPH:'F1F9:61945:夒 +CJK UNIFIED IDEOGRAPH:'F1FA:61946:嬽 +CJK UNIFIED IDEOGRAPH:'F1FB:61947:嬾 +CJK UNIFIED IDEOGRAPH:'F1FC:61948:嬿 +CJK UNIFIED IDEOGRAPH:'F1FD:61949:巃 +CJK UNIFIED IDEOGRAPH:'F1FE:61950:幰 +CJK UNIFIED IDEOGRAPH:'F240:62016:徿 +CJK UNIFIED IDEOGRAPH:'F241:62017:懻 +CJK UNIFIED IDEOGRAPH:'F242:62018:攇 +CJK UNIFIED IDEOGRAPH:'F243:62019:攐 +CJK UNIFIED IDEOGRAPH:'F244:62020:攍 +CJK UNIFIED IDEOGRAPH:'F245:62021:攉 +CJK UNIFIED IDEOGRAPH:'F246:62022:攌 +CJK UNIFIED IDEOGRAPH:'F247:62023:攎 +CJK UNIFIED IDEOGRAPH:'F248:62024:斄 +CJK UNIFIED IDEOGRAPH:'F249:62025:旞 +CJK UNIFIED IDEOGRAPH:'F24A:62026:旝 +CJK UNIFIED IDEOGRAPH:'F24B:62027:曞 +CJK UNIFIED IDEOGRAPH:'F24C:62028:櫧 +CJK UNIFIED IDEOGRAPH:'F24D:62029:櫠 +CJK UNIFIED IDEOGRAPH:'F24E:62030:櫌 +CJK UNIFIED IDEOGRAPH:'F24F:62031:櫑 +CJK UNIFIED IDEOGRAPH:'F250:62032:櫙 +CJK UNIFIED IDEOGRAPH:'F251:62033:櫋 +CJK UNIFIED IDEOGRAPH:'F252:62034:櫟 +CJK UNIFIED IDEOGRAPH:'F253:62035:櫜 +CJK UNIFIED IDEOGRAPH:'F254:62036:櫐 +CJK UNIFIED IDEOGRAPH:'F255:62037:櫫 +CJK UNIFIED IDEOGRAPH:'F256:62038:櫏 +CJK UNIFIED IDEOGRAPH:'F257:62039:櫍 +CJK UNIFIED IDEOGRAPH:'F258:62040:櫞 +CJK UNIFIED IDEOGRAPH:'F259:62041:歠 +CJK UNIFIED IDEOGRAPH:'F25A:62042:殰 +CJK UNIFIED IDEOGRAPH:'F25B:62043:氌 +CJK UNIFIED IDEOGRAPH:'F25C:62044:瀙 +CJK UNIFIED IDEOGRAPH:'F25D:62045:瀧 +CJK UNIFIED IDEOGRAPH:'F25E:62046:瀠 +CJK UNIFIED IDEOGRAPH:'F25F:62047:瀖 +CJK UNIFIED IDEOGRAPH:'F260:62048:瀫 +CJK UNIFIED IDEOGRAPH:'F261:62049:瀡 +CJK UNIFIED IDEOGRAPH:'F262:62050:瀢 +CJK UNIFIED IDEOGRAPH:'F263:62051:瀣 +CJK UNIFIED IDEOGRAPH:'F264:62052:瀩 +CJK UNIFIED IDEOGRAPH:'F265:62053:瀗 +CJK UNIFIED IDEOGRAPH:'F266:62054:瀤 +CJK UNIFIED IDEOGRAPH:'F267:62055:瀜 +CJK UNIFIED IDEOGRAPH:'F268:62056:瀪 +CJK UNIFIED IDEOGRAPH:'F269:62057:爌 +CJK UNIFIED IDEOGRAPH:'F26A:62058:爊 +CJK UNIFIED IDEOGRAPH:'F26B:62059:爇 +CJK UNIFIED IDEOGRAPH:'F26C:62060:爂 +CJK UNIFIED IDEOGRAPH:'F26D:62061:爅 +CJK UNIFIED IDEOGRAPH:'F26E:62062:犥 +CJK UNIFIED IDEOGRAPH:'F26F:62063:犦 +CJK UNIFIED IDEOGRAPH:'F270:62064:犤 +CJK UNIFIED IDEOGRAPH:'F271:62065:犣 +CJK UNIFIED IDEOGRAPH:'F272:62066:犡 +CJK UNIFIED IDEOGRAPH:'F273:62067:瓋 +CJK UNIFIED IDEOGRAPH:'F274:62068:瓅 +CJK UNIFIED IDEOGRAPH:'F275:62069:璷 +CJK UNIFIED IDEOGRAPH:'F276:62070:瓃 +CJK UNIFIED IDEOGRAPH:'F277:62071:甖 +CJK UNIFIED IDEOGRAPH:'F278:62072:癠 +CJK UNIFIED IDEOGRAPH:'F279:62073:矉 +CJK UNIFIED IDEOGRAPH:'F27A:62074:矊 +CJK UNIFIED IDEOGRAPH:'F27B:62075:矄 +CJK UNIFIED IDEOGRAPH:'F27C:62076:矱 +CJK UNIFIED IDEOGRAPH:'F27D:62077:礝 +CJK UNIFIED IDEOGRAPH:'F27E:62078:礛 +CJK UNIFIED IDEOGRAPH:'F2A1:62113:礡 +CJK UNIFIED IDEOGRAPH:'F2A2:62114:礜 +CJK UNIFIED IDEOGRAPH:'F2A3:62115:礗 +CJK UNIFIED IDEOGRAPH:'F2A4:62116:礞 +CJK UNIFIED IDEOGRAPH:'F2A5:62117:禰 +CJK UNIFIED IDEOGRAPH:'F2A6:62118:穧 +CJK UNIFIED IDEOGRAPH:'F2A7:62119:穨 +CJK UNIFIED IDEOGRAPH:'F2A8:62120:簳 +CJK UNIFIED IDEOGRAPH:'F2A9:62121:簼 +CJK UNIFIED IDEOGRAPH:'F2AA:62122:簹 +CJK UNIFIED IDEOGRAPH:'F2AB:62123:簬 +CJK UNIFIED IDEOGRAPH:'F2AC:62124:簻 +CJK UNIFIED IDEOGRAPH:'F2AD:62125:糬 +CJK UNIFIED IDEOGRAPH:'F2AE:62126:糪 +CJK UNIFIED IDEOGRAPH:'F2AF:62127:繶 +CJK UNIFIED IDEOGRAPH:'F2B0:62128:繵 +CJK UNIFIED IDEOGRAPH:'F2B1:62129:繸 +CJK UNIFIED IDEOGRAPH:'F2B2:62130:繰 +CJK UNIFIED IDEOGRAPH:'F2B3:62131:繷 +CJK UNIFIED IDEOGRAPH:'F2B4:62132:繯 +CJK UNIFIED IDEOGRAPH:'F2B5:62133:繺 +CJK UNIFIED IDEOGRAPH:'F2B6:62134:繲 +CJK UNIFIED IDEOGRAPH:'F2B7:62135:繴 +CJK UNIFIED IDEOGRAPH:'F2B8:62136:繨 +CJK UNIFIED IDEOGRAPH:'F2B9:62137:罋 +CJK UNIFIED IDEOGRAPH:'F2BA:62138:罊 +CJK UNIFIED IDEOGRAPH:'F2BB:62139:羃 +CJK UNIFIED IDEOGRAPH:'F2BC:62140:羆 +CJK UNIFIED IDEOGRAPH:'F2BD:62141:羷 +CJK UNIFIED IDEOGRAPH:'F2BE:62142:翽 +CJK UNIFIED IDEOGRAPH:'F2BF:62143:翾 +CJK UNIFIED IDEOGRAPH:'F2C0:62144:聸 +CJK UNIFIED IDEOGRAPH:'F2C1:62145:臗 +CJK UNIFIED IDEOGRAPH:'F2C2:62146:臕 +CJK UNIFIED IDEOGRAPH:'F2C3:62147:艤 +CJK UNIFIED IDEOGRAPH:'F2C4:62148:艡 +CJK UNIFIED IDEOGRAPH:'F2C5:62149:艣 +CJK UNIFIED IDEOGRAPH:'F2C6:62150:藫 +CJK UNIFIED IDEOGRAPH:'F2C7:62151:藱 +CJK UNIFIED IDEOGRAPH:'F2C8:62152:藭 +CJK UNIFIED IDEOGRAPH:'F2C9:62153:藙 +CJK UNIFIED IDEOGRAPH:'F2CA:62154:藡 +CJK UNIFIED IDEOGRAPH:'F2CB:62155:藨 +CJK UNIFIED IDEOGRAPH:'F2CC:62156:藚 +CJK UNIFIED IDEOGRAPH:'F2CD:62157:藗 +CJK UNIFIED IDEOGRAPH:'F2CE:62158:藬 +CJK UNIFIED IDEOGRAPH:'F2CF:62159:藲 +CJK UNIFIED IDEOGRAPH:'F2D0:62160:藸 +CJK UNIFIED IDEOGRAPH:'F2D1:62161:藘 +CJK UNIFIED IDEOGRAPH:'F2D2:62162:藟 +CJK UNIFIED IDEOGRAPH:'F2D3:62163:藣 +CJK UNIFIED IDEOGRAPH:'F2D4:62164:藜 +CJK UNIFIED IDEOGRAPH:'F2D5:62165:藑 +CJK UNIFIED IDEOGRAPH:'F2D6:62166:藰 +CJK UNIFIED IDEOGRAPH:'F2D7:62167:藦 +CJK UNIFIED IDEOGRAPH:'F2D8:62168:藯 +CJK UNIFIED IDEOGRAPH:'F2D9:62169:藞 +CJK UNIFIED IDEOGRAPH:'F2DA:62170:藢 +CJK UNIFIED IDEOGRAPH:'F2DB:62171:蠀 +CJK UNIFIED IDEOGRAPH:'F2DC:62172:蟺 +CJK UNIFIED IDEOGRAPH:'F2DD:62173:蠃 +CJK UNIFIED IDEOGRAPH:'F2DE:62174:蟶 +CJK UNIFIED IDEOGRAPH:'F2DF:62175:蟷 +CJK UNIFIED IDEOGRAPH:'F2E0:62176:蠉 +CJK UNIFIED IDEOGRAPH:'F2E1:62177:蠌 +CJK UNIFIED IDEOGRAPH:'F2E2:62178:蠋 +CJK UNIFIED IDEOGRAPH:'F2E3:62179:蠆 +CJK UNIFIED IDEOGRAPH:'F2E4:62180:蟼 +CJK UNIFIED IDEOGRAPH:'F2E5:62181:蠈 +CJK UNIFIED IDEOGRAPH:'F2E6:62182:蟿 +CJK UNIFIED IDEOGRAPH:'F2E7:62183:蠊 +CJK UNIFIED IDEOGRAPH:'F2E8:62184:蠂 +CJK UNIFIED IDEOGRAPH:'F2E9:62185:襢 +CJK UNIFIED IDEOGRAPH:'F2EA:62186:襚 +CJK UNIFIED IDEOGRAPH:'F2EB:62187:襛 +CJK UNIFIED IDEOGRAPH:'F2EC:62188:襗 +CJK UNIFIED IDEOGRAPH:'F2ED:62189:襡 +CJK UNIFIED IDEOGRAPH:'F2EE:62190:襜 +CJK UNIFIED IDEOGRAPH:'F2EF:62191:襘 +CJK UNIFIED IDEOGRAPH:'F2F0:62192:襝 +CJK UNIFIED IDEOGRAPH:'F2F1:62193:襙 +CJK UNIFIED IDEOGRAPH:'F2F2:62194:覈 +CJK UNIFIED IDEOGRAPH:'F2F3:62195:覷 +CJK UNIFIED IDEOGRAPH:'F2F4:62196:覶 +CJK UNIFIED IDEOGRAPH:'F2F5:62197:觶 +CJK UNIFIED IDEOGRAPH:'F2F6:62198:譐 +CJK UNIFIED IDEOGRAPH:'F2F7:62199:譈 +CJK UNIFIED IDEOGRAPH:'F2F8:62200:譊 +CJK UNIFIED IDEOGRAPH:'F2F9:62201:譀 +CJK UNIFIED IDEOGRAPH:'F2FA:62202:譓 +CJK UNIFIED IDEOGRAPH:'F2FB:62203:譖 +CJK UNIFIED IDEOGRAPH:'F2FC:62204:譔 +CJK UNIFIED IDEOGRAPH:'F2FD:62205:譋 +CJK UNIFIED IDEOGRAPH:'F2FE:62206:譕 +CJK UNIFIED IDEOGRAPH:'F340:62272:譑 +CJK UNIFIED IDEOGRAPH:'F341:62273:譂 +CJK UNIFIED IDEOGRAPH:'F342:62274:譒 +CJK UNIFIED IDEOGRAPH:'F343:62275:譗 +CJK UNIFIED IDEOGRAPH:'F344:62276:豃 +CJK UNIFIED IDEOGRAPH:'F345:62277:豷 +CJK UNIFIED IDEOGRAPH:'F346:62278:豶 +CJK UNIFIED IDEOGRAPH:'F347:62279:貚 +CJK UNIFIED IDEOGRAPH:'F348:62280:贆 +CJK UNIFIED IDEOGRAPH:'F349:62281:贇 +CJK UNIFIED IDEOGRAPH:'F34A:62282:贉 +CJK UNIFIED IDEOGRAPH:'F34B:62283:趬 +CJK UNIFIED IDEOGRAPH:'F34C:62284:趪 +CJK UNIFIED IDEOGRAPH:'F34D:62285:趭 +CJK UNIFIED IDEOGRAPH:'F34E:62286:趫 +CJK UNIFIED IDEOGRAPH:'F34F:62287:蹭 +CJK UNIFIED IDEOGRAPH:'F350:62288:蹸 +CJK UNIFIED IDEOGRAPH:'F351:62289:蹳 +CJK UNIFIED IDEOGRAPH:'F352:62290:蹪 +CJK UNIFIED IDEOGRAPH:'F353:62291:蹯 +CJK UNIFIED IDEOGRAPH:'F354:62292:蹻 +CJK UNIFIED IDEOGRAPH:'F355:62293:軂 +CJK UNIFIED IDEOGRAPH:'F356:62294:轒 +CJK UNIFIED IDEOGRAPH:'F357:62295:轑 +CJK UNIFIED IDEOGRAPH:'F358:62296:轏 +CJK UNIFIED IDEOGRAPH:'F359:62297:轐 +CJK UNIFIED IDEOGRAPH:'F35A:62298:轓 +CJK UNIFIED IDEOGRAPH:'F35B:62299:辴 +CJK UNIFIED IDEOGRAPH:'F35C:62300:酀 +CJK UNIFIED IDEOGRAPH:'F35D:62301:鄿 +CJK UNIFIED IDEOGRAPH:'F35E:62302:醰 +CJK UNIFIED IDEOGRAPH:'F35F:62303:醭 +CJK UNIFIED IDEOGRAPH:'F360:62304:鏞 +CJK UNIFIED IDEOGRAPH:'F361:62305:鏇 +CJK UNIFIED IDEOGRAPH:'F362:62306:鏏 +CJK UNIFIED IDEOGRAPH:'F363:62307:鏂 +CJK UNIFIED IDEOGRAPH:'F364:62308:鏚 +CJK UNIFIED IDEOGRAPH:'F365:62309:鏐 +CJK UNIFIED IDEOGRAPH:'F366:62310:鏹 +CJK UNIFIED IDEOGRAPH:'F367:62311:鏬 +CJK UNIFIED IDEOGRAPH:'F368:62312:鏌 +CJK UNIFIED IDEOGRAPH:'F369:62313:鏙 +CJK UNIFIED IDEOGRAPH:'F36A:62314:鎩 +CJK UNIFIED IDEOGRAPH:'F36B:62315:鏦 +CJK UNIFIED IDEOGRAPH:'F36C:62316:鏊 +CJK UNIFIED IDEOGRAPH:'F36D:62317:鏔 +CJK UNIFIED IDEOGRAPH:'F36E:62318:鏮 +CJK UNIFIED IDEOGRAPH:'F36F:62319:鏣 +CJK UNIFIED IDEOGRAPH:'F370:62320:鏕 +CJK UNIFIED IDEOGRAPH:'F371:62321:鏄 +CJK UNIFIED IDEOGRAPH:'F372:62322:鏎 +CJK UNIFIED IDEOGRAPH:'F373:62323:鏀 +CJK UNIFIED IDEOGRAPH:'F374:62324:鏒 +CJK UNIFIED IDEOGRAPH:'F375:62325:鏧 +CJK UNIFIED IDEOGRAPH:'F376:62326:镽 +CJK UNIFIED IDEOGRAPH:'F377:62327:闚 +CJK UNIFIED IDEOGRAPH:'F378:62328:闛 +CJK UNIFIED IDEOGRAPH:'F379:62329:雡 +CJK UNIFIED IDEOGRAPH:'F37A:62330:霩 +CJK UNIFIED IDEOGRAPH:'F37B:62331:霫 +CJK UNIFIED IDEOGRAPH:'F37C:62332:霬 +CJK UNIFIED IDEOGRAPH:'F37D:62333:霨 +CJK UNIFIED IDEOGRAPH:'F37E:62334:霦 +CJK UNIFIED IDEOGRAPH:'F3A1:62369:鞳 +CJK UNIFIED IDEOGRAPH:'F3A2:62370:鞷 +CJK UNIFIED IDEOGRAPH:'F3A3:62371:鞶 +CJK UNIFIED IDEOGRAPH:'F3A4:62372:韝 +CJK UNIFIED IDEOGRAPH:'F3A5:62373:韞 +CJK UNIFIED IDEOGRAPH:'F3A6:62374:韟 +CJK UNIFIED IDEOGRAPH:'F3A7:62375:顜 +CJK UNIFIED IDEOGRAPH:'F3A8:62376:顙 +CJK UNIFIED IDEOGRAPH:'F3A9:62377:顝 +CJK UNIFIED IDEOGRAPH:'F3AA:62378:顗 +CJK UNIFIED IDEOGRAPH:'F3AB:62379:颿 +CJK UNIFIED IDEOGRAPH:'F3AC:62380:颽 +CJK UNIFIED IDEOGRAPH:'F3AD:62381:颻 +CJK UNIFIED IDEOGRAPH:'F3AE:62382:颾 +CJK UNIFIED IDEOGRAPH:'F3AF:62383:饈 +CJK UNIFIED IDEOGRAPH:'F3B0:62384:饇 +CJK UNIFIED IDEOGRAPH:'F3B1:62385:饃 +CJK UNIFIED IDEOGRAPH:'F3B2:62386:馦 +CJK UNIFIED IDEOGRAPH:'F3B3:62387:馧 +CJK UNIFIED IDEOGRAPH:'F3B4:62388:騚 +CJK UNIFIED IDEOGRAPH:'F3B5:62389:騕 +CJK UNIFIED IDEOGRAPH:'F3B6:62390:騥 +CJK UNIFIED IDEOGRAPH:'F3B7:62391:騝 +CJK UNIFIED IDEOGRAPH:'F3B8:62392:騤 +CJK UNIFIED IDEOGRAPH:'F3B9:62393:騛 +CJK UNIFIED IDEOGRAPH:'F3BA:62394:騢 +CJK UNIFIED IDEOGRAPH:'F3BB:62395:騠 +CJK UNIFIED IDEOGRAPH:'F3BC:62396:騧 +CJK UNIFIED IDEOGRAPH:'F3BD:62397:騣 +CJK UNIFIED IDEOGRAPH:'F3BE:62398:騞 +CJK UNIFIED IDEOGRAPH:'F3BF:62399:騜 +CJK UNIFIED IDEOGRAPH:'F3C0:62400:騔 +CJK UNIFIED IDEOGRAPH:'F3C1:62401:髂 +CJK UNIFIED IDEOGRAPH:'F3C2:62402:鬋 +CJK UNIFIED IDEOGRAPH:'F3C3:62403:鬊 +CJK UNIFIED IDEOGRAPH:'F3C4:62404:鬎 +CJK UNIFIED IDEOGRAPH:'F3C5:62405:鬌 +CJK UNIFIED IDEOGRAPH:'F3C6:62406:鬷 +CJK UNIFIED IDEOGRAPH:'F3C7:62407:鯪 +CJK UNIFIED IDEOGRAPH:'F3C8:62408:鯫 +CJK UNIFIED IDEOGRAPH:'F3C9:62409:鯠 +CJK UNIFIED IDEOGRAPH:'F3CA:62410:鯞 +CJK UNIFIED IDEOGRAPH:'F3CB:62411:鯤 +CJK UNIFIED IDEOGRAPH:'F3CC:62412:鯦 +CJK UNIFIED IDEOGRAPH:'F3CD:62413:鯢 +CJK UNIFIED IDEOGRAPH:'F3CE:62414:鯰 +CJK UNIFIED IDEOGRAPH:'F3CF:62415:鯔 +CJK UNIFIED IDEOGRAPH:'F3D0:62416:鯗 +CJK UNIFIED IDEOGRAPH:'F3D1:62417:鯬 +CJK UNIFIED IDEOGRAPH:'F3D2:62418:鯜 +CJK UNIFIED IDEOGRAPH:'F3D3:62419:鯙 +CJK UNIFIED IDEOGRAPH:'F3D4:62420:鯥 +CJK UNIFIED IDEOGRAPH:'F3D5:62421:鯕 +CJK UNIFIED IDEOGRAPH:'F3D6:62422:鯡 +CJK UNIFIED IDEOGRAPH:'F3D7:62423:鯚 +CJK UNIFIED IDEOGRAPH:'F3D8:62424:鵷 +CJK UNIFIED IDEOGRAPH:'F3D9:62425:鶁 +CJK UNIFIED IDEOGRAPH:'F3DA:62426:鶊 +CJK UNIFIED IDEOGRAPH:'F3DB:62427:鶄 +CJK UNIFIED IDEOGRAPH:'F3DC:62428:鶈 +CJK UNIFIED IDEOGRAPH:'F3DD:62429:鵱 +CJK UNIFIED IDEOGRAPH:'F3DE:62430:鶀 +CJK UNIFIED IDEOGRAPH:'F3DF:62431:鵸 +CJK UNIFIED IDEOGRAPH:'F3E0:62432:鶆 +CJK UNIFIED IDEOGRAPH:'F3E1:62433:鶋 +CJK UNIFIED IDEOGRAPH:'F3E2:62434:鶌 +CJK UNIFIED IDEOGRAPH:'F3E3:62435:鵽 +CJK UNIFIED IDEOGRAPH:'F3E4:62436:鵫 +CJK UNIFIED IDEOGRAPH:'F3E5:62437:鵴 +CJK UNIFIED IDEOGRAPH:'F3E6:62438:鵵 +CJK UNIFIED IDEOGRAPH:'F3E7:62439:鵰 +CJK UNIFIED IDEOGRAPH:'F3E8:62440:鵩 +CJK UNIFIED IDEOGRAPH:'F3E9:62441:鶅 +CJK UNIFIED IDEOGRAPH:'F3EA:62442:鵳 +CJK UNIFIED IDEOGRAPH:'F3EB:62443:鵻 +CJK UNIFIED IDEOGRAPH:'F3EC:62444:鶂 +CJK UNIFIED IDEOGRAPH:'F3ED:62445:鵯 +CJK UNIFIED IDEOGRAPH:'F3EE:62446:鵹 +CJK UNIFIED IDEOGRAPH:'F3EF:62447:鵿 +CJK UNIFIED IDEOGRAPH:'F3F0:62448:鶇 +CJK UNIFIED IDEOGRAPH:'F3F1:62449:鵨 +CJK UNIFIED IDEOGRAPH:'F3F2:62450:麔 +CJK UNIFIED IDEOGRAPH:'F3F3:62451:麑 +CJK UNIFIED IDEOGRAPH:'F3F4:62452:黀 +CJK UNIFIED IDEOGRAPH:'F3F5:62453:黼 +CJK UNIFIED IDEOGRAPH:'F3F6:62454:鼭 +CJK UNIFIED IDEOGRAPH:'F3F7:62455:齀 +CJK UNIFIED IDEOGRAPH:'F3F8:62456:齁 +CJK UNIFIED IDEOGRAPH:'F3F9:62457:齍 +CJK UNIFIED IDEOGRAPH:'F3FA:62458:齖 +CJK UNIFIED IDEOGRAPH:'F3FB:62459:齗 +CJK UNIFIED IDEOGRAPH:'F3FC:62460:齘 +CJK UNIFIED IDEOGRAPH:'F3FD:62461:匷 +CJK UNIFIED IDEOGRAPH:'F3FE:62462:嚲 +CJK UNIFIED IDEOGRAPH:'F440:62528:嚵 +CJK UNIFIED IDEOGRAPH:'F441:62529:嚳 +CJK UNIFIED IDEOGRAPH:'F442:62530:壣 +CJK UNIFIED IDEOGRAPH:'F443:62531:孅 +CJK UNIFIED IDEOGRAPH:'F444:62532:巆 +CJK UNIFIED IDEOGRAPH:'F445:62533:巇 +CJK UNIFIED IDEOGRAPH:'F446:62534:廮 +CJK UNIFIED IDEOGRAPH:'F447:62535:廯 +CJK UNIFIED IDEOGRAPH:'F448:62536:忀 +CJK UNIFIED IDEOGRAPH:'F449:62537:忁 +CJK UNIFIED IDEOGRAPH:'F44A:62538:懹 +CJK UNIFIED IDEOGRAPH:'F44B:62539:攗 +CJK UNIFIED IDEOGRAPH:'F44C:62540:攖 +CJK UNIFIED IDEOGRAPH:'F44D:62541:攕 +CJK UNIFIED IDEOGRAPH:'F44E:62542:攓 +CJK UNIFIED IDEOGRAPH:'F44F:62543:旟 +CJK UNIFIED IDEOGRAPH:'F450:62544:曨 +CJK UNIFIED IDEOGRAPH:'F451:62545:曣 +CJK UNIFIED IDEOGRAPH:'F452:62546:曤 +CJK UNIFIED IDEOGRAPH:'F453:62547:櫳 +CJK UNIFIED IDEOGRAPH:'F454:62548:櫰 +CJK UNIFIED IDEOGRAPH:'F455:62549:櫪 +CJK UNIFIED IDEOGRAPH:'F456:62550:櫨 +CJK UNIFIED IDEOGRAPH:'F457:62551:櫹 +CJK UNIFIED IDEOGRAPH:'F458:62552:櫱 +CJK UNIFIED IDEOGRAPH:'F459:62553:櫮 +CJK UNIFIED IDEOGRAPH:'F45A:62554:櫯 +CJK UNIFIED IDEOGRAPH:'F45B:62555:瀼 +CJK UNIFIED IDEOGRAPH:'F45C:62556:瀵 +CJK UNIFIED IDEOGRAPH:'F45D:62557:瀯 +CJK UNIFIED IDEOGRAPH:'F45E:62558:瀷 +CJK UNIFIED IDEOGRAPH:'F45F:62559:瀴 +CJK UNIFIED IDEOGRAPH:'F460:62560:瀱 +CJK UNIFIED IDEOGRAPH:'F461:62561:灂 +CJK UNIFIED IDEOGRAPH:'F462:62562:瀸 +CJK UNIFIED IDEOGRAPH:'F463:62563:瀿 +CJK UNIFIED IDEOGRAPH:'F464:62564:瀺 +CJK UNIFIED IDEOGRAPH:'F465:62565:瀹 +CJK UNIFIED IDEOGRAPH:'F466:62566:灀 +CJK UNIFIED IDEOGRAPH:'F467:62567:瀻 +CJK UNIFIED IDEOGRAPH:'F468:62568:瀳 +CJK UNIFIED IDEOGRAPH:'F469:62569:灁 +CJK UNIFIED IDEOGRAPH:'F46A:62570:爓 +CJK UNIFIED IDEOGRAPH:'F46B:62571:爔 +CJK UNIFIED IDEOGRAPH:'F46C:62572:犨 +CJK UNIFIED IDEOGRAPH:'F46D:62573:獽 +CJK UNIFIED IDEOGRAPH:'F46E:62574:獼 +CJK UNIFIED IDEOGRAPH:'F46F:62575:璺 +CJK UNIFIED IDEOGRAPH:'F470:62576:皫 +CJK UNIFIED IDEOGRAPH:'F471:62577:皪 +CJK UNIFIED IDEOGRAPH:'F472:62578:皾 +CJK UNIFIED IDEOGRAPH:'F473:62579:盭 +CJK UNIFIED IDEOGRAPH:'F474:62580:矌 +CJK UNIFIED IDEOGRAPH:'F475:62581:矎 +CJK UNIFIED IDEOGRAPH:'F476:62582:矏 +CJK UNIFIED IDEOGRAPH:'F477:62583:矍 +CJK UNIFIED IDEOGRAPH:'F478:62584:矲 +CJK UNIFIED IDEOGRAPH:'F479:62585:礥 +CJK UNIFIED IDEOGRAPH:'F47A:62586:礣 +CJK UNIFIED IDEOGRAPH:'F47B:62587:礧 +CJK UNIFIED IDEOGRAPH:'F47C:62588:礨 +CJK UNIFIED IDEOGRAPH:'F47D:62589:礤 +CJK UNIFIED IDEOGRAPH:'F47E:62590:礩 +CJK UNIFIED IDEOGRAPH:'F4A1:62625:禲 +CJK UNIFIED IDEOGRAPH:'F4A2:62626:穮 +CJK UNIFIED IDEOGRAPH:'F4A3:62627:穬 +CJK UNIFIED IDEOGRAPH:'F4A4:62628:穭 +CJK UNIFIED IDEOGRAPH:'F4A5:62629:竷 +CJK UNIFIED IDEOGRAPH:'F4A6:62630:籉 +CJK UNIFIED IDEOGRAPH:'F4A7:62631:籈 +CJK UNIFIED IDEOGRAPH:'F4A8:62632:籊 +CJK UNIFIED IDEOGRAPH:'F4A9:62633:籇 +CJK UNIFIED IDEOGRAPH:'F4AA:62634:籅 +CJK UNIFIED IDEOGRAPH:'F4AB:62635:糮 +CJK UNIFIED IDEOGRAPH:'F4AC:62636:繻 +CJK UNIFIED IDEOGRAPH:'F4AD:62637:繾 +CJK UNIFIED IDEOGRAPH:'F4AE:62638:纁 +CJK UNIFIED IDEOGRAPH:'F4AF:62639:纀 +CJK UNIFIED IDEOGRAPH:'F4B0:62640:羺 +CJK UNIFIED IDEOGRAPH:'F4B1:62641:翿 +CJK UNIFIED IDEOGRAPH:'F4B2:62642:聹 +CJK UNIFIED IDEOGRAPH:'F4B3:62643:臛 +CJK UNIFIED IDEOGRAPH:'F4B4:62644:臙 +CJK UNIFIED IDEOGRAPH:'F4B5:62645:舋 +CJK UNIFIED IDEOGRAPH:'F4B6:62646:艨 +CJK UNIFIED IDEOGRAPH:'F4B7:62647:艩 +CJK UNIFIED IDEOGRAPH:'F4B8:62648:蘢 +CJK UNIFIED IDEOGRAPH:'F4B9:62649:藿 +CJK UNIFIED IDEOGRAPH:'F4BA:62650:蘁 +CJK UNIFIED IDEOGRAPH:'F4BB:62651:藾 +CJK UNIFIED IDEOGRAPH:'F4BC:62652:蘛 +CJK UNIFIED IDEOGRAPH:'F4BD:62653:蘀 +CJK UNIFIED IDEOGRAPH:'F4BE:62654:藶 +CJK UNIFIED IDEOGRAPH:'F4BF:62655:蘄 +CJK UNIFIED IDEOGRAPH:'F4C0:62656:蘉 +CJK UNIFIED IDEOGRAPH:'F4C1:62657:蘅 +CJK UNIFIED IDEOGRAPH:'F4C2:62658:蘌 +CJK UNIFIED IDEOGRAPH:'F4C3:62659:藽 +CJK UNIFIED IDEOGRAPH:'F4C4:62660:蠙 +CJK UNIFIED IDEOGRAPH:'F4C5:62661:蠐 +CJK UNIFIED IDEOGRAPH:'F4C6:62662:蠑 +CJK UNIFIED IDEOGRAPH:'F4C7:62663:蠗 +CJK UNIFIED IDEOGRAPH:'F4C8:62664:蠓 +CJK UNIFIED IDEOGRAPH:'F4C9:62665:蠖 +CJK UNIFIED IDEOGRAPH:'F4CA:62666:襣 +CJK UNIFIED IDEOGRAPH:'F4CB:62667:襦 +CJK UNIFIED IDEOGRAPH:'F4CC:62668:覹 +CJK UNIFIED IDEOGRAPH:'F4CD:62669:觷 +CJK UNIFIED IDEOGRAPH:'F4CE:62670:譠 +CJK UNIFIED IDEOGRAPH:'F4CF:62671:譪 +CJK UNIFIED IDEOGRAPH:'F4D0:62672:譝 +CJK UNIFIED IDEOGRAPH:'F4D1:62673:譨 +CJK UNIFIED IDEOGRAPH:'F4D2:62674:譣 +CJK UNIFIED IDEOGRAPH:'F4D3:62675:譥 +CJK UNIFIED IDEOGRAPH:'F4D4:62676:譧 +CJK UNIFIED IDEOGRAPH:'F4D5:62677:譭 +CJK UNIFIED IDEOGRAPH:'F4D6:62678:趮 +CJK UNIFIED IDEOGRAPH:'F4D7:62679:躆 +CJK UNIFIED IDEOGRAPH:'F4D8:62680:躈 +CJK UNIFIED IDEOGRAPH:'F4D9:62681:躄 +CJK UNIFIED IDEOGRAPH:'F4DA:62682:轙 +CJK UNIFIED IDEOGRAPH:'F4DB:62683:轖 +CJK UNIFIED IDEOGRAPH:'F4DC:62684:轗 +CJK UNIFIED IDEOGRAPH:'F4DD:62685:轕 +CJK UNIFIED IDEOGRAPH:'F4DE:62686:轘 +CJK UNIFIED IDEOGRAPH:'F4DF:62687:轚 +CJK UNIFIED IDEOGRAPH:'F4E0:62688:邍 +CJK UNIFIED IDEOGRAPH:'F4E1:62689:酃 +CJK UNIFIED IDEOGRAPH:'F4E2:62690:酁 +CJK UNIFIED IDEOGRAPH:'F4E3:62691:醷 +CJK UNIFIED IDEOGRAPH:'F4E4:62692:醵 +CJK UNIFIED IDEOGRAPH:'F4E5:62693:醲 +CJK UNIFIED IDEOGRAPH:'F4E6:62694:醳 +CJK UNIFIED IDEOGRAPH:'F4E7:62695:鐋 +CJK UNIFIED IDEOGRAPH:'F4E8:62696:鐓 +CJK UNIFIED IDEOGRAPH:'F4E9:62697:鏻 +CJK UNIFIED IDEOGRAPH:'F4EA:62698:鐠 +CJK UNIFIED IDEOGRAPH:'F4EB:62699:鐏 +CJK UNIFIED IDEOGRAPH:'F4EC:62700:鐔 +CJK UNIFIED IDEOGRAPH:'F4ED:62701:鏾 +CJK UNIFIED IDEOGRAPH:'F4EE:62702:鐕 +CJK UNIFIED IDEOGRAPH:'F4EF:62703:鐐 +CJK UNIFIED IDEOGRAPH:'F4F0:62704:鐨 +CJK UNIFIED IDEOGRAPH:'F4F1:62705:鐙 +CJK UNIFIED IDEOGRAPH:'F4F2:62706:鐍 +CJK UNIFIED IDEOGRAPH:'F4F3:62707:鏵 +CJK UNIFIED IDEOGRAPH:'F4F4:62708:鐀 +CJK UNIFIED IDEOGRAPH:'F4F5:62709:鏷 +CJK UNIFIED IDEOGRAPH:'F4F6:62710:鐇 +CJK UNIFIED IDEOGRAPH:'F4F7:62711:鐎 +CJK UNIFIED IDEOGRAPH:'F4F8:62712:鐖 +CJK UNIFIED IDEOGRAPH:'F4F9:62713:鐒 +CJK UNIFIED IDEOGRAPH:'F4FA:62714:鏺 +CJK UNIFIED IDEOGRAPH:'F4FB:62715:鐉 +CJK UNIFIED IDEOGRAPH:'F4FC:62716:鏸 +CJK UNIFIED IDEOGRAPH:'F4FD:62717:鐊 +CJK UNIFIED IDEOGRAPH:'F4FE:62718:鏿 +CJK UNIFIED IDEOGRAPH:'F540:62784:鏼 +CJK UNIFIED IDEOGRAPH:'F541:62785:鐌 +CJK UNIFIED IDEOGRAPH:'F542:62786:鏶 +CJK UNIFIED IDEOGRAPH:'F543:62787:鐑 +CJK UNIFIED IDEOGRAPH:'F544:62788:鐆 +CJK UNIFIED IDEOGRAPH:'F545:62789:闞 +CJK UNIFIED IDEOGRAPH:'F546:62790:闠 +CJK UNIFIED IDEOGRAPH:'F547:62791:闟 +CJK UNIFIED IDEOGRAPH:'F548:62792:霮 +CJK UNIFIED IDEOGRAPH:'F549:62793:霯 +CJK UNIFIED IDEOGRAPH:'F54A:62794:鞹 +CJK UNIFIED IDEOGRAPH:'F54B:62795:鞻 +CJK UNIFIED IDEOGRAPH:'F54C:62796:韽 +CJK UNIFIED IDEOGRAPH:'F54D:62797:韾 +CJK UNIFIED IDEOGRAPH:'F54E:62798:顠 +CJK UNIFIED IDEOGRAPH:'F54F:62799:顢 +CJK UNIFIED IDEOGRAPH:'F550:62800:顣 +CJK UNIFIED IDEOGRAPH:'F551:62801:顟 +CJK UNIFIED IDEOGRAPH:'F552:62802:飁 +CJK UNIFIED IDEOGRAPH:'F553:62803:飂 +CJK UNIFIED IDEOGRAPH:'F554:62804:饐 +CJK UNIFIED IDEOGRAPH:'F555:62805:饎 +CJK UNIFIED IDEOGRAPH:'F556:62806:饙 +CJK UNIFIED IDEOGRAPH:'F557:62807:饌 +CJK UNIFIED IDEOGRAPH:'F558:62808:饋 +CJK UNIFIED IDEOGRAPH:'F559:62809:饓 +CJK UNIFIED IDEOGRAPH:'F55A:62810:騲 +CJK UNIFIED IDEOGRAPH:'F55B:62811:騴 +CJK UNIFIED IDEOGRAPH:'F55C:62812:騱 +CJK UNIFIED IDEOGRAPH:'F55D:62813:騬 +CJK UNIFIED IDEOGRAPH:'F55E:62814:騪 +CJK UNIFIED IDEOGRAPH:'F55F:62815:騶 +CJK UNIFIED IDEOGRAPH:'F560:62816:騩 +CJK UNIFIED IDEOGRAPH:'F561:62817:騮 +CJK UNIFIED IDEOGRAPH:'F562:62818:騸 +CJK UNIFIED IDEOGRAPH:'F563:62819:騭 +CJK UNIFIED IDEOGRAPH:'F564:62820:髇 +CJK UNIFIED IDEOGRAPH:'F565:62821:髊 +CJK UNIFIED IDEOGRAPH:'F566:62822:髆 +CJK UNIFIED IDEOGRAPH:'F567:62823:鬐 +CJK UNIFIED IDEOGRAPH:'F568:62824:鬒 +CJK UNIFIED IDEOGRAPH:'F569:62825:鬑 +CJK UNIFIED IDEOGRAPH:'F56A:62826:鰋 +CJK UNIFIED IDEOGRAPH:'F56B:62827:鰈 +CJK UNIFIED IDEOGRAPH:'F56C:62828:鯷 +CJK UNIFIED IDEOGRAPH:'F56D:62829:鰅 +CJK UNIFIED IDEOGRAPH:'F56E:62830:鰒 +CJK UNIFIED IDEOGRAPH:'F56F:62831:鯸 +CJK UNIFIED IDEOGRAPH:'F570:62832:鱀 +CJK UNIFIED IDEOGRAPH:'F571:62833:鰇 +CJK UNIFIED IDEOGRAPH:'F572:62834:鰎 +CJK UNIFIED IDEOGRAPH:'F573:62835:鰆 +CJK UNIFIED IDEOGRAPH:'F574:62836:鰗 +CJK UNIFIED IDEOGRAPH:'F575:62837:鰔 +CJK UNIFIED IDEOGRAPH:'F576:62838:鰉 +CJK UNIFIED IDEOGRAPH:'F577:62839:鶟 +CJK UNIFIED IDEOGRAPH:'F578:62840:鶙 +CJK UNIFIED IDEOGRAPH:'F579:62841:鶤 +CJK UNIFIED IDEOGRAPH:'F57A:62842:鶝 +CJK UNIFIED IDEOGRAPH:'F57B:62843:鶒 +CJK UNIFIED IDEOGRAPH:'F57C:62844:鶘 +CJK UNIFIED IDEOGRAPH:'F57D:62845:鶐 +CJK UNIFIED IDEOGRAPH:'F57E:62846:鶛 +CJK UNIFIED IDEOGRAPH:'F5A1:62881:鶠 +CJK UNIFIED IDEOGRAPH:'F5A2:62882:鶔 +CJK UNIFIED IDEOGRAPH:'F5A3:62883:鶜 +CJK UNIFIED IDEOGRAPH:'F5A4:62884:鶪 +CJK UNIFIED IDEOGRAPH:'F5A5:62885:鶗 +CJK UNIFIED IDEOGRAPH:'F5A6:62886:鶡 +CJK UNIFIED IDEOGRAPH:'F5A7:62887:鶚 +CJK UNIFIED IDEOGRAPH:'F5A8:62888:鶢 +CJK UNIFIED IDEOGRAPH:'F5A9:62889:鶨 +CJK UNIFIED IDEOGRAPH:'F5AA:62890:鶞 +CJK UNIFIED IDEOGRAPH:'F5AB:62891:鶣 +CJK UNIFIED IDEOGRAPH:'F5AC:62892:鶿 +CJK UNIFIED IDEOGRAPH:'F5AD:62893:鶩 +CJK UNIFIED IDEOGRAPH:'F5AE:62894:鶖 +CJK UNIFIED IDEOGRAPH:'F5AF:62895:鶦 +CJK UNIFIED IDEOGRAPH:'F5B0:62896:鶧 +CJK UNIFIED IDEOGRAPH:'F5B1:62897:麙 +CJK UNIFIED IDEOGRAPH:'F5B2:62898:麛 +CJK UNIFIED IDEOGRAPH:'F5B3:62899:麚 +CJK UNIFIED IDEOGRAPH:'F5B4:62900:黥 +CJK UNIFIED IDEOGRAPH:'F5B5:62901:黤 +CJK UNIFIED IDEOGRAPH:'F5B6:62902:黧 +CJK UNIFIED IDEOGRAPH:'F5B7:62903:黦 +CJK UNIFIED IDEOGRAPH:'F5B8:62904:鼰 +CJK UNIFIED IDEOGRAPH:'F5B9:62905:鼮 +CJK UNIFIED IDEOGRAPH:'F5BA:62906:齛 +CJK UNIFIED IDEOGRAPH:'F5BB:62907:齠 +CJK UNIFIED IDEOGRAPH:'F5BC:62908:齞 +CJK UNIFIED IDEOGRAPH:'F5BD:62909:齝 +CJK UNIFIED IDEOGRAPH:'F5BE:62910:齙 +CJK UNIFIED IDEOGRAPH:'F5BF:62911:龑 +CJK UNIFIED IDEOGRAPH:'F5C0:62912:儺 +CJK UNIFIED IDEOGRAPH:'F5C1:62913:儹 +CJK UNIFIED IDEOGRAPH:'F5C2:62914:劘 +CJK UNIFIED IDEOGRAPH:'F5C3:62915:劗 +CJK UNIFIED IDEOGRAPH:'F5C4:62916:囃 +CJK UNIFIED IDEOGRAPH:'F5C5:62917:嚽 +CJK UNIFIED IDEOGRAPH:'F5C6:62918:嚾 +CJK UNIFIED IDEOGRAPH:'F5C7:62919:孈 +CJK UNIFIED IDEOGRAPH:'F5C8:62920:孇 +CJK UNIFIED IDEOGRAPH:'F5C9:62921:巋 +CJK UNIFIED IDEOGRAPH:'F5CA:62922:巏 +CJK UNIFIED IDEOGRAPH:'F5CB:62923:廱 +CJK UNIFIED IDEOGRAPH:'F5CC:62924:懽 +CJK UNIFIED IDEOGRAPH:'F5CD:62925:攛 +CJK UNIFIED IDEOGRAPH:'F5CE:62926:欂 +CJK UNIFIED IDEOGRAPH:'F5CF:62927:櫼 +CJK UNIFIED IDEOGRAPH:'F5D0:62928:欃 +CJK UNIFIED IDEOGRAPH:'F5D1:62929:櫸 +CJK UNIFIED IDEOGRAPH:'F5D2:62930:欀 +CJK UNIFIED IDEOGRAPH:'F5D3:62931:灃 +CJK UNIFIED IDEOGRAPH:'F5D4:62932:灄 +CJK UNIFIED IDEOGRAPH:'F5D5:62933:灊 +CJK UNIFIED IDEOGRAPH:'F5D6:62934:灈 +CJK UNIFIED IDEOGRAPH:'F5D7:62935:灉 +CJK UNIFIED IDEOGRAPH:'F5D8:62936:灅 +CJK UNIFIED IDEOGRAPH:'F5D9:62937:灆 +CJK UNIFIED IDEOGRAPH:'F5DA:62938:爝 +CJK UNIFIED IDEOGRAPH:'F5DB:62939:爚 +CJK UNIFIED IDEOGRAPH:'F5DC:62940:爙 +CJK UNIFIED IDEOGRAPH:'F5DD:62941:獾 +CJK UNIFIED IDEOGRAPH:'F5DE:62942:甗 +CJK UNIFIED IDEOGRAPH:'F5DF:62943:癪 +CJK UNIFIED IDEOGRAPH:'F5E0:62944:矐 +CJK UNIFIED IDEOGRAPH:'F5E1:62945:礭 +CJK UNIFIED IDEOGRAPH:'F5E2:62946:礱 +CJK UNIFIED IDEOGRAPH:'F5E3:62947:礯 +CJK UNIFIED IDEOGRAPH:'F5E4:62948:籔 +CJK UNIFIED IDEOGRAPH:'F5E5:62949:籓 +CJK UNIFIED IDEOGRAPH:'F5E6:62950:糲 +CJK UNIFIED IDEOGRAPH:'F5E7:62951:纊 +CJK UNIFIED IDEOGRAPH:'F5E8:62952:纇 +CJK UNIFIED IDEOGRAPH:'F5E9:62953:纈 +CJK UNIFIED IDEOGRAPH:'F5EA:62954:纋 +CJK UNIFIED IDEOGRAPH:'F5EB:62955:纆 +CJK UNIFIED IDEOGRAPH:'F5EC:62956:纍 +CJK UNIFIED IDEOGRAPH:'F5ED:62957:罍 +CJK UNIFIED IDEOGRAPH:'F5EE:62958:羻 +CJK UNIFIED IDEOGRAPH:'F5EF:62959:耰 +CJK UNIFIED IDEOGRAPH:'F5F0:62960:臝 +CJK UNIFIED IDEOGRAPH:'F5F1:62961:蘘 +CJK UNIFIED IDEOGRAPH:'F5F2:62962:蘪 +CJK UNIFIED IDEOGRAPH:'F5F3:62963:蘦 +CJK UNIFIED IDEOGRAPH:'F5F4:62964:蘟 +CJK UNIFIED IDEOGRAPH:'F5F5:62965:蘣 +CJK UNIFIED IDEOGRAPH:'F5F6:62966:蘜 +CJK UNIFIED IDEOGRAPH:'F5F7:62967:蘙 +CJK UNIFIED IDEOGRAPH:'F5F8:62968:蘧 +CJK UNIFIED IDEOGRAPH:'F5F9:62969:蘮 +CJK UNIFIED IDEOGRAPH:'F5FA:62970:蘡 +CJK UNIFIED IDEOGRAPH:'F5FB:62971:蘠 +CJK UNIFIED IDEOGRAPH:'F5FC:62972:蘩 +CJK UNIFIED IDEOGRAPH:'F5FD:62973:蘞 +CJK UNIFIED IDEOGRAPH:'F5FE:62974:蘥 +CJK UNIFIED IDEOGRAPH:'F640:63040:蠩 +CJK UNIFIED IDEOGRAPH:'F641:63041:蠝 +CJK UNIFIED IDEOGRAPH:'F642:63042:蠛 +CJK UNIFIED IDEOGRAPH:'F643:63043:蠠 +CJK UNIFIED IDEOGRAPH:'F644:63044:蠤 +CJK UNIFIED IDEOGRAPH:'F645:63045:蠜 +CJK UNIFIED IDEOGRAPH:'F646:63046:蠫 +CJK UNIFIED IDEOGRAPH:'F647:63047:衊 +CJK UNIFIED IDEOGRAPH:'F648:63048:襭 +CJK UNIFIED IDEOGRAPH:'F649:63049:襩 +CJK UNIFIED IDEOGRAPH:'F64A:63050:襮 +CJK UNIFIED IDEOGRAPH:'F64B:63051:襫 +CJK UNIFIED IDEOGRAPH:'F64C:63052:觺 +CJK UNIFIED IDEOGRAPH:'F64D:63053:譹 +CJK UNIFIED IDEOGRAPH:'F64E:63054:譸 +CJK UNIFIED IDEOGRAPH:'F64F:63055:譅 +CJK UNIFIED IDEOGRAPH:'F650:63056:譺 +CJK UNIFIED IDEOGRAPH:'F651:63057:譻 +CJK UNIFIED IDEOGRAPH:'F652:63058:贐 +CJK UNIFIED IDEOGRAPH:'F653:63059:贔 +CJK UNIFIED IDEOGRAPH:'F654:63060:趯 +CJK UNIFIED IDEOGRAPH:'F655:63061:躎 +CJK UNIFIED IDEOGRAPH:'F656:63062:躌 +CJK UNIFIED IDEOGRAPH:'F657:63063:轞 +CJK UNIFIED IDEOGRAPH:'F658:63064:轛 +CJK UNIFIED IDEOGRAPH:'F659:63065:轝 +CJK UNIFIED IDEOGRAPH:'F65A:63066:酆 +CJK UNIFIED IDEOGRAPH:'F65B:63067:酄 +CJK UNIFIED IDEOGRAPH:'F65C:63068:酅 +CJK UNIFIED IDEOGRAPH:'F65D:63069:醹 +CJK UNIFIED IDEOGRAPH:'F65E:63070:鐿 +CJK UNIFIED IDEOGRAPH:'F65F:63071:鐻 +CJK UNIFIED IDEOGRAPH:'F660:63072:鐶 +CJK UNIFIED IDEOGRAPH:'F661:63073:鐩 +CJK UNIFIED IDEOGRAPH:'F662:63074:鐽 +CJK UNIFIED IDEOGRAPH:'F663:63075:鐼 +CJK UNIFIED IDEOGRAPH:'F664:63076:鐰 +CJK UNIFIED IDEOGRAPH:'F665:63077:鐹 +CJK UNIFIED IDEOGRAPH:'F666:63078:鐪 +CJK UNIFIED IDEOGRAPH:'F667:63079:鐷 +CJK UNIFIED IDEOGRAPH:'F668:63080:鐬 +CJK UNIFIED IDEOGRAPH:'F669:63081:鑀 +CJK UNIFIED IDEOGRAPH:'F66A:63082:鐱 +CJK UNIFIED IDEOGRAPH:'F66B:63083:闥 +CJK UNIFIED IDEOGRAPH:'F66C:63084:闤 +CJK UNIFIED IDEOGRAPH:'F66D:63085:闣 +CJK UNIFIED IDEOGRAPH:'F66E:63086:霵 +CJK UNIFIED IDEOGRAPH:'F66F:63087:霺 +CJK UNIFIED IDEOGRAPH:'F670:63088:鞿 +CJK UNIFIED IDEOGRAPH:'F671:63089:韡 +CJK UNIFIED IDEOGRAPH:'F672:63090:顤 +CJK UNIFIED IDEOGRAPH:'F673:63091:飉 +CJK UNIFIED IDEOGRAPH:'F674:63092:飆 +CJK UNIFIED IDEOGRAPH:'F675:63093:飀 +CJK UNIFIED IDEOGRAPH:'F676:63094:饘 +CJK UNIFIED IDEOGRAPH:'F677:63095:饖 +CJK UNIFIED IDEOGRAPH:'F678:63096:騹 +CJK UNIFIED IDEOGRAPH:'F679:63097:騽 +CJK UNIFIED IDEOGRAPH:'F67A:63098:驆 +CJK UNIFIED IDEOGRAPH:'F67B:63099:驄 +CJK UNIFIED IDEOGRAPH:'F67C:63100:驂 +CJK UNIFIED IDEOGRAPH:'F67D:63101:驁 +CJK UNIFIED IDEOGRAPH:'F67E:63102:騺 +CJK UNIFIED IDEOGRAPH:'F6A1:63137:騿 +CJK UNIFIED IDEOGRAPH:'F6A2:63138:髍 +CJK UNIFIED IDEOGRAPH:'F6A3:63139:鬕 +CJK UNIFIED IDEOGRAPH:'F6A4:63140:鬗 +CJK UNIFIED IDEOGRAPH:'F6A5:63141:鬘 +CJK UNIFIED IDEOGRAPH:'F6A6:63142:鬖 +CJK UNIFIED IDEOGRAPH:'F6A7:63143:鬺 +CJK UNIFIED IDEOGRAPH:'F6A8:63144:魒 +CJK UNIFIED IDEOGRAPH:'F6A9:63145:鰫 +CJK UNIFIED IDEOGRAPH:'F6AA:63146:鰝 +CJK UNIFIED IDEOGRAPH:'F6AB:63147:鰜 +CJK UNIFIED IDEOGRAPH:'F6AC:63148:鰬 +CJK UNIFIED IDEOGRAPH:'F6AD:63149:鰣 +CJK UNIFIED IDEOGRAPH:'F6AE:63150:鰨 +CJK UNIFIED IDEOGRAPH:'F6AF:63151:鰩 +CJK UNIFIED IDEOGRAPH:'F6B0:63152:鰤 +CJK UNIFIED IDEOGRAPH:'F6B1:63153:鰡 +CJK UNIFIED IDEOGRAPH:'F6B2:63154:鶷 +CJK UNIFIED IDEOGRAPH:'F6B3:63155:鶶 +CJK UNIFIED IDEOGRAPH:'F6B4:63156:鶼 +CJK UNIFIED IDEOGRAPH:'F6B5:63157:鷁 +CJK UNIFIED IDEOGRAPH:'F6B6:63158:鷇 +CJK UNIFIED IDEOGRAPH:'F6B7:63159:鷊 +CJK UNIFIED IDEOGRAPH:'F6B8:63160:鷏 +CJK UNIFIED IDEOGRAPH:'F6B9:63161:鶾 +CJK UNIFIED IDEOGRAPH:'F6BA:63162:鷅 +CJK UNIFIED IDEOGRAPH:'F6BB:63163:鷃 +CJK UNIFIED IDEOGRAPH:'F6BC:63164:鶻 +CJK UNIFIED IDEOGRAPH:'F6BD:63165:鶵 +CJK UNIFIED IDEOGRAPH:'F6BE:63166:鷎 +CJK UNIFIED IDEOGRAPH:'F6BF:63167:鶹 +CJK UNIFIED IDEOGRAPH:'F6C0:63168:鶺 +CJK UNIFIED IDEOGRAPH:'F6C1:63169:鶬 +CJK UNIFIED IDEOGRAPH:'F6C2:63170:鷈 +CJK UNIFIED IDEOGRAPH:'F6C3:63171:鶱 +CJK UNIFIED IDEOGRAPH:'F6C4:63172:鶭 +CJK UNIFIED IDEOGRAPH:'F6C5:63173:鷌 +CJK UNIFIED IDEOGRAPH:'F6C6:63174:鶳 +CJK UNIFIED IDEOGRAPH:'F6C7:63175:鷍 +CJK UNIFIED IDEOGRAPH:'F6C8:63176:鶲 +CJK UNIFIED IDEOGRAPH:'F6C9:63177:鹺 +CJK UNIFIED IDEOGRAPH:'F6CA:63178:麜 +CJK UNIFIED IDEOGRAPH:'F6CB:63179:黫 +CJK UNIFIED IDEOGRAPH:'F6CC:63180:黮 +CJK UNIFIED IDEOGRAPH:'F6CD:63181:黭 +CJK UNIFIED IDEOGRAPH:'F6CE:63182:鼛 +CJK UNIFIED IDEOGRAPH:'F6CF:63183:鼘 +CJK UNIFIED IDEOGRAPH:'F6D0:63184:鼚 +CJK UNIFIED IDEOGRAPH:'F6D1:63185:鼱 +CJK UNIFIED IDEOGRAPH:'F6D2:63186:齎 +CJK UNIFIED IDEOGRAPH:'F6D3:63187:齥 +CJK UNIFIED IDEOGRAPH:'F6D4:63188:齤 +CJK UNIFIED IDEOGRAPH:'F6D5:63189:龒 +CJK UNIFIED IDEOGRAPH:'F6D6:63190:亹 +CJK UNIFIED IDEOGRAPH:'F6D7:63191:囆 +CJK UNIFIED IDEOGRAPH:'F6D8:63192:囅 +CJK UNIFIED IDEOGRAPH:'F6D9:63193:囋 +CJK UNIFIED IDEOGRAPH:'F6DA:63194:奱 +CJK UNIFIED IDEOGRAPH:'F6DB:63195:孋 +CJK UNIFIED IDEOGRAPH:'F6DC:63196:孌 +CJK UNIFIED IDEOGRAPH:'F6DD:63197:巕 +CJK UNIFIED IDEOGRAPH:'F6DE:63198:巑 +CJK UNIFIED IDEOGRAPH:'F6DF:63199:廲 +CJK UNIFIED IDEOGRAPH:'F6E0:63200:攡 +CJK UNIFIED IDEOGRAPH:'F6E1:63201:攠 +CJK UNIFIED IDEOGRAPH:'F6E2:63202:攦 +CJK UNIFIED IDEOGRAPH:'F6E3:63203:攢 +CJK UNIFIED IDEOGRAPH:'F6E4:63204:欋 +CJK UNIFIED IDEOGRAPH:'F6E5:63205:欈 +CJK UNIFIED IDEOGRAPH:'F6E6:63206:欉 +CJK UNIFIED IDEOGRAPH:'F6E7:63207:氍 +CJK UNIFIED IDEOGRAPH:'F6E8:63208:灕 +CJK UNIFIED IDEOGRAPH:'F6E9:63209:灖 +CJK UNIFIED IDEOGRAPH:'F6EA:63210:灗 +CJK UNIFIED IDEOGRAPH:'F6EB:63211:灒 +CJK UNIFIED IDEOGRAPH:'F6EC:63212:爞 +CJK UNIFIED IDEOGRAPH:'F6ED:63213:爟 +CJK UNIFIED IDEOGRAPH:'F6EE:63214:犩 +CJK UNIFIED IDEOGRAPH:'F6EF:63215:獿 +CJK UNIFIED IDEOGRAPH:'F6F0:63216:瓘 +CJK UNIFIED IDEOGRAPH:'F6F1:63217:瓕 +CJK UNIFIED IDEOGRAPH:'F6F2:63218:瓙 +CJK UNIFIED IDEOGRAPH:'F6F3:63219:瓗 +CJK UNIFIED IDEOGRAPH:'F6F4:63220:癭 +CJK UNIFIED IDEOGRAPH:'F6F5:63221:皭 +CJK UNIFIED IDEOGRAPH:'F6F6:63222:礵 +CJK UNIFIED IDEOGRAPH:'F6F7:63223:禴 +CJK UNIFIED IDEOGRAPH:'F6F8:63224:穰 +CJK UNIFIED IDEOGRAPH:'F6F9:63225:穱 +CJK UNIFIED IDEOGRAPH:'F6FA:63226:籗 +CJK UNIFIED IDEOGRAPH:'F6FB:63227:籜 +CJK UNIFIED IDEOGRAPH:'F6FC:63228:籙 +CJK UNIFIED IDEOGRAPH:'F6FD:63229:籛 +CJK UNIFIED IDEOGRAPH:'F6FE:63230:籚 +CJK UNIFIED IDEOGRAPH:'F740:63296:糴 +CJK UNIFIED IDEOGRAPH:'F741:63297:糱 +CJK UNIFIED IDEOGRAPH:'F742:63298:纑 +CJK UNIFIED IDEOGRAPH:'F743:63299:罏 +CJK UNIFIED IDEOGRAPH:'F744:63300:羇 +CJK UNIFIED IDEOGRAPH:'F745:63301:臞 +CJK UNIFIED IDEOGRAPH:'F746:63302:艫 +CJK UNIFIED IDEOGRAPH:'F747:63303:蘴 +CJK UNIFIED IDEOGRAPH:'F748:63304:蘵 +CJK UNIFIED IDEOGRAPH:'F749:63305:蘳 +CJK UNIFIED IDEOGRAPH:'F74A:63306:蘬 +CJK UNIFIED IDEOGRAPH:'F74B:63307:蘲 +CJK UNIFIED IDEOGRAPH:'F74C:63308:蘶 +CJK UNIFIED IDEOGRAPH:'F74D:63309:蠬 +CJK UNIFIED IDEOGRAPH:'F74E:63310:蠨 +CJK UNIFIED IDEOGRAPH:'F74F:63311:蠦 +CJK UNIFIED IDEOGRAPH:'F750:63312:蠪 +CJK UNIFIED IDEOGRAPH:'F751:63313:蠥 +CJK UNIFIED IDEOGRAPH:'F752:63314:襱 +CJK UNIFIED IDEOGRAPH:'F753:63315:覿 +CJK UNIFIED IDEOGRAPH:'F754:63316:覾 +CJK UNIFIED IDEOGRAPH:'F755:63317:觻 +CJK UNIFIED IDEOGRAPH:'F756:63318:譾 +CJK UNIFIED IDEOGRAPH:'F757:63319:讄 +CJK UNIFIED IDEOGRAPH:'F758:63320:讂 +CJK UNIFIED IDEOGRAPH:'F759:63321:讆 +CJK UNIFIED IDEOGRAPH:'F75A:63322:讅 +CJK UNIFIED IDEOGRAPH:'F75B:63323:譿 +CJK UNIFIED IDEOGRAPH:'F75C:63324:贕 +CJK UNIFIED IDEOGRAPH:'F75D:63325:躕 +CJK UNIFIED IDEOGRAPH:'F75E:63326:躔 +CJK UNIFIED IDEOGRAPH:'F75F:63327:躚 +CJK UNIFIED IDEOGRAPH:'F760:63328:躒 +CJK UNIFIED IDEOGRAPH:'F761:63329:躐 +CJK UNIFIED IDEOGRAPH:'F762:63330:躖 +CJK UNIFIED IDEOGRAPH:'F763:63331:躗 +CJK UNIFIED IDEOGRAPH:'F764:63332:轠 +CJK UNIFIED IDEOGRAPH:'F765:63333:轢 +CJK UNIFIED IDEOGRAPH:'F766:63334:酇 +CJK UNIFIED IDEOGRAPH:'F767:63335:鑌 +CJK UNIFIED IDEOGRAPH:'F768:63336:鑐 +CJK UNIFIED IDEOGRAPH:'F769:63337:鑊 +CJK UNIFIED IDEOGRAPH:'F76A:63338:鑋 +CJK UNIFIED IDEOGRAPH:'F76B:63339:鑏 +CJK UNIFIED IDEOGRAPH:'F76C:63340:鑇 +CJK UNIFIED IDEOGRAPH:'F76D:63341:鑅 +CJK UNIFIED IDEOGRAPH:'F76E:63342:鑈 +CJK UNIFIED IDEOGRAPH:'F76F:63343:鑉 +CJK UNIFIED IDEOGRAPH:'F770:63344:鑆 +CJK UNIFIED IDEOGRAPH:'F771:63345:霿 +CJK UNIFIED IDEOGRAPH:'F772:63346:韣 +CJK UNIFIED IDEOGRAPH:'F773:63347:顪 +CJK UNIFIED IDEOGRAPH:'F774:63348:顩 +CJK UNIFIED IDEOGRAPH:'F775:63349:飋 +CJK UNIFIED IDEOGRAPH:'F776:63350:饔 +CJK UNIFIED IDEOGRAPH:'F777:63351:饛 +CJK UNIFIED IDEOGRAPH:'F778:63352:驎 +CJK UNIFIED IDEOGRAPH:'F779:63353:驓 +CJK UNIFIED IDEOGRAPH:'F77A:63354:驔 +CJK UNIFIED IDEOGRAPH:'F77B:63355:驌 +CJK UNIFIED IDEOGRAPH:'F77C:63356:驏 +CJK UNIFIED IDEOGRAPH:'F77D:63357:驈 +CJK UNIFIED IDEOGRAPH:'F77E:63358:驊 +CJK UNIFIED IDEOGRAPH:'F7A1:63393:驉 +CJK UNIFIED IDEOGRAPH:'F7A2:63394:驒 +CJK UNIFIED IDEOGRAPH:'F7A3:63395:驐 +CJK UNIFIED IDEOGRAPH:'F7A4:63396:髐 +CJK UNIFIED IDEOGRAPH:'F7A5:63397:鬙 +CJK UNIFIED IDEOGRAPH:'F7A6:63398:鬫 +CJK UNIFIED IDEOGRAPH:'F7A7:63399:鬻 +CJK UNIFIED IDEOGRAPH:'F7A8:63400:魖 +CJK UNIFIED IDEOGRAPH:'F7A9:63401:魕 +CJK UNIFIED IDEOGRAPH:'F7AA:63402:鱆 +CJK UNIFIED IDEOGRAPH:'F7AB:63403:鱈 +CJK UNIFIED IDEOGRAPH:'F7AC:63404:鰿 +CJK UNIFIED IDEOGRAPH:'F7AD:63405:鱄 +CJK UNIFIED IDEOGRAPH:'F7AE:63406:鰹 +CJK UNIFIED IDEOGRAPH:'F7AF:63407:鰳 +CJK UNIFIED IDEOGRAPH:'F7B0:63408:鱁 +CJK UNIFIED IDEOGRAPH:'F7B1:63409:鰼 +CJK UNIFIED IDEOGRAPH:'F7B2:63410:鰷 +CJK UNIFIED IDEOGRAPH:'F7B3:63411:鰴 +CJK UNIFIED IDEOGRAPH:'F7B4:63412:鰲 +CJK UNIFIED IDEOGRAPH:'F7B5:63413:鰽 +CJK UNIFIED IDEOGRAPH:'F7B6:63414:鰶 +CJK UNIFIED IDEOGRAPH:'F7B7:63415:鷛 +CJK UNIFIED IDEOGRAPH:'F7B8:63416:鷒 +CJK UNIFIED IDEOGRAPH:'F7B9:63417:鷞 +CJK UNIFIED IDEOGRAPH:'F7BA:63418:鷚 +CJK UNIFIED IDEOGRAPH:'F7BB:63419:鷋 +CJK UNIFIED IDEOGRAPH:'F7BC:63420:鷐 +CJK UNIFIED IDEOGRAPH:'F7BD:63421:鷜 +CJK UNIFIED IDEOGRAPH:'F7BE:63422:鷑 +CJK UNIFIED IDEOGRAPH:'F7BF:63423:鷟 +CJK UNIFIED IDEOGRAPH:'F7C0:63424:鷩 +CJK UNIFIED IDEOGRAPH:'F7C1:63425:鷙 +CJK UNIFIED IDEOGRAPH:'F7C2:63426:鷘 +CJK UNIFIED IDEOGRAPH:'F7C3:63427:鷖 +CJK UNIFIED IDEOGRAPH:'F7C4:63428:鷵 +CJK UNIFIED IDEOGRAPH:'F7C5:63429:鷕 +CJK UNIFIED IDEOGRAPH:'F7C6:63430:鷝 +CJK UNIFIED IDEOGRAPH:'F7C7:63431:麶 +CJK UNIFIED IDEOGRAPH:'F7C8:63432:黰 +CJK UNIFIED IDEOGRAPH:'F7C9:63433:鼵 +CJK UNIFIED IDEOGRAPH:'F7CA:63434:鼳 +CJK UNIFIED IDEOGRAPH:'F7CB:63435:鼲 +CJK UNIFIED IDEOGRAPH:'F7CC:63436:齂 +CJK UNIFIED IDEOGRAPH:'F7CD:63437:齫 +CJK UNIFIED IDEOGRAPH:'F7CE:63438:龕 +CJK UNIFIED IDEOGRAPH:'F7CF:63439:龢 +CJK UNIFIED IDEOGRAPH:'F7D0:63440:儽 +CJK UNIFIED IDEOGRAPH:'F7D1:63441:劙 +CJK UNIFIED IDEOGRAPH:'F7D2:63442:壨 +CJK UNIFIED IDEOGRAPH:'F7D3:63443:壧 +CJK UNIFIED IDEOGRAPH:'F7D4:63444:奲 +CJK UNIFIED IDEOGRAPH:'F7D5:63445:孍 +CJK UNIFIED IDEOGRAPH:'F7D6:63446:巘 +CJK UNIFIED IDEOGRAPH:'F7D7:63447:蠯 +CJK UNIFIED IDEOGRAPH:'F7D8:63448:彏 +CJK UNIFIED IDEOGRAPH:'F7D9:63449:戁 +CJK UNIFIED IDEOGRAPH:'F7DA:63450:戃 +CJK UNIFIED IDEOGRAPH:'F7DB:63451:戄 +CJK UNIFIED IDEOGRAPH:'F7DC:63452:攩 +CJK UNIFIED IDEOGRAPH:'F7DD:63453:攥 +CJK UNIFIED IDEOGRAPH:'F7DE:63454:斖 +CJK UNIFIED IDEOGRAPH:'F7DF:63455:曫 +CJK UNIFIED IDEOGRAPH:'F7E0:63456:欑 +CJK UNIFIED IDEOGRAPH:'F7E1:63457:欒 +CJK UNIFIED IDEOGRAPH:'F7E2:63458:欏 +CJK UNIFIED IDEOGRAPH:'F7E3:63459:毊 +CJK UNIFIED IDEOGRAPH:'F7E4:63460:灛 +CJK UNIFIED IDEOGRAPH:'F7E5:63461:灚 +CJK UNIFIED IDEOGRAPH:'F7E6:63462:爢 +CJK UNIFIED IDEOGRAPH:'F7E7:63463:玂 +CJK UNIFIED IDEOGRAPH:'F7E8:63464:玁 +CJK UNIFIED IDEOGRAPH:'F7E9:63465:玃 +CJK UNIFIED IDEOGRAPH:'F7EA:63466:癰 +CJK UNIFIED IDEOGRAPH:'F7EB:63467:矔 +CJK UNIFIED IDEOGRAPH:'F7EC:63468:籧 +CJK UNIFIED IDEOGRAPH:'F7ED:63469:籦 +CJK UNIFIED IDEOGRAPH:'F7EE:63470:纕 +CJK UNIFIED IDEOGRAPH:'F7EF:63471:艬 +CJK UNIFIED IDEOGRAPH:'F7F0:63472:蘺 +CJK UNIFIED IDEOGRAPH:'F7F1:63473:虀 +CJK UNIFIED IDEOGRAPH:'F7F2:63474:蘹 +CJK UNIFIED IDEOGRAPH:'F7F3:63475:蘼 +CJK UNIFIED IDEOGRAPH:'F7F4:63476:蘱 +CJK UNIFIED IDEOGRAPH:'F7F5:63477:蘻 +CJK UNIFIED IDEOGRAPH:'F7F6:63478:蘾 +CJK UNIFIED IDEOGRAPH:'F7F7:63479:蠰 +CJK UNIFIED IDEOGRAPH:'F7F8:63480:蠲 +CJK UNIFIED IDEOGRAPH:'F7F9:63481:蠮 +CJK UNIFIED IDEOGRAPH:'F7FA:63482:蠳 +CJK UNIFIED IDEOGRAPH:'F7FB:63483:襶 +CJK UNIFIED IDEOGRAPH:'F7FC:63484:襴 +CJK UNIFIED IDEOGRAPH:'F7FD:63485:襳 +CJK UNIFIED IDEOGRAPH:'F7FE:63486:觾 +CJK UNIFIED IDEOGRAPH:'F840:63552:讌 +CJK UNIFIED IDEOGRAPH:'F841:63553:讎 +CJK UNIFIED IDEOGRAPH:'F842:63554:讋 +CJK UNIFIED IDEOGRAPH:'F843:63555:讈 +CJK UNIFIED IDEOGRAPH:'F844:63556:豅 +CJK UNIFIED IDEOGRAPH:'F845:63557:贙 +CJK UNIFIED IDEOGRAPH:'F846:63558:躘 +CJK UNIFIED IDEOGRAPH:'F847:63559:轤 +CJK UNIFIED IDEOGRAPH:'F848:63560:轣 +CJK UNIFIED IDEOGRAPH:'F849:63561:醼 +CJK UNIFIED IDEOGRAPH:'F84A:63562:鑢 +CJK UNIFIED IDEOGRAPH:'F84B:63563:鑕 +CJK UNIFIED IDEOGRAPH:'F84C:63564:鑝 +CJK UNIFIED IDEOGRAPH:'F84D:63565:鑗 +CJK UNIFIED IDEOGRAPH:'F84E:63566:鑞 +CJK UNIFIED IDEOGRAPH:'F84F:63567:韄 +CJK UNIFIED IDEOGRAPH:'F850:63568:韅 +CJK UNIFIED IDEOGRAPH:'F851:63569:頀 +CJK UNIFIED IDEOGRAPH:'F852:63570:驖 +CJK UNIFIED IDEOGRAPH:'F853:63571:驙 +CJK UNIFIED IDEOGRAPH:'F854:63572:鬞 +CJK UNIFIED IDEOGRAPH:'F855:63573:鬟 +CJK UNIFIED IDEOGRAPH:'F856:63574:鬠 +CJK UNIFIED IDEOGRAPH:'F857:63575:鱒 +CJK UNIFIED IDEOGRAPH:'F858:63576:鱘 +CJK UNIFIED IDEOGRAPH:'F859:63577:鱐 +CJK UNIFIED IDEOGRAPH:'F85A:63578:鱊 +CJK UNIFIED IDEOGRAPH:'F85B:63579:鱍 +CJK UNIFIED IDEOGRAPH:'F85C:63580:鱋 +CJK UNIFIED IDEOGRAPH:'F85D:63581:鱕 +CJK UNIFIED IDEOGRAPH:'F85E:63582:鱙 +CJK UNIFIED IDEOGRAPH:'F85F:63583:鱌 +CJK UNIFIED IDEOGRAPH:'F860:63584:鱎 +CJK UNIFIED IDEOGRAPH:'F861:63585:鷻 +CJK UNIFIED IDEOGRAPH:'F862:63586:鷷 +CJK UNIFIED IDEOGRAPH:'F863:63587:鷯 +CJK UNIFIED IDEOGRAPH:'F864:63588:鷣 +CJK UNIFIED IDEOGRAPH:'F865:63589:鷫 +CJK UNIFIED IDEOGRAPH:'F866:63590:鷸 +CJK UNIFIED IDEOGRAPH:'F867:63591:鷤 +CJK UNIFIED IDEOGRAPH:'F868:63592:鷶 +CJK UNIFIED IDEOGRAPH:'F869:63593:鷡 +CJK UNIFIED IDEOGRAPH:'F86A:63594:鷮 +CJK UNIFIED IDEOGRAPH:'F86B:63595:鷦 +CJK UNIFIED IDEOGRAPH:'F86C:63596:鷲 +CJK UNIFIED IDEOGRAPH:'F86D:63597:鷰 +CJK UNIFIED IDEOGRAPH:'F86E:63598:鷢 +CJK UNIFIED IDEOGRAPH:'F86F:63599:鷬 +CJK UNIFIED IDEOGRAPH:'F870:63600:鷴 +CJK UNIFIED IDEOGRAPH:'F871:63601:鷳 +CJK UNIFIED IDEOGRAPH:'F872:63602:鷨 +CJK UNIFIED IDEOGRAPH:'F873:63603:鷭 +CJK UNIFIED IDEOGRAPH:'F874:63604:黂 +CJK UNIFIED IDEOGRAPH:'F875:63605:黐 +CJK UNIFIED IDEOGRAPH:'F876:63606:黲 +CJK UNIFIED IDEOGRAPH:'F877:63607:黳 +CJK UNIFIED IDEOGRAPH:'F878:63608:鼆 +CJK UNIFIED IDEOGRAPH:'F879:63609:鼜 +CJK UNIFIED IDEOGRAPH:'F87A:63610:鼸 +CJK UNIFIED IDEOGRAPH:'F87B:63611:鼷 +CJK UNIFIED IDEOGRAPH:'F87C:63612:鼶 +CJK UNIFIED IDEOGRAPH:'F87D:63613:齃 +CJK UNIFIED IDEOGRAPH:'F87E:63614:齏 +CJK UNIFIED IDEOGRAPH:'F8A1:63649:齱 +CJK UNIFIED IDEOGRAPH:'F8A2:63650:齰 +CJK UNIFIED IDEOGRAPH:'F8A3:63651:齮 +CJK UNIFIED IDEOGRAPH:'F8A4:63652:齯 +CJK UNIFIED IDEOGRAPH:'F8A5:63653:囓 +CJK UNIFIED IDEOGRAPH:'F8A6:63654:囍 +CJK UNIFIED IDEOGRAPH:'F8A7:63655:孎 +CJK UNIFIED IDEOGRAPH:'F8A8:63656:屭 +CJK UNIFIED IDEOGRAPH:'F8A9:63657:攭 +CJK UNIFIED IDEOGRAPH:'F8AA:63658:曭 +CJK UNIFIED IDEOGRAPH:'F8AB:63659:曮 +CJK UNIFIED IDEOGRAPH:'F8AC:63660:欓 +CJK UNIFIED IDEOGRAPH:'F8AD:63661:灟 +CJK UNIFIED IDEOGRAPH:'F8AE:63662:灡 +CJK UNIFIED IDEOGRAPH:'F8AF:63663:灝 +CJK UNIFIED IDEOGRAPH:'F8B0:63664:灠 +CJK UNIFIED IDEOGRAPH:'F8B1:63665:爣 +CJK UNIFIED IDEOGRAPH:'F8B2:63666:瓛 +CJK UNIFIED IDEOGRAPH:'F8B3:63667:瓥 +CJK UNIFIED IDEOGRAPH:'F8B4:63668:矕 +CJK UNIFIED IDEOGRAPH:'F8B5:63669:礸 +CJK UNIFIED IDEOGRAPH:'F8B6:63670:禷 +CJK UNIFIED IDEOGRAPH:'F8B7:63671:禶 +CJK UNIFIED IDEOGRAPH:'F8B8:63672:籪 +CJK UNIFIED IDEOGRAPH:'F8B9:63673:纗 +CJK UNIFIED IDEOGRAPH:'F8BA:63674:羉 +CJK UNIFIED IDEOGRAPH:'F8BB:63675:艭 +CJK UNIFIED IDEOGRAPH:'F8BC:63676:虃 +CJK UNIFIED IDEOGRAPH:'F8BD:63677:蠸 +CJK UNIFIED IDEOGRAPH:'F8BE:63678:蠷 +CJK UNIFIED IDEOGRAPH:'F8BF:63679:蠵 +CJK UNIFIED IDEOGRAPH:'F8C0:63680:衋 +CJK UNIFIED IDEOGRAPH:'F8C1:63681:讔 +CJK UNIFIED IDEOGRAPH:'F8C2:63682:讕 +CJK UNIFIED IDEOGRAPH:'F8C3:63683:躞 +CJK UNIFIED IDEOGRAPH:'F8C4:63684:躟 +CJK UNIFIED IDEOGRAPH:'F8C5:63685:躠 +CJK UNIFIED IDEOGRAPH:'F8C6:63686:躝 +CJK UNIFIED IDEOGRAPH:'F8C7:63687:醾 +CJK UNIFIED IDEOGRAPH:'F8C8:63688:醽 +CJK UNIFIED IDEOGRAPH:'F8C9:63689:釂 +CJK UNIFIED IDEOGRAPH:'F8CA:63690:鑫 +CJK UNIFIED IDEOGRAPH:'F8CB:63691:鑨 +CJK UNIFIED IDEOGRAPH:'F8CC:63692:鑩 +CJK UNIFIED IDEOGRAPH:'F8CD:63693:雥 +CJK UNIFIED IDEOGRAPH:'F8CE:63694:靆 +CJK UNIFIED IDEOGRAPH:'F8CF:63695:靃 +CJK UNIFIED IDEOGRAPH:'F8D0:63696:靇 +CJK UNIFIED IDEOGRAPH:'F8D1:63697:韇 +CJK UNIFIED IDEOGRAPH:'F8D2:63698:韥 +CJK UNIFIED IDEOGRAPH:'F8D3:63699:驞 +CJK UNIFIED IDEOGRAPH:'F8D4:63700:髕 +CJK UNIFIED IDEOGRAPH:'F8D5:63701:魙 +CJK UNIFIED IDEOGRAPH:'F8D6:63702:鱣 +CJK UNIFIED IDEOGRAPH:'F8D7:63703:鱧 +CJK UNIFIED IDEOGRAPH:'F8D8:63704:鱦 +CJK UNIFIED IDEOGRAPH:'F8D9:63705:鱢 +CJK UNIFIED IDEOGRAPH:'F8DA:63706:鱞 +CJK UNIFIED IDEOGRAPH:'F8DB:63707:鱠 +CJK UNIFIED IDEOGRAPH:'F8DC:63708:鸂 +CJK UNIFIED IDEOGRAPH:'F8DD:63709:鷾 +CJK UNIFIED IDEOGRAPH:'F8DE:63710:鸇 +CJK UNIFIED IDEOGRAPH:'F8DF:63711:鸃 +CJK UNIFIED IDEOGRAPH:'F8E0:63712:鸆 +CJK UNIFIED IDEOGRAPH:'F8E1:63713:鸅 +CJK UNIFIED IDEOGRAPH:'F8E2:63714:鸀 +CJK UNIFIED IDEOGRAPH:'F8E3:63715:鸁 +CJK UNIFIED IDEOGRAPH:'F8E4:63716:鸉 +CJK UNIFIED IDEOGRAPH:'F8E5:63717:鷿 +CJK UNIFIED IDEOGRAPH:'F8E6:63718:鷽 +CJK UNIFIED IDEOGRAPH:'F8E7:63719:鸄 +CJK UNIFIED IDEOGRAPH:'F8E8:63720:麠 +CJK UNIFIED IDEOGRAPH:'F8E9:63721:鼞 +CJK UNIFIED IDEOGRAPH:'F8EA:63722:齆 +CJK UNIFIED IDEOGRAPH:'F8EB:63723:齴 +CJK UNIFIED IDEOGRAPH:'F8EC:63724:齵 +CJK UNIFIED IDEOGRAPH:'F8ED:63725:齶 +CJK UNIFIED IDEOGRAPH:'F8EE:63726:囔 +CJK UNIFIED IDEOGRAPH:'F8EF:63727:攮 +CJK UNIFIED IDEOGRAPH:'F8F0:63728:斸 +CJK UNIFIED IDEOGRAPH:'F8F1:63729:欘 +CJK UNIFIED IDEOGRAPH:'F8F2:63730:欙 +CJK UNIFIED IDEOGRAPH:'F8F3:63731:欗 +CJK UNIFIED IDEOGRAPH:'F8F4:63732:欚 +CJK UNIFIED IDEOGRAPH:'F8F5:63733:灢 +CJK UNIFIED IDEOGRAPH:'F8F6:63734:爦 +CJK UNIFIED IDEOGRAPH:'F8F7:63735:犪 +CJK UNIFIED IDEOGRAPH:'F8F8:63736:矘 +CJK UNIFIED IDEOGRAPH:'F8F9:63737:矙 +CJK UNIFIED IDEOGRAPH:'F8FA:63738:礹 +CJK UNIFIED IDEOGRAPH:'F8FB:63739:籩 +CJK UNIFIED IDEOGRAPH:'F8FC:63740:籫 +CJK UNIFIED IDEOGRAPH:'F8FD:63741:糶 +CJK UNIFIED IDEOGRAPH:'F8FE:63742:纚 +CJK UNIFIED IDEOGRAPH:'F940:63808:纘 +CJK UNIFIED IDEOGRAPH:'F941:63809:纛 +CJK UNIFIED IDEOGRAPH:'F942:63810:纙 +CJK UNIFIED IDEOGRAPH:'F943:63811:臠 +CJK UNIFIED IDEOGRAPH:'F944:63812:臡 +CJK UNIFIED IDEOGRAPH:'F945:63813:虆 +CJK UNIFIED IDEOGRAPH:'F946:63814:虇 +CJK UNIFIED IDEOGRAPH:'F947:63815:虈 +CJK UNIFIED IDEOGRAPH:'F948:63816:襹 +CJK UNIFIED IDEOGRAPH:'F949:63817:襺 +CJK UNIFIED IDEOGRAPH:'F94A:63818:襼 +CJK UNIFIED IDEOGRAPH:'F94B:63819:襻 +CJK UNIFIED IDEOGRAPH:'F94C:63820:觿 +CJK UNIFIED IDEOGRAPH:'F94D:63821:讘 +CJK UNIFIED IDEOGRAPH:'F94E:63822:讙 +CJK UNIFIED IDEOGRAPH:'F94F:63823:躥 +CJK UNIFIED IDEOGRAPH:'F950:63824:躤 +CJK UNIFIED IDEOGRAPH:'F951:63825:躣 +CJK UNIFIED IDEOGRAPH:'F952:63826:鑮 +CJK UNIFIED IDEOGRAPH:'F953:63827:鑭 +CJK UNIFIED IDEOGRAPH:'F954:63828:鑯 +CJK UNIFIED IDEOGRAPH:'F955:63829:鑱 +CJK UNIFIED IDEOGRAPH:'F956:63830:鑳 +CJK UNIFIED IDEOGRAPH:'F957:63831:靉 +CJK UNIFIED IDEOGRAPH:'F958:63832:顲 +CJK UNIFIED IDEOGRAPH:'F959:63833:饟 +CJK UNIFIED IDEOGRAPH:'F95A:63834:鱨 +CJK UNIFIED IDEOGRAPH:'F95B:63835:鱮 +CJK UNIFIED IDEOGRAPH:'F95C:63836:鱭 +CJK UNIFIED IDEOGRAPH:'F95D:63837:鸋 +CJK UNIFIED IDEOGRAPH:'F95E:63838:鸍 +CJK UNIFIED IDEOGRAPH:'F95F:63839:鸐 +CJK UNIFIED IDEOGRAPH:'F960:63840:鸏 +CJK UNIFIED IDEOGRAPH:'F961:63841:鸒 +CJK UNIFIED IDEOGRAPH:'F962:63842:鸑 +CJK UNIFIED IDEOGRAPH:'F963:63843:麡 +CJK UNIFIED IDEOGRAPH:'F964:63844:黵 +CJK UNIFIED IDEOGRAPH:'F965:63845:鼉 +CJK UNIFIED IDEOGRAPH:'F966:63846:齇 +CJK UNIFIED IDEOGRAPH:'F967:63847:齸 +CJK UNIFIED IDEOGRAPH:'F968:63848:齻 +CJK UNIFIED IDEOGRAPH:'F969:63849:齺 +CJK UNIFIED IDEOGRAPH:'F96A:63850:齹 +CJK UNIFIED IDEOGRAPH:'F96B:63851:圞 +CJK UNIFIED IDEOGRAPH:'F96C:63852:灦 +CJK UNIFIED IDEOGRAPH:'F96D:63853:籯 +CJK UNIFIED IDEOGRAPH:'F96E:63854:蠼 +CJK UNIFIED IDEOGRAPH:'F96F:63855:趲 +CJK UNIFIED IDEOGRAPH:'F970:63856:躦 +CJK UNIFIED IDEOGRAPH:'F971:63857:釃 +CJK UNIFIED IDEOGRAPH:'F972:63858:鑴 +CJK UNIFIED IDEOGRAPH:'F973:63859:鑸 +CJK UNIFIED IDEOGRAPH:'F974:63860:鑶 +CJK UNIFIED IDEOGRAPH:'F975:63861:鑵 +CJK UNIFIED IDEOGRAPH:'F976:63862:驠 +CJK UNIFIED IDEOGRAPH:'F977:63863:鱴 +CJK UNIFIED IDEOGRAPH:'F978:63864:鱳 +CJK UNIFIED IDEOGRAPH:'F979:63865:鱱 +CJK UNIFIED IDEOGRAPH:'F97A:63866:鱵 +CJK UNIFIED IDEOGRAPH:'F97B:63867:鸔 +CJK UNIFIED IDEOGRAPH:'F97C:63868:鸓 +CJK UNIFIED IDEOGRAPH:'F97D:63869:黶 +CJK UNIFIED IDEOGRAPH:'F97E:63870:鼊 +CJK UNIFIED IDEOGRAPH:'F9A1:63905:龤 +CJK UNIFIED IDEOGRAPH:'F9A2:63906:灨 +CJK UNIFIED IDEOGRAPH:'F9A3:63907:灥 +CJK UNIFIED IDEOGRAPH:'F9A4:63908:糷 +CJK UNIFIED IDEOGRAPH:'F9A5:63909:虪 +CJK UNIFIED IDEOGRAPH:'F9A6:63910:蠾 +CJK UNIFIED IDEOGRAPH:'F9A7:63911:蠽 +CJK UNIFIED IDEOGRAPH:'F9A8:63912:蠿 +CJK UNIFIED IDEOGRAPH:'F9A9:63913:讞 +CJK UNIFIED IDEOGRAPH:'F9AA:63914:貜 +CJK UNIFIED IDEOGRAPH:'F9AB:63915:躩 +CJK UNIFIED IDEOGRAPH:'F9AC:63916:軉 +CJK UNIFIED IDEOGRAPH:'F9AD:63917:靋 +CJK UNIFIED IDEOGRAPH:'F9AE:63918:顳 +CJK UNIFIED IDEOGRAPH:'F9AF:63919:顴 +CJK UNIFIED IDEOGRAPH:'F9B0:63920:飌 +CJK UNIFIED IDEOGRAPH:'F9B1:63921:饡 +CJK UNIFIED IDEOGRAPH:'F9B2:63922:馫 +CJK UNIFIED IDEOGRAPH:'F9B3:63923:驤 +CJK UNIFIED IDEOGRAPH:'F9B4:63924:驦 +CJK UNIFIED IDEOGRAPH:'F9B5:63925:驧 +CJK UNIFIED IDEOGRAPH:'F9B6:63926:鬤 +CJK UNIFIED IDEOGRAPH:'F9B7:63927:鸕 +CJK UNIFIED IDEOGRAPH:'F9B8:63928:鸗 +CJK UNIFIED IDEOGRAPH:'F9B9:63929:齈 +CJK UNIFIED IDEOGRAPH:'F9BA:63930:戇 +CJK UNIFIED IDEOGRAPH:'F9BB:63931:欞 +CJK UNIFIED IDEOGRAPH:'F9BC:63932:爧 +CJK UNIFIED IDEOGRAPH:'F9BD:63933:虌 +CJK UNIFIED IDEOGRAPH:'F9BE:63934:躨 +CJK UNIFIED IDEOGRAPH:'F9BF:63935:钂 +CJK UNIFIED IDEOGRAPH:'F9C0:63936:钀 +CJK UNIFIED IDEOGRAPH:'F9C1:63937:钁 +CJK UNIFIED IDEOGRAPH:'F9C2:63938:驩 +CJK UNIFIED IDEOGRAPH:'F9C3:63939:驨 +CJK UNIFIED IDEOGRAPH:'F9C4:63940:鬮 +CJK UNIFIED IDEOGRAPH:'F9C5:63941:鸙 +CJK UNIFIED IDEOGRAPH:'F9C6:63942:爩 +CJK UNIFIED IDEOGRAPH:'F9C7:63943:虋 +CJK UNIFIED IDEOGRAPH:'F9C8:63944:讟 +CJK UNIFIED IDEOGRAPH:'F9C9:63945:钃 +CJK UNIFIED IDEOGRAPH:'F9CA:63946:鱹 +CJK UNIFIED IDEOGRAPH:'F9CB:63947:麷 +CJK UNIFIED IDEOGRAPH:'F9CC:63948:癵 +CJK UNIFIED IDEOGRAPH:'F9CD:63949:驫 +CJK UNIFIED IDEOGRAPH:'F9CE:63950:鱺 +CJK UNIFIED IDEOGRAPH:'F9CF:63951:鸝 +CJK UNIFIED IDEOGRAPH:'F9D0:63952:灩 +CJK UNIFIED IDEOGRAPH:'F9D1:63953:灪 +CJK UNIFIED IDEOGRAPH:'F9D2:63954:麤 +CJK UNIFIED IDEOGRAPH:'F9D3:63955:齾 +CJK UNIFIED IDEOGRAPH:'F9D4:63956:齉 +CJK UNIFIED IDEOGRAPH:'F9D5:63957:龘 +CJK UNIFIED IDEOGRAPH:'F9D6:63958:碁 +CJK UNIFIED IDEOGRAPH:'F9D7:63959:銹 +CJK UNIFIED IDEOGRAPH:'F9D8:63960:裏 +CJK UNIFIED IDEOGRAPH:'F9D9:63961:墻 +CJK UNIFIED IDEOGRAPH:'F9DA:63962:恒 +CJK UNIFIED IDEOGRAPH:'F9DB:63963:粧 +CJK UNIFIED IDEOGRAPH:'F9DC:63964:嫺 +BOX DRAWINGS DOUBLE DOWN AND RIGHT:'F9DD:63965:╔ +BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL:'F9DE:63966:╦ +BOX DRAWINGS DOUBLE DOWN AND LEFT:'F9DF:63967:╗ +BOX DRAWINGS DOUBLE VERTICAL AND RIGHT:'F9E0:63968:╠ +BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL:'F9E1:63969:╬ +BOX DRAWINGS DOUBLE VERTICAL AND LEFT:'F9E2:63970:╣ +BOX DRAWINGS DOUBLE UP AND RIGHT:'F9E3:63971:╚ +BOX DRAWINGS DOUBLE UP AND HORIZONTAL:'F9E4:63972:╩ +BOX DRAWINGS DOUBLE UP AND LEFT:'F9E5:63973:╝ +BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE:'F9E6:63974:╒ +BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE:'F9E7:63975:╤ +BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE:'F9E8:63976:╕ +BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE:'F9E9:63977:╞ +BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE:'F9EA:63978:╪ +BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE:'F9EB:63979:╡ +BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE:'F9EC:63980:╘ +BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE:'F9ED:63981:╧ +BOX DRAWINGS UP SINGLE AND LEFT DOUBLE:'F9EE:63982:╛ +BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE:'F9EF:63983:╓ +BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE:'F9F0:63984:╥ +BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE:'F9F1:63985:╖ +BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE:'F9F2:63986:╟ +BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE:'F9F3:63987:╫ +BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE:'F9F4:63988:╢ +BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE:'F9F5:63989:╙ +BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE:'F9F6:63990:╨ +BOX DRAWINGS UP DOUBLE AND LEFT SINGLE:'F9F7:63991:╜ +BOX DRAWINGS DOUBLE VERTICAL:'F9F8:63992:║ +BOX DRAWINGS DOUBLE HORIZONTAL:'F9F9:63993:═ +BOX DRAWINGS LIGHT ARC DOWN AND RIGHT:'F9FA:63994:╭ +BOX DRAWINGS LIGHT ARC DOWN AND LEFT:'F9FB:63995:╮ +BOX DRAWINGS LIGHT ARC UP AND RIGHT:'F9FC:63996:╰ +BOX DRAWINGS LIGHT ARC UP AND LEFT:'F9FD:63997:╯ +DARK SHADE:'F9FE:63998:▓ + + +SINGLE LOW-9 QUOTATION MARK:'82:8218:‚ +DOUBLE LOW-9 QUOTATION MARK:'84:8222:„ +HORIZONTAL ELLIPSIS:'85:8230:… +SINGLE LOW-9 QUOTATION MARK:'82:8218:‚ +DOUBLE LOW-9 QUOTATION MARK:'84:8222:„ +HORIZONTAL ELLIPSIS:'85:8230:… +DAGGER:'86:8224:† +DOUBLE DAGGER:'87:8225:‡ +PER MILLE SIGN:'89:8240:‰ +LATIN CAPITAL LETTER S WITH CARON:'8A:352:Š +SINGLE LEFT-POINTING ANGLE QUOTATION MARK:'8B:8249:‹ +LATIN CAPITAL LETTER S WITH ACUTE:'8C:346:Ś +LATIN CAPITAL LETTER T WITH CARON:'8D:356:Ť +LATIN CAPITAL LETTER Z WITH CARON:'8E:381:Ž +LATIN CAPITAL LETTER Z WITH ACUTE:'8F:377:Ź +LEFT SINGLE QUOTATION MARK:'91:8216:‘ +RIGHT SINGLE QUOTATION MARK:'92:8217:’ +LEFT DOUBLE QUOTATION MARK:'93:8220:“ +RIGHT DOUBLE QUOTATION MARK:'94:8221:” +BULLET:'95:8226:• +EN DASH:'96:8211:– +EM DASH:'97:8212:— +TRADE MARK SIGN:'99:8482:™ +LATIN SMALL LETTER S WITH CARON:'9A:353:š +SINGLE RIGHT-POINTING ANGLE QUOTATION MARK:'9B:8250:› +LATIN SMALL LETTER S WITH ACUTE:'9C:347:ś +LATIN SMALL LETTER T WITH CARON:'9D:357:ť +LATIN SMALL LETTER Z WITH CARON:'9E:382:ž +LATIN SMALL LETTER Z WITH ACUTE:'9F:378:ź +NO-BREAK SPACE:'A0:160:  +CARON (MANDARIN CHINESE THIRD TONE):'A1:711:ˇ +BREVE:'A2:728:˘ +LATIN CAPITAL LETTER L WITH STROKE:'A3:321:Ł +CURRENCY SIGN:'A4:164:¤ +LATIN CAPITAL LETTER A WITH OGONEK:'A5:260:Ą +BROKEN BAR:'A6:166:¦ +SECTION SIGN:'A7:167:§ +DIAERESIS:'A8:168:¨ +COPYRIGHT SIGN:'A9:169:© +LATIN CAPITAL LETTER S WITH CEDILLA:'AA:350:Ş +LEFT-POINTING DOUBLE ANGLE QUOTATION MARK:'AB:171:« +NOT SIGN:'AC:172:¬ +SOFT HYPHEN:'AD:173:­ +REGISTERED SIGN:'AE:174:® +LATIN CAPITAL LETTER Z WITH DOT ABOVE:'AF:379:Ż +DEGREE SIGN:'B0:176:° +PLUS-MINUS SIGN:'B1:177:± +OGONEK:'B2:731:˛ +LATIN SMALL LETTER L WITH STROKE:'B3:322:ł +ACUTE ACCENT:'B4:180:´ +MICRO SIGN:'B5:181:µ +PILCROW SIGN:'B6:182:¶ +MIDDLE DOT:'B7:183:· +CEDILLA:'B8:184:¸ +LATIN SMALL LETTER A WITH OGONEK:'B9:261:ą +LATIN SMALL LETTER S WITH CEDILLA:'BA:351:ş +RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK:'BB:187:» +LATIN CAPITAL LETTER L WITH CARON:'BC:317:Ľ +DOUBLE ACUTE ACCENT:'BD:733:˝ +LATIN SMALL LETTER L WITH CARON:'BE:318:ľ +LATIN SMALL LETTER Z WITH DOT ABOVE:'BF:380:ż +LATIN CAPITAL LETTER R WITH ACUTE:'C0:340:Ŕ +LATIN CAPITAL LETTER A WITH ACUTE:'C1:193:Á +LATIN CAPITAL LETTER A WITH CIRCUMFLEX:'C2:194: +LATIN CAPITAL LETTER A WITH BREVE:'C3:258:Ă +LATIN CAPITAL LETTER A WITH DIAERESIS:'C4:196:Ä +LATIN CAPITAL LETTER L WITH ACUTE:'C5:313:Ĺ +LATIN CAPITAL LETTER C WITH ACUTE:'C6:262:Ć +LATIN CAPITAL LETTER C WITH CEDILLA:'C7:199:Ç +LATIN CAPITAL LETTER C WITH CARON:'C8:268:Č +LATIN CAPITAL LETTER E WITH ACUTE:'C9:201:É +LATIN CAPITAL LETTER E WITH OGONEK:'CA:280:Ę +LATIN CAPITAL LETTER E WITH DIAERESIS:'CB:203:Ë +LATIN CAPITAL LETTER E WITH CARON:'CC:282:Ě +LATIN CAPITAL LETTER I WITH ACUTE:'CD:205:Í +LATIN CAPITAL LETTER I WITH CIRCUMFLEX:'CE:206:Î +LATIN CAPITAL LETTER D WITH CARON:'CF:270:Ď +LATIN CAPITAL LETTER D WITH STROKE:'D0:272:Đ +LATIN CAPITAL LETTER N WITH ACUTE:'D1:323:Ń +LATIN CAPITAL LETTER N WITH CARON:'D2:327:Ň +LATIN CAPITAL LETTER O WITH ACUTE:'D3:211:Ó +LATIN CAPITAL LETTER O WITH CIRCUMFLEX:'D4:212:Ô +LATIN CAPITAL LETTER O WITH DOUBLE ACUTE:'D5:336:Ő +LATIN CAPITAL LETTER O WITH DIAERESIS:'D6:214:Ö +MULTIPLICATION SIGN:'D7:215:× +LATIN CAPITAL LETTER R WITH CARON:'D8:344:Ř +LATIN CAPITAL LETTER U WITH RING ABOVE:'D9:366:Ů +LATIN CAPITAL LETTER U WITH ACUTE:'DA:218:Ú +LATIN CAPITAL LETTER U WITH DOUBLE ACUTE:'DB:368:Ű +LATIN CAPITAL LETTER U WITH DIAERESIS:'DC:220:Ü +LATIN CAPITAL LETTER Y WITH ACUTE:'DD:221:Ý +LATIN CAPITAL LETTER T WITH CEDILLA:'DE:354:Ţ +LATIN SMALL LETTER SHARP S (GERMAN):'DF:223:ß +LATIN SMALL LETTER R WITH ACUTE:'E0:341:ŕ +LATIN SMALL LETTER A WITH ACUTE:'E1:225:á +LATIN SMALL LETTER A WITH CIRCUMFLEX:'E2:226:â +LATIN SMALL LETTER A WITH BREVE:'E3:259:ă +LATIN SMALL LETTER A WITH DIAERESIS:'E4:228:ä +LATIN SMALL LETTER L WITH ACUTE:'E5:314:ĺ +LATIN SMALL LETTER C WITH ACUTE:'E6:263:ć +LATIN SMALL LETTER C WITH CEDILLA:'E7:231:ç +LATIN SMALL LETTER C WITH CARON:'E8:269:č +LATIN SMALL LETTER E WITH ACUTE:'E9:233:é +LATIN SMALL LETTER E WITH OGONEK:'EA:281:ę +LATIN SMALL LETTER E WITH DIAERESIS:'EB:235:ë +LATIN SMALL LETTER E WITH CARON:'EC:283:ě +LATIN SMALL LETTER I WITH ACUTE:'ED:237:í +LATIN SMALL LETTER I WITH CIRCUMFLEX:'EE:238:î +LATIN SMALL LETTER D WITH CARON:'EF:271:ď +LATIN SMALL LETTER D WITH STROKE:'F0:273:đ +LATIN SMALL LETTER N WITH ACUTE:'F1:324:ń +LATIN SMALL LETTER N WITH CARON:'F2:328:ň +LATIN SMALL LETTER O WITH ACUTE:'F3:243:ó +LATIN SMALL LETTER O WITH CIRCUMFLEX:'F4:244:ô +LATIN SMALL LETTER O WITH DOUBLE ACUTE:'F5:337:ő +LATIN SMALL LETTER O WITH DIAERESIS:'F6:246:ö +DIVISION SIGN:'F7:247:÷ +LATIN SMALL LETTER R WITH CARON:'F8:345:ř +LATIN SMALL LETTER U WITH RING ABOVE:'F9:367:ů +LATIN SMALL LETTER U WITH ACUTE:'FA:250:ú +LATIN SMALL LETTER U WITH DOUBLE ACUTE:'FB:369:ű +LATIN SMALL LETTER U WITH DIAERESIS:'FC:252:ü +LATIN SMALL LETTER Y WITH ACUTE:'FD:253:ý +LATIN SMALL LETTER T WITH CEDILLA:'FE:355:ţ +DOT ABOVE (MANDARIN CHINESE LIGHT TONE):'FF:729:˙ + + +CYRILLIC CAPITAL LETTER DJE (SERBOCROATIAN):'80:1026:Ђ +CYRILLIC CAPITAL LETTER GJE:'81:1027:Ѓ +SINGLE LOW-9 QUOTATION MARK:'82:8218:‚ +CYRILLIC SMALL LETTER GJE:'83:1107:ѓ +DOUBLE LOW-9 QUOTATION MARK:'84:8222:„ +HORIZONTAL ELLIPSIS:'85:8230:… +DAGGER:'86:8224:† +DOUBLE DAGGER:'87:8225:‡ +PER MILLE SIGN:'89:8240:‰ +CYRILLIC CAPITAL LETTER LJE:'8A:1033:Љ +SINGLE LEFT-POINTING ANGLE QUOTATION MARK:'8B:8249:‹ +CYRILLIC CAPITAL LETTER NJE:'8C:1034:Њ +CYRILLIC CAPITAL LETTER KJE:'8D:1036:Ќ +CYRILLIC CAPITAL LETTER TSHE (SERBOCROATIAN):'8E:1035:Ћ +CYRILLIC CAPITAL LETTER DZHE:'8F:1039:Џ +CYRILLIC SMALL LETTER DJE (SERBOCROATIAN):'90:1106:ђ +LEFT SINGLE QUOTATION MARK:'91:8216:‘ +RIGHT SINGLE QUOTATION MARK:'92:8217:’ +LEFT DOUBLE QUOTATION MARK:'93:8220:“ +RIGHT DOUBLE QUOTATION MARK:'94:8221:” +BULLET:'95:8226:• +EN DASH:'96:8211:– +EM DASH:'97:8212:— +TRADE MARK SIGN:'99:8482:™ +CYRILLIC SMALL LETTER LJE:'9A:1113:љ +SINGLE RIGHT-POINTING ANGLE QUOTATION MARK:'9B:8250:› +CYRILLIC SMALL LETTER NJE:'9C:1114:њ +CYRILLIC SMALL LETTER KJE:'9D:1116:ќ +CYRILLIC SMALL LETTER TSHE (SERBOCROATIAN):'9E:1115:ћ +CYRILLIC SMALL LETTER DZHE:'9F:1119:џ +NO-BREAK SPACE:'A0:160:  +CYRILLIC CAPITAL LETTER SHORT U (BYELORUSSIAN):'A1:1038:Ў +CYRILLIC SMALL LETTER SHORT U (BYELORUSSIAN):'A2:1118:ў +CYRILLIC CAPITAL LETTER JE:'A3:1032:Ј +CURRENCY SIGN:'A4:164:¤ +CYRILLIC CAPITAL LETTER GHE WITH UPTURN:'A5:1168:Ґ +BROKEN BAR:'A6:166:¦ +SECTION SIGN:'A7:167:§ +CYRILLIC CAPITAL LETTER IO:'A8:1025:Ё +COPYRIGHT SIGN:'A9:169:© +CYRILLIC CAPITAL LETTER UKRAINIAN IE:'AA:1028:Є +LEFT-POINTING DOUBLE ANGLE QUOTATION MARK:'AB:171:« +NOT SIGN:'AC:172:¬ +SOFT HYPHEN:'AD:173:­ +REGISTERED SIGN:'AE:174:® +CYRILLIC CAPITAL LETTER YI (UKRAINIAN):'AF:1031:Ї +DEGREE SIGN:'B0:176:° +PLUS-MINUS SIGN:'B1:177:± +CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I:'B2:1030:І +CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I:'B3:1110:і +CYRILLIC SMALL LETTER GHE WITH UPTURN:'B4:1169:ґ +MICRO SIGN:'B5:181:µ +PILCROW SIGN:'B6:182:¶ +MIDDLE DOT:'B7:183:· +CYRILLIC SMALL LETTER IO:'B8:1105:ё +NUMERO SIGN:'B9:8470:№ +CYRILLIC SMALL LETTER UKRAINIAN IE:'BA:1108:є +RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK:'BB:187:» +CYRILLIC SMALL LETTER JE:'BC:1112:ј +CYRILLIC CAPITAL LETTER DZE:'BD:1029:Ѕ +CYRILLIC SMALL LETTER DZE:'BE:1109:ѕ +CYRILLIC SMALL LETTER YI (UKRAINIAN):'BF:1111:ї +CYRILLIC CAPITAL LETTER A:'C0:1040:А +CYRILLIC CAPITAL LETTER BE:'C1:1041:Б +CYRILLIC CAPITAL LETTER VE:'C2:1042:В +CYRILLIC CAPITAL LETTER GHE:'C3:1043:Г +CYRILLIC CAPITAL LETTER DE:'C4:1044:Д +CYRILLIC CAPITAL LETTER IE:'C5:1045:Е +CYRILLIC CAPITAL LETTER ZHE:'C6:1046:Ж +CYRILLIC CAPITAL LETTER ZE:'C7:1047:З +CYRILLIC CAPITAL LETTER I:'C8:1048:И +CYRILLIC CAPITAL LETTER SHORT I:'C9:1049:Й +CYRILLIC CAPITAL LETTER KA:'CA:1050:К +CYRILLIC CAPITAL LETTER EL:'CB:1051:Л +CYRILLIC CAPITAL LETTER EM:'CC:1052:М +CYRILLIC CAPITAL LETTER EN:'CD:1053:Н +CYRILLIC CAPITAL LETTER O:'CE:1054:О +CYRILLIC CAPITAL LETTER PE:'CF:1055:П +CYRILLIC CAPITAL LETTER ER:'D0:1056:Р +CYRILLIC CAPITAL LETTER ES:'D1:1057:С +CYRILLIC CAPITAL LETTER TE:'D2:1058:Т +CYRILLIC CAPITAL LETTER U:'D3:1059:У +CYRILLIC CAPITAL LETTER EF:'D4:1060:Ф +CYRILLIC CAPITAL LETTER HA:'D5:1061:Х +CYRILLIC CAPITAL LETTER TSE:'D6:1062:Ц +CYRILLIC CAPITAL LETTER CHE:'D7:1063:Ч +CYRILLIC CAPITAL LETTER SHA:'D8:1064:Ш +CYRILLIC CAPITAL LETTER SHCHA:'D9:1065:Щ +CYRILLIC CAPITAL LETTER HARD SIGN:'DA:1066:Ъ +CYRILLIC CAPITAL LETTER YERU:'DB:1067:Ы +CYRILLIC CAPITAL LETTER SOFT SIGN:'DC:1068:Ь +CYRILLIC CAPITAL LETTER E:'DD:1069:Э +CYRILLIC CAPITAL LETTER YU:'DE:1070:Ю +CYRILLIC CAPITAL LETTER YA:'DF:1071:Я +CYRILLIC SMALL LETTER A:'E0:1072:а +CYRILLIC SMALL LETTER BE:'E1:1073:б +CYRILLIC SMALL LETTER VE:'E2:1074:в +CYRILLIC SMALL LETTER GHE:'E3:1075:г +CYRILLIC SMALL LETTER DE:'E4:1076:д +CYRILLIC SMALL LETTER IE:'E5:1077:е +CYRILLIC SMALL LETTER ZHE:'E6:1078:ж +CYRILLIC SMALL LETTER ZE:'E7:1079:з +CYRILLIC SMALL LETTER I:'E8:1080:и +CYRILLIC SMALL LETTER SHORT I:'E9:1081:й +CYRILLIC SMALL LETTER KA:'EA:1082:к +CYRILLIC SMALL LETTER EL:'EB:1083:л +CYRILLIC SMALL LETTER EM:'EC:1084:м +CYRILLIC SMALL LETTER EN:'ED:1085:н +CYRILLIC SMALL LETTER O:'EE:1086:о +CYRILLIC SMALL LETTER PE:'EF:1087:п +CYRILLIC SMALL LETTER ER:'F0:1088:р +CYRILLIC SMALL LETTER ES:'F1:1089:с +CYRILLIC SMALL LETTER TE:'F2:1090:т +CYRILLIC SMALL LETTER U:'F3:1091:у +CYRILLIC SMALL LETTER EF:'F4:1092:ф +CYRILLIC SMALL LETTER HA:'F5:1093:х +CYRILLIC SMALL LETTER TSE:'F6:1094:ц +CYRILLIC SMALL LETTER CHE:'F7:1095:ч +CYRILLIC SMALL LETTER SHA:'F8:1096:ш +CYRILLIC SMALL LETTER SHCHA:'F9:1097:щ +CYRILLIC SMALL LETTER HARD SIGN:'FA:1098:ъ +CYRILLIC SMALL LETTER YERU:'FB:1099:ы +CYRILLIC SMALL LETTER SOFT SIGN:'FC:1100:ь +CYRILLIC SMALL LETTER E:'FD:1101:э +CYRILLIC SMALL LETTER YU:'FE:1102:ю +CYRILLIC SMALL LETTER YA:'FF:1103:я + + +LATIN SMALL LETTER Y WITH DIAERESIS:'00:00:ÿ +EURO SIGN:'80:8364:€ +SINGLE LOW-9 QUOTATION MARK:'82:8218:‚ +LATIN SMALL LETTER F WITH HOOK:'83:402:ƒ +DOUBLE LOW-9 QUOTATION MARK:'84:8222:„ +HORIZONTAL ELLIPSIS:'85:8230:… +DAGGER:'86:8224:† +DOUBLE DAGGER:'87:8225:‡ +MODIFIER LETTER CIRCUMFLEX ACCENT:'88:710:ˆ +PER MILLE SIGN:'89:8240:‰ +LATIN CAPITAL LETTER S WITH CARON:'8A:352:Š +SINGLE LEFT-POINTING ANGLE QUOTATION MARK:'8B:8249:‹ +LATIN CAPITAL LIGATURE OE:'8C:338:Œ +LEFT SINGLE QUOTATION MARK:'91:8216:‘ +RIGHT SINGLE QUOTATION MARK:'92:8217:’ +LEFT DOUBLE QUOTATION MARK:'93:8220:“ +RIGHT DOUBLE QUOTATION MARK:'94:8221:” +BULLET:'95:8226:• +EN DASH:'96:8211:– +EM DASH:'97:8212:— +SMALL TILDE:'98:732:˜ +TRADE MARK SIGN:'99:8482:™ +LATIN SMALL LETTER S WITH CARON:'9A:353:š +SINGLE RIGHT-POINTING ANGLE QUOTATION MARK:'9B:8250:› +LATIN SMALL LIGATURE OE:'9C:339:œ +LATIN CAPITAL LETTER Y WITH DIAERESIS:'9F:376:Ÿ +NO-BREAK SPACE:'A0:160:  +INVERTED EXCLAMATION MARK:'A1:161:¡ +CENT SIGN:'A2:162:¢ +POUND SIGN:'A3:163:£ +CURRENCY SIGN:'A4:164:¤ +YEN SIGN:'A5:165:¥ +BROKEN BAR:'A6:166:¦ +SECTION SIGN:'A7:167:§ +DIAERESIS:'A8:168:¨ +COPYRIGHT SIGN:'A9:169:© +FEMININE ORDINAL INDICATOR:'AA:170:ª +LEFT-POINTING DOUBLE ANGLE QUOTATION MARK:'AB:171:« +NOT SIGN:'AC:172:¬ +SOFT HYPHEN:'AD:173:­ +REGISTERED SIGN:'AE:174:® +MACRON:'AF:175:¯ +DEGREE SIGN:'B0:176:° +PLUS-MINUS SIGN:'B1:177:± +SUPERSCRIPT TWO:'B2:178:² +SUPERSCRIPT THREE:'B3:179:³ +ACUTE ACCENT:'B4:180:´ +MICRO SIGN:'B5:181:µ +PILCROW SIGN:'B6:182:¶ +MIDDLE DOT:'B7:183:· +CEDILLA:'B8:184:¸ +SUPERSCRIPT ONE:'B9:185:¹ +MASCULINE ORDINAL INDICATOR:'BA:186:º +RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK:'BB:187:» +VULGAR FRACTION ONE QUARTER:'BC:188:¼ +VULGAR FRACTION ONE HALF:'BD:189:½ +VULGAR FRACTION THREE QUARTERS:'BE:190:¾ +INVERTED QUESTION MARK:'BF:191:¿ +LATIN CAPITAL LETTER A WITH GRAVE:'C0:192:À +LATIN CAPITAL LETTER A WITH ACUTE:'C1:193:Á +LATIN CAPITAL LETTER A WITH CIRCUMFLEX:'C2:194: +LATIN CAPITAL LETTER A WITH TILDE:'C3:195:à +LATIN CAPITAL LETTER A WITH DIAERESIS:'C4:196:Ä +LATIN CAPITAL LETTER A WITH RING ABOVE:'C5:197:Å +LATIN CAPITAL LETTER AE:'C6:198:Æ +LATIN CAPITAL LETTER C WITH CEDILLA:'C7:199:Ç +LATIN CAPITAL LETTER E WITH GRAVE:'C8:200:È +LATIN CAPITAL LETTER E WITH ACUTE:'C9:201:É +LATIN CAPITAL LETTER E WITH CIRCUMFLEX:'CA:202:Ê +LATIN CAPITAL LETTER E WITH DIAERESIS:'CB:203:Ë +LATIN CAPITAL LETTER I WITH GRAVE:'CC:204:Ì +LATIN CAPITAL LETTER I WITH ACUTE:'CD:205:Í +LATIN CAPITAL LETTER I WITH CIRCUMFLEX:'CE:206:Î +LATIN CAPITAL LETTER I WITH DIAERESIS:'CF:207:Ï +LATIN CAPITAL LETTER ETH (ICELANDIC):'D0:208:Ð +LATIN CAPITAL LETTER N WITH TILDE:'D1:209:Ñ +LATIN CAPITAL LETTER O WITH GRAVE:'D2:210:Ò +LATIN CAPITAL LETTER O WITH ACUTE:'D3:211:Ó +LATIN CAPITAL LETTER O WITH CIRCUMFLEX:'D4:212:Ô +LATIN CAPITAL LETTER O WITH TILDE:'D5:213:Õ +LATIN CAPITAL LETTER O WITH DIAERESIS:'D6:214:Ö +MULTIPLICATION SIGN:'D7:215:× +LATIN CAPITAL LETTER O WITH STROKE:'D8:216:Ø +LATIN CAPITAL LETTER U WITH GRAVE:'D9:217:Ù +LATIN CAPITAL LETTER U WITH ACUTE:'DA:218:Ú +LATIN CAPITAL LETTER U WITH CIRCUMFLEX:'DB:219:Û +LATIN CAPITAL LETTER U WITH DIAERESIS:'DC:220:Ü +LATIN CAPITAL LETTER Y WITH ACUTE:'DD:221:Ý +LATIN CAPITAL LETTER THORN (ICELANDIC):'DE:222:Þ +LATIN SMALL LETTER SHARP S (GERMAN):'DF:223:ß +LATIN SMALL LETTER A WITH GRAVE:'E0:224:à +LATIN SMALL LETTER A WITH ACUTE:'E1:225:á +LATIN SMALL LETTER A WITH CIRCUMFLEX:'E2:226:â +LATIN SMALL LETTER A WITH TILDE:'E3:227:ã +LATIN SMALL LETTER A WITH DIAERESIS:'E4:228:ä +LATIN SMALL LETTER A WITH RING ABOVE:'E5:229:å +LATIN SMALL LETTER AE:'E6:230:æ +LATIN SMALL LETTER C WITH CEDILLA:'E7:231:ç +LATIN SMALL LETTER E WITH GRAVE:'E8:232:è +LATIN SMALL LETTER E WITH ACUTE:'E9:233:é +LATIN SMALL LETTER E WITH CIRCUMFLEX:'EA:234:ê +LATIN SMALL LETTER E WITH DIAERESIS:'EB:235:ë +LATIN SMALL LETTER I WITH GRAVE:'EC:236:ì +LATIN SMALL LETTER I WITH ACUTE:'ED:237:í +LATIN SMALL LETTER I WITH CIRCUMFLEX:'EE:238:î +LATIN SMALL LETTER I WITH DIAERESIS:'EF:239:ï +LATIN SMALL LETTER ETH (ICELANDIC):'F0:240:ð +LATIN SMALL LETTER N WITH TILDE:'F1:241:ñ +LATIN SMALL LETTER O WITH GRAVE:'F2:242:ò +LATIN SMALL LETTER O WITH ACUTE:'F3:243:ó +LATIN SMALL LETTER O WITH CIRCUMFLEX:'F4:244:ô +LATIN SMALL LETTER O WITH TILDE:'F5:245:õ +LATIN SMALL LETTER O WITH DIAERESIS:'F6:246:ö +DIVISION SIGN:'F7:247:÷ +LATIN SMALL LETTER O WITH STROKE:'F8:248:ø +LATIN SMALL LETTER U WITH GRAVE:'F9:249:ù +LATIN SMALL LETTER U WITH ACUTE:'FA:250:ú +LATIN SMALL LETTER U WITH CIRCUMFLEX:'FB:251:û +LATIN SMALL LETTER U WITH DIAERESIS:'FC:252:ü +LATIN SMALL LETTER Y WITH ACUTE:'FD:253:ý +LATIN SMALL LETTER THORN (ICELANDIC):'FE:254:þ +LATIN SMALL LETTER Y WITH DIAERESIS:'FF:255:ÿ +MY UNDEFINED SYMBOL:\'8D:141: +MY UNDEFINED SYMBOL:\'8E:142: +MY UNDEFINED SYMBOL:\'8F:143: +MY UNDEFINED SYMBOL:\'90:144: +MY UNDEFINED SYMBOL:\'9D:157: +MY UNDEFINED SYMBOL:\'9E:158: + + +SINGLE LOW-9 QUOTATION MARK:'82:8218:‚ +LATIN SMALL LETTER F WITH HOOK:'83:402:ƒ +DOUBLE LOW-9 QUOTATION MARK:'84:8222:„ +HORIZONTAL ELLIPSIS:'85:8230:… +DAGGER:'86:8224:† +DOUBLE DAGGER:'87:8225:‡ +PER MILLE SIGN:'89:8240:‰ +SINGLE LEFT-POINTING ANGLE QUOTATION MARK:'8B:8249:‹ +LEFT SINGLE QUOTATION MARK:'91:8216:‘ +RIGHT SINGLE QUOTATION MARK:'92:8217:’ +LEFT DOUBLE QUOTATION MARK:'93:8220:“ +RIGHT DOUBLE QUOTATION MARK:'94:8221:” +BULLET:'95:8226:• +EN DASH:'96:8211:– +EM DASH:'97:8212:— +TRADE MARK SIGN:'99:8482:™ +SINGLE RIGHT-POINTING ANGLE QUOTATION MARK:'9B:8250:› +NO-BREAK SPACE:'A0:160:  +GREEK DIALYTIKA TONOS:'A1:901:΅ +GREEK CAPITAL LETTER ALPHA WITH TONOS:'A2:902:Ά +POUND SIGN:'A3:163:£ +CURRENCY SIGN:'A4:164:¤ +YEN SIGN:'A5:165:¥ +BROKEN BAR:'A6:166:¦ +SECTION SIGN:'A7:167:§ +DIAERESIS:'A8:168:¨ +COPYRIGHT SIGN:'A9:169:© +LEFT-POINTING DOUBLE ANGLE QUOTATION MARK:'AB:171:« +NOT SIGN:'AC:172:¬ +SOFT HYPHEN:'AD:173:­ +REGISTERED SIGN:'AE:174:® +HORIZONTAL BAR:'AF:8213:― +DEGREE SIGN:'B0:176:° +PLUS-MINUS SIGN:'B1:177:± +SUPERSCRIPT TWO:'B2:178:² +SUPERSCRIPT THREE:'B3:179:³ +GREEK TONOS:'B4:900:΄ +MICRO SIGN:'B5:181:µ +PILCROW SIGN:'B6:182:¶ +MIDDLE DOT:'B7:183:· +GREEK CAPITAL LETTER EPSILON WITH TONOS:'B8:904:Έ +GREEK CAPITAL LETTER ETA WITH TONOS:'B9:905:Ή +GREEK CAPITAL LETTER IOTA WITH TONOS:'BA:906:Ί +RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK:'BB:187:» +GREEK CAPITAL LETTER OMICRON WITH TONOS:'BC:908:Ό +VULGAR FRACTION ONE HALF:'BD:189:½ +GREEK CAPITAL LETTER UPSILON WITH TONOS:'BE:910:Ύ +GREEK CAPITAL LETTER OMEGA WITH TONOS:'BF:911:Ώ +GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS:'C0:912:ΐ +GREEK CAPITAL LETTER ALPHA:'C1:913:Α +GREEK CAPITAL LETTER BETA:'C2:914:Β +GREEK CAPITAL LETTER GAMMA:'C3:915:Γ +GREEK CAPITAL LETTER DELTA:'C4:916:Δ +GREEK CAPITAL LETTER EPSILON:'C5:917:Ε +GREEK CAPITAL LETTER ZETA:'C6:918:Ζ +GREEK CAPITAL LETTER ETA:'C7:919:Η +GREEK CAPITAL LETTER THETA:'C8:920:Θ +GREEK CAPITAL LETTER IOTA:'C9:921:Ι +GREEK CAPITAL LETTER KAPPA:'CA:922:Κ +GREEK CAPITAL LETTER LAMDA:'CB:923:Λ +GREEK CAPITAL LETTER MU:'CC:924:Μ +GREEK CAPITAL LETTER NU:'CD:925:Ν +GREEK CAPITAL LETTER XI:'CE:926:Ξ +GREEK CAPITAL LETTER OMICRON:'CF:927:Ο +GREEK CAPITAL LETTER PI:'D0:928:Π +GREEK CAPITAL LETTER RHO:'D1:929:Ρ +GREEK CAPITAL LETTER SIGMA:'D3:931:Σ +GREEK CAPITAL LETTER TAU:'D4:932:Τ +GREEK CAPITAL LETTER UPSILON:'D5:933:Υ +GREEK CAPITAL LETTER PHI:'D6:934:Φ +GREEK CAPITAL LETTER CHI:'D7:935:Χ +GREEK CAPITAL LETTER PSI:'D8:936:Ψ +GREEK CAPITAL LETTER OMEGA:'D9:937:Ω +GREEK CAPITAL LETTER IOTA WITH DIALYTIKA:'DA:938:Ϊ +GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA:'DB:939:Ϋ +GREEK SMALL LETTER ALPHA WITH TONOS:'DC:940:ά +GREEK SMALL LETTER EPSILON WITH TONOS:'DD:941:έ +GREEK SMALL LETTER ETA WITH TONOS:'DE:942:ή +GREEK SMALL LETTER IOTA WITH TONOS:'DF:943:ί +GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS:'E0:944:ΰ +GREEK SMALL LETTER ALPHA:'E1:945:α +GREEK SMALL LETTER BETA:'E2:946:β +GREEK SMALL LETTER GAMMA:'E3:947:γ +GREEK SMALL LETTER DELTA:'E4:948:δ +GREEK SMALL LETTER EPSILON:'E5:949:ε +GREEK SMALL LETTER ZETA:'E6:950:ζ +GREEK SMALL LETTER ETA:'E7:951:η +GREEK SMALL LETTER THETA:'E8:952:θ +GREEK SMALL LETTER IOTA:'E9:953:ι +GREEK SMALL LETTER KAPPA:'EA:954:κ +GREEK SMALL LETTER LAMDA:'EB:955:λ +GREEK SMALL LETTER MU:'EC:956:μ +GREEK SMALL LETTER NU:'ED:957:ν +GREEK SMALL LETTER XI:'EE:958:ξ +GREEK SMALL LETTER OMICRON:'EF:959:ο +GREEK SMALL LETTER PI:'F0:960:π +GREEK SMALL LETTER RHO:'F1:961:ρ +GREEK SMALL LETTER FINAL SIGMA:'F2:962:ς +GREEK SMALL LETTER SIGMA:'F3:963:σ +GREEK SMALL LETTER TAU:'F4:964:τ +GREEK SMALL LETTER UPSILON:'F5:965:υ +GREEK SMALL LETTER PHI:'F6:966:φ +GREEK SMALL LETTER CHI:'F7:967:χ +GREEK SMALL LETTER PSI:'F8:968:ψ +GREEK SMALL LETTER OMEGA:'F9:969:ω +GREEK SMALL LETTER IOTA WITH DIALYTIKA:'FA:970:ϊ +GREEK SMALL LETTER UPSILON WITH DIALYTIKA:'FB:971:ϋ +GREEK SMALL LETTER OMICRON WITH TONOS:'FC:972:ό +GREEK SMALL LETTER UPSILON WITH TONOS:'FD:973:ύ +GREEK SMALL LETTER OMEGA WITH TONOS:'FE:974:ώ + + +SINGLE LOW-9 QUOTATION MARK:'82:8218:‚ +LATIN SMALL LETTER F WITH HOOK:'83:402:ƒ +DOUBLE LOW-9 QUOTATION MARK:'84:8222:„ +HORIZONTAL ELLIPSIS:'85:8230:… +DAGGER:'86:8224:† +DOUBLE DAGGER:'87:8225:‡ +MODIFIER LETTER CIRCUMFLEX ACCENT:'88:710:ˆ +PER MILLE SIGN:'89:8240:‰ +LATIN CAPITAL LETTER S WITH CARON:'8A:352:Š +SINGLE LEFT-POINTING ANGLE QUOTATION MARK:'8B:8249:‹ +LATIN CAPITAL LIGATURE OE:'8C:338:Œ +LEFT SINGLE QUOTATION MARK:'91:8216:‘ +RIGHT SINGLE QUOTATION MARK:'92:8217:’ +LEFT DOUBLE QUOTATION MARK:'93:8220:“ +RIGHT DOUBLE QUOTATION MARK:'94:8221:” +BULLET:'95:8226:• +EN DASH:'96:8211:– +EM DASH:'97:8212:— +SMALL TILDE:'98:732:˜ +TRADE MARK SIGN:'99:8482:™ +LATIN SMALL LETTER S WITH CARON:'9A:353:š +SINGLE RIGHT-POINTING ANGLE QUOTATION MARK:'9B:8250:› +LATIN SMALL LIGATURE OE:'9C:339:œ +LATIN CAPITAL LETTER Y WITH DIAERESIS:'9F:376:Ÿ +NO-BREAK SPACE:'A0:160:  +INVERTED EXCLAMATION MARK:'A1:161:¡ +CENT SIGN:'A2:162:¢ +POUND SIGN:'A3:163:£ +CURRENCY SIGN:'A4:164:¤ +YEN SIGN:'A5:165:¥ +BROKEN BAR:'A6:166:¦ +SECTION SIGN:'A7:167:§ +DIAERESIS:'A8:168:¨ +COPYRIGHT SIGN:'A9:169:© +FEMININE ORDINAL INDICATOR:'AA:170:ª +LEFT-POINTING DOUBLE ANGLE QUOTATION MARK:'AB:171:« +NOT SIGN:'AC:172:¬ +SOFT HYPHEN:'AD:173:­ +REGISTERED SIGN:'AE:174:® +MACRON:'AF:175:¯ +DEGREE SIGN:'B0:176:° +PLUS-MINUS SIGN:'B1:177:± +SUPERSCRIPT TWO:'B2:178:² +SUPERSCRIPT THREE:'B3:179:³ +ACUTE ACCENT:'B4:180:´ +MICRO SIGN:'B5:181:µ +PILCROW SIGN:'B6:182:¶ +MIDDLE DOT:'B7:183:· +CEDILLA:'B8:184:¸ +SUPERSCRIPT ONE:'B9:185:¹ +MASCULINE ORDINAL INDICATOR:'BA:186:º +RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK:'BB:187:» +VULGAR FRACTION ONE QUARTER:'BC:188:¼ +VULGAR FRACTION ONE HALF:'BD:189:½ +VULGAR FRACTION THREE QUARTERS:'BE:190:¾ +INVERTED QUESTION MARK:'BF:191:¿ +LATIN CAPITAL LETTER A WITH GRAVE:'C0:192:À +LATIN CAPITAL LETTER A WITH ACUTE:'C1:193:Á +LATIN CAPITAL LETTER A WITH CIRCUMFLEX:'C2:194: +LATIN CAPITAL LETTER A WITH TILDE:'C3:195:à +LATIN CAPITAL LETTER A WITH DIAERESIS:'C4:196:Ä +LATIN CAPITAL LETTER A WITH RING ABOVE:'C5:197:Å +LATIN CAPITAL LETTER AE:'C6:198:Æ +LATIN CAPITAL LETTER C WITH CEDILLA:'C7:199:Ç +LATIN CAPITAL LETTER E WITH GRAVE:'C8:200:È +LATIN CAPITAL LETTER E WITH ACUTE:'C9:201:É +LATIN CAPITAL LETTER E WITH CIRCUMFLEX:'CA:202:Ê +LATIN CAPITAL LETTER E WITH DIAERESIS:'CB:203:Ë +LATIN CAPITAL LETTER I WITH GRAVE:'CC:204:Ì +LATIN CAPITAL LETTER I WITH ACUTE:'CD:205:Í +LATIN CAPITAL LETTER I WITH CIRCUMFLEX:'CE:206:Î +LATIN CAPITAL LETTER I WITH DIAERESIS:'CF:207:Ï +LATIN CAPITAL LETTER G WITH BREVE:'D0:286:Ğ +LATIN CAPITAL LETTER N WITH TILDE:'D1:209:Ñ +LATIN CAPITAL LETTER O WITH GRAVE:'D2:210:Ò +LATIN CAPITAL LETTER O WITH ACUTE:'D3:211:Ó +LATIN CAPITAL LETTER O WITH CIRCUMFLEX:'D4:212:Ô +LATIN CAPITAL LETTER O WITH TILDE:'D5:213:Õ +LATIN CAPITAL LETTER O WITH DIAERESIS:'D6:214:Ö +MULTIPLICATION SIGN:'D7:215:× +LATIN CAPITAL LETTER O WITH STROKE:'D8:216:Ø +LATIN CAPITAL LETTER U WITH GRAVE:'D9:217:Ù +LATIN CAPITAL LETTER U WITH ACUTE:'DA:218:Ú +LATIN CAPITAL LETTER U WITH CIRCUMFLEX:'DB:219:Û +LATIN CAPITAL LETTER U WITH DIAERESIS:'DC:220:Ü +LATIN CAPITAL LETTER I WITH DOT ABOVE:'DD:304:İ +LATIN CAPITAL LETTER S WITH CEDILLA:'DE:350:Ş +LATIN SMALL LETTER SHARP S (GERMAN):'DF:223:ß +LATIN SMALL LETTER A WITH GRAVE:'E0:224:à +LATIN SMALL LETTER A WITH ACUTE:'E1:225:á +LATIN SMALL LETTER A WITH CIRCUMFLEX:'E2:226:â +LATIN SMALL LETTER A WITH TILDE:'E3:227:ã +LATIN SMALL LETTER A WITH DIAERESIS:'E4:228:ä +LATIN SMALL LETTER A WITH RING ABOVE:'E5:229:å +LATIN SMALL LETTER AE:'E6:230:æ +LATIN SMALL LETTER C WITH CEDILLA:'E7:231:ç +LATIN SMALL LETTER E WITH GRAVE:'E8:232:è +LATIN SMALL LETTER E WITH ACUTE:'E9:233:é +LATIN SMALL LETTER E WITH OGONEK:'EA:281:ę +LATIN SMALL LETTER E WITH DIAERESIS:'EB:235:ë +LATIN SMALL LETTER E WITH DOT ABOVE:'EC:279:ė +LATIN SMALL LETTER I WITH ACUTE:'ED:237:í +LATIN SMALL LETTER I WITH CIRCUMFLEX:'EE:238:î +LATIN SMALL LETTER I WITH MACRON:'EF:299:ī +LATIN SMALL LETTER G WITH BREVE:'F0:287:ğ +LATIN SMALL LETTER N WITH TILDE:'F1:241:ñ +LATIN SMALL LETTER O WITH GRAVE:'F2:242:ò +LATIN SMALL LETTER O WITH ACUTE:'F3:243:ó +LATIN SMALL LETTER O WITH CIRCUMFLEX:'F4:244:ô +LATIN SMALL LETTER O WITH TILDE:'F5:245:õ +LATIN SMALL LETTER O WITH DIAERESIS:'F6:246:ö +DIVISION SIGN:'F7:247:÷ +LATIN SMALL LETTER O WITH STROKE:'F8:248:ø +LATIN SMALL LETTER U WITH GRAVE:'F9:249:ù +LATIN SMALL LETTER U WITH ACUTE:'FA:250:ú +LATIN SMALL LETTER U WITH CIRCUMFLEX:'FB:251:û +LATIN SMALL LETTER U WITH DIAERESIS:'FC:252:ü +LATIN SMALL LETTER DOTLESS I:'FD:305:ı +LATIN SMALL LETTER S WITH CEDILLA:'FE:351:ş +LATIN SMALL LETTER Y WITH DIAERESIS:'FF:255:ÿ + + +SINGLE LOW-9 QUOTATION MARK:'82:8218:‚ +LATIN SMALL LETTER F WITH HOOK:'83:402:ƒ +DOUBLE LOW-9 QUOTATION MARK:'84:8222:„ +HORIZONTAL ELLIPSIS:'85:8230:… +DAGGER:'86:8224:† +DOUBLE DAGGER:'87:8225:‡ +PER MILLE SIGN:'89:8240:‰ +SINGLE LEFT-POINTING ANGLE QUOTATION MARK:'8B:8249:‹ +LEFT SINGLE QUOTATION MARK:'91:8216:‘ +RIGHT SINGLE QUOTATION MARK:'92:8217:’ +LEFT DOUBLE QUOTATION MARK:'93:8220:“ +RIGHT DOUBLE QUOTATION MARK:'94:8221:” +BULLET:'95:8226:• +EN DASH:'96:8211:– +EM DASH:'97:8212:— +TRADE MARK SIGN:'99:8482:™ +SINGLE RIGHT-POINTING ANGLE QUOTATION MARK:'9B:8250:› +NO-BREAK SPACE:'A0:160:  +CENT SIGN:'A2:162:¢ +POUND SIGN:'A3:163:£ +CURRENCY SIGN:'A4:164:¤ +YEN SIGN:'A5:165:¥ +BROKEN BAR:'A6:166:¦ +SECTION SIGN:'A7:167:§ +DIAERESIS:'A8:168:¨ +COPYRIGHT SIGN:'A9:169:© +MULTIPLICATION SIGN:'AA:215:× +LEFT-POINTING DOUBLE ANGLE QUOTATION MARK:'AB:171:« +NOT SIGN:'AC:172:¬ +SOFT HYPHEN:'AD:173:­ +REGISTERED SIGN:'AE:174:® +OVERLINE:'AF:8254:‾ +DEGREE SIGN:'B0:176:° +PLUS-MINUS SIGN:'B1:177:± +SUPERSCRIPT TWO:'B2:178:² +SUPERSCRIPT THREE:'B3:179:³ +ACUTE ACCENT:'B4:180:´ +MICRO SIGN:'B5:181:µ +PILCROW SIGN:'B6:182:¶ +MIDDLE DOT:'B7:183:· +CEDILLA:'B8:184:¸ +SUPERSCRIPT ONE:'B9:185:¹ +DIVISION SIGN:'BA:247:÷ +RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK:'BB:187:» +VULGAR FRACTION ONE QUARTER:'BC:188:¼ +VULGAR FRACTION ONE HALF:'BD:189:½ +VULGAR FRACTION THREE QUARTERS:'BE:190:¾ +DOUBLE LOW LINE:'DF:8215:‗ +HEBREW LETTER ALEF:'E0:1488:א +HEBREW LETTER BET:'E1:1489:ב +HEBREW LETTER GIMEL:'E2:1490:ג +HEBREW LETTER DALET:'E3:1491:ד +HEBREW LETTER HE:'E4:1492:ה +HEBREW LETTER VAV:'E5:1493:ו +HEBREW LETTER ZAYIN:'E6:1494:ז +HEBREW LETTER HET:'E7:1495:ח +HEBREW LETTER TET:'E8:1496:ט +HEBREW LETTER YOD:'E9:1497:י +HEBREW LETTER FINAL KAF:'EA:1498:ך +HEBREW LETTER KAF:'EB:1499:כ +HEBREW LETTER LAMED:'EC:1500:ל +HEBREW LETTER FINAL MEM:'ED:1501:ם +HEBREW LETTER MEM:'EE:1502:מ +HEBREW LETTER FINAL NUN:'EF:1503:ן +HEBREW LETTER NUN:'F0:1504:נ +HEBREW LETTER SAMEKH:'F1:1505:ס +HEBREW LETTER AYIN:'F2:1506:ע +HEBREW LETTER FINAL PE:'F3:1507:ף +HEBREW LETTER PE:'F4:1508:פ +HEBREW LETTER FINAL TSADI:'F5:1509:ץ +HEBREW LETTER TSADI:'F6:1510:צ +HEBREW LETTER QOF:'F7:1511:ק +HEBREW LETTER RESH:'F8:1512:ר +HEBREW LETTER SHIN:'F9:1513:ש +HEBREW LETTER TAV:'FA:1514:ת +LEFT-TO-RIGHT MARK:'FD:8206:‎ +RIGHT-TO-LEFT MARK:'FE:8207:‏ +NUL:'00:0:� + + +ARABIC COMMA:'80:1548:، +ARABIC-INDIC DIGIT ZERO:'81:1632:٠ +SINGLE LOW-9 QUOTATION MARK:'82:8218:‚ +ARABIC-INDIC DIGIT ONE:'83:1633:١ +DOUBLE LOW-9 QUOTATION MARK:'84:8222:„ +HORIZONTAL ELLIPSIS:'85:8230:… +DAGGER:'86:8224:† +DOUBLE DAGGER:'87:8225:‡ +ARABIC-INDIC DIGIT TWO:'88:1634:٢ +ARABIC-INDIC DIGIT THREE:'89:1635:٣ +ARABIC-INDIC DIGIT FOUR:'8A:1636:٤ +SINGLE LEFT-POINTING ANGLE QUOTATION MARK:'8B:8249:‹ +ARABIC-INDIC DIGIT FIVE:'8C:1637:٥ +ARABIC-INDIC DIGIT SIX:'8D:1638:٦ +ARABIC-INDIC DIGIT SEVEN:'8E:1639:٧ +ARABIC-INDIC DIGIT EIGHT:'8F:1640:٨ +ARABIC-INDIC DIGIT NINE:'90:1641:٩ +LEFT SINGLE QUOTATION MARK:'91:8216:‘ +RIGHT SINGLE QUOTATION MARK:'92:8217:’ +LEFT DOUBLE QUOTATION MARK:'93:8220:“ +RIGHT DOUBLE QUOTATION MARK:'94:8221:” +BULLET:'95:8226:• +EN DASH:'96:8211:– +EM DASH:'97:8212:— +ARABIC SEMICOLON:'98:1563:؛ +TRADE MARK SIGN:'99:8482:™ +ARABIC QUESTION MARK:'9A:1567:؟ +SINGLE RIGHT-POINTING ANGLE QUOTATION MARK:'9B:8250:› +ARABIC LETTER HAMZA:'9C:1569:ء +ARABIC LETTER ALEF WITH MADDA ABOVE:'9D:1570:آ +ARABIC LETTER ALEF WITH HAMZA ABOVE:'9E:1571:أ +LATIN CAPITAL LETTER Y WITH DIAERESIS:'9F:376:Ÿ +NO-BREAK SPACE:'A0:160:  +ARABIC LETTER WAW WITH HAMZA ABOVE:'A1:1572:ؤ +ARABIC LETTER ALEF WITH HAMZA BELOW:'A2:1573:إ +POUND SIGN:'A3:163:£ +CURRENCY SIGN:'A4:164:¤ +ARABIC LETTER YEH WITH HAMZA ABOVE:'A5:1574:ئ +BROKEN BAR:'A6:166:¦ +SECTION SIGN:'A7:167:§ +ARABIC LETTER ALEF:'A8:1575:ا +COPYRIGHT SIGN:'A9:169:© +ARABIC LETTER BEH:'AA:1576:ب +LEFT-POINTING DOUBLE ANGLE QUOTATION MARK:'AB:171:« +NOT SIGN:'AC:172:¬ +SOFT HYPHEN:'AD:173:­ +REGISTERED SIGN:'AE:174:® +ARABIC LETTER PEH:'AF:1662:پ +DEGREE SIGN:'B0:176:° +PLUS-MINUS SIGN:'B1:177:± +ARABIC LETTER TEH MARBUTA:'B2:1577:ة +ARABIC LETTER TEH:'B3:1578:ت +ARABIC LETTER THEH:'B4:1579:ث +MICRO SIGN:'B5:181:µ +PILCROW SIGN:'B6:182:¶ +MIDDLE DOT:'B7:183:· +ARABIC LETTER JEEM:'B8:1580:ج +ARABIC LETTER TCHEH:'B9:1670:چ +ARABIC LETTER HAH:'BA:1581:ح +RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK:'BB:187:» +ARABIC LETTER KHAH:'BC:1582:خ +ARABIC LETTER DAL:'BD:1583:د +ARABIC LETTER THAL:'BE:1584:ذ +ARABIC LETTER REH:'BF:1585:ر +LATIN CAPITAL LETTER A WITH GRAVE:'C0:192:À +ARABIC LETTER ZAIN:'C1:1586:ز +LATIN CAPITAL LETTER A WITH CIRCUMFLEX:'C2:194: +ARABIC LETTER JEH:'C3:1688:ژ +ARABIC LETTER SEEN:'C4:1587:س +ARABIC LETTER SHEEN:'C5:1588:ش +ARABIC LETTER SAD:'C6:1589:ص +LATIN CAPITAL LETTER C WITH CEDILLA:'C7:199:Ç +LATIN CAPITAL LETTER E WITH GRAVE:'C8:200:È +LATIN CAPITAL LETTER E WITH ACUTE:'C9:201:É +LATIN CAPITAL LETTER E WITH CIRCUMFLEX:'CA:202:Ê +LATIN CAPITAL LETTER E WITH DIAERESIS:'CB:203:Ë +ARABIC LETTER DAD:'CC:1590:ض +ARABIC LETTER TAH:'CD:1591:ط +LATIN CAPITAL LETTER I WITH CIRCUMFLEX:'CE:206:Î +LATIN CAPITAL LETTER I WITH DIAERESIS:'CF:207:Ï +BOPOMOFO LETTER ZH:'D0:12563:ㄓ +ARABIC LETTER AIN:'D1:1593:ع +ARABIC LETTER GHAIN:'D2:1594:غ +ARABIC TATWEEL:'D3:1600:ـ +LATIN CAPITAL LETTER O WITH CIRCUMFLEX:'D4:212:Ô +ARABIC LETTER FEH:'D5:1601:ف +ARABIC LETTER QAF:'D6:1602:ق +MULTIPLICATION SIGN:'D7:215:× +ARABIC LETTER KAF:'D8:1603:ك +LATIN CAPITAL LETTER U WITH GRAVE:'D9:217:Ù +ARABIC LETTER GAF:'DA:1711:گ +LATIN CAPITAL LETTER U WITH CIRCUMFLEX:'DB:219:Û +LATIN CAPITAL LETTER U WITH DIAERESIS:'DC:220:Ü +ARABIC LETTER LAM:'DD:1604:ل +ARABIC LETTER MEEM:'DE:1605:م +ARABIC LETTER NOON:'DF:1606:ن +LATIN SMALL LETTER A WITH GRAVE:'E0:224:à +ARABIC LETTER HEH:'E1:1607:ه +LATIN SMALL LETTER A WITH CIRCUMFLEX:'E2:226:â +ARABIC LETTER HAH WITH HAMZA ABOVE:'E3:1665:ځ +ARABIC LETTER WAW:'E4:1608:و +ARABIC LETTER ALEF MAKSURA:'E5:1609:ى +ARABIC LETTER YEH:'E6:1610:ي +LATIN SMALL LETTER C WITH CEDILLA:'E7:231:ç +LATIN SMALL LETTER E WITH GRAVE:'E8:232:è +LATIN SMALL LETTER E WITH ACUTE:'E9:233:é +LATIN SMALL LETTER E WITH CIRCUMFLEX:'EA:234:ê +LATIN SMALL LETTER E WITH DIAERESIS:'EB:235:ë +ARABIC FATHATAN:'EC:1611:ً +ARABIC DAMMATAN:'ED:1612:ٌ +LATIN SMALL LETTER I WITH CIRCUMFLEX:'EE:238:î +LATIN SMALL LETTER I WITH DIAERESIS:'EF:239:ï +ARABIC KASRATAN:'F0:1613:ٍ +ARABIC FATHA:'F1:1614:َ +ARABIC DAMMA:'F2:1615:ُ +ARABIC KASRA:'F3:1616:ِ +LATIN SMALL LETTER O WITH CIRCUMFLEX:'F4:244:ô +ARABIC SHADDA:'F5:1617:ّ +ARABIC SUKUN:'F6:1618:ْ +DIVISION SIGN:'F7:247:÷ +LATIN SMALL LETTER U WITH GRAVE:'F9:249:ù +LATIN SMALL LETTER U WITH CIRCUMFLEX:'FB:251:û +LATIN SMALL LETTER U WITH DIAERESIS:'FC:252:ü +LEFT-TO-RIGHT MARK:'FD:8206:‎ +RIGHT-TO-LEFT MARK:'FE:8207:‏ +LATIN SMALL LETTER Y WITH DIAERESIS:'FF:255:ÿ + + +SINGLE LOW-9 QUOTATION MARK:'82:8218:‚ +DOUBLE LOW-9 QUOTATION MARK:'84:8222:„ +HORIZONTAL ELLIPSIS:'85:8230:… +DAGGER:'86:8224:† +DOUBLE DAGGER:'87:8225:‡ +PER MILLE SIGN:'89:8240:‰ +SINGLE LEFT-POINTING ANGLE QUOTATION MARK:'8B:8249:‹ +LEFT SINGLE QUOTATION MARK:'91:8216:‘ +RIGHT SINGLE QUOTATION MARK:'92:8217:’ +LEFT DOUBLE QUOTATION MARK:'93:8220:“ +RIGHT DOUBLE QUOTATION MARK:'94:8221:” +BULLET:'95:8226:• +EN DASH:'96:8211:– +EM DASH:'97:8212:— +TRADE MARK SIGN:'99:8482:™ +SINGLE RIGHT-POINTING ANGLE QUOTATION MARK:'9B:8250:› +NO-BREAK SPACE:'A0:160:  +CENT SIGN:'A2:162:¢ +POUND SIGN:'A3:163:£ +CURRENCY SIGN:'A4:164:¤ +BROKEN BAR:'A6:166:¦ +SECTION SIGN:'A7:167:§ +LATIN CAPITAL LETTER O WITH STROKE:'A8:216:Ø +COPYRIGHT SIGN:'A9:169:© +LATIN CAPITAL LETTER R WITH CEDILLA:'AA:342:Ŗ +LEFT-POINTING DOUBLE ANGLE QUOTATION MARK:'AB:171:« +NOT SIGN:'AC:172:¬ +SOFT HYPHEN:'AD:173:­ +REGISTERED SIGN:'AE:174:® +LATIN CAPITAL LETTER AE:'AF:198:Æ +DEGREE SIGN:'B0:176:° +PLUS-MINUS SIGN:'B1:177:± +SUPERSCRIPT TWO:'B2:178:² +SUPERSCRIPT THREE:'B3:179:³ +MICRO SIGN:'B5:181:µ +PILCROW SIGN:'B6:182:¶ +MIDDLE DOT:'B7:183:· +LATIN SMALL LETTER O WITH STROKE:'B8:248:ø +SUPERSCRIPT ONE:'B9:185:¹ +LATIN SMALL LETTER R WITH CEDILLA:'BA:343:ŗ +RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK:'BB:187:» +VULGAR FRACTION ONE QUARTER:'BC:188:¼ +VULGAR FRACTION ONE HALF:'BD:189:½ +VULGAR FRACTION THREE QUARTERS:'BE:190:¾ +LATIN SMALL LETTER AE:'BF:230:æ +LATIN CAPITAL LETTER A WITH OGONEK:'C0:260:Ą +LATIN CAPITAL LETTER I WITH OGONEK:'C1:302:Į +LATIN CAPITAL LETTER A WITH MACRON:'C2:256:Ā +LATIN CAPITAL LETTER C WITH ACUTE:'C3:262:Ć +LATIN CAPITAL LETTER A WITH DIAERESIS:'C4:196:Ä +LATIN CAPITAL LETTER A WITH RING ABOVE:'C5:197:Å +LATIN CAPITAL LETTER E WITH OGONEK:'C6:280:Ę +LATIN CAPITAL LETTER E WITH MACRON:'C7:274:Ē +LATIN CAPITAL LETTER C WITH CARON:'C8:268:Č +LATIN CAPITAL LETTER E WITH ACUTE:'C9:201:É +LATIN CAPITAL LETTER Z WITH ACUTE:'CA:377:Ź +LATIN CAPITAL LETTER E WITH DOT ABOVE:'CB:278:Ė +LATIN CAPITAL LETTER G WITH CEDILLA:'CC:290:Ģ +LATIN CAPITAL LETTER K WITH CEDILLA:'CD:310:Ķ +LATIN CAPITAL LETTER I WITH MACRON:'CE:298:Ī +LATIN CAPITAL LETTER L WITH CEDILLA:'CF:315:Ļ +LATIN CAPITAL LETTER S WITH CARON:'D0:352:Š +LATIN CAPITAL LETTER N WITH ACUTE:'D1:323:Ń +LATIN CAPITAL LETTER N WITH CEDILLA:'D2:325:Ņ +LATIN CAPITAL LETTER O WITH ACUTE:'D3:211:Ó +LATIN CAPITAL LETTER O WITH MACRON:'D4:332:Ō +LATIN CAPITAL LETTER O WITH TILDE:'D5:213:Õ +LATIN CAPITAL LETTER O WITH DIAERESIS:'D6:214:Ö +MULTIPLICATION SIGN:'D7:215:× +LATIN CAPITAL LETTER U WITH OGONEK:'D8:370:Ų +LATIN CAPITAL LETTER L WITH STROKE:'D9:321:Ł +LATIN CAPITAL LETTER S WITH ACUTE:'DA:346:Ś +LATIN CAPITAL LETTER U WITH MACRON:'DB:362:Ū +LATIN CAPITAL LETTER U WITH DIAERESIS:'DC:220:Ü +LATIN CAPITAL LETTER Z WITH DOT ABOVE:'DD:379:Ż +LATIN CAPITAL LETTER Z WITH CARON:'DE:381:Ž +LATIN SMALL LETTER SHARP S (GERMAN):'DF:223:ß +LATIN SMALL LETTER A WITH OGONEK:'E0:261:ą +LATIN SMALL LETTER I WITH OGONEK:'E1:303:į +LATIN SMALL LETTER A WITH MACRON:'E2:257:ā +LATIN SMALL LETTER C WITH ACUTE:'E3:263:ć +LATIN SMALL LETTER A WITH DIAERESIS:'E4:228:ä +LATIN SMALL LETTER A WITH RING ABOVE:'E5:229:å +LATIN SMALL LETTER E WITH OGONEK:'E6:281:ę +LATIN SMALL LETTER E WITH MACRON:'E7:275:ē +LATIN SMALL LETTER C WITH CARON:'E8:269:č +LATIN SMALL LETTER E WITH ACUTE:'E9:233:é +LATIN SMALL LETTER Z WITH ACUTE:'EA:378:ź +LATIN SMALL LETTER E WITH DOT ABOVE:'EB:279:ė +LATIN SMALL LETTER G WITH CEDILLA:'EC:291:ģ +LATIN SMALL LETTER K WITH CEDILLA:'ED:311:ķ +LATIN SMALL LETTER I WITH MACRON:'EE:299:ī +LATIN SMALL LETTER L WITH CEDILLA:'EF:316:ļ +LATIN SMALL LETTER S WITH CARON:'F0:353:š +LATIN SMALL LETTER N WITH ACUTE:'F1:324:ń +LATIN SMALL LETTER N WITH CEDILLA:'F2:326:ņ +LATIN SMALL LETTER O WITH ACUTE:'F3:243:ó +LATIN SMALL LETTER O WITH MACRON:'F4:333:ō +LATIN SMALL LETTER O WITH TILDE:'F5:245:õ +LATIN SMALL LETTER O WITH DIAERESIS:'F6:246:ö +DIVISION SIGN:'F7:247:÷ +LATIN SMALL LETTER U WITH OGONEK:'F8:371:ų +LATIN SMALL LETTER L WITH STROKE:'F9:322:ł +LATIN SMALL LETTER S WITH ACUTE:'FA:347:ś +LATIN SMALL LETTER U WITH MACRON:'FB:363:ū +LATIN SMALL LETTER U WITH DIAERESIS:'FC:252:ü +LATIN SMALL LETTER Z WITH DOT ABOVE:'FD:380:ż +LATIN SMALL LETTER Z WITH CARON:'FE:382:ž + +#mac_roman + +LATIN CAPITAL LETTER A WITH DIAERESIS:'80:196:Ä +LATIN CAPITAL LETTER A WITH RING ABOVE:'81:197:Å +LATIN CAPITAL LETTER C WITH CEDILLA:'82:199:Ç +LATIN CAPITAL LETTER E WITH ACUTE:'83:201:É +LATIN CAPITAL LETTER N WITH TILDE:'84:209:Ñ +LATIN CAPITAL LETTER O WITH DIAERESIS:'85:214:Ö +LATIN CAPITAL LETTER U WITH DIAERESIS:'86:220:Ü +LATIN SMALL LETTER A WITH ACUTE:'87:225:á +LATIN SMALL LETTER A WITH GRAVE:'88:224:à +LATIN SMALL LETTER A WITH CIRCUMFLEX:'89:226:â +LATIN SMALL LETTER A WITH DIAERESIS:'8A:228:ä +LATIN SMALL LETTER A WITH TILDE:'8B:227:ã +LATIN SMALL LETTER A WITH RING ABOVE:'8C:229:å +LATIN SMALL LETTER C WITH CEDILLA:'8D:231:ç +LATIN SMALL LETTER E WITH ACUTE:'8E:233:é +LATIN SMALL LETTER E WITH GRAVE:'8F:232:è +LATIN SMALL LETTER E WITH CIRCUMFLEX:'90:234:ê +LATIN SMALL LETTER E WITH DIAERESIS:'91:235:ë +LATIN SMALL LETTER I WITH ACUTE:'92:237:í +LATIN SMALL LETTER I WITH GRAVE:'93:236:ì +LATIN SMALL LETTER I WITH CIRCUMFLEX:'94:238:î +LATIN SMALL LETTER I WITH DIAERESIS:'95:239:ï +LATIN SMALL LETTER N WITH TILDE:'96:241:ñ +LATIN SMALL LETTER O WITH ACUTE:'97:243:ó +LATIN SMALL LETTER O WITH GRAVE:'98:242:ò +LATIN SMALL LETTER O WITH CIRCUMFLEX:'99:244:ô +LATIN SMALL LETTER O WITH DIAERESIS:'9A:246:ö +LATIN SMALL LETTER O WITH TILDE:'9B:245:õ +LATIN SMALL LETTER U WITH ACUTE:'9C:250:ú +LATIN SMALL LETTER U WITH GRAVE:'9D:249:ù +LATIN SMALL LETTER U WITH CIRCUMFLEX:'9E:251:û +LATIN SMALL LETTER U WITH DIAERESIS:'9F:252:ü +DAGGER:'A0:8224:† +DEGREE SIGN:'A1:176:° +CENT SIGN:'A2:162:¢ +POUND SIGN:'A3:163:£ +SECTION SIGN:'A4:167:§ +BULLET:'A5:8226:• +PILCROW SIGN:'A6:182:¶ +LATIN SMALL LETTER SHARP S:'A7:223:ß +REGISTERED SIGN:'A8:174:® +COPYRIGHT SIGN:'A9:169:© +TRADE MARK SIGN:'AA:8482:™ +ACUTE ACCENT:'AB:180:´ +DIAERESIS:'AC:168:¨ +NOT EQUAL TO:'AD:8800:≠ +LATIN CAPITAL LETTER AE:'AE:198:Æ +LATIN CAPITAL LETTER O WITH STROKE:'AF:216:Ø +INFINITY:'B0:8734:∞ +PLUS-MINUS SIGN:'B1:177:± +LESS-THAN OR EQUAL TO:'B2:8804:≤ +GREATER-THAN OR EQUAL TO:'B3:8805:≥ +YEN SIGN:'B4:165:¥ +MICRO SIGN:'B5:181:µ +PARTIAL DIFFERENTIAL:'B6:8706:∂ +BULLET:'B7:8226:• +N-ARY PRODUCT:'B8:8719:∏ +GREEK SMALL LETTER PI:'B9:960:π +INTEGRAL:'BA:8747:∫ +FEMININE ORDINAL INDICATOR:'BB:170:ª +MASCULINE ORDINAL INDICATOR:'BC:186:º +GREEK CAPITAL LETTER OMEGA:'BD:937:Ω +LATIN SMALL LETTER AE:'BE:230:æ +LATIN SMALL LETTER O WITH STROKE:'BF:248:ø +INVERTED QUESTION MARK:'C0:191:¿ +INVERTED EXCLAMATION MARK:'C1:161:¡ +NOT SIGN:'C2:172:¬ +SQUARE ROOT:'C3:8730:√ +LATIN SMALL LETTER F WITH HOOK:'C4:402:ƒ +ALMOST EQUAL TO:'C5:8776:≈ +INCREMENT:'C6:8710:∆ +LEFT-POINTING DOUBLE ANGLE QUOTATION MARK:'C7:171:« +RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK:'C8:187:» +HORIZONTAL ELLIPSIS:'C9:8230:… +NO-BREAK SPACE:'CA:160:  +LATIN CAPITAL LETTER A WITH GRAVE:'CB:192:À +LATIN CAPITAL LETTER A WITH TILDE:'CC:195:à +LATIN CAPITAL LETTER O WITH TILDE:'CD:213:Õ +LATIN CAPITAL LIGATURE OE:'CE:338:Œ +LATIN SMALL LIGATURE OE:'CF:339:œ +EN DASH:'D0:8211:– +EM DASH:'D1:8212:— +LEFT DOUBLE QUOTATION MARK:'D2:8220:“ +RIGHT DOUBLE QUOTATION MARK:'D3:8221:” +LEFT SINGLE QUOTATION MARK:'D4:8216:‘ +RIGHT SINGLE QUOTATION MARK:'D5:8217:’ +DIVISION SIGN:'D6:247:÷ +LOZENGE:'D7:9674:◊ +LATIN SMALL LETTER Y WITH DIAERESIS:'D8:255:ÿ +LATIN CAPITAL LETTER Y WITH DIAERESIS:'D9:376:Ÿ +FRACTION SLASH:'DA:8260:⁄ +EURO SIGN:'DB:8364:€ +SINGLE LEFT-POINTING ANGLE QUOTATION MARK:'DC:8249:‹ +SINGLE RIGHT-POINTING ANGLE QUOTATION MARK:'DD:8250:› +LATIN SMALL LIGATURE FI:'DE:64257:fi +LATIN SMALL LIGATURE FL:'DF:64258:fl +DOUBLE DAGGER:'E0:8225:‡ +MIDDLE DOT:'E1:183:· +SINGLE LOW-9 QUOTATION MARK:'E2:8218:‚ +DOUBLE LOW-9 QUOTATION MARK:'E3:8222:„ +PER MILLE SIGN:'E4:8240:‰ +LATIN CAPITAL LETTER A WITH CIRCUMFLEX:'E5:194: +LATIN CAPITAL LETTER E WITH CIRCUMFLEX:'E6:202:Ê +LATIN CAPITAL LETTER A WITH ACUTE:'E7:193:Á +LATIN CAPITAL LETTER E WITH DIAERESIS:'E8:203:Ë +LATIN CAPITAL LETTER E WITH GRAVE:'E9:200:È +LATIN CAPITAL LETTER I WITH ACUTE:'EA:205:Í +LATIN CAPITAL LETTER I WITH CIRCUMFLEX:'EB:206:Î +LATIN CAPITAL LETTER I WITH DIAERESIS:'EC:207:Ï +LATIN CAPITAL LETTER I WITH GRAVE:'ED:204:Ì +LATIN CAPITAL LETTER O WITH ACUTE:'EE:211:Ó +LATIN CAPITAL LETTER O WITH CIRCUMFLEX:'EF:212:Ô +APPLE LOGO:'F0:63743: +LATIN CAPITAL LETTER O WITH GRAVE:'F1:210:Ò +LATIN CAPITAL LETTER U WITH ACUTE:'F2:218:Ú +LATIN CAPITAL LETTER U WITH CIRCUMFLEX:'F3:219:Û +LATIN CAPITAL LETTER U WITH GRAVE:'F4:217:Ù +LATIN SMALL LETTER DOTLESS I:'F5:305:ı +MODIFIER LETTER CIRCUMFLEX ACCENT:'F6:710:ˆ +SMALL TILDE:'F7:732:˜ +MACRON:'F8:175:¯ +BREVE:'F9:728:˘ +DOT ABOVE:'FA:729:˙ +RING ABOVE:'FB:730:˚ +CEDILLA:'FC:184:¸ +DOUBLE ACUTE ACCENT:'FD:733:˝ +OGONEK:'FE:731:˛ +CARON:'FF:711:ˇ + + +LATIN SMALL LETTER A:'61:97:'41 +LATIN SMALL LETTER B:'62:98:'42 +LATIN SMALL LETTER C:'63:99:'43 +LATIN SMALL LETTER D:'64:100:'44 +LATIN SMALL LETTER E:'65:101:'45 +LATIN SMALL LETTER F:'66:102:'46 +LATIN SMALL LETTER G:'67:103:'47 +LATIN SMALL LETTER H:'68:104:48 +LATIN SMALL LETTER I:'69:105:'49 +LATIN SMALL LETTER J:'6A:106:'4a +LATIN SMALL LETTER K:'6B:107:'4b +LATIN SMALL LETTER L:'6C:108:'4c +LATIN SMALL LETTER M:'6D:109:'4d +LATIN SMALL LETTER N:'6E:110:'4e +LATIN SMALL LETTER O:'6F:111:'4f +LATIN SMALL LETTER P:'70:112:'50 +LATIN SMALL LETTER Q:'71:113:'51 +LATIN SMALL LETTER R:'72:114:'52 +LATIN SMALL LETTER S:'73:115:'53 +LATIN SMALL LETTER T:'74:116:'54 +LATIN SMALL LETTER U:'75:117:'55 +LATIN SMALL LETTER V:'76:118:'56 +LATIN SMALL LETTER W:'77:119:'57 +LATIN SMALL LETTER X:'78:120:'58 +LATIN SMALL LETTER Y:'79:121:'59 +LATIN SMALL LETTER Z:'7A:122:'5a +NO UNICODE VALUE:'87:135:\'E7 +NO UNICODE VALUE:'8E:142:\'83 +NO UNICODE VALUE:'EA:234:\'92 +NO UNICODE VALUE:'97:151:\'EE +NO UNICODE VALUE:'9C:156:\'F2 +NO UNICODE VALUE:'88:136:\'CB +NO UNICODE VALUE:'8F:143:\'E9 +NO UNICODE VALUE:'93:147:\'ED +NO UNICODE VALUE:'98:152:\'F1 +NO UNICODE VALUE:'9D:157:\'F4 +NO UNICODE VALUE:'89:137:\'D5 +NO UNICODE VALUE:'90:144:\'E6 +NO UNICODE VALUE:'94:148:\'EB +NO UNICODE VALUE:'99:153:\'EF +NO UNICODE VALUE:'9E:158:\'F3 +NO UNICODE VALUE:'BF:191:\'AF +NO UNICODE VALUE:'96:150:\'84 +NO UNICODE VALUE:'9B:155:\'CD +NO UNICODE VALUE:'8B:139:\'CC +NO UNICODE VALUE:'8A:138:\'80 +NO UNICODE VALUE:'91:145:\'E8 +NO UNICODE VALUE:'95:149:\'EC +NO UNICODE VALUE:'9A:154:\'85 +NO UNICODE VALUE:'9F:159:\'86 +NO UNICODE VALUE:'8D:141:\'82 +NO UNICODE VALUE:'8C:140:\'81 + + +LATIN SMALL LETTER A:a:97:A +LATIN SMALL LETTER B:b:98:B +LATIN SMALL LETTER C:c:99:C +LATIN SMALL LETTER D:d:100:D +LATIN SMALL LETTER E:e:101:E +LATIN SMALL LETTER F:f:102:F +LATIN SMALL LETTER G:g:103:G +LATIN SMALL LETTER H:h:104:H +LATIN SMALL LETTER I:i:105:I +LATIN SMALL LETTER J:j:106:J +LATIN SMALL LETTER K:k:107:K +LATIN SMALL LETTER L:l:108:L +LATIN SMALL LETTER M:m:109:M +LATIN SMALL LETTER N:n:110:N +LATIN SMALL LETTER O:o:111:O +LATIN SMALL LETTER P:p:112:P +LATIN SMALL LETTER Q:q:113:Q +LATIN SMALL LETTER R:r:114:R +LATIN SMALL LETTER S:s:115:S +LATIN SMALL LETTER T:t:116:T +LATIN SMALL LETTER U:u:117:U +LATIN SMALL LETTER V:v:118:V +LATIN SMALL LETTER W:w:119:W +LATIN SMALL LETTER X:x:120:X +LATIN SMALL LETTER Y:y:121:Y +LATIN SMALL LETTER Z:z:122:Z + + +MY UNDEFINED SYMBOL:'C3:00: +SPACE:'20:32: +EXCLAMATION MARK:'21:33:! +FOR ALL:'22:8704:∀ +NUMBER SIGN:'23:35:# +THERE EXISTS:'24:8707:∃ +PERCENTAGE SIGN:'25:37:% +AMPERSAND:'26:38:& +CONTAINS AS A MEMBER:'27:8715:∋ +LEFT PARENTHESIS:'28:40:( +RIGHT PERENTHESIS:'29:41:) +ASTERISK OPERATOR:'2A:8727:∗ +PLUS SIGN:'2B:43:+ +COMMA:'2C:44:, +MINUS SIGN:'2D:8722:− +FULL STOP:'2E:46:. +DIVISION SLASH:'2F:8725:∕ +DIGIT ZERO:'30:48:0 +DIGIT ONE:'31:49:1 +DIGIT TWO:'32:50:2 +DIGIT THREE:'33:51:3 +DIGIT FOUR:'34:52:4 +DIGIT FIVE:'35:53:5 +DIGIT SIX:'36:54:6 +DIGIT SEVEN:'37:55:7 +DIGIT EIGHT:'38:56:8 +DIGIT NINE:'39:57:9 +RATIO:'3A:8758:∶ +SEMICOLON:'3B:59:; +LESS-THAN SIGN:'3C:60:< +EQUALS SIGN TO:'3D:61:= +GREATER-THAN SIGN:'3E:62:> +QUESTION MARK:'3F:63:? +APPROXTIMATELY EQUAL TO:'40:8773:≅ +GREEK CAPITOL LETTER ALPHA:'41:913:Α +GREEK CAPAITOL LETTER BETA:'42:914:Β +GREEK CAPITOL LETTER CHI:'43:935:Χ +GREEK CAPITOL LETTER DELTA:'44:916:Δ +GREEK CAPITOL LETTER EPSILON:'45:917:Ε +GREEK CAPITOL LETTER PHI:'46:934:Φ +GREEK CAPITOL LETTER GAMMA:'47:915:Γ +GREEK CAPITOL LETTER ETA:'48:919:Η +GREEK CAPITOL LETTER ITOA:'49:913:Α +GREEK THETA SYMBOL:'4A:977:ϑ +GREEK CAPITOL LETTER KAPPA:'4B:922:Κ +GREEK CAPITOL LETTER LAMBDA:'4C:923:Λ +GREEK CAPITOL LETTER MU:'4D:924:Μ +GREEK CAPITOL LETTER NU:'4E:925:Ν +GREEK CAPITOL LETTER OMICRON:'4F:927:Ο +GREEK CAPITAL LETTER PI:'50:928:Π +GREEK CAPITOL LETTER THETA:'51:920:Θ +GREEK CAPITOL LETTER RHO:'52:929:Ρ +GREEK CAPITOL LETTER SIGMA:'53:931:Σ +GREEK CAPITOL LETTER TAU:'54:932:Τ +GREEK CAPITOL LETTER UPSILON:'55:933:Υ +GREEK LETTER STIGMA:'56:986:Ϛ +GREEK CAPITOL LETTER OMEGA:'57:937:Ω +GREEK CAPITOL LETTER XI:'58:926:Ξ +GREEK CAPITOL LETTER PSI:'59:936:Ψ +GREEK CAPITOL LETTER ZETA:'5A:918:Ζ +LEFT SQUARE BRACKET:'5B:91:[ +THEREFORE:'5C:8756:∴ +RIGHT SQUARE BRACKET:'5D:93:] +UP TACK:'5E:8869:⊥ +MODIFIER LETTER LOW MACRON:'5F:717:ˍ +MODIFIER LETTER MACRON:'60:713:ˉ +GREEK SMALL LETTER ALPHA:'61:945:α +GREEK SMALL LETTER BETA:'62:946:β +GREEK SMALL LETTER CHI:'63:967:χ +GREEK SMALL LETTER DELTA:'64:948:δ +GREEK SMALL LETTER EPSILON:'65:949:ε +GREEK PHI SYMBOL:'66:981:ϕ +GREEK MSALL LETTER DELTA:'67:947:γ +GREEK SMALL LETTER ETA:'68:951:η +GREEK SMALL LETTER IOTA:'69:953:ι +GREEK SMALL LETTER PHI:'6A:966:φ +GREEK SMALL LETTER KAPPA:'6B:954:κ +GREEK SMALL LETTER LAMDA:'6C:955:λ +GREEK SMALL LETTER MU:'6D:956:μ +GREEK SMALL LETTER NU:'6E:957:ν +GREEK SMALL LETTER OMICRON:'6F:959:ο +GREEK SMALL LETTER PI:'70:960:π +GREEK SMALL LETTER THETA:'71:952:θ +GREEK SMALL LETTER RHO:'72:961:ρ +GREEK SMALL LETTER SIGMA:'73:963:σ +GREEK SMALL LETTER TAU:'74:964:τ +GREEK SMALL LETTER UPSILON:'75:965:υ +GREEK PI SYMBOL:'76:982:ϖ +GREEK SMALL LETTER OMEGA:'77:969:ω +GREEK SMALL LETTER XI:'78:958:ξ +GREEK SMALL LETTER PHI:'79:966:φ +GREEK SMALL LETTER ZETA:'7A:950:ζ +LEFT CURLY BRACKET:'7B:123:{ +DIVIDES:'7C:8739:∣ +RIGHT CURLY BRACKET:'7D:125:} +TILDE OPERATOR:'7E:8764:∼ +GREEK UPSILON WITH HOOK SYMBOL:'A1:978:ϒ +COMBINING ACUTE TONE MARK:'A2:833:́ +LESS THAN OR EQUAL TO:'A3:8804:≤ +DIVISION SLASH:'A4:8725:∕ +INFINITY:'A5:8734:∞ +LATIN SMALL LETTER F WITH HOOK:'A6:402:ƒ +BLACK CLUB SUIT:'A7:9827:♣ +BLACK DIAMOND SUIT:'A8:9830:♦ +BLACK HEART SUIT:'A9:9829:♥ +BLACK SPADE SUIT:'AA:9824:♠ +LEFT RIGHT ARROW:'AB:8596:↔ +LEFTWARDS ARROW:'AC:8592:← +UPWARDS ARROW:'AD:8593:↑ +RIGHTWARDS ARROW:'AE:8594:→ +DOWNWARDS ARROW:'AF:8595:↓ +DEGREE SIGN:'B0:176:° +PLUS OR MINUS SIGN:'B1:177:± +DOUBLE ACUTE ACCENT:'B2:733:˝ +GREATER THAN OR EQUAL TO:'B3:8805:≥ +MULTIPLICATION SIGN:'B4:215:× +DON'T KNOW:'B5:8733:∝ +PARTIAL DIFFERENTIAL:'B6:8706:∂ +BULLET:'B7:183:· +DIVISION:'B8:247:÷ +NOT EQUAL TO:'B9:8800:≠ +IDENTICAL TO:'BA:8801:≡ +ALMOST EQUAL TO:'BB:8776:≈ +MIDLINE HORIZONTAL ELLIPSES:'BC:8943:⋯ +DIVIDES:'BD:8739:∣ +BOX DRAWINGS LIGHT HORIZONTAL:'BE:9472:─ +DOWNWARDS ARROW WITH TIP LEFTWARDS:'BF:8626:↲ +CIRCLED TIMES:'C4:8855:⊗ +CIRCLED PLUS:'C5:8853:⊕ +EMPTY SET:'C6:8709:∅ +INTERSECTION:'C7:8745:∩ +UNION:'C8:8746:∪ +SUPERSET OF:'C9:8835:⊃ +SUPERSET OF OR EQUAL TO:'CA:8839:⊇ +NIETHER A SUBSET OR EQUAL TO:'CB:8836:⊄ +SUBSET OF:'CC:8834:⊂ +SUBSET OR EQUAL TO:'CD:8838:⊆ +ELEMENT OF:'CE:8712:∈ +NOT AN ELEMENT OF:'CF:8713:∉ +ANGLE:'D0:8736:∠ +WHITE DOWN POINTING TRIANBLE:'D1:9661:▽ +REGISTERED SIGN:'D2:174:® +COPYRIGHT:'D3:169:© +TRADEMARK SYMBOL:'D4:8482:™ +NARY OPERATOR:'D5:8719:∏ +SQUARE ROOT:'D6:8730:√ +BULLET OPERATOR:'D7:8729:∙ +NOT SIGN:'D8:172:¬ +LOGICAL AND:'D9:8743:∧ +LOGICAL OR:'DA:8744:∨ +LEFT RIGHT DOUBLE ARROW:'DB:8660:⇔ +LEFTWARDS DOUBLE ARROW:'DC:8656:⇐ +UPWARDS DOUBLE ARROW:'DD:8657:⇑ +RIGHTWARDS DOUBLE ARROW:'DE:8658:⇒ +DOWNWARDS DOUBLE ARROW:'DF:8659:⇓ +BETWEEN:'E0:8812:≬ +MATHMATICAL LEFT ANGELBRACKET:'E1:10216:⟨ +REGISTERED SIGN:'E2:174:® +COPYRIGHT:'E3:169:© +TRADEMARK SYMBOL:'E4:8482:™ +N-ARY SUMMATION:'E5:8721:∑ +LARGE LEFT PARENTHESIS PART1:'E6:0: +LARGE LEFT PARENTHESIS PART2:'E7:0: +LARGE LEFT PARENTHESIS PART3:'E8:0: +LARGE LEFT SQUARE BRACKET PART1:'E9:0: +LARGE LEFT SQUARE BRACKET PART2:'EA:0: +LARGE LEFT SQUARE BRACKET PART3:'EB:0: +LARGE LEFT BRACKET PART1:'EC:0: +LARGE LEFT BRACKET PART2:'ED:0: +LARGE LEFT BRACKET PART3:'EE:0: +DIVIDES:'EF:8739:∣ +MATHMATICAL RIGHT ANGLE BRACKET:'F1:10217:⟩ +INTEGRAL:'F2:8747:∫ +LARGE INTEGRAL PART 1:'F3:0: +LARGE INTEGRAL PART 2:'F4:0: +LARGE INTEGRAL PART 3:'F5:0: +LARGE RIGHT PARENTHESIS PART1:'F6:0: +LARGE RIGHT PARENTHESIS PART2:'F7:0: +LARGE RIGHT PARENTHESIS PART3:'F8:0: +LARGE RIGHT SQAURE BRACKET PART1:'F9:0: +LARGE RIGHT SQUARE BRACKET PART2:'FA:0: +LARGE RIGHT SQUARE BRACKETPART3:'FB:0: +LARGE RIGHT BRACKET PART1:'FC:0: +LARGE RIGHT BRACKETPART2:'FD:0: +LARGE RIGHT BRACKETPART3:'FE:0: +DOUBLE ACUTE ACCENT:'B2:733:˝ +MY UNDEFINED SYMBOL:'7F:127: +MY UNDEFINED SYMBOL:'80:128: +MY UNDEFINED SYMBOL:'81:129: +MY UNDEFINED SYMBOL:'82:130: +MY UNDEFINED SYMBOL:'83:131: +MY UNDEFINED SYMBOL:'84:132: +MY UNDEFINED SYMBOL:'85:133: +MY UNDEFINED SYMBOL:'86:134: +MY UNDEFINED SYMBOL:'87:135: +MY UNDEFINED SYMBOL:'88:136: +MY UNDEFINED SYMBOL:'89:137: +MY UNDEFINED SYMBOL:'8A:138: +MY UNDEFINED SYMBOL:'8B:139: +MY UNDEFINED SYMBOL:'8C:140: +MY UNDEFINED SYMBOL:'8D:141: +MY UNDEFINED SYMBOL:'8E:142: +MY UNDEFINED SYMBOL:'8F:143: +MY UNDEFINED SYMBOL:'90:144: +MY UNDEFINED SYMBOL:'91:145: +MY UNDEFINED SYMBOL:'92:146: +MY UNDEFINED SYMBOL:'93:147: +MY UNDEFINED SYMBOL:'94:148: +MY UNDEFINED SYMBOL:'95:149: +MY UNDEFINED SYMBOL:'96:150: +MY UNDEFINED SYMBOL:'97:151: +MY UNDEFINED SYMBOL:'98:152: +MY UNDEFINED SYMBOL:'99:153: +MY UNDEFINED SYMBOL:'9A:154: +MY UNDEFINED SYMBOL:'9B:155: +MY UNDEFINED SYMBOL:'9C:156: +MY UNDEFINED SYMBOL:'9D:157: +MY UNDEFINED SYMBOL:'9E:158: +MY UNDEFINED SYMBOL:'9F:159: +MY UNDEFINED SYMBOL:'A0:160: +MY UNDEFINED SYMBOL:'F0:160: + + +SPACE: :32:\'20 +EXCLAMATION MARK:!:33:\'21 +QUOTATION MARK:":34:\'22 +NUMBER SIGN:#:35:\'23 +DOLLAR SIGN:$:36:\'24 +PERCENT SIGN:%:37:\'25 +AMPERSAND:&:38:\'26 +APOSTROPHE:':39:\'27 +LEFT PARENTHESIS:(:40:\'28 +RIGHT PARENTHESIS:):41:\'29 +ASTERISK:*:42:\'2A +PLUS SIGN:+:43:\'2B +COMMA:,:44:\'2C +HYPHEN-MINUS:-:45:\'2D +FULL STOP:.:46:\'2E +SOLIDUS:/:47:\'2F +DIGIT ZERO:0:48:\'30 +DIGIT ONE:1:49:\'31 +DIGIT TWO:2:50:\'32 +DIGIT THREE:3:51:\'33 +DIGIT FOUR:4:52:\'34 +DIGIT FIVE:5:53:\'35 +DIGIT SIX:6:54:\'36 +DIGIT SEVEN:7:55:\'37 +DIGIT EIGHT:8:56:\'38 +DIGIT NINE:9:57:\'39 +COLON:\\colon:58:\'3A +SEMICOLON:;:59:\'3B +EQUALS SIGN:=:61:\'3D +QUESTION MARK:?:63:\'3F +LATIN CAPITAL LETTER A:A:65:\'41 +LATIN CAPITAL LETTER B:B:66:\'42 +LATIN CAPITAL LETTER C:C:67:\'43 +LATIN CAPITAL LETTER D:D:68:\'44 +LATIN CAPITAL LETTER E:E:69:\'45 +LATIN CAPITAL LETTER F:F:70:\'46 +LATIN CAPITAL LETTER G:G:71:\'47 +LATIN CAPITAL LETTER H:H:72:\'48 +LATIN CAPITAL LETTER I:I:73:\'49 +LATIN CAPITAL LETTER J:J:74:\'4A +LATIN CAPITAL LETTER K:K:75:\'4B +LATIN CAPITAL LETTER L:L:76:\'4C +LATIN CAPITAL LETTER M:M:77:\'4D +LATIN CAPITAL LETTER N:N:78:\'4E +LATIN CAPITAL LETTER O:O:79:\'4F +LATIN CAPITAL LETTER P:P:80:\'50 +LATIN CAPITAL LETTER Q:Q:81:\'51 +LATIN CAPITAL LETTER R:R:82:\'52 +LATIN CAPITAL LETTER S:S:83:\'53 +LATIN CAPITAL LETTER T:T:84:\'54 +LATIN CAPITAL LETTER U:U:85:\'55 +LATIN CAPITAL LETTER V:V:86:\'56 +LATIN CAPITAL LETTER W:W:87:\'57 +LATIN CAPITAL LETTER X:X:88:\'58 +LATIN CAPITAL LETTER Y:Y:89:\'59 +LATIN CAPITAL LETTER Z:Z:90:\'5A +LEFT SQUARE BRACKET:[:91:\'5B +REVERSE SOLIDUS:\\:92:\'5C +RIGHT SQUARE BRACKET:]:93:\'5D +LATIN SMALL LETTER A:a:97:\'61 +LATIN SMALL LETTER B:b:98:\'62 +LATIN SMALL LETTER C:c:99:\'63 +LATIN SMALL LETTER D:d:100:\'64 +LATIN SMALL LETTER E:e:101:\'65 +LATIN SMALL LETTER F:f:102:\'66 +LATIN SMALL LETTER G:g:103:\'67 +LATIN SMALL LETTER H:h:104:\'68 +LATIN SMALL LETTER I:i:105:\'69 +LATIN SMALL LETTER J:j:106:\'6A +LATIN SMALL LETTER K:k:107:\'6B +LATIN SMALL LETTER L:l:108:\'6C +LATIN SMALL LETTER M:m:109:\'6D +LATIN SMALL LETTER N:n:110:\'6E +LATIN SMALL LETTER O:o:111:\'6F +LATIN SMALL LETTER P:p:112:\'70 +LATIN SMALL LETTER Q:q:113:\'71 +LATIN SMALL LETTER R:r:114:\'72 +LATIN SMALL LETTER S:s:115:\'73 +LATIN SMALL LETTER T:t:116:\'74 +LATIN SMALL LETTER U:u:117:\'75 +LATIN SMALL LETTER V:v:118:\'76 +LATIN SMALL LETTER W:w:119:\'77 +LATIN SMALL LETTER X:x:120:\'78 +LATIN SMALL LETTER Y:y:121:\'79 +LATIN SMALL LETTER Z:z:122:\'7A +LEFT CURLY BRACKET:{:123:\'7B +VERTICAL LINE:|:124:\'7C +RIGHT CURLY BRACKET:}:125:\'7D +TILDE:~:126:\'7E + + +SPACE:'20:32: +LOWER RIGHT PENCIL:'21:9998:✎ +BLACK SCISSORS:'22:9986:✂ +UPPER BLADE SCISSORS:'23:9985:✁ +PROPOSE "LOWER LEFT SPECTACLES":'24:none: +PROPOSE "BELL":'25:none: +PROPOSE "OPEN BOOK":'26:none: +PROPOSE "LIGHTED CANDLE":'27:none: +BLACK TELEPHONE:'28:9742:☎ +TELEPHONE LOCATION SIGN:'29:9990:✆ +ENVELOPE:'2A:9993:✉ +ENVELOPE:'2B:9993:✉ +PROPOSE "MAIL FLAG DOWN":'2C:none: +PROPOSE "MAIL FLAG UP":'2D:none: +PROPOSE "MAIL FULL":'2E:none: +PROPOSE "MAIL EMPTY":'2F:none: +PROPOSE "FOLDER CLOSE":'30:none: +PROPOSE "FOLDER OPEN":'31:none: +PROPOSE "DOCUMENT FOLDED":'32:none: +PROPOSE "DOCUMENT":'33:none: +PROPOSE "MULTIPLE DOCUMENTS":'34:none: +PROPOSE "FILE CABINET":'35:none: +HOURGLASS:'36:8987:⌛ +KEYBOARD:'37:9000:⌨ +PROPOSE "MOUSE":'38:none: +PROPOSE "QUICKCAM CAMERA":'39:none: +PROPOSE "COMPUTER":'3A:none: +PROPOSE "HARD DRIVE":'3B:none: +PROPOSE "THREE AND A HALF FLOPPY":'3C:none: +PROPOSE "FIVE AND A QUARTER FLOPPY":'3D:none: +TAPE DRIVE:'3E:9991:✇ +WRITING HAND:'3F:9997:✍ +WRITING HAND:'40:9997:✍ +VICTORY HAND:'41:9996:✌ +PROPOSE "PICKING HAND(OR OMMAT)":'42:none: +PROPOSE "WHITE UP POINTING THUMB":'43:none: +PROPOSE "WHITE DOWN POINTING THUMB":'44:none: +WHITE LEFT POINTING INDEX:'45:9756:☜ +WHITE RIGHT POINTING INDEX:'46:9758:☞ +WHITE UP POINTING INDEX:'47:9757:☝ +WHITE DOWN POINTING INDEX:'48:9759:☟ +PROPOSE "WHITE PALM":'49:none: +WHITE SMILING FACE:'4A:9786:☺ +WHITE SMILING FACE":'4B:9786:☺ +WHITE FROWNING FACE:'4C:9785:☹ +PROPOSE "BLACK BOMB WITH FUSE":'4D:none: +SKULL AND CROSSBONES:'4E:9760:☠ +PROPOSE "WHITE BILLOWING SQUARE FLAG":'4F:none: +PROPOSE "WHITE BILLOWING TRIANGLE FLAG":'50:none: +AIRPLANE:'51:9992:✈ +WHITE SUN WITH RAYS:'52:9788:☼ +PROPOSE "INK BLOT":'53:none: +SNOWFLAKE:'54:10052:❄ +SHADOWED WHITE LATIN CROSS:'55:10014:✞ +SHADOWED WHITE LATIN CROSS:'56:10014:✞ +LATIN CROSS:'57:10013:✝ +MALTESE CROSS:'58:10016:✠ +STAR OF DAVID:'59:10017:✡ +STAR AND CRESCENT:'5A:9770:☪ +YIN YANG:'5B:9775:☯ +DEVANGARI OM CORRECT:'5C:2384:ॐ +WHEEL OF DHARMA:'5D:9784:☸ +ARIES:'5E:9800:♈ +TAURUS:'5F:9801:♉ +GEMINI:'60:9802:♊ +CANCER:'61:9803:♋ +LEO:'62:9804:♌ +VIRGO:'63:9805:♍ +LIBRA:'64:9806:♎ +SCORPIUS:'65:9807:♏ +SAGITTARIUS:'66:9808:♐ +CAPRICORN:'67:9809:♑ +AQUARIUS:'68:9810:♒ +PISCES:'69:9811:♓ +AMPERSAND:'6A:38:& +AMPERSAND:'6B:38:& +BLACK CIRCLE:'6C:9679:● +SHADOWED WHITE CIRCLE:'6D:10061:❍ +BLACK SQUARE:'6E:9632:■ +WHITE SQUARE:'6F:9633:□ +WHITE SQUARE:'70:9633:□ +LOWER RIGHT SHADOWED WHITE SQUARE:'71:10065:❑ +UPPER RIGHT SHADOWED WHITE SQUARE:'72:10066:❒ +LOZENGE:'73:9674:◊ +LOZENGE:'74:9674:◊ +BLACK DIAMOND:'75:9670:◆ +BLACK DIAMOND MINUS WHITE X:'76:10070:❖ +BLACK DIAMOND:'77:9670:◆ +X IN A RECTANGLE BOX:'78:8999:⌧ +APL FUNCTIONAL SYMBOL QUAD UP CARET:'79:9043:⍓ +PLACE OF INTEREST SIGN:'7A:8984:⌘ +WHITE FLORETTE:'7B:10048:❀ +BLACK FLORETTE:'7C:10047:✿ +HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT:'7D:10077:❝ +HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT:'7E:10078:❞ +"UNUSED":'7F:none:udef_symbol/> +CIRCLED DIGIT ZERO:'80:9450:⓪ +CIRCLED DIGIT ONE:'81:9312:① +CIRCLED DIGIT TWO:'82:9313:② +CIRCLED DIGIT THREE:'83:9314:③ +CIRCLED DIGIT FOUR:'84:9315:④ +CIRCLED DIGIT FIVE:'85:9316:⑤ +CIRCLED DIGIT SIX:'86:9317:⑥ +CIRCLED DIGIT SEVEN:'87:9318:⑦ +CIRCLED DIGIT EIGHT:'88:9319:⑧ +CIRCLED DIGIT NINE:'89:9320:⑨ +CIRCLED NUMBER TEN:'8A:9321:⑩ +PROPOSE "DINGBAT NEGATIVE CIRCLED DIGIT ZERO":'8B:none: +DINGBAT NEGATIVE CIRCLED DIGIT ONE:'8C:10102:❶ +DINGBAT NEGATIVE CIRCLED DIGIT TWO:'8D:10103:❷ +DINGBAT NEGATIVE CIRCLED DIGIT THREE:'8E:10104:❸ +DINGBAT NEGATIVE CIRCLED DIGIT FOUR:'8F:10105:❹ +DINGBAT NEGATIVE CIRCLED DIGIT FIVE:'90:10106:❺ +DINGBAT NEGATIVE CIRCLED DIGIT SIX:'91:10107:❻ +DINGBAT NEGATIVE CIRCLED DIGIT SEVEN:'92:10108:❼ +DINGBAT NEGATIVE CIRCLED DIGIT EIGHT:'93:10109:❽ +DINGBAT NEGATIVE CIRCLED DIGIT NINE:'94:10110:❾ +DINGBAT NEGATIVE CIRCLED NUMBER TEN:'95:10111:❿ +ROTATED FLORAL HEART BULLET:'96:10087:❧ +REVERSED ROTATED FLORAL HEART BULLET:'97:9753:☙ +REVERSED ROTATED FLORAL HEART BULLET:'98:9753:☙ +ROTATED FLORAL HEART BULLET:'99:10087:❧ +ROTATED FLORAL HEART BULLET:'9A:10087:❧ +REVERSED ROTATED FLORAL HEART BULLET:'9B:9753:☙ +REVERSED ROTATED FLORAL HEART BULLET:'9C:9753:☙ +ROTATED FLORAL HEART BULLET:'9D:10087:❧ +BULLET:'9E:8226:• +BLACK CIRCLE:'9F:9679:● +DON'T KNOW:'A0:160:  +WHITE CIRCLE:'A1:9675:○ +WHITE CIRCLE:'A2:9675:○ +WHITE CIRCLE:'A3:9675:○ +SUN:'A4:9737:☉ +SUN:'A5:9737:☉ +SHADOWED WHITE CIRCLE:'A6:10061:❍ +BLACK SMALL SQUARE:'A7:9642:▪ +WHITE SQUARE:'A8:9633:□ +PROPOSE "THEE MIGHT BE IN THERE SOMEWHERE":'A9:none: +BLACK FOUR POINTED STAR MAYBE:'AA:10022:✦ +BLACK STAR:'AB:9733:★ +SIX POINTED BLACK STAR:'AC:10038:✶ +EIGHT POINTED RECTILINEAR BLACK STAR:'AD:10039:✷ +TWELVE POINTED BLACK STAR:'AE:10040:✸ +EIGHT POINTED PINWHEEL STAR:'AF:10037:✵ +PROPOSE "CROSSHAIR SQUARE":'B0:none: +PROPOSE "CROSSHAIR CIRCLE":'B1:none: +WHITE FOUR POINTED STAR:'B2:10023:✧ +PROPOSE "THIS HAS TO BE A KNOWN SYMBOL":'B3:none: +REPLACEMENT CHARACTER:'B4:65533:� +CIRCLED WHITE STAR:'B5:10026:✪ +SHADOWED WHITE STAR:'B6:10032:✰ +PROPOSE "1 OCLOCK":'B7:none: +PROPOSE "2 OCLOCK":'B8:none: +PROPOSE "3 OCLOCK":'B9:none: +PROPOSE "4 OCLOCK":'BA:none: +PROPOSE "5 OCLOCK":'BB:none: +PROPOSE "6 OCLOCK":'BC:none: +PROPOSE "7 OCLOCK":'BD:none: +PROPOSE "8 OCLOCK":'BE:none: +PROPOSE "9 OCLOCK":'BF:none: +PROPOSE "10 OCLOCK":'C0:none: +PROPOSE "11 OCLOCK":'C1:none: +PROPOSE "12 OCLOCK":'C2:none: +PROPOSE "NOTCHED DOWNWARDS DOUBLE ARROW WITH TIP LEFTWARDS":'C3:none: +PROPOSE "NOTCHED DOWNWARDS DOUBLE ARROW WITH TIP RIGHTWARDS":'C4:none: +PROPOSE "NOTCHED UPWARDS DOUBLE ARROW WITH TIP LEFTWARDS":'C5:none: +PROPOSE "NOTCHED UPWARDS DOUBLE ARROW WITH TIP RIGHTWARDS":'C6:none: +PROPOSE "NOTCHED LEFTWARDS DOUBLE ARROW WITH TIP UPWARDS":'C7:none: +PROPOSE "NOTCHED RIGHTWARDS DOUBLE ARROW WITH TIP UPWARDS":'C8:none: +PROPOSE "NOTCHED LEFTWARDS DOUBLE ARROW WITH TIP DOWNWARDS":'C9:none: +PROPOSE "NOTCHED RIGHTWARDS DOUBLE ARROW WITH TIP DOWNWARDS":'CA:none: +PROPOSE "NO IDEA":'CB:none: +PROPOSE "REVERSE OF ABOVE":'CC:none: +PROPOSE "HEDERA LOWER LEFT":'CD:none: +PROPOSE "HEDERA UPPER LEFT REVERSED":'CE:none: +PROPOSE "HEDERA LOWER RIGHT REVERSED":'CF:none: +PROPOSE "HEDERA UPPER RIGHT":'D0:none: +PROPOSE "HEDERA UPPER LEFT":'D1:none: +PROPOSE "HEDERA LOWER LEFT REVERSED":'D2:none: +PROPOSE "HEDERA UPPER RIGHT REVERSED":'D3:none: +PROPOSE "HEDERA LOWER RIGHT":'D4:none: +ERASE TO THE LEFT:'D5:9003:⌫ +ERASE TO THE RIGHT:'D6:8998:⌦ +PROPOSE "THREE-D TOP-LIGHTED LEFTWARDS ARROWHEAD":'D7:none: +THREE-D TOP-LIGHTED RIGHTWARDS ARROWHEAD:'D8:10146:➢ +PROPOSE "THREE-D RIGHT-LIGHTED UPWARDS ARROWHEAD":'D9:none: +PROPOSE "THREE-D LEFT-LIGHTED DOWNWARDS ARROWHEAD":'DA:none: +PROPOSE "CIRCLED HEAVY WHITE LEFTWARDS ARROW":'DB:none: +CIRCLED HEAVY WHITE RIGHTWARDS ARROW:'DC:10162:➲ +PROPOSE "CIRCLED HEAVY WHITE UPWARDS ARROW":'DD:none: +PROPOSE "CIRCLED HEAVY WHITE DOWNWARDS ARROW":'DE:none: +PROPOSE "WIDE-HEADED LEFTWARDS ARROW":'DF:none: +PROPOSE "WIDE-HEADED RIGHTWARDS ARROW":'E0:none: +PROPOSE "WIDE-HEADED UPWARDS ARROW":'E1:none: +PROPOSE "WIDE-HEADED DOWNWARDS ARROW":'E2:none: +PROPOSE "WIDE-HEADED NORTHWEST-WARDS ARROW":'E3:none: +PROPOSE "WIDE-HEADED NORTHEAST-WARDS ARROW":'E4:none: +PROPOSE "WIDE-HEADED SOUTHWEST-WARDS ARROW":'E5:none: +PROPOSE "WIDE-HEADED SOUTHEAST-WARDS ARROW":'E6:none: +PROPOSE "HEAVY WIDE-HEADED LEFTWARDS ARROW":'E7:none: +HEAVY WIDE-HEADED RIGHTWARDS ARROW:'E8:10132:➔ +PROPOSE "HEAVY WIDE-HEADED UPWARDS ARROW":'E9:none: +PROPOSE "HEAVY WIDE-HEADED DOWNWARDS ARROW":'EA:none: +PROPOSE "HEAVY WIDE-HEADED NORTHWEST-WARDS ARROW":'EB:none: +PROPOSE "HEAVY WIDE-HEADED NORTHEAST-WARDS ARROW":'EC:none: +PROPOSE "HEAVY WIDE-HEADED SOUTHWEST-WARDS ARROW":'ED:none: +PROPOSE "HEAVY WIDE-HEADED SOUTHEAST-WARDS ARROW":'EE:none: +LEFTWARDS WHITE ARROW:'EF:8678:⇦ +RIGHTWARDS WHITE ARROW:'F0:8680:⇨ +UPWARDS WHITE ARROW:'F1:8679:⇧ +DOWNWARDS WHITE ARROW:'F2:8681:⇩ +LEFT RIGHT DOUBLE ARROW:'F3:8660:⇔ +UP DOWN DOUBLE ARROW:'F4:8661:⇕ +NORTH WEST DOUBLE ARROW:'F5:8662:⇖ +NORTH EAST DOUBLE ARROW:'F6:8663:⇗ +SOUTH WEST DOUBLE ARROW:'F7:8665:⇙ +SOUTH EAST DOUBLE ARROW:'F8:8664:⇘ +"NO IDEA":'F9:none: +"NO IDEA":'FA:none: +BALLOT X:'FB:10007:✗ +CHECK MARK:'FC:10003:✓ +BALLOT BOX WITH X:'FD:9746:☒ +BALLOT BOX WITH CHECK:'FE:9745:☑ +PROPOSE "MICROSOFT WINDOWS LOGO":'FF:none: + + +SPACE:'20:32: +UPPER BLADE SCISSORS:'21:9985:✁ +BLACK SCISSORS:'22:9986:✂ +LOWER BLADE SCISSORS:'23:9987:✃ +WHITE SCISSORS:'24:9988:✄ +BLACK TELEPHONE:'25:9742:☎ +TELEPHONE LOCATION SIGN:'26:9990:✆ +TAPE DRIVE:'27:9991:✇ +AIRPLANE:'28:9992:✈ +ENVELOPE:'29:9993:✉ +BLACK RIGHT POINTING INDEX:'2A:9755:☛ +WHITE RIGHT POINTING INDEX:'2B:9758:☞ +VICTORY HAND:'2C:9996:✌ +WRITING HAND:'2D:9997:✍ +LOWER RIGHT PENCIL:'2E:9998:✎ +PENCIL:'2F:9999:✏ +UPPER RIGHT PENCIL:'30:10000:✐ +WHITE NIB:'31:10001:✑ +BLACK NIB:'32:10002:✒ +CHECKMARK:'33:10003:✓ +HEAVY CHECKMARK:'34:10004:✔ +MULTIPLICATION X:'35:10005:✕ +HEAVY MULTIPLICATION X:'36:10006:✖ +BALLOT X:'37:10007:✗ +HEAVY BALLOT X:'38:10008:✘ +OUTLINED GREEK CROSS:'39:10009:✙ +HEAVY GREK CROSS:'3A:10010:✚ +OPEN CENTRE CROSS:'3B:10011:✛ +HEAVY OPEN CENTRE CROSS:'3C:10011:✛ +LATIN CROSS:'3D:10013:✝ +SHADOWED WHITE LATIN CROSS:'3E:10014:✞ +OUTLINED LATIN CROSS:'3F:10015:✟ +MALTESE CROSS:'40:10016:✠ +STAR OF DAVID:'41:10017:✡ +FOUR TEARDROP-SPOKED ASTERISK:'42:10018:✢ +FOUR BALLOON-SPOKED ASTERISK:'43:10019:✣ +10019:'43:10019:✣ +HEAVY FOUR BALLOON-SPOKED ASTERISK:'44:10020:✤ +FOUR CLUB-SPOKED ASTERISK:'45:10021:✥ +BLACK FOUR POINTED STAR:'46:10022:✦ +WHITE FOUR POINTED STAR:'47:10023:✧ +BLACK STAR:'48:9989:✅ +STRESS OUTLINED WHITE STAR:'49:10025:✩ +CIRCLED WHITE STAR:'4A:10026:✪ +OPEN CENTRE BLACK STAR:'4B:10027:✫ +BLACK CENTRE WHITE STAR:'4C:10028:✬ +OUTLINED BLACK STAR:'4D:10029:✭ +HEAVY OUTLINED BLACK STAR:'4E:10030:✮ +PINWHEEL STAR:'4F:10031:✯ +SHADOWED WHITE STAR:'50:10032:✰ +HEAVY ASTERISK:'51:10033:✱ +OPEN CENTRE ASTERISK:'52:10034:✲ +EIGHT SPOKED ASTERISK:'53:10035:✳ +EIGHT POINTED BLACK STAR:'54:10036:✴ +EIGHT POINTED PINWHEEL STAR:'55:10037:✵ +SIX POINTED BLACK STAR:'56:10038:✶ +EIGHT POINTED RECTILINEAR BLACK STAR:'57:10039:✷ +HEAVY EIGHT POINTED RECTILINEAR BLACK STAR:'58:10040:✸ +TWELVE POINTED BLACK STAR:'59:10041:✹ +SIXTEEN POINTED ASTERISK:'5A:10042:✺ +TEARDROP-SPOKED ASTERISK:'5B:10043:✻ +OPEN CENTRE TEARDROP-SPOKED ASTERISK:'5C:10044:✼ +HEAVY TEARDROP-SPOKED ASTERISK:'5D:10045:✽ +SIX PETALLED BLACK AND WHITE FLORETTE:'5E:10046:✾ +BLACK FLORETTE:'5F:10047:✿ +WHITE FLORETTE:'60:10048:❀ +EIGHT PETALLED OUTLINED BLACK FLORETTE:'61:10049:❁ +CIRCLED OPEN CENTRE EIGHT POINTED STAR:'62:10050:❂ +HEAVY TEARDROP-SPOKED PINWHEEL ASTERISK:'63:10051:❃ +SNOWFLAKE:'64:10052:❄ +TIGHT TRIFOLIATE SNOWFLAKE:'65:10053:❅ +HEAVY CHEVRON SNOWFLAKE:'66:10054:❆ +SPARKLE:'67:10055:❇ +HEAVY SPARKLE:'68:10056:❈ +BALLOON-SPOKED ASTERISK:'69:10057:❉ +TEARDROP-SPOKED ASTERISK:'6A:10043:✻ +HEAVY TEARDROP-SPOKED ASTERISK:'6B:10045:✽ +BLACK CIRCLE:'6C:9679:● +SHADOWED WHITE CIRCLE:'6D:10061:❍ +BLACK SQUARE:'6E:9632:■ +LOWER RIGHT DROP-SHADOWED SQUARE:'6F:10063:❏ +UPPER RIGHT DROP-SHADOWED WHITE SQUARE:'70:10064:❐ +LOWER RIGHT SHADOWED SQUARE:'71:10065:❑ +UPPER RIGHT SHADOWED WHITE SQUARE:'72:10066:❒ +BLACK UP-POINTING TRIANGLE:'73:9660:▲ +BLACK DOWN-POINTING TRIANGLE:'74:9651:▼ +BLACK DIAMOND:'75:9670:◆ +BLACK DIAMOND MINUS WHITE X:'76:10070:❖ +RIGHT HALF BLACK CIRCLE:'77:9479:┇ +LIGHT VERTICAL BAR:'78:10072:❘ +MEDIUM VERTICAL BAR:'79:10073:❙ +HEAVY VERTICAL BAR:'7A:10074:❚ +HEAVY SINGLE TURNED COMMA QUOTATION MARK ORNAMENT:'7B:10075:❛ +HEAVY SINGLE COMMA QUOTATION MARK ORNAMENT:'7C:10076:❜ +HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT:'7D:10077:❝ +HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT:'7E:10078:❞ +UNUSED:'7F:none:udef_symbol num="7F"/> +MEDIUM LEFT PARENTHESIS ORNAMENT:'80:10088:❨ +MEDIUM RIGHT PARENTHESIS ORNAMENT:'81:10089:❩ +MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT:'82:10090:❪ +MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT:'83:10091:❫ +MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT:'84:10092:❬ +MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT:'85:10093:❭ +HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT:'86:10094:❮ +HEAVY RIGHT-POITING ANGLE QUOTATION MARK ORNAMENT:'87:10095:❯ +HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT:'88:10096:❰ +HEAVY RIGHT-POTING ANGLE BRACKET ORNAMENT:'89:10097:❱ +LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT:'8A:10098:❲ +LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT:'8B:10099:❳ +MEDIUM LEFT CURLY BRACKET ORNAMENT:'8C:10100:❴ +MEDIUM RIGHT CURLY BRACKET ORNAMENT:'8D:10101:❵ +UNUSED:'8E:none: +UNUSED:'8F:none:udef_symbol num="8F"/> +UNUSED:'90:none:udef_symbol num="90"/> +UNUSED:'91:none:udef_symbol num="91"/> +UNUSED:'92:none:udef_symbol num="92"/> +UNUSED:'93:none:udef_symbol num="93"/> +UNUSED:'94:none:udef_symbol num="94"/> +UNUSED:'95:none:udef_symbol num="95"/> +UNUSED:'96:none:udef_symbol num="96"/> +UNUSED:'97:none:udef_symbol num="97"/> +UNUSED:'98:none:udef_symbol num="98"/> +UNUSED:'99:none:udef_symbol num="99"/> +UNUSED:'9A:none:udef_symbol num="9A"/> +UNUSED:'9B:none:udef_symbol num="9B"/> +UNUSED:'9C:none:udef_symbol num="9C"/> +UNUSED:'9D:none:udef_symbol num="9D"/> +UNUSED:'9E:none:udef_symbol num="9E"/> +UNUSED:'9F:none:udef_symbol num="9F"/> +UNUSED:'A0:none:udef_symbol num="A0"/> +CURVED STEM PARAGRAPH SIGN ORNAMENT:'A1:10081:❡ +HEAVY EXCLAMATION MARK ORNAMENT:'A2:10082:❢ +HEAVY HEART EXCLAMATION MARK ORNAMENT:'A3:10083:❣ +HEAVY BLACK HEART:'A4:10084:❤ +ROTATED HEAVY BLACK HEART BULLET:'A5:10085:❥ +FLORAL HEART:'A6:10086:❦ +ROTATED FLORAL HEART BULLET:'A7:10087:❧ +BLACK CLUB SUIT:'A8:9827:♣ +BLACK DIAMOND SUIT:'A9:9830:♦ +BLACK HEART SUIT:'AA:9829:♥ +BLACK SPADE SUIT:'AB:9824:♠ +DINGBAT CIRCLED SANS SERIF DIGIT ONE:'AC:10112:➀ +DINGBAT CIRCLED SANS SERIF DIGIT TWO:'AD:10113:➁ +DINGBAT CIRCLED SANS SERIF DIGIT THREE:'AE:10114:➂ +DINGBAT CIRCLED SANS SERIF DIGIT FOUR:'AF:10115:➃ +DINGBAT CIRCLED SANS SERIF DIGIT FIVE:'B0:10116:➄ +DINGBAT CIRCLED SANS SERIF DIGIT SIX:'B1:10117:➅ +DINGBAT CIRCLED SANS SERIF DIGIT SEVEN:'B2:10118:➆ +DINGBAT CIRCLED SANS SERIF DIGIT EIGHT:'B3:10119:➇ +DINGBAT CIRCLED SANS SERIF DIGIT NINE:'B4:10120:➈ +DINGBAT CIRCLED SANS SERIF DIGIT TEN:'B5:10121:➉ +DINGBAT NEGATIVE CIRCLED DIGIT ONE:'B6:10102:❶ +DINGBAT NEGATIVE CIRCLED DIGIT TWO:'B7:10103:❷ +DINGBAT NEGATIVE CIRCLED DIGIT THREE:'B8:10104:❸ +DINGBAT NEGATIVE CIRCLED DIGIT FOUR:'B9:10105:❹ +DINGBAT NEGATIVE CIRCLED DIGIT FIVE:'BA:10106:❺ +DINGBAT NEGATIVE CIRCLED DIGIT SIX:'BB:10107:❻ +DINGBAT NEGATIVE CIRCLED DIGIT SEVEN:'BC:10108:❼ +DINGBAT NEGATIVE CIRCLED DIGIT EIGHT:'BD:10109:❽ +DINGBAT NEGATIVE CIRCLED DIGIT:'BE:10110:❾ +DINGBAT NEGATIVE CIRCLED DIGIT:'BF:10111:❿ +DINGBAT CIRCLED SANS-SERIF DIGIT ONE:'C0:10112:➀ +DINGBAT CIRCLED SANS-SERIF DIGIT TWO:'C1:10113:➁ +DINGBAT CIRCLED SANS-SERIF DIGIT THREE:'C2:10114:➂ +DINGBAT CIRCLED SANS-SERIF DIGIT FOUR:'C3:10115:➃ +DINGBAT CIRCLED SANS-SERIF DIGIT FIVE:'C4:10116:➄ +DINGBAT CIRCLED SANS-SERIF DIGIT SIX:'C5:10117:➅ +DINGBAT CIRCLED SANS-SERIF DIGIT SEVEN:'C6:10118:➆ +DINGBAT CIRCLED SANS-SERIF DIGIT EIGHT:'C7:10119:➇ +DINGBAT CIRCLED SANS-SERIF DIGIT NINE:'C8:10120:➈ +DINGBAT CIRCLED SANS-SERIF DIGIT TEN:'C9:10121:➉ +DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ONE:'CA:10122:➊ +DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT TWO:'CB:10123:➋ +DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT THREE:'CC:10124:➌ +DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FOUR:'CD:10125:➍ +DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FIVE:'CE:10126:➎ +DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SIX:'CF:10127:➏ +DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SEVEN:'D0:10128:➐ +DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT EIGHT:'D1:10129:➑ +DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT NINE:'D2:10130:➒ +DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT TEN:'D3:10131:➓ +HEAVY WIDE-HEADED RIGHTWARDS ARROW:'D4:10132:➔ +RIGHTWARDS ARROW:'D5:8594:→ +LEFT RIGHT ARROW:'D6:8596:↔ +UP DOWN ARROW:'D7:8597:↕ +HEAVY SOUTH EAST ARROW:'D8:10136:➘ +HEAVY RIGHTWARDS ARROW:'D9:10137:➙ +HEAVY NORTHEAST ARROW:'DA:10138:➚ +DRAFTING POINT RIGHTWARDS ARROW:'DB:10139:➛ +HEAVY ROUND-TIPPED RIGHTWARDS ARROW:'DC:10140:➜ +TRIANGLE-HEADED RIGHTWARDS ARROW:'DD:10141:➝ +HEAVY TRIANGLE-HEADED RIGHTWARDS ARROW:'DE:10142:➞ +DASHED TRIANGLE-HEADED RIGHTWARDS ARROW:'DF:10143:➟ +HEAVY DASHED TRIANGLE-HEADED RIGHTWARS ARROW:'E0:10144:➠ +BLACK RIGHTWARDS ARROW:'E1:10145:➡ +THREE-D TOP-LIGHTED RIGHTWARDS ARROWHEAD:'E2:10146:➢ +THREE-D BOTTOM-LIGHTED RIGHTWARDS ARROWHEAD:'E3:10147:➣ +BLACK RIGHTWARDS ARROWHEAD:'E4:10148:➤ +HEAVY BLACK CURVED DOWNWARDS AND RIGHTWARDS ARROW:'E5:10149:➥ +HEAVY BLACK CURVED UPWARDS AND RIGHTWARDS ARROW:'E6:10150:➦ +SQUAT BLACK RIGHTWARDS ARROW:'E7:10151:➧ +HEAVY CONCAVE-POINTED BLACK RIGHTWARDS ARROW:'E8:10152:➨ +RIGHT-SHADED WHITE RIGHTWARDS ARROW:'E9:10153:➩ +LEFT-SHADED WHITE RIGHTWARDS ARROW:'EA:10154:➪ +BACK-TILTED SHADOWED WHITE RIGHTWARDS ARROW:'EB:10155:➫ +FRONT-TILTED SHADOWED WHITE RIGHWARDS ARROW:'EC:10156:➬ +HEAVY LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW:'ED:10157:➭ +HEAVY UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW:'EE:10157:➭ +NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW:'EF:10158:➮ +UNUSED:'F0:none:udef_symbol num="F0"/> +NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW:'F1:10161:➱ +CIRCLED HEAVY WHITE RIGHTWARDS ARROW:'F2:10162:➲ +WHITE-FEATHERED RIGHTWARDS ARROW:'F3:10163:➳ +BLACK-FEATHERED SOUTH EAST ARROW:'F4:10164:➴ +BLACK-FEATHERED RIGHTWARDS ARROW:'F5:10165:➵ +BLACK-FEATHERED NORTH EAST ARROW:'F6:10166:➶ +HEAVY BLACK-FEATHERED SOUTH EAST ARROW:'F7:10167:➷ +HEAVY BLACK-FEATHERED RIGHTWARDS ARROW:'F8:10168:➸ +HEAVY BLACK-FEATHERED NORTH EAST ARROW:'F9:10169:➹ +TEARDROP-BARBED RITGHTWARDS ARROW:'FA:10170:➺ +HEAVY TEARDROP-SHANKED RIGHTWARDS ARROW:'FB:10171:➻ +WEDGE-TAILED RIGHTWARDS ARROW:'FC:10172:➼ +HEAVY WEDGED-TAILED RIGHTWARDS ARROW:'FD:10173:➽ +OPEN-OUTLINED RIGHTWARDS ARROW:'FE:10174:➾ +UNUSED:'FF:none:udef_symbol num="FF"/> + + +LATIN CAPITAL LETTER S WITH CARON:š:352:Š +LATIN CAPITAL LETTER S WITH ACUTE:ś:346:Ś +LATIN CAPITAL LETTER T WITH CARON:ť:356:Ť +LATIN CAPITAL LETTER Z WITH CARON:ž:381:Ž +LATIN CAPITAL LETTER Z WITH ACUTE:ź:377:Ź +LATIN CAPITAL LETTER L WITH STROKE:ł:321:Ł +LATIN CAPITAL LETTER A WITH OGONEK:ą:260:Ą +LATIN CAPITAL LETTER S WITH CEDILLA:ş:350:Ş +LATIN CAPITAL LETTER Z WITH DOT ABOVE:ż:379:Ż +LATIN CAPITAL LETTER L WITH CARON:ľ:317:Ľ +LATIN CAPITAL LETTER R WITH ACUTE:ŕ:340:Ŕ +LATIN CAPITAL LETTER A WITH ACUTE:á:193:Á +LATIN CAPITAL LETTER A WITH CIRCUMFLEX:â:194: +LATIN CAPITAL LETTER A WITH BREVE:ă:258:Ă +LATIN CAPITAL LETTER A WITH DIAERESIS:ä:196:Ä +LATIN CAPITAL LETTER L WITH ACUTE:ĺ:313:Ĺ +LATIN CAPITAL LETTER C WITH ACUTE:ć:262:Ć +LATIN CAPITAL LETTER C WITH CEDILLA:ç:199:Ç +LATIN CAPITAL LETTER C WITH CARON:č:268:Č +LATIN CAPITAL LETTER E WITH ACUTE:é:201:É +LATIN CAPITAL LETTER E WITH OGONEK:ę:280:Ę +LATIN CAPITAL LETTER E WITH DIAERESIS:ë:203:Ë +LATIN CAPITAL LETTER E WITH CARON:ě:282:Ě +LATIN CAPITAL LETTER I WITH ACUTE:í:205:Í +LATIN CAPITAL LETTER I WITH CIRCUMFLEX:î:206:Î +LATIN CAPITAL LETTER D WITH CARON:ď:270:Ď +LATIN CAPITAL LETTER D WITH STROKE:đ:272:Đ +LATIN CAPITAL LETTER N WITH ACUTE:ń:323:Ń +LATIN CAPITAL LETTER N WITH CARON:ň:327:Ň +LATIN CAPITAL LETTER O WITH ACUTE:ó:211:Ó +LATIN CAPITAL LETTER O WITH CIRCUMFLEX:ô:212:Ô +LATIN CAPITAL LETTER O WITH DOUBLE ACUTE:ő:336:Ő +LATIN CAPITAL LETTER O WITH DIAERESIS:ö:214:Ö +LATIN CAPITAL LETTER R WITH CARON:ř:344:Ř +LATIN CAPITAL LETTER U WITH RING ABOVE:ů:366:Ů +LATIN CAPITAL LETTER U WITH ACUTE:ú:218:Ú +LATIN CAPITAL LETTER U WITH DOUBLE ACUTE:ű:368:Ű +LATIN CAPITAL LETTER U WITH DIAERESIS:ü:220:Ü +LATIN CAPITAL LETTER Y WITH ACUTE:ý:221:Ý +LATIN CAPITAL LETTER T WITH CEDILLA:ţ:354:Ţ +CYRILLIC CAPITAL LETTER DJE (SERBOCROATIAN):ђ:1026:Ђ +CYRILLIC CAPITAL LETTER GJE:ѓ:1027:Ѓ +CYRILLIC CAPITAL LETTER LJE:љ:1033:Љ +CYRILLIC CAPITAL LETTER NJE:њ:1034:Њ +CYRILLIC CAPITAL LETTER KJE:ќ:1036:Ќ +CYRILLIC CAPITAL LETTER TSHE (SERBOCROATIAN):ћ:1035:Ћ +CYRILLIC CAPITAL LETTER DZHE:џ:1039:Џ +CYRILLIC CAPITAL LETTER SHORT U (BYELORUSSIAN):ў:1038:Ў +CYRILLIC CAPITAL LETTER JE:ј:1032:Ј +CYRILLIC CAPITAL LETTER GHE WITH UPTURN:ґ:1168:Ґ +CYRILLIC CAPITAL LETTER IO:ё:1025:Ё +CYRILLIC CAPITAL LETTER UKRAINIAN IE:є:1028:Є +CYRILLIC CAPITAL LETTER YI (UKRAINIAN):ї:1031:Ї +CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I:і:1030:І +CYRILLIC CAPITAL LETTER DZE:ѕ:1029:Ѕ +CYRILLIC CAPITAL LETTER A:а:1040:А +CYRILLIC CAPITAL LETTER BE:б:1041:Б +CYRILLIC CAPITAL LETTER VE:в:1042:В +CYRILLIC CAPITAL LETTER GHE:г:1043:Г +CYRILLIC CAPITAL LETTER DE:д:1044:Д +CYRILLIC CAPITAL LETTER IE:е:1045:Е +CYRILLIC CAPITAL LETTER ZHE:ж:1046:Ж +CYRILLIC CAPITAL LETTER ZE:з:1047:З +CYRILLIC CAPITAL LETTER I:и:1048:И +CYRILLIC CAPITAL LETTER SHORT I:й:1049:Й +CYRILLIC CAPITAL LETTER KA:к:1050:К +CYRILLIC CAPITAL LETTER EL:л:1051:Л +CYRILLIC CAPITAL LETTER EM:м:1052:М +CYRILLIC CAPITAL LETTER EN:н:1053:Н +CYRILLIC CAPITAL LETTER O:о:1054:О +CYRILLIC CAPITAL LETTER PE:п:1055:П +CYRILLIC CAPITAL LETTER ER:р:1056:Р +CYRILLIC CAPITAL LETTER ES:с:1057:С +CYRILLIC CAPITAL LETTER TE:т:1058:Т +CYRILLIC CAPITAL LETTER U:у:1059:У +CYRILLIC CAPITAL LETTER EF:ф:1060:Ф +CYRILLIC CAPITAL LETTER HA:х:1061:Х +CYRILLIC CAPITAL LETTER TSE:ц:1062:Ц +CYRILLIC CAPITAL LETTER CHE:ч:1063:Ч +CYRILLIC CAPITAL LETTER SHA:ш:1064:Ш +CYRILLIC CAPITAL LETTER SHCHA:щ:1065:Щ +CYRILLIC CAPITAL LETTER YERU:ы:1067:Ы +CYRILLIC CAPITAL LETTER SOFT SIGN:ь:1068:Ь +CYRILLIC CAPITAL LETTER E:э:1069:Э +CYRILLIC CAPITAL LETTER YU:ю:1070:Ю +CYRILLIC CAPITAL LETTER YA:я:1071:Я +CYRILLIC CAPITAL LETTER HARD SIGN:ъ:1066:Ъ +LATIN CAPITAL LIGATURE OE:œ:338:Œ +LATIN CAPITAL LETTER Y WITH DIAERESIS:ÿ:376:Ÿ +LATIN CAPITAL LETTER A WITH GRAVE:à:192:À +LATIN CAPITAL LETTER A WITH TILDE:ã:195:à +LATIN CAPITAL LETTER A WITH RING ABOVE:å:197:Å +LATIN CAPITAL LETTER AE:æ:198:Æ +LATIN CAPITAL LETTER E WITH GRAVE:è:200:È +LATIN CAPITAL LETTER E WITH CIRCUMFLEX:ê:202:Ê +LATIN CAPITAL LETTER I WITH GRAVE:ì:204:Ì +LATIN CAPITAL LETTER I WITH DIAERESIS:ï:207:Ï +LATIN CAPITAL LETTER ETH (ICELANDIC):ð:208:Ð +LATIN CAPITAL LETTER N WITH TILDE:ñ:209:Ñ +LATIN CAPITAL LETTER O WITH GRAVE:ò:210:Ò +LATIN CAPITAL LETTER O WITH TILDE:õ:213:Õ +LATIN CAPITAL LETTER O WITH STROKE:ø:216:Ø +LATIN CAPITAL LETTER U WITH GRAVE:ù:217:Ù +LATIN CAPITAL LETTER U WITH CIRCUMFLEX:û:219:Û +LATIN CAPITAL LETTER THORN (ICELANDIC):þ:222:Þ +GREEK CAPITAL LETTER EPSILON WITH TONOS:έ:904:Έ +GREEK CAPITAL LETTER ETA WITH TONOS:ή:905:Ή +GREEK CAPITAL LETTER IOTA WITH TONOS:ί:906:Ί +GREEK CAPITAL LETTER OMICRON WITH TONOS:ό:908:Ό +GREEK CAPITAL LETTER UPSILON WITH TONOS:ύ:910:Ύ +GREEK CAPITAL LETTER OMEGA WITH TONOS:ώ:911:Ώ +GREEK CAPITAL LETTER IOTA WITH DIALYTIKA:Ϊ:938:Ϊ +GREEK CAPITAL LETTER ALPHA:α:913:Α +GREEK CAPITAL LETTER BETA:β:914:Β +GREEK CAPITAL LETTER GAMMA:γ:915:Γ +GREEK CAPITAL LETTER DELTA:δ:916:Δ +GREEK CAPITAL LETTER EPSILON:ε:917:Ε +GREEK CAPITAL LETTER ZETA:ζ:918:Ζ +GREEK CAPITAL LETTER ETA:η:919:Η +GREEK CAPITAL LETTER THETA:θ:920:Θ +GREEK CAPITAL LETTER IOTA:ι:921:Ι +GREEK CAPITAL LETTER KAPPA:κ:922:Κ +GREEK CAPITAL LETTER LAMDA:λ:923:Λ +GREEK CAPITAL LETTER MU:μ:924:Μ +GREEK CAPITAL LETTER NU:ν:925:Ν +GREEK CAPITAL LETTER XI:ξ:926:Ξ +GREEK CAPITAL LETTER OMICRON:ο:927:Ο +GREEK CAPITAL LETTER PI:π:928:Π +GREEK CAPITAL LETTER RHO:ρ:929:Ρ +GREEK CAPITAL LETTER SIGMA:σ:931:Σ +GREEK CAPITAL LETTER TAU:τ:932:Τ +GREEK CAPITAL LETTER UPSILON:υ:933:Υ +GREEK CAPITAL LETTER PHI:φ:934:Φ +GREEK CAPITAL LETTER CHI:χ:935:Χ +GREEK CAPITAL LETTER OMEGA:ω:937:Ω +GREEK CAPITAL LETTER ALPHA WITH TONOS:ά:902:Ά +GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA:ϋ:939:Ϋ +GREEK CAPITAL LETTER PSI:ψ:936:Ψ +GREEK CAPITAL LETTER IOTA WITH DIALYTIKA:ϊ:938:Ϊ +LATIN CAPITAL LETTER G WITH BREVE:ğ:286:Ğ +LATIN CAPITAL LETTER E WITH DOT ABOVE:ė:278:Ė +LATIN CAPITAL LETTER R WITH CEDILLA:ŗ:342:Ŗ +LATIN CAPITAL LETTER I WITH OGONEK:ī:302:Į +LATIN CAPITAL LETTER A WITH MACRON:ā:256:Ā +LATIN CAPITAL LETTER E WITH MACRON:ē:274:Ē +LATIN CAPITAL LETTER G WITH CEDILLA:ģ:290:Ģ +LATIN CAPITAL LETTER K WITH CEDILLA:ķ:310:Ķ +LATIN CAPITAL LETTER I WITH MACRON:ī:298:Ī +LATIN CAPITAL LETTER L WITH CEDILLA:ļ:315:Ļ +LATIN CAPITAL LETTER N WITH CEDILLA:ņ:325:Ņ +LATIN CAPITAL LETTER O WITH MACRON:ō:332:Ō +LATIN CAPITAL LETTER U WITH OGONEK:ų:370:Ų +LATIN CAPITAL LETTER U WITH MACRON:ū:362:Ū + +#unused character maps + + +LATIN CAPITAL LETTER A:'41:65:'61 +LATIN CAPITAL LETTER B:'42:66:'62 +LATIN CAPITAL LETTER C:'43:67:'63 +LATIN CAPITAL LETTER D:'44:68:'64 +LATIN CAPITAL LETTER E:'45:69:'65 +LATIN CAPITAL LETTER F:'46:70:'66 +LATIN CAPITAL LETTER G:'47:71:'67 +LATIN CAPITAL LETTER H:'48:72:'68 +LATIN CAPITAL LETTER I:'49:73:'69 +LATIN CAPITAL LETTER J:'4A:74:'6a +LATIN CAPITAL LETTER K:'4B:75:'6b +LATIN CAPITAL LETTER L:'4C:76:'6c +LATIN CAPITAL LETTER M:'4D:77:'6d +LATIN CAPITAL LETTER N:'4E:78:'6e +LATIN CAPITAL LETTER O:'4F:79:'6f +LATIN CAPITAL LETTER P:'50:80:'70 +LATIN CAPITAL LETTER Q:'51:81:'71 +LATIN CAPITAL LETTER R:'52:82:'72 +LATIN CAPITAL LETTER S:'53:83:'73 +LATIN CAPITAL LETTER T:'54:84:'74 +LATIN CAPITAL LETTER U:'55:85:'75 +LATIN CAPITAL LETTER V:'56:86:'76 +LATIN CAPITAL LETTER W:'57:87:'77 +LATIN CAPITAL LETTER X:'58:88:'78 +LATIN CAPITAL LETTER Y:'59:89:'79 +LATIN CAPITAL LETTER Z:'5A:90:'7a +LATIN CAPITAL LETTER A:A:65:a +LATIN CAPITAL LETTER B:B:66:b +LATIN CAPITAL LETTER C:C:67:c +LATIN CAPITAL LETTER D:D:68:d +LATIN CAPITAL LETTER E:E:69:e +LATIN CAPITAL LETTER F:F:70:f +LATIN CAPITAL LETTER G:G:71:g +LATIN CAPITAL LETTER H:H:72:h +LATIN CAPITAL LETTER I:I:73:i +LATIN CAPITAL LETTER J:J:74:j +LATIN CAPITAL LETTER K:K:75:K +LATIN CAPITAL LETTER L:L:76:l +LATIN CAPITAL LETTER M:M:77:m +LATIN CAPITAL LETTER N:N:78:n +LATIN CAPITAL LETTER O:O:79:o +LATIN CAPITAL LETTER P:P:80:p +LATIN CAPITAL LETTER Q:Q:81:q +LATIN CAPITAL LETTER R:R:82:r +LATIN CAPITAL LETTER S:S:83:s +LATIN CAPITAL LETTER T:T:84:t +LATIN CAPITAL LETTER U:U:85:u +LATIN CAPITAL LETTER V:V:86:v +LATIN CAPITAL LETTER W:W:87:x +LATIN CAPITAL LETTER X:X:88:x +LATIN CAPITAL LETTER Y:Y:89:y +LATIN CAPITAL LETTER Z:Z:90:z +NO UNICODE VALUE:'E7:231:\'87 +NO UNICODE VALUE:'83:131:\'8E +NO UNICODE VALUE:'92:146:\'EA +NO UNICODE VALUE:'EE:238:\'97 +NO UNICODE VALUE:'F2:242:\'9C +NO UNICODE VALUE:'CB:203:\'88 +NO UNICODE VALUE:'E9:233:\'8F +NO UNICODE VALUE:'ED:237:\'93 +NO UNICODE VALUE:'F1:241:\'98 +NO UNICODE VALUE:'F4:244:\'9D +NO UNICODE VALUE:'E5:229:\'89 +NO UNICODE VALUE:'E6:230:\'90 +NO UNICODE VALUE:'EB:235:\'94 +NO UNICODE VALUE:'EF:239:\'99 +NO UNICODE VALUE:'F3:243:\'9E +NO UNICODE VALUE:'AF:175:\'BF +NO UNICODE VALUE:'84:132:\'96 +NO UNICODE VALUE:'CD:205:\'9B +NO UNICODE VALUE:'CC:204:\'8B +NO UNICODE VALUE:'80:128:\'8A +NO UNICODE VALUE:'E8:232:\'91 +NO UNICODE VALUE:'EC:236:\'95 +NO UNICODE VALUE:'85:133:\'9A +NO UNICODE VALUE:'86:134:\'9F +NO UNICODE VALUE:'82:130:\'8D +NO UNICODE VALUE:'81:129:\'8C +NO UNICODE VALUE:'E1:129:\'C1 + + +CANCER:a:9803:♋ +LEO:b:9804:♌ +VIRGO:c:9805:♍ +LIBRA:d:9806:♎ +SCORPIOUS:e:9807:♏ +SAGITARRIUS:f:9808:♐ +CAPRICON:g:9809:♑ +AQUARIUS:h:9810:♒ +PISCES:i:9811:♓ +MY LOOPY ET:j:0: +AMPERSAND:k:38:& +BLACK CIRCLE:l:9679:● +SHADOWED WHITE CIRCLE:m:10061:❍ +BLACK SQUARE:n:9632:■ +WHITE SQUARE:o:9633:□ +WHITE SQUARE:p:9633:□ +LOWER RIGHT SHADOWED SQUARE:q:10065:❑ +UPPER RIGHT SHADOWED WHITE SQUARE:r:10066:❒ +BLACK DIAMOND:s:9670:◆ +BLACK DIAMOND:t:9670:◆ +BLACK DIAMOND:u:9670:◆ +BLACK DIAMOND MINUS WHITE X:v:10070:❖ +BLACK DIAMOND MINUS WHITE X:w:10070:❖ +BALLOT BOX WITH X:x:9746:☒ +MY COMPUTER KEY:y:0: +MY APPLE KEY:z:0: +VICTORY HAND:A:9996:✌ +OKAY HAND:B:0: +MY THUMBS UP:C:0: +MY THUMBS DOWN:D:0: +WHITE LEFT POINTING INDEX:E:9756:☜ +WHITE RIGHT POINTING INDEX:F:9758:☞ +WHITE POINTING UP INDEX:G:9757:☝ +WHITE POINTING DOWN INDEX:H:9759:☟ +MY OPEN HAND:I:0: +WHITE SMILING FACE:J:9786:☺ +MY STRAIGHT FACE:K:0: +WHITE FROWNING FACE:L:9785:☹ +MY BOMB:M:0: +SKULL AND CROSSBONES:N:9760:☠ +MY FLAG:O:0: +MY PENNANT:P:0: +AIRPLANE:Q:9992:✈ +CIRCLED OPEN CENTRE EIGHT POINTED STAR:R:9794:♂ +MY TEARDROP:S:0: +SNOWFLAKE:T:10052:❄ +SHADOWED WHITE LATIN CROSS:U:10014:✞ +SHADOWED WHITE LATIN CROSS:V:10014:✞ +MY CELTIC CROSS:W:0: +MALTESE CORSS:X:10016:✠ +STAR OF DAVID:Y:10017:✡ +STAR AND CRESCENT:Z:9770:☪ +MY FOLDER:0:0: +MY OPEN FOLDER:1:0: +MY DOG-EARED DOCUMENT:2:0: +MY DOCUMENT:3:0: +MY PAGES:4:0: +MY FILE CABINETS:5:0: +MY HOUR GLASS:6:0: +MY KEYBOARD:7:0: +MY MOUSE:8:0: +MY BOTTOM OF MOUSE:9:0: +LOWER RIGHT PENCIL:!:9998:✎ +WRITING HAND:@:9996:✌ +UPPER BLADE SCISSORS:#:9985:✁ +MY GLASSES:$:0: +MY BELL:%:0: +ARIES:^:9800:♈ +MY BOOK:&:0: +ENVELOPE:*:9993:✉ +BLACK TELEPHONE:(:9742:☎ +TELEPHONE LOCATION SIGN:):9990:✆ +MY MAILBOX:-:0: +TAURUS:_:9801:♉ +MY BLACK FLOPPY DISK:=:0: +ENVELOPE:+:9993:✉ +HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT:~:10078:❞ +GEMINI:`:9802:♊ +MY WHITE FLOPPY DISK:<:0: +MY TAPE REEL:>:0: +MY OPEN MAILBOX:.:0: +WRITING HAND:?:9996:✌ +EIGHT PETALLED OUTLINED BLACK FLORETTE:|:10049:❁ +MY OPEN MAILBOX:/:0: +MY COMPUETR:\\colon:0: +MY DOWNWARD LEAF:" :0: +MY UPWARD LEAF:" :0: + + +EXCLAMATION MARK:33:33:! +FOR ALL:34:8704:∀ +NUMBER SIGN:35:35:# +THERE EXISTS:36:8707:∃ +PERCENTAGE SIGN:37:37:% +AMPERSAND:38:38:& +CONTAINS AS A MEMBER:39:8715:∋ +LEFT PARENTHESIS:40:40:( +RIGHT PERENTHESIS:41:41:) +ASTERISK OPERATOR:42:8727:∗ +PLUS SIGN:43:43:+ +COMMA:44:44:, +MINUS SIGN:45:8722:− +FULL STOP:46:46:. +DIVISION SLASH:47:8725:∕ +DIGIT ZERO:48:48:0 +DIGIT ONE:49:49:1 +DIGIT TWO:50:50:2 +DIGIT THREE:51:51:3 +DIGIT FOUR:52:52:4 +DIGIT FIVE:53:53:5 +DIGIT SIX:54:54:6 +DIGIT SEVEN:55:55:7 +DIGIT EIGHT:56:56:8 +DIGIT NINE:57:57:9 +RATIO:58:8758:∶ +SEMICOLON:59:59:; +LESS-THAN SIGN:60:60:< +EQUALS SIGN TO:61:61:= +GREATER-THAN SIGN:62:62:> +QUESTION MARK:63:63:? +APPROXTIMATELY EQUAL TO:64:8773:≅ +GREEK CAPITOL LETTER ALPHA:65:913:Α +GREEK CAPAITOL LETTER BETA:66:914:Β +GREEK CAPITOL LETTER CHI:67:935:Χ +GREEK CAPITOL LETTER DELTA:68:916:Δ +GREEK CAPITOL LETTER EPSILON:69:917:Ε +GREEK CAPITOL LETTER PHI:70:934:Φ +GREEK CAPITOL LETTER GAMMA:71:915:Γ +GREEK CAPITOL LETTER ETA:72:919:Η +GREEK CAPITOL LETTER ITOA:73:913:Α +GREEK THETA SYMBOL:74:977:ϑ +GREEK CAPITOL LETTER KAPPA:75:922:Κ +GREEK CAPITOL LETTER LAMBDA:76:923:Λ +GREEK CAPITOL LETTER MU:77:924:Μ +GREEK CAPITOL LETTER NU:78:925:Ν +GREEK CAPITOL LETTER OMICRON:79:927:Ο +GREEK CAPITAL LETTER PI:80:928:Π +GREEK CAPITOL LETTER THETA:81:920:Θ +GREEK CAPITOL LETTER RHO:82:929:Ρ +GREEK CAPITOL LETTER SIGMA:83:931:Σ +GREEK CAPITOL LETTER TAU:84:932:Τ +GREEK CAPITOL LETTER UPSILON:85:933:Υ +GREEK LETTER STIGMA:86:986:Ϛ +GREEK CAPITOL LETTER OMEGA:87:937:Ω +GREEK CAPITOL LETTER XI:88:926:Ξ +GREEK CAPITOL LETTER PSI:89:936:Ψ +GREEK CAPITOL LETTER ZETA:90:918:Ζ +LEFT SQUARE BRACKET:91:91:[ +THEREFORE:92:8756:∴ +RIGHT SQUARE BRACKET:93:93:] +UP TACK:94:8869:⊥ +MODIFIER LETTER LOW MACRON:95:717:ˍ +MODIFIER LETTER MACRON:96:713:ˉ +GREEK SMALL LETTER ALPHA:97:945:α +GREEK SMALL LETTER BETA:98:946:β +GREEK SMALL LETTER CHI:99:967:χ +GREEK SMALL LETTER DELTA:100:948:δ +GREEK SMALL LETTER EPSILON:101:949:ε +GREEK PHI SYMBOL:102:981:ϕ +GREEK MSALL LETTER DELTA:103:947:γ +GREEK SMALL LETTER ETA:104:951:η +GREEK SMALL LETTER IOTA:105:953:ι +GREEK SMALL LETTER PHI:106:966:φ +GREEK SMALL LETTER KAPPA:107:954:κ +GREEK SMALL LETTER LAMDA:108:955:λ +GREEK SMALL LETTER MU:109:956:μ +GREEK SMALL LETTER NU:110:957:ν +GREEK SMALL LETTER OMICRON:111:959:ο +GREEK SMALL LETTER PI:112:960:π +GREEK SMALL LETTER THETA:113:952:θ +GREEK SMALL LETTER RHO:114:961:ρ +GREEK SMALL LETTER SIGMA:115:963:σ +GREEK SMALL LETTER TAU:116:964:τ +GREEK SMALL LETTER UPSILON:117:965:υ +GREEK PI SYMBOL:118:982:ϖ +GREEK SMALL LETTER OMEGA:119:969:ω +GREEK SMALL LETTER XI:120:958:ξ +GREEK SMALL LETTER PHI:121:966:φ +GREEK SMALL LETTER ZETA:122:950:ζ +LEFT CURLY BRACKET:123:123:{ +DIVIDES:124:8739:∣ +RIGHT CURLY BRACKET:125:125:} +TILDE OPERATOR:126:8764:∼ +GREEK UPSILON WITH HOOK SYMBOL:161:978:ϒ +COMBINING ACUTE TONE MARK:162:833:́ +LESS THAN OR EQUAL TO:163:8804:≤ +DIVISION SLASH:164:8725:∕ +INFINITY:165:8734:∞ +SMALL LETTER F:166:15:f +BLACK CLUB SUIT:167:9827:♣ +BLACK DIAMOND SUIT:168:9830:♦ +BLACK HEART SUIT:169:9829:♥ +BLACK SPADE SUIT:170:9824:♠ +LEFT RIGHT ARROW:171:8596:↔ +LEFTWARDS ARROW:172:8592:← +UPWARDS ARROW:173:8593:↑ +RIGHTWARDS ARROW:174:8594:→ +DOWNWARDS ARROW:175:8595:↓ +DEGREE SIGN:176:176:° +PLUS OR MINUS SIGN:177:177:± +DOUBLE ACUTE ACCENT:178:733:˝ +GREATER THAN OR EQUAL TO:179:8805:≥ +MULTIPLICATION SIGN:180:215:× +DON'T KNOW:181:8733:∝ +PARTIAL DIFFERENTIAL:182:8706:∂ +BULLET:183:183:· +DIVISION:184:247:÷ +NOT EQUAL TO:185:8800:≠ +IDENTICAL TO:186:8801:≡ +ALMOST EQUAL TO:187:8776:≈ +MIDLINE HORIZONTAL ELLIPSES:188:8943:⋯ +DIVIDES:189:8739:∣ +BOX DRAWINGS LIGHT HORIZONTAL:190:9472:─ +DOWNWARDS ARROW WITH TIP LEFTWARDS:191:8626:↲ +CIRCLED TIMES:196:8855:⊗ +CIRCLED PLUS:197:8853:⊕ +EMPTY SET:198:8709:∅ +INTERSECTION:199:8745:∩ +UNION:200:8746:∪ +SUPERSET OF:201:8835:⊃ +SUPERSET OF OR EQUAL TO:202:8839:⊇ +NIETHER A SUBSET OR EQUAL TO:203:8836:⊄ +SUBSET OF:204:8834:⊂ +SUBSET OR EQUAL TO:205:8838:⊆ +ELEMENT OF:206:8712:∈ +NOT AN ELEMENT OF:207:8713:∉ +ANGLE:208:8736:∠ +WHITE DOWN POINTING TRIANBLE:209:9661:▽ +REGISTERED SIGN:210:174:® +COPYRIGHT:211:169:© +TRADEMARK SYMBOL:212:8482:™ +NARY OPERATOR:213:8719:∏ +SQUARE ROOT:214:8730:√ +BULLET OPERATOR:215:8729:∙ +NOT SIGN:216:172:¬ +LOGICAL AND:217:8743:∧ +LOGICAL OR:218:8744:∨ +LEFT RIGHT DOUBLE ARROW:219:8660:⇔ +LEFTWARDS DOUBLE ARROW:220:8656:⇐ +UPWARDS DOUBLE ARROW:221:8657:⇑ +RIGHTWARDS DOUBLE ARROW:222:8658:⇒ +DOWNWARDS DOUBLE ARROW:223:8659:⇓ +BETWEEN:224:8812:≬ +MATHMATICAL LEFT ANGELBRACKET:225:10216:⟨ +REGISTERED SIGN:226:174:® +COPYRIGHT:227:169:© +TRADEMARK SYMBOL:228:8482:™ +N-ARY SUMMATION:229:8721:∑ +LARGE LEFT PARENTHESIS PART1:230:0: +LARGE LEFT PARENTHESIS PART2:231:0: +LARGE LEFT PARENTHESIS PART3:232:0: +LARGE LEFT SQUARE BRACKET PART1:233:0: +LARGE LEFT SQUARE BRACKET PART2:234:0: +LARGE LEFT SQUARE BRACKET PART3:235:0: +LARGE LEFT BRACKET PART1:236:0: +LARGE LEFT BRACKET PART2:237:0: +LARGE LEFT BRACKET PART3:238:0: +DIVIDES:239:8739:∣ +MATHMATICAL RIGHT ANGLE BRACKET:241:10217:⟩ +INTEGRAL:242:8747:∫ +LARGE INTEGRAL PART 1:243:0: +LARGE INTEGRAL PART 2:244:0: +LARGE INTEGRAL PART 3:245:0: +LARGE RIGHT PARENTHESIS PART1:246:0: +LARGE RIGHT PARENTHESIS PART2:247:0: +LARGE RIGHT PARENTHESIS PART3:248:0: +LARGE RIGHT SQAURE BRACKET PART1:249:0: +LARGE RIGHT SQUARE BRACKET PART2:250:0: +LARGE RIGHT SQUARE BRACKETPART3:251:0: +LARGE RIGHT BRACKET PART1:252:0: +LARGE RIGHT BRACKETPART2:253:0: +LARGE RIGHT BRACKETPART3:254:0: +DOUBLE ACUTE ACCENT:178:733:˝ + + +EXCLMATION POINT:33:unknown:! +FOR ALL:34:8704:∀ +POUND SIGN:35:unknown:# +THERE EXISTS:36:8707:∃ +PERCENTAGE SIGN:37:unknown:% +AMPERSAND:38:38:& +CONTAINS AS A MEMBER:39:unknown:∋ +LEFT PARENTHESIS:40:unknown:( +RIGHT PERENTHESIS:41:unknown:) +ASTERISK OPERATOR:42:8727:∗ +PLUS:43:unknown:+ +COMMA:44:unknown:, +MINUS SIGN:45:8722:− +PERIOD:46:unknown:. +DIVISION SLASH:47:8725:∕ +ZERO:48:0:0 +ONE:49:1:1 +TWO:50:2:2 +THREE:51:3:3 +FOUR:52:4:4 +FIVE:53:5:5 +SIX:54:6:6 +SEVEN:55:7:7 +EIGHT:56:8:8 +NINE:57:9:9 +RATIO:58:8758:∶ +SEMICOLON:59:unknown:; +LESS THAN:60:unknown:< +EQAULS TO:61:unknown:= +GREATER THAN:62:unknown:> +QUESTION MARK:63:unknown:? +APPROXTIMATELY EQUAL TO:64:8773:≅ +GREEK CAPITOL LETTER ALPHA:65:913:Α +GREEK CAPAITOL LETTER BETA:66:914:Β +GREEK CAPITOL LETTER CHI:67:unknown:Χ +GREEK CAPITOL LETTER DELTA:68:916:Δ +GREEK CAPITOL LETTER EPSILON:69:917:Ε +GREEK CAPITOL LETTER PHI:70:unknown:Φ +GREEK CAPITOL LETTER GAMMA:71:915:Γ +GREEK CAPITOL LETTER ETA:72:919:Η +GREEK CAPITOL LETTER ITOA:73:913:Α +GREEK THETA SYMBOL:74:unknown:ϑ +GREEK CAPITOL LETTER KAPPA:75:unknown:Κ +GREEK CAPITOL LETTER LAMBDA:76:unknown:Λ +GREEK CAPITOL LETTER MU:77:unknown:Μ +GREEK CAPITOL LETTER NU:78:unknown:Ν +GREEK CAPITOL LETTER OMICRON:79:unknown:Ο +GREEK CAPITAL LETTER PI:80:unknown:Π +GREEK CAPITOL LETTER THETA:81:920:Θ +GREEK CAPITOL LETTER RHO:82:unknown:Ρ +GREEK CAPITOL LETTER SIGMA:83:unknown:Σ +GREEK CAPITOL LETTER TAU:84:unknown:Τ +GREEK CAPITOL LETTER UPSILON:85:unknown:Υ +GREEK LETTER STIGMA:86:unknown:Ϛ +GREEK CAPITOL LETTEROMEGA:87:unknown:Ω +GREEK CAPITOL LETTER XI:88:unknown:Ξ +GREEK CAPITOL LETTER PSI:89:unknown:Ψ +GREEK CAPITOL LETTER ZETA:90:918:Ζ +LEFT BRACKET:91:unknown:[ +THEREFORE:92:8756:∴ +LEFT BRACKET:93:unknown:[ +UP TACK:94:unknown:⊥ +MODIFIER LETTER LOW MACRON:95:unknown:ˍ +MODIFIER LETTER MACRON:96:unknown:ˉ +GREEK SMALL LETTER ALPHA:97:unknown:α +GREEK SMALL LETTER BETA:98:unknown:β +GREEK SMALL LETTER CHI:99:unknown:χ +GREEK SMALL LETTER DELTA:100:unknown:δ +GREEK SMALL LETTER EPSILON:101:unknown:ε +GREEK PHI SYMBOL:102:unknown:ϕ +GREEK MSALL LETTER DELTA:103:unknown:γ +GREEK SMALL LETTER ETA:104:unknown:η +GREEK SMALL LETTER IOTA:105:unknown:ι +GREEK SMALL LETTER PHI:106:unknown:φ +GREEK SMALL LETTER KAPPA:107:unknown:κ +GREEK SMALL LETTER LAMDA:108:unknown:λ +GREEK SMALL LETTER MU:109:unknown:μ +GREEK SMALL LETTER NU:110:unknown:ν +GREEK SMALL LETTER OMICRON:111:unknown:ο +GREEK SMALL LETTER PI:112:unknown:π +GREEK SMALL LETTER THETA:113:unknown:θ +GREEK SMALL LETTER RHO:114:unknown:ρ +GREEK SMALL LETTER SIGMA:115:unknown:σ +GREEK SMALL LETTER TAU:116:unknown:τ +GREEK SMALL LETTER UPSILON:117:unknown:υ +GREEK PI SYMBOL:118:unknown:ϖ +GREEK SMALL LETTER OMEGA:119:unknown:ω +GREEK SMALL LETTER XI:120:unknown:ξ +GREEK SMALL LETTER PHI:121:unknown:φ +GREEK SMALL LETTER ZETA:122:unknown:ζ +RIGHT BRACKET:123:unknown:{ +DIVIDES:124:8739:∣ +LEFT BRACKET:125:unknown:} +TILDE OPERATOR:126:unknown:∼ +GREEK UPSILON WITH HOOK SYMBOL:161:unknown:ϒ +COMBINING ACUTE TONE MARK:162:833:́ +LESS THAN OR EQUAL TO:163:8804:≤ +DIVISION SLASH:164:8725:∕ +INFINITY:165:unknown:∞ +SMALL LETTER F:166:unknown:f +BLACK CLUB SUIT:167:9827:♣ +BLACK DIAMOND SUIT:168:9830:♦ +BLACK HEART SUIT:169:9829:♥ +BLACK SPADE SUIT:170:9824:♠ +LEFT RIGHT ARROW:171:8596:↔ +LEFTWARDS ARROW:172:8592:← +UPWARDS ARROW:173:8593:↑ +RIGHTWARDS ARROW:174:8594:→ +DOWNWARDS ARROW:175:8595:↓ +DEGREE SIGN:176:unknown:° +PLUS OR MINUS SIGN:177:unknown:± +DOUBLE ACUTE ACCENT:178:unknown:˝ +GREATER THAN OR EQUAL TO:179:8805:≥ +MULTIPLICATION SIGN:180:unknown:× +DON' T KNOW:181:unknown:∝ +PARTIAL DIFFERENTIAL:182:8706:∂ +BULLET?:183:unknown:· +DIVISION:184:unknown:÷ +NOT EQUAL TO:185:8800:≠ +IDENTICAL TO:186:8801:≡ +ALMOST EQUAL TO:187:8776:≈ +MIDLINE HORIZONTAL ELLIPSES:188:unknown:⋯ +DIVIDES:189:8739:∣ +BOX DRAWINGS LIGHT HORIZONTAL:190:9472:─ +DOWNWARDS ARROW WITH TIP LEFTWARDS:191:unknown:↲ +CIRCLED TIMES:196:8855:⊗ +CIRCLED PLUS:197:8853:⊕ +EMPTY SET:198:8709:∅ +INTERSECTION:199:8745:∩ +UNION:200:unknown:∪ +SUPERSET OF:201:8835:⊃ +SUPERSET OF OR EQUAL TO:202:8839:⊇ +NIETHER A SUBSET OR EQUAL TO:203:8836:⊄ +SUBSET OF:204:8834:⊂ +SUBSET OR EQUAL TO:205:8838:⊆ +ELEMENT OF:206:8712:∈ +NOT AN ELEMENT OF:207:8713:∉ +ANGLE:208:8736:∠ +WHITE DOWN POINTING TRIANBLE:209:unknown:▽ +REGISTERED SIGN:210:unknown:® +COPYRIGHT:211:unknown:© +NARY OPERATOR:213:unknown:∏ +SQUARE ROOT:214:unknown:√ +BULLET OPERATOR:215:8729:∙ +NOT SIGN:216:unknown:¬ +LOGICAL AND:217:8743:∧ +LOGICAL OR:218:8744:∨ +LEFT RIGHT DOUBLE ARROW:219:unknown:⇔ +LEFTWARDS DOUBLE ARROW:220:unknown:⇐ +UPWARDS DOUBLE ARROW:221:unknown:⇑ +RIGHTWARDS DOUBLE ARROW:222:unknown:⇒ +DOWNWARDS DOUBLE ARROW:223:unknown:⇓ +BETWEEN:224:unknown:≬ +MATHMATICAL LEFT ANGELBRACKET:225:unknown:⟨ +REGISTERED SIGN:226:unknown:® +COPYRIGHT:227:unknown:© +N-ARY SUMMATION:229:8721:∑ +LARGE LEFT PARENTHESIS PART1:230:unknown: +LARGE LEFT PARENTHESIS PART2:231:unknown: +LARGE LEFT PARENTHESIS PART3:232:unknown: +LARGE LEFT SQUARE BRACKET PART1:233:unknown: +LARGE LEFT SQUARE BRACKET PART2:234:unknown: +LARGE LEFT SQUARE BRACKET PART3:235:unknown: +LARGE LEFT BRACKET PART1:236:unknown: +LARGE LEFT BRACKET PART2:237:unknown: +LARGE LEFT BRACKET PART3:238:unknown: +DIVIDES:239:8739:∣ +MATHMATICAL RIGHT ANGLE BRACKET:241:unknown:27E9 +INTEGRAL:242:unknown:∫ +LARGE INTEGRAL PART 1:243:unknown: +LARGE INTEGRAL PART 2:244:unknown: +LARGE INTEGRAL PART 3:245:unknown: +LARGE RIGHT PARENTHESIS PART1:246:unknown: +LARGE RIGHT PARENTHESIS PART2:247:unknown: +LARGE RIGHT PARENTHESIS PART3:248:unknown: +LARGE RIGHT SQAURE BRACKET PART1:249:unknown: +LARGE RIGHT SQUARE BRACKET PART2:250:unknown: +LARGE RIGHT SQUARE BRACKETPART3:251:unknown: +LARGE RIGHT BRACKET PART1:252:unknown: +LARGE RIGHT BRACKETPART2:253:unknown: +LARGE RIGHT BRACKETPART3:254:unknown: +DOUBLE ACUTE ACCENT:178:unknown:02DD +TRADEMARK SYMBOL:212:unknown:™ +TRADEMARK SYMBOL:228:unknown:™ + + +GREEK CAPITAL LETTER ALPHA:A:65:Α +GREEK CAPITAL LETTER BETA:B:66:Β +GREEK CAPITAL LETTER CHI:C:67:Χ +GREEK CAPITAL LETTER DELTA:D:68:Δ +GREEK CAPITAL LETTER EPSILON:E:69:Ε +GREEK CAPITAL LETTER PHI:F:70:Φ +GREEK CAPITAL LETTER GAMMA:G:71:Γ +GREEK CAPITAL LETTER ETA:H:72:Η +GREEK CAPITAL LETTER IOTA:I:73:Ι +GREEK THETA SYMBOL:J:74:ϑ +GREEK CAPITAL LETTER KAPPA:K:75:Κ +GREEK CAPITAL LETTER LAMDA:L:76:Λ +GREEK CAPITAL LETTER MU:M:77:Μ +GREEK CAPITAL LETTER NU:N:78:Ν +GREEK CAPITAL LETTER OMICRON:O:79:Ο +GREEK CAPITAL LETTER PI:P:80:Π +GREEK CAPITAL LETTER THETA:T:81:Θ +GREEK CAPITAL LETTER RHO:R:82:Ρ +GREEK CAPITAL LETTER SIGMA:S:83:Σ +GREEK CAPITAL LETTER TAU:T:84:Τ +GREEK CAPITAL LETTER UPSILON:U:85:Υ +GREEK SMALL LETTER FINAL SIGMA:V:86:Ϛ +GREEK CAPITAL LETTER OMEGA:W:87:Ω +GREEK CAPITAL LETTER XI:X:88:Ξ +GREEK CAPITAL LETTER PSI:Y:89:Ψ +GREEK CAPITAL LETTER ZETA:Z:90:Ζ +GREEK SMALL LETTER ALPHA:a:97:α +GREEK SMALL LETTER BETA:b:98:β +GREEK SMALL LETTER CHI:c:99:χ +GREEK SMALL LETTER DELTA:d:100:δ +GREEK SMALL LETTER EPSILON:e:101:ε +GREEK SMALL LETTER PHI:f:102:φ +GREEK SMALL LETTER GAMMA:g:103:γ +GREEK SMALL LETTER ETA:h:104:η +GREEK SMALL LETTER IOTA:i:105:ι +GREEK PHI SYMBOL:j:106:φ +GREEK SMALL LETTER KAPPA:k:107:κ +GREEK SMALL LETTER LAMDA:l:108:λ +GREEK SMALL LETTER MU:m:109:μ +GREEK SMALL LETTER NU:n:110:ν +GREEK SMALL LETTER OMICRON:o:111:ο +GREEK SMALL LETTER PI:p:112:π +GREEK SMALL LETTER THETA:q:113:θ +GREEK SMALL LETTER RHO:r:114:ρ +GREEK SMALL LETTER SIGMA:s:115:σ +GREEK SMALL LETTER TAU:t:116:τ +GREEK SMALL LETTER UPSILON:u:117:υ +GREEK PI SYMBOL:v:118:ϖ +GREEK SMALL LETTER OMEGA:w:119:ω +GREEK SMALL LETTER XI:x:120:ξ +GREEK SMALL LETTER PSI:y:121:ψ +GREEK SMALL LETTER ZETA:z:122:ζ +APROXTIMATELY EQUAL TO:@:unknown:≅ +THERE EXISTS:$:unknown:2203 +UP TACK:^:unknown:⊥ + + +STAR OF DAVID:A:10017:✡ +FOUR TEARDROP-SPOKED ASTERISK:B:10018:✢ +FOUR BALLOON-SPOKED ASTERISK:C:10019:✣ +HEAVY FOUR BALLOON-SPOKED ASTERISK:D:10020:✤ +FOUR CLUB-SPOKED ASTERISK:E:10021:✥ +BLACK FOUR POINTED STAR:F:10022:✦ +WHITE FOUR POINTED STAR:G:10023:✧ +BLACK STAR:H:9989:✅ +STRESS OUTLINED WHITE STAR:I:10025:✩ +CIRCLED WHITE STAR:J:10026:✪ +OPEN CENTRE BLACK STAR:K:10027:✫ +BLACK CENTRE WHITE STAR:L:10028:✬ +OUTLINED BLACK STAR:M:10029:✭ +HEAVY OUTLINED BLACK STAR:N:10030:✮ +PINWHEEL STAR:O:10031:✯ +SHADOWED WHITE STAR:P:10032:✰ +HEAVY ASTERISK:Q:10033:✱ +OPEN CENTRE ASTERISK:R:10034:✲ +EIGHT SPOKED ASTERISK:S:10035:✳ +EIGHT POINTED BLACK STAR:T:10036:✴ +EIGHT POINTED PINWHEEL STAR:U:10037:✵ +SIX POINTED BLACK STAR:V:10038:✶ +EIGHT POINTED RECTILINEAR BLACK STAR:W:10039:✷ +HEAVY EIGHT POINTED RECTILINEAR BLACK STAR:X:10040:✸ +TWELVE POINTED BLACK STAR:Y:10041:✹ +SIXTEEN POINTED ASTERISK:Z:10042:✺ +EIGHT PETALLED OUTLINED BLACK FLORETTE:a:10049:❁ +CIRCLED OPEN CENTRE EIGHT POINTED STAR:b:10050:❂ +HEAVY TEARDROP-SPOKED PINWHEEL ASTERISK:c:10051:❃ +SNOWFLAKE:d:10052:❄ +TIGHT TRIFOLIATE SNOWFLAKE:e:10053:❅ +HEAVY CHEVRON SNOWFLAKE:f:10054:❆ +SPARKLE:g:10055:❇ +HEAVY SPARKLE:h:10056:❈ +BALLOON-SPOKED ASTERISK:i:10057:❉ +TEARDROP-SPOKED ASTERISK:j:10043:✻ +HEAVY TEARDROP-SPOKED ASTERISK:k:10045:✽ +BLACK CIRCLE:l:9679:● +SHADOWED WHITE CIRCLE:m:10061:❍ +BLACK SQUARE:n:9632:■ +LOWER RIGHT DROP-SHADOWED SQUARE:o:10063:❏ +UPPER RIGHT DROP-SHADOWED WHITE SQUARE:p:10064:❐ +LOWER RIGHT SHADOWED SQUARE:q:10065:❑ +UPPER RIGHT SHADOWED WHITE SQUARE:r:10066:❒ +BLACK UP-POINTING TRIANGLE:s:9650:▲ +BLACK DOWN-POINTING TRIANGLE:t:9660:▼ +BLACK DIAMOND:u:9670:◆ +BLACK DIAMOND MINUS WHITE X:v:10070:❖ +RIGHT HALF BLACK CIRCLE:w:9479:┇ +LIGHT VERTICAL BAR:x:10072:❘ +MEDIUM VERTICAL BAR:y:10073:❙ +HEAVY VERTICAL BAR:z:10074:❚ +WHITE NIB:1:10001:✑ +BLACK NIB:2:10002:✒ +CHECKMARK:3:10003:✓ +HEAVY CHECKMARK:4:10004:✔ +MULTIPLICATION X:5:10005:✕ +HEAVY MULTIPLICATION X:6:10006:✖ +BALLOT X:7:10007:✗ +HEAVY BALLOT X:8:10008:✘ +OUTLINED GREEK CROSS:9:10009:✙ +UPPER RIGHT PENCIL:0:10000:✐ +UPPER BLADE SCISSORS:!:9985:✁ +MALTESE CROSS:@:10016:✠ +LOWER BLADE SCISSORS:#:9987:✃ +WHITE SCISSORS:$:9988:✄ +BLACK TELEPHONE:%:9742:☎ +SIX PETALLED BLACK AND WHITE FLORETTE:^:10046:✾ +TELEPHONE LOCATION SIGN:&:9990:✆ +BLACK RIGHT POINTING INDEX:*:9755:☛ +AIRPLANE:(:9992:✈ +ENVELOPE:):9993:✉ +HEAVY GREK CROSS:\\colon:10010:✚ +OUTLINED LATIN CROSS:?:10015:✟ +PENCIL:/:9999:✏ +OPEN CENTRE TEARDROP-SPOKED ASTERISK:\\:10044:✼ +WHITE RIGHT POINTING INDEX:+:9758:☞ +WRITING HAND:-:9997:✍ +LATIN CROSS:=:10013:✝ +HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT:~:10078:❞ + + +LEFT DOUBLE QUOTATION MARK:LDBLQUOTE :8220:“ +RIGHT DOUBLE QUOTATION MARK:RDBLQUOTE :8221:” +RIGHT SINGLE QUOTATION MARK:RQUOTE :8217:’ +LEFT SINGLE QUOTATION MARK:LQUOTE :8216:‘ +EM DASH:EMDASH :8212:— +EN DASH:ENDASH :8211:– +MIDDLE DOT:BULLET :183:· +NO-BREAK SPACE:~ :167:§ +HORIZONTAL TABULATION:TAB :9: + + +NULL:\xef:0:&#xnull; + + +""" diff --git a/ebook_converter/ebooks/rtf2xml/check_brackets.py b/ebook_converter/ebooks/rtf2xml/check_brackets.py new file mode 100644 index 0000000..c3ebfcd --- /dev/null +++ b/ebook_converter/ebooks/rtf2xml/check_brackets.py @@ -0,0 +1,62 @@ +from __future__ import unicode_literals, absolute_import, print_function, division +######################################################################### +# # +# # +# copyright 2002 Paul Henry Tremblay # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # +# General Public License for more details. # +# # +# # +######################################################################### + + +from . import open_for_read + + +class CheckBrackets: + """Check that brackets match up""" + + def __init__(self, bug_handler=None, file=None): + self.__file=file + self.__bug_handler = bug_handler + self.__bracket_count=0 + self.__ob_count = 0 + self.__cb_count = 0 + self.__open_bracket_num = [] + + def open_brack(self, line): + num = line[-5:-1] + self.__open_bracket_num.append(num) + self.__bracket_count += 1 + + def close_brack(self, line): + num = line[-5:-1] + try: + last_num = self.__open_bracket_num.pop() + except: + return False + if num != last_num: + return False + self.__bracket_count -= 1 + return True + + def check_brackets(self): + line_count = 0 + with open_for_read(self.__file) as read_obj: + for line in read_obj: + line_count += 1 + self.__token_info = line[:16] + if self.__token_info == 'ob value pair to the color dictionary, with the number + as the key, and the hex number as the value. Write an empty tag + with the hex number and number as attributes. Add one to the color + number. Reset the color string to '#' + """ + hex_num = line[-3:-1] + self.__color_string += hex_num + self.__color_dict[self.__color_num] = self.__color_string + self.__write_obj.write( + 'mi%s%s\n' % (self.__color_num, self.__color_string) + ) + self.__color_num += 1 + self.__color_string = '#' + + def __in_color_func(self, line): + """ + Requires: + line + Returns: + nothing + Logic: + Check if the end of the color table has been reached. If so, + change the state to after the color table. + Othewise, get a function by passing the self.__token_info to the + state dictionary. + """ + # mi -1: + line = re.sub(self.__line_color_exp, self.__sub_from_line_color, line) + self.__write_obj.write(line) + """ + if num == 0: + hex_num = 'false' + else: + hex_num = self.__color_dict.get(num) + if hex_num == None: + if self.__run_level > 0: + sys.stderr.write( + 'module is colors.py\n' + 'function is self.__after_color_func\n' + 'no value in self.__color_dict for key %s\n' % num + ) + if self.__run_level > 3: + sys.stderr.write( + 'run level is %s\n' + 'Script will now quit\n' + % self.__run_level) + else: + self.__write_obj.write( + 'cw 3: + msg = 'can\'t make integer from string\n' + raise self.__bug_handler(msg) + else: + return 'bdr-color_:no-value' + hex_num = self.__figure_num(num) + return 'bdr-color_:%s' % hex_num + + def __figure_num(self, num): + if num == 0: + hex_num = 'false' + else: + hex_num = self.__color_dict.get(num) + if hex_num is None: + hex_num = '0' + if self.__run_level > 3: + msg = 'no value in self.__color_dict' \ + 'for key %s at line %d\n' % (num, self.__line) + raise self.__bug_handler(msg) + return hex_num + + def __do_nothing_func(self, line): + """ + Bad RTF will have text in the color table + """ + pass + + def convert_colors(self): + """ + Requires: + nothing + Returns: + nothing (changes the original file) + Logic: + Read one line in at a time. Determine what action to take based on + the state. If the state is before the color table, look for the + beginning of the color table. + If the state is in the color table, create the color dictionary + and print out the tags. + If the state if afer the color table, look for lines with color + info, and substitute the number with the hex number. + """ + self.__initiate_values() + with open_for_read(self.__file) as read_obj: + with open_for_write(self.__write_to) as self.__write_obj: + for line in read_obj: + self.__line+=1 + self.__token_info = line[:16] + action = self.__state_dict.get(self.__state) + if action is None: + try: + sys.stderr.write('no matching state in module fonts.py\n') + sys.stderr.write(self.__state + '\n') + except: + pass + action(line) + copy_obj = copy.Copy(bug_handler=self.__bug_handler) + if self.__copy: + copy_obj.copy_file(self.__write_to, "color.data") + copy_obj.rename(self.__write_to, self.__file) + os.remove(self.__write_to) diff --git a/ebook_converter/ebooks/rtf2xml/combine_borders.py b/ebook_converter/ebooks/rtf2xml/combine_borders.py new file mode 100644 index 0000000..547f7d7 --- /dev/null +++ b/ebook_converter/ebooks/rtf2xml/combine_borders.py @@ -0,0 +1,93 @@ +from __future__ import unicode_literals, absolute_import, print_function, division +######################################################################### +# # +# # +# copyright 2002 Paul Henry Tremblay # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # +# General Public License for more details. # +# # +# # +######################################################################### +import os + +from calibre.ebooks.rtf2xml import copy +from calibre.ptempfile import better_mktemp +from . import open_for_read, open_for_write + + +class CombineBorders: + """Combine borders in RTF tokens to make later processing easier""" + + def __init__(self, + in_file , + bug_handler, + copy=None, + run_level=1, + ): + self.__file = in_file + self.__bug_handler = bug_handler + self.__copy = copy + self.__write_to = better_mktemp() + self.__state = 'default' + self.__bord_pos = 'default' + self.__bord_att = [] + + def found_bd(self, line): + # cw' % info) + + def __empty_func(self, line): + """ + Print out empty tag and newlines when needed. + """ + info = line[17:-1] + self.__write_obj.write( + '<%s/>' % info) + self.__new_line = 0 + if info in self.__block: + self.__write_new_line() + if info in self.__two_new_line: + self.__write_extra_new_line() + + def __open_att_func(self, line): + """ + Process lines for open tags that have attributes. + The important info is between [17:-1]. Take this info and split it + with the delimeter '<'. The first token in this group is the element + name. The rest are attributes, separated fromt their values by '>'. So + read each token one at a time, and split them by '>'. + """ + # mi + info = line[17:-1] + tokens = info.split("<") + element_name = tokens[0] + tokens = tokens[1:] + self.__write_obj.write('<%s' % element_name) + for token in tokens: + groups = token.split('>') + try: + val = groups[0] + att = groups[1] + att = att.replace('"', '"') + att = att.replace("'", '"') + self.__write_obj.write( + ' %s="%s"' % (val, att) + ) + except: + if self.__run_level > 3: + msg = 'index out of range\n' + raise self.__bug_handler(msg) + self.__write_obj.write('>') + self.__new_line = 0 + if element_name in self.__block: + self.__write_new_line() + if element_name in self.__two_new_line: + self.__write_extra_new_line() + + def __empty_att_func(self, line): + """ + Same as the __open_att_func, except a '/' is placed at the end of the tag. + """ + # mi + info = line[17:-1] + tokens = info.split("<") + element_name = tokens[0] + tokens = tokens[1:] + self.__write_obj.write('<%s' % element_name) + for token in tokens: + groups = token.split('>') + val = groups[0] + att = groups[1] + att = att.replace('"', '"') + att = att.replace("'", '"') + self.__write_obj.write( + ' %s="%s"' % (val, att)) + self.__write_obj.write('/>') + self.__new_line = 0 + if element_name in self.__block: + self.__write_new_line() + if element_name in self.__two_new_line: + self.__write_extra_new_line() + + def __close_func(self, line): + """ + Print out the closed tag and new lines, if appropriate. + """ + # mi' % info) + self.__new_line = 0 + if info in self.__block: + self.__write_new_line() + if info in self.__two_new_line: + self.__write_extra_new_line() + + def __text_func(self, line): + """ + Simply print out the information between [17:-1] + """ + # tx') + elif not check_encoding_obj.check_encoding(self.__file, self.__encoding, verbose=False): + self.__write_obj.write('') + self.__convert_utf = True + else: + self.__write_obj.write('') + sys.stderr.write('Bad RTF encoding, revert to US-ASCII chars and' + ' hope for the best') + self.__bad_encoding = True + self.__new_line = 0 + self.__write_new_line() + if self.__no_dtd: + pass + elif self.__dtd_path: + self.__write_obj.write( + '' % self.__dtd_path + ) + elif self.__dtd_path == '': + # don't print dtd if further transformations are going to take + # place + pass + else: + self.__write_obj.write( + '' % public_dtd + ) + self.__new_line = 0 + self.__write_new_line() + + def convert_to_tags(self): + """ + Read in the file one line at a time. Get the important info, between + [:16]. Check if this info matches a dictionary entry. If it does, call + the appropriate function. + The functions that are called: + a text function for text + an open function for open tags + an open with attribute function for tags with attributes + an empty with attribute function for tags that are empty but have + attribtes. + a closed function for closed tags. + an empty tag function. + """ + self.__initiate_values() + with open_for_write(self.__write_to) as self.__write_obj: + self.__write_dec() + with open_for_read(self.__file) as read_obj: + for line in read_obj: + self.__token_info = line[:16] + action = self.__state_dict.get(self.__token_info) + if action is not None: + action(line) + # convert all encodings to UTF8 or ASCII to avoid unsupported encodings in lxml + if self.__convert_utf or self.__bad_encoding: + copy_obj = copy.Copy(bug_handler=self.__bug_handler) + copy_obj.rename(self.__write_to, self.__file) + with open_for_read(self.__file) as read_obj: + with open_for_write(self.__write_to) as write_obj: + for line in read_obj: + write_obj.write(line) + copy_obj = copy.Copy(bug_handler=self.__bug_handler) + if self.__copy: + copy_obj.copy_file(self.__write_to, "convert_to_tags.data") + copy_obj.rename(self.__write_to, self.__file) + os.remove(self.__write_to) diff --git a/ebook_converter/ebooks/rtf2xml/copy.py b/ebook_converter/ebooks/rtf2xml/copy.py new file mode 100644 index 0000000..f81cc50 --- /dev/null +++ b/ebook_converter/ebooks/rtf2xml/copy.py @@ -0,0 +1,63 @@ +from __future__ import unicode_literals, absolute_import, print_function, division +######################################################################### +# # +# # +# copyright 2002 Paul Henry Tremblay # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # +# General Public License for more details. # +# # +# # +######################################################################### +import os, shutil + + +class Copy: + """Copy each changed file to a directory for debugging purposes""" + __dir = "" + + def __init__(self, bug_handler, file=None, deb_dir=None, ): + self.__file = file + self.__bug_handler = bug_handler + + def set_dir(self, deb_dir): + """Set the temporary directory to write files to""" + if deb_dir is None: + message = "No directory has been provided to write to in the copy.py" + raise self.__bug_handler(message) + check = os.path.isdir(deb_dir) + if not check: + message = "%(deb_dir)s is not a directory" % vars() + raise self.__bug_handler(message) + Copy.__dir = deb_dir + + def remove_files(self): + """Remove files from directory""" + self.__remove_the_files(Copy.__dir) + + def __remove_the_files(self, the_dir): + """Remove files from directory""" + list_of_files = os.listdir(the_dir) + for file in list_of_files: + rem_file = os.path.join(Copy.__dir,file) + if os.path.isdir(rem_file): + self.__remove_the_files(rem_file) + else: + try: + os.remove(rem_file) + except OSError: + pass + + def copy_file(self, file, new_file): + """ + Copy the file to a new name + If the platform is linux, use the faster linux command + of cp. Otherwise, use a safe python method. + """ + write_file = os.path.join(Copy.__dir,new_file) + shutil.copyfile(file, write_file) + + def rename(self, source, dest): + shutil.copyfile(source, dest) diff --git a/ebook_converter/ebooks/rtf2xml/default_encoding.py b/ebook_converter/ebooks/rtf2xml/default_encoding.py new file mode 100644 index 0000000..a1b7019 --- /dev/null +++ b/ebook_converter/ebooks/rtf2xml/default_encoding.py @@ -0,0 +1,188 @@ +from __future__ import unicode_literals, absolute_import, print_function, division +######################################################################### +# # +# copyright 2002 Paul Henry Tremblay # +# # +######################################################################### + +''' +Codepages as to RTF 1.9.1: + 437 United States IBM + 708 Arabic (ASMO 708) + 709 Arabic (ASMO 449+, BCON V4) + 710 Arabic (transparent Arabic) + 711 Arabic (Nafitha Enhanced) + 720 Arabic (transparent ASMO) + 819 Windows 3.1 (United States and Western Europe) + 850 IBM multilingual + 852 Eastern European + 860 Portuguese + 862 Hebrew + 863 French Canadian + 864 Arabic + 865 Norwegian + 866 Soviet Union + 874 Thai + 932 Japanese + 936 Simplified Chinese + 949 Korean + 950 Traditional Chinese + 1250 Eastern European + 1251 Cyrillic + 1252 Western European + 1253 Greek + 1254 Turkish + 1255 Hebrew + 1256 Arabic + 1257 Baltic + 1258 Vietnamese + 1361 Johab + 10000 MAC Roman + 10001 MAC Japan + 10004 MAC Arabic + 10005 MAC Hebrew + 10006 MAC Greek + 10007 MAC Cyrillic + 10029 MAC Latin2 + 10081 MAC Turkish + 57002 Devanagari + 57003 Bengali + 57004 Tamil + 57005 Telugu + 57006 Assamese + 57007 Oriya + 57008 Kannada + 57009 Malayalam + 57010 Gujarati + 57011 Punjabi +''' +import re +from . import open_for_read + + +class DefaultEncoding: + """ + Find the default encoding for the doc + """ + + # Note: not all those encoding are really supported by rtf2xml + # See http://msdn.microsoft.com/en-us/library/windows/desktop/dd317756%28v=vs.85%29.aspx + # and src\calibre\gui2\widgets.py for the input list in calibre + ENCODINGS = { + # Special cases + 'cp1252':'1252', + 'utf-8':'1252', + 'ascii':'1252', + # Normal cases + 'big5':'950', + 'cp1250':'1250', + 'cp1251':'1251', + 'cp1253':'1253', + 'cp1254':'1254', + 'cp1255':'1255', + 'cp1256':'1256', + 'shift_jis':'932', + 'gb2312':'936', + # Not in RTF 1.9.1 codepage specification + 'hz':'52936', + 'iso8859_5':'28595', + 'iso2022_jp':'50222', + 'iso2022_kr':'50225', + 'euc_jp':'51932', + 'euc_kr':'51949', + 'gb18030':'54936', + } + + def __init__(self, in_file, bug_handler, default_encoding, run_level=1, check_raw=False): + self.__file = in_file + self.__bug_handler = bug_handler + self.__platform = 'Windows' + self.__default_num = 'not-defined' + self.__code_page = self.ENCODINGS.get(default_encoding, '1252') + self.__datafetched = False + self.__fetchraw = check_raw + + def find_default_encoding(self): + if not self.__datafetched: + self._encoding() + self.__datafetched = True + code_page = 'ansicpg' + self.__code_page + # if self.__code_page == '10000': + # self.__code_page = 'mac_roman' + return self.__platform, code_page, self.__default_num + + def get_codepage(self): + if not self.__datafetched: + self._encoding() + self.__datafetched = True + # if self.__code_page == '10000': + # self.__code_page = 'mac_roman' + return self.__code_page + + def get_platform(self): + if not self.__datafetched: + self._encoding() + self.__datafetched = True + return self.__platform + + def _encoding(self): + with open_for_read(self.__file) as read_obj: + cpfound = False + if not self.__fetchraw: + for line in read_obj: + self.__token_info = line[:16] + if self.__token_info == 'mi 3: + msg = 'Flag problem\n' + raise self.__bug_handler(msg) + return True + elif self.__token_info in self.__allowable : + if self.__ob: + self.__write_obj.write(self.__ob) + self.__ob = 0 + self.__state = 'default' + else: + pass + return True + elif self.__token_info == 'cw 5: + msg = ('After an asterisk, and found neither an allowable or non-allowable token\n\ + token is "%s"\n') % self.__token_info + raise self.__bug_handler(msg) + if not self.__ob: + self.__write_cb = True + self.__ob = 0 + self.__state = 'delete' + self.__cb_count = 0 + return False + + def __found_list_func(self, line): + """ + print out control words in this group + """ + self.__state = 'list' + + def __list_func(self, line): + """ + Check to see if the group has ended. + Return True for all control words. + Return False otherwise. + """ + if self.__delete_count == self.__cb_count and \ + self.__token_info == 'cb 3: + msg = 'no key for "%s" "%s"\n' % (field_name, changed_string) + raise self.__bug_handler(msg) + the_list = self.__fall_back_func(field_name, line) + return the_list + return the_list + + def __default_inst_func(self, field_name, name, line): + """ + Requires: + field_name -- the first word in the string + name -- the changed name according to the dictionary + line -- the string to be parsed + Returns: + The name of the field. + Logic: + I only need the changed name for the field. + """ + return [None, None, name] + + def __fall_back_func(self, field_name, line): + """ + Requires: + field_name -- the first word in the string + name -- the changed name according to the dictionary + line -- the string to be parsed + Returns: + The name of the field. + Logic: + Used for fields not found in dict + """ + the_string = field_name + the_string += 'none' + return [None, None, the_string] + + def __equation_func(self, field_name, name, line): + """ + Requried: + field_name -- the first word in the string + name --the changed name according to the dictionary + line -- the string to be parse + Retuns: + The name of the field + Logic: + """ + return [None, None, name] + + def __no_switch_func(self, field_name, name, line): + """ + Required: + field_name --the first + field_name -- the first word in the string + name --the changed name according to the dictionary + line -- the string to be parse + Retuns: + The name of the field + Logic: + """ + return [None, None, name] + + def __num_type_and_format_func(self, field_name, name, line): + """ + Required: + field_name -- the first word in the string + name --the changed name according to the dictionary + line -- the string to be parse + Returns: + list of None, None, and part of a tag + Logic: + parse num_type + parse num_format + """ + the_string = name + num_format = self.__parse_num_format(line) + if num_format: + the_string += '%s' % num_format + num_type = self.__parse_num_type(line) + if num_type: + the_string += '%s' % num_type + # Only QUOTE takes a (mandatory?) argument + if field_name == 'QUOTE': + match_group = re.search(r'QUOTE\s{1,}"(.*?)"', line) + if match_group: + arg = match_group.group(1) + the_string += '%s' % arg + return [None, None, the_string] + + def __num_format_func(self, field_name, name, line): + """ + Required: + field_name -- the first word in the string + name --the changed name according to the dictionary + line -- the string to be parse + Returns: + list of None, None, and part of a tag + Logic: + """ + the_string = name + num_format = self.__parse_num_format(line) + if num_format: + the_string += '%s' % num_format + return [None, None, the_string] + + def __parse_num_format(self, the_string): + """ + Required: + the_string -- the string to parse + Returns: + a string if the_string contains number formatting information + None, otherwise + Logic: + """ + match_group = re.search(self.__date_exp, the_string) + if match_group: + return match_group(1) + + def __parse_num_type(self, the_string): + """ + Required: + the_string -- the string to parse + Returns: + a string if the_string contains number type information + None, otherwise + Logic: + the_string might look like: + USERNAME \\* Arabic \\* MERGEFORMAT + Get the \\* Upper part. Use a dictionary to convert the "Arabic" to + a more-readable word for the value of the key "number-type". + ( + """ + match_group = re.search(self.__num_type_exp, the_string) + if match_group: + name = match_group.group(1) + changed_name = self.__number_dict.get(name) + if changed_name: + return changed_name + else: + sys.stderr.write('module is fields_string\n') + sys.stderr.write('method is __parse_num_type\n') + sys.stderr.write('no dictionary entry for %s\n' % name) + + def __date_func(self, field_name, name, line): + """ + Required: + field_name --the fist + field_name -- the first word in the string + name --the changed name according to the dictionary + line -- the string to be parse + Returns: + list of None, None, and part of a tag + Logic: + """ + the_string = name + match_group = re.search(self.__date_exp, line) + if match_group: + the_string += '%s' % match_group.group(1) + return [None, None, the_string] + + def __simple_info_func(self, field_name, name, line): + """ + Requried: + field_name -- the first word in the string + name --the changed name according to the dictionary + line -- the string to be parse + Retuns: + The name of the field + Logic: + These fields can only have the following switches: + 1. Upper + 2. Lower + 3. FirstCap + 4. Caps + """ + the_string = name + match_group = re.search(self.__format_text_exp, line) + if match_group: + name = match_group.group(1) + changed_name = self.__text_format_dict.get(name) + if changed_name: + the_string += '%s' % changed_name + else: + sys.stderr.write('module is fields_string\n') + sys.stderr.write('method is __parse_num_type\n') + sys.stderr.write('no dictionary entry for %s\n' % name) + return [None, None, the_string] + + def __hyperlink_func(self, field_name, name, line): + """ + Requried: + field_name -- the first word in the string + name --the changed name according to the dictionary + line -- the string to be parse + Retuns: + The name of the field + """ + self.__link_switch = re.compile(r'\\l\s{1,}"{0,1}(.*?)"{0,1}\s') + the_string = name + match_group = re.search(self.__link_switch, line) + if match_group: + link = match_group.group(1) + link = link.replace('"', """) + the_string += '%s' % link + # \l "txt" "link" + # want "file name" so must get rid of \c "txt" + line = re.sub(self.__link_switch, '', line) + match_group = re.search(self.__quote_exp, line) + if match_group: + arg = match_group.group(1) + the_string += '%s' % arg + else: + pass + index = line.find('\\m') + if index > -1: + the_string += 'true' + index = line.find('\\n') + if index > -1: + the_string += 'true' + index = line.find('\\h') + if index > -1: + the_string += 'true' + return [None, None, the_string] + + def __include_text_func(self, field_name, name, line): + """ + Requried: + field_name -- the first word in the string + name --the changed name according to the dictionary + line -- the string to be parse + Retuns: + The name of the field + Logic: + """ + the_string = name + match_group = re.search(self.__format_text_exp, line) + if match_group: + name = match_group.group(1) + changed_name = self.__text_format_dict.get(name) + if changed_name: + the_string += '%s' % changed_name + else: + sys.stderr.write('module is fields_string\n') + sys.stderr.write('method is __parse_num_type\n') + sys.stderr.write('no dictionary entry for %s\n' % name) + match_group = re.search(self.__filter_switch, line) + if match_group: + arg = match_group.group(1) + the_string += '%s' % arg + # \c "txt" "file name" + # want "file name" so must get rid of \c "txt" + line = re.sub(self.__filter_switch, '', line) + match_group = re.search(self.__quote_exp, line) + if match_group: + arg = match_group.group(1) + arg = arg.replace('"', """) + the_string += '%s' % arg + else: + sys.stderr.write('Module is field_strings\n') + sys.stderr.write('method is include_text_func\n') + sys.stderr.write('no argument for include text\n') + index = line.find('\\!') + if index > -1: + the_string += 'true' + return [None, None, the_string] + + def __include_pict_func(self, field_name, name, line): + """ + Requried: + field_name -- the first word in the string + name --the changed name according to the dictionary + line -- the string to be parse + Retuns: + The name of the field + Logic: + """ + the_string = name + match_group = re.search(self.__filter_switch, line) + if match_group: + arg = match_group.group(1) + arg = arg.replace('"', """) + the_string += '%s' % arg + # \c "txt" "file name" + # want "file name" so must get rid of \c "txt" + line = re.sub(self.__filter_switch, '', line) + match_group = re.search(self.__quote_exp, line) + if match_group: + arg = match_group.group(1) + the_string += '%s' % arg + else: + sys.stderr.write('Module is field_strings\n') + sys.stderr.write('method is include_pict_func\n') + sys.stderr.write('no argument for include pict\n') + index = line.find('\\d') + if index > -1: + the_string += 'true' + return [None, None, the_string] + + def __ref_func(self, field_name, name, line): + """ + Requires: + field_name -- the first word in the string + name -- the changed name according to the dictionary + line -- the string to be parsed + Returns: + The name of the field. + Logic: + A page reference field looks like this: + PAGEREF _Toc440880424 \\h + I want to extract the second line of info, which is used as an + achor in the resulting XML file. + """ + the_string = name + match_group = re.search(self.__format_text_exp, line) + if match_group: + name = match_group.group(1) + changed_name = self.__text_format_dict.get(name) + if changed_name: + the_string += '%s' % changed_name + else: + sys.stderr.write('module is fields_string\n') + sys.stderr.write('method is __parse_num_type\n') + sys.stderr.write('no dictionary entry for %s\n' % name) + line = re.sub(self.__merge_format_exp, '', line) + words = line.split() + words = words[1:] # get rid of field name + for word in words: + if word[0:1] != '\\': + the_string += '%s' % word + index = line.find('\\f') + if index > -1: + the_string += 'true' + index = line.find('\\h') + if index > -1: + the_string += 'true' + index = line.find('\\n') + if index > -1: + the_string += 'true' + index = line.find('\\r') + if index > -1: + the_string += 'true' + index = line.find('\\p') + if index > -1: + the_string += 'true' + index = line.find('\\t') + if index > -1: + the_string += 'true' + index = line.find('\\w') + if index > -1: + the_string += 'true' + return [None, None, the_string] + + def __toc_table_func(self, field_name, name, line): + """ + Requires: + field_name -- the name of the first word in the string + name --the changed name, according to the dictionary. + line --the string to be parsed. + Returns: + A string for a TOC table field. + Logic: + If the string contains Figure, it is a table of figures. + Otherwise, it is a plain old table of contents. + """ + the_string = name + index = line.find('\\c "Figure"') + if index > -1: + the_string = the_string.replace('table-of-contents', 'table-of-figures') + # don't really need the first value in this list, I don't believe + return [name, None, the_string] + + def __sequence_func(self, field_name, name, line): + """ + Requires: + field_name --the name of the first word in the string. + name --the changed name according to the dictionary. + line -- the string to parse. + Returns: + A string with a value for the type and label attributes + Logic: + The type of sequence--whether figure, graph, my-name, or + whatever--is represented by the second word in the string. Extract + and return. + SEQ Figure \\* ARABIC + """ + fields = line.split() + label = fields[1] + my_string = '%s + The simple field in the above example conatins no paragraph or sections breaks. + This line of RTF: + {{\field{\*\fldinst SYMBOL 97 \\f "Symbol" \\s 12}{\fldrslt\f3\fs24}}} + Becomes: + Χ + The RTF in the example above should be represented as UTF-8 rather than a field. + This RTF: + {\field\fldedit{\*\fldinst { TOC \\o "1-3" }}{\fldrslt {\lang1024 + Heading one\tab }{\field{\*\fldinst {\lang1024 PAGEREF _Toc440880424 + \\h }{\lang1024 {\*\datafield + {\lang1024 1}}}{\lang1024 \par }\pard\plain + \s18\li240\widctlpar\tqr\tldot\tx8630\aspalpha\aspnum\faauto\adjustright\rin0\lin240\itap0 + \f4\lang1033\cgrid {\lang1024 Heading 2\tab }{\field{\*\fldinst + {\lang1024 PAGEREF _Toc440880425 \\h }{\lang1024 {\*\datafield + {\lang1024 1}}}{\lang1024 \par }\pard\plain + \widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 + \f4\lang1033\cgrid }}\pard\plain + \widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 + \f4\lang1033\cgrid {\fs28 \\u214\'85 \par }{\fs36 {\field{\*\fldinst + SYMBOL 67 \\f "Symbol" \\s 18}{\fldrslt\f3\fs36}}} + Becomes: + + + Heading one 1 + + + Heading 2 1 + + + """ + + def __init__(self, + in_file, + bug_handler, + copy=None, + run_level=1, + ): + """ + Required: + 'file'--file to parse + Optional: + 'copy'-- whether to make a copy of result for debugging + 'temp_dir' --where to output temporary results (default is + directory from which the script is run.) + Returns: + nothing + """ + self.__file = in_file + self.__bug_handler = bug_handler + self.__copy = copy + self.__run_level = run_level + self.__write_to = better_mktemp() + + def __initiate_values(self): + """ + Initiate all values. + """ + self.__text_string = '' + self.__field_instruction_string = '' + self.__marker = 'mi, + since this field is really just UTF-8. + If the field contains paragraph or section breaks, it is a + field-block rather than just a field. + Write the paragraph or section markers for later parsing of the + file. + If the filed list contains more strings, add the latest + (processed) string to the last string in the list. Otherwise, + write the string to the output file. + """ + last_bracket = self.__field_count.pop() + instruction = self.__field_instruction.pop() + inner_field_string = self.__field_string.pop() + sec_in_field = self.__sec_in_field.pop() + par_in_field = self.__par_in_field.pop() + # add a closing bracket, since the closing bracket is not included in + # the field string + if self.__symbol: + inner_field_string = '%scb%s\n%s'\ + 'mi%s\n%s'\ + 'mi%s' + '%snone\n' % (type, my_string)) + return my_changed_string + + def __found_toc_index_func(self, line, tag): + """ + Requires: + line --the line to parse + Returns: + nothing + Logic: + This function is called when a toc or index entry is found. The opening + bracket count is stored in the beginning bracket count. The state + is changed to 'toc_index.' + """ + self.__beg_bracket_count = self.__ob_count + self.__cb_count = 0 + self.__state = 'toc_index' + self.__tag = tag + + def __toc_index_func(self, line): + """ + Requires: + line --the line to parse + Returns: + nothing + Logic: + This function handles all lines within a toc or index entry. It + adds each line to a string until the end of the entry is found. It + processes the string with the fields_string module, and + prints out the result. + """ + if self.__beg_bracket_count == self.__cb_count: + self.__state = 'body' + type = self.__tag + if type == 'index': + my_string = self.__parse_index_func( + self.__text_string) + elif type == 'toc': + my_string = self.__parse_toc_func( + self.__text_string) + self.__write_obj.write(self.__marker) + self.__write_obj.write(my_string) + self.__text_string = '' + self.__write_obj.write(line) + else: + self.__text_string += line + + def fix_fields(self): + """ + Requires: + nothing + Returns: + nothing (changes the original file) + Logic: + Read one line in at a time. Determine what action to take based on + the state. If the state is before the body, look for the + beginning of the body. + The other two states are toc_index (for toc and index entries) and + bookmark. + """ + self.__initiate_values() + with open_for_read(self.__file) as read_obj: + with open_for_write(self.__write_to) as self.__write_obj: + for line in read_obj: + self.__token_info = line[:16] + if self.__token_info == 'ob value pair to the font-table + dictionary. Also create an empty tag with the name and number + as attributes. + Preamture end of font table + """ + # cw%s%s\n' % (self.__text_line, self.__font_num) + ) + elif self.__token_info == 'cwTimes0\n') + + def __after_font_table_func(self, line): + """ + Required: + line + Returns: + nothing + Logic: + Check the self.__token_info. If this matches a token with font + info, then extract the number from the line, and look up the font + name in the font dictionary. If no name exists for that number, + print out an error. Otherwise print out the same line, except with + the name rather than the number. + If the line does not contain font info, simply print it out to the + file. + """ + if self.__token_info == 'cw 3: + msg = 'no value for %s in self.__font_table\n' % font_num + raise self.__bug_handler(msg) + else: + # self.__special_font_dict + if font_name in self.__special_font_list: + self.__special_font_dict[font_name] = 1 + self.__write_obj.write( + 'cwendnote%s\n' % self.__footnote_count) + else: + self.__write_to_foot_obj.write( + 'mi%s\n' % self.__footnote_count) + self.__first_line = 0 + + def __in_footnote_func(self, line): + """Handle all tokens that are part of footnote""" + if self.__first_line: + self.__first_line_func(line) + if self.__token_info == 'cwNormal< + self.__name_regex = re.compile(r'([^<]+)') + self.__border_regex = re.compile(r'border-paragraph') + self.__found_appt = 0 + self.__line_num = 0 + self.__border_regex = re.compile(r'( 2: + msg = 'wrong flag' + raise self.__bug_handler(msg) + elif self.__token_info in self.__end_list: + self.__write_obj.write('mi -1: + return 1 + return 0 + + def __parse_pard_with_border(self, line): + border_string = '' + pard_string = '' + tokens = re.split(self.__border_regex, line) + for token in tokens: + if token[0:17] == '') + self.__found_appt = 0 + self.__line_num = 0 + + def __in_pard_func(self, line): + """ + Required: + line -- the line of current text. + Return: + Nothing + Logic: + You are in a list, but in the middle of a paragraph definition. + Don't do anything until you find the end of the paragraph definition. + """ + if self.__token_info == 'mi 2: + msg = 'wrong flag' + raise self.__bug_handler(msg) + elif self.__token_info in self.__end_list: + self.__write_obj.write('mi%s\n' % name) + self.__write_obj.write('mi%s\n' % (type) + ) + else: + sys.stderr.write( + 'module is header\n' + 'method is __found_header\n' + 'no dict entry\n' + 'line is %s' % line) + self.__write_to_head_obj.write( + 'minone\n' + ) + + def __default_sep(self, line): + """ + Handle all tokens that are not header tokens + """ + if self.__token_info[3:5] == 'hf': + self.__found_header(line) + self.__write_obj.write(line) + + def __initiate_sep_values(self): + """ + initiate counters for separate_footnotes method. + """ + self.__bracket_count=0 + self.__ob_count = 0 + self.__cb_count = 0 + self.__header_bracket_count = 0 + self.__in_header = False + self.__header_count = 0 + self.__head_dict = { + 'head-left_' : ('header-left'), + 'head-right' : ('header-right'), + 'foot-left_' : ('footer-left'), + 'foot-right' : ('footer-right'), + 'head-first' : ('header-first'), + 'foot-first' : ('footer-first'), + 'header____' : ('header'), + 'footer____' : ('footer'), + } + + def separate_headers(self): + """ + Separate all the footnotes in an RTF file and put them at the bottom, + where they are easier to process. Each time a footnote is found, + print all of its contents to a temporary file. Close both the main and + temporary file. Print the footnotes from the temporary file to the + bottom of the main file. + """ + self.__initiate_sep_values() + self.__header_holder = better_mktemp() + with open_for_read(self.__file) as read_obj: + with open_for_write(self.__write_to) as self.__write_obj: + with open_for_write(self.__header_holder) as self.__write_to_head_obj: + for line in read_obj: + self.__token_info = line[:16] + # keep track of opening and closing brackets + if self.__token_info == 'ob(\d+)') + + def __close_lists(self): + """ + Required: + Nothing + Return: + Nothing + Logic: + Reverse the list of dictionaries. Iterate through the list and + get the indent for each list. If the current indent is less than + or equal to the indent in the dictionary, close that level. + Keep track of how many levels you close. Reduce the list by that + many levels. + Reverse the list again. + """ + current_indent = self.__left_indent + self.__all_lists.reverse() + num_levels_closed = 0 + for the_dict in self.__all_lists: + list_indent = the_dict.get('left-indent') + if current_indent <= list_indent: + self.__write_end_item() + self.__write_end_list() + num_levels_closed += 1 + self.__all_lists = self.__all_lists[num_levels_closed:] + self.__all_lists.reverse() + + def __close_sections(self, current_level): + self.__all_sections.reverse() + num_levels_closed = 0 + for level in self.__all_sections: + if current_level <= level: + self.__write_end_section() + num_levels_closed += 1 + self.__all_sections = self.__all_sections[num_levels_closed:] + self.__all_sections.reverse() + + def __write_start_section(self, current_level, name): + section_num = '' + for the_num in self.__section_num: + section_num += '%s.' % the_num + section_num = section_num[:-1] + num_in_level = len(self.__all_sections) + num_in_level = self.__section_num[num_in_level] + level = len(self.__all_sections) + self.__write_obj.write( + 'mi%s%s%s' + '%s\n' + % (section_num, num_in_level, level, name) + ) + + def __write_end_section(self): + self.__write_obj.write('mi 10: + self.__write_obj.write('mi%snot-in-table\n' % + hex_num) + if self.__run_level > 4: + # msg = 'no dictionary entry for %s\n' + # msg += 'the hexidecimal num is "%s"\n' % (hex_num) + # msg += 'dictionary is %s\n' % self.__current_dict_name + msg = 'Character "&#x%s;" does not appear to be valid (or is a control character)\n' % token + raise self.__bug_handler(msg) + + def __found_body_func(self, line): + self.__state = 'body' + self.__write_obj.write(line) + + def __body_func(self, line): + """ + When parsing preamble + """ + self.__write_obj.write(line) + + def __preamble_func(self, line): + action = self.__preamble_state_dict.get(self.__token_info) + if action is not None: + action(line) + else: + self.__write_obj.write(line) + + def __convert_preamble(self): + self.__state = 'preamble' + with open_for_write(self.__write_to) as self.__write_obj: + with open_for_read(self.__file) as read_obj: + for line in read_obj: + self.__token_info = line[:16] + action = self.__preamble_state_dict.get(self.__state) + if action is None: + sys.stderr.write('error no state found in hex_2_utf8', + self.__state + ) + action(line) + copy_obj = copy.Copy(bug_handler=self.__bug_handler) + if self.__copy: + copy_obj.copy_file(self.__write_to, "preamble_utf_convert.data") + copy_obj.rename(self.__write_to, self.__file) + os.remove(self.__write_to) + + def __preamble_for_body_func(self, line): + """ + Required: + line -- line to parse + Returns: + nothing + Logic: + Used when parsing the body. + """ + if self.__token_info == 'mi 1: + self.__font_list.pop() + else: + sys.stderr.write('module is hex_2_utf8\n') + sys.stderr.write('method is end_font_func\n') + sys.stderr.write('self.__font_list should be greater than one?\n') + face = self.__font_list[-1] + if face == 'Symbol' and self.__convert_symbol: + self.__current_dict_name = 'Symbol' + self.__current_dict = self.__symbol_dict + elif face == 'Wingdings' and self.__convert_wingdings: + self.__current_dict_name = 'Wingdings' + self.__current_dict = self.__wingdings_dict + elif face == 'Zapf Dingbats' and self.__convert_zapf: + self.__current_dict_name = 'Zapf Dingbats' + self.__current_dict = self.__dingbats_dict + else: + self.__current_dict_name = 'default' + self.__current_dict = self.__def_dict + + def __start_special_font_func_old(self, line): + """ + Required: + line -- line + Returns; + nothing + Logic: + change the dictionary to use in conversion + """ + # for error checking + if self.__token_info == 'mi 1: + self.__caps_list.pop() + else: + sys.stderr.write('Module is hex_2_utf8\n' + 'method is __end_caps_func\n' + 'caps list should be more than one?\n') # self.__in_caps not set + + def __text_func(self, line): + """ + Required: + line -- line to parse + Returns: + nothing + Logic: + if in caps, convert. Otherwise, print out. + """ + text = line[17:-1] + # print line + if self.__current_dict_name in ('Symbol', 'Wingdings', 'Zapf Dingbats'): + the_string = '' + for letter in text: + hex_num = hex(ord(letter)) + hex_num = unicode_type(hex_num) + hex_num = hex_num.upper() + hex_num = hex_num[2:] + hex_num = '\'%s' % hex_num + converted = self.__current_dict.get(hex_num) + if converted is None: + sys.stderr.write('module is hex_2_ut8\nmethod is __text_func\n') + sys.stderr.write('no hex value for "%s"\n' % hex_num) + else: + the_string += converted + self.__write_obj.write('txа|б)') +line2 = re.sub(reg_exp, my_sub_func, line) +print line2 +""" diff --git a/ebook_converter/ebooks/rtf2xml/info.py b/ebook_converter/ebooks/rtf2xml/info.py new file mode 100644 index 0000000..37a1bf7 --- /dev/null +++ b/ebook_converter/ebooks/rtf2xml/info.py @@ -0,0 +1,285 @@ +from __future__ import unicode_literals, absolute_import, print_function, division +######################################################################### +# # +# # +# copyright 2002 Paul Henry Tremblay # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # +# General Public License for more details. # +# # +# # +######################################################################### +import sys, os, re + +from calibre.ebooks.rtf2xml import copy +from calibre.ptempfile import better_mktemp +from . import open_for_read, open_for_write + + +class Info: + """ + Make tags for document-information + """ + + def __init__(self, + in_file, + bug_handler, + copy=None, + run_level=1, + ): + """ + Required: + 'file'--file to parse + Optional: + 'copy'-- whether to make a copy of result for debugging + 'temp_dir' --where to output temporary results (default is + directory from which the script is run.) + Returns: + nothing + """ + self.__file = in_file + self.__bug_handler = bug_handler + self.__copy = copy + self.__run_level = run_level + self.__write_to = better_mktemp() + + def __initiate_values(self): + """ + Initiate all values. + """ + self.__text_string = '' + self.__state = 'before_info_table' + self.rmspace = re.compile(r'\s+') + self.__state_dict = { + 'before_info_table': self.__before_info_table_func, + 'after_info_table': self.__after_info_table_func, + 'in_info_table' : self.__in_info_table_func, + 'collect_text' : self.__collect_text_func, + 'collect_tokens' : self.__collect_tokens_func, + } + self.__info_table_dict = { + 'cw33\n + + def __collect_tokens_func(self, line): + """ + Requires: + line -- line to parse + Returns: + nothing + Logic: + This function collects all the token information and adds it to + the text string until the end of the field is found. + First check of the end of the information field. If found, write + the text string to the file. + If not found, get the relevant information from the text string. + This information cannot be directly added to the text string, + because it exists in abbreviated form. (num-of-wor) + I want to check this information in a dictionary to convert it + to a longer, readable form. If the key does not exist in the + dictionary, print out an error message. Otherise add the value + to the text string. + (num-of-wor => number-of-words) + """ + # cw 3: + msg = 'No dictionary match for %s\n' % att + raise self.__bug_handler(msg) + else: + self.__text_string += '<%s>%s' % (att_changed, value) + + def __single_field_func(self, line, tag): + value = line[20:-1] + self.__write_obj.write( + 'mi%s\n' % (tag, tag, value) + ) + + def __after_info_table_func(self, line): + """ + Requires: + line --line to write to file + Returns: + nothing + Logic: + After the end of the information table, simple write the line to + the file. + """ + self.__write_obj.write(line) + + def fix_info(self): + """ + Requires: + nothing + Returns: + nothing (changes the original file) + Logic: + Read one line in at a time. Determine what action to take based on + the state. If the state is before the information table, look for the + beginning of the style table. + If the state is in the information table, use other methods to + parse the information + style table, look for lines with style info, and substitute the + number with the name of the style. If the state if afer the + information table, simply write the line to the output file. + """ + self.__initiate_values() + with open_for_read(self.__file) as read_obj: + with open_for_write(self.__write_to) as self.__write_obj: + for line in read_obj: + self.__token_info = line[:16] + action = self.__state_dict.get(self.__state) + if action is None: + sys.stderr.write('No matching state in module styles.py\n') + sys.stderr.write(self.__state + '\n') + action(line) + copy_obj = copy.Copy(bug_handler=self.__bug_handler) + if self.__copy: + copy_obj.copy_file(self.__write_to, "info.data") + copy_obj.rename(self.__write_to, self.__file) + os.remove(self.__write_to) diff --git a/ebook_converter/ebooks/rtf2xml/inline.py b/ebook_converter/ebooks/rtf2xml/inline.py new file mode 100644 index 0000000..301c7ea --- /dev/null +++ b/ebook_converter/ebooks/rtf2xml/inline.py @@ -0,0 +1,427 @@ +from __future__ import unicode_literals, absolute_import, print_function, division +import sys, os + +from calibre.ebooks.rtf2xml import copy +from calibre.ptempfile import better_mktemp +from . import open_for_read, open_for_write + +""" +States. +1. default + 1. an open bracket ends this state. + 2. Text print out text. Print out any groups_in_waiting. + 3. closed bracket. Close groups +2. after an open bracket + 1. The lack of a control word ends this state. + 2. paragraph end -- close out all tags + 3. footnote beg -- close out all tags +""" + + +class Inline: + """ + Make inline tags within lists. + Logic: + """ + + def __init__(self, + in_file, + bug_handler, + copy=None, + run_level=1,): + """ + Required: + 'file'--file to parse + Optional: + 'copy'-- whether to make a copy of result for debugging + 'temp_dir' --where to output temporary results (default is + directory from which the script is run.) + Returns: + nothing + """ + self.__file = in_file + self.__bug_handler = bug_handler + self.__copy = copy + self.__run_level = run_level + self.__write_to = better_mktemp() + + def __initiate_values(self): + """ + Initiate all values. + """ + self.__state_dict = { + 'default': self.__default_func, + 'after_open_bracket': self.__after_open_bracket_func, + } + self.__default_dict = { + 'ob ci + 'annotation' : 'annotation', + 'blue______' : 'blue', + 'bold______' : 'bold', + 'caps______' : 'caps', + 'char-style' : 'character-style', + 'dbl-strike' : 'double-strike-through', + 'emboss____' : 'emboss', + 'engrave___' : 'engrave', + 'font-color' : 'font-color', + 'font-down_' : 'subscript', + 'font-size_' : 'font-size', + 'font-style' : 'font-style', + 'font-up___' : 'superscript', + 'footnot-mk' : 'footnote-marker', + 'green_____' : 'green', + 'hidden____' : 'hidden', + 'italics___' : 'italics', + 'outline___' : 'outline', + 'red_______' : 'red', + 'shadow____' : 'shadow', + 'small-caps' : 'small-caps', + 'strike-thr' : 'strike-through', + 'subscript_' : 'subscript', + 'superscrip' : 'superscript', + 'underlined' : 'underlined', + } + self.__caps_list = ['false'] + + def __set_list_func(self, line): + """ + Requires: + line--line of text + Returns: + nothing + Logic: + """ + if self.__place == 'in_list': + if self.__token_info == 'mi 3: + msg = 'self.__inline_list is %s\n' % self.__inline_list + raise self.__bug_handler(msg) + self.__write_obj.write('error\n') + self.__groups_in_waiting[0] = 0 + return + for the_dict in inline_list: + if the_dict['contains_inline']: + the_keys = the_dict.keys() + if 'font-style' in the_keys: + face = the_dict['font-style'] + self.__write_obj.write('mi%s' % (the_key, the_dict[the_key])) + self.__write_obj.write('\n') + self.__groups_in_waiting[0] = 0 + + def __end_para_func(self, line): + """ + Requires: + line -- line of text + Returns: + nothing + Logic: + Slice from the end the groups in waiting. + Iterate through the list. If the dictionary contaings info, write + a closing tag. + """ + if not self.__in_para: + return + if self.__groups_in_waiting[0] == 0: + inline_list = self.__inline_list + else: + last_index = -1 * self.__groups_in_waiting[0] + inline_list = self.__inline_list[0:last_index] + for the_dict in inline_list: + contains_info = the_dict.get('contains_inline') + if contains_info: + the_keys = the_dict.keys() + if 'font-style' in the_keys: + self.__write_obj.write('mi%s' % (the_key, the_dict[the_key])) + self.__write_obj.write('\n') + self.__groups_in_waiting[0] = 0 + + def __found_field_func(self, line): + """ + Just a default function to make sure I don't prematurely exit + default state + """ + pass + + def form_tags(self): + """ + Requires: + area--area to parse (list or non-list) + Returns: + nothing + Logic: + Read one line in at a time. Determine what action to take based on + the state. + """ + self.__initiate_values() + with open_for_read(self.__file) as read_obj: + with open_for_write(self.__write_to) as self.__write_obj: + for line in read_obj: + token = line[0:-1] + self.__token_info = '' + if token == 'tx%s\n' % self.__list_type) + 'mi a list. The first item is a dictionary. + The second item is a list containing a dictionary: + [{list-id:[]}, [{}]] + self.__all_lists[-1][0] => a dictionary of the list attributes + self.__all_lists[-1][-1] => a list with just a dictionary + self.__all_lists[-1][-1][0] => the dictionary of level attributes + """ + self.__state = 'level' + self.__level_ob_count = self.__ob_count + self.__all_lists[-1].append([]) + the_dict = {} + self.__all_lists[-1][-1].append(the_dict) + self.__level_dict + + def __level_func(self, line): + """ + Requires: + line -- line to parse + Returns: + nothing + Logic: + Look for the end of the this group. + Change states if an open bracket is found. + Add attributes to all_dicts if an appropriate token is found. + """ + if self.__token_info == 'cb 3: + msg = 'No matching token after open bracket\n' + msg += 'token is "%s\n"' % (line) + raise self.__bug_handler + + def __add_to_final_line(self): + """ + Method no longer used. + """ + self.__list_table_final = 'mi value pair. + Remove the first item (the dictionary) form this list. Now iterate + through what is left in the list. Each list will conatin one item, + a dictionary. Get this dictionary and print out key => value pair. + """ + not_allow = ['list-id',] + id = 0 + self.__list_table_final = 'mi(\d+)') + self.__lv_regex = re.compile(r'\(\d+)') + self.__found_appt = 0 + self.__line_num = 0 + + def __in_pard_func(self, line): + """ + Required: + line -- the line of current text. + Return: + Nothing + Logic: + You are in a list, but in the middle of a paragraph definition. + Don't do anything until you find the end of the paragraph definition. + """ + if self.__token_info == 'mi last_list_indent: + self.__write_obj.write(self.__list_chunk) + self.__write_start_list(id) + else: + self.__write_end_item() + self.__write_obj.write(self.__list_chunk) + self.__write_start_item() + self.__list_chunk = '' + + def __close_lists(self): + """ + Required: + Nothing + Return: + Nothing + Logic: + Reverse the list of dictionaries. Iterate through the list and + get the indent for each list. If the current indent is less than + or equal to the indent in the dictionary, close that level. + Keep track of how many levels you close. Reduce the list by that + many levels. + Reverse the list again. + """ + if self.__line_num < 25 and self.__found_appt: + sys.stderr.write('in closing out lists\n') + sys.stderr.write('current_indent is "%s"\n' % self.__left_indent) + current_indent = self.__left_indent + self.__all_lists.reverse() + num_levels_closed = 0 + for the_dict in self.__all_lists: + list_indent = the_dict.get('left-indent') + if self.__line_num < 25 and self.__found_appt: + sys.stderr.write('last indent is "%s"' % list_indent) + if current_indent <= list_indent: + self.__write_end_item() + self.__write_end_list() + num_levels_closed += 1 + self.__all_lists = self.__all_lists[num_levels_closed:] + self.__all_lists.reverse() + + def __write_end_list(self): + """ + Required: + Nothing + Return: + Nothing + Logic: + Write the end of a list. + """ + self.__write_obj.write('mi%s%s' + % (id, lev_num) + ) + list_dict = {} + if self.__list_of_lists: # older RTF won't generate a list_of_lists + index_of_list = self.__get_index_of_list(id) + if index_of_list is not None: # found a matching id + curlist = self.__list_of_lists[index_of_list] + list_dict = curlist[0] + level = int(self.__level) + 1 + if level >= len(curlist): + level = len(curlist) - 1 + level_dict = curlist[level][0] + list_type = level_dict.get('numbering-type') + if list_type == 'bullet': + list_type = 'unordered' + else: + list_type = 'ordered' + self.__write_obj.write( + '%s' % (list_type)) + else: # no matching id + self.__write_obj.write( + '%s' % (self.__list_type)) + else: # older RTF + self.__write_obj.write( + '%s' % (self.__list_type)) + # if you want to dump all the info to the list, rather than + # keeping it in the table above, change self.__write_list_info + # to true. + if self.__list_of_lists and self.__write_list_info and list_dict: + not_allow = ['list-id',] + the_keys_list = list_dict.keys() + for the_key in the_keys_list: + if the_key in not_allow: + continue + self.__write_obj.write('<%s>%s' % (the_key, list_dict[the_key])) + the_keys_level = level_dict.keys() + for the_key in the_keys_level: + self.__write_obj.write('<%s>%s' % (the_key, level_dict[the_key])) + self.__write_obj.write('\n') + self.__write_obj.write( + 'mi 0: + sys.stderr.write('Module is make_lists.py\n' + 'Method is __get_index_of_list\n' + 'The main list does not appear to have a matching id for %s \n' + % (id) + ) + # sys.stderr.write(repr(self.__list_of_lists)) +# if self.__run_level > 3: +# msg = 'level is "%s"\n' % self.__run_level +# self.__bug_handler + + def __write_start_item(self): + self.__write_obj.write('mi 3: + sys.stderr.write( + 'Old rtf construction %s (bracket %s, line %s)\n' % ( + self.__inline_info, unicode_type(self.__ob_group), line_num) + ) + return True + self.__previous_token = line[6:16] + return False diff --git a/ebook_converter/ebooks/rtf2xml/output.py b/ebook_converter/ebooks/rtf2xml/output.py new file mode 100644 index 0000000..7e653fe --- /dev/null +++ b/ebook_converter/ebooks/rtf2xml/output.py @@ -0,0 +1,121 @@ +from __future__ import unicode_literals, absolute_import, print_function, division +######################################################################### +# # +# # +# copyright 2002 Paul Henry Tremblay # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # +# General Public License for more details. # +# # +# # +######################################################################### +import sys, os +from polyglot.builtins import raw_input +from . import open_for_read, open_for_write +# , codecs + + +class Output: + """ + Output file + """ + + def __init__(self, + file, + orig_file, + output_dir=None, + out_file=None, + no_ask=True + ): + """ + Required: + 'file' -- xml file ready to output + orig_file -- original rtf file + Optional: + output_file -- the file to output to + Returns: + nothing + """ + self.__file = file + self.__orig_file = orig_file + self.__output_dir = output_dir + self.__no_ask = no_ask + self.__out_file = out_file + + def output(self): + """ + Required: + nothing + Returns: + nothing + Logic: + output the line to the screen if no output file given. Otherwise, output to + the file. + """ + if self.__output_dir: + self.__output_to_dir_func() + elif self.__out_file: + self.__output_to_file_func() + # self.__output_xml(self.__file, self.__out_file) + else: + self.__output_to_standard_func() + + def __output_to_dir_func(self): + """ + Requires: + nothing + Returns: + nothing + Logic: + Create a file within the output directory. + Read one file at a time. Output line to the newly-created file. + """ + base_name = os.path.basename(self.__orig_file) + base_name, ext = os.path.splitext(base_name) + output_file = os.path.join(self.__output_dir, '%s.xml' % base_name) + # change if user wants to output to a specific file + if self.__out_file: + output_file = os.path.join(self.__output_dir, self.__out_file) + user_response = 'o' + if os.path.isfile(output_file) and not self.__no_ask: + msg = 'Do you want to overwrite %s?\n' % output_file + msg += ('Type "o" to overwrite.\n' + 'Type any other key to print to standard output.\n') + sys.stderr.write(msg) + user_response = raw_input() + if user_response == 'o': + with open_for_read(self.__file) as read_obj: + with open_for_write(self.output_file) as write_obj: + for line in read_obj: + write_obj.write(line) + else: + self.__output_to_standard_func() + + def __output_to_file_func(self): + """ + Required: + nothing + Returns: + nothing + Logic: + read one line at a time. Output to standard + """ + with open_for_read(self.__file) as read_obj: + with open_for_write(self.__out_file) as write_obj: + for line in read_obj: + write_obj.write(line) + + def __output_to_standard_func(self): + """ + Required: + nothing + Returns: + nothing + Logic: + read one line at a time. Output to standard + """ + with open_for_read(self.__file) as read_obj: + for line in read_obj: + sys.stdout.write(line) diff --git a/ebook_converter/ebooks/rtf2xml/override_table.py b/ebook_converter/ebooks/rtf2xml/override_table.py new file mode 100644 index 0000000..3ae5309 --- /dev/null +++ b/ebook_converter/ebooks/rtf2xml/override_table.py @@ -0,0 +1,209 @@ +from __future__ import unicode_literals, absolute_import, print_function, division +from __future__ import print_function +######################################################################### +# # +# # +# copyright 2002 Paul Henry Tremblay # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # +# General Public License for more details. # +# # +# # +######################################################################### + + +class OverrideTable: + """ + Parse a line of text to make the override table. Return a string + (which will convert to XML) and the dictionary containing all the + information about the lists. This dictionary is the result of the + dictionary that is first passed to this module. This module + modifies the dictionary, assigning lists numbers to each list. + """ + + def __init__( + self, + list_of_lists, + run_level=1, + ): + self.__list_of_lists = list_of_lists + self.__initiate_values() + self.__run_level = run_level + + def __initiate_values(self): + self.__override_table_final = '' + self.__state = 'default' + self.__override_list = [] + self.__state_dict = { + 'default' : self.__default_func, + 'override' : self.__override_func, + 'unsure_ob' : self.__after_bracket_func, + } + self.__override_dict = { + 'cw 3: + msg = 'This override does not appear to have a list-id\n' + raise self.__bug_handler(msg) + current_table_id = override_dict.get('list-table-id') + if current_table_id is None and self.__run_level > 3: + msg = 'This override does not appear to have a list-table-id\n' + raise self.__bug_handler(msg) + counter = 0 + for list in self.__list_of_lists: + info_dict = list[0] + old_table_id = info_dict.get('list-table-id') + if old_table_id == current_table_id: + self.__list_of_lists[counter][0]['list-id'].append(list_id) + break + counter += 1 + + def __parse_lines(self, line): + """ + Requires: + line --ine to parse + Returns: + nothing + Logic: + Break the into tokens by splitting it on the newline. + Call on the method according to the state. + """ + lines = line.split('\n') + self.__ob_count = 0 + self.__ob_group = 0 + for line in lines: + self.__token_info = line[:16] + if self.__token_info == 'ob 3: + msg = 'No matching token after open bracket\n' + msg += 'token is "%s\n"' % (line) + raise self.__bug_handler(msg) + + def __write_final_string(self): + """ + Requires: + line -- line to parse + Returns: + nothing + Logic: + First write out the override-table tag. + Iteratere through the dictionaries in the main override_list. + For each dictionary, write an empty tag "override-list". Add + the attributes and values of the tag from the dictionary. + """ + self.__override_table_final = 'mi%s' % (the_key, the_dict[the_key]) + self.__override_table_final += '\n' + self.__override_table_final += '\n' + self.__override_table_final += \ + 'mi pf + 'par-end___' : 'para', + 'par-def___' : 'paragraph-definition', + 'keep-w-nex' : 'keep-with-next', + 'widow-cntl' : 'widow-control', + 'adjust-rgt' : 'adjust-right', + 'language__' : 'language', + 'right-inde' : 'right-indent', + 'fir-ln-ind' : 'first-line-indent', + 'left-inden' : 'left-indent', + 'space-befo' : 'space-before', + 'space-afte' : 'space-after', + 'line-space' : 'line-spacing', + 'default-ta' : 'default-tab', + 'align_____' : 'align', + 'widow-cntr' : 'widow-control', + # stylesheet = > ss + 'style-shet' : 'stylesheet', + 'based-on__' : 'based-on-style', + 'next-style' : 'next-style', + 'char-style' : 'character-style', + # this is changed to get a nice attribute + 'para-style' : 'name', + # graphics => gr + 'picture___' : 'pict', + 'obj-class_' : 'obj_class', + 'mac-pic___' : 'mac-pict', + # section => sc + 'section___' : 'section-new', + 'sect-defin' : 'section-reset', + 'sect-note_' : 'endnotes-in-section', + # list=> ls + 'list-text_' : 'list-text', + # this line must be wrong because it duplicates an earlier one + 'list-text_' : 'list-text', + 'list______' : 'list', + 'list-lev-d' : 'list-level-definition', + 'list-cardi' : 'list-cardinal-numbering', + 'list-decim' : 'list-decimal-numbering', + 'list-up-al' : 'list-uppercase-alphabetic-numbering', + 'list-up-ro' : 'list-uppercae-roman-numbering', + 'list-ord__' : 'list-ordinal-numbering', + 'list-ordte' : 'list-ordinal-text-numbering', + 'list-bulli' : 'list-bullet', + 'list-simpi' : 'list-simple', + 'list-conti' : 'list-continue', + 'list-hang_' : 'list-hang', + # 'list-tebef' : 'list-text-before', + # 'list-level' : 'level', + 'list-id___' : 'list-id', + 'list-start' : 'list-start', + 'nest-level' : 'nest-level', + # duplicate + 'list-level' : 'list-level', + # notes => nt + 'footnote__' : 'footnote', + 'type______' : 'type', + # anchor => an + 'toc_______' : 'anchor-toc', + 'book-mk-st' : 'bookmark-start', + 'book-mk-en' : 'bookmark-end', + 'index-mark' : 'anchor-index', + 'place_____' : 'place', + # field => fd + 'field_____' : 'field', + 'field-inst' : 'field-instruction', + 'field-rslt' : 'field-result', + 'datafield_' : 'data-field', + # info-tables => it + 'font-table' : 'font-table', + 'colr-table' : 'color-table', + 'lovr-table' : 'list-override-table', + 'listtable_' : 'list-table', + 'revi-table' : 'revision-table', + # character info => ci + 'hidden____' : 'hidden', + 'italics___' : 'italics', + 'bold______' : 'bold', + 'strike-thr' : 'strike-through', + 'shadow____' : 'shadow', + 'outline___' : 'outline', + 'small-caps' : 'small-caps', + 'caps______' : 'caps', + 'dbl-strike' : 'double-strike-through', + 'emboss____' : 'emboss', + 'engrave___' : 'engrave', + 'subscript_' : 'subscript', + 'superscrip' : 'superscipt', + 'font-style' : 'font-style', + 'font-color' : 'font-color', + 'font-size_' : 'font-size', + 'font-up___' : 'superscript', + 'font-down_' : 'subscript', + 'red_______' : 'red', + 'blue______' : 'blue', + 'green_____' : 'green', + # table => tb + 'row-def___' : 'row-definition', + 'cell______' : 'cell', + 'row_______' : 'row', + 'in-table__' : 'in-table', + 'columns___' : 'columns', + 'row-pos-le' : 'row-position-left', + 'cell-posit' : 'cell-position', + # preamble => pr + # underline + 'underlined' : 'underlined', + # border => bd + 'bor-t-r-hi' : 'border-table-row-horizontal-inside', + 'bor-t-r-vi' : 'border-table-row-vertical-inside', + 'bor-t-r-to' : 'border-table-row-top', + 'bor-t-r-le' : 'border-table-row-left', + 'bor-t-r-bo' : 'border-table-row-bottom', + 'bor-t-r-ri' : 'border-table-row-right', + 'bor-cel-bo' : 'border-cell-bottom', + 'bor-cel-to' : 'border-cell-top', + 'bor-cel-le' : 'border-cell-left', + 'bor-cel-ri' : 'border-cell-right', + # 'bor-par-bo' : 'border-paragraph-bottom', + 'bor-par-to' : 'border-paragraph-top', + 'bor-par-le' : 'border-paragraph-left', + 'bor-par-ri' : 'border-paragraph-right', + 'bor-par-bo' : 'border-paragraph-box', + 'bor-for-ev' : 'border-for-every-paragraph', + 'bor-outsid' : 'border-outisde', + 'bor-none__' : 'border', + # border type => bt + 'bdr-single' : 'single', + 'bdr-doubtb' : 'double-thickness-border', + 'bdr-shadow' : 'shadowed-border', + 'bdr-double' : 'double-border', + 'bdr-dotted' : 'dotted-border', + 'bdr-dashed' : 'dashed', + 'bdr-hair__' : 'hairline', + 'bdr-inset_' : 'inset', + 'bdr-das-sm' : 'dash-small', + 'bdr-dot-sm' : 'dot-dash', + 'bdr-dot-do' : 'dot-dot-dash', + 'bdr-outset' : 'outset', + 'bdr-trippl' : 'tripple', + 'bdr-thsm__' : 'thick-thin-small', + 'bdr-htsm__' : 'thin-thick-small', + 'bdr-hthsm_' : 'thin-thick-thin-small', + 'bdr-thm__' : 'thick-thin-medium', + 'bdr-htm__' : 'thin-thick-medium', + 'bdr-hthm_' : 'thin-thick-thin-medium', + 'bdr-thl__' : 'thick-thin-large', + 'bdr-hthl_' : 'think-thick-think-large', + 'bdr-wavy_' : 'wavy', + 'bdr-d-wav' : 'double-wavy', + 'bdr-strip' : 'striped', + 'bdr-embos' : 'emboss', + 'bdr-engra' : 'engrave', + 'bdr-frame' : 'frame', + 'bdr-li-wid' : 'line-width', + } + self.__tabs_dict = { + 'cw 3: + msg = 'no entry for %s\n' % self.__token_info + raise self.__bug_handler(msg) + + def __tab_leader_func(self, line): + """ + """ + leader = self.__tab_type_dict.get(self.__token_info) + if leader is not None: + self.__att_val_dict['tabs'] += '%s^' % leader + else: + if self.__run_level > 3: + msg = 'no entry for %s\n' % self.__token_info + raise self.__bug_handler(msg) + + def __tab_bar_func(self, line): + """ + """ + # self.__att_val_dict['tabs-bar'] += '%s:' % line[20:-1] + self.__att_val_dict['tabs'] += 'bar:%s;' % (line[20:-1]) + self.__tab_type = 'left' + + def __parse_border(self, line): + """ + Requires: + line --line to parse + Returns: + nothing (updates dictionary) + Logic: + Uses the border_parse module to return a dictionary of attribute + value pairs for a border line. + """ + border_dict = self.__border_obj.parse_border(line) + self.__att_val_dict.update(border_dict) + + def __para_def_in_para_def_func(self, line): + """ + Requires: + line --line to parse + Returns: + nothing + Logic: + I have found a \\pard while I am collecting tokens. I want to reset + the dectionary and do nothing else. + """ + # Change this + self.__state = 'collect_tokens' + self.__reset_dict() + + def __end_para_def_func(self, line): + """ + Requires: + Nothing + Returns: + Nothing + Logic: + The previous state was collect tokens, and I have found the start + of a paragraph. I want to outut the defintion tag; output the line + itself (telling me of the beginning of a paragraph);change the + state to 'in_paragraphs'; + """ + self.__write_para_def_beg() + self.__write_obj.write(line) + self.__state = 'in_paragraphs' + + def __start_para_after_def_func(self, line): + """ + Requires: + Nothing + Returns: + Nothing + Logic: + The state was is after_para_def. and I have found the start of a + paragraph. I want to outut the defintion tag; output the line + itself (telling me of the beginning of a paragraph);change the + state to 'in_paragraphs'. + (I now realize that this is absolutely identical to the function above!) + """ + self.__write_para_def_beg() + self.__write_obj.write(line) + self.__state = 'in_paragraphs' + + def __after_para_def_func(self, line): + """ + Requires: + line -- line to parse + Returns: + nothing + Logic: + Check if the token info is the start of a paragraph. If so, call + on the function found in the value of the dictionary. + """ + action = self.__after_para_def_dict.get(self.__token_info) + if self.__token_info == 'cw%s' % ('tabs', the_value)) + exclude = frozenset(['name', 'style-num', 'in-table'] + tabs_list) + for k in sorted(self.__att_val_dict): + if k not in exclude: + style_string += ('<%s>%s' % (k, self.__att_val_dict[k])) + style_string += '\n' + self.__body_style_strings.append(style_string) + + def __write_para_def_beg(self): + """ + Requires: + nothing + Returns: + nothing + Logic: + Print out the beginning of the pargraph definition tag, and the markers + that let me know when I have reached this tag. (These markers are + used for later parsing.) + """ + self.__get_num_of_style() + table = self.__att_val_dict.get('in-table') + if table: + # del self.__att_val_dict['in-table'] + self.__write_obj.write('mi%s' % self.__att_val_dict['name']) + self.__write_obj.write('%s' % self.__att_val_dict['style-num']) + tabs_list = ['tabs-left', 'tabs-right', 'tabs-decimal', 'tabs-center', + 'tabs-bar', 'tabs'] + """ + for tab_item in tabs_list: + if self.__att_val_dict[tab_item] != '': + the_value = self.__att_val_dict[tab_item] + the_value = the_value[:-1] + self.__write_obj.write('<%s>%s' % (tab_item, the_value)) + """ + if self.__att_val_dict['tabs'] != '': + the_value = self.__att_val_dict['tabs'] + # the_value = the_value[:-1] + self.__write_obj.write('<%s>%s' % ('tabs', the_value)) + keys = sorted(self.__att_val_dict) + exclude = frozenset(['name', 'style-num', 'in-table'] + tabs_list) + for key in keys: + if key not in exclude: + self.__write_obj.write('<%s>%s' % (key, self.__att_val_dict[key])) + self.__write_obj.write('\n') + self.__write_obj.write(self.__start2_marker) + if 'font-style' in keys: + face = self.__att_val_dict['font-style'] + self.__write_obj.write('mi 1: + sys.stderr.write('Removing files from old pict directory...\n') + all_files = os.listdir(self.__dir_name) + for the_file in all_files: + the_file = os.path.join(self.__dir_name, the_file) + try: + os.remove(the_file) + except OSError: + pass + if self.__run_level > 1: + sys.stderr.write('Files removed.\n') + + def __create_pict_file(self): + """Create a file for all the pict data to be written to. + """ + self.__pict_file = os.path.join(self.__dir_name, 'picts.rtf') + self.__write_pic_obj = open_for_write(self.__pict_file, append=True) + + def __in_pict_func(self, line): + if self.__cb_count == self.__pict_br_count: + self.__in_pict = False + self.__write_pic_obj.write("}\n") + return True + else: + action = self.__pict_dict.get(self.__token_info) + if action: + self.__write_pic_obj.write(action(line)) + return False + + def __default(self, line, write_obj): + """Determine if each token marks the beginning of pict data. + If it does, create a new file to write data to (if that file + has not already been created.) Set the self.__in_pict flag to true. + If the line does not contain pict data, return 1 + """ + """ + $pict_count++; + $pict_count = sprintf("%03d", $pict_count); + print OUTPUT "dv$pict_count\n"; + """ + if self.__token_info == 'cw%03d\n" % self.__pict_count) + write_obj.write('mi%03d\n' % self.__pict_count) + write_obj.write('mi%s' % (key, self.__page[key]) + ) + self.__write_obj.write('\n') +# mi%s' % (key, self.__section[key]) + ) + self.__write_obj.write('\n') + + def __section_func(self, line): + """ + Add info pertaining to section to the self.__section dictionary, to be + printed out later. + """ + info = self.__translate_sec.get(line[6:16]) + if info is None: + sys.stderr.write('woops!\n') + else: + self.__section[info] = 'true' + + def __body_func(self, line): + self.__write_obj.write(line) + + def __default_func(self, line): + # either in preamble or in body + pass + + def __para_def_func(self, line): + # if self.__ob_group == 1 + # this tells dept of group + if self.__cb_count == '0002': + self.__state = 'body' + self.__write_preamble() + self.__write_obj.write(line) + + def __text_func(self, line): + """ + If the cb_count is less than 1, you have hit the body + For older RTF + Newer RTF should never have to use this function + """ + if self.__cb_count == '': + cb_count = '0002' + else: + cb_count = self.__cb_count + # ignore previous lines + # should be + # if self.__ob_group == 1 + # this tells dept of group + if cb_count == '0002': + self.__state = 'body' + self.__write_preamble() + self.__write_obj.write(line) + + def __row_def_func(self, line): + # if self.__ob_group == 1 + # this tells dept of group + if self.__cb_count == '0002': + self.__state = 'body' + self.__write_preamble() + self.__write_obj.write(line) + + def __new_section_func(self, line): + """ + This is new. The start of a section marks the end of the preamble + """ + if self.__cb_count == '0002': + self.__state = 'body' + self.__write_preamble() + else: + sys.stderr.write('module is preamble_div\n') + sys.stderr.write('method is __new_section_func\n') + sys.stderr.write('bracket count should be 2?\n') + self.__write_obj.write(line) + + def __write_preamble(self): + """ + Write all the strings, which represent all the data in the preamble. + Write a body and section beginning. + """ + if self.__no_namespace: + self.__write_obj.write( + 'mihttp://rtf2xml.sourceforge.net/\n') + self.__write_obj.write('mi1\n') + # self.__print_sec_info() + # self.__write_obj.write('mi%s%s' + '%s\n' % (self.__default_font, self.__code_page, + self.__platform) + ) + + def __found_list_table_func(self, line): + self.__state = 'list_table' + + def __list_table_func(self, line): + if self.__token_info == 'mi" for sub fields + """ + + def __init__(self, + in_file, + exception_handler, + bug_handler, + copy=None, + run_level=1, + ): + self.__file = in_file + self.__bug_handler = bug_handler + self.__copy = copy + self.__run_level = run_level + self.__write_to = better_mktemp() + self.initiate_token_dict() + # self.initiate_token_actions() + self.compile_expressions() + self.__bracket_count=0 + self.__exception_handler = exception_handler + self.__bug_handler = bug_handler + + def compile_expressions(self): + self.__num_exp = re.compile(r"([a-zA-Z]+)(.*)") + self.__utf_exp = re.compile(r'(&.*?;)') + + def initiate_token_dict(self): + self.__return_code = 0 + self.dict_token={ + # unicode + 'mshex' : ('nu', '__________', self.__ms_hex_func), + # brackets + '{' : ('nu', '{', self.ob_func), + '}' : ('nu', '}', self.cb_func), + # microsoft characters + 'ldblquote' : ('mc', 'ldblquote', self.ms_sub_func), + 'rdblquote' : ('mc', 'rdblquote', self.ms_sub_func), + 'rquote' : ('mc', 'rquote', self.ms_sub_func), + 'lquote' : ('mc', 'lquote', self.ms_sub_func), + 'emdash' : ('mc', 'emdash', self.ms_sub_func), + 'endash' : ('mc', 'endash', self.ms_sub_func), + 'bullet' : ('mc', 'bullet', self.ms_sub_func), + '~' : ('mc', '~', self.ms_sub_func), + 'tab' : ('mc', 'tab', self.ms_sub_func), + '_' : ('mc', '_', self.ms_sub_func), + ';' : ('mc', ';', self.ms_sub_func), + # this must be wrong + '-' : ('mc', '-', self.ms_sub_func), + 'line' : ('mi', 'hardline-break', self.direct_conv_func), # calibre + # misc => ml + '*' : ('ml', 'asterisk__', self.default_func), + ':' : ('ml', 'colon_____', self.default_func), + # text + 'backslash' : ('nu', '\\', self.text_func), + 'ob' : ('nu', '{', self.text_func), + 'cb' : ('nu', '}', self.text_func), + # paragraph formatting => pf + 'page' : ('pf', 'page-break', self.default_func), + 'par' : ('pf', 'par-end___', self.default_func), + 'pard' : ('pf', 'par-def___', self.default_func), + 'keepn' : ('pf', 'keep-w-nex', self.bool_st_func), + 'widctlpar' : ('pf', 'widow-cntl', self.bool_st_func), + 'adjustright' : ('pf', 'adjust-rgt', self.bool_st_func), + 'lang' : ('pf', 'language__', self.__language_func), + 'ri' : ('pf', 'right-inde', self.divide_by_20), + 'fi' : ('pf', 'fir-ln-ind', self.divide_by_20), + 'li' : ('pf', 'left-inden', self.divide_by_20), + 'sb' : ('pf', 'space-befo', self.divide_by_20), + 'sa' : ('pf', 'space-afte', self.divide_by_20), + 'sl' : ('pf', 'line-space', self.divide_by_20), + 'deftab' : ('pf', 'default-ta', self.divide_by_20), + 'ql' : ('pf', 'align_____ ss + 'stylesheet' : ('ss', 'style-shet', self.default_func), + 'sbasedon' : ('ss', 'based-on__', self.default_func), + 'snext' : ('ss', 'next-style', self.default_func), + 'cs' : ('ss', 'char-style', self.default_func), + 's' : ('ss', 'para-style', self.default_func), + # graphics => gr + 'pict' : ('gr', 'picture___', self.default_func), + 'objclass' : ('gr', 'obj-class_', self.default_func), + 'macpict' : ('gr', 'mac-pic___', self.default_func), + # section => sc + 'sect' : ('sc', 'section___', self.default_func), + 'sectd' : ('sc', 'sect-defin', self.default_func), + 'endhere' : ('sc', 'sect-note_', self.default_func), + # list=> ls + 'pntext' : ('ls', 'list-text_', self.default_func), + # this line must be wrong because it duplicates an earlier one + 'listtext' : ('ls', 'list-text_', self.default_func), + 'pn' : ('ls', 'list______', self.default_func), + 'pnseclvl' : ('ls', 'list-level', self.default_func), + 'pncard' : ('ls', 'list-cardi', self.bool_st_func), + 'pndec' : ('ls', 'list-decim', self.bool_st_func), + 'pnucltr' : ('ls', 'list-up-al', self.bool_st_func), + 'pnucrm' : ('ls', 'list-up-ro', self.bool_st_func), + 'pnord' : ('ls', 'list-ord__', self.bool_st_func), + 'pnordt' : ('ls', 'list-ordte', self.bool_st_func), + 'pnlvlblt' : ('ls', 'list-bulli', self.bool_st_func), + 'pnlvlbody' : ('ls', 'list-simpi', self.bool_st_func), + 'pnlvlcont' : ('ls', 'list-conti', self.bool_st_func), + 'pnhang' : ('ls', 'list-hang_', self.bool_st_func), + 'pntxtb' : ('ls', 'list-tebef', self.bool_st_func), + 'ilvl' : ('ls', 'list-level', self.default_func), + 'ls' : ('ls', 'list-id___', self.default_func), + 'pnstart' : ('ls', 'list-start', self.default_func), + 'itap' : ('ls', 'nest-level', self.default_func), + 'leveltext' : ('ls', 'level-text', self.default_func), + 'levelnumbers' : ('ls', 'level-numb', self.default_func), + 'list' : ('ls', 'list-in-tb', self.default_func), + 'listlevel' : ('ls', 'list-tb-le', self.default_func), + 'listname' : ('ls', 'list-name_', self.default_func), + 'listtemplateid' : ('ls', 'ls-tem-id_', self.default_func), + 'leveltemplateid' : ('ls', 'lv-tem-id_', self.default_func), + 'listhybrid' : ('ls', 'list-hybri', self.default_func), + 'levelstartat' : ('ls', 'level-star', self.default_func), + 'levelspace' : ('ls', 'level-spac', self.divide_by_20), + 'levelindent' : ('ls', 'level-inde', self.default_func), + 'levelnfc' : ('ls', 'level-type', self.__list_type_func), + 'levelnfcn' : ('ls', 'level-type', self.__list_type_func), + 'listid' : ('ls', 'lis-tbl-id', self.default_func), + 'listoverride' : ('ls', 'lis-overid', self.default_func), + # duplicate + 'pnlvl' : ('ls', 'list-level', self.default_func), + # root info => ri + 'rtf' : ('ri', 'rtf_______', self.default_func), + 'deff' : ('ri', 'deflt-font', self.default_func), + 'mac' : ('ri', 'macintosh_', self.default_func), + 'pc' : ('ri', 'pc________', self.default_func), + 'pca' : ('ri', 'pca_______', self.default_func), + 'ansi' : ('ri', 'ansi______', self.default_func), + 'ansicpg' : ('ri', 'ansi-codpg', self.default_func), + # notes => nt + 'footnote' : ('nt', 'footnote__', self.default_func), + 'ftnalt' : ('nt', 'type______ an + 'tc' : ('an', 'toc_______', self.default_func), + 'bkmkstt' : ('an', 'book-mk-st', self.default_func), + 'bkmkstart' : ('an', 'book-mk-st', self.default_func), + 'bkmkend' : ('an', 'book-mk-en', self.default_func), + 'xe' : ('an', 'index-mark', self.default_func), + 'rxe' : ('an', 'place_____', self.default_func), + # index => in + 'bxe' : ('in', 'index-bold', self.default_func), + 'ixe' : ('in', 'index-ital', self.default_func), + 'txe' : ('in', 'index-see_', self.default_func), + # table of contents => tc + 'tcl' : ('tc', 'toc-level_', self.default_func), + 'tcn' : ('tc', 'toc-sup-nu', self.default_func), + # field => fd + 'field' : ('fd', 'field_____', self.default_func), + 'fldinst' : ('fd', 'field-inst', self.default_func), + 'fldrslt' : ('fd', 'field-rslt', self.default_func), + 'datafield' : ('fd', 'datafield_', self.default_func), + # info-tables => it + 'fonttbl' : ('it', 'font-table', self.default_func), + 'colortbl' : ('it', 'colr-table', self.default_func), + 'listoverridetable' : ('it', 'lovr-table', self.default_func), + 'listtable' : ('it', 'listtable_', self.default_func), + 'revtbl' : ('it', 'revi-table', self.default_func), + # character info => ci + 'b' : ('ci', 'bold______', self.bool_st_func), + 'blue' : ('ci', 'blue______', self.color_func), + 'caps' : ('ci', 'caps______', self.bool_st_func), + 'cf' : ('ci', 'font-color', self.colorz_func), + 'chftn' : ('ci', 'footnot-mk', self.bool_st_func), + 'dn' : ('ci', 'font-down_', self.divide_by_2), + 'embo' : ('ci', 'emboss____', self.bool_st_func), + 'f' : ('ci', 'font-style', self.default_func), + 'fs' : ('ci', 'font-size_', self.divide_by_2), + 'green' : ('ci', 'green_____', self.color_func), + 'i' : ('ci', 'italics___', self.bool_st_func), + 'impr' : ('ci', 'engrave___', self.bool_st_func), + 'outl' : ('ci', 'outline___', self.bool_st_func), + 'plain' : ('ci', 'plain_____', self.bool_st_func), + 'red' : ('ci', 'red_______', self.color_func), + 'scaps' : ('ci', 'small-caps', self.bool_st_func), + 'shad' : ('ci', 'shadow____', self.bool_st_func), + 'strike' : ('ci', 'strike-thr', self.bool_st_func), + 'striked' : ('ci', 'dbl-strike', self.bool_st_func), + 'sub' : ('ci', 'subscript_', self.bool_st_func), + 'super' : ('ci', 'superscrip', self.bool_st_func), + 'nosupersub' : ('ci', 'no-su-supe', self.__no_sup_sub_func), + 'up' : ('ci', 'font-up___', self.divide_by_2), + 'v' : ('ci', 'hidden____', self.default_func), + # underline + # can't see why it isn't a char info: 'ul'=>'ci' + 'ul' : ('ci', 'underlined tb + 'trowd' : ('tb', 'row-def___', self.default_func), + 'cell' : ('tb', 'cell______', self.default_func), + 'row' : ('tb', 'row_______', self.default_func), + 'intbl' : ('tb', 'in-table__', self.default_func), + 'cols' : ('tb', 'columns___', self.default_func), + 'trleft' : ('tb', 'row-pos-le', self.divide_by_20), + 'cellx' : ('tb', 'cell-posit', self.divide_by_20), + 'trhdr' : ('tb', 'row-header', self.default_func), + # preamble => pr + # document information => di + # TODO integrate \userprops + 'info' : ('di', 'doc-info__', self.default_func), + 'title' : ('di', 'title_____', self.default_func), + 'author' : ('di', 'author____', self.default_func), + 'operator' : ('di', 'operator__', self.default_func), + 'manager' : ('di', 'manager___', self.default_func), + 'company' : ('di', 'company___', self.default_func), + 'keywords' : ('di', 'keywords__', self.default_func), + 'category' : ('di', 'category__', self.default_func), + 'doccomm' : ('di', 'doc-notes_', self.default_func), + 'comment' : ('di', 'doc-notes_', self.default_func), + 'subject' : ('di', 'subject___', self.default_func), + 'creatim' : ('di', 'create-tim', self.default_func), + 'yr' : ('di', 'year______', self.default_func), + 'mo' : ('di', 'month_____', self.default_func), + 'dy' : ('di', 'day_______', self.default_func), + 'min' : ('di', 'minute____', self.default_func), + 'sec' : ('di', 'second____', self.default_func), + 'revtim' : ('di', 'revis-time', self.default_func), + 'edmins' : ('di', 'edit-time_', self.default_func), + 'printim' : ('di', 'print-time', self.default_func), + 'buptim' : ('di', 'backuptime', self.default_func), + 'nofwords' : ('di', 'num-of-wor', self.default_func), + 'nofchars' : ('di', 'num-of-chr', self.default_func), + 'nofcharsws' : ('di', 'numofchrws', self.default_func), + 'nofpages' : ('di', 'num-of-pag', self.default_func), + 'version' : ('di', 'version___', self.default_func), + 'vern' : ('di', 'intern-ver', self.default_func), + 'hlinkbase' : ('di', 'linkbase__', self.default_func), + 'id' : ('di', 'internalID', self.default_func), + # headers and footers => hf + 'headerf' : ('hf', 'head-first', self.default_func), + 'headerl' : ('hf', 'head-left_', self.default_func), + 'headerr' : ('hf', 'head-right', self.default_func), + 'footerf' : ('hf', 'foot-first', self.default_func), + 'footerl' : ('hf', 'foot-left_', self.default_func), + 'footerr' : ('hf', 'foot-right', self.default_func), + 'header' : ('hf', 'header____', self.default_func), + 'footer' : ('hf', 'footer____', self.default_func), + # page => pa + 'margl' : ('pa', 'margin-lef', self.divide_by_20), + 'margr' : ('pa', 'margin-rig', self.divide_by_20), + 'margb' : ('pa', 'margin-bot', self.divide_by_20), + 'margt' : ('pa', 'margin-top', self.divide_by_20), + 'gutter' : ('pa', 'gutter____', self.divide_by_20), + 'paperw' : ('pa', 'paper-widt', self.divide_by_20), + 'paperh' : ('pa', 'paper-hght', self.divide_by_20), + # annotation => an + 'annotation' : ('an', 'annotation', self.default_func), + # border => bd + 'trbrdrh' : ('bd', 'bor-t-r-hi', self.default_func), + 'trbrdrv' : ('bd', 'bor-t-r-vi', self.default_func), + 'trbrdrt' : ('bd', 'bor-t-r-to', self.default_func), + 'trbrdrl' : ('bd', 'bor-t-r-le', self.default_func), + 'trbrdrb' : ('bd', 'bor-t-r-bo', self.default_func), + 'trbrdrr' : ('bd', 'bor-t-r-ri', self.default_func), + 'clbrdrb' : ('bd', 'bor-cel-bo', self.default_func), + 'clbrdrt' : ('bd', 'bor-cel-to', self.default_func), + 'clbrdrl' : ('bd', 'bor-cel-le', self.default_func), + 'clbrdrr' : ('bd', 'bor-cel-ri', self.default_func), + 'brdrb' : ('bd', 'bor-par-bo', self.default_func), + 'brdrt' : ('bd', 'bor-par-to', self.default_func), + 'brdrl' : ('bd', 'bor-par-le', self.default_func), + 'brdrr' : ('bd', 'bor-par-ri', self.default_func), + 'box' : ('bd', 'bor-par-bx', self.default_func), + 'chbrdr' : ('bd', 'bor-par-bo', self.default_func), + 'brdrbtw' : ('bd', 'bor-for-ev', self.default_func), + 'brdrbar' : ('bd', 'bor-outsid', self.default_func), + 'brdrnone' : ('bd', 'bor-none__ bt + 'brdrs' : ('bt', 'bdr-single', self.default_func), + 'brdrth' : ('bt', 'bdr-doubtb', self.default_func), + 'brdrsh' : ('bt', 'bdr-shadow', self.default_func), + 'brdrdb' : ('bt', 'bdr-double', self.default_func), + 'brdrdot' : ('bt', 'bdr-dotted', self.default_func), + 'brdrdash' : ('bt', 'bdr-dashed', self.default_func), + 'brdrhair' : ('bt', 'bdr-hair__', self.default_func), + 'brdrinset' : ('bt', 'bdr-inset_', self.default_func), + 'brdrdashsm' : ('bt', 'bdr-das-sm', self.default_func), + 'brdrdashd' : ('bt', 'bdr-dot-sm', self.default_func), + 'brdrdashdd' : ('bt', 'bdr-dot-do', self.default_func), + 'brdroutset' : ('bt', 'bdr-outset', self.default_func), + 'brdrtriple' : ('bt', 'bdr-trippl', self.default_func), + 'brdrtnthsg' : ('bt', 'bdr-thsm__', self.default_func), + 'brdrthtnsg' : ('bt', 'bdr-htsm__', self.default_func), + 'brdrtnthtnsg' : ('bt', 'bdr-hthsm_', self.default_func), + 'brdrtnthmg' : ('bt', 'bdr-thm___', self.default_func), + 'brdrthtnmg' : ('bt', 'bdr-htm___', self.default_func), + 'brdrtnthtnmg' : ('bt', 'bdr-hthm__', self.default_func), + 'brdrtnthlg' : ('bt', 'bdr-thl___', self.default_func), + 'brdrtnthtnlg' : ('bt', 'bdr-hthl__', self.default_func), + 'brdrwavy' : ('bt', 'bdr-wavy__', self.default_func), + 'brdrwavydb' : ('bt', 'bdr-d-wav_', self.default_func), + 'brdrdashdotstr' : ('bt', 'bdr-strip_', self.default_func), + 'brdremboss' : ('bt', 'bdr-embos_', self.default_func), + 'brdrengrave' : ('bt', 'bdr-engra_', self.default_func), + 'brdrframe' : ('bt', 'bdr-frame_', self.default_func), + 'brdrw' : ('bt', 'bdr-li-wid', self.divide_by_20), + 'brsp' : ('bt', 'bdr-sp-wid', self.divide_by_20), + 'brdrcf' : ('bt', 'bdr-color_', self.default_func), + # comments + # 'comment' : ('cm', 'comment___', self.default_func), + } + self.__number_type_dict = { + 0: 'Arabic', + 1: 'uppercase Roman numeral', + 2: 'lowercase Roman numeral', + 3: 'uppercase letter', + 4: 'lowercase letter', + 5: 'ordinal number', + 6: 'cardianl text number', + 7: 'ordinal text number', + 10: 'Kanji numbering without the digit character', + 11: 'Kanji numbering with the digit character', + 1246: 'phonetic Katakana characters in aiueo order', + 1346: 'phonetic katakana characters in iroha order', + 14: 'double byte character', + 15: 'single byte character', + 16: 'Kanji numbering 3', + 17: 'Kanji numbering 4', + 18: 'Circle numbering' , + 19: 'double-byte Arabic numbering', + 2046: 'phonetic double-byte Katakana characters', + 2146: 'phonetic double-byte katakana characters', + 22: 'Arabic with leading zero', + 23: 'bullet', + 24: 'Korean numbering 2', + 25: 'Korean numbering 1', + 26: 'Chinese numbering 1', + 27: 'Chinese numbering 2', + 28: 'Chinese numbering 3', + 29: 'Chinese numbering 4', + 30: 'Chinese Zodiac numbering 1', + 31: 'Chinese Zodiac numbering 2', + 32: 'Chinese Zodiac numbering 3', + 33: 'Taiwanese double-byte numbering 1', + 34: 'Taiwanese double-byte numbering 2', + 35: 'Taiwanese double-byte numbering 3', + 36: 'Taiwanese double-byte numbering 4', + 37: 'Chinese double-byte numbering 1', + 38: 'Chinese double-byte numbering 2', + 39: 'Chinese double-byte numbering 3', + 40: 'Chinese double-byte numbering 4', + 41: 'Korean double-byte numbering 1', + 42: 'Korean double-byte numbering 2', + 43: 'Korean double-byte numbering 3', + 44: 'Korean double-byte numbering 4', + 45: 'Hebrew non-standard decimal', + 46: 'Arabic Alif Ba Tah', + 47: 'Hebrew Biblical standard', + 48: 'Arabic Abjad style', + 255: 'No number', + } + self.__language_dict = { + 1078 : 'Afrikaans', + 1052 : 'Albanian', + 1025 : 'Arabic', + 5121 : 'Arabic Algeria', + 15361 : 'Arabic Bahrain', + 3073 : 'Arabic Egypt', + 1 : 'Arabic General', + 2049 : 'Arabic Iraq', + 11265 : 'Arabic Jordan', + 13313 : 'Arabic Kuwait', + 12289 : 'Arabic Lebanon', + 4097 : 'Arabic Libya', + 6145 : 'Arabic Morocco', + 8193 : 'Arabic Oman', + 16385 : 'Arabic Qatar', + 10241 : 'Arabic Syria', + 7169 : 'Arabic Tunisia', + 14337 : 'Arabic U.A.E.', + 9217 : 'Arabic Yemen', + 1067 : 'Armenian', + 1101 : 'Assamese', + 2092 : 'Azeri Cyrillic', + 1068 : 'Azeri Latin', + 1069 : 'Basque', + 1093 : 'Bengali', + 4122 : 'Bosnia Herzegovina', + 1026 : 'Bulgarian', + 1109 : 'Burmese', + 1059 : 'Byelorussian', + 1027 : 'Catalan', + 2052 : 'Chinese China', + 4 : 'Chinese General', + 3076 : 'Chinese Hong Kong', + 4100 : 'Chinese Singapore', + 1028 : 'Chinese Taiwan', + 1050 : 'Croatian', + 1029 : 'Czech', + 1030 : 'Danish', + 2067 : 'Dutch Belgium', + 1043 : 'Dutch Standard', + 3081 : 'English Australia', + 10249 : 'English Belize', + 2057 : 'English British', + 4105 : 'English Canada', + 9225 : 'English Caribbean', + 9 : 'English General', + 6153 : 'English Ireland', + 8201 : 'English Jamaica', + 5129 : 'English New Zealand', + 13321 : 'English Philippines', + 7177 : 'English South Africa', + 11273 : 'English Trinidad', + 1033 : 'English United States', + 1061 : 'Estonian', + 1080 : 'Faerose', + 1065 : 'Farsi', + 1035 : 'Finnish', + 1036 : 'French', + 2060 : 'French Belgium', + 11276 : 'French Cameroon', + 3084 : 'French Canada', + 12300 : 'French Cote d\'Ivoire', + 5132 : 'French Luxembourg', + 13324 : 'French Mali', + 6156 : 'French Monaco', + 8204 : 'French Reunion', + 10252 : 'French Senegal', + 4108 : 'French Swiss', + 7180 : 'French West Indies', + 9228 : 'French Democratic Republic of the Congo', + 1122 : 'Frisian', + 1084 : 'Gaelic', + 2108 : 'Gaelic Ireland', + 1110 : 'Galician', + 1079 : 'Georgian', + 1031 : 'German', + 3079 : 'German Austrian', + 5127 : 'German Liechtenstein', + 4103 : 'German Luxembourg', + 2055 : 'German Switzerland', + 1032 : 'Greek', + 1095 : 'Gujarati', + 1037 : 'Hebrew', + 1081 : 'Hindi', + 1038 : 'Hungarian', + 1039 : 'Icelandic', + 1057 : 'Indonesian', + 1040 : 'Italian', + 2064 : 'Italian Switzerland', + 1041 : 'Japanese', + 1099 : 'Kannada', + 1120 : 'Kashmiri', + 2144 : 'Kashmiri India', + 1087 : 'Kazakh', + 1107 : 'Khmer', + 1088 : 'Kirghiz', + 1111 : 'Konkani', + 1042 : 'Korean', + 2066 : 'Korean Johab', + 1108 : 'Lao', + 1062 : 'Latvian', + 1063 : 'Lithuanian', + 2087 : 'Lithuanian Classic', + 1086 : 'Malay', + 2110 : 'Malay Brunei Darussalam', + 1100 : 'Malayalam', + 1082 : 'Maltese', + 1112 : 'Manipuri', + 1102 : 'Marathi', + 1104 : 'Mongolian', + 1121 : 'Nepali', + 2145 : 'Nepali India', + 1044 : 'Norwegian Bokmal', + 2068 : 'Norwegian Nynorsk', + 1096 : 'Oriya', + 1045 : 'Polish', + 1046 : 'Portuguese (Brazil)', + 2070 : 'Portuguese (Portugal)', + 1094 : 'Punjabi', + 1047 : 'Rhaeto-Romanic', + 1048 : 'Romanian', + 2072 : 'Romanian Moldova', + 1049 : 'Russian', + 2073 : 'Russian Moldova', + 1083 : 'Sami Lappish', + 1103 : 'Sanskrit', + 3098 : 'Serbian Cyrillic', + 2074 : 'Serbian Latin', + 1113 : 'Sindhi', + 1051 : 'Slovak', + 1060 : 'Slovenian', + 1070 : 'Sorbian', + 11274 : 'Spanish Argentina', + 16394 : 'Spanish Bolivia', + 13322 : 'Spanish Chile', + 9226 : 'Spanish Colombia', + 5130 : 'Spanish Costa Rica', + 7178 : 'Spanish Dominican Republic', + 12298 : 'Spanish Ecuador', + 17418 : 'Spanish El Salvador', + 4106 : 'Spanish Guatemala', + 18442 : 'Spanish Honduras', + 2058 : 'Spanish Mexico', + 3082 : 'Spanish Modern', + 19466 : 'Spanish Nicaragua', + 6154 : 'Spanish Panama', + 15370 : 'Spanish Paraguay', + 10250 : 'Spanish Peru', + 20490 : 'Spanish Puerto Rico', + 1034 : 'Spanish Traditional', + 14346 : 'Spanish Uruguay', + 8202 : 'Spanish Venezuela', + 1072 : 'Sutu', + 1089 : 'Swahili', + 1053 : 'Swedish', + 2077 : 'Swedish Finland', + 1064 : 'Tajik', + 1097 : 'Tamil', + 1092 : 'Tatar', + 1098 : 'Telugu', + 1054 : 'Thai', + 1105 : 'Tibetan', + 1073 : 'Tsonga', + 1074 : 'Tswana', + 1055 : 'Turkish', + 1090 : 'Turkmen', + 1058 : 'Ukranian', + 1056 : 'Urdu', + 2080 : 'Urdu India', + 2115 : 'Uzbek Cyrillic', + 1091 : 'Uzbek Latin', + 1075 : 'Venda', + 1066 : 'Vietnamese', + 1106 : 'Welsh', + 1076 : 'Xhosa', + 1085 : 'Yiddish', + 1077 : 'Zulu', + 1024 : 'Unkown', + 255 : 'Unkown', + } + """ + # unknown + # These must get passed on because they occure after \\* + 'do' : ('un', 'unknown___', self.default_func), + 'company' : ('un', 'company___', self.default_func), + 'shpinst' : ('un', 'unknown___', self.default_func), + 'panose' : ('un', 'unknown___', self.default_func), + 'falt' : ('un', 'unknown___', self.default_func), + 'listoverridetable' : ('un', 'unknown___', self.default_func), + 'category' : ('un', 'unknown___', self.default_func), + 'template' : ('un', 'unknown___', self.default_func), + 'ud' : ('un', 'unknown___', self.default_func), + 'formfield' : ('un', 'unknown___', self.default_func), + 'ts' : ('un', 'unknown___', self.default_func), + 'rsidtbl' : ('un', 'unknown___', self.default_func), + 'generator' : ('un', 'unknown___', self.default_func), + 'ftnsep' : ('un', 'unknown___', self.default_func), + 'aftnsep' : ('un', 'unknown___', self.default_func), + 'aftnsepc' : ('un', 'unknown___', self.default_func), + 'aftncn' : ('un', 'unknown___', self.default_func), + 'objclass' : ('un', 'unknown___', self.default_func), + 'objdata' : ('un', 'unknown___', self.default_func), + 'picprop' : ('un', 'unknown___', self.default_func), + 'blipuid' : ('un', 'unknown___', self.default_func), + """ + + def __ms_hex_func(self, pre, token, num): + num = num[1:] # chop off leading 0, which I added + num = num.upper() # the mappings store hex in caps + return 'tx 3: + msg = 'Number "%s" cannot be converted to integer\n' % num + raise self.__bug_handler(msg) + type = self.__number_type_dict.get(num) + if type is None: + if self.__run_level > 3: + msg = 'No type for "%s" in self.__number_type_dict\n' + raise self.__bug_handler + type = 'Arabic' + return 'cw<%s<%s 3: + msg = 'No entry for number "%s"' % num + raise self.__bug_handler(msg) + return 'cw<%s<%snum<%s\n' % (token, num) + + def divide_by_2(self, pre, token, num): + num = self.divide_num(num, 2) + return 'cw<%s<%s%s<%s\n' % (token, num, token) + + def divide_by_20(self, pre, token, num): + num = self.divide_num(num, 20) + return 'cw<%s<%s%s<%s\n' % (token, num, token) + + def text_func(self, pre, token, num=None): + return 'tx%s<%s\n' % (third_field, token, num, token) + + def bool_st_func(self, pre, token, num): + if num is None or num == '' or num == '1': + return 'cw<%s<%strue<%s\n' % (token, token) + elif num == '0': + return 'cw<%s<%sfalse<%s\n' % (token, token) + else: + msg = "boolean should have some value module process tokens\ntoken is %s\n'%s'\n" % (token, num) + raise self.__bug_handler(msg) + + def __no_sup_sub_func(self, pre, token, num): + the_string = 'cw 3: + msg = ('No number to process?\nthis indicates that the token \\(\\li\\) \ + should have a number and does not\nnumerator is \ + "%s"\ndenominator is "%s"\n') % (numerator, denominator) + raise self.__bug_handler(msg) + if 5 > self.__return_code: + self.__return_code = 5 + return 0 + num = '%0.2f' % round(numerator/denominator, 2) + return num + string_num = unicode_type(num) + if string_num[-2:] == ".0": + string_num = string_num[:-2] + return string_num + + def split_let_num(self, token): + match_obj = re.search(self.__num_exp,token) + if match_obj is not None: + first = match_obj.group(1) + second = match_obj.group(2) + if not second: + if self.__run_level > 3: + msg = "token is '%s' \n" % token + raise self.__bug_handler(msg) + return first, 0 + else: + if self.__run_level > 3: + msg = "token is '%s' \n" % token + raise self.__bug_handler + return token, 0 + return first, second + + def convert_to_hex(self,number): + """Convert a string to uppercase hexidecimal""" + num = int(number) + try: + hex_num = "%X" % num + return hex_num + except: + raise self.__bug_handler + + def process_cw(self, token): + """Change the value of the control word by determining what dictionary + it belongs to""" + special = ['*', ':', '}', '{', '~', '_', '-', ';'] + # if token != "{" or token != "}": + token = token[1:] # strip off leading \ + token = token.replace(" ", "") + # if not token: return + only_alpha = token.isalpha() + num = None + if not only_alpha and token not in special: + token, num = self.split_let_num(token) + pre, token, action = self.dict_token.get(token, (None, None, None)) + if action: + return action(pre, token, num) + + def __check_brackets(self, in_file): + self.__check_brack_obj = check_brackets.CheckBrackets(file=in_file) + good_br = self.__check_brack_obj.check_brackets()[0] + if not good_br: + return 1 + + def process_tokens(self): + """Main method for handling other methods. """ + line_count = 0 + with open_for_read(self.__file) as read_obj: + with open_for_write(self.__write_to) as write_obj: + for line in read_obj: + token = line.replace("\n", "") + line_count += 1 + if line_count == 1 and token != '\\{': + msg = '\nInvalid RTF: document doesn\'t start with {\n' + raise self.__exception_handler(msg) + elif line_count == 2 and token[0:4] != '\\rtf': + msg = '\nInvalid RTF: document doesn\'t start with \\rtf \n' + raise self.__exception_handler(msg) + + the_index = token.find('\\ ') + if token is not None and the_index > -1: + msg = '\nInvalid RTF: token "\\ " not valid.\nError at line %d'\ + % line_count + raise self.__exception_handler(msg) + elif token[:1] == "\\": + line = self.process_cw(token) + if line is not None: + write_obj.write(line) + else: + fields = re.split(self.__utf_exp, token) + for field in fields: + if not field: + continue + if field[0:1] == '&': + write_obj.write('tx 0: + for key in keys: + my_string += '<%s>%s' % (key, self.__section_values[key]) + my_string += '\n' + my_string += self.__mark_end + # # my_string += line + if self.__state == 'body': + self.__write_obj.write(my_string) + elif self.__state == 'sec_in_field': + self.__handle_sec_def(my_string) + elif self.__run_level > 3: + msg = 'missed a flag\n' + raise self.__bug_handler(msg) + + def __handle_sec_def(self, my_string): + """ + Requires: + my_string -- the string of attributes and values. (Do I need this?) + Returns: + nothing + Logic: + I need to append the dictionary of attributes and values to list + so I can use it later when I reach the end of the field-block. + """ + values_dict = self.__section_values + self.__list_of_sec_values.append(values_dict) + + def __body_func(self, line): + """ + Requires: + line --the line to parse + Returns: + nothing + Logic: + Look for the beginning of a section. Otherwise, print the line to + the output file. + """ + action = self.__body_dict.get(self.__token_info) + if action: + action(line) + else: + self.__write_obj.write(line) + + def __before_body_func(self, line): + """ + Requires: + line --line to parse + Returns: + nothing + Logic: + Look for the beginning of the body. Always print out the line. + """ + if self.__token_info == 'mi%s' + '%s' + 'rtf-native' + '0\n' + % (unicode_type(self.__section_num), unicode_type(self.__section_num)) + ) + self.__found_first_sec = 1 + elif self.__token_info == 'tx%s' + '%s' + 'rtf-native' + '0\n' + % (unicode_type(self.__section_num), unicode_type(self.__section_num)) + ) + self.__write_obj.write( + 'cw 0: + my_string += 'mi%s' % unicode_type(num) + ) + if self.__list_of_sec_values: + keys = self.__list_of_sec_values[0].keys() + for key in keys: + self.__write_obj.write( + '<%s>%s\n' % (key, self.__list_of_sec_values[0][key])) + self.__list_of_sec_values = self.__list_of_sec_values[1:] + self.__write_obj.write('0') + self.__write_obj.write('rtf-native') + self.__write_obj.write('%s' % unicode_type(self.__section_num)) + self.__write_obj.write('\n') + # Look here + + def __found_section_in_field_func(self, line): + """ + Requires: + line --line to parse + Returns: + nothing + Logic: + I have found a section in a field block. Add one to section + counter, and append this number to a list. + """ + self.__section_num += 1 + self.__field_num.append(self.__section_num) + self.__sec_in_field_string += line + + def __found_section_def_in_field_func(self, line): + """ + Requires: + line --line to parse + Returns: + nothing + Logic: + I have found a section definition in a filed block. Change the + state and clear the values dictionary. + """ + self.__state = 'section_def' + self.__section_values.clear() + + def make_sections(self): + """ + Requires: + nothing + Returns: + nothing (changes the original file) + Logic: + Read one line in at a time. Determine what action to take based on + the state. If the state is before the body, look for the + beginning of the body. + If the state is body, send the line to the body method. + """ + self.__initiate_values() + read_obj = open_for_read(self.__file) + self.__write_obj = open_for_write(self.__write_to) + line_to_read = 1 + while line_to_read: + line_to_read = read_obj.readline() + line = line_to_read + self.__token_info = line[:16] + action = self.__state_dict.get(self.__state) + if action is None: + sys.stderr.write('no matching state in module sections.py\n') + sys.stderr.write(self.__state + '\n') + action(line) + read_obj.close() + self.__write_obj.close() + copy_obj = copy.Copy(bug_handler=self.__bug_handler) + if self.__copy: + copy_obj.copy_file(self.__write_to, "sections.data") + copy_obj.rename(self.__write_to, self.__file) + os.remove(self.__write_to) diff --git a/ebook_converter/ebooks/rtf2xml/styles.py b/ebook_converter/ebooks/rtf2xml/styles.py new file mode 100644 index 0000000..d86e267 --- /dev/null +++ b/ebook_converter/ebooks/rtf2xml/styles.py @@ -0,0 +1,723 @@ +from __future__ import unicode_literals, absolute_import, print_function, division +######################################################################### +# # +# # +# copyright 2002 Paul Henry Tremblay # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # +# General Public License for more details. # +# # +# # +######################################################################### +import sys, os +from calibre.ebooks.rtf2xml import copy, border_parse +from calibre.ptempfile import better_mktemp +from . import open_for_read, open_for_write + + +class Styles: + """ + Change lines with style numbers to actual style names. + """ + + def __init__(self, + in_file, + bug_handler, + copy=None, + run_level=1, + ): + """ + Required: + 'file'--file to parse + Optional: + 'copy'-- whether to make a copy of result for debugging + 'temp_dir' --where to output temporary results (default is + directory from which the script is run.) + Returns: + nothing + """ + self.__file = in_file + self.__bug_handler = bug_handler + self.__copy = copy + self.__write_to = better_mktemp() + self.__run_level = run_level + + def __initiate_values(self): + """ + Initiate all values. + """ + self.__border_obj = border_parse.BorderParse() + self.__styles_dict = {'par':{}, 'char':{}} + self.__styles_num = '0' + self.__type_of_style = 'par' + self.__text_string = '' + self.__state = 'before_styles_table' + self.__state_dict = { + 'before_styles_table': self.__before_styles_func, + 'in_styles_table' : self.__in_styles_func, + 'in_individual_style' : self.__in_individual_style_func, + 'after_styles_table' : self.__after_styles_func, + 'mi pf + 'par-end___' : 'para', + 'par-def___' : 'paragraph-definition', + 'keep-w-nex' : 'keep-with-next', + 'widow-cntl' : 'widow-control', + 'adjust-rgt' : 'adjust-right', + 'language__' : 'language', + 'right-inde' : 'right-indent', + 'fir-ln-ind' : 'first-line-indent', + 'left-inden' : 'left-indent', + 'space-befo' : 'space-before', + 'space-afte' : 'space-after', + 'line-space' : 'line-spacing', + 'default-ta' : 'default-tab', + 'align_____' : 'align', + 'widow-cntr' : 'widow-control', + # page fomratting mixed in! (Just in older RTF?) + 'margin-lef' : 'left-indent', + 'margin-rig' : 'right-indent', + 'margin-bot' : 'space-after', + 'margin-top' : 'space-before', + # stylesheet = > ss + 'style-shet' : 'stylesheet', + 'based-on__' : 'based-on-style', + 'next-style' : 'next-style', + 'char-style' : 'character-style', + 'para-style' : 'paragraph-style', + # graphics => gr + 'picture___' : 'pict', + 'obj-class_' : 'obj_class', + 'mac-pic___' : 'mac-pict', + # section => sc + 'section___' : 'section-new', + 'sect-defin' : 'section-reset', + 'sect-note_' : 'endnotes-in-section', + # list=> ls + 'list-text_' : 'list-text', + 'list______' : 'list', + 'list-lev-d' : 'list-level-definition', + 'list-cardi' : 'list-cardinal-numbering', + 'list-decim' : 'list-decimal-numbering', + 'list-up-al' : 'list-uppercase-alphabetic-numbering', + 'list-up-ro' : 'list-uppercae-roman-numbering', + 'list-ord__' : 'list-ordinal-numbering', + 'list-ordte' : 'list-ordinal-text-numbering', + 'list-bulli' : 'list-bullet', + 'list-simpi' : 'list-simple', + 'list-conti' : 'list-continue', + 'list-hang_' : 'list-hang', + # 'list-tebef' : 'list-text-before', + # 'list-level' : 'level', + 'list-id___' : 'list-id', + 'list-start' : 'list-start', + 'nest-level' : 'nest-level', + # duplicate + 'list-level' : 'list-level', + # notes => nt + 'footnote__' : 'footnote', + 'type______' : 'type', + # anchor => an + 'toc_______' : 'anchor-toc', + 'book-mk-st' : 'bookmark-start', + 'book-mk-en' : 'bookmark-end', + 'index-mark' : 'anchor-index', + 'place_____' : 'place', + # field => fd + 'field_____' : 'field', + 'field-inst' : 'field-instruction', + 'field-rslt' : 'field-result', + 'datafield_' : 'data-field', + # info-tables => it + 'font-table' : 'font-table', + 'colr-table' : 'color-table', + 'lovr-table' : 'list-override-table', + 'listtable_' : 'list-table', + 'revi-table' : 'revision-table', + # character info => ci + 'hidden____' : 'hidden', + 'italics___' : 'italics', + 'bold______' : 'bold', + 'strike-thr' : 'strike-through', + 'shadow____' : 'shadow', + 'outline___' : 'outline', + 'small-caps' : 'small-caps', + 'dbl-strike' : 'double-strike-through', + 'emboss____' : 'emboss', + 'engrave___' : 'engrave', + 'subscript_' : 'subscript', + 'superscrip' : 'superscript', + 'plain_____' : 'plain', + 'font-style' : 'font-style', + 'font-color' : 'font-color', + 'font-size_' : 'font-size', + 'font-up___' : 'superscript', + 'font-down_' : 'subscript', + 'red_______' : 'red', + 'blue______' : 'blue', + 'green_____' : 'green', + 'caps______' : 'caps', + # table => tb + 'row-def___' : 'row-definition', + 'cell______' : 'cell', + 'row_______' : 'row', + 'in-table__' : 'in-table', + 'columns___' : 'columns', + 'row-pos-le' : 'row-position-left', + 'cell-posit' : 'cell-position', + # preamble => pr + # underline + 'underlined' : 'underlined', + # border => bd + 'bor-t-r-hi' : 'border-table-row-horizontal-inside', + 'bor-t-r-vi' : 'border-table-row-vertical-inside', + 'bor-t-r-to' : 'border-table-row-top', + 'bor-t-r-le' : 'border-table-row-left', + 'bor-t-r-bo' : 'border-table-row-bottom', + 'bor-t-r-ri' : 'border-table-row-right', + 'bor-cel-bo' : 'border-cell-bottom', + 'bor-cel-to' : 'border-cell-top', + 'bor-cel-le' : 'border-cell-left', + 'bor-cel-ri' : 'border-cell-right', + # 'bor-par-bo' : 'border-paragraph-bottom', + 'bor-par-to' : 'border-paragraph-top', + 'bor-par-le' : 'border-paragraph-left', + 'bor-par-ri' : 'border-paragraph-right', + 'bor-par-bo' : 'border-paragraph-box', + 'bor-for-ev' : 'border-for-every-paragraph', + 'bor-outsid' : 'border-outisde', + 'bor-none__' : 'border', + # border type => bt + 'bdr-single' : 'single', + 'bdr-doubtb' : 'double-thickness-border', + 'bdr-shadow' : 'shadowed-border', + 'bdr-double' : 'double-border', + 'bdr-dotted' : 'dotted-border', + 'bdr-dashed' : 'dashed', + 'bdr-hair__' : 'hairline', + 'bdr-inset_' : 'inset', + 'bdr-das-sm' : 'dash-small', + 'bdr-dot-sm' : 'dot-dash', + 'bdr-dot-do' : 'dot-dot-dash', + 'bdr-outset' : 'outset', + 'bdr-trippl' : 'tripple', + 'bdr-thsm__' : 'thick-thin-small', + 'bdr-htsm__' : 'thin-thick-small', + 'bdr-hthsm_' : 'thin-thick-thin-small', + 'bdr-thm__' : 'thick-thin-medium', + 'bdr-htm__' : 'thin-thick-medium', + 'bdr-hthm_' : 'thin-thick-thin-medium', + 'bdr-thl__' : 'thick-thin-large', + 'bdr-hthl_' : 'think-thick-think-large', + 'bdr-wavy_' : 'wavy', + 'bdr-d-wav' : 'double-wavy', + 'bdr-strip' : 'striped', + 'bdr-embos' : 'emboss', + 'bdr-engra' : 'engrave', + 'bdr-frame' : 'frame', + 'bdr-li-wid' : 'line-width', + # tabs + 'tab-center' : 'center', + 'tab-right_' : 'right', + 'tab-dec___' : 'decimal', + 'leader-dot' : 'leader-dot', + 'leader-hyp' : 'leader-hyphen', + 'leader-und' : 'leader-underline', + } + self.__tabs_dict = { + 'cw 3: + msg = 'no value for key %s\n' % info + raise self.__bug_handler(msg) + else: + value = line[20:-1] + self.__enter_dict_entry(att, value) + elif line[0:2] == 'tx': + self.__text_string += line[17:-1] + + def __tab_stop_func(self, line): + """ + Requires: + line -- line to parse + Returns: + nothing + Logic: + Try to add the number to dictionary entry tabs-left, or tabs-right, etc. + If the dictionary entry doesn't exist, create one. + """ + try: + if self.__leader_found: + self.__styles_dict['par'][self.__styles_num]['tabs']\ + += '%s:' % self.__tab_type + self.__styles_dict['par'][self.__styles_num]['tabs']\ + += '%s;' % line[20:-1] + else: + self.__styles_dict['par'][self.__styles_num]['tabs']\ + += '%s:' % self.__tab_type + self.__styles_dict['par'][self.__styles_num]['tabs']\ + += '%s;' % line[20:-1] + except KeyError: + self.__enter_dict_entry('tabs', '') + self.__styles_dict['par'][self.__styles_num]['tabs']\ + += '%s:' % self.__tab_type + self.__styles_dict['par'][self.__styles_num]['tabs'] += '%s;' % line[20:-1] + self.__tab_type = 'left' + self.__leader_found = 0 + + def __tab_type_func(self, line): + """ + """ + type = self.__tab_type_dict.get(self.__token_info) + if type is not None: + self.__tab_type = type + else: + if self.__run_level > 3: + msg = 'no entry for %s\n' % self.__token_info + raise self.__bug_handler(msg) + + def __tab_leader_func(self, line): + """ + Requires: + line --line to parse + Returns: + nothing + Logic: + Try to add the string of the tab leader to dictionary entry + tabs-left, or tabs-right, etc. If the dictionary entry doesn't + exist, create one. + """ + self.__leader_found = 1 + leader = self.__tab_type_dict.get(self.__token_info) + if leader is not None: + leader += '^' + try: + self.__styles_dict['par'][self.__styles_num]['tabs'] += ':%s;' % leader + except KeyError: + self.__enter_dict_entry('tabs', '') + self.__styles_dict['par'][self.__styles_num]['tabs'] += '%s;' % leader + else: + if self.__run_level > 3: + msg = 'no entry for %s\n' % self.__token_info + raise self.__bug_handler(msg) + + def __tab_bar_func(self, line): + """ + Requires: + line -- line to parse + Returns: + nothing + Logic: + Try to add the string of the tab bar to dictionary entry tabs-bar. + If the dictionary entry doesn't exist, create one. + """ + # self.__add_dict_entry('tabs-bar', line[20:-1]) + try: + self.__styles_dict['par'][self.__styles_num]['tabs']\ + += '%s:' % 'bar' + self.__styles_dict['par'][self.__styles_num]['tabs']\ + += '%s;' % line[20:-1] + except KeyError: + self.__enter_dict_entry('tabs', '') + self.__styles_dict['par'][self.__styles_num]['tabs']\ + += '%s:' % 'bar' + self.__styles_dict['par'][self.__styles_num]['tabs']\ + += '%s;' % line[20:-1] + self.__tab_type = 'left' + + def __enter_dict_entry(self, att, value): + """ + Required: + att -- the attribute + value -- the value + Returns: + nothing + Logic: + Try to add the attribute value directly to the styles dictionary. + If a keyerror is found, that means I have to build the "branches" + of the dictionary before I can add the key value pair. + """ + try: + self.__styles_dict[self.__type_of_style][self.__styles_num][att] = value + except KeyError: + self.__add_dict_entry(att, value) + + def __add_dict_entry(self, att, value): + """ + Required: + att --the attribute + value --the value + Returns: + nothing + Logic: + I have to build the branches of the dictionary before I can add + the leaves. (I am comparing a dictionary to a tree.) To achieve + this, I first make a temporary dictionary by extracting either the + inside dictionary of the keyword par or char. This temporary + dictionary is called type_dict. + Next, create a second, smaller dictionary with just the attribute and value. + Add the small dictionary to the type dictionary. + Add this type dictionary to the main styles dictionary. + """ + if self.__type_of_style == 'par': + type_dict =self.__styles_dict['par'] + elif self.__type_of_style == 'char': + type_dict = self.__styles_dict['char'] + else: + if self.__run_level > 3: + msg = self.__type_of_style + 'error\n' + raise self.__bug_handler(msg) + smallest_dict = {} + smallest_dict[att] = value + type_dict[self.__styles_num] = smallest_dict + self.__styles_dict[self.__type_of_style] = type_dict + + def __para_style_func(self, line): + """ + Required: + line + Returns: + nothing + Logic: + Set the type of style to paragraph. + Extract the number for a line such as "cw '15'. I want to change the 15 to the name of the + style. I accomplish this by simply looking up the value of 15 in + the styles table. + Use two loops. First, check all the paragraph styles. Then check + all the characer styles. + The inner loop: first check 'next-style', then check 'based-on-style'. + Make sure values exist for the keys to avoid the nasty keyerror message. + """ + types = ['par', 'char'] + for type in types: + keys = self.__styles_dict[type].keys() + for key in keys: + styles = ['next-style', 'based-on-style'] + for style in styles: + value = self.__styles_dict[type][key].get(style) + if value is not None: + temp_dict = self.__styles_dict[type].get(value) + if temp_dict: + changed_value = self.__styles_dict[type][value].get('name') + if changed_value: + self.__styles_dict[type][key][style] = \ + changed_value + else: + if value == 0 or value == '0': + pass + else: + if self.__run_level > 4: + msg = '%s %s is based on %s\n' % (type, key, value) + msg = 'There is no style with %s\n' % value + raise self.__bug_handler(msg) + del self.__styles_dict[type][key][style] + + def __print_style_table(self): + """ + Required: + nothing + Returns: + nothing + Logic: + This function prints out the style table. + I use three nested for loops. The outer loop prints out the + paragraphs styles, then the character styles. + The next loop iterates through the style numbers. + The most inside loop iterates over the pairs of attributes and + values, and prints them out. + """ + types = ['par', 'char'] + for type in types: + if type == 'par': + prefix = 'paragraph' + else: + prefix = 'character' + self.__write_obj.write( + 'mi%s' % (prefix, num) + ) + attributes = self.__styles_dict[type][num].keys() + for att in attributes: + this_value = self.__styles_dict[type][num][att] + self.__write_obj.write( + '<%s>%s' % (att, this_value) + ) + self.__write_obj.write('\n') + self.__write_obj.write( + 'mi 0: + if self.__state[-1] == 'in_row_def': + self.__state.pop() + # added [{]] at the *end* of each /cell. Get rid of extra one + self.__cell_list.pop() + widths = self.__row_dict.get('widths') + if widths: + width_list = widths.split(',') + num_cells = len(width_list) + self.__row_dict['number-of-cells'] = num_cells + + def __in_row_def_func(self, line): + """ + Requires: + line --line to parse + Returns: + nothing + Logic: + In the text that defines a row. If a control word is found, handle the + control word with another method. + Check for states that will end this state. + While in the row definition, certain tokens can end a row or end a table. + If a paragrah definition (pard-start) is found, and the you are already in + a table, start of a row. + """ + if self.__token_info == 'cw 0 and self.__state[-1] == 'in_table': + self.__start_row_func(line) + self.__start_cell_func(line) + self.__write_obj.write(line) + elif self.__token_info == 'mi 0 and self.__state[-1] != 'in_table': + self.__start_table_func(line) + self.__write_obj.write(line) + else: + self.__write_obj.write(line) + + def __handle_row_token(self, line): + """ + Requires: + line -- line to parse + Returns: + ? + Logic: + the tokens in the row definition contain the following information: + 1. row borders. + 2. cell borders for all cells in the row. + 3. cell postions for all cells in the row. + Put all information about row borders into a row dictionary. + Put all information about cell borders into into the dictionary in + the last item in the cell list. ([{border:something, width:something}, + {border:something, width:something}]) + cw attributes for key=> value + pop the self.__cell_list. + Otherwise, print out a cell tag. + """ + self.__state.append('in_cell') + # self.__cell_list = [] + if len(self.__cell_list) > 0: + self.__write_obj.write('mi%s' % (key, cell_dict[key])) + self.__write_obj.write('\n') + # self.__cell_list.pop() + self.__cell_list.pop(0) + # self.__cell_list = self.__cell_list[1:] + else: + self.__write_obj.write('mi attributes for key=> value + """ + self.__state.append('in_row') + self.__write_obj.write('mi%s' % (key, self.__row_dict[key])) + self.__write_obj.write('\n') + self.__cells_in_row = 0 + self.__rows_in_table += 1 + + def __found_cell_position(self, line): + """ + needs: + line: current line + returns: + nothing + logic: + Calculate the cell width. + If the cell is the first cell, you should add the left cell position to it. + (This value is often negative.) + Next, set the new last_cell_position to the current cell position. + """ + # cw 1: + if self.__state[-1] == 'in_cell': + self.__state.pop() + self.__write_obj.write('mi 1 and self.__state[-1] == 'in_row': + self.__state.pop() + self.__write_obj.write('mi self.__max_number_cells_in_row: + self.__max_number_cells_in_row = self.__cells_in_row + self.__list_of_cells_in_row.append(self.__cells_in_row) + + def __empty_cell(self, line): + """ + Required: + line -- line of text + Returns: + nothing + Logic: + Write an empty tag with attributes if there are attributes. + Otherwise, writen an empty tag with cell as element. + """ + if len(self.__cell_list) > 0: + self.__write_obj.write('mi%s' % (key, cell_dict[key])) + self.__write_obj.write('\n') + else: + self.__write_obj.write('mi max: + mode = item + max = num_of_values + return mode + + def make_table(self): + """ + Requires: + nothing + Returns: + A dictionary of values for the beginning of the table. + Logic: + Read one line in at a time. Determine what action to take based on + the state. + """ + self.__initiate_values() + read_obj = open_for_read(self.__file) + self.__write_obj = open_for_write(self.__write_to) + line_to_read = 1 + while line_to_read: + line_to_read = read_obj.readline() + line = line_to_read + self.__token_info = line[:16] + action = self.__state_dict.get(self.__state[-1]) + # print self.__state[-1] + if action is None: + sys.stderr.write('No matching state in module table.py\n') + sys.stderr.write(self.__state[-1] + '\n') + action(line) + read_obj.close() + self.__write_obj.close() + copy_obj = copy.Copy(bug_handler=self.__bug_handler) + if self.__copy: + copy_obj.copy_file(self.__write_to, "table.data") + copy_obj.rename(self.__write_to, self.__file) + os.remove(self.__write_to) + return self.__table_data diff --git a/ebook_converter/ebooks/rtf2xml/table_info.py b/ebook_converter/ebooks/rtf2xml/table_info.py new file mode 100644 index 0000000..cb4bc5e --- /dev/null +++ b/ebook_converter/ebooks/rtf2xml/table_info.py @@ -0,0 +1,88 @@ +from __future__ import unicode_literals, absolute_import, print_function, division +######################################################################### +# # +# # +# copyright 2002 Paul Henry Tremblay # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # +# General Public License for more details. # +# # +# # +######################################################################### +import os +from calibre.ebooks.rtf2xml import copy +from calibre.ptempfile import better_mktemp +from . import open_for_read, open_for_write + +# note to self. This is the first module in which I use tempfile. A good idea? +""" +""" + + +class TableInfo: + """ + Insert table data for tables. + Logic: + """ + + def __init__(self, + in_file, + bug_handler, + table_data, + copy=None, + run_level=1,): + """ + Required: + 'file'--file to parse + 'table_data' -- a dictionary for each table. + Optional: + 'copy'-- whether to make a copy of result for debugging + 'temp_dir' --where to output temporary results (default is + directory from which the script is run.) + Returns: + nothing + """ + self.__file = in_file + self.__bug_handler = bug_handler + self.__copy = copy + self.__table_data = table_data + self.__run_level = run_level + self.__write_to = better_mktemp() + # self.__write_to = 'table_info.data' + + def insert_info(self): + """ + """ + read_obj = open_for_read(self.__file) + self.__write_obj = open_for_write(self.__write_to) + line_to_read = 1 + while line_to_read: + line_to_read = read_obj.readline() + line = line_to_read + if line == 'mi 0: + table_dict = self.__table_data[0] + self.__write_obj.write('mi%s' % (key, table_dict[key])) + self.__write_obj.write('\n') + self.__table_data = self.__table_data[1:] + else: + # this shouldn't happen! + if self.__run_level > 3: + msg = 'Not enough data for each table\n' + raise self.__bug_handler(msg) + self.__write_obj.write('mi\n\g<2>", input_file) + input_file = self.__cs_ast.sub(r"\g<1>", input_file) + input_file = self.__ms_hex_exp.sub(r"\\mshex0\g<1> ", input_file) + input_file = self.__utf_ud.sub(r"\\{\\uc0 \g<1>\\}", input_file) + # remove \n in bin data + input_file = self.__bin_exp.sub(lambda x: + x.group().replace('\n', '') + '\n', input_file) + # split + tokens = re.split(self.__splitexp, input_file) + # remove empty tokens and \n + return list(filter(lambda x: len(x) > 0 and x != '\n', tokens)) + + def __compile_expressions(self): + SIMPLE_RPL = { + "\\\\": "\\backslash ", + "\\~": "\\~ ", + "\\;": "\\; ", + "&": "&", + "<": "<", + ">": ">", + "\\~": "\\~ ", + "\\_": "\\_ ", + "\\:": "\\: ", + "\\-": "\\- ", + # turn into a generic token to eliminate special + # cases and make processing easier + "\\{": "\\ob ", + # turn into a generic token to eliminate special + # cases and make processing easier + "\\}": "\\cb ", + # put a backslash in front of to eliminate special cases and + # make processing easier + "{": "\\{", + # put a backslash in front of to eliminate special cases and + # make processing easier + "}": "\\}", + } + self.__replace_spchar = MReplace(SIMPLE_RPL) + # add ;? in case of char following \u + self.__ms_hex_exp = re.compile(r"\\\'([0-9a-fA-F]{2})") + self.__utf_exp = re.compile(r"\\u(-?\d{3,6}) ?") + self.__bin_exp = re.compile(r"(?:\\bin(-?\d{0,10})[\n ]+)[01\n]+") + # manage upr/ud situations + self.__utf_ud = re.compile(r"\\{[\n ]?\\upr[\n ]?(?:\\{.*?\\})[\n ]?" + + r"\\{[\n ]?\\*[\n ]?\\ud[\n ]?(\\{.*?\\})[\n ]?\\}[\n ]?\\}") + # add \n in split for whole file reading + # why keep backslash whereas \is replaced before? + # remove \n from endline char + self.__splitexp = re.compile(r"(\\[{}]|\n|\\[^\s\\{}&]+(?:[ \t\r\f\v])?)") + # this is for old RTF + self.__par_exp = re.compile(r'(\\\n+|\\ )') + # handle improper cs char-style with \* before without { + self.__cs_ast = re.compile(r'\\\*([\n ]*\\cs\d+[\n \\]+)') + # handle cw using a digit as argument and without space as delimiter + self.__cwdigit_exp = re.compile(r"(\\[a-zA-Z]+[\-0-9]+)([^0-9 \\]+)") + + def tokenize(self): + """Main class for handling other methods. Reads the file \ + , uses method self.sub_reg to make basic substitutions,\ + and process tokens by itself""" + # read + with open_for_read(self.__file) as read_obj: + input_file = read_obj.read() + + # process simple replacements and split giving us a correct list + # remove '' and \n in the process + tokens = self.__sub_reg_split(input_file) + # correct unicode + tokens = map(self.__unicode_process, tokens) + # remove empty items created by removing \uc + tokens = list(filter(lambda x: len(x) > 0, tokens)) + + # write + with open_for_write(self.__write_to) as write_obj: + write_obj.write('\n'.join(tokens)) + # Move and copy + copy_obj = copy.Copy(bug_handler=self.__bug_handler) + if self.__copy: + copy_obj.copy_file(self.__write_to, "tokenize.data") + copy_obj.rename(self.__write_to, self.__file) + os.remove(self.__write_to) + + # self.__special_tokens = [ '_', '~', "'", '{', '}' ] + +# import sys +# def main(args=sys.argv): + # if len(args) < 2: + # print 'No file' + # return + # file = 'data_tokens.txt' + # if len(args) == 3: + # file = args[2] + # to = Tokenize(args[1], Exception, out_file = file) + # to.tokenize() + + +# if __name__ == '__main__': + # sys.exit(main()) + +# calibre-debug -e src/calibre/ebooks/rtf2xml/tokenize.py diff --git a/ebook_converter/ebooks/txt/__init__.py b/ebook_converter/ebooks/txt/__init__.py new file mode 100644 index 0000000..5d05174 --- /dev/null +++ b/ebook_converter/ebooks/txt/__init__.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python2 +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2008, John Schember john@nachtimwald.com' +__docformat__ = 'restructuredtext en' + +''' +Used for txt output +''' diff --git a/ebook_converter/ebooks/txt/processor.py b/ebook_converter/ebooks/txt/processor.py new file mode 100644 index 0000000..dbe6dfe --- /dev/null +++ b/ebook_converter/ebooks/txt/processor.py @@ -0,0 +1,345 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2009, John Schember ' +__docformat__ = 'restructuredtext en' + + +''' +Read content from txt file. +''' + +import os, re + +from calibre import prepare_string_for_xml, isbytestring +from calibre.ebooks.metadata.opf2 import OPFCreator + +from calibre.ebooks.conversion.preprocess import DocAnalysis +from calibre.utils.cleantext import clean_ascii_chars +from polyglot.builtins import iteritems, unicode_type, map, range, long_type + +HTML_TEMPLATE = '%s \n%s\n' + + +def clean_txt(txt): + ''' + Run transformations on the text to put it into + consistent state. + ''' + if isbytestring(txt): + txt = txt.decode('utf-8', 'replace') + # Strip whitespace from the end of the line. Also replace + # all line breaks with \n. + txt = '\n'.join([line.rstrip() for line in txt.splitlines()]) + + # Replace whitespace at the beginning of the line with   + txt = re.sub('(?m)(?<=^)([ ]{2,}|\t+)(?=.)', ' ' * 4, txt) + + # Condense redundant spaces + txt = re.sub('[ ]{2,}', ' ', txt) + + # Remove blank space from the beginning and end of the document. + txt = re.sub(r'^\s+(?=.)', '', txt) + txt = re.sub(r'(?<=.)\s+$', '', txt) + # Remove excessive line breaks. + txt = re.sub('\n{5,}', '\n\n\n\n', txt) + # remove ASCII invalid chars : 0 to 8 and 11-14 to 24 + txt = clean_ascii_chars(txt) + + return txt + + +def split_txt(txt, epub_split_size_kb=0): + ''' + Ensure there are split points for converting + to EPUB. A misdetected paragraph type can + result in the entire document being one giant + paragraph. In this case the EPUB parser will not + be able to determine where to split the file + to accommodate the EPUB file size limitation + and will fail. + ''' + # Takes care if there is no point to split + if epub_split_size_kb > 0: + if isinstance(txt, unicode_type): + txt = txt.encode('utf-8') + length_byte = len(txt) + # Calculating the average chunk value for easy splitting as EPUB (+2 as a safe margin) + chunk_size = long_type(length_byte / (int(length_byte / (epub_split_size_kb * 1024)) + 2)) + # if there are chunks with a superior size then go and break + parts = txt.split(b'\n\n') + lengths = tuple(map(len, parts)) + if lengths and max(lengths) > chunk_size: + txt = b'\n\n'.join([ + split_string_separator(line, chunk_size) for line in parts + ]) + if isbytestring(txt): + txt = txt.decode('utf-8') + + return txt + + +def convert_basic(txt, title='', epub_split_size_kb=0): + ''' + Converts plain text to html by putting all paragraphs in +

tags. It condense and retains blank lines when necessary. + + Requires paragraphs to be in single line format. + ''' + txt = clean_txt(txt) + txt = split_txt(txt, epub_split_size_kb) + + lines = [] + blank_count = 0 + # Split into paragraphs based on having a blank line between text. + for line in txt.split('\n'): + if line.strip(): + blank_count = 0 + lines.append(u'

%s

' % prepare_string_for_xml(line.replace('\n', ' '))) + else: + blank_count += 1 + if blank_count == 2: + lines.append(u'

 

') + + return HTML_TEMPLATE % (title, u'\n'.join(lines)) + + +DEFAULT_MD_EXTENSIONS = ('footnotes', 'tables', 'toc') + + +def create_markdown_object(extensions): + # Need to load markdown extensions without relying on pkg_resources + import importlib + from calibre.ebooks.markdown import Markdown + from markdown import Extension + + class NotBrainDeadMarkdown(Markdown): + def build_extension(self, ext_name, configs): + if '.' in ext_name or ':' in ext_name: + return Markdown.build_extension(self, ext_name, configs) + ext_name = 'markdown.extensions.' + ext_name + module = importlib.import_module(ext_name) + if hasattr(module, 'makeExtension'): + return module.makeExtension(**configs) + for name, x in vars(module).items(): + if type(x) is type and issubclass(x, Extension) and x is not Extension: + return x(**configs) + raise ImportError('No extension class in {}'.format(ext_name)) + + from calibre.ebooks.conversion.plugins.txt_input import MD_EXTENSIONS + extensions = [x.lower() for x in extensions] + extensions = [x for x in extensions if x in MD_EXTENSIONS] + md = NotBrainDeadMarkdown(extensions=extensions) + return md + + +def convert_markdown(txt, title='', extensions=DEFAULT_MD_EXTENSIONS): + md = create_markdown_object(extensions) + return HTML_TEMPLATE % (title, md.convert(txt)) + + +def convert_markdown_with_metadata(txt, title='', extensions=DEFAULT_MD_EXTENSIONS): + from calibre.ebooks.metadata.book.base import Metadata + from calibre.utils.date import parse_only_date + from calibre.db.write import get_series_values + if 'meta' not in extensions: + extensions.append('meta') + md = create_markdown_object(extensions) + html = md.convert(txt) + mi = Metadata(title or _('Unknown')) + m = md.Meta + for k, v in iteritems({'date':'pubdate', 'summary':'comments'}): + if v not in m and k in m: + m[v] = m.pop(k) + for k in 'title authors series tags pubdate comments publisher rating'.split(): + val = m.get(k) + if val: + mf = mi.metadata_for_field(k) + if not mf.get('is_multiple'): + val = val[0] + if k == 'series': + val, si = get_series_values(val) + mi.series_index = 1 if si is None else si + if k == 'rating': + try: + val = max(0, min(int(float(val)), 10)) + except Exception: + continue + if mf.get('datatype') == 'datetime': + try: + val = parse_only_date(val, assume_utc=False) + except Exception: + continue + setattr(mi, k, val) + return mi, HTML_TEMPLATE % (mi.title, html) + + +def convert_textile(txt, title=''): + from calibre.ebooks.textile import textile + html = textile(txt, encoding='utf-8') + return HTML_TEMPLATE % (title, html) + + +def normalize_line_endings(txt): + txt = txt.replace('\r\n', '\n') + txt = txt.replace('\r', '\n') + return txt + + +def separate_paragraphs_single_line(txt): + txt = txt.replace('\n', '\n\n') + return txt + + +def separate_paragraphs_print_formatted(txt): + txt = re.sub(u'(?miu)^(?P\t+|[ ]{2,})(?=.)', lambda mo: '\n%s' % mo.group('indent'), txt) + return txt + + +def separate_hard_scene_breaks(txt): + def sep_break(line): + if len(line.strip()) > 0: + return '\n%s\n' % line + else: + return line + txt = re.sub(r'(?miu)^[ \t-=~\/_]+$', lambda mo: sep_break(mo.group()), txt) + return txt + + +def block_to_single_line(txt): + txt = re.sub(r'(?<=.)\n(?=.)', ' ', txt) + return txt + + +def preserve_spaces(txt): + ''' + Replaces spaces multiple spaces with   entities. + ''' + txt = re.sub('(?P[ ]{2,})', lambda mo: ' ' + (' ' * (len(mo.group('space')) - 1)), txt) + txt = txt.replace('\t', '    ') + return txt + + +def remove_indents(txt): + ''' + Remove whitespace at the beginning of each line. + ''' + return '\n'.join([l.lstrip() for l in txt.splitlines()]) + + +def opf_writer(path, opf_name, manifest, spine, mi): + opf = OPFCreator(path, mi) + opf.create_manifest(manifest) + opf.create_spine(spine) + with lopen(os.path.join(path, opf_name), 'wb') as opffile: + opf.render(opffile) + + +def split_string_separator(txt, size): + ''' + Splits the text by putting \n\n at the point size. + ''' + if len(txt) > size and size > 2: + size -= 2 + txt = [] + for part in (txt[i * size: (i + 1) * size] for i in range(0, len(txt), size)): + idx = part.rfind(b'.') + if idx == -1: + part += b'\n\n' + else: + part = part[:idx + 1] + b'\n\n' + part[idx:] + txt.append(part) + txt = b''.join(txt) + return txt + + +def detect_paragraph_type(txt): + ''' + Tries to determine the paragraph type of the document. + + block: Paragraphs are separated by a blank line. + single: Each line is a paragraph. + print: Each paragraph starts with a 2+ spaces or a tab + and ends when a new paragraph is reached. + unformatted: most lines have hard line breaks, few/no blank lines or indents + + returns block, single, print, unformatted + ''' + txt = txt.replace('\r\n', '\n') + txt = txt.replace('\r', '\n') + txt_line_count = len(re.findall(r'(?mu)^\s*.+$', txt)) + + # Check for hard line breaks - true if 55% of the doc breaks in the same region + docanalysis = DocAnalysis('txt', txt) + hardbreaks = docanalysis.line_histogram(.55) + + if hardbreaks: + # Determine print percentage + tab_line_count = len(re.findall(r'(?mu)^(\t|\s{2,}).+$', txt)) + print_percent = tab_line_count / float(txt_line_count) + + # Determine block percentage + empty_line_count = len(re.findall(r'(?mu)^\s*$', txt)) + block_percent = empty_line_count / float(txt_line_count) + + # Compare the two types - the type with the larger number of instances wins + # in cases where only one or the other represents the vast majority of the document neither wins + if print_percent >= block_percent: + if .15 <= print_percent <= .75: + return 'print' + elif .15 <= block_percent <= .75: + return 'block' + + # Assume unformatted text with hardbreaks if nothing else matches + return 'unformatted' + + # return single if hardbreaks is false + return 'single' + + +def detect_formatting_type(txt): + ''' + Tries to determine the formatting of the document. + + markdown: Markdown formatting is used. + textile: Textile formatting is used. + heuristic: When none of the above formatting types are + detected heuristic is returned. + ''' + # Keep a count of the number of format specific object + # that are found in the text. + markdown_count = 0 + textile_count = 0 + + # Check for markdown + # Headings + markdown_count += len(re.findall('(?mu)^#+', txt)) + markdown_count += len(re.findall('(?mu)^=+$', txt)) + markdown_count += len(re.findall('(?mu)^-+$', txt)) + # Images + markdown_count += len(re.findall(r'(?u)!\[.*?\](\[|\()', txt)) + # Links + markdown_count += len(re.findall(r'(?u)^|[^!]\[.*?\](\[|\()', txt)) + + # Check for textile + # Headings + textile_count += len(re.findall(r'(?mu)^h[1-6]\.', txt)) + # Block quote. + textile_count += len(re.findall(r'(?mu)^bq\.', txt)) + # Images + textile_count += len(re.findall(r'(?mu)(?<=\!)\S+(?=\!)', txt)) + # Links + textile_count += len(re.findall(r'"[^"]*":\S+', txt)) + # paragraph blocks + textile_count += len(re.findall(r'(?mu)^p(<|<>|=|>)?\. ', txt)) + + # Decide if either markdown or textile is used in the text + # based on the number of unique formatting elements found. + if markdown_count > 5 or textile_count > 5: + if markdown_count > textile_count: + return 'markdown' + else: + return 'textile' + + return 'heuristic' diff --git a/ebook_converter/ebooks/unihandecode/__init__.py b/ebook_converter/ebooks/unihandecode/__init__.py new file mode 100644 index 0000000..91238ed --- /dev/null +++ b/ebook_converter/ebooks/unihandecode/__init__.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL 3' +__copyright__ = '2010, Hiroshi Miura ' +__docformat__ = 'restructuredtext en' +__all__ = ["Unihandecoder"] + +''' +Decode unicode text to an ASCII representation of the text. +Translate unicode characters to ASCII. + +Inspired from John Schember's unidecode library which was created as part +of calibre. + +Copyright(c) 2009, John Schember + +Tranliterate the string from unicode characters to ASCII in Chinese and others. + +''' +import unicodedata + + +class Unihandecoder(object): + preferred_encoding = None + decoder = None + + def __init__(self, lang="zh", encoding='utf-8'): + self.preferred_encoding = encoding + lang = lang.lower() + if lang[:2] == 'ja': + from calibre.ebooks.unihandecode.jadecoder import Jadecoder + self.decoder = Jadecoder() + elif lang[:2] == 'kr' or lang == 'korean': + from calibre.ebooks.unihandecode.krdecoder import Krdecoder + self.decoder = Krdecoder() + elif lang[:2] == 'vn' or lang == 'vietnum': + from calibre.ebooks.unihandecode.vndecoder import Vndecoder + self.decoder = Vndecoder() + else: # zh and others + from calibre.ebooks.unihandecode.unidecoder import Unidecoder + self.decoder = Unidecoder() + + def decode(self, text): + if isinstance(text, bytes): + try: + text = text.decode(self.preferred_encoding) + except Exception: + text = text.decode('utf-8', 'replace') + # at first unicode normalize it. (see Unicode standards) + ntext = unicodedata.normalize('NFKC', text) + return self.decoder.decode(ntext) diff --git a/ebook_converter/ebooks/unihandecode/jacodepoints.py b/ebook_converter/ebooks/unihandecode/jacodepoints.py new file mode 100644 index 0000000..89d83d9 --- /dev/null +++ b/ebook_converter/ebooks/unihandecode/jacodepoints.py @@ -0,0 +1,5252 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL 3' +__copyright__ = '2010 Hiroshi Miura ' +__docformat__ = 'restructuredtext en' + +''' +Unicode code point dictionary. +Based on Unicode.org Unihan database. +''' + +CODEPOINTS = { + 'x34':[ + 'Qiu ','Tian ','','','Kua ','Wu ','Yin ','','','','','','Si ','','','', + '','','','','','','Ye ','','','','','','Chou ','','','', + '','Nuo ','','','Qiu ','','','','Xu ','Xing ','','Xiong ','Liu ','Lin ','Xiang ','Yong ', + 'Xin ','Zhen ','Dai ','Wu ','Pan ','','','Ma ','Qian ','Yi ','Zhong ','N ','Cheng ','Fung ','','', + '','Zhuo ','Fang ','Ao ','Wu ','Zuo ','','Zhou ','Dong ','Su ','Yi ','Jiong ','Wang ','Lei ','Nao ','Zhu ', + 'Suk ','','','','Xu ','','','Saan ','Jie ','Die ','Nuo ','Su ','Yi ','Long ','Ying ','Beng ', + '','','','Lan ','Miao ','Yi ','Li ','Ji ','Yu ','Luo ','Chai ','Nom ','','','Hun ','Xu ', + 'Hui ','Rao ','','Zhou ','Caam ','Han ','Xi ','Tai ','Ai ','Hui ','Jun ','Ma ','Lue ','Tang ','Xiao ','Tiao ', + 'Zha ','Yu ','Ku ','Er ','Nang ','Qi ','Chi ','Mu ','Han ','Tang ','Se ','Si ','Qiong ','Lei ','Sa ','', + '','Hui ','Pu ','Ta ','Shu ','Zoeng ','Ou ','Tai ','','Mian ','Wen ','Diao ','Yu ','Mie ','Jun ','Niao ', + 'Xie ','You ','','','She ','Fung ','Lei ','Li ','Sin ','Luo ','Sek ','Ji ','','Kwaan ','','', + 'Quan ','','Cai ','Liang ','Gu ','Mao ','Gung ','Gua ','Sui ','Din ','','Mao ','Man ','Hyun ','Shi ','Li ', + '','Wang ','Kou ','Chui ','Zhen ','Ding ','','','Bing ','Huan ','Dong ','Gong ','Cang ','','Lian ','Jiong ', + 'Lu ','Xing ','','Nan ','Xie ','','Bi ','Jie ','Su ','Hung ','Geoi6','Gung ','You ','Xing ','Qi ','Ngo ', + 'Dian ','Fu ','Luo ','Qia ','Jie ','Tong ','Bak ','Yan ','Ci ','Fan ','Lang ','','Fu ','He ','Diu ','Li ', + 'Hua ','Tou ','Pian ','Dai ','Jun ','E ','Qie ','Yi ','Jue ','Rui ','Jian ','Gong ','Chi ','Chong ','Chi ','', + ], + 'x35':[ + 'Lue ','Daang ','Lin ','Jue ','Su ','Xiao ','Chan ','Put ','','Zhu ','Dan ','Jian ','Zhou ','Duo ','Xie ','Li ', + 'Cim ','Chi ','Xi ','Jian ','','Ji ','','Fei ','Chu ','Bang ','Kou ','','Ba ','Liang ','Kuai ','', + 'He ','Bit ','Jue ','Lei ','Shen ','Pi ','Yang ','Lu ','Bei ','E ','Lu ','','Coek ','Che ','Nuo ','Suan ', + 'Heng ','Yu ','','Gui ','Yi ','Xian ','Gong ','Lou ','Cam ','Le ','Shi ','Pei ','Sun ','Yao ','Jie ','Zou ', + '','Que ','Yin ','Him ','Zhi ','Jia ','Hu ','La ','Hou ','Ke ','Bou ','Jing ','Ai ','Deoi ','E ','Chu ', + 'Xie ','Chu ','Wei ','','Teng ','Huan ','Su ','You ','Caam ','Jun ','Zhao ','Xu ','Shi ','','Caat ','Kui ', + 'Soeng ','He ','Gai ','Yan ','Qiu ','Yi ','Hua ','Si ','Fan ','Zhang ','Dan ','Fang ','Song ','Ao ','Fu ','Nei ', + 'He ','You ','Hua ','Hung ','Chen ','Guo ','Ng ','Hua ','Li ','Fa ','Hao ','Pou ','Dung6','Si ','','', + 'Le ','Lin ','Yi ','Hou ','Zaau ','Xu ','Qu ','Er ','','','','','','','','Nei ', + 'Wei ','Xie ','Ti ','Hong ','Tun ','Bo ','Nie ','Yin ','San ','','','','','','Wai ','Shou ', + 'Ba ','Ye ','Ji ','Tou ','Han ','Jiong ','Dong ','Wen ','Lu ','Sou ','Guo ','Ling ','','Tian ','Lun ','', + '','','','','','ge ','Ye ','Shi ','Xue ','Fen ','Chun ','Rou ','Duo ','Ze ','E ','Xie ', + 'Zaau ','E ','Sheng ','Wen ','Man ','Hu ','Ge ','Xia ','Man ','Bi ','Ji ','Hou ','Zhi ','','Gaa ','', + '','Bai ','Ai ','Ci ','Hin ','Gou ','Dan ','Bai ','Bo ','Na ','Li ','Xiao ','Xiu ','','','', + '','','Dong ','Ti ','Cu ','Kuo ','Lao ','Zhi ','Ai ','Xi ','','Qie ','Zaa ','Hei ','','', + 'Chu ','Ji ','Huo ','Ta ','Yan ','Xu ','Put ','Sai ','','','','Go6','Ye ','Xiang ','Heoi ','Xia ', + ], + 'x36':[ + 'Zuo ','Yi ','Ci ','','','Xian ','Tai ','Rong ','Yi ','Zhi ','Yi ','Xian ','Ju ','Ji ','Han ','', + 'Pao ','Li ','','Lan ','Can ','Han ','Yan ','','','Yan ','Han ','Haam ','Chi ','Nian ','Huo ','', + 'Bi ','Xia ','Weng ','Xuan ','Waan ','You ','Qin ','Xu ','Nei ','Bi ','Hao ','Jing ','Ao ','Ao ','','', + 'Zam ','Taan ','Ju ','Zaau ','Zuo ','Bu ','Jie ','Ai ','Zang ','Ci ','Fa ','Zaan ','','','','Nie ', + 'Liu ','Mang ','Dui ','Bong ','Bi ','Bao ','','Chu ','Han ','Tian ','Chang ','','','Do ','Wai ','Fu ', + 'Duo ','Yu ','Ye ','Kui ','Han ','Kuai ','','Kuai ','Ziu ','Long ','Sing ','Bu ','Chi ','Xie ','Nie ','Lang ', + 'Yi ','Zung ','Man ','Zhang ','Xia ','Gun ','','','Ji ','Liao ','Ye ','Ji ','Yin ','','Da ','Yi ', + 'Xie ','Hao ','Yong ','Han ','Chan ','Tai ','Tang ','Zhi ','Bao ','Meng ','Gui ','Chan ','Lei ','','Xi ','', + 'Hei ','Qiao ','Rang ','Yun ','','Long ','Fu ','Zuk ','','Gu ','Hoi ','Diu ','Hua ','Guo ','','Gao ', + 'Tao ','','Shan ','Lai ','Nie ','Fu ','Gao ','Qie ','Ban ','Gaa ','','Xi ','Xu ','Kui ','Meng ','Chuo ', + 'Hiu ','Ji ','Nu ','Xiao ','Yi ','Yu ','Yi ','Yan ','','Ran ','Hao ','Sha ','Gwan ','You ','Daam ','Xin ', + 'Bi ','Zaau ','Dian ','O ','Bu ','Dung ','Si ','Er ','Si ','Mao ','Yun ','Gei ','Naau ','Qiao ','','Pao ', + '','Ping ','Nuo ','Jie ','Zi ','Er ','Duo ','','','','Duo ','','','Qie ','Leoi ','Ou ', + 'Sou ','Can ','Dou ','Ci ','Peng ','Yi ','So ','Zuo ','Po ','Qie ','Tong ','Xin ','You ','Bei ','Long ','', + '','','','','','Ta ','Lan ','Man ','Qiang ','Zhou ','Yan ','Sek ','Lu ','Sik ','Sao ','Mian ', + 'Fan ','Rui ','Fa ','Cha ','Nao ','Cing ','Chou ','Gai ','Shu ','Pian ','Aam ','Kui ','Sha ','Saan ','Xian ','Zhi ', + ], + 'x37':[ + '','','Fung ','Lian ','Xun ','Xu ','Mi ','Hui ','Mu ','Zung ','Pang ','Yi ','Gou ','Tang ','Qi ','Yun ', + 'Shu ','Fu ','Yi ','Da ','','Lian ','Cao ','Can ','Ju ','Lu ','Su ','Nen ','Ao ','An ','Qian ','', + 'Ceoi ','Sung ','','Ran ','Shen ','Mai ','Han ','Yue ','Er ','Ao ','Xian ','Ma ','','','Lan ','Hei ', + 'Yue ','Dong ','Weng ','Huai ','Meng ','Niao ','Wan ','Mi ','Nie ','Qu ','Zan ','Lian ','Zhi ','Zi ','Hai ','Xu ', + 'Hao ','Xun ','Zhi ','Fan ','Chun ','Gou ','','Chun ','Luan ','Zhu ','Shou ','Liao ','Jie ','Xie ','Ding ','Jie ', + 'Rong ','Mang ','Geoi ','Ge ','Yao ','Ning ','Yi ','Lang ','Yong ','Yin ','','Su ','Sik ','Lin ','Ya ','Mao ', + 'Ming ','Zui ','Yu ','Ye ','Gou ','Mi ','Jun ','Wen ','','Hoi ','Dian ','Long ','','Xing ','Cui ','Qiao ', + 'Mian ','Meng ','Qin ','','Wan ','De ','Ai ','','Bian ','Nou ','Lian ','Jin ','Zyu ','Chui ','Zuo ','Bo ', + 'Fui ','Yao ','Tui ','Ji ','Aam ','Guo ','Ji ','Wei ','Bui6','Zaat ','Xu ','Nian ','Yun ','','Ba ','Zhe ', + 'Ju ','Wei ','Xi ','Qi ','Yi ','Xie ','Ci ','Qiu ','Tun ','Niao ','Qi ','Ji ','Teoi ','','','Dian ', + 'Lao ','Zhan ','Zi ','Fan ','Yin ','Cen ','Ji ','Hui ','Zai ','Lan ','Nao ','Ju ','Qin ','Dai ','Shutsu ','Jie ', + 'Xu ','Cung ','Yong ','Dou ','Chi ','Tou ','Min ','Huang ','Sui ','Ke ','Zu ','Hao ','Cheng ','Xue ','Ni ','Chi ', + 'Lian ','An ','Chi ','Si ','Xiang ','Yang ','Hua ','Cuo ','Qiu ','Lao ','Fu ','Dui ','Mang ','Lang ','Tuo ','Han ', + 'Mang ','Bo ','Kwan ','Qi ','Han ','','Long ','Ban ','Tiao ','Lao ','Qi ','Zan ','Mi ','Pei ','Zhan ','Xiang ', + 'Gang ','','Qi ','','Lu ','Caam ','Yun ','E ','Quan ','Min ','Wei ','Quan ','Shu ','Min ','Daat6','', + 'Ming ','Yao ','Jue ','Li ','Kuai ','Gang ','Yuan ','Da ','Gou ','Lao ','Lou ','Qian ','Ao ','Biao ','Zung ','Mang ', + ], + 'x38':[ + 'Dao ','Caam ','Ao ','','Xi ','Fu ','Daan ','Jiu ','Run ','Tong ','Qu ','E ','Hei ','Ji ','Ji ','Hua ', + 'Jiao ','Zui ','Biao ','Meng ','Bai ','Wei ','Ji ','Ao ','Yu ','Hao ','Dui ','Wo ','Ni ','Cuan ','','Li ', + 'Lu ','Niao ','Hua ','Lai ','','Lu ','Fung ','Mi ','Yu ','Fong ','Ju ','','','Zhan ','Pang ','Yi ', + '','Ji ','Bi ','','Ren ','Fong ','Fan ','Ge ','Ku ','Jie ','Miao ','Hei ','Si ','Tong ','Zyun ','Ci ', + 'Bi ','Kai ','Li ','Fong ','Sun ','Nuo ','Fong ','Ji ','Men ','Xian ','Qia ','E ','Mao ','','Saam ','Tou ', + 'Zin ','Qiao ','Zeon ','Kwaan ','Wu ','Zing ','Chuang ','Ti ','Lian ','Bi ','Haat6','Mang ','Xue ','Feng ','Lei ','Zou ', + 'Zheng ','Chu ','Man ','Long ','','Yin ','Baan ','Zheng ','Qian ','Luan ','Nie ','Yi ','','Ji ','Ji ','Zhai ', + 'Yu ','Jiu ','Huan ','Di ','Kaap ','Ling ','Ji ','Ben ','Zha ','Ci ','Dan ','Liao ','Yi ','Zhao ','Xian ','Chi ', + 'Ci ','Chi ','Yan ','Lang ','Dou ','Long ','Chan ','','Tui ','Cha ','Ai ','Chi ','','Ying ','Cha ','Tou ', + '','Tui ','Cha ','Yao ','Zong ','Zung ','Pun ','Qiao ','Lian ','Qin ','Lu ','Yan ','Kong ','Sou ','Yi ','Chan ', + 'Jiong ','Jiang ','','Jing ','','Dong ','Go ','Juan ','Han ','Di ','Wu ','','Hong ','Tou ','Chi ','Min ', + 'Bi ','','Xun ','Lu ','Sai ','She ','Bi ','','Bi ','','Xian ','Wei ','Bie ','Er ','Juan ','', + 'Zhen ','Bei ','Yi ','Yu ','Qu ','Zan ','Mi ','Ni ','Si ','Gung ','','Daan ','Shan ','Tai ','Mu ','Jing ', + 'Bian ','Rong ','Ceng ','Can ','Ding ','','','','Keoi ','Di ','Tong ','Ta ','Xing ','Sung ','Duo ','Xi ', + 'Tong ','','Ti ','Shan ','Jian ','Zhi ','Wai ','Yin ','','','Huan ','Zhong ','Qi ','Zung ','','Xie ', + 'Xie ','Ze ','Wei ','','','Ta ','Zhan ','Ning ','','','Sam ','Yi ','Ren ','Shu ','Cha ','Zhuo ', + ], + 'x39':[ + '','Mian ','Ji ','Fang ','Pei ','Ai ','Fan ','Ao ','Qin ','Qia ','Xiao ','Fan ','Gaam ','Qiao ','Go ','Tong ', + 'Tip ','You ','Gou ','Ben ','Fu ','Chu ','Zhu ','','Chu ','Zaan ','Hang ','Nin ','Jue ','Cung ','Cha ','Kong ', + 'Lie ','Li ','Xu ','Paang ','Yu ','Hai ','Li ','Hou ','Gong ','Ke ','Yuan ','De ','Hui ','Giu ','Kuang ','Jiong ', + 'Zan ','Fu ','Qie ','Bei ','Xi ','Ci ','Pang ','Haam ','Xi ','Qiu ','Huang ','Nan ','','Chou ','San ','Jim ', + 'De ','De ','Te ','Men ','Ling ','Shou ','Dian ','Can ','Die ','Che ','Peng ','Zi ','Ju ','Ji ','Lai ','Tian ', + 'Yuan ','Zaau ','Cai ','Qi ','Yu ','Lian ','Cung ','','','','Yu ','Ji ','Wei ','Mi ','Cui ','Xie ', + 'Xu ','Xi ','Qiu ','Hui ','Ging ','Yu ','Qie ','Shun ','Chui ','Duo ','Lou ','Deon ','Pang ','Tai ','Zhou ','Yin ', + 'Sou ','Fei ','Shen ','Yuan ','Yi ','Hun ','Se ','Ye ','Min ','Fen ','He ','','Yin ','Ce ','Ni ','Ao ', + 'Feng ','Lian ','Chang ','Chan ','Ma ','Di ','Fu ','Lu ','','Yi ','Hua ','Caa ','Tui ','E ','Hua ','Sun ', + 'Ni ','Lian ','Li ','Xian ','Yan ','Long ','Men ','Jian ','Gik ','','Bian ','Yu ','Huo ','Miao ','Chou ','Hai ', + '','Le ','Jie ','Wei ','Yi ','Huan ','He ','Can ','Lan ','Yin ','Xie ','Zaat ','Luo ','Ling ','Qian ','Huo ', + 'Cim ','Wo ','Zoi ','','Ge ','Zyu ','Die ','Yong ','Ji ','Ang ','Ru ','Xi ','Shuang ','Xu ','Yi ','Hu ', + 'Ji ','Qu ','Tian ','Sau ','Qian ','Mu ','Gaan ','Mao ','Yin ','Gai ','Ba ','Xian ','Mao ','Fang ','Ya ','Gong ', + 'Song ','Wei ','Xue ','Gwaa ','Guai ','Jiu ','E ','Zi ','Cui ','Bi ','Wa ','Hin ','Lie ','Gaa ','','Kuai ', + '','Hai ','Zaan ','Zhu ','Chong ','Xian ','Xuan ','So ','Qiu ','Pei ','Gui ','Er ','Gong ','Qiong ','Bak6','Lao ', + 'Li ','Chen ','San ','Bo ','Wo ','Pou ','Hang ','Duo ','Paang ','Te ','Ta ','Zhi ','Biao ','Gu ','Fat ','Coeng ', + ], + 'x3a':[ + 'Bing ','Zhi ','Dong ','Cheng ','Zhao ','Nei ','Lin ','Po ','Ji ','Min ','Wei ','Che ','Gou ','Bong ','Ru ','Taan ', + 'Bu ','Zung ','Kui ','Lao ','Han ','Ying ','Zhi ','Jie ','Xing ','Xie ','Xun ','Shan ','Qian ','Xie ','Su ','Hai ', + 'Mi ','Hun ','Nang ','','Hui ','Na ','Song ','Ben ','Liu ','Jie ','Huang ','Lan ','','Hu ','Dou ','Huo ', + 'Ge ','Yao ','Ce ','Gui ','Jian ','Jian ','Chou ','Jin ','Ma ','Hui ','Men ','Can ','Lue ','Pi ','Yang ','Ju ', + 'Ju ','Que ','','','Shai ','Cau ','Jiu ','Hua ','Xian ','Xie ','Syun ','Su ','Fei ','Ce ','Ye ','', + '','','Qin ','Hui ','Tun ','Ling ','Qiang ','Xi ','Yi ','Nim ','Meng ','Tuan ','Lan ','Hao ','Ci ','Zhai ', + 'Piao ','Luo ','Mi ','Buk ','Fu ','Cam ','Xie ','Bo ','Hui ','Qi ','Xie ','','Hei ','Bo ','Qian ','Ban ', + 'Jiao ','Jue ','Kun ','Song ','Ju ','E ','Nie ','','Die ','Die ','Pei ','Gui ','Zi ','Qi ','Chui ','Gwaat6', + 'Yu ','Qin ','Faat ','Ke ','Fu ','Gaang ','Di ','Xian ','Gui ','He ','Qun ','Han ','Tong ','Bo ','Shan ','Bi ', + 'Lu ','Ye ','Ni ','Chuai ','San ','Diao ','Lu ','Tou ','Lian ','Ke ','San ','Zhen ','Chuai ','Lian ','Mao ','Deon ', + 'Qian ','Ke ','Shao ','Qiao ','Bi ','Zaa ','Yin ','Kaap ','Shan ','Su ','Sa ','Rui ','Zhuo ','Lu ','Ling ','Cha ', + 'Zaai ','Huan ','','','Jia ','Ban ','Hu ','Dou ','Caam ','Lou ','','Juan ','Ke ','Suo ','Ge ','Zhe ', + 'Ding ','Duan ','Zhu ','Yan ','Pang ','Cha ','','','','','Yi ','Zin ','','You ','Gun ','Yao ', + 'Yao ','Shi ','Gong ','Qi ','Gen ','Gwong ','','Hou ','Mi ','Fu ','Hu ','Guang ','Dan ','Dai ','Tou ','Yan ', + '','Dung ','Qu ','','Chang ','Ming ','Tou ','Bao ','On ','Ceon ','Zung ','Xian ','','','','Mao ', + 'Lang ','Nan ','Pei ','Chen ','Hau ','Fei ','Cou ','Gei ','Qie ','Dai ','Sik ','Kun ','Die ','Lu ','Thung ','', + ], + 'x3b':[ + '','Caap ','Yu ','Tai ','Chan ','Man ','Mian ','Huan ','Wan ','Nuan ','Huan ','Hou ','Jing ','Bo ','Xian ','Li ', + 'Jin ','','Mang ','Piao ','Hao ','Yang ','','Xian ','Su ','Wei ','Che ','Kap ','Jin ','Ceng ','He ','', + 'Shai ','Ling ','Fui ','Dui ','Zaap ','Pu ','Yue ','Bo ','','Hui ','Die ','Yan ','Ju ','Jiao ','Kuai ','Lie ', + 'Yu ','Ti ','Tim ','Wu ','Hong ','Xiao ','Hao ','','Tiu ','Zaang ','','Huang ','Fu ','','','Dun ', + '','Reng ','Jiao ','Gong ','Xin ','','','Yuan ','Jue ','Hua ','Sik ','Bang ','Mou ','Cat ','Gong ','Wei ', + '','Mei ','Si ','Bian ','Lu ','Keoi ','','','He ','She ','Lu ','Pai ','Rong ','Qiu ','Lie ','Gong ', + 'Xian ','Xi ','Hing ','','Niao ','','','','Xie ','Lei ','Fu ','Cuan ','Zhuo ','Fei ','Zuo ','Die ', + 'Ji ','He ','Ji ','','Gin ','','','','Tu ','Xian ','Yan ','Tang ','Ta ','Di ','Jue ','Ang ', + 'Han ','Yao ','Ju ','Rui ','Bang ','Zeoi ','Nie ','Tian ','Nai ','','','You ','Mian ','Zin ','Bui ','Nai ', + 'Xing ','Qi ','Zaan ','Gen ','Tong ','Er ','Jia ','Qin ','Mao ','E ','Li ','Chi ','Zong ','He ','Jie ','Ji ', + '','Guan ','Hou ','Gai ','Cung ','Fen ','Se ','Waat ','Ji ','Sik ','Qiong ','He ','Zung ','Xian ','Jie ','Hua ', + 'Bi ','Sing ','Caai ','Zhen ','Sau ','Zin ','Shi ','Gai ','Song ','Zhi ','Ben ','','','','Lang ','Bi ', + 'Xian ','Bang ','Dai ','Cat ','Zi ','Pi ','Chan ','Bi ','Su ','Huo ','Hen ','Ying ','Chuan ','Jiang ','Nen ','Gu ', + 'Fang ','','','Ta ','Cui ','Sai ','De ','Ran ','Kuan ','Che ','Da ','Hu ','Cui ','Lu ','Juan ','Lu ', + 'Qian ','Pao ','Zhen ','Fan ','Li ','Cao ','Qi ','','','Ti ','Ling ','Qu ','Lian ','Lu ','Shu ','Gong ', + 'Zhe ','Biao ','Jin ','Qing ','','','Zong ','Pu ','Jin ','Biao ','Jian ','Gun ','','Ban ','Zou ','Lie ', + ], + 'x3c':[ + 'Li ','Luo ','Shen ','Mian ','Jian ','Di ','Bei ','Cim ','Lian ','Zeon ','Xun ','Pin ','Que ','Long ','Zui ','Gou ', + 'Jue ','San ','She ','','Xie ','Hei ','Lan ','Cu ','Yi ','Nuo ','Li ','Yue ','','Yi ','Ci ','Ji ', + 'Kang ','Xie ','Hang ','Zi ','Ke ','Hui ','Qu ','Hai6','Hei ','Hoi ','Wa ','Caam ','Xun ','Haap6','Shen ','Kou ', + 'Qie ','Sha ','Xu ','Ya ','Po ','Zu ','You ','Zi ','Lian ','Jin ','Xia ','Yi ','Qie ','Mi ','Jiao ','Hei ', + 'Chi ','Shi ','Fong ','Yin ','Mo ','Yi ','Hei ','Se ','Jin ','Ye ','Zaau ','Que ','Che ','Luan ','Kwaan ','Zheng ', + '','','Ho ','','Se ','Gwai ','Cui ','Zaau ','An ','Xiu ','Can ','Chuan ','Zha ','','Ji ','Bo ', + 'Fu ','Sing ','Lang ','Tui ','Sek6','Ling ','E ','Wo ','Lian ','Du ','Men ','Lan ','Wei ','Duan ','Kuai ','Ai ', + 'Zai ','Hui ','Yi ','Mo ','Zi ','Ben ','Beng ','','Bi ','Li ','Lu ','Luo ','Hoi ','Dan ','Goi ','Que ', + 'Chen ','Hung ','Cheng ','Jiu ','Kou ','Ji ','Ling ','Ci ','Shao ','Kai ','Rui ','Chuo ','Neng ','Zi ','Lou ','Bao ', + '','','Bao ','Rong ','Saan ','Lei ','Siu ','Fu ','Qu ','Saau ','Saa ','Zhi ','Tan ','Rong ','Zu ','Ying ', + 'Mao ','Nai ','Bian ','Saau ','Seoi ','Tang ','Han ','Zao ','Rong ','','Dang ','Pu ','Ziu ','Tan ','','Ran ', + 'Ning ','Lie ','Die ','Die ','Zhong ','Siu ','Lu ','Dan ','Kap ','Gui ','Ji ','Ni ','Yi ','Nian ','Yu ','Wang ', + 'Guo ','Ze ','Yan ','Cui ','Xian ','Jiao ','Shu ','Fu ','Pei ','Ngoet ','Zaau ','Zaau ','At ','Bu ','Bian ','Chi ', + 'Sa ','Yi ','Bian ','','Dui ','Lan ','Zi ','Chai ','Cung ','Xuan ','Yu ','Yu ','Zaau ','Hong ','Cung ','', + 'Ta ','Gwo ','','','Suk6','Ju ','Xie ','Xi ','Jian ','Tan ','Pan ','Ta ','Xuan ','Xian ','Niao ','Tan ', + 'Gaau ','','','','Mi ','Ji ','Gou ','Wen ','Faa ','Wang ','You ','Ze ','Bi ','Mi ','Goeng ','Xie ', + ], + 'x3d':[ + 'Fan ','Yi ','Dam ','Lei ','Ying ','Siu ','Jin ','She ','Yin ','Ji ','Zyun ','Su ','','','','Wang ', + 'Mian ','Su ','Yi ','Zai ','Se ','Ji ','Luo ','Zaau ','Mao ','Zha ','Sui ','Zhi ','Bian ','Li ','Caai ','', + '','','','','','Qiao ','Guan ','','Zhen ','Zung ','Nie ','Jun ','Xie ','Yao ','Xie ','Zi ', + 'Neng ','Sam ','Si ','Long ','Chen ','Mi ','Que ','Dam ','Na ','','','','Su ','Xie ','Bo ','Ding ', + 'Cuan ','Fong ','Chuang ','Che ','Han ','Dan ','Hao ','','','','Shen ','Mi ','Chan ','Men ','Han ','Cui ', + 'Jue ','He ','Fei ','Shi ','Che ','Shen ','Nu ','Fu ','Man ','Cing ','','','','Yi ','Chou ','Mei ', + 'Faat ','Bao ','Lei ','Ke ','Dian ','Bi ','Sui ','Ge ','Bi ','Yi ','Xian ','Ni ','Ying ','Zhu ','Chun ','Feng ', + 'Xu ','Piao ','Wu ','Liao ','Cang ','Zou ','Ceoi ','Bian ','Yao ','Huan ','Pai ','Sou ','','Dui ','Jing ','Xi ', + 'Bak6','Guo ','','','Yan ','Xue ','Chu ','Heng ','Ying ','','','','Lian ','Xian ','Huan ','Zaan ', + '','Lian ','Shan ','Cang ','Bei ','Jian ','Shu ','Fan ','Dian ','','Ba ','Yu ','Zyun ','','Nang ','Lei ', + 'Yi ','Dai ','','Chan ','Chao ','Gon ','Jin ','Nen ','Pei ','','','Liao ','Mei ','Jiu ','Siu ','Liu ', + 'Han ','','Yong ','Jin ','Chi ','Ren ','Nong ','','','Hong ','Tian ','Bung ','Oi ','Gwaa ','Biu ','Bo ', + 'Qiong ','','Shu ','Cui ','Hui ','Chao ','Dou ','Guai ','E ','Wei ','Fen ','Tan ','','Lun ','He ','Yong ', + 'Hui ','Nim6','Yu ','Zong ','Yan ','Qiu ','Zhao ','Jiong ','Tai ','Zin ','','Bou ','','Dut ','','Tui ', + 'Lin ','Jiong ','Zha ','Sing ','He ','Zing ','Xu ','','','Hei ','Cui ','Qing ','Mo ','Fung ','Zou ','Beng ', + 'Li ','','','Yan ','Ge ','Mo ','Bei ','Juan ','Die ','Shao ','','Wu ','Yan ','','Jue ','Hin ', + ], + 'x3e':[ + 'Tai ','Han ','','Dian ','Ji ','Jie ','','','Ziu ','Xie ','La ','Fan ','Huo ','Xi ','Nie ','Mi ', + 'Ran ','Cuan ','Yin ','Mi ','','Jue ','Keoi ','Tong ','Wan ','Ze ','Li ','Shao ','Kong ','Kan ','Ban ','Taai ', + 'Tiao ','Syu ','Bei ','Ye ','Pian ','Chan ','Hu ','Ken ','Gaau ','An ','Chun ','Qian ','Bei ','Baa ','Fen ','Fo ', + 'Tuo ','Tuo ','Zuo ','Ling ','','Gui ','Zin ','Shi ','Hou ','Lie ','Saa ','Si ','Fung ','Bei ','Ren ','Du ', + 'Bo ','Liang ','Ci ','Bi ','Ji ','Zong ','Fai ','He ','Li ','Yuan ','Yue ','Saau ','Chan ','Di ','Lei ','Jin ', + 'Chong ','Si ','Pu ','Yi ','Goeng ','Fun ','Huan ','Tao ','Ru ','Ying ','Ying ','Rao ','Yin ','Shi ','Yin ','Jue ', + 'Tun ','Xuan ','Gaa ','Zung ','Qie ','Zhu ','Ciu ','Zoeng ','You ','','Saan ','Xi ','Shi ','Yi ','Mo ','Zaau ', + '','Hu ','Xiao ','Wu ','Gang ','Jing ','Ting ','Shi ','Ni ','Gang ','Ta ','Waai ','Chu ','Chan ','Piao ','Diao ', + 'Nao ','Nao ','Gan ','Gou ','Yu ','Hou ','','Si ','Ci ','Hu ','Yang ','Zung ','Xian ','Ban ','Rong ','Lou ', + 'Zhao ','Can ','Liao ','Piao ','Hai ','Fan ','Han ','Dan ','Zhan ','','Ta ','Zhu ','Ban ','Jian ','Yu ','Zhuo ', + 'You ','Li ','Kut ','Hei ','Cim ','Chan ','Lian ','Hei ','Si ','Jiu ','Pu ','Qiu ','Gong ','Zi ','Yu ','', + 'Si ','Reng ','Niu ','Mei ','Baat ','Jiu ','','Xu ','Ping ','Bian ','Mao ','','','','','Yi ', + 'You ','Gwai ','Ping ','Kuk ','Bao ','Hui ','','','','Bu ','Mang ','La ','Tu ','Wu ','Li ','Ling ', + '','Ji ','Jun ','Lit6','Duo ','Jue ','Dai ','Bei ','','','','','','La ','Bian ','Sui ', + 'Tu ','Die ','','','','','','Duo ','','','Sui ','Bi ','Tu ','Se ','Can ','Tu ', + 'Mian ','Zeon ','Lu ','','','Zhan ','Bi ','Ji ','Cen ','Hyun ','Li ','','','Sui ','Zung ','Shu ', + ], + 'x3f':[ + '','','E ','','Gei ','','','Qiong ','Luo ','Yin ','Tun ','Gu ','Yu ','Lei ','Bei ','Nei ', + 'Pian ','Lian ','Qiu ','Lian ','Waan ','Dong ','Li ','Ding ','Wa ','Zhou ','Gong ','Xing ','Ang ','Fan ','Peng ','Bai ', + 'Tuo ','Syu ','E ','Bai ','Qi ','Chu ','Gong ','Tong ','Han ','Cheng ','Jia ','Huan ','Xing ','Dian ','Mai ','Dong ', + 'E ','Ruan ','Lie ','Sheng ','Ou ','Di ','Yu ','Chuan ','Rong ','Hong ','Tang ','Cong ','Piao ','Shuang ','Lu ','Tong ', + 'Zheng ','Li ','Sa ','Ban ','Si ','Dang ','Dong ','Guai ','Yi ','Han ','Xie ','Luo ','Liu ','Ham ','Dan ','', + 'Cim ','Tan ','Saang ','','','You ','Nan ','','Gang ','Jun ','Chi ','Kou ','Wan ','Li ','Liu ','Lie ', + 'Xia ','Baai ','An ','Yu ','Ju ','Rou ','Xun ','Zi ','Cuo ','Can ','Zeng ','Yong ','Fu ','Ruan ','Sing ','Xi ', + 'Shu ','Jiao ','Jiao ','Han ','Zhang ','Zong ','','Shui ','Chen ','Fan ','Ji ','Zi ','','Gu ','Wu ','Wo ', + 'Qie ','Shu ','Hoi ','Tuo ','Du ','Si ','Ran ','Mu ','Fu ','Ling ','Ji ','Xiu ','Xuan ','Nai ','At ','Jie ', + 'Li ','Da ','Ji ','Zyun ','Lu ','Shen ','Li ','Lang ','Geng ','Yin ','Se ','Qin ','Qie ','Che ','You ','Bu ', + 'Huang ','Que ','Lai ','Zaam ','Hong ','Xu ','Bang ','Ke ','Qi ','Gwaai ','Sheng ','Pin ','Gaai ','Zhou ','Huang ','Tui ', + 'Hu ','Bei ','','','Zaa ','Ji ','Gu ','Sai ','Gao ','Chai ','Ma ','Zhu ','Tui ','Tui ','Lian ','Lang ', + 'Baan ','','Zing ','Dai ','Ai ','Xian ','Gwo ','Xi ','Zung ','Tui ','Can ','Sao ','Cim ','Jie ','Fen ','Qun ', + '','Yao ','Dao ','Jia ','Lei ','Yan ','Lu ','Tui ','Ying ','Pi ','Luo ','Li ','Bie ','Hoeng ','Mao ','Bai ', + 'huang ','Dau ','Yao ','He ','Chun ','Hu ','Ning ','Chou ','Li ','Tang ','Huan ','Bi ','Baa ','Che ','Yang ','Da ', + 'Ao ','Xue ','Zi ','','Daap ','Ran ','Bong ','Zao ','Wan ','Ta ','Bao ','Gon ','Yan ','Gaai ','Zhu ','Ya ', + ], + 'x40':[ + 'Fan ','You ','On ','Tui ','Meng ','She ','Jin ','Gu ','Qi ','Qiao ','Jiao ','Yan ','','Kan ','Mian ','Xian ', + 'San ','Na ','Cin ','Huan ','Niu ','Cheng ','Tin ','Jue ','Xi ','Qi ','Ang ','Mei ','Gu ','','Tou ','Fan ', + 'Qu ','Chan ','Shun ','Bi ','Mao ','Shuo ','Gu ','Hong ','Huan ','Luo ','Hang ','Jia ','Quan ','Goi ','Mang ','Bu ', + 'Gu ','Fung ','Mu ','Ai ','Ying ','Shun ','Lang ','Jie ','Di ','Jie ','Cau ','Pin ','Ren ','Yan ','Du ','Di ', + '','Lang ','Xian ','Biu ','Xing ','Bei ','An ','Mi ','Qi ','Qi ','Wo ','She ','Yu ','Jia ','Cheng ','Yao ', + 'Ying ','Yang ','Ji ','Jie ','Han ','Min ','Lou ','Kai ','Yao ','Yan ','Sun ','Gui ','Huang ','Ying ','Sheng ','Cha ', + 'Lian ','','Xuan ','Chuan ','Che ','Ni ','Qu ','Miao ','Huo ','Yu ','Nan ','Hu ','Ceng ','Biu ','Qian ','She ', + 'Jiang ','Ao ','Mai ','Mang ','Zhan ','Bian ','Jiao ','Jue ','Nong ','Bi ','Shi ','Li ','Mo ','Lie ','Mie ','Mo ', + 'Xi ','Chan ','Qu ','Jiao ','Huo ','Zin ','Xu ','Nang ','Tong ','Hou ','Yu ','','Cung ','Bo ','Zuan ','Diu ', + 'Chuo ','Ci ','Jie ','Kwai ','Xing ','Hui ','Shi ','Gwaat6','Caam ','','Yao ','Yu ','Bang ','Jie ','Zhe ','Gaa ', + 'She ','Di ','Dong ','Ci ','Fu ','Min ','Zhen ','Zhen ','','Yan ','Diao ','Hong ','Gong ','Diu6','Lue ','Guai ', + 'La ','Cui ','Fa ','Cuo ','Yan ','Gung ','Jie ','Gwaai ','Guo ','Suo ','Wan ','Zheng ','Nie ','Diao ','Lai ','Ta ', + 'Cui ','Aa ','Gun ','','','Dai ','','Mian ','Gaai ','Min ','Ju ','Yu ','Zan ','Zhao ','Ze ','Saang ', + '','Pan ','He ','Gou ','Hong ','Lao ','Wu ','Chuo ','Hang ','Lu ','Cu ','Lian ','Zi ','Qiao ','Shu ','', + 'xuan ','Cen ','Zaam ','Hui ','Su ','Chuang ','Deon ','Long ','','Nao ','Tan ','Dan ','Wei ','Gan ','Da ','Li ', + 'Caat ','Xian ','Pan ','La ','Zyu ','Niao ','Huai ','Ying ','Xian ','Lan ','Mo ','Ba ','','Fu ','Bi ','Fu ', + ], + 'x41':[ + 'Huo ','Yi ','Liu ','Zoeng ','Zaan ','Juan ','Huo ','Cheng ','Dou ','E ','','Yan ','Zhui ','Du ','Qi ','Yu ', + 'Quan ','Huo ','Nie ','Heng ','Ju ','She ','','','Peng ','Ming ','Cao ','Lou ','Li ','Chun ','','Cui ', + 'Shan ','Daam ','Qi ','','Lai ','Ling ','Liao ','Reng ','Yu ','Nao ','Chuo ','Qi ','Yi ','Nian ','Fu ','Jian ', + 'Ya ','Fong ','Chui ','Cin ','','','Bi ','Dan ','Po ','Nian ','Zhi ','Chao ','Tian ','Tian ','Rou ','Yi ', + 'Lie ','An ','He ','Qiong ','Li ','Gwai ','Zi ','Su ','Yuan ','Ya ','Du ','Wan ','Gyun ','Dong ','You ','Hui ', + 'Jian ','Rui ','Mang ','Ju ','Zi ','Geoi ','An ','Sui ','Lai ','Hun ','Qiang ','Coeng ','Duo ','Hung ','Na ','Can ', + 'Ti ','Xu ','Jiu ','Huang ','Qi ','Jie ','Mao ','Yan ','Heoi ','Zhi ','Tui ','','Ai ','Pang ','Cang ','Tang ', + 'En ','Hun ','Qi ','Chu ','Suo ','Zhuo ','Nou ','Tu ','Zu ','Lou ','Miao ','Li ','Man ','Gu ','Cen ','Hua ', + 'Mei ','Gou ','Lian ','Dao ','Shan ','Ci ','','','Zhi ','Ba ','Cui ','Qiu ','','Long ','Cim ','Fei ', + 'Guo ','Cheng ','Jiu ','E ','Cung ','Jue ','Hong ','Jiao ','Cuan ','Yao ','Tong ','Cha ','You ','Shu ','Yao ','Ge ', + 'Huan ','Lang ','Jue ','Chen ','Cyun ','Cyun ','Shen ','Fo ','Ming ','Ming ','Hung ','Chuang ','Yun ','Han6','Jin ','Chuo ', + 'Zyu ','Tan ','Hong ','Qiong ','','Cheng ','Zaau ','Yu ','Cheng ','Tong ','Pun ','Qiao ','Fo ','Ju ','Lan ','Yi ', + 'Rong ','Si ','Hin ','Si ','Ngat ','Fa ','','Meng ','Gui ','','','Hai ','Qiao ','Chuo ','Que ','Dui ', + 'Li ','Ba ','Jie ','Seoi ','Luo ','Deoi ','Yun ','Zung ','Hu ','Yin ','Pok ','Zhi ','Lian ','Zim ','Gan ','Jian ', + 'Zhou ','Zhu ','Ku ','Na ','Dui ','Ze ','Yang ','Zhu ','Gong ','Yi ','Ci ','Gei ','Chuang ','Lao ','Ren ','Rong ', + 'Zing ','Na ','Ce ','Zin ','','Yi ','Jue ','Bi ','Cheng ','Jun ','Chou ','Hui ','Chi ','Zhi ','Yan ','', + ], + 'x42':[ + 'Saan ','Lun ','Bing ','Zhao ','Han ','Yu ','Dai ','Zhao ','Fei ','Sha ','Ling ','Ta ','Zeoi ','Mang ','Ye ','Bao ', + 'Kui ','Gua ','Nan ','Ge ','Gaa ','Chi ','Fo ','Suo ','Ci ','Zhou ','Tai ','Kuai ','Qin ','Seoi ','Du ','Ce ', + 'Huan ','Gung ','Sai ','Zheng ','Qian ','Gan ','Zung ','Wei ','','','Xi ','Na ','Pu ','Huai ','Ju ','Zaan ', + 'Sau ','Tou ','Pan ','Ta ','Qian ','Zung ','Rong ','Luo ','Hu ','Sou ','Zung ','Pu ','Mie ','Gan ','Shuo ','Mai ', + 'Shu ','Ling ','Lei ','Jiang ','Leng ','Zhi ','Diao ','','San ','Hu ','Fan ','Mei ','Sui ','Jian ','Tang ','Xie ', + 'Fu ','Mo ','Fan ','Lei ','Can ','Ceng ','Ling ','Zaap ','Cong ','Yun ','Meng ','Yu ','Zhi ','Qi ','Dan ','Huo ', + 'Wei ','Tan ','Se ','Xie ','Sou ','Song ','Cin ','Liu ','Yi ','Aau ','Lei ','Li ','Fei ','Lie ','Lin ','Xian ', + 'Yao ','Aau ','Bie ','Xian ','Rang ','Zhuan ','Soeng ','Dan ','Bian ','Ling ','Hong ','Qi ','Liao ','Ban ','Mi ','Hu ', + 'Hu ','Caap ','Ce ','Pei ','Qiong ','Ming ','Jiu ','Bu ','Mei ','San ','Mei ','Zong ','','Li ','Quan ','Sam ', + 'En ','Xiang ','Zing ','Shi ','Zing ','Gin ','Lan ','Huang ','Jiu ','Yan ','Deoi ','Sa ','Tuan ','Xie ','Zhe ','Men ', + 'Xi ','Man ','Zoeng ','Huang ','Tan ','Xiao ','Ya ','Bi ','Luo ','Fan ','Li ','Cui ','Cha ','Chou ','Di ','Kuang ', + 'Chu ','Cim ','Chan ','Mi ','Qian ','Qiu ','Zhen ','Zi ','Heoi ','Cim ','Gu ','Yan ','Chi ','Guai ','Mu ','Bo ', + 'Kua ','Geng ','Yao ','Mao ','Wang ','','','','Ru ','Jue ','Zing ','Min ','Jiang ','O ','Zhan ','Zuo ', + 'Yue ','Bing ','Nou6','Zhou ','Bi ','Ren ','Yu ','Gin ','Chuo ','Er ','Yi ','Mi ','Qing ','Zing ','Wang ','Ji ', + 'Bu ','Syu ','Bie ','Fan ','Yao ','Li ','Fan ','Qu ','Fu ','Er ','O ','Zang ','Zim ','Huo ','Jin ','Qi ', + 'Ju ','Lai ','Che ','Bei ','Niu ','Yi ','Xu ','Liu ','Xun ','Fu ','Cau ','Nin ','Ting ','Beng ','Zha ','Wui ', + ], + 'x43':[ + 'Fo ','Zaau ','Ou ','Shuo ','Geng ','Tang ','Gui ','Hui ','Ta ','Gong ','Yao ','Daap ','Qi ','Han ','Lue ','Mi ', + 'Mi ','Gin ','Lu ','Fan ','Ou ','Mi ','Jie ','Fu ','Mi ','Huang ','Su ','Yao ','Nie ','Jin ','Lian ','Bi ', + 'Qing ','Ti ','Ling ','Zuan ','Zhi ','Yin ','Dao ','Chou ','Cai ','Mi ','Yan ','Lan ','Chong ','Ziu ','Soeng ','Guan ', + 'She ','Luo ','Fan ','Si ','Luo ','Zhu ','Zi ','Chou ','Juan ','Jiong ','Er ','Yi ','Rui ','Cai ','Ren ','Fu ', + 'Lan ','Sui ','Yu ','Yao ','Dian ','Ling ','Zhu ','Ta ','Ping ','Qian ','Jue ','Chui ','Bu ','Gu ','Cun ','', + 'Han ','Han ','Mou ','Hu ','Hong ','Di ','Fu ','Xuan ','Mi ','Mei ','Lang ','Gu ','Zhao ','Ta ','Yu ','Zong ', + 'Li ','Liao ','Wu ','Lei ','Ji ','Lei ','Li ','Zong ','Bo ','Ang ','Kui ','Tuo ','Ping ','Cau ','Zhao ','Gui ', + 'Zaan ','Xu ','Nai ','Chuo ','Duo ','Kaap ','Dong ','Gui ','Bo ','Zin ','Huan ','Xuan ','Can ','Li ','Tui ','Huang ', + 'Xue ','Hu ','Bao ','Ran ','Tiao ','Fu ','Liao ','Zaau ','Yi ','Shu ','Po ','He ','Cu ','Fu ','Na ','An ', + 'Chao ','Lu ','Zhan ','Ta ','Fu ','Gwaang ','Zang ','Qiao ','Su ','Baan ','Guan ','','Fan ','Chu ','','Er ', + 'Er ','Nuan ','Qi ','Si ','Chu ','','Yan ','Bang ','An ','Zi ','Ne ','Chuang ','Ba ','Ciu ','Ti ','Han ', + 'Zuo ','Ba ','Zhe ','Wa ','Sheng ','Bi ','Er ','Zhu ','Wu ','Wen ','Zhi ','Zhou ','Lu ','Wen ','Gun ','Qiu ', + 'La ','Zai ','Sou ','Mian ','Zhi ','Qi ','Cao ','Piao ','Lian ','Saap ','Long ','Su ','Qi ','Yuan ','Feng ','Heoi ', + 'Jue ','Di ','Pian ','Guan ','Niu ','Ren ','Zhen ','Gai ','Pi ','Tan ','Chao ','Chun ','Ho ','Chun ','Mo ','Bie ', + 'Qi ','Shi ','Bi ','Jue ','Si ','Taam ','Hua ','Na ','Hui ','Kaap ','Er ','Caau ','Mou ','Zyu ','Xi ','Zhi ', + 'Ren ','Ju ','Die ','Zhe ','Shao ','Meng ','Bi ','Han ','Yu ','Xian ','Pong ','Neng ','Can ','Bu ','Pong ','Qi ', + ], + 'x44':[ + 'Ji ','Niao ','Lu ','Jiong ','Han ','Yi ','Cai ','Chun ','Zhi ','Zi ','Da ','Cung ','Tian ','Zhou ','Daai ','Chun ', + 'Cau ','Zhe ','Zaa ','Rou ','Bin ','Ji ','Yi ','Du ','Jue ','Ge ','Ji ','Dap ','Can ','Suo ','Ruo ','Xiang ', + 'Huang ','Qi ','Zhu ','Cuo ','Chi ','Weng ','Haap6','Kao ','Gu ','Kai ','Fan ','Sung ','Cao ','Zhi ','Chan ','Lei ', + 'Gaau ','Zak6','Zhe ','Yu ','Gui ','Huang ','Jin ','Daan ','Guo ','Sao ','Tan ','','Xi ','Man ','Duo ','Ao ', + 'Pi ','Wu ','Ai ','Meng ','Pi ','Meng ','Yang ','Zhi ','Bo ','Ying ','Wei ','Nao ','Lan ','Yan ','Chan ','Quan ', + 'Zhen ','Pu ','','Tai ','Fei ','Shu ','','Dang ','Cha ','Ran ','Tian ','Chi ','Ta ','Jia ','Shun ','Huang ', + 'Liao ','Caa ','Dou ','','Jin ','E ','Keoi ','Fu ','Duo ','','E ','','Yao ','Di ','','Di ', + 'Bu ','Man ','Che ','Lun ','Qi ','Mu ','Can ','','Zung ','Sau ','Fan ','You ','Saau ','Da ','','Su ', + 'Fu ','Ji ','Jiang ','Cao ','Bo ','Teng ','Che ','Fu ','Bu ','Wu ','Haai ','Yang ','Ming ','Pang ','Mang ','Zang ', + 'Meng ','Cao ','Tiao ','Kai ','Bai ','Xiao ','Xin ','Qi ','Seoi ','','Shao ','Heng ','Niu ','Xiao ','Chen ','Daan ', + 'Fan ','Yin ','Ang ','Ran ','Ri ','Fa ','Fan ','Qu ','Shi ','He ','Bian ','Dai ','Mo ','Deng ','','', + 'Hong ','Zing ','Cha ','Duo ','You ','Hao ','Tin ','Kut ','Xian ','Lei ','Jin ','Qi ','','Mei ','Zi ','', + '','','Yan ','Yi ','Yin ','Qi ','Zhe ','Xi ','Yi ','Ye ','E ','','Zhi ','Han ','Chuo ','', + 'Chun ','Bing ','Kuai ','Chou ','','Tuo ','Qiong ','Cung ','Jiu ','Gwai ','Cu ','Fu ','','Meng ','Li ','Lie ', + 'Ta ','Zi ','Gu ','Liang ','Fat ','La ','Dian ','Ci ','Aang ','','','Ji ','','Cha ','Mao ','Du ', + 'Zaan ','Chai ','Rui ','Hen ','Ruan ','','Lai ','Xing ','Gan ','Yi ','Mei ','','He ','Ji ','So ','Han ', + ], + 'x45':[ + 'Seoi ','Li ','Zi ','Zu ','Yao ','Geoi ','Li ','Qi ','Gan ','Li ','','','','','Su ','Chou ', + '','Xie ','Bei ','Xu ','Jing ','Pu ','Ling ','Xiang ','Zuo ','Diao ','Chun ','Qing ','Nan ','','Lu ','Chi ', + 'Shao ','Yu ','Hua ','Li ','','Siu ','','Li ','','','Dui ','','Yi ','Ning ','Si ','Hu ', + 'Fu ','Zaap ','Cheng ','Nan ','Ce ','Gaan ','Ti ','Qin ','Biao ','Sui ','Wei ','Deon ','Se ','Ai ','E ','Jie ', + 'Kuan ','Fei ','','Yin ','Zing ','Sao ','Dou ','Hui ','Xie ','Ze ','Tan ','Chang ','Zhi ','Yi ','Fu ','E ', + '','Jun ','Gaa ','Cha ','Xian ','Man ','Syun ','Bi ','Ling ','Jie ','Kui ','Jia ','','Cing ','Lang ','Guk ', + 'Fei ','Lu ','Zha ','He ','','Ni ','Ying ','Xiao ','Teng ','Lao ','Ze ','Kui ','Goeng ','Qian ','Ju ','Piao ', + 'Ban ','Dou ','Lin ','Mi ','Zhuo ','Xie ','Hu ','Mi ','Gaai ','Za ','Cong ','Ge ','Nan ','Zhu ','Yan ','Han ', + 'Ceoi ','Yi ','Luan ','Yue ','Ran ','Ling ','Niang ','Yu ','Nue ','Heoi ','Yi ','Nue ','Qin ','Qian ','Xia ','Chu ', + 'Jin ','Mi ','','Na ','Han ','Zu ','Xia ','Yan ','Tu ','','Wu ','Suo ','Yin ','Chong ','Zhou ','Mang ', + 'Yuan ','Nu ','Miao ','Sao ','Wan ','Li ','','Na ','Shi ','Bi ','Ci ','Bang ','','Juan ','Xiang ','Gui ', + 'Pai ','Hong ','Xun ','Zha ','Yao ','Kwan ','','Hei ','E ','Yang ','Tiao ','You ','Jue ','Li ','','Li ', + '','Ji ','Hu ','Zhan ','Fu ','Chang ','Guan ','Ju ','Meng ','Coeng ','Cheng ','Mou ','Sing ','Li ','Zaan ','', + 'Si ','Yi ','Bing ','Cung ','Hou ','Wan ','Chi ','','Ge ','Han ','Bo ','Saau ','Liu ','Can ','Can ','Yi ', + 'Xuan ','Yan ','Suo ','Gao ','Yong ','Zung ','Fung ','Hong ','Yu ','Cik ','Zhe ','Ma ','Fung ','','Shuang ','Jin ', + 'Guan ','Pu ','Lin ','','Ting ','Goeng ','La ','Yi ','Zung ','Ci ','Yan ','Jie ','Faan ','Wei ','Xian ','Ning ', + ], + 'x46':[ + 'Fu ','Ge ','','Mo ','Fu ','Nai ','Xian ','Wen ','Li ','Can ','Mie ','','Ni ','Chai ','Wan ','Xu ', + 'Nu ','Mai ','Co ','Kan ','Ho ','Hang ','','Faai ','Yu ','Wei ','Zhu ','Gei ','Gan ','Yi ','','', + 'Fu ','Bi ','Zhu ','Zi ','Shu ','Xia ','Ni ','','Jiao ','Xuan ','Cung ','Nou ','Rong ','Die ','Sa ','Sau ', + '','Yu ','','Kaam ','Zung ','Lu ','Han ','','Yi ','Zui ','Zhan ','Su ','Wan ','Ni ','Guan ','Jue ', + 'Beng ','Can ','Zung ','Duo ','Qi ','Yao ','Gui ','Nuan ','Hou ','Xun ','Xie ','','Hui ','','Xie ','Bo ', + 'Ke ','Ceoi ','Xu ','Bai ','Aau ','Chu ','Bang ','Ti ','Chu ','Chi ','Niao ','Guan ','Feng ','Xie ','Dang ','Duo ', + 'Jue ','Hui ','Zeng ','Sa ','Duo ','Ling ','Meng ','Fan ','Guo ','Meng ','Long ','','Ying ','Hin ','Guan ','Cu ', + 'Li ','Du ','Ceng ','E ','Sin ','Saai ','','De ','De ','Jiang ','Lian ','','Shao ','Xi ','Si ','Wei ', + '','','He ','You ','Lu ','Lai ','Ou ','Sheng ','Juan ','Qi ','','Yun ','','Qi ','Zong ','Leng ', + 'Ji ','Mai ','Chuang ','Nian ','Baan ','Li ','Ling ','Gong ','Chen ','','Xian ','Hu ','Bei ','Zu ','Dai ','Dai ', + 'Hun ','Soi ','Che ','Ti ','','Nuo ','Zhi ','Liu ','Fei ','Jiao ','Gwaan ','Ao ','Lin ','','Reng ','Tao ', + 'Pi ','Xin ','Shan ','Xie ','Wa ','Tao ','Tin ','Xi ','Xie ','Pi ','Yao ','Yao ','Nu ','Hao ','Nin ','Yin ', + 'Fan ','Nan ','Chi ','Wang ','Yuan ','Xia ','Zhou ','Yuan ','Shi ','Mi ','','Ge ','Pao ','Fei ','Hu ','Ni ', + 'Ci ','Mi ','Bian ','Gam ','Na ','Yu ','E ','Zhi ','Nin ','Xu ','Lue ','Hui ','Xun ','Nao ','Han ','Jia ', + 'Dou ','Hua ','Tuk ','','Cu ','Xi ','Song ','Mi ','Xin ','Wu ','Qiong ','Zheng ','Chou ','Xing ','Jiu ','Ju ', + 'Hun ','Ti ','Man ','Jian ','Qi ','Shou ','Lei ','Wan ','Che ','Can ','Jie ','You ','Hui ','Zha ','Su ','Ge ', + ], + 'x47':[ + 'Nao ','Xi ','','Deoi ','Chi ','Wei ','Mo ','Gun ','Cau ','','Zao ','Hui ','Luan ','Liao ','Lao ','', + '','Qia ','Ao ','Nie ','Sui ','Mai ','Tan ','Xin ','Jing ','An ','Ta ','Chan ','Wei ','Tuan ','Ji ','Chen ', + 'Che ','Xu ','Xian ','Xin ','','Daan ','','Nao ','','Yan ','Qiu ','Hong ','Song ','Jun ','Liao ','Ju ', + '','Man ','Lie ','','Chu ','Chi ','Xiang ','Cam ','Mei ','Shu ','Ce ','Chi ','Gu ','Yu ','Zaam ','', + 'Liao ','Lao ','Shu ','Zhe ','Soeng ','','Fat ','Fui ','E ','','Sha ','Zong ','Jue ','Jun ','','Lou ', + 'Wei ','Cung ','Zhu ','La ','Fun ','Zhe ','Zhao ','Zaau ','Yi ','','Ni ','Bo ','Syun ','Yi ','Hao ','Ya ', + 'Huan ','Man ','Man ','Qu ','Lao ','Hao ','','Men ','Xian ','Zhen ','Shu ','Zuo ','Zhu ','Gou ','Xuan ','Yi ', + 'Ti ','xie ','Jin ','Can ','Zai ','Bu ','Liang ','Zhi ','Ji ','Wan ','Guan ','Ceoi ','Qing ','Ai ','Fu ','Gui ', + 'Gou ','Xian ','Ruan ','Zhi ','Biao ','Yi ','Suo ','Die ','Gui ','Sheng ','Xun ','Chen ','She ','Qing ','','', + 'Chun ','Hong ','Dong ','Cheng ','Wei ','Die ','Shu ','Caai ','Ji ','Za ','Qi ','','Fu ','Ao ','Fu ','Po ', + '','Tan ','Zha ','Che ','Qu ','You ','He ','Hou ','Gui ','E ','Jiang ','Yun ','Tou ','Qiu ','','Fu ', + 'Zuo ','Hu ','','Bo ','','Jue ','Di ','Jue ','Fu ','Huang ','','Yong ','Chui ','Suo ','Chi ','Hin ', + '','','Man ','Ca ','Qi ','Jian ','Bi ','Gei ','Zhi ','Zhu ','Qu ','Zhan ','Ji ','Dian ','','Li ', + 'Li ','La ','Quan ','Ding ','Fu ','Cha ','Tang ','Shi ','Hang ','Qie ','Qi ','Bo ','Na ','Tou ','Chu ','Cu ', + 'Yue ','Di ','Chen ','Chu ','Bi ','Mang ','Ba ','Tian ','Min ','Lie ','Feng ','Caang ','Qiu ','Tiao ','Fu ','Kuo ', + 'Jian ','Ci ','','','Zhen ','Qiu ','Cuo ','Chi ','Kui ','Lie ','Bang ','Du ','Wu ','So ','Jue ','Lu ', + ], + 'x48':[ + 'Chang ','Zai ','Chu ','Liang ','Tian ','Kun ','Chang ','Jue ','Tu ','Hua ','Fei ','Bi ','','Qia ','Wo ','Ji ', + 'Qu ','Kui ','Hu ','Cu ','Sui ','','','Qiu ','Pi ','Bei ','Wa ','Jiao ','Rong ','','Cu ','Die ', + 'Chi ','Cuo ','Meng ','Xuan ','Duo ','Bie ','Zhe ','Chu ','Chan ','Gui ','Duan ','Zou ','Deng ','Lai ','Teng ','Yue ', + 'Quan ','Shu ','Ling ','','Qin ','Fu ','She ','Tiao ','','Ai ','','Qiong ','Diao ','Hai ','Shan ','Wai ', + 'Zhan ','Long ','Jiu ','Li ','','Min ','Rong ','Yue ','Jue ','Kang ','Fan ','Qi ','Hong ','Fu ','Lu ','Hong ', + 'Tuo ','Min ','Tian ','Juan ','Qi ','Zheng ','Jing ','Gong ','Tian ','Lang ','Mao ','Yin ','Lu ','Yun ','Ju ','Pi ', + '','Xie ','Bian ','','Zeoi ','Rong ','Sang ','Wu ','Cha ','Gu ','Chan ','Peng ','Man ','Saau ','Zung ','Shuang ', + 'Keng ','Zhuan ','Chan ','Si ','Chuang ','Sui ','Bei ','Kai ','','Zhi ','Wei ','Min ','Ling ','','Nei ','Ling ', + 'Qi ','Yue ','Lip ','Yi ','Xi ','Chen ','','Rong ','Chen ','Nong ','You ','Ji ','Bo ','Fang ','Gei ','', + 'Cu ','Di ','Gaau ','Yu ','Ge ','Xu ','Lu ','He ','','Bai ','Gong ','Jiong ','Gwai ','Ya ','Nu ','You ', + 'Song ','Xie ','Cang ','Yao ','Shu ','Yan ','Shuai ','Liao ','Sung ','Yu ','Bo ','Sui ','Cin ','Yan ','Lei ','Lin ', + 'Tai ','Du ','Yue ','Ji ','Cin ','Yun ','Bong ','','','Ju ','Ceot ','Chen ','Cung ','Xiang ','Xian ','On ', + 'Gui ','Yu ','Lei ','','Tu ','Chen ','Xing ','Qiu ','Hang ','','Dang ','Cai ','Di ','Yan ','Ci ','Gung ', + 'Zing ','Chan ','','Li ','Suo ','Ma ','Ma ','','Tang ','Pei ','Lou ','Sat ','Cuo ','Tu ','E ','Can ', + 'Jie ','Ti ','Ji ','Dang ','Jiao ','Bi ','Lei ','Yi ','Chun ','Chun ','Po ','Li ','Zai ','Tai ','Po ','Tian ', + 'Ju ','Xu ','Fan ','','Xu ','Er ','Huo ','Zyu ','Ran ','Fa ','Gyun ','','Liang ','Ti ','Mi ','', + ], + 'x49':[ + '','Cen ','Mei ','Yin ','Mian ','Tu ','Kui ','Sau ','Hei ','Mi ','Rong ','Guo ','Coeng ','Mi ','Ju ','Pi ', + 'Jin ','Wang ','Ji ','Meng ','Jian ','Xue ','Bao ','Gan ','Chan ','Li ','Li ','Qiu ','Dun ','Ying ','Yun ','Chen ', + 'Ji ','Ran ','','Lue ','','Gui ','Yue ','Hui ','Pi ','Cha ','Duo ','Chan ','So ','Kuan ','She ','Xing ', + 'Weng ','Shi ','Chi ','Ye ','Han ','Fei ','Ye ','Yan ','Zuan ','Saau ','Yin ','Duo ','Xian ','Gwaan ','Tou ','Qie ', + 'Chan ','Han ','Meng ','Yue ','Cu ','Qian ','Jin ','Shan ','Mu ','Zyun ','Coeng ','Baang ','Zheng ','Zhi ','Chun ','Yu ', + 'Mou ','Wan ','Chou ','Kei ','Su ','Pie ','Tian ','Kuan ','Cu ','Sui ','Co ','Jie ','Jian ','Ao ','Jiao ','Ye ', + 'Saam ','Ye ','Long ','Zao ','Bao ','Lian ','','Huan ','Lu ','Wei ','Xian ','Tie ','Bo ','Zheng ','Zhu ','Ba ', + 'Meng ','Xie ','Aau ','Zaau ','Teon ','Xiao ','Li ','Zha ','Mi ','','Ye ','','','Put ','Xie ','', + '','Bong ','Shan ','Coeng ','','Shan ','Jue ','Ji ','Fang ','','Niao ','Ao ','Chu ','Wu ','Guan ','Xie ', + 'Ting ','Xie ','Dang ','Zim ','Tan ','Ping ','Xia ','Xu ','Bi ','Si ','Huo ','Zheng ','Wu ','','Run ','Chuai ', + 'Shi ','Huan ','Kuo ','Fu ','Chuai ','Xian ','Qin ','Qie ','Lan ','','Ya ','Zing ','Que ','','Chun ','Zhi ', + 'Gau ','Kui ','Qian ','Hang ','Yi ','Ni ','Zheng ','Chuai ','','Shi ','Cap ','Ci ','Jue ','Xu ','Yun ','', + '','Chu ','Dao ','Dian ','Ge ','Ti ','Hong ','Ni ','','Li ','','Xian ','Seoi ','Xi ','Xuan ','', + 'Gwik ','Taai ','Lai ','Zau ','Mu ','Cheng ','Jian ','Bi ','Qi ','Ling ','Hao ','Bang ','Tang ','Di ','Fu ','Xian ', + 'Shuan ','Zung ','Keoi ','Zaan ','Pu ','Hui ','Wei ','Yi ','Ye ','','Che ','Hao ','Baai ','','Xian ','Chan ', + 'Hun ','Gaau ','Han ','Ci ','Zi ','Qi ','Kui ','Rou ','Gu ','Zing ','Xiong ','Gap ','Hu ','Cui ','Syu ','Que ', + ], + 'x4a':[ + 'Di ','Che ','Cau ','','Yan ','Liao ','Bi ','Soeng ','Ban ','Zing ','','Nue ','Bao ','Ying ','Hong ','Ci ', + 'Qia ','Ti ','Yu ','Lei ','Bao ','Wu ','Ji ','Fu ','Xian ','Cen ','Fat ','Se ','Baang ','Cing ','Yu ','Waa ', + 'Ai ','Han ','Dan ','Ge ','Di ','Hu ','Pang ','Zaam ','Zaa ','Ling ','Mai ','Mai ','Lian ','Siu ','Xue ','Zhen ', + 'Po ','Fu ','Nou ','Xi ','Dui ','Dan ','Yun ','Xian ','Yin ','Suk ','Dui ','Beng ','Hu ','Fei ','Fei ','Qian ', + 'Bei ','Fei ','','Shi ','Tian ','Zhan ','Jian ','','Hui ','Fu ','Wan ','Mo ','Qiao ','Liao ','','Mie ', + 'Ge ','Hong ','Yu ','Qi ','Duo ','Ang ','Saa ','Ba ','Di ','Xuan ','Di ','Bi ','Zhou ','Pao ','Nian ','Yi ', + 'Ting ','Jia ','Da ','Duo ','Xi ','Dan ','Tiao ','Xie ','Chang ','Yuan ','Guan ','Liang ','Beng ','Gei ','Lu ','Ji ', + 'Xuan ','Shu ','Dou ','Shu ','Hu ','Yun ','Chan ','Bong ','Rong ','E ','Zung ','Ba ','Feng ','Zyu ','Zhe ','Fen ', + 'Guan ','Bu ','Ge ','Deon ','Huang ','Du ','Ti ','Bo ','Qian ','La ','Long ','Wei ','Zhan ','Lan ','Seoi ','Na ', + 'Bi ','Tuo ','Jiao ','','Bu ','Ju ','Po ','Xia ','Wei ','Fu ','He ','Fan ','Chan ','Hu ','Za ','', + 'Saai ','Zai ','Zai ','Zai ','Fan ','Die ','Hong ','Chi ','Bao ','Yin ','','Haang ','Bo ','Ruan ','Chou ','Ying ', + 'Zi ','Gai ','Kwaan ','Yun ','Zhen ','Ya ','Zeoi ','Hou ','Min ','Pei ','Ge ','Bian ','Zyut ','Hao ','Mi ','Sheng ', + 'Gen ','Bi ','Duo ','Chun ','Chua ','San ','Cheng ','Ran ','Zen ','Mao ','Bo ','Tui ','Pi ','Fu ','Zyut ','Hei ', + 'Lin ','Hei ','Men ','Wu ','Qi ','Zhi ','Chen ','Xia ','He ','Sang ','Gwaa ','Hou ','Au ','Fu ','Rao ','Hun ', + 'Pei ','Qian ','Si ','Xi ','Ming ','Kui ','Ge ','','Ao ','San ','Shuang ','Lou ','Zhen ','Hui ','Can ','Ci ', + 'Lin ','Na ','Han ','Du ','Jin ','Mian ','Fan ','E ','Nao ','Hong ','Hong ','Xue ','Xue ','Pau ','Bi ','Ciu ', + ], + 'x4b':[ + 'You ','Yi ','Xue ','Sa ','Yu ','Li ','Li ','Yuan ','Dui ','Hao ','Qie ','Leng ','Paau ','Fat ','Guo ','Bu ', + 'Wei ','Wei ','Saau ','An ','Xu ','Shang ','Heng ','Yang ','Gwik ','Yao ','Fan ','Bi ','Ci ','Heng ','Tao ','Liu ', + 'Fei ','Zhu ','Tou ','Qi ','Chao ','Yi ','Dou ','Yuan ','Cu ','Zai ','Bo ','Can ','Yang ','Tou ','Yi ','Nian ', + 'Shao ','Ben ','Ngaau ','Ban ','Mo ','Ai ','En ','She ','Caan ','Zhi ','Yang ','Jian ','Yuan ','Dui ','Ti ','Wei ', + 'Xun ','Zhi ','Yi ','Ren ','Shi ','Hu ','Ne ','Yi ','Jian ','Sui ','Ying ','Bao ','Hu ','Hu ','Xie ','', + 'Yang ','Lian ','Sik ','En ','Deoi ','Jian ','Zhu ','Ying ','Yan ','Jin ','Chuang ','Dan ','','Kuai ','Yi ','Ye ', + 'Jian ','En ','Ning ','Ci ','Qian ','Xue ','Bo ','Mi ','Shui ','Mi ','Liang ','Qi ','Qi ','Shou ','Bi ','Bo ', + 'Beng ','Bie ','Ni ','Wei ','Huan ','Fan ','Qi ','Liu ','Fu ','Ang ','Ang ','Fan ','Qi ','Qun ','Tuo ','Yi ', + 'Bo ','Pian ','Bo ','Keoi ','Xuan ','','Baai6','Yu ','Chi ','Lu ','Yi ','Li ','Zaau ','Niao ','Xi ','Wu ', + 'Gwing ','Lei ','Pei ','Zhao ','Zui ','Chuo ','Coeng ','An ','Er ','Yu ','Leng ','Fu ','Sha ','Huan ','Chu ','Sou ', + 'Bik ','Bi ','Die ','Song ','Di ','Li ','Giu ','Han ','Zai ','Gu ','Cheng ','Lou ','Mo ','Mi ','Mai ','Ao ', + 'Dan ','Zhu ','Huang ','Fan ','Deng ','Tong ','','Du ','Hu ','Wei ','Ji ','Chi ','Lin ','Biu ','Pang ','Jian ', + 'Nie ','Luo ','Ji ','Ngon ','Waa ','Nie ','Yi ','Gwaat6','Wan ','Ya ','Qia ','Bo ','Hau ','Ling ','Gan ','Huo ', + 'Hai ','Hong ','Heng ','Kui ','Cen ','Ting ','Lang ','Bi ','Huan ','Po ','Ou ','Jian ','Ti ','Sui ','Kwaa ','Dui ', + 'Ao ','Jian ','Mo ','Gui ','Kuai ','An ','Ma ','Qing ','Fen ','','Kao ','Hao ','Duo ','Cim ','Nai ','Seoi ', + 'Jie ','Fu ','Pa ','Sung ','Chang ','Nie ','Man ','Sung ','Ci ','Cim ','Kuo ','Gai ','Di ','Fu ','Tiao ','Zu ', + ], + 'x4c':[ + 'Wo ','Fei ','Cai ','Peng ','Shi ','Sou ','Rou ','Qi ','Cha ','Pan ','Bo ','Man ','Zong ','Ci ','Gui ','Ji ', + 'Lan ','Siu ','Meng ','Mian ','Pan ','Lu ','Cuan ','Gau ','Liu ','Yi ','Wen ','Li ','Li ','Zeng ','Zhu ','Hun ', + 'Shen ','Chi ','Xing ','Wang ','Dung ','Huo ','Pi ','Bou6','Mei ','Che ','Mei ','Chao ','Ju ','Nou ','','Ni ', + 'Ru ','Ling ','Ya ','','Qi ','Zi ','','Bang ','Gung ','Ze ','Jie ','Yu ','Xin ','Bei ','Ba ','Tuo ', + 'Ong ','Qiao ','You ','Di ','Jie ','Mo ','Sheng ','Shan ','Qi ','Shan ','Mi ','Dan ','Yi ','Geng ','Geng ','Tou ', + 'Fu ','Xue ','Yi ','Ting ','Tiao ','Mou ','Liu ','Caan ','Li ','Suk ','Lu ','Xu ','Cuo ','Ba ','Liu ','Ju ', + 'Zhan ','Ju ','Zang ','Zu ','Xian ','Zhi ','','','Zhi ','','','La ','Seoi ','Geng ','E ','Mu ', + 'Zhong ','Di ','Yan ','Zin ','Geng ','Zung ','Lang ','Yu ','Caau ','Na ','Hai ','Hua ','Zhan ','Coeng ','Lou ','Chan ', + 'Die ','Wei ','Xuan ','Zao ','Min ','Kwai ','Sou ','','','Si ','Tuo ','Cen ','Kuan ','Teng ','Nei ','Lao ', + 'Lu ','Yi ','Xie ','Yan ','Qing ','Pu ','Chou ','Xian ','Guan ','Jie ','Lai ','Meng ','Ye ','Ceoi ','Li ','Yin ', + 'Ceon ','Cau ','Teng ','Yu ','','Gau ','Cha ','Du ','Hong ','Si ','Xi ','Gaau ','Qi ','Ci ','Yuan ','Ji ', + 'Yun ','Fang ','Gung ','Hang ','Zhen ','Hu ','','','Jie ','Pei ','Gan ','Xuan ','Saang ','Dao ','Qiao ','Ci ', + 'Die ','Ba ','Tiao ','Wan ','Ci ','Zhi ','Bai ','Wu ','Bao ','Dan ','Ba ','Tong ','Gyun ','Gung ','Jiu ','Gui ', + 'Ci ','You ','Yuan ','Lao ','Jiu ','Fou ','Nei ','E ','E ','Xing ','He ','Yan ','Tu ','Bu ','Beng ','Kou ', + 'Chui ','Zeoi ','Qi ','Yuan ','Bit ','','Hyun ','Hou ','Huang ','Ziu ','Juan ','Kui ','E ','Ji ','Mo ','Chong ', + 'Bao ','Wu ','Zhen ','Xu ','Da ','Chi ','Gaai ','Cong ','Ma ','Kou ','Yan ','Can ','Aau ','He ','Dang ','Lan ', + ], + 'x4d':[ + 'Tong ','Yu ','Hang ','Nao ','Li ','Fen ','Pu ','Ling ','Ao ','Xuan ','Yi ','Xuan ','Meng ','Ang ','Lei ','Yan ', + 'Bao ','Die ','Ling ','Shi ','Jiao ','Lie ','Jing ','Ju ','Ti ','Pi ','Gang ','Jiao ','Huai ','Bu ','Di ','Huan ', + 'Yao ','Li ','Mi ','Fu ','Saang ','Gaa ','Ren ','Wai ','','Piao ','Lu ','Ling ','Yi ','Cai ','Shan ','Fat ', + 'Shu ','Tuo ','Mo ','He ','Tie ','Bing ','Peng ','Hun ','Fu ','Guo ','Bu ','Li ','Chan ','Bai ','Cuo ','Meng ', + 'Suo ','Qiang ','Zhi ','Kuang ','Bi ','Ao ','Meng ','Xian ','Guk ','Tou ','Teon ','Wei ','Cim ','Tan ','Caau ','Lao ', + 'Chan ','Ni ','Ni ','Li ','Dong ','Ju ','Jian ','Fu ','Sha ','Zha ','Tao ','Jian ','Nong ','Ya ','Jing ','Gan ', + 'Di ','Jian ','Mei ','Da ','Jian ','She ','Xie ','Zai ','Mang ','Li ','Gun ','Yu ','Ta ','Zhe ','Yang ','Tuan ', + 'Soeng ','He ','Diao ','Wei ','Yun ','Zha ','Qu ','Waa ','Caau ','Zi ','Ting ','Gu ','Soeng ','Ca ','Fu ','Tie ', + 'Ta ','Ta ','Zhuo ','Han ','Ping ','He ','Ceoi ','Zhou ','Bo ','Liu ','Nu ','Kaap ','Pao ','Di ','Sha ','Ti ', + 'Kuai ','Ti ','Qi ','Ji ','Chi ','Pa ','Jin ','Ke ','Li ','Ju ','Qu ','La ','Gu ','Qia ','Qi ','Xian ', + 'Jian ','Shi ','Xian ','Ai ','Hua ','Ju ','Ze ','Yao ','Tam ','Ji ','Cha ','Kan ','Gin ','','Yan ','Gwaai ', + 'Ziu ','Tong ','Nan ','Yue ','Ceoi ','Chi ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x4e':[ + 'Ichi ','Tei ','Kou ','Shichi ','Shou ','Ka ','','Man ','Jou ','San ','Jou ','Ka ','Ki ','Fu ','Yo ','Ben ', + 'Kai ','Chuu ','Chuu ','Sen ','Sha ','Hi ','Se ','Sei ','Kyuu ','Hei ','Ye ','Cong ','Dong ','Si ','Shou ','Chuu ', + 'Kyuu ','Ryou ','Chuu ','Yuu ','Ryou ','Yan ','Hei ','Sang ','Kon ','Kyuu ','Ka ','A ','Qiang ','Chuu ','Keki ','Kai ', + 'Hou ','Kan ','Sen ','San ','Lin ','Saku ','Chu ','Ha ','Gan ','Tan ','Wei ','Shu ','Sei ','Rei ','Kyo ','Hetsu ', + 'Futsu ','I ','Gai ','Dai ','Shime ','Kyuu ','Kyuu ','Taku ','Eu ','Yi ','','Shi ','Wu ','Saku ','Ko ','Bou ', + 'Le ','Gin ','Hei ','Hau ','Qiao ','Ko ','Kai ','Jou ','Jou ','Otsu ','In ','','Ba ','Kyuu ','Kotsu ','Ya ', + 'Xi ','Xiang ','Gai ','Kyuu ','Hal ','','Shu ','Twul ','Shi ','Kei ','Dou ','Jia ','Kel ','Shi ','','Ol ', + 'Mai ','Ran ','Cal ','Nyuu ','Setsu ','En ','Fu ','Sha ','Na ','Kan ','Sol ','El ','Cwul ','','Kan ','Chi ', + 'Ki ','Ken ','Ran ','Rin ','I ','Ketsu ','Ryou ','Ma ','Yo ','Sou ','Ji ','Ji ','Ni ','Choku ','U ','U ', + 'Yu ','Un ','Go ','Ki ','Go ','Sei ','Shi ','Sai ','Sen ','Kou ','Ya ','Sa ','A ','Sei ','A ','Kyoku ', + 'Tou ','Bou ','Kou ','Ta ','Kou ','Gai ','Eki ','Chan ','Kyou ','Mu ','','Kyou ','Kyou ','Tei ','Ryou ','Kyou ', + 'Kei ','Ya ','Qin ','Haku ','You ','Xie ','Tan ','Ren ','Ta ','Bi ','Jin ','Ren ','Shuu ','La ','Bou ','Yi ', + 'Shuu ','Jin ','Roku ','Tei ','Soku ','Hu ','Fu ','Kyuu ','Hatsu ','Shou ','Kon ','Kai ','Bing ','Jou ','Juu ','Butsu ', + 'San ','Lun ','Sya ','Cang ','Shi ','Shi ','Ta ','Jou ','Fu ','Sen ','Ken ','Ta ','Kou ','Dou ','Jin ','Sen ', + 'Kan ','Kitsu ','Haku ','Dai ','Rei ','I ','Chao ','Chang ','Sa ','','Yi ','Mu ','Men ','Jin ','Ka ','Sou ', + 'Gyou ','Ken ','Chuu ','Hi ','Gatsu ','Ko ','Ken ','Kai ','Yao ','Feng ','Cang ','Nin ','Kyou ','Hin ','Tei ','Hou ', + ], + 'x4f':[ + 'Shou ','Ki ','Hai ','Yo ','Chou ','Ton ','Wen ','Eki ','Shin ','Kou ','I ','Kyuu ','Ai ','Go ','Ki ','Fuku ', + 'Batsu ','Kyuu ','Kin ','Hai ','Shin ','Hu ','Do ','Gin ','Yuu ','Ka ','Kai ','Yu ','Sai ','Den ','San ','Wei ', + 'Chuan ','Kuruma ','Ya ','Ken ','Shang ','Chang ','Lun ','Cang ','Xun ','Shin ','Wei ','Zhu ','','Ken ','Do ','Haku ', + 'Ko ','Ji ','Ji ','Setsu ','Han ','Kyoku ','Rei ','Chuu ','Shin ','Sho ','Shi ','Hou ','Ji ','Kya ','Hi ','I ', + 'Shi ','Ai ','Yai ','Ten ','Han ','Mai ','Tan ','Cho ','Ho ','Kyo ','Bi ','Shou ','Shi ','I ','Tei ','Juu ', + 'Sa ','Yuu ','Au ','Tei ','Chin ','Ka ','Hitsu ','Ta ','Sha ','Yo ','Itsu ','Butsu ','Saku ','Kou ','Nei ','Tou ', + 'Ji ','Ken ','Kyo ','You ','Wa ','Qian ','','Ka ','','Hai ','Kuwai ','Kaku ','Ryou ','Xiang ','Kou ','You ', + 'Haku ','Hou ','Ming ','Ka ','Ji ','Hei ','Kitsu ','Kou ','Katsu ','Ki ','Sen ','Chou ','Kou ','Shi ','Itsu ','Shi ', + 'Kei ','Shin ','Taku ','Kan ','Shitsu ','Kai ','Rai ','I ','Shi ','Ka ','Kou ','Rei ','In ','Ji ','Bi ','Shu ', + 'Kyoku ','Yuu ','An ','Rotsu ','Bou ','Ji ','Ron ','Tou ','Ta ','Choku ','Shun ','Kyou ','Chuu ','I ','Jo ','Sen ', + 'Kyou ','Ka ','Bu ','Ryo ','Ko ','Jiao ','Zhen ','Ce ','Qiao ','Kuai ','Chai ','Nei ','Nong ','Jin ','Bu ','Kou ', + 'Jiong ','Cheng ','Shin ','Sa ','Chuu ','Shin ','Ryo ','Kyoku ','Shu ','Tei ','Shin ','Tatsu ','Hotsu ','Dan ','Kou ','Ben ', + 'Tai ','Gu ','Kei ','Soku ','Ga ','Kyuu ','Sho ','Kyau ','Koku ','Go ','Shun ','Chuu ','Fu ','Ryou ','Sho ','Seu ', + 'Ri ','You ','Kon ','Gau ','Ken ','San ','Hai ','Zoku ','Fu ','Ki ','Ri ','Ben ','Hei ','Ho ','Yu ','Shi ', + 'Kyou ','Shin ','Shuu ','Mata ','Omokage ','Kuruma ','Chou ','','Yan ','Lia ','Li ','Rai ','Si ','Jian ','Shuu ','Fu ', + 'Ka ','Ku ','Kou ','Hai ','Sen ','Hyou ','Shuku ','Hi ','Hou ','Ya ','En ','Bi ','Iku ','Kin ','Hi ','Chi ', + ], + 'x50':[ + 'Chou ','Chi ','Hei ','Kyuu ','Kou ','Sai ','Ryou ','En ','Rai ','Sou ','Sou ','Ko ','Kuwan ','Bai ','Ten ','Shuku ', + 'Shuku ','Mon ','Tou ','Tan ','Kutsu ','Sui ','Kou ','Hou ','Shou ','Kou ','I ','Ki ','Teki ','Kan ','Kei ','Shaku ', + 'Ki ','Shou ','Shou ','Hou ','Chi ','Kou ','Ken ','Sou ','Kyo ','Sen ','Gei ','Rin ','Taku ','I ','Ra ','Shou ', + 'Ryou ','Kon ','Tou ','Shi ','Hon ','Bu ','Ku ','Dai ','Cai ','Ken ','Zhai ','Ya ','Chi ','Sha ','Qing ','', + 'Ei ','Shou ','Sen ','En ','Dan ','Shou ','Shun ','Ka ','Ketsu ','I ','U ','Hei ','Ja ','Tei ','Wai ','Hen ', + 'Gan ','Huu ','Tou ','Aku ','E ','Kai ','Sha ','Sei ','Kan ','Tei ','Saku ','Sou ','Tei ','Hai ','You ','Kuwau ', + 'Eu ','Tan ','Seu ','En ','Yu ','Ken ','Sho ','Ta ','Shi ','Huu ','Hiyoku ','Chi ','Sou ','Ben ','Shuu ','I ', + 'Setsu ','Shun ','Shi ','Tan ','Soku ','Tei ','Guu ','Chuu ','Chuu ','Bi ','San ','Rou ','Jie ','Gi ','Fen ','Chang ', + 'Kai ','Sou ','Chi ','So ','Katsu ','Fu ','Gen ','Jou ','Ritsu ','Ru ','In ','Kau ','Ba ','Bou ','Ten ','Tou ', + 'Kou ','Ketsu ','Kei ','Sen ','Ken ','Kaku ','Sau ','Chu ','San ','Bi ','Kou ','You ','Eu ','Tan ','Sa ','Au ', + 'Hatsu ','Hei ','Ka ','Dai ','Sai ','Tang ','Cot ','Bin ','Chu ','Nuo ','San ','Lei ','Sai ','You ','Sou ','Sou ', + 'Hou ','Shou ','Gou ','Den ','U ','Sai ','Soku ','Shou ','Sau ','Kyou ','Tei ','Sa ','Han ','Shou ','Kei ','En ', + 'Tei ','Setsu ','Rou ','Bi ','Heu ','Kin ','Ren ','Riku ','Ban ','Sen ','Sen ','Tan ','You ','Dou ','Sen ','Zou ', + 'Sen ','Kyou ','Jiong ','Tai ','Son ','Boku ','Ki ','Rau ','Shou ','Kou ','Ryou ','Ki ','Tou ','San ','Gi ','Ki ', + 'Fan ','Hui ','Sen ','Sen ','Tan ','Kyou ','Shyuu ','Sou ','Hun ','Kan ','Kitsu ','E ','Seu ','Sen ','Dou ','Rin ', + 'Hoku ','Ko ','','Su ','Xian ','Kyou ','Bin ','Ye ','Kin ','Ka ','Shou ','Heki ','Hou ','Shuu ','Ai ','Shi ', + ], + 'x51':[ + 'Gi ','Shun ','Dou ','Sen ','Oku ','Tou ','Kei ','Ken ','Kai ','Ken ','Sho ','Tan ','Keu ','Sa ','Sai ','', + 'Hin ','Gan ','Ju ','Tai ','Chuu ','Sei ','Ran ','Gi ','Jin ','Ken ','Bou ','Bu ','Dau ','Kei ','Ji ','Shou ', + 'Ryou ','Rai ','Ryo ','Kou ','Hou ','Iku ','Hyou ','San ','Shitsu ','Shi ','Yuu ','Hao ','Shin ','Shin ','Reki ','Tou ', + 'I ','Rou ','Cho ','San ','Shou ','Shuu ','Hui ','Rei ','Ra ','San ','Da ','Tou ','Gen ','Rai ','Nang ','Jin ', + 'Kotsu ','In ','Shin ','Gen ','Kei ','Juu ','Chou ','Kyou ','Sen ','Kou ','Tai ','Koku ','Da ','Men ','To ','Chou ', + 'Ji ','Da ','Ji ','Shin ','To ','Shi ','Yan ','En ','Shi ','Sip ','Tou ','Qian ','Tou ','Fen ','Mao ','Shin ', + 'Dou ','Payk ','Kyou ','Li ','Kou ','Nyuu ','Bou ','Dai ','Zen ','Ryou ','Yu ','Hachi ','Kou ','Roku ','Kei ','', + 'Lan ','Kyou ','Tian ','Guan ','Xing ','Hei ','Ki ','Gu ','Ten ','Ji ','Ppwun ','Yang ','Ken ','Shou ','Ki ','Yi ', + 'Ki ','Chan ','Kei ','Bou ','Zen ','Dai ','En ','Mao ','Gang ','Nen ','Satsu ','Kei ','Satsu ','Sai ','Ka ','Kei ', + 'Bou ','Chuu ','Bou ','Kou ','Ku ','Ben ','Beki ','Jou ','In ','Sha ','Kan ','Jun ','Nong ','Gi ','Bi ','Shi ', + 'Kan ','Bou ','Chou ','Shu ','En ','Mei ','Kou ','Lam ','Fu ','Sha ','Beki ','Hyou ','Tou ','Tai ','Gang ','Feng ', + 'Hyou ','Go ','Chuu ','Ketsu ','Go ','Kyou ','Ya ','Rei ','Han ','Hutsu ','Bin ','Dong ','Shou ','Retsu ','Kyou ','Sen ', + 'Jing ','Shu ','Bai ','Tu ','Sei ','Ko ','Jun ','Shou ','Sou ','Ryou ','Sei ','Chou ','Ryou ','Tou ','Gan ','Gen ', + 'In ','Sou ','Gi ','Ritsu ','Sau ','Bei ','Jun ','Sai ','Shi ','Taku ','Jin ','Rin ','Rin ','Gyou ','Ki ','Du ', + 'Ki ','Bon ','Bon ','Han ','Hou ','Kyo ','Sho ','Tako ','Fuu ','Kogarashi ','Nagu ','Fu ','Feng ','Hyou ','Fuu ','Kai ', + 'Kou ','Gai ','Kan ','Tou ','Hyou ','Kan ','Kyou ','Kai ','Totsu ','Ou ','Shutsu ','Ji ','Dang ','Kan ','Kan ','Zao ', + ], + 'x52':[ + 'Tou ','Teu ','Tau ','Jin ','Jin ','Sou ','Bun ','Setsu ','Gai ','Ki ','Kan ','Sen ','Son ','Chu ','Fun ','Ki ', + 'Tan ','Kei ','Ka ','Gun ','Ketsu ','Ri ','Getsu ','Retsu ','Ryuu ','Ze ','Gang ','Chuang ','Hutsu ','Sho ','Sho ','Chou ', + 'San ','Bin ','Rei ','Zhong ','Han ','Betsu ','Kyou ','Gou ','Hou ','Ri ','San ','Betsu ','San ','Jing ','Katsu ','Gen ', + 'Tou ','Sou ','Kei ','Ko ','Ta ','Ji ','Sei ','Satsu ','Ken ','Satsu ','Shi ','Koku ','Kyou ','Gui ','Ci ','Gui ', + 'Kai ','Ta ','Ji ','Tei ','Kei ','Rou ','Ra ','Soku ','Yuan ','Sa ','Saku ','Koku ','Ratsu ','Zen ','Satsu ','Sou ', + 'Gua ','Jian ','Saku ','Li ','Teki ','Hi ','Bou ','San ','Ki ','Sou ','Shi ','Gou ','Wan ','Haku ','Ki ','Tetsu ', + 'Kei ','En ','Toku ','Ken ','Zai ','Haku ','En ','Ju ','Kaku ','Jou ','Sen ','Taku ','Tan ','Oku ','Ka ','Fuku ', + 'Jou ','Ken ','Katsu ','Tou ','Gai ','Sou ','Juan ','San ','Tan ','Riku ','Ri ','Huu ','San ','Hyou ','Kou ','Shou ', + 'Katsu ','Syou ','Ketsu ','Kaku ','Satsu ','Taku ','Ren ','Geki ','Heki ','Ru ','Kai ','Syou ','Kei ','Ken ','Ken ','Tang ', + 'Kaku ','Zai ','Ken ','Gi ','Ken ','Shitsu ','San ','San ','Ba ','Ri ','Chaku ','Ryoku ','Atsu ','Kan ','Hen ','Kou ', + 'Ka ','Wu ','Mai ','Retsu ','Kin ','Kou ','Kyou ','Shi ','Dong ','Jo ','Do ','Gou ','Ku ','Shou ','Itsu ','Sho ', + 'Baku ','Rei ','Kei ','Rou ','Rou ','Ken ','Kou ','You ','Ai ','Kou ','Bou ','Kyou ','Katsu ','Retsu ','Gai ','Sei ', + 'Koku ','Kei ','Kou ','Botsu ','Bin ','Choku ','Rou ','Yuu ','You ','Ben ','Ke ','Xun ','Ken ','Kei ','Lu ','Hou ', + 'Bau ','Rai ','Roku ','Kai ','Ben ','Dou ','Kyaku ','Bou ','Kan ','Mu ','Ei ','Kun ','Ou ','Shou ','Rou ','Bo ', + 'Riku ','Heu ','Sei ','Seki ','Kin ','Kyou ','Sou ','Kan ','You ','Ei ','Kyaku ','Han ','Ken ','Tong ','Ju ','Tan ', + 'Kyou ','Bai ','Kun ','Kun ','Ryo ','Rei ','Ketsu ','Jou ','Kan ','Hou ','Shaku ','In ','Kyuu ','Bun ','Kou ','Butsu ', + ], + 'x53':[ + 'In ','Monme ','Niou ','Katsu ','Kai ','Hou ','Sou ','','Kyou ','Hyou ','Kiku ','Tou ','Kou ','Ho ','Ou ','Hou ', + 'Hoku ','Kyuu ','Tou ','Kyou ','Qiong ','Hi ','Ka ','Hoku ','Dou ','Shi ','Hou ','Kyuu ','I ','Sou ','Shou ','Kou ', + 'Shou ','Kyou ','Kotsu ','Kou ','Kyaku ','Hen ','Gui ','Kyou ','Zou ','Kyou ','Hi ','Kotsu ','Yu ','Ki ','Gui ','Wai ', + 'Tan ','Ki ','Ren ','Ren ','San ','Toku ','Jiu ','Kyo ','Kei ','Hitsu ','Ku ','I ','An ','En ','Hen ','Toku ', + 'Ku ','Juu ','Shin ','Sen ','Juu ','Sou ','Sotsu ','Shou ','Go ','Ki ','Han ','Sei ','Shuu ','Ban ','Hua ','Xie ', + 'Ban ','Hi ','Sotsu ','Taku ','Kyou ','Tan ','Mai ','Nan ','Tan ','Shou ','Haku ','Shutsu ','Boku ','Kan ','Hen ','Bu ', + 'Sen ','Sahu ','Lu ','Yuu ','Sei ','Sei ','Ka ','Wo ','Setsu ','Setsu ','Jie ','Wei ','Gau ','Kyou ','Shi ','Bou ', + 'In ','Ki ','Shou ','Soku ','Kyaku ','Ran ','Shi ','Kan ','Sha ','Jutsu ','Kin ','Kyaku ','Gotsu ','Soku ','Gaku ','Kyou ', + 'Shitsu ','','Kan ','Sen ','Yaku ','Ting ','Li ','Taku ','Kan ','Rei ','Ka ','Atsu ','Yan ','She ','Shi ','Sa ', + 'Pang ','','Kahu ','Gai ','Shitsu ','Ce ','Bou ','Tei ','Rin ','Sha ','Kou ','Ting ','Shi ','Saku ','Hi ','Gen ', + 'Shi ','Gen ','Xiang ','Yan ','Reki ','Ketsu ','Ka ','Ten ','Zu ','Kyuu ','Kin ','Gou ','Ki ','En ','Shi ','Reki ', + 'Shou ','Lan ','Rei ','Gen ','En ','Gen ','Shi ','Kou ','Rin ','Jiu ','Kyo ','Kyo ','Uk ','Rui ','Du ','Xian ', + 'Sen ','San ','San ','San ','San ','San ','Ai ','Tai ','Yuu ','Sha ','Kyuu ','Yuu ','Sou ','Han ','Shuu ','Kai ', + 'Hatsu ','Fa ','Jaku ','Shi ','Shuku ','Tetsu ','Shu ','Ju ','Hen ','Jo ','Ka ','Han ','Sou ','Kou ','I ','Sou ', + 'Chou ','Ei ','Sou ','Kou ','Ko ','Ku ','Rei ','Ka ','Tou ','Kou ','Shi ','Kyou ','Shou ','Hatsu ','Tei ','Ka ', + 'Dai ','Shitsu ','Shi ','U ','Qiu ','Ha ','Kyou ','Gou ','Shi ','Iu ','Kamasu ','Roku ','Chou ','Ji ','Duk ','Hong ', + ], + 'x54':[ + 'Mie ','Ku ','Bou ','Kitsu ','Kaku ','Ten ','You ','Zi ','Gou ','Kichi ','Chou ','Sun ','Dou ','Mei ','Kou ','Ri ', + 'To ','Kou ','Ta ','Ka ','Se ','Ryo ','A ','Ma ','Gou ','Kuu ','I ','Kun ','Chuu ','Rin ','Don ','Gin ', + 'Hai ','Hitsu ','Shin ','Shin ','Kai ','Hou ','Hi ','Ha ','Ton ','Fun ','Guu ','Gan ','Kin ','Kou ','Sen ','Kei ', + 'Kou ','Shi ','Shin ','Go ','Go ','Byou ','Totsu ','Ketsu ','Kyuu ','Sui ','Tou ','Fun ','Kou ','In ','Go ','Koku ', + 'Ga ','Kin ','Ryo ','Aku ','Koku ','Bai ','Bou ','Kei ','Tei ','Go ','Koku ','Hu ','Kyou ','Un ','Seki ','Shou ', + 'Totsu ','Don ','Fu ','Yi ','Dai ','Ou ','Li ','Bai ','Yuan ','Kuai ','','Qiang ','Wu ','E ','Shi ','Gen ', + 'Hon ','Bun ','Ji ','Bou ','Rei ','Zen ','Iu ','Tei ','Shuu ','Shi ','Ju ','Tehu ','Ki ','Ei ','Ki ','Hei ', + 'Shi ','Ko ','Shi ','Mi ','Ku ','Ka ','Do ','Kou ','Hi ','Itsu ','Kyou ','Shin ','Ko ','Mei ','Tatsu ','Ka ', + 'So ','Kan ','Sou ','Ta ','Totsu ','Tou ','Hou ','Hetsu ','Hutsu ','Au ','Wa ','Saku ','Wa ','Kai ','Kyuu ','Ei ', + 'Ho ','Da ','Shu ','Wa ','Rou ','Ko ','Ka ','Zuo ','Bu ','Long ','Dong ','Ning ','Ta ','Si ','Xian ','Kaku ', + 'Shuu ','Ji ','Gaku ','Kou ','Ta ','Ki ','I ','Retsu ','Shi ','Bi ','Bi ','Shi ','Kou ','Kitsu ','Tou ','Kaku ', + 'Shutsu ','Satsu ','Shou ','Gai ','Kai ','Kuu ','Kuui ','Tau ','Kan ','Atsu ','Ken ','Ku ','Ka ','In ','Rou ','I ', + 'Ai ','Hin ','Shin ','Tou ','Kou ','Kou ','Shi ','Ai ','Gou ','Sai ','Iku ','Tetsu ','Pai ','Kyou ','Gai ','Kon ', + 'Kuang ','Ya ','Da ','Xiao ','Bi ','Yue ','','Hua ','Sasou ','Kuai ','Duo ','','Ji ','Nong ','Mou ','Yo ', + 'Kou ','In ','Rou ','Pou ','Bou ','Ka ','Ga ','Ka ','Shou ','Ri ','Da ','Shoku ','Ka ','Koku ','Kou ','Ken ', + 'Rou ','Hotsu ','Tetsu ','Tatsu ','Liang ','Ba ','Ba ','Retsu ','Sai ','Fou ','Ho ','Kan ','Kou ','Kou ','Yatsu ','Ka ', + ], + 'x55':[ + 'Iu ','Gen ','Gu ','Koku ','Bai ','Kan ','Sa ','Shin ','Ou ','Kai ','Kyou ','To ','Sen ','Kan ','Ri ','Ki ', + 'Tou ','Zei ','Shuu ','Che ','Go ','Sou ','A ','Tou ','Kei ','Teki ','Shin ','Ma ','Mal ','Kou ','Dou ','Kes ', + 'Lao ','Ryou ','Suo ','Zao ','Kan ','Laang ','Sha ','Soku ','Zuo ','Wo ','Hou ','Gin ','Ka ','Ki ','Shuu ','Yui ', + 'Setsu ','Shou ','Ji ','Rei ','Kyou ','An ','Sha ','Yo ','Ten ','Yo ','Tian ','Rai ','Sahu ','Seki ','Da ','Kotsu ', + 'Gai ','Tou ','Nou ','Shuu ','Taku ','Taku ','Shou ','Teki ','Kou ','Ran ','A ','Kyou ','Kou ','Ton ','Go ','Mon ', + 'Sai ','Sou ','Kotsu ','Kei ','Kei ','Tou ','Tan ','Tan ','En ','Shi ','Hi ','Sai ','Setsu ','Ka ','A ','Kei ', + 'Tetsu ','Hai ','Ryou ','Kan ','Hi ','Sha ','Rahu ','Ze ','Qing ','Gua ','Pa ','Zhe ','Se ','Zhuan ','Gou ','Kaku ', + 'Luo ','Yan ','Di ','Quan ','Tan ','Bo ','Ding ','Lang ','Xiao ','Geoi ','Tang ','Shi ','Tei ','Gan ','Shuu ','Tan ', + 'Kaku ','Gyou ','Ki ','Nan ','Zen ','Yu ','Tetsu ','Ratsu ','Kai ','Kou ','Kan ','Chou ','Shuku ','Sai ','Ka ','Sha ', + 'Yu ','In ','San ','Eu ','Aku ','Ben ','Hu ','Gin ','Zen ','Kai ','Kan ','Kan ','Ki ','Katsu ','Soku ','Ki ', + 'Zhong ','I ','Tehu ','Ku ','Kou ','To ','Jou ','Ken ','Ryou ','Yu ','Sou ','Kitsu ','Kyou ','Gen ','Tan ','Pen ', + 'Kuu ','Ri ','Yaku ','Sa ','I ','Miao ','Ei ','Pen ','Phos ','Kui ','Xi ','Yu ','Jie ','Lou ','Ku ','Sou ', + 'Kaku ','Tei ','Eu ','Kou ','Sa ','Kyuu ','Shou ','Shoku ','You ','So ','Kou ','Kyou ','Eki ','Saku ','Ba ','Sa ', + 'Katsu ','Kahu ','Tou ','Sou ','Shin ','Shoku ','Shuhu ','Atsu ','Kei ','Hou ','O ','Ken ','Shi ','Kaku ','Shi ','Sa ', + 'Luo ','Rou ','Ratsu ','Shi ','Shi ','Kou ','Sa ','Garon ','Kai ','Sa ','Qin ','Nie ','He ','Cis ','Sai ','Ng ', + 'Ge ','Na ','Dia ','Ai ','','Tong ','Hitsu ','Gou ','Gou ','Ren ','Sui ','Sha ','Baku ','Soku ','Sou ','Tan ', + ], + 'x56':[ + 'Saku ','Sahu ','Kyou ','Chong ','Keu ','Kai ','Tan ','San ','Sau ','Ka ','Gai ','Xiao ','Heu ','Rou ','Katsu ','Ka ', + 'Hau ','Ko ','Kei ','Kaku ','Ou ','Ken ','Saku ','Shou ','Kyo ','Ha ','Toku ','Ma ','Ba ','Hu ','Roku ','To ', + 'Katsu ','Tang ','Ye ','Beng ','Ying ','Saai ','Jiao ','Mi ','Shou ','Ka ','Bai ','Dam ','Sai ','Hou ','Tou ','Shou ', + 'Ki ','Shoku ','Tou ','Ki ','Shi ','Keu ','Sei ','Kou ','Bu ','Reu ','Kyou ','Ki ','Kyuu ','Tan ','Tan ','Boku ', + 'Son ','O ','Son ','Han ','Kitsu ','Ki ','Sou ','Tou ','Shuku ','Tan ','Itsu ','Ton ','Sou ','Seu ','Itsu ','Kyuu ', + 'Ki ','Hao ','Lian ','Kyo ','Tou ','Ki ','Yin ','Boku ','Ketsu ','Kin ','Eibiro ','Gou ','Lu ','Si ','Gen ','You ', + 'Tatsu ','Sen ','Iku ','Chu ','Kin ','Dou ','Etsu ','Hui ','Ki ','Kaku ','Sou ','I ','Zei ','Kyou ','En ','Ai ', + 'You ','Kyaku ','Kuwai ','Gu ','Fun ','Dou ','Katsu ','Kin ','Ton ','Tou ','Hanashi ','Sai ','Pi ','Pi ','In ','Sui ', + 'Dei ','Teki ','Ran ','Tou ','Kaku ','Ju ','Kou ','Kaku ','You ','Duo ','Hi ','Chuu ','Sei ','Shin ','Kau ','Tei ', + 'Shou ','','','Ca ','Tei ','Ro ','Hui ','Haku ','Iu ','Gou ','Gin ','Hu ','Bi ','Kaku ','Tetsu ','Ri ', + 'Ryuu ','Haai ','Nou ','Xiao ','Mo ','En ','Reki ','Ro ','Rou ','Haku ','Tan ','Shin ','Hin ','Hi ','Kou ','Huo ', + 'Mo ','Ki ','Ta ','Koku ','Gen ','San ','Ou ','Jau ','Dian ','La ','Ta ','Gou ','Shaku ','Setsu ','Kan ','Huo ', + 'Ten ','Shou ','Gou ','Sou ','Li ','Ten ','Tai ','Li ','Gei ','Ra ','Nou ','Satsu ','So ','Xi ','So ','Kan ', + 'Satsu ','Shoku ','Lan ','Ketsu ','Dou ','Trom ','Lo ','I ','Kai ','In ','Shuu ','Shi ','Jin ','Ken ','Kai ','Shin ', + 'In ','Juu ','Shuu ','Dan ','Ton ','Kou ','En ','Kei ','Hen ','Yun ','Sou ','Kotsu ','Kai ','Gan ','Ka ','Koku ', + 'Kon ','Sou ','I ','To ','Wei ','Lun ','Koku ','Kin ','Ri ','Rei ','Ko ','Koku ','Tai ','Koku ','Tu ','Yuu ', + ], + 'x57':[ + 'Koku ','Gin ','Kon ','Ho ','Gyo ','Kan ','Yuan ','Rin ','Ken ','Gyo ','Sei ','Koku ','Sen ','I ','En ','Ken ', + 'Ku ','Ho ','En ','En ','Ou ','Toshokan ','To ','To ','Dan ','Lue ','Kai ','Eki ','Kan ','Ran ','Ran ','Do ', + 'Atsu ','Tu ','Tei ','Kutsu ','Haku ','Roku ','Iri ','Atsu ','Zai ','U ','Gitsu ','Au ','O ','Kei ','Hi ','I ', + 'Chi ','Qian ','Qian ','Shiu ','Shaku ','Dang ','Qia ','Akutsu ','Yama ','Kuang ','Chang ','Ki ','Nie ','Botsu ','Gyuu ','Katsu ', + 'Shi ','Shi ','Han ','Xun ','Tou ','Kin ','Bai ','Kin ','Keng ','Ton ','Bou ','Hun ','Hon ','Tan ','Kan ','Hai ', + 'Za ','Kou ','Hi ','Xing ','Di ','Jing ','Ji ','Kai ','Di ','Kei ','Ken ','Tan ','Li ','Ba ','Wu ','Fen ', + 'Zhui ','Ha ','Han ','Tang ','Kon ','Sho ','Tan ','Seki ','I ','Kan ','Hei ','Ten ','Ka ','Dei ','Dai ','Hi ', + 'Kei ','Au ','Hutsu ','Au ','Riku ','Kyou ','Boku ','Ka ','Gou ','Ketsu ','Hatsu ','Chi ','Taku ','Rei ','Cho ','Fu ', + 'Ko ','Chi ','Sui ','Ratsu ','Long ','Long ','Lu ','Ao ','Tai ','Hou ','','Kei ','Tou ','Ji ','Ke ','Rotsu ', + 'Shi ','Chi ','Lei ','Gai ','Shyou ','Kou ','Dui ','Teu ','Huku ','Kuu ','Geu ','Da ','Da ','Ki ','Ta ','You ', + 'Gin ','Hatsu ','Kou ','En ','Tetsu ','Keu ','Ken ','Kei ','Shu ','Sei ','Ha ','Dian ','Kyou ','Wu ','Kua ','', + 'Tao ','Dang ','Kai ','Gake ','Nao ','An ','Sei ','Xian ','Kan ','Hou ','Hu ','Hai ','Eki ','Gin ','Kan ','Sho ', + 'Sui ','Shin ','Kau ','Ai ','Hou ','Fang ','Kaku ','You ','Shun ','Jia ','Di ','Mai ','Rou ','Xuan ','Jou ','Sen ', + 'Shin ','Zhe ','Rachi ','Rachi ','Ho ','Tei ','Gomi ','Bu ','Shi ','Xun ','Guo ','Jiong ','Sho ','Ten ','Tei ','Iki ', + 'Fu ','O ','Ken ','Sai ','Hi ','Sei ','Wan ','Ku ','Lun ','Sau ','Kong ','Shou ','Tou ','Tai ','Tan ','En ', + 'Sai ','Shyuu ','Hou ','Kan ','Shoku ','Ta ','Gei ','Shitsu ','Eki ','Bai ','Ki ','Shun ','Ki ','Sou ','Shu ','Dei ', + ], + 'x58':[ + 'Kutsu ','Ka ','Dou ','Kon ','Gen ','Ken ','Tai ','Kin ','Kou ','Iku ','A ','Hou ','Ko ','To ','Leng ','', + 'Ya ','Qian ','','An ','','Da ','Nao ','Tu ','Shou ','In ','Hun ','Hiyoku ','Ren ','Ka ','Teu ','Ten ', + 'Kou ','Hou ','Bao ','Gu ','Tei ','Bou ','Kai ','Zen ','Getsu ','Kou ','Kan ','Zong ','Yu ','Kau ','Gaku ','Gyou ', + 'En ','Hou ','Shitsu ','Bi ','Jou ','To ','Ku ','An ','Hu ','Shou ','Kai ','Shin ','Kou ','Kou ','Chuan ','Kan ', + 'Hei ','Rui ','Xiang ','Huang ','Leng ','Duan ','','Xuan ','Ki ','Seki ','Kai ','Ei ','Tou ','Shou ','You ','Kai ', + 'So ','So ','Shi ','Beki ','Tou ','Ou ','Shou ','To ','Tou ','Kaku ','Chou ','Ritsu ','Hou ','Hau ','Soku ','Sou ', + 'Dui ','Ten ','O ','Tei ','Ken ','Kaku ','Zhen ','Ai ','Kyou ','En ','Kan ','Ten ','Yuan ','Wen ','Xie ','Liu ', + 'Ama ','Lang ','Jou ','Peng ','Hou ','Jin ','Koku ','Lu ','Ou ','Zan ','Bai ','Baku ','Sen ','Sau ','Juku ','Rou ', + 'Chi ','Ban ','Hyou ','Kyou ','Soku ','Sho ','Tetsu ','Shou ','Kan ','You ','Ten ','Shin ','Shaku ','Ki ','Kuwaku ','Shou ', + 'Kin ','Teki ','Shou ','Bo ','Sai ','Yan ','Tou ','Zou ','Qi ','Qiang ','Liang ','','Tsui ','Kou ','Zou ','Kyo ', + 'Sen ','Sen ','Hatsu ','Haku ','Kuai ','Tou ','Han ','Que ','Boku ','Ton ','Dun ','Shun ','Chi ','Sei ','Da ','Da ', + 'Tan ','Tou ','Bo ','Fun ','Huang ','Tan ','Da ','Ye ','Sho ','Mama ','Ou ','Shou ','Keki ','Kau ','Kon ','Eki ', + 'Pi ','Heki ','Ten ','Jiang ','Ya ','You ','Kaku ','Dan ','On ','Kyo ','Kai ','Dang ','Jou ','Zan ','Ken ','Kan ', + 'Shi ','Gaku ','Ai ','Atsu ','Tau ','Gou ','Zen ','Mama ','Rui ','Kou ','Ro ','En ','Tan ','I ','Kai ','Ryou ', + 'Rou ','Ei ','Reki ','Rin ','Jou ','Ten ','Xun ','Gan ','Rai ','Ha ','','Shi ','Jin ','','Sou ','Sou ', + 'Sei ','Ichi ','Bai ','Kaku ','Shu ','Zhuang ','Hu ','Ko ','Kon ','Ichi ','Ko ','Sei ','Kon ','Ju ','Bou ','Shun ', + ], + 'x59':[ + 'Shou ','Yi ','Chi ','Ko ','Chu ','Kou ','Hou ','Bei ','Cay ','Hen ','Sui ','Shun ','Ryou ','Fu ','Sa ','Ka ', + 'Kei ','','Dou ','Ka ','Ki ','Seki ','Gai ','En ','Bou ','Shuku ','Ta ','Ta ','Ya ','Sei ','Uys ','Gou ', + 'Kou ','Ki ','Mu ','Bou ','In ','Ka ','Chen ','Tai ','Shoku ','Ten ','Ta ','Fu ','Ketsu ','You ','Ou ','Kou ', + 'Kou ','Shitsu ','Tou ','Tai ','Tou ','En ','Hi ','I ','Ko ','Jia ','Duo ','Kwu ','Kuang ','Yun ','Kou ','Ha ', + 'Bou ','Lian ','Huan ','Tei ','En ','Hou ','Ken ','Ki ','Na ','Hou ','Xie ','Fen ','Ten ','','Kei ','Sou ', + 'Kan ','Setsu ','Kai ','Ta ','Hon ','Eki ','Jiang ','Tou ','Jou ','Hon ','Kei ','Kou ','Hi ','Chou ','Shun ','Kou ', + 'Ten ','Gau ','Sha ','Wan ','Pan ','Ou ','Wu ','Ou ','Shou ','Ren ','Datsu ','In ','Shou ','Seki ','Fun ','Katsu ', + 'Hi ','Ren ','Sha ','Jo ','Do ','Tei ','Dai ','Sen ','Kan ','Chi ','Jiu ','Dan ','Ta ','Kou ','Sen ','Gan ', + 'Ji ','Shaku ','Jo ','Hi ','Bou ','Kou ','Zhuang ','Fu ','Ma ','Dan ','Nin ','Fu ','Sei ','Ken ','Kai ','Bun ', + 'Shou ','Pa ','To ','Ki ','Keng ','Chuu ','You ','Sen ','Un ','Myou ','Huu ','Shi ','Yue ','Sou ','Juu ','An ', + 'Dou ','Kin ','Hun ','Hi ','Yo ','Da ','Hou ','Gen ','Bou ','Wu ','Yu ','Gui ','To ','Hatsu ','Ji ','Chuu ', + 'Chaku ','Shou ','Datsu ','Dai ','En ','Tou ','Ken ','Chitsu ','A ','Mai ','Batsu ','Sai ','Hi ','Shin ','Shou ','E ', + 'Ka ','Ku ','Fa ','Sei ','Bin ','Han ','Bo ','Hu ','Rei ','Shi ','Shi ','Shi ','Zen ','San ','Au ','Ban ', + 'So ','Ko ','Shi ','Sei ','I ','Zi ','Kyo ','San ','Hin ','Nin ','You ','Tou ','Kyou ','Su ','Kitsu ','Kai ', + 'Shou ','Katsu ','Ken ','Kou ','Kou ','Bo ','Kan ','Kan ','I ','Den ','Tetsu ','Ki ','Ki ','Ken ','Kou ','Kou ', + 'Jun ','Ka ','An ','Bei ','Retsu ','Hai ','Ou ','Yuu ','Ken ','Ta ','Shin ','In ','Shi ','Ki ','Sen ','Shi ', + ], + 'x5a':[ + 'Shuu ','I ','Hong ','A ','Ru ','Ya ','Rao ','Jiao ','Luan ','Hei ','Ken ','Shao ','Ri ','Sei ','Ketsu ','Bou ', + '','Sha ','Bo ','Bi ','Ke ','Saku ','Saku ','Tei ','Jou ','Gou ','Nan ','Go ','Da ','Pei ','Dai ','Ken ', + 'Shin ','Zhi ','Han ','Tei ','Sou ','Ga ','Pin ','Tai ','Ban ','Ben ','Go ','Yan ','Bu ','Ki ','Den ','Go ', + 'Ji ','Yu ','Wa ','','Xian ','Shu ','Shu ','Tsui ','Ki ','Ken ','Zhui ','Dong ','Shou ','Lu ','Gai ','A ', + 'A ','Rou ','Ben ','Sou ','Hou ','Kiku ','Ba ','Sai ','Ryou ','En ','Hyou ','Xiao ','Shuku ','Ki ','Hui ','Fu ', + 'Wa ','Zui ','Tan ','Hi ','','Shou ','Ten ','Gei ','Ken ','Jing ','Kon ','Kei ','Kan ','Ten ','Kei ','Ko ', + 'Wan ','Lai ','Hi ','In ','Shuu ','Dou ','Fu ','Sei ','Lun ','Gen ','Ran ','Kun ','In ','A ','','Li ', + 'Ten ','Xian ','Hwa ','Kaku ','Ying ','Chan ','Shen ','Tei ','Tou ','Yao ','Bu ','Dan ','Shaku ','Ka ','Tou ','Sei ', + 'Yu ','Wei ','Ti ','Juu ','Bi ','Dan ','Ruan ','Qin ','','Wu ','Sen ','Shun ','Bou ','Fu ','So ','Tan ', + 'Ki ','Zhong ','Bai ','Kou ','Ben ','En ','Ei ','Ken ','','I ','Bi ','En ','Tei ','Shuu ','Shi ','Setsu ', + 'Ta ','Lian ','Bou ','Ran ','Shi ','Hen ','I ','Kai ','Jiu ','Ko ','Ou ','','Ho ','Shu ','Tou ','Gui ', + 'Shiu ','Eu ','Hei ','Seki ','En ','You ','Jou ','Joku ','Shi ','Riu ','Bi ','Han ','Ou ','Bo ','Kou ','Ki ', + 'Shin ','Ka ','Sou ','Zhen ','Gen ','Cha ','You ','Bei ','Seu ','Shitsu ','So ','Jou ','Ken ','Tau ','Pang ','Rou ', + 'Jou ','Bao ','Ai ','Pi ','Pin ','Ei ','Hyou ','Ou ','Rui ','Seb ','Ban ','Ei ','Shau ','Kau ','Shou ','Jiyuku ', + 'Ri ','Chaku ','Ki ','En ','Jin ','Sen ','Kou ','Ce ','Kan ','Don ','Rau ','Bo ','Sha ','Ko ','Ko ','Ao ', + 'Nen ','Qiang ','Maa ','Hetsu ','Ko ','Bu ','Seu ','Ta ','Sen ','Bau ','Kan ','Kan ','Mo ','Reu ','Lian ','Kaku ', + ], + 'x5b':[ + 'Ki ','Tou ','Shoku ','Shu ','','Kuwa ','Xi ','Kuwai ','Deu ','Ki ','Yan ','Sen ','Kyou ','Bi ','Han ','Han ', + 'Sen ','Yi ','Wei ','Keu ','Hu ','Shi ','Hei ','Sen ','Sui ','Shou ','Ren ','Ken ','','Jou ','Tou ','Yi ', + 'San ','Ai ','Jou ','Tau ','Ba ','Chou ','Chiu ','Shin ','Shi ','Yu ','Hin ','','Shu ','Dai ','En ','Tai ', + 'Ei ','Can ','Jou ','','Ei ','Mian ','Kaka ','Ba ','Shin ','Xing ','Ni ','Du ','Riwa ','En ','Ran ','En ', + 'Sou ','Rei ','Jiao ','Jou ','Lan ','Sen ','Ying ','Sawa ','Sui ','Quan ','Mi ','Ri ','Ren ','Gen ','Shoku ','Lan ', + 'Shi ','Getsu ','Ketsu ','Jue ','Kou ','You ','Shi ','Ji ','Son ','Sun ','Fu ','Botsu ','Shi ','Kou ','Shin ','Mou ', + 'Si ','Tai ','Bao ','Ki ','Ko ','Do ','Gaku ','','Sen ','Kai ','Luan ','Son ','Huai ','Mie ','Sou ','Kan ', + 'Juku ','Sen ','A ','Shi ','Ni ','Fu ','Shi ','Ri ','Gaku ','Bo ','Ju ','Dai ','Getsu ','Getsu ','Ei ','San ', + 'Ben ','Cho ','Rong ','Ta ','Ki ','Taku ','Kyou ','U ','Shu ','An ','Totsu ','Sou ','Kan ','Niku ','Eu ','Kou ', + 'Gi ','Sei ','Chun ','Bitsu ','Shu ','Tou ','Kou ','Shuu ','Kan ','Chuu ','Tei ','En ','Gi ','Hou ','Shi ','Jitsu ', + 'Chong ','Shen ','Kyaku ','Sen ','Shitsu ','Yuu ','Kan ','Yi ','Tewa ','Shi ','Xian ','Kyuu ','Sei ','Kun ','Kyuu ','Kou ', + 'Sai ','Sa ','Hou ','Gai ','En ','Shou ','Ka ','Shin ','Shin ','You ','Kou ','Mitsu ','Kou ','Kuan ','Bin ','Shuku ', + 'Sai ','San ','Jaku ','En ','Ki ','In ','Mitsu ','Kou ','Qing ','Kaku ','Tei ','Ken ','Fu ','Nei ','Hei ','Kan ', + 'Bi ','Shin ','Kan ','Guu ','Shoku ','Nei ','Shin ','Nei ','Shi ','Yu ','Hou ','Kan ','Nei ','Shin ','Baku ','Satsu ', + 'Ku ','Ka ','Shin ','Kotsu ','Go ','Ryou ','Jitsu ','Nei ','Sai ','Shin ','I ','Sha ','Kan ','Hui ','Ryou ','Shun ', + 'Kan ','Gei ','Gi ','Hou ','Shin ','Chou ','Hou ','Feng ','Sun ','Tai ','Ji ','Xun ','Dao ','Rin ','Tai ','Ju ', + ], + 'x5c':[ + 'Ha ','Fuu ','Sen ','Hu ','Sha ','Koku ','Shou ','Shou ','Sen ','I ','Son ','Jin ','Shu ','Tai ','Dou ','Shou ', + 'Setsu ','Shou ','Ji ','Ji ','Ji ','Ga ','Sen ','Shuku ','Chen ','Shou ','Shou ','','Ga ','Chang ','Ryou ','Sen ', + 'Sen ','','Ou ','Ou ','Yuu ','Ryou ','Ryou ','Yao ','Bou ','Ou ','Ou ','Ou ','Kai ','Gyou ','Ta ','Ki ', + 'Shou ','Shuu ','Kan ','Kotsu ','Gan ','Tai ','Kan ','Kan ','Shi ','In ','Shaku ','Kou ','Ni ','Jin ','Bi ','Nyou ', + 'Kyoku ','Hi ','Ceng ','Ki ','Hi ','Kyo ','Kai ','Ten ','Kutsu ','Ti ','Kai ','Oku ','Chou ','Shi ','Shi ','Hei ', + 'Geki ','Setsu ','Chen ','Ki ','Dei ','Ten ','Sei ','','Man ','A ','Rou ','Hei ','Tei ','Fei ','Zoku ','Tei ', + 'To ','Ru ','Ru ','Shi ','Sou ','Ri ','Ju ','Tei ','Ku ','Kyaku ','Ryou ','Kyaku ','Zoku ','Ki ','Sa ','Ton ', + 'Geki ','San ','','Sen ','Ryoku ','Gatsu ','Nata ','','Long ','Kitsu ','Ki ','Jin ','Gotsu ','Kan ','Shin ','Yu ', + 'Shutsu ','Sui ','Qi ','','Yue ','Han ','Eu ','Gou ','Ka ','Butsu ','Setsu ','Gou ','Kyuu ','Qian ','Fen ','Guwan ', + 'Ki ','Shin ','Ken ','Ki ','Sa ','Kai ','Qu ','Gang ','Xian ','Ao ','Lan ','Dao ','Ba ','Saku ','Zuo ','You ', + 'Kyo ','Kou ','Ke ','Kou ','Ketsu ','Ha ','Ryuu ','Teu ','So ','Gan ','Hutsu ','Shuu ','Kou ','Rei ','Ta ','Hi ', + 'You ','Tai ','Kou ','Gaku ','Ku ','Ko ','Haku ','Bin ','Gan ','Tiao ','Rei ','Ji ','Yuri ','Dong ','Sen ','Kui ', + 'Shuu ','Mao ','Tong ','Xue ','Yi ','Kura ','Kahu ','Kou ','Raku ','Gaku ','Hu ','Shun ','Tetsu ','Lu ','Gon ','Ji ', + 'Kai ','Quan ','Tou ','Yi ','Bo ','Shi ','An ','Gi ','Kan ','Ji ','Bitsu ','Ri ','Kei ','Tou ','Ki ','You ', + 'Touge ','Kyou ','Li ','Gyou ','Jiao ','Zheng ','Luan ','Jiao ','Ga ','Ga ','Yoku ','Ya ','Ho ','Shou ','Kin ','Hou ', + 'Hou ','Dou ','Ri ','You ','Ken ','Kou ','Tou ','Shin ','Sei ','To ','Kou ','Shun ','Hao ','Kyou ','Yin ','Yu ', + ], + 'x5d':[ + 'Lang ','Kan ','Lao ','Lai ','Ken ','Que ','Kou ','Suu ','Shuu ','Ta ','','Ka ','Ju ','Rai ','Ki ','Bin ', + 'Kon ','Kon ','Shutsu ','Gu ','Sai ','Gai ','Gai ','Kou ','Ron ','Ron ','Ryou ','Kutsu ','Duo ','Sau ','Guo ','Gin ', + 'Tou ','Kan ','Sou ','I ','Kou ','Hei ','En ','Shuu ','Sehu ','Hou ','Zu ','Kutsu ','Dong ','Zhan ','Gu ','Yin ', + '','Shoku ','Kou ','Yu ','Wai ','Seu ','Hou ','Shiu ','Ton ','Tei ','I ','Zhi ','Shi ','Sai ','Yao ','Gaku ', + 'Chiu ','Kan ','Ritsu ','Gen ','Mei ','Kan ','Kei ','Kei ','Kan ','Tei ','Shou ','Bi ','Kan ','Wu ','Guu ','Zong ', + 'Ran ','Ketsu ','Gan ','Gan ','Wei ','Sou ','Sa ','Sei ','Rong ','Yamashina ','Qin ','Yu ','Ki ','Lou ','To ','Ki ', + 'Gei ','Ou ','Sou ','Tau ','Kei ','Ketsu ','Ai ','Riu ','O ','Suu ','Kou ','Zi ','Kai ','Hou ','Dian ','Sa ', + 'Ken ','You ','Getsu ','Sa ','Ji ','','Tao ','Shou ','Zong ','Kyou ','Reu ','','San ','Tetsu ','Shin ','Tei ', + 'To ','Ru ','Shou ','San ','San ','Ao ','Sau ','Ku ','Shau ','Sui ','Sui ','Tou ','Tou ','Shihu ','Yu ','Bo ', + 'Ryuu ','Xiang ','Shou ','Ha ','Kin ','Seu ','Yan ','Lao ','Zhan ','Rin ','Ryou ','Ryou ','Shin ','Tou ','Ta ','Son ', + 'Kyou ','Kei ','Gyou ','Qiao ','Yao ','Jue ','Zhan ','Eki ','Kaku ','Dau ','Gyou ','Gyou ','Gi ','Gatsu ','Ken ','Shiu ', + 'Kai ','Katsu ','Kei ','Di ','Au ','Sai ','','Gi ','Kou ','Tou ','Rei ','Za ','Sho ','Gaku ','Yin ','', + 'Satsu ','Li ','Sui ','Rou ','Long ','Dian ','Kou ','Ki ','Ju ','San ','Ying ','Ki ','Gan ','Gi ','Dou ','Ken ', + 'Chou ','San ','Ran ','Ten ','Ten ','','Gan ','Yan ','Gen ','Ki ','Yan ','Sen ','Kai ','Sen ','Shuu ','Kou ', + 'Kei ','Jun ','Chao ','Sou ','Rehu ','Kou ','Sa ','Kou ','Kyo ','Kyou ','Kek ','Fu ','Pwu ','Pwu ','Shi ','Qiu ', + 'Qiu ','Ki ','I ','Shi ','Ha ','Shi ','Zhao ','Kou ','I ','Kin ','Son ','Kan ','Phas ','Son ','Kin ','Hutsu ', + ], + 'x5e':[ + 'Sou ','Bi ','Shi ','Fu ','Tei ','Shuai ','Han ','Den ','Shi ','Fen ','Ha ','Shi ','Ki ','Ko ','Tan ','Wei ', + 'Zhang ','Do ','Tai ','Ma ','Hi ','Batsu ','Jou ','Fu ','Ren ','Chitsu ','Sou ','Haku ','Zhi ','Tei ','Mo ','Eki ', + 'Gei ','Hei ','Kahu ','Ken ','Geyo ','Sotsu ','Tai ','Zheng ','Sei ','Seu ','Zhen ','Shi ','Kun ','Seki ','Hou ','Tai ', + 'Ki ','Chou ','Hei ','Chou ','Satsu ','Wan ','Tai ','I ','Jou ','Sha ','Qi ','Ze ','Guo ','Bou ','To ','Hou ', + 'Tei ','Su ','Beki ','I ','Aku ','Fuku ','Yi ','Hou ','Hei ','Tazuna ','Kou ','Han ','Kou ','Tou ','Beki ','Ka ', + 'Tou ','Ki ','Zhong ','Shin ','Ban ','Maku ','Hyou ','Kaku ','Saku ','Baku ','Hou ','Shou ','Kei ','Sen ','Hoku ','Shi ', + 'Ko ','Han ','Tou ','Hei ','Hei ','','Beki ','Seu ','Sen ','Hun ','Bou ','Hou ','Chuu ','Betsu ','Chu ','Setsu ', + 'Ken ','Ran ','Kan ','Hei ','Nen ','Ken ','Hei ','Hei ','Kou ','Kan ','You ','Gen ','You ','Yuu ','Ki ','Gen ', + 'Hi ','Chou ','Shoku ','Kou ','Sou ','Mo ','Qing ','Hi ','Kin ','Ton ','Shou ','Ki ','Ga ','Hai ','Kai ','Jo ', + 'Lu ','Wu ','','Ku ','Ying ','Tei ','Hou ','Ten ','Ya ','Miao ','Kou ','Shi ','Fu ','Tong ','Pang ','Fei ', + 'Shou ','Yi ','Chitsu ','Teu ','Chi ','Kyuu ','Taku ','Za ','Kou ','Tu ','Ki ','Ko ','Bou ','Tei ','Iu ','Ho ', + 'Hei ','Chou ','Rai ','Hi ','Seki ','An ','Sho ','Kou ','You ','Tuo ','Song ','Sho ','Qing ','Dou ','Yu ','Byou ', + 'Sou ','Shi ','Shou ','Hai ','Jiu ','Ahu ','Kai ','Riu ','Ka ','Ren ','Rou ','Shuu ','Chi ','Pou ','Kei ','Jiu ', + 'Kyuu ','Kin ','Gou ','Kaku ','Rou ','In ','Ryou ','Tai ','Roku ','Yoku ','Zu ','Ten ','To ','Shi ','Kin ','Byou ', + 'Shou ','Bu ','Hai ','Kou ','Koc ','Kai ','Heki ','Shau ','Kai ','Rin ','Rin ','Ryou ','Ryo ','','Ei ','Sen ', + 'Chou ','You ','Rei ','Chou ','In ','Jun ','En ','Tei ','Teki ','Po ','Ken ','Kai ','Dai ','Kai ','Kyou ','Juu ', + ], + 'x5f':[ + 'Kai ','Ben ','I ','Ki ','Rou ','Hun ','Kyo ','En ','Eki ','Jou ','Hei ','Yoku ','Itsu ','Ni ','San ','Shiki ', + 'Ni ','Shi ','Shi ','Kyuu ','Chou ','In ','Te ','Futsu ','Kou ','O ','Tai ','Shi ','Kyou ','Ha ','Shen ','Tei ', + 'Zhang ','Kutsu ','Tou ','Hu ','Tei ','Mi ','Gen ','Ko ','Seu ','Do ','Jing ','Shin ','I ','Bi ','Ken ','Wan ', + 'Sou ','Jaku ','Xuan ','Jing ','Ton ','Chou ','Gyau ','Kyou ','Hou ','Dan ','Kyou ','Hitsu ','Hitsu ','You ','Dan ','Ken ', + 'Kou ','Sei ','Hotsu ','Hitsu ','Kou ','Nagi ','Bie ','You ','Dan ','Kuwaku ','Kyou ','Kau ','Bi ','Kuwaku ','Wan ','Kuwaku ', + 'Kei ','Kei ','Gui ','Tou ','Roku ','Lu ','Tan ','Sui ','Tei ','I ','I ','I ','I ','I ','I ','Kaku ', + 'Kuwaku ','San ','Kei ','Bun ','Tou ','Gen ','Gen ','Iku ','Chi ','Sai ','Hyou ','Chou ','Hin ','Hou ','Yong ','Heu ', + 'Shou ','Ei ','Chi ','Teki ','Shaku ','Ta ','Kihu ','Hou ','Shou ','Yaku ','Ou ','Che ','Hi ','Chi ','Rei ','Futsu ', + 'Ou ','Sei ','So ','Ou ','Kei ','Tai ','Sei ','Shun ','Kon ','You ','Kai ','Ritsu ','Go ','Ai ','Cheng ','Choku ', + 'Jo ','Kei ','To ','Juu ','','Lai ','Sou ','Toku ','Hai ','Shi ','','Ki ','Shou ','Chi ','Juu ','Zhou ', + 'Rai ','Gyo ','Shou ','Jie ','Takeshi ','Chi ','Jia ','Hen ','Kou ','Fuku ','Jun ','I ','Hou ','You ','Bi ','Kei ', + 'Sei ','Hyou ','Chi ','Toku ','Chou ','Chou ','Bie ','Toku ','Shou ','Tetsu ','Jiao ','Wei ','Kyou ','Ki ','Mei ','Long ', + 'Xiang ','Bao ','Qu ','Shin ','Ritsushinben ','Hitsu ','Yi ','Roku ','Jin ','Tou ','Ding ','Kai ','Ki ','Nin ','Ren ','Chan ', + 'Kun ','Toku ','Toku ','Kan ','Kitsu ','Shi ','Son ','Shi ','Bou ','Bou ','Xi ','Fan ','Ou ','Ten ','Bin ','Min ', + 'Chuu ','Chuu ','Go ','Ji ','Go ','Xi ','Ye ','You ','Gan ','Sou ','Shou ','Kai ','Yo ','Hen ','Shi ','Ki ', + 'Sui ','Shin ','Tai ','Ton ','Qian ','Nen ','Kon ','Kyou ','Jiku ','Wang ','Ken ','Kin ','Kou ','Kotsu ','Kai ','Fun ', + ], + 'x60':[ + 'Huai ','Tai ','Song ','Wu ','Ou ','Chang ','Chuang ','Kyo ','Yi ','Bao ','Chou ','Min ','Pei ','Saku ','Shin ','You ', + 'Kou ','Ban ','Do ','Dou ','Sei ','Ha ','Fu ','Chou ','Ko ','Ko ','Sho ','Datsu ','Rei ','Shi ','Chou ','Tei ', + 'Tai ','I ','Tu ','You ','Hu ','Kyuu ','Hou ','Sei ','En ','Ji ','Kai ','Futsu ','Xi ','Hitsu ','You ','Kyou ', + 'Xuan ','Sou ','Bing ','Kyou ','Xu ','Jutsu ','Pi ','Xi ','Xi ','Tan ','Koraeru ','Zong ','Dui ','','Ki ','Yi ', + 'Shi ','In ','Jun ','Ji ','Xi ','Lao ','Kou ','Kyou ','Bou ','Shi ','Kyou ','Ren ','Chou ','Kou ','Die ','Hao ', + 'Kyou ','Ki ','Kou ','Xi ','Kyou ','Jo ','Shi ','Ko ','Qiu ','You ','I ','Hui ','Chi ','Kai ','Yi ','Kyou ', + 'Kai ','Rin ','Kai ','Shi ','Jutsu ','Chi ','Xiang ','Jiku ','Kon ','On ','Kaku ','Dou ','Ten ','Kyou ','Quan ','Soku ', + 'Kou ','Etsu ','Peng ','Ken ','De ','Kei ','E ','Kyuu ','Tong ','Yan ','Kai ','Ce ','Nao ','Yun ','Bou ','You ', + 'Yong ','En ','Hi ','Kon ','Shou ','Etsu ','Yo ','Yu ','Kai ','Shitsu ','Tetsu ','Rin ','Tei ','Kan ','Kou ','Qie ', + 'Ti ','Ho ','Yuu ','Ken ','Kai ','Ki ','Hai ','Ban ','I ','Heng ','Shou ','Sen ','Cheng ','Kai ','Go ','Go ', + 'Yuu ','Li ','Ryou ','Kan ','Sou ','Yoku ','Etsu ','Ri ','Ji ','Nou ','Aku ','Que ','Xuan ','Qian ','Wu ','Min ', + 'Sou ','Hi ','Hi ','Toku ','Sui ','Chou ','Mon ','Rei ','Ki ','Guan ','Guan ','Kei ','Tou ','Sei ','Kou ','Tian ', + 'Lun ','Xi ','Kan ','Kun ','Deki ','Jou ','Chuu ','Ton ','Ka ','Sen ','Ryou ','Wan ','Yuan ','Jin ','Ki ','Ran ', + 'Yu ','Waku ','He ','Ken ','Tan ','Teki ','Teki ','Nie ','Bou ','Tetsu ','Kotsu ','Kon ','Seki ','Shou ','Kin ','I ', + 'Kei ','O ','Sa ','Sou ','Jian ','You ','Dian ','Ku ','San ','Cheng ','Toku ','Bei ','Qie ','Can ','Dan ','Guan ', + 'Da ','Nou ','Un ','Sou ','Zui ','Chou ','Kou ','Shun ','Kei ','Ja ','Sei ','Soku ','Hen ','Kon ','Zong ','Ti ', + ], + 'x61':[ + 'Shou ','Shuu ','Botsu ','Ken ','Wei ','Ge ','Ken ','I ','Yu ','Yu ','Hyoku ','Xuan ','Kan ','Bin ','Hyoku ','I ', + 'Ben ','You ','Kei ','Tou ','In ','Gaku ','Shin ','Bou ','Ke ','Kaku ','Gu ','Ai ','Kyou ','Yan ','Zen ','Kan ', + 'Un ','Sou ','Sai ','Leng ','Fen ','','Kui ','Ki ','Kaku ','Gong ','Un ','So ','So ','Qi ','Yao ','Song ', + 'Kau ','Shitsu ','Gu ','Ju ','Sou ','Deki ','Kyou ','Kai ','Zheng ','You ','Cao ','Sun ','Shin ','Haku ','Ki ','Gen ', + 'Xie ','Kon ','You ','Yang ','Ritsu ','Sou ','Tou ','In ','Ji ','Kin ','Ken ','Tai ','Kou ','Un ','Shin ','Ming ', + '','She ','Cong ','Hyou ','Mo ','Bo ','Guo ','Chi ','San ','Zan ','Zan ','Cui ','Min ','Toku ','Shou ','Dou ', + 'Gou ','Shuang ','Man ','Kan ','Que ','Zou ','Jiu ','Kei ','Gai ','Lian ','Ou ','Shou ','Kin ','Gin ','Ryo ','Shou ', + 'I ','Tan ','Ban ','Kan ','Shou ','You ','Kei ','Kou ','Tei ','Zhi ','Lou ','Ken ','Seki ','Qi ','Yoku ','Hyou ', + 'Ryou ','Sou ','Yuu ','Tou ','Chi ','Tong ','Cheng ','Kei ','Qu ','Peng ','Hai ','Hetsu ','Chun ','Kyou ','Zou ','Chi ', + 'Ren ','Hyou ','Kai ','Kei ','Shou ','Cheng ','Gin ','Gin ','Ki ','Ki ','Tan ','Tan ','Ta ','Tai ','Dui ','Shoku ', + 'Ketsu ','Ce ','Xiao ','Fan ','Fun ','Rou ','Lao ','Dou ','Kan ','Kei ','Kan ','Bin ','Kei ','Ryou ','Bu ','Can ', + 'Jue ','Cu ','Ken ','Tan ','Sheng ','Pi ','Oku ','Chu ','Sen ','Dou ','Tan ','Tan ','Kei ','Song ','Kan ','Jiao ', + 'Wai ','Ken ','Tou ','Kin ','Qin ','Qu ','Sou ','Kon ','Kai ','You ','Ou ','Bou ','Eki ','Rin ','Shoku ','Shun ', + 'Kai ','Men ','Lan ','Ai ','Rin ','En ','Gua ','Xia ','Chi ','Yu ','Yin ','Dai ','Bou ','Gai ','Bou ','Tsui ', + 'Qi ','Ba ','Ran ','Mon ','Chyuu ','Zhi ','Da ','Da ','Yan ','You ','Bo ','Zhi ','Kou ','Kou ','You ','Fu ', + 'Liu ','Mie ','Chou ','','Zan ','Meng ','Ran ','Kai ','Ken ','Rang ','Zan ','Ji ','Ku ','Kan ','Shou ','I ', + ], + 'x62':[ + 'Ren ','Dan ','Mi ','Tou ','Kyaku ','Gang ','Gang ','Tou ','Ka ','Etsu ','Bo ','Jian ','Jutsu ','Ju ','Juu ','Xi ', + 'Sei ','Ga ','Kai ','Ka ','San ','Shou ','Waku ','Qiang ','Zhan ','Dong ','Seki ','Katsu ','Tetsu ','Zoku ','Katsu ','Geki ', + 'Shoku ','Kan ','Shuu ','Ki ','Gai ','Deng ','Sen ','Sou ','Ge ','Sen ','Setsu ','Yoku ','Jian ','Yan ','Riku ','Gi ', + 'Sen ','Gi ','Gi ','Taku ','Tai ','Gu ','Ko ','Ko ','Ko ','Aku ','Shi ','Rei ','Bou ','Ko ','Rei ','Bou ', + 'Sho ','Hen ','Ten ','Kei ','Shou ','I ','I ','Sen ','Ko ','Hi ','Yan ','Shu ','Shu ','Sai ','Satsu ','Qiu ', + 'Roku ','Hoku ','Hai ','Da ','Jou ','Futsu ','Hameru ','Zai ','Taku ','Zhang ','Chou ','Kou ','U ','Ku ','Kan ','Shen ', + 'Sa ','Yi ','Gu ','Kou ','Gotsu ','Tuo ','Qian ','Zhi ','Sate ','Kuo ','Men ','Sao ','Yang ','Juu ','Fun ','Ta ', + 'Rao ','Sou ','Qian ','Han ','Jia ','Yu ','Fu ','Ao ','Xi ','Hi ','Tei ','Zi ','Aku ','Ton ','Ka ','Shou ', + 'Gi ','Yan ','Kyou ','Ben ','Shou ','Ju ','Wen ','Hu ','Getsu ','Ketsu ','Ha ','Qin ','Zhen ','Shou ','Un ','Gan ', + 'Dotsu ','Yoku ','Jo ','Sou ','Hou ','Tou ','Tou ','Kou ','Setsu ','Pou ','Fu ','Hou ','Batsu ','Ao ','Taku ','Tuan ', + 'Kou ','Lun ','Qiang ','','Hu ','Bao ','Hei ','Zhi ','Hou ','Tan ','Pu ','Hi ','Tai ','Yao ','Zhen ','Zha ', + 'Yang ','Hou ','He ','Ji ','Yi ','Tei ','Chitsu ','Hi ','Za ','Matsu ','Bai ','Shin ','Ou ','Chuu ','Kyo ','Bin ', + 'Chu ','Jia ','Futsu ','Zhan ','Chu ','Tan ','Taku ','Bo ','Den ','Ratsu ','Fu ','Hou ','Han ','Haku ','Rei ','Da ', + 'Kai ','Kan ','Kyo ','Taku ','Batsu ','Ta ','Ta ','Ou ','Kou ','Setsu ','Hen ','Shou ','Hai ','Hai ','Di ','Ni ', + 'Kyo ','Kaku ','Long ','Jian ','','Yong ','Lan ','Ning ','Bo ','Ze ','Sen ','Shuu ','Katsu ','Shiki ','Kitsu ','Jou ', + 'Nin ','Kyou ','Kyou ','Ken ','Sen ','Son ','Satsu ','Gou ','Chi ','Xie ','Ce ','Hui ','Hou ','Ei ','Shuu ','Da ', + ], + 'x63':[ + 'Bo ','Ji ','Kei ','Chitsu ','Kou ','Duo ','Duo ','Shi ','Ketsu ','An ','Rou ','Shin ','Kaku ','Kou ','Ku ','Dong ', + 'Da ','Chou ','Lie ','Ta ','Lu ','Die ','Atsu ','Jue ','Mushiru ','Kyo ','Zhi ','Luan ','Ya ','Zhua ','Ta ','Kyou ', + 'Nao ','Dang ','Jiao ','Zheng ','Ji ','Hui ','Xun ','Ku ','Ai ','Tatsu ','Da ','Za ','Bo ','Kou ','Ti ','Shin ', + 'Cheng ','Suo ','Suo ','Keng ','Mei ','Rou ','Kyoku ','Peng ','Jian ','Yuu ','Tei ','Shan ','Da ','Ban ','Kyou ','Sou ', + 'Feng ','Kaku ','Go ','Kun ','Kyuu ','Tong ','Kon ','Huo ','Tu ','Soku ','Hou ','Ratsu ','Hatsu ','Kan ','Sou ','Detsu ', + 'En ','Ze ','Shou ','Se ','Kaku ','Ho ','Huan ','Ho ','Son ','Yi ','Zhai ','Ryo ','Sou ','Tatsu ','Lao ','Sun ', + 'Bang ','Jian ','Kan ','Dao ','','Wan ','Kin ','Hou ','Sha ','Retsu ','Min ','Mon ','Hu ','Hai ','Kyo ','Dao ', + 'Wo ','Gai ','Ken ','Yue ','Fun ','Ten ','Sui ','Shou ','Totsu ','Ben ','Natsu ','Nen ','Da ','Sotsu ','Wo ','Sei ', + 'Kin ','Cheng ','Ten ','Sou ','Ron ','Qing ','Gang ','Tatsu ','Ju ','Tou ','Hou ','Di ','Shou ','Gun ','Ki ','Tou ', + 'Kou ','Qi ','Hai ','Shu ','Kan ','Ryou ','Eki ','Ya ','Kutsu ','Sou ','Ryou ','Ka ','Yi ','Huo ','En ','Tou ', + 'Ryaku ','Sai ','Tan ','Sei ','Hyou ','Setsu ','Teki ','Kou ','Sui ','En ','So ','Sou ','Kiku ','Ten ','Ken ','Kou ', + 'Bai ','Shou ','Kei ','Lu ','Kaku ','Haba ','','Zhi ','Dan ','Maang ','Xian ','Sou ','Guan ','Hou ','En ','Nuo ', + 'Kan ','Tei ','Jiu ','Sen ','Yu ','Ken ','Ki ','Nan ','Kou ','Juu ','Pi ','Wei ','Sai ','Zou ','Sen ','Byou ', + 'Tei ','Getsu ','Sou ','Shi ','Sou ','Chin ','Yuu ','Shun ','Heng ','Bian ','You ','Kan ','En ','Zuan ','An ','Xu ', + 'Satsu ','Aku ','Ke ','Shi ','Ji ','Tei ','La ','La ','Cheng ','Kai ','Shuu ','Jiu ','Totsu ','Kei ','Ki ','Geng ', + 'Chong ','Shuo ','Setsu ','Setsu ','En ','Ken ','Ya ','Sou ','Sa ','Hai ','You ','','Dam ','Lan ','Wen ','Qin ', + ], + 'x64':[ + 'Chan ','Ge ','Lou ','Zong ','Geng ','Jiao ','Kou ','Qin ','Yong ','Kaku ','Shuu ','Chi ','Zhan ','Son ','Sun ','Haku ', + 'Chiku ','Rong ','Hou ','Sa ','Sou ','Ke ','You ','Tou ','Shi ','Nu ','Xie ','Jian ','Sou ','Qiu ','Kou ','Xian ', + 'Saku ','Sang ','Shin ','Mie ','Aku ','Tai ','Jaku ','Shan ','Tou ','Ketsu ','Tou ','Pan ','Han ','Tou ','Li ','Tou ', + 'Kotsu ','Zhi ','Wa ','Xia ','Ken ','On ','Shou ','Tian ','Zhen ','E ','Kei ','Nuo ','Quan ','Ta ','Saku ','Kaku ', + 'Wu ','En ','Setsu ','Kang ','She ','Shu ','Bai ','You ','Bin ','Sou ','Tan ','Satsu ','Chan ','Suo ','Kyuu ','Shou ', + 'Chuang ','Kaku ','Hei ','Hou ','Shutsu ','Di ','Qi ','','Teki ','Lian ','Tou ','Chi ','Kan ','Roku ','Luo ','Rou ', + 'Sou ','Kai ','Hu ','Sa ','Chuang ','Tang ','Hua ','Sai ','Nai ','Ma ','Jiang ','Gui ','Ying ','Seki ','Ao ','Shi ', + 'Nie ','Man ','Shan ','Kou ','Cho ','Suo ','Tan ','Jiao ','Mo ','Mo ','Shou ','San ','Keng ','Hyou ','Jiang ','Yin ', + 'Gou ','Qian ','Liao ','Geki ','Ying ','Ketsu ','Pie ','Hetsu ','Rou ','Dun ','Xian ','Ruan ','Kui ','Zan ','Yi ','San ', + 'Chou ','Chou ','San ','Dou ','Heng ','Sei ','Qian ','Huang ','Tou ','Son ','Nen ','Rin ','Zheng ','Ki ','Shu ','Kyou ', + 'Ji ','Sou ','Dan ','Tan ','Tetsu ','Hatsu ','Sha ','Jue ','Shou ','Ryou ','Ben ','Bu ','Kyou ','Ha ','Satsu ','Zhuo ', + 'San ','Tuo ','Boku ','Kin ','Dun ','Nian ','','Xie ','Lu ','Kaku ','Cuan ','Tachi ','Kan ','Kou ','Ta ','Ren ', + 'Gan ','You ','Rai ','Kuo ','Ryo ','Sen ','Zhuo ','Taku ','Pu ','Saku ','Geki ','Tou ','Saku ','Sou ','Kei ','Jing ', + 'Kan ','Shou ','Kin ','Kuai ','Tan ','Kei ','Ge ','Heki ','Haku ','Ao ','Kyo ','Ye ','','Mang ','Sou ','Mi ', + 'Sei ','Tai ','Teki ','Tou ','Kou ','Ran ','Satsu ','Kyo ','Ye ','Ju ','You ','Ye ','Gi ','Kyo ','Ji ','Hin ', + 'Dou ','Kaku ','Teki ','Jie ','Kaku ','Ma ','Sen ','Ketsu ','Lie ','Tan ','Hai ','Sou ','Lu ','Ryaku ','Jou ','Teki ', + ], + 'x65':[ + 'Han ','You ','Lei ','Sa ','Cho ','San ','Nian ','Xian ','Kun ','Kaku ','Fuki ','La ','Han ','Ying ','Lu ','Rou ', + 'Qian ','Qian ','Zan ','Ken ','Ran ','San ','Ei ','Mei ','Jou ','Sen ','','San ','Kei ','Setsu ','Ra ','Kun ', + 'Mi ','Li ','San ','Ren ','Tan ','Zuan ','Rei ','Dian ','Wa ','Tou ','Kaku ','Kaku ','Ran ','Li ','Dou ','Shi ', + 'Ki ','Ki ','Qi ','Xin ','Hoku ','Boku ','Shuu ','Kou ','Yuu ','Kai ','I ','Kou ','Kan ','Han ','Hou ','Sei ', + 'Bo ','Dian ','Kou ','Bin ','Wu ','Ko ','He ','Saku ','Kou ','Bi ','Chu ','Kaku ','Di ','Jo ','Kyou ','Bin ', + 'Shin ','Kyuu ','Chin ','Duo ','Gyo ','Choku ','Gou ','Hai ','Jo ','Kyou ','Duo ','Lian ','Nie ','Hei ','Shou ','Ten ', + 'Tatsu ','I ','Kan ','San ','Ke ','Yan ','Ton ','Ki ','Dou ','Kou ','Tatsu ','Seku ','Kei ','You ','Xia ','Bin ', + 'Suu ','Ai ','Kou ','Ai ','Sei ','Teki ','Zhen ','Fu ','Suu ','Liao ','Ku ','Kei ','Xi ','Kyou ','Sen ','Kyou ', + 'Zhuo ','Eki ','Ren ','Hei ','Li ','Kou ','Kou ','Bun ','Gaku ','Sei ','Sei ','Zhai ','Hin ','Jue ','Sai ','', + 'Hi ','Han ','Han ','Lan ','Yu ','Ran ','Wei ','To ','Shou ','Ryou ','Jia ','Koku ','Sha ','Ka ','Yu ','Shin ', + 'Kaku ','Atsu ','Tou ','Shuku ','Kin ','Seki ','Gin ','Fu ','Qiang ','Zhan ','Qu ','Shaku ','Zan ','Dan ','Saku ','Shi ', + 'Shin ','Zhuo ','Taku ','Kin ','Rin ','Zhuo ','Chu ','Dan ','Zhu ','Hou ','Xie ','Hang ','O ','Shi ','Pei ','You ', + 'Mye ','Hou ','Ki ','Sen ','Bou ','Ryo ','Hai ','Pi ','Ryuu ','Fu ','Fang ','Sen ','Sei ','Jing ','Ji ','Zoku ', + 'Chou ','Yi ','Ryuu ','Shao ','Ken ','Es ','I ','Ki ','Shi ','Han ','Piao ','Han ','Zhan ','Guai ','Sui ','Yo ', + 'Bu ','Ki ','Ki ','Ki ','Huo ','Nichi ','Tan ','Kyuu ','Shi ','Sou ','Xie ','Tiao ','Jun ','Kyoku ','Xu ','Xu ', + 'Kan ','Kan ','Tai ','Di ','Ku ','Tan ','Shi ','Kuang ','Yang ','Ji ','Ou ','Bin ','Min ','Tun ','Shun ','Go ', + ], + 'x66':[ + 'In ','Bei ','Kou ','Soku ','Han ','Jie ','Kon ','Shou ','Ko ','Hou ','Kou ','Gui ','Shou ','Ken ','Mei ','Kon ', + 'Fen ','Kin ','Kotsu ','Eki ','Seki ','Kin ','En ','Ze ','Fang ','Tan ','Shen ','Ju ','You ','San ','Hei ','Sei ', + 'Ei ','Ken ','Hotsu ','Shin ','Rei ','Shun ','Kou ','Mai ','Saku ','Batsu ','Hen ','Ku ','Kon ','Shou ','Shou ','Ze ', + 'Shi ','Iku ','Fei ','Tetsu ','Bou ','Jitsu ','Chou ','On ','Dong ','Ai ','Bing ','Kou ','Chuu ','Long ','Xian ','Kou ', + 'Chou ','Chou ','Ji ','Kou ','Kou ','Ken ','Kai ','Xu ','Jiao ','Shin ','Shitsu ','Shin ','Shou ','Tong ','Kou ','An ', + 'Gai ','Kyou ','Sai ','Xiao ','Ye ','Yun ','Hui ','Kan ','Kan ','Shun ','Ban ','Ken ','Kon ','Chuu ','Ki ','Sei ', + 'Sei ','Ho ','Setsu ','Zhe ','Go ','Han ','Kai ','Kou ','Shin ','Ban ','Ten ','Taku ','Sai ','Zhou ','Fu ','Kei ', + 'Seki ','Shan ','Yi ','Seki ','Sei ','Kei ','Shou ','Ki ','Tei ','Eki ','Chi ','An ','En ','Lin ','Ryou ','Shou ', + 'Ou ','Gyou ','Zan ','Hi ','Ken ','Xuan ','Yi ','Ka ','Un ','Ki ','Fu ','Bin ','Kei ','Etsu ','Ei ','Sho ', + 'I ','Sho ','Sei ','Mao ','Nan ','Jian ','Dan ','An ','You ','Shun ','You ','Sa ','Fu ','Mei ','Jiao ','Kai ', + 'Kou ','Weng ','Chou ','Qi ','Kou ','Yan ','Reki ','Ai ','Ki ','Gui ','Men ','Zan ','Xie ','Kou ','Bo ','Mo ', + 'Cong ','Jitsu ','Shou ','Hui ','Bou ','Kan ','Xuan ','Chuan ','Ryou ','Sen ','Dan ','Kei ','Hetsu ','Lin ','Ton ','Ki ', + 'Ei ','Ki ','Kou ','Tai ','You ','You ','Reki ','Don ','Tou ','Gyou ','Fei ','Qin ','Shou ','Hao ','Eki ','Kyou ', + 'Xing ','Sen ','Jiao ','Bao ','Kei ','Yan ','Ai ','Ye ','Ru ','Sho ','Bou ','Kun ','You ','Baku ','Li ','Shin ', + 'Kou ','Jou ','','Yan ','Huo ','Lu ','Gi ','Rong ','Rou ','Dou ','Luo ','Ran ','Sai ','Tang ','Gan ','Chu ', + 'Etsu ','Ou ','Kyoku ','Ei ','Kou ','Ei ','Hu ','Katsu ','Sho ','Sou ','Sou ','Shou ','Ban ','Zo ','So ','Tai ', + ], + 'x67':[ + 'Sai ','Can ','Xu ','Kai ','Yin ','Ketsu ','Fen ','Hi ','Getsu ','Yuu ','Ruan ','Hou ','Han ','Fuku ','Rei ','Hi ', + 'Kyou ','','Niku ','Chou ','Saku ','Chin ','Rou ','Rou ','Sen ','Mei ','Huang ','Bou ','Ton ','Chou ','Ki ','Ki ', + 'Ei ','Zong ','Bou ','Tong ','Lang ','','Bou ','Rou ','Boku ','Tou ','Mi ','Matsu ','Hon ','Satsu ','Jutsu ','Jutsu ', + '','Shu ','Ren ','Hatsu ','Boku ','Da ','Da ','Tou ','Ryoku ','Qiu ','Ki ','Jiu ','Bi ','Kyuu ','Tou ','Shi ', + 'Sha ','Eburi ','Za ','Quan ','Qian ','U ','Kan ','O ','Sa ','San ','Xun ','Fan ','Gotsu ','Zi ','Ri ','Kyou ', + 'Zai ','Son ','Ren ','Hyou ','Taku ','Tei ','Jou ','Mang ','Chi ','Yoku ','Gu ','Gong ','Do ','Chi ','Ko ','Soku ', + 'Kou ','Jou ','Moku ','Soma ','Tochi ','Rai ','Sugi ','Man ','Yang ','Ma ','Byou ','Si ','Gen ','Kou ','Hai ','Hai ', + 'Ketsu ','Tou ','Kou ','You ','Ken ','Sho ','Chun ','Ha ','Shu ','Hua ','Xin ','Chuu ','Cho ','Chou ','Shou ','Han ', + 'Song ','Kyou ','Yue ','Jin ','Kou ','Kei ','Mao ','Hi ','Bi ','Ou ','Ang ','Hou ','Fun ','Yi ','Hu ','Dan ', + 'Seki ','Ko ','Ya ','Shu ','Xun ','Chin ','You ','Rin ','Zei ','Ga ','Mai ','Sou ','Ka ','Shi ','Cong ','Yun ', + 'Waku ','Masu ','Suu ','Zao ','','Li ','Ro ','Jian ','Cheng ','Shou ','Qiang ','Feng ','Nan ','Xiao ','Xian ','Ko ', + 'Hei ','I ','Shi ','Ki ','Kai ','Kyou ','Ka ','Ka ','Ku ','Hou ','Mo ','Ei ','You ','Sou ','Shi ','Nie ', + 'Hi ','Ta ','I ','Rei ','Hei ','Ji ','Rou ','He ','Han ','Han ','Shuu ','Dai ','Ci ','Yang ','Fu ','Haku ', + 'Bou ','Kan ','Shitsu ','Sen ','Nyuu ','Mao ','Zhao ','Shou ','Sha ','Kou ','Yuu ','Shen ','Kyo ','Taku ','Saku ','Nan ', + 'Ning ','Ei ','Tei ','Zhi ','Sa ','Sa ','Tan ','Ko ','','Kyuu ','Ao ','Fu ','Kan ','Bo ','Totsu ','Ka ', + 'Na ','Chuu ','Hi ','Ryuu ','Sai ','Saku ','Shi ','Shuku ','Pei ','Shi ','Guai ','Sa ','Yao ','Jue ','Kyuu ','Shi ', + ], + 'x68':[ + 'Zhi ','Liu ','Toga ','Tochi ','Ei ','Saku ','','Biao ','San ','Jie ','Long ','Dong ','Lu ','Sayng ','Li ','Lan ', + 'Yong ','Shu ','Xun ','Sen ','Kei ','Zhen ','Sei ','Ritsu ','Yi ','Kou ','Zhen ','Li ','Su ','Ten ','Kan ','Hei ', + 'Ren ','Kou ','Haku ','Ren ','Bing ','Zi ','Chou ','Ei ','Setsu ','Ku ','Chu ','Son ','Sei ','Ji ','Er ','Iku ', + 'Hatsu ','Kyou ','Gou ','Rou ','Sen ','Li ','','Yang ','Kaku ','Kon ','Zhi ','Choku ','Kou ','Sai ','Luan ','Fuku ', + 'Ketsu ','Kou ','Kei ','Tou ','Kou ','Gai ','Kyou ','Ru ','An ','An ','Ken ','Yi ','Taku ','Ko ','Shitsu ','Qiong ', + 'Dou ','Sou ','Sou ','Kan ','Kitsu ','Kyuu ','Xue ','Ta ','Tsui ','U ','Zan ','Kasei ','Ou ','Masu ','','San ', + 'Ya ','Nao ','Zhen ','Tou ','Qi ','Qiao ','Hua ','Kai ','Jiang ','Zhuang ','Xun ','Sa ','Sha ','Zhen ','Hai ','Tei ', + 'Katsu ','Kei ','Hotsu ','Ben ','Fu ','Zui ','Tou ','Kaku ','Xi ','Rou ','Ryuu ','Hou ','Shitsu ','Wen ','Kun ','Kan ', + 'Cu ','Ryou ','Kyuu ','Tei ','You ','Bai ','Hou ','Long ','Hou ','Zhuang ','Di ','Xuan ','Tu ','Sou ','Ou ','Koku ', + 'Bi ','Di ','Han ','Shi ','Shi ','Ren ','Hai ','Kou ','Ken ','Huan ','Ban ','Da ','Kyou ','Jou ','Ji ','Kyou ', + 'Ryo ','Kan ','Shou ','Shin ','Fen ','Shou ','Mu ','Go ','Ri ','Ri ','Tou ','Cen ','Ying ','Sa ','Kiku ','Tei ', + 'Kai ','Kon ','Setsu ','So ','Chan ','Fuu ','Bi ','Jing ','Li ','Bin ','Fumoto ','Shikimi ','Tou ','Zhi ','Lai ','Lian ', + 'Jian ','Setsu ','Ling ','Li ','Ki ','Hei ','Rin ','Cong ','Sen ','Men ','Ki ','Ki ','Sai ','Kon ','Chan ','Toku ', + 'Hi ','Hai ','Bou ','Hou ','Kon ','Shu ','Tou ','Sou ','Kyoku ','Rei ','Hou ','Yu ','Yo ','Ko ','Hun ','Tou ', + 'Tou ','Kou ','Wang ','Tei ','Xi ','Han ','Cheng ','San ','Kei ','Yuan ','En ','Yoku ','Ken ','Eki ','Shin ','Jin ', + 'Soi ','Rou ','Sei ','Zhuo ','Fu ','Kan ','Rai ','Zou ','Zou ','Tou ','Kan ','Fen ','Hun ','Chin ','Qiong ','Nie ', + ], + 'x69':[ + 'Wan ','Kaku ','Lu ','Hao ','Setsu ','I ','Chuu ','Ju ','Kiku ','Jou ','Sotsu ','Ryou ','Kou ','Shoku ','Tsui ','A ', + 'Kyo ','Hei ','Shou ','Taku ','Zi ','Bin ','Hou ','Tei ','Chu ','Sugi ','Kunugi ','Momiji ','Ken ','Gui ','Xi ','Du ', + 'Qian ','Kunugi ','Kai ','Shide ','Luo ','Nagi ','Ken ','Myeng ','Tafu ','','Kunugi ','Zhan ','','Tuo ','Sen ','Duo ', + 'Ya ','Fuu ','Wei ','Wai ','Tan ','Ka ','Shu ','Jian ','I ','Chin ','Xi ','En ','Yan ','Ten ','Zhan ','Chin ', + 'Yu ','He ','Sa ','Wo ','Pian ','Hyku ','Yao ','Huo ','Xu ','Jaku ','You ','La ','Yan ','Ben ','Kon ','Kui ', + 'Jie ','Kui ','Si ','Fuu ','Setsu ','Da ','Zhi ','Ken ','Mu ','Bou ','So ','Ko ','Ko ','Ren ','Rou ','Ting ', + 'Nan ','Yu ','Shuu ','Bi ','Sou ','Ken ','Ken ','Ying ','Tei ','Hen ','You ','Shuu ','Ketsu ','Gyou ','Cho ','Jun ', + 'Yu ','Sou ','I ','Bai ','Tei ','Goku ','Jie ','Kai ','Shuu ','Ei ','Juu ','Kou ','Rou ','Gaku ','Hazou ','Katsura ', + 'Komai ','Muro ','Gai ','Tan ','Lan ','Otsu ','Yu ','Chen ','Lu ','Ju ','Sakaki ','','Pi ','Setsu ','Ka ','Yi ', + 'Zhan ','Fu ','Doku ','Mi ','Rou ','You ','Koku ','Jian ','Ku ','Ta ','Yao ','Shin ','Bou ','Sha ','Yuan ','Zi ', + 'Bei ','So ','Jia ','Yao ','Jie ','Kou ','Kan ','Hi ','Sa ','Qian ','Ma ','Shun ','Yuan ','Sha ','Ei ','Shi ', + 'Zhi ','Sui ','Otsu ','Ting ','Ryuu ','Rong ','Tang ','Kaku ','Tai ','Si ','Shou ','Tou ','Kou ','Xi ','Kotsu ','Ki ', + 'Kao ','Kou ','Sun ','Han ','Tao ','Kaku ','Xun ','Ten ','Dou ','Ji ','Saku ','Kou ','Tsui ','Sou ','Sa ','Qian ', + 'Kai ','Bai ','Xu ','Kou ','Gao ','Zhuo ','Taku ','Kyou ','You ','Ten ','Jia ','Jian ','Zui ','Tou ','Rou ','Bin ', + 'Zhu ','','Shuu ','Qi ','Lian ','Ei ','Yong ','San ','Kaku ','Gai ','Gai ','Tan ','Hua ','Shuku ','Shin ','Sai ', + 'Beng ','Yuu ','Koku ','Shou ','Hu ','Kan ','Kui ','Yi ','Nie ','Kou ','Kang ','Ki ','Gui ','Sou ','Ban ','Kin ', + ], + 'x6a':[ + 'Teki ','Tou ','Gaku ','Rou ','Chen ','Shou ','Li ','Xiu ','Qing ','Shuang ','Han ','Tou ','Kan ','Ji ','Suo ','Rui ', + 'Lu ','Ryou ','Mitsu ','Rou ','Sou ','Soku ','Ke ','Cho ','Tang ','Hyou ','Roku ','Kyuu ','Shu ','Sa ','Suu ','Shou ', + 'Bon ','Mo ','Boku ','You ','Jou ','Peng ','Zhu ','Sha ','Sei ','Ken ','Ou ','Kashi ','Cong ','','Hokuso ','Qiang ', + 'Tara ','Ying ','Ji ','Xin ','Shoku ','Shou ','Sai ','Sou ','Boku ','Ju ','Ka ','Ki ','Zhen ','Son ','Etsu ','Sen ', + 'Xi ','Xun ','Dian ','Fa ','Kan ','Bo ','Bu ','Zei ','Dou ','Rin ','Ryou ','Kyou ','Xian ','Run ','Han ','Zhan ', + 'Taku ','Rou ','Un ','Shun ','Tui ','Tou ','Tou ','Meng ','Kitsu ','Tou ','Su ','Ketsu ','Jue ','Tan ','Hui ','Ki ', + 'Nuo ','Shou ','Da ','Ning ','Zui ','Zhu ','Tou ','Sou ','Fen ','Qiong ','Zen ','Ou ','Cen ','Gu ','Liu ','Lao ', + 'Gao ','Zu ','Zusa ','Nude ','Ca ','San ','Ji ','Dou ','Shou ','Lu ','Gaan ','','Yuan ','Ta ','Shu ','Kyou ', + 'Tan ','Rin ','Nong ','In ','Geki ','Sui ','San ','Sui ','Xuan ','Tei ','Gan ','Kyoku ','Zui ','Yoku ','Go ','Pu ', + 'En ','Rai ','Feng ','Hui ','Dang ','Ji ','Sui ','Haku ','Bi ','Ding ','Chu ','Ta ','Kai ','Shuu ','Kai ','Ka ', + 'Kei ','Zhe ','Ken ','Shou ','Dao ','Gi ','Biao ','Song ','She ','Rin ','Reki ','Satsu ','Bou ','Yin ','Tou ','Tai ', + 'Hen ','Ki ','','Bin ','Kaku ','Ji ','Qian ','Mi ','Nei ','Yi ','Gao ','Kan ','In ','Ji ','Kei ','En ', + 'Qi ','Mitsu ','Tou ','Ki ','Chun ','Ji ','Kai ','Po ','Tou ','Chu ','Han ','Mian ','Yuu ','Zhi ','Guang ','Qian ', + 'Rui ','Rai ','Sa ','Ro ','Rei ','San ','Ryo ','Mie ','Hui ','Ou ','Ryo ','Shitsu ','Kou ','Toku ','En ','Reki ', + 'Fei ','Zhuo ','Sou ','Lian ','Sen ','Chu ','','Sho ','Ro ','Yan ','Reki ','Zhu ','Shin ','Jie ','E ','Su ', + 'Kai ','Getsu ','Yo ','Long ','Lai ','','Xian ','Kwi ','Ju ','Xiao ','Rei ','Ou ','Sen ','In ','You ','Ying ', + ], + 'x6b':[ + 'Xiang ','Nong ','Haku ','San ','Ran ','Kyo ','Sou ','Shou ','Wei ','Sou ','Ken ','Qu ','Cang ','','Yu ','Ra ', + 'Rei ','San ','Ran ','Dang ','Jue ','Em ','Ran ','Ran ','Zhu ','Lei ','Li ','Ha ','Nang ','Utsu ','Rei ','Tsuki ', + 'Ketsu ','Ji ','Huan ','Gon ','Yo ','Yu ','Qian ','Ou ','Ku ','Chao ','Chu ','Keki ','Kai ','Yi ','Jue ','Kitsu ', + 'Xu ','Xia ','Yoku ','Kuai ','Lang ','Kan ','Saku ','Ki ','Ai ','I ','Gi ','Kutsu ','Chi ','Kin ','Kan ','Tan ', + 'Kan ','Kan ','Chuan ','Sou ','','Yin ','Kin ','Ketsu ','Yu ','Ken ','Kyou ','Yi ','Ka ','O ','Tan ','Jin ', + 'Ou ','Hu ','Teki ','Kan ','Kyo ','Pen ','Ki ','Xiao ','Kutsu ','Kyuu ','Sen ','Kan ','Chu ','Eki ','Kan ','Yo ', + 'Setsu ','Kan ','Shi ','Sei ','Shi ','Ho ','Bu ','Ki ','Bu ','Ho ','Wai ','Kyo ','Qian ','Chi ','Juu ','Shi ', + 'Shuu ','Zhong ','Sei ','Sei ','Reki ','Saku ','Yu ','Li ','Ki ','Gatsu ','Dai ','Shi ','Jian ','Setsu ','Botsu ','Botsu ', + 'You ','Botsu ','So ','You ','Ten ','Sou ','Tai ','Shang ','Xu ','Jun ','Shu ','Zan ','Jue ','Hyou ','Qia ','Qiu ', + 'Su ','Kyou ','Yun ','Lian ','Yi ','Fuu ','Shoku ','You ','Zan ','Hun ','Dan ','Kyoku ','Ye ','','In ','Otsu ', + 'Shuu ','Bin ','Tei ','Kin ','Shou ','Yin ','Diao ','Cu ','Kai ','San ','Ei ','Tan ','To ','Kyou ','Ren ','Hin ', + 'Toku ','Sen ','Sen ','Shu ','Ou ','Dan ','Zhu ','In ','Kei ','Ei ','Satsu ','Kaku ','Kaku ','Kou ','Shun ','Ten ', + 'Ki ','Ki ','Gu ','Kaku ','Keki ','Ki ','Ou ','Hui ','Duan ','I ','Xiao ','Bu ','Kan ','Bo ','Mai ','Mai ', + 'Ai ','Zuo ','Doku ','Iku ','Hi ','Bi ','Hi ','Pi ','Hi ','Bi ','San ','Mou ','','','Pu ','Mushiru ', + 'Jia ','Sen ','Sai ','Boku ','Tuo ','Xun ','Ji ','Juu ','Xian ','Ju ','Mu ','Kou ','Kyuu ','Dou ','Mushiru ','Tan ', + 'Pei ','Kiku ','Duo ','Zei ','Bi ','San ','','Bou ','Sui ','Yu ','Yu ','Tuo ','He ','Jian ','Ta ','San ', + ], + 'x6c':[ + 'Lu ','Mu ','Ri ','Tong ','Juu ','Shou ','Pu ','Luo ','Sen ','Sou ','Zhan ','Meng ','Luo ','Ku ','Chou ','Shi ', + 'Tei ','Min ','Ketsu ','Bou ','Ki ','Pie ','Nai ','Ki ','Dao ','Sen ','Chuan ','Fun ','Ri ','Nei ','','Hutsu ', + 'Shen ','Dong ','Qing ','Ki ','In ','Xi ','Gai ','You ','An ','Ya ','Ke ','Qing ','A ','Dong ','Tan ','Lu ', + 'Qing ','Yang ','Un ','Un ','Sui ','Sanzui ','Shou ','Hyou ','Ei ','Kan ','Sui ','Roku ','Ni ','Ton ','Han ','Ki ', + 'Tei ','Juu ','Kyuu ','Bin ','Ze ','Mian ','Cuan ','Hui ','Diao ','Yi ','Sa ','Saku ','Chuan ','Kan ','Han ','Tai ', + 'Seki ','Tuo ','Bou ','Qiu ','Kitsu ','San ','Pai ','Kan ','Qian ','O ','O ','Shin ','Shi ','Jo ','Kou ','Kou ', + 'Chi ','O ','Tsuchi ','','Tang ','Zhi ','Chi ','Ken ','Beki ','Itsu ','Ou ','Kei ','Jing ','Zei ','Jun ','Kou ', + 'Ta ','Quan ','Kyuu ','Hen ','Hen ','Gan ','Bun ','Zhong ','Hou ','Kyou ','Ketsu ','Ko ','','Ki ','Fun ','Xu ', + 'Xu ','Shin ','Ki ','Yoku ','Yun ','Gen ','Kou ','En ','Chin ','Chin ','Dan ','You ','Ton ','Go ','Huo ','Qi ', + 'Boku ','Rou ','Botsu ','Tou ','Ben ','Butsu ','Chuu ','Ten ','Hi ','Sa ','Shi ','Hai ','Han ','Zhui ','Za ','Kou ', + 'Liu ','Botsu ','Taku ','Feng ','Ou ','Li ','Lun ','Cang ','Feng ','Wei ','Hu ','Matsu ','Mei ','Shu ','Sho ','Zan ', + 'Taku ','Ta ','Ta ','Ka ','Rei ','Dei ','Yi ','Fa ','Futsu ','Yu ','Ten ','Ji ','Shou ','Ko ','Ten ','En ', + 'Si ','Kyou ','Kei ','Ju ','Ei ','Shuu ','Itsu ','Jia ','Zhong ','Sen ','Haku ','Hui ','Hitsu ','Hon ','Zhuo ','Chutsu ', + 'Ryoku ','Yuu ','Ko ','Ou ','Kan ','Hou ','Bou ','Shi ','Hu ','Hou ','Sei ','Han ','Tei ','So ','Ning ','Cheng ', + 'Rei ','Hou ','Ha ','Kyuu ','Si ','Dei ','Ju ','Etsu ','Chuu ','Sou ','Rui ','Ken ','Ketsu ','Fu ','Han ','Bin ', + 'Tai ','Ou ','Sei ','Ei ','Kan ','Ryuu ','Xue ','Long ','Lu ','','Bo ','Xie ','Po ','Ze ','Jing ','Yin ', + ], + 'x6d':[ + 'Zhou ','Ji ','Yi ','Hui ','Kai ','Zui ','Cheng ','In ','Wei ','Hou ','Sen ','You ','Retsu ','Si ','Ki ','Ji ', + 'Xing ','Huku ','Sei ','Saku ','Zhi ','Yin ','Wu ','Sen ','Kao ','Shu ','Kou ','Raku ','','An ','Dou ','I ', + 'Mou ','Lei ','Yi ','Mi ','Quan ','Shin ','Baku ','I ','Kou ','Ei ','Kou ','Kyoku ','Shuo ','Kuang ','Tou ','Ketsu ', + 'Ju ','Ji ','Shuu ','Jo ','Ping ','Shun ','Kyou ','Zhi ','Kou ','En ','Ming ','Katsu ','Ai ','Kou ','Ha ','O ', + 'Qu ','Ryuu ','Yi ','Jia ','Jou ','Sen ','Jiang ','Jiao ','Cheng ','Shi ','Zhuo ','Ce ','Pal ','Kuai ','Ji ','Liu ', + 'Chan ','Hun ','Hu ','Nong ','Xun ','Jin ','Lie ','Kyuu ','Wei ','Setsu ','Shun ','Han ','Hin ','Mang ','Saku ','Yuu ', + 'Xi ','Hotsu ','Dou ','Kan ','Kou ','Yuu ','Ho ','Tei ','Lan ','Kou ','Rou ','Han ','Ri ','Geng ','Fu ','Go ', + 'Ren ','Chun ','Feng ','Yi ','Yoku ','Tong ','Lao ','Kai ','Shin ','Shou ','Chong ','Weng ','Bai ','Sui ','Cheng ','Pei ', + 'Xian ','Shen ','To ','Kun ','Pin ','Netsu ','Han ','Tei ','Shou ','Shou ','Nian ','Tu ','Yuu ','Xiao ','Sen ','Ting ', + 'E ','Sou ','Ton ','Ken ','San ','Tei ','Rei ','Sei ','Shi ','Rui ','Sei ','Tou ','Toku ','Lao ','Lai ','Lian ', + 'Wei ','Wo ','Yun ','Kan ','Di ','','Run ','Jian ','Zhang ','Se ','Huu ','Guan ','Kei ','Shou ','Shuan ','Gai ', + 'Chuo ','Zhang ','Eki ','Kong ','En ','Kan ','Tuo ','Tou ','Ko ','Wa ','Ju ','Gan ','Ryou ','Kon ','Ta ','Toku ', + 'Ten ','Qie ','De ','Juan ','Shi ','Seki ','Kou ','Ki ','Kotsu ','Guo ','Kan ','Rin ','Shou ','Zhou ','Hou ','Kou ', + 'Chang ','Shuku ','Sei ','Fang ','Chi ','Riku ','Dou ','Ju ','Tou ','Sou ','Rui ','Sei ','Peng ','Hi ','Shou ','Ten ', + 'Hi ','Tan ','Yoku ','Ni ','Yo ','Roku ','Kan ','Mi ','Jou ','Ryou ','Rin ','In ','Sai ','Qu ','Wai ','Iku ', + 'Den ','Shin ','Piao ','Shun ','Otsu ','En ','Rai ','Kon ','Sei ','En ','Sen ','Ten ','Byou ','Zhi ','Yin ','Mi ', + ], + 'x6e':[ + 'Hon ','Yuan ','Wen ','Re ','Hi ','Sei ','Yuan ','Katsu ','Sai ','Shou ','En ','Juu ','Roku ','Zi ','Du ','', + 'Jian ','Min ','Pi ','Kei ','Yu ','En ','Shen ','Shin ','Rou ','Kan ','Sho ','Gen ','Nuan ','Yu ','Shuu ','Tei ', + 'Kyo ','To ','Huu ','Sa ','Botsu ','Aku ','Ka ','Tei ','Wei ','On ','Ru ','Setsu ','Soku ','I ','Ka ','Kou ', + 'Yan ','Hong ','Sen ','Mi ','Katsu ','Mao ','Ei ','Yan ','Yuu ','Kou ','Byou ','Sei ','Bi ','Zai ','Kon ','Nai ', + 'Kui ','Shi ','E ','Hai ','Bi ','Ren ','Qi ','Qi ','Bai ','Ten ','Sou ','I ','Can ','Tan ','Ben ','Kai ', + 'Mo ','Sho ','Shuu ','Hon ','Sen ','Jian ','Ko ','Hou ','Shou ','Yi ','Yin ','Tan ','Shoku ','Kai ','Tou ','Kou ', + 'Tan ','Yu ','Hyoku ','Bin ','Shi ','Tu ','Sheng ','Yuu ','Keki ','Zhong ','','Shou ','Jiao ','qiu ','In ','Tou ', + 'Long ','Huo ','Kan ','Dan ','Ban ','You ','Sen ','Chui ','Liang ','Chan ','Yan ','Jun ','Nie ','Shi ','Wan ','Shitsu ', + 'Man ','Ying ','Ratsu ','Kui ','','Jian ','Xu ','Lu ','Ki ','Gai ','','','Hatsu ','Shin ','Gui ','Tou ', + 'Gen ','Suo ','Yuan ','Ren ','Yao ','Meng ','Jun ','Sheng ','Kou ','Tai ','Da ','Wa ','Ryuu ','Kou ','Sao ','Mei ', + 'Sa ','Shi ','Itsu ','Lun ','Ma ','Ho ','Mi ','Ritsu ','Cai ','Wu ','Kei ','On ','Qiang ','Shoku ','Shi ','So ', + 'Yi ','Shin ','Sou ','Un ','Xiu ','Yin ','You ','Kon ','Su ','Su ','Deki ','Tou ','Shi ','Joku ','Wei ','Han ', + 'Chiku ','Cho ','Bou ','Ou ','Sou ','Metsu ','He ','Ten ','Kou ','Kou ','Ki ','Ji ','Deki ','Chi ','Kei ','Hu ', + 'Jie ','Katsu ','Ge ','Sai ','Tou ','Tou ','Sui ','Bi ','Jiao ','Hui ','Kon ','Yin ','Gao ','Sou ','Tai ','Yan ', + 'She ','Man ','Ying ','Chun ','Lu ','Lan ','Luan ','','Bin ','Tan ','Yu ','Shuu ','Ko ','Hitsu ','Hyuu ','Tai ', + 'Jiang ','Kou ','Shin ','Shang ','Teki ','Mi ','Ao ','Ro ','Ko ','Ko ','You ','San ','Fan ','You ','Kon ','Man ', + ], + 'x6f':[ + 'Qing ','Ryou ','Hyou ','Ji ','Gai ','Jiao ','Shitsu ','Xi ','Sei ','Roku ','Ru ','Long ','Kin ','Kaku ','Cong ','Rou ', + 'Zhi ','Gai ','Qiang ','Ri ','En ','Sou ','Kou ','Cong ','Shin ','Tuan ','Ou ','Tou ','Ye ','Xi ','Mi ','Tang ', + 'Baku ','Shang ','Kan ','Ran ','Lan ','Wa ','Gi ','Qian ','Feng ','Sen ','I ','Man ','Shi ','Bou ','Kang ','Tou ', + 'Hou ','Sou ','Chou ','Shou ','Chong ','Xu ','Kan ','Kuo ','Zen ','Yan ','Chuang ','Ryou ','Sai ','Ti ','You ','Shou ', + 'Sou ','Ei ','Hong ','Xun ','Shu ','Kan ','Ying ','Xiao ','','','Xu ','Lian ','Zhi ','Wei ','Pi ','Ketsu ', + 'Jiao ','Hatsu ','Tou ','Kei ','Ketsu ','Wu ','Pa ','Shuu ','Han ','Ki ','Shuku ','Sen ','Sen ','Kyuu ','Ro ','Seki ', + 'Sun ','Ton ','Kou ','Min ','Jun ','Su ','Rou ','Zhen ','Sou ','Yi ','Di ','Wan ','Tan ','Tan ','Chou ','Jin ', + 'Kai ','','Shao ','Tu ','Cho ','San ','Hei ','Bi ','San ','Chan ','San ','Shu ','Dou ','Ho ','Rin ','Wei ', + 'Juu ','Juu ','Chou ','Gei ','Chou ','Hua ','Gyou ','Rou ','Tetsu ','Gan ','Cun ','Kou ','Shi ','Shu ','Hou ','Han ', + 'Un ','Ryuu ','Kou ','Huku ','Kou ','He ','Kan ','Kan ','Shan ','Seki ','Iku ','','Lan ','','Yu ','Rin ', + 'Shou ','Sou ','Dang ','Kan ','Taku ','Kai ','Yo ','Rei ','Sei ','Xue ','Rei ','Man ','Zi ','Yong ','Kai ','San ', + 'Ren ','Ten ','Ye ','Iku ','Huan ','Shin ','Sen ','Man ','Dan ','Tan ','Yi ','Sui ','Heki ','Ju ','Ta ','Qin ', + 'Geki ','Daku ','Ren ','Nou ','Guo ','Shin ','Fun ','Shoku ','Shuu ','Sui ','Kai ','Chu ','Ta ','Song ','Ding ','', + 'Zhu ','Lai ','Bin ','Lian ','Dei ','Shitsu ','Shu ','Mi ','Nei ','Ying ','Ei ','Meng ','Jin ','Qi ','Hi ','Sai ', + 'Gou ','Ju ','Zui ','Wo ','Tou ','Yin ','Yin ','Dui ','Shi ','Kaku ','Jing ','Ran ','Shun ','Ai ','Hoku ','Taku ', + 'I ','Hin ','Gu ','Sen ','Xing ','Hin ','Katsu ','Fei ','','Boku ','Sen ','Wei ','Roku ','San ','Ryo ','Li ', + ], + 'x70':[ + 'Yuu ','You ','Lu ','Si ','Jie ','Ei ','Toku ','Ou ','Hui ','Sha ','Pan ','Shin ','Biao ','Ten ','Mo ','Ryuu ', + 'Jian ','Baku ','Shoku ','Chou ','Gu ','Hin ','Huo ','Ken ','Ro ','Qin ','Kan ','Ei ','Yong ','Reki ','Jou ','Shou ', + 'Ei ','Sui ','Wei ','Kai ','Huai ','Hao ','Cho ','Sou ','Rai ','Dui ','Fan ','Hu ','Rai ','','','Ei ', + 'Bi ','Ji ','Ren ','Jian ','Ei ','Fen ','Lin ','Yoku ','Jian ','Seku ','Chan ','Dai ','Jou ','Jian ','Ran ','Fan ', + 'Shuang ','Yuan ','Zhuo ','Huu ','Shou ','Lei ','Lan ','Cong ','Ku ','You ','Sen ','Hou ','Kan ','Que ','En ','Hao ', + 'Hyeng ','Sai ','Zan ','Luan ','En ','Ri ','Mi ','Shan ','Dan ','Dang ','Jiao ','Chan ','','Kou ','Ha ','Zhu ', + 'Lan ','Lan ','Nang ','Wan ','Ran ','Shun ','Xian ','En ','Gan ','En ','Yu ','Ka ','Hyou ','Mie ','Kou ','Tou ', + 'Kai ','Xiao ','Xiao ','','Hong ','Rei ','Sou ','Zhuan ','Kyuu ','Zha ','Xie ','Chi ','Shaku ','Sai ','Sai ','Can ', + 'Yang ','Ki ','Zhong ','Fen ','Niu ','Kei ','Bun ','Po ','Yi ','Ro ','Sui ','Pi ','Kai ','Pan ','En ','Kai ', + 'Pang ','Mu ','Sou ','Liao ','Kei ','Kou ','Ton ','Kou ','Kin ','Sha ','Kwang ','You ','Wei ','Qiang ','','Da ', + 'Xia ','Zheng ','Zhu ','Ke ','Shou ','Fu ','Ba ','Duo ','Duo ','Ling ','Zhuo ','Ken ','Ko ','Tan ','Hou ','Kei ', + 'Hou ','Tai ','Tai ','Hei ','You ','Tong ','Han ','Shu ','Saku ','Ten ','I ','Shi ','Lian ','Chi ','Huang ','', + 'Hu ','Shuo ','Lan ','Jing ','Jiao ','Xu ','Xing ','Quan ','Retsu ','Kan ','You ','Kou ','Xiu ','Xian ','Yin ','U ', + 'Zhou ','You ','Shi ','Ei ','Tou ','Ketsu ','Sai ','Kai ','Kou ','Raku ','Xia ','Zhu ','Ten ','Jou ','Po ','En ', + 'Hui ','Guang ','Zhe ','Hui ','Kou ','','Fan ','Shao ','Ye ','Hui ','','Tang ','Jin ','Re ','','Xi ', + 'Fu ','Kei ','Che ','Pu ','Jing ','Zhuo ','Ting ','Wan ','Hai ','Hou ','Kou ','Shan ','Hu ','Hou ','Chi ','Rong ', + ], + 'x71':[ + 'Hu ','','Shu ','Kaku ','Kun ','Koku ','Etsu ','Shou ','Xi ','En ','Han ','Sou ','Shun ','Di ','Xie ','Kyoku ', + 'Wu ','','Lua ','Han ','En ','Kan ','Men ','Ju ','Chou ','Hou ','Fun ','Lin ','Kon ','Hun ','Ton ','Xi ', + 'Sai ','Mu ','Hong ','Ju ','Fu ','Wo ','Shou ','Cong ','Feng ','Ping ','Qiong ','Zetsu ','Xi ','Kei ','Xin ','Shaku ', + 'En ','En ','Yi ','Jue ','Yu ','Gang ','Zen ','Pi ','Ko ','','Sheng ','Shou ','Shou ','','Nam ','Geng ', + 'Wat ','Shin ','He ','Kui ','Zhong ','Tan ','Ka ','Ki ','Feng ','Ren ','Ken ','Sei ','Kou ','Jiao ','Sen ','Bi ', + 'Ei ','Sha ','I ','Tuan ','Tian ','Ki ','Dan ','Dan ','Chan ','En ','Kei ','Jiong ','Iku ','Mei ','Satsu ','Wei ', + 'You ','Xin ','Kei ','Rou ','Bai ','Kan ','Ku ','Shou ','Wai ','Han ','Qiu ','Sui ','You ','Lie ','Sha ','', + 'Gao ','Gua ','Bao ','Hu ','Un ','Xia ','','','Bian ','Kou ','Tui ','Tang ','Chao ','Sen ','En ','Bo ', + 'You ','Xie ','Xi ','Wu ','Soku ','Un ','He ','Koku ','Ki ','Yun ','Yuu ','Nai ','Sen ','','Yao ','Kun ', + 'Mi ','Lian ','Kei ','Wu ','You ','Kou ','En ','Qiang ','Liu ','Ki ','Hitsu ','Hyou ','Zong ','Lu ','Jian ','Juku ', + 'Yuu ','Lou ','Hou ','Sui ','Yi ','Tong ','Jue ','Zong ','I ','Hu ','Yi ','Zhi ','Gou ','Wei ','Liao ','Zen ', + 'Ou ','Netsu ','Kei ','Man ','','Shang ','Cuan ','Zeng ','Jian ','Ki ','Ki ','Xi ','Yi ','Xiao ','Shi ','Kou ', + 'Sen ','You ','Qian ','Nen ','En ','Xian ','Qiao ','Zun ','Tou ','Ton ','Shen ','Shou ','Fun ','Si ','Ryou ','Yu ', + 'Rin ','Tong ','Shou ','Fun ','Han ','En ','Shin ','Ran ','Mei ','Tou ','Itsu ','Jing ','Mon ','','','Ei ', + 'Iku ','Yi ','Xue ','Lan ','Tai ','Sou ','San ','Sui ','Xi ','Que ','Cong ','Lian ','Ki ','Shoku ','Shou ','Ling ', + 'Wei ','Yi ','Xie ','Zhao ','Hui ','Tatsu ','Nung ','Lan ','Jiyu ','Sen ','Kao ','Kun ','Jin ','Chou ','Tou ','You ', + ], + 'x72':[ + 'Kaku ','Lan ','Biao ','Rong ','Li ','Mo ','Baku ','Zetsu ','Ryo ','Rou ','Ao ','Xun ','Kuang ','Shaku ','','Li ', + 'Ro ','Jue ','Liao ','En ','Xi ','Xie ','Long ','You ','','Rang ','Yaku ','Ran ','Cong ','Shaku ','Tong ','Kan ', + '','Che ','Mi ','Tang ','Ran ','Zhu ','Laam ','Ling ','San ','Yu ','Sou ','Tsumekanmuri ','Ha ','Sou ','Pao ','Shou ', + 'En ','Ai ','I ','','Kaku ','Shaku ','Fu ','Ye ','Ha ','Ta ','Ya ','Kou ','Sho ','Sou ','Ji ','Shou ', + 'Sou ','Ka ','Sou ','Ouchou ','Qiang ','You ','Shou ','Hen ','Han ','Pan ','Shao ','Sen ','Hai ','Du ','Sou ','Chu ', + 'Sou ','Bian ','Chou ','Bou ','Haku ','Sou ','Yuu ','','Toku ','Ga ','Tou ','Gyuu ','Ushihen ','Hin ','Kyuu ','Bou ', + 'Ta ','Bo ','Rou ','Jin ','Mang ','Fang ','Mao ','Boku ','Kou ','Motsu ','Yan ','Ka ','Hai ','Si ','Sen ','Ko ', + 'You ','Ka ','Sei ','Mu ','Tei ','Qian ','Quan ','Sen ','Shi ','Toku ','Xi ','Bou ','Kou ','Ken ','Go ','Koku ', + 'Sei ','Ri ','Ri ','Pou ','I ','Gang ','Zhi ','Hon ','Quan ','Jun ','Du ','Ju ','Jia ','Ken ','Hou ','Pian ', + 'Ke ','Ju ','Kou ','Su ','Xi ','Bei ','Raku ','Jie ','Ma ','San ','Wei ','Bou ','Dun ','Tong ','','Jiang ', + 'Gi ','Li ','Toku ','Lie ','Pi ','Piao ','Bao ','Gi ','Shuu ','Wei ','Kui ','Chou ','Ken ','Kemonohen ','Hatsu ','Han ', + 'Qiu ','Keki ','Sai ','Chuo ','Kan ','Ge ','Jou ','Guang ','Ma ','Yuu ','Kang ','Bo ','Hou ','Ya ','Gin ','Huan ', + 'Jou ','In ','Kyou ','Juu ','Teki ','Qing ','Chuu ','Boku ','Bei ','Hi ','Ju ','Ni ','Sei ','Pao ','Kou ','Tuo ', + 'Ko ','Ling ','Hi ','Pi ','Ni ','Ou ','Yuu ','Kou ','Ketsu ','Sho ','Dan ','Haku ','Gu ','Sen ','Ning ','Kan ', + 'Gan ','Kou ','Kaku ','Zhao ','Ji ','Shun ','Shan ','Ta ','Rong ','Shu ','Tong ','Lao ','Doku ','Kyou ','Shi ','Hua ', + 'Zheng ','Yu ','Sun ','Yo ','Hei ','Mang ','Xi ','Ken ','Ri ','Kyou ','Gen ','San ','Rou ','Hai ','Sei ','Yan ', + ], + 'x73':[ + 'Sha ','Li ','Kan ','Xian ','Kei ','Hai ','Fei ','Ou ','Ba ','Qi ','Gei ','Hyou ','Yin ','Rai ','Xi ','Jian ', + 'Qiang ','Kun ','En ','Ka ','Zong ','Mi ','Shou ','I ','Sei ','Sou ','Ya ','Mou ','Sai ','Sotsu ','Sha ','Ryou ', + 'Cen ','Luo ','Ko ','Zong ','Ki ','Wai ','Feng ','Ka ','En ','Sei ','Cho ','Byou ','I ','Yuan ','Ken ','Tan ', + 'Ya ','Dou ','Katsu ','Jia ','Kou ','Hen ','Yuu ','Yuu ','Mei ','Zha ','You ','Son ','Bo ','Bei ','Katsu ','En ', + 'Sou ','Ma ','Yuan ','Gai ','Goku ','Shi ','Hao ','','Yi ','Zhen ','Sou ','Hao ','Man ','Kyou ','Shou ','Baku ', + 'Shou ','Chan ','Gou ','Ao ','Hao ','Cui ','Fun ','Ketsu ','Hei ','Bi ','Huang ','Pu ','Lin ','Kitsu ','Tou ','Gyou ', + 'Ryou ','Shuo ','Xiao ','Juu ','Ton ','Xi ','Katsu ','Ken ','Doku ','Wai ','Kai ','Ken ','Kai ','Ta ','Sen ','Kun ', + 'Dou ','Hin ','Kaku ','Nou ','Meng ','Ryou ','Nyou ','Kou ','Juu ','Ro ','Datsu ','Ken ','Bi ','Rang ','Huan ','Nao ', + 'Ra ','Ken ','Qi ','Kyaku ','Gen ','Myou ','Ji ','Ritsu ','Lu ','Gyoku ','Su ','Ou ','Qiu ','Ga ','Tei ','Le ', + 'Hatsu ','Ji ','Hong ','Teki ','Chuan ','Kan ','Kyuu ','U ','Ki ','Yu ','Yang ','Ma ','Kou ','Wu ','Hu ','Bin ', + 'Kai ','Ya ','Hin ','Bian ','Bang ','Getsu ','Ketsu ','Yun ','Jue ','Gan ','Kan ','Bai ','Dan ','Hin ','Wei ','Huan ', + 'Xian ','Qiang ','Rei ','Tai ','Yi ','Gan ','Ping ','Ten ','Fu ','Ken ','Xi ','Ha ','Sei ','Kou ','Jia ','Shou ', + 'Haku ','Ci ','Ka ','Ran ','Sheng ','Shin ','I ','Zu ','Ka ','Bin ','San ','Ryuu ','Hitsu ','Chin ','Chin ','Kaku ', + 'Fa ','Long ','Shin ','Kou ','Jian ','Li ','Kou ','Xian ','Zhou ','Kyou ','Yan ','Xiu ','Yang ','Ku ','Raku ','Su ', + 'Shu ','Kin ','Gin ','Shun ','Bao ','Ji ','Kyou ','You ','Xia ','Kou ','Kei ','Chong ','Xu ','Han ','Hai ','', + 'Dang ','Ei ','Hun ','Wen ','Ga ','Tei ','Di ','Bu ','Go ','Sei ','Kun ','Bai ','Bei ','Tei ','Gen ','Shuku ', + ], + 'x74':[ + 'Kan ','Zen ','Yan ','Kyuu ','Ken ','Rou ','Ri ','Shuu ','Fu ','Ryuu ','Ya ','Xi ','Ling ','Li ','Jin ','Lian ', + 'Suo ','Sa ','','Wan ','Dian ','Pin ','Zhan ','Cui ','Min ','Yu ','Kyo ','Chin ','Lai ','Wen ','Sheng ','Wei ', + 'Dian ','Chu ','Taku ','Pei ','Sou ','Ko ','Ki ','E ','Kon ','Shou ','Ki ','Hou ','En ','Koku ','Sou ','Kan ', + 'En ','Chou ','Hai ','Rin ','Kin ','Bi ','Ha ','Que ','Zhuo ','Kin ','Hou ','','Qiong ','Du ','Jie ','Kon ', + 'U ','Bou ','Mei ','Chun ','Sen ','Tei ','Sei ','Tai ','Rou ','Min ','Zhen ','I ','Ruan ','Kan ','Jie ','Chuan ', + 'Jian ','Ten ','Chou ','Lian ','Quan ','Ka ','Duan ','En ','Ye ','Dou ','Ko ','Ei ','Yu ','Kou ','Zui ','Shitsu ', + 'Ryuu ','','You ','Sa ','You ','Wen ','O ','Shin ','Shin ','Ei ','Ba ','Tou ','Liu ','Tou ','Ritsu ','Rou ', + 'Kai ','Ten ','Shou ','Sa ','Jue ','Zhao ','You ','Ai ','Bin ','Tu ','Chang ','Kun ','Zhuan ','Cong ','Kin ','Yi ', + 'Sai ','Sou ','Qi ','Ri ','Ying ','Sou ','Kyuu ','Sen ','Ao ','Rin ','Men ','Shou ','Yin ','','Ying ','Tei ', + 'Ro ','Bu ','Tou ','xiu ','Zeng ','Xun ','Qu ','Dang ','Rin ','Ryou ','Kei ','Su ','Kou ','Gui ','Haku ','Ei ', + 'Han ','Shin ','Ryuu ','Ki ','','Jing ','Ai ','Heki ','San ','Kyo ','Sou ','Tou ','Jiao ','Gun ','Tan ','Kai ', + 'Kan ','Shitsu ','Sui ','Tian ','','Yo ','Jin ','Lu ','Bin ','Shuu ','Wen ','Sui ','Lan ','Ji ','Ji ','Sen ', + 'Ruan ','Huo ','Gai ','Lei ','Du ','Li ','Zhi ','Rou ','Rei ','San ','Kei ','Zhe ','Kai ','Sui ','La ','Rou ', + 'Ro ','Li ','Zan ','Ran ','Ei ','Mi ','Xiang ','Xi ','Kan ','Dao ','San ','Kan ','Ka ','Bo ','Tetsu ','Haku ', + 'Ko ','Zhi ','Hyou ','Ben ','Shou ','Li ','Ga ','Dekaguramu ','Kou ','Kiroguramu ','Han ','Hon ','Fang ','Dan ','Ou ','Ou ', + 'Deshiguramu ','Miriguramu ','Ton ','Hu ','Rii ','Yi ','Hei ','Shi ','Hekutogura ','Juan ','Chou ','Chi ','Sarake ','Dang ','Meng ','Hou ', + ], + 'x75':[ + 'Zhui ','Hei ','Bian ','Shuu ','Ken ','Senchigura ','Shi ','Ying ','Qi ','Xian ','Lou ','Di ','Ou ','Bou ','Sen ','Peng ', + 'Lin ','Sou ','Bu ','Heki ','Dan ','Ou ','Ou ','Gen ','Kan ','Dai ','Shin ','Ten ','Ten ','Han ','Shou ','Sei ', + 'Sei ','Shin ','San ','San ','Zui ','Sei ','So ','Shin ','You ','Shutsu ','Roku ','Ho ','You ','Beng ','Feng ','Nei ', + 'Den ','Yuu ','Kou ','Shin ','Sou ','Dian ','Futsu ','Dan ','Ten ','Hei ','Chou ','Ga ','Chou ','Ken ','Shi ','Mou ', + 'Hi ','Qi ','Liu ','Shun ','Ryuu ','Chang ','Ho ','In ','Han ','Fu ','Kou ','Ten ','Kai ','Kai ','Ken ','I ', + 'Fuku ','Hata ','Ho ','Tap ','Han ','Jiang ','Wa ','Tou ','Nan ','Ryuu ','Hon ','Shin ','Chiku ','Ho ','Bou ','Shoku ', + 'Hata ','Kai ','Hitsu ','Da ','Shi ','Ryaku ','Kei ','Ryaku ','Pan ','Kesa ','Ban ','Kaku ','Yo ','Yo ','Mu ','Shun ', + 'I ','Ryuu ','Yo ','Jou ','Chuu ','Kaku ','Tou ','Tetsu ','Ki ','Wan ','Kyou ','Shou ','Chou ','Ton ','Sui ','Ki ', + 'Cha ','Ryu ','Jou ','Tuan ','Lin ','Kyou ','Kyou ','Chuu ','Bo ','Jou ','Jou ','So ','Nie ','Dan ','So ','So ', + 'Chi ','Gi ','Daku ','Zai ','Chou ','Hi ','Jie ','Liao ','Gang ','Gitsu ','Kyuu ','Zhou ','Ka ','San ','Xu ','Nue ', + 'Li ','Yang ','Chin ','Yuu ','Ha ','Kai ','Jue ','Zhi ','Xia ','Cui ','Bi ','Eki ','Li ','Zong ','Chuang ','Feng ', + 'Zhu ','Hou ','Hi ','Kan ','A ','Shi ','Xie ','Qi ','Tan ','Shin ','Hou ','Zhi ','Tou ','Sho ','Shitsu ','Hi ', + 'Ku ','Sen ','Ka ','Ken ','Sa ','Byou ','Datsu ','Shou ','Yong ','Jing ','Sen ','Chong ','Tou ','I ','Kai ','I ', + 'Hui ','Duo ','You ','Chi ','Ji ','Kon ','Ya ','Bai ','Tou ','Kei ','Xiao ','Tsuu ','Toku ','Mang ','Hi ','Shou ', + 'San ','Ho ','Ri ','Shi ','Sa ','Duo ','Wu ','Sa ','Lao ','Sou ','Huan ','Xian ','Eki ','Peng ','Chou ','Kan ', + 'Tan ','Hi ','Ma ','Rin ','Chi ','Ji ','Dian ','An ','Chi ','Hi ','Hi ','Min ','Ko ','Dui ','A ','I ', + ], + 'x76':[ + 'Yo ','Sui ','A ','Shoku ','Shaku ','Dan ','Shen ','Shou ','Kei ','Yu ','Kou ','Fuu ','Ratsu ','You ','Shen ','To ', + 'Yu ','Gua ','Gon ','Tan ','Ku ','Ka ','In ','Yi ','Lu ','Sou ','Jue ','Sei ','Shoku ','Kan ','Ei ','On ', + 'Seki ','Sou ','Han ','Kai ','Ryuu ','Sa ','Sou ','Gyaku ','Dian ','Tou ','Pie ','Tan ','Zhang ','Hyou ','Shin ','Cu ', + 'Rui ','Yi ','Shou ','Chuu ','Shou ','Sai ','Sou ','Suo ','Ka ','Chou ','Rou ','Rou ','Baku ','Jin ','Yin ','Ying ', + 'Kou ','Fuku ','Ryou ','Ryuu ','Shou ','Ryuu ','Rou ','Kan ','Hai ','Tan ','In ','Kaku ','Gan ','Ban ','Xian ','Guan ', + 'Guai ','Nong ','Yu ','Wei ','Yi ','You ','Heki ','Lei ','Rei ','Sho ','Dan ','Lin ','Den ','Lin ','Lai ','Hetsu ', + 'Ji ','Chi ','You ','Xian ','Setsu ','Chou ','Mak6','Reki ','Kaku ','Rai ','Shaku ','Dian ','Sen ','Ei ','In ','Ku ', + 'You ','Tan ','Ten ','Luo ','Ren ','Luan ','Hatsu ','','Ki ','Po ','Hotsu ','Tou ','Hotsu ','Haku ','Hyaku ','Qie ', + 'Hyuu ','Sou ','Zao ','Bou ','Teki ','Hae ','Kai ','Kou ','Ki ','Ci ','Ling ','Kou ','Batsu ','Soku ','Kou ','Peng ', + 'Kou ','Ai ','E ','Kou ','Han ','Hyoku ','Kan ','Chou ','Qian ','Seki ','Gai ','Kyou ','Kou ','Kou ','Hao ','Saku ', + 'Sai ','Hao ','Kyou ','You ','Ha ','Kou ','Kyou ','Ai ','Sei ','Huang ','Reki ','Piao ','He ','Shaku ','Hi ','Gan ', + 'Hou ','Zhou ','Jun ','Qiu ','Shun ','Que ','Zha ','Ko ','Kun ','Kun ','Suu ','Zha ','Gu ','Ten ','Du ','Bai ', + 'Qi ','Ei ','U ','Hai ','Zhao ','Chuu ','Bon ','He ','Ei ','Ka ','Eki ','Hatsu ','Wan ','Kou ','Ou ','Zhan ', + 'Yan ','Jian ','Kou ','Yu ','Kai ','Fan ','Gai ','Tou ','Pan ','Fu ','Qiu ','Sei ','Tou ','Lu ','San ','Mei ', + 'Rei ','Jin ','Xu ','Kan ','Ban ','Kan ','Ou ','Ro ','Shu ','Zhou ','Tou ','An ','Ko ','Li ','Moku ','Ding ', + 'Kan ','Ku ','Mou ','Mang ','Choku ','Qi ','Gin ','Tian ','Shou ','Shun ','Xin ','Kei ','Han ','Feng ','Jun ','Min ', + ], + 'x77':[ + 'Bei ','Sei ','Shi ','Yun ','Ben ','Pan ','Hou ','Byou ','Tan ','Bi ','Bou ','Kan ','Ken ','Ou ','Shi ','Yang ', + 'Zheng ','Yao ','Shin ','Huo ','Tou ','Shin ','Kuang ','Ku ','Shen ','Chi ','Sei ','Mai ','Batsu ','Zhu ','Shin ','Shin ', + 'Min ','Di ','Wan ','Die ','Tei ','Sei ','Sei ','Chao ','Sou ','Gen ','Bing ','Mi ','Long ','Ki ','Tou ','Bei ', + 'Die ','Yi ','Er ','Ming ','Ken ','Shi ','Kyou ','Ken ','Bou ','Chin ','Chou ','Yang ','Gan ','Baku ','Shuu ','Mai ', + 'Chaku ','Zheng ','Bi ','Jun ','Shao ','Kan ','Kan ','Tei ','Cheng ','Cuo ','En ','E ','Wan ','Ken ','Ki ','Kon ', + 'Lai ','Jian ','Sen ','Tian ','Hun ','Wan ','Chou ','Seki ','Qiong ','Lie ','Gai ','Sei ','Sei ','Li ','Rai ','Sui ', + 'Ken ','Sui ','Ki ','Toku ','Hei ','Hei ','Boku ','Kon ','Gei ','Lu ','Eki ','Shou ','Sai ','Zhou ','Yu ','Hun ', + 'Batsu ','Ka ','Sei ','Kei ','Kon ','','Chun ','Jian ','Mei ','To ','Kou ','Xuan ','Ti ','Kei ','Kou ','Ei ', + 'Bou ','Xu ','Fa ','Wen ','Byou ','Chou ','Ki ','Mi ','Weng ','Kou ','Dang ','Shin ','Kou ','Sou ','Katsu ','Qiong ', + 'Mao ','Mei ','Man ','Shui ','Saku ','Shou ','Ei ','Diao ','Ou ','Mo ','Shun ','Cong ','Lou ','Chi ','Ban ','Hyou ', + 'Dou ','Ji ','Bou ','','Run ','Betsu ','Xi ','Shou ','Pu ','Zhu ','Dou ','Shen ','Shun ','Ryou ','Tetsu ','Kan ', + 'Kan ','You ','Xu ','Dou ','Mou ','Rin ','Ki ','Xian ','Ye ','Ai ','Hui ','Sen ','Ken ','Ko ','Shou ','Ku ', + 'Wei ','Chou ','Sao ','Gei ','Xun ','Yao ','Huo ','Mou ','Ben ','Hin ','Mian ','Li ','Kuang ','Kaku ','Xuan ','Mian ', + 'Huo ','Ro ','Bou ','Long ','Guan ','Ban ','Xi ','Chiku ','Tang ','Kan ','Shoku ','Mu ','Kin ','Lin ','Itsu ','Saku ', + 'Saku ','Jue ','Shi ','I ','Shin ','Chi ','Kou ','Shin ','Ying ','Ku ','Chuu ','Jiao ','Sa ','Tan ','Wai ','Kyou ', + 'Sou ','Waku ','Bai ','Shaku ','Tei ','Qi ','Ji ','Zi ','Kan ','Wu ','Tuo ','Kotsu ','Kou ','Xi ','Fan ','Kuang ', + ], + 'x78':[ + 'Dang ','Ma ','Sa ','Dan ','Jue ','Rei ','Hu ','Min ','Nuo ','Keki ','Kang ','Zhi ','Sei ','Kan ','Kai ','Fen ', + 'E ','Ga ','Hi ','Zhe ','Ken ','Sai ','Zhuan ','Che ','Dun ','Pan ','Yan ','','Feng ','Kyou ','Mo ','Zha ', + 'Sho ','Giku ','Ra ','Ta ','Tuo ','Shi ','Sai ','Chin ','Ai ','Fei ','Mu ','Zhu ','Li ','Hen ','Do ','Ping ', + 'Hou ','Ling ','Hou ','Le ','Ha ','Ou ','Po ','Shin ','Za ','Nuo ','Rei ','Long ','Tong ','','Li ','Kou ', + 'Chu ','Keng ','Quan ','Shu ','Kou ','Kei ','E ','Dou ','Katsu ','Lu ','Wei ','Ai ','Raku ','Ken ','Kei ','Ken ', + 'Tong ','Peng ','Sei ','','Hong ','Shuo ','Xia ','Qiao ','','Gai ','Qiao ','','Kou ','Shou ','Kaku ','Chan ', + 'Rou ','Kou ','Yu ','Kou ','Kou ','Mang ','Long ','Yong ','Sha ','Che ','Gi ','Ryuu ','Kou ','Mang ','Kaku ','Ken ', + 'Sha ','Kun ','Hazama ','','Kaki ','Lu ','Chen ','Jian ','Nue ','Song ','Taku ','Keng ','Hou ','Yan ','Tsui ','Kong ', + 'Ceng ','Go ','Zong ','Qing ','Lin ','Jun ','Ha ','Tei ','Min ','Diao ','Sen ','He ','Roku ','Gai ','Sai ','Shaku ', + 'Ling ','Hi ','Yin ','Tai ','Bu ','Ki ','Lun ','Wan ','Ten ','Gang ','Hai ','Qi ','Chen ','Zen ','Gan ','Katsu ', + 'Ding ','Toku ','Tuo ','Ketsu ','Ei ','Bian ','Ke ','Heki ','Wai ','Seki ','Chin ','Duan ','Ka ','Tou ','Ti ','Dou ', + 'Hou ','Ken ','Tei ','Tan ','Cha ','Seki ','Qi ','','Feng ','Xuan ','Kaku ','Kaku ','Ba ','Kou ','Ten ','Sotsu ', + 'E ','Ji ','Liu ','Si ','Tang ','Hou ','Katsu ','Hei ','I ','Sou ','Rai ','Sa ','Ten ','Xia ','Kei ','Lian ', + 'Han ','Gai ','In ','Tai ','Taku ','Kai ','Rou ','','Qing ','Gun ','Sen ','San ','Qi ','Ao ','Peng ','Riku ', + 'Ro ','Kan ','Qiang ','Chen ','In ','Lei ','Hyou ','Seki ','Ma ','Qi ','Sai ','Zong ','Kei ','Chuo ','','Ki ', + 'Shan ','Lao ','Kyo ','Sou ','Tou ','Jian ','Seki ','Rin ','Ding ','Dian ','Kou ','Han ','Za ','Kou ','Di ','Reki ', + ], + 'x79':[ + 'Kan ','Shou ','','Zhang ','Qiao ','Dun ','Ken ','Iku ','Zhui ','He ','Huo ','Zhai ','Rai ','Ke ','So ','Ji ', + 'Kaku ','Tou ','Gi ','Jiang ','Pi ','Pi ','Yu ','Pin ','Qi ','Gai ','Kai ','Jian ','Yo ','Ruan ','Bou ','Hou ', + 'Ji ','Haku ','','Mie ','Ca ','Kin ','Kou ','Rai ','Lei ','Shitsu ','Rei ','Reki ','Ban ','Kaku ','Pao ','Ying ', + 'Li ','Rou ','Long ','Mo ','Haku ','Sou ','Guan ','Lan ','Zan ','Yan ','Shi ','Shi ','Rei ','Jou ','Sha ','Yaku ', + 'Shi ','Ki ','Ta ','Ma ','Kai ','You ','Ken ','Ki ','Ki ','Shi ','Hou ','Tai ','Zhong ','','Yi ','Seki ', + 'Yuu ','Chitsu ','Tiao ','Futsu ','Hu ','Hi ','So ','Shi ','San ','Mi ','So ','Kyo ','Ko ','Shuku ','Shin ','Sui ', + 'Shi ','Chai ','Dei ','Lu ','Yu ','Shou ','Wu ','Chou ','Hyou ','Shu ','Gui ','Kou ','Zhi ','Sai ','Gao ','Zhen ', + 'Gao ','Shui ','Shin ','Chen ','Gai ','Kun ','Di ','Tou ','Huo ','Tou ','Ki ','Ko ','Kan ','Zui ','Ryou ','Roku ', + 'Rin ','Kin ','Dao ','Zhi ','Roku ','Zen ','Bei ','Zhe ','Hui ','You ','Kei ','In ','Shi ','Ka ','Tei ','Fuku ', + 'Yuan ','Gu ','Xian ','You ','Shi ','I ','Bai ','Si ','Tei ','','Zhuo ','Shin ','Ei ','Shoku ','Gao ','Tang ', + 'Si ','Ba ','Ta ','','Xuan ','Qi ','Gyo ','Ki ','Ki ','Shi ','Zen ','Tan ','Kuai ','Sui ','Rei ','Jou ', + 'Dei ','Tou ','Li ','Jou ','Yaku ','Ti ','Zan ','Lei ','Juu ','U ','Guu ','Chi ','Xie ','Kin ','Ka ','Toku ', + 'Shuu ','Shi ','Jin ','Toku ','Shi ','Cha ','Gan ','Gei ','Sen ','Hei ','Nen ','Shuu ','Qiu ','Chuu ','Fen ','Kou ', + 'Yun ','Ka ','Byou ','Zhi ','Kou ','Hi ','Shi ','Yu ','Hi ','Ku ','Han ','Pi ','Ni ','Reki ','Yuu ','So ', + 'Hi ','Hatsu ','Rei ','Matsu ','Shou ','Den ','Shin ','Ou ','Zuo ','Chitsu ','Chi ','Jotsu ','Kyo ','Shi ','Huo ','Ji ', + 'Shou ','Tou ','Zhi ','Huo ','He ','Yin ','Zi ','Zhi ','Katsu ','Ren ','Du ','I ','Shu ','Hui ','Nong ','Fu ', + ], + 'x7a':[ + 'Ki ','Kao ','Rou ','Hu ','Ze ','Zei ','Lu ','Kon ','Kan ','Kou ','Tei ','Tei ','To ','Sou ','Zei ','Ya ', + 'Lun ','Riku ','Gu ','Zuo ','Jin ','Shun ','Bang ','Hai ','Ki ','Choku ','Chi ','Kon ','Ryou ','Peng ','Ka ','Rin ', + 'Chuu ','Sotsu ','Yu ','Su ','Lue ','','Yi ','Kei ','Bian ','Ji ','Fu ','Hyoku ','Nuo ','Katsu ','Shu ','Sou ', + 'Sho ','Shou ','Tou ','On ','Ren ','Shi ','Yu ','Shoku ','Kiku ','Shin ','Chi ','Tou ','Ka ','Kei ','Kou ','Kou ', + 'Koku ','Rong ','Sui ','You ','Sei ','Kou ','Boku ','San ','Bon ','Chi ','Ji ','Lu ','So ','Seki ','Ei ','On ', + 'Shuu ','Se ','','Yi ','Huang ','Shou ','Ki ','Sui ','Xiao ','Hoku ','Jiao ','Zhuo ','Tou ','Sai ','Lu ','Sui ', + 'Jou ','Shoku ','Ai ','Jou ','Nuo ','Yo ','','Sei ','Tui ','On ','Shou ','Kaku ','Gong ','Ryo ','Biao ','', + 'Jou ','Zhuo ','Li ','Zan ','Ketsu ','Atsu ','Kyuu ','Qiong ','Seki ','Kyuu ','Kuu ','Yu ','Sen ','Sei ','You ','Sen ', + 'Chun ','Totsu ','Rou ','Setsu ','Saku ','You ','Bin ','Bao ','You ','Bing ','Wa ','Chutsu ','Jiao ','Qiao ','Diao ','Wu ', + 'Kei ','You ','Chitsu ','Sou ','You ','Chou ','Kou ','Sou ','Kin ','Xiao ','Cheng ','Kou ','Cuan ','Wo ','Tan ','Kutsu ', + 'Ka ','Zhui ','Xu ','Sotsu ','','Kui ','Dou ','','Yin ','Ka ','Wa ','Ya ','Yu ','Ju ','Kyuu ','You ', + 'You ','Tiao ','Chao ','Wa ','Tian ','Chou ','Ku ','Liao ','Xi ','Go ','Ki ','Sou ','Sou ','Fun ','Kuan ','Ryuu ', + 'Cheng ','Cui ','Piao ','Sou ','Zan ','Kyou ','Kyuu ','Tou ','Sou ','Rou ','Setsu ','Ritsu ','Sho ','Dekaritto ','Fuu ','Kirorittoru ', + 'Chu ','Kou ','Ki ','Miririttoru ','','Deshiritto ','Shu ','Miao ','Ju ','Tan ','Cho ','Rei ','Ryuu ','Hei ','Jing ','Kei ', + 'Shou ','Hekutoritto ','Shi ','Shun ','Hong ','Dou ','Shou ','Jing ','Chou ','Gi ','Ju ','Sei ','Ku ','Ketsu ','Ping ','Tan ', + 'Senchiritto ','Sen ','Ceng ','Deng ','Shun ','Huai ','Kyou ','Kan ','Kei ','Chiku ','Toku ','Roku ','Hou ','U ','Shi ','Kan ', + ], + 'x7b':[ + 'Mang ','Zhu ','Utsubo ','Du ','Kei ','Xiao ','Ha ','San ','Kyuu ','Zhen ','Sou ','Jun ','Ya ','Zhui ','Yuan ','Kotsu ', + 'Gang ','Shou ','Cen ','Pi ','Hitsu ','Jian ','Yi ','Dong ','Sen ','Sou ','Xia ','Teki ','Zhu ','Na ','Chi ','Ko ', + 'Ryuu ','Qie ','Min ','Hou ','Tiao ','Shi ','Fu ','Saku ','Hon ','Hai ','Tan ','Shi ','Dai ','Rei ','Saku ','Do ', + 'Hutsu ','Kou ','Fan ','Ka ','Ka ','Han ','Shi ','Mao ','Po ','Sasa ','Jian ','Qiong ','Long ','Souke ','Bian ','Raku ', + 'Kei ','Kyoku ','Chi ','Yin ','Yao ','Sen ','Hitsu ','Kyou ','Katsu ','Tou ','Jiao ','Kin ','Sen ','Jun ','Jo ','Batsu ', + 'Kyou ','Chiku ','Tou ','Ji ','Tou ','Kou ','Saku ','Zhong ','Kou ','Lai ','Bi ','Shai ','Dang ','Sou ','Ce ','Fu ', + 'In ','Tu ','Pa ','Li ','Rou ','Kyo ','Kan ','Ken ','Han ','Tou ','Kou ','Zhi ','Sei ','San ','Sei ','Cho ', + 'Saku ','Shou ','Sou ','Tei ','Kyou ','En ','Gao ','Kai ','Gan ','Chou ','Kyou ','Gang ','Yun ','O ','Qian ','Shou ', + 'Jian ','Pu ','Lai ','Zou ','Hai ','Bi ','Hei ','Ka ','Chi ','Kai ','Yu ','Sen ','Zhao ','Ko ','Ko ','Sou ', + 'Sei ','Sou ','Sou ','Lu ','Haku ','Ki ','Rin ','San ','Kin ','Fuku ','Satsu ','Ko ','Kou ','Kan ','Ken ','Kin ', + 'Sui ','Kan ','Yuan ','Ce ','Ju ','Ha ','Ze ','Qie ','Tuo ','Luo ','Tan ','Xiao ','Joku ','Sen ','','Hen ', + 'Shun ','Shou ','Sen ','Ping ','Shin ','Sei ','Ko ','Shi ','Cho ','Yue ','Shun ','Ritsu ','Oku ','Tou ','Shuo ','Ji ', + 'Setsu ','Kou ','Sei ','Mei ','Han ','Sui ','Ten ','Hen ','Hou ','Chiku ','Kou ','Kyou ','Kou ','Qiu ','Miao ','Kan ', + '','Kui ','Sik ','Lou ','Un ','He ','Tou ','Waku ','Chou ','Kou ','Hi ','Jaku ','Zheng ','Kou ','Nie ','Qian ', + 'Shou ','San ','Gong ','Pang ','Toku ','Ritsu ','Hei ','Zhuo ','Cho ','Shi ','Chi ','Zhu ','Qiang ','Rou ','Lan ','Jian ', + 'Bu ','Li ','Sui ','Hitsu ','Teki ','Sou ','En ','Hou ','Shin ','San ','Hai ','Piao ','Tou ','Yu ','Betsu ','Zhuan ', + ], + 'x7c':[ + 'Saku ','Shi ','Ke ','I ','Ko ','Chan ','Kou ','Sou ','Ping ','Shuu ','Ji ','Ki ','Soku ','Rou ','Saku ','Roku ', + 'Nian ','Sa ','San ','Sen ','Sa ','Le ','Duan ','Yana ','Shou ','Haku ','Mi ','Shi ','Dang ','Liao ','Tan ','Ten ', + 'Hu ','Kan ','Min ','Ki ','Dai ','Kyou ','Tou ','Kou ','Shun ','Lao ','Shin ','Shou ','Ro ','Shi ','Zan ','', + 'Pai ','Hata ','Pai ','Kan ','Kyo ','Du ','Roku ','En ','Ha ','Tou ','Sai ','Ke ','Long ','Sen ','Ren ','Bo ', + 'Chuu ','Lai ','','Ran ','Kui ','Yu ','Waku ','Hao ','Zhen ','Tai ','Teki ','Mi ','Chuu ','Seki ','','Hata ', + 'Tou ','Sen ','Shuu ','Han ','Su ','Ryuu ','Sen ','Zhuo ','Tou ','Ryoku ','Ro ','Sen ','Taku ','Ei ','Gyo ','Rai ', + 'Rou ','Shinshi ','Lian ','Ran ','Sen ','Yaku ','Zhong ','Kyo ','Lian ','Hen ','Duan ','Zuan ','Ri ','Shi ','Ra ','Ying ', + 'Waku ','Zhuo ','Yu ','Bei ','Di ','Dekameetoru ','Shen ','Zhe ','Shen ','Jo ','Xie ','Lei ','Sen ','Shi ','Momi ','Cun ', + '','Kiromeetoru ','Kume ','Hi ','Ban ','Wu ','Sa ','Kou ','Rou ','Fun ','Bi ','Sui ','','Mirimeetoru ','Chi ','Ta ', + 'Ro ','Ba ','Ryuu ','Gan ','Kyo ','Haku ','Mo ','So ','Nen ','Zhou ','Li ','Shuku ','Tiao ','Li ','Sei ','Zoku ', + 'Kou ','Tou ','Shi ','Ce ','Etsu ','Shuku ','Rin ','Shou ','Hekutomeetoru ','','Fen ','Ji ','','Sukumo ','Ryou ','Xian ', + 'Fuu ','Ryou ','San ','Kou ','Li ','Etsu ','Roku ','Kiku ','Qi ','Sui ','Hai ','Chou ','Rin ','Sou ','Sei ','Ka ', + 'Kouji ','San ','San ','Tang ','Hen ','Juu ','Mian ','Kou ','Sho ','Sou ','Ko ','Jian ','Zan ','Shi ','Senchimeeto ','Setsu ', + 'Fu ','Ni ','Hi ','Koku ','Shuu ','Kou ','Tou ','Kyuu ','Sukumo ','Sou ','Sou ','Tang ','Bi ','San ','Fun ','Sou ', + 'Kou ','Jiang ','Bo ','San ','San ','Nuo ','Shi ','Ryou ','Jiang ','Kai ','Bo ','Kai ','','Zong ','Xian ','Da ', + 'Dan ','Nie ','Rei ','Zuo ','Teki ','Getsu ','Chou ','Lan ','Shi ','Si ','Kyuu ','Kei ','Gong ','Zheng ','Kyuu ','You ', + ], + 'x7d':[ + 'Ki ','Cha ','Chuu ','Shun ','Yaku ','Ku ','U ','Kotsu ','Kan ','Jin ','Bin ','Mon ','Qiu ','Tou ','Zi ','Tou ', + 'Chuu ','Huu ','Kei ','Sho ','Shun ','Hi ','Chin ','Sa ','Kou ','Shi ','Kyuu ','Fun ','Un ','Jin ','Tan ','Jin ', + 'So ','Bou ','Saku ','Sai ','Jiu ','Zha ','Ha ','Jin ','Fu ','Zhi ','Sei ','Shi ','Chuu ','Kou ','Satsu ','Rui ', + 'Sei ','Hutsu ','Setsu ','Shin ','Bei ','Cho ','Qu ','Ling ','Zhu ','Shou ','Kon ','Yang ','Hutsu ','Ta ','Shin ','Tai ', + 'Chutsu ','Shi ','Shuu ','Gen ','So ','Kei ','Ban ','Ku ','Baku ','Shu ','Zui ','Kou ','Kei ','Jin ','Kou ','Setsu ', + 'Ketsu ','Shu ','Chou ','Kai ','Bai ','Zetsu ','Kou ','Kotsu ','Ci ','Kan ','Kou ','Jou ','Ketsu ','Ku ','Kou ','Quan ', + 'Gai ','Raku ','Ken ','Hou ','Xian ','Hi ','Kyuu ','Tou ','Juu ','Tiao ','In ','Lei ','Xie ','Quan ','Jo ','Gai ', + 'Tetsu ','Tou ','Shi ','Kou ','Xiang ','Kai ','Zetsu ','Zhi ','Ken ','Ken ','Chi ','Bun ','Zhen ','Ryo ','Cheng ','Kyuu ', + 'Shu ','Hou ','Tou ','Shou ','Wan ','Shin ','Kou ','Xiu ','Tei ','Tou ','Xie ','Kou ','Keki ','Hutsu ','Ting ','Sui ', + 'Dui ','Kon ','Fu ','Kei ','Hu ','Zhi ','En ','Gei ','Feng ','Kei ','Zoku ','Kase ','Sou ','Chin ','Ta ','Rei ', + 'Ryoku ','Liang ','Chuu ','Ken ','Shao ','Qi ','Ki ','Shun ','Qi ','Wan ','Sen ','Sen ','Ju ','I ','Kei ','Tou ', + 'Wan ','Kou ','Mou ','Hou ','Tei ','Sai ','Kuwa ','Sai ','Rin ','Ryuu ','Ki ','Tan ','Bei ','Shaku ','Ryou ','Men ', + 'Qi ','Qie ','Tan ','Shou ','Kon ','Shuu ','Seki ','Shi ','Xing ','Liang ','Kin ','Hi ','Zui ','Bin ','Yoku ','Sou ', + 'Fan ','Ryoku ','Sho ','Ying ','Zhang ','Kasuri ','Sho ','Shou ','Kan ','Kaku ','Sen ','Ruan ','Ben ','Shuu ','Tan ','Zhong ', + 'Tei ','Bin ','Bou ','En ','Setsu ','Hou ','Shi ','Qiu ','Hen ','Kan ','Kou ','Sou ','Men ','I ','Fu ','I ', + 'Yu ','Kou ','Byou ','Xie ','Ren ','Sou ','Hen ','Yun ','Yin ','Tei ','Kai ','Chi ','Un ','Cheng ','Chan ','Dai ', + ], + 'x7e':[ + 'Ka ','En ','Sou ','Xu ','Jou ','Odoshi ','Kou ','Sen ','Ei ','Shin ','Ei ','Tsui ','Ni ','Bang ','Gu ','Pan ', + 'Shuu ','Ken ','Sa ','Quan ','Shuang ','Un ','Xia ','Sai ','Xi ','Rong ','Tao ','Baku ','In ','Shin ','Kou ','Joku ', + 'Koku ','Sai ','Tou ','Ken ','Su ','Zhen ','Juu ','Tou ','Kou ','Cai ','Bi ','Hou ','Shuku ','Ri ','Shuku ','En ', + 'Xi ','Juu ','Rui ','Ten ','Ken ','Ban ','Chuu ','Ru ','Mo ','Hyou ','Ren ','Bi ','Xuan ','Sou ','Seki ','San ', + 'Sui ','Han ','Shuai ','Hou ','Ei ','Sou ','Kyuu ','You ','Kyou ','Hun ','Sen ','Kei ','Zung ','Shuu ','Bin ','Xuan ', + 'Kei ','Qiao ','Shou ','Zuo ','Shoku ','Zen ','San ','Lin ','Kitsu ','Han ','Ryou ','Chuo ','Zun ','Kan ','Jou ','Sen ', + 'Rui ','Shuu ','Kai ','Hua ','San ','Ki ','Kyou ','Un ','Da ','Jou ','Kai ','Kei ','Se ','Ken ','Kyou ','Ken ', + 'Sou ','Cong ','Jie ','Shaku ','Bo ','Chan ','Yi ','Nao ','Sui ','Eki ','Shai ','Ju ','Kei ','Hin ','Ten ','Ran ', + 'Pu ','Kun ','San ','Kasuri ','Peng ','Li ','Boku ','Rai ','Ketsu ','San ','Kou ','You ','Zoku ','Rui ','Sen ','Ten ', + 'Kou ','Ro ','Ten ','Ei ','San ','Shou ','Sen ','Zui ','Sab ','Luo ','Shi ','Tou ','Ran ','Rui ','Ren ','Si ', + 'Jiu ','Yu ','Hong ','Zhou ','Xian ','He ','Yue ','Ji ','Wan ','Kuang ','Ji ','Ren ','Wei ','Yun ','Kou ','Chun ', + 'Pi ','Sha ','Gang ','Na ','Ren ','Zong ','Lun ','Fen ','Zhi ','Wen ','Fang ','Cho ','Yin ','Niu ','Shu ','Xian ', + 'Gan ','Xie ','Fu ','Lian ','Zu ','Shen ','Xi ','Zhi ','Zhong ','Zhou ','Ban ','Fu ','Zhuo ','Shao ','Yi ','Jing ', + 'Dai ','Bang ','Rong ','Jie ','Ku ','Rao ','Die ','Heng ','Hui ','Gei ','Xuan ','Jiang ','Luo ','Jue ','Jiao ','Tong ', + 'Geng ','Xiao ','Juan ','Xiu ','Xi ','Sui ','Tao ','Ji ','Ti ','Ji ','Xu ','Ling ','Ying ','Xu ','Qi ','Fei ', + 'Chuo ','Zhang ','Gun ','Sheng ','Wei ','Mian ','Shou ','Beng ','Chou ','Tou ','Liu ','Quan ','Zong ','Zhan ','Wan ','Lu ', + ], + 'x7f':[ + 'Zhui ','Zi ','Ke ','Xiang ','Jian ','Mian ','Lan ','Ti ','Miao ','Qi ','Yun ','Hui ','Si ','Duo ','Duan ','Bian ', + 'Sen ','Gou ','Zhui ','Huan ','Di ','Lu ','Bian ','Min ','Yuan ','Jin ','Fu ','Ru ','Zhen ','Feng ','Shuai ','Gao ', + 'Chan ','Li ','Yi ','Jian ','Bin ','Piao ','Man ','Lei ','Ying ','Suo ','Mou ','Sao ','Xie ','Liao ','Shan ','Zeng ', + 'Jiang ','Qian ','Zao ','Huan ','Jiao ','Zuan ','Kan ','Sha ','Kou ','Fou ','Ketsu ','Fu ','Ketsu ','Hachi ','Hei ','Tou ', + 'Diu6','Gang ','Ying ','Ou ','Kei ','Ka ','Guan ','Son ','Tan ','Cang ','Qi ','Weng ','Ou ','Rai ','Tan ','Ro ', + 'Kan ','Bou ','Mou ','Mou ','Bou ','Kan ','','Luo ','Fu ','Mi ','Fa ','Ro ','Shu ','Sha ','Mao ','Ko ', + 'Bin ','Kou ','Ba ','Kai ','Tei ','Ken ','Hu ','Shin ','An ','Tou ','Zai ','Kei ','Zhuo ','Yoku ','Chi ','An ', + 'Batsu ','Gun ','Sho ','Si ','Pi ','Ba ','Ryuu ','Hi ','Batsu ','Ri ','Chao ','Wei ','Bi ','Kei ','Sou ','Shou ', + 'Ryuu ','Ji ','Ken ','Beki ','Zhao ','Ra ','Hi ','Ki ','Ki ','Luan ','You ','Ba ','Kyou ','Tatsu ','Bi ','You ', + 'Yuu ','Yuu ','Fen ','Ba ','Kou ','Yang ','Ko ','Kyou ','Sou ','Gao ','Rei ','Yi ','Cho ','Tei ','Shuu ','Qian ', + 'Yi ','Sen ','Jou ','Gun ','Gun ','Qiang ','Kan ','Suo ','Sen ','Gi ','You ','Qiang ','Xian ','Yu ','Kou ','Katsu ', + 'Tang ','Yuan ','Gi ','Fan ','Sen ','Fen ','Sen ','Lian ','Rui ','Kou ','Nou ','Qiang ','San ','U ','Gong ','Gei ', + 'Chuu ','Ou ','Fen ','Kou ','Chi ','Shi ','Sui ','Fu ','Kou ','Pen ','Yoku ','La ','Yoku ','Pi ','Rei ','Ryuu ', + 'Zhi ','Qu ','Shuu ','Xie ','Shou ','Kyuu ','Xi ','Qi ','Qiao ','Hui ','Hui ','Yuu ','Se ','Hong ','Jiang ','Keki ', + 'Sui ','Hi ','Tao ','Sou ','Chi ','Sho ','Sen ','Xuan ','Shi ','Hen ','Zong ','Gan ','Ki ','Hou ','Kaku ','Koku ', + 'Kan ','Ao ','Hyou ','Ei ','Lian ','Qu ','','Lin ','Pen ','Gyou ','Gou ','Hon ','Yoku ','Kai ','Ken ','Tou ', + ], + 'x80':[ + 'You ','Rou ','','Kou ','Mou ','Sha ','Ki ','Kou ','Kou ','Kou ','Tetsu ','Tetsu ','Ji ','Sa ','Zen ','Ji ', + 'Tai ','Tan ','Rai ','Tei ','Shi ','Kou ','Sou ','Mou ','Un ','Ha ','Pi ','Chi ','Shi ','Sho ','Ka ','Kyo ', + 'Kou ','Jo ','Lao ','Lun ','Seki ','Tang ','Gou ','Lou ','Dou ','Jiang ','Pang ','Ze ','Rou ','Ji ','Rou ','Huo ', + 'Yuu ','Mo ','Huai ','Ji ','Chou ','Tei ','Ya ','Tou ','Song ','Kin ','Un ','Chi ','Tan ','Tan ','Kou ','Kou ', + 'Shoku ','','Nie ','Dan ','Shin ','Che ','Rei ','Zheng ','You ','Wa ','Ryou ','Long ','Zhi ','Ning ','Tiao ','Er ', + 'Ya ','Die ','Katsu ','','Lian ','Hao ','Sei ','Lie ','Hei ','Jing ','Shuu ','Bi ','Di ','Guo ','Bun ','Sei ', + 'Hei ','Sou ','Shikato ','','Tei ','Yu ','Sou ','Kui ','Ren ','Kui ','Cong ','Ren ','Weng ','Ki ','Ren ','Ren ', + 'Sou ','Gou ','Sei ','Shou ','Chou ','Gai ','Jou ','Shoku ','Dan ','Dei ','qie ','Ji ','Chou ','Chou ','Rou ','Itsu ', + 'Yu ','Chou ','Si ','Su ','I ','Shuku ','Shi ','Chou ','Chou ','Niku ','Yi ','Roku ','Ki ','Qiu ','Kou ','Cao ', + 'Ge ','Di ','Huan ','Kou ','Yi ','Ren ','Shou ','Ru ','Chuu ','Yuan ','To ','Kou ','Yuu ','Kan ','Sa ','Wo ', + 'Chang ','Ko ','Shi ','Han ','Fu ','Hi ','Fun ','Hai ','Pang ','Ken ','Bou ','Shun ','Yuu ','Dotsu ','Hang ','Kou ', + 'Ran ','Kou ','Iku ','Wen ','Kou ','Jin ','Pi ','Qian ','Kitsu ','Hi ','Hai ','Ken ','Jing ','Tai ','Shen ','Zhong ', + 'Zhang ','Xie ','Shen ','I ','Chuu ','Die ','Tan ','Fei ','Hatsu ','Bo ','Ku ','Tian ','Hai ','Ko ','Tai ','Shi ', + 'Ku ','Zhi ','Dei ','Ping ','Shi ','Hu ','Han ','Shin ','Ken ','So ','Hai ','Kou ','Sheng ','Chi ','Hou ','Mu ', + 'Kyo ','Ko ','Ke ','Yi ','In ','Sho ','Yang ','Long ','Dong ','Ka ','Lu ','Jing ','Nu ','In ','Hou ','Ko ', + 'I ','Kou ','Kai ','Kaku ','Dou ','Zhi ','Kou ','Xiong ','Kyou ','Ji ','Atsu ','Xing ','Hen ','Nou ','Shi ','', + ], + 'x81':[ + 'Cheng ','Tiao ','Shi ','Zei ','Mei ','Kyou ','Zei ','Kyou ','Myaku ','Myaku ','Seki ','Kyou ','Nin ','Kuai ','Sa ','Zang ', + 'Qi ','Nao ','Mi ','Nong ','Luan ','Wan ','Hotsu ','Bun ','Kan ','Qiu ','Kyaku ','Kei ','Ju ','Heng ','Sa ','Lie ', + 'Sen ','Ting ','Mei ','Shin ','Shin ','Qian ','Te ','Sai ','Cu ','Shuu ','Xin ','Datsu ','Hou ','Cheng ','Nei ','Ho ', + 'Tou ','Datsu ','Niao ','Nou ','Pi ','Ko ','Gua ','Li ','Lian ','Chou ','Zei ','Jie ','Ryou ','Zhou ','Hi ','Biao ', + 'Lun ','Hen ','Guo ','Kui ','Chui ','Tan ','Ten ','Dai ','Jing ','Jie ','Seki ','Eki ','You ','Ren ','Jin ','Chuo ', + 'Fu ','Fu ','Kyo ','Hi ','Kou ','Wan ','Dong ','Hi ','Kaku ','Zong ','Ding ','Wu ','Mei ','Ruan ','Zhuan ','Chitsu ', + 'Sou ','Ra ','Ou ','Di ','An ','Sei ','Nou ','Shu ','Sen ','Dan ','Yun ','Shou ','Rou ','Gaku ','Sai ','Totsu ', + 'You ','Ken ','Wei ','Jiao ','Yu ','Jia ','Duan ','Hyoku ','Chou ','Fuku ','Sen ','Ni ','Mian ','Otsu ','Teng ','Tai ', + 'Hou ','Ken ','Ryo ','Otsu ','Shuu ','Tou ','So ','Zhui ','Kaku ','Yi ','Haku ','Ryou ','Seki ','Pi ','Kai ','Kou ', + 'Ryo ','Bin ','','Chou ','Lu ','Kaku ','Hou ','Chuai ','Hyou ','Jiang ','Fu ','Tou ','Maku ','Shitsu ','Sen ','Lu ', + 'Kou ','Ying ','Rou ','Chitsu ','Tara ','Chun ','Lian ','Tong ','Bou ','Ji ','Zha ','Liao ','Cui ','Gui ','Kyou ','Teng ', + 'Han ','Zhi ','Shou ','Sen ','Ko ','Sui ','Run ','Xiang ','Zui ','Fen ','You ','Tan ','Zhua ','Tan ','Kai ','Dou ', + 'Den ','Lian ','Hi ','You ','Jue ','Shoku ','Oku ','Juan ','Rou ','Ren ','Sou ','Den ','Gu ','Sei ','Sui ','Hin ', + 'Xun ','Dau ','Huo ','Zou ','Xian ','Hyou ','Xing ','Kon ','Rou ','En ','Ryo ','Koku ','Zang ','Ra ','Ku ','Zou ', + 'Ren ','Dei ','Zang ','Shin ','Kan ','Ga ','Guang ','Zou ','Rin ','Guang ','Shi ','Kyou ','Nie ','Shuu ','Ji ','Gao ', + 'Shuu ','Ben ','Getsu ','Shi ','Chi ','Kaku ','Sen ','Die ','Jitsu ','Shuu ','Tai ','Shin ','Kyuu ','Kan ','Yu ','Sou ', + ], + 'x82':[ + 'You ','Yo ','Shou ','Shaku ','Shaku ','Kyuu ','Yu ','Yo ','Kyou ','Kyo ','Kyuu ','Xin ','Zetsu ','Sha ','Sha ','Kyuu ', + 'Shi ','Tan ','Jo ','Shi ','Ten ','Dan ','Ho ','Ho ','Kan ','Kuu ','Ten ','Sen ','Shun ','Katsu ','Bu ','Shuu ', + 'Dao ','Kou ','San ','Yi ','','Pa ','Tai ','Fan ','Han ','Sen ','Kou ','Hou ','Han ','Que ','Ro ','Zhong ', + 'Jian ','Cang ','Rei ','Chiku ','Taku ','Ta ','Haku ','Ken ','Ka ','Sen ','Kou ','Lu ','Hong ','Pang ','Xi ','', + 'Fu ','Zao ','Feng ','Ri ','Sou ','Yo ','Rou ','Tei ','','Wei ','Bo ','Mou ','Nian ','Ju ','Kou ','Shuu ', + 'Zong ','Hen ','Mao ','Die ','Dou6','Bang ','Sa ','Yi ','Sou ','Sou ','Sou ','Lou ','Tai ','Sori ','Yao ','Dou ', + 'Tou ','Dang ','Shou ','Ro ','Gi ','Jie ','Kan ','Waku ','Mou ','Qi ','Ro ','Ro ','Chan ','Sou ','Kon ','Ryou ', + 'Jian ','Kan ','Shoku ','Yan ','Hotsu ','Ping ','En ','En ','Sou ','','Yi ','Roku ','Ting ','Kyuu ','Gai ','Jou ', + 'Shou ','Kou ','Jie ','Hou ','Kan ','Yi ','Chai ','Ben ','Ba ','Kai ','Sen ','U ','Yu ','Shaku ','Kyuu ','Tu ', + 'Xia ','Ki ','Bou ','Zi ','Ki ','Sui ','Chi ','Xiang ','Hi ','Fu ','Ton ','I ','Wu ','Shi ','Qi ','San ', + 'Bun ','Ken ','Ren ','Huu ','Kou ','Kai ','Ro ','Cho ','Kyuu ','Kin ','Ki ','Gen ','Fun ','Ba ','Zei ','Shin ', + 'Ki ','Ka ','Kuwa ','Hou ','Butsu ','Jue ','Gou ','Shi ','Gei ','Kin ','Ou ','Suu ','Bou ','Ga ','Hi ','Jou ', + 'Hang ','Cong ','Yin ','You ','Bian ','Gai ','Susa ','Wei ','Li ','Pi ','E ','Xian ','Chang ','Cang ','Meng ','Su ', + 'Tei ','En ','Zen ','Rei ','Tai ','Chou ','Di ','Byou ','Qiong ','Ryuu ','You ','Ka ','Boku ','Pei ','Hou ','Kou ', + 'Bin ','I ','I ','Kyo ','Hi ','Jaku ','Ku ','Cho ','Dei ','Bo ','Hei ','Sen ','Qiu ','You ','Xian ','Hon ', + 'Hong ','Ei ','Zha ','Tou ','So ','Die ','Detsu ','Kan ','Hu ','Hei ','Mai ','Fu ','Sheng ','Ko ','Hitsu ','Wei ', + ], + 'x83':[ + 'Hutsu ','Satsu ','Mo ','Han ','Ka ','Bou ','Bou ','Hatsu ','Shi ','Matsu ','Shi ','Shi ','Chi ','Kyoku ','Kei ','Long ', + '','Niao ','','Xue ','Ying ','Qiong ','Kaku ','Mei ','Ri ','Rong ','Yin ','Kon ','Sen ','Sai ','Shin ','Itsu ', + 'Xiu ','U ','Retsu ','Go ','Ji ','Gui ','Ce ','Chong ','Shi ','Gou ','Guang ','Bou ','Shi ','Keki ','Shou ','Fuku ', + 'Yu ','Shu ','Ji ','Kou ','Kai ','In ','Cha ','Hai ','Jou ','Jo ','Shuu ','Mang ','Tou ','Chuu ','','Zhu ', + 'Jun ','Huan ','Ka ','Sen ','Kai ','Tou ','Kei ','Kou ','Chuan ','Sou ','Kei ','Er ','An ','Kyou ','Chi ','Jin ', + 'Sen ','Tei ','Kou ','Hei ','Ri ','Kin ','Hou ','Shoku ','Sou ','Da ','Jia ','Rao ','Bi ','Ze ','Qiao ','Hui ', + 'Qi ','Dang ','','Rong ','Hun ','Ying ','Luo ','Ying ','Xun ','Jin ','Sun ','Yin ','Mai ','Hong ','Zhou ','Yao ', + 'To ','Wei ','Chu ','Tou ','Fu ','Jin ','Yin ','Ka ','Hotsu ','Bu ','Yun ','Teki ','To ','I ','Sui ','Sei ', + 'Shin ','Wu ','Hetsu ','Xi ','Kou ','Ri ','Hu ','Cho ','Mo ','Chi ','Sou ','Ji ','Duo ','Kyuu ','Sa ','Suo ', + 'Chen ','Feng ','Kyo ','Mai ','Mou ','Kou ','Kei ','Che ','Shin ','Kin ','En ','Tei ','Teki ','Sa ','Kan ','Kan ', + 'Yuu ','Cuo ','Kyou ','Wang ','You ','Niu ','Sou ','Kan ','Rou ','Hu ','Ga ','Bo ','Bun ','Setsu ','Nan ','Mu ', + 'Kan ','Rai ','Lian ','Shi ','Wo ','To ','Lian ','Huo ','You ','Ying ','Ying ','Nuc ','Chun ','Bou ','Mou ','Shi ', + 'En ','Sei ','Di ','Qu ','Dong ','Kan ','Zou ','Ko ','La ','Ryoku ','Kiku ','Wei ','Kin ','Nie ','Kon ','Ka ', + 'Hoku ','Shi ','Gao ','Ka ','Hoku ','Lun ','Shou ','Chou ','Suu ','Chui ','Zhan ','Men ','Sai ','Hatsu ','Li ','To ', + 'Ha ','Han ','Bao ','Qin ','Juan ','Xi ','Qin ','Di ','Shou ','Hai ','Tou ','Kin ','Zhao ','Tai ','Geng ','Ka ', + 'Ko ','Ryou ','Hi ','Jin ','An ','Wang ','Hou ','Sou ','En ','Sho ','Jian ','Rin ','Tan ','Shuku ','Tian ','Dao ', + ], + 'x84':[ + 'Hu ','Ki ','He ','Sui ','Tou ','Shun ','Hi ','Chou ','Huan ','Fei ','Rai ','Sei ','Hou ','Hei ','I ','Tan ', + 'Sha ','Kan ','Yan ','Gi ','Tiao ','Sei ','Wan ','Ce ','Nai ','Kutabireru ','Tuo ','Kyuu ','Tie ','Luo ','','', + 'Hou ','','Yaji ','','Ying ','Ying ','Ying ','Xiao ','Sa ','Shuu ','Kuwa ','Xiang ','Man ','Yu ','Yu ','Huu ', + 'Lian ','Ken ','Yuan ','Nan ','Ze ','Wa ','Chun ','Xiao ','Yu ','Hen ','Mao ','An ','Gaku ','Raku ','Ying ','Huo ', + 'Gua ','Jiang ','Mian ','Zuo ','Zuo ','Sho ','Ho ','Juu ','Shi ','You ','An ','Qu ','Jian ','Huku ','Ritsu ','Sen ', + 'Pen ','Hou ','Kou ','Hong ','Hou ','Yan ','Totsu ','Cho ','Shi ','Shou ','Chin ','Katsu ','Katsu ','Jing ','Mi ','Huang ', + 'Shin ','Ho ','Gai ','Tou ','Chuu ','Sen ','I ','Hotsu ','Wei ','Ha ','Kei ','Ko ','Sou ','Ka ','Tan ','Yaku ', + 'Sui ','Sou ','Quan ','I ','Shin ','Ki ','Tei ','Gun ','Sai ','Shi ','Shuu ','Lan ','Sou ','You ','Yuan ','Mei ', + 'Yun ','Shutsu ','Tei ','Zhuan ','Kan ','Sukumo ','Xue ','Chan ','Kai ','Kui ','','Shou ','Lou ','Wei ','Pai ','', + 'Shuu ','Yin ','Shi ','Jun ','Shi ','Un ','Shin ','Lang ','Nu ','Bou ','He ','Que ','San ','Yuan ','Ri ','Kon ', + 'Xi ','Hou ','Chu ','Xu ','Tu ','Liu ','Waku ','Zhen ','Sen ','So ','Haku ','Cuo ','Yuan ','Suu ','Yu ','Kai ', + 'Pan ','Ho ','Ho ','Na ','Saku ','Xi ','Fen ','Yun ','Jou ','Ken ','Shitsu ','Jaku ','Sou ','On ','Bei ','Kou ', + 'Son ','Shin ','Mei ','Huo ','Chiku ','Liu ','Seki ','Kotsu ','Kou ','You ','Ou ','Gai ','Sa ','Shi ','Tang ','Ra ', + 'Joku ','Sa ','Xian ','Hai ','Yao ','Gui ','Hi ','Zong ','Gun ','Za ','Chou ','Ce ','Hai ','Lan ','','Ji ', + 'Li ','Can ','Lang ','Yu ','','Ying ','Mo ','Shou ','Tiao ','Mao ','Tou ','Zhu ','Hou ','An ','Ren ','Sou ', + 'Shi ','Hei ','Kyuu ','Jin ','Shun ','Jie ','Wei ','Tai ','Cao ','Yu ','Gei ','Shuu ','Ryou ','Hitsu ','Lu ','Shuku ', + ], + 'x85':[ + 'Hou ','Zhang ','Rui ','Kyou ','Man ','Yan ','Ryou ','Kike ','Piao ','Gun ','Han ','Di ','Soku ','Lu ','Setsu ','Shou ', + 'Teki ','Betsu ','Xun ','Ban ','Fuku ','Tei ','Cuo ','Sho ','Shin ','Xuan ','Utsu ','Hu ','Gou ','Mi ','Rou ','Zoku ', + 'Zhong ','Sai ','Ha ','Shou ','Bitsu ','Sou ','Chou ','Sei ','Jun ','Yin ','Sen ','En ','So ','In ','Kui ','Chin ', + 'Hu ','Sha ','Kou ','Sen ','Ma ','Zou ','Sonoko ','Qiang ','Dou ','Lian ','Lin ','Kou ','Ai ','Hei ','Li ','I ', + 'Kyoku ','Jin ','Sheng ','Ban ','Meng ','Ou ','Ten ','Dian ','Shin ','Shou ','Zui ','Zui ','Lei ','Yu ','Kyou ','Cho ', + 'Kuwa ','Kan ','Bai ','Un ','Bao ','Yuu ','Kyo ','Ro ','Jou ','Kei ','Gaku ','Teng ','Hi ','Setsu ','Sai ','Hitsu ', + 'Jo ','Hun ','Kai ','Shun ','Zui ','Ya ','Xu ','Fu ','Ketsu ','Tou ','Bu ','Tou ','Si ','Shou ','Xi ','Rou ', + 'Un ','','Qi ','Kan ','Yun ','Sun ','Ling ','Yo ','Xia ','You ','Shuu ','Kou ','Si ','Dou ','Rai ','Ken ', + 'Un ','Iku ','Xi ','Hao ','Haku ','Kou ','Ai ','Bi ','Kai ','Wai ','Kei ','Shi ','Kyou ','Luan ','Mie ','Yoku ', + 'Rou ','Kyou ','Can ','Shin ','Shoku ','Lian ','Ke ','En ','Tatsu ','Tei ','Tang ','Setsu ','Heki ','Sen ','Sun ','Ren ', + 'Han ','Ding ','Kai ','Gu ','Kai ','Shoku ','Sen ','Kou ','Kou ','Satsu ','Shin ','Kun ','Yaku ','Hai ','Sou ','Sho ', + 'Kun ','Dui ','Pin ','Wei ','Nou ','Chou ','Bai ','Ju ','Hyou ','Tai ','Sei ','Zao ','Chin ','Shin ','Shi ','Gi ', + 'Ying ','Kou ','Sou ','Xiao ','Qi ','Fa ','Jian ','Sho ','Kui ','Sha ','Hen ','Chou ','Mi ','Ran ','Shin ','Zou ', + 'Baku ','Qiong ','Qie ','Xian ','','Guu ','Xian ','Su ','Ryo ','Yi ','Shoku ','Xie ','Rei ','Gei ','La ','Rui ', + 'Kyou ','Di ','Zhi ','Bei ','Tou ','Yaku ','Ba ','Huan ','Hyou ','Han ','Sou ','Tan ','Tui ','Kyuu ','Qiao ','Wei ', + 'Liu ','Hui ','','Kou ','Un ','','Reki ','Sho ','Chu ','Ai ','Rin ','Sou ','Ken ','Chen ','Rai ','Kaku ', + ], + 'x86':[ + 'Taku ','Wu ','Zui ','Rui ','Ki ','Kou ','Ro ','So ','Tui ','Mang ','Un ','Hin ','Yu ','Kun ','Ki ','Kei ', + 'Ken ','Ma ','Hagi ','So ','Jiong ','','Getsu ','Haku ','Jou ','Ei ','Sen ','Iku ','Ju ','Lian ','Ren ','Yin ', + 'Qiang ','Ou ','Rou ','Tong ','Wei ','Yue ','Ling ','Ku ','Yao ','Han ','Mi ','Lan ','Kui ','Ran ','Ji ','Tou ', + 'Katsura ','Lei ','Lei ','Hua ','Feng ','Zhi ','Gi ','Kui ','San ','Huai ','Ri ','Ji ','Bi ','Ryuu ','Huai ','Ra ', + 'Sei ','Ki ','Ro ','Jian ','San ','','Rui ','Quan ','Kyou ','Yi ','Luan ','Men ','Bie ','Ko ','Ko ','Lu ', + 'Gyaku ','Lu ','Shi ','Kou ','Ken ','Sho ','Ko ','Kyo ','Sa ','Huku ','Kyo ','Kyo ','Ryo ','Ko ','Gu ','Gou ', + 'Kou ','Kyo ','Hou ','Hou ','Gan ','Zhan ','Zhan ','Ki ','Ban ','Keki ','Shu ','Chuu ','Kyuu ','Diao ','Ji ','Kyuu ', + 'Cheng ','Shitsu ','','Di ','Zhe ','Sha ','U ','Kan ','Zi ','Kou ','Ki ','Bou ','Ge ','Sui ','Xia ','Chai ', + 'Shi ','Yi ','Ma ','Xiang ','Fang ','E ','Pa ','Chi ','Ken ','Bun ','Bun ','Zei ','Hou ','Hi ','Yue ','Yue ', + 'Jun ','Ki ','Tong ','In ','Qi ','San ','Gen ','Jue ','Kai ','Qin ','Ki ','Zhong ','Ka ','Ci ','Mu ','Wang ', + 'Fen ','Hun ','Hang ','Kou ','Sou ','Fu ','Zen ','Kai ','Hu ','Shi ','Tou ','Hou ','Xian ','Ji ','Te ','Kyuu ', + 'Yuu ','Saku ','Ping ','Chi ','Yuu ','Ka ','Kan ','Kyo ','Reki ','Hu ','Ran ','Zha ','Gou ','Pi ','Bo ','Ken ', + 'Shu ','Chou ','Bie ','Hei ','Ko ','Zen ','Sho ','Ja ','Tie ','Rei ','Gu ','Tan ','Gu ','Kei ','Rei ','Cheng ', + 'Qu ','Bou ','Kaku ','Ci ','Kai ','Kai ','Mang ','Huu ','Yang ','A ','Retsu ','Shu ','I ','Xian ','Katsu ','Kou ', + 'Rei ','Yi ','Ping ','Kitsu ','Kou ','Setsu ','Yi ','Bou ','Mo ','Kyou ','Qie ','Gui ','Kyou ','Shitsu ','Ban ','Ebi ', + 'Zhi ','Jia ','Rao ','Si ','Qi ','Xing ','Lie ','Qiu ','Sou ','You ','Kyou ','Zei ','Sha ','Bai ','Ga ','Han ', + ], + 'x87':[ + 'Shoku ','Xuan ','Hou ','Shin ','Shin ','Hu ','Ken ','Tetsu ','Go ','Fu ','Ri ','Rou ','Bi ','Sho ','En ','Yuu ', + 'Kyou ','Tan ','En ','Ten ','Ten ','Zei ','Kai ','Gua ','Chi ','Shou ','Hi ','Ju ','Mitsu ','Qi ','Ki ','Iku ', + 'Jun ','Sho ','Meng ','Kyou ','Si ','Seki ','Lun ','Li ','Shou ','Chou ','Tao ','Kun ','Gan ','Han ','Yoku ','Hou ', + 'Fei ','Hi ','I ','Dun ','Eki ','Yuan ','Su ','Ken ','Qian ','Zei ','Gei ','Sei ','I ','Ryou ','Ka ','En ', + 'Tou ','E ','Ban ','Tei ','Wang ','San ','Yang ','Ying ','Guo ','Sen ','','Rou ','Ka ','Soku ','Katsu ','Ting ', + 'Mai ','Xu ','Mian ','Yu ','Jie ','Shoku ','Xuan ','Kou ','En ','Hen ','Rou ','Wei ','Fu ','En ','Mei ','I ', + 'Fuku ','Zen ','Xie ','Yuu ','Shuu ','Bou ','Ka ','Ying ','Shitsu ','Chong ','Tou ','Zhu ','Zong ','Ti ','Fuku ','En ', + 'Hui ','Mou ','Ratsu ','Du ','Ko ','Qiu ','Chou ','Li ','Ka ','Yun ','Ju ','Nan ','Lou ','Qun ','Rong ','You ', + 'Jiang ','','Rou ','Hou ','Shi ','Shi ','Shi ','Kei ','Gen ','O ','Lian ','Shuu ','Han ','Yuu ','Rong ','Ji ', + 'O ','Qiu ','Han ','Shin ','Yi ','Hei ','Hua ','Tou ','Gi ','Du ','Nai ','He ','Hu ','Hui ','Ba ','Mei ', + 'I ','Wen ','Kei ','Tou ','Yu ','Cang ','So ','Ebi ','Man ','','Shang ','Seki ','Sou ','Chi ','Tei ','Gou ', + 'Lu ','I ','Zhi ','Tou ','Chen ','Hyou ','Qu ','Pi ','Yu ','Jian ','Ra ','Rou ','Qin ','Shuu ','In ','Shou ', + 'Shutsu ','Bun ','Jiao ','Wan ','Chitsu ','Zhe ','Ba ','Ba ','Kaku ','Ryuu ','Bou ','Shitsu ','Cong ','Li ','Dani ','Xiao ', + 'Tou ','Zhang ','Bou ','Xiang ','Mo ','Sui ','Shi ','Qiu ','Te ','Shoku ','Hou ','Peng ','Kyou ','Qu ','Bie ','Ryou ', + 'Han ','Gui ','Ki ','Ki ','Sen ','Huang ','Fei ','Lao ','Jue ','Jue ','Kei ','In ','Sen ','Shou ','Shan ','Gyou ', + 'Xiao ','Bou ','Ki ','Jin ','Si ','','Tei ','Tou ','Rei ','Kai ','Sen ','Gi ','Jing ','Da ','Sen ','Kei ', + ], + 'x88':[ + 'Ci ','Kyou ','She ','Ra ','Qin ','You ','Tai ','Li ','Ze ','Ken ','Ren ','Shoku ','Ze ','Katsu ','Bou ','Kai ', + 'Sei ','Ei ','Ken ','Bou ','Kou ','Da ','Kaku ','Zhuo ','Setsu ','Hen ','Kaku ','Betsu ','Han ','Lei ','Setsu ','Rou ', + 'Mi ','Rei ','Shun ','Rei ','Qiu ','Nie ','Lu ','To ','Shou ','Zhu ','Long ','Li ','Long ','Hou ','Etsu ','Beng ', + 'Shou ','Ko ','Ken ','Ying ','','Kei ','San ','Qu ','Quan ','To ','San ','Ban ','Kyaku ','Jie ','Zhu ','Zha ', + 'Ketsu ','Kou ','Jiku ','Hai ','Jiku ','Kin ','Shuu ','Mo ','Ji ','Kaku ','Betsu ','Kyoku ','Kou ','En ','Kan ','Yuan ', + '','Rei ','Ken ','Jutsu ','Xian ','Tou ','Kou ','Gai ','Kan ','Gyo ','Ko ','Ei ','Dou ','Shou ','Ei ','Dou ', + 'Shun ','Kou ','Ku ','I ','Koromohen ','Bu ','Kan ','Yu ','Hyou ','Sai ','Yi ','San ','Chen ','Fu ','Kon ','Fen ', + 'Sa ','Kyou ','Dou ','Zhong ','Dan ','Jitsu ','Zhong ','Chuu ','Xie ','Ki ','Xie ','Zen ','Zhi ','Jin ','Kin ','Kin ', + 'Kin ','En ','Bei ','Chai ','Ao ','Niao ','Hui ','Ran ','Ka ','Tuo ','Ling ','Tai ','Bao ','Hou ','Yao ','Zuo ', + 'Bi ','Shao ','Tan ','Ju ','He ','Shu ','Shuu ','Shin ','I ','Ha ','Hatsu ','Tei ','Batsu ','Fu ','Kon ','Chitsu ', + 'Chitsu ','Ran ','Han ','Yi ','Bou ','','Na ','Kou ','Ken ','Chan ','Kyo ','Hi ','Gun ','Xi ','Ne ','Bo ', + 'Horo ','Fuku ','Yi ','Shi ','Ko ','Jin ','Jiang ','Kou ','Cun ','Mo ','Ketsu ','Er ','Luo ','Jo ','Chu ','Kei ', + 'In ','Sai ','Retsu ','Kamishimo ','Yuki ','Sou ','Dang ','Seot ','Kon ','Ken ','Jou ','Shu ','Kou ','Kon ','Tei ','Ri ', + 'Juan ','Shin ','Hou ','Koku ','Ei ','Yuu ','Zhen ','Liu ','Kyuu ','Kun ','Ji ','Youu ','Ho ','Sou ','Sei ','Sa ', + 'Qun ','Ri ','Lian ','Lian ','Ku ','Jian ','Fou ','Sen ','Hi ','Gun ','Tau ','Yuan ','Ling ','Chi ','Chang ','Chuu ', + 'Tatsu ','Hyou ','Ryou ','Shou ','Hai ','Hai ','Fei ','En ','Ra ','Ka ','Yan ','Du ','Seki ','Sei ','Kyo ','Qi ', + ], + 'x89':[ + 'Ji ','Seki ','Kai ','Ken ','Tsuma ','Ti ','Shi ','Fuku ','Chong ','Xie ','Hen ','Die ','Kon ','Tan ','Shuu ','Yuu ', + 'Katsu ','Yuan ','Hou ','Ho ','Fu ','Yu ','Tan ','Yan ','I ','Hai ','Cho ','Lu ','Ena ','Tan ','On ','Da ', + 'Kou ','Da ','Huai ','Rong ','Yuan ','Joku ','Dai ','Kei ','Sa ','Ban ','Tai ','Chi ','Sang ','Niao ','Ying ','Jie ', + 'Ken ','Kaie ','Ko ','Lian ','Bao ','Ri ','Chou ','Shi ','Rou ','Gei ','Chou ','Setsu ','Xian ','Wei ','Hyou ','Cao ', + 'Seki ','Kyou ','Shin ','Hou ','Jou ','Chihaya ','Hoku ','Jian ','Zhuan ','Kan ','Zui ','Ji ','Tan ','Zatsu ','Fan ','Hatsu ', + 'Xiang ','Xin ','Hetsu ','Rao ','Man ','Ran ','Ou ','Taku ','Gui ','Cao ','Sui ','Jou ','Sen ','Lian ','Heki ','Kin ', + 'Tou ','Shoku ','Tan ','Hi ','Ran ','Pu ','Ju ','Zhi ','','Shu ','Betsu ','Seki ','Bai ','Ketsu ','Haku ','Shin ', + 'Rai ','Long ','Shuu ','Sen ','Ran ','Shou ','Dai ','Tasuki ','Zan ','Shi ','Ken ','Han ','Gei ','Ran ','Aka ','Sei ', + 'Xi ','You ','Feng ','Tan ','','Biao ','Fuku ','Ha ','Kaku ','Ki ','Ki ','Ken ','Kan ','Hen ','Yan ','Ki ', + 'Kaku ','Pian ','Mao ','Beki ','Eki ','Betsu ','Shi ','Shi ','Ten ','Ra ','Kaku ','Biki ','Chou ','Lian ','Yao ','Shi ', + 'Kin ','Geki ','Shan ','Wei ','Xi ','Ten ','Yu ','Ran ','E ','To ','Shin ','Pang ','Ki ','Ming ','Ying ','Kou ', + 'So ','Zhan ','Kin ','Kan ','Tou ','Kan ','Ra ','Shu ','Kan ','Wei ','Kaku ','Qu ','Ra ','Ran ','Shen ','Teki ', + 'Kan ','Jian ','Guan ','Yan ','Gui ','Mi ','Shi ','Zhan ','Lan ','Jue ','Ji ','Xi ','Di ','Tian ','Yu ','Gou ', + 'Jin ','Qu ','Kaku ','Jiu ','Kin ','So ','Ketsu ','Shi ','Sou ','Ji ','Ko ','Dan ','Shi ','Tei ','Shang ','Hua ', + 'Quan ','Ge ','Chi ','Kai ','Gui ','Kou ','Shoku ','Kai ','Hun ','Kyuu ','Xing ','Soku ','Ni ','Ki ','Lu ','Zhi ', + 'Zha ','Hitsu ','Xing ','Koku ','Shou ','Gong ','Shi ','Xue ','Shoku ','Kei ','Yi ','Lu ','Jue ','Kei ','Yan ','Kei ', + ], + 'x8a':[ + 'Gen ','Gonben ','Tei ','Fu ','Kyuu ','Kyuu ','Jiao ','Kou ','Kei ','Fan ','Jin ','Diao ','Kou ','Cha ','Tou ','Ku ', + 'Ketsu ','Shi ','Jin ','Kun ','Gin ','San ','Kitsu ','Taku ','Ki ','Xun ','Yin ','Ka ','Fen ','Ga ','You ','Shou ', + 'Shin ','Yin ','Kin ','Ketsu ','Kon ','Totsu ','Shin ','You ','Zhi ','Xiong ','Hou ','Shin ','Sou ','Setsu ','Xian ','Sa ', + 'Tun ','Kyo ','Yi ','Yaku ','So ','Chi ','Ka ','Shin ','He ','Xu ','Shin ','Chuu ','Shou ','Kou ','Shi ','Zi ', + 'Tan ','Ko ','Fu ','Ken ','Die ','Rei ','Tei ','You ','Ri ','Dou ','Pan ','Zhou ','Gan ','Ei ','Kyo ','Ao ', + 'Sa ','Ta ','Tai ','Kyo ','Shou ','Hyou ','Hi ','Kyou ','Kutsu ','Ba ','Da ','So ','Tou ','Cho ','Shi ','Zhe ', + 'Ei ','Ku ','Jun ','Kei ','Huang ','Kou ','Shi ','Satsu ','Jiao ','Shi ','Hen ','Ta ','Kou ','Ki ','Sen ','Hui ', + 'Kitsu ','Wa ','Gai ','Shou ','Wei ','Shin ','Shuu ','Tou ','Mi ','Sen ','Bii ','Gaku ','Kai ','Yan ','Kyou ','Kai ', + 'Ji ','Beng ','Chou ','Shi ','Rui ','Chuu ','Kyou ','Ko ','Wu ','Yo ','Teng ','Ki ','Shi ','Nin ','Su ','Rou ', + 'Ga ','Kyou ','Ki ','Sei ','Ting ','Tan ','Hotsu ','Ten ','Yuu ','Kou ','Shou ','Qin ','Shua ','An ','Go ','Kou ', + 'Sei ','Kai ','Xian ','Fu ','Go ','Kou ','Shou ','Ho ','Kai ','Kei ','Setsu ','Zhen ','Setsu ','Toku ','Yasashi ','Shou ', + 'Sui ','Jie ','Ka ','Kutsu ','Cong ','Xiao ','Sui ','Bou ','Xuan ','Hi ','Chi ','Tou ','Gi ','Na ','Gin ','Chou ', + 'Pi ','Chuo ','Ten ','Chin ','Jun ','Ji ','Ki ','Dan ','Sui ','Zui ','Kiku ','Sei ','Kan ','Sou ','Ze ','Shu ', + 'Qian ','Taku ','Ryou ','Sen ','Shuku ','Kou ','Ron ','Shin ','Biao ','Huai ','Jou ','Yu ','Chou ','Sho ','Hen ','Shi ', + 'Ken ','Shi ','Kon ','Hua ','Gaku ','Zhong ','Tei ','Kai ','Fu ','Pu ','Ting ','Kan ','Kei ','Yu ','Shi ','Chuan ', + 'Shi ','Ki ','Yin ','An ','Kan ','Nan ','Shin ','Fuu ','Sho ','Yang ','Gen ','Heng ','Ken ','Ge ','Daku ','Shuu ', + ], + 'x8b':[ + 'Bou ','Etsu ','I ','','Tou ','Sou ','Sen ','Ken ','Bo ','','Kou ','Kaku ','Ka ','Ying ','Mei ','Xiao ', + 'Hitsu ','Kei ','Qiang ','Chen ','Gyaku ','Ti ','Shoku ','Bou ','Chi ','Ken ','Shi ','Kou ','Gen ','Sha ','Kaku ','Tou ', + 'You ','You ','','Yu ','Biao ','Cong ','Kei ','Li ','Bo ','Mo ','Shang ','Taku ','Byou ','Sei ','Ze ','Jie ', + 'Ren ','Lou ','Can ','Ou ','Guan ','Xi ','Zhuo ','Gyou ','Ao ','Kin ','Zhe ','Yi ','Ko ','Jiang ','Ban ','Chao ', + 'Han ','Ka ','Sen ','Ku ','Sou ','Shuu ','Ki ','She ','Tai ','Shou ','Nao ','Lan ','Ka ','You ','Kitsu ','Ki ', + 'Zun ','Jiao ','Ha ','Kei ','Sen ','Mu ','Shin ','Zha ','Shiki ','Shou ','Tan ','Shin ','Fu ','Sheng ','Ken ','Sou ', + 'Tan ','Dang ','Sui ','Sen ','Ji ','Jiao ','Kei ','Lian ','Nou ','Yi ','Ai ','Sen ','Hi ','Ki ','Hua ','Yaku ', + 'Gi ','Zen ','Jou ','Nou ','Ken ','Zhui ','Tou ','Go ','Chuu ','Kou ','Ye ','Ying ','Kan ','Yo ','Sen ','Hui ', + 'Toku ','Taku ','Xuan ','San ','Ru ','Shin ','Ei ','Chan ','Li ','Yi ','Hen ','Shou ','En ','Gaku ','Shuu ','Ei ', + 'Shuu ','Yao ','San ','Jou ','In ','Ran ','Shin ','Huo ','Zhe ','Kan ','San ','Yi ','Tou ','Zhan ','Getsu ','Toku ', + 'Yan ','Ji ','Ding ','Fu ','Ren ','Ji ','Jie ','Hong ','Tao ','Rang ','Shan ','Qi ','Taku ','Xun ','Yi ','Xun ', + 'Ji ','Ren ','Jiang ','Hui ','Ou ','Ju ','Ya ','Ne ','Xu ','E ','Lun ','Xiong ','Song ','Feng ','She ','Fang ', + 'Jue ','Zheng ','Gu ','He ','Ping ','Zu ','Shi ','Xiong ','Zha ','Su ','Zhen ','Di ','Zou ','Ci ','Qu ','Zhao ', + 'Bi ','Yi ','Yi ','Kuang ','Lei ','Shi ','Gua ','Shi ','Jie ','Hui ','Cheng ','Zhu ','Shen ','Hua ','Dan ','Gou ', + 'Quan ','Gui ','Xun ','Yi ','Zheng ','Gai ','Xiang ','Cha ','Hun ','Xu ','Zhou ','Jie ','Wu ','Yu ','Qiao ','Wu ', + 'Gao ','You ','Hui ','Kuang ','Shuo ','Song ','Ai ','Qing ','Zhu ','Zou ','Nuo ','Du ','Zhuo ','Fei ','Ke ','Wei ', + ], + 'x8c':[ + 'Yu ','Shui ','Shen ','Diao ','Chan ','Liang ','Zhun ','Sui ','Tan ','Shen ','Yi ','Mou ','Chen ','Die ','Huang ','Jian ', + 'Xie ','Nue ','Ye ','Wei ','E ','Yu ','Xuan ','Chan ','Zi ','An ','Yan ','Di ','Mi ','Pian ','Xu ','Mo ', + 'Dang ','Su ','Xie ','Yao ','Bang ','Shi ','Qian ','Mi ','Jin ','Man ','Zhe ','Jian ','Miu ','Tan ','Zen ','Qiao ', + 'Lan ','Pu ','Jue ','Yan ','Qian ','Zhan ','Chen ','Koku ','Sen ','Kou ','Ka ','Jue ','Hong ','Kan ','Kou ','Kei ', + 'Xi ','Katsu ','Liao ','Han ','Du ','Rou ','Tou ','Kou ','Ki ','Shi ','Hou ','Tou ','En ','Bi ','Ju ','Kan ', + 'Hou ','Chitsu ','Zhi ','En ','En ','Shi ','Chu ','Ka ','Ton ','Gi ','Ton ','Eki ','Ken ','Ha ','Hou ','E ', + 'Cu ','Shou ','Ken ','Ken ','Kon ','Gai ','Kyo ','Fu ','Ki ','Hin ','Gou ','Yo ','Cho ','Ka ','Fen ','Xi ', + 'Bo ','Wen ','Huan ','Hin ','Di ','Sou ','Hun ','Yi ','Chi ','Hou ','Sai ','Kan ','Hi ','Na ','Hi ','Gou ', + 'Na ','You ','Chou ','Mo ','Si ','Kyuu ','Kan ','Kon ','He ','Kaku ','Haku ','Kan ','Bou ','Ri ','Gei ','Bi ', + 'Yu ','Jia ','Tan ','Byou ','Hi ','Xi ','E ','Ju ','Baku ','Chu ','Tan ','Kan ','Kyaku ','Bai ','Tei ','Yuan ', + 'Fu ','Zai ','Kou ','Te ','I ','Hang ','Wan ','Hin ','Ka ','Han ','Don ','Kan ','Seki ','Shitsu ','Ni ','Cho ', + 'Sei ','Bi ','Shi ','Ni ','Ki ','Pian ','Hen ','Bai ','Tai ','Sei ','Kyou ','Hi ','Ten ','I ','Chi ','Bou ', + 'Ga ','Hi ','Ro ','Chin ','Wai ','Kai ','Hen ','Shi ','Ko ','Shutsu ','Zoku ','Kou ','Gai ','Sou ','Sen ','Ei ', + 'Xun ','Shin ','Sha ','Hin ','Hin ','Kyuu ','Sha ','Chuan ','Zang ','Shuu ','Rai ','San ','Shi ','Chin ','Shou ','Tian ', + 'Bai ','Shoku ','Ken ','Bai ','Sen ','Sui ','Fu ','Tan ','Sou ','Cong ','Shitsu ','Ji ','Chou ','To ','Jin ','Kei ', + 'Shun ','Yun ','Hou ','Zai ','Rai ','Huu ','Cang ','Sei ','You ','Ai ','Tan ','Fu ','Kou ','Sai ','Saku ','Rou ', + ], + 'x8d':[ + 'Wei ','Hai ','Chen ','Wan ','Shi ','Zei ','Biao ','In ','Zou ','Tan ','San ','Gan ','','Sen ','Wan ','Ei ', + 'Shin ','Gan ','Ken ','Zou ','Hi ','Du ','Shoku ','Ken ','','Xuan ','Long ','Kou ','Zou ','Bei ','Zhen ','Fu ', + 'Yuan ','Gong ','Cai ','Ze ','Xian ','Bai ','Zhang ','Huo ','Zhi ','Fan ','Tan ','Pin ','Bian ','Gou ','Zhu ','Guan ', + 'Er ','Jian ','Bi ','Shi ','Tie ','Gui ','Kuang ','Dai ','Mao ','Fei ','He ','Yi ','Zei ','Zhi ','Jia ','Hui ', + 'Zi ','Ren ','Lu ','Zang ','Zi ','Gai ','Jin ','Qiu ','Zhen ','Lai ','She ','Fu ','Du ','Ji ','Shu ','Shang ', + 'Si ','Hi ','Zhou ','Geng ','Pei ','Tan ','Lai ','Feng ','Zhui ','Fu ','Zhuan ','Sai ','Ze ','Yan ','Zan ','In ', + 'Zeng ','Shan ','Ying ','Gan ','Seki ','Keki ','Sha ','Tan ','Xiong ','Kyoku ','Cheng ','Kaku ','Tei ','Sha ','Ka ','Tang ', + 'Sou ','Sou ','Li ','Kyuu ','Fu ','Zhao ','Gan ','Ki ','Shan ','Qiong ','Qin ','Xian ','Ci ','Jue ','Qin ','Chi ', + 'Ci ','Chin ','Chin ','Die ','Sho ','Chou ','Di ','Se ','Tan ','Zhu ','Etsu ','Qu ','Jie ','Chi ','Chu ','Gua ', + 'Ketsu ','Shi ','Tiao ','Duo ','Lie ','Kan ','Suo ','Cu ','Xi ','Chou ','Su ','Yin ','Ju ','Jian ','Shaku ','Tou ', + 'Taku ','Cui ','Lu ','Shu ','Dang ','Qiu ','Shi ','Ti ','Suu ','Chi ','Huang ','Kyou ','Kyou ','Yao ','Zao ','Kan ', + '','Zan ','San ','Soku ','Pa ','Haku ','Ku ','Kotsu ','Dun ','Ketsu ','Fu ','Chin ','Gen ','Fang ','Shi ','Sa ', + 'Getsu ','Pa ','Ki ','Yue ','Qiang ','Taku ','Tai ','Ei ','Den ','Ling ','Bai ','Batsu ','Tetsu ','Ku ','Ta ','Ka ', + 'Ci ','Hou ','Qia ','Zhu ','Ku ','Chou ','Seki ','Fu ','Pan ','Sho ','San ','Ha ','Ni ','Kyo ','Li ','Kon ', + 'Yi ','Seki ','Dai ','Sen ','Kou ','Ta ','Zhu ','Sen ','Ko ','Zhuai ','Ki ','Kyou ','Ki ','Xiang ','Chi ','Ro ', + 'Hou ','Chi ','Kou ','Chou ','Sai ','Sen ','Ta ','Qiao ','Bi ','Xian ','Ta ','Ji ','Kyoku ','Ki ','Shu ','To ', + ], + 'x8e':[ + 'Chu ','Kei ','Nie ','Xiao ','Haku ','Tei ','Shun ','Mou ','Sho ','Ryou ','You ','Kyaku ','Chou ','Qiao ','Mau ','Tou ', + 'Sen ','Ki ','Wo ','Wei ','Tou ','Jie ','Seki ','Nie ','Ju ','Ju ','Lun ','Lu ','Leng ','Ka ','Kyo ','Chi ', + 'En ','Ken ','Teki ','Hou ','Zu ','Qie ','Ki ','Shuku ','Zong ','Cai ','Shou ','Peng ','Zhi ','Zheng ','Dian ','Zhi ', + 'Yu ','Taku ','Dun ','Shun ','You ','Shou ','Tei ','Ta ','Chin ','Sen ','Jian ','Gua ','Tang ','Ku ','Fu ','Zu ', + 'Chou ','Hen ','Juu ','Nuo ','Tei ','Cha ','Tui ','Ken ','Tou ','Sa ','Kei ','Tou ','Shou ','Ten ','Ten ','Tei ', + 'Seki ','Nie ','Man ','Liu ','San ','Hitsu ','Chong ','Lu ','Liao ','Shuku ','Tang ','Tai ','Shuku ','Shi ','Ki ','Seki ', + 'Seki ','You ','Teki ','Man ','Shou ','Lian ','Beng ','Zao ','Nian ','Hetsu ','Tui ','Ju ','Tou ','Sou ','Xian ','Han ', + 'Shuu ','Shou ','Son ','Bo ','Shuu ','Zu ','Ketsu ','Jue ','Lin ','Tou ','Kyou ','Kyou ','Boku ','Liao ','Dun ','Cuan ', + 'Kuang ','Sou ','Tatsu ','Heki ','Heki ','Choku ','Ju ','Cho ','Qiao ','Ton ','Chuu ','Sei ','Wu ','Yaku ','Nian ','Lin ', + 'Ryou ','Teki ','Reki ','Chi ','Ten ','Chu ','Duan ','Ei ','Long ','Rin ','Sen ','Ei ','Zuan ','Ran ','Shou ','Rang ', + 'Xie ','Jou ','Tou ','Qu ','Jie ','Cuan ','Zuan ','Shi ','Kui ','Kyaku ','Rin ','Shin ','Kyuu ','Tan ','Segare ','Ku ', + 'Tei ','Ta ','Ta ','Kyuu ','Lang ','Nerau ','Luo ','Ai ','Ji ','Ju ','Tou ','Utsuke ','','Yan ','Shitsuke ','Kang ', + 'Ku ','Rou ','Lao ','Ta ','Shoku ','Yagate ','Tei ','Tou ','Yagate ','Yu ','Sha ','Atsu ','Ki ','Gun ','Wei ','Getsu ', + 'Sen ','Tei ','Ken ','Fan ','Jin ','Shan ','Tsumugikuruma ','Shu ','Tun ','Chen ','Dai ','Aku ','Dou ','Qi ','Mao ','Nan ', + 'Jin ','Fan ','Ten ','Gou ','Hu ','Qu ','Huang ','Di ','Rei ','Dai ','Ao ','Shin ','Fan ','Kyou ','Ou ','Peng ', + 'Hai ','Ko ','Gu ','Pao ','Zhu ','Rong ','E ','Hatsu ','Jiku ','Shi ','You ','Ka ','Itsu ','Kei ','Shoku ','Byou ', + ], + 'x8f':[ + 'Ji ','Qiong ','Kyoku ','Kaku ','Guang ','Ro ','Kai ','Sen ','Chuu ','Sai ','Chi ','She ','Ryou ','Yu ','Shao ','Yuu ', + 'Kan ','Yun ','Chou ','Ban ','Fu ','Kei ','Shuu ','Gei ','Ryou ','Chou ','Zhan ','Ryou ','Shi ','Ki ','Bou ','Tetsu ', + 'Ka ','Kan ','Yi ','Hou ','Qian ','Kon ','Ren ','Byou ','Kan ','Hai ','Rin ','Pai ','Ryou ','Zen ','Juu ','Shuu ', + 'Yang ','Xian ','Chuan ','Sou ','Chun ','Katsu ','Yuu ','Kou ','Yu ','Fuku ','Shi ','Fuku ','Wen ','Ben ','Ten ','Yo ', + 'On ','Tou ','Koku ','Shin ','Katsu ','En ','Roku ','Kou ','Chao ','Ten ','Wei ','Hun ','Sori ','Tetsu ','Kyou ','San ', + 'Pu ','Rau ','Hun ','Han ','Rin ','Katsu ','Se ','Kan ','Kan ','Yi ','Ji ','Dui ','Ji ','Yo ','Kan ','Gou ', + 'Lei ','Hi ','Reki ','Reki ','Ro ','Rin ','Che ','Ya ','Gui ','Xuan ','Di ','Ren ','Zhuan ','E ','Lun ','Ruan ', + 'Hong ','Gu ','Ke ','Lu ','Zhou ','Zhi ','Yi ','Hu ','Zhen ','Li ','Yao ','Qing ','Shi ','Zai ','Zhi ','Jiao ', + 'Zhou ','Quan ','Lu ','Jiao ','Zhe ','Fu ','Liang ','Nian ','Bei ','Hui ','Gun ','Wang ','Liang ','Chuo ','Zi ','Cou ', + 'Fu ','Ji ','Wen ','Shu ','Pei ','Yuan ','Xia ','Zhan ','Lu ','Che ','Lin ','Shin ','Ko ','Ji ','Ji ','Heki ', + 'Sai ','Hen ','La ','Ratsu ','Ji ','Setsu ','Han ','Ben ','Ben ','Bian ','','Bian ','Ban ','Ji ','Hen ','Ben ', + 'Shin ','Joku ','Nou ','Nong ','Zhen ','Chaku ','Chaku ','Suberu ','Shou ','Hen ','Hen ','Tsuji ','Komu ','Liao ','Tatsu ','Ten ', + 'Kan ','Sen ','U ','Yu ','Kitsu ','Jin ','I ','Guo ','Mai ','Qi ','Sou ','Ou ','tu ','Chun ','Gei ','Ti ', + 'Un ','Kin ','Kou ','Ga ','Hen ','Go ','Da ','E ','Huan ','Zhe ','Totemo ','Jin ','Yuan ','Wei ','Lian ','Chi ', + 'Shou ','Ni ','Chou ','Sei ','I ','Kei ','Ka ','Chen ','Tai ','Ji ','Teki ','Haku ','Ou ','Tetsu ','Saku ','Tou ', + 'Jutsu ','Ta ','Kep ','Jing ','Kai ','Tou ','Yuu ','Mei ','Hou ','Seki ','Dai ','I ','Jie ','Tsui ','Retsu ','Xun ', + ], + 'x90':[ + 'Tai ','Sou ','Katsu ','Tou ','Hou ','Kou ','Gyaku ','Dun ','Kei ','Xuan ','Xun ','Ho ','Yuu ','Shou ','Shuu ','Tou ', + 'Chiku ','Kyuu ','Di ','Tei ','To ','Kei ','Teki ','Tou ','Gi ','Gen ','Ts ','Kyou ','Wu ','Sei ','Tei ','Soku ', + 'Zou ','Shun ','Hou ','Ren ','Suo ','Kai ','Li ','Sako ','Rai ','Kamu ','Saku ','Jue ','Hou ','Kan ','Tai ','Ryoku ', + 'Yuu ','Shuu ','Shin ','Iku ','Taku ','Ki ','I ','Keki ','Itsu ','Tatsu ','En ','Luo ','Hitsu ','Nuo ','Yu ','Tou ', + 'Sui ','Ton ','Sui ','Gen ','Sen ','Chi ','Ti ','Guu ','Shi ','Tei ','Yuu ','Un ','Gaku ','Hen ','Ka ','Atsu ', + 'Ka ','Kou ','Shuu ','Dou ','Tatsu ','I ','Appare ','Yi ','Kou ','You ','Chu ','Ryuu ','Son ','Tou ','Tei ','Chi ', + 'En ','So ','Tou ','Ken ','','You ','Kan ','Shou ','Gou ','Teki ','Ce ','Chi ','Soku ','Sou ','Sha ','Ton ', + 'Tei ','Lou ','Chi ','Cuo ','Rin ','Jun ','Jou ','Sen ','Sen ','Itsu ','I ','Wu ','Ryou ','Kyo ','Shi ','Hi ', + 'You ','Bai ','Kai ','Sui ','Kan ','Ken ','Teng ','Ji ','Baku ','Hen ','Hen ','Ryou ','Rei ','Yuan ','Yuu ','Ra ', + 'Ri ','Yuu ','Ting ','Deng ','Qi ','You ','Shan ','Kan ','U ','Bou ','Ru ','Kyou ','','Kuang ','Fu ','Kang ', + 'Hin ','Hou ','Kei ','Da ','','Shin ','Hou ','Yuan ','Son ','Huo ','Ya ','Bang ','Wu ','Ju ','You ','Kan ', + 'Tai ','Kyuu ','Hitsu ','Hi ','Hei ','Shou ','Hai ','Wa ','Tei ','Zou ','Ye ','Lin ','Kuang ','Kei ','Chu ','Shi ', + 'Ku ','Iku ','Gai ','Kou ','Keki ','Shitsu ','Ji ','Shun ','Kou ','Xing ','Kou ','Xi ','Kei ','Nuo ','Rou ','Jia ', + 'Kuai ','Zheng ','Rou ','Yun ','Yan ','Sei ','Dou ','Chi ','Ryo ','Hu ','Wu ','Fu ','Kou ','Kaku ','Rou ','Kou ', + 'Geng ','Gun ','Ei ','Bo ','Geki ','Hai ','Li ','Yun ','Bu ','Xiao ','Qi ','Hi ','Qing ','Kaku ','','Tan ', + 'Shuu ','Ping ','Lai ','Ni ','Chin ','Yuu ','Bu ','Kyou ','Dan ','Ju ','Yong ','Qiao ','Yi ','To ','En ','Bi ', + ], + 'x91':[ + 'Jaku ','Bei ','Gaku ','Yu ','Ken ','Gu ','Un ','Hou ','Ki ','Kyou ','Xiang ','Sou ','Tang ','Mei ','Xi ','Ru ', + 'Chiku ','Zi ','Suu ','Ju ','O ','Kyou ','Un ','Kou ','You ','Hi ','Baku ','Chao ','Hu ','Liao ','Gin ','Zhuan ', + 'Ko ','Qiao ','En ','Shou ','Man ','Kyou ','Xu ','Tou ','Bi ','Shin ','Bi ','Ceng ','Wei ','Tei ','Bou ','Sen ', + 'Rin ','Ha ','Tan ','Meng ','Gyou ','Cao ','Kai ','Hou ','Meng ','Shuu ','Kou ','Lian ','Sab ','Ten ','You ','Qi ', + 'Yan ','Chan ','Zan ','Rei ','Huan ','Xi ','Fuu ','San ','Ri ','Yuu ','Tei ','Shuu ','Shaku ','Hai ','Chuu ','I ', + 'Hang ','Yu ','Shu ','En ','Sui ','Mao ','Tan ','Ku ','Tou ','Shin ','Hun ','Sakenomoto ','','Yun ','Tai ','Tian ', + 'Qia ','Ta ','Saku ','Kan ','Ko ','So ','Hatsu ','Shuu ','Zai ','Mei ','Raku ','Setsu ','Shuu ','Yuu ','Tong ','Zhi ', + 'Xian ','Shou ','Tei ','In ','To ','Kou ','Bai ','Koku ','San ','Rai ','Ho ','Sui ','Hai ','Yan ','Xi ','Niang ', + 'Wei ','Ryoku ','Rin ','En ','Tao ','Hai ','San ','Shun ','Tan ','Sui ','Tetsu ','Saku ','Kun ','Tei ','Dai ','Du ', + 'Ko ','Sho ','Sei ','Tan ','Shyuu ','Shun ','Un ','Hatsu ','Kou ','Sou ','Mi ','Quan ','Shuu ','Cuo ','Un ','Yong ', + 'Ang ','Sa ','Kai ','Tang ','Shou ','Piao ','San ','Yu ','Ri ','Zao ','Rou ','I ','Shou ','Hoku ','Shou ','Kei ', + 'Tan ','Hatsu ','Jou ','Eki ','Rei ','Kyo ','Gen ','Yi ','Jou ','Ru ','Kun ','Shuu ','En ','Rei ','Mi ','Bi ', + 'Jou ','Kin ','Shou ','Shi ','Mi ','Gen ','Han ','Sai ','Shaku ','Yuu ','Shi ','Shaku ','Ri ','Chou ','Ya ','Ryou ', + 'Ri ','Kin ','','Hyuu ','Itsu ','Liao ','Tou ','Shou ','Tei ','Haku ','Kyuu ','Koku ','Fu ','Shin ','Shuu ','Hatsu ', + 'Luan ','Fu ','Nai ','Chou ','San ','Shou ','Kou ','Sen ','Zi ','Han ','U ','Hua ','Kan ','Kou ','Sen ','Bou ', + 'Jitsu ','Tei ','Si ','Xi ','Yi ','Sa ','Shi ','To ','Xi ','Jo ','Qian ','Kyuu ','Ken ','Heki ','Ye ','Kin ', + ], + 'x92':[ + 'Ha ','Hou ','Chen ','Xing ','Tou ','Getsu ','En ','Hu ','Pi ','Dou ','Shin ','E ','Etsu ','Don ','Kou ','Yin ', + 'Ken ','Han ','Sou ','Jin ','Shou ','Chuu ','Hun ','Yun ','Gi ','Qin ','Pi ','Guo ','Kou ','In ','Kin ','Shi ', + 'Yi ','Zhong ','Nie ','Kai ','Jitsu ','Ka ','Ta ','Kang ','Habaki ','Ro ','Ngaak ','','Taku ','Zi ','Dei ','Totsu ', + 'Shi ','Min ','Gu ','A ','Rei ','Hei ','Shi ','Ko ','Hatsu ','Hi ','Gyoku ','Si ','Saku ','Bu ','Chuu ','Ten ', + 'Kou ','Zhen ','Shi ','Shi ','Tetsu ','Kyo ','Ten ','Shi ','Sha ','Ken ','Shou ','Hou ','He ','Hi ','Sou ','Sho ', + 'Seki ','Haku ','Zhu ','Chi ','Za ','Po ','Tong ','Kan ','Futsu ','Tai ','Ryuu ','En ','Fuu ','Ryuu ','Etsu ','Pi ', + 'Ei ','Han ','Hachi ','Jie ','Kou ','Shutsu ','Sei ','Bou ','Dei ','Jou ','Di ','Jia ','Mu ','Dan ','Shin ','I ', + 'Shi ','Kou ','Ka ','Bei ','Jian ','Tou ','Kei ','Kou ','Kou ','Shi ','Er ','Raku ','Hei ','Shuku ','Bou ','Kou ', + 'Gin ','Jun ','Zhou ','Juu ','Shang ','Dou ','Mo ','Lei ','Tei ','Itsu ','Shutsu ','Ren ','Zun ','Chitsu ','Kyou ','Shan ', + 'Chi ','Sen ','Kei ','Sen ','Pi ','Tetsu ','Shu ','Kou ','Mei ','Kai ','You ','Sen ','Kan ','Xiu ','Jun ','Sa ', + 'Rou ','Ji ','Pi ','Ru ','Bei ','I ','Yin ','Kou ','An ','Diu ','You ','Shoku ','Kao ','Sen ','Luan ','Kasugai ', + 'Ai ','Diao ','Kan ','Ei ','Shi ','Keng ','Kyuu ','Shou ','Shou ','Shuu ','Sou ','Tei ','Sa ','Katsu ','Gong ','Shou ', + 'Tou ','Ryo ','Bai ','Rou ','Wan ','Shi ','In ','Hai ','Yoku ','Su ','Yu ','Sen ','Tei ','Hotsu ','Kan ','Kyou ', + 'Kou ','Cuan ','Hou ','Ten ','Wan ','Shi ','Si ','Ken ','Ka ','Gyo ','Tiao ','Gong ','Saku ','Retsu ','Xing ','Sen ', + 'Shin ','Kan ','Lue ','Ya ','Jo ','Tou ','Ju ','Ken ','Tetsu ','Bou ','Ho ','Li ','Han ','Ei ','Sei ','Gao ', + 'Ri ','Te ','Byou ','Chuu ','','Tu ','Liu ','Zui ','Kyo ','Chou ','En ','Ken ','Kou ','Diao ','Tao ','Shou ', + ], + 'x93':[ + 'Rin ','Guo ','Ryou ','Bei ','Roku ','Li ','Sei ','Pou ','Ken ','Min ','Zui ','Peng ','An ','Hi ','Xian ','A ', + 'Sui ','Rai ','A ','Kong ','Tou ','Kon ','Du ','Wei ','Tsui ','Shi ','Sou ','Ben ','Jou ','Sou ','Shun ','Tan ', + 'Jou ','Ki ','Sen ','Tei ','Ki ','Iku ','Kin ','Kan ','Byou ','Shou ','Ten ','Seki ','Ren ','Tao ','Ko ','Saku ', + 'Shu ','Zhen ','Roku ','Mou ','Roku ','Nie ','Hyou ','Atsu ','Lai ','Ken ','Kazari ','Bu ','Nai ','Wan ','Zan ','', + 'De ','Xian ','','Huo ','Kei ','','Men ','Kai ','Ei ','Tei ','Ren ','Ka ','Xian ','To ','Tu ','Wei ', + 'Sou ','Huu ','Juu ','Ji ','Gaku ','Kun ','Chin ','Tei ','Satsu ','Hong ','You ','Tan ','Ka ','Yu ','Kou ','Xing ', + 'Kou ','Wei ','Fu ','Zhao ','Sou ','Ketsu ','She ','Kou ','Kui ','Ten ','Bou ','Qiao ','Shuu ','Kou ','Chuu ','Sou ', + 'Kan ','You ','Min ','Kan ','Tan ','Ken ','Shou ','Kui ','Hu ','Xuan ','Ta ','Jie ','Shin ','Hen ','Shou ','Shi ', + 'Shuu ','Ya ','Bi ','Pai ','Ai ','Jie ','','Mei ','Sa ','Ta ','Hau ','Katsu ','Ren ','Saku ','Xi ','Ryuu ', + 'Soku ','Ye ','Dou ','Weng ','You ','Tou ','Sa ','Sou ','Reki ','Shuo ','Tsui ','Haku ','Pan ','Sa ','Hei ','Sang ', + 'Gang ','Shi ','Wu ','Ei ','Kou ','Tiao ','Ryuu ','Gai ','Shun ','Sai ','Sou ','Ban ','Kou ','Chin ','Chin ','Luo ', + 'Itsu ','Yuan ','Tang ','Nie ','Soku ','Ka ','Ka ','Ma ','Juan ','Kasugai ','Habaki ','Suo ','','','','Na ', + 'Lu ','Sa ','Ou ','Zoku ','Tan ','Shyuu ','Kan ','Sen ','Ren ','Shyuu ','Gyou ','Ban ','Baku ','Ra ','Bi ','Wei ', + 'Ryuu ','Teki ','Qiao ','Sou ','Yi ','Lu ','Ou ','Kou ','Shou ','Sai ','Qi ','Shou ','Tou ','Man ','You ','San ', + 'Feng ','Kyou ','Hyou ','Shu ','Rou ','Shuu ','Shou ','Rou ','San ','Jian ','Cao ','Li ','Xia ','Xi ','Kang ','', + 'Beng ','','','Zheng ','Lu ','Hua ','Ji ','Hoku ','Tei ','Kyou ','Hatsu ','Rin ','Suo ','Shuu ','San ','Cheng ', + ], + 'x94':[ + 'Kui ','Shi ','Ryuu ','Dou ','Kou ','Pie ','Sui ','Han ','Kyou ','Sen ','Yang ','Tang ','Xiang ','Tetsu ','Shou ','Son ', + 'Ryou ','Jie ','Lao ','Tai ','Shin ','San ','Ki ','Kan ','Shou ','Tou ','A ','Ying ','Dui ','Jue ','Nou ','Tei ', + 'Pu ','Tetsu ','','','Ding ','Shan ','Kai ','Jian ','Fei ','Sui ','Lu ','Sen ','Hui ','Yu ','Ren ','Shaku ', + 'Qiao ','Sen ','Taku ','Rai ','Heki ','Tetsu ','Kan ','Ye ','Taku ','Guo ','Tou ','Kyo ','Fen ','Tatsu ','Bei ','I ', + 'Ai ','Ban ','Xun ','Tyou ','Chuu ','Kou ','Zhui ','Ji ','Gei ','Ta ','Kaku ','Qing ','Hin ','Ying ','Kui ','Ning ', + 'Xu ','Kan ','Kan ','Yari ','Cha ','Shitsu ','Mie ','Li ','Lei ','Kei ','San ','Kou ','Shou ','Peng ','Rou ','Toku ', + 'Shaku ','Saku ','Ryo ','Hyou ','Bao ','Lu ','','Thoa ','Rou ','E ','Ro ','Kin ','Jian ','Ran ','Haku ','Sen ', + 'Yaku ','San ','Jou ','Jian ','Xi ','Kan ','Cang ','Jou ','Lei ','Cuan ','Qu ','Pan ','Ra ','San ','Ran ','Saku ', + 'Nie ','Kaku ','Tang ','Shoku ','Ran ','Jin ','Qiu ','Yi ','Zhen ','Ding ','Zhao ','Po ','Diao ','Tu ','Qian ','Chuan ', + 'Shan ','Ji ','Fan ','Diao ','Men ','Nu ','Xi ','Chai ','Xing ','Gai ','Bu ','Tai ','Ju ','Dun ','Chao ','Zhong ', + 'Na ','Bei ','Gang ','Ban ','Qian ','Yao ','Qin ','Jun ','Wu ','Gou ','Kang ','Fang ','Huo ','Dou ','Niu ','Ba ', + 'Yu ','Qian ','Zheng ','Qian ','Gu ','Bo ','E ','Po ','Bu ','Ba ','Yue ','Zuan ','Mu ','Dan ','Jia ','Dian ', + 'You ','Tie ','Bo ','Ling ','Shuo ','Qian ','Liu ','Hou ','Shi ','Xuan ','She ','Bi ','Ni ','Pi ','Duo ','Xing ', + 'Kao ','Lao ','Er ','Bou ','A ','You ','Cheng ','Jia ','Ye ','Nao ','Zhi ','Dang ','Tong ','Lu ','Diao ','Yin ', + 'Kai ','Zha ','Zhu ','Xian ','Ting ','Diu ','Sen ','Hua ','Quan ','Sha ','Jia ','Yao ','Ge ','Ming ','Zheng ','Se ', + 'Jiao ','Yi ','Chan ','Chong ','Tang ','An ','Yin ','Ru ','Zhu ','Lao ','Pu ','Wu ','Lai ','Te ','Lian ','Keng ', + ], + 'x95':[ + 'Xiao ','Suo ','Li ','Zheng ','Chu ','Guo ','Gao ','Tie ','Xiu ','Cuo ','Lue ','Feng ','Xin ','Liu ','Kai ','Jian ', + 'Rui ','Ti ','Lang ','Qian ','Ju ','A ','Qiang ','Duo ','Tian ','Cuo ','Mao ','Ben ','Qi ','De ','Kua ','Kun ', + 'Chang ','Xi ','Gu ','Luo ','Chui ','Zhui ','Jin ','Zhi ','Xian ','Juan ','Huo ','Pou ','Tan ','Ding ','Jian ','Ju ', + 'Meng ','Zi ','Qie ','Ying ','Kai ','Qiang ','Song ','E ','Cha ','Qiao ','Shou ','Duan ','Sou ','Kou ','Huan ','Ai ', + 'Du ','Mei ','Lou ','Zi ','Fei ','Mei ','Mo ','Zhen ','Bo ','Ge ','Nie ','Tang ','Juan ','Nie ','Na ','Liu ', + 'Hao ','Bang ','Yi ','Jia ','Bin ','Rong ','Biao ','Tang ','Man ','Luo ','Beng ','Yong ','Jing ','Di ','Zu ','Xuan ', + 'Ryuu ','Tan ','Jue ','Liao ','Pu ','Lu ','Dui ','Lan ','Pu ','Cuan ','Qiang ','Deng ','Huo ','Lei ','Kan ','Zhuo ', + 'Lian ','Yi ','Cha ','Biao ','Rou ','Chan ','Xiang ','Chou ','Chou ','Kyuu ','Ao ','Die ','Qu ','Liao ','Bi ','Chang ', + 'Mon ','Ma ','San ','Sen ','Koku ','Men ','Yan ','Hei ','Kan ','Hei ','Tsukaeru ','Kai ','Kou ','Hou ','Kou ','Jun ', + 'San ','Kan ','Xian ','Kan ','Bin ','Xia ','Yuru ','Dou ','Kou ','Tou ','','Peng ','Xia ','Rei ','Hen ','Hi ', + 'Tama ','Gai ','Kan ','Kaku ','Kou ','Batsu ','Shuku ','Kou ','Kei ','Ben ','Hai ','Kon ','Rou ','Ro ','Ting ','Sha ', + 'Ju ','Etsu ','Etsu ','Chan ','Keki ','Lin ','Shou ','Shai ','Kun ','En ','Ben ','En ','A ','Kon ','Yoku ','Bun ', + 'Xiang ','Bao ','Xiang ','Geki ','Yao ','Wen ','Han ','An ','I ','In ','Katsu ','Ketsu ','Ran ','To ','','Phwung ', + 'Ten ','Getsu ','Tou ','Kai ','Kou ','Ketsu ','Chin ','Kan ','Tou ','Kei ','Ki ','Tang ','Kan ','Hyou ','Kn ','Kyuu ', + 'Kai ','Sen ','Heki ','Dang ','Kan ','Tatsu ','Gon ','','Men ','Shuan ','Shan ','Yan ','Han ','Bi ','Wen ','Chuang ', + 'Run ','Wei ','Xian ','Hong ','Jian ','Min ','Kang ','Men ','Zha ','Nao ','Gui ','Wen ','Ta ','Min ','Lu ','Kai ', + ], + 'x96':[ + 'Fa ','Ge ','He ','Kun ','Jiu ','Yue ','Lang ','To ','Yu ','Yan ','Chang ','Xi ','Wen ','Hun ','Yan ','E ', + 'Chan ','Lan ','Qu ','Hui ','Kuo ','Que ','Ge ','Tian ','Ta ','Que ','Kan ','Huan ','Fu ','Kozatohen ','Roku ','Dui ', + 'Xin ','Sen ','Gotsu ','Yi ','Chi ','In ','You ','Dou ','Aku ','Sheng ','Han ','Pei ','Kou ','Yun ','Gen ','Shi ', + 'Pi ','Sei ','Bou ','You ','Yin ','Zhen ','Jie ','Tei ','Aku ','Qu ','Kyo ','So ','So ','En ','Ling ','A ', + 'Da ','Ta ','Ha ','Bing ','Fu ','Ji ','Lu ','Long ','Chen ','Xing ','Duo ','Rou ','Haku ','Kou ','Shu ','Ta ', + 'Gen ','Er ','Ki ','Yu ','Gai ','Shan ','Kai ','Shou ','Kei ','Chun ','Fu ','Hei ','Kou ','Sen ','Shou ','Choku ', + 'Pu ','Tou ','In ','Jin ','Jo ','Kan ','Tou ','Nie ','Yun ','Xian ','Bai ','Pei ','Suu ','Yi ','Tai ','Lun ', + 'In ','Ju ','Sui ','Chin ','Hi ','Ryou ','Tou ','Kan ','Riku ','','Ken ','In ','Sho ','You ','Jou ','Kyou ', + 'Chong ','En ','In ','Shu ','Tei ','Guu ','Ryuu ','Wei ','Wai ','Getsu ','Tai ','Ta ','An ','Kou ','Kai ','Zui ', + 'In ','Kai ','Yan ','Hui ','Kaku ','In ','O ','Kai ','Ai ','Geki ','Tou ','Sai ','Shou ','Tou ','Ao ','Geki ', + 'In ','','Rao ','Rin ','Tai ','Tou ','Hei ','Sui ','Zui ','Ou ','Ken ','Fen ','Ni ','Er ','Sei ','Tou ', + 'Shitsu ','In ','Shitsu ','Ki ','Rou ','Xi ','Tai ','Rei ','Rei ','Sui ','Koku ','Seki ','Jun ','Jun ','Nan ','Yi ', + 'Jaku ','Gan ','Qin ','Ya ','Yuu ','Ga ','Shuu ','Ko ','Kan ','Chi ','Kou ','Sen ','Shi ','You ','Sho ','Chu ', + 'Hu ','Zatsu ','Raku ','Yu ','Chou ','Chou ','Sui ','Han ','Waku ','Sou ','Kan ','Suu ','Zatsu ','You ','Kei ','Kei ', + 'Chou ','Liu ','Ri ','Nan ','Xue ','Za ','Ji ','Ji ','U ','U ','Setsu ','Da ','Fou ','Se ','Mu ','Bun ', + 'Fun ','Hou ','Un ','Li ','Li ','Ang ','Rei ','Rai ','An ','Haku ','Mu ','Den ','Dang ','Xing ','Wu ','Zhao ', + ], + 'x97':[ + 'Ju ','Ji ','Boku ','Chin ','Shou ','Shou ','Tei ','Shin ','Hai ','Bai ','Rei ','Qi ','Chou ','Kaku ','Sou ','Hi ', + 'Weng ','Ten ','Yin ','Gei ','Zhu ','Tun ','Rin ','','Dong ','Ei ','Bou ','Rei ','Sou ','Rei ','Ka ','Hong ', + 'Yin ','Baku ','Baku ','In ','Ryuu ','Meng ','Bin ','Mu ','I ','Huo ','In ','Xi ','Yi ','Ai ','Dan ','Deng ', + 'San ','Itsu ','Ro ','Ryuu ','Dai ','Ji ','Pang ','Yang ','Haku ','Heki ','Wei ','','Xi ','Sei ','Bai ','Meng ', + 'Meng ','Rai ','Reki ','Kaku ','Ai ','Fei ','Tai ','Long ','Rei ','Ai ','Fuu ','Li ','Bao ','','Kaku ','Kaku ', + 'Bing ','Sei ','Sei ','Jing ','Tian ','Shin ','Sei ','Tei ','Qing ','Sei ','Sei ','Ten ','Sei ','Tian ','Hi ','Fei ', + 'Kou ','Hi ','Men ','Men ','Hou ','Ye ','Ten ','Kai ','You ','Kaku ','Tei ','Sai ','Jian ','Jin ','Teki ','Du ', + 'Wu ','Jin ','Qin ','Kin ','Ka ','Niu ','Ha ','In ','Sou ','Ketsu ','Matsu ','So ','Tan ','Ban ','Yi ','Ou ', + 'Tou ','Hi ','Jia ','Hong ','Hou ','Ou ','Tomo ','Yin ','Jia ','Tou ','Ji ','Ai ','An ','An ','Hen ','Kyou ', + 'Kohaze ','Da ','Qiao ','Ting ','Wan ','Gou ','Sai ','Tou ','Sou ','Ken ','Kou ','Beng ','Tou ','Zhang ','Hei ','Kaku ', + 'Kiku ','La ','Shou ','Juu ','Bang ','Yi ','Shuu ','Qiu ','Katsu ','Xiao ','Mu ','Kiku ','Ken ','Hen ','Tei ','Jian ', + 'On ','Tou ','Kou ','Tou ','Fuku ','Ai ','Han ','Ge ','Hitsu ','Kaku ','Tou ','Lou ','Ki ','Qiao ','Ka ','Ki ', + 'Jian ','Kyou ','Chan ','Datsu ','Aku ','Ken ','Sen ','Toku ','Betsu ','Sen ','Ran ','I ','Jin ','Futsu ','Bai ','Juan ', + 'Kou ','I ','Qiao ','Kan ','Chou ','','Rou ','Un ','Shou ','I ','Ge ','Hai ','Tou ','Kou ','On ','', + 'Hitsu ','Sakan ','Hui ','Du ','Batsu ','Du ','Wei ','Ren ','Fu ','Han ','Wei ','Yun ','Tao ','Kyuu ','Kyou ','Sen ', + 'Xie ','Sen ','Sei ','On ','Sou ','In ','Shou ','Raku ','Hou ','Heng ','Ei ','In ','Peng ','Yin ','Yin ','Kyou ', + ], + 'x98':[ + 'Hu ','Ketsu ','Chou ','Kei ','Kui ','Kou ','Jun ','Kan ','Shu ','I ','Kyoku ','Gu ','Shou ','Gi ','Ki ','Kou ', + 'Yo ','Gan ','Han ','Ton ','Teki ','Dan ','Han ','Ha ','Ryou ','Saku ','Kei ','Lei ','Kan ','Qiao ','Atsu ','E ', + 'Gai ','Kitsu ','Gua ','Shin ','I ','I ','Kai ','Dui ','Pian ','Ping ','Lei ','Fu ','Kyou ','Tou ','Kai ','Kai ', + 'Kyou ','Le ','Tei ','Tei ','Ei ','In ','Hu ','Kan ','Kei ','Tai ','Tui ','Hin ','Rai ','Tai ','Shi ','Zi ', + 'Chui ','Ding ','Lai ','Yan ','Kan ','Jian ','Ka ','Sui ','Jiong ','Qin ','I ','Sai ','Dai ','Gaku ','Gaku ','Gan ', + 'Hun ','Kan ','Gyou ','Sen ','Gan ','Ken ','Shin ','Gi ','Gan ','Sou ','Ten ','Ten ','Jiang ','Ku ','Rui ','Liao ', + 'Piao ','Yi ','Ban ','Shuku ','Rao ','Kou ','Shou ','Ko ','Xun ','Qian ','Kai ','Sen ','Ju ','Hong ','Bin ','Ken ', + 'Hin ','Ro ','Lan ','Shou ','Kan ','Ye ','Ding ','Qing ','Han ','Xiang ','Shun ','Xu ','Xu ','Wan ','Gu ','Dun ', + 'Qi ','Ban ','Song ','Hang ','Yu ','Lu ','Ling ','Po ','Jing ','Jie ','Jia ','Tian ','Han ','Ying ','Jiong ','Hai ', + 'Yi ','Pin ','Hui ','Tui ','Han ','Ei ','Ying ','Ke ','Ti ','Yong ','E ','Zhuan ','Yan ','E ','Nie ','Man ', + 'Dian ','Sang ','Hao ','Lei ','Zhan ','Ru ','Pin ','Quan ','Fuu ','Biao ','Oroshi ','Fu ','Xia ','Sen ','Hyou ','Satsu ', + 'Hatsu ','Tai ','Lie ','Katsu ','Sen ','Shao ','Ku ','Hyou ','Shi ','Wei ','You ','You ','Sou ','Kai ','Sao ','Han ', + 'Liu ','Xi ','Ryuu ','Hyou ','Hyou ','Ryuu ','Hyou ','Hyou ','Hyou ','Liao ','','Se ','Fuu ','Biao ','Feng ','Yang ', + 'Zhan ','Biao ','Sa ','Ju ','Si ','Sou ','Yao ','Liu ','Piao ','Biao ','Biao ','Hi ','Hon ','Fei ','Fei ','Shoku ', + 'Shi ','San ','Ki ','Tei ','Si ','Taku ','Ken ','Son ','Xiang ','Ton ','Jin ','Yo ','Juan ','Choku ','In ','Han ', + 'Han ','Sun ','In ','Shu ','I ','Zhai ','Hitsu ','Jie ','Tao ','Liu ','Ci ','Tie ','Shi ','Hou ','Shoku ','Duo ', + ], + 'x99':[ + 'Hai ','Jin ','Ten ','Kou ','Jia ','Hei ','Yao ','To ','Shi ','Shou ','You ','Yang ','Ji ','Yan ','Le ','Yi ', + 'San ','Hotsu ','Dai ','Ga ','Ho ','Shun ','Tou ','Soku ','Yo ','Shi ','Kou ','Kon ','Ka ','Shoku ','Sen ','Tetsu ', + 'Hei ','Kan ','Hou ','Ye ','Tan ','Fei ','Chou ','Dai ','Kan ','E ','Nuan ','Un ','Ko ','Huang ','Tetsu ','Hui ', + 'Jian ','Kou ','Ei ','Tou ','Fun ','Dai ','Gu ','Cha ','Song ','Tou ','Haku ','Kou ','Ki ','Ki ','Ryuu ','Sou ', + 'Tou ','You ','Un ','Mo ','Tang ','Man ','Hitsu ','Yo ','Shuu ','Kin ','San ','Ki ','Sen ','Zen ','Shi ','Dan ', + 'I ','Ki ','Jou ','Cheng ','You ','Tou ','Hui ','Kyou ','Sen ','Fun ','Hai ','Bou ','En ','Mo ','San ','Shou ', + 'Ra ','Zuan ','Nang ','Shi ','Ding ','Ji ','Tuo ','Xing ','Tun ','Xi ','Ren ','Yu ','Chi ','Fan ','Yin ','Jian ', + 'Shi ','Bao ','Si ','Duo ','Yi ','Er ','Rao ','Xiang ','Jia ','Le ','Jiao ','Yi ','Bing ','Bo ','Dou ','E ', + 'Yu ','Nei ','Jun ','Guo ','Hun ','Xian ','Guan ','Cha ','Kui ','Gu ','Sou ','Chan ','Ye ','Mo ','Bo ','Liu ', + 'Xiu ','Jin ','Man ','San ','Zhuan ','Nang ','Shu ','Ki ','Kaku ','Kou ','Fen ','Hatsu ','Ni ','Hitsu ','Bo ','To ', + 'Han ','Fei ','Jian ','An ','Ai ','Fuku ','Ken ','Wen ','Kei ','Fen ','Bin ','Xing ','Ba ','Gyo ','Hyou ','Han ', + 'Teki ','Ta ','Taku ','Chi ','Shun ','Shu ','Zhi ','Pei ','Xin ','Jitsu ','Sou ','Yin ','Bun ','Chuu ','Dan ','Ro ', + 'You ','Baku ','Bao ','Ketsu ','Ta ','Eki ','Ku ','','Ku ','Kei ','Bo ','Zhao ','Yuan ','Peng ','Zhou ','Ju ', + 'Chuu ','Do ','Ku ','Hi ','Sou ','Ga ','Ling ','Zhen ','Tai ','Fu ','You ','Shi ','Hitsu ','Ta ','Da ','Shi ', + 'Liu ','Ba ','Hen ','Tao ','Zhi ','Rong ','Teng ','Tou ','Xun ','Quan ','Shin ','Kei ','Ji ','Kai ','Haku ','', + 'In ','Raku ','Shuu ','Dan ','Kai ','Ryuu ','Ju ','Song ','Shin ','Bou ','Liang ','Kan ','Tu ','Ken ','Tai ','Shun ', + ], + 'x9a':[ + 'E ','Tei ','Sei ','Gai ','Ryoku ','Sui ','Zhou ','She ','Hen ','Kun ','Tao ','Rai ','Sou ','Ke ','Ki ','Ki ', + 'Ken ','Hi ','Sou ','Ken ','Jie ','Yao ','Bu ','Hen ','Cong ','Hen ','Qian ','Fei ','Huang ','Jian ','Kaku ','Yu ', + 'Tei ','Quan ','Ka ','Sou ','Ki ','Rou ','Si ','Ka ','Tan ','Kui ','Sou ','Ken ','Cheng ','Shitsu ','Ryuu ','Pang ', + 'Tou ','Xi ','Cao ','Toku ','Yan ','Gen ','Shuu ','Sou ','Sen ','Li ','Chi ','Shuang ','Lu ','Xi ','Ra ','Zhang ', + 'Baku ','Gou ','San ','Hyou ','Sou ','Ku ','Bi ','Chi ','Yu ','Xu ','Ka ','Hatsu ','Shuku ','Gyou ','Rin ','Chan ', + 'Dun ','Ryuu ','Tan ','Zeng ','Ten ','Kyou ','Tetsu ','Ken ','Luo ','Zhan ','Kyou ','Eki ','Ye ','Taku ','Bin ','Shuu ', + 'Yan ','Peng ','Ryo ','Teng ','Jou ','Ki ','Shuang ','Ju ','Xi ','Kan ','Ri ','Hyuu ','Ma ','Yu ','Tuo ','Xun ', + 'Chi ','Qu ','Ri ','Bo ','Lu ','Zang ','Shi ','Si ','Fu ','Ju ','Zou ','Zhu ','Tuo ','Nu ','Jia ','Yi ', + 'Tai ','Xiao ','Ma ','Yin ','Jiao ','Hua ','Luo ','Hai ','Pian ','Hyuu ','Li ','Cheng ','Yan ','Xin ','Shin ','Jun ', + 'Qi ','Qi ','Ke ','Zhui ','Sou ','Su ','Can ','Pian ','Zhi ','Kui ','Sao ','Wu ','Ao ','Liu ','Qian ','Shan ', + 'Piao ','Luo ','Cong ','Chan ','Zou ','Ji ','Shuang ','Xiang ','Kotsu ','Wei ','I ','I ','U ','Kan ','Yoku ','Kou ', + 'Tou ','Xie ','Haku ','Bi ','Shi ','Tai ','Tei ','Ku ','Kai ','Kou ','Gou ','Ka ','Kaku ','Tui ','Kou ','Hen ', + 'Hi ','Kai ','Ka ','Gu ','Zui ','Lou ','Haku ','Xiao ','Hou ','Bo ','Ci ','Kuan ','Bin ','Mo ','Ryou ','Rou ', + 'Kou ','Toku ','Sou ','Zui ','Tei ','Hin ','Kan ','Ro ','Kou ','Kou ','Qiao ','Kou ','Kyou ','Lao ','Sou ','Hyou ', + 'Kon ','Kun ','Tei ','Hou ','Kyuu ','Zen ','Bou ','Tan ','Kun ','Bin ','Hatsu ','Chou ','Hi ','Shi ','Hatsu ','Zen ', + 'Ti ','Hou ','Hi ','Bou ','Futsu ','Ji ','Rong ','Kyoku ','','Kyuu ','Gatsu ','Kei ','Peng ','Sa ','Shao ','Sa ', + ], + 'x9b':[ + 'Tei ','Ri ','Bin ','Sou ','Tei ','Hou ','Shou ','Zheng ','Ken ','Sou ','Shun ','Sen ','Ta ','Ko ','Ratsu ','Jiu ', + 'Ki ','Lian ','Shin ','Bin ','Peng ','Mo ','San ','Man ','Ban ','Sou ','Shu ','Ryou ','Kan ','Qian ','Nong ','Kan ', + 'Katsu ','Ning ','Hin ','Ryou ','Rang ','Tou ','Tou ','Tou ','Kou ','Geki ','Tou ','Kan ','Tou ','Tou ','Kyuu ','Chou ', + 'Utsu ','Utsu ','Reki ','Ken ','Fu ','Sen ','Ki ','Sou ','Liu ','Ki ','Shou ','Shuku ','Ki ','Bi ','Ji ','Qi ', + 'Jie ','Kai ','Kon ','Batsu ','Haku ','Mi ','Xu ','Yan ','Shou ','Liang ','Yu ','Tai ','Ki ','Bou ','Ryou ','Gi ', + 'Jian ','Chi ','Piao ','Bi ','Ma ','Ki ','Kyo ','Shuu ','En ','Zhan ','Gyo ','Tou ','Jin ','Ji ','Eri ','Gong ', + 'Tuo ','Teki ','Ji ','Sho ','E ','Gou ','Sa ','Hang ','Ton ','Hachi ','Kai ','Shin ','Han ','Gen ','Hi ','Ro ', + 'Wen ','Hu ','Ro ','Shi ','Hou ','Fun ','Na ','Yuu ','Namazu ','Todo ','He ','Xia ','Qu ','Han ','Pi ','Rei ', + 'Ta ','Bo ','Qiu ','Hyou ','Futsu ','Hitsu ','Sei ','Bi ','Ju ','Chou ','Haku ','Yuu ','Gun ','Hi ','Nen ','Sei ', + 'Tai ','Hou ','Fu ','Sa ','Kyo ','Gu ','Kajika ','Konoshiro ','','Ta ','Kitsu ','Shu ','Hou ','Shou ','Ji ','An ', + 'Gai ','Tiao ','Zhu ','Yin ','Lie ','Luo ','Tou ','I ','Shi ','Hou ','I ','Kou ','Ho ','Kei ','Sen ','Ge ', + 'Kai ','Bora ','Mate ','Kao ','Gori ','Duo ','Jun ','Tei ','Ben ','Sou ','Za ','Sa ','Shin ','Yu ','Dai ','Chou ', + 'Kon ','Kou ','','Wu ','Qiu ','Ting ','Ho ','Kan ','Yuu ','Ri ','Sa ','Sa ','Gao ','Meng ','Ugui ','Asari ', + 'Subashiri ','Kazunoko ','Kochi ','Ni ','Shi ','Qi ','Sei ','Shou ','Dai ','Chun ','Ji ','Chou ','Qie ','Ko ','Zhou ','Tou ', + 'Lai ','Hi ','Gei ','Eki ','Kon ','Riku ','Jiu ','Shou ','Gei ','Lun ','Ryou ','Sou ','Li ','Meng ','Zong ','Sei ', + 'Nen ','Shachi ','Dojou ','Sukesou ','Shi ','Sou ','Hun ','Tei ','Kou ','Sei ','Sho ','La ','Zong ','Seki ','Bian ','Hen ', + ], + 'x9c':[ + 'Kan ','Sen ','Soku ','Wai ','I ','Yu ','Shun ','Rou ','Chou ','Kou ','Ren ','En ','Shuu ','Shuu ','Jian ','Hyoku ', + 'Gaku ','You ','Fuku ','Sai ','Kan ','Ka ','Ta ','Hu ','Muroaji ','Haya ','Haraka ','On ','Ken ','Hao ','O ','Fang ', + 'Sao ','Ryuu ','Ba ','Shi ','Shi ','Kan ','Shi ','Tou ','Chou ','You ','Kou ','Rong ','Qian ','Ki ','On ','Iwashi ', + 'Hatahata ','Ren ','Gou ','Le ','Hui ','Bin ','Sei ','Chou ','Qu ','Ken ','Sou ','Ban ','Xi ','Shuu ','Hyou ','Ji ', + 'Ji ','Chiku ','Shou ','Shuu ','Sen ','Shou ','Shou ','Kou ','Setsu ','Betsu ','Itsu ','Qu ','Xiang ','Bo ','Kyou ','Shin ', + 'Shuku ','Huang ','Son ','Sen ','Sen ','Fan ','Kei ','Rin ','Shin ','Miao ','Kisu ','Eso ','Kyou ','Fun ','Kan ','Kou ', + 'Kai ','Zei ','Sao ','Tan ','Kan ','Gui ','Sheng ','Rei ','Shou ','Hatahata ','Shiira ','Ai ','Ru ','Ji ','Sho ','Huo ', + 'Shiira ','Li ','Ryou ','Li ','Mie ','Shin ','Shou ','Gaku ','Ro ','Guan ','Li ','Sen ','Yu ','Dao ','Ji ','You ', + 'Tun ','Lu ','Fang ','Ba ','He ','Bo ','Ping ','Nian ','Lu ','Yuu ','Sa ','Fu ','Haku ','Bao ','Hou ','Hi ', + 'Tai ','Gui ','Jie ','Kao ','Wei ','Er ','Tong ','Ze ','Hou ','Kai ','Ji ','Jiao ','Xian ','Za ','Xiang ','Xun ', + 'Geng ','Li ','Lian ','Jian ','Li ','Shi ','Tiao ','Gun ','Sha ','Wan ','Jun ','Ji ','Kochi ','Qing ','Ling ','Qi ', + 'Zou ','Fei ','Kun ','Chang ','Gu ','Ni ','Nian ','Diao ','Jing ','Sou ','Shi ','Zi ','Fen ','Die ','Hyaku ','Chang ', + 'Shi ','On ','Wei ','Sai ','E ','Qiu ','Fu ','Huang ','Quan ','Jiang ','Bian ','Sao ','Ao ','Qi ','Ta ','Yin ', + 'Yao ','Fang ','Jian ','Le ','Biao ','Xue ','Bie ','Man ','Min ','Yong ','Wei ','Xi ','Jue ','Shan ','Lin ','Zun ', + 'Huo ','Gan ','Li ','Zhan ','Guan ','Chou ','Itsu ','Fu ','Li ','Kyuu ','Bu ','Gan ','Fu ','Diao ','Kei ','Hou ', + 'Nio ','Gan ','Shi ','Hou ','Mei ','Bao ','En ','Shi ','Hu ','Ken ','Fu ','Fen ','Wen ','Jian ','Shi ','Yu ', + ], + 'x9d':[ + 'Fou ','Yao ','Ketsu ','Ketsu ','Pi ','Huan ','Chin ','Hou ','Gan ','A ','Zheng ','Hou ','Feng ','Wen ','Ou ','Te ', + 'Jia ','Do ','Rei ','Mie ','Fu ','Ta ','Wen ','Ryuu ','Hen ','Zhi ','Ge ','En ','Shi ','Ku ','You ','Shi ', + 'Dan ','Ju ','You ','Ko ','Zhong ','Yu ','You ','Rong ','Ou ','Tie ','Itsu ','Shigi ','Ou ','Zhui ','Wu ','Ji ', + 'Katsu ','Ai ','Shi ','An ','Kou ','Jiao ','Ji ','Lie ','Zhu ','Ren ','Tei ','Kou ','Ro ','Jo ','Bou ','Kou ', + 'Ren ','Kou ','Kyuu ','Chuu ','Shi ','Raku ','Chidori ','Toki ','Ten ','Luan ','Kou ','Ji ','Yu ','Huan ','Tuo ','Bu ', + 'Bu ','Ken ','Yu ','Hotsu ','Shun ','Xun ','Bi ','Xi ','Jun ','Geki ','Tu ','Jing ','Tei ','Ga ','Ga ','Kyou ', + 'Koku ','Bu ','Shin ','Rai ','Ikaruga ','Kakesu ','Lu ','Hei ','Shu ','Fuku ','An ','Tou ','Hou ','Qin ','Qian ','Hi ', + 'Chou ','Lu ','Jaku ','Jian ','Ju ','Tu ','A ','En ','Qi ','Li ','Ya ','Sui ','Kou ','Zhui ','Kon ','Sheng ', + 'Qi ','Jing ','Yi ','Geki ','Sei ','Zi ','Rai ','Tou ','Qi ','Shun ','Kou ','Ju ','Qu ','Isuka ','Kikuitadaki ','Kei ', + 'Shu ','','Seki ','Byou ','Rou ','An ','Shuu ','Tei ','Ko ','Ti ','Gaku ','Jie ','Mao ','Fu ','Chun ','Tu ', + 'Yan ','Katsu ','Yuan ','Pian ','Kon ','Mei ','Hu ','Ying ','Dun ','Boku ','Keki ','Tsugumi ','Sou ','Fang ','Koku ','Ou ', + 'Yuan ','Ken ','Ou ','Shi ','Kaku ','Suu ','Tang ','Xia ','Jaku ','Ryuu ','Seki ','Kotsu ','Ken ','Zhun ','Han ','Shi ', + 'Zi ','Geki ','You ','An ','Kei ','Li ','Ten ','Kou ','Ti ','Tei ','Geki ','Tu ','Ma ','Jiao ','Gao ','Ten ', + 'Chen ','Li ','Zhuan ','Sha ','Gou ','You ','Ei ','Ou ','Chi ','Shi ','Ryuu ','Rong ','Lou ','Bi ','Sou ','Saku ', + 'Gyo ','Wu ','Jue ','Yin ','Quan ','Shi ','Shou ','I ','Hua ','Hetsu ','Ying ','Shuku ','Huang ','Ban ','Kyou ','Ryou ', + 'En ','Kao ','Shuu ','Kan ','Kan ','Tu ','Mai ','Zun ','Itsu ','You ','Ro ','Tuan ','Xian ','Kaku ','I ','Pi ', + ], + 'x9e':[ + 'Shu ','Luo ','Kei ','Yi ','Ji ','Zhe ','Yu ','Sen ','Ye ','Yang ','Heki ','Ning ','Huo ','Mi ','You ','Meng ', + 'Teki ','Gaku ','Yo ','Lei ','Bao ','Ro ','Kaku ','Long ','Shuang ','Yaku ','Ou ','Kan ','Ku ','Ri ','Ran ','Niao ', + 'Jiu ','Ji ','Yuan ','Ming ','Shi ','Ou ','Ya ','Cang ','Bao ','Zhen ','Gu ','Dong ','Lu ','Ya ','Xiao ','Yang ', + 'Rei ','Zhi ','Qu ','Yuan ','Kaku ','Tuo ','Si ','Zhi ','Er ','Gua ','Xiu ','Heng ','Zhou ','Ge ','Luan ','Hong ', + 'Bu ','Bo ','Li ','Juan ','Hu ','E ','Yu ','Xian ','Ti ','Wu ','Que ','Miao ','An ','Kun ','Bei ','Peng ', + 'Qian ','Chun ','Geng ','Yuan ','Su ','Hu ','He ','E ','Gu ','Qiu ','Zi ','Mei ','Mu ','Ni ','Yao ','Ou ', + 'Liu ','Seki ','Geki ','Jian ','He ','Yi ','Ying ','Zhe ','Liao ','Liao ','Jiao ','Jiu ','Yu ','Lu ','Xuan ','Zhan ', + 'Ying ','Huo ','Meng ','Guan ','Shuang ','Ro ','Kyou ','Ling ','Ken ','Kan ','Sa ','Kan ','Ken ','En ','Cuo ','Roku ', + 'Yuu ','So ','Ki ','Hou ','So ','Hou ','Zhu ','Kin ','Shu ','Jian ','Mi ','Bi ','Gu ','Liu ','Shin ','Kin ', + 'Lin ','Gei ','Ki ','Roku ','Jiu ','Kin ','Kei ','Rei ','Kyou ','Yan ','Jia ','Bei ','Li ','Sha ','Shou ','Rin ', + 'Jing ','Ji ','Ling ','Yan ','So ','Baku ','Baku ','Ge ','Shou ','Fu ','Men ','Mian ','Fu ','Hou ','Kyo ','Kiku ', + 'Bou ','Fu ','Xian ','Rai ','Kiku ','Ben ','','Feng ','Fu ','Kiku ','Men ','Ma ','Ma ','Mo ','Ki ','Ro ', + 'Zou ','Nen ','Fen ','Kou ','Kou ','Jin ','Kou ','Tian ','Tou ','Heng ','Xi ','Kou ','Kou ','Sho ','Rei ','Nen ', + 'Chi ','Koku ','Koku ','Yi ','Ken ','Tan ','Xi ','Tuan ','Moku ','Moku ','Qian ','Tai ','Chutsu ','Yuu ','Ten ','Ei ', + 'Katsu ','En ','Qu ','Mei ','En ','Gei ','Yu ','Rei ','Tou ','Du ','Can ','Yin ','Kan ','En ','Tan ','An ', + 'Shin ','Tai ','San ','Yi ','Bai ','Tan ','En ','Toku ','Ro ','Chi ','Fen ','Futsu ','Ho ','Bou ','Min ','Gen ', + ], + 'x9f':[ + 'Cu ','Qu ','Chou ','Wai ','Zhu ','Chi ','Mang ','Gou ','Betsu ','Ta ','Bi ','Yuan ','Chao ','Tuo ','Tei ','Beki ', + 'Dai ','Tei ','Shi ','Ko ','Ko ','Tou ','Fun ','Tou ','Yuan ','Hei ','Chou ','Kou ','Qi ','Yuan ','Tang ','Tou ', + 'So ','Sho ','Fun ','Fei ','Wen ','Ba ','Chou ','Tuo ','Tong ','Qu ','Sei ','Seki ','Yuu ','Shi ','Ting ','Go ', + 'Nian ','Sei ','Kon ','Ju ','En ','Tu ','Ti ','Kei ','Xian ','En ','Rui ','Bi ','Gyou ','Gu ','Kan ','Gotsu ', + 'Wu ','Kou ','Xi ','Katsu ','Sha ','Kyuu ','Ou ','Sa ','Nong ','Nang ','Sei ','Sai ','Ji ','Zi ','Sei ','Sei ', + 'Qi ','Ji ','Shi ','Shin ','Shin ','Kotsu ','Ga ','Kin ','Kai ','Pao ','Saku ','Shi ','Zi ','Chi ','Gen ','So ', + 'Chou ','Rei ','Rei ','Shutsu ','Quan ','Xie ','Gin ','Ketsu ','Kyuu ','Gou ','Soku ','Kun ','Gyo ','Sho ','Gi ','Gei ', + 'Saku ','Seku ','Ku ','Gun ','Xian ','Gou ','Gaku ','Aku ','Yi ','Chuo ','Shuu ','Dian ','Chu ','Kin ','Ya ','Chi ', + 'Chen ','He ','Ken ','Ju ','Ling ','Pao ','Tiao ','Zi ','Ken ','Yu ','Chuo ','Qu ','Wo ','Ryuu ','Pang ','Kyou ', + 'Hou ','En ','Ryu ','Long ','Kyou ','Gan ','Tou ','Rei ','Tou ','Long ','Gong ','Kan ','Ki ','Shuu ','Betsu ','Gui ', + 'Yaku ','Sui ','Ka ','Kaku ','Kai ','Yaku ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Shan ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'xf9':[ + 'Kay ','Kayng ','Ke ','Ko ','Kol ','Koc ','Kwi ','Kwi ','Kyun ','Kul ','Kum ','Na ','Na ','Na ','La ','Na ', + 'Na ','Na ','Na ','Na ','Nak ','Nak ','Nak ','Nak ','Nak ','Nak ','Nak ','Nan ','Nan ','Nan ','Nan ','Nan ', + 'Nan ','Nam ','Nam ','Nam ','Nam ','Nap ','Nap ','Nap ','Long ','Nang ','Nang ','Nang ','Nang ','Nay ','Nayng ','No ', + 'No ','No ','No ','No ','No ','No ','Lou ','No ','No ','No ','No ','Nok ','Nok ','Nok ','Nok ','Nok ', + 'Nok ','Non ','Nong ','Nong ','Nong ','Nong ','Noy ','Noy ','Noy ','Noy ','Nwu ','Nwu ','Nwu ','Nwu ','Nwu ','Nwu ', + 'Nwu ','Nwu ','Nuk ','Nuk ','Num ','Nung ','Nung ','Nung ','Nung ','Nung ','Twu ','La ','Lak ','Lak ','Lan ','Lyeng ', + 'Lo ','Lyul ','Li ','Pey ','Pen ','Pyen ','Pwu ','Pwul ','Pi ','Sak ','Sak ','Sam ','Sayk ','Sayng ','Sep ','Sey ', + 'Sway ','Sin ','Sim ','Sip ','Ya ','Yak ','Yak ','Yang ','Yang ','Yang ','Yang ','Yang ','Yang ','Yang ','Yang ','Ye ', + 'Ye ','Ye ','Ye ','Ye ','Ye ','Ye ','Ye ','Ye ','Ye ','Ye ','Yek ','Yek ','Yek ','Yek ','Yen ','Yen ', + 'Yen ','Yen ','Yen ','Yen ','Yen ','Yen ','Yen ','Yen ','Yen ','Yen ','Yen ','Yen ','Yel ','Yel ','Yel ','Yel ', + 'Yel ','Yel ','Yem ','Yem ','Yem ','Yem ','Yem ','Yep ','Yeng ','Yeng ','Yeng ','Yeng ','Yeng ','Yeng ','Yeng ','Yeng ', + 'Yeng ','Yeng ','Yeng ','Yeng ','Yeng ','Yey ','Yey ','Yey ','Yey ','O ','Yo ','Yo ','Yo ','Yo ','Yo ','Yo ', + 'Yo ','Yo ','Yo ','Yo ','Yong ','Wun ','Wen ','Yu ','Yu ','Yu ','Yu ','Yu ','Yu ','Yu ','Yu ','Yu ', + 'Yu ','Yuk ','Yuk ','Yuk ','Yun ','Yun ','Yun ','Yun ','Yul ','Yul ','Yul ','Yul ','Yung ','I ','I ','I ', + 'I ','I ','I ','I ','I ','I ','I ','I ','I ','I ','I ','Ik ','Ik ','In ','In ','In ', + 'In ','In ','In ','In ','Im ','Im ','Im ','Ip ','Ip ','Ip ','Cang ','Cek ','Ci ','Cip ','Cha ','Chek ', + ], + 'xfa':[ + 'Chey ','Thak ','Thak ','Thang ','Thayk ','Thong ','Pho ','Phok ','Hang ','Hang ','Hyen ','Hwak ','Kotsu ','Kaku ','','Coc ', + 'Chou ','','Sei ','','','Ki ','Cho ','Eki ','Rei ','Shin ','Shou ','Fuku ','Sei ','Sei ','U ','', + 'Hagi ','','Sho ','','','Itsu ','To ','','','','Han ','Shi ','Kan ','Kaku ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x200':[ + 'Ha ','Qi ','','','','Hai ','','','','Qiu ','','','','Shi ','','', + '','','','','jue ','','','','','','','yu ','','','','', + '','','','','','','','Ba ','Cup ','','Kha ','','','','','', + '','','','','Trut ','','','','','','','','','lu ','','', + '','','','','','','','','','','','','','','','', + '','Duoi ','','','','','','','','','Cui ','','','','','', + '','','','','','Ga ','','','','','Nham ','','','','','', + '','','','','','','','','Suot ','','','','','','','', + '','','','','','','','','jie ','','','','','','','', + '','','','','Zi ','','','','','','','','','Zung ','','', + '','','Pai ','','Dui ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','jiu ','','','','','', + ], + 'x201':[ + 'Vu ','','','','','','','','','','','','','jie ','','', + '','jue ','','','','','','','','','','','','','','', + '','','','','','','Gop ','Vai ','','Hai ','','','','','','', + '','','','Kep ','','','Nham ','','','','','Lam ','Nam ','Vai ','','wei ', + '','','jie ','','','','','','','','','','','Mat ','Mat ','', + 'Mat ','','Mat ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','zhang ','','','Mat ','','','', + '','','','','','','','','','','','','Yong ','','','', + 'xu ','','','','','','','','','','','','','','','', + '','','','','','','','','','Faan ','','','','','','', + '','','','Trum ','','','dan ','','','','','','','','','', + '','','','','','','','','','','','','','Voi ','','', + '','','','','','Va ','','','chu ','','','','','','','', + '','','','','','','','','','','','','','','','qu ', + '','','','','','','','','','','','','Hua ','Top ','','', + ], + 'x202':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','yun ','','','','','','','','','','','', + 'dan ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Nay ','', + 'Tray ','','','','','','','ju ','','du ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','jian ','','','','','','','','Ngai ','','Nho ','Thay ','','', + '','','','','','','','Bing ','','zhuan ','shu ','','jue ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','lian ','','','','','','','','she ','', + '','','','','','May ','Mu ','','','fu ','','','ju ','','','', + '','','','','','','','','','','Tao ','','','','','', + ], + 'x203':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Wu ','','','','','','','','shuai ','','', + 'gai ','','','','zhuang ','','','','','','','','','fu ','','', + '','Man ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','But ','','','','','yao ','','','','Gap ','','bie ', + '','','qu ','','','yang ','','','','','','','','sha ','','', + '','','','','','','','','','','Xum ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Cap ','Bay ','','','','','jue ','', + '','','','yu ','','','','sa ','','','','dun ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','xiao ','','','','','yu ','qu ','','','','', + '','','','','','Ngai ','','','','','','','','Tui ','','', + '','','','Giong ','','','','','','','','','','','','', + ], + 'x204':[ + '','meng ','','','','','','','','jie ','shu ','','','su ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','meng ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Trom ','','','Long ','','','','', + '','','','','','Ngua ','','','','','nei ','nei ','','','zhai ','', + '','','','','','','','','','','','','Nhau ','','','cu ', + '','','','','','','','','','','','','','','','', + '','','','','wu ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Rang ','','','','','','','','','','', + '','','','','','lian ','','Tin ','','','','','','','fan ','', + 'Truoc ','','','','','','','','','','','','','','','', + 'Quanh ','','','','Mong ','','','fu ','','','','','','','','', + '','','','','','','','','Vao ','Nhui ','','','','','','', + '','','','','','','','','','Lon ','','Tron ','Sip ','','','', + ], + 'x205':[ + '','','','Xi ','','','','','','Juan ','','','','','','', + '','hai ','','','','lun ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','heng ','','','','','','','','','Zheng ','','','','', + '','','','','Nap ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'cheng ','','','qia ','','','yu ','','','','','','','zhao ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Xuong ','','','','','','','', + '','','','','','','','','Nap ','','','','','','','', + '','','','','Bay ','Chong ','','','','','','','','','','Ngat ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','qiu ','xie ','','','','','','', + '','','','','','','','','','','','die ','','','','', + '','','','Lun ','','','Ping ','','die ','','','','','','','', + 'Tron ','','','','','','','','','Ret ','','','','liu ','','', + ], + 'x206':[ + '','bu ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','lai ','','', + '','','he ','jiao ','','','','','','','','','','','','', + '','','','','','','','','','','','wu ','','','','', + '','','','','','','ju ','','','','','','','','','', + '','','','','jiu ','wei ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','xian ','','','','chang ','','','','','', + 'Moc ','','','','he ','','','','','','','','','','','', + '','','Ra ','','','','','','','','','','','','','Got ', + '','zhe ','','','','ju ','','','','Shan ','Sha ','','','','','', + '','','','','','','','','','','','','Cham ','','','', + '','','','','','','','','','cu ','','','','','','', + '','','','','Chem ','','','','','','Tiu ','','','','','', + '','','','','','','','','fen ','','','','','','','', + ], + 'x207':[ + '','','','jiu ','xu ','','','','','','','','','','Xian ','', + 'kuai ','','','','','','','','','bu ','','','','','','', + '','','','','qia ','','','','','','','','','','Hui ','', + '','Pai ','','','','','','','','ju ','','','Qia ','','','', + '','','','','','','','Bao ','','','','','','','','', + '','','','','','Cun ','','','qia ','','','','','','','', + '','','','','','','','','','','','','','Peng ','','', + '','','','','','','','','','Gaai ','','','','','','', + '','','','zhe ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','Got ','Bam ','','','','','','','','','','gun ','Lou ','','', + 'Jiao ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','yao ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Hoat ','','','','','','','','','','', + '','','','','','','','','','','','ze ,bai','','','','', + ], + 'x208':[ + '','','','','zhao ','','','','','Bua ','','','','','','', + '','Tet ','','','du ','','','','','','','','','','','', + 'du ','','','','','','','','','Truoc ','','','','Chom ','','die ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','Gang ','','','','','', + '','','','','','','','','','','','','','','','', + '','duan ','','','','','','','','','Khuot ','','','','','', + '','','','','','','','han ','','','','','','','','', + '','Nhoc ','','','','','','','','','juan ','','','Vam ','Giup ','Giup ', + '','','','dian ','Jue ','','','','','','','','Lu ','','','', + '','','','','','','','','','','','','','','','', + '','','Ruon ','','','','','','','10383.060,wan ','','','','','','', + 'yun ','','','','','','','','','','','','','','','', + '','','','','','','','','','','qu ','shao ','','','','', + '','','','pao ','','','','','','','bao ','','','','fu ','jiu ', + ], + 'x209':[ + '','','','','','','Cho ','','','','','','Cho ','','hua ','Bao ', + '','','','','','','','','','','','','','mao ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','diao ','','','', + '','','','','','','','','','','','','','','wei ','', + '','diao ','','','','','','','','','','','','','','', + '','','','','Giau ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','sa ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','luan ','Muoi ','','','','','','Gan ', + '','','','','','','','','','Chuc ','','Lung ','','','','', + '','','','','','','Tron ','yu ','','','','','','Nhu ','','', + '','','','','','he ','','','','shao ','','','','','','', + '','','','','','','','','','Hui ','','','','','','', + '','','','','','','','','','','','','','','','heng ', + ], + 'x20a':[ + '','','','wai ','','','','','','','jue ','','','','zhuan ','', + '','','','','','','','','','','','','','','','', + '','','jun ','','','','','','','','','','','ju ','','', + '','','','','','bang ','','','','','','','','','','', + '','','','','','','','','zhu ','','','','','','','', + '','','','','','Me ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','Li ','','','','','', + '','','','mei ','','','','','','','','','','','','', + 'liu ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','fu ','','','','', + '','','','jue ','','Day ','','','','','','','','','','Rot ', + '','','','','','','','','','','','','','','','', + '','','','yu ','','','','','','','','','','','tu ','', + '','','','','','','','','','shan ','','','','','','', + ], + 'x20b':[ + '','','','','','','guan ','','','','','','','','','', + '','','Cut ','','','','','','','','','Mo ','','fu ','','', + 'Mot ','','','bang ','','','','','','','biao ','','','','jie ','', + '','','','','','','Jin ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','Zhuo ','','','','','bian ','','','','','','tun ', + '','','','','','','','','','','de ','','zhu ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Naai ','Aa ','','','','','','', + '','','','','','mang ','','','','','','','','','Ngot ','sa ,san', + '','','','','','','','','Daai6','','','Jai ','','','','', + '','','','zhe ','','','','','ban ','jie ','','','','','','', + '','','','','','','Cai ','','','','','','','','Hin ','pian ', + '','','','','bian ','','','reng ','','reng ','','','Danh ','Zi ','','', + ], + 'x20c':[ + '','','Ngoen ','','','','','','','','','Jaau ','Mut ','','','Mom ', + '','an ','','he ','','','','','','Khen ','','hu ,gao','','','','', + '','','','','','','','','','','','','','Meo ','','', + '','','Eot ','','','','','Lo ','','','dai ','wai ,wai','','','','', + '','Tam ','Dat ','Nip ','','Quai ','','','','','','','','Phom ','','', + '','','','Ngai ','','','','','Ngaak6','','','','Chun ','','','', + '','sa ,shai','','','','Fik ','','','','','','','','','','', + '','','na ','','','','','Ming ','San ','','','','','','','', + '','','','','','','','','','','','','shu ','','','Nham ', + '','','','Hang ','','','Ji ','','','','','','Zaang ','','','', + '','','','','','','Nhung ','','','','','','','','Khinh ','', + '','ge ','','','','Gip ','','die ','','','','','','fu ','','Shu ', + '','Kwan ','','','','','','he ','','','','','qia ','','','Ce ', + 'Vang ','','','','','Caau ','Dap6','','Nhu ','Thay ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','Tu ','','','','','','','cheng ','','', + ], + 'x20d':[ + '','','','','','','','','','','','Phao ','Nhanh ','Nhan ','','Mang ', + 'Nuc ','','','','','Miu ','Voi ','','','','','Gung ','','','','', + '','xiao ','','','','Ngoam ','zhu ','','','','','Thut ','','','','', + 'Gau6','hu ','ta ','Ngaau ','','zao ','','','','','','','dao ','','na ','', + '','','','','','','Daam ','Koe ','Mui ','Hong ','','','','','','', + 'Mep ','','','','','','','','Mun ','','','','','','','', + '','','','ya ','','','','zhen ,chun','de ','Go ','','','','','','Gwit ', + '','E ','','','','','','xuan ','','','','','Mang ','Faat ','Waak ','Pe ', + 'Tham ','Nhu ','','','','','','','Se ','','Pha ','','','','','', + '','U ','','','','Nhau ','Uong ','','Sat ','Bop ','','','Zai ','','','', + '','Troi ','Du ','Mai ','','Kung ','','Dim6','','','','da ','nang ','','','Chut ', + '','','Gap6','','','','','','jue ','he ','','','','','','', + '','','dai ','','','zhu ','','','','','','','','ta ','','', + '','','','','','','bian ','','','xu ','','','','','','', + '','','','','Phao ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x20e':[ + '','pai ','Giot ','','Inh ','','','','','Kak ','Tap ','','','Me ','Naa ','Ge ', + 'Kam ','Soek ','Bou ','','','','','Xua ','Tuc ','Song ','','','','','','Bai ', + '','','','','','','Khan ','','','','','Tau ','','','','', + '','','','','','','','','','yu ','Ngaak6','','','','Map ','', + 'xun ','wa ','','ang ','han ','','','','','','','','Lan ','','','', + '','yao ','','ge ','','bao ','','','xu ','','','','','','','', + '','','','','','','','','','','','','','Ko ','','', + '','','','Git6','','','','Ngo ','Kam ','Lan ','Maai ','Zam6','','Cay ','','', + '','','','','','','','','','','','','Gwe ','','','', + 'huan ','','','','','','','','Long ','Thoi ','Ban ','','','Gaak ','','ku ', + 'Lung ','','Gaa ','','','','','','','Trou ','He ','Loe ','He ','','','', + '','Hung ','','','','Chac ','Nop ','','','Ri ','Que ','Cop ','Xui ','','Chau ','Ngoan ', + '','Guong ','Ngon ','Han ','Oang ','','','','','','','','','huan ','','zu ', + '','','','','','','','Le ','Zeot6','he ','','','','','','', + '','','','','Don ','zhao ','','','','','','','tu ','','','', + '','','','','Long ','','','','','','Aa6','Bai ','Dau6','','','', + ], + 'x20f':[ + '','','','','','','','','','','','','','','','', + '','','','','','Paai ','','Zaam ','wu ','','','','','','','', + '','','jiang ,qiang','','','','Muon ','','','lun ','Day ','','','But ','Ngai ','Ho ', + 'Kang ','Loe ','','','','Danh ','','Thay ','','','','Ji ','','','','', + '','Xo ','','Zap ','Tham ','Thung ','Nuot ','','','','','Nac ','Syut ','','Nhai ','', + 'Ngo ','','Neng ','Ngon ','Thua ','','Giuc ','','','','','Oam ','','','','', + '','','','','Kik ','','','','','','','','','','','', + '','','','','','yu ','','','','','','zhe ','','','','', + 'Hup ','','','','','','','','','','','','','He ','','Ce ', + '','','','','','','','','','','','Ngoang ','','','','', + '','','shu ','Rum ','','','Bai ','','','la ','','','','We ','','', + '','','','','Baang ','Zaa ','Ging ','','','Nuot ','','','Cyut ','Nhun ','Nhap ','', + '','Si ','Xep ','','','','','','','','','','','','','', + '','','Het ','sa ','','qiao ','','','','','','Lu ','hua ','','','', + '','','','','','','','','','','Gaa ','Saau ','Soe ','Wet ','','Ngui ', + '','','','','','Khan ','','','','','','','','','','', + ], + 'x210':[ + '','','','','','','','','','','','','','','','', + '','','','','Lu ','','','','','','','','','Nam6','Zip ','', + 'Bei6','','','','','Phao ','','','','Lok ','','Bam ','','','','', + '','Hao ','Goi ','','','','','Ron ','','','xie ','','','','','', + 'han ','','','','','','','','fan ','','','','','ai ','yu ','Am ', + '','','','','','','','','','','Hon ','','Wo ','Hang ','Xao ','', + '','','','','','','','','','','','','','','','Dyut ', + '','','','zhan ','','Gan ','Zit ','Doeng ','Kwaat ','','Ngon ','Ziu ','','','','', + 'Khao ','','','Hun ','','','','Mom ','Buk6','','yu ','','','Eng ','','', + '','Ban ','','','','','Lai ','','','','','','','Zuk6','','bao ', + '','shu ','','','','','','','','','Ze ','peng ','','','Ngau ','', + 'Ran ','','Ray ','Troi ','','','','Khoan ','','','','','','','','', + 'E ','Leng ','','','lai ','','','Bai6','Kwaak ','Gaa ','','','','Chem ','Phan ','Doe6', + '','','Boc ','Bo ','','Gung ','Le ','Mua ','','Mut ','','','','lun ','','', + '','','','','Laai6','','','','','','','','','','','', + '','','','','Ceoi ','Ngung ','Sek ','','','Chen ','','','','','Phac ','Thot ', + ], + 'x211':[ + '','Lum ','','','','','','','','','','','','Ruc ','Gam ','Ham ', + '','','dao ','','','','','','','','','','','','','Haa ', + '','Zaai ','','','','','Lom ','','','Khan ','Toe ','Khem ','Hun ','','','Jik ', + 'Tot ','cu ','ru ','','','Ji ','','','','luan ','','','','Soe ','','', + '','','','','','e ,ei','','','Laa ','Dang ','Bun ','Hum ','','','','Lai ', + 'Lanh ','Ngong ','','','','','','','la ','yun ','','','','','','', + '','','','','','die ','','Nan ','','','','','Hoai ','','','', + '','huan ','','','','','','','','','','huan ','','','','', + 'Gwang ','Nhau ','','','Nhep ','wan ','','Wok ','','','','','','','','', + '','Nham ','','','','lian ','Trom ','','','','Gu ','','','','Giau ','', + '','','','','','jiu ','','','','','','','','','','', + 'dun ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','die ','','','','','','Doe ','','','','','he ','', + 'zhe ','','','','','','wei ','','','tu ','','','','','','hun ', + '','','','','','dang ','he ','tai ','Quay ','','yu ','Nhot ','ya ','','','', + ], + 'x212':[ + '','','','','','jue ','','','','','','','','','Mui ','', + '','','','yuan ','','','','','','You ','','','','','','', + '','','','','','','','','yu ','','','','','','','', + '','','','','','','lei ','','','','','','','','','', + '','','','','','','','','','','','','','','Cong ','', + '','','tun ','','','','Cong ','','','','','','','','','', + '','','','','','','','','','bao ','','','','','','', + '','','','','lu ,hu','','','jie ','','','','','','','Tum ','Moc ', + '','','','','','','','','','','','','','shu ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Sanh ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','gao ', + '','','','','','','','','','de ','','','yu ','','','', + '','','','','','','','','','','','','','','','', + ], + 'x213':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','guai ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'hu ','','','','','','','','Che ','Vung ','Lam ','','Mun ','Nui ','','', + '','','','','','zhai ','','','du ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','du ','','','','','','', + '','an ','','','','','','','','','','Bun ','Nam ','','','Hang ', + '','','','','','','','','','','','','','Thong ','su ','', + '','','','','Gung ','','','','','','zhu ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','xia ','','','','','','','', + '','Luong ','','','','Tret ','Xay ','Bui ','','','','','','','','bai ', + '','','','','','','','','','','','','','','','', + ], + 'x214':[ + '','','','','','','','','','','','','chu ','','','', + '','','','','','','xian ','Hoc ','','','','','','fu ','','', + '','','','','','sa ','','','','','','','','','Ve ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Coi ','Chum ','','','','Thoai ','','','','','','Lan ','Sui ','', + '','','','','','','','','','','','','','Coi ','','', + '','','Gom ','','','','','','','','','','','','yu ','', + '','sa ','','Juk ','Lan ','','','','','','yu ','','','ju ','','', + '','','shu ','xian ','','','gai ','','','','','','','','','', + '','','','','','','','','','','','Cau ','','','Suong ','', + '','','','','','','','','','','','','','','','', + '','','','Loi ','Vung ','','','','','','','','','','','San ', + '','','lai ','','Lam ','','','','','','','','','','','', + '','','','','','Chen ','zhan ','','','','','','','','','Chum ', + '','','','','','','','','','','','','','','','', + ], + 'x215':[ + '','','','','','','','','','','','','','','','', + '','','','','Lan ','','','','','','','','','','','', + '','','','','','','','','','','shu ','','','','','', + '','','','','yu ','','','','','','','','','','','Trau ', + '','','','','','','','','','','','','','','','', + '','','kua ','','','','','hai ','','','','','','','','', + '','','','','','','','hang ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','yun ','','','','','','','','','','','','','', + '','','','','','','','','','','guai ','','','','','su ', + '','Bon ','','','','','','','','','','','','','','', + '','','Sai ','','','','','','','','','Lam ','','','Tum ','', + 'Muong ','','','','','','','Peng ','','','','','','','','', + '','','','','','chun ','','','','','','','','','','', + '','','','','','','','','','fan ','','','','','','', + ], + 'x216':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','zhe ','Mat ','Lon ', + 'juan ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','jie ','','','','','','','bie ','','','','','', + '','','','','Canh ','Nhon ','','','','','','','','','','', + '','Bi ','','Xon ','','','','yan ','wei ','','','','hao ','','','', + '','','','','meng ','','','','','','Lon ','','','','','', + 'jue ','To ','To ','','','','Hai ','','','','','','','','','', + '','','','','','','','','','zhang ','','da ','','hao ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','can ','','', + '','','','','Nua ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x217':[ + 'fan ','','hu ','','','','','','','','','','','','','', + '','','','','','','','','','','ru ','','','','','', + '','','','','','','','','','','','','','','','zhe ', + '','Ji ','gao ','','','','','','','','','','','','','', + '','','','Bua ','','','','','chu ','','zhe ','','','','','', + '','','','','Kep ','Va ','','','','','cheng ','','du ','','','nian ', + '','','','','','','Vu ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','cu ','','','pan ', + 'hu ','','','xian ','','','','','','','fu ','nai ','','','','', + '','','','','','','','','','','','','','','Nen ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','lian ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x218':[ + '','','','','','','','','','','','','','','','', + '','','','','','','hao ','','yang ','','','','','','fu ','', + '','','','Cuoi ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'juan ','','Nhang ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','qu ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'zhuan ','','','','','','','','dang ','','','','','','','', + 'Sau ','','','','','','','','','','man ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Sui ','','', + '','','','','','','','','shu ','','','','','','','', + '','','','','han ','Ban ','','','','','','','','','','', + '','','nei ','','','','','','Cuoi ','','','','','','cai ','jie ', + '','','','','','','','','','','','Sen ','','','','', + ], + 'x219':[ + '','','','','','','','','','','Chua ','','','','fan ','', + '','','','Moi ','Moi ','','','zhu ','','na ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','jiao ','','','','Nhat ','xiao ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Con ','ju ,ru','','','','','','Me ','','','', + '','xu ','','','fu ','So ','','','','','','','','','','', + '','','','','','er ','','','','','','shu ','','','','', + '','','','','','','','Rot ','','','','Chat ','','','Nhang ','', + '','','','xiao ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','mian ','','','','','wa ','','pao ','','','','','','', + '','','','','','','heng ','','zhu ','','','','','','','', + '','','','','','','','','','dai ','','','','','','', + ], + 'x21a':[ + '','','','','Xia ','ju ','','','','','','','','','','', + '','','','','','','','zao ','','','','','','','','', + '','','','yu ','','','','Tot ','','','','','','','','', + '','','jie ','','Ning ','nai ','','','','','','','','','','yu ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','jie ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','an ','','','Xum ','','','', + 'ceng ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','Sao ','','','','','','','','','','','','','','', + '','','','','','','Lung ','','','','','','','','','', + ], + 'x21b':[ + '','','','','','','','','Xuong ','sai ','yu ','jiao ','','','','', + '','','','','','','','','20960.020,lao ','','','','','','yu ','', + '','','','','','','','','','','','wu ','','','','', + '','','','','','','','Tac ','','','','','Gang ','','','', + '','','de ','','','','','','','Ban ','','','','','','', + 'shuan ','','','','','Cut ','','','','','','','Mon ','','','', + '','','bai ','','','','','Chut ','','','','','Be ','','','', + '','Chut ','Trut ','kao ','','','','','luan ','','','Nhon ','','','','', + '','','','','','','Mon ','Chut ','','Mon ','','May ','Be ','Chut ','','', + '','','','Choai ','','','','','','nai ','','','','','','', + 'May ','','','Be ','Be ','Be ','Zao ','','','Be ','','Nhen ','Mon ','Nhon ','Mon ','', + '','','Tho ','','','Chuong ','Chuong ','','Nhon ','','','','','Nhon ','','', + 'Oat ','','','','','','','wu ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'ga ','','','','chao ','','','','','','','','','ga ','','', + ], + 'x21c':[ + '','','','','','hu ','','','','','','','','','','', + 'qiao ','','','','','','','','','','','','','','','', + '','','xie ','','','','','','','','Duk ','','','','','', + '','','','','','','','','','','','','','ai ','','pu ', + '','','','','','','Shu ','','','','','','','','','', + '','','','','','','','','','','','','zhao ','','','', + '','','','xu ','','','','','','Thuoc ','','','','','','', + '','zhu ','','','','','','die ','Gang ','','qu ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Ti ','','jue ','','','qiu ','','','','','', + '','','Ke ','jiang ','','','','','','','yun ','','Gwat6','','','', + 'qu ','','','','','','','','','','','','','','','', + 'Ngoe ','','kai ','Cuoi ','','','','','','','','','','','','', + '','chu ','','','','','','','ju ','','','','Cuoi ','Rot ','','', + '','','','','','Toi ','','','','','','','','','','', + '','','','Cuoi ','lu ','','','','','','','','','','jue ','', + ], + 'x21d':[ + '','','','','','','lu ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','ya ','','', + '','hu ,jie','','','','','','','','','','','','','','', + '','','','','','','','','','Ngut ','','','','','','', + '','','','','','','','','hu ','ang ','','fu ','','','','', + '','','','','','','','','','','','','mu ','','','', + '','','','','','','','','','','Cu ','','','','','', + 'Nui ','','yao ','ai ','','','','','','fan ','','ju ','','','','', + 'qie ','','','','','','','','','','','','','','','', + '','','kuang ','','','','ya ','','Ngan ','','kan ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','lu ', + '','','','','','','','','bie ','','','han ','','na ','','', + '','','','','wu ','gao ','','','','','','','','','','', + '','','','','','','','','','','','ya ','','','','', + ], + 'x21e':[ + '','','','','','','','','','','','','zhu ','','jie ','Voi ', + '','','','','xie ','','','ya ','','','','','','','','', + '','','','','','','ze ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','ya ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Nghi ','','','','','','','','','','','','','die ','','', + '','','','','','','','','','hu ','','','','','','', + '','','','','','','','','','','','','','','','', + '','die ','','','','','','','','','','','pen ','','','', + '','','','','','','Din ','','','','','','','','','', + '','','','','tu ','','','xia ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Voi ','','Seoi ','Von ','Chon ','','','','','','','','', + 'zhu ','','','','','','','','gun ','man ','','','zu ','','hu ','', + '','lei ','','','','','','','','','','','','','','', + ], + 'x21f':[ + '','','','','die ','','','','','','','','','','','', + '','','','dian ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','wei ','','','','','','','','','','','','','kuai ','', + '','','','','','yun ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','Non ','','','','', + '','Jie ','bang ','','','','','','','','','','','','','', + '','','','','','','','kuang ','','','','','','','','', + '','','','ceng ','','dang ','','','','','','','','','','', + '','','','','','','','','hai ','','','','Doc ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','nang ','','', + '','','','','','yu ','','','','','','','','','','yu ', + '','','','','','','','','','','Nao ','','xun ','','ju ','', + ], + 'x220':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','wan ','','','','','','','','', + '','','','','','Vang ','Sua ','Tron ','Sang ','','','','Lon ','','Sam ','', + '','To ','Lon ','','','han ','','','','','','','fu ','','','', + 'fu ','','','','','','','','','','','Trang ','','Va ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','jue ','','','','','', + '','','','','','','','','Phuon ','','','bu ','','','','', + 'fu ','','','','xuan ','','fu ','','','','','','','','Du ','', + 'xie ','Shi ','','','','','','','','','','','Vua ','','','', + '','','','','','','','','','','','','','','','', + 'Tranh ','yuan ','','','','','','','','mao ','qian ','','','','','', + 'wu ','','','','','','','Lei ','Long ','','Vua ','','','','','', + '','','','','','Ta ','','han ','qian ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','la ','','','','','','','','','','','', + ], + 'x221':[ + '','','','Phoi ','','','','','','','','','','he ,ge','bang ','', + 'meng ','','','wu ','dai ','','','','','','','','han ','Bau ','','', + '','','','','','','','cu ','','','','','','','','Man ', + '','','','','','xiang ','Hua ','','','','','','','','','', + '','','','','','','Manh ','','','mao ','','ceng ','','','','Lian ', + '','','dan ','','','','Lian ','','','','','','','dian ','','', + '','','','','gai ','Ju ','','','','','zu ','','Chan ','','','', + '','','','','','','','','','yao ','','','nei ','','','', + '','','neng ','','','','','','','','','','','','','', + '','','','','','','','','','','','','ge ','','Jian ','', + 'Lai ','Nin ','','','','Nam ','jian ','May ','May ','','May ','','','','','', + 'hu ','','','','','','','','','','chen ','','','','','', + '','','','','','','','Guan ','yan ','Doi ','','','','','','', + '','','','','','','','sha ','','','','','','','han ','', + '','Khuya ','','','','','ren ','','','','fan ','','','','','', + '','','','','bu ','na ','','','','','','','','','','', + ], + 'x222':[ + '','','','','','','','','Nap ','','','','','','','', + '','','','','','bai ','','','Roku ','','','kun ','','qiu ','','', + 'cu ,la','','','','','','','','','','','','','','','', + '','','pu ','','','','','','','','','jie ','','zhan ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','du ,tu','','','', + '','','hu ','','jia ','','','','la ','','','','','','','', + '','','','','','','','','','','','','','Kho ','U ','ma ', + '','','','','','','','','','','','','','Zu ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','yu ','','lu ','','','','','','', + '','fen ','','','','','','','','','','','','','','', + '','','','','','yu ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','xian ','', + '','','','','','','','','','wu ','','','','','','', + ], + 'x223':[ + '','','','','qu ','','','','','','Rong ','','Rong ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','fu ','','yu ','','','','', + '','','','','','','','','','','','','','','gao ','juan ', + '','','','','','quan ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','die ','','','','','','dai ','','su ','', + '','','','','jie ','','qu ','','han ','','','','','','','', + '','jie ','','','','juan ','','','','','dan ','','','','','', + '','','','','','hu ','','','','jue ','','yu ','','','','', + '','','','','','','','','','','','','','fu ','','', + '','Ban ','','','','','','','','','','','','','','', + '','','Cong ','Cong ','xun ','','','','','','','','','liu ','','', + '','','','Beng ','','','','jue ','','','','','','','','Von ', + ], + 'x224':[ + '','','','','yuan ','','','','','','','','','','Khom ','', + '','','','','','','','','','','','','','','cheng ','', + '','','','','','','','King ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','jiu ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','hu ','','','','','','', + '','','','','','','','','','','','','','','Bay ','', + '','','fu ','','chu ','','','','','','','','','','lan ','', + '','','','','','','','','','','','','','','','', + 'yu ','','','','','','','','','','','','','','jiao ','', + '','','','','','','','','','','','ang ','','','','', + '','','','','sa ','','','','','','','','ge ','','','', + '','','kua ','','','','','','','','','','xie ','','','', + '','','wu ,hu','','','xiu ','','','','','','','','','','', + ], + 'x225':[ + '','','yan ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','yu ','','','yu ','','','','','','','yu ','','','', + '','','liu ','','20832.030,yu ','','','','','','','','','','','', + '','','','','','shuai ','','','','','','yuan ','','','','', + '','shuai ','','','','','','','','','','','','','','ao ', + '','','','','','','','','','','jiao ','','sa ','xian ','zha ','dian ', + '','','','','','','','','San ','','','shan ','','','','', + 'Suot ','','','','','','','','tiao ','','','','','','','su ', + '','','','','','Sau ','Sau ','','','','','','','xian ','','', + '','yu ','','','','','jue ','nang ','','','','','','','','', + '','','','','','ru ','','','','','','','','','','', + '','','','','xia ','','','','','Nuoi ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','wu ','','','','','','','chang ','','Lo ','','','', + ], + 'x226':[ + '','','','','qiu ','Maau ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Rung ','Rap ','', + '','','','','','','','','Jiang ','','','','','','','', + '','wu ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Hung ','','','','','','','','','Nhon ','E ','Tim ','kan ','', + '','Lung6','','','','','','','','','','','','','','', + 'xian ','','','','','','ju ','','','','','miao ','','','','', + '','su ','','','','','Ti ','','','','','','','','','', + '','','','','','','','','','','hu ','','','','','', + '','','','','','','','','','Khuay ','','zhu ','Ngop ','','','', + '','','','qiu ','ya ','','','','','','','','','','bie ','', + '','','','','','','xiang ','','','','ru ','wang ','','','','ya ', + '','','','','','','','','yu ','','','','','','','', + '','','','','Mang ','Zang ','','','','','','','','','','', + ], + 'x227':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','Vung ','','','','','','','','', + '','','','','','','','','','','','Xing ','Duo ','','','', + '','','','','','','sao ','','Nao ','','','','','','','jia ', + 'tu ','','du ','','','','','','','','','','mao ','yao ','','', + '','','','','','','','','','Vui ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','wu ','Fit ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'hai ','','','','','','','','','','','','','','','gao ', + '','','','','','','fu ','','','','','','','liu ','','', + '','','','','','Fit ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Chua ','','Nan ','','','Nep ','','','Chac ','Cham ','','','','','','', + '','','','yang ','','','','','','','','','','','','', + 'ai ','teng ','','','','','','','','Nhuoc ','','','','','','', + ], + 'x228':[ + '','','','Geng6','Sung ','Thung ','','','','','','','','','','', + 'Ngo ','','','','','','','','','','','','','','','', + '','sao ','','','','Gan ','Hon ','','','Mo ','','shu ','','','','Lang ', + '','','fu ','Bie ','','Tang ','','xiang ','','','','','','dang ','','', + '','','dang ','','','','','','','','','','','ge ','yu ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'zhao ','','','','','','','','','','','','','','','', + '','','Ghet ','','Ngung ','','','','','','','','chang ','zhe ','','', + '','','su ','','','','','','','','kai ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Khan ','','', + 'Ngay ','','','','Quo ','','','','','','','','','','','ai ', + '','','','','','','','','','','','','','','','', + 'liu ','','','','','','','Khuay ','','','','','','','','', + '','','','','','','','','','Hung ','','','','','','chu ', + ], + 'x229':[ + '','sao ','','','','','','','','','','','','','','', + 'liu ','','','','','','','','meng ','','zhan ','','','Cham ','','', + '','','','','zhuang ','','','','','','','','','','','', + '','','','','','','','','','Goe ','','','','','','', + '','','teng ','zhu ','','','Lung ','','Lo ','','','','','','','', + '','','','','','','Trai ','','xie ','','jiao ','','','','Chong ','', + 'Sung ','','','','','','','','','','','','','','','', + '','','','','','','','Ngoi ','','','','','','','','', + '','','Laan ','','','','','','','','','','qu ','','qiu ','Zai ', + '','','','','','','','','','','hua ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','shu ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','han ','ge ','','','','','','','','', + '','','Ta ','','','','','','','','','','','','','', + ], + 'x22a':[ + '','','','','','','','','','','','','','','','jue ', + '','','','','','','','zei ','','','','','jie ','','','', + '','','','','','hu ','hu ','','','','','chu ','','','','', + '','','','','','','','','','','','','','','','', + '','ju ','','','zhu ','','','','','','Quanh ','','','','','', + '','','','ge ','','','','','','','','','Ho ','','','', + '','','shan ','','Muon ','','Zit ','Hat ','','','','','','Thuon ','Dat ','jue ', + '','','','','','','','','hai ','xia ','','','','','Chop ','', + '','','','cu ','','','','','','','','','','','','', + '','','','','','','','Vuc ','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Ngat ','Vat ','Nang ','','','','','Muc ','','','','','','','zhang ','', + '','','','Keo ','','That ','Vun ','','','','','','Tha ','','','Kam ', + 'jie ','','','','','Wing ','Trot ','','So ','','','','Trum ','Rung ','Quay ','', + '','','','Bac ','','','Haku ','','Ngung ','','','Lat ','','nu ','','', + 'zhe ','','','','','zu ','','','','','','nie ','','','','', + ], + 'x22b':[ + '','','','','Bung ','','','','','','','','','','','', + 'Muc ','','','','','','','Chui ','','','','','','','','', + '','','','Tay ','Khuong ','Giang ','','','','','','','','','Vot ','', + '','Khep ','','','','','','nan ','','','','','dun ','','','Kaai ', + '','','','Dau ','','','Chou ','','','','','','','','','', + '','Thuoc ','','','','','','','','','','','Xac ','','','', + '','','','','','bian ','','','','','','','','','','Quet ', + '','','','Giau ','Khuay ','','','Vom ','','Lan ','Dui ','Xoi ','','','','', + '','','','','','','','','','','ya ','','','','','bang ', + '','Luk ','','','','','','','','','','','','','sao ','', + '','','','','','','','','','Co ','Ron ','','Chut ','Co ','','', + '','','','','','','','','','','','','','','','Quay ', + '','','','','','lu ,jue','','','','xie ','Dik ','','zhai ','','Ngaau ','', + 'Co ','','','Va ','Quat ','Ngoi ','Khep ','Quay ','Huo ','','','Sap ','Buoc ','Ven ','','', + 'Va ','Roc ','Sua ','','','','Lay ','','','','','','','','yu ','', + '','Sau ','wan ','xue ','','','','','','ge ','','','','','mao ','', + ], + 'x22c':[ + '','','','','','','fu ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Wo ','','','','','Gap ','Zung ','pan ', + '','','','','jie ','','','','jia ','','','','jia ','','Boi ','', + 'Gieo ','Waa ','','','','Dap6','','','','Cai ','Phung ','Xoi ','','Nhot ','','Sin ', + '','','Saak ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Kek ','','','','','','','', + '','','','','Bung ','','','','','','','','','Run ','','', + '','Laa ','','Rung ','Cau ','','','Gay ','','Kap ','Mai ','Mo ','','','','', + '','Cau ','Long ','','','Cou ','','Sou ','Lou ','','','','die ','','','zhu ', + '','','Bat ','','','','Ngou ','','zu ','','','','','','','', + '','lang ','','','','','','','','','','','Saai ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x22d':[ + '','','','','','','','Chap ','Daat ','','Chop ','Chong ','','','','', + 'Day ','','Paang ','','','Ning ','','','Xay ','','','','Xau ','','Nhung ','', + '','','fen ','','','','','','','','','','ban ','','','', + '','lei ','xie ,jie','','','','','','','','','','','','','', + '','','','','Cou ','','','yang ','','','','','Deoi ','','','', + '','','','Paang ','','','','','','','','','','','','', + '','','','','','zao ','','Gaan ','','Doi ','','','Don ','','','', + '','Khoi ','','Sum ','Quay ','','Don ','Cat ','Xap ','','','','Vot ','Ro ','','', + '','','','','','Sip ','','','','','','','','Saap ','','', + '','Niao ','guai ','','','','','','','','','','Ngung ','','','Cui ', + 'Saau ','','','Die ','Loe ','','','','','','','','','','','Maan ', + '','','','','','','bang ','','Bum ','','Dom ','Bung ','Ngoi ','','','Don ', + '','Nem ','Xan ','','','Tro ','Chen ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','Ban ','','','','','','','','','','Deoi ','', + '','','Hang ','','','Vo ','liu ','','','','du ','','','','','jie ', + ], + 'x22e':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','Lan ','','','', + '','','','Niao ','','cuan ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Choc ','Gai ','Mac ','Rung ','','Xe ','','','','','yu ', + '','Zaang6','','','','','','','','lan ','','','','','','', + '','','','Keo ','Xau ','','','','Tum ','Suong ','','','','','','', + '','','','xiao ','','','','','','','','','','Giam ','Que ','', + '','','','','','','','yao ','','ta ','','Naan ','','','','', + '','','Bung ','','Bau ','','','','','','','','','Uon ','','chan ', + '','','','','','','','','','','','','','','','', + '','','','Maan ','yu ','','','','','Chia ','Chia ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','cheng ','','','','','','','','','hai ','','','', + '','','','','','','','','sa ','','','','','','jie ,fu','', + '','','','','','','','','','','','','','','','', + ], + 'x22f':[ + '','','','','','','','','','','','','bao ','','','', + '','','','','','','','','','','','','','','','', + '','','','qia ','','','','','','','','jiao ','','','','', + '','','','','','','','','','','xue ','','','','','', + '','','','','','','','da ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','mao ','','','','','','','','','','','jiu ','','', + '','','','','Duk ','','','','','','','','Va ','','','', + '','wei ','','','yu ','du ','','','','','cheng ','','','','','', + '','','kuai ','','','','','','','','','','','','','', + '','','','','','','','','','','','','lu ','','','', + '','','','','','','','','','','','','','','','wen ', + '','','meng ','','','','','','','','','','','','','', + '','','','','','','','','','','','','man ','','','', + '','xie ','luan ','','','','cheng ','cheng ','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x230':[ + 'lei ','','','','qun ','','','','','','','','','chen ','','cheng ', + '','','Chong ','','','','','','','','','','','','','Va ', + '','','','fu ','','','','san ','','','','','','','','sa ', + '','','','','','','','','','','','','','','fu ','', + '','','','','','','','','','','','','','dao ','','', + '','','','','Lon ','','gan ','tan ','','','','','man ','','','', + '','','','','','','','','','','','','','','','', + '','','','','qia ','','','','','','','','','','','', + '','','','','','','','','','','yun ','','','','','', + '','','','','','','','','','','','','','xiang ','','', + '','','','','','','','','','','','','xiao ','','','', + '','','','dang ','','zhuan ','','','','','','','','','','', + '','','','','','','','','','dang ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','yan ','', + ], + 'x231':[ + '','','','','','','','','','','','','','','fu ','', + '','','','','','','','','','Huang ','','','','yan ','','hu ', + '','','','','','','','','','','','','','','','', + '','','','','liang ','','','','','','wei ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Khuya ','Khuya ','','','','','','', + '','jue ','','','','','','','','','','','','','','', + 'xiang ','','','','','Tam ','Luc ','','','','','','','','','', + '','','','','','','','','','','','','','','','Phoi ', + 'Trua ','','xu ','','','xian ','','','','gan ','','','','','','', + '','','','','','','','hao ','','','','','','','Chang ','', + 'Giay ','','','','','fu ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','Sao ', + '','','Bie ','','','','','','dai ','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x232':[ + '','','','','','','','','','','mu ','','','die ','','', + '','','','Phoi ','','Mai ','','Ngay ','','','','Quat ','Ngay ','','Hong ','', + 'bian ','','Tia ','','','tu ','','','','','','','','','','', + 'Nau ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Ui ','Trua ','', + '','','','','','sang ','','ang ','nai ','','','','','','Gou ','', + '','','','','','','','','','ya ','','','','','','', + '','','','','','Rua ','','','','','','','','','','', + '','','','mao ','','','','','','','','Se ','','Mo ','Chop ','', + '','','','','meng ','','','','','','','','','sang ','xu ','kan ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Bay ','', + 'Sao ','Toi ','','','','','','','','yu ','dan ','','','','','pu ', + '','','','','','','','','','','','','','','ai ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Som ','','', + ], + 'x233':[ + '','Trua ','Trua ','','','','Trua ','','','Khuya ','','Som ','Rua ','','','de ', + '','','','','','','','','','','','','','Nang ','','', + 'chun ','','','','','','','','xun ','','','','','','','', + '','','','','','','','','','','Xeo ','','','','','', + 'Nguc ','','','','','','','ju ','','','','Cui ','','Oam ','','cha ', + '','','','','','','','','','','','yu ','','','','', + '','','','','','','kuang ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','Luo ','','','','','','','','','', + '','','','','nian ','','','','','','hu ','','','','Trang ','', + '','','','','','','','','','','','','','','','', + '','','','','Dun ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','shu ','','','','','','','','pai ', + '','','','','','','','','','','','','','','','', + '','','','','Jan ','','','he ','','','','','','','Zai ','Then ', + ], + 'x234':[ + '','','','','','Nhum ','Thot ','','','','','','','','','', + '','','','','','','','','','','','','','Xop ','','', + '','','','','','','','','','','','','','','','', + '','','Queo ','','','','','','','','han ','','','','','', + '','Cung ','hu ','','','','','','','','','','','','Roi ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','Gian ','','','Sim ','','','','Nen ','','','','fu ', + '','','dian ','','','','qiao ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Mang ','','','','','','','','','','','','', + '','Xoai ','Sao ','Cong ','','','','han ','kuang ','','','','','','','', + '','','','','','','','','','sha ,jie','','','Gou ','','','', + '','','shan ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','Lau ', + ], + 'x235':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Cui ','Bap ', + '','Pha ','Xoi ','Ngoc ','','Chanh ','Nhai ','','Kang ','','','','','','','', + '','','','','','','','','','','mao ','','Gon ','','','', + '','','','yu ','','pao ','','','','','','','','','','', + '','','','','','','','','Hay ','','','','','','','', + '','','','','','','','','','','','','Noc ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','yun ','','','','','','','','','', + '','','','','','Peng ','Chay ','Chay ','','','Ca ','','','','','', + 'Suot ','Trac ','','ju ','','','','','','','qu ','','jue ','','ang ','', + '','','','','','','','','','ru ','','','xun ','','','', + '','','','','','','','','','','','','','','','', + 'reng ','','','Chua ','','','','','','','','','','','','', + '','','','','','','','','','','Cha ','','','','','', + '','','','','','','ta ','','','yang ','','','','','Son ','', + ], + 'x236':[ + '','Ca ','','Cay ','Thot ','','','','Son ','Cum ','','','','','','', + '','','','','','','','Nik ','','bang ','Seot ','','','','','', + '','','','chun ','','','Yi ','','','','','','','','','', + '','','','','','','','','','','','','','Nau ','Vai ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','Rac ','','','','','','', + '','','juan ','','','','','','','','Mo ','Sop ','','','Chay ','Rui ', + '','','','','jie ','zhe ','hu ','','Sot ','Con ','Mam ','','','','','', + '','','','jie ','','','','pao ','','','','ye ','','','lei ','', + 'ru ','','','juan ','','Jaap ','','','','','','','','','','', + '','','zhuan ','','','','jiang ','hao ','','','dun ','','','','','', + '','','','','','','','','','','Hong ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','Xanh ', + '','Gu ','','Khay ','','Be ','','','','Then ','Tu ','hu ','','','','', + '','Dom ','','','','','','','ze ','','','die ','','zha ','','', + ], + 'x237':[ + '','','sa ','','','','','','','','','Mo ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','juan ','','','','ai ','','','', + 'Lim ','Son ','','','','','','','','','wen ','','','','Chua ','', + '','','hun ','','','ai ','','','','Duoi ','','ta ','','','','gao ', + '','yu ,yu','','','','','','hu ','','','','','10389.190,bian ','su ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Khu ','Cuoi ','','','dun ','','','','','','','Tram ','', + '','meng ','','lu ','tan ','','','liu ','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'lian ','','','','','','','','','','','','','','','', + '','','','Mong ','','','','xiao ','','huai ','','','','','','', + '','liu ','wu ','','','','','','','','','','','','','', + '','','','','','','','','','Dui ','','','Ran ','','','', + 'yu ','Kyo ','','','','','','','mei ','','lian ','','','lao ','','', + ], + 'x238':[ + '','','','','','','','','','','','','','','','', + '','','Tham ','Pheo ','','Chua ','Chua ','Que ','Gau ','','liu ','','zhao ','','','', + '','','','','','','','','','Tram ','','','','','','', + '','Tram ','','','','','','','','','','','','Ha ','','', + '','','','','','','','','','yu ','','','','','cen ','', + '','','','Tram ','','yan ','','','','','','','','Vui ','','die ', + '','','','','Nen ','','','lei ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','xu ','','','','','', + '','','yu ','','','','qian ','','','','','','','','','', + '','','','','','dian ','','','','','','','','','','', + 'zu ','','','','','','chu ','','','','','','','','','', + '','','','','','','','','dian ','','','','','','yu ','', + '','','','','','','','','','','an ','','','','hun ','', + '','','','dian ','','','','','','','','','','','sha ','', + '','','xie ','','da ','','','','','','sha ','','','','','', + ], + 'x239':[ + '','zhu ','','','','','','','ze ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','shu ', + '','','','','','','','','','','','','','','','', + '','','ta ','wan ','','','','','','','wang ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','guan ','','','','','','','','','','', + '','','','tu ','','','','ta ','','chu ','','','zhu ','','da ','', + '','','','','','','','','','','','','','Ngay ','','', + '','','','','','','','','','','','','','','','', + 'chu ','chu ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Laai ','du ','','','','','die ','','','','','','','', + '','','','','','','','','','bai ','','dian ','','qiu ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','nao ','','', + ], + 'x23a':[ + 'luan ','','die ','','qia ','','','mao ','','','','','','','','', + '','','','wu ','tao ','','','','','','','zu ','ma ','','','', + '','','','jiang ','xu ','','','Giuoc ','','','','','','Quan ','','', + '','','du ','xiang ','','','','','','','','','','','','hun ', + '','','','','','','','','','','','','','','','lu ', + '','','','','guan ','','','','','','er ','','','','','', + '','','liao ','','','','Ngoeo ','shan ','','','','','','zhai ','','ye ', + 'diao ','','','','jiang ','','','','Toi ','huai ','yu ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Ji ','','','','','','','','','','dian ','','','bian ','','', + '','','','','','','','','gu ','','','','','','','', + '','','','','','','','','hu ','','','','','','su ','', + '','','','','','','','','','','','','dao ','','','', + '','','','','','','','','','','','','','','','', + '','','','','xie ','','','Van ','','dai ','','','','','','', + ], + 'x23b':[ + '','','guan ','','','','pei ','','','','','','','','jue ','juan ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','ba ','ba ','','','','','','wu ','','', + 'bao ','','','Su ','','','','','','','','','','','','', + '','','','','','','','','fu ','','','','','ge ','','', + 'ru ','','','','','','','','','','','','','','','Ria ', + 'Mao ','','','qiu ,qu','','','','','','','','Mau ','','','','', + '','','','','','','','Ngu ','','','de ','','jie ','jie ','','', + '','','','','','','','','','','','','','','','', + 'san ','','chun ','','','','nai ','','','','','','','','','', + 'de ','','','','','','','','','','','','','','','', + 'mao ','','','','','','','','','','','ru ','','','wu ','', + '','','','','','','','','','','ta ','','','','','', + '','','','','','','','','','men ','','','','','','', + '','pei ','','','','','','','qu ','','','','su ','','','', + ], + 'x23c':[ + '','','','','','','','','','','','qu ','','','','', + '','','','','','sao ','','','kun ','','','','','','jie ','', + 'qu ','qu ','','','','meng ','','','','','','','du ','','','', + '','','','','','','','','','','','qu ','','','','', + '','','kun ','','','','Ho ','','','','','','','dan ','','', + '','','','xiao ,hao','','','','','','','','','','','','', + '','','','','','','','','','','','','Hoi ','','','', + 'Ram ','','','liu ','','','Vuc ','','','','','','','','','Nhop ', + '','','','','','','','','','','','','','Ngut ','','', + '','','','','','','','','','','','','','','','', + 'Ngot ','','','','','','','','','','','','','','','', + '','','he ','','','','','Nap6','','','','','','','guai ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','fan ','','','jie ', + '','','','','zhan ','','','','Deoi ','','','','','piao ','','', + '','','','','','','','','','','','','Doe ','','','', + ], + 'x23d':[ + '','','','','','','','','','','','','','','','', + '','','','jian ','','','','','','','Hup ','Nhung ','','','','', + '','','zao ','zhuang ','','','','','','','','','','','','', + '','','','','','','','','','','','','mao ','tan ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Bung ','', + '','','','','Ngam ','','','','zhu ','','','','gan ','','','', + '','','','','','','','','','','','','','zhuang ','','', + 'pao ','','','','','','','','su ','','','','','ju ','','', + '','can ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Loi ','', + 'Nhom ','','','','','','','','','','','','','','','', + ], + 'x23e':[ + '','','','xu ','','','','bian ','','','','','','','huai ','', + '','','','','','','','','','','she ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','fu ','','','','', + '','','','','','Lut ','','Tran ','','','','','','qiao ,xiao','','Cong ', + '','','','','','qian ','','','','xie ','','','hu ','','','xun ', + '','','','','','na ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','tao ','', + 'qiao ','','','','','','','','','','','','','','','', + 'Nuot ','','','Bui ','','','','Xoi ','','Duoi ','','','','dang ,xiang','','', + '','','','','','Ma ','','','','','shu ','','fu ','','','', + 'xie ','lang ','','','','','','','','zhe ','','','can ','','','', + '','','','','','','','','','','','','','','','', + ], + 'x23f':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','lu ', + '','','','','','','ze ','shuai ','','','Bot ','','','','','Vui ', + 'Lung ','Ngau ','Doi ','Xop ','','','','Lot ','','','','','Tran ','Lang ','','', + 'Ngau ','','','','','','Veo ','','','ru ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','an ','jian ','','53066.030,teng ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','Doi ','','','','Khoi ','','','Xoi ','Bui ','', + '','','','Ngau ','','','fu ','','su ','','lian ','','he ','','','', + 'ze ','','','','','','','','','','','','','','','', + '','','','xiao ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x240':[ + '','','','','','','','','','han ','','','','','','', + '','','','Loc ','','','Ngoi ','Rua ','Vung ','','','','Tanh ','yu ','','', + '','','','','','','la ','','','jian ','','','','','','', + '','','bian ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Dao ','Khoi ','','','','Trong ','Bot ','','Chua ','','','','', + 'Dao ','dan ','jie ','bai ','','','xian ','','','','','','','','','', + '','cai ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','zhuan ','','','','','Rua ','Dan ','Phun ','Loi ','Toe ','','', + '','','','','','','','','','','lan ','','yao ','','','xuan ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','Leo ','','Muong ','', + '','','','','','','','Thuot ','lan ','','','','','','','', + '','','','','','','Deng ','','','','xun ','','','','','', + ], + 'x241':[ + '','','','','','','','','','','','','','','','', + '','fan ','','','','','','','','','','','','','','', + '','','','','','ta ','','pan ','','','','','','','','Trong ', + 'Nhan ','','Can ','','','','','','','','','','','','','', + '','','','','','','','','','','yan ','','','','man ','', + '','','can ','','','','','','','','','','Veo ','','','', + '','','','men ','','','','','','','','','','','','', + '','','shuan ','','','','','','','','','','','','','', + '','cheng ','','','','','','','','','','','','Chi ','','', + '','','','','','','','','','','','','gua ','','xu ','', + '','','','Saap6','','','','','','','','','','','','', + '','','','','','','','','Tom ','','','','','','','', + '','','','','','','','','','','','','Kho ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','Say ','Phoi ','Tat ','','','','','Bep ','', + '','','Nhum ','','','','','','','','','','','','Ying ','', + ], + 'x242':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Lui ','', + 'Sot ','Ngut ','','','','','','he ','','','Cho ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','lao ','shao ','', + '','','','Tro ','','Tro ','Se ','Heo ','Ngun ','','','Toa ','Rang ','','','', + '','','','','','','','','fu ','','','kai ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Luk6','','','','','','','','','','','','','', + 'Roi ','','','Tro ','Nhem ','','','','','Rom ','','Phoi ','Phoi ','Lom ','','', + 'Ben ','','','','','','la ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'zhu ','','','','','','Ranh ','Nau ','Khet ','Kho ','','Phoi ','Kho ','Choi ','Um ','', + ], + 'x243':[ + '','','su ','','','','','','','','','','','Hok ','','', + 'han ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','gan ','','','','','','', + '','','','Hay ','','','Ngot ','Nau ','','Ngun ','','','','','','', + '','Chong ','','shu ','','Jau ','','','','','','','zao ','','','', + 'Jit6','','','','Zhang ','','','','','','','','','','','', + '','','','','','','Loa ','','','','','','','','','', + '','','','','','','','','','','','','','Quac ','','', + '','','Phap ','','','Tat ','','','','','','Ram ','','','','', + '','','','','','','','zhu ','','','','','','','','', + '','Zuan ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Nhoi ','','Ho ','Thui ','Khet ','Thap ','Se ','','Rao ','Buot ','','','','', + '','chu ','Zhou ','','','','','','','','','','','','','', + ], + 'x244':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','Ham ','Nau ','','Soi ','','', + 'Luoc ','','','','','','','','','kai ','','','','','','', + '','','cuan ','','','','','','','','','','','','','', + '','','','xian ','','','','','Chang ','','','','','Hung ','','', + '','','','','','Xun ','','','','','','','','','','', + '','','','','','','','','','','','Bung ','Loe ','','','Sem ', + '','','','','','','','ye ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','Nung ','Nau ','','yao ','','Nhui ', + '','','Lom ','','','','Sem ','','','','','','','','','', + '','','','','Thap ','','','','','','','ta ','','','','', + '','','','','','','Ram ','','','','','','','','','', + '','','','Lo ','','','','','','','','','','','','', + '','','','','','','','','','Ben ','','','','','','', + '','','','','','','','','','','Vau ','','','','dao ','', + ], + 'x245':[ + '','','','','','','','','','','','ju ','','','','', + '','','','','','','','','','','shang ','Su ','','','','', + '','','','bao ','','','','','','','','','','','','Vuot ', + '','','','','','','','Danh ','','','','','','','','', + '','','','','','','','','','','shen ','','','','','', + '','','','','Cha ','','','','','','','','','','zhu ','', + '','','','','','','','','','','','','','Jiang ','','Jiang ', + '','','','','','','','diao ','','','','','','','','', + '','','','','','','zhan ','','','','','','','','','', + '','','die ','ze ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','he ','','','','ju ','','','','Lop ','','','','xiang ','','', + '','cu ','','','','','Mui ','','Sip ','','','','','','','pei ', + '','','','cheng ','','','','','','','','lian ','','','','', + '','','','','','','','','die ','','shu ','','','','','', + '','','Tam ','','','pu ','','','','Phuon ','','chan ','','','','', + ], + 'x246':[ + 'dao ','','','','','','','','','','','Nga ','','','','', + '','','','Nanh ','hu ','','','','','','','chun ','','','','', + 'tian ','','','chen ','','','','','','','','','','','','', + '','','zhuang ','','','hu ','','shu ','','','','','','','','', + '','','','','','bai ','','','','','','','','','','qu ', + '','','xie ','','zhao ','','','','','','','tu ','','','','', + '','','','','','','','','','','','','','','Ngau ','', + '','','','','Caau ','','','','','','','','','','','', + '','','','','','mu ','','Nghe ','','','die ','','','','yu ','', + '','','','','','','','','','','du ','','','','','', + '','du ','','','mei ','','Co ','Sao ','','','','','','','','xiu ', + '','','','','','bu ','','','','','','','','','','', + '','','','','','','','Chan ','','','','','','','','', + '','','','','','','','','','','','','','su ','Nghe ','', + 'Trau ','','ceng ','ta ','','','jue ','xun ','','','','','','qun ','','', + '','','','','','','','','','','','','','','','', + ], + 'x247':[ + '','','','','huai ','','','zhan ','','','','','','','','', + '','','','','ju ','ba ','lei ','','','','','','','','','', + '','','','','zhe ','','','','','','','','San ','Tu ','','Kap6', + '','','','','','21335.010,yan ','','hu ','','yu ','','','','','','', + '','','mu ','','','','','','','','','','','','','', + 'hao ','Muop ','na ','','','','','','hu ','','','','','','Chuot ','', + '','','','','','','','bao ','','','','','','','lu ','', + '','','','','','','','','','Chu ','','','','','','', + '','','','','','','','','','shu ','','','','','','', + '','','','San ','Thac ','Tay ','','','','','','zang ','','','yu ','', + 'cha ','xie ','','','','','Moi ','Khon ','','','','','','','','', + 'qiu ','','hu ','zai ','jue ','','han ','','','','','Hum ','','','','an ', + 'zao ','','','sha ','','xian ','','','','an ','','','','zhe ','jue ','', + '','','','','','','','','lu ','','','','','xia ','xiao ','', + '','','dun ','','','','','','','','tu ','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x248':[ + '','','','','Ga ','Voi ','','ge ','','','','Trau ','','','','', + 'ta ','Lau ','','','','','','','','','su ','','','','','ta ', + '','','','','','','','','','','fu ','','','','','', + 'Gau ','','','','','','','','','','','','','cu ','','', + '','','','su ','','','','','','','','','','','','', + '','','','','','','','','','','','Nanh ','','','','huan ', + '','','','','','','','','','','','','','','Ran ','', + '','','','','','','xu ','','','','','','','','','', + '','huan ','su ','','','','','Vuot ','San ','','lu ','','','','','', + '','','','ju ,qu','Nhen ','Dou ','','','su ','','','','','','','ze ', + '','','','','','','','','','','Lie ','','','','','', + '','','','','','ai ','','','','','xie ','','','Nhat ','','', + '','','','','Beo ','','','','','','','','xiao ','','','', + '','xie ','','','','','','','','','','','','','','', + '','Doc ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x249':[ + '','','','','','','','','','','da ','','','','','', + 'su ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','wai ','','','','', + 'Vua ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','su ','','','liu ','','','','','','','','', + '','','','','','','','','','','','','','Xa ','','', + 'mao ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','Cung ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','yu ','Cong ','','','','','', + '','','','jian ','','','','','','wan ','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x24a':[ + '','','','','','','','','','','','','','lu ','qu ','', + '','','','','','','hu ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','zhuan ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','hao ','xiang ','','','hao ','','', + '','dian ,tian','ge ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','chan ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','qia ','jiao ','','','','','','','','Dua ', + ], + 'x24b':[ + 'Dua ','','','','','','','','Hau ','','','','','','','', + '','','','','','','','','','','','Lu ','','yan ','','', + '','','','','','','wa ','zu ','fan ','','','','','','','', + '','xu ','','','','','','na ','Sanh ','','','','','','','', + '','','','','','','','','diao ','','','','','fan ','','', + '','wu ','','','','','','','','','','','','','','fu ', + 'na ','','','','','','','','','','','','','','','', + '','hu ','','','su ','','','','','','','','','xu ','','', + '','','','Ang ','','','','','','','','','','','lei ','heng ', + '','Be ','','','','','','Lo ','','','lei ','','shan ','','','', + 'Muong ','','','','','','','lu ','Lung ','','jun ','','','Chan ','','xie ', + '','zhe ','','','','','','liu ','lei ','','','','dai ','','Ngot ','Ngot ', + '','','','','','','Ngon ','','','','','','','','','', + '','Lam ','','','','','','','','','','','','','','', + '','','','','','','','','Song ','Song ','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x24c':[ + '','','','','','','','','','','','','','','','', + '','pu ','','','','','','','','','','','','','','hang ', + '','','','','','','zha ','','','','','','chao ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','na ','na ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','diao ','','','','','','', + '','','','','','','','xie ','','','','','','fu ','','', + '','','Duoi ','','','','','','','','','','Ruong ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','juan ','','','','','','','', + 'mao ','','','','','','','','','','','','','','','', + '','','','','','cha ','Trai ','Trai ','','han ','','','','','','', + '','','','','','yu ','','','','','','','','','','', + '','','Trong ','','','','','','Roc ','','','','','','','zhu ', + 'Ve ','Ruong ','','','lei ','','','','','','','','','Ruong ','','', + ], + 'x24d':[ + '','','','','','','','','','','','','','die ','','', + '','','','','','','','','','','','','','','','', + '','','','','','Ngat ','','','','','','','','Bot ','','huan ', + '','du ','','','','','','','','','','','','','','', + '','','','','','','','','','','du ','','','','','', + 'wu ','','wen ','','','','','','','','To ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','Si ','','','qia ','','','','hai ','','', + '','','','','','','','','Tay ','','','','','','Chau ','', + '','Nhan ','Ben ','','','tun ','fu ','','','','','','zhuang ','','','', + '','','','','','','','','','','','','','','du ','', + '','chuan ','','','','','','','Naa ','Guoc ','','Nghen ','Mang ','Mut ','','', + '','','fei ','jian ','','','','Wak6','','','','','','','','', + '','jiu ','','','lun ','','','','dao ','de ','','','','','','la ', + '','','ju ','','','','','','','','Mang ','Cek ','','','','Loet ', + '','','','Nhom ','','','Buou ','','','wai ','','','','','','', + ], + 'x24e':[ + '','','','','','','','','','','dai ','','','','','', + '','fu ','Ngung ','','','','','fu ','','','','','','','','', + '','','','','','','','Hoen ','','','','yun ','','','su ','', + '','','','','','bu ','','qun ','','','','Naa ','','','','', + '','','','','','','','','','','','jue ','','','','', + 'Lit ','','','','','','Hen ','','Nhoc ','Choc ','','chen ','','','','', + '','','','hu ','teng ','','','','lian ','','','','','','','', + '','','','','','','','','','','','','Buou ','Not ','','Ngo ', + '','','','','','','','bian ','','','','','','','','', + '','','','Bie ','','','','','','','','','','','','', + '','','','','','','','Zang ','','','shan ','','','Buot ','Gua ','Mun ', + 'Khom ','','','','Buou ','','','','','','','juan ','lu ','','ao ','', + '','','','','','','','','','','','','','','Cum ','', + 'Hom ','','Toi ','','','','','','','','','','','','','', + '','','ai ','','','','','','','','','Nhoi ','','','','', + '','lu ','','','','','bian ','','','','','','','','','', + ], + 'x24f':[ + '','meng ','','','','','','','','','','chan ','','','','', + 'guan ,huan','','','','','','','jue ','lei ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','ju ','','','','','Dang ','','','','','','','', + '','','','','','huan ','','','','','','','','','','', + '','','','er ','','huan ','','Nguoi ','','','','','','','','', + '','','','chang ','','','','','','','','','','','','', + '','zu ','','','','Phau ','','','Trang ','bai ','lu ','','','','','nian ', + '','','','','zhu ','hu ','','','','','','','','','','', + '','','','Tram ','Vang ','','','','','','','miao ','','','','Ho ', + '','','','','','','','','','','','yao ','','','','', + 'Nguoi ','','','','','bie ','','','','','','','','','','', + '','','Saai ','','cun ','','','','','','','','','','Pi ','nan ', + '','','','','','','','wa ','','','','','','','','xun ', + '','','','cheng ','','','Da ','han ','xiao ','','Zaap ','','','','','', + 'Trong ','','','','lu ','','','','','','','','','ta ','','', + ], + 'x250':[ + '','du ','','','','','','','','','','','Giay ','','','', + '','','','liu ','lu ','','','','','','','','','','','', + '','','','xue ,qiao','','la ','','','','','','','Jim ','','','', + 'la ','','du ','Mo ','','lu ','','','','','','','','','xiang ','', + '','','jie ','mang ','','','','','','','','','','','','', + '','','Ngaau ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','diao ','', + '','','','','','','','','','','','','','','','', + '','Jim ','','ju ','','','','','','Trom ','','tu ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','hu ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'cha ','','','','','','','','','','','','','','','', + '','Mam ','','','qu ','','','','','','Mam ','Mam ','','','','', + '','','','','','','','','Vuc ','','','','','','','', + '','Nhap ','','','','fan ','','','','chuan ','yao ','','','','du ','', + ], + 'x251':[ + '','meng ','','','','','','','mu ','','','','','','Cik ','', + '','fu ','','','','','','','','','','','','mian ','','', + '','','','','','','','','','','','Gap6','','','Nham ','Ngom ', + 'Nhon ','','mie ','','Xue ','xu ,yu','','','','bao ','','','','','','', + '','','','Nhon ','','','','','Laap ','','','','','','','', + '','dian ','fan ','','','','','','','','','','','','','Ngaau ', + 'Hau ','er ','','','','','','','','','','','','','','', + '','','Chau ','','','wei ','','','','','xu ','','','','Zong ','', + 'Giuong ','','','Nho ','','','','','','yu ','','','jue ','','','', + '','','','','','','','','','','','xu ','wang ','','juan ','', + '','','','','','xie ','liu ','','','','','','','','','', + '','','nao ','','','','wan ','jiu ','','Ngop ','Dau ','Ru ','Le ','','','Quau ', + 'Mang ','Tro ','Bet ','','','','','','Nhon ','','','','han ,qia','','','xu ', + '','','jie ','','','','','','jun ','','','','','','dian ','', + '','','','Gwat6','','','','','','','','','','','','mai ', + '','','','','','','Him ','','','','','Tro ','','','','xu ', + ], + 'x252':[ + '','','','','chuang ','','mao ','','','huan ','sha ','','','','','kuang ', + '','','','','','','die ','','','la ','','lu ','','','','Sou ', + '','','','','','','','','','','','','','','leng ','', + '','','Kip ','Chot ','Nguoc ','Nhon ','Nam6','','','','','','','','','', + 'guan ','ju ','','nai ','','ge ','','','','','ma ','teng ','','','','', + '','','','','','','','','','','','','chen ','','','', + '','','','','','','','','','','','','Let ','','Soc ','', + 'han ,qia','','','','','Ma ','lu ','','','','die ','','','','','', + 'Xam ','','','','','','','','','','xu ','','Caau ','','','', + '','','','chan ','','','','','Ghe ','Zong ','','','','Chop ','Quac ','Nhan ', + '','','','','Nguoi ','','Mu ','','','','','guan ','','zun ','','xie ', + '','','','','Toet ','','','','','','','','','','','', + '','','','','','','','Caang ','','','','','Sa ','','','', + '','','Tre ','','','Trom ','','','Saau ','','','','','','','Xi ', + '','','','jia ','','','','','','','','','','','','', + '','','Lem ','Coi ','Ngam ','Him ','Lam ','','Soi ','','','','','','','', + ], + 'x253':[ + 'Xet ','','','','','','','','Trom ','','pan ','','','','','', + 'liu ','','','','','','','','','','','Lai6','','','','', + '','','','','','Khoe ','Len ','','','','','','','xuan ','','meng ', + 'wei ','42521.120,meng ','','','','','','','Dim ','Ngam ','yao ','','','','','', + '','','','','','','','','','','','','','Lom ','','', + '','','Cham ','','lei ','','','','Nheo ','','bian ','Ngom ','','','','', + '','','','hao ','','','','','','','zhai ','','','','','', + '','ze ','na ','','','','','','','','','','','','','', + '','','','','','','kai ','','wu ','','','','','ze ','','', + 'yu ','zan ','','','','xu ','','xu ','','','','','','','','', + '','','cuan ','cuan ','cuan ','','','','','','','','','','','', + '','','','','','','','','qia ','','tiao ','','','','','', + '','','','','','','','huan ','','','','','','','','', + '','','wu ','','','','','','jue ','','','','','ya ','','', + '','','','','kua ','','','','','','','','','','an ','zhe ', + '','','','','','','','','','','','','','','','Van ', + ], + 'x254':[ + '','pu ','','','','','Van ','Ngan ','So ','Ngan ','','','','Ngan ','','Coc ', + '','','Cut ','','Van ','ya ','','','Shi ','','','','','','Mong ','', + '','','','','','','','','','yun ','','','','','','', + '','','','','','','','','','','','','','zhe ','','hu ', + '','','Chai ','','','','','die ','','','','guai ','','','','', + '','ao ','','','','','','','','','','','','','','', + '','','bu ','','','Sinh ','','','','','Nao ','','','','','du ', + 'guai ','','Ran ','','','','Loi ','','','','','','dian ','','','', + 'wu ','','','','','','','','','','','','','','','', + '','','','','','','','','xun ','','','','','','','', + '','','','','','','','ya ','lu ','','','','','chu ','','', + '','','','kang ','','','hua ','','','','','','','','','', + '','','','','Mai ','','','','','Sanh ','','','','du ','','', + 'jie ','','xian ,kan','','','','','','','','','','','','','', + '','','','','','','','','','','','','dao ','','','', + '','','','','Mai ','','','Canh ','','','','','','','','Tuo ', + ], + 'x255':[ + 'Gwang ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','yu ','','','','','','','','','','','','','', + '','shan ','','','','Ji ','','','','','','','','','','Ham ', + '','','','','Mai ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','zhe ','','','','','','','','','','','','', + '','','jue ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','la ','','', + '','','Quanh ','','','','','','','','','','','','','', + '','','','','','','','','zao ','Cuoi ','','','','','','', + '','','','','','','','','','','','','','','','du ', + '','','','','','','','','','','','','','','','', + '','','','ta ','','','','','','','dao ','','Chen ','','','', + '','','','','','','','','Nen ','','','qu ','','ca ','','', + '','','','','','xiang ','','','','','lan ','','','','','', + ], + 'x256':[ + '','','','','yu ','','','','','','jiao ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','fu ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Rung ','','','','','','','','','','','','', + '','','','xun ','','','ru ','','','Lay ','','','','','','', + '','','','','','','','','','','','','','','','yu ', + '','','jun ','','','','','','','','lu ','','','','','', + '','','','','','','','','','','','','','','','', + 'zhun ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','liu ','','','','','','','','','','', + '','nu ','','','','','','','','','','','','feng ','lu ','', + '','','','','','zhuan ','','zhe ','','','lu ','','','','','jue ', + 'liao ','','','','','','','','','','','','','','','', + ], + 'x257':[ + '','','','','','','','','','','','','Ao ','','','', + '','','Yan ','','','','','','','zan ','','','','','','', + '','','','','','Yi ','','','','','','','','','jun ','', + '','','','','','','','','','','','','','','','', + 'she ','','','','wan ','','','','','','','','','','','', + '','','gua ','','jie ','','he ,xie','','','','','','','','','du ', + '','','Li ','','','jie ','','ba ','yu ','','','','','','','', + '','','','','','','','','he ','','','','','Cay ','du ,zha','', + '','','','','he ','','','','','','','','','he ','','zhu ', + '','','','','','','Giong ','','zun ','','ru ','Duo ','jiang ','','','', + '','','','','','','','heng ','','','','','','','','zu ', + '','','','','ku ','','','','','','','','','','','', + '','','','he ','','','','','','','','','','','','', + '','','','','','','','','','','chang ','','','','','', + '','','','','','','','','','','mao ','','','','','', + '','','','','','','','','','Lui ','','','Bap ','','','', + ], + 'x258':[ + '','','','','','huan ','','','','','','','','','','', + '','','','','','','','','','','','','yang ','','','', + '','','','','','','','','','','','','Trau ','Giong ','Rom ','Rom ', + '','','','','chang ','','','liu ','','jie ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','jun ','jiao ','','','','','','','','','','','', + '','','','','Ji ','','','','','','','','','ai ','','', + '','','','Nanh ','Mam ','','','','','','','','','','zun ','', + 'Cau ','','','','','','','','','','','','','','','hu ', + '','','','','','','','','','','','','','','','', + '','','cheng ','','','','kuai ','','ge ','xie ','','jie ','','','','', + '','','','','','','zu ','','pu ','','','','','','','', + '','','','','','','','','','','','meng ','','','','xiang ', + '','','','','lu ','','','','','','','','','','','', + '','','','','','','','','mu ','ran ','','','','','','', + ], + 'x259':[ + '','','','','','','','','','','','zhe ','','','','', + '','','','','','','','','jue ','','','','','','','', + '','','','','','','ai ','','nu ','','','','','','','', + '','','','','','mian ','','','','','','','','','','', + '','','','','','Lung ','','','','','','','','','','', + '','','','','','','','','','','','','','','','wa ', + '','','','','','','','','','','','','','','','', + '','cheng ','','','','yang ','','','','liu ','','','','qiu ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','fu ','','','','','','qia ','dian ', + '','','jiao ','','','','','','','','','','','','','', + '','','','','','','xian ','','','','','','','','','', + '','','','','','','','','','','','','','','Hang ','', + '','','','','','liu ','','','','','','','','','','', + '','','','tu ','','','','','','Nup ','','','','','zhe ','', + 'hua ','','','','','','','fu ','','Tam ','','qu ','','','','', + ], + 'x25a':[ + '','','','','','','','','','','','','liu ','fu ','dan ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Trong ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','Hoam ','','Chui ','','','','','','', + '','','','','','','','','','','','','','ca ','','', + '','','','zhu ','hai ','','','','','','','','','','','', + '','','Hai ','','','','','','','','','','','','','', + '','','','','','','','','','','','fu ','','','','', + '','','','','','','','','','','fu ','','','Trong ','Trong ','', + '','','','','','','','','','','','','','','','', + '','cu ','','','pang ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','dun ','','','', + 'lu ','Deon6','','','','','','','','chen ','','','huang ','shi ','','', + ], + 'x25b':[ + '','','','','','','','','','','','','','','','', + '','','','yao ','','','','','','ju ','','','','','','', + '','','','','','','','','Khau ','Nia ','','','','','Giang ','Kao ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Mang ','Mau ', + '','qiu ','dun ','','','','','','','','mang ','','','miao ','yuan ','', + 'wu ','','','','','','','','','','','','fei ','','meng ','', + '','','','','','','Mang ','','','','','','','','','', + '','','','','','','','Buong ','Hum ','Bu ','','','','','','', + '','','','','','hang ','','ju ','nian ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','Manh ','Tre ','Mui ','','', + '','','Toi ','Trum ','','dang ','du ','','ye ','','','','','','','pai ', + '','','','','','','jian ,sha','','','','Trau ','','','','yu ','', + '','','','','','','','','zhu ','','','','','','','', + ], + 'x25c':[ + '','','','','','','','','','','Thap ','','','','','', + '','','','','','','','','','','','fu ','','','','', + '','','shan ','liu ','','','','','','','hu ','','','','','', + '','','','xian ','','','','','','','','mu ','','','zhai ','', + '','','nu ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Ro ','','','','Ghi ','Gianh ','','', + '','','','','','','','','','','','','','juan ','','', + '','','','','dan ','','','dan ','','hu ','','','','','lu ','chuan ', + 'wu ','','','','','','','du ','','','shuang ','fu ','ju ','','','diao ', + 'wang ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','fu ','','','','','','xun ','','', + 'Khay ','','','','','','bu ','','','','','','','','','', + '','fen ','dian ','','','','','','','','suan ','','an ','','','', + '','','du ','','','','','','dan ','','','','','','','', + ], + 'x25d':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','Thung ','Mui ','','','','','','','', + '','','','','','','','','ai ','ge ','ju ','tun ,dian','','qia ','','', + '','jian ','','','','suan ','','','','','','qiang ','','','','', + '','','','','','','','','','','','','','','','dian ', + '','','','','','','Toi ','Hom ','Ray ','','Lak6','Nong ','','','jie ','zhu ', + '','','','','zhao ','','','','','','','','','','','sa ', + '','','','','','','','','','','','','','','','Mung ', + 'Thung ','','Gay ','','','liu ','','','','','','','','','','', + '','','','','','','','','','','','','hu ','','','', + '','','','','','','','','','','','','','','Toi ','', + '','','','','','','','','','','die ','','','','','', + '','ban ','','','','','hu ','','','','','','','','','', + '','','','','yu ','die ','','','','','','','','','yu ','', + '','','','','','','','','','','','','','','','', + '','fu ','','','','','','','','','Mo ','May ','cu ','','','', + ], + 'x25e':[ + '','Nan ','','','','','','','dang ','','','','','','','', + '','','','','','','','','','','','','','Trum ','','', + '','','','shan ','yu ','','','','','','yu ','','','','','', + '','','','','','tun ','','','','','','','','','','', + 'Tam ','','','','','','','fan ','','Nap6','','','','zhu ','','', + '','','','','yu ','','','','','','','can ','','','','', + '','','','','','','','','','','','','','','','', + 'Lau ','','','','bu ','chu ','','liu ','Bot ','','','','','','','', + '','','','','','','','','','','ge ','','','','','', + '','Tam ','','Lo ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','Com ','','','','', + '','','','','','','','xian ','','he ','','','','','','', + '','','','','','','','','','','Nam ','','','','bu ','No6', + '','May ','','','','','sa ','','','mian ','','','','','','', + '','','','','xia ','','','','Bun ','','','','','','','', + ], + 'x25f':[ + 'zu ','','','ze ','','','','','','','','','','','','', + '','','','','','Lep ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','xiao ','','','Thung ','','','','','','','','','Com ','','xian ', + 'jian ','','','','Men ','','','','Miao ','','','','','','','', + '','Phan ','','','Xia ','','','','','','','','niang ','','','', + '','','','','','','he ','','lian ','','','','','','','', + '','','','Men ','','zhu ','','','','','','reng ','jie ','','','', + '','','','','','wu ','','','','','','cu ','','','','', + '','','','','','','','fu ','hu ','','','','','','jue ','diao ', + '','','','','','','','','','','','','','','Buoc ','', + '','Vuong ','Tim ','na ','','','','','','','','','','','','', + '','','','','','','','Giay ','','','','','','dai ','','', + '','','','','Khau ','','','','','','','','','','','pai ', + '','','','','','','','chao ','','','','','','','','', + ], + 'x260':[ + '','','','','','','','Jing ','','','Dai ','','','','','Thua ', + '','','','','','','Kep ','','','','','','zhuang ','','','', + 'liu ','','','','','','','','No ','','','','','','','', + '','','','','','','','','mao ','Thun ','Xe ','Cui ','Noi ','Keo ','Rang ','', + 'Boi ','Nuoc ','','','','','zhuan ,juan,shuan','nian ','','','hua ','','','','','yan ', + 'jue ','','','','','','','','','','','','die ','','','', + '','','','Go ','','','','','','','','','','','','', + '','','','','','','','','','Ro ','','','May ','Vuong ','','', + '','','','','','','','','','','fu ','','','','','', + '','','','','wan ','','','Sok ','','','','The ','','','','', + '','','','','','Dam ','','','','','','','','','','', + '','','','','','','','','','','','Luot ','','','','Buoc ', + '','','','','','','','','','','','','','','','', + 'Tao ','','','liu ','he ','','','','','','','','','','','', + '','','','','mu ','','','','','','','','','','Gai ','', + '','','','','','','','','','','','','','','','', + ], + 'x261':[ + '','Thun ','Dai ','','Quan ','','May ','','','','','','Chap ','','','', + '','','','Xau ','die ','','','','','','','','','','Van ','', + 'Nut ','','','Cuon ','','','','','','','','','','','','', + '','','','','Chai ','','','','Xung ','','Rang ','Quan ','','qu ','','', + 'xun ','','','','zhe ','','dian ','','','','','','','','','', + '','xun ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Tan ','', + '','Thua ','','','','','','','','','','','','ju ','','yun ', + '','','','','','','','','','','','lai ','','','','', + '','','','','','','','','','','Neo ','','','','wu ','Mung ', + '','','','','','','','','','','','','','','','Ban ', + '','','','','','','','','','','','la ','','','','', + '','','','','','','','','','','','','','','','', + '','','Roi ','','','','','','','','','la ','','','','', + '','','','','','','','','','','','','yao ','','Chung ','', + '','','','','','','','','he ','','','','','','','', + ], + 'x262':[ + '','','Nhau ','nang ','','die ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','yu ','','','','','','','','','','','','', + '','','','','','','','','yu ','','','','','','','', + '','','','','','','Cha ','','','liu ','','','','','','', + '','','','','','','','','Caang ','bian ','','','','','','ya ', + '','','','','','','','ya ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','hu ','cen ','','','','','','','','','','','','', + 'ju ','','','','','','','','hu ','','Bon ','Tu ','','','','', + '','','','','','','fu ','hu ','','','','','','','','', + '','','','','','','','','','','','','','meng ','fu ','liu ', + '','','','','','xie ','','','xian ','','','','','','','', + '','','','','lu ','','','','','','','','','','','', + '','','yu ','han ','','','Ra ','','','','dan ','','','','','yu ', + '','','','','','','','','','','','','','','','', + ], + 'x263':[ + '','','','','','','','','','su ','su ','','','','','', + '','','liao ','','','lu ','','','','','','','','','','lu ', + '','','','','','','huan ','','','','','','','','','', + '','','','','','','','du ','','','','','','','','', + 'nan ','','','','','quan ','','','','','','','','','','fen ', + '','','ta ','tun ','','','','','','','','','','','','', + '','','','','','','','','','Gu ','fen ','','','','','', + '','','','','','','','','shan ','','','','','','','', + '','','','','su ','','','chuan ','','','','','','','','', + '','','jie ','','','','','','yu ','','','Guong ','chuan ','','','', + '','Xinh ','','','','','wu ','','','','','','Tanh ','fu ','','', + 'gu ','','','','','','','','','','','','','','','', + 'ren ','','','','','jue ','','','','','','','','','','', + '','','','Bon ','','du ','','hu ','','','','','yu ','','','', + '','','mai ','','','','','','huai ','','','','','','','', + '','','','','','','','','','','','yu ,yu','','','','', + ], + 'x264':[ + '','','','','','','','Taap ','Fen ','','','','','','','', + '','','','','','','','','','','','qu ,yu','','','','', + '','fu ','','','hai ','','','','','','','','','','','', + 'chai ','','','','','','','','','','','','','','','', + '','','','','','','','ta ','','','','zu ','','xu ','yan ','chai ', + '','','','','','','','','','','','','ge ','','','', + '','','','','','','','','','','','','','','','', + '','','ta ','','','','ta ','','','fu ','','','','','liu ','', + '','','','','','han ','','','','','','','','','','he ', + '','yu ','','','','','','','','','','','Zin ','','','', + '','','','','','','la ','','','','','','','','','', + 'tai ','','','','','Khu ','shu ','Bou ','','','dao ','','','','','', + '','','','','','Gia ','','Khu ','','Lu ','','wang ','','','nai ','', + 'jue ','','','','','','','','','','','','','','','', + '','Ma ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x265':[ + '','','','','','tu ','','','ze ','','','','','fu ','','', + '','','','','','','','','','Cay ','','','','','','', + 'pai ','','','','','','kuai ','','','','','','qu ','','zhe ','sha ', + '','','','','','','','','','nai ','','','','','','tian ', + '','','','','','','ye ','','','','','','','','','sao ', + '','','Zim ','xu ','','','','','','qu ','','','','','','', + '','','','','','','','','','','','','','','','', + 'duo ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','hua ','','', + '','Nghe ','','','','','','','','','','','','','','', + '','','','','','','','yan ','','','','','','','','', + '','','','','','','','','','','','Tai ','hu ','','','Dap ', + '','tian ','','','','','','','','','','','','ai ','','Lang ', + 'ai ','zhe ','','lu ','','','','zhe ','','','','','','','Ghe ','', + '','','','hu ','','','','','','','','','','','','', + '','','','','','','','','','','','ju ','','','','', + ], + 'x266':[ + '','','','','','','','','','','','','','wai ,wa','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','Paa ','','','','','','', + '','','','','','','','','','','','','','','','', + 'pan ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Moc ','Mao ','Hong ','Tim ','','','','','','','','ju ','dai ', + '','','','','zhu ','Wan ','Gu ','','','ban ','','mai ','Ci ','','','', + '','','','','','','','','','','','','','','','', + '','','','Ping ','','','Zaap ','','','','','','','','','', + '','','','hen ','','','','','','','','xie ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','Ruot ','','','ku ', + 'na ','','','','xuan ','','','','he ','','Nam6','','Ham ','','','', + '','','','','','','','','','','','','','','','', + '','','jue ','','','','','','','','Bet ','Thon ','','','Nuc ','Mang ', + ], + 'x267':[ + '','','','xu ','','','','','','','','','','pang ','','', + '','','','','','','Ngaa6','','Vu ','','','','','','Ron ','', + '','','','','','','','','','','','','','','','', + '','','','','tun ','','','','','','','','','','','', + '','','','','Rang ','','','','Ngac ','','','Mun ','Mep ','','Phop ','', + '','','','','','','','','','','','','','huan ','','', + '','Jim ','','','ban ','','','','','','','','tu ','','','', + '','','','xu ','','','','','','','','','','','','', + '','Tuoi ','','','','','','','','','','','','','Nghen ','', + '','','','Phay ','','','','','','','','','','','','', + '','','Tao ','Sao ','','zhe ','','','','','','sai ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','Bo ','Zin ','Gay ','Suoi ','Khu ', + '','','','tun ','','','','Nem ','','','','','ze ','','','', + 'cu ','','','','Xiu ','','','','','','','','','','','', + '','','hun ','ju ','','','Nem ','','','','','','','','Khu ','', + ], + 'x268':[ + '','cu ','','','','xun ','Sun ','ceng ','','','','','','','','', + '','','jue ','','','','pao ','','Vai ','','','','','','','', + '','','jiu ','zhe ','','','shu ','','','','','','','','','', + '','Phet ','','','','Roi ','Seo ','','','','','','','','','sa ', + '','','','','du ','','Fat ','','','','','Ron ','','','','', + '','','','','','','','','','','','','','','Ngam ','Lung ', + 'Song ','','Rau ','','','','','','san ','','','','','yu ','','', + '','yao ,shao','','','','hun ','Lom ','','','','','','','','','', + '','','','','','','','','','','Pok ','','Duk6','','guang ','', + '','','','Mak6','','','','','','','','','','','','', + 'Rang ','','','','','','','meng ','','','','','','','','', + '','','','Vai ','Lot ','','','','','','','','','','','', + '','','','','lei ','','','Lo ','','','','','','','Nan ','', + '','','qu ','','','','','Nhau ','','Nang ','','','','','','', + '','','','','','','','','','','','','','','','', + '','Zak ','','','','','','','lian ','','','','','','','', + ], + 'x269':[ + '','','','','','','','','','','ru ','yao ','','','Gao ','', + '','','','','','','','','','wa ','','','','','','', + '','','','','','','Hot ','zhai ','','','','','hai ','','Thoi ','Kham ', + '','','','','','','','','','','','','','','','', + '','wu ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','Xue ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','fen ','','','','','','','','Kyo ','','xiao ','','','','', + '','','cheng ','','','','','','','yu ','','yu ','','','','', + '','','','','','','','','','','','','','juan ,fan','','', + '','','','Lau ','','Weng ','','','','','','','','','','', + '','','','','','','tian ','','hu ','','','ta ','','','ta ','ta ', + '','','','','','ta ','','','','','','','huai ','','','', + '','ta ','Loe ','','','hua ','','','zhuan ','','Laai ','','','','','', + ], + 'x26a':[ + '','','Mua ','','','','','','fu ','wu ','','fu ','','','ta ','', + '','Chai ','','','','','chao ','','','','','','Qua ','','','', + '','fu ','','','','','jia ','','','','','','','','','', + '','','','wu ','','','','','','','','Khoang ','','','','', + '','','','','','','','','','','','bai ','','','','', + '','','','','','','','','','','Mui ','Gu ','','','yu ','', + '','fu ','xian ','','','','','','','','','','','','','', + '','sheng ','','','','jian ','','','','','','','','','','sha ', + '','','','','','','','lu ','Ao ','','','','','','','Thong ', + '','','','','dun ','','','','jue ','ta ','zun ','','','teng ','','', + 'hua ','','','','','','','','','','peng ','','','','','', + '','','','','','Ghe ','','','','','','Khoang ','Ghe ','','','', + 'teng ','','','','','','','','','','','','','','','', + '','','','','','','','','','ba ','','','','','','', + '','','','','','','','','','','wa ','','','','','xun ', + 'meng ','','','','','','','','','','','','','','','', + ], + 'x26b':[ + '','','wu ','zhe ','','','','','','','','','','','','', + '','','','','','','qiu ','','','','hu ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','zhu ','','','','','','','', + '','','','','','','','','hu ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','Tup ','','','Hung ','','','','','', + 'ru ','','','','','','','','','','','jiu ','','','','', + '','jiao ','','','','','','','','','','','','','','', + '','pu ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','Nen ','','','','','fu ','','','','','','', + '','','','','','xu ','','','','','','','','','','', + '','zao ','','','','','','','','','','','','','','', + '','','','cu ','','','','','','','xiao ','','Dua ','','','', + '','','','','','','','','','','','','','','','', + ], + 'x26c':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','fen ','','','','Ngon ', + '','','Nua ','','Lau ','','','','','','qiu ','','','dun ','','', + '','','','ye ','','','','','','','fu ','','','','','', + 'yu ','','yu ','yu ','Gu ','','','','','','','meng ','','','','', + '','','mu ','','Bei ','','Fu ','','','','','','xiao ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Nhai ','','','','','','','','','','','','','', + '','','','','','','','','','','','fu ','','','','wan ', + '','','','','','','','Lei6','','','','Rom ','','','Muop ','', + '','hao ,mao','','xie ','','','','','','','','','','','','', + 'nai ,na','','','fu ','du ','','','','','Tre ','','','','','bai ','', + '','','','xun ','','','','','','','','','he ','','','', + '','','','','','','meng ','','','','','','','juan ','ru ','', + ], + 'x26d':[ + '','','','','','','','','','hu ','','Mong ','jun ','she ','','', + '','','','','meng ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','Ke ','','','Nu ','','','','','', + '','','','hun ','','','','','','','','','zu ','','','', + '','','','','jie ','','','','','','','','jun ','','','', + '','','','','','','','','','','','shan ','','','','', + '','ta ','','','','','','','','heng ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Kou ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Chu ','','', + '','','','','','','qiang ','','','Bom ','','','','','','Mai ', + '','','','hu ','','','','hai ','ru ','meng ','','','','wu ','','', + ], + 'x26e':[ + '','','','','','','','','','qia ','','','','','','', + 'lu ','','','','','','','','','','','','','','','', + '','','','','','','','','','','pei ','','','','','', + '','fu ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','zhao ','','','','', + '','','','Thom ','','','Voi ','Bui ','','Nhai ','','Dam ','','','','', + '','','','','','','','du ','','','','','','','','', + '','','','','','','ju ','','','','','chuan ','Lao ','','','hu ', + '','','jie ','xiang ','','','','','xiang ','','','lang ','','','','', + '','','shuan ','','','chu ','','','','','','','','','','', + '','dan ','','','','sa ','','','','','','','','','','', + 'Zaau ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x26f':[ + '','','','Sang ','','','','','ju ','','leng ','lu ','','','','', + '','','','','','','','','','','Lum ','San ','San ','','Dua ','Khay ', + 'Sung ','','she ','','','','','sa ','','','mao ','qu ','','','','Zuk6', + '','juan ','','','','he ','','','','','','mei ','','','','', + '','','lu ','mian ','dian ','','','','','','Waa ','','','','lu ','fu ', + '','','zei ','','Om ','','','','','','','','dan ','','wan ','', + '','','','','','','','','','','','','','','','', + 'Tranh ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','sha ','','','','lu ','', + 'Dua ','','','','','','','','','dan ','','','','','','', + '','','','','','','jian ','lu ','','','','','','ta ','','', + 'chu ','fu ','','','','','dang ','','','','lu ','','','','','', + 'jie ','','','','','','lu ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x270':[ + '','','','','chang ','','meng ','','','','','','su ','','','Sung ', + '','Giong ','Non ','Ru ','','sa ','','','','','','','Sam ','','','', + '','zhan ','','','','','','','Lop ','','','','','','','', + '','chai ','','','','','','','','','xie ','','','','','', + '','','','xu ','','','','','','fan ','meng ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','Ghem ','','','','','','','','','','','', + '','zhan ','jian ','han ','dan ','','jian ','','','','','','','','','', + '','','','','hu ','','','','','','','meng ','ju ','','','', + '','meng ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','Dua ','','','','chu ', + '','','','','','','','','','','','','','','','', + 'yu ','','','','','','','','','','','','','','','', + '','','','','','','Muong ','Khoai ','','','','','','','','', + ], + 'x271':[ + '','','','','','','','','','','Han ','','','','','fu ', + '','','qu ','','','','','','','','','ju ','','','','', + '','','','','','','','','','','','','','','','', + '','','Mo ','','','','','','','','','','','','','', + '','','','','','','','','diao ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','Men ','Muong ','','', + 'hu ','','','','','','','','','','nang ','','','','','', + '','','','','Thuoc ','','','','','','','','','','','', + 'gan ','','','','','','','','','','','','','','','', + '','xu ','','lu ','','','','','','','','','','','','hu ', + '','','','','','','','','','','','','','','','', + '','','','','lu ','','','','zu ','','','','','','he ','', + '','','','','','','','','','','','','','shu ','','', + 'yao ','','','','','','','','','','','','','','he ','', + 'hu ','','','','','','','','','','','','hao ','','','zu ', + ], + 'x272':[ + '','','','','xia ','','','','','','','','ge ','','','', + '','ge ','','','','','ge ','','','','42573.210,zhu ','','teng ','ya ','','', + '','','','','','','','','','','','','','wu ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','tai ','','','','','','','','Trun ','Vat ','','','','','', + '','','xue ','yu ','fan ','','','','','bu ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Gwaai ','','dai ,de','','Buom ','Nhong ','','','','Vat ','', + 'Trut ','','','','','','','','ku ','','','qu ','','','','ru ', + '','','','','','xu ','','','','','','','he ','','','', + '','','','','','Gong ','Doe ','','','','','','','','','', + 'Chau ','','','','','','','','','','Saa ','','du ','Zhe ','','', + '','','','kao ','','','','','','','','','','','','Moi ', + '','na ','','','','','Mei ','','','','','','','','','', + '','','','','','Cuong ','Mot ','','','','Chay ','','Nhong ','Mang ','','', + ], + 'x273':[ + '','','Bo ','','','','','Bang ','fu ','lu ','','','','lu ','','ta ', + '','','','Fu ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','Cua ','','','','','Ngai ','','','','Cua ', + '','','','shuai ','','jue ','','','','fan ','','','','','','', + 'jie ','','','','','','','','','jie ','yu ','','','','','feng ', + '','die ','','','lian ','hu ','','','','','','','','','','dian ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Chau ','','', + '','','','','','shan ','','','','','','','','','','', + '','','zu ','','zhe ','','','','','','','','','','','', + '','','xie ','xie ','','','','','','','','','','','','', + '','','','liu ','','','','','','','','','','','','', + '','','','','','jie ','','','','','','sha ','','','','Nhuc ', + 'Sam ','','','Bo ','Choi ','','','Nhuc ','','ai ','','','','','','zhu ', + ], + 'x274':[ + '','su ','','xie ','yu ,yu','Zeoi ','','','zu ','','','','','','','', + '','','su ','','','','Luon ','','','wu ','','','','','','', + '','','Hou ','','','','','','','','','','','','','', + 'du ','','','lu ','su ','','','','','','','','','','Bo ','Sung ', + '','Sam ','','Ngao ','','Vet ','Chang ','','','','','','','','','', + 'yu ','','Giun ','','dai ','','','','dang ','zu ','','','','chuan ','','', + 'du ','','','','','','xie ','zhe ','','','','sao ','','','','', + '','','','','','','','','','','','','','','','', + '','','fu ','','','Buom ','','Sau ','','Rua ','','Rom ','Rua ','Rua ','e ','', + '','','','','','','','','','fu ','','','lei ','','','', + '','','','','','','','','chai ','','','','','','','', + '','','','','','','','','','','','','','lei ','','zei ', + '','ai ','','','','','','','','','','','','Ban ','','', + '','','','','','','fei ','','','','','','','','','', + '','','','','','','','','','','','','','','','Ngoe ', + 'Sam ','','','','','','','','','','','','','','','', + ], + 'x275':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','ta ','','','','','','','','','du ','qiu ','','', + '','','','','chai ','','','','','','','','e ','','','', + '','','','','','','','','','','','','','','qu ','', + '','','','','','','','','','','Trai ','','','','','', + '','fu ','','','','','','chai ','zang ','','','','','','','', + '','','','','Naan ','','','','','','shuang ','','','','','', + '','','','','','','ta ','','','','','','','','','', + '','','','','','','','','','','fu ','','','','','', + '','','','','','','Moi ','','','','','','','','an ','', + '','','','','','','','','','','','','','','','xiang ', + '','','','','','','','','n ','','','san ','hu ','','zu ','', + '','','','','','','','Jiku ','','','','','','','','', + '','','','','','','','','','la ','yu ,qu','jue ','','','','', + '','shu ,yu','','','Jung ','','','Jutsu ','jian ','','','','','','','shuai ', + ], + 'x276':[ + '','','Chong ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','hu ','','','','','','','','','','','','','', + '','','','','','','','','','Taai ','','','','','','', + 'La ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','pu ','','che ','','', + '','','','','','','','53077.090,jian ','','','','','','zhan ','yuan ','', + '','','','','','','yu ','','','','','Lot ','','','','', + 'mu ','huan ','','','e ','Long6','','','','','','peng ','','','','', + '','','','','Tung ','','','','','','','','','','','', + 'Song ','','Xong ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','Trang ','Lun ','May ','','','','','','', + '','','','','du ','','','tu ','','','','','','','hu ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','Toi ','','','','','','','','', + ], + 'x277':[ + '','Sha ','','','','','','','','','','','','','','', + '','','','','','','Chan ','Mo ','','Xong ','','','','','','', + 'shuai ','','','','','','su ','','','','','','','','','', + '','','','','','','','','','','Bau ','','','','','', + '','','','jue ','','','','','','','','','','','','', + '','zhan ','heng ','','qu ','wei ','','','bao ','','','','','','Gei ','', + '','','','','','','','','Cheo ','Toang ','','','','','','', + '','','ju ','he ','','','','','','','','','','','','', + 'shu ','','','','','','','','','','','','','','','yu ', + '','meng ','hu ','','','','','','','','','','','','','', + '','','','','','','','','','jie ','La ','shu ','jie ','lei ','','', + 'zu ','','','','','','','','','','su ','','','','','', + '','','','xie ','','','','','','','','','','','','', + '','','','','','','','','nang ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x278':[ + '','','','','','','','','cha ','','mao ','','','','','', + '','','xian ','','','','','','','','','chan ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','gao ','','','', + '','','','','','','','','','','Thay ','','','','','', + '','jiu ','','','','','','','','','','','','','','', + '','yun ','','','','','','','','','','','','','','', + '','','','','lian ','','','','','','','','','','','', + '','','','','','','','','','','','lao ','','','','', + '','Don ','','','','','','','','','','','','Lai6','','', + '','','yao ','','','','','wei ','','','','','','','','', + '','','','','','','chu ','','','','','','','e ','','', + '','','','','','','','','Caau ','','','','qiao ','','','', + '','','ju ','','','qiu ','','','','','','','','','','', + '','','hun ','','','','','Dia ','','','','','','','','', + '','','','','','lun ','','','jue ','','','ju ','hu ','','','', + ], + 'x279':[ + '','','','','','','','','','','','','','','','', + '','ju ','','','','qiu ','','','','','','','','','','', + 'zhe ','','','','','','','','','','','','','Ba ','','', + '','','','','','','','','','Thoi ','','','jue ','','','', + '','','','Choi ','','','su ','','','','','','kuang ','','jue ','', + '','','','','Va ','','','','','','','','','','tan ','', + '','','','','','','','','','','','','','','','hu ', + '','fu ','','','yang ','','','ren ','','','Kwan ','','yun ','','','xun ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','pu ','', + 'Ngaak ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','Beng ', + 'Ngoa ','','','','wang ','','','','','','','','','','','', + '','','','xu ','','','','','','','','','','Ngaa6','','', + '','','','','','','','','','','','','','','','Khoang ', + '','','','','','','tu ','','bie ','','','zha ','','','','', + ], + 'x27a':[ + '','','','','','','','','','','Zaa6','','','','','', + '','','','','','','','','','','','','','','','', + '','chen ','','','','','','','','','','','','','','', + '','','','','','','','','','lu ','','','','','Tam ','', + '','','','','','yan ','','','','','','','','','','', + '','','','','','','','','','Daan ','','','','su ','','', + '','','','','','','','','','','','','','','','', + 'bian ','','la ','','','','qia ','','','','','','','','','', + '','','','','','nu ','','','','','','','','','','', + '','','','','','','','','','','','','','','he ,ge','', + '','','','','','','','','ma ','','','','','','','', + '','','','','','','','','','xia ','','','','','','', + '','','','','','','','','','','yu ','','','','','', + '','jie ','xia ','','','','','cha ','','','','yang ','','','','', + '','','wang ','','','','','','','','','','','','','', + '','','','','','','','','','','','','Mo ','','jiu ','', + ], + 'x27b':[ + '','hao ','','','','','','','','','','fa ','','','','', + '','','','','','','','','','','','','','','yun ','', + '','','','','','','','','Wai ','','gun ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','dan ','','','','','','','meng ','','','','','', + '','','','','teng ','','','','','','','','Leoi6','sa ','','', + '','','','','','','','','','','','','','','','', + '','','','he ','','','','','','','','','','shan ','','', + '','','','','','','','','','','','','','','','', + '','ta ','','','','','','liu ','','','','','','','','', + '','','','','','','','','','','','jue ','','','','', + '','fen ','','','','he ','','','','','zhan ','','tai ','qian ','','', + '','','','','Hang ','Hang ','','','','','','','','lao ','','', + '','','','','','','jun ','','','','','','','','','', + '','','','','','zai ','juan ','','','chu ','','','','','','', + 'kan ','','','','','Phong ','','','','','','','','','','', + ], + 'x27c':[ + '','','','','','','','yu ','wu ','','Tian ','','','','','', + '','','','','','','','Nanh ','','','','','','','','', + '','','','','','','','Shuu ','','','han ','chu ','','tun ','','', + '','','','','','','','','','na ','','','','','','ai ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','mai ','','','','lun ','jue ,jun','','', + '','','','','','','','','','','','','','','','', + '','','','huai ','','','','','','','','','','','','', + '','','','','','ceng ','','hu ','','','','ju ','sha ','meng ','','', + '','','','','','','','wei ','','','','','','','','', + '','','zhe ','','','hu ','','','','','','Cop ','','','','', + '','','','','','qu ','','','','','','','Beo ','','','', + '','','fu ','','','','','Cop ','','','','','','','wu ','pei ', + '','','','','','','','','Hum ','','','sha ','','zhao ','wei ','', + '','','','','','','','','','tuan ','','','mei ','','','', + '','','','','','','','','gu ','shao ','','','','','','', + ], + 'x27d':[ + '','','peng ','','','','','','','','huan ','Beo ','fu ','','biao ','', + '','','','','','biao ','','','','','guai ','','','','','', + '','','','','','pei ','','','','','Suo ','','','','','Me ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','Qua ', + 'pai ','','','','','','','','ai ','','','','','','','', + '','','','She ','','','','','','','','','','','','', + '','','','','Zaang ','','','','','','yun ','','','xu ','','', + '','','','','cheng ','','','','','','','','','','','', + 'yu ','','','','','','','','','','','','','','','', + '','','','','','cha ','Faan ','ze ','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'fen ','xie ','','','','','','','','','','','','Xoe ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','shan ','','Mua ','','','','','','ju ','', + ], + 'x27e':[ + '','','','','','','','','','','','','','','','', + '','','','','','','Zhuan ','xue ','','','','','','','','', + '','','','','','','lan ','ju ','','xun ','zhan ','gun ','','','','', + '','','','','','','','','','','','Bui ','','','','chai ', + '','','','','','','','','reng ','','','Vay ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','Son ','','','xu ','','', + '','Tham ','hu ','gan ','','','','','','','','','','','hu ','', + 'Tham ','Tham ','','','','','','','','','','','','','','', + 'jue ','','zu ','','','','','','','','','','jiao ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','chu ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','xian ','','','','','ju ','','Mut6','','','','','','', + '','','','','','','','','','','','','','','','', + 'hu ,zao','qiu ','','fu ','lang ','sha ','','','','','','','','','','', + ], + 'x27f':[ + '','','','','','','','','','','','','','Lanh ','','', + '','xu ','','','leng ','','','fu ','','','','','cu ','','','', + '','','','','dao ','','','','jie ,jue','','','yu ','','','Tang ','shu ,yu', + '','','','','','','','','','','','','','','','', + '','','','','jie ','','','Day ','Day ','','','','','','','', + '','','Cau ','','','','','','','','','','','','','jie ', + '','','','','','lu ','','chu ','','','','lian ','','','','', + '','','','','','','e ','su ','Jue ','','','ju ','','','','', + '','','','','','','xuan ','','','','','','Tron ','','','', + 'jiao ','','','','','','','','','','yu ','','','xun ','','', + 'xun ','','','ju ','','du ','','','','xun ,xuan','','','','','','jie ', + '','qu ','','','','jue ','','','','','','jiu ','','','','Treo ', + '','','','','','','','','','ku ,wu','','ku ','zha ','','','ba ', + 'Chen ','Nhac ','Dam6','hu ','nu ','e ','','','','','','','','','','', + '','','','','','bie ','','','','ge ','','Tau ','','','','', + '','','','','','','','yu ','','Mau ','Xoat ','ju ','','','','', + ], + 'x280':[ + '','','','','','','','','Buoc ','','','','','Dung ','Lop ','', + 'Rong ','','','','','','hai ','','','','','cun ','','','','', + '','','','Kei ','Leoi ','','','','','','','','zai ','','','', + 'Bang ','','','','xun ','','','','','','','','','','','', + '','xuan ','xie ','','han ','','','tun ','Gaang ','','cen ','','','Ren ','Choanh ','', + '','','','','','','','','','','','','','Buot ','','', + '','Noi ','','','','','','Noi ','Cuong ','','Dau ','','','','','', + 'Xui ','','','','','','','','','','','','Bon ','de ','','', + '','','','peng ','','','','','','','','','','','','', + 'Leoi ','','','','Doc ','','','Co ','','','','','','','tan ','', + '','','','wu ','','','chuan ','','','','','','','du ','','', + '','hun ','','','','','','','','','','','','Dam6','Naam ','', + '','','','','','','','','','','','','Giay ','Tot ','','Xam ', + 'Giay ','','','','','Soc ','kua ','teng ','','','ta ','sa ','','','Pun ','Pun ', + '','','','sao ','','','','','','Sin ','','','','zu ','','', + '','','jie ','neng ','','','','Chuc ','','','','','To ','Nhuc ','Xung ','', + ], + 'x281':[ + '','','','','','','','','','','Te ','','','','','', + '','','','','shuan ','zu ','','','','','','','','','','', + 'Tat ','','','','','','','','','','','','','','','yu ', + '','','','','Sup ','','','','','','Chui ','','','','Ghe ','Giong ', + '','Sup ','Mop ','','','','','','','Lung ','','xiao ','','Ren ','','Laam ', + '','','shu ,chu','','','','','','','','','','','Jaang ','Nhap ','', + '','','','','','Bay ','','','','','','','','','','', + '','','','','','','','Doi ','','','','','','','Sum ','', + '','','Khum ','','zhu ','','','cha ','juan ','','','','','','zei ','', + '','','','','','','','','','','','','','Cui ','','', + 'Quay ','Dep ','','','','Tuon ','','','','','Jaang ','','','','','Buk6', + 'ta ,da','','','','','','','','','','','','','','','', + '','kuang ','','','','bao ','lai ','','','Leo ','','','','','','', + '','','','','','','lu ','','','','','','','','','', + '','','','','','','chan ','','','zhan ','','','','','','', + '','','','','','Nhao ','Khuy ','','','','','','','','','', + ], + 'x282':[ + '','','','','','','','Laam ','die ','','','','','','','', + '','','','leng ','','','','','','','Pei ','','','','','', + '','','','','','','','','','','','zhu ','','','','', + '','','','','','','','','','','ye ','','','','','', + '','huang ','','','','','','','','Pei ','','','','','','', + '','','','','','','Nei ','','','','','','','','Lung ','', + 'Ban ','','','','','','','','','','','','','mei ','','', + '','tang ','','','','','','','','','','','Wu ','xiang ','','', + '','','','','','','','','','','','','Lan ','','','', + '','','','','','','','','','','','Laak ','','','','', + '','','','','','','','','','','','','','','','', + '','yu ','','','','','','','','','dai ','','xuan ','','','jue ', + '','','','','','','','','du ','','','','','Wan ','','', + '','','','','','','','','zha ','','','pao ','','','bu ','he ', + '','','Lip ','','So ','','','ju ','hun ','','','','','','','Zhuai ', + '','','','','','','','','','','','','','','','', + ], + 'x283':[ + '','','','','zang ','','','','','','','','','','xu ','', + '','','','','','','','','jun ','','','','','','','', + 'lu ','','','','','fu ','','','','Tang ','','','chao ','ta ','','', + '','','','','','','','','','','','','','','','', + '','','','','Co ','','','he ','','','','','','','mu ','', + '','','xian ,jian','','','','','','','','','du ','','','','', + '','','','','','','Sau ','','','peng ','','','','','','ju ', + '','','','Yao ','','','','','','','','','','','','', + '','','','','','','So ','','','','','','','','','', + '','','','','yang ','','','','','','','','','','','Truoc ', + 'Truoc ','','','','','','','peng ','','','','jian ','jiao ','','','', + '','','','peng ','Dang ','','qu ','','mu ','','','','','','fen ','', + '','','','','','','','','','shuan ','jian ','','','','','', + '','','','','lu ,du','','','','','','ge ','','','','','', + '','','','','','xian ','','So ','','','','','','','','', + '','','','xie ','ge ','','','','','jue ','','','','','','', + ], + 'x284':[ + '','die ','','zhe ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','ku ','','qu ','','ge ','ban ','','','','','','','','Cay ','', + '','ban ','','','','','','','','','','','','','ban ,bian','', + '','','','','','','','','','','','','chen ','','','', + '','','Tu ','','','','','','','','','','Xuong ','','','', + '','','','','','wu ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','pan ','','','','','','','qiu ','','','','','', + '','','','','','','','','','','','','bie ','','kan ','', + '','','','','','','','','nai ','','','','','','','', + '','','','','','','','','','','Quanh ','','','','','', + '','','','','','','','','','','die ','','','','','', + '','','','','','','','','','','','','','','dai ','', + '','Lung ','','','','','','','','','','','','','','', + 'jie ','','','','ya ','','','','','','','','','','','pei ', + ], + 'x285':[ + '','','','','','','','','Choi ','','Suot ','','Co ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','shu ','','','','','','','','','ta ', + '','','','','','','','','','','','','','','','Chuc ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'ze ','','chu ','','','','qiu ','','','','','','','','','', + '','','','','','','','','','','','','','jie ','','', + '','','','','','Sang ','','','','','','','yang ','','','jiu ', + '','','','','','','','','','','','','','','','', + '','','','','','','','Mau ','','','','','','','','', + '','xian ','','','','','xiang ','sha ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','dao ','','','','','','','','','Nhanh ','yu ,ju','','', + '','chao ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','da ','', + ], + 'x286':[ + '','','jiu ','','','','','','','sha ','','','','','','', + '','','','','','','','','','xian ','','','','','xian ','', + '','','','','','','','','','','','','','','jiu ','', + '','Nhanh ','','','kao ','','','','','','','','','','','', + '','','','','','','','','','','','','','Keo ','ta ','zan ', + '','','','','zhu ','','Suot ','','','','','','','Lui ','','', + '','','','','','','','','','','','','','','','', + '','','','','','xiang ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','bian ','','','','','','','','','','', + '','','','','','','','qie ','','','','','','','hao ','', + '','','cun ','','ru ','zai ','','','','','','','','','','', + '','','','','','','','','','','','','','shao ','han ','', + 'jun ','','bu ','','','','kuai ','','','','','','xiang ','','','', + '','yun ','','','','pu ','','','','','','','pei ','','','', + '','','','','','','','','','','','','','','','', + ], + 'x287':[ + '','','','','','','','','','','','','huan ','qiao ','','', + '','','','','','','yu ','','mei ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','he ','','','he ','','','','','','','','','','chuang ','xu ', + '','','','','','','','','','','','zhai ','','','','', + '','guan ','','','','','','','','','','tu ','shun ','','hu ','', + '','','','','','','dang ','','','','','','','feng ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'cheng ','','','yu ','','zhu ,chu','','qun ','','qu ','','ge ','','','','', + '','','','','','','','','gai ','','','meng ','','','','', + '','','','qu ','','','','','','','','','wan ','lei ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','dai ','','','','','','','','','','','qiu ','','', + ], + 'x288':[ + '','','','','','','','','','Tam ','','','','','','', + '','','Faan ','','','','bao ','','','','','','','','','', + '','','','','','wei ','','','','','','','hao ','','','', + '','','Giam ','Gay ','Sua ','Xoang ','','','','','','','','','','', + '','','','jiao ','','','','','','Dam ','','','nei ','','yan ','', + '','','','','','','','zha ','','','','','','','','', + '','','','yan ','','','','','Gay ','','','hun ','','mu ','','', + '','','','','','','','','','','','','Giam ','','','', + '','','','','','','','liu ','han ','','meng ','hu ','','','','', + '','','','','','','','','','','','','','','','Cay ', + 'meng ','','mu ','','hu ','Mi ','shai ,zha','','','','chao ','','','','','nian ', + '','','','','','','','','','','','','','','','', + '','','','','','chuai ','','','','','','','','','','', + '','','','','','','','hu ','meng ','pao ','','','','','','', + '','','','','Giam ','Dau ','Zeoi6','','lan ','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x289':[ + '','','','','','','','','','','','','','','','', + '','juan ','','','','','','','','','','','','','','', + '','guang ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','jie ','','','','','','','','','','','','','', + '','','','','','','','','','','','hu ','','','','', + '','','','cen ','','','','','','','','','','','','', + '','','','','','','dai ','','','','','','','','','', + 'Keo ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','fu ','','','','', + '','','','','','','','Nen ','','','','','','Lao ','','', + 'liu ','','','','','','','','','','','','','','','', + '','','','','','','Bua ','','','','','','','','','', + '','xiang ','','','','bian ','','wu ','','','','','Bong ','','','', + 'Gang ','','','Xot ','','','','','','','sao ','','','','','', + 'zu ','','','','','','','','','','','','','','','', + ], + 'x28a':[ + '','','','','','Hoat ','','','','','','','','','','', + '','','','','','','','quan ','','','chao ','he ','','','','', + 'Cuoc ','wu ','','','Khep ','','Mai ','Thep ','','','','','','','','', + 'ruan ','','','zu ','','','yu ','tu ','meng ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','mao ','','','yu ','','','', + 'zu ','','','','','','','','','','','','','xia ','','', + '','','','','','jian ','','','','','','','','','yu ','', + '','','','','','liu ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','ruan ','','','yan ','','','','','','','','','', + '','','','','Bam ','Lon ','','','Choc ','','Sat ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','Han ','','','','','', + '','','','','','Cuoc ','','','','','','','','','','', + ], + 'x28b':[ + '','','','','','','','','','Dui ','','','','','','', + 'jue ','','','','ruan ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','zhu ','','','','','','','Baang ','Bay ','','Choang ', + '','','Choang ','die ','','','','','','','','','','','','', + '','Thau ','','','','','','','','','','','','','','', + '','','','','','','','','','','Com ','','','','','', + '','','','','','','','Bung ','Hom ','Cun ','','','','','','', + 'Nhon ','Thoi ','','','yu ','','','','Ban ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','cai ','','','','','','','','','','','jiang ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Dui ','','','','','','','', + ], + 'x28c':[ + '','','qian ','','','','','','','','','','','','','ta ', + '','diao ','','','','','','','','','','','jue ','','','', + '','','','','','','','','','','','','','','','', + '','','','','Nen ','','','','yu ','','Ben ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','duan ','','','','','', + '','','','','','','dao ','','','','','','','','','', + '','','','','','','','','','','','','cen ','Dai ','Dai ','', + '','','','','jun ','','','','zhu ','','an ','','','','','', + '','','qiu ','','','','','','','','','','','','','', + '','','','','','','','','','','','feng ','wu ','jiao ','','', + 'peng ','','','','','','','','','','','','','','','', + 'niao ','','chan ','','','','nang ','','','','Gau ','','','Cat6','','', + '','','Diu ','','men ','','','','tun ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','die ','','','','','', + ], + 'x28d':[ + '','','','','','','','','','','','','','','xu ','', + '','Kuang ','','wei ','','','','die ','','','','','','','','', + '','','he ','yan ','','','Cua ','','','tu ','','','hu ','','','', + 'chu ','','','','','','','','','','men ','','','','','', + '','','','','','','','','','','zhe ','','','','','', + '','','','','','','','','','','xie ','','','ta ','','fu ', + '','','','Cua ','','','yu ','','','','xie ','','xian ','jian ','xu ','', + '','','','','','','','','','','','','','','','', + '','yan ','ai ','','','','','','','','jun ','','','','','', + '','','','','','','','lang ','','Lan ','','','','shu ','','', + '','','yu ','','','','','','','','','','hua ','wen ','','e ', + '','','','','','','','','','Gwaan ','','','','','','', + '','niu ','','','xiang ','','sa ','','','','','','','','run ','', + '','','','jian ','xu ','','','','','shu ','','','','','','', + '','','','','','xie ','','','','','','','','','','Cua ', + '','','','','','','Cua ','','','','','','','','dang ','', + ], + 'x28e':[ + '','','','','','','','','','','','','','Cup ','','', + 'reng ','','','','','','','han ','','','Ji ','gai ','','','','', + '','','','','','','','','','','','','Zhen ','','','', + 'ju ','','','','','','','','','','','','','','','', + '','','','','','','xuan ','','','','','','','','','', + '','','','','','','','','xu ','','cheng ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','zhao ','','','','','','','', + '','','','','','fu ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','duan ','','','','qiu ','','','','','','','xun ','', + '','','','','','','','','','Jiao ','','','','','','', + '','','yan ','','','','','','','','','','','xu ','','', + '','','','','','','','die ','','','','','','','','', + '','','','','','','','liu ','','','','Luong ','','','','', + '','','Xia ','','','','Geki ','','','','','','','','','', + ], + 'x28f':[ + '','','','','','','','','zhan ','cuan ','wu ','','','','jue ','', + '','','','','xun ','','','','','','Be ','','','','','', + '','','','','chen ','','','','','','','qu ','','','zhan ','', + '','jue ','','','','','','','','','','','','qu ','','meng ', + '','','pu ','','','','','','','','','','','du ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','xia ', + '','','','','','','','','','','','','','','','dai ', + '','','','','','','','','','','','','yu ','','','', + '','','','','fang ','','','','','','','','','','','', + '','','','','die ','','','','','','','','','','','', + '','','','','','','','','','','','','','','tiao ','', + '','','','','','','','','','','','','','','','wu ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','wei ','','', + '','','','','','','','','','','','','','','','', + ], + 'x290':[ + '','','','','','','','','','','','run ','','','','', + '','','','','','','','','','','','','','','','', + '','','','wei ','','','','','','','','','','','','', + '','','','Song ','','','','','','','','','','','','', + '','','','','','','','','','','','','wei ','','','', + '','','','','','','','','','','','','','','cai ','', + '','','','','','','Loi ','','','','','','','','','', + '','','','','','','Ngat ','','','','','','','','','', + 'Con ','Ngut ','','shai ','tun ','','','','','','','','','','fu ','Che ', + 'Ram ','Bung ','','','fu ','Phat ','ze ','pu ','','','','','','','pao ','Mu ', + '','','','','hua ','','','','','','','','','','','', + '','','','Rei ','','dian ','Set ','','','','','','','','','', + 'yan ','','','','','','','','','','','','','','','', + '','','','','','','','','','','xuan ','','','','','', + 'dai ','','','','','','','','','','','','','','','', + '','','','','ba ','','','dai ','','','','','','','','', + ], + 'x291':[ + '','','','','','lu ','','','','','','ru ','','','Mua ','Bung ', + '','','','','','dan ','meng ','xia ','','','','','','','','', + '','','','','','','peng ','','Guot ','','','','','','','wu ', + 'Set ','','May ','','','Nap ','Xoi ','piao ','','','','','','','ze ','', + '','','','','lu ','','','bu ','','','','','','man ','','', + '','','','','','','','','','','','Bung ','','','','', + 'nan ','','he ','','','','','','','','','','','','cen ','', + '','','','','','','','','','May ','Rau ','Zyu ','','','dan ','fu ', + '','','','','','sa ','','','','','','Rao ','','Rao ','liu ','', + 'Sam ','','','','dian ','','','','','','','','','','','', + 'Mong ','Rao ','','','','','','','','','','','Mong ','','','', + '','','','','','','','Sam ','','','','','','','Khuya ','', + '','','','','','Mu ','Sam ','hun ','','','','','','Loa ','','', + 'qu ','','','','','','','','','','','','','','','', + '','','Xanh ','','','','','','','','','','','','','fei ', + '','','','','','','','','','','','','','fei ','','', + ], + 'x292':[ + '','','Bay ','','','','','','pang ','dan ','','ai ','','','','', + '','','','','','','','mai ','','','','','','','dao ','', + '','','','','chu ','','','','','','','','wan ','','diao ','', + '','','suan ','','','','','','','mian ','','','','','','', + 'lan ','','','','','','','','','','','','','','','', + 'gan ','','','','jian ','','','','','','','','hang ','','','', + '','','','','','xuan ','','','','','','','','','','', + 'ang ','','','','','fen ','','','ju ','','','','','fu ','','qu ', + '','','','ma ','','bao ','','yu ','','','','','','mai ','','', + '','','','','jiao ','','','','','','','','','','','', + '','','','','','','','','','','','','bu ','','','', + '','','','','','zhe ','bu ','','','','jue ','xun ','','Hia ','','', + '','','bai ','','','ta ','','','nao ','yu ','','','','','','', + '','','','','','','','','Xie ','diao ','','','','','die ','fu ,fu', + '','','xuan ,yun','','yu ','','','Xie ','fu ','','','xuan ','','','','', + '','','','','','','','la ','','','gao ','','','e ','','mei ', + ], + 'x293':[ + '','','','','','','','ta ','','ta ','','','','','','', + 'ta ','','','','','','','','ta ','','','','','','','', + '','','','','','','','','','','ze ','lu ','','','xu ','', + '','','xu ','','','','','','','','','','','','','', + '','','bao ','','','','','','','','','sheng ','','','','fu ', + '','','','','','','','Bang ','','','','','','','','', + '','','Roi ','Dep ','','','','','','','','','','','','', + '','','','xu ','','','','jue ','','','','','lu ','','','', + '','','','','','','','','','','','','','','ge ','', + '','','','','','','','','','','','fu ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','wei ','','','','yu ','','bai ','','ta ','','', + '','','','','','yun ','yun ','duan ','','wei ','','','','','','', + '','','','','','','hun ','','','','','','','','bai ','yu ', + '','','','','','','','','','','','','','','','', + '','','','','yu ','','','','','juan ','jue ','','','','','', + ], + 'x294':[ + '','','','','','sa ','','','','','','','','','','', + '','','','','','','','','','','fu ','peng ','','','','', + '','zu ','','','','','','','','','','su ','','','','', + '','','','','','','zhe ','','','','','','su ','','','', + '','e ','','','','','','','guang ','','','','','ao ','','', + '','','','','','','','','','','','','','','','', + '','','','','','men ','','','','','','','','','la ','', + '','','','','yao ','','','','','xuan ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','yan ','','','','','','','','','', + '','','','','','','','','','','','','','','qiu ','', + '','','','','','','','','','','fu ','','','','wu ','', + '','','','','','','','','','','','','','','','', + '','','','','','','fu ','','','','','Ngup ','Mang ','bie ','','', + '','','','','an ','Ngok6','wu ','','','','lu ','','','','','', + '','','','','','','','','','','','jue ','','','','', + ], + 'x295':[ + 'wai ','','dun ','','jie ','','','','','','zhuan ','hang ','','','','', + '','','','','','qiu ','','Lei ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','ze ','xu ','','','','','','','','xu ','','','', + 'ao ','','','','','','','','','','','','','','','', + 'liao ','','','','','wai ','','','','','','','','','','', + 'han ','','','','dan ','','','','','','','','','Gai ','','', + '','','','','','','','','','','','','','','yuan ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','peng ','','','','', + '','','','','tun ','','','','','','','','fu ','','','', + '','','','','','','','','','','han ','','fu ','','','', + '','','','To ','','','','','','sa ','','','','','','', + 'hua ','','','','','qiu ','','','','','','','','','sa ','', + '','','','','han ','','','','','liu ','','','','','','', + '','','','','Bung6','','','','','','','','','wu ','','', + ], + 'x296':[ + 'zhao ','','','','May ','','','','','','la ','','','yuan ','','', + '','','','','','','','','','','','','','','','', + '','','','To ','yu ','','','','','','','','','','','', + 'su ','shuai ','','yu ','','','','','','su ','','yu ','','','','', + '','','','','liu ','','cheng ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','niu ','','','','Bay ','','','','', + '','','','','yu ','','','','','','','','','','','', + '','','','','Nhu ','','niu ','','','','','na ','','','','', + '','','','','','','','Qua ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','No ','Qua ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','zai ','','','mao ','','yu ','','','yu ','','', + '','','','','','','','','','','ju ','','lu ','','','', + ], + 'x297':[ + '','','','ju ','','','','Juan ','','','','','','','','', + '','','','','','','','','','','','','','','','ang ', + 'Mam ','','','','','','','','','','','','','','','', + '','','fu ','','','','','','','','','','','yan ','','', + '','','','','','','','','','','','','','','','', + '','','','','','wu ','','yu ','','','','','','','','', + 'Qiu ','','','','','su ','','','','','','','','','','', + '','','','','','','','','','','','Chan ','','jiang ','','', + '','','','','','','','','zhu ','','','','','','','', + '','','','','','','','','','','','','','','hai ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','han ', + '','yuan ,xuan','Qua ','','','','','ao ','','','','shan ','','','','', + '','yu ','','','Caat ','','','','','','','','','','meng ','', + '','','','','','','jie ','','','','','','','','huai ','', + '','','','yu ','','','chan ,jie','','','','','Nang ','','','','', + ], + 'x298':[ + '','','','','','','','','','','','','','','','', + '','Ding ','','','Mao ','','','','','','','','','','','', + 'Cui ','','','','','','','Guc ','','','','','','','','wei ', + '','Chui ','','Chui ','Cui ','Choi ','','fu ','','','','','','','','', + '','','','yu ','','','','','','','','Thom ','','','','', + '','','','','hai ','peng ','','','','','','','','','','bie ', + '','','','','','','','','','','','fan ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','wan ','','','','','','','','wen ','','','', + 'zhe ','','','','ban ','bu ','','','','','','ge ','','','liu ','', + '','','','','','','Giong ','','','','hu ','','','','','', + 'fu ','','Sai ','qu ','','','yu ','','','jiu ','','shu ','','','','fu ', + '','','','','','','','','','','xu ','','','','','', + '','Ngon ','','','','','','','','','','','fu ','bu ','','', + '','','','','','','','','','zhe ','','','','','tu ','', + '','lu ','','','','','','','fu ','','','','','','','', + ], + 'x299':[ + '','','','','','','','','','','xian ,jian','kun ','','','','', + '','','','','','','','','','cheng ','','','','','tan ','', + 'xie ','','','duan ','','','','','','e ','','','','','','', + '','','','','','','','','','','yu ','','','','','', + '','','','','','','','zhan ','','','','Au6','qia ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','yu ','','', + '','','','','','','','','','','','','','tu ','','zu ', + '','','','','','','','','','bie ','','','','','','', + '','','','','','','','','','','','','','','','', + 'bang ','yu ','Jyu ','','','','','','','','','','','','','', + '','','','','','','','','','xian ','meng ','','','','','', + '','','','','','','','cai ','du ','','','','','','','jue ', + '','','ju ','','','','','','qu ','','','','','','','', + '','jue ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x29a':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','yu ','','yu ','','','ba ','','','', + 'ya ','','','','','','','','','fan ','','','','Que ','','', + '','','ma ','','','','','','','','','','Kheo ','','','', + '','','','','','','','Song ','','','','','','Peng ','','', + '','','','','','','Song ','','','','','','','','','', + 'zu ','leng ','','','','','','dan ','','','Xuong ','Xuong ','','','du ','bian ', + '','qia ','he ','','','','yan ','','','','','teng ','','','','Hom ', + '','','','hai ','','','','','','xu ','','','','','','', + '','','','','','','','Jue ','','','','pu ','','','Sun ','', + '','','','','','','','','','','','','','','','', + '','','','','yan ','So ','','','','','','','','Cut ','','', + 'kai ','mao ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','sao ','','','','','','','','','', + '','','','','ju ','','','','','cheng ','','','','','','', + ], + 'x29b':[ + '','','','','','','','','','','','','','','Zam ','', + '','Chom ','','','','','','','','','','','ju ','','','zha ', + '','','','','','','','','','','','','','','','', + '','dao ','','','','','','','','','','','','','','', + '','','','','','','','','','','ju ','','','','','', + '','','','','','','','','','','','','Xui ','','','dao ', + '','','an ','','','han ','','','','','','','','','','', + '','','','','','Quan ','Rau ','','','','fu ','','','','','', + '','qia ','','','','na ','','','','','','','','','','', + '','','','','Quan ','','','','','','','','','ya ','','', + '','','','','','','','','','','','','','Ria ','','', + '','','','','','','','','','','','','','','','', + '','Rau ','','','zun ','','nao ','','','','','','','','cheng ','', + '','','','','','','','','jiao ','','','yao ','','','can ','', + '','','','','','','','','','','','','','Ban ','','Xoam ', + '','pu ','zhuang ','','','','','','','','','','','la ','','', + ], + 'x29c':[ + '','','','zhan ','','','','','Nheo ','','','','','bian ','','', + '','','','','','','','','','','','','','','','', + '','','','','ju ','','','','jue ','','yu ','','','','','hu ', + '','','','xie ','er ','','','','','','','','','','','', + '','','','','','','','','','','er ,xian','','yu ','hu ','','', + '','','','','','','','','','ku ','','','','','jiao ','', + '','','','','','','','','ru ','','','','','','','', + '','yu ','','','','','','','','','','','','','','', + '','','','','','','','','','','hao ','','','niu ','','hua ', + '','','','','','','','','','','','','','','','', + 'zhu ','Coi ','','','','Troi ','','','','','','','zhu ','','','', + '','','zu ','','','','','','','','','','','','yu ','', + '','','','','','','lai ','','','','Ranh ','','wu ','','fu ','zhuan ', + '','','su ','','yao ','','','','','','','','','','','', + '','','yan ','','','zhu ','','','','','','','','','','', + '','','','Troi ','','ju ','','','','','','','','','','', + ], + 'x29d':[ + '','','','','','','','shai ','','yun ','','','','','','', + '','','jiang ','','','','','','ju ','','Troi ','','','teng ','wei ','', + '','gu ','','','liao ','','','','','','','','','','','', + '','','meng ','cha ','','','','','','qu ','','lei ','','','','', + '','','','Troi ','','qu ','','','','','','Gyo ','','qiu ','','hua ', + '','','','','','','','','','','du ','','','Chai ','','', + '','','','','','','mu ','','','','','','hu ','','','', + '','','','','','','','','','fu ','','','','Tom ','','', + '','','zhu ','','zhu ','Ci ','','','','Pou ','','','','','','', + '','','','','','','mu ','','','','','','','','','Buop ', + '','meng ','','','','','guai ','jiu ','','mu ','','','Si ','wu ','','ru ', + '','zha ','','','','','','','','','','','','','','', + '','','xie ','','jiang ','','','Hung ','','','Thu ','','','','','', + 'ju ','','','','','Luon ','bu ','','','','','','','','','', + '','','','','','','','','','','','','','jiang ','','', + 'xun ','','','','','','Mang ','','','','','qia ','','','','', + ], + 'x29e':[ + '','','','tu ','hua ','','','','','','','','','','','', + 'ru ','','','','','','','','','','','','','','','', + '','','','','','','','','Yi ','','','','','','Bong ','Chuoi ', + 'Go ','','','','','','','','Thia ','','','','','','ye ','', + '','','','','hai ','','','','','','','','','','an ','ba ', + '','han ','','','','','','','','','','','','','','nai ', + '','','','','Thu ','','','','','Nau ','','Tep ','','Chay ','Mu ','Tuoi ', + '','chu ','','','','','','','','','ge ','','han ','','na ','ge ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','Bon ','','Trau ','','','','','Bong ','','Bon ','xie ','','','','Soc ', + 'yu ,wu','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Mam ','','Sop ','Dua ','','Tram ','','bu ','jian ','','wu ','Tram ','','zhuan ','','Vay ', + '','','','','','','','','','','','','','','','', + '','','','','','die ','','','','','Vay ','Leo ','','','','', + ], + 'x29f':[ + 'Vay ','','','','','','','','Ao ','','','','','','','', + '','','','','','','','','','ge ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','xu ','','','Sau ','Lui ','','','','wei ','', + '','','','','','','Ruoc ','','','','','','','','','', + '','','','','Sau ','Luon ','','','','qu ','','','','','','', + '','','','','','','','ba ','Nheo ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','han ,yan','','', + '','bao ','','','','','','xun ','','','','','','','','', + '','','','','','','jie ','','','','','hu ','','','','fu ', + '','','mao ','','','','','','','','','','','','','', + '','','','bao ','','','','','Mao ','','Khuou ','','','ju ','Caa ','qu ', + '','','','','','qu ','','','Khuou ','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2a0':[ + '','','','','Chim ','','','','','','','','','','','', + '','','Shi ','','','','','','jiang ','','','','','','','', + 'xun ','','','ju ','','','','','','','','','','','','', + '','','','','','','','','','','fu ','','','','jie ','', + 'yu ','','','','Ket ','Sac ','Hau ','Song ','zhuang ','','','cheng ','','jie ','','chen ', + '','','','','','','qu ','','','','','','','','','', + 'jue ','yan ','','','','ju ','','','','','','','','','xiu ','', + '','','','','Coc ','Coc ','','','','','','','','su ','','', + '','','','','','','','','','yu ','','fu ','ta ','','','', + '','','hu ','','','','','','','','','','mei ','','','', + '','','','','','','','','','','','','','','','', + '','','','Cun ','','yu ','','','','','','','','pen ','fu ','', + '','','liu ','','','','','','jie ','','','','','yu ','yu ','Mei ', + '','mao ','','fu ','','','','','','','','jian ','','','','', + '','','','','','','','','','','','','','','','', + '','Hau ','','','Ga ','','','','','','','','','','','Ge ', + ], + 'x2a1':[ + '','','xia ','','','Set ','','','','','qu ','','','','ge ','', + '','su ','','','','','','','','','','','','','','', + '','','','','','Cut ','','','','','','','','','hu ,gu','', + '','','','mai ','','','','','','','','','','','','', + '','','','','su ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','Cuoc ','Choi ','Ri ','Sam ','','','','Tu ','','', + '','','','','','','','','jie ','','','','','','','', + '','','qu ','','','','','','','','','xie ','','','','', + '','','','','','','','','','','','','','','','', + 'fu ','','','','','Khuou ','Tu ','','','','','','','','','', + 'ya ','liu ','','','','','can ','64272.110,chu ','','','','','','','','jian ', + '','','','','','','chu ,du','','ai ','','','Cui ','','','Quam ','', + '','xun ','','','','','','','','','','','','yu ','','', + '','','','','','','','','','Ngan ','','Cui ','','cai ','','liu ', + '','','jie ','','','','','','','la ','','','','','','', + ], + 'x2a2':[ + '','','','','','','','','lai ','','he ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','jue ','','','','guan ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Muoi ','','tan ','','En ','','','','','','kan ', + '','bian ','','','Muoi ','','','','','','','','','','','gan ', + '','','','','','Mam ','','gan ,tan','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','xiao ','','zhu ','','yu ','','','','', + '','jian ','','','','','','','','yu ','','','','zu ','','', + 'nuan ','','','','','','','','','','','','','su ','','', + '','pu ','','','','','','','','','','','','','yu ','', + '','','','','','','','','','','','','','','','', + ], + 'x2a3':[ + '','','','','','na ','qu ','','','','','tun ','','','','', + '','','','ku ','su ','','','','','','','','','','','ze ', + '','','','ge ','','','','jie ','','','tiao ','','','','','', + '','','','','','','shu ','','','','','','','hun ','','nie ', + '','jun ','hu ','','lu ','','','','chao ','','','','','','','fu ', + '','','','','','','','','','','','','','yun ','','', + '','','','','','','','xuan ','','','','','','','','', + '','','','','','','shan ','','Qu ','du ','','sao ','','','','kuang ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','liu ','','','','','','','','','','mei ','','', + '','','','','tun ','kang ','tun ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','heng ','','','','','','Huang ','','','','','','', + '','','','','','','','','','','kuang ','piao ','','','','', + '','','','hu ','','','bao ','','','','','hu ','','','','', + ], + 'x2a4':[ + 'Naa ','','','','','','bie ','','','','','','','','','', + '','','','','','','','','','','','','','dai ,tai','du ','', + '','','','','','tai ','','shu ','','','','','','','su ','', + '','','','','','','','','','','','','','','','', + '','','cha ','','lu ','','yu ','','yan ','','qiao ','','yu ','','','tu ', + '','Ngam ','tun ','','','','','','','','','','','yu ','','', + '','','','','','','','die ','cha ','dian ','','','','','','', + '','','','','','','','wai ','','','','','','zhai ','','', + '','','','','','','','','','','','','','','','lu ', + '','','','','','','','Tham ','','','','','ma ','','','', + '','','','','','','','','','','mai ','','Nung ','','','', + '','','','','','','','','','','','','','','dan ','teng ', + '','','','','','','','','','','yu ','','','','','', + '','','','','','','','','','','','','','','','', + '','cu ','','','','','','','','','','Sam ','','','','', + 'cu ','','','','','','','','','','','','','','','', + ], + 'x2a5':[ + '','','Ding ','','','','','','','','','','','peng ','','', + '','','','','','','','','','','','','','','','', + 'Trong ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','hu ','','','','','','', + '','','','','','','','','','','','','','cu ','jun ','', + '','','','','','','','','er ','','','','','ai ','hu ','', + '','hu ','','','','','','','','','','','','','','', + '','','','','jiao ','','','','pu ','','','jie ','lu ','','','', + 'yao ,ya','','','','','','','','','Hou ','','qiu ','jue ','','','', + '','','','','','','','','','xu ','','','','Ngui ','','', + '','','','','','','su ','liao ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','pa ','','','','','','','','','na ','','', + '','','','','','','zhan ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2a6':[ + '','Kap6','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','zu ','','','zhan ','','','','','', + '','','Ji ','','','Rang ','','','','he ','qia ','','','','','', + '','','','','','','','','hu ','','yan ','','','','','', + '','','','','','','','','','','','Nak ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','jue ','','','','','','','','','','', + '','','','','','','','','','','Trong ','','','','','', + '','','','','','zhe ','','','','Gwi ','','','gan ','','','cu ', + '','','','','','','','','','zhu ','','','','','','', + 'xiao ','','','','','Rua ','','Rua ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2a7':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2a8':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Bai ','','','','','','','Zhan ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Luan ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2aa':[ + '','','','','','','','','','','Song ','','','','','', + '','','','','','','','Jue ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Yong ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2ae':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','Nu ','','','','','','', + '','','','','','','','','','','','','','','','', + 'Cong ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2af':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Xian ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2b0':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','Li ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Fei ','','','','','','','', + '','','','','','','','','','Su ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','Kou ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2b1':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Chi ','','','','','','','', + '','','','','','','','','Xun ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2b2':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Qia ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Gong ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2b3':[ + 'Ji ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Luo ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','Yi ','','','','','','', + '','','Nao ','','','','','','','','','','','','','', + 'Xi ','','Xiao ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','Jiao ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2b4':[ + '','','','','Yue ','','Kuai ','','','Ling ','','','','','','', + 'Ni ','','','Bu ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','Han ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','Fu ','','Cong ','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2b5':[ + '','','','','','','','','','','','','','','Jue ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Duo ','','','','','','','Su ','','','','','','','Huang ','', + '','','','','','','','','','','','','','','','', + ], + 'x2b6':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Han ','Ai ','','','','Ti ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Xu ','Gong ','','','','','','', + '','','Ping ','','Hui ','Shi ','','','','Pu ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','Zhi ','','','Jue ','', + '','','Ning ','','','','','','','','','','','','','', + '','','','','','','Chi ','','Ti ','','','','','','','', + ], + 'x2f8':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Gai ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2f9':[ + '','','','','','','','Baan6','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ] +} diff --git a/ebook_converter/ebooks/unihandecode/jadecoder.py b/ebook_converter/ebooks/unihandecode/jadecoder.py new file mode 100644 index 0000000..d6318c2 --- /dev/null +++ b/ebook_converter/ebooks/unihandecode/jadecoder.py @@ -0,0 +1,43 @@ +# coding:utf-8 +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL 3' +__copyright__ = '2010, Hiroshi Miura ' +__docformat__ = 'restructuredtext en' + +''' +Decode unicode text to an ASCII representation of the text for Japanese. + Translate unicode string to ASCII roman string. + +API is based on the python unidecode, +which is based on Ruby gem (http://rubyforge.org/projects/unidecode/) +and perl module Text::Unidecode +(http://search.cpan.org/~sburke/Text-Unidecode-0.04/). + +This functionality is owned by Kakasi Japanese processing engine. + +Copyright (c) 2010 Hiroshi Miura +''' + +import re +from calibre.ebooks.unihandecode.unidecoder import Unidecoder +from calibre.ebooks.unihandecode.unicodepoints import CODEPOINTS +from calibre.ebooks.unihandecode.jacodepoints import CODEPOINTS as JACODES +from calibre.ebooks.unihandecode.pykakasi.kakasi import kakasi + + +class Jadecoder(Unidecoder): + kakasi = None + codepoints = {} + + def __init__(self): + self.codepoints = CODEPOINTS + self.codepoints.update(JACODES) + self.kakasi = kakasi() + + def decode(self, text): + try: + result=self.kakasi.do(text) + return re.sub('[^\x00-\x7f]', lambda x: self.replace_point(x.group()),result) + except: + return re.sub('[^\x00-\x7f]', lambda x: self.replace_point(x.group()),text) diff --git a/ebook_converter/ebooks/unihandecode/krcodepoints.py b/ebook_converter/ebooks/unihandecode/krcodepoints.py new file mode 100644 index 0000000..bca8e3f --- /dev/null +++ b/ebook_converter/ebooks/unihandecode/krcodepoints.py @@ -0,0 +1,5252 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL 3' +__copyright__ = '2010 Hiroshi Miura ' +__docformat__ = 'restructuredtext en' + +''' +Unicode code point dictionary. +Based on Unicode.org Unihan database. +''' + +CODEPOINTS = { + 'x34':[ + 'Qiu ','Tian ','','','Kua ','Wu ','Yin ','','','','','','Si ','','','', + '','','','','','','Ye ','','','','','','Chou ','','','', + '','Nuo ','','','Qiu ','','','','Xu ','Xing ','','Xiong ','Liu ','Lin ','Xiang ','Yong ', + 'Xin ','Zhen ','Dai ','Wu ','Pan ','','','Ma ','Qian ','Yi ','Zhong ','N ','Cheng ','Fung ','','', + '','Zhuo ','Fang ','Ao ','Wu ','Zuo ','','Zhou ','Dong ','Su ','Yi ','Jiong ','Wang ','Lei ','Nao ','Zhu ', + 'Suk ','','','','Xu ','','','Saan ','Jie ','Die ','Nuo ','Su ','Yi ','Long ','Ying ','Beng ', + '','','','Lan ','Miao ','Yi ','Li ','Ji ','Yu ','Luo ','Chai ','Nom ','','','Hun ','Xu ', + 'Hui ','Rao ','','Zhou ','Caam ','Han ','Xi ','Tai ','Ai ','Hui ','Jun ','Ma ','Lue ','Tang ','Xiao ','Tiao ', + 'Zha ','Yu ','Ku ','Er ','Nang ','Qi ','Chi ','Mu ','Han ','Tang ','Se ','Si ','Qiong ','Lei ','Sa ','', + '','Hui ','Pu ','Ta ','Shu ','Zoeng ','Ou ','Tai ','','Mian ','Wen ','Diao ','Yu ','Mie ','Jun ','Niao ', + 'Xie ','You ','','','She ','Fung ','Lei ','Li ','Sin ','Luo ','Sek ','Ji ','','Kwaan ','','', + 'Quan ','','Cai ','Liang ','Gu ','Mao ','Gung ','Gua ','Sui ','Din ','','Mao ','Man ','Hyun ','Shi ','Li ', + '','Wang ','Kou ','Chui ','Zhen ','Ding ','','','Bing ','Huan ','Dong ','Gong ','Cang ','','Lian ','Jiong ', + 'Lu ','Xing ','','Nan ','Xie ','','Bi ','Jie ','Su ','Hung ','Geoi6','Gung ','You ','Xing ','Qi ','Phay ', + 'Dian ','Fu ','Luo ','Qia ','Jie ','Tong ','Bak ','Yan ','Ci ','Fan ','Lang ','','Fu ','He ','Diu ','Li ', + 'Hua ','Tou ','Pian ','Dai ','Jun ','E ','Qie ','Yi ','Jue ','Rui ','Jian ','Gong ','Chi ','Chong ','Chi ','', + ], + 'x35':[ + 'Lue ','Daang ','Lin ','Jue ','Su ','Xiao ','Chan ','Put ','','Zhu ','Dan ','Jian ','Zhou ','Duo ','Xie ','Li ', + 'Cim ','Chi ','Xi ','Jian ','','Ji ','','Fei ','Chu ','Bang ','Kou ','','Ba ','Liang ','Kuai ','', + 'He ','Bit ','Jue ','Lei ','Shen ','Pi ','Yang ','Lu ','Bei ','E ','Lu ','','Coek ','Che ','Nuo ','Suan ', + 'Heng ','Yu ','','Gui ','Yi ','Xian ','Gong ','Lou ','Cam ','Le ','Shi ','Pei ','Sun ','Yao ','Jie ','Zou ', + '','Que ','Yin ','Him ','Zhi ','Jia ','Hu ','La ','Hou ','Ke ','Bou ','Jing ','Ai ','Deoi ','E ','Chu ', + 'Xie ','Chu ','Wei ','','Teng ','Huan ','Su ','You ','Caam ','Jun ','Zhao ','Xu ','Shi ','','Caat ','Kui ', + 'Soeng ','He ','Gai ','Yan ','Qiu ','Yi ','Hua ','Si ','Fan ','Zhang ','Dan ','Fang ','Song ','Ao ','Fu ','Nei ', + 'He ','You ','Hua ','Hung ','Chen ','Guo ','Ng ','Hua ','Li ','Fa ','Hao ','Pou ','Dung6','Si ','','', + 'Le ','Lin ','Yi ','Hou ','Zaau ','Xu ','Qu ','Er ','','','','','','','','Nei ', + 'Wei ','Xie ','Ti ','Hong ','Tun ','Bo ','Nie ','Yin ','San ','','','','','','Wai ','Shou ', + 'Ba ','Ye ','Ji ','Tou ','Han ','Jiong ','Dong ','Wen ','Lu ','Sou ','Guo ','Ling ','','Tian ','Lun ','', + '','','','','','ge ','Ye ','Shi ','Xue ','Fen ','Chun ','Rou ','Duo ','Ze ','E ','Xie ', + 'Zaau ','E ','Sheng ','Wen ','Man ','Hu ','Ge ','Xia ','Man ','Bi ','Ji ','Hou ','Zhi ','','Gaa ','', + '','Bai ','Ai ','Ci ','Hin ','Gou ','Dan ','Bai ','Bo ','Na ','Li ','Xiao ','Xiu ','','','', + '','','Dong ','Ti ','Cu ','Kuo ','Lao ','Zhi ','Ai ','Xi ','','Qie ','Zaa ','Hei ','','', + 'Chu ','Ji ','Huo ','Ta ','Yan ','Xu ','Put ','Sai ','','','','Go6','Ye ','Xiang ','Heoi ','Xia ', + ], + 'x36':[ + 'Zuo ','Yi ','Ci ','','','Xian ','Tai ','Rong ','Yi ','Zhi ','Yi ','Xian ','Ju ','Ji ','Han ','', + 'Pao ','Li ','','Lan ','Can ','Han ','Yan ','','','Yan ','Han ','Haam ','Chi ','Nian ','Huo ','', + 'Bi ','Xia ','Weng ','Xuan ','Waan ','You ','Qin ','Xu ','Nei ','Bi ','Hao ','Jing ','Ao ','Ao ','','', + 'Zam ','Taan ','Ju ','Zaau ','Zuo ','Bu ','Jie ','Ai ','Zang ','Ci ','Fa ','Zaan ','','','','Nie ', + 'Liu ','Mang ','Dui ','Bong ','Bi ','Bao ','','Chu ','Han ','Tian ','Chang ','','','Do ','Wai ','Fu ', + 'Duo ','Yu ','Ye ','Kui ','Han ','Kuai ','','Kuai ','Ziu ','Long ','Sing ','Bu ','Chi ','Xie ','Nie ','Lang ', + 'Yi ','Zung ','Man ','Zhang ','Xia ','Gun ','','','Ji ','Liao ','Ye ','Ji ','Yin ','','Da ','Yi ', + 'Xie ','Hao ','Yong ','Han ','Chan ','Tai ','Tang ','Zhi ','Bao ','Meng ','Gui ','Chan ','Lei ','','Xi ','', + 'Hei ','Qiao ','Rang ','Yun ','','Long ','Fu ','Zuk ','','Gu ','Hoi ','Diu ','Hua ','Guo ','','Gao ', + 'Tao ','','Shan ','Lai ','Nie ','Fu ','Gao ','Qie ','Ban ','Gaa ','','Xi ','Xu ','Kui ','Meng ','Chuo ', + 'Hiu ','Ji ','Nu ','Xiao ','Yi ','Yu ','Yi ','Yan ','','Ran ','Hao ','Sha ','Gwan ','You ','Daam ','Xin ', + 'Bi ','Zaau ','Dian ','O ','Bu ','Dung ','Si ','Er ','Si ','Mao ','Yun ','Gei ','Naau ','Qiao ','','Pao ', + '','Ping ','Nuo ','Jie ','Zi ','Er ','Duo ','','','','Duo ','','','Qie ','Leoi ','Ou ', + 'Sou ','Can ','Dou ','Ci ','Peng ','Yi ','So ','Zuo ','Po ','Qie ','Tong ','Xin ','You ','Bei ','Long ','', + '','','','','','Ta ','Lan ','Man ','Qiang ','Zhou ','Yan ','Sek ','Lu ','Sik ','Sao ','Mian ', + 'Fan ','Rui ','Fa ','Cha ','Nao ','Cing ','Chou ','Gai ','Shu ','Pian ','Aam ','Kui ','Sha ','Saan ','Xian ','Zhi ', + ], + 'x37':[ + '','','Fung ','Lian ','Xun ','Xu ','Mi ','Hui ','Mu ','Zung ','Pang ','Yi ','Gou ','Tang ','Qi ','Yun ', + 'Shu ','Fu ','Yi ','Da ','','Lian ','Cao ','Can ','Ju ','Lu ','Su ','Nen ','Ao ','An ','Qian ','', + 'Ceoi ','Sung ','','Ran ','Shen ','Mai ','Han ','Yue ','Er ','Ao ','Xian ','Ma ','','','Lan ','Hei ', + 'Yue ','Dong ','Weng ','Huai ','Meng ','Niao ','Wan ','Mi ','Nie ','Qu ','Zan ','Lian ','Zhi ','Zi ','Hai ','Xu ', + 'Hao ','Xun ','Zhi ','Fan ','Chun ','Gou ','','Chun ','Luan ','Zhu ','Shou ','Liao ','Jie ','Xie ','Ding ','Jie ', + 'Rong ','Mang ','Geoi ','Ge ','Yao ','Ning ','Yi ','Lang ','Yong ','Yin ','','Su ','Sik ','Lin ','Ya ','Mao ', + 'Ming ','Zui ','Yu ','Ye ','Gou ','Mi ','Jun ','Wen ','','Hoi ','Dian ','Long ','','Xing ','Cui ','Qiao ', + 'Mian ','Meng ','Qin ','','Wan ','De ','Ai ','','Bian ','Nou ','Lian ','Jin ','Zyu ','Chui ','Zuo ','Bo ', + 'Fui ','Yao ','Tui ','Ji ','Aam ','Guo ','Ji ','Wei ','Bui6','Zaat ','Xu ','Nian ','Yun ','','Ba ','Zhe ', + 'Ju ','Wei ','Xi ','Qi ','Yi ','Xie ','Ci ','Qiu ','Tun ','Niao ','Qi ','Ji ','Teoi ','','','Dian ', + 'Lao ','Zhan ','Zi ','Fan ','Yin ','Cen ','Ji ','Hui ','Zai ','Lan ','Nao ','Ju ','Qin ','Dai ','Shutsu ','Jie ', + 'Xu ','Cung ','Yong ','Dou ','Chi ','Tou ','Min ','Huang ','Sui ','Ke ','Zu ','Hao ','Cheng ','Xue ','Ni ','Chi ', + 'Lian ','An ','Chi ','Si ','Xiang ','Yang ','Hua ','Cuo ','Qiu ','Lao ','Fu ','Dui ','Mang ','Lang ','Tuo ','Han ', + 'Mang ','Bo ','Kwan ','Qi ','Han ','','Long ','Ban ','Tiao ','Lao ','Qi ','Zan ','Mi ','Pei ','Zhan ','Xiang ', + 'Gang ','','Qi ','','Lu ','Caam ','Yun ','E ','Quan ','Min ','Wei ','Quan ','Shu ','Min ','Daat6','', + 'Ming ','Yao ','Jue ','Li ','Kuai ','Gang ','Yuan ','Da ','Gou ','Lao ','Lou ','Qian ','Ao ','Biao ','Zung ','Mang ', + ], + 'x38':[ + 'Dao ','Caam ','Ao ','','Xi ','Fu ','Daan ','Jiu ','Run ','Tong ','Qu ','E ','Hei ','Ji ','Ji ','Hua ', + 'Jiao ','Zui ','Biao ','Meng ','Bai ','Wei ','Ji ','Ao ','Yu ','Hao ','Dui ','Wo ','Ni ','Cuan ','','Li ', + 'Lu ','Niao ','Hua ','Lai ','','Lu ','Fung ','Mi ','Yu ','Fong ','Ju ','','','Zhan ','Pang ','Yi ', + '','Ji ','Bi ','','Ren ','Fong ','Fan ','Ge ','Ku ','Jie ','Miao ','Hei ','Si ','Tong ','Zyun ','Ci ', + 'Bi ','Kai ','Li ','Fong ','Sun ','Nuo ','Fong ','Ji ','Men ','Xian ','Qia ','E ','Mao ','','Saam ','Tou ', + 'Zin ','Qiao ','Zeon ','Kwaan ','Wu ','Zing ','Chuang ','Ti ','Lian ','Bi ','Haat6','Mang ','Xue ','Feng ','Lei ','Zou ', + 'Zheng ','Chu ','Man ','Long ','','Yin ','Baan ','Zheng ','Qian ','Luan ','Nie ','Yi ','','Ji ','Ji ','Zhai ', + 'Yu ','Jiu ','Huan ','Di ','Lup ','Ling ','Ji ','Ben ','Zha ','Ci ','Dan ','Liao ','Yi ','Zhao ','Xian ','Chi ', + 'Ci ','Chi ','Yan ','Lang ','Dou ','Long ','Chan ','','Tui ','Cha ','Ai ','Chi ','','Ying ','Cha ','Tou ', + '','Tui ','Cha ','Yao ','Zong ','Zung ','Pun ','Qiao ','Lian ','Qin ','Lu ','Yan ','Kong ','Sou ','Yi ','Chan ', + 'Jiong ','Jiang ','','Jing ','','Dong ','Go ','Juan ','Han ','Di ','Wu ','','Hong ','Tou ','Chi ','Min ', + 'Bi ','','Xun ','Lu ','Sai ','She ','Bi ','','Bi ','','Xian ','Wei ','Bie ','Er ','Juan ','', + 'Zhen ','Bei ','Yi ','Yu ','Qu ','Zan ','Mi ','Ni ','Si ','Gung ','','Daan ','Shan ','Tai ','Mu ','Jing ', + 'Bian ','Rong ','Ceng ','Can ','Ding ','','','','Keoi ','Di ','Tong ','Ta ','Xing ','Sung ','Duo ','Xi ', + 'Tong ','','Ti ','Shan ','Jian ','Zhi ','Wai ','Yin ','','','Huan ','Zhong ','Qi ','Zung ','','Xie ', + 'Xie ','Ze ','Wei ','','','Ta ','Zhan ','Ning ','','','Sam ','Yi ','Ren ','Shu ','Cha ','Zhuo ', + ], + 'x39':[ + '','Mian ','Ji ','Fang ','Pei ','Ai ','Fan ','Ao ','Qin ','Qia ','Xiao ','Fan ','Gaam ','Qiao ','Go ','Tong ', + 'Tip ','You ','Gou ','Ben ','Fu ','Chu ','Zhu ','','Chu ','Zaan ','Hang ','Nin ','Jue ','Cung ','Cha ','Kong ', + 'Lie ','Li ','Xu ','Paang ','Yu ','Hai ','Li ','Hou ','Gong ','Ke ','Yuan ','De ','Hui ','Giu ','Kuang ','Jiong ', + 'Zan ','Fu ','Qie ','Bei ','Xi ','Ci ','Pang ','Haam ','Xi ','Qiu ','Huang ','Nan ','','Chou ','San ','Jim ', + 'De ','De ','Te ','Men ','Ling ','Shou ','Dian ','Can ','Die ','Che ','Peng ','Zi ','Ju ','Ji ','Lai ','Tian ', + 'Yuan ','Zaau ','Cai ','Qi ','Yu ','Lian ','Cung ','','','','Yu ','Ji ','Wei ','Mi ','Cui ','Xie ', + 'Xu ','Xi ','Qiu ','Hui ','Ging ','Yu ','Qie ','Shun ','Chui ','Duo ','Lou ','Deon ','Pang ','Tai ','Zhou ','Yin ', + 'Sou ','Fei ','Shen ','Yuan ','Yi ','Hun ','Se ','Ye ','Min ','Fen ','He ','','Yin ','Ce ','Ni ','Ao ', + 'Feng ','Lian ','Chang ','Chan ','Ma ','Di ','Hu ','Lu ','','Yi ','Hua ','Caa ','Tui ','E ','Hua ','Sun ', + 'Ni ','Lian ','Li ','Xian ','Yan ','Long ','Men ','Jian ','Gik ','','Bian ','Yu ','Huo ','Miao ','Chou ','Hai ', + '','Le ','Jie ','Wei ','Yi ','Huan ','He ','Can ','Lan ','Yin ','Xie ','Zaat ','Luo ','Ling ','Qian ','Huo ', + 'Cim ','Wo ','Zoi ','','Ge ','Zyu ','Die ','Yong ','Ji ','Ang ','Ru ','Xi ','Shuang ','Xu ','Yi ','Hu ', + 'Ji ','Qu ','Tian ','Sau ','Qian ','Mu ','Gaan ','Mao ','Yin ','Gai ','Ba ','Xian ','Mao ','Fang ','Ya ','Gong ', + 'Song ','Wei ','Xue ','Gwaa ','Guai ','Jiu ','E ','Zi ','Cui ','Bi ','Wa ','Hin ','Lie ','Gaa ','','Kuai ', + '','Hai ','Zaan ','Zhu ','Chong ','Xian ','Xuan ','So ','Qiu ','Pei ','Gui ','Er ','Gong ','Qiong ','Bak6','Lao ', + 'Li ','Chen ','San ','Bo ','Wo ','Pou ','Hang ','Duo ','Paang ','Te ','Ta ','Zhi ','Biao ','Gu ','Hot ','Coeng ', + ], + 'x3a':[ + 'Bing ','Zhi ','Dong ','Cheng ','Zhao ','Nei ','Lin ','Po ','Ji ','Min ','Wei ','Che ','Gou ','Bong ','Ru ','Taan ', + 'Bu ','Zung ','Kui ','Lao ','Han ','Ying ','Zhi ','Jie ','Xing ','Xie ','Xun ','Shan ','Qian ','Xie ','Su ','Hai ', + 'Mi ','Hun ','Nang ','','Hui ','Na ','Song ','Ben ','Liu ','Jie ','Huang ','Lan ','','Hu ','Dou ','Huo ', + 'Ge ','Yao ','Ce ','Gui ','Jian ','Jian ','Chou ','Jin ','Ma ','Hui ','Men ','Can ','Lue ','Pi ','Yang ','Ju ', + 'Ju ','Que ','','','Shai ','Cau ','Jiu ','Hua ','Xian ','Xie ','Syun ','Su ','Fei ','Ce ','Ye ','', + '','','Qin ','Hui ','Tun ','Ling ','Qiang ','Xi ','Yi ','Nim ','Meng ','Tuan ','Lan ','Hao ','Ci ','Zhai ', + 'Piao ','Luo ','Mi ','Buk ','Fu ','Cam ','Xie ','Bo ','Hui ','Qi ','Xie ','','Hei ','Bo ','Qian ','Ban ', + 'Jiao ','Jue ','Kun ','Song ','Ju ','E ','Nie ','','Die ','Die ','Pei ','Gui ','Zi ','Qi ','Chui ','Gwaat6', + 'Yu ','Qin ','Faat ','Ke ','Fu ','Gaang ','Di ','Xian ','Gui ','He ','Qun ','Han ','Tong ','Bo ','Shan ','Bi ', + 'Lu ','Ye ','Ni ','Chuai ','San ','Diao ','Lu ','Tou ','Lian ','Ke ','San ','Zhen ','Chuai ','Lian ','Mao ','Deon ', + 'Qian ','Ke ','Shao ','Qiao ','Bi ','Zaa ','Yin ','Kaap ','Shan ','Su ','Sa ','Rui ','Zhuo ','Lu ','Ling ','Cha ', + 'Zaai ','Huan ','','','Jia ','Ban ','Hu ','Dou ','Caam ','Lou ','','Juan ','Ke ','Suo ','Ge ','Zhe ', + 'Ding ','Duan ','Zhu ','Yan ','Pang ','Cha ','','','','','Yi ','Zin ','','You ','Gun ','Yao ', + 'Yao ','Shi ','Gong ','Qi ','Gen ','Gwong ','','Hou ','Mi ','Fu ','Hu ','Guang ','Dan ','Dai ','Tou ','Yan ', + '','Dung ','Qu ','','Chang ','Ming ','Tou ','Bao ','On ','Ceon ','Zung ','Xian ','','','','Mao ', + 'Lang ','Nan ','Pei ','Chen ','Hau ','Fei ','Cou ','Gei ','Qie ','Dai ','Sik ','Kun ','Die ','Lu ','Thung ','', + ], + 'x3b':[ + '','Caap ','Yu ','Tai ','Chan ','Man ','Mian ','Huan ','Wan ','Nuan ','Huan ','Hou ','Jing ','Bo ','Xian ','Li ', + 'Jin ','','Mang ','Piao ','Hao ','Yang ','','Xian ','Su ','Wei ','Che ','Kap ','Jin ','Ceng ','He ','', + 'Shai ','Ling ','Fui ','Dui ','Zaap ','Pu ','Yue ','Bo ','','Hui ','Die ','Yan ','Ju ','Jiao ','Kuai ','Lie ', + 'Yu ','Ti ','Tim ','Wu ','Hong ','Xiao ','Hao ','','Tiu ','Zaang ','','Huang ','Fu ','','','Dun ', + '','Reng ','Jiao ','Gong ','Xin ','','','Yuan ','Jue ','Hua ','Sik ','Bang ','Mou ','Cat ','Gong ','Wei ', + '','Mei ','Si ','Bian ','Lu ','Keoi ','','','He ','She ','Lu ','Pai ','Rong ','Qiu ','Lie ','Gong ', + 'Xian ','Xi ','Hing ','','Niao ','','','','Xie ','Lei ','Fu ','Cuan ','Zhuo ','Fei ','Zuo ','Die ', + 'Ji ','He ','Ji ','','Gin ','','','','Tu ','Xian ','Yan ','Tang ','Ta ','Di ','Jue ','Ang ', + 'Han ','Yao ','Ju ','Rui ','Bang ','Zeoi ','Nie ','Tian ','Nai ','','','You ','Mian ','Zin ','Bui ','Nai ', + 'Xing ','Qi ','Zaan ','Gen ','Tong ','Er ','Jia ','Qin ','Mao ','E ','Li ','Chi ','Zong ','He ','Jie ','Ji ', + '','Guan ','Hou ','Gai ','Cung ','Fen ','Se ','Waat ','Ji ','Sik ','Qiong ','He ','Zung ','Xian ','Jie ','Hua ', + 'Bi ','Sing ','Caai ','Zhen ','Sau ','Zin ','Shi ','Gai ','Song ','Zhi ','Ben ','','','','Lang ','Bi ', + 'Xian ','Bang ','Dai ','Cat ','Zi ','Pi ','Chan ','Bi ','Su ','Huo ','Hen ','Ying ','Chuan ','Jiang ','Nen ','Gu ', + 'Fang ','','','Ta ','Cui ','Sai ','De ','Ran ','Kuan ','Che ','Da ','Hu ','Cui ','Lu ','Juan ','Lu ', + 'Qian ','Pao ','Zhen ','Fan ','Li ','Cao ','Qi ','','','Ti ','Ling ','Qu ','Lian ','Lu ','Shu ','Gong ', + 'Zhe ','Biao ','Jin ','Qing ','','','Zong ','Pu ','Jin ','Biao ','Jian ','Gun ','','Ban ','Zou ','Lie ', + ], + 'x3c':[ + 'Li ','Luo ','Shen ','Mian ','Jian ','Di ','Bei ','Cim ','Lian ','Zeon ','Xun ','Pin ','Que ','Long ','Zui ','Gou ', + 'Jue ','San ','She ','','Xie ','Hei ','Lan ','Cu ','Yi ','Nuo ','Li ','Yue ','','Yi ','Ci ','Ji ', + 'Kang ','Xie ','Hang ','Zi ','Ke ','Hui ','Qu ','Hai6','Hei ','Hoi ','Wa ','Caam ','Xun ','Haap6','Shen ','Kou ', + 'Qie ','Sha ','Xu ','Ya ','Po ','Zu ','You ','Zi ','Lian ','Jin ','Xia ','Yi ','Qie ','Mi ','Jiao ','Hei ', + 'Chi ','Shi ','Fong ','Yin ','Mo ','Yi ','Hei ','Se ','Jin ','Ye ','Zaau ','Que ','Che ','Luan ','Kwaan ','Zheng ', + '','','Ho ','','Se ','Gwai ','Cui ','Zaau ','An ','Xiu ','Can ','Chuan ','Zha ','','Ji ','Bo ', + 'Fu ','Sing ','Lang ','Tui ','Sek6','Ling ','E ','Wo ','Lian ','Du ','Men ','Lan ','Wei ','Duan ','Kuai ','Ai ', + 'Zai ','Hui ','Yi ','Mo ','Zi ','Ben ','Beng ','','Bi ','Li ','Lu ','Luo ','Hoi ','Dan ','Goi ','Que ', + 'Chen ','Hung ','Cheng ','Jiu ','Kou ','Ji ','Ling ','Ci ','Shao ','Kai ','Rui ','Chuo ','Neng ','Zi ','Lou ','Bao ', + '','','Bao ','Rong ','Saan ','Lei ','Siu ','Fu ','Qu ','Saau ','Saa ','Zhi ','Tan ','Rong ','Zu ','Ying ', + 'Mao ','Nai ','Bian ','Saau ','Seoi ','Tang ','Han ','Zao ','Rong ','','Dang ','Pu ','Ziu ','Tan ','','Ran ', + 'Ning ','Lie ','Die ','Die ','Zhong ','Siu ','Lu ','Dan ','Kap ','Gui ','Ji ','Ni ','Yi ','Nian ','Yu ','Wang ', + 'Guo ','Ze ','Yan ','Cui ','Xian ','Jiao ','Shu ','Fu ','Pei ','Ngoet ','Zaau ','Zaau ','Nhop ','Bu ','Bian ','Chi ', + 'Sa ','Yi ','Bian ','','Dui ','Lan ','Zi ','Chai ','Cung ','Xuan ','Yu ','Yu ','Zaau ','Hong ','Cung ','', + 'Ta ','Gwo ','','','Suk6','Ju ','Xie ','Xi ','Jian ','Tan ','Pan ','Ta ','Xuan ','Xian ','Niao ','Tan ', + 'Gaau ','','','','Mi ','Ji ','Gou ','Wen ','Faa ','Wang ','You ','Ze ','Bi ','Mi ','Goeng ','Xie ', + ], + 'x3d':[ + 'Fan ','Yi ','Dam ','Lei ','Ying ','Siu ','Jin ','She ','Yin ','Ji ','Zyun ','Su ','','','','Wang ', + 'Mian ','Su ','Yi ','Zai ','Se ','Ji ','Luo ','Zaau ','Mao ','Zha ','Sui ','Zhi ','Bian ','Li ','Caai ','', + '','','','','','Qiao ','Guan ','','Zhen ','Zung ','Nie ','Jun ','Xie ','Yao ','Xie ','Zi ', + 'Neng ','Sam ','Si ','Long ','Chen ','Mi ','Que ','Dam ','Na ','','','','Su ','Xie ','Bo ','Ding ', + 'Cuan ','Fong ','Chuang ','Che ','Han ','Dan ','Hao ','','','','Shen ','Mi ','Chan ','Men ','Han ','Cui ', + 'Jue ','He ','Fei ','Shi ','Che ','Shen ','Nu ','Fu ','Man ','Cing ','','','','Yi ','Chou ','Mei ', + 'Faat ','Bao ','Lei ','Ke ','Dian ','Bi ','Sui ','Ge ','Bi ','Yi ','Xian ','Ni ','Ying ','Zhu ','Chun ','Feng ', + 'Xu ','Piao ','Wu ','Liao ','Cang ','Zou ','Ceoi ','Bian ','Yao ','Huan ','Pai ','Sou ','','Dui ','Jing ','Xi ', + 'Bak6','Guo ','','','Yan ','Xue ','Chu ','Heng ','Ying ','','','','Lian ','Xian ','Huan ','Zaan ', + '','Lian ','Shan ','Cang ','Bei ','Jian ','Shu ','Fan ','Dian ','','Ba ','Yu ','Zyun ','','Nang ','Lei ', + 'Yi ','Dai ','','Chan ','Chao ','Gon ','Jin ','Nen ','Pei ','','','Liao ','Mei ','Jiu ','Siu ','Liu ', + 'Han ','','Yong ','Jin ','Chi ','Ren ','Nong ','','','Hong ','Tian ','Bung ','Oi ','Gwaa ','Biu ','Bo ', + 'Qiong ','','Shu ','Cui ','Hui ','Chao ','Dou ','Guai ','E ','Wei ','Fen ','Tan ','','Lun ','He ','Yong ', + 'Hui ','Nim6','Yu ','Zong ','Yan ','Qiu ','Zhao ','Jiong ','Tai ','Zin ','','Bou ','','Dut ','','Tui ', + 'Lin ','Jiong ','Zha ','Sing ','He ','Zing ','Xu ','','','Hei ','Cui ','Qing ','Mo ','Fung ','Zou ','Beng ', + 'Li ','','','Yan ','Ge ','Mo ','Bei ','Juan ','Die ','Shao ','','Wu ','Yan ','','Jue ','Hin ', + ], + 'x3e':[ + 'Tai ','Han ','','Dian ','Ji ','Jie ','','','Ziu ','Xie ','La ','Fan ','Huo ','Xi ','Nie ','Mi ', + 'Ran ','Cuan ','Yin ','Mi ','','Jue ','Keoi ','Tong ','Wan ','Ze ','Li ','Shao ','Kong ','Kan ','Ban ','Taai ', + 'Tiao ','Syu ','Bei ','Ye ','Pian ','Chan ','Hu ','Ken ','Gaau ','An ','Chun ','Qian ','Bei ','Baa ','Fen ','Fo ', + 'Tuo ','Tuo ','Zuo ','Ling ','','Gui ','Zin ','Shi ','Hou ','Lie ','Saa ','Si ','Fung ','Bei ','Ren ','Du ', + 'Bo ','Liang ','Ci ','Bi ','Ji ','Zong ','Fai ','He ','Li ','Yuan ','Yue ','Saau ','Chan ','Di ','Lei ','Jin ', + 'Chong ','Si ','Pu ','Yi ','Goeng ','Fun ','Huan ','Tao ','Ru ','Ying ','Ying ','Rao ','Yin ','Shi ','Yin ','Jue ', + 'Tun ','Xuan ','Gaa ','Zung ','Qie ','Zhu ','Ciu ','Zoeng ','You ','','Saan ','Xi ','Shi ','Yi ','Mo ','Huou ', + '','Hu ','Xiao ','Wu ','Gang ','Jing ','Ting ','Shi ','Ni ','Gang ','Ta ','Waai ','Chu ','Chan ','Piao ','Diao ', + 'Nao ','Nao ','Gan ','Gou ','Yu ','Hou ','','Si ','Ci ','Hu ','Yang ','Zung ','Xian ','Ban ','Rong ','Lou ', + 'Zhao ','Can ','Liao ','Piao ','Hai ','Fan ','Han ','Dan ','Zhan ','','Ta ','Zhu ','Ban ','Jian ','Yu ','Zhuo ', + 'You ','Li ','Kut ','Hei ','Cim ','Chan ','Lian ','Heo ','Si ','Jiu ','Pu ','Qiu ','Gong ','Zi ','Yu ','', + 'Si ','Reng ','Niu ','Mei ','Baat ','Jiu ','','Xu ','Ping ','Bian ','Mao ','','','','','Yi ', + 'You ','Gwai ','Ping ','Kuk ','Bao ','Hui ','','','','Bu ','Mang ','La ','Tu ','Wu ','Li ','Ling ', + '','Ji ','Jun ','Lit6','Duo ','Jue ','Dai ','Bei ','','','','','','La ','Bian ','Sui ', + 'Tu ','Die ','','','','','','Duo ','','','Sui ','Bi ','Tu ','Se ','Can ','Tu ', + 'Mian ','Zeon ','Lu ','','','Zhan ','Bi ','Ji ','Cen ','Hyun ','Li ','','','Sui ','Zung ','Shu ', + ], + 'x3f':[ + '','','E ','','Gei ','','','Qiong ','Luo ','Yin ','Tun ','Gu ','Yu ','Lei ','Bei ','Nei ', + 'Pian ','Lian ','Qiu ','Lian ','Waan ','Dong ','Li ','Ding ','Wa ','Zhou ','Gong ','Xing ','Ang ','Fan ','Peng ','Bai ', + 'Tuo ','Syu ','E ','Bai ','Qi ','Chu ','Gong ','Tong ','Han ','Cheng ','Jia ','Huan ','Xing ','Dian ','Mai ','Dong ', + 'E ','Ruan ','Lie ','Sheng ','Ou ','Di ','Yu ','Chuan ','Rong ','Hong ','Tang ','Cong ','Piao ','Shuang ','Lu ','Tong ', + 'Zheng ','Li ','Sa ','Ban ','Si ','Dang ','Dong ','Guai ','Yi ','Han ','Xie ','Luo ','Liu ','Ham ','Dan ','', + 'Cim ','Tan ','Saang ','','','You ','Nan ','','Gang ','Jun ','Chi ','Kou ','Wan ','Li ','Liu ','Lie ', + 'Xia ','Baai ','An ','Yu ','Ju ','Rou ','Xun ','Zi ','Cuo ','Can ','Zeng ','Yong ','Fu ','Ruan ','Sing ','Xi ', + 'Shu ','Jiao ','Jiao ','Han ','Zhang ','Zong ','','Shui ','Chen ','Fan ','Ji ','Zi ','','Gu ','Wu ','Cui ', + 'Qie ','Shu ','Hoi ','Tuo ','Du ','Si ','Ran ','Mu ','Fu ','Ling ','Ji ','Xiu ','Xuan ','Nai ','At ','Jie ', + 'Li ','Da ','Ji ','Zyun ','Lu ','Shen ','Li ','Lang ','Geng ','Yin ','Se ','Qin ','Qie ','Che ','You ','Bu ', + 'Huang ','Que ','Lai ','Zaam ','Hong ','Xu ','Bang ','Ke ','Qi ','Gwaai ','Sheng ','Pin ','Gaai ','Zhou ','Huang ','Tui ', + 'Hu ','Bei ','','','Zaa ','Ji ','Gu ','Sai ','Gao ','Chai ','Ma ','Zhu ','Tui ','Tui ','Lian ','Lang ', + 'Baan ','','Zing ','Dai ','Ai ','Xian ','Gwo ','Xi ','Zung ','Tui ','Can ','Sao ','Cim ','Jie ','Fen ','Qun ', + '','Yao ','Dao ','Jia ','Lei ','Yan ','Lu ','Tui ','Ying ','Pi ','Luo ','Li ','Bie ','Hoeng ','Mao ','Bai ', + 'huang ','Dau ','Yao ','He ','Chun ','Hu ','Ning ','Chou ','Li ','Tang ','Huan ','Bi ','Baa ','Che ','Yang ','Da ', + 'Ao ','Xue ','Zi ','','Daap ','Ran ','Bong ','Zao ','Wan ','Ta ','Bao ','Gon ','Yan ','Gaai ','Zhu ','Ya ', + ], + 'x40':[ + 'Fan ','You ','On ','Tui ','Meng ','She ','Jin ','Gu ','Qi ','Qiao ','Jiao ','Yan ','','Kan ','Mian ','Xian ', + 'San ','Na ','Cin ','Huan ','Niu ','Cheng ','Tin ','Jue ','Xi ','Qi ','Ang ','Mei ','Gu ','','Tou ','Fan ', + 'Qu ','Chan ','Shun ','Bi ','Mao ','Shuo ','Gu ','Hong ','Huan ','Luo ','Hang ','Jia ','Quan ','Goi ','Mang ','Bu ', + 'Gu ','Fung ','Mu ','Ai ','Ying ','Shun ','Lang ','Jie ','Di ','Jie ','Cau ','Pin ','Ren ','Yan ','Du ','Di ', + '','Lang ','Xian ','Biu ','Xing ','Bei ','An ','Mi ','Qi ','Qi ','Wo ','She ','Yu ','Jia ','Cheng ','Yao ', + 'Ying ','Yang ','Ji ','Jie ','Han ','Min ','Lou ','Kai ','Yao ','Yan ','Sun ','Gui ','Huang ','Ying ','Sheng ','Cha ', + 'Lian ','','Xuan ','Chuan ','Che ','Ni ','Qu ','Miao ','Huo ','Yu ','Nan ','Hu ','Ceng ','Biu ','Qian ','She ', + 'Jiang ','Ao ','Mai ','Mang ','Zhan ','Bian ','Jiao ','Jue ','Nong ','Bi ','Shi ','Li ','Mo ','Lie ','Mie ','Mo ', + 'Xi ','Chan ','Qu ','Jiao ','Huo ','Zin ','Xu ','Nang ','Tong ','Hou ','Yu ','','Cung ','Bo ','Zuan ','Diu ', + 'Chuo ','Ci ','Jie ','Kwai ','Xing ','Hui ','Shi ','Gwaat6','Caam ','','Yao ','Yu ','Bang ','Jie ','Zhe ','Gaa ', + 'She ','Di ','Dong ','Ci ','Fu ','Min ','Zhen ','Zhen ','','Yan ','Diao ','Hong ','Gong ','Diu6','Lue ','Guai ', + 'La ','Cui ','Fa ','Cuo ','Yan ','Gung ','Jie ','Gwaai ','Guo ','Suo ','Wan ','Zheng ','Nie ','Diao ','Lai ','Ta ', + 'Cui ','Aa ','Gun ','','','Dai ','','Mian ','Gaai ','Min ','Ju ','Yu ','Zan ','Zhao ','Ze ','Saang ', + '','Pan ','He ','Gou ','Hong ','Lao ','Wu ','Chuo ','Hang ','Lu ','Cu ','Lian ','Zi ','Qiao ','Shu ','', + 'xuan ','Cen ','Zaam ','Hui ','Su ','Chuang ','Deon ','Long ','','Nao ','Tan ','Dan ','Wei ','Gan ','Da ','Li ', + 'Caat ','Xian ','Pan ','La ','Zyu ','Niao ','Huai ','Ying ','Xian ','Lan ','Mo ','Ba ','','Fu ','Bi ','Fu ', + ], + 'x41':[ + 'Huo ','Yi ','Liu ','Zoeng ','Zaan ','Juan ','Huo ','Cheng ','Dou ','E ','','Yan ','Zhui ','Du ','Qi ','Yu ', + 'Quan ','Huo ','Nie ','Heng ','Ju ','She ','','','Peng ','Ming ','Cao ','Lou ','Li ','Chun ','','Cui ', + 'Shan ','Daam ','Qi ','','Lai ','Ling ','Liao ','Reng ','Yu ','Nao ','Chuo ','Qi ','Yi ','Nian ','Fu ','Jian ', + 'Ya ','Fong ','Chui ','Cin ','','','Bi ','Dan ','Po ','Nian ','Zhi ','Chao ','Tian ','Tian ','Rou ','Yi ', + 'Lie ','An ','He ','Qiong ','Li ','Gwai ','Zi ','Su ','Yuan ','Ya ','Du ','Wan ','Gyun ','Dong ','You ','Hui ', + 'Jian ','Rui ','Mang ','Ju ','Zi ','Geoi ','An ','Sui ','Lai ','Hun ','Qiang ','Coeng ','Duo ','Hung ','Na ','Can ', + 'Ti ','Xu ','Jiu ','Huang ','Qi ','Jie ','Mao ','Yan ','Heoi ','Zhi ','Tui ','','Ai ','Pang ','Cang ','Tang ', + 'En ','Hun ','Qi ','Chu ','Suo ','Zhuo ','Nou ','Tu ','Zu ','Lou ','Miao ','Li ','Man ','Gu ','Cen ','Hua ', + 'Mei ','Gou ','Lian ','Dao ','Shan ','Ci ','','','Zhi ','Ba ','Cui ','Qiu ','','Long ','Cim ','Fei ', + 'Guo ','Cheng ','Jiu ','E ','Cung ','Jue ','Hong ','Jiao ','Cuan ','Yao ','Tong ','Cha ','You ','Shu ','Yao ','Ge ', + 'Huan ','Lang ','Jue ','Chen ','Cyun ','Cyun ','Shen ','Fo ','Ming ','Ming ','Hung ','Chuang ','Yun ','Han6','Jin ','Chuo ', + 'Zyu ','Tan ','Hong ','Qiong ','','Cheng ','Zaau ','Yu ','Cheng ','Tong ','Pun ','Qiao ','Fo ','Ju ','Lan ','Yi ', + 'Rong ','Si ','Hin ','Si ','Ngat ','Fa ','','Meng ','Gui ','','','Hai ','Qiao ','Chuo ','Que ','Dui ', + 'Li ','Ba ','Jie ','Seoi ','Luo ','Deoi ','Yun ','Zung ','Hu ','Yin ','Pok ','Zhi ','Lian ','Zim ','Gan ','Jian ', + 'Zhou ','Zhu ','Ku ','Na ','Dui ','Ze ','Yang ','Zhu ','Gong ','Yi ','Ci ','Gei ','Chuang ','Lao ','Ren ','Rong ', + 'Zing ','Na ','Ce ','Zin ','','Yi ','Jue ','Bi ','Cheng ','Jun ','Chou ','Hui ','Chi ','Zhi ','Yan ','', + ], + 'x42':[ + 'Saan ','Lun ','Bing ','Zhao ','Han ','Yu ','Dai ','Zhao ','Fei ','Sha ','Ling ','Ta ','Zeoi ','Mang ','Ye ','Bao ', + 'Kui ','Gua ','Nan ','Ge ','Gaa ','Chi ','Fo ','Suo ','Ci ','Zhou ','Tai ','Kuai ','Qin ','Seoi ','Du ','Ce ', + 'Huan ','Gung ','Sai ','Zheng ','Qian ','Gan ','Zung ','Wei ','','','Xi ','Na ','Pu ','Huai ','Ju ','Zaan ', + 'Sau ','Tou ','Pan ','Ta ','Qian ','Zung ','Rong ','Luo ','Hu ','Sou ','Zung ','Pu ','Mie ','Gan ','Shuo ','Mai ', + 'Shu ','Ling ','Lei ','Jiang ','Leng ','Zhi ','Diao ','','San ','Hu ','Fan ','Mei ','Sui ','Jian ','Tang ','Xie ', + 'Fu ','Mo ','Fan ','Lei ','Can ','Ceng ','Ling ','Zaap ','Cong ','Yun ','Meng ','Yu ','Zhi ','Qi ','Dan ','Huo ', + 'Wei ','Tan ','Se ','Xie ','Sou ','Song ','Cin ','Liu ','Yi ','Aau ','Lei ','Li ','Fei ','Lie ','Lin ','Xian ', + 'Yao ','Aau ','Bie ','Xian ','Rang ','Zhuan ','Soeng ','Dan ','Bian ','Ling ','Hong ','Qi ','Liao ','Ban ','Mi ','Hu ', + 'Hu ','Caap ','Ce ','Pei ','Qiong ','Ming ','Jiu ','Bu ','Mei ','San ','Mei ','Zong ','','Li ','Quan ','Sam ', + 'En ','Xiang ','Zing ','Shi ','Zing ','Gin ','Lan ','Huang ','Jiu ','Yan ','Deoi ','Sa ','Tuan ','Xie ','Zhe ','Men ', + 'Xi ','Man ','Zoeng ','Huang ','Tan ','Xiao ','Ya ','Bi ','Luo ','Fan ','Li ','Cui ','Cha ','Chou ','Di ','Kuang ', + 'Chu ','Cim ','Chan ','Mi ','Qian ','Qiu ','Zhen ','Chai ','Heoi ','Cim ','Gu ','Yan ','Chi ','Guai ','Mu ','Bo ', + 'Kua ','Geng ','Yao ','Mao ','Wang ','','','','Ru ','Jue ','Zing ','Min ','Jiang ','O ','Zhan ','Zuo ', + 'Yue ','Bing ','Nou6','Zhou ','Bi ','Ren ','Yu ','Gin ','Chuo ','Er ','Yi ','Mi ','Qing ','Zing ','Wang ','Ji ', + 'Bu ','Syu ','Bie ','Fan ','Yao ','Li ','Fan ','Qu ','Fu ','Er ','O ','Zang ','Zim ','Huo ','Jin ','Qi ', + 'Ju ','Lai ','Che ','Bei ','Niu ','Yi ','Xu ','Liu ','Xun ','Fu ','Cau ','Nin ','Ting ','Beng ','Zha ','Wui ', + ], + 'x43':[ + 'Fo ','Zaau ','Ou ','Shuo ','Geng ','Tang ','Gui ','Hui ','Ta ','Gong ','Yao ','Daap ','Qi ','Han ','Lue ','Mi ', + 'Mi ','Gin ','Lu ','Fan ','Ou ','Mi ','Jie ','Fu ','Mi ','Huang ','Su ','Yao ','Nie ','Jin ','Lian ','Bi ', + 'Qing ','Ti ','Ling ','Zuan ','Zhi ','Yin ','Dao ','Chou ','Cai ','Mi ','Yan ','Lan ','Chong ','Ziu ','Soeng ','Guan ', + 'She ','Luo ','Fan ','Si ','Luo ','Zhu ','Zi ','Chou ','Juan ','Jiong ','Er ','Yi ','Rui ','Cai ','Ren ','Fu ', + 'Lan ','Sui ','Yu ','Yao ','Dian ','Ling ','Zhu ','Ta ','Ping ','Qian ','Jue ','Chui ','Bu ','Gu ','Cun ','', + 'Han ','Han ','Mou ','Hu ','Hong ','Di ','Fu ','Xuan ','Mi ','Mei ','Lang ','Gu ','Zhao ','Ta ','Yu ','Zong ', + 'Li ','Liao ','Wu ','Lei ','Ji ','Lei ','Li ','Zong ','Bo ','Ang ','Kui ','Tuo ','Ping ','Cau ','Zhao ','Gui ', + 'Zaan ','Xu ','Nai ','Chuo ','Duo ','Kaap ','Dong ','Gui ','Bo ','Zin ','Huan ','Xuan ','Can ','Li ','Tui ','Huang ', + 'Xue ','Hu ','Bao ','Ran ','Tiao ','Fu ','Liao ','Zaau ','Yi ','Shu ','Po ','He ','Cu ','Fu ','Na ','An ', + 'Chao ','Lu ','Zhan ','Ta ','Fu ','Gwaang ','Zang ','Qiao ','Su ','Baan ','Guan ','','Fan ','Chu ','','Er ', + 'Er ','Nuan ','Qi ','Si ','Chu ','','Yan ','Bang ','An ','Zi ','Ne ','Chuang ','Ba ','Ciu ','Ti ','Han ', + 'Zuo ','Ba ','Zhe ','Wa ','Sheng ','Bi ','Er ','Zhu ','Wu ','Wen ','Zhi ','Zhou ','Lu ','Wen ','Gun ','Qiu ', + 'La ','Zai ','Sou ','Mian ','Zhi ','Qi ','Cao ','Piao ','Lian ','Saap ','Long ','Su ','Qi ','Yuan ','Feng ','Heoi ', + 'Jue ','Di ','Pian ','Guan ','Niu ','Ren ','Zhen ','Gai ','Pi ','Tan ','Chao ','Chun ','Ho ','Chun ','Mo ','Bie ', + 'Qi ','Shi ','Bi ','Jue ','Si ','Taam ','Hua ','Na ','Hui ','Kaap ','Er ','Caau ','Mou ','Zyu ','Xi ','Zhi ', + 'Ren ','Ju ','Die ','Zhe ','Shao ','Meng ','Bi ','Han ','Yu ','Xian ','Pong ','Neng ','Can ','Bu ','Bong ','Qi ', + ], + 'x44':[ + 'Ji ','Niao ','Lu ','Jiong ','Han ','Yi ','Cai ','Chun ','Zhi ','Zi ','Da ','Cung ','Tian ','Zhou ','Daai ','Chun ', + 'Cau ','Zhe ','Zaa ','Rou ','Bin ','Ji ','Yi ','Du ','Jue ','Ge ','Ji ','Dap ','Can ','Suo ','Ruo ','Xiang ', + 'Huang ','Qi ','Zhu ','Cuo ','Chi ','Weng ','Haap6','Kao ','Gu ','Kai ','Fan ','Sung ','Cao ','Zhi ','Chan ','Lei ', + 'Gaau ','Zak6','Zhe ','Yu ','Gui ','Huang ','Jin ','Daan ','Guo ','Sao ','Tan ','','Xi ','Man ','Duo ','Ao ', + 'Pi ','Wu ','Ai ','Meng ','Pi ','Meng ','Yang ','Zhi ','Bo ','Ying ','Wei ','Nao ','Lan ','Yan ','Chan ','Quan ', + 'Zhen ','Pu ','','Tai ','Fei ','Shu ','','Dang ','Cha ','Ran ','Tian ','Chi ','Ta ','Jia ','Shun ','Huang ', + 'Liao ','Caa ','Dou ','','Jin ','E ','Keoi ','Fu ','Duo ','','E ','','Yao ','Di ','','Di ', + 'Bu ','Man ','Che ','Lun ','Qi ','Mu ','Can ','','Zung ','Sau ','Fan ','You ','Saau ','Da ','','Su ', + 'Fu ','Ji ','Jiang ','Cao ','Bo ','Teng ','Che ','Fu ','Bu ','Wu ','Haai ','Yang ','Ming ','Pang ','Mang ','Zang ', + 'Meng ','Cao ','Tiao ','Kai ','Bai ','Xiao ','Xin ','Qi ','Seoi ','','Shao ','Heng ','Niu ','Xiao ','Chen ','Daan ', + 'Fan ','Yin ','Ang ','Ran ','Ri ','Fa ','Fan ','Qu ','Shi ','He ','Bian ','Dai ','Mo ','Deng ','','', + 'Hong ','Zing ','Cha ','Duo ','You ','Hao ','Tin ','Kut ','Xian ','Lei ','Jin ','Qi ','','Mei ','Zi ','', + '','','Yan ','Yi ','Yin ','Qi ','Zhe ','Xi ','Yi ','Ye ','E ','','Zhi ','Han ','Chuo ','', + 'Chun ','Bing ','Kuai ','Chou ','','Tuo ','Qiong ','Cung ','Jiu ','Gwai ','Cu ','Fu ','','Meng ','Li ','Lie ', + 'Ta ','Zi ','Gu ','Liang ','Fat ','La ','Dian ','Ci ','Aang ','','','Ji ','','Cha ','Mao ','Du ', + 'Zaan ','Chai ','Rui ','Hen ','Ruan ','','Lai ','Xing ','Gan ','Yi ','Mei ','','He ','Ji ','So ','Han ', + ], + 'x45':[ + 'Seoi ','Li ','Zi ','Zu ','Yao ','Geoi ','Li ','Qi ','Gan ','Li ','','','','','Su ','Chou ', + '','Xie ','Bei ','Xu ','Jing ','Pu ','Ling ','Xiang ','Zuo ','Diao ','Chun ','Qing ','Nan ','','Lu ','Chi ', + 'Shao ','Yu ','Hua ','Li ','','Siu ','','Li ','','','Dui ','','Yi ','Ning ','Si ','Hu ', + 'Fu ','Zaap ','Cheng ','Nan ','Ce ','Gaan ','Ti ','Qin ','Biao ','Sui ','Wei ','Deon ','Se ','Ai ','E ','Jie ', + 'Kuan ','Fei ','','Yin ','Zing ','Sao ','Dou ','Hui ','Xie ','Ze ','Tan ','Chang ','Zhi ','Yi ','Fu ','E ', + '','Jun ','Gaa ','Cha ','Xian ','Man ','Syun ','Bi ','Ling ','Jie ','Kui ','Jia ','','Sang ','Lang ','Guk ', + 'Fei ','Lu ','Zha ','He ','','Ni ','Ying ','Xiao ','Teng ','Lao ','Ze ','Kui ','Goeng ','Qian ','Ju ','Piao ', + 'Ban ','Dou ','Lin ','Mi ','Zhuo ','Xie ','Hu ','Mi ','Gaai ','Za ','Cong ','Ge ','Nan ','Zhu ','Yan ','Han ', + 'Ceoi ','Yi ','Luan ','Yue ','Ran ','Ling ','Niang ','Yu ','Nue ','Heoi ','Yi ','Nue ','Qin ','Qian ','Xia ','Chu ', + 'Jin ','Mi ','','Na ','Han ','Zu ','Xia ','Yan ','Tu ','','Wu ','Suo ','Yin ','Chong ','Zhou ','Mang ', + 'Yuan ','Nu ','Miao ','Sao ','Wan ','Li ','','Na ','Shi ','Bi ','Ci ','Bang ','','Juan ','Xiang ','Gui ', + 'Pai ','Hong ','Xun ','Zha ','Yao ','Kwan ','','He ','E ','Yang ','Tiao ','You ','Jue ','Li ','','Li ', + '','Ji ','Hu ','Zhan ','Fu ','Chang ','Guan ','Ju ','Meng ','Coeng ','Cheng ','Mou ','Sing ','Li ','Zaan ','', + 'Si ','Yi ','Bing ','Cung ','Hou ','Wan ','Chi ','','Ge ','Han ','Bo ','Saau ','Liu ','Can ','Can ','Yi ', + 'Xuan ','Yan ','Suo ','Gao ','Yong ','Zung ','Fung ','Hong ','Yu ','Cik ','Zhe ','Ma ','Fung ','','Shuang ','Jin ', + 'Guan ','Pu ','Lin ','','Ting ','Goeng ','La ','Yi ','Zung ','Ci ','Yan ','Jie ','Faan ','Wei ','Xian ','Ning ', + ], + 'x46':[ + 'Fu ','Ge ','','Mo ','Fu ','Nai ','Xian ','Wen ','Li ','Can ','Mie ','','Ni ','Chai ','Wan ','Xu ', + 'Nu ','Mai ','Co ','Kan ','Ho ','Hang ','','Faai ','Yu ','Wei ','Zhu ','Gei ','Gan ','Yi ','','', + 'Fu ','Bi ','Zhu ','Zi ','Shu ','Xia ','Ni ','','Jiao ','Xuan ','Cung ','Nou ','Rong ','Die ','Sa ','Sau ', + '','Yu ','','Kaam ','Zung ','Lu ','Han ','','Yi ','Zui ','Zhan ','Su ','Wan ','Ni ','Guan ','Jue ', + 'Beng ','Can ','Zung ','Duo ','Qi ','Yao ','Gui ','Nuan ','Hou ','Xun ','Xie ','','Hui ','','Xie ','Bo ', + 'Ke ','Ceoi ','Xu ','Bai ','Aau ','Chu ','Bang ','Ti ','Chu ','Chi ','Niao ','Guan ','Feng ','Xie ','Dang ','Duo ', + 'Jue ','Hui ','Zeng ','Sa ','Duo ','Ling ','Meng ','Fan ','Guo ','Meng ','Long ','','Ying ','Hin ','Guan ','Cu ', + 'Li ','Du ','Ceng ','E ','Sin ','Saai ','','De ','De ','Jiang ','Lian ','','Shao ','Xi ','Si ','Wei ', + '','','He ','You ','Lu ','Lai ','Ou ','Sheng ','Juan ','Qi ','','Yun ','','Qi ','Zong ','Leng ', + 'Ji ','Mai ','Chuang ','Nian ','Baan ','Li ','Ling ','Gong ','Chen ','','Xian ','Hu ','Bei ','Zu ','Dai ','Dai ', + 'Hun ','Soi ','Che ','Ti ','','Nuo ','Zhi ','Liu ','Fei ','Jiao ','Gwaan ','Ao ','Lin ','','Reng ','Tao ', + 'Pi ','Xin ','Shan ','Xie ','Wa ','Tao ','Tin ','Xi ','Xie ','Pi ','Yao ','Yao ','Nu ','Hao ','Nin ','Yin ', + 'Fan ','Nan ','Chi ','Wang ','Yuan ','Xia ','Zhou ','Yuan ','Shi ','Mi ','','Ge ','Pao ','Fei ','Hu ','Ni ', + 'Ci ','Mi ','Bian ','Gam ','Na ','Yu ','E ','Zhi ','Nin ','Xu ','Lue ','Hui ','Xun ','Nao ','Han ','Jia ', + 'Dou ','Hua ','Tuk ','','Cu ','Xi ','Song ','Mi ','Xin ','Wu ','Qiong ','Zheng ','Chou ','Xing ','Jiu ','Ju ', + 'Hun ','Ti ','Man ','Jian ','Qi ','Shou ','Lei ','Wan ','Che ','Can ','Jie ','You ','Hui ','Zha ','Su ','Ge ', + ], + 'x47':[ + 'Nao ','Xi ','','Deoi ','Chi ','Wei ','Mo ','Gun ','Cau ','','Zao ','Hui ','Luan ','Liao ','Lao ','', + '','Qia ','Ao ','Nie ','Sui ','Mai ','Tan ','Xin ','Jing ','An ','Ta ','Chan ','Wei ','Tuan ','Ji ','Chen ', + 'Che ','Xu ','Xian ','Xin ','','Daan ','','Nao ','','Yan ','Qiu ','Hong ','Song ','Jun ','Liao ','Ju ', + '','Man ','Lie ','','Chu ','Chi ','Xiang ','Cam ','Mei ','Shu ','Ce ','Chi ','Gu ','Yu ','Zaam ','', + 'Liao ','Lao ','Shu ','Zhe ','Soeng ','','Fat ','Fui ','E ','','Sha ','Zong ','Jue ','Jun ','','Lou ', + 'Wei ','Cung ','Zhu ','La ','Fun ','Zhe ','Zhao ','Zaau ','Yi ','','Ni ','Bo ','Syun ','Yi ','Hao ','Ya ', + 'Huan ','Man ','Man ','Qu ','Lao ','Hao ','','Men ','Xian ','Zhen ','Shu ','Zuo ','Zhu ','Gou ','Xuan ','Yi ', + 'Ti ','xie ','Jin ','Can ','Zai ','Bu ','Liang ','Zhi ','Ji ','Wan ','Guan ','Ceoi ','Qing ','Ai ','Fu ','Gui ', + 'Gou ','Xian ','Ruan ','Zhi ','Biao ','Yi ','Suo ','Die ','Gui ','Sheng ','Xun ','Chen ','She ','Qing ','','', + 'Chun ','Hong ','Dong ','Cheng ','Wei ','Die ','Shu ','Caai ','Ji ','Za ','Qi ','','Fu ','Ao ','Fu ','Po ', + '','Tan ','Zha ','Che ','Qu ','You ','He ','Hou ','Gui ','E ','Jiang ','Yun ','Tou ','Qiu ','','Fu ', + 'Zuo ','Hu ','','Bo ','','Jue ','Di ','Jue ','Fu ','Huang ','','Yong ','Chui ','Suo ','Chi ','Hin ', + '','','Man ','Ca ','Qi ','Jian ','Bi ','Gei ','Zhi ','Zhu ','Qu ','Zhan ','Ji ','Dian ','','Li ', + 'Li ','La ','Quan ','Ding ','Fu ','Cha ','Tang ','Shi ','Hang ','Qie ','Qi ','Bo ','Na ','Tou ','Chu ','Cu ', + 'Yue ','Di ','Chen ','Chu ','Bi ','Mang ','Ba ','Tian ','Min ','Lie ','Feng ','Caang ','Qiu ','Tiao ','Fu ','Kuo ', + 'Jian ','Ci ','','','Zhen ','Qiu ','Cuo ','Chi ','Kui ','Lie ','Bang ','Du ','Wu ','So ','Jue ','Lu ', + ], + 'x48':[ + 'Chang ','Zai ','Chu ','Liang ','Tian ','Kun ','Chang ','Jue ','Tu ','Hua ','Fei ','Bi ','','Qia ','Wo ','Ji ', + 'Qu ','Kui ','Hu ','Cu ','Sui ','','','Qiu ','Pi ','Bei ','Wa ','Jiao ','Rong ','','Cu ','Die ', + 'Chi ','Cuo ','Meng ','Xuan ','Duo ','Bie ','Zhe ','Chu ','Chan ','Gui ','Duan ','Zou ','Deng ','Lai ','Teng ','Yue ', + 'Quan ','Shu ','Ling ','','Qin ','Fu ','She ','Tiao ','','Ai ','','Qiong ','Diao ','Hai ','Shan ','Wai ', + 'Zhan ','Long ','Jiu ','Li ','','Min ','Rong ','Yue ','Jue ','Kang ','Fan ','Qi ','Hong ','Fu ','Lu ','Hong ', + 'Tuo ','Min ','Tian ','Juan ','Qi ','Zheng ','Jing ','Gong ','Tian ','Lang ','Mao ','Yin ','Lu ','Yun ','Ju ','Pi ', + '','Xie ','Bian ','','Zeoi ','Rong ','Sang ','Wu ','Cha ','Gu ','Chan ','Peng ','Man ','Saau ','Zung ','Shuang ', + 'Keng ','Zhuan ','Chan ','Si ','Chuang ','Sui ','Bei ','Kai ','','Zhi ','Wei ','Min ','Ling ','','Nei ','Ling ', + 'Qi ','Yue ','Lip ','Yi ','Xi ','Chen ','','Rong ','Chen ','Nong ','You ','Ji ','Bo ','Fang ','Gei ','', + 'Cu ','Di ','Gaau ','Yu ','Ge ','Xu ','Lu ','He ','','Bai ','Gong ','Jiong ','Gwai ','Ya ','Nu ','You ', + 'Song ','Xie ','Cang ','Yao ','Shu ','Yan ','Shuai ','Liao ','Sung ','Yu ','Bo ','Sui ','Cin ','Yan ','Lei ','Lin ', + 'Tai ','Du ','Yue ','Ji ','Cin ','Yun ','Bong ','','','Ju ','Ceot ','Chen ','Cung ','Xiang ','Xian ','On ', + 'Gui ','Yu ','Lei ','','Tu ','Chen ','Xing ','Qiu ','Hang ','','Dang ','Cai ','Di ','Yan ','Ci ','Gung ', + 'Zing ','Chan ','','Li ','Suo ','Ma ','Ma ','','Tang ','Pei ','Lou ','Sat ','Cuo ','Tu ','E ','Can ', + 'Jie ','Ti ','Ji ','Dang ','Jiao ','Bi ','Lei ','Yi ','Chun ','Chun ','Po ','Li ','Zai ','Tai ','Po ','Tian ', + 'Ju ','Xu ','Fan ','','Xu ','Er ','Huo ','Chua ','Ran ','Fa ','Gyun ','','Liang ','Ti ','Mi ','', + ], + 'x49':[ + '','Cen ','Mei ','Yin ','Mian ','Tu ','Kui ','Sau ','Hei ','Mi ','Rong ','Guo ','Coeng ','Mi ','Ju ','Pi ', + 'Jin ','Wang ','Ji ','Meng ','Jian ','Xue ','Bao ','Gan ','Chan ','Li ','Li ','Qiu ','Dun ','Ying ','Yun ','Chen ', + 'Ji ','Ran ','','Lue ','','Gui ','Yue ','Hui ','Pi ','Cha ','Duo ','Chan ','So ','Kuan ','She ','Xing ', + 'Weng ','Shi ','Chi ','Ye ','Han ','Fei ','Ye ','Yan ','Zuan ','Saau ','Yin ','Duo ','Xian ','Gwaan ','Tou ','Qie ', + 'Chan ','Han ','Meng ','Yue ','Cu ','Qian ','Jin ','Shan ','Mu ','Zyun ','Coeng ','Baang ','Zheng ','Zhi ','Chun ','Yu ', + 'Mou ','Wan ','Chou ','Kei ','Su ','Pie ','Tian ','Kuan ','Cu ','Sui ','Co ','Jie ','Jian ','Ao ','Jiao ','Ye ', + 'Saam ','Ye ','Long ','Zao ','Bao ','Lian ','','Huan ','Lu ','Wei ','Xian ','Tie ','Bo ','Zheng ','Zhu ','Ba ', + 'Meng ','Xie ','Aau ','Zaau ','Teon ','Xiao ','Li ','Zha ','Mi ','','Ye ','','','Put ','Xie ','', + '','Bong ','Shan ','Coeng ','','Shan ','Jue ','Ji ','Fang ','','Niao ','Ao ','Chu ','Wu ','Guan ','Xie ', + 'Ting ','Xie ','Dang ','Zim ','Tan ','Ping ','Xia ','Xu ','Bi ','Si ','Huo ','Zheng ','Wu ','','Run ','Chuai ', + 'Shi ','Huan ','Kuo ','Fu ','Chuai ','Xian ','Qin ','Qie ','Lan ','','Ya ','Zing ','Que ','','Chun ','Zhi ', + 'Gau ','Kui ','Qian ','Hang ','Yi ','Ni ','Zheng ','Chuai ','','Shi ','Cap ','Ci ','Jue ','Xu ','Yun ','', + '','Chu ','Dao ','Dian ','Ge ','Ti ','Hong ','Ni ','','Li ','','Xian ','Seoi ','Xi ','Xuan ','', + 'Gwik ','Taai ','Lai ','Zau ','Mu ','Cheng ','Jian ','Bi ','Qi ','Ling ','Hao ','Bang ','Tang ','Di ','Fu ','Xian ', + 'Shuan ','Zung ','Keoi ','Zaan ','Pu ','Hui ','Wei ','Yi ','Ye ','','Che ','Hao ','Baai ','','Xian ','Chan ', + 'Hun ','Gaau ','Han ','Ci ','Zi ','Qi ','Kui ','Rou ','Gu ','Zing ','Xiong ','Gap ','Hu ','Cui ','Syu ','Que ', + ], + 'x4a':[ + 'Di ','Che ','Cau ','','Yan ','Liao ','Bi ','Soeng ','Ban ','Zing ','','Nue ','Bao ','Ying ','Hong ','Ci ', + 'Qia ','Ti ','Yu ','Lei ','Bao ','Wu ','Ji ','Fu ','Xian ','Cen ','Fat ','Se ','Baang ','Cing ','Yu ','Waa ', + 'Ai ','Han ','Dan ','Ge ','Di ','Hu ','Pang ','Zaam ','Zaa ','Ling ','Mai ','Mai ','Lian ','Siu ','Xue ','Zhen ', + 'Po ','Fu ','Nou ','Xi ','Dui ','Dan ','Yun ','Xian ','Yin ','Suk ','Dui ','Beng ','Hu ','Fei ','Fei ','Qian ', + 'Bei ','Fei ','','Shi ','Tian ','Zhan ','Jian ','','Hui ','Fu ','Wan ','Mo ','Qiao ','Liao ','','Mie ', + 'Ge ','Hong ','Yu ','Qi ','Duo ','Ang ','Saa ','Ba ','Di ','Xuan ','Di ','Bi ','Zhou ','Pao ','Nian ','Yi ', + 'Ting ','Jia ','Da ','Duo ','Xi ','Dan ','Tiao ','Xie ','Chang ','Yuan ','Guan ','Liang ','Beng ','Gei ','Lu ','Ji ', + 'Xuan ','Shu ','Dou ','Shu ','Hu ','Yun ','Chan ','Bong ','Rong ','E ','Zung ','Ba ','Feng ','Zyu ','Zhe ','Fen ', + 'Guan ','Bu ','Ge ','Deon ','Huang ','Du ','Ti ','Bo ','Qian ','La ','Long ','Wei ','Zhan ','Lan ','Seoi ','Na ', + 'Bi ','Tuo ','Jiao ','','Bu ','Ju ','Po ','Xia ','Wei ','Fu ','He ','Fan ','Chan ','Hu ','Za ','', + 'Saai ','Zai ','Zai ','Zai ','Fan ','Die ','Hong ','Chi ','Bao ','Yin ','','Haang ','Bo ','Ruan ','Chou ','Ying ', + 'Zi ','Gai ','Kwaan ','Yun ','Zhen ','Ya ','Zeoi ','Hou ','Min ','Pei ','Ge ','Bian ','Zyut ','Hao ','Mi ','Sheng ', + 'Gen ','Bi ','Duo ','Chun ','Chua ','San ','Cheng ','Ran ','Zen ','Mao ','Bo ','Tui ','Pi ','Fu ','Zyut ','Hei ', + 'Lin ','Hei ','Men ','Wu ','Qi ','Zhi ','Chen ','Xia ','He ','Sang ','Gwaa ','Hou ','Au ','Fu ','Rao ','Hun ', + 'Pei ','Qian ','Si ','Xi ','Ming ','Kui ','Ge ','','Ao ','San ','Shuang ','Lou ','Zhen ','Hui ','Can ','Ci ', + 'Lin ','Na ','Han ','Du ','Jin ','Mian ','Fan ','E ','Nao ','Hong ','Hong ','Xue ','Xue ','Pau ','Bi ','Ciu ', + ], + 'x4b':[ + 'You ','Yi ','Xue ','Sa ','Yu ','Li ','Li ','Yuan ','Dui ','Hao ','Qie ','Leng ','Paau ','Fat ','Guo ','Bu ', + 'Wei ','Wei ','Saau ','An ','Xu ','Shang ','Heng ','Yang ','Gwik ','Yao ','Fan ','Bi ','Ci ','Heng ','Tao ','Liu ', + 'Fei ','Zhu ','Tou ','Qi ','Chao ','Yi ','Dou ','Yuan ','Cu ','Zai ','Bo ','Can ','Yang ','Tou ','Yi ','Nian ', + 'Shao ','Ben ','Ngaau ','Ban ','Mo ','Ai ','En ','She ','Caan ','Zhi ','Yang ','Jian ','Yuan ','Dui ','Ti ','Wei ', + 'Xun ','Zhi ','Yi ','Ren ','Shi ','Hu ','Ne ','Yi ','Jian ','Sui ','Ying ','Bao ','Hu ','Hu ','Xie ','', + 'Yang ','Lian ','Sik ','En ','Deoi ','Jian ','Zhu ','Ying ','Yan ','Jin ','Chuang ','Dan ','','Kuai ','Yi ','Ye ', + 'Jian ','En ','Ning ','Ci ','Qian ','Xue ','Bo ','Mi ','Shui ','Mi ','Liang ','Qi ','Qi ','Shou ','Bi ','Bo ', + 'Beng ','Bie ','Ni ','Wei ','Huan ','Fan ','Qi ','Liu ','Fu ','Ang ','Ang ','Fan ','Qi ','Qun ','Tuo ','Yi ', + 'Bo ','Pian ','Bo ','Keoi ','Xuan ','','Baai6','Yu ','Chi ','Lu ','Yi ','Li ','Zaau ','Niao ','Xi ','Wu ', + 'Gwing ','Lei ','Pei ','Zhao ','Zui ','Chuo ','Coeng ','An ','Er ','Yu ','Leng ','Fu ','Sha ','Huan ','Chu ','Sou ', + 'Bik ','Bi ','Die ','Song ','Di ','Li ','Giu ','Han ','Zai ','Gu ','Cheng ','Lou ','Mo ','Mi ','Mai ','Ao ', + 'Dan ','Zhu ','Huang ','Fan ','Deng ','Tong ','','Du ','Hu ','Wei ','Ji ','Chi ','Lin ','Biu ','Pang ','Jian ', + 'Nie ','Luo ','Ji ','Ngon ','Waa ','Nie ','Yi ','Gwaat6','Wan ','Ya ','Qia ','Bo ','Hau ','Ling ','Gan ','Huo ', + 'Hai ','Hong ','Heng ','Kui ','Cen ','Ting ','Lang ','Bi ','Huan ','Po ','Ou ','Jian ','Ti ','Sui ','Kwaa ','Dui ', + 'Ao ','Jian ','Mo ','Gui ','Kuai ','An ','Ma ','Qing ','Fen ','','Kao ','Hao ','Duo ','Cim ','Nai ','Seoi ', + 'Jie ','Fu ','Pa ','Sung ','Chang ','Nie ','Man ','Sung ','Ci ','Cim ','Kuo ','Gai ','Di ','Fu ','Tiao ','Zu ', + ], + 'x4c':[ + 'Wo ','Fei ','Cai ','Peng ','Shi ','Sou ','Rou ','Qi ','Cha ','Pan ','Bo ','Man ','Zong ','Ci ','Gui ','Ji ', + 'Lan ','Siu ','Meng ','Mian ','Pan ','Lu ','Cuan ','Gau ','Liu ','Yi ','Wen ','Li ','Li ','Zeng ','Zhu ','Hun ', + 'Shen ','Chi ','Xing ','Wang ','Dung ','Huo ','Pi ','Bou6','Mei ','Che ','Mei ','Chao ','Ju ','Nou ','','Ni ', + 'Ru ','Ling ','Ya ','','Qi ','Zi ','','Bang ','Gung ','Ze ','Jie ','Yu ','Xin ','Bei ','Ba ','Tuo ', + 'Ong ','Qiao ','You ','Di ','Jie ','Mo ','Sheng ','Shan ','Qi ','Shan ','Mi ','Dan ','Yi ','Geng ','Geng ','Tou ', + 'Fu ','Xue ','Yi ','Ting ','Tiao ','Mou ','Liu ','Caan ','Li ','Suk ','Lu ','Xu ','Cuo ','Ba ','Liu ','Ju ', + 'Zhan ','Ju ','Zang ','Zu ','Xian ','Zhi ','','','Zhi ','','','La ','Seoi ','Geng ','E ','Mu ', + 'Zhong ','Di ','Yan ','Zin ','Geng ','Zung ','Lang ','Yu ','Caau ','Na ','Hai ','Hua ','Zhan ','Coeng ','Lou ','Chan ', + 'Die ','Wei ','Xuan ','Zao ','Min ','Kwai ','Sou ','','','Si ','Tuo ','Cen ','Kuan ','Teng ','Nei ','Lao ', + 'Lu ','Yi ','Xie ','Yan ','Qing ','Pu ','Chou ','Xian ','Guan ','Jie ','Lai ','Meng ','Ye ','Ceoi ','Li ','Yin ', + 'Ceon ','Cau ','Teng ','Yu ','','Gau ','Cha ','Du ','Hong ','Si ','Xi ','Gaau ','Qi ','Ci ','Yuan ','Ji ', + 'Yun ','Fang ','Gung ','Hang ','Zhen ','Hu ','','','Jie ','Pei ','Gan ','Xuan ','Saang ','Dao ','Qiao ','Ci ', + 'Die ','Ba ','Tiao ','Wan ','Ci ','Zhi ','Bai ','Wu ','Bao ','Dan ','Ba ','Tong ','Gyun ','Gung ','Jiu ','Gui ', + 'Ci ','You ','Yuan ','Lao ','Jiu ','Fou ','Nei ','E ','E ','Xing ','He ','Yan ','Tu ','Bu ','Beng ','Kou ', + 'Chui ','Zeoi ','Qi ','Yuan ','Bit ','','Hyun ','Hou ','Huang ','Ziu ','Juan ','Kui ','E ','Ji ','Mo ','Chong ', + 'Bao ','Wu ','Zhen ','Xu ','Da ','Chi ','Gaai ','Cong ','Ma ','Kou ','Yan ','Can ','Aau ','He ','Dang ','Lan ', + ], + 'x4d':[ + 'Tong ','Yu ','Hang ','Nao ','Li ','Fen ','Pu ','Ling ','Ao ','Xuan ','Yi ','Xuan ','Meng ','Ang ','Lei ','Yan ', + 'Bao ','Die ','Ling ','Shi ','Jiao ','Lie ','Jing ','Ju ','Ti ','Pi ','Gang ','Jiao ','Huai ','Bu ','Di ','Huan ', + 'Yao ','Li ','Mi ','Fu ','Saang ','Gaa ','Ren ','Wai ','','Piao ','Lu ','Ling ','Yi ','Cai ','Shan ','Fat ', + 'Shu ','Tuo ','Mo ','He ','Tie ','Bing ','Peng ','Hun ','Fu ','Guo ','Bu ','Li ','Chan ','Bai ','Cuo ','Meng ', + 'Suo ','Qiang ','Zhi ','Kuang ','Bi ','Ao ','Meng ','Xian ','Guk ','Tou ','Teon ','Wei ','Cim ','Tan ','Caau ','Lao ', + 'Chan ','Ni ','Ni ','Li ','Dong ','Ju ','Jian ','Fu ','Sha ','Zha ','Tao ','Jian ','Nong ','Ya ','Jing ','Gan ', + 'Di ','Jian ','Mei ','Da ','Jian ','She ','Xie ','Zai ','Mang ','Li ','Gun ','Yu ','Ta ','Zhe ','Yang ','Tuan ', + 'Soeng ','He ','Diao ','Wei ','Yun ','Zha ','Qu ','Waa ','Caau ','Zi ','Ting ','Gu ','Soeng ','Ca ','Fu ','Tie ', + 'Ta ','Ta ','Zhuo ','Han ','Ping ','He ','Ceoi ','Zhou ','Bo ','Liu ','Nu ','Kaap ','Pao ','Di ','Sha ','Ti ', + 'Kuai ','Ti ','Qi ','Ji ','Chi ','Pa ','Jin ','Ke ','Li ','Ju ','Qu ','La ','Gu ','Qia ','Qi ','Xian ', + 'Jian ','Shi ','Xian ','Ai ','Hua ','Ju ','Ze ','Yao ','Tam ','Ji ','Cha ','Kan ','Gin ','','Yan ','Gwaai ', + 'Ziu ','Tong ','Nan ','Yue ','Ceoi ','Chi ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x4e':[ + 'Il ','Ceng ','Kyo ','Chil ','Sang ','Ha ','','Man ','Cang ','Sam ','Sang ','Ha ','Ki ','Pwu ','Ye ','Myen ', + 'Kal ','Chwuk ','Chou ','Zhuan ','Cha ','Pi ','Sey ','Shi ','Kwu ','Pyeng ','Ye ','Cong ','Dong ','Si ','Sung ','Cwu ', + 'Kwu ','Lyang ','Cwu ','Yu ','Lyang ','Yan ','Pyeng ','Sang ','Kon ','Kwu ','Kay ','A ','Qiang ','Cwung ','Kuk ','Jie ', + 'Pong ','Kwan ','Koc ','Chan ','Lin ','Chak ','Cwu ','Ha ','Hwan ','Tan ','Wei ','Cwu ','Ceng ','Li ','Ju ','Pyel ', + 'Pwul ','Yi ','Yey ','Nay ','Shime ','Kwu ','Kwu ','Cek ','Yo ','Yi ','','Ci ','Wu ','Sa ','Ho ','Phip ', + 'Le ','Im ','Ping ','Pang ','Qiao ','Hu ','Koy ','Sung ','Sung ','Ul ','Yin ','','Mya ','Kwu ','Kel ','Ya ', + 'Xi ','Xiang ','Gai ','Kyu ','Hal ','','Shu ','Twul ','Si ','Kyey ','Nang ','Kal ','Kel ','Tol ','','Ol ', + 'Mai ','Lan ','Cal ','Yu ','Xue ','Yan ','Phol ','Sal ','Na ','Gan ','Sol ','El ','Cwul ','','Kan ','Chi ', + 'Kwi ','Ken ','Lan ','Lin ','Uy ','Kwel ','Lyo ','Ma ','Ye ','Zheng ','Sa ','Sa ','I ','Chok ','Wu ','Yu ', + 'Wul ','Wun ','Ho ','Ki ','O ','Ceng ','Si ','Sui ','Sen ','Kung ','Ya ','Sa ','A ','Cey ','A ','Kuk ', + 'Twu ','Mang ','Hang ','Ta ','Kyo ','Hay ','Yek ','Chan ','Hyeng ','Mu ','','Hyang ','Kyeng ','Ceng ','Lyang ','Xiang ', + 'Kyeng ','Ya ','Qin ','Pak ','Yu ','Xie ','Tan ','Lyem ','Duo ','Mi ','In ','In ','Ji ','La ','Mang ','Yi ', + 'Sip ','In ','Luk ','Ding ','Chuk ','Jin ','Pwu ','Kwu ','Ba ','Zhang ','Kum ','Kay ','Bing ','Ing ','Cong ','Pwul ', + 'San ','Lun ','Sya ','Cang ','Ca ','Sa ','Tha ','Cang ','Pwu ','Sen ','Hen ','Cha ','Hong ','Tong ','In ','Chen ', + 'Gan ','Hul ','Cak ','Tay ','Lyeng ','I ','Chao ','Chang ','Sa ','','Yi ','Mu ','Men ','In ','Ka ','Chao ', + 'Ang ','Qian ','Cwung ','Pi ','Wan ','O ','Ken ','Kay ','Yao ','Feng ','Cang ','Im ','Wang ','Pin ','Di ','Pang ', + ], + 'x4f':[ + 'Cong ','Ki ','Pei ','Ye ','Diao ','Ton ','Wen ','Yek ','Sim ','Hang ','I ','Kup ','Ai ','O ','Ki ','Pok ', + 'Pel ','Hyu ','Jin ','Bei ','Dan ','Fu ','Tang ','Zhong ','You ','Hwa ','Hoy ','Yu ','Col ','Cen ','San ','Wei ', + 'Chuan ','Che ','Ya ','Hyen ','Shang ','Chang ','Lun ','Cang ','Xun ','Sin ','Wei ','Zhu ','','Xuan ','Nu ','Payk ', + 'Ko ','Ni ','Ni ','Xie ','Pan ','Xu ','Lyeng ','Zhou ','Sin ','Qu ','Sa ','Phayng ','Sa ','Ka ','Pi ','Yi ', + 'Sa ','I ','Ceng ','Cen ','Han ','Mai ','Tan ','Ce ','Pho ','Kwu ','Phi ','So ','Ci ','Wi ','Ce ','Cwu ', + 'Cwa ','Wu ','Ang ','Pwun ','Cem ','Ha ','Phil ','Tha ','Sa ','Ye ','Il ','Pwul ','Cak ','Kwu ','Nyeng ','Tong ', + 'Ni ','Xuan ','Qu ','Yong ','Wa ','Qian ','','Ka ','','Phay ','Hoy ','He ','Lao ','Xiang ','Ge ','Yang ', + 'Peyk ','Fa ','Ming ','Ka ','I ','Pyeng ','Kil ','Hang ','Kwal ','Kwey ','Cen ','Co ','Kyo ','Cha ','Il ','Sa ', + 'Hyeng ','Sin ','Thak ','Kan ','Cil ','Hay ','Lay ','I ','Chi ','Kwa ','Kwang ','Lyey ','Yin ','Si ','Mi ','Cwu ', + 'Hyek ','Yu ','An ','Lu ','Mo ','Er ','Lyun ','Tong ','Cha ','Chik ','Swun ','Kong ','Cwu ','Uy ','Ye ','Jian ', + 'Hyep ','Ka ','Zai ','Lye ','Ko ','Jiao ','Zhen ','Ce ','Qiao ','Kuai ','Chai ','Ning ','Nong ','Jin ','Mo ','Hwu ', + 'Jiong ','Cheng ','Cin ','Cwa ','Chou ','Chim ','Lye ','Kwuk ','Twu ','Ceng ','Shen ','Thal ','Bo ','Nan ','Hao ','Phyen ', + 'Tui ','Yu ','Kyey ','Chok ','A ','Kwu ','Xu ','Kwang ','Ku ','O ','Cwun ','Up ','Po ','Lyang ','Co ','So ', + 'Li ','Yong ','Hun ','Kyeng ','Hyen ','San ','Pai ','Sok ','Pwu ','Huy ','Li ','Myen ','Ping ','Po ','Yu ','Sa ', + 'Hyep ','Sin ','Xiu ','O ','Cey ','Ke ','Chou ','','Yan ','Lia ','Li ','Lai ','Si ','Jian ','Swu ','Pwu ', + 'Hwa ','Kwu ','Hyo ','Pay ','Chen ','Phyo ','Swuk ','Pi ','Pong ','A ','Em ','Pi ','Yu ','Xin ','Pi ','Jian ', + ], + 'x50':[ + 'Chang ','Chi ','Pyeng ','Kwu ','Hyo ','Swi ','Lyang ','Wan ','Lai ','Chang ','Zong ','Kay ','Kwan ','Pay ','Cen ','Swuk ', + 'Swuk ','Mwun ','To ','Tam ','Kwul ','Swu ','Hayng ','Pwung ','Tang ','Hwu ','Uy ','Ki ','Chek ','Kan ','Kyeng ','Cha ', + 'Hyu ','Chang ','Chep ','Pang ','Chi ','Kong ','Kwen ','Cong ','Ke ','Chen ','Yey ','Lyun ','Thak ','Wi ','La ','Song ', + 'Lung ','Hon ','Tong ','Sa ','Pwun ','Wu ','Kwu ','Nai ','Cai ','Kem ','Zhai ','Ya ','Chi ','Sha ','Qing ','', + 'Ying ','Ching ','Jian ','En ','Nan ','Tong ','Chwun ','Ka ','Key ','Wi ','Yu ','Bing ','Ya ','Ti ','Oy ','Phyen ', + 'An ','Feng ','Thang ','Ak ','E ','Hay ','Cha ','Sheng ','Kan ','Di ','Cwu ','Sap ','Ceng ','Pay ','Yep ','Hwang ', + 'Yo ','Zhan ','Cho ','Yan ','You ','Ken ','Xu ','Zha ','Chi ','Pwu ','Phip ','Chi ','Chong ','Myen ','Ji ','Uy ', + 'Sel ','Xun ','Si ','Duan ','Chuk ','Ceng ','Wu ','Thwu ','Thwu ','Pi ','Za ','Lu ','Jie ','Wi ','Fen ','Chang ', + 'Koy ','Sou ','Zhi ','So ','Xia ','Pwu ','Yuan ','Rong ','Li ','Ru ','Yun ','Kang ','Ma ','Pang ','Cen ','Tang ', + 'Hao ','Kel ','Hyey ','Sen ','Kyem ','Kak ','Chang ','Chu ','San ','Pi ','Hyo ','Yong ','Yo ','Thap ','Sa ','Yang ', + 'Fa ','Bing ','Ka ','Dai ','Zai ','Tang ','Cot ','Bin ','Chu ','Nuo ','Can ','Lei ','Choy ','Yong ','Co ','Chong ', + 'Pwung ','Song ','O ','Cen ','Kwu ','Chay ','Cou ','Sang ','Qiang ','Jing ','Cey ','Sa ','Han ','Cang ','Kyeng ','En ', + 'Di ','Sel ','Lwu ','Bei ','Phyo ','Kun ','Lyen ','Lyuk ','Man ','Chem ','Sen ','Tham ','Ying ','Tong ','Cwun ','Sang ', + 'Shan ','Kyo ','Kwun ','Tui ','Cwun ','Pok ','Huy ','Lao ','Chang ','Guang ','Lyo ','Ki ','Deng ','Can ','Wi ','Ki ', + 'Fan ','Hui ','Chen ','Cham ','Than ','Yo ','Chwu ','Sung ','Pwun ','Han ','Kyel ','E ','Cho ','Cham ','Tong ','Lin ', + 'Pwuk ','Gu ','','Su ','Xian ','Kang ','Min ','Yep ','Kum ','Ka ','Qiao ','Pyek ','Feng ','Chwu ','Ay ','Sa ', + ], + 'x51':[ + 'Uy ','Cwun ','Nong ','Chen ','Ek ','Dang ','Kyeng ','Hyen ','Koy ','Kem ','Chu ','Tam ','Kyo ','Sha ','Zai ','', + 'Pin ','Ap ','Yu ','Tay ','Cwu ','Cey ','Lan ','Uy ','Cin ','Qian ','Meng ','Mwu ','Nyeng ','Qiong ','Ni ','Sang ', + 'Lyep ','Loy ','Lye ','Kuang ','Pho ','Yuk ','Phyo ','Chan ','Cil ','Sa ','Wu ','Ho ','Chen ','Chun ','Li ','Teng ', + 'Wei ','Long ','Ce ','Cham ','Sang ','Swuk ','Hyey ','Lye ','La ','Chan ','Na ','Tang ','Em ','Lay ','Nang ','In ', + 'Ol ','Yun ','Cam ','Wen ','Hyeng ','Chwung ','Co ','Hyung ','Sen ','Kwang ','Thay ','Kuk ','Thay ','Myen ','Tho ','Chang ', + 'A ','Thay ','A ','Chim ','Tho ','Si ','Yen ','Yen ','Shi ','Sip ','Tang ','Chen ','Twu ','Fen ','Mao ','Sin ', + 'Dou ','Payk ','Kung ','Li ','Huang ','Ip ','Mang ','Nay ','Cen ','Lyang ','Yu ','Phal ','Kong ','Lyuk ','Hyey ','', + 'Lan ','Kong ','Tian ','Guan ','Xing ','Pyeng ','Ki ','Kwu ','Cen ','Ca ','Ppwun ','Yang ','Kyem ','Shou ','Ji ','Yi ', + 'Ki ','Chan ','Kyeng ','Mo ','Yem ','Nay ','Wen ','Mao ','Gang ','Yem ','Chayk ','Jiong ','Chayk ','Cay ','Gua ','Kyeng ', + 'Mo ','Cwu ','Mo ','Kwu ','Hwu ','Myen ','Myek ','Yong ','Yu ','Sa ','Kan ','Jun ','Nong ','Uy ','Mi ','Sek ', + 'Kwan ','Mong ','Chong ','Chwi ','Wen ','Myeng ','Kou ','Lam ','Pwu ','Sa ','Myek ','Ping ','Tong ','Tai ','Gang ','Feng ', + 'Ping ','Ho ','Chwung ','Kyel ','Ho ','Hwang ','Ya ','Layng ','Pan ','Pwul ','Min ','Dong ','Xian ','Lyel ','Xia ','Jian ', + 'Jing ','Swu ','Mei ','Tu ','Che ','Ko ','Cwun ','Song ','Ceng ','Lyang ','Cheng ','Co ','Lung ','Tong ','Gan ','Kam ', + 'Yin ','Cwu ','Uy ','Yul ','Chang ','Ming ','Cwun ','Choy ','Si ','Duo ','Kum ','Lum ','Lum ','Ung ','Huy ','Du ', + 'Kwey ','Pem ','Pem ','Pem ','Feng ','Ke ','Che ','Tako ','Phwung ','Mok ','Ci ','Fu ','Feng ','Ping ','Phwung ','Kai ', + 'Hwang ','Kay ','Gan ','Tung ','Ping ','Kam ','Hyung ','Koy ','Chel ','Yo ','Chwul ','Ji ','Dang ','Ham ','Ham ','Zao ', + ], + 'x52':[ + 'To ','Co ','To ','In ','In ','Chang ','Pwun ','Cel ','Yey ','Ji ','Kan ','Chen ','Chon ','Chu ','Mwun ','Ki ', + 'Dan ','Hyeng ','Hwa ','Wan ','Kyel ','Li ','Wel ','Lyel ','Lyu ','Ze ','Gang ','Chuang ','Pwul ','Cho ','Qu ','Ju ', + 'San ','Min ','Ling ','Zhong ','Phan ','Pyel ','Kep ','Kep ','Pho ','Li ','San ','Pyel ','Chan ','Jing ','Kwal ','Gen ', + 'To ','Chang ','Kyu ','Ko ','Tha ','I ','Cey ','Sway ','Kwen ','Chal ','Ca ','Kak ','Jie ','Gui ','Ci ','Gui ', + 'Kai ','Duo ','Ji ','Chey ','Kyeng ','Lou ','Gen ','Chik ','Yuan ','Cwa ','Sak ','Kuk ','Lal ','Cen ','Chal ','Chang ', + 'Gua ','Jian ','Chak ','Li ','Chek ','Pi ','Pwu ','Can ','Qi ','Chang ','Sa ','Kang ','Wan ','Pak ','Ki ','Chel ', + 'Kyeng ','Sem ','Zhuo ','Kem ','Ji ','Pak ','Em ','Ju ','Koyk ','Ing ','Cen ','Thak ','Tan ','Ok ','Kwa ','Pwu ', + 'Sheng ','Jian ','Hal ','Cha ','Kay ','Chang ','Juan ','San ','Tan ','Lyuk ','Li ','Fou ','Shan ','Phyo ','Kou ','Cho ', + 'Kwal ','Qiao ','Kwey ','Hoyk ','Cha ','Zhuo ','Lian ','Kuk ','Pyek ','Lyu ','Hoy ','Co ','Kwi ','Kem ','Kem ','Tang ', + 'Hwak ','Cey ','Kem ','Uy ','Kem ','Zhi ','Cham ','Chan ','Ma ','Li ','Chok ','Lyek ','Ya ','Quan ','Ban ','Kong ', + 'Ka ','Wu ','Mai ','Lyel ','Kun ','Keng ','Hyep ','Zhi ','Dong ','Co ','No ','Kep ','Kwu ','Cho ','Il ','Zhu ', + 'Miao ','Lye ','Jing ','Lao ','Lo ','Kwen ','Kwu ','Yang ','Wa ','Hyo ','Mou ','Kwang ','Hal ','Lie ','Hayk ','Shi ', + 'Kuk ','Kyeng ','Hao ','Pal ','Min ','Chik ','Lang ','Yong ','Yong ','Myen ','Ke ','Xun ','Kwen ','Kyeng ','Lu ','Pou ', + 'Meng ','Lay ','Luk ','Kai ','Min ','Tong ','Wuk ','Wuk ','Kam ','Mwu ','Yi ','Hwun ','Weng ','Sung ','Lo ','Mo ', + 'Lyuk ','Phyo ','Sey ','Cek ','Kun ','Qiang ','Cho ','Kwen ','Yang ','Yey ','Jue ','Fan ','Juan ','Tong ','Ke ','Tan ', + 'Hyep ','May ','Hwun ','Hwun ','Lye ','Lye ','Chel ','Yang ','Kwen ','Pho ','Cak ','Kyun ','Kwu ','Mwun ','Kwu ','Mwul ', + ], + 'x53':[ + 'Kyun ','Mwun ','Nay ','Kay ','Kay ','Pho ','Chong ','','Hung ','Phyeng ','Kwuk ','To ','Hap ','Pho ','Ap ','Pho ', + 'Pok ','Kwung ','Tap ','Kwu ','Qiong ','Pi ','Hwa ','Pwuk ','Noy ','Si ','Pang ','Kwu ','I ','Cap ','Cang ','Kang ', + 'Cang ','Kwang ','Hu ','Kap ','Qu ','Pyen ','Gui ','Hyep ','Zang ','Kuang ','Pi ','Hu ','Yu ','Kwey ','Gui ','Hoy ', + 'Tan ','Kwey ','Lyem ','Lyem ','San ','Tok ','Kwu ','Qu ','Hyey ','Phil ','Kwu ','Yey ','Ap ','En ','Phyen ','Nik ', + 'Kwu ','Sip ','Sin ','Chen ','Ip ','Sap ','Col ','Sung ','O ','Hwey ','Pan ','Sey ','Sip ','Man ','Hua ','Xie ', + 'Man ','Pi ','Col ','Thak ','Hyep ','Tan ','Mai ','Nam ','Tan ','Cip ','Pak ','Shuai ','Pok ','Kwan ','Pyen ','Key ', + 'Cem ','Cap ','Lu ','Yu ','Lu ','Xi ','Kway ','Wo ','Sel ','Cel ','Jie ','Wei ','Ang ','Kong ','Chi ','Myo ', + 'In ','Wi ','So ','Cuk ','Kak ','Lan ','Si ','Kwen ','Sa ','Hyul ','Kun ','Kak ','Ol ','Cuk ','Ak ','Kyeng ', + 'Sul ','','Em ','Cem ','Ayk ','Ting ','Li ','Chayk ','Han ','Lye ','A ','Ap ','Yan ','She ','Ci ','Zha ', + 'Pang ','','He ','Ay ','Cil ','Ce ','Pang ','Ti ','Li ','She ','Hwu ','Ting ','Zui ','Co ','Pi ','Wen ', + 'Chuk ','Yuan ','Xiang ','Yan ','Lyek ','Kwel ','Ha ','Dian ','Cwu ','Kwu ','Kun ','Ao ','Kwey ','Yem ','Si ','Li ', + 'Chang ','Em ','Lye ','Em ','Yan ','Wen ','Sa ','Koyng ','Lin ','Kwu ','Ke ','Ke ','Uk ','Lwi ','Du ','Xian ', + 'Zhuan ','Sam ','Sam ','Cham ','Cham ','Cham ','Ai ','Dai ','Wu ','Cha ','Kup ','Wu ','Ssang ','Pan ','Shou ','Kway ', + 'Ba ','Fa ','Yak ','Sa ','Swuk ','Chel ','Chwi ','Swu ','Pyen ','Se ','Ka ','Pan ','Sou ','Gao ','Wi ','Swu ', + 'Die ','Yey ','Chong ','Kwu ','Ko ','Kwu ','Lyeng ','Gua ','To ','Ko ','Ci ','Kyu ','So ','Phal ','Ceng ','Ka ', + 'Thay ','Cil ','Sa ','Wu ','Kwu ','Pha ','Hyep ','Ho ','Sa ','Tan ','Ip ','Le ','Diao ','Ji ','Duk ','Hong ', + ], + 'x54':[ + 'Mie ','Yu ','Mang ','Hul ','Kak ','Hyen ','Yo ','Zi ','Hap ','Kil ','Cek ','Chon ','Tong ','Myeng ','Hwu ','Li ', + 'Tho ','Hyang ','Tha ','Xia ','Ye ','Lye ','A ','Ma ','Wu ','Xue ','Uy ','Kwun ','Chou ','Lin ','Than ','Um ', + 'Phyey ','Phil ','Sim ','Qin ','Jie ','Bu ','Pwu ','Pha ','Twun ','Pwun ','Wa ','Ham ','Un ','Hang ','Cen ','Kyey ', + 'Hong ','Ci ','Sin ','O ','O ','Myo ','Nwul ','Hyel ','Hup ','Chwi ','Twu ','Mwun ','Hwu ','Hwu ','O ','Ko ', + 'Ha ','Jun ','Lye ','Ay ','Ge ','May ','May ','Qi ','Ceng ','O ','Ko ','Fu ','Kyu ','Hong ','Chek ','Sung ', + 'Nwul ','Than ','Fu ','Yi ','Dai ','Ou ','Li ','Bai ','Yuan ','Kuai ','','Qiang ','Wu ','Ayk ','Shi ','Hyen ', + 'Pen ','Wen ','Ni ','Bou ','Lyeng ','Ran ','Yu ','Cey ','Cwu ','Shi ','Cwu ','Chep ','Hi ','Yey ','Ki ','Ping ', + 'Ca ','Ko ','Zi ','Mi ','Kwu ','Ka ','No ','Hap ','Pi ','Il ','Hyo ','Sin ','Ho ','Myeng ','Tal ','Ke ', + 'Ce ','Kan ','Cap ','Tuo ','Tol ','Pou ','Pho ','Phil ','Pwul ','Ang ','Hwa ','Sa ','Hwa ','Hay ','Kwu ','Yeng ', + 'Pwu ','Que ','Cwu ','Wa ','Ka ','Ko ','Ka ','Zuo ','Bu ','Long ','Dong ','Ning ','Tha ','Si ','Xian ','Huo ', + 'Cip ','I ','Ak ','Guang ','Tha ','Huy ','I ','Lyel ','Ca ','Mi ','Mi ','Ci ','Kyo ','Kil ','Cwu ','Kak ', + 'Shuai ','Chal ','So ','Hay ','Hui ','Kua ','Si ','To ','Ham ','E ','Hwen ','Hyu ','Kway ','In ','Lao ','I ', + 'Ay ','Phwum ','Sin ','Tong ','Hong ','Hyung ','Chi ','Wa ','Hap ','Cay ','Yu ','Di ','Pai ','Sang ','Ay ','Hen ', + 'Kuang ','Ya ','Da ','Xiao ','Bi ','Yue ','','Hua ','Sasou ','Kuai ','Duo ','','Ji ','Nong ','Mou ','Yo ', + 'Hao ','Wen ','Long ','Pou ','Pang ','Ka ','A ','Chi ','Cho ','Li ','Na ','Cok ','Ha ','Kok ','Hyo ','Hyen ', + 'Lo ','Pal ','Chel ','Chal ','Liang ','Ba ','Ma ','Lyel ','Sui ','Pwu ','Pho ','Han ','Hyeng ','Kyeng ','Shuo ','Ka ', + ], + 'x55':[ + 'Yu ','En ','Gu ','Gu ','Phay ','Ham ','Sa ','Cin ','Up ','Ay ','Kyep ','Tu ','Yen ','Wan ','Li ','Huy ', + 'Tang ','Zuo ','Qiu ','Che ','O ','Co ','A ','Dou ','Qi ','Di ','Chim ','Ma ','Mal ','Hong ','Dou ','Kes ', + 'Lao ','Liang ','Suo ','Zao ','Hwan ','Laang ','Sha ','Ji ','Zuo ','Wo ','Pong ','Kum ','Ho ','Ki ','Swu ','Yu ', + 'Shua ','Chang ','A ','Lye ','Kang ','An ','Cha ','Yuk ','Cem ','E ','Tian ','Lai ','Sap ','Xi ','Tha ','Hol ', + 'Ay ','Co ','Nyo ','Sap ','Thak ','Thak ','Sang ','Cek ','Heng ','Lam ','A ','Kyo ','Xiang ','Thon ','O ','Mwun ', + 'Chway ','Cap ','Hu ','Kyey ','Qi ','To ','Tam ','Tam ','Ye ','Ca ','Pi ','Cui ','Chel ','Wa ','A ','Kyey ', + 'Zhe ','Pay ','Liang ','Ham ','Pi ','Sha ','La ','Ze ','Qing ','Gua ','Pa ','Zhe ','Se ','Zhuan ','Nie ','Guo ', + 'Luo ','Yan ','Di ','Quan ','Tan ','Bo ','Ding ','Lang ','Xiao ','Geoi ','Tang ','Si ','Cey ','Am ','Chwu ','Tam ', + 'Kayk ','Ong ','Wei ','Nam ','Sen ','Yuk ','Chel ','Lal ','Kay ','Hwu ','Ham ','Chep ','Cwu ','Cay ','Wai ','Ya ', + 'Yu ','Um ','Cam ','Yo ','Ak ','Mian ','Hu ','Wun ','Chen ','Hwey ','Hwan ','Hwan ','Huy ','Kal ','Cul ','Wi ', + 'Cong ','Wei ','Sha ','Hwu ','Hwang ','Du ','Yep ','Hwen ','Lyang ','Yu ','Sang ','Kkik ','Kyo ','An ','Tan ','Pen ', + 'Sik ','Li ','Yak ','Sa ','Wei ','Miao ','Yeng ','Pen ','Phos ','Kui ','Xi ','Yu ','Jie ','Lou ','Ku ','So ', + 'Hak ','Cey ','Yo ','Hyo ','Sa ','Hwu ','Chang ','Sayk ','Ong ','So ','Hong ','Hyep ','I ','Suo ','Ma ','Cha ', + 'Hal ','Hap ','Thap ','Sang ','Cin ','Yok ','Sou ','Wa ','Ji ','Pang ','O ','Kyem ','Ki ','Kyek ','Ca ','Cha ', + 'La ','Ong ','Ol ','Sa ','Chi ','Hao ','Suo ','Lyun ','Hai ','Sway ','Qin ','Nie ','He ','Cis ','Sai ','Ng ', + 'Ge ','Na ','Dia ','Ai ','','Tong ','Phil ','O ','O ','Lyen ','Choy ','Cha ','Mak ','Swu ','Cwu ','Tham ', + ], + 'x56':[ + 'Di ','Chuk ','Kyo ','Chong ','Kyo ','Kay ','Than ','Sam ','Co ','Ka ','Ay ','Xiao ','Phyo ','Lwu ','Al ','Ha ', + 'Kyo ','Ho ','Hyey ','Koyk ','Kwu ','En ','Chayk ','Sang ','He ','Po ','De ','Ma ','Ma ','Hu ','Luk ','To ', + 'Al ','Tang ','Ye ','Beng ','Ying ','Saai ','Jiao ','Mi ','So ','Hwa ','Mai ','Yen ','Choy ','Peng ','Cho ','So ', + 'Ki ','Chok ','Co ','Koy ','Chwi ','Hyo ','Si ','Ho ','Mwu ','Lyo ','Kyo ','Huy ','Hyu ','Than ','Tam ','Mwuk ', + 'Son ','O ','Cwun ','Pen ','Chi ','Wi ','Cham ','Tam ','Chwuk ','Tam ','Yul ','Thon ','Cayng ','Cho ','Yel ','Hup ', + 'Ki ','Hao ','Lian ','He ','Deng ','Wi ','Yin ','Pu ','Jue ','Qin ','Xun ','Nie ','Lu ','Si ','Em ','Ying ', + 'Tal ','Dan ','Wuk ','Cwu ','Kum ','Nong ','El ','Hway ','Ki ','Ak ','Co ','Huy ','Se ','Kyo ','Yen ','Ay ', + 'Ong ','Kyak ','Khway ','Wu ','Pwun ','Dao ','Kal ','Xin ','Thon ','Dang ','Sin ','Sai ','Pi ','Pi ','Yin ','Zui ', + 'Nyeng ','Di ','Lam ','Thap ','Hoyk ','Yu ','Hyo ','Ha ','Ya ','Duo ','Pi ','Chou ','Cey ','Cin ','Ho ','Chey ', + 'Chang ','','','Ca ','Chey ','Lo ','Hui ','Pak ','Wu ','Kyo ','Un ','Hak ','Mwuk ','Huang ','Zhe ','Li ', + 'Lyu ','Haai ','Nang ','Xiao ','Mo ','Yen ','Lyek ','Lo ','Long ','Fu ','Tam ','Chin ','Pin ','Pi ','Hyang ','Huo ', + 'Mo ','Huy ','Tha ','Ko ','Em ','Chan ','Ayng ','Yang ','Dian ','La ','Ta ','Hyo ','Cak ','Chuo ','Hwan ','Huo ', + 'Cen ','Sep ','Hyo ','Cap ','Li ','Chen ','Chay ','Li ','Yey ','La ','Nang ','Chal ','Su ','Huy ','So ','Kan ', + 'Cal ','Chok ','Lan ','Sel ','Nang ','Trom ','Lo ','Kwuk ','Hui ','In ','Swu ','Sa ','Nin ','Ken ','Hoy ','Sin ', + 'In ','Nan ','Tuan ','Tan ','Ton ','Kang ','Yen ','Kyeng ','Pian ','Wun ','Chang ','Hol ','Hoy ','Wan ','Wa ','Guo ', + 'Kon ','Chong ','Wi ','To ','Wei ','Lun ','Kwuk ','Kyun ','Ri ','Lyeng ','Ko ','Guo ','Tai ','Kwuk ','Tu ','Yu ', + ], + 'x57':[ + 'Kwuk ','Un ','Hon ','Pho ','E ','Ham ','Yuan ','Lyun ','Kwen ','E ','Cheng ','Kwuk ','Chen ','Wi ','Wen ','Kwen ', + 'Ku ','Fu ','Wen ','Wen ','E ','Toshokan ','To ','To ','Tan ','Lue ','Hui ','Yek ','Wen ','Lan ','Luan ','Tho ', + 'Ya ','Tu ','Ting ','Sheng ','Pu ','Lok ','Iri ','Ap ','Cay ','Wei ','Ge ','Yu ','O ','Kyu ','Pi ','Yi ', + 'Ci ','Qian ','Qian ','Zhen ','Zhuo ','Dang ','Qia ','Akutsu ','Yama ','Kuang ','Chang ','Ki ','Nie ','Mo ','Kup ','Jia ', + 'Ci ','Zhi ','Phan ','Xun ','Tou ','Qin ','Fen ','Kyun ','Keng ','Tun ','Pang ','Fen ','Pwun ','Tam ','Kam ','Pay ', + 'Cwa ','Kayng ','Bi ','Xing ','Di ','Jing ','Ji ','Kuai ','Di ','Jing ','Jian ','Tan ','Li ','Ba ','Wu ','Fen ', + 'Zhui ','Pha ','Pan ','Tang ','Kon ','Qu ','Than ','Chek ','I ','Kam ','Phyeng ','Cem ','Gua ','Ni ','Tay ','Pay ', + 'Kyeng ','Ang ','Fo ','Yo ','Liu ','Kwu ','Mu ','Ka ','Kwu ','Xue ','Ba ','Ci ','Thak ','Ling ','Zhu ','Fu ', + 'Hu ','Zhi ','Swu ','La ','Long ','Long ','Lu ','Ao ','Tay ','Pao ','','Hyeng ','Tong ','Ji ','Ke ','Lu ', + 'Ci ','Chi ','Lei ','Hay ','Yin ','Hwu ','Dui ','Zhao ','Fu ','Guang ','Yao ','Duo ','Duo ','Gui ','Tha ','Yang ', + 'Un ','Fa ','Kwu ','Wen ','Cil ','Xie ','Ken ','Jiong ','Shou ','Seng ','Ha ','Dian ','Hong ','Wu ','Kua ','', + 'Tao ','Dang ','Kai ','Gake ','Nao ','An ','Xing ','Xian ','Wan ','Bang ','Pei ','Ba ','Yi ','Un ','Han ','Xu ', + 'Chui ','Cen ','Geng ','Ay ','Peng ','Fang ','Kak ','Yong ','Cwun ','Hyep ','Di ','May ','Lang ','Xuan ','Seng ','Yen ', + 'Jin ','Chel ','Lal ','Lie ','Pu ','Cheng ','Gomi ','Bu ','Shi ','Xun ','Guo ','Jiong ','Ya ','Nian ','Di ','Yek ', + 'Pwu ','Ya ','Juan ','Sui ','Pi ','Cheng ','Wan ','Ju ','Lun ','Zheng ','Kong ','Chong ','Dong ','Thay ','Tan ','An ', + 'Chay ','Shu ','Beng ','Kam ','Sik ','Duo ','Yi ','Cip ','Yi ','Pay ','Ki ','Cwun ','Ki ','So ','Ju ','Ni ', + ], + 'x58':[ + 'Kwul ','Ke ','Tang ','Kon ','Ni ','Kyen ','Thoy ','Kun ','Kang ','Yuk ','Ak ','Pwul ','Gu ','Tu ','Leng ','', + 'Ya ','Qian ','','An ','','Tha ','Nao ','Tol ','Cheng ','In ','Hun ','Bi ','Lian ','Kwa ','Chep ','Zhuan ', + 'Hwu ','Po ','Bao ','Yu ','Cey ','Mao ','Kyey ','Yen ','E ','Geng ','Kam ','Zong ','Yu ','Huang ','E ','Yo ', + 'En ','Po ','Ji ','Mei ','Cang ','To ','Tuo ','Yin ','Feng ','Zhong ','Kyey ','Zhen ','Feng ','Gang ','Chuan ','Jian ', + 'Pyeng ','Rui ','Xiang ','Huang ','Leng ','Duan ','','Xuan ','Ji ','Chek ','Koy ','Yeng ','Thap ','Sup ','Yong ','Kay ', + 'So ','So ','Si ','Mi ','Thap ','Weng ','Cheng ','To ','Tang ','Ko ','Chong ','Li ','Pong ','Bang ','Say ','Zang ', + 'Dui ','Cen ','O ','Cheng ','Hwun ','Ge ','Zhen ','Ai ','Gong ','Yem ','Kan ','Cen ','Yuan ','Wen ','Xie ','Liu ', + 'Ama ','Lang ','Chang ','Peng ','Beng ','Cin ','Cu ','Lu ','Ou ','Cham ','Mei ','Mo ','Cen ','Sang ','Swuk ','Lou ', + 'Ci ','Man ','Biao ','Kyeng ','Qi ','Se ','Di ','Zhang ','Kan ','Yong ','Cem ','Chen ','Zhi ','Ki ','Guo ','Qiang ', + 'Kun ','Di ','Shang ','Myo ','Cui ','Yan ','Ta ','Cung ','Qi ','Qiang ','Liang ','','Chwu ','Yo ','Cung ','He ', + 'Shan ','Sen ','Ba ','Pok ','Kuai ','Dong ','Fan ','Que ','Mwuk ','Ton ','Dun ','Cwun ','Di ','Sheng ','Tha ','Duo ', + 'Tam ','Tung ','Wu ','Pwun ','Huang ','Tan ','Da ','Ye ','Sho ','Mama ','O ','Cang ','Ji ','Qiao ','Kan ','Yi ', + 'Pi ','Pyek ','Dian ','Kang ','Ye ','Ong ','Bo ','Tan ','Lan ','Ju ','Huai ','Dang ','Yang ','Qian ','Hwun ','Lan ', + 'Xi ','Hak ','Ai ','Ap ','To ','Ho ','Ruan ','Mama ','Lwu ','Kwang ','Lo ','Yan ','Tam ','Yu ','Koy ','Long ', + 'Long ','Rui ','Li ','Lin ','Yang ','Ten ','Xun ','Yan ','Lei ','Pha ','','Sa ','Im ','','Cang ','Cang ', + 'Seng ','Il ','May ','Ke ','Zhu ','Zhuang ','Hu ','Hu ','Kun ','Il ','Ho ','Se ','Ho ','Swu ','Mang ','Zun ', + ], + 'x59':[ + 'Shou ','Yi ','Zhi ','Gu ','Chu ','Jiang ','Pong ','Bei ','Cay ','Pyen ','Sui ','Qun ','Ling ','Fu ','Zuo ','Ha ', + 'Hyeng ','','Nao ','Xia ','Ki ','Sek ','Oy ','Yuan ','Mao ','Swuk ','Ta ','Duo ','Ya ','Qing ','Uys ','Gou ', + 'Gou ','Qi ','Mong ','Meng ','In ','Kwa ','Chen ','Tay ','Ze ','Chen ','Thay ','Pwu ','Khway ','Yo ','Ang ','Hang ', + 'Gao ','Sil ','Ben ','Tai ','Tou ','Yan ','Bi ','I ','Kwa ','Jia ','Duo ','Kwu ','Kuang ','Yun ','Hyep ','Pa ', + 'En ','Lian ','Huan ','Di ','Em ','Pao ','Quan ','Ki ','Nay ','Pong ','Xie ','Fen ','Cem ','','Kyu ','Cwu ', + 'Hwan ','Kyey ','Kai ','Cha ','Pwun ','Hyek ','Jiang ','Thwu ','Cang ','Ben ','Hay ','Xiang ','Fei ','Diao ','Xun ','Keng ', + 'Cen ','Ao ','Sa ','Weng ','Pan ','O ','Wu ','O ','Cang ','Lyem ','Thal ','Yun ','Cang ','Sek ','Pwun ','Huo ', + 'Bi ','Lian ','Duo ','Nye ','No ','Ding ','Nay ','Qian ','Kan ','Ta ','Jiu ','Nan ','Cha ','Ho ','Xian ','Fan ', + 'Ji ','Cak ','Ye ','Pi ','Mang ','Hong ','Zhuang ','Fu ','Ma ','Dan ','Im ','Fu ','Jing ','Yen ','Xie ','Wen ', + 'Zhong ','Pha ','Thwu ','Ki ','Keng ','Zhong ','Yo ','Kum ','Yun ','Myo ','Pei ','Shi ','Yue ','Cang ','Niu ','Yan ', + 'Na ','Xin ','Fen ','Pi ','Yu ','Tha ','Feng ','Wan ','Pang ','Wu ','Yu ','Gui ','Thwu ','Ba ','Ni ','Chwuk ', + 'Zhuo ','Zhao ','Tal ','Nai ','Yuan ','Tou ','Xuan ','Zhi ','E ','May ','Mo ','Che ','Bi ','Shen ','Chep ','E ', + 'He ','Xu ','Fa ','Ceng ','Min ','Ban ','Mo ','Fu ','Lyeng ','Ca ','Zi ','Si ','Ran ','San ','Yang ','Man ', + 'Ce ','Ko ','Sa ','Seng ','Wi ','Zi ','Ju ','San ','Pin ','Im ','Yo ','Tong ','Kang ','Cwu ','Kil ','Gai ', + 'Shang ','Kuo ','Yen ','Kyo ','Kwu ','Mo ','Kan ','Jian ','I ','Nian ','Cil ','Huy ','Huy ','Xian ','Hang ','Guang ', + 'Jun ','Kua ','Yan ','Ming ','Lie ','Pei ','Yan ','You ','Yen ','Cha ','Sin ','In ','Chi ','Gui ','Quan ','Ca ', + ], + 'x5a':[ + 'Song ','Wi ','Hong ','Way ','Lou ','Ya ','Rao ','Jiao ','Luan ','Ping ','Xian ','Shao ','Li ','Cheng ','Xiao ','Mang ', + '','Sa ','Wu ','Mi ','Ke ','Lai ','Chuo ','Ding ','Nang ','Hyeng ','Nan ','O ','Na ','Pei ','Nei ','Yen ', + 'Sin ','Zhi ','Han ','Cey ','Zhuang ','A ','Pin ','Thay ','Han ','Man ','Wu ','Yan ','Wu ','Ay ','Yan ','O ', + 'Si ','Yu ','Wa ','','Xian ','Chwu ','Chwi ','Shui ','Qi ','Xian ','Zhui ','Dong ','Chang ','Lu ','Ai ','A ', + 'A ','Lwu ','Mian ','Cong ','Pou ','Ju ','Pha ','Cai ','Ding ','Wan ','Biao ','Xiao ','Swuk ','Qi ','Hui ','Fu ', + 'Wa ','Wo ','Tan ','Fei ','','Jie ','Tian ','Ni ','Quan ','Jing ','Hon ','Jing ','Qian ','Dian ','Xing ','Hu ', + 'Wa ','Lai ','Pi ','In ','Zhou ','Chuo ','Pwu ','Ceng ','Lun ','Yan ','Lam ','Kun ','Um ','Ya ','','Li ', + 'Dian ','Xian ','Hwa ','Hua ','Ying ','Chan ','Shen ','Ceng ','Dang ','Yao ','Wu ','Nan ','Ruo ','Jia ','Tou ','Se ', + 'Yu ','Wei ','Ti ','Rou ','Mi ','Dan ','Ruan ','Qin ','','Wu ','Qian ','Chun ','Mao ','Pwu ','Jie ','Duan ', + 'Xi ','Zhong ','May ','Hwang ','Mian ','Am ','Ying ','Xuan ','','Wei ','Mi ','Wen ','Zhen ','Qiu ','Ti ','Sel ', + 'Tuo ','Lian ','Mo ','Ran ','Si ','Pian ','Wei ','Way ','Jiu ','Hu ','O ','','Ho ','Xu ','Tou ','Gui ', + 'Zou ','Yao ','Pi ','Sik ','Yuan ','Ing ','Rong ','Ru ','Chi ','Liu ','Mi ','Pan ','On ','Ma ','Kwu ','Koy ', + 'Qin ','Ka ','Swu ','Zhen ','Wen ','Cha ','Yong ','Ming ','Ayng ','Cil ','Su ','Nyo ','Hyem ','Tao ','Pang ','Lang ', + 'Nao ','Bao ','Ai ','Pi ','Pin ','Yi ','Phyo ','Kwu ','Lei ','Sen ','Man ','Yey ','Zhang ','Kang ','Yong ','Ni ', + 'Li ','Cek ','Kyu ','En ','Jin ','Cen ','Hang ','Ce ','Han ','Nwun ','Lao ','Mo ','Zhe ','Ho ','Ho ','O ', + 'Nen ','Qiang ','Maa ','Pie ','Gu ','Wu ','Cho ','Tuo ','Zhan ','Mao ','Han ','Han ','Mo ','Lyo ','Lian ','Hua ', + ], + 'x5b':[ + 'Kyu ','Deng ','Zhi ','Xu ','','Hwa ','Xi ','Hui ','Yo ','Huy ','Yan ','Sen ','Kyo ','Mei ','Fan ','Fan ', + 'Xian ','Yi ','Wei ','Jiao ','Fu ','Shi ','Phyey ','Shan ','Sui ','Cang ','Lian ','Hyen ','','Niao ','Dong ','Yi ', + 'Can ','Ai ','Yang ','Neng ','Ma ','Co ','Chou ','Jin ','Ca ','Yu ','Pin ','','Xu ','Nay ','Yan ','Tai ', + 'Yeng ','Can ','Nyo ','','Yeng ','Mian ','Kaka ','Ma ','Shen ','Xing ','Ni ','Du ','Liu ','Yuan ','Lan ','Yen ', + 'Sang ','Ling ','Jiao ','Yang ','Lan ','Sem ','Ying ','Shuang ','Shuai ','Quan ','Mi ','Li ','Lyen ','Yan ','Zhu ','Lan ', + 'Ca ','Hyel ','Jue ','Jue ','Kong ','Ing ','Ca ','Ca ','Con ','Sun ','Pwu ','Phay ','Ca ','Hyo ','Xin ','Mayng ', + 'Si ','Thay ','Bao ','Kyey ','Ko ','No ','Hak ','','Zhuan ','Hay ','Luan ','Son ','Huai ','Mie ','Cong ','Qian ', + 'Swuk ','Can ','Ya ','Ca ','Ni ','Pwu ','Ca ','Li ','Hak ','Bo ','Yu ','Lai ','El ','El ','Ying ','San ', + 'Mian ','Ce ','Yong ','Ta ','Gui ','Tayk ','Qiong ','Wu ','Swu ','An ','Ka ','Song ','Wan ','Rou ','Yao ','Koyng ', + 'Yi ','Jing ','Zhun ','Pok ','Zhu ','Thang ','Hoyng ','Cong ','Kwan ','Cwu ','Ceng ','Wan ','Uy ','Po ','Shi ','Sil ', + 'Chong ','Shen ','Kayk ','Sen ','Sil ','Yu ','Hwan ','Yi ','Tiao ','Shi ','Xian ','Kwung ','Seng ','Qun ','Kwung ','Xiao ', + 'Cay ','Zha ','Bao ','Hay ','Yen ','So ','Ka ','Shen ','Sin ','Yong ','Huang ','Mil ','Kou ','Kuan ','Bin ','Swuk ', + 'Chay ','Zan ','Cek ','Wen ','Ki ','In ','Mil ','Kwu ','Qing ','Que ','Zhen ','Jian ','Pwu ','Ning ','Bing ','Huan ', + 'May ','Qin ','Han ','Wu ','Sik ','Nyeng ','Chim ','Nyeng ','Chi ','Yu ','Bao ','Kwan ','Nyeng ','Chim ','Mak ','Chal ', + 'Ju ','Kwa ','Chim ','Hu ','O ','Lyo ','Sil ','Nyeng ','Chay ','Sim ','Wei ','Sa ','Kwan ','Hyey ','Lyo ','Cwun ', + 'Hwan ','Yi ','Yi ','Po ','Qin ','Chong ','Po ','Feng ','Chon ','Tay ','Sa ','Xun ','Dao ','Lu ','Tay ','Swu ', + ], + 'x5c':[ + 'Po ','Pong ','Cen ','Fu ','Sa ','Kuk ','Cang ','Cang ','Cen ','Wi ','Con ','Sim ','Cwu ','Tay ','To ','So ', + 'Ji ','So ','Er ','I ','I ','Ga ','Chem ','Shu ','Chen ','Sang ','Sang ','','Ga ','Chang ','Liao ','Sen ', + 'Sen ','','Wang ','Wang ','Wu ','Liao ','Liao ','Yao ','Pang ','Wang ','Wang ','Wang ','Ga ','Yo ','Duo ','Kui ', + 'Zhong ','Chwi ','Gan ','Gu ','Gan ','Tui ','Gan ','Gan ','Si ','Yun ','Chek ','Ko ','Ni ','Cin ','Mi ','Nyo ', + 'Kwuk ','Pi ','Ceng ','Xi ','Bi ','Ke ','Kyey ','Cen ','Kwul ','Ti ','Jie ','Ok ','Diao ','Si ','Si ','Pyeng ', + 'Kuk ','Sel ','Chen ','Xi ','Ni ','Cen ','Xi ','','Man ','E ','Lou ','Pyeng ','Ti ','Fei ','Chok ','Xie ', + 'To ','Lu ','Lwu ','Xi ','Chung ','Li ','Ju ','Xie ','Kwu ','Jue ','Liao ','Jue ','Sok ','Xi ','Che ','Twun ', + 'Ni ','San ','','Sen ','Li ','Xue ','Nata ','','Long ','Hul ','Ki ','Ren ','Wu ','Han ','Shen ','Yu ', + 'Chwul ','Sui ','Qi ','','Yue ','Ban ','Yao ','Ang ','Ha ','Wu ','Cel ','E ','Kup ','Qian ','Fen ','Wan ', + 'Ki ','Cam ','Kyem ','Qi ','Cha ','Jie ','Qu ','Gang ','Xian ','Ao ','Lan ','Dao ','Ba ','Cak ','Zuo ','Yang ', + 'Ju ','Kang ','Ke ','Kwu ','Xue ','Pha ','Lip ','Cho ','Ce ','Am ','Pwul ','Swu ','Kap ','Lyeng ','Tuo ','Pei ', + 'You ','Tay ','Kuang ','Ak ','Qu ','Ho ','Po ','Min ','An ','Tiao ','Lyeng ','Chi ','Yuri ','Dong ','Cem ','Kui ', + 'Swu ','Mao ','Tong ','Xue ','Yi ','Kura ','He ','Ke ','Luo ','E ','Fu ','Swun ','Die ','Lu ','An ','Er ', + 'Gai ','Quan ','Tong ','Yi ','Mu ','Shi ','An ','Wei ','Hu ','Chi ','Mi ','Li ','Ji ','Tong ','Wei ','You ', + 'Sang ','Xia ','Li ','Yo ','Jiao ','Zheng ','Luan ','Jiao ','A ','A ','Yu ','Ye ','Bu ','Cho ','Qun ','Pong ', + 'Pong ','No ','Li ','You ','Hyen ','Hong ','To ','Shen ','Cheng ','Tu ','Geng ','Cwun ','Hao ','Hyep ','Yin ','Yu ', + ], + 'x5d':[ + 'Lang ','Kan ','Lao ','Lai ','Hem ','Que ','Kong ','Swung ','Chong ','Ta ','','Hua ','Ju ','Lay ','Ki ','Min ', + 'Kon ','Kon ','Zu ','Gu ','Choy ','Ay ','Ay ','Kang ','Lun ','Lyun ','Leng ','Kwul ','Duo ','Zheng ','Guo ','Um ', + 'Dong ','Han ','Cayng ','Wei ','Hyo ','Pi ','Em ','Swung ','Jie ','Pwung ','Zu ','Jue ','Dong ','Zhan ','Gu ','Yin ', + '','Ze ','Huang ','Yu ','Oy ','Yang ','Feng ','Qiu ','Dun ','Ti ','Yi ','Zhi ','Shi ','Cay ','Yao ','E ', + 'Zhu ','Kam ','Lyul ','Yan ','Mei ','Gan ','Ji ','Ji ','Huan ','Ting ','Sheng ','Mi ','Kam ','Wu ','Yu ','Zong ', + 'Lam ','Jue ','Am ','Am ','Oy ','Zong ','Cha ','Sui ','Rong ','Yamashina ','Kum ','Yu ','Ki ','Lou ','Tu ','Dui ', + 'Xi ','Weng ','Cang ','Dang ','Hong ','Jie ','Ai ','Liu ','Wu ','Swung ','Qiao ','Zi ','Oy ','Beng ','Dian ','Cha ', + 'Qian ','Yong ','Nie ','Cuo ','Ji ','','Tao ','Song ','Zong ','Jiang ','Liao ','','Chan ','Die ','Cen ','Ding ', + 'Tu ','Lwu ','Cang ','Zhan ','Cham ','Ao ','Cao ','Kwu ','Qiang ','Zui ','Zui ','To ','Dao ','Xi ','Yu ','Bo ', + 'Long ','Xiang ','Cung ','Bo ','Kum ','Cho ','Yan ','Lao ','Zhan ','Lin ','Liao ','Liao ','Jin ','Tung ','Duo ','Zun ', + 'Kyo ','Gui ','Yo ','Qiao ','Yao ','Jue ','Zhan ','Yek ','Xue ','Nao ','Ep ','Ep ','Yi ','E ','Hem ','Ji ', + 'Hay ','Ke ','Xi ','Di ','Ao ','Zui ','','Uy ','Yeng ','Dao ','Lyeng ','Za ','Se ','Ak ','Yin ','', + 'Jie ','Li ','Sui ','Long ','Long ','Dian ','Ying ','Xi ','Ju ','Cham ','Ying ','Kyu ','Yan ','Oy ','Nao ','Quan ', + 'Chao ','Chan ','Man ','Cen ','Cen ','','Am ','Yan ','Yan ','Nao ','Hen ','Chuan ','Gui ','Chen ','Cwu ','Huang ', + 'Jing ','Swun ','So ','Chao ','Lie ','Kong ','Cwa ','Kyo ','Ke ','Gong ','Kek ','Mwu ','Pwu ','Pwu ','Cha ','Qiu ', + 'Qiu ','Ki ','I ','Sa ','Pha ','Chi ','Zhao ','Hang ','Yi ','Kun ','Son ','Kwen ','Phas ','Son ','Ken ','Fu ', + ], + 'x5e':[ + 'Za ','Bi ','Si ','Pho ','Ding ','Shuai ','Pem ','Nie ','Shi ','Pwun ','Pa ','Zhi ','Huy ','Hu ','Dan ','Wei ', + 'Zhang ','Thang ','Dai ','Ma ','Pei ','Mal ','Chep ','Fu ','Lyem ','Cil ','Chwu ','Payk ','Zhi ','Cey ','Mo ','Yi ', + 'Yi ','Ping ','Qia ','Juan ','Ru ','Sol ','Tay ','Zheng ','Sey ','Qiao ','Zhen ','Sa ','Qun ','Sek ','Bang ','Tay ', + 'Kwi ','Chou ','Ping ','Cang ','Sha ','Wan ','Tay ','Yu ','Sang ','Sha ','Qi ','Ze ','Guo ','Mo ','Du ','Hwu ', + 'Ceng ','Xu ','Mi ','Wi ','Ak ','Phok ','Yi ','Pang ','Ping ','Tazuna ','Gong ','Pan ','Hwang ','Dao ','Myek ','Jia ', + 'Teng ','Hui ','Zhong ','Shan ','Man ','Mak ','Biao ','Guo ','Chayk ','Mu ','Pang ','Zhang ','Jiong ','Chan ','Pok ','Chi ', + 'Hu ','Pen ','Tang ','Phyey ','Hei ','','Mi ','Qiao ','Chem ','Fen ','Mong ','Pang ','Cwu ','Mie ','Chu ','Jie ', + 'Hen ','Lan ','Kan ','Phyeng ','Nyen ','Qian ','Pyeng ','Pyeng ','Hayng ','Kan ','Yo ','Hwan ','Yu ','Yu ','Ki ','Em ', + 'Pi ','Cheng ','Ze ','Kwang ','Cang ','Mo ','Qing ','Pi ','Qin ','Dun ','Sang ','Ki ','Ya ','Bai ','Jie ','Se ', + 'Lu ','Wu ','','Ku ','Ying ','Ce ','Pho ','Cem ','Ya ','Miao ','Kyeng ','Ci ','Pwu ','Tong ','Pang ','Fei ', + 'Sang ','Yi ','Zhi ','Tiao ','Zhi ','Xiu ','To ','Cwa ','Xiao ','Tu ','Gui ','Ko ','Pang ','Ceng ','You ','Bu ', + 'Ding ','Cheng ','Lai ','Pi ','Ji ','Am ','Se ','Kang ','Yong ','Tuo ','Song ','Se ','Qing ','Yu ','Yu ','Miao ', + 'Sou ','Chi ','Sang ','Phyey ','Kwu ','He ','Hui ','Liu ','Ha ','Lyem ','Lang ','Swu ','Zhi ','Pou ','Qing ','Kwu ', + 'Kwu ','Kun ','Ao ','Kwak ','Lou ','Um ','Lyo ','Dai ','Lu ','Yi ','Cwu ','Cen ','Tu ','Si ','Hum ','Myo ', + 'Chang ','Mwu ','Phyey ','Kwang ','Koc ','Koy ','Bi ','Cang ','Hay ','Lum ','Lin ','Liao ','Lye ','','Ying ','Xian ', + 'Ting ','Ong ','Li ','Cheng ','Yin ','Xun ','Yen ','Ceng ','Di ','Po ','Ken ','Hoy ','Nay ','Hoy ','Gong ','Ip ', + ], + 'x5f':[ + 'Kai ','Pyen ','Yi ','Ki ','Long ','Fen ','Ju ','Kam ','Hyek ','Zang ','Phyey ','Ik ','Yi ','I ','San ','Sik ', + 'Er ','Si ','Si ','Kwung ','Co ','In ','Hu ','Pwul ','Hong ','Wu ','Tui ','I ','Jiang ','Ba ','Shen ','Cey ', + 'Zhang ','Jue ','To ','Fu ','Di ','Mi ','Hyen ','Ho ','Chao ','No ','Jing ','Zhen ','Yi ','Mi ','Quan ','Wan ', + 'Shao ','Yak ','Xuan ','Jing ','Ton ','Cang ','Jiang ','Kang ','Peng ','Than ','Kang ','Bi ','Phil ','She ','Than ','Jian ', + 'Kwu ','Sei ','Pal ','Bi ','Kou ','Nagi ','Pyel ','Xiao ','Than ','Kuo ','Kang ','Hong ','Mi ','Kuo ','Man ','Jue ', + 'Ji ','Ji ','Gui ','Tang ','Lok ','Lu ','Tan ','Hyey ','Chey ','Hwi ','Hwi ','I ','Yi ','I ','I ','Huo ', + 'Huo ','Shan ','Hyeng ','Wen ','Tong ','En ','En ','Wuk ','Chi ','Chay ','Phyo ','Co ','Pin ','Phayng ','Yong ','Piao ', + 'Chang ','Yeng ','Chi ','Chi ','Zhuo ','Tuo ','Ji ','Pang ','Zhong ','Yek ','Wang ','Che ','Phi ','Chi ','Ling ','Pwul ', + 'Wang ','Ceng ','Co ','Wang ','Kyeng ','Tay ','Xi ','Swun ','Hun ','Yang ','Hoy ','Lyul ','Hwu ','Wa ','Cheng ','Zhi ', + 'Se ','Kyeng ','To ','Cong ','','Lai ','Cong ','Tuk ','Pay ','Sa ','','Qi ','Sang ','Zhi ','Cong ','Zhou ', + 'Lay ','E ','Xie ','Cha ','Jian ','Chi ','Jia ','Phyen ','Hwang ','Pok ','Swun ','Wei ','Pang ','Yo ','Mi ','Hyey ', + 'Zheng ','Piao ','Chi ','Tek ','Cing ','Cing ','Bie ','Tek ','Chong ','Chel ','Jiao ','Wei ','Yo ','Hwi ','Mei ','Long ', + 'Xiang ','Bao ','Qu ','Sim ','Ritsushinben ','Phil ','Yi ','Le ','Ren ','To ','Ding ','Gai ','Ki ','In ','Ren ','Chan ', + 'Tham ','Te ','Thuk ','Gan ','Qi ','Shi ','Chon ','Ci ','Mang ','Mang ','Xi ','Fan ','Ung ','Chem ','Min ','Min ', + 'Chwung ','Chwung ','O ','Ji ','O ','Xi ','Ye ','You ','Wan ','Cong ','Zhong ','Khway ','Yu ','Pyen ','Ki ','Qi ', + 'Cui ','Chim ','Tai ','Tun ','Qian ','Nyem ','Hun ','Hyung ','Nyu ','Wang ','Xian ','Hun ','Kang ','Hol ','Kai ','Pwun ', + ], + 'x60':[ + 'Huai ','Tai ','Song ','Wu ','Ou ','Chang ','Chuang ','Ju ','Yi ','Bao ','Cho ','Min ','Pei ','Cak ','Zen ','Ang ', + 'Kou ','Ban ','No ','Nao ','Ceng ','Pha ','Pho ','Chep ','Gu ','Ho ','Ju ','Tal ','Lyeng ','Sa ','Chou ','Di ', + 'Thay ','I ','Tu ','You ','Fu ','Kup ','Phyeng ','Seng ','Wen ','Ni ','Koy ','Fu ','Xi ','Bi ','You ','Kep ', + 'Xuan ','Chong ','Bing ','Hwang ','Xu ','Chu ','Pi ','Xi ','Xi ','Tan ','Koraeru ','Zong ','Dui ','','Ki ','Yi ', + 'Chi ','Im ','Swun ','Si ','Xi ','Lao ','Hang ','Kwang ','Mo ','Zhi ','Hyep ','Lyen ','Tiao ','Hwang ','Die ','Hao ', + 'Kong ','Gui ','Hang ','Xi ','Xiao ','Se ','Shi ','Kua ','Qiu ','Yang ','Ey ','Hui ','Chi ','Kwal ','Yi ','Hyung ', + 'Koy ','Lin ','Hoy ','Ca ','Hyul ','Chi ','Xiang ','Nu ','Han ','Un ','Kak ','Thong ','Nyem ','Kong ','Quan ','Sik ', + 'Hup ','Yue ','Peng ','Ken ','De ','Hyey ','E ','Kyuu ','Tong ','Yan ','Kai ','Ce ','Nao ','Yun ','Mang ','Yong ', + 'Yong ','Yen ','Pi ','Kon ','Cho ','Yel ','Yu ','Yu ','Jie ','Sil ','Zhe ','Lin ','Cey ','Han ','Hao ','Hyep ', + 'Ti ','Bu ','Up ','Qian ','Hoy ','Huy ','Phay ','Mwun ','Yi ','Heng ','Song ','Cen ','Cheng ','Kui ','Wu ','O ', + 'Yu ','Li ','Lyang ','Hwan ','Chong ','Yi ','Yel ','Li ','Nin ','Noy ','Ak ','Que ','Xuan ','Qian ','Wu ','Min ', + 'Cong ','Pi ','Pi ','Tek ','Chwey ','Chang ','Min ','Li ','Kyey ','Guan ','Guan ','Hayng ','To ','Che ','Kong ','Tian ', + 'Lun ','Xi ','Kan ','Kun ','Nyek ','Ceng ','Chwu ','Ton ','Guo ','Chem ','Liang ','Wan ','Yuan ','Jin ','Ji ','Lam ', + 'Yu ','Hok ','He ','Kwen ','Tan ','Chek ','Chek ','Nie ','Mang ','Chel ','Hol ','Hon ','Sek ','Chang ','Xin ','Yu ', + 'Hyey ','Ak ','Swa ','Chong ','Jian ','Yong ','Dian ','Ju ','Cham ','Cheng ','Tek ','Bei ','Qie ','Can ','Dan ','Guan ', + 'Tha ','Noy ','Wun ','Sang ','Chwey ','Die ','Hwang ','Cwun ','Kyeng ','Ya ','Seng ','Chuk ','Phyen ','Hun ','Zong ','Ti ', + ], + 'x61':[ + 'Cho ','Swu ','Bei ','Sen ','Wei ','Ge ','Ken ','Wei ','Yu ','Yu ','Bi ','Xuan ','Huan ','Min ','Phyak ','Uy ', + 'Mian ','Yong ','Kai ','Dang ','Um ','Ak ','Chen ','Mou ','Ke ','Ke ','Wu ','Ay ','Hyep ','Yan ','Nuo ','Kam ', + 'On ','Zong ','Sai ','Leng ','Fen ','','Kui ','Koy ','Que ','Gong ','Yun ','Su ','So ','Ki ','Yao ','Song ', + 'Hwang ','Ji ','Gu ','Ju ','Chang ','Ni ','Xie ','Kay ','Zheng ','Yong ','Cao ','Sun ','Sin ','Bo ','Kay ','Wen ', + 'Xie ','Hun ','Yong ','Yang ','Lyul ','Sao ','To ','Un ','Ca ','Xu ','Kyem ','Thay ','Hwang ','On ','Shen ','Ming ', + '','She ','Cong ','Phyo ','Mo ','Mo ','Guo ','Chi ','Cham ','Cham ','Cham ','Cui ','Min ','Thuk ','Zhang ','Thong ', + 'O ','Shuang ','Man ','Kwan ','Kak ','Zao ','Jiu ','Hyey ','Kay ','Lian ','Ou ','Cong ','Jin ','Yin ','Lye ','Shang ', + 'Wi ','Tan ','Man ','Kan ','Sup ','Yong ','Kyeng ','Kang ','Di ','Zhi ','Lwu ','Juan ','Chek ','Chek ','Yok ','Ping ', + 'Liao ','Chong ','Wu ','Yong ','Zhi ','Tong ','Cheng ','Qi ','Qu ','Peng ','Pi ','Pyel ','Chun ','Kyo ','Cung ','Chi ', + 'Lyen ','Ping ','Kwey ','Hui ','Cho ','Cheng ','Un ','Yin ','Huy ','Huy ','Than ','Tan ','Duo ','Dui ','Dui ','Su ', + 'Jue ','Ce ','Xiao ','Fan ','Pwun ','Lao ','Lao ','Tong ','Kam ','Key ','Xian ','Min ','Kyeng ','Liao ','Mwu ','Cham ', + 'Jue ','Cu ','Hen ','Tan ','Sheng ','Pi ','Ek ','Chu ','Sem ','Nao ','Tam ','Than ','Kyeng ','Song ','Kam ','Jiao ', + 'Wai ','Huan ','Dong ','Kun ','Qin ','Qu ','Co ','Kan ','Hay ','Ung ','O ','Mwu ','Yek ','Lin ','Se ','Jun ', + 'Huai ','Men ','Lan ','Ai ','Lin ','Yem ','Gua ','Ha ','Chi ','Yu ','Yin ','Dai ','Meng ','Ai ','Mong ','Tay ', + 'Qi ','Mo ','Lan ','Mwun ','Chou ','Zhi ','Na ','Nuo ','Yan ','Yang ','Bo ','Zhi ','Kuang ','Kuang ','You ','Fu ', + 'Liu ','Mie ','Cing ','','Chan ','Meng ','La ','Hoy ','Hyen ','Rang ','Cham ','Ji ','Kwu ','Hwan ','Sep ','Uy ', + ], + 'x62':[ + 'Lyen ','Nan ','Mi ','Tang ','Jue ','Gang ','Gang ','Tang ','Kwa ','Yue ','Mwu ','Jian ','Swul ','Swu ','Yung ','Xi ', + 'Seng ','A ','Kyey ','Ge ','Can ','Cang ','Hok ','Qiang ','Zhan ','Dong ','Chek ','Jia ','Die ','Cek ','Al ','Kuk ', + 'Shi ','Kam ','Cip ','Kui ','Gai ','Deng ','Cen ','Chang ','Ge ','Cen ','Cel ','Yu ','Jian ','Yan ','Lyuk ','Huy ', + 'Cen ','Huy ','Huy ','Chak ','Tay ','Kwu ','Ho ','Ho ','Ho ','Ayk ','Shi ','Lye ','Mao ','Hu ','Lye ','Pang ', + 'So ','Phyen ','Dian ','Kyeng ','Shang ','Yi ','Yi ','Sen ','Ho ','Pi ','Yem ','Swu ','Shu ','Cay ','Chal ','Qiu ', + 'Le ','Pok ','Pay ','Tha ','Reng ','Pwul ','Hameru ','Cay ','Thak ','Zhang ','Diao ','Kang ','Yu ','Ku ','Han ','Shen ', + 'Cha ','Yi ','Gu ','Kwu ','Wu ','Tuo ','Qian ','Zhi ','In ','Kuo ','Men ','Sao ','Yang ','Niu ','Pwun ','Cha ', + 'Rao ','Kup ','Qian ','Pan ','Jia ','Yu ','Pwu ','Ao ','Xi ','Pi ','Ci ','Zi ','Ayk ','Dun ','Co ','Sung ', + 'Ki ','Yan ','Kuang ','Pyen ','Cho ','Ju ','Mwun ','Hu ','Yue ','Kyel ','Pha ','Qin ','Zhen ','Zheng ','Yun ','Wan ', + 'Nu ','Ek ','Se ','Co ','Pwu ','Thwu ','Twu ','Hang ','Cel ','Pou ','Fu ','Pho ','Pal ','Ao ','Thayk ','Tuan ', + 'Kou ','Lun ','Qiang ','','Hu ','Bao ','Bing ','Zhi ','Phyeng ','Tan ','Pu ','Phi ','Thay ','Yao ','Zhen ','Zha ', + 'Yang ','Pho ','He ','Ni ','Yi ','Ce ','Chi ','Pi ','Za ','Mal ','Mei ','Shen ','Ap ','Chwu ','Qu ','Min ', + 'Chu ','Jia ','Pwul ','Zhan ','Cwu ','Tan ','Thak ','Mwu ','Nyem ','Lap ','Pwu ','Pho ','Pan ','Pak ','Ling ','Na ', + 'Koy ','Kyem ','Ke ','Chek ','Pal ','Tha ','Tha ','Yo ','Kwu ','Col ','Pan ','Cho ','Pay ','Bai ','Di ','Ni ', + 'Ke ','Hwak ','Long ','Jian ','','Yong ','Lan ','Ning ','Pal ','Ze ','Qian ','Hen ','Kwal ','Sik ','Kil ','Cung ', + 'Nin ','Kong ','Gong ','Kwen ','Shuan ','Con ','Chal ','Ko ','Chi ','Xie ','Ce ','Hui ','Phyeng ','Yey ','Sup ','Na ', + ], + 'x63':[ + 'Bo ','Ci ','Kway ','Zhi ','Kuo ','Duo ','Duo ','Ci ','Sel ','An ','Nong ','Zhen ','Kyek ','Jiao ','Ku ','Dong ', + 'Na ','To ','Lyen ','Zha ','Lu ','Die ','Wa ','Jue ','Lyut ','Ju ','Zhi ','Luan ','Ya ','Zhua ','Ta ','Xie ', + 'Nao ','Dang ','Jiao ','Zheng ','Ji ','Hui ','Xun ','Ku ','Ay ','Tuo ','Na ','Cwa ','Bo ','Geng ','Ti ','Cin ', + 'Cheng ','Suo ','Suo ','Keng ','Mei ','Long ','Ju ','Peng ','Jian ','Up ','Ceng ','Yen ','Nuo ','Man ','Hyep ','Cha ', + 'Feng ','Jiao ','O ','Kwun ','Kwu ','Tong ','Kon ','Huo ','Tu ','Chak ','Pou ','Le ','Phal ','Han ','So ','Nal ', + 'Yen ','Ze ','Song ','Ye ','Jue ','Pho ','Huan ','Chek ','Zun ','Yi ','Zhai ','Lu ','Sou ','Tuo ','Lao ','Sun ', + 'Bang ','Jian ','Hwan ','Dao ','','Wan ','Qin ','Pong ','Sa ','Lyel ','Min ','Mwun ','Fu ','Bai ','Ke ','Dao ', + 'Wo ','Ay ','Kwen ','Yue ','Zong ','Chen ','Chwu ','Chep ','Tu ','Ben ','Nal ','Nyem ','Nuo ','Zu ','Wo ','Se ', + 'Hun ','Cheng ','Dian ','So ','Lyun ','Qing ','Gang ','Chel ','Swu ','To ','Pwu ','Di ','Cang ','Gun ','Ki ','To ', + 'Qia ','Qi ','Pay ','Shu ','Qian ','Ling ','Ayk ','Ya ','Kwul ','Zheng ','Liang ','Kway ','Yey ','Huo ','Shan ','Ceng ', + 'Lyak ','Chay ','Tham ','Chey ','Bing ','Cep ','Ti ','Kong ','Chwu ','Em ','Co ','Zou ','Kwuk ','Tian ','Qian ','Ken ', + 'Bai ','Shou ','Key ','Lu ','Guo ','Haba ','','Zhi ','Dan ','Maang ','Xian ','So ','Guan ','Peng ','Yen ','Nuo ', + 'Kan ','Zhen ','Jiu ','Cen ','Yu ','Yan ','Kyu ','Nan ','Hong ','Yu ','Pi ','Wei ','Sai ','Zou ','Xuan ','Myo ', + 'Cey ','Nie ','Sap ','Shi ','Zong ','Zhen ','Up ','Shun ','Heng ','Bian ','Yang ','Hwan ','Am ','Zuan ','An ','Se ', + 'Al ','Ak ','Ke ','Chwi ','Ji ','Ti ','La ','La ','Cheng ','Kay ','Jiu ','Chwu ','Tu ','Key ','Hwi ','Geng ', + 'Chong ','Shuo ','Sel ','Xie ','Wen ','Ken ','Ya ','Sap ','Zha ','Bei ','Yao ','','Dam ','Lan ','Wen ','Qin ', + ], + 'x64':[ + 'Chan ','Ge ','Lou ','Zong ','Geng ','Jiao ','Kwu ','Qin ','Yong ','Kak ','Chou ','Chi ','Zhan ','Son ','Sun ','Pak ', + 'Hyuk ','Rong ','Pang ','Cha ','So ','Ke ','Yo ','To ','Zhi ','Nu ','Xie ','Jian ','Swu ','Qiu ','Gao ','Xian ', + 'Shuo ','Sang ','Cin ','Mie ','Ayk ','Chwu ','Nuo ','Shan ','Thap ','Jie ','Tang ','Pan ','Pan ','Thap ','Li ','To ', + 'Kol ','Zhi ','Wa ','Xia ','Qian ','Wen ','Chang ','Tian ','Zhen ','E ','Hyu ','Nuo ','Quan ','Cha ','Chak ','Ge ', + 'Wu ','En ','Sep ','Kang ','She ','Shu ','Bai ','Yao ','Bin ','Sou ','Tan ','Sa ','Chan ','Suo ','Liao ','Chong ', + 'Chuang ','Guo ','Pyeng ','Feng ','Shuai ','Di ','Qi ','','Cek ','Lian ','Tang ','Chi ','Guan ','Lu ','Luo ','Lou ', + 'Chong ','Gai ','Hu ','Zha ','Chuang ','Tang ','Hua ','Choy ','Nai ','Ma ','Jiang ','Gui ','Ying ','Chek ','Ao ','Ci ', + 'Nie ','Man ','Shan ','Kwu ','Shu ','Suo ','Tuan ','Jiao ','Mo ','Mo ','Cep ','Sem ','Keng ','Phyo ','Jiang ','Yin ', + 'Gou ','Qian ','Liao ','Kyek ','Ying ','Kwey ','Pie ','Pie ','Lo ','Dun ','Xian ','Ruan ','Kui ','Zan ','Yi ','Xun ', + 'Thayng ','Thayng ','Sal ','Yo ','Heng ','Se ','Qian ','Huang ','Thap ','Cwun ','Nyen ','Lin ','Zheng ','Hwi ','Tang ','Kyo ', + 'Ji ','Cao ','Dan ','Dan ','Chel ','Pal ','Che ','Jue ','Xiao ','Lyo ','Ben ','Mwu ','Qiao ','Pha ','Chwal ','Zhuo ', + 'Chan ','Tuo ','Pak ','Qin ','Dun ','Nian ','','Xie ','Lu ','Kyo ','Cuan ','Tal ','Kam ','Qiao ','Kwa ','Kem ', + 'Gan ','Ong ','Lei ','Kuo ','Lo ','Chen ','Zhuo ','Thayk ','Pu ','Chak ','Kyek ','Dang ','Suo ','Co ','Kyeng ','Jing ', + 'Hwan ','Jie ','Kum ','Kuai ','Tam ','Hyu ','Ge ','Pyek ','Pyek ','Ao ','Ke ','Ye ','','Mang ','Sou ','Mi ', + 'Cey ','Tay ','Thak ','To ','Xing ','Lam ','Chal ','Ke ','Ye ','Ru ','Ye ','Ye ','Uy ','Hwa ','Ji ','Pin ', + 'Ning ','Kak ','Chek ','Jie ','Hwak ','Mo ','Jian ','Xie ','Lie ','Tan ','Pha ','Sou ','Lu ','Lue ','Yo ','Zhi ', + ], + 'x65':[ + 'Pan ','Yang ','Long ','Sa ','The ','Zan ','Nian ','Hen ','Jun ','Huo ','Lye ','La ','Han ','Ying ','Lu ','Long ', + 'Qian ','Qian ','Zan ','Qian ','Lan ','San ','Ying ','Mei ','Yang ','Cham ','','Cuan ','Xie ','Sep ','Luo ','Jun ', + 'Mi ','Li ','Chan ','Lyen ','Than ','Zuan ','Li ','Dian ','Wa ','Dang ','Kyo ','Hwak ','Lam ','Li ','Nang ','Ci ', + 'Gui ','Gui ','Ki ','Xin ','Pu ','Sui ','Swu ','Ko ','Yu ','Kay ','Yi ','Kong ','Gan ','Pan ','Pang ','Ceng ', + 'Bo ','Dian ','Kou ','Min ','Wu ','Ko ','He ','Ce ','Hyo ','Mi ','Chu ','Ge ','Di ','Se ','Kyo ','Min ', + 'Chen ','Kwu ','Zhen ','Duo ','E ','Chik ','O ','Phay ','Se ','Kyo ','Duo ','Lian ','Nie ','Phyey ','Chang ','Dian ', + 'Duo ','I ','Kam ','San ','Ke ','Yan ','Ton ','Qi ','Dou ','Hyo ','Duo ','Jiao ','Kyeng ','Yang ','Xia ','Min ', + 'Swu ','Ai ','Ko ','Ai ','Ceng ','Cek ','Zhen ','Pwu ','Swu ','Liao ','Qu ','Xiong ','Xi ','Jiao ','Sen ','Jiao ', + 'Zhuo ','Twu ','Lyem ','Phyey ','Li ','Hyo ','Hyo ','Mwun ','Hak ','Qi ','Qi ','Zhai ','Pin ','Jue ','Zhai ','', + 'Pi ','Pan ','Ban ','Lan ','Yu ','Lan ','Wei ','Twu ','Sheng ','Lyo ','Jia ','Kok ','Sa ','Ka ','Yu ','Cim ', + 'Jiao ','Al ','Tou ','Chu ','Kun ','Chek ','Yin ','Pwu ','Qiang ','Zhan ','Qu ','Cak ','Cham ','Tan ','Zhuo ','Sa ', + 'Sin ','Cak ','Chak ','Qin ','Lin ','Zhuo ','Chu ','Tan ','Zhu ','Pang ','Xie ','Hang ','E ','Si ','Pei ','Yu ', + 'Mye ','Pang ','Ki ','Cen ','Mo ','Lye ','Phay ','Pi ','Liu ','Pwu ','Pang ','Sen ','Ceng ','Jing ','Ni ','Cok ', + 'Zhao ','Yi ','Lyu ','Shao ','Jian ','Es ','Yi ','Ki ','Zhi ','Fan ','Piao ','Fan ','Zhan ','Guai ','Sui ','Yu ', + 'Mwu ','Ji ','Ki ','Ki ','Huo ','Il ','Tan ','Kwu ','Ci ','Co ','Xie ','Tiao ','Swun ','Wuk ','Xu ','Xu ', + 'Kan ','Han ','Tay ','Di ','Wu ','Chan ','Shi ','Kuang ','Yang ','Shi ','Wang ','Min ','Min ','Ton ','Chun ','O ', + ], + 'x66':[ + 'Yun ','Bei ','Ang ','Chi ','Ban ','Jie ','Kon ','Sung ','Hu ','Pang ','Ho ','Gui ','Chang ','Xuan ','Myeng ','Hon ', + 'Pwun ','Kum ','Hu ','Yek ','Sek ','Hun ','Yan ','Ze ','Fang ','Tan ','Shen ','Ke ','Yang ','Zan ','Pyeng ','Seng ', + 'Yeng ','Hyen ','Pei ','Zhen ','Lyeng ','Chwun ','Hao ','May ','Cak ','Mo ','Bian ','Kwu ','Hun ','So ','Zong ','Si ', + 'Ha ','Wuk ','Fei ','Die ','Myo ','Nil ','Chang ','On ','Dong ','Ai ','Pyeng ','Ang ','Cwu ','Long ','Xian ','Kuang ', + 'Tiao ','Co ','Si ','Hwang ','Hwang ','Xuan ','Kui ','Xu ','Kyo ','Cin ','Zhi ','Cin ','Sang ','Tong ','Hong ','An ', + 'Gai ','Xiang ','Shai ','Xiao ','Ye ','Yun ','Hui ','Han ','Han ','Cwun ','Man ','Hyen ','Kun ','Cwu ','Huy ','Seng ', + 'Sheng ','Pho ','Cel ','Zhe ','O ','Hwan ','Hoy ','Ho ','Sin ','Man ','Tian ','Thak ','Swi ','Zhou ','Po ','Kyeng ', + 'Sek ','Shan ','Yi ','Sek ','Cheng ','Qi ','Ceng ','Kwi ','Ceng ','Yi ','Ci ','Am ','Wan ','Lin ','Liang ','Chang ', + 'Wang ','Hyo ','Zan ','Hi ','Hwen ','Xuan ','Yi ','Ka ','Hwun ','Hwi ','Fu ','Min ','Kyu ','He ','Yeng ','Du ', + 'Wi ','Se ','Qing ','Mao ','Nan ','Jian ','Nan ','Am ','Yang ','Chun ','Yao ','Suo ','Jin ','Myeng ','Kyo ','Kai ', + 'Ko ','Weng ','Chang ','Ki ','Hao ','Yan ','Li ','Ai ','Ki ','Gui ','Men ','Cam ','Sel ','Hao ','Mo ','Mo ', + 'Cong ','Nil ','Cang ','Hye ','Phok ','Han ','Xuan ','Chuan ','Lyo ','Sem ','Dan ','Kyeng ','Pie ','Lin ','Ton ','Huy ', + 'Ey ','Ki ','Huang ','Tai ','Yep ','Yep ','Lyek ','Tam ','Tong ','Hyo ','Fei ','Qin ','Zhao ','Hao ','Yi ','Xiang ', + 'Xing ','Sen ','Jiao ','Pho ','Jing ','Yan ','Ay ','Ye ','Ru ','Se ','Mong ','Hwun ','Yo ','Pho ','Li ','Chen ', + 'Kwang ','Cep ','','Yen ','Huo ','Lu ','Huy ','Rong ','Long ','Nang ','La ','Luan ','Swa ','Tang ','Em ','Chok ', + 'Wal ','Yue ','Kok ','Yey ','Kyeng ','Ye ','Hu ','Kal ','Se ','Co ','Co ','Shou ','Man ','Ceng ','Cung ','Chey ', + ], + 'x67':[ + 'Choy ','Can ','Xu ','Hoy ','Yin ','Kel ','Fen ','Pi ','Wel ','Yu ','Ruan ','Pwung ','Pan ','Pok ','Ling ','Fei ', + 'Qu ','','Nu ','Tiao ','Sak ','Cim ','Lang ','Lang ','Juan ','Ming ','Huang ','Mang ','Tun ','Co ','Ki ','Ki ', + 'Ying ','Zong ','Wang ','Tong ','Lang ','','Mong ','Long ','Mok ','Tung ','Mi ','Mal ','Pon ','Chal ','Chwul ','Chwul ', + '','Cwu ','Ren ','Pha ','Pak ','Tha ','Tha ','Dao ','Li ','Qiu ','Kwey ','Jiu ','Bi ','Hwu ','Ting ','Ci ', + 'Sha ','Eburi ','Za ','Quan ','Qian ','Yu ','Kan ','Wu ','Cha ','Sam ','Xun ','Fan ','Wu ','Zi ','Li ','Hayng ', + 'Cay ','Chon ','Ren ','Phyo ','Tuo ','Di ','Cang ','Mang ','Chi ','Yi ','Gu ','Gong ','Twu ','Yi ','Ki ','Sok ', + 'Kang ','Co ','Moku ','Son ','Tochi ','Lai ','Sugi ','Mang ','Yang ','Ma ','Cho ','Si ','Wen ','Hang ','Phyey ','Pay ', + 'Kel ','Tong ','Ko ','Myo ','Xian ','Ce ','Chun ','Pha ','Shu ','Hua ','Xin ','Nyu ','Ce ','Chou ','Song ','Phan ', + 'Song ','Ji ','Yue ','Jin ','Gou ','Ji ','Mao ','Pi ','Bi ','Wang ','Ang ','Pang ','Pwun ','Yi ','Fu ','Nam ', + 'Sek ','Hu ','Ya ','Twu ','Xun ','Chim ','Yao ','Lim ','Yey ','Wa ','May ','Zhao ','Kwa ','Ci ','Cong ','Yun ', + 'Waku ','Dou ','Shu ','Zao ','','Li ','Ro ','Jian ','Cheng ','Shou ','Qiang ','Feng ','Nan ','Xiao ','Xian ','Ko ', + 'Phyeng ','Tay ','Si ','Ci ','Guai ','Xiao ','Ka ','Ka ','Kwu ','Fu ','Mo ','Yi ','Ye ','Ye ','Si ','Nie ', + 'Bi ','Tha ','Yi ','Ling ','Pyeng ','Ni ','La ','He ','Pan ','Fan ','Cong ','Dai ','Ci ','Yang ','Fu ','Payk ', + 'Mo ','Kam ','Chil ','Yem ','Yu ','Mao ','Zhao ','Song ','Ca ','Hap ','Yu ','Shen ','Gui ','Thak ','Cak ','Nam ', + 'Ning ','Yong ','Ce ','Zhi ','Zha ','Sa ','Dan ','Gu ','','Kwu ','Ao ','Fu ','Kan ','Bo ','Duo ','Ka ', + 'Nay ','Cwu ','Bi ','Lyu ','Si ','Chayk ','Sa ','Chwuk ','Pei ','Si ','Guai ','Sa ','Yao ','Jue ','Kwu ','Si ', + ], + 'x68':[ + 'Zhi ','Liu ','Mei ','Hoy ','Yeng ','Chayk ','','Biao ','Zhan ','Jie ','Long ','Dong ','Lu ','Sayng ','Li ','Lan ', + 'Yong ','Shu ','Swun ','Cen ','Qi ','Zhen ','Se ','Lyul ','Yi ','Xiang ','Zhen ','Li ','Su ','Kwal ','Kan ','Bing ', + 'Ren ','Kyo ','Payk ','Ren ','Bing ','Zi ','Chou ','Yi ','Jie ','Xu ','Cwu ','Jian ','Zui ','Er ','I ','Wuk ', + 'Fa ','Kong ','Ko ','Lao ','Cen ','Li ','','Yang ','Hayk ','Kun ','Zhi ','Sik ','Kyek ','Cay ','Luan ','Fu ', + 'Kel ','Hang ','Kyey ','To ','Kwang ','Wei ','Kwang ','Ru ','An ','An ','Juan ','Yi ','Zhuo ','Ku ','Cil ','Qiong ', + 'Tong ','Sang ','Sang ','Hwan ','Kil ','Jiu ','Xue ','Duo ','Zhui ','Yu ','Zan ','Kasei ','Ayng ','Masu ','','Zhan ', + 'Ya ','Nao ','Zhen ','Dang ','Qi ','Qiao ','Hua ','Hoy ','Jiang ','Zhuang ','Xun ','Suo ','Sha ','Cin ','Bei ','Ceng ', + 'Gua ','Jing ','Bo ','Ben ','Pwu ','Rui ','Thong ','Kak ','Xi ','Lang ','Liu ','Feng ','Qi ','Wen ','Kwun ','Han ', + 'Cu ','Lyang ','Qiu ','Ceng ','You ','May ','Pang ','Long ','Peng ','Zhuang ','Di ','Xuan ','Tu ','Zao ','Ao ','Kok ', + 'Bi ','Di ','Han ','Cay ','Chi ','Ren ','Bei ','Kyeng ','Jian ','Huan ','Wan ','Na ','Jia ','Co ','Ji ','Hyo ', + 'Lye ','Wan ','Cho ','Sim ','Fen ','Song ','Meng ','O ','Li ','Li ','Dou ','Cen ','Ying ','Sa ','Ju ','Cey ', + 'Kyey ','Kon ','Zhuo ','So ','Chan ','Pem ','Mi ','Jing ','Li ','Bing ','Fumoto ','Shikimi ','Tao ','Zhi ','Lai ','Lian ', + 'Jian ','Zhuo ','Ling ','Li ','Ki ','Pyeng ','Zhun ','Cong ','Qian ','Myen ','Ki ','Ki ','Chay ','Kon ','Chan ','Te ', + 'Pi ','Pai ','Pong ','Pou ','Hun ','Cong ','Ceng ','Co ','Kuk ','Li ','Pwung ','Yu ','Yu ','Gu ','Hun ','Tong ', + 'Tang ','Gang ','Wang ','Chey ','Xi ','Fan ','Cheng ','Can ','Kyey ','Yuan ','Yan ','Yu ','Kwen ','Yi ','Sam ','Ren ', + 'Chui ','Leng ','Se ','Zhuo ','Fu ','Ke ','Lai ','Zou ','Zou ','To ','Kwan ','Pwun ','Pwun ','Chen ','Qiong ','Nie ', + ], + 'x69':[ + 'Wan ','Kwak ','Lu ','Hao ','Cep ','Uy ','Chou ','Ju ','Ju ','Cheng ','Zuo ','Lyang ','Qiang ','Sik ','Chwu ','Ya ', + 'Ju ','Pi ','Cho ','Zhuo ','Zi ','Bin ','Peng ','Ding ','Chu ','Chang ','Mun ','Momiji ','Kem ','Gui ','Xi ','Du ', + 'Qian ','Kunugi ','Kai ','Shide ','Luo ','Zhi ','Ken ','Myeng ','Tafu ','','Peng ','Zhan ','','Tuo ','Sen ','Duo ', + 'Ya ','Fou ','Wei ','Wei ','Tan ','Jia ','Cong ','Jian ','Yi ','Chim ','Po ','Yan ','Yan ','Yen ','Zhan ','Chwun ', + 'Yu ','He ','Sa ','Wo ','Pian ','Bi ','Yao ','Huo ','Xu ','Ruo ','Yang ','La ','Yan ','Ben ','Hun ','Kyu ', + 'Jie ','Kui ','Si ','Phwung ','Sel ','Tha ','Zhi ','Ken ','Mu ','Mwu ','Cho ','Hu ','Hu ','Lyen ','Lung ','Ting ', + 'Nam ','Yu ','Yu ','Mi ','Song ','Wen ','Wen ','Ying ','Ceng ','Pian ','Cep ','Cup ','Kal ','Ep ','Ce ','Swun ', + 'Yu ','Cou ','Wei ','May ','Di ','Kuk ','Jie ','Hay ','Chwu ','Yeng ','Rou ','Heng ','Lwu ','Le ','Hazou ','Katsura ', + 'Pin ','Muro ','Kay ','Tan ','Lan ','Yun ','Yu ','Chen ','Lu ','Ju ','Sakaki ','','Pi ','Xie ','Ka ','Yi ', + 'Zhan ','Pwu ','Nai ','Mi ','Lang ','Yong ','Kok ','Jian ','Kwu ','Ta ','Yao ','Cin ','Pang ','Sha ','Yuan ','Cay ', + 'Ming ','Su ','Jia ','Yao ','Kel ','Hwang ','Kan ','Pi ','Ca ','Qian ','Ma ','Sun ','Yuan ','Sa ','Yeng ','Shi ', + 'Ci ','Choy ','Yun ','Ting ','Lyu ','Rong ','Tang ','Kyo ','Zhai ','Si ','Sheng ','Thap ','Hap ','Xi ','Kol ','Qi ', + 'Ko ','Ko ','Sun ','Pan ','Tao ','Ge ','Xun ','Cen ','Nou ','Ji ','Sak ','Kwu ','Thoy ','Chang ','Cha ','Qian ', + 'Koy ','Mei ','Xu ','Kong ','Gao ','Zhuo ','Tuo ','Kyou ','Yang ','Cen ','Jia ','Jian ','Zui ','Tou ','Rou ','Bin ', + 'Zhu ','','Xi ','Qi ','Lian ','Hyey ','Yong ','Cham ','Kwak ','Kay ','Kay ','Tuan ','Hua ','Sayk ','Sen ','Cui ', + 'Beng ','You ','Kok ','Jiang ','Hu ','Huan ','Kui ','Yi ','Nie ','Ko ','Kang ','Kyu ','Gui ','Co ','Man ','Kun ', + ], + 'x6a':[ + 'Cek ','Zhuang ','Ak ','Lang ','Chen ','Cong ','Li ','Xiu ','Qing ','Shuang ','Pen ','Thong ','Guan ','Ji ','Suo ','Lei ', + 'Lu ','Lyang ','Mil ','Lwu ','So ','Su ','Ke ','Ce ','Tang ','Phyo ','Lu ','Kyu ','Shu ','Zha ','Chwu ','Cang ', + 'Men ','Mo ','Niao ','Yang ','Tiao ','Peng ','Zhu ','Sha ','Chi ','Kwen ','Hoyng ','Kyen ','Cong ','','Hokuso ','Qiang ', + 'Tara ','Ying ','Er ','Xin ','Zhi ','Cho ','Zui ','Cong ','Pok ','Swu ','Hwa ','Kwey ','Zhen ','Cwun ','Yue ','Zhan ', + 'Xi ','Xun ','Dian ','Pel ','Kam ','Mo ','Wu ','Chwi ','Yo ','Lin ','Lyu ','Kyo ','Xian ','Run ','Fan ','Zhan ', + 'Thak ','Lao ','Wun ','Swun ','Tui ','Cheng ','Tang ','Meng ','Kyul ','Tung ','Swuk ','Jue ','Jue ','Tan ','Hui ','Ki ', + 'Nuo ','Sang ','Tha ','Ning ','Rui ','Zhu ','Tong ','Zeng ','Fen ','Qiong ','Ran ','Hoyng ','Cen ','Gu ','Liu ','Lao ', + 'Gao ','Chu ','Zusa ','Nude ','Ca ','San ','Ji ','Dou ','Shou ','Lu ','Gian ','','Yuan ','Ta ','Shu ','Kang ', + 'Tan ','Lin ','Nong ','Yin ','Kyek ','Sui ','Shan ','Zui ','Xuan ','Ceng ','Gan ','Ju ','Zui ','Ek ','Kum ','Pu ', + 'Chem ','Lei ','Feng ','Hui ','Tang ','Ji ','Sui ','Pyek ','Bi ','Ding ','Chu ','Zhua ','Hoy ','Cup ','Jie ','Ka ', + 'Kyeng ','Zhe ','Kem ','Cang ','Dao ','Yi ','Biao ','Song ','She ','Lin ','Reki ','Cha ','Meng ','Yin ','To ','Tay ', + 'Mian ','Qi ','','Pin ','Huo ','Ji ','Yem ','Mi ','Ning ','Yi ','Gao ','Ham ','Un ','Er ','Qing ','Yem ', + 'Qi ','Mi ','To ','Kwey ','Chun ','Ji ','Kui ','Po ','Deng ','Chu ','Han ','Mian ','You ','Zhi ','Guang ','Qian ', + 'Lei ','Lei ','Sa ','Lo ','Li ','Cuan ','Lu ','Mie ','Hui ','Ou ','Lye ','Cul ','Ko ','Tok ','Yen ','Lyek ', + 'Fei ','Zhuo ','Sou ','Lian ','Sen ','Chu ','','Zhu ','Lu ','Yan ','Lyek ','Zhu ','Chin ','Jie ','E ','Su ', + 'Huai ','Nie ','Yu ','Long ','Lai ','','Hen ','Kwi ','Ju ','Xiao ','Ling ','Ayng ','Chem ','Yin ','You ','Ying ', + ], + 'x6b':[ + 'Xiang ','Nong ','Pak ','Cham ','Lan ','Ju ','Shuang ','She ','Wei ','Cong ','Kwen ','Qu ','Cang ','','Yu ','Luo ', + 'Li ','Chan ','Lan ','Dang ','Jue ','Em ','Lam ','Lan ','Zhu ','Lei ','Li ','Ba ','Nang ','Yu ','Lyeng ','Tsuki ', + 'Hum ','Cha ','Huan ','Hun ','Yu ','Yu ','Qian ','Ou ','Xu ','Chao ','Chu ','Chi ','Hay ','Yi ','Jue ','Xi ', + 'Xu ','Xia ','Yok ','Kuai ','Lang ','Kuan ','Shuo ','Huy ','Ay ','Uy ','Ki ','Hwul ','Chi ','Hum ','Kwan ','Kam ', + 'Kuan ','Kan ','Chuan ','Sap ','','Yin ','Hum ','Hel ','Yu ','Kyem ','Xiao ','Yi ','Ka ','Wu ','Than ','Jin ', + 'Kwu ','Hu ','Ti ','Hwan ','He ','Pen ','Xi ','Xiao ','Xu ','Hup ','Sen ','Kem ','Chu ','Yi ','Kan ','Ye ', + 'Chel ','Hwan ','Ci ','Ceng ','Cha ','Po ','Mwu ','Ki ','Bu ','Po ','Way ','Ju ','Qian ','Chi ','Se ','Chi ', + 'Se ','Zhong ','Sey ','Sey ','Li ','Cuo ','Yu ','Lyek ','Kwi ','Al ','Dai ','Sa ','Jian ','Zhe ','Mo ','Mol ', + 'Yo ','Mol ','Co ','Ang ','Cin ','Sheng ','Thay ','Shang ','Xu ','Swun ','Swu ','Can ','Jue ','Phyo ','Qia ','Qiu ', + 'Su ','Kung ','Yun ','Lian ','Yi ','Fou ','Sik ','Ye ','Can ','Hun ','Dan ','Ji ','Ye ','','Wun ','Wen ', + 'Chou ','Bin ','Chey ','Jin ','Sang ','Yin ','Diao ','Cu ','Hui ','Cuan ','Yi ','Than ','Du ','Kang ','Lyem ','Pin ', + 'Du ','Sen ','Sem ','Swi ','Ou ','Tan ','Zhu ','Un ','Qing ','Yi ','Sal ','Kak ','Kak ','Hyo ','Jun ','Cen ', + 'Hwey ','Hwey ','Gu ','Que ','Kyek ','Uy ','Kwu ','Hui ','Duan ','Yi ','Xiao ','Mwu ','Guan ','Mo ','May ','May ', + 'Ai ','Zuo ','Tok ','Yuk ','Pi ','Bi ','Pi ','Pi ','Pi ','Bi ','Cham ','Mo ','','','Pu ','Mushiru ', + 'Jia ','Zhan ','Sai ','Mu ','Tuo ','Xun ','Er ','Rong ','Xian ','Ju ','Mu ','Ho ','Kwu ','Dou ','Mushiru ','Tam ', + 'Pei ','Ju ','Duo ','Chwi ','Bi ','San ','','Mao ','Sui ','Shu ','Yu ','Tuo ','He ','Jian ','Ta ','Sam ', + ], + 'x6c':[ + 'Lu ','Mu ','Mao ','Tong ','Rong ','Chang ','Pu ','Luo ','Cen ','Sao ','Zhan ','Meng ','Luo ','Qu ','Die ','Ssi ', + 'Ce ','Min ','Jue ','Mayng ','Qi ','Pie ','Nai ','Ki ','Dao ','Xian ','Chuan ','Pwun ','Ri ','Nei ','','Fu ', + 'Shen ','Dong ','Qing ','Ki ','In ','Xi ','Hai ','Yang ','An ','Ya ','Ke ','Qing ','Ya ','Dong ','Dan ','Lu ', + 'Qing ','Yang ','On ','On ','Swu ','Sanzui ','Zheng ','Ping ','Yeng ','Dang ','Sui ','Le ','Ni ','Than ','Pem ','Kwey ', + 'Ceng ','Cip ','Kwu ','Pha ','Ze ','Mian ','Cuan ','Hui ','Diao ','Yi ','Cha ','Cak ','Chuan ','Wan ','Pem ','Tay ', + 'Sek ','Tuo ','Mang ','Qiu ','Hul ','San ','Pai ','Han ','Qian ','O ','O ','Sin ','Sa ','Ye ','Hong ','Kang ', + 'Ci ','O ','Tsuchi ','','Tang ','Zhi ','Chi ','Qian ','Myek ','Yul ','Wang ','Qing ','Jing ','Yey ','Jun ','Hong ', + 'Thay ','Quan ','Kup ','Bian ','Pha ','Gan ','Mwun ','Zhong ','Fang ','Xiong ','Kyel ','Hang ','','Ki ','Pwun ','Xu ', + 'Xu ','Sim ','Ki ','Ok ','Wun ','Wen ','Hang ','Yen ','Chim ','Chim ','Dan ','You ','Ton ','Ho ','Huo ','Qi ', + 'Mok ','Rou ','Mol ','Tap ','Myen ','Mwul ','Chwung ','Tian ','Pi ','Sa ','Ci ','Phay ','Pan ','Zhui ','Za ','Gou ', + 'Liu ','Mei ','Thayk ','Feng ','Ou ','Li ','Lun ','Cang ','Feng ','Wei ','Hu ','Mal ','May ','Shu ','Ce ','Zan ', + 'Thak ','Tha ','Tuo ','Ha ','Li ','Mi ','Yi ','Fa ','Pi ','Yu ','Tian ','Chi ','So ','Ko ','Chem ','Yen ', + 'Si ','Hwang ','Hyeng ','Ju ','Sel ','Swi ','Il ','Jia ','Zhong ','Chen ','Pak ','Hui ','Phil ','Ben ','Zhuo ','Chu ', + 'Luk ','Yu ','Gu ','Hong ','Kem ','Pep ','Mao ','Sa ','Hu ','Phyeng ','Ca ','Pem ','Ci ','So ','Ning ','Cheng ', + 'Lyeng ','Pho ','Pha ','Up ','Si ','Ni ','Ju ','Yue ','Cwu ','Sheng ','Lei ','Hyen ','Xue ','Fu ','Pan ','Min ', + 'Thay ','Ang ','Ji ','Yeng ','Guan ','Beng ','Xue ','Long ','Lu ','','Bo ','Xie ','Po ','Ze ','Jing ','Yin ', + ], + 'x6d':[ + 'Zhou ','Ji ','Yi ','Hui ','Hoy ','Zui ','Cheng ','In ','Wei ','Hou ','Chen ','Yang ','Lyel ','Si ','Ji ','Er ', + 'Xing ','Po ','Sey ','Suo ','Zhi ','Yin ','Wu ','Sey ','Kao ','Swu ','Jiang ','Lak ','','An ','Tong ','I ', + 'Mou ','Lei ','Yi ','Mi ','Quan ','Cin ','Mo ','Yu ','Xiao ','Sel ','Hong ','Hyek ','Sok ','Kuang ','To ','Qie ', + 'Ju ','Er ','Cwu ','Ru ','Ping ','Swun ','Hyung ','Zhi ','Kwang ','Wen ','Myeng ','Hwal ','Wa ','Hup ','Pha ','Wu ', + 'Qu ','Lyu ','Yi ','Jia ','Jing ','Chen ','Jiang ','Jiao ','Cheng ','Shi ','Zhuo ','Ce ','Pal ','Kuai ','Ji ','Liu ', + 'Chan ','Hun ','Hu ','Nong ','Xun ','Jin ','Lie ','Qiu ','Wei ','Cel ','Cwun ','Han ','Pin ','Mang ','Zhuo ','You ', + 'Xi ','Pal ','Dou ','Wan ','Koyng ','Up ','Pho ','Yeng ','Lan ','Ho ','Lang ','Han ','Li ','Geng ','Pwu ','Wu ', + 'Lian ','Chun ','Feng ','Yi ','Yok ','Tong ','Lao ','Hay ','Chim ','Hyep ','Chong ','Weng ','Mei ','Sui ','Cheng ','Phay ', + 'Xian ','Shen ','To ','Kun ','Pin ','Nyel ','Han ','Kyeng ','So ','Sep ','Nian ','Tu ','Yong ','Hyo ','Yen ','Ting ', + 'E ','So ','Tun ','Yen ','Cam ','Chey ','Li ','Shui ','Si ','Lwu ','Shui ','Tao ','Tok ','Lao ','Lai ','Lian ', + 'Wei ','Wo ','Yun ','Hwan ','Di ','','Run ','Jian ','Zhang ','Se ','Pwu ','Kwan ','Xing ','Shou ','Shuan ','Ay ', + 'Chuo ','Zhang ','Ayk ','Kong ','Wan ','Ham ','Tuo ','Tong ','Hwu ','Wo ','Ju ','Gan ','Lyang ','Hun ','Ta ','Thak ', + 'Ceng ','Qie ','De ','Kwen ','Chi ','Sek ','Hyo ','Ki ','Kwul ','Guo ','Han ','Lim ','Tang ','Zhou ','Peng ','Ho ', + 'Chang ','Swuk ','Che ','Fang ','Chi ','Lu ','Nyo ','Ju ','To ','Cong ','Lwu ','Zhi ','Peng ','Pi ','Song ','Tian ', + 'Pi ','Tam ','Yek ','Ni ','E ','Lok ','Kem ','Mi ','Ceng ','Ling ','Lyun ','Um ','Swi ','Qu ','Hoy ','Yu ', + 'Nian ','Sim ','Piao ','Swun ','Wa ','Yen ','Lay ','Hon ','Cheng ','Em ','Chen ','Chem ','Myo ','Zhi ','Yin ','Mi ', + ], + 'x6e':[ + 'Ben ','Yuan ','Wen ','Re ','Fei ','Cheng ','Yuan ','Kal ','Cey ','Sep ','Yuan ','Juu ','Lok ','Zi ','Du ','', + 'Jian ','Min ','Pi ','Kei ','Yu ','Yuan ','Shen ','Cham ','Rou ','Hwan ','Ce ','Kam ','Nuan ','Thwu ','Qiu ','Ceng ', + 'Ke ','To ','Feng ','Sa ','Pal ','Ak ','Wa ','Di ','Oy ','On ','Ru ','Sel ','Chuk ','Wi ','Ge ','Hang ', + 'Yan ','Hong ','Sen ','Mi ','Kal ','Mao ','Yeng ','Yen ','Yu ','Hong ','Myo ','Xing ','Mi ','Cay ','Hon ','Nai ', + 'Kui ','Shi ','E ','Pay ','Mi ','Lyen ','Qi ','Qi ','Mei ','Tian ','Cwu ','Wei ','Can ','Tan ','Myen ','Hui ', + 'Mo ','Se ','Ji ','Pwun ','Cen ','Jian ','Ho ','Feng ','Sang ','Yi ','Yin ','Tam ','Sik ','Jie ','Ceng ','Hwang ', + 'Tan ','Yu ','Bi ','Min ','Shi ','Tu ','Sheng ','Yong ','Qu ','Zhong ','','Chwu ','Jiao ','qiu ','In ','Thang ', + 'Long ','Huo ','Wen ','Nam ','Ban ','You ','Quan ','Chui ','Liang ','Chan ','Po ','Chun ','Nie ','Zi ','Wan ','Sup ', + 'Man ','Yeng ','Ratsu ','Kui ','','Jian ','Xu ','Lu ','Gui ','Kay ','','','Pal ','Jin ','Gui ','Tang ', + 'Wen ','Suo ','Yuan ','Lian ','Yao ','Mong ','Cwun ','Sheng ','Hap ','Tai ','Da ','Wa ','Lyu ','Kwu ','Sao ','Myeng ', + 'Zha ','Shi ','Il ','Lun ','Ma ','Pwu ','Wei ','Lyul ','Cai ','Wu ','Kyey ','On ','Qiang ','Ze ','Shi ','So ', + 'Yi ','Cin ','Swu ','Yun ','Xiu ','Un ','Yong ','Hon ','Su ','Su ','Nik ','Ta ','Shi ','Yok ','Wei ','Pan ', + 'Chu ','Ce ','Pang ','Ong ','Chang ','Myel ','He ','Dian ','Ho ','Hwang ','Xi ','Ca ','Chek ','Zhi ','Hyeng ','Fu ', + 'Jie ','Hwal ','Ge ','Cay ','To ','Tung ','Sui ','Bi ','Jiao ','Hoy ','Kon ','Yin ','Gao ','Long ','Zhi ','Yan ', + 'She ','Man ','Ying ','Chun ','Lu ','Lan ','Luan ','','Bin ','Tan ','Yu ','Sou ','Ho ','Phil ','Biao ','Chey ', + 'Jiang ','Kou ','Cham ','Shang ','Cek ','Mil ','Ao ','Lo ','Ho ','Hu ','You ','Chan ','Fan ','Yong ','Kon ','Man ', + ], + 'x6f':[ + 'Qing ','E ','Phyo ','Ji ','Ay ','Jiao ','Chil ','Xi ','Ji ','Lok ','Lu ','Long ','Kun ','Guo ','Cong ','Lwu ', + 'Zhi ','Kay ','Qiang ','Li ','Yen ','Co ','Jiao ','Cong ','Chun ','Tan ','Kwu ','Teng ','Ye ','Xi ','Mi ','Tang ', + 'Mak ','Shang ','Han ','Lyen ','Lan ','Wa ','Li ','Qian ','Feng ','Xuan ','Uy ','Man ','Ci ','Mang ','Kang ','Ta ', + 'Pwul ','Swu ','Chang ','Cang ','Chong ','Xu ','Huan ','Kuo ','Cem ','Yan ','Chuang ','Liao ','Choy ','Ti ','Yang ','Cang ', + 'Cong ','Yeng ','Hong ','Xun ','Shu ','Guan ','Ying ','Xiao ','','','Xu ','Lian ','Zhi ','Wei ','Pi ','Yul ', + 'Jiao ','Pal ','Dang ','Hui ','Kyel ','Wu ','Pa ','Cip ','Pan ','Kyu ','Swu ','Cam ','Cam ','Hup ','Lo ','Sek ', + 'Sun ','Ton ','Hwang ','Min ','Lyun ','Su ','Lyo ','Zhen ','Zhong ','Yi ','Di ','Wan ','Dan ','Tam ','Co ','Sim ', + 'Kwey ','','Shao ','Tu ','Ce ','San ','Hei ','Bi ','San ','Chan ','Can ','Shu ','Tong ','Po ','Lin ','Wei ', + 'Se ','Sap ','Cing ','Jiong ','Cing ','Hua ','Yo ','Lao ','Chel ','Kem ','Cun ','Hoyng ','Si ','Cwu ','Phayng ','Han ', + 'Wun ','Liu ','Hong ','Fu ','Ho ','He ','Xian ','Kan ','San ','Sek ','Iku ','','Lan ','','Yu ','Lum ', + 'Mian ','Co ','Dang ','Han ','Thayk ','Xie ','Yu ','Lyey ','Se ','Xue ','Ling ','Man ','Zi ','Yong ','Hoy ','Chan ', + 'Lian ','Cen ','Ye ','O ','Huan ','Zhen ','Cen ','Man ','Dan ','Tam ','Yi ','Sui ','Pi ','Ju ','Tan ','Qin ', + 'Kyek ','Thak ','Lyem ','Nong ','Guo ','Jin ','Pwun ','Sayk ','Ji ','Swu ','Yey ','Chu ','Ta ','Song ','Ding ','', + 'Zhu ','Lai ','Bin ','Lian ','Mi ','Sup ','Shu ','Mi ','Nyeng ','Ying ','Yeng ','Mong ','Jin ','Qi ','Pi ','Cey ', + 'Ho ','Yu ','Zui ','Wo ','To ','Yin ','Yin ','Dui ','Ci ','Ho ','Jing ','Lam ','Cwun ','Ai ','Pok ','Thak ', + 'Wei ','Pin ','Gu ','Cam ','Yeng ','Hin ','Kuo ','Fei ','','Boku ','Chen ','Wei ','Luo ','Zan ','Lye ','Li ', + ], + 'x70':[ + 'You ','Yang ','Lu ','Si ','Jie ','Hyeng ','Tok ','Wang ','Hui ','Sa ','Pan ','Sin ','Biao ','Chan ','Mo ','Lyu ', + 'Jian ','Phok ','Sayk ','Cing ','Gu ','Pin ','Huo ','Xian ','Lo ','Qin ','Han ','Yeng ','Yung ','Lyek ','Ceng ','So ', + 'Ying ','Sui ','Wei ','Hay ','Huai ','Hao ','Ce ','Lyong ','Loy ','Dui ','Fan ','Hu ','Loy ','','','Yeng ', + 'Mi ','Ji ','Lyem ','Jian ','Ying ','Fen ','Lin ','Ik ','Chem ','Yue ','Chan ','Dai ','Yang ','Jian ','Lan ','Fan ', + 'Shuang ','Yuan ','Zhuo ','Feng ','Sep ','Lei ','Lan ','Cong ','Qu ','Yong ','Qian ','Fa ','Kwan ','Que ','Yem ','Hao ', + 'Hyeng ','Say ','Zan ','Lan ','Yan ','Li ','Mi ','Shan ','Than ','Dang ','Jiao ','Chan ','','Ho ','Pha ','Zhu ', + 'Lan ','Lan ','Nang ','Man ','Luan ','Xun ','Xian ','Yem ','Gan ','Yem ','Yu ','Hwa ','Biao ','Mie ','Guang ','Ceng ', + 'Hoy ','Xiao ','Xiao ','','Hong ','Lyeng ','Zao ','Zhuan ','Kwu ','Zha ','Xie ','Chi ','Cak ','Cay ','Cay ','Can ', + 'Yang ','Ki ','Zhong ','Fen ','Niu ','Kyeng ','Mwun ','Po ','Yi ','Lo ','Chwi ','Pi ','Kai ','Pan ','Yem ','Kai ', + 'Pang ','Mu ','Cho ','Liao ','Gui ','Hang ','Tun ','Guang ','Hun ','Ca ','Kwang ','Guang ','Wei ','Qiang ','','Da ', + 'Xia ','Ceng ','Zhu ','Ke ','So ','Fu ','Ba ','Duo ','Duo ','Ling ','Zhuo ','Hyen ','Ke ','Than ','Pho ','Hyeng ', + 'Pho ','Tai ','Tai ','Pyeng ','Yang ','Tong ','Han ','Cwu ','Cak ','Cem ','Wi ','Shi ','Lian ','Chi ','Huang ','', + 'Hu ','Shuo ','Lan ','Jing ','Jiao ','Xu ','Xing ','Quan ','Lyel ','Hwan ','Yang ','Hyo ','Xiu ','Xian ','Yin ','O ', + 'Zhou ','Yao ','Shi ','Kyey ','Tong ','Xue ','Zai ','Kai ','Hong ','Lak ','Xia ','Zhu ','Hwen ','Cung ','Po ','Yen ', + 'Hui ','Guang ','Zhe ','Hoy ','Kao ','','Fan ','Shao ','Ye ','Hui ','','Tang ','Jin ','Re ','','Xi ', + 'Fu ','Kyeng ','Che ','Pu ','Jing ','Zhuo ','Ting ','Wan ','Hai ','Phayng ','Lang ','Shan ','Hu ','Pong ','Chi ','Rong ', + ], + 'x71':[ + 'Hu ','','Shu ','He ','Hwun ','Ku ','Jue ','Xiao ','Xi ','En ','Han ','Zhuang ','Cwun ','Di ','Xie ','Ji ', + 'Wu ','','Lua ','Han ','Yen ','Hwan ','Men ','Ju ','Chou ','Pay ','Pwun ','Lin ','Hon ','Hun ','Ton ','Xi ', + 'Swi ','Mwu ','Hong ','Ju ','Fu ','Wo ','Cho ','Cong ','Feng ','Ping ','Qiong ','Ruo ','Xi ','Kyeng ','Hun ','Cak ', + 'Yen ','Hyek ','Yi ','Jue ','Yu ','Gang ','Yen ','Pi ','Gu ','','Sheng ','Chang ','So ','','Nam ','Geng ', + 'Wat ','Chen ','He ','Kui ','Zhong ','Duan ','Ha ','Hwi ','Feng ','Lyen ','Hwen ','Xing ','Hwang ','Jiao ','Cen ','Bi ', + 'Yeng ','Ca ','Wi ','Tuan ','Tian ','Huy ','Nan ','Nan ','Chan ','Yen ','Jiong ','Jiong ','Wuk ','Mei ','Sal ','Wei ', + 'Ye ','Xin ','Kyeng ','Rou ','May ','Hwan ','Hwu ','Co ','Oy ','Pen ','Qiu ','Sui ','Yang ','Lie ','Ca ','', + 'Gao ','Gua ','Bao ','Hu ','Yun ','Xia ','','','Bian ','Gou ','Tui ','Tang ','Chao ','Sen ','En ','Bo ', + 'Yep ','Xie ','Xi ','Wu ','Sik ','On ','He ','Hyo ','Huy ','Wun ','Wung ','Nai ','Shan ','','Yao ','Hwun ', + 'Mi ','Lian ','Hyeng ','Wu ','Yong ','Kou ','En ','Qiang ','Liu ','Huy ','Bi ','Phyo ','Zong ','Lu ','Jian ','Swuk ', + 'Sup ','Lou ','Pong ','Sui ','Ik ','Tong ','Jue ','Zong ','Wi ','Hu ','Yi ','Zhi ','O ','Wei ','Liao ','Sen ', + 'Ou ','Yel ','Kyeng ','Man ','','Shang ','Cuan ','Zeng ','Jian ','Huy ','Huy ','Xi ','Yi ','Xiao ','Chi ','Huang ', + 'Chan ','Yep ','Qian ','Yen ','Yan ','Xian ','Qiao ','Zun ','Tung ','Ton ','Shen ','Cho ','Fen ','Si ','Lyo ','Yu ', + 'Lin ','Tong ','So ','Fen ','Pen ','Yen ','Sim ','Lan ','Mei ','Thang ','Yi ','Jing ','Men ','','','Yeng ', + 'Wuk ','Yi ','Xue ','Lan ','Tai ','Co ','Chan ','Swu ','Xi ','Que ','Cong ','Lian ','Hwey ','Chok ','Sep ','Ling ', + 'Wei ','Yi ','Xie ','Zhao ','Hui ','Tatsu ','Nung ','Lan ','Ru ','Huy ','Kao ','Hwun ','Sin ','Chou ','To ','Yo ', + ], + 'x72':[ + 'Hyek ','Lan ','Biao ','Rong ','Li ','Mo ','Phok ','Sel ','Lu ','La ','Ao ','Hwun ','Kwang ','Sak ','','Li ', + 'Lo ','Jue ','Liao ','Yan ','Huy ','Xie ','Long ','Yep ','','Rang ','Yak ','Lan ','Cong ','Jue ','Tong ','Kwan ', + '','Che ','Mi ','Tang ','Lan ','Chok ','Laam ','Ling ','Chan ','Yu ','Co ','Lam ','Pha ','Cayng ','Pao ','Cheng ', + 'Wen ','Ai ','Wi ','','Jue ','Cak ','Pwu ','Ye ','Pha ','Ta ','Ya ','Hyo ','Zu ','Sang ','I ','Qiang ', + 'Sang ','Ge ','Cang ','Die ','Qiang ','Yong ','Cang ','Phyen ','Phan ','Pan ','Shao ','Cen ','Phay ','Du ','Chuang ','Tou ', + 'Zha ','Bian ','Chep ','Pang ','Pak ','Chuang ','Yu ','','Tok ','A ','Thayng ','Wu ','Ushihen ','Pin ','Jiu ','Mo ', + 'Tuo ','Mo ','Loy ','Ren ','Mang ','Fang ','Mao ','Mok ','Gang ','Mwul ','Yan ','Ge ','Bei ','Si ','Jian ','Ko ', + 'You ','Ge ','Sayng ','Mu ','Ce ','Qian ','Quan ','Quan ','Ca ','Thuk ','Xi ','Mang ','Keng ','Kyen ','Wu ','Gu ', + 'Se ','Li ','Li ','Pou ','Ji ','Gang ','Zhi ','Pwun ','Quan ','Run ','Du ','Ju ','Jia ','Ken ','Feng ','Pian ', + 'Ke ','Ju ','Ho ','Chu ','Xi ','Bei ','Lak ','Jie ','Ma ','San ','Wei ','Li ','Ton ','Tong ','','Jiang ', + 'Gi ','Li ','Tok ','Lie ','Pi ','Piao ','Bao ','Huy ','Chou ','Wei ','Kui ','Chou ','Kyen ','Hyun ','Ba ','Pem ', + 'Qiu ','Ji ','Cai ','Cak ','An ','Hil ','Cang ','Guang ','Ma ','You ','Kang ','Bo ','Hou ','Ya ','Yin ','Huan ', + 'Sang ','Yun ','Kwang ','Niu ','Cek ','Qing ','Zhong ','Mu ','Bei ','Pi ','Ju ','Ni ','Sheng ','Pao ','Ap ','Tuo ', + 'Ho ','Ling ','Pi ','Pi ','Ni ','Ao ','You ','Kwu ','Yue ','Ce ','Dan ','Po ','Gu ','Xian ','Ning ','Huan ', + 'Hen ','Kyo ','Hak ','Zhao ','Ji ','Swun ','Shan ','Ta ','Yung ','Swu ','Tong ','Lao ','Tok ','Xia ','Shi ','Hua ', + 'Zheng ','Yu ','Sun ','Yu ','Phyey ','Mang ','Xi ','Kyen ','Li ','Hyep ','Un ','San ','Lang ','Phay ','Zhi ','Yan ', + ], + 'x73':[ + 'Sha ','Li ','Han ','Xian ','Jing ','Pai ','Fei ','Yao ','Ba ','Ki ','Yey ','Biao ','Yin ','Lai ','Xi ','Jian ', + 'Qiang ','Kun ','Yan ','Kwa ','Zong ','Mi ','Chang ','Uy ','Cey ','Cayng ','Ya ','Mayng ','Si ','Col ','She ','Ryou ', + 'Cen ','Luo ','Ho ','Zong ','Ji ','Oy ','Feng ','Wa ','Wen ','Seng ','Ce ','Myo ','Wei ','Yuan ','Hen ','Tuan ', + 'Ya ','No ','Xie ','Jia ','Hwu ','Bian ','Yu ','Yu ','Mei ','Zha ','Yao ','Sun ','Bo ','Ming ','Hwal ','Wen ', + 'Sou ','Ma ','Yuan ','Ay ','Ok ','Sa ','Hao ','','Yi ','Zhen ','Chuang ','Hao ','Man ','Jing ','Jiang ','Mu ', + 'Cang ','Chan ','O ','Ao ','Hao ','Cui ','Fen ','Kwel ','Phyey ','Bi ','Huang ','Pu ','Lin ','Yu ','Tong ','Yao ', + 'Lyo ','Shuo ','Xiao ','Swu ','Ton ','Xi ','Ge ','Juan ','Tok ','Yey ','Hoy ','Hem ','Hay ','Ta ','Xian ','Hwun ', + 'Yeng ','Pin ','Hoyk ','Nou ','Meng ','Lyep ','Nao ','Kwang ','Swu ','Lu ','Tal ','Hen ','Mi ','Rang ','Huan ','Nao ', + 'Luo ','Hem ','Qi ','Jue ','Hyen ','Miao ','Ca ','Sol ','Lo ','Ok ','Su ','Wang ','Qiu ','Ga ','Ceng ','Le ', + 'Ba ','Ji ','Hong ','Di ','Chen ','Kan ','Kwu ','Wu ','Ki ','Ye ','Yang ','Ma ','Gong ','Wu ','Pwu ','Min ', + 'Kay ','Ya ','Bin ','Bian ','Bang ','Yue ','Kyel ','Yun ','Kak ','Wan ','Jian ','May ','Dan ','Pin ','Wei ','Huan ', + 'Xian ','Qiang ','Lyeng ','Tay ','Yi ','An ','Ping ','Cem ','Fu ','Hyeng ','Xi ','Pha ','Ci ','Gou ','Jia ','Shao ', + 'Pak ','Ci ','Ka ','Ran ','Sheng ','Shen ','I ','Zu ','Ka ','Min ','San ','Liu ','Phil ','Cin ','Zhen ','Kak ', + 'Fa ','Long ','Cin ','Jiao ','Jian ','Li ','Kwang ','Xian ','Zhou ','Kong ','Yan ','Xiu ','Yang ','Hwu ','Lak ','Su ', + 'Cwu ','Qin ','Un ','Swun ','Po ','I ','Hyang ','Yao ','Xia ','Hyeng ','Kyu ','Chwung ','Xu ','Pan ','Phay ','', + 'Dang ','Ei ','Hun ','Wen ','E ','Ceng ','Di ','Mwu ','Wu ','Seng ','Jun ','Mei ','Bei ','Ceng ','Hyen ','Chuo ', + ], + 'x74':[ + 'Han ','Sen ','Yan ','Kwu ','Hyen ','Lang ','Li ','Swu ','Fu ','Lyu ','Ye ','Xi ','Ling ','Li ','Cin ','Lian ', + 'Suo ','Sa ','','Wan ','Dian ','Pin ','Zhan ','Cui ','Min ','Yu ','Ju ','Chim ','Lai ','Wen ','Sheng ','Wei ', + 'Cen ','Swu ','Thak ','Pei ','Cayng ','Ho ','Ki ','E ','Kon ','Chang ','Ki ','Pong ','Wan ','Lu ','Cong ','Kwan ', + 'Yem ','Co ','Pay ','Lim ','Kum ','Pi ','Pha ','Que ','Thak ','Qin ','Pep ','','Qiong ','Du ','Jie ','Hun ', + 'Wu ','Mo ','Mei ','Chwun ','Sen ','Cey ','Seng ','Dai ','Rou ','Min ','Zhen ','Wi ','Ruan ','Huan ','Hay ','Chuan ', + 'Jian ','Zhuan ','Yang ','Lian ','Quan ','Ha ','Duan ','Wen ','Ye ','No ','Ho ','Yeng ','Yu ','Hwang ','Se ','Sul ', + 'Lyu ','','Yong ','Sway ','Yo ','On ','Wu ','Jin ','Cin ','Hyeng ','Ma ','Tao ','Liu ','Tang ','Li ','Lang ', + 'Koy ','Cen ','Chang ','Cha ','Jue ','Zhao ','Yo ','Ai ','Bin ','Tu ','Chang ','Kun ','Zhuan ','Cong ','Kun ','Yi ', + 'Choy ','Cong ','Ki ','Li ','Ying ','Suo ','Kwu ','Sen ','Ao ','Lyen ','Mwun ','Cang ','Yin ','','Ying ','Zhi ', + 'Lu ','Wu ','Deng ','xiu ','Zeng ','Xun ','Qu ','Dang ','Lin ','Liao ','Qiong ','Su ','Hwang ','Koy ','Pak ','Kyeng ', + 'Fan ','Cin ','Liu ','Ki ','','Kyeng ','Ai ','Pyek ','Chan ','Qu ','Co ','Tang ','Jiao ','Gun ','Tan ','Hui ', + 'Hwan ','Se ','Swu ','Tian ','','Ye ','Jin ','Lu ','Bin ','Swu ','Wen ','Zui ','Lan ','Say ','Ji ','Sen ', + 'Ruan ','Huo ','Gai ','Lei ','Du ','Li ','Cil ','Rou ','Li ','Zan ','Kyeng ','Zhe ','Gui ','Sui ','La ','Lyong ', + 'Lu ','Li ','Zan ','Lan ','Yeng ','Mi ','Xiang ','Xi ','Kwan ','Dao ','Chan ','Hwan ','Kwa ','Bo ','Die ','Bao ', + 'Ho ','Zhi ','Phyo ','Phan ','Rang ','Li ','Wa ','Dekaguramu ','Jiang ','Chen ','Fan ','Pen ','Fang ','Dan ','Ong ','Ou ', + 'Deshiguramu ','Miriguramu ','Thon ','Hu ','Ling ','Yi ','Pyeng ','Ca ','Hekutogura ','Juan ','Chang ','Chi ','Sarake ','Dang ','Meng ','Pou ', + ], + 'x75':[ + 'Zhui ','Pyeng ','Bian ','Chwu ','Kyen ','Senchigura ','Ci ','Ying ','Qi ','Xian ','Lou ','Di ','Kwu ','Meng ','Cen ','Peng ', + 'Lin ','Cung ','Wu ','Pyek ','Dan ','Ong ','Ying ','Yan ','Kam ','Dai ','Sim ','Chem ','Chem ','Han ','Sang ','Sayng ', + 'Qing ','Shen ','San ','San ','Rui ','Sayng ','So ','Sen ','Yong ','Shuai ','Lu ','Po ','Yong ','Beng ','Feng ','Nyeng ', + 'Cen ','Yu ','Kap ','Sin ','Zha ','Dian ','Fu ','Nam ','Cen ','Ping ','Ceng ','Hwa ','Ceng ','Kyen ','Zi ','Meng ', + 'Pi ','Qi ','Liu ','Xun ','Liu ','Chang ','Mu ','Kyun ','Fan ','Fu ','Kyeng ','Cen ','Kyey ','Jie ','Kyen ','Oy ', + 'Fu ','Cen ','Mu ','Tap ','Pan ','Jiang ','Wa ','Da ','Nan ','Lyu ','Pwun ','Cin ','Chwuk ','Mwu ','Mu ','Ce ', + 'Cen ','Gai ','Phil ','Da ','Chi ','Lyak ','Hyu ','Lyak ','Pan ','Kesa ','Pen ','Hwa ','Yu ','Yu ','Mwu ','Cwun ', + 'I ','Liu ','Yu ','Die ','Chou ','Hwa ','Tang ','Chuo ','Ki ','Wan ','Kang ','Sheng ','Chang ','Tuan ','Lei ','Ki ', + 'Cha ','Liu ','Jou ','Tuan ','Lin ','Jiang ','Kang ','Cwu ','Pyek ','Die ','Chep ','Phil ','Nie ','Dan ','So ','So ', + 'Zhi ','Uy ','Chuang ','Nai ','Ceng ','Bi ','Jie ','Liao ','Gang ','Hul ','Kwu ','Zhou ','Xia ','San ','Xu ','Nue ', + 'Li ','Yang ','Chen ','Yu ','Pha ','Kay ','Jue ','Zhi ','Xia ','Chwi ','Bi ','Yek ','Li ','Zong ','Chuang ','Feng ', + 'Zhu ','Pho ','Phi ','Kam ','A ','Ca ','Xie ','Qi ','Tal ','Cin ','Fa ','Zhi ','Tong ','Ce ','Cil ','Fei ', + 'Kwu ','Dian ','Ka ','Hyen ','Zha ','Pyeng ','Ni ','Cung ','Yong ','Jing ','Cen ','Chong ','Tong ','I ','Hay ','Wei ', + 'Hui ','Duo ','Yang ','Chi ','Chi ','Hun ','Ya ','Mei ','Twu ','Kyeng ','Xiao ','Thong ','Tu ','Mang ','Pi ','Xiao ', + 'Suan ','Pu ','Li ','Ci ','Cwa ','Duo ','Wu ','Sa ','Lao ','Swu ','Huan ','Xian ','Yi ','Peng ','Zhang ','Guan ', + 'Tam ','Fei ','Ma ','Lim ','Chi ','Ji ','Dian ','An ','Chi ','Pi ','Pi ','Min ','Ko ','Dui ','E ','Wi ', + ], + 'x76':[ + 'E ','Chwi ','Ya ','Zhu ','Cu ','Dan ','Shen ','Cong ','Kyey ','Yu ','Hou ','Phwung ','La ','Yang ','Shen ','Tu ', + 'Yu ','Gua ','Wen ','Huan ','Ku ','Ha ','Yin ','Yi ','Lu ','So ','Jue ','Chi ','Xi ','Guan ','Yi ','On ', + 'Chek ','Chang ','Pan ','Lei ','Lyu ','Chai ','Swu ','Hak ','Dian ','Da ','Pie ','Tan ','Zhang ','Biao ','Shen ','Cok ', + 'La ','Yi ','Zong ','Chwu ','Cang ','Zhai ','Sou ','Suo ','Que ','Diao ','Lou ','Lwu ','Mo ','Jin ','Yin ','Ying ', + 'Huang ','Fu ','Lyo ','Lyung ','Qiao ','Liu ','Lo ','Xian ','Phyey ','Tan ','Yin ','He ','Am ','Ban ','Kan ','Guan ', + 'Guai ','Nong ','Yu ','Wei ','Yi ','Ong ','Pyek ','Lei ','Lye ','Shu ','Dan ','Lin ','Cen ','Lin ','Lai ','Bie ', + 'Ji ','Chi ','Yang ','Xian ','Cel ','Cing ','Mak6','Lyek ','Kwak ','La ','Shaku ','Dian ','Sen ','Yeng ','Un ','Kwu ', + 'Yong ','Than ','Cen ','Luo ','Luan ','Luan ','Bo ','','Kyey ','Po ','Pal ','Tung ','Pal ','Payk ','Payk ','Qie ', + 'Kup ','Co ','Zao ','Mo ','Cek ','Pa ','Kay ','Hwang ','Gui ','Ci ','Ling ','Ko ','Mo ','Ji ','Kyo ','Peng ', + 'Ko ','Ai ','E ','Ho ','Han ','Bi ','Hwan ','Chou ','Qian ','Xi ','Ay ','Hyo ','Ho ','Huang ','Ho ','Ze ', + 'Cui ','Hao ','Xiao ','Ye ','Pha ','Hao ','Jiao ','Ai ','Xing ','Huang ','Li ','Piao ','Hak ','Jiao ','Phi ','Gan ', + 'Pao ','Zhou ','Jun ','Qiu ','Cwun ','Que ','Sa ','Gu ','Kwun ','Jun ','Chwu ','Zha ','Gu ','Zhan ','Du ','Myeng ', + 'Qi ','Ying ','Wu ','Pay ','Zhao ','Zhong ','Pwun ','He ','Yeng ','He ','Ik ','Bo ','Wan ','Hap ','Ang ','Zhan ', + 'Yan ','Jian ','Hap ','Yu ','Hoy ','Fan ','Kay ','Dao ','Pan ','Po ','Qiu ','Seng ','To ','Lu ','Can ','Mayng ', + 'Li ','Cin ','Xu ','Kam ','Pan ','Kwan ','An ','Lo ','Shu ','Zhou ','Thang ','An ','Ko ','Li ','Mok ','Ding ', + 'Gan ','Yu ','Mayng ','Mang ','Cik ','Qi ','Ruan ','Tian ','Sang ','Swun ','Xin ','Hyey ','Pan ','Feng ','Swun ','Min ', + ], + 'x77':[ + 'Ming ','Seng ','Shi ','Yun ','Myen ','Pan ','Fang ','Myo ','Tham ','Mi ','Mo ','Kan ','Hyen ','Ou ','Shi ','Yang ', + 'Zheng ','Yao ','Shen ','Huo ','Da ','Zhen ','Kuang ','Ju ','Shen ','Chi ','Sayng ','May ','Mo ','Zhu ','Cin ','Zhen ', + 'Myen ','Di ','Yuan ','Die ','Yi ','Ca ','Ca ','Chao ','Cap ','Hyen ','Bing ','Mi ','Long ','Sui ','Dong ','Mi ', + 'Die ','Yi ','Er ','Ming ','Swun ','Chi ','Kuang ','Kwen ','Mo ','Zhen ','Co ','Yang ','An ','Mo ','Cwung ','Mai ', + 'Chak ','Zheng ','Mei ','Jun ','Shao ','Han ','Hwan ','Cey ','Cheng ','Cuo ','Juan ','E ','Wan ','Hyen ','Xi ','Kun ', + 'Lai ','Jian ','Sem ','Tian ','Hun ','Wan ','Ling ','Shi ','Qiong ','Lie ','Ay ','Ceng ','Zheng ','Li ','Lai ','Swu ', + 'Kwen ','Swu ','Swu ','Tok ','Bi ','Pi ','Mok ','Hun ','Yey ','Lu ','Yi ','Chep ','Chay ','Zhou ','Yu ','Hun ', + 'Ma ','Xia ','Xing ','Xi ','Gun ','','Chun ','Ken ','Mei ','To ','Hou ','Xuan ','Ti ','Kyu ','Ko ','Yey ', + 'Mao ','Xu ','Fa ','Wen ','Miao ','Chou ','Kui ','Mi ','Weng ','Kou ','Dang ','Cin ','Ke ','Swu ','Hal ','Qiong ', + 'Mao ','Myeng ','Man ','Shui ','Ze ','Zhang ','Yey ','Diao ','Ou ','Mak ','Shun ','Cong ','Lou ','Chi ','Man ','Piao ', + 'Tang ','Ji ','Mong ','','Run ','Pyel ','Xi ','Qiao ','Pu ','Zhu ','Cing ','Shen ','Swun ','Lyo ','Che ','Xian ', + 'Kam ','Ye ','Xu ','Tong ','Mou ','Lin ','Kui ','Xian ','Ye ','Ay ','Hui ','Chem ','Kem ','Ko ','Zhao ','Kwu ', + 'Wei ','Chou ','Sao ','Nyeng ','Xun ','Yao ','Huo ','Mong ','Mian ','Pin ','Mian ','Li ','Kuang ','Hwak ','Xuan ','Mian ', + 'Huo ','Lu ','Meng ','Long ','Guan ','Man ','Xi ','Chok ','Tang ','Kem ','Chok ','Mo ','Kung ','Lin ','Yul ','Shuo ', + 'Ce ','Hwak ','Si ','Uy ','Shen ','Ci ','Hou ','Sin ','Ying ','Kwu ','Zhou ','Jiao ','Cuo ','Tan ','Way ','Kyo ', + 'Cung ','Huo ','Bai ','Sek ','Ding ','Qi ','Ji ','Zi ','Gan ','Wu ','Thak ','Kol ','Kang ','Sek ','Fan ','Kuang ', + ], + 'x78':[ + 'Dang ','Ma ','Sa ','Dan ','Jue ','Li ','Fu ','Min ','Nuo ','Huo ','Kang ','Zhi ','Chey ','Kan ','Jie ','Pwun ', + 'E ','A ','Pi ','Zhe ','Yen ','Sway ','Zhuan ','Che ','Dun ','Pan ','Yan ','','Feng ','Fa ','Mo ','Zha ', + 'Qu ','Yu ','La ','Tuo ','Tuo ','Ci ','Chay ','Chim ','Ai ','Fei ','Mu ','Zhu ','Lip ','Phyem ','Nu ','Ping ', + 'Phayng ','Ling ','Pho ','Le ','Pha ','Bo ','Po ','Shen ','Za ','Nuo ','Lye ','Long ','Tong ','','Li ','Kou ', + 'Chu ','Keng ','Quan ','Cwu ','Kuang ','Kyu ','E ','Nao ','Jia ','Lu ','Wei ','Ai ','Luo ','Ken ','Xing ','Yen ', + 'Tong ','Peng ','Xi ','','Hong ','Shuo ','Xia ','Qiao ','','Wei ','Qiao ','','Kayng ','Cho ','Que ','Chan ', + 'Lang ','Hong ','Yu ','Xiao ','Xia ','Mang ','Long ','Yong ','Cha ','Che ','E ','Lyu ','Kyeng ','Mang ','Hak ','Yen ', + 'Sha ','Kun ','Yu ','','Kaki ','Lu ','Chen ','Jian ','Nue ','Song ','Zhuo ','Keng ','Pwung ','Yan ','Zhui ','Kong ', + 'Ceng ','Ki ','Zong ','Qing ','Lin ','Jun ','Bo ','Ceng ','Min ','Diao ','Jian ','He ','Lok ','Ay ','Sway ','Cak ', + 'Ling ','Pi ','Yin ','Tay ','Wu ','Qi ','Lun ','Wan ','Dian ','Gang ','Bei ','Qi ','Chen ','Ruan ','Yan ','Sel ', + 'Ding ','Du ','Tuo ','Kal ','Yeng ','Bian ','Ke ','Pyek ','Oy ','Sek ','Zhen ','Duan ','Xia ','Thang ','Ti ','Nao ', + 'Peng ','Jian ','Di ','Tan ','Cha ','Seki ','Qi ','','Feng ','Xuan ','Hwak ','Hwak ','Ma ','Gong ','Nyen ','Su ', + 'E ','Ca ','Liu ','Si ','Tang ','Pang ','Hua ','Pi ','Oy ','Sang ','Loy ','Cha ','Zhen ','Xia ','Kyey ','Lyem ', + 'Pan ','Ay ','Yun ','Dui ','Chayk ','Kay ','La ','','Qing ','Gun ','Cen ','Chan ','Qi ','Ao ','Peng ','Lu ', + 'Nyo ','Kan ','Qiang ','Chen ','Yin ','Lei ','Biao ','Cek ','Ma ','Qi ','Choy ','Zong ','Kyeng ','Chuo ','','Ki ', + 'Shan ','Lao ','Qu ','Zeng ','Tung ','Kan ','Xi ','Lin ','Ding ','Dian ','Kwang ','Pan ','Cap ','Kyo ','Di ','Li ', + ], + 'x79':[ + 'Kan ','Cho ','','Zhang ','Qiao ','Dun ','Xian ','Yu ','Zhui ','He ','Huo ','Zhai ','Loy ','Ke ','Cho ','Kup ', + 'Que ','Tang ','Uy ','Jiang ','Pi ','Pi ','Ye ','Pin ','Qi ','Ay ','Kai ','Jian ','Yu ','Ruan ','Meng ','Pao ', + 'Ci ','Bo ','','Mie ','Ca ','Xian ','Kwang ','Loy ','Lei ','Zhi ','Lye ','Lyek ','Pan ','Hwak ','Pao ','Ying ', + 'Li ','Long ','Long ','Mo ','Bo ','Shuang ','Guan ','Lan ','Zan ','Yan ','Si ','Shi ','Lyey ','Reng ','Sa ','Yue ', + 'Sa ','Ki ','Ta ','Ma ','Xie ','Yo ','Chen ','Ki ','Ki ','Ci ','Phayng ','Dui ','Zhong ','','Yi ','Shi ', + 'Wu ','Zhi ','Tiao ','Pwul ','Pwu ','Pi ','Co ','Ci ','Suan ','Mei ','Co ','Ke ','Ho ','Chwuk ','Sin ','Swu ', + 'Sa ','Chai ','Ni ','Lu ','Yu ','Sang ','Wu ','Co ','Phyo ','Zhu ','Gui ','Xia ','Zhi ','Cey ','Gao ','Zhen ', + 'Gao ','Shui ','Jin ','Chen ','Gai ','Kun ','Di ','To ','Huo ','Tao ','Ki ','Gu ','Kwan ','Zui ','Ling ','Lok ', + 'Phwum ','Kum ','Dao ','Zhi ','Lu ','Sen ','Bei ','Zhe ','Hui ','You ','Kyey ','In ','Zi ','Hwa ','Ceng ','Pok ', + 'Yuan ','Wu ','Xian ','Yang ','Cey ','Yi ','Mei ','Si ','Di ','','Zhuo ','Zhen ','Yong ','Cik ','Gao ','Tang ', + 'Si ','Ma ','Ta ','','Xuan ','Qi ','E ','Huy ','Ki ','Si ','Sen ','Tam ','Kuai ','Sui ','Lyey ','Nong ', + 'Ni ','To ','Li ','Yang ','Yak ','Ti ','Zan ','Lei ','Rou ','Wu ','Ong ','Li ','Xie ','Kum ','Hwa ','Tok ', + 'Swu ','Sa ','Ren ','Tok ','Zi ','Cha ','Kan ','Yi ','Xian ','Pyeng ','Nyen ','Chwu ','Qiu ','Chwung ','Fen ','Hao ', + 'Yun ','Kwa ','Cho ','Zhi ','Geng ','Pi ','Ci ','Yu ','Pi ','Ku ','Ban ','Pi ','Ni ','Li ','You ','Co ', + 'Pi ','Ba ','Lyeng ','Mal ','Ching ','Nian ','Cin ','Ang ','Zuo ','Cil ','Ci ','Chwul ','Ke ','Zi ','Huo ','Ji ', + 'Ching ','Tong ','Zhi ','Huo ','He ','Yin ','Zi ','Zhi ','Kal ','Ren ','Du ','I ','Zhu ','Hui ','Nong ','Fu ', + ], + 'x7a':[ + 'Huy ','Ko ','Lang ','Fu ','Ze ','Sey ','Lu ','Kun ','Kan ','Geng ','Cey ','Ceng ','To ','Cho ','Sey ','Ya ', + 'Lun ','Lu ','Gu ','Zuo ','Im ','Zhun ','Bang ','Phay ','Ji ','Cik ','Chi ','Kun ','Lung ','Peng ','Kwa ','Phwum ', + 'Co ','Zu ','Yu ','Su ','Lue ','','Yi ','Sel ','Bian ','Ji ','Fu ','Bi ','Nuo ','Jie ','Cong ','Zong ', + 'Xu ','Ching ','To ','On ','Lian ','Zi ','Wuk ','Cik ','Xu ','Cin ','Zhi ','To ','Ka ','Kyey ','Gao ','Ko ', + 'Kok ','Rong ','Sui ','You ','Ji ','Kang ','Mok ','Shan ','Men ','Chi ','Ji ','Lu ','So ','Cek ','Yeng ','On ', + 'Chwu ','Se ','','Yi ','Huang ','Qie ','Ji ','Swu ','Xiao ','Pu ','Jiao ','Zhuo ','Tong ','Sai ','Lu ','Sui ', + 'Nong ','Sayk ','Yey ','Rang ','Nuo ','Yu ','','Ji ','Tui ','On ','Cheng ','Hwak ','Gong ','Lu ','Biao ','', + 'Yang ','Zhuo ','Li ','Zan ','Hyel ','Al ','Kwu ','Qiong ','Xi ','Kwung ','Kong ','Yu ','Sen ','Ceng ','Yo ','Chen ', + 'Twun ','Tol ','Lo ','Cel ','Chak ','Yo ','Phyem ','Bao ','Yo ','Bing ','Wa ','Zhu ','Jiao ','Qiao ','Diao ','Wu ', + 'Gui ','Yao ','Cil ','Chang ','Yao ','Co ','Kyo ','Chang ','Kwun ','Xiao ','Cheng ','Kwu ','Cuan ','Wo ','Dan ','Kwul ', + 'Kwa ','Zhui ','Xu ','Sol ','','Kui ','Dou ','','Yin ','Wa ','Wa ','Ya ','Yu ','Ju ','Kwung ','Yo ', + 'Yao ','Tiao ','Chao ','Yu ','Tian ','Diao ','Kwu ','Liao ','Xi ','O ','Kyu ','Chang ','Zhao ','Fun ','Kwan ','Lyung ', + 'Cheng ','Cui ','Piao ','Zao ','Chan ','Kyu ','Qiong ','Twu ','Co ','Long ','Cel ','Lip ','Chu ','Dekaritto ','Fou ','Kirorittoru ', + 'Chu ','Hong ','Qi ','Miririttoru ','','Deshiritto ','Shu ','Myo ','Ju ','Cham ','Zhu ','Ling ','Lyong ','Pyeng ','Jing ','Kyeng ', + 'Cang ','Hekutoritto ','Sa ','Cwun ','Hong ','Tong ','Song ','Jing ','Diao ','Yi ','Swu ','Jing ','Qu ','Kal ','Ping ','Tan ', + 'Shao ','Zhuan ','Ceng ','Deng ','Cui ','Huai ','Kyeng ','Kan ','Kyeng ','Cwuk ','Chwuk ','Le ','Peng ','Wu ','Chi ','Kan ', + ], + 'x7b':[ + 'Mang ','Zhu ','Utsubo ','Du ','Ji ','Xiao ','Pha ','Suan ','Kup ','Zhen ','Co ','Swun ','A ','Zhui ','Yuan ','Hol ', + 'Gang ','So ','Kum ','Pi ','Bi ','Jian ','Yi ','Dong ','Cem ','Sayng ','Xia ','Cek ','Zhu ','Na ','Thay ','Gu ', + 'Lip ','Qie ','Min ','Bao ','Tiao ','Sa ','Pwu ','Chayk ','Pwun ','Pei ','Tal ','Zi ','Cey ','Lyeng ','Ze ','No ', + 'Fu ','Gou ','Fan ','Ka ','Ge ','Pem ','Shi ','Mao ','Po ','Sey ','Jian ','Kong ','Long ','Souke ','Bian ','Luo ', + 'Gui ','Qu ','Chi ','Yin ','Yao ','Sen ','Phil ','Qiong ','Kwal ','Tung ','Jiao ','Kun ','Cen ','Swun ','Ru ','Pel ', + 'Kwang ','Chwuk ','Thong ','Kyey ','Tap ','Xing ','Chayk ','Zhong ','Kou ','Lai ','Bi ','Shai ','Dang ','Zheng ','Ce ','Pwu ', + 'Kyun ','Tu ','Pa ','Li ','Lang ','Ke ','Kwan ','Kyen ','Han ','Thong ','Xia ','Zhi ','Seng ','Suan ','Se ','Zhu ', + 'Zuo ','So ','Shao ','Ceng ','Ce ','Yen ','Gao ','Kuai ','Gan ','Chou ','Kyou ','Gang ','Yun ','O ','Qian ','So ', + 'Jian ','Pu ','Lai ','Zou ','Bi ','Bi ','Bi ','Kay ','Chi ','Guai ','Yu ','Cen ','Zhao ','Ko ','Ho ','Cayng ', + 'Jing ','Sha ','Chwu ','Lu ','Pak ','Ki ','Lin ','San ','Jun ','Pok ','Cha ','Gu ','Kong ','Kyem ','Quan ','Jun ', + 'Chwu ','Kwan ','Yuan ','Ce ','Ju ','Bo ','Ze ','Qie ','Tuo ','Luo ','Tan ','Xiao ','Ruo ','Cen ','','Bian ', + 'Sun ','Sang ','Xian ','Ping ','Cam ','Sheng ','Hu ','Shi ','Ce ','Yue ','Chun ','Lu ','Wu ','Dong ','So ','Ji ', + 'Cel ','Hwang ','Xing ','Mei ','Pem ','Chui ','Cen ','Phyen ','Feng ','Chwuk ','Hong ','Hyep ','Hwu ','Qiu ','Miao ','Qian ', + '','Kui ','Sik ','Lou ','Wun ','He ','Tang ','Yue ','Chou ','Ko ','Fei ','Yak ','Zheng ','Kwu ','Nie ','Qian ', + 'So ','Chan ','Gong ','Pang ','Tok ','Lyul ','Pi ','Zhuo ','Chu ','Sa ','Ci ','Zhu ','Qiang ','Long ','Lan ','Jian ', + 'Bu ','Li ','Hui ','Phil ','Di ','Cong ','Yan ','Pong ','Sen ','Zhuan ','Pai ','Piao ','Dou ','Yu ','Myel ','Zhuan ', + ], + 'x7c':[ + 'Chayk ','Xi ','Guo ','Yi ','Hu ','Chan ','Kou ','Cok ','Ping ','Chwu ','Ji ','Kwey ','Su ','Lou ','Zha ','Lok ', + 'Nian ','Sa ','Chan ','Sen ','Sa ','Le ','Duan ','Yana ','So ','Bo ','Mi ','Si ','Dang ','Liao ','Tan ','Cem ', + 'Po ','Kan ','Min ','Kui ','Dai ','Jiao ','Deng ','Hwang ','Sun ','Lao ','Cam ','So ','Lu ','Shi ','Zan ','', + 'Pai ','Hata ','Pai ','Gan ','Ju ','Du ','Lu ','Chem ','Pha ','Dang ','Sai ','Ke ','Long ','Chem ','Lyem ','Pwu ', + 'Zhou ','Lai ','','Lam ','Kui ','Yu ','Yue ','Hao ','Zhen ','Tai ','Ti ','Mi ','Cwu ','Cek ','','Hata ', + 'Tung ','Zhuan ','Cwu ','Fan ','Swu ','Zhou ','Sen ','Zhuo ','Teng ','Lu ','Lu ','Cen ','Thak ','Ying ','Yu ','Loy ', + 'Long ','Shinshi ','Lian ','Lan ','Chem ','Yak ','Zhong ','Ke ','Lian ','Pyen ','Duan ','Zuan ','Li ','Si ','Luo ','Ying ', + 'Yue ','Zhuo ','Yu ','Mi ','Di ','Fan ','Shen ','Zhe ','Shen ','Nu ','Xie ','Lyu ','Xian ','Zi ','In ','Cun ', + '','Chen ','Kume ','Pi ','Ban ','Wu ','Sha ','Kang ','Rou ','Pwun ','Bi ','Cui ','','Mo ','Chi ','Ta ', + 'Ro ','Ba ','Lip ','Gan ','Ju ','Pak ','Mo ','Co ','Cem ','Zhou ','Li ','Su ','Tiao ','Li ','Xi ','Sok ', + 'Hong ','Tong ','Ca ','Ce ','Wel ','Cwuk ','Lin ','Cang ','Payk ','','Fen ','Ji ','','Sukumo ','Lyang ','Xian ', + 'Fu ','Lyang ','Chan ','Kayng ','Li ','Wel ','Lu ','Ju ','Qi ','Swu ','Bai ','Zhang ','Lin ','Cong ','Ceng ','Guo ', + 'Kouji ','San ','San ','Tang ','Bian ','Yu ','Myen ','Hou ','Xu ','Zong ','Ho ','Jian ','Zan ','Ci ','Li ','Xie ', + 'Fu ','Ni ','Bei ','Gu ','Xiu ','Ko ','Tang ','Kwu ','Sukumo ','Co ','Cang ','Tang ','Mi ','Sam ','Pwun ','Co ', + 'Kang ','Jiang ','Mo ','San ','Can ','Na ','Xi ','Lyang ','Jiang ','Kuai ','Bo ','Huan ','','Zong ','Xian ','Na ', + 'Tan ','Nie ','Lye ','Zuo ','Cek ','Nie ','Co ','Lan ','Sa ','Si ','Kyu ','Kyey ','Gong ','Zheng ','Kyu ','You ', + ], + 'x7d':[ + 'Ki ','Cha ','Cwu ','Swun ','Yak ','Hong ','Wu ','Hul ','Hwan ','Ren ','Mwun ','Mwun ','Qiu ','Nap ','Zi ','Tou ', + 'Nyu ','Fou ','Jie ','Se ','Swun ','Pi ','Yin ','Sa ','Koyng ','Ci ','Kup ','Pwun ','Wun ','Ren ','Dan ','Jin ', + 'So ','Pang ','Sayk ','Cui ','Jiu ','Zha ','Ha ','Jin ','Fu ','Zhi ','Ci ','Ca ','Cwu ','Hong ','Chal ','Lwu ', + 'Sey ','Pwul ','Sel ','Sin ','Bei ','Ce ','Qu ','Ling ','Zhu ','So ','Kam ','Yang ','Fu ','Tuo ','Zhen ','Dai ', + 'Chu ','Shi ','Cong ','Hyen ','Co ','Kyeng ','Pan ','Ju ','Mo ','Swul ','Zui ','Kou ','Kyeng ','Im ','Heng ','Xie ', + 'Kyel ','Zhu ','Chou ','Gua ','Bai ','Cel ','Kwang ','Hu ','Ci ','Hwan ','Geng ','Co ','Hyel ','Ku ','Kyo ','Quan ', + 'Gai ','Lak ','Hyen ','Pyeng ','Xian ','Fu ','Kup ','Tong ','Yung ','Co ','In ','Lei ','Xie ','Quan ','Se ','Gai ', + 'Cil ','Thong ','Sa ','Kang ','Xiang ','Hui ','Cel ','Zhi ','Jian ','Kyen ','Chi ','Mian ','Zhen ','Lu ','Cheng ','Kwu ', + 'Shu ','Bang ','Tong ','Cho ','Wan ','Qin ','Kyeng ','Xiu ','Ti ','Xiu ','Xie ','Hong ','Xi ','Fu ','Ceng ','Yu ', + 'Dui ','Kun ','Fu ','Kyeng ','Hu ','Zhi ','Yan ','Jiong ','Pong ','Kyey ','Sok ','Kase ','Cong ','Lin ','Duo ','Li ', + 'Lok ','Liang ','Cwu ','Kwen ','Shao ','Ki ','Ki ','Cwun ','Qi ','Wen ','Qian ','Sen ','Swu ','Yu ','Kyey ','Tao ', + 'Kwan ','Kang ','Mang ','Pwung ','Chel ','Chay ','Guo ','Cui ','Lyun ','Liu ','Ki ','Than ','Bei ','Cak ','Lung ','Myen ', + 'Qi ','Qie ','Tan ','Zong ','Kon ','Zou ','Yi ','Chi ','Xing ','Liang ','Kin ','Pi ','Yu ','Min ','Yu ','Chong ', + 'Fan ','Lok ','Se ','Ying ','Zhang ','Kasuri ','Se ','Sang ','Ham ','Ke ','Sen ','Ruan ','Myen ','Cip ','Tan ','Zhong ', + 'Chey ','Min ','Miao ','Yen ','Xie ','Bao ','Si ','Qiu ','Phyen ','Wan ','Geng ','Cong ','Myen ','Wei ','Fu ','Wi ', + 'Yu ','Gou ','Myo ','Xie ','Lyen ','Zong ','Phyen ','Yun ','Yin ','Cey ','Gua ','Chi ','On ','Cheng ','Chan ','Dai ', + ], + 'x7e':[ + 'Xia ','Yen ','Chong ','Xu ','Jou ','Odoshi ','Geng ','Sen ','Yeng ','Cin ','Ayk ','Chwu ','Ni ','Bang ','Gu ','Pan ', + 'Chwu ','Kyem ','Cuo ','Quan ','Shuang ','On ','Xia ','Choy ','Kyey ','Rong ','Tao ','Pak ','Yun ','Cin ','Ho ','Yo ', + 'Kok ','Cay ','Tung ','Hyen ','Su ','Zhen ','Cong ','Tao ','Kou ','Cai ','Bi ','Pong ','Cu ','Li ','Chwuk ','Yen ', + 'Xi ','Cong ','Lyu ','Kyen ','Kyen ','Man ','Zhi ','Lwu ','Mo ','Phyo ','Lian ','Mi ','Xuan ','Chong ','Cek ','Shan ', + 'Sui ','Pen ','Shuai ','Pwung ','Yey ','So ','Mwu ','Yo ','Kang ','Hun ','Sem ','Kyey ','Zung ','Swu ','Ran ','Xuan ', + 'Sey ','Qiao ','Cung ','Zuo ','Cik ','Sen ','San ','Lin ','Yu ','Pen ','Lyo ','Chuo ','Zun ','Jian ','Yo ','Chan ', + 'Rui ','Swu ','Kwey ','Hua ','Chan ','Xi ','Kang ','Un ','Da ','Sung ','Hoy ','Kyey ','Se ','Kyen ','Jiang ','Hyen ', + 'Co ','Cong ','Jie ','Jiao ','Bo ','Chan ','Ek ','Nao ','Sui ','Yek ','Shai ','Xu ','Kyey ','Pin ','Kyen ','Lan ', + 'Pu ','Hwun ','Chan ','Qi ','Peng ','Li ','Mo ','Loy ','Hil ','Chan ','Kwang ','You ','Sok ','Lyu ','Xian ','Cen ', + 'Kou ','Lu ','Chan ','Yeng ','Cay ','Xiang ','Sem ','Zui ','Chan ','Luo ','Xi ','To ','Lam ','Lei ','Lian ','Si ', + 'Jiu ','Yu ','Hong ','Zhou ','Xian ','He ','Yue ','Ji ','Wan ','Kuang ','Ji ','Ren ','Wei ','Yun ','Koyng ','Chun ', + 'Pi ','Sha ','Gang ','Na ','Ren ','Zong ','Lun ','Fen ','Zhi ','Wen ','Fang ','Ce ','Yin ','Niu ','Shu ','Xian ', + 'Gan ','Xie ','Fu ','Lian ','Zu ','Shen ','Xi ','Zhi ','Zhong ','Zhou ','Ban ','Fu ','Zhuo ','Shao ','Yi ','Jing ', + 'Dai ','Bang ','Rong ','Jie ','Ku ','Rao ','Die ','Heng ','Hui ','Gei ','Xuan ','Jiang ','Luo ','Jue ','Jiao ','Tong ', + 'Geng ','Xiao ','Juan ','Xiu ','Xi ','Sui ','Tao ','Ji ','Ti ','Ji ','Xu ','Ling ','Ying ','Xu ','Qi ','Fei ', + 'Chuo ','Zhang ','Gun ','Sheng ','Wei ','Mian ','Shou ','Beng ','Chou ','Tao ','Liu ','Quan ','Zong ','Zhan ','Wan ','Lu ', + ], + 'x7f':[ + 'Zhui ','Zi ','Ke ','Xiang ','Jian ','Mian ','Lan ','Ti ','Miao ','Qi ','On ','Hui ','Si ','Duo ','Duan ','Bian ', + 'Sen ','Gou ','Zhui ','Huan ','Di ','Lu ','Bian ','Min ','Yuan ','Jin ','Fu ','Ru ','Zhen ','Feng ','Shuai ','Gao ', + 'Chan ','Li ','Yi ','Jian ','Bin ','Piao ','Man ','Lei ','Ying ','Suo ','Mou ','Sao ','Xie ','Liao ','Shan ','Zeng ', + 'Jiang ','Qian ','Zao ','Huan ','Jiao ','Zuan ','Pwu ','Sa ','Hang ','Fou ','Kyel ','Fou ','Ketsu ','Bo ','Pyeng ','Hang ', + 'Diu6','Gang ','Ying ','Ayng ','Kyeng ','Ha ','Guan ','Cwun ','Tan ','Cang ','Qi ','Ong ','Ayng ','Loy ','Tam ','Lu ', + 'Kwan ','Wang ','Wang ','Gang ','Mang ','Han ','','Luo ','Pwu ','Mi ','Fa ','Gu ','Zhu ','Ce ','Mao ','Ko ', + 'Min ','Kang ','Ba ','Kway ','Ti ','Juan ','Pwu ','Lin ','Em ','Zhao ','Coy ','Kway ','Zhuo ','Yu ','Chi ','An ', + 'Pel ','Nan ','Se ','Si ','Pi ','May ','Liu ','Pha ','Pel ','Li ','Chao ','Wei ','Phil ','Kyey ','Cung ','Tong ', + 'Liu ','Ji ','Kyen ','Mi ','Zhao ','La ','Pi ','Ki ','Ki ','Luan ','Yang ','Mi ','Kang ','Ta ','Mi ','Yang ', + 'You ','You ','Fen ','Ba ','Ko ','Yang ','Ko ','Kang ','Cang ','Gao ','Lyeng ','Yi ','Zhu ','Ce ','Swu ','Qian ', + 'Yi ','Sen ','Rong ','Qun ','Kwun ','Qiang ','Huan ','Suo ','Sen ','Uy ','You ','Kang ','Xian ','Yu ','Geng ','Kal ', + 'Tang ','Yuan ','Huy ','Fan ','Shan ','Fen ','Cen ','Lian ','Li ','Kayng ','Nou ','Qiang ','Chan ','Wu ','Gong ','Yi ', + 'Chong ','Ong ','Fen ','Hong ','Chi ','Si ','Cui ','Fu ','Xia ','Pen ','Ik ','La ','Ik ','Pi ','Lyeng ','Liu ', + 'Zhi ','Qu ','Sup ','Xie ','Sang ','Hup ','Hup ','Qi ','Qiao ','Hui ','Hwi ','So ','Se ','Hong ','Jiang ','Cek ', + 'Chwi ','Pi ','Tao ','Sap ','Si ','Zhu ','Cen ','Xuan ','Shi ','Phyen ','Zong ','Wan ','Hwi ','Hou ','Hayk ','He ', + 'Han ','Ko ','Piao ','Yey ','Lian ','Qu ','','Lin ','Pen ','Kyo ','Ko ','Pen ','Ik ','Hui ','Hyen ','Dao ', + ], + 'x80':[ + 'Yo ','Lo ','','Ko ','Mo ','Ca ','Ki ','Kwu ','Kwu ','Kwu ','Die ','Die ','I ','Shua ','Ruan ','Er ', + 'Nay ','Tan ','Loy ','Ting ','Ca ','Kyeng ','Cho ','Mo ','Wun ','Pha ','Pi ','Chi ','Si ','Chu ','Ka ','Ju ', + 'He ','Se ','Lao ','Lun ','Ji ','Tang ','Wu ','Lou ','Nwu ','Jiang ','Pang ','Ze ','Lwu ','Ki ','Lao ','Huo ', + 'Wu ','Mo ','Huai ','I ','Zhe ','Ting ','Ya ','Da ','Song ','Qin ','Yun ','Chi ','Dan ','Tham ','Hong ','Kyeng ', + 'Zhi ','','Nie ','Tam ','Zhen ','Che ','Lyeng ','Zheng ','You ','Wa ','Lyo ','Long ','Zhi ','Ning ','Tiao ','Er ', + 'Ya ','Die ','Kwal ','','Lian ','Ho ','Seng ','Lie ','Ping ','Jing ','Chwi ','Bi ','Di ','Guo ','Mwun ','Xu ', + 'Ping ','Cong ','Shikato ','','Ting ','Yu ','Cong ','Kui ','Ren ','Kui ','Cong ','Lyen ','Weng ','Kui ','Lyen ','Lyen ', + 'Chong ','O ','Seng ','Yong ','Cheng ','Oy ','Sep ','Cik ','Dan ','Ning ','qie ','Ji ','Cheng ','Cheng ','Long ','Yul ', + 'Yu ','Zhao ','Si ','Su ','I ','Swuk ','Sa ','Co ','Zhao ','Yuk ','Yi ','Luk ','Ki ','Qiu ','Ken ','Cao ', + 'Ge ','Di ','Huan ','Hwang ','Yi ','Ren ','Cho ','Ru ','Cwu ','Yuan ','Twu ','Hang ','Rong ','Kan ','Cha ','Wo ', + 'Chang ','Ko ','Ci ','Han ','Fu ','Pi ','Pwun ','Pei ','Pang ','Kyen ','Pang ','Swun ','You ','Nwul ','Hang ','Kung ', + 'Ran ','Koyng ','Yuk ','Wen ','Hyo ','Ki ','Pi ','Qian ','Xi ','Xi ','Phyey ','Ken ','Jing ','Tai ','Shen ','Zhong ', + 'Zhang ','Xie ','Shen ','Wi ','Cwu ','Die ','Tan ','Fei ','Ba ','Bo ','Kwu ','Tian ','Pay ','Gua ','Thay ','Zi ', + 'Ku ','Zhi ','Ni ','Ping ','Zi ','Pwu ','Pan ','Zhen ','Xian ','Co ','Pay ','Kap ','Sheng ','Zhi ','Pho ','Mu ', + 'Ke ','Ho ','Ke ','Yi ','Yun ','Se ','Yang ','Long ','Dong ','Ka ','Lu ','Jing ','Nu ','Yan ','Pang ','Kwa ', + 'Yi ','Kwang ','Hai ','Ge ','Tong ','Zhi ','Xiao ','Hyung ','Hyung ','Er ','E ','Xing ','Pyen ','Nung ','Ca ','', + ], + 'x81':[ + 'Cheng ','Tiao ','Ci ','Cui ','Mei ','Hyep ','Chwi ','Hyep ','Mayk ','Mayk ','Chek ','Kyou ','Nin ','Kuai ','Sa ','Zang ', + 'Qi ','Nao ','Mi ','Nong ','Luan ','Wan ','Pal ','Wen ','Wan ','Qiu ','Kak ','Kyeng ','Rou ','Heng ','Cuo ','Lie ', + 'Shan ','Ting ','Mei ','Swun ','Sin ','Qian ','Te ','Choy ','Cu ','Swu ','Xin ','Thal ','Pao ','Cheng ','Nei ','Pho ', + 'Twu ','Thal ','Niao ','Noy ','Pi ','Ko ','Gua ','Li ','Lian ','Chang ','Swu ','Jie ','Liang ','Zhou ','Pi ','Biao ', + 'Lun ','Pyen ','Guo ','Kui ','Chui ','Dan ','Cen ','Nei ','Jing ','Jie ','Sek ','Ayk ','Yan ','Ren ','Sin ','Chuo ', + 'Pwu ','Pwu ','Ke ','Pi ','Kang ','Wan ','Dong ','Pi ','Guo ','Zong ','Ding ','Wu ','Mei ','Ruan ','Zhuan ','Cil ', + 'Cwu ','Gua ','Ou ','Di ','Am ','Seng ','Noy ','Yu ','Chuan ','Nan ','Yun ','Cong ','Rou ','Ak ','Sai ','Tu ', + 'Yo ','Ken ','Wei ','Jiao ','Yu ','Jia ','Tan ','Phik ','Cang ','Pok ','Sen ','Ni ','Mian ','Wa ','Tung ','Thoy ', + 'Pang ','Qian ','Lye ','Ol ','Swu ','Tang ','So ','Zhui ','Kyek ','Yi ','Pak ','Lyo ','Ji ','Pi ','Xie ','Ko ', + 'Lu ','Bin ','','Chang ','Lu ','Guo ','Pang ','Chuai ','Phyo ','Jiang ','Pwu ','Tang ','Mak ','Sul ','Cen ','Lu ', + 'Kyo ','Ying ','Lu ','Cil ','Tara ','Chun ','Lian ','Tong ','Phayng ','Ni ','Zha ','Liao ','Cui ','Gui ','Xiao ','Teng ', + 'Pen ','Zhi ','Jiao ','Sen ','Mwu ','Chwey ','Run ','Xiang ','Swu ','Pwun ','Ung ','Dan ','Zhua ','Tam ','Hoy ','Nong ', + 'Twun ','Lian ','Pi ','Yong ','Jue ','Chu ','Ek ','Juan ','La ','Lian ','Co ','Tun ','Gu ','Cey ','Cui ','Pin ', + 'Xun ','No ','Huo ','Cang ','Xian ','Biao ','Xing ','Kuan ','Lap ','Yen ','Lye ','Huo ','Zang ','La ','Qu ','Cang ', + 'Lyen ','Ni ','Zang ','Sin ','Qian ','Wa ','Guang ','Cang ','Lim ','Guang ','Ca ','Jiao ','El ','Chwi ','Ji ','Gao ', + 'Chou ','Mian ','Nie ','Ci ','Chi ','Ge ','Chen ','Die ','Zhi ','Xiu ','Tay ','Cin ','Kwu ','Xian ','Yu ','Cha ', + ], + 'x82':[ + 'Yao ','Ye ','Yong ','Sek ','Sek ','Kwu ','Yu ','Ye ','Hung ','Ju ','Kwu ','Xin ','Sel ','Sa ','Sha ','Jiu ', + 'Ci ','Tan ','Se ','Shi ','Tian ','Dan ','Pho ','Pu ','Kwan ','Hua ','Tan ','Chen ','Swun ','Xia ','Mwu ','Cwu ', + 'Dao ','Kang ','Shan ','Yi ','','Pa ','Tai ','Fan ','Ban ','Chuan ','Hang ','Pang ','Pan ','Que ','Ro ','Zhong ', + 'Jian ','Cang ','Ling ','Chwuk ','Ze ','Tha ','Pak ','Hyen ','Ka ','Sen ','Xia ','Lu ','Hong ','Pang ','Xi ','', + 'Pwu ','Zao ','Feng ','Li ','Shao ','Ye ','Lang ','Ceng ','','Wei ','Bo ','Meng ','Nian ','Ke ','Huang ','Shou ', + 'Zong ','Phyen ','Mao ','Die ','Dou6','Bang ','Cha ','Yi ','So ','Chang ','Co ','Lou ','Dai ','Sori ','Yao ','Tong ', + 'Tou ','Dang ','Tan ','Lu ','Uy ','Jie ','Ham ','Huo ','Mong ','Qi ','Lo ','Lo ','Chan ','Shuang ','Kan ','Lyang ', + 'Jian ','Kan ','Sayk ','Yan ','Pwul ','Ping ','Yem ','Yem ','Cho ','','Yi ','Le ','Ting ','Qiu ','Ay ','Nai ', + 'Tiao ','Jiao ','Jie ','Peng ','Wan ','Yi ','Chai ','Mian ','Mi ','Gan ','Chen ','Wu ','Yu ','Cak ','Kwung ','Tu ', + 'Xia ','Qi ','Mang ','Zi ','Hwey ','Sui ','Zhi ','Xiang ','Pi ','Pwu ','Twun ','Wei ','Wu ','Ci ','Qi ','Sam ', + 'Wen ','Kem ','In ','Pwu ','Kou ','Kay ','Ho ','Se ','Kup ','Kum ','Ki ','Wen ','Pwun ','Pha ','Yey ','Sim ', + 'Ki ','Hwa ','Hua ','Pang ','Wu ','Jue ','Gou ','Ci ','Wun ','Kun ','Ao ','Chwu ','Mo ','A ','Pi ','Ing ', + 'Hang ','Cong ','Yin ','You ','Bian ','Yey ','Susa ','Wei ','Li ','Pi ','E ','Xian ','Chang ','Cang ','Meng ','Su ', + 'Yi ','Wen ','Yem ','Lyeng ','Thay ','Cho ','Di ','Myo ','Qiong ','Li ','Yong ','Ka ','Mok ','Pei ','Pho ','Kwu ', + 'Min ','I ','Yi ','Ke ','Pi ','Yak ','Ko ','Ce ','Ni ','Bo ','Bing ','Cem ','Qiu ','Yao ','Xian ','Pwun ', + 'Hong ','Yeng ','Zha ','Tong ','Ce ','Die ','Nie ','Gan ','Hu ','Phyeng ','May ','Pwu ','Sheng ','Ko ','Phil ','Mi ', + ], + 'x83':[ + 'Pwul ','Cwul ','Mwu ','Pem ','Ka ','Mo ','Mao ','Ba ','Ca ','Mal ','Zi ','Di ','Chi ','Ji ','Jing ','Long ', + '','Niao ','','Xue ','Ying ','Qiong ','Ge ','Myeng ','Li ','Rong ','Yin ','Kan ','Chen ','Chay ','Chen ','Yu ', + 'Xiu ','Zi ','Lie ','O ','Ji ','Gui ','Ce ','Chong ','Ca ','Gou ','Kwang ','Mang ','Si ','Jiao ','Jiao ','Pok ', + 'Yu ','Swu ','Ca ','Kang ','Hoy ','In ','Ta ','Fa ','Yong ','Ye ','Chong ','Mang ','Tong ','Zhong ','','Zhu ', + 'Swun ','Huan ','Kua ','Cen ','Gai ','Da ','Hyeng ','Hayng ','Chuan ','Cho ','Hyeng ','Er ','An ','Shou ','Chi ','Im ', + 'Chen ','Cey ','Hwang ','Ping ','Li ','Jin ','Lao ','Shu ','Cang ','Da ','Jia ','Rao ','Bi ','Ze ','Qiao ','Hui ', + 'Qi ','Dang ','','Rong ','Hun ','Ying ','Luo ','Ying ','Xun ','Jin ','Sun ','Yin ','Mai ','Hong ','Zhou ','Yao ', + 'Du ','Wei ','Chu ','Twu ','Fu ','Ren ','Yin ','Ha ','Bi ','Bu ','Yun ','Cek ','Tu ','Sui ','Sui ','Cheng ', + 'Chen ','Wu ','Bie ','Xi ','Geng ','Li ','Fu ','Zhu ','Mo ','Li ','Cang ','Ji ','Duo ','Qiu ','Sa ','Suo ', + 'Chen ','Feng ','Ke ','May ','Meng ','Xing ','Kyeng ','Che ','Sin ','Jun ','Yen ','Ceng ','Diao ','Cwa ','Kwan ','Ham ', + 'Yu ','Cuo ','Hyep ','Wang ','Chen ','Niu ','Shao ','Xian ','Lang ','Pwu ','A ','Mak ','Wen ','Jie ','Nan ','Mu ', + 'Kan ','Lay ','Lian ','Shi ','Wo ','To ','Lian ','Huo ','You ','Ying ','Ying ','Nuc ','Chun ','Mang ','Mang ','Ca ', + 'Wan ','Cheng ','Cek ','Qu ','Dong ','Kwan ','Zou ','Gu ','La ','Lok ','Kwuk ','Mi ','Kyun ','Nie ','Kun ','He ', + 'Pu ','Chi ','Gao ','Kwa ','Pok ','Lun ','Chang ','Chou ','Swung ','Chui ','Zhan ','Men ','Chay ','Ba ','Li ','To ', + 'Pha ','Ham ','Bao ','Qin ','Juan ','Xi ','Qin ','Di ','Jie ','Po ','Dang ','Kun ','Zhao ','Tai ','Geng ','Hwa ', + 'Ko ','Lung ','Pi ','Jin ','Am ','Wang ','Pong ','Zhou ','Yan ','Ce ','Jian ','Lin ','Tan ','Swu ','Tian ','Dao ', + ], + 'x84':[ + 'Hu ','Qi ','He ','Chwey ','To ','Chwun ','Pi ','Cang ','Huan ','Fei ','Lay ','Che ','Mayng ','Phyeng ','Wi ','Dan ', + 'Sha ','Huan ','Yan ','Yi ','Tiao ','Qi ','Wan ','Ce ','Nai ','Kutabireru ','Tuo ','Jiu ','Tie ','Luo ','','', + 'Meng ','','Yaji ','','Ying ','Ying ','Ying ','Xiao ','Sa ','Chwu ','Ke ','Xiang ','Man ','Yu ','Yu ','Fu ', + 'Lian ','Hwen ','Yuan ','Nan ','Ze ','Wa ','Chun ','Xiao ','Yu ','Phyen ','Mao ','An ','Ak ','Lak ','Ying ','Huo ', + 'Gua ','Jiang ','Mian ','Zuo ','Zuo ','Ju ','Po ','Rou ','Xi ','Yep ','Am ','Qu ','Jian ','Fu ','Lu ','Jing ', + 'Pen ','Phwung ','Hong ','Hong ','Hou ','Yan ','Tu ','Ce ','Zi ','Xiang ','Sim ','Kal ','Jie ','Jing ','Mi ','Huang ', + 'Shen ','Pho ','Gai ','Tong ','Zhou ','Qian ','Wi ','Bo ','Wei ','Pha ','Kyey ','Ho ','Cang ','Ka ','Duan ','Yak ', + 'Jun ','Chong ','Quan ','Wi ','Zhen ','Kyu ','Ting ','Hwun ','Xi ','Shi ','Cup ','Lan ','Zong ','Yao ','Yuan ','Mei ', + 'Yun ','Shu ','Chey ','Zhuan ','Guan ','Sukumo ','Xue ','Chan ','Kai ','Kui ','','Cang ','Lou ','Wi ','Pai ','', + 'Swu ','Yin ','Shi ','Chun ','Si ','Yun ','Zhen ','Lang ','Nu ','Mong ','He ','Que ','San ','Yuan ','Li ','Kwu ', + 'Xi ','Pang ','Chu ','Xu ','Tu ','Liu ','Wo ','Zhen ','Chen ','Zu ','Po ','Cuo ','Yuan ','Chwu ','Yu ','Koy ', + 'Pan ','Pu ','Pho ','Na ','Sak ','Xi ','Fen ','Yun ','Cung ','Kyem ','Cil ','Yak ','Chang ','En ','Mi ','Ho ', + 'So ','Cin ','Myeng ','Huo ','Chwuk ','Liu ','Sek ','Gu ','Lang ','Yong ','Ong ','Kay ','Cuo ','Si ','Tang ','Luo ', + 'Yok ','Sa ','Xian ','Pay ','Yao ','Gui ','Pi ','Zong ','Gun ','Za ','Swu ','Ce ','Hai ','Lan ','','Ji ', + 'Li ','Can ','Lang ','Yu ','','Ying ','Mo ','Diao ','Tiao ','Mao ','Tong ','Zhu ','Pong ','Am ','Lyen ','Chong ', + 'Xi ','Phyeng ','Qiu ','Jin ','Swun ','Jie ','Wei ','Tui ','Cao ','Yu ','Yi ','Ji ','Lyo ','Phil ','Lu ','Swuk ', + ], + 'x85':[ + 'Pwu ','Zhang ','Luo ','Jiang ','Man ','Yan ','Lung ','Ji ','Piao ','Gun ','Han ','Di ','Su ','Lu ','She ','Shang ', + 'Di ','Myel ','Xun ','Man ','Pok ','Chey ','Cuo ','Ca ','Sam ','Xuan ','Wul ','Hu ','Ao ','Mi ','Lwu ','Cwu ', + 'Zhong ','Chay ','Po ','Cang ','Mi ','Chong ','Co ','Hui ','Jun ','Yin ','Cem ','Yan ','So ','Um ','Kui ','Cin ', + 'Hu ','Sha ','Kou ','Qian ','Ma ','Cang ','Sonoko ','Qiang ','Dou ','Lian ','Lin ','Kou ','Ai ','Phyey ','Li ','Wi ', + 'Ji ','Tam ','Sheng ','Pen ','Meng ','Ou ','Chen ','Dian ','Xun ','Cho ','Yey ','Yey ','Lei ','Yu ','Kyo ','Chu ', + 'Hua ','Jian ','Mai ','Wun ','Bao ','Yu ','Ke ','Lu ','Yo ','Hyey ','E ','Teng ','Fei ','Jue ','Chey ','Fa ', + 'Ru ','Pwun ','Kui ','Swun ','Yu ','Ya ','Xu ','Fu ','Kwel ','Thang ','Mwu ','Tong ','Si ','So ','Xi ','Long ', + 'On ','','Qi ','Jian ','Yun ','Sun ','Ling ','Yu ','Xia ','Yong ','Cup ','Hong ','Si ','Nong ','Loy ','Xuan ', + 'On ','Yu ','Xi ','Hao ','Pak ','Hao ','Ay ','Mi ','Hui ','Yey ','Kyey ','Ci ','Hyang ','Luan ','Mie ','Uy ', + 'Leng ','Kang ','Can ','Shen ','Cang ','Lian ','Ke ','Wen ','Da ','Chi ','Tang ','Sel ','Pyek ','Tam ','Sun ','Lian ', + 'Fan ','Ding ','Jie ','Gu ','Hay ','Chok ','Chen ','Kao ','Hwung ','Sal ','Sin ','Hwun ','Yak ','Hai ','Sou ','Se ', + 'Hwun ','Dui ','Pin ','Wei ','Neng ','Chou ','Mai ','Ru ','Piao ','Tai ','Cey ','Zao ','Chen ','Zhen ','Er ','Ni ', + 'Ying ','Ko ','Cong ','Xiao ','Qi ','Fa ','Jian ','Xu ','Kui ','Ca ','Bian ','Diao ','Mi ','Lam ','Sin ','Cang ', + 'Myo ','Qiong ','Qie ','Xian ','','Wu ','Xian ','Su ','Lu ','Yi ','Xu ','Xie ','Lye ','Yey ','La ','Lei ', + 'Xiao ','Di ','Zhi ','Bei ','Tung ','Yak ','Mo ','Huan ','Biao ','Pen ','Swu ','Tan ','Tui ','Qiong ','Qiao ','Wei ', + 'Liu ','Hui ','','Gao ','On ','','Li ','Ce ','Chu ','Ay ','Lin ','Co ','Xuan ','Chin ','Lai ','Kwak ', + ], + 'x86':[ + 'Thak ','Wu ','Yey ','Rui ','Ki ','Heng ','Lo ','So ','Tui ','Mang ','On ','Pin ','Yu ','Xun ','Ji ','Jiong ', + 'Xian ','Mo ','Hagi ','Su ','Jiong ','','El ','Pyek ','Yang ','Yi ','Sen ','Yu ','Ju ','Lian ','Lian ','Yin ', + 'Qiang ','Ying ','Long ','Tong ','Wei ','Yue ','Ling ','Ke ','Yao ','Pen ','Mi ','Lan ','Kui ','Lan ','Ji ','Thang ', + 'Katsura ','Lei ','Lei ','Hua ','Feng ','Zhi ','Wei ','Kui ','Zhan ','Huai ','Li ','Ji ','Mi ','Lei ','Huai ','La ', + 'Ji ','Ki ','Lu ','Jian ','San ','','Lei ','Quan ','Xiao ','Yi ','Luan ','Men ','Bie ','Hu ','Ho ','Lu ', + 'Hak ','Lu ','Si ','Hyo ','Ken ','Che ','Hu ','Xu ','Cuo ','Fu ','He ','He ','Lo ','Hu ','Wu ','Ho ', + 'Jiao ','Ju ','Guo ','Bao ','Yan ','Zhan ','Zhan ','Hyu ','Ban ','Xi ','Shu ','Hwey ','Kyu ','Diao ','Ji ','Kyu ', + 'Cheng ','Sul ','','Di ','Zhe ','She ','Yu ','Gan ','Ca ','Hong ','Hwey ','Meng ','Ge ','Sui ','Xia ','Chai ', + 'Shi ','Yi ','Ma ','Xiang ','Fang ','E ','Pa ','Chi ','Qian ','Wen ','Mwun ','Yey ','Pang ','Pi ','Yue ','Yue ', + 'Jun ','Qi ','Tong ','In ','Qi ','Chen ','Yuan ','Jue ','Hui ','Qin ','Qi ','Zhong ','Ya ','Ci ','Mu ','Wang ', + 'Fen ','Fen ','Hang ','Kong ','Co ','Fu ','Ran ','Jie ','Pwu ','Chi ','Twu ','Piao ','Xian ','Ni ','Te ','Kwu ', + 'Yu ','Chayk ','Ping ','Chi ','Yu ','He ','Han ','Ju ','Li ','Fu ','Ran ','Zha ','Gou ','Pi ','Bo ','Xian ', + 'Cwu ','Diao ','Bie ','Bing ','Gu ','Cem ','Ce ','Sa ','Tie ','Lyeng ','Gu ','Tan ','Gu ','Hyeng ','Li ','Cheng ', + 'Qu ','Mou ','Ge ','Ci ','Hoy ','Hui ','Mang ','Fu ','Yang ','Wa ','Lie ','Cwu ','Yi ','Xian ','Hwal ','Kyo ', + 'Li ','Yi ','Ping ','Kil ','Hap ','She ','Yi ','Wang ','Mo ','Kong ','Qie ','Gui ','Kong ','Cil ','Man ','Ebi ', + 'Zhi ','Jia ','Rao ','Si ','Qi ','Xing ','Lie ','Qiu ','So ','Yong ','Jia ','Sey ','Che ','Bai ','A ','Han ', + ], + 'x87':[ + 'Chok ','Xuan ','Pong ','Sin ','Zhen ','Fu ','Hyen ','Zhe ','O ','Pwu ','Li ','Lang ','Bi ','Chu ','Yuan ','You ', + 'Jie ','Tan ','Yan ','Ting ','Dian ','Sey ','Hoy ','Gua ','Ci ','Song ','Pi ','Ju ','Mil ','Ki ','Qi ','Yu ', + 'Jun ','Sa ','Meng ','Qiang ','Si ','Sek ','Lun ','Li ','Cep ','Co ','Tao ','Kun ','Gan ','Han ','Yu ','Bang ', + 'Fei ','Pi ','Wei ','Dun ','Chek ','Yen ','Su ','Kwen ','Qian ','Rui ','Yey ','Cheng ','Wei ','Liang ','Guo ','Wen ', + 'Tong ','E ','Ban ','Di ','Wang ','Can ','Yang ','Ying ','Guo ','Sen ','','Lap ','Kwa ','Ji ','Kal ','Ting ', + 'Mai ','Xu ','Mian ','Yu ','Jie ','Sik ','Xuan ','Hwang ','Yan ','Phyen ','Rou ','Wei ','Fu ','Yuan ','Mei ','Wi ', + 'Pok ','Ruan ','Xie ','You ','Yu ','Mo ','Ha ','Ying ','Sul ','Chong ','Tang ','Zhu ','Zong ','Ti ','Pok ','Yuan ', + 'Hui ','Meng ','La ','Du ','Hwu ','Qiu ','Cep ','Li ','Wa ','Yun ','Ju ','Nan ','Lou ','Qun ','Rong ','Ying ', + 'Jiang ','','Lang ','Pang ','Si ','Xi ','Ci ','Xi ','Yuan ','Weng ','Lian ','Sou ','Pan ','Yung ','Rong ','Ji ', + 'Wu ','Qiu ','Han ','Qin ','Yi ','Bi ','Hua ','Tang ','Uy ','Du ','Nai ','He ','Hu ','Hui ','Ma ','Myeng ', + 'Yi ','Wen ','Hyeng ','Tung ','Yu ','Cang ','So ','Ebi ','Man ','','Shang ','Shi ','Cao ','Li ','Di ','Ao ', + 'Lu ','Wei ','Zhi ','Tang ','Cin ','Piao ','Qu ','Pi ','Yu ','Jian ','La ','Lwu ','Qin ','Cong ','Yin ','Jiang ', + 'Sol ','Wen ','Jiao ','Wan ','Chip ','Zhe ','Ma ','Ma ','Guo ','Liu ','Mo ','Sil ','Cong ','Li ','Man ','Xiao ', + 'Tou ','Zhang ','Mang ','Xiang ','Mo ','Zui ','Si ','Qiu ','Te ','Zhi ','Phayng ','Phayng ','Jiao ','Qu ','Bie ','Liao ', + 'Pan ','Gui ','Xi ','Ki ','Zhuan ','Huang ','Fei ','Lao ','Jue ','Jue ','Hui ','Yin ','Sen ','Jiao ','Shan ','Yo ', + 'Xiao ','Mou ','Chwung ','Xun ','Si ','','Cheng ','Tang ','Li ','Hay ','Shan ','Uy ','Jing ','Da ','Sem ','Qi ', + ], + 'x88':[ + 'Ci ','Xiang ','She ','La ','Qin ','Sung ','Chai ','Li ','Ze ','Xuan ','Lian ','Zhu ','Ze ','Kal ','Mang ','Xie ', + 'Qi ','Yeng ','Jian ','Meng ','Hao ','Yu ','Huo ','Zhuo ','Jie ','Bin ','He ','Mie ','Fan ','Lei ','Jie ','Lap ', + 'Mi ','Lye ','Cwun ','Lye ','Qiu ','Nie ','Lu ','Du ','Xiao ','Zhu ','Long ','Li ','Long ','Feng ','Ye ','Beng ', + 'Shang ','Ko ','Kyen ','Ying ','','Xi ','Cam ','Qu ','Quan ','Twu ','Can ','Man ','Jue ','Jie ','Zhu ','Zha ', + 'Hyel ','Huang ','Niu ','Pei ','Nyuk ','Hun ','Cwung ','Mo ','Er ','Ke ','Myel ','Xi ','Hayng ','Yen ','Kan ','Yuan ', + '','Ling ','Hyen ','Swul ','Xian ','Tong ','Long ','Ka ','Xian ','A ','Hu ','Wi ','Dao ','Chwung ','Wi ','Dao ', + 'Zhun ','Hyeng ','Kwu ','Uy ','Koromohen ','Bu ','Gan ','Yu ','Phyo ','Cha ','Yi ','Sam ','Chen ','Fu ','Kon ','Fen ', + 'Soy ','Jie ','Nap ','Zhong ','Dan ','Ri ','Zhong ','Chwung ','Xie ','Qi ','Xie ','Ran ','Zhi ','Im ','Kum ','Kum ', + 'Jun ','Wen ','Myey ','Chai ','Ao ','Niao ','Wi ','Ran ','Ka ','Tuo ','Ling ','Tay ','Bao ','Pho ','Yao ','Zuo ', + 'Bi ','Shao ','Tan ','Ju ','He ','Shu ','Swu ','Cin ','Yi ','Pa ','Bo ','Ce ','Wa ','Pwu ','Kon ','Zhi ', + 'Zhi ','Ran ','Pen ','Yi ','Mwu ','','Na ','Kou ','Xian ','Chan ','Ke ','Phi ','Gun ','Xi ','Ne ','Bo ', + 'Horo ','Pok ','Yi ','Chi ','Ko ','Ren ','Jiang ','Jia ','Cun ','Mo ','Jie ','Er ','Luo ','Ru ','Zhu ','Gui ', + 'In ','Cay ','Lyel ','Kamishimo ','Yuki ','Cang ','Dang ','Seot ','Kun ','Ken ','Nyo ','Shu ','Jia ','Kon ','Cheng ','Li ', + 'Juan ','Shen ','Pwu ','Ge ','Yey ','Yu ','Zhen ','Liu ','Kwu ','Kwun ','Ji ','Yi ','Po ','Cang ','Shui ','Sa ', + 'Qun ','Li ','Lian ','Lian ','Ku ','Jian ','Fou ','Chan ','Pi ','Gun ','Tao ','Yuan ','Ling ','Chi ','Chang ','Cwu ', + 'Duo ','Phyo ','Liang ','Sang ','Pay ','Pey ','Fei ','Yuan ','La ','Kwa ','Yan ','Du ','Xi ','Cey ','Ke ','Qi ', + ], + 'x89':[ + 'Ji ','Zhi ','Gua ','Ken ','Che ','Ti ','Ti ','Pok ','Chong ','Xie ','Phyen ','Die ','Kon ','Duan ','Xiu ','Xiu ', + 'Kal ','Yuan ','Pho ','Po ','Fu ','Yu ','Tuan ','Yan ','Wi ','Pey ','Ce ','Lu ','Ena ','Tan ','Yun ','Da ', + 'Gou ','Da ','Huai ','Rong ','Yuan ','Yo ','Nai ','Kyeng ','Suo ','Ban ','Thoy ','Chi ','Sang ','Niao ','Ying ','Jie ', + 'Ken ','Huai ','Ku ','Lian ','Bao ','Li ','Sup ','Shi ','Lwu ','Yi ','Chep ','Sel ','Xian ','Wei ','Biao ','Cao ', + 'Ji ','Kang ','Sen ','Bao ','Yang ','Chihaya ','Pu ','Jian ','Zhuan ','Jian ','Zui ','Ji ','Dan ','Cap ','Fan ','Bo ', + 'Xiang ','Xin ','Bie ','Rao ','Man ','Lan ','O ','Duo ','Koy ','Cao ','Sui ','Nong ','Chem ','Lian ','Pyek ','Kum ', + 'Tang ','Shu ','Tan ','Bi ','Lam ','Pu ','Yu ','Zhi ','','Shu ','Mal ','Shi ','Bai ','Hil ','Bo ','Chin ', + 'Lai ','Long ','Sup ','Xian ','Lan ','Zhe ','Dai ','Tasuki ','Zan ','Shi ','Jian ','Pan ','Yi ','Ran ','Ya ','Se ', + 'Xi ','Yo ','Feng ','Tam ','','Biao ','Pok ','Phay ','Hayk ','Ki ','Ji ','Kyen ','Kwan ','Bian ','Yan ','Kyu ', + 'Jue ','Pian ','Mao ','Myek ','Mi ','Mie ','Si ','Sa ','Cem ','Luo ','Kak ','Mi ','Tiao ','Lian ','Yao ','Zhi ', + 'Jun ','Kyek ','Shan ','Wei ','Xi ','Tian ','Yu ','Lam ','Ak ','To ','Chin ','Pang ','Ki ','Ming ','Ying ','Kwu ', + 'Qu ','Zhan ','Kun ','Kwan ','Deng ','Jian ','Luo ','Che ','Jian ','Wei ','Kak ','Qu ','Luo ','Lam ','Shen ','Cek ', + 'Kwan ','Jian ','Guan ','Yan ','Gui ','Mi ','Shi ','Zhan ','Lan ','Jue ','Ji ','Xi ','Di ','Tian ','Yu ','Gou ', + 'Jin ','Qu ','Kak ','Jiu ','Kun ','Cu ','Kyel ','Zhi ','Chao ','Ji ','Ko ','Dan ','Ca ','Ce ','Shang ','Hua ', + 'Quan ','Ge ','Chi ','Hay ','Gui ','Koyng ','Chok ','Jie ','Hun ','Qiu ','Xing ','Sok ','Ni ','Ji ','Lu ','Zhi ', + 'Zha ','Phil ','Xing ','Kok ','Sang ','Gong ','Chi ','Xue ','Chok ','Xi ','Yi ','Lu ','Jue ','Xi ','Yan ','Xi ', + ], + 'x8a':[ + 'En ','Gonben ','Ceng ','Pwu ','Qiu ','Qiu ','Jiao ','Koyng ','Kyey ','Pem ','Sin ','Diao ','Hong ','Cha ','Tho ','Xu ', + 'Al ','I ','Ren ','Hwun ','Un ','San ','Hul ','Thak ','Ki ','Xun ','Un ','Wa ','Fen ','A ','Yao ','Song ', + 'Shen ','Yin ','Hun ','Kyel ','Xiao ','Nwul ','Chen ','You ','Zhi ','Xiong ','Pang ','Xin ','Chao ','Sel ','Xian ','Sha ', + 'Tun ','He ','Yi ','Yek ','So ','Chi ','Ka ','Shen ','He ','Xu ','Cin ','Cwu ','Ceng ','Gou ','Ca ','Zi ', + 'Zhan ','Ko ','Fu ','Quan ','Die ','Ling ','Ce ','Yang ','Li ','Nao ','Pan ','Cwu ','Gan ','Yi ','Ke ','Ao ', + 'Sa ','I ','I ','Qu ','Co ','Phyeng ','Phi ','Hyeng ','Kwul ','Ba ','Da ','Ce ','Tao ','Zhu ','Sa ','Zhe ', + 'Yeng ','Hwu ','Swun ','Yey ','Huang ','He ','Si ','Cha ','Jiao ','Si ','Hen ','Tha ','Kwu ','Kwey ','Cen ','Hui ', + 'Hil ','Hwa ','Hay ','Sang ','Wei ','Sen ','Chou ','Tong ','Mi ','Chem ','Ming ','E ','Hoy ','Yan ','Xiong ','Kway ', + 'Er ','Beng ','Co ','Chi ','Loy ','Cwu ','Kwang ','Kwa ','Wu ','Yey ','Teng ','Ji ','Ci ','In ','Su ','Lang ', + 'E ','Kwang ','Huy ','Se ','Ting ','Than ','Bo ','Chan ','Yu ','Heng ','Cho ','Qin ','Shua ','An ','E ','Xiao ', + 'Seng ','Kyey ','Hyen ','Mwu ','O ','Ko ','Song ','Pho ','Hoy ','Jing ','Sel ','Zhen ','Sel ','Tok ','Yasashi ','Chang ', + 'Swu ','Jie ','Kwa ','Qu ','Cong ','Xiao ','Swu ','Wang ','Xuan ','Pi ','Chi ','Ta ','Uy ','Na ','Un ','Co ', + 'Pi ','Chuo ','Chem ','Chen ','Swun ','Ji ','Qi ','Tam ','Zhui ','Wi ','Ju ','Cheng ','Jian ','Cayng ','Ze ','Chwu ', + 'Qian ','Chak ','Lyang ','Jian ','Zhu ','Hao ','Lon ','Sim ','Biao ','Huai ','Pian ','Yu ','Chep ','Se ','Phyen ','Si ', + 'Hwen ','Si ','Wen ','Hua ','Ak ','Zhong ','Chey ','Hay ','Fu ','Pu ','Ceng ','Kan ','Qi ','Yu ','Ca ','Chuan ', + 'Si ','Hwi ','Yin ','Am ','Ham ','Nan ','Sim ','Phwung ','Cey ','Yang ','En ','Heng ','Hwen ','Ge ','Nak ','Qi ', + ], + 'x8b':[ + 'Mo ','Al ','Wi ','','Tung ','Zou ','Shan ','Ken ','Bo ','','Huang ','Huo ','Ka ','Ying ','Mi ','Xiao ', + 'Mil ','Hyey ','Qiang ','Chen ','Hak ','Ti ','So ','Pang ','Chi ','Kyem ','Ik ','Kang ','Wen ','Sa ','Xue ','Tao ', + 'Yo ','Yao ','','Wu ','Biao ','Cong ','Kyeng ','Li ','Mo ','Mo ','Shang ','Cek ','Lyu ','Cen ','Ze ','Jie ', + 'Lian ','Lou ','Can ','Kwu ','Guan ','Xi ','Zhuo ','O ','Ao ','Kun ','Zhe ','Yi ','Hu ','Jiang ','Man ','Chao ', + 'Han ','Hwa ','Chan ','Hwu ','Zeng ','Se ','Xi ','She ','Dui ','Cung ','Nao ','Lan ','Wa ','Ying ','Hyul ','Ki ', + 'Zun ','Jiao ','Bo ','Hui ','Sen ','Mu ','Cham ','Zha ','Sik ','Cho ','Tam ','Zen ','Po ','Sheng ','Xuan ','Co ', + 'Tan ','Dang ','Sui ','Qian ','Ji ','Jiao ','Kyeng ','Lian ','Nou ','Yi ','Ai ','Sem ','Pi ','Hui ','Hua ','Yek ', + 'Uy ','Sen ','Rang ','Nou ','Kyen ','Zhui ','Ta ','Ho ','Zhou ','Hao ','Ye ','Ying ','Jian ','Yey ','Jian ','Hyey ', + 'Tok ','Zhe ','Xuan ','Chan ','Lei ','Shen ','Wei ','Chan ','Li ','Yu ','Pyen ','Zhe ','Yen ','E ','Swu ','Wei ', + 'Swu ','Yao ','Cham ','Yang ','Yin ','Lan ','Cham ','Huo ','Zhe ','Hwan ','Chan ','Yi ','Tang ','Zhan ','En ','Du ', + 'Yan ','Ji ','Ding ','Fu ','Ren ','Ji ','Jie ','Hong ','Tao ','Rang ','Shan ','Qi ','Thak ','Xun ','Yi ','Xun ', + 'Ji ','Ren ','Jiang ','Hui ','Ou ','Ju ','Ya ','Ne ','Xu ','E ','Lun ','Xiong ','Song ','Feng ','She ','Fang ', + 'Jue ','Zheng ','Gu ','He ','Ping ','Zu ','Shi ','Xiong ','Zha ','Su ','Zhen ','Di ','Zou ','Ci ','Qu ','Zhao ', + 'Bi ','Yi ','Yi ','Kuang ','Lei ','Shi ','Gua ','Shi ','Jie ','Hui ','Cheng ','Zhu ','Shen ','Hua ','Dan ','Gou ', + 'Quan ','Gui ','Xun ','Yi ','Zheng ','Gai ','Xiang ','Cha ','Hun ','Xu ','Zhou ','Jie ','Wu ','Yu ','Qiao ','Wu ', + 'Gao ','You ','Hui ','Kuang ','Shuo ','Song ','Ai ','Qing ','Zhu ','Zou ','Nuo ','Du ','Zhuo ','Fei ','Ke ','Wei ', + ], + 'x8c':[ + 'Yu ','Shui ','Shen ','Diao ','Chan ','Liang ','Zhun ','Sui ','Tan ','Shen ','Yi ','Mou ','Chen ','Die ','Huang ','Jian ', + 'Xie ','Nue ','Ye ','Wei ','E ','Yu ','Xuan ','Chan ','Zi ','An ','Yan ','Di ','Mi ','Pian ','Se ','Mo ', + 'Dang ','Su ','Xie ','Yao ','Bang ','Shi ','Qian ','Mi ','Jin ','Man ','Zhe ','Jian ','Miu ','Tan ','Zen ','Qiao ', + 'Lan ','Pu ','Jue ','Yan ','Qian ','Zhan ','Chen ','Kok ','Qian ','Hong ','Xia ','Jue ','Hong ','Han ','Hong ','Kyey ', + 'Xi ','Hwal ','Liao ','Han ','Du ','Long ','Twu ','Kang ','Kay ','Si ','Lyey ','Deng ','Wan ','Bi ','Swu ','Xian ', + 'Phwung ','Zhi ','Zhi ','Yan ','Yan ','Si ','Chwuk ','Hui ','Tun ','Yi ','Ton ','Yi ','Jian ','Ba ','Hou ','E ', + 'Cu ','Sang ','Hwan ','Yen ','Ken ','Gai ','Qu ','Fu ','Huy ','Bin ','Ho ','Yey ','Ce ','Jia ','Fen ','Xi ', + 'Bo ','Wen ','Huan ','Pin ','Di ','Zong ','Fen ','Yi ','Chi ','Phyo ','Si ','An ','Pi ','Na ','Pi ','Gou ', + 'Na ','You ','Cho ','Mayk ','Si ','Hyu ','Huan ','Kun ','He ','He ','Mayk ','Han ','Mo ','Li ','Ni ','Bi ', + 'Yu ','Jia ','Tuan ','Myo ','Pi ','Xi ','E ','Ju ','Mayk ','Chu ','Tan ','Huan ','Jue ','Phay ','Ceng ','Yuan ', + 'Pwu ','Cay ','Kong ','Te ','Yi ','Hang ','Wan ','Pin ','Hwa ','Phan ','Tham ','Kwan ','Chayk ','Zhi ','Er ','Ce ', + 'Sey ','Bi ','Ca ','I ','Kwi ','Pian ','Phyem ','May ','Tay ','Sheng ','Hwang ','Pi ','Chep ','I ','Chi ','Mwu ', + 'Ha ','Pwun ','Loy ','Im ','Hoy ','Gai ','Pyen ','Ca ','Ka ','Xu ','Cek ','Jiao ','Gai ','Zang ','Jian ','Ying ', + 'Xun ','Cin ','She ','Pin ','Pin ','Qiu ','She ','Chuan ','Zang ','Cwu ','Loy ','Chan ','Sa ','Chen ','Sang ','Tian ', + 'Pay ','Kayng ','Hyen ','May ','Chen ','Sui ','Pwu ','Tan ','Cong ','Cong ','Cil ','Ji ','Cang ','To ','Jin ','Xiong ', + 'Shun ','Yun ','Bao ','Zai ','Loy ','Feng ','Cang ','Ji ','Sheng ','Ai ','Zhuan ','Pwu ','Kwu ','Say ','Sayk ','Liao ', + ], + 'x8d':[ + 'Wei ','Bai ','Chen ','Zhuan ','Ci ','Chwey ','Biao ','Yun ','Cung ','Tan ','Chan ','An ','','Sem ','Wan ','Yeng ', + 'Sin ','Gan ','Xian ','Cang ','Pi ','Du ','Sok ','Yan ','','Xuan ','Long ','Kong ','Cang ','Bei ','Zhen ','Fu ', + 'Yuan ','Gong ','Cai ','Ze ','Xian ','Bai ','Zhang ','Huo ','Zhi ','Fan ','Tan ','Pin ','Bian ','Gou ','Zhu ','Guan ', + 'Er ','Jian ','Bi ','Shi ','Tie ','Gui ','Kuang ','Dai ','Mao ','Fei ','He ','Yi ','Zei ','Zhi ','Jia ','Hui ', + 'Zi ','Ren ','Lu ','Zang ','Zi ','Gai ','Jin ','Qiu ','Zhen ','Lai ','She ','Fu ','Du ','Ji ','Shu ','Shang ', + 'Si ','Bi ','Cwu ','Geng ','Pei ','Tan ','Lai ','Feng ','Zhui ','Fu ','Zhuan ','Sai ','Ze ','Yan ','Zan ','Yun ', + 'Zeng ','Shan ','Ying ','Gan ','Cek ','Xi ','Sa ','Nan ','Xiong ','Xi ','Cheng ','Hyek ','Cheng ','Ca ','Xia ','Tang ', + 'Cwu ','Zou ','Li ','Kyu ','Pwu ','Zhao ','Kan ','Ki ','Shan ','Qiong ','Qin ','Xian ','Ci ','Jue ','Qin ','Chi ', + 'Ci ','Cin ','Chen ','Die ','Ju ','Cho ','Di ','Se ','Zhan ','Zhu ','Wel ','Qu ','Jie ','Chi ','Cwu ','Gua ', + 'Hyel ','Ca ','Tiao ','Duo ','Lie ','Gan ','Suo ','Cu ','Xi ','Co ','Su ','Yin ','Ju ','Jian ','Que ','Tang ', + 'Cho ','Cui ','Lu ','Chwi ','Dang ','Qiu ','Zi ','Ti ','Chwu ','Chi ','Huang ','Kyo ','Qiao ','Yao ','Zao ','Ti ', + '','Zan ','Chan ','Cok ','Pa ','Pak ','Ku ','Ke ','Dun ','Jue ','Pwu ','Chen ','Kyen ','Fang ','Ci ','Sap ', + 'Yue ','Pa ','Ki ','Yue ','Qiang ','Tuo ','Thay ','Yi ','Nian ','Ling ','Mei ','Pal ','Cil ','Ku ','Tha ','Ka ', + 'Ci ','Pao ','Qia ','Zhu ','Ju ','Cep ','Chek ','Pwu ','Pan ','Ju ','San ','Pha ','Ni ','Ke ','Li ','Kun ', + 'Yi ','Cek ','Dai ','Sen ','Kyo ','Duo ','Zhu ','Quan ','Kwa ','Zhuai ','Kwey ','Kong ','Kyu ','Xiang ','Chi ','Lo ', + 'Beng ','Chi ','Jia ','Co ','Cai ','Chen ','Ta ','Qiao ','Bi ','Xian ','Duo ','Ji ','Kwuk ','Ki ','Shu ','Tu ', + ], + 'x8e':[ + 'Chu ','Jing ','Nie ','Xiao ','Bo ','Chi ','Cwun ','Mou ','So ','Lyang ','Yong ','Jiao ','Chou ','Qiao ','Mau ','Tap ', + 'Chen ','Qi ','Wo ','Wei ','Thak ','Jie ','Ji ','Nie ','Ju ','Ju ','Lun ','Lu ','Leng ','Kwa ','Ke ','Ci ', + 'Wan ','Quan ','Ti ','Pwu ','Zu ','Qie ','Ji ','Cu ','Zong ','Chay ','Cong ','Peng ','Zhi ','Zheng ','Dian ','Zhi ', + 'Yu ','Thak ','Dun ','Chun ','Yong ','Cong ','Cey ','Zhe ','Chen ','Tan ','Jian ','Gua ','Tang ','Wu ','Fu ','Zu ', + 'Cep ','Phyen ','Yu ','Nuo ','Cey ','Cha ','Tui ','Ken ','To ','Cha ','Hyey ','Ta ','Chang ','Zhan ','Dian ','Cey ', + 'Ji ','Nie ','Man ','Liu ','Zhan ','Phil ','Chong ','Lu ','Liao ','Chwuk ','Tang ','Dai ','Chwuk ','Xi ','Kui ','Cek ', + 'Chek ','Qiang ','Di ','Man ','Cong ','Lian ','Beng ','Zao ','Nian ','Pyel ','Tui ','Ju ','Deng ','Chung ','Xian ','Pen ', + 'Cwu ','Zhong ','Cwun ','Bo ','Chwuk ','Zu ','Kwel ','Jue ','Lin ','Ta ','Kyo ','Qiao ','Pok ','Liao ','Dun ','Cuan ', + 'Kuang ','Co ','Ta ','Bi ','Bi ','Chok ','Ju ','Ce ','Qiao ','Ton ','Cwu ','Cey ','Wu ','Yak ','Nian ','Lin ', + 'Lyep ','Chek ','Lyek ','Ci ','Cen ','Chu ','Duan ','Wei ','Long ','Lin ','Sen ','Wei ','Zuan ','Lan ','Sep ','Rang ', + 'Xie ','Sep ','Ta ','Qu ','Jie ','Cuan ','Zuan ','Xi ','Kui ','Kwak ','Lin ','Sin ','Kwung ','Dan ','Segare ','Qu ', + 'Ti ','Tha ','Duo ','Kwung ','Lang ','Nerau ','Luo ','Ai ','Ji ','Ju ','Tang ','Utsuke ','','Yan ','Shitsuke ','Kang ', + 'Kwu ','Lou ','Lao ','Tuo ','Zhi ','Yagate ','Chey ','Dao ','Yagate ','Yu ','Cha ','Al ','Kwey ','Kwun ','Wei ','Yue ', + 'Xin ','Di ','Hen ','Fan ','Ren ','Shan ','Qiang ','Shu ','Tun ','Chen ','Dai ','E ','Na ','Qi ','Mao ','Yen ', + 'Ren ','Fan ','Cen ','Hong ','Hu ','Qu ','Huang ','Di ','Lyeng ','Dai ','Ao ','Cin ','Fan ','Kuang ','Ang ','Peng ', + 'Bei ','Gu ','Gu ','Pao ','Zhu ','Rong ','E ','Ba ','Chwuk ','Ci ','Cho ','Ka ','Il ','Kyeng ','Sik ','Pyeng ', + ], + 'x8f':[ + 'Er ','Qiong ','Ju ','Kyo ','Guang ','Lo ','Kai ','Cen ','Cwu ','Cay ','Zhi ','She ','Liang ','Yu ','Shao ','You ', + 'Huan ','Yun ','Chep ','Man ','Po ','Kyeng ','Zhou ','Ni ','Ling ','Zhe ','Zhan ','Lyang ','Chi ','Hwi ','Mang ','Chel ', + 'Guo ','Kan ','Yi ','Peng ','Qian ','Gun ','Lyen ','Pyeng ','Kwan ','Pay ','Lyun ','Pai ','Liang ','Ruan ','Rou ','Cip ', + 'Yang ','Xian ','Chuan ','Cwu ','Chun ','Ge ','You ','Hong ','Swu ','Pok ','Zi ','Pok ','Wen ','Ben ','Cen ','Ye ', + 'On ','Tao ','Kok ','Zhen ','Hal ','Wen ','Lok ','Jiu ','Chao ','Cen ','Wei ','Hun ','Sori ','Chel ','Kyo ','Zhan ', + 'Pu ','Lao ','Pwun ','Fan ','Lin ','Ge ','Se ','Kem ','Hwan ','Yi ','Ji ','Dui ','Er ','Ye ','Ham ','Koyng ', + 'Lei ','Pi ','Lyek ','Lyek ','Lo ','Lin ','Che ','Ya ','Gui ','Xuan ','Di ','Ren ','Zhuan ','E ','Lun ','Ruan ', + 'Hong ','Gu ','Ke ','Lu ','Zhou ','Zhi ','Yi ','Hu ','Zhen ','Li ','Yao ','Qing ','Shi ','Zai ','Zhi ','Jiao ', + 'Zhou ','Quan ','Lu ','Jiao ','Zhe ','Fu ','Liang ','Nian ','Bei ','Hui ','Gun ','Wang ','Liang ','Chuo ','Zi ','Cou ', + 'Fu ','Ji ','Wen ','Shu ','Pei ','Yuan ','Xia ','Zhan ','Lu ','Che ','Lin ','Sin ','Ko ','Ci ','Sa ','Phi ', + 'Zui ','Bian ','Lal ','Lal ','Ci ','Xue ','Phan ','Bian ','Pyen ','Bian ','','Bian ','Ban ','Sa ','Pyen ','Pyen ', + 'Cin ','Yok ','Nong ','Nong ','Zhen ','Chuo ','Chuo ','Suberu ','Reng ','Pyen ','Pyen ','Sip ','Ip ','Liao ','Da ','Chen ', + 'Kan ','Qian ','O ','O ','Hul ','Sin ','Yi ','Guo ','Mai ','Qi ','Za ','Wang ','tu ','Twun ','Yeng ','Ti ', + 'Yun ','Kun ','Hang ','A ','Pan ','O ','Da ','E ','Huan ','Zhe ','Totemo ','Jin ','Yuan ','Wei ','Lian ','Chi ', + 'Che ','Ni ','Cho ','Zhi ','I ','Hyeng ','Ka ','Chen ','Thay ','I ','Cek ','Pak ','Wang ','Cil ','Ze ','Tao ', + 'Swul ','Tuo ','Kep ','Jing ','Hoy ','Tong ','You ','Mi ','Pyeng ','Cek ','Nay ','Yi ','Jie ','Chwu ','Lie ','Xun ', + ], + 'x90':[ + 'Thoy ','Song ','Kwal ','To ','Pang ','Hwu ','Yek ','Ci ','Hyeng ','Xuan ','Xun ','Pho ','Yu ','So ','Qiu ','Thwu ', + 'Chwuk ','Kwu ','Di ','Di ','To ','Kyeng ','Cek ','Twu ','Yi ','Ce ','Thong ','Guang ','Wu ','Se ','Lyeng ','Sok ', + 'Co ','Cwun ','Pong ','Lyen ','Suo ','Hoy ','Li ','Sako ','Lai ','Ben ','Cuo ','Jue ','Beng ','Huan ','Chey ','Lu ', + 'Yu ','Cwu ','Cin ','Yu ','Thak ','Kyu ','Wi ','Ti ','Il ','Da ','Wen ','Luo ','Phip ','Nuo ','Yu ','Dang ', + 'Sui ','Twun ','Swu ','Yan ','Chuan ','Ci ','Ti ','Wu ','Shi ','Ceng ','Yu ','Wun ','E ','Phyen ','Kwa ','Al ', + 'Ha ','Hwang ','Cwu ','To ','Tal ','Wi ','Appare ','Yi ','Kwu ','Yo ','Chu ','Lyu ','Son ','Tap ','Chey ','Ci ', + 'Wen ','So ','Ta ','Kyen ','','Yao ','Guan ','Zhang ','O ','Cek ','Ce ','Chi ','Sok ','Co ','Cha ','Twun ', + 'Di ','Lou ','Ci ','Cuo ','Lin ','Cwun ','Yo ','Chen ','Sen ','Yu ','Yu ','Wu ','Lyo ','Ke ','Shi ','Phi ', + 'Yo ','May ','Hay ','Swu ','Hwan ','Cen ','Teng ','I ','Mak ','Bian ','Pyen ','La ','Lye ','Yuan ','Yao ','La ', + 'Li ','Up ','Ting ','Deng ','Qi ','Ong ','Shan ','Han ','Yu ','Mang ','Ru ','Kong ','','Kuang ','Fu ','Kang ', + 'Pin ','Pang ','Hyeng ','Na ','','Shen ','Pang ','Yuan ','Chon ','Huo ','Sa ','Bang ','Wu ','Ju ','You ','Han ', + 'Thay ','Kwu ','Bi ','Pi ','Pyeng ','So ','Phay ','Wa ','Ce ','Zou ','Ye ','Lin ','Kuang ','Kyu ','Cwu ','Shi ', + 'Ku ','Wuk ','Gai ','Hap ','Kuk ','Cil ','Ji ','Xun ','Hou ','Xing ','Kyo ','Xi ','Gui ','Nuo ','Lang ','Jia ', + 'Kuai ','Zheng ','Rou ','Yun ','Yan ','Cheng ','Dou ','Chi ','Lu ','Fu ','Wu ','Fu ','Ko ','Hak ','Lang ','Kyep ', + 'Geng ','Kwun ','Yeng ','Bo ','Kuk ','Bei ','Li ','Yun ','Pwu ','Xiao ','Che ','Pi ','Qing ','Kwak ','','Tam ', + 'Zou ','Ping ','Lai ','Ni ','Chim ','Wu ','Bu ','Hyang ','Dan ','Ju ','Yong ','Qiao ','Yi ','To ','Yan ','Mei ', + ], + 'x91':[ + 'Ruo ','Bei ','Ak ','Yu ','Juan ','Yu ','Yun ','Hou ','Kui ','Hyang ','Xiang ','Sou ','Tang ','Ming ','Xi ','Ru ', + 'Chu ','Zi ','Chwu ','Ju ','O ','Hyang ','Yun ','Hao ','Yong ','Pi ','Mo ','Chao ','Fu ','Liao ','Un ','Zhuan ', + 'Hu ','Qiao ','En ','Cang ','Man ','Qiao ','Xu ','Tung ','Bi ','Xin ','Bi ','Ceng ','Wei ','Ceng ','Mao ','Shan ', + 'Lin ','Pha ','Tan ','Meng ','Ep ','Cao ','Hoy ','Feng ','Meng ','Zou ','Kwang ','Lian ','Zan ','Cen ','You ','Qi ', + 'Yan ','Chan ','Zan ','Ling ','Huan ','Xi ','Feng ','Zan ','Lyek ','Yu ','Ceng ','Chwu ','Cak ','Pay ','Cwu ','Yi ', + 'Hang ','Yu ','Cwu ','Yan ','Zui ','Mao ','Tham ','Hwu ','Tou ','Zhen ','Fen ','Sakenomoto ','','Yun ','Tai ','Tian ', + 'Qia ','Tuo ','Cho ','Kem ','Ko ','So ','Pal ','Chou ','Zai ','Myeng ','Lak ','Chuo ','Swu ','You ','Tong ','Zhi ', + 'Xian ','Cang ','Ceng ','Yin ','To ','Hyo ','May ','Hok ','San ','Loy ','Pu ','Zui ','Hai ','Yan ','Xi ','Niang ', + 'Wei ','Lu ','Lan ','Em ','Tao ','Pei ','Zhan ','Swun ','Tan ','Chwi ','Chuo ','Cho ','Kun ','Cey ','Mian ','Du ', + 'Ho ','Xu ','Seng ','Tan ','Jiu ','Chun ','On ','Pal ','Ke ','Sou ','Mi ','Quan ','Chwu ','Cuo ','On ','Yong ', + 'Ang ','Zha ','Hay ','Tang ','Cang ','Piao ','Shan ','Yu ','Li ','Zao ','Lyo ','Uy ','Cang ','Bu ','Cho ','Hyey ', + 'Tan ','Pal ','Nong ','Yi ','Lyey ','Kyak ','Jiao ','Yi ','Niang ','Ru ','Xun ','Chou ','Yan ','Ling ','Mi ','Mi ', + 'Yang ','Hun ','Jiao ','Si ','Mi ','Yem ','Pyen ','Chay ','Sek ','Yu ','Shi ','Sek ','Li ','Cwung ','Ya ','Lyang ', + 'Li ','Kim ','','Ga ','Yi ','Liao ','Dao ','Soy ','Ceng ','Po ','Qiu ','He ','Pwu ','Chim ','Zhi ','Ba ', + 'Luan ','Fu ','Nai ','Co ','Sam ','Qiao ','Kwu ','Chen ','Zi ','Fan ','Wu ','Hua ','Han ','Kong ','Qi ','Mang ', + 'Ri ','Di ','Si ','Xi ','Yi ','Chay ','Shi ','Tu ','Xi ','Nu ','Qian ','Kyuu ','Jian ','Pi ','Ye ','Kun ', + ], + 'x92':[ + 'Ba ','Fang ','Chen ','Xing ','Dou ','Yue ','Yan ','Pwu ','Pi ','Na ','Xin ','E ','Jue ','Twun ','Gou ','Yin ', + 'Kem ','Phan ','Sap ','Ren ','Cho ','Niu ','Fen ','Yun ','Ji ','Qin ','Pi ','Guo ','Hoyng ','Yin ','Kyun ','Co ', + 'Yi ','Zhong ','Nie ','Gai ','Ri ','Huo ','Tai ','Kang ','Habaki ','Ro ','Ngaak ','','Duo ','Zi ','Ni ','Tu ', + 'Shi ','Min ','Gu ','Ke ','Lyeng ','Pyeng ','Yi ','Ko ','Pal ','Pi ','Ok ','Si ','Zuo ','Bu ','You ','Cen ', + 'Kap ','Cin ','Shi ','Shi ','Chel ','Ke ','Chan ','Shi ','Shi ','Hyen ','Zhao ','Pho ','He ','Bi ','Sayng ','Se ', + 'Sek ','Pak ','Cwu ','Chi ','Za ','Po ','Tong ','Kyem ','Fu ','Zhai ','Liu ','Yen ','Fu ','Li ','Wel ','Pi ', + 'Yang ','Ban ','Pal ','Jie ','Kwu ','Swul ','Ceng ','Mu ','Ni ','Nie ','Di ','Jia ','Mu ','Dan ','Shen ','Yi ', + 'Si ','Kwang ','Ka ','Bei ','Jian ','Tong ','Xing ','Hong ','Kyo ','Chi ','Er ','Ge ','Pyeng ','Shi ','Mo ','Ha ', + 'Un ','Jun ','Zhou ','Chong ','Shang ','Tong ','Mo ','Lei ','Ji ','Yu ','Xu ','Im ','Zun ','Zhi ','Kong ','Shan ', + 'Chi ','Sen ','Xing ','Cen ','Pi ','Chel ','Swu ','Hou ','Myeng ','Kwa ','Co ','Sem ','Ham ','Xiu ','Jun ','Cha ', + 'Lao ','Ji ','Pi ','Ru ','Mi ','Yi ','Yin ','Guang ','An ','Diu ','You ','Se ','Kao ','Cen ','Luan ','Kasugai ', + 'Ai ','Diao ','Han ','Yey ','Shi ','Keng ','Kwu ','So ','Zhe ','Swu ','Zang ','Ti ','Cuo ','Gua ','Gong ','Zhong ', + 'Dou ','Lu ','Mei ','Lang ','Wan ','Xin ','Yun ','Bei ','Ok ','Su ','Yu ','Chan ','Ceng ','Bo ','Han ','Hyep ', + 'Hong ','Cen ','Pong ','Chan ','Wan ','Zhi ','Si ','Hyen ','Wu ','Wu ','Tiao ','Gong ','Zhuo ','Lue ','Xing ','Chim ', + 'Shen ','Han ','Lue ','Xie ','Se ','Ceng ','Ju ','Xian ','Tie ','Mang ','Pho ','Li ','Pan ','Yey ','Cheng ','Gao ', + 'Li ','Te ','Pyeng ','Zhu ','','Tu ','Liu ','Zui ','Ke ','Cheng ','Wen ','Jian ','Kang ','Co ','Tao ','Chang ', + ], + 'x93':[ + 'Lun ','Guo ','Ling ','Bei ','Lok ','Li ','Cheng ','Pou ','Juan ','Min ','Zui ','Peng ','An ','Pi ','Xian ','A ', + 'Chwu ','Lei ','A ','Kong ','Ta ','Kon ','Du ','Wei ','Chwu ','Chi ','Cayng ','Ben ','Nie ','Cong ','Swun ','Tam ', + 'Ceng ','Ki ','Cen ','Chel ','Ki ','Yu ','Kum ','Kwan ','Myo ','Chang ','Cen ','Sek ','Tong ','Tao ','Ko ','Chak ', + 'Shu ','Zhen ','Lok ','Meng ','Lu ','Hua ','Biao ','Ga ','Lai ','Ken ','Kazari ','Bu ','Nai ','Wan ','Zan ','', + 'De ','Xian ','','Huo ','Liang ','','Men ','Kai ','Yeng ','Si ','Lyen ','Kwa ','Xian ','To ','Tu ','Wei ', + 'Cong ','Fu ','Rou ','Ji ','Ak ','Rou ','Chen ','Cey ','Zha ','Hong ','Yang ','Tan ','Ha ','Wu ','Keng ','Xing ', + 'Koyng ','Wei ','Fu ','Zhao ','Sap ','Qie ','She ','Hong ','Kui ','Tian ','Mwu ','Cho ','Cho ','Hou ','Yu ','Cong ', + 'Hwan ','Ye ','Min ','Jian ','Duan ','Ken ','Si ','Kui ','Hu ','Xuan ','Zhe ','Jie ','Chim ','Bian ','Cong ','Zi ', + 'Xiu ','Ye ','Mei ','Pai ','Ai ','Jie ','','Mei ','Chuo ','Ta ','Pang ','Xia ','Kyem ','Suo ','Xi ','Lyu ', + 'Zu ','Ye ','Nou ','Weng ','Yong ','Tang ','Sway ','Cayng ','Ge ','Shuo ','Chwu ','Pak ','Pan ','Sa ','Bi ','Sang ', + 'Gang ','Ca ','Wu ','Hyeng ','Hwang ','Tiao ','Liu ','Kay ','Sun ','Sha ','Sou ','Wan ','Ho ','Cin ','Cin ','Luo ', + 'Il ','Yuan ','Tang ','Nie ','Xi ','Jia ','Ge ','Ma ','Juan ','Kasugai ','Habaki ','Suo ','','','','Na ', + 'Lu ','Sway ','Ou ','Cok ','Tuan ','Xiu ','Guan ','Sen ','Lyen ','Shou ','O ','Man ','Mak ','Luo ','Bi ','Wei ', + 'Liu ','Cek ','Qiao ','Cong ','Yi ','Lu ','O ','Kayng ','Cang ','Cui ','Qi ','Chang ','Tang ','Man ','Yong ','San ', + 'Feng ','Kyeng ','Phyo ','Shu ','Lwu ','Xiu ','Chong ','Long ','Cham ','Jian ','Cao ','Li ','Xia ','Xi ','Kang ','', + 'Beng ','','','Zheng ','Lu ','Hua ','Cip ','Pu ','Hui ','Qiang ','Po ','Lin ','Suo ','Swu ','San ','Cheng ', + ], + 'x94':[ + 'Kui ','Si ','Liu ','Nyo ','Hoyng ','Pie ','Sui ','Fan ','Qiao ','Quan ','Yang ','Tang ','Xiang ','Jue ','Jiao ','Cwun ', + 'Lyo ','Jie ','Lao ','Tay ','Sim ','Zan ','Ji ','Jian ','Cong ','Tung ','Ya ','Ying ','Dui ','Jue ','Nou ','Ti ', + 'Pu ','Tie ','','','Ding ','Sen ','Kai ','Jian ','Fei ','Sui ','Lo ','Cen ','Hui ','Yu ','Lian ','Zhuo ', + 'Qiao ','Qian ','Zhuo ','Lei ','Bi ','Chel ','Hwan ','Ye ','Thak ','Guo ','Tang ','Ju ','Fen ','Da ','Bei ','Yi ', + 'Ai ','Zong ','Hwun ','Diao ','Cwu ','Heng ','Zhui ','Ji ','Nie ','Ta ','Hwak ','Qing ','Pin ','Ying ','Kui ','Ning ', + 'Xu ','Kam ','Kam ','Yari ','Cha ','Cil ','Mie ','Li ','Lei ','Ji ','Zuan ','Kwang ','Shang ','Peng ','Lap ','Du ', + 'Sak ','Chuo ','Lye ','Phyo ','Bao ','Lu ','','Thoa ','Long ','E ','Lo ','Xin ','Jian ','Lan ','Bo ','Jian ', + 'Yak ','Cham ','Yang ','Jian ','Xi ','Kwan ','Cang ','Sep ','Lei ','Cuan ','Qu ','Pan ','La ','Chan ','Lan ','Chak ', + 'Nie ','Jue ','Tang ','Shu ','Lan ','Jin ','Qiu ','Yi ','Zhen ','Ding ','Zhao ','Po ','Diao ','Tu ','Qian ','Chuan ', + 'Shan ','Sap ','Fan ','Diao ','Men ','Nu ','Xi ','Chai ','Xing ','Gai ','Bu ','Tai ','Ju ','Dun ','Chao ','Zhong ', + 'Na ','Bei ','Gang ','Ban ','Qian ','Yao ','Qin ','Jun ','Wu ','Gou ','Kang ','Fang ','Huo ','Dou ','Niu ','Ba ', + 'Yu ','Qian ','Zheng ','Qian ','Gu ','Bo ','E ','Po ','Bu ','Ba ','Yue ','Zuan ','Mu ','Dan ','Jia ','Dian ', + 'You ','Tie ','Bo ','Ling ','Shuo ','Qian ','Liu ','Bao ','Shi ','Xuan ','She ','Bi ','Ni ','Pi ','Duo ','Xing ', + 'Kao ','Lao ','Er ','Mang ','Ya ','You ','Cheng ','Jia ','Ye ','Nao ','Zhi ','Dang ','Tong ','Lu ','Diao ','Yin ', + 'Kai ','Zha ','Zhu ','Xian ','Ting ','Diu ','Xian ','Hua ','Quan ','Sha ','Jia ','Yao ','Ge ','Ming ','Zheng ','Se ', + 'Jiao ','Yi ','Chan ','Chong ','Tang ','An ','Yin ','Ru ','Zhu ','Lao ','Pu ','Wu ','Lai ','Te ','Lian ','Keng ', + ], + 'x95':[ + 'Xiao ','Suo ','Li ','Zheng ','Chu ','Guo ','Gao ','Tie ','Xiu ','Cuo ','Lue ','Feng ','Xin ','Liu ','Kai ','Jian ', + 'Rui ','Ti ','Lang ','Qian ','Ju ','A ','Qiang ','Duo ','Tian ','Cuo ','Mao ','Ben ','Ki ','De ','Kua ','Kun ', + 'Chang ','Xi ','Gu ','Luo ','Chui ','Zhui ','Jin ','Zhi ','Xian ','Juan ','Huo ','Pou ','Tan ','Ding ','Jian ','Ju ', + 'Meng ','Zi ','Qie ','Yeng ','Kai ','Qiang ','Song ','E ','Cha ','Qiao ','Cong ','Duan ','Sou ','Koyng ','Huan ','Ai ', + 'Du ','Mei ','Lou ','Zi ','Fei ','Mei ','Mo ','Zhen ','Bo ','Ge ','Nie ','Tang ','Juan ','Nie ','Na ','Liu ', + 'Hao ','Bang ','Yi ','Jia ','Bin ','Rong ','Biao ','Tang ','Man ','Luo ','Beng ','Yong ','Jing ','Di ','Zu ','Xuan ', + 'Liu ','Tan ','Jue ','Liao ','Pu ','Lu ','Dui ','Lan ','Pu ','Cuan ','Qiang ','Deng ','Huo ','Lei ','Huan ','Zhuo ', + 'Lian ','Yi ','Cha ','Biao ','La ','Chan ','Xiang ','Cang ','Chang ','Jiu ','Ao ','Die ','Qu ','Liao ','Mi ','Chang ', + 'Mwun ','Ma ','Shuan ','Sem ','Huo ','Men ','Yan ','Bi ','Han ','Phyey ','San ','Kay ','Kang ','Beng ','Koyng ','Lyun ', + 'San ','Han ','Han ','Kan ','Min ','Xia ','Yuru ','Dou ','Kap ','Nao ','','Peng ','Xia ','Ling ','Bian ','Pi ', + 'Run ','He ','Kwan ','Kak ','Hap ','Pel ','Chwuk ','Hong ','Kyu ','Min ','Se ','Kon ','Lang ','Lye ','Ting ','Sha ', + 'Ju ','Yel ','Yel ','Chan ','Qu ','Lin ','Cheng ','Shai ','Kun ','Em ','Wen ','Yem ','An ','Hon ','Yek ','Wen ', + 'Xiang ','Bao ','Xiang ','Kyek ','Yao ','Wen ','Ban ','Am ','Wi ','Yin ','Hwal ','Kyel ','Lan ','To ','','Phwung ', + 'Tian ','Nie ','Ta ','Kay ','Hap ','Kwel ','Chum ','Kwan ','Dou ','Qi ','Kyu ','Tang ','Kwan ','Piao ','Ham ','Xi ', + 'Kwey ','Chen ','Pyek ','Dang ','Huan ','Tal ','Wen ','','Men ','Shuan ','Shan ','Yan ','Han ','Bi ','Wen ','Chuang ', + 'Run ','Wei ','Xian ','Hong ','Jian ','Min ','Kang ','Men ','Zha ','Nao ','Gui ','Wen ','Ta ','Min ','Lu ','Kai ', + ], + 'x96':[ + 'Fa ','Ge ','He ','Kun ','Jiu ','Yue ','Lang ','Du ','Yu ','Yan ','Chang ','Xi ','Wen ','Hun ','Yan ','E ', + 'Chan ','Lan ','Qu ','Hui ','Kuo ','Que ','Ge ','Tian ','Ta ','Que ','Kan ','Huan ','Pwu ','Pwu ','Le ','Dui ', + 'Xin ','Chen ','Ol ','Yi ','Chi ','Yin ','Yang ','Dou ','Ayk ','Sheng ','Phan ','Pei ','Keng ','Yun ','Wan ','Ci ', + 'Pi ','Ceng ','Pang ','Yang ','Yin ','Zhen ','Jie ','Cheng ','E ','Qu ','Di ','Co ','Co ','Cem ','Ling ','A ', + 'Tha ','Tuo ','Phi ','Bing ','Pwu ','Ji ','Lu ','Long ','Chen ','Xing ','Duo ','Lwu ','Mayk ','Kang ','Shu ','La ', + 'Han ','Er ','Gui ','Yu ','Hay ','Shan ','Xun ','Qiao ','Hyeng ','Chun ','Fu ','Phyey ','Hyep ','Sem ','Sung ','Chek ', + 'Pu ','Twu ','Wen ','Cin ','Cey ','Ham ','Tou ','Nie ','Yun ','Xian ','Pay ','Pei ','Chwu ','Yi ','Dui ','Lun ', + 'Um ','Ju ','Swu ','Cin ','Pi ','Lung ','To ','Ham ','Lyuk ','','Hem ','Yin ','Ce ','Yang ','Reng ','Shan ', + 'Chong ','Yan ','Yin ','Yu ','Cey ','Wu ','Lyung ','Wei ','Oy ','El ','Tay ','Swu ','An ','Hwang ','Kyey ','Swu ', + 'Un ','Ki ','Yan ','Hui ','Kyek ','Wun ','Wu ','Oy ','Ay ','Kuk ','Tang ','Cey ','Cang ','Dao ','Ao ','Xi ', + 'Un ','','Rao ','Lin ','Thoy ','Deng ','Pi ','Swu ','Swu ','O ','Hem ','Fen ','Ni ','Er ','Ji ','Dao ', + 'Sup ','Un ','E ','Hyu ','Long ','Xi ','I ','Lyey ','Lyey ','Chwu ','He ','Chek ','Cwun ','Jun ','Nan ','Yi ', + 'Cak ','An ','Qin ','Ya ','Wung ','A ','Cip ','Ko ','Huan ','Chi ','Gou ','Cwun ','Ca ','Ong ','Ce ','Chu ', + 'Hu ','Cap ','Lak ','Yu ','Chou ','Co ','Swu ','Han ','Huo ','Ssang ','Kwan ','Chwu ','Cap ','Ong ','Kyey ','Xi ', + 'Chou ','Liu ','Li ','Nan ','Xue ','Za ','Ji ','Ji ','Wu ','Wu ','Sel ','Na ','Fou ','Se ','Mu ','Mwun ', + 'Pwun ','Pang ','Wun ','Li ','Li ','Ang ','Lyeng ','Loy ','An ','Pak ','Mong ','Cen ','Dang ','Xing ','Wu ','Zhao ', + ], + 'x97':[ + 'Swu ','Ji ','Mu ','Chen ','So ','Sap ','Ceng ','Cin ','Phay ','May ','Ling ','Qi ','Cwu ','Kwak ','Sap ','Pi ', + 'Weng ','Cem ','Yin ','Yey ','Cwu ','Tun ','Lim ','','Dong ','Yeng ','Wu ','Ling ','Sang ','Ling ','Ha ','Hong ', + 'Yin ','Mo ','Mai ','Wun ','Liu ','Meng ','Pin ','Mwu ','Wei ','Huo ','Um ','Xi ','Yi ','Ai ','Dan ','Deng ', + 'Sen ','Yu ','Lo ','Long ','Dai ','Ji ','Pang ','Yang ','Phay ','Pyek ','Wei ','','Xi ','Cey ','May ','Meng ', + 'Meng ','Lei ','Lyek ','Huo ','Ay ','Fei ','Chey ','Long ','Lyeng ','Ay ','Feng ','Li ','Po ','','He ','He ', + 'Bing ','Cheng ','Cheng ','Jing ','Tian ','Zhen ','Ceng ','Cheng ','Qing ','Jing ','Ceng ','Cen ','Ceng ','Chen ','Pi ','Fei ', + 'Ko ','Mi ','Myen ','Mian ','Pao ','Ye ','Cen ','Hui ','Yep ','Hyek ','Ding ','Cha ','Jian ','In ','Di ','Du ', + 'Wu ','Ren ','Qin ','Kun ','Hwa ','Nyu ','Pha ','In ','Sa ','Na ','Mal ','Zu ','Tal ','Ban ','Yi ','Yao ', + 'To ','Phi ','Jia ','Hong ','Pho ','Ang ','Tomo ','Yin ','Jia ','Tao ','Ji ','Hyey ','An ','An ','Hen ','Kong ', + 'Kohaze ','Da ','Qiao ','Ting ','Man ','Ying ','Sui ','Tiao ','Cho ','Xuan ','Kong ','Beng ','Ta ','Zhang ','Bing ','Kuo ', + 'Kwuk ','La ','Xie ','Yu ','Bang ','Yi ','Chwu ','Qiu ','Kal ','Xiao ','Mu ','Kwu ','Ken ','Phyen ','Cey ','Jian ', + 'On ','To ','Kwu ','Ta ','Pi ','Xie ','Pan ','Ge ','Phil ','Kwak ','Tou ','Lou ','Gui ','Kyo ','Xue ','Ji ', + 'Jian ','Kang ','Chan ','Tal ','Huo ','Xian ','Chen ','Du ','Wa ','Chen ','Lan ','Wi ','Ren ','Pwul ','Mei ','Juan ', + 'Kap ','Wei ','Qiao ','Han ','Chang ','','Rou ','Xun ','She ','Wi ','Ge ','Bei ','To ','Kwu ','On ','', + 'Phil ','Wi ','Hui ','Du ','Wa ','Du ','Wei ','Ren ','Fu ','Han ','Wei ','Yun ','Tao ','Kwu ','Kwu ','Xian ', + 'Xie ','Sem ','Cey ','Um ','Za ','Wun ','So ','Le ','Peng ','Heng ','Yeng ','Wun ','Peng ','Yin ','Yin ','Hyang ', + ], + 'x98':[ + 'Ho ','Hyel ','Ceng ','Kyeng ','Kui ','Hang ','Swun ','Han ','Swu ','I ','Wuk ','Gu ','Song ','Kyu ','Ki ','Hang ', + 'Yey ','Wan ','Pan ','Ton ','Di ','Dan ','Pan ','Pha ','Lyeng ','Ce ','Kyeng ','Lei ','He ','Qiao ','Al ','E ', + 'Wei ','Hil ','Gua ','Sin ','I ','Shen ','Hay ','Dui ','Pian ','Ping ','Lei ','Pwu ','Hyep ','Twu ','Hoy ','Kui ', + 'Hyep ','Le ','Ting ','Cheng ','Ying ','Jun ','Hu ','Am ','Kyeng ','Thoy ','Tui ','Pin ','Loy ','Thoy ','Zi ','Ca ', + 'Chui ','Ding ','Loy ','Yan ','Han ','Jian ','Kwa ','Chwi ','Kyeng ','Qin ','Yi ','Si ','Cey ','Ayk ','Ak ','An ', + 'Hun ','Kan ','Ong ','Cen ','An ','Hyen ','Sin ','Yi ','Wen ','Sang ','Cen ','Cen ','Jiang ','Ku ','Lyu ','Liao ', + 'Piao ','Yi ','Man ','Qi ','Rao ','Ho ','Cho ','Ko ','Xun ','Qian ','Hui ','Cen ','Ru ','Hong ','Bin ','Hyen ', + 'Pin ','Lo ','Lan ','Sep ','Kwan ','Ye ','Ding ','Qing ','Han ','Xiang ','Shun ','Xu ','Xu ','Wan ','Gu ','Dun ', + 'Qi ','Ban ','Song ','Hang ','Yu ','Lu ','Ling ','Po ','Jing ','Jie ','Jia ','Tian ','Han ','Ying ','Jiong ','Hai ', + 'Yi ','Pin ','Hui ','Tui ','Han ','Ying ','Ying ','Ke ','Ti ','Yong ','E ','Zhuan ','Yan ','E ','Nie ','Man ', + 'Dian ','Sang ','Hao ','Lei ','Zhan ','Ru ','Pin ','Quan ','Phwung ','Biao ','Oroshi ','Fu ','Xia ','Cem ','Biao ','Sap ', + 'Ba ','Thay ','Lyel ','Kwal ','Xuan ','Shao ','Kwu ','Bi ','Si ','Wei ','Yang ','Yao ','Swu ','Kai ','Sao ','Pem ', + 'Liu ','Xi ','Lyo ','Piao ','Phyo ','Liu ','Phyo ','Phyo ','Biao ','Lyo ','','Sil ','Feng ','Biao ','Feng ','Yang ', + 'Zhan ','Biao ','Sa ','Ju ','Si ','Sou ','Yao ','Liu ','Piao ','Biao ','Biao ','Pi ','Pen ','Fei ','Fei ','Sik ', + 'Shi ','Son ','Ki ','Ceng ','Si ','Tuo ','Cen ','Son ','Xiang ','Tun ','Im ','E ','Juan ','Chik ','Um ','Pan ', + 'Fan ','Son ','Um ','Zhu ','I ','Zhai ','Bi ','Jie ','Tao ','Liu ','Ci ','Chel ','Sa ','Pho ','Sik ','Duo ', + ], + 'x99':[ + 'Hai ','Im ','Tian ','Kyo ','Jia ','Pyeng ','Yao ','Tong ','Ci ','Hyang ','Yang ','Yang ','I ','Yan ','Le ','Yi ', + 'Chan ','Bo ','Noy ','A ','Pho ','Cwun ','Dou ','Su ','Ye ','Shi ','Hyo ','Hun ','Guo ','Shi ','Cen ','Zhui ', + 'Pyeng ','Xian ','Bu ','Ye ','Tan ','Fei ','Cang ','Wi ','Kwan ','E ','Nan ','Hun ','Ho ','Huang ','Chel ','Hui ', + 'Cen ','Hwu ','He ','Tang ','Fen ','Wei ','Gu ','Cha ','Song ','Tang ','Bo ','Gao ','Huy ','Kwey ','Liu ','Sou ', + 'Tao ','Ye ','On ','Mo ','Tang ','Man ','Bi ','Yu ','Swu ','Kun ','Can ','Kwey ','Chan ','Sen ','Chi ','Dan ', + 'Uy ','Ki ','Yo ','Cheng ','Ong ','To ','Hui ','Hyang ','Zhan ','Fen ','Hai ','Meng ','Yem ','Mo ','Cham ','Xiang ', + 'Luo ','Zuan ','Nang ','Shi ','Ceng ','Ji ','Tuo ','Xing ','Tun ','Xi ','Ren ','Yu ','Chi ','Fan ','Yin ','Jian ', + 'Shi ','Bao ','Si ','Duo ','Yi ','Er ','Rao ','Xiang ','Jia ','Le ','Jiao ','Yi ','Bing ','Bo ','Dou ','E ', + 'Yu ','Nei ','Jun ','Guo ','Hun ','Xian ','Guan ','Cha ','Kui ','Gu ','Sou ','Chan ','Ye ','Mo ','Bo ','Liu ', + 'Xiu ','Jin ','Man ','Can ','Zhuan ','Nang ','Swu ','Kyu ','Koyk ','Hyang ','Fen ','Ba ','Ni ','Phil ','Bo ','Tu ', + 'Han ','Fei ','Jian ','Am ','Ai ','Pok ','Xian ','Wen ','Hyeng ','Fen ','Bin ','Xing ','Ma ','E ','Phwung ','Han ', + 'Cek ','Tha ','Tuo ','Chi ','Swun ','Zhu ','Zhi ','Pei ','Xin ','Il ','Sa ','Yin ','Wen ','Zhi ','Dan ','Lu ', + 'You ','Pak ','Bao ','Kuai ','Tha ','Yek ','Kwu ','','Kwu ','Kyeng ','Bo ','Zhao ','Yuan ','Peng ','Zhou ','Ke ', + 'Cwu ','No ','Kwu ','Pi ','Zang ','Ka ','Ling ','Zhen ','Tha ','Pwu ','Yang ','Sa ','Phil ','Tha ','Tha ','Sa ', + 'Liu ','Ma ','Pyen ','Tao ','Zhi ','Rong ','Teng ','Dong ','Swun ','Quan ','Sin ','Jiong ','Er ','Hay ','Pak ','', + 'Yin ','Lak ','Shuu ','Dan ','Xie ','Liu ','Ju ','Song ','Chim ','Mang ','Liang ','Han ','Tu ','Hyen ','Tui ','Cwun ', + ], + 'x9a':[ + 'E ','Ping ','Seng ','Ay ','Lok ','Chwu ','Zhou ','She ','Pyeng ','Kun ','Tao ','Lay ','Zong ','Kwa ','Ki ','Ki ', + 'Yan ','Pi ','So ','Hem ','Jie ','Yao ','Mwu ','Pian ','Chong ','Phyen ','Qian ','Pi ','Huang ','Jian ','Huo ','Yu ', + 'Ti ','Quan ','Xia ','Zong ','Kui ','Rou ','Si ','Gua ','Tuo ','Kui ','Sou ','Ken ','Cheng ','Cul ','Liu ','Pang ', + 'Tung ','Xi ','Cao ','Du ','Yan ','Wen ','Chwu ','So ','Sen ','Li ','Zhi ','Shuang ','Lu ','Xi ','La ','Zhang ', + 'Mayk ','O ','Cham ','Phyo ','Chong ','Kwu ','Bi ','Zhi ','Yu ','Xu ','Hwa ','Bo ','Swuk ','Hyo ','Lin ','Can ', + 'Dun ','Liu ','Than ','Zeng ','Tan ','Kyo ','Tie ','Hem ','La ','Zhan ','Kyeng ','Yek ','Ye ','Tuo ','Bin ','Chwi ', + 'Yan ','Peng ','Lye ','Teng ','Yang ','Ki ','Shuang ','Ju ','Xi ','Hwan ','Lye ','Biao ','Ma ','Yu ','Tuo ','Xun ', + 'Chi ','Qu ','Il ','Bo ','Lu ','Zang ','Shi ','Si ','Fu ','Ju ','Zou ','Zhu ','Tuo ','Nu ','Jia ','Yi ', + 'Tai ','Xiao ','Ma ','Yin ','Jiao ','Hua ','Luo ','Hai ','Pian ','Biao ','Li ','Cheng ','Yan ','Xin ','Qin ','Jun ', + 'Qi ','Qi ','Ke ','Zhui ','Zong ','Swuk ','Can ','Pian ','Zhi ','Kui ','Sao ','Wu ','Ao ','Liu ','Qian ','Shan ', + 'Piao ','Luo ','Cong ','Chan ','Zou ','Ji ','Shuang ','Xiang ','Kol ','Wei ','I ','I ','Yu ','Gan ','Yi ','Hang ', + 'Thwu ','Xie ','Bao ','Bi ','Chi ','Ti ','Cey ','Ko ','Hay ','Kyo ','Gou ','Kua ','Kyek ','Tui ','Geng ','Pyen ', + 'Pi ','Kwa ','Ka ','Yu ','Sui ','Lou ','Pak ','Xiao ','Pang ','Bo ','Ci ','Kuan ','Bin ','Mo ','Liao ','Lwu ', + 'Nao ','Chok ','Cang ','Swu ','Chey ','Pin ','Kwan ','Lo ','Ko ','Ko ','Qiao ','Kao ','Qiao ','Lao ','Zao ','Phyo ', + 'Kun ','Kon ','Ti ','Pang ','Xiu ','Yem ','Mo ','Dan ','Kun ','Bin ','Fa ','Cho ','Pi ','Ca ','Pal ','Yem ', + 'Chey ','Pao ','Phi ','Mao ','Pwul ','Er ','Rong ','Qu ','','Hyu ','Kwal ','Kyey ','Peng ','Cwa ','Shao ','Sha ', + ], + 'x9b':[ + 'Ti ','Li ','Pin ','Zong ','Ti ','Pwul ','Song ','Zheng ','Kwen ','Zong ','Swun ','Cen ','Duo ','Ho ','La ','Jiu ', + 'Ki ','Lian ','Cin ','Bin ','Peng ','Mo ','Sam ','Man ','Man ','Sung ','Swu ','Lie ','Qian ','Qian ','Nong ','Hwan ', + 'Kwal ','Ning ','Pin ','Lyep ','Rang ','Dou ','Dou ','Lyo ','Hong ','Hyek ','Thwu ','Han ','Dou ','Dou ','Kwu ','Cheng ', + 'Wul ','Wul ','Kyek ','Juan ','Fu ','Qian ','Gui ','Zong ','Liu ','Gui ','Sang ','Yu ','Kwi ','Mei ','Ji ','Qi ', + 'Jie ','Koy ','Hon ','Pal ','Payk ','May ','Xu ','Yan ','So ','Liang ','Yu ','Chwu ','Qi ','Mang ','Lyang ','Wi ', + 'Jian ','Li ','Piao ','Bi ','Ma ','Ji ','Xu ','Chou ','Yem ','Zhan ','E ','Dao ','In ','Ji ','Eri ','Gong ', + 'Tuo ','Diao ','Ji ','Xu ','E ','E ','Sa ','Hang ','Tun ','Mo ','Jie ','Shen ','Fan ','Yuan ','Bi ','Lo ', + 'Wen ','Hu ','Lu ','Za ','Pang ','Fen ','Na ','You ','Namazu ','Todo ','He ','Xia ','Qu ','Han ','Pi ','Ling ', + 'Tha ','Bo ','Qiu ','Phyeng ','Fu ','Bi ','Ji ','Wei ','Ju ','Diao ','Bo ','You ','Gun ','Pi ','Cem ','Xing ', + 'Thay ','Pho ','Pwu ','Ca ','Ju ','Gu ','Kajika ','Tong ','','Ta ','Kil ','Shu ','Hou ','Sang ','I ','An ', + 'Wei ','Tiao ','Zhu ','Yin ','Lie ','Luo ','Tong ','Cey ','Ci ','Bing ','Yu ','Kyo ','Bu ','Hay ','Sen ','Ge ', + 'Hui ','Bora ','Mate ','Kao ','Gori ','Duo ','Jun ','Ti ','Mian ','So ','Za ','Sha ','Qin ','Yu ','Nei ','Zhe ', + 'Kon ','Kyeng ','','Wu ','Qiu ','Ting ','Pho ','Hon ','Tiao ','Li ','Sa ','Sa ','Gao ','Meng ','Ugui ','Asari ', + 'Subashiri ','Kazunoko ','Yong ','Ni ','Chi ','Qi ','Cheng ','Xiang ','Nei ','Chun ','Ji ','Co ','Qie ','Ko ','Zhou ','Dong ', + 'Lai ','Pi ','Yey ','Yi ','Kon ','Lu ','Jiu ','Chang ','Kyeng ','Lun ','Lung ','Chwu ','Li ','Meng ','Zong ','Zhi ', + 'Nian ','Shachi ','Dojou ','Sukesou ','Shi ','Shen ','Hun ','Cey ','Hou ','Xing ','Zhu ','La ','Zong ','Cuk ','Bian ','Phyen ', + ], + 'x9c':[ + 'Huan ','Quan ','Ze ','Wei ','Wei ','Yu ','Qun ','Rou ','Cep ','Hwang ','Lyen ','Yan ','Chwu ','Chwu ','Jian ','Bi ', + 'Ak ','Yang ','Pok ','Say ','Jian ','Ha ','Tuo ','Hu ','Muroaji ','Ruo ','Haraka ','Wen ','Jian ','Hao ','Wu ','Fang ', + 'Sao ','Liu ','Ma ','Si ','Sa ','Hwan ','Shi ','Teng ','Thap ','Yo ','Ge ','Rong ','Qian ','Ki ','On ','Yak ', + 'Hatahata ','Lyen ','O ','Luk ','Hui ','Min ','Ji ','Co ','Qu ','Kyen ','So ','Man ','Xi ','Qiu ','Phyo ','Ji ', + 'Ji ','Zhu ','Jiang ','Qiu ','Zhuan ','Yong ','Zhang ','Kang ','Sel ','Pyel ','Jue ','Qu ','Xiang ','Bo ','Jiao ','Sim ', + 'Su ','Huang ','Cwun ','Sen ','Sen ','Fan ','Kwel ','Lin ','Sim ','Miao ','Xi ','Eso ','Kyou ','Pwun ','Guan ','Hwu ', + 'Hoy ','Zei ','Sao ','Cen ','Gan ','Gui ','Sheng ','Lyey ','Chang ','Hatahata ','Shiira ','Ai ','Ru ','Cey ','Xu ','Huo ', + 'Shiira ','Li ','Lie ','Li ','Mie ','Zhen ','Xiang ','E ','Lo ','Guan ','Lye ','Sen ','Yu ','Dao ','Ji ','You ', + 'Tun ','Lu ','Fang ','Ba ','He ','Bo ','Ping ','Nian ','Lu ','You ','Zha ','Fu ','Bo ','Bao ','Hou ','Pi ', + 'Tai ','Gui ','Jie ','Kao ','Wei ','Er ','Tong ','Ze ','Hou ','Kuai ','Ji ','Jiao ','Xian ','Za ','Xiang ','Xun ', + 'Geng ','Li ','Lian ','Jian ','Li ','Shi ','Tiao ','Gun ','Sha ','Wan ','Jun ','Ji ','Yong ','Qing ','Ling ','Qi ', + 'Zou ','Fei ','Kun ','Chang ','Gu ','Ni ','Nian ','Diao ','Jing ','Shen ','Shi ','Zi ','Fen ','Die ','Bi ','Chang ', + 'Shi ','Wen ','Wei ','Sai ','E ','Qiu ','Fu ','Huang ','Quan ','Jiang ','Bian ','Sao ','Ao ','Qi ','Ta ','Yin ', + 'Yao ','Fang ','Jian ','Le ','Biao ','Xue ','Bie ','Man ','Min ','Yong ','Wei ','Xi ','Jue ','Shan ','Lin ','Zun ', + 'Huo ','Gan ','Li ','Zhan ','Guan ','Co ','Ul ','Pwu ','Li ','Kwu ','Bu ','Yan ','Pwu ','Diao ','Kyey ','Pong ', + 'Nio ','Gan ','Shi ','Pong ','Myeng ','Bao ','Yen ','Zhi ','Hu ','Qin ','Fu ','Fen ','Wen ','Jian ','Shi ','Yu ', + ], + 'x9d':[ + 'Fou ','Yao ','Jue ','Kyek ','Pi ','Huan ','Cim ','Po ','An ','A ','Zheng ','Fang ','Pong ','Wen ','Ou ','Te ', + 'Jia ','Nu ','Lyeng ','Mie ','Fu ','Tha ','Wen ','Li ','Pyen ','Chi ','Ge ','Wen ','Zi ','Qu ','Xiao ','Chi ', + 'Dan ','Ju ','You ','Ko ','Zhong ','Yu ','Ang ','Rong ','Ap ','Tie ','Yu ','Shigi ','Ying ','Zhui ','Wu ','Er ', + 'Kwal ','Ai ','Zhi ','Yan ','Heng ','Jiao ','Al ','Lie ','Zhu ','Ren ','Yi ','Hong ','Luo ','Ru ','Mou ','Ge ', + 'Ren ','Kyo ','Hyu ','Zhou ','Chi ','Luo ','Chidori ','Toki ','Ten ','Luan ','Jia ','Ji ','Yu ','Huan ','Tuo ','Bu ', + 'Wu ','Kyen ','Yu ','Pal ','Cwun ','Xun ','Bi ','Xi ','Jun ','Ju ','Tu ','Jing ','Cey ','A ','A ','Kuang ', + 'Kok ','Mwu ','Shen ','Lai ','Ikaruga ','Kakesu ','Lu ','Ping ','Shu ','Pok ','An ','Zhao ','Pwung ','Qin ','Qian ','Phil ', + 'Co ','Lu ','Cak ','Jian ','Ju ','Tu ','Ya ','Wen ','Qi ','Li ','Ye ','Chwu ','Kong ','Zhui ','Kon ','Sheng ', + 'Qi ','Jing ','Yi ','Yi ','Cheng ','Zi ','Lai ','Dong ','Qi ','Swun ','Geng ','Ju ','Qu ','Isuka ','Kikuitadaki ','Ji ', + 'Shu ','','Chi ','Miao ','Rou ','An ','Chwu ','Ti ','Hu ','Ti ','Ak ','Jie ','Mao ','Fu ','Chun ','Tu ', + 'Yan ','Kal ','Yuan ','Pian ','Kon ','Mei ','Hu ','Ying ','Dun ','Mok ','Ju ','Tsugumi ','Cheng ','Fang ','Gu ','Ayng ', + 'Yuan ','Xuan ','Weng ','Shi ','Hak ','Chwu ','Tang ','Xia ','Yak ','Lyu ','Ji ','Kol ','Jian ','Zhun ','Han ','Ca ', + 'Zi ','Ik ','Yo ','Yan ','Kyey ','Li ','Tian ','Kwu ','Ti ','Ti ','Ni ','Tu ','Ma ','Jiao ','Gao ','Tian ', + 'Chen ','Li ','Zhuan ','Ca ','Ao ','Yao ','Yey ','Kwu ','Chi ','Ci ','Liao ','Rong ','Lou ','Bi ','Shuang ','Zhuo ', + 'Yu ','Wu ','Jue ','Yin ','Quan ','Si ','Cho ','Yi ','Hua ','Pyel ','Ayng ','Swuk ','Huang ','Fan ','Jiao ','Liao ', + 'Yen ','Ko ','Chwi ','Han ','Xian ','Tu ','Mai ','Zun ','Hul ','Ung ','Lo ','Tuan ','Xian ','Hak ','Yi ','Pyek ', + ], + 'x9e':[ + 'Shu ','Luo ','Qi ','Yi ','Ji ','Zhe ','Yu ','Cen ','Ye ','Yang ','Pi ','Ning ','Huo ','Mi ','Ying ','Mong ', + 'Di ','Yue ','Yu ','Lei ','Bao ','Lo ','He ','Long ','Shuang ','Yue ','Ayng ','Kwan ','Kwu ','Li ','Lan ','Niao ', + 'Jiu ','Ji ','Yuan ','Ming ','Shi ','Ou ','Ya ','Cang ','Bao ','Zhen ','Gu ','Dong ','Lu ','Ya ','Xiao ','Yang ', + 'Ling ','Zhi ','Qu ','Yuan ','Xue ','Tuo ','Si ','Zhi ','Er ','Gua ','Xiu ','Heng ','Zhou ','Ge ','Luan ','Hong ', + 'Wu ','Bo ','Li ','Juan ','Hu ','E ','Yu ','Xian ','Ti ','Wu ','Que ','Miao ','An ','Kun ','Bei ','Peng ', + 'Qian ','Chun ','Geng ','Yuan ','Su ','Hu ','He ','E ','Gu ','Chwu ','Zi ','Mei ','Mu ','Ni ','Yao ','Weng ', + 'Liu ','Ji ','Ni ','Jian ','He ','Yi ','Ying ','Zhe ','Liao ','Liao ','Jiao ','Jiu ','Yu ','Lu ','Xuan ','Zhan ', + 'Ying ','Huo ','Meng ','Guan ','Shuang ','Lo ','Kung ','Lyeng ','Jian ','Ham ','Cuo ','Kem ','Jian ','Yem ','Cuo ','Lok ', + 'Wu ','Cu ','Kwey ','Biao ','Chwu ','Biao ','Zhu ','Kyun ','Cwu ','Jian ','Mi ','Mi ','Wu ','Liu ','Chen ','Kyun ', + 'Lin ','Yey ','Ki ','Lok ','Jiu ','Jun ','Jing ','Li ','Xiang ','Yan ','Jia ','Mi ','Li ','Sa ','Cang ','Lin ', + 'Jing ','Ji ','Ling ','Yan ','Chwu ','Mayk ','Mayk ','Ge ','Chao ','Pwu ','Myen ','Mian ','Fu ','Pao ','Qu ','Kwuk ', + 'Mo ','Fu ','Xian ','Lai ','Kwuk ','Myen ','','Feng ','Fu ','Kwuk ','Myen ','Ma ','Ma ','Ma ','Hwi ','Ma ', + 'Zou ','Nen ','Fen ','Hwang ','Hwang ','Kum ','Guang ','Tian ','Tou ','Heng ','Xi ','Kuang ','Hoyng ','Se ','Lye ','Cem ', + 'Li ','Huk ','Huk ','Yi ','Kem ','Dan ','Ki ','Tuan ','Mwuk ','Mo ','Kyem ','Tay ','Chwul ','Yu ','Cem ','I ', + 'Hil ','Yan ','Qu ','Mei ','Yan ','Kyeng ','Yu ','Li ','Tang ','Du ','Can ','Yin ','An ','Yan ','Tam ','Am ', + 'Zhen ','Dai ','Cham ','Yi ','Mi ','Tam ','Yem ','Tok ','Lu ','Zhi ','Pwun ','Pwul ','Po ','Min ','Min ','Wen ', + ], + 'x9f':[ + 'Chwuk ','Qu ','Co ','Wa ','Cwu ','Zhi ','Mang ','O ','Pyel ','Tha ','Pyek ','Yuan ','Chao ','Tuo ','Ceng ','Mi ', + 'Nay ','Ding ','Zi ','Ko ','Gu ','Tong ','Fen ','To ','Yuan ','Pi ','Chang ','Gao ','Qi ','Yuan ','Tang ','Teng ', + 'Se ','Shu ','Pwun ','Fei ','Wen ','Ba ','Diao ','Tuo ','Tong ','Qu ','Sheng ','Sek ','Yu ','Shi ','Ting ','O ', + 'Nian ','Jing ','Hun ','Ju ','En ','Tu ','Ti ','Hyey ','Kyem ','En ','Lei ','Pi ','Yao ','Kwu ','Han ','Wu ', + 'Wu ','Hou ','Xi ','Ge ','Cha ','Xiu ','Weng ','Zha ','Nong ','Nang ','Ca ','Cay ','Ji ','Zi ','Cay ','Cey ', + 'Qi ','Ji ','Chi ','Chen ','Chin ','Hul ','Ya ','Un ','Xie ','Pho ','Cuo ','Shi ','Cha ','Chi ','Nian ','Ce ', + 'Cho ','Lyeng ','Ling ','Chek ','Quan ','Xie ','Kan ','Sel ','Jiu ','Kyo ','Chak ','Kon ','E ','Chu ','Yi ','Ni ', + 'Cuo ','Zou ','Wu ','Nen ','Xian ','Ou ','Ak ','Ak ','Yi ','Chuo ','Zou ','Dian ','Chu ','Jin ','Ya ','Chi ', + 'Chen ','He ','Ken ','Ju ','Ling ','Pao ','Tiao ','Zi ','Ken ','Yu ','Chuo ','Qu ','Wo ','Lyong ','Pang ','Gong ', + 'Pang ','Yan ','Lyong ','Long ','Kong ','Kam ','Ta ','Ling ','Ta ','Long ','Gong ','Kan ','Kwu ','Chwu ','Pyel ','Gui ', + 'Yak ','Chwi ','Hwa ','Jue ','Hay ','Yu ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Shan ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'xf9':[ + 'Kay ','Kayng ','Ke ','Ko ','Kol ','Koc ','Kwi ','Kwi ','Kyun ','Kul ','Kum ','Na ','Na ','Na ','Na ','Na ', + 'Na ','Na ','Na ','Na ','Nak ','Nak ','Nak ','Nak ','Nak ','Nak ','Nak ','Nan ','Nan ','Nan ','Nan ','Nan ', + 'Nan ','Nam ','Nam ','Nam ','Nam ','Nap ','Nap ','Nap ','Nang ','Nang ','Nang ','Nang ','Nang ','Nay ','Nayng ','No ', + 'No ','No ','No ','No ','No ','No ','No ','No ','No ','No ','No ','Nok ','Nok ','Nok ','Nok ','Nok ', + 'Nok ','Non ','Nong ','Nong ','Nong ','Nong ','Noy ','Noy ','Noy ','Noy ','Nwu ','Nwu ','Nwu ','Nwu ','Nwu ','Nwu ', + 'Nwu ','Nwu ','Nuk ','Nuk ','Num ','Nung ','Nung ','Nung ','Nung ','Nung ','Twu ','La ','Lak ','Lak ','Lan ','Lyeng ', + 'Lo ','Lyul ','Li ','Pey ','Pen ','Pyen ','Pwu ','Pwul ','Pi ','Sak ','Sak ','Sam ','Sayk ','Sayng ','Sep ','Sey ', + 'Sway ','Sin ','Sim ','Sip ','Ya ','Yak ','Yak ','Yang ','Yang ','Yang ','Yang ','Yang ','Yang ','Yang ','Yang ','Ye ', + 'Ye ','Ye ','Ye ','Ye ','Ye ','Ye ','Ye ','Ye ','Ye ','Ye ','Yek ','Yek ','Yek ','Yek ','Yen ','Yen ', + 'Yen ','Yen ','Yen ','Yen ','Yen ','Yen ','Yen ','Yen ','Yen ','Yen ','Yen ','Yen ','Yel ','Yel ','Yel ','Yel ', + 'Yel ','Yel ','Yem ','Yem ','Yem ','Yem ','Yem ','Yep ','Yeng ','Yeng ','Yeng ','Yeng ','Yeng ','Yeng ','Yeng ','Yeng ', + 'Yeng ','Yeng ','Yeng ','Yeng ','Yeng ','Yey ','Yey ','Yey ','Yey ','O ','Yo ','Yo ','Yo ','Yo ','Yo ','Yo ', + 'Yo ','Yo ','Yo ','Yo ','Yong ','Wun ','Wen ','Yu ','Yu ','Yu ','Yu ','Yu ','Yu ','Yu ','Yu ','Yu ', + 'Yu ','Yuk ','Yuk ','Yuk ','Yun ','Yun ','Yun ','Yun ','Yul ','Yul ','Yul ','Yul ','Yung ','I ','I ','I ', + 'I ','I ','I ','I ','I ','I ','I ','I ','I ','I ','I ','Ik ','Ik ','In ','In ','In ', + 'In ','In ','In ','In ','Im ','Im ','Im ','Ip ','Ip ','Ip ','Cang ','Cek ','Ci ','Cip ','Cha ','Chek ', + ], + 'xfa':[ + 'Chey ','Thak ','Thak ','Thang ','Thayk ','Thong ','Pho ','Phok ','Hang ','Hang ','Hyen ','Hwak ','Ol ','Huo ','','Coc ', + 'Chong ','','Cheng ','','','Huy ','Ce ','Ik ','Lyey ','Sin ','Sang ','Pok ','Ceng ','Ceng ','Wu ','', + 'Hagi ','','Cey ','','','Il ','To ','','','','Pan ','Sa ','Kwan ','Hak ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x200':[ + 'Ha ','Qi ','','','','Hai ','','','','Qiu ','','','','Shi ','','', + '','','','','jue ','','','','','','','yu ','','','','', + '','','','','','','','Ba ','Cup ','','Kha ','','','','','', + '','','','','Trut ','','','','','','','','','lu ','','', + '','','','','','','','','','','','','','','','', + '','Duoi ','','','','','','','','','Cui ','','','','','', + '','','','','','Ga ','','','','','Nham ','','','','','', + '','','','','','','','','Suot ','','','','','','','', + '','','','','','','','','jie ','','','','','','','', + '','','','','Zi ','','','','','','','','','Zung ','','', + '','','Pai ','','Dui ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','jiu ','','','','','', + ], + 'x201':[ + 'Vu ','','','','','','','','','','','','','jie ','','', + '','jue ','','','','','','','','','','','','','','', + '','','','','','','Gop ','Vai ','','Hai ','','','','','','', + '','','','Kep ','','','Nham ','','','','','Lam ','Nam ','Vai ','','wei ', + '','','jie ','','','','','','','','','','','Mat ','Mat ','', + 'Mat ','','Mat ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','zhang ','','','Mat ','','','', + '','','','','','','','','','','','','Yong ','','','', + 'xu ','','','','','','','','','','','','','','','', + '','','','','','','','','','Faan ','','','','','','', + '','','','Trum ','','','dan ','','','','','','','','','', + '','','','','','','','','','','','','','Voi ','','', + '','','','','','Va ','','','chu ','','','','','','','', + '','','','','','','','','','','','','','','','qu ', + '','','','','','','','','','','','','Hua ','Top ','','', + ], + 'x202':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','yun ','','','','','','','','','','','', + 'dan ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Nay ','', + 'Tray ','','','','','','','ju ','','du ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','jian ','','','','','','','','Ngai ','','Nho ','Thay ','','', + '','','','','','','','Bing ','','zhuan ','shu ','','jue ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','lian ','','','','','','','','she ','', + '','','','','','May ','Mu ','','','fu ','','','ju ','','','', + '','','','','','','','','','','Tao ','','','','','', + ], + 'x203':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Wu ','','','','','','','','shuai ','','', + 'gai ','','','','zhuang ','','','','','','','','','fu ','','', + '','Man ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','But ','','','','','yao ','','','','Gap ','','bie ', + '','','qu ','','','yang ','','','','','','','','sha ','','', + '','','','','','','','','','','Xum ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Cap ','Bay ','','','','','jue ','', + '','','','yu ','','','','sa ','','','','dun ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','xiao ','','','','','yu ','qu ','','','','', + '','','','','','Ngai ','','','','','','','','Tui ','','', + '','','','Giong ','','','','','','','','','','','','', + ], + 'x204':[ + '','meng ','','','','','','','','jie ','shu ','','','su ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','meng ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Trom ','','','Long ','','','','', + '','','','','','Ngua ','','','','','nei ','nei ','','','zhai ','', + '','','','','','','','','','','','','Nhau ','','','cu ', + '','','','','','','','','','','','','','','','', + '','','','','wu ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Rang ','','','','','','','','','','', + '','','','','','lian ','','Tin ','','','','','','','fan ','', + 'Truoc ','','','','','','','','','','','','','','','', + 'Quanh ','','','','Mong ','','','fu ','','','','','','','','', + '','','','','','','','','Vao ','Nhui ','','','','','','', + '','','','','','','','','','Lon ','','Tron ','Sip ','','','', + ], + 'x205':[ + '','','','Xi ','','','','','','Juan ','','','','','','', + '','hai ','','','','lun ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','heng ','','','','','','','','','Zheng ','','','','', + '','','','','Nap ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'cheng ','','','qia ','','','yu ','','','','','','','zhao ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Xuong ','','','','','','','', + '','','','','','','','','Nap ','','','','','','','', + '','','','','Bay ','Chong ','','','','','','','','','','Ngat ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','qiu ','xie ','','','','','','', + '','','','','','','','','','','','die ','','','','', + '','','','Lun ','','','Ping ','','die ','','','','','','','', + 'Tron ','','','','','','','','','Ret ','','','','liu ','','', + ], + 'x206':[ + '','bu ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','lai ','','', + '','','he ','jiao ','','','','','','','','','','','','', + '','','','','','','','','','','','wu ','','','','', + '','','','','','','ju ','','','','','','','','','', + '','','','','jiu ','wei ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','xian ','','','','chang ','','','','','', + 'Moc ','','','','he ','','','','','','','','','','','', + '','','Ra ','','','','','','','','','','','','','Got ', + '','zhe ','','','','ju ','','','','Shan ','Sha ','','','','','', + '','','','','','','','','','','','','Cham ','','','', + '','','','','','','','','','cu ','','','','','','', + '','','','','Chem ','','','','','','Tiu ','','','','','', + '','','','','','','','','fen ','','','','','','','', + ], + 'x207':[ + '','','','jiu ','xu ','','','','','','','','','','Xian ','', + 'kuai ','','','','','','','','','bu ','','','','','','', + '','','','','qia ','','','','','','','','','','Hui ','', + '','Pai ','','','','','','','','ju ','','','Qia ','','','', + '','','','','','','','Bao ','','','','','','','','', + '','','','','','Cun ','','','qia ','','','','','','','', + '','','','','','','','','','','','','','Peng ','','', + '','','','','','','','','','Gaai ','','','','','','', + '','','','zhe ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','Got ','Bam ','','','','','','','','','','gun ','Lou ','','', + 'Jiao ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','yao ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Hoat ','','','','','','','','','','', + '','','','','','','','','','','','ze ,bai','','','','', + ], + 'x208':[ + '','','','','zhao ','','','','','Bua ','','','','','','', + '','Tet ','','','du ','','','','','','','','','','','', + 'du ','','','','','','','','','Truoc ','','','','Chom ','','die ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','Gang ','','','','','', + '','','','','','','','','','','','','','','','', + '','duan ','','','','','','','','','Khuot ','','','','','', + '','','','','','','','han ','','','','','','','','', + '','Nhoc ','','','','','','','','','juan ','','','Vam ','Giup ','Giup ', + '','','','dian ','Jue ','','','','','','','','Lu ','','','', + '','','','','','','','','','','','','','','','', + '','','Ruon ','','','','','','','10383.060,wan ','','','','','','', + 'yun ','','','','','','','','','','','','','','','', + '','','','','','','','','','','qu ','shao ','','','','', + '','','','pao ','','','','','','','bao ','','','','fu ','jiu ', + ], + 'x209':[ + '','','','','','','Cho ','','','','','','Cho ','','hua ','Bao ', + '','','','','','','','','','','','','','mao ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','diao ','','','', + '','','','','','','','','','','','','','','wei ','', + '','diao ','','','','','','','','','','','','','','', + '','','','','Giau ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','sa ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','luan ','Muoi ','','','','','','Gan ', + '','','','','','','','','','Chuc ','','Lung ','','','','', + '','','','','','','Tron ','yu ','','','','','','Nhu ','','', + '','','','','','he ','','','','shao ','','','','','','', + '','','','','','','','','','Hui ','','','','','','', + '','','','','','','','','','','','','','','','heng ', + ], + 'x20a':[ + '','','','wai ','','','','','','','jue ','','','','zhuan ','', + '','','','','','','','','','','','','','','','', + '','','jun ','','','','','','','','','','','ju ','','', + '','','','','','bang ','','','','','','','','','','', + '','','','','','','','','zhu ','','','','','','','', + '','','','','','Me ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','Li ','','','','','', + '','','','mei ','','','','','','','','','','','','', + 'liu ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','fu ','','','','', + '','','','jue ','','Day ','','','','','','','','','','Rot ', + '','','','','','','','','','','','','','','','', + '','','','yu ','','','','','','','','','','','tu ','', + '','','','','','','','','','shan ','','','','','','', + ], + 'x20b':[ + '','','','','','','guan ','','','','','','','','','', + '','','Cut ','','','','','','','','','Mo ','','fu ','','', + 'Mot ','','','bang ','','','','','','','biao ','','','','jie ','', + '','','','','','','Jin ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','Zhuo ','','','','','bian ','','','','','','tun ', + '','','','','','','','','','','de ','','zhu ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Naai ','Leo ','','','','','','', + '','','','','','mang ','','','','','','','','','Ngot ','sa ,san', + '','','','','','','','','Daai6','','','Jai ','','','','', + '','','','zhe ','','','','','ban ','jie ','','','','','','', + '','','','','','','Thet ','','','','','','','','Hin ','pian ', + '','','','','bian ','','','reng ','','reng ','','','Danh ','Chui ','','', + ], + 'x20c':[ + '','','Ngoen ','','','','','','','','','Jaau ','Mut ','','','Mom ', + '','an ','','he ','','','','','','Khen ','','hu ,gao','','','','', + '','','','','','','','','','','','','','Meo ','','', + '','','Eot ','','','','','Lo ','','','dai ','wai ,wai','','','','', + '','Tam ','Dat ','Nip ','','Quai ','','','','','','','','Phom ','','', + '','','','Ngai ','','','','','Ngaak6','','','','Chun ','','','', + '','sa ,shai','','','','Fik ','','','','','','','','','','', + '','','na ','','','','','Ming ','San ','','','','','','','', + '','','','','','','','','','','','','shu ','','','Nham ', + '','','','Hang ','','','E ','','','','','','Gianh ','','','', + '','','','','','','Nhung ','','','','','','','','Khinh ','', + '','ge ','','','','Mep ','','die ','','','','','','fu ','','Shu ', + '','Kwan ','','','','','','he ','','','','','qia ','','','Ce ', + 'Vang ','','','','','Caau ','Dap6','','Nhu ','Thay ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','Tu ','','','','','','','cheng ','','', + ], + 'x20d':[ + '','','','','','','','','','','','Phao ','Nhanh ','Nhan ','','Mang ', + 'Nuc ','','','','','Miu ','Voi ','','','','','Gung ','','','','', + '','xiao ','','','','Ngoam ','zhu ','','','','','Thut ','','','','', + 'Gau6','hu ','ta ','Ngaau ','','zao ','','','','','','','dao ','','na ','', + '','','','','','','Daam ','Koe ','Mui ','Hong ','','','','','','', + 'Mep ','','','','','','','','Mun ','','','','','','','', + '','','','ya ','','','','zhen ,chun','de ','Go ','','','','','','Gwit ', + '','E ','','','','','','xuan ','','','','','Mang ','Faat ','Waak ','Pe ', + 'Tham ','Nhu ','','','','','','','Se ','','Pha ','','','','','', + '','U ','','','','Nhau ','Uong ','','Sat ','Bop ','','','Zai ','','','', + '','Troi ','Du ','Mai ','','Khung ','','Dim6','','','','da ','nang ','','','Chut ', + '','','Gap6','','','','','','jue ','he ','','','','','','', + '','','dai ','','','zhu ','','','','','','','','ta ','','', + '','','','','','','bian ','','','xu ','','','','','','', + '','','','','Phao ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x20e':[ + '','pai ','Giot ','','Inh ','','','','','Kak ','Tap ','','','Me ','Naa ','Ge ', + 'Kam ','Soek ','Bou ','','','','','Xua ','Tuc ','Song ','','','','','','Bai ', + '','','','','','','Khan ','','','','','Tau ','','','','', + '','','','','','','','','','yu ','Ngaak6','','','','Map ','', + 'xun ','wa ','','ang ','han ','','','','','','','','Lan ','','','', + '','yao ','','ge ','','bao ','','','xu ','','','','','','','', + '','','','','','','','','','','','','','Ko ','','', + '','','','Git6','','','','Ngo ','Kam ','Lan ','Maai ','Zam6','','Cay ','','', + '','','','','','','','','','','','','Gwe ','','','', + 'huan ','','','','','','','','Long ','Thoi ','Ban ','','','Gaak ','','ku ', + 'Lung ','','Gaa ','','','','','','','Trou ','He ','Loe ','He ','','','', + '','Hung ','','','','Chac ','Nop ','','','Ri ','Que ','Cop ','Xui ','','Chau ','Ngoan ', + '','Guong ','Ngon ','Han ','Oang ','','','','','','','','','huan ','','zu ', + '','','','','','','','Le ','Zeot6','he ','','','','','','', + '','','','','Don ','zhao ','','','','','','','tu ','','','', + '','','','','Long ','','','','','','Aa6','Bai ','Dau6','','','', + ], + 'x20f':[ + '','','','','','','','','','','','','','','','', + '','','','','','Paai ','','Zaam ','wu ','','','','','','','', + '','','jiang ,qiang','','','','Muon ','','','lun ','Day ','','','But ','Ngai ','Ho ', + 'Kang ','Loe ','','','','Danh ','','Thay ','','','','Ji ','','','','', + '','Xo ','','Zap ','Tham ','Thung ','Nuot ','','','','','Nac ','Toet ','','Nhai ','', + 'Ngo ','','Neng ','Ngon ','Thua ','','Giuc ','','','','','Oam ','','','','', + '','','','','Kik ','','','','','','','','','','','', + '','','','','','yu ','','','','','','zhe ','','','','', + 'Hup ','','','','','','','','','','','','','He ','','Ce ', + '','','','','','','','','','','','Ngoang ','','','','', + '','','shu ','Rum ','','','Bai ','','','la ','','','','We ','','', + '','','','','Baang ','Zaa ','Ging ','','','Nuot ','','','Cyut ','Nhun ','Nhap ','', + '','Si ','Xep ','','','','','','','','','','','','','', + '','','Het ','sa ','','qiao ','','','','','','Lu ','hua ','','','', + '','','','','','','','','','','Gaa ','Saau ','Soe ','Wet ','','Ngui ', + '','','','','','Khan ','','','','','','','','','','', + ], + 'x210':[ + '','','','','','','','','','','','','','','','', + '','','','','Lu ','','','','','','','','','Nam6','Zip ','', + 'Bei6','','','','','Phao ','','','','Lok ','','Bam ','','','','', + '','Hao ','Cay ','','','','','Ron ','','','xie ','','','','','', + 'han ','','','','','','','','fan ','','','','','ai ','yu ','Am ', + '','','','','','','','','','','Hon ','','Wo ','Hang ','Xao ','', + '','','','','','','','','','','','','','','','Dyut ', + '','','','zhan ','','Gan ','Zit ','Doeng ','Kwaat ','','Ngon ','Ziu ','','','','', + 'Khao ','','','Hun ','','','','Mom ','Voc ','','yu ','','','Eng ','','', + '','Ban ','','','','','Lai ','','','','','','','Zuk6','','bao ', + '','shu ','','','','','','','','','Ze ','peng ','','','Ngau ','', + 'Ran ','','Ray ','Troi ','','','','Khoan ','','','','','','','','', + 'E ','Leng ','','','lai ','','','Bai6','Kwaak ','Gaa ','','','','Chem ','Phan ','Doe6', + '','','Boc ','Bo ','','Gung ','Le ','Mua ','','Mut ','','','','lun ','','', + '','','','','Laai6','','','','','','','','','','','', + '','','','','Ceoi ','Ngung ','Sek ','','','Chen ','','','','','Phac ','Thot ', + ], + 'x211':[ + '','Lum ','','','','','','','','','','','','Ruc ','Gam ','Ham ', + '','','dao ','','','','','','','','','','','','','Haa ', + '','Chay ','','','','','Lom ','','','Khan ','Toe ','Khem ','Hun ','','','Jik ', + 'Tot ','cu ','ru ','','','Ji ','','','','luan ','','','','Soe ','','', + '','','','','','e ,ei','','','Laa ','Dang ','Bun ','Hum ','','','','Lai ', + 'Lanh ','Ngong ','','','','','','','la ','yun ','','','','','','', + '','','','','','die ','','Nan ','','','','','Hoai ','','','', + '','huan ','','','','','','','','','','huan ','','','','', + 'Gwang ','Nhau ','','','Nhep ','wan ','','Wok ','','','','','','','','', + '','Nham ','','','','lian ','Trom ','','','','Gu ','','','','Giau ','', + '','','','','','jiu ','','','','','','','','','','', + 'dun ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','die ','','','','','','Doe ','','','','','he ','', + 'zhe ','','','','','','wei ','','','tu ','','','','','','hun ', + '','','','','','dang ','he ','tai ','Quay ','','yu ','Nhot ','ya ','','','', + ], + 'x212':[ + '','','','','','jue ','','','','','','','','','Mui ','', + '','','','yuan ','','','','','','You ','','','','','','', + '','','','','','','','','yu ','','','','','','','', + '','','','','','','lei ','','','','','','','','','', + '','','','','','','','','','','','','','','Cong ','', + '','','tun ','','','','Cong ','','','','','','','','','', + '','','','','','','','','','bao ','','','','','','', + '','','','','lu ,hu','','','jie ','','','','','','','Tum ','Moc ', + '','','','','','','','','','','','','','shu ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Sanh ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','gao ', + '','','','','','','','','','de ','','','yu ','','','', + '','','','','','','','','','','','','','','','', + ], + 'x213':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','guai ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'hu ','','','','','','','','Che ','Vung ','Lam ','','Mun ','Nui ','','', + '','','','','','zhai ','','','du ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','du ','','','','','','', + '','an ','','','','','','','','','','Bun ','Nam ','','','Hang ', + '','','','','','','','','','','','','','Thong ','su ','', + '','','','','Gung ','','','','','','zhu ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','xia ','','','','','','','', + '','Luong ','','','','Tret ','Xay ','Bui ','','','','','','','','bai ', + '','','','','','','','','','','','','','','','', + ], + 'x214':[ + '','','','','','','','','','','','','chu ','','','', + '','','','','','','xian ','Hoc ','','','','','','fu ','','', + '','','','','','sa ','','','','','','','','','Ve ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Coi ','Chum ','','','','Thoai ','','','','','','Lan ','Sui ','', + '','','','','','','','','','','','','','Coi ','','', + '','','Gom ','','','','','','','','','','','','yu ','', + '','sa ','','Juk ','Lan ','','','','','','yu ','','','ju ','','', + '','','shu ','xian ','','','gai ','','','','','','','','','', + '','','','','','','','','','','','Cau ','','','Suong ','', + '','','','','','','','','','','','','','','','', + '','','','Loi ','Vung ','','','','','','','','','','','San ', + '','','lai ','','Lam ','','','','','','','','','','','', + '','','','','','Chen ','zhan ','','','','','','','','','Chum ', + '','','','','','','','','','','','','','','','', + ], + 'x215':[ + '','','','','','','','','','','','','','','','', + '','','','','Lan ','','','','','','','','','','','', + '','','','','','','','','','','shu ','','','','','', + '','','','','yu ','','','','','','','','','','','Trau ', + '','','','','','','','','','','','','','','','', + '','','kua ','','','','','hai ','','','','','','','','', + '','','','','','','','hang ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','yun ','','','','','','','','','','','','','', + '','','','','','','','','','','guai ','','','','','su ', + '','Bon ','','','','','','','','','','','','','','', + '','','Sai ','','','','','','','','','Lam ','','','Tum ','', + 'Muong ','','','','','','','Peng ','','','','','','','','', + '','','','','','chun ','','','','','','','','','','', + '','','','','','','','','','fan ','','','','','','', + ], + 'x216':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','zhe ','Mat ','Lon ', + 'juan ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','jie ','','','','','','','bie ','','','','','', + '','','','','Canh ','Nhon ','','','','','','','','','','', + '','Bi ','','Xon ','','','','yan ','wei ','','','','hao ','','','', + '','','','','meng ','','','','','','Lon ','','','','','', + 'jue ','To ','To ','','','','Hai ','','','','','','','','','', + '','','','','','','','','','zhang ','','da ','','hao ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','can ','','', + '','','','','Nua ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x217':[ + 'fan ','','hu ','','','','','','','','','','','','','', + '','','','','','','','','','','ru ','','','','','', + '','','','','','','','','','','','','','','','zhe ', + '','Ji ','gao ','','','','','','','','','','','','','', + '','','','Bua ','','','','','chu ','','zhe ','','','','','', + '','','','','Kep ','Va ','','','','','cheng ','','du ','','','nian ', + '','','','','','','Vu ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','cu ','','','pan ', + 'hu ','','','xian ','','','','','','','fu ','nai ','','','','', + '','','','','','','','','','','','','','','Nen ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','lian ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x218':[ + '','','','','','','','','','','','','','','','', + '','','','','','','hao ','','yang ','','','','','','fu ','', + '','','','Cuoi ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'juan ','','Nhang ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','qu ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'zhuan ','','','','','','','','dang ','','','','','','','', + 'Sau ','','','','','','','','','','man ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Sui ','','', + '','','','','','','','','shu ','','','','','','','', + '','','','','han ','Ban ','','','','','','','','','','', + '','','nei ','','','','','','Cuoi ','','','','','','cai ','jie ', + '','','','','','','','','','','','Sen ','','','','', + ], + 'x219':[ + '','','','','','','','','','','Chua ','','','','fan ','', + '','','','Moi ','Moi ','','','zhu ','','na ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','jiao ','','','','Nhat ','xiao ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Con ','ju ,ru','','','','','','Me ','','','', + '','xu ','','','fu ','So ','','','','','','','','','','', + '','','','','','er ','','','','','','shu ','','','','', + '','','','','','','','Rot ','','','','Chat ','','','Nhang ','', + '','','','xiao ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','mian ','','','','','wa ','','pao ','','','','','','', + '','','','','','','heng ','','zhu ','','','','','','','', + '','','','','','','','','','dai ','','','','','','', + ], + 'x21a':[ + '','','','','Xia ','ju ','','','','','','','','','','', + '','','','','','','','zao ','','','','','','','','', + '','','','yu ','','','','Tot ','','','','','','','','', + '','','jie ','','Ning ','nai ','','','','','','','','','','yu ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','jie ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','an ','','','Xum ','','','', + 'ceng ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','Sao ','','','','','','','','','','','','','','', + '','','','','','','Lung ','','','','','','','','','', + ], + 'x21b':[ + '','','','','','','','','Xuong ','sai ','yu ','jiao ','','','','', + '','','','','','','','','20960.020,lao ','','','','','','yu ','', + '','','','','','','','','','','','wu ','','','','', + '','','','','','','','Tac ','','','','','Gang ','','','', + '','','de ','','','','','','','Ban ','','','','','','', + 'shuan ','','','','','Cut ','','','','','','','Mon ','','','', + '','','bai ','','','','','Chut ','','','','','Be ','','','', + '','Chut ','Trut ','kao ','','','','','luan ','','','Nhon ','','','','', + '','','','','','','Mon ','Chut ','','Mon ','','May ','Be ','Chut ','','', + '','','','Choai ','','','','','','nai ','','','','','','', + 'May ','','','Be ','Be ','Be ','Zao ','','','Be ','','Nhen ','Mon ','Nhon ','Mon ','', + '','','Tho ','','','Chuong ','Chuong ','','Nhon ','','','','','Nhon ','','', + 'Oat ','','','','','','','wu ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'ga ','','','','chao ','','','','','','','','','ga ','','', + ], + 'x21c':[ + '','','','','','hu ','','','','','','','','','','', + 'qiao ','','','','','','','','','','','','','','','', + '','','xie ','','','','','','','','Duk ','','','','','', + '','','','','','','','','','','','','','ai ','','pu ', + '','','','','','','Shu ','','','','','','','','','', + '','','','','','','','','','','','','zhao ','','','', + '','','','xu ','','','','','','Thuoc ','','','','','','', + '','zhu ','','','','','','die ','Gang ','','qu ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Ti ','','jue ','','','qiu ','','','','','', + '','','Ke ','jiang ','','','','','','','yun ','','Gwat6','','','', + 'qu ','','','','','','','','','','','','','','','', + 'Ngoe ','','kai ','Cuoi ','','','','','','','','','','','','', + '','chu ','','','','','','','ju ','','','','Cuoi ','Rot ','','', + '','','','','','Toi ','','','','','','','','','','', + '','','','Cuoi ','lu ','','','','','','','','','','jue ','', + ], + 'x21d':[ + '','','','','','','lu ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','ya ','','', + '','hu ,jie','','','','','','','','','','','','','','', + '','','','','','','','','','Ngut ','','','','','','', + '','','','','','','','','hu ','ang ','','fu ','','','','', + '','','','','','','','','','','','','mu ','','','', + '','','','','','','','','','','Cu ','','','','','', + 'Nui ','','yao ','ai ','','','','','','fan ','','ju ','','','','', + 'qie ','','','','','','','','','','','','','','','', + '','','kuang ','','','','ya ','','Ngan ','','kan ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','lu ', + '','','','','','','','','bie ','','','han ','','na ','','', + '','','','','wu ','gao ','','','','','','','','','','', + '','','','','','','','','','','','ya ','','','','', + ], + 'x21e':[ + '','','','','','','','','','','','','zhu ','','jie ','Voi ', + '','','','','xie ','','','ya ','','','','','','','','', + '','','','','','','ze ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','ya ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Nghi ','','','','','','','','','','','','','die ','','', + '','','','','','','','','','hu ','','','','','','', + '','','','','','','','','','','','','','','','', + '','die ','','','','','','','','','','','pen ','','','', + '','','','','','','Din ','','','','','','','','','', + '','','','','tu ','','','xia ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Voi ','','Seoi ','Von ','Chon ','','','','','','','','', + 'zhu ','','','','','','','','gun ','man ','','','zu ','','hu ','', + '','lei ','','','','','','','','','','','','','','', + ], + 'x21f':[ + '','','','','die ','','','','','','','','','','','', + '','','','dian ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','wei ','','','','','','','','','','','','','kuai ','', + '','','','','','yun ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','Non ','','','','', + '','Jie ','bang ','','','','','','','','','','','','','', + '','','','','','','','kuang ','','','','','','','','', + '','','','ceng ','','dang ','','','','','','','','','','', + '','','','','','','','','hai ','','','','Doc ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','nang ','','', + '','','','','','yu ','','','','','','','','','','yu ', + '','','','','','','','','','','Nao ','','xun ','','ju ','', + ], + 'x220':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','wan ','','','','','','','','', + '','','','','','Vang ','Sua ','Tron ','Sang ','','','','Lon ','','Sam ','', + '','To ','Lon ','','','han ','','','','','','','fu ','','','', + 'fu ','','','','','','','','','','','Trang ','','Va ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','jue ','','','','','', + '','','','','','','','','Phuon ','','','bu ','','','','', + 'fu ','','','','xuan ','','fu ','','','','','','','','Du ','', + 'xie ','Shi ','','','','','','','','','','','Vua ','','','', + '','','','','','','','','','','','','','','','', + 'Tranh ','yuan ','','','','','','','','mao ','qian ','','','','','', + 'wu ','','','','','','','Lei ','Long ','','Vua ','','','','','', + '','','','','','Ta ','','han ','qian ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','la ','','','','','','','','','','','', + ], + 'x221':[ + '','','','Phoi ','','','','','','','','','','he ,ge','bang ','', + 'meng ','','','wu ','dai ','','','','','','','','han ','Bau ','','', + '','','','','','','','cu ','','','','','','','','Man ', + '','','','','','xiang ','Hua ','','','','','','','','','', + '','','','','','','Manh ','','','mao ','','ceng ','','','','Lian ', + '','','dan ','','','','Lian ','','','','','','','dian ','','', + '','','','','gai ','Ju ','','','','','zu ','','Chan ','','','', + '','','','','','','','','','yao ','','','nei ','','','', + '','','neng ','','','','','','','','','','','','','', + '','','','','','','','','','','','','ge ','','Jian ','', + 'Lai ','Nin ','','','','Nam ','jian ','May ','May ','','May ','','','','','', + 'hu ','','','','','','','','','','chen ','','','','','', + '','','','','','','','Guan ','yan ','Doi ','','','','','','', + '','','','','','','','sha ','','','','','','','han ','', + '','Khuya ','','','','','ren ','','','','fan ','','','','','', + '','','','','bu ','na ','','','','','','','','','','', + ], + 'x222':[ + '','','','','','','','','Nap ','','','','','','','', + '','','','','','bai ','','','Roku ','','','kun ','','qiu ','','', + 'cu ,la','','','','','','','','','','','','','','','', + '','','pu ','','','','','','','','','jie ','','zhan ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','du ,tu','','','', + '','','hu ','','jia ','','','','la ','','','','','','','', + '','','','','','','','','','','','','','Kho ','U ','ma ', + '','','','','','','','','','','','','','Zu ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','yu ','','lu ','','','','','','', + '','fen ','','','','','','','','','','','','','','', + '','','','','','yu ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','xian ','', + '','','','','','','','','','wu ','','','','','','', + ], + 'x223':[ + '','','','','qu ','','','','','','Rong ','','Rong ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','fu ','','yu ','','','','', + '','','','','','','','','','','','','','','gao ','juan ', + '','','','','','quan ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','die ','','','','','','dai ','','su ','', + '','','','','jie ','','qu ','','han ','','','','','','','', + '','jie ','','','','juan ','','','','','dan ','','','','','', + '','','','','','hu ','','','','jue ','','yu ','','','','', + '','','','','','','','','','','','','','fu ','','', + '','Ban ','','','','','','','','','','','','','','', + '','','Cong ','Cong ','xun ','','','','','','','','','liu ','','', + '','','','Beng ','','','','jue ','','','','','','','','Von ', + ], + 'x224':[ + '','','','','yuan ','','','','','','','','','','Khom ','', + '','','','','','','','','','','','','','','cheng ','', + '','','','','','','','King ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','jiu ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','hu ','','','','','','', + '','','','','','','','','','','','','','','Bay ','', + '','','fu ','','chu ','','','','','','','','','','lan ','', + '','','','','','','','','','','','','','','','', + 'yu ','','','','','','','','','','','','','','jiao ','', + '','','','','','','','','','','','ang ','','','','', + '','','','','sa ','','','','','','','','ge ','','','', + '','','kua ','','','','','','','','','','xie ','','','', + '','','wu ,hu','','','xiu ','','','','','','','','','','', + ], + 'x225':[ + '','','yan ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','yu ','','','yu ','','','','','','','yu ','','','', + '','','liu ','','20832.030,yu ','','','','','','','','','','','', + '','','','','','shuai ','','','','','','yuan ','','','','', + '','shuai ','','','','','','','','','','','','','','ao ', + '','','','','','','','','','','jiao ','','sa ','xian ','zha ','dian ', + '','','','','','','','','San ','','','shan ','','','','', + 'Suot ','','','','','','','','tiao ','','','','','','','su ', + '','','','','','Sau ','Sau ','','','','','','','xian ','','', + '','yu ','','','','','jue ','nang ','','','','','','','','', + '','','','','','ru ','','','','','','','','','','', + '','','','','xia ','','','','','Nuoi ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','wu ','','','','','','','chang ','','Lo ','','','', + ], + 'x226':[ + '','','','','qiu ','Maau ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Rung ','Rap ','', + '','','','','','','','','Jiang ','','','','','','','', + '','wu ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Hung ','','','','','','','','','Nhon ','E ','Tim ','kan ','', + '','Lung6','','','','','','','','','','','','','','', + 'xian ','','','','','','ju ','','','','','miao ','','','','', + '','su ','','','','','Ti ','','','','','','','','','', + '','','','','','','','','','','hu ','','','','','', + '','','','','','','','','','Khuay ','','zhu ','Ngop ','','','', + '','','','qiu ','ya ','','','','','','','','','','bie ','', + '','','','','','','xiang ','','','','ru ','wang ','','','','ya ', + '','','','','','','','','yu ','','','','','','','', + '','','','','Mang ','Zang ','','','','','','','','','','', + ], + 'x227':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','Vung ','','','','','','','','', + '','','','','','','','','','','','Xing ','Duo ','','','', + '','','','','','','sao ','','Nao ','','','','','','','jia ', + 'tu ','','du ','','','','','','','','','','mao ','yao ','','', + '','','','','','','','','','Vui ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','wu ','Fit ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'hai ','','','','','','','','','','','','','','','gao ', + '','','','','','','fu ','','','','','','','liu ','','', + '','','','','','Fit ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Chua ','','Nan ','','','Nep ','','','Chac ','Cham ','','','','','','', + '','','','yang ','','','','','','','','','','','','', + 'ai ','teng ','','','','','','','','Nhuoc ','','','','','','', + ], + 'x228':[ + '','','','Geng6','Sung ','Thung ','','','','','','','','','','', + 'Ngo ','','','','','','','','','','','','','','','', + '','sao ','','','','Gan ','Hon ','','','Mo ','','shu ','','','','Lang ', + '','','fu ','Bie ','','Tang ','','xiang ','','','','','','dang ','','', + '','','dang ','','','','','','','','','','','ge ','yu ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'zhao ','','','','','','','','','','','','','','','', + '','','Ghet ','','Ngung ','','','','','','','','chang ','zhe ','','', + '','','su ','','','','','','','','kai ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Khan ','','', + 'Ngay ','','','','Quo ','','','','','','','','','','','ai ', + '','','','','','','','','','','','','','','','', + 'liu ','','','','','','','Khuay ','','','','','','','','', + '','','','','','','','','','Hung ','','','','','','chu ', + ], + 'x229':[ + '','sao ','','','','','','','','','','','','','','', + 'liu ','','','','','','','','meng ','','zhan ','','','Cham ','','', + '','','','','zhuang ','','','','','','','','','','','', + '','','','','','','','','','Goe ','','','','','','', + '','','teng ','zhu ','','','Lung ','','Lo ','','','','','','','', + '','','','','','','Trai ','','xie ','','jiao ','','','','Chong ','', + 'Sung ','','','','','','','','','','','','','','','', + '','','','','','','','Ngoi ','','','','','','','','', + '','','Laan ','','','','','','','','','','qu ','','qiu ','Zai ', + '','','','','','','','','','','hua ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','shu ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','han ','ge ','','','','','','','','', + '','','Ta ','','','','','','','','','','','','','', + ], + 'x22a':[ + '','','','','','','','','','','','','','','','jue ', + '','','','','','','','zei ','','','','','jie ','','','', + '','','','','','hu ','hu ','','','','','chu ','','','','', + '','','','','','','','','','','','','','','','', + '','ju ','','','zhu ','','','','','','Quanh ','','','','','', + '','','','ge ','','','','','','','','','Ho ','','','', + '','','shan ','','Muon ','','Zit ','Hat ','','','','','','Thuon ','Dat ','jue ', + '','','','','','','','','hai ','xia ','','','','','Chop ','', + '','','','cu ','','','','','','','','','','','','', + '','','','','','','','Vuc ','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Ngat ','Vat ','Nang ','','','','','Muc ','','','','','','','zhang ','', + '','','','Keo ','','That ','Vun ','','','','','','Tha ','','','Kam ', + 'jie ','','','','','Wing ','Trot ','','So ','','','','Trum ','Rung ','Quay ','', + '','','','Bac ','','','Haku ','','Ngung ','','','Lat ','','nu ','','', + 'zhe ','','','','','zu ','','','','','','nie ','','','','', + ], + 'x22b':[ + '','','','','Bung ','','','','','','','','','','','', + 'Muc ','','','','','','','Chui ','','','','','','','','', + '','','','Tay ','Khuong ','Giang ','','','','','','','','','Vot ','', + '','Khep ','','','','','','nan ','','','','','dun ','','','Xoi ', + '','','','Dau ','','','Chou ','','','','','','','','','', + '','Thuoc ','','','','','','','','','','','Xac ','','','', + '','','','','','bian ','','','','','','','','','','Quet ', + '','','','Giau ','Khuay ','','','Vom ','','Lan ','Dui ','Xoi ','','','','', + '','','','','','','','','','','ya ','','','','','bang ', + '','Luk ','','','','','','','','','','','','','sao ','', + '','','','','','','','','','Co ','Ron ','','Chut ','Co ','','', + '','','','','','','','','','','','','','','','Quay ', + '','','','','','lu ,jue','','','','xie ','Dik ','','zhai ','','Ngaau ','', + 'Co ','','','Va ','Quat ','Ngoi ','Khep ','Quay ','Huo ','','','Sap ','Buoc ','Ven ','','', + 'Va ','Roc ','Sua ','','','','Lay ','','','','','','','','yu ','', + '','Sau ','wan ','xue ','','','','','','ge ','','','','','mao ','', + ], + 'x22c':[ + '','','','','','','fu ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Wo ','','','','','Gap ','Zung ','pan ', + '','','','','jie ','','','','jia ','','','','jia ','','Boi ','', + 'Gieo ','Waa ','','','','Dap6','','','','Cai ','Phung ','Xoi ','','Nhot ','','Sin ', + '','','Saak ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Kek ','','','','','','','', + '','','','','Bung ','','','','','','','','','Run ','','', + '','Laa ','','Rung ','Cau ','','','Gay ','','Cap ','Mai ','Mo ','','','','', + '','Cau ','Sang ','','','Cao ','','Sou ','Lou ','','','','die ','','','zhu ', + '','','Bat ','','','','Ngao ','','zu ','','','','','','','', + '','lang ','','','','','','','','','','','Saai ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x22d':[ + '','','','','','','','Chap ','Daat ','','Chop ','Chong ','','','','', + 'Day ','','Phanh ','','','Ning ','','','Xay ','','','','Xau ','','Nhung ','', + '','','fen ','','','','','','','','','','ban ','','','', + '','lei ','xie ,jie','','','','','','','','','','','','','', + '','','','','Cou ','','','yang ','','','','','Dui ','','','', + '','','','Paang ','','','','','','','','','','','','', + '','','','','','zao ','','Dan ','','Doi ','','','Don ','','','', + '','Khoi ','','Sum ','Quay ','','Don ','Cat ','Xap ','','','','Vot ','Ro ','','', + '','','','','','Sip ','','','','','','','','Saap ','','', + '','Niao ','guai ','','','','','','','','','','Ngung ','','','Cui ', + 'Saau ','','','Die ','Loe ','','','','','','','','','','','Maan ', + '','','','','','','bang ','','Bum ','','Dom ','Bung ','Ngoi ','','','Don ', + '','Nem ','Xan ','','','Tro ','Chen ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','Ban ','','','','','','','','','','Dui ','', + '','','Hang ','','','Vo ','liu ','','','','du ','','','','','jie ', + ], + 'x22e':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','Lan ','','','', + '','','','Niao ','','cuan ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Choc ','Gai ','Mac ','Rung ','','Xe ','','','','','yu ', + '','Zaang6','','','','','','','','lan ','','','','','','', + '','','','Keo ','Xau ','','','','Tum ','Suong ','','','','','','', + '','','','xiao ','','','','','','','','','','Giam ','Que ','', + '','','','','','','','yao ','','ta ','','Naan ','','','','', + '','','Bung ','','Bau ','','','','','','','','','Uon ','','chan ', + '','','','','','','','','','','','','','','','', + '','','','Man ','yu ','','','','','Chia ','Chia ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','cheng ','','','','','','','','','hai ','','','', + '','','','','','','','','sa ','','','','','','jie ,fu','', + '','','','','','','','','','','','','','','','', + ], + 'x22f':[ + '','','','','','','','','','','','','bao ','','','', + '','','','','','','','','','','','','','','','', + '','','','qia ','','','','','','','','jiao ','','','','', + '','','','','','','','','','','xue ','','','','','', + '','','','','','','','da ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','mao ','','','','','','','','','','','jiu ','','', + '','','','','Duk ','','','','','','','','Va ','','','', + '','wei ','','','yu ','du ','','','','','cheng ','','','','','', + '','','kuai ','','','','','','','','','','','','','', + '','','','','','','','','','','','','lu ','','','', + '','','','','','','','','','','','','','','','wen ', + '','','meng ','','','','','','','','','','','','','', + '','','','','','','','','','','','','man ','','','', + '','xie ','luan ','','','','cheng ','cheng ','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x230':[ + 'lei ','','','','qun ','','','','','','','','','chen ','','cheng ', + '','','Chong ','','','','','','','','','','','','','Va ', + '','','','fu ','','','','san ','','','','','','','','sa ', + '','','','','','','','','','','','','','','fu ','', + '','','','','','','','','','','','','','dao ','','', + '','','','','Lon ','','gan ','tan ','','','','','man ','','','', + '','','','','','','','','','','','','','','','', + '','','','','qia ','','','','','','','','','','','', + '','','','','','','','','','','yun ','','','','','', + '','','','','','','','','','','','','','xiang ','','', + '','','','','','','','','','','','','xiao ','','','', + '','','','dang ','','zhuan ','','','','','','','','','','', + '','','','','','','','','','dang ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','yan ','', + ], + 'x231':[ + '','','','','','','','','','','','','','','fu ','', + '','','','','','','','','','Huang ','','','','yan ','','hu ', + '','','','','','','','','','','','','','','','', + '','','','','liang ','','','','','','wei ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Khuya ','Khuya ','','','','','','', + '','jue ','','','','','','','','','','','','','','', + 'xiang ','','','','','Tam ','Luc ','','','','','','','','','', + '','','','','','','','','','','','','','','','Phoi ', + 'Trua ','','xu ','','','xian ','','','','gan ','','','','','','', + '','','','','','','','hao ','','','','','','','Chang ','', + 'Giay ','','','','','fu ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','Sao ', + '','','Bie ','','','','','','dai ','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x232':[ + '','','','','','','','','','','mu ','','','die ','','', + '','','','Phoi ','','Mai ','','Ngay ','','','','Quat ','Ngay ','','Hong ','', + 'bian ','','Tia ','','','tu ','','','','','','','','','','', + 'Nau ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Ui ','Trua ','', + '','','','','','sang ','','ang ','nai ','','','','','','Gou ','', + '','','','','','','','','','ya ','','','','','','', + '','','','','','Rua ','','','','','','','','','','', + '','','','mao ','','','','','','','','Se ','','Mo ','Chop ','', + '','','','','meng ','','','','','','','','','sang ','xu ','kan ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Bay ','', + 'Sao ','Toi ','','','','','','','','yu ','dan ','','','','','pu ', + '','','','','','','','','','','','','','','ai ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Som ','','', + ], + 'x233':[ + '','Trua ','Trua ','','','','Trua ','','','Khuya ','','Som ','Rua ','','','de ', + '','','','','','','','','','','','','','Nang ','','', + 'chun ','','','','','','','','xun ','','','','','','','', + '','','','','','','','','','','Xeo ','','','','','', + 'Nguc ','','','','','','','ju ','','','','Cui ','','Oam ','','cha ', + '','','','','','','','','','','','yu ','','','','', + '','','','','','','kuang ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','Luo ','','','','','','','','','', + '','','','','nian ','','','','','','hu ','','','','Trang ','', + '','','','','','','','','','','','','','','','', + '','','','','Dun ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','shu ','','','','','','','','pai ', + '','','','','','','','','','','','','','','','', + '','','','','Jan ','','','he ','','','','','','','Zai ','Then ', + ], + 'x234':[ + '','','','','','Nhum ','Thot ','','','','','','','','','', + '','','','','','','','','','','','','','Xop ','','', + '','','','','','','','','','','','','','','','', + '','','Queo ','','','','','','','','han ','','','','','', + '','Cung ','hu ','','','','','','','','','','','','Roi ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','Gian ','','','Sim ','','','','Nen ','','','','fu ', + '','','dian ','','','','qiao ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Mang ','','','','','','','','','','','','', + '','Xoai ','Sao ','Cong ','','','','han ','kuang ','','','','','','','', + '','','','','','','','','','sha ,jie','','','Gou ','','','', + '','','shan ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','Lau ', + ], + 'x235':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Cui ','Bap ', + '','Pha ','Xoi ','Ngoc ','','Chanh ','Nhai ','','Kang ','','','','','','','', + '','','','','','','','','','','mao ','','Gon ','','','', + '','','','yu ','','pao ','','','','','','','','','','', + '','','','','','','','','Hay ','','','','','','','', + '','','','','','','','','','','','','Noc ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','yun ','','','','','','','','','', + '','','','','','Peng ','Chay ','Chay ','','','Ca ','','','','','', + 'Suot ','Trac ','','ju ','','','','','','','qu ','','jue ','','ang ','', + '','','','','','','','','','ru ','','','xun ','','','', + '','','','','','','','','','','','','','','','', + 'reng ','','','Chua ','','','','','','','','','','','','', + '','','','','','','','','','','Cha ','','','','','', + '','','','','','','ta ','','','yang ','','','','','Son ','', + ], + 'x236':[ + '','Ca ','','Cay ','Thot ','','','','Son ','Cum ','','','','','','', + '','','','','','','','Nik ','','bang ','Seot ','','','','','', + '','','','chun ','','','Yi ','','','','','','','','','', + '','','','','','','','','','','','','','Nau ','Vai ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','Rac ','','','','','','', + '','','juan ','','','','','','','','Mo ','Sop ','','','Chay ','Rui ', + '','','','','jie ','zhe ','hu ','','Sot ','Con ','Mam ','','','','','', + '','','','jie ','','','','pao ','','','','ye ','','','lei ','', + 'ru ','','','juan ','','Jaap ','','','','','','','','','','', + '','','zhuan ','','','','jiang ','hao ','','','dun ','','','','','', + '','','','','','','','','','','Hong ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','Xanh ', + '','Gu ','','Khay ','','Be ','','','','Then ','Tu ','hu ','','','','', + '','Dom ','','','','','','','ze ','','','die ','','zha ','','', + ], + 'x237':[ + '','','sa ','','','','','','','','','Mo ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','juan ','','','','ai ','','','', + 'Lim ','Son ','','','','','','','','','wen ','','','','Chua ','', + '','','hun ','','','ai ','','','','Duoi ','','ta ','','','','gao ', + '','yu ,yu','','','','','','hu ','','','','','10389.190,bian ','su ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Khu ','Cuoi ','','','dun ','','','','','','','Tram ','', + '','meng ','','lu ','tan ','','','liu ','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'lian ','','','','','','','','','','','','','','','', + '','','','Mong ','','','','xiao ','','huai ','','','','','','', + '','liu ','wu ','','','','','','','','','','','','','', + '','','','','','','','','','Dui ','','','Ran ','','','', + 'yu ','Kyo ','','','','','','','mei ','','lian ','','','lao ','','', + ], + 'x238':[ + '','','','','','','','','','','','','','','','', + '','','Tham ','Pheo ','','Chua ','Chua ','Que ','Gau ','','liu ','','zhao ','','','', + '','','','','','','','','','Tram ','','','','','','', + '','Tram ','','','','','','','','','','','','Ha ','','', + '','','','','','','','','','yu ','','','','','cen ','', + '','','','Tram ','','yan ','','','','','','','','Vui ','','die ', + '','','','','Nen ','','','lei ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','xu ','','','','','', + '','','yu ','','','','qian ','','','','','','','','','', + '','','','','','dian ','','','','','','','','','','', + 'zu ','','','','','','chu ','','','','','','','','','', + '','','','','','','','','dian ','','','','','','yu ','', + '','','','','','','','','','','an ','','','','hun ','', + '','','','dian ','','','','','','','','','','','sha ','', + '','','xie ','','da ','','','','','','sha ','','','','','', + ], + 'x239':[ + '','zhu ','','','','','','','ze ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','shu ', + '','','','','','','','','','','','','','','','', + '','','ta ','wan ','','','','','','','wang ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','guan ','','','','','','','','','','', + '','','','tu ','','','','ta ','','chu ','','','zhu ','','da ','', + '','','','','','','','','','','','','','Ngay ','','', + '','','','','','','','','','','','','','','','', + 'chu ','chu ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Laai ','du ','','','','','die ','','','','','','','', + '','','','','','','','','','bai ','','dian ','','qiu ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','nao ','','', + ], + 'x23a':[ + 'luan ','','die ','','qia ','','','mao ','','','','','','','','', + '','','','wu ','tao ','','','','','','','zu ','ma ','','','', + '','','','jiang ','xu ','','','Giuoc ','','','','','','Quan ','','', + '','','du ','xiang ','','','','','','','','','','','','hun ', + '','','','','','','','','','','','','','','','lu ', + '','','','','guan ','','','','','','er ','','','','','', + '','','liao ','','','','Ngoeo ','shan ','','','','','','zhai ','','ye ', + 'diao ','','','','jiang ','','','','Toi ','huai ','yu ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Ji ','','','','','','','','','','dian ','','','bian ','','', + '','','','','','','','','gu ','','','','','','','', + '','','','','','','','','hu ','','','','','','su ','', + '','','','','','','','','','','','','dao ','','','', + '','','','','','','','','','','','','','','','', + '','','','','xie ','','','Van ','','dai ','','','','','','', + ], + 'x23b':[ + '','','guan ','','','','pei ','','','','','','','','jue ','juan ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','ba ','ba ','','','','','','wu ','','', + 'bao ','','','Su ','','','','','','','','','','','','', + '','','','','','','','','fu ','','','','','ge ','','', + 'ru ','','','','','','','','','','','','','','','Ria ', + 'Mao ','','','qiu ,qu','','','','','','','','Mau ','','','','', + '','','','','','','','Ngu ','','','de ','','jie ','jie ','','', + '','','','','','','','','','','','','','','','', + 'san ','','chun ','','','','nai ','','','','','','','','','', + 'de ','','','','','','','','','','','','','','','', + 'mao ','','','','','','','','','','','ru ','','','wu ','', + '','','','','','','','','','','ta ','','','','','', + '','','','','','','','','','men ','','','','','','', + '','pei ','','','','','','','qu ','','','','su ','','','', + ], + 'x23c':[ + '','','','','','','','','','','','qu ','','','','', + '','','','','','sao ','','','kun ','','','','','','jie ','', + 'qu ','qu ','','','','meng ','','','','','','','du ','','','', + '','','','','','','','','','','','qu ','','','','', + '','','kun ','','','','Ho ','','','','','','','dan ','','', + '','','','xiao ,hao','','','','','','','','','','','','', + '','','','','','','','','','','','','Hoi ','','','', + 'Ram ','','','liu ','','','Vuc ','','','','','','','','','Nhop ', + '','','','','','','','','','','','','','Ngut ','','', + '','','','','','','','','','','','','','','','', + 'Ngot ','','','','','','','','','','','','','','','', + '','','he ','','','','','Nap6','','','','','','','guai ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','fan ','','','jie ', + '','','','','zhan ','','','','Deoi ','','','','','piao ','','', + '','','','','','','','','','','','','Doe ','','','', + ], + 'x23d':[ + '','','','','','','','','','','','','','','','', + '','','','jian ','','','','','','','Hup ','Nhung ','','','','', + '','','zao ','zhuang ','','','','','','','','','','','','', + '','','','','','','','','','','','','mao ','tan ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Bung ','', + '','','','','Ngam ','','','','zhu ','','','','gan ','','','', + '','','','','','','','','','','','','','zhuang ','','', + 'pao ','','','','','','','','su ','','','','','ju ','','', + '','can ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Loi ','', + 'Nhom ','','','','','','','','','','','','','','','', + ], + 'x23e':[ + '','','','xu ','','','','bian ','','','','','','','huai ','', + '','','','','','','','','','','she ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','fu ','','','','', + '','','','','','Lut ','','Tran ','','','','','','qiao ,xiao','','Cong ', + '','','','','','qian ','','','','xie ','','','hu ','','','xun ', + '','','','','','na ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','tao ','', + 'qiao ','','','','','','','','','','','','','','','', + 'Nuot ','','','Bui ','','','','Xoi ','','Duoi ','','','','dang ,xiang','','', + '','','','','','Ma ','','','','','shu ','','fu ','','','', + 'xie ','lang ','','','','','','','','zhe ','','','can ','','','', + '','','','','','','','','','','','','','','','', + ], + 'x23f':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','lu ', + '','','','','','','ze ','shuai ','','','Bot ','','','','','Vui ', + 'Lung ','Ngau ','Doi ','Xop ','','','','Lot ','','','','','Tran ','Lang ','','', + 'Ngau ','','','','','','Veo ','','','ru ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','an ','jian ','','53066.030,teng ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','Doi ','','','','Khoi ','','','Xoi ','Bui ','', + '','','','Ngau ','','','fu ','','su ','','lian ','','he ','','','', + 'ze ','','','','','','','','','','','','','','','', + '','','','xiao ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x240':[ + '','','','','','','','','','han ','','','','','','', + '','','','Loc ','','','Ngoi ','Rua ','Vung ','','','','Tanh ','yu ','','', + '','','','','','','la ','','','jian ','','','','','','', + '','','bian ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Dao ','Khoi ','','','','Trong ','Bot ','','Chua ','','','','', + 'Dao ','dan ','jie ','bai ','','','xian ','','','','','','','','','', + '','cai ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','zhuan ','','','','','Rua ','Dan ','Phun ','Loi ','Toe ','','', + '','','','','','','','','','','lan ','','yao ','','','xuan ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','Leo ','','Muong ','', + '','','','','','','','Thuot ','lan ','','','','','','','', + '','','','','','','Deng ','','','','xun ','','','','','', + ], + 'x241':[ + '','','','','','','','','','','','','','','','', + '','fan ','','','','','','','','','','','','','','', + '','','','','','ta ','','pan ','','','','','','','','Trong ', + 'Nhan ','','Can ','','','','','','','','','','','','','', + '','','','','','','','','','','yan ','','','','man ','', + '','','can ','','','','','','','','','','Veo ','','','', + '','','','men ','','','','','','','','','','','','', + '','','shuan ','','','','','','','','','','','','','', + '','cheng ','','','','','','','','','','','','Chi ','','', + '','','','','','','','','','','','','gua ','','xu ','', + '','','','Saap6','','','','','','','','','','','','', + '','','','','','','','','Tom ','','','','','','','', + '','','','','','','','','','','','','Kho ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','Say ','Phoi ','Tat ','','','','','Bep ','', + '','','Nhum ','','','','','','','','','','','','Ying ','', + ], + 'x242':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Lui ','', + 'Sot ','Ngut ','','','','','','he ','','','Cho ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','lao ','shao ','', + '','','','Tro ','','Tro ','Se ','Heo ','Ngun ','','','Toa ','Rang ','','','', + '','','','','','','','','fu ','','','kai ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Luoc ','','','','','','','','','','','','','', + 'Roi ','','','Tro ','Nhem ','','','','','Rom ','','Phoi ','Phoi ','Lom ','','', + 'Ben ','','','','','','la ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'zhu ','','','','','','Ranh ','Nau ','Khet ','Kho ','','Phoi ','Kho ','Choi ','Um ','', + ], + 'x243':[ + '','','su ','','','','','','','','','','','Hok ','','', + 'han ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','gan ','','','','','','', + '','','','Hay ','','','Ngot ','Nau ','','Ngun ','','','','','','', + '','Chong ','','shu ','','Jau ','','','','','','','zao ','','','', + 'Jit6','','','','Zhang ','','','','','','','','','','','', + '','','','','','','Loa ','','','','','','','','','', + '','','','','','','','','','','','','','Quac ','','', + '','','Phap ','','','Tat ','','','','','','Ram ','','','','', + '','','','','','','','zhu ','','','','','','','','', + '','Zuan ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Nhoi ','','Ho ','Thui ','Khet ','Thap ','Se ','','Rao ','Buot ','','','','', + '','chu ','Zhou ','','','','','','','','','','','','','', + ], + 'x244':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','Ham ','Nau ','','Soi ','','', + 'Luoc ','','','','','','','','','kai ','','','','','','', + '','','cuan ','','','','','','','','','','','','','', + '','','','xian ','','','','','Chang ','','','','','Hung ','','', + '','','','','','Xun ','','','','','','','','','','', + '','','','','','','','','','','','Bung ','Loe ','','','Sem ', + '','','','','','','','ye ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','Nung ','Nau ','','yao ','','Nhui ', + '','','Lom ','','','','Sem ','','','','','','','','','', + '','','','','Thap ','','','','','','','ta ','','','','', + '','','','','','','Ram ','','','','','','','','','', + '','','','Lo ','','','','','','','','','','','','', + '','','','','','','','','','Ben ','','','','','','', + '','','','','','','','','','','Vau ','','','','dao ','', + ], + 'x245':[ + '','','','','','','','','','','','ju ','','','','', + '','','','','','','','','','','shang ','Su ','','','','', + '','','','bao ','','','','','','','','','','','','Vuot ', + '','','','','','','','Danh ','','','','','','','','', + '','','','','','','','','','','shen ','','','','','', + '','','','','Cha ','','','','','','','','','','zhu ','', + '','','','','','','','','','','','','','Jiang ','','Jiang ', + '','','','','','','','diao ','','','','','','','','', + '','','','','','','zhan ','','','','','','','','','', + '','','die ','ze ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','he ','','','','ju ','','','','Lop ','','','','xiang ','','', + '','cu ','','','','','Mui ','','Sip ','','','','','','','pei ', + '','','','cheng ','','','','','','','','lian ','','','','', + '','','','','','','','','die ','','shu ','','','','','', + '','','Tam ','','','pu ','','','','Phuon ','','chan ','','','','', + ], + 'x246':[ + 'dao ','','','','','','','','','','','Nga ','','','','', + '','','','Nanh ','hu ','','','','','','','chun ','','','','', + 'tian ','','','chen ','','','','','','','','','','','','', + '','','zhuang ','','','hu ','','shu ','','','','','','','','', + '','','','','','bai ','','','','','','','','','','qu ', + '','','xie ','','zhao ','','','','','','','tu ','','','','', + '','','','','','','','','','','','','','','Ngau ','', + '','','','','Caau ','','','','','','','','','','','', + '','','','','','mu ','','Nghe ','','','die ','','','','yu ','', + '','','','','','','','','','','du ','','','','','', + '','du ','','','mei ','','Co ','Sao ','','','','','','','','xiu ', + '','','','','','bu ','','','','','','','','','','', + '','','','','','','','Chan ','','','','','','','','', + '','','','','','','','','','','','','','su ','Nghe ','', + 'Trau ','','ceng ','ta ','','','jue ','xun ','','','','','','qun ','','', + '','','','','','','','','','','','','','','','', + ], + 'x247':[ + '','','','','huai ','','','zhan ','','','','','','','','', + '','','','','ju ','ba ','lei ','','','','','','','','','', + '','','','','zhe ','','','','','','','','San ','Tu ','','Cop ', + '','','','','','21335.010,yan ','','hu ','','yu ','','','','','','', + '','','mu ','','','','','','','','','','','','','', + 'hao ','Muop ','na ','','','','','','hu ','','','','','','Chuot ','', + '','','','','','','','bao ','','','','','','','lu ','', + '','','','','','','','','','Chu ','','','','','','', + '','','','','','','','','','shu ','','','','','','', + '','','','San ','Thac ','Tay ','','','','','','zang ','','','yu ','', + 'cha ','xie ','','','','','Moi ','Khon ','','','','','','','','', + 'qiu ','','hu ','zai ','jue ','','han ','','','','','Hum ','','','','an ', + 'zao ','','','sha ','','xian ','','','','an ','','','','zhe ','jue ','', + '','','','','','','','','lu ','','','','','xia ','xiao ','', + '','','dun ','','','','','','','','tu ','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x248':[ + '','','','','Ga ','Voi ','','ge ','','','','Trau ','','','','', + 'ta ','Lau ','','','','','','','','','su ','','','','','ta ', + '','','','','','','','','','','fu ','','','','','', + 'Gau ','','','','','','','','','','','','','cu ','','', + '','','','su ','','','','','','','','','','','','', + '','','','','','','','','','','','Nanh ','','','','huan ', + '','','','','','','','','','','','','','','Ran ','', + '','','','','','','xu ','','','','','','','','','', + '','huan ','su ','','','','','Vuot ','San ','','lu ','','','','','', + '','','','ju ,qu','Nhen ','Dou ','','','su ','','','','','','','ze ', + '','','','','','','','','','','Lie ','','','','','', + '','','','','','ai ','','','','','xie ','','','Nhat ','','', + '','','','','Beo ','','','','','','','','xiao ','','','', + '','xie ','','','','','','','','','','','','','','', + '','Doc ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x249':[ + '','','','','','','','','','','da ','','','','','', + 'su ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','wai ','','','','', + 'Vua ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','su ','','','liu ','','','','','','','','', + '','','','','','','','','','','','','','Xa ','','', + 'mao ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','Cung ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','yu ','Cong ','','','','','', + '','','','jian ','','','','','','wan ','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x24a':[ + '','','','','','','','','','','','','','lu ','qu ','', + '','','','','','','hu ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','zhuan ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','hao ','xiang ','','','hao ','','', + '','dian ,tian','ge ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','chan ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','qia ','jiao ','','','','','','','','Dua ', + ], + 'x24b':[ + 'Dua ','','','','','','','','Hau ','','','','','','','', + '','','','','','','','','','','','Lu ','','yan ','','', + '','','','','','','wa ','zu ','fan ','','','','','','','', + '','xu ','','','','','','na ','Sanh ','','','','','','','', + '','','','','','','','','diao ','','','','','fan ','','', + '','wu ','','','','','','','','','','','','','','fu ', + 'na ','','','','','','','','','','','','','','','', + '','hu ','','','su ','','','','','','','','','xu ','','', + '','','','Ang ','','','','','','','','','','','lei ','heng ', + '','Be ','','','','','','Lo ','','','lei ','','shan ','','','', + 'Muong ','','','','','','','lu ','Lung ','','jun ','','','Chan ','','xie ', + '','zhe ','','','','','','liu ','lei ','','','','dai ','','Ngot ','Ngot ', + '','','','','','','Ngon ','','','','','','','','','', + '','Lam ','','','','','','','','','','','','','','', + '','','','','','','','','Song ','Song ','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x24c':[ + '','','','','','','','','','','','','','','','', + '','pu ','','','','','','','','','','','','','','hang ', + '','','','','','','zha ','','','','','','chao ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','na ','na ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','diao ','','','','','','', + '','','','','','','','xie ','','','','','','fu ','','', + '','','Duoi ','','','','','','','','','','Ruong ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','juan ','','','','','','','', + 'mao ','','','','','','','','','','','','','','','', + '','','','','','cha ','Trai ','Trai ','','han ','','','','','','', + '','','','','','yu ','','','','','','','','','','', + '','','Trong ','','','','','','Roc ','','','','','','','zhu ', + 'Ve ','Ruong ','','','lei ','','','','','','','','','Ruong ','','', + ], + 'x24d':[ + '','','','','','','','','','','','','','die ','','', + '','','','','','','','','','','','','','','','', + '','','','','','Ngat ','','','','','','','','Bot ','','huan ', + '','du ','','','','','','','','','','','','','','', + '','','','','','','','','','','du ','','','','','', + 'wu ','','wen ','','','','','','','','To ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','Si ','','','qia ','','','','hai ','','', + '','','','','','','','','Tay ','','','','','','Chau ','', + '','Nhan ','Ben ','','','tun ','fu ','','','','','','zhuang ','','','', + '','','','','','','','','','','','','','','du ','', + '','chuan ','','','','','','','Naa ','Guoc ','','Nghen ','Mang ','Mut ','','', + '','','fei ','jian ','','','','Wak6','','','','','','','','', + '','jiu ','','','lun ','','','','dao ','de ','','','','','','la ', + '','','ju ','','','','','','','','Mang ','Cek ','','','','Loet ', + '','','','Nhom ','','','Buou ','','','wai ','','','','','','', + ], + 'x24e':[ + '','','','','','','','','','','dai ','','','','','', + '','fu ','Ngung ','','','','','fu ','','','','','','','','', + '','','','','','','','Hoen ','','','','yun ','','','su ','', + '','','','','','bu ','','qun ','','','','Naa ','','','','', + '','','','','','','','','','','','jue ','','','','', + 'Lit ','','','','','','Hen ','','Nhoc ','Choc ','','chen ','','','','', + '','','','hu ','teng ','','','','lian ','','','','','','','', + '','','','','','','','','','','','','Buou ','Not ','','Ngo ', + '','','','','','','','bian ','','','','','','','','', + '','','','Bie ','','','','','','','','','','','','', + '','','','','','','','Zang ','','','shan ','','','Buot ','Gua ','Mun ', + 'Khom ','','','','Buou ','','','','','','','juan ','lu ','','ao ','', + '','','','','','','','','','','','','','','Cum ','', + 'Hom ','','Toi ','','','','','','','','','','','','','', + '','','ai ','','','','','','','','','Nhoi ','','','','', + '','lu ','','','','','bian ','','','','','','','','','', + ], + 'x24f':[ + '','meng ','','','','','','','','','','chan ','','','','', + 'guan ,huan','','','','','','','jue ','lei ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','ju ','','','','','Dang ','','','','','','','', + '','','','','','huan ','','','','','','','','','','', + '','','','er ','','huan ','','Nguoi ','','','','','','','','', + '','','','chang ','','','','','','','','','','','','', + '','zu ','','','','Phau ','','','Trang ','bai ','lu ','','','','','nian ', + '','','','','zhu ','hu ','','','','','','','','','','', + '','','','Tram ','Vang ','','','','','','','miao ','','','','Ho ', + '','','','','','','','','','','','yao ','','','','', + 'Nguoi ','','','','','bie ','','','','','','','','','','', + '','','Saai ','','cun ','','','','','','','','','','Pi ','nan ', + '','','','','','','','wa ','','','','','','','','xun ', + '','','','cheng ','','','Da ','han ','xiao ','','Zaap ','','','','','', + 'Trong ','','','','lu ','','','','','','','','','ta ','','', + ], + 'x250':[ + '','du ','','','','','','','','','','','Giay ','','','', + '','','','liu ','lu ','','','','','','','','','','','', + '','','','xue ,qiao','','la ','','','','','','','Jim ','','','', + 'la ','','du ','Mo ','','lu ','','','','','','','','','xiang ','', + '','','jie ','mang ','','','','','','','','','','','','', + '','','Ngaau ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','diao ','', + '','','','','','','','','','','','','','','','', + '','Jim ','','ju ','','','','','','Trom ','','tu ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','hu ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'cha ','','','','','','','','','','','','','','','', + '','Mam ','','','qu ','','','','','','Mam ','Mam ','','','','', + '','','','','','','','','Vuc ','','','','','','','', + '','Nhap ','','','','fan ','','','','chuan ','yao ','','','','du ','', + ], + 'x251':[ + '','meng ','','','','','','','mu ','','','','','','Cik ','', + '','fu ','','','','','','','','','','','','mian ','','', + '','','','','','','','','','','','Gap6','','','Nham ','Ngom ', + 'Nhon ','','mie ','','Xue ','xu ,yu','','','','bao ','','','','','','', + '','','','Nhon ','','','','','Laap ','','','','','','','', + '','dian ','fan ','','','','','','','','','','','','','Ngaau ', + 'Hau ','er ','','','','','','','','','','','','','','', + '','','Chau ','','','wei ','','','','','xu ','','','','Zong ','', + 'Giuong ','','','Nho ','','','','','','yu ','','','jue ','','','', + '','','','','','','','','','','','xu ','wang ','','juan ','', + '','','','','','xie ','liu ','','','','','','','','','', + '','','nao ','','','','wan ','jiu ','','Ngop ','Dau ','Ru ','Le ','','','Quau ', + 'Mang ','Tro ','Bet ','','','','','','Nhon ','','','','han ,qia','','','xu ', + '','','jie ','','','','','','jun ','','','','','','dian ','', + '','','','Gwat6','','','','','','','','','','','','mai ', + '','','','','','','Him ','','','','','Tro ','','','','xu ', + ], + 'x252':[ + '','','','','chuang ','','mao ','','','huan ','sha ','','','','','kuang ', + '','','','','','','die ','','','la ','','lu ','','','','Sou ', + '','','','','','','','','','','','','','','leng ','', + '','','Ngap ','Chot ','Nguoc ','Nhon ','Nom ','','','','','','','','','', + 'guan ','ju ','','nai ','','ge ','','','','','ma ','teng ','','','','', + '','','','','','','','','','','','','chen ','','','', + '','','','','','','','','','','','','Let ','','Soc ','', + 'han ,qia','','','','','Ma ','lu ','','','','die ','','','','','', + 'Xam ','','','','','','','','','','xu ','','Caau ','','','', + '','','','chan ','','','','','Ghe ','Zong ','','','','Chop ','Quac ','Nhan ', + '','','','','Nguoi ','','Mu ','','','','','guan ','','zun ','','xie ', + '','','','','Toet ','','','','','','','','','','','', + '','','','','','','','Caang ','','','','','Sa ','','','', + '','','Tre ','','','Trom ','','','Saau ','','','','','','','Xi ', + '','','','jia ','','','','','','','','','','','','', + '','','Lem ','Coi ','Ngam ','Him ','Lam ','','Soi ','','','','','','','', + ], + 'x253':[ + 'Xet ','','','','','','','','Trom ','','pan ','','','','','', + 'liu ','','','','','','','','','','','Lai6','','','','', + '','','','','','Khoe ','Len ','','','','','','','xuan ','','meng ', + 'wei ','42521.120,meng ','','','','','','','Dim ','Ngam ','yao ','','','','','', + '','','','','','','','','','','','','','Lom ','','', + '','','Cham ','','lei ','','','','Nheo ','','bian ','Ngom ','','','','', + '','','','hao ','','','','','','','zhai ','','','','','', + '','ze ','na ','','','','','','','','','','','','','', + '','','','','','','kai ','','wu ','','','','','ze ','','', + 'yu ','zan ','','','','xu ','','xu ','','','','','','','','', + '','','cuan ','cuan ','cuan ','','','','','','','','','','','', + '','','','','','','','','qia ','','tiao ','','','','','', + '','','','','','','','huan ','','','','','','','','', + '','','wu ','','','','','','jue ','','','','','ya ','','', + '','','','','kua ','','','','','','','','','','an ','zhe ', + '','','','','','','','','','','','','','','','Van ', + ], + 'x254':[ + '','pu ','','','','','Van ','Ngan ','So ','Ngan ','','','','Ngan ','','Coc ', + '','','Cut ','','Van ','ya ','','','Shi ','','','','','','Mong ','', + '','','','','','','','','','yun ','','','','','','', + '','','','','','','','','','','','','','zhe ','','hu ', + '','','Chai ','','','','','die ','','','','guai ','','','','', + '','ao ','','','','','','','','','','','','','','', + '','','bu ','','','Sinh ','','','','','Nao ','','','','','du ', + 'guai ','','Ran ','','','','Loi ','','','','','','dian ','','','', + 'wu ','','','','','','','','','','','','','','','', + '','','','','','','','','xun ','','','','','','','', + '','','','','','','','ya ','lu ','','','','','chu ','','', + '','','','kang ','','','hua ','','','','','','','','','', + '','','','','Mai ','','','','','Sanh ','','','','du ','','', + 'jie ','','xian ,kan','','','','','','','','','','','','','', + '','','','','','','','','','','','','dao ','','','', + '','','','','Mai ','','','Canh ','','','','','','','','Tuo ', + ], + 'x255':[ + 'Gwang ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','yu ','','','','','','','','','','','','','', + '','shan ','','','','Ji ','','','','','','','','','','Ham ', + '','','','','Mai ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','zhe ','','','','','','','','','','','','', + '','','jue ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','la ','','', + '','','Quanh ','','','','','','','','','','','','','', + '','','','','','','','','zao ','Cuoi ','','','','','','', + '','','','','','','','','','','','','','','','du ', + '','','','','','','','','','','','','','','','', + '','','','ta ','','','','','','','dao ','','Chen ','','','', + '','','','','','','','','Nen ','','','qu ','','ca ','','', + '','','','','','xiang ','','','','','lan ','','','','','', + ], + 'x256':[ + '','','','','yu ','','','','','','jiao ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','fu ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Rung ','','','','','','','','','','','','', + '','','','xun ','','','ru ','','','Lay ','','','','','','', + '','','','','','','','','','','','','','','','yu ', + '','','jun ','','','','','','','','lu ','','','','','', + '','','','','','','','','','','','','','','','', + 'zhun ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','liu ','','','','','','','','','','', + '','nu ','','','','','','','','','','','','feng ','lu ','', + '','','','','','zhuan ','','zhe ','','','lu ','','','','','jue ', + 'liao ','','','','','','','','','','','','','','','', + ], + 'x257':[ + '','','','','','','','','','','','','Ao ','','','', + '','','Yan ','','','','','','','zan ','','','','','','', + '','','','','','Yi ','','','','','','','','','jun ','', + '','','','','','','','','','','','','','','','', + 'she ','','','','wan ','','','','','','','','','','','', + '','','gua ','','jie ','','he ,xie','','','','','','','','','du ', + '','','Li ','','','jie ','','ba ','yu ','','','','','','','', + '','','','','','','','','he ','','','','','Cay ','du ,zha','', + '','','','','he ','','','','','','','','','he ','','zhu ', + '','','','','','','Giong ','','zun ','','ru ','Duo ','jiang ','','','', + '','','','','','','','heng ','','','','','','','','zu ', + '','','','','ku ','','','','','','','','','','','', + '','','','he ','','','','','','','','','','','','', + '','','','','','','','','','','chang ','','','','','', + '','','','','','','','','','','mao ','','','','','', + '','','','','','','','','','Lui ','','','Bap ','','','', + ], + 'x258':[ + '','','','','','huan ','','','','','','','','','','', + '','','','','','','','','','','','','yang ','','','', + '','','','','','','','','','','','','Trau ','Giong ','Rom ','Rom ', + '','','','','chang ','','','liu ','','jie ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','jun ','jiao ','','','','','','','','','','','', + '','','','','Ji ','','','','','','','','','ai ','','', + '','','','Nanh ','Mam ','','','','','','','','','','zun ','', + 'Cau ','','','','','','','','','','','','','','','hu ', + '','','','','','','','','','','','','','','','', + '','','cheng ','','','','kuai ','','ge ','xie ','','jie ','','','','', + '','','','','','','zu ','','pu ','','','','','','','', + '','','','','','','','','','','','meng ','','','','xiang ', + '','','','','lu ','','','','','','','','','','','', + '','','','','','','','','mu ','ran ','','','','','','', + ], + 'x259':[ + '','','','','','','','','','','','zhe ','','','','', + '','','','','','','','','jue ','','','','','','','', + '','','','','','','ai ','','nu ','','','','','','','', + '','','','','','mian ','','','','','','','','','','', + '','','','','','Lung ','','','','','','','','','','', + '','','','','','','','','','','','','','','','wa ', + '','','','','','','','','','','','','','','','', + '','cheng ','','','','yang ','','','','liu ','','','','qiu ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','fu ','','','','','','qia ','dian ', + '','','jiao ','','','','','','','','','','','','','', + '','','','','','','xian ','','','','','','','','','', + '','','','','','','','','','','','','','','Hang ','', + '','','','','','liu ','','','','','','','','','','', + '','','','tu ','','','','','','Nup ','','','','','zhe ','', + 'hua ','','','','','','','fu ','','Tam ','','qu ','','','','', + ], + 'x25a':[ + '','','','','','','','','','','','','liu ','fu ','dan ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Trong ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','Hoam ','','Chui ','','','','','','', + '','','','','','','','','','','','','','ca ','','', + '','','','zhu ','hai ','','','','','','','','','','','', + '','','Hai ','','','','','','','','','','','','','', + '','','','','','','','','','','','fu ','','','','', + '','','','','','','','','','','fu ','','','Trong ','Trong ','', + '','','','','','','','','','','','','','','','', + '','cu ','','','pang ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','dun ','','','', + 'lu ','Deon6','','','','','','','','chen ','','','huang ','shi ','','', + ], + 'x25b':[ + '','','','','','','','','','','','','','','','', + '','','','yao ','','','','','','ju ','','','','','','', + '','','','','','','','','Khau ','Nia ','','','','','Giang ','Kao ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Mang ','Mau ', + '','qiu ','dun ','','','','','','','','mang ','','','miao ','yuan ','', + 'wu ','','','','','','','','','','','','fei ','','meng ','', + '','','','','','','Mang ','','','','','','','','','', + '','','','','','','','Buong ','Hum ','Bu ','','','','','','', + '','','','','','hang ','','ju ','nian ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','Manh ','Tre ','Mui ','','', + '','','Toi ','Trum ','','dang ','du ','','ye ','','','','','','','pai ', + '','','','','','','jian ,sha','','','','Trau ','','','','yu ','', + '','','','','','','','','zhu ','','','','','','','', + ], + 'x25c':[ + '','','','','','','','','','','Thap ','','','','','', + '','','','','','','','','','','','fu ','','','','', + '','','shan ','liu ','','','','','','','hu ','','','','','', + '','','','xian ','','','','','','','','mu ','','','zhai ','', + '','','nu ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Ro ','','','','Ghi ','Gianh ','','', + '','','','','','','','','','','','','','juan ','','', + '','','','','dan ','','','dan ','','hu ','','','','','lu ','chuan ', + 'wu ','','','','','','','du ','','','shuang ','fu ','ju ','','','diao ', + 'wang ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','fu ','','','','','','xun ','','', + 'Khay ','','','','','','bu ','','','','','','','','','', + '','fen ','dian ','','','','','','','','suan ','','an ','','','', + '','','du ','','','','','','dan ','','','','','','','', + ], + 'x25d':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','Thung ','Mui ','','','','','','','', + '','','','','','','','','ai ','ge ','ju ','tun ,dian','','qia ','','', + '','jian ','','','','suan ','','','','','','qiang ','','','','', + '','','','','','','','','','','','','','','','dian ', + '','','','','','','Toi ','Hom ','Ray ','','Lak6','Nong ','','','jie ','zhu ', + '','','','','zhao ','','','','','','','','','','','sa ', + '','','','','','','','','','','','','','','','Mung ', + 'Thung ','','Gay ','','','liu ','','','','','','','','','','', + '','','','','','','','','','','','','hu ','','','', + '','','','','','','','','','','','','','','Toi ','', + '','','','','','','','','','','die ','','','','','', + '','ban ','','','','','hu ','','','','','','','','','', + '','','','','yu ','die ','','','','','','','','','yu ','', + '','','','','','','','','','','','','','','','', + '','fu ','','','','','','','','','Mo ','May ','cu ','','','', + ], + 'x25e':[ + '','Nan ','','','','','','','dang ','','','','','','','', + '','','','','','','','','','','','','','Trum ','','', + '','','','shan ','yu ','','','','','','yu ','','','','','', + '','','','','','tun ','','','','','','','','','','', + 'Tam ','','','','','','','fan ','','Nap6','','','','zhu ','','', + '','','','','yu ','','','','','','','can ','','','','', + '','','','','','','','','','','','','','','','', + 'Lau ','','','','bu ','chu ','','liu ','Bot ','','','','','','','', + '','','','','','','','','','','ge ','','','','','', + '','Tam ','','Lo ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','Com ','','','','', + '','','','','','','','xian ','','he ','','','','','','', + '','','','','','','','','','','Nam ','','','','bu ','No6', + '','May ','','','','','sa ','','','mian ','','','','','','', + '','','','','xia ','','','','Bun ','','','','','','','', + ], + 'x25f':[ + 'zu ','','','ze ','','','','','','','','','','','','', + '','','','','','Lep ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','xiao ','','','Thung ','','','','','','','','','Com ','','xian ', + 'jian ','','','','Men ','','','','Miao ','','','','','','','', + '','Phan ','','','Xia ','','','','','','','','niang ','','','', + '','','','','','','he ','','lian ','','','','','','','', + '','','','Men ','','zhu ','','','','','','reng ','jie ','','','', + '','','','','','wu ','','','','','','cu ','','','','', + '','','','','','','','fu ','hu ','','','','','','jue ','diao ', + '','','','','','','','','','','','','','','Buoc ','', + '','Vuong ','Tim ','na ','','','','','','','','','','','','', + '','','','','','','','Giay ','','','','','','dai ','','', + '','','','','Khau ','','','','','','','','','','','pai ', + '','','','','','','','chao ','','','','','','','','', + ], + 'x260':[ + '','','','','','','','Jing ','','','Dai ','','','','','Thua ', + '','','','','','','Kep ','','','','','','zhuang ','','','', + 'liu ','','','','','','','','No ','','','','','','','', + '','','','','','','','','mao ','Thun ','Xe ','Cui ','Noi ','Keo ','Rang ','', + 'Boi ','Nuoc ','','','','','zhuan ,juan,shuan','nian ','','','hua ','','','','','yan ', + 'jue ','','','','','','','','','','','','die ','','','', + '','','','Go ','','','','','','','','','','','','', + '','','','','','','','','','Ro ','','','May ','Vuong ','','', + '','','','','','','','','','','fu ','','','','','', + '','','','','wan ','','','Sok ','','','','The ','','','','', + '','','','','','Dam ','','','','','','','','','','', + '','','','','','','','','','','','Luot ','','','','Buoc ', + '','','','','','','','','','','','','','','','', + 'Tao ','','','liu ','he ','','','','','','','','','','','', + '','','','','mu ','','','','','','','','','','Gai ','', + '','','','','','','','','','','','','','','','', + ], + 'x261':[ + '','Thun ','Dai ','','Quan ','','May ','','','','','','Chap ','','','', + '','','','Xau ','die ','','','','','','','','','','Van ','', + 'Nut ','','','Cuon ','','','','','','','','','','','','', + '','','','','Chai ','','','','Xung ','','Rang ','Quan ','','qu ','','', + 'xun ','','','','zhe ','','dian ','','','','','','','','','', + '','xun ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Tan ','', + '','Thua ','','','','','','','','','','','','ju ','','yun ', + '','','','','','','','','','','','lai ','','','','', + '','','','','','','','','','','Neo ','','','','wu ','Mung ', + '','','','','','','','','','','','','','','','Ban ', + '','','','','','','','','','','','la ','','','','', + '','','','','','','','','','','','','','','','', + '','','Roi ','','','','','','','','','la ','','','','', + '','','','','','','','','','','','','yao ','','Chung ','', + '','','','','','','','','he ','','','','','','','', + ], + 'x262':[ + '','','Nhau ','nang ','','die ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','yu ','','','','','','','','','','','','', + '','','','','','','','','yu ','','','','','','','', + '','','','','','','Cha ','','','liu ','','','','','','', + '','','','','','','','','Caang ','bian ','','','','','','ya ', + '','','','','','','','ya ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','hu ','cen ','','','','','','','','','','','','', + 'ju ','','','','','','','','hu ','','Bon ','Tu ','','','','', + '','','','','','','fu ','hu ','','','','','','','','', + '','','','','','','','','','','','','','meng ','fu ','liu ', + '','','','','','xie ','','','xian ','','','','','','','', + '','','','','lu ','','','','','','','','','','','', + '','','yu ','han ','','','Ra ','','','','dan ','','','','','yu ', + '','','','','','','','','','','','','','','','', + ], + 'x263':[ + '','','','','','','','','','su ','su ','','','','','', + '','','liao ','','','lu ','','','','','','','','','','lu ', + '','','','','','','huan ','','','','','','','','','', + '','','','','','','','du ','','','','','','','','', + 'nan ','','','','','quan ','','','','','','','','','','fen ', + '','','ta ','tun ','','','','','','','','','','','','', + '','','','','','','','','','Gu ','fen ','','','','','', + '','','','','','','','','shan ','','','','','','','', + '','','','','su ','','','chuan ','','','','','','','','', + '','','jie ','','','','','','yu ','','','Guong ','chuan ','','','', + '','Xinh ','','','','','wu ','','','','','','Tanh ','fu ','','', + 'gu ','','','','','','','','','','','','','','','', + 'ren ','','','','','jue ','','','','','','','','','','', + '','','','Bon ','','du ','','hu ','','','','','yu ','','','', + '','','mai ','','','','','','huai ','','','','','','','', + '','','','','','','','','','','','yu ,yu','','','','', + ], + 'x264':[ + '','','','','','','','Taap ','Fen ','','','','','','','', + '','','','','','','','','','','','qu ,yu','','','','', + '','fu ','','','hai ','','','','','','','','','','','', + 'chai ','','','','','','','','','','','','','','','', + '','','','','','','','ta ','','','','zu ','','xu ','yan ','chai ', + '','','','','','','','','','','','','ge ','','','', + '','','','','','','','','','','','','','','','', + '','','ta ','','','','ta ','','','fu ','','','','','liu ','', + '','','','','','han ','','','','','','','','','','he ', + '','yu ','','','','','','','','','','','Zin ','','','', + '','','','','','','la ','','','','','','','','','', + 'tai ','','','','','Khu ','shu ','Bou ','','','dao ','','','','','', + '','','','','','Gia ','','Khu ','','Lu ','','wang ','','','nai ','', + 'jue ','','','','','','','','','','','','','','','', + '','Ma ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x265':[ + '','','','','','tu ','','','ze ','','','','','fu ','','', + '','','','','','','','','','Cay ','','','','','','', + 'pai ','','','','','','kuai ','','','','','','qu ','','zhe ','sha ', + '','','','','','','','','','nai ','','','','','','tian ', + '','','','','','','ye ','','','','','','','','','sao ', + '','','Zim ','xu ','','','','','','qu ','','','','','','', + '','','','','','','','','','','','','','','','', + 'duo ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','hua ','','', + '','Nghe ','','','','','','','','','','','','','','', + '','','','','','','','yan ','','','','','','','','', + '','','','','','','','','','','','Tai ','hu ','','','Dap ', + '','tian ','','','','','','','','','','','','ai ','','Lang ', + 'ai ','zhe ','','lu ','','','','zhe ','','','','','','','Ghe ','', + '','','','hu ','','','','','','','','','','','','', + '','','','','','','','','','','','ju ','','','','', + ], + 'x266':[ + '','','','','','','','','','','','','','wai ,wa','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','Paa ','','','','','','', + '','','','','','','','','','','','','','','','', + 'pan ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Moc ','Mao ','Hong ','Tim ','','','','','','','','ju ','dai ', + '','','','','zhu ','Wan ','Gu ','','','ban ','','mai ','Ci ','','','', + '','','','','','','','','','','','','','','','', + '','','','Ping ','','','Zaap ','','','','','','','','','', + '','','','hen ','','','','','','','','xie ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','Ruot ','','','ku ', + 'na ','','','','xuan ','','','','he ','','Nam6','','Ham ','','','', + '','','','','','','','','','','','','','','','', + '','','jue ','','','','','','','','Bet ','Thon ','','','Nuc ','Mang ', + ], + 'x267':[ + '','','','xu ','','','','','','','','','','pang ','','', + '','','','','','','Ngaa6','','Vu ','','','','','','Ron ','', + '','','','','','','','','','','','','','','','', + '','','','','tun ','','','','','','','','','','','', + '','','','','Rang ','','','','Ngac ','','','Mun ','Mep ','','Phop ','', + '','','','','','','','','','','','','','huan ','','', + '','Jim ','','','ban ','','','','','','','','tu ','','','', + '','','','xu ','','','','','','','','','','','','', + '','Tuoi ','','','','','','','','','','','','','Nghen ','', + '','','','Phay ','','','','','','','','','','','','', + '','','Tao ','Sao ','','zhe ','','','','','','sai ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','Bo ','Zin ','Gay ','Suoi ','Khu ', + '','','','tun ','','','','Nem ','','','','','ze ','','','', + 'cu ','','','','Xiu ','','','','','','','','','','','', + '','','hun ','ju ','','','Nem ','','','','','','','','Khu ','', + ], + 'x268':[ + '','cu ','','','','xun ','Sun ','ceng ','','','','','','','','', + '','','jue ','','','','pao ','','Vai ','','','','','','','', + '','','jiu ','zhe ','','','shu ','','','','','','','','','', + '','Phet ','','','','Roi ','Seo ','','','','','','','','','sa ', + '','','','','du ','','Fat ','','','','','Ron ','','','','', + '','','','','','','','','','','','','','','Ngam ','Lung ', + 'Song ','','Rau ','','','','','','san ','','','','','yu ','','', + '','yao ,shao','','','','hun ','Lom ','','','','','','','','','', + '','','','','','','','','','','Pok ','','Duk6','','guang ','', + '','','','Mak6','','','','','','','','','','','','', + 'Rang ','','','','','','','meng ','','','','','','','','', + '','','','Vai ','Lot ','','','','','','','','','','','', + '','','','','lei ','','','Lo ','','','','','','','Nan ','', + '','','qu ','','','','','Nhau ','','Nang ','','','','','','', + '','','','','','','','','','','','','','','','', + '','Zak ','','','','','','','lian ','','','','','','','', + ], + 'x269':[ + '','','','','','','','','','','ru ','yao ','','','Gao ','', + '','','','','','','','','','wa ','','','','','','', + '','','','','','','Hot ','zhai ','','','','','hai ','','Thoi ','Kham ', + '','','','','','','','','','','','','','','','', + '','wu ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','Xue ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','fen ','','','','','','','','Kyo ','','xiao ','','','','', + '','','cheng ','','','','','','','yu ','','yu ','','','','', + '','','','','','','','','','','','','','juan ,fan','','', + '','','','Lau ','','Weng ','','','','','','','','','','', + '','','','','','','tian ','','hu ','','','ta ','','','ta ','ta ', + '','','','','','ta ','','','','','','','huai ','','','', + '','ta ','Loe ','','','hua ','','','zhuan ','','Laai ','','','','','', + ], + 'x26a':[ + '','','Mua ','','','','','','fu ','wu ','','fu ','','','ta ','', + '','Chai ','','','','','chao ','','','','','','Qua ','','','', + '','fu ','','','','','jia ','','','','','','','','','', + '','','','wu ','','','','','','','','Khoang ','','','','', + '','','','','','','','','','','','bai ','','','','', + '','','','','','','','','','','Mui ','Gu ','','','yu ','', + '','fu ','xian ','','','','','','','','','','','','','', + '','sheng ','','','','jian ','','','','','','','','','','sha ', + '','','','','','','','lu ','Ao ','','','','','','','Thong ', + '','','','','dun ','','','','jue ','ta ','zun ','','','teng ','','', + 'hua ','','','','','','','','','','peng ','','','','','', + '','','','','','Ghe ','','','','','','Khoang ','Ghe ','','','', + 'teng ','','','','','','','','','','','','','','','', + '','','','','','','','','','ba ','','','','','','', + '','','','','','','','','','','wa ','','','','','xun ', + 'meng ','','','','','','','','','','','','','','','', + ], + 'x26b':[ + '','','wu ','zhe ','','','','','','','','','','','','', + '','','','','','','qiu ','','','','hu ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','zhu ','','','','','','','', + '','','','','','','','','hu ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','Tup ','','','Hung ','','','','','', + 'ru ','','','','','','','','','','','jiu ','','','','', + '','jiao ','','','','','','','','','','','','','','', + '','pu ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','Nen ','','','','','fu ','','','','','','', + '','','','','','xu ','','','','','','','','','','', + '','zao ','','','','','','','','','','','','','','', + '','','','cu ','','','','','','','xiao ','','Dua ','','','', + '','','','','','','','','','','','','','','','', + ], + 'x26c':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','fen ','','','','Ngon ', + '','','Nua ','','Lau ','','','','','','qiu ','','','dun ','','', + '','','','ye ','','','','','','','fu ','','','','','', + 'yu ','','yu ','yu ','Gu ','','','','','','','meng ','','','','', + '','','mu ','','Bei ','','Fu ','','','','','','xiao ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Nhai ','','','','','','','','','','','','','', + '','','','','','','','','','','','fu ','','','','wan ', + '','','','','','','','Lei6','','','','Rom ','','','Muop ','', + '','hao ,mao','','xie ','','','','','','','','','','','','', + 'nai ,na','','','fu ','du ','','','','','Tre ','','','','','bai ','', + '','','','xun ','','','','','','','','','he ','','','', + '','','','','','','meng ','','','','','','','juan ','ru ','', + ], + 'x26d':[ + '','','','','','','','','','hu ','','Mong ','jun ','she ','','', + '','','','','meng ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','Ke ','','','Nu ','','','','','', + '','','','hun ','','','','','','','','','zu ','','','', + '','','','','jie ','','','','','','','','jun ','','','', + '','','','','','','','','','','','shan ','','','','', + '','ta ','','','','','','','','heng ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Kou ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Chu ','','', + '','','','','','','qiang ','','','Bom ','','','','','','Mai ', + '','','','hu ','','','','hai ','ru ','meng ','','','','wu ','','', + ], + 'x26e':[ + '','','','','','','','','','qia ','','','','','','', + 'lu ','','','','','','','','','','','','','','','', + '','','','','','','','','','','pei ','','','','','', + '','fu ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','zhao ','','','','', + '','','','Thom ','','','Voi ','Bui ','','Nhai ','','Dam ','','','','', + '','','','','','','','du ','','','','','','','','', + '','','','','','','ju ','','','','','chuan ','Lao ','','','hu ', + '','','jie ','xiang ','','','','','xiang ','','','lang ','','','','', + '','','shuan ','','','chu ','','','','','','','','','','', + '','dan ','','','','sa ','','','','','','','','','','', + 'Zaau ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x26f':[ + '','','','Sang ','','','','','ju ','','leng ','lu ','','','','', + '','','','','','','','','','','Lum ','San ','San ','','Dua ','Khay ', + 'Sung ','','she ','','','','','sa ','','','mao ','qu ','','','','Zuk6', + '','juan ','','','','he ','','','','','','mei ','','','','', + '','','lu ','mian ','dian ','','','','','','Waa ','','','','lu ','fu ', + '','','zei ','','Om ','','','','','','','','dan ','','wan ','', + '','','','','','','','','','','','','','','','', + 'Tranh ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','sha ','','','','lu ','', + 'Dua ','','','','','','','','','dan ','','','','','','', + '','','','','','','jian ','lu ','','','','','','ta ','','', + 'chu ','fu ','','','','','dang ','','','','lu ','','','','','', + 'jie ','','','','','','lu ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x270':[ + '','','','','chang ','','meng ','','','','','','su ','','','Sung ', + '','Giong ','Non ','Ru ','','sa ','','','','','','','Sam ','','','', + '','zhan ','','','','','','','Lop ','','','','','','','', + '','chai ','','','','','','','','','xie ','','','','','', + '','','','xu ','','','','','','fan ','meng ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','Ghem ','','','','','','','','','','','', + '','zhan ','jian ','han ','dan ','','jian ','','','','','','','','','', + '','','','','hu ','','','','','','','meng ','ju ','','','', + '','meng ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','Dua ','','','','chu ', + '','','','','','','','','','','','','','','','', + 'yu ','','','','','','','','','','','','','','','', + '','','','','','','Muong ','Khoai ','','','','','','','','', + ], + 'x271':[ + '','','','','','','','','','','Han ','','','','','fu ', + '','','qu ','','','','','','','','','ju ','','','','', + '','','','','','','','','','','','','','','','', + '','','Mo ','','','','','','','','','','','','','', + '','','','','','','','','diao ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','Men ','Muong ','','', + 'hu ','','','','','','','','','','nang ','','','','','', + '','','','','Thuoc ','','','','','','','','','','','', + 'gan ','','','','','','','','','','','','','','','', + '','xu ','','lu ','','','','','','','','','','','','hu ', + '','','','','','','','','','','','','','','','', + '','','','','lu ','','','','zu ','','','','','','he ','', + '','','','','','','','','','','','','','shu ','','', + 'yao ','','','','','','','','','','','','','','he ','', + 'hu ','','','','','','','','','','','','hao ','','','zu ', + ], + 'x272':[ + '','','','','xia ','','','','','','','','ge ','','','', + '','ge ','','','','','ge ','','','','42573.210,zhu ','','teng ','ya ','','', + '','','','','','','','','','','','','','wu ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','tai ','','','','','','','','Trun ','Vat ','','','','','', + '','','xue ','yu ','fan ','','','','','bu ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Gwaai ','','dai ,de','','Buom ','Nhong ','','','','Vat ','', + 'Trut ','','','','','','','','ku ','','','qu ','','','','ru ', + '','','','','','xu ','','','','','','','he ','','','', + '','','','','','Gong ','Doe ','','','','','','','','','', + 'Chau ','','','','','','','','','','Saa ','','du ','Zhe ','','', + '','','','kao ','','','','','','','','','','','','Moi ', + '','na ','','','','','Mei ','','','','','','','','','', + '','','','','','Cuong ','Mot ','','','','Chay ','','Nhong ','Mang ','','', + ], + 'x273':[ + '','','Bo ','','','','','Bang ','fu ','lu ','','','','lu ','','ta ', + '','','','Fu ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','Cua ','','','','','Ngai ','','','','Cua ', + '','','','shuai ','','jue ','','','','fan ','','','','','','', + 'jie ','','','','','','','','','jie ','yu ','','','','','feng ', + '','die ','','','lian ','hu ','','','','','','','','','','dian ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Chau ','','', + '','','','','','shan ','','','','','','','','','','', + '','','zu ','','zhe ','','','','','','','','','','','', + '','','xie ','xie ','','','','','','','','','','','','', + '','','','liu ','','','','','','','','','','','','', + '','','','','','jie ','','','','','','sha ','','','','Nhuc ', + 'Sam ','','','Bo ','Choi ','','','Nhuc ','','ai ','','','','','','zhu ', + ], + 'x274':[ + '','su ','','xie ','yu ,yu','Zeoi ','','','zu ','','','','','','','', + '','','su ','','','','Luon ','','','wu ','','','','','','', + '','','Hou ','','','','','','','','','','','','','', + 'du ','','','lu ','su ','','','','','','','','','','Bo ','Sung ', + '','Sam ','','Ngao ','','Vet ','Chang ','','','','','','','','','', + 'yu ','','Giun ','','dai ','','','','dang ','zu ','','','','chuan ','','', + 'du ','','','','','','xie ','zhe ','','','','sao ','','','','', + '','','','','','','','','','','','','','','','', + '','','fu ','','','Buom ','','Sau ','','Rua ','','Rom ','Rua ','Rua ','e ','', + '','','','','','','','','','fu ','','','lei ','','','', + '','','','','','','','','chai ','','','','','','','', + '','','','','','','','','','','','','','lei ','','zei ', + '','ai ','','','','','','','','','','','','Ban ','','', + '','','','','','','fei ','','','','','','','','','', + '','','','','','','','','','','','','','','','Ngoe ', + 'Sam ','','','','','','','','','','','','','','','', + ], + 'x275':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','ta ','','','','','','','','','du ','qiu ','','', + '','','','','chai ','','','','','','','','e ','','','', + '','','','','','','','','','','','','','','qu ','', + '','','','','','','','','','','Trai ','','','','','', + '','fu ','','','','','','chai ','zang ','','','','','','','', + '','','','','Naan ','','','','','','shuang ','','','','','', + '','','','','','','ta ','','','','','','','','','', + '','','','','','','','','','','fu ','','','','','', + '','','','','','','Moi ','','','','','','','','an ','', + '','','','','','','','','','','','','','','','xiang ', + '','','','','','','','','n ','','','san ','hu ','','zu ','', + '','','','','','','','Jiku ','','','','','','','','', + '','','','','','','','','','la ','yu ,qu','jue ','','','','', + '','shu ,yu','','','Jung ','','','Jutsu ','jian ','','','','','','','shuai ', + ], + 'x276':[ + '','','Chong ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','hu ','','','','','','','','','','','','','', + '','','','','','','','','','Taai ','','','','','','', + 'La ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','pu ','','che ','','', + '','','','','','','','53077.090,jian ','','','','','','zhan ','yuan ','', + '','','','','','','yu ','','','','','Lot ','','','','', + 'mu ','huan ','','','e ','Long6','','','','','','peng ','','','','', + '','','','','Tung ','','','','','','','','','','','', + 'Song ','','Xong ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','Trang ','Lun ','May ','','','','','','', + '','','','','du ','','','tu ','','','','','','','hu ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','Toi ','','','','','','','','', + ], + 'x277':[ + '','Sha ','','','','','','','','','','','','','','', + '','','','','','','Chan ','Mo ','','Xong ','','','','','','', + 'shuai ','','','','','','su ','','','','','','','','','', + '','','','','','','','','','','Bau ','','','','','', + '','','','jue ','','','','','','','','','','','','', + '','zhan ','heng ','','qu ','wei ','','','bao ','','','','','','Gei ','', + '','','','','','','','','Cheo ','Toang ','','','','','','', + '','','ju ','he ','','','','','','','','','','','','', + 'shu ','','','','','','','','','','','','','','','yu ', + '','meng ','hu ','','','','','','','','','','','','','', + '','','','','','','','','','jie ','La ','shu ','jie ','lei ','','', + 'zu ','','','','','','','','','','su ','','','','','', + '','','','xie ','','','','','','','','','','','','', + '','','','','','','','','nang ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x278':[ + '','','','','','','','','cha ','','mao ','','','','','', + '','','xian ','','','','','','','','','chan ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','gao ','','','', + '','','','','','','','','','','Thay ','','','','','', + '','jiu ','','','','','','','','','','','','','','', + '','yun ','','','','','','','','','','','','','','', + '','','','','lian ','','','','','','','','','','','', + '','','','','','','','','','','','lao ','','','','', + '','Don ','','','','','','','','','','','','Lai6','','', + '','','yao ','','','','','wei ','','','','','','','','', + '','','','','','','chu ','','','','','','','e ','','', + '','','','','','','','','Caau ','','','','qiao ','','','', + '','','ju ','','','qiu ','','','','','','','','','','', + '','','hun ','','','','','Dia ','','','','','','','','', + '','','','','','lun ','','','jue ','','','ju ','hu ','','','', + ], + 'x279':[ + '','','','','','','','','','','','','','','','', + '','ju ','','','','qiu ','','','','','','','','','','', + 'zhe ','','','','','','','','','','','','','Ba ','','', + '','','','','','','','','','Thoi ','','','jue ','','','', + '','','','Choi ','','','su ','','','','','','kuang ','','jue ','', + '','','','','Va ','','','','','','','','','','tan ','', + '','','','','','','','','','','','','','','','hu ', + '','fu ','','','yang ','','','ren ','','','Kwan ','','yun ','','','xun ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','pu ','', + 'Ngaak ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','Beng ', + 'Ngoa ','','','','wang ','','','','','','','','','','','', + '','','','xu ','','','','','','','','','','Ngaa6','','', + '','','','','','','','','','','','','','','','Khoang ', + '','','','','','','tu ','','bie ','','','zha ','','','','', + ], + 'x27a':[ + '','','','','','','','','','','Zaa6','','','','','', + '','','','','','','','','','','','','','','','', + '','chen ','','','','','','','','','','','','','','', + '','','','','','','','','','lu ','','','','','Tam ','', + '','','','','','yan ','','','','','','','','','','', + '','','','','','','','','','Daan ','','','','su ','','', + '','','','','','','','','','','','','','','','', + 'bian ','','la ','','','','qia ','','','','','','','','','', + '','','','','','nu ','','','','','','','','','','', + '','','','','','','','','','','','','','','he ,ge','', + '','','','','','','','','ma ','','','','','','','', + '','','','','','','','','','xia ','','','','','','', + '','','','','','','','','','','yu ','','','','','', + '','jie ','xia ','','','','','cha ','','','','yang ','','','','', + '','','wang ','','','','','','','','','','','','','', + '','','','','','','','','','','','','Mo ','','jiu ','', + ], + 'x27b':[ + '','hao ','','','','','','','','','','fa ','','','','', + '','','','','','','','','','','','','','','yun ','', + '','','','','','','','','Wai ','','gun ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','dan ','','','','','','','meng ','','','','','', + '','','','','teng ','','','','','','','','Leoi6','sa ','','', + '','','','','','','','','','','','','','','','', + '','','','he ','','','','','','','','','','shan ','','', + '','','','','','','','','','','','','','','','', + '','ta ','','','','','','liu ','','','','','','','','', + '','','','','','','','','','','','jue ','','','','', + '','fen ','','','','he ','','','','','zhan ','','tai ','qian ','','', + '','','','','Hang ','Hang ','','','','','','','','lao ','','', + '','','','','','','jun ','','','','','','','','','', + '','','','','','zai ','juan ','','','chu ','','','','','','', + 'kan ','','','','','Phong ','','','','','','','','','','', + ], + 'x27c':[ + '','','','','','','','yu ','wu ','','Tian ','','','','','', + '','','','','','','','Nanh ','','','','','','','','', + '','','','','','','','Shuu ','','','han ','chu ','','tun ','','', + '','','','','','','','','','na ','','','','','','ai ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','mai ','','','','lun ','jue ,jun','','', + '','','','','','','','','','','','','','','','', + '','','','huai ','','','','','','','','','','','','', + '','','','','','ceng ','','hu ','','','','ju ','sha ','meng ','','', + '','','','','','','','wei ','','','','','','','','', + '','','zhe ','','','hu ','','','','','','Cop ','','','','', + '','','','','','qu ','','','','','','','Beo ','','','', + '','','fu ','','','','','Cop ','','','','','','','wu ','pei ', + '','','','','','','','','Hum ','','','sha ','','zhao ','wei ','', + '','','','','','','','','','tuan ','','','mei ','','','', + '','','','','','','','','gu ','shao ','','','','','','', + ], + 'x27d':[ + '','','peng ','','','','','','','','huan ','Beo ','fu ','','biao ','', + '','','','','','biao ','','','','','guai ','','','','','', + '','','','','','pei ','','','','','Suo ','','','','','Me ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','Qua ', + 'pai ','','','','','','','','ai ','','','','','','','', + '','','','She ','','','','','','','','','','','','', + '','','','','Danh ','','','','','','yun ','','','xu ','','', + '','','','','cheng ','','','','','','','','','','','', + 'yu ','','','','','','','','','','','','','','','', + '','','','','','cha ','Faan ','ze ','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'fen ','xie ','','','','','','','','','','','','Xoe ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','shan ','','Mua ','','','','','','ju ','', + ], + 'x27e':[ + '','','','','','','','','','','','','','','','', + '','','','','','','Zhuan ','xue ','','','','','','','','', + '','','','','','','lan ','ju ','','xun ','zhan ','gun ','','','','', + '','','','','','','','','','','','Bui ','','','','chai ', + '','','','','','','','','reng ','','','Vay ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','Son ','','','xu ','','', + '','Tham ','hu ','gan ','','','','','','','','','','','hu ','', + 'Tham ','Tham ','','','','','','','','','','','','','','', + 'jue ','','zu ','','','','','','','','','','jiao ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','chu ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','xian ','','','','','ju ','','Mut6','','','','','','', + '','','','','','','','','','','','','','','','', + 'hu ,zao','qiu ','','fu ','lang ','sha ','','','','','','','','','','', + ], + 'x27f':[ + '','','','','','','','','','','','','','Lanh ','','', + '','xu ','','','leng ','','','fu ','','','','','cu ','','','', + '','','','','dao ','','','','jie ,jue','','','yu ','','','Tang ','shu ,yu', + '','','','','','','','','','','','','','','','', + '','','','','jie ','','','Day ','Day ','','','','','','','', + '','','Cau ','','','','','','','','','','','','','jie ', + '','','','','','lu ','','chu ','','','','lian ','','','','', + '','','','','','','e ','su ','Jue ','','','ju ','','','','', + '','','','','','','xuan ','','','','','','Tron ','','','', + 'jiao ','','','','','','','','','','yu ','','','xun ','','', + 'xun ','','','ju ','','du ','','','','xun ,xuan','','','','','','jie ', + '','qu ','','','','jue ','','','','','','jiu ','','','','Treo ', + '','','','','','','','','','ku ,wu','','ku ','zha ','','','ba ', + 'Chen ','Nhac ','Dam6','hu ','nu ','e ','','','','','','','','','','', + '','','','','','bie ','','','','ge ','','Dau ','','','','', + '','','','','','','','yu ','','Mau ','Xoat ','ju ','','','','', + ], + 'x280':[ + '','','','','','','','','Buoc ','','','','','Dung ','Lop ','', + 'Rong ','','','','','','hai ','','','','','cun ','','','','', + '','','','Kei ','Choi ','','','','','','','','zai ','','','', + 'Bang ','','','','xun ','','','','','','','','','','','', + '','xuan ','xie ','','han ','','','tun ','Gaang ','','cen ','','','Ren ','Choanh ','', + '','','','','','','','','','','','','','Buot ','','', + '','Noi ','','','','','','Noi ','Cuong ','','Dau ','','','','','', + 'Xui ','','','','','','','','','','','','Bon ','de ','','', + '','','','peng ','','','','','','','','','','','','', + 'Leoi ','','','','Doc ','','','Co ','','','','','','','tan ','', + '','','','wu ','','','chuan ','','','','','','','du ','','', + '','hun ','','','','','','','','','','','','Dam6','Naam ','', + '','','','','','','','','','','','','Giay ','Tot ','','Xam ', + 'Giay ','','','','','Soc ','kua ','teng ','','','ta ','sa ','','','Pun ','Pun ', + '','','','sao ','','','','','','Sin ','','','','zu ','','', + '','','jie ','neng ','','','','Chuc ','','','','','To ','Nhuc ','Xung ','', + ], + 'x281':[ + '','','','','','','','','','','Te ','','','','','', + '','','','','shuan ','zu ','','','','','','','','','','', + 'Tat ','','','','','','','','','','','','','','','yu ', + '','','','','Sup ','','','','','','Chui ','','','','Ghe ','Giong ', + '','Sup ','Mop ','','','','','','','Lung ','','xiao ','','Ren ','','Laam ', + '','','shu ,chu','','','','','','','','','','','Jaang ','Nhap ','', + '','','','','','Bay ','','','','','','','','','','', + '','','','','','','','Doi ','','','','','','','Sum ','', + '','','Khum ','','zhu ','','','cha ','juan ','','','','','','zei ','', + '','','','','','','','','','','','','','Cui ','','', + 'Quay ','Dep ','','','','Tuon ','','','','','Jaang ','','','','','Buk6', + 'ta ,da','','','','','','','','','','','','','','','', + '','kuang ','','','','bao ','lai ','','','Leo ','','','','','','', + '','','','','','','lu ','','','','','','','','','', + '','','','','','','chan ','','','zhan ','','','','','','', + '','','','','','Nhao ','Khuy ','','','','','','','','','', + ], + 'x282':[ + '','','','','','','','Laam ','die ','','','','','','','', + '','','','leng ','','','','','','','Pei ','','','','','', + '','','','','','','','','','','','zhu ','','','','', + '','','','','','','','','','','ye ','','','','','', + '','huang ','','','','','','','','Pei ','','','','','','', + '','','','','','','Nei ','','','','','','','','Lung ','', + 'Ban ','','','','','','','','','','','','','mei ','','', + '','tang ','','','','','','','','','','','Wu ','xiang ','','', + '','','','','','','','','','','','','Lan ','','','', + '','','','','','','','','','','','Laak ','','','','', + '','','','','','','','','','','','','','','','', + '','yu ','','','','','','','','','dai ','','xuan ','','','jue ', + '','','','','','','','','du ','','','','','Wan ','','', + '','','','','','','','','zha ','','','pao ','','','bu ','he ', + '','','Lip ','','So ','','','ju ','hun ','','','','','','','Zhuai ', + '','','','','','','','','','','','','','','','', + ], + 'x283':[ + '','','','','zang ','','','','','','','','','','xu ','', + '','','','','','','','','jun ','','','','','','','', + 'lu ','','','','','fu ','','','','Tang ','','','chao ','ta ','','', + '','','','','','','','','','','','','','','','', + '','','','','Co ','','','he ','','','','','','','mu ','', + '','','xian ,jian','','','','','','','','','du ','','','','', + '','','','','','','Sau ','','','peng ','','','','','','ju ', + '','','','Yao ','','','','','','','','','','','','', + '','','','','','','So ','','','','','','','','','', + '','','','','yang ','','','','','','','','','','','Truoc ', + 'Truoc ','','','','','','','peng ','','','','jian ','jiao ','','','', + '','','','peng ','Dang ','','qu ','','mu ','','','','','','fen ','', + '','','','','','','','','','shuan ','jian ','','','','','', + '','','','','lu ,du','','','','','','ge ','','','','','', + '','','','','','xian ','','So ','','','','','','','','', + '','','','xie ','ge ','','','','','jue ','','','','','','', + ], + 'x284':[ + '','die ','','zhe ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','ku ','','qu ','','ge ','ban ','','','','','','','','Cay ','', + '','ban ','','','','','','','','','','','','','ban ,bian','', + '','','','','','','','','','','','','chen ','','','', + '','','Tu ','','','','','','','','','','Xuong ','','','', + '','','','','','wu ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','pan ','','','','','','','qiu ','','','','','', + '','','','','','','','','','','','','bie ','','kan ','', + '','','','','','','','','nai ','','','','','','','', + '','','','','','','','','','','Quanh ','','','','','', + '','','','','','','','','','','die ','','','','','', + '','','','','','','','','','','','','','','dai ','', + '','Lung ','','','','','','','','','','','','','','', + 'jie ','','','','ya ','','','','','','','','','','','pei ', + ], + 'x285':[ + '','','','','','','','','Choi ','','Suot ','','Co ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','shu ','','','','','','','','','ta ', + '','','','','','','','','','','','','','','','Chuc ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'ze ','','chu ','','','','qiu ','','','','','','','','','', + '','','','','','','','','','','','','','jie ','','', + '','','','','','Sang ','','','','','','','yang ','','','jiu ', + '','','','','','','','','','','','','','','','', + '','','','','','','','Mau ','','','','','','','','', + '','xian ','','','','','xiang ','sha ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','dao ','','','','','','','','','Nhanh ','yu ,ju','','', + '','chao ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','da ','', + ], + 'x286':[ + '','','jiu ','','','','','','','sha ','','','','','','', + '','','','','','','','','','xian ','','','','','xian ','', + '','','','','','','','','','','','','','','jiu ','', + '','Nhanh ','','','kao ','','','','','','','','','','','', + '','','','','','','','','','','','','','Keo ','ta ','zan ', + '','','','','zhu ','','Suot ','','','','','','','Lui ','','', + '','','','','','','','','','','','','','','','', + '','','','','','xiang ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','bian ','','','','','','','','','','', + '','','','','','','','qie ','','','','','','','hao ','', + '','','cun ','','ru ','zai ','','','','','','','','','','', + '','','','','','','','','','','','','','shao ','han ','', + 'jun ','','bu ','','','','kuai ','','','','','','xiang ','','','', + '','yun ','','','','pu ','','','','','','','pei ','','','', + '','','','','','','','','','','','','','','','', + ], + 'x287':[ + '','','','','','','','','','','','','huan ','qiao ','','', + '','','','','','','yu ','','mei ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','he ','','','he ','','','','','','','','','','chuang ','xu ', + '','','','','','','','','','','','zhai ','','','','', + '','guan ','','','','','','','','','','tu ','shun ','','hu ','', + '','','','','','','dang ','','','','','','','feng ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'cheng ','','','yu ','','zhu ,chu','','qun ','','qu ','','ge ','','','','', + '','','','','','','','','gai ','','','meng ','','','','', + '','','','qu ','','','','','','','','','wan ','lei ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','dai ','','','','','','','','','','','qiu ','','', + ], + 'x288':[ + '','','','','','','','','','Tam ','','','','','','', + '','','Faan ','','','','bao ','','','','','','','','','', + '','','','','','wei ','','','','','','','hao ','','','', + '','','Giam ','Gay ','Sua ','Xoang ','','','','','','','','','','', + '','','','jiao ','','','','','','Dam ','','','nei ','','yan ','', + '','','','','','','','zha ','','','','','','','','', + '','','','yan ','','','','','Gay ','','','hun ','','mu ','','', + '','','','','','','','','','','','','Giam ','','','', + '','','','','','','','liu ','han ','','meng ','hu ','','','','', + '','','','','','','','','','','','','','','','Cay ', + 'meng ','','mu ','','hu ','Mi ','shai ,zha','','','','chao ','','','','','nian ', + '','','','','','','','','','','','','','','','', + '','','','','','chuai ','','','','','','','','','','', + '','','','','','','','hu ','meng ','pao ','','','','','','', + '','','','','Giam ','Dau ','Zeoi6','','lan ','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x289':[ + '','','','','','','','','','','','','','','','', + '','juan ','','','','','','','','','','','','','','', + '','guang ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','jie ','','','','','','','','','','','','','', + '','','','','','','','','','','','hu ','','','','', + '','','','cen ','','','','','','','','','','','','', + '','','','','','','dai ','','','','','','','','','', + 'Keo ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','fu ','','','','', + '','','','','','','','Nen ','','','','','','Lao ','','', + 'liu ','','','','','','','','','','','','','','','', + '','','','','','','Bua ','','','','','','','','','', + '','xiang ','','','','bian ','','wu ','','','','','Bong ','','','', + 'Gang ','','','Xot ','','','','','','','sao ','','','','','', + 'zu ','','','','','','','','','','','','','','','', + ], + 'x28a':[ + '','','','','','Hoat ','','','','','','','','','','', + '','','','','','','','quan ','','','chao ','he ','','','','', + 'Cuoc ','wu ','','','Khep ','','Mai ','Thep ','','','','','','','','', + 'ruan ','','','zu ','','','yu ','tu ','meng ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','mao ','','','yu ','','','', + 'zu ','','','','','','','','','','','','','xia ','','', + '','','','','','jian ','','','','','','','','','yu ','', + '','','','','','liu ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','ruan ','','','yan ','','','','','','','','','', + '','','','','Bam ','Lon ','','','Choc ','','Sat ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','Han ','','','','','', + '','','','','','Cuoc ','','','','','','','','','','', + ], + 'x28b':[ + '','','','','','','','','','Dui ','','','','','','', + 'jue ','','','','ruan ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','zhu ','','','','','','','Baang ','Bay ','','Choang ', + '','','Choang ','die ','','','','','','','','','','','','', + '','Thau ','','','','','','','','','','','','','','', + '','','','','','','','','','','Com ','','','','','', + '','','','','','','','Bung ','Hom ','Cun ','','','','','','', + 'Nhon ','Thoi ','','','yu ','','','','Ban ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','cai ','','','','','','','','','','','jiang ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Dui ','','','','','','','', + ], + 'x28c':[ + '','','qian ','','','','','','','','','','','','','ta ', + '','diao ','','','','','','','','','','','jue ','','','', + '','','','','','','','','','','','','','','','', + '','','','','Nen ','','','','yu ','','Ben ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','duan ','','','','','', + '','','','','','','dao ','','','','','','','','','', + '','','','','','','','','','','','','cen ','Dai ','Dai ','', + '','','','','jun ','','','','zhu ','','an ','','','','','', + '','','qiu ','','','','','','','','','','','','','', + '','','','','','','','','','','','feng ','wu ','jiao ','','', + 'peng ','','','','','','','','','','','','','','','', + 'niao ','','chan ','','','','nang ','','','','Gau ','','','Cat6','','', + '','','Mon ','','men ','','','','tun ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','die ','','','','','', + ], + 'x28d':[ + '','','','','','','','','','','','','','','xu ','', + '','Kuang ','','wei ','','','','die ','','','','','','','','', + '','','he ','yan ','','','Cua ','','','tu ','','','hu ','','','', + 'chu ','','','','','','','','','','men ','','','','','', + '','','','','','','','','','','zhe ','','','','','', + '','','','','','','','','','','xie ','','','ta ','','fu ', + '','','','Cua ','','','yu ','','','','xie ','','xian ','jian ','xu ','', + '','','','','','','','','','','','','','','','', + '','yan ','ai ','','','','','','','','jun ','','','','','', + '','','','','','','','lang ','','Lan ','','','','shu ','','', + '','','yu ','','','','','','','','','','hua ','wen ','','e ', + '','','','','','','','','','Gwaan ','','','','','','', + '','niu ','','','xiang ','','sa ','','','','','','','','run ','', + '','','','jian ','xu ','','','','','shu ','','','','','','', + '','','','','','xie ','','','','','','','','','','Cua ', + '','','','','','','Cua ','','','','','','','','dang ','', + ], + 'x28e':[ + '','','','','','','','','','','','','','Cup ','','', + 'reng ','','','','','','','han ','','','Ji ','gai ','','','','', + '','','','','','','','','','','','','Zhen ','','','', + 'ju ','','','','','','','','','','','','','','','', + '','','','','','','xuan ','','','','','','','','','', + '','','','','','','','','xu ','','cheng ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','zhao ','','','','','','','', + '','','','','','fu ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','duan ','','','','qiu ','','','','','','','xun ','', + '','','','','','','','','','Jiao ','','','','','','', + '','','yan ','','','','','','','','','','','xu ','','', + '','','','','','','','die ','','','','','','','','', + '','','','','','','','liu ','','','','Luong ','','','','', + '','','Xia ','','','','Geki ','','','','','','','','','', + ], + 'x28f':[ + '','','','','','','','','zhan ','cuan ','wu ','','','','jue ','', + '','','','','xun ','','','','','','Be ','','','','','', + '','','','','chen ','','','','','','','qu ','','','zhan ','', + '','jue ','','','','','','','','','','','','qu ','','meng ', + '','','pu ','','','','','','','','','','','du ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','xia ', + '','','','','','','','','','','','','','','','dai ', + '','','','','','','','','','','','','yu ','','','', + '','','','','fang ','','','','','','','','','','','', + '','','','','die ','','','','','','','','','','','', + '','','','','','','','','','','','','','','tiao ','', + '','','','','','','','','','','','','','','','wu ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','wei ','','', + '','','','','','','','','','','','','','','','', + ], + 'x290':[ + '','','','','','','','','','','','run ','','','','', + '','','','','','','','','','','','','','','','', + '','','','wei ','','','','','','','','','','','','', + '','','','Song ','','','','','','','','','','','','', + '','','','','','','','','','','','','wei ','','','', + '','','','','','','','','','','','','','','cai ','', + '','','','','','','Loi ','','','','','','','','','', + '','','','','','','Ngat ','','','','','','','','','', + 'Con ','Ngut ','','shai ','tun ','','','','','','','','','','fu ','Che ', + 'Ram ','Bung ','','','fu ','Phat ','ze ','pu ','','','','','','','pao ','Mu ', + '','','','','hua ','','','','','','','','','','','', + '','','','Rei ','','dian ','Set ','','','','','','','','','', + 'yan ','','','','','','','','','','','','','','','', + '','','','','','','','','','','xuan ','','','','','', + 'dai ','','','','','','','','','','','','','','','', + '','','','','ba ','','','dai ','','','','','','','','', + ], + 'x291':[ + '','','','','','lu ','','','','','','ru ','','','Mua ','Bung ', + '','','','','','dan ','meng ','xia ','','','','','','','','', + '','','','','','','peng ','','Guot ','','','','','','','wu ', + 'Set ','','May ','','','Nap ','Xoi ','piao ','','','','','','','ze ','', + '','','','','lu ','','','bu ','','','','','','man ','','', + '','','','','','','','','','','','Bung ','','','','', + 'nan ','','he ','','','','','','','','','','','','cen ','', + '','','','','','','','','','May ','Rau ','Zyu ','','','dan ','fu ', + '','','','','','sa ','','','','','','Rao ','','Rao ','liu ','', + 'Sam ','','','','dian ','','','','','','','','','','','', + 'Mong ','Rao ','','','','','','','','','','','Mong ','','','', + '','','','','','','','Sam ','','','','','','','Khuya ','', + '','','','','','Mu ','Sam ','hun ','','','','','','Loa ','','', + 'qu ','','','','','','','','','','','','','','','', + '','','Xanh ','','','','','','','','','','','','','fei ', + '','','','','','','','','','','','','','fei ','','', + ], + 'x292':[ + '','','Bay ','','','','','','pang ','dan ','','ai ','','','','', + '','','','','','','','mai ','','','','','','','dao ','', + '','','','','chu ','','','','','','','','wan ','','diao ','', + '','','suan ','','','','','','','mian ','','','','','','', + 'lan ','','','','','','','','','','','','','','','', + 'gan ','','','','jian ','','','','','','','','hang ','','','', + '','','','','','xuan ','','','','','','','','','','', + 'ang ','','','','','fen ','','','ju ','','','','','fu ','','qu ', + '','','','ma ','','bao ','','yu ','','','','','','mai ','','', + '','','','','jiao ','','','','','','','','','','','', + '','','','','','','','','','','','','bu ','','','', + '','','','','','zhe ','bu ','','','','jue ','xun ','','Hia ','','', + '','','bai ','','','ta ','','','nao ','yu ','','','','','','', + '','','','','','','','','Xie ','diao ','','','','','die ','fu ,fu', + '','','xuan ,yun','','yu ','','','Xie ','fu ','','','xuan ','','','','', + '','','','','','','','la ','','','gao ','','','e ','','mei ', + ], + 'x293':[ + '','','','','','','','ta ','','ta ','','','','','','', + 'ta ','','','','','','','','ta ','','','','','','','', + '','','','','','','','','','','ze ','lu ','','','xu ','', + '','','xu ','','','','','','','','','','','','','', + '','','bao ','','','','','','','','','sheng ','','','','fu ', + '','','','','','','','Bang ','','','','','','','','', + '','','Roi ','Dep ','','','','','','','','','','','','', + '','','','xu ','','','','jue ','','','','','lu ','','','', + '','','','','','','','','','','','','','','ge ','', + '','','','','','','','','','','','fu ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','wei ','','','','yu ','','bai ','','ta ','','', + '','','','','','yun ','yun ','duan ','','wei ','','','','','','', + '','','','','','','hun ','','','','','','','','bai ','yu ', + '','','','','','','','','','','','','','','','', + '','','','','yu ','','','','','juan ','jue ','','','','','', + ], + 'x294':[ + '','','','','','sa ','','','','','','','','','','', + '','','','','','','','','','','fu ','peng ','','','','', + '','zu ','','','','','','','','','','su ','','','','', + '','','','','','','zhe ','','','','','','su ','','','', + '','e ','','','','','','','guang ','','','','','ao ','','', + '','','','','','','','','','','','','','','','', + '','','','','','men ','','','','','','','','','la ','', + '','','','','yao ','','','','','xuan ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','yan ','','','','','','','','','', + '','','','','','','','','','','','','','','qiu ','', + '','','','','','','','','','','fu ','','','','wu ','', + '','','','','','','','','','','','','','','','', + '','','','','','','fu ','','','','','Ngup ','Mang ','bie ','','', + '','','','','an ','Ngok6','wu ','','','','lu ','','','','','', + '','','','','','','','','','','','jue ','','','','', + ], + 'x295':[ + 'wai ','','dun ','','jie ','','','','','','zhuan ','hang ','','','','', + '','','','','','qiu ','','Lei ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','ze ','xu ','','','','','','','','xu ','','','', + 'ao ','','','','','','','','','','','','','','','', + 'liao ','','','','','wai ','','','','','','','','','','', + 'han ','','','','dan ','','','','','','','','','Gai ','','', + '','','','','','','','','','','','','','','yuan ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','peng ','','','','', + '','','','','tun ','','','','','','','','fu ','','','', + '','','','','','','','','','','han ','','fu ','','','', + '','','','To ','','','','','','sa ','','','','','','', + 'hua ','','','','','qiu ','','','','','','','','','sa ','', + '','','','','han ','','','','','liu ','','','','','','', + '','','','','Bung6','','','','','','','','','wu ','','', + ], + 'x296':[ + 'zhao ','','','','May ','','','','','','la ','','','yuan ','','', + '','','','','','','','','','','','','','','','', + '','','','To ','yu ','','','','','','','','','','','', + 'su ','shuai ','','yu ','','','','','','su ','','yu ','','','','', + '','','','','liu ','','cheng ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','niu ','','','','Bay ','','','','', + '','','','','yu ','','','','','','','','','','','', + '','','','','Nhu ','','niu ','','','','','na ','','','','', + '','','','','','','','Qua ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','No ','Qua ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','zai ','','','mao ','','yu ','','','yu ','','', + '','','','','','','','','','','ju ','','lu ','','','', + ], + 'x297':[ + '','','','ju ','','','','Juan ','','','','','','','','', + '','','','','','','','','','','','','','','','ang ', + 'Mam ','','','','','','','','','','','','','','','', + '','','fu ','','','','','','','','','','','yan ','','', + '','','','','','','','','','','','','','','','', + '','','','','','wu ','','yu ','','','','','','','','', + 'Qiu ','','','','','su ','','','','','','','','','','', + '','','','','','','','','','','','Chan ','','jiang ','','', + '','','','','','','','','zhu ','','','','','','','', + '','','','','','','','','','','','','','','hai ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','han ', + '','yuan ,xuan','Qua ','','','','','ao ','','','','shan ','','','','', + '','yu ','','','Caat ','','','','','','','','','','meng ','', + '','','','','','','jie ','','','','','','','','huai ','', + '','','','yu ','','','chan ,jie','','','','','Nang ','','','','', + ], + 'x298':[ + '','','','','','','','','','','','','','','','', + '','Ding ','','','Mao ','','','','','','','','','','','', + 'Cui ','','','','','','','Guc ','','','','','','','','wei ', + '','Chui ','','Chui ','Cui ','Choi ','','fu ','','','','','','','','', + '','','','yu ','','','','','','','','Thom ','','','','', + '','','','','hai ','peng ','','','','','','','','','','bie ', + '','','','','','','','','','','','fan ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','wan ','','','','','','','','wen ','','','', + 'zhe ','','','','ban ','bu ','','','','','','ge ','','','liu ','', + '','','','','','','Giong ','','','','hu ','','','','','', + 'fu ','','Sai ','qu ','','','yu ','','','jiu ','','shu ','','','','fu ', + '','','','','','','','','','','xu ','','','','','', + '','Ngon ','','','','','','','','','','','fu ','bu ','','', + '','','','','','','','','','zhe ','','','','','tu ','', + '','lu ','','','','','','','fu ','','','','','','','', + ], + 'x299':[ + '','','','','','','','','','','xian ,jian','kun ','','','','', + '','','','','','','','','','cheng ','','','','','tan ','', + 'xie ','','','duan ','','','','','','e ','','','','','','', + '','','','','','','','','','','yu ','','','','','', + '','','','','','','','zhan ','','','','Au6','qia ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','yu ','','', + '','','','','','','','','','','','','','tu ','','zu ', + '','','','','','','','','','bie ','','','','','','', + '','','','','','','','','','','','','','','','', + 'bang ','yu ','Jyu ','','','','','','','','','','','','','', + '','','','','','','','','','xian ','meng ','','','','','', + '','','','','','','','cai ','du ','','','','','','','jue ', + '','','ju ','','','','','','qu ','','','','','','','', + '','jue ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x29a':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','yu ','','yu ','','','ba ','','','', + 'ya ','','','','','','','','','fan ','','','','Que ','','', + '','','ma ','','','','','','','','','','Kheo ','','','', + '','','','','','','','Song ','','','','','','Peng ','','', + '','','','','','','Song ','','','','','','','','','', + 'zu ','leng ','','','','','','dan ','','','Xuong ','Xuong ','','','du ','bian ', + '','qia ','he ','','','','yan ','','','','','teng ','','','','Hom ', + '','','','hai ','','','','','','xu ','','','','','','', + '','','','','','','','Jue ','','','','pu ','','','Sun ','', + '','','','','','','','','','','','','','','','', + '','','','','yan ','So ','','','','','','','','Cut ','','', + 'kai ','mao ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','sao ','','','','','','','','','', + '','','','','ju ','','','','','cheng ','','','','','','', + ], + 'x29b':[ + '','','','','','','','','','','','','','','Zam ','', + '','Chom ','','','','','','','','','','','ju ','','','zha ', + '','','','','','','','','','','','','','','','', + '','dao ','','','','','','','','','','','','','','', + '','','','','','','','','','','ju ','','','','','', + '','','','','','','','','','','','','Xui ','','','dao ', + '','','an ','','','han ','','','','','','','','','','', + '','','','','','Quan ','Rau ','','','','fu ','','','','','', + '','qia ','','','','na ','','','','','','','','','','', + '','','','','Quan ','','','','','','','','','ya ','','', + '','','','','','','','','','','','','','Ria ','','', + '','','','','','','','','','','','','','','','', + '','Rau ','','','zun ','','nao ','','','','','','','','cheng ','', + '','','','','','','','','jiao ','','','yao ','','','can ','', + '','','','','','','','','','','','','','Ban ','','Xoam ', + '','pu ','zhuang ','','','','','','','','','','','la ','','', + ], + 'x29c':[ + '','','','zhan ','','','','','Nheo ','','','','','bian ','','', + '','','','','','','','','','','','','','','','', + '','','','','ju ','','','','jue ','','yu ','','','','','hu ', + '','','','xie ','er ','','','','','','','','','','','', + '','','','','','','','','','','er ,xian','','yu ','hu ','','', + '','','','','','','','','','ku ','','','','','jiao ','', + '','','','','','','','','ru ','','','','','','','', + '','yu ','','','','','','','','','','','','','','', + '','','','','','','','','','','hao ','','','niu ','','hua ', + '','','','','','','','','','','','','','','','', + 'zhu ','Coi ','','','','Troi ','','','','','','','zhu ','','','', + '','','zu ','','','','','','','','','','','','yu ','', + '','','','','','','lai ','','','','Ranh ','','wu ','','fu ','zhuan ', + '','','su ','','yao ','','','','','','','','','','','', + '','','yan ','','','zhu ','','','','','','','','','','', + '','','','Troi ','','ju ','','','','','','','','','','', + ], + 'x29d':[ + '','','','','','','','shai ','','yun ','','','','','','', + '','','jiang ','','','','','','ju ','','Troi ','','','teng ','wei ','', + '','gu ','','','liao ','','','','','','','','','','','', + '','','meng ','cha ','','','','','','qu ','','lei ','','','','', + '','','','Troi ','','qu ','','','','','','Gyo ','','qiu ','','hua ', + '','','','','','','','','','','du ','','','Chai ','','', + '','','','','','','mu ','','','','','','hu ','','','', + '','','','','','','','','','fu ','','','','Tom ','','', + '','','zhu ','','zhu ','Ci ','','','','Pou ','','','','','','', + '','','','','','','mu ','','','','','','','','','Buop ', + '','meng ','','','','','guai ','jiu ','','mu ','','','Si ','wu ','','ru ', + '','zha ','','','','','','','','','','','','','','', + '','','xie ','','jiang ','','','Hung ','','','Thu ','','','','','', + 'ju ','','','','','Luon ','bu ','','','','','','','','','', + '','','','','','','','','','','','','','jiang ','','', + 'xun ','','','','','','Mang ','','','','','qia ','','','','', + ], + 'x29e':[ + '','','','tu ','hua ','','','','','','','','','','','', + 'ru ','','','','','','','','','','','','','','','', + '','','','','','','','','Yi ','','','','','','Bong ','Chuoi ', + 'Go ','','','','','','','','Thia ','','','','','','ye ','', + '','','','','hai ','','','','','','','','','','an ','ba ', + '','han ','','','','','','','','','','','','','','nai ', + '','','','','Thu ','','','','','Nau ','','Tep ','','Chay ','Mu ','Tuoi ', + '','chu ','','','','','','','','','ge ','','han ','','na ','ge ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','Bon ','','Trau ','','','','','Bong ','','Bon ','xie ','','','','Soc ', + 'yu ,wu','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Mam ','','Sop ','Dua ','','Tram ','','bu ','jian ','','wu ','Tram ','','zhuan ','','Vay ', + '','','','','','','','','','','','','','','','', + '','','','','','die ','','','','','Vay ','Leo ','','','','', + ], + 'x29f':[ + 'Vay ','','','','','','','','Ao ','','','','','','','', + '','','','','','','','','','ge ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','xu ','','','Sau ','Lui ','','','','wei ','', + '','','','','','','Ruoc ','','','','','','','','','', + '','','','','Sau ','Luon ','','','','qu ','','','','','','', + '','','','','','','','ba ','Nheo ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','han ,yan','','', + '','bao ','','','','','','xun ','','','','','','','','', + '','','','','','','jie ','','','','','hu ','','','','fu ', + '','','mao ','','','','','','','','','','','','','', + '','','','bao ','','','','','Mao ','','Khuou ','','','ju ','Caa ','qu ', + '','','','','','qu ','','','Khuou ','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2a0':[ + '','','','','Chim ','','','','','','','','','','','', + '','','Shi ','','','','','','jiang ','','','','','','','', + 'xun ','','','ju ','','','','','','','','','','','','', + '','','','','','','','','','','fu ','','','','jie ','', + 'yu ','','','','Ket ','Sac ','Hau ','Song ','zhuang ','','','cheng ','','jie ','','chen ', + '','','','','','','qu ','','','','','','','','','', + 'jue ','yan ','','','','ju ','','','','','','','','','xiu ','', + '','','','','Coc ','Coc ','','','','','','','','su ','','', + '','','','','','','','','','yu ','','fu ','ta ','','','', + '','','hu ','','','','','','','','','','mei ','','','', + '','','','','','','','','','','','','','','','', + '','','','Cun ','','yu ','','','','','','','','pen ','fu ','', + '','','liu ','','','','','','jie ','','','','','yu ','yu ','Mei ', + '','mao ','','fu ','','','','','','','','jian ','','','','', + '','','','','','','','','','','','','','','','', + '','Hau ','','','Ga ','','','','','','','','','','','Ge ', + ], + 'x2a1':[ + '','','xia ','','','Set ','','','','','qu ','','','','ge ','', + '','su ','','','','','','','','','','','','','','', + '','','','','','Cut ','','','','','','','','','hu ,gu','', + '','','','mai ','','','','','','','','','','','','', + '','','','','su ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','Cuoc ','Choi ','Ri ','Sam ','','','','Tu ','','', + '','','','','','','','','jie ','','','','','','','', + '','','qu ','','','','','','','','','xie ','','','','', + '','','','','','','','','','','','','','','','', + 'fu ','','','','','Khuou ','Tu ','','','','','','','','','', + 'ya ','liu ','','','','','can ','64272.110,chu ','','','','','','','','jian ', + '','','','','','','chu ,du','','ai ','','','Cui ','','','Quam ','', + '','xun ','','','','','','','','','','','','yu ','','', + '','','','','','','','','','Ngan ','','Cui ','','cai ','','liu ', + '','','jie ','','','','','','','la ','','','','','','', + ], + 'x2a2':[ + '','','','','','','','','lai ','','he ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','jue ','','','','guan ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Muoi ','','tan ','','En ','','','','','','kan ', + '','bian ','','','Muoi ','','','','','','','','','','','gan ', + '','','','','','Mam ','','gan ,tan','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','xiao ','','zhu ','','yu ','','','','', + '','jian ','','','','','','','','yu ','','','','zu ','','', + 'nuan ','','','','','','','','','','','','','su ','','', + '','pu ','','','','','','','','','','','','','yu ','', + '','','','','','','','','','','','','','','','', + ], + 'x2a3':[ + '','','','','','na ','qu ','','','','','tun ','','','','', + '','','','ku ','su ','','','','','','','','','','','ze ', + '','','','ge ','','','','jie ','','','tiao ','','','','','', + '','','','','','','shu ','','','','','','','hun ','','nie ', + '','jun ','hu ','','lu ','','','','chao ','','','','','','','fu ', + '','','','','','','','','','','','','','yun ','','', + '','','','','','','','xuan ','','','','','','','','', + '','','','','','','shan ','','Qu ','du ','','sao ','','','','kuang ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','liu ','','','','','','','','','','mei ','','', + '','','','','tun ','kang ','tun ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','heng ','','','','','','Huang ','','','','','','', + '','','','','','','','','','','kuang ','piao ','','','','', + '','','','hu ','','','bao ','','','','','hu ','','','','', + ], + 'x2a4':[ + 'Naa ','','','','','','bie ','','','','','','','','','', + '','','','','','','','','','','','','','dai ,tai','du ','', + '','','','','','tai ','','shu ','','','','','','','su ','', + '','','','','','','','','','','','','','','','', + '','','cha ','','lu ','','yu ','','yan ','','qiao ','','yu ','','','tu ', + '','Ngam ','tun ','','','','','','','','','','','yu ','','', + '','','','','','','','die ','cha ','dian ','','','','','','', + '','','','','','','','wai ','','','','','','zhai ','','', + '','','','','','','','','','','','','','','','lu ', + '','','','','','','','Tham ','','','','','ma ','','','', + '','','','','','','','','','','mai ','','Nung ','','','', + '','','','','','','','','','','','','','','dan ','teng ', + '','','','','','','','','','','yu ','','','','','', + '','','','','','','','','','','','','','','','', + '','cu ','','','','','','','','','','Sam ','','','','', + 'cu ','','','','','','','','','','','','','','','', + ], + 'x2a5':[ + '','','Ding ','','','','','','','','','','','peng ','','', + '','','','','','','','','','','','','','','','', + 'Trong ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','hu ','','','','','','', + '','','','','','','','','','','','','','cu ','jun ','', + '','','','','','','','','er ','','','','','ai ','hu ','', + '','hu ','','','','','','','','','','','','','','', + '','','','','jiao ','','','','pu ','','','jie ','lu ','','','', + 'yao ,ya','','','','','','','','','Hou ','','qiu ','jue ','','','', + '','','','','','','','','','xu ','','','','Ngui ','','', + '','','','','','','su ','liao ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','pa ','','','','','','','','','na ','','', + '','','','','','','zhan ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2a6':[ + '','Kap6','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','zu ','','','zhan ','','','','','', + '','','Ji ','','','Rang ','','','','he ','qia ','','','','','', + '','','','','','','','','hu ','','yan ','','','','','', + '','','','','','','','','','','','Nak ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','jue ','','','','','','','','','','', + '','','','','','','','','','','Trong ','','','','','', + '','','','','','zhe ','','','','Gwi ','','','gan ','','','cu ', + '','','','','','','','','','zhu ','','','','','','', + 'xiao ','','','','','Rua ','','Rua ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2a7':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2a8':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Bai ','','','','','','','Zhan ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Luan ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2aa':[ + '','','','','','','','','','','Song ','','','','','', + '','','','','','','','Jue ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Yong ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2ae':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','Nu ','','','','','','', + '','','','','','','','','','','','','','','','', + 'Cong ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2af':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Xian ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2b0':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','Li ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Fei ','','','','','','','', + '','','','','','','','','','Su ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','Kou ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2b1':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Chi ','','','','','','','', + '','','','','','','','','Xun ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2b2':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Qia ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Gong ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2b3':[ + 'Ji ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Luo ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','Yi ','','','','','','', + '','','Nao ','','','','','','','','','','','','','', + 'Xi ','','Xiao ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','Jiao ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2b4':[ + '','','','','Yue ','','Kuai ','','','Ling ','','','','','','', + 'Ni ','','','Bu ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','Han ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','Fu ','','Cong ','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2b5':[ + '','','','','','','','','','','','','','','Jue ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Duo ','','','','','','','Su ','','','','','','','Huang ','', + '','','','','','','','','','','','','','','','', + ], + 'x2b6':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Han ','Ai ','','','','Ti ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Xu ','Gong ','','','','','','', + '','','Ping ','','Hui ','Shi ','','','','Pu ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','Zhi ','','','Jue ','', + '','','Ning ','','','','','','','','','','','','','', + '','','','','','','Chi ','','Ti ','','','','','','','', + ], + 'x2f8':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Gai ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2f9':[ + '','','','','','','','Baan6','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ] +} diff --git a/ebook_converter/ebooks/unihandecode/krdecoder.py b/ebook_converter/ebooks/unihandecode/krdecoder.py new file mode 100644 index 0000000..914f6f4 --- /dev/null +++ b/ebook_converter/ebooks/unihandecode/krdecoder.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL 3' +__copyright__ = '2010, Hiroshi Miura ' +__docformat__ = 'restructuredtext en' + +''' +Decode unicode text to an ASCII representation of the text in Korean. +Based on unidecoder. + +''' + +from calibre.ebooks.unihandecode.unidecoder import Unidecoder +from calibre.ebooks.unihandecode.krcodepoints import CODEPOINTS as HANCODES +from calibre.ebooks.unihandecode.unicodepoints import CODEPOINTS + + +class Krdecoder(Unidecoder): + + codepoints = {} + + def __init__(self): + self.codepoints = CODEPOINTS + self.codepoints.update(HANCODES) diff --git a/ebook_converter/ebooks/unihandecode/unicodepoints.py b/ebook_converter/ebooks/unihandecode/unicodepoints.py new file mode 100644 index 0000000..13eeed2 --- /dev/null +++ b/ebook_converter/ebooks/unihandecode/unicodepoints.py @@ -0,0 +1,1799 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL 3' +__copyright__ = '2009, John Schember ' +__docformat__ = 'restructuredtext en' + +''' +Unicode code point dictionary. + +Based on Text::Unidecode's xAB.pm lists. This combines all xAB.pm files into +a single dictionary. +''' + + +CODEPOINTS = { + 'x20': [ + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '', '', '', '', + '-', '-', '-', '-', '--', '--', '||', '_', '\'', '\'', ',', '\'', '"', '"', ',,', '"', + '+', '++', '*', '*>', '.', '..', '...', '.', '\n', '\n\n', '', '', '', '', '', ' ', + '%0', '%00', '\'', '\'\'', '\'\'\'', '`', '``', '```', '^', '<', '>', '*', '!!', '!?', '-', '_', + '-', '^', '***', '--', '/', '-[', ']-', '[?]', '?!', '!?', '7', 'PP', '(]', '[)', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '', '', '', '', '', '', + '0', '', '', '', '4', '5', '6', '7', '8', '9', '+', '-', '=', '(', ')', 'n', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '-', '=', '(', ')', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + 'ECU', 'CL', 'Cr', 'FF', 'L', 'mil', 'N', 'Pts', 'Rs', 'W', 'NS', 'D', 'EU', 'K', 'T', 'Dr', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + ], + 'x25': [ + '-', '-', '|', '|', '-', '-', '|', '|', '-', '-', '|', '|', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '-', '-', '|', '|', + '-', '|', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '/', '\\', 'X', '-', '|', '-', '|', '-', '|', '-', '|', '-', '|', '-', '|', + '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', + '#', '#', '#', '#', '-', '|', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', + '#', '#', '^', '^', '^', '^', '>', '>', '>', '>', '>', '>', 'V', 'V', 'V', 'V', + '<', '<', '<', '<', '<', '<', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', + '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', + '*', '*', '*', '*', '*', '*', '*', '#', '#', '#', '#', '#', '^', '^', '^', 'O', + '#', '#', '#', '#', '#', '#', '#', '#', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + ], + 'x1e': [ + 'A', 'a', 'B', 'b', 'B', 'b', 'B', 'b', 'C', 'c', 'D', 'd', 'D', 'd', 'D', 'd', + 'D', 'd', 'D', 'd', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'F', 'f', + 'G', 'g', 'H', 'h', 'H', 'h', 'H', 'h', 'H', 'h', 'H', 'h', 'I', 'i', 'I', 'i', + 'K', 'k', 'K', 'k', 'K', 'k', 'L', 'l', 'L', 'l', 'L', 'l', 'L', 'l', 'M', 'm', + 'M', 'm', 'M', 'm', 'N', 'n', 'N', 'n', 'N', 'n', 'N', 'n', 'O', 'o', 'O', 'o', + 'O', 'o', 'O', 'o', 'P', 'p', 'P', 'p', 'R', 'r', 'R', 'r', 'R', 'r', 'R', 'r', + 'S', 's', 'S', 's', 'S', 's', 'S', 's', 'S', 's', 'T', 't', 'T', 't', 'T', 't', + 'T', 't', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'V', 'v', 'V', 'v', + 'W', 'w', 'W', 'w', 'W', 'w', 'W', 'w', 'W', 'w', 'X', 'x', 'X', 'x', 'Y', 'y', + 'Z', 'z', 'Z', 'z', 'Z', 'z', 'h', 't', 'w', 'y', 'a', 'S', '[?]', '[?]', '[?]', '[?]', + 'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a', + 'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', + 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'I', 'i', 'I', 'i', 'O', 'o', 'O', 'o', + 'O', 'o', 'O', 'o', 'O', 'o', 'O', 'o', 'O', 'o', 'O', 'o', 'O', 'o', 'O', 'o', + 'O', 'o', 'O', 'o', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', + 'U', 'u', 'Y', 'y', 'Y', 'y', 'Y', 'y', 'Y', 'y', '[?]', '[?]', '[?]', '[?]', '[?]', + ], + 'xae': [ + 'geul', 'geulg', 'geulm', 'geulb', 'geuls', 'geult', 'geulp', 'geulh', 'geum', 'geub', 'geubs', 'geus', 'geuss', 'geung', 'geuj', 'geuc', + 'geuk', 'geut', 'geup', 'geuh', 'gyi', 'gyig', 'gyigg', 'gyigs', 'gyin', 'gyinj', 'gyinh', 'gyid', 'gyil', 'gyilg', 'gyilm', 'gyilb', + 'gyils', 'gyilt', 'gyilp', 'gyilh', 'gyim', 'gyib', 'gyibs', 'gyis', 'gyiss', 'gying', 'gyij', 'gyic', 'gyik', 'gyit', 'gyip', 'gyih', + 'gi', 'gig', 'gigg', 'gigs', 'gin', 'ginj', 'ginh', 'gid', 'gil', 'gilg', 'gilm', 'gilb', 'gils', 'gilt', 'gilp', 'gilh', + 'gim', 'gib', 'gibs', 'gis', 'giss', 'ging', 'gij', 'gic', 'gik', 'git', 'gip', 'gih', 'gga', 'ggag', 'ggagg', 'ggags', + 'ggan', 'gganj', 'gganh', 'ggad', 'ggal', 'ggalg', 'ggalm', 'ggalb', 'ggals', 'ggalt', 'ggalp', 'ggalh', 'ggam', 'ggab', 'ggabs', 'ggas', + 'ggass', 'ggang', 'ggaj', 'ggac', 'ggak', 'ggat', 'ggap', 'ggah', 'ggae', 'ggaeg', 'ggaegg', 'ggaegs', 'ggaen', 'ggaenj', 'ggaenh', 'ggaed', + 'ggael', 'ggaelg', 'ggaelm', 'ggaelb', 'ggaels', 'ggaelt', 'ggaelp', 'ggaelh', 'ggaem', 'ggaeb', 'ggaebs', 'ggaes', 'ggaess', 'ggaeng', 'ggaej', 'ggaec', + 'ggaek', 'ggaet', 'ggaep', 'ggaeh', 'ggya', 'ggyag', 'ggyagg', 'ggyags', 'ggyan', 'ggyanj', 'ggyanh', 'ggyad', 'ggyal', 'ggyalg', 'ggyalm', 'ggyalb', + 'ggyals', 'ggyalt', 'ggyalp', 'ggyalh', 'ggyam', 'ggyab', 'ggyabs', 'ggyas', 'ggyass', 'ggyang', 'ggyaj', 'ggyac', 'ggyak', 'ggyat', 'ggyap', 'ggyah', + 'ggyae', 'ggyaeg', 'ggyaegg', 'ggyaegs', 'ggyaen', 'ggyaenj', 'ggyaenh', 'ggyaed', 'ggyael', 'ggyaelg', 'ggyaelm', 'ggyaelb', 'ggyaels', 'ggyaelt', 'ggyaelp', 'ggyaelh', + 'ggyaem', 'ggyaeb', 'ggyaebs', 'ggyaes', 'ggyaess', 'ggyaeng', 'ggyaej', 'ggyaec', 'ggyaek', 'ggyaet', 'ggyaep', 'ggyaeh', 'ggeo', 'ggeog', 'ggeogg', 'ggeogs', + 'ggeon', 'ggeonj', 'ggeonh', 'ggeod', 'ggeol', 'ggeolg', 'ggeolm', 'ggeolb', 'ggeols', 'ggeolt', 'ggeolp', 'ggeolh', 'ggeom', 'ggeob', 'ggeobs', 'ggeos', + 'ggeoss', 'ggeong', 'ggeoj', 'ggeoc', 'ggeok', 'ggeot', 'ggeop', 'ggeoh', 'gge', 'ggeg', 'ggegg', 'ggegs', 'ggen', 'ggenj', 'ggenh', 'gged', + 'ggel', 'ggelg', 'ggelm', 'ggelb', 'ggels', 'ggelt', 'ggelp', 'ggelh', 'ggem', 'ggeb', 'ggebs', 'gges', 'ggess', 'ggeng', 'ggej', 'ggec', + 'ggek', 'gget', 'ggep', 'ggeh', 'ggyeo', 'ggyeog', 'ggyeogg', 'ggyeogs', 'ggyeon', 'ggyeonj', 'ggyeonh', 'ggyeod', 'ggyeol', 'ggyeolg', 'ggyeolm', 'ggyeolb', + ], + 'xa2': [ + 'kax', 'ka', 'kap', 'kuox', 'kuo', 'kuop', 'kot', 'kox', 'ko', 'kop', 'ket', 'kex', 'ke', 'kep', 'kut', 'kux', + 'ku', 'kup', 'kurx', 'kur', 'ggit', 'ggix', 'ggi', 'ggiex', 'ggie', 'ggiep', 'ggat', 'ggax', 'gga', 'ggap', 'gguot', 'gguox', + 'gguo', 'gguop', 'ggot', 'ggox', 'ggo', 'ggop', 'gget', 'ggex', 'gge', 'ggep', 'ggut', 'ggux', 'ggu', 'ggup', 'ggurx', 'ggur', + 'mgiex', 'mgie', 'mgat', 'mgax', 'mga', 'mgap', 'mguox', 'mguo', 'mguop', 'mgot', 'mgox', 'mgo', 'mgop', 'mgex', 'mge', 'mgep', + 'mgut', 'mgux', 'mgu', 'mgup', 'mgurx', 'mgur', 'hxit', 'hxix', 'hxi', 'hxip', 'hxiet', 'hxiex', 'hxie', 'hxiep', 'hxat', 'hxax', + 'hxa', 'hxap', 'hxuot', 'hxuox', 'hxuo', 'hxuop', 'hxot', 'hxox', 'hxo', 'hxop', 'hxex', 'hxe', 'hxep', 'ngiex', 'ngie', 'ngiep', + 'ngat', 'ngax', 'nga', 'ngap', 'nguot', 'nguox', 'nguo', 'ngot', 'ngox', 'ngo', 'ngop', 'ngex', 'nge', 'ngep', 'hit', 'hiex', + 'hie', 'hat', 'hax', 'ha', 'hap', 'huot', 'huox', 'huo', 'huop', 'hot', 'hox', 'ho', 'hop', 'hex', 'he', 'hep', + 'wat', 'wax', 'wa', 'wap', 'wuox', 'wuo', 'wuop', 'wox', 'wo', 'wop', 'wex', 'we', 'wep', 'zit', 'zix', 'zi', + 'zip', 'ziex', 'zie', 'ziep', 'zat', 'zax', 'za', 'zap', 'zuox', 'zuo', 'zuop', 'zot', 'zox', 'zo', 'zop', 'zex', + 'ze', 'zep', 'zut', 'zux', 'zu', 'zup', 'zurx', 'zur', 'zyt', 'zyx', 'zy', 'zyp', 'zyrx', 'zyr', 'cit', 'cix', + 'ci', 'cip', 'ciet', 'ciex', 'cie', 'ciep', 'cat', 'cax', 'ca', 'cap', 'cuox', 'cuo', 'cuop', 'cot', 'cox', 'co', + 'cop', 'cex', 'ce', 'cep', 'cut', 'cux', 'cu', 'cup', 'curx', 'cur', 'cyt', 'cyx', 'cy', 'cyp', 'cyrx', 'cyr', + 'zzit', 'zzix', 'zzi', 'zzip', 'zziet', 'zziex', 'zzie', 'zziep', 'zzat', 'zzax', 'zza', 'zzap', 'zzox', 'zzo', 'zzop', 'zzex', + 'zze', 'zzep', 'zzux', 'zzu', 'zzup', 'zzurx', 'zzur', 'zzyt', 'zzyx', 'zzy', 'zzyp', 'zzyrx', 'zzyr', 'nzit', 'nzix', 'nzi', + 'nzip', 'nziex', 'nzie', 'nziep', 'nzat', 'nzax', 'nza', 'nzap', 'nzuox', 'nzuo', 'nzox', 'nzop', 'nzex', 'nze', 'nzux', 'nzu', + ], + 'xc2': [ + 'syon', 'syonj', 'syonh', 'syod', 'syol', 'syolg', 'syolm', 'syolb', 'syols', 'syolt', 'syolp', 'syolh', 'syom', 'syob', 'syobs', 'syos', + 'syoss', 'syong', 'syoj', 'syoc', 'syok', 'syot', 'syop', 'syoh', 'su', 'sug', 'sugg', 'sugs', 'sun', 'sunj', 'sunh', 'sud', + 'sul', 'sulg', 'sulm', 'sulb', 'suls', 'sult', 'sulp', 'sulh', 'sum', 'sub', 'subs', 'sus', 'suss', 'sung', 'suj', 'suc', + 'suk', 'sut', 'sup', 'suh', 'sweo', 'sweog', 'sweogg', 'sweogs', 'sweon', 'sweonj', 'sweonh', 'sweod', 'sweol', 'sweolg', 'sweolm', 'sweolb', + 'sweols', 'sweolt', 'sweolp', 'sweolh', 'sweom', 'sweob', 'sweobs', 'sweos', 'sweoss', 'sweong', 'sweoj', 'sweoc', 'sweok', 'sweot', 'sweop', 'sweoh', + 'swe', 'sweg', 'swegg', 'swegs', 'swen', 'swenj', 'swenh', 'swed', 'swel', 'swelg', 'swelm', 'swelb', 'swels', 'swelt', 'swelp', 'swelh', + 'swem', 'sweb', 'swebs', 'swes', 'swess', 'sweng', 'swej', 'swec', 'swek', 'swet', 'swep', 'sweh', 'swi', 'swig', 'swigg', 'swigs', + 'swin', 'swinj', 'swinh', 'swid', 'swil', 'swilg', 'swilm', 'swilb', 'swils', 'swilt', 'swilp', 'swilh', 'swim', 'swib', 'swibs', 'swis', + 'swiss', 'swing', 'swij', 'swic', 'swik', 'swit', 'swip', 'swih', 'syu', 'syug', 'syugg', 'syugs', 'syun', 'syunj', 'syunh', 'syud', + 'syul', 'syulg', 'syulm', 'syulb', 'syuls', 'syult', 'syulp', 'syulh', 'syum', 'syub', 'syubs', 'syus', 'syuss', 'syung', 'syuj', 'syuc', + 'syuk', 'syut', 'syup', 'syuh', 'seu', 'seug', 'seugg', 'seugs', 'seun', 'seunj', 'seunh', 'seud', 'seul', 'seulg', 'seulm', 'seulb', + 'seuls', 'seult', 'seulp', 'seulh', 'seum', 'seub', 'seubs', 'seus', 'seuss', 'seung', 'seuj', 'seuc', 'seuk', 'seut', 'seup', 'seuh', + 'syi', 'syig', 'syigg', 'syigs', 'syin', 'syinj', 'syinh', 'syid', 'syil', 'syilg', 'syilm', 'syilb', 'syils', 'syilt', 'syilp', 'syilh', + 'syim', 'syib', 'syibs', 'syis', 'syiss', 'sying', 'syij', 'syic', 'syik', 'syit', 'syip', 'syih', 'si', 'sig', 'sigg', 'sigs', + 'sin', 'sinj', 'sinh', 'sid', 'sil', 'silg', 'silm', 'silb', 'sils', 'silt', 'silp', 'silh', 'sim', 'sib', 'sibs', 'sis', + 'siss', 'sing', 'sij', 'sic', 'sik', 'sit', 'sip', 'sih', 'ssa', 'ssag', 'ssagg', 'ssags', 'ssan', 'ssanj', 'ssanh', 'ssad', + ], + 'x03': [ + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '', '', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '\'', ',', '[?]', '[?]', '[?]', '[?]', '', '[?]', '[?]', '[?]', '?', '[?]', + '[?]', '[?]', '[?]', '[?]', '', '', 'A', ';', 'E', 'E', 'I', '[?]', 'O', '[?]', 'U', 'O', + 'I', 'A', 'B', 'G', 'D', 'E', 'Z', 'E', 'Th', 'I', 'K', 'L', 'M', 'N', 'Ks', 'O', + 'P', 'R', '[?]', 'S', 'T', 'U', 'Ph', 'Kh', 'Ps', 'O', 'I', 'U', 'a', 'e', 'e', 'i', + 'u', 'a', 'b', 'g', 'd', 'e', 'z', 'e', 'th', 'i', 'k', 'l', 'm', 'n', 'x', 'o', + 'p', 'r', 's', 's', 't', 'u', 'ph', 'kh', 'ps', 'o', 'i', 'u', 'o', 'u', 'o', '[?]', + 'b', 'th', 'U', 'U', 'U', 'ph', 'p', '&', '[?]', '[?]', 'St', 'st', 'W', 'w', 'Q', 'q', + 'Sp', 'sp', 'Sh', 'sh', 'F', 'f', 'Kh', 'kh', 'H', 'h', 'G', 'g', 'CH', 'ch', 'Ti', 'ti', + 'k', 'r', 'c', 'j', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + ], + 'xc5': [ + 'sseum', 'sseub', 'sseubs', 'sseus', 'sseuss', 'sseung', 'sseuj', 'sseuc', 'sseuk', 'sseut', 'sseup', 'sseuh', 'ssyi', 'ssyig', 'ssyigg', 'ssyigs', + 'ssyin', 'ssyinj', 'ssyinh', 'ssyid', 'ssyil', 'ssyilg', 'ssyilm', 'ssyilb', 'ssyils', 'ssyilt', 'ssyilp', 'ssyilh', 'ssyim', 'ssyib', 'ssyibs', 'ssyis', + 'ssyiss', 'ssying', 'ssyij', 'ssyic', 'ssyik', 'ssyit', 'ssyip', 'ssyih', 'ssi', 'ssig', 'ssigg', 'ssigs', 'ssin', 'ssinj', 'ssinh', 'ssid', + 'ssil', 'ssilg', 'ssilm', 'ssilb', 'ssils', 'ssilt', 'ssilp', 'ssilh', 'ssim', 'ssib', 'ssibs', 'ssis', 'ssiss', 'ssing', 'ssij', 'ssic', + 'ssik', 'ssit', 'ssip', 'ssih', 'a', 'ag', 'agg', 'ags', 'an', 'anj', 'anh', 'ad', 'al', 'alg', 'alm', 'alb', + 'als', 'alt', 'alp', 'alh', 'am', 'ab', 'abs', 'as', 'ass', 'ang', 'aj', 'ac', 'ak', 'at', 'ap', 'ah', + 'ae', 'aeg', 'aegg', 'aegs', 'aen', 'aenj', 'aenh', 'aed', 'ael', 'aelg', 'aelm', 'aelb', 'aels', 'aelt', 'aelp', 'aelh', + 'aem', 'aeb', 'aebs', 'aes', 'aess', 'aeng', 'aej', 'aec', 'aek', 'aet', 'aep', 'aeh', 'ya', 'yag', 'yagg', 'yags', + 'yan', 'yanj', 'yanh', 'yad', 'yal', 'yalg', 'yalm', 'yalb', 'yals', 'yalt', 'yalp', 'yalh', 'yam', 'yab', 'yabs', 'yas', + 'yass', 'yang', 'yaj', 'yac', 'yak', 'yat', 'yap', 'yah', 'yae', 'yaeg', 'yaegg', 'yaegs', 'yaen', 'yaenj', 'yaenh', 'yaed', + 'yael', 'yaelg', 'yaelm', 'yaelb', 'yaels', 'yaelt', 'yaelp', 'yaelh', 'yaem', 'yaeb', 'yaebs', 'yaes', 'yaess', 'yaeng', 'yaej', 'yaec', + 'yaek', 'yaet', 'yaep', 'yaeh', 'eo', 'eog', 'eogg', 'eogs', 'eon', 'eonj', 'eonh', 'eod', 'eol', 'eolg', 'eolm', 'eolb', + 'eols', 'eolt', 'eolp', 'eolh', 'eom', 'eob', 'eobs', 'eos', 'eoss', 'eong', 'eoj', 'eoc', 'eok', 'eot', 'eop', 'eoh', + 'e', 'eg', 'egg', 'egs', 'en', 'enj', 'enh', 'ed', 'el', 'elg', 'elm', 'elb', 'els', 'elt', 'elp', 'elh', + 'em', 'eb', 'ebs', 'es', 'ess', 'eng', 'ej', 'ec', 'ek', 'et', 'ep', 'eh', 'yeo', 'yeog', 'yeogg', 'yeogs', + 'yeon', 'yeonj', 'yeonh', 'yeod', 'yeol', 'yeolg', 'yeolm', 'yeolb', 'yeols', 'yeolt', 'yeolp', 'yeolh', 'yeom', 'yeob', 'yeobs', 'yeos', + ], + 'xfb': [ + 'ff', 'fi', 'fl', 'ffi', 'ffl', 'st', 'st', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', 'mn', 'me', 'mi', 'vn', 'mkh', '[?]', '[?]', '[?]', '[?]', '[?]', 'yi', '', 'ay', + '`', '', 'd', 'h', 'k', 'l', 'm', 'm', 't', '+', 'sh', 's', 'sh', 's', 'a', 'a', + '', 'b', 'g', 'd', 'h', 'v', 'z', '[?]', 't', 'y', 'k', 'k', 'l', '[?]', 'l', '[?]', + 'n', 'n', '[?]', 'p', 'p', '[?]', 'ts', 'ts', 'r', 'sh', 't', 'vo', 'b', 'k', 'p', 'l', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + ], + 'x06': [ + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', ',', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', ';', '[?]', '[?]', '[?]', '?', + '[?]', '', 'a', '\'', 'w\'', '', 'y\'', 'a', 'b', '@', 't', 'th', 'j', 'H', 'kh', 'd', + 'dh', 'r', 'z', 's', 'sh', 'S', 'D', 'T', 'Z', '`', 'G', '[?]', '[?]', '[?]', '[?]', '[?]', + '', 'f', 'q', 'k', 'l', 'm', 'n', 'h', 'w', '~', 'y', 'an', 'un', 'in', 'a', 'u', + 'i', 'W', '', '', '\'', '\'', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '%', '.', ',', '*', '[?]', '[?]', + '', '\'', '\'', '\'', '', '\'', '\'w', '\'u', '\'y', 'tt', 'tth', 'b', 't', 'T', 'p', 'th', + 'bh', '\'h', 'H', 'ny', 'dy', 'H', 'ch', 'cch', 'dd', 'D', 'D', 'Dt', 'dh', 'ddh', 'd', 'D', + 'D', 'rr', 'R', 'R', 'R', 'R', 'R', 'R', 'j', 'R', 'S', 'S', 'S', 'S', 'S', 'T', + 'GH', 'F', 'F', 'F', 'v', 'f', 'ph', 'Q', 'Q', 'kh', 'k', 'K', 'K', 'ng', 'K', 'g', + 'G', 'N', 'G', 'G', 'G', 'L', 'L', 'L', 'L', 'N', 'N', 'N', 'N', 'N', 'h', 'Ch', + 'hy', 'h', 'H', '@', 'W', 'oe', 'oe', 'u', 'yu', 'yu', 'W', 'v', 'y', 'Y', 'Y', 'W', + '', '', 'y', 'y\'', '.', 'ae', '', '', '', '', '', '', '', '@', '#', '', + '', '', '', '', '', '', '', '', '', '^', '', '', '', '', '[?]', '[?]', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'Sh', 'D', 'Gh', '&', '+m', + ], + 'x07': [ + '//', '/', ',', '!', '!', '-', ',', ',', ';', '?', '~', '\\{', '\\}', '*', '[?]', '', + '\'', '', 'b', 'g', 'g', 'd', 'd', 'h', 'w', 'z', 'H', 't', 't', 'y', 'yh', 'k', + 'l', 'm', 'n', 's', 's', '`', 'p', 'p', 'S', 'q', 'r', 'sh', 't', '[?]', '[?]', '[?]', + 'a', 'a', 'a', 'A', 'A', 'A', 'e', 'e', 'e', 'E', 'i', 'i', 'u', 'u', 'u', 'o', + '', '`', '\'', '', '', 'X', 'Q', '@', '@', '|', '+', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + 'h', 'sh', 'n', 'r', 'b', 'L', 'k', '\'', 'v', 'm', 'f', 'dh', 'th', 'l', 'g', 'ny', + 's', 'd', 'z', 't', 'y', 'p', 'j', 'ch', 'tt', 'hh', 'kh', 'th', 'z', 'sh', 's', 'd', + 't', 'z', '`', 'gh', 'q', 'w', 'a', 'aa', 'i', 'ee', 'u', 'oo', 'e', 'ey', 'o', 'oa', + '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + ], + 'xcc': [ + 'jjyim', 'jjyib', 'jjyibs', 'jjyis', 'jjyiss', 'jjying', 'jjyij', 'jjyic', 'jjyik', 'jjyit', 'jjyip', 'jjyih', 'jji', 'jjig', 'jjigg', 'jjigs', + 'jjin', 'jjinj', 'jjinh', 'jjid', 'jjil', 'jjilg', 'jjilm', 'jjilb', 'jjils', 'jjilt', 'jjilp', 'jjilh', 'jjim', 'jjib', 'jjibs', 'jjis', + 'jjiss', 'jjing', 'jjij', 'jjic', 'jjik', 'jjit', 'jjip', 'jjih', 'ca', 'cag', 'cagg', 'cags', 'can', 'canj', 'canh', 'cad', + 'cal', 'calg', 'calm', 'calb', 'cals', 'calt', 'calp', 'calh', 'cam', 'cab', 'cabs', 'cas', 'cass', 'cang', 'caj', 'cac', + 'cak', 'cat', 'cap', 'cah', 'cae', 'caeg', 'caegg', 'caegs', 'caen', 'caenj', 'caenh', 'caed', 'cael', 'caelg', 'caelm', 'caelb', + 'caels', 'caelt', 'caelp', 'caelh', 'caem', 'caeb', 'caebs', 'caes', 'caess', 'caeng', 'caej', 'caec', 'caek', 'caet', 'caep', 'caeh', + 'cya', 'cyag', 'cyagg', 'cyags', 'cyan', 'cyanj', 'cyanh', 'cyad', 'cyal', 'cyalg', 'cyalm', 'cyalb', 'cyals', 'cyalt', 'cyalp', 'cyalh', + 'cyam', 'cyab', 'cyabs', 'cyas', 'cyass', 'cyang', 'cyaj', 'cyac', 'cyak', 'cyat', 'cyap', 'cyah', 'cyae', 'cyaeg', 'cyaegg', 'cyaegs', + 'cyaen', 'cyaenj', 'cyaenh', 'cyaed', 'cyael', 'cyaelg', 'cyaelm', 'cyaelb', 'cyaels', 'cyaelt', 'cyaelp', 'cyaelh', 'cyaem', 'cyaeb', 'cyaebs', 'cyaes', + 'cyaess', 'cyaeng', 'cyaej', 'cyaec', 'cyaek', 'cyaet', 'cyaep', 'cyaeh', 'ceo', 'ceog', 'ceogg', 'ceogs', 'ceon', 'ceonj', 'ceonh', 'ceod', + 'ceol', 'ceolg', 'ceolm', 'ceolb', 'ceols', 'ceolt', 'ceolp', 'ceolh', 'ceom', 'ceob', 'ceobs', 'ceos', 'ceoss', 'ceong', 'ceoj', 'ceoc', + 'ceok', 'ceot', 'ceop', 'ceoh', 'ce', 'ceg', 'cegg', 'cegs', 'cen', 'cenj', 'cenh', 'ced', 'cel', 'celg', 'celm', 'celb', + 'cels', 'celt', 'celp', 'celh', 'cem', 'ceb', 'cebs', 'ces', 'cess', 'ceng', 'cej', 'cec', 'cek', 'cet', 'cep', 'ceh', + 'cyeo', 'cyeog', 'cyeogg', 'cyeogs', 'cyeon', 'cyeonj', 'cyeonh', 'cyeod', 'cyeol', 'cyeolg', 'cyeolm', 'cyeolb', 'cyeols', 'cyeolt', 'cyeolp', 'cyeolh', + 'cyeom', 'cyeob', 'cyeobs', 'cyeos', 'cyeoss', 'cyeong', 'cyeoj', 'cyeoc', 'cyeok', 'cyeot', 'cyeop', 'cyeoh', 'cye', 'cyeg', 'cyegg', 'cyegs', + 'cyen', 'cyenj', 'cyenh', 'cyed', 'cyel', 'cyelg', 'cyelm', 'cyelb', 'cyels', 'cyelt', 'cyelp', 'cyelh', 'cyem', 'cyeb', 'cyebs', 'cyes', + ], + 'xc6': [ + 'yeoss', 'yeong', 'yeoj', 'yeoc', 'yeok', 'yeot', 'yeop', 'yeoh', 'ye', 'yeg', 'yegg', 'yegs', 'yen', 'yenj', 'yenh', 'yed', + 'yel', 'yelg', 'yelm', 'yelb', 'yels', 'yelt', 'yelp', 'yelh', 'yem', 'yeb', 'yebs', 'yes', 'yess', 'yeng', 'yej', 'yec', + 'yek', 'yet', 'yep', 'yeh', 'o', 'og', 'ogg', 'ogs', 'on', 'onj', 'onh', 'od', 'ol', 'olg', 'olm', 'olb', + 'ols', 'olt', 'olp', 'olh', 'om', 'ob', 'obs', 'os', 'oss', 'ong', 'oj', 'oc', 'ok', 'ot', 'op', 'oh', + 'wa', 'wag', 'wagg', 'wags', 'wan', 'wanj', 'wanh', 'wad', 'wal', 'walg', 'walm', 'walb', 'wals', 'walt', 'walp', 'walh', + 'wam', 'wab', 'wabs', 'was', 'wass', 'wang', 'waj', 'wac', 'wak', 'wat', 'wap', 'wah', 'wae', 'waeg', 'waegg', 'waegs', + 'waen', 'waenj', 'waenh', 'waed', 'wael', 'waelg', 'waelm', 'waelb', 'waels', 'waelt', 'waelp', 'waelh', 'waem', 'waeb', 'waebs', 'waes', + 'waess', 'waeng', 'waej', 'waec', 'waek', 'waet', 'waep', 'waeh', 'oe', 'oeg', 'oegg', 'oegs', 'oen', 'oenj', 'oenh', 'oed', + 'oel', 'oelg', 'oelm', 'oelb', 'oels', 'oelt', 'oelp', 'oelh', 'oem', 'oeb', 'oebs', 'oes', 'oess', 'oeng', 'oej', 'oec', + 'oek', 'oet', 'oep', 'oeh', 'yo', 'yog', 'yogg', 'yogs', 'yon', 'yonj', 'yonh', 'yod', 'yol', 'yolg', 'yolm', 'yolb', + 'yols', 'yolt', 'yolp', 'yolh', 'yom', 'yob', 'yobs', 'yos', 'yoss', 'yong', 'yoj', 'yoc', 'yok', 'yot', 'yop', 'yoh', + 'u', 'ug', 'ugg', 'ugs', 'un', 'unj', 'unh', 'ud', 'ul', 'ulg', 'ulm', 'ulb', 'uls', 'ult', 'ulp', 'ulh', + 'um', 'ub', 'ubs', 'us', 'uss', 'ung', 'uj', 'uc', 'uk', 'ut', 'up', 'uh', 'weo', 'weog', 'weogg', 'weogs', + 'weon', 'weonj', 'weonh', 'weod', 'weol', 'weolg', 'weolm', 'weolb', 'weols', 'weolt', 'weolp', 'weolh', 'weom', 'weob', 'weobs', 'weos', + 'weoss', 'weong', 'weoj', 'weoc', 'weok', 'weot', 'weop', 'weoh', 'we', 'weg', 'wegg', 'wegs', 'wen', 'wenj', 'wenh', 'wed', + 'wel', 'welg', 'welm', 'welb', 'wels', 'welt', 'welp', 'welh', 'wem', 'web', 'webs', 'wes', 'wess', 'weng', 'wej', 'wec', + ], + 'xb8': [ + 'reoss', 'reong', 'reoj', 'reoc', 'reok', 'reot', 'reop', 'reoh', 're', 'reg', 'regg', 'regs', 'ren', 'renj', 'renh', 'red', + 'rel', 'relg', 'relm', 'relb', 'rels', 'relt', 'relp', 'relh', 'rem', 'reb', 'rebs', 'res', 'ress', 'reng', 'rej', 'rec', + 'rek', 'ret', 'rep', 'reh', 'ryeo', 'ryeog', 'ryeogg', 'ryeogs', 'ryeon', 'ryeonj', 'ryeonh', 'ryeod', 'ryeol', 'ryeolg', 'ryeolm', 'ryeolb', + 'ryeols', 'ryeolt', 'ryeolp', 'ryeolh', 'ryeom', 'ryeob', 'ryeobs', 'ryeos', 'ryeoss', 'ryeong', 'ryeoj', 'ryeoc', 'ryeok', 'ryeot', 'ryeop', 'ryeoh', + 'rye', 'ryeg', 'ryegg', 'ryegs', 'ryen', 'ryenj', 'ryenh', 'ryed', 'ryel', 'ryelg', 'ryelm', 'ryelb', 'ryels', 'ryelt', 'ryelp', 'ryelh', + 'ryem', 'ryeb', 'ryebs', 'ryes', 'ryess', 'ryeng', 'ryej', 'ryec', 'ryek', 'ryet', 'ryep', 'ryeh', 'ro', 'rog', 'rogg', 'rogs', + 'ron', 'ronj', 'ronh', 'rod', 'rol', 'rolg', 'rolm', 'rolb', 'rols', 'rolt', 'rolp', 'rolh', 'rom', 'rob', 'robs', 'ros', + 'ross', 'rong', 'roj', 'roc', 'rok', 'rot', 'rop', 'roh', 'rwa', 'rwag', 'rwagg', 'rwags', 'rwan', 'rwanj', 'rwanh', 'rwad', + 'rwal', 'rwalg', 'rwalm', 'rwalb', 'rwals', 'rwalt', 'rwalp', 'rwalh', 'rwam', 'rwab', 'rwabs', 'rwas', 'rwass', 'rwang', 'rwaj', 'rwac', + 'rwak', 'rwat', 'rwap', 'rwah', 'rwae', 'rwaeg', 'rwaegg', 'rwaegs', 'rwaen', 'rwaenj', 'rwaenh', 'rwaed', 'rwael', 'rwaelg', 'rwaelm', 'rwaelb', + 'rwaels', 'rwaelt', 'rwaelp', 'rwaelh', 'rwaem', 'rwaeb', 'rwaebs', 'rwaes', 'rwaess', 'rwaeng', 'rwaej', 'rwaec', 'rwaek', 'rwaet', 'rwaep', 'rwaeh', + 'roe', 'roeg', 'roegg', 'roegs', 'roen', 'roenj', 'roenh', 'roed', 'roel', 'roelg', 'roelm', 'roelb', 'roels', 'roelt', 'roelp', 'roelh', + 'roem', 'roeb', 'roebs', 'roes', 'roess', 'roeng', 'roej', 'roec', 'roek', 'roet', 'roep', 'roeh', 'ryo', 'ryog', 'ryogg', 'ryogs', + 'ryon', 'ryonj', 'ryonh', 'ryod', 'ryol', 'ryolg', 'ryolm', 'ryolb', 'ryols', 'ryolt', 'ryolp', 'ryolh', 'ryom', 'ryob', 'ryobs', 'ryos', + 'ryoss', 'ryong', 'ryoj', 'ryoc', 'ryok', 'ryot', 'ryop', 'ryoh', 'ru', 'rug', 'rugg', 'rugs', 'run', 'runj', 'runh', 'rud', + 'rul', 'rulg', 'rulm', 'rulb', 'ruls', 'rult', 'rulp', 'rulh', 'rum', 'rub', 'rubs', 'rus', 'russ', 'rung', 'ruj', 'ruc', + ], + 'x33': [ + 'apartment', 'alpha', 'ampere', 'are', 'inning', 'inch', 'won', 'escudo', 'acre', 'ounce', 'ohm', 'kai-ri', 'carat', 'calorie', 'gallon', 'gamma', + 'giga', 'guinea', 'curie', 'guilder', 'kilo', 'kilogram', 'kilometer', 'kilowatt', 'gram', 'gram ton', 'cruzeiro', 'krone', 'case', 'koruna', 'co-op', 'cycle', + 'centime', 'shilling', 'centi', 'cent', 'dozen', 'desi', 'dollar', 'ton', 'nano', 'knot', 'heights', 'percent', 'parts', 'barrel', 'piaster', 'picul', + 'pico', 'building', 'farad', 'feet', 'bushel', 'franc', 'hectare', 'peso', 'pfennig', 'hertz', 'pence', 'page', 'beta', 'point', 'volt', 'hon', + 'pound', 'hall', 'horn', 'micro', 'mile', 'mach', 'mark', 'mansion', 'micron', 'milli', 'millibar', 'mega', 'megaton', 'meter', 'yard', 'yard', + 'yuan', 'liter', 'lira', 'rupee', 'ruble', 'rem', 'roentgen', 'watt', '0h', '1h', '2h', '3h', '4h', '5h', '6h', '7h', + '8h', '9h', '10h', '11h', '12h', '13h', '14h', '15h', '16h', '17h', '18h', '19h', '20h', '21h', '22h', '23h', + '24h', 'HPA', 'da', 'AU', 'bar', 'oV', 'pc', '[?]', '[?]', '[?]', '[?]', 'Heisei', 'Syouwa', 'Taisyou', 'Meiji', 'Inc.', + 'pA', 'nA', 'microamp', 'mA', 'kA', 'kB', 'MB', 'GB', 'cal', 'kcal', 'pF', 'nF', 'microFarad', 'microgram', 'mg', 'kg', + 'Hz', 'kHz', 'MHz', 'GHz', 'THz', 'microliter', 'ml', 'dl', 'kl', 'fm', 'nm', 'micrometer', 'mm', 'cm', 'km', 'mm^2', + 'cm^2', 'm^2', 'km^2', 'mm^4', 'cm^3', 'm^3', 'km^3', 'm/s', 'm/s^2', 'Pa', 'kPa', 'MPa', 'GPa', 'rad', 'rad/s', 'rad/s^2', + 'ps', 'ns', 'microsecond', 'ms', 'pV', 'nV', 'microvolt', 'mV', 'kV', 'MV', 'pW', 'nW', 'microwatt', 'mW', 'kW', 'MW', + 'kOhm', 'MOhm', 'a.m.', 'Bq', 'cc', 'cd', 'C/kg', 'Co.', 'dB', 'Gy', 'ha', 'HP', 'in', 'K.K.', 'KM', 'kt', + 'lm', 'ln', 'log', 'lx', 'mb', 'mil', 'mol', 'pH', 'p.m.', 'PPM', 'PR', 'sr', 'Sv', 'Wb', '[?]', '[?]', + '1d', '2d', '3d', '4d', '5d', '6d', '7d', '8d', '9d', '10d', '11d', '12d', '13d', '14d', '15d', '16d', + '17d', '18d', '19d', '20d', '21d', '22d', '23d', '24d', '25d', '26d', '27d', '28d', '29d', '30d', '31d', + ], + 'x32': [ + '(g)', '(n)', '(d)', '(r)', '(m)', '(b)', '(s)', '()', '(j)', '(c)', '(k)', '(t)', '(p)', '(h)', '(ga)', '(na)', + '(da)', '(ra)', '(ma)', '(ba)', '(sa)', '(a)', '(ja)', '(ca)', '(ka)', '(ta)', '(pa)', '(ha)', '(ju)', '[?]', '[?]', '[?]', + '(1) ', '(2) ', '(3) ', '(4) ', '(5) ', '(6) ', '(7) ', '(8) ', '(9) ', '(10) ', '(Yue) ', '(Huo) ', '(Shui) ', '(Mu) ', '(Jin) ', '(Tu) ', + '(Ri) ', '(Zhu) ', '(You) ', '(She) ', '(Ming) ', '(Te) ', '(Cai) ', '(Zhu) ', '(Lao) ', '(Dai) ', '(Hu) ', '(Xue) ', '(Jian) ', '(Qi) ', '(Zi) ', '(Xie) ', + '(Ji) ', '(Xiu) ', '<<', '>>', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '(g)', '(n)', '(d)', '(r)', '(m)', '(b)', '(s)', '()', '(j)', '(c)', '(k)', '(t)', '(p)', '(h)', '(ga)', '(na)', + '(da)', '(ra)', '(ma)', '(ba)', '(sa)', '(a)', '(ja)', '(ca)', '(ka)', '(ta)', '(pa)', '(ha)', '[?]', '[?]', '[?]', 'KIS ', + '(1) ', '(2) ', '(3) ', '(4) ', '(5) ', '(6) ', '(7) ', '(8) ', '(9) ', '(10) ', '(Yue) ', '(Huo) ', '(Shui) ', '(Mu) ', '(Jin) ', '(Tu) ', + '(Ri) ', '(Zhu) ', '(You) ', '(She) ', '(Ming) ', '(Te) ', '(Cai) ', '(Zhu) ', '(Lao) ', '(Mi) ', '(Nan) ', '(Nu) ', '(Shi) ', '(You) ', '(Yin) ', '(Zhu) ', + '(Xiang) ', '(Xiu) ', '(Xie) ', '(Zheng) ', '(Shang) ', '(Zhong) ', '(Xia) ', '(Zuo) ', '(You) ', '(Yi) ', '(Zong) ', '(Xue) ', '(Jian) ', '(Qi) ', '(Zi) ', '(Xie) ', + '(Ye) ', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '1M', '2M', '3M', '4M', '5M', '6M', '7M', '8M', '9M', '10M', '11M', '12M', '[?]', '[?]', '[?]', '[?]', + 'a', 'i', 'u', 'u', 'o', 'ka', 'ki', 'ku', 'ke', 'ko', 'sa', 'si', 'su', 'se', 'so', 'ta', + 'ti', 'tu', 'te', 'to', 'na', 'ni', 'nu', 'ne', 'no', 'ha', 'hi', 'hu', 'he', 'ho', 'ma', 'mi', + 'mu', 'me', 'mo', 'ya', 'yu', 'yo', 'ra', 'ri', 'ru', 're', 'ro', 'wa', 'wi', 'we', 'wo', + ], + 'x04': [ + 'Ie', 'Io', 'Dj', 'Gj', 'Ie', 'Dz', 'I', 'Yi', 'J', 'Lj', 'Nj', 'Tsh', 'Kj', 'I', 'U', 'Dzh', + 'A', 'B', 'V', 'G', 'D', 'Ie', 'Zh', 'Z', 'I', 'I', 'K', 'L', 'M', 'N', 'O', 'P', + 'R', 'S', 'T', 'U', 'F', 'Kh', 'Ts', 'Ch', 'Sh', 'Shch', '', 'Y', '\'', 'E', 'Iu', 'Ia', + 'a', 'b', 'v', 'gh', 'd', 'ie', 'zh', 'z', 'i', 'i', 'k', 'l', 'm', 'n', 'o', 'p', + 'r', 's', 't', 'u', 'f', 'kh', 'ts', 'ch', 'sh', 'shch', '', 'y', '\'', 'e', 'iu', 'ia', + 'ie', 'io', 'dj', 'gj', 'ie', 'dz', 'i', 'yi', 'j', 'lj', 'nj', 'tsh', 'kj', 'i', 'u', 'dzh', + 'O', 'o', 'E', 'e', 'Ie', 'ie', 'E', 'e', 'Ie', 'ie', 'O', 'o', 'Io', 'io', 'Ks', 'ks', + 'Ps', 'ps', 'F', 'f', 'Y', 'y', 'Y', 'y', 'u', 'u', 'O', 'o', 'O', 'o', 'Ot', 'ot', + 'Q', 'q', '*1000*', '', '', '', '', '[?]', '*100.000*', '*1.000.000*', '[?]', '[?]', '"', '"', 'R\'', 'r\'', + 'G\'', 'g\'', 'G\'', 'g\'', 'G\'', 'g\'', 'Zh\'', 'zh\'', 'Z\'', 'z\'', 'K\'', 'k\'', 'K\'', 'k\'', 'K\'', 'k\'', + 'K\'', 'k\'', 'N\'', 'n\'', 'Ng', 'ng', 'P\'', 'p\'', 'Kh', 'kh', 'S\'', 's\'', 'T\'', 't\'', 'U', 'u', + 'U\'', 'u\'', 'Kh\'', 'kh\'', 'Tts', 'tts', 'Ch\'', 'ch\'', 'Ch\'', 'ch\'', 'H', 'h', 'Ch', 'ch', 'Ch\'', 'ch\'', + '`', 'Zh', 'zh', 'K\'', 'k\'', '[?]', '[?]', 'N\'', 'n\'', '[?]', '[?]', 'Ch', 'ch', '[?]', '[?]', '[?]', + 'a', 'a', 'A', 'a', 'Ae', 'ae', 'Ie', 'ie', '@', '@', '@', '@', 'Zh', 'zh', 'Z', 'z', + 'Dz', 'dz', 'I', 'i', 'I', 'i', 'O', 'o', 'O', 'o', 'O', 'o', 'E', 'e', 'U', 'u', + 'U', 'u', 'U', 'u', 'Ch', 'ch', '[?]', '[?]', 'Y', 'y', '[?]', '[?]', '[?]', '[?]', '[?]', + ], + 'xb6': [ + 'ddyels', 'ddyelt', 'ddyelp', 'ddyelh', 'ddyem', 'ddyeb', 'ddyebs', 'ddyes', 'ddyess', 'ddyeng', 'ddyej', 'ddyec', 'ddyek', 'ddyet', 'ddyep', 'ddyeh', + 'ddo', 'ddog', 'ddogg', 'ddogs', 'ddon', 'ddonj', 'ddonh', 'ddod', 'ddol', 'ddolg', 'ddolm', 'ddolb', 'ddols', 'ddolt', 'ddolp', 'ddolh', + 'ddom', 'ddob', 'ddobs', 'ddos', 'ddoss', 'ddong', 'ddoj', 'ddoc', 'ddok', 'ddot', 'ddop', 'ddoh', 'ddwa', 'ddwag', 'ddwagg', 'ddwags', + 'ddwan', 'ddwanj', 'ddwanh', 'ddwad', 'ddwal', 'ddwalg', 'ddwalm', 'ddwalb', 'ddwals', 'ddwalt', 'ddwalp', 'ddwalh', 'ddwam', 'ddwab', 'ddwabs', 'ddwas', + 'ddwass', 'ddwang', 'ddwaj', 'ddwac', 'ddwak', 'ddwat', 'ddwap', 'ddwah', 'ddwae', 'ddwaeg', 'ddwaegg', 'ddwaegs', 'ddwaen', 'ddwaenj', 'ddwaenh', 'ddwaed', + 'ddwael', 'ddwaelg', 'ddwaelm', 'ddwaelb', 'ddwaels', 'ddwaelt', 'ddwaelp', 'ddwaelh', 'ddwaem', 'ddwaeb', 'ddwaebs', 'ddwaes', 'ddwaess', 'ddwaeng', 'ddwaej', 'ddwaec', + 'ddwaek', 'ddwaet', 'ddwaep', 'ddwaeh', 'ddoe', 'ddoeg', 'ddoegg', 'ddoegs', 'ddoen', 'ddoenj', 'ddoenh', 'ddoed', 'ddoel', 'ddoelg', 'ddoelm', 'ddoelb', + 'ddoels', 'ddoelt', 'ddoelp', 'ddoelh', 'ddoem', 'ddoeb', 'ddoebs', 'ddoes', 'ddoess', 'ddoeng', 'ddoej', 'ddoec', 'ddoek', 'ddoet', 'ddoep', 'ddoeh', + 'ddyo', 'ddyog', 'ddyogg', 'ddyogs', 'ddyon', 'ddyonj', 'ddyonh', 'ddyod', 'ddyol', 'ddyolg', 'ddyolm', 'ddyolb', 'ddyols', 'ddyolt', 'ddyolp', 'ddyolh', + 'ddyom', 'ddyob', 'ddyobs', 'ddyos', 'ddyoss', 'ddyong', 'ddyoj', 'ddyoc', 'ddyok', 'ddyot', 'ddyop', 'ddyoh', 'ddu', 'ddug', 'ddugg', 'ddugs', + 'ddun', 'ddunj', 'ddunh', 'ddud', 'ddul', 'ddulg', 'ddulm', 'ddulb', 'dduls', 'ddult', 'ddulp', 'ddulh', 'ddum', 'ddub', 'ddubs', 'ddus', + 'dduss', 'ddung', 'dduj', 'dduc', 'dduk', 'ddut', 'ddup', 'dduh', 'ddweo', 'ddweog', 'ddweogg', 'ddweogs', 'ddweon', 'ddweonj', 'ddweonh', 'ddweod', + 'ddweol', 'ddweolg', 'ddweolm', 'ddweolb', 'ddweols', 'ddweolt', 'ddweolp', 'ddweolh', 'ddweom', 'ddweob', 'ddweobs', 'ddweos', 'ddweoss', 'ddweong', 'ddweoj', 'ddweoc', + 'ddweok', 'ddweot', 'ddweop', 'ddweoh', 'ddwe', 'ddweg', 'ddwegg', 'ddwegs', 'ddwen', 'ddwenj', 'ddwenh', 'ddwed', 'ddwel', 'ddwelg', 'ddwelm', 'ddwelb', + 'ddwels', 'ddwelt', 'ddwelp', 'ddwelh', 'ddwem', 'ddweb', 'ddwebs', 'ddwes', 'ddwess', 'ddweng', 'ddwej', 'ddwec', 'ddwek', 'ddwet', 'ddwep', 'ddweh', + 'ddwi', 'ddwig', 'ddwigg', 'ddwigs', 'ddwin', 'ddwinj', 'ddwinh', 'ddwid', 'ddwil', 'ddwilg', 'ddwilm', 'ddwilb', 'ddwils', 'ddwilt', 'ddwilp', 'ddwilh', + ], + 'x23': [ + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + ], + 'xbc': [ + 'mil', 'milg', 'milm', 'milb', 'mils', 'milt', 'milp', 'milh', 'mim', 'mib', 'mibs', 'mis', 'miss', 'ming', 'mij', 'mic', + 'mik', 'mit', 'mip', 'mih', 'ba', 'bag', 'bagg', 'bags', 'ban', 'banj', 'banh', 'bad', 'bal', 'balg', 'balm', 'balb', + 'bals', 'balt', 'balp', 'balh', 'bam', 'bab', 'babs', 'bas', 'bass', 'bang', 'baj', 'bac', 'bak', 'bat', 'bap', 'bah', + 'bae', 'baeg', 'baegg', 'baegs', 'baen', 'baenj', 'baenh', 'baed', 'bael', 'baelg', 'baelm', 'baelb', 'baels', 'baelt', 'baelp', 'baelh', + 'baem', 'baeb', 'baebs', 'baes', 'baess', 'baeng', 'baej', 'baec', 'baek', 'baet', 'baep', 'baeh', 'bya', 'byag', 'byagg', 'byags', + 'byan', 'byanj', 'byanh', 'byad', 'byal', 'byalg', 'byalm', 'byalb', 'byals', 'byalt', 'byalp', 'byalh', 'byam', 'byab', 'byabs', 'byas', + 'byass', 'byang', 'byaj', 'byac', 'byak', 'byat', 'byap', 'byah', 'byae', 'byaeg', 'byaegg', 'byaegs', 'byaen', 'byaenj', 'byaenh', 'byaed', + 'byael', 'byaelg', 'byaelm', 'byaelb', 'byaels', 'byaelt', 'byaelp', 'byaelh', 'byaem', 'byaeb', 'byaebs', 'byaes', 'byaess', 'byaeng', 'byaej', 'byaec', + 'byaek', 'byaet', 'byaep', 'byaeh', 'beo', 'beog', 'beogg', 'beogs', 'beon', 'beonj', 'beonh', 'beod', 'beol', 'beolg', 'beolm', 'beolb', + 'beols', 'beolt', 'beolp', 'beolh', 'beom', 'beob', 'beobs', 'beos', 'beoss', 'beong', 'beoj', 'beoc', 'beok', 'beot', 'beop', 'beoh', + 'be', 'beg', 'begg', 'begs', 'ben', 'benj', 'benh', 'bed', 'bel', 'belg', 'belm', 'belb', 'bels', 'belt', 'belp', 'belh', + 'bem', 'beb', 'bebs', 'bes', 'bess', 'beng', 'bej', 'bec', 'bek', 'bet', 'bep', 'beh', 'byeo', 'byeog', 'byeogg', 'byeogs', + 'byeon', 'byeonj', 'byeonh', 'byeod', 'byeol', 'byeolg', 'byeolm', 'byeolb', 'byeols', 'byeolt', 'byeolp', 'byeolh', 'byeom', 'byeob', 'byeobs', 'byeos', + 'byeoss', 'byeong', 'byeoj', 'byeoc', 'byeok', 'byeot', 'byeop', 'byeoh', 'bye', 'byeg', 'byegg', 'byegs', 'byen', 'byenj', 'byenh', 'byed', + 'byel', 'byelg', 'byelm', 'byelb', 'byels', 'byelt', 'byelp', 'byelh', 'byem', 'byeb', 'byebs', 'byes', 'byess', 'byeng', 'byej', 'byec', + 'byek', 'byet', 'byep', 'byeh', 'bo', 'bog', 'bogg', 'bogs', 'bon', 'bonj', 'bonh', 'bod', 'bol', 'bolg', 'bolm', 'bolb', + ], + 'x2f': [ + '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', + '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', + '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', + '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', + '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', + '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', + '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', + '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', + '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', + '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', + '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', + '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', + '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', + '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?]', '[?]', '[?]', + ], + 'xb4': [ + 'dwaen', 'dwaenj', 'dwaenh', 'dwaed', 'dwael', 'dwaelg', 'dwaelm', 'dwaelb', 'dwaels', 'dwaelt', 'dwaelp', 'dwaelh', 'dwaem', 'dwaeb', 'dwaebs', 'dwaes', + 'dwaess', 'dwaeng', 'dwaej', 'dwaec', 'dwaek', 'dwaet', 'dwaep', 'dwaeh', 'doe', 'doeg', 'doegg', 'doegs', 'doen', 'doenj', 'doenh', 'doed', + 'doel', 'doelg', 'doelm', 'doelb', 'doels', 'doelt', 'doelp', 'doelh', 'doem', 'doeb', 'doebs', 'does', 'doess', 'doeng', 'doej', 'doec', + 'doek', 'doet', 'doep', 'doeh', 'dyo', 'dyog', 'dyogg', 'dyogs', 'dyon', 'dyonj', 'dyonh', 'dyod', 'dyol', 'dyolg', 'dyolm', 'dyolb', + 'dyols', 'dyolt', 'dyolp', 'dyolh', 'dyom', 'dyob', 'dyobs', 'dyos', 'dyoss', 'dyong', 'dyoj', 'dyoc', 'dyok', 'dyot', 'dyop', 'dyoh', + 'du', 'dug', 'dugg', 'dugs', 'dun', 'dunj', 'dunh', 'dud', 'dul', 'dulg', 'dulm', 'dulb', 'duls', 'dult', 'dulp', 'dulh', + 'dum', 'dub', 'dubs', 'dus', 'duss', 'dung', 'duj', 'duc', 'duk', 'dut', 'dup', 'duh', 'dweo', 'dweog', 'dweogg', 'dweogs', + 'dweon', 'dweonj', 'dweonh', 'dweod', 'dweol', 'dweolg', 'dweolm', 'dweolb', 'dweols', 'dweolt', 'dweolp', 'dweolh', 'dweom', 'dweob', 'dweobs', 'dweos', + 'dweoss', 'dweong', 'dweoj', 'dweoc', 'dweok', 'dweot', 'dweop', 'dweoh', 'dwe', 'dweg', 'dwegg', 'dwegs', 'dwen', 'dwenj', 'dwenh', 'dwed', + 'dwel', 'dwelg', 'dwelm', 'dwelb', 'dwels', 'dwelt', 'dwelp', 'dwelh', 'dwem', 'dweb', 'dwebs', 'dwes', 'dwess', 'dweng', 'dwej', 'dwec', + 'dwek', 'dwet', 'dwep', 'dweh', 'dwi', 'dwig', 'dwigg', 'dwigs', 'dwin', 'dwinj', 'dwinh', 'dwid', 'dwil', 'dwilg', 'dwilm', 'dwilb', + 'dwils', 'dwilt', 'dwilp', 'dwilh', 'dwim', 'dwib', 'dwibs', 'dwis', 'dwiss', 'dwing', 'dwij', 'dwic', 'dwik', 'dwit', 'dwip', 'dwih', + 'dyu', 'dyug', 'dyugg', 'dyugs', 'dyun', 'dyunj', 'dyunh', 'dyud', 'dyul', 'dyulg', 'dyulm', 'dyulb', 'dyuls', 'dyult', 'dyulp', 'dyulh', + 'dyum', 'dyub', 'dyubs', 'dyus', 'dyuss', 'dyung', 'dyuj', 'dyuc', 'dyuk', 'dyut', 'dyup', 'dyuh', 'deu', 'deug', 'deugg', 'deugs', + 'deun', 'deunj', 'deunh', 'deud', 'deul', 'deulg', 'deulm', 'deulb', 'deuls', 'deult', 'deulp', 'deulh', 'deum', 'deub', 'deubs', 'deus', + 'deuss', 'deung', 'deuj', 'deuc', 'deuk', 'deut', 'deup', 'deuh', 'dyi', 'dyig', 'dyigg', 'dyigs', 'dyin', 'dyinj', 'dyinh', 'dyid', + ], + 'xc9': [ + 'jun', 'junj', 'junh', 'jud', 'jul', 'julg', 'julm', 'julb', 'juls', 'jult', 'julp', 'julh', 'jum', 'jub', 'jubs', 'jus', + 'juss', 'jung', 'juj', 'juc', 'juk', 'jut', 'jup', 'juh', 'jweo', 'jweog', 'jweogg', 'jweogs', 'jweon', 'jweonj', 'jweonh', 'jweod', + 'jweol', 'jweolg', 'jweolm', 'jweolb', 'jweols', 'jweolt', 'jweolp', 'jweolh', 'jweom', 'jweob', 'jweobs', 'jweos', 'jweoss', 'jweong', 'jweoj', 'jweoc', + 'jweok', 'jweot', 'jweop', 'jweoh', 'jwe', 'jweg', 'jwegg', 'jwegs', 'jwen', 'jwenj', 'jwenh', 'jwed', 'jwel', 'jwelg', 'jwelm', 'jwelb', + 'jwels', 'jwelt', 'jwelp', 'jwelh', 'jwem', 'jweb', 'jwebs', 'jwes', 'jwess', 'jweng', 'jwej', 'jwec', 'jwek', 'jwet', 'jwep', 'jweh', + 'jwi', 'jwig', 'jwigg', 'jwigs', 'jwin', 'jwinj', 'jwinh', 'jwid', 'jwil', 'jwilg', 'jwilm', 'jwilb', 'jwils', 'jwilt', 'jwilp', 'jwilh', + 'jwim', 'jwib', 'jwibs', 'jwis', 'jwiss', 'jwing', 'jwij', 'jwic', 'jwik', 'jwit', 'jwip', 'jwih', 'jyu', 'jyug', 'jyugg', 'jyugs', + 'jyun', 'jyunj', 'jyunh', 'jyud', 'jyul', 'jyulg', 'jyulm', 'jyulb', 'jyuls', 'jyult', 'jyulp', 'jyulh', 'jyum', 'jyub', 'jyubs', 'jyus', + 'jyuss', 'jyung', 'jyuj', 'jyuc', 'jyuk', 'jyut', 'jyup', 'jyuh', 'jeu', 'jeug', 'jeugg', 'jeugs', 'jeun', 'jeunj', 'jeunh', 'jeud', + 'jeul', 'jeulg', 'jeulm', 'jeulb', 'jeuls', 'jeult', 'jeulp', 'jeulh', 'jeum', 'jeub', 'jeubs', 'jeus', 'jeuss', 'jeung', 'jeuj', 'jeuc', + 'jeuk', 'jeut', 'jeup', 'jeuh', 'jyi', 'jyig', 'jyigg', 'jyigs', 'jyin', 'jyinj', 'jyinh', 'jyid', 'jyil', 'jyilg', 'jyilm', 'jyilb', + 'jyils', 'jyilt', 'jyilp', 'jyilh', 'jyim', 'jyib', 'jyibs', 'jyis', 'jyiss', 'jying', 'jyij', 'jyic', 'jyik', 'jyit', 'jyip', 'jyih', + 'ji', 'jig', 'jigg', 'jigs', 'jin', 'jinj', 'jinh', 'jid', 'jil', 'jilg', 'jilm', 'jilb', 'jils', 'jilt', 'jilp', 'jilh', + 'jim', 'jib', 'jibs', 'jis', 'jiss', 'jing', 'jij', 'jic', 'jik', 'jit', 'jip', 'jih', 'jja', 'jjag', 'jjagg', 'jjags', + 'jjan', 'jjanj', 'jjanh', 'jjad', 'jjal', 'jjalg', 'jjalm', 'jjalb', 'jjals', 'jjalt', 'jjalp', 'jjalh', 'jjam', 'jjab', 'jjabs', 'jjas', + 'jjass', 'jjang', 'jjaj', 'jjac', 'jjak', 'jjat', 'jjap', 'jjah', 'jjae', 'jjaeg', 'jjaegg', 'jjaegs', 'jjaen', 'jjaenj', 'jjaenh', 'jjaed', + ], + 'xb7': [ + 'ddwim', 'ddwib', 'ddwibs', 'ddwis', 'ddwiss', 'ddwing', 'ddwij', 'ddwic', 'ddwik', 'ddwit', 'ddwip', 'ddwih', 'ddyu', 'ddyug', 'ddyugg', 'ddyugs', + 'ddyun', 'ddyunj', 'ddyunh', 'ddyud', 'ddyul', 'ddyulg', 'ddyulm', 'ddyulb', 'ddyuls', 'ddyult', 'ddyulp', 'ddyulh', 'ddyum', 'ddyub', 'ddyubs', 'ddyus', + 'ddyuss', 'ddyung', 'ddyuj', 'ddyuc', 'ddyuk', 'ddyut', 'ddyup', 'ddyuh', 'ddeu', 'ddeug', 'ddeugg', 'ddeugs', 'ddeun', 'ddeunj', 'ddeunh', 'ddeud', + 'ddeul', 'ddeulg', 'ddeulm', 'ddeulb', 'ddeuls', 'ddeult', 'ddeulp', 'ddeulh', 'ddeum', 'ddeub', 'ddeubs', 'ddeus', 'ddeuss', 'ddeung', 'ddeuj', 'ddeuc', + 'ddeuk', 'ddeut', 'ddeup', 'ddeuh', 'ddyi', 'ddyig', 'ddyigg', 'ddyigs', 'ddyin', 'ddyinj', 'ddyinh', 'ddyid', 'ddyil', 'ddyilg', 'ddyilm', 'ddyilb', + 'ddyils', 'ddyilt', 'ddyilp', 'ddyilh', 'ddyim', 'ddyib', 'ddyibs', 'ddyis', 'ddyiss', 'ddying', 'ddyij', 'ddyic', 'ddyik', 'ddyit', 'ddyip', 'ddyih', + 'ddi', 'ddig', 'ddigg', 'ddigs', 'ddin', 'ddinj', 'ddinh', 'ddid', 'ddil', 'ddilg', 'ddilm', 'ddilb', 'ddils', 'ddilt', 'ddilp', 'ddilh', + 'ddim', 'ddib', 'ddibs', 'ddis', 'ddiss', 'dding', 'ddij', 'ddic', 'ddik', 'ddit', 'ddip', 'ddih', 'ra', 'rag', 'ragg', 'rags', + 'ran', 'ranj', 'ranh', 'rad', 'ral', 'ralg', 'ralm', 'ralb', 'rals', 'ralt', 'ralp', 'ralh', 'ram', 'rab', 'rabs', 'ras', + 'rass', 'rang', 'raj', 'rac', 'rak', 'rat', 'rap', 'rah', 'rae', 'raeg', 'raegg', 'raegs', 'raen', 'raenj', 'raenh', 'raed', + 'rael', 'raelg', 'raelm', 'raelb', 'raels', 'raelt', 'raelp', 'raelh', 'raem', 'raeb', 'raebs', 'raes', 'raess', 'raeng', 'raej', 'raec', + 'raek', 'raet', 'raep', 'raeh', 'rya', 'ryag', 'ryagg', 'ryags', 'ryan', 'ryanj', 'ryanh', 'ryad', 'ryal', 'ryalg', 'ryalm', 'ryalb', + 'ryals', 'ryalt', 'ryalp', 'ryalh', 'ryam', 'ryab', 'ryabs', 'ryas', 'ryass', 'ryang', 'ryaj', 'ryac', 'ryak', 'ryat', 'ryap', 'ryah', + 'ryae', 'ryaeg', 'ryaegg', 'ryaegs', 'ryaen', 'ryaenj', 'ryaenh', 'ryaed', 'ryael', 'ryaelg', 'ryaelm', 'ryaelb', 'ryaels', 'ryaelt', 'ryaelp', 'ryaelh', + 'ryaem', 'ryaeb', 'ryaebs', 'ryaes', 'ryaess', 'ryaeng', 'ryaej', 'ryaec', 'ryaek', 'ryaet', 'ryaep', 'ryaeh', 'reo', 'reog', 'reogg', 'reogs', + 'reon', 'reonj', 'reonh', 'reod', 'reol', 'reolg', 'reolm', 'reolb', 'reols', 'reolt', 'reolp', 'reolh', 'reom', 'reob', 'reobs', 'reos', + ], + 'xbe': [ + 'byum', 'byub', 'byubs', 'byus', 'byuss', 'byung', 'byuj', 'byuc', 'byuk', 'byut', 'byup', 'byuh', 'beu', 'beug', 'beugg', 'beugs', + 'beun', 'beunj', 'beunh', 'beud', 'beul', 'beulg', 'beulm', 'beulb', 'beuls', 'beult', 'beulp', 'beulh', 'beum', 'beub', 'beubs', 'beus', + 'beuss', 'beung', 'beuj', 'beuc', 'beuk', 'beut', 'beup', 'beuh', 'byi', 'byig', 'byigg', 'byigs', 'byin', 'byinj', 'byinh', 'byid', + 'byil', 'byilg', 'byilm', 'byilb', 'byils', 'byilt', 'byilp', 'byilh', 'byim', 'byib', 'byibs', 'byis', 'byiss', 'bying', 'byij', 'byic', + 'byik', 'byit', 'byip', 'byih', 'bi', 'big', 'bigg', 'bigs', 'bin', 'binj', 'binh', 'bid', 'bil', 'bilg', 'bilm', 'bilb', + 'bils', 'bilt', 'bilp', 'bilh', 'bim', 'bib', 'bibs', 'bis', 'biss', 'bing', 'bij', 'bic', 'bik', 'bit', 'bip', 'bih', + 'bba', 'bbag', 'bbagg', 'bbags', 'bban', 'bbanj', 'bbanh', 'bbad', 'bbal', 'bbalg', 'bbalm', 'bbalb', 'bbals', 'bbalt', 'bbalp', 'bbalh', + 'bbam', 'bbab', 'bbabs', 'bbas', 'bbass', 'bbang', 'bbaj', 'bbac', 'bbak', 'bbat', 'bbap', 'bbah', 'bbae', 'bbaeg', 'bbaegg', 'bbaegs', + 'bbaen', 'bbaenj', 'bbaenh', 'bbaed', 'bbael', 'bbaelg', 'bbaelm', 'bbaelb', 'bbaels', 'bbaelt', 'bbaelp', 'bbaelh', 'bbaem', 'bbaeb', 'bbaebs', 'bbaes', + 'bbaess', 'bbaeng', 'bbaej', 'bbaec', 'bbaek', 'bbaet', 'bbaep', 'bbaeh', 'bbya', 'bbyag', 'bbyagg', 'bbyags', 'bbyan', 'bbyanj', 'bbyanh', 'bbyad', + 'bbyal', 'bbyalg', 'bbyalm', 'bbyalb', 'bbyals', 'bbyalt', 'bbyalp', 'bbyalh', 'bbyam', 'bbyab', 'bbyabs', 'bbyas', 'bbyass', 'bbyang', 'bbyaj', 'bbyac', + 'bbyak', 'bbyat', 'bbyap', 'bbyah', 'bbyae', 'bbyaeg', 'bbyaegg', 'bbyaegs', 'bbyaen', 'bbyaenj', 'bbyaenh', 'bbyaed', 'bbyael', 'bbyaelg', 'bbyaelm', 'bbyaelb', + 'bbyaels', 'bbyaelt', 'bbyaelp', 'bbyaelh', 'bbyaem', 'bbyaeb', 'bbyaebs', 'bbyaes', 'bbyaess', 'bbyaeng', 'bbyaej', 'bbyaec', 'bbyaek', 'bbyaet', 'bbyaep', 'bbyaeh', + 'bbeo', 'bbeog', 'bbeogg', 'bbeogs', 'bbeon', 'bbeonj', 'bbeonh', 'bbeod', 'bbeol', 'bbeolg', 'bbeolm', 'bbeolb', 'bbeols', 'bbeolt', 'bbeolp', 'bbeolh', + 'bbeom', 'bbeob', 'bbeobs', 'bbeos', 'bbeoss', 'bbeong', 'bbeoj', 'bbeoc', 'bbeok', 'bbeot', 'bbeop', 'bbeoh', 'bbe', 'bbeg', 'bbegg', 'bbegs', + 'bben', 'bbenj', 'bbenh', 'bbed', 'bbel', 'bbelg', 'bbelm', 'bbelb', 'bbels', 'bbelt', 'bbelp', 'bbelh', 'bbem', 'bbeb', 'bbebs', 'bbes', + ], + 'x10': [ + 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', 'jh', 'ny', 'nny', 'tt', 'tth', 'dd', 'ddh', 'nn', + 'tt', 'th', 'd', 'dh', 'n', 'p', 'ph', 'b', 'bh', 'm', 'y', 'r', 'l', 'w', 's', 'h', + 'll', 'a', '[?]', 'i', 'ii', 'u', 'uu', 'e', '[?]', 'o', 'au', '[?]', 'aa', 'i', 'ii', 'u', + 'uu', 'e', 'ai', '[?]', '[?]', '[?]', 'N', '\'', ':', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ' / ', ' // ', 'n*', 'r*', 'l*', 'e*', + 'sh', 'ss', 'R', 'RR', 'L', 'LL', 'R', 'RR', 'L', 'LL', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + 'A', 'B', 'G', 'D', 'E', 'V', 'Z', 'T`', 'I', 'K', 'L', 'M', 'N', 'O', 'P', 'Zh', + 'R', 'S', 'T', 'U', 'P`', 'K`', 'G\'', 'Q', 'Sh', 'Ch`', 'C`', 'Z\'', 'C', 'Ch', 'X', 'J', + 'H', 'E', 'Y', 'W', 'Xh', 'OE', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + 'a', 'b', 'g', 'd', 'e', 'v', 'z', 't`', 'i', 'k', 'l', 'm', 'n', 'o', 'p', 'zh', + 'r', 's', 't', 'u', 'p`', 'k`', 'g\'', 'q', 'sh', 'ch`', 'c`', 'z\'', 'c', 'ch', 'x', 'j', + 'h', 'e', 'y', 'w', 'xh', 'oe', 'f', '[?]', '[?]', '[?]', '[?]', ' // ', '[?]', '[?]', '[?]', + ], + 'x1f': [ + 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'e', 'e', 'e', 'e', 'e', 'e', '[?]', '[?]', 'E', 'E', 'E', 'E', 'E', 'E', '[?]', '[?]', + 'e', 'e', 'e', 'e', 'e', 'e', 'e', 'e', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', + 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'I', 'I', 'I', 'I', 'I', 'I', 'I', 'I', + 'o', 'o', 'o', 'o', 'o', 'o', '[?]', '[?]', 'O', 'O', 'O', 'O', 'O', 'O', '[?]', '[?]', + 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', '[?]', 'U', '[?]', 'U', '[?]', 'U', '[?]', 'U', + 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', + 'a', 'a', 'e', 'e', 'e', 'e', 'i', 'i', 'o', 'o', 'u', 'u', 'o', 'o', '[?]', '[?]', + 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'e', 'e', 'e', 'e', 'e', 'e', 'e', 'e', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', + 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', + 'a', 'a', 'a', 'a', 'a', '[?]', 'a', 'a', 'A', 'A', 'A', 'A', 'A', '\'', 'i', '\'', + '~', '"~', 'e', 'e', 'e', '[?]', 'e', 'e', 'E', 'E', 'E', 'E', 'E', '\'`', '\'\'', '\'~', + 'i', 'i', 'i', 'i', '[?]', '[?]', 'i', 'i', 'I', 'I', 'I', 'I', '[?]', '`\'', '`\'', '`~', + 'u', 'u', 'u', 'u', 'R', 'R', 'u', 'u', 'U', 'U', 'U', 'U', 'R', '"`', '"\'', '`', + '[?]', '[?]', 'o', 'o', 'o', '[?]', 'o', 'o', 'O', 'O', 'O', 'O', 'O', '\'', '`', + ], + 'x31': [ + '[?]', '[?]', '[?]', '[?]', '[?]', 'B', 'P', 'M', 'F', 'D', 'T', 'N', 'L', 'G', 'K', 'H', + 'J', 'Q', 'X', 'ZH', 'CH', 'SH', 'R', 'Z', 'C', 'S', 'A', 'O', 'E', 'EH', 'AI', 'EI', + 'AU', 'OU', 'AN', 'EN', 'ANG', 'ENG', 'ER', 'I', 'U', 'IU', 'V', 'NG', 'GN', '[?]', '[?]', '[?]', + '[?]', 'g', 'gg', 'gs', 'n', 'nj', 'nh', 'd', 'dd', 'r', 'lg', 'lm', 'lb', 'ls', 'lt', 'lp', + 'rh', 'm', 'b', 'bb', 'bs', 's', 'ss', '', 'j', 'jj', 'c', 'k', 't', 'p', 'h', 'a', + 'ae', 'ya', 'yae', 'eo', 'e', 'yeo', 'ye', 'o', 'wa', 'wae', 'oe', 'yo', 'u', 'weo', 'we', 'wi', + 'yu', 'eu', 'yi', 'i', '', 'nn', 'nd', 'ns', 'nZ', 'lgs', 'ld', 'lbs', 'lZ', 'lQ', 'mb', 'ms', + 'mZ', 'mN', 'bg', '', 'bsg', 'bst', 'bj', 'bt', 'bN', 'bbN', 'sg', 'sn', 'sd', 'sb', 'sj', 'Z', + '', 'N', 'Ns', 'NZ', 'pN', 'hh', 'Q', 'yo-ya', 'yo-yae', 'yo-i', 'yu-yeo', 'yu-ye', 'yu-i', 'U', 'U-i', '[?]', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 'BU', 'ZI', 'JI', 'GU', 'EE', 'ENN', 'OO', 'ONN', 'IR', 'ANN', 'INN', 'UNN', 'IM', 'NGG', 'AINN', 'AUNN', + 'AM', 'OM', 'ONG', 'INNN', 'P', 'T', 'K', 'H', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + ], + 'x18': [ + ' @ ', ' ... ', ', ', '. ', ': ', ' // ', '', '-', ', ', '. ', '', '', '', '', '', '[?]', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + 'a', 'e', 'i', 'o', 'u', 'O', 'U', 'ee', 'n', 'ng', 'b', 'p', 'q', 'g', 'm', 'l', + 's', 'sh', 't', 'd', 'ch', 'j', 'y', 'r', 'w', 'f', 'k', 'kha', 'ts', 'z', 'h', 'zr', + 'lh', 'zh', 'ch', '-', 'e', 'i', 'o', 'u', 'O', 'U', 'ng', 'b', 'p', 'q', 'g', 'm', + 't', 'd', 'ch', 'j', 'ts', 'y', 'w', 'k', 'g', 'h', 'jy', 'ny', 'dz', 'e', 'i', 'iy', + 'U', 'u', 'ng', 'k', 'g', 'h', 'p', 'sh', 't', 'd', 'j', 'f', 'g', 'h', 'ts', 'z', + 'r', 'ch', 'zh', 'i', 'k', 'r', 'f', 'zh', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', 'H', 'X', 'W', 'M', ' 3 ', ' 333 ', 'a', 'i', 'k', 'ng', 'c', 'tt', 'tth', 'dd', 'nn', + 't', 'd', 'p', 'ph', 'ss', 'zh', 'z', 'a', 't', 'zh', 'gh', 'ng', 'c', 'jh', 'tta', 'ddh', + 't', 'dh', 'ss', 'cy', 'zh', 'z', 'u', 'y', 'bh', '\'', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + ], + 'x11': [ + 'g', 'gg', 'n', 'd', 'dd', 'r', 'm', 'b', 'bb', 's', 'ss', '', 'j', 'jj', 'c', 'k', + 't', 'p', 'h', 'ng', 'nn', 'nd', 'nb', 'dg', 'rn', 'rr', 'rh', 'rN', 'mb', 'mN', 'bg', 'bn', + '', 'bs', 'bsg', 'bst', 'bsb', 'bss', 'bsj', 'bj', 'bc', 'bt', 'bp', 'bN', 'bbN', 'sg', 'sn', 'sd', + 'sr', 'sm', 'sb', 'sbg', 'sss', 's', 'sj', 'sc', 'sk', 'st', 'sp', 'sh', '', '', '', '', + 'Z', 'g', 'd', 'm', 'b', 's', 'Z', '', 'j', 'c', 't', 'p', 'N', 'j', '', '', + '', '', 'ck', 'ch', '', '', 'pb', 'pN', 'hh', 'Q', '[?]', '[?]', '[?]', '[?]', '[?]', '', + '', 'a', 'ae', 'ya', 'yae', 'eo', 'e', 'yeo', 'ye', 'o', 'wa', 'wae', 'oe', 'yo', 'u', 'weo', + 'we', 'wi', 'yu', 'eu', 'yi', 'i', 'a-o', 'a-u', 'ya-o', 'ya-yo', 'eo-o', 'eo-u', 'eo-eu', 'yeo-o', 'yeo-u', 'o-eo', + 'o-e', 'o-ye', 'o-o', 'o-u', 'yo-ya', 'yo-yae', 'yo-yeo', 'yo-o', 'yo-i', 'u-a', 'u-ae', 'u-eo-eu', 'u-ye', 'u-u', 'yu-a', 'yu-eo', + 'yu-e', 'yu-yeo', 'yu-ye', 'yu-u', 'yu-i', 'eu-u', 'eu-eu', 'yi-u', 'i-a', 'i-ya', 'i-o', 'i-u', 'i-eu', 'i-U', 'U', 'U-eo', + 'U-u', 'U-i', 'UU', '[?]', '[?]', '[?]', '[?]', '[?]', 'g', 'gg', 'gs', 'n', 'nj', 'nh', 'd', 'l', + 'lg', 'lm', 'lb', 'ls', 'lt', 'lp', 'lh', 'm', 'b', 'bs', 's', 'ss', 'ng', 'j', 'c', 'k', + 't', 'p', 'h', 'gl', 'gsg', 'ng', 'nd', 'ns', 'nZ', 'nt', 'dg', 'tl', 'lgs', 'ln', 'ld', 'lth', + 'll', 'lmg', 'lms', 'lbs', 'lbh', 'rNp', 'lss', 'lZ', 'lk', 'lQ', 'mg', 'ml', 'mb', 'ms', 'mss', 'mZ', + 'mc', 'mh', 'mN', 'bl', 'bp', 'ph', 'pN', 'sg', 'sd', 'sl', 'sb', 'Z', 'g', 'ss', '', 'kh', + 'N', 'Ns', 'NZ', 'pb', 'pN', 'hn', 'hl', 'hm', 'hb', 'Q', '[?]', '[?]', '[?]', '[?]', '[?]', + ], + 'xcf': [ + 'ke', 'keg', 'kegg', 'kegs', 'ken', 'kenj', 'kenh', 'ked', 'kel', 'kelg', 'kelm', 'kelb', 'kels', 'kelt', 'kelp', 'kelh', + 'kem', 'keb', 'kebs', 'kes', 'kess', 'keng', 'kej', 'kec', 'kek', 'ket', 'kep', 'keh', 'kyeo', 'kyeog', 'kyeogg', 'kyeogs', + 'kyeon', 'kyeonj', 'kyeonh', 'kyeod', 'kyeol', 'kyeolg', 'kyeolm', 'kyeolb', 'kyeols', 'kyeolt', 'kyeolp', 'kyeolh', 'kyeom', 'kyeob', 'kyeobs', 'kyeos', + 'kyeoss', 'kyeong', 'kyeoj', 'kyeoc', 'kyeok', 'kyeot', 'kyeop', 'kyeoh', 'kye', 'kyeg', 'kyegg', 'kyegs', 'kyen', 'kyenj', 'kyenh', 'kyed', + 'kyel', 'kyelg', 'kyelm', 'kyelb', 'kyels', 'kyelt', 'kyelp', 'kyelh', 'kyem', 'kyeb', 'kyebs', 'kyes', 'kyess', 'kyeng', 'kyej', 'kyec', + 'kyek', 'kyet', 'kyep', 'kyeh', 'ko', 'kog', 'kogg', 'kogs', 'kon', 'konj', 'konh', 'kod', 'kol', 'kolg', 'kolm', 'kolb', + 'kols', 'kolt', 'kolp', 'kolh', 'kom', 'kob', 'kobs', 'kos', 'koss', 'kong', 'koj', 'koc', 'kok', 'kot', 'kop', 'koh', + 'kwa', 'kwag', 'kwagg', 'kwags', 'kwan', 'kwanj', 'kwanh', 'kwad', 'kwal', 'kwalg', 'kwalm', 'kwalb', 'kwals', 'kwalt', 'kwalp', 'kwalh', + 'kwam', 'kwab', 'kwabs', 'kwas', 'kwass', 'kwang', 'kwaj', 'kwac', 'kwak', 'kwat', 'kwap', 'kwah', 'kwae', 'kwaeg', 'kwaegg', 'kwaegs', + 'kwaen', 'kwaenj', 'kwaenh', 'kwaed', 'kwael', 'kwaelg', 'kwaelm', 'kwaelb', 'kwaels', 'kwaelt', 'kwaelp', 'kwaelh', 'kwaem', 'kwaeb', 'kwaebs', 'kwaes', + 'kwaess', 'kwaeng', 'kwaej', 'kwaec', 'kwaek', 'kwaet', 'kwaep', 'kwaeh', 'koe', 'koeg', 'koegg', 'koegs', 'koen', 'koenj', 'koenh', 'koed', + 'koel', 'koelg', 'koelm', 'koelb', 'koels', 'koelt', 'koelp', 'koelh', 'koem', 'koeb', 'koebs', 'koes', 'koess', 'koeng', 'koej', 'koec', + 'koek', 'koet', 'koep', 'koeh', 'kyo', 'kyog', 'kyogg', 'kyogs', 'kyon', 'kyonj', 'kyonh', 'kyod', 'kyol', 'kyolg', 'kyolm', 'kyolb', + 'kyols', 'kyolt', 'kyolp', 'kyolh', 'kyom', 'kyob', 'kyobs', 'kyos', 'kyoss', 'kyong', 'kyoj', 'kyoc', 'kyok', 'kyot', 'kyop', 'kyoh', + 'ku', 'kug', 'kugg', 'kugs', 'kun', 'kunj', 'kunh', 'kud', 'kul', 'kulg', 'kulm', 'kulb', 'kuls', 'kult', 'kulp', 'kulh', + 'kum', 'kub', 'kubs', 'kus', 'kuss', 'kung', 'kuj', 'kuc', 'kuk', 'kut', 'kup', 'kuh', 'kweo', 'kweog', 'kweogg', 'kweogs', + ], + 'x01': [ + 'A', 'a', 'A', 'a', 'A', 'a', 'C', 'c', 'C', 'c', 'C', 'c', 'C', 'c', 'D', 'd', + 'D', 'd', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'G', 'g', 'G', 'g', + 'G', 'g', 'G', 'g', 'H', 'h', 'H', 'h', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', + 'I', 'i', 'IJ', '', 'J', 'j', 'K', 'k', 'k', 'L', 'l', 'L', 'l', 'L', 'l', 'L', + 'l', 'L', 'l', 'N', 'n', 'N', 'n', 'N', 'n', '\'n', 'ng', 'NG', 'O', 'o', 'O', 'o', + 'O', 'o', 'OE', 'oe', 'R', 'r', 'R', 'r', 'R', 'r', 'S', 's', 'S', 's', 'S', 's', + 'S', 's', 'T', 't', 'T', 't', 'T', 't', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', + 'U', 'u', 'U', 'u', 'W', 'w', 'Y', 'y', 'Y', 'Z', 'z', 'Z', 'z', 'Z', 'z', 's', + 'b', 'B', 'B', 'b', '6', '6', 'O', 'C', 'c', 'D', 'D', 'D', 'd', 'd', '3', '@', + 'E', 'F', 'f', 'G', 'G', 'hv', 'I', 'I', 'K', 'k', 'l', 'l', 'W', 'N', 'n', 'O', + 'O', 'o', 'OI', 'oi', 'P', 'p', 'YR', '2', '2', 'SH', 'sh', 't', 'T', 't', 'T', 'U', + 'u', 'Y', 'V', 'Y', 'y', 'Z', 'z', 'ZH', 'ZH', 'zh', 'zh', '2', '5', '5', 'ts', 'w', + '|', '||', '|=', '!', 'DZ', 'Dz', 'dz', 'LJ', 'Lj', 'lj', 'NJ', 'Nj', 'nj', 'A', 'a', 'I', + 'i', 'O', 'o', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', '@', 'A', 'a', + 'A', 'a', 'AE', 'ae', 'G', 'g', 'G', 'g', 'K', 'k', 'O', 'o', 'O', 'o', 'ZH', 'zh', + 'j', 'DZ', 'D', 'dz', 'G', 'g', 'HV', 'W', 'N', 'n', 'A', 'a', 'AE', 'ae', 'O', 'o', + ], + 'xc7': [ + 'wek', 'wet', 'wep', 'weh', 'wi', 'wig', 'wigg', 'wigs', 'win', 'winj', 'winh', 'wid', 'wil', 'wilg', 'wilm', 'wilb', + 'wils', 'wilt', 'wilp', 'wilh', 'wim', 'wib', 'wibs', 'wis', 'wiss', 'wing', 'wij', 'wic', 'wik', 'wit', 'wip', 'wih', + 'yu', 'yug', 'yugg', 'yugs', 'yun', 'yunj', 'yunh', 'yud', 'yul', 'yulg', 'yulm', 'yulb', 'yuls', 'yult', 'yulp', 'yulh', + 'yum', 'yub', 'yubs', 'yus', 'yuss', 'yung', 'yuj', 'yuc', 'yuk', 'yut', 'yup', 'yuh', 'eu', 'eug', 'eugg', 'eugs', + 'eun', 'eunj', 'eunh', 'eud', 'eul', 'eulg', 'eulm', 'eulb', 'euls', 'eult', 'eulp', 'eulh', 'eum', 'eub', 'eubs', 'eus', + 'euss', 'eung', 'euj', 'euc', 'euk', 'eut', 'eup', 'euh', 'yi', 'yig', 'yigg', 'yigs', 'yin', 'yinj', 'yinh', 'yid', + 'yil', 'yilg', 'yilm', 'yilb', 'yils', 'yilt', 'yilp', 'yilh', 'yim', 'yib', 'yibs', 'yis', 'yiss', 'ying', 'yij', 'yic', + 'yik', 'yit', 'yip', 'yih', 'i', 'ig', 'igg', 'igs', 'in', 'inj', 'inh', 'id', 'il', 'ilg', 'ilm', 'ilb', + 'ils', 'ilt', 'ilp', 'ilh', 'im', 'ib', 'ibs', 'is', 'iss', 'ing', 'ij', 'ic', 'ik', 'it', 'ip', 'ih', + 'ja', 'jag', 'jagg', 'jags', 'jan', 'janj', 'janh', 'jad', 'jal', 'jalg', 'jalm', 'jalb', 'jals', 'jalt', 'jalp', 'jalh', + 'jam', 'jab', 'jabs', 'jas', 'jass', 'jang', 'jaj', 'jac', 'jak', 'jat', 'jap', 'jah', 'jae', 'jaeg', 'jaegg', 'jaegs', + 'jaen', 'jaenj', 'jaenh', 'jaed', 'jael', 'jaelg', 'jaelm', 'jaelb', 'jaels', 'jaelt', 'jaelp', 'jaelh', 'jaem', 'jaeb', 'jaebs', 'jaes', + 'jaess', 'jaeng', 'jaej', 'jaec', 'jaek', 'jaet', 'jaep', 'jaeh', 'jya', 'jyag', 'jyagg', 'jyags', 'jyan', 'jyanj', 'jyanh', 'jyad', + 'jyal', 'jyalg', 'jyalm', 'jyalb', 'jyals', 'jyalt', 'jyalp', 'jyalh', 'jyam', 'jyab', 'jyabs', 'jyas', 'jyass', 'jyang', 'jyaj', 'jyac', + 'jyak', 'jyat', 'jyap', 'jyah', 'jyae', 'jyaeg', 'jyaegg', 'jyaegs', 'jyaen', 'jyaenj', 'jyaenh', 'jyaed', 'jyael', 'jyaelg', 'jyaelm', 'jyaelb', + 'jyaels', 'jyaelt', 'jyaelp', 'jyaelh', 'jyaem', 'jyaeb', 'jyaebs', 'jyaes', 'jyaess', 'jyaeng', 'jyaej', 'jyaec', 'jyaek', 'jyaet', 'jyaep', 'jyaeh', + ], + 'x16': [ + 'kka', 'kk', 'nu', 'no', 'ne', 'nee', 'ni', 'na', 'mu', 'mo', 'me', 'mee', 'mi', 'ma', 'yu', 'yo', + 'ye', 'yee', 'yi', 'ya', 'ju', 'ju', 'jo', 'je', 'jee', 'ji', 'ji', 'ja', 'jju', 'jjo', 'jje', 'jjee', + 'jji', 'jja', 'lu', 'lo', 'le', 'lee', 'li', 'la', 'dlu', 'dlo', 'dle', 'dlee', 'dli', 'dla', 'lhu', 'lho', + 'lhe', 'lhee', 'lhi', 'lha', 'tlhu', 'tlho', 'tlhe', 'tlhee', 'tlhi', 'tlha', 'tlu', 'tlo', 'tle', 'tlee', 'tli', 'tla', + 'zu', 'zo', 'ze', 'zee', 'zi', 'za', 'z', 'z', 'dzu', 'dzo', 'dze', 'dzee', 'dzi', 'dza', 'su', 'so', + 'se', 'see', 'si', 'sa', 'shu', 'sho', 'she', 'shee', 'shi', 'sha', 'sh', 'tsu', 'tso', 'tse', 'tsee', 'tsi', + 'tsa', 'chu', 'cho', 'che', 'chee', 'chi', 'cha', 'ttsu', 'ttso', 'ttse', 'ttsee', 'ttsi', 'ttsa', 'X', '.', 'qai', + 'ngai', 'nngi', 'nngii', 'nngo', 'nngoo', 'nnga', 'nngaa', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + ' ', 'b', 'l', 'f', 's', 'n', 'h', 'd', 't', 'c', 'q', 'm', 'g', 'ng', 'z', 'r', + 'a', 'o', 'u', 'e', 'i', 'ch', 'th', 'ph', 'p', 'x', 'p', '<', '>', '[?]', '[?]', '[?]', + 'f', 'v', 'u', 'yr', 'y', 'w', 'th', 'th', 'a', 'o', 'ac', 'ae', 'o', 'o', 'o', 'oe', + 'on', 'r', 'k', 'c', 'k', 'g', 'ng', 'g', 'g', 'w', 'h', 'h', 'h', 'h', 'n', 'n', + 'n', 'i', 'e', 'j', 'g', 'ae', 'a', 'eo', 'p', 'z', 's', 's', 's', 'c', 'z', 't', + 't', 'd', 'b', 'b', 'p', 'p', 'e', 'm', 'm', 'm', 'l', 'l', 'ng', 'ng', 'd', 'o', + 'ear', 'ior', 'qu', 'qu', 'qu', 's', 'yr', 'yr', 'yr', 'q', 'x', '.', ':', '+', '17', '18', + '19', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + ], + 'xac': [ + 'ga', 'gag', 'gagg', 'gags', 'gan', 'ganj', 'ganh', 'gad', 'gal', 'galg', 'galm', 'galb', 'gals', 'galt', 'galp', 'galh', + 'gam', 'gab', 'gabs', 'gas', 'gass', 'gang', 'gaj', 'gac', 'gak', 'gat', 'gap', 'gah', 'gae', 'gaeg', 'gaegg', 'gaegs', + 'gaen', 'gaenj', 'gaenh', 'gaed', 'gael', 'gaelg', 'gaelm', 'gaelb', 'gaels', 'gaelt', 'gaelp', 'gaelh', 'gaem', 'gaeb', 'gaebs', 'gaes', + 'gaess', 'gaeng', 'gaej', 'gaec', 'gaek', 'gaet', 'gaep', 'gaeh', 'gya', 'gyag', 'gyagg', 'gyags', 'gyan', 'gyanj', 'gyanh', 'gyad', + 'gyal', 'gyalg', 'gyalm', 'gyalb', 'gyals', 'gyalt', 'gyalp', 'gyalh', 'gyam', 'gyab', 'gyabs', 'gyas', 'gyass', 'gyang', 'gyaj', 'gyac', + 'gyak', 'gyat', 'gyap', 'gyah', 'gyae', 'gyaeg', 'gyaegg', 'gyaegs', 'gyaen', 'gyaenj', 'gyaenh', 'gyaed', 'gyael', 'gyaelg', 'gyaelm', 'gyaelb', + 'gyaels', 'gyaelt', 'gyaelp', 'gyaelh', 'gyaem', 'gyaeb', 'gyaebs', 'gyaes', 'gyaess', 'gyaeng', 'gyaej', 'gyaec', 'gyaek', 'gyaet', 'gyaep', 'gyaeh', + 'geo', 'geog', 'geogg', 'geogs', 'geon', 'geonj', 'geonh', 'geod', 'geol', 'geolg', 'geolm', 'geolb', 'geols', 'geolt', 'geolp', 'geolh', + 'geom', 'geob', 'geobs', 'geos', 'geoss', 'geong', 'geoj', 'geoc', 'geok', 'geot', 'geop', 'geoh', 'ge', 'geg', 'gegg', 'gegs', + 'gen', 'genj', 'genh', 'ged', 'gel', 'gelg', 'gelm', 'gelb', 'gels', 'gelt', 'gelp', 'gelh', 'gem', 'geb', 'gebs', 'ges', + 'gess', 'geng', 'gej', 'gec', 'gek', 'get', 'gep', 'geh', 'gyeo', 'gyeog', 'gyeogg', 'gyeogs', 'gyeon', 'gyeonj', 'gyeonh', 'gyeod', + 'gyeol', 'gyeolg', 'gyeolm', 'gyeolb', 'gyeols', 'gyeolt', 'gyeolp', 'gyeolh', 'gyeom', 'gyeob', 'gyeobs', 'gyeos', 'gyeoss', 'gyeong', 'gyeoj', 'gyeoc', + 'gyeok', 'gyeot', 'gyeop', 'gyeoh', 'gye', 'gyeg', 'gyegg', 'gyegs', 'gyen', 'gyenj', 'gyenh', 'gyed', 'gyel', 'gyelg', 'gyelm', 'gyelb', + 'gyels', 'gyelt', 'gyelp', 'gyelh', 'gyem', 'gyeb', 'gyebs', 'gyes', 'gyess', 'gyeng', 'gyej', 'gyec', 'gyek', 'gyet', 'gyep', 'gyeh', + 'go', 'gog', 'gogg', 'gogs', 'gon', 'gonj', 'gonh', 'god', 'gol', 'golg', 'golm', 'golb', 'gols', 'golt', 'golp', 'golh', + 'gom', 'gob', 'gobs', 'gos', 'goss', 'gong', 'goj', 'goc', 'gok', 'got', 'gop', 'goh', 'gwa', 'gwag', 'gwagg', 'gwags', + ], + 'xbf': [ + 'bbess', 'bbeng', 'bbej', 'bbec', 'bbek', 'bbet', 'bbep', 'bbeh', 'bbyeo', 'bbyeog', 'bbyeogg', 'bbyeogs', 'bbyeon', 'bbyeonj', 'bbyeonh', 'bbyeod', + 'bbyeol', 'bbyeolg', 'bbyeolm', 'bbyeolb', 'bbyeols', 'bbyeolt', 'bbyeolp', 'bbyeolh', 'bbyeom', 'bbyeob', 'bbyeobs', 'bbyeos', 'bbyeoss', 'bbyeong', 'bbyeoj', 'bbyeoc', + 'bbyeok', 'bbyeot', 'bbyeop', 'bbyeoh', 'bbye', 'bbyeg', 'bbyegg', 'bbyegs', 'bbyen', 'bbyenj', 'bbyenh', 'bbyed', 'bbyel', 'bbyelg', 'bbyelm', 'bbyelb', + 'bbyels', 'bbyelt', 'bbyelp', 'bbyelh', 'bbyem', 'bbyeb', 'bbyebs', 'bbyes', 'bbyess', 'bbyeng', 'bbyej', 'bbyec', 'bbyek', 'bbyet', 'bbyep', 'bbyeh', + 'bbo', 'bbog', 'bbogg', 'bbogs', 'bbon', 'bbonj', 'bbonh', 'bbod', 'bbol', 'bbolg', 'bbolm', 'bbolb', 'bbols', 'bbolt', 'bbolp', 'bbolh', + 'bbom', 'bbob', 'bbobs', 'bbos', 'bboss', 'bbong', 'bboj', 'bboc', 'bbok', 'bbot', 'bbop', 'bboh', 'bbwa', 'bbwag', 'bbwagg', 'bbwags', + 'bbwan', 'bbwanj', 'bbwanh', 'bbwad', 'bbwal', 'bbwalg', 'bbwalm', 'bbwalb', 'bbwals', 'bbwalt', 'bbwalp', 'bbwalh', 'bbwam', 'bbwab', 'bbwabs', 'bbwas', + 'bbwass', 'bbwang', 'bbwaj', 'bbwac', 'bbwak', 'bbwat', 'bbwap', 'bbwah', 'bbwae', 'bbwaeg', 'bbwaegg', 'bbwaegs', 'bbwaen', 'bbwaenj', 'bbwaenh', 'bbwaed', + 'bbwael', 'bbwaelg', 'bbwaelm', 'bbwaelb', 'bbwaels', 'bbwaelt', 'bbwaelp', 'bbwaelh', 'bbwaem', 'bbwaeb', 'bbwaebs', 'bbwaes', 'bbwaess', 'bbwaeng', 'bbwaej', 'bbwaec', + 'bbwaek', 'bbwaet', 'bbwaep', 'bbwaeh', 'bboe', 'bboeg', 'bboegg', 'bboegs', 'bboen', 'bboenj', 'bboenh', 'bboed', 'bboel', 'bboelg', 'bboelm', 'bboelb', + 'bboels', 'bboelt', 'bboelp', 'bboelh', 'bboem', 'bboeb', 'bboebs', 'bboes', 'bboess', 'bboeng', 'bboej', 'bboec', 'bboek', 'bboet', 'bboep', 'bboeh', + 'bbyo', 'bbyog', 'bbyogg', 'bbyogs', 'bbyon', 'bbyonj', 'bbyonh', 'bbyod', 'bbyol', 'bbyolg', 'bbyolm', 'bbyolb', 'bbyols', 'bbyolt', 'bbyolp', 'bbyolh', + 'bbyom', 'bbyob', 'bbyobs', 'bbyos', 'bbyoss', 'bbyong', 'bbyoj', 'bbyoc', 'bbyok', 'bbyot', 'bbyop', 'bbyoh', 'bbu', 'bbug', 'bbugg', 'bbugs', + 'bbun', 'bbunj', 'bbunh', 'bbud', 'bbul', 'bbulg', 'bbulm', 'bbulb', 'bbuls', 'bbult', 'bbulp', 'bbulh', 'bbum', 'bbub', 'bbubs', 'bbus', + 'bbuss', 'bbung', 'bbuj', 'bbuc', 'bbuk', 'bbut', 'bbup', 'bbuh', 'bbweo', 'bbweog', 'bbweogg', 'bbweogs', 'bbweon', 'bbweonj', 'bbweonh', 'bbweod', + 'bbweol', 'bbweolg', 'bbweolm', 'bbweolb', 'bbweols', 'bbweolt', 'bbweolp', 'bbweolh', 'bbweom', 'bbweob', 'bbweobs', 'bbweos', 'bbweoss', 'bbweong', 'bbweoj', 'bbweoc', + ], + 'xd3': [ + 'tim', 'tib', 'tibs', 'tis', 'tiss', 'ting', 'tij', 'tic', 'tik', 'tit', 'tip', 'tih', 'pa', 'pag', 'pagg', 'pags', + 'pan', 'panj', 'panh', 'pad', 'pal', 'palg', 'palm', 'palb', 'pals', 'palt', 'palp', 'palh', 'pam', 'pab', 'pabs', 'pas', + 'pass', 'pang', 'paj', 'pac', 'pak', 'pat', 'pap', 'pah', 'pae', 'paeg', 'paegg', 'paegs', 'paen', 'paenj', 'paenh', 'paed', + 'pael', 'paelg', 'paelm', 'paelb', 'paels', 'paelt', 'paelp', 'paelh', 'paem', 'paeb', 'paebs', 'paes', 'paess', 'paeng', 'paej', 'paec', + 'paek', 'paet', 'paep', 'paeh', 'pya', 'pyag', 'pyagg', 'pyags', 'pyan', 'pyanj', 'pyanh', 'pyad', 'pyal', 'pyalg', 'pyalm', 'pyalb', + 'pyals', 'pyalt', 'pyalp', 'pyalh', 'pyam', 'pyab', 'pyabs', 'pyas', 'pyass', 'pyang', 'pyaj', 'pyac', 'pyak', 'pyat', 'pyap', 'pyah', + 'pyae', 'pyaeg', 'pyaegg', 'pyaegs', 'pyaen', 'pyaenj', 'pyaenh', 'pyaed', 'pyael', 'pyaelg', 'pyaelm', 'pyaelb', 'pyaels', 'pyaelt', 'pyaelp', 'pyaelh', + 'pyaem', 'pyaeb', 'pyaebs', 'pyaes', 'pyaess', 'pyaeng', 'pyaej', 'pyaec', 'pyaek', 'pyaet', 'pyaep', 'pyaeh', 'peo', 'peog', 'peogg', 'peogs', + 'peon', 'peonj', 'peonh', 'peod', 'peol', 'peolg', 'peolm', 'peolb', 'peols', 'peolt', 'peolp', 'peolh', 'peom', 'peob', 'peobs', 'peos', + 'peoss', 'peong', 'peoj', 'peoc', 'peok', 'peot', 'peop', 'peoh', 'pe', 'peg', 'pegg', 'pegs', 'pen', 'penj', 'penh', 'ped', + 'pel', 'pelg', 'pelm', 'pelb', 'pels', 'pelt', 'pelp', 'pelh', 'pem', 'peb', 'pebs', 'pes', 'pess', 'peng', 'pej', 'pec', + 'pek', 'pet', 'pep', 'peh', 'pyeo', 'pyeog', 'pyeogg', 'pyeogs', 'pyeon', 'pyeonj', 'pyeonh', 'pyeod', 'pyeol', 'pyeolg', 'pyeolm', 'pyeolb', + 'pyeols', 'pyeolt', 'pyeolp', 'pyeolh', 'pyeom', 'pyeob', 'pyeobs', 'pyeos', 'pyeoss', 'pyeong', 'pyeoj', 'pyeoc', 'pyeok', 'pyeot', 'pyeop', 'pyeoh', + 'pye', 'pyeg', 'pyegg', 'pyegs', 'pyen', 'pyenj', 'pyenh', 'pyed', 'pyel', 'pyelg', 'pyelm', 'pyelb', 'pyels', 'pyelt', 'pyelp', 'pyelh', + 'pyem', 'pyeb', 'pyebs', 'pyes', 'pyess', 'pyeng', 'pyej', 'pyec', 'pyek', 'pyet', 'pyep', 'pyeh', 'po', 'pog', 'pogg', 'pogs', + 'pon', 'ponj', 'ponh', 'pod', 'pol', 'polg', 'polm', 'polb', 'pols', 'polt', 'polp', 'polh', 'pom', 'pob', 'pobs', 'pos', + ], + 'x0e': [ + '[?]', 'k', 'kh', 'kh', 'kh', 'kh', 'kh', 'ng', 'cch', 'ch', 'ch', 'ch', 'ch', 'y', 'd', 't', + 'th', 'th', 'th', 'n', 'd', 't', 'th', 'th', 'th', 'n', 'b', 'p', 'ph', 'f', 'ph', 'f', + 'ph', 'm', 'y', 'r', 'R', 'l', 'L', 'w', 's', 's', 's', 'h', 'l', '`', 'h', '~', + 'a', 'a', 'aa', 'am', 'i', 'ii', 'ue', 'uue', 'u', 'uu', '\'', '[?]', '[?]', '[?]', '[?]', 'Bh.', + 'e', 'ae', 'o', 'ai', 'ai', 'ao', '+', '', '', '', '', '', '', 'M', '', ' * ', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ' // ', ' /// ', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', 'k', 'kh', '[?]', 'kh', '[?]', '[?]', 'ng', 'ch', '[?]', 's', '[?]', '[?]', 'ny', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', 'd', 'h', 'th', 'th', '[?]', 'n', 'b', 'p', 'ph', 'f', 'ph', 'f', + '[?]', 'm', 'y', 'r', '[?]', 'l', '[?]', 'w', '[?]', '[?]', 's', 'h', '[?]', '`', '', '~', + 'a', '', 'aa', 'am', 'i', 'ii', 'y', 'yy', 'u', 'uu', '[?]', 'o', 'l', 'ny', '[?]', '[?]', + 'e', 'ei', 'o', 'ay', 'ai', '[?]', '+', '[?]', '', '', '', '', '', 'M', '[?]', '[?]', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '[?]', '[?]', 'hn', 'hm', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + ], + 'xbd': [ + 'bols', 'bolt', 'bolp', 'bolh', 'bom', 'bob', 'bobs', 'bos', 'boss', 'bong', 'boj', 'boc', 'bok', 'bot', 'bop', 'boh', + 'bwa', 'bwag', 'bwagg', 'bwags', 'bwan', 'bwanj', 'bwanh', 'bwad', 'bwal', 'bwalg', 'bwalm', 'bwalb', 'bwals', 'bwalt', 'bwalp', 'bwalh', + 'bwam', 'bwab', 'bwabs', 'bwas', 'bwass', 'bwang', 'bwaj', 'bwac', 'bwak', 'bwat', 'bwap', 'bwah', 'bwae', 'bwaeg', 'bwaegg', 'bwaegs', + 'bwaen', 'bwaenj', 'bwaenh', 'bwaed', 'bwael', 'bwaelg', 'bwaelm', 'bwaelb', 'bwaels', 'bwaelt', 'bwaelp', 'bwaelh', 'bwaem', 'bwaeb', 'bwaebs', 'bwaes', + 'bwaess', 'bwaeng', 'bwaej', 'bwaec', 'bwaek', 'bwaet', 'bwaep', 'bwaeh', 'boe', 'boeg', 'boegg', 'boegs', 'boen', 'boenj', 'boenh', 'boed', + 'boel', 'boelg', 'boelm', 'boelb', 'boels', 'boelt', 'boelp', 'boelh', 'boem', 'boeb', 'boebs', 'boes', 'boess', 'boeng', 'boej', 'boec', + 'boek', 'boet', 'boep', 'boeh', 'byo', 'byog', 'byogg', 'byogs', 'byon', 'byonj', 'byonh', 'byod', 'byol', 'byolg', 'byolm', 'byolb', + 'byols', 'byolt', 'byolp', 'byolh', 'byom', 'byob', 'byobs', 'byos', 'byoss', 'byong', 'byoj', 'byoc', 'byok', 'byot', 'byop', 'byoh', + 'bu', 'bug', 'bugg', 'bugs', 'bun', 'bunj', 'bunh', 'bud', 'bul', 'bulg', 'bulm', 'bulb', 'buls', 'bult', 'bulp', 'bulh', + 'bum', 'bub', 'bubs', 'bus', 'buss', 'bung', 'buj', 'buc', 'buk', 'but', 'bup', 'buh', 'bweo', 'bweog', 'bweogg', 'bweogs', + 'bweon', 'bweonj', 'bweonh', 'bweod', 'bweol', 'bweolg', 'bweolm', 'bweolb', 'bweols', 'bweolt', 'bweolp', 'bweolh', 'bweom', 'bweob', 'bweobs', 'bweos', + 'bweoss', 'bweong', 'bweoj', 'bweoc', 'bweok', 'bweot', 'bweop', 'bweoh', 'bwe', 'bweg', 'bwegg', 'bwegs', 'bwen', 'bwenj', 'bwenh', 'bwed', + 'bwel', 'bwelg', 'bwelm', 'bwelb', 'bwels', 'bwelt', 'bwelp', 'bwelh', 'bwem', 'bweb', 'bwebs', 'bwes', 'bwess', 'bweng', 'bwej', 'bwec', + 'bwek', 'bwet', 'bwep', 'bweh', 'bwi', 'bwig', 'bwigg', 'bwigs', 'bwin', 'bwinj', 'bwinh', 'bwid', 'bwil', 'bwilg', 'bwilm', 'bwilb', + 'bwils', 'bwilt', 'bwilp', 'bwilh', 'bwim', 'bwib', 'bwibs', 'bwis', 'bwiss', 'bwing', 'bwij', 'bwic', 'bwik', 'bwit', 'bwip', 'bwih', + 'byu', 'byug', 'byugg', 'byugs', 'byun', 'byunj', 'byunh', 'byud', 'byul', 'byulg', 'byulm', 'byulb', 'byuls', 'byult', 'byulp', 'byulh', + ], + 'x0c': [ + '[?]', 'N', 'N', 'H', '[?]', 'a', 'aa', 'i', 'ii', 'u', 'uu', 'R', 'L', '[?]', 'e', 'ee', + 'ai', '[?]', 'o', 'oo', 'au', 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', 'jh', 'ny', 'tt', + 'tth', 'dd', 'ddh', 'nn', 't', 'th', 'd', 'dh', 'n', '[?]', 'p', 'ph', 'b', 'bh', 'm', 'y', + 'r', 'rr', 'l', 'll', '[?]', 'v', 'sh', 'ss', 's', 'h', '[?]', '[?]', '[?]', '[?]', 'aa', 'i', + 'ii', 'u', 'uu', 'R', 'RR', '[?]', 'e', 'ee', 'ai', '[?]', 'o', 'oo', 'au', '', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '+', '+', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + 'RR', 'LL', '[?]', '[?]', '[?]', '[?]', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', 'N', 'H', '[?]', 'a', 'aa', 'i', 'ii', 'u', 'uu', 'R', 'L', '[?]', 'e', 'ee', + 'ai', '[?]', 'o', 'oo', 'au', 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', 'jh', 'ny', 'tt', + 'tth', 'dd', 'ddh', 'nn', 't', 'th', 'd', 'dh', 'n', '[?]', 'p', 'ph', 'b', 'bh', 'm', 'y', + 'r', 'rr', 'l', 'll', '[?]', 'v', 'sh', 'ss', 's', 'h', '[?]', '[?]', '[?]', '[?]', 'aa', 'i', + 'ii', 'u', 'uu', 'R', 'RR', '[?]', 'e', 'ee', 'ai', '[?]', 'o', 'oo', 'au', '', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '+', '+', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', 'lll', '[?]', + 'RR', 'LL', '[?]', '[?]', '[?]', '[?]', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + ], + 'xd1': [ + 'tyal', 'tyalg', 'tyalm', 'tyalb', 'tyals', 'tyalt', 'tyalp', 'tyalh', 'tyam', 'tyab', 'tyabs', 'tyas', 'tyass', 'tyang', 'tyaj', 'tyac', + 'tyak', 'tyat', 'tyap', 'tyah', 'tyae', 'tyaeg', 'tyaegg', 'tyaegs', 'tyaen', 'tyaenj', 'tyaenh', 'tyaed', 'tyael', 'tyaelg', 'tyaelm', 'tyaelb', + 'tyaels', 'tyaelt', 'tyaelp', 'tyaelh', 'tyaem', 'tyaeb', 'tyaebs', 'tyaes', 'tyaess', 'tyaeng', 'tyaej', 'tyaec', 'tyaek', 'tyaet', 'tyaep', 'tyaeh', + 'teo', 'teog', 'teogg', 'teogs', 'teon', 'teonj', 'teonh', 'teod', 'teol', 'teolg', 'teolm', 'teolb', 'teols', 'teolt', 'teolp', 'teolh', + 'teom', 'teob', 'teobs', 'teos', 'teoss', 'teong', 'teoj', 'teoc', 'teok', 'teot', 'teop', 'teoh', 'te', 'teg', 'tegg', 'tegs', + 'ten', 'tenj', 'tenh', 'ted', 'tel', 'telg', 'telm', 'telb', 'tels', 'telt', 'telp', 'telh', 'tem', 'teb', 'tebs', 'tes', + 'tess', 'teng', 'tej', 'tec', 'tek', 'tet', 'tep', 'teh', 'tyeo', 'tyeog', 'tyeogg', 'tyeogs', 'tyeon', 'tyeonj', 'tyeonh', 'tyeod', + 'tyeol', 'tyeolg', 'tyeolm', 'tyeolb', 'tyeols', 'tyeolt', 'tyeolp', 'tyeolh', 'tyeom', 'tyeob', 'tyeobs', 'tyeos', 'tyeoss', 'tyeong', 'tyeoj', 'tyeoc', + 'tyeok', 'tyeot', 'tyeop', 'tyeoh', 'tye', 'tyeg', 'tyegg', 'tyegs', 'tyen', 'tyenj', 'tyenh', 'tyed', 'tyel', 'tyelg', 'tyelm', 'tyelb', + 'tyels', 'tyelt', 'tyelp', 'tyelh', 'tyem', 'tyeb', 'tyebs', 'tyes', 'tyess', 'tyeng', 'tyej', 'tyec', 'tyek', 'tyet', 'tyep', 'tyeh', + 'to', 'tog', 'togg', 'togs', 'ton', 'tonj', 'tonh', 'tod', 'tol', 'tolg', 'tolm', 'tolb', 'tols', 'tolt', 'tolp', 'tolh', + 'tom', 'tob', 'tobs', 'tos', 'toss', 'tong', 'toj', 'toc', 'tok', 'tot', 'top', 'toh', 'twa', 'twag', 'twagg', 'twags', + 'twan', 'twanj', 'twanh', 'twad', 'twal', 'twalg', 'twalm', 'twalb', 'twals', 'twalt', 'twalp', 'twalh', 'twam', 'twab', 'twabs', 'twas', + 'twass', 'twang', 'twaj', 'twac', 'twak', 'twat', 'twap', 'twah', 'twae', 'twaeg', 'twaegg', 'twaegs', 'twaen', 'twaenj', 'twaenh', 'twaed', + 'twael', 'twaelg', 'twaelm', 'twaelb', 'twaels', 'twaelt', 'twaelp', 'twaelh', 'twaem', 'twaeb', 'twaebs', 'twaes', 'twaess', 'twaeng', 'twaej', 'twaec', + 'twaek', 'twaet', 'twaep', 'twaeh', 'toe', 'toeg', 'toegg', 'toegs', 'toen', 'toenj', 'toenh', 'toed', 'toel', 'toelg', 'toelm', 'toelb', + ], + 'x26': [ + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '[?]', '[?]', '[?]', '[?]', '[?]', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + ], + 'xd4': [ + 'poss', 'pong', 'poj', 'poc', 'pok', 'pot', 'pop', 'poh', 'pwa', 'pwag', 'pwagg', 'pwags', 'pwan', 'pwanj', 'pwanh', 'pwad', + 'pwal', 'pwalg', 'pwalm', 'pwalb', 'pwals', 'pwalt', 'pwalp', 'pwalh', 'pwam', 'pwab', 'pwabs', 'pwas', 'pwass', 'pwang', 'pwaj', 'pwac', + 'pwak', 'pwat', 'pwap', 'pwah', 'pwae', 'pwaeg', 'pwaegg', 'pwaegs', 'pwaen', 'pwaenj', 'pwaenh', 'pwaed', 'pwael', 'pwaelg', 'pwaelm', 'pwaelb', + 'pwaels', 'pwaelt', 'pwaelp', 'pwaelh', 'pwaem', 'pwaeb', 'pwaebs', 'pwaes', 'pwaess', 'pwaeng', 'pwaej', 'pwaec', 'pwaek', 'pwaet', 'pwaep', 'pwaeh', + 'poe', 'poeg', 'poegg', 'poegs', 'poen', 'poenj', 'poenh', 'poed', 'poel', 'poelg', 'poelm', 'poelb', 'poels', 'poelt', 'poelp', 'poelh', + 'poem', 'poeb', 'poebs', 'poes', 'poess', 'poeng', 'poej', 'poec', 'poek', 'poet', 'poep', 'poeh', 'pyo', 'pyog', 'pyogg', 'pyogs', + 'pyon', 'pyonj', 'pyonh', 'pyod', 'pyol', 'pyolg', 'pyolm', 'pyolb', 'pyols', 'pyolt', 'pyolp', 'pyolh', 'pyom', 'pyob', 'pyobs', 'pyos', + 'pyoss', 'pyong', 'pyoj', 'pyoc', 'pyok', 'pyot', 'pyop', 'pyoh', 'pu', 'pug', 'pugg', 'pugs', 'pun', 'punj', 'punh', 'pud', + 'pul', 'pulg', 'pulm', 'pulb', 'puls', 'pult', 'pulp', 'pulh', 'pum', 'pub', 'pubs', 'pus', 'puss', 'pung', 'puj', 'puc', + 'puk', 'put', 'pup', 'puh', 'pweo', 'pweog', 'pweogg', 'pweogs', 'pweon', 'pweonj', 'pweonh', 'pweod', 'pweol', 'pweolg', 'pweolm', 'pweolb', + 'pweols', 'pweolt', 'pweolp', 'pweolh', 'pweom', 'pweob', 'pweobs', 'pweos', 'pweoss', 'pweong', 'pweoj', 'pweoc', 'pweok', 'pweot', 'pweop', 'pweoh', + 'pwe', 'pweg', 'pwegg', 'pwegs', 'pwen', 'pwenj', 'pwenh', 'pwed', 'pwel', 'pwelg', 'pwelm', 'pwelb', 'pwels', 'pwelt', 'pwelp', 'pwelh', + 'pwem', 'pweb', 'pwebs', 'pwes', 'pwess', 'pweng', 'pwej', 'pwec', 'pwek', 'pwet', 'pwep', 'pweh', 'pwi', 'pwig', 'pwigg', 'pwigs', + 'pwin', 'pwinj', 'pwinh', 'pwid', 'pwil', 'pwilg', 'pwilm', 'pwilb', 'pwils', 'pwilt', 'pwilp', 'pwilh', 'pwim', 'pwib', 'pwibs', 'pwis', + 'pwiss', 'pwing', 'pwij', 'pwic', 'pwik', 'pwit', 'pwip', 'pwih', 'pyu', 'pyug', 'pyugg', 'pyugs', 'pyun', 'pyunj', 'pyunh', 'pyud', + 'pyul', 'pyulg', 'pyulm', 'pyulb', 'pyuls', 'pyult', 'pyulp', 'pyulh', 'pyum', 'pyub', 'pyubs', 'pyus', 'pyuss', 'pyung', 'pyuj', 'pyuc', + ], + 'x12': [ + 'ha', 'hu', 'hi', 'haa', 'hee', 'he', 'ho', '[?]', 'la', 'lu', 'li', 'laa', 'lee', 'le', 'lo', 'lwa', + 'hha', 'hhu', 'hhi', 'hhaa', 'hhee', 'hhe', 'hho', 'hhwa', 'ma', 'mu', 'mi', 'maa', 'mee', 'me', 'mo', 'mwa', + 'sza', 'szu', 'szi', 'szaa', 'szee', 'sze', 'szo', 'szwa', 'ra', 'ru', 'ri', 'raa', 'ree', 're', 'ro', 'rwa', + 'sa', 'su', 'si', 'saa', 'see', 'se', 'so', 'swa', 'sha', 'shu', 'shi', 'shaa', 'shee', 'she', 'sho', 'shwa', + 'qa', 'qu', 'qi', 'qaa', 'qee', 'qe', 'qo', '[?]', 'qwa', '[?]', 'qwi', 'qwaa', 'qwee', 'qwe', '[?]', '[?]', + 'qha', 'qhu', 'qhi', 'qhaa', 'qhee', 'qhe', 'qho', '[?]', 'qhwa', '[?]', 'qhwi', 'qhwaa', 'qhwee', 'qhwe', '[?]', '[?]', + 'ba', 'bu', 'bi', 'baa', 'bee', 'be', 'bo', 'bwa', 'va', 'vu', 'vi', 'vaa', 'vee', 've', 'vo', 'vwa', + 'ta', 'tu', 'ti', 'taa', 'tee', 'te', 'to', 'twa', 'ca', 'cu', 'ci', 'caa', 'cee', 'ce', 'co', 'cwa', + 'xa', 'xu', 'xi', 'xaa', 'xee', 'xe', 'xo', '[?]', 'xwa', '[?]', 'xwi', 'xwaa', 'xwee', 'xwe', '[?]', '[?]', + 'na', 'nu', 'ni', 'naa', 'nee', 'ne', 'no', 'nwa', 'nya', 'nyu', 'nyi', 'nyaa', 'nyee', 'nye', 'nyo', 'nywa', + '\'a', '\'u', '[?]', '\'aa', '\'ee', '\'e', '\'o', '\'wa', 'ka', 'ku', 'ki', 'kaa', 'kee', 'ke', 'ko', '[?]', + 'kwa', '[?]', 'kwi', 'kwaa', 'kwee', 'kwe', '[?]', '[?]', 'kxa', 'kxu', 'kxi', 'kxaa', 'kxee', 'kxe', 'kxo', '[?]', + 'kxwa', '[?]', 'kxwi', 'kxwaa', 'kxwee', 'kxwe', '[?]', '[?]', 'wa', 'wu', 'wi', 'waa', 'wee', 'we', 'wo', '[?]', + '`a', '`u', '`i', '`aa', '`ee', '`e', '`o', '[?]', 'za', 'zu', 'zi', 'zaa', 'zee', 'ze', 'zo', 'zwa', + 'zha', 'zhu', 'zhi', 'zhaa', 'zhee', 'zhe', 'zho', 'zhwa', 'ya', 'yu', 'yi', 'yaa', 'yee', 'ye', 'yo', '[?]', + 'da', 'du', 'di', 'daa', 'dee', 'de', 'do', 'dwa', 'dda', 'ddu', 'ddi', 'ddaa', 'ddee', 'dde', 'ddo', 'ddwa', + ], + 'xc8': [ + 'jeo', 'jeog', 'jeogg', 'jeogs', 'jeon', 'jeonj', 'jeonh', 'jeod', 'jeol', 'jeolg', 'jeolm', 'jeolb', 'jeols', 'jeolt', 'jeolp', 'jeolh', + 'jeom', 'jeob', 'jeobs', 'jeos', 'jeoss', 'jeong', 'jeoj', 'jeoc', 'jeok', 'jeot', 'jeop', 'jeoh', 'je', 'jeg', 'jegg', 'jegs', + 'jen', 'jenj', 'jenh', 'jed', 'jel', 'jelg', 'jelm', 'jelb', 'jels', 'jelt', 'jelp', 'jelh', 'jem', 'jeb', 'jebs', 'jes', + 'jess', 'jeng', 'jej', 'jec', 'jek', 'jet', 'jep', 'jeh', 'jyeo', 'jyeog', 'jyeogg', 'jyeogs', 'jyeon', 'jyeonj', 'jyeonh', 'jyeod', + 'jyeol', 'jyeolg', 'jyeolm', 'jyeolb', 'jyeols', 'jyeolt', 'jyeolp', 'jyeolh', 'jyeom', 'jyeob', 'jyeobs', 'jyeos', 'jyeoss', 'jyeong', 'jyeoj', 'jyeoc', + 'jyeok', 'jyeot', 'jyeop', 'jyeoh', 'jye', 'jyeg', 'jyegg', 'jyegs', 'jyen', 'jyenj', 'jyenh', 'jyed', 'jyel', 'jyelg', 'jyelm', 'jyelb', + 'jyels', 'jyelt', 'jyelp', 'jyelh', 'jyem', 'jyeb', 'jyebs', 'jyes', 'jyess', 'jyeng', 'jyej', 'jyec', 'jyek', 'jyet', 'jyep', 'jyeh', + 'jo', 'jog', 'jogg', 'jogs', 'jon', 'jonj', 'jonh', 'jod', 'jol', 'jolg', 'jolm', 'jolb', 'jols', 'jolt', 'jolp', 'jolh', + 'jom', 'job', 'jobs', 'jos', 'joss', 'jong', 'joj', 'joc', 'jok', 'jot', 'jop', 'joh', 'jwa', 'jwag', 'jwagg', 'jwags', + 'jwan', 'jwanj', 'jwanh', 'jwad', 'jwal', 'jwalg', 'jwalm', 'jwalb', 'jwals', 'jwalt', 'jwalp', 'jwalh', 'jwam', 'jwab', 'jwabs', 'jwas', + 'jwass', 'jwang', 'jwaj', 'jwac', 'jwak', 'jwat', 'jwap', 'jwah', 'jwae', 'jwaeg', 'jwaegg', 'jwaegs', 'jwaen', 'jwaenj', 'jwaenh', 'jwaed', + 'jwael', 'jwaelg', 'jwaelm', 'jwaelb', 'jwaels', 'jwaelt', 'jwaelp', 'jwaelh', 'jwaem', 'jwaeb', 'jwaebs', 'jwaes', 'jwaess', 'jwaeng', 'jwaej', 'jwaec', + 'jwaek', 'jwaet', 'jwaep', 'jwaeh', 'joe', 'joeg', 'joegg', 'joegs', 'joen', 'joenj', 'joenh', 'joed', 'joel', 'joelg', 'joelm', 'joelb', + 'joels', 'joelt', 'joelp', 'joelh', 'joem', 'joeb', 'joebs', 'joes', 'joess', 'joeng', 'joej', 'joec', 'joek', 'joet', 'joep', 'joeh', + 'jyo', 'jyog', 'jyogg', 'jyogs', 'jyon', 'jyonj', 'jyonh', 'jyod', 'jyol', 'jyolg', 'jyolm', 'jyolb', 'jyols', 'jyolt', 'jyolp', 'jyolh', + 'jyom', 'jyob', 'jyobs', 'jyos', 'jyoss', 'jyong', 'jyoj', 'jyoc', 'jyok', 'jyot', 'jyop', 'jyoh', 'ju', 'jug', 'jugg', 'jugs', + ], + 'xaf': [ + 'ggyeols', 'ggyeolt', 'ggyeolp', 'ggyeolh', 'ggyeom', 'ggyeob', 'ggyeobs', 'ggyeos', 'ggyeoss', 'ggyeong', 'ggyeoj', 'ggyeoc', 'ggyeok', 'ggyeot', 'ggyeop', 'ggyeoh', + 'ggye', 'ggyeg', 'ggyegg', 'ggyegs', 'ggyen', 'ggyenj', 'ggyenh', 'ggyed', 'ggyel', 'ggyelg', 'ggyelm', 'ggyelb', 'ggyels', 'ggyelt', 'ggyelp', 'ggyelh', + 'ggyem', 'ggyeb', 'ggyebs', 'ggyes', 'ggyess', 'ggyeng', 'ggyej', 'ggyec', 'ggyek', 'ggyet', 'ggyep', 'ggyeh', 'ggo', 'ggog', 'ggogg', 'ggogs', + 'ggon', 'ggonj', 'ggonh', 'ggod', 'ggol', 'ggolg', 'ggolm', 'ggolb', 'ggols', 'ggolt', 'ggolp', 'ggolh', 'ggom', 'ggob', 'ggobs', 'ggos', + 'ggoss', 'ggong', 'ggoj', 'ggoc', 'ggok', 'ggot', 'ggop', 'ggoh', 'ggwa', 'ggwag', 'ggwagg', 'ggwags', 'ggwan', 'ggwanj', 'ggwanh', 'ggwad', + 'ggwal', 'ggwalg', 'ggwalm', 'ggwalb', 'ggwals', 'ggwalt', 'ggwalp', 'ggwalh', 'ggwam', 'ggwab', 'ggwabs', 'ggwas', 'ggwass', 'ggwang', 'ggwaj', 'ggwac', + 'ggwak', 'ggwat', 'ggwap', 'ggwah', 'ggwae', 'ggwaeg', 'ggwaegg', 'ggwaegs', 'ggwaen', 'ggwaenj', 'ggwaenh', 'ggwaed', 'ggwael', 'ggwaelg', 'ggwaelm', 'ggwaelb', + 'ggwaels', 'ggwaelt', 'ggwaelp', 'ggwaelh', 'ggwaem', 'ggwaeb', 'ggwaebs', 'ggwaes', 'ggwaess', 'ggwaeng', 'ggwaej', 'ggwaec', 'ggwaek', 'ggwaet', 'ggwaep', 'ggwaeh', + 'ggoe', 'ggoeg', 'ggoegg', 'ggoegs', 'ggoen', 'ggoenj', 'ggoenh', 'ggoed', 'ggoel', 'ggoelg', 'ggoelm', 'ggoelb', 'ggoels', 'ggoelt', 'ggoelp', 'ggoelh', + 'ggoem', 'ggoeb', 'ggoebs', 'ggoes', 'ggoess', 'ggoeng', 'ggoej', 'ggoec', 'ggoek', 'ggoet', 'ggoep', 'ggoeh', 'ggyo', 'ggyog', 'ggyogg', 'ggyogs', + 'ggyon', 'ggyonj', 'ggyonh', 'ggyod', 'ggyol', 'ggyolg', 'ggyolm', 'ggyolb', 'ggyols', 'ggyolt', 'ggyolp', 'ggyolh', 'ggyom', 'ggyob', 'ggyobs', 'ggyos', + 'ggyoss', 'ggyong', 'ggyoj', 'ggyoc', 'ggyok', 'ggyot', 'ggyop', 'ggyoh', 'ggu', 'ggug', 'ggugg', 'ggugs', 'ggun', 'ggunj', 'ggunh', 'ggud', + 'ggul', 'ggulg', 'ggulm', 'ggulb', 'gguls', 'ggult', 'ggulp', 'ggulh', 'ggum', 'ggub', 'ggubs', 'ggus', 'gguss', 'ggung', 'gguj', 'gguc', + 'gguk', 'ggut', 'ggup', 'gguh', 'ggweo', 'ggweog', 'ggweogg', 'ggweogs', 'ggweon', 'ggweonj', 'ggweonh', 'ggweod', 'ggweol', 'ggweolg', 'ggweolm', 'ggweolb', + 'ggweols', 'ggweolt', 'ggweolp', 'ggweolh', 'ggweom', 'ggweob', 'ggweobs', 'ggweos', 'ggweoss', 'ggweong', 'ggweoj', 'ggweoc', 'ggweok', 'ggweot', 'ggweop', 'ggweoh', + 'ggwe', 'ggweg', 'ggwegg', 'ggwegs', 'ggwen', 'ggwenj', 'ggwenh', 'ggwed', 'ggwel', 'ggwelg', 'ggwelm', 'ggwelb', 'ggwels', 'ggwelt', 'ggwelp', 'ggwelh', + ], + 'x28': [ + ' ', 'a', '1', 'b', '\'', 'k', '2', 'l', '@', 'c', 'i', 'f', '/', 'm', 's', 'p', + '"', 'e', '3', 'h', '9', 'o', '6', 'r', '^', 'd', 'j', 'g', '>', 'n', 't', 'q', + ',', '*', '5', '<', '-', 'u', '8', 'v', '.', '%', '[', '\\$', '+', 'x', '!', '&', + ';', ':', '4', '\\', '0', 'z', '7', '(', '_', '?', 'w', ']', '#', 'y', ')', '=', + '[d7]', '[d17]', '[d27]', '[d127]', '[d37]', '[d137]', '[d237]', '[d1237]', '[d47]', '[d147]', '[d247]', '[d1247]', '[d347]', '[d1347]', '[d2347]', '[d12347]', + '[d57]', '[d157]', '[d257]', '[d1257]', '[d357]', '[d1357]', '[d2357]', '[d12357]', '[d457]', '[d1457]', '[d2457]', '[d12457]', '[d3457]', '[d13457]', '[d23457]', '[d123457]', + '[d67]', '[d167]', '[d267]', '[d1267]', '[d367]', '[d1367]', '[d2367]', '[d12367]', '[d467]', '[d1467]', '[d2467]', '[d12467]', '[d3467]', '[d13467]', '[d23467]', '[d123467]', + '[d567]', '[d1567]', '[d2567]', '[d12567]', '[d3567]', '[d13567]', '[d23567]', '[d123567]', '[d4567]', '[d14567]', '[d24567]', '[d124567]', '[d34567]', '[d134567]', '[d234567]', '[d1234567]', + '[d8]', '[d18]', '[d28]', '[d128]', '[d38]', '[d138]', '[d238]', '[d1238]', '[d48]', '[d148]', '[d248]', '[d1248]', '[d348]', '[d1348]', '[d2348]', '[d12348]', + '[d58]', '[d158]', '[d258]', '[d1258]', '[d358]', '[d1358]', '[d2358]', '[d12358]', '[d458]', '[d1458]', '[d2458]', '[d12458]', '[d3458]', '[d13458]', '[d23458]', '[d123458]', + '[d68]', '[d168]', '[d268]', '[d1268]', '[d368]', '[d1368]', '[d2368]', '[d12368]', '[d468]', '[d1468]', '[d2468]', '[d12468]', '[d3468]', '[d13468]', '[d23468]', '[d123468]', + '[d568]', '[d1568]', '[d2568]', '[d12568]', '[d3568]', '[d13568]', '[d23568]', '[d123568]', '[d4568]', '[d14568]', '[d24568]', '[d124568]', '[d34568]', '[d134568]', '[d234568]', '[d1234568]', + '[d78]', '[d178]', '[d278]', '[d1278]', '[d378]', '[d1378]', '[d2378]', '[d12378]', '[d478]', '[d1478]', '[d2478]', '[d12478]', '[d3478]', '[d13478]', '[d23478]', '[d123478]', + '[d578]', '[d1578]', '[d2578]', '[d12578]', '[d3578]', '[d13578]', '[d23578]', '[d123578]', '[d4578]', '[d14578]', '[d24578]', '[d124578]', '[d34578]', '[d134578]', '[d234578]', '[d1234578]', + '[d678]', '[d1678]', '[d2678]', '[d12678]', '[d3678]', '[d13678]', '[d23678]', '[d123678]', '[d4678]', '[d14678]', '[d24678]', '[d124678]', '[d34678]', '[d134678]', '[d234678]', '[d1234678]', + '[d5678]', '[d15678]', '[d25678]', '[d125678]', '[d35678]', '[d135678]', '[d235678]', '[d1235678]', '[d45678]', '[d145678]', '[d245678]', '[d1245678]', '[d345678]', '[d1345678]', '[d2345678]', '[d12345678]', + ], + 'xb1': [ + 'nyaess', 'nyaeng', 'nyaej', 'nyaec', 'nyaek', 'nyaet', 'nyaep', 'nyaeh', 'neo', 'neog', 'neogg', 'neogs', 'neon', 'neonj', 'neonh', 'neod', + 'neol', 'neolg', 'neolm', 'neolb', 'neols', 'neolt', 'neolp', 'neolh', 'neom', 'neob', 'neobs', 'neos', 'neoss', 'neong', 'neoj', 'neoc', + 'neok', 'neot', 'neop', 'neoh', 'ne', 'neg', 'negg', 'negs', 'nen', 'nenj', 'nenh', 'ned', 'nel', 'nelg', 'nelm', 'nelb', + 'nels', 'nelt', 'nelp', 'nelh', 'nem', 'neb', 'nebs', 'nes', 'ness', 'neng', 'nej', 'nec', 'nek', 'net', 'nep', 'neh', + 'nyeo', 'nyeog', 'nyeogg', 'nyeogs', 'nyeon', 'nyeonj', 'nyeonh', 'nyeod', 'nyeol', 'nyeolg', 'nyeolm', 'nyeolb', 'nyeols', 'nyeolt', 'nyeolp', 'nyeolh', + 'nyeom', 'nyeob', 'nyeobs', 'nyeos', 'nyeoss', 'nyeong', 'nyeoj', 'nyeoc', 'nyeok', 'nyeot', 'nyeop', 'nyeoh', 'nye', 'nyeg', 'nyegg', 'nyegs', + 'nyen', 'nyenj', 'nyenh', 'nyed', 'nyel', 'nyelg', 'nyelm', 'nyelb', 'nyels', 'nyelt', 'nyelp', 'nyelh', 'nyem', 'nyeb', 'nyebs', 'nyes', + 'nyess', 'nyeng', 'nyej', 'nyec', 'nyek', 'nyet', 'nyep', 'nyeh', 'no', 'nog', 'nogg', 'nogs', 'non', 'nonj', 'nonh', 'nod', + 'nol', 'nolg', 'nolm', 'nolb', 'nols', 'nolt', 'nolp', 'nolh', 'nom', 'nob', 'nobs', 'nos', 'noss', 'nong', 'noj', 'noc', + 'nok', 'not', 'nop', 'noh', 'nwa', 'nwag', 'nwagg', 'nwags', 'nwan', 'nwanj', 'nwanh', 'nwad', 'nwal', 'nwalg', 'nwalm', 'nwalb', + 'nwals', 'nwalt', 'nwalp', 'nwalh', 'nwam', 'nwab', 'nwabs', 'nwas', 'nwass', 'nwang', 'nwaj', 'nwac', 'nwak', 'nwat', 'nwap', 'nwah', + 'nwae', 'nwaeg', 'nwaegg', 'nwaegs', 'nwaen', 'nwaenj', 'nwaenh', 'nwaed', 'nwael', 'nwaelg', 'nwaelm', 'nwaelb', 'nwaels', 'nwaelt', 'nwaelp', 'nwaelh', + 'nwaem', 'nwaeb', 'nwaebs', 'nwaes', 'nwaess', 'nwaeng', 'nwaej', 'nwaec', 'nwaek', 'nwaet', 'nwaep', 'nwaeh', 'noe', 'noeg', 'noegg', 'noegs', + 'noen', 'noenj', 'noenh', 'noed', 'noel', 'noelg', 'noelm', 'noelb', 'noels', 'noelt', 'noelp', 'noelh', 'noem', 'noeb', 'noebs', 'noes', + 'noess', 'noeng', 'noej', 'noec', 'noek', 'noet', 'noep', 'noeh', 'nyo', 'nyog', 'nyogg', 'nyogs', 'nyon', 'nyonj', 'nyonh', 'nyod', + 'nyol', 'nyolg', 'nyolm', 'nyolb', 'nyols', 'nyolt', 'nyolp', 'nyolh', 'nyom', 'nyob', 'nyobs', 'nyos', 'nyoss', 'nyong', 'nyoj', 'nyoc', + ], + 'xfd': [ + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '[?]', '[?]', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '', '', '', '', '', '', '', '', '', '', '', '', '[?]', '[?]', '[?]', + ], + 'x14': [ + '[?]', 'e', 'aai', 'i', 'ii', 'o', 'oo', 'oo', 'ee', 'i', 'a', 'aa', 'we', 'we', 'wi', 'wi', + 'wii', 'wii', 'wo', 'wo', 'woo', 'woo', 'woo', 'wa', 'wa', 'waa', 'waa', 'waa', 'ai', 'w', '\'', 't', + 'k', 'sh', 's', 'n', 'w', 'n', '[?]', 'w', 'c', '?', 'l', 'en', 'in', 'on', 'an', 'pe', + 'paai', 'pi', 'pii', 'po', 'poo', 'poo', 'hee', 'hi', 'pa', 'paa', 'pwe', 'pwe', 'pwi', 'pwi', 'pwii', 'pwii', + 'pwo', 'pwo', 'pwoo', 'pwoo', 'pwa', 'pwa', 'pwaa', 'pwaa', 'pwaa', 'p', 'p', 'h', 'te', 'taai', 'ti', 'tii', + 'to', 'too', 'too', 'dee', 'di', 'ta', 'taa', 'twe', 'twe', 'twi', 'twi', 'twii', 'twii', 'two', 'two', 'twoo', + 'twoo', 'twa', 'twa', 'twaa', 'twaa', 'twaa', 't', 'tte', 'tti', 'tto', 'tta', 'ke', 'kaai', 'ki', 'kii', 'ko', + 'koo', 'koo', 'ka', 'kaa', 'kwe', 'kwe', 'kwi', 'kwi', 'kwii', 'kwii', 'kwo', 'kwo', 'kwoo', 'kwoo', 'kwa', 'kwa', + 'kwaa', 'kwaa', 'kwaa', 'k', 'kw', 'keh', 'kih', 'koh', 'kah', 'ce', 'caai', 'ci', 'cii', 'co', 'coo', 'coo', + 'ca', 'caa', 'cwe', 'cwe', 'cwi', 'cwi', 'cwii', 'cwii', 'cwo', 'cwo', 'cwoo', 'cwoo', 'cwa', 'cwa', 'cwaa', 'cwaa', + 'cwaa', 'c', 'th', 'me', 'maai', 'mi', 'mii', 'mo', 'moo', 'moo', 'ma', 'maa', 'mwe', 'mwe', 'mwi', 'mwi', + 'mwii', 'mwii', 'mwo', 'mwo', 'mwoo', 'mwoo', 'mwa', 'mwa', 'mwaa', 'mwaa', 'mwaa', 'm', 'm', 'mh', 'm', 'm', + 'ne', 'naai', 'ni', 'nii', 'no', 'noo', 'noo', 'na', 'naa', 'nwe', 'nwe', 'nwa', 'nwa', 'nwaa', 'nwaa', 'nwaa', + 'n', 'ng', 'nh', 'le', 'laai', 'li', 'lii', 'lo', 'loo', 'loo', 'la', 'laa', 'lwe', 'lwe', 'lwi', 'lwi', + 'lwii', 'lwii', 'lwo', 'lwo', 'lwoo', 'lwoo', 'lwa', 'lwa', 'lwaa', 'lwaa', 'l', 'l', 'l', 'se', 'saai', 'si', + 'sii', 'so', 'soo', 'soo', 'sa', 'saa', 'swe', 'swe', 'swi', 'swi', 'swii', 'swii', 'swo', 'swo', 'swoo', 'swoo', + ], + 'x00': [ + '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f', + '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f', + ' ', '!', '"', '#', '\\$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', + '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ']', '\\', ']', '^', '_', + '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '\\{', '|', '\\}', '~', '\x7f', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + ' ', '!', 'C/', 'PS', '\\$?', 'Y=', '|', 'SS', '"', '(c)', 'a', '<<', '!', '', '(r)', '-', + 'deg', '+-', '2', '3', '\'', 'u', 'P', '*', ',', '1', 'o', '>>', '1/4', '1/2', '3/4', '?', + 'A', 'A', 'A', 'A', 'A', 'A', 'AE', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I', + 'D', 'N', 'O', 'O', 'O', 'O', 'O', 'x', 'O', 'U', 'U', 'U', 'U', 'U', 'Th', 'ss', + 'a', 'a', 'a', 'a', 'a', 'a', 'ae', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', + 'd', 'n', 'o', 'o', 'o', 'o', 'o', '/', 'o', 'u', 'u', 'u', 'u', 'y', 'th', 'y', + ], + 'xfe': [ + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '', '', '', '~', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '..', '--', '-', '_', '_', '(', ') ', '\\{', '\\} ', '[', '] ', '[(', ')] ', '<<', '>> ', '<', + '> ', '[', '] ', '\\{', '\\}', '[?]', '[?]', '[?]', '[?]', '', '', '', '', '', '', '', + ',', ',', '.', '', ';', ':', '?', '!', '-', '(', ')', '\\{', '\\}', '\\{', '\\}', '#', + '&', '*', '+', '-', '<', '>', '=', '', '\\', '\\$', '%', '@', '[?]', '[?]', '[?]', '[?]', + '', '', '', '[?]', '', '[?]', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '[?]', '[?]', '', + ], + 'xad': [ + 'gwan', 'gwanj', 'gwanh', 'gwad', 'gwal', 'gwalg', 'gwalm', 'gwalb', 'gwals', 'gwalt', 'gwalp', 'gwalh', 'gwam', 'gwab', 'gwabs', 'gwas', + 'gwass', 'gwang', 'gwaj', 'gwac', 'gwak', 'gwat', 'gwap', 'gwah', 'gwae', 'gwaeg', 'gwaegg', 'gwaegs', 'gwaen', 'gwaenj', 'gwaenh', 'gwaed', + 'gwael', 'gwaelg', 'gwaelm', 'gwaelb', 'gwaels', 'gwaelt', 'gwaelp', 'gwaelh', 'gwaem', 'gwaeb', 'gwaebs', 'gwaes', 'gwaess', 'gwaeng', 'gwaej', 'gwaec', + 'gwaek', 'gwaet', 'gwaep', 'gwaeh', 'goe', 'goeg', 'goegg', 'goegs', 'goen', 'goenj', 'goenh', 'goed', 'goel', 'goelg', 'goelm', 'goelb', + 'goels', 'goelt', 'goelp', 'goelh', 'goem', 'goeb', 'goebs', 'goes', 'goess', 'goeng', 'goej', 'goec', 'goek', 'goet', 'goep', 'goeh', + 'gyo', 'gyog', 'gyogg', 'gyogs', 'gyon', 'gyonj', 'gyonh', 'gyod', 'gyol', 'gyolg', 'gyolm', 'gyolb', 'gyols', 'gyolt', 'gyolp', 'gyolh', + 'gyom', 'gyob', 'gyobs', 'gyos', 'gyoss', 'gyong', 'gyoj', 'gyoc', 'gyok', 'gyot', 'gyop', 'gyoh', 'gu', 'gug', 'gugg', 'gugs', + 'gun', 'gunj', 'gunh', 'gud', 'gul', 'gulg', 'gulm', 'gulb', 'guls', 'gult', 'gulp', 'gulh', 'gum', 'gub', 'gubs', 'gus', + 'guss', 'gung', 'guj', 'guc', 'guk', 'gut', 'gup', 'guh', 'gweo', 'gweog', 'gweogg', 'gweogs', 'gweon', 'gweonj', 'gweonh', 'gweod', + 'gweol', 'gweolg', 'gweolm', 'gweolb', 'gweols', 'gweolt', 'gweolp', 'gweolh', 'gweom', 'gweob', 'gweobs', 'gweos', 'gweoss', 'gweong', 'gweoj', 'gweoc', + 'gweok', 'gweot', 'gweop', 'gweoh', 'gwe', 'gweg', 'gwegg', 'gwegs', 'gwen', 'gwenj', 'gwenh', 'gwed', 'gwel', 'gwelg', 'gwelm', 'gwelb', + 'gwels', 'gwelt', 'gwelp', 'gwelh', 'gwem', 'gweb', 'gwebs', 'gwes', 'gwess', 'gweng', 'gwej', 'gwec', 'gwek', 'gwet', 'gwep', 'gweh', + 'gwi', 'gwig', 'gwigg', 'gwigs', 'gwin', 'gwinj', 'gwinh', 'gwid', 'gwil', 'gwilg', 'gwilm', 'gwilb', 'gwils', 'gwilt', 'gwilp', 'gwilh', + 'gwim', 'gwib', 'gwibs', 'gwis', 'gwiss', 'gwing', 'gwij', 'gwic', 'gwik', 'gwit', 'gwip', 'gwih', 'gyu', 'gyug', 'gyugg', 'gyugs', + 'gyun', 'gyunj', 'gyunh', 'gyud', 'gyul', 'gyulg', 'gyulm', 'gyulb', 'gyuls', 'gyult', 'gyulp', 'gyulh', 'gyum', 'gyub', 'gyubs', 'gyus', + 'gyuss', 'gyung', 'gyuj', 'gyuc', 'gyuk', 'gyut', 'gyup', 'gyuh', 'geu', 'geug', 'geugg', 'geugs', 'geun', 'geunj', 'geunh', 'geud', + ], + 'x05': [ + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', 'A', 'B', 'G', 'D', 'E', 'Z', 'E', 'E', 'T`', 'Zh', 'I', 'L', 'Kh', 'Ts', 'K', + 'H', 'Dz', 'Gh', 'Ch', 'M', 'Y', 'N', 'Sh', 'O', 'Ch`', 'P', 'J', 'Rh', 'S', 'V', 'T', + 'R', 'Ts`', 'W', 'P`', 'K`', 'O', 'F', '[?]', '[?]', '<', '\'', '/', '!', ',', '?', '.', + '[?]', 'a', 'b', 'g', 'd', 'e', 'z', 'e', 'e', 't`', 'zh', 'i', 'l', 'kh', 'ts', 'k', + 'h', 'dz', 'gh', 'ch', 'm', 'y', 'n', 'sh', 'o', 'ch`', 'p', 'j', 'rh', 's', 'v', 't', + 'r', 'ts`', 'w', 'p`', 'k`', 'o', 'f', 'ew', '[?]', '.', '-', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '[?]', '', '', '', '', '', '', '', '', '', '', '', '', '', + '@', 'e', 'a', 'o', 'i', 'e', 'e', 'a', 'a', 'o', '[?]', 'u', '\'', '', '', '', + '', '', '', ':', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '', 'b', 'g', 'd', 'h', 'v', 'z', 'kh', 't', 'y', 'k', 'k', 'l', 'm', 'm', 'n', + 'n', 's', '`', 'p', 'p', 'ts', 'ts', 'q', 'r', 'sh', 't', '[?]', '[?]', '[?]', '[?]', '[?]', + 'V', 'oy', 'i', '\'', '"', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + ], + 'xce': [ + 'cwik', 'cwit', 'cwip', 'cwih', 'cyu', 'cyug', 'cyugg', 'cyugs', 'cyun', 'cyunj', 'cyunh', 'cyud', 'cyul', 'cyulg', 'cyulm', 'cyulb', + 'cyuls', 'cyult', 'cyulp', 'cyulh', 'cyum', 'cyub', 'cyubs', 'cyus', 'cyuss', 'cyung', 'cyuj', 'cyuc', 'cyuk', 'cyut', 'cyup', 'cyuh', + 'ceu', 'ceug', 'ceugg', 'ceugs', 'ceun', 'ceunj', 'ceunh', 'ceud', 'ceul', 'ceulg', 'ceulm', 'ceulb', 'ceuls', 'ceult', 'ceulp', 'ceulh', + 'ceum', 'ceub', 'ceubs', 'ceus', 'ceuss', 'ceung', 'ceuj', 'ceuc', 'ceuk', 'ceut', 'ceup', 'ceuh', 'cyi', 'cyig', 'cyigg', 'cyigs', + 'cyin', 'cyinj', 'cyinh', 'cyid', 'cyil', 'cyilg', 'cyilm', 'cyilb', 'cyils', 'cyilt', 'cyilp', 'cyilh', 'cyim', 'cyib', 'cyibs', 'cyis', + 'cyiss', 'cying', 'cyij', 'cyic', 'cyik', 'cyit', 'cyip', 'cyih', 'ci', 'cig', 'cigg', 'cigs', 'cin', 'cinj', 'cinh', 'cid', + 'cil', 'cilg', 'cilm', 'cilb', 'cils', 'cilt', 'cilp', 'cilh', 'cim', 'cib', 'cibs', 'cis', 'ciss', 'cing', 'cij', 'cic', + 'cik', 'cit', 'cip', 'cih', 'ka', 'kag', 'kagg', 'kags', 'kan', 'kanj', 'kanh', 'kad', 'kal', 'kalg', 'kalm', 'kalb', + 'kals', 'kalt', 'kalp', 'kalh', 'kam', 'kab', 'kabs', 'kas', 'kass', 'kang', 'kaj', 'kac', 'kak', 'kat', 'kap', 'kah', + 'kae', 'kaeg', 'kaegg', 'kaegs', 'kaen', 'kaenj', 'kaenh', 'kaed', 'kael', 'kaelg', 'kaelm', 'kaelb', 'kaels', 'kaelt', 'kaelp', 'kaelh', + 'kaem', 'kaeb', 'kaebs', 'kaes', 'kaess', 'kaeng', 'kaej', 'kaec', 'kaek', 'kaet', 'kaep', 'kaeh', 'kya', 'kyag', 'kyagg', 'kyags', + 'kyan', 'kyanj', 'kyanh', 'kyad', 'kyal', 'kyalg', 'kyalm', 'kyalb', 'kyals', 'kyalt', 'kyalp', 'kyalh', 'kyam', 'kyab', 'kyabs', 'kyas', + 'kyass', 'kyang', 'kyaj', 'kyac', 'kyak', 'kyat', 'kyap', 'kyah', 'kyae', 'kyaeg', 'kyaegg', 'kyaegs', 'kyaen', 'kyaenj', 'kyaenh', 'kyaed', + 'kyael', 'kyaelg', 'kyaelm', 'kyaelb', 'kyaels', 'kyaelt', 'kyaelp', 'kyaelh', 'kyaem', 'kyaeb', 'kyaebs', 'kyaes', 'kyaess', 'kyaeng', 'kyaej', 'kyaec', + 'kyaek', 'kyaet', 'kyaep', 'kyaeh', 'keo', 'keog', 'keogg', 'keogs', 'keon', 'keonj', 'keonh', 'keod', 'keol', 'keolg', 'keolm', 'keolb', + 'keols', 'keolt', 'keolp', 'keolh', 'keom', 'keob', 'keobs', 'keos', 'keoss', 'keong', 'keoj', 'keoc', 'keok', 'keot', 'keop', 'keoh', + ], + 'x2e': [ + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', + '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?]', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', + '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', + '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', + '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', + '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', + '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', + '[?] ', '[?] ', '[?] ', '[?] ', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + ], + 'xd7': [ + 'hwen', 'hwenj', 'hwenh', 'hwed', 'hwel', 'hwelg', 'hwelm', 'hwelb', 'hwels', 'hwelt', 'hwelp', 'hwelh', 'hwem', 'hweb', 'hwebs', 'hwes', + 'hwess', 'hweng', 'hwej', 'hwec', 'hwek', 'hwet', 'hwep', 'hweh', 'hwi', 'hwig', 'hwigg', 'hwigs', 'hwin', 'hwinj', 'hwinh', 'hwid', + 'hwil', 'hwilg', 'hwilm', 'hwilb', 'hwils', 'hwilt', 'hwilp', 'hwilh', 'hwim', 'hwib', 'hwibs', 'hwis', 'hwiss', 'hwing', 'hwij', 'hwic', + 'hwik', 'hwit', 'hwip', 'hwih', 'hyu', 'hyug', 'hyugg', 'hyugs', 'hyun', 'hyunj', 'hyunh', 'hyud', 'hyul', 'hyulg', 'hyulm', 'hyulb', + 'hyuls', 'hyult', 'hyulp', 'hyulh', 'hyum', 'hyub', 'hyubs', 'hyus', 'hyuss', 'hyung', 'hyuj', 'hyuc', 'hyuk', 'hyut', 'hyup', 'hyuh', + 'heu', 'heug', 'heugg', 'heugs', 'heun', 'heunj', 'heunh', 'heud', 'heul', 'heulg', 'heulm', 'heulb', 'heuls', 'heult', 'heulp', 'heulh', + 'heum', 'heub', 'heubs', 'heus', 'heuss', 'heung', 'heuj', 'heuc', 'heuk', 'heut', 'heup', 'heuh', 'hyi', 'hyig', 'hyigg', 'hyigs', + 'hyin', 'hyinj', 'hyinh', 'hyid', 'hyil', 'hyilg', 'hyilm', 'hyilb', 'hyils', 'hyilt', 'hyilp', 'hyilh', 'hyim', 'hyib', 'hyibs', 'hyis', + 'hyiss', 'hying', 'hyij', 'hyic', 'hyik', 'hyit', 'hyip', 'hyih', 'hi', 'hig', 'higg', 'higs', 'hin', 'hinj', 'hinh', 'hid', + 'hil', 'hilg', 'hilm', 'hilb', 'hils', 'hilt', 'hilp', 'hilh', 'him', 'hib', 'hibs', 'his', 'hiss', 'hing', 'hij', 'hic', + 'hik', 'hit', 'hip', 'hih', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + ], + 'x21': [ + '', '', '', '', '', '', '', '', '', '', 'g', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', ' 1/3 ', ' 2/3 ', ' 1/5 ', ' 2/5 ', ' 3/5 ', ' 4/5 ', ' 1/6 ', ' 5/6 ', ' 1/8 ', ' 3/8 ', ' 5/8 ', ' 7/8 ', ' 1/', + 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X', 'XI', 'XII', 'L', 'C', 'D', 'M', + 'i', 'ii', 'iii', 'iv', 'v', 'vi', 'vii', 'viii', 'ix', 'x', 'xi', 'xii', 'l', 'c', 'd', 'm', + '(D', 'D)', '((|))', ')', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '-', '|', '-', '|', '-', '|', '\\', '/', '\\', '/', '-', '-', '~', '~', '-', '|', + '-', '|', '-', '-', '-', '|', '-', '|', '|', '-', '-', '-', '-', '-', '-', '|', + '|', '|', '|', '|', '|', '|', '^', 'V', '\\', '=', 'V', '^', '-', '-', '|', '|', + '-', '-', '|', '|', '=', '|', '=', '=', '|', '=', '|', '=', '=', '=', '=', '=', + '=', '|', '=', '|', '=', '|', '\\', '/', '\\', '/', '=', '=', '~', '~', '|', '|', + '-', '|', '-', '|', '-', '-', '-', '|', '-', '|', '|', '|', '|', '|', '|', '|', + '-', '\\', '\\', '|', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + ], + 'xb0': [ + 'ggwem', 'ggweb', 'ggwebs', 'ggwes', 'ggwess', 'ggweng', 'ggwej', 'ggwec', 'ggwek', 'ggwet', 'ggwep', 'ggweh', 'ggwi', 'ggwig', 'ggwigg', 'ggwigs', + 'ggwin', 'ggwinj', 'ggwinh', 'ggwid', 'ggwil', 'ggwilg', 'ggwilm', 'ggwilb', 'ggwils', 'ggwilt', 'ggwilp', 'ggwilh', 'ggwim', 'ggwib', 'ggwibs', 'ggwis', + 'ggwiss', 'ggwing', 'ggwij', 'ggwic', 'ggwik', 'ggwit', 'ggwip', 'ggwih', 'ggyu', 'ggyug', 'ggyugg', 'ggyugs', 'ggyun', 'ggyunj', 'ggyunh', 'ggyud', + 'ggyul', 'ggyulg', 'ggyulm', 'ggyulb', 'ggyuls', 'ggyult', 'ggyulp', 'ggyulh', 'ggyum', 'ggyub', 'ggyubs', 'ggyus', 'ggyuss', 'ggyung', 'ggyuj', 'ggyuc', + 'ggyuk', 'ggyut', 'ggyup', 'ggyuh', 'ggeu', 'ggeug', 'ggeugg', 'ggeugs', 'ggeun', 'ggeunj', 'ggeunh', 'ggeud', 'ggeul', 'ggeulg', 'ggeulm', 'ggeulb', + 'ggeuls', 'ggeult', 'ggeulp', 'ggeulh', 'ggeum', 'ggeub', 'ggeubs', 'ggeus', 'ggeuss', 'ggeung', 'ggeuj', 'ggeuc', 'ggeuk', 'ggeut', 'ggeup', 'ggeuh', + 'ggyi', 'ggyig', 'ggyigg', 'ggyigs', 'ggyin', 'ggyinj', 'ggyinh', 'ggyid', 'ggyil', 'ggyilg', 'ggyilm', 'ggyilb', 'ggyils', 'ggyilt', 'ggyilp', 'ggyilh', + 'ggyim', 'ggyib', 'ggyibs', 'ggyis', 'ggyiss', 'ggying', 'ggyij', 'ggyic', 'ggyik', 'ggyit', 'ggyip', 'ggyih', 'ggi', 'ggig', 'ggigg', 'ggigs', + 'ggin', 'gginj', 'gginh', 'ggid', 'ggil', 'ggilg', 'ggilm', 'ggilb', 'ggils', 'ggilt', 'ggilp', 'ggilh', 'ggim', 'ggib', 'ggibs', 'ggis', + 'ggiss', 'gging', 'ggij', 'ggic', 'ggik', 'ggit', 'ggip', 'ggih', 'na', 'nag', 'nagg', 'nags', 'nan', 'nanj', 'nanh', 'nad', + 'nal', 'nalg', 'nalm', 'nalb', 'nals', 'nalt', 'nalp', 'nalh', 'nam', 'nab', 'nabs', 'nas', 'nass', 'nang', 'naj', 'nac', + 'nak', 'nat', 'nap', 'nah', 'nae', 'naeg', 'naegg', 'naegs', 'naen', 'naenj', 'naenh', 'naed', 'nael', 'naelg', 'naelm', 'naelb', + 'naels', 'naelt', 'naelp', 'naelh', 'naem', 'naeb', 'naebs', 'naes', 'naess', 'naeng', 'naej', 'naec', 'naek', 'naet', 'naep', 'naeh', + 'nya', 'nyag', 'nyagg', 'nyags', 'nyan', 'nyanj', 'nyanh', 'nyad', 'nyal', 'nyalg', 'nyalm', 'nyalb', 'nyals', 'nyalt', 'nyalp', 'nyalh', + 'nyam', 'nyab', 'nyabs', 'nyas', 'nyass', 'nyang', 'nyaj', 'nyac', 'nyak', 'nyat', 'nyap', 'nyah', 'nyae', 'nyaeg', 'nyaegg', 'nyaegs', + 'nyaen', 'nyaenj', 'nyaenh', 'nyaed', 'nyael', 'nyaelg', 'nyaelm', 'nyaelb', 'nyaels', 'nyaelt', 'nyaelp', 'nyaelh', 'nyaem', 'nyaeb', 'nyaebs', 'nyaes', + ], + 'xa3': [ + 'nzup', 'nzurx', 'nzur', 'nzyt', 'nzyx', 'nzy', 'nzyp', 'nzyrx', 'nzyr', 'sit', 'six', 'si', 'sip', 'siex', 'sie', 'siep', + 'sat', 'sax', 'sa', 'sap', 'suox', 'suo', 'suop', 'sot', 'sox', 'so', 'sop', 'sex', 'se', 'sep', 'sut', 'sux', + 'su', 'sup', 'surx', 'sur', 'syt', 'syx', 'sy', 'syp', 'syrx', 'syr', 'ssit', 'ssix', 'ssi', 'ssip', 'ssiex', 'ssie', + 'ssiep', 'ssat', 'ssax', 'ssa', 'ssap', 'ssot', 'ssox', 'sso', 'ssop', 'ssex', 'sse', 'ssep', 'ssut', 'ssux', 'ssu', 'ssup', + 'ssyt', 'ssyx', 'ssy', 'ssyp', 'ssyrx', 'ssyr', 'zhat', 'zhax', 'zha', 'zhap', 'zhuox', 'zhuo', 'zhuop', 'zhot', 'zhox', 'zho', + 'zhop', 'zhet', 'zhex', 'zhe', 'zhep', 'zhut', 'zhux', 'zhu', 'zhup', 'zhurx', 'zhur', 'zhyt', 'zhyx', 'zhy', 'zhyp', 'zhyrx', + 'zhyr', 'chat', 'chax', 'cha', 'chap', 'chuot', 'chuox', 'chuo', 'chuop', 'chot', 'chox', 'cho', 'chop', 'chet', 'chex', 'che', + 'chep', 'chux', 'chu', 'chup', 'churx', 'chur', 'chyt', 'chyx', 'chy', 'chyp', 'chyrx', 'chyr', 'rrax', 'rra', 'rruox', 'rruo', + 'rrot', 'rrox', 'rro', 'rrop', 'rret', 'rrex', 'rre', 'rrep', 'rrut', 'rrux', 'rru', 'rrup', 'rrurx', 'rrur', 'rryt', 'rryx', + 'rry', 'rryp', 'rryrx', 'rryr', 'nrat', 'nrax', 'nra', 'nrap', 'nrox', 'nro', 'nrop', 'nret', 'nrex', 'nre', 'nrep', 'nrut', + 'nrux', 'nru', 'nrup', 'nrurx', 'nrur', 'nryt', 'nryx', 'nry', 'nryp', 'nryrx', 'nryr', 'shat', 'shax', 'sha', 'shap', 'shuox', + 'shuo', 'shuop', 'shot', 'shox', 'sho', 'shop', 'shet', 'shex', 'she', 'shep', 'shut', 'shux', 'shu', 'shup', 'shurx', 'shur', + 'shyt', 'shyx', 'shy', 'shyp', 'shyrx', 'shyr', 'rat', 'rax', 'ra', 'rap', 'ruox', 'ruo', 'ruop', 'rot', 'rox', 'ro', + 'rop', 'rex', 're', 'rep', 'rut', 'rux', 'ru', 'rup', 'rurx', 'rur', 'ryt', 'ryx', 'ry', 'ryp', 'ryrx', 'ryr', + 'jit', 'jix', 'ji', 'jip', 'jiet', 'jiex', 'jie', 'jiep', 'juot', 'juox', 'juo', 'juop', 'jot', 'jox', 'jo', 'jop', + 'jut', 'jux', 'ju', 'jup', 'jurx', 'jur', 'jyt', 'jyx', 'jy', 'jyp', 'jyrx', 'jyr', 'qit', 'qix', 'qi', 'qip', + ], + 'xbb': [ + 'moen', 'moenj', 'moenh', 'moed', 'moel', 'moelg', 'moelm', 'moelb', 'moels', 'moelt', 'moelp', 'moelh', 'moem', 'moeb', 'moebs', 'moes', + 'moess', 'moeng', 'moej', 'moec', 'moek', 'moet', 'moep', 'moeh', 'myo', 'myog', 'myogg', 'myogs', 'myon', 'myonj', 'myonh', 'myod', + 'myol', 'myolg', 'myolm', 'myolb', 'myols', 'myolt', 'myolp', 'myolh', 'myom', 'myob', 'myobs', 'myos', 'myoss', 'myong', 'myoj', 'myoc', + 'myok', 'myot', 'myop', 'myoh', 'mu', 'mug', 'mugg', 'mugs', 'mun', 'munj', 'munh', 'mud', 'mul', 'mulg', 'mulm', 'mulb', + 'muls', 'mult', 'mulp', 'mulh', 'mum', 'mub', 'mubs', 'mus', 'muss', 'mung', 'muj', 'muc', 'muk', 'mut', 'mup', 'muh', + 'mweo', 'mweog', 'mweogg', 'mweogs', 'mweon', 'mweonj', 'mweonh', 'mweod', 'mweol', 'mweolg', 'mweolm', 'mweolb', 'mweols', 'mweolt', 'mweolp', 'mweolh', + 'mweom', 'mweob', 'mweobs', 'mweos', 'mweoss', 'mweong', 'mweoj', 'mweoc', 'mweok', 'mweot', 'mweop', 'mweoh', 'mwe', 'mweg', 'mwegg', 'mwegs', + 'mwen', 'mwenj', 'mwenh', 'mwed', 'mwel', 'mwelg', 'mwelm', 'mwelb', 'mwels', 'mwelt', 'mwelp', 'mwelh', 'mwem', 'mweb', 'mwebs', 'mwes', + 'mwess', 'mweng', 'mwej', 'mwec', 'mwek', 'mwet', 'mwep', 'mweh', 'mwi', 'mwig', 'mwigg', 'mwigs', 'mwin', 'mwinj', 'mwinh', 'mwid', + 'mwil', 'mwilg', 'mwilm', 'mwilb', 'mwils', 'mwilt', 'mwilp', 'mwilh', 'mwim', 'mwib', 'mwibs', 'mwis', 'mwiss', 'mwing', 'mwij', 'mwic', + 'mwik', 'mwit', 'mwip', 'mwih', 'myu', 'myug', 'myugg', 'myugs', 'myun', 'myunj', 'myunh', 'myud', 'myul', 'myulg', 'myulm', 'myulb', + 'myuls', 'myult', 'myulp', 'myulh', 'myum', 'myub', 'myubs', 'myus', 'myuss', 'myung', 'myuj', 'myuc', 'myuk', 'myut', 'myup', 'myuh', + 'meu', 'meug', 'meugg', 'meugs', 'meun', 'meunj', 'meunh', 'meud', 'meul', 'meulg', 'meulm', 'meulb', 'meuls', 'meult', 'meulp', 'meulh', + 'meum', 'meub', 'meubs', 'meus', 'meuss', 'meung', 'meuj', 'meuc', 'meuk', 'meut', 'meup', 'meuh', 'myi', 'myig', 'myigg', 'myigs', + 'myin', 'myinj', 'myinh', 'myid', 'myil', 'myilg', 'myilm', 'myilb', 'myils', 'myilt', 'myilp', 'myilh', 'myim', 'myib', 'myibs', 'myis', + 'myiss', 'mying', 'myij', 'myic', 'myik', 'myit', 'myip', 'myih', 'mi', 'mig', 'migg', 'migs', 'min', 'minj', 'minh', 'mid', + ], + 'x02': [ + 'A', 'a', 'A', 'a', 'E', 'e', 'E', 'e', 'I', 'i', 'I', 'i', 'O', 'o', 'O', 'o', + 'R', 'r', 'R', 'r', 'U', 'u', 'U', 'u', 'S', 's', 'T', 't', 'Y', 'y', 'H', 'h', + '[?]', '[?]', 'OU', 'ou', 'Z', 'z', 'A', 'a', 'E', 'e', 'O', 'o', 'O', 'o', 'O', 'o', + 'O', 'o', 'Y', 'y', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + 'a', 'a', 'a', 'b', 'o', 'c', 'd', 'd', 'e', '@', '@', 'e', 'e', 'e', 'e', 'j', + 'g', 'g', 'g', 'g', 'u', 'Y', 'h', 'h', 'i', 'i', 'I', 'l', 'l', 'l', 'lZ', 'W', + 'W', 'm', 'n', 'n', 'n', 'o', 'OE', 'O', 'F', 'R', 'R', 'R', 'R', 'r', 'r', 'R', + 'R', 'R', 's', 'S', 'j', 'S', 'S', 't', 't', 'U', 'U', 'v', '^', 'W', 'Y', 'Y', + 'z', 'z', 'Z', 'Z', '?', '?', '?', 'C', '@', 'B', 'E', 'G', 'H', 'j', 'k', 'L', + 'q', '?', '?', 'dz', 'dZ', 'dz', 'ts', 'tS', 'tC', 'fN', 'ls', 'lz', 'WW', ']]', '[?]', '[?]', + 'k', 'h', 'j', 'r', 'r', 'r', 'r', 'w', 'y', '\'', '"', '`', '\'', '`', '`', '\'', + '?', '?', '<', '>', '^', 'V', '^', 'V', '\'', '-', '/', '\\', ',', '_', '\\', '/', + ':', '.', '`', '\'', '^', 'V', '+', '-', 'V', '.', '@', ',', '~', '"', 'R', 'X', + 'G', 'l', 's', 'x', '?', '', '', '', '', '', '', '', 'V', '=', '"', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + ], + 'xb5': [ + 'dyil', 'dyilg', 'dyilm', 'dyilb', 'dyils', 'dyilt', 'dyilp', 'dyilh', 'dyim', 'dyib', 'dyibs', 'dyis', 'dyiss', 'dying', 'dyij', 'dyic', + 'dyik', 'dyit', 'dyip', 'dyih', 'di', 'dig', 'digg', 'digs', 'din', 'dinj', 'dinh', 'did', 'dil', 'dilg', 'dilm', 'dilb', + 'dils', 'dilt', 'dilp', 'dilh', 'dim', 'dib', 'dibs', 'dis', 'diss', 'ding', 'dij', 'dic', 'dik', 'dit', 'dip', 'dih', + 'dda', 'ddag', 'ddagg', 'ddags', 'ddan', 'ddanj', 'ddanh', 'ddad', 'ddal', 'ddalg', 'ddalm', 'ddalb', 'ddals', 'ddalt', 'ddalp', 'ddalh', + 'ddam', 'ddab', 'ddabs', 'ddas', 'ddass', 'ddang', 'ddaj', 'ddac', 'ddak', 'ddat', 'ddap', 'ddah', 'ddae', 'ddaeg', 'ddaegg', 'ddaegs', + 'ddaen', 'ddaenj', 'ddaenh', 'ddaed', 'ddael', 'ddaelg', 'ddaelm', 'ddaelb', 'ddaels', 'ddaelt', 'ddaelp', 'ddaelh', 'ddaem', 'ddaeb', 'ddaebs', 'ddaes', + 'ddaess', 'ddaeng', 'ddaej', 'ddaec', 'ddaek', 'ddaet', 'ddaep', 'ddaeh', 'ddya', 'ddyag', 'ddyagg', 'ddyags', 'ddyan', 'ddyanj', 'ddyanh', 'ddyad', + 'ddyal', 'ddyalg', 'ddyalm', 'ddyalb', 'ddyals', 'ddyalt', 'ddyalp', 'ddyalh', 'ddyam', 'ddyab', 'ddyabs', 'ddyas', 'ddyass', 'ddyang', 'ddyaj', 'ddyac', + 'ddyak', 'ddyat', 'ddyap', 'ddyah', 'ddyae', 'ddyaeg', 'ddyaegg', 'ddyaegs', 'ddyaen', 'ddyaenj', 'ddyaenh', 'ddyaed', 'ddyael', 'ddyaelg', 'ddyaelm', 'ddyaelb', + 'ddyaels', 'ddyaelt', 'ddyaelp', 'ddyaelh', 'ddyaem', 'ddyaeb', 'ddyaebs', 'ddyaes', 'ddyaess', 'ddyaeng', 'ddyaej', 'ddyaec', 'ddyaek', 'ddyaet', 'ddyaep', 'ddyaeh', + 'ddeo', 'ddeog', 'ddeogg', 'ddeogs', 'ddeon', 'ddeonj', 'ddeonh', 'ddeod', 'ddeol', 'ddeolg', 'ddeolm', 'ddeolb', 'ddeols', 'ddeolt', 'ddeolp', 'ddeolh', + 'ddeom', 'ddeob', 'ddeobs', 'ddeos', 'ddeoss', 'ddeong', 'ddeoj', 'ddeoc', 'ddeok', 'ddeot', 'ddeop', 'ddeoh', 'dde', 'ddeg', 'ddegg', 'ddegs', + 'dden', 'ddenj', 'ddenh', 'dded', 'ddel', 'ddelg', 'ddelm', 'ddelb', 'ddels', 'ddelt', 'ddelp', 'ddelh', 'ddem', 'ddeb', 'ddebs', 'ddes', + 'ddess', 'ddeng', 'ddej', 'ddec', 'ddek', 'ddet', 'ddep', 'ddeh', 'ddyeo', 'ddyeog', 'ddyeogg', 'ddyeogs', 'ddyeon', 'ddyeonj', 'ddyeonh', 'ddyeod', + 'ddyeol', 'ddyeolg', 'ddyeolm', 'ddyeolb', 'ddyeols', 'ddyeolt', 'ddyeolp', 'ddyeolh', 'ddyeom', 'ddyeob', 'ddyeobs', 'ddyeos', 'ddyeoss', 'ddyeong', 'ddyeoj', 'ddyeoc', + 'ddyeok', 'ddyeot', 'ddyeop', 'ddyeoh', 'ddye', 'ddyeg', 'ddyegg', 'ddyegs', 'ddyen', 'ddyenj', 'ddyenh', 'ddyed', 'ddyel', 'ddyelg', 'ddyelm', 'ddyelb', + ], + 'x17': [ + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', 'jh', 'ny', 't', 'tth', 'd', 'ddh', 'nn', 't', + 'th', 'd', 'dh', 'n', 'p', 'ph', 'b', 'bh', 'm', 'y', 'r', 'l', 'v', 'sh', 'ss', 's', + 'h', 'l', 'q', 'a', 'aa', 'i', 'ii', 'u', 'uk', 'uu', 'uuv', 'ry', 'ryy', 'ly', 'lyy', 'e', + 'ai', 'oo', 'oo', 'au', 'a', 'aa', 'aa', 'i', 'ii', 'y', 'yy', 'u', 'uu', 'ua', 'oe', 'ya', + 'ie', 'e', 'ae', 'ai', 'oo', 'au', 'M', 'H', 'a`', '', '', '', 'r', '', '!', '', + '', '', '', '', '.', ' // ', ':', '+', '++', ' * ', ' /// ', 'KR', '\'', '[?]', '[?]', '[?]', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + ], + 'x0b': [ + '[?]', 'N', 'N', 'H', '[?]', 'a', 'aa', 'i', 'ii', 'u', 'uu', 'R', 'L', '[?]', '[?]', 'e', + 'ai', '[?]', '[?]', 'o', 'au', 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', 'jh', 'ny', 'tt', + 'tth', 'dd', 'ddh', 'nn', 't', 'th', 'd', 'dh', 'n', '[?]', 'p', 'ph', 'b', 'bh', 'm', 'y', + 'r', '[?]', 'l', 'll', '[?]', '', 'sh', 'ss', 's', 'h', '[?]', '[?]', '\'', '\'', 'aa', 'i', + 'ii', 'u', 'uu', 'R', '[?]', '[?]', '[?]', 'e', 'ai', '[?]', '[?]', 'o', 'au', '', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '+', '+', '[?]', '[?]', '[?]', '[?]', 'rr', 'rh', '[?]', 'yy', + 'RR', 'LL', '[?]', '[?]', '[?]', '[?]', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', 'N', 'H', '[?]', 'a', 'aa', 'i', 'ii', 'u', 'uu', '[?]', '[?]', '[?]', 'e', 'ee', + 'ai', '[?]', 'o', 'oo', 'au', 'k', '[?]', '[?]', '[?]', 'ng', 'c', '[?]', 'j', '[?]', 'ny', 'tt', + '[?]', '[?]', '[?]', 'nn', 't', '[?]', '[?]', '[?]', 'n', 'nnn', 'p', '[?]', '[?]', '[?]', 'm', 'y', + 'r', 'rr', 'l', 'll', 'lll', 'v', '[?]', 'ss', 's', 'h', '[?]', '[?]', '[?]', '[?]', 'aa', 'i', + 'ii', 'u', 'uu', '[?]', '[?]', '[?]', 'e', 'ee', 'ai', '[?]', 'o', 'oo', 'au', '', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '+', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '+10+', '+100+', '+1000+', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + ], + 'x0f': [ + 'AUM', '', '', '', '', '', '', '', ' // ', ' * ', '', '-', ' / ', ' / ', ' // ', ' -/ ', + ' +/ ', ' X/ ', ' /XX/ ', ' /X/ ', ', ', '', '', '', '', '', '', '', '', '', '', '', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.5', '1.5', '2.5', '3.5', '4.5', '5.5', + '6.5', '7.5', '8.5', '-.5', '+', '*', '^', '_', '', '~', '[?]', ']', '[[', ']]', '', '', + 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', '[?]', 'ny', 'tt', 'tth', 'dd', 'ddh', 'nn', 't', + 'th', 'd', 'dh', 'n', 'p', 'ph', 'b', 'bh', 'm', 'ts', 'tsh', 'dz', 'dzh', 'w', 'zh', 'z', + '\'', 'y', 'r', 'l', 'sh', 'ssh', 's', 'h', 'a', 'kss', 'r', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', 'aa', 'i', 'ii', 'u', 'uu', 'R', 'RR', 'L', 'LL', 'e', 'ee', 'o', 'oo', 'M', 'H', + 'i', 'ii', '', '', '', '', '', '', '', '', '', '', '[?]', '[?]', '[?]', '[?]', + 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', '[?]', 'ny', 'tt', 'tth', 'dd', 'ddh', 'nn', 't', + 'th', 'd', 'dh', 'n', 'p', 'ph', 'b', 'bh', 'm', 'ts', 'tsh', 'dz', 'dzh', 'w', 'zh', 'z', + '\'', 'y', 'r', 'l', 'sh', 'ss', 's', 'h', 'a', 'kss', 'w', 'y', 'r', '[?]', 'X', ' :X: ', + ' /O/ ', ' /o/ ', ' \\o\\ ', ' (O) ', '', '', '', '', '', '', '', '', '', '[?]', '[?]', '', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + ], + 'xc4': [ + 'sswals', 'sswalt', 'sswalp', 'sswalh', 'sswam', 'sswab', 'sswabs', 'sswas', 'sswass', 'sswang', 'sswaj', 'sswac', 'sswak', 'sswat', 'sswap', 'sswah', + 'sswae', 'sswaeg', 'sswaegg', 'sswaegs', 'sswaen', 'sswaenj', 'sswaenh', 'sswaed', 'sswael', 'sswaelg', 'sswaelm', 'sswaelb', 'sswaels', 'sswaelt', 'sswaelp', 'sswaelh', + 'sswaem', 'sswaeb', 'sswaebs', 'sswaes', 'sswaess', 'sswaeng', 'sswaej', 'sswaec', 'sswaek', 'sswaet', 'sswaep', 'sswaeh', 'ssoe', 'ssoeg', 'ssoegg', 'ssoegs', + 'ssoen', 'ssoenj', 'ssoenh', 'ssoed', 'ssoel', 'ssoelg', 'ssoelm', 'ssoelb', 'ssoels', 'ssoelt', 'ssoelp', 'ssoelh', 'ssoem', 'ssoeb', 'ssoebs', 'ssoes', + 'ssoess', 'ssoeng', 'ssoej', 'ssoec', 'ssoek', 'ssoet', 'ssoep', 'ssoeh', 'ssyo', 'ssyog', 'ssyogg', 'ssyogs', 'ssyon', 'ssyonj', 'ssyonh', 'ssyod', + 'ssyol', 'ssyolg', 'ssyolm', 'ssyolb', 'ssyols', 'ssyolt', 'ssyolp', 'ssyolh', 'ssyom', 'ssyob', 'ssyobs', 'ssyos', 'ssyoss', 'ssyong', 'ssyoj', 'ssyoc', + 'ssyok', 'ssyot', 'ssyop', 'ssyoh', 'ssu', 'ssug', 'ssugg', 'ssugs', 'ssun', 'ssunj', 'ssunh', 'ssud', 'ssul', 'ssulg', 'ssulm', 'ssulb', + 'ssuls', 'ssult', 'ssulp', 'ssulh', 'ssum', 'ssub', 'ssubs', 'ssus', 'ssuss', 'ssung', 'ssuj', 'ssuc', 'ssuk', 'ssut', 'ssup', 'ssuh', + 'ssweo', 'ssweog', 'ssweogg', 'ssweogs', 'ssweon', 'ssweonj', 'ssweonh', 'ssweod', 'ssweol', 'ssweolg', 'ssweolm', 'ssweolb', 'ssweols', 'ssweolt', 'ssweolp', 'ssweolh', + 'ssweom', 'ssweob', 'ssweobs', 'ssweos', 'ssweoss', 'ssweong', 'ssweoj', 'ssweoc', 'ssweok', 'ssweot', 'ssweop', 'ssweoh', 'sswe', 'ssweg', 'sswegg', 'sswegs', + 'sswen', 'sswenj', 'sswenh', 'sswed', 'sswel', 'sswelg', 'sswelm', 'sswelb', 'sswels', 'sswelt', 'sswelp', 'sswelh', 'sswem', 'ssweb', 'sswebs', 'sswes', + 'sswess', 'ssweng', 'sswej', 'sswec', 'sswek', 'sswet', 'sswep', 'ssweh', 'sswi', 'sswig', 'sswigg', 'sswigs', 'sswin', 'sswinj', 'sswinh', 'sswid', + 'sswil', 'sswilg', 'sswilm', 'sswilb', 'sswils', 'sswilt', 'sswilp', 'sswilh', 'sswim', 'sswib', 'sswibs', 'sswis', 'sswiss', 'sswing', 'sswij', 'sswic', + 'sswik', 'sswit', 'sswip', 'sswih', 'ssyu', 'ssyug', 'ssyugg', 'ssyugs', 'ssyun', 'ssyunj', 'ssyunh', 'ssyud', 'ssyul', 'ssyulg', 'ssyulm', 'ssyulb', + 'ssyuls', 'ssyult', 'ssyulp', 'ssyulh', 'ssyum', 'ssyub', 'ssyubs', 'ssyus', 'ssyuss', 'ssyung', 'ssyuj', 'ssyuc', 'ssyuk', 'ssyut', 'ssyup', 'ssyuh', + 'sseu', 'sseug', 'sseugg', 'sseugs', 'sseun', 'sseunj', 'sseunh', 'sseud', 'sseul', 'sseulg', 'sseulm', 'sseulb', 'sseuls', 'sseult', 'sseulp', 'sseulh', + ], + 'xd0': [ + 'kweon', 'kweonj', 'kweonh', 'kweod', 'kweol', 'kweolg', 'kweolm', 'kweolb', 'kweols', 'kweolt', 'kweolp', 'kweolh', 'kweom', 'kweob', 'kweobs', 'kweos', + 'kweoss', 'kweong', 'kweoj', 'kweoc', 'kweok', 'kweot', 'kweop', 'kweoh', 'kwe', 'kweg', 'kwegg', 'kwegs', 'kwen', 'kwenj', 'kwenh', 'kwed', + 'kwel', 'kwelg', 'kwelm', 'kwelb', 'kwels', 'kwelt', 'kwelp', 'kwelh', 'kwem', 'kweb', 'kwebs', 'kwes', 'kwess', 'kweng', 'kwej', 'kwec', + 'kwek', 'kwet', 'kwep', 'kweh', 'kwi', 'kwig', 'kwigg', 'kwigs', 'kwin', 'kwinj', 'kwinh', 'kwid', 'kwil', 'kwilg', 'kwilm', 'kwilb', + 'kwils', 'kwilt', 'kwilp', 'kwilh', 'kwim', 'kwib', 'kwibs', 'kwis', 'kwiss', 'kwing', 'kwij', 'kwic', 'kwik', 'kwit', 'kwip', 'kwih', + 'kyu', 'kyug', 'kyugg', 'kyugs', 'kyun', 'kyunj', 'kyunh', 'kyud', 'kyul', 'kyulg', 'kyulm', 'kyulb', 'kyuls', 'kyult', 'kyulp', 'kyulh', + 'kyum', 'kyub', 'kyubs', 'kyus', 'kyuss', 'kyung', 'kyuj', 'kyuc', 'kyuk', 'kyut', 'kyup', 'kyuh', 'keu', 'keug', 'keugg', 'keugs', + 'keun', 'keunj', 'keunh', 'keud', 'keul', 'keulg', 'keulm', 'keulb', 'keuls', 'keult', 'keulp', 'keulh', 'keum', 'keub', 'keubs', 'keus', + 'keuss', 'keung', 'keuj', 'keuc', 'keuk', 'keut', 'keup', 'keuh', 'kyi', 'kyig', 'kyigg', 'kyigs', 'kyin', 'kyinj', 'kyinh', 'kyid', + 'kyil', 'kyilg', 'kyilm', 'kyilb', 'kyils', 'kyilt', 'kyilp', 'kyilh', 'kyim', 'kyib', 'kyibs', 'kyis', 'kyiss', 'kying', 'kyij', 'kyic', + 'kyik', 'kyit', 'kyip', 'kyih', 'ki', 'kig', 'kigg', 'kigs', 'kin', 'kinj', 'kinh', 'kid', 'kil', 'kilg', 'kilm', 'kilb', + 'kils', 'kilt', 'kilp', 'kilh', 'kim', 'kib', 'kibs', 'kis', 'kiss', 'king', 'kij', 'kic', 'kik', 'kit', 'kip', 'kih', + 'ta', 'tag', 'tagg', 'tags', 'tan', 'tanj', 'tanh', 'tad', 'tal', 'talg', 'talm', 'talb', 'tals', 'talt', 'talp', 'talh', + 'tam', 'tab', 'tabs', 'tas', 'tass', 'tang', 'taj', 'tac', 'tak', 'tat', 'tap', 'tah', 'tae', 'taeg', 'taegg', 'taegs', + 'taen', 'taenj', 'taenh', 'taed', 'tael', 'taelg', 'taelm', 'taelb', 'taels', 'taelt', 'taelp', 'taelh', 'taem', 'taeb', 'taebs', 'taes', + 'taess', 'taeng', 'taej', 'taec', 'taek', 'taet', 'taep', 'taeh', 'tya', 'tyag', 'tyagg', 'tyags', 'tyan', 'tyanj', 'tyanh', 'tyad', + ], + 'xb9': [ + 'ruk', 'rut', 'rup', 'ruh', 'rweo', 'rweog', 'rweogg', 'rweogs', 'rweon', 'rweonj', 'rweonh', 'rweod', 'rweol', 'rweolg', 'rweolm', 'rweolb', + 'rweols', 'rweolt', 'rweolp', 'rweolh', 'rweom', 'rweob', 'rweobs', 'rweos', 'rweoss', 'rweong', 'rweoj', 'rweoc', 'rweok', 'rweot', 'rweop', 'rweoh', + 'rwe', 'rweg', 'rwegg', 'rwegs', 'rwen', 'rwenj', 'rwenh', 'rwed', 'rwel', 'rwelg', 'rwelm', 'rwelb', 'rwels', 'rwelt', 'rwelp', 'rwelh', + 'rwem', 'rweb', 'rwebs', 'rwes', 'rwess', 'rweng', 'rwej', 'rwec', 'rwek', 'rwet', 'rwep', 'rweh', 'rwi', 'rwig', 'rwigg', 'rwigs', + 'rwin', 'rwinj', 'rwinh', 'rwid', 'rwil', 'rwilg', 'rwilm', 'rwilb', 'rwils', 'rwilt', 'rwilp', 'rwilh', 'rwim', 'rwib', 'rwibs', 'rwis', + 'rwiss', 'rwing', 'rwij', 'rwic', 'rwik', 'rwit', 'rwip', 'rwih', 'ryu', 'ryug', 'ryugg', 'ryugs', 'ryun', 'ryunj', 'ryunh', 'ryud', + 'ryul', 'ryulg', 'ryulm', 'ryulb', 'ryuls', 'ryult', 'ryulp', 'ryulh', 'ryum', 'ryub', 'ryubs', 'ryus', 'ryuss', 'ryung', 'ryuj', 'ryuc', + 'ryuk', 'ryut', 'ryup', 'ryuh', 'reu', 'reug', 'reugg', 'reugs', 'reun', 'reunj', 'reunh', 'reud', 'reul', 'reulg', 'reulm', 'reulb', + 'reuls', 'reult', 'reulp', 'reulh', 'reum', 'reub', 'reubs', 'reus', 'reuss', 'reung', 'reuj', 'reuc', 'reuk', 'reut', 'reup', 'reuh', + 'ryi', 'ryig', 'ryigg', 'ryigs', 'ryin', 'ryinj', 'ryinh', 'ryid', 'ryil', 'ryilg', 'ryilm', 'ryilb', 'ryils', 'ryilt', 'ryilp', 'ryilh', + 'ryim', 'ryib', 'ryibs', 'ryis', 'ryiss', 'rying', 'ryij', 'ryic', 'ryik', 'ryit', 'ryip', 'ryih', 'ri', 'rig', 'rigg', 'rigs', + 'rin', 'rinj', 'rinh', 'rid', 'ril', 'rilg', 'rilm', 'rilb', 'rils', 'rilt', 'rilp', 'rilh', 'rim', 'rib', 'ribs', 'ris', + 'riss', 'ring', 'rij', 'ric', 'rik', 'rit', 'rip', 'rih', 'ma', 'mag', 'magg', 'mags', 'man', 'manj', 'manh', 'mad', + 'mal', 'malg', 'malm', 'malb', 'mals', 'malt', 'malp', 'malh', 'mam', 'mab', 'mabs', 'mas', 'mass', 'mang', 'maj', 'mac', + 'mak', 'mat', 'map', 'mah', 'mae', 'maeg', 'maegg', 'maegs', 'maen', 'maenj', 'maenh', 'maed', 'mael', 'maelg', 'maelm', 'maelb', + 'maels', 'maelt', 'maelp', 'maelh', 'maem', 'maeb', 'maebs', 'maes', 'maess', 'maeng', 'maej', 'maec', 'maek', 'maet', 'maep', 'maeh', + ], + 'xff': [ + '[?]', '!', '"', '#', '\\$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', + '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', + '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '\\{', '|', '\\}', '~', '[?]', + '[?]', '.', '[', ']', ',', '*', 'wo', 'a', 'i', 'u', 'e', 'o', 'ya', 'yu', 'yo', 'tu', + '+', 'a', 'i', 'u', 'e', 'o', 'ka', 'ki', 'ku', 'ke', 'ko', 'sa', 'si', 'su', 'se', 'so', + 'ta', 'ti', 'tu', 'te', 'to', 'na', 'ni', 'nu', 'ne', 'no', 'ha', 'hi', 'hu', 'he', 'ho', 'ma', + 'mi', 'mu', 'me', 'mo', 'ya', 'yu', 'yo', 'ra', 'ri', 'ru', 're', 'ro', 'wa', 'n', ':', ';', + '', 'g', 'gg', 'gs', 'n', 'nj', 'nh', 'd', 'dd', 'r', 'lg', 'lm', 'lb', 'ls', 'lt', 'lp', + 'rh', 'm', 'b', 'bb', 'bs', 's', 'ss', '', 'j', 'jj', 'c', 'k', 't', 'p', 'h', '[?]', + '[?]', '[?]', 'a', 'ae', 'ya', 'yae', 'eo', 'e', '[?]', '[?]', 'yeo', 'ye', 'o', 'wa', 'wae', 'oe', + '[?]', '[?]', 'yo', 'u', 'weo', 'we', 'wi', 'yu', '[?]', '[?]', 'eu', 'yi', 'i', '[?]', '[?]', '[?]', + '/C', 'PS', '!', '-', '|', 'Y=', 'W=', '[?]', '|', '-', '|', '-', '|', '#', 'O', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '\\{', '|', '\\}', '', '', '', '', + ], + 'xc3': [ + 'ssal', 'ssalg', 'ssalm', 'ssalb', 'ssals', 'ssalt', 'ssalp', 'ssalh', 'ssam', 'ssab', 'ssabs', 'ssas', 'ssass', 'ssang', 'ssaj', 'ssac', + 'ssak', 'ssat', 'ssap', 'ssah', 'ssae', 'ssaeg', 'ssaegg', 'ssaegs', 'ssaen', 'ssaenj', 'ssaenh', 'ssaed', 'ssael', 'ssaelg', 'ssaelm', 'ssaelb', + 'ssaels', 'ssaelt', 'ssaelp', 'ssaelh', 'ssaem', 'ssaeb', 'ssaebs', 'ssaes', 'ssaess', 'ssaeng', 'ssaej', 'ssaec', 'ssaek', 'ssaet', 'ssaep', 'ssaeh', + 'ssya', 'ssyag', 'ssyagg', 'ssyags', 'ssyan', 'ssyanj', 'ssyanh', 'ssyad', 'ssyal', 'ssyalg', 'ssyalm', 'ssyalb', 'ssyals', 'ssyalt', 'ssyalp', 'ssyalh', + 'ssyam', 'ssyab', 'ssyabs', 'ssyas', 'ssyass', 'ssyang', 'ssyaj', 'ssyac', 'ssyak', 'ssyat', 'ssyap', 'ssyah', 'ssyae', 'ssyaeg', 'ssyaegg', 'ssyaegs', + 'ssyaen', 'ssyaenj', 'ssyaenh', 'ssyaed', 'ssyael', 'ssyaelg', 'ssyaelm', 'ssyaelb', 'ssyaels', 'ssyaelt', 'ssyaelp', 'ssyaelh', 'ssyaem', 'ssyaeb', 'ssyaebs', 'ssyaes', + 'ssyaess', 'ssyaeng', 'ssyaej', 'ssyaec', 'ssyaek', 'ssyaet', 'ssyaep', 'ssyaeh', 'sseo', 'sseog', 'sseogg', 'sseogs', 'sseon', 'sseonj', 'sseonh', 'sseod', + 'sseol', 'sseolg', 'sseolm', 'sseolb', 'sseols', 'sseolt', 'sseolp', 'sseolh', 'sseom', 'sseob', 'sseobs', 'sseos', 'sseoss', 'sseong', 'sseoj', 'sseoc', + 'sseok', 'sseot', 'sseop', 'sseoh', 'sse', 'sseg', 'ssegg', 'ssegs', 'ssen', 'ssenj', 'ssenh', 'ssed', 'ssel', 'sselg', 'sselm', 'sselb', + 'ssels', 'sselt', 'sselp', 'sselh', 'ssem', 'sseb', 'ssebs', 'sses', 'ssess', 'sseng', 'ssej', 'ssec', 'ssek', 'sset', 'ssep', 'sseh', + 'ssyeo', 'ssyeog', 'ssyeogg', 'ssyeogs', 'ssyeon', 'ssyeonj', 'ssyeonh', 'ssyeod', 'ssyeol', 'ssyeolg', 'ssyeolm', 'ssyeolb', 'ssyeols', 'ssyeolt', 'ssyeolp', 'ssyeolh', + 'ssyeom', 'ssyeob', 'ssyeobs', 'ssyeos', 'ssyeoss', 'ssyeong', 'ssyeoj', 'ssyeoc', 'ssyeok', 'ssyeot', 'ssyeop', 'ssyeoh', 'ssye', 'ssyeg', 'ssyegg', 'ssyegs', + 'ssyen', 'ssyenj', 'ssyenh', 'ssyed', 'ssyel', 'ssyelg', 'ssyelm', 'ssyelb', 'ssyels', 'ssyelt', 'ssyelp', 'ssyelh', 'ssyem', 'ssyeb', 'ssyebs', 'ssyes', + 'ssyess', 'ssyeng', 'ssyej', 'ssyec', 'ssyek', 'ssyet', 'ssyep', 'ssyeh', 'sso', 'ssog', 'ssogg', 'ssogs', 'sson', 'ssonj', 'ssonh', 'ssod', + 'ssol', 'ssolg', 'ssolm', 'ssolb', 'ssols', 'ssolt', 'ssolp', 'ssolh', 'ssom', 'ssob', 'ssobs', 'ssos', 'ssoss', 'ssong', 'ssoj', 'ssoc', + 'ssok', 'ssot', 'ssop', 'ssoh', 'sswa', 'sswag', 'sswagg', 'sswags', 'sswan', 'sswanj', 'sswanh', 'sswad', 'sswal', 'sswalg', 'sswalm', 'sswalb', + ], + 'x09': [ + '[?]', 'N', 'N', 'H', '[?]', 'a', 'aa', 'i', 'ii', 'u', 'uu', 'R', 'L', 'eN', 'e', 'e', + 'ai', 'oN', 'o', 'o', 'au', 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', 'jh', 'ny', 'tt', + 'tth', 'dd', 'ddh', 'nn', 't', 'th', 'd', 'dh', 'n', 'nnn', 'p', 'ph', 'b', 'bh', 'm', 'y', + 'r', 'rr', 'l', 'l', 'lll', 'v', 'sh', 'ss', 's', 'h', '[?]', '[?]', '\'', '\'', 'aa', 'i', + 'ii', 'u', 'uu', 'R', 'RR', 'eN', 'e', 'e', 'ai', 'oN', 'o', 'o', 'au', '', '[?]', '[?]', + 'AUM', '\'', '\'', '`', '\'', '[?]', '[?]', '[?]', 'q', 'khh', 'ghh', 'z', 'dddh', 'rh', 'f', 'yy', + 'RR', 'LL', 'L', 'LL', ' / ', ' // ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '.', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', 'N', 'N', 'H', '[?]', 'a', 'aa', 'i', 'ii', 'u', 'uu', 'R', 'RR', '[?]', '[?]', 'e', + 'ai', '[?]', '[?]', 'o', 'au', 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', 'jh', 'ny', 'tt', + 'tth', 'dd', 'ddh', 'nn', 't', 'th', 'd', 'dh', 'n', '[?]', 'p', 'ph', 'b', 'bh', 'm', 'y', + 'r', '[?]', 'l', '[?]', '[?]', '[?]', 'sh', 'ss', 's', 'h', '[?]', '[?]', '\'', '[?]', 'aa', 'i', + 'ii', 'u', 'uu', 'R', 'RR', '[?]', '[?]', 'e', 'ai', '[?]', '[?]', 'o', 'au', '', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '+', '[?]', '[?]', '[?]', '[?]', 'rr', 'rh', '[?]', 'yy', + 'RR', 'LL', 'L', 'LL', '[?]', '[?]', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'r\'', 'r`', 'Rs', 'Rs', '1/', '2/', '3/', '4/', ' 1 - 1/', '/16', '', '[?]', '[?]', '[?]', '[?]', + ], + 'xb2': [ + 'nyok', 'nyot', 'nyop', 'nyoh', 'nu', 'nug', 'nugg', 'nugs', 'nun', 'nunj', 'nunh', 'nud', 'nul', 'nulg', 'nulm', 'nulb', + 'nuls', 'nult', 'nulp', 'nulh', 'num', 'nub', 'nubs', 'nus', 'nuss', 'nung', 'nuj', 'nuc', 'nuk', 'nut', 'nup', 'nuh', + 'nweo', 'nweog', 'nweogg', 'nweogs', 'nweon', 'nweonj', 'nweonh', 'nweod', 'nweol', 'nweolg', 'nweolm', 'nweolb', 'nweols', 'nweolt', 'nweolp', 'nweolh', + 'nweom', 'nweob', 'nweobs', 'nweos', 'nweoss', 'nweong', 'nweoj', 'nweoc', 'nweok', 'nweot', 'nweop', 'nweoh', 'nwe', 'nweg', 'nwegg', 'nwegs', + 'nwen', 'nwenj', 'nwenh', 'nwed', 'nwel', 'nwelg', 'nwelm', 'nwelb', 'nwels', 'nwelt', 'nwelp', 'nwelh', 'nwem', 'nweb', 'nwebs', 'nwes', + 'nwess', 'nweng', 'nwej', 'nwec', 'nwek', 'nwet', 'nwep', 'nweh', 'nwi', 'nwig', 'nwigg', 'nwigs', 'nwin', 'nwinj', 'nwinh', 'nwid', + 'nwil', 'nwilg', 'nwilm', 'nwilb', 'nwils', 'nwilt', 'nwilp', 'nwilh', 'nwim', 'nwib', 'nwibs', 'nwis', 'nwiss', 'nwing', 'nwij', 'nwic', + 'nwik', 'nwit', 'nwip', 'nwih', 'nyu', 'nyug', 'nyugg', 'nyugs', 'nyun', 'nyunj', 'nyunh', 'nyud', 'nyul', 'nyulg', 'nyulm', 'nyulb', + 'nyuls', 'nyult', 'nyulp', 'nyulh', 'nyum', 'nyub', 'nyubs', 'nyus', 'nyuss', 'nyung', 'nyuj', 'nyuc', 'nyuk', 'nyut', 'nyup', 'nyuh', + 'neu', 'neug', 'neugg', 'neugs', 'neun', 'neunj', 'neunh', 'neud', 'neul', 'neulg', 'neulm', 'neulb', 'neuls', 'neult', 'neulp', 'neulh', + 'neum', 'neub', 'neubs', 'neus', 'neuss', 'neung', 'neuj', 'neuc', 'neuk', 'neut', 'neup', 'neuh', 'nyi', 'nyig', 'nyigg', 'nyigs', + 'nyin', 'nyinj', 'nyinh', 'nyid', 'nyil', 'nyilg', 'nyilm', 'nyilb', 'nyils', 'nyilt', 'nyilp', 'nyilh', 'nyim', 'nyib', 'nyibs', 'nyis', + 'nyiss', 'nying', 'nyij', 'nyic', 'nyik', 'nyit', 'nyip', 'nyih', 'ni', 'nig', 'nigg', 'nigs', 'nin', 'ninj', 'ninh', 'nid', + 'nil', 'nilg', 'nilm', 'nilb', 'nils', 'nilt', 'nilp', 'nilh', 'nim', 'nib', 'nibs', 'nis', 'niss', 'ning', 'nij', 'nic', + 'nik', 'nit', 'nip', 'nih', 'da', 'dag', 'dagg', 'dags', 'dan', 'danj', 'danh', 'dad', 'dal', 'dalg', 'dalm', 'dalb', + 'dals', 'dalt', 'dalp', 'dalh', 'dam', 'dab', 'dabs', 'das', 'dass', 'dang', 'daj', 'dac', 'dak', 'dat', 'dap', 'dah', + ], + 'x0a': [ + '[?]', '[?]', 'N', '[?]', '[?]', 'a', 'aa', 'i', 'ii', 'u', 'uu', '[?]', '[?]', '[?]', '[?]', 'ee', + 'ai', '[?]', '[?]', 'oo', 'au', 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', 'jh', 'ny', 'tt', + 'tth', 'dd', 'ddh', 'nn', 't', 'th', 'd', 'dh', 'n', '[?]', 'p', 'ph', 'b', 'bb', 'm', 'y', + 'r', '[?]', 'l', 'll', '[?]', 'v', 'sh', '[?]', 's', 'h', '[?]', '[?]', '\'', '[?]', 'aa', 'i', + 'ii', 'u', 'uu', '[?]', '[?]', '[?]', '[?]', 'ee', 'ai', '[?]', '[?]', 'oo', 'au', '', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', 'khh', 'ghh', 'z', 'rr', '[?]', 'f', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'N', 'H', '', '', 'G.E.O.', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', 'N', 'N', 'H', '[?]', 'a', 'aa', 'i', 'ii', 'u', 'uu', 'R', '[?]', 'eN', '[?]', 'e', + 'ai', 'oN', '[?]', 'o', 'au', 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', 'jh', 'ny', 'tt', + 'tth', 'dd', 'ddh', 'nn', 't', 'th', 'd', 'dh', 'n', '[?]', 'p', 'ph', 'b', 'bh', 'm', 'ya', + 'r', '[?]', 'l', 'll', '[?]', 'v', 'sh', 'ss', 's', 'h', '[?]', '[?]', '\'', '\'', 'aa', 'i', + 'ii', 'u', 'uu', 'R', 'RR', 'eN', '[?]', 'e', 'ai', 'oN', '[?]', 'o', 'au', '', '[?]', '[?]', + 'AUM', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + 'RR', '[?]', '[?]', '[?]', '[?]', '[?]', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + ], + 'x0d': [ + '[?]', '[?]', 'N', 'H', '[?]', 'a', 'aa', 'i', 'ii', 'u', 'uu', 'R', 'L', '[?]', 'e', 'ee', + 'ai', '[?]', 'o', 'oo', 'au', 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', 'jh', 'ny', 'tt', + 'tth', 'dd', 'ddh', 'nn', 't', 'th', 'd', 'dh', 'n', '[?]', 'p', 'ph', 'b', 'bh', 'm', 'y', + 'r', 'rr', 'l', 'll', 'lll', 'v', 'sh', 'ss', 's', 'h', '[?]', '[?]', '[?]', '[?]', 'aa', 'i', + 'ii', 'u', 'uu', 'R', '[?]', '[?]', 'e', 'ee', 'ai', '', 'o', 'oo', 'au', '', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '+', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + 'RR', 'LL', '[?]', '[?]', '[?]', '[?]', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', 'N', 'H', '[?]', 'a', 'aa', 'ae', 'aae', 'i', 'ii', 'u', 'uu', 'R', 'RR', 'L', + 'LL', 'e', 'ee', 'ai', 'o', 'oo', 'au', '[?]', '[?]', '[?]', 'k', 'kh', 'g', 'gh', 'ng', 'nng', + 'c', 'ch', 'j', 'jh', 'ny', 'jny', 'nyj', 'tt', 'tth', 'dd', 'ddh', 'nn', 'nndd', 't', 'th', 'd', + 'dh', 'n', '[?]', 'nd', 'p', 'ph', 'b', 'bh', 'm', 'mb', 'y', 'r', '[?]', 'l', '[?]', '[?]', + 'v', 'sh', 'ss', 's', 'h', 'll', 'f', '[?]', '[?]', '[?]', '', '[?]', '[?]', '[?]', '[?]', 'aa', + 'ae', 'aae', 'i', 'ii', 'u', '[?]', 'uu', '[?]', 'R', 'e', 'ee', 'ai', 'o', 'oo', 'au', 'L', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', 'RR', 'LL', ' . ', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + ], + 'xc1': [ + 'syae', 'syaeg', 'syaegg', 'syaegs', 'syaen', 'syaenj', 'syaenh', 'syaed', 'syael', 'syaelg', 'syaelm', 'syaelb', 'syaels', 'syaelt', 'syaelp', 'syaelh', + 'syaem', 'syaeb', 'syaebs', 'syaes', 'syaess', 'syaeng', 'syaej', 'syaec', 'syaek', 'syaet', 'syaep', 'syaeh', 'seo', 'seog', 'seogg', 'seogs', + 'seon', 'seonj', 'seonh', 'seod', 'seol', 'seolg', 'seolm', 'seolb', 'seols', 'seolt', 'seolp', 'seolh', 'seom', 'seob', 'seobs', 'seos', + 'seoss', 'seong', 'seoj', 'seoc', 'seok', 'seot', 'seop', 'seoh', 'se', 'seg', 'segg', 'segs', 'sen', 'senj', 'senh', 'sed', + 'sel', 'selg', 'selm', 'selb', 'sels', 'selt', 'selp', 'selh', 'sem', 'seb', 'sebs', 'ses', 'sess', 'seng', 'sej', 'sec', + 'sek', 'set', 'sep', 'seh', 'syeo', 'syeog', 'syeogg', 'syeogs', 'syeon', 'syeonj', 'syeonh', 'syeod', 'syeol', 'syeolg', 'syeolm', 'syeolb', + 'syeols', 'syeolt', 'syeolp', 'syeolh', 'syeom', 'syeob', 'syeobs', 'syeos', 'syeoss', 'syeong', 'syeoj', 'syeoc', 'syeok', 'syeot', 'syeop', 'syeoh', + 'sye', 'syeg', 'syegg', 'syegs', 'syen', 'syenj', 'syenh', 'syed', 'syel', 'syelg', 'syelm', 'syelb', 'syels', 'syelt', 'syelp', 'syelh', + 'syem', 'syeb', 'syebs', 'syes', 'syess', 'syeng', 'syej', 'syec', 'syek', 'syet', 'syep', 'syeh', 'so', 'sog', 'sogg', 'sogs', + 'son', 'sonj', 'sonh', 'sod', 'sol', 'solg', 'solm', 'solb', 'sols', 'solt', 'solp', 'solh', 'som', 'sob', 'sobs', 'sos', + 'soss', 'song', 'soj', 'soc', 'sok', 'sot', 'sop', 'soh', 'swa', 'swag', 'swagg', 'swags', 'swan', 'swanj', 'swanh', 'swad', + 'swal', 'swalg', 'swalm', 'swalb', 'swals', 'swalt', 'swalp', 'swalh', 'swam', 'swab', 'swabs', 'swas', 'swass', 'swang', 'swaj', 'swac', + 'swak', 'swat', 'swap', 'swah', 'swae', 'swaeg', 'swaegg', 'swaegs', 'swaen', 'swaenj', 'swaenh', 'swaed', 'swael', 'swaelg', 'swaelm', 'swaelb', + 'swaels', 'swaelt', 'swaelp', 'swaelh', 'swaem', 'swaeb', 'swaebs', 'swaes', 'swaess', 'swaeng', 'swaej', 'swaec', 'swaek', 'swaet', 'swaep', 'swaeh', + 'soe', 'soeg', 'soegg', 'soegs', 'soen', 'soenj', 'soenh', 'soed', 'soel', 'soelg', 'soelm', 'soelb', 'soels', 'soelt', 'soelp', 'soelh', + 'soem', 'soeb', 'soebs', 'soes', 'soess', 'soeng', 'soej', 'soec', 'soek', 'soet', 'soep', 'soeh', 'syo', 'syog', 'syogg', 'syogs', + ], + 'xba': [ + 'mya', 'myag', 'myagg', 'myags', 'myan', 'myanj', 'myanh', 'myad', 'myal', 'myalg', 'myalm', 'myalb', 'myals', 'myalt', 'myalp', 'myalh', + 'myam', 'myab', 'myabs', 'myas', 'myass', 'myang', 'myaj', 'myac', 'myak', 'myat', 'myap', 'myah', 'myae', 'myaeg', 'myaegg', 'myaegs', + 'myaen', 'myaenj', 'myaenh', 'myaed', 'myael', 'myaelg', 'myaelm', 'myaelb', 'myaels', 'myaelt', 'myaelp', 'myaelh', 'myaem', 'myaeb', 'myaebs', 'myaes', + 'myaess', 'myaeng', 'myaej', 'myaec', 'myaek', 'myaet', 'myaep', 'myaeh', 'meo', 'meog', 'meogg', 'meogs', 'meon', 'meonj', 'meonh', 'meod', + 'meol', 'meolg', 'meolm', 'meolb', 'meols', 'meolt', 'meolp', 'meolh', 'meom', 'meob', 'meobs', 'meos', 'meoss', 'meong', 'meoj', 'meoc', + 'meok', 'meot', 'meop', 'meoh', 'me', 'meg', 'megg', 'megs', 'men', 'menj', 'menh', 'med', 'mel', 'melg', 'melm', 'melb', + 'mels', 'melt', 'melp', 'melh', 'mem', 'meb', 'mebs', 'mes', 'mess', 'meng', 'mej', 'mec', 'mek', 'met', 'mep', 'meh', + 'myeo', 'myeog', 'myeogg', 'myeogs', 'myeon', 'myeonj', 'myeonh', 'myeod', 'myeol', 'myeolg', 'myeolm', 'myeolb', 'myeols', 'myeolt', 'myeolp', 'myeolh', + 'myeom', 'myeob', 'myeobs', 'myeos', 'myeoss', 'myeong', 'myeoj', 'myeoc', 'myeok', 'myeot', 'myeop', 'myeoh', 'mye', 'myeg', 'myegg', 'myegs', + 'myen', 'myenj', 'myenh', 'myed', 'myel', 'myelg', 'myelm', 'myelb', 'myels', 'myelt', 'myelp', 'myelh', 'myem', 'myeb', 'myebs', 'myes', + 'myess', 'myeng', 'myej', 'myec', 'myek', 'myet', 'myep', 'myeh', 'mo', 'mog', 'mogg', 'mogs', 'mon', 'monj', 'monh', 'mod', + 'mol', 'molg', 'molm', 'molb', 'mols', 'molt', 'molp', 'molh', 'mom', 'mob', 'mobs', 'mos', 'moss', 'mong', 'moj', 'moc', + 'mok', 'mot', 'mop', 'moh', 'mwa', 'mwag', 'mwagg', 'mwags', 'mwan', 'mwanj', 'mwanh', 'mwad', 'mwal', 'mwalg', 'mwalm', 'mwalb', + 'mwals', 'mwalt', 'mwalp', 'mwalh', 'mwam', 'mwab', 'mwabs', 'mwas', 'mwass', 'mwang', 'mwaj', 'mwac', 'mwak', 'mwat', 'mwap', 'mwah', + 'mwae', 'mwaeg', 'mwaegg', 'mwaegs', 'mwaen', 'mwaenj', 'mwaenh', 'mwaed', 'mwael', 'mwaelg', 'mwaelm', 'mwaelb', 'mwaels', 'mwaelt', 'mwaelp', 'mwaelh', + 'mwaem', 'mwaeb', 'mwaebs', 'mwaes', 'mwaess', 'mwaeng', 'mwaej', 'mwaec', 'mwaek', 'mwaet', 'mwaep', 'mwaeh', 'moe', 'moeg', 'moegg', 'moegs', + ], + 'xb3': [ + 'dae', 'daeg', 'daegg', 'daegs', 'daen', 'daenj', 'daenh', 'daed', 'dael', 'daelg', 'daelm', 'daelb', 'daels', 'daelt', 'daelp', 'daelh', + 'daem', 'daeb', 'daebs', 'daes', 'daess', 'daeng', 'daej', 'daec', 'daek', 'daet', 'daep', 'daeh', 'dya', 'dyag', 'dyagg', 'dyags', + 'dyan', 'dyanj', 'dyanh', 'dyad', 'dyal', 'dyalg', 'dyalm', 'dyalb', 'dyals', 'dyalt', 'dyalp', 'dyalh', 'dyam', 'dyab', 'dyabs', 'dyas', + 'dyass', 'dyang', 'dyaj', 'dyac', 'dyak', 'dyat', 'dyap', 'dyah', 'dyae', 'dyaeg', 'dyaegg', 'dyaegs', 'dyaen', 'dyaenj', 'dyaenh', 'dyaed', + 'dyael', 'dyaelg', 'dyaelm', 'dyaelb', 'dyaels', 'dyaelt', 'dyaelp', 'dyaelh', 'dyaem', 'dyaeb', 'dyaebs', 'dyaes', 'dyaess', 'dyaeng', 'dyaej', 'dyaec', + 'dyaek', 'dyaet', 'dyaep', 'dyaeh', 'deo', 'deog', 'deogg', 'deogs', 'deon', 'deonj', 'deonh', 'deod', 'deol', 'deolg', 'deolm', 'deolb', + 'deols', 'deolt', 'deolp', 'deolh', 'deom', 'deob', 'deobs', 'deos', 'deoss', 'deong', 'deoj', 'deoc', 'deok', 'deot', 'deop', 'deoh', + 'de', 'deg', 'degg', 'degs', 'den', 'denj', 'denh', 'ded', 'del', 'delg', 'delm', 'delb', 'dels', 'delt', 'delp', 'delh', + 'dem', 'deb', 'debs', 'des', 'dess', 'deng', 'dej', 'dec', 'dek', 'det', 'dep', 'deh', 'dyeo', 'dyeog', 'dyeogg', 'dyeogs', + 'dyeon', 'dyeonj', 'dyeonh', 'dyeod', 'dyeol', 'dyeolg', 'dyeolm', 'dyeolb', 'dyeols', 'dyeolt', 'dyeolp', 'dyeolh', 'dyeom', 'dyeob', 'dyeobs', 'dyeos', + 'dyeoss', 'dyeong', 'dyeoj', 'dyeoc', 'dyeok', 'dyeot', 'dyeop', 'dyeoh', 'dye', 'dyeg', 'dyegg', 'dyegs', 'dyen', 'dyenj', 'dyenh', 'dyed', + 'dyel', 'dyelg', 'dyelm', 'dyelb', 'dyels', 'dyelt', 'dyelp', 'dyelh', 'dyem', 'dyeb', 'dyebs', 'dyes', 'dyess', 'dyeng', 'dyej', 'dyec', + 'dyek', 'dyet', 'dyep', 'dyeh', 'do', 'dog', 'dogg', 'dogs', 'don', 'donj', 'donh', 'dod', 'dol', 'dolg', 'dolm', 'dolb', + 'dols', 'dolt', 'dolp', 'dolh', 'dom', 'dob', 'dobs', 'dos', 'doss', 'dong', 'doj', 'doc', 'dok', 'dot', 'dop', 'doh', + 'dwa', 'dwag', 'dwagg', 'dwags', 'dwan', 'dwanj', 'dwanh', 'dwad', 'dwal', 'dwalg', 'dwalm', 'dwalb', 'dwals', 'dwalt', 'dwalp', 'dwalh', + 'dwam', 'dwab', 'dwabs', 'dwas', 'dwass', 'dwang', 'dwaj', 'dwac', 'dwak', 'dwat', 'dwap', 'dwah', 'dwae', 'dwaeg', 'dwaegg', 'dwaegs', + ], + 'xa0': [ + 'it', 'ix', 'i', 'ip', 'iet', 'iex', 'ie', 'iep', 'at', 'ax', 'a', 'ap', 'uox', 'uo', 'uop', 'ot', + 'ox', 'o', 'op', 'ex', 'e', 'wu', 'bit', 'bix', 'bi', 'bip', 'biet', 'biex', 'bie', 'biep', 'bat', 'bax', + 'ba', 'bap', 'buox', 'buo', 'buop', 'bot', 'box', 'bo', 'bop', 'bex', 'be', 'bep', 'but', 'bux', 'bu', 'bup', + 'burx', 'bur', 'byt', 'byx', 'by', 'byp', 'byrx', 'byr', 'pit', 'pix', 'pi', 'pip', 'piex', 'pie', 'piep', 'pat', + 'pax', 'pa', 'pap', 'puox', 'puo', 'puop', 'pot', 'pox', 'po', 'pop', 'put', 'pux', 'pu', 'pup', 'purx', 'pur', + 'pyt', 'pyx', 'py', 'pyp', 'pyrx', 'pyr', 'bbit', 'bbix', 'bbi', 'bbip', 'bbiet', 'bbiex', 'bbie', 'bbiep', 'bbat', 'bbax', + 'bba', 'bbap', 'bbuox', 'bbuo', 'bbuop', 'bbot', 'bbox', 'bbo', 'bbop', 'bbex', 'bbe', 'bbep', 'bbut', 'bbux', 'bbu', 'bbup', + 'bburx', 'bbur', 'bbyt', 'bbyx', 'bby', 'bbyp', 'nbit', 'nbix', 'nbi', 'nbip', 'nbiex', 'nbie', 'nbiep', 'nbat', 'nbax', 'nba', + 'nbap', 'nbot', 'nbox', 'nbo', 'nbop', 'nbut', 'nbux', 'nbu', 'nbup', 'nburx', 'nbur', 'nbyt', 'nbyx', 'nby', 'nbyp', 'nbyrx', + 'nbyr', 'hmit', 'hmix', 'hmi', 'hmip', 'hmiex', 'hmie', 'hmiep', 'hmat', 'hmax', 'hma', 'hmap', 'hmuox', 'hmuo', 'hmuop', 'hmot', + 'hmox', 'hmo', 'hmop', 'hmut', 'hmux', 'hmu', 'hmup', 'hmurx', 'hmur', 'hmyx', 'hmy', 'hmyp', 'hmyrx', 'hmyr', 'mit', 'mix', + 'mi', 'mip', 'miex', 'mie', 'miep', 'mat', 'max', 'ma', 'map', 'muot', 'muox', 'muo', 'muop', 'mot', 'mox', 'mo', + 'mop', 'mex', 'me', 'mut', 'mux', 'mu', 'mup', 'murx', 'mur', 'myt', 'myx', 'my', 'myp', 'fit', 'fix', 'fi', + 'fip', 'fat', 'fax', 'fa', 'fap', 'fox', 'fo', 'fop', 'fut', 'fux', 'fu', 'fup', 'furx', 'fur', 'fyt', 'fyx', + 'fy', 'fyp', 'vit', 'vix', 'vi', 'vip', 'viet', 'viex', 'vie', 'viep', 'vat', 'vax', 'va', 'vap', 'vot', 'vox', + 'vo', 'vop', 'vex', 'vep', 'vut', 'vux', 'vu', 'vup', 'vurx', 'vur', 'vyt', 'vyx', 'vy', 'vyp', 'vyrx', 'vyr', + ], + 'x15': [ + 'swa', 'swa', 'swaa', 'swaa', 'swaa', 's', 's', 'sw', 's', 'sk', 'skw', 'sW', 'spwa', 'stwa', 'skwa', 'scwa', + 'she', 'shi', 'shii', 'sho', 'shoo', 'sha', 'shaa', 'shwe', 'shwe', 'shwi', 'shwi', 'shwii', 'shwii', 'shwo', 'shwo', 'shwoo', + 'shwoo', 'shwa', 'shwa', 'shwaa', 'shwaa', 'sh', 'ye', 'yaai', 'yi', 'yii', 'yo', 'yoo', 'yoo', 'ya', 'yaa', 'ywe', + 'ywe', 'ywi', 'ywi', 'ywii', 'ywii', 'ywo', 'ywo', 'ywoo', 'ywoo', 'ywa', 'ywa', 'ywaa', 'ywaa', 'ywaa', 'y', 'y', + 'y', 'yi', 're', 're', 'le', 'raai', 'ri', 'rii', 'ro', 'roo', 'lo', 'ra', 'raa', 'la', 'rwaa', 'rwaa', + 'r', 'r', 'r', 'fe', 'faai', 'fi', 'fii', 'fo', 'foo', 'fa', 'faa', 'fwaa', 'fwaa', 'f', 'the', 'the', + 'thi', 'thi', 'thii', 'thii', 'tho', 'thoo', 'tha', 'thaa', 'thwaa', 'thwaa', 'th', 'tthe', 'tthi', 'ttho', 'ttha', 'tth', + 'tye', 'tyi', 'tyo', 'tya', 'he', 'hi', 'hii', 'ho', 'hoo', 'ha', 'haa', 'h', 'h', 'hk', 'qaai', 'qi', + 'qii', 'qo', 'qoo', 'qa', 'qaa', 'q', 'tlhe', 'tlhi', 'tlho', 'tlha', 're', 'ri', 'ro', 'ra', 'ngaai', 'ngi', + 'ngii', 'ngo', 'ngoo', 'nga', 'ngaa', 'ng', 'nng', 'she', 'shi', 'sho', 'sha', 'the', 'thi', 'tho', 'tha', 'th', + 'lhi', 'lhii', 'lho', 'lhoo', 'lha', 'lhaa', 'lh', 'the', 'thi', 'thii', 'tho', 'thoo', 'tha', 'thaa', 'th', 'b', + 'e', 'i', 'o', 'a', 'we', 'wi', 'wo', 'wa', 'ne', 'ni', 'no', 'na', 'ke', 'ki', 'ko', 'ka', + 'he', 'hi', 'ho', 'ha', 'ghu', 'gho', 'ghe', 'ghee', 'ghi', 'gha', 'ru', 'ro', 're', 'ree', 'ri', 'ra', + 'wu', 'wo', 'we', 'wee', 'wi', 'wa', 'hwu', 'hwo', 'hwe', 'hwee', 'hwi', 'hwa', 'thu', 'tho', 'the', 'thee', + 'thi', 'tha', 'ttu', 'tto', 'tte', 'ttee', 'tti', 'tta', 'pu', 'po', 'pe', 'pee', 'pi', 'pa', 'p', 'gu', + 'go', 'ge', 'gee', 'gi', 'ga', 'khu', 'kho', 'khe', 'khee', 'khi', 'kha', 'kku', 'kko', 'kke', 'kkee', 'kki', + ], + 'x13': [ + 'ja', 'ju', 'ji', 'jaa', 'jee', 'je', 'jo', 'jwa', 'ga', 'gu', 'gi', 'gaa', 'gee', 'ge', 'go', '[?]', + 'gwa', '[?]', 'gwi', 'gwaa', 'gwee', 'gwe', '[?]', '[?]', 'gga', 'ggu', 'ggi', 'ggaa', 'ggee', 'gge', 'ggo', '[?]', + 'tha', 'thu', 'thi', 'thaa', 'thee', 'the', 'tho', 'thwa', 'cha', 'chu', 'chi', 'chaa', 'chee', 'che', 'cho', 'chwa', + 'pha', 'phu', 'phi', 'phaa', 'phee', 'phe', 'pho', 'phwa', 'tsa', 'tsu', 'tsi', 'tsaa', 'tsee', 'tse', 'tso', 'tswa', + 'tza', 'tzu', 'tzi', 'tzaa', 'tzee', 'tze', 'tzo', '[?]', 'fa', 'fu', 'fi', 'faa', 'fee', 'fe', 'fo', 'fwa', + 'pa', 'pu', 'pi', 'paa', 'pee', 'pe', 'po', 'pwa', 'rya', 'mya', 'fya', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', ' ', '.', ',', ';', ':', ':: ', '?', '//', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '10+', '20+', '30+', '40+', '50+', '60+', '70+', '80+', '90+', '100+', '10,000+', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + 'a', 'e', 'i', 'o', 'u', 'v', 'ga', 'ka', 'ge', 'gi', 'go', 'gu', 'gv', 'ha', 'he', 'hi', + 'ho', 'hu', 'hv', 'la', 'le', 'li', 'lo', 'lu', 'lv', 'ma', 'me', 'mi', 'mo', 'mu', 'na', 'hna', + 'nah', 'ne', 'ni', 'no', 'nu', 'nv', 'qua', 'que', 'qui', 'quo', 'quu', 'quv', 'sa', 's', 'se', 'si', + 'so', 'su', 'sv', 'da', 'ta', 'de', 'te', 'di', 'ti', 'do', 'du', 'dv', 'dla', 'tla', 'tle', 'tli', + 'tlo', 'tlu', 'tlv', 'tsa', 'tse', 'tsi', 'tso', 'tsu', 'tsv', 'wa', 'we', 'wi', 'wo', 'wu', 'wv', 'ya', + 'ye', 'yi', 'yo', 'yu', 'yv', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + ], + 'x27': [ + '[?]', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '[?]', + '[?]', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '[?]', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + ], + 'x24': [ + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '', '', '', '', '', '', '', '', '', '', '', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + ], + 'xcb': [ + 'jjwaels', 'jjwaelt', 'jjwaelp', 'jjwaelh', 'jjwaem', 'jjwaeb', 'jjwaebs', 'jjwaes', 'jjwaess', 'jjwaeng', 'jjwaej', 'jjwaec', 'jjwaek', 'jjwaet', 'jjwaep', 'jjwaeh', + 'jjoe', 'jjoeg', 'jjoegg', 'jjoegs', 'jjoen', 'jjoenj', 'jjoenh', 'jjoed', 'jjoel', 'jjoelg', 'jjoelm', 'jjoelb', 'jjoels', 'jjoelt', 'jjoelp', 'jjoelh', + 'jjoem', 'jjoeb', 'jjoebs', 'jjoes', 'jjoess', 'jjoeng', 'jjoej', 'jjoec', 'jjoek', 'jjoet', 'jjoep', 'jjoeh', 'jjyo', 'jjyog', 'jjyogg', 'jjyogs', + 'jjyon', 'jjyonj', 'jjyonh', 'jjyod', 'jjyol', 'jjyolg', 'jjyolm', 'jjyolb', 'jjyols', 'jjyolt', 'jjyolp', 'jjyolh', 'jjyom', 'jjyob', 'jjyobs', 'jjyos', + 'jjyoss', 'jjyong', 'jjyoj', 'jjyoc', 'jjyok', 'jjyot', 'jjyop', 'jjyoh', 'jju', 'jjug', 'jjugg', 'jjugs', 'jjun', 'jjunj', 'jjunh', 'jjud', + 'jjul', 'jjulg', 'jjulm', 'jjulb', 'jjuls', 'jjult', 'jjulp', 'jjulh', 'jjum', 'jjub', 'jjubs', 'jjus', 'jjuss', 'jjung', 'jjuj', 'jjuc', + 'jjuk', 'jjut', 'jjup', 'jjuh', 'jjweo', 'jjweog', 'jjweogg', 'jjweogs', 'jjweon', 'jjweonj', 'jjweonh', 'jjweod', 'jjweol', 'jjweolg', 'jjweolm', 'jjweolb', + 'jjweols', 'jjweolt', 'jjweolp', 'jjweolh', 'jjweom', 'jjweob', 'jjweobs', 'jjweos', 'jjweoss', 'jjweong', 'jjweoj', 'jjweoc', 'jjweok', 'jjweot', 'jjweop', 'jjweoh', + 'jjwe', 'jjweg', 'jjwegg', 'jjwegs', 'jjwen', 'jjwenj', 'jjwenh', 'jjwed', 'jjwel', 'jjwelg', 'jjwelm', 'jjwelb', 'jjwels', 'jjwelt', 'jjwelp', 'jjwelh', + 'jjwem', 'jjweb', 'jjwebs', 'jjwes', 'jjwess', 'jjweng', 'jjwej', 'jjwec', 'jjwek', 'jjwet', 'jjwep', 'jjweh', 'jjwi', 'jjwig', 'jjwigg', 'jjwigs', + 'jjwin', 'jjwinj', 'jjwinh', 'jjwid', 'jjwil', 'jjwilg', 'jjwilm', 'jjwilb', 'jjwils', 'jjwilt', 'jjwilp', 'jjwilh', 'jjwim', 'jjwib', 'jjwibs', 'jjwis', + 'jjwiss', 'jjwing', 'jjwij', 'jjwic', 'jjwik', 'jjwit', 'jjwip', 'jjwih', 'jjyu', 'jjyug', 'jjyugg', 'jjyugs', 'jjyun', 'jjyunj', 'jjyunh', 'jjyud', + 'jjyul', 'jjyulg', 'jjyulm', 'jjyulb', 'jjyuls', 'jjyult', 'jjyulp', 'jjyulh', 'jjyum', 'jjyub', 'jjyubs', 'jjyus', 'jjyuss', 'jjyung', 'jjyuj', 'jjyuc', + 'jjyuk', 'jjyut', 'jjyup', 'jjyuh', 'jjeu', 'jjeug', 'jjeugg', 'jjeugs', 'jjeun', 'jjeunj', 'jjeunh', 'jjeud', 'jjeul', 'jjeulg', 'jjeulm', 'jjeulb', + 'jjeuls', 'jjeult', 'jjeulp', 'jjeulh', 'jjeum', 'jjeub', 'jjeubs', 'jjeus', 'jjeuss', 'jjeung', 'jjeuj', 'jjeuc', 'jjeuk', 'jjeut', 'jjeup', 'jjeuh', + 'jjyi', 'jjyig', 'jjyigg', 'jjyigs', 'jjyin', 'jjyinj', 'jjyinh', 'jjyid', 'jjyil', 'jjyilg', 'jjyilm', 'jjyilb', 'jjyils', 'jjyilt', 'jjyilp', 'jjyilh', + ], + 'xc0': [ + 'bbweok', 'bbweot', 'bbweop', 'bbweoh', 'bbwe', 'bbweg', 'bbwegg', 'bbwegs', 'bbwen', 'bbwenj', 'bbwenh', 'bbwed', 'bbwel', 'bbwelg', 'bbwelm', 'bbwelb', + 'bbwels', 'bbwelt', 'bbwelp', 'bbwelh', 'bbwem', 'bbweb', 'bbwebs', 'bbwes', 'bbwess', 'bbweng', 'bbwej', 'bbwec', 'bbwek', 'bbwet', 'bbwep', 'bbweh', + 'bbwi', 'bbwig', 'bbwigg', 'bbwigs', 'bbwin', 'bbwinj', 'bbwinh', 'bbwid', 'bbwil', 'bbwilg', 'bbwilm', 'bbwilb', 'bbwils', 'bbwilt', 'bbwilp', 'bbwilh', + 'bbwim', 'bbwib', 'bbwibs', 'bbwis', 'bbwiss', 'bbwing', 'bbwij', 'bbwic', 'bbwik', 'bbwit', 'bbwip', 'bbwih', 'bbyu', 'bbyug', 'bbyugg', 'bbyugs', + 'bbyun', 'bbyunj', 'bbyunh', 'bbyud', 'bbyul', 'bbyulg', 'bbyulm', 'bbyulb', 'bbyuls', 'bbyult', 'bbyulp', 'bbyulh', 'bbyum', 'bbyub', 'bbyubs', 'bbyus', + 'bbyuss', 'bbyung', 'bbyuj', 'bbyuc', 'bbyuk', 'bbyut', 'bbyup', 'bbyuh', 'bbeu', 'bbeug', 'bbeugg', 'bbeugs', 'bbeun', 'bbeunj', 'bbeunh', 'bbeud', + 'bbeul', 'bbeulg', 'bbeulm', 'bbeulb', 'bbeuls', 'bbeult', 'bbeulp', 'bbeulh', 'bbeum', 'bbeub', 'bbeubs', 'bbeus', 'bbeuss', 'bbeung', 'bbeuj', 'bbeuc', + 'bbeuk', 'bbeut', 'bbeup', 'bbeuh', 'bbyi', 'bbyig', 'bbyigg', 'bbyigs', 'bbyin', 'bbyinj', 'bbyinh', 'bbyid', 'bbyil', 'bbyilg', 'bbyilm', 'bbyilb', + 'bbyils', 'bbyilt', 'bbyilp', 'bbyilh', 'bbyim', 'bbyib', 'bbyibs', 'bbyis', 'bbyiss', 'bbying', 'bbyij', 'bbyic', 'bbyik', 'bbyit', 'bbyip', 'bbyih', + 'bbi', 'bbig', 'bbigg', 'bbigs', 'bbin', 'bbinj', 'bbinh', 'bbid', 'bbil', 'bbilg', 'bbilm', 'bbilb', 'bbils', 'bbilt', 'bbilp', 'bbilh', + 'bbim', 'bbib', 'bbibs', 'bbis', 'bbiss', 'bbing', 'bbij', 'bbic', 'bbik', 'bbit', 'bbip', 'bbih', 'sa', 'sag', 'sagg', 'sags', + 'san', 'sanj', 'sanh', 'sad', 'sal', 'salg', 'salm', 'salb', 'sals', 'salt', 'salp', 'salh', 'sam', 'sab', 'sabs', 'sas', + 'sass', 'sang', 'saj', 'sac', 'sak', 'sat', 'sap', 'sah', 'sae', 'saeg', 'saegg', 'saegs', 'saen', 'saenj', 'saenh', 'saed', + 'sael', 'saelg', 'saelm', 'saelb', 'saels', 'saelt', 'saelp', 'saelh', 'saem', 'saeb', 'saebs', 'saes', 'saess', 'saeng', 'saej', 'saec', + 'saek', 'saet', 'saep', 'saeh', 'sya', 'syag', 'syagg', 'syags', 'syan', 'syanj', 'syanh', 'syad', 'syal', 'syalg', 'syalm', 'syalb', + 'syals', 'syalt', 'syalp', 'syalh', 'syam', 'syab', 'syabs', 'syas', 'syass', 'syang', 'syaj', 'syac', 'syak', 'syat', 'syap', 'syah', + ], + 'x22': [ + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + ], + 'xa1': [ + 'dit', 'dix', 'di', 'dip', 'diex', 'die', 'diep', 'dat', 'dax', 'da', 'dap', 'duox', 'duo', 'dot', 'dox', 'do', + 'dop', 'dex', 'de', 'dep', 'dut', 'dux', 'du', 'dup', 'durx', 'dur', 'tit', 'tix', 'ti', 'tip', 'tiex', 'tie', + 'tiep', 'tat', 'tax', 'ta', 'tap', 'tuot', 'tuox', 'tuo', 'tuop', 'tot', 'tox', 'to', 'top', 'tex', 'te', 'tep', + 'tut', 'tux', 'tu', 'tup', 'turx', 'tur', 'ddit', 'ddix', 'ddi', 'ddip', 'ddiex', 'ddie', 'ddiep', 'ddat', 'ddax', 'dda', + 'ddap', 'dduox', 'dduo', 'dduop', 'ddot', 'ddox', 'ddo', 'ddop', 'ddex', 'dde', 'ddep', 'ddut', 'ddux', 'ddu', 'ddup', 'ddurx', + 'ddur', 'ndit', 'ndix', 'ndi', 'ndip', 'ndiex', 'ndie', 'ndat', 'ndax', 'nda', 'ndap', 'ndot', 'ndox', 'ndo', 'ndop', 'ndex', + 'nde', 'ndep', 'ndut', 'ndux', 'ndu', 'ndup', 'ndurx', 'ndur', 'hnit', 'hnix', 'hni', 'hnip', 'hniet', 'hniex', 'hnie', 'hniep', + 'hnat', 'hnax', 'hna', 'hnap', 'hnuox', 'hnuo', 'hnot', 'hnox', 'hnop', 'hnex', 'hne', 'hnep', 'hnut', 'nit', 'nix', 'ni', + 'nip', 'niex', 'nie', 'niep', 'nax', 'na', 'nap', 'nuox', 'nuo', 'nuop', 'not', 'nox', 'no', 'nop', 'nex', 'ne', + 'nep', 'nut', 'nux', 'nu', 'nup', 'nurx', 'nur', 'hlit', 'hlix', 'hli', 'hlip', 'hliex', 'hlie', 'hliep', 'hlat', 'hlax', + 'hla', 'hlap', 'hluox', 'hluo', 'hluop', 'hlox', 'hlo', 'hlop', 'hlex', 'hle', 'hlep', 'hlut', 'hlux', 'hlu', 'hlup', 'hlurx', + 'hlur', 'hlyt', 'hlyx', 'hly', 'hlyp', 'hlyrx', 'hlyr', 'lit', 'lix', 'li', 'lip', 'liet', 'liex', 'lie', 'liep', 'lat', + 'lax', 'la', 'lap', 'luot', 'luox', 'luo', 'luop', 'lot', 'lox', 'lo', 'lop', 'lex', 'le', 'lep', 'lut', 'lux', + 'lu', 'lup', 'lurx', 'lur', 'lyt', 'lyx', 'ly', 'lyp', 'lyrx', 'lyr', 'git', 'gix', 'gi', 'gip', 'giet', 'giex', + 'gie', 'giep', 'gat', 'gax', 'ga', 'gap', 'guot', 'guox', 'guo', 'guop', 'got', 'gox', 'go', 'gop', 'get', 'gex', + 'ge', 'gep', 'gut', 'gux', 'gu', 'gup', 'gurx', 'gur', 'kit', 'kix', 'ki', 'kip', 'kiex', 'kie', 'kiep', 'kat', + ], + 'xd6': [ + 'hyeo', 'hyeog', 'hyeogg', 'hyeogs', 'hyeon', 'hyeonj', 'hyeonh', 'hyeod', 'hyeol', 'hyeolg', 'hyeolm', 'hyeolb', 'hyeols', 'hyeolt', 'hyeolp', 'hyeolh', + 'hyeom', 'hyeob', 'hyeobs', 'hyeos', 'hyeoss', 'hyeong', 'hyeoj', 'hyeoc', 'hyeok', 'hyeot', 'hyeop', 'hyeoh', 'hye', 'hyeg', 'hyegg', 'hyegs', + 'hyen', 'hyenj', 'hyenh', 'hyed', 'hyel', 'hyelg', 'hyelm', 'hyelb', 'hyels', 'hyelt', 'hyelp', 'hyelh', 'hyem', 'hyeb', 'hyebs', 'hyes', + 'hyess', 'hyeng', 'hyej', 'hyec', 'hyek', 'hyet', 'hyep', 'hyeh', 'ho', 'hog', 'hogg', 'hogs', 'hon', 'honj', 'honh', 'hod', + 'hol', 'holg', 'holm', 'holb', 'hols', 'holt', 'holp', 'holh', 'hom', 'hob', 'hobs', 'hos', 'hoss', 'hong', 'hoj', 'hoc', + 'hok', 'hot', 'hop', 'hoh', 'hwa', 'hwag', 'hwagg', 'hwags', 'hwan', 'hwanj', 'hwanh', 'hwad', 'hwal', 'hwalg', 'hwalm', 'hwalb', + 'hwals', 'hwalt', 'hwalp', 'hwalh', 'hwam', 'hwab', 'hwabs', 'hwas', 'hwass', 'hwang', 'hwaj', 'hwac', 'hwak', 'hwat', 'hwap', 'hwah', + 'hwae', 'hwaeg', 'hwaegg', 'hwaegs', 'hwaen', 'hwaenj', 'hwaenh', 'hwaed', 'hwael', 'hwaelg', 'hwaelm', 'hwaelb', 'hwaels', 'hwaelt', 'hwaelp', 'hwaelh', + 'hwaem', 'hwaeb', 'hwaebs', 'hwaes', 'hwaess', 'hwaeng', 'hwaej', 'hwaec', 'hwaek', 'hwaet', 'hwaep', 'hwaeh', 'hoe', 'hoeg', 'hoegg', 'hoegs', + 'hoen', 'hoenj', 'hoenh', 'hoed', 'hoel', 'hoelg', 'hoelm', 'hoelb', 'hoels', 'hoelt', 'hoelp', 'hoelh', 'hoem', 'hoeb', 'hoebs', 'hoes', + 'hoess', 'hoeng', 'hoej', 'hoec', 'hoek', 'hoet', 'hoep', 'hoeh', 'hyo', 'hyog', 'hyogg', 'hyogs', 'hyon', 'hyonj', 'hyonh', 'hyod', + 'hyol', 'hyolg', 'hyolm', 'hyolb', 'hyols', 'hyolt', 'hyolp', 'hyolh', 'hyom', 'hyob', 'hyobs', 'hyos', 'hyoss', 'hyong', 'hyoj', 'hyoc', + 'hyok', 'hyot', 'hyop', 'hyoh', 'hu', 'hug', 'hugg', 'hugs', 'hun', 'hunj', 'hunh', 'hud', 'hul', 'hulg', 'hulm', 'hulb', + 'huls', 'hult', 'hulp', 'hulh', 'hum', 'hub', 'hubs', 'hus', 'huss', 'hung', 'huj', 'huc', 'huk', 'hut', 'hup', 'huh', + 'hweo', 'hweog', 'hweogg', 'hweogs', 'hweon', 'hweonj', 'hweonh', 'hweod', 'hweol', 'hweolg', 'hweolm', 'hweolb', 'hweols', 'hweolt', 'hweolp', 'hweolh', + 'hweom', 'hweob', 'hweobs', 'hweos', 'hweoss', 'hweong', 'hweoj', 'hweoc', 'hweok', 'hweot', 'hweop', 'hweoh', 'hwe', 'hweg', 'hwegg', 'hwegs', + ], + 'xd5': [ + 'pyuk', 'pyut', 'pyup', 'pyuh', 'peu', 'peug', 'peugg', 'peugs', 'peun', 'peunj', 'peunh', 'peud', 'peul', 'peulg', 'peulm', 'peulb', + 'peuls', 'peult', 'peulp', 'peulh', 'peum', 'peub', 'peubs', 'peus', 'peuss', 'peung', 'peuj', 'peuc', 'peuk', 'peut', 'peup', 'peuh', + 'pyi', 'pyig', 'pyigg', 'pyigs', 'pyin', 'pyinj', 'pyinh', 'pyid', 'pyil', 'pyilg', 'pyilm', 'pyilb', 'pyils', 'pyilt', 'pyilp', 'pyilh', + 'pyim', 'pyib', 'pyibs', 'pyis', 'pyiss', 'pying', 'pyij', 'pyic', 'pyik', 'pyit', 'pyip', 'pyih', 'pi', 'pig', 'pigg', 'pigs', + 'pin', 'pinj', 'pinh', 'pid', 'pil', 'pilg', 'pilm', 'pilb', 'pils', 'pilt', 'pilp', 'pilh', 'pim', 'pib', 'pibs', 'pis', + 'piss', 'ping', 'pij', 'pic', 'pik', 'pit', 'pip', 'pih', 'ha', 'hag', 'hagg', 'hags', 'han', 'hanj', 'hanh', 'had', + 'hal', 'halg', 'halm', 'halb', 'hals', 'halt', 'halp', 'halh', 'ham', 'hab', 'habs', 'has', 'hass', 'hang', 'haj', 'hac', + 'hak', 'hat', 'hap', 'hah', 'hae', 'haeg', 'haegg', 'haegs', 'haen', 'haenj', 'haenh', 'haed', 'hael', 'haelg', 'haelm', 'haelb', + 'haels', 'haelt', 'haelp', 'haelh', 'haem', 'haeb', 'haebs', 'haes', 'haess', 'haeng', 'haej', 'haec', 'haek', 'haet', 'haep', 'haeh', + 'hya', 'hyag', 'hyagg', 'hyags', 'hyan', 'hyanj', 'hyanh', 'hyad', 'hyal', 'hyalg', 'hyalm', 'hyalb', 'hyals', 'hyalt', 'hyalp', 'hyalh', + 'hyam', 'hyab', 'hyabs', 'hyas', 'hyass', 'hyang', 'hyaj', 'hyac', 'hyak', 'hyat', 'hyap', 'hyah', 'hyae', 'hyaeg', 'hyaegg', 'hyaegs', + 'hyaen', 'hyaenj', 'hyaenh', 'hyaed', 'hyael', 'hyaelg', 'hyaelm', 'hyaelb', 'hyaels', 'hyaelt', 'hyaelp', 'hyaelh', 'hyaem', 'hyaeb', 'hyaebs', 'hyaes', + 'hyaess', 'hyaeng', 'hyaej', 'hyaec', 'hyaek', 'hyaet', 'hyaep', 'hyaeh', 'heo', 'heog', 'heogg', 'heogs', 'heon', 'heonj', 'heonh', 'heod', + 'heol', 'heolg', 'heolm', 'heolb', 'heols', 'heolt', 'heolp', 'heolh', 'heom', 'heob', 'heobs', 'heos', 'heoss', 'heong', 'heoj', 'heoc', + 'heok', 'heot', 'heop', 'heoh', 'he', 'heg', 'hegg', 'hegs', 'hen', 'henj', 'henh', 'hed', 'hel', 'helg', 'helm', 'helb', + 'hels', 'helt', 'help', 'helh', 'hem', 'heb', 'hebs', 'hes', 'hess', 'heng', 'hej', 'hec', 'hek', 'het', 'hep', 'heh', + ], + 'xd2': [ + 'toels', 'toelt', 'toelp', 'toelh', 'toem', 'toeb', 'toebs', 'toes', 'toess', 'toeng', 'toej', 'toec', 'toek', 'toet', 'toep', 'toeh', + 'tyo', 'tyog', 'tyogg', 'tyogs', 'tyon', 'tyonj', 'tyonh', 'tyod', 'tyol', 'tyolg', 'tyolm', 'tyolb', 'tyols', 'tyolt', 'tyolp', 'tyolh', + 'tyom', 'tyob', 'tyobs', 'tyos', 'tyoss', 'tyong', 'tyoj', 'tyoc', 'tyok', 'tyot', 'tyop', 'tyoh', 'tu', 'tug', 'tugg', 'tugs', + 'tun', 'tunj', 'tunh', 'tud', 'tul', 'tulg', 'tulm', 'tulb', 'tuls', 'tult', 'tulp', 'tulh', 'tum', 'tub', 'tubs', 'tus', + 'tuss', 'tung', 'tuj', 'tuc', 'tuk', 'tut', 'tup', 'tuh', 'tweo', 'tweog', 'tweogg', 'tweogs', 'tweon', 'tweonj', 'tweonh', 'tweod', + 'tweol', 'tweolg', 'tweolm', 'tweolb', 'tweols', 'tweolt', 'tweolp', 'tweolh', 'tweom', 'tweob', 'tweobs', 'tweos', 'tweoss', 'tweong', 'tweoj', 'tweoc', + 'tweok', 'tweot', 'tweop', 'tweoh', 'twe', 'tweg', 'twegg', 'twegs', 'twen', 'twenj', 'twenh', 'twed', 'twel', 'twelg', 'twelm', 'twelb', + 'twels', 'twelt', 'twelp', 'twelh', 'twem', 'tweb', 'twebs', 'twes', 'twess', 'tweng', 'twej', 'twec', 'twek', 'twet', 'twep', 'tweh', + 'twi', 'twig', 'twigg', 'twigs', 'twin', 'twinj', 'twinh', 'twid', 'twil', 'twilg', 'twilm', 'twilb', 'twils', 'twilt', 'twilp', 'twilh', + 'twim', 'twib', 'twibs', 'twis', 'twiss', 'twing', 'twij', 'twic', 'twik', 'twit', 'twip', 'twih', 'tyu', 'tyug', 'tyugg', 'tyugs', + 'tyun', 'tyunj', 'tyunh', 'tyud', 'tyul', 'tyulg', 'tyulm', 'tyulb', 'tyuls', 'tyult', 'tyulp', 'tyulh', 'tyum', 'tyub', 'tyubs', 'tyus', + 'tyuss', 'tyung', 'tyuj', 'tyuc', 'tyuk', 'tyut', 'tyup', 'tyuh', 'teu', 'teug', 'teugg', 'teugs', 'teun', 'teunj', 'teunh', 'teud', + 'teul', 'teulg', 'teulm', 'teulb', 'teuls', 'teult', 'teulp', 'teulh', 'teum', 'teub', 'teubs', 'teus', 'teuss', 'teung', 'teuj', 'teuc', + 'teuk', 'teut', 'teup', 'teuh', 'tyi', 'tyig', 'tyigg', 'tyigs', 'tyin', 'tyinj', 'tyinh', 'tyid', 'tyil', 'tyilg', 'tyilm', 'tyilb', + 'tyils', 'tyilt', 'tyilp', 'tyilh', 'tyim', 'tyib', 'tyibs', 'tyis', 'tyiss', 'tying', 'tyij', 'tyic', 'tyik', 'tyit', 'tyip', 'tyih', + 'ti', 'tig', 'tigg', 'tigs', 'tin', 'tinj', 'tinh', 'tid', 'til', 'tilg', 'tilm', 'tilb', 'tils', 'tilt', 'tilp', 'tilh', + ], + 'xcd': [ + 'cyess', 'cyeng', 'cyej', 'cyec', 'cyek', 'cyet', 'cyep', 'cyeh', 'co', 'cog', 'cogg', 'cogs', 'con', 'conj', 'conh', 'cod', + 'col', 'colg', 'colm', 'colb', 'cols', 'colt', 'colp', 'colh', 'com', 'cob', 'cobs', 'cos', 'coss', 'cong', 'coj', 'coc', + 'cok', 'cot', 'cop', 'coh', 'cwa', 'cwag', 'cwagg', 'cwags', 'cwan', 'cwanj', 'cwanh', 'cwad', 'cwal', 'cwalg', 'cwalm', 'cwalb', + 'cwals', 'cwalt', 'cwalp', 'cwalh', 'cwam', 'cwab', 'cwabs', 'cwas', 'cwass', 'cwang', 'cwaj', 'cwac', 'cwak', 'cwat', 'cwap', 'cwah', + 'cwae', 'cwaeg', 'cwaegg', 'cwaegs', 'cwaen', 'cwaenj', 'cwaenh', 'cwaed', 'cwael', 'cwaelg', 'cwaelm', 'cwaelb', 'cwaels', 'cwaelt', 'cwaelp', 'cwaelh', + 'cwaem', 'cwaeb', 'cwaebs', 'cwaes', 'cwaess', 'cwaeng', 'cwaej', 'cwaec', 'cwaek', 'cwaet', 'cwaep', 'cwaeh', 'coe', 'coeg', 'coegg', 'coegs', + 'coen', 'coenj', 'coenh', 'coed', 'coel', 'coelg', 'coelm', 'coelb', 'coels', 'coelt', 'coelp', 'coelh', 'coem', 'coeb', 'coebs', 'coes', + 'coess', 'coeng', 'coej', 'coec', 'coek', 'coet', 'coep', 'coeh', 'cyo', 'cyog', 'cyogg', 'cyogs', 'cyon', 'cyonj', 'cyonh', 'cyod', + 'cyol', 'cyolg', 'cyolm', 'cyolb', 'cyols', 'cyolt', 'cyolp', 'cyolh', 'cyom', 'cyob', 'cyobs', 'cyos', 'cyoss', 'cyong', 'cyoj', 'cyoc', + 'cyok', 'cyot', 'cyop', 'cyoh', 'cu', 'cug', 'cugg', 'cugs', 'cun', 'cunj', 'cunh', 'cud', 'cul', 'culg', 'culm', 'culb', + 'culs', 'cult', 'culp', 'culh', 'cum', 'cub', 'cubs', 'cus', 'cuss', 'cung', 'cuj', 'cuc', 'cuk', 'cut', 'cup', 'cuh', + 'cweo', 'cweog', 'cweogg', 'cweogs', 'cweon', 'cweonj', 'cweonh', 'cweod', 'cweol', 'cweolg', 'cweolm', 'cweolb', 'cweols', 'cweolt', 'cweolp', 'cweolh', + 'cweom', 'cweob', 'cweobs', 'cweos', 'cweoss', 'cweong', 'cweoj', 'cweoc', 'cweok', 'cweot', 'cweop', 'cweoh', 'cwe', 'cweg', 'cwegg', 'cwegs', + 'cwen', 'cwenj', 'cwenh', 'cwed', 'cwel', 'cwelg', 'cwelm', 'cwelb', 'cwels', 'cwelt', 'cwelp', 'cwelh', 'cwem', 'cweb', 'cwebs', 'cwes', + 'cwess', 'cweng', 'cwej', 'cwec', 'cwek', 'cwet', 'cwep', 'cweh', 'cwi', 'cwig', 'cwigg', 'cwigs', 'cwin', 'cwinj', 'cwinh', 'cwid', + 'cwil', 'cwilg', 'cwilm', 'cwilb', 'cwils', 'cwilt', 'cwilp', 'cwilh', 'cwim', 'cwib', 'cwibs', 'cwis', 'cwiss', 'cwing', 'cwij', 'cwic', + ], + 'x30': [ + ' ', ', ', '. ', '"', '[JIS]', '"', '/', '0', '<', '> ', '<<', '>> ', '[', '] ', '\\{', '\\} ', + '[(', ')] ', '@', 'X ', '[', '] ', '[[', ']] ', '((', ')) ', '[[', ']] ', '~ ', '``', '\'\'', ',,', + '@', '1', '2', '3', '4', '5', '6', '7', '8', '9', '', '', '', '', '', '', + '~', '+', '+', '+', '+', '', '@', ' // ', '+10+', '+20+', '+30+', '[?]', '[?]', '[?]', '', '', + '[?]', 'a', 'a', 'i', 'i', 'u', 'u', 'e', 'e', 'o', 'o', 'ka', 'ga', 'ki', 'gi', 'ku', + 'gu', 'ke', 'ge', 'ko', 'go', 'sa', 'za', 'si', 'zi', 'su', 'zu', 'se', 'ze', 'so', 'zo', 'ta', + 'da', 'ti', 'di', 'tu', 'tu', 'du', 'te', 'de', 'to', 'do', 'na', 'ni', 'nu', 'ne', 'no', 'ha', + 'ba', 'pa', 'hi', 'bi', 'pi', 'hu', 'bu', 'pu', 'he', 'be', 'pe', 'ho', 'bo', 'po', 'ma', 'mi', + 'mu', 'me', 'mo', 'ya', 'ya', 'yu', 'yu', 'yo', 'yo', 'ra', 'ri', 'ru', 're', 'ro', 'wa', 'wa', + 'wi', 'we', 'wo', 'n', 'vu', '[?]', '[?]', '[?]', '[?]', '', '', '', '', '"', '"', '[?]', + '[?]', 'a', 'a', 'i', 'i', 'u', 'u', 'e', 'e', 'o', 'o', 'ka', 'ga', 'ki', 'gi', 'ku', + 'gu', 'ke', 'ge', 'ko', 'go', 'sa', 'za', 'si', 'zi', 'su', 'zu', 'se', 'ze', 'so', 'zo', 'ta', + 'da', 'ti', 'di', 'tu', 'tu', 'du', 'te', 'de', 'to', 'do', 'na', 'ni', 'nu', 'ne', 'no', 'ha', + 'ba', 'pa', 'hi', 'bi', 'pi', 'hu', 'bu', 'pu', 'he', 'be', 'pe', 'ho', 'bo', 'po', 'ma', 'mi', + 'mu', 'me', 'mo', 'ya', 'ya', 'yu', 'yu', 'yo', 'yo', 'ra', 'ri', 'ru', 're', 'ro', 'wa', 'wa', + 'wi', 'we', 'wo', 'n', 'vu', 'ka', 'ke', 'va', 'vi', 've', 'vo', '', '', '"', '"', + ], + 'xca': [ + 'jjael', 'jjaelg', 'jjaelm', 'jjaelb', 'jjaels', 'jjaelt', 'jjaelp', 'jjaelh', 'jjaem', 'jjaeb', 'jjaebs', 'jjaes', 'jjaess', 'jjaeng', 'jjaej', 'jjaec', + 'jjaek', 'jjaet', 'jjaep', 'jjaeh', 'jjya', 'jjyag', 'jjyagg', 'jjyags', 'jjyan', 'jjyanj', 'jjyanh', 'jjyad', 'jjyal', 'jjyalg', 'jjyalm', 'jjyalb', + 'jjyals', 'jjyalt', 'jjyalp', 'jjyalh', 'jjyam', 'jjyab', 'jjyabs', 'jjyas', 'jjyass', 'jjyang', 'jjyaj', 'jjyac', 'jjyak', 'jjyat', 'jjyap', 'jjyah', + 'jjyae', 'jjyaeg', 'jjyaegg', 'jjyaegs', 'jjyaen', 'jjyaenj', 'jjyaenh', 'jjyaed', 'jjyael', 'jjyaelg', 'jjyaelm', 'jjyaelb', 'jjyaels', 'jjyaelt', 'jjyaelp', 'jjyaelh', + 'jjyaem', 'jjyaeb', 'jjyaebs', 'jjyaes', 'jjyaess', 'jjyaeng', 'jjyaej', 'jjyaec', 'jjyaek', 'jjyaet', 'jjyaep', 'jjyaeh', 'jjeo', 'jjeog', 'jjeogg', 'jjeogs', + 'jjeon', 'jjeonj', 'jjeonh', 'jjeod', 'jjeol', 'jjeolg', 'jjeolm', 'jjeolb', 'jjeols', 'jjeolt', 'jjeolp', 'jjeolh', 'jjeom', 'jjeob', 'jjeobs', 'jjeos', + 'jjeoss', 'jjeong', 'jjeoj', 'jjeoc', 'jjeok', 'jjeot', 'jjeop', 'jjeoh', 'jje', 'jjeg', 'jjegg', 'jjegs', 'jjen', 'jjenj', 'jjenh', 'jjed', + 'jjel', 'jjelg', 'jjelm', 'jjelb', 'jjels', 'jjelt', 'jjelp', 'jjelh', 'jjem', 'jjeb', 'jjebs', 'jjes', 'jjess', 'jjeng', 'jjej', 'jjec', + 'jjek', 'jjet', 'jjep', 'jjeh', 'jjyeo', 'jjyeog', 'jjyeogg', 'jjyeogs', 'jjyeon', 'jjyeonj', 'jjyeonh', 'jjyeod', 'jjyeol', 'jjyeolg', 'jjyeolm', 'jjyeolb', + 'jjyeols', 'jjyeolt', 'jjyeolp', 'jjyeolh', 'jjyeom', 'jjyeob', 'jjyeobs', 'jjyeos', 'jjyeoss', 'jjyeong', 'jjyeoj', 'jjyeoc', 'jjyeok', 'jjyeot', 'jjyeop', 'jjyeoh', + 'jjye', 'jjyeg', 'jjyegg', 'jjyegs', 'jjyen', 'jjyenj', 'jjyenh', 'jjyed', 'jjyel', 'jjyelg', 'jjyelm', 'jjyelb', 'jjyels', 'jjyelt', 'jjyelp', 'jjyelh', + 'jjyem', 'jjyeb', 'jjyebs', 'jjyes', 'jjyess', 'jjyeng', 'jjyej', 'jjyec', 'jjyek', 'jjyet', 'jjyep', 'jjyeh', 'jjo', 'jjog', 'jjogg', 'jjogs', + 'jjon', 'jjonj', 'jjonh', 'jjod', 'jjol', 'jjolg', 'jjolm', 'jjolb', 'jjols', 'jjolt', 'jjolp', 'jjolh', 'jjom', 'jjob', 'jjobs', 'jjos', + 'jjoss', 'jjong', 'jjoj', 'jjoc', 'jjok', 'jjot', 'jjop', 'jjoh', 'jjwa', 'jjwag', 'jjwagg', 'jjwags', 'jjwan', 'jjwanj', 'jjwanh', 'jjwad', + 'jjwal', 'jjwalg', 'jjwalm', 'jjwalb', 'jjwals', 'jjwalt', 'jjwalp', 'jjwalh', 'jjwam', 'jjwab', 'jjwabs', 'jjwas', 'jjwass', 'jjwang', 'jjwaj', 'jjwac', + 'jjwak', 'jjwat', 'jjwap', 'jjwah', 'jjwae', 'jjwaeg', 'jjwaegg', 'jjwaegs', 'jjwaen', 'jjwaenj', 'jjwaenh', 'jjwaed', 'jjwael', 'jjwaelg', 'jjwaelm', 'jjwaelb', + ], + 'xa4': [ + 'qiet', 'qiex', 'qie', 'qiep', 'quot', 'quox', 'quo', 'quop', 'qot', 'qox', 'qo', 'qop', 'qut', 'qux', 'qu', 'qup', + 'qurx', 'qur', 'qyt', 'qyx', 'qy', 'qyp', 'qyrx', 'qyr', 'jjit', 'jjix', 'jji', 'jjip', 'jjiet', 'jjiex', 'jjie', 'jjiep', + 'jjuox', 'jjuo', 'jjuop', 'jjot', 'jjox', 'jjo', 'jjop', 'jjut', 'jjux', 'jju', 'jjup', 'jjurx', 'jjur', 'jjyt', 'jjyx', 'jjy', + 'jjyp', 'njit', 'njix', 'nji', 'njip', 'njiet', 'njiex', 'njie', 'njiep', 'njuox', 'njuo', 'njot', 'njox', 'njo', 'njop', 'njux', + 'nju', 'njup', 'njurx', 'njur', 'njyt', 'njyx', 'njy', 'njyp', 'njyrx', 'njyr', 'nyit', 'nyix', 'nyi', 'nyip', 'nyiet', 'nyiex', + 'nyie', 'nyiep', 'nyuox', 'nyuo', 'nyuop', 'nyot', 'nyox', 'nyo', 'nyop', 'nyut', 'nyux', 'nyu', 'nyup', 'xit', 'xix', 'xi', + 'xip', 'xiet', 'xiex', 'xie', 'xiep', 'xuox', 'xuo', 'xot', 'xox', 'xo', 'xop', 'xyt', 'xyx', 'xy', 'xyp', 'xyrx', + 'xyr', 'yit', 'yix', 'yi', 'yip', 'yiet', 'yiex', 'yie', 'yiep', 'yuot', 'yuox', 'yuo', 'yuop', 'yot', 'yox', 'yo', + 'yop', 'yut', 'yux', 'yu', 'yup', 'yurx', 'yur', 'yyt', 'yyx', 'yy', 'yyp', 'yyrx', 'yyr', '[?]', '[?]', '[?]', + 'Qot', 'Li', 'Kit', 'Nyip', 'Cyp', 'Ssi', 'Ggop', 'Gep', 'Mi', 'Hxit', 'Lyr', 'Bbut', 'Mop', 'Yo', 'Put', 'Hxuo', + 'Tat', 'Ga', '[?]', '[?]', 'Ddur', 'Bur', 'Gguo', 'Nyop', 'Tu', 'Op', 'Jjut', 'Zot', 'Pyt', 'Hmo', 'Yit', 'Vur', + 'Shy', 'Vep', 'Za', 'Jo', '[?]', 'Jjy', 'Got', 'Jjie', 'Wo', 'Du', 'Shur', 'Lie', 'Cy', 'Cuop', 'Cip', 'Hxop', + 'Shat', '[?]', 'Shop', 'Che', 'Zziet', '[?]', 'Ke', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', + ], + 'xfc': [ + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + ], + 'x1d4':[ + 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O', + 'P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e', + 'f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u', + 'v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','K', + 'L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a', + 'b','c','d','e','f','g','','i','j','k','l','m','n','o','p','q', + 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G', + 'H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W', + 'X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m', + 'n','o','p','q','r','s','t','u','v','w','x','y','z','A','','C', + 'D','','','G','','','J','K','','','N','O','P','Q','','S', + 'T','U','V','W','X','Y','Z','a','b','c','d','','f','','h','i', + 'j','k','l','m','n','','p','q','r','s','t','u','v','w','x','y', + 'z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O', + 'P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e', + 'f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v' + ], + 'x1d5':[ + 'w','x','y','z','A','B','','D','E','F','G','','','J','K', + 'L','M','N','O','P','Q','','S','T','U','V','W','X','Y','','a', + 'b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q', + 'r','s','t','u','v','w','x','y','z','A','B','','D','E','F','G', + '','I','J','K','L','M','','O','','','','S','T','U','V','W', + 'X','Y','','a','b','c','d','e','f','g','h','i','j','k','l','m', + 'n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C', + 'D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S', + 'T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i', + 'j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y', + 'z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O', + 'P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e', + 'f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u', + 'v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','K', + 'L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a', + 'b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r' + ], + 'x1d6':[ + 's','t','u','v','w','x','y','z','A','B','C','D','E','F','G', + 'H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W', + 'X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m', + 'n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C', + 'D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S', + 'T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i', + 'j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y', + 'z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O', + 'P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e', + 'f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u', + 'v','w','x','y','z','i','j','','','Alpha','Beta','Gamma','Delta','Epsilon','Zeta','Eta', + 'Theta','Iota','Kappa','Lamda','Mu','Nu','Xi','Omicron','Pi','Rho','Theta','Sigma','Tau','Upsilon','Phi','Chi', + 'Psi','Omega','nabla','alpha','beta','gamma','delta','epsilon','zeta','eta','theta','iota','kappa','lamda','mu','nu', + 'xi','omicron','pi','rho','sigma','sigma','tai','upsilon','phi','chi','psi','omega','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','','' + ], + 'x1d7':[ + '','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','0', + '1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6', + '7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2', + '3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9' + ] + } diff --git a/ebook_converter/ebooks/unihandecode/unidecoder.py b/ebook_converter/ebooks/unihandecode/unidecoder.py new file mode 100644 index 0000000..e66a11d --- /dev/null +++ b/ebook_converter/ebooks/unihandecode/unidecoder.py @@ -0,0 +1,110 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL 3' +__copyright__ = '2010, Hiroshi Miura ' +__docformat__ = 'restructuredtext en' + +''' +Decode unicode text to an ASCII representation of the text in Chinese. +Transliterate unicode characters to ASCII based on chinese pronounce. + +Derived from John Schember's unidecode library. Which was created +as part of calibre. + +Copyright(c) 2009, John Schember + +Based on the ruby unidecode gem (http://rubyforge.org/projects/unidecode/) which +is based on the perl module Text::Unidecode +(http://search.cpan.org/~sburke/Text-Unidecode-0.04/). More information about +unidecode can be found at +http://interglacial.com/~sburke/tpj/as_html/tpj22.html. + +The major differences between this implementation and others is it's written in +python and it uses a single dictionary instead of loading the code group files +as needed. + + +Copyright (c) 2007 Russell Norris + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + + +Copyright 2001, Sean M. Burke , all rights reserved. + +The programs and documentation in this dist are distributed in the +hope that they will be useful, but without any warranty; without even +the implied warranty of merchantability or fitness for a particular +purpose. + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. +''' + +import re +from calibre.ebooks.unihandecode.unicodepoints import CODEPOINTS +from calibre.ebooks.unihandecode.zhcodepoints import CODEPOINTS as HANCODES +from polyglot.builtins import unicode_type + + +class Unidecoder(object): + + codepoints = {} + + def __init__(self): + self.codepoints = CODEPOINTS + self.codepoints.update(HANCODES) + + def decode(self, text): + # Replace characters larger than 127 with their ASCII equivelent. + return re.sub('[^\x00-\x7f]',lambda x: self.replace_point(x.group()), text) + + def replace_point(self, codepoint): + ''' + Returns the replacement character or ? if none can be found. + ''' + try: + # Split the unicode character xABCD into parts 0xAB and 0xCD. + # 0xAB represents the group within CODEPOINTS to query and 0xCD + # represents the position in the list of characters for the group. + return self.codepoints[self.code_group(codepoint)][self.grouped_point( + codepoint)] + except: + return '?' + + def code_group(self, character): + ''' + Find what group character is a part of. + ''' + # Code groups withing CODEPOINTS take the form 'xAB' + if not isinstance(character, unicode_type): + character = unicode_type(character, "utf-8") + return 'x%02x' % (ord(character) >> 8) + + def grouped_point(self, character): + ''' + Return the location the replacement character is in the list for a + the group character is a part of. + ''' + if not isinstance(character, unicode_type): + character = unicode_type(character, "utf-8") + return ord(character) & 255 diff --git a/ebook_converter/ebooks/unihandecode/vncodepoints.py b/ebook_converter/ebooks/unihandecode/vncodepoints.py new file mode 100644 index 0000000..2a74bb1 --- /dev/null +++ b/ebook_converter/ebooks/unihandecode/vncodepoints.py @@ -0,0 +1,5252 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL 3' +__copyright__ = '2010 Hiroshi Miura ' +__docformat__ = 'restructuredtext en' + +''' +Unicode code point dictionary. +Based on Unicode.org Unihan database. +''' + +CODEPOINTS = { + 'x34':[ + 'Qiu ','Tian ','','','Kua ','Wu ','Yin ','','','','','','Si ','','','', + '','','','','','','Ye ','','','','','','Chou ','','','', + '','Nuo ','','','Qiu ','','','','Xu ','Xing ','','Xiong ','Liu ','Lin ','Xiang ','Yong ', + 'Xin ','Zhen ','Dai ','Wu ','Pan ','','','Ma ','Qian ','Yi ','Zhong ','N ','Cheng ','Fung ','','', + '','Zhuo ','Fang ','Ao ','Wu ','Zuo ','','Zhou ','Dong ','Su ','Yi ','Jiong ','Wang ','Lei ','Nao ','Zhu ', + 'Suk ','','','','Xu ','','','Saan ','Jie ','Die ','Nuo ','Su ','Yi ','Long ','Ying ','Beng ', + '','','','Lan ','Miao ','Yi ','Li ','Ji ','Yu ','Luo ','Chai ','Nom ','','','Hun ','Xu ', + 'Hui ','Rao ','','Zhou ','Caam ','Han ','Xi ','Tai ','Ai ','Hui ','Jun ','Ma ','Lue ','Tang ','Xiao ','Tiao ', + 'Zha ','Yu ','Ku ','Er ','Nang ','Qi ','Chi ','Mu ','Han ','Tang ','Se ','Si ','Qiong ','Lei ','Sa ','', + '','Hui ','Pu ','Ta ','Shu ','Zoeng ','Ou ','Tai ','','Mian ','Wen ','Diao ','Yu ','Mie ','Jun ','Niao ', + 'Xie ','You ','','','She ','Fung ','Lei ','Li ','Sin ','Luo ','Sek ','Ji ','','Kwaan ','','', + 'Quan ','','Cai ','Liang ','Gu ','Mao ','Gung ','Gua ','Sui ','Din ','','Mao ','Man ','Hyun ','Shi ','Li ', + '','Wang ','Kou ','Chui ','Zhen ','Ding ','','','Bing ','Huan ','Dong ','Gong ','Cang ','','Lian ','Jiong ', + 'Lu ','Xing ','','Nan ','Xie ','','Bi ','Jie ','Su ','Hung ','Geoi6','Gung ','You ','Xing ','Qi ','Phay ', + 'Dian ','Fu ','Luo ','Qia ','Jie ','Tong ','Bak ','Yan ','Ci ','Fan ','Lang ','','Fu ','He ','Diu ','Li ', + 'Hua ','Tou ','Pian ','Dai ','Jun ','E ','Qie ','Yi ','Jue ','Rui ','Jian ','Gong ','Chi ','Chong ','Chi ','', + ], + 'x35':[ + 'Lue ','Daang ','Lin ','Jue ','Su ','Xiao ','Chan ','Put ','','Zhu ','Dan ','Jian ','Zhou ','Duo ','Xie ','Li ', + 'Cim ','Chi ','Xi ','Jian ','','Ji ','','Fei ','Chu ','Bang ','Kou ','','Ba ','Liang ','Kuai ','', + 'He ','Bit ','Jue ','Lei ','Shen ','Pi ','Yang ','Lu ','Bei ','E ','Lu ','','Coek ','Che ','Nuo ','Suan ', + 'Heng ','Yu ','','Gui ','Yi ','Xian ','Gong ','Lou ','Cam ','Le ','Shi ','Pei ','Sun ','Yao ','Jie ','Zou ', + '','Que ','Yin ','Him ','Zhi ','Jia ','Hu ','La ','Hou ','Ke ','Bou ','Jing ','Ai ','Deoi ','E ','Chu ', + 'Xie ','Chu ','Wei ','','Teng ','Huan ','Su ','You ','Caam ','Jun ','Zhao ','Xu ','Shi ','','Caat ','Kui ', + 'Soeng ','He ','Gai ','Yan ','Qiu ','Yi ','Hua ','Si ','Fan ','Zhang ','Dan ','Fang ','Song ','Ao ','Fu ','Nei ', + 'Mau ','You ','Hua ','Hung ','Chen ','Uong ','Ng ','Hua ','Lap ','Fa ','Hao ','Pou ','Dung6','Si ','','', + 'Le ','Lin ','Yi ','Hou ','Zaau ','Xu ','Qu ','Nhe ','','','','','','','','Nei ', + 'Wei ','Xie ','Ti ','Hong ','Tun ','Bo ','Nie ','Sum ','San ','','','','','','Wai ','Shou ', + 'Ba ','Ye ','Ji ','Tou ','Han ','Jiong ','Dong ','Wen ','Lu ','Sou ','Guo ','Ling ','','Tian ','Lun ','', + '','','','','','ge ','Ye ','Shi ','Xue ','Fen ','Chun ','Rou ','Duo ','Ze ','E ','Xie ', + 'Zaau ','E ','Sheng ','Wen ','Man ','Hu ','Ge ','Xia ','Man ','Bi ','Ji ','Hou ','Zhi ','','Gaa ','', + '','Boi ','Ai ','Ci ','Hin ','Gou ','Thao ','Bai ','Bo ','Na ','Trat ','Xiao ','Suc ','','','', + '','','Rong ','Ti ','Cu ','Kuo ','Lao ','Zhi ','Ai ','Xi ','','Qie ','Zaa ','Hei ','','', + 'Chu ','Ji ','Huo ','Ta ','Yan ','Xu ','Put ','Sai ','','','','Go6','Ye ','Xiang ','Heoi ','Xia ', + ], + 'x36':[ + 'Zuo ','Yi ','Ci ','','','Xian ','Tai ','Vang ','Yi ','Zhi ','Yi ','Xian ','Ju ','Ji ','Han ','', + 'Pao ','Li ','','Ran ','Can ','Han ','Yan ','','','Yan ','Han ','Haam ','Chi ','Nian ','Huo ','', + 'Bi ','Xia ','Weng ','Xuan ','Waan ','You ','Qin ','Xu ','Nei ','Bi ','Hao ','Jing ','Ao ','Ao ','','', + 'Zam ','Taan ','Ju ','Zaau ','Zuo ','Bu ','Jie ','Ai ','Zang ','Ci ','Fa ','Zaan ','','','','Nie ', + 'Liu ','Mang ','Dui ','Bong ','Bi ','Bao ','','Chu ','Han ','Tian ','Chang ','','','Do ','Wai ','Fu ', + 'Duo ','Yu ','Ye ','Kui ','Han ','Kuai ','','Kuai ','Ziu ','Long ','Sing ','Bu ','Chi ','Xie ','Nie ','Lang ', + 'Yi ','Zung ','Man ','Zhang ','Ho ','Gun ','','','Ji ','Liao ','Ye ','Ji ','Yin ','','Da ','Yi ', + 'Xie ','Hao ','Yong ','Han ','Chan ','Tai ','Tang ','Zhi ','Bao ','Meng ','Gui ','Chan ','Lei ','','Xi ','', + 'Hei ','Qiao ','Rang ','Yun ','','Long ','Fu ','Zuk ','','Gu ','Hoi ','Diu ','Hua ','Guo ','','Gao ', + 'Tao ','','Shan ','Lai ','Nie ','Fu ','Gao ','Qie ','Ban ','Gaa ','','Xi ','Xu ','Kui ','Meng ','Chuo ', + 'Hiu ','Ji ','Nu ','Xiao ','Yi ','Yu ','Yi ','Yan ','','Ran ','Hao ','Sha ','Gwan ','You ','Daam ','Xin ', + 'Bi ','Zaau ','Dian ','O ','Bu ','Dung ','Si ','Er ','Si ','Mao ','Yun ','Gei ','Naau ','Qiao ','','Pao ', + '','Ping ','Nuo ','Jie ','Zi ','Er ','Duo ','','','','Duo ','','','Qie ','Leoi ','Ou ', + 'Sou ','Can ','Dou ','Ci ','Peng ','Yi ','So ','Zuo ','Po ','Qie ','Tong ','Xin ','You ','Bei ','Long ','', + '','','','','','Ta ','Lan ','Man ','Qiang ','Zhou ','Em ','Sek ','Lu ','Sik ','Sao ','Mian ', + 'Fan ','Rui ','Fa ','Cha ','Nao ','Cing ','Chou ','Gai ','Shu ','Pian ','Aam ','Kui ','Sha ','Saan ','Xian ','Zhi ', + ], + 'x37':[ + '','','Fung ','Lian ','Xun ','Xu ','Mi ','Hui ','Mu ','Zung ','Pang ','Yi ','Gou ','Tang ','Qi ','Yun ', + 'Shu ','Fu ','Yi ','Da ','','Lian ','Cao ','Can ','Ju ','Lu ','Su ','Nen ','Ao ','An ','Qian ','', + 'Ceoi ','Sung ','','Ran ','Shen ','Mai ','Han ','Yue ','Er ','Ao ','Xian ','Ma ','','','Lan ','Hei ', + 'Yue ','Dong ','Weng ','Huai ','Meng ','Niao ','Wan ','Mi ','Nie ','Qu ','Zan ','Lian ','Zhi ','Zi ','Hai ','Xu ', + 'Hao ','Xun ','Zhi ','Fan ','Chun ','Gou ','','Chun ','Luan ','Zhu ','Shou ','Liao ','Jie ','Xie ','Ding ','Jie ', + 'Rong ','Mang ','Geoi ','Ge ','Yao ','Ning ','Yi ','Lang ','Yong ','Yin ','','Su ','Sik ','Lin ','Ya ','Mao ', + 'Ming ','Zui ','Yu ','Ye ','Gou ','Mi ','Jun ','Wen ','','Hoi ','Dian ','Long ','','Xing ','Cui ','Qiao ', + 'Mian ','Meng ','Qin ','','Wan ','De ','Ai ','','Bian ','Nou ','Lian ','Jin ','Zyu ','Chui ','Zuo ','Bo ', + 'Fui ','Yao ','Tui ','Ji ','Aam ','Guo ','Ji ','Wei ','Bui6','Zaat ','Xu ','Nian ','Yun ','','Ba ','Zhe ', + 'Ju ','Wei ','Xi ','Qi ','Yi ','Xie ','Ci ','Qiu ','Tun ','Niao ','Qi ','Ji ','Teoi ','','','Dian ', + 'Lao ','Zhan ','Zi ','Fan ','Yin ','Cen ','Ji ','Hui ','Zai ','Lan ','Nao ','Ju ','Qin ','Dai ','Shutsu ','Jie ', + 'Xu ','Cung ','Yong ','Dou ','Chi ','Tou ','Min ','Huang ','Sui ','Ke ','Zu ','Hao ','Cheng ','Xue ','Ni ','Chi ', + 'Lian ','An ','Chi ','Si ','Xiang ','Yang ','Hua ','Cuo ','Qiu ','Lao ','Fu ','Dui ','Mang ','Lang ','Tuo ','Han ', + 'Mang ','Bo ','Kwan ','Qi ','Han ','','Long ','Ban ','Tiao ','Lao ','Qi ','Zan ','Mi ','Pei ','Zhan ','Xiang ', + 'Gang ','','Qi ','','Lu ','Caam ','Yun ','E ','Quan ','Min ','Wei ','Quan ','Shu ','Min ','Daat6','', + 'Ming ','Yao ','Jue ','Li ','Kuai ','Gang ','Yuan ','Da ','Gou ','Lao ','Lou ','Qian ','Ao ','Biao ','Zung ','Mang ', + ], + 'x38':[ + 'Dao ','Caam ','Ao ','','Xi ','Fu ','Daan ','Jiu ','Run ','Tong ','Qu ','E ','Hei ','Ji ','Ji ','Hua ', + 'Jiao ','Zui ','Biao ','Meng ','Bai ','Wei ','Ji ','Ao ','Yu ','Hao ','Dui ','Wo ','Ni ','Cuan ','','Li ', + 'Lu ','Niao ','Hua ','Lai ','','Lu ','Fung ','Mi ','Yu ','Fong ','Ju ','','','Zhan ','Pang ','Yi ', + '','Ji ','Bi ','','Ren ','Fong ','Fan ','Ge ','Ku ','Jie ','Miao ','Hei ','Si ','Tong ','Zyun ','Ci ', + 'Bi ','Kai ','Li ','Fong ','Sun ','Nuo ','Fong ','Ji ','Men ','Xian ','Qia ','E ','Mao ','','Saam ','Tou ', + 'Zin ','Qiao ','Zeon ','Kwaan ','Wu ','Zing ','Chuang ','Ti ','Lian ','Bi ','Haat6','Mang ','Xue ','Feng ','Lei ','Zou ', + 'Zheng ','Chu ','Man ','Long ','','Yin ','Baan ','Zheng ','Qian ','Luan ','Nie ','Yi ','','Ji ','Ji ','Zhai ', + 'Yu ','Jiu ','Huan ','Di ','Lup ','Ling ','Ji ','Ben ','Zha ','Ci ','Dan ','Liao ','Yi ','Zhao ','Xian ','Chi ', + 'Ci ','Chi ','Yan ','Lang ','Dou ','Long ','Chan ','','Tui ','Cha ','Ai ','Chi ','','Ying ','Cha ','Tou ', + '','Tui ','Cha ','Yao ','Zong ','Zung ','Pun ','Qiao ','Lian ','Qin ','Lu ','Yan ','Kong ','Sou ','Yi ','Chan ', + 'Jiong ','Jiang ','','Jing ','','Dong ','Go ','Juan ','Han ','Di ','Wu ','','Hong ','Tou ','Chi ','Min ', + 'Bi ','','Xun ','Lu ','Sai ','She ','Bi ','','Bi ','','Xian ','Wei ','Bie ','Er ','Juan ','', + 'Zhen ','Bei ','Yi ','Yu ','Qu ','Zan ','Mi ','Ni ','Si ','Gung ','','Daan ','Shan ','Tai ','Mu ','Jing ', + 'Bian ','Rong ','Ceng ','Can ','Ding ','','','','Keoi ','Di ','Tong ','Ta ','Xing ','Sung ','Duo ','Xi ', + 'Tong ','','Ti ','Shan ','Jian ','Zhi ','Wai ','Yin ','','','Huan ','Zhong ','Qi ','Zung ','','Xie ', + 'Xie ','Ze ','Wei ','','','Ta ','Zhan ','Ning ','','','Sam ','Yi ','Ren ','Shu ','Cha ','Zhuo ', + ], + 'x39':[ + '','Mian ','Ji ','Fang ','Pei ','Ai ','Fan ','Ao ','Qin ','Qia ','Xiao ','Fan ','Gaam ','Qiao ','Go ','Tong ', + 'Tip ','You ','Gou ','Ben ','Fu ','Chu ','Zhu ','','Chu ','Zaan ','Hang ','Nin ','Jue ','Cung ','Cha ','Kong ', + 'Lie ','Li ','Xu ','Paang ','Yu ','Hai ','Li ','Hou ','Gong ','Ke ','Yuan ','De ','Hui ','Giu ','Kuang ','Jiong ', + 'Zan ','Fu ','Qie ','Bei ','Xi ','Ci ','Pang ','Haam ','Xi ','Qiu ','Huang ','Nan ','','Chou ','San ','Jim ', + 'De ','De ','Te ','Men ','Ling ','Shou ','Dian ','Can ','Die ','Che ','Peng ','Zi ','Ju ','Ji ','Lai ','Tian ', + 'Yuan ','Zaau ','Cai ','Qi ','Yu ','Lian ','Cung ','','','','Yu ','Ji ','Wei ','Mi ','Cui ','Xie ', + 'Xu ','Xi ','Qiu ','Hui ','Ging ','Ngung ','Qie ','Shun ','Chui ','Duo ','Lou ','Deon ','Pang ','Tai ','Zhou ','Yin ', + 'Sou ','Fei ','Shen ','Yuan ','Yi ','Hun ','Se ','Ye ','Min ','Fen ','He ','','Yin ','Ce ','Ni ','Ao ', + 'Feng ','Lian ','Chang ','Chan ','Ma ','Di ','Hu ','Lu ','','Yi ','Hua ','Caa ','Tui ','E ','Hua ','Sun ', + 'Ni ','Lian ','Li ','Xian ','Yan ','Long ','Muon ','Jian ','Gik ','','Bian ','Yu ','Huo ','Miao ','Chou ','Hai ', + '','Le ','Jie ','Wei ','Yi ','Huan ','He ','Can ','Lan ','Yin ','Xie ','Zaat ','Luo ','Ling ','Qian ','Huo ', + 'Cim ','Wo ','Zoi ','','Ge ','Zyu ','Die ','Yong ','Ji ','Ang ','Ru ','Xi ','Shuang ','Xu ','Yi ','Hu ', + 'Ji ','Qu ','Tian ','Sau ','Qian ','Mu ','Gaan ','Mao ','Yin ','Gai ','Ba ','Xian ','Mao ','Phang ','Ya ','Gong ', + 'Song ','Wei ','Xue ','Gwaa ','Guai ','Jiu ','E ','Zi ','Cui ','Bi ','Wa ','Hin ','Lie ','Gaa ','','Kuai ', + '','Hai ','Zaan ','Zhu ','Chong ','Xian ','Xuan ','So ','Qiu ','Pei ','Gui ','Er ','Gong ','Qiong ','Bak6','Lao ', + 'Li ','Chen ','San ','Bo ','Wo ','Pou ','Hang ','Duo ','Paang ','Te ','Ta ','Zhi ','Biao ','Gu ','Hot ','Coeng ', + ], + 'x3a':[ + 'Bing ','Zhi ','Dong ','Cheng ','Zhao ','Nei ','Lin ','Po ','Ji ','Min ','Wei ','Che ','Gou ','Bong ','Ru ','Taan ', + 'Bu ','Zung ','Kui ','Lao ','Han ','Ying ','Zhi ','Jie ','Xing ','Xie ','Xun ','Shan ','Qian ','Xie ','Su ','Hai ', + 'Mi ','Hun ','Nang ','','Hui ','Na ','Song ','Ben ','Liu ','Jie ','Huang ','Lan ','','Hu ','Dou ','Huo ', + 'Ge ','Yao ','Ce ','Gui ','Jian ','Jian ','Chou ','Jin ','Ma ','Hui ','Men ','Can ','Lue ','Pi ','Yang ','Ju ', + 'Ju ','Que ','','','Shai ','Cau ','Jiu ','Hua ','Xian ','Xie ','Syun ','Su ','Fei ','Ce ','Ye ','', + '','','Cam ','Hui ','Tun ','Ling ','Qiang ','Xi ','Yi ','Nim ','Meng ','Tuan ','Giam ','Hao ','Ci ','Zhai ', + 'Piao ','Luo ','Mi ','Buk ','Fu ','Cam ','Xie ','Bo ','Hui ','Qi ','Xie ','','Hei ','Bo ','Qian ','Ban ', + 'Jiao ','Jue ','Kun ','Song ','Ju ','E ','Nie ','','Die ','Die ','Pei ','Gui ','Zi ','Qi ','Chui ','Gwaat6', + 'Yu ','Qin ','Faat ','Ke ','Fu ','Gaang ','Di ','Xian ','Gui ','He ','Qun ','Han ','Tong ','Bo ','Shan ','Bi ', + 'Lu ','Ye ','Ni ','Chuai ','San ','Diao ','Lu ','Tou ','Lian ','Ke ','San ','Zhen ','Chuai ','Lian ','Mao ','Deon ', + 'Qian ','Ke ','Shao ','Qiao ','Bi ','Zaa ','Yin ','Kaap ','Shan ','Su ','Sa ','Rui ','Zhuo ','Lu ','Ling ','Cha ', + 'Zaai ','Huan ','','','Jia ','Ban ','Hu ','Dou ','Caam ','Lou ','','Juan ','Ke ','Suo ','Ge ','Zhe ', + 'Ding ','Duan ','Zhu ','Yan ','Pang ','Cha ','','','','','Yi ','Zin ','','You ','Gun ','Yao ', + 'Yao ','Shi ','Gong ','Qi ','Gen ','Gwong ','','Hou ','Mi ','Fu ','Hu ','Guang ','Dan ','Dai ','Tou ','Yan ', + '','Dung ','Qu ','','Chang ','Ming ','Tou ','Bao ','On ','Ceon ','Zung ','Xian ','','','','Mao ', + 'Lang ','Nan ','Pei ','Chen ','Hau ','Fei ','Cou ','Gei ','Qie ','Dai ','Sik ','Kun ','Die ','Lu ','Thung ','', + ], + 'x3b':[ + '','Caap ','Yu ','Tai ','Chan ','Man ','Mian ','Huan ','Wan ','Nuan ','Huan ','Hou ','Jing ','Bo ','Xian ','Li ', + 'Jin ','','Mang ','Piao ','Hao ','Yang ','','Xian ','Su ','Wei ','Che ','Kap ','Jin ','Ceng ','He ','', + 'Shai ','Ling ','Fui ','Dui ','Zaap ','Pu ','Yue ','Bo ','','Hui ','Die ','Yan ','Ju ','Jiao ','Kuai ','Lie ', + 'Yu ','Ti ','Tim ','Wu ','Hong ','Xiao ','Hao ','','Tiu ','Zaang ','','Huang ','Fu ','','','Dun ', + '','Reng ','Jiao ','Gong ','Xin ','','','Yuan ','Jue ','Hua ','Sik ','Bang ','Mou ','Cat ','Gong ','Wei ', + '','Mei ','Si ','Bian ','Lu ','Keoi ','','','He ','She ','Lu ','Pai ','Rong ','Qiu ','Lie ','Gong ', + 'Xian ','Xi ','Hing ','','Niao ','','','','Xie ','Lei ','Fu ','Cuan ','Zhuo ','Fei ','Zuo ','Die ', + 'Ji ','He ','Ji ','','Gin ','','','','Tu ','Xian ','Yan ','Tang ','Ta ','Di ','Jue ','Ang ', + 'Han ','Yao ','Ju ','Rui ','Bang ','Zeoi ','Nie ','Tian ','Nai ','','','You ','Mian ','Zin ','Bui ','Nai ', + 'Xing ','Qi ','Zaan ','Gen ','Tong ','Er ','Jia ','Qin ','Mao ','E ','Li ','Chi ','Zong ','He ','Jie ','Ji ', + '','Guan ','Hou ','Gai ','Cung ','Fen ','Se ','Waat ','Ji ','Sik ','Qiong ','He ','Zung ','Xian ','Jie ','Hua ', + 'Bi ','Sing ','Caai ','Zhen ','Sau ','Zin ','Shi ','Gai ','Song ','Zhi ','Ben ','','','','Lang ','Bi ', + 'Xian ','Bang ','Dai ','Cat ','Zi ','Pi ','Chan ','Bi ','Su ','Huo ','Hen ','Ying ','Chuan ','Jiang ','Nen ','Gu ', + 'Fang ','','','Ta ','Cui ','Sai ','De ','Ran ','Kuan ','Che ','Da ','Hu ','Cui ','Ro ','Juan ','Lu ', + 'Qian ','Pao ','Zhen ','Fan ','Li ','Cao ','Qi ','','','Ti ','Ling ','Qu ','Lian ','Lu ','Shu ','Gong ', + 'Zhe ','Biao ','Cum ','Qing ','','','Zong ','Buc ','Jin ','Biao ','Jian ','Gun ','','Ban ','Zou ','Xop ', + ], + 'x3c':[ + 'Li ','Luo ','Shen ','Mian ','Jian ','Di ','Bei ','Cim ','Lian ','Zeon ','Xun ','Pin ','Que ','Long ','Zui ','Gou ', + 'Jue ','San ','She ','','Xie ','Hei ','Lan ','Cu ','Yi ','Nuo ','Li ','Yue ','','Yi ','Ci ','Ji ', + 'Kang ','Xie ','Hang ','Zi ','Ke ','Hui ','Qu ','Hai6','Hei ','Hoi ','Wa ','Caam ','Xun ','Haap6','Shen ','Kou ', + 'Qie ','Sha ','Xu ','Ya ','Po ','Zu ','You ','Zi ','Lian ','Jin ','Xia ','Yi ','Qie ','Mi ','Jiao ','Hei ', + 'Chi ','Shi ','Fong ','Yin ','Mo ','Yi ','Hei ','Se ','Jin ','Ye ','Zaau ','Que ','Che ','Luan ','Kwaan ','Zheng ', + '','','Ho ','','Se ','Gwai ','Cui ','Zaau ','An ','Xiu ','Can ','Chuan ','Zha ','','Ji ','Bo ', + 'Fu ','Sing ','Lang ','Tui ','Sek6','Ling ','E ','Wo ','Lian ','Du ','Men ','Lan ','Wei ','Duan ','Kuai ','Ai ', + 'Zai ','Hui ','Yi ','Mo ','Zi ','Ben ','Beng ','','Bi ','Li ','Lu ','Luo ','Hoi ','Dan ','Goi ','Que ', + 'Chen ','Hung ','Cheng ','Jiu ','Kou ','Ji ','Ling ','Ci ','Shao ','Kai ','Rui ','Chuo ','Neng ','Zi ','Lou ','Bao ', + '','','Bao ','Rong ','Saan ','Lei ','Siu ','Fu ','Qu ','Saau ','Saa ','Zhi ','Tan ','Rong ','Zu ','Ying ', + 'Mao ','Nai ','Bian ','Saau ','Seoi ','Tang ','Han ','Zao ','Rong ','','Dang ','Pu ','Ziu ','Tan ','','Ran ', + 'Ning ','Lie ','Die ','Die ','Zhong ','Siu ','Lu ','Dan ','Kap ','Gui ','Ji ','Ni ','Yi ','Nian ','Yu ','Wang ', + 'Guo ','Ze ','Yan ','Cui ','Xian ','Jiao ','Shu ','Fu ','Pei ','Ngoet ','Zaau ','Zaau ','Nhop ','Bu ','Bian ','Chi ', + 'Sa ','Yi ','Bian ','','Dui ','Lan ','Zi ','Chai ','Cung ','Xuan ','Yu ','Yu ','Zaau ','Hong ','Cung ','', + 'Ta ','Gwo ','','','Suk6','Ju ','Xie ','Xi ','Jian ','Tan ','Pan ','Ta ','Xuan ','Xian ','Niao ','Tan ', + 'Gaau ','','','','Mi ','Ji ','Gou ','Wen ','Faa ','Wang ','You ','Ze ','Bi ','Mi ','Goeng ','Xie ', + ], + 'x3d':[ + 'Fan ','Yi ','Dam ','Lei ','Ying ','Siu ','Jin ','She ','Yin ','Ji ','Zyun ','Su ','','','','Wang ', + 'Mian ','Su ','Yi ','Zai ','Se ','Ji ','Luo ','Zaau ','Mao ','Zha ','Sui ','Zhi ','Bian ','Li ','Caai ','', + '','','','','','Qiao ','Guan ','','Zhen ','Zung ','Nie ','Jun ','Xie ','Yao ','Xie ','Zi ', + 'Neng ','Sam ','Si ','Long ','Chen ','Mi ','Que ','Dam ','Na ','','','','Su ','Xie ','Bo ','Ding ', + 'Cuan ','Fong ','Chuang ','Che ','Han ','Dan ','Hao ','','','','Shen ','Mi ','Chan ','Men ','Han ','Cui ', + 'Jue ','He ','Fei ','Shi ','Che ','Shen ','Nu ','Fu ','Man ','Cing ','','','','Yi ','Chou ','Mei ', + 'Faat ','Bao ','Loi ','Ke ','Dian ','Bi ','Sui ','Ge ','Bi ','Yi ','Xian ','Ni ','Ying ','Zhu ','Chun ','Feng ', + 'Xu ','Piao ','Wu ','Liao ','Cang ','Zou ','Ceoi ','Bian ','Yao ','Huan ','Pai ','Sou ','','Dui ','Jing ','Xi ', + 'Bak6','Guo ','','','Yan ','Xue ','Chu ','Heng ','Ying ','','','','Lian ','Xian ','Huan ','Zaan ', + '','Lian ','Shan ','Cang ','Bei ','Jian ','Shu ','Fan ','Dian ','','Ba ','Yu ','Zyun ','','Nang ','Lei ', + 'Yi ','Dai ','','Chan ','Chao ','Gon ','Jin ','Nen ','Pei ','','','Liao ','Mei ','Jiu ','Siu ','Liu ', + 'Han ','','Yong ','Jin ','Chi ','Ren ','Nong ','','','Hong ','Tian ','Bung ','Oi ','Gwaa ','Biu ','Bo ', + 'Qiong ','','Shu ','Cui ','Hui ','Chao ','Dou ','Guai ','E ','Wei ','Fen ','Tan ','','Lun ','He ','Yong ', + 'Hui ','Nim6','Yu ','Zong ','Yan ','Qiu ','Zhao ','Jiong ','Tai ','Zin ','','Bou ','','Dut ','','Tui ', + 'Lin ','Jiong ','Zha ','Sing ','He ','Zing ','Xu ','','','Hei ','Cui ','Qing ','Mo ','Fung ','Zou ','Beng ', + 'Li ','','','Yan ','Ge ','Mo ','Bei ','Juan ','Die ','Shao ','','Wu ','Yan ','','Jue ','Hin ', + ], + 'x3e':[ + 'Tai ','Han ','','Dian ','Ji ','Jie ','','','Ziu ','Xie ','La ','Fan ','Huo ','Xi ','Nie ','Mi ', + 'Ran ','Cuan ','Yin ','Mi ','','Jue ','Keoi ','Tong ','Wan ','Ze ','Li ','Shao ','Kong ','Kan ','Ban ','Taai ', + 'Tiao ','Syu ','Bei ','Ye ','Pian ','Chan ','Hu ','Ken ','Gaau ','An ','Chun ','Qian ','Bei ','Baa ','Fen ','Fo ', + 'Tuo ','Tuo ','Zuo ','Ling ','','Gui ','Zin ','Shi ','Hou ','Lie ','Saa ','Si ','Fung ','Bei ','Ren ','Du ', + 'Bo ','Liang ','Ci ','Bi ','Ji ','Zong ','Fai ','He ','Li ','Yuan ','Yue ','Saau ','Chan ','Di ','Lei ','Jin ', + 'Chong ','Si ','Pu ','Yi ','Goeng ','Fun ','Huan ','Tao ','Ru ','Ying ','Ying ','Rao ','Yin ','Shi ','Yin ','Jue ', + 'Tun ','Xuan ','Gaa ','Zung ','Qie ','Zhu ','Ciu ','Zoeng ','You ','','Saan ','Xi ','Shi ','Yi ','Mo ','Huou ', + '','Hu ','Xiao ','Wu ','Gang ','Jing ','Ting ','Shi ','Ni ','Gang ','Ta ','Waai ','Chu ','Chan ','Piao ','Diao ', + 'Nao ','Nao ','Gan ','Gou ','Yu ','Hou ','','Si ','Ci ','Hu ','Yang ','Zung ','Xian ','Ban ','Rong ','Lou ', + 'Zhao ','Can ','Liao ','Piao ','Voi ','Fan ','Han ','Dan ','Zhan ','','Ta ','Zhu ','Ban ','Jian ','Yu ','Zhuo ', + 'You ','Li ','Kut ','Hei ','Cim ','Chan ','Lian ','Heo ','Si ','Jiu ','Pu ','Qiu ','Gong ','Zi ','Yu ','', + 'Si ','Reng ','Niu ','Mei ','Baat ','Jiu ','','Xu ','Ping ','Bian ','Mao ','','','','','Yi ', + 'You ','Gwai ','Ping ','Kuk ','Bao ','Hui ','','','','Bu ','Mang ','La ','Tu ','Wu ','Li ','Ling ', + '','Ji ','Jun ','Lit6','Duo ','Jue ','Dai ','Bei ','','','','','','La ','Bian ','Sui ', + 'Tu ','Die ','','','','','','Duo ','','','Sui ','Bi ','Tu ','Se ','Can ','Tu ', + 'Mian ','Zeon ','Lu ','','','Zhan ','Bi ','Ji ','Cen ','Hyun ','Li ','','','Sui ','Zung ','Shu ', + ], + 'x3f':[ + '','','E ','','Gei ','','','Qiong ','Luo ','Yin ','Tun ','Gu ','Yu ','Lei ','Bei ','Nei ', + 'Pian ','Lian ','Qiu ','Lian ','Waan ','Dong ','Li ','Ding ','Wa ','Zhou ','Gong ','Xing ','Ang ','Fan ','Peng ','Bai ', + 'Tuo ','Syu ','E ','Bai ','Qi ','Chu ','Gong ','Tong ','Han ','Cheng ','Jia ','Huan ','Xing ','Dian ','Mai ','Dong ', + 'E ','Ruan ','Lie ','Sheng ','Ou ','Di ','Yu ','Chuan ','Rong ','Hong ','Tang ','Cong ','Piao ','Shuang ','Lu ','Tong ', + 'Zheng ','Li ','Sa ','Ban ','Si ','Dang ','Dong ','Guai ','Yi ','Han ','Xie ','Luo ','Liu ','Ham ','Dan ','', + 'Cim ','Tan ','Saang ','','','You ','Nan ','','Gang ','Jun ','Chi ','Kou ','Wan ','Li ','Liu ','Lie ', + 'Xia ','Baai ','An ','Yu ','Ju ','Rou ','Xun ','Zi ','Cuo ','Can ','Zeng ','Yong ','Fu ','Ruan ','Sing ','Xi ', + 'Shu ','Jiao ','Jiao ','Han ','Zhang ','Zong ','','Shui ','Chen ','Fan ','Ji ','Zi ','','Gu ','Wu ','Cui ', + 'Qie ','Shu ','Hoi ','Tuo ','Ru ','Si ','Ran ','Mu ','Fu ','Ling ','Ji ','Xiu ','Xuan ','Nai ','At ','Jie ', + 'Li ','Da ','Ji ','Zyun ','Lu ','Shen ','Li ','Lang ','Geng ','Yin ','Se ','Qin ','Qie ','Che ','You ','Bu ', + 'Huang ','Que ','Lai ','Zaam ','Hong ','Xu ','Bang ','Ke ','Qi ','Gwaai ','Sheng ','Pin ','Gaai ','Zhou ','Huang ','Tui ', + 'Hu ','Bei ','','','Zaa ','Ji ','Gu ','Sai ','Gao ','Chai ','Ma ','Zhu ','Tui ','Tui ','Hem ','Lang ', + 'Baan ','','Zing ','Dai ','Ai ','Xian ','Gwo ','Xi ','Zung ','Tui ','Can ','Sao ','Cim ','Jie ','Fen ','Qun ', + '','Yao ','Dao ','Jia ','Lei ','Yan ','Lu ','Tui ','Ying ','Pi ','Luo ','Li ','Bie ','Hoeng ','Mao ','Bai ', + 'huang ','Dau ','Yao ','He ','Chun ','Hu ','Ning ','Chou ','Li ','Tang ','Huan ','Bi ','Baa ','Che ','Yang ','Da ', + 'Ao ','Xue ','Zi ','','Daap ','Ran ','Bong ','Zao ','Wan ','Ta ','Bao ','Gon ','Yan ','Gaai ','Zhu ','Ya ', + ], + 'x40':[ + 'Fan ','You ','On ','Tui ','Meng ','She ','Jin ','Gu ','Qi ','Qiao ','Jiao ','Yan ','','Kan ','Mian ','Xian ', + 'San ','Na ','Cin ','Huan ','Niu ','Cheng ','Tin ','Jue ','Xi ','Qi ','Ang ','Mei ','Gu ','','Tou ','Fan ', + 'Qu ','Xem ','Shun ','Bi ','Mao ','Shuo ','Gu ','Hong ','Huan ','Luo ','Hang ','Jia ','Quan ','Goi ','Mang ','Bu ', + 'Gu ','Fung ','Mu ','Ai ','Ying ','Shun ','Lang ','Jie ','Di ','Jie ','Cau ','Pin ','Ren ','Yan ','Du ','Di ', + '','Lang ','Xian ','Biu ','Xing ','Bei ','An ','Mi ','Qi ','Qi ','Wo ','She ','Yu ','Jia ','Cheng ','Yao ', + 'Ying ','Yang ','Ji ','Jie ','Han ','Min ','Lou ','Kai ','Yao ','Yan ','Sun ','Coi ','Huang ','Ying ','Sheng ','Cha ', + 'Lian ','','Xuan ','Chuan ','Che ','Ni ','Qu ','Miao ','Huo ','Yu ','Nan ','Hu ','Ceng ','Biu ','Qian ','She ', + 'Jiang ','Ao ','Mai ','Mang ','Zhan ','Bian ','Jiao ','Jue ','Nong ','Bi ','Shi ','Li ','Mo ','Lie ','Mie ','Mo ', + 'Xi ','Chan ','Qu ','Jiao ','Huo ','Zin ','Xu ','Nang ','Tong ','Hou ','Yu ','','Cung ','Bo ','Zuan ','Diu ', + 'Chuo ','Ci ','Jie ','Kwai ','Xing ','Hui ','Shi ','Gwaat6','Caam ','','Yao ','Yu ','Bang ','Jie ','Zhe ','Gaa ', + 'She ','Di ','Dong ','Ci ','Fu ','Min ','Zhen ','Zhen ','','Yan ','Diao ','Hong ','Gong ','Diu6','Lue ','Guai ', + 'La ','Cui ','Fa ','Cuo ','Yan ','Gung ','Jie ','Gwaai ','Guo ','Suo ','Wan ','Zheng ','Nie ','Diao ','Lai ','Ta ', + 'Cui ','Aa ','Gun ','','','Dai ','','Mian ','Gaai ','Min ','Ju ','Yu ','Zan ','Zhao ','Ze ','Saang ', + '','Pan ','He ','Gou ','Hong ','Lao ','Wu ','Chuo ','Hang ','Lu ','Cu ','Lian ','Zi ','Qiao ','Shu ','', + 'xuan ','Cen ','Zaam ','Hui ','Su ','Chuang ','Deon ','Long ','','Nao ','Tan ','Dan ','Wei ','Gan ','Da ','Li ', + 'Caat ','Xian ','Pan ','La ','Zyu ','Niao ','Huai ','Ying ','Xian ','Lan ','Mo ','Ba ','','Fu ','Bi ','Fu ', + ], + 'x41':[ + 'Huo ','Yi ','Liu ','Zoeng ','Zaan ','Juan ','Huo ','Cheng ','Dou ','E ','','Yan ','Zhui ','Du ','Qi ','Yu ', + 'Quan ','Huo ','Nie ','Heng ','Ju ','She ','','','Peng ','Ming ','Cao ','Lou ','Li ','Chun ','','Cui ', + 'Shan ','Daam ','Qi ','','Lai ','Ling ','Liao ','Reng ','Yu ','Nao ','Chuo ','Qi ','Yi ','Nian ','Fu ','Jian ', + 'Ya ','Fong ','Chui ','Cin ','','','Bi ','Dan ','Po ','Nian ','Zhi ','Chao ','Tian ','Tian ','Rou ','Yi ', + 'Lie ','An ','He ','Qiong ','Li ','Gwai ','Zi ','Su ','Yuan ','Ya ','Du ','Wan ','Gyun ','Dong ','You ','Hui ', + 'Jian ','Rui ','Mang ','Ju ','Zi ','Geoi ','An ','Sui ','Lai ','Hun ','Qiang ','Coeng ','Duo ','Hung ','Na ','Can ', + 'Ti ','Xu ','Jiu ','Huang ','Qi ','Jie ','Mao ','Yan ','Heoi ','Zhi ','Tui ','','Ai ','Pang ','Cang ','Tang ', + 'En ','Hun ','Qi ','Chu ','Suo ','Zhuo ','Nou ','Tu ','Zu ','Lou ','Miao ','Li ','Man ','Gu ','Cen ','Hua ', + 'Mei ','Gou ','Lian ','Dao ','Shan ','Ci ','','','Zhi ','Ba ','Cui ','Qiu ','','Long ','Cim ','Fei ', + 'Guo ','Cheng ','Jiu ','E ','Cung ','Jue ','Hong ','Jiao ','Cuan ','Yao ','Tong ','Cha ','You ','Shu ','Yao ','Ge ', + 'Huan ','Lang ','Jue ','Chen ','Cyun ','Cyun ','Shen ','Fo ','Ming ','Ming ','Hung ','Chuang ','Yun ','Han6','Jin ','Chuo ', + 'Zyu ','Tan ','Hong ','Qiong ','','Cheng ','Zaau ','Yu ','Cheng ','Tong ','Pun ','Qiao ','Fo ','Ju ','Lan ','Yi ', + 'Rong ','Si ','Hin ','Si ','Ngat ','Fa ','','Meng ','Gui ','','','Hai ','Qiao ','Chuo ','Que ','Dui ', + 'Li ','Ba ','Jie ','Seoi ','Luo ','Deoi ','Yun ','Zung ','Hu ','Yin ','Pok ','Zhi ','Lian ','Zim ','Gan ','Jian ', + 'Zhou ','Zhu ','Ku ','Na ','Dui ','Ze ','Yang ','Zhu ','Gong ','Yi ','Ci ','Gei ','Chuang ','Lao ','Ren ','Rong ', + 'Zing ','Na ','Ce ','Zin ','','Yi ','Jue ','Bi ','Cheng ','Jun ','Chou ','Hui ','Chi ','Zhi ','Yan ','', + ], + 'x42':[ + 'Saan ','Lun ','Bing ','Zhao ','Han ','Yu ','Dai ','Zhao ','Fei ','Sha ','Ling ','Ta ','Zeoi ','Mang ','Ye ','Bao ', + 'Kui ','Gua ','Nan ','Ge ','Gaa ','Chi ','Fo ','Suo ','Ci ','Zhou ','Tai ','Kuai ','Qin ','Seoi ','Du ','Ce ', + 'Huan ','Gung ','Sai ','Zheng ','Qian ','Gan ','Zung ','Wei ','','','Xi ','Nap ','Pu ','Huai ','Ju ','Zaan ', + 'Sau ','Tou ','Pan ','Ta ','Qian ','Zung ','Rong ','Luo ','Hu ','Sou ','Zung ','Pu ','Mie ','Gan ','Shuo ','Mai ', + 'Shu ','Ling ','Lei ','Jiang ','Leng ','Zhi ','Diao ','','San ','Hu ','Fan ','Mei ','Sui ','Jian ','Tang ','Xie ', + 'Fu ','Mo ','Fan ','Lei ','Can ','Ceng ','Ling ','Zaap ','Cong ','Yun ','Meng ','Yu ','Zhi ','Qi ','Dan ','Huo ', + 'Wei ','Tan ','Se ','Xie ','Sou ','Song ','Cin ','Liu ','Yi ','Aau ','Lei ','Li ','Fei ','Lie ','Lin ','Xian ', + 'Yao ','Aau ','Bie ','Xian ','Rang ','Zhuan ','Soeng ','Dan ','Bian ','Ling ','Hong ','Qi ','Liao ','Ban ','Mi ','Hu ', + 'Hu ','Caap ','Ce ','Pei ','Qiong ','Ming ','Jiu ','Bu ','Mei ','San ','Mei ','Zong ','','Li ','Quan ','Sam ', + 'En ','Xiang ','Zing ','Shi ','Zing ','Gin ','Lan ','Huang ','Jiu ','Yan ','Deoi ','Sa ','Tuan ','Xie ','Zhe ','Men ', + 'Xi ','Man ','Zoeng ','Huang ','Tan ','Xiao ','Ya ','Bi ','Luo ','Fan ','Li ','Cui ','Cha ','Chou ','Di ','Kuang ', + 'Chu ','Cim ','Chan ','Mi ','Qian ','Qiu ','Zhen ','Chai ','Heoi ','Cim ','Gu ','Yan ','Chi ','Guai ','Mu ','Bo ', + 'Kua ','Geng ','Yao ','Mao ','Wang ','','','','Ru ','Jue ','Zing ','Min ','Jiang ','O ','Zhan ','Zuo ', + 'Yue ','Bing ','Nou6','Zhou ','Bi ','Ren ','Luot ','Gin ','Chuo ','Er ','Yi ','Mi ','Qing ','Zing ','Wang ','Ji ', + 'Bu ','Syu ','Bie ','Fan ','Yao ','Luoi ','Moi ','Qu ','Fu ','Er ','O ','Zang ','Zim ','Huo ','Jin ','Qi ', + 'Ju ','Lai ','Che ','Bei ','Niu ','Yi ','Xu ','Liu ','Xun ','Fu ','Cau ','Nin ','Ting ','Beng ','Zha ','Wui ', + ], + 'x43':[ + 'Fo ','Zaau ','Ou ','Shuo ','Geng ','Tang ','Gui ','Hui ','Ta ','Gong ','Yao ','Daap ','Qi ','Han ','Lue ','Mi ', + 'Mi ','Gin ','Lu ','Fan ','Ou ','Mi ','Jie ','Fu ','Mi ','Huang ','Su ','Yao ','Nie ','Jin ','Lian ','Bi ', + 'Qing ','Ti ','Ling ','Zuan ','Zhi ','Yin ','Dao ','Chou ','Cai ','Mi ','Yan ','Lan ','Chong ','Ziu ','Soeng ','Guan ', + 'She ','Luo ','Fan ','Si ','Luo ','Zhu ','Zi ','Chou ','Juan ','Jiong ','Er ','Yi ','Rui ','Cai ','Ren ','Fu ', + 'Lan ','Sui ','Yu ','Yao ','Dian ','Ling ','Zhu ','Ta ','Ping ','Qian ','Jue ','Chui ','Bu ','Gu ','Cun ','', + 'Han ','Han ','Mou ','Hu ','Hong ','Di ','Fu ','Xuan ','Mi ','Mei ','Lang ','Gu ','Zhao ','Ta ','Yu ','Zong ', + 'Li ','Liao ','Wu ','Lei ','Ji ','Lei ','Li ','Zong ','Bo ','Ang ','Kui ','Tuo ','Ping ','Cau ','Zhao ','Gui ', + 'Zaan ','Xu ','Nai ','Chuo ','Duo ','Kaap ','Dong ','Gui ','Bo ','Zin ','Huan ','Xuan ','Can ','Li ','Tui ','Huang ', + 'Xue ','Hu ','Bao ','Ran ','Tiao ','Fu ','Liao ','Zaau ','Yi ','Shu ','Po ','He ','Cu ','Fu ','Na ','An ', + 'Chao ','Lu ','Zhan ','Ta ','Fu ','Gwaang ','Zang ','Qiao ','Su ','Baan ','Guan ','','Fan ','Chu ','','Er ', + 'Er ','Nuan ','Qi ','Si ','Chu ','','Yan ','Bang ','An ','Zi ','Ne ','Chuang ','Ba ','Ciu ','Ti ','Han ', + 'Zuo ','Ba ','Zhe ','Wa ','Sheng ','Bi ','Er ','Zhu ','Wu ','Wen ','Zhi ','Zhou ','Lu ','Wen ','Gun ','Qiu ', + 'La ','Zai ','Sou ','Mian ','Zhi ','Qi ','Cao ','Piao ','Lian ','Saap ','Long ','Su ','Qi ','Yuan ','Feng ','Heoi ', + 'Jue ','Di ','Pian ','Guan ','Niu ','Ren ','Zhen ','Gai ','Pi ','Tan ','Chao ','Chun ','Ho ','Chun ','Mo ','Bie ', + 'Qi ','Shi ','Bi ','Jue ','Si ','Taam ','Hua ','Da ','Hui ','Kaap ','Er ','Caau ','Mou ','Zyu ','Xi ','Zhi ', + 'Ren ','Ju ','Die ','Zhe ','Teo ','Meng ','Bi ','Han ','Yu ','Xian ','Pong ','Neng ','Can ','Bu ','Bong ','Qi ', + ], + 'x44':[ + 'Ji ','Niao ','Lu ','Jiong ','Han ','Yi ','Cai ','Chun ','Zhi ','Zi ','Da ','Cung ','Tian ','Zhou ','Daai ','Chun ', + 'Cau ','Zhe ','Zaa ','Rou ','Bin ','Ji ','Yi ','Du ','Jue ','Ge ','Ji ','Dap ','Can ','Suo ','Ruo ','Xiang ', + 'Huang ','Qi ','Zhu ','Cuo ','Chi ','Weng ','Haap6','Kao ','Gu ','Kai ','Fan ','Sung ','Cao ','Zhi ','Chan ','Lei ', + 'Gaau ','Zak6','Zhe ','Yu ','Gui ','Huang ','Jin ','Daan ','Guo ','Sao ','Tan ','','Xi ','Man ','Duo ','Ao ', + 'Pi ','Wu ','Ai ','Meng ','Pi ','Meng ','Yang ','Zhi ','Bo ','Ying ','Wei ','Nao ','Lan ','Yan ','Chan ','Quan ', + 'Zhen ','Pu ','','Tai ','Fei ','Shu ','','Dang ','Cha ','Ran ','Tian ','Chi ','Ta ','Jia ','Shun ','Huang ', + 'Liao ','Caa ','Dou ','','Jin ','E ','Keoi ','Fu ','Duo ','','E ','','Yao ','Di ','','Di ', + 'Bu ','Man ','Che ','Lun ','Qi ','Mu ','Can ','','Zung ','Sau ','Fan ','You ','Saau ','Da ','','Su ', + 'Fu ','Ji ','Jiang ','Cao ','Bo ','Teng ','Che ','Fu ','Bu ','Wu ','Haai ','Yang ','Ming ','Pang ','Mang ','Zang ', + 'Meng ','Cao ','Tiao ','Kai ','Bai ','Xiao ','Xin ','Qi ','Seoi ','','Shao ','Heng ','Ngau ','Xiao ','Chen ','Daan ', + 'Fan ','Yin ','Ang ','Ran ','Ri ','Fa ','Fan ','Qu ','Shi ','He ','Bian ','Dai ','Mo ','Deng ','','', + 'Hong ','Zing ','Cha ','Duo ','You ','Hao ','Tin ','Kut ','Xian ','Lei ','Jin ','Qi ','','Mei ','Zi ','', + '','','Yan ','Yi ','Yin ','Qi ','Zhe ','Xi ','Yi ','Ye ','E ','','Zhi ','Han ','Chuo ','', + 'Chun ','Bing ','Kuai ','Chou ','','Tuo ','Qiong ','Cung ','Jiu ','Gwai ','Cu ','Fu ','','Meng ','Li ','Lie ', + 'Ta ','Zi ','Gu ','Liang ','Fat ','La ','Dian ','Ci ','Aang ','','','Ji ','','Cha ','Mao ','Du ', + 'Zaan ','Chai ','Rui ','Hen ','Ruan ','','Lai ','Xing ','Gan ','Yi ','Mei ','','He ','Ji ','So ','Han ', + ], + 'x45':[ + 'Seoi ','Li ','Zi ','Zu ','Yao ','Geoi ','Li ','Qi ','Gan ','Li ','','','','','Su ','Chou ', + '','Xie ','Bei ','Xu ','Jing ','Pu ','Ling ','Xiang ','Zuo ','Diao ','Chun ','Qing ','Nan ','','Lu ','Chi ', + 'Shao ','Yu ','Hua ','Li ','','Siu ','','Li ','','','Dui ','','Yi ','Ning ','Si ','Hu ', + 'Fu ','Zaap ','Cheng ','Nan ','Ce ','Gaan ','Ti ','Qin ','Biao ','Sui ','Wei ','Deon ','Se ','Ai ','E ','Jie ', + 'Kuan ','Fei ','','Yin ','Zing ','Sao ','Dou ','Hui ','Xie ','Ze ','Tan ','Chang ','Zhi ','Yi ','Fu ','E ', + '','Jun ','Gaa ','Cha ','Xian ','Man ','Syun ','Bi ','Ling ','Jie ','Kui ','Jia ','','Sang ','Lang ','Guk ', + 'Fei ','Lu ','Zha ','He ','','Ni ','Ying ','Xiao ','Teng ','Lao ','Ze ','Kui ','Goeng ','Qian ','Ju ','Piao ', + 'Ban ','Dou ','Lin ','Mi ','Zhuo ','Xie ','Hu ','Mi ','Gaai ','Za ','Cong ','Ge ','Nan ','Zhu ','Yan ','Han ', + 'Ceoi ','Yi ','Luan ','Yue ','Ran ','Ling ','Niang ','Yu ','Nue ','Heoi ','Yi ','Nue ','Qin ','Qian ','Xia ','Chu ', + 'Jin ','Mi ','','Na ','Han ','Zu ','Xia ','Yan ','Tu ','','Wu ','Suo ','Yin ','Chong ','Zhou ','Mang ', + 'Yuan ','Nu ','Miao ','Sao ','Wan ','Li ','','Na ','Shi ','Bi ','Ci ','Bang ','','Juan ','Xiang ','Gui ', + 'Pai ','Hong ','Xun ','Zha ','Yao ','Kwan ','','He ','E ','Yang ','Tiao ','You ','Jue ','Li ','','Li ', + '','Ji ','Hu ','Zhan ','Fu ','Chang ','Guan ','Ju ','Meng ','Coeng ','Cheng ','Mou ','Sing ','Li ','Zaan ','', + 'Si ','Yi ','Bing ','Cung ','Hou ','Wan ','Chi ','','Ge ','Han ','Bo ','Saau ','Liu ','Can ','Can ','Yi ', + 'Xuan ','Yan ','Suo ','Gao ','Yong ','Zung ','Fung ','Hong ','Yu ','Cik ','Zhe ','Ma ','Fung ','','Shuang ','Jin ', + 'Guan ','Pu ','Lin ','','Ting ','Goeng ','La ','Yi ','Zung ','Ci ','Yan ','Jie ','Faan ','Wei ','Xian ','Ning ', + ], + 'x46':[ + 'Fu ','Ge ','','Mo ','Fu ','Nai ','Xian ','Wen ','Li ','Can ','Mie ','','Ni ','Chai ','Wan ','Xu ', + 'Nu ','Mai ','Co ','Kan ','Ho ','Hang ','','Faai ','Yu ','Wei ','Zhu ','Gei ','Gan ','Yi ','','', + 'Fu ','Bi ','Zhu ','Zi ','Shu ','Xia ','Ni ','','Jiao ','Xuan ','Cung ','Nou ','Rong ','Die ','Sa ','Sau ', + '','Yu ','','Kaam ','Zung ','Lu ','Han ','','Yi ','Zui ','Zhan ','Su ','Wan ','Ni ','Guan ','Jue ', + 'Beng ','Can ','Zung ','Duo ','Qi ','Yao ','Gui ','Nuan ','Hou ','Xun ','Xie ','','Hui ','','Xie ','Bo ', + 'Ke ','Ceoi ','Xu ','Bai ','Aau ','Chu ','Bang ','Ti ','Chu ','Chi ','Niao ','Guan ','Feng ','Xie ','Dang ','Duo ', + 'Jue ','Hui ','Zeng ','Sa ','Duo ','Ling ','Meng ','Fan ','Guo ','Meng ','Long ','','Ying ','Hin ','Guan ','Cu ', + 'Li ','Du ','Ceng ','E ','Sin ','Saai ','','De ','De ','Jiang ','Lian ','','Shao ','Xi ','Si ','Wei ', + '','','He ','You ','Lu ','Lai ','Ou ','Sheng ','Juan ','Qi ','','Yun ','','Qi ','Zong ','Leng ', + 'Ji ','Mai ','Chuang ','Nian ','Baan ','Li ','Ling ','Gong ','Chen ','','Xian ','Hu ','Bei ','Zu ','Dai ','Dai ', + 'Hun ','Soi ','Che ','Ti ','','Nuo ','Zhi ','Liu ','Fei ','Jiao ','Gwaan ','Ao ','Lin ','','Reng ','Tao ', + 'Pi ','Xin ','Shan ','Xie ','Wa ','Tao ','Tin ','Xi ','Xie ','Pi ','Yao ','Yao ','Nu ','Hao ','Nin ','Yin ', + 'Fan ','Nan ','Chi ','Wang ','Yuan ','Xia ','Zhou ','Yuan ','Shi ','Mi ','','Ge ','Pao ','Fei ','Hu ','Ni ', + 'Ci ','Mi ','Bian ','Gam ','Na ','Yu ','E ','Zhi ','Nin ','Xu ','Lue ','Hui ','Xun ','Nao ','Han ','Jia ', + 'Dou ','Hua ','Tuk ','','Cu ','Xi ','Song ','Mi ','Xin ','Wu ','Qiong ','Zheng ','Chou ','Xing ','Jiu ','Ju ', + 'Hun ','Ti ','Man ','Jian ','Qi ','Shou ','Lei ','Wan ','Che ','Can ','Jie ','You ','Hui ','Zha ','Su ','Ge ', + ], + 'x47':[ + 'Nao ','Xi ','','Deoi ','Chi ','Wei ','Mo ','Gun ','Cau ','','Zao ','Hui ','Luan ','Liao ','Lao ','', + '','Qia ','Ao ','Nie ','Sui ','Mai ','Tan ','Xin ','Jing ','An ','Ta ','Chan ','Wei ','Tuan ','Ji ','Chen ', + 'Che ','Xu ','Xian ','Xin ','','Daan ','','Nao ','','Yan ','Qiu ','Hong ','Song ','Jun ','Liao ','Ju ', + '','Man ','Lie ','','Chu ','Chi ','Xiang ','Cam ','Mei ','Shu ','Ce ','Chi ','Gu ','Yu ','Zaam ','', + 'Liao ','Lao ','Shu ','Zhe ','Soeng ','','Fat ','Fui ','E ','','Sha ','Zong ','Jue ','Jun ','','Lou ', + 'Wei ','Cung ','Zhu ','La ','Fun ','Zhe ','Zhao ','Zaau ','Yi ','','Ni ','Bo ','Syun ','Yi ','Hao ','Ya ', + 'Huan ','Man ','Man ','Qu ','Lao ','Hao ','','Men ','Xian ','Zhen ','Shu ','Zuo ','Zhu ','Gou ','Xuan ','Yi ', + 'Ti ','xie ','Jin ','Can ','Zai ','Bu ','Liang ','Zhi ','Ji ','Wan ','Guan ','Ceoi ','Qing ','Ai ','Fu ','Gui ', + 'Gou ','Xian ','Ruan ','Zhi ','Biao ','Yi ','Suo ','Die ','Gui ','Sheng ','Xun ','Chen ','She ','Qing ','','', + 'Chun ','Hong ','Dong ','Cheng ','Wei ','Die ','Shu ','Caai ','Ji ','Za ','Qi ','','Fu ','Ao ','Fu ','Po ', + '','Tan ','Zha ','Che ','Qu ','You ','He ','Hou ','Gui ','E ','Jiang ','Yun ','Tou ','Qiu ','','Fu ', + 'Zuo ','Hu ','','Bo ','','Jue ','Di ','Jue ','Fu ','Huang ','','Yong ','Chui ','Suo ','Chi ','Hin ', + '','','Man ','Ca ','Qi ','Jian ','Bi ','Gei ','Zhi ','Zhu ','Qu ','Zhan ','Ji ','Dian ','','Li ', + 'Li ','La ','Quan ','Ding ','Fu ','Cha ','Tang ','Shi ','Hang ','Qie ','Qi ','Bo ','Na ','Tou ','Chu ','Cu ', + 'Yue ','Di ','Chen ','Chu ','Bi ','Mang ','Ba ','Tian ','Min ','Lie ','Feng ','Caang ','Kheo ','Tiao ','Fu ','Kuo ', + 'Jian ','Ci ','','','Zhen ','Qiu ','Cuo ','Chi ','Kui ','Lie ','Bang ','Du ','Wu ','So ','Jue ','Lu ', + ], + 'x48':[ + 'Chang ','Zai ','Chu ','Liang ','Tian ','Kun ','Chang ','Jue ','Tu ','Hua ','Fei ','Bi ','','Qia ','Wo ','Ji ', + 'Qu ','Kui ','Hu ','Cu ','Sui ','','','Qiu ','Pi ','Bei ','Wa ','Jiao ','Rong ','','Cu ','Die ', + 'Chi ','Cuo ','Meng ','Xuan ','Duo ','Bie ','Zhe ','Chu ','Chan ','Gui ','Duan ','Zou ','Deng ','Lai ','Teng ','Yue ', + 'Quan ','Shu ','Ling ','','Qin ','Fu ','She ','Tiao ','','Ai ','','Qiong ','Diao ','Hai ','Shan ','Wai ', + 'Zhan ','Long ','Jiu ','Li ','','Min ','Rong ','Yue ','Jue ','Kang ','Fan ','Qi ','Hong ','Fu ','Lu ','Hong ', + 'Tuo ','Min ','Tian ','Juan ','Qi ','Zheng ','Jing ','Gong ','Tian ','Lang ','Mao ','Yin ','Lu ','Yun ','Ju ','Pi ', + '','Xie ','Bian ','','Zeoi ','Rong ','Sang ','Wu ','Cha ','Gu ','Chan ','Peng ','Man ','Saau ','Zung ','Shuang ', + 'Keng ','Zhuan ','Chan ','Si ','Chuang ','Sui ','Bei ','Kai ','','Zhi ','Wei ','Min ','Ling ','','Nei ','Ling ', + 'Qi ','Yue ','Lip ','Yi ','Xi ','Chen ','','Rong ','Chen ','Nong ','You ','Ji ','Bo ','Fang ','Gei ','', + 'Cu ','Di ','Gaau ','Yu ','Ge ','Xu ','Lu ','He ','','Bai ','Gong ','Jiong ','Gwai ','Ya ','Nu ','You ', + 'Song ','Xie ','Cang ','Yao ','Shu ','Yan ','Suot ','Liao ','Sung ','Yu ','Bo ','Sui ','Cin ','Yan ','Lei ','Lin ', + 'Tai ','Du ','Yue ','Ji ','Cin ','Yun ','Bong ','','','Ju ','Ceot ','Chen ','Cung ','Xiang ','Xian ','On ', + 'Gui ','Yu ','Lei ','','Tu ','Chen ','Xing ','Qiu ','Hang ','','Dang ','Cai ','Di ','Yan ','Ci ','Gung ', + 'Zing ','Chan ','','Li ','Suo ','Ma ','Ma ','','Tang ','Pei ','Lou ','Sat ','Cuo ','Tu ','E ','Can ', + 'Jie ','Ti ','Ji ','Dang ','Jiao ','Bi ','Lei ','Yi ','Chun ','Chun ','Po ','Li ','Zai ','Tai ','Po ','Tian ', + 'Ju ','Xu ','Fan ','','Xu ','Er ','Huo ','Chua ','Ran ','Fa ','Gyun ','','Liang ','Ti ','Mi ','', + ], + 'x49':[ + '','Cen ','Mei ','Yin ','Mian ','Tu ','Kui ','Sau ','Hei ','Mi ','Rong ','Guo ','Coeng ','Mi ','Ju ','Pi ', + 'Jin ','Wang ','Ji ','Meng ','Jian ','Xue ','Bao ','Gan ','Chan ','Li ','Li ','Qiu ','Dun ','Ying ','Yun ','Chen ', + 'Ji ','Ran ','','Lue ','','Gui ','Yue ','Hui ','Pi ','Cha ','Duo ','Chan ','So ','Kuan ','She ','Xing ', + 'Weng ','Shi ','Chi ','Ye ','Han ','Fei ','Ye ','Yan ','Zuan ','Saau ','Yin ','Duo ','Xian ','Gwaan ','Tou ','Qie ', + 'Chan ','Han ','Meng ','Yue ','Cu ','Qian ','Jin ','Shan ','Mu ','Zyun ','Coeng ','Baang ','Zheng ','Zhi ','Chun ','Yu ', + 'Mou ','Wan ','Chou ','Kei ','Su ','Pie ','Tian ','Kuan ','Cu ','Sui ','Co ','Jie ','Jian ','Ao ','Jiao ','Ye ', + 'Saam ','Ye ','Long ','Zao ','Bao ','Lian ','','Huan ','Lu ','Wei ','Xian ','Tie ','Bo ','Zheng ','Zhu ','Ba ', + 'Meng ','Xie ','Aau ','Zaau ','Teon ','Xiao ','Li ','Zha ','Mi ','','Ye ','','','Put ','Xie ','', + '','Bong ','Shan ','Coeng ','','Shan ','Jue ','Ji ','Fang ','','Niao ','Ao ','Chu ','Wu ','Guan ','Xie ', + 'Ting ','Xie ','Dang ','Zim ','Tan ','Ping ','Xia ','Xu ','Bi ','Si ','Huo ','Zheng ','Wu ','','Run ','Chuai ', + 'Shi ','Huan ','Kuo ','Fu ','Chuai ','Xian ','Qin ','Qie ','Lan ','','Ya ','Zing ','Que ','','Chun ','Zhi ', + 'Gau ','Kui ','Qian ','Hang ','Yi ','Ni ','Zheng ','Chuai ','','Shi ','Cap ','Ci ','Jue ','Xu ','Yun ','', + '','Chu ','Dao ','Dian ','Ge ','Ti ','Hong ','Ni ','','Li ','','Xian ','Seoi ','Xi ','Xuan ','', + 'Gwik ','Taai ','Lai ','Zau ','Mu ','Cheng ','Jian ','Bi ','Qi ','Ling ','Hao ','Bang ','Tang ','Di ','Fu ','Xian ', + 'Shuan ','Zung ','Keoi ','Zaan ','Pu ','Hui ','Wei ','Yi ','Ye ','','Che ','Hao ','Baai ','','Xian ','Chan ', + 'Hun ','Gaau ','Han ','Ci ','Zi ','Qi ','Kui ','Rou ','Gu ','Zing ','Xiong ','Gap ','Hu ','Cui ','Syu ','Que ', + ], + 'x4a':[ + 'Di ','Che ','Cau ','','Yan ','Liao ','Bi ','Soeng ','Ban ','Zing ','','Nue ','Bao ','Ying ','Hong ','Ci ', + 'Qia ','Ti ','Yu ','Lei ','Bao ','Wu ','Ji ','Fu ','Xian ','Cen ','Fat ','Se ','Baang ','Cing ','Yu ','Waa ', + 'Ai ','Han ','Dan ','Ge ','Di ','Hu ','Pang ','Zaam ','Zaa ','Ling ','Mai ','Mai ','Lian ','Siu ','Xue ','Zhen ', + 'Po ','Fu ','Nou ','Xi ','Dui ','Dan ','Yun ','Xian ','Yin ','Suk ','Dui ','Beng ','Hu ','Fei ','Fei ','Qian ', + 'Bei ','Fei ','','Shi ','Tian ','Zhan ','Jian ','','Hui ','Fu ','Wan ','Mo ','Qiao ','Liao ','','Mie ', + 'Ge ','Hong ','Yu ','Qi ','Duo ','Ang ','Saa ','Ba ','Di ','Xuan ','Di ','Bi ','Zhou ','Pao ','Nian ','Yi ', + 'Ting ','Jia ','Da ','Duo ','Xi ','Dan ','Tiao ','Xie ','Chang ','Yuan ','Guan ','Liang ','Beng ','Gei ','Lu ','Ji ', + 'Xuan ','Shu ','Dou ','Shu ','Hu ','Yun ','Chan ','Bong ','Rong ','E ','Zung ','Ba ','Feng ','Zyu ','Zhe ','Fen ', + 'Guan ','Bu ','Ge ','Deon ','Huang ','Du ','Ti ','Bo ','Qian ','La ','Long ','Wei ','Zhan ','Lan ','Seoi ','Na ', + 'Bi ','Tuo ','Jiao ','','Bu ','Ju ','Po ','Xia ','Wei ','Fu ','He ','Fan ','Chan ','Hu ','Za ','', + 'Saai ','Zai ','Zai ','Zai ','Fan ','Die ','Hong ','Chi ','Bao ','Yin ','','Haang ','Bo ','Ruan ','Chou ','Ying ', + 'Zi ','Gai ','Kwaan ','Yun ','Zhen ','Ya ','Zeoi ','Hou ','Min ','Pei ','Ge ','Bian ','Zyut ','Hao ','Mi ','Sheng ', + 'Gen ','Bi ','Duo ','Chun ','Chua ','San ','Cheng ','Ran ','Zen ','Mao ','Bo ','Tui ','Pi ','Fu ','Zyut ','Hei ', + 'Lin ','Hei ','Men ','Wu ','Qi ','Zhi ','Chen ','Xia ','He ','Sang ','Gwaa ','Hou ','Au ','Fu ','Rao ','Hun ', + 'Pei ','Qian ','Si ','Xi ','Ming ','Kui ','Ge ','','Ao ','San ','Shuang ','Lou ','Zhen ','Hui ','Can ','Ci ', + 'Lin ','Na ','Han ','Du ','Jin ','Mian ','Fan ','E ','Nao ','Hong ','Hong ','Xue ','Xue ','Pau ','Bi ','Ciu ', + ], + 'x4b':[ + 'You ','Yi ','Xue ','Sa ','Yu ','Li ','Li ','Yuan ','Dui ','Hao ','Qie ','Leng ','Paau ','Fat ','Guo ','Bu ', + 'Wei ','Wei ','Saau ','An ','Xu ','Shang ','Heng ','Yang ','Gwik ','Yao ','Fan ','Bi ','Ci ','Heng ','Tao ','Liu ', + 'Fei ','Zhu ','Tou ','Qi ','Chao ','Yi ','Dou ','Yuan ','Cu ','Zai ','Bo ','Can ','Yang ','Tou ','Yi ','Nian ', + 'Shao ','Ben ','Ngaau ','Ban ','Mo ','Ai ','En ','She ','Caan ','Zhi ','Yang ','Jian ','Yuan ','Dui ','Ti ','Wei ', + 'Xun ','Zhi ','Yi ','Ren ','Shi ','Hu ','Ne ','Yi ','Jian ','Sui ','Ying ','Bao ','Hu ','Hu ','Xie ','', + 'Yang ','Lian ','Sik ','En ','Deoi ','Jian ','Zhu ','Ying ','Yan ','Jin ','Chuang ','Dan ','','Kuai ','Yi ','Ye ', + 'Jian ','En ','Ning ','Ci ','Qian ','Xue ','Bo ','Mi ','Shui ','Mi ','Liang ','Qi ','Qi ','Shou ','Bi ','Bo ', + 'Beng ','Bie ','Ni ','Wei ','Huan ','Fan ','Qi ','Liu ','Fu ','Ang ','Ang ','Fan ','Qi ','Qun ','Tuo ','Yi ', + 'Bo ','Pian ','Bo ','Keoi ','Xuan ','','Baai6','Yu ','Chi ','Lu ','Yi ','Li ','Zaau ','Niao ','Xi ','Wu ', + 'Gwing ','Lei ','Pei ','Zhao ','Zui ','Chuo ','Coeng ','An ','Er ','Yu ','Leng ','Fu ','Sha ','Huan ','Chu ','Sou ', + 'Bik ','Bi ','Die ','Song ','Di ','Li ','Giu ','Han ','Zai ','Gu ','Cheng ','Lou ','Mo ','Mi ','Mai ','Ao ', + 'Dan ','Zhu ','Huang ','Fan ','Deng ','Tong ','','Du ','Hu ','Wei ','Ji ','Chi ','Lin ','Biu ','Pang ','Jian ', + 'Nie ','Luo ','Ji ','Ngon ','Waa ','Nie ','Yi ','Gwaat6','Wan ','Ya ','Qia ','Bo ','Hau ','Ling ','Gan ','Huo ', + 'Hai ','Hong ','Heng ','Kui ','Cen ','Ting ','Lang ','Bi ','Huan ','Po ','Ou ','Jian ','Ti ','Sui ','Kwaa ','Dui ', + 'Ao ','Jian ','Mo ','Gui ','Kuai ','An ','Ma ','Qing ','Fen ','','Kao ','Hao ','Duo ','Cim ','Nai ','Seoi ', + 'Jie ','Fu ','Pa ','Sung ','Chang ','Nie ','Man ','Sung ','Ci ','Cim ','Kuo ','Gai ','Di ','Fu ','Tiao ','Zu ', + ], + 'x4c':[ + 'Wo ','Fei ','Cai ','Peng ','Shi ','Sou ','Rou ','Qi ','Cha ','Pan ','Bo ','Man ','Zong ','Ci ','Gui ','Ji ', + 'Lan ','Siu ','Meng ','Mian ','Pan ','Lu ','Cuan ','Gau ','Liu ','Yi ','Wen ','Li ','Li ','Zeng ','Zhu ','Hun ', + 'Shen ','Chi ','Xing ','Wang ','Dung ','Huo ','Pi ','Bou6','Mei ','Che ','Mei ','Chao ','Ju ','Nou ','','Ni ', + 'Ru ','Ling ','Ya ','','Qi ','Zi ','','Bang ','Gung ','Ze ','Jie ','Yu ','Xin ','Bei ','Ba ','Tuo ', + 'Ong ','Qiao ','You ','Di ','Jie ','Mo ','Sheng ','Shan ','Qi ','Shan ','Mi ','Dan ','Yi ','Geng ','Geng ','Tou ', + 'Fu ','Xue ','Yi ','Ting ','Tiao ','Mou ','Liu ','Caan ','Li ','Suk ','Lu ','Xu ','Cuo ','Ba ','Liu ','Ju ', + 'Zhan ','Ju ','Zang ','Zu ','Xian ','Zhi ','','','Zhi ','','','La ','Seoi ','Geng ','E ','Mu ', + 'Zhong ','Di ','Yan ','Zin ','Geng ','Zung ','Lang ','Yu ','Caau ','Na ','Hai ','Hua ','Zhan ','Coeng ','Lou ','Chan ', + 'Die ','Wei ','Xuan ','Zao ','Min ','Kwai ','Sou ','','','Si ','Tuo ','Cen ','Kuan ','Teng ','Nei ','Lao ', + 'Lu ','Yi ','Xie ','Yan ','Qing ','Pu ','Chou ','Xian ','Guan ','Jie ','Lai ','Meng ','Ye ','Ceoi ','Li ','Yin ', + 'Ceon ','Cau ','Teng ','Yu ','','Gau ','Cha ','Du ','Hong ','Si ','Xi ','Gaau ','Qi ','Ci ','Yuan ','Ji ', + 'Yun ','Fang ','Gung ','Hang ','Zhen ','Hu ','','','Jie ','Pei ','Gan ','Xuan ','Saang ','Dao ','Qiao ','Ci ', + 'Die ','Ba ','Tiao ','Wan ','Ci ','Zhi ','Bai ','Wu ','Bao ','Dan ','Ba ','Tong ','Gyun ','Gung ','Jiu ','Gui ', + 'Ci ','You ','Yuan ','Lao ','Jiu ','Fou ','Nei ','E ','E ','Xing ','He ','Yan ','Tu ','Bu ','Beng ','Kou ', + 'Chui ','Zeoi ','Qi ','Yuan ','Bit ','','Hyun ','Hou ','Huang ','Ziu ','Juan ','Kui ','E ','Ji ','Mo ','Chong ', + 'Bao ','Vo ','Zhen ','Xu ','Da ','Chi ','Gaai ','Cong ','Ma ','Kou ','Yan ','Can ','Aau ','He ','Dang ','Lan ', + ], + 'x4d':[ + 'Tong ','Yu ','Hang ','Nao ','Li ','Fen ','Pu ','Ling ','Ao ','Xuan ','Yi ','Xuan ','Meng ','Ang ','Lei ','Yan ', + 'Bao ','Die ','Ling ','Shi ','Jiao ','Lie ','Jing ','Ju ','Ti ','Pi ','Gang ','Jiao ','Huai ','Bu ','Di ','Huan ', + 'Yao ','Li ','Mi ','Fu ','Saang ','Gaa ','Ren ','Wai ','','Piao ','Lu ','Ling ','Yi ','Cai ','Shan ','Fat ', + 'Shu ','Tuo ','Mo ','He ','Tie ','Bing ','Peng ','Hun ','Fu ','Guo ','Bu ','Li ','Chan ','Bai ','Cuo ','Meng ', + 'Suo ','Qiang ','Zhi ','Kuang ','Bi ','Ao ','Meng ','Xian ','Guk ','Tou ','Teon ','Wei ','Cim ','Tan ','Caau ','Lao ', + 'Chan ','Ni ','Ni ','Li ','Dong ','Ju ','Jian ','Fu ','Sha ','Zha ','Tao ','Jian ','Nong ','Ya ','Jing ','Gan ', + 'Di ','Jian ','Mei ','Da ','Jian ','She ','Xie ','Zai ','Mang ','Li ','Gun ','Yu ','Ta ','Zhe ','Yang ','Tuan ', + 'Soeng ','He ','Diao ','Wei ','Yun ','Zha ','Qu ','Waa ','Caau ','Zi ','Ting ','Gu ','Soeng ','Ca ','Fu ','Tie ', + 'Ta ','Ta ','Zhuo ','Han ','Ping ','He ','Ceoi ','Zhou ','Bo ','Liu ','Nu ','Kaap ','Pao ','Di ','Sha ','Ti ', + 'Kuai ','Ti ','Qi ','Ji ','Chi ','Pa ','Jin ','Ke ','Li ','Ju ','Qu ','La ','Gu ','Qia ','Qi ','Xian ', + 'Jian ','Shi ','Xian ','Ai ','Hua ','Ju ','Ze ','Yao ','Tam ','Ji ','Cha ','Kan ','Gin ','','Yan ','Gwaai ', + 'Ziu ','Tong ','Nan ','Yue ','Ceoi ','Chi ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x4e':[ + 'Nhat ','Ding ','Kao ','That ','Shang ','Xia ','','Wan ','Zhang ','Tam ','Shang ','Xia ','Ji ','Bat ','Yu ','Mian ', + 'Gai ','Suu ','Chou ','Zhuan ','Qie ','Pi ','Shi ','Shi ','Khau ','Bing ','Ye ','Cong ','Dong ','Si ','Cheng ','Diu ', + 'Qiu ','Liang ','Diu ','You ','Liang ','Yan ','Bing ','Sang ','Gun ','Jiu ','Ge ','A ','Qiang ','Trung ','Ji ','Jie ', + 'Phong ','Guan ','Chuan ','Chan ','Lin ','Zhuo ','Zhu ','Ha ','Hoan ','Dan ','Wei ','Chua ','Jing ','Li ','Ju ','Pie ', + 'Fu ','Yi ','Yi ','Nai ','Shime ','Cuu ','Jiu ','Zhe ','Yao ','Yi ','','Chi ','Wu ','Zha ','Hu ','Fa ', + 'Le ','Zhong ','Ping ','Pang ','Qiao ','Hu ','Quai ','Cheng ','Cheng ','Yi ','Yin ','','Mie ','Cuu ','Khat ','Ye ', + 'Xi ','Xiang ','Gai ','Jiu ','Hal ','','Shu ','Twul ','Shi ','Ji ','Nang ','Jia ','Kel ','Shi ','','Ol ', + 'Mai ','Luan ','Cal ','Vu ','Xue ','Yan ','Fu ','Sha ','Na ','Gan ','Sol ','El ','Cwul ','','Gan ','Chi ', + 'Gui ','Gan ','Luan ','Lin ','Yi ','Jue ','Le ','Ma ','Yu ','Zheng ','Shi ','Shi ','Er ','Suc ','Vu ','Yu ', + 'Yu ','Van ','Hu ','Qi ','Wu ','Jing ','Si ','Sui ','Gen ','Gen ','Ya ','Ta ','Ya ','Qi ','Ya ','Cac ', + 'Tou ','Vong ','Cang ','Ta ','Giao ','Hai ','Yi ','Chan ','Hanh ','Mu ','','Xiang ','Kinh ','Ting ','Liang ','Xiang ', + 'Jing ','Ye ','Qin ','Bo ','You ','Xie ','Dan ','Lian ','Duo ','Wei ','Nhan ','Ren ','Ji ','La ','Wang ','Yi ', + 'Shi ','Nhan ','Le ','Ding ','Trac ','Jin ','Boc ','Chou ','Ba ','Zhang ','Kim ','Gioi ','Bing ','Nhung ','Cong ','Fo ', + 'San ','Lun ','Sya ','Cang ','Tu ','Shi ','Tha ','Zhang ','Fu ','Xian ','Xian ','Tuo ','Hong ','Tong ','Ren ','Qian ', + 'Gan ','Yi ','Di ','Dai ','Ling ','Yi ','Chao ','Chang ','Sa ','','Yi ','Mu ','Men ','Ren ','Jia ','Chao ', + 'Yang ','Qian ','Zhong ','Pi ','Wan ','Wu ','Jian ','Jia ','Yao ','Feng ','Cang ','Ren ','Wang ','Fen ','Di ','Fang ', + ], + 'x4f':[ + 'Zhong ','Qi ','Pei ','Yu ','Diao ','Dun ','Wen ','Yi ','Xin ','Kang ','Y ','Ji ','Ai ','Wu ','Ji ','Phuc ', + 'Fa ','Huu ','Jin ','Bei ','Dan ','Fu ','Tang ','Zhong ','You ','Huo ','Hoi ','Yu ','Cui ','Chuan ','San ','Wei ', + 'Chuan ','Che ','Ya ','Xian ','Shang ','Chang ','Lun ','Cang ','Xun ','Nho ','Wei ','Zhu ','','Xuan ','Nu ','Bo ', + 'Gu ','Ni ','Ni ','Xie ','Ban ','To ','Ranh ','Zhou ','Shen ','Qu ','Si ','Beng ','Si ','Gia ','Pi ','Yi ', + 'Si ','Ai ','Zheng ','Dian ','Han ','Mai ','Dan ','Zhu ','Bu ','Qu ','Bi ','Shao ','Ci ','Wei ','Di ','Tru ', + 'Zuo ','You ','Yang ','Ti ','Zhan ','He ','Bi ','Tuo ','She ','Du ','Yi ','Fo ','Zuo ','Kou ','Ning ','Tong ', + 'Ni ','Xuan ','Qu ','Yong ','Wa ','Qian ','','Ka ','','Pei ','Hui ','He ','Lao ','Xiang ','Ge ','Yang ', + 'Bai ','Fa ','Ming ','Giai ','Er ','Bing ','Ji ','Hen ','Huo ','Gui ','Quan ','Tiao ','Jiao ','Ci ','Yi ','Shi ', + 'Xing ','Shen ','Tuo ','Kan ','Zhi ','Gai ','Lai ','Yi ','Chi ','Kua ','Guang ','Li ','Yin ','Shi ','Mi ','Zhu ', + 'Xu ','You ','An ','Lu ','Mou ','Er ','Lun ','Tong ','Cha ','Chi ','Xun ','Cung ','Zhou ','Y ','Ru ','Jian ', + 'Xia ','Jia ','Zai ','Lu ','Ko ','Jiao ','Zhen ','Ce ','Qiao ','Kuai ','Chai ','Ning ','Nong ','Jin ','Wu ','Hou ', + 'Jiong ','Cheng ','Zhen ','Zuo ','Chou ','Xam ','Lu ','Ju ','Shu ','Ting ','Shen ','Tuo ','But ','Nan ','Hao ','Bian ', + 'Tui ','Yu ','Xi ','Xuc ','E ','Qiu ','Xu ','Kuang ','Ku ','Wu ','Tuan ','Yi ','Fu ','Lang ','Zu ','Qiao ', + 'Li ','Yong ','Hun ','Jing ','Xian ','San ','Pai ','Tuc ','Fu ','Xi ','Li ','Fu ','Ping ','Bao ','Yu ','Si ', + 'Xia ','Xin ','Xiu ','Yu ','Ti ','Che ','Chou ','','Yan ','Lia ','Li ','Lai ','Si ','Jian ','Tu ','Fu ', + 'He ','Cau ','Xiao ','Pai ','Jian ','Biao ','Chu ','Fei ','Feng ','Ya ','Em ','Bei ','Yu ','Xin ','Bi ','Jian ', + ], + 'x50':[ + 'Tranh ','Chi ','Bing ','Zan ','Yao ','Cui ','Lia ','Wan ','Lai ','Cang ','Zong ','Ge ','Guan ','Boi ','Tian ','Shu ', + 'Shu ','Men ','Dao ','Tan ','Jue ','Chui ','Xing ','Peng ','Tang ','Hou ','Yi ','Qi ','Ti ','Gan ','Jing ','Jie ', + 'Sui ','Xuong ','Jie ','Fang ','Zhi ','Kong ','Juan ','Zong ','Ju ','Qian ','Ni ','Luan ','Xac ','Wei ','Luo ','Song ', + 'Leng ','Hun ','Dong ','Zi ','Ben ','Wu ','Ju ','Nai ','Cai ','Jian ','Zhai ','Ye ','Zhi ','Sha ','Qing ','', + 'Ying ','Cheng ','Jian ','Yan ','Nuan ','Zhong ','Chun ','Jia ','Jie ','Wei ','Yu ','Bing ','Ruo ','Ti ','Wei ','Pian ', + 'Yan ','Feng ','Tang ','Wo ','E ','Xie ','Che ','Sheng ','Kan ','Di ','Zuo ','Cha ','Ting ','Bei ','Ye ','Huang ', + 'Yao ','Zhan ','Chou ','Yan ','You ','Jian ','Xu ','Zha ','Thay ','Fu ','Bi ','Zhi ','Zong ','Mian ','Ji ','Yi ', + 'Xie ','Xun ','Si ','Duan ','Trac ','Trinh ','Ou ','Tou ','Tou ','Bei ','Za ','Lu ','Jie ','Wei ','Fen ','Chang ', + 'Gui ','Sou ','Zhi ','Su ','Xia ','Fu ','Yuan ','Rong ','Li ','Ru ','Yun ','Gou ','Ma ','Bang ','Dian ','Tang ', + 'Hao ','Jie ','Xi ','Shan ','Qian ','Jue ','Cang ','Chu ','Tan ','Bei ','Xiao ','Yong ','Yao ','Tan ','Suo ','Yang ', + 'Fa ','Bing ','Jia ','Dai ','Zai ','Tang ','Cot ','Bin ','Chu ','Nuo ','Can ','Lei ','Cui ','Yong ','Zao ','Zong ', + 'Peng ','Song ','Ao ','Chuan ','Yu ','Zhai ','Cou ','Thuong ','Qiang ','Jing ','Chi ','Sha ','Han ','Zhang ','Khuynh ','Yan ', + 'Di ','Xi ','Lu ','Bei ','Piao ','Jin ','Lian ','Lu ','Man ','Qian ','Xian ','Tan ','Ying ','Dong ','Zhuan ','Xiang ', + 'Shan ','Qiao ','Jiong ','Tui ','Zun ','Boc ','Xi ','Lao ','Chang ','Guang ','Liao ','Qi ','Deng ','Chan ','Wei ','Ji ', + 'Fan ','Hui ','Chuan ','Jian ','Dan ','Jiao ','Jiu ','Tang ','Fen ','Xian ','Jue ','E ','Jiao ','Jian ','Tong ','Lin ', + 'Bo ','Gu ','','Su ','Xian ','Jiang ','Min ','Ye ','Jin ','Jia ','Qiao ','Pi ','Feng ','Zhou ','Ai ','Sai ', + ], + 'x51':[ + 'Nghi ','Jun ','Nung ','Chan ','Yi ','Dang ','Jing ','Xuan ','Cui ','Jian ','Chu ','Dan ','Jiao ','Sha ','Zai ','', + 'Bin ','An ','Nho ','Tai ','Chou ','Chai ','Lan ','Ni ','Jin ','Qian ','Meng ','Wu ','Ning ','Qiong ','Ni ','Chang ', + 'Lie ','Lei ','Lu ','Kuang ','Bao ','Du ','Biao ','Zan ','Zhi ','Si ','You ','Hao ','Chen ','Chen ','Li ','Teng ', + 'Wei ','Long ','Chu ','Sam ','Rang ','Shu ','Hui ','Li ','Luo ','Zan ','Nuo ','Tang ','Yan ','Lei ','Nang ','Er ', + 'Ngot ','Yun ','Zan ','Yuan ','Huynh ','Sung ','Zhao ','Hung ','Xian ','Quang ','Dui ','Khac ','Dui ','Mian ','Tu ','Chang ', + 'Er ','Dui ','Er ','Xin ','Tu ','Si ','Yan ','Yan ','Shi ','Sip ','Dang ','Qian ','Dou ','Fen ','Mao ','Shen ', + 'Dou ','Payk ','Jing ','Li ','Huang ','Ru ','Wang ','Nei ','Toan ','Liang ','Yu ','Ba ','Gong ','Luc ','Xi ','', + 'Lan ','Cong ','Tian ','Guan ','Xing ','Binh ','Qi ','Cu ','Dian ','Zi ','Ppwun ','Yang ','Jian ','Shou ','Ji ','Yi ', + 'Ji ','Chan ','Jiong ','Bou ','Ran ','Noi ','En ','Mao ','Gang ','Ran ','Ce ','Jiong ','Ce ','Zai ','Gua ','Jiong ', + 'Mao ','Zhou ','Mao ','Gou ','Xu ','Mian ','Mi ','Rong ','Yin ','Xie ','Kan ','Jun ','Nong ','Yi ','Mi ','Shi ', + 'Guan ','Meng ','Zhong ','Ju ','Oan ','Minh ','Kou ','Lam ','Fu ','Xie ','Mi ','Bing ','Dong ','Tai ','Gang ','Feng ', + 'Bang ','Hu ','Chong ','Jue ','Hu ','Huong ','Ye ','Leng ','Pan ','Fu ','Min ','Dong ','Xian ','Ret ','Xia ','Jian ', + 'Jing ','Shu ','Mei ','Tu ','Qi ','Gu ','Chon ','Song ','Jing ','Liang ','Qing ','Diao ','Lang ','Dong ','Gan ','Jian ', + 'Yin ','Cou ','Yi ','Li ','Cang ','Ming ','Jun ','Cui ','Si ','Duo ','Jin ','Lin ','Lin ','Ngung ','Xi ','Du ', + 'Ji ','Pham ','Fan ','Fan ','Feng ','Ju ','Chu ','Tako ','Feng ','Kogarashi ','Nagu ','Fu ','Feng ','Ping ','Feng ','Kai ', + 'Huang ','Kai ','Gan ','Deng ','Ping ','Qu ','Hung ','Kuai ','Tu ','Ao ','Xuat ','Ji ','Dang ','Han ','Han ','Zao ', + ], + 'x52':[ + 'Dao ','Diao ','Dao ','Ren ','Ren ','Chuang ','Phan ','Qie ','Yi ','Ji ','San ','Qian ','Cun ','Chu ','Wen ','Ji ', + 'Dan ','Xing ','Hua ','Wan ','Jue ','Li ','Yue ','Lie ','Liu ','Ze ','Gang ','Chuang ','Fu ','So ','Qu ','Ju ', + 'San ','Min ','Ling ','Zhong ','Pan ','Bie ','Jie ','Jie ','Bao ','Li ','Shan ','Bie ','Chan ','Jing ','Gua ','Gen ', + 'Dao ','Chuang ','Kui ','Ku ','Duo ','Er ','Zhi ','Shua ','Quan ','Cha ','Ci ','Khac ','Jie ','Gui ','Ci ','Gui ', + 'Kai ','Duo ','Ji ','Ti ','Jing ','Lou ','Gen ','Tac ','Yuan ','Cuo ','Tuoc ','Ke ','La ','Qian ','Cha ','Chuang ', + 'Gua ','Jian ','Cuo ','Li ','Ti ','Fei ','Bo ','Chan ','Qi ','Chuang ','Zi ','Gang ','Wan ','Bo ','Ji ','Duo ', + 'Qing ','Yan ','Zhuo ','Jian ','Ji ','Bo ','Yan ','Cua ','Huo ','Sheng ','Jian ','Duo ','Duan ','Wu ','Gua ','Fu ', + 'Sheng ','Jian ','Cat ','Zha ','Kai ','Chuang ','Juan ','Chan ','Tuan ','Lu ','Li ','Fou ','Shan ','Piao ','Kou ','Jiao ', + 'Gua ','Qiao ','Khoet ','Hua ','Chep ','Zhuo ','Lian ','Ju ','Pi ','Liu ','Gui ','Jiao ','Gui ','Jian ','Jian ','Tang ', + 'Huo ','Ji ','Jian ','Yi ','Jian ','Zhi ','Chan ','Cuan ','Mo ','Li ','Zhu ','Li ','Ya ','Quan ','Ban ','Gong ', + 'Gia ','Wu ','Mai ','Lie ','Jin ','Keng ','Xie ','Zhi ','Dong ','Zhu ','Nu ','Jie ','Cu ','Shao ','Yi ','Zhu ', + 'Miao ','Li ','Jing ','Lao ','Lao ','Juan ','Kou ','Yang ','Wa ','Xiao ','Mou ','Kuang ','Jie ','Lie ','He ','Shi ', + 'Ke ','Jin ','Hao ','Bot ','Min ','Chi ','Lang ','Yong ','Yong ','Mian ','Ke ','Xun ','Juan ','Qing ','Lu ','Pou ', + 'Meng ','Sac ','Lac ','Kai ','Mian ','Dong ','Huc ','Xu ','Kan ','Vu ','Yi ','Huan ','Weng ','Thang ','Lao ','Mu ', + 'Lu ','Piao ','Shi ','Ji ','Qin ','Qiang ','Jiao ','Quan ','Yang ','Yi ','Jue ','Fan ','Juan ','Tong ','Ju ','Dan ', + 'Xie ','Mai ','Xun ','Xun ','Lu ','Li ','Che ','Rang ','Quan ','Bao ','Chuoc ','Yun ','Jiu ','Bao ','Gou ','Wu ', + ], + 'x53':[ + 'Yun ','Monme ','Niou ','Gai ','Gai ','Bao ','Cong ','','Hung ','Peng ','Ju ','Tao ','Ge ','Pu ','An ','Pao ', + 'Fu ','Gong ','Da ','Jiu ','Qiong ','Bi ','Hua ','Bei ','Nao ','Chi ','Fang ','Jiu ','Yi ','Za ','Jiang ','Kang ', + 'Jiang ','Kuang ','Hu ','Hop ','Qu ','Bian ','Gui ','Qie ','Zang ','Kuang ','Fei ','Hu ','Tou ','Gui ','Gui ','Hui ', + 'Dan ','Gui ','Lian ','Lian ','Suan ','Du ','Jiu ','Qu ','Xi ','That ','Qu ','Yi ','Hop ','Yan ','Bian ','Ni ', + 'Khu ','Shi ','Xin ','Qian ','Nian ','Sa ','Zu ','Thang ','Ngo ','Hui ','Ban ','Shi ','Tap ','Wan ','Hua ','Xie ', + 'Wan ','Bei ','Tot ','Zhuo ','Xie ','Dan ','Mai ','Nam ','Dan ','Ji ','Bo ','Shuai ','Boc ','Kuang ','Bian ','Bu ', + 'Zhan ','Qia ','Lu ','You ','Lu ','Xi ','Gua ','Wo ','Xie ','Jie ','Jie ','Wei ','Ngang ','Qiong ','Zhi ','Mao ', + 'Yin ','Nguy ','Shao ','Ji ','Que ','Luan ','Shi ','Juan ','Xie ','Xu ','Jin ','Khuoc ','Wu ','Ji ','E ','Khanh ', + 'Xi ','','Chang ','Zhan ','E ','Ting ','Li ','Zhe ','Han ','Li ','Ya ','Ya ','Yan ','She ','Zhi ','Zha ', + 'Pang ','','He ','Day ','Zhi ','Ce ','Pang ','Ti ','Li ','She ','Hou ','Ting ','Zui ','Cuo ','Fei ','Yuan ', + 'Ce ','Yuan ','Xiang ','Yan ','Li ','Jue ','Sha ','Dian ','Chu ','Jiu ','Qin ','Ao ','Gui ','Yan ','Si ','Li ', + 'Chang ','Lan ','Li ','Yan ','Yan ','Yuan ','Si ','Gong ','Lin ','Qiu ','Qu ','Qu ','Uk ','Lei ','Du ','Xian ', + 'Zhuan ','San ','Can ','Tham ','Can ','Can ','Ai ','Dai ','You ','Cha ','Ji ','You ','Song ','Fan ','Shou ','Guai ', + 'Ba ','Fa ','Ruo ','Shi ','Thuc ','Zhuo ','Qu ','Thu ','Bian ','Xu ','Jia ','Pan ','Sou ','Gao ','Wei ','Sou ', + 'Die ','Rui ','Cong ','Kou ','Gu ','Cau ','Ling ','Gua ','Tao ','Khau ','Zhi ','Jiao ','Zhao ','Bot ','Ding ','Ke ', + 'Thai ','Chi ','Su ','You ','Qiu ','Po ','Xie ','Hao ','Ti ','Tan ','Chi ','Le ','Diao ','Ji ','Duk ','Hong ', + ], + 'x54':[ + 'Mie ','Hu ','Mang ','Chi ','Ge ','Xuan ','Yao ','Zi ','He ','Ji ','Diao ','Cun ','Tong ','Danh ','Hou ','Li ', + 'Tu ','Huong ','Cha ','Xia ','Ye ','Lu ','A ','Ma ','Ou ','Xue ','Yi ','Quan ','Chou ','Lin ','Tun ','Ngam ', + 'Fei ','Bi ','Qin ','Tam ','Jie ','Bu ','Fou ','Va ','Dun ','Phan ','Hoe ','Ham ','Ting ','Hang ','Shun ','Qi ', + 'Hong ','Zhi ','Shen ','Wu ','Wu ','Chao ','Ne ','Xue ','Cop ','Xuy ','Dou ','Wen ','Hong ','Ou ','Ngo ','Gao ', + 'Ya ','Jun ','Lu ','E ','Ge ','Mei ','Ngoc ','Qi ','Cheng ','Wu ','Gao ','Fu ','Jiao ','Hong ','Chi ','Sheng ', + 'Ne ','Tun ','Fu ','Yi ','Dai ','Ou ','Li ','Bai ','Yuan ','Kuai ','','Qiang ','Wu ','E ','Te ','Quan ', + 'Pen ','Ran ','Nai ','M ','Ling ','Ran ','You ','Di ','Chu ','Shi ','Zhou ','Tie ','Xi ','The ','Qi ','Ping ', + 'Zi ','Oa ','Zi ','Wei ','Gau ','Ha ','Nao ','Xia ','Pei ','Yi ','Xiao ','Shen ','Hu ','Ming ','Da ','Qu ', + 'Ju ','Cam ','Za ','Tuo ','Duo ','Pou ','Bau ','Bi ','Phot ','Yang ','He ','Zha ','Hoa ','Hay ','Jiu ','Yong ', + 'Fu ','Que ','Chu ','Wa ','Ka ','Gu ','Ka ','Zuo ','Bu ','Long ','Giong ','Ning ','Ta ','Si ','Xian ','Huo ', + 'Qi ','Er ','E ','Quang ','Zha ','Choi ','Yi ','Lie ','Zi ','Mie ','Mi ','Zhi ','Rao ','Gat ','Chau ','Ge ', + 'Shuai ','Zan ','Xiao ','Cay ','Hui ','Kua ','Huai ','Tao ','Xian ','E ','Xuan ','Hiu ','Oa ','Yan ','Lao ','Yi ', + 'Ai ','Pin ','Shen ','Tong ','Hong ','Xiong ','Duo ','Oa ','Ha ','Tai ','Yu ','Di ','Pai ','Xiang ','Ai ','Gan ', + 'Kuang ','Ya ','Da ','Xiao ','Bi ','Yue ','','Hua ','Sasou ','Kuai ','Duo ','','Ji ','Nong ','Mou ','Yo ', + 'Hao ','Yuan ','Trong ','Pou ','Mang ','Ca ','Nga ','Chi ','Shao ','Li ','Na ','Zu ','Ha ','Ku ','Hao ','Xian ', + 'Rao ','Buot ','Zhe ','Zha ','Liang ','Ba ','Mie ','Le ','Sui ','Fou ','Bu ','Han ','Heng ','Geng ','Shuo ','Ge ', + ], + 'x55':[ + 'You ','Ngon ','Gu ','Gu ','Bai ','Han ','Suo ','Chun ','Yi ','Ai ','Jia ','Tu ','Xian ','Huan ','Li ','Hoi ', + 'Tang ','Zuo ','Qiu ','Che ','Wu ','Zao ','Ya ','Dou ','Qi ','Di ','Qin ','Ma ','Mal ','Hong ','Dou ','Kes ', + 'Lao ','Liang ','Suo ','Zao ','Huan ','Laang ','Sha ','Ji ','Zuo ','Wo ','Feng ','Cam ','Hu ','Qi ','Shou ','Wei ', + 'Shua ','Xuong ','Er ','Li ','Qiang ','An ','Jie ','Yo ','Nian ','Yu ','Tian ','Lai ','Thep ','Xi ','Tuo ','Hu ', + 'Nhai ','Zhou ','Nou ','Ken ','Troc ','Zhuo ','Thuong ','Di ','Heng ','Lam ','A ','Xiao ','Xiang ','Tun ','Wu ','Wen ', + 'Cui ','Sha ','Quat ','Qi ','Qi ','Tao ','Dan ','Dan ','Ye ','Zi ','Bi ','Cui ','Chuo ','He ','Ya ','Qi ', + 'Zhe ','Fei ','Liang ','Ham ','Pi ','Sha ','La ','Ze ','Qing ','Quay ','Pa ','Gia ','Se ','Zhuan ','Nie ','Guo ', + 'Luo ','Nham ','Di ','Quan ','Tan ','Bo ','Ding ','Lang ','Xiao ','Geoi ','Tang ','Chi ','Ti ','An ','Jiu ','Dan ', + 'Ka ','Ngum ','Wei ','Nan ','Shan ','Yu ','Zhe ','La ','Jie ','Hou ','Han ','Die ','Zhou ','Chai ','Oa ','Re ', + 'Yu ','Yin ','Zan ','Eo ','O ','Mian ','Hu ','Yun ','Chuan ','Hui ','Huan ','Huan ','Xi ','He ','Ji ','Kui ', + 'Zhong ','Wei ','Sha ','Xu ','Huang ','Du ','Nham ','Xuan ','Liang ','Yu ','Tang ','Chi ','Qiao ','Yan ','Dan ','Pen ', + 'Can ','Li ','Yo ','Zha ','Wei ','Miao ','Ying ','Pen ','Phos ','Kui ','Xi ','Du ','Jie ','Lou ','Ku ','Sao ', + 'Huo ','Ti ','Yao ','Gao ','A ','Xiu ','Qiang ','Se ','Yong ','Nho ','Hong ','Xie ','Yi ','Suo ','Mua ','Cha ', + 'Hai ','Ke ','Ta ','Sang ','Xin ','Ru ','Sou ','Cut ','Ji ','Bang ','Wu ','Khem ','Shi ','Ge ','Zi ','Jie ', + 'Luo ','Weng ','Wa ','Si ','Chi ','Hao ','Suo ','Garon ','Hai ','Suo ','Qin ','Nie ','He ','Cis ','Sai ','Ng ', + 'Ge ','Na ','Dia ','Ai ','','Tong ','Bi ','Ngao ','Ao ','Lian ','Cui ','Zhe ','Mo ','Sou ','Sou ','Tan ', + ], + 'x56':[ + 'Di ','Qi ','Jiao ','Chong ','Jiao ','Kai ','Han ','Tham ','Tao ','Jia ','Ai ','Xiao ','Piao ','Lau ','Ga ','Gu ', + 'Xiao ','Hu ','Hui ','Guo ','Ou ','Xian ','Ze ','Chang ','Xu ','Po ','De ','Ma ','Ma ','Hu ','Lei ','Du ', + 'Ga ','Tang ','Ye ','Beng ','Ying ','Saai ','Jiao ','Mi ','Xiao ','Hua ','Mai ','Ran ','Choi ','Peng ','Lao ','Xiao ', + 'Ji ','Zhu ','Trao ','Kui ','Zui ','Xiao ','Si ','Hao ','Fu ','Liao ','Qiao ','Hi ','Xiu ','Tan ','Tan ','Hei ', + 'Sun ','E ','Ton ','Fan ','Chi ','Vay ','Zan ','Chuang ','Cu ','Dan ','Yu ','Tun ','Cheng ','Jiao ','Ye ','Hap ', + 'Qi ','Hao ','Lian ','Xu ','Deng ','Hui ','Yin ','Pu ','Jue ','Qin ','Xun ','Nie ','Lu ','Si ','Yan ','Ying ', + 'Da ','Dan ','O ','Zhou ','Jin ','Nong ','Yue ','Hui ','Qi ','E ','Zao ','Yi ','Shi ','Jiao ','Yuan ','Ai ', + 'Yong ','Jue ','Goi ','Yu ','Phun ','Dao ','Gat ','Ham ','Dun ','Dang ','Hanashi ','Sai ','Pi ','Pi ','Yin ','Zui ', + 'Ning ','Di ','Lan ','Ta ','Huo ','Nheo ','Hao ','Xia ','Ya ','Doi ','Xi ','Tru ','Ji ','Jin ','Hao ','Ti ', + 'Chang ','','','Ca ','Ti ','Lu ','Hui ','Bo ','You ','Nie ','Yin ','Hu ','Mut ','Huang ','Zhe ','Li ', + 'Liu ','Haai ','Nang ','Xiao ','Mo ','Yan ','Li ','Lo ','Lung ','Fu ','Dan ','Chen ','Pin ','Pi ','Xiang ','Huo ', + 'Mo ','Xi ','Duo ','Ku ','Yan ','Chan ','Inh ','Rang ','Dian ','La ','Ta ','Xiao ','Jiao ','Chuo ','Huan ','Huo ', + 'Zhuan ','Nie ','Hiu ','Ca ','Le ','Chan ','Chai ','Li ','Yi ','La ','Nang ','Zan ','Su ','Xi ','So ','Jian ', + 'Za ','Chuc ','Lan ','Nie ','Nang ','Trom ','Lo ','Wei ','Hui ','Yin ','Tu ','Si ','Nin ','Jian ','Hui ','Xin ', + 'Nhan ','Nan ','Tuan ','Tuan ','Dun ','Kang ','Yuan ','Jiong ','Pian ','Yun ','Cong ','Hu ','Hui ','Yuan ','E ','Guo ', + 'Khon ','Song ','Wei ','Tu ','Wei ','Lun ','Guo ','Khuan ','Ri ','Ling ','Co ','Quoc ','Tai ','Guo ','Tu ','You ', + ], + 'x57':[ + 'Guo ','Yin ','Hun ','Bo ','Yu ','Han ','Yuan ','Lun ','Quan ','Yu ','Qing ','Quoc ','Chuan ','Wei ','Yuan ','Quan ', + 'Ku ','Fu ','Yuan ','Yuan ','E ','Toshokan ','Tu ','Tu ','Tuan ','Lue ','Hui ','Yi ','Yuan ','Luan ','Luan ','Tu ', + 'Ya ','Tu ','Ting ','Sheng ','Pu ','Lu ','Iri ','Ya ','Zai ','Wei ','Ge ','Yu ','Wu ','Gui ','Pi ','Yi ', + 'Di ','Qian ','Qian ','Zhen ','Zhuo ','Dang ','Qia ','Akutsu ','Yama ','Kuang ','Chang ','Qi ','Nie ','Mo ','Ji ','Jia ', + 'Zhi ','Zhi ','Ban ','Xun ','Tou ','Qin ','Fen ','Quan ','Keng ','Tun ','Fang ','Phan ','Ben ','Tan ','Kan ','Huai ', + 'Zuo ','Ganh ','Bi ','Xing ','Di ','Jing ','Ji ','Kuai ','Di ','Jing ','Jian ','Tan ','Li ','Ba ','Wu ','Vun ', + 'Zhui ','Pha ','Pan ','Tang ','Kun ','Qu ','Tan ','Zhi ','Tuo ','Gan ','Ping ','Dian ','Gua ','Noi ','Tai ','Pi ', + 'Jiong ','Yang ','Fo ','Ao ','Liu ','Qiu ','Mu ','Ke ','Gou ','Xue ','Ba ','Chi ','Che ','Ling ','Zhu ','Fu ', + 'Hu ','Zhi ','Thuy ','Lap ','Long ','Long ','Lu ','Ao ','Tai ','Bau ','','Xing ','Dong ','Ji ','Ke ','Lu ', + 'Ci ','Chi ','Lei ','Gay ','Yin ','Hou ','Dui ','Zhao ','Fu ','Guang ','Yao ','Duo ','Duo ','Gui ','Cha ','Yang ', + 'Yin ','Fa ','Gou ','Yuan ','Die ','Xie ','Ken ','Jiong ','Shou ','E ','Ha ','Dian ','Hong ','Wu ','Khoai ','', + 'Tao ','Dang ','Kai ','Gake ','Nao ','Ang ','Xing ','Xian ','Huan ','Bang ','Pei ','Ba ','Yi ','Yin ','Han ','Xu ', + 'Chui ','Cen ','Geng ','Ai ','Peng ','Fang ','Que ','Yong ','Xun ','Jia ','Di ','Mai ','Lang ','Xuan ','Thanh ','Yan ', + 'Jin ','Zhe ','Lei ','Lie ','Pu ','Cheng ','Gomi ','Bu ','Shi ','Xun ','Guo ','Jiong ','Ye ','Nam ','Di ','Yu ', + 'Bu ','Ya ','Juan ','Sui ','Pi ','Cheng ','Wan ','Ju ','Lun ','Zheng ','Kong ','Chong ','Dong ','Dai ','Tan ','An ', + 'Cai ','Shu ','Beng ','Kan ','Zhi ','Duo ','Yi ','Chap ','Yi ','Pei ','Co ','Zhun ','Qi ','Sao ','Ju ','Ni ', + ], + 'x58':[ + 'Ku ','Ke ','Tang ','Kun ','Ni ','Jian ','Dui ','Jin ','Gang ','Yu ','E ','Peng ','Gu ','Tu ','Leng ','', + 'Ya ','Qian ','','An ','','Duo ','Nao ','Tu ','Cheng ','Yin ','Hun ','Bi ','Lian ','Guo ','Die ','Zhuan ', + 'Hou ','Bao ','Bao ','Yu ','Di ','Mao ','Jie ','Ruan ','E ','Geng ','Kham ','Zong ','Yu ','Huang ','E ','Yao ', + 'Yan ','Bao ','Ji ','Mei ','Chang ','Du ','Tuo ','Om ','Feng ','Zhong ','Jie ','Zhen ','Feng ','Gang ','Chuan ','Jian ', + 'Hei ','Rui ','Xiang ','Huang ','Leng ','Duan ','','Xuan ','Ji ','Ji ','Khoi ','Ying ','Ta ','Cheng ','Yong ','Kai ', + 'Su ','Su ','Shi ','Mi ','Ta ','Weng ','Cheng ','Tu ','Tang ','Que ','Zhong ','Li ','Peng ','Bang ','Tac ','Zang ', + 'Dui ','Tian ','Wu ','Cheng ','Ven ','Ge ','Zhen ','Ai ','Gong ','Yan ','Kan ','Tian ','Yuan ','Wen ','Xie ','Liu ', + 'Ama ','Lang ','Chang ','Vung ','Beng ','Chen ','Cu ','Lu ','Ou ','Qian ','Mei ','Mo ','Zhuan ','Shuang ','Thuc ','Lou ', + 'Chi ','Man ','Biao ','Jing ','Qi ','Shu ','Di ','Zhang ','Kan ','Yong ','Dian ','Chen ','Zhi ','Xi ','Guo ','Qiang ', + 'Jin ','Di ','Shang ','Mo ','Cui ','Yan ','Ta ','Zeng ','Qi ','Qiang ','Liang ','','Zhui ','Qiao ','Tang ','Xu ', + 'Shan ','Shan ','Ba ','Pu ','Kuai ','Dong ','Fan ','Que ','Mo ','Dun ','Dun ','Zun ','Di ','Sheng ','Duo ','Duo ', + 'Tan ','Deng ','Wu ','Fen ','Huang ','Tan ','Da ','Ye ','Sho ','Mama ','Ao ','Qiang ','Ji ','Qiao ','Ken ','Yi ', + 'Pi ','Bi ','Dian ','Jiang ','Ye ','Yong ','Bo ','Tan ','Lan ','Ju ','Huai ','Dang ','Rang ','Qian ','Xun ','Lan ', + 'Xi ','He ','Ai ','Ya ','Dao ','Hao ','Ruan ','Mama ','Lei ','Kuang ','Lu ','Yan ','Tan ','Wei ','Huai ','Long ', + 'Long ','Rui ','Li ','Lin ','Rang ','Ten ','Xun ','Yan ','Lei ','Ba ','','Shi ','Nham ','','Zhuang ','Zhuang ', + 'Sheng ','Yi ','Mai ','Ke ','Zhu ','Zhuang ','Hu ','Hu ','Kun ','Nhat ','Hu ','Xu ','Kun ','Tho ','Mang ','Zun ', + ], + 'x59':[ + 'Shou ','Yi ','Zhi ','Gu ','Chu ','Jiang ','Feng ','Bei ','Cay ','Bian ','Sui ','Qun ','Ling ','Fu ','Zuo ','Xia ', + 'Xiong ','','Nao ','Xia ','Kui ','Xi ','Wai ','Yuan ','Mao ','Tuc ','Duo ','Duo ','Ye ','Qing ','Uys ','Gou ', + 'Gou ','Qi ','Meng ','Meng ','Yin ','Huo ','Chen ','Da ','Ze ','Tian ','Tai ','Phu ','Guai ','Yao ','Yang ','Hang ', + 'Gao ','That ','Ben ','Tai ','Tou ','Yan ','Bi ','Yi ','Khoa ','Jia ','Duo ','Kwu ','Kuang ','Yun ','Jia ','Pa ', + 'En ','Lian ','Huan ','Di ','Yan ','Pao ','Quan ','Qi ','Nai ','Phung ','Xie ','Fen ','Dian ','','Kui ','Tau ', + 'Huan ','Qi ','Kai ','She ','Ben ','Yi ','Jiang ','Tao ','Zang ','Ben ','Xi ','Xiang ','Fei ','Diao ','Xun ','Keng ', + 'Dian ','Ao ','Xa ','Weng ','Pan ','Ao ','Wu ','Ao ','Jiang ','Lian ','Duo ','Yun ','Jiang ','Shi ','Phan ','Huo ', + 'Bi ','Lian ','Duo ','Nu ','Nu ','Ding ','Nai ','Qian ','Gian ','Ta ','Jiu ','Nan ','Cha ','Hao ','Xian ','Fan ', + 'Ji ','Shuo ','Nhu ','Phi ','Wang ','Hong ','Zhuang ','Fu ','Ma ','Dan ','Ren ','Fu ','Jing ','Ngon ','Xie ','Wen ', + 'Zhong ','Pa ','Du ','Ji ','Keng ','Zhong ','Yao ','Jin ','Yun ','Miao ','Pei ','Shi ','Yue ','Trang ','Niu ','Yan ', + 'Na ','Xin ','Fen ','Bi ','Yu ','Tuo ','Feng ','Yuan ','Fang ','Wu ','Yu ','Gui ','Du ','Ba ','Ni ','Dau ', + 'Zhuo ','Zhao ','Da ','Nai ','Yuan ','Tou ','Xuan ','Zhi ','E ','Muoi ','Mo ','Qi ','Bi ','Shen ','Qie ','E ', + 'He ','Xu ','Fa ','Zheng ','Min ','Nua ','Mu ','Fu ','Lanh ','Zi ','Zi ','Shi ','Ran ','Shan ','Yang ','Man ', + 'Thu ','Gu ','Si ','Xing ','Wei ','Zi ','Ju ','Shan ','Pin ','Ren ','Yao ','Tong ','Jiang ','Shu ','Ji ','Gai ', + 'Shang ','Kuo ','Juan ','Jiao ','Gou ','Mu ','Gian ','Jian ','Yi ','Nian ','Zhi ','Ji ','Ji ','Xian ','Heng ','Guang ', + 'Jun ','Kua ','Yan ','Ming ','Lie ','Pei ','Yan ','You ','Yan ','Cha ','Shen ','Nhan ','Chi ','Gui ','Quan ','Tu ', + ], + 'x5a':[ + 'Song ','Uy ','Hong ','Wa ','Lou ','Ya ','Rao ','Jiao ','Luan ','Ping ','Xian ','Shao ','Li ','Cheng ','Xiao ','Mang ', + '','Suo ','Wu ','Wei ','Ke ','Lai ','Chuo ','Ding ','Nuong ','Xing ','Nan ','Yu ','Na ','Pei ','Nei ','Juan ', + 'Shen ','Zhi ','Han ','Di ','Zhuang ','Nga ','Pin ','Tui ','Han ','Mian ','Wu ','Yan ','Wu ','Xi ','Yan ','Yu ', + 'Si ','Yu ','Wa ','','Xian ','Ju ','Thu ','Shui ','Qi ','Xian ','Zhui ','Dong ','Chang ','Lu ','Ai ','E ', + 'E ','Lau ','Mian ','Cong ','Pou ','Ju ','Ba ','Cai ','Ding ','Wan ','Biao ','Xiao ','Shu ','Qi ','Hui ','Fu ', + 'E ','Wo ','Tan ','Fei ','','Jie ','Tian ','Ni ','Quan ','Jing ','Hun ','Jing ','Qian ','Dian ','Xing ','Hu ', + 'Wa ','Lai ','Bi ','Yin ','Zhou ','Chuo ','Phu ','Jing ','Lun ','Yan ','Lam ','Kun ','Dam ','Ya ','','Li ', + 'Dian ','Xian ','Hwa ','Hua ','Ying ','Chan ','Shen ','Ting ','Dang ','Yao ','Wu ','Nan ','Ruo ','Jia ','Tou ','Xu ', + 'Yu ','Wei ','Ti ','Rou ','Mei ','Dan ','Ruan ','Qin ','','Wu ','Qian ','Chun ','Mao ','Fu ','Chua ','Duan ', + 'Xi ','Zhong ','Moi ','Huang ','Mian ','An ','Ying ','Xuan ','','Wei ','Mei ','Yuan ','Zhen ','Qiu ','Ti ','Xie ', + 'Tuo ','Lian ','Mao ','Ran ','Si ','Pian ','Wei ','Oa ','Jiu ','Hu ','Ao ','','Bou ','Xu ','Tou ','Gui ', + 'Zou ','Yao ','Pi ','Xi ','Yuan ','Ying ','Rong ','Ru ','Chi ','Liu ','Mei ','Pan ','Ao ','Ma ','Gou ','Kui ', + 'Qin ','Jia ','Dau ','Zhen ','Yuan ','Cha ','Yong ','Ming ','Ying ','Ji ','Su ','Niao ','Xian ','Tao ','Pang ','Lang ', + 'Nao ','Bao ','Ai ','Pi ','Pin ','Yi ','Piao ','Yu ','Lei ','Xuan ','Man ','Yi ','Zhang ','Kang ','Yong ','Ni ', + 'Li ','Di ','Gui ','Yan ','Jin ','Zhuan ','Chang ','Ce ','Han ','Non ','Lao ','Mo ','Zhe ','Hu ','Hu ','Ao ', + 'Nen ','Qiang ','Maa ','Pie ','Gu ','Wu ','Jiao ','Tuo ','Zhan ','Mao ','Xian ','Xian ','Mo ','Liao ','Lian ','Hua ', + ], + 'x5b':[ + 'Gui ','Deng ','Zhi ','Xu ','','Hua ','Xi ','Hui ','Rao ','Xi ','Yan ','Chan ','Jiao ','Mei ','Fan ','Fan ', + 'Xian ','Yi ','Wei ','Jiao ','Fu ','Shi ','Bi ','Shan ','Sui ','Qiang ','Lian ','Huan ','','Niao ','Dong ','Yi ', + 'Can ','Ai ','Niang ','Neng ','Ma ','Tiao ','Chou ','Jin ','Ci ','Yu ','Pin ','','Xu ','Nai ','Yan ','Tai ', + 'Anh ','Can ','Niao ','','Ying ','Mian ','Kaka ','Ma ','Shen ','Xing ','Ni ','Du ','Liu ','Yuan ','Lan ','Yan ', + 'Shuang ','Ling ','Jiao ','Niang ','Lan ','Xian ','Ying ','Shuang ','Shuai ','Quan ','Mi ','Li ','Luan ','Yan ','Zhu ','Lan ', + 'Zi ','Jie ','Jue ','Jue ','Kong ','Yun ','Zi ','Zi ','Cun ','Sun ','Fu ','But ','Zi ','Xiao ','Xin ','Meng ', + 'Si ','Tai ','Bao ','Ji ','Gu ','Nua ','Xue ','','Zhuan ','Hai ','Luan ','Sun ','Huai ','Mie ','Cong ','Qian ', + 'Shu ','Chan ','Ya ','Zi ','Ni ','Fu ','Zi ','Li ','Hoc ','Bo ','Nho ','Lai ','Nie ','Nie ','Ying ','Luan ', + 'Mian ','Ning ','Rong ','Ta ','Gui ','Zhai ','Qiong ','Yu ','Thu ','An ','Tu ','Tong ','Hoan ','Rou ','Yao ','Hong ', + 'Yi ','Jing ','Zhun ','Mi ','Zhu ','Dang ','Hong ','Zong ','Quan ','Tru ','Ding ','Wan ','Nghi ','Bao ','Shi ','Shi ', + 'Chong ','Shen ','Ke ','Xuan ','That ','You ','Huan ','Yi ','Tiao ','Shi ','Xian ','Cung ','Cheng ','Qun ','Gong ','Xiao ', + 'Zai ','Zha ','Bao ','Hai ','Yan ','Xiao ','Gia ','Shen ','Chen ','Dung ','Huang ','Mi ','Kou ','Kuan ','Bin ','Tuc ', + 'Cai ','Zan ','Ji ','Yuan ','Gui ','Yin ','Mi ','Khau ','Qing ','Que ','Zhen ','Jian ','Phu ','Ning ','Bing ','Huan ', + 'Mei ','Qin ','Han ','Ngu ','Shi ','Ning ','Jin ','Ning ','Zhi ','Yu ','Bao ','Kuan ','Ning ','Qin ','Mo ','Cha ', + 'Ju ','Gua ','Qin ','Hu ','Wu ','Liao ','Shi ','Ning ','Zhai ','Shen ','Wei ','Xie ','Khoan ','Hui ','Liao ','Jun ', + 'Huan ','Yi ','Yi ','Bao ','Qin ','Chong ','Bao ','Feng ','Thon ','Dui ','Si ','Xun ','Dao ','Lu ','Dui ','Tho ', + ], + 'x5c':[ + 'Po ','Phong ','Zhuan ','Fu ','She ','Ke ','Jiang ','Tuong ','Zhuan ','Wei ','Zun ','Xun ','Shu ','Dui ','Dao ','Xiao ', + 'Ji ','Shao ','Er ','Er ','Er ','Ga ','Jian ','Shu ','Chen ','Shang ','Chuong ','','Ga ','Chang ','Liao ','Xian ', + 'Xian ','','Wang ','Wang ','You ','Liao ','Liao ','Yao ','Mang ','Wang ','Wang ','Wang ','Ga ','Yao ','Duo ','Kui ', + 'Zhong ','Jiu ','Gan ','Gu ','Gan ','Tui ','Gan ','Gan ','Thay ','Yin ','Chi ','Kao ','Ni ','Jin ','Wei ','Niao ', + 'Cuc ','Pi ','Ceng ','Xi ','Bi ','Cu ','Jie ','Tian ','Khuat ','Ti ','Jie ','Wu ','Diao ','Thi ','Shi ','Ping ', + 'Ji ','Xie ','Chen ','Xi ','Ni ','Zhan ','Xi ','','Man ','E ','Lou ','Ping ','Ti ','Fei ','Shu ','Xie ', + 'Tu ','Lu ','Lu ','Xi ','Ceng ','Lu ','Ju ','Xie ','Ju ','Jue ','Liao ','Jue ','Thuoc ','Xi ','Che ','Truan ', + 'Ni ','Son ','','Xian ','Li ','Xue ','Nata ','','Long ','Yi ','Qi ','Ren ','Wu ','Han ','Shen ','Yu ', + 'Chu ','Sui ','Qi ','','Yue ','Ban ','Yao ','Ang ','Ya ','Wu ','Jie ','E ','Ji ','Qian ','Fen ','Yuan ', + 'Qi ','Cen ','Qian ','Qi ','Cha ','Jie ','Qu ','Gang ','Xian ','Ao ','Lan ','Dao ','Ba ','Zuo ','Zuo ','Yang ', + 'Ju ','Gang ','Ke ','Gou ','Xue ','Bei ','Li ','Tiao ','Ju ','Nham ','Fu ','Xiu ','Jia ','Ling ','Tuo ','Pei ', + 'You ','Dai ','Kuang ','Yue ','Qu ','Hu ','Po ','Min ','Ngan ','Tiao ','Ling ','Chi ','Yuri ','Dong ','Sen ','Kui ', + 'Xiu ','Mao ','Tong ','Xue ','Yi ','Kura ','He ','Ke ','Luo ','E ','Fu ','Xun ','Die ','Lu ','An ','Er ', + 'Gai ','Quan ','Tong ','Yi ','Mu ','Shi ','An ','Wei ','Hu ','Zhi ','Mi ','Li ','Ji ','Tong ','Wei ','You ', + 'Touge ','Xia ','Li ','Yao ','Jiao ','Zheng ','Luan ','Jiao ','E ','E ','Yu ','Ye ','Bu ','Qiao ','Qun ','Feng ', + 'Feng ','Nao ','Li ','You ','Xian ','Hong ','Dao ','Shen ','Cheng ','Tu ','Geng ','Jun ','Hao ','Xia ','Yin ','Yu ', + ], + 'x5d':[ + 'Lang ','Kan ','Lao ','Lai ','Xian ','Que ','Kong ','Sung ','Chong ','Ta ','','Hua ','Ju ','Lai ','Qi ','Min ', + 'Kun ','Kun ','Zu ','Gu ','Cui ','Ya ','Day ','Gang ','Lun ','Son ','Leng ','Jue ','Duo ','Zheng ','Guo ','Yin ', + 'Dong ','Han ','Zheng ','Wei ','Yao ','Pi ','Yan ','Song ','Jie ','Beng ','Zu ','Jue ','Dong ','Zhan ','Gu ','Yin ', + '','Ze ','Huang ','Yu ','Wei ','Yang ','Feng ','Qiu ','Dun ','Ti ','Yi ','Zhi ','Shi ','Zai ','Yao ','E ', + 'Zhu ','Kham ','Lu ','Yan ','Mei ','Gan ','Ji ','Ji ','Huan ','Ting ','Sheng ','Mi ','Qian ','Wu ','Yu ','Zong ', + 'Lan ','Jue ','Yan ','Yan ','Wei ','Zong ','Cha ','Sui ','Rong ','Yamashina ','Qin ','Yu ','Ki ','Lou ','Tu ','Dui ', + 'Xi ','Weng ','Cang ','Dang ','Hong ','Jie ','Ai ','Liu ','Wu ','Tung ','Qiao ','Zi ','Wei ','Beng ','Dian ','Cuo ', + 'Qian ','Yong ','Nie ','Cuo ','Ji ','','Tao ','Song ','Zong ','Jiang ','Liao ','','Chan ','Die ','Cen ','Ding ', + 'Tu ','Lou ','Zhang ','Zhan ','Zhan ','Ao ','Cao ','Qu ','Qiang ','Zui ','Zui ','Dao ','Dao ','Xi ','Yu ','Bo ', + 'Long ','Xiang ','Ceng ','Bo ','Qin ','Jiao ','Yan ','Lao ','Zhan ','Lin ','Liao ','Liao ','Jin ','Deng ','Duo ','Zun ', + 'Jiao ','Gui ','Yao ','Qiao ','Yao ','Jue ','Zhan ','Yi ','Xue ','Nao ','Ye ','Ye ','Yi ','E ','Xian ','Ji ', + 'Xie ','Ke ','Xi ','Di ','Ao ','Zui ','','Yi ','Rong ','Dao ','Ling ','Za ','Yu ','Yue ','Yin ','', + 'Jie ','Li ','Sui ','Long ','Long ','Dian ','Ying ','Xi ','Ju ','Chan ','Ying ','Kui ','Yan ','Nguy ','Nao ','Quan ', + 'Chao ','Cuan ','Luan ','Dian ','Dian ','','Nham ','Yan ','Yan ','Nao ','Yan ','Chuan ','Gui ','Chuan ','Chau ','Huang ', + 'Jing ','Xun ','Sao ','Chao ','Lie ','Gong ','Zuo ','Qiao ','Ju ','Gong ','Kek ','Wu ','Pwu ','Pwu ','Sai ','Qiu ', + 'Qiu ','Ji ','Yi ','Si ','Ba ','Zhi ','Zhao ','Xiang ','Yi ','Jin ','Xun ','Juan ','Phas ','Ron ','Can ','Fu ', + ], + 'x5e':[ + 'Za ','Bi ','Shi ','Bo ','Ding ','Shuai ','Fan ','Nie ','Shi ','Fen ','Pa ','Zhi ','Hoi ','Hu ','Dan ','Wei ', + 'Zhang ','Tang ','Dai ','Ma ','Pei ','Pa ','Tie ','Fu ','Lian ','Zhi ','Zhou ','Bo ','Zhi ','Di ','Mo ','Yi ', + 'Yi ','Ping ','Qia ','Juan ','Ru ','Shuai ','Dai ','Zheng ','Shui ','Qiao ','Zhen ','Su ','Qun ','Xi ','Bang ','Dai ', + 'Gui ','Chou ','Ping ','Truong ','Sha ','Wan ','Dai ','Wei ','Chang ','Sha ','Qi ','Ze ','Guo ','Mao ','Du ','Hou ', + 'Tranh ','Xu ','Mi ','Wei ','Wo ','Fu ','Yi ','Bang ','Ping ','Tazuna ','Gong ','Pan ','Huang ','Thao ','Mi ','Jia ', + 'Teng ','Hui ','Zhong ','Shan ','Man ','Mu ','Biao ','Guo ','Ze ','Mu ','Bang ','Truong ','Jiong ','Chan ','Fu ','Zhi ', + 'Hu ','Phan ','Choang ','Bi ','Hei ','','Mi ','Qiao ','Chan ','Fen ','Meng ','Bang ','Chou ','Mie ','Chu ','Jie ', + 'Xian ','Lan ','Can ','Ping ','Nian ','Qian ','Bing ','Bing ','Xing ','Gan ','Yao ','Huan ','You ','You ','Ji ','Yan ', + 'Pi ','Ting ','Ze ','Guang ','Chang ','Mo ','Qing ','Bi ','Qin ','Dun ','Sang ','Gui ','Ya ','Bai ','Jie ','Xu ', + 'Lu ','Wu ','','Ku ','Ying ','Di ','Pao ','Dian ','Ya ','Miao ','Canh ','Ci ','Fu ','Tong ','Pang ','Fei ', + 'Xiang ','Yi ','Zhi ','Tiao ','Zhi ','Xiu ','Du ','Toa ','Xiao ','Tu ','Gui ','Kho ','Pang ','Ting ','You ','Bu ', + 'Ding ','Cheng ','Lai ','Bei ','Ji ','Am ','Shu ','Khang ','Yong ','Tuo ','Song ','Shu ','Qing ','Yu ','Yu ','Miao ', + 'Sou ','Ce ','Ruong ','Fei ','Jiu ','He ','Hui ','Liu ','Sha ','Lian ','Lang ','Sou ','Zhi ','Pou ','Qing ','Jiu ', + 'Jiu ','Jin ','Ao ','Kuo ','Lou ','Yin ','Liao ','Dai ','Lu ','Yi ','Chu ','Chan ','Tu ','Si ','Xin ','Miao ', + 'Chang ','Vu ','Fei ','Guang ','Koc ','Kuai ','Bi ','Qiang ','Xie ','Lin ','Lin ','Liao ','Lu ','','Ying ','Xian ', + 'Ting ','Yong ','Li ','Ting ','Yin ','Xun ','Dang ','Ting ','Di ','Po ','Jian ','Hui ','Nai ','Hui ','Trap ','Nian ', + ], + 'x5f':[ + 'Kai ','Bian ','Yi ','Qi ','Long ','Fen ','Ju ','Yan ','Yi ','Zang ','Bi ','Yi ','Yi ','Er ','San ','Shi ', + 'Er ','Shi ','Shi ','Cung ','Diao ','Yin ','Hu ','Phat ','Hong ','Wu ','Tui ','Chi ','Jiang ','Ba ','Shen ','Di ', + 'Zhang ','Jue ','Tao ','Fu ','Di ','Mi ','Xian ','Hu ','Chao ','Nu ','Jing ','Zhen ','Yi ','Mi ','Quan ','Wan ', + 'Shao ','Ruo ','Xuan ','Jing ','Dun ','Truong ','Jiang ','Cang ','Peng ','Dan ','Qiang ','Bi ','Bi ','She ','Dan ','Jian ', + 'Gou ','Sei ','Fa ','Bi ','Kou ','Nagi ','Bie ','Xiao ','Dan ','Kuo ','Cuong ','Hong ','Mi ','Kuo ','Wan ','Jue ', + 'Ji ','Ji ','Gui ','Dang ','Lu ','Lu ','Tuan ','Hui ','Zhi ','Hui ','Hui ','Yi ','Yi ','Yi ','Yi ','Huo ', + 'Huo ','Shan ','Xing ','Wen ','Tong ','Yan ','Yan ','Yu ','Chi ','Cai ','Biao ','Diao ','Ban ','Banh ','Yong ','Piao ', + 'Zhang ','Ying ','Chi ','Chi ','Zhuo ','Tuo ','Ji ','Pang ','Zhong ','Yi ','Wang ','Che ','Bi ','Chi ','Ling ','Phot ', + 'Wang ','Chinh ','Cu ','Wang ','Jing ','Dai ','Xi ','Xun ','Hen ','Yang ','Huai ','Lu ','Hou ','Wa ','Cheng ','Zhi ', + 'Xu ','Jing ','Tu ','Cong ','','Lai ','Cong ','De ','Pai ','Xi ','','Qi ','Chang ','Zhi ','Cong ','Zhou ', + 'Lai ','Yu ','Xie ','Jie ','Jian ','Chi ','Jia ','Bian ','Huang ','Fu ','Xun ','Wei ','Bang ','Yao ','Vi ','Xi ', + 'Zheng ','Piao ','Chi ','De ','Zheng ','Trung ','Bie ','De ','Chong ','Che ','Jiao ','Wei ','Jiao ','Hui ','Mei ','Long ', + 'Xiang ','Bao ','Qu ','Tam ','Ritsushinben ','Tat ','Hat ','Le ','Ren ','Dao ','Ding ','Gai ','Ji ','Ren ','Ren ','Thin ', + 'Tan ','Thac ','Thac ','Gan ','Qi ','Shi ','Cun ','Zhi ','Vong ','Mang ','Xi ','Fan ','Ying ','Tian ','Min ','Min ', + 'Trung ','Chong ','Wu ','Ji ','Wu ','Xi ','Ye ','You ','Wan ','Cong ','Zhong ','Kuai ','Yu ','Bian ','Zhi ','Qi ', + 'Cui ','Chen ','Tai ','Tun ','Qian ','Nian ','Hun ','Xiong ','Niu ','Wang ','Xian ','Xin ','Kang ','Hot ','Kai ','Fen ', + ], + 'x60':[ + 'Huai ','Tai ','Song ','Wu ','Ou ','Chang ','Chuang ','Ju ','Yi ','Bao ','Chao ','Min ','Pei ','Zuo ','Zen ','Yang ', + 'Kou ','Ban ','No ','Nao ','Zheng ','Pa ','Bo ','Tie ','Gu ','Hu ','Ju ','Da ','Lanh ','Tu ','Chou ','Di ', + 'Dai ','Yi ','Tu ','You ','Fu ','Cap ','Peng ','Xing ','Yuan ','Ni ','Guai ','Fu ','Xi ','Bi ','You ','Qie ', + 'Xuan ','Cong ','Bing ','Huang ','Xu ','Truot ','Pi ','Xi ','Xi ','Tan ','Koraeru ','Zong ','Dui ','','Ki ','Yi ', + 'Chi ','Ren ','Xun ','Shi ','Ghet ','Lau ','Heng ','Kuang ','Mu ','Zhi ','Xie ','Lian ','Tiao ','Huang ','Die ','Hao ', + 'Kong ','Nguay ','Heng ','Xi ','Xiao ','Shu ','Shi ','Kua ','Qiu ','Yang ','Hui ','Hui ','Chi ','Jia ','Yi ','Hung ', + 'Guai ','Lin ','Hui ','Zi ','Xu ','Chi ','Xiang ','Nu ','Hen ','En ','Ke ','Tong ','Tian ','Cung ','Quan ','Xi ', + 'Qia ','Yue ','Peng ','Ken ','De ','Hui ','E ','Kyuu ','Tong ','Yan ','Kai ','Ce ','Nao ','Yun ','Mang ','Yong ', + 'Yong ','Yuan ','Pi ','Kun ','Qiao ','Dot ','Yu ','Do ','Jie ','Xi ','Zhe ','Lin ','Ti ','Han ','Hao ','Qie ', + 'Ti ','Bu ','Yi ','Qian ','Hoi ','Xi ','Bei ','Man ','Yi ','Heng ','Song ','Thoan ','Cheng ','Kui ','Wu ','Wu ', + 'You ','Li ','Liang ','Huan ','Cong ','Yi ','Yue ','Li ','Nin ','Nao ','E ','Que ','Xuan ','Qian ','Wu ','Min ', + 'Cong ','Fei ','Bi ','Duo ','Cui ','Chang ','Muon ','Li ','Ji ','Guan ','Guan ','Xing ','Dao ','Qi ','Kong ','Tian ', + 'Lun ','Xi ','Kan ','Kun ','Ni ','Qing ','Chou ','Run ','Guo ','Chan ','Kinh ','Wan ','Yuan ','Cam ','Ji ','Lin ', + 'Yu ','Huo ','He ','Quan ','Tan ','Ti ','Ti ','Nie ','Wang ','Chuo ','Hot ','Hun ','Xi ','Chang ','Xin ','Wei ', + 'Hui ','E ','Rui ','Zong ','Jian ','Yong ','Dian ','Ju ','Can ','Cheng ','De ','Bei ','Qie ','Can ','Dan ','Guan ', + 'Duo ','Nao ','Yun ','Xiang ','Nhoai ','Die ','Hoang ','Chun ','Qiong ','Re ','Xing ','Ce ','Bian ','Hun ','Zong ','Ti ', + ], + 'x61':[ + 'Qiao ','Chou ','Bei ','Xuan ','Wei ','Ge ','Qian ','Wei ','Yu ','Yu ','Bi ','Xuan ','Huan ','Min ','Bi ','Yi ', + 'Mian ','Yong ','Kai ','Dang ','Yin ','E ','Chen ','Mou ','Ke ','Ke ','Ngu ','Ai ','Qie ','Yan ','Nuo ','Gan ', + 'Yun ','Zong ','Sai ','Leng ','Fen ','','Kui ','Kui ','Que ','Gong ','Yun ','Su ','Su ','Qi ','Yao ','Song ', + 'Huang ','Ji ','Gu ','Ju ','Chuang ','Ni ','Xie ','Kai ','Zheng ','Yong ','Cao ','Sun ','Shen ','Bo ','Kai ','Yuan ', + 'Xie ','Hun ','Yong ','Yang ','Li ','Sao ','Tao ','Yin ','Ci ','Xu ','Qian ','Tai ','Huang ','Yun ','Shen ','Ming ', + '','She ','Cong ','Piao ','Mo ','Mo ','Guo ','Chi ','Can ','Can ','Can ','Cui ','Min ','Te ','Zhang ','Tong ', + 'Ao ','Shuang ','Man ','Quen ','Que ','Zao ','Jiu ','Hui ','Kai ','Lian ','Ou ','Tung ','Jin ','Yin ','Lu ','Shang ', + 'Wei ','Tuan ','Man ','Ghen ','She ','Yong ','Qing ','Kang ','Di ','Zhi ','Lou ','Juan ','Qi ','Qi ','Duc ','Ping ', + 'Liao ','Cong ','You ','Chong ','Zhi ','Tong ','Cheng ','Qi ','Qu ','Peng ','Bei ','Bie ','Chun ','Jiao ','Zeng ','Chi ', + 'Lian ','Ping ','Kui ','Hui ','Qiao ','Cheng ','Yin ','Yin ','Xi ','Xi ','Dan ','Tan ','Duo ','Dui ','Dui ','Su ', + 'Jue ','Ce ','Xiao ','Fan ','Fen ','Lao ','Lao ','Chong ','Han ','Qi ','Xian ','Min ','Jing ','Liao ','Wu ','Can ', + 'Jue ','Cu ','Xian ','Tan ','Sheng ','Pi ','Yi ','Chu ','Xian ','Nao ','Dan ','Tan ','Jing ','Song ','Han ','Jiao ', + 'Wai ','Huan ','Dong ','Qin ','Qin ','Qu ','Cao ','Khan ','Xie ','Ying ','Ao ','Mao ','Yi ','Lin ','Se ','Jun ', + 'Huai ','Men ','Lan ','Ai ','Lin ','Yan ','Gua ','Xia ','Chi ','Yu ','Yin ','Dai ','Meng ','Ai ','Mong ','Dui ', + 'Qi ','Mo ','Nham ','Men ','Chou ','Zhi ','Nhua ','Nuo ','Yan ','Yang ','Bo ','Zhi ','Kuang ','Kuang ','You ','Fu ', + 'Liu ','Mie ','Cheng ','','Chan ','Meng ','Lan ','Hoai ','Xuan ','Rang ','Chan ','Ji ','Ju ','Huan ','She ','Yi ', + ], + 'x62':[ + 'Lian ','Nan ','Mi ','Tang ','Jue ','Gang ','Gang ','Gang ','Qua ','Yue ','Wu ','Jian ','Tuat ','Thu ','Nhung ','Xi ', + 'Thanh ','Wo ','Gioi ','Ge ','Jian ','Qiang ','Huo ','Qiang ','Zhan ','Dong ','Qi ','Jia ','Die ','Zei ','Jia ','Ji ', + 'Shi ','Kan ','Ji ','Kui ','Gai ','Deng ','Zhan ','Chuang ','Ge ','Jian ','Jie ','Yu ','Jian ','Yan ','Lu ','Xi ', + 'Zhan ','Xi ','Xi ','Chuo ','Dai ','Qu ','Hu ','Ho ','Hu ','E ','Shi ','Li ','Mao ','Hu ','Li ','Fang ', + 'Suo ','Bian ','Dian ','Jiong ','Shang ','Yi ','Yi ','Shan ','Hu ','Fei ','Yan ','Shou ','Shu ','Tai ','Zha ','Qiu ', + 'Le ','Boc ','Bat ','Da ','Reng ','Chang ','Hameru ','Zai ','Tuo ','Zhang ','Diao ','Giang ','Vo ','Ku ','Han ','Shen ', + 'Xoa ','Yi ','Ngat ','Khau ','Wu ','Tuo ','Qian ','Zhi ','Nhan ','Kuo ','Men ','Sao ','Yang ','Niu ','Ban ','Che ', + 'Rao ','Gap ','Qian ','Ban ','Jia ','Yu ','Phu ','Ao ','Xi ','Pi ','Zhi ','Zi ','E ','Dun ','Quo ','Cheng ', + 'Ji ','Yan ','Kuang ','Bian ','Sao ','Ju ','Wen ','Hu ','Ngoat ','Khoet ','Ba ','Qin ','Zhen ','Zheng ','Yun ','Wan ', + 'Nu ','Yi ','Shu ','Co ','Pou ','Tou ','Dou ','Kang ','Zhe ','Pou ','Fu ','Phao ','Ba ','Ao ','Ze ','Tuan ', + 'Kou ','Lun ','Qiang ','','Hu ','Bao ','Bing ','Zhi ','Banh ','Tan ','Pu ','Pho ','Tai ','Yao ','Zhen ','Zha ', + 'Yang ','Bao ','He ','Nai ','Yi ','Di ','That ','Pho ','Za ','Mo ','Mei ','Shen ','Ya ','Chou ','Qu ','Min ', + 'Chu ','Gio ','Phat ','Zhan ','Zhu ','Dan ','Chai ','Mu ','Nian ','Lap ','Fu ','Pao ','Ban ','Pai ','Ling ','Na ', + 'Guai ','Qian ','Ju ','Tuo ','Ba ','Tuo ','Tuo ','Huc ','Cau ','Chut ','Pan ','Zhao ','Bai ','Bai ','Di ','Ni ', + 'Ju ','Kuo ','Long ','Jian ','','Dung ','Lan ','Ning ','Bo ','Ze ','Tay ','Gan ','Kuo ','Shi ','Cat ','Chung ', + 'Nhum ','Gong ','Gong ','Quan ','Shuan ','Cun ','Zan ','Kao ','Chi ','Xie ','Ce ','Hui ','Phanh ','Ye ','Shi ','Na ', + ], + 'x63':[ + 'Bo ','Chi ','Gua ','Choi ','Quang ','Duo ','Duo ','Zhi ','Qie ','An ','Nong ','Zhen ','Ge ','Gieo ','Ku ','Rung ', + 'Ru ','Tiao ','Tret ','Zha ','Lu ','Die ','Wa ','Jue ','Lyut ','Ju ','Zhi ','Luan ','Ya ','Zhua ','Ta ','Xie ', + 'Nao ','Dang ','Jiao ','Zheng ','Ji ','Hui ','Xun ','Ku ','Ai ','Tuo ','Nuo ','Cuo ','Vot ','Geng ','Ti ','Chan ', + 'Cheng ','Suo ','Suo ','Keng ','Mei ','Long ','Ju ','Vang ','Ken ','Yi ','Ting ','Shan ','Noa ','Wan ','Xie ','Thoc ', + 'Feng ','Keo ','Wu ','Khuan ','Jiu ','Tong ','Kun ','Huo ','Gio ','Zhuo ','Pou ','Le ','Ba ','Han ','Shao ','Nie ', + 'Juan ','Ze ','Song ','Ye ','Jue ','Bu ','Huan ','Bu ','Thoa ','Yi ','Zhai ','Lu ','Sou ','Tuo ','Lao ','Sun ', + 'Banh ','Jian ','Huan ','Dao ','','Uon ','Qin ','Peng ','She ','Lie ','Min ','Men ','Fu ','Bai ','Ju ','Dao ', + 'Wo ','Nhay ','Cuon ','Yue ','Zong ','Chen ','Chui ','Jie ','Tu ','Ben ','Nai ','Nian ','Nuo ','Zu ','Wo ','Xi ', + 'Xian ','Cheng ','Dian ','Sao ','Lun ','Qing ','Gang ','Suot ','Thu ','Trao ','Pou ','Di ','Zhang ','Gun ','Ji ','Tao ', + 'Qia ','Cai ','Bai ','Shu ','Qian ','Ling ','Ye ','Ya ','Jue ','Zheng ','Liang ','Gua ','Yi ','Huo ','Shan ','Zheng ', + 'Luot ','Cai ','Tan ','Che ','Bing ','Jie ','Ti ','Khong ','Suy ','Yan ','Tho ','Zou ','Cuc ','Tian ','Qian ','Ken ', + 'Bai ','Shou ','Jie ','Lu ','Guo ','Haba ','','Zhi ','Dan ','Maang ','Xian ','Sao ','Guan ','Peng ','Yuan ','Nhac ', + 'Jian ','Rinh ','Dua ','Jian ','Yu ','Yan ','Kui ','Nan ','Hong ','Rou ','Pi ','Wei ','Sai ','Zou ','Xuan ','Miao ', + 'Ti ','Nie ','Chap ','Shi ','Zong ','Zhen ','Yi ','Shun ','Heng ','Bian ','Duong ','Huan ','Yan ','Zuan ','An ','Xu ', + 'Ya ','Wo ','Ke ','Chuai ','Ji ','Ti ','La ','La ','Cheng ','Kai ','Jiu ','Jiu ','Dut ','Jie ','Huy ','Geng ', + 'Chong ','Shuo ','She ','Xie ','Yuan ','Qian ','Ye ','Cha ','Zha ','Bei ','Yao ','','Dam ','Lan ','Wen ','Qin ', + ], + 'x64':[ + 'Chan ','Ge ','Lou ','Zong ','Geng ','Jiao ','Cau ','Qin ','Dong ','Que ','So ','Chi ','Zhan ','Ton ','Dun ','Bo ', + 'Chu ','Rong ','Beng ','Sai ','Trao ','Ke ','Gieo ','Dao ','Zhi ','Nu ','Xie ','Gom ','Suu ','Qiu ','Cao ','Xian ', + 'Shuo ','Sang ','Jin ','Mie ','E ','Chui ','Nuo ','Shan ','Ta ','Jie ','Tang ','Pan ','Bung ','Da ','Lat ','Tao ', + 'Hu ','Zhi ','Wa ','Xia ','Qian ','Wen ','Qiang ','Tian ','Zhen ','E ','Xi ','Nuo ','Quan ','Cha ','Zha ','Ge ', + 'Wu ','En ','She ','Kang ','She ','Shu ','Bai ','Yao ','Bin ','Sou ','Tan ','Sa ','Chan ','Suo ','Liao ','Chong ', + 'Chuang ','Guo ','Bing ','Feng ','Shuai ','Di ','Qi ','','Zhai ','Lian ','Tang ','Chi ','Guan ','Lu ','Luo ','Lua ', + 'Zong ','Gai ','Hu ','Zha ','Chuang ','Tang ','Hua ','Cui ','Nai ','Mo ','Ruon ','Gui ','Ying ','Zhi ','Ao ','Zhi ', + 'Nie ','Man ','Shan ','Khua ','Shu ','Suo ','Tuan ','Jiao ','Mo ','Mo ','Zhe ','Shan ','Ken ','Piao ','Jiang ','Yin ', + 'Gou ','Qian ','Liao ','Ji ','Ying ','Quet ','Pie ','Pie ','Lau ','Dun ','Xian ','Ruan ','Quay ','Zan ','Nhat ','Xun ', + 'Cheng ','Cheng ','Sa ','Nheo ','Heng ','Si ','Qian ','Huang ','Da ','Zun ','Nian ','Lin ','Zheng ','Vay ','Chang ','Keo ', + 'Ji ','Cao ','Dan ','Dan ','Che ','Bo ','Che ','Jue ','Xiao ','Liao ','Ben ','Fu ','Qiao ','Bo ','Cuo ','Zhuo ', + 'Zhuan ','Tuo ','Vuc ','Qin ','Dun ','Nian ','','Xie ','Lu ','Jiao ','Cuan ','Ta ','Han ','Qiao ','Zhua ','Jian ', + 'Gan ','Yong ','Lei ','Nong ','Lu ','Chen ','Zhuo ','Ze ','Pu ','Thoc ','Ji ','Dang ','Suo ','Cao ','Qing ','Jing ', + 'Huan ','Jie ','Qin ','Kuai ','Dan ','Xi ','Ge ','Pi ','Bo ','Ao ','Co ','Ye ','','Mang ','Sou ','Mi ', + 'Ji ','Tai ','Zhuo ','Dao ','Xing ','Lan ','Ca ','Ju ','Ye ','Ru ','Ye ','Ye ','Ni ','Wo ','Ji ','Bin ', + 'Ning ','Ge ','Zhi ','Jie ','Kuo ','Mo ','Jian ','Xie ','Lie ','Tan ','Bai ','Sou ','Lu ','Lue ','Rao ','Zhi ', + ], + 'x65':[ + 'Pan ','Yang ','Lei ','Sa ','Shu ','Zan ','Nian ','Xian ','Jun ','Huo ','Li ','La ','Han ','Ying ','Lu ','Long ', + 'Qian ','Qian ','Zan ','Qian ','Dan ','San ','Ying ','Mei ','Rang ','Som ','','Cuan ','Xie ','Nhep ','Ra ','Jun ', + 'Mi ','Li ','Zan ','Luan ','Tan ','Zuan ','Li ','Dian ','Wa ','Dang ','Jiao ','Jue ','Lan ','Li ','Nang ','Chi ', + 'Gui ','Gui ','Qi ','Xin ','Pu ','Sui ','Thu ','Kao ','You ','Gai ','Yi ','Gong ','Gan ','Ban ','Fang ','Zheng ', + 'Bo ','Dian ','Kou ','Min ','Wu ','Co ','He ','Ce ','Xiao ','Mi ','Chu ','Ge ','Di ','Xu ','Jiao ','Min ', + 'Chen ','Jiu ','Zhen ','Duo ','Yu ','Sac ','Ngao ','Bai ','Xu ','Jiao ','Duo ','Lian ','Nie ','Bi ','Chang ','Dian ', + 'Duo ','Yi ','Gan ','San ','Ke ','Yan ','Dun ','Qi ','Dou ','Xiao ','Duo ','Jiao ','Jing ','Yang ','Xia ','Min ', + 'Shu ','Ai ','Xao ','Ai ','Zheng ','Di ','Zhen ','Fu ','So ','Liao ','Qu ','Xiong ','Xi ','Jiao ','Sen ','Jiao ', + 'Zhuo ','Yi ','Lian ','Bi ','Li ','Xiao ','Xiao ','Van ','Xue ','Qi ','Qi ','Zhai ','Bin ','Jue ','Trai ','', + 'Fei ','Ban ','Ban ','Lan ','Yu ','Lan ','Wei ','Dou ','Sheng ','Liao ','Jia ','Hu ','Ta ','Jia ','Yu ','Cham ', + 'Jiao ','Wo ','Tou ','Chu ','Can ','Chi ','Yin ','Bua ','Qiang ','Zhan ','Qu ','Zhuo ','Zhan ','Duan ','Zhuo ','Si ', + 'Tan ','Zhuo ','Zhuo ','Qin ','Lin ','Zhuo ','Chu ','Duan ','Zhu ','Phuong ','Xie ','Hang ','Yu ','Thi ','Pei ','You ', + 'Mye ','Bang ','Qi ','Zhan ','Mao ','Lu ','Pei ','Pi ','Liu ','Fu ','Fang ','Toan ','Tinh ','Jing ','Ni ','Toc ', + 'Zhao ','Yi ','Liu ','Shao ','Jian ','Es ','Yi ','Qi ','Zhi ','Fan ','Piao ','Phuon ','Zhan ','Guai ','Sui ','Yu ', + 'Wu ','Ji ','Ji ','Ji ','Huo ','Ri ','Dan ','Jiu ','Zhi ','Zao ','Xie ','Tiao ','Xun ','Xu ','Xu ','Xu ', + 'Gan ','Han ','Tai ','Di ','Hu ','Chan ','Shi ','Kuang ','Yang ','Shi ','Wang ','Min ','Min ','Tun ','Chun ','Wu ', + ], + 'x66':[ + 'Yun ','Bei ','Ngang ','Ze ','Ban ','Jie ','Con ','Thang ','Hu ','Fang ','Hao ','Gui ','Chang ','Xuan ','Minh ','Hun ', + 'Fen ','Qin ','Hu ','Yi ','Xi ','Xin ','Yan ','Ze ','Fang ','Tan ','Shen ','Ju ','Yang ','Zan ','Bing ','Tinh ', + 'Ying ','Xuan ','Pei ','Zhen ','Ling ','Chun ','Hao ','Muoi ','Zuo ','Mo ','Bian ','Xu ','Hun ','Zhao ','Zong ','Shi ', + 'Shi ','Yu ','Fei ','Die ','Mao ','Ni ','Chang ','Wen ','Dong ','Ai ','Bing ','Ang ','Zhou ','Long ','Xian ','Kuang ', + 'Tiao ','Chao ','Shi ','Huang ','Huang ','Xuan ','Kui ','Xu ','Jiao ','Jin ','Zhi ','Jin ','Shang ','Tong ','Hong ','Yan ', + 'Gai ','Xiang ','Shai ','Xiao ','Ye ','Yun ','Hui ','Han ','Han ','Jun ','Wan ','Xian ','Kun ','Zhou ','Xi ','Sheng ', + 'Sheng ','Bu ','Zhe ','Zhe ','Wu ','Han ','Hui ','Hao ','Chen ','Wan ','Tian ','Zhuo ','Zui ','Zhou ','Pu ','Jing ', + 'Xi ','Shan ','Yi ','Xi ','Qing ','Qi ','Tinh ','Gui ','Zhen ','Yi ','Zhi ','An ','Wan ','Lin ','Liang ','Chang ', + 'Wang ','Xiao ','Zan ','Hi ','Xuan ','Xuan ','Yi ','Xia ','Yun ','Hui ','Fu ','Min ','Kui ','He ','Ying ','Du ', + 'Wei ','Shu ','Qing ','Mao ','Nan ','Jian ','Nuan ','An ','Yang ','Chun ','Yao ','Suo ','Jin ','Ming ','Jiao ','Kai ', + 'Gao ','Weng ','Suong ','Qi ','Hao ','Yan ','Li ','Ai ','Ji ','Gui ','Men ','Zan ','Xie ','Hao ','Mo ','Mo ', + 'Cong ','Ni ','Zhang ','Hui ','Bao ','Han ','Xuan ','Chuan ','Liao ','Xian ','Dan ','Jing ','Pie ','Lin ','Tun ','Xi ', + 'Yi ','Ji ','Huang ','Tai ','Ye ','Ye ','Li ','Tan ','Tong ','Xiao ','Fei ','Qin ','Zhao ','Hao ','Yi ','Xiang ', + 'Xing ','Sen ','Jiao ','Bao ','Jing ','Yan ','Ai ','Ye ','Ru ','Shu ','Meng ','Xun ','Yao ','Pu ','Li ','Chen ', + 'Kuang ','Die ','','Yan ','Huo ','Trua ','Xi ','Rong ','Long ','Nang ','Luo ','Luan ','Shai ','Tang ','Yan ','Chu ', + 'Yue ','Yue ','Khuc ','Day ','Xau ','Ye ','Hu ','He ','Thu ','Tao ','Cao ','Shou ','Man ','Ceng ','Ceng ','Ti ', + ], + 'x67':[ + 'Toi ','Can ','Xu ','Hoi ','Yin ','Qie ','Fen ','Pi ','Yue ','You ','Ruan ','Peng ','Ban ','Phuc ','Ling ','Xoet ', + 'Qu ','','Nu ','Tiao ','Shuo ','Zhen ','Lang ','Lang ','Juan ','Ming ','Huang ','Vong ','Tun ','Zhao ','Ji ','Qi ', + 'Ying ','Zong ','Wang ','Tong ','Lang ','','Meng ','Long ','Moc ','Deng ','Mui ','Mo ','Ben ','Zha ','Shu ','Zhu ', + '','Cho ','Ren ','Ba ','Phac ','Duo ','Duo ','Dao ','Li ','Qiu ','Co ','Jiu ','Bi ','Xiu ','Ting ','Ci ', + 'Sha ','Eburi ','Za ','Quan ','Then ','Vu ','Con ','Wu ','Cha ','Shan ','Xun ','Fan ','Wu ','Zi ','Li ','Xing ', + 'Cai ','Cun ','Ren ','Shao ','Tuo ','Di ','Zhang ','Mang ','Chi ','Yi ','Gu ','Gong ','Du ','Yi ','Qi ','Thut ', + 'Gang ','Tiao ','Moku ','Son ','Tochi ','Lai ','Sugi ','Mang ','Yang ','Ma ','Miao ','Si ','Yuan ','Hang ','Fei ','Bei ', + 'Jie ','Hoc ','Gao ','Yao ','Xian ','Chu ','Chun ','Pa ','Shu ','Hua ','Tam ','Chou ','Zhu ','Chou ','Tung ','Ban ', + 'Song ','Ji ','Yue ','Jin ','Gou ','Ji ','Mao ','Pi ','Bi ','Wang ','Ang ','Fang ','Fen ','Yi ','Fu ','Nan ', + 'Xi ','Hu ','Ya ','Dou ','Xun ','Zhen ','Yao ','Lam ','Rui ','E ','Mai ','Zhao ','Guo ','Chi ','Cong ','Yun ', + 'Waku ','Dou ','Shu ','Zao ','','Li ','Ro ','Jian ','Cheng ','Shou ','Qiang ','Feng ','Nan ','Xiao ','Sim ','Ku ', + 'Ping ','Yi ','Xi ','Zhi ','Guai ','Xiao ','Jia ','Da ','Cu ','Fu ','Mo ','Yi ','Ye ','Ye ','Shi ','Nie ', + 'Bi ','Xa ','Yi ','Ranh ','Bing ','Ni ','La ','He ','Pan ','Muop ','Zhong ','Dai ','Ci ','Yang ','Fu ','Bai ', + 'Mou ','Gan ','Qi ','Nhuom ','Nhu ','Mao ','Zhao ','Song ','Zhe ','Xia ','Dau ','Shen ','Gui ','Tuo ','Zuo ','Nan ', + 'Ning ','Yong ','Di ','Zhi ','Zha ','Tra ','Dan ','Gu ','','Jiu ','Ao ','Fu ','Jian ','Bo ','Duo ','Ke ', + 'Nai ','Tru ','Bi ','Liu ','Sai ','Zha ','Si ','Zhu ','Pei ','Shi ','Guai ','Cha ','Yao ','Jue ','Jiu ','Shi ', + ], + 'x68':[ + 'Zhi ','Liu ','Mei ','Tochi ','Rong ','Zha ','','Biao ','Zhan ','Jie ','Long ','Dong ','Lu ','Sanh ','Li ','Lan ', + 'Vanh ','Shu ','Xun ','Thoen ','Qi ','Zhen ','Qi ','Li ','Yi ','Xiang ','Zhen ','Li ','Su ','Gua ','Kan ','Bing ', + 'Ren ','Xiao ','Bo ','Ren ','Bing ','Zi ','Chou ','Yi ','Jie ','Xu ','Zhu ','Jian ','Zui ','Er ','Er ','You ', + 'Fa ','Gong ','Kao ','Lao ','Zhan ','Li ','','Yang ','He ','Can ','Zhi ','Shi ','Ge ','Zai ','Luan ','Fu ', + 'Jie ','Hanh ','Gui ','Tao ','Quang ','Wei ','Kuang ','Ru ','An ','An ','Juan ','Yi ','Zhuo ','Ku ','Chuoi ','Qiong ', + 'Tong ','Tang ','Sang ','Huan ','Jie ','Jiu ','Xue ','Duo ','Zhui ','Yu ','Zan ','Kasei ','Ying ','Masu ','','Zhan ', + 'Ya ','Nao ','Zhen ','Dang ','Qi ','Qiao ','Hua ','Kuai ','Jiang ','Zhuang ','Xun ','Suo ','Sha ','Zhen ','Bei ','Ting ', + 'Gua ','Jing ','Vut ','Ben ','Fu ','Rui ','Thung ','Jue ','Xi ','Lang ','Liu ','Feng ','Qi ','Wen ','Jun ','Gan ', + 'Cu ','Luong ','Qiu ','Ting ','You ','Mai ','Buong ','Long ','Peng ','Zhuang ','Di ','Xuan ','Tu ','Zao ','Ao ','Gu ', + 'Bi ','Di ','Han ','Zi ','Zhi ','Ren ','Voi ','Geng ','Jian ','Huan ','Wan ','Nuo ','Jia ','Tiao ','Ji ','Xiao ', + 'Lu ','Hun ','Shao ','Cen ','Fen ','Song ','Meng ','Wu ','Li ','Li ','Dou ','Cen ','Ying ','Thoi ','Coc ','Ti ', + 'Gioi ','Kun ','Zhuo ','So ','Chan ','Fan ','Wei ','Jing ','Li ','Bing ','Fumoto ','Shikimi ','Tao ','Zhi ','Lai ','Lian ', + 'Jian ','Zhuo ','Ranh ','Li ','Qi ','Bing ','Zhun ','Cong ','Qian ','Mian ','Qi ','Qi ','Cai ','Gun ','Chan ','Te ', + 'Fei ','Pai ','Bang ','Pou ','Hun ','Zong ','Cheng ','Zao ','Gac ','Li ','Peng ','Yu ','Yu ','Gu ','Hun ','Nham ', + 'Tang ','Gang ','Wang ','Di ','Xi ','Fan ','Ranh ','Zhan ','Qi ','Yuan ','Yan ','Yu ','Quan ','Yi ','Chum ','Ren ', + 'Chui ','Sang ','Qi ','Zhuo ','Fu ','Ke ','Lai ','Zou ','Zou ','Zhuo ','Quan ','Fen ','Fen ','Chen ','Qiong ','Nie ', + ], + 'x69':[ + 'Wan ','Guo ','Lu ','Hao ','Jie ','Yi ','Chou ','Gu ','Ju ','Cheng ','Chot ','Liang ','Qiang ','Zhi ','Zhui ','Ya ', + 'Ju ','Bei ','Jiao ','Zhuo ','Zi ','Bin ','Peng ','Ding ','Chu ','Sugi ','Mun ','Momiji ','Jian ','Gui ','Xi ','Du ', + 'Qian ','Kunugi ','Kai ','Shide ','Luo ','Tre ','Ken ','Myeng ','Tafu ','','Peng ','Zhan ','','Tuo ','Sen ','Duo ', + 'Da ','Fou ','Wei ','Wei ','Duan ','Jia ','Zong ','Jian ','Yi ','Shen ','Xi ','Yan ','Yan ','Chuan ','Zhan ','Chun ', + 'Yu ','He ','Zha ','Wo ','Pian ','Bi ','Yao ','Huo ','Xu ','Ruo ','Duong ','La ','Yan ','Ben ','Hun ','Kui ', + 'Jie ','Kui ','Si ','Phong ','Xie ','Tuo ','Zhi ','Jian ','Mu ','Mao ','Chu ','Hu ','Hu ','Lian ','Leng ','Ting ', + 'Nan ','Yu ','Giua ','Me ','Song ','Xuan ','Xuan ','Ying ','Zhen ','Pian ','Ye ','Ji ','Jie ','Ye ','Chu ','Shun ', + 'Yu ','Cou ','Wei ','Mei ','Di ','Ji ','Jie ','Kai ','Qiu ','Ying ','Rou ','Heng ','Lou ','Le ','Hazou ','Katsura ', + 'Pin ','Muro ','Gai ','Tan ','Lan ','Yun ','Yu ','Chen ','Lu ','Ju ','Sakaki ','','Pi ','Xie ','Jia ','Yi ', + 'Zhan ','Fu ','Nai ','Mi ','Lang ','Rong ','Keo ','Jian ','Ju ','Ta ','Yao ','Zhen ','Bang ','Sha ','Yuan ','Zi ', + 'Ming ','Su ','Jia ','Yao ','Jie ','Huang ','Gan ','Fei ','Zha ','Qian ','Ma ','Sun ','Yuan ','Xie ','Vinh ','Shi ', + 'Zhi ','Cui ','Yun ','Ting ','Liu ','Rong ','Tang ','Que ','Zhai ','Si ','Sheng ','Ta ','Ke ','Xi ','Cot ','Qi ', + 'Kao ','Cau ','Sun ','Ban ','Tao ','Ge ','Xun ','Dian ','Noc ','Ji ','Shuo ','Gou ','Dui ','Thuong ','Xay ','Qian ', + 'Huai ','Mei ','Suc ','Gang ','Cau ','Zhuo ','Tuo ','Kyou ','Yang ','Dian ','Jia ','Jian ','Zui ','Tou ','Rou ','Bin ', + 'Zhu ','','Xi ','Qi ','Lian ','Hui ','Yong ','Qian ','Guo ','Gai ','Gai ','Tuan ','Hua ','Cu ','Sen ','Cui ', + 'Beng ','You ','Hu ','Jiang ','Hu ','Huan ','Guoc ','Yi ','Nie ','Gao ','Kang ','Gui ','Gui ','Tau ','Man ','Jin ', + ], + 'x6a':[ + 'Di ','Thung ','Le ','Lang ','Chen ','Cong ','Li ','Xiu ','Qing ','Shuang ','Phan ','Tong ','Guan ','Ji ','Suo ','Lei ', + 'Lu ','Liang ','Mi ','Lou ','Sao ','Su ','Ke ','Vu ','Tang ','Biao ','Lu ','Jiu ','Shu ','Zha ','Xu ','Zhang ', + 'Men ','Mo ','Niao ','Yang ','Tiao ','Peng ','Zhu ','Sha ','Xi ','Quan ','Heng ','Jian ','Cong ','','Hokuso ','Qiang ', + 'Tara ','Ying ','Er ','Xin ','Zhi ','Qiao ','Chuoi ','Cong ','Pu ','Thu ','Hua ','Kui ','Zhen ','Zun ','Yue ','Zhan ', + 'Xi ','Xun ','Dian ','Fa ','Gan ','Mo ','Wu ','Qiao ','Nao ','Sang ','Liu ','Qiao ','Xian ','Run ','Fan ','Zhan ', + 'Tuo ','Lao ','Yun ','Shun ','Tui ','Cheng ','Tang ','Meng ','Quat ','Chanh ','Su ','Cot ','Jue ','Tan ','Hui ','Co ', + 'Nuo ','Xiang ','Tuo ','Ning ','Rui ','Zhu ','Chuang ','Zeng ','Fen ','Qiong ','Ran ','Heng ','Tram ','Gu ','Liu ','Rao ', + 'Gao ','Chu ','Zusa ','Nude ','Ca ','San ','Ji ','Dau ','Shou ','Lu ','Gian ','','Yuan ','Thot ','Shu ','Jiang ', + 'Tan ','Day ','Nong ','Yin ','Xi ','Sui ','Shan ','Zui ','Xuan ','Cheng ','Gan ','Ju ','Zui ','Yi ','Qin ','Pu ', + 'Yan ','Rui ','Feng ','Hui ','Dang ','Ji ','Sui ','Bo ','Bi ','Ding ','Chu ','Zhua ','Coi ','Ji ','Jie ','Jia ', + 'Qing ','Zhe ','Ghem ','Qiang ','Dao ','Yi ','Biao ','Song ','She ','Lin ','Reki ','Cha ','Meng ','Yin ','Tao ','Tai ', + 'Mian ','Qi ','','Bin ','Huo ','Ji ','Qian ','Mi ','Ning ','Yi ','Cao ','Jian ','Yin ','Er ','Qing ','Yan ', + 'Qi ','Mi ','Zhao ','Gui ','Chun ','Ji ','Kui ','Po ','Deng ','Chu ','Han ','Mian ','You ','Zhi ','Guang ','Qian ', + 'Lei ','Lei ','Sa ','Lu ','Li ','Cuan ','Lu ','Mie ','Hui ','Ou ','Lu ','Jie ','Gao ','Du ','Yuan ','Li ', + 'Fei ','Zhuo ','Sou ','Lian ','Sen ','Chu ','','Zhu ','Lu ','Yan ','Li ','Zhu ','Chen ','Jie ','E ','Su ', + 'Huai ','Nie ','Yu ','Long ','Lai ','','Xian ','Kwi ','Ju ','Xiao ','Ling ','Ying ','Jian ','Yin ','You ','Ying ', + ], + 'x6b':[ + 'Xiang ','Nong ','Bo ','Chan ','Lan ','Ju ','Shuang ','She ','Wei ','Cong ','Quan ','Qu ','Cang ','','Yu ','Luo ', + 'Li ','Zan ','Luan ','Dang ','Jue ','Em ','Lan ','Lan ','Zhu ','Lei ','Li ','Ba ','Nang ','Yu ','Ling ','Tsuki ', + 'Qian ','Ci ','Huan ','Han ','Yu ','Yu ','Qian ','Ou ','Xu ','Chao ','Chu ','Chi ','Kai ','Yi ','Jue ','Xi ', + 'Xu ','Xia ','Duc ','Kuai ','Lang ','Kuan ','Shuo ','Xi ','Ai ','Yi ','Khi ','Xu ','Chi ','Kham ','Kuan ','Kan ', + 'Kuan ','Kan ','Chuan ','Sha ','','Yin ','Can ','Xie ','Yu ','Qian ','Xiao ','Yi ','Ca ','Wu ','Tan ','Jin ', + 'Ou ','Hu ','Ti ','Huan ','Xu ','Pen ','Xi ','Xiao ','Xu ','Xi ','Sen ','Han ','Chu ','Yi ','Kan ','Ru ', + 'Chuo ','Hoan ','Zhi ','Zheng ','Thu ','Bo ','Wu ','Qi ','Bu ','Bu ','Quay ','Ju ','Qian ','Chi ','Se ','Chi ', + 'Se ','Zhong ','Sui ','Sui ','Li ','Cuo ','Yu ','Li ','Gui ','Dai ','Dai ','Phoi ','Jian ','Zhe ','Mo ','Mo ', + 'Yao ','Mo ','Cu ','Trua ','Tian ','Sheng ','Dai ','Shang ','Xu ','Xun ','Thua ','Can ','Jue ','Piao ','Qia ','Qiu ', + 'Su ','Qing ','Yun ','Lian ','Yi ','Fou ','Zhi ','Ye ','Can ','Hun ','Dan ','Ji ','Ye ','','Yun ','Wen ', + 'Chou ','Bin ','Ti ','Jin ','Shang ','Yin ','Diao ','Cu ','Hui ','Cuan ','Yi ','Dan ','Du ','Jiang ','Lian ','Tan ', + 'Du ','Sen ','Jian ','Shu ','Ou ','Duan ','Zhu ','Yin ','Qing ','Yi ','Sha ','Que ','Ke ','Yao ','Jun ','Dian ', + 'Hui ','Hui ','Gu ','Que ','Ji ','Yi ','Ou ','Hui ','Duan ','Yi ','Xiao ','Wu ','Guan ','Mu ','Mei ','Mei ', + 'Ai ','Zuo ','Du ','Yu ','Bi ','Bi ','Bi ','Pi ','Pi ','Bi ','Chan ','Mao ','','','Pu ','Mushiru ', + 'Jia ','Zhan ','Sai ','Mu ','Tuo ','Xun ','Er ','Rong ','Xian ','Ju ','Mu ','Hao ','Qiu ','Dou ','Mushiru ','Tan ', + 'Pei ','Ju ','Duo ','Cui ','Bi ','San ','','Mao ','Sui ','Shu ','Yu ','Tuo ','He ','Jian ','Ta ','San ', + ], + 'x6c':[ + 'Lu ','Mu ','Li ','Tong ','Rong ','Chang ','Pu ','Luo ','Chen ','Sao ','Zhan ','Meng ','Luo ','Qu ','Die ','Shi ', + 'Di ','Dan ','Jue ','Manh ','Qi ','Pie ','Nai ','Qi ','Dao ','Xian ','Chuan ','Fen ','Ri ','Nei ','','Fu ', + 'Shen ','Dong ','Qing ','Qi ','Yin ','Xi ','Hai ','Yang ','An ','Ya ','Ke ','Qing ','Ya ','Dong ','Dan ','Lu ', + 'Qing ','Yang ','Yun ','Yun ','Heo ','Sanzui ','Zheng ','Bing ','Vang ','Dang ','Sui ','Le ','Ni ','Tun ','Fan ','Gui ', + 'Ting ','Chap ','Qiu ','Bin ','Ze ','Mian ','Cuan ','Hui ','Diao ','Yi ','Xoa ','Zhuo ','Chuan ','Wan ','Fan ','Dai ', + 'Xi ','Tuo ','Mang ','Qiu ','Qi ','Khung ','Pai ','Han ','Qian ','Wu ','Wu ','Vam ','Si ','Nho ','Gong ','Giang ', + 'Chi ','Wu ','Tsuchi ','','Tang ','Zhi ','Chi ','Qian ','Mi ','Gu ','Wang ','Qing ','Jing ','Rui ','Jun ','Hong ', + 'Tai ','Quan ','Cum ','Bian ','Bian ','Ngam ','Wen ','Zhong ','Fang ','Xiong ','Jue ','Hang ','','Qi ','Fen ','Do ', + 'Xu ','Tam ','Yi ','Wo ','Yun ','Yuan ','Hang ','Yan ','Chen ','Chen ','Dan ','You ','Xon ','Hu ','Huo ','Qi ', + 'Muc ','Rou ','Mo ','Ta ','Mian ','Vat ','Khem ','Tian ','Bi ','Vanh ','Zhi ','Pei ','Pan ','Zhui ','Za ','Gou ', + 'Liu ','Mei ','Ze ','Feng ','Ou ','Li ','Lun ','Cang ','Feng ','Wei ','Hu ','Mo ','Mei ','Shu ','Ju ','Zan ', + 'Tuo ','Sang ','Tuo ','Ha ','Li ','Mi ','Yi ','Fa ','Fei ','You ','Tian ','Zhi ','Zhao ','Gu ','Cham ','Yan ', + 'Si ','Kuang ','Jiong ','Ju ','Tuot ','Tu ','Yi ','Jia ','Zhong ','Quan ','Bo ','Hui ','Mi ','Ben ','Zhuo ','Chu ', + 'Le ','Ao ','Gu ','Hong ','Gan ','Fa ','Mao ','Si ','Hu ','Ping ','Ci ','Fan ','Chi ','Su ','Ning ','Cheng ', + 'Ling ','Bau ','Ba ','Khap ','Si ','Ni ','Ju ','Yue ','Chu ','Sheng ','Thot ','Xuan ','Xue ','Fu ','Pan ','Min ', + 'Tai ','Yang ','Ji ','Yong ','Guan ','Beng ','Xue ','Long ','Lu ','','Bo ','Xie ','Po ','Ze ','Jing ','Yin ', + ], + 'x6d':[ + 'Zhou ','Ji ','Yi ','Hui ','Hui ','Tuoi ','Cheng ','Yin ','Wei ','Hou ','Jian ','Duong ','Ret ','Si ','Ji ','Er ', + 'Xing ','Fu ','Sa ','Suo ','Zhi ','Yin ','Wu ','Xi ','Kao ','Chua ','Jiang ','Luo ','','An ','Dong ','Yi ', + 'Mou ','Gioi ','Yi ','Mi ','Quan ','Jin ','Mo ','Wei ','Xiao ','Xie ','Hong ','Xu ','Shuo ','Kuang ','Tao ','Qie ', + 'Ju ','Er ','Zhou ','Nho ','Ping ','Xun ','Xiong ','Zhi ','Guang ','Huan ','Ming ','Huo ','Wa ','Qia ','Pai ','Wu ', + 'Qu ','Luu ','Yi ','Jia ','Jing ','Qian ','Jiang ','Jiao ','Cheng ','Shi ','Zhuo ','Ce ','Pal ','Kuai ','Ji ','Liu ', + 'Chan ','Hun ','Hu ','Nong ','Xun ','Jin ','Lie ','Gau ','Wei ','Zhe ','Jun ','Han ','Bang ','Mang ','Zhuo ','You ', + 'Ho ','Bot ','Dou ','Wan ','Hong ','Yi ','Pu ','Ying ','Lan ','Hao ','Lang ','Han ','Li ','Geng ','Phu ','Wu ', + 'Lian ','Chun ','Feng ','Yi ','Yu ','Tong ','Lao ','Hai ','Tam ','Jia ','Chong ','Weng ','Mei ','Sui ','Cheng ','Pei ', + 'Xian ','Shen ','Do ','Kun ','Pin ','Nie ','Han ','Kinh ','Xiao ','She ','Nian ','Tu ','Yong ','Xiao ','Xian ','Ting ', + 'E ','Su ','Tun ','Quen ','Cen ','Ti ','Rang ','Shui ','Si ','Lei ','Shui ','Tao ','Du ','Lao ','Thui ','Lian ', + 'Wei ','Wo ','Yun ','Huan ','Di ','','Run ','Jian ','Zhang ','Se ','Fu ','Guan ','Xing ','Shou ','Shuan ','Ya ', + 'Chuo ','Zhang ','Ye ','Kong ','Wo ','Han ','Tuo ','Dong ','He ','Wo ','Ju ','Gan ','Luong ','Hun ','Ta ','Zhuo ', + 'Dian ','Qie ','De ','Juan ','Zi ','Xi ','Yao ','Qi ','Gu ','Guo ','Han ','Lam ','Tang ','Zhou ','Peng ','Hao ', + 'Chang ','Shu ','Qi ','Fang ','Chi ','Lu ','Nao ','Ju ','Tao ','Cong ','Lei ','Zhi ','Peng ','Fei ','Song ','Tian ', + 'Pi ','Dan ','Yu ','Ni ','Yu ','Lu ','Gan ','Mi ','Jing ','Lang ','Lun ','Dam ','Cui ','Qu ','Hoai ','Roc ', + 'Nian ','Tham ','Piao ','Choang ','Wa ','Yuan ','Lai ','Hun ','Qing ','Yan ','Qian ','Tian ','Miao ','Zhi ','Yin ','Mi ', + ], + 'x6e':[ + 'Ben ','Yuan ','Wen ','Nuoc ','Fei ','Thanh ','Yuan ','Ke ','Ji ','She ','Yuan ','Juu ','Lu ','Zi ','Du ','', + 'Jian ','Min ','Pi ','Kei ','Yu ','Yuan ','Shen ','Shen ','Rou ','Huan ','Zhu ','Jian ','Nuan ','Yu ','Qiu ','Ting ', + 'Qu ','Du ','Feng ','Zha ','Bot ','Wo ','Wo ','Di ','Wei ','Wen ','Ru ','Xie ','Trac ','Ngan ','Ge ','Gang ', + 'Yan ','Hong ','Xuan ','Mi ','Ke ','Mao ','Ying ','Yan ','You ','Hong ','Miao ','Xing ','Mei ','Zai ','Hun ','Nai ', + 'Kui ','Shi ','E ','Pai ','Mua ','Lian ','Qi ','Qi ','Mei ','Tian ','Cou ','Wei ','Can ','Tuan ','Mian ','Hui ', + 'Mo ','Xu ','Ji ','Bun ','Jian ','Jian ','Hu ','Feng ','Tuong ','Yi ','Yin ','Zhan ','Shi ','Jie ','Cheng ','Huang ', + 'Tan ','Yu ','Bi ','Min ','Shi ','Dot ','Sheng ','Rung ','Xo ','Zhong ','','Jiao ','Jiao ','qiu ','Yin ','Thang ', + 'Long ','Huo ','Yuan ','Nuom ','Ban ','You ','Quan ','Chui ','Liang ','Chan ','Yan ','Chun ','Nie ','Zi ','Wan ','Shi ', + 'Man ','Ying ','Ratsu ','Kui ','','Jian ','Xu ','Lu ','Gui ','Gai ','','','Po ','Jin ','Gui ','Tang ', + 'Yuan ','Suo ','Yuan ','Lian ','Yao ','Trung ','Zhun ','Sheng ','Hup ','Tai ','Da ','Wa ','Liu ','Gou ','Sao ','Ming ', + 'Zha ','Shi ','Yi ','Lun ','Ma ','Pu ','Wei ','Rot ','Cai ','Wu ','Khe ','Wen ','Qiang ','Ze ','Shi ','Su ', + 'Yi ','Zhen ','Sou ','Yun ','Xiu ','Yin ','Rong ','Hun ','Su ','Su ','Ni ','Ta ','Shi ','Ru ','Wei ','Pan ', + 'Soc ','Chu ','Pang ','Weng ','Cang ','Mie ','He ','Chan ','Hao ','Huang ','Xi ','Zi ','Di ','Zhi ','Xing ','Fu ', + 'Jie ','Got ','Ge ','Zi ','Thao ','Teng ','Sui ','Bi ','Jiao ','Hui ','Gun ','Yin ','Gao ','Long ','Zhi ','Yan ', + 'She ','Man ','Ying ','Chun ','Lu ','Lan ','Luan ','','Bin ','Tan ','Yu ','Sou ','Hu ','Bi ','Biao ','Zhi ', + 'Jiang ','Kou ','Ruom ','Shang ','Di ','Mi ','Ao ','Lu ','Hu ','Hu ','You ','Chan ','Fan ','Yong ','Gun ','Man ', + ], + 'x6f':[ + 'Qing ','Ngu ','Piao ','Ji ','Ya ','Jiao ','Qi ','Xi ','Ji ','Loc ','Sau ','Long ','Jin ','Guo ','Cong ','Lou ', + 'Zhi ','Ngay ','Qiang ','Li ','Yan ','Cao ','Jiao ','Cong ','Chun ','Tuan ','Ou ','Teng ','Ye ','Xi ','Mi ','Tang ', + 'Mo ','Shang ','Han ','Lan ','Lan ','Wa ','Li ','Qian ','Vung ','Xuan ','Yi ','Man ','Zi ','Mang ','Kang ','Ta ', + 'Peng ','Shu ','Truong ','Zhang ','Chong ','Xu ','Huan ','Kuo ','Jian ','Yan ','Chuang ','Liao ','Cui ','Ti ','Yang ','Jiang ', + 'Cong ','Ying ','Hong ','Xun ','Shu ','Guan ','Ying ','Xiao ','','','Xu ','Lian ','Zhi ','Wei ','Pi ','Jue ', + 'Jiao ','Po ','Dang ','Hui ','Jie ','Wu ','Pa ','Ji ','Pan ','Voi ','Xiao ','Qian ','Qian ','Xi ','Lu ','Xi ', + 'Lun ','Dun ','Huang ','Min ','Run ','Su ','Lao ','Zhen ','Zhong ','Yi ','Di ','Wan ','Dan ','Tan ','Chao ','Xun ', + 'Kui ','','Shao ','Tu ','Zhu ','San ','Hei ','Vuot ','Shan ','Chan ','Chan ','Shu ','Tong ','Pu ','Lin ','Wei ', + 'Se ','Se ','Cheng ','Jiong ','Cheng ','Hua ','Khu ','Lao ','Che ','Gan ','Cun ','Heng ','Si ','Shu ','Peng ','Han ', + 'Yun ','Liu ','Hong ','Fu ','Hao ','He ','Xian ','Jian ','Shan ','Xi ','Iku ','','Lan ','','Yu ','Lin ', + 'Mian ','Zao ','Dang ','Huan ','Ze ','Xie ','Yu ','Li ','Shi ','Xue ','Ling ','Man ','Zi ','Yong ','Goi ','Can ', + 'Lian ','Dian ','Ye ','Ao ','Huan ','Zhen ','Chan ','Man ','Dan ','Dan ','Yi ','Sui ','Pi ','Ju ','Ta ','Qin ', + 'Ji ','Troc ','Lian ','Nong ','Guo ','Jin ','Fen ','Se ','Xap ','Sui ','Hui ','Chu ','Ta ','Song ','Ding ','', + 'Zhu ','Lai ','Bin ','Lian ','Mi ','Shi ','Shu ','Mi ','Ning ','Ying ','Ying ','Meng ','Jin ','Qi ','Tia ','Ji ', + 'Hao ','Nhua ','Zui ','Wo ','Tao ','Yin ','Yin ','Dui ','Ci ','Huo ','Jing ','Lan ','Jun ','Ai ','Pu ','Zhuo ', + 'Wei ','Bin ','Gu ','Qian ','Xing ','Ban ','Kuo ','Fei ','','Boku ','Jian ','Wei ','Luo ','Zan ','Lu ','Li ', + ], + 'x70':[ + 'You ','Yang ','Lu ','Si ','Jie ','Ying ','Du ','Wang ','Hui ','Xie ','Pan ','Shen ','Biao ','Chan ','Mo ','Liu ', + 'Tuom ','Pu ','Se ','Cheng ','Gu ','Bin ','Huo ','Xian ','Lu ','Qin ','Han ','Ying ','Yong ','Li ','Jing ','Xiao ', + 'Ying ','Sui ','Wei ','Xie ','Huai ','Hao ','Zhu ','Long ','Lai ','Dui ','Fan ','Hu ','Lai ','','','Ying ', + 'Mi ','Ji ','Lian ','Jian ','Ying ','Fen ','Lin ','Yi ','Jian ','Yue ','Chan ','Dai ','Rang ','Jian ','Nham ','Fan ', + 'Shuang ','Yuan ','Zhuo ','Feng ','She ','Lei ','Lan ','Cong ','Qu ','Yong ','Qian ','Fa ','Guan ','Que ','Yan ','Hao ', + 'Hyeng ','Ngo ','Zan ','Luan ','Yan ','Li ','Mi ','Shan ','Tan ','Dang ','Jiao ','Chan ','','Hao ','Ba ','Luoc ', + 'Lan ','Lan ','Nang ','Wan ','Luan ','Xun ','Xian ','Yan ','Gan ','Yan ','Yu ','Huo ','Biao ','Mie ','Guang ','Deng ', + 'Hui ','Xiao ','Xiao ','','Hong ','Linh ','Zao ','Zhuan ','Jiu ','Zha ','Xie ','Chi ','Chuoc ','Tai ','Tai ','Can ', + 'Yang ','Qi ','Zhong ','Fen ','Niu ','Jiong ','Wen ','Po ','Yi ','Lu ','Chui ','Pi ','Kai ','Pan ','Yan ','Kai ', + 'Pang ','Mu ','Sao ','Liao ','Gui ','Kang ','Tun ','Guang ','Xin ','Zhi ','Kwang ','Guang ','Wei ','Qiang ','','Da ', + 'Xia ','Zheng ','Zhu ','Ke ','Zhao ','Phut ','Ba ','Duo ','Duo ','Ling ','Zhuo ','Xuan ','Ju ','Than ','Pao ','Jiong ', + 'Pao ','Tai ','Tai ','Bing ','Yang ','Tong ','Han ','Zhu ','Zha ','Dian ','Wei ','Shi ','Lian ','Chi ','Huang ','', + 'Hu ','Shuo ','Lan ','Jing ','Jiao ','Xu ','Xing ','Quan ','Lie ','Huan ','Rang ','Xiao ','Xiu ','Xian ','Yin ','Wu ', + 'Zhou ','Yao ','Shi ','Wei ','Tong ','Xue ','Zai ','Kai ','Hong ','Luo ','Xia ','Chuc ','Xuan ','Chung ','Po ','Yan ', + 'Hui ','Guang ','Zhe ','Tro ','Kao ','','Fan ','Shao ','Ye ','Hui ','','Tang ','Jin ','Re ','','Xi ', + 'Fu ','Jiong ','Che ','Pu ','Jing ','Zhuo ','Ting ','Wan ','Hai ','Phanh ','Lang ','Shan ','Hu ','Feng ','Chi ','Rong ', + ], + 'x71':[ + 'Hu ','','Shu ','He ','Xun ','Ku ','Jue ','Xiao ','Xi ','Yan ','Han ','Zhuang ','Jun ','Di ','Xie ','Ji ', + 'Wu ','','Lua ','Han ','Yan ','Huan ','Men ','Ju ','Chou ','Vui ','Fen ','Lin ','Kun ','Hun ','Hung ','Xi ', + 'Sot ','Wu ','Hong ','Ju ','Fu ','Wo ','Jiao ','Cong ','Feng ','Ping ','Qiong ','Ruo ','Xi ','Qiong ','Xin ','Zhuo ', + 'Yan ','Yan ','Yi ','Jue ','Yu ','Gang ','Ran ','Pi ','Gu ','','Sheng ','Chang ','Shao ','','Nam ','Geng ', + 'Wat ','Chen ','He ','Kui ','Zhong ','Duan ','Xia ','Hui ','Feng ','Lian ','Xuan ','Xing ','Huang ','Jiao ','Jian ','Bi ', + 'Ying ','Zhu ','Wei ','Tuan ','Tian ','Xi ','Nuan ','Nuan ','Chan ','Yan ','Jiong ','Jiong ','Yu ','Mei ','Sha ','Wei ', + 'Ye ','Xin ','Qiong ','Rou ','Mei ','Huan ','Xu ','Zhao ','Oi ','Fan ','Qiu ','Sui ','Yang ','Lie ','Zhu ','', + 'Gao ','Gua ','Bao ','Hu ','Yun ','Xia ','','','Bian ','Gou ','Tui ','Tang ','Chao ','Shan ','En ','Bo ', + 'Huang ','Xie ','Xi ','Wu ','Tat ','Yun ','He ','He ','Xi ','Yun ','Hung ','Nai ','Shan ','','Yao ','Xun ', + 'Mi ','Lian ','Ying ','Wu ','Rong ','Kou ','En ','Qiang ','Liu ','Hay ','Bi ','Biao ','Zong ','Lu ','Jian ','Thuc ', + 'Yi ','Lou ','Feng ','Thui ','Yi ','Tong ','Jue ','Zong ','Yun ','Hu ','Yi ','Zhi ','Ao ','Wei ','Liao ','Han ', + 'Ou ','Re ','Jiong ','Man ','','Shang ','Cuan ','Tung ','Jian ','Xi ','Xi ','Xi ','Yi ','Xiao ','Xe ','Huang ', + 'Chan ','Ye ','Qian ','Nhen ','Yan ','Xian ','Qiao ','Zun ','Deng ','Dun ','Shen ','Jiao ','Fen ','Si ','Liao ','Yu ', + 'Lan ','Tong ','Shao ','Fen ','Fan ','Yan ','Xun ','Lan ','Mei ','Tang ','Yi ','Jing ','Men ','','','Ying ', + 'Yu ','Yi ','Xue ','Lan ','Tai ','Zao ','Can ','Sui ','Xi ','Que ','Cong ','Lian ','Hui ','Zhu ','Xie ','Ling ', + 'Wei ','Yi ','Xie ','Zhao ','Hui ','Tatsu ','Nung ','Lan ','Ru ','Xian ','Kao ','Hun ','Jin ','Chou ','Dao ','Yao ', + ], + 'x72':[ + 'He ','Lan ','Biao ','Rong ','Li ','Mo ','Bao ','Ruo ','Lu ','Dop ','Ao ','Xun ','Kuang ','Shuo ','','Li ', + 'Chua ','Jue ','Liao ','Yan ','Xi ','Xie ','Long ','Ye ','','Rang ','Yue ','Lan ','Cong ','Jue ','Tong ','Guan ', + '','Che ','Mi ','Tang ','Lan ','Zhu ','Laam ','Ling ','Cuan ','Yu ','Zhua ','Lam ','Pa ','Tranh ','Pao ','Cheng ', + 'Vuon ','Ai ','Vay ','','Jue ','Tuoc ','Fu ','Ye ','Ba ','Die ','Ye ','Yao ','Zu ','Sung ','Er ','Qiang ', + 'Chuang ','Ge ','Zang ','Die ','Qiang ','Yong ','Teo ','Pian ','Ban ','Pan ','Shao ','Jian ','Bai ','Du ','Chuang ','Tou ', + 'Zha ','Bian ','Die ','Bang ','Bo ','Chuang ','You ','','Du ','Nha ','Cheng ','Nguu ','Ushihen ','Pin ','Jiu ','Mou ', + 'Tuo ','Mu ','Lao ','Ren ','Mang ','Fang ','Mao ','Mu ','Gang ','Wu ','Yan ','Ge ','Bei ','Si ','Jian ','Gu ', + 'You ','Ge ','Sinh ','Mu ','Di ','Qian ','Quan ','Quan ','Zi ','Te ','Xi ','Mang ','Keng ','Qian ','Wu ','Gu ', + 'Xi ','Li ','Li ','Pou ','Ji ','Gang ','Zhi ','Ben ','Quan ','Run ','Du ','Ju ','Jia ','Jian ','Feng ','Pian ', + 'Ke ','Ju ','Kao ','Chu ','Xi ','Bei ','Luo ','Jie ','Ma ','San ','Wei ','Li ','Dun ','Tong ','','Jiang ', + 'Nghe ','Li ','Du ','Lie ','Pi ','Piao ','Bao ','Xi ','Chou ','Wei ','Kui ','Chou ','Quan ','Hyun ','Ba ','Fan ', + 'Qiu ','Ji ','Cai ','Chuo ','An ','Ge ','Zhuang ','Guang ','Ma ','You ','Kang ','Bo ','Hou ','Ya ','Yin ','Huan ', + 'Zhuang ','Yun ','Kuang ','Niu ','Di ','Qing ','Zhong ','Mu ','Bei ','Pi ','Ju ','Ni ','Sheng ','Pao ','Xia ','Tuo ', + 'Hu ','Ling ','Fei ','Pi ','Nai ','Ao ','You ','Gou ','Yue ','Ju ','Dan ','Po ','Gu ','Xian ','Ning ','Huan ', + 'Hen ','Jiao ','He ','Zhao ','Ji ','Xun ','Shan ','Ta ','Rong ','Shou ','Tong ','Lao ','Du ','Xia ','Shi ','Hua ', + 'Zheng ','Yu ','Sun ','Yu ','Bi ','Mang ','Xi ','Juan ','Li ','Xia ','Yin ','Suan ','Lang ','Bei ','Zhi ','Yan ', + ], + 'x73':[ + 'Sha ','Li ','Han ','Xian ','Jing ','Pai ','Fei ','Yao ','Ba ','Qi ','Ni ','Biao ','Yin ','Lai ','Xi ','Jian ', + 'Qiang ','Kun ','Yan ','Guo ','Zong ','Mi ','Chang ','Yi ','Zhi ','Zheng ','Ya ','Meng ','Cai ','Cu ','She ','Ryou ', + 'Cen ','Luo ','Hu ','Zong ','Ji ','Wei ','Feng ','Wo ','Yuan ','Xing ','Zhu ','Mao ','Wei ','Yuan ','Xian ','Tuan ', + 'Ya ','Nao ','Xie ','Jia ','Hou ','Bian ','You ','You ','Mei ','Zha ','Yao ','Sun ','Bo ','Ming ','Hua ','Yuan ', + 'Sou ','Ma ','Yuan ','Dai ','Yu ','Tep ','Hao ','','Yi ','Zhen ','Chuang ','Hao ','Man ','Jing ','Jiang ','Mu ', + 'Zhang ','Chan ','Ngao ','Ngao ','Hao ','Cui ','Fen ','Jue ','Bi ','Bi ','Huang ','Pu ','Lin ','Yu ','Tong ','Yao ', + 'Liao ','Shuo ','Xiao ','Juu ','Ton ','Xi ','Ge ','Juan ','Du ','Hui ','Kuai ','Xian ','Xie ','Ta ','Xian ','Xun ', + 'Nanh ','Pin ','Huo ','Nou ','Meng ','Lop ','Nao ','Guang ','Thu ','Lu ','Ta ','Xian ','Mi ','Rang ','Huan ','Nao ', + 'Luo ','Xian ','Qi ','Jue ','Xuan ','Miao ','Zi ','Lu ','Lu ','Ngoc ','Su ','Vuong ','Qiu ','Ga ','Ding ','Le ', + 'Ba ','Ji ','Hong ','Di ','Chuan ','Gan ','Jiu ','Yu ','Ji ','Yu ','Yang ','Ma ','Gong ','Wu ','Fu ','Min ', + 'Jie ','Nga ','Bin ','Bian ','Bang ','Yue ','Jue ','Yun ','Jue ','Wan ','Jian ','Mei ','Dan ','Pi ','Wei ','Huan ', + 'Xian ','Qiang ','Ling ','Ngan ','Yi ','An ','Ping ','Dian ','Fu ','Xuan ','Xi ','Bo ','Ci ','Gou ','Jia ','Shao ', + 'Po ','Ci ','Ke ','Ran ','Sheng ','Shen ','Yi ','Zu ','Jia ','Min ','San ','Liu ','Bi ','Tran ','Zhen ','Jue ', + 'Fa ','Long ','Jin ','Jiao ','Jian ','Li ','Guang ','Xian ','Zhou ','Gong ','Yan ','Xiu ','Yang ','Xu ','Luo ','Su ', + 'Chau ','Qin ','Ken ','Xun ','Bao ','Er ','Xiang ','Yao ','Xia ','Heng ','Gui ','Chong ','Xu ','Ban ','Pei ','', + 'Dang ','Ei ','Hun ','Wen ','E ','Cheng ','Di ','Wu ','Wu ','Cheng ','Jun ','Mei ','Bei ','Ting ','Xian ','Chuo ', + ], + 'x74':[ + 'Han ','Xuan ','Yan ','Qiu ','Quan ','Lang ','Li ','Xiu ','Fu ','Luu ','Ye ','Xi ','Ling ','Li ','Jin ','Lian ', + 'Suo ','Sa ','','Wan ','Dian ','Pin ','Zhan ','Cui ','Min ','Yu ','Ju ','Chen ','Trai ','Wen ','Sheng ','Wei ', + 'Dian ','Chu ','Zhuo ','Pei ','Cheng ','Hu ','Qi ','E ','Kun ','Chang ','Qi ','Beng ','Wan ','Lu ','Cong ','Guan ', + 'Yan ','Diao ','Bei ','Lin ','Qin ','Pi ','Ba ','Que ','Zhuo ','Qin ','Fa ','','Qiong ','Du ','Jie ','Hun ', + 'Yu ','Mao ','Mei ','Chun ','Xuan ','Ti ','Xing ','Dai ','Rou ','Min ','Zhen ','Wei ','Ruan ','Huan ','Jie ','Chuan ', + 'Jian ','Zhuan ','Yang ','Lian ','Quan ','Xia ','Duan ','Yuan ','Ye ','Nao ','Hu ','Ying ','Yu ','Huang ','Rui ','Sat ', + 'Liu ','','Rong ','Suo ','Rom ','Wen ','Wu ','Jin ','Jin ','Ying ','Ma ','Tao ','Liu ','Tang ','Li ','Lang ', + 'Gui ','Tian ','Qiang ','Cuo ','Jue ','Zhao ','Yao ','Ai ','Bin ','Tu ','Chang ','Kun ','Zhuan ','Cong ','Jin ','Yi ', + 'Cui ','Cong ','Qi ','Li ','Ying ','Suo ','Qiu ','Xuan ','Ao ','Lian ','Men ','Zhang ','Yin ','','Ying ','Zhi ', + 'Lu ','Wu ','Deng ','xiu ','Zeng ','Xun ','Qu ','Dang ','Lin ','Liao ','Qiong ','Su ','Huang ','Gui ','Pu ','Jing ', + 'Fan ','Jin ','Liu ','Ji ','','Jing ','Ai ','Bi ','Can ','Qu ','Zao ','Dang ','Jiao ','Gun ','Tan ','Hui ', + 'Huan ','Se ','Sui ','Tian ','','Yu ','Jin ','Lu ','Bin ','Shou ','Wen ','Zui ','Lan ','Xi ','Ji ','Xuan ', + 'Ruan ','Huo ','Gai ','Lei ','Du ','Li ','Zhi ','Rou ','Li ','Zan ','Qiong ','Zhe ','Gui ','Sui ','La ','Long ', + 'Lu ','Li ','Zan ','Lan ','Ying ','Mi ','Xiang ','Xi ','Guan ','Dao ','Zan ','Huan ','Qua ','Bo ','Die ','Bao ', + 'Hu ','Zhi ','Piao ','Ban ','Rang ','Li ','Wa ','Dekaguramu ','Jiang ','Cin ','Fan ','Pen ','Fang ','Dan ','Weng ','Ou ', + 'Deshiguramu ','Miriguramu ','Ton ','Hu ','Ling ','Yi ','Ping ','Ci ','Hekutogura ','Juan ','Chang ','Chi ','Sarake ','Dang ','Meng ','Pou ', + ], + 'x75':[ + 'Zhui ','Ping ','Bian ','Zhou ','Zhen ','Senchigura ','Ci ','Ying ','Qi ','Xian ','Lou ','Di ','Ou ','Manh ','Zhuan ','Peng ', + 'Lin ','Zeng ','Wu ','Pi ','Dan ','Weng ','Ying ','Yan ','Gan ','Dai ','Shen ','Tian ','Tian ','Han ','Chang ','Sinh ', + 'Qing ','Shen ','Chan ','Chan ','Rui ','Sheng ','Su ','Sen ','Dung ','Shuai ','Lu ','Fu ','Yong ','Beng ','Feng ','Ning ', + 'Tian ','Do ','Jia ','Shen ','Zha ','Dian ','Fu ','Nam ','Dian ','Ping ','Ting ','Hua ','Ting ','Quan ','Zi ','Meng ', + 'Bi ','Qi ','Liu ','Xun ','Liu ','Chang ','Mu ','Yun ','Fan ','Fu ','Geng ','Tian ','Gioi ','Jie ','Quan ','Wei ', + 'Fu ','Tian ','Mu ','Tap ','Pan ','Jiang ','Wa ','Da ','Nan ','Luu ','Ben ','Zhen ','Chu ','Mu ','Mu ','Ce ', + 'Hata ','Gai ','Bi ','Da ','Zhi ','Lue ','Qi ','Lue ','Pan ','Kesa ','Fan ','Hua ','Yu ','Yu ','Mu ','Jun ', + 'Yi ','Luu ','Yu ','Die ','Chou ','Hua ','Dang ','Chuo ','Ji ','Wan ','Cung ','Sheng ','Chang ','Tuan ','Lei ','Ji ', + 'Cha ','Liu ','Jou ','Tuan ','Lin ','Jiang ','Jiang ','Chou ','Bo ','Die ','Die ','Sat ','Nie ','Dan ','Shu ','So ', + 'Zhi ','Yi ','Chuang ','Nai ','Ding ','Bi ','Jie ','Liao ','Gang ','Ge ','Jiu ','Zhou ','Xia ','Shan ','Xu ','Nue ', + 'Li ','Yang ','Chen ','You ','Ba ','Jie ','Jue ','Zhi ','Xia ','Cui ','Bi ','Yi ','Li ','Zong ','Chuang ','Feng ', + 'Zhu ','Pao ','Pi ','Gan ','Ke ','Ci ','Xie ','Qi ','Dan ','Zhen ','Fa ','Zhi ','Teng ','Thu ','Ji ','Fei ', + 'Khu ','Dian ','Jia ','Xian ','Zha ','Bing ','Ni ','Zheng ','Yong ','Jing ','Quan ','Chong ','Tong ','Yi ','Kai ','Wei ', + 'Hui ','Duo ','Yang ','Chi ','Zhi ','Not ','Ya ','Mei ','Dou ','Jing ','Xiao ','Thong ','Tu ','Mang ','Pi ','Xiao ', + 'Suan ','Pu ','Li ','Zhi ','Cuo ','Duo ','Wu ','Sha ','Lao ','Shou ','Huan ','Xian ','Yi ','Peng ','Zhang ','Guan ', + 'Tan ','Fei ','Ma ','Lin ','Chi ','Ji ','Dian ','An ','Chi ','Bi ','Bi ','Min ','Gu ','Dui ','E ','Wei ', + ], + 'x76':[ + 'Yu ','Cui ','Ya ','Zhu ','Cu ','Dan ','Shen ','Zhong ','Ji ','Yu ','Hou ','Phong ','La ','Yang ','Shen ','Tu ', + 'Yu ','Gua ','Wen ','Huan ','Ku ','Jia ','Yin ','Yi ','Lu ','Sao ','Jue ','Chi ','Xi ','Guan ','Yi ','Wen ', + 'Ji ','Chuang ','Ban ','Lei ','Liu ','Chai ','Xau ','Nue ','Dian ','Da ','Pie ','Tan ','Zhang ','Biao ','Shen ','Cu ', + 'Luo ','Yi ','Zong ','Chou ','Chuong ','Zhai ','Sou ','Suo ','Que ','Diao ','Lou ','Lu ','Mo ','Jin ','Yin ','Ying ', + 'Huang ','Fu ','Liao ','Long ','Qiao ','Liu ','Lao ','Xian ','Fei ','Dan ','Yin ','He ','Ai ','Ban ','Xian ','Guan ', + 'Guai ','Nong ','Yu ','Wei ','Yi ','Yong ','Pi ','Lei ','Li ','Shu ','Dan ','Lin ','Dian ','Lin ','Lai ','Bie ', + 'Ji ','Si ','Yang ','Xian ','Jie ','Zheng ','Mak6','Li ','Huo ','Lai ','Zik ','Dian ','Xuan ','Ying ','Yin ','Qu ', + 'Ung ','Tan ','Dian ','Luo ','Luan ','Luan ','Bo ','','Gui ','Po ','Fa ','Deng ','Fa ','Bai ','Bai ','Qie ', + 'Bi ','Zao ','Zao ','Mao ','De ','Pa ','Giai ','Hoang ','Gui ','Ci ','Ling ','Gao ','Mo ','Ji ','Jiao ','Peng ', + 'Cau ','Ai ','E ','Hao ','Han ','Bi ','Wan ','Chou ','Qian ','Xi ','Ai ','Jiong ','Hao ','Huang ','Hao ','Ze ', + 'Cui ','Hao ','Xiao ','Ye ','Po ','Hao ','Jiao ','Ai ','Xing ','Huang ','Li ','Piao ','He ','Jiao ','Pi ','Gan ', + 'Pao ','Zhou ','Jun ','Qiu ','Cun ','Que ','Zha ','Gu ','Jun ','Jun ','Zhou ','Zha ','Gu ','Zhan ','Du ','Min ', + 'Qi ','Ying ','Yu ','Bei ','Zhao ','Zhong ','Pho ','He ','Ying ','He ','Yi ','Bo ','Wan ','He ','Ang ','Zhan ', + 'Yan ','Jian ','Hop ','Yu ','Kui ','Fan ','Gai ','Dao ','Pan ','Fu ','Qiu ','Sheng ','Dao ','Lu ','Chen ','Meng ', + 'Li ','Jin ','Xu ','Jian ','Ban ','Guan ','An ','Lu ','Shu ','Zhou ','Dang ','An ','Gu ','Li ','Muc ','Ding ', + 'Gan ','Xu ','Mang ','Mang ','Zhi ','Qi ','Ruan ','Tian ','Tuong ','Dun ','Xin ','Xi ','Pan ','Feng ','Dun ','Min ', + ], + 'x77':[ + 'Ming ','Sheng ','Shi ','Yun ','Mian ','Pan ','Fang ','Miao ','Dan ','Mi ','Mao ','Kan ','Xian ','Ou ','Shi ','Yang ', + 'Zheng ','Yao ','Shen ','Mu ','Da ','Zhen ','Kuang ','Ju ','Shen ','Chi ','Sheng ','Muoi ','Mat ','Zhu ','Zhen ','Chan ', + 'Mian ','Di ','Yuan ','Die ','Yi ','Zi ','Zi ','Chao ','Zha ','Xuan ','Bing ','Mi ','Long ','Sui ','Dong ','Mi ', + 'Die ','Yi ','Er ','Ming ','Xuan ','Chi ','Kuang ','Juan ','Mou ','Zhen ','Tiao ','Yang ','Cua ','Mo ','Chung ','Mai ', + 'Zhao ','Zheng ','Mei ','Jun ','Shao ','Han ','Huan ','Di ','Cheng ','Cuo ','Juan ','E ','Wan ','Xian ','Xi ','Kun ', + 'Lai ','Jian ','Shan ','Tian ','Hun ','Wan ','Ling ','Shi ','Qiong ','Lie ','Yai ','Jing ','Zheng ','Li ','Lai ','Sui ', + 'Juan ','Shui ','Sui ','Du ','Bi ','Bi ','Muc ','Hun ','Ni ','Lu ','Yi ','Jie ','Cai ','Zhou ','Yu ','Hun ', + 'Ma ','Xia ','Xing ','Xi ','Gun ','','Chun ','Jian ','Mei ','Du ','Hou ','Xuan ','Ti ','Kui ','Gao ','Rui ', + 'Mao ','Xu ','Fa ','Wen ','Miao ','Chou ','Kui ','Mi ','Weng ','Kou ','Dang ','Tran ','Ke ','Sou ','Xia ','Qiong ', + 'Mao ','Ming ','Man ','Shui ','Ze ','Zhang ','Yi ','Diao ','Ou ','Mo ','Shun ','Cong ','Lou ','Chi ','Man ','Piao ', + 'Cheng ','Ji ','Meng ','','Run ','Pie ','Xi ','Qiao ','Pu ','Zhu ','Deng ','Shen ','Shun ','Liao ','Che ','Xian ', + 'Kan ','Ye ','Xu ','Chang ','Mou ','Lin ','Kui ','Xian ','Ye ','Ai ','Hui ','Zhan ','Lim ','Gu ','Zhao ','Ju ', + 'Wei ','Chou ','Sao ','Ning ','Xun ','Yao ','Huo ','Meng ','Mian ','Bin ','Mian ','Li ','Kuang ','Jue ','Xuan ','Mian ', + 'Huo ','Lu ','Meng ','Long ','Guan ','Man ','Xi ','Chu ','Tang ','Kan ','Zhu ','Mau ','Cang ','Lin ','Yu ','Shuo ', + 'Ce ','Jue ','Ngao ','Yi ','Shen ','Tri ','Hou ','Shen ','Ying ','Ju ','Zhou ','Jiao ','Cuo ','Duan ','Ai ','Jiao ', + 'Zeng ','Huo ','Bai ','Shi ','Ding ','Qi ','Ji ','Zi ','Gan ','Wu ','Tuo ','Ku ','Qiang ','Xi ','Fan ','Kuang ', + ], + 'x78':[ + 'Dang ','Ma ','Sha ','Dan ','Jue ','Li ','Fu ','Min ','Nuo ','Huo ','Kang ','Zhi ','Qi ','Kan ','Jie ','Fen ', + 'E ','Ya ','Pi ','Zhe ','Khan ','Sui ','Zhuan ','Che ','Dun ','Pan ','Yan ','','Feng ','Fa ','Mo ','Zha ', + 'Qu ','Yu ','Luo ','Tuo ','Tuo ','Di ','Zhai ','Kham ','Ai ','Fei ','Mu ','Zhu ','Li ','Bian ','Nu ','Ping ', + 'Peng ','Ling ','Bau ','Le ','Po ','Bo ','Po ','Shen ','Za ','Nuo ','Li ','Long ','Tong ','','Li ','Kou ', + 'Chu ','Keng ','Quan ','Zhu ','Kuang ','Gui ','E ','Nao ','Jia ','Lu ','Wei ','Ai ','Ngac ','Ken ','Xing ','Yan ', + 'Tong ','Peng ','Xi ','','Hong ','Shuo ','Xia ','Qiao ','','Wei ','Qiao ','','Keng ','Xiao ','Que ','Chan ', + 'Lang ','Hong ','Yu ','Xiao ','Xia ','Mang ','Long ','Yong ','Che ','Che ','E ','Luu ','Khu ','Mang ','Que ','Kho ', + 'Sha ','Kun ','Yu ','','Kaki ','Lu ','Chen ','Jian ','Nue ','Song ','Zhuo ','Keng ','Peng ','Yan ','Zhui ','Kong ', + 'Ceng ','Qi ','Zong ','Qing ','Lin ','Jun ','Bo ','Ding ','Min ','Diao ','Jian ','He ','Lu ','Ai ','Sui ','Que ', + 'Ling ','Bei ','Yin ','Dui ','Wu ','Qi ','Lun ','Wan ','Dian ','Gang ','Bei ','Qi ','Chen ','Ruan ','Yan ','Die ', + 'Ding ','Du ','Tuo ','Jie ','Ying ','Bian ','Ke ','Bi ','Wei ','Shuo ','Zhen ','Duan ','Xia ','Dang ','Ti ','Nao ', + 'Peng ','Jian ','Di ','Tan ','Cha ','Seki ','Qi ','','Feng ','Xuan ','Que ','Que ','Ma ','Gong ','Nian ','Su ', + 'E ','Ci ','Liu ','Si ','Tang ','Bang ','Hua ','Pi ','Wei ','Sang ','Loi ','Cuo ','Zhen ','Xia ','Qi ','Lian ', + 'Pan ','Wei ','Yun ','Dui ','Zhe ','Ke ','La ','','Qing ','Gun ','Zhuan ','Chan ','Qi ','Ao ','Peng ','Lu ', + 'Lu ','Kan ','Qiang ','Chen ','Yin ','Lei ','Biao ','Qi ','Mai ','Qi ','Cui ','Zong ','Qing ','Chuo ','','Ji ', + 'Shan ','Lao ','Qu ','Zeng ','Deng ','Jian ','Xi ','Co ','Ding ','Dian ','Hoang ','Pan ','Za ','Qiao ','Di ','Li ', + ], + 'x79':[ + 'Kan ','Jiao ','','Zhang ','Qiao ','Dun ','Xian ','Yu ','Zhui ','He ','Huo ','Zhai ','Lei ','Ke ','Chu ','Ji ', + 'Que ','Dang ','Yi ','Jiang ','Pi ','Pi ','Yu ','Pin ','Qi ','Ai ','Kai ','Jian ','Yu ','Ruan ','Meng ','Pao ', + 'Ci ','Bo ','','Mie ','Ca ','Xian ','Kuang ','Lei ','Lei ','Zhi ','Li ','Li ','Troi ','Que ','Pao ','Ying ', + 'Li ','Long ','Long ','Mo ','Bo ','Shuang ','Guan ','Lan ','Zan ','Yan ','Shi ','Shi ','Li ','Reng ','She ','Yue ', + 'Si ','Qi ','Ta ','Ma ','Xie ','Yao ','Xian ','Qi ','Qi ','Zhi ','Beng ','Dui ','Zhong ','','Yi ','Shi ', + 'You ','Zhi ','Tiao ','Fu ','Fu ','Mi ','Zu ','Zhi ','Suan ','Mei ','To ','Qu ','Hu ','Chuc ','Shen ','Sui ', + 'Ci ','Chai ','Mi ','Lu ','Yu ','Xiang ','Wu ','Tiao ','Piao ','Zhu ','Gui ','Xia ','Zhi ','Ji ','Gao ','Zhen ', + 'Gao ','Shui ','Jin ','Chen ','Gai ','Kun ','Di ','Dao ','Huo ','Tao ','Qi ','Gu ','Guan ','Zui ','Ling ','Loc ', + 'Bing ','Cam ','Dao ','Zhi ','Lu ','Shan ','Bei ','Zhe ','Hui ','You ','Xi ','Yin ','Zi ','Huo ','Zhen ','Phuc ', + 'Yuan ','Wu ','Xian ','Yang ','Ti ','Yi ','Mei ','Si ','Di ','','Zhuo ','Zhen ','Yong ','Ji ','Gao ','Tang ', + 'Si ','Ma ','Ta ','','Xuan ','Qi ','Yu ','Xi ','Ji ','Si ','Chan ','Tan ','Kuai ','Sui ','Li ','Nong ', + 'Ni ','Dao ','Li ','Rang ','Yue ','Ti ','Zan ','Lei ','Rou ','Yu ','Yu ','Le ','Xie ','Qin ','He ','Tu ', + 'Tu ','Tu ','Ren ','Tu ','Zi ','Cha ','Gan ','Yi ','Xian ','Bing ','Nian ','Thu ','Qiu ','Zhong ','Fen ','Hao ', + 'Yun ','Khoa ','Miao ','Zhi ','Geng ','Bi ','Zhi ','Yu ','Mi ','Ku ','Ban ','Pi ','Ni ','Li ','You ','Zu ', + 'Pi ','Ba ','Ling ','Mo ','Cheng ','Nian ','Qin ','Yang ','Zuo ','Zhi ','Zhi ','Shu ','Ju ','Zi ','Huo ','Ji ', + 'Xung ','Tong ','Zhi ','Huo ','He ','Yin ','Zi ','Gie ','Jie ','Ren ','Du ','Yi ','Zhu ','Hui ','Nong ','Fu ', + ], + 'x7a':[ + 'Hi ','Kao ','Lang ','Fu ','Ze ','Shui ','Lu ','Kun ','Gan ','Geng ','Ti ','Cheng ','Tu ','Shao ','Shui ','Ya ', + 'Lun ','Lu ','Gu ','Zuo ','Ren ','Zhun ','Bang ','Bai ','Ji ','Zhi ','Zhi ','Kun ','Leng ','Peng ','Ke ','Bing ', + 'Chou ','Zu ','Yu ','Su ','Lue ','','Yi ','Xi ','Bian ','Ji ','Fu ','Bi ','Nuo ','Jie ','Zhong ','Zong ', + 'Xu ','Xung ','Dao ','Wen ','Lian ','Zi ','Yu ','Ji ','Xu ','Zhen ','Zhi ','Dao ','Jia ','Ji ','Gao ','Gao ', + 'Gu ','Rong ','Sui ','You ','Ji ','Kang ','Mu ','Shan ','Men ','Zhi ','Cay ','Lu ','Su ','Ji ','Ying ','Wen ', + 'Qiu ','Se ','','Yi ','Huang ','Qie ','Ji ','Sui ','Xiao ','Pu ','Jiao ','Zhuo ','Tong ','Sai ','Lu ','Sui ', + 'Nong ','Se ','Hui ','Rang ','Nuo ','Yu ','','Ji ','Tui ','Wen ','Cheng ','Huo ','Gong ','Hot ','Biao ','', + 'Rang ','Zhuo ','Li ','Zan ','Xue ','Wa ','Jiu ','Qiong ','Xi ','Khum ','Kong ','Yu ','Sen ','Jing ','Yao ','Chuan ', + 'Zhun ','Tu ','Lao ','Qie ','Zhai ','Yao ','Bian ','Bao ','Yao ','Bing ','Wa ','Zhu ','Jiao ','Qiao ','Diao ','Wu ', + 'Gui ','Yao ','Zhi ','Chuang ','Yao ','Tiao ','Jiao ','Song ','Jiong ','Xiao ','Cheng ','Kou ','Cuan ','Wo ','Dan ','Ku ', + 'Ke ','Zhui ','Xu ','Su ','','Kui ','Dou ','','Yin ','Wo ','Wa ','Ya ','Yu ','Ju ','Cung ','Yao ', + 'Yao ','Tiao ','Chao ','Yu ','Tian ','Diao ','Ju ','Liao ','Xi ','Wu ','Kui ','Chuang ','Zhao ','Fun ','Kuan ','Long ', + 'Cheng ','Cui ','Piao ','Zao ','Cuan ','Qiao ','Qiong ','Dou ','Zao ','Long ','Qie ','Li ','Chu ','Dekaritto ','Fou ','Kirorittoru ', + 'Chu ','Hong ','Qi ','Miririttoru ','','Deshiritto ','Shu ','Miao ','Ju ','Zhan ','Zhu ','Ling ','Long ','Bing ','Jing ','Jing ', + 'Chuong ','Hekutoritto ','Si ','Jun ','Hong ','Tong ','Song ','Jing ','Diao ','Yi ','Shu ','Jing ','Qu ','Jie ','Ping ','Duan ', + 'Shao ','Zhuan ','Ceng ','Deng ','Cui ','Huai ','Jing ','Kan ','Jing ','Truc ','Zhu ','Le ','Peng ','Yu ','Chi ','Gan ', + ], + 'x7b':[ + 'Mang ','Zhu ','Utsubo ','Du ','Ji ','Xiao ','Ba ','Suan ','Ji ','Zhen ','Zhao ','Sun ','Ya ','Zhui ','Yuan ','Hu ', + 'Gang ','Xiao ','Cen ','Pi ','Bi ','Jian ','Yi ','Dong ','Shan ','Dam ','Xia ','Di ','Zhu ','Na ','Chi ','Gu ', + 'Li ','Qie ','Min ','Bao ','Tiao ','Si ','Bua ','Ce ','Ben ','Pei ','Da ','Zi ','Di ','Ling ','Ze ','Nu ', + 'Fu ','Cau ','Fan ','Jia ','Ge ','Fan ','Shi ','Mao ','Po ','Sasa ','Jian ','Qiong ','Long ','Souke ','Bian ','Luo ', + 'Gui ','Qu ','Chi ','Yin ','Yao ','Xian ','But ','Qiong ','Gua ','Deng ','Jiao ','Gan ','Quan ','Sun ','Ru ','Fa ', + 'Kuang ','Truc ','Tong ','Ji ','Da ','Xing ','Ce ','Zhong ','Kou ','Lai ','Bi ','Shai ','Dang ','Zheng ','Ce ','Fu ', + 'Yun ','Tu ','Pa ','Li ','Lang ','Ju ','Guan ','Jian ','Han ','Thung ','Xia ','Zhi ','Cheng ','Toan ','Shi ','Zhu ', + 'Zuo ','Xiao ','Shao ','Ting ','Ce ','Yan ','Gao ','Kuai ','Gan ','Chou ','Kyou ','Gang ','Yun ','O ','Qian ','Xiao ', + 'Jian ','Pu ','Lai ','Zou ','Bi ','Bi ','Bi ','Ge ','Chi ','Guai ','Yu ','Jian ','Zhao ','Gu ','Chi ','Tranh ', + 'Jing ','Sha ','Zhou ','Lu ','Bo ','Kia ','Lin ','Suan ','Jun ','Fu ','Zha ','Gu ','Kong ','Qian ','Quan ','Jun ', + 'Chui ','Guan ','Yuan ','Ce ','Nhot ','Bo ','Ze ','Qie ','Tuo ','Luo ','Dan ','Xiao ','Ruo ','Jian ','','Bian ', + 'Sun ','Ruong ','Xian ','Ping ','Bu ','Sheng ','Hu ','Shi ','Zhu ','Yue ','Chun ','Lu ','Wu ','Dong ','Shuo ','Ji ', + 'Jie ','Huang ','Xing ','Mei ','Fan ','Chui ','Zhuan ','Pian ','Feng ','Troc ','Hong ','Qie ','Hou ','Qiu ','Miao ','Qian ', + '','Kui ','Sik ','Lou ','Yun ','He ','Tang ','Yue ','Chou ','Gau ','Fei ','Ruo ','Zheng ','Gou ','Nie ','Qian ', + 'Xiao ','Cuan ','Gong ','Pang ','Du ','Li ','Bi ','Zhuo ','Chu ','Ray ','Chi ','Zhu ','Qiang ','Long ','Lan ','Jian ', + 'Bu ','Li ','Hui ','Bi ','Di ','Cong ','Yan ','Bong ','Sen ','Zhuan ','Pai ','Piao ','Dou ','Yu ','Mie ','Zhuan ', + ], + 'x7c':[ + 'Ze ','Xi ','Guo ','Yi ','Hu ','Chan ','Kou ','Cu ','Ping ','Chou ','Ji ','Gui ','Su ','Lou ','Zha ','Lu ', + 'Nian ','Suo ','Cuan ','Sen ','Suo ','Le ','Duan ','Yana ','Xiao ','Bo ','Mi ','Si ','Thang ','Liao ','Dan ','Dian ', + 'Fu ','Jian ','Min ','Kui ','Dai ','Jiao ','Deng ','Huang ','Sun ','Lau ','Tram ','Xiao ','Ro ','Shi ','Zan ','', + 'Pai ','Hata ','Pai ','Gan ','Ju ','Du ','Lu ','Yan ','Bo ','Dang ','Sai ','Ke ','Long ','Qian ','Lian ','Bu ', + 'Zhou ','Lai ','','Lan ','Kui ','Yu ','Yue ','Hao ','Zhen ','Tai ','Ti ','Mi ','Chou ','Ji ','','Hata ', + 'Teng ','Zhuan ','Zhou ','Fan ','Sou ','Zhou ','Tam ','Zhuo ','Teng ','Lu ','Gat ','Jian ','Tuo ','Ying ','Yu ','Lai ', + 'Long ','Shinshi ','Lian ','Tran ','Qian ','Yue ','Zhong ','Qu ','Lian ','Bian ','Duan ','Zuan ','Li ','Si ','Luo ','Ying ', + 'Yue ','Zhuo ','Yu ','Mi ','Di ','Fan ','Shen ','Zhe ','Shen ','Nu ','Xie ','Lei ','Xian ','Zi ','Ni ','Cun ', + '','Qian ','Kume ','Bi ','Ban ','Wu ','Sha ','Kang ','Rou ','Phan ','Bi ','Cui ','','Li ','Chi ','Ta ', + 'Ro ','Ba ','Li ','Gan ','Ju ','Po ','Mo ','Cu ','Nian ','Zhou ','Li ','Su ','Tiao ','Li ','Xi ','Su ', + 'Hong ','Tong ','Zi ','Ce ','Yue ','Zhou ','Lin ','Zhuang ','Bai ','','Fen ','Ji ','','Sukumo ','Liang ','Xian ', + 'Fu ','Liang ','Can ','Geng ','Li ','Yue ','Lu ','Ju ','Qi ','Cui ','Bai ','Zhang ','Lin ','Zong ','Tinh ','Guo ', + 'Kouji ','San ','San ','Tang ','Bian ','Rou ','Mian ','Hou ','Xu ','Zong ','Hu ','Jian ','Zan ','Ci ','Li ','Xie ', + 'Fu ','Ni ','Bei ','Gu ','Xiu ','Gao ','Tang ','Qiu ','Sukumo ','Cao ','Zhuang ','Tang ','Mi ','Tam ','Phan ','Zao ', + 'Kang ','Jiang ','Mo ','San ','San ','Nuo ','Xi ','Luong ','Jiang ','Kuai ','Bo ','Huan ','','Zong ','Xian ','Nuo ', + 'Tuan ','Nie ','Li ','Zuo ','Di ','Nie ','Tiao ','Lan ','Mi ','Si ','Jiu ','Xi ','Gong ','Zheng ','Jiu ','You ', + ], + 'x7d':[ + 'Ji ','Cha ','Zhou ','Xun ','Yue ','Hong ','Yu ','Hot ','Wan ','Ren ','Wen ','Van ','Qiu ','Na ','Zi ','Tou ', + 'Neo ','Fou ','Jie ','Shu ','Chun ','Pi ','Yin ','Sa ','Hong ','Zhi ','Cap ','Phan ','Yun ','Ren ','Dan ','Jin ', + 'To ','Fang ','Suo ','Cui ','Jiu ','Zha ','Ha ','Jin ','Fu ','Zhi ','Ci ','Zi ','Chou ','Hong ','Za ','Lei ', + 'Toi ','Fu ','Xie ','Thang ','Bei ','Zhu ','Qu ','Ling ','Zhu ','Shao ','Gan ','Yang ','Fu ','Tuo ','Zhen ','Dai ', + 'Chu ','Shi ','Chung ','Xian ','Zu ','Jiong ','Ban ','Ju ','Mo ','Shu ','Zui ','Kou ','Jing ','Ren ','Heng ','Day ', + 'Jie ','Zhu ','Chou ','Gua ','Bai ','Jue ','Quang ','Hu ','Ci ','Geng ','Geng ','Tao ','Xie ','Ku ','Jiao ','Quan ', + 'Gai ','Luo ','Xuan ','Bing ','Xian ','Fu ','Cap ','Tong ','Nhung ','Tiao ','Yin ','Lei ','Xie ','Quan ','Xu ','Gai ', + 'Die ','Thong ','To ','Jiang ','Xiang ','Hui ','Jue ','Zhi ','Ken ','Juan ','Chi ','Mian ','Zhen ','Lu ','Cheng ','Qiu ', + 'Shu ','Bang ','Tong ','Xiao ','Wan ','Qin ','Geng ','Xiu ','Ti ','Tu ','Xie ','Hong ','Xi ','Fu ','Ting ','Noi ', + 'Dui ','Kun ','Fu ','Kinh ','Hu ','Zhi ','Yan ','Jiong ','Feng ','Ji ','Zoku ','Kase ','Zong ','Lin ','Duo ','Li ', + 'Luc ','Liang ','Chou ','Cuon ','Shao ','Qi ','Qi ','Zhun ','Qi ','Wan ','Qian ','Xian ','Shou ','Wei ','Qi ','Tao ', + 'Wan ','Cuong ','Wang ','Beng ','Zhui ','Cai ','Guo ','Cui ','Luan ','Liu ','Qi ','Zhan ','Bei ','Xuoc ','Trang ','Mian ', + 'Qi ','Qie ','Tan ','Zong ','Gun ','Zou ','Yi ','Zi ','Xing ','Liang ','Jin ','Fei ','Rui ','Min ','Yu ','Zong ', + 'Fan ','Lu ','Xu ','Ying ','Zhang ','Kasuri ','Xu ','Xiang ','Dam ','Ke ','Xian ','Ruan ','Mian ','Ji ','Duan ','Zhong ', + 'Di ','Min ','Miao ','Yuan ','Xie ','Bao ','Si ','Qiu ','Bian ','Huan ','Geng ','Cong ','Mian ','Wei ','Fu ','Wei ', + 'Yu ','Gou ','Miao ','Xie ','Lian ','Zong ','Bian ','Yun ','Yin ','Ti ','Gua ','Zhi ','Yun ','Cheng ','Chan ','Dai ', + ], + 'x7e':[ + 'Xia ','Yuan ','Zong ','Xu ','Jou ','Odoshi ','Geng ','Sen ','Quanh ','Jin ','Yi ','Zhui ','Ni ','Bang ','Lam ','Pan ', + 'Zhou ','Jian ','Cuo ','Quan ','Shuang ','Yun ','Xia ','Cui ','Xi ','Rong ','Tao ','Fu ','Yun ','Chen ','Gao ','Nhoc ', + 'Hu ','Zai ','Teng ','Xian ','Su ','Zhen ','Zong ','Tao ','Kou ','Cai ','Bi ','Feng ','Cu ','Li ','Suo ','Yin ', + 'Xi ','Tung ','Lei ','Zhuan ','Qian ','Man ','Zhi ','Lua ','Mac ','Piao ','Lian ','Mi ','Xuan ','Zong ','Ji ','Shan ', + 'Sui ','Fan ','Shuai ','Beng ','Yi ','Sao ','Mou ','Yao ','Qiang ','Hun ','Sen ','Xi ','Zung ','Xiu ','Ran ','Xuan ', + 'Sui ','Qiao ','Zeng ','Zuo ','Zhi ','Shan ','San ','Lin ','Yu ','Fan ','Liao ','Chuo ','Zun ','Jian ','Rao ','Chan ', + 'Rui ','Xiu ','Hui ','Hua ','Zuan ','Xi ','Qiang ','Un ','Da ','Sheng ','Hui ','Xi ','Se ','Ken ','Jiang ','Huan ', + 'Thao ','Cong ','Jie ','Nhau ','Bo ','Chan ','Giay ','Nao ','Sui ','Yi ','Shai ','Xu ','Ji ','Bin ','Qian ','Lan ', + 'Buoc ','Xun ','Zuan ','Qi ','Peng ','Li ','Mo ','Lei ','Xie ','Zuan ','Kuang ','You ','Tuc ','Lei ','Xian ','Chan ', + 'Kou ','Lu ','Chan ','Ying ','Cai ','Xiang ','Xian ','Zui ','Zuan ','La ','Xi ','Dao ','Lan ','Lei ','Lian ','Si ', + 'Jiu ','Yu ','Hong ','Zhou ','Xian ','He ','Yue ','Ji ','Wan ','Kuang ','Ji ','Ren ','Wei ','Yun ','Hong ','Chun ', + 'Pi ','Sha ','Gang ','Na ','Ren ','Zong ','Lun ','Fen ','Zhi ','Wen ','Fang ','Zhu ','Yin ','Niu ','Shu ','Xian ', + 'Gan ','Xie ','Fu ','Lian ','Zu ','Shen ','Xi ','Zhi ','Zhong ','Zhou ','Ban ','Fu ','Zhuo ','Shao ','Yi ','Jing ', + 'Dai ','Bang ','Rong ','Jie ','Ku ','Rao ','Die ','Heng ','Hui ','Gei ','Xuan ','Jiang ','Luo ','Jue ','Jiao ','Tong ', + 'Geng ','Xiao ','Juan ','Xiu ','Xi ','Sui ','Tao ','Ji ','Ti ','Ji ','Xu ','Ling ','Ying ','Xu ','Qi ','Fei ', + 'Chuo ','Zhang ','Gun ','Sheng ','Wei ','Mian ','Shou ','Beng ','Chou ','Tao ','Liu ','Quan ','Zong ','Zhan ','Wan ','Lu ', + ], + 'x7f':[ + 'Zhui ','Zi ','Ke ','Xiang ','Jian ','Mian ','Lan ','Ti ','Miao ','Qi ','Yun ','Hui ','Si ','Duo ','Duan ','Bian ', + 'Xian ','Gou ','Zhui ','Huan ','Di ','Lu ','Bian ','Min ','Yuan ','Jin ','Fu ','Ru ','Zhen ','Feng ','Shuai ','Gao ', + 'Chan ','Li ','Yi ','Jian ','Bin ','Piao ','Man ','Lei ','Ying ','Suo ','Mou ','Sao ','Xie ','Liao ','Shan ','Zeng ', + 'Jiang ','Qian ','Zao ','Huan ','Jiao ','Zuan ','Fou ','Xie ','Cong ','Fou ','Que ','Fou ','Ketsu ','Bo ','Ping ','Hou ', + 'Diu6','Gang ','Ying ','Ying ','Qing ','Xia ','Guan ','Zun ','Tan ','Cang ','Qi ','Weng ','Ying ','Lei ','Tan ','Lu ', + 'Guan ','Wang ','Wang ','Gang ','Wang ','Han ','','Luo ','Fu ','Mi ','Fa ','Gu ','Zhu ','Ju ','Mao ','Gu ', + 'Min ','Gang ','Ba ','Gua ','Ti ','Juan ','Fu ','Lin ','Yan ','Zhao ','Toi ','Gua ','Zhuo ','Yu ','Zhi ','An ', + 'Fa ','Nan ','Shu ','Si ','Pi ','Ma ','Liu ','Ba ','Fa ','Li ','Chao ','Wei ','Bi ','Ji ','Zeng ','Tong ', + 'Liu ','Ji ','Juan ','Mi ','Zhao ','La ','Pi ','Ji ','Ji ','Luan ','Duong ','Mi ','Qiang ','Ta ','Mei ','Yang ', + 'You ','You ','Fen ','Ba ','Gao ','Yang ','Gu ','Qiang ','Zang ','Gao ','Ling ','Yi ','Zhu ','Di ','Xiu ','Qian ', + 'Yi ','Xian ','Rong ','Qun ','Qun ','Qiang ','Huan ','Suo ','Xian ','Yi ','You ','Qiang ','Xian ','Yu ','Canh ','Jie ', + 'Tang ','Yuan ','Xi ','Fan ','Shan ','Fen ','Shan ','Lian ','Lei ','Geng ','Nou ','Qiang ','Chan ','Yu ','Gong ','Yi ', + 'Chong ','Weng ','Fen ','Hong ','Chi ','Chi ','Cui ','Fu ','Xia ','Pen ','Yi ','La ','Yi ','Pi ','Ling ','Liu ', + 'Zhi ','Qu ','Xi ','Xie ','Xiang ','Hap ','Xi ','Qi ','Qiao ','Hui ','Hui ','Xiao ','Se ','Hong ','Jiang ','Di ', + 'Cui ','Fei ','Tao ','Sha ','Chi ','Zhu ','Jian ','Xuan ','Shi ','Pian ','Zong ','Wan ','Hui ','Hou ','He ','He ', + 'Han ','Ao ','Piao ','Yi ','Lian ','Qu ','','Lin ','Pen ','Qiao ','Ao ','Fan ','Yi ','Hui ','Xuan ','Dao ', + ], + 'x80':[ + 'Yao ','Lao ','','Kao ','Mao ','Zhe ','Qi ','Gou ','Gou ','Gou ','Die ','Die ','Er ','Shua ','Ruan ','Er ', + 'Nai ','Zhuan ','Lei ','Ting ','Zi ','Canh ','Chao ','Hao ','Yun ','Ba ','Pi ','Chi ','Si ','Chu ','Roi ','Ju ', + 'He ','Chu ','Lao ','Lun ','Ji ','Tang ','Ou ','Lou ','Nou ','Jiang ','Pang ','Ze ','Lou ','Ji ','Lao ','Huo ', + 'You ','Mo ','Huai ','Er ','Zhe ','Ting ','Ye ','Da ','Song ','Qin ','Yun ','Chi ','Dan ','Dan ','Hong ','Geng ', + 'Zhi ','','Nie ','Dan ','Zhen ','Che ','Ling ','Zheng ','You ','Wa ','Liao ','Long ','Zhi ','Ning ','Tiao ','Er ', + 'Ya ','Die ','Gua ','','Lian ','Hao ','Sheng ','Lie ','Pin ','Jing ','Tu ','Bi ','Di ','Guo ','Wen ','Xu ', + 'Ping ','Cong ','Shikato ','','Ting ','Yu ','Cong ','Kui ','Ren ','Kui ','Cong ','Lian ','Weng ','Kui ','Lian ','Lian ', + 'Cong ','Ao ','Thanh ','Song ','Ting ','Kui ','Nie ','Zhi ','Dan ','Ning ','qie ','Ji ','Ting ','Ting ','Long ','Yu ', + 'Yu ','Zhao ','Si ','Su ','Yi ','Su ','Si ','Zhao ','Zhao ','Rou ','Yi ','Lei ','Ji ','Qiu ','Ken ','Cao ', + 'Ge ','Di ','Huan ','Huang ','Yi ','Ren ','Xiao ','Ru ','Zhou ','Yuan ','Du ','Gang ','Rong ','Gan ','Cha ','Wo ', + 'Chang ','Gu ','Chi ','Han ','Fu ','Fei ','Fen ','Pei ','Pang ','Jian ','Fang ','Zhun ','You ','Noi ','Hang ','Ken ', + 'Ran ','Quang ','Duc ','Wen ','Yao ','Jin ','Pi ','Qian ','Xi ','Xi ','Fei ','Ken ','Jing ','Tai ','Shen ','Zhong ', + 'Zhang ','Xie ','Than ','Wei ','Tru ','Die ','Dan ','Fei ','Ba ','Bo ','Qu ','Tian ','Boi ','Gua ','Thai ','Zi ', + 'Ku ','Zhi ','Ni ','Ping ','Zi ','Fu ','Pang ','Zhen ','Xian ','Zuo ','Pei ','Jia ','Thang ','Zhi ','Bao ','Mu ', + 'Qu ','Hu ','Ke ','Yi ','Yin ','Xu ','Yang ','Long ','Dong ','Ka ','Lu ','Jing ','Nu ','Nhan ','Pang ','Kua ', + 'Yi ','Guang ','Hai ','Ge ','Dong ','Zhi ','Xiao ','Xiong ','Xiong ','Er ','E ','Xing ','Pian ','Nang ','Zi ','', + ], + 'x81':[ + 'Cheng ','Tiao ','Zhi ','Cui ','Mei ','Xie ','Cui ','Xie ','Mai ','Mai ','Ji ','Kyou ','Nin ','Kuai ','Sa ','Zang ', + 'Qi ','Nao ','Mi ','Nong ','Luan ','Wan ','Bo ','Wen ','Guan ','Qiu ','Jiao ','Jing ','Rou ','Heng ','Cuo ','Lie ', + 'Shan ','Ting ','Mei ','Chun ','Shen ','Qian ','Te ','Zui ','Cu ','Xiu ','Xin ','Tuo ','Pao ','Cheng ','Nei ','Fu ', + 'Dou ','Tuo ','Niao ','Nou ','Pi ','Gu ','Gua ','Li ','Lian ','Truong ','Cui ','Jie ','Liang ','Zhou ','Pi ','Biao ', + 'Lun ','Pian ','Guo ','Kui ','Chui ','Dan ','Tian ','Nei ','Jing ','Jie ','La ','Yi ','Yan ','Ren ','Shen ','Chuo ', + 'Fu ','Fu ','Ju ','Fei ','Xoang ','Wan ','Dong ','Pi ','Guo ','Zong ','Ding ','Wu ','Mei ','Ruan ','Zhuan ','Zhi ', + 'Cou ','Gua ','Ou ','Di ','An ','Tanh ','Nao ','Yu ','Chuan ','Nem ','Yun ','Zhong ','Rou ','E ','Sai ','Tu ', + 'Yao ','Jian ','Wei ','Jiao ','Yu ','Jia ','Duan ','Bi ','Chang ','Phuc ','Xian ','Ni ','Mian ','Wa ','Teng ','Tui ', + 'Bang ','Qian ','Lu ','Wa ','Sou ','Tang ','Su ','Zhui ','Ge ','Yi ','Bo ','Liao ','Ji ','Pi ','Xie ','Cao ', + 'Lu ','Bin ','','Chang ','Lu ','Guo ','Pang ','Chuai ','Piao ','Jiang ','Fu ','Tang ','Mo ','Xi ','Zhuan ','Lu ', + 'Keo ','Ying ','Lu ','Zhi ','Tara ','Chun ','Lian ','Tong ','Banh ','Ni ','Zha ','Liao ','Cui ','Gui ','Xiao ','Teng ', + 'Fan ','Zhi ','Jiao ','Shan ','Hu ','Cui ','Run ','Xiang ','Sui ','Fen ','Ying ','Dan ','Zhua ','Dan ','Kuai ','Nong ', + 'Tun ','Lian ','Bi ','Yong ','Jue ','Chu ','Yi ','Juan ','La ','Lian ','Sao ','Tun ','Gu ','Qi ','Cui ','Bin ', + 'Xun ','Ru ','Huo ','Zang ','Xian ','Biao ','Xing ','Kuan ','La ','Yan ','Lu ','Huo ','Zang ','Luo ','Qu ','Zang ', + 'Luan ','Ni ','Zang ','Chen ','Qian ','Wo ','Guang ','Tang ','Lin ','Guang ','Zi ','Jiao ','Nie ','Xu ','Ji ','Gao ', + 'Chou ','Mian ','Nie ','Zhi ','Zhi ','Ge ','Jian ','Die ','Zhi ','Xiu ','Tai ','Zhen ','Coi ','Xian ','Yu ','Cha ', + ], + 'x82':[ + 'Yao ','Yu ','Thung ','Xi ','Xi ','Jiu ','Yu ','Yu ','Hung ','Cu ','Jiu ','Xin ','She ','She ','Sha ','Jiu ', + 'Shi ','Tan ','Thu ','Shi ','Tian ','Dan ','Pho ','Pu ','Guan ','Hua ','Tan ','Chuan ','Thuan ','Xia ','Wu ','Zhou ', + 'Dao ','Gang ','Shan ','Yi ','','Pa ','Tai ','Fan ','Ban ','Chuan ','Hang ','Fang ','Ban ','Que ','Ro ','Zhong ', + 'Jian ','Cang ','Ling ','Zhu ','Ze ','Duo ','Bo ','Xian ','Ge ','Chuan ','Xia ','Lu ','Hong ','Pang ','Xi ','', + 'Fu ','Zao ','Feng ','Li ','Shao ','Yu ','Lang ','Ting ','','Wei ','Bo ','Manh ','Nian ','Ju ','Huang ','Shou ', + 'Zong ','Bian ','Mao ','Die ','Dou6','Bang ','Cha ','Yi ','Sao ','Cang ','Tau ','Lou ','Dai ','Sori ','Yao ','Tong ', + 'Tou ','Dang ','Tan ','Lu ','Yi ','Jie ','Jian ','Huo ','Meng ','Qi ','Lu ','Lu ','Chan ','Shuang ','Can ','Luong ', + 'Jian ','Gian ','Sac ','Yan ','Fu ','Ping ','Yan ','Yan ','Cao ','','Yi ','Le ','Ting ','Qiu ','Ai ','Nai ', + 'Tiao ','Jiao ','Jie ','Peng ','Wan ','Yi ','Chai ','Mian ','Mie ','Gan ','Qian ','Yu ','Yu ','Shao ','Khung ','Tu ', + 'Xia ','Qi ','Mang ','Zi ','Hui ','Sui ','Zhi ','Xiang ','Pi ','Phu ','Tun ','Wei ','Wu ','Chi ','Qi ','Sam ', + 'Wen ','Qian ','Ren ','Bup ','Kou ','Jie ','Lu ','Xu ','Ji ','Qin ','Qi ','Yuan ','Fen ','Ba ','Noi ','Xin ', + 'Ji ','Hoa ','Hua ','Fang ','Wu ','Jue ','Gou ','Zhi ','Yun ','Qin ','Ao ','So ','Mao ','Ya ','Nao ','Nhang ', + 'Hang ','Cong ','Yin ','You ','Bian ','Yi ','Susa ','Wei ','Li ','Pi ','E ','Xian ','Chang ','Cang ','Meng ','Su ', + 'Yi ','Yuan ','Ran ','Linh ','Tai ','Tiao ','Di ','Meo ','Qiong ','Li ','Yong ','Ke ','Mu ','Bac ','Bao ','Gou ', + 'Min ','Yi ','Yi ','Ju ','Phi ','Ruo ','Ku ','Zhu ','Ni ','Bo ','Bing ','Shan ','Qiu ','Yao ','Xian ','Ben ', + 'Hong ','Anh ','Zha ','Rong ','Ju ','Die ','Nie ','Gan ','Hu ','Ping ','Mei ','Fu ','Sheng ','Gu ','Bi ','Wei ', + ], + 'x83':[ + 'Phat ','Zhuo ','Mao ','Fan ','Nha ','Mao ','Mao ','Ba ','Zi ','Mo ','Zi ','Di ','Chi ','Ji ','Jing ','Long ', + '','Niao ','','Xue ','Ying ','Qiong ','Ge ','Ming ','Li ','Rong ','Yin ','Gen ','Qian ','Chai ','Chen ','Yu ', + 'Xiu ','Zi ','Lie ','Wu ','Ji ','Gui ','Thuoc ','Chong ','Ci ','Gou ','Guang ','Muong ','Chi ','Jiao ','Jiao ','Fu ', + 'Yu ','Zhu ','Zi ','Jiang ','Hui ','Yin ','Tra ','Fa ','Rong ','Nha ','Sung ','Mang ','Tong ','Zhong ','','Zhu ', + 'Xun ','Huan ','Kua ','Quan ','Gai ','Da ','Jing ','Hanh ','Chuan ','Cao ','Jing ','Er ','An ','Shou ','Chuoi ','Ren ', + 'Jian ','Sun ','Hoang ','Ping ','Li ','Jin ','Lao ','Shu ','Zhuang ','Da ','Jia ','Rao ','Bi ','Ze ','Qiao ','Hui ', + 'Qi ','Dang ','','Rong ','Hun ','Ying ','Luo ','Ying ','Xun ','Jin ','Sun ','Yin ','Mai ','Hong ','Zhou ','Yao ', + 'Du ','Wei ','Chu ','Dou ','Fu ','Ren ','Yin ','He ','Mut ','Bu ','Yun ','Di ','Dua ','Sui ','Sui ','Cheng ', + 'Chen ','Wu ','Bie ','Xi ','Geng ','Li ','Bo ','Zhu ','Mo ','Li ','Trang ','Ji ','Duo ','Qiu ','Sha ','Suo ', + 'Chen ','Feng ','Ju ','Moi ','Meng ','Xing ','Hanh ','Che ','Shen ','Jun ','Yan ','Ting ','Diao ','Cuo ','Guan ','Han ', + 'You ','Cuo ','Jia ','Wang ','You ','Niu ','Shao ','Xian ','Lang ','Fu ','E ','Mo ','Wen ','Jie ','Nan ','Mu ', + 'Vay ','Lai ','Lian ','Shi ','Wo ','To ','Lian ','Huo ','You ','Ying ','Ying ','Nuc ','Chun ','Mang ','Mang ','Ci ', + 'Wan ','Jing ','Di ','Qu ','Dong ','Jian ','Zou ','Gu ','La ','Lu ','Cuc ','Wei ','Jun ','Nie ','Kun ','He ', + 'Pu ','Zi ','Gao ','Guo ','Fu ','Ham ','Chang ','Chou ','Song ','Chui ','Zhan ','Men ','Cai ','Ba ','Li ','Tho ', + 'Bo ','Han ','Bao ','Qin ','Juan ','Xi ','Qin ','Di ','Jie ','Pu ','Dang ','Jin ','Zhao ','Tai ','Geng ','Hoa ', + 'Gu ','Lang ','Fei ','Jin ','Am ','Wang ','Phung ','Zhou ','Yan ','Ju ','Jian ','Lum ','Tan ','Shu ','Tian ','Dao ', + ], + 'x84':[ + 'Hu ','Qi ','He ','Cui ','Tao ','Chun ','Pi ','Chang ','Huan ','Fei ','Lai ','Qi ','Manh ','Ping ','Wei ','Dan ', + 'Sha ','Huan ','Yan ','Yi ','Tiao ','Qi ','Wan ','Ce ','Nai ','Kutabireru ','Tuo ','Jiu ','Tie ','Luo ','','', + 'Meng ','','Yaji ','','Ying ','Ying ','Ying ','Xiao ','Sa ','Qiu ','Ke ','Xiang ','Wan ','Yu ','Yu ','Fu ', + 'Lian ','Xuan ','Yuan ','Nan ','Ze ','Wo ','Chun ','Xiao ','Yu ','Pian ','Mao ','An ','E ','Luo ','Ying ','Huo ', + 'Gua ','Jiang ','Mian ','Zuo ','Zuo ','Ju ','Bao ','Nhu ','Xi ','Ye ','An ','Qu ','Jian ','Fu ','Lu ','Jing ', + 'Pen ','Feng ','Hong ','Hong ','Hou ','Yan ','Nhut ','Zhu ','Zi ','Xiang ','Shen ','Ge ','Jie ','Jing ','Mi ','Huang ', + 'Shen ','Pu ','Gai ','Dong ','Zhou ','Qian ','Wei ','Bo ','Wei ','Ba ','Ji ','Hu ','Zang ','Jia ','Duan ','Yao ', + 'Jun ','Cong ','Quan ','Wei ','Zhen ','Kui ','Ting ','Hun ','Toi ','Shi ','Qi ','Lan ','Zong ','Yao ','Yuan ','Mei ', + 'Yun ','Shu ','Di ','Zhuan ','Guan ','Sukumo ','Xue ','Chan ','Kai ','Kui ','','Jiang ','Lou ','Wei ','Pai ','', + 'Sou ','Yin ','Shi ','Chun ','Shi ','Yun ','Zhen ','Lang ','Nu ','Meng ','He ','Que ','Suan ','Yuan ','Li ','Ju ', + 'Xi ','Bang ','Chu ','Xu ','Tu ','Liu ','Wo ','Zhen ','Qian ','Zu ','Po ','Cuo ','Yuan ','Chu ','Yu ','Kuai ', + 'Pan ','Pu ','Pu ','Na ','Shuo ','Xi ','Fen ','Yun ','Chung ','Jian ','Ji ','Ruo ','Cang ','En ','Mi ','Hao ', + 'Sun ','Zhen ','Ming ','Sau ','Xu ','Liu ','Xi ','Gu ','Lang ','Rong ','Weng ','Gai ','Cuo ','Shi ','Tang ','Luo ', + 'Doi ','Suo ','Xian ','Bui ','Yao ','Gui ','Bi ','Zong ','Gun ','Za ','Xiu ','Ce ','Hai ','Lan ','','Ji ', + 'Li ','Can ','Lang ','Yu ','','Ying ','Mo ','Diao ','Tiao ','Mao ','Tong ','Zhu ','Peng ','An ','Sen ','Cong ', + 'Xi ','Ping ','Qiu ','Jin ','Chun ','Jie ','Wei ','Tui ','Cao ','Yu ','Yi ','Giap ','Liao ','Bi ','Lu ','Su ', + ], + 'x85':[ + 'Bu ','Zhang ','Luo ','Jiang ','Man ','Yan ','Ling ','Ji ','Piao ','Gun ','Han ','Di ','Su ','Lu ','She ','Shang ', + 'Di ','Mie ','Xun ','Mon ','Bo ','Di ','Cuo ','Zhe ','Sam ','Xuan ','Wei ','Hu ','Ao ','Mi ','Lou ','Cu ', + 'Zhong ','Cai ','Po ','Jiang ','Mi ','Cong ','Niao ','Hui ','Jun ','Yin ','Jian ','Yan ','Shu ','Yin ','Kui ','Chen ', + 'Hu ','Sha ','Kou ','Qian ','Ma ','Zang ','Sonoko ','Qiang ','Dou ','Lian ','Lin ','Kou ','Ai ','Bi ','Li ','Wei ', + 'Ji ','Tum ','Sheng ','Fan ','Muong ','Ou ','Chan ','Dian ','Xun ','Jiao ','Rui ','Rui ','Lei ','Yu ','Qiao ','Chu ', + 'Hua ','Jian ','Mai ','Yun ','Bao ','You ','Qu ','Lu ','Rao ','Hui ','E ','Teng ','Fei ','Jue ','Zui ','Fa ', + 'Ru ','Fen ','Kui ','Shun ','Rui ','Ya ','Xu ','Fu ','Jue ','Dang ','Wu ','Tong ','Si ','Xiao ','Xi ','Long ', + 'Yun ','','Qi ','Jian ','Yun ','Sun ','Ling ','Yu ','Xia ','Yong ','Ji ','Hong ','Si ','Nong ','Lei ','Xuan ', + 'Yun ','Yu ','Xi ','Hao ','Bo ','Hao ','Ai ','Wei ','Hui ','Wei ','Ji ','Ci ','Xiang ','Luan ','Mie ','Yi ', + 'Leng ','Jiang ','Can ','Shen ','Qiang ','Rom ','Ke ','Yuan ','Da ','Ti ','Tang ','Xue ','Bi ','Zhan ','Sun ','Lian ', + 'Fan ','Ding ','Jie ','Gu ','Xie ','Shu ','Jian ','Kao ','Hong ','Sa ','Xin ','Xun ','Yao ','Hai ','Sou ','Shu ', + 'Xun ','Dui ','Pin ','Wei ','Neng ','Chou ','Mai ','Nho ','Piao ','Tai ','Ci ','Zao ','Chen ','Zhen ','Er ','Ni ', + 'Ying ','Gao ','Cong ','Xiao ','Qi ','Fa ','Jian ','Xu ','Kui ','Jie ','Bian ','Diao ','Mi ','Lam ','Jin ','Cang ', + 'Miao ','Qiong ','Qie ','Xian ','','Ou ','Xian ','Su ','Lu ','Yi ','Xu ','Xie ','Li ','Yi ','La ','Lei ', + 'Xiao ','Di ','Zhi ','Bei ','Teng ','Yao ','Mo ','Huan ','Biao ','Fan ','Su ','Tan ','Tui ','Qiong ','Qiao ','Wei ', + 'Liu ','Hui ','','Gao ','Yun ','','Li ','Shu ','Chu ','Ai ','Lin ','Zao ','Xuan ','Chen ','Lai ','Huo ', + ], + 'x86':[ + 'Tuo ','Wu ','Rui ','Rui ','Qi ','Heng ','Lu ','To ','Tui ','Mang ','Yun ','Pin ','Yu ','Xun ','Ji ','Jiong ', + 'Xian ','Mo ','Hagi ','Su ','Jiong ','','Nie ','Bo ','Rang ','Yi ','Xian ','Yu ','Ju ','Lem ','Lian ','Yin ', + 'Qiang ','Ying ','Lung ','Tong ','Wei ','Yue ','Ling ','Qu ','Yao ','Fan ','Mi ','Lan ','Kui ','Lan ','Ji ','Dang ', + 'Katsura ','Lei ','Lei ','Hua ','Feng ','Zhi ','Wei ','Kui ','Zhan ','Huai ','Loe ','Ji ','Mi ','Lei ','Huai ','Luo ', + 'Ji ','Kui ','Lu ','Jian ','San ','','Lei ','Quan ','Xiao ','Yi ','Luan ','Men ','Bie ','Hu ','Hu ','Lu ', + 'Nue ','Lu ','Si ','Xiao ','Qian ','Xu ','Hu ','Xu ','Cuo ','Fu ','Hu ','Xu ','Lu ','Hu ','Yu ','Hao ', + 'Jiao ','Ju ','Guo ','Bao ','Yan ','Zhan ','Zhan ','Khuya ','Ban ','Xi ','Shu ','Trung ','Gu ','Diao ','Ji ','Cu ', + 'Cheng ','Shi ','','Di ','Zhe ','She ','Yu ','Gan ','Tua ','Hong ','Hui ','Meng ','Ge ','Sui ','Xia ','Chai ', + 'Shi ','Yi ','Ma ','Xiang ','Fang ','E ','Pa ','Chi ','Qian ','Wen ','Wen ','Rui ','Bang ','Bi ','Yue ','Yue ', + 'Jun ','Qi ','Tong ','Yin ','Qi ','Can ','Yuan ','Jue ','Hui ','Qin ','Qi ','Zhong ','Ya ','Ci ','Mu ','Wang ', + 'Fen ','Fen ','Hang ','Gong ','Tao ','Fu ','Ran ','Jie ','Phu ','Si ','Dou ','Bau ','Xian ','Ni ','Te ','Qiu ', + 'You ','Zha ','Ping ','Chi ','You ','Ha ','Han ','Ju ','Li ','Fu ','Ran ','Zha ','Gou ','Pi ','Bo ','Xian ', + 'Chau ','Diao ','Bie ','Bing ','Gu ','Ran ','Qu ','Xa ','Tie ','Ling ','Gu ','Dan ','Gu ','Ying ','Li ','Cheng ', + 'Qu ','Mou ','Cac ','Ci ','Hui ','Hui ','Mang ','Fu ','Yang ','Wa ','Lie ','Chau ','Yi ','Xian ','Kuo ','Giao ', + 'Li ','Yi ','Ping ','Jie ','Ha ','She ','Nhan ','Wang ','Mo ','Qiong ','Qie ','Gui ','Gong ','Chay ','Man ','Ebi ', + 'Zhi ','Jia ','Rao ','Si ','Qi ','Xing ','Lie ','Qiu ','Shao ','Nhong ','Jia ','Tui ','Che ','Bai ','E ','Han ', + ], + 'x87':[ + 'Xoc ','Xuan ','Ong ','Shen ','Zhen ','Fu ','Xian ','Zhe ','Wu ','Fu ','Li ','Lang ','Bi ','Chu ','Yuan ','You ', + 'Jie ','Dan ','Yan ','Ting ','Dian ','Shui ','Hui ','Gua ','Zhi ','Song ','Bay ','Ju ','Mi ','Qi ','Qi ','Yu ', + 'Jun ','La ','Meng ','Qiang ','Si ','Xi ','Trun ','Li ','Die ','Tiao ','Tao ','Kun ','Gan ','Han ','Yu ','Bang ', + 'Fei ','Pi ','Wei ','Dun ','Yi ','Yuan ','Su ','Quan ','Qian ','Rui ','Ni ','Qing ','Wei ','Liang ','Guo ','Wan ', + 'Dong ','E ','Ban ','Di ','Wang ','Can ','Yang ','Ying ','Guo ','Chan ','','La ','Ke ','Ji ','He ','Ting ', + 'Mai ','Xu ','Mian ','Yu ','Jie ','Shi ','Xuan ','Huang ','Yan ','Bian ','Rou ','Wei ','Fu ','Yuan ','Mei ','Wei ', + 'Fu ','Ruan ','Xie ','Du ','Qiu ','Mao ','Xia ','Ying ','Shi ','Trun ','Tang ','Zhu ','Zong ','Ti ','Fu ','Yuan ', + 'Hui ','Meng ','La ','Noc ','Ha ','Qiu ','Die ','Li ','Gua ','Yun ','Ju ','Nan ','Lou ','Qun ','Rong ','Ying ', + 'Jiang ','','Lang ','Pang ','Si ','Xi ','Ci ','Xi ','Yuan ','Ong ','Lian ','Sou ','Ban ','Rong ','Rong ','Ji ', + 'Wu ','Qiu ','Han ','Qin ','Yi ','Bi ','Hua ','Tang ','Yi ','Du ','Nai ','He ','Hu ','Hui ','Ma ','Ming ', + 'Yi ','Wen ','Ying ','Teng ','Yu ','Cang ','So ','Ebi ','Man ','','Shang ','Shi ','Cao ','Chi ','Di ','Ao ', + 'Lu ','Wei ','Zhi ','Tang ','Chen ','Piao ','Qu ','Pi ','Yu ','Jian ','Luo ','Sau ','Qin ','Zhong ','Yin ','Jiang ', + 'Shuai ','Wen ','Jiao ','Wan ','Zhe ','Zhe ','Ma ','Ma ','Guo ','Liu ','Mao ','Xi ','Cong ','Li ','Man ','Xiao ', + 'Tou ','Zhang ','Mang ','Xiang ','Mo ','Zui ','Si ','Qiu ','Te ','Zhi ','Peng ','Peng ','Jiao ','Qu ','Bie ','Liu ', + 'Pan ','Ve ','Xi ','Ji ','Zhuan ','Huang ','Fei ','Lao ','Jue ','Jue ','Hui ','Yin ','Chan ','Jiao ','Shan ','Rao ', + 'Xiao ','Mou ','Trung ','Xun ','Si ','','Cheng ','Dang ','Li ','Xie ','Shan ','Yi ','Jing ','Da ','Chan ','Qi ', + ], + 'x88':[ + 'Ci ','Xiang ','She ','Luo ','Qin ','Ying ','Chai ','Li ','Ze ','Xuan ','Lian ','Zhu ','Ze ','Xie ','Mang ','Xie ', + 'Qi ','Rong ','Jian ','Meng ','Hao ','Ru ','Huo ','Zhuo ','Jie ','Bin ','He ','Mot ','Fan ','Lei ','Jie ','La ', + 'Mi ','Li ','Chun ','Li ','Qiu ','Nie ','Lu ','Du ','Xiao ','Zhu ','Long ','Li ','Long ','Feng ','Ye ','Beng ', + 'Shang ','Gu ','Juan ','Ying ','','Xi ','Can ','Qu ','Quan ','Du ','Can ','Man ','Jue ','Jie ','Zhu ','Zha ', + 'Xie ','Huang ','Niu ','Pei ','Nu ','Xin ','Zhong ','Mo ','Er ','Ke ','Met ','Xi ','Hang ','Yan ','Kan ','Yuan ', + '','Ling ','Xuan ','Shu ','Xian ','Tong ','Long ','Jie ','Xian ','Ya ','Hu ','Wei ','Dao ','Chong ','Wei ','Dao ', + 'Zhun ','Heng ','Qu ','Y ','Koromohen ','Bu ','Gan ','Yu ','Biao ','Cha ','Yi ','Oam ','Chen ','Fu ','Gun ','Fen ', + 'Suy ','Jie ','Na ','Zhong ','Dan ','Ri ','Zhong ','Zhong ','Xie ','Qi ','Xie ','Ran ','Zhi ','Ren ','Kham ','Jin ', + 'Jun ','Yuan ','Mei ','Chai ','Ao ','Niao ','Hui ','Ran ','Ca ','Tuo ','Ling ','Dai ','Bao ','Bao ','Yao ','Ven ', + 'Bi ','Cheo ','Tan ','Ju ','He ','Shu ','Tu ','Zhen ','Yi ','Pa ','Bo ','Di ','Wa ','Fu ','Gon ','Zhi ', + 'Zhi ','Ran ','Pan ','Yi ','Mao ','','Na ','Kou ','Xian ','Chan ','Qu ','Bei ','Gun ','Xi ','Ne ','Bo ', + 'Horo ','Fu ','Yi ','Chi ','Kho ','Ren ','Jiang ','Jia ','Cun ','Mo ','Jie ','Er ','Luo ','Ru ','Zhu ','Gui ', + 'Yin ','Trai ','Lie ','Kamishimo ','Yuki ','Zhuang ','Dang ','Seot ','Kun ','Ken ','Niao ','Shu ','Jia ','Kun ','Cheng ','Li ', + 'Juan ','Shen ','Bau ','Ge ','Yi ','Yu ','Zhen ','Liu ','Qiu ','Qun ','Ji ','Yi ','Bu ','Trang ','Shui ','Sha ', + 'Qun ','Li ','Lian ','Lian ','Ku ','Jian ','Fou ','Chan ','Bi ','Gun ','Tao ','Yuan ','Ling ','Chi ','Chang ','Chou ', + 'Duo ','Biao ','Liang ','Chang ','Bui ','Pei ','Fei ','Yuan ','Luo ','Guo ','Yan ','Du ','Xi ','Zhi ','Ju ','Qi ', + ], + 'x89':[ + 'Ji ','Zhi ','Gua ','Ken ','Tsuma ','Ti ','Ti ','Fu ','Chong ','Xie ','Bian ','Die ','Kun ','Duan ','Xiu ','Xiu ', + 'He ','Yuan ','Bao ','Bao ','Fu ','Yu ','Tuan ','Yan ','Hui ','Bei ','Chu ','Lu ','Ena ','Tan ','Yun ','Da ', + 'Gou ','Da ','Huai ','Rong ','Yuan ','Ru ','Nai ','Jiong ','Suo ','Ban ','Tun ','Chi ','Sang ','Niao ','Ying ','Jie ', + 'Qian ','Huai ','Kho ','Lian ','Bao ','Li ','Chap ','Shi ','Lu ','Yi ','Die ','Xie ','Xian ','Wei ','Biao ','Cao ', + 'Ji ','Jiang ','Sen ','Bao ','Xiang ','Chihaya ','Boc ','Jian ','Zhuan ','Jian ','Tui ','Ji ','Dan ','Za ','Fan ','Bo ', + 'Xiang ','Xin ','Bie ','Rao ','Man ','Lan ','Ao ','Duo ','Gui ','Cao ','Sui ','Nong ','Chan ','Lian ','Bi ','Jin ', + 'Dang ','Shu ','Tan ','Bi ','Lan ','Pu ','Ru ','Zhi ','','Shu ','Wa ','Shi ','Bai ','Xie ','Bo ','Chen ', + 'Lai ','Long ','Xi ','Xian ','Lan ','Zhe ','Dai ','Tasuki ','Zan ','Shi ','Jian ','Pan ','Yi ','Ran ','Ya ','Tay ', + 'Xi ','Yao ','Feng ','Tan ','','Biao ','Fu ','Ba ','He ','Ji ','Ji ','Jian ','Guan ','Bian ','Yan ','Qui ', + 'Jue ','Pian ','Mao ','Mi ','Mi ','Mie ','Shi ','Si ','Zhan ','Luo ','Jue ','Mi ','Tiao ','Lian ','Yao ','Zhi ', + 'Jun ','Xi ','Shan ','Wei ','Xi ','Tian ','Yu ','Lan ','E ','Du ','Than ','Pang ','Ji ','Ming ','Ying ','Gou ', + 'Qu ','Zhan ','Jin ','Guan ','Deng ','Jian ','Luo ','Qu ','Jian ','Wei ','Jue ','Qu ','Luo ','Lan ','Shen ','Di ', + 'Quan ','Jian ','Guan ','Yan ','Gui ','Mi ','Shi ','Zhan ','Lan ','Jue ','Ji ','Xi ','Di ','Tian ','Yu ','Gou ', + 'Jin ','Qu ','Jiao ','Jiu ','Jin ','Cu ','Jue ','Zhi ','Chao ','Ji ','Gu ','Dan ','Zi ','Di ','Shang ','Khoe ', + 'Quan ','Ge ','Chi ','Jie ','Gui ','Gong ','Chu ','Jie ','Hun ','Qiu ','Xing ','Su ','Ni ','Ji ','Lu ','Zhi ', + 'Zha ','Bi ','Xing ','Hu ','Shang ','Gong ','Zhi ','Xue ','Xuc ','Xi ','Yi ','Lu ','Jue ','Xi ','Yan ','Xi ', + ], + 'x8a':[ + 'Yan ','Gonben ','Ding ','Fu ','Qiu ','Qiu ','Jiao ','Hong ','Ji ','Fan ','Xun ','Diao ','Hong ','Cha ','Tao ','Xu ', + 'Jie ','Yi ','Ren ','Huan ','Yin ','Shan ','Qi ','Tuo ','Ji ','Xun ','Yin ','Ngoa ','Fen ','Ya ','Yao ','Tung ', + 'Shen ','Yin ','Xin ','Jue ','Xiao ','Dot ','Chen ','You ','Zhi ','Xiong ','Fang ','Xin ','Chao ','She ','Xian ','Sha ', + 'Tun ','Xu ','Yi ','Yi ','To ','Chi ','He ','Shen ','He ','Xu ','Zhen ','Chu ','Zheng ','Gou ','Zi ','Zi ', + 'Zhan ','Gu ','Fu ','Quan ','Die ','Ling ','Di ','Yang ','Li ','Nao ','Pan ','Zhou ','Gan ','Yi ','Ju ','Ao ', + 'Zha ','Tuo ','Yi ','Qu ','Zhao ','Ping ','Bi ','Xiong ','Qu ','Ba ','Da ','Tro ','Tao ','Zhu ','Ci ','Zhe ', + 'Yong ','Xu ','Xun ','Yi ','Huang ','He ','Shi ','Cha ','Jiao ','Thi ','Hen ','Cha ','Gou ','Gui ','Quan ','Hui ', + 'Jie ','Hua ','Gai ','Xiang ','Wei ','Shen ','Chou ','Tong ','Mi ','Zhan ','Ming ','E ','Hui ','Yan ','Xiong ','Gua ', + 'Er ','Beng ','Tiao ','Chi ','Lei ','Tru ','Kuang ','Khoa ','Wu ','Yu ','Teng ','Ji ','Zhi ','Ren ','Su ','Lang ', + 'E ','Kuang ','E ','Shi ','Ting ','Dan ','Bo ','Chan ','Du ','Heng ','Qiao ','Qin ','Shua ','An ','Yu ','Xiao ', + 'Thanh ','Jie ','Xian ','Vu ','Wu ','Gao ','Tung ','Pu ','Hoi ','Jing ','Shuo ','Zhen ','Shuo ','Du ','Yasashi ','Chang ', + 'Shui ','Jie ','Ke ','Qu ','Cong ','Xiao ','Sui ','Wang ','Xuan ','Fei ','Chi ','Ta ','Yi ','Na ','Yin ','Diao ', + 'Pi ','Chuo ','Chan ','Chen ','Zhun ','Ji ','Qi ','Tan ','Zhui ','Wei ','Ju ','Qing ','Jian ','Zheng ','Ze ','Zou ', + 'Qian ','Zhuo ','Liang ','Jian ','Zhu ','Hao ','Lun ','Shen ','Biao ','Huai ','Pian ','Hua ','Die ','Xu ','Pian ','Shi ', + 'Xuan ','Shi ','Hun ','Hua ','E ','Zhong ','Di ','Hai ','Fu ','Pu ','Ting ','Jian ','Qi ','Du ','Zi ','Chuan ', + 'Xi ','Hui ','Yin ','Am ','Xian ','Nan ','Chen ','Phung ','Chu ','Yang ','Yan ','Heng ','Xuan ','Ge ','Nuo ','Qi ', + ], + 'x8b':[ + 'Muu ','Ye ','Wei ','','Teng ','Zou ','Shan ','Jian ','Bo ','','Huang ','Huo ','Ge ','Ying ','Mi ','Xiao ', + 'Mi ','Xi ','Qiang ','Chen ','Huoc ','Ti ','Su ','Bang ','Chi ','Qian ','Shi ','Jiang ','Yuan ','Xie ','Xue ','Tao ', + 'Dao ','Yao ','','Yu ','Biao ','Cong ','Qing ','Li ','Mo ','Mo ','Shang ','Zhe ','Miu ','Jian ','Ze ','Jie ', + 'Lian ','Lou ','Can ','Ou ','Guan ','Xi ','Zhuo ','Ao ','Ao ','Jin ','Zhe ','Yi ','Hu ','Jiang ','Man ','Chao ', + 'Han ','Hua ','Chan ','Xu ','Zeng ','Se ','Xi ','She ','Dui ','Zheng ','Nao ','Lan ','E ','Ying ','Jue ','Ji ', + 'Zun ','Jiao ','Bo ','Hui ','Zhuan ','Mu ','Zen ','Zha ','Shi ','Qiao ','Tan ','Zen ','Pu ','Sheng ','Xuan ','Zao ', + 'Tan ','Dang ','Sui ','Qian ','Ji ','Jiao ','Jing ','Lian ','Nou ','Yi ','Ai ','Zhan ','Pi ','Hui ','Hua ','Yi ', + 'Yi ','Shan ','Rang ','Nou ','Qian ','Zhui ','Ta ','Ho ','Zhou ','Hao ','Ye ','Ying ','Jian ','Yu ','Jian ','Hui ', + 'Du ','Zhe ','Xuan ','Zan ','Lei ','Shen ','Wei ','Chan ','Li ','Yi ','Bian ','Zhe ','Yan ','E ','Thu ','Wei ', + 'Chou ','Yao ','Sam ','Rang ','Yin ','Lan ','Chen ','Huo ','Zhe ','Huan ','Zan ','Yi ','Dang ','Zhan ','Yan ','Du ', + 'Yan ','Ji ','Ding ','Fu ','Ren ','Ji ','Jie ','Hong ','Tao ','Rang ','Shan ','Qi ','Tuo ','Xun ','Yi ','Xun ', + 'Ji ','Ren ','Jiang ','Hui ','Ou ','Ju ','Ya ','Ne ','Xu ','E ','Lun ','Xiong ','Song ','Feng ','She ','Fang ', + 'Jue ','Zheng ','Gu ','He ','Ping ','Zu ','Shi ','Xiong ','Zha ','Su ','Zhen ','Di ','Zou ','Ci ','Qu ','Zhao ', + 'Bi ','Yi ','Yi ','Kuang ','Lei ','Shi ','Gua ','Shi ','Jie ','Hui ','Cheng ','Zhu ','Shen ','Hua ','Dan ','Gou ', + 'Quan ','Gui ','Xun ','Yi ','Zheng ','Gai ','Xiang ','Cha ','Hun ','Xu ','Zhou ','Jie ','Wu ','Yu ','Qiao ','Wu ', + 'Gao ','You ','Hui ','Kuang ','Shuo ','Song ','Ai ','Qing ','Zhu ','Zou ','Nuo ','Du ','Zhuo ','Fei ','Ke ','Wei ', + ], + 'x8c':[ + 'Yu ','Shui ','Shen ','Diao ','Chan ','Liang ','Zhun ','Sui ','Tan ','Shen ','Yi ','Mou ','Chen ','Die ','Huang ','Jian ', + 'Xie ','Nue ','Ye ','Wei ','E ','Yu ','Xuan ','Chan ','Zi ','An ','Yan ','Di ','Mi ','Pian ','Xu ','Mo ', + 'Dang ','Su ','Xie ','Yao ','Bang ','Shi ','Qian ','Mi ','Jin ','Man ','Zhe ','Jian ','Miu ','Tan ','Zen ','Qiao ', + 'Lan ','Pu ','Jue ','Yan ','Qian ','Zhan ','Chen ','Coc ','Qian ','Hong ','Xia ','Jue ','Hong ','Han ','Hong ','Xi ', + 'Xi ','Huo ','Liao ','Han ','Du ','Long ','Dou ','Jiang ','Qi ','Chi ','Li ','Deng ','Wan ','Bi ','Shu ','Xian ', + 'Phong ','Zhi ','Zhi ','Yan ','Yan ','Shi ','Chu ','Hui ','Tun ','Yi ','Tun ','Yi ','Jian ','Ba ','Hou ','E ', + 'Cu ','Xiang ','Huan ','Jian ','Ken ','Gai ','Qu ','Fu ','Xi ','Bin ','Hao ','Yu ','Tru ','Jia ','Fen ','Xi ', + 'Bo ','Wen ','Huan ','Bin ','Di ','Zong ','Fen ','Yi ','Zhi ','Beo ','Sai ','An ','Pi ','Na ','Pi ','Gou ', + 'Na ','You ','Diao ','Mo ','Si ','Huou ','Huan ','Kun ','He ','He ','Mo ','Han ','Mao ','Li ','Ni ','Bi ', + 'Yu ','Jia ','Tuan ','Mao ','Pi ','Xi ','E ','Ju ','Mo ','Chu ','Tan ','Huan ','Jue ','Bei ','Trinh ','Yuan ', + 'Phu ','Tai ','Cong ','Te ','Yi ','Hang ','Wan ','Pin ','Huo ','Fan ','Tham ','Quan ','Ze ','Zhi ','Er ','Zhu ', + 'Shi ','Bi ','Zi ','Er ','Gui ','Pian ','Bian ','Mai ','Dai ','Sheng ','Kuang ','Fei ','Tie ','Yi ','Chi ','Mao ', + 'He ','Bi ','Lo ','Lin ','Hui ','Gai ','Pian ','Zi ','Jia ','Xu ','Zei ','Jiao ','Gai ','Zang ','Jian ','Ying ', + 'Xun ','Zhen ','She ','Tan ','Bin ','Qiu ','She ','Chuan ','Zang ','Zhou ','Lai ','Zan ','Ci ','Chen ','Shang ','Tian ', + 'Pei ','Geng ','Xian ','Mai ','Jian ','Sui ','Phu ','Tan ','Cong ','Cong ','Chat ','Ji ','Zhang ','Du ','Jin ','Xiong ', + 'Shun ','Yun ','Bao ','Zai ','Lai ','Phung ','Cang ','Ji ','Sheng ','Ai ','Zhuan ','Fu ','Gou ','Sai ','Ze ','Liao ', + ], + 'x8d':[ + 'Wei ','Bai ','Chen ','Zhuan ','Zhi ','Zhui ','Biao ','Yun ','Zeng ','Tan ','Zan ','Yan ','','Shan ','Wan ','Ying ', + 'Jin ','Gan ','Xian ','Tang ','Bi ','Du ','Chuoc ','Yan ','','Xuan ','Long ','Gan ','Zang ','Bei ','Zhen ','Fu ', + 'Yuan ','Gong ','Cai ','Ze ','Xian ','Bai ','Zhang ','Huo ','Zhi ','Fan ','Tan ','Pin ','Bian ','Gou ','Zhu ','Guan ', + 'Er ','Jian ','Bi ','Shi ','Tie ','Gui ','Kuang ','Dai ','Mao ','Fei ','He ','Yi ','Zei ','Zhi ','Jia ','Hui ', + 'Zi ','Ren ','Lu ','Zang ','Zi ','Gai ','Jin ','Qiu ','Zhen ','Lai ','She ','Fu ','Du ','Ji ','Shu ','Shang ', + 'Si ','Bi ','Zhou ','Geng ','Pei ','Tan ','Lai ','Feng ','Zhui ','Fu ','Zhuan ','Sai ','Ze ','Yan ','Zan ','Yun ', + 'Zeng ','Shan ','Ying ','Gan ','Chi ','Xi ','She ','Nan ','Xiong ','Xi ','Cheng ','He ','Cheng ','Zhe ','Xia ','Tang ', + 'Zou ','Zou ','Li ','Jiu ','Fu ','Zhao ','Gan ','Qi ','Shan ','Qiong ','Qin ','Xian ','Ci ','Jue ','Qin ','Chi ', + 'Ci ','San ','Chen ','Die ','Ju ','Chao ','Di ','Se ','Zhan ','Zhu ','Yue ','Qu ','Jie ','Chi ','Chu ','Gua ', + 'Xue ','Ci ','Tiao ','Duo ','Lie ','Gan ','Suo ','Cu ','Xi ','Zhao ','Su ','Yin ','Ju ','Jian ','Que ','Tang ', + 'Chuo ','Cui ','Lu ','Thu ','Dang ','Qiu ','Zi ','Ti ','Xu ','Chi ','Huang ','Qiao ','Qiao ','Yao ','Zao ','Ti ', + '','Zan ','Zan ','Tuc ','Pa ','Bao ','Ku ','Ke ','Dun ','Jue ','Fu ','Chen ','Jian ','Fang ','Zhi ','Sa ', + 'Yue ','Pa ','Qi ','Yue ','Qiang ','Tuo ','Tai ','Yi ','Nian ','Ling ','Mei ','Ba ','Die ','Ku ','Tuo ','Jia ', + 'Ci ','Pao ','Qia ','Zhu ','Ju ','Die ','Zhi ','Fu ','Pan ','Ju ','Shan ','Bo ','Ni ','Ju ','Li ','Ngan ', + 'Yi ','Ji ','Dai ','Xian ','Jiao ','Duo ','Zhu ','Quan ','Kua ','Zhuai ','Gui ','Qiong ','Kui ','Xiang ','Choi ','Lo ', + 'Beng ','Zhi ','Jia ','Tiao ','Cai ','Jian ','Ta ','Qiao ','Bi ','Xian ','Duo ','Ji ','Ju ','Ji ','Shu ','Tu ', + ], + 'x8e':[ + 'Chu ','Jing ','Nie ','Xiao ','Bo ','Chi ','Qun ','Mou ','Shu ','Lang ','Yong ','Jiao ','Chou ','Qiao ','Mau ','Ta ', + 'Jian ','Qi ','Wo ','Wei ','Zhuo ','Jie ','Ji ','Nie ','Guoc ','Ju ','Lun ','Lu ','Leng ','Huai ','Ju ','Chi ', + 'Wan ','Quan ','Ti ','Voi ','Zu ','Qie ','Ji ','Cu ','Zong ','Cai ','Zong ','Peng ','Zhi ','Zheng ','Dian ','Zhi ', + 'Yu ','Duo ','Dun ','Chun ','Yong ','Zhong ','Di ','Zhe ','Chen ','Chuai ','Jian ','Gua ','Tang ','Ju ','Fu ','Zu ', + 'Die ','Pian ','Rou ','Nuo ','Ti ','Cha ','Tui ','Jian ','Dao ','Tha ','Xi ','Ta ','Qiang ','Zhan ','Chan ','Ti ', + 'Ji ','Nie ','Man ','Liu ','Zhan ','Bi ','Chong ','Lu ','Liao ','Cu ','Tang ','Dai ','Toc ','Xi ','Kui ','Ji ', + 'Zhi ','Qiang ','Di ','Pan ','Zong ','Lian ','Beng ','Zao ','Nian ','Bie ','Tui ','Ju ','Deng ','Ceng ','Xian ','Fan ', + 'Chu ','Zhong ','Dun ','Bo ','Cu ','Zu ','Jue ','Jue ','Lin ','Ta ','Qiao ','Qiao ','Pu ','Liao ','Dun ','Cuan ', + 'Kuang ','Zao ','Ta ','Bi ','Bi ','Ghen ','Ju ','Chu ','Qiao ','Dun ','Tru ','Ji ','Wu ','Yue ','Nian ','Lin ', + 'Lie ','Zhi ','Li ','Zhi ','Chan ','Chu ','Duan ','Wei ','Long ','Lin ','Xian ','Wei ','Zuan ','Lan ','Xie ','Rang ', + 'Xie ','Nie ','Ta ','Qu ','Jie ','Cuan ','Zuan ','Xi ','Kui ','Jue ','Lin ','Than ','Cung ','Dan ','Segare ','Qu ', + 'Ti ','Duo ','Duo ','Gong ','Lang ','Nerau ','Luo ','Ai ','Ji ','Ju ','Tang ','Utsuke ','','Yan ','Shitsuke ','Kang ', + 'Xo ','Lou ','Lao ','Tuo ','Zhi ','Yagate ','Ti ','Dao ','Yagate ','Yu ','Xa ','Ya ','Gui ','Quan ','Wei ','Ngot ', + 'Xin ','Di ','Xuan ','Fan ','Ren ','Shan ','Qiang ','Shu ','Tun ','Chen ','Dai ','E ','Na ','Qi ','Mao ','Ruan ', + 'Ren ','Fan ','Zhuan ','Hong ','Hu ','Qu ','Huang ','Di ','Ling ','Dai ','Ao ','Zhen ','Fan ','Kuang ','Ang ','Peng ', + 'Bei ','Gu ','Gu ','Pao ','Zhu ','Rong ','E ','Ba ','Truc ','Zhi ','Yao ','Ke ','Yi ','Qing ','Shi ','Ping ', + ], + 'x8f':[ + 'Er ','Qiong ','Ju ','Jiao ','Guang ','Lu ','Kai ','Quan ','Zhou ','Zai ','Zhi ','She ','Liang ','Yu ','Shao ','You ', + 'Huan ','Yun ','Zhe ','Wan ','Fu ','Khinh ','Zhou ','Ni ','Ling ','Zhe ','Zhan ','Liang ','Zi ','Huy ','Wang ','Chuo ', + 'Guo ','Kan ','Yi ','Peng ','Qian ','Gun ','Nian ','Pian ','Guan ','Boi ','Luan ','Pai ','Liang ','Ruan ','Rou ','Ji ', + 'Yang ','Xian ','Chuan ','Cou ','Chun ','Ge ','You ','Hong ','Thau ','Fu ','Zi ','Fu ','Wen ','Ben ','Zhan ','Yu ', + 'Wen ','Tao ','Gu ','Zhen ','Xia ','Yuan ','Lu ','Jiu ','Chao ','Zhuan ','Wei ','Hun ','Sori ','Che ','Jiao ','Zhan ', + 'Pu ','Lao ','Fen ','Fan ','Lin ','Ge ','Se ','Kan ','Huan ','Yi ','Ji ','Dui ','Er ','Yu ','Xian ','Hong ', + 'Lei ','Pei ','Li ','Li ','Lu ','Lin ','Che ','Ya ','Gui ','Xuan ','Di ','Ren ','Zhuan ','E ','Lun ','Ruan ', + 'Hong ','Gu ','Ke ','Lu ','Zhou ','Zhi ','Yi ','Hu ','Zhen ','Li ','Yao ','Qing ','Shi ','Zai ','Zhi ','Jiao ', + 'Zhou ','Quan ','Lu ','Jiao ','Zhe ','Fu ','Liang ','Nian ','Bei ','Hui ','Gun ','Wang ','Liang ','Chuo ','Zi ','Cou ', + 'Fu ','Ji ','Wen ','Shu ','Pei ','Yuan ','Xia ','Zhan ','Lu ','Che ','Lin ','Tan ','Gu ','Ci ','Ci ','Pi ', + 'Zui ','Bian ','La ','La ','Ci ','Xue ','Ban ','Bian ','Bian ','Bian ','','Bian ','Ban ','Ci ','Bian ','Bian ', + 'Chen ','Nhoc ','Nong ','Nong ','Zhen ','Chuo ','Chuo ','Suberu ','Reng ','Bian ','Bian ','Tsuji ','Komu ','Liao ','Da ','Chan ', + 'Gan ','Qian ','Vu ','Yu ','Hat ','Xun ','Yi ','Guo ','Mai ','Qi ','Za ','Wang ','tu ','Zhun ','Ying ','Ti ', + 'Yun ','Jin ','Hang ','Ya ','Fan ','Wu ','Da ','E ','Huan ','Zhe ','Totemo ','Jin ','Yuan ','Wei ','Lian ','Chi ', + 'Che ','Ni ','Tiao ','Zhi ','Yi ','Jiong ','Da ','Chen ','Dai ','Er ','Di ','Po ','Wang ','Die ','Ze ','Tao ', + 'Shu ','Tuo ','Kep ','Jing ','Hui ','Tong ','You ','Mi ','Beng ','Ji ','Nai ','Yi ','Jie ','Truy ','Luot ','Xun ', + ], + 'x90':[ + 'Tui ','Tong ','Shi ','Tao ','Pang ','Hou ','Ni ','Dun ','Jiong ','Xuan ','Xun ','Bu ','You ','Xiao ','Tua ','Thau ', + 'Truc ','Qiu ','Di ','Di ','Tu ','Jing ','Ti ','Dou ','Yi ','Zhe ','Tong ','Guang ','Wu ','Shi ','Cheng ','Toc ', + 'Zao ','Qun ','Phung ','Lian ','Suo ','Hui ','Li ','Sako ','Lai ','Ben ','Cuo ','Jue ','Beng ','Huan ','Dai ','Lu ', + 'You ','Chu ','Jin ','Yu ','Ruoc ','Kui ','Wei ','Ti ','Yi ','Da ','Yuan ','Luo ','Bi ','Nuo ','Du ','Dang ', + 'Sui ','Tron ','Sui ','Yan ','Chuan ','Chi ','Ti ','Ngo ','Shi ','Zhen ','Du ','Yun ','E ','Bian ','Guo ','E ', + 'Xia ','Huang ','Qiu ','Dao ','Da ','Vi ','Appare ','Yi ','Gou ','Yao ','Chu ','Liu ','Xun ','Ta ','Di ','Chi ', + 'Yuan ','Su ','Ta ','Qian ','','Yao ','Guan ','Zhang ','Ngao ','Shi ','Ce ','Chi ','Su ','Tao ','Zhe ','Ron ', + 'Di ','Lou ','Chi ','Cuo ','Lin ','Tuan ','Rao ','Qian ','Xuan ','Yu ','Di ','Wu ','Liao ','Ju ','Shi ','Bi ', + 'Yao ','Mai ','Xie ','Sui ','Hoan ','Zhan ','Teng ','Er ','Miao ','Bian ','Bian ','La ','Li ','Yuan ','Yao ','Luo ', + 'Li ','Yi ','Ting ','Deng ','Qi ','Yong ','Shan ','Han ','Yu ','Muong ','Ru ','Qiong ','','Kuang ','Fu ','Kang ', + 'Bin ','Fang ','Xing ','Na ','','Shen ','Vang ','Yuan ','Cun ','Huo ','Ta ','Bang ','Wu ','Ju ','You ','Han ', + 'Tai ','Qiu ','Bi ','Pei ','Bing ','Shao ','Bei ','Wa ','Di ','Zou ','Ye ','Lin ','Kuang ','Gui ','Chau ','Shi ', + 'Ku ','Yu ','Gai ','He ','Xi ','Zhi ','Ji ','Xun ','Hou ','Xing ','Jiao ','Xi ','Gui ','Nuo ','Lang ','Jia ', + 'Kuai ','Zheng ','Rou ','Yun ','Yan ','Cheng ','Dou ','Chi ','Lu ','Fu ','Wu ','Fu ','Gao ','Hao ','Lang ','Jia ', + 'Geng ','Jun ','Ying ','Bo ','Xi ','Bei ','Li ','Yun ','Bo ','Xiao ','Qi ','Pi ','Qing ','Guo ','','Tan ', + 'Zou ','Ping ','Lai ','Ni ','Chen ','You ','Bu ','Xiang ','Dan ','Ju ','Yong ','Qiao ','Yi ','Du ','Yan ','Mei ', + ], + 'x91':[ + 'Ruo ','Bei ','E ','Yu ','Juan ','Yu ','Yun ','Hou ','Kui ','Xiang ','Xiang ','Sou ','Tang ','Ming ','Xi ','Ru ', + 'Chu ','Zi ','Zou ','Ju ','Wu ','Huong ','Yun ','Hao ','Yong ','Bi ','Mo ','Chao ','Fu ','Liao ','Yin ','Zhuan ', + 'Hu ','Qiao ','Yan ','Zhang ','Man ','Qiao ','Xu ','Deng ','Bi ','Xin ','Bi ','Ceng ','Wei ','Zheng ','Mao ','Shan ', + 'Lan ','Po ','Dan ','Meng ','Ye ','Cao ','Kuai ','Feng ','Meng ','Zou ','Kuang ','Lian ','Zan ','Chan ','You ','Qi ', + 'Yan ','Chan ','Zan ','Ling ','Huan ','Xi ','Feng ','Zan ','Li ','Dau ','Ding ','Qiu ','Chuoc ','Phoi ','Zhou ','Yi ', + 'Hang ','Yu ','Jiu ','Yan ','Zui ','Mao ','Dan ','Xu ','Tou ','Zhen ','Fen ','Sakenomoto ','','Yun ','Tai ','Tian ', + 'Qia ','Tuo ','Zuo ','Han ','Gu ','Su ','Po ','Chou ','Zai ','Ming ','Lao ','Chuo ','Thu ','You ','Tong ','Zhi ', + 'Xian ','Jiang ','Xanh ','Yin ','Tu ','Jiao ','Mei ','Khoc ','Suan ','Lei ','Pu ','Zui ','Hai ','Yan ','Xi ','Niang ', + 'Wei ','Lu ','Lan ','Yan ','Tao ','Pei ','Zhan ','Chun ','Tan ','Zui ','Chuo ','Cu ','Kun ','Ti ','Mian ','Du ', + 'Hu ','Xu ','Xing ','Tan ','Jiu ','Chun ','Yun ','Po ','Ke ','Sou ','Mi ','Quan ','Xau ','Say ','Yun ','Yong ', + 'Ang ','Zha ','Hai ','Tang ','Jiang ','Piao ','Shan ','Yu ','Li ','Zao ','Lao ','Y ','Tuong ','Bu ','Jiao ','Xi ', + 'Tan ','Po ','Nong ','Yi ','Li ','Ju ','Jiao ','Yi ','Niang ','Ru ','Xun ','Chou ','Yan ','Ling ','Mi ','Mi ', + 'Niang ','Xin ','Jiao ','Xi ','Mi ','Yan ','Bian ','Cai ','Shi ','You ','Shi ','Shi ','Li ','Trong ','Ye ','Liang ', + 'Li ','Kim ','','Ga ','Yi ','Liao ','Dao ','Zhao ','Ding ','Po ','Qiu ','He ','Fu ','Cham ','Zhi ','Ngoat ', + 'Luan ','Fu ','Nai ','Diao ','Shan ','Qiao ','Kou ','Chuan ','Zi ','Fan ','Yu ','Hua ','Han ','Cong ','Qi ','Mang ', + 'Ri ','Di ','Si ','Xi ','Yi ','Thoa ','Shi ','Tu ','Xi ','Nu ','Qian ','Kyuu ','Jian ','Pi ','Ye ','Yin ', + ], + 'x92':[ + 'Ba ','Fang ','Chen ','Xing ','Dou ','Yue ','Yan ','Fu ','Pi ','Na ','Xin ','E ','Khoet ','Nhon ','Gou ','Yin ', + 'Qian ','Ban ','Ji ','Ren ','Chao ','Niu ','Fen ','Yun ','Ji ','Qin ','Pi ','Guo ','Hong ','Yin ','Jun ','Shi ', + 'Yi ','Zhong ','Nie ','Gai ','Ri ','Huo ','Tai ','Kang ','Habaki ','Ro ','Ngaak ','','Duo ','Zi ','Ban ','Tu ', + 'Shi ','Min ','Gu ','Ke ','Ling ','Bing ','Yi ','Gu ','Bo ','Pi ','Yu ','Si ','Zuo ','Bua ','You ','Dian ', + 'Jia ','Zhen ','Shi ','Shi ','Tie ','Ju ','Chan ','Shi ','Shi ','Xuan ','Zhao ','Bao ','He ','Bi ','Sheng ','Chu ', + 'Shi ','Bo ','Zhu ','Chi ','Za ','Po ','Tong ','Qian ','Fu ','Zhai ','Liu ','Qian ','Fu ','Li ','Yue ','Pi ', + 'Yang ','Ban ','Bo ','Jie ','Cau ','Shu ','Zheng ','Mu ','Ni ','Nie ','Di ','Jia ','Mu ','Dan ','Shen ','Yi ', + 'Si ','Kuang ','Ka ','Bei ','Jian ','Tong ','Xing ','Hong ','Jiao ','Chi ','Er ','Ge ','Bing ','Shi ','Mou ','Ha ', + 'Ngan ','Jun ','Zhou ','Sung ','Shang ','Tong ','Mo ','Lei ','Ji ','Yu ','Nhong ','Ren ','Zun ','Zhi ','Qiong ','Shan ', + 'Chi ','Ten ','Xing ','Quan ','Pi ','Tie ','Zhu ','Hou ','Ming ','Gio ','Yao ','Xian ','Xian ','Xiu ','Jun ','Cha ', + 'Lao ','Ji ','Pi ','Ru ','Mi ','Yi ','Yin ','Guang ','An ','Diu ','You ','Se ','Kao ','Qian ','Luan ','Kasugai ', + 'Ai ','Diao ','Han ','Rui ','Shi ','Keng ','Qiu ','Tiu ','Zhe ','Xiu ','Zang ','Ti ','Cuo ','Gua ','Gong ','Zhong ', + 'Dou ','Lu ','Mei ','Lang ','Wan ','Xin ','Yun ','Bei ','Wu ','Su ','Yu ','Chan ','Ting ','Bo ','Han ','Jia ', + 'Hong ','Cuan ','Feng ','Chan ','Wan ','Zhi ','Si ','Xuan ','Wu ','Wu ','Tiao ','Gong ','Zhuo ','Lue ','Xing ','Xam ', + 'Shen ','Han ','Lue ','Xie ','Chu ','Cat ','Cuoc ','Xian ','Tie ','Mang ','Pho ','Li ','Pan ','Nhon ','Cheng ','Gao ', + 'Li ','Te ','Lap ','Zhu ','','Tu ','Liu ','Zui ','Cua ','Chang ','Yuan ','Jian ','Gang ','Diao ','Tao ','Chang ', + ], + 'x93':[ + 'Lun ','Guo ','Ling ','Bei ','Lu ','Li ','Thanh ','Pou ','Juan ','Min ','Zui ','Peng ','An ','Pi ','Xian ','Ya ', + 'Dui ','Lei ','A ','Kong ','Ta ','Kun ','Du ','Wei ','Chui ','Zi ','Tranh ','Ben ','Nie ','Cong ','Dui ','Tan ', + 'Ding ','Qi ','Qian ','Zhuo ','Qi ','Yu ','Gam ','Guan ','Mao ','Chang ','Tian ','Xi ','Lian ','Tao ','Gu ','Cuo ', + 'Shu ','Zhen ','Lu ','Meng ','Lu ','Hua ','Biao ','Ga ','Lai ','Ken ','Kazari ','Bu ','Nai ','Wan ','Zan ','', + 'De ','Xian ','','Huo ','Liang ','','Men ','Kai ','Ying ','Di ','Lian ','Guo ','Xian ','Du ','Tu ','Wei ', + 'Cong ','Fu ','Rou ','Ji ','E ','Rou ','Chen ','Ti ','Zha ','Hong ','Yang ','Duan ','Xia ','Yu ','Keng ','Xing ', + 'Huang ','Wei ','Fu ','Zhao ','Cha ','Qie ','She ','Hong ','Kui ','Tian ','Mou ','Qiao ','Qiao ','Hou ','Thau ','Cong ', + 'Huan ','Ye ','Min ','Jian ','Duan ','Jian ','Si ','Kui ','Hu ','Xuan ','Zhe ','Jie ','Cham ','Bian ','Chung ','Zi ', + 'Xiu ','Ye ','Mei ','Pai ','Ai ','Jie ','','Mei ','Chuo ','Ta ','Bang ','Xia ','Guom ','Suo ','Xi ','Liu ', + 'Zu ','Ye ','Nou ','Weng ','Rong ','Tang ','Suo ','Thuong ','Ge ','Shuo ','Chui ','Bo ','Pan ','Sa ','Bi ','Sang ', + 'Gang ','Zi ','Wu ','Ying ','Huang ','Tiao ','Liu ','Kai ','Sun ','Sha ','Sou ','Wan ','Nhum ','Zhen ','Tran ','Luo ', + 'Yi ','Yuan ','Tang ','Nie ','Xi ','Jia ','Ge ','Ma ','Juan ','Kasugai ','Habaki ','Suo ','','','','Na ', + 'Lu ','Suo ','Ou ','Zu ','Tuan ','Xiu ','Guan ','Xuan ','Lian ','Shou ','Ao ','Man ','Mo ','Luo ','Bi ','Wei ', + 'Liu ','Di ','Qiao ','Cong ','Yi ','Lu ','Ao ','Tret ','Qiang ','Cui ','Qi ','Chang ','Tang ','Man ','Yong ','Chan ', + 'Feng ','Jing ','Tiu ','Shu ','Lou ','Xiu ','Cong ','Long ','Zan ','Jian ','Cao ','Li ','Xia ','Xi ','Kang ','', + 'Beng ','','','Zheng ','Lu ','Hua ','Ji ','Pu ','Hui ','Qiang ','Po ','Lin ','Suo ','Xiu ','San ','Cheng ', + ], + 'x94':[ + 'Kui ','Si ','Liu ','Nao ','Heng ','Pie ','Sui ','Fan ','Qiao ','Quan ','Yang ','Tang ','Xiang ','Jue ','Jiao ','Zun ', + 'Banh ','Jie ','Lao ','Dui ','Tan ','Zan ','Ji ','Jian ','Zhong ','Deng ','Ya ','Ying ','Dui ','Jue ','Nou ','Ti ', + 'Pu ','Tie ','','','Ding ','Shan ','Kai ','Jian ','Fei ','Sui ','Lu ','Juan ','Hui ','Yu ','Lian ','Zhuo ', + 'Khuan ','Qian ','Zhuo ','Lei ','Bi ','Tie ','Huan ','Ye ','Duo ','Guo ','Dang ','Ju ','Fen ','Da ','Bei ','Yi ', + 'Ai ','Zong ','Xun ','Diao ','Zhu ','Heng ','Zhui ','Ji ','Nie ','Ta ','Huo ','Qing ','Bin ','Ying ','Kui ','Ning ', + 'Xu ','Jian ','Jian ','Yari ','Cha ','Zhi ','Mie ','Li ','Lei ','Ji ','Zuan ','Kuang ','Shang ','Peng ','La ','Du ', + 'Thuoc ','Chuo ','Lu ','Biao ','Bao ','Lu ','','Thoa ','Long ','E ','Lu ','Xin ','Jian ','Lan ','Bo ','Jian ', + 'Yao ','Chan ','Xiang ','Jian ','Xi ','Guan ','Cang ','Nie ','Lei ','Cuan ','Qu ','Pan ','La ','Zuan ','Luan ','Zao ', + 'Nie ','Jue ','Tang ','Shu ','Lan ','Jin ','Qiu ','Yi ','Zhen ','Ding ','Zhao ','Po ','Diao ','Tu ','Qian ','Chuan ', + 'Shan ','Ji ','Fan ','Diao ','Men ','Nu ','Xi ','Chai ','Xing ','Gai ','Bu ','Tai ','Ju ','Dun ','Chao ','Zhong ', + 'Na ','Bei ','Gang ','Ban ','Qian ','Yao ','Qin ','Jun ','Wu ','Gou ','Kang ','Fang ','Huo ','Dou ','Niu ','Ba ', + 'Yu ','Qian ','Zheng ','Qian ','Gu ','Bo ','E ','Po ','Bu ','Ba ','Yue ','Zuan ','Mu ','Dan ','Jia ','Dian ', + 'You ','Tie ','Bo ','Ling ','Shuo ','Qian ','Liu ','Bao ','Shi ','Xuan ','She ','Bi ','Ni ','Pi ','Duo ','Xing ', + 'Kao ','Lao ','Er ','Mang ','Ya ','You ','Cheng ','Jia ','Ye ','Nao ','Zhi ','Dang ','Tong ','Lu ','Diao ','Yin ', + 'Kai ','Zha ','Zhu ','Xian ','Ting ','Diu ','Xian ','Hua ','Quan ','Sha ','Jia ','Yao ','Ge ','Ming ','Zheng ','Se ', + 'Jiao ','Yi ','Chan ','Chong ','Tang ','An ','Yin ','Ru ','Zhu ','Lao ','Pu ','Wu ','Lai ','Te ','Lian ','Keng ', + ], + 'x95':[ + 'Xiao ','Suo ','Li ','Zheng ','Chu ','Guo ','Gao ','Tie ','Xiu ','Cuo ','Lue ','Feng ','Xin ','Liu ','Kai ','Jian ', + 'Rui ','Ti ','Lang ','Qian ','Ju ','A ','Qiang ','Duo ','Tian ','Cuo ','Mao ','Ben ','Qi ','De ','Kua ','Kun ', + 'Chang ','Xi ','Gu ','Luo ','Chui ','Zhui ','Jin ','Zhi ','Xian ','Juan ','Huo ','Pou ','Tan ','Ding ','Jian ','Ju ', + 'Meng ','Zi ','Qie ','Ying ','Kai ','Qiang ','Song ','E ','Cha ','Qiao ','Zhong ','Duan ','Sou ','Huang ','Huan ','Ai ', + 'Du ','Mei ','Lou ','Zi ','Fei ','Mei ','Mo ','Zhen ','Bo ','Ge ','Nie ','Tang ','Juan ','Nie ','Na ','Liu ', + 'Hao ','Bang ','Yi ','Jia ','Bin ','Rong ','Biao ','Tang ','Man ','Luo ','Beng ','Yong ','Jing ','Di ','Zu ','Xuan ', + 'Liu ','Tan ','Jue ','Liao ','Pu ','Lu ','Dui ','Lan ','Pu ','Cuan ','Qiang ','Deng ','Huo ','Lei ','Huan ','Zhuo ', + 'Lian ','Yi ','Cha ','Biao ','La ','Chan ','Xiang ','Chang ','Chang ','Jiu ','Ao ','Die ','Qu ','Liao ','Mi ','Chang ', + 'Men ','Ma ','Shuan ','Shan ','Huo ','Men ','Yan ','Bi ','Han ','Bi ','Tsukaeru ','Khai ','Kang ','Beng ','Hong ','Run ', + 'San ','Nhan ','Xian ','Gian ','Min ','Xia ','Yuru ','Dou ','Zha ','Nao ','','Peng ','Xia ','Ling ','Bian ','Bi ', + 'Run ','He ','Guan ','Ge ','Ge ','Fa ','Chu ','Hong ','Gui ','Min ','Hai ','Kun ','Lang ','Lu ','Ting ','Sha ', + 'Ju ','Yue ','Yue ','Chan ','Qu ','Lin ','Chang ','Shai ','Kun ','Yan ','Wen ','Yan ','E ','Hun ','Vac ','Wen ', + 'Xiang ','Bao ','Xiang ','Qu ','Yao ','Wen ','Ban ','An ','Wei ','Yin ','Kuo ','Que ','Lan ','Du ','','Phwung ', + 'Tian ','Nie ','Ta ','Kai ','He ','Que ','Sam ','Guan ','Dou ','Qi ','Kui ','Tang ','Quan ','Piao ','Kan ','Xi ', + 'Hui ','Xen ','Pi ','Dang ','Huan ','Ta ','Wen ','','Men ','Shuan ','Shan ','Yan ','Han ','Bi ','Wen ','Chuang ', + 'Run ','Wei ','Xian ','Hong ','Jian ','Min ','Kang ','Men ','Zha ','Nao ','Gui ','Wen ','Ta ','Min ','Lu ','Kai ', + ], + 'x96':[ + 'Fa ','Ge ','He ','Kun ','Jiu ','Yue ','Lang ','Du ','Yu ','Yan ','Chang ','Xi ','Wen ','Hun ','Yan ','E ', + 'Chan ','Lan ','Qu ','Hui ','Kuo ','Que ','Ge ','Tian ','Ta ','Que ','Kan ','Huan ','Fu ','Fu ','Le ','Dui ', + 'Xin ','Qian ','Wu ','Yi ','Tuo ','Yin ','Yang ','Dou ','E ','Sheng ','Ban ','Pei ','Keng ','Yun ','Ruan ','Zhi ', + 'Pi ','Jing ','Fang ','Yang ','Yin ','Zhen ','Jie ','Cheng ','E ','Qu ','Di ','Zu ','Zuo ','Dian ','Ling ','A ', + 'Tuo ','Tuo ','Bei ','Bing ','Fu ','Ji ','Lu ','Long ','Chen ','Xing ','Duo ','Lou ','Mo ','Jiang ','Shu ','Duo ', + 'Xian ','Er ','Gui ','Yu ','Gai ','Shan ','Xun ','Qiao ','Xing ','Chun ','Fu ','Bi ','Xia ','Shan ','Thang ','Zhi ', + 'Pu ','Dou ','Yuan ','Zhen ','Chu ','Xian ','Tou ','Nie ','Yun ','Xian ','Pei ','Pei ','Zou ','Yi ','Dui ','Lun ', + 'Yin ','Ju ','Chui ','Chen ','Pi ','Lang ','Tao ','Xian ','Luc ','','Xian ','Yin ','Zhu ','Duong ','Reng ','Shan ', + 'Chong ','Yan ','Yin ','Yu ','Di ','Yu ','Long ','Wei ','Wei ','Nie ','Dui ','Sui ','An ','Huang ','Giai ','Sui ', + 'Yin ','Gai ','Yan ','Hui ','Ge ','Yun ','Wu ','Wei ','Ai ','Xi ','Tang ','Ji ','Chuong ','Dao ','Ao ','Xi ', + 'Yin ','','Rao ','Lin ','Tui ','Deng ','Pi ','Sui ','Sui ','Yu ','Xian ','Fen ','Ni ','Er ','Ji ','Dao ', + 'Thap ','Yin ','E ','Hui ','Luong ','Xi ','Li ','Li ','Li ','Zhui ','He ','Zhi ','Zhun ','Jun ','Nan ','Yi ', + 'Tuoc ','Yan ','Qin ','Ya ','Hung ','Ya ','Ji ','Gu ','Huan ','Zhi ','Gou ','Tuan ','Thu ','Yong ','Ju ','Chu ', + 'Hu ','Za ','Luo ','Yu ','Chou ','Diao ','Tuy ','Han ','Huo ','Song ','Guan ','Chu ','Za ','Yong ','Ji ','Xi ', + 'Chou ','Liu ','Li ','Nan ','Xue ','Za ','Ji ','Ji ','Yu ','Yu ','Xue ','Na ','Fou ','Se ','Mu ','Wen ', + 'Fen ','Pang ','Van ','Li ','Li ','Ang ','Ling ','Lei ','An ','Bao ','Meng ','Dian ','Dang ','Xing ','Wu ','Zhao ', + ], + 'x97':[ + 'Xu ','Ji ','Mu ','Chen ','Xiao ','Zha ','Ting ','Zhen ','Pei ','Mei ','Ling ','Qi ','Chou ','Hoac ','Sha ','Phay ', + 'Weng ','Zhan ','Yin ','Nghi ','Zhu ','Tun ','Lam ','','Dong ','Ying ','Wu ','Ling ','Suong ','Ling ','Xia ','Hong ', + 'Yin ','Mo ','Mai ','Yun ','Liu ','Meng ','Bin ','Vu ','Wei ','Huo ','Yin ','Xi ','Yi ','Ai ','Dan ','Deng ', + 'Xian ','Yu ','Lo ','Long ','Dai ','Ji ','Pang ','Yang ','Ba ','Pi ','Wei ','','Xi ','Ji ','Mai ','Meng ', + 'Mong ','Lei ','Li ','Huo ','Ai ','Fei ','Dai ','Long ','Linh ','Ai ','Feng ','Li ','Bao ','','He ','He ', + 'Bing ','Qing ','Thanh ','Jing ','Tian ','Zhen ','Jing ','Cheng ','Qing ','Jing ','Jing ','Dian ','Jing ','Tian ','Phi ','Fei ', + 'Kao ','Mi ','Mian ','Mian ','Pao ','Ye ','Tian ','Hui ','Ye ','Ge ','Ding ','Cha ','Jian ','Ren ','Di ','Du ', + 'Wu ','Ren ','Qin ','Jin ','Xue ','Niu ','Ba ','Yin ','Sa ','Na ','Mo ','Zu ','Da ','Ban ','Yi ','Yao ', + 'Tao ','Tuo ','Jia ','Hong ','Pao ','Yang ','Tomo ','Yin ','Jia ','Tao ','Ji ','Hai ','An ','An ','Hen ','Gong ', + 'Kohaze ','Da ','Qiao ','Ting ','Wan ','Ying ','Sui ','Tiao ','Qiao ','Xuan ','Kong ','Beng ','Ta ','Zhang ','Bing ','Kuo ', + 'Cuc ','La ','Xie ','Rou ','Bang ','Yi ','Qiu ','Qiu ','He ','Xiao ','Mu ','Ju ','Jian ','Bian ','Di ','Jian ', + 'On ','Tao ','Gou ','Ta ','Bei ','Xie ','Pan ','Ge ','Bi ','Kuo ','Tou ','Lou ','Gui ','Qiao ','Xue ','Ji ', + 'Jian ','Cuong ','Chan ','Da ','Huo ','Xian ','Qian ','Du ','Wa ','Jian ','Lan ','Wei ','Ren ','Fu ','Mei ','Juan ', + 'Ge ','Wei ','Qiao ','Han ','Chang ','','Rou ','Xun ','She ','Wei ','Ge ','Bei ','Tao ','Gou ','Yun ','', + 'Bi ','Wei ','Hui ','Du ','Wa ','Du ','Wei ','Ren ','Fu ','Han ','Wei ','Yun ','Tao ','Jiu ','Jiu ','Xian ', + 'Xie ','Xian ','Ji ','Yin ','Za ','Yun ','Shao ','Le ','Peng ','Heng ','Ying ','Yun ','Peng ','Yin ','Yin ','Huong ', + ], + 'x98':[ + 'Hu ','Ye ','Ding ','Qing ','Kui ','Xiang ','Shun ','Han ','Tua ','Yi ','Xu ','Gu ','Tung ','Kui ','Qi ','Hang ', + 'Yu ','Ngoan ','Ban ','Dun ','Di ','Dan ','Pan ','Po ','Ling ','Ce ','Jing ','Lei ','He ','Qiao ','E ','E ', + 'Wei ','Jie ','Gua ','Shen ','Yi ','Shen ','Hai ','Dui ','Pian ','Ping ','Lei ','Fu ','Jia ','Tou ','Hui ','Kui ', + 'Jia ','Le ','Ting ','Cheng ','Ying ','Jun ','Hu ','Han ','Jing ','Tui ','Tui ','Pin ','Lai ','Tui ','Zi ','Zi ', + 'Chui ','Ding ','Lai ','Yan ','Han ','Jian ','Ke ','Cui ','Jiong ','Qin ','Yi ','Sai ','Ti ','E ','E ','Yan ', + 'Hun ','Kan ','Dong ','Zhuan ','Nhan ','Xian ','Xin ','Yi ','Yuan ','Sang ','Dian ','Dian ','Jiang ','Ku ','Lei ','Liao ', + 'Piao ','Yi ','Man ','Qi ','Rao ','Hao ','Qiao ','Co ','Xun ','Qian ','Hui ','Zhan ','Ru ','Hong ','Bin ','Xian ', + 'Pin ','Lu ','Lan ','Nie ','Quan ','Ye ','Ding ','Qing ','Han ','Xiang ','Shun ','Xu ','Xu ','Wan ','Gu ','Dun ', + 'Qi ','Ban ','Song ','Hang ','Yu ','Lu ','Ling ','Po ','Jing ','Jie ','Jia ','Tian ','Han ','Ying ','Jiong ','Hai ', + 'Yi ','Pin ','Hui ','Tui ','Han ','Ying ','Ying ','Ke ','Ti ','Yong ','E ','Zhuan ','Yan ','E ','Nie ','Man ', + 'Dian ','Sang ','Hao ','Lei ','Zhan ','Ru ','Pin ','Quan ','Phong ','Biao ','Oroshi ','Fu ','Xia ','Zhan ','Biao ','Sa ', + 'Ba ','Tai ','Lie ','Gua ','Xuan ','Shao ','Ju ','Bi ','Si ','Wei ','Yang ','Yao ','Sou ','Kai ','Sao ','Fan ', + 'Liu ','Xi ','Liao ','Piao ','Piao ','Liu ','Biao ','Biao ','Biao ','Liao ','','Se ','Feng ','Biao ','Feng ','Yang ', + 'Zhan ','Biao ','Sa ','Ju ','Si ','Sou ','Yao ','Liu ','Piao ','Biao ','Biao ','Phi ','Fan ','Fei ','Fei ','Shi ', + 'Shi ','Can ','Co ','Ding ','Si ','Tuo ','Zhan ','Sun ','Xiang ','Tun ','Ren ','Yu ','Juan ','Chi ','Yin ','Fan ', + 'Fan ','Sun ','Yin ','Zhu ','Yi ','Zhai ','Bi ','Jie ','Tao ','Liu ','Ci ','Tie ','Si ','Bao ','Shi ','Duo ', + ], + 'x99':[ + 'Hai ','Ren ','Tian ','Jiao ','Jia ','Bing ','Yao ','Tong ','Ci ','Xiang ','Yang ','Yang ','Er ','Yan ','Le ','Yi ', + 'Can ','Bo ','Nei ','E ','Bu ','Jun ','Dou ','Su ','Du ','Shi ','Yao ','Hun ','Guo ','Shi ','Jian ','Zhui ', + 'Bing ','Xian ','Bu ','Ye ','Tan ','Fei ','Zhang ','Wei ','Guan ','E ','Nuan ','Hun ','Hu ','Huang ','Tie ','Hui ', + 'Jian ','Hou ','He ','Xing ','Fen ','Wei ','Gu ','Cha ','Song ','Tang ','Bo ','Gao ','Xi ','Kui ','Liu ','Sou ', + 'Tao ','Ye ','Yun ','Mo ','Tang ','Man ','Bi ','Yu ','Xiu ','Jin ','San ','Kui ','Zhuan ','Shan ','Chi ','Dan ', + 'Yi ','Co ','Rao ','Cheng ','Yong ','Tao ','Hui ','Xiang ','Zhan ','Fen ','Hai ','Meng ','Yan ','Mo ','Chan ','Xiang ', + 'Luo ','Zuan ','Nang ','Shi ','Ding ','Ji ','Tuo ','Xing ','Tun ','Xi ','Ren ','Yu ','Chi ','Fan ','Yin ','Jian ', + 'Shi ','Bao ','Si ','Duo ','Yi ','Er ','Rao ','Xiang ','Jia ','Le ','Jiao ','Yi ','Bing ','Bo ','Dou ','E ', + 'Yu ','Nei ','Jun ','Guo ','Hun ','Xian ','Guan ','Cha ','Kui ','Gu ','Sou ','Chan ','Ye ','Mo ','Bo ','Liu ', + 'Xiu ','Jin ','Man ','San ','Zhuan ','Nang ','Shou ','Kui ','Guo ','Huong ','Fen ','Ba ','Ni ','Bi ','Bo ','Tu ', + 'Han ','Fei ','Jian ','An ','Ai ','Fu ','Xian ','Wen ','Hanh ','Fen ','Bin ','Xing ','Ma ','Yu ','Feng ','Han ', + 'Di ','Tuo ','Tuo ','Chi ','Xun ','Zhu ','Zhi ','Pei ','Xin ','Ri ','Sa ','Yin ','Wen ','Zhi ','Dan ','Lu ', + 'You ','Bo ','Bao ','Kuai ','Tuo ','Yi ','Qu ','','Qu ','Jiong ','Bo ','Zhao ','Yuan ','Peng ','Zhou ','Ju ', + 'Tru ','Nu ','Cau ','Pi ','Zang ','Jia ','Ling ','Zhen ','Tai ','Fu ','Yang ','Shi ','Bi ','Tuo ','Tuo ','Si ', + 'Liu ','Ma ','Pian ','Tao ','Zhi ','Rong ','Teng ','Dong ','Xun ','Quan ','Shen ','Jiong ','Er ','Hai ','Bo ','', + 'Yin ','Luo ','Shuu ','Dan ','Xie ','Liu ','Ju ','Song ','Xam ','Mang ','Liang ','Han ','Tu ','Xuan ','Tui ','Tuan ', + ], + 'x9a':[ + 'E ','Cheng ','Xing ','Ai ','Lu ','Choai ','Zhou ','She ','Pian ','Kun ','Tao ','Lai ','Zong ','Ke ','Qi ','Qi ', + 'Yan ','Fei ','Sao ','Yan ','Jie ','Yao ','Wu ','Pian ','Cong ','Pian ','Qian ','Fei ','Huang ','Jian ','Huo ','Yu ', + 'Ti ','Quan ','Xia ','Zong ','Kui ','Rou ','Si ','Gua ','Tuo ','Kui ','Sou ','Qian ','Cheng ','Zhi ','Liu ','Pang ', + 'Teng ','Xi ','Cao ','Du ','Yan ','Yuan ','Zou ','Tao ','Shan ','Li ','Zhi ','Shuang ','Lu ','Xi ','Luo ','Zhang ', + 'Mo ','Ao ','Can ','Piao ','Cong ','Xui ','Bi ','Zhi ','Yu ','Xu ','Hua ','Bo ','Su ','Xiao ','Lin ','Chan ', + 'Dun ','Liu ','Tuo ','Zeng ','Tan ','Jiao ','Tie ','Yan ','Luo ','Zhan ','Kinh ','Yi ','Ye ','Tuo ','Bin ','Zou ', + 'Yan ','Peng ','Lu ','Teng ','Xiang ','Ji ','Shuang ','Ju ','Xi ','Huan ','Li ','Biao ','Ma ','Yu ','Tuo ','Xun ', + 'Chi ','Qu ','Ri ','Bo ','Lu ','Zang ','Shi ','Si ','Fu ','Ju ','Zou ','Zhu ','Tuo ','Nu ','Jia ','Yi ', + 'Tai ','Xiao ','Ma ','Yin ','Jiao ','Hua ','Luo ','Hai ','Pian ','Biao ','Li ','Cheng ','Yan ','Xin ','Qin ','Jun ', + 'Qi ','Qi ','Ke ','Zhui ','Zong ','Su ','Can ','Pian ','Zhi ','Kui ','Sao ','Wu ','Ao ','Liu ','Qian ','Shan ', + 'Piao ','Luo ','Cong ','Chan ','Zou ','Ji ','Shuang ','Xiang ','Cot ','Wei ','Wei ','Wei ','Yu ','Gan ','Yi ','Ang ', + 'Tou ','Xie ','Bao ','Bi ','Chi ','Ti ','Di ','Ku ','Hai ','Qiao ','Gou ','Kua ','Ge ','Tui ','Geng ','Pian ', + 'Bi ','Ke ','Ka ','Yu ','Sui ','Vay ','Bo ','Xiao ','Pang ','Bo ','Ci ','Kuan ','Bin ','Mo ','Liao ','Lou ', + 'Nao ','Du ','Zang ','Sui ','Ti ','Bin ','Kuan ','Lu ','Cao ','Gao ','Qiao ','Kao ','Qiao ','Lao ','Zao ','Biao ', + 'Kun ','Kun ','Ti ','Fang ','Xiu ','Ran ','Mao ','Dan ','Kun ','Bin ','Fa ','Tiao ','Pi ','Zi ','Fa ','Ran ', + 'Ti ','Pao ','Pi ','Mao ','Fu ','Er ','Rong ','Qu ','','Xiu ','Gua ','Ji ','Peng ','Zhua ','Shao ','Sha ', + ], + 'x9b':[ + 'Ti ','Li ','Ban ','Zong ','Ti ','Peng ','Song ','Zheng ','Quan ','Zong ','Shun ','Jian ','Duo ','Hu ','La ','Jiu ', + 'Qi ','Lian ','Zhen ','Bin ','Peng ','Mo ','San ','Man ','Man ','Seng ','Tu ','Lie ','Qian ','Qian ','Nong ','Huan ', + 'Kuai ','Ning ','Bin ','Lie ','Rang ','Dou ','Dou ','Nao ','Hong ','Xi ','Dou ','Han ','Dou ','Dou ','Jiu ','Chang ', + 'Yu ','Yu ','Li ','Juan ','Fu ','Qian ','Gui ','Zong ','Liu ','Gui ','Shang ','Yu ','Gui ','Mei ','Ji ','Qi ', + 'Jie ','Kui ','Hun ','Ba ','Po ','Mei ','Xu ','Yan ','Xiao ','Liang ','Yu ','Tui ','Qi ','Wang ','Liang ','Wei ', + 'Jian ','Chi ','Piao ','Bi ','Ma ','Ji ','Xu ','Chou ','Yan ','Zhan ','Ngu ','Dao ','Ren ','Ji ','Eri ','Gong ', + 'Tuo ','Diao ','Ji ','Xu ','E ','E ','Sha ','Hang ','Tun ','Mo ','Jie ','Shen ','Fan ','Yuan ','Bi ','Lu ', + 'Wen ','Hu ','Lu ','Za ','Fang ','Fen ','Na ','You ','Namazu ','Todo ','He ','Xia ','Qu ','Han ','Pi ','Ling ', + 'Tuo ','Bo ','Qiu ','Ping ','Fu ','Bi ','Ji ','Wei ','Ju ','Diao ','Bo ','You ','Gun ','Pi ','Nian ','Xing ', + 'Tai ','Bao ','Fu ','Zha ','Ju ','Gu ','Kajika ','Konoshiro ','','Ta ','Jie ','Shu ','Hou ','Xiang ','Er ','An ', + 'Wei ','Tiao ','Zhu ','Yin ','Lie ','Luo ','Tong ','Yi ','Qi ','Bing ','Wei ','Jiao ','Bu ','Gui ','Xian ','Ge ', + 'Hui ','Bora ','Mate ','Kao ','Gori ','Duo ','Jun ','Ti ','Mian ','Xiao ','Za ','Sha ','Qin ','Yu ','Nei ','Zhe ', + 'Gun ','Geng ','','Wu ','Qiu ','Ting ','Fu ','Wan ','Tiao ','Li ','Sha ','Sha ','Gao ','Meng ','Ugui ','Asari ', + 'Subashiri ','Kazunoko ','Yong ','Ni ','Zi ','Qi ','Qing ','Xiang ','Nei ','Chun ','Ji ','Diao ','Qie ','Gu ','Zhou ','Dong ', + 'Lai ','Fei ','Ni ','Yi ','Kun ','Lu ','Jiu ','Chang ','Jing ','Lun ','Ling ','Zou ','Li ','Meng ','Zong ','Zhi ', + 'Nian ','Shachi ','Dojou ','Sukesou ','Shi ','Shen ','Hun ','Shi ','Hou ','Xing ','Zhu ','La ','Zong ','Ji ','Bian ','Bian ', + ], + 'x9c':[ + 'Huan ','Quan ','Ze ','Wei ','Wei ','Yu ','Qun ','Rou ','Die ','Huang ','Lian ','Yan ','Qiu ','Qiu ','Jian ','Bi ', + 'E ','Yang ','Fu ','Sai ','Jian ','Xia ','Tuo ','Hu ','Muroaji ','Ruo ','Haraka ','Wen ','Jian ','Hao ','Wu ','Fang ', + 'Sao ','Liu ','Ma ','Shi ','Shi ','Guan ','Shi ','Teng ','Ta ','Yao ','Ge ','Rong ','Qian ','Qi ','Wen ','Ruo ', + 'Hatahata ','Lian ','Ao ','Le ','Hui ','Min ','Ji ','Tiao ','Qu ','Jian ','Sao ','Man ','Xi ','Qiu ','Biao ','Ji ', + 'Ji ','Zhu ','Jiang ','Qiu ','Zhuan ','Yong ','Zhang ','Kang ','Xue ','Bie ','Jue ','Qu ','Xiang ','Bo ','Jiao ','Xun ', + 'Su ','Huang ','Zun ','Shan ','Shan ','Fan ','Gui ','Lin ','Xun ','Ngheo ','Xi ','Eso ','Kyou ','Fen ','Guan ','Hou ', + 'Kuai ','Zei ','Sao ','Zhan ','Gan ','Gui ','Sheng ','Li ','Chang ','Hatahata ','Shiira ','Ai ','Ru ','Ji ','Xu ','Huo ', + 'Shiira ','Li ','Lie ','Li ','Mie ','Zhen ','Xiang ','E ','Lu ','Guan ','Li ','Xian ','Yu ','Dao ','Ji ','You ', + 'Tun ','Lu ','Fang ','Ba ','He ','Bo ','Ping ','Nian ','Lu ','You ','Zha ','Fu ','Bo ','Bao ','Hou ','Pi ', + 'Tai ','Gui ','Jie ','Kao ','Wei ','Er ','Tong ','Ze ','Hou ','Kuai ','Ji ','Jiao ','Xian ','Za ','Xiang ','Xun ', + 'Geng ','Li ','Lian ','Jian ','Li ','Shi ','Tiao ','Gun ','Sha ','Wan ','Jun ','Ji ','Yong ','Qing ','Ling ','Qi ', + 'Zou ','Fei ','Kun ','Chang ','Gu ','Ni ','Nian ','Diao ','Jing ','Shen ','Shi ','Zi ','Fen ','Die ','Bi ','Chang ', + 'Shi ','Wen ','Wei ','Sai ','E ','Qiu ','Fu ','Huang ','Quan ','Jiang ','Bian ','Sao ','Ao ','Qi ','Ta ','Yin ', + 'Yao ','Fang ','Jian ','Le ','Biao ','Xue ','Bie ','Man ','Min ','Yong ','Wei ','Xi ','Jue ','Shan ','Lin ','Zun ', + 'Huo ','Gan ','Li ','Zhan ','Guan ','Niao ','Yi ','Fu ','Li ','Cuu ','Bu ','Yan ','Fu ','Diao ','Ji ','Feng ', + 'Nio ','Gan ','Shi ','Feng ','Ming ','Bao ','Yuan ','Zhi ','Hu ','Qin ','Fu ','Fen ','Wen ','Jian ','Shi ','Yu ', + ], + 'x9d':[ + 'Fou ','Yao ','Jue ','Jue ','Pi ','Huan ','Zhen ','Bao ','Yan ','Ya ','Zheng ','Fang ','Feng ','Wen ','Ou ','Te ', + 'Jia ','Nu ','Ling ','Mie ','Fu ','Tuo ','Wen ','Li ','Bian ','Zhi ','Ge ','Yuan ','Zi ','Cu ','Xiao ','Chi ', + 'Dan ','Ju ','You ','Gu ','Zhong ','Yu ','Yang ','Rong ','Ya ','Tie ','Yu ','Shigi ','Ying ','Zhui ','Wu ','Er ', + 'Gua ','Ai ','Zhi ','Yan ','Heng ','Jiao ','Ji ','Lie ','Zhu ','Ren ','Yi ','Hong ','Luo ','Ru ','Mou ','Ge ', + 'Ren ','Jiao ','Xiu ','Zhou ','Zhi ','Luo ','Chidori ','Toki ','Ten ','Luan ','Jia ','Ji ','Yu ','Huan ','Tuo ','Bu ', + 'Wu ','Juan ','Coc ','Bo ','Xun ','Xun ','Bi ','Xi ','Jun ','Ju ','Tu ','Jing ','Ti ','Nga ','E ','Kuang ', + 'Hu ','Wu ','Shen ','Lai ','Ikaruga ','Kakesu ','Lu ','Ping ','Shu ','Fu ','An ','Zhao ','Peng ','Qin ','Qian ','Bei ', + 'Diao ','Lu ','Thuoc ','Jian ','Cuoc ','Tu ','Ya ','Yuan ','Qi ','Li ','Ye ','Zhui ','Kong ','Zhui ','Kun ','Sheng ', + 'Qi ','Jing ','Yi ','Yi ','Jing ','Zi ','Lai ','Dong ','Qi ','Chun ','Geng ','Ju ','Qu ','Isuka ','Kikuitadaki ','Ji ', + 'Shu ','','Chi ','Miao ','Rou ','An ','Qiu ','Ti ','Hu ','Ti ','E ','Jie ','Mao ','Fu ','Chun ','Tu ', + 'Yan ','He ','Yuan ','Pian ','Yun ','Mei ','Hu ','Ying ','Dun ','Wu ','Ju ','Tsugumi ','Cang ','Fang ','Gu ','Oanh ', + 'Yuan ','Xuan ','Weng ','Shi ','He ','Chu ','Tang ','Xia ','Ruo ','Liu ','Ji ','Gu ','Jian ','Zhun ','Han ','Zi ', + 'Zi ','Ni ','Yao ','Yan ','Ji ','Li ','Tian ','Kou ','Ti ','Ti ','Ni ','Cha ','Ma ','Jiao ','Gao ','Tian ', + 'Chen ','Li ','Zhuan ','Zhe ','Ao ','Yao ','Yi ','Ou ','Chi ','Zhi ','Liao ','Rong ','Lou ','Bi ','Shuang ','Zhuo ', + 'Yu ','Wu ','Jue ','Yin ','Quan ','Si ','Jiao ','Yi ','Hua ','Bi ','Ying ','Su ','Huang ','Fan ','Keo ','Liao ', + 'Yan ','Kao ','Jiu ','Xian ','Xian ','Tu ','Mai ','Zun ','Yu ','Ying ','Lu ','Tuan ','Xian ','Xue ','Yi ','Pi ', + ], + 'x9e':[ + 'Shu ','Luo ','Qi ','Yi ','Ji ','Zhe ','Yu ','Zhan ','Ye ','Yang ','Pi ','Ning ','Huo ','Mi ','Ying ','Meng ', + 'Di ','Yue ','Yu ','Lei ','Bao ','Lu ','He ','Long ','Shuang ','Yue ','Ying ','Guan ','Qu ','Li ','Loan ','Niao ', + 'Jiu ','Ji ','Yuan ','Ming ','Shi ','Ou ','Ya ','Cang ','Bao ','Zhen ','Gu ','Dong ','Lu ','Ya ','Xiao ','Yang ', + 'Ling ','Zhi ','Qu ','Yuan ','Xue ','Tuo ','Si ','Zhi ','Er ','Gua ','Xiu ','Heng ','Zhou ','Ge ','Luan ','Hong ', + 'Wu ','Bo ','Li ','Juan ','Hu ','E ','Yu ','Xian ','Ti ','Wu ','Que ','Miao ','An ','Kun ','Bei ','Peng ', + 'Qian ','Chun ','Geng ','Yuan ','Su ','Hu ','He ','E ','Gu ','Qiu ','Zi ','Mei ','Mu ','Ni ','Yao ','Weng ', + 'Liu ','Ji ','Ni ','Jian ','He ','Yi ','Ying ','Zhe ','Liao ','Liao ','Jiao ','Jiu ','Yu ','Lu ','Xuan ','Zhan ', + 'Ying ','Huo ','Meng ','Guan ','Shuang ','Lu ','Jin ','Ling ','Jian ','Xian ','Cuo ','Jian ','Jian ','Yan ','Cuo ','Loc ', + 'You ','Cu ','Ji ','Biao ','Cu ','Biao ','Zhu ','Jun ','Zhu ','Jian ','Mi ','Mi ','Wu ','Liu ','Chen ','Jun ', + 'Lin ','Ni ','Qi ','Lu ','Jiu ','Jun ','Jing ','Li ','Xiang ','Yan ','Jia ','Mi ','Li ','She ','Zhang ','Lan ', + 'Jing ','Ji ','Ling ','Yan ','Cu ','Mai ','Mai ','Ge ','Chao ','Fu ','Mian ','Mian ','Fu ','Pao ','Qu ','Qu ', + 'Mou ','Fu ','Xian ','Lai ','Qu ','Mian ','','Feng ','Fu ','Qu ','Mian ','Ma ','Me ','Mo ','Hui ','Ro ', + 'Zou ','Nen ','Fen ','Huang ','Hoang ','Jin ','Guang ','Tian ','Tou ','Heng ','Xi ','Kuang ','Heng ','Shu ','Li ','Nian ', + 'Chi ','Hac ','Hei ','Yi ','Qian ','Dan ','Xi ','Tuan ','Mo ','Mo ','Qian ','Dai ','Chu ','You ','Dian ','Yi ', + 'Xia ','Yan ','Qu ','Mei ','Yan ','Qing ','Yu ','Li ','Dang ','Du ','Can ','Yin ','An ','Yan ','Tan ','An ', + 'Zhen ','Dai ','Can ','Yi ','Mei ','Dan ','Yan ','Du ','Lu ','Zhi ','Fen ','Fu ','Fu ','Min ','Min ','Yuan ', + ], + 'x9f':[ + 'Cu ','Qu ','Chao ','Wa ','Zhu ','Zhi ','Mang ','Ao ','Bie ','Tuo ','Bi ','Yuan ','Chao ','Tuo ','Ding ','Mi ', + 'Nai ','Ding ','Zi ','Gu ','Gu ','Dong ','Fen ','Tao ','Yuan ','Pi ','Chang ','Gao ','Qi ','Yuan ','Tang ','Teng ', + 'Shu ','Shu ','Fen ','Fei ','Wen ','Ba ','Diao ','Tuo ','Tong ','Qu ','Sheng ','Shi ','You ','Shi ','Ting ','Wu ', + 'Nian ','Jing ','Hun ','Ju ','Yan ','Tu ','Ti ','Xi ','Xian ','Yan ','Lei ','Bi ','Yao ','Qiu ','Han ','Wu ', + 'Wu ','Hou ','Xi ','Ge ','Zha ','Xiu ','Weng ','Zha ','Nong ','Nang ','Tay ','Zhai ','Ji ','Zi ','Ji ','Ji ', + 'Qi ','Ji ','Chi ','Chen ','Chen ','He ','Ya ','Ken ','Xie ','Pao ','Cuo ','Shi ','Zi ','Chi ','Nian ','Ju ', + 'Tiao ','Ling ','Ling ','Chu ','Quan ','Xie ','Ken ','Nie ','Jiu ','Yao ','Chuo ','Kun ','Yu ','Chu ','Yi ','Ni ', + 'Cuo ','Zou ','Qu ','Nen ','Xian ','Ou ','E ','Wo ','Yi ','Chuo ','Zou ','Dian ','Chu ','Jin ','Ya ','Chi ', + 'Chen ','He ','Ken ','Ju ','Ling ','Pao ','Tiao ','Zi ','Ken ','Yu ','Chuo ','Qu ','Wo ','Long ','Pang ','Gong ', + 'Pang ','Yan ','Long ','Long ','Gong ','Kan ','Ta ','Ling ','Ta ','Long ','Gong ','Kan ','Gui ','Qiu ','Bie ','Gui ', + 'Yue ','Chui ','He ','Jue ','Xie ','Yu ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Shan ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'xf9':[ + 'Kay ','Kayng ','Ke ','Ko ','Kol ','Koc ','Kwi ','Kwi ','Kyun ','Kul ','Kum ','Na ','Na ','Na ','La ','Na ', + 'Na ','Na ','Na ','Na ','Nak ','Nak ','Nak ','Nak ','Nak ','Nak ','Nak ','Nan ','Nan ','Nan ','Nan ','Nan ', + 'Nan ','Nam ','Nam ','Nam ','Nam ','Nap ','Nap ','Nap ','Long ','Nang ','Nang ','Nang ','Nang ','Nay ','Nayng ','No ', + 'No ','No ','No ','No ','No ','No ','Lou ','No ','No ','No ','No ','Nok ','Nok ','Nok ','Nok ','Nok ', + 'Nok ','Non ','Nong ','Nong ','Nong ','Nong ','Noy ','Noy ','Noy ','Noy ','Nwu ','Nwu ','Nwu ','Nwu ','Nwu ','Nwu ', + 'Nwu ','Nwu ','Nuk ','Nuk ','Num ','Nung ','Nung ','Nung ','Nung ','Nung ','Twu ','La ','Lak ','Lak ','Lan ','Lyeng ', + 'Lo ','Lyul ','Li ','Pey ','Pen ','Pyen ','Pwu ','Pwul ','Pi ','Sak ','Sak ','Sam ','Sayk ','Sayng ','Sep ','Sey ', + 'Sway ','Sin ','Sim ','Sip ','Ya ','Yak ','Yak ','Yang ','Yang ','Yang ','Yang ','Yang ','Yang ','Yang ','Yang ','Ye ', + 'Ye ','Ye ','Ye ','Ye ','Ye ','Ye ','Ye ','Ye ','Ye ','Ye ','Yek ','Yek ','Yek ','Yek ','Yen ','Yen ', + 'Yen ','Yen ','Yen ','Yen ','Yen ','Yen ','Yen ','Yen ','Yen ','Yen ','Yen ','Yen ','Yel ','Yel ','Yel ','Yel ', + 'Yel ','Yel ','Yem ','Yem ','Yem ','Yem ','Yem ','Yep ','Yeng ','Yeng ','Yeng ','Yeng ','Yeng ','Yeng ','Yeng ','Yeng ', + 'Yeng ','Yeng ','Yeng ','Yeng ','Yeng ','Yey ','Yey ','Yey ','Yey ','O ','Yo ','Yo ','Yo ','Yo ','Yo ','Yo ', + 'Yo ','Yo ','Yo ','Yo ','Yong ','Wun ','Wen ','Yu ','Yu ','Yu ','Yu ','Yu ','Yu ','Yu ','Yu ','Yu ', + 'Yu ','Yuk ','Yuk ','Yuk ','Yun ','Yun ','Yun ','Yun ','Yul ','Yul ','Yul ','Yul ','Yung ','I ','I ','I ', + 'I ','I ','I ','I ','I ','I ','I ','I ','I ','I ','I ','Ik ','Ik ','In ','In ','In ', + 'In ','In ','In ','In ','Im ','Im ','Im ','Ip ','Ip ','Ip ','Cang ','Cek ','Ci ','Cip ','Cha ','Chek ', + ], + 'xfa':[ + 'Chey ','Thak ','Thak ','Thang ','Thayk ','Thong ','Pho ','Phok ','Hang ','Hang ','Hyen ','Hwak ','Wu ','Huo ','','Coc ', + 'Zhong ','','Qing ','','','Xi ','Zhu ','Yi ','Li ','Shen ','Xiang ','Fu ','Jing ','Jing ','Yu ','', + 'Hagi ','','Zhu ','','','Yi ','Du ','','','','Fan ','Si ','Guan ','He ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x200':[ + 'Ha ','Qi ','','','','Hai ','','','','Qiu ','','','','Shi ','','', + '','','','','jue ','','','','','','','yu ','','','','', + '','','','','','','','Ba ','Cup ','','Kha ','','','','','', + '','','','','Trut ','','','','','','','','','lu ','','', + '','','','','','','','','','','','','','','','', + '','Duoi ','','','','','','','','','Cui ','','','','','', + '','','','','','Ga ','','','','','Nham ','','','','','', + '','','','','','','','','Suot ','','','','','','','', + '','','','','','','','','jie ','','','','','','','', + '','','','','Zi ','','','','','','','','','Zung ','','', + '','','Pai ','','Dui ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','jiu ','','','','','', + ], + 'x201':[ + 'Vu ','','','','','','','','','','','','','jie ','','', + '','jue ','','','','','','','','','','','','','','', + '','','','','','','Gop ','Vai ','','Hai ','','','','','','', + '','','','Kep ','','','Nham ','','','','','Lam ','Nam ','Vai ','','wei ', + '','','jie ','','','','','','','','','','','Mat ','Mat ','', + 'Mat ','','Mat ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','zhang ','','','Mat ','','','', + '','','','','','','','','','','','','Yong ','','','', + 'xu ','','','','','','','','','','','','','','','', + '','','','','','','','','','Faan ','','','','','','', + '','','','Trum ','','','dan ','','','','','','','','','', + '','','','','','','','','','','','','','Voi ','','', + '','','','','','Va ','','','chu ','','','','','','','', + '','','','','','','','','','','','','','','','qu ', + '','','','','','','','','','','','','Hua ','Top ','','', + ], + 'x202':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','yun ','','','','','','','','','','','', + 'dan ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Nay ','', + 'Tray ','','','','','','','ju ','','du ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','jian ','','','','','','','','Ngai ','','Nho ','Thay ','','', + '','','','','','','','Bing ','','zhuan ','shu ','','jue ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','lian ','','','','','','','','she ','', + '','','','','','May ','Mu ','','','fu ','','','ju ','','','', + '','','','','','','','','','','Tao ','','','','','', + ], + 'x203':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Wu ','','','','','','','','shuai ','','', + 'gai ','','','','zhuang ','','','','','','','','','fu ','','', + '','Man ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','But ','','','','','yao ','','','','Gap ','','bie ', + '','','qu ','','','yang ','','','','','','','','sha ','','', + '','','','','','','','','','','Xum ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Cap ','Bay ','','','','','jue ','', + '','','','yu ','','','','sa ','','','','dun ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','xiao ','','','','','yu ','qu ','','','','', + '','','','','','Ngai ','','','','','','','','Tui ','','', + '','','','Giong ','','','','','','','','','','','','', + ], + 'x204':[ + '','meng ','','','','','','','','jie ','shu ','','','su ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','meng ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Trom ','','','Long ','','','','', + '','','','','','Ngua ','','','','','nei ','nei ','','','zhai ','', + '','','','','','','','','','','','','Nhau ','','','cu ', + '','','','','','','','','','','','','','','','', + '','','','','wu ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Rang ','','','','','','','','','','', + '','','','','','lian ','','Tin ','','','','','','','fan ','', + 'Truoc ','','','','','','','','','','','','','','','', + 'Quanh ','','','','Mong ','','','fu ','','','','','','','','', + '','','','','','','','','Vao ','Nhui ','','','','','','', + '','','','','','','','','','Lon ','','Tron ','Sip ','','','', + ], + 'x205':[ + '','','','Xi ','','','','','','Juan ','','','','','','', + '','hai ','','','','lun ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','heng ','','','','','','','','','Zheng ','','','','', + '','','','','Nap ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'cheng ','','','qia ','','','yu ','','','','','','','zhao ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Xuong ','','','','','','','', + '','','','','','','','','Nap ','','','','','','','', + '','','','','Bay ','Chong ','','','','','','','','','','Ngat ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','qiu ','xie ','','','','','','', + '','','','','','','','','','','','die ','','','','', + '','','','Lun ','','','Ping ','','die ','','','','','','','', + 'Tron ','','','','','','','','','Ret ','','','','liu ','','', + ], + 'x206':[ + '','bu ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','lai ','','', + '','','he ','jiao ','','','','','','','','','','','','', + '','','','','','','','','','','','wu ','','','','', + '','','','','','','ju ','','','','','','','','','', + '','','','','jiu ','wei ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','xian ','','','','chang ','','','','','', + 'Moc ','','','','he ','','','','','','','','','','','', + '','','Ra ','','','','','','','','','','','','','Got ', + '','zhe ','','','','ju ','','','','Shan ','Sha ','','','','','', + '','','','','','','','','','','','','Cham ','','','', + '','','','','','','','','','cu ','','','','','','', + '','','','','Chem ','','','','','','Tiu ','','','','','', + '','','','','','','','','fen ','','','','','','','', + ], + 'x207':[ + '','','','jiu ','xu ','','','','','','','','','','Xian ','', + 'kuai ','','','','','','','','','bu ','','','','','','', + '','','','','qia ','','','','','','','','','','Hui ','', + '','Pai ','','','','','','','','ju ','','','Qia ','','','', + '','','','','','','','Bao ','','','','','','','','', + '','','','','','Cun ','','','qia ','','','','','','','', + '','','','','','','','','','','','','','Peng ','','', + '','','','','','','','','','Gaai ','','','','','','', + '','','','zhe ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','Got ','Bam ','','','','','','','','','','gun ','Lou ','','', + 'Jiao ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','yao ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Hoat ','','','','','','','','','','', + '','','','','','','','','','','','ze ,bai','','','','', + ], + 'x208':[ + '','','','','zhao ','','','','','Bua ','','','','','','', + '','Tet ','','','du ','','','','','','','','','','','', + 'du ','','','','','','','','','Truoc ','','','','Chom ','','die ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','Gang ','','','','','', + '','','','','','','','','','','','','','','','', + '','duan ','','','','','','','','','Khuot ','','','','','', + '','','','','','','','han ','','','','','','','','', + '','Nhoc ','','','','','','','','','juan ','','','Vam ','Giup ','Giup ', + '','','','dian ','Jue ','','','','','','','','Lu ','','','', + '','','','','','','','','','','','','','','','', + '','','Ruon ','','','','','','','10383.060,wan ','','','','','','', + 'yun ','','','','','','','','','','','','','','','', + '','','','','','','','','','','qu ','shao ','','','','', + '','','','pao ','','','','','','','bao ','','','','fu ','jiu ', + ], + 'x209':[ + '','','','','','','Cho ','','','','','','Cho ','','hua ','Bao ', + '','','','','','','','','','','','','','mao ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','diao ','','','', + '','','','','','','','','','','','','','','wei ','', + '','diao ','','','','','','','','','','','','','','', + '','','','','Giau ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','sa ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','luan ','Muoi ','','','','','','Gan ', + '','','','','','','','','','Chuc ','','Lung ','','','','', + '','','','','','','Tron ','yu ','','','','','','Nhu ','','', + '','','','','','he ','','','','shao ','','','','','','', + '','','','','','','','','','Hui ','','','','','','', + '','','','','','','','','','','','','','','','heng ', + ], + 'x20a':[ + '','','','wai ','','','','','','','jue ','','','','zhuan ','', + '','','','','','','','','','','','','','','','', + '','','jun ','','','','','','','','','','','ju ','','', + '','','','','','bang ','','','','','','','','','','', + '','','','','','','','','zhu ','','','','','','','', + '','','','','','Me ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','Li ','','','','','', + '','','','mei ','','','','','','','','','','','','', + 'liu ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','fu ','','','','', + '','','','jue ','','Day ','','','','','','','','','','Rot ', + '','','','','','','','','','','','','','','','', + '','','','yu ','','','','','','','','','','','tu ','', + '','','','','','','','','','shan ','','','','','','', + ], + 'x20b':[ + '','','','','','','guan ','','','','','','','','','', + '','','Cut ','','','','','','','','','Mo ','','fu ','','', + 'Mot ','','','bang ','','','','','','','biao ','','','','jie ','', + '','','','','','','Jin ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','Zhuo ','','','','','bian ','','','','','','tun ', + '','','','','','','','','','','de ','','zhu ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Naai ','Leo ','','','','','','', + '','','','','','mang ','','','','','','','','','Ngot ','sa ,san', + '','','','','','','','','Daai6','','','Jai ','','','','', + '','','','zhe ','','','','','ban ','jie ','','','','','','', + '','','','','','','Thet ','','','','','','','','Hin ','pian ', + '','','','','bian ','','','reng ','','reng ','','','Danh ','Chui ','','', + ], + 'x20c':[ + '','','Ngoen ','','','','','','','','','Jaau ','Mut ','','','Mom ', + '','an ','','he ','','','','','','Khen ','','hu ,gao','','','','', + '','','','','','','','','','','','','','Meo ','','', + '','','Eot ','','','','','Lo ','','','dai ','wai ,wai','','','','', + '','Tam ','Dat ','Nip ','','Quai ','','','','','','','','Phom ','','', + '','','','Ngai ','','','','','Ngaak6','','','','Chun ','','','', + '','sa ,shai','','','','Fik ','','','','','','','','','','', + '','','na ','','','','','Ming ','San ','','','','','','','', + '','','','','','','','','','','','','shu ','','','Nham ', + '','','','Hang ','','','E ','','','','','','Gianh ','','','', + '','','','','','','Nhung ','','','','','','','','Khinh ','', + '','ge ','','','','Mep ','','die ','','','','','','fu ','','Thoc ', + '','Kwan ','','','','','','he ','','','','','qia ','','','Ce ', + 'Vang ','','','','','Caau ','Dap6','','Nhu ','Thay ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','Tu ','','','','','','','cheng ','','', + ], + 'x20d':[ + '','','','','','','','','','','','Phao ','Nhanh ','Nhan ','','Mang ', + 'Nuc ','','','','','Miu ','Voi ','','','','','Gung ','','','','', + '','xiao ','','','','Ngoam ','zhu ','','','','','Thut ','','','','', + 'Gau6','hu ','ta ','Ngaau ','','zao ','','','','','','','dao ','','na ','', + '','','','','','','Daam ','Koe ','Mui ','Hong ','','','','','','', + 'Mep ','','','','','','','','Mun ','','','','','','','', + '','','','ya ','','','','zhen ,chun','de ','Go ','','','','','','Gwit ', + '','E ','','','','','','xuan ','','','','','Mang ','Faat ','Waak ','Pe ', + 'Tham ','Nhu ','','','','','','','Se ','','Pha ','','','','','', + '','U ','','','','Nhau ','Uong ','','Sat ','Bop ','','','Zai ','','','', + '','Troi ','Du ','Mai ','','Khung ','','Dim6','','','','da ','nang ','','','Chut ', + '','','Gap6','','','','','','jue ','he ','','','','','','', + '','','dai ','','','zhu ','','','','','','','','ta ','','', + '','','','','','','bian ','','','xu ','','','','','','', + '','','','','Phao ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x20e':[ + '','pai ','Giot ','','Inh ','','','','','Kak ','Tap ','','','Me ','Naa ','Ge ', + 'Kam ','Soek ','Bou ','','','','','Xua ','Tuc ','Song ','','','','','','Bai ', + '','','','','','','Khan ','','','','','Tau ','','','','', + '','','','','','','','','','yu ','Ngaak6','','','','Map ','', + 'xun ','wa ','','ang ','han ','','','','','','','','Lan ','','','', + '','yao ','','ge ','','bao ','','','xu ','','','','','','','', + '','','','','','','','','','','','','','Ko ','','', + '','','','Git6','','','','Ngo ','Kam ','Lan ','Maai ','Zam6','','Cay ','','', + '','','','','','','','','','','','','Gwe ','','','', + 'huan ','','','','','','','','Long ','Thoi ','Ban ','','','Gaak ','','ku ', + 'Lung ','','Gaa ','','','','','','','Trou ','He ','Loe ','He ','','','', + '','Hung ','','','','Chac ','Nop ','','','Ri ','Que ','Cop ','Xui ','','Chau ','Ngoan ', + '','Guong ','Ngon ','Han ','Oang ','','','','','','','','','huan ','','zu ', + '','','','','','','','Le ','Zeot6','he ','','','','','','', + '','','','','Don ','zhao ','','','','','','','tu ','','','', + '','','','','Long ','','','','','','Aa6','Bai ','Dau6','','','', + ], + 'x20f':[ + '','','','','','','','','','','','','','','','', + '','','','','','Paai ','','Zaam ','wu ','','','','','','','', + '','','jiang ,qiang','','','','Muon ','','','lun ','Day ','','','But ','Ngai ','Ho ', + 'Kang ','Loe ','','','','Danh ','','Thay ','','','','Ji ','','','','', + '','Xo ','','Zap ','Tham ','Thung ','Nuot ','','','','','Nac ','Toet ','','Nhai ','', + 'Ngo ','','Neng ','Ngon ','Thua ','','Giuc ','','','','','Oam ','','','','', + '','','','','Kik ','','','','','','','','','','','', + '','','','','','yu ','','','','','','zhe ','','','','', + 'Hup ','','','','','','','','','','','','','He ','','Ce ', + '','','','','','','','','','','','Ngoang ','','','','', + '','','shu ','Rum ','','','Bai ','','','la ','','','','We ','','', + '','','','','Baang ','Zaa ','Ging ','','','Nuot ','','','Cyut ','Nhun ','Nhap ','', + '','Si ','Xep ','','','','','','','','','','','','','', + '','','Het ','sa ','','qiao ','','','','','','Lu ','hua ','','','', + '','','','','','','','','','','Gaa ','Saau ','Soe ','Wet ','','Ngui ', + '','','','','','Khan ','','','','','','','','','','', + ], + 'x210':[ + '','','','','','','','','','','','','','','','', + '','','','','Ro ','','','','','','','','','Nam6','Zip ','', + 'Bei6','','','','','Phao ','','','','Lok ','','Bam ','','','','', + '','Hao ','Cay ','','','','','Ron ','','','xie ','','','','','', + 'han ','','','','','','','','fan ','','','','','ai ','yu ','Am ', + '','','','','','','','','','','Hon ','','Wo ','Hang ','Xao ','', + '','','','','','','','','','','','','','','','Dyut ', + '','','','zhan ','','Gan ','Zit ','Doeng ','Kwaat ','','Ngon ','Ziu ','','','','', + 'Khao ','','','Hun ','','','','Mom ','Voc ','','yu ','','','Eng ','','', + '','Ban ','','','','','Lai ','','','','','','','Zuk6','','bao ', + '','shu ','','','','','','','','','Ze ','peng ','','','Ngau ','', + 'Ran ','','Ray ','Troi ','','','','Khoan ','','','','','','','','', + 'E ','Leng ','','','lai ','','','Bai6','Kwaak ','Gaa ','','','','Chem ','Phan ','Doe6', + '','','Boc ','Bo ','','Gung ','Le ','Mua ','','Mut ','','','','lun ','','', + '','','','','Laai6','','','','','','','','','','','', + '','','','','Ceoi ','Ngung ','Sek ','','','Chen ','','','','','Phac ','Thot ', + ], + 'x211':[ + '','Lum ','','','','','','','','','','','','Ruc ','Gam ','Ham ', + '','','dao ','','','','','','','','','','','','','Haa ', + '','Chay ','','','','','Lom ','','','Khan ','Toe ','Khem ','Hun ','','','Jik ', + 'Tot ','cu ','ru ','','','Ji ','','','','luan ','','','','Soe ','','', + '','','','','','e ,ei','','','Laa ','Dang ','Bun ','Hum ','','','','Lai ', + 'Lanh ','Ngong ','','','','','','','la ','yun ','','','','','','', + '','','','','','die ','','Nan ','','','','','Hoai ','','','', + '','huan ','','','','','','','','','','huan ','','','','', + 'Gwang ','Nhau ','','','Nhep ','wan ','','Wok ','','','','','','','','', + '','Nham ','','','','lian ','Trom ','','','','Gu ','','','','Giau ','', + '','','','','','jiu ','','','','','','','','','','', + 'dun ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','die ','','','','','','Doe ','','','','','he ','', + 'zhe ','','','','','','wei ','','','tu ','','','','','','hun ', + '','','','','','dang ','he ','tai ','Quay ','','yu ','Nhot ','ya ','','','', + ], + 'x212':[ + '','','','','','jue ','','','','','','','','','Mui ','', + '','','','yuan ','','','','','','You ','','','','','','', + '','','','','','','','','yu ','','','','','','','', + '','','','','','','lei ','','','','','','','','','', + '','','','','','','','','','','','','','','Cong ','', + '','','tun ','','','','Cong ','','','','','','','','','', + '','','','','','','','','','bao ','','','','','','', + '','','','','lu ,hu','','','jie ','','','','','','','Tum ','Moc ', + '','','','','','','','','','','','','','shu ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Sanh ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','gao ', + '','','','','','','','','','de ','','','yu ','','','', + '','','','','','','','','','','','','','','','', + ], + 'x213':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','guai ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'hu ','','','','','','','','Che ','Vung ','Lam ','','Mun ','Nui ','','', + '','','','','','zhai ','','','du ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','du ','','','','','','', + '','an ','','','','','','','','','','Bun ','Nam ','','','Hang ', + '','','','','','','','','','','','','','Thong ','su ','', + '','','','','Gung ','','','','','','zhu ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','xia ','','','','','','','', + '','Luong ','','','','Tret ','Xay ','Bui ','','','','','','','','bai ', + '','','','','','','','','','','','','','','','', + ], + 'x214':[ + '','','','','','','','','','','','','chu ','','','', + '','','','','','','xian ','Hoc ','','','','','','fu ','','', + '','','','','','sa ','','','','','','','','','Ve ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Coi ','Chum ','','','','Thoai ','','','','','','Lan ','Sui ','', + '','','','','','','','','','','','','','Coi ','','', + '','','Gom ','','','','','','','','','','','','yu ','', + '','sa ','','Juk ','Lan ','','','','','','yu ','','','ju ','','', + '','','shu ','xian ','','','gai ','','','','','','','','','', + '','','','','','','','','','','','Cau ','','','Suong ','', + '','','','','','','','','','','','','','','','', + '','','','Loi ','Vung ','','','','','','','','','','','San ', + '','','lai ','','Lam ','','','','','','','','','','','', + '','','','','','Chen ','zhan ','','','','','','','','','Chum ', + '','','','','','','','','','','','','','','','', + ], + 'x215':[ + '','','','','','','','','','','','','','','','', + '','','','','Lan ','','','','','','','','','','','', + '','','','','','','','','','','shu ','','','','','', + '','','','','yu ','','','','','','','','','','','Trau ', + '','','','','','','','','','','','','','','','', + '','','kua ','','','','','hai ','','','','','','','','', + '','','','','','','','hang ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','yun ','','','','','','','','','','','','','', + '','','','','','','','','','','guai ','','','','','su ', + '','Bon ','','','','','','','','','','','','','','', + '','','Sai ','','','','','','','','','Lam ','','','Tum ','', + 'Muong ','','','','','','','Peng ','','','','','','','','', + '','','','','','chun ','','','','','','','','','','', + '','','','','','','','','','fan ','','','','','','', + ], + 'x216':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','zhe ','Mat ','Lon ', + 'juan ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','jie ','','','','','','','bie ','','','','','', + '','','','','Canh ','Nhon ','','','','','','','','','','', + '','Bi ','','Xon ','','','','yan ','wei ','','','','hao ','','','', + '','','','','meng ','','','','','','Lon ','','','','','', + 'jue ','To ','To ','','','','Hai ','','','','','','','','','', + '','','','','','','','','','zhang ','','da ','','hao ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','can ','','', + '','','','','Nua ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x217':[ + 'fan ','','hu ','','','','','','','','','','','','','', + '','','','','','','','','','','ru ','','','','','', + '','','','','','','','','','','','','','','','zhe ', + '','Ji ','gao ','','','','','','','','','','','','','', + '','','','Bua ','','','','','chu ','','zhe ','','','','','', + '','','','','Kep ','Va ','','','','','cheng ','','du ','','','nian ', + '','','','','','','Vu ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','cu ','','','pan ', + 'hu ','','','xian ','','','','','','','fu ','nai ','','','','', + '','','','','','','','','','','','','','','Nen ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','lian ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x218':[ + '','','','','','','','','','','','','','','','', + '','','','','','','hao ','','yang ','','','','','','fu ','', + '','','','Cuoi ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'juan ','','Nhang ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','qu ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'zhuan ','','','','','','','','dang ','','','','','','','', + 'Sau ','','','','','','','','','','man ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Sui ','','', + '','','','','','','','','shu ','','','','','','','', + '','','','','han ','Ban ','','','','','','','','','','', + '','','nei ','','','','','','Cuoi ','','','','','','cai ','jie ', + '','','','','','','','','','','','Sen ','','','','', + ], + 'x219':[ + '','','','','','','','','','','Chua ','','','','fan ','', + '','','','Moi ','Moi ','','','zhu ','','na ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','jiao ','','','','Nhat ','xiao ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Con ','ju ,ru','','','','','','Me ','','','', + '','xu ','','','fu ','So ','','','','','','','','','','', + '','','','','','er ','','','','','','shu ','','','','', + '','','','','','','','Rot ','','','','Chat ','','','Nhang ','', + '','','','xiao ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','mian ','','','','','wa ','','pao ','','','','','','', + '','','','','','','heng ','','zhu ','','','','','','','', + '','','','','','','','','','dai ','','','','','','', + ], + 'x21a':[ + '','','','','Xia ','ju ','','','','','','','','','','', + '','','','','','','','zao ','','','','','','','','', + '','','','yu ','','','','Tot ','','','','','','','','', + '','','jie ','','Ning ','nai ','','','','','','','','','','yu ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','jie ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','an ','','','Xum ','','','', + 'ceng ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','Sao ','','','','','','','','','','','','','','', + '','','','','','','Lung ','','','','','','','','','', + ], + 'x21b':[ + '','','','','','','','','Xuong ','sai ','yu ','jiao ','','','','', + '','','','','','','','','20960.020,lao ','','','','','','yu ','', + '','','','','','','','','','','','wu ','','','','', + '','','','','','','','Tac ','','','','','Gang ','','','', + '','','de ','','','','','','','Ban ','','','','','','', + 'shuan ','','','','','Cut ','','','','','','','Mon ','','','', + '','','bai ','','','','','Chut ','','','','','Be ','','','', + '','Chut ','Trut ','kao ','','','','','luan ','','','Nhon ','','','','', + '','','','','','','Mon ','Chut ','','Mon ','','May ','Be ','Chut ','','', + '','','','Choai ','','','','','','nai ','','','','','','', + 'May ','','','Be ','Be ','Be ','Zao ','','','Be ','','Nhen ','Mon ','Nhon ','Mon ','', + '','','Tho ','','','Chuong ','Chuong ','','Nhon ','','','','','Nhon ','','', + 'Oat ','','','','','','','wu ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'ga ','','','','chao ','','','','','','','','','ga ','','', + ], + 'x21c':[ + '','','','','','hu ','','','','','','','','','','', + 'qiao ','','','','','','','','','','','','','','','', + '','','xie ','','','','','','','','Duk ','','','','','', + '','','','','','','','','','','','','','ai ','','pu ', + '','','','','','','Shu ','','','','','','','','','', + '','','','','','','','','','','','','zhao ','','','', + '','','','xu ','','','','','','Thuoc ','','','','','','', + '','zhu ','','','','','','die ','Gang ','','qu ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Ti ','','jue ','','','qiu ','','','','','', + '','','Ke ','jiang ','','','','','','','yun ','','Gwat6','','','', + 'qu ','','','','','','','','','','','','','','','', + 'Ngoe ','','kai ','Cuoi ','','','','','','','','','','','','', + '','chu ','','','','','','','ju ','','','','Cuoi ','Rot ','','', + '','','','','','Toi ','','','','','','','','','','', + '','','','Cuoi ','lu ','','','','','','','','','','jue ','', + ], + 'x21d':[ + '','','','','','','lu ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','ya ','','', + '','hu ,jie','','','','','','','','','','','','','','', + '','','','','','','','','','Ngut ','','','','','','', + '','','','','','','','','hu ','ang ','','fu ','','','','', + '','','','','','','','','','','','','mu ','','','', + '','','','','','','','','','','Cu ','','','','','', + 'Nui ','','yao ','ai ','','','','','','fan ','','ju ','','','','', + 'qie ','','','','','','','','','','','','','','','', + '','','kuang ','','','','ya ','','Ngan ','','kan ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','lu ', + '','','','','','','','','bie ','','','han ','','na ','','', + '','','','','wu ','gao ','','','','','','','','','','', + '','','','','','','','','','','','ya ','','','','', + ], + 'x21e':[ + '','','','','','','','','','','','','zhu ','','jie ','Voi ', + '','','','','xie ','','','ya ','','','','','','','','', + '','','','','','','ze ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','ya ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Nghi ','','','','','','','','','','','','','die ','','', + '','','','','','','','','','hu ','','','','','','', + '','','','','','','','','','','','','','','','', + '','die ','','','','','','','','','','','pen ','','','', + '','','','','','','Din ','','','','','','','','','', + '','','','','tu ','','','xia ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Voi ','','Seoi ','Von ','Chon ','','','','','','','','', + 'zhu ','','','','','','','','gun ','man ','','','zu ','','hu ','', + '','lei ','','','','','','','','','','','','','','', + ], + 'x21f':[ + '','','','','die ','','','','','','','','','','','', + '','','','dian ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','wei ','','','','','','','','','','','','','kuai ','', + '','','','','','yun ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','Non ','','','','', + '','Jie ','bang ','','','','','','','','','','','','','', + '','','','','','','','kuang ','','','','','','','','', + '','','','ceng ','','dang ','','','','','','','','','','', + '','','','','','','','','hai ','','','','Doc ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','nang ','','', + '','','','','','yu ','','','','','','','','','','yu ', + '','','','','','','','','','','Nao ','','xun ','','ju ','', + ], + 'x220':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','wan ','','','','','','','','', + '','','','','','Vang ','Sua ','Tron ','Sang ','','','','Lon ','','Sam ','', + '','To ','Lon ','','','han ','','','','','','','fu ','','','', + 'fu ','','','','','','','','','','','Trang ','','Va ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','jue ','','','','','', + '','','','','','','','','Phuon ','','','bu ','','','','', + 'fu ','','','','xuan ','','fu ','','','','','','','','Du ','', + 'xie ','Shi ','','','','','','','','','','','Vua ','','','', + '','','','','','','','','','','','','','','','', + 'Tranh ','yuan ','','','','','','','','mao ','qian ','','','','','', + 'wu ','','','','','','','Lei ','Long ','','Vua ','','','','','', + '','','','','','Ta ','','han ','qian ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','la ','','','','','','','','','','','', + ], + 'x221':[ + '','','','Phoi ','','','','','','','','','','he ,ge','bang ','', + 'meng ','','','wu ','dai ','','','','','','','','han ','Bau ','','', + '','','','','','','','cu ','','','','','','','','Man ', + '','','','','','xiang ','Hua ','','','','','','','','','', + '','','','','','','Manh ','','','mao ','','ceng ','','','','Lian ', + '','','dan ','','','','Lian ','','','','','','','dian ','','', + '','','','','gai ','Ju ','','','','','zu ','','Chan ','','','', + '','','','','','','','','','yao ','','','nei ','','','', + '','','neng ','','','','','','','','','','','','','', + '','','','','','','','','','','','','ge ','','Jian ','', + 'Lai ','Nin ','','','','Nam ','jian ','May ','May ','','May ','','','','','', + 'hu ','','','','','','','','','','chen ','','','','','', + '','','','','','','','Guan ','yan ','Doi ','','','','','','', + '','','','','','','','sha ','','','','','','','han ','', + '','Khuya ','','','','','ren ','','','','fan ','','','','','', + '','','','','bu ','na ','','','','','','','','','','', + ], + 'x222':[ + '','','','','','','','','Nap ','','','','','','','', + '','','','','','bai ','','','Roku ','','','kun ','','qiu ','','', + 'cu ,la','','','','','','','','','','','','','','','', + '','','pu ','','','','','','','','','jie ','','zhan ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','du ,tu','','','', + '','','hu ','','jia ','','','','la ','','','','','','','', + '','','','','','','','','','','','','','Kho ','U ','ma ', + '','','','','','','','','','','','','','Ceoi ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','yu ','','lu ','','','','','','', + '','fen ','','','','','','','','','','','','','','', + '','','','','','yu ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','xian ','', + '','','','','','','','','','wu ','','','','','','', + ], + 'x223':[ + '','','','','qu ','','','','','','Rong ','','Rong ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','fu ','','yu ','','','','', + '','','','','','','','','','','','','','','gao ','juan ', + '','','','','','quan ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','die ','','','','','','dai ','','su ','', + '','','','','jie ','','qu ','','han ','','','','','','','', + '','jie ','','','','juan ','','','','','dan ','','','','','', + '','','','','','hu ','','','','jue ','','yu ','','','','', + '','','','','','','','','','','','','','fu ','','', + '','Ban ','','','','','','','','','','','','','','', + '','','Cong ','Cong ','xun ','','','','','','','','','liu ','','', + '','','','Beng ','','','','jue ','','','','','','','','Von ', + ], + 'x224':[ + '','','','','yuan ','','','','','','','','','','Khom ','', + '','','','','','','','','','','','','','','cheng ','', + '','','','','','','','King ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','jiu ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','hu ','','','','','','', + '','','','','','','','','','','','','','','Bay ','', + '','','fu ','','chu ','','','','','','','','','','lan ','', + '','','','','','','','','','','','','','','','', + 'yu ','','','','','','','','','','','','','','jiao ','', + '','','','','','','','','','','','ang ','','','','', + '','','','','sa ','','','','','','','','ge ','','','', + '','','kua ','','','','','','','','','','xie ','','','', + '','','wu ,hu','','','xiu ','','','','','','','','','','', + ], + 'x225':[ + '','','yan ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','yu ','','','yu ','','','','','','','yu ','','','', + '','','liu ','','20832.030,yu ','','','','','','','','','','','', + '','','','','','shuai ','','','','','','yuan ','','','','', + '','shuai ','','','','','','','','','','','','','','ao ', + '','','','','','','','','','','jiao ','','sa ','xian ','zha ','dian ', + '','','','','','','','','San ','','','shan ','','','','', + 'Suot ','','','','','','','','tiao ','','','','','','','su ', + '','','','','','Sau ','Sau ','','','','','','','xian ','','', + '','yu ','','','','','jue ','nang ','','','','','','','','', + '','','','','','ru ','','','','','','','','','','', + '','','','','xia ','','','','','Nuoi ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','wu ','','','','','','','chang ','','Lo ','','','', + ], + 'x226':[ + '','','','','qiu ','Maau ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Rung ','Rap ','', + '','','','','','','','','Jiang ','','','','','','','', + '','wu ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Hung ','','','','','','','','','Nhon ','E ','Tim ','kan ','', + '','Lung6','','','','','','','','','','','','','','', + 'xian ','','','','','','ju ','','','','','miao ','','','','', + '','su ','','','','','Ti ','','','','','','','','','', + '','','','','','','','','','','hu ','','','','','', + '','','','','','','','','','Khuay ','','zhu ','Ngop ','','','', + '','','','qiu ','ya ','','','','','','','','','','bie ','', + '','','','','','','xiang ','','','','ru ','wang ','','','','ya ', + '','','','','','','','','yu ','','','','','','','', + '','','','','Mang ','Zang ','','','','','','','','','','', + ], + 'x227':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','Vung ','','','','','','','','', + '','','','','','','','','','','','Xing ','Duo ','','','', + '','','','','','','sao ','','Nao ','','','','','','','jia ', + 'tu ','','du ','','','','','','','','','','mao ','yao ','','', + '','','','','','','','','','Vui ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','wu ','Fit ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'hai ','','','','','','','','','','','','','','','gao ', + '','','','','','','fu ','','','','','','','liu ','','', + '','','','','','Fit ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Chua ','','Nan ','','','Nep ','','','Chac ','Cham ','','','','','','', + '','','','yang ','','','','','','','','','','','','', + 'ai ','teng ','','','','','','','','Nhuoc ','','','','','','', + ], + 'x228':[ + '','','','Geng6','Sung ','Thung ','','','','','','','','','','', + 'Ngo ','','','','','','','','','','','','','','','', + '','sao ','','','','Gan ','Hon ','','','Mo ','','shu ','','','','Lang ', + '','','fu ','Bie ','','Tang ','','xiang ','','','','','','dang ','','', + '','','dang ','','','','','','','','','','','ge ','yu ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'zhao ','','','','','','','','','','','','','','','', + '','','Ghet ','','Ngung ','','','','','','','','chang ','zhe ','','', + '','','su ','','','','','','','','kai ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Khan ','','', + 'Ngay ','','','','Quo ','','','','','','','','','','','ai ', + '','','','','','','','','','','','','','','','', + 'liu ','','','','','','','Khuay ','','','','','','','','', + '','','','','','','','','','Hung ','','','','','','chu ', + ], + 'x229':[ + '','sao ','','','','','','','','','','','','','','', + 'liu ','','','','','','','','meng ','','zhan ','','','Cham ','','', + '','','','','zhuang ','','','','','','','','','','','', + '','','','','','','','','','Goe ','','','','','','', + '','','teng ','zhu ','','','Lung ','','Lo ','','','','','','','', + '','','','','','','Trai ','','xie ','','jiao ','','','','Chong ','', + 'Sung ','','','','','','','','','','','','','','','', + '','','','','','','','Ngoi ','','','','','','','','', + '','','Laan ','','','','','','','','','','qu ','','qiu ','Zai ', + '','','','','','','','','','','hua ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','shu ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','han ','ge ','','','','','','','','', + '','','Ta ','','','','','','','','','','','','','', + ], + 'x22a':[ + '','','','','','','','','','','','','','','','jue ', + '','','','','','','','zei ','','','','','jie ','','','', + '','','','','','hu ','hu ','','','','','chu ','','','','', + '','','','','','','','','','','','','','','','', + '','ju ','','','zhu ','','','','','','Quanh ','','','','','', + '','','','ge ','','','','','','','','','Ho ','','','', + '','','shan ','','Muon ','','Zit ','Hat ','','','','','','Thuon ','Dat ','jue ', + '','','','','','','','','hai ','xia ','','','','','Chop ','', + '','','','cu ','','','','','','','','','','','','', + '','','','','','','','Vuc ','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Ngat ','Vat ','Nang ','','','','','Muc ','','','','','','','zhang ','', + '','','','Keo ','','That ','Vun ','','','','','','Tha ','','','Kam ', + 'jie ','','','','','Wing ','Trot ','','So ','','','','Trum ','Rung ','Quay ','', + '','','','Bac ','','','Haku ','','Ngung ','','','Lat ','','nu ','','', + 'zhe ','','','','','zu ','','','','','','nie ','','','','', + ], + 'x22b':[ + '','','','','Bung ','','','','','','','','','','','', + 'Muc ','','','','','','','Chui ','','','','','','','','', + '','','','Tay ','Khuong ','Giang ','','','','','','','','','Vot ','', + '','Khep ','','','','','','nan ','','','','','dun ','','','Xoi ', + '','','','Dau ','','','Chou ','','','','','','','','','', + '','Thuoc ','','','','','','','','','','','Xac ','','','', + '','','','','','bian ','','','','','','','','','','Quet ', + '','','','Giau ','Khuay ','','','Vom ','','Lan ','Dui ','Xoi ','','','','', + '','','','','','','','','','','ya ','','','','','bang ', + '','Luk ','','','','','','','','','','','','','sao ','', + '','','','','','','','','','Co ','Ron ','','Chut ','Co ','','', + '','','','','','','','','','','','','','','','Quay ', + '','','','','','lu ,jue','','','','xie ','Dik ','','zhai ','','Ngaau ','', + 'Co ','','','Va ','Quat ','Ngoi ','Khep ','Quay ','Huo ','','','Sap ','Buoc ','Ven ','','', + 'Va ','Roc ','Sua ','','','','Lay ','','','','','','','','yu ','', + '','Sau ','wan ','xue ','','','','','','ge ','','','','','mao ','', + ], + 'x22c':[ + '','','','','','','fu ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Wo ','','','','','Gap ','Zung ','pan ', + '','','','','jie ','','','','jia ','','','','jia ','','Boi ','', + 'Gieo ','Waa ','','','','Dap6','','','','Cai ','Phung ','Xoi ','','Nhot ','','Sin ', + '','','Saak ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Kek ','','','','','','','', + '','','','','Bung ','','','','','','','','','Run ','','', + '','Laa ','','Rung ','Cau ','','','Gay ','','Cap ','Mai ','Mo ','','','','', + '','Cau ','Sang ','','','Cao ','','Sou ','Lou ','','','','die ','','','zhu ', + '','','Bat ','','','','Ngao ','','zu ','','','','','','','', + '','lang ','','','','','','','','','','','Saai ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x22d':[ + '','','','','','','','Chap ','Daat ','','Chop ','Chong ','','','','', + 'Day ','','Phanh ','','','Ning ','','','Xay ','','','','Xau ','','Nhung ','', + '','','fen ','','','','','','','','','','ban ','','','', + '','lei ','xie ,jie','','','','','','','','','','','','','', + '','','','','Cou ','','','yang ','','','','','Dui ','','','', + '','','','Paang ','','','','','','','','','','','','', + '','','','','','zao ','','Dan ','','Doi ','','','Don ','','','', + '','Khoi ','','Sum ','Quay ','','Don ','Cat ','Xap ','','','','Vot ','Ro ','','', + '','','','','','Sip ','','','','','','','','Saap ','','', + '','Niao ','guai ','','','','','','','','','','Ngung ','','','Cui ', + 'Saau ','','','Die ','Loe ','','','','','','','','','','','Maan ', + '','','','','','','bang ','','Bum ','','Dom ','Bung ','Ngoi ','','','Don ', + '','Nem ','Xan ','','','Tro ','Chen ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','Ban ','','','','','','','','','','Dui ','', + '','','Hang ','','','Vo ','liu ','','','','du ','','','','','jie ', + ], + 'x22e':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','Lan ','','','', + '','','','Niao ','','cuan ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Choc ','Gai ','Mac ','Rung ','','Xe ','','','','','yu ', + '','Zaang6','','','','','','','','lan ','','','','','','', + '','','','Keo ','Xau ','','','','Tum ','Suong ','','','','','','', + '','','','xiao ','','','','','','','','','','Giam ','Que ','', + '','','','','','','','yao ','','ta ','','Naan ','','','','', + '','','Bung ','','Bau ','','','','','','','','','Uon ','','chan ', + '','','','','','','','','','','','','','','','', + '','','','Man ','yu ','','','','','Chia ','Chia ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','cheng ','','','','','','','','','hai ','','','', + '','','','','','','','','sa ','','','','','','jie ,fu','', + '','','','','','','','','','','','','','','','', + ], + 'x22f':[ + '','','','','','','','','','','','','bao ','','','', + '','','','','','','','','','','','','','','','', + '','','','qia ','','','','','','','','jiao ','','','','', + '','','','','','','','','','','xue ','','','','','', + '','','','','','','','da ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','mao ','','','','','','','','','','','jiu ','','', + '','','','','Duk ','','','','','','','','Va ','','','', + '','wei ','','','yu ','du ','','','','','cheng ','','','','','', + '','','kuai ','','','','','','','','','','','','','', + '','','','','','','','','','','','','lu ','','','', + '','','','','','','','','','','','','','','','wen ', + '','','meng ','','','','','','','','','','','','','', + '','','','','','','','','','','','','man ','','','', + '','xie ','luan ','','','','cheng ','cheng ','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x230':[ + 'lei ','','','','qun ','','','','','','','','','chen ','','cheng ', + '','','Chong ','','','','','','','','','','','','','Va ', + '','','','fu ','','','','san ','','','','','','','','sa ', + '','','','','','','','','','','','','','','fu ','', + '','','','','','','','','','','','','','dao ','','', + '','','','','Lon ','','gan ','tan ','','','','','man ','','','', + '','','','','','','','','','','','','','','','', + '','','','','qia ','','','','','','','','','','','', + '','','','','','','','','','','yun ','','','','','', + '','','','','','','','','','','','','','xiang ','','', + '','','','','','','','','','','','','xiao ','','','', + '','','','dang ','','zhuan ','','','','','','','','','','', + '','','','','','','','','','dang ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','yan ','', + ], + 'x231':[ + '','','','','','','','','','','','','','','fu ','', + '','','','','','','','','','Huang ','','','','yan ','','hu ', + '','','','','','','','','','','','','','','','', + '','','','','liang ','','','','','','wei ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Khuya ','Khuya ','','','','','','', + '','jue ','','','','','','','','','','','','','','', + 'xiang ','','','','','Tam ','Luc ','','','','','','','','','', + '','','','','','','','','','','','','','','','Phoi ', + 'Trua ','','xu ','','','xian ','','','','gan ','','','','','','', + '','','','','','','','hao ','','','','','','','Chang ','', + 'Giay ','','','','','fu ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','Sao ', + '','','Bie ','','','','','','dai ','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x232':[ + '','','','','','','','','','','mu ','','','die ','','', + '','','','Phoi ','','Mai ','','Ngay ','','','','Quat ','Ngay ','','Hong ','', + 'bian ','','Tia ','','','tu ','','','','','','','','','','', + 'Nau ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Ui ','Trua ','', + '','','','','','sang ','','ang ','nai ','','','','','','Gou ','', + '','','','','','','','','','ya ','','','','','','', + '','','','','','Rua ','','','','','','','','','','', + '','','','mao ','','','','','','','','Se ','','Mo ','Chop ','', + '','','','','meng ','','','','','','','','','sang ','xu ','kan ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Bay ','', + 'Sao ','Toi ','','','','','','','','yu ','dan ','','','','','pu ', + '','','','','','','','','','','','','','','ai ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Som ','','', + ], + 'x233':[ + '','Trua ','Trua ','','','','Trua ','','','Khuya ','','Som ','Rua ','','','de ', + '','','','','','','','','','','','','','Nang ','','', + 'chun ','','','','','','','','xun ','','','','','','','', + '','','','','','','','','','','Xeo ','','','','','', + 'Nguc ','','','','','','','ju ','','','','Cui ','','Oam ','','cha ', + '','','','','','','','','','','','yu ','','','','', + '','','','','','','kuang ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','Luo ','','','','','','','','','', + '','','','','nian ','','','','','','hu ','','','','Trang ','', + '','','','','','','','','','','','','','','','', + '','','','','Dun ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','shu ','','','','','','','','pai ', + '','','','','','','','','','','','','','','','', + '','','','','Jan ','','','he ','','','','','','','Qua ','Then ', + ], + 'x234':[ + '','','','','','Nhum ','Thot ','','','','','','','','','', + '','','','','','','','','','','','','','Xop ','','', + '','','','','','','','','','','','','','','','', + '','','Queo ','','','','','','','','han ','','','','','', + '','Cung ','hu ','','','','','','','','','','','','Roi ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','Gian ','','','Sim ','','','','Nen ','','','','fu ', + '','','dian ','','','','qiao ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Mang ','','','','','','','','','','','','', + '','Xoai ','Sao ','Cong ','','','','han ','kuang ','','','','','','','', + '','','','','','','','','','sha ,jie','','','Gou ','','','', + '','','shan ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','Lau ', + ], + 'x235':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Cui ','Bap ', + '','Pha ','Xoi ','Ngoc ','','Chanh ','Nhai ','','Kang ','','','','','','','', + '','','','','','','','','','','mao ','','Gon ','','','', + '','','','yu ','','pao ','','','','','','','','','','', + '','','','','','','','','Hay ','','','','','','','', + '','','','','','','','','','','','','Noc ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','yun ','','','','','','','','','', + '','','','','','Peng ','Chay ','Chay ','','','Ca ','','','','','', + 'Suot ','Trac ','','ju ','','','','','','','qu ','','jue ','','ang ','', + '','','','','','','','','','ru ','','','xun ','','','', + '','','','','','','','','','','','','','','','', + 'reng ','','','Chua ','','','','','','','','','','','','', + '','','','','','','','','','','Cha ','','','','','', + '','','','','','','ta ','','','yang ','','','','','Son ','', + ], + 'x236':[ + '','Ca ','','Cay ','Thot ','','','','Son ','Cum ','','','','','','', + '','','','','','','','Nik ','','bang ','Seot ','','','','','', + '','','','chun ','','','Yi ','','','','','','','','','', + '','','','','','','','','','','','','','Nau ','Vai ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','Rac ','','','','','','', + '','','juan ','','','','','','','','Mo ','Sop ','','','Chay ','Rui ', + '','','','','jie ','zhe ','hu ','','Sot ','Con ','Mam ','','','','','', + '','','','jie ','','','','pao ','','','','ye ','','','lei ','', + 'ru ','','','juan ','','Jaap ','','','','','','','','','','', + '','','zhuan ','','','','jiang ','hao ','','','dun ','','','','','', + '','','','','','','','','','','Hong ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','Xanh ', + '','Gu ','','Khay ','','Be ','','','','Then ','Tu ','hu ','','','','', + '','Dom ','','','','','','','ze ','','','die ','','zha ','','', + ], + 'x237':[ + '','','sa ','','','','','','','','','Mo ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','juan ','','','','ai ','','','', + 'Lim ','Son ','','','','','','','','','wen ','','','','Chua ','', + '','','hun ','','','ai ','','','','Duoi ','','ta ','','','','gao ', + '','yu ,yu','','','','','','hu ','','','','','10389.190,bian ','su ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Khu ','Cuoi ','','','dun ','','','','','','','Tram ','', + '','meng ','','lu ','tan ','','','liu ','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'lian ','','','','','','','','','','','','','','','', + '','','','Mong ','','','','xiao ','','huai ','','','','','','', + '','liu ','wu ','','','','','','','','','','','','','', + '','','','','','','','','','Dui ','','','Ran ','','','', + 'yu ','Kyo ','','','','','','','mei ','','lian ','','','lao ','','', + ], + 'x238':[ + '','','','','','','','','','','','','','','','', + '','','Tham ','Pheo ','','Chua ','Chua ','Que ','Gau ','','liu ','','zhao ','','','', + '','','','','','','','','','Tram ','','','','','','', + '','Tram ','','','','','','','','','','','','Ha ','','', + '','','','','','','','','','yu ','','','','','cen ','', + '','','','Tram ','','yan ','','','','','','','','Vui ','','die ', + '','','','','Nen ','','','lei ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','xu ','','','','','', + '','','yu ','','','','qian ','','','','','','','','','', + '','','','','','dian ','','','','','','','','','','', + 'zu ','','','','','','chu ','','','','','','','','','', + '','','','','','','','','dian ','','','','','','yu ','', + '','','','','','','','','','','an ','','','','hun ','', + '','','','dian ','','','','','','','','','','','sha ','', + '','','xie ','','da ','','','','','','sha ','','','','','', + ], + 'x239':[ + '','zhu ','','','','','','','ze ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','shu ', + '','','','','','','','','','','','','','','','', + '','','ta ','wan ','','','','','','','wang ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','guan ','','','','','','','','','','', + '','','','tu ','','','','ta ','','chu ','','','zhu ','','da ','', + '','','','','','','','','','','','','','Ngay ','','', + '','','','','','','','','','','','','','','','', + 'chu ','chu ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Laai ','du ','','','','','die ','','','','','','','', + '','','','','','','','','','bai ','','dian ','','qiu ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','nao ','','', + ], + 'x23a':[ + 'luan ','','die ','','qia ','','','mao ','','','','','','','','', + '','','','wu ','tao ','','','','','','','zu ','ma ','','','', + '','','','jiang ','xu ','','','Giuoc ','','','','','','Quan ','','', + '','','du ','xiang ','','','','','','','','','','','','hun ', + '','','','','','','','','','','','','','','','lu ', + '','','','','guan ','','','','','','er ','','','','','', + '','','liao ','','','','Ngoeo ','shan ','','','','','','zhai ','','ye ', + 'diao ','','','','jiang ','','','','Toi ','huai ','yu ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Ji ','','','','','','','','','','dian ','','','bian ','','', + '','','','','','','','','gu ','','','','','','','', + '','','','','','','','','hu ','','','','','','su ','', + '','','','','','','','','','','','','dao ','','','', + '','','','','','','','','','','','','','','','', + '','','','','xie ','','','Van ','','dai ','','','','','','', + ], + 'x23b':[ + '','','guan ','','','','pei ','','','','','','','','jue ','juan ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','ba ','ba ','','','','','','wu ','','', + 'bao ','','','Su ','','','','','','','','','','','','', + '','','','','','','','','fu ','','','','','ge ','','', + 'ru ','','','','','','','','','','','','','','','Ria ', + 'Mao ','','','qiu ,qu','','','','','','','','Mau ','','','','', + '','','','','','','','Ngu ','','','de ','','jie ','jie ','','', + '','','','','','','','','','','','','','','','', + 'san ','','chun ','','','','nai ','','','','','','','','','', + 'de ','','','','','','','','','','','','','','','', + 'mao ','','','','','','','','','','','ru ','','','wu ','', + '','','','','','','','','','','ta ','','','','','', + '','','','','','','','','','men ','','','','','','', + '','pei ','','','','','','','qu ','','','','su ','','','', + ], + 'x23c':[ + '','','','','','','','','','','','qu ','','','','', + '','','','','','sao ','','','kun ','','','','','','jie ','', + 'qu ','qu ','','','','meng ','','','','','','','du ','','','', + '','','','','','','','','','','','qu ','','','','', + '','','kun ','','','','Ho ','','','','','','','dan ','','', + '','','','xiao ,hao','','','','','','','','','','','','', + '','','','','','','','','','','','','Hoi ','','','', + 'Ram ','','','liu ','','','Vuc ','','','','','','','','','Nhop ', + '','','','','','','','','','','','','','Ngut ','','', + '','','','','','','','','','','','','','','','', + 'Ngot ','','','','','','','','','','','','','','','', + '','','he ','','','','','Nap6','','','','','','','guai ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','fan ','','','jie ', + '','','','','zhan ','','','','Deoi ','','','','','piao ','','', + '','','','','','','','','','','','','Doe ','','','', + ], + 'x23d':[ + '','','','','','','','','','','','','','','','', + '','','','jian ','','','','','','','Hup ','Nhung ','','','','', + '','','zao ','zhuang ','','','','','','','','','','','','', + '','','','','','','','','','','','','mao ','tan ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Bung ','', + '','','','','Ngam ','','','','zhu ','','','','gan ','','','', + '','','','','','','','','','','','','','zhuang ','','', + 'pao ','','','','','','','','su ','','','','','ju ','','', + '','can ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Loi ','', + 'Nhom ','','','','','','','','','','','','','','','', + ], + 'x23e':[ + '','','','xu ','','','','bian ','','','','','','','huai ','', + '','','','','','','','','','','she ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','fu ','','','','', + '','','','','','Lut ','','Tran ','','','','','','qiao ,xiao','','Cong ', + '','','','','','qian ','','','','xie ','','','hu ','','','xun ', + '','','','','','na ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','tao ','', + 'qiao ','','','','','','','','','','','','','','','', + 'Nuot ','','','Bui ','','','','Xoi ','','Duoi ','','','','dang ,xiang','','', + '','','','','','Ma ','','','','','shu ','','fu ','','','', + 'xie ','lang ','','','','','','','','zhe ','','','can ','','','', + '','','','','','','','','','','','','','','','', + ], + 'x23f':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','lu ', + '','','','','','','ze ','shuai ','','','Bot ','','','','','Vui ', + 'Lung ','Ngau ','Doi ','Xop ','','','','Lot ','','','','','Tran ','Lang ','','', + 'Ngau ','','','','','','Veo ','','','ru ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','an ','jian ','','53066.030,teng ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','Doi ','','','','Khoi ','','','Xoi ','Bui ','', + '','','','Ngau ','','','fu ','','su ','','lian ','','he ','','','', + 'ze ','','','','','','','','','','','','','','','', + '','','','xiao ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x240':[ + '','','','','','','','','','han ','','','','','','', + '','','','Loc ','','','Ngoi ','Rua ','Vung ','','','','Tanh ','yu ','','', + '','','','','','','la ','','','jian ','','','','','','', + '','','bian ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Dao ','Khoi ','','','','Trong ','Bot ','','Chua ','','','','', + 'Dao ','dan ','jie ','bai ','','','xian ','','','','','','','','','', + '','cai ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','zhuan ','','','','','Rua ','Dan ','Phun ','Loi ','Toe ','','', + '','','','','','','','','','','lan ','','yao ','','','xuan ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','Leo ','','Muong ','', + '','','','','','','','Thuot ','lan ','','','','','','','', + '','','','','','','Deng ','','','','xun ','','','','','', + ], + 'x241':[ + '','','','','','','','','','','','','','','','', + '','fan ','','','','','','','','','','','','','','', + '','','','','','ta ','','pan ','','','','','','','','Trong ', + 'Nhan ','','Can ','','','','','','','','','','','','','', + '','','','','','','','','','','yan ','','','','man ','', + '','','can ','','','','','','','','','','Veo ','','','', + '','','','men ','','','','','','','','','','','','', + '','','shuan ','','','','','','','','','','','','','', + '','cheng ','','','','','','','','','','','','Chi ','','', + '','','','','','','','','','','','','gua ','','xu ','', + '','','','Saap6','','','','','','','','','','','','', + '','','','','','','','','Tom ','','','','','','','', + '','','','','','','','','','','','','Kho ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','Say ','Phoi ','Tat ','','','','','Bep ','', + '','','Nhum ','','','','','','','','','','','','Ying ','', + ], + 'x242':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Lui ','', + 'Sot ','Ngut ','','','','','','he ','','','Cho ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','lao ','shao ','', + '','','','Tro ','','Tro ','Se ','Heo ','Ngun ','','','Toa ','Rang ','','','', + '','','','','','','','','fu ','','','kai ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Luoc ','','','','','','','','','','','','','', + 'Roi ','','','Tro ','Nhem ','','','','','Rom ','','Phoi ','Phoi ','Lom ','','', + 'Ben ','','','','','','la ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'zhu ','','','','','','Ranh ','Nau ','Khet ','Kho ','','Phoi ','Kho ','Choi ','Um ','', + ], + 'x243':[ + '','','su ','','','','','','','','','','','Hok ','','', + 'han ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','gan ','','','','','','', + '','','','Hay ','','','Ngot ','Nau ','','Ngun ','','','','','','', + '','Chong ','','shu ','','Jau ','','','','','','','zao ','','','', + 'Jit6','','','','Zhang ','','','','','','','','','','','', + '','','','','','','Loa ','','','','','','','','','', + '','','','','','','','','','','','','','Quac ','','', + '','','Phap ','','','Tat ','','','','','','Ram ','','','','', + '','','','','','','','zhu ','','','','','','','','', + '','Zuan ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Nhoi ','','Ho ','Thui ','Khet ','Thap ','Se ','','Rao ','Buot ','','','','', + '','chu ','Zhou ','','','','','','','','','','','','','', + ], + 'x244':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','Ham ','Nau ','','Soi ','','', + 'Luoc ','','','','','','','','','kai ','','','','','','', + '','','cuan ','','','','','','','','','','','','','', + '','','','xian ','','','','','Chang ','','','','','Hung ','','', + '','','','','','Xun ','','','','','','','','','','', + '','','','','','','','','','','','Bung ','Loe ','','','Sem ', + '','','','','','','','ye ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','Nung ','Nau ','','yao ','','Nhui ', + '','','Lom ','','','','Sem ','','','','','','','','','', + '','','','','Thap ','','','','','','','ta ','','','','', + '','','','','','','Ram ','','','','','','','','','', + '','','','Lo ','','','','','','','','','','','','', + '','','','','','','','','','Ben ','','','','','','', + '','','','','','','','','','','Vau ','','','','dao ','', + ], + 'x245':[ + '','','','','','','','','','','','ju ','','','','', + '','','','','','','','','','','shang ','Su ','','','','', + '','','','bao ','','','','','','','','','','','','Vuot ', + '','','','','','','','Danh ','','','','','','','','', + '','','','','','','','','','','shen ','','','','','', + '','','','','Cha ','','','','','','','','','','zhu ','', + '','','','','','','','','','','','','','Jiang ','','Jiang ', + '','','','','','','','diao ','','','','','','','','', + '','','','','','','zhan ','','','','','','','','','', + '','','die ','ze ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','he ','','','','ju ','','','','Lop ','','','','xiang ','','', + '','cu ','','','','','Mui ','','Sip ','','','','','','','pei ', + '','','','cheng ','','','','','','','','lian ','','','','', + '','','','','','','','','die ','','shu ','','','','','', + '','','Tam ','','','pu ','','','','Phuon ','','chan ','','','','', + ], + 'x246':[ + 'dao ','','','','','','','','','','','Nga ','','','','', + '','','','Nanh ','hu ','','','','','','','chun ','','','','', + 'tian ','','','chen ','','','','','','','','','','','','', + '','','zhuang ','','','hu ','','shu ','','','','','','','','', + '','','','','','bai ','','','','','','','','','','qu ', + '','','xie ','','zhao ','','','','','','','tu ','','','','', + '','','','','','','','','','','','','','','Ngau ','', + '','','','','Caau ','','','','','','','','','','','', + '','','','','','mu ','','Nghe ','','','die ','','','','yu ','', + '','','','','','','','','','','du ','','','','','', + '','du ','','','mei ','','Co ','Sao ','','','','','','','','xiu ', + '','','','','','bu ','','','','','','','','','','', + '','','','','','','','Chan ','','','','','','','','', + '','','','','','','','','','','','','','su ','Nghe ','', + 'Trau ','','ceng ','ta ','','','jue ','xun ','','','','','','qun ','','', + '','','','','','','','','','','','','','','','', + ], + 'x247':[ + '','','','','huai ','','','zhan ','','','','','','','','', + '','','','','ju ','ba ','lei ','','','','','','','','','', + '','','','','zhe ','','','','','','','','San ','Tu ','','Cop ', + '','','','','','21335.010,yan ','','hu ','','yu ','','','','','','', + '','','mu ','','','','','','','','','','','','','', + 'hao ','Muop ','na ','','','','','','hu ','','','','','','Chuot ','', + '','','','','','','','bao ','','','','','','','lu ','', + '','','','','','','','','','Chu ','','','','','','', + '','','','','','','','','','shu ','','','','','','', + '','','','San ','Thac ','Tay ','','','','','','zang ','','','yu ','', + 'cha ','xie ','','','','','Moi ','Khon ','','','','','','','','', + 'qiu ','','hu ','zai ','jue ','','han ','','','','','Hum ','','','','an ', + 'zao ','','','sha ','','xian ','','','','an ','','','','zhe ','jue ','', + '','','','','','','','','lu ','','','','','xia ','xiao ','', + '','','dun ','','','','','','','','tu ','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x248':[ + '','','','','Ga ','Voi ','','ge ','','','','Trau ','','','','', + 'ta ','Lau ','','','','','','','','','su ','','','','','ta ', + '','','','','','','','','','','fu ','','','','','', + 'Gau ','','','','','','','','','','','','','cu ','','', + '','','','su ','','','','','','','','','','','','', + '','','','','','','','','','','','Nanh ','','','','huan ', + '','','','','','','','','','','','','','','Ran ','', + '','','','','','','xu ','','','','','','','','','', + '','huan ','su ','','','','','Vuot ','San ','','lu ','','','','','', + '','','','ju ,qu','Nhen ','Dou ','','','su ','','','','','','','ze ', + '','','','','','','','','','','Lie ','','','','','', + '','','','','','ai ','','','','','xie ','','','Nhat ','','', + '','','','','Beo ','','','','','','','','xiao ','','','', + '','xie ','','','','','','','','','','','','','','', + '','Doc ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x249':[ + '','','','','','','','','','','da ','','','','','', + 'su ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','wai ','','','','', + 'Vua ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','su ','','','liu ','','','','','','','','', + '','','','','','','','','','','','','','Xa ','','', + 'mao ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','Cung ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','yu ','Cong ','','','','','', + '','','','jian ','','','','','','wan ','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x24a':[ + '','','','','','','','','','','','','','lu ','qu ','', + '','','','','','','hu ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','zhuan ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','hao ','xiang ','','','hao ','','', + '','dian ,tian','ge ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','chan ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','qia ','jiao ','','','','','','','','Dua ', + ], + 'x24b':[ + 'Dua ','','','','','','','','Hau ','','','','','','','', + '','','','','','','','','','','','Lu ','','yan ','','', + '','','','','','','wa ','zu ','fan ','','','','','','','', + '','xu ','','','','','','na ','Sanh ','','','','','','','', + '','','','','','','','','diao ','','','','','fan ','','', + '','wu ','','','','','','','','','','','','','','fu ', + 'na ','','','','','','','','','','','','','','','', + '','hu ','','','su ','','','','','','','','','xu ','','', + '','','','Ang ','','','','','','','','','','','lei ','heng ', + '','Be ','','','','','','Lo ','','','lei ','','shan ','','','', + 'Muong ','','','','','','','lu ','Lung ','','jun ','','','Chan ','','xie ', + '','zhe ','','','','','','liu ','lei ','','','','dai ','','Ngot ','Ngot ', + '','','','','','','Ngon ','','','','','','','','','', + '','Lam ','','','','','','','','','','','','','','', + '','','','','','','','','Song ','Song ','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x24c':[ + '','','','','','','','','','','','','','','','', + '','pu ','','','','','','','','','','','','','','hang ', + '','','','','','','zha ','','','','','','chao ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','na ','na ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','diao ','','','','','','', + '','','','','','','','xie ','','','','','','fu ','','', + '','','Duoi ','','','','','','','','','','Ruong ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','juan ','','','','','','','', + 'mao ','','','','','','','','','','','','','','','', + '','','','','','cha ','Trai ','Trai ','','han ','','','','','','', + '','','','','','yu ','','','','','','','','','','', + '','','Trong ','','','','','','Roc ','','','','','','','zhu ', + 'Ve ','Ruong ','','','lei ','','','','','','','','','Ruong ','','', + ], + 'x24d':[ + '','','','','','','','','','','','','','die ','','', + '','','','','','','','','','','','','','','','', + '','','','','','Ngat ','','','','','','','','Bot ','','huan ', + '','du ','','','','','','','','','','','','','','', + '','','','','','','','','','','du ','','','','','', + 'wu ','','wen ','','','','','','','','To ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','Si ','','','qia ','','','','hai ','','', + '','','','','','','','','Tay ','','','','','','Chau ','', + '','Nhan ','Ben ','','','tun ','fu ','','','','','','zhuang ','','','', + '','','','','','','','','','','','','','','du ','', + '','chuan ','','','','','','','Naa ','Guoc ','','Nghen ','Mang ','Mut ','','', + '','','fei ','jian ','','','','Wak6','','','','','','','','', + '','jiu ','','','lun ','','','','dao ','de ','','','','','','la ', + '','','ju ','','','','','','','','Mang ','Cek ','','','','Loet ', + '','','','Nhom ','','','Buou ','','','wai ','','','','','','', + ], + 'x24e':[ + '','','','','','','','','','','dai ','','','','','', + '','fu ','Ngung ','','','','','fu ','','','','','','','','', + '','','','','','','','Hoen ','','','','yun ','','','su ','', + '','','','','','bu ','','qun ','','','','Naa ','','','','', + '','','','','','','','','','','','jue ','','','','', + 'Lit ','','','','','','Hen ','','Nhoc ','Choc ','','chen ','','','','', + '','','','hu ','teng ','','','','lian ','','','','','','','', + '','','','','','','','','','','','','Buou ','Not ','','Ngo ', + '','','','','','','','bian ','','','','','','','','', + '','','','Bie ','','','','','','','','','','','','', + '','','','','','','','Zang ','','','shan ','','','Buot ','Gua ','Mun ', + 'Khom ','','','','Buou ','','','','','','','juan ','lu ','','ao ','', + '','','','','','','','','','','','','','','Cum ','', + 'Hom ','','Toi ','','','','','','','','','','','','','', + '','','ai ','','','','','','','','','Nhoi ','','','','', + '','lu ','','','','','bian ','','','','','','','','','', + ], + 'x24f':[ + '','meng ','','','','','','','','','','chan ','','','','', + 'guan ,huan','','','','','','','jue ','lei ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','ju ','','','','','Dang ','','','','','','','', + '','','','','','huan ','','','','','','','','','','', + '','','','er ','','huan ','','Nguoi ','','','','','','','','', + '','','','chang ','','','','','','','','','','','','', + '','zu ','','','','Phau ','','','Trang ','bai ','lu ','','','','','nian ', + '','','','','zhu ','hu ','','','','','','','','','','', + '','','','Tram ','Vang ','','','','','','','miao ','','','','Ho ', + '','','','','','','','','','','','yao ','','','','', + 'Nguoi ','','','','','bie ','','','','','','','','','','', + '','','Saai ','','cun ','','','','','','','','','','Pi ','nan ', + '','','','','','','','wa ','','','','','','','','xun ', + '','','','cheng ','','','Da ','han ','xiao ','','Zaap ','','','','','', + 'Trong ','','','','lu ','','','','','','','','','ta ','','', + ], + 'x250':[ + '','du ','','','','','','','','','','','Giay ','','','', + '','','','liu ','lu ','','','','','','','','','','','', + '','','','xue ,qiao','','la ','','','','','','','Jim ','','','', + 'la ','','du ','Mo ','','lu ','','','','','','','','','xiang ','', + '','','jie ','mang ','','','','','','','','','','','','', + '','','Ngaau ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','diao ','', + '','','','','','','','','','','','','','','','', + '','Jim ','','ju ','','','','','','Trom ','','tu ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','hu ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'cha ','','','','','','','','','','','','','','','', + '','Mam ','','','qu ','','','','','','Mam ','Mam ','','','','', + '','','','','','','','','Vuc ','','','','','','','', + '','Nhap ','','','','fan ','','','','chuan ','yao ','','','','du ','', + ], + 'x251':[ + '','meng ','','','','','','','mu ','','','','','','Cik ','', + '','fu ','','','','','','','','','','','','mian ','','', + '','','','','','','','','','','','Gap6','','','Nham ','Ngom ', + 'Nhon ','','mie ','','Xue ','xu ,yu','','','','bao ','','','','','','', + '','','','Nhon ','','','','','Laap ','','','','','','','', + '','dian ','fan ','','','','','','','','','','','','','Ngaau ', + 'Hau ','er ','','','','','','','','','','','','','','', + '','','Chau ','','','wei ','','','','','xu ','','','','Zong ','', + 'Giuong ','','','Nho ','','','','','','yu ','','','jue ','','','', + '','','','','','','','','','','','xu ','wang ','','juan ','', + '','','','','','xie ','liu ','','','','','','','','','', + '','','nao ','','','','wan ','jiu ','','Ngop ','Dau ','Ru ','Le ','','','Quau ', + 'Mang ','Tro ','Bet ','','','','','','Nhon ','','','','han ,qia','','','xu ', + '','','jie ','','','','','','jun ','','','','','','dian ','', + '','','','Gwat6','','','','','','','','','','','','mai ', + '','','','','','','Him ','','','','','Tro ','','','','xu ', + ], + 'x252':[ + '','','','','chuang ','','mao ','','','huan ','sha ','','','','','kuang ', + '','','','','','','die ','','','la ','','lu ','','','','Sou ', + '','','','','','','','','','','','','','','leng ','', + '','','Ngap ','Chot ','Nguoc ','Nhon ','Nom ','','','','','','','','','', + 'guan ','ju ','','nai ','','ge ','','','','','ma ','teng ','','','','', + '','','','','','','','','','','','','chen ','','','', + '','','','','','','','','','','','','Let ','','Soc ','', + 'han ,qia','','','','','Ma ','lu ','','','','die ','','','','','', + 'Xam ','','','','','','','','','','xu ','','Caau ','','','', + '','','','chan ','','','','','Ghe ','Zong ','','','','Chop ','Quac ','Nhan ', + '','','','','Nguoi ','','Mu ','','','','','guan ','','zun ','','xie ', + '','','','','Toet ','','','','','','','','','','','', + '','','','','','','','Caang ','','','','','Sa ','','','', + '','','Tre ','','','Trom ','','','Saau ','','','','','','','Nguoi ', + '','','','jia ','','','','','','','','','','','','', + '','','Lem ','Coi ','Ngam ','Him ','Lam ','','Soi ','','','','','','','', + ], + 'x253':[ + 'Xet ','','','','','','','','Trom ','','pan ','','','','','', + 'liu ','','','','','','','','','','','Lai6','','','','', + '','','','','','Khoe ','Len ','','','','','','','xuan ','','meng ', + 'wei ','42521.120,meng ','','','','','','','Dim ','Ngam ','yao ','','','','','', + '','','','','','','','','','','','','','Lom ','','', + '','','Cham ','','lei ','','','','Nheo ','','bian ','Ngom ','','','','', + '','','','hao ','','','','','','','zhai ','','','','','', + '','ze ','na ','','','','','','','','','','','','','', + '','','','','','','kai ','','wu ','','','','','ze ','','', + 'yu ','zan ','','','','xu ','','xu ','','','','','','','','', + '','','cuan ','cuan ','cuan ','','','','','','','','','','','', + '','','','','','','','','qia ','','tiao ','','','','','', + '','','','','','','','huan ','','','','','','','','', + '','','wu ','','','','','','jue ','','','','','ya ','','', + '','','','','kua ','','','','','','','','','','an ','zhe ', + '','','','','','','','','','','','','','','','Van ', + ], + 'x254':[ + '','pu ','','','','','Van ','Ngan ','So ','Ngan ','','','','Ngan ','','Coc ', + '','','Cut ','','Van ','ya ','','','Shi ','','','','','','Mong ','', + '','','','','','','','','','yun ','','','','','','', + '','','','','','','','','','','','','','zhe ','','hu ', + '','','Chai ','','','','','die ','','','','guai ','','','','', + '','ao ','','','','','','','','','','','','','','', + '','','bu ','','','Sinh ','','','','','Nao ','','','','','du ', + 'guai ','','Ran ','','','','Loi ','','','','','','dian ','','','', + 'wu ','','','','','','','','','','','','','','','', + '','','','','','','','','xun ','','','','','','','', + '','','','','','','','ya ','lu ','','','','','chu ','','', + '','','','kang ','','','hua ','','','','','','','','','', + '','','','','Mai ','','','','','Sanh ','','','','du ','','', + 'jie ','','xian ,kan','','','','','','','','','','','','','', + '','','','','','','','','','','','','dao ','','','', + '','','','','Mai ','','','Canh ','','','','','','','','Tuo ', + ], + 'x255':[ + 'Gwang ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','yu ','','','','','','','','','','','','','', + '','shan ','','','','Ji ','','','','','','','','','','Ham ', + '','','','','Mai ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','zhe ','','','','','','','','','','','','', + '','','jue ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','la ','','', + '','','Quanh ','','','','','','','','','','','','','', + '','','','','','','','','zao ','Cuoi ','','','','','','', + '','','','','','','','','','','','','','','','du ', + '','','','','','','','','','','','','','','','', + '','','','ta ','','','','','','','dao ','','Chen ','','','', + '','','','','','','','','Nen ','','','qu ','','ca ','','', + '','','','','','xiang ','','','','','lan ','','','','','', + ], + 'x256':[ + '','','','','yu ','','','','','','jiao ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','fu ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Rung ','','','','','','','','','','','','', + '','','','xun ','','','ru ','','','Lay ','','','','','','', + '','','','','','','','','','','','','','','','yu ', + '','','jun ','','','','','','','','lu ','','','','','', + '','','','','','','','','','','','','','','','', + 'zhun ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','liu ','','','','','','','','','','', + '','nu ','','','','','','','','','','','','feng ','lu ','', + '','','','','','zhuan ','','zhe ','','','lu ','','','','','jue ', + 'liao ','','','','','','','','','','','','','','','', + ], + 'x257':[ + '','','','','','','','','','','','','Ao ','','','', + '','','Yan ','','','','','','','zan ','','','','','','', + '','','','','','Yi ','','','','','','','','','jun ','', + '','','','','','','','','','','','','','','','', + 'she ','','','','wan ','','','','','','','','','','','', + '','','gua ','','jie ','','he ,xie','','','','','','','','','du ', + '','','Li ','','','jie ','','ba ','yu ','','','','','','','', + '','','','','','','','','he ','','','','','Cay ','du ,zha','', + '','','','','he ','','','','','','','','','he ','','zhu ', + '','','','','','','Giong ','','zun ','','ru ','Duo ','jiang ','','','', + '','','','','','','','heng ','','','','','','','','zu ', + '','','','','ku ','','','','','','','','','','','', + '','','','he ','','','','','','','','','','','','', + '','','','','','','','','','','chang ','','','','','', + '','','','','','','','','','','mao ','','','','','', + '','','','','','','','','','Lui ','','','Bap ','','','', + ], + 'x258':[ + '','','','','','huan ','','','','','','','','','','', + '','','','','','','','','','','','','yang ','','','', + '','','','','','','','','','','','','Trau ','Giong ','Rom ','Rom ', + '','','','','chang ','','','liu ','','jie ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','jun ','jiao ','','','','','','','','','','','', + '','','','','Ji ','','','','','','','','','ai ','','', + '','','','Nanh ','Mam ','','','','','','','','','','zun ','', + 'Cau ','','','','','','','','','','','','','','','hu ', + '','','','','','','','','','','','','','','','', + '','','cheng ','','','','kuai ','','ge ','xie ','','jie ','','','','', + '','','','','','','zu ','','pu ','','','','','','','', + '','','','','','','','','','','','meng ','','','','xiang ', + '','','','','lu ','','','','','','','','','','','', + '','','','','','','','','mu ','ran ','','','','','','', + ], + 'x259':[ + '','','','','','','','','','','','zhe ','','','','', + '','','','','','','','','jue ','','','','','','','', + '','','','','','','ai ','','nu ','','','','','','','', + '','','','','','mian ','','','','','','','','','','', + '','','','','','Lung ','','','','','','','','','','', + '','','','','','','','','','','','','','','','wa ', + '','','','','','','','','','','','','','','','', + '','cheng ','','','','yang ','','','','liu ','','','','qiu ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','fu ','','','','','','qia ','dian ', + '','','jiao ','','','','','','','','','','','','','', + '','','','','','','xian ','','','','','','','','','', + '','','','','','','','','','','','','','','Hang ','', + '','','','','','liu ','','','','','','','','','','', + '','','','tu ','','','','','','Nup ','','','','','zhe ','', + 'hua ','','','','','','','fu ','','Tam ','','qu ','','','','', + ], + 'x25a':[ + '','','','','','','','','','','','','liu ','fu ','dan ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Trong ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','Hoam ','','Chui ','','','','','','', + '','','','','','','','','','','','','','ca ','','', + '','','','zhu ','hai ','','','','','','','','','','','', + '','','Hai ','','','','','','','','','','','','','', + '','','','','','','','','','','','fu ','','','','', + '','','','','','','','','','','fu ','','','Trong ','Trong ','', + '','','','','','','','','','','','','','','','', + '','cu ','','','pang ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','dun ','','','', + 'lu ','Deon6','','','','','','','','chen ','','','huang ','shi ','','', + ], + 'x25b':[ + '','','','','','','','','','','','','','','','', + '','','','yao ','','','','','','ju ','','','','','','', + '','','','','','','','','Khau ','Nia ','','','','','Giang ','Kao ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Mang ','Mau ', + '','qiu ','dun ','','','','','','','','mang ','','','miao ','yuan ','', + 'wu ','','','','','','','','','','','','fei ','','meng ','', + '','','','','','','Mang ','','','','','','','','','', + '','','','','','','','Buong ','Hum ','Bu ','','','','','','', + '','','','','','hang ','','ju ','nian ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','Manh ','Tre ','Mui ','','', + '','','Toi ','Trum ','','dang ','du ','','ye ','','','','','','','pai ', + '','','','','','','jian ,sha','','','','Trau ','','','','yu ','', + '','','','','','','','','zhu ','','','','','','','', + ], + 'x25c':[ + '','','','','','','','','','','Thap ','','','','','', + '','','','','','','','','','','','fu ','','','','', + '','','shan ','liu ','','','','','','','hu ','','','','','', + '','','','xian ','','','','','','','','mu ','','','zhai ','', + '','','nu ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Ro ','','','','Ghi ','Gianh ','','', + '','','','','','','','','','','','','','juan ','','', + '','','','','dan ','','','dan ','','hu ','','','','','lu ','chuan ', + 'wu ','','','','','','','du ','','','shuang ','fu ','ju ','','','diao ', + 'wang ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','fu ','','','','','','xun ','','', + 'Khay ','','','','','','bu ','','','','','','','','','', + '','fen ','dian ','','','','','','','','suan ','','an ','','','', + '','','du ','','','','','','dan ','','','','','','','', + ], + 'x25d':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','Thung ','Mui ','','','','','','','', + '','','','','','','','','ai ','ge ','ju ','tun ,dian','','qia ','','', + '','jian ','','','','suan ','','','','','','qiang ','','','','', + '','','','','','','','','','','','','','','','dian ', + '','','','','','','Toi ','Hom ','Ray ','','Lak6','Nong ','','','jie ','zhu ', + '','','','','zhao ','','','','','','','','','','','sa ', + '','','','','','','','','','','','','','','','Mung ', + 'Thung ','','Gay ','','','liu ','','','','','','','','','','', + '','','','','','','','','','','','','hu ','','','', + '','','','','','','','','','','','','','','Toi ','', + '','','','','','','','','','','die ','','','','','', + '','ban ','','','','','hu ','','','','','','','','','', + '','','','','yu ','die ','','','','','','','','','yu ','', + '','','','','','','','','','','','','','','','', + '','fu ','','','','','','','','','Mo ','May ','cu ','','','', + ], + 'x25e':[ + '','Nan ','','','','','','','dang ','','','','','','','', + '','','','','','','','','','','','','','Trum ','','', + '','','','shan ','yu ','','','','','','yu ','','','','','', + '','','','','','tun ','','','','','','','','','','', + 'Tam ','','','','','','','fan ','','Nap6','','','','zhu ','','', + '','','','','yu ','','','','','','','can ','','','','', + '','','','','','','','','','','','','','','','', + 'Lau ','','','','bu ','chu ','','liu ','Bot ','','','','','','','', + '','','','','','','','','','','ge ','','','','','', + '','Tam ','','Lo ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','Com ','','','','', + '','','','','','','','xian ','','he ','','','','','','', + '','','','','','','','','','','Nam ','','','','bu ','No6', + '','May ','','','','','sa ','','','mian ','','','','','','', + '','','','','xia ','','','','Bun ','','','','','','','', + ], + 'x25f':[ + 'zu ','','','ze ','','','','','','','','','','','','', + '','','','','','Lep ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','xiao ','','','Thung ','','','','','','','','','Com ','','xian ', + 'jian ','','','','Men ','','','','Miao ','','','','','','','', + '','Phan ','','','Xia ','','','','','','','','niang ','','','', + '','','','','','','he ','','lian ','','','','','','','', + '','','','Men ','','zhu ','','','','','','reng ','jie ','','','', + '','','','','','wu ','','','','','','cu ','','','','', + '','','','','','','','fu ','hu ','','','','','','jue ','diao ', + '','','','','','','','','','','','','','','Buoc ','', + '','Vuong ','Tim ','na ','','','','','','','','','','','','', + '','','','','','','','Giay ','','','','','','dai ','','', + '','','','','Khau ','','','','','','','','','','','pai ', + '','','','','','','','chao ','','','','','','','','', + ], + 'x260':[ + '','','','','','','','Jing ','','','Dai ','','','','','Thua ', + '','','','','','','Kep ','','','','','','zhuang ','','','', + 'liu ','','','','','','','','No ','','','','','','','', + '','','','','','','','','mao ','Thun ','Xe ','Cui ','Noi ','Keo ','Rang ','', + 'Boi ','Nuoc ','','','','','zhuan ,juan,shuan','nian ','','','hua ','','','','','yan ', + 'jue ','','','','','','','','','','','','die ','','','', + '','','','Go ','','','','','','','','','','','','', + '','','','','','','','','','Ro ','','','May ','Vuong ','','', + '','','','','','','','','','','fu ','','','','','', + '','','','','wan ','','','Sok ','','','','The ','','','','', + '','','','','','Dam ','','','','','','','','','','', + '','','','','','','','','','','','Luot ','','','','Buoc ', + '','','','','','','','','','','','','','','','', + 'Tao ','','','liu ','he ','','','','','','','','','','','', + '','','','','mu ','','','','','','','','','','Gai ','', + '','','','','','','','','','','','','','','','', + ], + 'x261':[ + '','Thun ','Dai ','','Quan ','','May ','','','','','','Chap ','','','', + '','','','Xau ','die ','','','','','','','','','','Van ','', + 'Nut ','','','Cuon ','','','','','','','','','','','','', + '','','','','Chai ','','','','Xung ','','Rang ','Quan ','','qu ','','', + 'xun ','','','','zhe ','','dian ','','','','','','','','','', + '','xun ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Tan ','', + '','Thua ','','','','','','','','','','','','ju ','','yun ', + '','','','','','','','','','','','lai ','','','','', + '','','','','','','','','','','Neo ','','','','wu ','Mung ', + '','','','','','','','','','','','','','','','Ban ', + '','','','','','','','','','','','la ','','','','', + '','','','','','','','','','','','','','','','', + '','','Roi ','','','','','','','','','la ','','','','', + '','','','','','','','','','','','','yao ','','Chung ','', + '','','','','','','','','he ','','','','','','','', + ], + 'x262':[ + '','','Nhau ','nang ','','die ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','yu ','','','','','','','','','','','','', + '','','','','','','','','yu ','','','','','','','', + '','','','','','','Cha ','','','liu ','','','','','','', + '','','','','','','','','Caang ','bian ','','','','','','ya ', + '','','','','','','','ya ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','hu ','cen ','','','','','','','','','','','','', + 'ju ','','','','','','','','hu ','','Bon ','Tu ','','','','', + '','','','','','','fu ','hu ','','','','','','','','', + '','','','','','','','','','','','','','meng ','fu ','liu ', + '','','','','','xie ','','','xian ','','','','','','','', + '','','','','lu ','','','','','','','','','','','', + '','','yu ','han ','','','Ra ','','','','dan ','','','','','yu ', + '','','','','','','','','','','','','','','','', + ], + 'x263':[ + '','','','','','','','','','su ','su ','','','','','', + '','','liao ','','','lu ','','','','','','','','','','lu ', + '','','','','','','huan ','','','','','','','','','', + '','','','','','','','du ','','','','','','','','', + 'nan ','','','','','quan ','','','','','','','','','','fen ', + '','','ta ','tun ','','','','','','','','','','','','', + '','','','','','','','','','Gu ','fen ','','','','','', + '','','','','','','','','shan ','','','','','','','', + '','','','','su ','','','chuan ','','','','','','','','', + '','','jie ','','','','','','yu ','','','Guong ','chuan ','','','', + '','Xinh ','','','','','wu ','','','','','','Tanh ','fu ','','', + 'gu ','','','','','','','','','','','','','','','', + 'ren ','','','','','jue ','','','','','','','','','','', + '','','','Bon ','','du ','','hu ','','','','','yu ','','','', + '','','mai ','','','','','','huai ','','','','','','','', + '','','','','','','','','','','','yu ,yu','','','','', + ], + 'x264':[ + '','','','','','','','Taap ','Fen ','','','','','','','', + '','','','','','','','','','','','qu ,yu','','','','', + '','fu ','','','hai ','','','','','','','','','','','', + 'chai ','','','','','','','','','','','','','','','', + '','','','','','','','ta ','','','','zu ','','xu ','yan ','chai ', + '','','','','','','','','','','','','ge ','','','', + '','','','','','','','','','','','','','','','', + '','','ta ','','','','ta ','','','fu ','','','','','liu ','', + '','','','','','han ','','','','','','','','','','he ', + '','yu ','','','','','','','','','','','Zin ','','','', + '','','','','','','la ','','','','','','','','','', + 'tai ','','','','','Khu ','shu ','Bou ','','','dao ','','','','','', + '','','','','','Gia ','','Khu ','','Lu ','','wang ','','','nai ','', + 'jue ','','','','','','','','','','','','','','','', + '','Ma ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x265':[ + '','','','','','tu ','','','ze ','','','','','fu ','','', + '','','','','','','','','','Cay ','','','','','','', + 'pai ','','','','','','kuai ','','','','','','qu ','','zhe ','sha ', + '','','','','','','','','','nai ','','','','','','tian ', + '','','','','','','ye ','','','','','','','','','sao ', + '','','Zim ','xu ','','','','','','qu ','','','','','','', + '','','','','','','','','','','','','','','','', + 'duo ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','hua ','','', + '','Nghe ','','','','','','','','','','','','','','', + '','','','','','','','yan ','','','','','','','','', + '','','','','','','','','','','','Tai ','hu ','','','Dap ', + '','tian ','','','','','','','','','','','','ai ','','Lang ', + 'ai ','zhe ','','lu ','','','','zhe ','','','','','','','Ghe ','', + '','','','hu ','','','','','','','','','','','','', + '','','','','','','','','','','','ju ','','','','', + ], + 'x266':[ + '','','','','','','','','','','','','','wai ,wa','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','Paa ','','','','','','', + '','','','','','','','','','','','','','','','', + 'pan ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Moc ','Mao ','Hong ','Tim ','','','','','','','','ju ','dai ', + '','','','','zhu ','Wan ','Gu ','','','ban ','','mai ','Ci ','','','', + '','','','','','','','','','','','','','','','', + '','','','Ping ','','','Zaap ','','','','','','','','','', + '','','','hen ','','','','','','','','xie ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','Ruot ','','','ku ', + 'na ','','','','xuan ','','','','he ','','Nam6','','Ham ','','','', + '','','','','','','','','','','','','','','','', + '','','jue ','','','','','','','','Bet ','Thon ','','','Nuc ','Mang ', + ], + 'x267':[ + '','','','xu ','','','','','','','','','','pang ','','', + '','','','','','','Ngaa6','','Vu ','','','','','','Ron ','', + '','','','','','','','','','','','','','','','', + '','','','','tun ','','','','','','','','','','','', + '','','','','Rang ','','','','Ngac ','','','Mun ','Mep ','','Phop ','', + '','','','','','','','','','','','','','huan ','','', + '','Jim ','','','ban ','','','','','','','','tu ','','','', + '','','','xu ','','','','','','','','','','','','', + '','Tuoi ','','','','','','','','','','','','','Nghen ','', + '','','','Phay ','','','','','','','','','','','','', + '','','Tao ','Sao ','','zhe ','','','','','','sai ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','Bo ','Zin ','Gay ','Suoi ','Khu ', + '','','','tun ','','','','Nem ','','','','','ze ','','','', + 'cu ','','','','Xiu ','','','','','','','','','','','', + '','','hun ','ju ','','','Nem ','','','','','','','','Khu ','', + ], + 'x268':[ + '','cu ','','','','xun ','Sun ','ceng ','','','','','','','','', + '','','jue ','','','','pao ','','Vai ','','','','','','','', + '','','jiu ','zhe ','','','shu ','','','','','','','','','', + '','Phet ','','','','Roi ','Seo ','','','','','','','','','sa ', + '','','','','du ','','Fat ','','','','','Ron ','','','','', + '','','','','','','','','','','','','','','Ngam ','Lung ', + 'Song ','','Rau ','','','','','','san ','','','','','yu ','','', + '','yao ,shao','','','','hun ','Lom ','','','','','','','','','', + '','','','','','','','','','','Pok ','','Duk6','','guang ','', + '','','','Mak6','','','','','','','','','','','','', + 'Rang ','','','','','','','meng ','','','','','','','','', + '','','','Vai ','Lot ','','','','','','','','','','','', + '','','','','lei ','','','Lo ','','','','','','','Nan ','', + '','','qu ','','','','','Nhau ','','Nang ','','','','','','', + '','','','','','','','','','','','','','','','', + '','Zak ','','','','','','','lian ','','','','','','','', + ], + 'x269':[ + '','','','','','','','','','','ru ','yao ','','','Gao ','', + '','','','','','','','','','wa ','','','','','','', + '','','','','','','Hot ','zhai ','','','','','hai ','','Thoi ','Kham ', + '','','','','','','','','','','','','','','','', + '','wu ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','Xue ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','fen ','','','','','','','','Kyo ','','xiao ','','','','', + '','','cheng ','','','','','','','yu ','','yu ','','','','', + '','','','','','','','','','','','','','juan ,fan','','', + '','','','Lau ','','Weng ','','','','','','','','','','', + '','','','','','','tian ','','hu ','','','ta ','','','ta ','ta ', + '','','','','','ta ','','','','','','','huai ','','','', + '','ta ','Loe ','','','hua ','','','zhuan ','','Laai ','','','','','', + ], + 'x26a':[ + '','','Mua ','','','','','','fu ','wu ','','fu ','','','ta ','', + '','Chai ','','','','','chao ','','','','','','Qua ','','','', + '','fu ','','','','','jia ','','','','','','','','','', + '','','','wu ','','','','','','','','Khoang ','','','','', + '','','','','','','','','','','','bai ','','','','', + '','','','','','','','','','','Mui ','Gu ','','','yu ','', + '','fu ','xian ','','','','','','','','','','','','','', + '','sheng ','','','','jian ','','','','','','','','','','sha ', + '','','','','','','','lu ','Ao ','','','','','','','Thong ', + '','','','','dun ','','','','jue ','ta ','zun ','','','teng ','','', + 'hua ','','','','','','','','','','peng ','','','','','', + '','','','','','Ghe ','','','','','','Khoang ','Ghe ','','','', + 'teng ','','','','','','','','','','','','','','','', + '','','','','','','','','','ba ','','','','','','', + '','','','','','','','','','','wa ','','','','','xun ', + 'meng ','','','','','','','','','','','','','','','', + ], + 'x26b':[ + '','','wu ','zhe ','','','','','','','','','','','','', + '','','','','','','qiu ','','','','hu ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','zhu ','','','','','','','', + '','','','','','','','','hu ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','Tup ','','','Hung ','','','','','', + 'ru ','','','','','','','','','','','jiu ','','','','', + '','jiao ','','','','','','','','','','','','','','', + '','pu ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','Nen ','','','','','fu ','','','','','','', + '','','','','','xu ','','','','','','','','','','', + '','zao ','','','','','','','','','','','','','','', + '','','','cu ','','','','','','','xiao ','','Dua ','','','', + '','','','','','','','','','','','','','','','', + ], + 'x26c':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','fen ','','','','Ngon ', + '','','Nua ','','Lau ','','','','','','qiu ','','','dun ','','', + '','','','ye ','','','','','','','fu ','','','','','', + 'yu ','','yu ','yu ','Gu ','','','','','','','meng ','','','','', + '','','mu ','','Bei ','','Fu ','','','','','','xiao ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Nhai ','','','','','','','','','','','','','', + '','','','','','','','','','','','fu ','','','','wan ', + '','','','','','','','Lei6','','','','Rom ','','','Muop ','', + '','hao ,mao','','xie ','','','','','','','','','','','','', + 'nai ,na','','','fu ','du ','','','','','Tre ','','','','','bai ','', + '','','','xun ','','','','','','','','','he ','','','', + '','','','','','','meng ','','','','','','','juan ','ru ','', + ], + 'x26d':[ + '','','','','','','','','','hu ','','Mong ','jun ','she ','','', + '','','','','meng ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','Ke ','','','Nu ','','','','','', + '','','','hun ','','','','','','','','','zu ','','','', + '','','','','jie ','','','','','','','','jun ','','','', + '','','','','','','','','','','','shan ','','','','', + '','ta ','','','','','','','','heng ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Kou ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Chu ','','', + '','','','','','','qiang ','','','Bom ','','','','','','Mai ', + '','','','hu ','','','','hai ','ru ','meng ','','','','wu ','','', + ], + 'x26e':[ + '','','','','','','','','','qia ','','','','','','', + 'lu ','','','','','','','','','','','','','','','', + '','','','','','','','','','','pei ','','','','','', + '','fu ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','zhao ','','','','', + '','','','Thom ','','','Voi ','Bui ','','Nhai ','','Dam ','','','','', + '','','','','','','','du ','','','','','','','','', + '','','','','','','ju ','','','','','chuan ','Lao ','','','hu ', + '','','jie ','xiang ','','','','','xiang ','','','lang ','','','','', + '','','shuan ','','','chu ','','','','','','','','','','', + '','dan ','','','','sa ','','','','','','','','','','', + 'Zaau ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x26f':[ + '','','','Sang ','','','','','ju ','','leng ','lu ','','','','', + '','','','','','','','','','','Lum ','San ','San ','','Dua ','Khay ', + 'Sung ','','she ','','','','','sa ','','','mao ','qu ','','','','Zuk6', + '','juan ','','','','he ','','','','','','mei ','','','','', + '','','lu ','mian ','dian ','','','','','','Waa ','','','','lu ','fu ', + '','','zei ','','Om ','','','','','','','','dan ','','wan ','', + '','','','','','','','','','','','','','','','', + 'Tranh ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','sha ','','','','lu ','', + 'Dua ','','','','','','','','','dan ','','','','','','', + '','','','','','','jian ','lu ','','','','','','ta ','','', + 'chu ','fu ','','','','','dang ','','','','lu ','','','','','', + 'jie ','','','','','','lu ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x270':[ + '','','','','chang ','','meng ','','','','','','su ','','','Sung ', + '','Giong ','Non ','Ru ','','sa ','','','','','','','Sam ','','','', + '','zhan ','','','','','','','Lop ','','','','','','','', + '','chai ','','','','','','','','','xie ','','','','','', + '','','','xu ','','','','','','fan ','meng ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','Ghem ','','','','','','','','','','','', + '','zhan ','jian ','han ','dan ','','jian ','','','','','','','','','', + '','','','','hu ','','','','','','','meng ','ju ','','','', + '','meng ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','Dua ','','','','chu ', + '','','','','','','','','','','','','','','','', + 'yu ','','','','','','','','','','','','','','','', + '','','','','','','Muong ','Khoai ','','','','','','','','', + ], + 'x271':[ + '','','','','','','','','','','Han ','','','','','fu ', + '','','qu ','','','','','','','','','ju ','','','','', + '','','','','','','','','','','','','','','','', + '','','Mo ','','','','','','','','','','','','','', + '','','','','','','','','diao ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','Men ','Muong ','','', + 'hu ','','','','','','','','','','nang ','','','','','', + '','','','','Thuoc ','','','','','','','','','','','', + 'gan ','','','','','','','','','','','','','','','', + '','xu ','','lu ','','','','','','','','','','','','hu ', + '','','','','','','','','','','','','','','','', + '','','','','lu ','','','','zu ','','','','','','he ','', + '','','','','','','','','','','','','','shu ','','', + 'yao ','','','','','','','','','','','','','','he ','', + 'hu ','','','','','','','','','','','','hao ','','','zu ', + ], + 'x272':[ + '','','','','xia ','','','','','','','','ge ','','','', + '','ge ','','','','','ge ','','','','42573.210,zhu ','','teng ','ya ','','', + '','','','','','','','','','','','','','wu ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','tai ','','','','','','','','Trun ','Vat ','','','','','', + '','','xue ','yu ','fan ','','','','','bu ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Gwaai ','','dai ,de','','Buom ','Nhong ','','','','Vat ','', + 'Trut ','','','','','','','','ku ','','','qu ','','','','ru ', + '','','','','','xu ','','','','','','','he ','','','', + '','','','','','Gong ','Doe ','','','','','','','','','', + 'Chau ','','','','','','','','','','Saa ','','du ','Chet ','','', + '','','','kao ','','','','','','','','','','','','Moi ', + '','na ','','','','','Mei ','','','','','','','','','', + '','','','','','Cuong ','Mot ','','','','Chay ','','Nhong ','Mang ','','', + ], + 'x273':[ + '','','Bo ','','','','','Bang ','fu ','lu ','','','','lu ','','ta ', + '','','','Fu ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','Cua ','','','','','Ngai ','','','','Cua ', + '','','','shuai ','','jue ','','','','fan ','','','','','','', + 'jie ','','','','','','','','','jie ','yu ','','','','','feng ', + '','die ','','','lian ','hu ','','','','','','','','','','dian ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Chau ','','', + '','','','','','shan ','','','','','','','','','','', + '','','zu ','','zhe ','','','','','','','','','','','', + '','','xie ','xie ','','','','','','','','','','','','', + '','','','liu ','','','','','','','','','','','','', + '','','','','','jie ','','','','','','sha ','','','','Nhuc ', + 'Sam ','','','Bo ','Choi ','','','Nhuc ','','ai ','','','','','','zhu ', + ], + 'x274':[ + '','su ','','xie ','yu ,yu','Zeoi ','','','zu ','','','','','','','', + '','','su ','','','','Luon ','','','wu ','','','','','','', + '','','Hou ','','','','','','','','','','','','','', + 'du ','','','lu ','su ','','','','','','','','','','Bo ','Sung ', + '','Sam ','','Ngao ','','Vet ','Chang ','','','','','','','','','', + 'yu ','','Giun ','','dai ','','','','dang ','zu ','','','','chuan ','','', + 'du ','','','','','','xie ','zhe ','','','','sao ','','','','', + '','','','','','','','','','','','','','','','', + '','','fu ','','','Buom ','','Sau ','','Rua ','','Rom ','Rua ','Rua ','e ','', + '','','','','','','','','','fu ','','','lei ','','','', + '','','','','','','','','chai ','','','','','','','', + '','','','','','','','','','','','','','lei ','','zei ', + '','ai ','','','','','','','','','','','','Ban ','','', + '','','','','','','fei ','','','','','','','','','', + '','','','','','','','','','','','','','','','Ngoe ', + 'Sam ','','','','','','','','','','','','','','','', + ], + 'x275':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','ta ','','','','','','','','','du ','qiu ','','', + '','','','','chai ','','','','','','','','e ','','','', + '','','','','','','','','','','','','','','qu ','', + '','','','','','','','','','','Trai ','','','','','', + '','fu ','','','','','','chai ','zang ','','','','','','','', + '','','','','Naan ','','','','','','shuang ','','','','','', + '','','','','','','ta ','','','','','','','','','', + '','','','','','','','','','','fu ','','','','','', + '','','','','','','Moi ','','','','','','','','an ','', + '','','','','','','','','','','','','','','','xiang ', + '','','','','','','','','n ','','','san ','hu ','','zu ','', + '','','','','','','','Jiku ','','','','','','','','', + '','','','','','','','','','la ','yu ,qu','jue ','','','','', + '','shu ,yu','','','Jung ','','','Jutsu ','jian ','','','','','','','shuai ', + ], + 'x276':[ + '','','Chong ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','hu ','','','','','','','','','','','','','', + '','','','','','','','','','Taai ','','','','','','', + 'La ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','pu ','','che ','','', + '','','','','','','','53077.090,jian ','','','','','','zhan ','yuan ','', + '','','','','','','yu ','','','','','Lot ','','','','', + 'mu ','huan ','','','e ','Long6','','','','','','peng ','','','','', + '','','','','Tung ','','','','','','','','','','','', + 'Song ','','Xong ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','Trang ','Lun ','May ','','','','','','', + '','','','','du ','','','tu ','','','','','','','hu ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','Toi ','','','','','','','','', + ], + 'x277':[ + '','Sha ','','','','','','','','','','','','','','', + '','','','','','','Chan ','Mo ','','Xong ','','','','','','', + 'shuai ','','','','','','su ','','','','','','','','','', + '','','','','','','','','','','Bau ','','','','','', + '','','','jue ','','','','','','','','','','','','', + '','zhan ','heng ','','qu ','wei ','','','bao ','','','','','','Gei ','', + '','','','','','','','','Cheo ','Toang ','','','','','','', + '','','ju ','he ','','','','','','','','','','','','', + 'shu ','','','','','','','','','','','','','','','yu ', + '','meng ','hu ','','','','','','','','','','','','','', + '','','','','','','','','','jie ','La ','shu ','jie ','lei ','','', + 'zu ','','','','','','','','','','su ','','','','','', + '','','','xie ','','','','','','','','','','','','', + '','','','','','','','','nang ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x278':[ + '','','','','','','','','cha ','','mao ','','','','','', + '','','xian ','','','','','','','','','chan ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','gao ','','','', + '','','','','','','','','','','Thay ','','','','','', + '','jiu ','','','','','','','','','','','','','','', + '','yun ','','','','','','','','','','','','','','', + '','','','','lian ','','','','','','','','','','','', + '','','','','','','','','','','','lao ','','','','', + '','Don ','','','','','','','','','','','','Lai6','','', + '','','yao ','','','','','wei ','','','','','','','','', + '','','','','','','chu ','','','','','','','e ','','', + '','','','','','','','','Caau ','','','','qiao ','','','', + '','','ju ','','','qiu ','','','','','','','','','','', + '','','hun ','','','','','Dia ','','','','','','','','', + '','','','','','lun ','','','jue ','','','ju ','hu ','','','', + ], + 'x279':[ + '','','','','','','','','','','','','','','','', + '','ju ','','','','qiu ','','','','','','','','','','', + 'zhe ','','','','','','','','','','','','','Ba ','','', + '','','','','','','','','','Thoi ','','','jue ','','','', + '','','','Choi ','','','su ','','','','','','kuang ','','jue ','', + '','','','','Va ','','','','','','','','','','tan ','', + '','','','','','','','','','','','','','','','hu ', + '','fu ','','','yang ','','','ren ','','','Kwan ','','yun ','','','xun ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','pu ','', + 'Ngaak ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','Beng ', + 'Ngoa ','','','','wang ','','','','','','','','','','','', + '','','','xu ','','','','','','','','','','Ngaa6','','', + '','','','','','','','','','','','','','','','Khoang ', + '','','','','','','tu ','','bie ','','','zha ','','','','', + ], + 'x27a':[ + '','','','','','','','','','','Zaa6','','','','','', + '','','','','','','','','','','','','','','','', + '','chen ','','','','','','','','','','','','','','', + '','','','','','','','','','lu ','','','','','Tam ','', + '','','','','','yan ','','','','','','','','','','', + '','','','','','','','','','Daan ','','','','su ','','', + '','','','','','','','','','','','','','','','', + 'bian ','','la ','','','','qia ','','','','','','','','','', + '','','','','','nu ','','','','','','','','','','', + '','','','','','','','','','','','','','','he ,ge','', + '','','','','','','','','ma ','','','','','','','', + '','','','','','','','','','xia ','','','','','','', + '','','','','','','','','','','yu ','','','','','', + '','jie ','xia ','','','','','cha ','','','','yang ','','','','', + '','','wang ','','','','','','','','','','','','','', + '','','','','','','','','','','','','Mo ','','jiu ','', + ], + 'x27b':[ + '','hao ','','','','','','','','','','fa ','','','','', + '','','','','','','','','','','','','','','yun ','', + '','','','','','','','','Wai ','','gun ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','dan ','','','','','','','meng ','','','','','', + '','','','','teng ','','','','','','','','Leoi6','sa ','','', + '','','','','','','','','','','','','','','','', + '','','','he ','','','','','','','','','','shan ','','', + '','','','','','','','','','','','','','','','', + '','ta ','','','','','','liu ','','','','','','','','', + '','','','','','','','','','','','jue ','','','','', + '','fen ','','','','he ','','','','','zhan ','','tai ','qian ','','', + '','','','','Hang ','Hang ','','','','','','','','lao ','','', + '','','','','','','jun ','','','','','','','','','', + '','','','','','zai ','juan ','','','chu ','','','','','','', + 'kan ','','','','','Phong ','','','','','','','','','','', + ], + 'x27c':[ + '','','','','','','','yu ','wu ','','Tian ','','','','','', + '','','','','','','','Nanh ','','','','','','','','', + '','','','','','','','Shuu ','','','han ','chu ','','tun ','','', + '','','','','','','','','','na ','','','','','','ai ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','mai ','','','','lun ','jue ,jun','','', + '','','','','','','','','','','','','','','','', + '','','','huai ','','','','','','','','','','','','', + '','','','','','ceng ','','hu ','','','','ju ','sha ','meng ','','', + '','','','','','','','wei ','','','','','','','','', + '','','zhe ','','','hu ','','','','','','Cop ','','','','', + '','','','','','qu ','','','','','','','Beo ','','','', + '','','fu ','','','','','Cop ','','','','','','','wu ','pei ', + '','','','','','','','','Hum ','','','sha ','','zhao ','wei ','', + '','','','','','','','','','tuan ','','','mei ','','','', + '','','','','','','','','gu ','shao ','','','','','','', + ], + 'x27d':[ + '','','peng ','','','','','','','','huan ','Beo ','fu ','','biao ','', + '','','','','','biao ','','','','','guai ','','','','','', + '','','','','','pei ','','','','','Suo ','','','','','Me ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','Qua ', + 'pai ','','','','','','','','ai ','','','','','','','', + '','','','She ','','','','','','','','','','','','', + '','','','','Danh ','','','','','','yun ','','','xu ','','', + '','','','','cheng ','','','','','','','','','','','', + 'yu ','','','','','','','','','','','','','','','', + '','','','','','cha ','Faan ','ze ','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'fen ','xie ','','','','','','','','','','','','Xoe ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','shan ','','Mua ','','','','','','ju ','', + ], + 'x27e':[ + '','','','','','','','','','','','','','','','', + '','','','','','','Zhuan ','xue ','','','','','','','','', + '','','','','','','lan ','ju ','','xun ','zhan ','gun ','','','','', + '','','','','','','','','','','','Bui ','','','','chai ', + '','','','','','','','','reng ','','','Vay ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','Son ','','','xu ','','', + '','Tham ','hu ','gan ','','','','','','','','','','','hu ','', + 'Tham ','Tham ','','','','','','','','','','','','','','', + 'jue ','','zu ','','','','','','','','','','jiao ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','chu ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','xian ','','','','','ju ','','Mut6','','','','','','', + '','','','','','','','','','','','','','','','', + 'hu ,zao','qiu ','','fu ','lang ','sha ','','','','','','','','','','', + ], + 'x27f':[ + '','','','','','','','','','','','','','Lanh ','','', + '','xu ','','','leng ','','','fu ','','','','','cu ','','','', + '','','','','dao ','','','','jie ,jue','','','yu ','','','Tang ','shu ,yu', + '','','','','','','','','','','','','','','','', + '','','','','jie ','','','Day ','Day ','','','','','','','', + '','','Cau ','','','','','','','','','','','','','jie ', + '','','','','','lu ','','chu ','','','','lian ','','','','', + '','','','','','','e ','su ','Jue ','','','ju ','','','','', + '','','','','','','xuan ','','','','','','Tron ','','','', + 'jiao ','','','','','','','','','','yu ','','','xun ','','', + 'xun ','','','ju ','','du ','','','','xun ,xuan','','','','','','jie ', + '','qu ','','','','jue ','','','','','','jiu ','','','','Treo ', + '','','','','','','','','','ku ,wu','','ku ','zha ','','','ba ', + 'Chen ','Nhac ','Dam6','hu ','nu ','e ','','','','','','','','','','', + '','','','','','bie ','','','','ge ','','Dau ','','','','', + '','','','','','','','yu ','','Mau ','Xoat ','ju ','','','','', + ], + 'x280':[ + '','','','','','','','','Buoc ','','','','','Dung ','Lop ','', + 'Rong ','','','','','','hai ','','','','','cun ','','','','', + '','','','Kei ','Choi ','','','','','','','','zai ','','','', + 'Bang ','','','','xun ','','','','','','','','','','','', + '','xuan ','xie ','','han ','','','tun ','Gaang ','','cen ','','','Ren ','Choanh ','', + '','','','','','','','','','','','','','Buot ','','', + '','Noi ','','','','','','Noi ','Cuong ','','Dau ','','','','','', + 'Xui ','','','','','','','','','','','','Bon ','de ','','', + '','','','peng ','','','','','','','','','','','','', + 'Leoi ','','','','Doc ','','','Co ','','','','','','','tan ','', + '','','','wu ','','','chuan ','','','','','','','du ','','', + '','hun ','','','','','','','','','','','','Dam6','Naam ','', + '','','','','','','','','','','','','Giay ','Tot ','','Xam ', + 'Giay ','','','','','Soc ','kua ','teng ','','','ta ','sa ','','','Pun ','Pun ', + '','','','sao ','','','','','','Sin ','','','','zu ','','', + '','','jie ','neng ','','','','Chuc ','','','','','To ','Nhuc ','Xung ','', + ], + 'x281':[ + '','','','','','','','','','','Te ','','','','','', + '','','','','shuan ','zu ','','','','','','','','','','', + 'Tat ','','','','','','','','','','','','','','','yu ', + '','','','','Sup ','','','','','','Chui ','','','','Ghe ','Giong ', + '','Sup ','Mop ','','','','','','','Lung ','','xiao ','','Ren ','','Laam ', + '','','shu ,chu','','','','','','','','','','','Jaang ','Nhap ','', + '','','','','','Bay ','','','','','','','','','','', + '','','','','','','','Doi ','','','','','','','Sum ','', + '','','Khum ','','zhu ','','','cha ','juan ','','','','','','zei ','', + '','','','','','','','','','','','','','Cui ','','', + 'Quay ','Dep ','','','','Tuon ','','','','','Jaang ','','','','','Buk6', + 'ta ,da','','','','','','','','','','','','','','','', + '','kuang ','','','','bao ','lai ','','','Leo ','','','','','','', + '','','','','','','lu ','','','','','','','','','', + '','','','','','','chan ','','','zhan ','','','','','','', + '','','','','','Nhao ','Khuy ','','','','','','','','','', + ], + 'x282':[ + '','','','','','','','Laam ','die ','','','','','','','', + '','','','leng ','','','','','','','Pei ','','','','','', + '','','','','','','','','','','','zhu ','','','','', + '','','','','','','','','','','ye ','','','','','', + '','huang ','','','','','','','','Pei ','','','','','','', + '','','','','','','Nei ','','','','','','','','Lung ','', + 'Ban ','','','','','','','','','','','','','mei ','','', + '','tang ','','','','','','','','','','','Wu ','xiang ','','', + '','','','','','','','','','','','','Lan ','','','', + '','','','','','','','','','','','Laak ','','','','', + '','','','','','','','','','','','','','','','', + '','yu ','','','','','','','','','dai ','','xuan ','','','jue ', + '','','','','','','','','du ','','','','','Wan ','','', + '','','','','','','','','zha ','','','pao ','','','bu ','he ', + '','','Lip ','','So ','','','ju ','hun ','','','','','','','Zhuai ', + '','','','','','','','','','','','','','','','', + ], + 'x283':[ + '','','','','zang ','','','','','','','','','','xu ','', + '','','','','','','','','jun ','','','','','','','', + 'lu ','','','','','fu ','','','','Tang ','','','chao ','ta ','','', + '','','','','','','','','','','','','','','','', + '','','','','Co ','','','he ','','','','','','','mu ','', + '','','xian ,jian','','','','','','','','','du ','','','','', + '','','','','','','Sau ','','','peng ','','','','','','ju ', + '','','','Yao ','','','','','','','','','','','','', + '','','','','','','So ','','','','','','','','','', + '','','','','yang ','','','','','','','','','','','Truoc ', + 'Truoc ','','','','','','','peng ','','','','jian ','jiao ','','','', + '','','','peng ','Dang ','','qu ','','mu ','','','','','','fen ','', + '','','','','','','','','','shuan ','jian ','','','','','', + '','','','','lu ,du','','','','','','ge ','','','','','', + '','','','','','xian ','','So ','','','','','','','','', + '','','','xie ','ge ','','','','','jue ','','','','','','', + ], + 'x284':[ + '','die ','','zhe ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','ku ','','qu ','','ge ','ban ','','','','','','','','Cay ','', + '','ban ','','','','','','','','','','','','','ban ,bian','', + '','','','','','','','','','','','','chen ','','','', + '','','Tu ','','','','','','','','','','Xuong ','','','', + '','','','','','wu ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','pan ','','','','','','','qiu ','','','','','', + '','','','','','','','','','','','','bie ','','kan ','', + '','','','','','','','','nai ','','','','','','','', + '','','','','','','','','','','Quanh ','','','','','', + '','','','','','','','','','','die ','','','','','', + '','','','','','','','','','','','','','','dai ','', + '','Lung ','','','','','','','','','','','','','','', + 'jie ','','','','ya ','','','','','','','','','','','pei ', + ], + 'x285':[ + '','','','','','','','','Choi ','','Suot ','','Co ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','shu ','','','','','','','','','ta ', + '','','','','','','','','','','','','','','','Chuc ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'ze ','','chu ','','','','qiu ','','','','','','','','','', + '','','','','','','','','','','','','','jie ','','', + '','','','','','Sang ','','','','','','','yang ','','','jiu ', + '','','','','','','','','','','','','','','','', + '','','','','','','','Mau ','','','','','','','','', + '','xian ','','','','','xiang ','sha ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','dao ','','','','','','','','','Nhanh ','yu ,ju','','', + '','chao ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','da ','', + ], + 'x286':[ + '','','jiu ','','','','','','','sha ','','','','','','', + '','','','','','','','','','xian ','','','','','xian ','', + '','','','','','','','','','','','','','','jiu ','', + '','Nhanh ','','','kao ','','','','','','','','','','','', + '','','','','','','','','','','','','','Keo ','ta ','zan ', + '','','','','zhu ','','Suot ','','','','','','','Lui ','','', + '','','','','','','','','','','','','','','','', + '','','','','','xiang ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','bian ','','','','','','','','','','', + '','','','','','','','qie ','','','','','','','hao ','', + '','','cun ','','ru ','zai ','','','','','','','','','','', + '','','','','','','','','','','','','','shao ','han ','', + 'jun ','','bu ','','','','kuai ','','','','','','xiang ','','','', + '','yun ','','','','pu ','','','','','','','pei ','','','', + '','','','','','','','','','','','','','','','', + ], + 'x287':[ + '','','','','','','','','','','','','huan ','qiao ','','', + '','','','','','','yu ','','mei ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','he ','','','he ','','','','','','','','','','chuang ','xu ', + '','','','','','','','','','','','zhai ','','','','', + '','guan ','','','','','','','','','','tu ','shun ','','hu ','', + '','','','','','','dang ','','','','','','','feng ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'cheng ','','','yu ','','zhu ,chu','','qun ','','qu ','','ge ','','','','', + '','','','','','','','','gai ','','','meng ','','','','', + '','','','qu ','','','','','','','','','wan ','lei ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','dai ','','','','','','','','','','','qiu ','','', + ], + 'x288':[ + '','','','','','','','','','Tam ','','','','','','', + '','','Faan ','','','','bao ','','','','','','','','','', + '','','','','','wei ','','','','','','','hao ','','','', + '','','Giam ','Gay ','Sua ','Xoang ','','','','','','','','','','', + '','','','jiao ','','','','','','Dam ','','','nei ','','yan ','', + '','','','','','','','zha ','','','','','','','','', + '','','','yan ','','','','','Gay ','','','hun ','','mu ','','', + '','','','','','','','','','','','','Giam ','','','', + '','','','','','','','liu ','han ','','meng ','hu ','','','','', + '','','','','','','','','','','','','','','','Cay ', + 'meng ','','mu ','','hu ','Mi ','shai ,zha','','','','chao ','','','','','nian ', + '','','','','','','','','','','','','','','','', + '','','','','','chuai ','','','','','','','','','','', + '','','','','','','','hu ','meng ','pao ','','','','','','', + '','','','','Giam ','Dau ','Zeoi6','','lan ','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x289':[ + '','','','','','','','','','','','','','','','', + '','juan ','','','','','','','','','','','','','','', + '','guang ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','jie ','','','','','','','','','','','','','', + '','','','','','','','','','','','hu ','','','','', + '','','','cen ','','','','','','','','','','','','', + '','','','','','','dai ','','','','','','','','','', + 'Keo ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','fu ','','','','', + '','','','','','','','Nen ','','','','','','Lao ','','', + 'liu ','','','','','','','','','','','','','','','', + '','','','','','','Bua ','','','','','','','','','', + '','xiang ','','','','bian ','','wu ','','','','','Bong ','','','', + 'Gang ','','','Xot ','','','','','','','sao ','','','','','', + 'zu ','','','','','','','','','','','','','','','', + ], + 'x28a':[ + '','','','','','Hoat ','','','','','','','','','','', + '','','','','','','','quan ','','','chao ','he ','','','','', + 'Cuoc ','wu ','','','Khep ','','Mai ','Thep ','','','','','','','','', + 'ruan ','','','zu ','','','yu ','tu ','meng ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','mao ','','','yu ','','','', + 'zu ','','','','','','','','','','','','','xia ','','', + '','','','','','jian ','','','','','','','','','yu ','', + '','','','','','liu ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','ruan ','','','yan ','','','','','','','','','', + '','','','','Bam ','Lon ','','','Choc ','','Sat ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','Han ','','','','','', + '','','','','','Cuoc ','','','','','','','','','','', + ], + 'x28b':[ + '','','','','','','','','','Dui ','','','','','','', + 'jue ','','','','ruan ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','zhu ','','','','','','','Baang ','Bay ','','Choang ', + '','','Choang ','die ','','','','','','','','','','','','', + '','Thau ','','','','','','','','','','','','','','', + '','','','','','','','','','','Com ','','','','','', + '','','','','','','','Bung ','Hom ','Cun ','','','','','','', + 'Nhon ','Thoi ','','','yu ','','','','Ban ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','cai ','','','','','','','','','','','jiang ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Dui ','','','','','','','', + ], + 'x28c':[ + '','','qian ','','','','','','','','','','','','','ta ', + '','diao ','','','','','','','','','','','jue ','','','', + '','','','','','','','','','','','','','','','', + '','','','','Nen ','','','','yu ','','Ben ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','duan ','','','','','', + '','','','','','','dao ','','','','','','','','','', + '','','','','','','','','','','','','cen ','Dai ','Dai ','', + '','','','','jun ','','','','zhu ','','an ','','','','','', + '','','qiu ','','','','','','','','','','','','','', + '','','','','','','','','','','','feng ','wu ','jiao ','','', + 'peng ','','','','','','','','','','','','','','','', + 'niao ','','chan ','','','','nang ','','','','Gau ','','','Cat6','','', + '','','Mon ','','men ','','','','tun ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','die ','','','','','', + ], + 'x28d':[ + '','','','','','','','','','','','','','','xu ','', + '','Kuang ','','wei ','','','','die ','','','','','','','','', + '','','he ','yan ','','','Cua ','','','tu ','','','hu ','','','', + 'chu ','','','','','','','','','','men ','','','','','', + '','','','','','','','','','','zhe ','','','','','', + '','','','','','','','','','','xie ','','','ta ','','fu ', + '','','','Cua ','','','yu ','','','','xie ','','xian ','jian ','xu ','', + '','','','','','','','','','','','','','','','', + '','yan ','ai ','','','','','','','','jun ','','','','','', + '','','','','','','','lang ','','Lan ','','','','shu ','','', + '','','yu ','','','','','','','','','','hua ','wen ','','e ', + '','','','','','','','','','Gwaan ','','','','','','', + '','niu ','','','xiang ','','sa ','','','','','','','','run ','', + '','','','jian ','xu ','','','','','shu ','','','','','','', + '','','','','','xie ','','','','','','','','','','Cua ', + '','','','','','','Cua ','','','','','','','','dang ','', + ], + 'x28e':[ + '','','','','','','','','','','','','','Cup ','','', + 'reng ','','','','','','','han ','','','Ji ','gai ','','','','', + '','','','','','','','','','','','','Zhen ','','','', + 'ju ','','','','','','','','','','','','','','','', + '','','','','','','xuan ','','','','','','','','','', + '','','','','','','','','xu ','','cheng ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','zhao ','','','','','','','', + '','','','','','fu ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','duan ','','','','qiu ','','','','','','','xun ','', + '','','','','','','','','','Jiao ','','','','','','', + '','','yan ','','','','','','','','','','','xu ','','', + '','','','','','','','die ','','','','','','','','', + '','','','','','','','liu ','','','','Luong ','','','','', + '','','Xia ','','','','Geki ','','','','','','','','','', + ], + 'x28f':[ + '','','','','','','','','zhan ','cuan ','wu ','','','','jue ','', + '','','','','xun ','','','','','','Be ','','','','','', + '','','','','chen ','','','','','','','qu ','','','zhan ','', + '','jue ','','','','','','','','','','','','qu ','','meng ', + '','','pu ','','','','','','','','','','','du ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','xia ', + '','','','','','','','','','','','','','','','dai ', + '','','','','','','','','','','','','yu ','','','', + '','','','','fang ','','','','','','','','','','','', + '','','','','die ','','','','','','','','','','','', + '','','','','','','','','','','','','','','tiao ','', + '','','','','','','','','','','','','','','','wu ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','wei ','','', + '','','','','','','','','','','','','','','','', + ], + 'x290':[ + '','','','','','','','','','','','run ','','','','', + '','','','','','','','','','','','','','','','', + '','','','wei ','','','','','','','','','','','','', + '','','','Song ','','','','','','','','','','','','', + '','','','','','','','','','','','','wei ','','','', + '','','','','','','','','','','','','','','cai ','', + '','','','','','','Loi ','','','','','','','','','', + '','','','','','','Ngat ','','','','','','','','','', + 'Con ','Ngut ','','shai ','tun ','','','','','','','','','','fu ','Che ', + 'Ram ','Bung ','','','fu ','Phat ','ze ','pu ','','','','','','','pao ','Mu ', + '','','','','hua ','','','','','','','','','','','', + '','','','Rei ','','dian ','Set ','','','','','','','','','', + 'yan ','','','','','','','','','','','','','','','', + '','','','','','','','','','','xuan ','','','','','', + 'dai ','','','','','','','','','','','','','','','', + '','','','','ba ','','','dai ','','','','','','','','', + ], + 'x291':[ + '','','','','','lu ','','','','','','ru ','','','Mua ','Bung ', + '','','','','','dan ','meng ','xia ','','','','','','','','', + '','','','','','','peng ','','Guot ','','','','','','','wu ', + 'Set ','','May ','','','Nap ','Xoi ','piao ','','','','','','','ze ','', + '','','','','lu ','','','bu ','','','','','','man ','','', + '','','','','','','','','','','','Bung ','','','','', + 'nan ','','he ','','','','','','','','','','','','cen ','', + '','','','','','','','','','May ','Rau ','Zyu ','','','dan ','fu ', + '','','','','','sa ','','','','','','Rao ','','Rao ','liu ','', + 'Sam ','','','','dian ','','','','','','','','','','','', + 'Mong ','Rao ','','','','','','','','','','','Mong ','','','', + '','','','','','','','Sam ','','','','','','','Khuya ','', + '','','','','','Mu ','Sam ','hun ','','','','','','Loa ','','', + 'qu ','','','','','','','','','','','','','','','', + '','','Xanh ','','','','','','','','','','','','','fei ', + '','','','','','','','','','','','','','fei ','','', + ], + 'x292':[ + '','','Bay ','','','','','','pang ','dan ','','ai ','','','','', + '','','','','','','','mai ','','','','','','','dao ','', + '','','','','chu ','','','','','','','','wan ','','diao ','', + '','','suan ','','','','','','','mian ','','','','','','', + 'lan ','','','','','','','','','','','','','','','', + 'gan ','','','','jian ','','','','','','','','hang ','','','', + '','','','','','xuan ','','','','','','','','','','', + 'ang ','','','','','fen ','','','ju ','','','','','fu ','','qu ', + '','','','ma ','','bao ','','yu ','','','','','','mai ','','', + '','','','','jiao ','','','','','','','','','','','', + '','','','','','','','','','','','','bu ','','','', + '','','','','','zhe ','bu ','','','','jue ','xun ','','Hia ','','', + '','','bai ','','','ta ','','','nao ','yu ','','','','','','', + '','','','','','','','','Xie ','diao ','','','','','die ','fu ,fu', + '','','xuan ,yun','','yu ','','','Xie ','fu ','','','xuan ','','','','', + '','','','','','','','la ','','','gao ','','','e ','','mei ', + ], + 'x293':[ + '','','','','','','','ta ','','ta ','','','','','','', + 'ta ','','','','','','','','ta ','','','','','','','', + '','','','','','','','','','','ze ','lu ','','','xu ','', + '','','xu ','','','','','','','','','','','','','', + '','','bao ','','','','','','','','','sheng ','','','','fu ', + '','','','','','','','Bang ','','','','','','','','', + '','','Roi ','Dep ','','','','','','','','','','','','', + '','','','xu ','','','','jue ','','','','','lu ','','','', + '','','','','','','','','','','','','','','ge ','', + '','','','','','','','','','','','fu ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','wei ','','','','yu ','','bai ','','ta ','','', + '','','','','','yun ','yun ','duan ','','wei ','','','','','','', + '','','','','','','hun ','','','','','','','','bai ','yu ', + '','','','','','','','','','','','','','','','', + '','','','','yu ','','','','','juan ','jue ','','','','','', + ], + 'x294':[ + '','','','','','sa ','','','','','','','','','','', + '','','','','','','','','','','fu ','peng ','','','','', + '','zu ','','','','','','','','','','su ','','','','', + '','','','','','','zhe ','','','','','','su ','','','', + '','e ','','','','','','','guang ','','','','','ao ','','', + '','','','','','','','','','','','','','','','', + '','','','','','men ','','','','','','','','','la ','', + '','','','','yao ','','','','','xuan ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','yan ','','','','','','','','','', + '','','','','','','','','','','','','','','qiu ','', + '','','','','','','','','','','fu ','','','','wu ','', + '','','','','','','','','','','','','','','','', + '','','','','','','fu ','','','','','Ngup ','Mang ','bie ','','', + '','','','','an ','Ngok6','wu ','','','','lu ','','','','','', + '','','','','','','','','','','','jue ','','','','', + ], + 'x295':[ + 'wai ','','dun ','','jie ','','','','','','zhuan ','hang ','','','','', + '','','','','','qiu ','','Lei ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','ze ','xu ','','','','','','','','xu ','','','', + 'ao ','','','','','','','','','','','','','','','', + 'liao ','','','','','wai ','','','','','','','','','','', + 'han ','','','','dan ','','','','','','','','','Gai ','','', + '','','','','','','','','','','','','','','yuan ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','peng ','','','','', + '','','','','tun ','','','','','','','','fu ','','','', + '','','','','','','','','','','han ','','fu ','','','', + '','','','To ','','','','','','sa ','','','','','','', + 'hua ','','','','','qiu ','','','','','','','','','sa ','', + '','','','','han ','','','','','liu ','','','','','','', + '','','','','Bung6','','','','','','','','','wu ','','', + ], + 'x296':[ + 'zhao ','','','','May ','','','','','','la ','','','yuan ','','', + '','','','','','','','','','','','','','','','', + '','','','To ','yu ','','','','','','','','','','','', + 'su ','shuai ','','yu ','','','','','','su ','','yu ','','','','', + '','','','','liu ','','cheng ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','niu ','','','','Bay ','','','','', + '','','','','yu ','','','','','','','','','','','', + '','','','','Nhu ','','niu ','','','','','na ','','','','', + '','','','','','','','Qua ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','No ','Qua ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','zai ','','','mao ','','yu ','','','yu ','','', + '','','','','','','','','','','ju ','','lu ','','','', + ], + 'x297':[ + '','','','ju ','','','','Juan ','','','','','','','','', + '','','','','','','','','','','','','','','','ang ', + 'Mam ','','','','','','','','','','','','','','','', + '','','fu ','','','','','','','','','','','yan ','','', + '','','','','','','','','','','','','','','','', + '','','','','','wu ','','yu ','','','','','','','','', + 'Qiu ','','','','','su ','','','','','','','','','','', + '','','','','','','','','','','','Chan ','','jiang ','','', + '','','','','','','','','zhu ','','','','','','','', + '','','','','','','','','','','','','','','hai ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','han ', + '','yuan ,xuan','Qua ','','','','','ao ','','','','shan ','','','','', + '','yu ','','','Caat ','','','','','','','','','','meng ','', + '','','','','','','jie ','','','','','','','','huai ','', + '','','','yu ','','','chan ,jie','','','','','Nang ','','','','', + ], + 'x298':[ + '','','','','','','','','','','','','','','','', + '','Ding ','','','Mao ','','','','','','','','','','','', + 'Cui ','','','','','','','Guc ','','','','','','','','wei ', + '','Chui ','','Chui ','Cui ','Choi ','','fu ','','','','','','','','', + '','','','yu ','','','','','','','','Thom ','','','','', + '','','','','hai ','peng ','','','','','','','','','','bie ', + '','','','','','','','','','','','fan ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','wan ','','','','','','','','wen ','','','', + 'zhe ','','','','ban ','bu ','','','','','','ge ','','','liu ','', + '','','','','','','Giong ','','','','hu ','','','','','', + 'fu ','','Sai ','qu ','','','yu ','','','jiu ','','shu ','','','','fu ', + '','','','','','','','','','','xu ','','','','','', + '','Ngon ','','','','','','','','','','','fu ','bu ','','', + '','','','','','','','','','zhe ','','','','','tu ','', + '','lu ','','','','','','','fu ','','','','','','','', + ], + 'x299':[ + '','','','','','','','','','','xian ,jian','kun ','','','','', + '','','','','','','','','','cheng ','','','','','tan ','', + 'xie ','','','duan ','','','','','','e ','','','','','','', + '','','','','','','','','','','yu ','','','','','', + '','','','','','','','zhan ','','','','Au6','qia ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','yu ','','', + '','','','','','','','','','','','','','tu ','','zu ', + '','','','','','','','','','bie ','','','','','','', + '','','','','','','','','','','','','','','','', + 'bang ','yu ','Jyu ','','','','','','','','','','','','','', + '','','','','','','','','','xian ','meng ','','','','','', + '','','','','','','','cai ','du ','','','','','','','jue ', + '','','ju ','','','','','','qu ','','','','','','','', + '','jue ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x29a':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','yu ','','yu ','','','ba ','','','', + 'ya ','','','','','','','','','fan ','','','','Que ','','', + '','','ma ','','','','','','','','','','Kheo ','','','', + '','','','','','','','Song ','','','','','','Peng ','','', + '','','','','','','Song ','','','','','','','','','', + 'zu ','leng ','','','','','','dan ','','','Xuong ','Xuong ','','','du ','bian ', + '','qia ','he ','','','','yan ','','','','','teng ','','','','Hom ', + '','','','hai ','','','','','','xu ','','','','','','', + '','','','','','','','Jue ','','','','pu ','','','Sun ','', + '','','','','','','','','','','','','','','','', + '','','','','yan ','So ','','','','','','','','Cut ','','', + 'kai ','mao ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','sao ','','','','','','','','','', + '','','','','ju ','','','','','cheng ','','','','','','', + ], + 'x29b':[ + '','','','','','','','','','','','','','','Zam ','', + '','Chom ','','','','','','','','','','','ju ','','','zha ', + '','','','','','','','','','','','','','','','', + '','dao ','','','','','','','','','','','','','','', + '','','','','','','','','','','ju ','','','','','', + '','','','','','','','','','','','','Xui ','','','dao ', + '','','an ','','','han ','','','','','','','','','','', + '','','','','','Quan ','Rau ','','','','fu ','','','','','', + '','qia ','','','','na ','','','','','','','','','','', + '','','','','Quan ','','','','','','','','','ya ','','', + '','','','','','','','','','','','','','Ria ','','', + '','','','','','','','','','','','','','','','', + '','Rau ','','','zun ','','nao ','','','','','','','','cheng ','', + '','','','','','','','','jiao ','','','yao ','','','can ','', + '','','','','','','','','','','','','','Ban ','','Xoam ', + '','pu ','zhuang ','','','','','','','','','','','la ','','', + ], + 'x29c':[ + '','','','zhan ','','','','','Nheo ','','','','','bian ','','', + '','','','','','','','','','','','','','','','', + '','','','','ju ','','','','jue ','','yu ','','','','','hu ', + '','','','xie ','er ','','','','','','','','','','','', + '','','','','','','','','','','er ,xian','','yu ','hu ','','', + '','','','','','','','','','ku ','','','','','jiao ','', + '','','','','','','','','ru ','','','','','','','', + '','yu ','','','','','','','','','','','','','','', + '','','','','','','','','','','hao ','','','niu ','','hua ', + '','','','','','','','','','','','','','','','', + 'zhu ','Coi ','','','','Troi ','','','','','','','zhu ','','','', + '','','zu ','','','','','','','','','','','','yu ','', + '','','','','','','lai ','','','','Ranh ','','wu ','','fu ','zhuan ', + '','','su ','','yao ','','','','','','','','','','','', + '','','yan ','','','zhu ','','','','','','','','','','', + '','','','Troi ','','ju ','','','','','','','','','','', + ], + 'x29d':[ + '','','','','','','','shai ','','yun ','','','','','','', + '','','jiang ','','','','','','ju ','','Troi ','','','teng ','wei ','', + '','gu ','','','liao ','','','','','','','','','','','', + '','','meng ','cha ','','','','','','qu ','','lei ','','','','', + '','','','Troi ','','qu ','','','','','','Gyo ','','qiu ','','hua ', + '','','','','','','','','','','du ','','','Chai ','','', + '','','','','','','mu ','','','','','','hu ','','','', + '','','','','','','','','','fu ','','','','Tom ','','', + '','','zhu ','','zhu ','Ci ','','','','Pou ','','','','','','', + '','','','','','','mu ','','','','','','','','','Buop ', + '','meng ','','','','','guai ','jiu ','','mu ','','','Si ','wu ','','ru ', + '','zha ','','','','','','','','','','','','','','', + '','','xie ','','jiang ','','','Hung ','','','Thu ','','','','','', + 'ju ','','','','','Luon ','bu ','','','','','','','','','', + '','','','','','','','','','','','','','jiang ','','', + 'xun ','','','','','','Mang ','','','','','qia ','','','','', + ], + 'x29e':[ + '','','','tu ','hua ','','','','','','','','','','','', + 'ru ','','','','','','','','','','','','','','','', + '','','','','','','','','Yi ','','','','','','Bong ','Chuoi ', + 'Go ','','','','','','','','Thia ','','','','','','ye ','', + '','','','','hai ','','','','','','','','','','an ','ba ', + '','han ','','','','','','','','','','','','','','nai ', + '','','','','Thu ','','','','','Nau ','','Tep ','','Chay ','Mu ','Tuoi ', + '','chu ','','','','','','','','','ge ','','han ','','na ','ge ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','Bon ','','Trau ','','','','','Bong ','','Bon ','xie ','','','','Soc ', + 'yu ,wu','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Mam ','','Sop ','Dua ','','Tram ','','bu ','jian ','','wu ','Tram ','','zhuan ','','Vay ', + '','','','','','','','','','','','','','','','', + '','','','','','die ','','','','','Vay ','Leo ','','','','', + ], + 'x29f':[ + 'Vay ','','','','','','','','Ao ','','','','','','','', + '','','','','','','','','','ge ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','xu ','','','Sau ','Lui ','','','','wei ','', + '','','','','','','Ruoc ','','','','','','','','','', + '','','','','Sau ','Luon ','','','','qu ','','','','','','', + '','','','','','','','ba ','Nheo ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','han ,yan','','', + '','bao ','','','','','','xun ','','','','','','','','', + '','','','','','','jie ','','','','','hu ','','','','fu ', + '','','mao ','','','','','','','','','','','','','', + '','','','bao ','','','','','Mao ','','Khuou ','','','ju ','Caa ','qu ', + '','','','','','qu ','','','Khuou ','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2a0':[ + '','','','','Chim ','','','','','','','','','','','', + '','','Shi ','','','','','','jiang ','','','','','','','', + 'xun ','','','ju ','','','','','','','','','','','','', + '','','','','','','','','','','fu ','','','','jie ','', + 'yu ','','','','Ket ','Sac ','Hau ','Song ','zhuang ','','','cheng ','','jie ','','chen ', + '','','','','','','qu ','','','','','','','','','', + 'jue ','yan ','','','','ju ','','','','','','','','','xiu ','', + '','','','','Coc ','Coc ','','','','','','','','su ','','', + '','','','','','','','','','yu ','','fu ','ta ','','','', + '','','hu ','','','','','','','','','','mei ','','','', + '','','','','','','','','','','','','','','','', + '','','','Cun ','','yu ','','','','','','','','pen ','fu ','', + '','','liu ','','','','','','jie ','','','','','yu ','yu ','Mei ', + '','mao ','','fu ','','','','','','','','jian ','','','','', + '','','','','','','','','','','','','','','','', + '','Hau ','','','Ga ','','','','','','','','','','','Ge ', + ], + 'x2a1':[ + '','','xia ','','','Set ','','','','','qu ','','','','ge ','', + '','su ','','','','','','','','','','','','','','', + '','','','','','Cut ','','','','','','','','','hu ,gu','', + '','','','mai ','','','','','','','','','','','','', + '','','','','su ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','Cuoc ','Choi ','Ri ','Sam ','','','','Tu ','','', + '','','','','','','','','jie ','','','','','','','', + '','','qu ','','','','','','','','','xie ','','','','', + '','','','','','','','','','','','','','','','', + 'fu ','','','','','Khuou ','Tu ','','','','','','','','','', + 'ya ','liu ','','','','','can ','64272.110,chu ','','','','','','','','jian ', + '','','','','','','chu ,du','','ai ','','','Cui ','','','Quam ','', + '','xun ','','','','','','','','','','','','yu ','','', + '','','','','','','','','','Ngan ','','Cui ','','cai ','','liu ', + '','','jie ','','','','','','','la ','','','','','','', + ], + 'x2a2':[ + '','','','','','','','','lai ','','he ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','jue ','','','','guan ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Muoi ','','tan ','','En ','','','','','','kan ', + '','bian ','','','Muoi ','','','','','','','','','','','gan ', + '','','','','','Mam ','','gan ,tan','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','xiao ','','zhu ','','yu ','','','','', + '','jian ','','','','','','','','yu ','','','','zu ','','', + 'nuan ','','','','','','','','','','','','','su ','','', + '','pu ','','','','','','','','','','','','','yu ','', + '','','','','','','','','','','','','','','','', + ], + 'x2a3':[ + '','','','','','na ','qu ','','','','','tun ','','','','', + '','','','ku ','su ','','','','','','','','','','','ze ', + '','','','ge ','','','','jie ','','','tiao ','','','','','', + '','','','','','','shu ','','','','','','','hun ','','nie ', + '','jun ','hu ','','lu ','','','','chao ','','','','','','','fu ', + '','','','','','','','','','','','','','yun ','','', + '','','','','','','','xuan ','','','','','','','','', + '','','','','','','shan ','','Qu ','du ','','sao ','','','','kuang ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','liu ','','','','','','','','','','mei ','','', + '','','','','tun ','kang ','tun ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','heng ','','','','','','Huang ','','','','','','', + '','','','','','','','','','','kuang ','piao ','','','','', + '','','','hu ','','','bao ','','','','','hu ','','','','', + ], + 'x2a4':[ + 'Naa ','','','','','','bie ','','','','','','','','','', + '','','','','','','','','','','','','','dai ,tai','du ','', + '','','','','','tai ','','shu ','','','','','','','su ','', + '','','','','','','','','','','','','','','','', + '','','cha ','','lu ','','yu ','','yan ','','qiao ','','yu ','','','tu ', + '','Ngam ','tun ','','','','','','','','','','','yu ','','', + '','','','','','','','die ','cha ','dian ','','','','','','', + '','','','','','','','wai ','','','','','','zhai ','','', + '','','','','','','','','','','','','','','','lu ', + '','','','','','','','Tham ','','','','','ma ','','','', + '','','','','','','','','','','mai ','','Nung ','','','', + '','','','','','','','','','','','','','','dan ','teng ', + '','','','','','','','','','','yu ','','','','','', + '','','','','','','','','','','','','','','','', + '','cu ','','','','','','','','','','Sam ','','','','', + 'cu ','','','','','','','','','','','','','','','', + ], + 'x2a5':[ + '','','Ding ','','','','','','','','','','','peng ','','', + '','','','','','','','','','','','','','','','', + 'Trong ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','hu ','','','','','','', + '','','','','','','','','','','','','','cu ','jun ','', + '','','','','','','','','er ','','','','','ai ','hu ','', + '','hu ','','','','','','','','','','','','','','', + '','','','','jiao ','','','','pu ','','','jie ','lu ','','','', + 'yao ,ya','','','','','','','','','Hou ','','qiu ','jue ','','','', + '','','','','','','','','','xu ','','','','Ngui ','','', + '','','','','','','su ','liao ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','pa ','','','','','','','','','na ','','', + '','','','','','','zhan ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2a6':[ + '','Kap6','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','zu ','','','zhan ','','','','','', + '','','Ji ','','','Rang ','','','','he ','qia ','','','','','', + '','','','','','','','','hu ','','yan ','','','','','', + '','','','','','','','','','','','Nak ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','jue ','','','','','','','','','','', + '','','','','','','','','','','Trong ','','','','','', + '','','','','','zhe ','','','','Gwi ','','','gan ','','','cu ', + '','','','','','','','','','zhu ','','','','','','', + 'xiao ','','','','','Rua ','','Rua ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2a7':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2a8':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Bai ','','','','','','','Zhan ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Luan ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2aa':[ + '','','','','','','','','','','Song ','','','','','', + '','','','','','','','Jue ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Yong ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2ae':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','Nu ','','','','','','', + '','','','','','','','','','','','','','','','', + 'Cong ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2af':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Xian ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2b0':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','Li ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Fei ','','','','','','','', + '','','','','','','','','','Su ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','Kou ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2b1':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Chi ','','','','','','','', + '','','','','','','','','Xun ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2b2':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Qia ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Gong ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2b3':[ + 'Ji ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Luo ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','Yi ','','','','','','', + '','','Nao ','','','','','','','','','','','','','', + 'Xi ','','Xiao ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','Jiao ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2b4':[ + '','','','','Yue ','','Kuai ','','','Ling ','','','','','','', + 'Ni ','','','Bu ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','Han ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','Fu ','','Cong ','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2b5':[ + '','','','','','','','','','','','','','','Jue ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Duo ','','','','','','','Su ','','','','','','','Huang ','', + '','','','','','','','','','','','','','','','', + ], + 'x2b6':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Han ','Ai ','','','','Ti ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Xu ','Gong ','','','','','','', + '','','Ping ','','Hui ','Shi ','','','','Pu ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','Zhi ','','','Jue ','', + '','','Ning ','','','','','','','','','','','','','', + '','','','','','','Chi ','','Ti ','','','','','','','', + ], + 'x2f8':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Gai ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2f9':[ + '','','','','','','','Baan6','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ] +} diff --git a/ebook_converter/ebooks/unihandecode/vndecoder.py b/ebook_converter/ebooks/unihandecode/vndecoder.py new file mode 100644 index 0000000..60ee7fb --- /dev/null +++ b/ebook_converter/ebooks/unihandecode/vndecoder.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL 3' +__copyright__ = '2010, Hiroshi Miura ' +__docformat__ = 'restructuredtext en' + +''' +Decode unicode text to an ASCII representation of the text in Vietnamese. + +''' + +from calibre.ebooks.unihandecode.unidecoder import Unidecoder +from calibre.ebooks.unihandecode.vncodepoints import CODEPOINTS as HANCODES +from calibre.ebooks.unihandecode.unicodepoints import CODEPOINTS + + +class Vndecoder(Unidecoder): + + codepoints = {} + + def __init__(self): + self.codepoints = CODEPOINTS + self.codepoints.update(HANCODES) diff --git a/ebook_converter/ebooks/unihandecode/zhcodepoints.py b/ebook_converter/ebooks/unihandecode/zhcodepoints.py new file mode 100644 index 0000000..57e4de3 --- /dev/null +++ b/ebook_converter/ebooks/unihandecode/zhcodepoints.py @@ -0,0 +1,5252 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL 3' +__copyright__ = '2010 Hiroshi Miura ' +__docformat__ = 'restructuredtext en' + +''' +Unicode code point dictionary. +Based on Unicode.org Unihan database. +''' + +CODEPOINTS = { + 'x34':[ + 'Qiu ','Tian ','','','Kua ','Wu ','Yin ','','','','','','Si ','','','', + '','','','','','','Ye ','','','','','','Chou ','','','', + '','Nuo ','','','Qiu ','','','','Xu ','Xing ','','Xiong ','Liu ','Lin ','Xiang ','Yong ', + 'Xin ','Zhen ','Dai ','Wu ','Pan ','','','Ma ','Qian ','Yi ','Zhong ','N ','Cheng ','Fung ','','', + '','Zhuo ','Fang ','Ao ','Wu ','Zuo ','','Zhou ','Dong ','Su ','Yi ','Jiong ','Wang ','Lei ','Nao ','Zhu ', + 'Suk ','','','','Xu ','','','Saan ','Jie ','Die ','Nuo ','Su ','Yi ','Long ','Ying ','Beng ', + '','','','Lan ','Miao ','Yi ','Li ','Ji ','Yu ','Luo ','Chai ','Nom ','','','Hun ','Xu ', + 'Hui ','Rao ','','Zhou ','Caam ','Han ','Xi ','Tai ','Ai ','Hui ','Jun ','Ma ','Lue ','Tang ','Xiao ','Tiao ', + 'Zha ','Yu ','Ku ','Er ','Nang ','Qi ','Chi ','Mu ','Han ','Tang ','Se ','Si ','Qiong ','Lei ','Sa ','', + '','Hui ','Pu ','Ta ','Shu ','Zoeng ','Ou ','Tai ','','Mian ','Wen ','Diao ','Yu ','Mie ','Jun ','Niao ', + 'Xie ','You ','','','She ','Fung ','Lei ','Li ','Sin ','Luo ','Sek ','Ji ','','Kwaan ','','', + 'Quan ','','Cai ','Liang ','Gu ','Mao ','Gung ','Gua ','Sui ','Din ','','Mao ','Man ','Hyun ','Shi ','Li ', + '','Wang ','Kou ','Chui ','Zhen ','Ding ','','','Bing ','Huan ','Dong ','Gong ','Cang ','','Lian ','Jiong ', + 'Lu ','Xing ','','Nan ','Xie ','','Bi ','Jie ','Su ','Hung ','Geoi6','Gung ','You ','Xing ','Qi ','Ngo ', + 'Dian ','Fu ','Luo ','Qia ','Jie ','Tong ','Bak ','Yan ','Ci ','Fan ','Lang ','','Fu ','He ','Diu ','Li ', + 'Hua ','Tou ','Pian ','Dai ','Jun ','E ','Qie ','Yi ','Jue ','Rui ','Jian ','Gong ','Chi ','Chong ','Chi ','', + ], + 'x35':[ + 'Lue ','Daang ','Lin ','Jue ','Su ','Xiao ','Chan ','Put ','','Zhu ','Dan ','Jian ','Zhou ','Duo ','Xie ','Li ', + 'Cim ','Chi ','Xi ','Jian ','','Ji ','','Fei ','Chu ','Bang ','Kou ','','Ba ','Liang ','Kuai ','', + 'He ','Bit ','Jue ','Lei ','Shen ','Pi ','Yang ','Lu ','Bei ','E ','Lu ','','Coek ','Che ','Nuo ','Suan ', + 'Heng ','Yu ','','Gui ','Yi ','Xian ','Gong ','Lou ','Cam ','Le ','Shi ','Pei ','Sun ','Yao ','Jie ','Zou ', + '','Que ','Yin ','Him ','Zhi ','Jia ','Hu ','La ','Hou ','Ke ','Bou ','Jing ','Ai ','Deoi ','E ','Chu ', + 'Xie ','Chu ','Wei ','','Teng ','Huan ','Su ','You ','Caam ','Jun ','Zhao ','Xu ','Shi ','','Caat ','Kui ', + 'Soeng ','He ','Gai ','Yan ','Qiu ','Yi ','Hua ','Si ','Fan ','Zhang ','Dan ','Fang ','Song ','Ao ','Fu ','Nei ', + 'He ','You ','Hua ','Hung ','Chen ','Guo ','Ng ','Hua ','Li ','Fa ','Hao ','Pou ','Dung6','Si ','','', + 'Le ','Lin ','Yi ','Hou ','Zaau ','Xu ','Qu ','Er ','','','','','','','','Nei ', + 'Wei ','Xie ','Ti ','Hong ','Tun ','Bo ','Nie ','Yin ','San ','','','','','','Wai ','Shou ', + 'Ba ','Ye ','Ji ','Tou ','Han ','Jiong ','Dong ','Wen ','Lu ','Sou ','Guo ','Ling ','','Tian ','Lun ','', + '','','','','','ge ','Ye ','Shi ','Xue ','Fen ','Chun ','Rou ','Duo ','Ze ','E ','Xie ', + 'Zaau ','E ','Sheng ','Wen ','Man ','Hu ','Ge ','Xia ','Man ','Bi ','Ji ','Hou ','Zhi ','','Gaa ','', + '','Bai ','Ai ','Ci ','Hin ','Gou ','Dan ','Bai ','Bo ','Na ','Li ','Xiao ','Xiu ','','','', + '','','Dong ','Ti ','Cu ','Kuo ','Lao ','Zhi ','Ai ','Xi ','','Qie ','Zaa ','Hei ','','', + 'Chu ','Ji ','Huo ','Ta ','Yan ','Xu ','Put ','Sai ','','','','Go6','Ye ','Xiang ','Heoi ','Xia ', + ], + 'x36':[ + 'Zuo ','Yi ','Ci ','','','Xian ','Tai ','Rong ','Yi ','Zhi ','Yi ','Xian ','Ju ','Ji ','Han ','', + 'Pao ','Li ','','Lan ','Can ','Han ','Yan ','','','Yan ','Han ','Haam ','Chi ','Nian ','Huo ','', + 'Bi ','Xia ','Weng ','Xuan ','Waan ','You ','Qin ','Xu ','Nei ','Bi ','Hao ','Jing ','Ao ','Ao ','','', + 'Zam ','Taan ','Ju ','Zaau ','Zuo ','Bu ','Jie ','Ai ','Zang ','Ci ','Fa ','Zaan ','','','','Nie ', + 'Liu ','Mang ','Dui ','Bong ','Bi ','Bao ','','Chu ','Han ','Tian ','Chang ','','','Do ','Wai ','Fu ', + 'Duo ','Yu ','Ye ','Kui ','Han ','Kuai ','','Kuai ','Ziu ','Long ','Sing ','Bu ','Chi ','Xie ','Nie ','Lang ', + 'Yi ','Zung ','Man ','Zhang ','Xia ','Gun ','','','Ji ','Liao ','Ye ','Ji ','Yin ','','Da ','Yi ', + 'Xie ','Hao ','Yong ','Han ','Chan ','Tai ','Tang ','Zhi ','Bao ','Meng ','Gui ','Chan ','Lei ','','Xi ','', + 'Hei ','Qiao ','Rang ','Yun ','','Long ','Fu ','Zuk ','','Gu ','Hoi ','Diu ','Hua ','Guo ','','Gao ', + 'Tao ','','Shan ','Lai ','Nie ','Fu ','Gao ','Qie ','Ban ','Gaa ','','Xi ','Xu ','Kui ','Meng ','Chuo ', + 'Hiu ','Ji ','Nu ','Xiao ','Yi ','Yu ','Yi ','Yan ','','Ran ','Hao ','Sha ','Gwan ','You ','Daam ','Xin ', + 'Bi ','Zaau ','Dian ','O ','Bu ','Dung ','Si ','Er ','Si ','Mao ','Yun ','Gei ','Naau ','Qiao ','','Pao ', + '','Ping ','Nuo ','Jie ','Zi ','Er ','Duo ','','','','Duo ','','','Qie ','Leoi ','Ou ', + 'Sou ','Can ','Dou ','Ci ','Peng ','Yi ','So ','Zuo ','Po ','Qie ','Tong ','Xin ','You ','Bei ','Long ','', + '','','','','','Ta ','Lan ','Man ','Qiang ','Zhou ','Yan ','Sek ','Lu ','Sik ','Sao ','Mian ', + 'Fan ','Rui ','Fa ','Cha ','Nao ','Cing ','Chou ','Gai ','Shu ','Pian ','Aam ','Kui ','Sha ','Saan ','Xian ','Zhi ', + ], + 'x37':[ + '','','Fung ','Lian ','Xun ','Xu ','Mi ','Hui ','Mu ','Zung ','Pang ','Yi ','Gou ','Tang ','Qi ','Yun ', + 'Shu ','Fu ','Yi ','Da ','','Lian ','Cao ','Can ','Ju ','Lu ','Su ','Nen ','Ao ','An ','Qian ','', + 'Ceoi ','Sung ','','Ran ','Shen ','Mai ','Han ','Yue ','Er ','Ao ','Xian ','Ma ','','','Lan ','Hei ', + 'Yue ','Dong ','Weng ','Huai ','Meng ','Niao ','Wan ','Mi ','Nie ','Qu ','Zan ','Lian ','Zhi ','Zi ','Hai ','Xu ', + 'Hao ','Xun ','Zhi ','Fan ','Chun ','Gou ','','Chun ','Luan ','Zhu ','Shou ','Liao ','Jie ','Xie ','Ding ','Jie ', + 'Rong ','Mang ','Geoi ','Ge ','Yao ','Ning ','Yi ','Lang ','Yong ','Yin ','','Su ','Sik ','Lin ','Ya ','Mao ', + 'Ming ','Zui ','Yu ','Ye ','Gou ','Mi ','Jun ','Wen ','','Hoi ','Dian ','Long ','','Xing ','Cui ','Qiao ', + 'Mian ','Meng ','Qin ','','Wan ','De ','Ai ','','Bian ','Nou ','Lian ','Jin ','Zyu ','Chui ','Zuo ','Bo ', + 'Fui ','Yao ','Tui ','Ji ','Aam ','Guo ','Ji ','Wei ','Bui6','Zaat ','Xu ','Nian ','Yun ','','Ba ','Zhe ', + 'Ju ','Wei ','Xi ','Qi ','Yi ','Xie ','Ci ','Qiu ','Tun ','Niao ','Qi ','Ji ','Teoi ','','','Dian ', + 'Lao ','Zhan ','Zi ','Fan ','Yin ','Cen ','Ji ','Hui ','Zai ','Lan ','Nao ','Ju ','Qin ','Dai ','Shutsu ','Jie ', + 'Xu ','Cung ','Yong ','Dou ','Chi ','Tou ','Min ','Huang ','Sui ','Ke ','Zu ','Hao ','Cheng ','Xue ','Ni ','Chi ', + 'Lian ','An ','Chi ','Si ','Xiang ','Yang ','Hua ','Cuo ','Qiu ','Lao ','Fu ','Dui ','Mang ','Lang ','Tuo ','Han ', + 'Mang ','Bo ','Kwan ','Qi ','Han ','','Long ','Ban ','Tiao ','Lao ','Qi ','Zan ','Mi ','Pei ','Zhan ','Xiang ', + 'Gang ','','Qi ','','Lu ','Caam ','Yun ','E ','Quan ','Min ','Wei ','Quan ','Shu ','Min ','Daat6','', + 'Ming ','Yao ','Jue ','Li ','Kuai ','Gang ','Yuan ','Da ','Gou ','Lao ','Lou ','Qian ','Ao ','Biao ','Zung ','Mang ', + ], + 'x38':[ + 'Dao ','Caam ','Ao ','','Xi ','Fu ','Daan ','Jiu ','Run ','Tong ','Qu ','E ','Hei ','Ji ','Ji ','Hua ', + 'Jiao ','Zui ','Biao ','Meng ','Bai ','Wei ','Ji ','Ao ','Yu ','Hao ','Dui ','Wo ','Ni ','Cuan ','','Li ', + 'Lu ','Niao ','Hua ','Lai ','','Lu ','Fung ','Mi ','Yu ','Fong ','Ju ','','','Zhan ','Pang ','Yi ', + '','Ji ','Bi ','','Ren ','Fong ','Fan ','Ge ','Ku ','Jie ','Miao ','Hei ','Si ','Tong ','Zyun ','Ci ', + 'Bi ','Kai ','Li ','Fong ','Sun ','Nuo ','Fong ','Ji ','Men ','Xian ','Qia ','E ','Mao ','','Saam ','Tou ', + 'Zin ','Qiao ','Zeon ','Kwaan ','Wu ','Zing ','Chuang ','Ti ','Lian ','Bi ','Haat6','Mang ','Xue ','Feng ','Lei ','Zou ', + 'Zheng ','Chu ','Man ','Long ','','Yin ','Baan ','Zheng ','Qian ','Luan ','Nie ','Yi ','','Ji ','Ji ','Zhai ', + 'Yu ','Jiu ','Huan ','Di ','Kaap ','Ling ','Ji ','Ben ','Zha ','Ci ','Dan ','Liao ','Yi ','Zhao ','Xian ','Chi ', + 'Ci ','Chi ','Yan ','Lang ','Dou ','Long ','Chan ','','Tui ','Cha ','Ai ','Chi ','','Ying ','Cha ','Tou ', + '','Tui ','Cha ','Yao ','Zong ','Zung ','Pun ','Qiao ','Lian ','Qin ','Lu ','Yan ','Kong ','Sou ','Yi ','Chan ', + 'Jiong ','Jiang ','','Jing ','','Dong ','Go ','Juan ','Han ','Di ','Wu ','','Hong ','Tou ','Chi ','Min ', + 'Bi ','','Xun ','Lu ','Sai ','She ','Bi ','','Bi ','','Xian ','Wei ','Bie ','Er ','Juan ','', + 'Zhen ','Bei ','Yi ','Yu ','Qu ','Zan ','Mi ','Ni ','Si ','Gung ','','Daan ','Shan ','Tai ','Mu ','Jing ', + 'Bian ','Rong ','Ceng ','Can ','Ding ','','','','Keoi ','Di ','Tong ','Ta ','Xing ','Sung ','Duo ','Xi ', + 'Tong ','','Ti ','Shan ','Jian ','Zhi ','Wai ','Yin ','','','Huan ','Zhong ','Qi ','Zung ','','Xie ', + 'Xie ','Ze ','Wei ','','','Ta ','Zhan ','Ning ','','','Sam ','Yi ','Ren ','Shu ','Cha ','Zhuo ', + ], + 'x39':[ + '','Mian ','Ji ','Fang ','Pei ','Ai ','Fan ','Ao ','Qin ','Qia ','Xiao ','Fan ','Gaam ','Qiao ','Go ','Tong ', + 'Tip ','You ','Gou ','Ben ','Fu ','Chu ','Zhu ','','Chu ','Zaan ','Hang ','Nin ','Jue ','Cung ','Cha ','Kong ', + 'Lie ','Li ','Xu ','Paang ','Yu ','Hai ','Li ','Hou ','Gong ','Ke ','Yuan ','De ','Hui ','Giu ','Kuang ','Jiong ', + 'Zan ','Fu ','Qie ','Bei ','Xi ','Ci ','Pang ','Haam ','Xi ','Qiu ','Huang ','Nan ','','Chou ','San ','Jim ', + 'De ','De ','Te ','Men ','Ling ','Shou ','Dian ','Can ','Die ','Che ','Peng ','Zi ','Ju ','Ji ','Lai ','Tian ', + 'Yuan ','Zaau ','Cai ','Qi ','Yu ','Lian ','Cung ','','','','Yu ','Ji ','Wei ','Mi ','Cui ','Xie ', + 'Xu ','Xi ','Qiu ','Hui ','Ging ','Yu ','Qie ','Shun ','Chui ','Duo ','Lou ','Deon ','Pang ','Tai ','Zhou ','Yin ', + 'Sou ','Fei ','Shen ','Yuan ','Yi ','Hun ','Se ','Ye ','Min ','Fen ','He ','','Yin ','Ce ','Ni ','Ao ', + 'Feng ','Lian ','Chang ','Chan ','Ma ','Di ','Fu ','Lu ','','Yi ','Hua ','Caa ','Tui ','E ','Hua ','Sun ', + 'Ni ','Lian ','Li ','Xian ','Yan ','Long ','Men ','Jian ','Gik ','','Bian ','Yu ','Huo ','Miao ','Chou ','Hai ', + '','Le ','Jie ','Wei ','Yi ','Huan ','He ','Can ','Lan ','Yin ','Xie ','Zaat ','Luo ','Ling ','Qian ','Huo ', + 'Cim ','Wo ','Zoi ','','Ge ','Zyu ','Die ','Yong ','Ji ','Ang ','Ru ','Xi ','Shuang ','Xu ','Yi ','Hu ', + 'Ji ','Qu ','Tian ','Sau ','Qian ','Mu ','Gaan ','Mao ','Yin ','Gai ','Ba ','Xian ','Mao ','Fang ','Ya ','Gong ', + 'Song ','Wei ','Xue ','Gwaa ','Guai ','Jiu ','E ','Zi ','Cui ','Bi ','Wa ','Hin ','Lie ','Gaa ','','Kuai ', + '','Hai ','Zaan ','Zhu ','Chong ','Xian ','Xuan ','So ','Qiu ','Pei ','Gui ','Er ','Gong ','Qiong ','Bak6','Lao ', + 'Li ','Chen ','San ','Bo ','Wo ','Pou ','Hang ','Duo ','Paang ','Te ','Ta ','Zhi ','Biao ','Gu ','Fat ','Coeng ', + ], + 'x3a':[ + 'Bing ','Zhi ','Dong ','Cheng ','Zhao ','Nei ','Lin ','Po ','Ji ','Min ','Wei ','Che ','Gou ','Bong ','Ru ','Taan ', + 'Bu ','Zung ','Kui ','Lao ','Han ','Ying ','Zhi ','Jie ','Xing ','Xie ','Xun ','Shan ','Qian ','Xie ','Su ','Hai ', + 'Mi ','Hun ','Nang ','','Hui ','Na ','Song ','Ben ','Liu ','Jie ','Huang ','Lan ','','Hu ','Dou ','Huo ', + 'Ge ','Yao ','Ce ','Gui ','Jian ','Jian ','Chou ','Jin ','Ma ','Hui ','Men ','Can ','Lue ','Pi ','Yang ','Ju ', + 'Ju ','Que ','','','Shai ','Cau ','Jiu ','Hua ','Xian ','Xie ','Syun ','Su ','Fei ','Ce ','Ye ','', + '','','Qin ','Hui ','Tun ','Ling ','Qiang ','Xi ','Yi ','Nim ','Meng ','Tuan ','Lan ','Hao ','Ci ','Zhai ', + 'Piao ','Luo ','Mi ','Buk ','Fu ','Cam ','Xie ','Bo ','Hui ','Qi ','Xie ','','Hei ','Bo ','Qian ','Ban ', + 'Jiao ','Jue ','Kun ','Song ','Ju ','E ','Nie ','','Die ','Die ','Pei ','Gui ','Zi ','Qi ','Chui ','Gwaat6', + 'Yu ','Qin ','Faat ','Ke ','Fu ','Gaang ','Di ','Xian ','Gui ','He ','Qun ','Han ','Tong ','Bo ','Shan ','Bi ', + 'Lu ','Ye ','Ni ','Chuai ','San ','Diao ','Lu ','Tou ','Lian ','Ke ','San ','Zhen ','Chuai ','Lian ','Mao ','Deon ', + 'Qian ','Ke ','Shao ','Qiao ','Bi ','Zaa ','Yin ','Kaap ','Shan ','Su ','Sa ','Rui ','Zhuo ','Lu ','Ling ','Cha ', + 'Zaai ','Huan ','','','Jia ','Ban ','Hu ','Dou ','Caam ','Lou ','','Juan ','Ke ','Suo ','Ge ','Zhe ', + 'Ding ','Duan ','Zhu ','Yan ','Pang ','Cha ','','','','','Yi ','Zin ','','You ','Gun ','Yao ', + 'Yao ','Shi ','Gong ','Qi ','Gen ','Gwong ','','Hou ','Mi ','Fu ','Hu ','Guang ','Dan ','Dai ','Tou ','Yan ', + '','Dung ','Qu ','','Chang ','Ming ','Tou ','Bao ','On ','Ceon ','Zung ','Xian ','','','','Mao ', + 'Lang ','Nan ','Pei ','Chen ','Hau ','Fei ','Cou ','Gei ','Qie ','Dai ','Sik ','Kun ','Die ','Lu ','Thung ','', + ], + 'x3b':[ + '','Caap ','Yu ','Tai ','Chan ','Man ','Mian ','Huan ','Wan ','Nuan ','Huan ','Hou ','Jing ','Bo ','Xian ','Li ', + 'Jin ','','Mang ','Piao ','Hao ','Yang ','','Xian ','Su ','Wei ','Che ','Kap ','Jin ','Ceng ','He ','', + 'Shai ','Ling ','Fui ','Dui ','Zaap ','Pu ','Yue ','Bo ','','Hui ','Die ','Yan ','Ju ','Jiao ','Kuai ','Lie ', + 'Yu ','Ti ','Tim ','Wu ','Hong ','Xiao ','Hao ','','Tiu ','Zaang ','','Huang ','Fu ','','','Dun ', + '','Reng ','Jiao ','Gong ','Xin ','','','Yuan ','Jue ','Hua ','Sik ','Bang ','Mou ','Cat ','Gong ','Wei ', + '','Mei ','Si ','Bian ','Lu ','Keoi ','','','He ','She ','Lu ','Pai ','Rong ','Qiu ','Lie ','Gong ', + 'Xian ','Xi ','Hing ','','Niao ','','','','Xie ','Lei ','Fu ','Cuan ','Zhuo ','Fei ','Zuo ','Die ', + 'Ji ','He ','Ji ','','Gin ','','','','Tu ','Xian ','Yan ','Tang ','Ta ','Di ','Jue ','Ang ', + 'Han ','Yao ','Ju ','Rui ','Bang ','Zeoi ','Nie ','Tian ','Nai ','','','You ','Mian ','Zin ','Bui ','Nai ', + 'Xing ','Qi ','Zaan ','Gen ','Tong ','Er ','Jia ','Qin ','Mao ','E ','Li ','Chi ','Zong ','He ','Jie ','Ji ', + '','Guan ','Hou ','Gai ','Cung ','Fen ','Se ','Waat ','Ji ','Sik ','Qiong ','He ','Zung ','Xian ','Jie ','Hua ', + 'Bi ','Sing ','Caai ','Zhen ','Sau ','Zin ','Shi ','Gai ','Song ','Zhi ','Ben ','','','','Lang ','Bi ', + 'Xian ','Bang ','Dai ','Cat ','Zi ','Pi ','Chan ','Bi ','Su ','Huo ','Hen ','Ying ','Chuan ','Jiang ','Nen ','Gu ', + 'Fang ','','','Ta ','Cui ','Sai ','De ','Ran ','Kuan ','Che ','Da ','Hu ','Cui ','Lu ','Juan ','Lu ', + 'Qian ','Pao ','Zhen ','Fan ','Li ','Cao ','Qi ','','','Ti ','Ling ','Qu ','Lian ','Lu ','Shu ','Gong ', + 'Zhe ','Biao ','Jin ','Qing ','','','Zong ','Pu ','Jin ','Biao ','Jian ','Gun ','','Ban ','Zou ','Lie ', + ], + 'x3c':[ + 'Li ','Luo ','Shen ','Mian ','Jian ','Di ','Bei ','Cim ','Lian ','Zeon ','Xun ','Pin ','Que ','Long ','Zui ','Gou ', + 'Jue ','San ','She ','','Xie ','Hei ','Lan ','Cu ','Yi ','Nuo ','Li ','Yue ','','Yi ','Ci ','Ji ', + 'Kang ','Xie ','Hang ','Zi ','Ke ','Hui ','Qu ','Hai6','Hei ','Hoi ','Wa ','Caam ','Xun ','Haap6','Shen ','Kou ', + 'Qie ','Sha ','Xu ','Ya ','Po ','Zu ','You ','Zi ','Lian ','Jin ','Xia ','Yi ','Qie ','Mi ','Jiao ','Hei ', + 'Chi ','Shi ','Fong ','Yin ','Mo ','Yi ','Hei ','Se ','Jin ','Ye ','Zaau ','Que ','Che ','Luan ','Kwaan ','Zheng ', + '','','Ho ','','Se ','Gwai ','Cui ','Zaau ','An ','Xiu ','Can ','Chuan ','Zha ','','Ji ','Bo ', + 'Fu ','Sing ','Lang ','Tui ','Sek6','Ling ','E ','Wo ','Lian ','Du ','Men ','Lan ','Wei ','Duan ','Kuai ','Ai ', + 'Zai ','Hui ','Yi ','Mo ','Zi ','Ben ','Beng ','','Bi ','Li ','Lu ','Luo ','Hoi ','Dan ','Goi ','Que ', + 'Chen ','Hung ','Cheng ','Jiu ','Kou ','Ji ','Ling ','Ci ','Shao ','Kai ','Rui ','Chuo ','Neng ','Zi ','Lou ','Bao ', + '','','Bao ','Rong ','Saan ','Lei ','Siu ','Fu ','Qu ','Saau ','Saa ','Zhi ','Tan ','Rong ','Zu ','Ying ', + 'Mao ','Nai ','Bian ','Saau ','Seoi ','Tang ','Han ','Zao ','Rong ','','Dang ','Pu ','Ziu ','Tan ','','Ran ', + 'Ning ','Lie ','Die ','Die ','Zhong ','Siu ','Lu ','Dan ','Kap ','Gui ','Ji ','Ni ','Yi ','Nian ','Yu ','Wang ', + 'Guo ','Ze ','Yan ','Cui ','Xian ','Jiao ','Shu ','Fu ','Pei ','Ngoet ','Zaau ','Zaau ','At ','Bu ','Bian ','Chi ', + 'Sa ','Yi ','Bian ','','Dui ','Lan ','Zi ','Chai ','Cung ','Xuan ','Yu ','Yu ','Zaau ','Hong ','Cung ','', + 'Ta ','Gwo ','','','Suk6','Ju ','Xie ','Xi ','Jian ','Tan ','Pan ','Ta ','Xuan ','Xian ','Niao ','Tan ', + 'Gaau ','','','','Mi ','Ji ','Gou ','Wen ','Faa ','Wang ','You ','Ze ','Bi ','Mi ','Goeng ','Xie ', + ], + 'x3d':[ + 'Fan ','Yi ','Dam ','Lei ','Ying ','Siu ','Jin ','She ','Yin ','Ji ','Zyun ','Su ','','','','Wang ', + 'Mian ','Su ','Yi ','Zai ','Se ','Ji ','Luo ','Zaau ','Mao ','Zha ','Sui ','Zhi ','Bian ','Li ','Caai ','', + '','','','','','Qiao ','Guan ','','Zhen ','Zung ','Nie ','Jun ','Xie ','Yao ','Xie ','Zi ', + 'Neng ','Sam ','Si ','Long ','Chen ','Mi ','Que ','Dam ','Na ','','','','Su ','Xie ','Bo ','Ding ', + 'Cuan ','Fong ','Chuang ','Che ','Han ','Dan ','Hao ','','','','Shen ','Mi ','Chan ','Men ','Han ','Cui ', + 'Jue ','He ','Fei ','Shi ','Che ','Shen ','Nu ','Fu ','Man ','Cing ','','','','Yi ','Chou ','Mei ', + 'Faat ','Bao ','Lei ','Ke ','Dian ','Bi ','Sui ','Ge ','Bi ','Yi ','Xian ','Ni ','Ying ','Zhu ','Chun ','Feng ', + 'Xu ','Piao ','Wu ','Liao ','Cang ','Zou ','Ceoi ','Bian ','Yao ','Huan ','Pai ','Sou ','','Dui ','Jing ','Xi ', + 'Bak6','Guo ','','','Yan ','Xue ','Chu ','Heng ','Ying ','','','','Lian ','Xian ','Huan ','Zaan ', + '','Lian ','Shan ','Cang ','Bei ','Jian ','Shu ','Fan ','Dian ','','Ba ','Yu ','Zyun ','','Nang ','Lei ', + 'Yi ','Dai ','','Chan ','Chao ','Gon ','Jin ','Nen ','Pei ','','','Liao ','Mei ','Jiu ','Siu ','Liu ', + 'Han ','','Yong ','Jin ','Chi ','Ren ','Nong ','','','Hong ','Tian ','Bung ','Oi ','Gwaa ','Biu ','Bo ', + 'Qiong ','','Shu ','Cui ','Hui ','Chao ','Dou ','Guai ','E ','Wei ','Fen ','Tan ','','Lun ','He ','Yong ', + 'Hui ','Nim6','Yu ','Zong ','Yan ','Qiu ','Zhao ','Jiong ','Tai ','Zin ','','Bou ','','Dut ','','Tui ', + 'Lin ','Jiong ','Zha ','Sing ','He ','Zing ','Xu ','','','Hei ','Cui ','Qing ','Mo ','Fung ','Zou ','Beng ', + 'Li ','','','Yan ','Ge ','Mo ','Bei ','Juan ','Die ','Shao ','','Wu ','Yan ','','Jue ','Hin ', + ], + 'x3e':[ + 'Tai ','Han ','','Dian ','Ji ','Jie ','','','Ziu ','Xie ','La ','Fan ','Huo ','Xi ','Nie ','Mi ', + 'Ran ','Cuan ','Yin ','Mi ','','Jue ','Keoi ','Tong ','Wan ','Ze ','Li ','Shao ','Kong ','Kan ','Ban ','Taai ', + 'Tiao ','Syu ','Bei ','Ye ','Pian ','Chan ','Hu ','Ken ','Gaau ','An ','Chun ','Qian ','Bei ','Baa ','Fen ','Fo ', + 'Tuo ','Tuo ','Zuo ','Ling ','','Gui ','Zin ','Shi ','Hou ','Lie ','Saa ','Si ','Fung ','Bei ','Ren ','Du ', + 'Bo ','Liang ','Ci ','Bi ','Ji ','Zong ','Fai ','He ','Li ','Yuan ','Yue ','Saau ','Chan ','Di ','Lei ','Jin ', + 'Chong ','Si ','Pu ','Yi ','Goeng ','Fun ','Huan ','Tao ','Ru ','Ying ','Ying ','Rao ','Yin ','Shi ','Yin ','Jue ', + 'Tun ','Xuan ','Gaa ','Zung ','Qie ','Zhu ','Ciu ','Zoeng ','You ','','Saan ','Xi ','Shi ','Yi ','Mo ','Zaau ', + '','Hu ','Xiao ','Wu ','Gang ','Jing ','Ting ','Shi ','Ni ','Gang ','Ta ','Waai ','Chu ','Chan ','Piao ','Diao ', + 'Nao ','Nao ','Gan ','Gou ','Yu ','Hou ','','Si ','Ci ','Hu ','Yang ','Zung ','Xian ','Ban ','Rong ','Lou ', + 'Zhao ','Can ','Liao ','Piao ','Hai ','Fan ','Han ','Dan ','Zhan ','','Ta ','Zhu ','Ban ','Jian ','Yu ','Zhuo ', + 'You ','Li ','Kut ','Hei ','Cim ','Chan ','Lian ','Hei ','Si ','Jiu ','Pu ','Qiu ','Gong ','Zi ','Yu ','', + 'Si ','Reng ','Niu ','Mei ','Baat ','Jiu ','','Xu ','Ping ','Bian ','Mao ','','','','','Yi ', + 'You ','Gwai ','Ping ','Kuk ','Bao ','Hui ','','','','Bu ','Mang ','La ','Tu ','Wu ','Li ','Ling ', + '','Ji ','Jun ','Lit6','Duo ','Jue ','Dai ','Bei ','','','','','','La ','Bian ','Sui ', + 'Tu ','Die ','','','','','','Duo ','','','Sui ','Bi ','Tu ','Se ','Can ','Tu ', + 'Mian ','Zeon ','Lu ','','','Zhan ','Bi ','Ji ','Cen ','Hyun ','Li ','','','Sui ','Zung ','Shu ', + ], + 'x3f':[ + '','','E ','','Gei ','','','Qiong ','Luo ','Yin ','Tun ','Gu ','Yu ','Lei ','Bei ','Nei ', + 'Pian ','Lian ','Qiu ','Lian ','Waan ','Dong ','Li ','Ding ','Wa ','Zhou ','Gong ','Xing ','Ang ','Fan ','Peng ','Bai ', + 'Tuo ','Syu ','E ','Bai ','Qi ','Chu ','Gong ','Tong ','Han ','Cheng ','Jia ','Huan ','Xing ','Dian ','Mai ','Dong ', + 'E ','Ruan ','Lie ','Sheng ','Ou ','Di ','Yu ','Chuan ','Rong ','Hong ','Tang ','Cong ','Piao ','Shuang ','Lu ','Tong ', + 'Zheng ','Li ','Sa ','Ban ','Si ','Dang ','Dong ','Guai ','Yi ','Han ','Xie ','Luo ','Liu ','Ham ','Dan ','', + 'Cim ','Tan ','Saang ','','','You ','Nan ','','Gang ','Jun ','Chi ','Kou ','Wan ','Li ','Liu ','Lie ', + 'Xia ','Baai ','An ','Yu ','Ju ','Rou ','Xun ','Zi ','Cuo ','Can ','Zeng ','Yong ','Fu ','Ruan ','Sing ','Xi ', + 'Shu ','Jiao ','Jiao ','Han ','Zhang ','Zong ','','Shui ','Chen ','Fan ','Ji ','Zi ','','Gu ','Wu ','Wo ', + 'Qie ','Shu ','Hoi ','Tuo ','Du ','Si ','Ran ','Mu ','Fu ','Ling ','Ji ','Xiu ','Xuan ','Nai ','At ','Jie ', + 'Li ','Da ','Ji ','Zyun ','Lu ','Shen ','Li ','Lang ','Geng ','Yin ','Se ','Qin ','Qie ','Che ','You ','Bu ', + 'Huang ','Que ','Lai ','Zaam ','Hong ','Xu ','Bang ','Ke ','Qi ','Gwaai ','Sheng ','Pin ','Gaai ','Zhou ','Huang ','Tui ', + 'Hu ','Bei ','','','Zaa ','Ji ','Gu ','Sai ','Gao ','Chai ','Ma ','Zhu ','Tui ','Tui ','Lian ','Lang ', + 'Baan ','','Zing ','Dai ','Ai ','Xian ','Gwo ','Xi ','Zung ','Tui ','Can ','Sao ','Cim ','Jie ','Fen ','Qun ', + '','Yao ','Dao ','Jia ','Lei ','Yan ','Lu ','Tui ','Ying ','Pi ','Luo ','Li ','Bie ','Hoeng ','Mao ','Bai ', + 'huang ','Dau ','Yao ','He ','Chun ','Hu ','Ning ','Chou ','Li ','Tang ','Huan ','Bi ','Baa ','Che ','Yang ','Da ', + 'Ao ','Xue ','Zi ','','Daap ','Ran ','Bong ','Zao ','Wan ','Ta ','Bao ','Gon ','Yan ','Gaai ','Zhu ','Ya ', + ], + 'x40':[ + 'Fan ','You ','On ','Tui ','Meng ','She ','Jin ','Gu ','Qi ','Qiao ','Jiao ','Yan ','','Kan ','Mian ','Xian ', + 'San ','Na ','Cin ','Huan ','Niu ','Cheng ','Tin ','Jue ','Xi ','Qi ','Ang ','Mei ','Gu ','','Tou ','Fan ', + 'Qu ','Chan ','Shun ','Bi ','Mao ','Shuo ','Gu ','Hong ','Huan ','Luo ','Hang ','Jia ','Quan ','Goi ','Mang ','Bu ', + 'Gu ','Fung ','Mu ','Ai ','Ying ','Shun ','Lang ','Jie ','Di ','Jie ','Cau ','Pin ','Ren ','Yan ','Du ','Di ', + '','Lang ','Xian ','Biu ','Xing ','Bei ','An ','Mi ','Qi ','Qi ','Wo ','She ','Yu ','Jia ','Cheng ','Yao ', + 'Ying ','Yang ','Ji ','Jie ','Han ','Min ','Lou ','Kai ','Yao ','Yan ','Sun ','Gui ','Huang ','Ying ','Sheng ','Cha ', + 'Lian ','','Xuan ','Chuan ','Che ','Ni ','Qu ','Miao ','Huo ','Yu ','Nan ','Hu ','Ceng ','Biu ','Qian ','She ', + 'Jiang ','Ao ','Mai ','Mang ','Zhan ','Bian ','Jiao ','Jue ','Nong ','Bi ','Shi ','Li ','Mo ','Lie ','Mie ','Mo ', + 'Xi ','Chan ','Qu ','Jiao ','Huo ','Zin ','Xu ','Nang ','Tong ','Hou ','Yu ','','Cung ','Bo ','Zuan ','Diu ', + 'Chuo ','Ci ','Jie ','Kwai ','Xing ','Hui ','Shi ','Gwaat6','Caam ','','Yao ','Yu ','Bang ','Jie ','Zhe ','Gaa ', + 'She ','Di ','Dong ','Ci ','Fu ','Min ','Zhen ','Zhen ','','Yan ','Diao ','Hong ','Gong ','Diu6','Lue ','Guai ', + 'La ','Cui ','Fa ','Cuo ','Yan ','Gung ','Jie ','Gwaai ','Guo ','Suo ','Wan ','Zheng ','Nie ','Diao ','Lai ','Ta ', + 'Cui ','Aa ','Gun ','','','Dai ','','Mian ','Gaai ','Min ','Ju ','Yu ','Zan ','Zhao ','Ze ','Saang ', + '','Pan ','He ','Gou ','Hong ','Lao ','Wu ','Chuo ','Hang ','Lu ','Cu ','Lian ','Zi ','Qiao ','Shu ','', + 'xuan ','Cen ','Zaam ','Hui ','Su ','Chuang ','Deon ','Long ','','Nao ','Tan ','Dan ','Wei ','Gan ','Da ','Li ', + 'Caat ','Xian ','Pan ','La ','Zyu ','Niao ','Huai ','Ying ','Xian ','Lan ','Mo ','Ba ','','Fu ','Bi ','Fu ', + ], + 'x41':[ + 'Huo ','Yi ','Liu ','Zoeng ','Zaan ','Juan ','Huo ','Cheng ','Dou ','E ','','Yan ','Zhui ','Du ','Qi ','Yu ', + 'Quan ','Huo ','Nie ','Heng ','Ju ','She ','','','Peng ','Ming ','Cao ','Lou ','Li ','Chun ','','Cui ', + 'Shan ','Daam ','Qi ','','Lai ','Ling ','Liao ','Reng ','Yu ','Nao ','Chuo ','Qi ','Yi ','Nian ','Fu ','Jian ', + 'Ya ','Fong ','Chui ','Cin ','','','Bi ','Dan ','Po ','Nian ','Zhi ','Chao ','Tian ','Tian ','Rou ','Yi ', + 'Lie ','An ','He ','Qiong ','Li ','Gwai ','Zi ','Su ','Yuan ','Ya ','Du ','Wan ','Gyun ','Dong ','You ','Hui ', + 'Jian ','Rui ','Mang ','Ju ','Zi ','Geoi ','An ','Sui ','Lai ','Hun ','Qiang ','Coeng ','Duo ','Hung ','Na ','Can ', + 'Ti ','Xu ','Jiu ','Huang ','Qi ','Jie ','Mao ','Yan ','Heoi ','Zhi ','Tui ','','Ai ','Pang ','Cang ','Tang ', + 'En ','Hun ','Qi ','Chu ','Suo ','Zhuo ','Nou ','Tu ','Zu ','Lou ','Miao ','Li ','Man ','Gu ','Cen ','Hua ', + 'Mei ','Gou ','Lian ','Dao ','Shan ','Ci ','','','Zhi ','Ba ','Cui ','Qiu ','','Long ','Cim ','Fei ', + 'Guo ','Cheng ','Jiu ','E ','Cung ','Jue ','Hong ','Jiao ','Cuan ','Yao ','Tong ','Cha ','You ','Shu ','Yao ','Ge ', + 'Huan ','Lang ','Jue ','Chen ','Cyun ','Cyun ','Shen ','Fo ','Ming ','Ming ','Hung ','Chuang ','Yun ','Han6','Jin ','Chuo ', + 'Zyu ','Tan ','Hong ','Qiong ','','Cheng ','Zaau ','Yu ','Cheng ','Tong ','Pun ','Qiao ','Fo ','Ju ','Lan ','Yi ', + 'Rong ','Si ','Hin ','Si ','Ngat ','Fa ','','Meng ','Gui ','','','Hai ','Qiao ','Chuo ','Que ','Dui ', + 'Li ','Ba ','Jie ','Seoi ','Luo ','Deoi ','Yun ','Zung ','Hu ','Yin ','Pok ','Zhi ','Lian ','Zim ','Gan ','Jian ', + 'Zhou ','Zhu ','Ku ','Na ','Dui ','Ze ','Yang ','Zhu ','Gong ','Yi ','Ci ','Gei ','Chuang ','Lao ','Ren ','Rong ', + 'Zing ','Na ','Ce ','Zin ','','Yi ','Jue ','Bi ','Cheng ','Jun ','Chou ','Hui ','Chi ','Zhi ','Yan ','', + ], + 'x42':[ + 'Saan ','Lun ','Bing ','Zhao ','Han ','Yu ','Dai ','Zhao ','Fei ','Sha ','Ling ','Ta ','Zeoi ','Mang ','Ye ','Bao ', + 'Kui ','Gua ','Nan ','Ge ','Gaa ','Chi ','Fo ','Suo ','Ci ','Zhou ','Tai ','Kuai ','Qin ','Seoi ','Du ','Ce ', + 'Huan ','Gung ','Sai ','Zheng ','Qian ','Gan ','Zung ','Wei ','','','Xi ','Na ','Pu ','Huai ','Ju ','Zaan ', + 'Sau ','Tou ','Pan ','Ta ','Qian ','Zung ','Rong ','Luo ','Hu ','Sou ','Zung ','Pu ','Mie ','Gan ','Shuo ','Mai ', + 'Shu ','Ling ','Lei ','Jiang ','Leng ','Zhi ','Diao ','','San ','Hu ','Fan ','Mei ','Sui ','Jian ','Tang ','Xie ', + 'Fu ','Mo ','Fan ','Lei ','Can ','Ceng ','Ling ','Zaap ','Cong ','Yun ','Meng ','Yu ','Zhi ','Qi ','Dan ','Huo ', + 'Wei ','Tan ','Se ','Xie ','Sou ','Song ','Cin ','Liu ','Yi ','Aau ','Lei ','Li ','Fei ','Lie ','Lin ','Xian ', + 'Yao ','Aau ','Bie ','Xian ','Rang ','Zhuan ','Soeng ','Dan ','Bian ','Ling ','Hong ','Qi ','Liao ','Ban ','Mi ','Hu ', + 'Hu ','Caap ','Ce ','Pei ','Qiong ','Ming ','Jiu ','Bu ','Mei ','San ','Mei ','Zong ','','Li ','Quan ','Sam ', + 'En ','Xiang ','Zing ','Shi ','Zing ','Gin ','Lan ','Huang ','Jiu ','Yan ','Deoi ','Sa ','Tuan ','Xie ','Zhe ','Men ', + 'Xi ','Man ','Zoeng ','Huang ','Tan ','Xiao ','Ya ','Bi ','Luo ','Fan ','Li ','Cui ','Cha ','Chou ','Di ','Kuang ', + 'Chu ','Cim ','Chan ','Mi ','Qian ','Qiu ','Zhen ','Zi ','Heoi ','Cim ','Gu ','Yan ','Chi ','Guai ','Mu ','Bo ', + 'Kua ','Geng ','Yao ','Mao ','Wang ','','','','Ru ','Jue ','Zing ','Min ','Jiang ','O ','Zhan ','Zuo ', + 'Yue ','Bing ','Nou6','Zhou ','Bi ','Ren ','Yu ','Gin ','Chuo ','Er ','Yi ','Mi ','Qing ','Zing ','Wang ','Ji ', + 'Bu ','Syu ','Bie ','Fan ','Yao ','Li ','Fan ','Qu ','Fu ','Er ','O ','Zang ','Zim ','Huo ','Jin ','Qi ', + 'Ju ','Lai ','Che ','Bei ','Niu ','Yi ','Xu ','Liu ','Xun ','Fu ','Cau ','Nin ','Ting ','Beng ','Zha ','Wui ', + ], + 'x43':[ + 'Fo ','Zaau ','Ou ','Shuo ','Geng ','Tang ','Gui ','Hui ','Ta ','Gong ','Yao ','Daap ','Qi ','Han ','Lue ','Mi ', + 'Mi ','Gin ','Lu ','Fan ','Ou ','Mi ','Jie ','Fu ','Mi ','Huang ','Su ','Yao ','Nie ','Jin ','Lian ','Bi ', + 'Qing ','Ti ','Ling ','Zuan ','Zhi ','Yin ','Dao ','Chou ','Cai ','Mi ','Yan ','Lan ','Chong ','Ziu ','Soeng ','Guan ', + 'She ','Luo ','Fan ','Si ','Luo ','Zhu ','Zi ','Chou ','Juan ','Jiong ','Er ','Yi ','Rui ','Cai ','Ren ','Fu ', + 'Lan ','Sui ','Yu ','Yao ','Dian ','Ling ','Zhu ','Ta ','Ping ','Qian ','Jue ','Chui ','Bu ','Gu ','Cun ','', + 'Han ','Han ','Mou ','Hu ','Hong ','Di ','Fu ','Xuan ','Mi ','Mei ','Lang ','Gu ','Zhao ','Ta ','Yu ','Zong ', + 'Li ','Liao ','Wu ','Lei ','Ji ','Lei ','Li ','Zong ','Bo ','Ang ','Kui ','Tuo ','Ping ','Cau ','Zhao ','Gui ', + 'Zaan ','Xu ','Nai ','Chuo ','Duo ','Kaap ','Dong ','Gui ','Bo ','Zin ','Huan ','Xuan ','Can ','Li ','Tui ','Huang ', + 'Xue ','Hu ','Bao ','Ran ','Tiao ','Fu ','Liao ','Zaau ','Yi ','Shu ','Po ','He ','Cu ','Fu ','Na ','An ', + 'Chao ','Lu ','Zhan ','Ta ','Fu ','Gwaang ','Zang ','Qiao ','Su ','Baan ','Guan ','','Fan ','Chu ','','Er ', + 'Er ','Nuan ','Qi ','Si ','Chu ','','Yan ','Bang ','An ','Zi ','Ne ','Chuang ','Ba ','Ciu ','Ti ','Han ', + 'Zuo ','Ba ','Zhe ','Wa ','Sheng ','Bi ','Er ','Zhu ','Wu ','Wen ','Zhi ','Zhou ','Lu ','Wen ','Gun ','Qiu ', + 'La ','Zai ','Sou ','Mian ','Zhi ','Qi ','Cao ','Piao ','Lian ','Saap ','Long ','Su ','Qi ','Yuan ','Feng ','Heoi ', + 'Jue ','Di ','Pian ','Guan ','Niu ','Ren ','Zhen ','Gai ','Pi ','Tan ','Chao ','Chun ','Ho ','Chun ','Mo ','Bie ', + 'Qi ','Shi ','Bi ','Jue ','Si ','Taam ','Hua ','Na ','Hui ','Kaap ','Er ','Caau ','Mou ','Zyu ','Xi ','Zhi ', + 'Ren ','Ju ','Die ','Zhe ','Shao ','Meng ','Bi ','Han ','Yu ','Xian ','Pong ','Neng ','Can ','Bu ','Pong ','Qi ', + ], + 'x44':[ + 'Ji ','Niao ','Lu ','Jiong ','Han ','Yi ','Cai ','Chun ','Zhi ','Zi ','Da ','Cung ','Tian ','Zhou ','Daai ','Chun ', + 'Cau ','Zhe ','Zaa ','Rou ','Bin ','Ji ','Yi ','Du ','Jue ','Ge ','Ji ','Dap ','Can ','Suo ','Ruo ','Xiang ', + 'Huang ','Qi ','Zhu ','Cuo ','Chi ','Weng ','Haap6','Kao ','Gu ','Kai ','Fan ','Sung ','Cao ','Zhi ','Chan ','Lei ', + 'Gaau ','Zak6','Zhe ','Yu ','Gui ','Huang ','Jin ','Daan ','Guo ','Sao ','Tan ','','Xi ','Man ','Duo ','Ao ', + 'Pi ','Wu ','Ai ','Meng ','Pi ','Meng ','Yang ','Zhi ','Bo ','Ying ','Wei ','Nao ','Lan ','Yan ','Chan ','Quan ', + 'Zhen ','Pu ','','Tai ','Fei ','Shu ','','Dang ','Cha ','Ran ','Tian ','Chi ','Ta ','Jia ','Shun ','Huang ', + 'Liao ','Caa ','Dou ','','Jin ','E ','Keoi ','Fu ','Duo ','','E ','','Yao ','Di ','','Di ', + 'Bu ','Man ','Che ','Lun ','Qi ','Mu ','Can ','','Zung ','Sau ','Fan ','You ','Saau ','Da ','','Su ', + 'Fu ','Ji ','Jiang ','Cao ','Bo ','Teng ','Che ','Fu ','Bu ','Wu ','Haai ','Yang ','Ming ','Pang ','Mang ','Zang ', + 'Meng ','Cao ','Tiao ','Kai ','Bai ','Xiao ','Xin ','Qi ','Seoi ','','Shao ','Heng ','Niu ','Xiao ','Chen ','Daan ', + 'Fan ','Yin ','Ang ','Ran ','Ri ','Fa ','Fan ','Qu ','Shi ','He ','Bian ','Dai ','Mo ','Deng ','','', + 'Hong ','Zing ','Cha ','Duo ','You ','Hao ','Tin ','Kut ','Xian ','Lei ','Jin ','Qi ','','Mei ','Zi ','', + '','','Yan ','Yi ','Yin ','Qi ','Zhe ','Xi ','Yi ','Ye ','E ','','Zhi ','Han ','Chuo ','', + 'Chun ','Bing ','Kuai ','Chou ','','Tuo ','Qiong ','Cung ','Jiu ','Gwai ','Cu ','Fu ','','Meng ','Li ','Lie ', + 'Ta ','Zi ','Gu ','Liang ','Fat ','La ','Dian ','Ci ','Aang ','','','Ji ','','Cha ','Mao ','Du ', + 'Zaan ','Chai ','Rui ','Hen ','Ruan ','','Lai ','Xing ','Gan ','Yi ','Mei ','','He ','Ji ','So ','Han ', + ], + 'x45':[ + 'Seoi ','Li ','Zi ','Zu ','Yao ','Geoi ','Li ','Qi ','Gan ','Li ','','','','','Su ','Chou ', + '','Xie ','Bei ','Xu ','Jing ','Pu ','Ling ','Xiang ','Zuo ','Diao ','Chun ','Qing ','Nan ','','Lu ','Chi ', + 'Shao ','Yu ','Hua ','Li ','','Siu ','','Li ','','','Dui ','','Yi ','Ning ','Si ','Hu ', + 'Fu ','Zaap ','Cheng ','Nan ','Ce ','Gaan ','Ti ','Qin ','Biao ','Sui ','Wei ','Deon ','Se ','Ai ','E ','Jie ', + 'Kuan ','Fei ','','Yin ','Zing ','Sao ','Dou ','Hui ','Xie ','Ze ','Tan ','Chang ','Zhi ','Yi ','Fu ','E ', + '','Jun ','Gaa ','Cha ','Xian ','Man ','Syun ','Bi ','Ling ','Jie ','Kui ','Jia ','','Cing ','Lang ','Guk ', + 'Fei ','Lu ','Zha ','He ','','Ni ','Ying ','Xiao ','Teng ','Lao ','Ze ','Kui ','Goeng ','Qian ','Ju ','Piao ', + 'Ban ','Dou ','Lin ','Mi ','Zhuo ','Xie ','Hu ','Mi ','Gaai ','Za ','Cong ','Ge ','Nan ','Zhu ','Yan ','Han ', + 'Ceoi ','Yi ','Luan ','Yue ','Ran ','Ling ','Niang ','Yu ','Nue ','Heoi ','Yi ','Nue ','Qin ','Qian ','Xia ','Chu ', + 'Jin ','Mi ','','Na ','Han ','Zu ','Xia ','Yan ','Tu ','','Wu ','Suo ','Yin ','Chong ','Zhou ','Mang ', + 'Yuan ','Nu ','Miao ','Sao ','Wan ','Li ','','Na ','Shi ','Bi ','Ci ','Bang ','','Juan ','Xiang ','Gui ', + 'Pai ','Hong ','Xun ','Zha ','Yao ','Kwan ','','Hei ','E ','Yang ','Tiao ','You ','Jue ','Li ','','Li ', + '','Ji ','Hu ','Zhan ','Fu ','Chang ','Guan ','Ju ','Meng ','Coeng ','Cheng ','Mou ','Sing ','Li ','Zaan ','', + 'Si ','Yi ','Bing ','Cung ','Hou ','Wan ','Chi ','','Ge ','Han ','Bo ','Saau ','Liu ','Can ','Can ','Yi ', + 'Xuan ','Yan ','Suo ','Gao ','Yong ','Zung ','Fung ','Hong ','Yu ','Cik ','Zhe ','Ma ','Fung ','','Shuang ','Jin ', + 'Guan ','Pu ','Lin ','','Ting ','Goeng ','La ','Yi ','Zung ','Ci ','Yan ','Jie ','Faan ','Wei ','Xian ','Ning ', + ], + 'x46':[ + 'Fu ','Ge ','','Mo ','Fu ','Nai ','Xian ','Wen ','Li ','Can ','Mie ','','Ni ','Chai ','Wan ','Xu ', + 'Nu ','Mai ','Co ','Kan ','Ho ','Hang ','','Faai ','Yu ','Wei ','Zhu ','Gei ','Gan ','Yi ','','', + 'Fu ','Bi ','Zhu ','Zi ','Shu ','Xia ','Ni ','','Jiao ','Xuan ','Cung ','Nou ','Rong ','Die ','Sa ','Sau ', + '','Yu ','','Kaam ','Zung ','Lu ','Han ','','Yi ','Zui ','Zhan ','Su ','Wan ','Ni ','Guan ','Jue ', + 'Beng ','Can ','Zung ','Duo ','Qi ','Yao ','Gui ','Nuan ','Hou ','Xun ','Xie ','','Hui ','','Xie ','Bo ', + 'Ke ','Ceoi ','Xu ','Bai ','Aau ','Chu ','Bang ','Ti ','Chu ','Chi ','Niao ','Guan ','Feng ','Xie ','Dang ','Duo ', + 'Jue ','Hui ','Zeng ','Sa ','Duo ','Ling ','Meng ','Fan ','Guo ','Meng ','Long ','','Ying ','Hin ','Guan ','Cu ', + 'Li ','Du ','Ceng ','E ','Sin ','Saai ','','De ','De ','Jiang ','Lian ','','Shao ','Xi ','Si ','Wei ', + '','','He ','You ','Lu ','Lai ','Ou ','Sheng ','Juan ','Qi ','','Yun ','','Qi ','Zong ','Leng ', + 'Ji ','Mai ','Chuang ','Nian ','Baan ','Li ','Ling ','Gong ','Chen ','','Xian ','Hu ','Bei ','Zu ','Dai ','Dai ', + 'Hun ','Soi ','Che ','Ti ','','Nuo ','Zhi ','Liu ','Fei ','Jiao ','Gwaan ','Ao ','Lin ','','Reng ','Tao ', + 'Pi ','Xin ','Shan ','Xie ','Wa ','Tao ','Tin ','Xi ','Xie ','Pi ','Yao ','Yao ','Nu ','Hao ','Nin ','Yin ', + 'Fan ','Nan ','Chi ','Wang ','Yuan ','Xia ','Zhou ','Yuan ','Shi ','Mi ','','Ge ','Pao ','Fei ','Hu ','Ni ', + 'Ci ','Mi ','Bian ','Gam ','Na ','Yu ','E ','Zhi ','Nin ','Xu ','Lue ','Hui ','Xun ','Nao ','Han ','Jia ', + 'Dou ','Hua ','Tuk ','','Cu ','Xi ','Song ','Mi ','Xin ','Wu ','Qiong ','Zheng ','Chou ','Xing ','Jiu ','Ju ', + 'Hun ','Ti ','Man ','Jian ','Qi ','Shou ','Lei ','Wan ','Che ','Can ','Jie ','You ','Hui ','Zha ','Su ','Ge ', + ], + 'x47':[ + 'Nao ','Xi ','','Deoi ','Chi ','Wei ','Mo ','Gun ','Cau ','','Zao ','Hui ','Luan ','Liao ','Lao ','', + '','Qia ','Ao ','Nie ','Sui ','Mai ','Tan ','Xin ','Jing ','An ','Ta ','Chan ','Wei ','Tuan ','Ji ','Chen ', + 'Che ','Xu ','Xian ','Xin ','','Daan ','','Nao ','','Yan ','Qiu ','Hong ','Song ','Jun ','Liao ','Ju ', + '','Man ','Lie ','','Chu ','Chi ','Xiang ','Cam ','Mei ','Shu ','Ce ','Chi ','Gu ','Yu ','Zaam ','', + 'Liao ','Lao ','Shu ','Zhe ','Soeng ','','Fat ','Fui ','E ','','Sha ','Zong ','Jue ','Jun ','','Lou ', + 'Wei ','Cung ','Zhu ','La ','Fun ','Zhe ','Zhao ','Zaau ','Yi ','','Ni ','Bo ','Syun ','Yi ','Hao ','Ya ', + 'Huan ','Man ','Man ','Qu ','Lao ','Hao ','','Men ','Xian ','Zhen ','Shu ','Zuo ','Zhu ','Gou ','Xuan ','Yi ', + 'Ti ','xie ','Jin ','Can ','Zai ','Bu ','Liang ','Zhi ','Ji ','Wan ','Guan ','Ceoi ','Qing ','Ai ','Fu ','Gui ', + 'Gou ','Xian ','Ruan ','Zhi ','Biao ','Yi ','Suo ','Die ','Gui ','Sheng ','Xun ','Chen ','She ','Qing ','','', + 'Chun ','Hong ','Dong ','Cheng ','Wei ','Die ','Shu ','Caai ','Ji ','Za ','Qi ','','Fu ','Ao ','Fu ','Po ', + '','Tan ','Zha ','Che ','Qu ','You ','He ','Hou ','Gui ','E ','Jiang ','Yun ','Tou ','Qiu ','','Fu ', + 'Zuo ','Hu ','','Bo ','','Jue ','Di ','Jue ','Fu ','Huang ','','Yong ','Chui ','Suo ','Chi ','Hin ', + '','','Man ','Ca ','Qi ','Jian ','Bi ','Gei ','Zhi ','Zhu ','Qu ','Zhan ','Ji ','Dian ','','Li ', + 'Li ','La ','Quan ','Ding ','Fu ','Cha ','Tang ','Shi ','Hang ','Qie ','Qi ','Bo ','Na ','Tou ','Chu ','Cu ', + 'Yue ','Di ','Chen ','Chu ','Bi ','Mang ','Ba ','Tian ','Min ','Lie ','Feng ','Caang ','Qiu ','Tiao ','Fu ','Kuo ', + 'Jian ','Ci ','','','Zhen ','Qiu ','Cuo ','Chi ','Kui ','Lie ','Bang ','Du ','Wu ','So ','Jue ','Lu ', + ], + 'x48':[ + 'Chang ','Zai ','Chu ','Liang ','Tian ','Kun ','Chang ','Jue ','Tu ','Hua ','Fei ','Bi ','','Qia ','Wo ','Ji ', + 'Qu ','Kui ','Hu ','Cu ','Sui ','','','Qiu ','Pi ','Bei ','Wa ','Jiao ','Rong ','','Cu ','Die ', + 'Chi ','Cuo ','Meng ','Xuan ','Duo ','Bie ','Zhe ','Chu ','Chan ','Gui ','Duan ','Zou ','Deng ','Lai ','Teng ','Yue ', + 'Quan ','Shu ','Ling ','','Qin ','Fu ','She ','Tiao ','','Ai ','','Qiong ','Diao ','Hai ','Shan ','Wai ', + 'Zhan ','Long ','Jiu ','Li ','','Min ','Rong ','Yue ','Jue ','Kang ','Fan ','Qi ','Hong ','Fu ','Lu ','Hong ', + 'Tuo ','Min ','Tian ','Juan ','Qi ','Zheng ','Jing ','Gong ','Tian ','Lang ','Mao ','Yin ','Lu ','Yun ','Ju ','Pi ', + '','Xie ','Bian ','','Zeoi ','Rong ','Sang ','Wu ','Cha ','Gu ','Chan ','Peng ','Man ','Saau ','Zung ','Shuang ', + 'Keng ','Zhuan ','Chan ','Si ','Chuang ','Sui ','Bei ','Kai ','','Zhi ','Wei ','Min ','Ling ','','Nei ','Ling ', + 'Qi ','Yue ','Lip ','Yi ','Xi ','Chen ','','Rong ','Chen ','Nong ','You ','Ji ','Bo ','Fang ','Gei ','', + 'Cu ','Di ','Gaau ','Yu ','Ge ','Xu ','Lu ','He ','','Bai ','Gong ','Jiong ','Gwai ','Ya ','Nu ','You ', + 'Song ','Xie ','Cang ','Yao ','Shu ','Yan ','Shuai ','Liao ','Sung ','Yu ','Bo ','Sui ','Cin ','Yan ','Lei ','Lin ', + 'Tai ','Du ','Yue ','Ji ','Cin ','Yun ','Bong ','','','Ju ','Ceot ','Chen ','Cung ','Xiang ','Xian ','On ', + 'Gui ','Yu ','Lei ','','Tu ','Chen ','Xing ','Qiu ','Hang ','','Dang ','Cai ','Di ','Yan ','Ci ','Gung ', + 'Zing ','Chan ','','Li ','Suo ','Ma ','Ma ','','Tang ','Pei ','Lou ','Sat ','Cuo ','Tu ','E ','Can ', + 'Jie ','Ti ','Ji ','Dang ','Jiao ','Bi ','Lei ','Yi ','Chun ','Chun ','Po ','Li ','Zai ','Tai ','Po ','Tian ', + 'Ju ','Xu ','Fan ','','Xu ','Er ','Huo ','Zyu ','Ran ','Fa ','Gyun ','','Liang ','Ti ','Mi ','', + ], + 'x49':[ + '','Cen ','Mei ','Yin ','Mian ','Tu ','Kui ','Sau ','Hei ','Mi ','Rong ','Guo ','Coeng ','Mi ','Ju ','Pi ', + 'Jin ','Wang ','Ji ','Meng ','Jian ','Xue ','Bao ','Gan ','Chan ','Li ','Li ','Qiu ','Dun ','Ying ','Yun ','Chen ', + 'Ji ','Ran ','','Lue ','','Gui ','Yue ','Hui ','Pi ','Cha ','Duo ','Chan ','So ','Kuan ','She ','Xing ', + 'Weng ','Shi ','Chi ','Ye ','Han ','Fei ','Ye ','Yan ','Zuan ','Saau ','Yin ','Duo ','Xian ','Gwaan ','Tou ','Qie ', + 'Chan ','Han ','Meng ','Yue ','Cu ','Qian ','Jin ','Shan ','Mu ','Zyun ','Coeng ','Baang ','Zheng ','Zhi ','Chun ','Yu ', + 'Mou ','Wan ','Chou ','Kei ','Su ','Pie ','Tian ','Kuan ','Cu ','Sui ','Co ','Jie ','Jian ','Ao ','Jiao ','Ye ', + 'Saam ','Ye ','Long ','Zao ','Bao ','Lian ','','Huan ','Lu ','Wei ','Xian ','Tie ','Bo ','Zheng ','Zhu ','Ba ', + 'Meng ','Xie ','Aau ','Zaau ','Teon ','Xiao ','Li ','Zha ','Mi ','','Ye ','','','Put ','Xie ','', + '','Bong ','Shan ','Coeng ','','Shan ','Jue ','Ji ','Fang ','','Niao ','Ao ','Chu ','Wu ','Guan ','Xie ', + 'Ting ','Xie ','Dang ','Zim ','Tan ','Ping ','Xia ','Xu ','Bi ','Si ','Huo ','Zheng ','Wu ','','Run ','Chuai ', + 'Shi ','Huan ','Kuo ','Fu ','Chuai ','Xian ','Qin ','Qie ','Lan ','','Ya ','Zing ','Que ','','Chun ','Zhi ', + 'Gau ','Kui ','Qian ','Hang ','Yi ','Ni ','Zheng ','Chuai ','','Shi ','Cap ','Ci ','Jue ','Xu ','Yun ','', + '','Chu ','Dao ','Dian ','Ge ','Ti ','Hong ','Ni ','','Li ','','Xian ','Seoi ','Xi ','Xuan ','', + 'Gwik ','Taai ','Lai ','Zau ','Mu ','Cheng ','Jian ','Bi ','Qi ','Ling ','Hao ','Bang ','Tang ','Di ','Fu ','Xian ', + 'Shuan ','Zung ','Keoi ','Zaan ','Pu ','Hui ','Wei ','Yi ','Ye ','','Che ','Hao ','Baai ','','Xian ','Chan ', + 'Hun ','Gaau ','Han ','Ci ','Zi ','Qi ','Kui ','Rou ','Gu ','Zing ','Xiong ','Gap ','Hu ','Cui ','Syu ','Que ', + ], + 'x4a':[ + 'Di ','Che ','Cau ','','Yan ','Liao ','Bi ','Soeng ','Ban ','Zing ','','Nue ','Bao ','Ying ','Hong ','Ci ', + 'Qia ','Ti ','Yu ','Lei ','Bao ','Wu ','Ji ','Fu ','Xian ','Cen ','Fat ','Se ','Baang ','Cing ','Yu ','Waa ', + 'Ai ','Han ','Dan ','Ge ','Di ','Hu ','Pang ','Zaam ','Zaa ','Ling ','Mai ','Mai ','Lian ','Siu ','Xue ','Zhen ', + 'Po ','Fu ','Nou ','Xi ','Dui ','Dan ','Yun ','Xian ','Yin ','Suk ','Dui ','Beng ','Hu ','Fei ','Fei ','Qian ', + 'Bei ','Fei ','','Shi ','Tian ','Zhan ','Jian ','','Hui ','Fu ','Wan ','Mo ','Qiao ','Liao ','','Mie ', + 'Ge ','Hong ','Yu ','Qi ','Duo ','Ang ','Saa ','Ba ','Di ','Xuan ','Di ','Bi ','Zhou ','Pao ','Nian ','Yi ', + 'Ting ','Jia ','Da ','Duo ','Xi ','Dan ','Tiao ','Xie ','Chang ','Yuan ','Guan ','Liang ','Beng ','Gei ','Lu ','Ji ', + 'Xuan ','Shu ','Dou ','Shu ','Hu ','Yun ','Chan ','Bong ','Rong ','E ','Zung ','Ba ','Feng ','Zyu ','Zhe ','Fen ', + 'Guan ','Bu ','Ge ','Deon ','Huang ','Du ','Ti ','Bo ','Qian ','La ','Long ','Wei ','Zhan ','Lan ','Seoi ','Na ', + 'Bi ','Tuo ','Jiao ','','Bu ','Ju ','Po ','Xia ','Wei ','Fu ','He ','Fan ','Chan ','Hu ','Za ','', + 'Saai ','Zai ','Zai ','Zai ','Fan ','Die ','Hong ','Chi ','Bao ','Yin ','','Haang ','Bo ','Ruan ','Chou ','Ying ', + 'Zi ','Gai ','Kwaan ','Yun ','Zhen ','Ya ','Zeoi ','Hou ','Min ','Pei ','Ge ','Bian ','Zyut ','Hao ','Mi ','Sheng ', + 'Gen ','Bi ','Duo ','Chun ','Chua ','San ','Cheng ','Ran ','Zen ','Mao ','Bo ','Tui ','Pi ','Fu ','Zyut ','Hei ', + 'Lin ','Hei ','Men ','Wu ','Qi ','Zhi ','Chen ','Xia ','He ','Sang ','Gwaa ','Hou ','Au ','Fu ','Rao ','Hun ', + 'Pei ','Qian ','Si ','Xi ','Ming ','Kui ','Ge ','','Ao ','San ','Shuang ','Lou ','Zhen ','Hui ','Can ','Ci ', + 'Lin ','Na ','Han ','Du ','Jin ','Mian ','Fan ','E ','Nao ','Hong ','Hong ','Xue ','Xue ','Pau ','Bi ','Ciu ', + ], + 'x4b':[ + 'You ','Yi ','Xue ','Sa ','Yu ','Li ','Li ','Yuan ','Dui ','Hao ','Qie ','Leng ','Paau ','Fat ','Guo ','Bu ', + 'Wei ','Wei ','Saau ','An ','Xu ','Shang ','Heng ','Yang ','Gwik ','Yao ','Fan ','Bi ','Ci ','Heng ','Tao ','Liu ', + 'Fei ','Zhu ','Tou ','Qi ','Chao ','Yi ','Dou ','Yuan ','Cu ','Zai ','Bo ','Can ','Yang ','Tou ','Yi ','Nian ', + 'Shao ','Ben ','Ngaau ','Ban ','Mo ','Ai ','En ','She ','Caan ','Zhi ','Yang ','Jian ','Yuan ','Dui ','Ti ','Wei ', + 'Xun ','Zhi ','Yi ','Ren ','Shi ','Hu ','Ne ','Yi ','Jian ','Sui ','Ying ','Bao ','Hu ','Hu ','Xie ','', + 'Yang ','Lian ','Sik ','En ','Deoi ','Jian ','Zhu ','Ying ','Yan ','Jin ','Chuang ','Dan ','','Kuai ','Yi ','Ye ', + 'Jian ','En ','Ning ','Ci ','Qian ','Xue ','Bo ','Mi ','Shui ','Mi ','Liang ','Qi ','Qi ','Shou ','Bi ','Bo ', + 'Beng ','Bie ','Ni ','Wei ','Huan ','Fan ','Qi ','Liu ','Fu ','Ang ','Ang ','Fan ','Qi ','Qun ','Tuo ','Yi ', + 'Bo ','Pian ','Bo ','Keoi ','Xuan ','','Baai6','Yu ','Chi ','Lu ','Yi ','Li ','Zaau ','Niao ','Xi ','Wu ', + 'Gwing ','Lei ','Pei ','Zhao ','Zui ','Chuo ','Coeng ','An ','Er ','Yu ','Leng ','Fu ','Sha ','Huan ','Chu ','Sou ', + 'Bik ','Bi ','Die ','Song ','Di ','Li ','Giu ','Han ','Zai ','Gu ','Cheng ','Lou ','Mo ','Mi ','Mai ','Ao ', + 'Dan ','Zhu ','Huang ','Fan ','Deng ','Tong ','','Du ','Hu ','Wei ','Ji ','Chi ','Lin ','Biu ','Pang ','Jian ', + 'Nie ','Luo ','Ji ','Ngon ','Waa ','Nie ','Yi ','Gwaat6','Wan ','Ya ','Qia ','Bo ','Hau ','Ling ','Gan ','Huo ', + 'Hai ','Hong ','Heng ','Kui ','Cen ','Ting ','Lang ','Bi ','Huan ','Po ','Ou ','Jian ','Ti ','Sui ','Kwaa ','Dui ', + 'Ao ','Jian ','Mo ','Gui ','Kuai ','An ','Ma ','Qing ','Fen ','','Kao ','Hao ','Duo ','Cim ','Nai ','Seoi ', + 'Jie ','Fu ','Pa ','Sung ','Chang ','Nie ','Man ','Sung ','Ci ','Cim ','Kuo ','Gai ','Di ','Fu ','Tiao ','Zu ', + ], + 'x4c':[ + 'Wo ','Fei ','Cai ','Peng ','Shi ','Sou ','Rou ','Qi ','Cha ','Pan ','Bo ','Man ','Zong ','Ci ','Gui ','Ji ', + 'Lan ','Siu ','Meng ','Mian ','Pan ','Lu ','Cuan ','Gau ','Liu ','Yi ','Wen ','Li ','Li ','Zeng ','Zhu ','Hun ', + 'Shen ','Chi ','Xing ','Wang ','Dung ','Huo ','Pi ','Bou6','Mei ','Che ','Mei ','Chao ','Ju ','Nou ','','Ni ', + 'Ru ','Ling ','Ya ','','Qi ','Zi ','','Bang ','Gung ','Ze ','Jie ','Yu ','Xin ','Bei ','Ba ','Tuo ', + 'Ong ','Qiao ','You ','Di ','Jie ','Mo ','Sheng ','Shan ','Qi ','Shan ','Mi ','Dan ','Yi ','Geng ','Geng ','Tou ', + 'Fu ','Xue ','Yi ','Ting ','Tiao ','Mou ','Liu ','Caan ','Li ','Suk ','Lu ','Xu ','Cuo ','Ba ','Liu ','Ju ', + 'Zhan ','Ju ','Zang ','Zu ','Xian ','Zhi ','','','Zhi ','','','La ','Seoi ','Geng ','E ','Mu ', + 'Zhong ','Di ','Yan ','Zin ','Geng ','Zung ','Lang ','Yu ','Caau ','Na ','Hai ','Hua ','Zhan ','Coeng ','Lou ','Chan ', + 'Die ','Wei ','Xuan ','Zao ','Min ','Kwai ','Sou ','','','Si ','Tuo ','Cen ','Kuan ','Teng ','Nei ','Lao ', + 'Lu ','Yi ','Xie ','Yan ','Qing ','Pu ','Chou ','Xian ','Guan ','Jie ','Lai ','Meng ','Ye ','Ceoi ','Li ','Yin ', + 'Ceon ','Cau ','Teng ','Yu ','','Gau ','Cha ','Du ','Hong ','Si ','Xi ','Gaau ','Qi ','Ci ','Yuan ','Ji ', + 'Yun ','Fang ','Gung ','Hang ','Zhen ','Hu ','','','Jie ','Pei ','Gan ','Xuan ','Saang ','Dao ','Qiao ','Ci ', + 'Die ','Ba ','Tiao ','Wan ','Ci ','Zhi ','Bai ','Wu ','Bao ','Dan ','Ba ','Tong ','Gyun ','Gung ','Jiu ','Gui ', + 'Ci ','You ','Yuan ','Lao ','Jiu ','Fou ','Nei ','E ','E ','Xing ','He ','Yan ','Tu ','Bu ','Beng ','Kou ', + 'Chui ','Zeoi ','Qi ','Yuan ','Bit ','','Hyun ','Hou ','Huang ','Ziu ','Juan ','Kui ','E ','Ji ','Mo ','Chong ', + 'Bao ','Wu ','Zhen ','Xu ','Da ','Chi ','Gaai ','Cong ','Ma ','Kou ','Yan ','Can ','Aau ','He ','Dang ','Lan ', + ], + 'x4d':[ + 'Tong ','Yu ','Hang ','Nao ','Li ','Fen ','Pu ','Ling ','Ao ','Xuan ','Yi ','Xuan ','Meng ','Ang ','Lei ','Yan ', + 'Bao ','Die ','Ling ','Shi ','Jiao ','Lie ','Jing ','Ju ','Ti ','Pi ','Gang ','Jiao ','Huai ','Bu ','Di ','Huan ', + 'Yao ','Li ','Mi ','Fu ','Saang ','Gaa ','Ren ','Wai ','','Piao ','Lu ','Ling ','Yi ','Cai ','Shan ','Fat ', + 'Shu ','Tuo ','Mo ','He ','Tie ','Bing ','Peng ','Hun ','Fu ','Guo ','Bu ','Li ','Chan ','Bai ','Cuo ','Meng ', + 'Suo ','Qiang ','Zhi ','Kuang ','Bi ','Ao ','Meng ','Xian ','Guk ','Tou ','Teon ','Wei ','Cim ','Tan ','Caau ','Lao ', + 'Chan ','Ni ','Ni ','Li ','Dong ','Ju ','Jian ','Fu ','Sha ','Zha ','Tao ','Jian ','Nong ','Ya ','Jing ','Gan ', + 'Di ','Jian ','Mei ','Da ','Jian ','She ','Xie ','Zai ','Mang ','Li ','Gun ','Yu ','Ta ','Zhe ','Yang ','Tuan ', + 'Soeng ','He ','Diao ','Wei ','Yun ','Zha ','Qu ','Waa ','Caau ','Zi ','Ting ','Gu ','Soeng ','Ca ','Fu ','Tie ', + 'Ta ','Ta ','Zhuo ','Han ','Ping ','He ','Ceoi ','Zhou ','Bo ','Liu ','Nu ','Kaap ','Pao ','Di ','Sha ','Ti ', + 'Kuai ','Ti ','Qi ','Ji ','Chi ','Pa ','Jin ','Ke ','Li ','Ju ','Qu ','La ','Gu ','Qia ','Qi ','Xian ', + 'Jian ','Shi ','Xian ','Ai ','Hua ','Ju ','Ze ','Yao ','Tam ','Ji ','Cha ','Kan ','Gin ','','Yan ','Gwaai ', + 'Ziu ','Tong ','Nan ','Yue ','Ceoi ','Chi ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x4e':[ + 'Yi ','Ding ','Kao ','Qi ','Shang ','Xia ','','Wan ','Zhang ','San ','Shang ','Xia ','Ji ','Bu ','Yu ','Mian ', + 'Gai ','Chou ','Chou ','Zhuan ','Qie ','Pi ','Shi ','Shi ','Qiu ','Bing ','Ye ','Cong ','Dong ','Si ','Cheng ','Diu ', + 'Qiu ','Liang ','Diu ','You ','Liang ','Yan ','Bing ','Sang ','Gun ','Jiu ','Ge ','Ya ','Qiang ','Zhong ','Ji ','Jie ', + 'Feng ','Guan ','Chuan ','Chan ','Lin ','Zhuo ','Zhu ','Ha ','Wan ','Dan ','Wei ','Zhu ','Jing ','Li ','Ju ','Pie ', + 'Fu ','Yi ','Yi ','Nai ','Shime ','Jiu ','Jiu ','Zhe ','Yao ','Yi ','','Zhi ','Wu ','Zha ','Hu ','Fa ', + 'Le ','Zhong ','Ping ','Pang ','Qiao ','Hu ','Guai ','Cheng ','Cheng ','Yi ','Yin ','','Mie ','Jiu ','Qi ','Ye ', + 'Xi ','Xiang ','Gai ','Jiu ','Hal ','','Shu ','Twul ','Shi ','Ji ','Nang ','Jia ','Kel ','Shi ','','Ol ', + 'Mai ','Luan ','Cal ','Ru ','Xue ','Yan ','Fu ','Sha ','Na ','Gan ','Sol ','El ','Cwul ','','Gan ','Chi ', + 'Gui ','Gan ','Luan ','Lin ','Yi ','Jue ','Le ','Ma ','Yu ','Zheng ','Shi ','Shi ','Er ','Chu ','Yu ','Yu ', + 'Yu ','Yun ','Hu ','Qi ','Wu ','Jing ','Si ','Sui ','Gen ','Gen ','Ya ','Xie ','Ya ','Qi ','Ya ','Ji ', + 'Tou ','Wang ','Kang ','Ta ','Jiao ','Hai ','Yi ','Chan ','Heng ','Mu ','','Xiang ','Jing ','Ting ','Liang ','Xiang ', + 'Jing ','Ye ','Qin ','Bo ','You ','Xie ','Dan ','Lian ','Duo ','Wei ','Ren ','Ren ','Ji ','La ','Wang ','Yi ', + 'Shi ','Ren ','Le ','Ding ','Ze ','Jin ','Pu ','Chou ','Ba ','Zhang ','Jin ','Jie ','Bing ','Reng ','Cong ','Fo ', + 'San ','Lun ','Sya ','Cang ','Zi ','Shi ','Ta ','Zhang ','Fu ','Xian ','Xian ','Tuo ','Hong ','Tong ','Ren ','Qian ', + 'Gan ','Yi ','Di ','Dai ','Ling ','Yi ','Chao ','Chang ','Sa ','','Yi ','Mu ','Men ','Ren ','Jia ','Chao ', + 'Yang ','Qian ','Zhong ','Pi ','Wan ','Wu ','Jian ','Jia ','Yao ','Feng ','Cang ','Ren ','Wang ','Fen ','Di ','Fang ', + ], + 'x4f':[ + 'Zhong ','Qi ','Pei ','Yu ','Diao ','Dun ','Wen ','Yi ','Xin ','Kang ','Yi ','Ji ','Ai ','Wu ','Ji ','Fu ', + 'Fa ','Xiu ','Jin ','Bei ','Dan ','Fu ','Tang ','Zhong ','You ','Huo ','Hui ','Yu ','Cui ','Chuan ','San ','Wei ', + 'Chuan ','Che ','Ya ','Xian ','Shang ','Chang ','Lun ','Cang ','Xun ','Xin ','Wei ','Zhu ','','Xuan ','Nu ','Bo ', + 'Gu ','Ni ','Ni ','Xie ','Ban ','Xu ','Ling ','Zhou ','Shen ','Qu ','Si ','Beng ','Si ','Qie ','Pi ','Yi ', + 'Si ','Ai ','Zheng ','Dian ','Han ','Mai ','Dan ','Zhu ','Bu ','Qu ','Bi ','Shao ','Ci ','Wei ','Di ','Zhu ', + 'Zuo ','You ','Yang ','Ti ','Zhan ','He ','Bi ','Tuo ','She ','Yu ','Yi ','Fo ','Zuo ','Kou ','Ning ','Tong ', + 'Ni ','Xuan ','Qu ','Yong ','Wa ','Qian ','','Ka ','','Pei ','Hui ','He ','Lao ','Xiang ','Ge ','Yang ', + 'Bai ','Fa ','Ming ','Jia ','Er ','Bing ','Ji ','Hen ','Huo ','Gui ','Quan ','Tiao ','Jiao ','Ci ','Yi ','Shi ', + 'Xing ','Shen ','Tuo ','Kan ','Zhi ','Gai ','Lai ','Yi ','Chi ','Kua ','Guang ','Li ','Yin ','Shi ','Mi ','Zhu ', + 'Xu ','You ','An ','Lu ','Mou ','Er ','Lun ','Tong ','Cha ','Chi ','Xun ','Gong ','Zhou ','Yi ','Ru ','Jian ', + 'Xia ','Jia ','Zai ','Lu ','Ko ','Jiao ','Zhen ','Ce ','Qiao ','Kuai ','Chai ','Ning ','Nong ','Jin ','Wu ','Hou ', + 'Jiong ','Cheng ','Zhen ','Zuo ','Chou ','Qin ','Lu ','Ju ','Shu ','Ting ','Shen ','Tuo ','Bo ','Nan ','Hao ','Bian ', + 'Tui ','Yu ','Xi ','Cu ','E ','Qiu ','Xu ','Kuang ','Ku ','Wu ','Jun ','Yi ','Fu ','Lang ','Zu ','Qiao ', + 'Li ','Yong ','Hun ','Jing ','Xian ','San ','Pai ','Su ','Fu ','Xi ','Li ','Fu ','Ping ','Bao ','Yu ','Si ', + 'Xia ','Xin ','Xiu ','Yu ','Ti ','Che ','Chou ','','Yan ','Lia ','Li ','Lai ','Si ','Jian ','Xiu ','Fu ', + 'He ','Ju ','Xiao ','Pai ','Jian ','Biao ','Chu ','Fei ','Feng ','Ya ','An ','Bei ','Yu ','Xin ','Bi ','Jian ', + ], + 'x50':[ + 'Chang ','Chi ','Bing ','Zan ','Yao ','Cui ','Lia ','Wan ','Lai ','Cang ','Zong ','Ge ','Guan ','Bei ','Tian ','Shu ', + 'Shu ','Men ','Dao ','Tan ','Jue ','Chui ','Xing ','Peng ','Tang ','Hou ','Yi ','Qi ','Ti ','Gan ','Jing ','Jie ', + 'Sui ','Chang ','Jie ','Fang ','Zhi ','Kong ','Juan ','Zong ','Ju ','Qian ','Ni ','Lun ','Zhuo ','Wei ','Luo ','Song ', + 'Leng ','Hun ','Dong ','Zi ','Ben ','Wu ','Ju ','Nai ','Cai ','Jian ','Zhai ','Ye ','Zhi ','Sha ','Qing ','', + 'Ying ','Cheng ','Jian ','Yan ','Nuan ','Zhong ','Chun ','Jia ','Jie ','Wei ','Yu ','Bing ','Ruo ','Ti ','Wei ','Pian ', + 'Yan ','Feng ','Tang ','Wo ','E ','Xie ','Che ','Sheng ','Kan ','Di ','Zuo ','Cha ','Ting ','Bei ','Ye ','Huang ', + 'Yao ','Zhan ','Chou ','Yan ','You ','Jian ','Xu ','Zha ','Ci ','Fu ','Bi ','Zhi ','Zong ','Mian ','Ji ','Yi ', + 'Xie ','Xun ','Si ','Duan ','Ce ','Zhen ','Ou ','Tou ','Tou ','Bei ','Za ','Lu ','Jie ','Wei ','Fen ','Chang ', + 'Gui ','Sou ','Zhi ','Su ','Xia ','Fu ','Yuan ','Rong ','Li ','Ru ','Yun ','Gou ','Ma ','Bang ','Dian ','Tang ', + 'Hao ','Jie ','Xi ','Shan ','Qian ','Jue ','Cang ','Chu ','San ','Bei ','Xiao ','Yong ','Yao ','Tan ','Suo ','Yang ', + 'Fa ','Bing ','Jia ','Dai ','Zai ','Tang ','Cot ','Bin ','Chu ','Nuo ','Can ','Lei ','Cui ','Yong ','Zao ','Zong ', + 'Peng ','Song ','Ao ','Chuan ','Yu ','Zhai ','Cou ','Shang ','Qiang ','Jing ','Chi ','Sha ','Han ','Zhang ','Qing ','Yan ', + 'Di ','Xi ','Lu ','Bei ','Piao ','Jin ','Lian ','Lu ','Man ','Qian ','Xian ','Tan ','Ying ','Dong ','Zhuan ','Xiang ', + 'Shan ','Qiao ','Jiong ','Tui ','Zun ','Pu ','Xi ','Lao ','Chang ','Guang ','Liao ','Qi ','Deng ','Chan ','Wei ','Ji ', + 'Fan ','Hui ','Chuan ','Jian ','Dan ','Jiao ','Jiu ','Seng ','Fen ','Xian ','Jue ','E ','Jiao ','Jian ','Tong ','Lin ', + 'Bo ','Gu ','','Su ','Xian ','Jiang ','Min ','Ye ','Jin ','Jia ','Qiao ','Pi ','Feng ','Zhou ','Ai ','Sai ', + ], + 'x51':[ + 'Yi ','Jun ','Nong ','Chan ','Yi ','Dang ','Jing ','Xuan ','Kuai ','Jian ','Chu ','Dan ','Jiao ','Sha ','Zai ','', + 'Bin ','An ','Ru ','Tai ','Chou ','Chai ','Lan ','Ni ','Jin ','Qian ','Meng ','Wu ','Ning ','Qiong ','Ni ','Chang ', + 'Lie ','Lei ','Lu ','Kuang ','Bao ','Du ','Biao ','Zan ','Zhi ','Si ','You ','Hao ','Chen ','Chen ','Li ','Teng ', + 'Wei ','Long ','Chu ','Chan ','Rang ','Shu ','Hui ','Li ','Luo ','Zan ','Nuo ','Tang ','Yan ','Lei ','Nang ','Er ', + 'Wu ','Yun ','Zan ','Yuan ','Xiong ','Chong ','Zhao ','Xiong ','Xian ','Guang ','Dui ','Ke ','Dui ','Mian ','Tu ','Chang ', + 'Er ','Dui ','Er ','Xin ','Tu ','Si ','Yan ','Yan ','Shi ','Sip ','Dang ','Qian ','Dou ','Fen ','Mao ','Shen ', + 'Dou ','Payk ','Jing ','Li ','Huang ','Ru ','Wang ','Nei ','Quan ','Liang ','Yu ','Ba ','Gong ','Liu ','Xi ','', + 'Lan ','Gong ','Tian ','Guan ','Xing ','Bing ','Qi ','Ju ','Dian ','Zi ','Ppwun ','Yang ','Jian ','Shou ','Ji ','Yi ', + 'Ji ','Chan ','Jiong ','Mo ','Ran ','Nei ','Wen ','Mao ','Gang ','Ran ','Ce ','Jiong ','Ce ','Zai ','Gua ','Jiong ', + 'Mao ','Zhou ','Mao ','Gou ','Xu ','Mian ','Mi ','Rong ','Yin ','Xie ','Kan ','Jun ','Nong ','Yi ','Mi ','Shi ', + 'Guan ','Meng ','Zhong ','Ju ','Yuan ','Ming ','Kou ','Lam ','Fu ','Xie ','Mi ','Bing ','Dong ','Tai ','Gang ','Feng ', + 'Bing ','Hu ','Chong ','Jue ','Hu ','Kuang ','Ye ','Leng ','Pan ','Fu ','Min ','Dong ','Xian ','Lie ','Xia ','Jian ', + 'Jing ','Shu ','Mei ','Tu ','Qi ','Gu ','Zhun ','Song ','Jing ','Liang ','Qing ','Diao ','Ling ','Dong ','Gan ','Jian ', + 'Yin ','Cou ','Yi ','Li ','Cang ','Ming ','Cwun ','Cui ','Si ','Duo ','Jin ','Lin ','Lin ','Ning ','Xi ','Du ', + 'Ji ','Fan ','Fan ','Fan ','Feng ','Ju ','Chu ','Tako ','Feng ','Mok ','Ci ','Fu ','Feng ','Ping ','Feng ','Kai ', + 'Huang ','Kai ','Gan ','Deng ','Ping ','Qu ','Xiong ','Kuai ','Tu ','Ao ','Chu ','Ji ','Dang ','Han ','Han ','Zao ', + ], + 'x52':[ + 'Dao ','Diao ','Dao ','Ren ','Ren ','Chuang ','Fen ','Qie ','Yi ','Ji ','Kan ','Qian ','Cun ','Chu ','Wen ','Ji ', + 'Dan ','Xing ','Hua ','Wan ','Jue ','Li ','Yue ','Lie ','Liu ','Ze ','Gang ','Chuang ','Fu ','Chu ','Qu ','Ju ', + 'Shan ','Min ','Ling ','Zhong ','Pan ','Bie ','Jie ','Jie ','Bao ','Li ','Shan ','Bie ','Chan ','Jing ','Gua ','Gen ', + 'Dao ','Chuang ','Kui ','Ku ','Duo ','Er ','Zhi ','Shua ','Quan ','Cha ','Ci ','Ke ','Jie ','Gui ','Ci ','Gui ', + 'Kai ','Duo ','Ji ','Ti ','Jing ','Lou ','Gen ','Ze ','Yuan ','Cuo ','Xue ','Ke ','La ','Qian ','Cha ','Chuang ', + 'Gua ','Jian ','Cuo ','Li ','Ti ','Fei ','Pou ','Chan ','Qi ','Chuang ','Zi ','Gang ','Wan ','Bo ','Ji ','Duo ', + 'Qing ','Yan ','Zhuo ','Jian ','Ji ','Bo ','Yan ','Ju ','Huo ','Sheng ','Jian ','Duo ','Duan ','Wu ','Gua ','Fu ', + 'Sheng ','Jian ','Ge ','Zha ','Kai ','Chuang ','Juan ','Chan ','Tuan ','Lu ','Li ','Fou ','Shan ','Piao ','Kou ','Jiao ', + 'Gua ','Qiao ','Jue ','Hua ','Zha ','Zhuo ','Lian ','Ju ','Pi ','Liu ','Gui ','Jiao ','Gui ','Jian ','Jian ','Tang ', + 'Huo ','Ji ','Jian ','Yi ','Jian ','Zhi ','Chan ','Cuan ','Mo ','Li ','Zhu ','Li ','Ya ','Quan ','Ban ','Gong ', + 'Jia ','Wu ','Mai ','Lie ','Jin ','Keng ','Xie ','Zhi ','Dong ','Zhu ','Nu ','Jie ','Qu ','Shao ','Yi ','Zhu ', + 'Miao ','Li ','Jing ','Lao ','Lao ','Juan ','Kou ','Yang ','Wa ','Xiao ','Mou ','Kuang ','Jie ','Lie ','He ','Shi ', + 'Ke ','Jin ','Hao ','Bo ','Min ','Chi ','Lang ','Yong ','Yong ','Mian ','Ke ','Xun ','Juan ','Qing ','Lu ','Pou ', + 'Meng ','Lai ','Le ','Kai ','Mian ','Dong ','Xu ','Xu ','Kan ','Wu ','Yi ','Xun ','Weng ','Sheng ','Lao ','Mu ', + 'Lu ','Piao ','Shi ','Ji ','Qin ','Qiang ','Jiao ','Quan ','Yang ','Yi ','Jue ','Fan ','Juan ','Tong ','Ju ','Dan ', + 'Xie ','Mai ','Xun ','Xun ','Lu ','Li ','Che ','Rang ','Quan ','Bao ','Shao ','Yun ','Jiu ','Bao ','Gou ','Wu ', + ], + 'x53':[ + 'Yun ','Mwun ','Nay ','Gai ','Gai ','Bao ','Cong ','','Xiong ','Peng ','Ju ','Tao ','Ge ','Pu ','An ','Pao ', + 'Fu ','Gong ','Da ','Jiu ','Qiong ','Bi ','Hua ','Bei ','Nao ','Chi ','Fang ','Jiu ','Yi ','Za ','Jiang ','Kang ', + 'Jiang ','Kuang ','Hu ','Xia ','Qu ','Bian ','Gui ','Qie ','Zang ','Kuang ','Fei ','Hu ','Tou ','Gui ','Gui ','Hui ', + 'Dan ','Gui ','Lian ','Lian ','Suan ','Du ','Jiu ','Qu ','Xi ','Pi ','Qu ','Yi ','Qia ','Yan ','Bian ','Ni ', + 'Qu ','Shi ','Xin ','Qian ','Nian ','Sa ','Zu ','Sheng ','Wu ','Hui ','Ban ','Shi ','Xi ','Wan ','Hua ','Xie ', + 'Wan ','Bei ','Zu ','Zhuo ','Xie ','Dan ','Mai ','Nan ','Dan ','Ji ','Bo ','Shuai ','Bu ','Kuang ','Bian ','Bu ', + 'Zhan ','Qia ','Lu ','You ','Lu ','Xi ','Gua ','Wo ','Xie ','Jie ','Jie ','Wei ','Ang ','Qiong ','Zhi ','Mao ', + 'Yin ','Wei ','Shao ','Ji ','Que ','Luan ','Shi ','Juan ','Xie ','Xu ','Jin ','Que ','Wu ','Ji ','E ','Qing ', + 'Xi ','','Chang ','Zhan ','E ','Ting ','Li ','Zhe ','Han ','Li ','Ya ','Ya ','Yan ','She ','Zhi ','Zha ', + 'Pang ','','He ','Ya ','Zhi ','Ce ','Pang ','Ti ','Li ','She ','Hou ','Ting ','Zui ','Cuo ','Fei ','Yuan ', + 'Ce ','Yuan ','Xiang ','Yan ','Li ','Jue ','Sha ','Dian ','Chu ','Jiu ','Qin ','Ao ','Gui ','Yan ','Si ','Li ', + 'Chang ','Lan ','Li ','Yan ','Yan ','Yuan ','Si ','Gong ','Lin ','Qiu ','Qu ','Qu ','Uk ','Lei ','Du ','Xian ', + 'Zhuan ','San ','Can ','Can ','Can ','Can ','Ai ','Dai ','You ','Cha ','Ji ','You ','Shuang ','Fan ','Shou ','Guai ', + 'Ba ','Fa ','Ruo ','Shi ','Shu ','Zhuo ','Qu ','Shou ','Bian ','Xu ','Jia ','Pan ','Sou ','Gao ','Wei ','Sou ', + 'Die ','Rui ','Cong ','Kou ','Gu ','Ju ','Ling ','Gua ','Tao ','Kou ','Zhi ','Jiao ','Zhao ','Ba ','Ding ','Ke ', + 'Tai ','Chi ','Shi ','You ','Qiu ','Po ','Xie ','Hao ','Si ','Tan ','Chi ','Le ','Diao ','Ji ','Duk ','Hong ', + ], + 'x54':[ + 'Mie ','Xu ','Mang ','Chi ','Ge ','Xuan ','Yao ','Zi ','He ','Ji ','Diao ','Cun ','Tong ','Ming ','Hou ','Li ', + 'Tu ','Xiang ','Zha ','Xia ','Ye ','Lu ','A ','Ma ','Ou ','Xue ','Yi ','Jun ','Chou ','Lin ','Tun ','Yin ', + 'Fei ','Bi ','Qin ','Qin ','Jie ','Bu ','Fou ','Ba ','Dun ','Fen ','E ','Han ','Ting ','Hang ','Shun ','Qi ', + 'Hong ','Zhi ','Shen ','Wu ','Wu ','Chao ','Ne ','Xue ','Xi ','Chui ','Dou ','Wen ','Hou ','Ou ','Wu ','Gao ', + 'Ya ','Jun ','Lu ','E ','Ge ','Mei ','Dai ','Qi ','Cheng ','Wu ','Gao ','Fu ','Jiao ','Hong ','Chi ','Sheng ', + 'Ne ','Tun ','Fu ','Yi ','Dai ','Ou ','Li ','Bai ','Yuan ','Kuai ','','Qiang ','Wu ','E ','Shi ','Quan ', + 'Pen ','Wen ','Ni ','M ','Ling ','Ran ','You ','Di ','Zhou ','Shi ','Zhou ','Tie ','Xi ','Yi ','Qi ','Ping ', + 'Zi ','Gu ','Zi ','Wei ','Xu ','He ','Nao ','Xia ','Pei ','Yi ','Xiao ','Shen ','Hu ','Ming ','Da ','Qu ', + 'Ju ','Gam ','Za ','Tuo ','Duo ','Pou ','Pao ','Bi ','Fu ','Yang ','He ','Zha ','He ','Hai ','Jiu ','Yong ', + 'Fu ','Que ','Zhou ','Wa ','Ka ','Gu ','Ka ','Zuo ','Bu ','Long ','Dong ','Ning ','Tha ','Si ','Xian ','Huo ', + 'Qi ','Er ','E ','Guang ','Zha ','Xi ','Yi ','Lie ','Zi ','Mie ','Mi ','Zhi ','Yao ','Ji ','Zhou ','Ge ', + 'Shuai ','Zan ','Xiao ','Ke ','Hui ','Kua ','Huai ','Tao ','Xian ','E ','Xuan ','Xiu ','Wai ','Yan ','Lao ','Yi ', + 'Ai ','Pin ','Shen ','Tong ','Hong ','Xiong ','Duo ','Wa ','Ha ','Zai ','Yu ','Di ','Pai ','Xiang ','Ai ','Hen ', + 'Kuang ','Ya ','Da ','Xiao ','Bi ','Yue ','','Hua ','Sasou ','Kuai ','Duo ','','Ji ','Nong ','Mou ','Yo ', + 'Hao ','Yuan ','Long ','Pou ','Mang ','Ge ','E ','Chi ','Shao ','Li ','Na ','Zu ','He ','Ku ','Xiao ','Xian ', + 'Lao ','Bo ','Zhe ','Zha ','Liang ','Ba ','Mie ','Le ','Sui ','Fou ','Bu ','Han ','Heng ','Geng ','Shuo ','Ge ', + ], + 'x55':[ + 'You ','Yan ','Gu ','Gu ','Bai ','Han ','Suo ','Chun ','Yi ','Ai ','Jia ','Tu ','Xian ','Huan ','Li ','Xi ', + 'Tang ','Zuo ','Qiu ','Che ','Wu ','Zao ','Ya ','Dou ','Qi ','Di ','Qin ','Ma ','Mal ','Hong ','Dou ','Kes ', + 'Lao ','Liang ','Suo ','Zao ','Huan ','Laang ','Sha ','Ji ','Zuo ','Wo ','Feng ','Yin ','Hu ','Qi ','Shou ','Wei ', + 'Shua ','Chang ','Er ','Li ','Qiang ','An ','Jie ','Yo ','Nian ','Yu ','Tian ','Lai ','Sha ','Xi ','Tuo ','Hu ', + 'Ai ','Zhou ','Nou ','Ken ','Zhuo ','Zhuo ','Shang ','Di ','Heng ','Lan ','A ','Xiao ','Xiang ','Tun ','Wu ','Wen ', + 'Cui ','Sha ','Hu ','Qi ','Qi ','Tao ','Dan ','Dan ','Ye ','Zi ','Bi ','Cui ','Chuo ','He ','Ya ','Qi ', + 'Zhe ','Fei ','Liang ','Xian ','Pi ','Sha ','La ','Ze ','Qing ','Gua ','Pa ','Zhe ','Se ','Zhuan ','Nie ','Guo ', + 'Luo ','Yan ','Di ','Quan ','Tan ','Bo ','Ding ','Lang ','Xiao ','Geoi ','Tang ','Chi ','Ti ','An ','Jiu ','Dan ', + 'Ka ','Yong ','Wei ','Nan ','Shan ','Yu ','Zhe ','La ','Jie ','Hou ','Han ','Die ','Zhou ','Chai ','Wai ','Re ', + 'Yu ','Yin ','Zan ','Yao ','O ','Mian ','Hu ','Yun ','Chuan ','Hui ','Huan ','Huan ','Xi ','He ','Ji ','Kui ', + 'Zhong ','Wei ','Sha ','Xu ','Huang ','Du ','Nie ','Xuan ','Liang ','Yu ','Sang ','Chi ','Qiao ','Yan ','Dan ','Pen ', + 'Can ','Li ','Yo ','Zha ','Wei ','Miao ','Ying ','Pen ','Phos ','Kui ','Xi ','Yu ','Jie ','Lou ','Ku ','Sao ', + 'Huo ','Ti ','Yao ','He ','A ','Xiu ','Qiang ','Se ','Yong ','Su ','Hong ','Xie ','Yi ','Suo ','Ma ','Cha ', + 'Hai ','Ke ','Ta ','Sang ','Tian ','Ru ','Sou ','Wa ','Ji ','Pang ','Wu ','Xian ','Shi ','Ge ','Zi ','Jie ', + 'Luo ','Weng ','Wa ','Si ','Chi ','Hao ','Suo ','Lyun ','Hai ','Suo ','Qin ','Nie ','He ','Cis ','Sai ','Ng ', + 'Ge ','Na ','Dia ','Ai ','','Tong ','Bi ','Ao ','Ao ','Lian ','Cui ','Zhe ','Mo ','Sou ','Sou ','Tan ', + ], + 'x56':[ + 'Di ','Qi ','Jiao ','Chong ','Jiao ','Kai ','Tan ','San ','Cao ','Jia ','Ai ','Xiao ','Piao ','Lou ','Ga ','Gu ', + 'Xiao ','Hu ','Hui ','Guo ','Ou ','Xian ','Ze ','Chang ','Xu ','Po ','De ','Ma ','Ma ','Hu ','Lei ','Du ', + 'Ga ','Tang ','Ye ','Beng ','Ying ','Saai ','Jiao ','Mi ','Xiao ','Hua ','Mai ','Ran ','Zuo ','Peng ','Lao ','Xiao ', + 'Ji ','Zhu ','Chao ','Kui ','Zui ','Xiao ','Si ','Hao ','Fu ','Liao ','Qiao ','Xi ','Xiu ','Tan ','Tan ','Hei ', + 'Xun ','E ','Zun ','Fan ','Chi ','Hui ','Zan ','Chuang ','Cu ','Dan ','Yu ','Tun ','Cheng ','Jiao ','Ye ','Xi ', + 'Qi ','Hao ','Lian ','Xu ','Deng ','Hui ','Yin ','Pu ','Jue ','Qin ','Xun ','Nie ','Lu ','Si ','Yan ','Ying ', + 'Da ','Dan ','O ','Zhou ','Jin ','Nong ','Yue ','Hui ','Qi ','E ','Zao ','Yi ','Shi ','Jiao ','Yuan ','Ai ', + 'Yong ','Jue ','Kuai ','Yu ','Pen ','Dao ','Ge ','Xin ','Dun ','Dang ','Sin ','Sai ','Pi ','Pi ','Yin ','Zui ', + 'Ning ','Di ','Lan ','Ta ','Huo ','Ru ','Hao ','Xia ','Ya ','Duo ','Xi ','Chou ','Ji ','Jin ','Hao ','Ti ', + 'Chang ','','','Ca ','Ti ','Lu ','Hui ','Bo ','You ','Nie ','Yin ','Hu ','Mo ','Huang ','Zhe ','Li ', + 'Liu ','Haai ','Nang ','Xiao ','Mo ','Yan ','Li ','Lu ','Long ','Fu ','Dan ','Chen ','Pin ','Pi ','Xiang ','Huo ', + 'Mo ','Xi ','Duo ','Ku ','Yan ','Chan ','Ying ','Rang ','Dian ','La ','Ta ','Xiao ','Jiao ','Chuo ','Huan ','Huo ', + 'Zhuan ','Nie ','Xiao ','Ca ','Li ','Chan ','Chai ','Li ','Yi ','Luo ','Nang ','Zan ','Su ','Xi ','So ','Jian ', + 'Za ','Zhu ','Lan ','Nie ','Nang ','Trom ','Lo ','Wei ','Hui ','Yin ','Qiu ','Si ','Nin ','Jian ','Hui ','Xin ', + 'Yin ','Nan ','Tuan ','Tuan ','Dun ','Kang ','Yuan ','Jiong ','Pian ','Yun ','Cong ','Hu ','Hui ','Yuan ','E ','Guo ', + 'Kun ','Cong ','Wei ','Tu ','Wei ','Lun ','Guo ','Qun ','Ri ','Ling ','Gu ','Guo ','Tai ','Guo ','Tu ','You ', + ], + 'x57':[ + 'Guo ','Yin ','Hun ','Pu ','Yu ','Han ','Yuan ','Lun ','Quan ','Yu ','Qing ','Guo ','Chuan ','Wei ','Yuan ','Quan ', + 'Ku ','Fu ','Yuan ','Yuan ','E ','Toshokan ','Tu ','Tu ','Tuan ','Lue ','Hui ','Yi ','Yuan ','Luan ','Luan ','Tu ', + 'Ya ','Tu ','Ting ','Sheng ','Pu ','Lu ','Iri ','Ya ','Zai ','Wei ','Ge ','Yu ','Wu ','Gui ','Pi ','Yi ', + 'Di ','Qian ','Qian ','Zhen ','Zhuo ','Dang ','Qia ','Akutsu ','Yama ','Kuang ','Chang ','Qi ','Nie ','Mo ','Ji ','Jia ', + 'Zhi ','Zhi ','Ban ','Xun ','Tou ','Qin ','Fen ','Jun ','Keng ','Tun ','Fang ','Fen ','Ben ','Tan ','Kan ','Huai ', + 'Zuo ','Keng ','Bi ','Xing ','Di ','Jing ','Ji ','Kuai ','Di ','Jing ','Jian ','Tan ','Li ','Ba ','Wu ','Fen ', + 'Zhui ','Po ','Pan ','Tang ','Kun ','Qu ','Tan ','Zhi ','Tuo ','Gan ','Ping ','Dian ','Gua ','Ni ','Tai ','Pi ', + 'Jiong ','Yang ','Fo ','Ao ','Liu ','Qiu ','Mu ','Ke ','Gou ','Xue ','Ba ','Chi ','Che ','Ling ','Zhu ','Fu ', + 'Hu ','Zhi ','Chui ','La ','Long ','Long ','Lu ','Ao ','Tay ','Pao ','','Xing ','Dong ','Ji ','Ke ','Lu ', + 'Ci ','Chi ','Lei ','Gai ','Yin ','Hou ','Dui ','Zhao ','Fu ','Guang ','Yao ','Duo ','Duo ','Gui ','Cha ','Yang ', + 'Yin ','Fa ','Gou ','Yuan ','Die ','Xie ','Ken ','Jiong ','Shou ','E ','Ha ','Dian ','Hong ','Wu ','Kua ','', + 'Tao ','Dang ','Kai ','Gake ','Nao ','An ','Xing ','Xian ','Huan ','Bang ','Pei ','Ba ','Yi ','Yin ','Han ','Xu ', + 'Chui ','Cen ','Geng ','Ai ','Peng ','Fang ','Que ','Yong ','Xun ','Jia ','Di ','Mai ','Lang ','Xuan ','Cheng ','Yan ', + 'Jin ','Zhe ','Lei ','Lie ','Pu ','Cheng ','Gomi ','Bu ','Shi ','Xun ','Guo ','Jiong ','Ye ','Nian ','Di ','Yu ', + 'Bu ','Ya ','Juan ','Sui ','Pi ','Cheng ','Wan ','Ju ','Lun ','Zheng ','Kong ','Chong ','Dong ','Dai ','Tan ','An ', + 'Cai ','Shu ','Beng ','Kan ','Zhi ','Duo ','Yi ','Zhi ','Yi ','Pei ','Ji ','Zhun ','Qi ','Sao ','Ju ','Ni ', + ], + 'x58':[ + 'Ku ','Ke ','Tang ','Kun ','Ni ','Jian ','Dui ','Jin ','Gang ','Yu ','E ','Peng ','Gu ','Tu ','Leng ','', + 'Ya ','Qian ','','An ','','Duo ','Nao ','Tu ','Cheng ','Yin ','Hun ','Bi ','Lian ','Guo ','Die ','Zhuan ', + 'Hou ','Bao ','Bao ','Yu ','Di ','Mao ','Jie ','Ruan ','E ','Geng ','Kan ','Zong ','Yu ','Huang ','E ','Yao ', + 'Yan ','Bao ','Ji ','Mei ','Chang ','Du ','Tuo ','Yin ','Feng ','Zhong ','Jie ','Zhen ','Feng ','Gang ','Chuan ','Jian ', + 'Pyeng ','Rui ','Xiang ','Huang ','Leng ','Duan ','','Xuan ','Ji ','Ji ','Kuai ','Ying ','Ta ','Cheng ','Yong ','Kai ', + 'Su ','Su ','Shi ','Mi ','Ta ','Weng ','Cheng ','Tu ','Tang ','Que ','Zhong ','Li ','Peng ','Bang ','Sai ','Zang ', + 'Dui ','Tian ','Wu ','Cheng ','Xun ','Ge ','Zhen ','Ai ','Gong ','Yan ','Kan ','Tian ','Yuan ','Wen ','Xie ','Liu ', + 'Ama ','Lang ','Chang ','Peng ','Beng ','Chen ','Cu ','Lu ','Ou ','Qian ','Mei ','Mo ','Zhuan ','Shuang ','Shu ','Lou ', + 'Chi ','Man ','Biao ','Jing ','Qi ','Shu ','Di ','Zhang ','Kan ','Yong ','Dian ','Chen ','Zhi ','Xi ','Guo ','Qiang ', + 'Jin ','Di ','Shang ','Mu ','Cui ','Yan ','Ta ','Zeng ','Qi ','Qiang ','Liang ','','Zhui ','Qiao ','Zeng ','Xu ', + 'Shan ','Shan ','Ba ','Pu ','Kuai ','Dong ','Fan ','Que ','Mo ','Dun ','Dun ','Zun ','Di ','Sheng ','Duo ','Duo ', + 'Tan ','Deng ','Wu ','Fen ','Huang ','Tan ','Da ','Ye ','Sho ','Mama ','Ao ','Qiang ','Ji ','Qiao ','Ken ','Yi ', + 'Pi ','Bi ','Dian ','Jiang ','Ye ','Yong ','Bo ','Tan ','Lan ','Ju ','Huai ','Dang ','Rang ','Qian ','Xun ','Lan ', + 'Xi ','He ','Ai ','Ya ','Dao ','Hao ','Ruan ','Mama ','Lei ','Kuang ','Lu ','Yan ','Tan ','Wei ','Huai ','Long ', + 'Long ','Rui ','Li ','Lin ','Rang ','Ten ','Xun ','Yan ','Lei ','Ba ','','Shi ','Ren ','','Zhuang ','Zhuang ', + 'Sheng ','Yi ','Mai ','Ke ','Zhu ','Zhuang ','Hu ','Hu ','Kun ','Yi ','Hu ','Xu ','Kun ','Shou ','Mang ','Zun ', + ], + 'x59':[ + 'Shou ','Yi ','Zhi ','Gu ','Chu ','Jiang ','Feng ','Bei ','Cay ','Bian ','Sui ','Qun ','Ling ','Fu ','Zuo ','Xia ', + 'Xiong ','','Nao ','Xia ','Kui ','Xi ','Wai ','Yuan ','Mao ','Su ','Duo ','Duo ','Ye ','Qing ','Uys ','Gou ', + 'Gou ','Qi ','Meng ','Meng ','Yin ','Huo ','Chen ','Da ','Ze ','Tian ','Tai ','Fu ','Guai ','Yao ','Yang ','Hang ', + 'Gao ','Shi ','Ben ','Tai ','Tou ','Yan ','Bi ','Yi ','Kua ','Jia ','Duo ','Kwu ','Kuang ','Yun ','Jia ','Pa ', + 'En ','Lian ','Huan ','Di ','Yan ','Pao ','Quan ','Qi ','Nai ','Feng ','Xie ','Fen ','Dian ','','Kui ','Zou ', + 'Huan ','Qi ','Kai ','She ','Ben ','Yi ','Jiang ','Tao ','Zang ','Ben ','Xi ','Xiang ','Fei ','Diao ','Xun ','Keng ', + 'Dian ','Ao ','She ','Weng ','Pan ','Ao ','Wu ','Ao ','Jiang ','Lian ','Duo ','Yun ','Jiang ','Shi ','Fen ','Huo ', + 'Bi ','Lian ','Duo ','Nu ','Nu ','Ding ','Nai ','Qian ','Jian ','Ta ','Jiu ','Nan ','Cha ','Hao ','Xian ','Fan ', + 'Ji ','Shuo ','Ru ','Fei ','Wang ','Hong ','Zhuang ','Fu ','Ma ','Dan ','Ren ','Fu ','Jing ','Yan ','Xie ','Wen ', + 'Zhong ','Pa ','Du ','Ji ','Keng ','Zhong ','Yao ','Jin ','Yun ','Miao ','Pei ','Shi ','Yue ','Zhuang ','Niu ','Yan ', + 'Na ','Xin ','Fen ','Bi ','Yu ','Tuo ','Feng ','Yuan ','Fang ','Wu ','Yu ','Gui ','Du ','Ba ','Ni ','Zhou ', + 'Zhuo ','Zhao ','Da ','Nai ','Yuan ','Tou ','Xuan ','Zhi ','E ','Mei ','Mo ','Qi ','Bi ','Shen ','Qie ','E ', + 'He ','Xu ','Fa ','Zheng ','Min ','Ban ','Mu ','Fu ','Ling ','Zi ','Zi ','Shi ','Ran ','Shan ','Yang ','Man ', + 'Jie ','Gu ','Si ','Xing ','Wei ','Zi ','Ju ','Shan ','Pin ','Ren ','Yao ','Tong ','Jiang ','Shu ','Ji ','Gai ', + 'Shang ','Kuo ','Juan ','Jiao ','Gou ','Mu ','Jian ','Jian ','Yi ','Nian ','Zhi ','Ji ','Ji ','Xian ','Heng ','Guang ', + 'Jun ','Kua ','Yan ','Ming ','Lie ','Pei ','Yan ','You ','Yan ','Cha ','Shen ','Yin ','Chi ','Gui ','Quan ','Zi ', + ], + 'x5a':[ + 'Song ','Wei ','Hong ','Wa ','Lou ','Ya ','Rao ','Jiao ','Luan ','Ping ','Xian ','Shao ','Li ','Cheng ','Xiao ','Mang ', + '','Suo ','Wu ','Wei ','Ke ','Lai ','Chuo ','Ding ','Niang ','Xing ','Nan ','Yu ','Nuo ','Pei ','Nei ','Juan ', + 'Shen ','Zhi ','Han ','Di ','Zhuang ','E ','Pin ','Tui ','Han ','Mian ','Wu ','Yan ','Wu ','Xi ','Yan ','Yu ', + 'Si ','Yu ','Wa ','','Xian ','Ju ','Qu ','Shui ','Qi ','Xian ','Zhui ','Dong ','Chang ','Lu ','Ai ','E ', + 'E ','Lou ','Mian ','Cong ','Pou ','Ju ','Po ','Cai ','Ding ','Wan ','Biao ','Xiao ','Shu ','Qi ','Hui ','Fu ', + 'E ','Wo ','Tan ','Fei ','','Jie ','Tian ','Ni ','Quan ','Jing ','Hun ','Jing ','Qian ','Dian ','Xing ','Hu ', + 'Wa ','Lai ','Bi ','Yin ','Zhou ','Chuo ','Fu ','Jing ','Lun ','Yan ','Lan ','Kun ','Yin ','Ya ','','Li ', + 'Dian ','Xian ','Hwa ','Hua ','Ying ','Chan ','Shen ','Ting ','Dang ','Yao ','Wu ','Nan ','Ruo ','Jia ','Tou ','Xu ', + 'Yu ','Wei ','Ti ','Rou ','Mei ','Dan ','Ruan ','Qin ','','Wu ','Qian ','Chun ','Mao ','Fu ','Jie ','Duan ', + 'Xi ','Zhong ','Mei ','Huang ','Mian ','An ','Ying ','Xuan ','','Wei ','Mei ','Yuan ','Zhen ','Qiu ','Ti ','Xie ', + 'Tuo ','Lian ','Mao ','Ran ','Si ','Pian ','Wei ','Wa ','Jiu ','Hu ','Ao ','','Bou ','Xu ','Tou ','Gui ', + 'Zou ','Yao ','Pi ','Xi ','Yuan ','Ying ','Rong ','Ru ','Chi ','Liu ','Mei ','Pan ','Ao ','Ma ','Gou ','Kui ', + 'Qin ','Jia ','Sao ','Zhen ','Yuan ','Cha ','Yong ','Ming ','Ying ','Ji ','Su ','Niao ','Xian ','Tao ','Pang ','Lang ', + 'Nao ','Bao ','Ai ','Pi ','Pin ','Yi ','Piao ','Yu ','Lei ','Xuan ','Man ','Yi ','Zhang ','Kang ','Yong ','Ni ', + 'Li ','Di ','Gui ','Yan ','Jin ','Zhuan ','Chang ','Ce ','Han ','Nen ','Lao ','Mo ','Zhe ','Hu ','Hu ','Ao ', + 'Nen ','Qiang ','Maa ','Pie ','Gu ','Wu ','Jiao ','Tuo ','Zhan ','Mao ','Xian ','Xian ','Mo ','Liao ','Lian ','Hua ', + ], + 'x5b':[ + 'Gui ','Deng ','Zhi ','Xu ','','Hua ','Xi ','Hui ','Rao ','Xi ','Yan ','Chan ','Jiao ','Mei ','Fan ','Fan ', + 'Xian ','Yi ','Wei ','Jiao ','Fu ','Shi ','Bi ','Shan ','Sui ','Qiang ','Lian ','Huan ','','Niao ','Dong ','Yi ', + 'Can ','Ai ','Niang ','Neng ','Ma ','Tiao ','Chou ','Jin ','Ci ','Yu ','Pin ','','Xu ','Nai ','Yan ','Tai ', + 'Ying ','Can ','Niao ','','Ying ','Mian ','Kaka ','Ma ','Shen ','Xing ','Ni ','Du ','Liu ','Yuan ','Lan ','Yan ', + 'Shuang ','Ling ','Jiao ','Niang ','Lan ','Xian ','Ying ','Shuang ','Shuai ','Quan ','Mi ','Li ','Luan ','Yan ','Zhu ','Lan ', + 'Zi ','Jie ','Jue ','Jue ','Kong ','Yun ','Zi ','Zi ','Cun ','Sun ','Fu ','Bei ','Zi ','Xiao ','Xin ','Meng ', + 'Si ','Tai ','Bao ','Ji ','Gu ','Nu ','Xue ','','Zhuan ','Hai ','Luan ','Sun ','Huai ','Mie ','Cong ','Qian ', + 'Shu ','Chan ','Ya ','Zi ','Ni ','Fu ','Zi ','Li ','Xue ','Bo ','Ru ','Lai ','Nie ','Nie ','Ying ','Luan ', + 'Mian ','Ning ','Rong ','Ta ','Gui ','Zhai ','Qiong ','Yu ','Shou ','An ','Tu ','Song ','Wan ','Rou ','Yao ','Hong ', + 'Yi ','Jing ','Zhun ','Mi ','Zhu ','Dang ','Hong ','Zong ','Guan ','Zhou ','Ding ','Wan ','Yi ','Bao ','Shi ','Shi ', + 'Chong ','Shen ','Ke ','Xuan ','Shi ','You ','Huan ','Yi ','Tiao ','Shi ','Xian ','Gong ','Cheng ','Qun ','Gong ','Xiao ', + 'Zai ','Zha ','Bao ','Hai ','Yan ','Xiao ','Jia ','Shen ','Chen ','Rong ','Huang ','Mi ','Kou ','Kuan ','Bin ','Su ', + 'Cai ','Zan ','Ji ','Yuan ','Ji ','Yin ','Mi ','Kou ','Qing ','Que ','Zhen ','Jian ','Fu ','Ning ','Bing ','Huan ', + 'Mei ','Qin ','Han ','Yu ','Shi ','Ning ','Jin ','Ning ','Zhi ','Yu ','Bao ','Kuan ','Ning ','Qin ','Mo ','Cha ', + 'Ju ','Gua ','Qin ','Hu ','Wu ','Liao ','Shi ','Ning ','Zhai ','Shen ','Wei ','Xie ','Kuan ','Hui ','Liao ','Jun ', + 'Huan ','Yi ','Yi ','Bao ','Qin ','Chong ','Bao ','Feng ','Cun ','Dui ','Si ','Xun ','Dao ','Lu ','Dui ','Shou ', + ], + 'x5c':[ + 'Po ','Feng ','Zhuan ','Fu ','She ','Ke ','Jiang ','Jiang ','Zhuan ','Wei ','Zun ','Xun ','Shu ','Dui ','Dao ','Xiao ', + 'Ji ','Shao ','Er ','Er ','Er ','Ga ','Jian ','Shu ','Chen ','Shang ','Shang ','','Ga ','Chang ','Liao ','Xian ', + 'Xian ','','Wang ','Wang ','You ','Liao ','Liao ','Yao ','Mang ','Wang ','Wang ','Wang ','Ga ','Yao ','Duo ','Kui ', + 'Zhong ','Jiu ','Gan ','Gu ','Gan ','Tui ','Gan ','Gan ','Shi ','Yin ','Chi ','Kao ','Ni ','Jin ','Wei ','Niao ', + 'Ju ','Pi ','Ceng ','Xi ','Bi ','Ju ','Jie ','Tian ','Qu ','Ti ','Jie ','Wu ','Diao ','Shi ','Shi ','Ping ', + 'Ji ','Xie ','Chen ','Xi ','Ni ','Zhan ','Xi ','','Man ','E ','Lou ','Ping ','Ti ','Fei ','Shu ','Xie ', + 'Tu ','Lu ','Lu ','Xi ','Ceng ','Lu ','Ju ','Xie ','Ju ','Jue ','Liao ','Jue ','Shu ','Xi ','Che ','Tun ', + 'Ni ','Shan ','','Xian ','Li ','Xue ','Nata ','','Long ','Yi ','Qi ','Ren ','Wu ','Han ','Shen ','Yu ', + 'Chu ','Sui ','Qi ','','Yue ','Ban ','Yao ','Ang ','Ya ','Wu ','Jie ','E ','Ji ','Qian ','Fen ','Yuan ', + 'Qi ','Cen ','Qian ','Qi ','Cha ','Jie ','Qu ','Gang ','Xian ','Ao ','Lan ','Dao ','Ba ','Zuo ','Zuo ','Yang ', + 'Ju ','Gang ','Ke ','Gou ','Xue ','Bei ','Li ','Tiao ','Ju ','Yan ','Fu ','Xiu ','Jia ','Ling ','Tuo ','Pei ', + 'You ','Dai ','Kuang ','Yue ','Qu ','Hu ','Po ','Min ','An ','Tiao ','Ling ','Chi ','Yuri ','Dong ','Cem ','Kui ', + 'Xiu ','Mao ','Tong ','Xue ','Yi ','Kura ','He ','Ke ','Luo ','E ','Fu ','Xun ','Die ','Lu ','An ','Er ', + 'Gai ','Quan ','Tong ','Yi ','Mu ','Shi ','An ','Wei ','Hu ','Zhi ','Mi ','Li ','Ji ','Tong ','Wei ','You ', + 'Sang ','Xia ','Li ','Yao ','Jiao ','Zheng ','Luan ','Jiao ','E ','E ','Yu ','Ye ','Bu ','Qiao ','Qun ','Feng ', + 'Feng ','Nao ','Li ','You ','Xian ','Hong ','Dao ','Shen ','Cheng ','Tu ','Geng ','Jun ','Hao ','Xia ','Yin ','Yu ', + ], + 'x5d':[ + 'Lang ','Kan ','Lao ','Lai ','Xian ','Que ','Kong ','Chong ','Chong ','Ta ','','Hua ','Ju ','Lai ','Qi ','Min ', + 'Kun ','Kun ','Zu ','Gu ','Cui ','Ya ','Ya ','Gang ','Lun ','Lun ','Leng ','Jue ','Duo ','Zheng ','Guo ','Yin ', + 'Dong ','Han ','Zheng ','Wei ','Yao ','Pi ','Yan ','Song ','Jie ','Beng ','Zu ','Jue ','Dong ','Zhan ','Gu ','Yin ', + '','Ze ','Huang ','Yu ','Wei ','Yang ','Feng ','Qiu ','Dun ','Ti ','Yi ','Zhi ','Shi ','Zai ','Yao ','E ', + 'Zhu ','Kan ','Lu ','Yan ','Mei ','Gan ','Ji ','Ji ','Huan ','Ting ','Sheng ','Mei ','Qian ','Wu ','Yu ','Zong ', + 'Lan ','Jue ','Yan ','Yan ','Wei ','Zong ','Cha ','Sui ','Rong ','Yamashina ','Qin ','Yu ','Ki ','Lou ','Tu ','Dui ', + 'Xi ','Weng ','Cang ','Dang ','Hong ','Jie ','Ai ','Liu ','Wu ','Song ','Qiao ','Zi ','Wei ','Beng ','Dian ','Cuo ', + 'Qian ','Yong ','Nie ','Cuo ','Ji ','','Tao ','Song ','Zong ','Jiang ','Liao ','','Chan ','Die ','Cen ','Ding ', + 'Tu ','Lou ','Zhang ','Zhan ','Zhan ','Ao ','Cao ','Qu ','Qiang ','Zui ','Zui ','Dao ','Dao ','Xi ','Yu ','Bo ', + 'Long ','Xiang ','Ceng ','Bo ','Qin ','Jiao ','Yan ','Lao ','Zhan ','Lin ','Liao ','Liao ','Jin ','Deng ','Duo ','Zun ', + 'Jiao ','Gui ','Yao ','Qiao ','Yao ','Jue ','Zhan ','Yi ','Xue ','Nao ','Ye ','Ye ','Yi ','E ','Xian ','Ji ', + 'Xie ','Ke ','Xi ','Di ','Ao ','Zui ','','Yi ','Rong ','Dao ','Ling ','Za ','Yu ','Yue ','Yin ','', + 'Jie ','Li ','Sui ','Long ','Long ','Dian ','Ying ','Xi ','Ju ','Chan ','Ying ','Kui ','Yan ','Wei ','Nao ','Quan ', + 'Chao ','Cuan ','Luan ','Dian ','Dian ','','Yan ','Yan ','Yan ','Nao ','Yan ','Chuan ','Gui ','Chuan ','Zhou ','Huang ', + 'Jing ','Xun ','Chao ','Chao ','Lie ','Gong ','Zuo ','Qiao ','Ju ','Gong ','Kek ','Wu ','Pwu ','Pwu ','Cha ','Qiu ', + 'Qiu ','Ji ','Yi ','Si ','Ba ','Zhi ','Zhao ','Xiang ','Yi ','Jin ','Xun ','Juan ','Phas ','Xun ','Jin ','Fu ', + ], + 'x5e':[ + 'Za ','Bi ','Shi ','Bu ','Ding ','Shuai ','Fan ','Nie ','Shi ','Fen ','Pa ','Zhi ','Xi ','Hu ','Dan ','Wei ', + 'Zhang ','Tang ','Dai ','Ma ','Pei ','Pa ','Tie ','Fu ','Lian ','Zhi ','Zhou ','Bo ','Zhi ','Di ','Mo ','Yi ', + 'Yi ','Ping ','Qia ','Juan ','Ru ','Shuai ','Dai ','Zheng ','Shui ','Qiao ','Zhen ','Shi ','Qun ','Xi ','Bang ','Dai ', + 'Gui ','Chou ','Ping ','Zhang ','Sha ','Wan ','Dai ','Wei ','Chang ','Sha ','Qi ','Ze ','Guo ','Mao ','Du ','Hou ', + 'Zheng ','Xu ','Mi ','Wei ','Wo ','Fu ','Yi ','Bang ','Ping ','Tazuna ','Gong ','Pan ','Huang ','Dao ','Mi ','Jia ', + 'Teng ','Hui ','Zhong ','Shan ','Man ','Mu ','Biao ','Guo ','Ze ','Mu ','Bang ','Zhang ','Jiong ','Chan ','Fu ','Zhi ', + 'Hu ','Fan ','Chuang ','Bi ','Hei ','','Mi ','Qiao ','Chan ','Fen ','Meng ','Bang ','Chou ','Mie ','Chu ','Jie ', + 'Xian ','Lan ','Gan ','Ping ','Nian ','Qian ','Bing ','Bing ','Xing ','Gan ','Yao ','Huan ','You ','You ','Ji ','Yan ', + 'Pi ','Ting ','Ze ','Guang ','Zhuang ','Mo ','Qing ','Bi ','Qin ','Dun ','Chuang ','Gui ','Ya ','Bai ','Jie ','Xu ', + 'Lu ','Wu ','','Ku ','Ying ','Di ','Pao ','Dian ','Ya ','Miao ','Geng ','Ci ','Fu ','Tong ','Pang ','Fei ', + 'Xiang ','Yi ','Zhi ','Tiao ','Zhi ','Xiu ','Du ','Zuo ','Xiao ','Tu ','Gui ','Ku ','Pang ','Ting ','You ','Bu ', + 'Ding ','Cheng ','Lai ','Bei ','Ji ','An ','Shu ','Kang ','Yong ','Tuo ','Song ','Shu ','Qing ','Yu ','Yu ','Miao ', + 'Sou ','Ce ','Xiang ','Fei ','Jiu ','He ','Hui ','Liu ','Sha ','Lian ','Lang ','Sou ','Zhi ','Pou ','Qing ','Jiu ', + 'Jiu ','Jin ','Ao ','Kuo ','Lou ','Yin ','Liao ','Dai ','Lu ','Yi ','Chu ','Chan ','Tu ','Si ','Xin ','Miao ', + 'Chang ','Wu ','Fei ','Guang ','Koc ','Kuai ','Bi ','Qiang ','Xie ','Lin ','Lin ','Liao ','Lu ','','Ying ','Xian ', + 'Ting ','Yong ','Li ','Ting ','Yin ','Xun ','Yan ','Ting ','Di ','Po ','Jian ','Hui ','Nai ','Hui ','Gong ','Nian ', + ], + 'x5f':[ + 'Kai ','Bian ','Yi ','Qi ','Nong ','Fen ','Ju ','Yan ','Yi ','Zang ','Bi ','Yi ','Yi ','Er ','San ','Shi ', + 'Er ','Shi ','Shi ','Gong ','Diao ','Yin ','Hu ','Fu ','Hong ','Wu ','Tui ','Chi ','Jiang ','Ba ','Shen ','Di ', + 'Zhang ','Jue ','Tao ','Fu ','Di ','Mi ','Xian ','Hu ','Chao ','Nu ','Jing ','Zhen ','Yi ','Mi ','Quan ','Wan ', + 'Shao ','Ruo ','Xuan ','Jing ','Dun ','Zhang ','Jiang ','Qiang ','Peng ','Dan ','Qiang ','Bi ','Bi ','She ','Dan ','Jian ', + 'Gou ','Sei ','Fa ','Bi ','Kou ','Nagi ','Bie ','Xiao ','Dan ','Kuo ','Qiang ','Hong ','Mi ','Kuo ','Wan ','Jue ', + 'Ji ','Ji ','Gui ','Dang ','Lu ','Lu ','Tuan ','Hui ','Zhi ','Hui ','Hui ','Yi ','Yi ','Yi ','Yi ','Huo ', + 'Huo ','Shan ','Xing ','Wen ','Tong ','Yan ','Yan ','Yu ','Chi ','Cai ','Biao ','Diao ','Bin ','Peng ','Yong ','Piao ', + 'Zhang ','Ying ','Chi ','Chi ','Zhuo ','Tuo ','Ji ','Pang ','Zhong ','Yi ','Wang ','Che ','Bi ','Chi ','Ling ','Fu ', + 'Wang ','Zheng ','Cu ','Wang ','Jing ','Dai ','Xi ','Xun ','Hen ','Yang ','Huai ','Lu ','Hou ','Wa ','Cheng ','Zhi ', + 'Xu ','Jing ','Tu ','Cong ','','Lai ','Cong ','De ','Pai ','Xi ','','Qi ','Chang ','Zhi ','Cong ','Zhou ', + 'Lai ','Yu ','Xie ','Jie ','Jian ','Chi ','Jia ','Bian ','Huang ','Fu ','Xun ','Wei ','Pang ','Yao ','Wei ','Xi ', + 'Zheng ','Piao ','Chi ','De ','Zheng ','Zheng ','Bie ','De ','Chong ','Che ','Jiao ','Wei ','Jiao ','Hui ','Mei ','Long ', + 'Xiang ','Bao ','Qu ','Xin ','Ritsushinben ','Bi ','Yi ','Le ','Ren ','Dao ','Ding ','Gai ','Ji ','Ren ','Ren ','Chan ', + 'Tan ','Te ','Te ','Gan ','Qi ','Shi ','Cun ','Zhi ','Wang ','Mang ','Xi ','Fan ','Ying ','Tian ','Min ','Min ', + 'Zhong ','Chong ','Wu ','Ji ','Wu ','Xi ','Ye ','You ','Wan ','Cong ','Zhong ','Kuai ','Yu ','Bian ','Zhi ','Qi ', + 'Cui ','Chen ','Tai ','Tun ','Qian ','Nian ','Hun ','Xiong ','Niu ','Wang ','Xian ','Xin ','Kang ','Hu ','Kai ','Fen ', + ], + 'x60':[ + 'Huai ','Tai ','Song ','Wu ','Ou ','Chang ','Chuang ','Ju ','Yi ','Bao ','Chao ','Min ','Pei ','Zuo ','Zen ','Yang ', + 'Kou ','Ban ','Nu ','Nao ','Zheng ','Pa ','Bu ','Tie ','Gu ','Hu ','Ju ','Da ','Lian ','Si ','Chou ','Di ', + 'Dai ','Yi ','Tu ','You ','Fu ','Ji ','Peng ','Xing ','Yuan ','Ni ','Guai ','Fu ','Xi ','Bi ','You ','Qie ', + 'Xuan ','Cong ','Bing ','Huang ','Xu ','Chu ','Pi ','Xi ','Xi ','Tan ','Koraeru ','Zong ','Dui ','','Ki ','Yi ', + 'Chi ','Ren ','Xun ','Shi ','Xi ','Lao ','Heng ','Kuang ','Mu ','Zhi ','Xie ','Lian ','Tiao ','Huang ','Die ','Hao ', + 'Kong ','Gui ','Heng ','Xi ','Xiao ','Shu ','Shi ','Kua ','Qiu ','Yang ','Hui ','Hui ','Chi ','Jia ','Yi ','Xiong ', + 'Guai ','Lin ','Hui ','Zi ','Xu ','Chi ','Xiang ','Nu ','Hen ','En ','Ke ','Tong ','Tian ','Gong ','Quan ','Xi ', + 'Qia ','Yue ','Peng ','Ken ','De ','Hui ','E ','Kyuu ','Tong ','Yan ','Kai ','Ce ','Nao ','Yun ','Mang ','Yong ', + 'Yong ','Yuan ','Pi ','Kun ','Qiao ','Yue ','Yu ','Yu ','Jie ','Xi ','Zhe ','Lin ','Ti ','Han ','Hao ','Qie ', + 'Ti ','Bu ','Yi ','Qian ','Hui ','Xi ','Bei ','Man ','Yi ','Heng ','Song ','Quan ','Cheng ','Kui ','Wu ','Wu ', + 'You ','Li ','Liang ','Huan ','Cong ','Yi ','Yue ','Li ','Nin ','Nao ','E ','Que ','Xuan ','Qian ','Wu ','Min ', + 'Cong ','Fei ','Bei ','Duo ','Cui ','Chang ','Men ','Li ','Ji ','Guan ','Guan ','Xing ','Dao ','Qi ','Kong ','Tian ', + 'Lun ','Xi ','Kan ','Kun ','Ni ','Qing ','Chou ','Dun ','Guo ','Chan ','Liang ','Wan ','Yuan ','Jin ','Ji ','Lin ', + 'Yu ','Huo ','He ','Quan ','Tan ','Ti ','Ti ','Nie ','Wang ','Chuo ','Hu ','Hun ','Xi ','Chang ','Xin ','Wei ', + 'Hui ','E ','Rui ','Zong ','Jian ','Yong ','Dian ','Ju ','Can ','Cheng ','De ','Bei ','Qie ','Can ','Dan ','Guan ', + 'Duo ','Nao ','Yun ','Xiang ','Zhui ','Die ','Huang ','Chun ','Qiong ','Re ','Xing ','Ce ','Bian ','Hun ','Zong ','Ti ', + ], + 'x61':[ + 'Qiao ','Chou ','Bei ','Xuan ','Wei ','Ge ','Qian ','Wei ','Yu ','Yu ','Bi ','Xuan ','Huan ','Min ','Bi ','Yi ', + 'Mian ','Yong ','Kai ','Dang ','Yin ','E ','Chen ','Mou ','Ke ','Ke ','Yu ','Ai ','Qie ','Yan ','Nuo ','Gan ', + 'Yun ','Zong ','Sai ','Leng ','Fen ','','Kui ','Kui ','Que ','Gong ','Yun ','Su ','Su ','Qi ','Yao ','Song ', + 'Huang ','Ji ','Gu ','Ju ','Chuang ','Ni ','Xie ','Kai ','Zheng ','Yong ','Cao ','Sun ','Shen ','Bo ','Kai ','Yuan ', + 'Xie ','Hun ','Yong ','Yang ','Li ','Sao ','Tao ','Yin ','Ci ','Xu ','Qian ','Tai ','Huang ','Yun ','Shen ','Ming ', + '','She ','Cong ','Piao ','Mo ','Mu ','Guo ','Chi ','Can ','Can ','Can ','Cui ','Min ','Te ','Zhang ','Tong ', + 'Ao ','Shuang ','Man ','Guan ','Que ','Zao ','Jiu ','Hui ','Kai ','Lian ','Ou ','Song ','Jin ','Yin ','Lu ','Shang ', + 'Wei ','Tuan ','Man ','Qian ','She ','Yong ','Qing ','Kang ','Di ','Zhi ','Lou ','Juan ','Qi ','Qi ','Yu ','Ping ', + 'Liao ','Cong ','You ','Chong ','Zhi ','Tong ','Cheng ','Qi ','Qu ','Peng ','Bei ','Bie ','Chun ','Jiao ','Zeng ','Chi ', + 'Lian ','Ping ','Kui ','Hui ','Qiao ','Cheng ','Yin ','Yin ','Xi ','Xi ','Dan ','Tan ','Duo ','Dui ','Dui ','Su ', + 'Jue ','Ce ','Xiao ','Fan ','Fen ','Lao ','Lao ','Chong ','Han ','Qi ','Xian ','Min ','Jing ','Liao ','Wu ','Can ', + 'Jue ','Cu ','Xian ','Tan ','Sheng ','Pi ','Yi ','Chu ','Xian ','Nao ','Dan ','Tan ','Jing ','Song ','Han ','Jiao ', + 'Wai ','Huan ','Dong ','Qin ','Qin ','Qu ','Cao ','Ken ','Xie ','Ying ','Ao ','Mao ','Yi ','Lin ','Se ','Jun ', + 'Huai ','Men ','Lan ','Ai ','Lin ','Yan ','Gua ','Xia ','Chi ','Yu ','Yin ','Dai ','Meng ','Ai ','Meng ','Dui ', + 'Qi ','Mo ','Lan ','Men ','Chou ','Zhi ','Nuo ','Nuo ','Yan ','Yang ','Bo ','Zhi ','Kuang ','Kuang ','You ','Fu ', + 'Liu ','Mie ','Cheng ','','Chan ','Meng ','Lan ','Huai ','Xuan ','Rang ','Chan ','Ji ','Ju ','Huan ','She ','Yi ', + ], + 'x62':[ + 'Lian ','Nan ','Mi ','Tang ','Jue ','Gang ','Gang ','Gang ','Ge ','Yue ','Wu ','Jian ','Xu ','Shu ','Rong ','Xi ', + 'Cheng ','Wo ','Jie ','Ge ','Jian ','Qiang ','Huo ','Qiang ','Zhan ','Dong ','Qi ','Jia ','Die ','Zei ','Jia ','Ji ', + 'Shi ','Kan ','Ji ','Kui ','Gai ','Deng ','Zhan ','Chuang ','Ge ','Jian ','Jie ','Yu ','Jian ','Yan ','Lu ','Xi ', + 'Zhan ','Xi ','Xi ','Chuo ','Dai ','Qu ','Hu ','Hu ','Hu ','E ','Shi ','Li ','Mao ','Hu ','Li ','Fang ', + 'Suo ','Bian ','Dian ','Jiong ','Shang ','Yi ','Yi ','Shan ','Hu ','Fei ','Yan ','Shou ','Shu ','Cai ','Zha ','Qiu ', + 'Le ','Pu ','Ba ','Da ','Reng ','Fu ','Hameru ','Zai ','Tuo ','Zhang ','Diao ','Kang ','Yu ','Ku ','Han ','Shen ', + 'Cha ','Yi ','Gu ','Kou ','Wu ','Tuo ','Qian ','Zhi ','Ren ','Kuo ','Men ','Sao ','Yang ','Niu ','Ban ','Che ', + 'Rao ','Xi ','Qian ','Ban ','Jia ','Yu ','Fu ','Ao ','Xi ','Pi ','Zhi ','Zi ','E ','Dun ','Zhao ','Cheng ', + 'Ji ','Yan ','Kuang ','Bian ','Chao ','Ju ','Wen ','Hu ','Yue ','Jue ','Ba ','Qin ','Zhen ','Zheng ','Yun ','Wan ', + 'Nu ','Yi ','Shu ','Zhua ','Pou ','Tou ','Dou ','Kang ','Zhe ','Pou ','Fu ','Pao ','Ba ','Ao ','Ze ','Tuan ', + 'Kou ','Lun ','Qiang ','','Hu ','Bao ','Bing ','Zhi ','Peng ','Tan ','Pu ','Pi ','Tai ','Yao ','Zhen ','Zha ', + 'Yang ','Bao ','He ','Ni ','Yi ','Di ','Chi ','Pi ','Za ','Mo ','Mei ','Shen ','Ya ','Chou ','Qu ','Min ', + 'Chu ','Jia ','Fu ','Zhan ','Zhu ','Dan ','Chai ','Mu ','Nian ','La ','Fu ','Pao ','Ban ','Pai ','Ling ','Na ', + 'Guai ','Qian ','Ju ','Tuo ','Ba ','Tuo ','Tuo ','Ao ','Ju ','Zhuo ','Pan ','Zhao ','Bai ','Bai ','Di ','Ni ', + 'Ju ','Kuo ','Long ','Jian ','','Yong ','Lan ','Ning ','Bo ','Ze ','Qian ','Hen ','Kuo ','Shi ','Jie ','Zheng ', + 'Nin ','Gong ','Gong ','Quan ','Shuan ','Cun ','Zan ','Kao ','Chi ','Xie ','Ce ','Hui ','Pin ','Ye ','Shi ','Na ', + ], + 'x63':[ + 'Bo ','Chi ','Gua ','Zhi ','Kuo ','Duo ','Duo ','Zhi ','Qie ','An ','Nong ','Zhen ','Ge ','Jiao ','Ku ','Dong ', + 'Ru ','Tiao ','Lie ','Zha ','Lu ','Die ','Wa ','Jue ','Lyut ','Ju ','Zhi ','Luan ','Ya ','Zhua ','Ta ','Xie ', + 'Nao ','Dang ','Jiao ','Zheng ','Ji ','Hui ','Xun ','Ku ','Ai ','Tuo ','Nuo ','Cuo ','Bo ','Geng ','Ti ','Zhen ', + 'Cheng ','Suo ','Suo ','Keng ','Mei ','Long ','Ju ','Peng ','Jian ','Yi ','Ting ','Shan ','Nuo ','Wan ','Xie ','Cha ', + 'Feng ','Jiao ','Wu ','Jun ','Jiu ','Tong ','Kun ','Huo ','Tu ','Zhuo ','Pou ','Le ','Ba ','Han ','Shao ','Nie ', + 'Juan ','Ze ','Song ','Ye ','Jue ','Bu ','Huan ','Bu ','Zun ','Yi ','Zhai ','Lu ','Sou ','Tuo ','Lao ','Sun ', + 'Bang ','Jian ','Huan ','Dao ','','Wan ','Qin ','Peng ','She ','Lie ','Min ','Men ','Fu ','Bai ','Ju ','Dao ', + 'Wo ','Ai ','Juan ','Yue ','Zong ','Chen ','Chui ','Jie ','Tu ','Ben ','Na ','Nian ','Nuo ','Zu ','Wo ','Xi ', + 'Xian ','Cheng ','Dian ','Sao ','Lun ','Qing ','Gang ','Duo ','Shou ','Diao ','Pou ','Di ','Zhang ','Gun ','Ji ','Tao ', + 'Qia ','Qi ','Pai ','Shu ','Qian ','Ling ','Ye ','Ya ','Jue ','Zheng ','Liang ','Gua ','Yi ','Huo ','Shan ','Zheng ', + 'Lue ','Cai ','Tan ','Che ','Bing ','Jie ','Ti ','Kong ','Tui ','Yan ','Cuo ','Zou ','Ju ','Tian ','Qian ','Ken ', + 'Bai ','Shou ','Jie ','Lu ','Guo ','Haba ','','Zhi ','Dan ','Maang ','Xian ','Sao ','Guan ','Peng ','Yuan ','Nuo ', + 'Jian ','Zhen ','Jiu ','Jian ','Yu ','Yan ','Kui ','Nan ','Hong ','Rou ','Pi ','Wei ','Sai ','Zou ','Xuan ','Miao ', + 'Ti ','Nie ','Cha ','Shi ','Zong ','Zhen ','Yi ','Shun ','Heng ','Bian ','Yang ','Huan ','Yan ','Zuan ','An ','Xu ', + 'Ya ','Wo ','Ke ','Chuai ','Ji ','Ti ','La ','La ','Cheng ','Kai ','Jiu ','Jiu ','Tu ','Jie ','Hui ','Geng ', + 'Chong ','Shuo ','She ','Xie ','Yuan ','Qian ','Ye ','Cha ','Zha ','Bei ','Yao ','','Dam ','Lan ','Wen ','Qin ', + ], + 'x64':[ + 'Chan ','Ge ','Lou ','Zong ','Geng ','Jiao ','Gou ','Qin ','Yong ','Que ','Chou ','Chi ','Zhan ','Sun ','Sun ','Bo ', + 'Chu ','Rong ','Beng ','Cuo ','Sao ','Ke ','Yao ','Dao ','Zhi ','Nu ','Xie ','Jian ','Sou ','Qiu ','Gao ','Xian ', + 'Shuo ','Sang ','Jin ','Mie ','E ','Chui ','Nuo ','Shan ','Ta ','Jie ','Tang ','Pan ','Ban ','Da ','Li ','Tao ', + 'Hu ','Zhi ','Wa ','Xia ','Qian ','Wen ','Qiang ','Tian ','Zhen ','E ','Xi ','Nuo ','Quan ','Cha ','Zha ','Ge ', + 'Wu ','En ','She ','Kang ','She ','Shu ','Bai ','Yao ','Bin ','Sou ','Tan ','Sa ','Chan ','Suo ','Liao ','Chong ', + 'Chuang ','Guo ','Bing ','Feng ','Shuai ','Di ','Qi ','','Zhai ','Lian ','Tang ','Chi ','Guan ','Lu ','Luo ','Lou ', + 'Zong ','Gai ','Hu ','Zha ','Chuang ','Tang ','Hua ','Cui ','Nai ','Mo ','Jiang ','Gui ','Ying ','Zhi ','Ao ','Zhi ', + 'Nie ','Man ','Shan ','Kou ','Shu ','Suo ','Tuan ','Jiao ','Mo ','Mo ','Zhe ','Shan ','Keng ','Piao ','Jiang ','Yin ', + 'Gou ','Qian ','Liao ','Ji ','Ying ','Jue ','Pie ','Pie ','Lao ','Dun ','Xian ','Ruan ','Kui ','Zan ','Yi ','Xun ', + 'Cheng ','Cheng ','Sa ','Nao ','Heng ','Si ','Qian ','Huang ','Da ','Zun ','Nian ','Lin ','Zheng ','Hui ','Zhuang ','Jiao ', + 'Ji ','Cao ','Dan ','Dan ','Che ','Bo ','Che ','Jue ','Xiao ','Liao ','Ben ','Fu ','Qiao ','Bo ','Cuo ','Zhuo ', + 'Zhuan ','Tuo ','Pu ','Qin ','Dun ','Nian ','','Xie ','Lu ','Jiao ','Cuan ','Ta ','Han ','Qiao ','Zhua ','Jian ', + 'Gan ','Yong ','Lei ','Kuo ','Lu ','Shan ','Zhuo ','Ze ','Pu ','Chuo ','Ji ','Dang ','Suo ','Cao ','Qing ','Jing ', + 'Huan ','Jie ','Qin ','Kuai ','Dan ','Xi ','Ge ','Pi ','Bo ','Ao ','Ju ','Ye ','','Mang ','Sou ','Mi ', + 'Ji ','Tai ','Zhuo ','Dao ','Xing ','Lan ','Ca ','Ju ','Ye ','Ru ','Ye ','Ye ','Ni ','Wo ','Ji ','Bin ', + 'Ning ','Ge ','Zhi ','Jie ','Kuo ','Mo ','Jian ','Xie ','Lie ','Tan ','Bai ','Sou ','Lu ','Lue ','Rao ','Zhi ', + ], + 'x65':[ + 'Pan ','Yang ','Lei ','Sa ','Shu ','Zan ','Nian ','Xian ','Jun ','Huo ','Li ','La ','Han ','Ying ','Lu ','Long ', + 'Qian ','Qian ','Zan ','Qian ','Lan ','San ','Ying ','Mei ','Rang ','Chan ','','Cuan ','Xie ','She ','Luo ','Jun ', + 'Mi ','Li ','Zan ','Luan ','Tan ','Zuan ','Li ','Dian ','Wa ','Dang ','Jiao ','Jue ','Lan ','Li ','Nang ','Zhi ', + 'Gui ','Gui ','Qi ','Xin ','Pu ','Sui ','Shou ','Kao ','You ','Gai ','Yi ','Gong ','Gan ','Ban ','Fang ','Zheng ', + 'Bo ','Dian ','Kou ','Min ','Wu ','Gu ','He ','Ce ','Xiao ','Mi ','Chu ','Ge ','Di ','Xu ','Jiao ','Min ', + 'Chen ','Jiu ','Zhen ','Duo ','Yu ','Chi ','Ao ','Bai ','Xu ','Jiao ','Duo ','Lian ','Nie ','Bi ','Chang ','Dian ', + 'Duo ','Yi ','Gan ','San ','Ke ','Yan ','Dun ','Qi ','Dou ','Xiao ','Duo ','Jiao ','Jing ','Yang ','Xia ','Min ', + 'Shu ','Ai ','Qiao ','Ai ','Zheng ','Di ','Zhen ','Fu ','Shu ','Liao ','Qu ','Xiong ','Xi ','Jiao ','Sen ','Jiao ', + 'Zhuo ','Yi ','Lian ','Bi ','Li ','Xiao ','Xiao ','Wen ','Xue ','Qi ','Qi ','Zhai ','Bin ','Jue ','Zhai ','', + 'Fei ','Ban ','Ban ','Lan ','Yu ','Lan ','Wei ','Dou ','Sheng ','Liao ','Jia ','Hu ','Xie ','Jia ','Yu ','Zhen ', + 'Jiao ','Wo ','Tou ','Chu ','Jin ','Chi ','Yin ','Fu ','Qiang ','Zhan ','Qu ','Zhuo ','Zhan ','Duan ','Zhuo ','Si ', + 'Xin ','Zhuo ','Zhuo ','Qin ','Lin ','Zhuo ','Chu ','Duan ','Zhu ','Fang ','Xie ','Hang ','Yu ','Shi ','Pei ','You ', + 'Mye ','Pang ','Qi ','Zhan ','Mao ','Lu ','Pei ','Pi ','Liu ','Fu ','Fang ','Xuan ','Jing ','Jing ','Ni ','Zu ', + 'Zhao ','Yi ','Liu ','Shao ','Jian ','Es ','Yi ','Qi ','Zhi ','Fan ','Piao ','Fan ','Zhan ','Guai ','Sui ','Yu ', + 'Wu ','Ji ','Ji ','Ji ','Huo ','Ri ','Dan ','Jiu ','Zhi ','Zao ','Xie ','Tiao ','Xun ','Xu ','Xu ','Xu ', + 'Gan ','Han ','Tai ','Di ','Xu ','Chan ','Shi ','Kuang ','Yang ','Shi ','Wang ','Min ','Min ','Tun ','Chun ','Wu ', + ], + 'x66':[ + 'Yun ','Bei ','Ang ','Ze ','Ban ','Jie ','Kun ','Sheng ','Hu ','Fang ','Hao ','Gui ','Chang ','Xuan ','Ming ','Hun ', + 'Fen ','Qin ','Hu ','Yi ','Xi ','Xin ','Yan ','Ze ','Fang ','Tan ','Shen ','Ju ','Yang ','Zan ','Bing ','Xing ', + 'Ying ','Xuan ','Pei ','Zhen ','Ling ','Chun ','Hao ','Mei ','Zuo ','Mo ','Bian ','Xu ','Hun ','Zhao ','Zong ','Shi ', + 'Shi ','Yu ','Fei ','Die ','Mao ','Ni ','Chang ','Wen ','Dong ','Ai ','Bing ','Ang ','Zhou ','Long ','Xian ','Kuang ', + 'Tiao ','Chao ','Shi ','Huang ','Huang ','Xuan ','Kui ','Xu ','Jiao ','Jin ','Zhi ','Jin ','Shang ','Tong ','Hong ','Yan ', + 'Gai ','Xiang ','Shai ','Xiao ','Ye ','Yun ','Hui ','Han ','Han ','Jun ','Wan ','Xian ','Kun ','Zhou ','Xi ','Sheng ', + 'Sheng ','Bu ','Zhe ','Zhe ','Wu ','Han ','Hui ','Hao ','Chen ','Wan ','Tian ','Zhuo ','Zui ','Zhou ','Pu ','Jing ', + 'Xi ','Shan ','Yi ','Xi ','Qing ','Qi ','Jing ','Gui ','Zhen ','Yi ','Zhi ','An ','Wan ','Lin ','Liang ','Chang ', + 'Wang ','Xiao ','Zan ','Hi ','Xuan ','Xuan ','Yi ','Xia ','Yun ','Hui ','Fu ','Min ','Kui ','He ','Ying ','Du ', + 'Wei ','Shu ','Qing ','Mao ','Nan ','Jian ','Nuan ','An ','Yang ','Chun ','Yao ','Suo ','Jin ','Ming ','Jiao ','Kai ', + 'Gao ','Weng ','Chang ','Qi ','Hao ','Yan ','Li ','Ai ','Ji ','Gui ','Men ','Zan ','Xie ','Hao ','Mu ','Mo ', + 'Cong ','Ni ','Zhang ','Hui ','Bao ','Han ','Xuan ','Chuan ','Liao ','Xian ','Dan ','Jing ','Pie ','Lin ','Tun ','Xi ', + 'Yi ','Ji ','Huang ','Tai ','Ye ','Ye ','Li ','Tan ','Tong ','Xiao ','Fei ','Qin ','Zhao ','Hao ','Yi ','Xiang ', + 'Xing ','Sen ','Jiao ','Bao ','Jing ','Yan ','Ai ','Ye ','Ru ','Shu ','Meng ','Xun ','Yao ','Pu ','Li ','Chen ', + 'Kuang ','Die ','','Yan ','Huo ','Lu ','Xi ','Rong ','Long ','Nang ','Luo ','Luan ','Shai ','Tang ','Yan ','Chu ', + 'Yue ','Yue ','Qu ','Ye ','Geng ','Ye ','Hu ','He ','Shu ','Cao ','Cao ','Shou ','Man ','Ceng ','Ceng ','Ti ', + ], + 'x67':[ + 'Zui ','Can ','Xu ','Hui ','Yin ','Qie ','Fen ','Pi ','Yue ','You ','Ruan ','Peng ','Ban ','Fu ','Ling ','Fei ', + 'Qu ','','Nu ','Tiao ','Shuo ','Zhen ','Lang ','Lang ','Juan ','Ming ','Huang ','Wang ','Tun ','Zhao ','Ji ','Qi ', + 'Ying ','Zong ','Wang ','Tong ','Lang ','','Meng ','Long ','Mu ','Deng ','Wei ','Mo ','Ben ','Zha ','Shu ','Zhu ', + '','Zhu ','Ren ','Ba ','Po ','Duo ','Duo ','Dao ','Li ','Qiu ','Ji ','Jiu ','Bi ','Xiu ','Ting ','Ci ', + 'Sha ','Eburi ','Za ','Quan ','Qian ','Yu ','Gan ','Wu ','Cha ','Shan ','Xun ','Fan ','Wu ','Zi ','Li ','Xing ', + 'Cai ','Cun ','Ren ','Shao ','Tuo ','Di ','Zhang ','Mang ','Chi ','Yi ','Gu ','Gong ','Du ','Yi ','Qi ','Shu ', + 'Gang ','Tiao ','Moku ','Son ','Tochi ','Lai ','Sugi ','Mang ','Yang ','Ma ','Miao ','Si ','Yuan ','Hang ','Fei ','Bei ', + 'Jie ','Dong ','Gao ','Yao ','Xian ','Chu ','Chun ','Pa ','Shu ','Hua ','Xin ','Chou ','Zhu ','Chou ','Song ','Ban ', + 'Song ','Ji ','Yue ','Jin ','Gou ','Ji ','Mao ','Pi ','Bi ','Wang ','Ang ','Fang ','Fen ','Yi ','Fu ','Nan ', + 'Xi ','Hu ','Ya ','Dou ','Xun ','Zhen ','Yao ','Lin ','Rui ','E ','Mei ','Zhao ','Guo ','Zhi ','Cong ','Yun ', + 'Waku ','Dou ','Shu ','Zao ','','Li ','Ro ','Jian ','Cheng ','Shou ','Qiang ','Feng ','Nan ','Xiao ','Xian ','Ku ', + 'Ping ','Yi ','Xi ','Zhi ','Guai ','Xiao ','Jia ','Jia ','Ju ','Fu ','Mo ','Yi ','Ye ','Ye ','Shi ','Nie ', + 'Bi ','Duo ','Yi ','Ling ','Bing ','Ni ','La ','He ','Pan ','Fan ','Zhong ','Dai ','Ci ','Yang ','Fu ','Bai ', + 'Mou ','Gan ','Qi ','Ran ','Rou ','Mao ','Zhao ','Song ','Zhe ','Xia ','You ','Shen ','Gui ','Tuo ','Zuo ','Nan ', + 'Ning ','Yong ','Di ','Zhi ','Zha ','Cha ','Dan ','Gu ','','Jiu ','Ao ','Fu ','Jian ','Bo ','Duo ','Ke ', + 'Nai ','Zhu ','Bi ','Liu ','Chai ','Zha ','Si ','Zhu ','Pei ','Shi ','Guai ','Cha ','Yao ','Jue ','Jiu ','Shi ', + ], + 'x68':[ + 'Zhi ','Liu ','Mei ','Hoy ','Rong ','Zha ','','Biao ','Zhan ','Jie ','Long ','Dong ','Lu ','Sayng ','Li ','Lan ', + 'Yong ','Shu ','Xun ','Shuan ','Qi ','Zhen ','Qi ','Li ','Yi ','Xiang ','Zhen ','Li ','Su ','Gua ','Kan ','Bing ', + 'Ren ','Xiao ','Bo ','Ren ','Bing ','Zi ','Chou ','Yi ','Jie ','Xu ','Zhu ','Jian ','Zui ','Er ','Er ','You ', + 'Fa ','Gong ','Kao ','Lao ','Zhan ','Li ','','Yang ','He ','Gen ','Zhi ','Shi ','Ge ','Zai ','Luan ','Fu ', + 'Jie ','Heng ','Gui ','Tao ','Guang ','Wei ','Kuang ','Ru ','An ','An ','Juan ','Yi ','Zhuo ','Ku ','Zhi ','Qiong ', + 'Tong ','Sang ','Sang ','Huan ','Jie ','Jiu ','Xue ','Duo ','Zhui ','Yu ','Zan ','Kasei ','Ying ','Masu ','','Zhan ', + 'Ya ','Nao ','Zhen ','Dang ','Qi ','Qiao ','Hua ','Kuai ','Jiang ','Zhuang ','Xun ','Suo ','Sha ','Zhen ','Bei ','Ting ', + 'Gua ','Jing ','Bo ','Ben ','Fu ','Rui ','Tong ','Jue ','Xi ','Lang ','Liu ','Feng ','Qi ','Wen ','Jun ','Gan ', + 'Cu ','Liang ','Qiu ','Ting ','You ','Mei ','Bang ','Long ','Peng ','Zhuang ','Di ','Xuan ','Tu ','Zao ','Ao ','Gu ', + 'Bi ','Di ','Han ','Zi ','Zhi ','Ren ','Bei ','Geng ','Jian ','Huan ','Wan ','Nuo ','Jia ','Tiao ','Ji ','Xiao ', + 'Lu ','Hun ','Shao ','Cen ','Fen ','Song ','Meng ','Wu ','Li ','Li ','Dou ','Cen ','Ying ','Suo ','Ju ','Ti ', + 'Xie ','Kun ','Zhuo ','Shu ','Chan ','Fan ','Wei ','Jing ','Li ','Bing ','Fumoto ','Shikimi ','Tao ','Zhi ','Lai ','Lian ', + 'Jian ','Zhuo ','Ling ','Li ','Qi ','Bing ','Zhun ','Cong ','Qian ','Mian ','Qi ','Qi ','Cai ','Gun ','Chan ','Te ', + 'Fei ','Pai ','Bang ','Pou ','Hun ','Zong ','Cheng ','Zao ','Ji ','Li ','Peng ','Yu ','Yu ','Gu ','Hun ','Dong ', + 'Tang ','Gang ','Wang ','Di ','Xi ','Fan ','Cheng ','Zhan ','Qi ','Yuan ','Yan ','Yu ','Quan ','Yi ','Sen ','Ren ', + 'Chui ','Leng ','Qi ','Zhuo ','Fu ','Ke ','Lai ','Zou ','Zou ','Zhuo ','Guan ','Fen ','Fen ','Chen ','Qiong ','Nie ', + ], + 'x69':[ + 'Wan ','Guo ','Lu ','Hao ','Jie ','Yi ','Chou ','Ju ','Ju ','Cheng ','Zuo ','Liang ','Qiang ','Zhi ','Zhui ','Ya ', + 'Ju ','Bei ','Jiao ','Zhuo ','Zi ','Bin ','Peng ','Ding ','Chu ','Chang ','Mun ','Momiji ','Jian ','Gui ','Xi ','Du ', + 'Qian ','Kunugi ','Kai ','Shide ','Luo ','Zhi ','Ken ','Myeng ','Tafu ','','Peng ','Zhan ','','Tuo ','Sen ','Duo ', + 'Ye ','Fou ','Wei ','Wei ','Duan ','Jia ','Zong ','Jian ','Yi ','Shen ','Xi ','Yan ','Yan ','Chuan ','Zhan ','Chun ', + 'Yu ','He ','Zha ','Wo ','Pian ','Bi ','Yao ','Huo ','Xu ','Ruo ','Yang ','La ','Yan ','Ben ','Hun ','Kui ', + 'Jie ','Kui ','Si ','Feng ','Xie ','Tuo ','Zhi ','Jian ','Mu ','Mao ','Chu ','Hu ','Hu ','Lian ','Leng ','Ting ', + 'Nan ','Yu ','You ','Mei ','Song ','Xuan ','Xuan ','Ying ','Zhen ','Pian ','Ye ','Ji ','Jie ','Ye ','Chu ','Shun ', + 'Yu ','Cou ','Wei ','Mei ','Di ','Ji ','Jie ','Kai ','Qiu ','Ying ','Rou ','Heng ','Lou ','Le ','Hazou ','Katsura ', + 'Pin ','Muro ','Gai ','Tan ','Lan ','Yun ','Yu ','Chen ','Lu ','Ju ','Sakaki ','','Pi ','Xie ','Jia ','Yi ', + 'Zhan ','Fu ','Nai ','Mi ','Lang ','Rong ','Gu ','Jian ','Ju ','Ta ','Yao ','Zhen ','Bang ','Sha ','Yuan ','Zi ', + 'Ming ','Su ','Jia ','Yao ','Jie ','Huang ','Gan ','Fei ','Zha ','Qian ','Ma ','Sun ','Yuan ','Xie ','Rong ','Shi ', + 'Zhi ','Cui ','Yun ','Ting ','Liu ','Rong ','Tang ','Que ','Zhai ','Si ','Sheng ','Ta ','Ke ','Xi ','Gu ','Qi ', + 'Kao ','Gao ','Sun ','Pan ','Tao ','Ge ','Xun ','Dian ','Nou ','Ji ','Shuo ','Gou ','Chui ','Qiang ','Cha ','Qian ', + 'Huai ','Mei ','Xu ','Gang ','Gao ','Zhuo ','Tuo ','Kyou ','Yang ','Dian ','Jia ','Jian ','Zui ','Tou ','Rou ','Bin ', + 'Zhu ','','Xi ','Qi ','Lian ','Hui ','Yong ','Qian ','Guo ','Gai ','Gai ','Tuan ','Hua ','Cu ','Sen ','Cui ', + 'Beng ','You ','Hu ','Jiang ','Hu ','Huan ','Kui ','Yi ','Nie ','Gao ','Kang ','Gui ','Gui ','Cao ','Man ','Jin ', + ], + 'x6a':[ + 'Di ','Zhuang ','Le ','Lang ','Chen ','Cong ','Li ','Xiu ','Qing ','Shuang ','Fan ','Tong ','Guan ','Ji ','Suo ','Lei ', + 'Lu ','Liang ','Mi ','Lou ','Chao ','Su ','Ke ','Chu ','Tang ','Biao ','Lu ','Jiu ','Shu ','Zha ','Shu ','Zhang ', + 'Men ','Mo ','Niao ','Yang ','Tiao ','Peng ','Zhu ','Sha ','Xi ','Quan ','Heng ','Jian ','Cong ','','Hokuso ','Qiang ', + 'Tara ','Ying ','Er ','Xin ','Zhi ','Qiao ','Zui ','Cong ','Pu ','Shu ','Hua ','Kui ','Zhen ','Zun ','Yue ','Zhan ', + 'Xi ','Xun ','Dian ','Fa ','Gan ','Mo ','Wu ','Qiao ','Nao ','Lin ','Liu ','Qiao ','Xian ','Run ','Fan ','Zhan ', + 'Tuo ','Lao ','Yun ','Shun ','Tui ','Cheng ','Tang ','Meng ','Ju ','Cheng ','Su ','Jue ','Jue ','Tan ','Hui ','Ji ', + 'Nuo ','Xiang ','Tuo ','Ning ','Rui ','Zhu ','Chuang ','Zeng ','Fen ','Qiong ','Ran ','Heng ','Cen ','Gu ','Liu ','Lao ', + 'Gao ','Chu ','Zusa ','Nude ','Ca ','San ','Ji ','Dou ','Shou ','Lu ','Gaan ','','Yuan ','Ta ','Shu ','Jiang ', + 'Tan ','Lin ','Nong ','Yin ','Xi ','Sui ','Shan ','Zui ','Xuan ','Cheng ','Gan ','Ju ','Zui ','Yi ','Qin ','Pu ', + 'Yan ','Lei ','Feng ','Hui ','Dang ','Ji ','Sui ','Bo ','Bi ','Ding ','Chu ','Zhua ','Gui ','Ji ','Jie ','Jia ', + 'Qing ','Zhe ','Jian ','Qiang ','Dao ','Yi ','Biao ','Song ','She ','Lin ','Reki ','Cha ','Meng ','Yin ','Tao ','Tai ', + 'Mian ','Qi ','','Bin ','Huo ','Ji ','Qian ','Mi ','Ning ','Yi ','Gao ','Jian ','Yin ','Er ','Qing ','Yan ', + 'Qi ','Mi ','Zhao ','Gui ','Chun ','Ji ','Kui ','Po ','Deng ','Chu ','Han ','Mian ','You ','Zhi ','Guang ','Qian ', + 'Lei ','Lei ','Sa ','Lu ','Li ','Cuan ','Lu ','Mie ','Hui ','Ou ','Lu ','Jie ','Gao ','Du ','Yuan ','Li ', + 'Fei ','Zhuo ','Sou ','Lian ','Sen ','Chu ','','Zhu ','Lu ','Yan ','Li ','Zhu ','Chen ','Jie ','E ','Su ', + 'Huai ','Nie ','Yu ','Long ','Lai ','','Xian ','Kwi ','Ju ','Xiao ','Ling ','Ying ','Jian ','Yin ','You ','Ying ', + ], + 'x6b':[ + 'Xiang ','Nong ','Bo ','Chan ','Lan ','Ju ','Shuang ','She ','Wei ','Cong ','Quan ','Qu ','Cang ','','Yu ','Luo ', + 'Li ','Zan ','Luan ','Dang ','Jue ','Em ','Lan ','Lan ','Zhu ','Lei ','Li ','Ba ','Nang ','Yu ','Ling ','Tsuki ', + 'Qian ','Ci ','Huan ','Xin ','Yu ','Yu ','Qian ','Ou ','Xu ','Chao ','Chu ','Chi ','Kai ','Yi ','Jue ','Xi ', + 'Xu ','Xia ','Yu ','Kuai ','Lang ','Kuan ','Shuo ','Xi ','Ai ','Yi ','Qi ','Xu ','Chi ','Qin ','Kuan ','Kan ', + 'Kuan ','Kan ','Chuan ','Sha ','','Yin ','Xin ','Xie ','Yu ','Qian ','Xiao ','Yi ','Ge ','Wu ','Tan ','Jin ', + 'Ou ','Hu ','Ti ','Huan ','Xu ','Pen ','Xi ','Xiao ','Xu ','Xi ','Sen ','Han ','Chu ','Yi ','Kan ','Yu ', + 'Chuo ','Huan ','Zhi ','Zheng ','Ci ','Bu ','Wu ','Qi ','Bu ','Bu ','Wai ','Ju ','Qian ','Chi ','Se ','Chi ', + 'Se ','Zhong ','Sui ','Sui ','Li ','Cuo ','Yu ','Li ','Gui ','Dai ','Dai ','Si ','Jian ','Zhe ','Mo ','Mo ', + 'Yao ','Mo ','Cu ','Yang ','Tian ','Sheng ','Dai ','Shang ','Xu ','Xun ','Shu ','Can ','Jue ','Piao ','Qia ','Qiu ', + 'Su ','Qing ','Yun ','Lian ','Yi ','Fou ','Zhi ','Ye ','Can ','Hun ','Dan ','Ji ','Ye ','','Yun ','Wen ', + 'Chou ','Bin ','Ti ','Jin ','Shang ','Yin ','Diao ','Cu ','Hui ','Cuan ','Yi ','Dan ','Du ','Jiang ','Lian ','Bin ', + 'Du ','Sen ','Jian ','Shu ','Ou ','Duan ','Zhu ','Yin ','Qing ','Yi ','Sha ','Que ','Ke ','Yao ','Jun ','Dian ', + 'Hui ','Hui ','Gu ','Que ','Ji ','Yi ','Ou ','Hui ','Duan ','Yi ','Xiao ','Wu ','Guan ','Mu ','Mei ','Mei ', + 'Ai ','Zuo ','Du ','Yu ','Bi ','Bi ','Bi ','Pi ','Pi ','Bi ','Chan ','Mao ','','','Pu ','Mushiru ', + 'Jia ','Zhan ','Sai ','Mu ','Tuo ','Xun ','Er ','Rong ','Xian ','Ju ','Mu ','Hao ','Qiu ','Dou ','Mushiru ','Tan ', + 'Pei ','Ju ','Duo ','Cui ','Bi ','San ','','Mao ','Sui ','Shu ','Yu ','Tuo ','He ','Jian ','Ta ','San ', + ], + 'x6c':[ + 'Lu ','Mu ','Mao ','Tong ','Rong ','Chang ','Pu ','Luo ','Zhan ','Sao ','Zhan ','Meng ','Luo ','Qu ','Die ','Shi ', + 'Di ','Min ','Jue ','Mang ','Qi ','Pie ','Nai ','Qi ','Dao ','Xian ','Chuan ','Fen ','Ri ','Nei ','','Fu ', + 'Shen ','Dong ','Qing ','Qi ','Yin ','Xi ','Hai ','Yang ','An ','Ya ','Ke ','Qing ','Ya ','Dong ','Dan ','Lu ', + 'Qing ','Yang ','Yun ','Yun ','Shui ','Sanzui ','Zheng ','Bing ','Yong ','Dang ','Sui ','Le ','Ni ','Tun ','Fan ','Gui ', + 'Ting ','Zhi ','Qiu ','Bin ','Ze ','Mian ','Cuan ','Hui ','Diao ','Yi ','Cha ','Zhuo ','Chuan ','Wan ','Fan ','Dai ', + 'Xi ','Tuo ','Mang ','Qiu ','Qi ','Shan ','Pai ','Han ','Qian ','Wu ','Wu ','Xun ','Si ','Ru ','Gong ','Jiang ', + 'Chi ','Wu ','Tsuchi ','','Tang ','Zhi ','Chi ','Qian ','Mi ','Gu ','Wang ','Qing ','Jing ','Rui ','Jun ','Hong ', + 'Tai ','Quan ','Ji ','Bian ','Bian ','Gan ','Wen ','Zhong ','Fang ','Xiong ','Jue ','Hang ','','Qi ','Fen ','Xu ', + 'Xu ','Qin ','Yi ','Wo ','Yun ','Yuan ','Hang ','Yan ','Chen ','Chen ','Dan ','You ','Dun ','Hu ','Huo ','Qi ', + 'Mu ','Rou ','Mei ','Ta ','Mian ','Wu ','Chong ','Tian ','Bi ','Sha ','Zhi ','Pei ','Pan ','Zhui ','Za ','Gou ', + 'Liu ','Mei ','Ze ','Feng ','Ou ','Li ','Lun ','Cang ','Feng ','Wei ','Hu ','Mo ','Mei ','Shu ','Ju ','Zan ', + 'Tuo ','Tuo ','Tuo ','He ','Li ','Mi ','Yi ','Fa ','Fei ','You ','Tian ','Zhi ','Zhao ','Gu ','Zhan ','Yan ', + 'Si ','Kuang ','Jiong ','Ju ','Xie ','Qiu ','Yi ','Jia ','Zhong ','Quan ','Bo ','Hui ','Mi ','Ben ','Zhuo ','Chu ', + 'Le ','You ','Gu ','Hong ','Gan ','Fa ','Mao ','Si ','Hu ','Ping ','Ci ','Fan ','Chi ','Su ','Ning ','Cheng ', + 'Ling ','Pao ','Bo ','Qi ','Si ','Ni ','Ju ','Yue ','Zhu ','Sheng ','Lei ','Xuan ','Xue ','Fu ','Pan ','Min ', + 'Tai ','Yang ','Ji ','Yong ','Guan ','Beng ','Xue ','Long ','Lu ','','Bo ','Xie ','Po ','Ze ','Jing ','Yin ', + ], + 'x6d':[ + 'Zhou ','Ji ','Yi ','Hui ','Hui ','Zui ','Cheng ','Yin ','Wei ','Hou ','Jian ','Yang ','Lie ','Si ','Ji ','Er ', + 'Xing ','Fu ','Sa ','Suo ','Zhi ','Yin ','Wu ','Xi ','Kao ','Zhu ','Jiang ','Luo ','','An ','Dong ','Yi ', + 'Mou ','Lei ','Yi ','Mi ','Quan ','Jin ','Mo ','Wei ','Xiao ','Xie ','Hong ','Xu ','Shuo ','Kuang ','Tao ','Qie ', + 'Ju ','Er ','Zhou ','Ru ','Ping ','Xun ','Xiong ','Zhi ','Guang ','Huan ','Ming ','Huo ','Wa ','Qia ','Pai ','Wu ', + 'Qu ','Liu ','Yi ','Jia ','Jing ','Qian ','Jiang ','Jiao ','Cheng ','Shi ','Zhuo ','Ce ','Pal ','Kuai ','Ji ','Liu ', + 'Chan ','Hun ','Hu ','Nong ','Xun ','Jin ','Lie ','Qiu ','Wei ','Zhe ','Jun ','Han ','Bang ','Mang ','Zhuo ','You ', + 'Xi ','Bo ','Dou ','Wan ','Hong ','Yi ','Pu ','Ying ','Lan ','Hao ','Lang ','Han ','Li ','Geng ','Fu ','Wu ', + 'Lian ','Chun ','Feng ','Yi ','Yu ','Tong ','Lao ','Hai ','Jin ','Jia ','Chong ','Weng ','Mei ','Sui ','Cheng ','Pei ', + 'Xian ','Shen ','Tu ','Kun ','Pin ','Nie ','Han ','Jing ','Xiao ','She ','Nian ','Tu ','Yong ','Xiao ','Xian ','Ting ', + 'E ','Su ','Tun ','Juan ','Cen ','Ti ','Li ','Shui ','Si ','Lei ','Shui ','Tao ','Du ','Lao ','Lai ','Lian ', + 'Wei ','Wo ','Yun ','Huan ','Di ','','Run ','Jian ','Zhang ','Se ','Fu ','Guan ','Xing ','Shou ','Shuan ','Ya ', + 'Chuo ','Zhang ','Ye ','Kong ','Wo ','Han ','Tuo ','Dong ','He ','Wo ','Ju ','Gan ','Liang ','Hun ','Ta ','Zhuo ', + 'Dian ','Qie ','De ','Juan ','Zi ','Xi ','Yao ','Qi ','Gu ','Guo ','Han ','Lin ','Tang ','Zhou ','Peng ','Hao ', + 'Chang ','Shu ','Qi ','Fang ','Chi ','Lu ','Nao ','Ju ','Tao ','Cong ','Lei ','Zhi ','Peng ','Fei ','Song ','Tian ', + 'Pi ','Dan ','Yu ','Ni ','Yu ','Lu ','Gan ','Mi ','Jing ','Ling ','Lun ','Yin ','Cui ','Qu ','Huai ','Yu ', + 'Nian ','Shen ','Piao ','Chun ','Wa ','Yuan ','Lai ','Hun ','Qing ','Yan ','Qian ','Tian ','Miao ','Zhi ','Yin ','Mi ', + ], + 'x6e':[ + 'Ben ','Yuan ','Wen ','Re ','Fei ','Qing ','Yuan ','Ke ','Ji ','She ','Yuan ','Juu ','Lu ','Zi ','Du ','', + 'Jian ','Min ','Pi ','Kei ','Yu ','Yuan ','Shen ','Shen ','Rou ','Huan ','Zhu ','Jian ','Nuan ','Yu ','Qiu ','Ting ', + 'Qu ','Du ','Feng ','Zha ','Bo ','Wo ','Wo ','Di ','Wei ','Wen ','Ru ','Xie ','Ce ','Wei ','Ge ','Gang ', + 'Yan ','Hong ','Xuan ','Mi ','Ke ','Mao ','Ying ','Yan ','You ','Hong ','Miao ','Xing ','Mei ','Zai ','Hun ','Nai ', + 'Kui ','Shi ','E ','Pai ','Mei ','Lian ','Qi ','Qi ','Mei ','Tian ','Cou ','Wei ','Can ','Tuan ','Mian ','Hui ', + 'Mo ','Xu ','Ji ','Pen ','Jian ','Jian ','Hu ','Feng ','Xiang ','Yi ','Yin ','Zhan ','Shi ','Jie ','Cheng ','Huang ', + 'Tan ','Yu ','Bi ','Min ','Shi ','Tu ','Sheng ','Yong ','Qu ','Zhong ','','Jiao ','Jiao ','qiu ','Yin ','Tang ', + 'Long ','Huo ','Yuan ','Nan ','Ban ','You ','Quan ','Chui ','Liang ','Chan ','Yan ','Chun ','Nie ','Zi ','Wan ','Shi ', + 'Man ','Ying ','Ratsu ','Kui ','','Jian ','Xu ','Lu ','Gui ','Gai ','','','Po ','Jin ','Gui ','Tang ', + 'Yuan ','Suo ','Yuan ','Lian ','Yao ','Meng ','Zhun ','Sheng ','Ke ','Tai ','Da ','Wa ','Liu ','Gou ','Sao ','Ming ', + 'Zha ','Shi ','Yi ','Lun ','Ma ','Pu ','Wei ','Li ','Cai ','Wu ','Xi ','Wen ','Qiang ','Ze ','Shi ','Su ', + 'Yi ','Zhen ','Sou ','Yun ','Xiu ','Yin ','Rong ','Hun ','Su ','Su ','Ni ','Ta ','Shi ','Ru ','Wei ','Pan ', + 'Chu ','Chu ','Pang ','Weng ','Cang ','Mie ','He ','Dian ','Hao ','Huang ','Xi ','Zi ','Di ','Zhi ','Xing ','Fu ', + 'Jie ','Hua ','Ge ','Zi ','Tao ','Teng ','Sui ','Bi ','Jiao ','Hui ','Gun ','Yin ','Gao ','Long ','Zhi ','Yan ', + 'She ','Man ','Ying ','Chun ','Lu ','Lan ','Luan ','','Bin ','Tan ','Yu ','Sou ','Hu ','Bi ','Biao ','Zhi ', + 'Jiang ','Kou ','Shen ','Shang ','Di ','Mi ','Ao ','Lu ','Hu ','Hu ','You ','Chan ','Fan ','Yong ','Gun ','Man ', + ], + 'x6f':[ + 'Qing ','Yu ','Piao ','Ji ','Ya ','Jiao ','Qi ','Xi ','Ji ','Lu ','Lu ','Long ','Jin ','Guo ','Cong ','Lou ', + 'Zhi ','Gai ','Qiang ','Li ','Yan ','Cao ','Jiao ','Cong ','Chun ','Tuan ','Ou ','Teng ','Ye ','Xi ','Mi ','Tang ', + 'Mo ','Shang ','Han ','Lian ','Lan ','Wa ','Li ','Qian ','Feng ','Xuan ','Yi ','Man ','Zi ','Mang ','Kang ','Ta ', + 'Peng ','Shu ','Zhang ','Zhang ','Chong ','Xu ','Huan ','Kuo ','Jian ','Yan ','Chuang ','Liao ','Cui ','Ti ','Yang ','Jiang ', + 'Cong ','Ying ','Hong ','Xun ','Shu ','Guan ','Ying ','Xiao ','','','Xu ','Lian ','Zhi ','Wei ','Pi ','Jue ', + 'Jiao ','Po ','Dang ','Hui ','Jie ','Wu ','Pa ','Ji ','Pan ','Gui ','Xiao ','Qian ','Qian ','Xi ','Lu ','Xi ', + 'Sun ','Dun ','Huang ','Min ','Run ','Su ','Lao ','Zhen ','Zhong ','Yi ','Di ','Wan ','Dan ','Tan ','Chao ','Xun ', + 'Kui ','','Shao ','Tu ','Zhu ','San ','Hei ','Bi ','Shan ','Chan ','Chan ','Shu ','Tong ','Pu ','Lin ','Wei ', + 'Se ','Se ','Cheng ','Jiong ','Cheng ','Hua ','Jiao ','Lao ','Che ','Gan ','Cun ','Heng ','Si ','Shu ','Peng ','Han ', + 'Yun ','Liu ','Hong ','Fu ','Hao ','He ','Xian ','Jian ','Shan ','Xi ','Iku ','','Lan ','','Yu ','Lin ', + 'Mian ','Zao ','Dang ','Huan ','Ze ','Xie ','Yu ','Li ','Shi ','Xue ','Ling ','Man ','Zi ','Yong ','Kuai ','Can ', + 'Lian ','Dian ','Ye ','Ao ','Huan ','Zhen ','Chan ','Man ','Dan ','Dan ','Yi ','Sui ','Pi ','Ju ','Ta ','Qin ', + 'Ji ','Zhuo ','Lian ','Nong ','Guo ','Jin ','Fen ','Se ','Ji ','Sui ','Hui ','Chu ','Ta ','Song ','Ding ','', + 'Zhu ','Lai ','Bin ','Lian ','Mi ','Shi ','Shu ','Mi ','Ning ','Ying ','Ying ','Meng ','Jin ','Qi ','Pi ','Ji ', + 'Hao ','Ru ','Zui ','Wo ','Tao ','Yin ','Yin ','Dui ','Ci ','Huo ','Jing ','Lan ','Jun ','Ai ','Pu ','Zhuo ', + 'Wei ','Bin ','Gu ','Qian ','Xing ','Ban ','Kuo ','Fei ','','Boku ','Jian ','Wei ','Luo ','Zan ','Lu ','Li ', + ], + 'x70':[ + 'You ','Yang ','Lu ','Si ','Jie ','Ying ','Du ','Wang ','Hui ','Xie ','Pan ','Shen ','Biao ','Chan ','Mo ','Liu ', + 'Jian ','Pu ','Se ','Cheng ','Gu ','Bin ','Huo ','Xian ','Lu ','Qin ','Han ','Ying ','Yong ','Li ','Jing ','Xiao ', + 'Ying ','Sui ','Wei ','Xie ','Huai ','Hao ','Zhu ','Long ','Lai ','Dui ','Fan ','Hu ','Lai ','','','Ying ', + 'Mi ','Ji ','Lian ','Jian ','Ying ','Fen ','Lin ','Yi ','Jian ','Yue ','Chan ','Dai ','Rang ','Jian ','Lan ','Fan ', + 'Shuang ','Yuan ','Zhuo ','Feng ','She ','Lei ','Lan ','Cong ','Qu ','Yong ','Qian ','Fa ','Guan ','Que ','Yan ','Hao ', + 'Hyeng ','Sa ','Zan ','Luan ','Yan ','Li ','Mi ','Shan ','Tan ','Dang ','Jiao ','Chan ','','Hao ','Ba ','Zhu ', + 'Lan ','Lan ','Nang ','Wan ','Luan ','Xun ','Xian ','Yan ','Gan ','Yan ','Yu ','Huo ','Biao ','Mie ','Guang ','Deng ', + 'Hui ','Xiao ','Xiao ','','Hong ','Ling ','Zao ','Zhuan ','Jiu ','Zha ','Xie ','Chi ','Zhuo ','Zai ','Zai ','Can ', + 'Yang ','Qi ','Zhong ','Fen ','Niu ','Jiong ','Wen ','Po ','Yi ','Lu ','Chui ','Pi ','Kai ','Pan ','Yan ','Kai ', + 'Pang ','Mu ','Chao ','Liao ','Gui ','Kang ','Tun ','Guang ','Xin ','Zhi ','Kwang ','Guang ','Wei ','Qiang ','','Da ', + 'Xia ','Zheng ','Zhu ','Ke ','Zhao ','Fu ','Ba ','Duo ','Duo ','Ling ','Zhuo ','Xuan ','Ju ','Tan ','Pao ','Jiong ', + 'Pao ','Tai ','Tai ','Bing ','Yang ','Tong ','Han ','Zhu ','Zha ','Dian ','Wei ','Shi ','Lian ','Chi ','Huang ','', + 'Hu ','Shuo ','Lan ','Jing ','Jiao ','Xu ','Xing ','Quan ','Lie ','Huan ','Yang ','Xiao ','Xiu ','Xian ','Yin ','Wu ', + 'Zhou ','Yao ','Shi ','Wei ','Tong ','Xue ','Zai ','Kai ','Hong ','Luo ','Xia ','Zhu ','Xuan ','Zheng ','Po ','Yan ', + 'Hui ','Guang ','Zhe ','Hui ','Kao ','','Fan ','Shao ','Ye ','Hui ','','Tang ','Jin ','Re ','','Xi ', + 'Fu ','Jiong ','Che ','Pu ','Jing ','Zhuo ','Ting ','Wan ','Hai ','Peng ','Lang ','Shan ','Hu ','Feng ','Chi ','Rong ', + ], + 'x71':[ + 'Hu ','','Shu ','He ','Xun ','Ku ','Jue ','Xiao ','Xi ','Yan ','Han ','Zhuang ','Jun ','Di ','Xie ','Ji ', + 'Wu ','','Lua ','Han ','Yan ','Huan ','Men ','Ju ','Chou ','Bei ','Fen ','Lin ','Kun ','Hun ','Tun ','Xi ', + 'Cui ','Wu ','Hong ','Ju ','Fu ','Wo ','Jiao ','Cong ','Feng ','Ping ','Qiong ','Ruo ','Xi ','Qiong ','Xin ','Zhuo ', + 'Yan ','Yan ','Yi ','Jue ','Yu ','Gang ','Ran ','Pi ','Gu ','','Sheng ','Chang ','Shao ','','Nam ','Geng ', + 'Wat ','Chen ','He ','Kui ','Zhong ','Duan ','Xia ','Hui ','Feng ','Lian ','Xuan ','Xing ','Huang ','Jiao ','Jian ','Bi ', + 'Ying ','Zhu ','Wei ','Tuan ','Tian ','Xi ','Nuan ','Nuan ','Chan ','Yan ','Jiong ','Jiong ','Yu ','Mei ','Sha ','Wei ', + 'Ye ','Xin ','Qiong ','Rou ','Mei ','Huan ','Xu ','Zhao ','Wei ','Fan ','Qiu ','Sui ','Yang ','Lie ','Zhu ','', + 'Gao ','Gua ','Bao ','Hu ','Yun ','Xia ','','','Bian ','Gou ','Tui ','Tang ','Chao ','Shan ','En ','Bo ', + 'Huang ','Xie ','Xi ','Wu ','Xi ','Yun ','He ','He ','Xi ','Yun ','Xiong ','Nai ','Shan ','','Yao ','Xun ', + 'Mi ','Lian ','Ying ','Wu ','Rong ','Kou ','En ','Qiang ','Liu ','Xi ','Bi ','Biao ','Zong ','Lu ','Jian ','Shu ', + 'Yi ','Lou ','Feng ','Sui ','Yi ','Tong ','Jue ','Zong ','Yun ','Hu ','Yi ','Zhi ','Ao ','Wei ','Liao ','Han ', + 'Ou ','Re ','Jiong ','Man ','','Shang ','Cuan ','Zeng ','Jian ','Xi ','Xi ','Xi ','Yi ','Xiao ','Chi ','Huang ', + 'Chan ','Ye ','Qian ','Ran ','Yan ','Xian ','Qiao ','Zun ','Deng ','Dun ','Shen ','Jiao ','Fen ','Si ','Liao ','Yu ', + 'Lin ','Tong ','Shao ','Fen ','Fan ','Yan ','Xun ','Lan ','Mei ','Tang ','Yi ','Jing ','Men ','','','Ying ', + 'Yu ','Yi ','Xue ','Lan ','Tai ','Zao ','Can ','Sui ','Xi ','Que ','Cong ','Lian ','Hui ','Zhu ','Xie ','Ling ', + 'Wei ','Yi ','Xie ','Zhao ','Hui ','Tatsu ','Nung ','Lan ','Ru ','Xian ','Kao ','Xun ','Jin ','Chou ','Dao ','Yao ', + ], + 'x72':[ + 'He ','Lan ','Biao ','Rong ','Li ','Mo ','Bao ','Ruo ','Lu ','La ','Ao ','Xun ','Kuang ','Shuo ','','Li ', + 'Lu ','Jue ','Liao ','Yan ','Xi ','Xie ','Long ','Ye ','','Rang ','Yue ','Lan ','Cong ','Jue ','Tong ','Guan ', + '','Che ','Mi ','Tang ','Lan ','Zhu ','Laam ','Ling ','Cuan ','Yu ','Zhua ','Zaau ','Pa ','Zheng ','Pao ','Cheng ', + 'Yuan ','Ai ','Wei ','','Jue ','Jue ','Fu ','Ye ','Ba ','Die ','Ye ','Yao ','Zu ','Shuang ','Er ','Qiang ', + 'Chuang ','Ge ','Zang ','Die ','Qiang ','Yong ','Qiang ','Pian ','Ban ','Pan ','Shao ','Jian ','Pai ','Du ','Chuang ','Tou ', + 'Zha ','Bian ','Die ','Bang ','Bo ','Chuang ','You ','','Du ','Ya ','Cheng ','Niu ','Ushihen ','Pin ','Jiu ','Mou ', + 'Tuo ','Mu ','Lao ','Ren ','Mang ','Fang ','Mao ','Mu ','Gang ','Wu ','Yan ','Ge ','Bei ','Si ','Jian ','Gu ', + 'You ','Ge ','Sheng ','Mu ','Di ','Qian ','Quan ','Quan ','Zi ','Te ','Xi ','Mang ','Keng ','Qian ','Wu ','Gu ', + 'Xi ','Li ','Li ','Pou ','Ji ','Gang ','Zhi ','Ben ','Quan ','Run ','Du ','Ju ','Jia ','Jian ','Feng ','Pian ', + 'Ke ','Ju ','Kao ','Chu ','Xi ','Bei ','Luo ','Jie ','Ma ','San ','Wei ','Li ','Dun ','Tong ','','Jiang ', + 'Gi ','Li ','Du ','Lie ','Pi ','Piao ','Bao ','Xi ','Chou ','Wei ','Kui ','Chou ','Quan ','Hyun ','Ba ','Fan ', + 'Qiu ','Ji ','Cai ','Chuo ','An ','Ge ','Zhuang ','Guang ','Ma ','You ','Kang ','Bo ','Hou ','Ya ','Yin ','Huan ', + 'Zhuang ','Yun ','Kuang ','Niu ','Di ','Qing ','Zhong ','Mu ','Bei ','Pi ','Ju ','Ni ','Sheng ','Pao ','Xia ','Tuo ', + 'Hu ','Ling ','Fei ','Pi ','Ni ','Ao ','You ','Gou ','Yue ','Ju ','Dan ','Po ','Gu ','Xian ','Ning ','Huan ', + 'Hen ','Jiao ','He ','Zhao ','Ji ','Xun ','Shan ','Ta ','Rong ','Shou ','Tong ','Lao ','Du ','Xia ','Shi ','Hua ', + 'Zheng ','Yu ','Sun ','Yu ','Bi ','Mang ','Xi ','Juan ','Li ','Xia ','Yin ','Suan ','Lang ','Bei ','Zhi ','Yan ', + ], + 'x73':[ + 'Sha ','Li ','Han ','Xian ','Jing ','Pai ','Fei ','Yao ','Ba ','Qi ','Ni ','Biao ','Yin ','Lai ','Xi ','Jian ', + 'Qiang ','Kun ','Yan ','Guo ','Zong ','Mi ','Chang ','Yi ','Zhi ','Zheng ','Ya ','Meng ','Cai ','Cu ','She ','Ryou ', + 'Cen ','Luo ','Hu ','Zong ','Ji ','Wei ','Feng ','Wo ','Yuan ','Xing ','Zhu ','Mao ','Wei ','Yuan ','Xian ','Tuan ', + 'Ya ','Nao ','Xie ','Jia ','Hou ','Bian ','You ','You ','Mei ','Zha ','Yao ','Sun ','Bo ','Ming ','Hua ','Yuan ', + 'Sou ','Ma ','Yuan ','Dai ','Yu ','Shi ','Hao ','','Yi ','Zhen ','Chuang ','Hao ','Man ','Jing ','Jiang ','Mu ', + 'Zhang ','Chan ','Ao ','Ao ','Hao ','Cui ','Fen ','Jue ','Bi ','Bi ','Huang ','Pu ','Lin ','Yu ','Tong ','Yao ', + 'Liao ','Shuo ','Xiao ','Swu ','Ton ','Xi ','Ge ','Juan ','Du ','Hui ','Kuai ','Xian ','Xie ','Ta ','Xian ','Xun ', + 'Ning ','Pin ','Huo ','Nou ','Meng ','Lie ','Nao ','Guang ','Shou ','Lu ','Ta ','Xian ','Mi ','Rang ','Huan ','Nao ', + 'Luo ','Xian ','Qi ','Jue ','Xuan ','Miao ','Zi ','Lu ','Lu ','Yu ','Su ','Wang ','Qiu ','Ga ','Ding ','Le ', + 'Ba ','Ji ','Hong ','Di ','Chuan ','Gan ','Jiu ','Yu ','Ji ','Yu ','Yang ','Ma ','Gong ','Wu ','Fu ','Min ', + 'Jie ','Ya ','Bin ','Bian ','Bang ','Yue ','Jue ','Yun ','Jue ','Wan ','Jian ','Mei ','Dan ','Pi ','Wei ','Huan ', + 'Xian ','Qiang ','Ling ','Dai ','Yi ','An ','Ping ','Dian ','Fu ','Xuan ','Xi ','Bo ','Ci ','Gou ','Jia ','Shao ', + 'Po ','Ci ','Ke ','Ran ','Sheng ','Shen ','Yi ','Zu ','Jia ','Min ','Shan ','Liu ','Bi ','Zhen ','Zhen ','Jue ', + 'Fa ','Long ','Jin ','Jiao ','Jian ','Li ','Guang ','Xian ','Zhou ','Gong ','Yan ','Xiu ','Yang ','Xu ','Luo ','Su ', + 'Zhu ','Qin ','Ken ','Xun ','Bao ','Er ','Xiang ','Yao ','Xia ','Heng ','Gui ','Chong ','Xu ','Ban ','Pei ','', + 'Dang ','Ei ','Hun ','Wen ','E ','Cheng ','Di ','Wu ','Wu ','Cheng ','Jun ','Mei ','Bei ','Ting ','Xian ','Chuo ', + ], + 'x74':[ + 'Han ','Xuan ','Yan ','Qiu ','Quan ','Lang ','Li ','Xiu ','Fu ','Liu ','Ye ','Xi ','Ling ','Li ','Jin ','Lian ', + 'Suo ','Sa ','','Wan ','Dian ','Pin ','Zhan ','Cui ','Min ','Yu ','Ju ','Chen ','Lai ','Wen ','Sheng ','Wei ', + 'Dian ','Chu ','Zhuo ','Pei ','Cheng ','Hu ','Qi ','E ','Kun ','Chang ','Qi ','Beng ','Wan ','Lu ','Cong ','Guan ', + 'Yan ','Diao ','Bei ','Lin ','Qin ','Pi ','Pa ','Que ','Zhuo ','Qin ','Fa ','','Qiong ','Du ','Jie ','Hun ', + 'Yu ','Mao ','Mei ','Chwun ','Xuan ','Ti ','Xing ','Dai ','Rou ','Min ','Zhen ','Wei ','Ruan ','Huan ','Jie ','Chuan ', + 'Jian ','Zhuan ','Yang ','Lian ','Quan ','Xia ','Duan ','Yuan ','Ye ','Nao ','Hu ','Ying ','Yu ','Huang ','Rui ','Se ', + 'Liu ','','Rong ','Suo ','Yao ','Wen ','Wu ','Jin ','Jin ','Ying ','Ma ','Tao ','Liu ','Tang ','Li ','Lang ', + 'Gui ','Tian ','Qiang ','Cuo ','Jue ','Zhao ','Yao ','Ai ','Bin ','Tu ','Chang ','Kun ','Zhuan ','Cong ','Jin ','Yi ', + 'Cui ','Cong ','Qi ','Li ','Ying ','Suo ','Qiu ','Xuan ','Ao ','Lian ','Men ','Zhang ','Yin ','','Ying ','Zhi ', + 'Lu ','Wu ','Deng ','xiu ','Zeng ','Xun ','Qu ','Dang ','Lin ','Liao ','Qiong ','Su ','Huang ','Gui ','Pu ','Jing ', + 'Fan ','Jin ','Liu ','Ji ','','Jing ','Ai ','Bi ','Can ','Qu ','Zao ','Dang ','Jiao ','Gun ','Tan ','Hui ', + 'Huan ','Se ','Sui ','Tian ','','Yu ','Jin ','Lu ','Bin ','Shou ','Wen ','Zui ','Lan ','Xi ','Ji ','Xuan ', + 'Ruan ','Huo ','Gai ','Lei ','Du ','Li ','Zhi ','Rou ','Li ','Zan ','Qiong ','Zhe ','Gui ','Sui ','La ','Long ', + 'Lu ','Li ','Zan ','Lan ','Ying ','Mi ','Xiang ','Xi ','Guan ','Dao ','Zan ','Huan ','Gua ','Bo ','Die ','Bao ', + 'Hu ','Zhi ','Piao ','Ban ','Rang ','Li ','Wa ','Dekaguramu ','Jiang ','Cin ','Fan ','Pen ','Fang ','Dan ','Weng ','Ou ', + 'Deshiguramu ','Miriguramu ','Thon ','Hu ','Ling ','Yi ','Ping ','Ci ','Hekutogura ','Juan ','Chang ','Chi ','Sarake ','Dang ','Meng ','Pou ', + ], + 'x75':[ + 'Zhui ','Ping ','Bian ','Zhou ','Zhen ','Senchigura ','Ci ','Ying ','Qi ','Xian ','Lou ','Di ','Ou ','Meng ','Zhuan ','Peng ', + 'Lin ','Zeng ','Wu ','Pi ','Dan ','Weng ','Ying ','Yan ','Gan ','Dai ','Shen ','Tian ','Tian ','Han ','Chang ','Sheng ', + 'Qing ','Shen ','Chan ','Chan ','Rui ','Sheng ','Su ','Sen ','Yong ','Shuai ','Lu ','Fu ','Yong ','Beng ','Feng ','Ning ', + 'Tian ','You ','Jia ','Shen ','Zha ','Dian ','Fu ','Nan ','Dian ','Ping ','Ting ','Hua ','Ting ','Quan ','Zi ','Meng ', + 'Bi ','Qi ','Liu ','Xun ','Liu ','Chang ','Mu ','Yun ','Fan ','Fu ','Geng ','Tian ','Jie ','Jie ','Quan ','Wei ', + 'Fu ','Tian ','Mu ','Tap ','Pan ','Jiang ','Wa ','Da ','Nan ','Liu ','Ben ','Zhen ','Chu ','Mu ','Mu ','Ce ', + 'Cen ','Gai ','Bi ','Da ','Zhi ','Lue ','Qi ','Lue ','Pan ','Kesa ','Fan ','Hua ','Yu ','Yu ','Mu ','Jun ', + 'Yi ','Liu ','Yu ','Die ','Chou ','Hua ','Dang ','Chuo ','Ji ','Wan ','Jiang ','Sheng ','Chang ','Tuan ','Lei ','Ji ', + 'Cha ','Liu ','Jou ','Tuan ','Lin ','Jiang ','Jiang ','Chou ','Bo ','Die ','Die ','Pi ','Nie ','Dan ','Shu ','Shu ', + 'Zhi ','Yi ','Chuang ','Nai ','Ding ','Bi ','Jie ','Liao ','Gang ','Ge ','Jiu ','Zhou ','Xia ','Shan ','Xu ','Nue ', + 'Li ','Yang ','Chen ','You ','Ba ','Jie ','Jue ','Zhi ','Xia ','Cui ','Bi ','Yi ','Li ','Zong ','Chuang ','Feng ', + 'Zhu ','Pao ','Pi ','Gan ','Ke ','Ci ','Xie ','Qi ','Dan ','Zhen ','Fa ','Zhi ','Teng ','Ju ','Ji ','Fei ', + 'Qu ','Dian ','Jia ','Xian ','Zha ','Bing ','Ni ','Zheng ','Yong ','Jing ','Quan ','Chong ','Tong ','Yi ','Kai ','Wei ', + 'Hui ','Duo ','Yang ','Chi ','Zhi ','Hen ','Ya ','Mei ','Dou ','Jing ','Xiao ','Tong ','Tu ','Mang ','Pi ','Xiao ', + 'Suan ','Pu ','Li ','Zhi ','Cuo ','Duo ','Wu ','Sha ','Lao ','Shou ','Huan ','Xian ','Yi ','Peng ','Zhang ','Guan ', + 'Tan ','Fei ','Ma ','Lin ','Chi ','Ji ','Dian ','An ','Chi ','Bi ','Bi ','Min ','Gu ','Dui ','E ','Wei ', + ], + 'x76':[ + 'Yu ','Cui ','Ya ','Zhu ','Cu ','Dan ','Shen ','Zhong ','Ji ','Yu ','Hou ','Feng ','La ','Yang ','Shen ','Tu ', + 'Yu ','Gua ','Wen ','Huan ','Ku ','Jia ','Yin ','Yi ','Lu ','Sao ','Jue ','Chi ','Xi ','Guan ','Yi ','Wen ', + 'Ji ','Chuang ','Ban ','Lei ','Liu ','Chai ','Shou ','Nue ','Dian ','Da ','Pie ','Tan ','Zhang ','Biao ','Shen ','Cu ', + 'Luo ','Yi ','Zong ','Chou ','Zhang ','Zhai ','Sou ','Suo ','Que ','Diao ','Lou ','Lu ','Mo ','Jin ','Yin ','Ying ', + 'Huang ','Fu ','Liao ','Long ','Qiao ','Liu ','Lao ','Xian ','Fei ','Dan ','Yin ','He ','Ai ','Ban ','Xian ','Guan ', + 'Guai ','Nong ','Yu ','Wei ','Yi ','Yong ','Pi ','Lei ','Li ','Shu ','Dan ','Lin ','Dian ','Lin ','Lai ','Bie ', + 'Ji ','Chi ','Yang ','Xian ','Jie ','Zheng ','Mak6','Li ','Huo ','Lai ','Zik ','Dian ','Xuan ','Ying ','Yin ','Qu ', + 'Yong ','Tan ','Dian ','Luo ','Luan ','Luan ','Bo ','','Gui ','Po ','Fa ','Deng ','Fa ','Bai ','Bai ','Qie ', + 'Bi ','Zao ','Zao ','Mao ','De ','Pa ','Jie ','Huang ','Gui ','Ci ','Ling ','Gao ','Mo ','Ji ','Jiao ','Peng ', + 'Gao ','Ai ','E ','Hao ','Han ','Bi ','Wan ','Chou ','Qian ','Xi ','Ai ','Jiong ','Hao ','Huang ','Hao ','Ze ', + 'Cui ','Hao ','Xiao ','Ye ','Po ','Hao ','Jiao ','Ai ','Xing ','Huang ','Li ','Piao ','He ','Jiao ','Pi ','Gan ', + 'Pao ','Zhou ','Jun ','Qiu ','Cun ','Que ','Zha ','Gu ','Jun ','Jun ','Zhou ','Zha ','Gu ','Zhan ','Du ','Min ', + 'Qi ','Ying ','Yu ','Bei ','Zhao ','Zhong ','Pen ','He ','Ying ','He ','Yi ','Bo ','Wan ','He ','Ang ','Zhan ', + 'Yan ','Jian ','He ','Yu ','Kui ','Fan ','Gai ','Dao ','Pan ','Fu ','Qiu ','Sheng ','Dao ','Lu ','Zhan ','Meng ', + 'Li ','Jin ','Xu ','Jian ','Pan ','Guan ','An ','Lu ','Shu ','Zhou ','Dang ','An ','Gu ','Li ','Mu ','Ding ', + 'Gan ','Xu ','Mang ','Mang ','Zhi ','Qi ','Ruan ','Tian ','Xiang ','Dun ','Xin ','Xi ','Pan ','Feng ','Dun ','Min ', + ], + 'x77':[ + 'Ming ','Sheng ','Shi ','Yun ','Mian ','Pan ','Fang ','Miao ','Dan ','Mei ','Mao ','Kan ','Xian ','Ou ','Shi ','Yang ', + 'Zheng ','Yao ','Shen ','Huo ','Da ','Zhen ','Kuang ','Ju ','Shen ','Chi ','Sheng ','Mei ','Mo ','Zhu ','Zhen ','Zhen ', + 'Mian ','Di ','Yuan ','Die ','Yi ','Zi ','Zi ','Chao ','Zha ','Xuan ','Bing ','Mi ','Long ','Sui ','Dong ','Mi ', + 'Die ','Yi ','Er ','Ming ','Xuan ','Chi ','Kuang ','Juan ','Mou ','Zhen ','Tiao ','Yang ','Yan ','Mo ','Zhong ','Mai ', + 'Zhao ','Zheng ','Mei ','Jun ','Shao ','Han ','Huan ','Di ','Cheng ','Cuo ','Juan ','E ','Wan ','Xian ','Xi ','Kun ', + 'Lai ','Jian ','Shan ','Tian ','Hun ','Wan ','Ling ','Shi ','Qiong ','Lie ','Yai ','Jing ','Zheng ','Li ','Lai ','Sui ', + 'Juan ','Shui ','Sui ','Du ','Bi ','Bi ','Mu ','Hun ','Ni ','Lu ','Yi ','Jie ','Cai ','Zhou ','Yu ','Hun ', + 'Ma ','Xia ','Xing ','Xi ','Gun ','','Chun ','Jian ','Mei ','Du ','Hou ','Xuan ','Ti ','Kui ','Gao ','Rui ', + 'Mao ','Xu ','Fa ','Wen ','Miao ','Chou ','Kui ','Mi ','Weng ','Kou ','Dang ','Chen ','Ke ','Sou ','Xia ','Qiong ', + 'Mao ','Ming ','Man ','Shui ','Ze ','Zhang ','Yi ','Diao ','Ou ','Mo ','Shun ','Cong ','Lou ','Chi ','Man ','Piao ', + 'Cheng ','Ji ','Meng ','','Run ','Pie ','Xi ','Qiao ','Pu ','Zhu ','Deng ','Shen ','Shun ','Liao ','Che ','Xian ', + 'Kan ','Ye ','Xu ','Tong ','Mou ','Lin ','Kui ','Xian ','Ye ','Ai ','Hui ','Zhan ','Jian ','Gu ','Zhao ','Ju ', + 'Wei ','Chou ','Sao ','Ning ','Xun ','Yao ','Huo ','Meng ','Mian ','Bin ','Mian ','Li ','Kuang ','Jue ','Xuan ','Mian ', + 'Huo ','Lu ','Meng ','Long ','Guan ','Man ','Xi ','Chu ','Tang ','Kan ','Zhu ','Mao ','Jin ','Lin ','Yu ','Shuo ', + 'Ce ','Jue ','Shi ','Yi ','Shen ','Zhi ','Hou ','Shen ','Ying ','Ju ','Zhou ','Jiao ','Cuo ','Duan ','Ai ','Jiao ', + 'Zeng ','Huo ','Bai ','Shi ','Ding ','Qi ','Ji ','Zi ','Gan ','Wu ','Tuo ','Ku ','Qiang ','Xi ','Fan ','Kuang ', + ], + 'x78':[ + 'Dang ','Ma ','Sha ','Dan ','Jue ','Li ','Fu ','Min ','Nuo ','Huo ','Kang ','Zhi ','Qi ','Kan ','Jie ','Fen ', + 'E ','Ya ','Pi ','Zhe ','Yan ','Sui ','Zhuan ','Che ','Dun ','Pan ','Yan ','','Feng ','Fa ','Mo ','Zha ', + 'Qu ','Yu ','Luo ','Tuo ','Tuo ','Di ','Zhai ','Zhen ','Ai ','Fei ','Mu ','Zhu ','Li ','Bian ','Nu ','Ping ', + 'Peng ','Ling ','Pao ','Le ','Po ','Bo ','Po ','Shen ','Za ','Nuo ','Li ','Long ','Tong ','','Li ','Kou ', + 'Chu ','Keng ','Quan ','Zhu ','Kuang ','Gui ','E ','Nao ','Jia ','Lu ','Wei ','Ai ','Luo ','Ken ','Xing ','Yan ', + 'Tong ','Peng ','Xi ','','Hong ','Shuo ','Xia ','Qiao ','','Wei ','Qiao ','','Keng ','Xiao ','Que ','Chan ', + 'Lang ','Hong ','Yu ','Xiao ','Xia ','Mang ','Long ','Yong ','Che ','Che ','E ','Liu ','Ying ','Mang ','Que ','Yan ', + 'Sha ','Kun ','Yu ','','Kaki ','Lu ','Chen ','Jian ','Nue ','Song ','Zhuo ','Keng ','Peng ','Yan ','Zhui ','Kong ', + 'Ceng ','Qi ','Zong ','Qing ','Lin ','Jun ','Bo ','Ding ','Min ','Diao ','Jian ','He ','Lu ','Ai ','Sui ','Que ', + 'Ling ','Bei ','Yin ','Dui ','Wu ','Qi ','Lun ','Wan ','Dian ','Gang ','Bei ','Qi ','Chen ','Ruan ','Yan ','Die ', + 'Ding ','Du ','Tuo ','Jie ','Ying ','Bian ','Ke ','Bi ','Wei ','Shuo ','Zhen ','Duan ','Xia ','Dang ','Ti ','Nao ', + 'Peng ','Jian ','Di ','Tan ','Cha ','Seki ','Qi ','','Feng ','Xuan ','Que ','Que ','Ma ','Gong ','Nian ','Su ', + 'E ','Ci ','Liu ','Si ','Tang ','Bang ','Hua ','Pi ','Wei ','Sang ','Lei ','Cuo ','Zhen ','Xia ','Qi ','Lian ', + 'Pan ','Wei ','Yun ','Dui ','Zhe ','Ke ','La ','','Qing ','Gun ','Zhuan ','Chan ','Qi ','Ao ','Peng ','Lu ', + 'Lu ','Kan ','Qiang ','Chen ','Yin ','Lei ','Biao ','Qi ','Mo ','Qi ','Cui ','Zong ','Qing ','Chuo ','','Ji ', + 'Shan ','Lao ','Qu ','Zeng ','Deng ','Jian ','Xi ','Lin ','Ding ','Dian ','Huang ','Pan ','Za ','Qiao ','Di ','Li ', + ], + 'x79':[ + 'Kan ','Jiao ','','Zhang ','Qiao ','Dun ','Xian ','Yu ','Zhui ','He ','Huo ','Zhai ','Lei ','Ke ','Chu ','Ji ', + 'Que ','Dang ','Yi ','Jiang ','Pi ','Pi ','Yu ','Pin ','Qi ','Ai ','Kai ','Jian ','Yu ','Ruan ','Meng ','Pao ', + 'Ci ','Bo ','','Mie ','Ca ','Xian ','Kuang ','Lei ','Lei ','Zhi ','Li ','Li ','Fan ','Que ','Pao ','Ying ', + 'Li ','Long ','Long ','Mo ','Bo ','Shuang ','Guan ','Lan ','Zan ','Yan ','Shi ','Shi ','Li ','Reng ','She ','Yue ', + 'Si ','Qi ','Ta ','Ma ','Xie ','Yao ','Xian ','Qi ','Qi ','Zhi ','Beng ','Dui ','Zhong ','','Yi ','Shi ', + 'You ','Zhi ','Tiao ','Fu ','Fu ','Mi ','Zu ','Zhi ','Suan ','Mei ','Zuo ','Qu ','Hu ','Zhu ','Shen ','Sui ', + 'Ci ','Chai ','Mi ','Lu ','Yu ','Xiang ','Wu ','Tiao ','Piao ','Zhu ','Gui ','Xia ','Zhi ','Ji ','Gao ','Zhen ', + 'Gao ','Shui ','Jin ','Chen ','Gai ','Kun ','Di ','Dao ','Huo ','Tao ','Qi ','Gu ','Guan ','Zui ','Ling ','Lu ', + 'Bing ','Jin ','Dao ','Zhi ','Lu ','Shan ','Bei ','Zhe ','Hui ','You ','Xi ','Yin ','Zi ','Huo ','Zhen ','Fu ', + 'Yuan ','Wu ','Xian ','Yang ','Ti ','Yi ','Mei ','Si ','Di ','','Zhuo ','Zhen ','Yong ','Ji ','Gao ','Tang ', + 'Si ','Ma ','Ta ','','Xuan ','Qi ','Yu ','Xi ','Ji ','Si ','Chan ','Tan ','Kuai ','Sui ','Li ','Nong ', + 'Ni ','Dao ','Li ','Rang ','Yue ','Ti ','Zan ','Lei ','Rou ','Yu ','Yu ','Li ','Xie ','Qin ','He ','Tu ', + 'Xiu ','Si ','Ren ','Tu ','Zi ','Cha ','Gan ','Yi ','Xian ','Bing ','Nian ','Qiu ','Qiu ','Zhong ','Fen ','Hao ', + 'Yun ','Ke ','Miao ','Zhi ','Geng ','Bi ','Zhi ','Yu ','Mi ','Ku ','Ban ','Pi ','Ni ','Li ','You ','Zu ', + 'Pi ','Ba ','Ling ','Mo ','Cheng ','Nian ','Qin ','Yang ','Zuo ','Zhi ','Zhi ','Shu ','Ju ','Zi ','Huo ','Ji ', + 'Cheng ','Tong ','Zhi ','Huo ','He ','Yin ','Zi ','Zhi ','Jie ','Ren ','Du ','Yi ','Zhu ','Hui ','Nong ','Fu ', + ], + 'x7a':[ + 'Xi ','Kao ','Lang ','Fu ','Ze ','Shui ','Lu ','Kun ','Gan ','Geng ','Ti ','Cheng ','Tu ','Shao ','Shui ','Ya ', + 'Lun ','Lu ','Gu ','Zuo ','Ren ','Zhun ','Bang ','Bai ','Ji ','Zhi ','Zhi ','Kun ','Leng ','Peng ','Ke ','Bing ', + 'Chou ','Zu ','Yu ','Su ','Lue ','','Yi ','Xi ','Bian ','Ji ','Fu ','Bi ','Nuo ','Jie ','Zhong ','Zong ', + 'Xu ','Cheng ','Dao ','Wen ','Lian ','Zi ','Yu ','Ji ','Xu ','Zhen ','Zhi ','Dao ','Jia ','Ji ','Gao ','Gao ', + 'Gu ','Rong ','Sui ','You ','Ji ','Kang ','Mu ','Shan ','Men ','Zhi ','Ji ','Lu ','Su ','Ji ','Ying ','Wen ', + 'Qiu ','Se ','','Yi ','Huang ','Qie ','Ji ','Sui ','Xiao ','Pu ','Jiao ','Zhuo ','Tong ','Sai ','Lu ','Sui ', + 'Nong ','Se ','Hui ','Rang ','Nuo ','Yu ','','Ji ','Tui ','Wen ','Cheng ','Huo ','Gong ','Lu ','Biao ','', + 'Rang ','Zhuo ','Li ','Zan ','Xue ','Wa ','Jiu ','Qiong ','Xi ','Qiong ','Kong ','Yu ','Sen ','Jing ','Yao ','Chuan ', + 'Zhun ','Tu ','Lao ','Qie ','Zhai ','Yao ','Bian ','Bao ','Yao ','Bing ','Wa ','Zhu ','Jiao ','Qiao ','Diao ','Wu ', + 'Gui ','Yao ','Zhi ','Chuang ','Yao ','Tiao ','Jiao ','Chuang ','Jiong ','Xiao ','Cheng ','Kou ','Cuan ','Wo ','Dan ','Ku ', + 'Ke ','Zhui ','Xu ','Su ','','Kui ','Dou ','','Yin ','Wo ','Wa ','Ya ','Yu ','Ju ','Qiong ','Yao ', + 'Yao ','Tiao ','Chao ','Yu ','Tian ','Diao ','Ju ','Liao ','Xi ','Wu ','Kui ','Chuang ','Zhao ','Fun ','Kuan ','Long ', + 'Cheng ','Cui ','Piao ','Zao ','Cuan ','Qiao ','Qiong ','Dou ','Zao ','Long ','Qie ','Li ','Chu ','Dekaritto ','Fou ','Kirorittoru ', + 'Chu ','Hong ','Qi ','Miririttoru ','','Deshiritto ','Shu ','Miao ','Ju ','Zhan ','Zhu ','Ling ','Long ','Bing ','Jing ','Jing ', + 'Zhang ','Hekutoritto ','Si ','Jun ','Hong ','Tong ','Song ','Jing ','Diao ','Yi ','Shu ','Jing ','Qu ','Jie ','Ping ','Duan ', + 'Shao ','Zhuan ','Ceng ','Deng ','Cui ','Huai ','Jing ','Kan ','Jing ','Zhu ','Zhu ','Le ','Peng ','Yu ','Chi ','Gan ', + ], + 'x7b':[ + 'Mang ','Zhu ','Utsubo ','Du ','Ji ','Xiao ','Ba ','Suan ','Ji ','Zhen ','Zhao ','Sun ','Ya ','Zhui ','Yuan ','Hu ', + 'Gang ','Xiao ','Cen ','Pi ','Bi ','Jian ','Yi ','Dong ','Shan ','Sheng ','Xia ','Di ','Zhu ','Na ','Chi ','Gu ', + 'Li ','Qie ','Min ','Bao ','Tiao ','Si ','Fu ','Ce ','Ben ','Pei ','Da ','Zi ','Di ','Ling ','Ze ','Nu ', + 'Fu ','Gou ','Fan ','Jia ','Ge ','Fan ','Shi ','Mao ','Po ','Sey ','Jian ','Qiong ','Long ','Souke ','Bian ','Luo ', + 'Gui ','Qu ','Chi ','Yin ','Yao ','Xian ','Bi ','Qiong ','Gua ','Deng ','Jiao ','Jin ','Quan ','Sun ','Ru ','Fa ', + 'Kuang ','Zhu ','Tong ','Ji ','Da ','Xing ','Ce ','Zhong ','Kou ','Lai ','Bi ','Shai ','Dang ','Zheng ','Ce ','Fu ', + 'Yun ','Tu ','Pa ','Li ','Lang ','Ju ','Guan ','Jian ','Han ','Tong ','Xia ','Zhi ','Cheng ','Suan ','Shi ','Zhu ', + 'Zuo ','Xiao ','Shao ','Ting ','Ce ','Yan ','Gao ','Kuai ','Gan ','Chou ','Kyou ','Gang ','Yun ','O ','Qian ','Xiao ', + 'Jian ','Pu ','Lai ','Zou ','Bi ','Bi ','Bi ','Ge ','Chi ','Guai ','Yu ','Jian ','Zhao ','Gu ','Chi ','Zheng ', + 'Jing ','Sha ','Zhou ','Lu ','Bo ','Ji ','Lin ','Suan ','Jun ','Fu ','Zha ','Gu ','Kong ','Qian ','Quan ','Jun ', + 'Chui ','Guan ','Yuan ','Ce ','Ju ','Bo ','Ze ','Qie ','Tuo ','Luo ','Dan ','Xiao ','Ruo ','Jian ','','Bian ', + 'Sun ','Xiang ','Xian ','Ping ','Zhen ','Sheng ','Hu ','Shi ','Zhu ','Yue ','Chun ','Lu ','Wu ','Dong ','Shuo ','Ji ', + 'Jie ','Huang ','Xing ','Mei ','Fan ','Chui ','Zhuan ','Pian ','Feng ','Zhu ','Hong ','Qie ','Hou ','Qiu ','Miao ','Qian ', + '','Kui ','Sik ','Lou ','Yun ','He ','Tang ','Yue ','Chou ','Gao ','Fei ','Ruo ','Zheng ','Gou ','Nie ','Qian ', + 'Xiao ','Cuan ','Gong ','Pang ','Du ','Li ','Bi ','Zhuo ','Chu ','Shai ','Chi ','Zhu ','Qiang ','Long ','Lan ','Jian ', + 'Bu ','Li ','Hui ','Bi ','Di ','Cong ','Yan ','Peng ','Sen ','Zhuan ','Pai ','Piao ','Dou ','Yu ','Mie ','Zhuan ', + ], + 'x7c':[ + 'Ze ','Xi ','Guo ','Yi ','Hu ','Chan ','Kou ','Cu ','Ping ','Chou ','Ji ','Gui ','Su ','Lou ','Zha ','Lu ', + 'Nian ','Suo ','Cuan ','Sen ','Suo ','Le ','Duan ','Yana ','Xiao ','Bo ','Mi ','Si ','Dang ','Liao ','Dan ','Dian ', + 'Fu ','Jian ','Min ','Kui ','Dai ','Jiao ','Deng ','Huang ','Sun ','Lao ','Zan ','Xiao ','Lu ','Shi ','Zan ','', + 'Pai ','Hata ','Pai ','Gan ','Ju ','Du ','Lu ','Yan ','Bo ','Dang ','Sai ','Ke ','Long ','Qian ','Lian ','Bu ', + 'Zhou ','Lai ','','Lan ','Kui ','Yu ','Yue ','Hao ','Zhen ','Tai ','Ti ','Mi ','Chou ','Ji ','','Hata ', + 'Teng ','Zhuan ','Zhou ','Fan ','Sou ','Zhou ','Sen ','Zhuo ','Teng ','Lu ','Lu ','Jian ','Tuo ','Ying ','Yu ','Lai ', + 'Long ','Shinshi ','Lian ','Lan ','Qian ','Yue ','Zhong ','Qu ','Lian ','Bian ','Duan ','Zuan ','Li ','Si ','Luo ','Ying ', + 'Yue ','Zhuo ','Yu ','Mi ','Di ','Fan ','Shen ','Zhe ','Shen ','Nu ','Xie ','Lei ','Xian ','Zi ','Ni ','Cun ', + '','Qian ','Kume ','Bi ','Ban ','Wu ','Sha ','Kang ','Rou ','Fen ','Bi ','Cui ','','Li ','Chi ','Ta ', + 'Ro ','Ba ','Li ','Gan ','Ju ','Po ','Mo ','Cu ','Nian ','Zhou ','Li ','Su ','Tiao ','Li ','Xi ','Su ', + 'Hong ','Tong ','Zi ','Ce ','Yue ','Zhou ','Lin ','Zhuang ','Bai ','','Fen ','Ji ','','Sukumo ','Liang ','Xian ', + 'Fu ','Liang ','Can ','Geng ','Li ','Yue ','Lu ','Ju ','Qi ','Cui ','Bai ','Zhang ','Lin ','Zong ','Jing ','Guo ', + 'Kouji ','San ','San ','Tang ','Bian ','Rou ','Mian ','Hou ','Xu ','Zong ','Hu ','Jian ','Zan ','Ci ','Li ','Xie ', + 'Fu ','Ni ','Bei ','Gu ','Xiu ','Gao ','Tang ','Qiu ','Sukumo ','Cao ','Zhuang ','Tang ','Mi ','San ','Fen ','Zao ', + 'Kang ','Jiang ','Mo ','San ','San ','Nuo ','Xi ','Liang ','Jiang ','Kuai ','Bo ','Huan ','','Zong ','Xian ','Nuo ', + 'Tuan ','Nie ','Li ','Zuo ','Di ','Nie ','Tiao ','Lan ','Mi ','Si ','Jiu ','Xi ','Gong ','Zheng ','Jiu ','You ', + ], + 'x7d':[ + 'Ji ','Cha ','Zhou ','Xun ','Yue ','Hong ','Yu ','He ','Wan ','Ren ','Wen ','Wen ','Qiu ','Na ','Zi ','Tou ', + 'Niu ','Fou ','Jie ','Shu ','Chun ','Pi ','Yin ','Sha ','Hong ','Zhi ','Ji ','Fen ','Yun ','Ren ','Dan ','Jin ', + 'Su ','Fang ','Suo ','Cui ','Jiu ','Zha ','Ha ','Jin ','Fu ','Zhi ','Ci ','Zi ','Chou ','Hong ','Za ','Lei ', + 'Xi ','Fu ','Xie ','Shen ','Bei ','Zhu ','Qu ','Ling ','Zhu ','Shao ','Gan ','Yang ','Fu ','Tuo ','Zhen ','Dai ', + 'Chu ','Shi ','Zhong ','Xian ','Zu ','Jiong ','Ban ','Ju ','Mo ','Shu ','Zui ','Kou ','Jing ','Ren ','Heng ','Xie ', + 'Jie ','Zhu ','Chou ','Gua ','Bai ','Jue ','Kuang ','Hu ','Ci ','Geng ','Geng ','Tao ','Xie ','Ku ','Jiao ','Quan ', + 'Gai ','Luo ','Xuan ','Bing ','Xian ','Fu ','Gei ','Tong ','Rong ','Tiao ','Yin ','Lei ','Xie ','Quan ','Xu ','Gai ', + 'Die ','Tong ','Si ','Jiang ','Xiang ','Hui ','Jue ','Zhi ','Jian ','Juan ','Chi ','Mian ','Zhen ','Lu ','Cheng ','Qiu ', + 'Shu ','Bang ','Tong ','Xiao ','Wan ','Qin ','Geng ','Xiu ','Ti ','Xiu ','Xie ','Hong ','Xi ','Fu ','Ting ','Sui ', + 'Dui ','Kun ','Fu ','Jing ','Hu ','Zhi ','Yan ','Jiong ','Feng ','Ji ','Sok ','Kase ','Zong ','Lin ','Duo ','Li ', + 'Lu ','Liang ','Chou ','Quan ','Shao ','Qi ','Qi ','Zhun ','Qi ','Wan ','Qian ','Xian ','Shou ','Wei ','Qi ','Tao ', + 'Wan ','Gang ','Wang ','Beng ','Zhui ','Cai ','Guo ','Cui ','Lun ','Liu ','Qi ','Zhan ','Bei ','Chuo ','Ling ','Mian ', + 'Qi ','Qie ','Tan ','Zong ','Gun ','Zou ','Yi ','Zi ','Xing ','Liang ','Jin ','Fei ','Rui ','Min ','Yu ','Zong ', + 'Fan ','Lu ','Xu ','Ying ','Zhang ','Kasuri ','Xu ','Xiang ','Jian ','Ke ','Xian ','Ruan ','Mian ','Ji ','Duan ','Zhong ', + 'Di ','Min ','Miao ','Yuan ','Xie ','Bao ','Si ','Qiu ','Bian ','Huan ','Geng ','Cong ','Mian ','Wei ','Fu ','Wei ', + 'Yu ','Gou ','Miao ','Xie ','Lian ','Zong ','Bian ','Yun ','Yin ','Ti ','Gua ','Zhi ','Yun ','Cheng ','Chan ','Dai ', + ], + 'x7e':[ + 'Xia ','Yuan ','Zong ','Xu ','Jou ','Odoshi ','Geng ','Sen ','Ying ','Jin ','Yi ','Zhui ','Ni ','Bang ','Gu ','Pan ', + 'Zhou ','Jian ','Cuo ','Quan ','Shuang ','Yun ','Xia ','Cui ','Xi ','Rong ','Tao ','Fu ','Yun ','Chen ','Gao ','Ru ', + 'Hu ','Zai ','Teng ','Xian ','Su ','Zhen ','Zong ','Tao ','Kou ','Cai ','Bi ','Feng ','Cu ','Li ','Suo ','Yin ', + 'Xi ','Zong ','Lei ','Zhuan ','Qian ','Man ','Zhi ','Lu ','Mo ','Piao ','Lian ','Mi ','Xuan ','Zong ','Ji ','Shan ', + 'Sui ','Fan ','Shuai ','Beng ','Yi ','Sao ','Mou ','Yao ','Qiang ','Hun ','Sem ','Xi ','Zung ','Xiu ','Ran ','Xuan ', + 'Sui ','Qiao ','Zeng ','Zuo ','Zhi ','Shan ','San ','Lin ','Yu ','Fan ','Liao ','Chuo ','Zun ','Jian ','Rao ','Chan ', + 'Rui ','Xiu ','Hui ','Hua ','Zuan ','Xi ','Qiang ','Un ','Da ','Sheng ','Hui ','Xi ','Se ','Jian ','Jiang ','Huan ', + 'Zao ','Cong ','Jie ','Jiao ','Bo ','Chan ','Yi ','Nao ','Sui ','Yi ','Shai ','Xu ','Ji ','Bin ','Qian ','Lan ', + 'Pu ','Xun ','Zuan ','Qi ','Peng ','Li ','Mo ','Lei ','Xie ','Zuan ','Kuang ','You ','Xu ','Lei ','Xian ','Chan ', + 'Kou ','Lu ','Chan ','Ying ','Cai ','Xiang ','Xian ','Zui ','Zuan ','Luo ','Xi ','Dao ','Lan ','Lei ','Lian ','Si ', + 'Jiu ','Yu ','Hong ','Zhou ','Xian ','He ','Yue ','Ji ','Wan ','Kuang ','Ji ','Ren ','Wei ','Yun ','Hong ','Chun ', + 'Pi ','Sha ','Gang ','Na ','Ren ','Zong ','Lun ','Fen ','Zhi ','Wen ','Fang ','Zhu ','Yin ','Niu ','Shu ','Xian ', + 'Gan ','Xie ','Fu ','Lian ','Zu ','Shen ','Xi ','Zhi ','Zhong ','Zhou ','Ban ','Fu ','Zhuo ','Shao ','Yi ','Jing ', + 'Dai ','Bang ','Rong ','Jie ','Ku ','Rao ','Die ','Heng ','Hui ','Gei ','Xuan ','Jiang ','Luo ','Jue ','Jiao ','Tong ', + 'Geng ','Xiao ','Juan ','Xiu ','Xi ','Sui ','Tao ','Ji ','Ti ','Ji ','Xu ','Ling ','Ying ','Xu ','Qi ','Fei ', + 'Chuo ','Zhang ','Gun ','Sheng ','Wei ','Mian ','Shou ','Beng ','Chou ','Tao ','Liu ','Quan ','Zong ','Zhan ','Wan ','Lu ', + ], + 'x7f':[ + 'Zhui ','Zi ','Ke ','Xiang ','Jian ','Mian ','Lan ','Ti ','Miao ','Qi ','Yun ','Hui ','Si ','Duo ','Duan ','Bian ', + 'Xian ','Gou ','Zhui ','Huan ','Di ','Lu ','Bian ','Min ','Yuan ','Jin ','Fu ','Ru ','Zhen ','Feng ','Shuai ','Gao ', + 'Chan ','Li ','Yi ','Jian ','Bin ','Piao ','Man ','Lei ','Ying ','Suo ','Mou ','Sao ','Xie ','Liao ','Shan ','Zeng ', + 'Jiang ','Qian ','Zao ','Huan ','Jiao ','Zuan ','Fou ','Xie ','Gang ','Fou ','Que ','Fou ','Ketsu ','Bo ','Ping ','Hou ', + 'Diu6','Gang ','Ying ','Ying ','Qing ','Xia ','Guan ','Zun ','Tan ','Cang ','Qi ','Weng ','Ying ','Lei ','Tan ','Lu ', + 'Guan ','Wang ','Wang ','Gang ','Wang ','Han ','','Luo ','Fu ','Mi ','Fa ','Gu ','Zhu ','Ju ','Mao ','Gu ', + 'Min ','Gang ','Ba ','Gua ','Ti ','Juan ','Fu ','Lin ','Yan ','Zhao ','Zui ','Gua ','Zhuo ','Yu ','Zhi ','An ', + 'Fa ','Nan ','Shu ','Si ','Pi ','Ma ','Liu ','Ba ','Fa ','Li ','Chao ','Wei ','Bi ','Ji ','Zeng ','Tong ', + 'Liu ','Ji ','Juan ','Mi ','Zhao ','Luo ','Pi ','Ji ','Ji ','Luan ','Yang ','Mi ','Qiang ','Ta ','Mei ','Yang ', + 'You ','You ','Fen ','Ba ','Gao ','Yang ','Gu ','Qiang ','Zang ','Gao ','Ling ','Yi ','Zhu ','Di ','Xiu ','Qian ', + 'Yi ','Xian ','Rong ','Qun ','Qun ','Qiang ','Huan ','Suo ','Xian ','Yi ','You ','Qiang ','Xian ','Yu ','Geng ','Jie ', + 'Tang ','Yuan ','Xi ','Fan ','Shan ','Fen ','Shan ','Lian ','Lei ','Geng ','Nou ','Qiang ','Chan ','Yu ','Gong ','Yi ', + 'Chong ','Weng ','Fen ','Hong ','Chi ','Chi ','Cui ','Fu ','Xia ','Pen ','Yi ','La ','Yi ','Pi ','Ling ','Liu ', + 'Zhi ','Qu ','Xi ','Xie ','Xiang ','Xi ','Xi ','Qi ','Qiao ','Hui ','Hui ','Xiao ','Se ','Hong ','Jiang ','Di ', + 'Cui ','Fei ','Tao ','Sha ','Chi ','Zhu ','Jian ','Xuan ','Shi ','Pian ','Zong ','Wan ','Hui ','Hou ','He ','He ', + 'Han ','Ao ','Piao ','Yi ','Lian ','Qu ','','Lin ','Pen ','Qiao ','Ao ','Fan ','Yi ','Hui ','Xuan ','Dao ', + ], + 'x80':[ + 'Yao ','Lao ','','Kao ','Mao ','Zhe ','Qi ','Gou ','Gou ','Gou ','Die ','Die ','Er ','Shua ','Ruan ','Er ', + 'Nai ','Zhuan ','Lei ','Ting ','Zi ','Geng ','Chao ','Hao ','Yun ','Ba ','Pi ','Chi ','Si ','Chu ','Jia ','Ju ', + 'He ','Chu ','Lao ','Lun ','Ji ','Tang ','Ou ','Lou ','Nou ','Jiang ','Pang ','Ze ','Lou ','Ji ','Lao ','Huo ', + 'You ','Mo ','Huai ','Er ','Zhe ','Ting ','Ye ','Da ','Song ','Qin ','Yun ','Chi ','Dan ','Dan ','Hong ','Geng ', + 'Zhi ','','Nie ','Dan ','Zhen ','Che ','Ling ','Zheng ','You ','Wa ','Liao ','Long ','Zhi ','Ning ','Tiao ','Er ', + 'Ya ','Die ','Gua ','','Lian ','Hao ','Sheng ','Lie ','Pin ','Jing ','Ju ','Bi ','Di ','Guo ','Wen ','Xu ', + 'Ping ','Cong ','Shikato ','','Ting ','Yu ','Cong ','Kui ','Ren ','Kui ','Cong ','Lian ','Weng ','Kui ','Lian ','Lian ', + 'Cong ','Ao ','Sheng ','Song ','Ting ','Kui ','Nie ','Zhi ','Dan ','Ning ','qie ','Ji ','Ting ','Ting ','Long ','Yu ', + 'Yu ','Zhao ','Si ','Su ','Yi ','Su ','Si ','Zhao ','Zhao ','Rou ','Yi ','Lei ','Ji ','Qiu ','Ken ','Cao ', + 'Ge ','Di ','Huan ','Huang ','Yi ','Ren ','Xiao ','Ru ','Zhou ','Yuan ','Du ','Gang ','Rong ','Gan ','Cha ','Wo ', + 'Chang ','Gu ','Zhi ','Han ','Fu ','Fei ','Fen ','Pei ','Pang ','Jian ','Fang ','Zhun ','You ','Na ','Hang ','Ken ', + 'Ran ','Gong ','Yu ','Wen ','Yao ','Jin ','Pi ','Qian ','Xi ','Xi ','Fei ','Ken ','Jing ','Tai ','Shen ','Zhong ', + 'Zhang ','Xie ','Shen ','Wei ','Zhou ','Die ','Dan ','Fei ','Ba ','Bo ','Qu ','Tian ','Bei ','Gua ','Tai ','Zi ', + 'Ku ','Zhi ','Ni ','Ping ','Zi ','Fu ','Pang ','Zhen ','Xian ','Zuo ','Pei ','Jia ','Sheng ','Zhi ','Bao ','Mu ', + 'Qu ','Hu ','Ke ','Yi ','Yin ','Xu ','Yang ','Long ','Dong ','Ka ','Lu ','Jing ','Nu ','Yan ','Pang ','Kua ', + 'Yi ','Guang ','Hai ','Ge ','Dong ','Zhi ','Xiao ','Xiong ','Xiong ','Er ','E ','Xing ','Pian ','Neng ','Zi ','', + ], + 'x81':[ + 'Cheng ','Tiao ','Zhi ','Cui ','Mei ','Xie ','Cui ','Xie ','Mai ','Mai ','Ji ','Kyou ','Nin ','Kuai ','Sa ','Zang ', + 'Qi ','Nao ','Mi ','Nong ','Luan ','Wan ','Bo ','Wen ','Guan ','Qiu ','Jiao ','Jing ','Rou ','Heng ','Cuo ','Lie ', + 'Shan ','Ting ','Mei ','Chun ','Shen ','Qian ','Te ','Zui ','Cu ','Xiu ','Xin ','Tuo ','Pao ','Cheng ','Nei ','Fu ', + 'Dou ','Tuo ','Niao ','Noy ','Pi ','Gu ','Gua ','Li ','Lian ','Zhang ','Cui ','Jie ','Liang ','Zhou ','Pi ','Biao ', + 'Lun ','Pian ','Guo ','Kui ','Chui ','Dan ','Tian ','Nei ','Jing ','Jie ','La ','Yi ','Yan ','Ren ','Shen ','Chuo ', + 'Fu ','Fu ','Ju ','Fei ','Qiang ','Wan ','Dong ','Pi ','Guo ','Zong ','Ding ','Wu ','Mei ','Ruan ','Zhuan ','Zhi ', + 'Cou ','Gua ','Ou ','Di ','An ','Xing ','Nao ','Yu ','Chuan ','Nan ','Yun ','Zhong ','Rou ','E ','Sai ','Tu ', + 'Yao ','Jian ','Wei ','Jiao ','Yu ','Jia ','Duan ','Bi ','Chang ','Fu ','Xian ','Ni ','Mian ','Wa ','Teng ','Tui ', + 'Bang ','Qian ','Lu ','Wa ','Sou ','Tang ','Su ','Zhui ','Ge ','Yi ','Bo ','Liao ','Ji ','Pi ','Xie ','Gao ', + 'Lu ','Bin ','','Chang ','Lu ','Guo ','Pang ','Chuai ','Piao ','Jiang ','Fu ','Tang ','Mo ','Xi ','Zhuan ','Lu ', + 'Jiao ','Ying ','Lu ','Zhi ','Tara ','Chun ','Lian ','Tong ','Peng ','Ni ','Zha ','Liao ','Cui ','Gui ','Xiao ','Teng ', + 'Fan ','Zhi ','Jiao ','Shan ','Hu ','Cui ','Run ','Xiang ','Sui ','Fen ','Ying ','Dan ','Zhua ','Dan ','Kuai ','Nong ', + 'Tun ','Lian ','Bi ','Yong ','Jue ','Chu ','Yi ','Juan ','La ','Lian ','Sao ','Tun ','Gu ','Qi ','Cui ','Bin ', + 'Xun ','Ru ','Huo ','Zang ','Xian ','Biao ','Xing ','Kuan ','La ','Yan ','Lu ','Huo ','Zang ','Luo ','Qu ','Zang ', + 'Luan ','Ni ','Zang ','Chen ','Qian ','Wo ','Guang ','Zang ','Lin ','Guang ','Zi ','Jiao ','Nie ','Chou ','Ji ','Gao ', + 'Chou ','Mian ','Nie ','Zhi ','Zhi ','Ge ','Jian ','Die ','Zhi ','Xiu ','Tai ','Zhen ','Jiu ','Xian ','Yu ','Cha ', + ], + 'x82':[ + 'Yao ','Yu ','Chong ','Xi ','Xi ','Jiu ','Yu ','Yu ','Xing ','Ju ','Jiu ','Xin ','She ','She ','Sha ','Jiu ', + 'Shi ','Tan ','Shu ','Shi ','Tian ','Dan ','Pu ','Pu ','Guan ','Hua ','Tan ','Chuan ','Shun ','Xia ','Wu ','Zhou ', + 'Dao ','Gang ','Shan ','Yi ','','Pa ','Tai ','Fan ','Ban ','Chuan ','Hang ','Fang ','Ban ','Que ','Ro ','Zhong ', + 'Jian ','Cang ','Ling ','Zhu ','Ze ','Duo ','Bo ','Xian ','Ge ','Chuan ','Xia ','Lu ','Hong ','Pang ','Xi ','', + 'Fu ','Zao ','Feng ','Li ','Shao ','Yu ','Lang ','Ting ','','Wei ','Bo ','Meng ','Nian ','Ju ','Huang ','Shou ', + 'Zong ','Bian ','Mao ','Die ','Dou6','Bang ','Cha ','Yi ','Sao ','Cang ','Cao ','Lou ','Dai ','Sori ','Yao ','Tong ', + 'Tou ','Dang ','Tan ','Lu ','Yi ','Jie ','Jian ','Huo ','Meng ','Qi ','Lu ','Lu ','Chan ','Shuang ','Gen ','Liang ', + 'Jian ','Jian ','Se ','Yan ','Fu ','Ping ','Yan ','Yan ','Cao ','','Yi ','Le ','Ting ','Qiu ','Ai ','Nai ', + 'Tiao ','Jiao ','Jie ','Peng ','Wan ','Yi ','Chai ','Mian ','Mie ','Gan ','Qian ','Yu ','Yu ','Shao ','Qiong ','Tu ', + 'Xia ','Qi ','Mang ','Zi ','Hui ','Sui ','Zhi ','Xiang ','Pi ','Fu ','Tun ','Wei ','Wu ','Zhi ','Qi ','Shan ', + 'Wen ','Qian ','Ren ','Fu ','Kou ','Jie ','Lu ','Xu ','Ji ','Qin ','Qi ','Yuan ','Fen ','Ba ','Rui ','Xin ', + 'Ji ','Hua ','Hua ','Fang ','Wu ','Jue ','Gou ','Zhi ','Yun ','Qin ','Ao ','Chu ','Mao ','Ya ','Fei ','Reng ', + 'Hang ','Cong ','Yin ','You ','Bian ','Yi ','Susa ','Wei ','Li ','Pi ','E ','Xian ','Chang ','Cang ','Meng ','Su ', + 'Yi ','Yuan ','Ran ','Ling ','Tai ','Tiao ','Di ','Miao ','Qiong ','Li ','Yong ','Ke ','Mu ','Pei ','Bao ','Gou ', + 'Min ','Yi ','Yi ','Ju ','Pi ','Ruo ','Ku ','Zhu ','Ni ','Bo ','Bing ','Shan ','Qiu ','Yao ','Xian ','Ben ', + 'Hong ','Ying ','Zha ','Dong ','Ju ','Die ','Nie ','Gan ','Hu ','Ping ','Mei ','Fu ','Sheng ','Gu ','Bi ','Wei ', + ], + 'x83':[ + 'Fu ','Zhuo ','Mao ','Fan ','Qie ','Mao ','Mao ','Ba ','Zi ','Mo ','Zi ','Di ','Chi ','Ji ','Jing ','Long ', + '','Niao ','','Xue ','Ying ','Qiong ','Ge ','Ming ','Li ','Rong ','Yin ','Gen ','Qian ','Chai ','Chen ','Yu ', + 'Xiu ','Zi ','Lie ','Wu ','Ji ','Gui ','Ce ','Chong ','Ci ','Gou ','Guang ','Mang ','Chi ','Jiao ','Jiao ','Fu ', + 'Yu ','Zhu ','Zi ','Jiang ','Hui ','Yin ','Cha ','Fa ','Rong ','Ru ','Chong ','Mang ','Tong ','Zhong ','','Zhu ', + 'Xun ','Huan ','Kua ','Quan ','Gai ','Da ','Jing ','Xing ','Chuan ','Cao ','Jing ','Er ','An ','Shou ','Chi ','Ren ', + 'Jian ','Ti ','Huang ','Ping ','Li ','Jin ','Lao ','Shu ','Zhuang ','Da ','Jia ','Rao ','Bi ','Ze ','Qiao ','Hui ', + 'Qi ','Dang ','','Rong ','Hun ','Ying ','Luo ','Ying ','Xun ','Jin ','Sun ','Yin ','Mai ','Hong ','Zhou ','Yao ', + 'Du ','Wei ','Chu ','Dou ','Fu ','Ren ','Yin ','He ','Bi ','Bu ','Yun ','Di ','Tu ','Sui ','Sui ','Cheng ', + 'Chen ','Wu ','Bie ','Xi ','Geng ','Li ','Fu ','Zhu ','Mo ','Li ','Zhuang ','Ji ','Duo ','Qiu ','Sha ','Suo ', + 'Chen ','Feng ','Ju ','Mei ','Meng ','Xing ','Jing ','Che ','Shen ','Jun ','Yan ','Ting ','Diao ','Cuo ','Guan ','Han ', + 'You ','Cuo ','Jia ','Wang ','You ','Niu ','Shao ','Xian ','Lang ','Fu ','E ','Mo ','Wen ','Jie ','Nan ','Mu ', + 'Kan ','Lai ','Lian ','Shi ','Wo ','To ','Lian ','Huo ','You ','Ying ','Ying ','Nuc ','Chun ','Mang ','Mang ','Ci ', + 'Wan ','Jing ','Di ','Qu ','Dong ','Jian ','Zou ','Gu ','La ','Lu ','Ju ','Wei ','Jun ','Nie ','Kun ','He ', + 'Pu ','Zi ','Gao ','Guo ','Fu ','Lun ','Chang ','Chou ','Song ','Chui ','Zhan ','Men ','Cai ','Ba ','Li ','Tu ', + 'Bo ','Han ','Bao ','Qin ','Juan ','Xi ','Qin ','Di ','Jie ','Pu ','Dang ','Jin ','Zhao ','Tai ','Geng ','Hua ', + 'Gu ','Ling ','Fei ','Jin ','An ','Wang ','Beng ','Zhou ','Yan ','Ju ','Jian ','Lin ','Tan ','Shu ','Tian ','Dao ', + ], + 'x84':[ + 'Hu ','Qi ','He ','Cui ','Tao ','Chun ','Pi ','Chang ','Huan ','Fei ','Lai ','Qi ','Meng ','Ping ','Wei ','Dan ', + 'Sha ','Huan ','Yan ','Yi ','Tiao ','Qi ','Wan ','Ce ','Nai ','Kutabireru ','Tuo ','Jiu ','Tie ','Luo ','','', + 'Meng ','','Yaji ','','Ying ','Ying ','Ying ','Xiao ','Sa ','Qiu ','Ke ','Xiang ','Wan ','Yu ','Yu ','Fu ', + 'Lian ','Xuan ','Yuan ','Nan ','Ze ','Wo ','Chun ','Xiao ','Yu ','Pian ','Mao ','An ','E ','Luo ','Ying ','Huo ', + 'Gua ','Jiang ','Mian ','Zuo ','Zuo ','Ju ','Bao ','Rou ','Xi ','Ye ','An ','Qu ','Jian ','Fu ','Lu ','Jing ', + 'Pen ','Feng ','Hong ','Hong ','Hou ','Yan ','Tu ','Zhu ','Zi ','Xiang ','Shen ','Ge ','Jie ','Jing ','Mi ','Huang ', + 'Shen ','Pu ','Gai ','Dong ','Zhou ','Qian ','Wei ','Bo ','Wei ','Pa ','Ji ','Hu ','Zang ','Jia ','Duan ','Yao ', + 'Jun ','Cong ','Quan ','Wei ','Zhen ','Kui ','Ting ','Hun ','Xi ','Shi ','Qi ','Lan ','Zong ','Yao ','Yuan ','Mei ', + 'Yun ','Shu ','Di ','Zhuan ','Guan ','Sukumo ','Xue ','Chan ','Kai ','Kui ','','Jiang ','Lou ','Wei ','Pai ','', + 'Sou ','Yin ','Shi ','Chun ','Shi ','Yun ','Zhen ','Lang ','Nu ','Meng ','He ','Que ','Suan ','Yuan ','Li ','Ju ', + 'Xi ','Bang ','Chu ','Xu ','Tu ','Liu ','Wo ','Zhen ','Qian ','Zu ','Po ','Cuo ','Yuan ','Chu ','Yu ','Kuai ', + 'Pan ','Pu ','Pu ','Na ','Shuo ','Xi ','Fen ','Yun ','Zheng ','Jian ','Ji ','Ruo ','Cang ','En ','Mi ','Hao ', + 'Sun ','Zhen ','Ming ','Huo ','Xu ','Liu ','Xi ','Gu ','Lang ','Rong ','Weng ','Gai ','Cuo ','Shi ','Tang ','Luo ', + 'Ru ','Suo ','Xian ','Bei ','Yao ','Gui ','Bi ','Zong ','Gun ','Za ','Xiu ','Ce ','Hai ','Lan ','','Ji ', + 'Li ','Can ','Lang ','Yu ','','Ying ','Mo ','Diao ','Tiao ','Mao ','Tong ','Zhu ','Peng ','An ','Lian ','Cong ', + 'Xi ','Ping ','Qiu ','Jin ','Chun ','Jie ','Wei ','Tui ','Cao ','Yu ','Yi ','Ji ','Liao ','Bi ','Lu ','Su ', + ], + 'x85':[ + 'Bu ','Zhang ','Luo ','Jiang ','Man ','Yan ','Ling ','Ji ','Piao ','Gun ','Han ','Di ','Su ','Lu ','She ','Shang ', + 'Di ','Mie ','Xun ','Man ','Bo ','Di ','Cuo ','Zhe ','Sen ','Xuan ','Wei ','Hu ','Ao ','Mi ','Lou ','Cu ', + 'Zhong ','Cai ','Po ','Jiang ','Mi ','Cong ','Niao ','Hui ','Jun ','Yin ','Jian ','Yan ','Shu ','Yin ','Kui ','Chen ', + 'Hu ','Sha ','Kou ','Qian ','Ma ','Zang ','Sonoko ','Qiang ','Dou ','Lian ','Lin ','Kou ','Ai ','Bi ','Li ','Wei ', + 'Ji ','Xun ','Sheng ','Fan ','Meng ','Ou ','Chan ','Dian ','Xun ','Jiao ','Rui ','Rui ','Lei ','Yu ','Qiao ','Chu ', + 'Hua ','Jian ','Mai ','Yun ','Bao ','You ','Qu ','Lu ','Rao ','Hui ','E ','Teng ','Fei ','Jue ','Zui ','Fa ', + 'Ru ','Fen ','Kui ','Shun ','Rui ','Ya ','Xu ','Fu ','Jue ','Dang ','Wu ','Tong ','Si ','Xiao ','Xi ','Long ', + 'Yun ','','Qi ','Jian ','Yun ','Sun ','Ling ','Yu ','Xia ','Yong ','Ji ','Hong ','Si ','Nong ','Lei ','Xuan ', + 'Yun ','Yu ','Xi ','Hao ','Bo ','Hao ','Ai ','Wei ','Hui ','Wei ','Ji ','Ci ','Xiang ','Luan ','Mie ','Yi ', + 'Leng ','Jiang ','Can ','Shen ','Qiang ','Lian ','Ke ','Yuan ','Da ','Ti ','Tang ','Xue ','Bi ','Zhan ','Sun ','Lian ', + 'Fan ','Ding ','Jie ','Gu ','Xie ','Shu ','Jian ','Kao ','Hong ','Sa ','Xin ','Xun ','Yao ','Hai ','Sou ','Shu ', + 'Xun ','Dui ','Pin ','Wei ','Neng ','Chou ','Mai ','Ru ','Piao ','Tai ','Ci ','Zao ','Chen ','Zhen ','Er ','Ni ', + 'Ying ','Gao ','Cong ','Xiao ','Qi ','Fa ','Jian ','Xu ','Kui ','Jie ','Bian ','Diao ','Mi ','Lan ','Jin ','Cang ', + 'Miao ','Qiong ','Qie ','Xian ','','Ou ','Xian ','Su ','Lu ','Yi ','Xu ','Xie ','Li ','Yi ','La ','Lei ', + 'Xiao ','Di ','Zhi ','Bei ','Teng ','Yao ','Mo ','Huan ','Biao ','Fan ','Sou ','Tan ','Tui ','Qiong ','Qiao ','Wei ', + 'Liu ','Hui ','','Gao ','Yun ','','Li ','Shu ','Chu ','Ai ','Lin ','Zao ','Xuan ','Chen ','Lai ','Huo ', + ], + 'x86':[ + 'Tuo ','Wu ','Rui ','Rui ','Qi ','Heng ','Lu ','Su ','Tui ','Mang ','Yun ','Pin ','Yu ','Xun ','Ji ','Jiong ', + 'Xian ','Mo ','Hagi ','Su ','Jiong ','','Nie ','Bo ','Rang ','Yi ','Xian ','Yu ','Ju ','Lian ','Lian ','Yin ', + 'Qiang ','Ying ','Long ','Tong ','Wei ','Yue ','Ling ','Qu ','Yao ','Fan ','Mi ','Lan ','Kui ','Lan ','Ji ','Dang ', + 'Katsura ','Lei ','Lei ','Hua ','Feng ','Zhi ','Wei ','Kui ','Zhan ','Huai ','Li ','Ji ','Mi ','Lei ','Huai ','Luo ', + 'Ji ','Kui ','Lu ','Jian ','San ','','Lei ','Quan ','Xiao ','Yi ','Luan ','Men ','Bie ','Hu ','Hu ','Lu ', + 'Nue ','Lu ','Si ','Xiao ','Qian ','Chu ','Hu ','Xu ','Cuo ','Fu ','Xu ','Xu ','Lu ','Hu ','Yu ','Hao ', + 'Jiao ','Ju ','Guo ','Bao ','Yan ','Zhan ','Zhan ','Kui ','Ban ','Xi ','Shu ','Chong ','Qiu ','Diao ','Ji ','Qiu ', + 'Cheng ','Shi ','','Di ','Zhe ','She ','Yu ','Gan ','Zi ','Hong ','Hui ','Meng ','Ge ','Sui ','Xia ','Chai ', + 'Shi ','Yi ','Ma ','Xiang ','Fang ','E ','Pa ','Chi ','Qian ','Wen ','Wen ','Rui ','Bang ','Bi ','Yue ','Yue ', + 'Jun ','Qi ','Tong ','Yin ','Qi ','Can ','Yuan ','Jue ','Hui ','Qin ','Qi ','Zhong ','Ya ','Ci ','Mu ','Wang ', + 'Fen ','Fen ','Hang ','Gong ','Zao ','Fu ','Ran ','Jie ','Fu ','Chi ','Dou ','Piao ','Xian ','Ni ','Te ','Qiu ', + 'You ','Zha ','Ping ','Chi ','You ','He ','Han ','Ju ','Li ','Fu ','Ran ','Zha ','Gou ','Pi ','Bo ','Xian ', + 'Zhu ','Diao ','Bie ','Bing ','Gu ','Ran ','Qu ','She ','Tie ','Ling ','Gu ','Dan ','Gu ','Ying ','Li ','Cheng ', + 'Qu ','Mou ','Ge ','Ci ','Hui ','Hui ','Mang ','Fu ','Yang ','Wa ','Lie ','Zhu ','Yi ','Xian ','Kuo ','Jiao ', + 'Li ','Yi ','Ping ','Jie ','Ha ','She ','Yi ','Wang ','Mo ','Qiong ','Qie ','Gui ','Gong ','Zhi ','Man ','Ebi ', + 'Zhi ','Jia ','Rao ','Si ','Qi ','Xing ','Lie ','Qiu ','Shao ','Yong ','Jia ','Tui ','Che ','Bai ','E ','Han ', + ], + 'x87':[ + 'Shu ','Xuan ','Feng ','Shen ','Zhen ','Fu ','Xian ','Zhe ','Wu ','Fu ','Li ','Lang ','Bi ','Chu ','Yuan ','You ', + 'Jie ','Dan ','Yan ','Ting ','Dian ','Shui ','Hui ','Gua ','Zhi ','Song ','Fei ','Ju ','Mi ','Qi ','Qi ','Yu ', + 'Jun ','La ','Meng ','Qiang ','Si ','Xi ','Lun ','Li ','Die ','Tiao ','Tao ','Kun ','Gan ','Han ','Yu ','Bang ', + 'Fei ','Pi ','Wei ','Dun ','Yi ','Yuan ','Su ','Quan ','Qian ','Rui ','Ni ','Qing ','Wei ','Liang ','Guo ','Wan ', + 'Dong ','E ','Ban ','Di ','Wang ','Can ','Yang ','Ying ','Guo ','Chan ','','La ','Ke ','Ji ','He ','Ting ', + 'Mai ','Xu ','Mian ','Yu ','Jie ','Shi ','Xuan ','Huang ','Yan ','Bian ','Rou ','Wei ','Fu ','Yuan ','Mei ','Wei ', + 'Fu ','Ruan ','Xie ','You ','Qiu ','Mao ','Xia ','Ying ','Shi ','Chong ','Tang ','Zhu ','Zong ','Ti ','Fu ','Yuan ', + 'Hui ','Meng ','La ','Du ','Hu ','Qiu ','Die ','Li ','Gua ','Yun ','Ju ','Nan ','Lou ','Qun ','Rong ','Ying ', + 'Jiang ','','Lang ','Pang ','Si ','Xi ','Ci ','Xi ','Yuan ','Weng ','Lian ','Sou ','Ban ','Rong ','Rong ','Ji ', + 'Wu ','Qiu ','Han ','Qin ','Yi ','Bi ','Hua ','Tang ','Yi ','Du ','Nai ','He ','Hu ','Hui ','Ma ','Ming ', + 'Yi ','Wen ','Ying ','Teng ','Yu ','Cang ','So ','Ebi ','Man ','','Shang ','Shi ','Cao ','Chi ','Di ','Ao ', + 'Lu ','Wei ','Zhi ','Tang ','Chen ','Piao ','Qu ','Pi ','Yu ','Jian ','Luo ','Lou ','Qin ','Zhong ','Yin ','Jiang ', + 'Shuai ','Wen ','Jiao ','Wan ','Zhe ','Zhe ','Ma ','Ma ','Guo ','Liu ','Mao ','Xi ','Cong ','Li ','Man ','Xiao ', + 'Tou ','Zhang ','Mang ','Xiang ','Mo ','Zui ','Si ','Qiu ','Te ','Zhi ','Peng ','Peng ','Jiao ','Qu ','Bie ','Liao ', + 'Pan ','Gui ','Xi ','Ji ','Zhuan ','Huang ','Fei ','Lao ','Jue ','Jue ','Hui ','Yin ','Chan ','Jiao ','Shan ','Rao ', + 'Xiao ','Mou ','Chong ','Xun ','Si ','','Cheng ','Dang ','Li ','Xie ','Shan ','Yi ','Jing ','Da ','Chan ','Qi ', + ], + 'x88':[ + 'Ci ','Xiang ','She ','Luo ','Qin ','Ying ','Chai ','Li ','Ze ','Xuan ','Lian ','Zhu ','Ze ','Xie ','Mang ','Xie ', + 'Qi ','Rong ','Jian ','Meng ','Hao ','Ru ','Huo ','Zhuo ','Jie ','Bin ','He ','Mie ','Fan ','Lei ','Jie ','La ', + 'Mi ','Li ','Chun ','Li ','Qiu ','Nie ','Lu ','Du ','Xiao ','Zhu ','Long ','Li ','Long ','Feng ','Ye ','Beng ', + 'Shang ','Gu ','Juan ','Ying ','','Xi ','Can ','Qu ','Quan ','Du ','Can ','Man ','Jue ','Jie ','Zhu ','Zha ', + 'Xie ','Huang ','Niu ','Pei ','Nu ','Xin ','Zhong ','Mo ','Er ','Ke ','Mie ','Xi ','Xing ','Yan ','Kan ','Yuan ', + '','Ling ','Xuan ','Shu ','Xian ','Tong ','Long ','Jie ','Xian ','Ya ','Hu ','Wei ','Dao ','Chong ','Wei ','Dao ', + 'Zhun ','Heng ','Qu ','Yi ','Koromohen ','Bu ','Gan ','Yu ','Biao ','Cha ','Yi ','Shan ','Chen ','Fu ','Gun ','Fen ', + 'Shuai ','Jie ','Na ','Zhong ','Dan ','Ri ','Zhong ','Zhong ','Xie ','Qi ','Xie ','Ran ','Zhi ','Ren ','Qin ','Jin ', + 'Jun ','Yuan ','Mei ','Chai ','Ao ','Niao ','Hui ','Ran ','Jia ','Tuo ','Ling ','Dai ','Bao ','Pao ','Yao ','Zuo ', + 'Bi ','Shao ','Tan ','Ju ','He ','Shu ','Xiu ','Zhen ','Yi ','Pa ','Bo ','Di ','Wa ','Fu ','Gun ','Zhi ', + 'Zhi ','Ran ','Pan ','Yi ','Mao ','','Na ','Kou ','Xian ','Chan ','Qu ','Bei ','Gun ','Xi ','Ne ','Bo ', + 'Horo ','Fu ','Yi ','Chi ','Ku ','Ren ','Jiang ','Jia ','Cun ','Mo ','Jie ','Er ','Luo ','Ru ','Zhu ','Gui ', + 'Yin ','Cai ','Lie ','Kamishimo ','Yuki ','Zhuang ','Dang ','Seot ','Kun ','Ken ','Niao ','Shu ','Jia ','Kun ','Cheng ','Li ', + 'Juan ','Shen ','Pou ','Ge ','Yi ','Yu ','Zhen ','Liu ','Qiu ','Qun ','Ji ','Yi ','Bu ','Zhuang ','Shui ','Sha ', + 'Qun ','Li ','Lian ','Lian ','Ku ','Jian ','Fou ','Chan ','Bi ','Gun ','Tao ','Yuan ','Ling ','Chi ','Chang ','Chou ', + 'Duo ','Biao ','Liang ','Chang ','Pei ','Pei ','Fei ','Yuan ','Luo ','Guo ','Yan ','Du ','Xi ','Zhi ','Ju ','Qi ', + ], + 'x89':[ + 'Ji ','Zhi ','Gua ','Ken ','Che ','Ti ','Ti ','Fu ','Chong ','Xie ','Bian ','Die ','Kun ','Duan ','Xiu ','Xiu ', + 'He ','Yuan ','Bao ','Bao ','Fu ','Yu ','Tuan ','Yan ','Hui ','Bei ','Chu ','Lu ','Ena ','Tan ','Yun ','Da ', + 'Gou ','Da ','Huai ','Rong ','Yuan ','Ru ','Nai ','Jiong ','Suo ','Ban ','Tun ','Chi ','Sang ','Niao ','Ying ','Jie ', + 'Qian ','Huai ','Ku ','Lian ','Bao ','Li ','Zhe ','Shi ','Lu ','Yi ','Die ','Xie ','Xian ','Wei ','Biao ','Cao ', + 'Ji ','Jiang ','Sen ','Bao ','Xiang ','Chihaya ','Pu ','Jian ','Zhuan ','Jian ','Zui ','Ji ','Dan ','Za ','Fan ','Bo ', + 'Xiang ','Xin ','Bie ','Rao ','Man ','Lan ','Ao ','Duo ','Gui ','Cao ','Sui ','Nong ','Chan ','Lian ','Bi ','Jin ', + 'Dang ','Shu ','Tan ','Bi ','Lan ','Pu ','Ru ','Zhi ','','Shu ','Wa ','Shi ','Bai ','Xie ','Bo ','Chen ', + 'Lai ','Long ','Xi ','Xian ','Lan ','Zhe ','Dai ','Tasuki ','Zan ','Shi ','Jian ','Pan ','Yi ','Ran ','Ya ','Xi ', + 'Xi ','Yao ','Feng ','Tan ','','Biao ','Fu ','Ba ','He ','Ji ','Ji ','Jian ','Guan ','Bian ','Yan ','Gui ', + 'Jue ','Pian ','Mao ','Mi ','Mi ','Mie ','Shi ','Si ','Zhan ','Luo ','Jue ','Mi ','Tiao ','Lian ','Yao ','Zhi ', + 'Jun ','Xi ','Shan ','Wei ','Xi ','Tian ','Yu ','Lan ','E ','Du ','Qin ','Pang ','Ji ','Ming ','Ying ','Gou ', + 'Qu ','Zhan ','Jin ','Guan ','Deng ','Jian ','Luo ','Qu ','Jian ','Wei ','Jue ','Qu ','Luo ','Lan ','Shen ','Di ', + 'Guan ','Jian ','Guan ','Yan ','Gui ','Mi ','Shi ','Zhan ','Lan ','Jue ','Ji ','Xi ','Di ','Tian ','Yu ','Gou ', + 'Jin ','Qu ','Jiao ','Jiu ','Jin ','Cu ','Jue ','Zhi ','Chao ','Ji ','Gu ','Dan ','Zi ','Di ','Shang ','Hua ', + 'Quan ','Ge ','Chi ','Jie ','Gui ','Gong ','Chu ','Jie ','Hun ','Qiu ','Xing ','Su ','Ni ','Ji ','Lu ','Zhi ', + 'Zha ','Bi ','Xing ','Hu ','Shang ','Gong ','Zhi ','Xue ','Chu ','Xi ','Yi ','Lu ','Jue ','Xi ','Yan ','Xi ', + ], + 'x8a':[ + 'Yan ','Gonben ','Ding ','Fu ','Qiu ','Qiu ','Jiao ','Hong ','Ji ','Fan ','Xun ','Diao ','Hong ','Cha ','Tao ','Xu ', + 'Jie ','Yi ','Ren ','Xun ','Yin ','Shan ','Qi ','Tuo ','Ji ','Xun ','Yin ','E ','Fen ','Ya ','Yao ','Song ', + 'Shen ','Yin ','Xin ','Jue ','Xiao ','Ne ','Chen ','You ','Zhi ','Xiong ','Fang ','Xin ','Chao ','She ','Xian ','Sha ', + 'Tun ','Xu ','Yi ','Yi ','Su ','Chi ','He ','Shen ','He ','Xu ','Zhen ','Zhu ','Zheng ','Gou ','Zi ','Zi ', + 'Zhan ','Gu ','Fu ','Quan ','Die ','Ling ','Di ','Yang ','Li ','Nao ','Pan ','Zhou ','Gan ','Yi ','Ju ','Ao ', + 'Zha ','Tuo ','Yi ','Qu ','Zhao ','Ping ','Bi ','Xiong ','Qu ','Ba ','Da ','Zu ','Tao ','Zhu ','Ci ','Zhe ', + 'Yong ','Xu ','Xun ','Yi ','Huang ','He ','Shi ','Cha ','Jiao ','Shi ','Hen ','Cha ','Gou ','Gui ','Quan ','Hui ', + 'Jie ','Hua ','Gai ','Xiang ','Wei ','Shen ','Chou ','Tong ','Mi ','Zhan ','Ming ','E ','Hui ','Yan ','Xiong ','Gua ', + 'Er ','Beng ','Tiao ','Chi ','Lei ','Zhu ','Kuang ','Kua ','Wu ','Yu ','Teng ','Ji ','Zhi ','Ren ','Su ','Lang ', + 'E ','Kuang ','E ','Shi ','Ting ','Dan ','Bo ','Chan ','You ','Heng ','Qiao ','Qin ','Shua ','An ','Yu ','Xiao ', + 'Cheng ','Jie ','Xian ','Wu ','Wu ','Gao ','Song ','Pu ','Hui ','Jing ','Shuo ','Zhen ','Shuo ','Du ','Yasashi ','Chang ', + 'Shui ','Jie ','Ke ','Qu ','Cong ','Xiao ','Sui ','Wang ','Xuan ','Fei ','Chi ','Ta ','Yi ','Na ','Yin ','Diao ', + 'Pi ','Chuo ','Chan ','Chen ','Zhun ','Ji ','Qi ','Tan ','Zhui ','Wei ','Ju ','Qing ','Jian ','Zheng ','Ze ','Zou ', + 'Qian ','Zhuo ','Liang ','Jian ','Zhu ','Hao ','Lun ','Shen ','Biao ','Huai ','Pian ','Yu ','Die ','Xu ','Pian ','Shi ', + 'Xuan ','Shi ','Hun ','Hua ','E ','Zhong ','Di ','Xie ','Fu ','Pu ','Ting ','Jian ','Qi ','Yu ','Zi ','Chuan ', + 'Xi ','Hui ','Yin ','An ','Xian ','Nan ','Chen ','Feng ','Zhu ','Yang ','Yan ','Heng ','Xuan ','Ge ','Nuo ','Qi ', + ], + 'x8b':[ + 'Mou ','Ye ','Wei ','','Teng ','Zou ','Shan ','Jian ','Bo ','','Huang ','Huo ','Ge ','Ying ','Mi ','Xiao ', + 'Mi ','Xi ','Qiang ','Chen ','Nue ','Ti ','Su ','Bang ','Chi ','Qian ','Shi ','Jiang ','Yuan ','Xie ','Xue ','Tao ', + 'Yao ','Yao ','','Yu ','Biao ','Cong ','Qing ','Li ','Mo ','Mo ','Shang ','Zhe ','Miu ','Jian ','Ze ','Jie ', + 'Lian ','Lou ','Can ','Ou ','Guan ','Xi ','Zhuo ','Ao ','Ao ','Jin ','Zhe ','Yi ','Hu ','Jiang ','Man ','Chao ', + 'Han ','Hua ','Chan ','Xu ','Zeng ','Se ','Xi ','She ','Dui ','Zheng ','Nao ','Lan ','E ','Ying ','Jue ','Ji ', + 'Zun ','Jiao ','Bo ','Hui ','Zhuan ','Mu ','Zen ','Zha ','Shi ','Qiao ','Tan ','Zen ','Pu ','Sheng ','Xuan ','Zao ', + 'Tan ','Dang ','Sui ','Qian ','Ji ','Jiao ','Jing ','Lian ','Nou ','Yi ','Ai ','Zhan ','Pi ','Hui ','Hua ','Yi ', + 'Yi ','Shan ','Rang ','Nou ','Qian ','Zhui ','Ta ','Hu ','Zhou ','Hao ','Ye ','Ying ','Jian ','Yu ','Jian ','Hui ', + 'Du ','Zhe ','Xuan ','Zan ','Lei ','Shen ','Wei ','Chan ','Li ','Yi ','Bian ','Zhe ','Yan ','E ','Chou ','Wei ', + 'Chou ','Yao ','Chan ','Rang ','Yin ','Lan ','Chen ','Huo ','Zhe ','Huan ','Zan ','Yi ','Dang ','Zhan ','Yan ','Du ', + 'Yan ','Ji ','Ding ','Fu ','Ren ','Ji ','Jie ','Hong ','Tao ','Rang ','Shan ','Qi ','Tuo ','Xun ','Yi ','Xun ', + 'Ji ','Ren ','Jiang ','Hui ','Ou ','Ju ','Ya ','Ne ','Xu ','E ','Lun ','Xiong ','Song ','Feng ','She ','Fang ', + 'Jue ','Zheng ','Gu ','He ','Ping ','Zu ','Shi ','Xiong ','Zha ','Su ','Zhen ','Di ','Zou ','Ci ','Qu ','Zhao ', + 'Bi ','Yi ','Yi ','Kuang ','Lei ','Shi ','Gua ','Shi ','Jie ','Hui ','Cheng ','Zhu ','Shen ','Hua ','Dan ','Gou ', + 'Quan ','Gui ','Xun ','Yi ','Zheng ','Gai ','Xiang ','Cha ','Hun ','Xu ','Zhou ','Jie ','Wu ','Yu ','Qiao ','Wu ', + 'Gao ','You ','Hui ','Kuang ','Shuo ','Song ','Ai ','Qing ','Zhu ','Zou ','Nuo ','Du ','Zhuo ','Fei ','Ke ','Wei ', + ], + 'x8c':[ + 'Yu ','Shui ','Shen ','Diao ','Chan ','Liang ','Zhun ','Sui ','Tan ','Shen ','Yi ','Mou ','Chen ','Die ','Huang ','Jian ', + 'Xie ','Nue ','Ye ','Wei ','E ','Yu ','Xuan ','Chan ','Zi ','An ','Yan ','Di ','Mi ','Pian ','Xu ','Mo ', + 'Dang ','Su ','Xie ','Yao ','Bang ','Shi ','Qian ','Mi ','Jin ','Man ','Zhe ','Jian ','Miu ','Tan ','Zen ','Qiao ', + 'Lan ','Pu ','Jue ','Yan ','Qian ','Zhan ','Chen ','Gu ','Qian ','Hong ','Xia ','Jue ','Hong ','Han ','Hong ','Xi ', + 'Xi ','Huo ','Liao ','Han ','Du ','Long ','Dou ','Jiang ','Qi ','Chi ','Li ','Deng ','Wan ','Bi ','Shu ','Xian ', + 'Feng ','Zhi ','Zhi ','Yan ','Yan ','Shi ','Chu ','Hui ','Tun ','Yi ','Tun ','Yi ','Jian ','Ba ','Hou ','E ', + 'Cu ','Xiang ','Huan ','Jian ','Ken ','Gai ','Qu ','Fu ','Xi ','Bin ','Hao ','Yu ','Zhu ','Jia ','Fen ','Xi ', + 'Bo ','Wen ','Huan ','Bin ','Di ','Zong ','Fen ','Yi ','Zhi ','Bao ','Chai ','An ','Pi ','Na ','Pi ','Gou ', + 'Na ','You ','Diao ','Mo ','Si ','Xiu ','Huan ','Kun ','He ','He ','Mo ','Han ','Mao ','Li ','Ni ','Bi ', + 'Yu ','Jia ','Tuan ','Mao ','Pi ','Xi ','E ','Ju ','Mo ','Chu ','Tan ','Huan ','Jue ','Bei ','Zhen ','Yuan ', + 'Fu ','Cai ','Gong ','Te ','Yi ','Hang ','Wan ','Pin ','Huo ','Fan ','Tan ','Guan ','Ze ','Zhi ','Er ','Zhu ', + 'Shi ','Bi ','Zi ','Er ','Gui ','Pian ','Bian ','Mai ','Dai ','Sheng ','Kuang ','Fei ','Tie ','Yi ','Chi ','Mao ', + 'He ','Bi ','Lu ','Lin ','Hui ','Gai ','Pian ','Zi ','Jia ','Xu ','Zei ','Jiao ','Gai ','Zang ','Jian ','Ying ', + 'Xun ','Zhen ','She ','Bin ','Bin ','Qiu ','She ','Chuan ','Zang ','Zhou ','Lai ','Zan ','Ci ','Chen ','Shang ','Tian ', + 'Pei ','Geng ','Xian ','Mai ','Jian ','Sui ','Fu ','Tan ','Cong ','Cong ','Zhi ','Ji ','Zhang ','Du ','Jin ','Xiong ', + 'Shun ','Yun ','Bao ','Zai ','Lai ','Feng ','Cang ','Ji ','Sheng ','Ai ','Zhuan ','Fu ','Gou ','Sai ','Ze ','Liao ', + ], + 'x8d':[ + 'Wei ','Bai ','Chen ','Zhuan ','Zhi ','Zhui ','Biao ','Yun ','Zeng ','Tan ','Zan ','Yan ','','Shan ','Wan ','Ying ', + 'Jin ','Gan ','Xian ','Zang ','Bi ','Du ','Shu ','Yan ','','Xuan ','Long ','Gan ','Zang ','Bei ','Zhen ','Fu ', + 'Yuan ','Gong ','Cai ','Ze ','Xian ','Bai ','Zhang ','Huo ','Zhi ','Fan ','Tan ','Pin ','Bian ','Gou ','Zhu ','Guan ', + 'Er ','Jian ','Bi ','Shi ','Tie ','Gui ','Kuang ','Dai ','Mao ','Fei ','He ','Yi ','Zei ','Zhi ','Jia ','Hui ', + 'Zi ','Ren ','Lu ','Zang ','Zi ','Gai ','Jin ','Qiu ','Zhen ','Lai ','She ','Fu ','Du ','Ji ','Shu ','Shang ', + 'Si ','Bi ','Zhou ','Geng ','Pei ','Tan ','Lai ','Feng ','Zhui ','Fu ','Zhuan ','Sai ','Ze ','Yan ','Zan ','Yun ', + 'Zeng ','Shan ','Ying ','Gan ','Chi ','Xi ','She ','Nan ','Xiong ','Xi ','Cheng ','He ','Cheng ','Zhe ','Xia ','Tang ', + 'Zou ','Zou ','Li ','Jiu ','Fu ','Zhao ','Gan ','Qi ','Shan ','Qiong ','Qin ','Xian ','Ci ','Jue ','Qin ','Chi ', + 'Ci ','Chen ','Chen ','Die ','Ju ','Chao ','Di ','Se ','Zhan ','Zhu ','Yue ','Qu ','Jie ','Chi ','Chu ','Gua ', + 'Xue ','Ci ','Tiao ','Duo ','Lie ','Gan ','Suo ','Cu ','Xi ','Zhao ','Su ','Yin ','Ju ','Jian ','Que ','Tang ', + 'Chuo ','Cui ','Lu ','Qu ','Dang ','Qiu ','Zi ','Ti ','Qu ','Chi ','Huang ','Qiao ','Qiao ','Yao ','Zao ','Ti ', + '','Zan ','Zan ','Zu ','Pa ','Bao ','Ku ','Ke ','Dun ','Jue ','Fu ','Chen ','Jian ','Fang ','Zhi ','Sa ', + 'Yue ','Pa ','Qi ','Yue ','Qiang ','Tuo ','Tai ','Yi ','Nian ','Ling ','Mei ','Ba ','Die ','Ku ','Tuo ','Jia ', + 'Ci ','Pao ','Qia ','Zhu ','Ju ','Die ','Zhi ','Fu ','Pan ','Ju ','Shan ','Bo ','Ni ','Ju ','Li ','Gen ', + 'Yi ','Ji ','Dai ','Xian ','Jiao ','Duo ','Zhu ','Quan ','Kua ','Zhuai ','Gui ','Qiong ','Kui ','Xiang ','Chi ','Lu ', + 'Beng ','Zhi ','Jia ','Tiao ','Cai ','Jian ','Ta ','Qiao ','Bi ','Xian ','Duo ','Ji ','Ju ','Ji ','Shu ','Tu ', + ], + 'x8e':[ + 'Chu ','Jing ','Nie ','Xiao ','Bo ','Chi ','Qun ','Mou ','Shu ','Lang ','Yong ','Jiao ','Chou ','Qiao ','Mau ','Ta ', + 'Jian ','Qi ','Wo ','Wei ','Zhuo ','Jie ','Ji ','Nie ','Ju ','Ju ','Lun ','Lu ','Leng ','Huai ','Ju ','Chi ', + 'Wan ','Quan ','Ti ','Bo ','Zu ','Qie ','Ji ','Cu ','Zong ','Cai ','Zong ','Peng ','Zhi ','Zheng ','Dian ','Zhi ', + 'Yu ','Duo ','Dun ','Chun ','Yong ','Zhong ','Di ','Zhe ','Chen ','Chuai ','Jian ','Gua ','Tang ','Ju ','Fu ','Zu ', + 'Die ','Pian ','Rou ','Nuo ','Ti ','Cha ','Tui ','Jian ','Dao ','Cuo ','Xi ','Ta ','Qiang ','Zhan ','Dian ','Ti ', + 'Ji ','Nie ','Man ','Liu ','Zhan ','Bi ','Chong ','Lu ','Liao ','Cu ','Tang ','Dai ','Suo ','Xi ','Kui ','Ji ', + 'Zhi ','Qiang ','Di ','Pan ','Zong ','Lian ','Beng ','Zao ','Nian ','Bie ','Tui ','Ju ','Deng ','Ceng ','Xian ','Fan ', + 'Chu ','Zhong ','Dun ','Bo ','Cu ','Zu ','Jue ','Jue ','Lin ','Ta ','Qiao ','Qiao ','Pu ','Liao ','Dun ','Cuan ', + 'Kuang ','Zao ','Ta ','Bi ','Bi ','Zhu ','Ju ','Chu ','Qiao ','Dun ','Chou ','Ji ','Wu ','Yue ','Nian ','Lin ', + 'Lie ','Zhi ','Li ','Zhi ','Chan ','Chu ','Duan ','Wei ','Long ','Lin ','Xian ','Wei ','Zuan ','Lan ','Xie ','Rang ', + 'Xie ','Nie ','Ta ','Qu ','Jie ','Cuan ','Zuan ','Xi ','Kui ','Jue ','Lin ','Shen ','Gong ','Dan ','Segare ','Qu ', + 'Ti ','Duo ','Duo ','Gong ','Lang ','Nerau ','Luo ','Ai ','Ji ','Ju ','Tang ','Utsuke ','','Yan ','Shitsuke ','Kang ', + 'Qu ','Lou ','Lao ','Tuo ','Zhi ','Yagate ','Ti ','Dao ','Yagate ','Yu ','Che ','Ya ','Gui ','Jun ','Wei ','Yue ', + 'Xin ','Di ','Xuan ','Fan ','Ren ','Shan ','Qiang ','Shu ','Tun ','Chen ','Dai ','E ','Na ','Qi ','Mao ','Ruan ', + 'Ren ','Fan ','Zhuan ','Hong ','Hu ','Qu ','Huang ','Di ','Ling ','Dai ','Ao ','Zhen ','Fan ','Kuang ','Ang ','Peng ', + 'Bei ','Gu ','Gu ','Pao ','Zhu ','Rong ','E ','Ba ','Zhou ','Zhi ','Yao ','Ke ','Yi ','Qing ','Shi ','Ping ', + ], + 'x8f':[ + 'Er ','Qiong ','Ju ','Jiao ','Guang ','Lu ','Kai ','Quan ','Zhou ','Zai ','Zhi ','She ','Liang ','Yu ','Shao ','You ', + 'Huan ','Yun ','Zhe ','Wan ','Fu ','Qing ','Zhou ','Ni ','Ling ','Zhe ','Zhan ','Liang ','Zi ','Hui ','Wang ','Chuo ', + 'Guo ','Kan ','Yi ','Peng ','Qian ','Gun ','Nian ','Pian ','Guan ','Bei ','Lun ','Pai ','Liang ','Ruan ','Rou ','Ji ', + 'Yang ','Xian ','Chuan ','Cou ','Chun ','Ge ','You ','Hong ','Shu ','Fu ','Zi ','Fu ','Wen ','Ben ','Zhan ','Yu ', + 'Wen ','Tao ','Gu ','Zhen ','Xia ','Yuan ','Lu ','Jiu ','Chao ','Zhuan ','Wei ','Hun ','Sori ','Che ','Jiao ','Zhan ', + 'Pu ','Lao ','Fen ','Fan ','Lin ','Ge ','Se ','Kan ','Huan ','Yi ','Ji ','Dui ','Er ','Yu ','Xian ','Hong ', + 'Lei ','Pei ','Li ','Li ','Lu ','Lin ','Che ','Ya ','Gui ','Xuan ','Di ','Ren ','Zhuan ','E ','Lun ','Ruan ', + 'Hong ','Gu ','Ke ','Lu ','Zhou ','Zhi ','Yi ','Hu ','Zhen ','Li ','Yao ','Qing ','Shi ','Zai ','Zhi ','Jiao ', + 'Zhou ','Quan ','Lu ','Jiao ','Zhe ','Fu ','Liang ','Nian ','Bei ','Hui ','Gun ','Wang ','Liang ','Chuo ','Zi ','Cou ', + 'Fu ','Ji ','Wen ','Shu ','Pei ','Yuan ','Xia ','Zhan ','Lu ','Che ','Lin ','Xin ','Gu ','Ci ','Ci ','Pi ', + 'Zui ','Bian ','La ','La ','Ci ','Xue ','Ban ','Bian ','Bian ','Bian ','','Bian ','Ban ','Ci ','Bian ','Bian ', + 'Chen ','Ru ','Nong ','Nong ','Zhen ','Chuo ','Chuo ','Suberu ','Reng ','Bian ','Bian ','Sip ','Ip ','Liao ','Da ','Chan ', + 'Gan ','Qian ','Yu ','Yu ','Qi ','Xun ','Yi ','Guo ','Mai ','Qi ','Za ','Wang ','tu ','Zhun ','Ying ','Ti ', + 'Yun ','Jin ','Hang ','Ya ','Fan ','Wu ','Da ','E ','Huan ','Zhe ','Totemo ','Jin ','Yuan ','Wei ','Lian ','Chi ', + 'Che ','Ni ','Tiao ','Zhi ','Yi ','Jiong ','Jia ','Chen ','Dai ','Er ','Di ','Po ','Wang ','Die ','Ze ','Tao ', + 'Shu ','Tuo ','Kep ','Jing ','Hui ','Tong ','You ','Mi ','Beng ','Ji ','Nai ','Yi ','Jie ','Zhui ','Lie ','Xun ', + ], + 'x90':[ + 'Tui ','Song ','Shi ','Tao ','Pang ','Hou ','Ni ','Dun ','Jiong ','Xuan ','Xun ','Bu ','You ','Xiao ','Qiu ','Tou ', + 'Zhu ','Qiu ','Di ','Di ','Tu ','Jing ','Ti ','Dou ','Yi ','Zhe ','Tong ','Guang ','Wu ','Shi ','Cheng ','Su ', + 'Zao ','Qun ','Feng ','Lian ','Suo ','Hui ','Li ','Sako ','Lai ','Ben ','Cuo ','Jue ','Beng ','Huan ','Dai ','Lu ', + 'You ','Zhou ','Jin ','Yu ','Chuo ','Kui ','Wei ','Ti ','Yi ','Da ','Yuan ','Luo ','Bi ','Nuo ','Yu ','Dang ', + 'Sui ','Dun ','Sui ','Yan ','Chuan ','Chi ','Ti ','Yu ','Shi ','Zhen ','You ','Yun ','E ','Bian ','Guo ','E ', + 'Xia ','Huang ','Qiu ','Dao ','Da ','Wei ','Appare ','Yi ','Gou ','Yao ','Chu ','Liu ','Xun ','Ta ','Di ','Chi ', + 'Yuan ','Su ','Ta ','Qian ','','Yao ','Guan ','Zhang ','Ao ','Shi ','Ce ','Chi ','Su ','Zao ','Zhe ','Dun ', + 'Di ','Lou ','Chi ','Cuo ','Lin ','Zun ','Rao ','Qian ','Xuan ','Yu ','Yi ','Wu ','Liao ','Ju ','Shi ','Bi ', + 'Yao ','Mai ','Xie ','Sui ','Huan ','Zhan ','Teng ','Er ','Miao ','Bian ','Bian ','La ','Li ','Yuan ','Yao ','Luo ', + 'Li ','Yi ','Ting ','Deng ','Qi ','Yong ','Shan ','Han ','Yu ','Mang ','Ru ','Qiong ','','Kuang ','Fu ','Kang ', + 'Bin ','Fang ','Xing ','Na ','','Shen ','Bang ','Yuan ','Cun ','Huo ','Xie ','Bang ','Wu ','Ju ','You ','Han ', + 'Tai ','Qiu ','Bi ','Pei ','Bing ','Shao ','Bei ','Wa ','Di ','Zou ','Ye ','Lin ','Kuang ','Gui ','Zhu ','Shi ', + 'Ku ','Yu ','Gai ','He ','Xi ','Zhi ','Ji ','Xun ','Hou ','Xing ','Jiao ','Xi ','Gui ','Nuo ','Lang ','Jia ', + 'Kuai ','Zheng ','Rou ','Yun ','Yan ','Cheng ','Dou ','Chi ','Lu ','Fu ','Wu ','Fu ','Gao ','Hao ','Lang ','Jia ', + 'Geng ','Jun ','Ying ','Bo ','Xi ','Bei ','Li ','Yun ','Bu ','Xiao ','Qi ','Pi ','Qing ','Guo ','','Tan ', + 'Zou ','Ping ','Lai ','Ni ','Chen ','You ','Bu ','Xiang ','Dan ','Ju ','Yong ','Qiao ','Yi ','Du ','Yan ','Mei ', + ], + 'x91':[ + 'Ruo ','Bei ','E ','Yu ','Juan ','Yu ','Yun ','Hou ','Kui ','Xiang ','Xiang ','Sou ','Tang ','Ming ','Xi ','Ru ', + 'Chu ','Zi ','Zou ','Ju ','Wu ','Xiang ','Yun ','Hao ','Yong ','Bi ','Mo ','Chao ','Fu ','Liao ','Yin ','Zhuan ', + 'Hu ','Qiao ','Yan ','Zhang ','Man ','Qiao ','Xu ','Deng ','Bi ','Xin ','Bi ','Ceng ','Wei ','Zheng ','Mao ','Shan ', + 'Lin ','Po ','Dan ','Meng ','Ye ','Cao ','Kuai ','Feng ','Meng ','Zou ','Kuang ','Lian ','Zan ','Chan ','You ','Qi ', + 'Yan ','Chan ','Zan ','Ling ','Huan ','Xi ','Feng ','Zan ','Li ','You ','Ding ','Qiu ','Zhuo ','Pei ','Zhou ','Yi ', + 'Hang ','Yu ','Jiu ','Yan ','Zui ','Mao ','Dan ','Xu ','Tou ','Zhen ','Fen ','Sakenomoto ','','Yun ','Tai ','Tian ', + 'Qia ','Tuo ','Zuo ','Han ','Gu ','Su ','Po ','Chou ','Zai ','Ming ','Lao ','Chuo ','Chou ','You ','Tong ','Zhi ', + 'Xian ','Jiang ','Cheng ','Yin ','Tu ','Jiao ','Mei ','Ku ','Suan ','Lei ','Pu ','Zui ','Hai ','Yan ','Xi ','Niang ', + 'Wei ','Lu ','Lan ','Yan ','Tao ','Pei ','Zhan ','Chun ','Tan ','Zui ','Chuo ','Cu ','Kun ','Ti ','Mian ','Du ', + 'Hu ','Xu ','Xing ','Tan ','Jiu ','Chun ','Yun ','Po ','Ke ','Sou ','Mi ','Quan ','Chou ','Cuo ','Yun ','Yong ', + 'Ang ','Zha ','Hai ','Tang ','Jiang ','Piao ','Shan ','Yu ','Li ','Zao ','Lao ','Yi ','Jiang ','Bu ','Jiao ','Xi ', + 'Tan ','Po ','Nong ','Yi ','Li ','Ju ','Jiao ','Yi ','Niang ','Ru ','Xun ','Chou ','Yan ','Ling ','Mi ','Mi ', + 'Niang ','Xin ','Jiao ','Xi ','Mi ','Yan ','Bian ','Cai ','Shi ','You ','Shi ','Shi ','Li ','Zhong ','Ye ','Liang ', + 'Li ','Jin ','','Ga ','Yi ','Liao ','Dao ','Zhao ','Ding ','Po ','Qiu ','He ','Fu ','Zhen ','Zhi ','Ba ', + 'Luan ','Fu ','Nai ','Diao ','Shan ','Qiao ','Kou ','Chuan ','Zi ','Fan ','Yu ','Hua ','Han ','Gang ','Qi ','Mang ', + 'Ri ','Di ','Si ','Xi ','Yi ','Chai ','Shi ','Tu ','Xi ','Nu ','Qian ','Kyuu ','Jian ','Pi ','Ye ','Yin ', + ], + 'x92':[ + 'Ba ','Fang ','Chen ','Xing ','Dou ','Yue ','Yan ','Fu ','Pi ','Na ','Xin ','E ','Jue ','Dun ','Gou ','Yin ', + 'Qian ','Ban ','Ji ','Ren ','Chao ','Niu ','Fen ','Yun ','Ji ','Qin ','Pi ','Guo ','Hong ','Yin ','Jun ','Shi ', + 'Yi ','Zhong ','Nie ','Gai ','Ri ','Huo ','Tai ','Kang ','Habaki ','Ro ','Ngaak ','','Duo ','Zi ','Ni ','Tu ', + 'Shi ','Min ','Gu ','Ke ','Ling ','Bing ','Yi ','Gu ','Bo ','Pi ','Yu ','Si ','Zuo ','Bu ','You ','Dian ', + 'Jia ','Zhen ','Shi ','Shi ','Tie ','Ju ','Chan ','Shi ','Shi ','Xuan ','Zhao ','Bao ','He ','Bi ','Sheng ','Chu ', + 'Shi ','Bo ','Zhu ','Chi ','Za ','Po ','Tong ','Qian ','Fu ','Zhai ','Liu ','Qian ','Fu ','Li ','Yue ','Pi ', + 'Yang ','Ban ','Bo ','Jie ','Gou ','Shu ','Zheng ','Mu ','Ni ','Nie ','Di ','Jia ','Mu ','Dan ','Shen ','Yi ', + 'Si ','Kuang ','Ka ','Bei ','Jian ','Tong ','Xing ','Hong ','Jiao ','Chi ','Er ','Ge ','Bing ','Shi ','Mou ','Ha ', + 'Yin ','Jun ','Zhou ','Chong ','Shang ','Tong ','Mo ','Lei ','Ji ','Yu ','Xu ','Ren ','Zun ','Zhi ','Qiong ','Shan ', + 'Chi ','Xian ','Xing ','Quan ','Pi ','Tie ','Zhu ','Hou ','Ming ','Kua ','Yao ','Xian ','Xian ','Xiu ','Jun ','Cha ', + 'Lao ','Ji ','Pi ','Ru ','Mi ','Yi ','Yin ','Guang ','An ','Diu ','You ','Se ','Kao ','Qian ','Luan ','Kasugai ', + 'Ai ','Diao ','Han ','Rui ','Shi ','Keng ','Qiu ','Xiao ','Zhe ','Xiu ','Zang ','Ti ','Cuo ','Gua ','Gong ','Zhong ', + 'Dou ','Lu ','Mei ','Lang ','Wan ','Xin ','Yun ','Bei ','Wu ','Su ','Yu ','Chan ','Ting ','Bo ','Han ','Jia ', + 'Hong ','Cuan ','Feng ','Chan ','Wan ','Zhi ','Si ','Xuan ','Wu ','Wu ','Tiao ','Gong ','Zhuo ','Lue ','Xing ','Qian ', + 'Shen ','Han ','Lue ','Xie ','Chu ','Zheng ','Ju ','Xian ','Tie ','Mang ','Pu ','Li ','Pan ','Rui ','Cheng ','Gao ', + 'Li ','Te ','Pyeng ','Zhu ','','Tu ','Liu ','Zui ','Ju ','Chang ','Yuan ','Jian ','Gang ','Diao ','Tao ','Chang ', + ], + 'x93':[ + 'Lun ','Guo ','Ling ','Bei ','Lu ','Li ','Qiang ','Pou ','Juan ','Min ','Zui ','Peng ','An ','Pi ','Xian ','Ya ', + 'Zhui ','Lei ','A ','Kong ','Ta ','Kun ','Du ','Wei ','Chui ','Zi ','Zheng ','Ben ','Nie ','Cong ','Dui ','Tan ', + 'Ding ','Qi ','Qian ','Zhuo ','Qi ','Yu ','Jin ','Guan ','Mao ','Chang ','Tian ','Xi ','Lian ','Tao ','Gu ','Cuo ', + 'Shu ','Zhen ','Lu ','Meng ','Lu ','Hua ','Biao ','Ga ','Lai ','Ken ','Kazari ','Bu ','Nai ','Wan ','Zan ','', + 'De ','Xian ','','Huo ','Liang ','','Men ','Kai ','Ying ','Di ','Lian ','Guo ','Xian ','Du ','Tu ','Wei ', + 'Cong ','Fu ','Rou ','Ji ','E ','Rou ','Chen ','Ti ','Zha ','Hong ','Yang ','Duan ','Xia ','Yu ','Keng ','Xing ', + 'Huang ','Wei ','Fu ','Zhao ','Cha ','Qie ','She ','Hong ','Kui ','Tian ','Mou ','Qiao ','Qiao ','Hou ','Tou ','Cong ', + 'Huan ','Ye ','Min ','Jian ','Duan ','Jian ','Si ','Kui ','Hu ','Xuan ','Zhe ','Jie ','Zhen ','Bian ','Zhong ','Zi ', + 'Xiu ','Ye ','Mei ','Pai ','Ai ','Jie ','','Mei ','Chuo ','Ta ','Bang ','Xia ','Lian ','Suo ','Xi ','Liu ', + 'Zu ','Ye ','Nou ','Weng ','Rong ','Tang ','Suo ','Qiang ','Ge ','Shuo ','Chui ','Bo ','Pan ','Sa ','Bi ','Sang ', + 'Gang ','Zi ','Wu ','Ying ','Huang ','Tiao ','Liu ','Kai ','Sun ','Sha ','Sou ','Wan ','Hao ','Zhen ','Zhen ','Luo ', + 'Yi ','Yuan ','Tang ','Nie ','Xi ','Jia ','Ge ','Ma ','Juan ','Kasugai ','Habaki ','Suo ','','','','Na ', + 'Lu ','Suo ','Ou ','Zu ','Tuan ','Xiu ','Guan ','Xuan ','Lian ','Shou ','Ao ','Man ','Mo ','Luo ','Bi ','Wei ', + 'Liu ','Di ','Qiao ','Cong ','Yi ','Lu ','Ao ','Keng ','Qiang ','Cui ','Qi ','Chang ','Tang ','Man ','Yong ','Chan ', + 'Feng ','Jing ','Biao ','Shu ','Lou ','Xiu ','Cong ','Long ','Zan ','Jian ','Cao ','Li ','Xia ','Xi ','Kang ','', + 'Beng ','','','Zheng ','Lu ','Hua ','Ji ','Pu ','Hui ','Qiang ','Po ','Lin ','Suo ','Xiu ','San ','Cheng ', + ], + 'x94':[ + 'Kui ','Si ','Liu ','Nao ','Heng ','Pie ','Sui ','Fan ','Qiao ','Quan ','Yang ','Tang ','Xiang ','Jue ','Jiao ','Zun ', + 'Liao ','Jie ','Lao ','Dui ','Tan ','Zan ','Ji ','Jian ','Zhong ','Deng ','Ya ','Ying ','Dui ','Jue ','Nou ','Ti ', + 'Pu ','Tie ','','','Ding ','Shan ','Kai ','Jian ','Fei ','Sui ','Lu ','Juan ','Hui ','Yu ','Lian ','Zhuo ', + 'Qiao ','Qian ','Zhuo ','Lei ','Bi ','Tie ','Huan ','Ye ','Duo ','Guo ','Dang ','Ju ','Fen ','Da ','Bei ','Yi ', + 'Ai ','Zong ','Xun ','Diao ','Zhu ','Heng ','Zhui ','Ji ','Nie ','Ta ','Huo ','Qing ','Bin ','Ying ','Kui ','Ning ', + 'Xu ','Jian ','Jian ','Yari ','Cha ','Zhi ','Mie ','Li ','Lei ','Ji ','Zuan ','Kuang ','Shang ','Peng ','La ','Du ', + 'Shuo ','Chuo ','Lu ','Biao ','Bao ','Lu ','','Thoa ','Long ','E ','Lu ','Xin ','Jian ','Lan ','Bo ','Jian ', + 'Yao ','Chan ','Xiang ','Jian ','Xi ','Guan ','Cang ','Nie ','Lei ','Cuan ','Qu ','Pan ','Luo ','Zuan ','Luan ','Zao ', + 'Nie ','Jue ','Tang ','Shu ','Lan ','Jin ','Qiu ','Yi ','Zhen ','Ding ','Zhao ','Po ','Diao ','Tu ','Qian ','Chuan ', + 'Shan ','Ji ','Fan ','Diao ','Men ','Nu ','Xi ','Chai ','Xing ','Gai ','Bu ','Tai ','Ju ','Dun ','Chao ','Zhong ', + 'Na ','Bei ','Gang ','Ban ','Qian ','Yao ','Qin ','Jun ','Wu ','Gou ','Kang ','Fang ','Huo ','Dou ','Niu ','Ba ', + 'Yu ','Qian ','Zheng ','Qian ','Gu ','Bo ','E ','Po ','Bu ','Ba ','Yue ','Zuan ','Mu ','Dan ','Jia ','Dian ', + 'You ','Tie ','Bo ','Ling ','Shuo ','Qian ','Liu ','Bao ','Shi ','Xuan ','She ','Bi ','Ni ','Pi ','Duo ','Xing ', + 'Kao ','Lao ','Er ','Mang ','Ya ','You ','Cheng ','Jia ','Ye ','Nao ','Zhi ','Dang ','Tong ','Lu ','Diao ','Yin ', + 'Kai ','Zha ','Zhu ','Xian ','Ting ','Diu ','Xian ','Hua ','Quan ','Sha ','Jia ','Yao ','Ge ','Ming ','Zheng ','Se ', + 'Jiao ','Yi ','Chan ','Chong ','Tang ','An ','Yin ','Ru ','Zhu ','Lao ','Pu ','Wu ','Lai ','Te ','Lian ','Keng ', + ], + 'x95':[ + 'Xiao ','Suo ','Li ','Zheng ','Chu ','Guo ','Gao ','Tie ','Xiu ','Cuo ','Lue ','Feng ','Xin ','Liu ','Kai ','Jian ', + 'Rui ','Ti ','Lang ','Qian ','Ju ','A ','Qiang ','Duo ','Tian ','Cuo ','Mao ','Ben ','Qi ','De ','Kua ','Kun ', + 'Chang ','Xi ','Gu ','Luo ','Chui ','Zhui ','Jin ','Zhi ','Xian ','Juan ','Huo ','Pou ','Tan ','Ding ','Jian ','Ju ', + 'Meng ','Zi ','Qie ','Ying ','Kai ','Qiang ','Song ','E ','Cha ','Qiao ','Zhong ','Duan ','Sou ','Huang ','Huan ','Ai ', + 'Du ','Mei ','Lou ','Zi ','Fei ','Mei ','Mo ','Zhen ','Bo ','Ge ','Nie ','Tang ','Juan ','Nie ','Na ','Liu ', + 'Hao ','Bang ','Yi ','Jia ','Bin ','Rong ','Biao ','Tang ','Man ','Luo ','Beng ','Yong ','Jing ','Di ','Zu ','Xuan ', + 'Liu ','Tan ','Jue ','Liao ','Pu ','Lu ','Dui ','Lan ','Pu ','Cuan ','Qiang ','Deng ','Huo ','Lei ','Huan ','Zhuo ', + 'Lian ','Yi ','Cha ','Biao ','La ','Chan ','Xiang ','Chang ','Chang ','Jiu ','Ao ','Die ','Qu ','Liao ','Mi ','Chang ', + 'Men ','Ma ','Shuan ','Shan ','Huo ','Men ','Yan ','Bi ','Han ','Bi ','San ','Kai ','Kang ','Beng ','Hong ','Run ', + 'San ','Xian ','Xian ','Jian ','Min ','Xia ','Yuru ','Dou ','Zha ','Nao ','','Peng ','Xia ','Ling ','Bian ','Bi ', + 'Run ','He ','Guan ','Ge ','Ge ','Fa ','Chu ','Hong ','Gui ','Min ','Hai ','Kun ','Lang ','Lu ','Ting ','Sha ', + 'Ju ','Yue ','Yue ','Chan ','Qu ','Lin ','Chang ','Shai ','Kun ','Yan ','Wen ','Yan ','E ','Hun ','Yu ','Wen ', + 'Xiang ','Bao ','Xiang ','Qu ','Yao ','Wen ','Ban ','An ','Wei ','Yin ','Kuo ','Que ','Lan ','Du ','','Phwung ', + 'Tian ','Nie ','Ta ','Kai ','He ','Que ','Chuang ','Guan ','Dou ','Qi ','Kui ','Tang ','Guan ','Piao ','Kan ','Xi ', + 'Hui ','Chan ','Pi ','Dang ','Huan ','Ta ','Wen ','','Men ','Shuan ','Shan ','Yan ','Han ','Bi ','Wen ','Chuang ', + 'Run ','Wei ','Xian ','Hong ','Jian ','Min ','Kang ','Men ','Zha ','Nao ','Gui ','Wen ','Ta ','Min ','Lu ','Kai ', + ], + 'x96':[ + 'Fa ','Ge ','He ','Kun ','Jiu ','Yue ','Lang ','Du ','Yu ','Yan ','Chang ','Xi ','Wen ','Hun ','Yan ','E ', + 'Chan ','Lan ','Qu ','Hui ','Kuo ','Que ','Ge ','Tian ','Ta ','Que ','Kan ','Huan ','Fu ','Fu ','Le ','Dui ', + 'Xin ','Qian ','Wu ','Yi ','Tuo ','Yin ','Yang ','Dou ','E ','Sheng ','Ban ','Pei ','Keng ','Yun ','Ruan ','Zhi ', + 'Pi ','Jing ','Fang ','Yang ','Yin ','Zhen ','Jie ','Cheng ','E ','Qu ','Di ','Zu ','Zuo ','Dian ','Ling ','A ', + 'Tuo ','Tuo ','Bei ','Bing ','Fu ','Ji ','Lu ','Long ','Chen ','Xing ','Duo ','Lou ','Mo ','Jiang ','Shu ','Duo ', + 'Xian ','Er ','Gui ','Yu ','Gai ','Shan ','Xun ','Qiao ','Xing ','Chun ','Fu ','Bi ','Xia ','Shan ','Sheng ','Zhi ', + 'Pu ','Dou ','Yuan ','Zhen ','Chu ','Xian ','Tou ','Nie ','Yun ','Xian ','Pei ','Pei ','Zou ','Yi ','Dui ','Lun ', + 'Yin ','Ju ','Chui ','Chen ','Pi ','Ling ','Tao ','Xian ','Lu ','','Xian ','Yin ','Zhu ','Yang ','Reng ','Shan ', + 'Chong ','Yan ','Yin ','Yu ','Di ','Yu ','Long ','Wei ','Wei ','Nie ','Dui ','Sui ','An ','Huang ','Jie ','Sui ', + 'Yin ','Gai ','Yan ','Hui ','Ge ','Yun ','Wu ','Wei ','Ai ','Xi ','Tang ','Ji ','Zhang ','Dao ','Ao ','Xi ', + 'Yin ','','Rao ','Lin ','Tui ','Deng ','Pi ','Sui ','Sui ','Yu ','Xian ','Fen ','Ni ','Er ','Ji ','Dao ', + 'Xi ','Yin ','E ','Hui ','Long ','Xi ','Li ','Li ','Li ','Zhui ','He ','Zhi ','Zhun ','Jun ','Nan ','Yi ', + 'Que ','Yan ','Qin ','Ya ','Xiong ','Ya ','Ji ','Gu ','Huan ','Zhi ','Gou ','Jun ','Ci ','Yong ','Ju ','Chu ', + 'Hu ','Za ','Luo ','Yu ','Chou ','Diao ','Sui ','Han ','Huo ','Shuang ','Guan ','Chu ','Za ','Yong ','Ji ','Xi ', + 'Chou ','Liu ','Li ','Nan ','Xue ','Za ','Ji ','Ji ','Yu ','Yu ','Xue ','Na ','Fou ','Se ','Mu ','Wen ', + 'Fen ','Pang ','Yun ','Li ','Li ','Ang ','Ling ','Lei ','An ','Bao ','Meng ','Dian ','Dang ','Xing ','Wu ','Zhao ', + ], + 'x97':[ + 'Xu ','Ji ','Mu ','Chen ','Xiao ','Zha ','Ting ','Zhen ','Pei ','Mei ','Ling ','Qi ','Chou ','Huo ','Sha ','Fei ', + 'Weng ','Zhan ','Yin ','Ni ','Zhu ','Tun ','Lin ','','Dong ','Ying ','Wu ','Ling ','Shuang ','Ling ','Xia ','Hong ', + 'Yin ','Mo ','Mai ','Yun ','Liu ','Meng ','Bin ','Wu ','Wei ','Huo ','Yin ','Xi ','Yi ','Ai ','Dan ','Deng ', + 'Xian ','Yu ','Lu ','Long ','Dai ','Ji ','Pang ','Yang ','Ba ','Pi ','Wei ','','Xi ','Ji ','Mai ','Meng ', + 'Meng ','Lei ','Li ','Huo ','Ai ','Fei ','Dai ','Long ','Ling ','Ai ','Feng ','Li ','Bao ','','He ','He ', + 'Bing ','Qing ','Qing ','Jing ','Tian ','Zhen ','Jing ','Cheng ','Qing ','Jing ','Jing ','Dian ','Jing ','Tian ','Fei ','Fei ', + 'Kao ','Mi ','Mian ','Mian ','Pao ','Ye ','Tian ','Hui ','Ye ','Ge ','Ding ','Cha ','Jian ','Ren ','Di ','Du ', + 'Wu ','Ren ','Qin ','Jin ','Xue ','Niu ','Ba ','Yin ','Sa ','Na ','Mo ','Zu ','Da ','Ban ','Yi ','Yao ', + 'Tao ','Tuo ','Jia ','Hong ','Pao ','Yang ','Tomo ','Yin ','Jia ','Tao ','Ji ','Xie ','An ','An ','Hen ','Gong ', + 'Kohaze ','Da ','Qiao ','Ting ','Wan ','Ying ','Sui ','Tiao ','Qiao ','Xuan ','Kong ','Beng ','Ta ','Zhang ','Bing ','Kuo ', + 'Ju ','La ','Xie ','Rou ','Bang ','Yi ','Qiu ','Qiu ','He ','Xiao ','Mu ','Ju ','Jian ','Bian ','Di ','Jian ', + 'On ','Tao ','Gou ','Ta ','Bei ','Xie ','Pan ','Ge ','Bi ','Kuo ','Tou ','Lou ','Gui ','Qiao ','Xue ','Ji ', + 'Jian ','Jiang ','Chan ','Da ','Huo ','Xian ','Qian ','Du ','Wa ','Jian ','Lan ','Wei ','Ren ','Fu ','Mei ','Juan ', + 'Ge ','Wei ','Qiao ','Han ','Chang ','','Rou ','Xun ','She ','Wei ','Ge ','Bei ','Tao ','Gou ','Yun ','', + 'Bi ','Wei ','Hui ','Du ','Wa ','Du ','Wei ','Ren ','Fu ','Han ','Wei ','Yun ','Tao ','Jiu ','Jiu ','Xian ', + 'Xie ','Xian ','Ji ','Yin ','Za ','Yun ','Shao ','Le ','Peng ','Heng ','Ying ','Yun ','Peng ','Yin ','Yin ','Xiang ', + ], + 'x98':[ + 'Hu ','Ye ','Ding ','Qing ','Kui ','Xiang ','Shun ','Han ','Xu ','Yi ','Xu ','Gu ','Song ','Kui ','Qi ','Hang ', + 'Yu ','Wan ','Ban ','Dun ','Di ','Dan ','Pan ','Po ','Ling ','Ce ','Jing ','Lei ','He ','Qiao ','E ','E ', + 'Wei ','Jie ','Gua ','Shen ','Yi ','Shen ','Hai ','Dui ','Pian ','Ping ','Lei ','Fu ','Jia ','Tou ','Hui ','Kui ', + 'Jia ','Le ','Ting ','Cheng ','Ying ','Jun ','Hu ','Han ','Jing ','Tui ','Tui ','Pin ','Lai ','Tui ','Zi ','Zi ', + 'Chui ','Ding ','Lai ','Yan ','Han ','Jian ','Ke ','Cui ','Jiong ','Qin ','Yi ','Sai ','Ti ','E ','E ','Yan ', + 'Hun ','Kan ','Yong ','Zhuan ','Yan ','Xian ','Xin ','Yi ','Yuan ','Sang ','Dian ','Dian ','Jiang ','Ku ','Lei ','Liao ', + 'Piao ','Yi ','Man ','Qi ','Rao ','Hao ','Qiao ','Gu ','Xun ','Qian ','Hui ','Zhan ','Ru ','Hong ','Bin ','Xian ', + 'Pin ','Lu ','Lan ','Nie ','Quan ','Ye ','Ding ','Qing ','Han ','Xiang ','Shun ','Xu ','Xu ','Wan ','Gu ','Dun ', + 'Qi ','Ban ','Song ','Hang ','Yu ','Lu ','Ling ','Po ','Jing ','Jie ','Jia ','Tian ','Han ','Ying ','Jiong ','Hai ', + 'Yi ','Pin ','Hui ','Tui ','Han ','Ying ','Ying ','Ke ','Ti ','Yong ','E ','Zhuan ','Yan ','E ','Nie ','Man ', + 'Dian ','Sang ','Hao ','Lei ','Zhan ','Ru ','Pin ','Quan ','Feng ','Biao ','Oroshi ','Fu ','Xia ','Zhan ','Biao ','Sa ', + 'Ba ','Tai ','Lie ','Gua ','Xuan ','Shao ','Ju ','Bi ','Si ','Wei ','Yang ','Yao ','Sou ','Kai ','Sao ','Fan ', + 'Liu ','Xi ','Liao ','Piao ','Piao ','Liu ','Biao ','Biao ','Biao ','Liao ','','Se ','Feng ','Biao ','Feng ','Yang ', + 'Zhan ','Biao ','Sa ','Ju ','Si ','Sou ','Yao ','Liu ','Piao ','Biao ','Biao ','Fei ','Fan ','Fei ','Fei ','Shi ', + 'Shi ','Can ','Ji ','Ding ','Si ','Tuo ','Zhan ','Sun ','Xiang ','Tun ','Ren ','Yu ','Juan ','Chi ','Yin ','Fan ', + 'Fan ','Sun ','Yin ','Zhu ','Yi ','Zhai ','Bi ','Jie ','Tao ','Liu ','Ci ','Tie ','Si ','Bao ','Shi ','Duo ', + ], + 'x99':[ + 'Hai ','Ren ','Tian ','Jiao ','Jia ','Bing ','Yao ','Tong ','Ci ','Xiang ','Yang ','Yang ','Er ','Yan ','Le ','Yi ', + 'Can ','Bo ','Nei ','E ','Bu ','Jun ','Dou ','Su ','Yu ','Shi ','Yao ','Hun ','Guo ','Shi ','Jian ','Zhui ', + 'Bing ','Xian ','Bu ','Ye ','Tan ','Fei ','Zhang ','Wei ','Guan ','E ','Nuan ','Hun ','Hu ','Huang ','Tie ','Hui ', + 'Jian ','Hou ','He ','Xing ','Fen ','Wei ','Gu ','Cha ','Song ','Tang ','Bo ','Gao ','Xi ','Kui ','Liu ','Sou ', + 'Tao ','Ye ','Yun ','Mo ','Tang ','Man ','Bi ','Yu ','Xiu ','Jin ','San ','Kui ','Zhuan ','Shan ','Chi ','Dan ', + 'Yi ','Ji ','Rao ','Cheng ','Yong ','Tao ','Hui ','Xiang ','Zhan ','Fen ','Hai ','Meng ','Yan ','Mo ','Chan ','Xiang ', + 'Luo ','Zuan ','Nang ','Shi ','Ding ','Ji ','Tuo ','Xing ','Tun ','Xi ','Ren ','Yu ','Chi ','Fan ','Yin ','Jian ', + 'Shi ','Bao ','Si ','Duo ','Yi ','Er ','Rao ','Xiang ','Jia ','Le ','Jiao ','Yi ','Bing ','Bo ','Dou ','E ', + 'Yu ','Nei ','Jun ','Guo ','Hun ','Xian ','Guan ','Cha ','Kui ','Gu ','Sou ','Chan ','Ye ','Mo ','Bo ','Liu ', + 'Xiu ','Jin ','Man ','San ','Zhuan ','Nang ','Shou ','Kui ','Guo ','Xiang ','Fen ','Ba ','Ni ','Bi ','Bo ','Tu ', + 'Han ','Fei ','Jian ','An ','Ai ','Fu ','Xian ','Wen ','Xin ','Fen ','Bin ','Xing ','Ma ','Yu ','Feng ','Han ', + 'Di ','Tuo ','Tuo ','Chi ','Xun ','Zhu ','Zhi ','Pei ','Xin ','Ri ','Sa ','Yin ','Wen ','Zhi ','Dan ','Lu ', + 'You ','Bo ','Bao ','Kuai ','Tuo ','Yi ','Qu ','','Qu ','Jiong ','Bo ','Zhao ','Yuan ','Peng ','Zhou ','Ju ', + 'Zhu ','Nu ','Ju ','Pi ','Zang ','Jia ','Ling ','Zhen ','Tai ','Fu ','Yang ','Shi ','Bi ','Tuo ','Tuo ','Si ', + 'Liu ','Ma ','Pian ','Tao ','Zhi ','Rong ','Teng ','Dong ','Xun ','Quan ','Shen ','Jiong ','Er ','Hai ','Bo ','', + 'Yin ','Luo ','Shuu ','Dan ','Xie ','Liu ','Ju ','Song ','Qin ','Mang ','Liang ','Han ','Tu ','Xuan ','Tui ','Jun ', + ], + 'x9a':[ + 'E ','Cheng ','Xing ','Ai ','Lu ','Zhui ','Zhou ','She ','Pian ','Kun ','Tao ','Lai ','Zong ','Ke ','Qi ','Qi ', + 'Yan ','Fei ','Sao ','Yan ','Jie ','Yao ','Wu ','Pian ','Cong ','Pian ','Qian ','Fei ','Huang ','Jian ','Huo ','Yu ', + 'Ti ','Quan ','Xia ','Zong ','Kui ','Rou ','Si ','Gua ','Tuo ','Kui ','Sou ','Qian ','Cheng ','Zhi ','Liu ','Pang ', + 'Teng ','Xi ','Cao ','Du ','Yan ','Yuan ','Zou ','Sao ','Shan ','Li ','Zhi ','Shuang ','Lu ','Xi ','Luo ','Zhang ', + 'Mo ','Ao ','Can ','Piao ','Cong ','Qu ','Bi ','Zhi ','Yu ','Xu ','Hua ','Bo ','Su ','Xiao ','Lin ','Chan ', + 'Dun ','Liu ','Tuo ','Zeng ','Tan ','Jiao ','Tie ','Yan ','Luo ','Zhan ','Jing ','Yi ','Ye ','Tuo ','Bin ','Zou ', + 'Yan ','Peng ','Lu ','Teng ','Xiang ','Ji ','Shuang ','Ju ','Xi ','Huan ','Li ','Biao ','Ma ','Yu ','Tuo ','Xun ', + 'Chi ','Qu ','Ri ','Bo ','Lu ','Zang ','Shi ','Si ','Fu ','Ju ','Zou ','Zhu ','Tuo ','Nu ','Jia ','Yi ', + 'Tai ','Xiao ','Ma ','Yin ','Jiao ','Hua ','Luo ','Hai ','Pian ','Biao ','Li ','Cheng ','Yan ','Xin ','Qin ','Jun ', + 'Qi ','Qi ','Ke ','Zhui ','Zong ','Su ','Can ','Pian ','Zhi ','Kui ','Sao ','Wu ','Ao ','Liu ','Qian ','Shan ', + 'Piao ','Luo ','Cong ','Chan ','Zou ','Ji ','Shuang ','Xiang ','Gu ','Wei ','Wei ','Wei ','Yu ','Gan ','Yi ','Ang ', + 'Tou ','Xie ','Bao ','Bi ','Chi ','Ti ','Di ','Ku ','Hai ','Qiao ','Gou ','Kua ','Ge ','Tui ','Geng ','Pian ', + 'Bi ','Ke ','Ka ','Yu ','Sui ','Lou ','Bo ','Xiao ','Pang ','Bo ','Ci ','Kuan ','Bin ','Mo ','Liao ','Lou ', + 'Nao ','Du ','Zang ','Sui ','Ti ','Bin ','Kuan ','Lu ','Gao ','Gao ','Qiao ','Kao ','Qiao ','Lao ','Zao ','Biao ', + 'Kun ','Kun ','Ti ','Fang ','Xiu ','Ran ','Mao ','Dan ','Kun ','Bin ','Fa ','Tiao ','Pi ','Zi ','Fa ','Ran ', + 'Ti ','Pao ','Pi ','Mao ','Fu ','Er ','Rong ','Qu ','','Xiu ','Gua ','Ji ','Peng ','Zhua ','Shao ','Sha ', + ], + 'x9b':[ + 'Ti ','Li ','Bin ','Zong ','Ti ','Peng ','Song ','Zheng ','Quan ','Zong ','Shun ','Jian ','Duo ','Hu ','La ','Jiu ', + 'Qi ','Lian ','Zhen ','Bin ','Peng ','Mo ','San ','Man ','Man ','Seng ','Xu ','Lie ','Qian ','Qian ','Nong ','Huan ', + 'Kuai ','Ning ','Bin ','Lie ','Rang ','Dou ','Dou ','Nao ','Hong ','Xi ','Dou ','Han ','Dou ','Dou ','Jiu ','Chang ', + 'Yu ','Yu ','Li ','Juan ','Fu ','Qian ','Gui ','Zong ','Liu ','Gui ','Shang ','Yu ','Gui ','Mei ','Ji ','Qi ', + 'Jie ','Kui ','Hun ','Ba ','Po ','Mei ','Xu ','Yan ','Xiao ','Liang ','Yu ','Tui ','Qi ','Wang ','Liang ','Wei ', + 'Jian ','Chi ','Piao ','Bi ','Mo ','Ji ','Xu ','Chou ','Yan ','Zhan ','Yu ','Dao ','Ren ','Ji ','Eri ','Gong ', + 'Tuo ','Diao ','Ji ','Xu ','E ','E ','Sha ','Hang ','Tun ','Mo ','Jie ','Shen ','Fan ','Yuan ','Bi ','Lu ', + 'Wen ','Hu ','Lu ','Za ','Fang ','Fen ','Na ','You ','Namazu ','Todo ','He ','Xia ','Qu ','Han ','Pi ','Ling ', + 'Tuo ','Bo ','Qiu ','Ping ','Fu ','Bi ','Ji ','Wei ','Ju ','Diao ','Bo ','You ','Gun ','Pi ','Nian ','Xing ', + 'Tai ','Bao ','Fu ','Zha ','Ju ','Gu ','Kajika ','Tong ','','Ta ','Jie ','Shu ','Hou ','Xiang ','Er ','An ', + 'Wei ','Tiao ','Zhu ','Yin ','Lie ','Luo ','Tong ','Yi ','Qi ','Bing ','Wei ','Jiao ','Bu ','Gui ','Xian ','Ge ', + 'Hui ','Bora ','Mate ','Kao ','Gori ','Duo ','Jun ','Ti ','Mian ','Xiao ','Za ','Sha ','Qin ','Yu ','Nei ','Zhe ', + 'Gun ','Geng ','','Wu ','Qiu ','Ting ','Fu ','Wan ','Tiao ','Li ','Sha ','Sha ','Gao ','Meng ','Ugui ','Asari ', + 'Subashiri ','Kazunoko ','Yong ','Ni ','Zi ','Qi ','Qing ','Xiang ','Nei ','Chun ','Ji ','Diao ','Qie ','Gu ','Zhou ','Dong ', + 'Lai ','Fei ','Ni ','Yi ','Kun ','Lu ','Jiu ','Chang ','Jing ','Lun ','Ling ','Zou ','Li ','Meng ','Zong ','Zhi ', + 'Nian ','Shachi ','Dojou ','Sukesou ','Shi ','Shen ','Hun ','Shi ','Hou ','Xing ','Zhu ','La ','Zong ','Ji ','Bian ','Bian ', + ], + 'x9c':[ + 'Huan ','Quan ','Ze ','Wei ','Wei ','Yu ','Qun ','Rou ','Die ','Huang ','Lian ','Yan ','Qiu ','Qiu ','Jian ','Bi ', + 'E ','Yang ','Fu ','Sai ','Jian ','Xia ','Tuo ','Hu ','Muroaji ','Ruo ','Haraka ','Wen ','Jian ','Hao ','Wu ','Fang ', + 'Sao ','Liu ','Ma ','Shi ','Shi ','Guan ','Shi ','Teng ','Ta ','Yao ','Ge ','Rong ','Qian ','Qi ','Wen ','Ruo ', + 'Hatahata ','Lian ','Ao ','Le ','Hui ','Min ','Ji ','Tiao ','Qu ','Jian ','Sao ','Man ','Xi ','Qiu ','Biao ','Ji ', + 'Ji ','Zhu ','Jiang ','Qiu ','Zhuan ','Yong ','Zhang ','Kang ','Xue ','Bie ','Jue ','Qu ','Xiang ','Bo ','Jiao ','Xun ', + 'Su ','Huang ','Zun ','Shan ','Shan ','Fan ','Gui ','Lin ','Xun ','Miao ','Xi ','Eso ','Kyou ','Fen ','Guan ','Hou ', + 'Kuai ','Zei ','Sao ','Zhan ','Gan ','Gui ','Sheng ','Li ','Chang ','Hatahata ','Shiira ','Ai ','Ru ','Ji ','Xu ','Huo ', + 'Shiira ','Li ','Lie ','Li ','Mie ','Zhen ','Xiang ','E ','Lu ','Guan ','Li ','Xian ','Yu ','Dao ','Ji ','You ', + 'Tun ','Lu ','Fang ','Ba ','He ','Bo ','Ping ','Nian ','Lu ','You ','Zha ','Fu ','Bo ','Bao ','Hou ','Pi ', + 'Tai ','Gui ','Jie ','Kao ','Wei ','Er ','Tong ','Ze ','Hou ','Kuai ','Ji ','Jiao ','Xian ','Za ','Xiang ','Xun ', + 'Geng ','Li ','Lian ','Jian ','Li ','Shi ','Tiao ','Gun ','Sha ','Wan ','Jun ','Ji ','Yong ','Qing ','Ling ','Qi ', + 'Zou ','Fei ','Kun ','Chang ','Gu ','Ni ','Nian ','Diao ','Jing ','Shen ','Shi ','Zi ','Fen ','Die ','Bi ','Chang ', + 'Shi ','Wen ','Wei ','Sai ','E ','Qiu ','Fu ','Huang ','Quan ','Jiang ','Bian ','Sao ','Ao ','Qi ','Ta ','Yin ', + 'Yao ','Fang ','Jian ','Le ','Biao ','Xue ','Bie ','Man ','Min ','Yong ','Wei ','Xi ','Jue ','Shan ','Lin ','Zun ', + 'Huo ','Gan ','Li ','Zhan ','Guan ','Niao ','Yi ','Fu ','Li ','Jiu ','Bu ','Yan ','Fu ','Diao ','Ji ','Feng ', + 'Nio ','Gan ','Shi ','Feng ','Ming ','Bao ','Yuan ','Zhi ','Hu ','Qin ','Fu ','Fen ','Wen ','Jian ','Shi ','Yu ', + ], + 'x9d':[ + 'Fou ','Yao ','Jue ','Jue ','Pi ','Huan ','Zhen ','Bao ','Yan ','Ya ','Zheng ','Fang ','Feng ','Wen ','Ou ','Te ', + 'Jia ','Nu ','Ling ','Mie ','Fu ','Tuo ','Wen ','Li ','Bian ','Zhi ','Ge ','Yuan ','Zi ','Qu ','Xiao ','Chi ', + 'Dan ','Ju ','You ','Gu ','Zhong ','Yu ','Yang ','Rong ','Ya ','Tie ','Yu ','Shigi ','Ying ','Zhui ','Wu ','Er ', + 'Gua ','Ai ','Zhi ','Yan ','Heng ','Jiao ','Ji ','Lie ','Zhu ','Ren ','Yi ','Hong ','Luo ','Ru ','Mou ','Ge ', + 'Ren ','Jiao ','Xiu ','Zhou ','Zhi ','Luo ','Chidori ','Toki ','Ten ','Luan ','Jia ','Ji ','Yu ','Huan ','Tuo ','Bu ', + 'Wu ','Juan ','Yu ','Bo ','Xun ','Xun ','Bi ','Xi ','Jun ','Ju ','Tu ','Jing ','Ti ','E ','E ','Kuang ', + 'Hu ','Wu ','Shen ','Lai ','Ikaruga ','Kakesu ','Lu ','Ping ','Shu ','Fu ','An ','Zhao ','Peng ','Qin ','Qian ','Bei ', + 'Diao ','Lu ','Que ','Jian ','Ju ','Tu ','Ya ','Yuan ','Qi ','Li ','Ye ','Zhui ','Kong ','Zhui ','Kun ','Sheng ', + 'Qi ','Jing ','Yi ','Yi ','Jing ','Zi ','Lai ','Dong ','Qi ','Chun ','Geng ','Ju ','Qu ','Isuka ','Kikuitadaki ','Ji ', + 'Shu ','','Chi ','Miao ','Rou ','An ','Qiu ','Ti ','Hu ','Ti ','E ','Jie ','Mao ','Fu ','Chun ','Tu ', + 'Yan ','He ','Yuan ','Pian ','Yun ','Mei ','Hu ','Ying ','Dun ','Wu ','Ju ','Tsugumi ','Cang ','Fang ','Gu ','Ying ', + 'Yuan ','Xuan ','Weng ','Shi ','He ','Chu ','Tang ','Xia ','Ruo ','Liu ','Ji ','Gu ','Jian ','Zhun ','Han ','Zi ', + 'Zi ','Ni ','Yao ','Yan ','Ji ','Li ','Tian ','Kou ','Ti ','Ti ','Ni ','Tu ','Ma ','Jiao ','Gao ','Tian ', + 'Chen ','Li ','Zhuan ','Zhe ','Ao ','Yao ','Yi ','Ou ','Chi ','Zhi ','Liao ','Rong ','Lou ','Bi ','Shuang ','Zhuo ', + 'Yu ','Wu ','Jue ','Yin ','Quan ','Si ','Jiao ','Yi ','Hua ','Bi ','Ying ','Su ','Huang ','Fan ','Jiao ','Liao ', + 'Yan ','Kao ','Jiu ','Xian ','Xian ','Tu ','Mai ','Zun ','Yu ','Ying ','Lu ','Tuan ','Xian ','Xue ','Yi ','Pi ', + ], + 'x9e':[ + 'Shu ','Luo ','Qi ','Yi ','Ji ','Zhe ','Yu ','Zhan ','Ye ','Yang ','Pi ','Ning ','Huo ','Mi ','Ying ','Meng ', + 'Di ','Yue ','Yu ','Lei ','Bao ','Lu ','He ','Long ','Shuang ','Yue ','Ying ','Guan ','Qu ','Li ','Luan ','Niao ', + 'Jiu ','Ji ','Yuan ','Ming ','Shi ','Ou ','Ya ','Cang ','Bao ','Zhen ','Gu ','Dong ','Lu ','Ya ','Xiao ','Yang ', + 'Ling ','Zhi ','Qu ','Yuan ','Xue ','Tuo ','Si ','Zhi ','Er ','Gua ','Xiu ','Heng ','Zhou ','Ge ','Luan ','Hong ', + 'Wu ','Bo ','Li ','Juan ','Hu ','E ','Yu ','Xian ','Ti ','Wu ','Que ','Miao ','An ','Kun ','Bei ','Peng ', + 'Qian ','Chun ','Geng ','Yuan ','Su ','Hu ','He ','E ','Gu ','Qiu ','Zi ','Mei ','Mu ','Ni ','Yao ','Weng ', + 'Liu ','Ji ','Ni ','Jian ','He ','Yi ','Ying ','Zhe ','Liao ','Liao ','Jiao ','Jiu ','Yu ','Lu ','Xuan ','Zhan ', + 'Ying ','Huo ','Meng ','Guan ','Shuang ','Lu ','Jin ','Ling ','Jian ','Xian ','Cuo ','Jian ','Jian ','Yan ','Cuo ','Lu ', + 'You ','Cu ','Ji ','Biao ','Cu ','Biao ','Zhu ','Jun ','Zhu ','Jian ','Mi ','Mi ','Wu ','Liu ','Chen ','Jun ', + 'Lin ','Ni ','Qi ','Lu ','Jiu ','Jun ','Jing ','Li ','Xiang ','Yan ','Jia ','Mi ','Li ','She ','Zhang ','Lin ', + 'Jing ','Ji ','Ling ','Yan ','Cu ','Mai ','Mai ','Ge ','Chao ','Fu ','Mian ','Mian ','Fu ','Pao ','Qu ','Qu ', + 'Mou ','Fu ','Xian ','Lai ','Qu ','Mian ','','Feng ','Fu ','Qu ','Mian ','Ma ','Me ','Mo ','Hui ','Ma ', + 'Zou ','Nen ','Fen ','Huang ','Huang ','Jin ','Guang ','Tian ','Tou ','Heng ','Xi ','Kuang ','Heng ','Shu ','Li ','Nian ', + 'Chi ','Hei ','Hei ','Yi ','Qian ','Dan ','Xi ','Tuan ','Mo ','Mo ','Qian ','Dai ','Chu ','You ','Dian ','Yi ', + 'Xia ','Yan ','Qu ','Mei ','Yan ','Qing ','Yu ','Li ','Dang ','Du ','Can ','Yin ','An ','Yan ','Tan ','An ', + 'Zhen ','Dai ','Can ','Yi ','Mei ','Dan ','Yan ','Du ','Lu ','Zhi ','Fen ','Fu ','Fu ','Min ','Min ','Yuan ', + ], + 'x9f':[ + 'Cu ','Qu ','Chao ','Wa ','Zhu ','Zhi ','Mang ','Ao ','Bie ','Tuo ','Bi ','Yuan ','Chao ','Tuo ','Ding ','Mi ', + 'Nai ','Ding ','Zi ','Gu ','Gu ','Dong ','Fen ','Tao ','Yuan ','Pi ','Chang ','Gao ','Qi ','Yuan ','Tang ','Teng ', + 'Shu ','Shu ','Fen ','Fei ','Wen ','Ba ','Diao ','Tuo ','Tong ','Qu ','Sheng ','Shi ','You ','Shi ','Ting ','Wu ', + 'Nian ','Jing ','Hun ','Ju ','Yan ','Tu ','Ti ','Xi ','Xian ','Yan ','Lei ','Bi ','Yao ','Qiu ','Han ','Wu ', + 'Wu ','Hou ','Xi ','Ge ','Zha ','Xiu ','Weng ','Zha ','Nong ','Nang ','Qi ','Zhai ','Ji ','Zi ','Ji ','Ji ', + 'Qi ','Ji ','Chi ','Chen ','Chen ','He ','Ya ','Ken ','Xie ','Pao ','Cuo ','Shi ','Zi ','Chi ','Nian ','Ju ', + 'Tiao ','Ling ','Ling ','Chu ','Quan ','Xie ','Ken ','Nie ','Jiu ','Yao ','Chuo ','Kun ','Yu ','Chu ','Yi ','Ni ', + 'Cuo ','Zou ','Qu ','Nen ','Xian ','Ou ','E ','Wo ','Yi ','Chuo ','Zou ','Dian ','Chu ','Jin ','Ya ','Chi ', + 'Chen ','He ','Ken ','Ju ','Ling ','Pao ','Tiao ','Zi ','Ken ','Yu ','Chuo ','Qu ','Wo ','Long ','Pang ','Gong ', + 'Pang ','Yan ','Long ','Long ','Gong ','Kan ','Ta ','Ling ','Ta ','Long ','Gong ','Kan ','Gui ','Qiu ','Bie ','Gui ', + 'Yue ','Chui ','He ','Jue ','Xie ','Yu ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Shan ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'xf9':[ + 'Kay ','Kayng ','Ke ','Ko ','Kol ','Koc ','Kwi ','Kwi ','Kyun ','Kul ','Kum ','Na ','Na ','Na ','La ','Na ', + 'Na ','Na ','Na ','Na ','Nak ','Nak ','Nak ','Nak ','Nak ','Nak ','Nak ','Nan ','Nan ','Nan ','Nan ','Nan ', + 'Nan ','Nam ','Nam ','Nam ','Nam ','Nap ','Nap ','Nap ','Long ','Nang ','Nang ','Nang ','Nang ','Nay ','Nayng ','No ', + 'No ','No ','No ','No ','No ','No ','Lou ','No ','No ','No ','No ','Nok ','Nok ','Nok ','Nok ','Nok ', + 'Nok ','Non ','Nong ','Nong ','Nong ','Nong ','Noy ','Noy ','Noy ','Noy ','Nwu ','Nwu ','Nwu ','Nwu ','Nwu ','Nwu ', + 'Nwu ','Nwu ','Nuk ','Nuk ','Num ','Nung ','Nung ','Nung ','Nung ','Nung ','Twu ','La ','Lak ','Lak ','Lan ','Lyeng ', + 'Lo ','Lyul ','Li ','Pey ','Pen ','Pyen ','Pwu ','Pwul ','Pi ','Sak ','Sak ','Sam ','Sayk ','Sayng ','Sep ','Sey ', + 'Sway ','Sin ','Sim ','Sip ','Ya ','Yak ','Yak ','Yang ','Yang ','Yang ','Yang ','Yang ','Yang ','Yang ','Yang ','Ye ', + 'Ye ','Ye ','Ye ','Ye ','Ye ','Ye ','Ye ','Ye ','Ye ','Ye ','Yek ','Yek ','Yek ','Yek ','Yen ','Yen ', + 'Yen ','Yen ','Yen ','Yen ','Yen ','Yen ','Yen ','Yen ','Yen ','Yen ','Yen ','Yen ','Yel ','Yel ','Yel ','Yel ', + 'Yel ','Yel ','Yem ','Yem ','Yem ','Yem ','Yem ','Yep ','Yeng ','Yeng ','Yeng ','Yeng ','Yeng ','Yeng ','Yeng ','Yeng ', + 'Yeng ','Yeng ','Yeng ','Yeng ','Yeng ','Yey ','Yey ','Yey ','Yey ','O ','Yo ','Yo ','Yo ','Yo ','Yo ','Yo ', + 'Yo ','Yo ','Yo ','Yo ','Yong ','Wun ','Wen ','Yu ','Yu ','Yu ','Yu ','Yu ','Yu ','Yu ','Yu ','Yu ', + 'Yu ','Yuk ','Yuk ','Yuk ','Yun ','Yun ','Yun ','Yun ','Yul ','Yul ','Yul ','Yul ','Yung ','I ','I ','I ', + 'I ','I ','I ','I ','I ','I ','I ','I ','I ','I ','I ','Ik ','Ik ','In ','In ','In ', + 'In ','In ','In ','In ','Im ','Im ','Im ','Ip ','Ip ','Ip ','Cang ','Cek ','Ci ','Cip ','Cha ','Chek ', + ], + 'xfa':[ + 'Chey ','Thak ','Thak ','Thang ','Thayk ','Thong ','Pho ','Phok ','Hang ','Hang ','Hyen ','Hwak ','Wu ','Huo ','','Coc ', + 'Zhong ','','Qing ','','','Xi ','Zhu ','Yi ','Li ','Shen ','Xiang ','Fu ','Jing ','Jing ','Yu ','', + 'Hagi ','','Zhu ','','','Yi ','Du ','','','','Fan ','Si ','Guan ','He ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x200':[ + 'Ha ','Qi ','','','','Hai ','','','','Qiu ','','','','Shi ','','', + '','','','','jue ','','','','','','','yu ','','','','', + '','','','','','','','Ba ','Cup ','','Kha ','','','','','', + '','','','','Trut ','','','','','','','','','lu ','','', + '','','','','','','','','','','','','','','','', + '','Duoi ','','','','','','','','','Cui ','','','','','', + '','','','','','Ga ','','','','','Nham ','','','','','', + '','','','','','','','','Suot ','','','','','','','', + '','','','','','','','','jie ','','','','','','','', + '','','','','Zi ','','','','','','','','','Zung ','','', + '','','Pai ','','Dui ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','jiu ','','','','','', + ], + 'x201':[ + 'Vu ','','','','','','','','','','','','','jie ','','', + '','jue ','','','','','','','','','','','','','','', + '','','','','','','Gop ','Vai ','','Hai ','','','','','','', + '','','','Kep ','','','Nham ','','','','','Lam ','Nam ','Vai ','','wei ', + '','','jie ','','','','','','','','','','','Mat ','Mat ','', + 'Mat ','','Mat ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','zhang ','','','Mat ','','','', + '','','','','','','','','','','','','Yong ','','','', + 'xu ','','','','','','','','','','','','','','','', + '','','','','','','','','','Faan ','','','','','','', + '','','','Trum ','','','dan ','','','','','','','','','', + '','','','','','','','','','','','','','Voi ','','', + '','','','','','Va ','','','chu ','','','','','','','', + '','','','','','','','','','','','','','','','qu ', + '','','','','','','','','','','','','Hua ','Top ','','', + ], + 'x202':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','yun ','','','','','','','','','','','', + 'dan ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Nay ','', + 'Tray ','','','','','','','ju ','','du ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','jian ','','','','','','','','Ngai ','','Nho ','Thay ','','', + '','','','','','','','Bing ','','zhuan ','shu ','','jue ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','lian ','','','','','','','','she ','', + '','','','','','May ','Mu ','','','fu ','','','ju ','','','', + '','','','','','','','','','','Tao ','','','','','', + ], + 'x203':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Wu ','','','','','','','','shuai ','','', + 'gai ','','','','zhuang ','','','','','','','','','fu ','','', + '','Man ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','But ','','','','','yao ','','','','Gap ','','bie ', + '','','qu ','','','yang ','','','','','','','','sha ','','', + '','','','','','','','','','','Xum ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Cap ','Bay ','','','','','jue ','', + '','','','yu ','','','','sa ','','','','dun ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','xiao ','','','','','yu ','qu ','','','','', + '','','','','','Ngai ','','','','','','','','Tui ','','', + '','','','Giong ','','','','','','','','','','','','', + ], + 'x204':[ + '','meng ','','','','','','','','jie ','shu ','','','su ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','meng ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Trom ','','','Long ','','','','', + '','','','','','Ngua ','','','','','nei ','nei ','','','zhai ','', + '','','','','','','','','','','','','Nhau ','','','cu ', + '','','','','','','','','','','','','','','','', + '','','','','wu ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Rang ','','','','','','','','','','', + '','','','','','lian ','','Tin ','','','','','','','fan ','', + 'Truoc ','','','','','','','','','','','','','','','', + 'Quanh ','','','','Mong ','','','fu ','','','','','','','','', + '','','','','','','','','Vao ','Nhui ','','','','','','', + '','','','','','','','','','Lon ','','Tron ','Sip ','','','', + ], + 'x205':[ + '','','','Xi ','','','','','','Juan ','','','','','','', + '','hai ','','','','lun ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','heng ','','','','','','','','','Zheng ','','','','', + '','','','','Nap ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'cheng ','','','qia ','','','yu ','','','','','','','zhao ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Xuong ','','','','','','','', + '','','','','','','','','Nap ','','','','','','','', + '','','','','Bay ','Chong ','','','','','','','','','','Ngat ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','qiu ','xie ','','','','','','', + '','','','','','','','','','','','die ','','','','', + '','','','Lun ','','','Ping ','','die ','','','','','','','', + 'Tron ','','','','','','','','','Ret ','','','','liu ','','', + ], + 'x206':[ + '','bu ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','lai ','','', + '','','he ','jiao ','','','','','','','','','','','','', + '','','','','','','','','','','','wu ','','','','', + '','','','','','','ju ','','','','','','','','','', + '','','','','jiu ','wei ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','xian ','','','','chang ','','','','','', + 'Moc ','','','','he ','','','','','','','','','','','', + '','','Ra ','','','','','','','','','','','','','Got ', + '','zhe ','','','','ju ','','','','Shan ','Sha ','','','','','', + '','','','','','','','','','','','','Cham ','','','', + '','','','','','','','','','cu ','','','','','','', + '','','','','Chem ','','','','','','Tiu ','','','','','', + '','','','','','','','','fen ','','','','','','','', + ], + 'x207':[ + '','','','jiu ','xu ','','','','','','','','','','Xian ','', + 'kuai ','','','','','','','','','bu ','','','','','','', + '','','','','qia ','','','','','','','','','','Hui ','', + '','Pai ','','','','','','','','ju ','','','Qia ','','','', + '','','','','','','','Bao ','','','','','','','','', + '','','','','','Cun ','','','qia ','','','','','','','', + '','','','','','','','','','','','','','Peng ','','', + '','','','','','','','','','Gaai ','','','','','','', + '','','','zhe ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','Got ','Bam ','','','','','','','','','','gun ','Lou ','','', + 'Jiao ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','yao ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Hoat ','','','','','','','','','','', + '','','','','','','','','','','','ze ,bai','','','','', + ], + 'x208':[ + '','','','','zhao ','','','','','Bua ','','','','','','', + '','Tet ','','','du ','','','','','','','','','','','', + 'du ','','','','','','','','','Truoc ','','','','Chom ','','die ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','Gang ','','','','','', + '','','','','','','','','','','','','','','','', + '','duan ','','','','','','','','','Khuot ','','','','','', + '','','','','','','','han ','','','','','','','','', + '','Nhoc ','','','','','','','','','juan ','','','Vam ','Giup ','Giup ', + '','','','dian ','Jue ','','','','','','','','Lu ','','','', + '','','','','','','','','','','','','','','','', + '','','Ruon ','','','','','','','10383.060,wan ','','','','','','', + 'yun ','','','','','','','','','','','','','','','', + '','','','','','','','','','','qu ','shao ','','','','', + '','','','pao ','','','','','','','bao ','','','','fu ','jiu ', + ], + 'x209':[ + '','','','','','','Cho ','','','','','','Cho ','','hua ','Bao ', + '','','','','','','','','','','','','','mao ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','diao ','','','', + '','','','','','','','','','','','','','','wei ','', + '','diao ','','','','','','','','','','','','','','', + '','','','','Giau ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','sa ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','luan ','Muoi ','','','','','','Gan ', + '','','','','','','','','','Chuc ','','Lung ','','','','', + '','','','','','','Tron ','yu ','','','','','','Nhu ','','', + '','','','','','he ','','','','shao ','','','','','','', + '','','','','','','','','','Hui ','','','','','','', + '','','','','','','','','','','','','','','','heng ', + ], + 'x20a':[ + '','','','wai ','','','','','','','jue ','','','','zhuan ','', + '','','','','','','','','','','','','','','','', + '','','jun ','','','','','','','','','','','ju ','','', + '','','','','','bang ','','','','','','','','','','', + '','','','','','','','','zhu ','','','','','','','', + '','','','','','Me ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','Li ','','','','','', + '','','','mei ','','','','','','','','','','','','', + 'liu ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','fu ','','','','', + '','','','jue ','','Day ','','','','','','','','','','Rot ', + '','','','','','','','','','','','','','','','', + '','','','yu ','','','','','','','','','','','tu ','', + '','','','','','','','','','shan ','','','','','','', + ], + 'x20b':[ + '','','','','','','guan ','','','','','','','','','', + '','','Cut ','','','','','','','','','Mo ','','fu ','','', + 'Mot ','','','bang ','','','','','','','biao ','','','','jie ','', + '','','','','','','Jin ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','Zhuo ','','','','','bian ','','','','','','tun ', + '','','','','','','','','','','de ','','zhu ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Naai ','Aa ','','','','','','', + '','','','','','mang ','','','','','','','','','Ngot ','sa ,san', + '','','','','','','','','Daai6','','','Jai ','','','','', + '','','','zhe ','','','','','ban ','jie ','','','','','','', + '','','','','','','Cai ','','','','','','','','Hin ','pian ', + '','','','','bian ','','','reng ','','reng ','','','Danh ','Zi ','','', + ], + 'x20c':[ + '','','Ngoen ','','','','','','','','','Jaau ','Mut ','','','Mom ', + '','an ','','he ','','','','','','Khen ','','hu ,gao','','','','', + '','','','','','','','','','','','','','Meo ','','', + '','','Eot ','','','','','Lo ','','','dai ','wai ,wai','','','','', + '','Tam ','Dat ','Nip ','','Quai ','','','','','','','','Phom ','','', + '','','','Ngai ','','','','','Ngaak6','','','','Chun ','','','', + '','sa ,shai','','','','Fik ','','','','','','','','','','', + '','','na ','','','','','Ming ','San ','','','','','','','', + '','','','','','','','','','','','','shu ','','','Nham ', + '','','','Hang ','','','Ji ','','','','','','Zaang ','','','', + '','','','','','','Nhung ','','','','','','','','Khinh ','', + '','ge ','','','','Gip ','','die ','','','','','','fu ','','Shu ', + '','Kwan ','','','','','','he ','','','','','qia ','','','Ce ', + 'Vang ','','','','','Caau ','Dap6','','Nhu ','Thay ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','Tu ','','','','','','','cheng ','','', + ], + 'x20d':[ + '','','','','','','','','','','','Phao ','Nhanh ','Nhan ','','Mang ', + 'Nuc ','','','','','Miu ','Voi ','','','','','Gung ','','','','', + '','xiao ','','','','Ngoam ','zhu ','','','','','Thut ','','','','', + 'Gau6','hu ','ta ','Ngaau ','','zao ','','','','','','','dao ','','na ','', + '','','','','','','Daam ','Koe ','Mui ','Hong ','','','','','','', + 'Mep ','','','','','','','','Mun ','','','','','','','', + '','','','ya ','','','','zhen ,chun','de ','Go ','','','','','','Gwit ', + '','E ','','','','','','xuan ','','','','','Mang ','Faat ','Waak ','Pe ', + 'Tham ','Nhu ','','','','','','','Se ','','Pha ','','','','','', + '','U ','','','','Nhau ','Uong ','','Sat ','Bop ','','','Zai ','','','', + '','Troi ','Du ','Mai ','','Kung ','','Dim6','','','','da ','nang ','','','Chut ', + '','','Gap6','','','','','','jue ','he ','','','','','','', + '','','dai ','','','zhu ','','','','','','','','ta ','','', + '','','','','','','bian ','','','xu ','','','','','','', + '','','','','Phao ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x20e':[ + '','pai ','Giot ','','Inh ','','','','','Kak ','Tap ','','','Me ','Naa ','Ge ', + 'Kam ','Soek ','Bou ','','','','','Xua ','Tuc ','Song ','','','','','','Bai ', + '','','','','','','Khan ','','','','','Tau ','','','','', + '','','','','','','','','','yu ','Ngaak6','','','','Map ','', + 'xun ','wa ','','ang ','han ','','','','','','','','Lan ','','','', + '','yao ','','ge ','','bao ','','','xu ','','','','','','','', + '','','','','','','','','','','','','','Ko ','','', + '','','','Git6','','','','Ngo ','Kam ','Lan ','Maai ','Zam6','','Cay ','','', + '','','','','','','','','','','','','Gwe ','','','', + 'huan ','','','','','','','','Long ','Thoi ','Ban ','','','Gaak ','','ku ', + 'Lung ','','Gaa ','','','','','','','Trou ','He ','Loe ','He ','','','', + '','Hung ','','','','Chac ','Nop ','','','Ri ','Que ','Cop ','Xui ','','Chau ','Ngoan ', + '','Guong ','Ngon ','Han ','Oang ','','','','','','','','','huan ','','zu ', + '','','','','','','','Le ','Zeot6','he ','','','','','','', + '','','','','Don ','zhao ','','','','','','','tu ','','','', + '','','','','Long ','','','','','','Aa6','Bai ','Dau6','','','', + ], + 'x20f':[ + '','','','','','','','','','','','','','','','', + '','','','','','Paai ','','Zaam ','wu ','','','','','','','', + '','','jiang ,qiang','','','','Muon ','','','lun ','Day ','','','But ','Ngai ','Ho ', + 'Kang ','Loe ','','','','Danh ','','Thay ','','','','Ji ','','','','', + '','Xo ','','Zap ','Tham ','Thung ','Nuot ','','','','','Nac ','Syut ','','Nhai ','', + 'Ngo ','','Neng ','Ngon ','Thua ','','Giuc ','','','','','Oam ','','','','', + '','','','','Kik ','','','','','','','','','','','', + '','','','','','yu ','','','','','','zhe ','','','','', + 'Hup ','','','','','','','','','','','','','He ','','Ce ', + '','','','','','','','','','','','Ngoang ','','','','', + '','','shu ','Rum ','','','Bai ','','','la ','','','','We ','','', + '','','','','Baang ','Zaa ','Ging ','','','Nuot ','','','Cyut ','Nhun ','Nhap ','', + '','Si ','Xep ','','','','','','','','','','','','','', + '','','Het ','sa ','','qiao ','','','','','','Lu ','hua ','','','', + '','','','','','','','','','','Gaa ','Saau ','Soe ','Wet ','','Ngui ', + '','','','','','Khan ','','','','','','','','','','', + ], + 'x210':[ + '','','','','','','','','','','','','','','','', + '','','','','Lu ','','','','','','','','','Nam6','Zip ','', + 'Bei6','','','','','Phao ','','','','Lok ','','Bam ','','','','', + '','Hao ','Goi ','','','','','Ron ','','','xie ','','','','','', + 'han ','','','','','','','','fan ','','','','','ai ','yu ','Am ', + '','','','','','','','','','','Hon ','','Wo ','Hang ','Xao ','', + '','','','','','','','','','','','','','','','Dyut ', + '','','','zhan ','','Gan ','Zit ','Doeng ','Kwaat ','','Ngon ','Ziu ','','','','', + 'Khao ','','','Hun ','','','','Mom ','Buk6','','yu ','','','Eng ','','', + '','Ban ','','','','','Lai ','','','','','','','Zuk6','','bao ', + '','shu ','','','','','','','','','Ze ','peng ','','','Ngau ','', + 'Ran ','','Ray ','Troi ','','','','Khoan ','','','','','','','','', + 'E ','Leng ','','','lai ','','','Bai6','Kwaak ','Gaa ','','','','Chem ','Phan ','Doe6', + '','','Boc ','Bo ','','Gung ','Le ','Mua ','','Mut ','','','','lun ','','', + '','','','','Laai6','','','','','','','','','','','', + '','','','','Ceoi ','Ngung ','Sek ','','','Chen ','','','','','Phac ','Thot ', + ], + 'x211':[ + '','Lum ','','','','','','','','','','','','Ruc ','Gam ','Ham ', + '','','dao ','','','','','','','','','','','','','Haa ', + '','Zaai ','','','','','Lom ','','','Khan ','Toe ','Khem ','Hun ','','','Jik ', + 'Tot ','cu ','ru ','','','Ji ','','','','luan ','','','','Soe ','','', + '','','','','','e ,ei','','','Laa ','Dang ','Bun ','Hum ','','','','Lai ', + 'Lanh ','Ngong ','','','','','','','la ','yun ','','','','','','', + '','','','','','die ','','Nan ','','','','','Hoai ','','','', + '','huan ','','','','','','','','','','huan ','','','','', + 'Gwang ','Nhau ','','','Nhep ','wan ','','Wok ','','','','','','','','', + '','Nham ','','','','lian ','Trom ','','','','Gu ','','','','Giau ','', + '','','','','','jiu ','','','','','','','','','','', + 'dun ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','die ','','','','','','Doe ','','','','','he ','', + 'zhe ','','','','','','wei ','','','tu ','','','','','','hun ', + '','','','','','dang ','he ','tai ','Quay ','','yu ','Nhot ','ya ','','','', + ], + 'x212':[ + '','','','','','jue ','','','','','','','','','Mui ','', + '','','','yuan ','','','','','','You ','','','','','','', + '','','','','','','','','yu ','','','','','','','', + '','','','','','','lei ','','','','','','','','','', + '','','','','','','','','','','','','','','Cong ','', + '','','tun ','','','','Cong ','','','','','','','','','', + '','','','','','','','','','bao ','','','','','','', + '','','','','lu ,hu','','','jie ','','','','','','','Tum ','Moc ', + '','','','','','','','','','','','','','shu ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Sanh ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','gao ', + '','','','','','','','','','de ','','','yu ','','','', + '','','','','','','','','','','','','','','','', + ], + 'x213':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','guai ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'hu ','','','','','','','','Che ','Vung ','Lam ','','Mun ','Nui ','','', + '','','','','','zhai ','','','du ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','du ','','','','','','', + '','an ','','','','','','','','','','Bun ','Nam ','','','Hang ', + '','','','','','','','','','','','','','Thong ','su ','', + '','','','','Gung ','','','','','','zhu ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','xia ','','','','','','','', + '','Luong ','','','','Tret ','Xay ','Bui ','','','','','','','','bai ', + '','','','','','','','','','','','','','','','', + ], + 'x214':[ + '','','','','','','','','','','','','chu ','','','', + '','','','','','','xian ','Hoc ','','','','','','fu ','','', + '','','','','','sa ','','','','','','','','','Ve ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Coi ','Chum ','','','','Thoai ','','','','','','Lan ','Sui ','', + '','','','','','','','','','','','','','Coi ','','', + '','','Gom ','','','','','','','','','','','','yu ','', + '','sa ','','Juk ','Lan ','','','','','','yu ','','','ju ','','', + '','','shu ','xian ','','','gai ','','','','','','','','','', + '','','','','','','','','','','','Cau ','','','Suong ','', + '','','','','','','','','','','','','','','','', + '','','','Loi ','Vung ','','','','','','','','','','','San ', + '','','lai ','','Lam ','','','','','','','','','','','', + '','','','','','Chen ','zhan ','','','','','','','','','Chum ', + '','','','','','','','','','','','','','','','', + ], + 'x215':[ + '','','','','','','','','','','','','','','','', + '','','','','Lan ','','','','','','','','','','','', + '','','','','','','','','','','shu ','','','','','', + '','','','','yu ','','','','','','','','','','','Trau ', + '','','','','','','','','','','','','','','','', + '','','kua ','','','','','hai ','','','','','','','','', + '','','','','','','','hang ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','yun ','','','','','','','','','','','','','', + '','','','','','','','','','','guai ','','','','','su ', + '','Bon ','','','','','','','','','','','','','','', + '','','Sai ','','','','','','','','','Lam ','','','Tum ','', + 'Muong ','','','','','','','Peng ','','','','','','','','', + '','','','','','chun ','','','','','','','','','','', + '','','','','','','','','','fan ','','','','','','', + ], + 'x216':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','zhe ','Mat ','Lon ', + 'juan ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','jie ','','','','','','','bie ','','','','','', + '','','','','Canh ','Nhon ','','','','','','','','','','', + '','Bi ','','Xon ','','','','yan ','wei ','','','','hao ','','','', + '','','','','meng ','','','','','','Lon ','','','','','', + 'jue ','To ','To ','','','','Hai ','','','','','','','','','', + '','','','','','','','','','zhang ','','da ','','hao ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','can ','','', + '','','','','Nua ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x217':[ + 'fan ','','hu ','','','','','','','','','','','','','', + '','','','','','','','','','','ru ','','','','','', + '','','','','','','','','','','','','','','','zhe ', + '','Ji ','gao ','','','','','','','','','','','','','', + '','','','Bua ','','','','','chu ','','zhe ','','','','','', + '','','','','Kep ','Va ','','','','','cheng ','','du ','','','nian ', + '','','','','','','Vu ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','cu ','','','pan ', + 'hu ','','','xian ','','','','','','','fu ','nai ','','','','', + '','','','','','','','','','','','','','','Nen ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','lian ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x218':[ + '','','','','','','','','','','','','','','','', + '','','','','','','hao ','','yang ','','','','','','fu ','', + '','','','Cuoi ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'juan ','','Nhang ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','qu ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'zhuan ','','','','','','','','dang ','','','','','','','', + 'Sau ','','','','','','','','','','man ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Sui ','','', + '','','','','','','','','shu ','','','','','','','', + '','','','','han ','Ban ','','','','','','','','','','', + '','','nei ','','','','','','Cuoi ','','','','','','cai ','jie ', + '','','','','','','','','','','','Sen ','','','','', + ], + 'x219':[ + '','','','','','','','','','','Chua ','','','','fan ','', + '','','','Moi ','Moi ','','','zhu ','','na ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','jiao ','','','','Nhat ','xiao ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Con ','ju ,ru','','','','','','Me ','','','', + '','xu ','','','fu ','So ','','','','','','','','','','', + '','','','','','er ','','','','','','shu ','','','','', + '','','','','','','','Rot ','','','','Chat ','','','Nhang ','', + '','','','xiao ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','mian ','','','','','wa ','','pao ','','','','','','', + '','','','','','','heng ','','zhu ','','','','','','','', + '','','','','','','','','','dai ','','','','','','', + ], + 'x21a':[ + '','','','','Xia ','ju ','','','','','','','','','','', + '','','','','','','','zao ','','','','','','','','', + '','','','yu ','','','','Tot ','','','','','','','','', + '','','jie ','','Ning ','nai ','','','','','','','','','','yu ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','jie ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','an ','','','Xum ','','','', + 'ceng ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','Sao ','','','','','','','','','','','','','','', + '','','','','','','Lung ','','','','','','','','','', + ], + 'x21b':[ + '','','','','','','','','Xuong ','sai ','yu ','jiao ','','','','', + '','','','','','','','','20960.020,lao ','','','','','','yu ','', + '','','','','','','','','','','','wu ','','','','', + '','','','','','','','Tac ','','','','','Gang ','','','', + '','','de ','','','','','','','Ban ','','','','','','', + 'shuan ','','','','','Cut ','','','','','','','Mon ','','','', + '','','bai ','','','','','Chut ','','','','','Be ','','','', + '','Chut ','Trut ','kao ','','','','','luan ','','','Nhon ','','','','', + '','','','','','','Mon ','Chut ','','Mon ','','May ','Be ','Chut ','','', + '','','','Choai ','','','','','','nai ','','','','','','', + 'May ','','','Be ','Be ','Be ','Zao ','','','Be ','','Nhen ','Mon ','Nhon ','Mon ','', + '','','Tho ','','','Chuong ','Chuong ','','Nhon ','','','','','Nhon ','','', + 'Oat ','','','','','','','wu ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'ga ','','','','chao ','','','','','','','','','ga ','','', + ], + 'x21c':[ + '','','','','','hu ','','','','','','','','','','', + 'qiao ','','','','','','','','','','','','','','','', + '','','xie ','','','','','','','','Duk ','','','','','', + '','','','','','','','','','','','','','ai ','','pu ', + '','','','','','','Shu ','','','','','','','','','', + '','','','','','','','','','','','','zhao ','','','', + '','','','xu ','','','','','','Thuoc ','','','','','','', + '','zhu ','','','','','','die ','Gang ','','qu ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Ti ','','jue ','','','qiu ','','','','','', + '','','Ke ','jiang ','','','','','','','yun ','','Gwat6','','','', + 'qu ','','','','','','','','','','','','','','','', + 'Ngoe ','','kai ','Cuoi ','','','','','','','','','','','','', + '','chu ','','','','','','','ju ','','','','Cuoi ','Rot ','','', + '','','','','','Toi ','','','','','','','','','','', + '','','','Cuoi ','lu ','','','','','','','','','','jue ','', + ], + 'x21d':[ + '','','','','','','lu ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','ya ','','', + '','hu ,jie','','','','','','','','','','','','','','', + '','','','','','','','','','Ngut ','','','','','','', + '','','','','','','','','hu ','ang ','','fu ','','','','', + '','','','','','','','','','','','','mu ','','','', + '','','','','','','','','','','Cu ','','','','','', + 'Nui ','','yao ','ai ','','','','','','fan ','','ju ','','','','', + 'qie ','','','','','','','','','','','','','','','', + '','','kuang ','','','','ya ','','Ngan ','','kan ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','lu ', + '','','','','','','','','bie ','','','han ','','na ','','', + '','','','','wu ','gao ','','','','','','','','','','', + '','','','','','','','','','','','ya ','','','','', + ], + 'x21e':[ + '','','','','','','','','','','','','zhu ','','jie ','Voi ', + '','','','','xie ','','','ya ','','','','','','','','', + '','','','','','','ze ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','ya ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Nghi ','','','','','','','','','','','','','die ','','', + '','','','','','','','','','hu ','','','','','','', + '','','','','','','','','','','','','','','','', + '','die ','','','','','','','','','','','pen ','','','', + '','','','','','','Din ','','','','','','','','','', + '','','','','tu ','','','xia ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Voi ','','Seoi ','Von ','Chon ','','','','','','','','', + 'zhu ','','','','','','','','gun ','man ','','','zu ','','hu ','', + '','lei ','','','','','','','','','','','','','','', + ], + 'x21f':[ + '','','','','die ','','','','','','','','','','','', + '','','','dian ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','wei ','','','','','','','','','','','','','kuai ','', + '','','','','','yun ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','Non ','','','','', + '','Jie ','bang ','','','','','','','','','','','','','', + '','','','','','','','kuang ','','','','','','','','', + '','','','ceng ','','dang ','','','','','','','','','','', + '','','','','','','','','hai ','','','','Doc ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','nang ','','', + '','','','','','yu ','','','','','','','','','','yu ', + '','','','','','','','','','','Nao ','','xun ','','ju ','', + ], + 'x220':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','wan ','','','','','','','','', + '','','','','','Vang ','Sua ','Tron ','Sang ','','','','Lon ','','Sam ','', + '','To ','Lon ','','','han ','','','','','','','fu ','','','', + 'fu ','','','','','','','','','','','Trang ','','Va ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','jue ','','','','','', + '','','','','','','','','Phuon ','','','bu ','','','','', + 'fu ','','','','xuan ','','fu ','','','','','','','','Du ','', + 'xie ','Shi ','','','','','','','','','','','Vua ','','','', + '','','','','','','','','','','','','','','','', + 'Tranh ','yuan ','','','','','','','','mao ','qian ','','','','','', + 'wu ','','','','','','','Lei ','Long ','','Vua ','','','','','', + '','','','','','Ta ','','han ','qian ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','la ','','','','','','','','','','','', + ], + 'x221':[ + '','','','Phoi ','','','','','','','','','','he ,ge','bang ','', + 'meng ','','','wu ','dai ','','','','','','','','han ','Bau ','','', + '','','','','','','','cu ','','','','','','','','Man ', + '','','','','','xiang ','Hua ','','','','','','','','','', + '','','','','','','Manh ','','','mao ','','ceng ','','','','Lian ', + '','','dan ','','','','Lian ','','','','','','','dian ','','', + '','','','','gai ','Ju ','','','','','zu ','','Chan ','','','', + '','','','','','','','','','yao ','','','nei ','','','', + '','','neng ','','','','','','','','','','','','','', + '','','','','','','','','','','','','ge ','','Jian ','', + 'Lai ','Nin ','','','','Nam ','jian ','May ','May ','','May ','','','','','', + 'hu ','','','','','','','','','','chen ','','','','','', + '','','','','','','','Guan ','yan ','Doi ','','','','','','', + '','','','','','','','sha ','','','','','','','han ','', + '','Khuya ','','','','','ren ','','','','fan ','','','','','', + '','','','','bu ','na ','','','','','','','','','','', + ], + 'x222':[ + '','','','','','','','','Nap ','','','','','','','', + '','','','','','bai ','','','Roku ','','','kun ','','qiu ','','', + 'cu ,la','','','','','','','','','','','','','','','', + '','','pu ','','','','','','','','','jie ','','zhan ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','du ,tu','','','', + '','','hu ','','jia ','','','','la ','','','','','','','', + '','','','','','','','','','','','','','Kho ','U ','ma ', + '','','','','','','','','','','','','','Ceoi ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','yu ','','lu ','','','','','','', + '','fen ','','','','','','','','','','','','','','', + '','','','','','yu ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','xian ','', + '','','','','','','','','','wu ','','','','','','', + ], + 'x223':[ + '','','','','qu ','','','','','','Rong ','','Rong ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','fu ','','yu ','','','','', + '','','','','','','','','','','','','','','gao ','juan ', + '','','','','','quan ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','die ','','','','','','dai ','','su ','', + '','','','','jie ','','qu ','','han ','','','','','','','', + '','jie ','','','','juan ','','','','','dan ','','','','','', + '','','','','','hu ','','','','jue ','','yu ','','','','', + '','','','','','','','','','','','','','fu ','','', + '','Ban ','','','','','','','','','','','','','','', + '','','Cong ','Cong ','xun ','','','','','','','','','liu ','','', + '','','','Beng ','','','','jue ','','','','','','','','Von ', + ], + 'x224':[ + '','','','','yuan ','','','','','','','','','','Khom ','', + '','','','','','','','','','','','','','','cheng ','', + '','','','','','','','King ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','jiu ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','hu ','','','','','','', + '','','','','','','','','','','','','','','Bay ','', + '','','fu ','','chu ','','','','','','','','','','lan ','', + '','','','','','','','','','','','','','','','', + 'yu ','','','','','','','','','','','','','','jiao ','', + '','','','','','','','','','','','ang ','','','','', + '','','','','sa ','','','','','','','','ge ','','','', + '','','kua ','','','','','','','','','','xie ','','','', + '','','wu ,hu','','','xiu ','','','','','','','','','','', + ], + 'x225':[ + '','','yan ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','yu ','','','yu ','','','','','','','yu ','','','', + '','','liu ','','20832.030,yu ','','','','','','','','','','','', + '','','','','','shuai ','','','','','','yuan ','','','','', + '','shuai ','','','','','','','','','','','','','','ao ', + '','','','','','','','','','','jiao ','','sa ','xian ','zha ','dian ', + '','','','','','','','','San ','','','shan ','','','','', + 'Suot ','','','','','','','','tiao ','','','','','','','su ', + '','','','','','Sau ','Sau ','','','','','','','xian ','','', + '','yu ','','','','','jue ','nang ','','','','','','','','', + '','','','','','ru ','','','','','','','','','','', + '','','','','xia ','','','','','Nuoi ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','wu ','','','','','','','chang ','','Lo ','','','', + ], + 'x226':[ + '','','','','qiu ','Maau ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Rung ','Rap ','', + '','','','','','','','','Jiang ','','','','','','','', + '','wu ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Hung ','','','','','','','','','Nhon ','E ','Tim ','kan ','', + '','Lung6','','','','','','','','','','','','','','', + 'xian ','','','','','','ju ','','','','','miao ','','','','', + '','su ','','','','','Ti ','','','','','','','','','', + '','','','','','','','','','','hu ','','','','','', + '','','','','','','','','','Khuay ','','zhu ','Ngop ','','','', + '','','','qiu ','ya ','','','','','','','','','','bie ','', + '','','','','','','xiang ','','','','ru ','wang ','','','','ya ', + '','','','','','','','','yu ','','','','','','','', + '','','','','Mang ','Zang ','','','','','','','','','','', + ], + 'x227':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','Vung ','','','','','','','','', + '','','','','','','','','','','','Xing ','Duo ','','','', + '','','','','','','sao ','','Nao ','','','','','','','jia ', + 'tu ','','du ','','','','','','','','','','mao ','yao ','','', + '','','','','','','','','','Vui ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','wu ','Fit ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'hai ','','','','','','','','','','','','','','','gao ', + '','','','','','','fu ','','','','','','','liu ','','', + '','','','','','Fit ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Chua ','','Nan ','','','Nep ','','','Chac ','Cham ','','','','','','', + '','','','yang ','','','','','','','','','','','','', + 'ai ','teng ','','','','','','','','Nhuoc ','','','','','','', + ], + 'x228':[ + '','','','Geng6','Sung ','Thung ','','','','','','','','','','', + 'Ngo ','','','','','','','','','','','','','','','', + '','sao ','','','','Gan ','Hon ','','','Mo ','','shu ','','','','Lang ', + '','','fu ','Bie ','','Tang ','','xiang ','','','','','','dang ','','', + '','','dang ','','','','','','','','','','','ge ','yu ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'zhao ','','','','','','','','','','','','','','','', + '','','Ghet ','','Ngung ','','','','','','','','chang ','zhe ','','', + '','','su ','','','','','','','','kai ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Khan ','','', + 'Ngay ','','','','Quo ','','','','','','','','','','','ai ', + '','','','','','','','','','','','','','','','', + 'liu ','','','','','','','Khuay ','','','','','','','','', + '','','','','','','','','','Hung ','','','','','','chu ', + ], + 'x229':[ + '','sao ','','','','','','','','','','','','','','', + 'liu ','','','','','','','','meng ','','zhan ','','','Cham ','','', + '','','','','zhuang ','','','','','','','','','','','', + '','','','','','','','','','Goe ','','','','','','', + '','','teng ','zhu ','','','Lung ','','Lo ','','','','','','','', + '','','','','','','Trai ','','xie ','','jiao ','','','','Chong ','', + 'Sung ','','','','','','','','','','','','','','','', + '','','','','','','','Ngoi ','','','','','','','','', + '','','Laan ','','','','','','','','','','qu ','','qiu ','Zai ', + '','','','','','','','','','','hua ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','shu ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','han ','ge ','','','','','','','','', + '','','Ta ','','','','','','','','','','','','','', + ], + 'x22a':[ + '','','','','','','','','','','','','','','','jue ', + '','','','','','','','zei ','','','','','jie ','','','', + '','','','','','hu ','hu ','','','','','chu ','','','','', + '','','','','','','','','','','','','','','','', + '','ju ','','','zhu ','','','','','','Quanh ','','','','','', + '','','','ge ','','','','','','','','','Ho ','','','', + '','','shan ','','Muon ','','Zit ','Hat ','','','','','','Thuon ','Dat ','jue ', + '','','','','','','','','hai ','xia ','','','','','Chop ','', + '','','','cu ','','','','','','','','','','','','', + '','','','','','','','Vuc ','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Ngat ','Vat ','Nang ','','','','','Muc ','','','','','','','zhang ','', + '','','','Keo ','','That ','Vun ','','','','','','Tha ','','','Kam ', + 'jie ','','','','','Wing ','Trot ','','So ','','','','Trum ','Rung ','Quay ','', + '','','','Bac ','','','Haku ','','Ngung ','','','Lat ','','nu ','','', + 'zhe ','','','','','zu ','','','','','','nie ','','','','', + ], + 'x22b':[ + '','','','','Bung ','','','','','','','','','','','', + 'Muc ','','','','','','','Chui ','','','','','','','','', + '','','','Tay ','Khuong ','Giang ','','','','','','','','','Vot ','', + '','Khep ','','','','','','nan ','','','','','dun ','','','Kaai ', + '','','','Dau ','','','Chou ','','','','','','','','','', + '','Thuoc ','','','','','','','','','','','Xac ','','','', + '','','','','','bian ','','','','','','','','','','Quet ', + '','','','Giau ','Khuay ','','','Vom ','','Lan ','Dui ','Xoi ','','','','', + '','','','','','','','','','','ya ','','','','','bang ', + '','Luk ','','','','','','','','','','','','','sao ','', + '','','','','','','','','','Co ','Ron ','','Chut ','Co ','','', + '','','','','','','','','','','','','','','','Quay ', + '','','','','','lu ,jue','','','','xie ','Dik ','','zhai ','','Ngaau ','', + 'Co ','','','Va ','Quat ','Ngoi ','Khep ','Quay ','Huo ','','','Sap ','Buoc ','Ven ','','', + 'Va ','Roc ','Sua ','','','','Lay ','','','','','','','','yu ','', + '','Sau ','wan ','xue ','','','','','','ge ','','','','','mao ','', + ], + 'x22c':[ + '','','','','','','fu ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Wo ','','','','','Gap ','Zung ','pan ', + '','','','','jie ','','','','jia ','','','','jia ','','Boi ','', + 'Gieo ','Waa ','','','','Dap6','','','','Cai ','Phung ','Xoi ','','Nhot ','','Sin ', + '','','Saak ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Kek ','','','','','','','', + '','','','','Bung ','','','','','','','','','Run ','','', + '','Laa ','','Rung ','Cau ','','','Gay ','','Kap ','Mai ','Mo ','','','','', + '','Cau ','Long ','','','Cou ','','Sou ','Lou ','','','','die ','','','zhu ', + '','','Bat ','','','','Ngou ','','zu ','','','','','','','', + '','lang ','','','','','','','','','','','Saai ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x22d':[ + '','','','','','','','Chap ','Daat ','','Chop ','Chong ','','','','', + 'Day ','','Paang ','','','Ning ','','','Xay ','','','','Xau ','','Nhung ','', + '','','fen ','','','','','','','','','','ban ','','','', + '','lei ','xie ,jie','','','','','','','','','','','','','', + '','','','','Cou ','','','yang ','','','','','Deoi ','','','', + '','','','Paang ','','','','','','','','','','','','', + '','','','','','zao ','','Gaan ','','Doi ','','','Don ','','','', + '','Khoi ','','Sum ','Quay ','','Don ','Cat ','Xap ','','','','Vot ','Ro ','','', + '','','','','','Sip ','','','','','','','','Saap ','','', + '','Niao ','guai ','','','','','','','','','','Ngung ','','','Cui ', + 'Saau ','','','Die ','Loe ','','','','','','','','','','','Maan ', + '','','','','','','bang ','','Bum ','','Dom ','Bung ','Ngoi ','','','Don ', + '','Nem ','Xan ','','','Tro ','Chen ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','Ban ','','','','','','','','','','Deoi ','', + '','','Hang ','','','Vo ','liu ','','','','du ','','','','','jie ', + ], + 'x22e':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','Lan ','','','', + '','','','Niao ','','cuan ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Choc ','Gai ','Mac ','Rung ','','Xe ','','','','','yu ', + '','Zaang6','','','','','','','','lan ','','','','','','', + '','','','Keo ','Xau ','','','','Tum ','Suong ','','','','','','', + '','','','xiao ','','','','','','','','','','Giam ','Que ','', + '','','','','','','','yao ','','ta ','','Naan ','','','','', + '','','Bung ','','Bau ','','','','','','','','','Uon ','','chan ', + '','','','','','','','','','','','','','','','', + '','','','Maan ','yu ','','','','','Chia ','Chia ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','cheng ','','','','','','','','','hai ','','','', + '','','','','','','','','sa ','','','','','','jie ,fu','', + '','','','','','','','','','','','','','','','', + ], + 'x22f':[ + '','','','','','','','','','','','','bao ','','','', + '','','','','','','','','','','','','','','','', + '','','','qia ','','','','','','','','jiao ','','','','', + '','','','','','','','','','','xue ','','','','','', + '','','','','','','','da ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','mao ','','','','','','','','','','','jiu ','','', + '','','','','Duk ','','','','','','','','Va ','','','', + '','wei ','','','yu ','du ','','','','','cheng ','','','','','', + '','','kuai ','','','','','','','','','','','','','', + '','','','','','','','','','','','','lu ','','','', + '','','','','','','','','','','','','','','','wen ', + '','','meng ','','','','','','','','','','','','','', + '','','','','','','','','','','','','man ','','','', + '','xie ','luan ','','','','cheng ','cheng ','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x230':[ + 'lei ','','','','qun ','','','','','','','','','chen ','','cheng ', + '','','Chong ','','','','','','','','','','','','','Va ', + '','','','fu ','','','','san ','','','','','','','','sa ', + '','','','','','','','','','','','','','','fu ','', + '','','','','','','','','','','','','','dao ','','', + '','','','','Lon ','','gan ','tan ','','','','','man ','','','', + '','','','','','','','','','','','','','','','', + '','','','','qia ','','','','','','','','','','','', + '','','','','','','','','','','yun ','','','','','', + '','','','','','','','','','','','','','xiang ','','', + '','','','','','','','','','','','','xiao ','','','', + '','','','dang ','','zhuan ','','','','','','','','','','', + '','','','','','','','','','dang ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','yan ','', + ], + 'x231':[ + '','','','','','','','','','','','','','','fu ','', + '','','','','','','','','','Huang ','','','','yan ','','hu ', + '','','','','','','','','','','','','','','','', + '','','','','liang ','','','','','','wei ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Khuya ','Khuya ','','','','','','', + '','jue ','','','','','','','','','','','','','','', + 'xiang ','','','','','Tam ','Luc ','','','','','','','','','', + '','','','','','','','','','','','','','','','Phoi ', + 'Trua ','','xu ','','','xian ','','','','gan ','','','','','','', + '','','','','','','','hao ','','','','','','','Chang ','', + 'Giay ','','','','','fu ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','Sao ', + '','','Bie ','','','','','','dai ','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x232':[ + '','','','','','','','','','','mu ','','','die ','','', + '','','','Phoi ','','Mai ','','Ngay ','','','','Quat ','Ngay ','','Hong ','', + 'bian ','','Tia ','','','tu ','','','','','','','','','','', + 'Nau ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Ui ','Trua ','', + '','','','','','sang ','','ang ','nai ','','','','','','Gou ','', + '','','','','','','','','','ya ','','','','','','', + '','','','','','Rua ','','','','','','','','','','', + '','','','mao ','','','','','','','','Se ','','Mo ','Chop ','', + '','','','','meng ','','','','','','','','','sang ','xu ','kan ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Bay ','', + 'Sao ','Toi ','','','','','','','','yu ','dan ','','','','','pu ', + '','','','','','','','','','','','','','','ai ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Som ','','', + ], + 'x233':[ + '','Trua ','Trua ','','','','Trua ','','','Khuya ','','Som ','Rua ','','','de ', + '','','','','','','','','','','','','','Nang ','','', + 'chun ','','','','','','','','xun ','','','','','','','', + '','','','','','','','','','','Xeo ','','','','','', + 'Nguc ','','','','','','','ju ','','','','Cui ','','Oam ','','cha ', + '','','','','','','','','','','','yu ','','','','', + '','','','','','','kuang ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','Luo ','','','','','','','','','', + '','','','','nian ','','','','','','hu ','','','','Trang ','', + '','','','','','','','','','','','','','','','', + '','','','','Dun ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','shu ','','','','','','','','pai ', + '','','','','','','','','','','','','','','','', + '','','','','Jan ','','','he ','','','','','','','Dak6','Then ', + ], + 'x234':[ + '','','','','','Nhum ','Thot ','','','','','','','','','', + '','','','','','','','','','','','','','Xop ','','', + '','','','','','','','','','','','','','','','', + '','','Queo ','','','','','','','','han ','','','','','', + '','Cung ','hu ','','','','','','','','','','','','Roi ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','Gian ','','','Sim ','','','','Nen ','','','','fu ', + '','','dian ','','','','qiao ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Mang ','','','','','','','','','','','','', + '','Xoai ','Sao ','Cong ','','','','han ','kuang ','','','','','','','', + '','','','','','','','','','sha ,jie','','','Gou ','','','', + '','','shan ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','Lau ', + ], + 'x235':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Cui ','Bap ', + '','Pha ','Xoi ','Ngoc ','','Chanh ','Nhai ','','Kang ','','','','','','','', + '','','','','','','','','','','mao ','','Gon ','','','', + '','','','yu ','','pao ','','','','','','','','','','', + '','','','','','','','','Hay ','','','','','','','', + '','','','','','','','','','','','','Noc ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','yun ','','','','','','','','','', + '','','','','','Peng ','Chay ','Chay ','','','Ca ','','','','','', + 'Suot ','Trac ','','ju ','','','','','','','qu ','','jue ','','ang ','', + '','','','','','','','','','ru ','','','xun ','','','', + '','','','','','','','','','','','','','','','', + 'reng ','','','Chua ','','','','','','','','','','','','', + '','','','','','','','','','','Cha ','','','','','', + '','','','','','','ta ','','','yang ','','','','','Son ','', + ], + 'x236':[ + '','Ca ','','Cay ','Thot ','','','','Son ','Cum ','','','','','','', + '','','','','','','','Nik ','','bang ','Seot ','','','','','', + '','','','chun ','','','Yi ','','','','','','','','','', + '','','','','','','','','','','','','','Nau ','Vai ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','Rac ','','','','','','', + '','','juan ','','','','','','','','Mo ','Sop ','','','Chay ','Rui ', + '','','','','jie ','zhe ','hu ','','Sot ','Con ','Mam ','','','','','', + '','','','jie ','','','','pao ','','','','ye ','','','lei ','', + 'ru ','','','juan ','','Jaap ','','','','','','','','','','', + '','','zhuan ','','','','jiang ','hao ','','','dun ','','','','','', + '','','','','','','','','','','Hong ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','Xanh ', + '','Gu ','','Khay ','','Be ','','','','Then ','Tu ','hu ','','','','', + '','Dom ','','','','','','','ze ','','','die ','','zha ','','', + ], + 'x237':[ + '','','sa ','','','','','','','','','Mo ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','juan ','','','','ai ','','','', + 'Lim ','Son ','','','','','','','','','wen ','','','','Chua ','', + '','','hun ','','','ai ','','','','Duoi ','','ta ','','','','gao ', + '','yu ,yu','','','','','','hu ','','','','','10389.190,bian ','su ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Khu ','Cuoi ','','','dun ','','','','','','','Tram ','', + '','meng ','','lu ','tan ','','','liu ','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'lian ','','','','','','','','','','','','','','','', + '','','','Mong ','','','','xiao ','','huai ','','','','','','', + '','liu ','wu ','','','','','','','','','','','','','', + '','','','','','','','','','Dui ','','','Ran ','','','', + 'yu ','Kyo ','','','','','','','mei ','','lian ','','','lao ','','', + ], + 'x238':[ + '','','','','','','','','','','','','','','','', + '','','Tham ','Pheo ','','Chua ','Chua ','Que ','Gau ','','liu ','','zhao ','','','', + '','','','','','','','','','Tram ','','','','','','', + '','Tram ','','','','','','','','','','','','Ha ','','', + '','','','','','','','','','yu ','','','','','cen ','', + '','','','Tram ','','yan ','','','','','','','','Vui ','','die ', + '','','','','Nen ','','','lei ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','xu ','','','','','', + '','','yu ','','','','qian ','','','','','','','','','', + '','','','','','dian ','','','','','','','','','','', + 'zu ','','','','','','chu ','','','','','','','','','', + '','','','','','','','','dian ','','','','','','yu ','', + '','','','','','','','','','','an ','','','','hun ','', + '','','','dian ','','','','','','','','','','','sha ','', + '','','xie ','','da ','','','','','','sha ','','','','','', + ], + 'x239':[ + '','zhu ','','','','','','','ze ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','shu ', + '','','','','','','','','','','','','','','','', + '','','ta ','wan ','','','','','','','wang ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','guan ','','','','','','','','','','', + '','','','tu ','','','','ta ','','chu ','','','zhu ','','da ','', + '','','','','','','','','','','','','','Ngay ','','', + '','','','','','','','','','','','','','','','', + 'chu ','chu ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Laai ','du ','','','','','die ','','','','','','','', + '','','','','','','','','','bai ','','dian ','','qiu ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','nao ','','', + ], + 'x23a':[ + 'luan ','','die ','','qia ','','','mao ','','','','','','','','', + '','','','wu ','tao ','','','','','','','zu ','ma ','','','', + '','','','jiang ','xu ','','','Giuoc ','','','','','','Quan ','','', + '','','du ','xiang ','','','','','','','','','','','','hun ', + '','','','','','','','','','','','','','','','lu ', + '','','','','guan ','','','','','','er ','','','','','', + '','','liao ','','','','Ngoeo ','shan ','','','','','','zhai ','','ye ', + 'diao ','','','','jiang ','','','','Toi ','huai ','yu ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Ji ','','','','','','','','','','dian ','','','bian ','','', + '','','','','','','','','gu ','','','','','','','', + '','','','','','','','','hu ','','','','','','su ','', + '','','','','','','','','','','','','dao ','','','', + '','','','','','','','','','','','','','','','', + '','','','','xie ','','','Van ','','dai ','','','','','','', + ], + 'x23b':[ + '','','guan ','','','','pei ','','','','','','','','jue ','juan ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','ba ','ba ','','','','','','wu ','','', + 'bao ','','','Su ','','','','','','','','','','','','', + '','','','','','','','','fu ','','','','','ge ','','', + 'ru ','','','','','','','','','','','','','','','Ria ', + 'Mao ','','','qiu ,qu','','','','','','','','Mau ','','','','', + '','','','','','','','Ngu ','','','de ','','jie ','jie ','','', + '','','','','','','','','','','','','','','','', + 'san ','','chun ','','','','nai ','','','','','','','','','', + 'de ','','','','','','','','','','','','','','','', + 'mao ','','','','','','','','','','','ru ','','','wu ','', + '','','','','','','','','','','ta ','','','','','', + '','','','','','','','','','men ','','','','','','', + '','pei ','','','','','','','qu ','','','','su ','','','', + ], + 'x23c':[ + '','','','','','','','','','','','qu ','','','','', + '','','','','','sao ','','','kun ','','','','','','jie ','', + 'qu ','qu ','','','','meng ','','','','','','','du ','','','', + '','','','','','','','','','','','qu ','','','','', + '','','kun ','','','','Ho ','','','','','','','dan ','','', + '','','','xiao ,hao','','','','','','','','','','','','', + '','','','','','','','','','','','','Hoi ','','','', + 'Ram ','','','liu ','','','Vuc ','','','','','','','','','Nhop ', + '','','','','','','','','','','','','','Ngut ','','', + '','','','','','','','','','','','','','','','', + 'Ngot ','','','','','','','','','','','','','','','', + '','','he ','','','','','Nap6','','','','','','','guai ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','fan ','','','jie ', + '','','','','zhan ','','','','Deoi ','','','','','piao ','','', + '','','','','','','','','','','','','Doe ','','','', + ], + 'x23d':[ + '','','','','','','','','','','','','','','','', + '','','','jian ','','','','','','','Hup ','Nhung ','','','','', + '','','zao ','zhuang ','','','','','','','','','','','','', + '','','','','','','','','','','','','mao ','tan ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Bung ','', + '','','','','Ngam ','','','','zhu ','','','','gan ','','','', + '','','','','','','','','','','','','','zhuang ','','', + 'pao ','','','','','','','','su ','','','','','ju ','','', + '','can ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Loi ','', + 'Nhom ','','','','','','','','','','','','','','','', + ], + 'x23e':[ + '','','','xu ','','','','bian ','','','','','','','huai ','', + '','','','','','','','','','','she ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','fu ','','','','', + '','','','','','Lut ','','Tran ','','','','','','qiao ,xiao','','Cong ', + '','','','','','qian ','','','','xie ','','','hu ','','','xun ', + '','','','','','na ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','tao ','', + 'qiao ','','','','','','','','','','','','','','','', + 'Nuot ','','','Bui ','','','','Xoi ','','Duoi ','','','','dang ,xiang','','', + '','','','','','Ma ','','','','','shu ','','fu ','','','', + 'xie ','lang ','','','','','','','','zhe ','','','can ','','','', + '','','','','','','','','','','','','','','','', + ], + 'x23f':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','lu ', + '','','','','','','ze ','shuai ','','','Bot ','','','','','Vui ', + 'Lung ','Ngau ','Doi ','Xop ','','','','Lot ','','','','','Tran ','Lang ','','', + 'Ngau ','','','','','','Veo ','','','ru ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','an ','jian ','','53066.030,teng ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','Doi ','','','','Khoi ','','','Xoi ','Bui ','', + '','','','Ngau ','','','fu ','','su ','','lian ','','he ','','','', + 'ze ','','','','','','','','','','','','','','','', + '','','','xiao ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x240':[ + '','','','','','','','','','han ','','','','','','', + '','','','Loc ','','','Ngoi ','Rua ','Vung ','','','','Tanh ','yu ','','', + '','','','','','','la ','','','jian ','','','','','','', + '','','bian ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Dao ','Khoi ','','','','Trong ','Bot ','','Chua ','','','','', + 'Dao ','dan ','jie ','bai ','','','xian ','','','','','','','','','', + '','cai ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','zhuan ','','','','','Rua ','Dan ','Phun ','Loi ','Toe ','','', + '','','','','','','','','','','lan ','','yao ','','','xuan ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','Leo ','','Muong ','', + '','','','','','','','Thuot ','lan ','','','','','','','', + '','','','','','','Deng ','','','','xun ','','','','','', + ], + 'x241':[ + '','','','','','','','','','','','','','','','', + '','fan ','','','','','','','','','','','','','','', + '','','','','','ta ','','pan ','','','','','','','','Trong ', + 'Nhan ','','Can ','','','','','','','','','','','','','', + '','','','','','','','','','','yan ','','','','man ','', + '','','can ','','','','','','','','','','Veo ','','','', + '','','','men ','','','','','','','','','','','','', + '','','shuan ','','','','','','','','','','','','','', + '','cheng ','','','','','','','','','','','','Chi ','','', + '','','','','','','','','','','','','gua ','','xu ','', + '','','','Saap6','','','','','','','','','','','','', + '','','','','','','','','Tom ','','','','','','','', + '','','','','','','','','','','','','Kho ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','Say ','Phoi ','Tat ','','','','','Bep ','', + '','','Nhum ','','','','','','','','','','','','Ying ','', + ], + 'x242':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Lui ','', + 'Sot ','Ngut ','','','','','','he ','','','Cho ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','lao ','shao ','', + '','','','Tro ','','Tro ','Se ','Heo ','Ngun ','','','Toa ','Rang ','','','', + '','','','','','','','','fu ','','','kai ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Luk6','','','','','','','','','','','','','', + 'Roi ','','','Tro ','Nhem ','','','','','Rom ','','Phoi ','Phoi ','Lom ','','', + 'Ben ','','','','','','la ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'zhu ','','','','','','Ranh ','Nau ','Khet ','Kho ','','Phoi ','Kho ','Choi ','Um ','', + ], + 'x243':[ + '','','su ','','','','','','','','','','','Hok ','','', + 'han ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','gan ','','','','','','', + '','','','Hay ','','','Ngot ','Nau ','','Ngun ','','','','','','', + '','Chong ','','shu ','','Jau ','','','','','','','zao ','','','', + 'Jit6','','','','Zhang ','','','','','','','','','','','', + '','','','','','','Loa ','','','','','','','','','', + '','','','','','','','','','','','','','Quac ','','', + '','','Phap ','','','Tat ','','','','','','Ram ','','','','', + '','','','','','','','zhu ','','','','','','','','', + '','Zuan ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Nhoi ','','Ho ','Thui ','Khet ','Thap ','Se ','','Rao ','Buot ','','','','', + '','chu ','Zhou ','','','','','','','','','','','','','', + ], + 'x244':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','Ham ','Nau ','','Soi ','','', + 'Luoc ','','','','','','','','','kai ','','','','','','', + '','','cuan ','','','','','','','','','','','','','', + '','','','xian ','','','','','Chang ','','','','','Hung ','','', + '','','','','','Xun ','','','','','','','','','','', + '','','','','','','','','','','','Bung ','Loe ','','','Sem ', + '','','','','','','','ye ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','Nung ','Nau ','','yao ','','Nhui ', + '','','Lom ','','','','Sem ','','','','','','','','','', + '','','','','Thap ','','','','','','','ta ','','','','', + '','','','','','','Ram ','','','','','','','','','', + '','','','Lo ','','','','','','','','','','','','', + '','','','','','','','','','Ben ','','','','','','', + '','','','','','','','','','','Vau ','','','','dao ','', + ], + 'x245':[ + '','','','','','','','','','','','ju ','','','','', + '','','','','','','','','','','shang ','Su ','','','','', + '','','','bao ','','','','','','','','','','','','Vuot ', + '','','','','','','','Danh ','','','','','','','','', + '','','','','','','','','','','shen ','','','','','', + '','','','','Cha ','','','','','','','','','','zhu ','', + '','','','','','','','','','','','','','Jiang ','','Jiang ', + '','','','','','','','diao ','','','','','','','','', + '','','','','','','zhan ','','','','','','','','','', + '','','die ','ze ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','he ','','','','ju ','','','','Lop ','','','','xiang ','','', + '','cu ','','','','','Mui ','','Sip ','','','','','','','pei ', + '','','','cheng ','','','','','','','','lian ','','','','', + '','','','','','','','','die ','','shu ','','','','','', + '','','Tam ','','','pu ','','','','Phuon ','','chan ','','','','', + ], + 'x246':[ + 'dao ','','','','','','','','','','','Nga ','','','','', + '','','','Nanh ','hu ','','','','','','','chun ','','','','', + 'tian ','','','chen ','','','','','','','','','','','','', + '','','zhuang ','','','hu ','','shu ','','','','','','','','', + '','','','','','bai ','','','','','','','','','','qu ', + '','','xie ','','zhao ','','','','','','','tu ','','','','', + '','','','','','','','','','','','','','','Ngau ','', + '','','','','Caau ','','','','','','','','','','','', + '','','','','','mu ','','Nghe ','','','die ','','','','yu ','', + '','','','','','','','','','','du ','','','','','', + '','du ','','','mei ','','Co ','Sao ','','','','','','','','xiu ', + '','','','','','bu ','','','','','','','','','','', + '','','','','','','','Chan ','','','','','','','','', + '','','','','','','','','','','','','','su ','Nghe ','', + 'Trau ','','ceng ','ta ','','','jue ','xun ','','','','','','qun ','','', + '','','','','','','','','','','','','','','','', + ], + 'x247':[ + '','','','','huai ','','','zhan ','','','','','','','','', + '','','','','ju ','ba ','lei ','','','','','','','','','', + '','','','','zhe ','','','','','','','','San ','Tu ','','Kap6', + '','','','','','21335.010,yan ','','hu ','','yu ','','','','','','', + '','','mu ','','','','','','','','','','','','','', + 'hao ','Muop ','na ','','','','','','hu ','','','','','','Chuot ','', + '','','','','','','','bao ','','','','','','','lu ','', + '','','','','','','','','','Chu ','','','','','','', + '','','','','','','','','','shu ','','','','','','', + '','','','San ','Thac ','Tay ','','','','','','zang ','','','yu ','', + 'cha ','xie ','','','','','Moi ','Khon ','','','','','','','','', + 'qiu ','','hu ','zai ','jue ','','han ','','','','','Hum ','','','','an ', + 'zao ','','','sha ','','xian ','','','','an ','','','','zhe ','jue ','', + '','','','','','','','','lu ','','','','','xia ','xiao ','', + '','','dun ','','','','','','','','tu ','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x248':[ + '','','','','Ga ','Voi ','','ge ','','','','Trau ','','','','', + 'ta ','Lau ','','','','','','','','','su ','','','','','ta ', + '','','','','','','','','','','fu ','','','','','', + 'Gau ','','','','','','','','','','','','','cu ','','', + '','','','su ','','','','','','','','','','','','', + '','','','','','','','','','','','Nanh ','','','','huan ', + '','','','','','','','','','','','','','','Ran ','', + '','','','','','','xu ','','','','','','','','','', + '','huan ','su ','','','','','Vuot ','San ','','lu ','','','','','', + '','','','ju ,qu','Nhen ','Dou ','','','su ','','','','','','','ze ', + '','','','','','','','','','','Lie ','','','','','', + '','','','','','ai ','','','','','xie ','','','Nhat ','','', + '','','','','Beo ','','','','','','','','xiao ','','','', + '','xie ','','','','','','','','','','','','','','', + '','Doc ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x249':[ + '','','','','','','','','','','da ','','','','','', + 'su ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','wai ','','','','', + 'Vua ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','su ','','','liu ','','','','','','','','', + '','','','','','','','','','','','','','Xa ','','', + 'mao ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','Cung ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','yu ','Cong ','','','','','', + '','','','jian ','','','','','','wan ','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x24a':[ + '','','','','','','','','','','','','','lu ','qu ','', + '','','','','','','hu ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','zhuan ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','hao ','xiang ','','','hao ','','', + '','dian ,tian','ge ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','chan ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','qia ','jiao ','','','','','','','','Dua ', + ], + 'x24b':[ + 'Dua ','','','','','','','','Hau ','','','','','','','', + '','','','','','','','','','','','Lu ','','yan ','','', + '','','','','','','wa ','zu ','fan ','','','','','','','', + '','xu ','','','','','','na ','Sanh ','','','','','','','', + '','','','','','','','','diao ','','','','','fan ','','', + '','wu ','','','','','','','','','','','','','','fu ', + 'na ','','','','','','','','','','','','','','','', + '','hu ','','','su ','','','','','','','','','xu ','','', + '','','','Ang ','','','','','','','','','','','lei ','heng ', + '','Be ','','','','','','Lo ','','','lei ','','shan ','','','', + 'Muong ','','','','','','','lu ','Lung ','','jun ','','','Chan ','','xie ', + '','zhe ','','','','','','liu ','lei ','','','','dai ','','Ngot ','Ngot ', + '','','','','','','Ngon ','','','','','','','','','', + '','Lam ','','','','','','','','','','','','','','', + '','','','','','','','','Song ','Song ','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x24c':[ + '','','','','','','','','','','','','','','','', + '','pu ','','','','','','','','','','','','','','hang ', + '','','','','','','zha ','','','','','','chao ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','na ','na ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','diao ','','','','','','', + '','','','','','','','xie ','','','','','','fu ','','', + '','','Duoi ','','','','','','','','','','Ruong ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','juan ','','','','','','','', + 'mao ','','','','','','','','','','','','','','','', + '','','','','','cha ','Trai ','Trai ','','han ','','','','','','', + '','','','','','yu ','','','','','','','','','','', + '','','Trong ','','','','','','Roc ','','','','','','','zhu ', + 'Ve ','Ruong ','','','lei ','','','','','','','','','Ruong ','','', + ], + 'x24d':[ + '','','','','','','','','','','','','','die ','','', + '','','','','','','','','','','','','','','','', + '','','','','','Ngat ','','','','','','','','Bot ','','huan ', + '','du ','','','','','','','','','','','','','','', + '','','','','','','','','','','du ','','','','','', + 'wu ','','wen ','','','','','','','','To ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','Si ','','','qia ','','','','hai ','','', + '','','','','','','','','Tay ','','','','','','Chau ','', + '','Nhan ','Ben ','','','tun ','fu ','','','','','','zhuang ','','','', + '','','','','','','','','','','','','','','du ','', + '','chuan ','','','','','','','Naa ','Guoc ','','Nghen ','Mang ','Mut ','','', + '','','fei ','jian ','','','','Wak6','','','','','','','','', + '','jiu ','','','lun ','','','','dao ','de ','','','','','','la ', + '','','ju ','','','','','','','','Mang ','Cek ','','','','Loet ', + '','','','Nhom ','','','Buou ','','','wai ','','','','','','', + ], + 'x24e':[ + '','','','','','','','','','','dai ','','','','','', + '','fu ','Ngung ','','','','','fu ','','','','','','','','', + '','','','','','','','Hoen ','','','','yun ','','','su ','', + '','','','','','bu ','','qun ','','','','Naa ','','','','', + '','','','','','','','','','','','jue ','','','','', + 'Lit ','','','','','','Hen ','','Nhoc ','Choc ','','chen ','','','','', + '','','','hu ','teng ','','','','lian ','','','','','','','', + '','','','','','','','','','','','','Buou ','Not ','','Ngo ', + '','','','','','','','bian ','','','','','','','','', + '','','','Bie ','','','','','','','','','','','','', + '','','','','','','','Zang ','','','shan ','','','Buot ','Gua ','Mun ', + 'Khom ','','','','Buou ','','','','','','','juan ','lu ','','ao ','', + '','','','','','','','','','','','','','','Cum ','', + 'Hom ','','Toi ','','','','','','','','','','','','','', + '','','ai ','','','','','','','','','Nhoi ','','','','', + '','lu ','','','','','bian ','','','','','','','','','', + ], + 'x24f':[ + '','meng ','','','','','','','','','','chan ','','','','', + 'guan ,huan','','','','','','','jue ','lei ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','ju ','','','','','Dang ','','','','','','','', + '','','','','','huan ','','','','','','','','','','', + '','','','er ','','huan ','','Nguoi ','','','','','','','','', + '','','','chang ','','','','','','','','','','','','', + '','zu ','','','','Phau ','','','Trang ','bai ','lu ','','','','','nian ', + '','','','','zhu ','hu ','','','','','','','','','','', + '','','','Tram ','Vang ','','','','','','','miao ','','','','Ho ', + '','','','','','','','','','','','yao ','','','','', + 'Nguoi ','','','','','bie ','','','','','','','','','','', + '','','Saai ','','cun ','','','','','','','','','','Pi ','nan ', + '','','','','','','','wa ','','','','','','','','xun ', + '','','','cheng ','','','Da ','han ','xiao ','','Zaap ','','','','','', + 'Trong ','','','','lu ','','','','','','','','','ta ','','', + ], + 'x250':[ + '','du ','','','','','','','','','','','Giay ','','','', + '','','','liu ','lu ','','','','','','','','','','','', + '','','','xue ,qiao','','la ','','','','','','','Jim ','','','', + 'la ','','du ','Mo ','','lu ','','','','','','','','','xiang ','', + '','','jie ','mang ','','','','','','','','','','','','', + '','','Ngaau ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','diao ','', + '','','','','','','','','','','','','','','','', + '','Jim ','','ju ','','','','','','Trom ','','tu ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','hu ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'cha ','','','','','','','','','','','','','','','', + '','Mam ','','','qu ','','','','','','Mam ','Mam ','','','','', + '','','','','','','','','Vuc ','','','','','','','', + '','Nhap ','','','','fan ','','','','chuan ','yao ','','','','du ','', + ], + 'x251':[ + '','meng ','','','','','','','mu ','','','','','','Cik ','', + '','fu ','','','','','','','','','','','','mian ','','', + '','','','','','','','','','','','Gap6','','','Nham ','Ngom ', + 'Nhon ','','mie ','','Xue ','xu ,yu','','','','bao ','','','','','','', + '','','','Nhon ','','','','','Laap ','','','','','','','', + '','dian ','fan ','','','','','','','','','','','','','Ngaau ', + 'Hau ','er ','','','','','','','','','','','','','','', + '','','Chau ','','','wei ','','','','','xu ','','','','Zong ','', + 'Giuong ','','','Nho ','','','','','','yu ','','','jue ','','','', + '','','','','','','','','','','','xu ','wang ','','juan ','', + '','','','','','xie ','liu ','','','','','','','','','', + '','','nao ','','','','wan ','jiu ','','Ngop ','Dau ','Ru ','Le ','','','Quau ', + 'Mang ','Tro ','Bet ','','','','','','Nhon ','','','','han ,qia','','','xu ', + '','','jie ','','','','','','jun ','','','','','','dian ','', + '','','','Gwat6','','','','','','','','','','','','mai ', + '','','','','','','Him ','','','','','Tro ','','','','xu ', + ], + 'x252':[ + '','','','','chuang ','','mao ','','','huan ','sha ','','','','','kuang ', + '','','','','','','die ','','','la ','','lu ','','','','Sou ', + '','','','','','','','','','','','','','','leng ','', + '','','Kip ','Chot ','Nguoc ','Nhon ','Nam6','','','','','','','','','', + 'guan ','ju ','','nai ','','ge ','','','','','ma ','teng ','','','','', + '','','','','','','','','','','','','chen ','','','', + '','','','','','','','','','','','','Let ','','Soc ','', + 'han ,qia','','','','','Ma ','lu ','','','','die ','','','','','', + 'Xam ','','','','','','','','','','xu ','','Caau ','','','', + '','','','chan ','','','','','Ghe ','Zong ','','','','Chop ','Quac ','Nhan ', + '','','','','Nguoi ','','Mu ','','','','','guan ','','zun ','','xie ', + '','','','','Toet ','','','','','','','','','','','', + '','','','','','','','Caang ','','','','','Sa ','','','', + '','','Tre ','','','Trom ','','','Saau ','','','','','','','Xi ', + '','','','jia ','','','','','','','','','','','','', + '','','Lem ','Coi ','Ngam ','Him ','Lam ','','Soi ','','','','','','','', + ], + 'x253':[ + 'Xet ','','','','','','','','Trom ','','pan ','','','','','', + 'liu ','','','','','','','','','','','Lai6','','','','', + '','','','','','Khoe ','Len ','','','','','','','xuan ','','meng ', + 'wei ','42521.120,meng ','','','','','','','Dim ','Ngam ','yao ','','','','','', + '','','','','','','','','','','','','','Lom ','','', + '','','Cham ','','lei ','','','','Nheo ','','bian ','Ngom ','','','','', + '','','','hao ','','','','','','','zhai ','','','','','', + '','ze ','na ','','','','','','','','','','','','','', + '','','','','','','kai ','','wu ','','','','','ze ','','', + 'yu ','zan ','','','','xu ','','xu ','','','','','','','','', + '','','cuan ','cuan ','cuan ','','','','','','','','','','','', + '','','','','','','','','qia ','','tiao ','','','','','', + '','','','','','','','huan ','','','','','','','','', + '','','wu ','','','','','','jue ','','','','','ya ','','', + '','','','','kua ','','','','','','','','','','an ','zhe ', + '','','','','','','','','','','','','','','','Van ', + ], + 'x254':[ + '','pu ','','','','','Van ','Ngan ','So ','Ngan ','','','','Ngan ','','Coc ', + '','','Cut ','','Van ','ya ','','','Shi ','','','','','','Mong ','', + '','','','','','','','','','yun ','','','','','','', + '','','','','','','','','','','','','','zhe ','','hu ', + '','','Chai ','','','','','die ','','','','guai ','','','','', + '','ao ','','','','','','','','','','','','','','', + '','','bu ','','','Sinh ','','','','','Nao ','','','','','du ', + 'guai ','','Ran ','','','','Loi ','','','','','','dian ','','','', + 'wu ','','','','','','','','','','','','','','','', + '','','','','','','','','xun ','','','','','','','', + '','','','','','','','ya ','lu ','','','','','chu ','','', + '','','','kang ','','','hua ','','','','','','','','','', + '','','','','Mai ','','','','','Sanh ','','','','du ','','', + 'jie ','','xian ,kan','','','','','','','','','','','','','', + '','','','','','','','','','','','','dao ','','','', + '','','','','Mai ','','','Canh ','','','','','','','','Tuo ', + ], + 'x255':[ + 'Gwang ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','yu ','','','','','','','','','','','','','', + '','shan ','','','','Ji ','','','','','','','','','','Ham ', + '','','','','Mai ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','zhe ','','','','','','','','','','','','', + '','','jue ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','la ','','', + '','','Quanh ','','','','','','','','','','','','','', + '','','','','','','','','zao ','Cuoi ','','','','','','', + '','','','','','','','','','','','','','','','du ', + '','','','','','','','','','','','','','','','', + '','','','ta ','','','','','','','dao ','','Chen ','','','', + '','','','','','','','','Nen ','','','qu ','','ca ','','', + '','','','','','xiang ','','','','','lan ','','','','','', + ], + 'x256':[ + '','','','','yu ','','','','','','jiao ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','fu ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Rung ','','','','','','','','','','','','', + '','','','xun ','','','ru ','','','Lay ','','','','','','', + '','','','','','','','','','','','','','','','yu ', + '','','jun ','','','','','','','','lu ','','','','','', + '','','','','','','','','','','','','','','','', + 'zhun ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','liu ','','','','','','','','','','', + '','nu ','','','','','','','','','','','','feng ','lu ','', + '','','','','','zhuan ','','zhe ','','','lu ','','','','','jue ', + 'liao ','','','','','','','','','','','','','','','', + ], + 'x257':[ + '','','','','','','','','','','','','Ao ','','','', + '','','Yan ','','','','','','','zan ','','','','','','', + '','','','','','Yi ','','','','','','','','','jun ','', + '','','','','','','','','','','','','','','','', + 'she ','','','','wan ','','','','','','','','','','','', + '','','gua ','','jie ','','he ,xie','','','','','','','','','du ', + '','','Li ','','','jie ','','ba ','yu ','','','','','','','', + '','','','','','','','','he ','','','','','Cay ','du ,zha','', + '','','','','he ','','','','','','','','','he ','','zhu ', + '','','','','','','Giong ','','zun ','','ru ','Duo ','jiang ','','','', + '','','','','','','','heng ','','','','','','','','zu ', + '','','','','ku ','','','','','','','','','','','', + '','','','he ','','','','','','','','','','','','', + '','','','','','','','','','','chang ','','','','','', + '','','','','','','','','','','mao ','','','','','', + '','','','','','','','','','Lui ','','','Bap ','','','', + ], + 'x258':[ + '','','','','','huan ','','','','','','','','','','', + '','','','','','','','','','','','','yang ','','','', + '','','','','','','','','','','','','Trau ','Giong ','Rom ','Rom ', + '','','','','chang ','','','liu ','','jie ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','jun ','jiao ','','','','','','','','','','','', + '','','','','Ji ','','','','','','','','','ai ','','', + '','','','Nanh ','Mam ','','','','','','','','','','zun ','', + 'Cau ','','','','','','','','','','','','','','','hu ', + '','','','','','','','','','','','','','','','', + '','','cheng ','','','','kuai ','','ge ','xie ','','jie ','','','','', + '','','','','','','zu ','','pu ','','','','','','','', + '','','','','','','','','','','','meng ','','','','xiang ', + '','','','','lu ','','','','','','','','','','','', + '','','','','','','','','mu ','ran ','','','','','','', + ], + 'x259':[ + '','','','','','','','','','','','zhe ','','','','', + '','','','','','','','','jue ','','','','','','','', + '','','','','','','ai ','','nu ','','','','','','','', + '','','','','','mian ','','','','','','','','','','', + '','','','','','Lung ','','','','','','','','','','', + '','','','','','','','','','','','','','','','wa ', + '','','','','','','','','','','','','','','','', + '','cheng ','','','','yang ','','','','liu ','','','','qiu ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','fu ','','','','','','qia ','dian ', + '','','jiao ','','','','','','','','','','','','','', + '','','','','','','xian ','','','','','','','','','', + '','','','','','','','','','','','','','','Hang ','', + '','','','','','liu ','','','','','','','','','','', + '','','','tu ','','','','','','Nup ','','','','','zhe ','', + 'hua ','','','','','','','fu ','','Tam ','','qu ','','','','', + ], + 'x25a':[ + '','','','','','','','','','','','','liu ','fu ','dan ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Trong ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','Hoam ','','Chui ','','','','','','', + '','','','','','','','','','','','','','ca ','','', + '','','','zhu ','hai ','','','','','','','','','','','', + '','','Hai ','','','','','','','','','','','','','', + '','','','','','','','','','','','fu ','','','','', + '','','','','','','','','','','fu ','','','Trong ','Trong ','', + '','','','','','','','','','','','','','','','', + '','cu ','','','pang ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','dun ','','','', + 'lu ','Deon6','','','','','','','','chen ','','','huang ','shi ','','', + ], + 'x25b':[ + '','','','','','','','','','','','','','','','', + '','','','yao ','','','','','','ju ','','','','','','', + '','','','','','','','','Khau ','Nia ','','','','','Giang ','Kao ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Mang ','Mau ', + '','qiu ','dun ','','','','','','','','mang ','','','miao ','yuan ','', + 'wu ','','','','','','','','','','','','fei ','','meng ','', + '','','','','','','Mang ','','','','','','','','','', + '','','','','','','','Buong ','Hum ','Bu ','','','','','','', + '','','','','','hang ','','ju ','nian ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','Manh ','Tre ','Mui ','','', + '','','Toi ','Trum ','','dang ','du ','','ye ','','','','','','','pai ', + '','','','','','','jian ,sha','','','','Trau ','','','','yu ','', + '','','','','','','','','zhu ','','','','','','','', + ], + 'x25c':[ + '','','','','','','','','','','Thap ','','','','','', + '','','','','','','','','','','','fu ','','','','', + '','','shan ','liu ','','','','','','','hu ','','','','','', + '','','','xian ','','','','','','','','mu ','','','zhai ','', + '','','nu ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Ro ','','','','Ghi ','Gianh ','','', + '','','','','','','','','','','','','','juan ','','', + '','','','','dan ','','','dan ','','hu ','','','','','lu ','chuan ', + 'wu ','','','','','','','du ','','','shuang ','fu ','ju ','','','diao ', + 'wang ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','fu ','','','','','','xun ','','', + 'Khay ','','','','','','bu ','','','','','','','','','', + '','fen ','dian ','','','','','','','','suan ','','an ','','','', + '','','du ','','','','','','dan ','','','','','','','', + ], + 'x25d':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','Thung ','Mui ','','','','','','','', + '','','','','','','','','ai ','ge ','ju ','tun ,dian','','qia ','','', + '','jian ','','','','suan ','','','','','','qiang ','','','','', + '','','','','','','','','','','','','','','','dian ', + '','','','','','','Toi ','Hom ','Ray ','','Lak6','Nong ','','','jie ','zhu ', + '','','','','zhao ','','','','','','','','','','','sa ', + '','','','','','','','','','','','','','','','Mung ', + 'Thung ','','Gay ','','','liu ','','','','','','','','','','', + '','','','','','','','','','','','','hu ','','','', + '','','','','','','','','','','','','','','Toi ','', + '','','','','','','','','','','die ','','','','','', + '','ban ','','','','','hu ','','','','','','','','','', + '','','','','yu ','die ','','','','','','','','','yu ','', + '','','','','','','','','','','','','','','','', + '','fu ','','','','','','','','','Mo ','May ','cu ','','','', + ], + 'x25e':[ + '','Nan ','','','','','','','dang ','','','','','','','', + '','','','','','','','','','','','','','Trum ','','', + '','','','shan ','yu ','','','','','','yu ','','','','','', + '','','','','','tun ','','','','','','','','','','', + 'Tam ','','','','','','','fan ','','Nap6','','','','zhu ','','', + '','','','','yu ','','','','','','','can ','','','','', + '','','','','','','','','','','','','','','','', + 'Lau ','','','','bu ','chu ','','liu ','Bot ','','','','','','','', + '','','','','','','','','','','ge ','','','','','', + '','Tam ','','Lo ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','Com ','','','','', + '','','','','','','','xian ','','he ','','','','','','', + '','','','','','','','','','','Nam ','','','','bu ','No6', + '','May ','','','','','sa ','','','mian ','','','','','','', + '','','','','xia ','','','','Bun ','','','','','','','', + ], + 'x25f':[ + 'zu ','','','ze ','','','','','','','','','','','','', + '','','','','','Lep ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','xiao ','','','Thung ','','','','','','','','','Com ','','xian ', + 'jian ','','','','Men ','','','','Miao ','','','','','','','', + '','Phan ','','','Xia ','','','','','','','','niang ','','','', + '','','','','','','he ','','lian ','','','','','','','', + '','','','Men ','','zhu ','','','','','','reng ','jie ','','','', + '','','','','','wu ','','','','','','cu ','','','','', + '','','','','','','','fu ','hu ','','','','','','jue ','diao ', + '','','','','','','','','','','','','','','Buoc ','', + '','Vuong ','Tim ','na ','','','','','','','','','','','','', + '','','','','','','','Giay ','','','','','','dai ','','', + '','','','','Khau ','','','','','','','','','','','pai ', + '','','','','','','','chao ','','','','','','','','', + ], + 'x260':[ + '','','','','','','','Jing ','','','Dai ','','','','','Thua ', + '','','','','','','Kep ','','','','','','zhuang ','','','', + 'liu ','','','','','','','','No ','','','','','','','', + '','','','','','','','','mao ','Thun ','Xe ','Cui ','Noi ','Keo ','Rang ','', + 'Boi ','Nuoc ','','','','','zhuan ,juan,shuan','nian ','','','hua ','','','','','yan ', + 'jue ','','','','','','','','','','','','die ','','','', + '','','','Go ','','','','','','','','','','','','', + '','','','','','','','','','Ro ','','','May ','Vuong ','','', + '','','','','','','','','','','fu ','','','','','', + '','','','','wan ','','','Sok ','','','','The ','','','','', + '','','','','','Dam ','','','','','','','','','','', + '','','','','','','','','','','','Luot ','','','','Buoc ', + '','','','','','','','','','','','','','','','', + 'Tao ','','','liu ','he ','','','','','','','','','','','', + '','','','','mu ','','','','','','','','','','Gai ','', + '','','','','','','','','','','','','','','','', + ], + 'x261':[ + '','Thun ','Dai ','','Quan ','','May ','','','','','','Chap ','','','', + '','','','Xau ','die ','','','','','','','','','','Van ','', + 'Nut ','','','Cuon ','','','','','','','','','','','','', + '','','','','Chai ','','','','Xung ','','Rang ','Quan ','','qu ','','', + 'xun ','','','','zhe ','','dian ','','','','','','','','','', + '','xun ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Tan ','', + '','Thua ','','','','','','','','','','','','ju ','','yun ', + '','','','','','','','','','','','lai ','','','','', + '','','','','','','','','','','Neo ','','','','wu ','Mung ', + '','','','','','','','','','','','','','','','Ban ', + '','','','','','','','','','','','la ','','','','', + '','','','','','','','','','','','','','','','', + '','','Roi ','','','','','','','','','la ','','','','', + '','','','','','','','','','','','','yao ','','Chung ','', + '','','','','','','','','he ','','','','','','','', + ], + 'x262':[ + '','','Nhau ','nang ','','die ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','yu ','','','','','','','','','','','','', + '','','','','','','','','yu ','','','','','','','', + '','','','','','','Cha ','','','liu ','','','','','','', + '','','','','','','','','Caang ','bian ','','','','','','ya ', + '','','','','','','','ya ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','hu ','cen ','','','','','','','','','','','','', + 'ju ','','','','','','','','hu ','','Bon ','Tu ','','','','', + '','','','','','','fu ','hu ','','','','','','','','', + '','','','','','','','','','','','','','meng ','fu ','liu ', + '','','','','','xie ','','','xian ','','','','','','','', + '','','','','lu ','','','','','','','','','','','', + '','','yu ','han ','','','Ra ','','','','dan ','','','','','yu ', + '','','','','','','','','','','','','','','','', + ], + 'x263':[ + '','','','','','','','','','su ','su ','','','','','', + '','','liao ','','','lu ','','','','','','','','','','lu ', + '','','','','','','huan ','','','','','','','','','', + '','','','','','','','du ','','','','','','','','', + 'nan ','','','','','quan ','','','','','','','','','','fen ', + '','','ta ','tun ','','','','','','','','','','','','', + '','','','','','','','','','Gu ','fen ','','','','','', + '','','','','','','','','shan ','','','','','','','', + '','','','','su ','','','chuan ','','','','','','','','', + '','','jie ','','','','','','yu ','','','Guong ','chuan ','','','', + '','Xinh ','','','','','wu ','','','','','','Tanh ','fu ','','', + 'gu ','','','','','','','','','','','','','','','', + 'ren ','','','','','jue ','','','','','','','','','','', + '','','','Bon ','','du ','','hu ','','','','','yu ','','','', + '','','mai ','','','','','','huai ','','','','','','','', + '','','','','','','','','','','','yu ,yu','','','','', + ], + 'x264':[ + '','','','','','','','Taap ','Fen ','','','','','','','', + '','','','','','','','','','','','qu ,yu','','','','', + '','fu ','','','hai ','','','','','','','','','','','', + 'chai ','','','','','','','','','','','','','','','', + '','','','','','','','ta ','','','','zu ','','xu ','yan ','chai ', + '','','','','','','','','','','','','ge ','','','', + '','','','','','','','','','','','','','','','', + '','','ta ','','','','ta ','','','fu ','','','','','liu ','', + '','','','','','han ','','','','','','','','','','he ', + '','yu ','','','','','','','','','','','Zin ','','','', + '','','','','','','la ','','','','','','','','','', + 'tai ','','','','','Khu ','shu ','Bou ','','','dao ','','','','','', + '','','','','','Gia ','','Khu ','','Lu ','','wang ','','','nai ','', + 'jue ','','','','','','','','','','','','','','','', + '','Ma ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x265':[ + '','','','','','tu ','','','ze ','','','','','fu ','','', + '','','','','','','','','','Cay ','','','','','','', + 'pai ','','','','','','kuai ','','','','','','qu ','','zhe ','sha ', + '','','','','','','','','','nai ','','','','','','tian ', + '','','','','','','ye ','','','','','','','','','sao ', + '','','Zim ','xu ','','','','','','qu ','','','','','','', + '','','','','','','','','','','','','','','','', + 'duo ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','hua ','','', + '','Nghe ','','','','','','','','','','','','','','', + '','','','','','','','yan ','','','','','','','','', + '','','','','','','','','','','','Tai ','hu ','','','Dap ', + '','tian ','','','','','','','','','','','','ai ','','Lang ', + 'ai ','zhe ','','lu ','','','','zhe ','','','','','','','Ghe ','', + '','','','hu ','','','','','','','','','','','','', + '','','','','','','','','','','','ju ','','','','', + ], + 'x266':[ + '','','','','','','','','','','','','','wai ,wa','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','Paa ','','','','','','', + '','','','','','','','','','','','','','','','', + 'pan ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Moc ','Mao ','Hong ','Tim ','','','','','','','','ju ','dai ', + '','','','','zhu ','Wan ','Gu ','','','ban ','','mai ','Ci ','','','', + '','','','','','','','','','','','','','','','', + '','','','Ping ','','','Zaap ','','','','','','','','','', + '','','','hen ','','','','','','','','xie ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','Ruot ','','','ku ', + 'na ','','','','xuan ','','','','he ','','Nam6','','Ham ','','','', + '','','','','','','','','','','','','','','','', + '','','jue ','','','','','','','','Bet ','Thon ','','','Nuc ','Mang ', + ], + 'x267':[ + '','','','xu ','','','','','','','','','','pang ','','', + '','','','','','','Ngaa6','','Vu ','','','','','','Ron ','', + '','','','','','','','','','','','','','','','', + '','','','','tun ','','','','','','','','','','','', + '','','','','Rang ','','','','Ngac ','','','Mun ','Mep ','','Phop ','', + '','','','','','','','','','','','','','huan ','','', + '','Jim ','','','ban ','','','','','','','','tu ','','','', + '','','','xu ','','','','','','','','','','','','', + '','Tuoi ','','','','','','','','','','','','','Nghen ','', + '','','','Phay ','','','','','','','','','','','','', + '','','Tao ','Sao ','','zhe ','','','','','','sai ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','Bo ','Zin ','Gay ','Suoi ','Khu ', + '','','','tun ','','','','Nem ','','','','','ze ','','','', + 'cu ','','','','Xiu ','','','','','','','','','','','', + '','','hun ','ju ','','','Nem ','','','','','','','','Khu ','', + ], + 'x268':[ + '','cu ','','','','xun ','Sun ','ceng ','','','','','','','','', + '','','jue ','','','','pao ','','Vai ','','','','','','','', + '','','jiu ','zhe ','','','shu ','','','','','','','','','', + '','Phet ','','','','Roi ','Seo ','','','','','','','','','sa ', + '','','','','du ','','Fat ','','','','','Ron ','','','','', + '','','','','','','','','','','','','','','Ngam ','Lung ', + 'Song ','','Rau ','','','','','','san ','','','','','yu ','','', + '','yao ,shao','','','','hun ','Lom ','','','','','','','','','', + '','','','','','','','','','','Pok ','','Duk6','','guang ','', + '','','','Mak6','','','','','','','','','','','','', + 'Rang ','','','','','','','meng ','','','','','','','','', + '','','','Vai ','Lot ','','','','','','','','','','','', + '','','','','lei ','','','Lo ','','','','','','','Nan ','', + '','','qu ','','','','','Nhau ','','Nang ','','','','','','', + '','','','','','','','','','','','','','','','', + '','Zak ','','','','','','','lian ','','','','','','','', + ], + 'x269':[ + '','','','','','','','','','','ru ','yao ','','','Gao ','', + '','','','','','','','','','wa ','','','','','','', + '','','','','','','Hot ','zhai ','','','','','hai ','','Thoi ','Kham ', + '','','','','','','','','','','','','','','','', + '','wu ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','Xue ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','fen ','','','','','','','','Kyo ','','xiao ','','','','', + '','','cheng ','','','','','','','yu ','','yu ','','','','', + '','','','','','','','','','','','','','juan ,fan','','', + '','','','Lau ','','Weng ','','','','','','','','','','', + '','','','','','','tian ','','hu ','','','ta ','','','ta ','ta ', + '','','','','','ta ','','','','','','','huai ','','','', + '','ta ','Loe ','','','hua ','','','zhuan ','','Laai ','','','','','', + ], + 'x26a':[ + '','','Mua ','','','','','','fu ','wu ','','fu ','','','ta ','', + '','Chai ','','','','','chao ','','','','','','Qua ','','','', + '','fu ','','','','','jia ','','','','','','','','','', + '','','','wu ','','','','','','','','Khoang ','','','','', + '','','','','','','','','','','','bai ','','','','', + '','','','','','','','','','','Mui ','Gu ','','','yu ','', + '','fu ','xian ','','','','','','','','','','','','','', + '','sheng ','','','','jian ','','','','','','','','','','sha ', + '','','','','','','','lu ','Ao ','','','','','','','Thong ', + '','','','','dun ','','','','jue ','ta ','zun ','','','teng ','','', + 'hua ','','','','','','','','','','peng ','','','','','', + '','','','','','Ghe ','','','','','','Khoang ','Ghe ','','','', + 'teng ','','','','','','','','','','','','','','','', + '','','','','','','','','','ba ','','','','','','', + '','','','','','','','','','','wa ','','','','','xun ', + 'meng ','','','','','','','','','','','','','','','', + ], + 'x26b':[ + '','','wu ','zhe ','','','','','','','','','','','','', + '','','','','','','qiu ','','','','hu ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','zhu ','','','','','','','', + '','','','','','','','','hu ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','Tup ','','','Hung ','','','','','', + 'ru ','','','','','','','','','','','jiu ','','','','', + '','jiao ','','','','','','','','','','','','','','', + '','pu ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','Nen ','','','','','fu ','','','','','','', + '','','','','','xu ','','','','','','','','','','', + '','zao ','','','','','','','','','','','','','','', + '','','','cu ','','','','','','','xiao ','','Dua ','','','', + '','','','','','','','','','','','','','','','', + ], + 'x26c':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','fen ','','','','Ngon ', + '','','Nua ','','Lau ','','','','','','qiu ','','','dun ','','', + '','','','ye ','','','','','','','fu ','','','','','', + 'yu ','','yu ','yu ','Gu ','','','','','','','meng ','','','','', + '','','mu ','','Bei ','','Fu ','','','','','','xiao ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Nhai ','','','','','','','','','','','','','', + '','','','','','','','','','','','fu ','','','','wan ', + '','','','','','','','Lei6','','','','Rom ','','','Muop ','', + '','hao ,mao','','xie ','','','','','','','','','','','','', + 'nai ,na','','','fu ','du ','','','','','Tre ','','','','','bai ','', + '','','','xun ','','','','','','','','','he ','','','', + '','','','','','','meng ','','','','','','','juan ','ru ','', + ], + 'x26d':[ + '','','','','','','','','','hu ','','Mong ','jun ','she ','','', + '','','','','meng ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','Ke ','','','Nu ','','','','','', + '','','','hun ','','','','','','','','','zu ','','','', + '','','','','jie ','','','','','','','','jun ','','','', + '','','','','','','','','','','','shan ','','','','', + '','ta ','','','','','','','','heng ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Kou ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Chu ','','', + '','','','','','','qiang ','','','Bom ','','','','','','Mai ', + '','','','hu ','','','','hai ','ru ','meng ','','','','wu ','','', + ], + 'x26e':[ + '','','','','','','','','','qia ','','','','','','', + 'lu ','','','','','','','','','','','','','','','', + '','','','','','','','','','','pei ','','','','','', + '','fu ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','zhao ','','','','', + '','','','Thom ','','','Voi ','Bui ','','Nhai ','','Dam ','','','','', + '','','','','','','','du ','','','','','','','','', + '','','','','','','ju ','','','','','chuan ','Lao ','','','hu ', + '','','jie ','xiang ','','','','','xiang ','','','lang ','','','','', + '','','shuan ','','','chu ','','','','','','','','','','', + '','dan ','','','','sa ','','','','','','','','','','', + 'Zaau ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x26f':[ + '','','','Sang ','','','','','ju ','','leng ','lu ','','','','', + '','','','','','','','','','','Lum ','San ','San ','','Dua ','Khay ', + 'Sung ','','she ','','','','','sa ','','','mao ','qu ','','','','Zuk6', + '','juan ','','','','he ','','','','','','mei ','','','','', + '','','lu ','mian ','dian ','','','','','','Waa ','','','','lu ','fu ', + '','','zei ','','Om ','','','','','','','','dan ','','wan ','', + '','','','','','','','','','','','','','','','', + 'Tranh ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','sha ','','','','lu ','', + 'Dua ','','','','','','','','','dan ','','','','','','', + '','','','','','','jian ','lu ','','','','','','ta ','','', + 'chu ','fu ','','','','','dang ','','','','lu ','','','','','', + 'jie ','','','','','','lu ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x270':[ + '','','','','chang ','','meng ','','','','','','su ','','','Sung ', + '','Giong ','Non ','Ru ','','sa ','','','','','','','Sam ','','','', + '','zhan ','','','','','','','Lop ','','','','','','','', + '','chai ','','','','','','','','','xie ','','','','','', + '','','','xu ','','','','','','fan ','meng ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','Ghem ','','','','','','','','','','','', + '','zhan ','jian ','han ','dan ','','jian ','','','','','','','','','', + '','','','','hu ','','','','','','','meng ','ju ','','','', + '','meng ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','Dua ','','','','chu ', + '','','','','','','','','','','','','','','','', + 'yu ','','','','','','','','','','','','','','','', + '','','','','','','Muong ','Khoai ','','','','','','','','', + ], + 'x271':[ + '','','','','','','','','','','Han ','','','','','fu ', + '','','qu ','','','','','','','','','ju ','','','','', + '','','','','','','','','','','','','','','','', + '','','Mo ','','','','','','','','','','','','','', + '','','','','','','','','diao ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','Men ','Muong ','','', + 'hu ','','','','','','','','','','nang ','','','','','', + '','','','','Thuoc ','','','','','','','','','','','', + 'gan ','','','','','','','','','','','','','','','', + '','xu ','','lu ','','','','','','','','','','','','hu ', + '','','','','','','','','','','','','','','','', + '','','','','lu ','','','','zu ','','','','','','he ','', + '','','','','','','','','','','','','','shu ','','', + 'yao ','','','','','','','','','','','','','','he ','', + 'hu ','','','','','','','','','','','','hao ','','','zu ', + ], + 'x272':[ + '','','','','xia ','','','','','','','','ge ','','','', + '','ge ','','','','','ge ','','','','42573.210,zhu ','','teng ','ya ','','', + '','','','','','','','','','','','','','wu ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','tai ','','','','','','','','Trun ','Vat ','','','','','', + '','','xue ','yu ','fan ','','','','','bu ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Gwaai ','','dai ,de','','Buom ','Nhong ','','','','Vat ','', + 'Trut ','','','','','','','','ku ','','','qu ','','','','ru ', + '','','','','','xu ','','','','','','','he ','','','', + '','','','','','Gong ','Doe ','','','','','','','','','', + 'Chau ','','','','','','','','','','Saa ','','du ','Zhe ','','', + '','','','kao ','','','','','','','','','','','','Moi ', + '','na ','','','','','Mei ','','','','','','','','','', + '','','','','','Cuong ','Mot ','','','','Chay ','','Nhong ','Mang ','','', + ], + 'x273':[ + '','','Bo ','','','','','Bang ','fu ','lu ','','','','lu ','','ta ', + '','','','Fu ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','Cua ','','','','','Ngai ','','','','Cua ', + '','','','shuai ','','jue ','','','','fan ','','','','','','', + 'jie ','','','','','','','','','jie ','yu ','','','','','feng ', + '','die ','','','lian ','hu ','','','','','','','','','','dian ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Chau ','','', + '','','','','','shan ','','','','','','','','','','', + '','','zu ','','zhe ','','','','','','','','','','','', + '','','xie ','xie ','','','','','','','','','','','','', + '','','','liu ','','','','','','','','','','','','', + '','','','','','jie ','','','','','','sha ','','','','Nhuc ', + 'Sam ','','','Bo ','Choi ','','','Nhuc ','','ai ','','','','','','zhu ', + ], + 'x274':[ + '','su ','','xie ','yu ,yu','Zeoi ','','','zu ','','','','','','','', + '','','su ','','','','Luon ','','','wu ','','','','','','', + '','','Hou ','','','','','','','','','','','','','', + 'du ','','','lu ','su ','','','','','','','','','','Bo ','Sung ', + '','Sam ','','Ngao ','','Vet ','Chang ','','','','','','','','','', + 'yu ','','Giun ','','dai ','','','','dang ','zu ','','','','chuan ','','', + 'du ','','','','','','xie ','zhe ','','','','sao ','','','','', + '','','','','','','','','','','','','','','','', + '','','fu ','','','Buom ','','Sau ','','Rua ','','Rom ','Rua ','Rua ','e ','', + '','','','','','','','','','fu ','','','lei ','','','', + '','','','','','','','','chai ','','','','','','','', + '','','','','','','','','','','','','','lei ','','zei ', + '','ai ','','','','','','','','','','','','Ban ','','', + '','','','','','','fei ','','','','','','','','','', + '','','','','','','','','','','','','','','','Ngoe ', + 'Sam ','','','','','','','','','','','','','','','', + ], + 'x275':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','ta ','','','','','','','','','du ','qiu ','','', + '','','','','chai ','','','','','','','','e ','','','', + '','','','','','','','','','','','','','','qu ','', + '','','','','','','','','','','Trai ','','','','','', + '','fu ','','','','','','chai ','zang ','','','','','','','', + '','','','','Naan ','','','','','','shuang ','','','','','', + '','','','','','','ta ','','','','','','','','','', + '','','','','','','','','','','fu ','','','','','', + '','','','','','','Moi ','','','','','','','','an ','', + '','','','','','','','','','','','','','','','xiang ', + '','','','','','','','','n ','','','san ','hu ','','zu ','', + '','','','','','','','Jiku ','','','','','','','','', + '','','','','','','','','','la ','yu ,qu','jue ','','','','', + '','shu ,yu','','','Jung ','','','Jutsu ','jian ','','','','','','','shuai ', + ], + 'x276':[ + '','','Chong ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','hu ','','','','','','','','','','','','','', + '','','','','','','','','','Taai ','','','','','','', + 'La ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','pu ','','che ','','', + '','','','','','','','53077.090,jian ','','','','','','zhan ','yuan ','', + '','','','','','','yu ','','','','','Lot ','','','','', + 'mu ','huan ','','','e ','Long6','','','','','','peng ','','','','', + '','','','','Tung ','','','','','','','','','','','', + 'Song ','','Xong ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','Trang ','Lun ','May ','','','','','','', + '','','','','du ','','','tu ','','','','','','','hu ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','Toi ','','','','','','','','', + ], + 'x277':[ + '','Sha ','','','','','','','','','','','','','','', + '','','','','','','Chan ','Mo ','','Xong ','','','','','','', + 'shuai ','','','','','','su ','','','','','','','','','', + '','','','','','','','','','','Bau ','','','','','', + '','','','jue ','','','','','','','','','','','','', + '','zhan ','heng ','','qu ','wei ','','','bao ','','','','','','Gei ','', + '','','','','','','','','Cheo ','Toang ','','','','','','', + '','','ju ','he ','','','','','','','','','','','','', + 'shu ','','','','','','','','','','','','','','','yu ', + '','meng ','hu ','','','','','','','','','','','','','', + '','','','','','','','','','jie ','La ','shu ','jie ','lei ','','', + 'zu ','','','','','','','','','','su ','','','','','', + '','','','xie ','','','','','','','','','','','','', + '','','','','','','','','nang ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x278':[ + '','','','','','','','','cha ','','mao ','','','','','', + '','','xian ','','','','','','','','','chan ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','gao ','','','', + '','','','','','','','','','','Thay ','','','','','', + '','jiu ','','','','','','','','','','','','','','', + '','yun ','','','','','','','','','','','','','','', + '','','','','lian ','','','','','','','','','','','', + '','','','','','','','','','','','lao ','','','','', + '','Don ','','','','','','','','','','','','Lai6','','', + '','','yao ','','','','','wei ','','','','','','','','', + '','','','','','','chu ','','','','','','','e ','','', + '','','','','','','','','Caau ','','','','qiao ','','','', + '','','ju ','','','qiu ','','','','','','','','','','', + '','','hun ','','','','','Dia ','','','','','','','','', + '','','','','','lun ','','','jue ','','','ju ','hu ','','','', + ], + 'x279':[ + '','','','','','','','','','','','','','','','', + '','ju ','','','','qiu ','','','','','','','','','','', + 'zhe ','','','','','','','','','','','','','Ba ','','', + '','','','','','','','','','Thoi ','','','jue ','','','', + '','','','Choi ','','','su ','','','','','','kuang ','','jue ','', + '','','','','Va ','','','','','','','','','','tan ','', + '','','','','','','','','','','','','','','','hu ', + '','fu ','','','yang ','','','ren ','','','Kwan ','','yun ','','','xun ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','pu ','', + 'Ngaak ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','Beng ', + 'Ngoa ','','','','wang ','','','','','','','','','','','', + '','','','xu ','','','','','','','','','','Ngaa6','','', + '','','','','','','','','','','','','','','','Khoang ', + '','','','','','','tu ','','bie ','','','zha ','','','','', + ], + 'x27a':[ + '','','','','','','','','','','Zaa6','','','','','', + '','','','','','','','','','','','','','','','', + '','chen ','','','','','','','','','','','','','','', + '','','','','','','','','','lu ','','','','','Tam ','', + '','','','','','yan ','','','','','','','','','','', + '','','','','','','','','','Daan ','','','','su ','','', + '','','','','','','','','','','','','','','','', + 'bian ','','la ','','','','qia ','','','','','','','','','', + '','','','','','nu ','','','','','','','','','','', + '','','','','','','','','','','','','','','he ,ge','', + '','','','','','','','','ma ','','','','','','','', + '','','','','','','','','','xia ','','','','','','', + '','','','','','','','','','','yu ','','','','','', + '','jie ','xia ','','','','','cha ','','','','yang ','','','','', + '','','wang ','','','','','','','','','','','','','', + '','','','','','','','','','','','','Mo ','','jiu ','', + ], + 'x27b':[ + '','hao ','','','','','','','','','','fa ','','','','', + '','','','','','','','','','','','','','','yun ','', + '','','','','','','','','Wai ','','gun ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','dan ','','','','','','','meng ','','','','','', + '','','','','teng ','','','','','','','','Leoi6','sa ','','', + '','','','','','','','','','','','','','','','', + '','','','he ','','','','','','','','','','shan ','','', + '','','','','','','','','','','','','','','','', + '','ta ','','','','','','liu ','','','','','','','','', + '','','','','','','','','','','','jue ','','','','', + '','fen ','','','','he ','','','','','zhan ','','tai ','qian ','','', + '','','','','Hang ','Hang ','','','','','','','','lao ','','', + '','','','','','','jun ','','','','','','','','','', + '','','','','','zai ','juan ','','','chu ','','','','','','', + 'kan ','','','','','Phong ','','','','','','','','','','', + ], + 'x27c':[ + '','','','','','','','yu ','wu ','','Tian ','','','','','', + '','','','','','','','Nanh ','','','','','','','','', + '','','','','','','','Shuu ','','','han ','chu ','','tun ','','', + '','','','','','','','','','na ','','','','','','ai ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','mai ','','','','lun ','jue ,jun','','', + '','','','','','','','','','','','','','','','', + '','','','huai ','','','','','','','','','','','','', + '','','','','','ceng ','','hu ','','','','ju ','sha ','meng ','','', + '','','','','','','','wei ','','','','','','','','', + '','','zhe ','','','hu ','','','','','','Cop ','','','','', + '','','','','','qu ','','','','','','','Beo ','','','', + '','','fu ','','','','','Cop ','','','','','','','wu ','pei ', + '','','','','','','','','Hum ','','','sha ','','zhao ','wei ','', + '','','','','','','','','','tuan ','','','mei ','','','', + '','','','','','','','','gu ','shao ','','','','','','', + ], + 'x27d':[ + '','','peng ','','','','','','','','huan ','Beo ','fu ','','biao ','', + '','','','','','biao ','','','','','guai ','','','','','', + '','','','','','pei ','','','','','Suo ','','','','','Me ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','Qua ', + 'pai ','','','','','','','','ai ','','','','','','','', + '','','','She ','','','','','','','','','','','','', + '','','','','Zaang ','','','','','','yun ','','','xu ','','', + '','','','','cheng ','','','','','','','','','','','', + 'yu ','','','','','','','','','','','','','','','', + '','','','','','cha ','Faan ','ze ','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'fen ','xie ','','','','','','','','','','','','Xoe ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','shan ','','Mua ','','','','','','ju ','', + ], + 'x27e':[ + '','','','','','','','','','','','','','','','', + '','','','','','','Zhuan ','xue ','','','','','','','','', + '','','','','','','lan ','ju ','','xun ','zhan ','gun ','','','','', + '','','','','','','','','','','','Bui ','','','','chai ', + '','','','','','','','','reng ','','','Vay ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','Son ','','','xu ','','', + '','Tham ','hu ','gan ','','','','','','','','','','','hu ','', + 'Tham ','Tham ','','','','','','','','','','','','','','', + 'jue ','','zu ','','','','','','','','','','jiao ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','chu ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','xian ','','','','','ju ','','Mut6','','','','','','', + '','','','','','','','','','','','','','','','', + 'hu ,zao','qiu ','','fu ','lang ','sha ','','','','','','','','','','', + ], + 'x27f':[ + '','','','','','','','','','','','','','Lanh ','','', + '','xu ','','','leng ','','','fu ','','','','','cu ','','','', + '','','','','dao ','','','','jie ,jue','','','yu ','','','Tang ','shu ,yu', + '','','','','','','','','','','','','','','','', + '','','','','jie ','','','Day ','Day ','','','','','','','', + '','','Cau ','','','','','','','','','','','','','jie ', + '','','','','','lu ','','chu ','','','','lian ','','','','', + '','','','','','','e ','su ','Jue ','','','ju ','','','','', + '','','','','','','xuan ','','','','','','Tron ','','','', + 'jiao ','','','','','','','','','','yu ','','','xun ','','', + 'xun ','','','ju ','','du ','','','','xun ,xuan','','','','','','jie ', + '','qu ','','','','jue ','','','','','','jiu ','','','','Treo ', + '','','','','','','','','','ku ,wu','','ku ','zha ','','','ba ', + 'Chen ','Nhac ','Dam6','hu ','nu ','e ','','','','','','','','','','', + '','','','','','bie ','','','','ge ','','Tau ','','','','', + '','','','','','','','yu ','','Mau ','Xoat ','ju ','','','','', + ], + 'x280':[ + '','','','','','','','','Buoc ','','','','','Dung ','Lop ','', + 'Rong ','','','','','','hai ','','','','','cun ','','','','', + '','','','Kei ','Leoi ','','','','','','','','zai ','','','', + 'Bang ','','','','xun ','','','','','','','','','','','', + '','xuan ','xie ','','han ','','','tun ','Gaang ','','cen ','','','Ren ','Choanh ','', + '','','','','','','','','','','','','','Buot ','','', + '','Noi ','','','','','','Noi ','Cuong ','','Dau ','','','','','', + 'Xui ','','','','','','','','','','','','Bon ','de ','','', + '','','','peng ','','','','','','','','','','','','', + 'Leoi ','','','','Doc ','','','Co ','','','','','','','tan ','', + '','','','wu ','','','chuan ','','','','','','','du ','','', + '','hun ','','','','','','','','','','','','Dam6','Naam ','', + '','','','','','','','','','','','','Giay ','Tot ','','Xam ', + 'Giay ','','','','','Soc ','kua ','teng ','','','ta ','sa ','','','Pun ','Pun ', + '','','','sao ','','','','','','Sin ','','','','zu ','','', + '','','jie ','neng ','','','','Chuc ','','','','','To ','Nhuc ','Xung ','', + ], + 'x281':[ + '','','','','','','','','','','Te ','','','','','', + '','','','','shuan ','zu ','','','','','','','','','','', + 'Tat ','','','','','','','','','','','','','','','yu ', + '','','','','Sup ','','','','','','Chui ','','','','Ghe ','Giong ', + '','Sup ','Mop ','','','','','','','Lung ','','xiao ','','Ren ','','Laam ', + '','','shu ,chu','','','','','','','','','','','Jaang ','Nhap ','', + '','','','','','Bay ','','','','','','','','','','', + '','','','','','','','Doi ','','','','','','','Sum ','', + '','','Khum ','','zhu ','','','cha ','juan ','','','','','','zei ','', + '','','','','','','','','','','','','','Cui ','','', + 'Quay ','Dep ','','','','Tuon ','','','','','Jaang ','','','','','Buk6', + 'ta ,da','','','','','','','','','','','','','','','', + '','kuang ','','','','bao ','lai ','','','Leo ','','','','','','', + '','','','','','','lu ','','','','','','','','','', + '','','','','','','chan ','','','zhan ','','','','','','', + '','','','','','Nhao ','Khuy ','','','','','','','','','', + ], + 'x282':[ + '','','','','','','','Laam ','die ','','','','','','','', + '','','','leng ','','','','','','','Pei ','','','','','', + '','','','','','','','','','','','zhu ','','','','', + '','','','','','','','','','','ye ','','','','','', + '','huang ','','','','','','','','Pei ','','','','','','', + '','','','','','','Nei ','','','','','','','','Lung ','', + 'Ban ','','','','','','','','','','','','','mei ','','', + '','tang ','','','','','','','','','','','Wu ','xiang ','','', + '','','','','','','','','','','','','Lan ','','','', + '','','','','','','','','','','','Laak ','','','','', + '','','','','','','','','','','','','','','','', + '','yu ','','','','','','','','','dai ','','xuan ','','','jue ', + '','','','','','','','','du ','','','','','Wan ','','', + '','','','','','','','','zha ','','','pao ','','','bu ','he ', + '','','Lip ','','So ','','','ju ','hun ','','','','','','','Zhuai ', + '','','','','','','','','','','','','','','','', + ], + 'x283':[ + '','','','','zang ','','','','','','','','','','xu ','', + '','','','','','','','','jun ','','','','','','','', + 'lu ','','','','','fu ','','','','Tang ','','','chao ','ta ','','', + '','','','','','','','','','','','','','','','', + '','','','','Co ','','','he ','','','','','','','mu ','', + '','','xian ,jian','','','','','','','','','du ','','','','', + '','','','','','','Sau ','','','peng ','','','','','','ju ', + '','','','Yao ','','','','','','','','','','','','', + '','','','','','','So ','','','','','','','','','', + '','','','','yang ','','','','','','','','','','','Truoc ', + 'Truoc ','','','','','','','peng ','','','','jian ','jiao ','','','', + '','','','peng ','Dang ','','qu ','','mu ','','','','','','fen ','', + '','','','','','','','','','shuan ','jian ','','','','','', + '','','','','lu ,du','','','','','','ge ','','','','','', + '','','','','','xian ','','So ','','','','','','','','', + '','','','xie ','ge ','','','','','jue ','','','','','','', + ], + 'x284':[ + '','die ','','zhe ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','ku ','','qu ','','ge ','ban ','','','','','','','','Cay ','', + '','ban ','','','','','','','','','','','','','ban ,bian','', + '','','','','','','','','','','','','chen ','','','', + '','','Tu ','','','','','','','','','','Xuong ','','','', + '','','','','','wu ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','pan ','','','','','','','qiu ','','','','','', + '','','','','','','','','','','','','bie ','','kan ','', + '','','','','','','','','nai ','','','','','','','', + '','','','','','','','','','','Quanh ','','','','','', + '','','','','','','','','','','die ','','','','','', + '','','','','','','','','','','','','','','dai ','', + '','Lung ','','','','','','','','','','','','','','', + 'jie ','','','','ya ','','','','','','','','','','','pei ', + ], + 'x285':[ + '','','','','','','','','Choi ','','Suot ','','Co ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','shu ','','','','','','','','','ta ', + '','','','','','','','','','','','','','','','Chuc ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'ze ','','chu ','','','','qiu ','','','','','','','','','', + '','','','','','','','','','','','','','jie ','','', + '','','','','','Sang ','','','','','','','yang ','','','jiu ', + '','','','','','','','','','','','','','','','', + '','','','','','','','Mau ','','','','','','','','', + '','xian ','','','','','xiang ','sha ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','dao ','','','','','','','','','Nhanh ','yu ,ju','','', + '','chao ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','da ','', + ], + 'x286':[ + '','','jiu ','','','','','','','sha ','','','','','','', + '','','','','','','','','','xian ','','','','','xian ','', + '','','','','','','','','','','','','','','jiu ','', + '','Nhanh ','','','kao ','','','','','','','','','','','', + '','','','','','','','','','','','','','Keo ','ta ','zan ', + '','','','','zhu ','','Suot ','','','','','','','Lui ','','', + '','','','','','','','','','','','','','','','', + '','','','','','xiang ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','bian ','','','','','','','','','','', + '','','','','','','','qie ','','','','','','','hao ','', + '','','cun ','','ru ','zai ','','','','','','','','','','', + '','','','','','','','','','','','','','shao ','han ','', + 'jun ','','bu ','','','','kuai ','','','','','','xiang ','','','', + '','yun ','','','','pu ','','','','','','','pei ','','','', + '','','','','','','','','','','','','','','','', + ], + 'x287':[ + '','','','','','','','','','','','','huan ','qiao ','','', + '','','','','','','yu ','','mei ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','he ','','','he ','','','','','','','','','','chuang ','xu ', + '','','','','','','','','','','','zhai ','','','','', + '','guan ','','','','','','','','','','tu ','shun ','','hu ','', + '','','','','','','dang ','','','','','','','feng ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'cheng ','','','yu ','','zhu ,chu','','qun ','','qu ','','ge ','','','','', + '','','','','','','','','gai ','','','meng ','','','','', + '','','','qu ','','','','','','','','','wan ','lei ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','dai ','','','','','','','','','','','qiu ','','', + ], + 'x288':[ + '','','','','','','','','','Tam ','','','','','','', + '','','Faan ','','','','bao ','','','','','','','','','', + '','','','','','wei ','','','','','','','hao ','','','', + '','','Giam ','Gay ','Sua ','Xoang ','','','','','','','','','','', + '','','','jiao ','','','','','','Dam ','','','nei ','','yan ','', + '','','','','','','','zha ','','','','','','','','', + '','','','yan ','','','','','Gay ','','','hun ','','mu ','','', + '','','','','','','','','','','','','Giam ','','','', + '','','','','','','','liu ','han ','','meng ','hu ','','','','', + '','','','','','','','','','','','','','','','Cay ', + 'meng ','','mu ','','hu ','Mi ','shai ,zha','','','','chao ','','','','','nian ', + '','','','','','','','','','','','','','','','', + '','','','','','chuai ','','','','','','','','','','', + '','','','','','','','hu ','meng ','pao ','','','','','','', + '','','','','Giam ','Dau ','Zeoi6','','lan ','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x289':[ + '','','','','','','','','','','','','','','','', + '','juan ','','','','','','','','','','','','','','', + '','guang ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','jie ','','','','','','','','','','','','','', + '','','','','','','','','','','','hu ','','','','', + '','','','cen ','','','','','','','','','','','','', + '','','','','','','dai ','','','','','','','','','', + 'Keo ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','fu ','','','','', + '','','','','','','','Nen ','','','','','','Lao ','','', + 'liu ','','','','','','','','','','','','','','','', + '','','','','','','Bua ','','','','','','','','','', + '','xiang ','','','','bian ','','wu ','','','','','Bong ','','','', + 'Gang ','','','Xot ','','','','','','','sao ','','','','','', + 'zu ','','','','','','','','','','','','','','','', + ], + 'x28a':[ + '','','','','','Hoat ','','','','','','','','','','', + '','','','','','','','quan ','','','chao ','he ','','','','', + 'Cuoc ','wu ','','','Khep ','','Mai ','Thep ','','','','','','','','', + 'ruan ','','','zu ','','','yu ','tu ','meng ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','mao ','','','yu ','','','', + 'zu ','','','','','','','','','','','','','xia ','','', + '','','','','','jian ','','','','','','','','','yu ','', + '','','','','','liu ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','ruan ','','','yan ','','','','','','','','','', + '','','','','Bam ','Lon ','','','Choc ','','Sat ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','Han ','','','','','', + '','','','','','Cuoc ','','','','','','','','','','', + ], + 'x28b':[ + '','','','','','','','','','Dui ','','','','','','', + 'jue ','','','','ruan ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','zhu ','','','','','','','Baang ','Bay ','','Choang ', + '','','Choang ','die ','','','','','','','','','','','','', + '','Thau ','','','','','','','','','','','','','','', + '','','','','','','','','','','Com ','','','','','', + '','','','','','','','Bung ','Hom ','Cun ','','','','','','', + 'Nhon ','Thoi ','','','yu ','','','','Ban ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','cai ','','','','','','','','','','','jiang ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Dui ','','','','','','','', + ], + 'x28c':[ + '','','qian ','','','','','','','','','','','','','ta ', + '','diao ','','','','','','','','','','','jue ','','','', + '','','','','','','','','','','','','','','','', + '','','','','Nen ','','','','yu ','','Ben ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','duan ','','','','','', + '','','','','','','dao ','','','','','','','','','', + '','','','','','','','','','','','','cen ','Dai ','Dai ','', + '','','','','jun ','','','','zhu ','','an ','','','','','', + '','','qiu ','','','','','','','','','','','','','', + '','','','','','','','','','','','feng ','wu ','jiao ','','', + 'peng ','','','','','','','','','','','','','','','', + 'niao ','','chan ','','','','nang ','','','','Gau ','','','Cat6','','', + '','','Diu ','','men ','','','','tun ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','die ','','','','','', + ], + 'x28d':[ + '','','','','','','','','','','','','','','xu ','', + '','Kuang ','','wei ','','','','die ','','','','','','','','', + '','','he ','yan ','','','Cua ','','','tu ','','','hu ','','','', + 'chu ','','','','','','','','','','men ','','','','','', + '','','','','','','','','','','zhe ','','','','','', + '','','','','','','','','','','xie ','','','ta ','','fu ', + '','','','Cua ','','','yu ','','','','xie ','','xian ','jian ','xu ','', + '','','','','','','','','','','','','','','','', + '','yan ','ai ','','','','','','','','jun ','','','','','', + '','','','','','','','lang ','','Lan ','','','','shu ','','', + '','','yu ','','','','','','','','','','hua ','wen ','','e ', + '','','','','','','','','','Gwaan ','','','','','','', + '','niu ','','','xiang ','','sa ','','','','','','','','run ','', + '','','','jian ','xu ','','','','','shu ','','','','','','', + '','','','','','xie ','','','','','','','','','','Cua ', + '','','','','','','Cua ','','','','','','','','dang ','', + ], + 'x28e':[ + '','','','','','','','','','','','','','Cup ','','', + 'reng ','','','','','','','han ','','','Ji ','gai ','','','','', + '','','','','','','','','','','','','Zhen ','','','', + 'ju ','','','','','','','','','','','','','','','', + '','','','','','','xuan ','','','','','','','','','', + '','','','','','','','','xu ','','cheng ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','zhao ','','','','','','','', + '','','','','','fu ','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','duan ','','','','qiu ','','','','','','','xun ','', + '','','','','','','','','','Jiao ','','','','','','', + '','','yan ','','','','','','','','','','','xu ','','', + '','','','','','','','die ','','','','','','','','', + '','','','','','','','liu ','','','','Luong ','','','','', + '','','Xia ','','','','Geki ','','','','','','','','','', + ], + 'x28f':[ + '','','','','','','','','zhan ','cuan ','wu ','','','','jue ','', + '','','','','xun ','','','','','','Be ','','','','','', + '','','','','chen ','','','','','','','qu ','','','zhan ','', + '','jue ','','','','','','','','','','','','qu ','','meng ', + '','','pu ','','','','','','','','','','','du ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','xia ', + '','','','','','','','','','','','','','','','dai ', + '','','','','','','','','','','','','yu ','','','', + '','','','','fang ','','','','','','','','','','','', + '','','','','die ','','','','','','','','','','','', + '','','','','','','','','','','','','','','tiao ','', + '','','','','','','','','','','','','','','','wu ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','wei ','','', + '','','','','','','','','','','','','','','','', + ], + 'x290':[ + '','','','','','','','','','','','run ','','','','', + '','','','','','','','','','','','','','','','', + '','','','wei ','','','','','','','','','','','','', + '','','','Song ','','','','','','','','','','','','', + '','','','','','','','','','','','','wei ','','','', + '','','','','','','','','','','','','','','cai ','', + '','','','','','','Loi ','','','','','','','','','', + '','','','','','','Ngat ','','','','','','','','','', + 'Con ','Ngut ','','shai ','tun ','','','','','','','','','','fu ','Che ', + 'Ram ','Bung ','','','fu ','Phat ','ze ','pu ','','','','','','','pao ','Mu ', + '','','','','hua ','','','','','','','','','','','', + '','','','Rei ','','dian ','Set ','','','','','','','','','', + 'yan ','','','','','','','','','','','','','','','', + '','','','','','','','','','','xuan ','','','','','', + 'dai ','','','','','','','','','','','','','','','', + '','','','','ba ','','','dai ','','','','','','','','', + ], + 'x291':[ + '','','','','','lu ','','','','','','ru ','','','Mua ','Bung ', + '','','','','','dan ','meng ','xia ','','','','','','','','', + '','','','','','','peng ','','Guot ','','','','','','','wu ', + 'Set ','','May ','','','Nap ','Xoi ','piao ','','','','','','','ze ','', + '','','','','lu ','','','bu ','','','','','','man ','','', + '','','','','','','','','','','','Bung ','','','','', + 'nan ','','he ','','','','','','','','','','','','cen ','', + '','','','','','','','','','May ','Rau ','Zyu ','','','dan ','fu ', + '','','','','','sa ','','','','','','Rao ','','Rao ','liu ','', + 'Sam ','','','','dian ','','','','','','','','','','','', + 'Mong ','Rao ','','','','','','','','','','','Mong ','','','', + '','','','','','','','Sam ','','','','','','','Khuya ','', + '','','','','','Mu ','Sam ','hun ','','','','','','Loa ','','', + 'qu ','','','','','','','','','','','','','','','', + '','','Xanh ','','','','','','','','','','','','','fei ', + '','','','','','','','','','','','','','fei ','','', + ], + 'x292':[ + '','','Bay ','','','','','','pang ','dan ','','ai ','','','','', + '','','','','','','','mai ','','','','','','','dao ','', + '','','','','chu ','','','','','','','','wan ','','diao ','', + '','','suan ','','','','','','','mian ','','','','','','', + 'lan ','','','','','','','','','','','','','','','', + 'gan ','','','','jian ','','','','','','','','hang ','','','', + '','','','','','xuan ','','','','','','','','','','', + 'ang ','','','','','fen ','','','ju ','','','','','fu ','','qu ', + '','','','ma ','','bao ','','yu ','','','','','','mai ','','', + '','','','','jiao ','','','','','','','','','','','', + '','','','','','','','','','','','','bu ','','','', + '','','','','','zhe ','bu ','','','','jue ','xun ','','Hia ','','', + '','','bai ','','','ta ','','','nao ','yu ','','','','','','', + '','','','','','','','','Xie ','diao ','','','','','die ','fu ,fu', + '','','xuan ,yun','','yu ','','','Xie ','fu ','','','xuan ','','','','', + '','','','','','','','la ','','','gao ','','','e ','','mei ', + ], + 'x293':[ + '','','','','','','','ta ','','ta ','','','','','','', + 'ta ','','','','','','','','ta ','','','','','','','', + '','','','','','','','','','','ze ','lu ','','','xu ','', + '','','xu ','','','','','','','','','','','','','', + '','','bao ','','','','','','','','','sheng ','','','','fu ', + '','','','','','','','Bang ','','','','','','','','', + '','','Roi ','Dep ','','','','','','','','','','','','', + '','','','xu ','','','','jue ','','','','','lu ','','','', + '','','','','','','','','','','','','','','ge ','', + '','','','','','','','','','','','fu ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','wei ','','','','yu ','','bai ','','ta ','','', + '','','','','','yun ','yun ','duan ','','wei ','','','','','','', + '','','','','','','hun ','','','','','','','','bai ','yu ', + '','','','','','','','','','','','','','','','', + '','','','','yu ','','','','','juan ','jue ','','','','','', + ], + 'x294':[ + '','','','','','sa ','','','','','','','','','','', + '','','','','','','','','','','fu ','peng ','','','','', + '','zu ','','','','','','','','','','su ','','','','', + '','','','','','','zhe ','','','','','','su ','','','', + '','e ','','','','','','','guang ','','','','','ao ','','', + '','','','','','','','','','','','','','','','', + '','','','','','men ','','','','','','','','','la ','', + '','','','','yao ','','','','','xuan ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','yan ','','','','','','','','','', + '','','','','','','','','','','','','','','qiu ','', + '','','','','','','','','','','fu ','','','','wu ','', + '','','','','','','','','','','','','','','','', + '','','','','','','fu ','','','','','Ngup ','Mang ','bie ','','', + '','','','','an ','Ngok6','wu ','','','','lu ','','','','','', + '','','','','','','','','','','','jue ','','','','', + ], + 'x295':[ + 'wai ','','dun ','','jie ','','','','','','zhuan ','hang ','','','','', + '','','','','','qiu ','','Lei ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','ze ','xu ','','','','','','','','xu ','','','', + 'ao ','','','','','','','','','','','','','','','', + 'liao ','','','','','wai ','','','','','','','','','','', + 'han ','','','','dan ','','','','','','','','','Gai ','','', + '','','','','','','','','','','','','','','yuan ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','peng ','','','','', + '','','','','tun ','','','','','','','','fu ','','','', + '','','','','','','','','','','han ','','fu ','','','', + '','','','To ','','','','','','sa ','','','','','','', + 'hua ','','','','','qiu ','','','','','','','','','sa ','', + '','','','','han ','','','','','liu ','','','','','','', + '','','','','Bung6','','','','','','','','','wu ','','', + ], + 'x296':[ + 'zhao ','','','','May ','','','','','','la ','','','yuan ','','', + '','','','','','','','','','','','','','','','', + '','','','To ','yu ','','','','','','','','','','','', + 'su ','shuai ','','yu ','','','','','','su ','','yu ','','','','', + '','','','','liu ','','cheng ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','niu ','','','','Bay ','','','','', + '','','','','yu ','','','','','','','','','','','', + '','','','','Nhu ','','niu ','','','','','na ','','','','', + '','','','','','','','Qua ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','No ','Qua ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','zai ','','','mao ','','yu ','','','yu ','','', + '','','','','','','','','','','ju ','','lu ','','','', + ], + 'x297':[ + '','','','ju ','','','','Juan ','','','','','','','','', + '','','','','','','','','','','','','','','','ang ', + 'Mam ','','','','','','','','','','','','','','','', + '','','fu ','','','','','','','','','','','yan ','','', + '','','','','','','','','','','','','','','','', + '','','','','','wu ','','yu ','','','','','','','','', + 'Qiu ','','','','','su ','','','','','','','','','','', + '','','','','','','','','','','','Chan ','','jiang ','','', + '','','','','','','','','zhu ','','','','','','','', + '','','','','','','','','','','','','','','hai ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','han ', + '','yuan ,xuan','Qua ','','','','','ao ','','','','shan ','','','','', + '','yu ','','','Caat ','','','','','','','','','','meng ','', + '','','','','','','jie ','','','','','','','','huai ','', + '','','','yu ','','','chan ,jie','','','','','Nang ','','','','', + ], + 'x298':[ + '','','','','','','','','','','','','','','','', + '','Ding ','','','Mao ','','','','','','','','','','','', + 'Cui ','','','','','','','Guc ','','','','','','','','wei ', + '','Chui ','','Chui ','Cui ','Choi ','','fu ','','','','','','','','', + '','','','yu ','','','','','','','','Thom ','','','','', + '','','','','hai ','peng ','','','','','','','','','','bie ', + '','','','','','','','','','','','fan ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','wan ','','','','','','','','wen ','','','', + 'zhe ','','','','ban ','bu ','','','','','','ge ','','','liu ','', + '','','','','','','Giong ','','','','hu ','','','','','', + 'fu ','','Sai ','qu ','','','yu ','','','jiu ','','shu ','','','','fu ', + '','','','','','','','','','','xu ','','','','','', + '','Ngon ','','','','','','','','','','','fu ','bu ','','', + '','','','','','','','','','zhe ','','','','','tu ','', + '','lu ','','','','','','','fu ','','','','','','','', + ], + 'x299':[ + '','','','','','','','','','','xian ,jian','kun ','','','','', + '','','','','','','','','','cheng ','','','','','tan ','', + 'xie ','','','duan ','','','','','','e ','','','','','','', + '','','','','','','','','','','yu ','','','','','', + '','','','','','','','zhan ','','','','Au6','qia ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','yu ','','', + '','','','','','','','','','','','','','tu ','','zu ', + '','','','','','','','','','bie ','','','','','','', + '','','','','','','','','','','','','','','','', + 'bang ','yu ','Jyu ','','','','','','','','','','','','','', + '','','','','','','','','','xian ','meng ','','','','','', + '','','','','','','','cai ','du ','','','','','','','jue ', + '','','ju ','','','','','','qu ','','','','','','','', + '','jue ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x29a':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','yu ','','yu ','','','ba ','','','', + 'ya ','','','','','','','','','fan ','','','','Que ','','', + '','','ma ','','','','','','','','','','Kheo ','','','', + '','','','','','','','Song ','','','','','','Peng ','','', + '','','','','','','Song ','','','','','','','','','', + 'zu ','leng ','','','','','','dan ','','','Xuong ','Xuong ','','','du ','bian ', + '','qia ','he ','','','','yan ','','','','','teng ','','','','Hom ', + '','','','hai ','','','','','','xu ','','','','','','', + '','','','','','','','Jue ','','','','pu ','','','Sun ','', + '','','','','','','','','','','','','','','','', + '','','','','yan ','So ','','','','','','','','Cut ','','', + 'kai ','mao ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','sao ','','','','','','','','','', + '','','','','ju ','','','','','cheng ','','','','','','', + ], + 'x29b':[ + '','','','','','','','','','','','','','','Zam ','', + '','Chom ','','','','','','','','','','','ju ','','','zha ', + '','','','','','','','','','','','','','','','', + '','dao ','','','','','','','','','','','','','','', + '','','','','','','','','','','ju ','','','','','', + '','','','','','','','','','','','','Xui ','','','dao ', + '','','an ','','','han ','','','','','','','','','','', + '','','','','','Quan ','Rau ','','','','fu ','','','','','', + '','qia ','','','','na ','','','','','','','','','','', + '','','','','Quan ','','','','','','','','','ya ','','', + '','','','','','','','','','','','','','Ria ','','', + '','','','','','','','','','','','','','','','', + '','Rau ','','','zun ','','nao ','','','','','','','','cheng ','', + '','','','','','','','','jiao ','','','yao ','','','can ','', + '','','','','','','','','','','','','','Ban ','','Xoam ', + '','pu ','zhuang ','','','','','','','','','','','la ','','', + ], + 'x29c':[ + '','','','zhan ','','','','','Nheo ','','','','','bian ','','', + '','','','','','','','','','','','','','','','', + '','','','','ju ','','','','jue ','','yu ','','','','','hu ', + '','','','xie ','er ','','','','','','','','','','','', + '','','','','','','','','','','er ,xian','','yu ','hu ','','', + '','','','','','','','','','ku ','','','','','jiao ','', + '','','','','','','','','ru ','','','','','','','', + '','yu ','','','','','','','','','','','','','','', + '','','','','','','','','','','hao ','','','niu ','','hua ', + '','','','','','','','','','','','','','','','', + 'zhu ','Coi ','','','','Troi ','','','','','','','zhu ','','','', + '','','zu ','','','','','','','','','','','','yu ','', + '','','','','','','lai ','','','','Ranh ','','wu ','','fu ','zhuan ', + '','','su ','','yao ','','','','','','','','','','','', + '','','yan ','','','zhu ','','','','','','','','','','', + '','','','Troi ','','ju ','','','','','','','','','','', + ], + 'x29d':[ + '','','','','','','','shai ','','yun ','','','','','','', + '','','jiang ','','','','','','ju ','','Troi ','','','teng ','wei ','', + '','gu ','','','liao ','','','','','','','','','','','', + '','','meng ','cha ','','','','','','qu ','','lei ','','','','', + '','','','Troi ','','qu ','','','','','','Gyo ','','qiu ','','hua ', + '','','','','','','','','','','du ','','','Chai ','','', + '','','','','','','mu ','','','','','','hu ','','','', + '','','','','','','','','','fu ','','','','Tom ','','', + '','','zhu ','','zhu ','Ci ','','','','Pou ','','','','','','', + '','','','','','','mu ','','','','','','','','','Buop ', + '','meng ','','','','','guai ','jiu ','','mu ','','','Si ','wu ','','ru ', + '','zha ','','','','','','','','','','','','','','', + '','','xie ','','jiang ','','','Hung ','','','Thu ','','','','','', + 'ju ','','','','','Luon ','bu ','','','','','','','','','', + '','','','','','','','','','','','','','jiang ','','', + 'xun ','','','','','','Mang ','','','','','qia ','','','','', + ], + 'x29e':[ + '','','','tu ','hua ','','','','','','','','','','','', + 'ru ','','','','','','','','','','','','','','','', + '','','','','','','','','Yi ','','','','','','Bong ','Chuoi ', + 'Go ','','','','','','','','Thia ','','','','','','ye ','', + '','','','','hai ','','','','','','','','','','an ','ba ', + '','han ','','','','','','','','','','','','','','nai ', + '','','','','Thu ','','','','','Nau ','','Tep ','','Chay ','Mu ','Tuoi ', + '','chu ','','','','','','','','','ge ','','han ','','na ','ge ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','Bon ','','Trau ','','','','','Bong ','','Bon ','xie ','','','','Soc ', + 'yu ,wu','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Mam ','','Sop ','Dua ','','Tram ','','bu ','jian ','','wu ','Tram ','','zhuan ','','Vay ', + '','','','','','','','','','','','','','','','', + '','','','','','die ','','','','','Vay ','Leo ','','','','', + ], + 'x29f':[ + 'Vay ','','','','','','','','Ao ','','','','','','','', + '','','','','','','','','','ge ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','xu ','','','Sau ','Lui ','','','','wei ','', + '','','','','','','Ruoc ','','','','','','','','','', + '','','','','Sau ','Luon ','','','','qu ','','','','','','', + '','','','','','','','ba ','Nheo ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','han ,yan','','', + '','bao ','','','','','','xun ','','','','','','','','', + '','','','','','','jie ','','','','','hu ','','','','fu ', + '','','mao ','','','','','','','','','','','','','', + '','','','bao ','','','','','Mao ','','Khuou ','','','ju ','Caa ','qu ', + '','','','','','qu ','','','Khuou ','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2a0':[ + '','','','','Chim ','','','','','','','','','','','', + '','','Shi ','','','','','','jiang ','','','','','','','', + 'xun ','','','ju ','','','','','','','','','','','','', + '','','','','','','','','','','fu ','','','','jie ','', + 'yu ','','','','Ket ','Sac ','Hau ','Song ','zhuang ','','','cheng ','','jie ','','chen ', + '','','','','','','qu ','','','','','','','','','', + 'jue ','yan ','','','','ju ','','','','','','','','','xiu ','', + '','','','','Coc ','Coc ','','','','','','','','su ','','', + '','','','','','','','','','yu ','','fu ','ta ','','','', + '','','hu ','','','','','','','','','','mei ','','','', + '','','','','','','','','','','','','','','','', + '','','','Cun ','','yu ','','','','','','','','pen ','fu ','', + '','','liu ','','','','','','jie ','','','','','yu ','yu ','Mei ', + '','mao ','','fu ','','','','','','','','jian ','','','','', + '','','','','','','','','','','','','','','','', + '','Hau ','','','Ga ','','','','','','','','','','','Ge ', + ], + 'x2a1':[ + '','','xia ','','','Set ','','','','','qu ','','','','ge ','', + '','su ','','','','','','','','','','','','','','', + '','','','','','Cut ','','','','','','','','','hu ,gu','', + '','','','mai ','','','','','','','','','','','','', + '','','','','su ','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','Cuoc ','Choi ','Ri ','Sam ','','','','Tu ','','', + '','','','','','','','','jie ','','','','','','','', + '','','qu ','','','','','','','','','xie ','','','','', + '','','','','','','','','','','','','','','','', + 'fu ','','','','','Khuou ','Tu ','','','','','','','','','', + 'ya ','liu ','','','','','can ','64272.110,chu ','','','','','','','','jian ', + '','','','','','','chu ,du','','ai ','','','Cui ','','','Quam ','', + '','xun ','','','','','','','','','','','','yu ','','', + '','','','','','','','','','Ngan ','','Cui ','','cai ','','liu ', + '','','jie ','','','','','','','la ','','','','','','', + ], + 'x2a2':[ + '','','','','','','','','lai ','','he ','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','jue ','','','','guan ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','Muoi ','','tan ','','En ','','','','','','kan ', + '','bian ','','','Muoi ','','','','','','','','','','','gan ', + '','','','','','Mam ','','gan ,tan','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','xiao ','','zhu ','','yu ','','','','', + '','jian ','','','','','','','','yu ','','','','zu ','','', + 'nuan ','','','','','','','','','','','','','su ','','', + '','pu ','','','','','','','','','','','','','yu ','', + '','','','','','','','','','','','','','','','', + ], + 'x2a3':[ + '','','','','','na ','qu ','','','','','tun ','','','','', + '','','','ku ','su ','','','','','','','','','','','ze ', + '','','','ge ','','','','jie ','','','tiao ','','','','','', + '','','','','','','shu ','','','','','','','hun ','','nie ', + '','jun ','hu ','','lu ','','','','chao ','','','','','','','fu ', + '','','','','','','','','','','','','','yun ','','', + '','','','','','','','xuan ','','','','','','','','', + '','','','','','','shan ','','Qu ','du ','','sao ','','','','kuang ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','liu ','','','','','','','','','','mei ','','', + '','','','','tun ','kang ','tun ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','heng ','','','','','','Huang ','','','','','','', + '','','','','','','','','','','kuang ','piao ','','','','', + '','','','hu ','','','bao ','','','','','hu ','','','','', + ], + 'x2a4':[ + 'Naa ','','','','','','bie ','','','','','','','','','', + '','','','','','','','','','','','','','dai ,tai','du ','', + '','','','','','tai ','','shu ','','','','','','','su ','', + '','','','','','','','','','','','','','','','', + '','','cha ','','lu ','','yu ','','yan ','','qiao ','','yu ','','','tu ', + '','Ngam ','tun ','','','','','','','','','','','yu ','','', + '','','','','','','','die ','cha ','dian ','','','','','','', + '','','','','','','','wai ','','','','','','zhai ','','', + '','','','','','','','','','','','','','','','lu ', + '','','','','','','','Tham ','','','','','ma ','','','', + '','','','','','','','','','','mai ','','Nung ','','','', + '','','','','','','','','','','','','','','dan ','teng ', + '','','','','','','','','','','yu ','','','','','', + '','','','','','','','','','','','','','','','', + '','cu ','','','','','','','','','','Sam ','','','','', + 'cu ','','','','','','','','','','','','','','','', + ], + 'x2a5':[ + '','','Ding ','','','','','','','','','','','peng ','','', + '','','','','','','','','','','','','','','','', + 'Trong ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','hu ','','','','','','', + '','','','','','','','','','','','','','cu ','jun ','', + '','','','','','','','','er ','','','','','ai ','hu ','', + '','hu ','','','','','','','','','','','','','','', + '','','','','jiao ','','','','pu ','','','jie ','lu ','','','', + 'yao ,ya','','','','','','','','','Hou ','','qiu ','jue ','','','', + '','','','','','','','','','xu ','','','','Ngui ','','', + '','','','','','','su ','liao ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','pa ','','','','','','','','','na ','','', + '','','','','','','zhan ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2a6':[ + '','Kap6','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','zu ','','','zhan ','','','','','', + '','','Ji ','','','Rang ','','','','he ','qia ','','','','','', + '','','','','','','','','hu ','','yan ','','','','','', + '','','','','','','','','','','','Nak ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','jue ','','','','','','','','','','', + '','','','','','','','','','','Trong ','','','','','', + '','','','','','zhe ','','','','Gwi ','','','gan ','','','cu ', + '','','','','','','','','','zhu ','','','','','','', + 'xiao ','','','','','Rua ','','Rua ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2a7':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2a8':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Bai ','','','','','','','Zhan ', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','Luan ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2aa':[ + '','','','','','','','','','','Song ','','','','','', + '','','','','','','','Jue ','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','Yong ','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2ae':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','Nu ','','','','','','', + '','','','','','','','','','','','','','','','', + 'Cong ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2af':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','Xian ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2b0':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','Li ','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Fei ','','','','','','','', + '','','','','','','','','','Su ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','Kou ','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2b1':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Chi ','','','','','','','', + '','','','','','','','','Xun ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2b2':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Qia ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Gong ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2b3':[ + 'Ji ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Luo ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','Yi ','','','','','','', + '','','Nao ','','','','','','','','','','','','','', + 'Xi ','','Xiao ','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','Jiao ','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2b4':[ + '','','','','Yue ','','Kuai ','','','Ling ','','','','','','', + 'Ni ','','','Bu ','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','Han ','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','Fu ','','Cong ','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2b5':[ + '','','','','','','','','','','','','','','Jue ','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Duo ','','','','','','','Su ','','','','','','','Huang ','', + '','','','','','','','','','','','','','','','', + ], + 'x2b6':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','Han ','Ai ','','','','Ti ','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','Xu ','Gong ','','','','','','', + '','','Ping ','','Hui ','Shi ','','','','Pu ','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','Zhi ','','','Jue ','', + '','','Ning ','','','','','','','','','','','','','', + '','','','','','','Chi ','','Ti ','','','','','','','', + ], + 'x2f8':[ + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + 'Gai ','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ], + 'x2f9':[ + '','','','','','','','Baan6','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + ] +} diff --git a/ebook_converter/library/__init__.py b/ebook_converter/library/__init__.py new file mode 100644 index 0000000..655ca84 --- /dev/null +++ b/ebook_converter/library/__init__.py @@ -0,0 +1,87 @@ +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2008, Kovid Goyal ' + +''' Code to manage ebook library''' + + +import os +from polyglot.builtins import range + + +def db(path=None, read_only=False): + from calibre.db.legacy import LibraryDatabase + from calibre.utils.config import prefs + return LibraryDatabase(os.path.expanduser(path) if path else prefs['library_path'], + read_only=read_only) + + +def generate_test_db(library_path, # {{{ + num_of_records=20000, + num_of_authors=6000, + num_of_tags=10000, + tag_length=7, + author_length=7, + title_length=10, + max_authors=10, + max_tags=10 + ): + import random, string, os, sys, time + from calibre.constants import preferred_encoding + + if not os.path.exists(library_path): + os.makedirs(library_path) + + letters = string.letters.decode(preferred_encoding) + + def randstr(length): + return ''.join(random.choice(letters) for i in + range(length)) + + all_tags = [randstr(tag_length) for j in range(num_of_tags)] + print('Generated', num_of_tags, 'tags') + all_authors = [randstr(author_length) for j in range(num_of_authors)] + print('Generated', num_of_authors, 'authors') + all_titles = [randstr(title_length) for j in range(num_of_records)] + print('Generated', num_of_records, 'titles') + + testdb = db(library_path) + + print('Creating', num_of_records, 'records...') + + start = time.time() + + for i, title in enumerate(all_titles): + print(i+1, end=' ') + sys.stdout.flush() + authors = random.randint(1, max_authors) + authors = [random.choice(all_authors) for i in range(authors)] + tags = random.randint(0, max_tags) + tags = [random.choice(all_tags) for i in range(tags)] + from calibre.ebooks.metadata.book.base import Metadata + mi = Metadata(title, authors) + mi.tags = tags + testdb.import_book(mi, []) + + t = time.time() - start + print('\nGenerated', num_of_records, 'records in:', t, 'seconds') + print('Time per record:', t/num_of_records) +# }}} + + +def current_library_path(): + from calibre.utils.config import prefs + path = prefs['library_path'] + if path: + path = path.replace('\\', '/') + while path.endswith('/'): + path = path[:-1] + return path + + +def current_library_name(): + import posixpath + path = current_library_path() + if path: + return posixpath.basename(path) diff --git a/ebook_converter/library/catalogs/__init__.py b/ebook_converter/library/catalogs/__init__.py new file mode 100644 index 0000000..53303c8 --- /dev/null +++ b/ebook_converter/library/catalogs/__init__.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2012, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + + +FIELDS = ['all', 'title', 'title_sort', 'author_sort', 'authors', 'comments', + 'cover', 'formats','id', 'isbn', 'library_name','ondevice', 'pubdate', 'publisher', + 'rating', 'series_index', 'series', 'size', 'tags', 'timestamp', + 'uuid', 'languages', 'identifiers'] + +# Allowed fields for template +TEMPLATE_ALLOWED_FIELDS = ['author_sort', 'authors', 'id', 'isbn', 'pubdate', 'title_sort', + 'publisher', 'series_index', 'series', 'tags', 'timestamp', 'title', 'uuid'] + + +class AuthorSortMismatchException(Exception): + pass + + +class EmptyCatalogException(Exception): + pass + + +class InvalidGenresSourceFieldException(Exception): + pass + diff --git a/ebook_converter/library/catalogs/bibtex.py b/ebook_converter/library/catalogs/bibtex.py new file mode 100644 index 0000000..17bc2b0 --- /dev/null +++ b/ebook_converter/library/catalogs/bibtex.py @@ -0,0 +1,402 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2012, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import re, codecs, os, numbers +from collections import namedtuple + +from calibre import strftime +from calibre.customize import CatalogPlugin +from calibre.library.catalogs import FIELDS, TEMPLATE_ALLOWED_FIELDS +from calibre.customize.conversion import DummyReporter +from calibre.ebooks.metadata import format_isbn +from polyglot.builtins import filter, string_or_bytes, unicode_type + + +class BIBTEX(CatalogPlugin): + 'BIBTEX catalog generator' + + Option = namedtuple('Option', 'option, default, dest, action, help') + + name = 'Catalog_BIBTEX' + description = 'BIBTEX catalog generator' + supported_platforms = ['windows', 'osx', 'linux'] + author = 'Sengian' + version = (1, 0, 0) + file_types = {'bib'} + + cli_options = [ + Option('--fields', + default='all', + dest='fields', + action=None, + help=_('The fields to output when cataloging books in the ' + 'database. Should be a comma-separated list of fields.\n' + 'Available fields: %(fields)s.\n' + 'plus user-created custom fields.\n' + 'Example: %(opt)s=title,authors,tags\n' + "Default: '%%default'\n" + "Applies to: BIBTEX output format")%dict( + fields=', '.join(FIELDS), opt='--fields')), + + Option('--sort-by', + default='id', + dest='sort_by', + action=None, + help=_('Output field to sort on.\n' + 'Available fields: author_sort, id, rating, size, timestamp, title.\n' + "Default: '%default'\n" + "Applies to: BIBTEX output format")), + + Option('--create-citation', + default='True', + dest='impcit', + action=None, + help=_('Create a citation for BibTeX entries.\n' + 'Boolean value: True, False\n' + "Default: '%default'\n" + "Applies to: BIBTEX output format")), + + Option('--add-files-path', + default='True', + dest='addfiles', + action=None, + help=_('Create a file entry if formats is selected for BibTeX entries.\n' + 'Boolean value: True, False\n' + "Default: '%default'\n" + "Applies to: BIBTEX output format")), + + Option('--citation-template', + default='{authors}{id}', + dest='bib_cit', + action=None, + help=_('The template for citation creation from database fields.\n' + 'Should be a template with {} enclosed fields.\n' + 'Available fields: %s.\n' + "Default: '%%default'\n" + "Applies to: BIBTEX output format")%', '.join(TEMPLATE_ALLOWED_FIELDS)), + + Option('--choose-encoding', + default='utf8', + dest='bibfile_enc', + action=None, + help=_('BibTeX file encoding output.\n' + 'Available types: utf8, cp1252, ascii.\n' + "Default: '%default'\n" + "Applies to: BIBTEX output format")), + + Option('--choose-encoding-configuration', + default='strict', + dest='bibfile_enctag', + action=None, + help=_('BibTeX file encoding flag.\n' + 'Available types: strict, replace, ignore, backslashreplace.\n' + "Default: '%default'\n" + "Applies to: BIBTEX output format")), + + Option('--entry-type', + default='book', + dest='bib_entry', + action=None, + help=_('Entry type for BibTeX catalog.\n' + 'Available types: book, misc, mixed.\n' + "Default: '%default'\n" + "Applies to: BIBTEX output format"))] + + def run(self, path_to_output, opts, db, notification=DummyReporter()): + from calibre.utils.date import isoformat + from calibre.utils.html2text import html2text + from calibre.utils.bibtex import BibTeX + from calibre.library.save_to_disk import preprocess_template + from calibre.utils.logging import default_log as log + from calibre.utils.filenames import ascii_text + + library_name = os.path.basename(db.library_path) + + def create_bibtex_entry(entry, fields, mode, template_citation, + bibtexdict, db, citation_bibtex=True, calibre_files=True): + + # Bibtex doesn't like UTF-8 but keep unicode until writing + # Define starting chain or if book valid strict and not book return a Fail string + + bibtex_entry = [] + if mode != "misc" and check_entry_book_valid(entry) : + bibtex_entry.append('@book{') + elif mode != "book" : + bibtex_entry.append('@misc{') + else : + # case strict book + return '' + + if citation_bibtex : + # Citation tag + bibtex_entry.append(make_bibtex_citation(entry, template_citation, + bibtexdict)) + bibtex_entry = [' '.join(bibtex_entry)] + + for field in fields: + if field.startswith('#'): + item = db.get_field(entry['id'],field,index_is_id=True) + if isinstance(item, (bool, numbers.Number)): + item = repr(item) + elif field == 'title_sort': + item = entry['sort'] + elif field == 'library_name': + item = library_name + else: + item = entry[field] + + # check if the field should be included (none or empty) + if item is None: + continue + try: + if len(item) == 0 : + continue + except TypeError: + pass + + if field == 'authors' : + bibtex_entry.append('author = "%s"' % bibtexdict.bibtex_author_format(item)) + + elif field == 'id' : + bibtex_entry.append('calibreid = "%s"' % int(item)) + + elif field == 'rating' : + bibtex_entry.append('rating = "%s"' % int(item)) + + elif field == 'size' : + bibtex_entry.append('%s = "%s octets"' % (field, int(item))) + + elif field == 'tags' : + # A list to flatten + bibtex_entry.append('tags = "%s"' % bibtexdict.utf8ToBibtex(', '.join(item))) + + elif field == 'comments' : + # \n removal + item = item.replace('\r\n', ' ') + item = item.replace('\n', ' ') + # unmatched brace removal (users should use \leftbrace or \rightbrace for single braces) + item = bibtexdict.stripUnmatchedSyntax(item, '{', '}') + # html to text + try: + item = html2text(item) + except: + log.warn("Failed to convert comments to text") + bibtex_entry.append('note = "%s"' % bibtexdict.utf8ToBibtex(item)) + + elif field == 'isbn' : + # Could be 9, 10 or 13 digits + bibtex_entry.append('isbn = "%s"' % format_isbn(item)) + + elif field == 'formats' : + # Add file path if format is selected + formats = [format.rpartition('.')[2].lower() for format in item] + bibtex_entry.append('formats = "%s"' % ', '.join(formats)) + if calibre_files: + files = [':%s:%s' % (format, format.rpartition('.')[2].upper()) + for format in item] + bibtex_entry.append('file = "%s"' % ', '.join(files)) + + elif field == 'series_index' : + bibtex_entry.append('volume = "%s"' % int(item)) + + elif field == 'timestamp' : + bibtex_entry.append('timestamp = "%s"' % isoformat(item).partition('T')[0]) + + elif field == 'pubdate' : + bibtex_entry.append('year = "%s"' % item.year) + bibtex_entry.append('month = "%s"' % bibtexdict.utf8ToBibtex(strftime("%b", item))) + + elif field.startswith('#') and isinstance(item, string_or_bytes): + bibtex_entry.append('custom_%s = "%s"' % (field[1:], + bibtexdict.utf8ToBibtex(item))) + + elif isinstance(item, string_or_bytes): + # elif field in ['title', 'publisher', 'cover', 'uuid', 'ondevice', + # 'author_sort', 'series', 'title_sort'] : + bibtex_entry.append('%s = "%s"' % (field, bibtexdict.utf8ToBibtex(item))) + + bibtex_entry = ',\n '.join(bibtex_entry) + bibtex_entry += ' }\n\n' + + return bibtex_entry + + def check_entry_book_valid(entry): + # Check that the required fields are ok for a book entry + for field in ['title', 'authors', 'publisher'] : + if entry[field] is None or len(entry[field]) == 0 : + return False + if entry['pubdate'] is None : + return False + else : + return True + + def make_bibtex_citation(entry, template_citation, bibtexclass): + + # define a function to replace the template entry by its value + def tpl_replace(objtplname) : + + tpl_field = re.sub(r'[\{\}]', '', objtplname.group()) + + if tpl_field in TEMPLATE_ALLOWED_FIELDS : + if tpl_field in ['pubdate', 'timestamp'] : + tpl_field = isoformat(entry[tpl_field]).partition('T')[0] + elif tpl_field in ['tags', 'authors'] : + tpl_field =entry[tpl_field][0] + elif tpl_field in ['id', 'series_index'] : + tpl_field = unicode_type(entry[tpl_field]) + else : + tpl_field = entry[tpl_field] + return ascii_text(tpl_field) + else: + return '' + + if len(template_citation) >0 : + tpl_citation = bibtexclass.utf8ToBibtex( + bibtexclass.ValidateCitationKey(re.sub(r'\{[^{}]*\}', + tpl_replace, template_citation))) + + if len(tpl_citation) >0 : + return tpl_citation + + if len(entry["isbn"]) > 0 : + template_citation = '%s' % re.sub(r'[\D]','', entry["isbn"]) + + else : + template_citation = '%s' % unicode_type(entry["id"]) + + return bibtexclass.ValidateCitationKey(template_citation) + + self.fmt = path_to_output.rpartition('.')[2] + self.notification = notification + + # Combobox options + bibfile_enc = ['utf8', 'cp1252', 'ascii'] + bibfile_enctag = ['strict', 'replace', 'ignore', 'backslashreplace'] + bib_entry = ['mixed', 'misc', 'book'] + + # Needed beacause CLI return str vs int by widget + try: + bibfile_enc = bibfile_enc[opts.bibfile_enc] + bibfile_enctag = bibfile_enctag[opts.bibfile_enctag] + bib_entry = bib_entry[opts.bib_entry] + except: + if opts.bibfile_enc in bibfile_enc : + bibfile_enc = opts.bibfile_enc + else : + log.warn("Incorrect --choose-encoding flag, revert to default") + bibfile_enc = bibfile_enc[0] + if opts.bibfile_enctag in bibfile_enctag : + bibfile_enctag = opts.bibfile_enctag + else : + log.warn("Incorrect --choose-encoding-configuration flag, revert to default") + bibfile_enctag = bibfile_enctag[0] + if opts.bib_entry in bib_entry : + bib_entry = opts.bib_entry + else : + log.warn("Incorrect --entry-type flag, revert to default") + bib_entry = bib_entry[0] + + if opts.verbose: + opts_dict = vars(opts) + log("%s(): Generating %s" % (self.name,self.fmt)) + if opts.connected_device['is_device_connected']: + log(" connected_device: %s" % opts.connected_device['name']) + if opts_dict['search_text']: + log(" --search='%s'" % opts_dict['search_text']) + + if opts_dict['ids']: + log(" Book count: %d" % len(opts_dict['ids'])) + if opts_dict['search_text']: + log(" (--search ignored when a subset of the database is specified)") + + if opts_dict['fields']: + if opts_dict['fields'] == 'all': + log(" Fields: %s" % ', '.join(FIELDS[1:])) + else: + log(" Fields: %s" % opts_dict['fields']) + + log(" Output file will be encoded in %s with %s flag" % (bibfile_enc, bibfile_enctag)) + + log(" BibTeX entry type is %s with a citation like '%s' flag" % (bib_entry, opts_dict['bib_cit'])) + + # If a list of ids are provided, don't use search_text + if opts.ids: + opts.search_text = None + + data = self.search_sort_db(db, opts) + + if not len(data): + log.error("\nNo matching database entries for search criteria '%s'" % opts.search_text) + + # Get the requested output fields as a list + fields = self.get_output_fields(db, opts) + + if not len(data): + log.error("\nNo matching database entries for search criteria '%s'" % opts.search_text) + + # Initialize BibTeX class + bibtexc = BibTeX() + + # Entries writing after Bibtex formating (or not) + if bibfile_enc != 'ascii' : + bibtexc.ascii_bibtex = False + else : + bibtexc.ascii_bibtex = True + + # Check citation choice and go to default in case of bad CLI + if isinstance(opts.impcit, string_or_bytes) : + if opts.impcit == 'False' : + citation_bibtex= False + elif opts.impcit == 'True' : + citation_bibtex= True + else : + log.warn("Incorrect --create-citation, revert to default") + citation_bibtex= True + else : + citation_bibtex= opts.impcit + + # Check add file entry and go to default in case of bad CLI + if isinstance(opts.addfiles, string_or_bytes) : + if opts.addfiles == 'False' : + addfiles_bibtex = False + elif opts.addfiles == 'True' : + addfiles_bibtex = True + else : + log.warn("Incorrect --add-files-path, revert to default") + addfiles_bibtex= True + else : + addfiles_bibtex = opts.addfiles + + # Preprocess for error and light correction + template_citation = preprocess_template(opts.bib_cit) + + # Open output and write entries + with codecs.open(path_to_output, 'w', bibfile_enc, bibfile_enctag)\ + as outfile: + # File header + nb_entries = len(data) + + # check in book strict if all is ok else throw a warning into log + if bib_entry == 'book' : + nb_books = len(list(filter(check_entry_book_valid, data))) + if nb_books < nb_entries : + log.warn("Only %d entries in %d are book compatible" % (nb_books, nb_entries)) + nb_entries = nb_books + + # If connected device, add 'On Device' values to data + if opts.connected_device['is_device_connected'] and 'ondevice' in fields: + for entry in data: + entry['ondevice'] = db.catalog_plugin_on_device_temp_mapping[entry['id']]['ondevice'] + + outfile.write('%%%Calibre catalog\n%%%{0} entries in catalog\n\n'.format(nb_entries)) + outfile.write('@preamble{"This catalog of %d entries was generated by calibre on %s"}\n\n' + % (nb_entries, strftime("%A, %d. %B %Y %H:%M"))) + + for entry in data: + outfile.write(create_bibtex_entry(entry, fields, bib_entry, template_citation, + bibtexc, db, citation_bibtex, addfiles_bibtex)) diff --git a/ebook_converter/library/catalogs/csv_xml.py b/ebook_converter/library/catalogs/csv_xml.py new file mode 100644 index 0000000..e80c027 --- /dev/null +++ b/ebook_converter/library/catalogs/csv_xml.py @@ -0,0 +1,241 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2012, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import re, codecs, os +from collections import namedtuple + +from calibre.customize import CatalogPlugin +from calibre.library.catalogs import FIELDS +from calibre.customize.conversion import DummyReporter +from polyglot.builtins import unicode_type + + +class CSV_XML(CatalogPlugin): + + 'CSV/XML catalog generator' + + Option = namedtuple('Option', 'option, default, dest, action, help') + + name = 'Catalog_CSV_XML' + description = 'CSV/XML catalog generator' + supported_platforms = ['windows', 'osx', 'linux'] + author = 'Greg Riker' + version = (1, 0, 0) + file_types = {'csv', 'xml'} + + cli_options = [ + Option('--fields', + default='all', + dest='fields', + action=None, + help=_('The fields to output when cataloging books in the ' + 'database. Should be a comma-separated list of fields.\n' + 'Available fields: %(fields)s,\n' + 'plus user-created custom fields.\n' + 'Example: %(opt)s=title,authors,tags\n' + "Default: '%%default'\n" + "Applies to: CSV, XML output formats") % dict( + fields=', '.join(FIELDS), opt='--fields')), + + Option('--sort-by', + default='id', + dest='sort_by', + action=None, + help=_('Output field to sort on.\n' + 'Available fields: author_sort, id, rating, size, timestamp, title_sort\n' + "Default: '%default'\n" + "Applies to: CSV, XML output formats"))] + + def run(self, path_to_output, opts, db, notification=DummyReporter()): + from calibre.library import current_library_name + from calibre.utils.date import isoformat + from calibre.utils.html2text import html2text + from calibre.utils.logging import default_log as log + from lxml import etree + from calibre.ebooks.metadata import authors_to_string + + self.fmt = path_to_output.rpartition('.')[2] + self.notification = notification + current_library = current_library_name() + if getattr(opts, 'library_path', None): + current_library = os.path.basename(opts.library_path) + + if opts.verbose: + opts_dict = vars(opts) + log("%s('%s'): Generating %s" % (self.name, current_library, self.fmt.upper())) + if opts.connected_device['is_device_connected']: + log(" connected_device: %s" % opts.connected_device['name']) + if opts_dict['search_text']: + log(" --search='%s'" % opts_dict['search_text']) + + if opts_dict['ids']: + log(" Book count: %d" % len(opts_dict['ids'])) + if opts_dict['search_text']: + log(" (--search ignored when a subset of the database is specified)") + + if opts_dict['fields']: + if opts_dict['fields'] == 'all': + log(" Fields: %s" % ', '.join(FIELDS[1:])) + else: + log(" Fields: %s" % opts_dict['fields']) + + # If a list of ids are provided, don't use search_text + if opts.ids: + opts.search_text = None + + data = self.search_sort_db(db, opts) + + if not len(data): + log.error("\nNo matching database entries for search criteria '%s'" % opts.search_text) + # raise SystemExit(1) + + # Get the requested output fields as a list + fields = self.get_output_fields(db, opts) + + # If connected device, add 'On Device' values to data + if opts.connected_device['is_device_connected'] and 'ondevice' in fields: + for entry in data: + entry['ondevice'] = db.catalog_plugin_on_device_temp_mapping[entry['id']]['ondevice'] + + fm = {x: db.field_metadata.get(x, {}) for x in fields} + + if self.fmt == 'csv': + outfile = codecs.open(path_to_output, 'w', 'utf8') + + # Write a UTF-8 BOM + outfile.write('\ufeff') + + # Output the field headers + outfile.write('%s\n' % ','.join(fields)) + + # Output the entry fields + for entry in data: + outstr = [] + for field in fields: + if field.startswith('#'): + item = db.get_field(entry['id'], field, index_is_id=True) + if isinstance(item, (list, tuple)): + if fm.get(field, {}).get('display', {}).get('is_names', False): + item = ' & '.join(item) + else: + item = ', '.join(item) + elif field == 'library_name': + item = current_library + elif field == 'title_sort': + item = entry['sort'] + else: + item = entry[field] + + if item is None: + outstr.append('""') + continue + elif field == 'formats': + fmt_list = [] + for format in item: + fmt_list.append(format.rpartition('.')[2].lower()) + item = ', '.join(fmt_list) + elif field == 'authors': + item = authors_to_string(item) + elif field == 'tags': + item = ', '.join(item) + elif field == 'isbn': + # Could be 9, 10 or 13 digits, with hyphens, possibly ending in 'X' + item = '%s' % re.sub(r'[^\dX-]', '', item) + elif fm.get(field, {}).get('datatype') == 'datetime': + item = isoformat(item, as_utc=False) + elif field == 'comments': + item = item.replace('\r\n', ' ') + item = item.replace('\n', ' ') + elif fm.get(field, {}).get('datatype', None) == 'rating' and item: + item = '%.2g' % (item / 2) + + # Convert HTML to markdown text + if isinstance(item, unicode_type): + opening_tag = re.search(r'<(\w+)( |>)', item) + if opening_tag: + closing_tag = re.search(r'<\/%s>$' % opening_tag.group(1), item) + if closing_tag: + item = html2text(item) + + outstr.append('"%s"' % unicode_type(item).replace('"', '""')) + + outfile.write(','.join(outstr) + '\n') + outfile.close() + + elif self.fmt == 'xml': + from lxml.builder import E + + root = E.calibredb() + for r in data: + record = E.record() + root.append(record) + + for field in fields: + if field.startswith('#'): + val = db.get_field(r['id'], field, index_is_id=True) + if not isinstance(val, unicode_type): + val = unicode_type(val) + item = getattr(E, field.replace('#', '_'))(val) + record.append(item) + + for field in ('id', 'uuid', 'publisher', 'rating', 'size', + 'isbn', 'ondevice', 'identifiers'): + if field in fields: + val = r[field] + if not val: + continue + if not isinstance(val, (bytes, unicode_type)): + if (fm.get(field, {}).get('datatype', None) == + 'rating' and val): + val = '%.2g' % (val / 2) + val = unicode_type(val) + item = getattr(E, field)(val) + record.append(item) + + if 'title' in fields: + title = E.title(r['title'], sort=r['sort']) + record.append(title) + + if 'authors' in fields: + aus = E.authors(sort=r['author_sort']) + for au in r['authors']: + aus.append(E.author(au)) + record.append(aus) + + for field in ('timestamp', 'pubdate'): + if field in fields: + record.append(getattr(E, field)(isoformat(r[field], as_utc=False))) + + if 'tags' in fields and r['tags']: + tags = E.tags() + for tag in r['tags']: + tags.append(E.tag(tag)) + record.append(tags) + + if 'comments' in fields and r['comments']: + record.append(E.comments(r['comments'])) + + if 'series' in fields and r['series']: + record.append(E.series(r['series'], + index=unicode_type(r['series_index']))) + + if 'cover' in fields and r['cover']: + record.append(E.cover(r['cover'].replace(os.sep, '/'))) + + if 'formats' in fields and r['formats']: + fmt = E.formats() + for f in r['formats']: + fmt.append(E.format(f.replace(os.sep, '/'))) + record.append(fmt) + + if 'library_name' in fields: + record.append(E.library_name(current_library)) + + with open(path_to_output, 'wb') as f: + f.write(etree.tostring(root, encoding='utf-8', + xml_declaration=True, pretty_print=True)) diff --git a/ebook_converter/library/catalogs/epub_mobi.py b/ebook_converter/library/catalogs/epub_mobi.py new file mode 100644 index 0000000..112e7c9 --- /dev/null +++ b/ebook_converter/library/catalogs/epub_mobi.py @@ -0,0 +1,506 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2012, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import datetime, os, time +from collections import namedtuple + +from calibre import strftime +from calibre.customize import CatalogPlugin +from calibre.customize.conversion import OptionRecommendation, DummyReporter +from calibre.library import current_library_name +from calibre.library.catalogs import AuthorSortMismatchException, EmptyCatalogException +from calibre.ptempfile import PersistentTemporaryFile +from calibre.utils.localization import calibre_langcode_to_name, canonicalize_lang, get_lang +from polyglot.builtins import unicode_type + +Option = namedtuple('Option', 'option, default, dest, action, help') + + +class EPUB_MOBI(CatalogPlugin): + + 'EPUB catalog generator' + + name = 'Catalog_EPUB_MOBI' + description = 'AZW3/EPUB/MOBI catalog generator' + supported_platforms = ['windows', 'osx', 'linux'] + minimum_calibre_version = (0, 7, 40) + author = 'Greg Riker' + version = (1, 0, 0) + file_types = {'azw3', 'epub', 'mobi'} + + THUMB_SMALLEST = "1.0" + THUMB_LARGEST = "2.0" + + cli_options = [Option('--catalog-title', # {{{ + default='My Books', + dest='catalog_title', + action=None, + help=_('Title of generated catalog used as title in metadata.\n' + "Default: '%default'\n" + "Applies to: AZW3, EPUB, MOBI output formats")), + Option('--cross-reference-authors', + default=False, + dest='cross_reference_authors', + action='store_true', + help=_("Create cross-references in Authors section for books with multiple authors.\n" + "Default: '%default'\n" + "Applies to: AZW3, EPUB, MOBI output formats")), + Option('--debug-pipeline', + default=None, + dest='debug_pipeline', + action=None, + help=_("Save the output from different stages of the conversion " + "pipeline to the specified " + "directory. Useful if you are unsure at which stage " + "of the conversion process a bug is occurring.\n" + "Default: '%default'\n" + "Applies to: AZW3, EPUB, MOBI output formats")), + Option('--exclude-genre', + default=r'\[.+\]|^\+$', + dest='exclude_genre', + action=None, + help=_("Regex describing tags to exclude as genres.\n" + "Default: '%default' excludes bracketed tags, e.g. '[Project Gutenberg]', and '+', the default tag for read books.\n" + "Applies to: AZW3, EPUB, MOBI output formats")), + Option('--exclusion-rules', + default="(('Catalogs','Tags','Catalog'),)", + dest='exclusion_rules', + action=None, + help=_("Specifies the rules used to exclude books from the generated catalog.\n" + "The model for an exclusion rule is either\n('','Tags','') or\n" + "('','','').\n" + "For example:\n" + "(('Archived books','#status','Archived'),)\n" + "will exclude a book with a value of 'Archived' in the custom column 'status'.\n" + "When multiple rules are defined, all rules will be applied.\n" + "Default: \n" + '"' + '%default' + '"' + "\n" + "Applies to: AZW3, EPUB, MOBI output formats")), + Option('--generate-authors', + default=False, + dest='generate_authors', + action='store_true', + help=_("Include 'Authors' section in catalog.\n" + "Default: '%default'\n" + "Applies to: AZW3, EPUB, MOBI output formats")), + Option('--generate-descriptions', + default=False, + dest='generate_descriptions', + action='store_true', + help=_("Include 'Descriptions' section in catalog.\n" + "Default: '%default'\n" + "Applies to: AZW3, EPUB, MOBI output formats")), + Option('--generate-genres', + default=False, + dest='generate_genres', + action='store_true', + help=_("Include 'Genres' section in catalog.\n" + "Default: '%default'\n" + "Applies to: AZW3, EPUB, MOBI output formats")), + Option('--generate-titles', + default=False, + dest='generate_titles', + action='store_true', + help=_("Include 'Titles' section in catalog.\n" + "Default: '%default'\n" + "Applies to: AZW3, EPUB, MOBI output formats")), + Option('--generate-series', + default=False, + dest='generate_series', + action='store_true', + help=_("Include 'Series' section in catalog.\n" + "Default: '%default'\n" + "Applies to: AZW3, EPUB, MOBI output formats")), + Option('--generate-recently-added', + default=False, + dest='generate_recently_added', + action='store_true', + help=_("Include 'Recently Added' section in catalog.\n" + "Default: '%default'\n" + "Applies to: AZW3, EPUB, MOBI output formats")), + Option('--genre-source-field', + default=_('Tags'), + dest='genre_source_field', + action=None, + help=_("Source field for 'Genres' section.\n" + "Default: '%default'\n" + "Applies to: AZW3, EPUB, MOBI output formats")), + Option('--header-note-source-field', + default='', + dest='header_note_source_field', + action=None, + help=_("Custom field containing note text to insert in Description header.\n" + "Default: '%default'\n" + "Applies to: AZW3, EPUB, MOBI output formats")), + Option('--merge-comments-rule', + default='::', + dest='merge_comments_rule', + action=None, + help=_("#:[before|after]:[True|False] specifying:\n" + " Custom field containing notes to merge with Comments\n" + " [before|after] Placement of notes with respect to Comments\n" + " [True|False] - A horizontal rule is inserted between notes and Comments\n" + "Default: '%default'\n" + "Applies to: AZW3, EPUB, MOBI output formats")), + Option('--output-profile', + default=None, + dest='output_profile', + action=None, + help=_("Specifies the output profile. In some cases, an output profile is required to optimize" + " the catalog for the device. For example, 'kindle' or 'kindle_dx' creates a structured" + " Table of Contents with Sections and Articles.\n" + "Default: '%default'\n" + "Applies to: AZW3, EPUB, MOBI output formats")), + Option('--prefix-rules', + default="(('Read books','tags','+','\u2713'),('Wishlist item','tags','Wishlist','\u00d7'))", + dest='prefix_rules', + action=None, + help=_("Specifies the rules used to include prefixes indicating read books, wishlist items and other user-specified prefixes.\n" + "The model for a prefix rule is ('','','','').\n" + "When multiple rules are defined, the first matching rule will be used.\n" + "Default:\n" + '"' + '%default' + '"' + "\n" + "Applies to: AZW3, EPUB, MOBI output formats")), + Option('--preset', + default=None, + dest='preset', + action=None, + help=_("Use a named preset created with the GUI catalog builder.\n" + "A preset specifies all settings for building a catalog.\n" + "Default: '%default'\n" + "Applies to: AZW3, EPUB, MOBI output formats")), + Option('--use-existing-cover', + default=False, + dest='use_existing_cover', + action='store_true', + help=_("Replace existing cover when generating the catalog.\n" + "Default: '%default'\n" + "Applies to: AZW3, EPUB, MOBI output formats")), + Option('--thumb-width', + default='1.0', + dest='thumb_width', + action=None, + help=_("Size hint (in inches) for book covers in catalog.\n" + "Range: 1.0 - 2.0\n" + "Default: '%default'\n" + "Applies to: AZW3, EPUB, MOBI output formats")), + ] + # }}} + + def run(self, path_to_output, opts, db, notification=DummyReporter()): + from calibre.library.catalogs.epub_mobi_builder import CatalogBuilder + from calibre.utils.logging import default_log as log + from calibre.utils.config import JSONConfig + + # If preset specified from the cli, insert stored options from JSON file + if hasattr(opts, 'preset') and opts.preset: + available_presets = JSONConfig("catalog_presets") + if opts.preset not in available_presets: + if available_presets: + print(_('Error: Preset "%s" not found.' % opts.preset)) + print(_('Stored presets: %s' % ', '.join([p for p in sorted(available_presets.keys())]))) + else: + print(_('Error: No stored presets.')) + return 1 + + # Copy the relevant preset values to the opts object + for item in available_presets[opts.preset]: + if item not in ['exclusion_rules_tw', 'format', 'prefix_rules_tw']: + setattr(opts, item, available_presets[opts.preset][item]) + + # Provide an unconnected device + opts.connected_device = { + 'is_device_connected': False, + 'kind': None, + 'name': None, + 'save_template': None, + 'serial': None, + 'storage': None, + } + + # Convert prefix_rules and exclusion_rules from JSON lists to tuples + prs = [] + for rule in opts.prefix_rules: + prs.append(tuple(rule)) + opts.prefix_rules = tuple(prs) + + ers = [] + for rule in opts.exclusion_rules: + ers.append(tuple(rule)) + opts.exclusion_rules = tuple(ers) + + opts.log = log + opts.fmt = self.fmt = path_to_output.rpartition('.')[2] + + # Add local options + opts.creator = '%s, %s %s, %s' % (strftime('%A'), strftime('%B'), strftime('%d').lstrip('0'), strftime('%Y')) + opts.creator_sort_as = '%s %s' % ('calibre', strftime('%Y-%m-%d')) + opts.connected_kindle = False + + # Finalize output_profile + op = opts.output_profile + if op is None: + op = 'default' + + if opts.connected_device['name'] and 'kindle' in opts.connected_device['name'].lower(): + opts.connected_kindle = True + if opts.connected_device['serial'] and \ + opts.connected_device['serial'][:4] in ['B004', 'B005']: + op = "kindle_dx" + else: + op = "kindle" + + opts.description_clip = 380 if op.endswith('dx') or 'kindle' not in op else 100 + opts.author_clip = 100 if op.endswith('dx') or 'kindle' not in op else 60 + opts.output_profile = op + + opts.basename = "Catalog" + opts.cli_environment = not hasattr(opts, 'sync') + + # Hard-wired to always sort descriptions by author, with series after non-series + opts.sort_descriptions_by_author = True + + build_log = [] + + build_log.append("%s('%s'): Generating %s %sin %s environment, locale: '%s'" % + (self.name, + current_library_name(), + self.fmt, + 'for %s ' % opts.output_profile if opts.output_profile else '', + 'CLI' if opts.cli_environment else 'GUI', + calibre_langcode_to_name(canonicalize_lang(get_lang()), localize=False)) + ) + + # If exclude_genre is blank, assume user wants all tags as genres + if opts.exclude_genre.strip() == '': + # opts.exclude_genre = '\[^.\]' + # build_log.append(" converting empty exclude_genre to '\[^.\]'") + opts.exclude_genre = 'a^' + build_log.append(" converting empty exclude_genre to 'a^'") + if opts.connected_device['is_device_connected'] and \ + opts.connected_device['kind'] == 'device': + if opts.connected_device['serial']: + build_log.append(" connected_device: '%s' #%s%s " % + (opts.connected_device['name'], + opts.connected_device['serial'][0:4], + 'x' * (len(opts.connected_device['serial']) - 4))) + for storage in opts.connected_device['storage']: + if storage: + build_log.append(" mount point: %s" % storage) + else: + build_log.append(" connected_device: '%s'" % opts.connected_device['name']) + try: + for storage in opts.connected_device['storage']: + if storage: + build_log.append(" mount point: %s" % storage) + except: + build_log.append(" (no mount points)") + else: + build_log.append(" connected_device: '%s'" % opts.connected_device['name']) + + opts_dict = vars(opts) + if opts_dict['ids']: + build_log.append(" book count: %d" % len(opts_dict['ids'])) + + sections_list = [] + if opts.generate_authors: + sections_list.append('Authors') + if opts.generate_titles: + sections_list.append('Titles') + if opts.generate_series: + sections_list.append('Series') + if opts.generate_genres: + sections_list.append('Genres') + if opts.generate_recently_added: + sections_list.append('Recently Added') + if opts.generate_descriptions: + sections_list.append('Descriptions') + + if not sections_list: + if opts.cli_environment: + opts.log.warn('*** No Section switches specified, enabling all Sections ***') + opts.generate_authors = True + opts.generate_titles = True + opts.generate_series = True + opts.generate_genres = True + opts.generate_recently_added = True + opts.generate_descriptions = True + sections_list = ['Authors', 'Titles', 'Series', 'Genres', 'Recently Added', 'Descriptions'] + else: + opts.log.warn('\n*** No enabled Sections, terminating catalog generation ***') + return ["No Included Sections", "No enabled Sections.\nCheck E-book options tab\n'Included sections'\n"] + if opts.fmt == 'mobi' and sections_list == ['Descriptions']: + warning = _("\n*** Adding 'By authors' section required for MOBI output ***") + opts.log.warn(warning) + sections_list.insert(0, 'Authors') + opts.generate_authors = True + + opts.log(" Sections: %s" % ', '.join(sections_list)) + opts.section_list = sections_list + + # Limit thumb_width to 1.0" - 2.0" + try: + if float(opts.thumb_width) < float(self.THUMB_SMALLEST): + log.warning("coercing thumb_width from '%s' to '%s'" % (opts.thumb_width, self.THUMB_SMALLEST)) + opts.thumb_width = self.THUMB_SMALLEST + if float(opts.thumb_width) > float(self.THUMB_LARGEST): + log.warning("coercing thumb_width from '%s' to '%s'" % (opts.thumb_width, self.THUMB_LARGEST)) + opts.thumb_width = self.THUMB_LARGEST + opts.thumb_width = "%.2f" % float(opts.thumb_width) + except: + log.error("coercing thumb_width from '%s' to '%s'" % (opts.thumb_width, self.THUMB_SMALLEST)) + opts.thumb_width = "1.0" + + # eval prefix_rules if passed from command line + if type(opts.prefix_rules) is not tuple: + try: + opts.prefix_rules = eval(opts.prefix_rules) + except: + log.error("malformed --prefix-rules: %s" % opts.prefix_rules) + raise + for rule in opts.prefix_rules: + if len(rule) != 4: + log.error("incorrect number of args for --prefix-rules: %s" % repr(rule)) + + # eval exclusion_rules if passed from command line + if type(opts.exclusion_rules) is not tuple: + try: + opts.exclusion_rules = eval(opts.exclusion_rules) + except: + log.error("malformed --exclusion-rules: %s" % opts.exclusion_rules) + raise + for rule in opts.exclusion_rules: + if len(rule) != 3: + log.error("incorrect number of args for --exclusion-rules: %s" % repr(rule)) + + # Display opts + keys = sorted(opts_dict.keys()) + build_log.append(" opts:") + for key in keys: + if key in ['catalog_title', 'author_clip', 'connected_kindle', 'creator', + 'cross_reference_authors', 'description_clip', 'exclude_book_marker', + 'exclude_genre', 'exclude_tags', 'exclusion_rules', 'fmt', + 'genre_source_field', 'header_note_source_field', 'merge_comments_rule', + 'output_profile', 'prefix_rules', 'preset', 'read_book_marker', + 'search_text', 'sort_by', 'sort_descriptions_by_author', 'sync', + 'thumb_width', 'use_existing_cover', 'wishlist_tag']: + build_log.append(" %s: %s" % (key, repr(opts_dict[key]))) + if opts.verbose: + log('\n'.join(line for line in build_log)) + + # Capture start_time + opts.start_time = time.time() + + self.opts = opts + + if opts.verbose: + log.info(" Begin catalog source generation (%s)" % + unicode_type(datetime.timedelta(seconds=int(time.time() - opts.start_time)))) + + # Launch the Catalog builder + catalog = CatalogBuilder(db, opts, self, report_progress=notification) + + try: + catalog.build_sources() + if opts.verbose: + log.info(" Completed catalog source generation (%s)\n" % + unicode_type(datetime.timedelta(seconds=int(time.time() - opts.start_time)))) + except (AuthorSortMismatchException, EmptyCatalogException) as e: + log.error(" *** Terminated catalog generation: %s ***" % e) + except: + log.error(" unhandled exception in catalog generator") + raise + + else: + recommendations = [] + recommendations.append(('remove_fake_margins', False, + OptionRecommendation.HIGH)) + recommendations.append(('comments', '', OptionRecommendation.HIGH)) + + """ + >>> Use to debug generated catalog code before pipeline conversion <<< + """ + GENERATE_DEBUG_EPUB = False + if GENERATE_DEBUG_EPUB: + catalog_debug_path = os.path.join(os.path.expanduser('~'), 'Desktop', 'Catalog debug') + setattr(opts, 'debug_pipeline', os.path.expanduser(catalog_debug_path)) + + dp = getattr(opts, 'debug_pipeline', None) + if dp is not None: + recommendations.append(('debug_pipeline', dp, + OptionRecommendation.HIGH)) + + if opts.output_profile and opts.output_profile.startswith("kindle"): + recommendations.append(('output_profile', opts.output_profile, + OptionRecommendation.HIGH)) + recommendations.append(('book_producer', opts.output_profile, + OptionRecommendation.HIGH)) + if opts.fmt == 'mobi': + recommendations.append(('no_inline_toc', True, + OptionRecommendation.HIGH)) + recommendations.append(('verbose', 2, + OptionRecommendation.HIGH)) + + # Use existing cover or generate new cover + cpath = None + existing_cover = False + try: + search_text = 'title:"%s" author:%s' % ( + opts.catalog_title.replace('"', '\\"'), 'calibre') + matches = db.search(search_text, return_matches=True, sort_results=False) + if matches: + cpath = db.cover(matches[0], index_is_id=True, as_path=True) + if cpath and os.path.exists(cpath): + existing_cover = True + except: + pass + + if self.opts.use_existing_cover and not existing_cover: + log.warning("no existing catalog cover found") + + if self.opts.use_existing_cover and existing_cover: + recommendations.append(('cover', cpath, OptionRecommendation.HIGH)) + log.info("using existing catalog cover") + else: + from calibre.ebooks.covers import calibre_cover2 + log.info("replacing catalog cover") + new_cover_path = PersistentTemporaryFile(suffix='.jpg') + new_cover = calibre_cover2(opts.catalog_title, 'calibre') + new_cover_path.write(new_cover) + new_cover_path.close() + recommendations.append(('cover', new_cover_path.name, OptionRecommendation.HIGH)) + + # Run ebook-convert + from calibre.ebooks.conversion.plumber import Plumber + plumber = Plumber(os.path.join(catalog.catalog_path, opts.basename + '.opf'), + path_to_output, log, report_progress=notification, + abort_after_input_dump=False) + plumber.merge_ui_recommendations(recommendations) + plumber.run() + + try: + os.remove(cpath) + except: + pass + + if GENERATE_DEBUG_EPUB: + from calibre.ebooks.epub import initialize_container + from calibre.ebooks.tweak import zip_rebuilder + from calibre.utils.zipfile import ZipFile + input_path = os.path.join(catalog_debug_path, 'input') + epub_shell = os.path.join(catalog_debug_path, 'epub_shell.zip') + initialize_container(epub_shell, opf_name='content.opf') + with ZipFile(epub_shell, 'r') as zf: + zf.extractall(path=input_path) + os.remove(epub_shell) + zip_rebuilder(input_path, os.path.join(catalog_debug_path, 'input.epub')) + + if opts.verbose: + log.info(" Catalog creation complete (%s)\n" % + unicode_type(datetime.timedelta(seconds=int(time.time() - opts.start_time)))) + + # returns to gui2.actions.catalog:catalog_generated() + return catalog.error diff --git a/ebook_converter/library/comments.py b/ebook_converter/library/comments.py new file mode 100644 index 0000000..344dd99 --- /dev/null +++ b/ebook_converter/library/comments.py @@ -0,0 +1,174 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +# License: GPLv3 Copyright: 2010, Kovid Goyal + +from __future__ import absolute_import, division, print_function, unicode_literals + +import re + +from calibre import prepare_string_for_xml +from calibre.constants import preferred_encoding +from calibre.ebooks.BeautifulSoup import ( + BeautifulSoup, CData, Comment, Declaration, NavigableString, + ProcessingInstruction +) +from calibre.utils.html2text import html2text +from polyglot.builtins import unicode_type + +# Hackish - ignoring sentences ending or beginning in numbers to avoid +# confusion with decimal points. +lost_cr_pat = re.compile('([a-z])([\\.\\?!])([A-Z])') +lost_cr_exception_pat = re.compile(r'(Ph\.D)|(D\.Phil)|((Dr|Mr|Mrs|Ms)\.[A-Z])') +sanitize_pat = re.compile(r's + 'plain text' returns as +

plain text

+ + 'plain text with minimal markup' returns as +

plain text with minimal markup

+ + '

pre-formatted text

returns untouched + + 'A line of text\n\nFollowed by a line of text' returns as +

A line of text

+

Followed by a line of text

+ + 'A line of text.\nA second line of text.\rA third line of text' returns as +

A line of text.
A second line of text.
A third line of text.

+ + '...end of a paragraph.Somehow the break was lost...' returns as +

...end of a paragraph.

+

Somehow the break was lost...

+ + Deprecated HTML returns as HTML via BeautifulSoup() + + ''' + if not comments: + return u'

' + if not isinstance(comments, unicode_type): + comments = comments.decode(preferred_encoding, 'replace') + + if comments.lstrip().startswith('<'): + # Comment is already HTML do not mess with it + return comments + + if '<' not in comments: + comments = prepare_string_for_xml(comments) + parts = [u'

%s

'%x.replace(u'\n', u'
') + for x in comments.split('\n\n')] + return '\n'.join(parts) + + if sanitize_pat.search(comments) is not None: + try: + return sanitize_comments_html(comments) + except: + import traceback + traceback.print_exc() + return u'

' + + # Explode lost CRs to \n\n + comments = lost_cr_exception_pat.sub(lambda m: m.group().replace('.', + '.\r'), comments) + for lost_cr in lost_cr_pat.finditer(comments): + comments = comments.replace(lost_cr.group(), + '%s%s\n\n%s' % (lost_cr.group(1), + lost_cr.group(2), + lost_cr.group(3))) + + comments = comments.replace(u'\r', u'') + # Convert \n\n to

s + comments = comments.replace(u'\n\n', u'

') + # Convert solo returns to
+ comments = comments.replace(u'\n', '
') + # Convert two hyphens to emdash + comments = comments.replace('--', '—') + + soup = BeautifulSoup('

' + comments + '
').find('div') + result = BeautifulSoup('
') + container = result.find('div') + rtc = 0 + open_pTag = False + + all_tokens = list(soup.contents) + inline_tags = ('br', 'b', 'i', 'em', 'strong', 'span', 'font', 'a', 'hr') + for token in all_tokens: + if isinstance(token, (CData, Comment, Declaration, ProcessingInstruction)): + continue + if isinstance(token, NavigableString): + if not open_pTag: + pTag = result.new_tag('p') + open_pTag = True + ptc = 0 + pTag.insert(ptc, token) + ptc += 1 + elif token.name in inline_tags: + if not open_pTag: + pTag = result.new_tag('p') + open_pTag = True + ptc = 0 + pTag.insert(ptc, token) + ptc += 1 + else: + if open_pTag: + container.insert(rtc, pTag) + rtc += 1 + open_pTag = False + ptc = 0 + container.insert(rtc, token) + rtc += 1 + + if open_pTag: + container.insert(rtc, pTag) + + for p in container.findAll('p'): + p['class'] = 'description' + + return container.decode_contents() + + +def markdown(val): + try: + md = markdown.Markdown + except AttributeError: + from calibre.ebooks.markdown import Markdown + md = markdown.Markdown = Markdown() + return md.convert(val) + + +def merge_comments(one, two): + return comments_to_html(one) + '\n\n' + comments_to_html(two) + + +def sanitize_comments_html(html): + from calibre.ebooks.markdown import Markdown + text = html2text(html) + md = Markdown() + html = md.convert(text) + return html + + +def find_tests(): + import unittest + + class Test(unittest.TestCase): + + def test_comments_to_html(self): + for pat, val in [ + (b'lineone\n\nlinetwo', + '

lineone

\n

linetwo

'), + + ('a b&c\nf', + '

a b&c
f

'), + + ('a b\n\ncd', + '

a b

cd

'), + ]: + cval = comments_to_html(pat) + self.assertEqual(cval, val) + + return unittest.defaultTestLoader.loadTestsFromTestCase(Test) diff --git a/ebook_converter/library/field_metadata.py b/ebook_converter/library/field_metadata.py new file mode 100644 index 0000000..5e385b9 --- /dev/null +++ b/ebook_converter/library/field_metadata.py @@ -0,0 +1,702 @@ +from __future__ import absolute_import, division, print_function, unicode_literals + +''' +Created on 25 May 2010 + +@author: charles +''' + +import traceback +from collections import OrderedDict + +from calibre.utils.config_base import tweaks +from polyglot.builtins import iteritems, itervalues + +category_icon_map = { + 'authors' : 'user_profile.png', + 'series' : 'series.png', + 'formats' : 'book.png', + 'publisher' : 'publisher.png', + 'rating' : 'rating.png', + 'news' : 'news.png', + 'tags' : 'tags.png', + 'custom:' : 'column.png', + 'user:' : 'tb_folder.png', + 'search' : 'search.png', + 'identifiers': 'identifiers.png', + 'gst' : 'catalog.png', + 'languages' : 'languages.png', + } + +# Builtin metadata {{{ + + +def _builtin_field_metadata(): + # This is a function so that changing the UI language allows newly created + # field metadata objects to have correctly translated labels for builtin + # fields. + return [ + ('authors', {'table':'authors', + 'column':'name', + 'link_column':'author', + 'category_sort':'sort', + 'datatype':'text', + 'is_multiple':{'cache_to_list': ',', + 'ui_to_list': '&', + 'list_to_ui': ' & '}, + 'kind':'field', + 'name':_('Authors'), + 'search_terms':['authors', 'author'], + 'is_custom':False, + 'is_category':True, + 'is_csp': False}), + ('languages', {'table':'languages', + 'column':'lang_code', + 'link_column':'lang_code', + 'category_sort':'lang_code', + 'datatype':'text', + 'is_multiple':{'cache_to_list': ',', + 'ui_to_list': ',', + 'list_to_ui': ', '}, + 'kind':'field', + 'name':_('Languages'), + 'search_terms':['languages', 'language'], + 'is_custom':False, + 'is_category':True, + 'is_csp': False}), + + ('series', {'table':'series', + 'column':'name', + 'link_column':'series', + 'category_sort':'(title_sort(name))', + 'datatype':'series', + 'is_multiple':{}, + 'kind':'field', + 'name':ngettext('Series', 'Series', 1), + 'search_terms':['series'], + 'is_custom':False, + 'is_category':True, + 'is_csp': False}), + ('formats', {'table':None, + 'column':None, + 'datatype':'text', + 'is_multiple':{'cache_to_list': ',', + 'ui_to_list': ',', + 'list_to_ui': ', '}, + 'kind':'field', + 'name':_('Formats'), + 'search_terms':['formats', 'format'], + 'is_custom':False, + 'is_category':True, + 'is_csp': False}), + ('publisher', {'table':'publishers', + 'column':'name', + 'link_column':'publisher', + 'category_sort':'name', + 'datatype':'text', + 'is_multiple':{}, + 'kind':'field', + 'name':_('Publisher'), + 'search_terms':['publisher'], + 'is_custom':False, + 'is_category':True, + 'is_csp': False}), + ('rating', {'table':'ratings', + 'column':'rating', + 'link_column':'rating', + 'category_sort':'rating', + 'datatype':'rating', + 'is_multiple':{}, + 'kind':'field', + 'name':_('Rating'), + 'search_terms':['rating'], + 'is_custom':False, + 'is_category':True, + 'is_csp': False}), + ('news', {'table':'news', + 'column':'name', + 'category_sort':'name', + 'datatype':None, + 'is_multiple':{}, + 'kind':'category', + 'name':_('News'), + 'search_terms':[], + 'is_custom':False, + 'is_category':True, + 'is_csp': False}), + ('tags', {'table':'tags', + 'column':'name', + 'link_column': 'tag', + 'category_sort':'name', + 'datatype':'text', + 'is_multiple':{'cache_to_list': ',', + 'ui_to_list': ',', + 'list_to_ui': ', '}, + 'kind':'field', + 'name':_('Tags'), + 'search_terms':['tags', 'tag'], + 'is_custom':False, + 'is_category':True, + 'is_csp': False}), + ('identifiers', {'table':None, + 'column':None, + 'datatype':'text', + 'is_multiple':{'cache_to_list': ',', + 'ui_to_list': ',', + 'list_to_ui': ', '}, + 'kind':'field', + 'name':_('Identifiers'), + 'search_terms':['identifiers', 'identifier', 'isbn'], + 'is_custom':False, + 'is_category':True, + 'is_csp': True}), + ('author_sort',{'table':None, + 'column':None, + 'datatype':'text', + 'is_multiple':{}, + 'kind':'field', + 'name':_('Author sort'), + 'search_terms':['author_sort'], + 'is_custom':False, + 'is_category':False, + 'is_csp': False}), + ('au_map', {'table':None, + 'column':None, + 'datatype':'text', + 'is_multiple':{'cache_to_list': ',', + 'ui_to_list': None, + 'list_to_ui': None}, + 'kind':'field', + 'name':None, + 'search_terms':[], + 'is_custom':False, + 'is_category':False, + 'is_csp': False}), + ('comments', {'table':None, + 'column':None, + 'datatype':'text', + 'is_multiple':{}, + 'kind':'field', + 'name':_('Comments'), + 'search_terms':['comments', 'comment'], + 'is_custom':False, + 'is_category':False, + 'is_csp': False}), + ('cover', {'table':None, + 'column':None, + 'datatype':'int', + 'is_multiple':{}, + 'kind':'field', + 'name':_('Cover'), + 'search_terms':['cover'], + 'is_custom':False, + 'is_category':False, + 'is_csp': False}), + ('id', {'table':None, + 'column':None, + 'datatype':'int', + 'is_multiple':{}, + 'kind':'field', + 'name':None, + 'search_terms':['id'], + 'is_custom':False, + 'is_category':False, + 'is_csp': False}), + ('last_modified', {'table':None, + 'column':None, + 'datatype':'datetime', + 'is_multiple':{}, + 'kind':'field', + 'name':_('Modified'), + 'search_terms':['last_modified'], + 'is_custom':False, + 'is_category':False, + 'is_csp': False}), + ('ondevice', {'table':None, + 'column':None, + 'datatype':'text', + 'is_multiple':{}, + 'kind':'field', + 'name':_('On device'), + 'search_terms':['ondevice'], + 'is_custom':False, + 'is_category':False, + 'is_csp': False}), + ('path', {'table':None, + 'column':None, + 'datatype':'text', + 'is_multiple':{}, + 'kind':'field', + 'name':_('Path'), + 'search_terms':[], + 'is_custom':False, + 'is_category':False, + 'is_csp': False}), + ('pubdate', {'table':None, + 'column':None, + 'datatype':'datetime', + 'is_multiple':{}, + 'kind':'field', + 'name':_('Published'), + 'search_terms':['pubdate'], + 'is_custom':False, + 'is_category':False, + 'is_csp': False}), + ('marked', {'table':None, + 'column':None, + 'datatype':'text', + 'is_multiple':{}, + 'kind':'field', + 'name': None, + 'search_terms':['marked'], + 'is_custom':False, + 'is_category':False, + 'is_csp': False}), + ('series_index',{'table':None, + 'column':None, + 'datatype':'float', + 'is_multiple':{}, + 'kind':'field', + 'name':None, + 'search_terms':['series_index'], + 'is_custom':False, + 'is_category':False, + 'is_csp': False}), + ('series_sort', {'table':None, + 'column':None, + 'datatype':'text', + 'is_multiple':{}, + 'kind':'field', + 'name':_('Series sort'), + 'search_terms':['series_sort'], + 'is_custom':False, + 'is_category':False, + 'is_csp': False}), + ('sort', {'table':None, + 'column':None, + 'datatype':'text', + 'is_multiple':{}, + 'kind':'field', + 'name':_('Title sort'), + 'search_terms':['title_sort'], + 'is_custom':False, + 'is_category':False, + 'is_csp': False}), + ('size', {'table':None, + 'column':None, + 'datatype':'float', + 'is_multiple':{}, + 'kind':'field', + 'name':_('Size'), + 'search_terms':['size'], + 'is_custom':False, + 'is_category':False, + 'is_csp': False}), + ('timestamp', {'table':None, + 'column':None, + 'datatype':'datetime', + 'is_multiple':{}, + 'kind':'field', + 'name':_('Date'), + 'search_terms':['date'], + 'is_custom':False, + 'is_category':False, + 'is_csp': False}), + ('title', {'table':None, + 'column':None, + 'datatype':'text', + 'is_multiple':{}, + 'kind':'field', + 'name':_('Title'), + 'search_terms':['title'], + 'is_custom':False, + 'is_category':False, + 'is_csp': False}), + ('uuid', {'table':None, + 'column':None, + 'datatype':'text', + 'is_multiple':{}, + 'kind':'field', + 'name':None, + 'search_terms':['uuid'], + 'is_custom':False, + 'is_category':False, + 'is_csp': False}), + ] +# }}} + + +class FieldMetadata(object): + ''' + key: the key to the dictionary is: + - for standard fields, the metadata field name. + - for custom fields, the metadata field name prefixed by '#' + This is done to create two 'namespaces' so the names don't clash + + label: the actual column label. No prefixing. + + datatype: the type of information in the field. Valid values are listed in + VALID_DATA_TYPES below. + is_multiple: valid for the text datatype. If {}, the field is to be + treated as a single term. If not None, it contains a dict of the form + {'cache_to_list': ',', + 'ui_to_list': ',', + 'list_to_ui': ', '} + where the cache_to_list contains the character used to split the value in + the meta2 table, ui_to_list contains the character used to create a list + from a value shown in the ui (each resulting value must be strip()ed and + empty values removed), and list_to_ui contains the string used in join() + to create a displayable string from the list. + + kind == field: is a db field. + kind == category: standard tag category that isn't a field. see news. + kind == user: user-defined tag category. + kind == search: saved-searches category. + + is_category: is a tag browser category. If true, then: + table: name of the db table used to construct item list + column: name of the column in the normalized table to join on + link_column: name of the column in the connection table to join on. This + key should not be present if there is no link table + category_sort: the field in the normalized table to sort on. This + key must be present if is_category is True + If these are None, then the category constructor must know how + to build the item list (e.g., formats, news). + The order below is the order that the categories will + appear in the tags pane. + + name: the text that is to be used when displaying the field. Column headings + in the GUI, etc. + + search_terms: the terms that can be used to identify the field when + searching. They can be thought of as aliases for metadata keys, but are only + valid when passed to search(). + + is_custom: the field has been added by the user. + + rec_index: the index of the field in the db metadata record. + + is_csp: field contains colon-separated pairs. Must also be text, is_multiple + + ''' + + VALID_DATA_TYPES = frozenset([None, 'rating', 'text', 'comments', 'datetime', + 'int', 'float', 'bool', 'series', 'composite', 'enumeration']) + + # search labels that are not db columns + search_items = ['all', 'search', 'vl'] + __calibre_serializable__ = True + + def __init__(self): + self._field_metadata = _builtin_field_metadata() + self._tb_cats = OrderedDict() + self._tb_custom_fields = {} + self._search_term_map = {} + self.custom_label_to_key_map = {} + for k,v in self._field_metadata: + if v['kind'] == 'field' and v['datatype'] not in self.VALID_DATA_TYPES: + raise ValueError('Unknown datatype %s for field %s'%(v['datatype'], k)) + self._tb_cats[k] = v + self._tb_cats[k]['label'] = k + self._tb_cats[k]['display'] = {} + self._tb_cats[k]['is_editable'] = True + self._add_search_terms_to_map(k, v['search_terms']) + self._tb_cats['timestamp']['display'] = { + 'date_format': tweaks['gui_timestamp_display_format']} + self._tb_cats['pubdate']['display'] = { + 'date_format': tweaks['gui_pubdate_display_format']} + self._tb_cats['last_modified']['display'] = { + 'date_format': tweaks['gui_last_modified_display_format']} + self.custom_field_prefix = '#' + self.get = self._tb_cats.get + + def __getitem__(self, key): + if key == 'title_sort': + return self._tb_cats['sort'] + return self._tb_cats[key] + + def __setitem__(self, key, val): + raise AttributeError('Assigning to this object is forbidden') + + def __delitem__(self, key): + del self._tb_cats[key] + + def __iter__(self): + for key in self._tb_cats: + yield key + + def __contains__(self, key): + return key in self._tb_cats or key == 'title_sort' + + def has_key(self, key): + return key in self + + def keys(self): + return list(self._tb_cats.keys()) + + def __eq__(self, other): + if not isinstance(other, FieldMetadata): + return False + for attr in ('_tb_custom_fields', '_search_term_map', 'custom_label_to_key_map', 'custom_field_prefix'): + if getattr(self, attr) != getattr(other, attr): + return False + return dict(self._tb_cats) == dict(other._tb_cats) + + def __ne__(self, other): + return not self.__eq__(other) + + def sortable_field_keys(self): + return [k for k in self._tb_cats.keys() + if self._tb_cats[k]['kind']=='field' and + self._tb_cats[k]['datatype'] is not None] + + def ui_sortable_field_keys(self): + ans = {k:self._tb_cats[k]['name'] for k in set(self.sortable_field_keys()) - { + 'sort', 'author_sort', 'au_map', 'series_sort', 'marked', + 'series_index', 'path', 'formats', 'identifiers', 'uuid', + 'comments', + } if self._tb_cats[k]['name']} + ans['cover'] = _('Has cover') + return ans + + def displayable_field_keys(self): + return [k for k in self._tb_cats.keys() + if self._tb_cats[k]['kind']=='field' and + self._tb_cats[k]['datatype'] is not None and + k not in ('au_map', 'marked', 'ondevice', 'cover', 'series_sort') and + not self.is_series_index(k)] + + def standard_field_keys(self): + return [k for k in self._tb_cats.keys() + if self._tb_cats[k]['kind']=='field' and + not self._tb_cats[k]['is_custom']] + + def custom_field_keys(self, include_composites=True): + res = [] + for k in self._tb_cats.keys(): + fm = self._tb_cats[k] + if fm['kind']=='field' and fm['is_custom'] and \ + (fm['datatype'] != 'composite' or include_composites): + res.append(k) + return res + + def all_field_keys(self): + return [k for k in self._tb_cats.keys() if self._tb_cats[k]['kind']=='field'] + + def iterkeys(self): + for key in self._tb_cats: + yield key + + def itervalues(self): + return itervalues(self._tb_cats) + + def values(self): + return list(self._tb_cats.values()) + + def iteritems(self): + for key in self._tb_cats: + yield (key, self._tb_cats[key]) + iter_items = iteritems + + def custom_iteritems(self): + for key, meta in iteritems(self._tb_custom_fields): + yield (key, meta) + + def items(self): + return list(self.iter_items()) + + def is_custom_field(self, key): + return key.startswith(self.custom_field_prefix) + + def is_ignorable_field(self, key): + 'Custom fields and user categories are ignorable' + return self.is_custom_field(key) or key.startswith('@') + + def ignorable_field_keys(self): + return [k for k in self._tb_cats if self.is_ignorable_field(k)] + + def is_series_index(self, key): + try: + m = self._tb_cats[key] + return (m['datatype'] == 'float' and key.endswith('_index') and + key[:-6] in self._tb_cats) + except (KeyError, ValueError, TypeError, AttributeError): + return False + + def key_to_label(self, key): + if 'label' not in self._tb_cats[key]: + return key + return self._tb_cats[key]['label'] + + def label_to_key(self, label, prefer_custom=False): + if prefer_custom: + if label in self.custom_label_to_key_map: + return self.custom_label_to_key_map[label] + if 'label' in self._tb_cats: + return label + if not prefer_custom: + if label in self.custom_label_to_key_map: + return self.custom_label_to_key_map[label] + raise ValueError('Unknown key [%s]'%(label)) + + def all_metadata(self): + l = {} + for k in self._tb_cats: + l[k] = self._tb_cats[k] + return l + + def custom_field_metadata(self, include_composites=True): + if include_composites: + return self._tb_custom_fields + l = {} + for k in self.custom_field_keys(include_composites): + l[k] = self._tb_cats[k] + return l + + def add_custom_field(self, label, table, column, datatype, colnum, name, + display, is_editable, is_multiple, is_category, + is_csp=False): + key = self.custom_field_prefix + label + if key in self._tb_cats: + raise ValueError('Duplicate custom field [%s]'%(label)) + if datatype not in self.VALID_DATA_TYPES: + raise ValueError('Unknown datatype %s for field %s'%(datatype, key)) + self._tb_cats[key] = {'table':table, 'column':column, + 'datatype':datatype, 'is_multiple':is_multiple, + 'kind':'field', 'name':name, + 'search_terms':[key], 'label':label, + 'colnum':colnum, 'display':display, + 'is_custom':True, 'is_category':is_category, + 'link_column':'value','category_sort':'value', + 'is_csp' : is_csp, 'is_editable': is_editable,} + self._tb_custom_fields[key] = self._tb_cats[key] + self._add_search_terms_to_map(key, [key]) + self.custom_label_to_key_map[label] = key + if datatype == 'series': + key += '_index' + self._tb_cats[key] = {'table':None, 'column':None, + 'datatype':'float', 'is_multiple':{}, + 'kind':'field', 'name':'', + 'search_terms':[key], 'label':label+'_index', + 'colnum':None, 'display':{}, + 'is_custom':False, 'is_category':False, + 'link_column':None, 'category_sort':None, + 'is_editable': False, 'is_csp': False} + self._add_search_terms_to_map(key, [key]) + self.custom_label_to_key_map[label+'_index'] = key + + def remove_dynamic_categories(self): + for key in list(self._tb_cats.keys()): + val = self._tb_cats[key] + if val['is_category'] and val['kind'] in ('user', 'search'): + for k in self._tb_cats[key]['search_terms']: + if k in self._search_term_map: + del self._search_term_map[k] + del self._tb_cats[key] + + def remove_user_categories(self): + for key in list(self._tb_cats.keys()): + val = self._tb_cats[key] + if val['is_category'] and val['kind'] == 'user': + for k in self._tb_cats[key]['search_terms']: + if k in self._search_term_map: + del self._search_term_map[k] + del self._tb_cats[key] + + def _remove_grouped_search_terms(self): + to_remove = [v for v in self._search_term_map + if isinstance(self._search_term_map[v], list)] + for v in to_remove: + del self._search_term_map[v] + + def add_grouped_search_terms(self, gst): + self._remove_grouped_search_terms() + for t in gst: + try: + self._add_search_terms_to_map(gst[t], [t]) + except ValueError: + traceback.print_exc() + + def cc_series_index_column_for(self, key): + return self._tb_cats[key]['rec_index'] + 1 + + def add_user_category(self, label, name): + if label in self._tb_cats: + raise ValueError('Duplicate user field [%s]'%(label)) + st = [label] + if icu_lower(label) != label: + st.append(icu_lower(label)) + self._tb_cats[label] = {'table':None, 'column':None, + 'datatype':None, 'is_multiple':{}, + 'kind':'user', 'name':name, + 'search_terms':st, 'is_custom':False, + 'is_category':True, 'is_csp': False} + self._add_search_terms_to_map(label, st) + + def add_search_category(self, label, name, fail_on_existing=True): + if label in self._tb_cats: + if not fail_on_existing: + return + raise ValueError('Duplicate user field [%s]'%(label)) + self._tb_cats[label] = {'table':None, 'column':None, + 'datatype':None, 'is_multiple':{}, + 'kind':'search', 'name':name, + 'search_terms':[], 'is_custom':False, + 'is_category':True, 'is_csp': False} + + def set_field_record_index(self, label, index, prefer_custom=False): + if prefer_custom: + key = self.custom_field_prefix+label + if key not in self._tb_cats: + key = label + else: + if label in self._tb_cats: + key = label + else: + key = self.custom_field_prefix+label + self._tb_cats[key]['rec_index'] = index # let the exception fly ... + + def get_search_terms(self): + s_keys = sorted(self._search_term_map.keys()) + for v in self.search_items: + s_keys.append(v) + return s_keys + + def _add_search_terms_to_map(self, key, terms): + if terms is not None: + for t in terms: + if t in self._search_term_map: + raise ValueError('Attempt to add duplicate search term "%s"'%t) + self._search_term_map[t] = key + + def search_term_to_field_key(self, term): + return self._search_term_map.get(term, term) + + def searchable_fields(self): + return [k for k in self._tb_cats.keys() + if self._tb_cats[k]['kind']=='field' and + len(self._tb_cats[k]['search_terms']) > 0] + + +# The following two methods are to support serialization +# Note that they do not create copies of internal structures, for performance, +# so they are not safe to use for anything else +def fm_as_dict(self): + return { + 'custom_fields': self._tb_custom_fields, + 'search_term_map': self._search_term_map, + 'custom_label_to_key_map': self.custom_label_to_key_map, + 'user_categories': {k:v for k, v in iteritems(self._tb_cats) if v['kind'] == 'user'}, + 'search_categories': {k:v for k, v in iteritems(self._tb_cats) if v['kind'] == 'search'}, + } + + +def fm_from_dict(src): + ans = FieldMetadata() + ans._tb_custom_fields = src['custom_fields'] + ans._search_term_map = src['search_term_map'] + ans.custom_label_to_key_map = src['custom_label_to_key_map'] + for q in ('custom_fields', 'user_categories', 'search_categories'): + for k, v in iteritems(src[q]): + ans._tb_cats[k] = v + return ans diff --git a/ebook_converter/polyglot/__init__.py b/ebook_converter/polyglot/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ebook_converter/polyglot/binary.py b/ebook_converter/polyglot/binary.py new file mode 100644 index 0000000..360ac0b --- /dev/null +++ b/ebook_converter/polyglot/binary.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +# License: GPL v3 Copyright: 2019, Kovid Goyal + +from __future__ import absolute_import, division, print_function, unicode_literals + +from base64 import standard_b64decode, standard_b64encode +from binascii import hexlify, unhexlify + +from polyglot.builtins import unicode_type + + +def as_base64_bytes(x, enc='utf-8'): + if isinstance(x, unicode_type): + x = x.encode(enc) + return standard_b64encode(x) + + +def as_base64_unicode(x, enc='utf-8'): + if isinstance(x, unicode_type): + x = x.encode(enc) + return standard_b64encode(x).decode('ascii') + + +def from_base64_unicode(x, enc='utf-8'): + if isinstance(x, unicode_type): + x = x.encode('ascii') + return standard_b64decode(x).decode(enc) + + +def from_base64_bytes(x): + if isinstance(x, unicode_type): + x = x.encode('ascii') + return standard_b64decode(x) + + +def as_hex_bytes(x, enc='utf-8'): + if isinstance(x, unicode_type): + x = x.encode(enc) + return hexlify(x) + + +def as_hex_unicode(x, enc='utf-8'): + if isinstance(x, unicode_type): + x = x.encode(enc) + return hexlify(x).decode('ascii') + + +def from_hex_unicode(x, enc='utf-8'): + if isinstance(x, unicode_type): + x = x.encode('ascii') + return unhexlify(x).decode(enc) + + +def from_hex_bytes(x): + if isinstance(x, unicode_type): + x = x.encode('ascii') + return unhexlify(x) diff --git a/ebook_converter/polyglot/builtins.py b/ebook_converter/polyglot/builtins.py new file mode 100644 index 0000000..cb78f7f --- /dev/null +++ b/ebook_converter/polyglot/builtins.py @@ -0,0 +1,202 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +# License: GPL v3 Copyright: 2018, Kovid Goyal + +from __future__ import absolute_import, division, print_function, unicode_literals + +import os +import sys + +is_py3 = sys.version_info.major >= 3 +native_string_type = str +iterkeys = iter + + +def hasenv(x): + return getenv(x) is not None + + +def as_bytes(x, encoding='utf-8'): + if isinstance(x, unicode_type): + return x.encode(encoding) + if isinstance(x, bytes): + return x + if isinstance(x, bytearray): + return bytes(x) + if isinstance(x, memoryview): + return x.tobytes() + ans = unicode_type(x) + if isinstance(ans, unicode_type): + ans = ans.encode(encoding) + return ans + + +def as_unicode(x, encoding='utf-8', errors='strict'): + if isinstance(x, bytes): + return x.decode(encoding, errors) + return unicode_type(x) + + +def only_unicode_recursive(x, encoding='utf-8', errors='strict'): + # Convert any bytestrings in sets/lists/tuples/dicts to unicode + if isinstance(x, bytes): + return x.decode(encoding, errors) + if isinstance(x, unicode_type): + return x + if isinstance(x, (set, list, tuple, frozenset)): + return type(x)(only_unicode_recursive(i, encoding, errors) for i in x) + if isinstance(x, dict): + return {only_unicode_recursive(k, encoding, errors): only_unicode_recursive(v, encoding, errors) for k, v in iteritems(x)} + return x + + +if is_py3: + def reraise(tp, value, tb=None): + try: + if value is None: + value = tp() + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + finally: + value = None + tb = None + + import builtins + + zip = builtins.zip + map = builtins.map + filter = builtins.filter + range = builtins.range + + codepoint_to_chr = chr + unicode_type = str + string_or_bytes = str, bytes + string_or_unicode = str + long_type = int + raw_input = input + getcwd = os.getcwd + getenv = os.getenv + + def error_message(exc): + args = getattr(exc, 'args', None) + if args and isinstance(args[0], unicode_type): + return args[0] + return unicode_type(exc) + + def iteritems(d): + return iter(d.items()) + + def itervalues(d): + return iter(d.values()) + + def environ_item(x): + if isinstance(x, bytes): + x = x.decode('utf-8') + return x + + def exec_path(path, ctx=None): + ctx = ctx or {} + with open(path, 'rb') as f: + code = f.read() + code = compile(code, f.name, 'exec') + exec(code, ctx) + + def cmp(a, b): + return (a > b) - (a < b) + + def int_to_byte(x): + return bytes((x,)) + + def reload(module): + import importlib + return importlib.reload(module) + +else: + exec("""def reraise(tp, value, tb=None): + try: + raise tp, value, tb + finally: + tb = None +""") + + from future_builtins import zip, map, filter # noqa + range = xrange + import __builtin__ as builtins + + codepoint_to_chr = unichr + unicode_type = unicode + string_or_bytes = unicode, bytes + string_or_unicode = str, unicode + long_type = long + exec_path = execfile + raw_input = builtins.raw_input + cmp = builtins.cmp + int_to_byte = chr + getcwd = os.getcwdu + + def error_message(exc): + ans = exc.message + if isinstance(ans, bytes): + ans = ans.decode('utf-8', 'replace') + return ans + + def iteritems(d): + return d.iteritems() + + def itervalues(d): + return d.itervalues() + + def environ_item(x): + if isinstance(x, unicode_type): + x = x.encode('utf-8') + return x + + if hasattr(sys, 'getwindowsversion'): + def getenv(x, default=None): + if isinstance(x, bytes): + x = x.decode('mbcs', 'replace') + + if getenv.buf is None: + import ctypes + import ctypes.wintypes as w + getenv.cub = ctypes.create_unicode_buffer + getenv.buf = getenv.cub(1024) + getenv.gev = ctypes.windll.kernel32.GetEnvironmentVariableW + getenv.gev.restype = w.DWORD + getenv.gev.argtypes = [w.LPCWSTR, w.LPWSTR, w.DWORD] + res = getenv.gev(x, getenv.buf, len(getenv.buf)) + if res == 0: + return default + if res > len(getenv.buf) - 4: + getenv.buf = getenv.cub(res + 8) + res = getenv.gev(x, getenv.buf, len(getenv.buf)) + if res == 0: + return default + return getenv.buf.value + getenv.buf = None + else: + def getenv(x, default=None): + ans = os.getenv(x, default) + if isinstance(ans, bytes): + ans = ans.decode('utf-8', 'replace') + return ans + + def reload(module): + return builtins.reload(module) + + +def print_to_binary_file(fileobj, encoding='utf-8'): + + def print(*a, **kw): + f = kw.get('file', fileobj) + if a: + sep = as_bytes(kw.get('sep', ' '), encoding) + for x in a: + x = as_bytes(x, encoding) + f.write(x) + if x is not a[-1]: + f.write(sep) + f.write(as_bytes(kw.get('end', '\n'))) + + return print diff --git a/ebook_converter/polyglot/functools.py b/ebook_converter/polyglot/functools.py new file mode 100644 index 0000000..f0cdf08 --- /dev/null +++ b/ebook_converter/polyglot/functools.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +# License: GPL v3 Copyright: 2019, Kovid Goyal + +from __future__ import absolute_import, division, print_function, unicode_literals + +from polyglot.builtins import is_py3 +if is_py3: + from functools import lru_cache +else: + from backports.functools_lru_cache import lru_cache + +lru_cache diff --git a/ebook_converter/polyglot/html_entities.py b/ebook_converter/polyglot/html_entities.py new file mode 100644 index 0000000..2e20eee --- /dev/null +++ b/ebook_converter/polyglot/html_entities.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +# License: GPL v3 Copyright: 2019, Eli Schwartz + +from polyglot.builtins import is_py3 + +if is_py3: + from html.entities import name2codepoint +else: + from htmlentitydefs import name2codepoint diff --git a/ebook_converter/polyglot/urllib.py b/ebook_converter/polyglot/urllib.py new file mode 100644 index 0000000..1d30c99 --- /dev/null +++ b/ebook_converter/polyglot/urllib.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +# License: GPL v3 Copyright: 2018, Kovid Goyal + +from __future__ import absolute_import + +from polyglot.builtins import is_py3 + +if is_py3: + from urllib.request import (build_opener, getproxies, install_opener, # noqa + HTTPBasicAuthHandler, HTTPCookieProcessor, HTTPDigestAuthHandler, # noqa + url2pathname, urlopen, Request) # noqa + from urllib.parse import (parse_qs, quote, unquote as uq, quote_plus, urldefrag, # noqa + urlencode, urljoin, urlparse, urlunparse, urlsplit, urlunsplit) # noqa + from urllib.error import HTTPError, URLError # noqa + + def unquote(x, encoding='utf-8', errors='replace'): + binary = isinstance(x, bytes) + if binary: + x = x.decode(encoding, errors) + ans = uq(x, encoding, errors) + if binary: + ans = ans.encode(encoding, errors) + return ans + +else: + from urllib import (getproxies, quote, unquote as uq, quote_plus, url2pathname, # noqa + urlencode) # noqa + from urllib2 import (build_opener, install_opener, HTTPBasicAuthHandler, # noqa + HTTPCookieProcessor, HTTPDigestAuthHandler, HTTPError, URLError, # noqa + urlopen, Request) # noqa + from urlparse import (parse_qs, urldefrag, urljoin, urlparse, urlunparse, # noqa + urlsplit, urlunsplit) # noqa + + def unquote(x, encoding='utf-8', errors='replace'): + # unquote must run on a bytestring and will return a bytestring + # If it runs on a unicode object, it returns a double encoded unicode + # string: unquote(u'%C3%A4') != unquote(b'%C3%A4').decode('utf-8') + # and the latter is correct + binary = isinstance(x, bytes) + if not binary: + x = x.encode(encoding, errors) + ans = uq(x) + if not binary: + ans = ans.decode(encoding, errors) + return ans + + +def unquote_plus(x, encoding='utf-8', errors='replace'): + q, repl = (b'+', b' ') if isinstance(x, bytes) else ('+', ' ') + x = x.replace(q, repl) + return unquote(x, encoding=encoding, errors=errors) diff --git a/ebook_converter/ptempfile.py b/ebook_converter/ptempfile.py new file mode 100644 index 0000000..9d9bf81 --- /dev/null +++ b/ebook_converter/ptempfile.py @@ -0,0 +1,295 @@ +from __future__ import absolute_import, division, print_function, unicode_literals +__license__ = 'GPL v3' +__copyright__ = '2008, Kovid Goyal ' +""" +Provides platform independent temporary files that persist even after +being closed. +""" +import tempfile, os, atexit +from polyglot.builtins import map, getenv + +from calibre.constants import (__version__, __appname__, filesystem_encoding, + iswindows, get_windows_temp_path, isosx, ispy3) + + +def cleanup(path): + try: + import os as oss + if oss.path.exists(path): + oss.remove(path) + except: + pass + + +_base_dir = None + + +def remove_dir(x): + try: + import shutil + shutil.rmtree(x, ignore_errors=True) + except: + pass + + +def determined_remove_dir(x): + for i in range(10): + try: + import shutil + shutil.rmtree(x) + return + except: + import os # noqa + if os.path.exists(x): + # In case some other program has one of the temp files open. + import time + time.sleep(0.1) + else: + return + try: + import shutil + shutil.rmtree(x, ignore_errors=True) + except: + pass + + +def app_prefix(prefix): + if iswindows: + return '%s_'%__appname__ + return '%s_%s_%s'%(__appname__, __version__, prefix) + + +_osx_cache_dir = None + + +def osx_cache_dir(): + global _osx_cache_dir + if _osx_cache_dir: + return _osx_cache_dir + if _osx_cache_dir is None: + _osx_cache_dir = False + import ctypes + libc = ctypes.CDLL(None) + buf = ctypes.create_string_buffer(512) + l = libc.confstr(65538, ctypes.byref(buf), len(buf)) # _CS_DARWIN_USER_CACHE_DIR = 65538 + if 0 < l < len(buf): + try: + q = buf.value.decode('utf-8').rstrip('\0') + except ValueError: + pass + if q and os.path.isdir(q) and os.access(q, os.R_OK | os.W_OK | os.X_OK): + _osx_cache_dir = q + return q + + +def base_dir(): + global _base_dir + if _base_dir is not None and not os.path.exists(_base_dir): + # Some people seem to think that running temp file cleaners that + # delete the temp dirs of running programs is a good idea! + _base_dir = None + if _base_dir is None: + td = os.environ.get('CALIBRE_WORKER_TEMP_DIR', None) + if td is not None: + from calibre.utils.serialize import msgpack_loads + from polyglot.binary import from_hex_bytes + try: + td = msgpack_loads(from_hex_bytes(td)) + except Exception: + td = None + if td and os.path.exists(td): + _base_dir = td + else: + base = os.environ.get('CALIBRE_TEMP_DIR', None) + if base is not None and iswindows: + base = getenv('CALIBRE_TEMP_DIR') + prefix = app_prefix('tmp_') + if base is None: + if iswindows: + # On windows, if the TMP env var points to a path that + # cannot be encoded using the mbcs encoding, then the + # python 2 tempfile algorithm for getting the temporary + # directory breaks. So we use the win32 api to get a + # unicode temp path instead. See + # https://bugs.launchpad.net/bugs/937389 + base = get_windows_temp_path() + elif isosx: + # Use the cache dir rather than the temp dir for temp files as Apple + # thinks deleting unused temp files is a good idea. See note under + # _CS_DARWIN_USER_TEMP_DIR here + # https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/confstr.3.html + base = osx_cache_dir() + + _base_dir = tempfile.mkdtemp(prefix=prefix, dir=base) + atexit.register(determined_remove_dir if iswindows else remove_dir, _base_dir) + + try: + tempfile.gettempdir() + except: + # Widows temp vars set to a path not encodable in mbcs + # Use our temp dir + tempfile.tempdir = _base_dir + + return _base_dir + + +def reset_base_dir(): + global _base_dir + _base_dir = None + base_dir() + + +def force_unicode(x): + # Cannot use the implementation in calibre.__init__ as it causes a circular + # dependency + if isinstance(x, bytes): + x = x.decode(filesystem_encoding) + return x + + +def _make_file(suffix, prefix, base): + suffix, prefix = map(force_unicode, (suffix, prefix)) # no2to3 + return tempfile.mkstemp(suffix, prefix, dir=base) + + +def _make_dir(suffix, prefix, base): + suffix, prefix = map(force_unicode, (suffix, prefix)) # no2to3 + return tempfile.mkdtemp(suffix, prefix, base) + + +class PersistentTemporaryFile(object): + + """ + A file-like object that is a temporary file that is available even after being closed on + all platforms. It is automatically deleted on normal program termination. + """ + _file = None + + def __init__(self, suffix="", prefix="", dir=None, mode='w+b'): + if prefix is None: + prefix = "" + if dir is None: + dir = base_dir() + fd, name = _make_file(suffix, prefix, dir) + + self._file = os.fdopen(fd, mode) + self._name = name + self._fd = fd + atexit.register(cleanup, name) + + def __getattr__(self, name): + if name == 'name': + return self.__dict__['_name'] + return getattr(self.__dict__['_file'], name) + + def __enter__(self): + return self + + def __exit__(self, *args): + self.close() + + def __del__(self): + try: + self.close() + except: + pass + + +def PersistentTemporaryDirectory(suffix='', prefix='', dir=None): + ''' + Return the path to a newly created temporary directory that will + be automatically deleted on application exit. + ''' + if dir is None: + dir = base_dir() + tdir = _make_dir(suffix, prefix, dir) + + atexit.register(remove_dir, tdir) + return tdir + + +class TemporaryDirectory(object): + + ''' + A temporary directory to be used in a with statement. + ''' + + def __init__(self, suffix='', prefix='', dir=None, keep=False): + self.suffix = suffix + self.prefix = prefix + if dir is None: + dir = base_dir() + self.dir = dir + self.keep = keep + + def __enter__(self): + if not hasattr(self, 'tdir'): + self.tdir = _make_dir(self.suffix, self.prefix, self.dir) + return self.tdir + + def __exit__(self, *args): + if not self.keep and os.path.exists(self.tdir): + remove_dir(self.tdir) + + +class TemporaryFile(object): + + def __init__(self, suffix="", prefix="", dir=None, mode='w+b'): + if prefix is None: + prefix = '' + if suffix is None: + suffix = '' + if dir is None: + dir = base_dir() + self.prefix, self.suffix, self.dir, self.mode = prefix, suffix, dir, mode + self._file = None + + def __enter__(self): + fd, name = _make_file(self.suffix, self.prefix, self.dir) + self._file = os.fdopen(fd, self.mode) + self._name = name + self._file.close() + return name + + def __exit__(self, *args): + cleanup(self._name) + + +class SpooledTemporaryFile(tempfile.SpooledTemporaryFile): + + def __init__(self, max_size=0, suffix="", prefix="", dir=None, mode='w+b', + bufsize=-1): + if prefix is None: + prefix = '' + if suffix is None: + suffix = '' + if dir is None: + dir = base_dir() + if ispy3: + self._name = None + tempfile.SpooledTemporaryFile.__init__(self, max_size=max_size, + suffix=suffix, prefix=prefix, dir=dir, mode=mode) + else: + tempfile.SpooledTemporaryFile.__init__(self, max_size=max_size, + suffix=suffix, prefix=prefix, dir=dir, mode=mode, + bufsize=bufsize) + + if ispy3: + @property + def name(self): + return self._name + + @name.setter + def name(self, val): + self._name = val + + def truncate(self, *args): + # The stdlib SpooledTemporaryFile implementation of truncate() doesn't + # allow specifying a size. + self._file.truncate(*args) + + +def better_mktemp(*args, **kwargs): + fd, path = tempfile.mkstemp(*args, **kwargs) + os.close(fd) + return path diff --git a/ebook_converter/spell/__init__.py b/ebook_converter/spell/__init__.py new file mode 100644 index 0000000..e58ae8f --- /dev/null +++ b/ebook_converter/spell/__init__.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2014, Kovid Goyal ' + +from collections import namedtuple + +from calibre.utils.localization import canonicalize_lang + +DictionaryLocale = namedtuple('DictionaryLocale', 'langcode countrycode') + +ccodes, ccodemap, country_names = None, None, None + + +def get_codes(): + global ccodes, ccodemap, country_names + if ccodes is None: + from calibre.utils.serialize import msgpack_loads + data = msgpack_loads(P('localization/iso3166.calibre_msgpack', allow_user_override=False, data=True)) + ccodes, ccodemap, country_names = data['codes'], data['three_map'], data['names'] + return ccodes, ccodemap + + +def parse_lang_code(raw): + raw = raw or '' + parts = raw.replace('_', '-').split('-') + lc = canonicalize_lang(parts[0]) + if lc is None: + raise ValueError('Invalid language code: %r' % raw) + cc = None + if len(parts) > 1: + ccodes, ccodemap = get_codes()[:2] + q = parts[1].upper() + if q in ccodes: + cc = q + else: + cc = ccodemap.get(q, None) + return DictionaryLocale(lc, cc) diff --git a/ebook_converter/startup.py b/ebook_converter/startup.py new file mode 100644 index 0000000..7508b24 --- /dev/null +++ b/ebook_converter/startup.py @@ -0,0 +1,301 @@ +from __future__ import print_function, unicode_literals +__license__ = 'GPL v3' +__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net' +__docformat__ = 'restructuredtext en' + +''' +Perform various initialization tasks. +''' + +import locale, sys, os + +# Default translation is NOOP +from polyglot.builtins import builtins, is_py3, unicode_type +builtins.__dict__['_'] = lambda s: s + +# For strings which belong in the translation tables, but which shouldn't be +# immediately translated to the environment language +builtins.__dict__['__'] = lambda s: s + +# For backwards compat with some third party plugins +builtins.__dict__['dynamic_property'] = lambda func: func(None) + + +from calibre.constants import iswindows, preferred_encoding, plugins, isosx, islinux, isfrozen, DEBUG, isfreebsd, ispy3 + +_run_once = False +winutil = winutilerror = None + +if not _run_once: + _run_once = True + from importlib import import_module + + if not isfrozen and not ispy3: + # Prevent PyQt4 from being loaded + class PyQt4Ban(object): + + def find_module(self, fullname, path=None): + if fullname.startswith('PyQt4'): + return self + + def load_module(self, fullname): + raise ImportError('Importing PyQt4 is not allowed as calibre uses PyQt5') + + sys.meta_path.insert(0, PyQt4Ban()) + + class DeVendor(object): + + if ispy3: + + def find_spec(self, fullname, path, target=None): + spec = None + if fullname == 'calibre.web.feeds.feedparser': + m = import_module('feedparser') + spec = m.__spec__ + elif fullname.startswith('calibre.ebooks.markdown'): + m = import_module(fullname[len('calibre.ebooks.'):]) + spec = m.__spec__ + return spec + + else: + + def find_module(self, fullname, path=None): + if fullname == 'calibre.web.feeds.feedparser' or fullname.startswith('calibre.ebooks.markdown'): + return self + + def load_module(self, fullname): + if fullname == 'calibre.web.feeds.feedparser': + return import_module('feedparser') + return import_module(fullname[len('calibre.ebooks.'):]) + + sys.meta_path.insert(0, DeVendor()) + + # + # Platform specific modules + if iswindows: + winutil, winutilerror = plugins['winutil'] + if not winutil: + raise RuntimeError('Failed to load the winutil plugin: %s'%winutilerror) + if len(sys.argv) > 1 and not isinstance(sys.argv[1], unicode_type): + sys.argv[1:] = winutil.argv()[1-len(sys.argv):] + + if not ispy3: + # Python2's expanduser is broken for non-ASCII usernames + # and unicode paths + + def expanduser(path): + if isinstance(path, bytes): + path = path.decode('mbcs') + if path[:1] != '~': + return path + i, n = 1, len(path) + while i < n and path[i] not in '/\\': + i += 1 + userhome = winutil.special_folder_path(winutil.CSIDL_PROFILE) + if i != 1: # ~user + userhome = os.path.join(os.path.dirname(userhome), path[1:i]) + + return userhome + path[i:] + os.path.expanduser = expanduser + + # Ensure that all temp files/dirs are created under a calibre tmp dir + from calibre.ptempfile import base_dir + try: + base_dir() + except EnvironmentError: + pass # Ignore this error during startup, so we can show a better error message to the user later. + + # + # Convert command line arguments to unicode + enc = preferred_encoding + if isosx: + enc = 'utf-8' + for i in range(1, len(sys.argv)): + if not isinstance(sys.argv[i], unicode_type): + sys.argv[i] = sys.argv[i].decode(enc, 'replace') + + # + # Ensure that the max number of open files is at least 1024 + if iswindows: + # See https://msdn.microsoft.com/en-us/library/6e3b887c.aspx + if hasattr(winutil, 'setmaxstdio'): + winutil.setmaxstdio(max(1024, winutil.getmaxstdio())) + else: + import resource + soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE) + if soft < 1024: + try: + resource.setrlimit(resource.RLIMIT_NOFILE, (min(1024, hard), hard)) + except Exception: + if DEBUG: + import traceback + traceback.print_exc() + + # + # Setup resources + import calibre.utils.resources as resources + resources + + # + # Setup translations + from calibre.utils.localization import set_translators + + set_translators() + + # + # Initialize locale + # Import string as we do not want locale specific + # string.whitespace/printable, on windows especially, this causes problems. + # Before the delay load optimizations, string was loaded before this point + # anyway, so we preserve the old behavior explicitly. + import string + string + try: + locale.setlocale(locale.LC_ALL, '') # set the locale to the user's default locale + except: + dl = locale.getdefaultlocale() + try: + if dl: + locale.setlocale(locale.LC_ALL, dl[0]) + except: + pass + + # local_open() opens a file that wont be inherited by child processes + if is_py3: + local_open = open # PEP 446 + elif iswindows: + def local_open(name, mode='r', bufsize=-1): + mode += 'N' + return open(name, mode, bufsize) + elif isosx: + import fcntl + FIOCLEX = 0x20006601 + + def local_open(name, mode='r', bufsize=-1): + ans = open(name, mode, bufsize) + try: + fcntl.ioctl(ans.fileno(), FIOCLEX) + except EnvironmentError: + fcntl.fcntl(ans, fcntl.F_SETFD, fcntl.fcntl(ans, fcntl.F_GETFD) | fcntl.FD_CLOEXEC) + return ans + else: + import fcntl + try: + cloexec_flag = fcntl.FD_CLOEXEC + except AttributeError: + cloexec_flag = 1 + supports_mode_e = False + + def local_open(name, mode='r', bufsize=-1): + global supports_mode_e + mode += 'e' + ans = open(name, mode, bufsize) + if supports_mode_e: + return ans + old = fcntl.fcntl(ans, fcntl.F_GETFD) + if not (old & cloexec_flag): + fcntl.fcntl(ans, fcntl.F_SETFD, old | cloexec_flag) + else: + supports_mode_e = True + return ans + + builtins.__dict__['lopen'] = local_open + + from calibre.utils.icu import title_case, lower as icu_lower, upper as icu_upper + builtins.__dict__['icu_lower'] = icu_lower + builtins.__dict__['icu_upper'] = icu_upper + builtins.__dict__['icu_title'] = title_case + + def connect_lambda(bound_signal, self, func, **kw): + import weakref + r = weakref.ref(self) + del self + num_args = func.__code__.co_argcount - 1 + if num_args < 0: + raise TypeError('lambda must take at least one argument') + + def slot(*args): + ctx = r() + if ctx is not None: + if len(args) != num_args: + args = args[:num_args] + func(ctx, *args) + + bound_signal.connect(slot, **kw) + builtins.__dict__['connect_lambda'] = connect_lambda + + if islinux or isosx or isfreebsd: + # Name all threads at the OS level created using the threading module, see + # http://bugs.python.org/issue15500 + import threading + + orig_start = threading.Thread.start + + def new_start(self): + orig_start(self) + try: + name = self.name + if not name or name.startswith('Thread-'): + name = self.__class__.__name__ + if name == 'Thread': + name = self.name + if name: + if isinstance(name, unicode_type): + name = name.encode('ascii', 'replace').decode('ascii') + plugins['speedup'][0].set_thread_name(name[:15]) + except Exception: + pass # Don't care about failure to set name + threading.Thread.start = new_start + + +def test_lopen(): + from calibre.ptempfile import TemporaryDirectory + from calibre import CurrentDir + n = 'f\xe4llen' + print('testing lopen()') + + if iswindows: + import msvcrt, win32api + + def assert_not_inheritable(f): + if win32api.GetHandleInformation(msvcrt.get_osfhandle(f.fileno())) & 0b1: + raise SystemExit('File handle is inheritable!') + else: + import fcntl + + def assert_not_inheritable(f): + if not fcntl.fcntl(f, fcntl.F_GETFD) & fcntl.FD_CLOEXEC: + raise SystemExit('File handle is inheritable!') + + def copen(*args): + ans = lopen(*args) + assert_not_inheritable(ans) + return ans + + with TemporaryDirectory() as tdir, CurrentDir(tdir): + with copen(n, 'w') as f: + f.write('one') + + print('O_CREAT tested') + with copen(n, 'w+b') as f: + f.write(b'two') + with copen(n, 'r') as f: + if f.read() == 'two': + print('O_TRUNC tested') + else: + raise Exception('O_TRUNC failed') + with copen(n, 'ab') as f: + f.write(b'three') + with copen(n, 'r+') as f: + if f.read() == 'twothree': + print('O_APPEND tested') + else: + raise Exception('O_APPEND failed') + with copen(n, 'r+') as f: + f.seek(3) + f.write('xxxxx') + f.seek(0) + if f.read() == 'twoxxxxx': + print('O_RANDOM tested') + else: + raise Exception('O_RANDOM failed') diff --git a/ebook_converter/tinycss/__init__.py b/ebook_converter/tinycss/__init__.py new file mode 100644 index 0000000..73451ba --- /dev/null +++ b/ebook_converter/tinycss/__init__.py @@ -0,0 +1,52 @@ +# coding: utf8 +""" + tinycss + ------- + + A CSS parser, and nothing else. + + :copyright: (c) 2012 by Simon Sapin. + :license: BSD, see LICENSE for more details. +""" + +from .version import VERSION +__version__ = VERSION + +from tinycss.css21 import CSS21Parser +from tinycss.page3 import CSSPage3Parser +from tinycss.fonts3 import CSSFonts3Parser +from tinycss.media3 import CSSMedia3Parser + + +PARSER_MODULES = { + 'page3': CSSPage3Parser, + 'fonts3': CSSFonts3Parser, + 'media3': CSSMedia3Parser, +} + + +def make_parser(*features, **kwargs): + """Make a parser object with the chosen features. + + :param features: + Positional arguments are base classes the new parser class will extend. + The string ``'page3'`` is accepted as short for + :class:`~page3.CSSPage3Parser`. + :param kwargs: + Keyword arguments are passed to the parser’s constructor. + :returns: + An instance of a new subclass of :class:`CSS21Parser` + + """ + if features: + bases = tuple(PARSER_MODULES.get(f, f) for f in features) + parser_class = type('CustomCSSParser', bases + (CSS21Parser,), {}) + else: + parser_class = CSS21Parser + return parser_class(**kwargs) + + +def make_full_parser(**kwargs): + ''' A parser that parses all supported CSS 3 modules in addition to CSS 2.1 ''' + features = tuple(PARSER_MODULES) + return make_parser(*features, **kwargs) diff --git a/ebook_converter/tinycss/color3.py b/ebook_converter/tinycss/color3.py new file mode 100644 index 0000000..e0cb0bd --- /dev/null +++ b/ebook_converter/tinycss/color3.py @@ -0,0 +1,382 @@ +# coding: utf8 +""" + tinycss.colors3 + --------------- + + Parser for CSS 3 color values + http://www.w3.org/TR/css3-color/ + + This module does not provide anything that integrates in a parser class, + only functions that parse single tokens from (eg.) a property value. + + :copyright: (c) 2012 by Simon Sapin. + :license: BSD, see LICENSE for more details. +""" + +from __future__ import unicode_literals, division +import collections +import itertools +import re + +from .tokenizer import tokenize_grouped + + +class RGBA(collections.namedtuple('RGBA', ['red', 'green', 'blue', 'alpha'])): + """An RGBA color. + + A tuple of four floats in the 0..1 range: ``(r, g, b, a)``. + Also has ``red``, ``green``, ``blue`` and ``alpha`` attributes to access + the same values. + + """ + + +def parse_color_string(css_string): + """Parse a CSS string as a color value. + + This is a convenience wrapper around :func:`parse_color` in case you + have a string that is not from a CSS stylesheet. + + :param css_string: + An unicode string in CSS syntax. + :returns: + Same as :func:`parse_color`. + + """ + tokens = list(tokenize_grouped(css_string.strip())) + if len(tokens) == 1: + return parse_color(tokens[0]) + + +def parse_color(token): + """Parse single token as a color value. + + :param token: + A single :class:`~.token_data.Token` or + :class:`~.token_data.ContainerToken`, as found eg. in a + property value. + :returns: + * ``None``, if the token is not a valid CSS 3 color value. + (No exception is raised.) + * For the *currentColor* keyword: the string ``'currentColor'`` + * Every other values (including keywords, HSL and HSLA) is converted + to RGBA and returned as an :class:`RGBA` object (a 4-tuple with + attribute access). + The alpha channel is clipped to [0, 1], but R, G, or B can be + out of range (eg. ``rgb(-51, 306, 0)`` is represented as + ``(-.2, 1.2, 0, 1)``.) + + """ + if token.type == 'IDENT': + return COLOR_KEYWORDS.get(token.value.lower()) + elif token.type == 'HASH': + for multiplier, regexp in HASH_REGEXPS: + match = regexp(token.value) + if match: + r, g, b = [int(group * multiplier, 16) / 255 + for group in match.groups()] + return RGBA(r, g, b, 1.) + elif token.type == 'FUNCTION': + args = parse_comma_separated(token.content) + if args: + name = token.function_name.lower() + if name == 'rgb': + return parse_rgb(args, alpha=1.) + elif name == 'rgba': + alpha = parse_alpha(args[3:]) + if alpha is not None: + return parse_rgb(args[:3], alpha) + elif name == 'hsl': + return parse_hsl(args, alpha=1.) + elif name == 'hsla': + alpha = parse_alpha(args[3:]) + if alpha is not None: + return parse_hsl(args[:3], alpha) + + +def parse_alpha(args): + """ + If args is a list of a single INTEGER or NUMBER token, + retur its value clipped to the 0..1 range + Otherwise, return None. + """ + if len(args) == 1 and args[0].type in ('NUMBER', 'INTEGER'): + return min(1, max(0, args[0].value)) + + +def parse_rgb(args, alpha): + """ + If args is a list of 3 INTEGER tokens or 3 PERCENTAGE tokens, + return RGB values as a tuple of 3 floats in 0..1. + Otherwise, return None. + """ + types = [arg.type for arg in args] + if types == ['INTEGER', 'INTEGER', 'INTEGER']: + r, g, b = [arg.value / 255 for arg in args[:3]] + return RGBA(r, g, b, alpha) + elif types == ['PERCENTAGE', 'PERCENTAGE', 'PERCENTAGE']: + r, g, b = [arg.value / 100 for arg in args[:3]] + return RGBA(r, g, b, alpha) + + +def parse_hsl(args, alpha): + """ + If args is a list of 1 INTEGER token and 2 PERCENTAGE tokens, + return RGB values as a tuple of 3 floats in 0..1. + Otherwise, return None. + """ + types = [arg.type for arg in args] + if types == ['INTEGER', 'PERCENTAGE', 'PERCENTAGE']: + hsl = [arg.value for arg in args[:3]] + r, g, b = hsl_to_rgb(*hsl) + return RGBA(r, g, b, alpha) + + +def hsl_to_rgb(hue, saturation, lightness): + """ + :param hue: degrees + :param saturation: percentage + :param lightness: percentage + :returns: (r, g, b) as floats in the 0..1 range + """ + hue = (hue / 360) % 1 + saturation = min(1, max(0, saturation / 100)) + lightness = min(1, max(0, lightness / 100)) + + # Translated from ABC: http://www.w3.org/TR/css3-color/#hsl-color + def hue_to_rgb(m1, m2, h): + if h < 0: + h += 1 + if h > 1: + h -= 1 + if h * 6 < 1: + return m1 + (m2 - m1) * h * 6 + if h * 2 < 1: + return m2 + if h * 3 < 2: + return m1 + (m2 - m1) * (2 / 3 - h) * 6 + return m1 + + if lightness <= 0.5: + m2 = lightness * (saturation + 1) + else: + m2 = lightness + saturation - lightness * saturation + m1 = lightness * 2 - m2 + return ( + hue_to_rgb(m1, m2, hue + 1 / 3), + hue_to_rgb(m1, m2, hue), + hue_to_rgb(m1, m2, hue - 1 / 3), + ) + + +def parse_comma_separated(tokens): + """Parse a list of tokens (typically the content of a function token) + as arguments made of a single token each, separated by mandatory commas, + with optional white space around each argument. + + return the argument list without commas or white space; + or None if the function token content do not match the description above. + + """ + tokens = [token for token in tokens if token.type != 'S'] + if not tokens: + return [] + if len(tokens) % 2 == 1 and all( + token.type == 'DELIM' and token.value == ',' + for token in tokens[1::2]): + return tokens[::2] + + +HASH_REGEXPS = ( + (2, re.compile(r'^#([\da-f])([\da-f])([\da-f])$', re.I).match), + (1, re.compile(r'^#([\da-f]{2})([\da-f]{2})([\da-f]{2})$', re.I).match), +) + + +# (r, g, b) in 0..255 +BASIC_COLOR_KEYWORDS = [ + ('black', (0, 0, 0)), + ('silver', (192, 192, 192)), + ('gray', (128, 128, 128)), + ('white', (255, 255, 255)), + ('maroon', (128, 0, 0)), + ('red', (255, 0, 0)), + ('purple', (128, 0, 128)), + ('fuchsia', (255, 0, 255)), + ('green', (0, 128, 0)), + ('lime', (0, 255, 0)), + ('olive', (128, 128, 0)), + ('yellow', (255, 255, 0)), + ('navy', (0, 0, 128)), + ('blue', (0, 0, 255)), + ('teal', (0, 128, 128)), + ('aqua', (0, 255, 255)), +] + + +# (r, g, b) in 0..255 +EXTENDED_COLOR_KEYWORDS = [ + ('aliceblue', (240, 248, 255)), + ('antiquewhite', (250, 235, 215)), + ('aqua', (0, 255, 255)), + ('aquamarine', (127, 255, 212)), + ('azure', (240, 255, 255)), + ('beige', (245, 245, 220)), + ('bisque', (255, 228, 196)), + ('black', (0, 0, 0)), + ('blanchedalmond', (255, 235, 205)), + ('blue', (0, 0, 255)), + ('blueviolet', (138, 43, 226)), + ('brown', (165, 42, 42)), + ('burlywood', (222, 184, 135)), + ('cadetblue', (95, 158, 160)), + ('chartreuse', (127, 255, 0)), + ('chocolate', (210, 105, 30)), + ('coral', (255, 127, 80)), + ('cornflowerblue', (100, 149, 237)), + ('cornsilk', (255, 248, 220)), + ('crimson', (220, 20, 60)), + ('cyan', (0, 255, 255)), + ('darkblue', (0, 0, 139)), + ('darkcyan', (0, 139, 139)), + ('darkgoldenrod', (184, 134, 11)), + ('darkgray', (169, 169, 169)), + ('darkgreen', (0, 100, 0)), + ('darkgrey', (169, 169, 169)), + ('darkkhaki', (189, 183, 107)), + ('darkmagenta', (139, 0, 139)), + ('darkolivegreen', (85, 107, 47)), + ('darkorange', (255, 140, 0)), + ('darkorchid', (153, 50, 204)), + ('darkred', (139, 0, 0)), + ('darksalmon', (233, 150, 122)), + ('darkseagreen', (143, 188, 143)), + ('darkslateblue', (72, 61, 139)), + ('darkslategray', (47, 79, 79)), + ('darkslategrey', (47, 79, 79)), + ('darkturquoise', (0, 206, 209)), + ('darkviolet', (148, 0, 211)), + ('deeppink', (255, 20, 147)), + ('deepskyblue', (0, 191, 255)), + ('dimgray', (105, 105, 105)), + ('dimgrey', (105, 105, 105)), + ('dodgerblue', (30, 144, 255)), + ('firebrick', (178, 34, 34)), + ('floralwhite', (255, 250, 240)), + ('forestgreen', (34, 139, 34)), + ('fuchsia', (255, 0, 255)), + ('gainsboro', (220, 220, 220)), + ('ghostwhite', (248, 248, 255)), + ('gold', (255, 215, 0)), + ('goldenrod', (218, 165, 32)), + ('gray', (128, 128, 128)), + ('green', (0, 128, 0)), + ('greenyellow', (173, 255, 47)), + ('grey', (128, 128, 128)), + ('honeydew', (240, 255, 240)), + ('hotpink', (255, 105, 180)), + ('indianred', (205, 92, 92)), + ('indigo', (75, 0, 130)), + ('ivory', (255, 255, 240)), + ('khaki', (240, 230, 140)), + ('lavender', (230, 230, 250)), + ('lavenderblush', (255, 240, 245)), + ('lawngreen', (124, 252, 0)), + ('lemonchiffon', (255, 250, 205)), + ('lightblue', (173, 216, 230)), + ('lightcoral', (240, 128, 128)), + ('lightcyan', (224, 255, 255)), + ('lightgoldenrodyellow', (250, 250, 210)), + ('lightgray', (211, 211, 211)), + ('lightgreen', (144, 238, 144)), + ('lightgrey', (211, 211, 211)), + ('lightpink', (255, 182, 193)), + ('lightsalmon', (255, 160, 122)), + ('lightseagreen', (32, 178, 170)), + ('lightskyblue', (135, 206, 250)), + ('lightslategray', (119, 136, 153)), + ('lightslategrey', (119, 136, 153)), + ('lightsteelblue', (176, 196, 222)), + ('lightyellow', (255, 255, 224)), + ('lime', (0, 255, 0)), + ('limegreen', (50, 205, 50)), + ('linen', (250, 240, 230)), + ('magenta', (255, 0, 255)), + ('maroon', (128, 0, 0)), + ('mediumaquamarine', (102, 205, 170)), + ('mediumblue', (0, 0, 205)), + ('mediumorchid', (186, 85, 211)), + ('mediumpurple', (147, 112, 219)), + ('mediumseagreen', (60, 179, 113)), + ('mediumslateblue', (123, 104, 238)), + ('mediumspringgreen', (0, 250, 154)), + ('mediumturquoise', (72, 209, 204)), + ('mediumvioletred', (199, 21, 133)), + ('midnightblue', (25, 25, 112)), + ('mintcream', (245, 255, 250)), + ('mistyrose', (255, 228, 225)), + ('moccasin', (255, 228, 181)), + ('navajowhite', (255, 222, 173)), + ('navy', (0, 0, 128)), + ('oldlace', (253, 245, 230)), + ('olive', (128, 128, 0)), + ('olivedrab', (107, 142, 35)), + ('orange', (255, 165, 0)), + ('orangered', (255, 69, 0)), + ('orchid', (218, 112, 214)), + ('palegoldenrod', (238, 232, 170)), + ('palegreen', (152, 251, 152)), + ('paleturquoise', (175, 238, 238)), + ('palevioletred', (219, 112, 147)), + ('papayawhip', (255, 239, 213)), + ('peachpuff', (255, 218, 185)), + ('peru', (205, 133, 63)), + ('pink', (255, 192, 203)), + ('plum', (221, 160, 221)), + ('powderblue', (176, 224, 230)), + ('purple', (128, 0, 128)), + ('red', (255, 0, 0)), + ('rosybrown', (188, 143, 143)), + ('royalblue', (65, 105, 225)), + ('saddlebrown', (139, 69, 19)), + ('salmon', (250, 128, 114)), + ('sandybrown', (244, 164, 96)), + ('seagreen', (46, 139, 87)), + ('seashell', (255, 245, 238)), + ('sienna', (160, 82, 45)), + ('silver', (192, 192, 192)), + ('skyblue', (135, 206, 235)), + ('slateblue', (106, 90, 205)), + ('slategray', (112, 128, 144)), + ('slategrey', (112, 128, 144)), + ('snow', (255, 250, 250)), + ('springgreen', (0, 255, 127)), + ('steelblue', (70, 130, 180)), + ('tan', (210, 180, 140)), + ('teal', (0, 128, 128)), + ('thistle', (216, 191, 216)), + ('tomato', (255, 99, 71)), + ('turquoise', (64, 224, 208)), + ('violet', (238, 130, 238)), + ('wheat', (245, 222, 179)), + ('white', (255, 255, 255)), + ('whitesmoke', (245, 245, 245)), + ('yellow', (255, 255, 0)), + ('yellowgreen', (154, 205, 50)), +] + + +# (r, g, b, a) in 0..1 or a string marker +SPECIAL_COLOR_KEYWORDS = { + 'currentcolor': 'currentColor', + 'transparent': RGBA(0., 0., 0., 0.), +} + + +# RGBA namedtuples of (r, g, b, a) in 0..1 or a string marker +COLOR_KEYWORDS = SPECIAL_COLOR_KEYWORDS.copy() +COLOR_KEYWORDS.update( + # 255 maps to 1, 0 to 0, the rest is linear. + (keyword, RGBA(r / 255., g / 255., b / 255., 1.)) + for keyword, (r, g, b) in itertools.chain( + BASIC_COLOR_KEYWORDS, EXTENDED_COLOR_KEYWORDS)) diff --git a/ebook_converter/tinycss/css21.py b/ebook_converter/tinycss/css21.py new file mode 100644 index 0000000..2f1d3f8 --- /dev/null +++ b/ebook_converter/tinycss/css21.py @@ -0,0 +1,830 @@ +# coding: utf8 +""" + tinycss.css21 + ------------- + + Parser for CSS 2.1 + http://www.w3.org/TR/CSS21/syndata.html + + :copyright: (c) 2012 by Simon Sapin. + :license: BSD, see LICENSE for more details. +""" + +from __future__ import unicode_literals +from itertools import chain, islice + +from tinycss.decoding import decode +from tinycss.token_data import TokenList +from tinycss.tokenizer import tokenize_grouped +from tinycss.parsing import ( + strip_whitespace, remove_whitespace, split_on_comma, validate_value, + validate_any, ParseError) + + +# stylesheet : [ CDO | CDC | S | statement ]*; +# statement : ruleset | at-rule; +# at-rule : ATKEYWORD S* any* [ block | ';' S* ]; +# block : '{' S* [ any | block | ATKEYWORD S* | ';' S* ]* '}' S*; +# ruleset : selector? '{' S* declaration? [ ';' S* declaration? ]* '}' S*; +# selector : any+; +# declaration : property S* ':' S* value; +# property : IDENT; +# value : [ any | block | ATKEYWORD S* ]+; +# any : [ IDENT | NUMBER | PERCENTAGE | DIMENSION | STRING +# | DELIM | URI | HASH | UNICODE-RANGE | INCLUDES +# | DASHMATCH | ':' | FUNCTION S* [any|unused]* ')' +# | '(' S* [any|unused]* ')' | '[' S* [any|unused]* ']' +# ] S*; +# unused : block | ATKEYWORD S* | ';' S* | CDO S* | CDC S*; + + +class Stylesheet(object): + """ + A parsed CSS stylesheet. + + .. attribute:: rules + + A mixed list, in source order, of :class:`RuleSet` and various + at-rules such as :class:`ImportRule`, :class:`MediaRule` + and :class:`PageRule`. + Use their :obj:`at_keyword` attribute to distinguish them. + + .. attribute:: errors + + A list of :class:`~.parsing.ParseError`. Invalid rules and declarations + are ignored, with the details logged in this list. + + .. attribute:: encoding + + The character encoding that was used to decode the stylesheet + from bytes, or ``None`` for Unicode stylesheets. + + """ + def __init__(self, rules, errors, encoding): + self.rules = rules + self.errors = errors + self.encoding = encoding + + def __repr__(self): + return '<{0.__class__.__name__} {1} rules {2} errors>'.format( + self, len(self.rules), len(self.errors)) + + +class AtRule(object): + """ + An unparsed at-rule. + + .. attribute:: at_keyword + + The normalized (lower-case) at-keyword as a string. Eg: ``'@page'`` + + .. attribute:: head + + The part of the at-rule between the at-keyword and the ``{`` + marking the body, or the ``;`` marking the end of an at-rule without + a body. A :class:`~.token_data.TokenList`. + + .. attribute:: body + + The content of the body between ``{`` and ``}`` as a + :class:`~.token_data.TokenList`, or ``None`` if there is no body + (ie. if the rule ends with ``;``). + + The head was validated against the core grammar but **not** the body, + as the body might contain declarations. In case of an error in a + declaration, parsing should continue from the next declaration. + The whole rule should not be ignored as it would be for an error + in the head. + + These at-rules are expected to be parsed further before reaching + the user API. + + """ + + __slots__ = 'at_keyword', 'head', 'body', 'line', 'column' + + def __init__(self, at_keyword, head, body, line, column): + self.at_keyword = at_keyword + self.head = TokenList(head) + self.body = TokenList(body) if body is not None else body + self.line = line + self.column = column + + def __repr__(self): + return ('<{0.__class__.__name__} {0.line}:{0.column} {0.at_keyword}>' + .format(self)) + + +class RuleSet(object): + """A ruleset. + + .. attribute:: at_keyword + + Always ``None``. Helps to tell rulesets apart from at-rules. + + .. attribute:: selector + + The selector as a :class:`~.token_data.TokenList`. + In CSS 3, this is actually called a selector group. + + ``rule.selector.as_css()`` gives the selector as a string. + This string can be used with *cssselect*, see :ref:`selectors3`. + + .. attribute:: declarations + + The list of :class:`Declaration`, in source order. + + """ + + at_keyword = None + __slots__ = 'selector', 'declarations', 'line', 'column' + + def __init__(self, selector, declarations, line, column): + self.selector = TokenList(selector) + self.declarations = declarations + self.line = line + self.column = column + + def __repr__(self): + return ('<{0.__class__.__name__} at {0.line}:{0.column} {1}>' + .format(self, self.selector.as_css())) + + +class Declaration(object): + """A property declaration. + + .. attribute:: name + + The property name as a normalized (lower-case) string. + + .. attribute:: value + + The property value as a :class:`~.token_data.TokenList`. + + The value is not parsed. UAs using tinycss may only support + some properties or some values and tinycss does not know which. + They need to parse values themselves and ignore declarations with + unknown or unsupported properties or values, and fall back + on any previous declaration. + + :mod:`tinycss.color3` parses color values, but other values + will need specific parsing/validation code. + + .. attribute:: priority + + Either the string ``'important'`` or ``None``. + + """ + __slots__ = 'name', 'value', 'priority', 'line', 'column' + + def __init__(self, name, value, priority, line, column): + self.name = name + self.value = TokenList(value) + self.priority = priority + self.line = line + self.column = column + + def __repr__(self): + priority = ' !' + self.priority if self.priority else '' + return ('<{0.__class__.__name__} {0.line}:{0.column}' + ' {0.name}: {1}{2}>'.format( + self, self.value.as_css(), priority)) + + +class PageRule(object): + """A parsed CSS 2.1 @page rule. + + .. attribute:: at_keyword + + Always ``'@page'`` + + .. attribute:: selector + + The page selector. + In CSS 2.1 this is either ``None`` (no selector), or the string + ``'first'``, ``'left'`` or ``'right'`` for the pseudo class + of the same name. + + .. attribute:: specificity + + Specificity of the page selector. This is a tuple of four integers, + but these tuples are mostly meant to be compared to each other. + + .. attribute:: declarations + + A list of :class:`Declaration`, in source order. + + .. attribute:: at_rules + + The list of parsed at-rules inside the @page block, in source order. + Always empty for CSS 2.1. + + """ + at_keyword = '@page' + __slots__ = 'selector', 'specificity', 'declarations', 'at_rules', 'line', 'column' + + def __init__(self, selector, specificity, declarations, at_rules, + line, column): + self.selector = selector + self.specificity = specificity + self.declarations = declarations + self.at_rules = at_rules + self.line = line + self.column = column + + def __repr__(self): + return ('<{0.__class__.__name__} {0.line}:{0.column}' + ' {0.selector}>'.format(self)) + + +class MediaRule(object): + """A parsed @media rule. + + .. attribute:: at_keyword + + Always ``'@media'`` + + .. attribute:: media + + For CSS 2.1 without media queries: the media types + as a list of strings. + + .. attribute:: rules + + The list :class:`RuleSet` and various at-rules inside the @media + block, in source order. + + """ + at_keyword = '@media' + __slots__ = 'media', 'rules', 'line', 'column' + + def __init__(self, media, rules, line, column): + self.media = media + self.rules = rules + self.line = line + self.column = column + + def __repr__(self): + return ('<{0.__class__.__name__} {0.line}:{0.column}' + ' {0.media}>'.format(self)) + + +class ImportRule(object): + """A parsed @import rule. + + .. attribute:: at_keyword + + Always ``'@import'`` + + .. attribute:: uri + + The URI to be imported, as read from the stylesheet. + (URIs are not made absolute.) + + .. attribute:: media + + For CSS 2.1 without media queries: the media types + as a list of strings. + This attribute is explicitly ``['all']`` if the media was omitted + in the source. + + """ + at_keyword = '@import' + __slots__ = 'uri', 'media', 'line', 'column' + + def __init__(self, uri, media, line, column): + self.uri = uri + self.media = media + self.line = line + self.column = column + + def __repr__(self): + return ('<{0.__class__.__name__} {0.line}:{0.column}' + ' {0.uri}>'.format(self)) + + +def _remove_at_charset(tokens): + """Remove any valid @charset at the beggining of a token stream. + + :param tokens: + An iterable of tokens + :returns: + A possibly truncated iterable of tokens + + """ + tokens = iter(tokens) + header = list(islice(tokens, 4)) + if [t.type for t in header] == ['ATKEYWORD', 'S', 'STRING', ';']: + atkw, space, string, semicolon = header + if ((atkw.value, space.value) == ('@charset', ' ') + and string.as_css()[0] == '"'): + # Found a valid @charset rule, only keep what’s after it. + return tokens + return chain(header, tokens) + + +class CSS21Parser(object): + """Parser for CSS 2.1 + + This parser supports the core CSS syntax as well as @import, @media, + @page and !important. + + Note that property values are still not parsed, as UAs using this + parser may only support some properties or some values. + + Currently the parser holds no state. It being a class only allows + subclassing and overriding its methods. + + """ + + def __init__(self): + self.at_parsers = { + '@' + x:getattr(self, 'parse_%s_rule' % x) for x in ('media', 'page', 'import', 'charset')} + + # User API: + + def parse_stylesheet_file(self, css_file, protocol_encoding=None, + linking_encoding=None, document_encoding=None): + """Parse a stylesheet from a file or filename. + + Character encoding-related parameters and behavior are the same + as in :meth:`parse_stylesheet_bytes`. + + :param css_file: + Either a file (any object with a :meth:`~file.read` method) + or a filename. + :return: + A :class:`Stylesheet`. + + """ + if hasattr(css_file, 'read'): + css_bytes = css_file.read() + else: + with open(css_file, 'rb') as fd: + css_bytes = fd.read() + return self.parse_stylesheet_bytes(css_bytes, protocol_encoding, + linking_encoding, document_encoding) + + def parse_stylesheet_bytes(self, css_bytes, protocol_encoding=None, + linking_encoding=None, document_encoding=None): + """Parse a stylesheet from a byte string. + + The character encoding is determined from the passed metadata and the + ``@charset`` rule in the stylesheet (if any). + If no encoding information is available or decoding fails, + decoding defaults to UTF-8 and then fall back on ISO-8859-1. + + :param css_bytes: + A CSS stylesheet as a byte string. + :param protocol_encoding: + The "charset" parameter of a "Content-Type" HTTP header (if any), + or similar metadata for other protocols. + :param linking_encoding: + ```` or other metadata from the linking mechanism + (if any) + :param document_encoding: + Encoding of the referring style sheet or document (if any) + :return: + A :class:`Stylesheet`. + + """ + css_unicode, encoding = decode(css_bytes, protocol_encoding, + linking_encoding, document_encoding) + return self.parse_stylesheet(css_unicode, encoding=encoding) + + def parse_stylesheet(self, css_unicode, encoding=None): + """Parse a stylesheet from an Unicode string. + + :param css_unicode: + A CSS stylesheet as an unicode string. + :param encoding: + The character encoding used to decode the stylesheet from bytes, + if any. + :return: + A :class:`Stylesheet`. + + """ + tokens = tokenize_grouped(css_unicode) + if encoding: + tokens = _remove_at_charset(tokens) + rules, errors = self.parse_rules(tokens, context='stylesheet') + return Stylesheet(rules, errors, encoding) + + def parse_style_attr(self, css_source): + """Parse a "style" attribute (eg. of an HTML element). + + This method only accepts Unicode as the source (HTML) document + is supposed to handle the character encoding. + + :param css_source: + The attribute value, as an unicode string. + :return: + A tuple of the list of valid :class:`Declaration` and + a list of :class:`~.parsing.ParseError`. + """ + return self.parse_declaration_list(tokenize_grouped(css_source)) + + # API for subclasses: + + def parse_rules(self, tokens, context): + """Parse a sequence of rules (rulesets and at-rules). + + :param tokens: + An iterable of tokens. + :param context: + Either ``'stylesheet'`` or an at-keyword such as ``'@media'``. + (Most at-rules are only allowed in some contexts.) + :return: + A tuple of a list of parsed rules and a list of + :class:`~.parsing.ParseError`. + + """ + rules = [] + errors = [] + tokens = iter(tokens) + for token in tokens: + if token.type not in ('S', 'CDO', 'CDC'): + try: + if token.type == 'ATKEYWORD': + rule = self.read_at_rule(token, tokens) + result = self.parse_at_rule( + rule, rules, errors, context) + rules.append(result) + else: + rule, rule_errors = self.parse_ruleset(token, tokens) + rules.append(rule) + errors.extend(rule_errors) + except ParseError as exc: + errors.append(exc) + # Skip the entire rule + return rules, errors + + def read_at_rule(self, at_keyword_token, tokens): + """Read an at-rule from a token stream. + + :param at_keyword_token: + The ATKEYWORD token that starts this at-rule + You may have read it already to distinguish the rule + from a ruleset. + :param tokens: + An iterator of subsequent tokens. Will be consumed just enough + for one at-rule. + :return: + An unparsed :class:`AtRule`. + :raises: + :class:`~.parsing.ParseError` if the head is invalid for the core + grammar. The body is **not** validated. See :class:`AtRule`. + + """ + # CSS syntax is case-insensitive + at_keyword = at_keyword_token.value.lower() + head = [] + # For the ParseError in case `tokens` is empty: + token = at_keyword_token + for token in tokens: + if token.type in '{;': + break + # Ignore white space just after the at-keyword. + else: + head.append(token) + # On unexpected end of stylesheet, pretend that a ';' was there + head = strip_whitespace(head) + for head_token in head: + validate_any(head_token, 'at-rule head') + body = token.content if token.type == '{' else None + return AtRule(at_keyword, head, body, + at_keyword_token.line, at_keyword_token.column) + + def parse_at_rule(self, rule, previous_rules, errors, context): + """Parse an at-rule. + + Subclasses that override this method must use ``super()`` and + pass its return value for at-rules they do not know. + + In CSS 2.1, this method handles @charset, @import, @media and @page + rules. + + :param rule: + An unparsed :class:`AtRule`. + :param previous_rules: + The list of at-rules and rulesets that have been parsed so far + in this context. This list can be used to decide if the current + rule is valid. (For example, @import rules are only allowed + before anything but a @charset rule.) + :param context: + Either ``'stylesheet'`` or an at-keyword such as ``'@media'``. + (Most at-rules are only allowed in some contexts.) + :raises: + :class:`~.parsing.ParseError` if the rule is invalid. + :return: + A parsed at-rule + + """ + try: + parser = self.at_parsers[rule.at_keyword] + except KeyError: + raise ParseError(rule, 'unknown at-rule in {0} context: {1}' + .format(context, rule.at_keyword)) + else: + return parser(rule, previous_rules, errors, context) + + def parse_page_rule(self, rule, previous_rules, errors, context): + if context != 'stylesheet': + raise ParseError(rule, '@page rule not allowed in ' + context) + selector, specificity = self.parse_page_selector(rule.head) + if rule.body is None: + raise ParseError(rule, + 'invalid {0} rule: missing block'.format(rule.at_keyword)) + declarations, at_rules, rule_errors = \ + self.parse_declarations_and_at_rules(rule.body, '@page') + errors.extend(rule_errors) + return PageRule(selector, specificity, declarations, at_rules, + rule.line, rule.column) + + def parse_media_rule(self, rule, previous_rules, errors, context): + if context != 'stylesheet': + raise ParseError(rule, '@media rule not allowed in ' + context) + media = self.parse_media(rule.head, errors) + if rule.body is None: + raise ParseError(rule, + 'invalid {0} rule: missing block'.format(rule.at_keyword)) + rules, rule_errors = self.parse_rules(rule.body, '@media') + errors.extend(rule_errors) + return MediaRule(media, rules, rule.line, rule.column) + + def parse_import_rule(self, rule, previous_rules, errors, context): + if context != 'stylesheet': + raise ParseError(rule, + '@import rule not allowed in ' + context) + for previous_rule in previous_rules: + if previous_rule.at_keyword not in ('@charset', '@import'): + if previous_rule.at_keyword: + type_ = 'an {0} rule'.format(previous_rule.at_keyword) + else: + type_ = 'a ruleset' + raise ParseError(previous_rule, + '@import rule not allowed after ' + type_) + head = rule.head + if not head: + raise ParseError(rule, + 'expected URI or STRING for @import rule') + if head[0].type not in ('URI', 'STRING'): + raise ParseError(rule, + 'expected URI or STRING for @import rule, got ' + + head[0].type) + uri = head[0].value + media = self.parse_media(strip_whitespace(head[1:]), errors) + if rule.body is not None: + # The position of the ';' token would be best, but we don’t + # have it anymore here. + raise ParseError(head[-1], "expected ';', got a block") + return ImportRule(uri, media, rule.line, rule.column) + + def parse_charset_rule(self, rule, previous_rules, errors, context): + raise ParseError(rule, 'mis-placed or malformed @charset rule') + + def parse_media(self, tokens, errors): + """For CSS 2.1, parse a list of media types. + + Media Queries are expected to override this. + + :param tokens: + A list of tokens + :raises: + :class:`~.parsing.ParseError` on invalid media types/queries + :returns: + For CSS 2.1, a list of media types as strings + """ + if not tokens: + return ['all'] + media_types = [] + for part in split_on_comma(remove_whitespace(tokens)): + types = [token.type for token in part] + if types == ['IDENT']: + media_types.append(part[0].value) + else: + raise ParseError(tokens[0], 'expected a media type' + + ((', got ' + ', '.join(types)) if types else '')) + return media_types + + def parse_page_selector(self, tokens): + """Parse an @page selector. + + :param tokens: + An iterable of token, typically from the ``head`` attribute of + an unparsed :class:`AtRule`. + :returns: + A page selector. For CSS 2.1, this is ``'first'``, ``'left'``, + ``'right'`` or ``None``. + :raises: + :class:`~.parsing.ParseError` on invalid selectors + + """ + if not tokens: + return None, (0, 0) + if (len(tokens) == 2 and tokens[0].type == ':' + and tokens[1].type == 'IDENT'): + pseudo_class = tokens[1].value + specificity = { + 'first': (1, 0), 'left': (0, 1), 'right': (0, 1), + }.get(pseudo_class) + if specificity: + return pseudo_class, specificity + raise ParseError(tokens[0], 'invalid @page selector') + + def parse_declarations_and_at_rules(self, tokens, context): + """Parse a mixed list of declarations and at rules, as found eg. + in the body of an @page rule. + + Note that to add supported at-rules inside @page, + :class:`~.page3.CSSPage3Parser` extends :meth:`parse_at_rule`, + not this method. + + :param tokens: + An iterable of token, typically from the ``body`` attribute of + an unparsed :class:`AtRule`. + :param context: + An at-keyword such as ``'@page'``. + (Most at-rules are only allowed in some contexts.) + :returns: + A tuple of: + + * A list of :class:`Declaration` + * A list of parsed at-rules (empty for CSS 2.1) + * A list of :class:`~.parsing.ParseError` + + """ + at_rules = [] + declarations = [] + errors = [] + tokens = iter(tokens) + for token in tokens: + if token.type == 'ATKEYWORD': + try: + rule = self.read_at_rule(token, tokens) + result = self.parse_at_rule( + rule, at_rules, errors, context) + at_rules.append(result) + except ParseError as err: + errors.append(err) + elif token.type != 'S': + declaration_tokens = [] + while token and token.type != ';': + declaration_tokens.append(token) + token = next(tokens, None) + if declaration_tokens: + try: + declarations.append( + self.parse_declaration(declaration_tokens)) + except ParseError as err: + errors.append(err) + return declarations, at_rules, errors + + def parse_ruleset(self, first_token, tokens): + """Parse a ruleset: a selector followed by declaration block. + + :param first_token: + The first token of the ruleset (probably of the selector). + You may have read it already to distinguish the rule + from an at-rule. + :param tokens: + an iterator of subsequent tokens. Will be consumed just enough + for one ruleset. + :return: + a tuple of a :class:`RuleSet` and an error list. + The errors are recovered :class:`~.parsing.ParseError` in declarations. + (Parsing continues from the next declaration on such errors.) + :raises: + :class:`~.parsing.ParseError` if the selector is invalid for the + core grammar. + Note a that a selector can be valid for the core grammar but + not for CSS 2.1 or another level. + + """ + selector = [] + for token in chain([first_token], tokens): + if token.type == '{': + # Parse/validate once we’ve read the whole rule + selector = strip_whitespace(selector) + if not selector: + raise ParseError(first_token, 'empty selector') + for selector_token in selector: + validate_any(selector_token, 'selector') + declarations, errors = self.parse_declaration_list( + token.content) + ruleset = RuleSet(selector, declarations, + first_token.line, first_token.column) + return ruleset, errors + else: + selector.append(token) + raise ParseError(token, 'no declaration block found for ruleset') + + def parse_declaration_list(self, tokens): + """Parse a ``;`` separated declaration list. + + You may want to use :meth:`parse_declarations_and_at_rules` (or + some other method that uses :func:`parse_declaration` directly) + instead if you have not just declarations in the same context. + + :param tokens: + an iterable of tokens. Should stop at (before) the end + of the block, as marked by ``}``. + :return: + a tuple of the list of valid :class:`Declaration` and a list + of :class:`~.parsing.ParseError` + + """ + # split at ';' + parts = [] + this_part = [] + for token in tokens: + if token.type == ';': + parts.append(this_part) + this_part = [] + else: + this_part.append(token) + parts.append(this_part) + + declarations = [] + errors = [] + for tokens in parts: + tokens = strip_whitespace(tokens) + if tokens: + try: + declarations.append(self.parse_declaration(tokens)) + except ParseError as exc: + errors.append(exc) + # Skip the entire declaration + return declarations, errors + + def parse_declaration(self, tokens): + """Parse a single declaration. + + :param tokens: + an iterable of at least one token. Should stop at (before) + the end of the declaration, as marked by a ``;`` or ``}``. + Empty declarations (ie. consecutive ``;`` with only white space + in-between) should be skipped earlier and not passed to + this method. + :returns: + a :class:`Declaration` + :raises: + :class:`~.parsing.ParseError` if the tokens do not match the + 'declaration' production of the core grammar. + + """ + tokens = iter(tokens) + + name_token = next(tokens) # assume there is at least one + if name_token.type == 'IDENT': + # CSS syntax is case-insensitive + property_name = name_token.value.lower() + else: + raise ParseError(name_token, + 'expected a property name, got {0}'.format(name_token.type)) + + token = name_token # In case ``tokens`` is now empty + for token in tokens: + if token.type == ':': + break + elif token.type != 'S': + raise ParseError( + token, "expected ':', got {0}".format(token.type)) + else: + raise ParseError(token, "expected ':'") + + value = strip_whitespace(list(tokens)) + if not value: + raise ParseError(token, 'expected a property value') + validate_value(value) + value, priority = self.parse_value_priority(value) + return Declaration( + property_name, value, priority, name_token.line, name_token.column) + + def parse_value_priority(self, tokens): + """Separate any ``!important`` marker at the end of a property value. + + :param tokens: + A list of tokens for the property value. + :returns: + A tuple of the actual property value (a list of tokens) + and the :attr:`~Declaration.priority`. + """ + value = list(tokens) + # Walk the token list from the end + token = value.pop() + if token.type == 'IDENT' and token.value.lower() == 'important': + while value: + token = value.pop() + if token.type == 'DELIM' and token.value == '!': + # Skip any white space before the '!' + while value and value[-1].type == 'S': + value.pop() + if not value: + raise ParseError( + token, 'expected a value before !important') + return value, 'important' + # Skip white space between '!' and 'important' + elif token.type != 'S': + break + return tokens, None diff --git a/ebook_converter/tinycss/decoding.py b/ebook_converter/tinycss/decoding.py new file mode 100644 index 0000000..32e1799 --- /dev/null +++ b/ebook_converter/tinycss/decoding.py @@ -0,0 +1,255 @@ +# coding: utf8 +""" + tinycss.decoding + ---------------- + + Decoding stylesheets from bytes to Unicode. + http://www.w3.org/TR/CSS21/syndata.html#charset + + :copyright: (c) 2012 by Simon Sapin. + :license: BSD, see LICENSE for more details. +""" + +from __future__ import unicode_literals + +import operator +import re + +from polyglot.binary import from_hex_bytes + + +__all__ = ['decode'] # Everything else is implementation detail + + +def decode(css_bytes, protocol_encoding=None, + linking_encoding=None, document_encoding=None): + """ + Determine the character encoding from the passed metadata and the + ``@charset`` rule in the stylesheet (if any); and decode accordingly. + If no encoding information is available or decoding fails, + decoding defaults to UTF-8 and then fall back on ISO-8859-1. + + :param css_bytes: + a CSS stylesheet as a byte string + :param protocol_encoding: + The "charset" parameter of a "Content-Type" HTTP header (if any), + or similar metadata for other protocols. + :param linking_encoding: + ```` or other metadata from the linking mechanism + (if any) + :param document_encoding: + Encoding of the referring style sheet or document (if any) + :return: + A tuple of an Unicode string, with any BOM removed, and the + encoding that was used. + + """ + if protocol_encoding: + css_unicode = try_encoding(css_bytes, protocol_encoding) + if css_unicode is not None: + return css_unicode, protocol_encoding + for encoding, pattern in ENCODING_MAGIC_NUMBERS: + match = pattern(css_bytes) + if match: + has_at_charset = isinstance(encoding, tuple) + if has_at_charset: + extract, endianness = encoding + encoding = extract(match.group(1)) + # Get an ASCII-only unicode value. + # This is the only thing that works on both Python 2 and 3 + # for bytes.decode() + # Non-ASCII encoding names are invalid anyway, + # but make sure they stay invalid. + encoding = encoding.decode('ascii', 'replace') + encoding = encoding.replace('\ufffd', '?') + if encoding.replace('-', '').replace('_', '').lower() in [ + 'utf16', 'utf32']: + encoding += endianness + encoding = encoding.encode('ascii', 'replace').decode('ascii') + css_unicode = try_encoding(css_bytes, encoding) + if css_unicode and not (has_at_charset and not + css_unicode.startswith('@charset "')): + return css_unicode, encoding + break + for encoding in [linking_encoding, document_encoding]: + if encoding: + css_unicode = try_encoding(css_bytes, encoding) + if css_unicode is not None: + return css_unicode, encoding + css_unicode = try_encoding(css_bytes, 'UTF-8') + if css_unicode is not None: + return css_unicode, 'UTF-8' + return try_encoding(css_bytes, 'ISO-8859-1', fallback=False), 'ISO-8859-1' + + +def try_encoding(css_bytes, encoding, fallback=True): + if fallback: + try: + css_unicode = css_bytes.decode(encoding) + # LookupError means unknown encoding + except (UnicodeDecodeError, LookupError): + return None + else: + css_unicode = css_bytes.decode(encoding) + if css_unicode and css_unicode[0] == '\ufeff': + # Remove any Byte Order Mark + css_unicode = css_unicode[1:] + return css_unicode + + +def hex2re(hex_data): + return re.escape(from_hex_bytes(hex_data.replace(' ', '').encode('ascii'))) + + +class Slicer(object): + """Slice()[start:stop:end] == slice(start, stop, end)""" + def __getitem__(self, slice_): + return operator.itemgetter(slice_) + + +Slice = Slicer() + + +# List of (bom_size, encoding, pattern) +# bom_size is in bytes and can be zero +# encoding is a string or (slice_, endianness) for "as specified" +# slice_ is a slice object.How to extract the specified + +ENCODING_MAGIC_NUMBERS = [ + ((Slice[:], ''), re.compile( + hex2re('EF BB BF 40 63 68 61 72 73 65 74 20 22') + + b'([^\x22]*?)' + + hex2re('22 3B')).match), + + ('UTF-8', re.compile( + hex2re('EF BB BF')).match), + + ((Slice[:], ''), re.compile( + hex2re('40 63 68 61 72 73 65 74 20 22') + + b'([^\x22]*?)' + + hex2re('22 3B')).match), + + ((Slice[1::2], '-BE'), re.compile( + hex2re('FE FF 00 40 00 63 00 68 00 61 00 72 00 73 00 65 00' + '74 00 20 00 22') + + b'((\x00[^\x22])*?)' + + hex2re('00 22 00 3B')).match), + + ((Slice[1::2], '-BE'), re.compile( + hex2re('00 40 00 63 00 68 00 61 00 72 00 73 00 65 00 74 00' + '20 00 22') + + b'((\x00[^\x22])*?)' + + hex2re('00 22 00 3B')).match), + + ((Slice[::2], '-LE'), re.compile( + hex2re('FF FE 40 00 63 00 68 00 61 00 72 00 73 00 65 00 74' + '00 20 00 22 00') + + b'(([^\x22]\x00)*?)' + + hex2re('22 00 3B 00')).match), + + ((Slice[::2], '-LE'), re.compile( + hex2re('40 00 63 00 68 00 61 00 72 00 73 00 65 00 74 00 20' + '00 22 00') + + b'(([^\x22]\x00)*?)' + + hex2re('22 00 3B 00')).match), + + ((Slice[3::4], '-BE'), re.compile( + hex2re('00 00 FE FF 00 00 00 40 00 00 00 63 00 00 00 68 00' + '00 00 61 00 00 00 72 00 00 00 73 00 00 00 65 00 00' + '00 74 00 00 00 20 00 00 00 22') + + b'((\x00\x00\x00[^\x22])*?)' + + hex2re('00 00 00 22 00 00 00 3B')).match), + + ((Slice[3::4], '-BE'), re.compile( + hex2re('00 00 00 40 00 00 00 63 00 00 00 68 00 00 00 61 00' + '00 00 72 00 00 00 73 00 00 00 65 00 00 00 74 00 00' + '00 20 00 00 00 22') + + b'((\x00\x00\x00[^\x22])*?)' + + hex2re('00 00 00 22 00 00 00 3B')).match), + + +# Python does not support 2143 or 3412 endianness, AFAIK. +# I guess we could fix it up ourselves but meh. Patches welcome. + +# ((Slice[2::4], '-2143'), re.compile( +# hex2re('00 00 FF FE 00 00 40 00 00 00 63 00 00 00 68 00 00' +# '00 61 00 00 00 72 00 00 00 73 00 00 00 65 00 00 00' +# '74 00 00 00 20 00 00 00 22 00') +# + b'((\x00\x00[^\x22]\x00)*?)' +# + hex2re('00 00 22 00 00 00 3B 00')).match), + +# ((Slice[2::4], '-2143'), re.compile( +# hex2re('00 00 40 00 00 00 63 00 00 00 68 00 00 00 61 00 00' +# '00 72 00 00 00 73 00 00 00 65 00 00 00 74 00 00 00' +# '20 00 00 00 22 00') +# + b'((\x00\x00[^\x22]\x00)*?)' +# + hex2re('00 00 22 00 00 00 3B 00')).match), + +# ((Slice[1::4], '-3412'), re.compile( +# hex2re('FE FF 00 00 00 40 00 00 00 63 00 00 00 68 00 00 00' +# '61 00 00 00 72 00 00 00 73 00 00 00 65 00 00 00 74' +# '00 00 00 20 00 00 00 22 00 00') +# + b'((\x00[^\x22]\x00\x00)*?)' +# + hex2re('00 22 00 00 00 3B 00 00')).match), + +# ((Slice[1::4], '-3412'), re.compile( +# hex2re('00 40 00 00 00 63 00 00 00 68 00 00 00 61 00 00 00' +# '72 00 00 00 73 00 00 00 65 00 00 00 74 00 00 00 20' +# '00 00 00 22 00 00') +# + b'((\x00[^\x22]\x00\x00)*?)' +# + hex2re('00 22 00 00 00 3B 00 00')).match), + + ((Slice[::4], '-LE'), re.compile( + hex2re('FF FE 00 00 40 00 00 00 63 00 00 00 68 00 00 00 61' + '00 00 00 72 00 00 00 73 00 00 00 65 00 00 00 74 00' + '00 00 20 00 00 00 22 00 00 00') + + b'(([^\x22]\x00\x00\x00)*?)' + + hex2re('22 00 00 00 3B 00 00 00')).match), + + ((Slice[::4], '-LE'), re.compile( + hex2re('40 00 00 00 63 00 00 00 68 00 00 00 61 00 00 00 72' + '00 00 00 73 00 00 00 65 00 00 00 74 00 00 00 20 00' + '00 00 22 00 00 00') + + b'(([^\x22]\x00\x00\x00)*?)' + + hex2re('22 00 00 00 3B 00 00 00')).match), + + ('UTF-32-BE', re.compile( + hex2re('00 00 FE FF')).match), + + ('UTF-32-LE', re.compile( + hex2re('FF FE 00 00')).match), + +# ('UTF-32-2143', re.compile( +# hex2re('00 00 FF FE')).match), + +# ('UTF-32-3412', re.compile( +# hex2re('FE FF 00 00')).match), + + ('UTF-16-BE', re.compile( + hex2re('FE FF')).match), + + ('UTF-16-LE', re.compile( + hex2re('FF FE')).match), + + +# Some of there are supported by Python, but I didn’t bother. +# You know the story with patches ... + +# # as specified, transcoded from EBCDIC to ASCII +# ('as_specified-EBCDIC', re.compile( +# hex2re('7C 83 88 81 99 A2 85 A3 40 7F') +# + b'([^\x7F]*?)' +# + hex2re('7F 5E')).match), + +# # as specified, transcoded from IBM1026 to ASCII +# ('as_specified-IBM1026', re.compile( +# hex2re('AE 83 88 81 99 A2 85 A3 40 FC') +# + b'([^\xFC]*?)' +# + hex2re('FC 5E')).match), + +# # as specified, transcoded from GSM 03.38 to ASCII +# ('as_specified-GSM_03.38', re.compile( +# hex2re('00 63 68 61 72 73 65 74 20 22') +# + b'([^\x22]*?)' +# + hex2re('22 3B')).match), +] diff --git a/ebook_converter/tinycss/fonts3.py b/ebook_converter/tinycss/fonts3.py new file mode 100644 index 0000000..60030b7 --- /dev/null +++ b/ebook_converter/tinycss/fonts3.py @@ -0,0 +1,225 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2014, Kovid Goyal ' + + +import re +from polyglot.builtins import map +from tinycss.css21 import CSS21Parser, ParseError +from .tokenizer import tokenize_grouped + + +def parse_font_family_tokens(tokens): + families = [] + current_family = '' + + def commit(): + val = current_family.strip() + if val: + families.append(val) + + for token in tokens: + if token.type == 'STRING': + if current_family: + commit() + current_family = token.value + elif token.type == 'DELIM': + if token.value == ',': + if current_family: + commit() + current_family = '' + elif token.type == 'IDENT': + current_family += ' ' + token.value + if current_family: + commit() + return families + + +def parse_font_family(css_string): + return parse_font_family_tokens(tokenize_grouped(type('')(css_string).strip())) + + +def serialize_single_font_family(x): + xl = x.lower() + if xl in GENERIC_FAMILIES: + if xl == 'sansserif': + xl = 'sans-serif' + return xl + if SIMPLE_NAME_PAT.match(x) is not None and not x.lower().startswith('and'): + # css_parser dies if a font name starts with and + return x + return '"%s"' % x.replace('"', r'\"') + + +def serialize_font_family(families): + return ', '.join(map(serialize_single_font_family, families)) + + +GLOBAL_IDENTS = frozenset('inherit initial unset normal'.split()) +STYLE_IDENTS = frozenset('italic oblique'.split()) +VARIANT_IDENTS = frozenset(('small-caps',)) +WEIGHT_IDENTS = frozenset('bold bolder lighter'.split()) +STRETCH_IDENTS = frozenset('ultra-condensed extra-condensed condensed semi-condensed semi-expanded expanded extra-expanded ultra-expanded'.split()) +BEFORE_SIZE_IDENTS = STYLE_IDENTS | VARIANT_IDENTS | WEIGHT_IDENTS | STRETCH_IDENTS +SIZE_IDENTS = frozenset('xx-small x-small small medium large x-large xx-large larger smaller'.split()) +WEIGHT_SIZES = frozenset(map(int, '100 200 300 400 500 600 700 800 900'.split())) +LEGACY_FONT_SPEC = frozenset('caption icon menu message-box small-caption status-bar'.split()) +GENERIC_FAMILIES = frozenset('serif sans-serif sansserif cursive fantasy monospace'.split()) +SIMPLE_NAME_PAT = re.compile(r'[a-zA-Z][a-zA-Z0-9_-]*$') + + +def serialize_font(font_dict): + ans = [] + for x in 'style variant weight stretch'.split(): + val = font_dict.get('font-' + x) + if val is not None: + ans.append(val) + val = font_dict.get('font-size') + if val is not None: + fs = val + val = font_dict.get('line-height') + if val is not None: + fs += '/' + val + ans.append(fs) + val = font_dict.get('font-family') + if val: + ans.append(serialize_font_family(val)) + return ' '.join(ans) + + +def parse_font(css_string): + # See https://www.w3.org/TR/css-fonts-3/#font-prop + style = variant = weight = stretch = size = height = None + tokens = list(reversed(tuple(tokenize_grouped(type('')(css_string).strip())))) + if tokens and tokens[-1].value in LEGACY_FONT_SPEC: + return {'font-family':['sans-serif']} + while tokens: + tok = tokens.pop() + if tok.type == 'STRING': + tokens.append(tok) + break + if tok.type == 'INTEGER': + if size is None: + if weight is None and tok.value in WEIGHT_SIZES: + weight = tok.as_css() + continue + break + if height is None: + height = tok.as_css() + break + break + if tok.type == 'NUMBER': + if size is not None and height is None: + height = tok.as_css() + break + if tok.type == 'DELIM': + if tok.value == '/' and size is not None and height is None: + continue + break + if tok.type in ('DIMENSION', 'PERCENTAGE'): + if size is None: + size = tok.as_css() + continue + if height is None: + height = tok.as_css() + break + if tok.type == 'IDENT': + if tok.value in GLOBAL_IDENTS: + if size is not None: + if height is None: + height = tok.value + else: + tokens.append(tok) + break + if style is None: + style = tok.value + elif variant is None: + variant = tok.value + elif weight is None: + weight = tok.value + elif stretch is None: + stretch = tok.value + elif size is None: + size = tok.value + elif height is None: + height = tok.value + break + else: + tokens.append(tok) + break + continue + if tok.value in BEFORE_SIZE_IDENTS: + if size is not None: + break + if tok.value in STYLE_IDENTS: + style = tok.value + elif tok.value in VARIANT_IDENTS: + variant = tok.value + elif tok.value in WEIGHT_IDENTS: + weight = tok.value + elif tok.value in STRETCH_IDENTS: + stretch = tok.value + elif tok.value in SIZE_IDENTS: + size = tok.value + else: + tokens.append(tok) + break + families = parse_font_family_tokens(reversed(tokens)) + ans = {} + if style is not None: + ans['font-style'] = style + if variant is not None: + ans['font-variant'] = variant + if weight is not None: + ans['font-weight'] = weight + if stretch is not None: + ans['font-stretch'] = stretch + if size is not None: + ans['font-size'] = size + if height is not None: + ans['line-height'] = height + if families: + ans['font-family'] = families + return ans + + +class FontFaceRule(object): + + at_keyword = '@font-face' + __slots__ = 'declarations', 'line', 'column' + + def __init__(self, declarations, line, column): + self.declarations = declarations + self.line = line + self.column = column + + def __repr__(self): + return ('<{0.__class__.__name__} at {0.line}:{0.column}>' + .format(self)) + + +class CSSFonts3Parser(CSS21Parser): + + ''' Parse @font-face rules from the CSS 3 fonts module ''' + + ALLOWED_CONTEXTS_FOR_FONT_FACE = {'stylesheet', '@media', '@page'} + + def __init__(self): + super(CSSFonts3Parser, self).__init__() + self.at_parsers['@font-face'] = self.parse_font_face_rule + + def parse_font_face_rule(self, rule, previous_rules, errors, context): + if context not in self.ALLOWED_CONTEXTS_FOR_FONT_FACE: + raise ParseError(rule, + '@font-face rule not allowed in ' + context) + if rule.body is None: + raise ParseError(rule, + 'invalid {0} rule: missing block'.format(rule.at_keyword)) + if rule.head: + raise ParseError(rule, '{0} rule is not allowed to have content before the descriptor declaration'.format(rule.at_keyword)) + declarations, decerrors = self.parse_declaration_list(rule.body) + errors.extend(decerrors) + return FontFaceRule(declarations, rule.line, rule.column) diff --git a/ebook_converter/tinycss/media3.py b/ebook_converter/tinycss/media3.py new file mode 100644 index 0000000..3d4ebe1 --- /dev/null +++ b/ebook_converter/tinycss/media3.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2014, Kovid Goyal ' + +from tinycss.css21 import CSS21Parser +from tinycss.parsing import remove_whitespace, split_on_comma, ParseError +from polyglot.builtins import error_message + + +class MediaQuery(object): + + __slots__ = 'media_type', 'expressions', 'negated' + + def __init__(self, media_type='all', expressions=(), negated=False): + self.media_type = media_type + self.expressions = expressions + self.negated = negated + + def __repr__(self): + return '' % ( + self.media_type, self.negated, self.expressions) + + def __eq__(self, other): + return self.media_type == getattr(other, 'media_type', None) and \ + self.negated == getattr(other, 'negated', None) and \ + self.expressions == getattr(other, 'expressions', None) + + +class MalformedExpression(Exception): + + def __init__(self, tok, msg): + Exception.__init__(self, msg) + self.tok = tok + + +class CSSMedia3Parser(CSS21Parser): + + ''' Parse media queries as defined by the CSS 3 media module ''' + + def parse_media(self, tokens, errors): + if not tokens: + return [MediaQuery('all')] + queries = [] + + for part in split_on_comma(remove_whitespace(tokens)): + negated = False + media_type = None + expressions = [] + try: + for i, tok in enumerate(part): + if i == 0 and tok.type == 'IDENT': + val = tok.value.lower() + if val == 'only': + continue # ignore leading ONLY + if val == 'not': + negated = True + continue + if media_type is None and tok.type == 'IDENT': + media_type = tok.value + continue + elif media_type is None: + media_type = 'all' + + if tok.type == 'IDENT' and tok.value.lower() == 'and': + continue + if not tok.is_container: + raise MalformedExpression(tok, 'expected a media expression not a %s' % tok.type) + if tok.type != '(': + raise MalformedExpression(tok, 'media expressions must be in parentheses not %s' % tok.type) + content = remove_whitespace(tok.content) + if len(content) == 0: + raise MalformedExpression(tok, 'media expressions cannot be empty') + if content[0].type != 'IDENT': + raise MalformedExpression(content[0], 'expected a media feature not a %s' % tok.type) + media_feature, expr = content[0].value, None + if len(content) > 1: + if len(content) < 3: + raise MalformedExpression(content[1], 'malformed media feature definition') + if content[1].type != ':': + raise MalformedExpression(content[1], 'expected a :') + expr = content[2:] + if len(expr) == 1: + expr = expr[0] + elif len(expr) == 3 and (expr[0].type, expr[1].type, expr[1].value, expr[2].type) == ( + 'INTEGER', 'DELIM', '/', 'INTEGER'): + # This should really be moved into token_data, but + # since RATIO is not part of CSS 2.1 and does not + # occur anywhere else, we special case it here. + r = expr[0] + r.value = (expr[0].value, expr[2].value) + r.type = 'RATIO' + r._as_css = expr[0]._as_css + expr[1]._as_css + expr[2]._as_css + expr = r + else: + raise MalformedExpression(expr[0], 'malformed media feature definition') + + expressions.append((media_feature, expr)) + except MalformedExpression as err: + errors.append(ParseError(err.tok, error_message(err))) + media_type, negated, expressions = 'all', True, () + queries.append(MediaQuery(media_type or 'all', expressions=tuple(expressions), negated=negated)) + + return queries diff --git a/ebook_converter/tinycss/page3.py b/ebook_converter/tinycss/page3.py new file mode 100644 index 0000000..8a4e150 --- /dev/null +++ b/ebook_converter/tinycss/page3.py @@ -0,0 +1,163 @@ +# coding: utf8 +""" + tinycss.page3 + ------------------ + + Support for CSS 3 Paged Media syntax: + http://dev.w3.org/csswg/css3-page/ + + Adds support for named page selectors and margin rules. + + :copyright: (c) 2012 by Simon Sapin. + :license: BSD, see LICENSE for more details. +""" + +from __future__ import unicode_literals, division +from .css21 import CSS21Parser, ParseError + + +class MarginRule(object): + """A parsed at-rule for margin box. + + .. attribute:: at_keyword + + One of the 16 following strings: + + * ``@top-left-corner`` + * ``@top-left`` + * ``@top-center`` + * ``@top-right`` + * ``@top-right-corner`` + * ``@bottom-left-corner`` + * ``@bottom-left`` + * ``@bottom-center`` + * ``@bottom-right`` + * ``@bottom-right-corner`` + * ``@left-top`` + * ``@left-middle`` + * ``@left-bottom`` + * ``@right-top`` + * ``@right-middle`` + * ``@right-bottom`` + + .. attribute:: declarations + + A list of :class:`~.css21.Declaration` objects. + + .. attribute:: line + + Source line where this was read. + + .. attribute:: column + + Source column where this was read. + + """ + + __slots__ = 'at_keyword', 'declarations', 'line', 'column' + + def __init__(self, at_keyword, declarations, line, column): + self.at_keyword = at_keyword + self.declarations = declarations + self.line = line + self.column = column + + +class CSSPage3Parser(CSS21Parser): + """Extend :class:`~.css21.CSS21Parser` for `CSS 3 Paged Media`_ syntax. + + .. _CSS 3 Paged Media: http://dev.w3.org/csswg/css3-page/ + + Compared to CSS 2.1, the ``at_rules`` and ``selector`` attributes of + :class:`~.css21.PageRule` objects are modified: + + * ``at_rules`` is not always empty, it is a list of :class:`MarginRule` + objects. + + * ``selector``, instead of a single string, is a tuple of the page name + and the pseudo class. Each of these may be a ``None`` or a string. + + +--------------------------+------------------------+ + | CSS | Parsed selectors | + +==========================+========================+ + | .. code-block:: css | .. code-block:: python | + | | | + | @page {} | (None, None) | + | @page :first {} | (None, 'first') | + | @page chapter {} | ('chapter', None) | + | @page table:right {} | ('table', 'right') | + +--------------------------+------------------------+ + + """ + + PAGE_MARGIN_AT_KEYWORDS = ( + '@top-left-corner', + '@top-left', + '@top-center', + '@top-right', + '@top-right-corner', + '@bottom-left-corner', + '@bottom-left', + '@bottom-center', + '@bottom-right', + '@bottom-right-corner', + '@left-top', + '@left-middle', + '@left-bottom', + '@right-top', + '@right-middle', + '@right-bottom', + ) + + def __init__(self): + super(CSSPage3Parser, self).__init__() + for x in self.PAGE_MARGIN_AT_KEYWORDS: + self.at_parsers[x] = self.parse_page_margin_rule + + def parse_page_margin_rule(self, rule, previous_rules, errors, context): + if context != '@page': + raise ParseError(rule, + '%s rule not allowed in %s' % (rule.at_keyword, context)) + if rule.head: + raise ParseError(rule.head[0], + 'unexpected %s token in %s rule header' + % (rule.head[0].type, rule.at_keyword)) + declarations, body_errors = self.parse_declaration_list(rule.body) + errors.extend(body_errors) + return MarginRule(rule.at_keyword, declarations, + rule.line, rule.column) + + def parse_page_selector(self, head): + """Parse an @page selector. + + :param head: + The ``head`` attribute of an unparsed :class:`AtRule`. + :returns: + A page selector. For CSS 2.1, this is 'first', 'left', 'right' + or None. 'blank' is added by GCPM. + :raises: + :class`~parsing.ParseError` on invalid selectors + + """ + if not head: + return (None, None), (0, 0, 0) + if head[0].type == 'IDENT': + name = head.pop(0).value + while head and head[0].type == 'S': + head.pop(0) + if not head: + return (name, None), (1, 0, 0) + name_specificity = (1,) + else: + name = None + name_specificity = (0,) + if (len(head) == 2 and head[0].type == ':' + and head[1].type == 'IDENT'): + pseudo_class = head[1].value + specificity = { + 'first': (1, 0), 'blank': (1, 0), + 'left': (0, 1), 'right': (0, 1), + }.get(pseudo_class) + if specificity: + return (name, pseudo_class), (name_specificity + specificity) + raise ParseError(head[0], 'invalid @page selector') diff --git a/ebook_converter/tinycss/parsing.py b/ebook_converter/tinycss/parsing.py new file mode 100644 index 0000000..86e93c0 --- /dev/null +++ b/ebook_converter/tinycss/parsing.py @@ -0,0 +1,165 @@ +# coding: utf8 +""" + tinycss.parsing + --------------- + + Utilities for parsing lists of tokens. + + :copyright: (c) 2012 by Simon Sapin. + :license: BSD, see LICENSE for more details. +""" + +from __future__ import unicode_literals + + +# TODO: unit tests + +def split_on_comma(tokens): + """Split a list of tokens on commas, ie ``,`` DELIM tokens. + + Only "top-level" comma tokens are splitting points, not commas inside a + function or other :class:`ContainerToken`. + + :param tokens: + An iterable of :class:`~.token_data.Token` or + :class:`~.token_data.ContainerToken`. + :returns: + A list of lists of tokens + + """ + parts = [] + this_part = [] + for token in tokens: + if token.type == 'DELIM' and token.value == ',': + parts.append(this_part) + this_part = [] + else: + this_part.append(token) + parts.append(this_part) + return parts + + +def strip_whitespace(tokens): + """Remove whitespace at the beggining and end of a token list. + + Whitespace tokens in-between other tokens in the list are preserved. + + :param tokens: + A list of :class:`~.token_data.Token` or + :class:`~.token_data.ContainerToken`. + :return: + A new sub-sequence of the list. + + """ + for i, token in enumerate(tokens): + if token.type != 'S': + break + else: + return [] # only whitespace + tokens = tokens[i:] + while tokens and tokens[-1].type == 'S': + tokens.pop() + return tokens + + +def remove_whitespace(tokens): + """Remove any top-level whitespace in a token list. + + Whitespace tokens inside recursive :class:`~.token_data.ContainerToken` + are preserved. + + :param tokens: + A list of :class:`~.token_data.Token` or + :class:`~.token_data.ContainerToken`. + :return: + A new sub-sequence of the list. + + """ + return [token for token in tokens if token.type != 'S'] + + +def validate_value(tokens): + """Validate a property value. + + :param tokens: + an iterable of tokens + :raises: + :class:`ParseError` if there is any invalid token for the 'value' + production of the core grammar. + + """ + for token in tokens: + type_ = token.type + if type_ == '{': + validate_block(token.content, 'property value') + else: + validate_any(token, 'property value') + +def validate_block(tokens, context): + """ + :raises: + :class:`ParseError` if there is any invalid token for the 'block' + production of the core grammar. + :param tokens: an iterable of tokens + :param context: a string for the 'unexpected in ...' message + + """ + for token in tokens: + type_ = token.type + if type_ == '{': + validate_block(token.content, context) + elif type_ not in (';', 'ATKEYWORD'): + validate_any(token, context) + + +def validate_any(token, context): + """ + :raises: + :class:`ParseError` if this is an invalid token for the + 'any' production of the core grammar. + :param token: a single token + :param context: a string for the 'unexpected in ...' message + + """ + type_ = token.type + if type_ in ('FUNCTION', '(', '['): + for token in token.content: + validate_any(token, type_) + elif type_ not in ('S', 'IDENT', 'DIMENSION', 'PERCENTAGE', 'NUMBER', + 'INTEGER', 'URI', 'DELIM', 'STRING', 'HASH', ':', + 'UNICODE-RANGE'): + if type_ in ('}', ')', ']'): + adjective = 'unmatched' + else: + adjective = 'unexpected' + raise ParseError(token, + '{0} {1} token in {2}'.format(adjective, type_, context)) + + +class ParseError(ValueError): + """Details about a CSS syntax error. Usually indicates that something + (a rule or a declaration) was ignored and will not appear as a parsed + object. + + This exception is typically logged in a list rather than being propagated + to the user API. + + .. attribute:: line + + Source line where the error occured. + + .. attribute:: column + + Column in the source line where the error occured. + + .. attribute:: reason + + What happend (a string). + + """ + def __init__(self, subject, reason): + self.line = subject.line + self.column = subject.column + self.reason = reason + super(ParseError, self).__init__( + 'Parse error at {0.line}:{0.column}, {0.reason}'.format(self)) diff --git a/ebook_converter/tinycss/tests/__init__.py b/ebook_converter/tinycss/tests/__init__.py new file mode 100644 index 0000000..991303e --- /dev/null +++ b/ebook_converter/tinycss/tests/__init__.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2014, Kovid Goyal ' + +import unittest + + +def jsonify(tokens): + """Turn tokens into "JSON-compatible" data structures.""" + for token in tokens: + if token.type == 'FUNCTION': + yield (token.type, token.function_name, + list(jsonify(token.content))) + elif token.is_container: + yield token.type, list(jsonify(token.content)) + else: + yield token.type, token.value + + +class BaseTest(unittest.TestCase): + + longMessage = True + maxDiff = None + ae = unittest.TestCase.assertEqual + + def assert_errors(self, errors, expected_errors): + """Test not complete error messages but only substrings.""" + self.ae(len(errors), len(expected_errors)) + for error, expected in zip(errors, expected_errors): + self.assertIn(expected, type(u'')(error)) + + def jsonify_declarations(self, rule): + return [(decl.name, list(jsonify(decl.value))) + for decl in rule.declarations] diff --git a/ebook_converter/tinycss/tests/color3.py b/ebook_converter/tinycss/tests/color3.py new file mode 100644 index 0000000..036c193 --- /dev/null +++ b/ebook_converter/tinycss/tests/color3.py @@ -0,0 +1,198 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2014, Kovid Goyal ' + +from tinycss.color3 import parse_color_string, hsl_to_rgb +from tinycss.tests import BaseTest + + +class TestColor3(BaseTest): + + def test_color_parsing(self): + for css_source, expected_result in [ + ('', None), + (' /* hey */\n', None), + ('4', None), + ('top', None), + ('/**/transparent', (0, 0, 0, 0)), + ('transparent', (0, 0, 0, 0)), + (' transparent\n', (0, 0, 0, 0)), + ('TransParent', (0, 0, 0, 0)), + ('currentColor', 'currentColor'), + ('CURRENTcolor', 'currentColor'), + ('current_Color', None), + + ('black', (0, 0, 0, 1)), + ('white', (1, 1, 1, 1)), + ('fuchsia', (1, 0, 1, 1)), + ('cyan', (0, 1, 1, 1)), + ('CyAn', (0, 1, 1, 1)), + ('darkkhaki', (189 / 255., 183 / 255., 107 / 255., 1)), + + ('#', None), + ('#f', None), + ('#ff', None), + ('#fff', (1, 1, 1, 1)), + ('#ffg', None), + ('#ffff', None), + ('#fffff', None), + ('#ffffff', (1, 1, 1, 1)), + ('#fffffg', None), + ('#fffffff', None), + ('#ffffffff', None), + ('#fffffffff', None), + + ('#cba987', (203 / 255., 169 / 255., 135 / 255., 1)), + ('#CbA987', (203 / 255., 169 / 255., 135 / 255., 1)), + ('#1122aA', (17 / 255., 34 / 255., 170 / 255., 1)), + ('#12a', (17 / 255., 34 / 255., 170 / 255., 1)), + + ('rgb(203, 169, 135)', (203 / 255., 169 / 255., 135 / 255., 1)), + ('RGB(255, 255, 255)', (1, 1, 1, 1)), + ('rgB(0, 0, 0)', (0, 0, 0, 1)), + ('rgB(0, 51, 255)', (0, .2, 1, 1)), + ('rgb(0,51,255)', (0, .2, 1, 1)), + ('rgb(0\t, 51 ,255)', (0, .2, 1, 1)), + ('rgb(/* R */0, /* G */51, /* B */255)', (0, .2, 1, 1)), + ('rgb(-51, 306, 0)', (-.2, 1.2, 0, 1)), # out of 0..1 is allowed + + ('rgb(42%, 3%, 50%)', (.42, .03, .5, 1)), + ('RGB(100%, 100%, 100%)', (1, 1, 1, 1)), + ('rgB(0%, 0%, 0%)', (0, 0, 0, 1)), + ('rgB(10%, 20%, 30%)', (.1, .2, .3, 1)), + ('rgb(10%,20%,30%)', (.1, .2, .3, 1)), + ('rgb(10%\t, 20% ,30%)', (.1, .2, .3, 1)), + ('rgb(/* R */10%, /* G */20%, /* B */30%)', (.1, .2, .3, 1)), + ('rgb(-12%, 110%, 1400%)', (-.12, 1.1, 14, 1)), # out of 0..1 is allowed + + ('rgb(10%, 50%, 0)', None), + ('rgb(255, 50%, 0%)', None), + ('rgb(0, 0 0)', None), + ('rgb(0, 0, 0deg)', None), + ('rgb(0, 0, light)', None), + ('rgb()', None), + ('rgb(0)', None), + ('rgb(0, 0)', None), + ('rgb(0, 0, 0, 0)', None), + ('rgb(0%)', None), + ('rgb(0%, 0%)', None), + ('rgb(0%, 0%, 0%, 0%)', None), + ('rgb(0%, 0%, 0%, 0)', None), + + ('rgba(0, 0, 0, 0)', (0, 0, 0, 0)), + ('rgba(203, 169, 135, 0.3)', (203 / 255., 169 / 255., 135 / 255., 0.3)), + ('RGBA(255, 255, 255, 0)', (1, 1, 1, 0)), + ('rgBA(0, 51, 255, 1)', (0, 0.2, 1, 1)), + ('rgba(0, 51, 255, 1.1)', (0, 0.2, 1, 1)), + ('rgba(0, 51, 255, 37)', (0, 0.2, 1, 1)), + ('rgba(0, 51, 255, 0.42)', (0, 0.2, 1, 0.42)), + ('rgba(0, 51, 255, 0)', (0, 0.2, 1, 0)), + ('rgba(0, 51, 255, -0.1)', (0, 0.2, 1, 0)), + ('rgba(0, 51, 255, -139)', (0, 0.2, 1, 0)), + + ('rgba(42%, 3%, 50%, 0.3)', (.42, .03, .5, 0.3)), + ('RGBA(100%, 100%, 100%, 0)', (1, 1, 1, 0)), + ('rgBA(0%, 20%, 100%, 1)', (0, 0.2, 1, 1)), + ('rgba(0%, 20%, 100%, 1.1)', (0, 0.2, 1, 1)), + ('rgba(0%, 20%, 100%, 37)', (0, 0.2, 1, 1)), + ('rgba(0%, 20%, 100%, 0.42)', (0, 0.2, 1, 0.42)), + ('rgba(0%, 20%, 100%, 0)', (0, 0.2, 1, 0)), + ('rgba(0%, 20%, 100%, -0.1)', (0, 0.2, 1, 0)), + ('rgba(0%, 20%, 100%, -139)', (0, 0.2, 1, 0)), + + ('rgba(255, 255, 255, 0%)', None), + ('rgba(10%, 50%, 0, 1)', None), + ('rgba(255, 50%, 0%, 1)', None), + ('rgba(0, 0, 0 0)', None), + ('rgba(0, 0, 0, 0deg)', None), + ('rgba(0, 0, 0, light)', None), + ('rgba()', None), + ('rgba(0)', None), + ('rgba(0, 0, 0)', None), + ('rgba(0, 0, 0, 0, 0)', None), + ('rgba(0%)', None), + ('rgba(0%, 0%)', None), + ('rgba(0%, 0%, 0%)', None), + ('rgba(0%, 0%, 0%, 0%)', None), + ('rgba(0%, 0%, 0%, 0%, 0%)', None), + + ('HSL(0, 0%, 0%)', (0, 0, 0, 1)), + ('hsL(0, 100%, 50%)', (1, 0, 0, 1)), + ('hsl(60, 100%, 37.5%)', (0.75, 0.75, 0, 1)), + ('hsl(780, 100%, 37.5%)', (0.75, 0.75, 0, 1)), + ('hsl(-300, 100%, 37.5%)', (0.75, 0.75, 0, 1)), + ('hsl(300, 50%, 50%)', (0.75, 0.25, 0.75, 1)), + + ('hsl(10, 50%, 0)', None), + ('hsl(50%, 50%, 0%)', None), + ('hsl(0, 0% 0%)', None), + ('hsl(30deg, 100%, 100%)', None), + ('hsl(0, 0%, light)', None), + ('hsl()', None), + ('hsl(0)', None), + ('hsl(0, 0%)', None), + ('hsl(0, 0%, 0%, 0%)', None), + + ('HSLA(-300, 100%, 37.5%, 1)', (0.75, 0.75, 0, 1)), + ('hsLA(-300, 100%, 37.5%, 12)', (0.75, 0.75, 0, 1)), + ('hsla(-300, 100%, 37.5%, 0.2)', (0.75, 0.75, 0, .2)), + ('hsla(-300, 100%, 37.5%, 0)', (0.75, 0.75, 0, 0)), + ('hsla(-300, 100%, 37.5%, -3)', (0.75, 0.75, 0, 0)), + + ('hsla(10, 50%, 0, 1)', None), + ('hsla(50%, 50%, 0%, 1)', None), + ('hsla(0, 0% 0%, 1)', None), + ('hsla(30deg, 100%, 100%, 1)', None), + ('hsla(0, 0%, light, 1)', None), + ('hsla()', None), + ('hsla(0)', None), + ('hsla(0, 0%)', None), + ('hsla(0, 0%, 0%, 50%)', None), + ('hsla(0, 0%, 0%, 1, 0%)', None), + + ('cmyk(0, 0, 0, 0)', None), + ]: + result = parse_color_string(css_source) + if isinstance(result, tuple): + for got, expected in zip(result, expected_result): + # Compensate for floating point errors: + self.assertLess(abs(got - expected), 1e-10) + for i, attr in enumerate(['red', 'green', 'blue', 'alpha']): + self.ae(getattr(result, attr), result[i]) + else: + self.ae(result, expected_result) + + def test_hsl(self): + for hsl, expected_rgb in [ + # http://en.wikipedia.org/wiki/HSL_and_HSV#Examples + ((0, 0, 100), (1, 1, 1)), + ((127, 0, 100), (1, 1, 1)), + ((0, 0, 50), (0.5, 0.5, 0.5)), + ((127, 0, 50), (0.5, 0.5, 0.5)), + ((0, 0, 0), (0, 0, 0)), + ((127, 0, 0), (0, 0, 0)), + ((0, 100, 50), (1, 0, 0)), + ((60, 100, 37.5), (0.75, 0.75, 0)), + ((780, 100, 37.5), (0.75, 0.75, 0)), + ((-300, 100, 37.5), (0.75, 0.75, 0)), + ((120, 100, 25), (0, 0.5, 0)), + ((180, 100, 75), (0.5, 1, 1)), + ((240, 100, 75), (0.5, 0.5, 1)), + ((300, 50, 50), (0.75, 0.25, 0.75)), + ((61.8, 63.8, 39.3), (0.628, 0.643, 0.142)), + ((251.1, 83.2, 51.1), (0.255, 0.104, 0.918)), + ((134.9, 70.7, 39.6), (0.116, 0.675, 0.255)), + ((49.5, 89.3, 49.7), (0.941, 0.785, 0.053)), + ((283.7, 77.5, 54.2), (0.704, 0.187, 0.897)), + ((14.3, 81.7, 62.4), (0.931, 0.463, 0.316)), + ((56.9, 99.1, 76.5), (0.998, 0.974, 0.532)), + ((162.4, 77.9, 44.7), (0.099, 0.795, 0.591)), + ((248.3, 60.1, 37.3), (0.211, 0.149, 0.597)), + ((240.5, 29, 60.7), (0.495, 0.493, 0.721)), + ]: + for got, expected in zip(hsl_to_rgb(*hsl), expected_rgb): + # Compensate for floating point errors and Wikipedia’s rounding: + self.assertLess(abs(got - expected), 0.001) diff --git a/ebook_converter/tinycss/tests/css21.py b/ebook_converter/tinycss/tests/css21.py new file mode 100644 index 0000000..571d37a --- /dev/null +++ b/ebook_converter/tinycss/tests/css21.py @@ -0,0 +1,336 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2014, Kovid Goyal ' + +import io +import os +import tempfile + +from tinycss.css21 import CSS21Parser +from tinycss.tests.tokenizing import jsonify +from tinycss.tests import BaseTest + +class CoreParser(CSS21Parser): + """A parser that always accepts unparsed at-rules.""" + def parse_at_rule(self, rule, stylesheet_rules, errors, context): + return rule + +def parse_bytes(css_bytes, kwargs): + return CSS21Parser().parse_stylesheet_bytes(css_bytes, **kwargs) + + +def parse_bytesio_file(css_bytes, kwargs): + css_file = io.BytesIO(css_bytes) + return CSS21Parser().parse_stylesheet_file(css_file, **kwargs) + + +def parse_filename(css_bytes, kwargs): + css_file = tempfile.NamedTemporaryFile(delete=False) + try: + css_file.write(css_bytes) + # Windows can not open the filename a second time while + # it is still open for writing. + css_file.close() + return CSS21Parser().parse_stylesheet_file(css_file.name, **kwargs) + finally: + os.remove(css_file.name) + + +class TestCSS21(BaseTest): + + def test_bytes(self): + for (css_bytes, kwargs, expected_result, parse) in [ + params + (parse,) + for parse in [parse_bytes, parse_bytesio_file, parse_filename] + for params in [ + ('@import "é";'.encode('utf8'), {}, 'é'), + ('@import "é";'.encode('utf16'), {}, 'é'), # with a BOM + ('@import "é";'.encode('latin1'), {}, 'é'), + ('@import "£";'.encode('Shift-JIS'), {}, '\x81\x92'), # latin1 mojibake + ('@charset "Shift-JIS";@import "£";'.encode('Shift-JIS'), {}, '£'), + (' @charset "Shift-JIS";@import "£";'.encode('Shift-JIS'), {}, + '\x81\x92'), + ('@import "£";'.encode('Shift-JIS'), + {'document_encoding': 'Shift-JIS'}, '£'), + ('@import "£";'.encode('Shift-JIS'), + {'document_encoding': 'utf8'}, '\x81\x92'), + ('@charset "utf8"; @import "£";'.encode('utf8'), + {'document_encoding': 'latin1'}, '£'), + # Mojibake yay! + (' @charset "utf8"; @import "é";'.encode('utf8'), + {'document_encoding': 'latin1'}, 'é'), + ('@import "é";'.encode('utf8'), {'document_encoding': 'latin1'}, 'é'), + ] + ]: + stylesheet = parse(css_bytes, kwargs) + self.ae(stylesheet.rules[0].at_keyword, '@import') + self.ae(stylesheet.rules[0].uri, expected_result) + + def test_at_rules(self): + for (css_source, expected_rules, expected_errors) in [ + (' /* hey */\n', 0, []), + ('foo {}', 1, []), + ('foo{} @lipsum{} bar{}', 2, + ['unknown at-rule in stylesheet context: @lipsum']), + ('@charset "ascii"; foo {}', 1, []), + (' @charset "ascii"; foo {}', 1, ['mis-placed or malformed @charset rule']), + ('@charset ascii; foo {}', 1, ['mis-placed or malformed @charset rule']), + ('foo {} @charset "ascii";', 1, ['mis-placed or malformed @charset rule']), + ]: + # Pass 'encoding' to allow @charset + stylesheet = CSS21Parser().parse_stylesheet(css_source, encoding='utf8') + self.assert_errors(stylesheet.errors, expected_errors) + self.ae(len(stylesheet.rules), expected_rules) + + def test_core_parser(self): + for (css_source, expected_rules, expected_errors) in [ + (' /* hey */\n', [], []), + + ('foo{} /* hey */\n@bar;@baz{}', + [('foo', []), ('@bar', [], None), ('@baz', [], [])], []), + + ('@import "foo.css"/**/;', [ + ('@import', [('STRING', 'foo.css')], None)], []), + + ('@import "foo.css"/**/', [ + ('@import', [('STRING', 'foo.css')], None)], []), + + ('@import "foo.css', [ + ('@import', [('STRING', 'foo.css')], None)], []), + + ('{}', [], ['empty selector']), + + ('a{b:4}', [('a', [('b', [('INTEGER', 4)])])], []), + + ('@page {\t b: 4; @margin}', [('@page', [], [ + ('S', '\t '), ('IDENT', 'b'), (':', ':'), ('S', ' '), ('INTEGER', 4), + (';', ';'), ('S', ' '), ('ATKEYWORD', '@margin'), + ])], []), + + ('foo', [], ['no declaration block found']), + + ('foo @page {} bar {}', [('bar', [])], + ['unexpected ATKEYWORD token in selector']), + + ('foo { content: "unclosed string;\n color:red; ; margin/**/\n: 2cm; }', + [('foo', [('margin', [('DIMENSION', 2)])])], + ['unexpected BAD_STRING token in property value']), + + ('foo { 4px; bar: 12% }', + [('foo', [('bar', [('PERCENTAGE', 12)])])], + ['expected a property name, got DIMENSION']), + + ('foo { bar! 3cm auto ; baz: 7px }', + [('foo', [('baz', [('DIMENSION', 7)])])], + ["expected ':', got DELIM"]), + + ('foo { bar ; baz: {("}"/* comment */) {0@fizz}} }', + [('foo', [('baz', [('{', [ + ('(', [('STRING', '}')]), ('S', ' '), + ('{', [('INTEGER', 0), ('ATKEYWORD', '@fizz')]) + ])])])], + ["expected ':'"]), + + ('foo { bar: ; baz: not(z) }', + [('foo', [('baz', [('FUNCTION', 'not', [('IDENT', 'z')])])])], + ['expected a property value']), + + ('foo { bar: (]) ; baz: U+20 }', + [('foo', [('baz', [('UNICODE-RANGE', 'U+20')])])], + ['unmatched ] token in (']), + ]: + stylesheet = CoreParser().parse_stylesheet(css_source) + self.assert_errors(stylesheet.errors, expected_errors) + result = [ + (rule.at_keyword, list(jsonify(rule.head)), + list(jsonify(rule.body)) + if rule.body is not None else None) + if rule.at_keyword else + (rule.selector.as_css(), [ + (decl.name, list(jsonify(decl.value))) + for decl in rule.declarations]) + for rule in stylesheet.rules + ] + self.ae(result, expected_rules) + + def test_parse_style_attr(self): + for (css_source, expected_declarations, expected_errors) in [ + (' /* hey */\n', [], []), + + ('b:4', [('b', [('INTEGER', 4)])], []), + + ('{b:4}', [], ['expected a property name, got {']), + + ('b:4} c:3', [], ['unmatched } token in property value']), + + (' 4px; bar: 12% ', + [('bar', [('PERCENTAGE', 12)])], + ['expected a property name, got DIMENSION']), + + ('bar! 3cm auto ; baz: 7px', + [('baz', [('DIMENSION', 7)])], + ["expected ':', got DELIM"]), + + ('foo; bar ; baz: {("}"/* comment */) {0@fizz}}', + [('baz', [('{', [ + ('(', [('STRING', '}')]), ('S', ' '), + ('{', [('INTEGER', 0), ('ATKEYWORD', '@fizz')]) + ])])], + ["expected ':'", "expected ':'"]), + + ('bar: ; baz: not(z)', + [('baz', [('FUNCTION', 'not', [('IDENT', 'z')])])], + ['expected a property value']), + + ('bar: (]) ; baz: U+20', + [('baz', [('UNICODE-RANGE', 'U+20')])], + ['unmatched ] token in (']), + ]: + declarations, errors = CSS21Parser().parse_style_attr(css_source) + self.assert_errors(errors, expected_errors) + result = [(decl.name, list(jsonify(decl.value))) + for decl in declarations] + self.ae(result, expected_declarations) + + def test_important(self): + for (css_source, expected_declarations, expected_errors) in [ + (' /* hey */\n', [], []), + + ('a:1; b:2', + [('a', [('INTEGER', 1)], None), ('b', [('INTEGER', 2)], None)], []), + + ('a:1 important; b: important', + [('a', [('INTEGER', 1), ('S', ' '), ('IDENT', 'important')], None), + ('b', [('IDENT', 'important')], None)], + []), + + ('a:1 !important; b:2', + [('a', [('INTEGER', 1)], 'important'), ('b', [('INTEGER', 2)], None)], + []), + + ('a:1!\t Im\\50 O\\RTant; b:2', + [('a', [('INTEGER', 1)], 'important'), ('b', [('INTEGER', 2)], None)], + []), + + ('a: !important; b:2', + [('b', [('INTEGER', 2)], None)], + ['expected a value before !important']), + + ]: + declarations, errors = CSS21Parser().parse_style_attr(css_source) + self.assert_errors(errors, expected_errors) + result = [(decl.name, list(jsonify(decl.value)), decl.priority) + for decl in declarations] + self.ae(result, expected_declarations) + + def test_at_import(self): + for (css_source, expected_rules, expected_errors) in [ + (' /* hey */\n', [], []), + ('@import "foo.css";', [('foo.css', ['all'])], []), + ('@import url(foo.css);', [('foo.css', ['all'])], []), + ('@import "foo.css" screen, print;', + [('foo.css', ['screen', 'print'])], []), + ('@charset "ascii"; @import "foo.css"; @import "bar.css";', + [('foo.css', ['all']), ('bar.css', ['all'])], []), + ('foo {} @import "foo.css";', + [], ['@import rule not allowed after a ruleset']), + ('@page {} @import "foo.css";', + [], ['@import rule not allowed after an @page rule']), + ('@import ;', + [], ['expected URI or STRING for @import rule']), + ('@import foo.css;', + [], ['expected URI or STRING for @import rule, got IDENT']), + ('@import "foo.css" {}', + [], ["expected ';', got a block"]), + ]: + # Pass 'encoding' to allow @charset + stylesheet = CSS21Parser().parse_stylesheet(css_source, encoding='utf8') + self.assert_errors(stylesheet.errors, expected_errors) + + result = [ + (rule.uri, rule.media) + for rule in stylesheet.rules + if rule.at_keyword == '@import' + ] + self.ae(result, expected_rules) + + def test_at_page(self): + for (css, expected_result, expected_errors) in [ + ('@page {}', (None, (0, 0), []), []), + ('@page:first {}', ('first', (1, 0), []), []), + ('@page :left{}', ('left', (0, 1), []), []), + ('@page\t\n:right {}', ('right', (0, 1), []), []), + ('@page :last {}', None, ['invalid @page selector']), + ('@page : right {}', None, ['invalid @page selector']), + ('@page table:left {}', None, ['invalid @page selector']), + + ('@page;', None, ['invalid @page rule: missing block']), + ('@page { a:1; ; b: 2 }', + (None, (0, 0), [('a', [('INTEGER', 1)]), ('b', [('INTEGER', 2)])]), + []), + ('@page { a:1; c: ; b: 2 }', + (None, (0, 0), [('a', [('INTEGER', 1)]), ('b', [('INTEGER', 2)])]), + ['expected a property value']), + ('@page { a:1; @top-left {} b: 2 }', + (None, (0, 0), [('a', [('INTEGER', 1)]), ('b', [('INTEGER', 2)])]), + ['unknown at-rule in @page context: @top-left']), + ('@page { a:1; @top-left {}; b: 2 }', + (None, (0, 0), [('a', [('INTEGER', 1)]), ('b', [('INTEGER', 2)])]), + ['unknown at-rule in @page context: @top-left']), + ]: + stylesheet = CSS21Parser().parse_stylesheet(css) + self.assert_errors(stylesheet.errors, expected_errors) + + if expected_result is None: + self.assertFalse(stylesheet.rules) + else: + self.ae(len(stylesheet.rules), 1) + rule = stylesheet.rules[0] + self.ae(rule.at_keyword, '@page') + self.ae(rule.at_rules, []) # in CSS 2.1 + result = ( + rule.selector, + rule.specificity, + [(decl.name, list(jsonify(decl.value))) + for decl in rule.declarations], + ) + self.ae(result, expected_result) + + def test_at_media(self): + for (css_source, expected_rules, expected_errors) in [ + (' /* hey */\n', [], []), + ('@media {}', [(['all'], [])], []), + ('@media all {}', [(['all'], [])], []), + ('@media screen, print {}', [(['screen', 'print'], [])], []), + ('@media all;', [], ['invalid @media rule: missing block']), + ('@media 4 {}', [], ['expected a media type, got INTEGER']), + ('@media , screen {}', [], ['expected a media type']), + ('@media screen, {}', [], ['expected a media type']), + ('@media screen print {}', [], + ['expected a media type, got IDENT, IDENT']), + + ('@media all { @page { a: 1 } @media; @import; foo { a: 1 } }', + [(['all'], [('foo', [('a', [('INTEGER', 1)])])])], + ['@page rule not allowed in @media', + '@media rule not allowed in @media', + '@import rule not allowed in @media']), + + ]: + stylesheet = CSS21Parser().parse_stylesheet(css_source) + self.assert_errors(stylesheet.errors, expected_errors) + + for rule in stylesheet.rules: + self.ae(rule.at_keyword, '@media') + result = [ + (rule.media, [ + (sub_rule.selector.as_css(), [ + (decl.name, list(jsonify(decl.value))) + for decl in sub_rule.declarations]) + for sub_rule in rule.rules + ]) + for rule in stylesheet.rules + ] + self.ae(result, expected_rules) diff --git a/ebook_converter/tinycss/tests/decoding.py b/ebook_converter/tinycss/tests/decoding.py new file mode 100644 index 0000000..be3dde1 --- /dev/null +++ b/ebook_converter/tinycss/tests/decoding.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2014, Kovid Goyal ' + +from tinycss.decoding import decode +from tinycss.tests import BaseTest + +def params(css, encoding, use_bom=False, expect_error=False, **kwargs): + """Nicer syntax to make a tuple.""" + return css, encoding, use_bom, expect_error, kwargs + +class TestDecoding(BaseTest): + + def test_decoding(self): + for (css, encoding, use_bom, expect_error, kwargs) in [ + params('', 'utf8'), # default to utf8 + params('𐂃', 'utf8'), + params('é', 'latin1'), # utf8 fails, fall back on ShiftJIS + params('£', 'ShiftJIS', expect_error=True), + params('£', 'ShiftJIS', protocol_encoding='Shift-JIS'), + params('£', 'ShiftJIS', linking_encoding='Shift-JIS'), + params('£', 'ShiftJIS', document_encoding='Shift-JIS'), + params('£', 'ShiftJIS', protocol_encoding='utf8', + document_encoding='ShiftJIS'), + params('@charset "utf8"; £', 'ShiftJIS', expect_error=True), + params('@charset "utf£8"; £', 'ShiftJIS', expect_error=True), + params('@charset "unknown-encoding"; £', 'ShiftJIS', expect_error=True), + params('@charset "utf8"; £', 'ShiftJIS', document_encoding='ShiftJIS'), + params('£', 'ShiftJIS', linking_encoding='utf8', + document_encoding='ShiftJIS'), + params('@charset "utf-32"; 𐂃', 'utf-32-be'), + params('@charset "Shift-JIS"; £', 'ShiftJIS'), + params('@charset "ISO-8859-8"; £', 'ShiftJIS', expect_error=True), + params('𐂃', 'utf-16-le', expect_error=True), # no BOM + params('𐂃', 'utf-16-le', use_bom=True), + params('𐂃', 'utf-32-be', expect_error=True), + params('𐂃', 'utf-32-be', use_bom=True), + params('𐂃', 'utf-32-be', document_encoding='utf-32-be'), + params('𐂃', 'utf-32-be', linking_encoding='utf-32-be'), + params('@charset "utf-32-le"; 𐂃', 'utf-32-be', + use_bom=True, expect_error=True), + # protocol_encoding takes precedence over @charset + params('@charset "ISO-8859-8"; £', 'ShiftJIS', + protocol_encoding='Shift-JIS'), + params('@charset "unknown-encoding"; £', 'ShiftJIS', + protocol_encoding='Shift-JIS'), + params('@charset "Shift-JIS"; £', 'ShiftJIS', + protocol_encoding='utf8'), + # @charset takes precedence over document_encoding + params('@charset "Shift-JIS"; £', 'ShiftJIS', + document_encoding='ISO-8859-8'), + # @charset takes precedence over linking_encoding + params('@charset "Shift-JIS"; £', 'ShiftJIS', + linking_encoding='ISO-8859-8'), + # linking_encoding takes precedence over document_encoding + params('£', 'ShiftJIS', + linking_encoding='Shift-JIS', document_encoding='ISO-8859-8'), + ]: + if use_bom: + source = '\ufeff' + css + else: + source = css + css_bytes = source.encode(encoding) + result, result_encoding = decode(css_bytes, **kwargs) + if expect_error: + self.assertNotEqual(result, css) + else: + self.ae(result, css) diff --git a/ebook_converter/tinycss/tests/fonts3.py b/ebook_converter/tinycss/tests/fonts3.py new file mode 100644 index 0000000..08c7297 --- /dev/null +++ b/ebook_converter/tinycss/tests/fonts3.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2014, Kovid Goyal ' + +from tinycss.fonts3 import CSSFonts3Parser, parse_font_family, parse_font, serialize_font +from tinycss.tests import BaseTest + +from polyglot.builtins import iteritems + + +class TestFonts3(BaseTest): + + def test_font_face(self): + 'Test parsing of font face rules' + for css, expected_declarations, expected_errors in [ + ('@font-face {}', [], []), + + ('@font-face { font-family: Moose; src: url(font1.ttf) }', + [('font-family', [('IDENT', 'Moose')]), ('src', [('URI', 'font1.ttf')])], []), + ]: + stylesheet = CSSFonts3Parser().parse_stylesheet(css) + self.assert_errors(stylesheet.errors, expected_errors) + self.ae(len(stylesheet.rules), 1) + rule = stylesheet.rules[0] + self.ae(self.jsonify_declarations(rule), expected_declarations) + + stylesheet = CSSFonts3Parser().parse_stylesheet('@font-face;') + self.assert_errors(stylesheet.errors, ['missing block']) + + def test_parse_font_family(self): + ' Test parsing of font-family values ' + for raw, q in iteritems({ + '"1as"': ['1as'], + 'A B C, serif': ['A B C', 'serif'], + r'Red\/Black': ['Red/Black'], + 'A B': ['A B'], + r'Ahem\!': ['Ahem!'], + r'"Ahem!"': ['Ahem!'], + '€42': ['€42'], + r'Hawaii\ 5-0': ['Hawaii 5-0'], + r'"X \"Y"': ['X "Y'], + 'A B, C D, "E", serif': ['A B', 'C D', 'E', 'serif'], + '': [], + '"", a': ['a'], + }): + self.ae(q, parse_font_family(raw)) + for single in ('serif', 'sans-serif', 'A B C'): + self.ae([single], parse_font_family(single)) + + def test_parse_font(self): + def t(raw, **kw): + q = {('line' if k == 'height' else 'font') + '-' + k:v for k, v in iteritems(kw)} + self.ae(q, parse_font(raw)) + self.ae(q, parse_font(serialize_font(q))) + t('caption', family=['sans-serif']) + t('serif', family=['serif']) + t('12pt/14pt sans-serif', size='12pt', height='14pt', family=['sans-serif']) + t('80% sans-serif', size='80%', family=['sans-serif']) + t('x-large/110% "new century schoolbook", serif', size='x-large', height='110%', family=['new century schoolbook', 'serif']) + t('bold italic large Palatino, serif', weight='bold', style='italic', size='large', family=['Palatino', 'serif']) + t('normal small-caps 120%/120% fantasy', style='normal', variant='small-caps', size='120%', height='120%', family=['fantasy']) + t('condensed oblique 12pt Helvetica Neue, serif', stretch='condensed', style='oblique', size='12pt', family=['Helvetica Neue', 'serif']) + t('300 italic 1.3em/1.7em FB Armada, sans-serif', weight='300', style='italic', size='1.3em', height='1.7em', family=['FB Armada', 'sans-serif']) diff --git a/ebook_converter/tinycss/tests/main.py b/ebook_converter/tinycss/tests/main.py new file mode 100644 index 0000000..321722b --- /dev/null +++ b/ebook_converter/tinycss/tests/main.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2014, Kovid Goyal ' + +import unittest, os, argparse + +def find_tests(): + from calibre.utils.run_tests import find_tests_in_dir + base = os.path.dirname(os.path.abspath(__file__)) + return find_tests_in_dir(base) + +def run_tests(find_tests=find_tests, for_build=False): + if not for_build: + parser = argparse.ArgumentParser() + parser.add_argument('name', nargs='?', default=None, + help='The name of the test to run') + args = parser.parse_args() + if not for_build and args.name and args.name.startswith('.'): + tests = find_tests() + q = args.name[1:] + if not q.startswith('test_'): + q = 'test_' + q + ans = None + try: + for suite in tests: + for test in suite._tests: + if test.__class__.__name__ == 'ModuleImportFailure': + raise Exception('Failed to import a test module: %s' % test) + for s in test: + if s._testMethodName == q: + ans = s + raise StopIteration() + except StopIteration: + pass + if ans is None: + print ('No test named %s found' % args.name) + raise SystemExit(1) + tests = ans + else: + tests = unittest.defaultTestLoader.loadTestsFromName(args.name) if not for_build and args.name else find_tests() + r = unittest.TextTestRunner + if for_build: + r = r(verbosity=0, buffer=True, failfast=True) + else: + r = r(verbosity=4) + result = r.run(tests) + if for_build and result.errors or result.failures: + raise SystemExit(1) + +if __name__ == '__main__': + run_tests() + + diff --git a/ebook_converter/tinycss/tests/media3.py b/ebook_converter/tinycss/tests/media3.py new file mode 100644 index 0000000..0d37156 --- /dev/null +++ b/ebook_converter/tinycss/tests/media3.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2014, Kovid Goyal ' + +from tinycss.media3 import CSSMedia3Parser, MediaQuery as MQ +from tinycss.tests import BaseTest, jsonify + +def jsonify_expr(e): + if e is None: + return None + return next(jsonify([e])) + +def jsonify_expressions(mqlist): + for mq in mqlist: + mq.expressions = tuple( + (k, jsonify_expr(e)) for k, e in mq.expressions) + return mqlist + +class TestFonts3(BaseTest): + + def test_media_queries(self): + 'Test parsing of media queries from the CSS 3 media module' + for css, media_query_list, expected_errors in [ + # CSS 2.1 (simple media queries) + ('@media {}', [MQ()], []), + ('@media all {}', [MQ()], []), + ('@media screen {}', [MQ('screen')], []), + ('@media , screen {}', [MQ(), MQ('screen')], []), + ('@media screen, {}', [MQ('screen'), MQ()], []), + + # Examples from the CSS 3 specs + ('@media screen and (color) {}', [MQ('screen', (('color', None),))], []), + ('@media all and (min-width:500px) {}', [ + MQ('all', (('min-width', ('DIMENSION', 500)),))], []), + ('@media (min-width:500px) {}', [ + MQ('all', (('min-width', ('DIMENSION', 500)),))], []), + ('@media (orientation: portrait) {}', [ + MQ('all', (('orientation', ('IDENT', 'portrait')),))], []), + ('@media screen and (color), projection and (color) {}', [ + MQ('screen', (('color', None),)), MQ('projection', (('color', None),)),], []), + ('@media not screen and (color) {}', [ + MQ('screen', (('color', None),), True)], []), + ('@media only screen and (color) {}', [ + MQ('screen', (('color', None),))], []), + ('@media aural and (device-aspect-ratio: 16/9) {}', [ + MQ('aural', (('device-aspect-ratio', ('RATIO', (16, 9))),))], []), + ('@media (resolution: 166dpi) {}', [ + MQ('all', (('resolution', ('DIMENSION', 166)),))], []), + ('@media (min-resolution: 166DPCM) {}', [ + MQ('all', (('min-resolution', ('DIMENSION', 166)),))], []), + + # Malformed media queries + ('@media (example, all,), speech {}', [MQ(negated=True), MQ('speech')], ['expected a :']), + ('@media &test, screen {}', [MQ(negated=True), MQ('screen')], ['expected a media expression not a DELIM']), + + ]: + stylesheet = CSSMedia3Parser().parse_stylesheet(css) + self.assert_errors(stylesheet.errors, expected_errors) + self.ae(len(stylesheet.rules), 1) + rule = stylesheet.rules[0] + self.ae(jsonify_expressions(rule.media), media_query_list) + diff --git a/ebook_converter/tinycss/tests/page3.py b/ebook_converter/tinycss/tests/page3.py new file mode 100644 index 0000000..aa3fac3 --- /dev/null +++ b/ebook_converter/tinycss/tests/page3.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2014, Kovid Goyal ' + +from tinycss.page3 import CSSPage3Parser +from tinycss.tests import BaseTest + +class TestPage3(BaseTest): + + def test_selectors(self): + for css, expected_selector, expected_specificity, expected_errors in [ + ('@page {}', (None, None), (0, 0, 0), []), + + ('@page :first {}', (None, 'first'), (0, 1, 0), []), + ('@page:left{}', (None, 'left'), (0, 0, 1), []), + ('@page :right {}', (None, 'right'), (0, 0, 1), []), + ('@page :blank{}', (None, 'blank'), (0, 1, 0), []), + ('@page :last {}', None, None, ['invalid @page selector']), + ('@page : first {}', None, None, ['invalid @page selector']), + + ('@page foo:first {}', ('foo', 'first'), (1, 1, 0), []), + ('@page bar :left {}', ('bar', 'left'), (1, 0, 1), []), + (r'@page \26:right {}', ('&', 'right'), (1, 0, 1), []), + + ('@page foo {}', ('foo', None), (1, 0, 0), []), + (r'@page \26 {}', ('&', None), (1, 0, 0), []), + + ('@page foo fist {}', None, None, ['invalid @page selector']), + ('@page foo, bar {}', None, None, ['invalid @page selector']), + ('@page foo&first {}', None, None, ['invalid @page selector']), + ]: + stylesheet = CSSPage3Parser().parse_stylesheet(css) + self.assert_errors(stylesheet.errors, expected_errors) + + if stylesheet.rules: + self.ae(len(stylesheet.rules), 1) + rule = stylesheet.rules[0] + self.ae(rule.at_keyword, '@page') + selector = rule.selector + self.ae(rule.specificity, expected_specificity) + else: + selector = None + self.ae(selector, expected_selector) + + def test_content(self): + for css, expected_declarations, expected_rules, expected_errors in [ + ('@page {}', [], [], []), + ('@page { foo: 4; bar: z }', + [('foo', [('INTEGER', 4)]), ('bar', [('IDENT', 'z')])], [], []), + ('''@page { foo: 4; + @top-center { content: "Awesome Title" } + @bottom-left { content: counter(page) } + bar: z + }''', + [('foo', [('INTEGER', 4)]), ('bar', [('IDENT', 'z')])], + [('@top-center', [('content', [('STRING', 'Awesome Title')])]), + ('@bottom-left', [('content', [ + ('FUNCTION', 'counter', [('IDENT', 'page')])])])], + []), + ('''@page { foo: 4; + @bottom-top { content: counter(page) } + bar: z + }''', + [('foo', [('INTEGER', 4)]), ('bar', [('IDENT', 'z')])], + [], + ['unknown at-rule in @page context: @bottom-top']), + + ('@page{} @top-right{}', [], [], [ + '@top-right rule not allowed in stylesheet']), + ('@page{ @top-right 4 {} }', [], [], [ + 'unexpected INTEGER token in @top-right rule header']), + # Not much error recovery tests here. This should be covered in test_css21 + ]: + stylesheet = CSSPage3Parser().parse_stylesheet(css) + self.assert_errors(stylesheet.errors, expected_errors) + + self.ae(len(stylesheet.rules), 1) + rule = stylesheet.rules[0] + self.ae(rule.at_keyword, '@page') + self.ae(self.jsonify_declarations(rule), expected_declarations) + rules = [(margin_rule.at_keyword, self.jsonify_declarations(margin_rule)) + for margin_rule in rule.at_rules] + self.ae(rules, expected_rules) diff --git a/ebook_converter/tinycss/tests/tokenizing.py b/ebook_converter/tinycss/tests/tokenizing.py new file mode 100644 index 0000000..e99077d --- /dev/null +++ b/ebook_converter/tinycss/tests/tokenizing.py @@ -0,0 +1,269 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2014, Kovid Goyal ' + +from tinycss.tests import BaseTest, jsonify +from tinycss.tokenizer import python_tokenize_flat, c_tokenize_flat, regroup + +if c_tokenize_flat is None: + tokenizers = (python_tokenize_flat,) +else: + tokenizers = (python_tokenize_flat, c_tokenize_flat) + +def token_api(self, tokenize): + for css_source in [ + '(8, foo, [z])', '[8, foo, (z)]', '{8, foo, [z]}', 'func(8, foo, [z])' + ]: + tokens = list(regroup(tokenize(css_source))) + self.ae(len(tokens), 1) + self.ae(len(tokens[0].content), 7) + +def token_serialize_css(self, tokenize): + for tokenize in tokenizers: + for css_source in [ +r'''p[example="\ +foo(int x) {\ + this.x = x;\ +}\ +"]''', + '"Lorem\\26Ipsum\ndolor" sit', + '/* Lorem\nipsum */\fa {\n color: red;\tcontent: "dolor\\\fsit" }', + 'not([[lorem]]{ipsum (42)})', + 'a[b{d]e}', + 'a[b{"d', + ]: + for _regroup in (regroup, lambda x: x): + tokens = _regroup(tokenize(css_source, ignore_comments=False)) + result = ''.join(token.as_css() for token in tokens) + self.ae(result, css_source) + +def comments(self, tokenize): + for ignore_comments, expected_tokens in [ + (False, [ + ('COMMENT', '/* lorem */'), + ('S', ' '), + ('IDENT', 'ipsum'), + ('[', [ + ('IDENT', 'dolor'), + ('COMMENT', '/* sit */'), + ]), + ('BAD_COMMENT', '/* amet') + ]), + (True, [ + ('S', ' '), + ('IDENT', 'ipsum'), + ('[', [ + ('IDENT', 'dolor'), + ]), + ]), + ]: + css_source = '/* lorem */ ipsum[dolor/* sit */]/* amet' + tokens = regroup(tokenize(css_source, ignore_comments)) + result = list(jsonify(tokens)) + self.ae(result, expected_tokens) + +def token_grouping(self, tokenize): + for css_source, expected_tokens in [ + ('', []), + (r'Lorem\26 "i\psum"4px', [ + ('IDENT', 'Lorem&'), ('STRING', 'ipsum'), ('DIMENSION', 4)]), + + ('not([[lorem]]{ipsum (42)})', [ + ('FUNCTION', 'not', [ + ('[', [ + ('[', [ + ('IDENT', 'lorem'), + ]), + ]), + ('{', [ + ('IDENT', 'ipsum'), + ('S', ' '), + ('(', [ + ('INTEGER', 42), + ]) + ]) + ])]), + + # Close everything at EOF, no error + ('a[b{"d', [ + ('IDENT', 'a'), + ('[', [ + ('IDENT', 'b'), + ('{', [ + ('STRING', 'd'), + ]), + ]), + ]), + + # Any remaining ), ] or } token is a nesting error + ('a[b{d]e}', [ + ('IDENT', 'a'), + ('[', [ + ('IDENT', 'b'), + ('{', [ + ('IDENT', 'd'), + (']', ']'), # The error is visible here + ('IDENT', 'e'), + ]), + ]), + ]), + # ref: + ('a[b{d}e]', [ + ('IDENT', 'a'), + ('[', [ + ('IDENT', 'b'), + ('{', [ + ('IDENT', 'd'), + ]), + ('IDENT', 'e'), + ]), + ]), + ]: + tokens = regroup(tokenize(css_source, ignore_comments=False)) + result = list(jsonify(tokens)) + self.ae(result, expected_tokens) + +def positions(self, tokenize): + css = '/* Lorem\nipsum */\fa {\n color: red;\tcontent: "dolor\\\fsit" }' + tokens = tokenize(css, ignore_comments=False) + result = [(token.type, token.line, token.column) for token in tokens] + self.ae(result, [ + ('COMMENT', 1, 1), ('S', 2, 9), + ('IDENT', 3, 1), ('S', 3, 2), ('{', 3, 3), + ('S', 3, 4), ('IDENT', 4, 5), (':', 4, 10), + ('S', 4, 11), ('IDENT', 4, 12), (';', 4, 15), ('S', 4, 16), + ('IDENT', 4, 17), (':', 4, 24), ('S', 4, 25), ('STRING', 4, 26), + ('S', 5, 5), ('}', 5, 6)]) + +def tokens(self, tokenize): + for css_source, expected_tokens in [ + ('', []), + ('red -->', + [('IDENT', 'red'), ('S', ' '), ('CDC', '-->')]), + # Longest match rule: no CDC + ('red-->', + [('IDENT', 'red--'), ('DELIM', '>')]), + +(r'''p[example="\ +foo(int x) {\ + this.x = x;\ +}\ +"]''', [ + ('IDENT', 'p'), + ('[', '['), + ('IDENT', 'example'), + ('DELIM', '='), + ('STRING', 'foo(int x) { this.x = x;}'), + (']', ']')]), + + # Numbers are parsed + ('42 .5 -4pX 1.25em 30%', + [('INTEGER', 42), ('S', ' '), + ('NUMBER', .5), ('S', ' '), + # units are normalized to lower-case: + ('DIMENSION', -4, 'px'), ('S', ' '), + ('DIMENSION', 1.25, 'em'), ('S', ' '), + ('PERCENTAGE', 30, '%')]), + + # URLs are extracted + ('url(foo.png)', [('URI', 'foo.png')]), + ('url("foo.png")', [('URI', 'foo.png')]), + + # Escaping + + (r'/* Comment with a \ backslash */', + [('COMMENT', '/* Comment with a \ backslash */')]), # Unchanged + + # backslash followed by a newline in a string: ignored + ('"Lorem\\\nIpsum"', [('STRING', 'LoremIpsum')]), + + # backslash followed by a newline outside a string: stands for itself + ('Lorem\\\nIpsum', [ + ('IDENT', 'Lorem'), ('DELIM', '\\'), + ('S', '\n'), ('IDENT', 'Ipsum')]), + + # Cancel the meaning of special characters + (r'"Lore\m Ipsum"', [('STRING', 'Lorem Ipsum')]), # or not specal + (r'"Lorem \49psum"', [('STRING', 'Lorem Ipsum')]), + (r'"Lorem \49 psum"', [('STRING', 'Lorem Ipsum')]), + (r'"Lorem\"Ipsum"', [('STRING', 'Lorem"Ipsum')]), + (r'"Lorem\\Ipsum"', [('STRING', r'Lorem\Ipsum')]), + (r'"Lorem\5c Ipsum"', [('STRING', r'Lorem\Ipsum')]), + (r'Lorem\+Ipsum', [('IDENT', 'Lorem+Ipsum')]), + (r'Lorem+Ipsum', [('IDENT', 'Lorem'), ('DELIM', '+'), ('IDENT', 'Ipsum')]), + (r'url(foo\).png)', [('URI', 'foo).png')]), + + # Unicode and backslash escaping + ('\\26 B', [('IDENT', '&B')]), + ('\\&B', [('IDENT', '&B')]), + ('@\\26\tB', [('ATKEYWORD', '@&B')]), + ('@\\&B', [('ATKEYWORD', '@&B')]), + ('#\\26\nB', [('HASH', '#&B')]), + ('#\\&B', [('HASH', '#&B')]), + ('\\26\r\nB(', [('FUNCTION', '&B(')]), + ('\\&B(', [('FUNCTION', '&B(')]), + (r'12.5\000026B', [('DIMENSION', 12.5, '&b')]), + (r'12.5\0000263B', [('DIMENSION', 12.5, '&3b')]), # max 6 digits + (r'12.5\&B', [('DIMENSION', 12.5, '&b')]), + (r'"\26 B"', [('STRING', '&B')]), + (r"'\000026B'", [('STRING', '&B')]), + (r'"\&B"', [('STRING', '&B')]), + (r'url("\26 B")', [('URI', '&B')]), + (r'url(\26 B)', [('URI', '&B')]), + (r'url("\&B")', [('URI', '&B')]), + (r'url(\&B)', [('URI', '&B')]), + (r'Lorem\110000Ipsum', [('IDENT', 'Lorem\uFFFDIpsum')]), + + # Bad strings + + # String ends at EOF without closing: no error, parsed + ('"Lorem\\26Ipsum', [('STRING', 'Lorem&Ipsum')]), + # Unescaped newline: ends the string, error, unparsed + ('"Lorem\\26Ipsum\n', [ + ('BAD_STRING', r'"Lorem\26Ipsum'), ('S', '\n')]), + # Tokenization restarts after the newline, so the second " starts + # a new string (which ends at EOF without errors, as above.) + ('"Lorem\\26Ipsum\ndolor" sit', [ + ('BAD_STRING', r'"Lorem\26Ipsum'), ('S', '\n'), + ('IDENT', 'dolor'), ('STRING', ' sit')]), + + ]: + sources = [css_source] + for css_source in sources: + tokens = tokenize(css_source, ignore_comments=False) + result = [ + (token.type, token.value) + ( + () if token.unit is None else (token.unit,)) + for token in tokens + ] + self.ae(result, expected_tokens) + + +class TestTokenizer(BaseTest): + + def run_test(self, func): + for tokenize in tokenizers: + func(self, tokenize) + + def test_token_api(self): + self.run_test(token_api) + + def test_token_serialize_css(self): + self.run_test(token_serialize_css) + + def test_comments(self): + self.run_test(comments) + + def test_token_grouping(self): + self.run_test(token_grouping) + + def test_positions(self): + """Test the reported line/column position of each token.""" + self.run_test(positions) + + def test_tokens(self): + self.run_test(tokens) + diff --git a/ebook_converter/tinycss/token_data.py b/ebook_converter/tinycss/token_data.py new file mode 100644 index 0000000..dfbafc1 --- /dev/null +++ b/ebook_converter/tinycss/token_data.py @@ -0,0 +1,450 @@ +# coding: utf8 +""" + tinycss.token_data + ------------------ + + Shared data for both implementations (Cython and Python) of the tokenizer. + + :copyright: (c) 2012 by Simon Sapin. + :license: BSD, see LICENSE for more details. +""" + +from __future__ import unicode_literals + +import re +import sys +import operator +import functools +import string + + +# * Raw strings with the r'' notation are used so that \ do not need +# to be escaped. +# * Names and regexps are separated by a tabulation. +# * Macros are re-ordered so that only previous definitions are needed. +# * {} are used for macro substitution with ``string.Formatter``, +# so other uses of { or } have been doubled. +# * The syntax is otherwise compatible with re.compile. +# * Some parentheses were added to add capturing groups. +# (in unicode, DIMENSION and URI) + +# *** Willful violation: *** +# Numbers can take a + or - sign, but the sign is a separate DELIM token. +# Since comments are allowed anywhere between tokens, this makes +# the following this is valid. It means 10 negative pixels: +# margin-top: -/**/10px + +# This makes parsing numbers a pain, so instead we’ll do the same is Firefox +# and make the sign part as of the 'num' macro. The above CSS will be invalid. +# See discussion: +# http://lists.w3.org/Archives/Public/www-style/2011Oct/0028.html +MACROS = r''' + nl \n|\r\n|\r|\f + w [ \t\r\n\f]* + nonascii [^\0-\237] + unicode \\([0-9a-f]{{1,6}})(\r\n|[ \n\r\t\f])? + simple_escape [^\n\r\f0-9a-f] + escape {unicode}|\\{simple_escape} + nmstart [_a-z]|{nonascii}|{escape} + nmchar [_a-z0-9-]|{nonascii}|{escape} + name {nmchar}+ + ident [-]?{nmstart}{nmchar}* + num [-+]?(?:[0-9]*\.[0-9]+|[0-9]+) + string1 \"([^\n\r\f\\"]|\\{nl}|{escape})*\" + string2 \'([^\n\r\f\\']|\\{nl}|{escape})*\' + string {string1}|{string2} + badstring1 \"([^\n\r\f\\"]|\\{nl}|{escape})*\\? + badstring2 \'([^\n\r\f\\']|\\{nl}|{escape})*\\? + badstring {badstring1}|{badstring2} + badcomment1 \/\*[^*]*\*+([^/*][^*]*\*+)* + badcomment2 \/\*[^*]*(\*+[^/*][^*]*)* + badcomment {badcomment1}|{badcomment2} + baduri1 url\({w}([!#$%&*-~]|{nonascii}|{escape})*{w} + baduri2 url\({w}{string}{w} + baduri3 url\({w}{badstring} + baduri {baduri1}|{baduri2}|{baduri3} +'''.replace(r'\0', '\0').replace(r'\237', '\237') + +# Removed these tokens. Instead, they’re tokenized as two DELIM each. +# INCLUDES ~= +# DASHMATCH |= +# They are only used in selectors but selectors3 also have ^=, *= and $=. +# We don’t actually parse selectors anyway + +# Re-ordered so that the longest match is always the first. +# For example, "url('foo')" matches URI, BAD_URI, FUNCTION and IDENT, +# but URI would always be a longer match than the others. +TOKENS = r''' + S [ \t\r\n\f]+ + + URI url\({w}({string}|([!#$%&*-\[\]-~]|{nonascii}|{escape})*){w}\) + BAD_URI {baduri} + FUNCTION {ident}\( + UNICODE-RANGE u\+[0-9a-f?]{{1,6}}(-[0-9a-f]{{1,6}})? + IDENT {ident} + + ATKEYWORD @{ident} + HASH #{name} + + DIMENSION ({num})({ident}) + PERCENTAGE {num}% + NUMBER {num} + + STRING {string} + BAD_STRING {badstring} + + COMMENT \/\*[^*]*\*+([^/*][^*]*\*+)*\/ + BAD_COMMENT {badcomment} + + : : + ; ; + { \{{ + } \}} + ( \( + ) \) + [ \[ + ] \] + CDO +''' + + +# Strings with {macro} expanded +COMPILED_MACROS = {} + + +COMPILED_TOKEN_REGEXPS = [] # [(name, regexp.match)] ordered +COMPILED_TOKEN_INDEXES = {} # {name: i} helper for the C speedups + + +# Indexed by codepoint value of the first character of a token. +# Codepoints >= 160 (aka nonascii) all use the index 160. +# values are (i, name, regexp.match) +TOKEN_DISPATCH = [] + + +try: + unichr +except NameError: + # Python 3 + unichr = chr + unicode = str + + +def _init(): + """Import-time initialization.""" + COMPILED_MACROS.clear() + for line in MACROS.splitlines(): + if line.strip(): + name, value = line.split('\t') + COMPILED_MACROS[name.strip()] = '(?:%s)' \ + % value.format(**COMPILED_MACROS) + + COMPILED_TOKEN_REGEXPS[:] = ( + ( + name.strip(), + re.compile( + value.format(**COMPILED_MACROS), + # Case-insensitive when matching eg. uRL(foo) + # but preserve the case in extracted groups + re.I + ).match + ) + for line in TOKENS.splitlines() + if line.strip() + for name, value in [line.split('\t')] + ) + + COMPILED_TOKEN_INDEXES.clear() + for i, (name, regexp) in enumerate(COMPILED_TOKEN_REGEXPS): + COMPILED_TOKEN_INDEXES[name] = i + + dispatch = [[] for i in range(161)] + for chars, names in [ + (' \t\r\n\f', ['S']), + ('uU', ['URI', 'BAD_URI', 'UNICODE-RANGE']), + # \ is an escape outside of another token + (string.ascii_letters + '\\_-' + unichr(160), ['FUNCTION', 'IDENT']), + (string.digits + '.+-', ['DIMENSION', 'PERCENTAGE', 'NUMBER']), + ('@', ['ATKEYWORD']), + ('#', ['HASH']), + ('\'"', ['STRING', 'BAD_STRING']), + ('/', ['COMMENT', 'BAD_COMMENT']), + ('<', ['CDO']), + ('-', ['CDC']), + ]: + for char in chars: + dispatch[ord(char)].extend(names) + for char in ':;{}()[]': + dispatch[ord(char)] = [char] + + TOKEN_DISPATCH[:] = ( + [ + (index,) + COMPILED_TOKEN_REGEXPS[index] + for name in names + for index in [COMPILED_TOKEN_INDEXES[name]] + ] + for names in dispatch + ) + +_init() + + +def _unicode_replace(match, int=int, unichr=unichr, maxunicode=sys.maxunicode): + codepoint = int(match.group(1), 16) + if codepoint <= maxunicode: + return unichr(codepoint) + else: + return '\N{REPLACEMENT CHARACTER}' # U+FFFD + +UNICODE_UNESCAPE = functools.partial( + re.compile(COMPILED_MACROS['unicode'], re.I).sub, + _unicode_replace) + +NEWLINE_UNESCAPE = functools.partial( + re.compile(r'()\\' + COMPILED_MACROS['nl']).sub, + '') + +SIMPLE_UNESCAPE = functools.partial( + re.compile(r'\\(%s)' % COMPILED_MACROS['simple_escape'] , re.I).sub, + # Same as r'\1', but faster on CPython + operator.methodcaller('group', 1)) + +FIND_NEWLINES = lambda x : list(re.compile(COMPILED_MACROS['nl']).finditer(x)) + + +class Token(object): + r"""A single atomic token. + + .. attribute:: is_container + + Always ``False``. + Helps to tell :class:`Token` apart from :class:`ContainerToken`. + + .. attribute:: type + + The type of token as a string: + + ``S`` + A sequence of white space + + ``IDENT`` + An identifier: a name that does not start with a digit. + A name is a sequence of letters, digits, ``_``, ``-``, escaped + characters and non-ASCII characters. Eg: ``margin-left`` + + ``HASH`` + ``#`` followed immediately by a name. Eg: ``#ff8800`` + + ``ATKEYWORD`` + ``@`` followed immediately by an identifier. Eg: ``@page`` + + ``URI`` + Eg: ``url(foo)`` The content may or may not be quoted. + + ``UNICODE-RANGE`` + ``U+`` followed by one or two hexadecimal + Unicode codepoints. Eg: ``U+20-00FF`` + + ``INTEGER`` + An integer with an optional ``+`` or ``-`` sign + + ``NUMBER`` + A non-integer number with an optional ``+`` or ``-`` sign + + ``DIMENSION`` + An integer or number followed immediately by an + identifier (the unit). Eg: ``12px`` + + ``PERCENTAGE`` + An integer or number followed immediately by ``%`` + + ``STRING`` + A string, quoted with ``"`` or ``'`` + + ``:`` or ``;`` + That character. + + ``DELIM`` + A single character not matched in another token. Eg: ``,`` + + See the source of the :mod:`.token_data` module for the precise + regular expressions that match various tokens. + + Note that other token types exist in the early tokenization steps, + but these are ignored, are syntax errors, or are later transformed + into :class:`ContainerToken` or :class:`FunctionToken`. + + .. attribute:: value + + The parsed value: + + * INTEGER, NUMBER, PERCENTAGE or DIMENSION tokens: the numeric value + as an int or float. + * STRING tokens: the unescaped string without quotes + * URI tokens: the unescaped URI without quotes or + ``url(`` and ``)`` markers. + * IDENT, ATKEYWORD or HASH tokens: the unescaped token, + with ``@`` or ``#`` markers left as-is + * Other tokens: same as :attr:`as_css` + + *Unescaped* refers to the various escaping methods based on the + backslash ``\`` character in CSS syntax. + + .. attribute:: unit + + * DIMENSION tokens: the normalized (unescaped, lower-case) + unit name as a string. eg. ``'px'`` + * PERCENTAGE tokens: the string ``'%'`` + * Other tokens: ``None`` + + .. attribute:: line + + The line number in the CSS source of the start of this token. + + .. attribute:: column + + The column number (inside a source line) of the start of this token. + + """ + is_container = False + __slots__ = 'type', '_as_css', 'value', 'unit', 'line', 'column' + + def __init__(self, type_, css_value, value, unit, line, column): + self.type = type_ + self._as_css = css_value + self.value = value + self.unit = unit + self.line = line + self.column = column + + def as_css(self): + """ + Return as an Unicode string the CSS representation of the token, + as parsed in the source. + """ + return self._as_css + + def __repr__(self): + return ('' + .format(self, self.unit or '')) + + +class ContainerToken(object): + """A token that contains other (nested) tokens. + + .. attribute:: is_container + + Always ``True``. + Helps to tell :class:`ContainerToken` apart from :class:`Token`. + + .. attribute:: type + + The type of token as a string. One of ``{``, ``(``, ``[`` or + ``FUNCTION``. For ``FUNCTION``, the object is actually a + :class:`FunctionToken`. + + .. attribute:: unit + + Always ``None``. Included to make :class:`ContainerToken` behave + more like :class:`Token`. + + .. attribute:: content + + A list of :class:`Token` or nested :class:`ContainerToken`, + not including the opening or closing token. + + .. attribute:: line + + The line number in the CSS source of the start of this token. + + .. attribute:: column + + The column number (inside a source line) of the start of this token. + + """ + is_container = True + unit = None + __slots__ = 'type', '_css_start', '_css_end', 'content', 'line', 'column' + + def __init__(self, type_, css_start, css_end, content, line, column): + self.type = type_ + self._css_start = css_start + self._css_end = css_end + self.content = content + self.line = line + self.column = column + + def as_css(self): + """ + Return as an Unicode string the CSS representation of the token, + as parsed in the source. + """ + parts = [self._css_start] + parts.extend(token.as_css() for token in self.content) + parts.append(self._css_end) + return ''.join(parts) + + format_string = '' + + def __repr__(self): + return (self.format_string + ' {0.content}').format(self) + + +class FunctionToken(ContainerToken): + """A specialized :class:`ContainerToken` for a ``FUNCTION`` group. + Has an additional attribute: + + .. attribute:: function_name + + The unescaped name of the function, with the ``(`` marker removed. + + """ + __slots__ = 'function_name', + + def __init__(self, type_, css_start, css_end, function_name, content, + line, column): + super(FunctionToken, self).__init__( + type_, css_start, css_end, content, line, column) + # Remove the ( marker: + self.function_name = function_name[:-1] + + format_string = ('') + + +class TokenList(list): + """ + A mixed list of :class:`~.token_data.Token` and + :class:`~.token_data.ContainerToken` objects. + + This is a subclass of the builtin :class:`~builtins.list` type. + It can be iterated, indexed and sliced as usual, but also has some + additional API: + + """ + @property + def line(self): + """The line number in the CSS source of the first token.""" + return self[0].line + + @property + def column(self): + """The column number (inside a source line) of the first token.""" + return self[0].column + + def as_css(self): + """ + Return as an Unicode string the CSS representation of the tokens, + as parsed in the source. + """ + return ''.join(token.as_css() for token in self) + +def load_c_tokenizer(): + from calibre.constants import plugins + tokenizer, err = plugins['tokenizer'] + if err: + raise RuntimeError('Failed to load module tokenizer: %s' % err) + tokens = list(':;(){}[]') + ['DELIM', 'INTEGER', 'STRING'] + tokenizer.init(COMPILED_TOKEN_REGEXPS, UNICODE_UNESCAPE, NEWLINE_UNESCAPE, SIMPLE_UNESCAPE, FIND_NEWLINES, TOKEN_DISPATCH, COMPILED_TOKEN_INDEXES, *tokens) + return tokenizer diff --git a/ebook_converter/tinycss/tokenizer.c b/ebook_converter/tinycss/tokenizer.c new file mode 100644 index 0000000..f7df2b3 --- /dev/null +++ b/ebook_converter/tinycss/tokenizer.c @@ -0,0 +1,504 @@ +/* + * tokenizer.c + * Copyright (C) 2014 Kovid Goyal + * + * Distributed under terms of the GPL3 license. + */ + +#define UNICODE +#define PY_SSIZE_T_CLEAN +#include +#include + +// Token type definition {{{ +typedef struct { + PyObject_HEAD + // Type-specific fields go here. + PyObject *is_container; + PyObject *type; + PyObject *_as_css; + PyObject *value; + PyObject *unit; + PyObject *line; + PyObject *column; + +} tokenizer_Token; + +static void +tokenizer_Token_dealloc(tokenizer_Token* self) +{ + Py_XDECREF(self->is_container); self->is_container = NULL; + Py_XDECREF(self->type); self->type = NULL; + Py_XDECREF(self->_as_css); self->_as_css = NULL; + Py_XDECREF(self->value); self->value = NULL; + Py_XDECREF(self->unit); self->unit = NULL; + Py_XDECREF(self->line); self->line = NULL; + Py_XDECREF(self->column); self->column = NULL; + Py_TYPE(self)->tp_free((PyObject*)self); +} + + +static PyObject * +tokenizer_Token_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + tokenizer_Token *self = NULL; + self = (tokenizer_Token *)type->tp_alloc(type, 0); + if (self == NULL) return PyErr_NoMemory(); + + if (!PyArg_ParseTuple(args, "OOOOOO", &(self->type), &(self->_as_css), &(self->value), &(self->unit), &(self->line), &(self->column))) { + Py_TYPE(self)->tp_free((PyObject *) self); + return NULL; + } + Py_INCREF(self->type); Py_INCREF(self->_as_css); Py_INCREF(self->value); Py_INCREF(self->unit); Py_INCREF(self->line); Py_INCREF(self->column); + self->is_container = Py_False; Py_INCREF(self->is_container); + + return (PyObject *)self; +} + +#if PY_MAJOR_VERSION >= 3 +#define PyObject_Unicode_Compat(arg) PyObject_Str(arg) +#else +#define PyObject_Unicode_Compat(arg) PyObject_Unicode(arg) +#endif + +static PyObject * +tokenizer_Token_repr(tokenizer_Token *self) { + PyObject *type = NULL, *line = NULL, *column = NULL, *value = NULL, *ans = NULL, *unit = NULL; + if (!self->type || !self->line || !self->column || !self->value) + return PyBytes_FromString(""); + type = PyObject_Unicode_Compat(self->type); + line = PyObject_Unicode_Compat(self->line); + column = PyObject_Unicode_Compat(self->column); + value = PyObject_Unicode_Compat(self->value); + if (type && line && column && value) { + if (self->unit != NULL && PyObject_IsTrue(self->unit)) { + unit = PyObject_Unicode_Compat(self->unit); + if (unit != NULL) + ans = PyUnicode_FromFormat("", type, line, column, value, unit); + else + PyErr_NoMemory(); + } else + ans = PyUnicode_FromFormat("", type, line, column, value); + } else PyErr_NoMemory(); + Py_XDECREF(type); Py_XDECREF(line); Py_XDECREF(column); Py_XDECREF(value); Py_XDECREF(unit); + return ans; +} + +static PyObject * +tokenizer_Token_as_css(tokenizer_Token *self, PyObject *args, PyObject *kwargs) { + if (!self->_as_css) { + Py_RETURN_NONE; + } + Py_INCREF(self->_as_css); + return self->_as_css; +} + +static PyMemberDef tokenizer_Token_members[] = { + {"is_container", T_OBJECT_EX, offsetof(tokenizer_Token, is_container), 0, "False unless this token is a container for other tokens"}, + {"type", T_OBJECT_EX, offsetof(tokenizer_Token, type), 0, "The token type"}, + {"_as_css", T_OBJECT_EX, offsetof(tokenizer_Token, _as_css), 0, "Internal variable, use as_css() method instead."}, + {"value", T_OBJECT_EX, offsetof(tokenizer_Token, value), 0, "The token value"}, + {"unit", T_OBJECT_EX, offsetof(tokenizer_Token, unit), 0, "The token unit"}, + {"line", T_OBJECT_EX, offsetof(tokenizer_Token, line), 0, "The token line number"}, + {"column", T_OBJECT_EX, offsetof(tokenizer_Token, column), 0, "The token column number"}, + {NULL} /* Sentinel */ +}; + +static PyMethodDef tokenizer_Token_methods[] = { + {"as_css", (PyCFunction)tokenizer_Token_as_css, METH_VARARGS, + "as_css() -> Return the CSS representation of this token" + }, + + {NULL} /* Sentinel */ +}; + +static PyTypeObject tokenizer_TokenType = { // {{{ + PyVarObject_HEAD_INIT(NULL, 0) + /* tp_name */ "tokenizer.Token", + /* tp_basicsize */ sizeof(tokenizer_Token), + /* tp_itemsize */ 0, + /* tp_dealloc */ (destructor) tokenizer_Token_dealloc, + /* tp_print */ 0, + /* tp_getattr */ 0, + /* tp_setattr */ 0, + /* tp_compare */ 0, + /* tp_repr */ (reprfunc) tokenizer_Token_repr, + /* tp_as_number */ 0, + /* tp_as_sequence */ 0, + /* tp_as_mapping */ 0, + /* tp_hash */ 0, + /* tp_call */ 0, + /* tp_str */ 0, + /* tp_getattro */ 0, + /* tp_setattro */ 0, + /* tp_as_buffer */ 0, + /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + /* tp_doc */ "Token", + /* tp_traverse */ 0, + /* tp_clear */ 0, + /* tp_richcompare */ 0, + /* tp_weaklistoffset */ 0, + /* tp_iter */ 0, + /* tp_iternext */ 0, + /* tp_methods */ tokenizer_Token_methods, + /* tp_members */ tokenizer_Token_members, + /* tp_getset */ 0, + /* tp_base */ 0, + /* tp_dict */ 0, + /* tp_descr_get */ 0, + /* tp_descr_set */ 0, + /* tp_dictoffset */ 0, + /* tp_init */ 0, + /* tp_alloc */ 0, + /* tp_new */ tokenizer_Token_new, +}; // }}} +// }}} + +static PyObject *COMPILED_TOKEN_REGEXPS = NULL, *UNICODE_UNESCAPE = NULL, *NEWLINE_UNESCAPE = NULL, *SIMPLE_UNESCAPE = NULL, *FIND_NEWLINES = NULL, *TOKEN_DISPATCH = NULL; +static PyObject *COLON = NULL, *SCOLON = NULL, *LPAR = NULL, *RPAR = NULL, *LBRACE = NULL, *RBRACE = NULL, *LBOX = NULL, *RBOX = NULL, *DELIM_TOK = NULL, *INTEGER = NULL, *STRING_TOK = NULL; + +static Py_ssize_t BAD_COMMENT, BAD_STRING, PERCENTAGE, DIMENSION, ATKEYWORD, FUNCTION, COMMENT, NUMBER, STRING, IDENT, HASH, URI, DELIM = -1; + +#define CLEANUP(x) Py_XDECREF((x)); x = NULL; + +static PyObject* +tokenize_cleanup(PyObject *self, PyObject *args) { + CLEANUP(COMPILED_TOKEN_REGEXPS); CLEANUP(UNICODE_UNESCAPE); CLEANUP(NEWLINE_UNESCAPE); CLEANUP(SIMPLE_UNESCAPE); CLEANUP(FIND_NEWLINES); CLEANUP(TOKEN_DISPATCH); + CLEANUP(COLON); CLEANUP(SCOLON); CLEANUP(LPAR); CLEANUP(RPAR); CLEANUP(LBRACE); CLEANUP(RBRACE); CLEANUP(LBOX); CLEANUP(RBOX); CLEANUP(DELIM_TOK); CLEANUP(INTEGER); CLEANUP(STRING_TOK); + Py_RETURN_NONE; +} + +static PyObject* +tokenize_init(PyObject *self, PyObject *args) { + PyObject *cti = NULL; + + if (COMPILED_TOKEN_REGEXPS != NULL) { + tokenize_cleanup(NULL, NULL); + } + if (!PyArg_ParseTuple(args, "OOOOOOOOOOOOOOOOOO", &COMPILED_TOKEN_REGEXPS, &UNICODE_UNESCAPE, &NEWLINE_UNESCAPE, &SIMPLE_UNESCAPE, &FIND_NEWLINES, &TOKEN_DISPATCH, &cti, &COLON, &SCOLON, &LPAR, &RPAR, &LBRACE, &RBRACE, &LBOX, &RBOX, &DELIM_TOK, &INTEGER, &STRING_TOK)) return NULL; + Py_INCREF(COMPILED_TOKEN_REGEXPS); Py_INCREF(UNICODE_UNESCAPE); Py_INCREF(NEWLINE_UNESCAPE); Py_INCREF(SIMPLE_UNESCAPE); Py_INCREF(FIND_NEWLINES); Py_INCREF(TOKEN_DISPATCH); + Py_INCREF(COLON); Py_INCREF(SCOLON); Py_INCREF(LPAR); Py_INCREF(RPAR); Py_INCREF(LBRACE); Py_INCREF(RBRACE); Py_INCREF(LBOX); Py_INCREF(RBOX); Py_INCREF(DELIM_TOK); Py_INCREF(INTEGER); Py_INCREF(STRING_TOK); + +#define SETCONST(x) do { (x) = PyNumber_AsSsize_t(PyDict_GetItemString(cti, #x), PyExc_OverflowError); \ + if((x) == -1 && PyErr_Occurred() != NULL) { return NULL; } \ + } while(0) + SETCONST(BAD_COMMENT); SETCONST(BAD_STRING); SETCONST(PERCENTAGE); SETCONST(DIMENSION); SETCONST(ATKEYWORD); SETCONST(FUNCTION); SETCONST(COMMENT); SETCONST(NUMBER); SETCONST(STRING); SETCONST(IDENT); SETCONST(HASH); SETCONST(URI); + + Py_RETURN_NONE; +} + +#if PY_VERSION_HEX >= 0x03030000 +#define ITER_CODE_PTS(unicode_object) { \ + int _kind = PyUnicode_KIND(unicode_object); \ + void *_data = PyUnicode_DATA(unicode_object); \ + for (Py_ssize_t iteridx = 0; iteridx < PyUnicode_GET_LENGTH(unicode_object); iteridx++) { \ + Py_UCS4 ch = PyUnicode_READ(_kind, _data, iteridx); +#else +#define PyUnicode_GET_LENGTH PyUnicode_GET_SIZE +#define ITER_CODE_PTS(unicode_object) { \ + Py_UNICODE *_data = PyUnicode_AS_UNICODE(unicode_object); \ + Py_ssize_t iteridx; \ + for (iteridx = 0; iteridx < PyUnicode_GET_LENGTH(unicode_object); iteridx++) { \ + Py_UNICODE ch = _data[iteridx]; +#endif + +#define END_ITER_CODE_PTS }} + +static PyObject *unicode_to_number(PyObject *src) { +#if PY_MAJOR_VERSION >= 3 + PyObject* ans = PyFloat_FromString(src); +#else + PyObject* ans = PyFloat_FromString(src, NULL); +#endif + double val = PyFloat_AsDouble(ans); + long lval = (long)val; + if (val - lval != 0) return ans; + Py_DECREF(ans); +#if PY_MAJOR_VERSION >= 3 + return PyLong_FromLong(lval); +#else + return PyInt_FromLong(lval); +#endif +} + + +static void lowercase(PyObject *x) { + ITER_CODE_PTS(x) + if ('A' <= ch && ch <= 'Z') { +#if PY_VERSION_HEX >= 0x03030000 + PyUnicode_WRITE(_kind, _data, iteridx, ch + 32); +#else + _data[iteridx] += 32; +#endif + } + END_ITER_CODE_PTS +} + +static PyObject* +clone_unicode(const PyObject* src, Py_ssize_t start_offset, Py_ssize_t end_offset) { +#if PY_VERSION_HEX >= 0x03030000 + int kind = PyUnicode_KIND(src); + void *data; + switch(kind) { + case PyUnicode_1BYTE_KIND: + data = PyUnicode_1BYTE_DATA(src) + start_offset; break; + case PyUnicode_2BYTE_KIND: + data = PyUnicode_2BYTE_DATA(src) + start_offset; break; + case PyUnicode_4BYTE_KIND: + data = PyUnicode_4BYTE_DATA(src) + start_offset; break; + default: + PyErr_SetString(PyExc_RuntimeError, "Invalid byte kind for unicode object"); + return NULL; + } + return PyUnicode_FromKindAndData(kind, data, PyUnicode_GET_LENGTH(src) - start_offset - end_offset); +#else + return PyUnicode_FromUnicode(PyUnicode_AS_UNICODE(src) + start_offset, PyUnicode_GET_LENGTH(src) - start_offset - end_offset); +#endif +} + +static PyObject* +tokenize_flat(PyObject *self, PyObject *args) { +#if PY_VERSION_HEX >= 0x03030000 + void *css_source = NULL; int css_kind; Py_UCS4 c = 0, codepoint = 0; +#define first_char(string) PyUnicode_READ_CHAR(string, 0) +#define unicode_from_data(data, sz) PyUnicode_FromKindAndData(css_kind, data, sz) +#else + Py_UNICODE *css_source = NULL, c = 0, codepoint = 0; +#define first_char(string) PyUnicode_AS_UNICODE(string)[0] +#define unicode_from_data(data, sz) PyUnicode_FromUnicode(data, sz) +#endif + PyObject *ic = NULL, *token = NULL, *tokens = NULL, *type_name = NULL, *css_value = NULL, *value = NULL, *unit = NULL, *tries = NULL, *match = NULL, *match_func = NULL, *py_source = NULL, *item = NULL, *newlines = NULL; + int ignore_comments = 0; + Py_ssize_t pos = 0, line = 1, column = 1, i = 0; + Py_ssize_t length = 0, next_pos = 0, type_ = -1, source_len = 0; + + + if (COMPILED_TOKEN_REGEXPS == NULL) { + PyErr_SetString(PyExc_RuntimeError, "tokenizer module not initialized. You must call init() first."); return NULL; + } + + if (!PyArg_ParseTuple(args, "UO", &py_source, &ic)) return NULL; + if (PyObject_IsTrue(ic)) ignore_comments = 1; +#if PY_VERSION_HEX >= 0x03030000 + if (PyUnicode_READY(py_source) != 0) return NULL; + css_source = PyUnicode_DATA(py_source); css_kind = PyUnicode_KIND(py_source); +#else + css_source = PyUnicode_AS_UNICODE(py_source); +#endif + source_len = PyUnicode_GET_LENGTH(py_source); + + tokens = PyList_New(0); + if (tokens == NULL) return PyErr_NoMemory(); + +#define UNESCAPE(x, func) item = PyObject_CallFunctionObjArgs(func, x, NULL); if (item == NULL) { goto error; } Py_DECREF(x); x = item; item = NULL; + +#define TONUMBER(x) item = unicode_to_number(x); if (item == NULL) goto error; Py_DECREF(x); x = item; item = NULL; + +#define SINGLE(x) { type_ = -1; type_name = x; Py_INCREF(type_name); css_value = x; Py_INCREF(css_value); } + + while (pos < source_len) { +#if PY_VERSION_HEX >= 0x03030000 + c = PyUnicode_READ(css_kind, css_source, pos); +#else + c = css_source[pos]; +#endif + + css_value = NULL; type_name = NULL; value = NULL; unit = NULL; match = NULL; + + if (c == ':') SINGLE(COLON) else if (c == ';') SINGLE(SCOLON) else if (c == '(') SINGLE(LPAR) else if (c == ')') SINGLE(RPAR) else if (c == '{') SINGLE(LBRACE) else if (c == '}') SINGLE(RBRACE) else if (c == '[') SINGLE(LBOX) else if (c == ']') SINGLE(RBOX) else + { + codepoint = (c > 160) ? 160: c; + tries = PyList_GET_ITEM(TOKEN_DISPATCH, codepoint); + for (i = 0; i < PyList_Size(tries); i++) { + item = PyList_GET_ITEM(tries, i); + match_func = PyTuple_GET_ITEM(item, 2); + match = PyObject_CallFunction(match_func, "On", py_source, pos); + if (match == NULL) { goto error; } + if (match != Py_None) { + css_value = PyObject_CallMethod(match, "group", NULL); + if (css_value == NULL) { goto error; } + type_ = PyNumber_AsSsize_t(PyTuple_GET_ITEM(item, 0), PyExc_OverflowError); + if(type_ == -1 && PyErr_Occurred() != NULL) { goto error; } + type_name = PyTuple_GET_ITEM(item, 1); + Py_INCREF(type_name); + break; + } + } + if (css_value == NULL) { // No match + type_ = DELIM; type_name = DELIM_TOK; Py_INCREF(type_name); css_value = unicode_from_data(&c, 1); + if (css_value == NULL) { goto error; } + } + } + + length = PyUnicode_GET_LENGTH(css_value); + next_pos = pos + length; + + // Now calculate the value and unit for this token (if any) + if (! (ignore_comments && (type_ == COMMENT || type_ == BAD_COMMENT))) { + if (type_ == DIMENSION) { + value = PyObject_CallMethod(match, "group", "I", 1); + if (value == NULL) { goto error; } + TONUMBER(value); + unit = PyObject_CallMethod(match, "group", "I", 2); + if (unit == NULL) { goto error; } + UNESCAPE(unit, SIMPLE_UNESCAPE); + UNESCAPE(unit, UNICODE_UNESCAPE); + lowercase(unit); + } else + + if (type_ == PERCENTAGE) { + if (PyUnicode_GET_LENGTH(css_value) > 0) { + value = clone_unicode(css_value, 0, 1); + if (value == NULL) goto error; + } else { value = css_value; Py_INCREF(value); } + if (value == NULL) goto error; + TONUMBER(value); + unit = PyUnicode_FromString("%"); + if (unit == NULL) goto error; + } else + + if (type_ == NUMBER) { + value = css_value; Py_INCREF(value); + TONUMBER(value); + if (!PyFloat_Check(value)) { + Py_XDECREF(type_name); + type_name = INTEGER; + Py_INCREF(type_name); + } + } else + + if (type_ == IDENT || type_ == ATKEYWORD || type_ == HASH || type_ == FUNCTION) { + value = PyObject_CallFunctionObjArgs(SIMPLE_UNESCAPE, css_value, NULL); + if (value == NULL) goto error; + UNESCAPE(value, UNICODE_UNESCAPE); + } else + + if (type_ == URI) { + value = PyObject_CallMethod(match, "group", "I", 1); + if (value == NULL) { goto error; } + if (PyObject_IsTrue(value) && PyUnicode_GET_LENGTH(value) > 1 && (first_char(value) == '"' || first_char(value) == '\'')) { + item = clone_unicode(value, 1, 1); + if (item == NULL) goto error; + Py_DECREF(value); value = item; item = NULL; + UNESCAPE(value, NEWLINE_UNESCAPE); + } + UNESCAPE(value, SIMPLE_UNESCAPE); + UNESCAPE(value, UNICODE_UNESCAPE); + } else + + if (type_ == STRING) { + if (PyObject_IsTrue(css_value) && PyUnicode_GET_LENGTH(css_value) > 1) { // remove quotes + value = clone_unicode(css_value, 1, 1); + } else { + value = css_value; Py_INCREF(value); + } + UNESCAPE(value, NEWLINE_UNESCAPE); + UNESCAPE(value, SIMPLE_UNESCAPE); + UNESCAPE(value, UNICODE_UNESCAPE); + } else + + if (type_ == BAD_STRING && next_pos == source_len) { + Py_XDECREF(type_name); type_name = STRING_TOK; Py_INCREF(type_name); + if (PyObject_IsTrue(css_value) && PyUnicode_GET_LENGTH(css_value) > 0) { // remove quote + value = clone_unicode(css_value, 1, 0); + } else { + value = css_value; Py_INCREF(value); + } + UNESCAPE(value, NEWLINE_UNESCAPE); + UNESCAPE(value, SIMPLE_UNESCAPE); + UNESCAPE(value, UNICODE_UNESCAPE); + } else { + value = css_value; Py_INCREF(value); + } // if(type_ == ...) + + if (unit == NULL) { unit = Py_None; Py_INCREF(unit); } + item = Py_BuildValue("OOOOnn", type_name, css_value, value, unit, line, column); + if (item == NULL) goto error; + token = PyObject_CallObject((PyObject *) &tokenizer_TokenType, item); + Py_DECREF(item); item = NULL; + if (token == NULL) goto error; + if (PyList_Append(tokens, token) != 0) { Py_DECREF(token); token = NULL; goto error; } + Py_DECREF(token); + + } // if(!(ignore_comments... + + Py_XDECREF(match); match = NULL; + + pos = next_pos; + newlines = PyObject_CallFunctionObjArgs(FIND_NEWLINES, css_value, NULL); + if (newlines == NULL) goto error; + Py_XDECREF(css_value); css_value = NULL; Py_XDECREF(type_name); type_name = NULL; Py_XDECREF(value); value = NULL; Py_XDECREF(unit); unit = NULL; + if (PyObject_IsTrue(newlines)) { + line += PyList_Size(newlines); + item = PyObject_CallMethod(PyList_GET_ITEM(newlines, PyList_Size(newlines) - 1), "end", NULL); + if (item == NULL) { Py_DECREF(newlines); newlines = NULL; goto error; } + column = PyNumber_AsSsize_t(item, PyExc_OverflowError); + if(column == -1 && PyErr_Occurred()) { Py_DECREF(newlines); newlines = NULL; goto error; } + column = length - column + 1; + Py_DECREF(item); item = NULL; + } else column += length; + Py_DECREF(newlines); newlines = NULL; + + } // while (pos < ...) + + return tokens; +error: + Py_XDECREF(tokens); Py_XDECREF(css_value); Py_XDECREF(type_name); Py_XDECREF(value); Py_XDECREF(unit); Py_XDECREF(match); + return NULL; +#undef unicode_from_data +#undef first_char +} + +static PyMethodDef tokenizer_methods[] = { + {"tokenize_flat", tokenize_flat, METH_VARARGS, + "tokenize_flat(css_source, ignore_comments)\n\n Convert CSS source into a flat list of tokens" + }, + + {"init", tokenize_init, METH_VARARGS, + "init()\n\nInitialize the module." + }, + + {"cleanup", tokenize_cleanup, METH_VARARGS, + "cleanup()\n\nRelease resources allocated by init(). Safe to call multiple times." + }, + + {NULL, NULL, 0, NULL} +}; + +#if PY_MAJOR_VERSION >= 3 +#define INITERROR return NULL +static struct PyModuleDef tokenizer_module = { + /* m_base */ PyModuleDef_HEAD_INIT, + /* m_name */ "tokenizer", + /* m_doc */ "Implementation of tokenizer in C for speed.", + /* m_size */ -1, + /* m_methods */ tokenizer_methods, + /* m_slots */ 0, + /* m_traverse */ 0, + /* m_clear */ 0, + /* m_free */ 0, +}; + +CALIBRE_MODINIT_FUNC PyInit_tokenizer(void) { + if (PyType_Ready(&tokenizer_TokenType) < 0) + INITERROR; + + PyObject *mod = PyModule_Create(&tokenizer_module); +#else +#define INITERROR return +CALIBRE_MODINIT_FUNC inittokenizer(void) { + if (PyType_Ready(&tokenizer_TokenType) < 0) + INITERROR; + + PyObject *mod = Py_InitModule3("tokenizer", tokenizer_methods, + "Implementation of tokenizer in C for speed."); +#endif + + if (mod == NULL) INITERROR; + Py_INCREF(&tokenizer_TokenType); + PyModule_AddObject(mod, "Token", (PyObject *) &tokenizer_TokenType); + +#if PY_MAJOR_VERSION >= 3 + return mod; +#endif +} diff --git a/ebook_converter/tinycss/tokenizer.py b/ebook_converter/tinycss/tokenizer.py new file mode 100644 index 0000000..154c111 --- /dev/null +++ b/ebook_converter/tinycss/tokenizer.py @@ -0,0 +1,216 @@ +# coding: utf8 +""" + tinycss.tokenizer + ----------------- + + Tokenizer for the CSS core syntax: + http://www.w3.org/TR/CSS21/syndata.html#tokenization + + This is the pure-python implementation. See also speedups.pyx + + :copyright: (c) 2012 by Simon Sapin. + :license: BSD, see LICENSE for more details. +""" + +from __future__ import unicode_literals + +from tinycss import token_data + + +def tokenize_flat(css_source, ignore_comments=True, + # Make these local variable to avoid global lookups in the loop + tokens_dispatch=token_data.TOKEN_DISPATCH, + unicode_unescape=token_data.UNICODE_UNESCAPE, + newline_unescape=token_data.NEWLINE_UNESCAPE, + simple_unescape=token_data.SIMPLE_UNESCAPE, + find_newlines=token_data.FIND_NEWLINES, + Token=token_data.Token, + len=len, + int=int, + float=float, + list=list, + _None=None, +): + """ + :param css_source: + CSS as an unicode string + :param ignore_comments: + if true (the default) comments will not be included in the + return value + :return: + An iterator of :class:`Token` + + """ + + pos = 0 + line = 1 + column = 1 + source_len = len(css_source) + tokens = [] + while pos < source_len: + char = css_source[pos] + if char in ':;{}()[]': + type_ = char + css_value = char + else: + codepoint = min(ord(char), 160) + for _index, type_, regexp in tokens_dispatch[codepoint]: + match = regexp(css_source, pos) + if match is not None: + # First match is the longest. See comments on TOKENS above. + css_value = match.group() + break + else: + # No match. + # "Any other character not matched by the above rules, + # and neither a single nor a double quote." + # ... but quotes at the start of a token are always matched + # by STRING or BAD_STRING. So DELIM is any single character. + type_ = 'DELIM' + css_value = char + length = len(css_value) + next_pos = pos + length + + # A BAD_COMMENT is a comment at EOF. Ignore it too. + if not (ignore_comments and type_ in ('COMMENT', 'BAD_COMMENT')): + # Parse numbers, extract strings and URIs, unescape + unit = _None + if type_ == 'DIMENSION': + value = match.group(1) + value = float(value) if '.' in value else int(value) + unit = match.group(2) + unit = simple_unescape(unit) + unit = unicode_unescape(unit) + unit = unit.lower() # normalize + elif type_ == 'PERCENTAGE': + value = css_value[:-1] + value = float(value) if '.' in value else int(value) + unit = '%' + elif type_ == 'NUMBER': + value = css_value + if '.' in value: + value = float(value) + else: + value = int(value) + type_ = 'INTEGER' + elif type_ in ('IDENT', 'ATKEYWORD', 'HASH', 'FUNCTION'): + value = simple_unescape(css_value) + value = unicode_unescape(value) + elif type_ == 'URI': + value = match.group(1) + if value and value[0] in '"\'': + value = value[1:-1] # Remove quotes + value = newline_unescape(value) + value = simple_unescape(value) + value = unicode_unescape(value) + elif type_ == 'STRING': + value = css_value[1:-1] # Remove quotes + value = newline_unescape(value) + value = simple_unescape(value) + value = unicode_unescape(value) + # BAD_STRING can only be one of: + # * Unclosed string at the end of the stylesheet: + # Close the string, but this is not an error. + # Make it a "good" STRING token. + # * Unclosed string at the (unescaped) end of the line: + # Close the string, but this is an error. + # Leave it as a BAD_STRING, don’t bother parsing it. + # See http://www.w3.org/TR/CSS21/syndata.html#parsing-errors + elif type_ == 'BAD_STRING' and next_pos == source_len: + type_ = 'STRING' + value = css_value[1:] # Remove quote + value = newline_unescape(value) + value = simple_unescape(value) + value = unicode_unescape(value) + else: + value = css_value + tokens.append(Token(type_, css_value, value, unit, line, column)) + + pos = next_pos + newlines = find_newlines(css_value) + if newlines: + line += len(newlines) + # Add 1 to have lines start at column 1, not 0 + column = length - newlines[-1].end() + 1 + else: + column += length + return tokens + + +def regroup(tokens): + """ + Match pairs of tokens: () [] {} function() + (Strings in "" or '' are taken care of by the tokenizer.) + + Opening tokens are replaced by a :class:`ContainerToken`. + Closing tokens are removed. Unmatched closing tokens are invalid + but left as-is. All nested structures that are still open at + the end of the stylesheet are implicitly closed. + + :param tokens: + a *flat* iterable of tokens, as returned by :func:`tokenize_flat`. + :return: + A tree of tokens. + + """ + # "global" objects for the inner recursion + pairs = {'FUNCTION': ')', '(': ')', '[': ']', '{': '}'} + tokens = iter(tokens) + eof = [False] + + def _regroup_inner(stop_at=None, + tokens=tokens, pairs=pairs, eof=eof, + ContainerToken=token_data.ContainerToken, + FunctionToken=token_data.FunctionToken): + for token in tokens: + type_ = token.type + if type_ == stop_at: + return + + end = pairs.get(type_) + if end is None: + yield token # Not a grouping token + else: + assert not isinstance(token, ContainerToken), ( + 'Token looks already grouped: {0}'.format(token)) + content = list(_regroup_inner(end)) + if eof[0]: + end = '' # Implicit end of structure at EOF. + if type_ == 'FUNCTION': + yield FunctionToken(token.type, token.as_css(), end, + token.value, content, + token.line, token.column) + else: + yield ContainerToken(token.type, token.as_css(), end, + content, + token.line, token.column) + else: + eof[0] = True # end of file/stylesheet + return _regroup_inner() + + +def tokenize_grouped(css_source, ignore_comments=True): + """ + :param css_source: + CSS as an unicode string + :param ignore_comments: + if true (the default) comments will not be included in the + return value + :return: + An iterator of :class:`Token` + + """ + return regroup(tokenize_flat(css_source, ignore_comments)) + + +# Optional Cython version of tokenize_flat +# Make both versions available with explicit names for tests. +python_tokenize_flat = tokenize_flat + +try: + tok = token_data.load_c_tokenizer() +except (ImportError, RuntimeError): + c_tokenize_flat = None +else: + # Use the c tokenizer by default + c_tokenize_flat = tokenize_flat = lambda s, ignore_comments=False:tok.tokenize_flat(s, ignore_comments) diff --git a/ebook_converter/tinycss/version.py b/ebook_converter/tinycss/version.py new file mode 100644 index 0000000..014a8e4 --- /dev/null +++ b/ebook_converter/tinycss/version.py @@ -0,0 +1 @@ +VERSION = '0.3' diff --git a/ebook_converter/translations/__init__.py b/ebook_converter/translations/__init__.py new file mode 100644 index 0000000..bb409a2 --- /dev/null +++ b/ebook_converter/translations/__init__.py @@ -0,0 +1 @@ +from __future__ import absolute_import, division, print_function, unicode_literals diff --git a/ebook_converter/translations/dynamic.py b/ebook_converter/translations/dynamic.py new file mode 100644 index 0000000..e55e5bb --- /dev/null +++ b/ebook_converter/translations/dynamic.py @@ -0,0 +1,39 @@ +from __future__ import absolute_import, division, print_function, unicode_literals +''' +Dynamic language lookup of translations for user-visible strings. +''' + +__license__ = 'GPL v3' +__copyright__ = '2008, Marshall T. Vandegrift ' + +import io +from gettext import GNUTranslations +from calibre.constants import ispy3 +from calibre.utils.localization import get_lc_messages_path +from zipfile import ZipFile + +__all__ = ['translate'] + +_CACHE = {} + + +def translate(lang, text): + trans = None + if lang in _CACHE: + trans = _CACHE[lang] + else: + mpath = get_lc_messages_path(lang) + if mpath is not None: + with ZipFile(P('localization/locales.zip', + allow_user_override=False), 'r') as zf: + try: + buf = io.BytesIO(zf.read(mpath + '/messages.mo')) + except Exception: + pass + else: + trans = GNUTranslations(buf) + _CACHE[lang] = trans + if trans is None: + return getattr(__builtins__, '_', lambda x: x)(text) + f = getattr(trans, 'gettext' if ispy3 else 'ugettext') + return f(text) diff --git a/ebook_converter/utils/__init__.py b/ebook_converter/utils/__init__.py new file mode 100644 index 0000000..ca4af88 --- /dev/null +++ b/ebook_converter/utils/__init__.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python2 + +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net' +__docformat__ = 'restructuredtext en' + +''' +Miscelleaneous utilities. +''' + +from time import time +from polyglot.builtins import as_bytes + + +def join_with_timeout(q, timeout=2): + ''' Join the queue q with a specified timeout. Blocks until all tasks on + the queue are done or times out with a runtime error. ''' + q.all_tasks_done.acquire() + try: + endtime = time() + timeout + while q.unfinished_tasks: + remaining = endtime - time() + if remaining <= 0.0: + raise RuntimeError('Waiting for queue to clear timed out') + q.all_tasks_done.wait(remaining) + finally: + q.all_tasks_done.release() + + +def unpickle_binary_string(data): + # Maintains compatibility with python's pickle module protocol version 2 + import struct + PROTO, SHORT_BINSTRING, BINSTRING = b'\x80', b'U', b'T' + if data.startswith(PROTO + b'\x02'): + offset = 2 + which = data[offset:offset+1] + offset += 1 + if which == BINSTRING: + sz, = struct.unpack_from(' +from __future__ import absolute_import, division, print_function, unicode_literals + +import re +from polyglot.builtins import codepoint_to_chr, map, range, filter +from polyglot.html_entities import name2codepoint +from calibre.constants import plugins, preferred_encoding + +_ncxc = plugins['speedup'][0].clean_xml_chars + + +def native_clean_xml_chars(x): + if isinstance(x, bytes): + x = x.decode(preferred_encoding) + return _ncxc(x) + + +def ascii_pat(for_binary=False): + attr = 'binary' if for_binary else 'text' + ans = getattr(ascii_pat, attr, None) + if ans is None: + chars = set(range(32)) - {9, 10, 13} + chars.add(127) + pat = '|'.join(map(codepoint_to_chr, chars)) + if for_binary: + pat = pat.encode('ascii') + ans = re.compile(pat) + setattr(ascii_pat, attr, ans) + return ans + + +def clean_ascii_chars(txt, charlist=None): + r''' + Remove ASCII control chars. + This is all control chars except \t, \n and \r + ''' + is_binary = isinstance(txt, bytes) + empty = b'' if is_binary else '' + if not txt: + return empty + + if charlist is None: + pat = ascii_pat(is_binary) + else: + pat = '|'.join(map(codepoint_to_chr, charlist)) + if is_binary: + pat = pat.encode('utf-8') + return pat.sub(empty, txt) + + +def allowed(x): + x = ord(x) + return (x != 127 and (31 < x < 0xd7ff or x in (9, 10, 13))) or (0xe000 < x < 0xfffd) or (0x10000 < x < 0x10ffff) + + +def py_clean_xml_chars(unicode_string): + return ''.join(filter(allowed, unicode_string)) + + +clean_xml_chars = native_clean_xml_chars or py_clean_xml_chars + + +def test_clean_xml_chars(): + raw = 'asd\x02a\U00010437x\ud801b\udffe\ud802' + if native_clean_xml_chars(raw) != 'asda\U00010437xb': + raise ValueError('Failed to XML clean: %r' % raw) + + +# Fredrik Lundh: http://effbot.org/zone/re-sub.htm#unescape-html +# Removes HTML or XML character references and entities from a text string. +# +# @param text The HTML (or XML) source text. +# @return The plain text, as a Unicode string, if necessary. + +def unescape(text, rm=False, rchar=''): + def fixup(m, rm=rm, rchar=rchar): + text = m.group(0) + if text[:2] == "&#": + # character reference + try: + if text[:3] == "&#x": + return codepoint_to_chr(int(text[3:-1], 16)) + else: + return codepoint_to_chr(int(text[2:-1])) + except ValueError: + pass + else: + # named entity + try: + text = codepoint_to_chr(name2codepoint[text[1:-1]]) + except KeyError: + pass + if rm: + return rchar # replace by char + return text # leave as is + return re.sub("&#?\\w+;", fixup, text) diff --git a/ebook_converter/utils/config.py b/ebook_converter/utils/config.py new file mode 100644 index 0000000..0c6ded7 --- /dev/null +++ b/ebook_converter/utils/config.py @@ -0,0 +1,464 @@ +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net' +__docformat__ = 'restructuredtext en' + +''' +Manage application-wide preferences. +''' + +import optparse +import os +from copy import deepcopy + +from calibre.constants import ( + CONFIG_DIR_MODE, __appname__, __author__, config_dir, get_version, iswindows +) +from calibre.utils.config_base import ( + Config, ConfigInterface, ConfigProxy, Option, OptionSet, OptionValues, + StringConfig, json_dumps, json_loads, make_config_dir, plugin_dir, prefs, + tweaks, from_json, to_json +) +from calibre.utils.lock import ExclusiveFile +from polyglot.builtins import string_or_bytes, native_string_type + + +# optparse uses gettext.gettext instead of _ from builtins, so we +# monkey patch it. +optparse._ = _ + +if False: + # Make pyflakes happy + Config, ConfigProxy, Option, OptionValues, StringConfig, OptionSet, + ConfigInterface, tweaks, plugin_dir, prefs, from_json, to_json + + +def check_config_write_access(): + return os.access(config_dir, os.W_OK) and os.access(config_dir, os.X_OK) + + +class CustomHelpFormatter(optparse.IndentedHelpFormatter): + + def format_usage(self, usage): + from calibre.utils.terminal import colored + parts = usage.split(' ') + if parts: + parts[0] = colored(parts[0], fg='yellow', bold=True) + usage = ' '.join(parts) + return colored(_('Usage'), fg='blue', bold=True) + ': ' + usage + + def format_heading(self, heading): + from calibre.utils.terminal import colored + return "%*s%s:\n" % (self.current_indent, '', + colored(heading, fg='blue', bold=True)) + + def format_option(self, option): + import textwrap + from calibre.utils.terminal import colored + + result = [] + opts = self.option_strings[option] + opt_width = self.help_position - self.current_indent - 2 + if len(opts) > opt_width: + opts = "%*s%s\n" % (self.current_indent, "", + colored(opts, fg='green')) + indent_first = self.help_position + else: # start help on same line as opts + opts = "%*s%-*s " % (self.current_indent, "", opt_width + + len(colored('', fg='green')), colored(opts, fg='green')) + indent_first = 0 + result.append(opts) + if option.help: + help_text = self.expand_default(option).split('\n') + help_lines = [] + + for line in help_text: + help_lines.extend(textwrap.wrap(line, self.help_width)) + result.append("%*s%s\n" % (indent_first, "", help_lines[0])) + result.extend(["%*s%s\n" % (self.help_position, "", line) + for line in help_lines[1:]]) + elif opts[-1] != "\n": + result.append("\n") + return "".join(result)+'\n' + + +class OptionParser(optparse.OptionParser): + + def __init__(self, + usage='%prog [options] filename', + version=None, + epilog=None, + gui_mode=False, + conflict_handler='resolve', + **kwds): + import textwrap + from calibre.utils.terminal import colored + + usage = textwrap.dedent(usage) + if epilog is None: + epilog = _('Created by ')+colored(__author__, fg='cyan') + usage += '\n\n'+_('''Whenever you pass arguments to %prog that have spaces in them, ''' + '''enclose the arguments in quotation marks. For example: "{}"''').format( + "C:\\some path with spaces" if iswindows else '/some path/with spaces') +'\n' + if version is None: + version = '%%prog (%s %s)'%(__appname__, get_version()) + optparse.OptionParser.__init__(self, usage=usage, version=version, epilog=epilog, + formatter=CustomHelpFormatter(), + conflict_handler=conflict_handler, **kwds) + self.gui_mode = gui_mode + if False: + # Translatable string from optparse + _("Options") + _("show this help message and exit") + _("show program's version number and exit") + + def print_usage(self, file=None): + from calibre.utils.terminal import ANSIStream + s = ANSIStream(file) + optparse.OptionParser.print_usage(self, file=s) + + def print_help(self, file=None): + from calibre.utils.terminal import ANSIStream + s = ANSIStream(file) + optparse.OptionParser.print_help(self, file=s) + + def print_version(self, file=None): + from calibre.utils.terminal import ANSIStream + s = ANSIStream(file) + optparse.OptionParser.print_version(self, file=s) + + def error(self, msg): + if self.gui_mode: + raise Exception(msg) + optparse.OptionParser.error(self, msg) + + def merge(self, parser): + ''' + Add options from parser to self. In case of conflicts, conflicting options from + parser are skipped. + ''' + opts = list(parser.option_list) + groups = list(parser.option_groups) + + def merge_options(options, container): + for opt in deepcopy(options): + if not self.has_option(opt.get_opt_string()): + container.add_option(opt) + + merge_options(opts, self) + + for group in groups: + g = self.add_option_group(group.title) + merge_options(group.option_list, g) + + def subsume(self, group_name, msg=''): + ''' + Move all existing options into a subgroup named + C{group_name} with description C{msg}. + ''' + opts = [opt for opt in self.options_iter() if opt.get_opt_string() not in ('--version', '--help')] + self.option_groups = [] + subgroup = self.add_option_group(group_name, msg) + for opt in opts: + self.remove_option(opt.get_opt_string()) + subgroup.add_option(opt) + + def options_iter(self): + for opt in self.option_list: + if native_string_type(opt).strip(): + yield opt + for gr in self.option_groups: + for opt in gr.option_list: + if native_string_type(opt).strip(): + yield opt + + def option_by_dest(self, dest): + for opt in self.options_iter(): + if opt.dest == dest: + return opt + + def merge_options(self, lower, upper): + ''' + Merge options in lower and upper option lists into upper. + Default values in upper are overridden by + non default values in lower. + ''' + for dest in lower.__dict__.keys(): + if dest not in upper.__dict__: + continue + opt = self.option_by_dest(dest) + if lower.__dict__[dest] != opt.default and \ + upper.__dict__[dest] == opt.default: + upper.__dict__[dest] = lower.__dict__[dest] + + def add_option_group(self, *args, **kwargs): + if isinstance(args[0], string_or_bytes): + args = list(args) + args[0] = native_string_type(args[0]) + return optparse.OptionParser.add_option_group(self, *args, **kwargs) + + +class DynamicConfig(dict): + ''' + A replacement for QSettings that supports dynamic config keys. + Returns `None` if a config key is not found. Note that the config + data is stored in a JSON file. + ''' + + def __init__(self, name='dynamic'): + dict.__init__(self, {}) + self.name = name + self.defaults = {} + self.refresh() + + @property + def file_path(self): + return os.path.join(config_dir, self.name+'.pickle.json') + + def decouple(self, prefix): + self.name = prefix + self.name + self.refresh() + + def read_old_serialized_representation(self): + from calibre.utils.shared_file import share_open + from calibre.utils.serialize import pickle_loads + path = self.file_path.rpartition('.')[0] + try: + with share_open(path, 'rb') as f: + raw = f.read() + except EnvironmentError: + raw = b'' + try: + d = pickle_loads(raw).copy() + except Exception: + d = {} + return d + + def refresh(self, clear_current=True): + d = {} + migrate = False + if clear_current: + self.clear() + if os.path.exists(self.file_path): + with ExclusiveFile(self.file_path) as f: + raw = f.read() + if raw: + try: + d = json_loads(raw) + except Exception as err: + print('Failed to de-serialize JSON representation of stored dynamic data for {} with error: {}'.format( + self.name, err)) + else: + d = self.read_old_serialized_representation() + migrate = bool(d) + else: + d = self.read_old_serialized_representation() + migrate = bool(d) + if migrate and d: + raw = json_dumps(d, ignore_unserializable=True) + with ExclusiveFile(self.file_path) as f: + f.seek(0), f.truncate() + f.write(raw) + + self.update(d) + + def __getitem__(self, key): + try: + return dict.__getitem__(self, key) + except KeyError: + return self.defaults.get(key, None) + + def get(self, key, default=None): + try: + return dict.__getitem__(self, key) + except KeyError: + return self.defaults.get(key, default) + + def __setitem__(self, key, val): + dict.__setitem__(self, key, val) + self.commit() + + def set(self, key, val): + self.__setitem__(key, val) + + def commit(self): + if not getattr(self, 'name', None): + return + if not os.path.exists(self.file_path): + make_config_dir() + raw = json_dumps(self) + with ExclusiveFile(self.file_path) as f: + f.seek(0) + f.truncate() + f.write(raw) + + +dynamic = DynamicConfig() + + +class XMLConfig(dict): + + ''' + Similar to :class:`DynamicConfig`, except that it uses an XML storage + backend instead of a pickle file. + + See `https://docs.python.org/dev/library/plistlib.html`_ for the supported + data types. + ''' + + EXTENSION = '.plist' + + def __init__(self, rel_path_to_cf_file, base_path=config_dir): + dict.__init__(self) + self.no_commit = False + self.defaults = {} + self.file_path = os.path.join(base_path, + *(rel_path_to_cf_file.split('/'))) + self.file_path = os.path.abspath(self.file_path) + if not self.file_path.endswith(self.EXTENSION): + self.file_path += self.EXTENSION + + self.refresh() + + def mtime(self): + try: + return os.path.getmtime(self.file_path) + except EnvironmentError: + return 0 + + def touch(self): + try: + os.utime(self.file_path, None) + except EnvironmentError: + pass + + def raw_to_object(self, raw): + from polyglot.plistlib import loads + return loads(raw) + + def to_raw(self): + from polyglot.plistlib import dumps + return dumps(self) + + def decouple(self, prefix): + self.file_path = os.path.join(os.path.dirname(self.file_path), prefix + os.path.basename(self.file_path)) + self.refresh() + + def refresh(self, clear_current=True): + d = {} + if os.path.exists(self.file_path): + with ExclusiveFile(self.file_path) as f: + raw = f.read() + try: + d = self.raw_to_object(raw) if raw.strip() else {} + except SystemError: + pass + except: + import traceback + traceback.print_exc() + d = {} + if clear_current: + self.clear() + self.update(d) + + def __getitem__(self, key): + from polyglot.plistlib import Data + try: + ans = dict.__getitem__(self, key) + if isinstance(ans, Data): + ans = ans.data + return ans + except KeyError: + return self.defaults.get(key, None) + + def get(self, key, default=None): + from polyglot.plistlib import Data + try: + ans = dict.__getitem__(self, key) + if isinstance(ans, Data): + ans = ans.data + return ans + except KeyError: + return self.defaults.get(key, default) + + def __setitem__(self, key, val): + from polyglot.plistlib import Data + if isinstance(val, bytes): + val = Data(val) + dict.__setitem__(self, key, val) + self.commit() + + def set(self, key, val): + self.__setitem__(key, val) + + def __delitem__(self, key): + try: + dict.__delitem__(self, key) + except KeyError: + pass # ignore missing keys + else: + self.commit() + + def commit(self): + if self.no_commit: + return + if hasattr(self, 'file_path') and self.file_path: + dpath = os.path.dirname(self.file_path) + if not os.path.exists(dpath): + os.makedirs(dpath, mode=CONFIG_DIR_MODE) + with ExclusiveFile(self.file_path) as f: + raw = self.to_raw() + f.seek(0) + f.truncate() + f.write(raw) + + def __enter__(self): + self.no_commit = True + + def __exit__(self, *args): + self.no_commit = False + self.commit() + + +class JSONConfig(XMLConfig): + + EXTENSION = '.json' + + def raw_to_object(self, raw): + return json_loads(raw) + + def to_raw(self): + return json_dumps(self) + + def __getitem__(self, key): + try: + return dict.__getitem__(self, key) + except KeyError: + return self.defaults[key] + + def get(self, key, default=None): + try: + return dict.__getitem__(self, key) + except KeyError: + return self.defaults.get(key, default) + + def __setitem__(self, key, val): + dict.__setitem__(self, key, val) + self.commit() + + +class DevicePrefs: + + def __init__(self, global_prefs): + self.global_prefs = global_prefs + self.overrides = {} + + def set_overrides(self, **kwargs): + self.overrides = kwargs.copy() + + def __getitem__(self, key): + return self.overrides.get(key, self.global_prefs[key]) + + +device_prefs = DevicePrefs(prefs) diff --git a/ebook_converter/utils/config_base.py b/ebook_converter/utils/config_base.py new file mode 100644 index 0000000..8def5ba --- /dev/null +++ b/ebook_converter/utils/config_base.py @@ -0,0 +1,674 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai + +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2011, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import os, re, traceback, numbers +from functools import partial +from collections import defaultdict +from copy import deepcopy + +from calibre.utils.lock import ExclusiveFile +from calibre.constants import config_dir, CONFIG_DIR_MODE, ispy3, preferred_encoding, filesystem_encoding, iswindows +from polyglot.builtins import unicode_type, iteritems, map + +plugin_dir = os.path.join(config_dir, 'plugins') + + +def parse_old_style(src): + if ispy3: + import pickle as cPickle + else: + import cPickle + options = {'cPickle':cPickle} + try: + if not isinstance(src, unicode_type): + src = src.decode('utf-8') + src = src.replace('PyQt%d.QtCore' % 4, 'PyQt5.QtCore') + src = re.sub(r'cPickle\.loads\(([\'"])', r'cPickle.loads(b\1', src) + exec(src, options) + except Exception as err: + try: + print('Failed to parse old style options string with error: {}'.format(err)) + except Exception: + pass + return options + + +def to_json(obj): + import datetime + if isinstance(obj, bytearray): + from base64 import standard_b64encode + return {'__class__': 'bytearray', + '__value__': standard_b64encode(bytes(obj)).decode('ascii')} + if isinstance(obj, datetime.datetime): + from calibre.utils.date import isoformat + return {'__class__': 'datetime.datetime', + '__value__': isoformat(obj, as_utc=True)} + if isinstance(obj, (set, frozenset)): + return {'__class__': 'set', '__value__': tuple(obj)} + if isinstance(obj, bytes): + return obj.decode('utf-8') + if hasattr(obj, 'toBase64'): # QByteArray + return {'__class__': 'bytearray', + '__value__': bytes(obj.toBase64()).decode('ascii')} + raise TypeError(repr(obj) + ' is not JSON serializable') + + +def safe_to_json(obj): + try: + return to_json(obj) + except Exception: + pass + + +def from_json(obj): + custom = obj.get('__class__') + if custom is not None: + if custom == 'bytearray': + from base64 import standard_b64decode + return bytearray(standard_b64decode(obj['__value__'].encode('ascii'))) + if custom == 'datetime.datetime': + from calibre.utils.iso8601 import parse_iso8601 + return parse_iso8601(obj['__value__'], assume_utc=True) + if custom == 'set': + return set(obj['__value__']) + return obj + + +def force_unicode(x): + try: + return x.decode('mbcs' if iswindows else preferred_encoding) + except UnicodeDecodeError: + try: + return x.decode(filesystem_encoding) + except UnicodeDecodeError: + return x.decode('utf-8', 'replace') + + +def force_unicode_recursive(obj): + if isinstance(obj, bytes): + return force_unicode(obj) + if isinstance(obj, (list, tuple)): + return type(obj)(map(force_unicode_recursive, obj)) + if isinstance(obj, dict): + return {force_unicode_recursive(k): force_unicode_recursive(v) for k, v in iteritems(obj)} + return obj + + +def json_dumps(obj, ignore_unserializable=False): + import json + try: + ans = json.dumps(obj, indent=2, default=safe_to_json if ignore_unserializable else to_json, sort_keys=True, ensure_ascii=False) + except UnicodeDecodeError: + obj = force_unicode_recursive(obj) + ans = json.dumps(obj, indent=2, default=safe_to_json if ignore_unserializable else to_json, sort_keys=True, ensure_ascii=False) + if not isinstance(ans, bytes): + ans = ans.encode('utf-8') + return ans + + +def json_loads(raw): + import json + if isinstance(raw, bytes): + raw = raw.decode('utf-8') + return json.loads(raw, object_hook=from_json) + + +def make_config_dir(): + if not os.path.exists(plugin_dir): + os.makedirs(plugin_dir, mode=CONFIG_DIR_MODE) + + +class Option(object): + + def __init__(self, name, switches=[], help='', type=None, choices=None, + check=None, group=None, default=None, action=None, metavar=None): + if choices: + type = 'choice' + + self.name = name + self.switches = switches + self.help = help.replace('%default', repr(default)) if help else None + self.type = type + if self.type is None and action is None and choices is None: + if isinstance(default, float): + self.type = 'float' + elif isinstance(default, numbers.Integral) and not isinstance(default, bool): + self.type = 'int' + + self.choices = choices + self.check = check + self.group = group + self.default = default + self.action = action + self.metavar = metavar + + def __eq__(self, other): + return self.name == getattr(other, 'name', other) + + def __repr__(self): + return 'Option: '+self.name + + def __str__(self): + return repr(self) + + +class OptionValues(object): + + def copy(self): + return deepcopy(self) + + +class OptionSet(object): + + OVERRIDE_PAT = re.compile(r'#{3,100} Override Options #{15}(.*?)#{3,100} End Override #{3,100}', + re.DOTALL|re.IGNORECASE) + + def __init__(self, description=''): + self.description = description + self.defaults = {} + self.preferences = [] + self.group_list = [] + self.groups = {} + self.set_buffer = {} + self.loads_pat = None + + def has_option(self, name_or_option_object): + if name_or_option_object in self.preferences: + return True + for p in self.preferences: + if p.name == name_or_option_object: + return True + return False + + def get_option(self, name_or_option_object): + idx = self.preferences.index(name_or_option_object) + if idx > -1: + return self.preferences[idx] + for p in self.preferences: + if p.name == name_or_option_object: + return p + + def add_group(self, name, description=''): + if name in self.group_list: + raise ValueError('A group by the name %s already exists in this set'%name) + self.groups[name] = description + self.group_list.append(name) + return partial(self.add_opt, group=name) + + def update(self, other): + for name in other.groups.keys(): + self.groups[name] = other.groups[name] + if name not in self.group_list: + self.group_list.append(name) + for pref in other.preferences: + if pref in self.preferences: + self.preferences.remove(pref) + self.preferences.append(pref) + + def smart_update(self, opts1, opts2): + ''' + Updates the preference values in opts1 using only the non-default preference values in opts2. + ''' + for pref in self.preferences: + new = getattr(opts2, pref.name, pref.default) + if new != pref.default: + setattr(opts1, pref.name, new) + + def remove_opt(self, name): + if name in self.preferences: + self.preferences.remove(name) + + def add_opt(self, name, switches=[], help=None, type=None, choices=None, + group=None, default=None, action=None, metavar=None): + ''' + Add an option to this section. + + :param name: The name of this option. Must be a valid Python identifier. + Must also be unique in this OptionSet and all its subsets. + :param switches: List of command line switches for this option + (as supplied to :module:`optparse`). If empty, this + option will not be added to the command line parser. + :param help: Help text. + :param type: Type checking of option values. Supported types are: + `None, 'choice', 'complex', 'float', 'int', 'string'`. + :param choices: List of strings or `None`. + :param group: Group this option belongs to. You must previously + have created this group with a call to :method:`add_group`. + :param default: The default value for this option. + :param action: The action to pass to optparse. Supported values are: + `None, 'count'`. For choices and boolean options, + action is automatically set correctly. + ''' + pref = Option(name, switches=switches, help=help, type=type, choices=choices, + group=group, default=default, action=action, metavar=None) + if group is not None and group not in self.groups.keys(): + raise ValueError('Group %s has not been added to this section'%group) + if pref in self.preferences: + raise ValueError('An option with the name %s already exists in this set.'%name) + self.preferences.append(pref) + self.defaults[name] = default + + def retranslate_help(self): + t = _ + for opt in self.preferences: + if opt.help: + opt.help = t(opt.help) + if opt.name == 'use_primary_find_in_search': + opt.help = opt.help.format(u'ñ') + + def option_parser(self, user_defaults=None, usage='', gui_mode=False): + from calibre.utils.config import OptionParser + parser = OptionParser(usage, gui_mode=gui_mode) + groups = defaultdict(lambda : parser) + for group, desc in self.groups.items(): + groups[group] = parser.add_option_group(group.upper(), desc) + + for pref in self.preferences: + if not pref.switches: + continue + g = groups[pref.group] + action = pref.action + if action is None: + action = 'store' + if pref.default is True or pref.default is False: + action = 'store_' + ('false' if pref.default else 'true') + args = dict( + dest=pref.name, + help=pref.help, + metavar=pref.metavar, + type=pref.type, + choices=pref.choices, + default=getattr(user_defaults, pref.name, pref.default), + action=action, + ) + g.add_option(*pref.switches, **args) + + return parser + + def get_override_section(self, src): + match = self.OVERRIDE_PAT.search(src) + if match: + return match.group() + return '' + + def parse_string(self, src): + options = {} + if src: + is_old_style = (isinstance(src, bytes) and src.startswith(b'#')) or (isinstance(src, unicode_type) and src.startswith(u'#')) + if is_old_style: + options = parse_old_style(src) + else: + try: + options = json_loads(src) + if not isinstance(options, dict): + raise Exception('options is not a dictionary') + except Exception as err: + try: + print('Failed to parse options string with error: {}'.format(err)) + except Exception: + pass + opts = OptionValues() + for pref in self.preferences: + val = options.get(pref.name, pref.default) + formatter = __builtins__.get(pref.type, None) + if callable(formatter): + val = formatter(val) + setattr(opts, pref.name, val) + + return opts + + def serialize(self, opts, ignore_unserializable=False): + data = {pref.name: getattr(opts, pref.name, pref.default) for pref in self.preferences} + return json_dumps(data, ignore_unserializable=ignore_unserializable) + + +class ConfigInterface(object): + + def __init__(self, description): + self.option_set = OptionSet(description=description) + self.add_opt = self.option_set.add_opt + self.add_group = self.option_set.add_group + self.remove_opt = self.remove = self.option_set.remove_opt + self.parse_string = self.option_set.parse_string + self.get_option = self.option_set.get_option + self.preferences = self.option_set.preferences + + def update(self, other): + self.option_set.update(other.option_set) + + def option_parser(self, usage='', gui_mode=False): + return self.option_set.option_parser(user_defaults=self.parse(), + usage=usage, gui_mode=gui_mode) + + def smart_update(self, opts1, opts2): + self.option_set.smart_update(opts1, opts2) + + +class Config(ConfigInterface): + ''' + A file based configuration. + ''' + + def __init__(self, basename, description=''): + ConfigInterface.__init__(self, description) + self.filename_base = basename + + @property + def config_file_path(self): + return os.path.join(config_dir, self.filename_base + '.py.json') + + def parse(self): + src = '' + migrate = False + path = self.config_file_path + if os.path.exists(path): + with ExclusiveFile(path) as f: + try: + src = f.read().decode('utf-8') + except ValueError: + print("Failed to parse", path) + traceback.print_exc() + if not src: + path = path.rpartition('.')[0] + from calibre.utils.shared_file import share_open + try: + with share_open(path, 'rb') as f: + src = f.read().decode('utf-8') + except Exception: + pass + else: + migrate = bool(src) + ans = self.option_set.parse_string(src) + if migrate: + new_src = self.option_set.serialize(ans, ignore_unserializable=True) + with ExclusiveFile(self.config_file_path) as f: + f.seek(0), f.truncate() + f.write(new_src) + return ans + + def set(self, name, val): + if not self.option_set.has_option(name): + raise ValueError('The option %s is not defined.'%name) + if not os.path.exists(config_dir): + make_config_dir() + with ExclusiveFile(self.config_file_path) as f: + src = f.read() + opts = self.option_set.parse_string(src) + setattr(opts, name, val) + src = self.option_set.serialize(opts) + f.seek(0) + f.truncate() + if isinstance(src, unicode_type): + src = src.encode('utf-8') + f.write(src) + + +class StringConfig(ConfigInterface): + ''' + A string based configuration + ''' + + def __init__(self, src, description=''): + ConfigInterface.__init__(self, description) + self.set_src(src) + + def set_src(self, src): + self.src = src + if isinstance(self.src, bytes): + self.src = self.src.decode('utf-8') + + def parse(self): + return self.option_set.parse_string(self.src) + + def set(self, name, val): + if not self.option_set.has_option(name): + raise ValueError('The option %s is not defined.'%name) + opts = self.option_set.parse_string(self.src) + setattr(opts, name, val) + self.set_src(self.option_set.serialize(opts)) + + +class ConfigProxy(object): + ''' + A Proxy to minimize file reads for widely used config settings + ''' + + def __init__(self, config): + self.__config = config + self.__opts = None + + @property + def defaults(self): + return self.__config.option_set.defaults + + def refresh(self): + self.__opts = self.__config.parse() + + def retranslate_help(self): + self.__config.option_set.retranslate_help() + + def __getitem__(self, key): + return self.get(key) + + def __setitem__(self, key, val): + return self.set(key, val) + + def __delitem__(self, key): + self.set(key, self.defaults[key]) + + def get(self, key): + if self.__opts is None: + self.refresh() + return getattr(self.__opts, key) + + def set(self, key, val): + if self.__opts is None: + self.refresh() + setattr(self.__opts, key, val) + return self.__config.set(key, val) + + def help(self, key): + return self.__config.get_option(key).help + + +def create_global_prefs(conf_obj=None): + c = Config('global', 'calibre wide preferences') if conf_obj is None else conf_obj + c.add_opt('database_path', + default=os.path.expanduser('~/library1.db'), + help=_('Path to the database in which books are stored')) + c.add_opt('filename_pattern', default=u'(?P.+) - (?P<author>[^_]+)', + help=_('Pattern to guess metadata from filenames')) + c.add_opt('isbndb_com_key', default='', + help=_('Access key for isbndb.com')) + c.add_opt('network_timeout', default=5, + help=_('Default timeout for network operations (seconds)')) + c.add_opt('library_path', default=None, + help=_('Path to directory in which your library of books is stored')) + c.add_opt('language', default=None, + help=_('The language in which to display the user interface')) + c.add_opt('output_format', default='EPUB', + help=_('The default output format for e-book conversions. When auto-converting' + ' to send to a device this can be overridden by individual device preferences.' + ' These can be changed by right clicking the device icon in calibre and' + ' choosing "Configure".')) + c.add_opt('input_format_order', default=['EPUB', 'AZW3', 'MOBI', 'LIT', 'PRC', + 'FB2', 'HTML', 'HTM', 'XHTM', 'SHTML', 'XHTML', 'ZIP', 'DOCX', 'ODT', 'RTF', 'PDF', + 'TXT'], + help=_('Ordered list of formats to prefer for input.')) + c.add_opt('read_file_metadata', default=True, + help=_('Read metadata from files')) + c.add_opt('worker_process_priority', default='normal', + help=_('The priority of worker processes. A higher priority ' + 'means they run faster and consume more resources. ' + 'Most tasks like conversion/news download/adding books/etc. ' + 'are affected by this setting.')) + c.add_opt('swap_author_names', default=False, + help=_('Swap author first and last names when reading metadata')) + c.add_opt('add_formats_to_existing', default=False, + help=_('Add new formats to existing book records')) + c.add_opt('check_for_dupes_on_ctl', default=False, + help=_('Check for duplicates when copying to another library')) + c.add_opt('installation_uuid', default=None, help='Installation UUID') + c.add_opt('new_book_tags', default=[], help=_('Tags to apply to books added to the library')) + c.add_opt('mark_new_books', default=False, help=_( + 'Mark newly added books. The mark is a temporary mark that is automatically removed when calibre is restarted.')) + + # these are here instead of the gui preferences because calibredb and + # calibre server can execute searches + c.add_opt('saved_searches', default={}, help=_('List of named saved searches')) + c.add_opt('user_categories', default={}, help=_('User-created Tag browser categories')) + c.add_opt('manage_device_metadata', default='manual', + help=_('How and when calibre updates metadata on the device.')) + c.add_opt('limit_search_columns', default=False, + help=_('When searching for text without using lookup ' + 'prefixes, as for example, Red instead of title:Red, ' + 'limit the columns searched to those named below.')) + c.add_opt('limit_search_columns_to', + default=['title', 'authors', 'tags', 'series', 'publisher'], + help=_('Choose columns to be searched when not using prefixes, ' + 'as for example, when searching for Red instead of ' + 'title:Red. Enter a list of search/lookup names ' + 'separated by commas. Only takes effect if you set the option ' + 'to limit search columns above.')) + c.add_opt('use_primary_find_in_search', default=True, + help=_(u'Characters typed in the search box will match their ' + 'accented versions, based on the language you have chosen ' + 'for the calibre interface. For example, in ' + u'English, searching for n will match both {} and n, but if ' + 'your language is Spanish it will only match n. Note that ' + 'this is much slower than a simple search on very large ' + 'libraries. Also, this option will have no effect if you turn ' + 'on case-sensitive searching')) + c.add_opt('case_sensitive', default=False, help=_( + 'Make searches case-sensitive')) + + c.add_opt('migrated', default=False, help='For Internal use. Don\'t modify.') + return c + + +prefs = ConfigProxy(create_global_prefs()) +if prefs['installation_uuid'] is None: + import uuid + prefs['installation_uuid'] = unicode_type(uuid.uuid4()) + +# Read tweaks + + +def tweaks_file(): + return os.path.join(config_dir, 'tweaks.json') + + +def make_unicode(obj): + if isinstance(obj, bytes): + try: + return obj.decode('utf-8') + except UnicodeDecodeError: + return obj.decode(preferred_encoding, errors='replace') + if isinstance(obj, (list, tuple)): + return list(map(make_unicode, obj)) + if isinstance(obj, dict): + return {make_unicode(k): make_unicode(v) for k, v in iteritems(obj)} + return obj + + +def normalize_tweak(val): + if isinstance(val, (list, tuple)): + return tuple(map(normalize_tweak, val)) + if isinstance(val, dict): + return {k: normalize_tweak(v) for k, v in iteritems(val)} + return val + + +def write_custom_tweaks(tweaks_dict): + make_config_dir() + tweaks_dict = make_unicode(tweaks_dict) + changed_tweaks = {} + default_tweaks = exec_tweaks(default_tweaks_raw()) + for key, cval in iteritems(tweaks_dict): + if key in default_tweaks and normalize_tweak(cval) == normalize_tweak(default_tweaks[key]): + continue + changed_tweaks[key] = cval + raw = json_dumps(changed_tweaks) + with open(tweaks_file(), 'wb') as f: + f.write(raw) + + +def exec_tweaks(path): + if isinstance(path, bytes): + raw = path + fname = '<string>' + else: + with open(path, 'rb') as f: + raw = f.read() + fname = f.name + code = compile(raw, fname, 'exec') + l = {} + g = {'__file__': fname} + exec(code, g, l) + return l + + +def read_custom_tweaks(): + make_config_dir() + tf = tweaks_file() + ans = {} + if os.path.exists(tf): + with open(tf, 'rb') as f: + raw = f.read() + raw = raw.strip() + if not raw: + return ans + try: + return json_loads(raw) + except Exception: + import traceback + traceback.print_exc() + return ans + old_tweaks_file = tf.rpartition('.')[0] + '.py' + if os.path.exists(old_tweaks_file): + ans = exec_tweaks(old_tweaks_file) + ans = make_unicode(ans) + write_custom_tweaks(ans) + return ans + + +def default_tweaks_raw(): + return P('default_tweaks.py', data=True, allow_user_override=False) + + +def read_tweaks(): + default_tweaks = exec_tweaks(default_tweaks_raw()) + try: + custom_tweaks = read_custom_tweaks() + except Exception: + custom_tweaks = {} + default_tweaks.update(custom_tweaks) + return default_tweaks + + +tweaks = read_tweaks() + + +def reset_tweaks_to_default(): + default_tweaks = exec_tweaks(default_tweaks_raw()) + tweaks.clear() + tweaks.update(default_tweaks) + + +class Tweak(object): + + def __init__(self, name, value): + self.name, self.value = name, value + + def __enter__(self): + self.origval = tweaks[self.name] + tweaks[self.name] = self.value + + def __exit__(self, *args): + tweaks[self.name] = self.origval diff --git a/ebook_converter/utils/date.py b/ebook_converter/utils/date.py new file mode 100644 index 0000000..9845641 --- /dev/null +++ b/ebook_converter/utils/date.py @@ -0,0 +1,485 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>' +__docformat__ = 'restructuredtext en' + +import re +from datetime import datetime, time as dtime, timedelta, MINYEAR, MAXYEAR +from functools import partial + +from calibre import strftime +from calibre.constants import iswindows, isosx, plugins, preferred_encoding +from calibre.utils.iso8601 import utc_tz, local_tz, UNDEFINED_DATE +from calibre.utils.localization import lcdata +from polyglot.builtins import unicode_type, native_string_type + +_utc_tz = utc_tz +_local_tz = local_tz + +# When parsing ambiguous dates that could be either dd-MM Or MM-dd use the +# user's locale preferences +if iswindows: + import ctypes + LOCALE_SSHORTDATE, LOCALE_USER_DEFAULT = 0x1f, 0 + buf = ctypes.create_string_buffer(b'\0', 255) + try: + ctypes.windll.kernel32.GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SSHORTDATE, buf, 255) + parse_date_day_first = buf.value.index(b'd') < buf.value.index(b'M') + except: + parse_date_day_first = False + del ctypes, LOCALE_SSHORTDATE, buf, LOCALE_USER_DEFAULT +elif isosx: + try: + date_fmt = plugins['usbobserver'][0].date_format() + parse_date_day_first = date_fmt.index('d') < date_fmt.index('M') + except: + parse_date_day_first = False +else: + try: + def first_index(raw, queries): + for q in queries: + try: + return raw.index(native_string_type(q)) + except ValueError: + pass + return -1 + + import locale + raw = locale.nl_langinfo(locale.D_FMT) + parse_date_day_first = first_index(raw, ('%d', '%a', '%A')) < first_index(raw, ('%m', '%b', '%B')) + del raw, first_index + except: + parse_date_day_first = False + +DEFAULT_DATE = datetime(2000,1,1, tzinfo=utc_tz) +EPOCH = datetime(1970, 1, 1, tzinfo=_utc_tz) + + +def is_date_undefined(qt_or_dt): + d = qt_or_dt + if d is None: + return True + if hasattr(d, 'toString'): + if hasattr(d, 'date'): + d = d.date() + try: + d = datetime(d.year(), d.month(), d.day(), tzinfo=utc_tz) + except ValueError: + return True # Undefined QDate + return d.year < UNDEFINED_DATE.year or ( + d.year == UNDEFINED_DATE.year and + d.month == UNDEFINED_DATE.month and + d.day == UNDEFINED_DATE.day) + + +_iso_pat = None + + +def iso_pat(): + global _iso_pat + if _iso_pat is None: + _iso_pat = re.compile(r'\d{4}[/.-]\d{1,2}[/.-]\d{1,2}') + return _iso_pat + + +def parse_date(date_string, assume_utc=False, as_utc=True, default=None): + ''' + Parse a date/time string into a timezone aware datetime object. The timezone + is always either UTC or the local timezone. + + :param assume_utc: If True and date_string does not specify a timezone, + assume UTC, otherwise assume local timezone. + + :param as_utc: If True, return a UTC datetime + + :param default: Missing fields are filled in from default. If None, the + current month and year are used. + ''' + from dateutil.parser import parse + if not date_string: + return UNDEFINED_DATE + if isinstance(date_string, bytes): + date_string = date_string.decode(preferred_encoding, 'replace') + if default is None: + func = datetime.utcnow if assume_utc else datetime.now + default = func().replace(day=15, hour=0, minute=0, second=0, microsecond=0, + tzinfo=_utc_tz if assume_utc else _local_tz) + if iso_pat().match(date_string) is not None: + dt = parse(date_string, default=default) + else: + dt = parse(date_string, default=default, dayfirst=parse_date_day_first) + if dt.tzinfo is None: + dt = dt.replace(tzinfo=_utc_tz if assume_utc else _local_tz) + return dt.astimezone(_utc_tz if as_utc else _local_tz) + + +def fix_only_date(val): + n = val + timedelta(days=1) + if n.month > val.month: + val = val.replace(day=val.day-1) + if val.day == 1: + val = val.replace(day=2) + return val + + +def parse_only_date(raw, assume_utc=True, as_utc=True): + ''' + Parse a date string that contains no time information in a manner that + guarantees that the month and year are always correct in all timezones, and + the day is at most one day wrong. + ''' + f = utcnow if assume_utc else now + default = f().replace(hour=0, minute=0, second=0, microsecond=0, + day=15) + return fix_only_date(parse_date(raw, default=default, assume_utc=assume_utc, as_utc=as_utc)) + + +def strptime(val, fmt, assume_utc=False, as_utc=True): + dt = datetime.strptime(val, fmt) + if dt.tzinfo is None: + dt = dt.replace(tzinfo=_utc_tz if assume_utc else _local_tz) + return dt.astimezone(_utc_tz if as_utc else _local_tz) + + +def dt_factory(time_t, assume_utc=False, as_utc=True): + dt = datetime(*(time_t[0:6])) + if dt.tzinfo is None: + dt = dt.replace(tzinfo=_utc_tz if assume_utc else _local_tz) + return dt.astimezone(_utc_tz if as_utc else _local_tz) + + +safeyear = lambda x: min(max(x, MINYEAR), MAXYEAR) + + +def qt_to_dt(qdate_or_qdatetime, as_utc=True): + o = qdate_or_qdatetime + if hasattr(o, 'toUTC'): + # QDateTime + o = o.toUTC() + d, t = o.date(), o.time() + try: + ans = datetime(safeyear(d.year()), d.month(), d.day(), t.hour(), t.minute(), t.second(), t.msec()*1000, utc_tz) + except ValueError: + ans = datetime(safeyear(d.year()), d.month(), 1, t.hour(), t.minute(), t.second(), t.msec()*1000, utc_tz) + if not as_utc: + ans = ans.astimezone(local_tz) + return ans + + try: + dt = datetime(safeyear(o.year()), o.month(), o.day()).replace(tzinfo=_local_tz) + except ValueError: + dt = datetime(safeyear(o.year()), o.month(), 1).replace(tzinfo=_local_tz) + return dt.astimezone(_utc_tz if as_utc else _local_tz) + + +def fromtimestamp(ctime, as_utc=True): + dt = datetime.utcfromtimestamp(ctime).replace(tzinfo=_utc_tz) + if not as_utc: + dt = dt.astimezone(_local_tz) + return dt + + +def fromordinal(day, as_utc=True): + return datetime.fromordinal(day).replace( + tzinfo=_utc_tz if as_utc else _local_tz) + + +def isoformat(date_time, assume_utc=False, as_utc=True, sep='T'): + if not hasattr(date_time, 'tzinfo'): + return unicode_type(date_time.isoformat()) + if date_time.tzinfo is None: + date_time = date_time.replace(tzinfo=_utc_tz if assume_utc else + _local_tz) + date_time = date_time.astimezone(_utc_tz if as_utc else _local_tz) + # native_string_type(sep) because isoformat barfs with unicode sep on python 2.x + return unicode_type(date_time.isoformat(native_string_type(sep))) + + +def internal_iso_format_string(): + return 'yyyy-MM-ddThh:mm:ss' + + +def w3cdtf(date_time, assume_utc=False): + if hasattr(date_time, 'tzinfo'): + if date_time.tzinfo is None: + date_time = date_time.replace(tzinfo=_utc_tz if assume_utc else + _local_tz) + date_time = date_time.astimezone(_utc_tz if as_utc else _local_tz) + return unicode_type(date_time.strftime('%Y-%m-%dT%H:%M:%SZ')) + + +def as_local_time(date_time, assume_utc=True): + if not hasattr(date_time, 'tzinfo'): + return date_time + if date_time.tzinfo is None: + date_time = date_time.replace(tzinfo=_utc_tz if assume_utc else + _local_tz) + return date_time.astimezone(_local_tz) + + +def dt_as_local(dt): + if dt.tzinfo is local_tz: + return dt + return dt.astimezone(local_tz) + + +def as_utc(date_time, assume_utc=True): + if not hasattr(date_time, 'tzinfo'): + return date_time + if date_time.tzinfo is None: + date_time = date_time.replace(tzinfo=_utc_tz if assume_utc else + _local_tz) + return date_time.astimezone(_utc_tz) + + +def now(): + return datetime.now().replace(tzinfo=_local_tz) + + +def utcnow(): + return datetime.utcnow().replace(tzinfo=_utc_tz) + + +def utcfromtimestamp(stamp): + try: + return datetime.utcfromtimestamp(stamp).replace(tzinfo=_utc_tz) + except ValueError: + # Raised if stamp is out of range for the platforms gmtime function + # For example, this happens with negative values on windows + try: + return EPOCH + timedelta(seconds=stamp) + except (ValueError, OverflowError): + # datetime can only represent years between 1 and 9999 + import traceback + traceback.print_exc() + return utcnow() + + +def timestampfromdt(dt, assume_utc=True): + return (as_utc(dt, assume_utc=assume_utc) - EPOCH).total_seconds() + +# Format date functions {{{ + + +def fd_format_hour(dt, ampm, hr): + l = len(hr) + h = dt.hour + if ampm: + h = h%12 + if l == 1: + return '%d'%h + return '%02d'%h + + +def fd_format_minute(dt, ampm, min): + l = len(min) + if l == 1: + return '%d'%dt.minute + return '%02d'%dt.minute + + +def fd_format_second(dt, ampm, sec): + l = len(sec) + if l == 1: + return '%d'%dt.second + return '%02d'%dt.second + + +def fd_format_ampm(dt, ampm, ap): + res = strftime('%p', t=dt.timetuple()) + if ap == 'AP': + return res + return res.lower() + + +def fd_format_day(dt, ampm, dy): + l = len(dy) + if l == 1: + return '%d'%dt.day + if l == 2: + return '%02d'%dt.day + return lcdata['abday' if l == 3 else 'day'][(dt.weekday() + 1) % 7] + + +def fd_format_month(dt, ampm, mo): + l = len(mo) + if l == 1: + return '%d'%dt.month + if l == 2: + return '%02d'%dt.month + return lcdata['abmon' if l == 3 else 'mon'][dt.month - 1] + + +def fd_format_year(dt, ampm, yr): + if len(yr) == 2: + return '%02d'%(dt.year % 100) + return '%04d'%dt.year + + +fd_function_index = { + 'd': fd_format_day, + 'M': fd_format_month, + 'y': fd_format_year, + 'h': fd_format_hour, + 'm': fd_format_minute, + 's': fd_format_second, + 'a': fd_format_ampm, + 'A': fd_format_ampm, + } + + +def fd_repl_func(dt, ampm, mo): + s = mo.group(0) + if not s: + return '' + return fd_function_index[s[0]](dt, ampm, s) + + +def format_date(dt, format, assume_utc=False, as_utc=False): + ''' Return a date formatted as a string using a subset of Qt's formatting codes ''' + if not format: + format = 'dd MMM yyyy' + + if not isinstance(dt, datetime): + dt = datetime.combine(dt, dtime()) + + if hasattr(dt, 'tzinfo'): + if dt.tzinfo is None: + dt = dt.replace(tzinfo=_utc_tz if assume_utc else + _local_tz) + dt = dt.astimezone(_utc_tz if as_utc else _local_tz) + + if format == 'iso': + return isoformat(dt, assume_utc=assume_utc, as_utc=as_utc) + + if dt == UNDEFINED_DATE: + return '' + + repl_func = partial(fd_repl_func, dt, 'ap' in format.lower()) + return re.sub( + '(s{1,2})|(m{1,2})|(h{1,2})|(ap)|(AP)|(d{1,4}|M{1,4}|(?:yyyy|yy))', + repl_func, format) + +# }}} + +# Clean date functions {{{ + + +def cd_has_hour(tt, dt): + tt['hour'] = dt.hour + return '' + + +def cd_has_minute(tt, dt): + tt['min'] = dt.minute + return '' + + +def cd_has_second(tt, dt): + tt['sec'] = dt.second + return '' + + +def cd_has_day(tt, dt): + tt['day'] = dt.day + return '' + + +def cd_has_month(tt, dt): + tt['mon'] = dt.month + return '' + + +def cd_has_year(tt, dt): + tt['year'] = dt.year + return '' + + +cd_function_index = { + 'd': cd_has_day, + 'M': cd_has_month, + 'y': cd_has_year, + 'h': cd_has_hour, + 'm': cd_has_minute, + 's': cd_has_second + } + + +def cd_repl_func(tt, dt, match_object): + s = match_object.group(0) + if not s: + return '' + return cd_function_index[s[0]](tt, dt) + + +def clean_date_for_sort(dt, fmt=None): + ''' Return dt with fields not in shown in format set to a default ''' + if not fmt: + fmt = 'yyMd' + + if not isinstance(dt, datetime): + dt = datetime.combine(dt, dtime()) + + if hasattr(dt, 'tzinfo'): + if dt.tzinfo is None: + dt = dt.replace(tzinfo=_local_tz) + dt = as_local_time(dt) + + if fmt == 'iso': + fmt = 'yyMdhms' + + tt = {'year':UNDEFINED_DATE.year, 'mon':UNDEFINED_DATE.month, + 'day':UNDEFINED_DATE.day, 'hour':UNDEFINED_DATE.hour, + 'min':UNDEFINED_DATE.minute, 'sec':UNDEFINED_DATE.second} + + repl_func = partial(cd_repl_func, tt, dt) + re.sub('(s{1,2})|(m{1,2})|(h{1,2})|(d{1,4}|M{1,4}|(?:yyyy|yy))', repl_func, fmt) + return dt.replace(year=tt['year'], month=tt['mon'], day=tt['day'], hour=tt['hour'], + minute=tt['min'], second=tt['sec'], microsecond=0) +# }}} + + +def replace_months(datestr, clang): + # Replace months by english equivalent for parse_date + frtoen = { + '[jJ]anvier': 'jan', + '[fF].vrier': 'feb', + '[mM]ars': 'mar', + '[aA]vril': 'apr', + '[mM]ai': 'may', + '[jJ]uin': 'jun', + '[jJ]uillet': 'jul', + '[aA]o.t': 'aug', + '[sS]eptembre': 'sep', + '[Oo]ctobre': 'oct', + '[nN]ovembre': 'nov', + '[dD].cembre': 'dec'} + detoen = { + '[jJ]anuar': 'jan', + '[fF]ebruar': 'feb', + '[mM].rz': 'mar', + '[aA]pril': 'apr', + '[mM]ai': 'may', + '[jJ]uni': 'jun', + '[jJ]uli': 'jul', + '[aA]ugust': 'aug', + '[sS]eptember': 'sep', + '[Oo]ktober': 'oct', + '[nN]ovember': 'nov', + '[dD]ezember': 'dec'} + + if clang == 'fr': + dictoen = frtoen + elif clang == 'de': + dictoen = detoen + else: + return datestr + + for k in dictoen: + tmp = re.sub(k, dictoen[k], datestr) + if tmp != datestr: + break + return tmp diff --git a/ebook_converter/utils/default_tweaks.py b/ebook_converter/utils/default_tweaks.py new file mode 100644 index 0000000..5ca16b1 --- /dev/null +++ b/ebook_converter/utils/default_tweaks.py @@ -0,0 +1,568 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +# License: GPLv3 Copyright: 2010, Kovid Goyal <kovid at kovidgoyal.net> +from __future__ import unicode_literals + +# Contains various tweaks that affect calibre behavior. Only edit this file if +# you know what you are doing. If you delete this file, it will be recreated from +# defaults. + +#: Auto increment series index +# The algorithm used to assign a book added to an existing series a series number. +# New series numbers assigned using this tweak are always integer values, except +# if a constant non-integer is specified. +# Possible values are: +# next - First available integer larger than the largest existing number +# first_free - First available integer larger than 0 +# next_free - First available integer larger than the smallest existing number +# last_free - First available integer smaller than the largest existing number. Return largest existing + 1 if no free number is found +# const - Assign the number 1 always +# no_change - Do not change the series index +# a number - Assign that number always. The number is not in quotes. Note that 0.0 can be used here. +# Examples: +# series_index_auto_increment = 'next' +# series_index_auto_increment = 'next_free' +# series_index_auto_increment = 16.5 +# +# Set the use_series_auto_increment_tweak_when_importing tweak to True to +# use the above values when importing/adding books. If this tweak is set to +# False (the default) then the series number will be set to 1 if it is not +# explicitly set during the import. If set to True, then the +# series index will be set according to the series_index_auto_increment setting. +# Note that the use_series_auto_increment_tweak_when_importing tweak is used +# only when a value is not provided during import. If the importing regular +# expression produces a value for series_index, or if you are reading metadata +# from books and the import plugin produces a value, than that value will +# be used irrespective of the setting of the tweak. +series_index_auto_increment = 'next' +use_series_auto_increment_tweak_when_importing = False + +#: Add separator after completing an author name +# Should the completion separator be append +# to the end of the completed text to +# automatically begin a new completion operation +# for authors. +# Can be either True or False +authors_completer_append_separator = False + +#: Author sort name algorithm +# The algorithm used to copy author to author_sort. +# Possible values are: +# invert: use "fn ln" -> "ln, fn" +# copy : copy author to author_sort without modification +# comma : use 'copy' if there is a ',' in the name, otherwise use 'invert' +# nocomma : "fn ln" -> "ln fn" (without the comma) +# When this tweak is changed, the author_sort values stored with each author +# must be recomputed by right-clicking on an author in the left-hand tags pane, +# selecting 'manage authors', and pressing 'Recalculate all author sort values'. +# The author name suffixes are words that are ignored when they occur at the +# end of an author name. The case of the suffix is ignored and trailing +# periods are automatically handled. The same is true for prefixes. +# The author name copy words are a set of words which if they occur in an +# author name cause the automatically generated author sort string to be +# identical to the author name. This means that the sort for a string like Acme +# Inc. will be Acme Inc. instead of Inc., Acme +author_sort_copy_method = 'comma' +author_name_suffixes = ('Jr', 'Sr', 'Inc', 'Ph.D', 'Phd', + 'MD', 'M.D', 'I', 'II', 'III', 'IV', + 'Junior', 'Senior') +author_name_prefixes = ('Mr', 'Mrs', 'Ms', 'Dr', 'Prof') +author_name_copywords = ('Corporation', 'Company', 'Co.', 'Agency', 'Council', + 'Committee', 'Inc.', 'Institute', 'Society', 'Club', 'Team') + +#: Splitting multiple author names +# By default, calibre splits a string containing multiple author names on +# ampersands and the words "and" and "with". You can customize the splitting +# by changing the regular expression below. Strings are split on whatever the +# specified regular expression matches, in addition to ampersands. +# Default: r'(?i),?\s+(and|with)\s+' +authors_split_regex = r'(?i),?\s+(and|with)\s+' + +#: Use author sort in Tag browser +# Set which author field to display in the tags pane (the list of authors, +# series, publishers etc on the left hand side). The choices are author and +# author_sort. This tweak affects only what is displayed under the authors +# category in the tags pane and Content server. Please note that if you set this +# to author_sort, it is very possible to see duplicate names in the list because +# although it is guaranteed that author names are unique, there is no such +# guarantee for author_sort values. Showing duplicates won't break anything, but +# it could lead to some confusion. When using 'author_sort', the tooltip will +# show the author's name. +# Examples: +# categories_use_field_for_author_name = 'author' +# categories_use_field_for_author_name = 'author_sort' +categories_use_field_for_author_name = 'author' + +#: Control partitioning of Tag browser +# When partitioning the tags browser, the format of the subcategory label is +# controlled by a template: categories_collapsed_name_template if sorting by +# name, categories_collapsed_rating_template if sorting by average rating, and +# categories_collapsed_popularity_template if sorting by popularity. There are +# two variables available to the template: first and last. The variable 'first' +# is the initial item in the subcategory, and the variable 'last' is the final +# item in the subcategory. Both variables are 'objects'; they each have multiple +# values that are obtained by using a suffix. For example, first.name for an +# author category will be the name of the author. The sub-values available are: +# name: the printable name of the item +# count: the number of books that references this item +# avg_rating: the average rating of all the books referencing this item +# sort: the sort value. For authors, this is the author_sort for that author +# category: the category (e.g., authors, series) that the item is in. +# Note that the "r'" in front of the { is necessary if there are backslashes +# (\ characters) in the template. It doesn't hurt anything to leave it there +# even if there aren't any backslashes. +categories_collapsed_name_template = r'{first.sort:shorten(4,,0)} - {last.sort:shorten(4,,0)}' +categories_collapsed_rating_template = r'{first.avg_rating:4.2f:ifempty(0)} - {last.avg_rating:4.2f:ifempty(0)}' +categories_collapsed_popularity_template = r'{first.count:d} - {last.count:d}' + +#: Control order of categories in the Tag browser +# Change the following dict to change the order that categories are displayed in +# the Tag browser. Items are named using their lookup name, and will be sorted +# using the number supplied. The lookup name '*' stands for all names that +# otherwise do not appear. Two names with the same value will be sorted +# using the default order; the one used when the dict is empty. +# Example: tag_browser_category_order = {'series':1, 'tags':2, '*':3} +# resulting in the order series, tags, then everything else in default order. +tag_browser_category_order = {'*':1} + + +#: Specify columns to sort the booklist by on startup +# Provide a set of columns to be sorted on when calibre starts. +# The argument is None if saved sort history is to be used +# otherwise it is a list of column,order pairs. Column is the +# lookup/search name, found using the tooltip for the column +# Order is 0 for ascending, 1 for descending. +# For example, set it to [('authors',0),('title',0)] to sort by +# title within authors. +sort_columns_at_startup = None + +#: Control how dates are displayed +# Format to be used for publication date and the timestamp (date). +# A string controlling how the publication date is displayed in the GUI +# d the day as number without a leading zero (1 to 31) +# dd the day as number with a leading zero (01 to 31) +# ddd the abbreviated localized day name (e.g. 'Mon' to 'Sun'). +# dddd the long localized day name (e.g. 'Monday' to 'Sunday'). +# M the month as number without a leading zero (1-12) +# MM the month as number with a leading zero (01-12) +# MMM the abbreviated localized month name (e.g. 'Jan' to 'Dec'). +# MMMM the long localized month name (e.g. 'January' to 'December'). +# yy the year as two digit number (00-99) +# yyyy the year as four digit number +# h the hours without a leading 0 (0 to 11 or 0 to 23, depending on am/pm) ' +# hh the hours with a leading 0 (00 to 11 or 00 to 23, depending on am/pm) ' +# m the minutes without a leading 0 (0 to 59) ' +# mm the minutes with a leading 0 (00 to 59) ' +# s the seconds without a leading 0 (0 to 59) ' +# ss the seconds with a leading 0 (00 to 59) ' +# ap use a 12-hour clock instead of a 24-hour clock, with "ap" replaced by the localized string for am or pm +# AP use a 12-hour clock instead of a 24-hour clock, with "AP" replaced by the localized string for AM or PM +# iso the date with time and timezone. Must be the only format present +# For example, given the date of 9 Jan 2010, the following formats show +# MMM yyyy ==> Jan 2010 yyyy ==> 2010 dd MMM yyyy ==> 09 Jan 2010 +# MM/yyyy ==> 01/2010 d/M/yy ==> 9/1/10 yy ==> 10 +# +# publication default if not set: MMM yyyy +# timestamp default if not set: dd MMM yyyy +# last_modified_display_format if not set: dd MMM yyyy +gui_pubdate_display_format = 'MMM yyyy' +gui_timestamp_display_format = 'dd MMM yyyy' +gui_last_modified_display_format = 'dd MMM yyyy' + +#: Control sorting of titles and series in the library display +# Control title and series sorting in the library view. If set to +# 'library_order', the title sort field will be used instead of the title. +# Unless you have manually edited the title sort field, leading articles such as +# The and A will be ignored. If set to 'strictly_alphabetic', the titles will be +# sorted as-is (sort by title instead of title sort). For example, with +# library_order, The Client will sort under 'C'. With strictly_alphabetic, the +# book will sort under 'T'. +# This flag affects calibre's library display. It has no effect on devices. In +# addition, titles for books added before changing the flag will retain their +# order until the title is edited. Editing a title and hitting return +# without changing anything is sufficient to change the sort. Or you can use +# the 'Update title sort' action in the Bulk metadata edit dialog to update +# it for many books at once. +title_series_sorting = 'library_order' + +#: Control formatting of title and series when used in templates +# Control how title and series names are formatted when saving to disk/sending +# to device. The behavior depends on the field being processed. If processing +# title, then if this tweak is set to 'library_order', the title will be +# replaced with title_sort. If it is set to 'strictly_alphabetic', then the +# title will not be changed. If processing series, then if set to +# 'library_order', articles such as 'The' and 'An' will be moved to the end. If +# set to 'strictly_alphabetic', the series will be sent without change. +# For example, if the tweak is set to library_order, "The Lord of the Rings" +# will become "Lord of the Rings, The". If the tweak is set to +# strictly_alphabetic, it would remain "The Lord of the Rings". Note that the +# formatter function raw_field will return the base value for title and +# series regardless of the setting of this tweak. +save_template_title_series_sorting = 'library_order' + +#: Set the list of words considered to be "articles" for sort strings +# Set the list of words that are to be considered 'articles' when computing the +# title sort strings. The articles differ by language. By default, calibre uses +# a combination of articles from English and whatever language the calibre user +# interface is set to. In addition, in some contexts where the book language is +# available, the language of the book is used. You can change the list of +# articles for a given language or add a new language by editing +# per_language_title_sort_articles. To tell calibre to use a language other +# than the user interface language, set, default_language_for_title_sort. For +# example, to use German, set it to 'deu'. A value of None means the user +# interface language is used. The setting title_sort_articles is ignored +# (present only for legacy reasons). +per_language_title_sort_articles = { + # English + 'eng' : (r'A\s+', r'The\s+', r'An\s+'), + # Esperanto + 'epo': (r'La\s+', r"L'", 'L´'), + # Spanish + 'spa' : (r'El\s+', r'La\s+', r'Lo\s+', r'Los\s+', r'Las\s+', r'Un\s+', + r'Una\s+', r'Unos\s+', r'Unas\s+'), + # French + 'fra' : (r'Le\s+', r'La\s+', r"L'", u'L´', u'L’', r'Les\s+', r'Un\s+', r'Une\s+', + r'Des\s+', r'De\s+La\s+', r'De\s+', r"D'", u'D´', u'L’'), + # Italian + 'ita': ('Lo\\s+', 'Il\\s+', "L'", 'L´', 'La\\s+', 'Gli\\s+', + 'I\\s+', 'Le\\s+', 'Uno\\s+', 'Un\\s+', 'Una\\s+', "Un'", + 'Un´', 'Dei\\s+', 'Degli\\s+', 'Delle\\s+', 'Del\\s+', + 'Della\\s+', 'Dello\\s+', "Dell'", 'Dell´'), + # Portuguese + 'por' : (r'A\s+', r'O\s+', r'Os\s+', r'As\s+', r'Um\s+', r'Uns\s+', + r'Uma\s+', r'Umas\s+', ), + # Romanian + 'ron' : (r'Un\s+', r'O\s+', r'Nişte\s+', ), + # German + 'deu' : (r'Der\s+', r'Die\s+', r'Das\s+', r'Den\s+', r'Ein\s+', + r'Eine\s+', r'Einen\s+', r'Dem\s+', r'Des\s+', r'Einem\s+', + r'Eines\s+'), + # Dutch + 'nld' : (r'De\s+', r'Het\s+', r'Een\s+', r"'n\s+", r"'s\s+", r'Ene\s+', + r'Ener\s+', r'Enes\s+', r'Den\s+', r'Der\s+', r'Des\s+', + r"'t\s+"), + # Swedish + 'swe' : (r'En\s+', r'Ett\s+', r'Det\s+', r'Den\s+', r'De\s+', ), + # Turkish + 'tur' : (r'Bir\s+', ), + # Afrikaans + 'afr' : (r"'n\s+", r'Die\s+', ), + # Greek + 'ell' : (r'O\s+', r'I\s+', r'To\s+', r'Ta\s+', r'Tus\s+', r'Tis\s+', + r"'Enas\s+", r"'Mia\s+", r"'Ena\s+", r"'Enan\s+", ), + # Hungarian + 'hun' : (r'A\s+', r'Az\s+', r'Egy\s+',), +} +default_language_for_title_sort = None +title_sort_articles=r'^(A|The|An)\s+' + +#: Specify a folder calibre should connect to at startup +# Specify a folder that calibre should connect to at startup using +# connect_to_folder. This must be a full path to the folder. If the folder does +# not exist when calibre starts, it is ignored. +# Example for Windows: +# auto_connect_to_folder = 'C:/Users/someone/Desktop/testlib' +# Example for other operating systems: +# auto_connect_to_folder = '/home/dropbox/My Dropbox/someone/library' +auto_connect_to_folder = '' + +#: Specify renaming rules for SONY collections +# Specify renaming rules for sony collections. This tweak is only applicable if +# metadata management is set to automatic. Collections on Sonys are named +# depending upon whether the field is standard or custom. A collection derived +# from a standard field is named for the value in that field. For example, if +# the standard 'series' column contains the value 'Darkover', then the +# collection name is 'Darkover'. A collection derived from a custom field will +# have the name of the field added to the value. For example, if a custom series +# column named 'My Series' contains the name 'Darkover', then the collection +# will by default be named 'Darkover (My Series)'. For purposes of this +# documentation, 'Darkover' is called the value and 'My Series' is called the +# category. If two books have fields that generate the same collection name, +# then both books will be in that collection. +# This set of tweaks lets you specify for a standard or custom field how +# the collections are to be named. You can use it to add a description to a +# standard field, for example 'Foo (Tag)' instead of the 'Foo'. You can also use +# it to force multiple fields to end up in the same collection. For example, you +# could force the values in 'series', '#my_series_1', and '#my_series_2' to +# appear in collections named 'some_value (Series)', thereby merging all of the +# fields into one set of collections. +# There are two related tweaks. The first determines the category name to use +# for a metadata field. The second is a template, used to determines how the +# value and category are combined to create the collection name. +# The syntax of the first tweak, sony_collection_renaming_rules, is: +# {'field_lookup_name':'category_name_to_use', 'lookup_name':'name', ...} +# The second tweak, sony_collection_name_template, is a template. It uses the +# same template language as plugboards and save templates. This tweak controls +# how the value and category are combined together to make the collection name. +# The only two fields available are {category} and {value}. The {value} field is +# never empty. The {category} field can be empty. The default is to put the +# value first, then the category enclosed in parentheses, it isn't empty: +# '{value} {category:|(|)}' +# Examples: The first three examples assume that the second tweak +# has not been changed. +# 1: I want three series columns to be merged into one set of collections. The +# column lookup names are 'series', '#series_1' and '#series_2'. I want nothing +# in the parenthesis. The value to use in the tweak value would be: +# sony_collection_renaming_rules={'series':'', '#series_1':'', '#series_2':''} +# 2: I want the word '(Series)' to appear on collections made from series, and +# the word '(Tag)' to appear on collections made from tags. Use: +# sony_collection_renaming_rules={'series':'Series', 'tags':'Tag'} +# 3: I want 'series' and '#myseries' to be merged, and for the collection name +# to have '(Series)' appended. The renaming rule is: +# sony_collection_renaming_rules={'series':'Series', '#myseries':'Series'} +# 4: Same as example 2, but instead of having the category name in parentheses +# and appended to the value, I want it prepended and separated by a colon, such +# as in Series: Darkover. I must change the template used to format the category name +# The resulting two tweaks are: +# sony_collection_renaming_rules={'series':'Series', 'tags':'Tag'} +# sony_collection_name_template='{category:||: }{value}' +sony_collection_renaming_rules={} +sony_collection_name_template='{value}{category:| (|)}' + +#: Specify how SONY collections are sorted +# Specify how sony collections are sorted. This tweak is only applicable if +# metadata management is set to automatic. You can indicate which metadata is to +# be used to sort on a collection-by-collection basis. The format of the tweak +# is a list of metadata fields from which collections are made, followed by the +# name of the metadata field containing the sort value. +# Example: The following indicates that collections built from pubdate and tags +# are to be sorted by the value in the custom column '#mydate', that collections +# built from 'series' are to be sorted by 'series_index', and that all other +# collections are to be sorted by title. If a collection metadata field is not +# named, then if it is a series- based collection it is sorted by series order, +# otherwise it is sorted by title order. +# [(['pubdate', 'tags'],'#mydate'), (['series'],'series_index'), (['*'], 'title')] +# Note that the bracketing and parentheses are required. The syntax is +# [ ( [list of fields], sort field ) , ( [ list of fields ] , sort field ) ] +# Default: empty (no rules), so no collection attributes are named. +sony_collection_sorting_rules = [] + +#: Control how tags are applied when copying books to another library +# Set this to True to ensure that tags in 'Tags to add when adding +# a book' are added when copying books to another library +add_new_book_tags_when_importing_books = False + +#: Set custom metadata fields that the Content server will or will not display. +# Controls what fields are displayed when clicking the "Search" button in the +# browser to search your calibre library. +# content_server_will_display is a list of custom fields to be displayed. +# content_server_wont_display is a list of custom fields not to be displayed. +# wont_display has priority over will_display. +# The special value '*' means all custom fields. The value [] means no entries. +# Defaults: +# content_server_will_display = ['*'] +# content_server_wont_display = [] +# +# Examples: +# +# To display only the custom fields #mytags and #genre: +# content_server_will_display = ['#mytags', '#genre'] +# content_server_wont_display = [] +# +# To display all fields except #mycomments: +# content_server_will_display = ['*'] +# content_server_wont_display['#mycomments'] +content_server_will_display = ['*'] +content_server_wont_display = [] + +#: Set the maximum number of sort 'levels' +# Set the maximum number of sort 'levels' that calibre will use to resort the +# library after certain operations such as searches or device insertion. Each +# sort level adds a performance penalty. If the database is large (thousands of +# books) the penalty might be noticeable. If you are not concerned about multi- +# level sorts, and if you are seeing a slowdown, reduce the value of this tweak. +maximum_resort_levels = 5 + +#: Choose whether dates are sorted using visible fields +# Date values contain both a date and a time. When sorted, all the fields are +# used, regardless of what is displayed. Set this tweak to True to use only +# the fields that are being displayed. +sort_dates_using_visible_fields = False + +#: Fuzz value for trimming covers +# The value used for the fuzz distance when trimming a cover. +# Colors within this distance are considered equal. +# The distance is in absolute intensity units. +cover_trim_fuzz_value = 10 + +#: Control behavior of the book list +# You can control the behavior of double clicks and pressing enter on the books list. +# Choices: open_viewer, do_nothing, +# edit_cell, edit_metadata. Selecting anything other than open_viewer has the +# side effect of disabling editing a field using a single click. +# Default: open_viewer. +# Example: doubleclick_on_library_view = 'do_nothing' +# You can also control whether the book list scrolls horizontal per column or +# per pixel. Default is per column. +doubleclick_on_library_view = 'open_viewer' +enter_key_behavior = 'do_nothing' +horizontal_scrolling_per_column = True + +#: Language to use when sorting +# Setting this tweak will force sorting to use the +# collating order for the specified language. This might be useful if you run +# calibre in English but want sorting to work in the language where you live. +# Set the tweak to the desired ISO 639-1 language code, in lower case. +# You can find the list of supported locales at +# https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes +# Default: locale_for_sorting = '' -- use the language calibre displays in +# Example: locale_for_sorting = 'fr' -- sort using French rules. +# Example: locale_for_sorting = 'nb' -- sort using Norwegian rules. +locale_for_sorting = '' + +#: Number of columns for custom metadata in the edit metadata dialog +# Set whether to use one or two columns for custom metadata when editing +# metadata one book at a time. If True, then the fields are laid out using two +# columns. If False, one column is used. +metadata_single_use_2_cols_for_custom_fields = True + +#: Order of custom column(s) in edit metadata +# Controls the order that custom columns are listed in edit metadata single +# and bulk. The columns listed in the tweak are displayed first and in the +# order provided. Any columns not listed are displayed after the listed ones, +# in alphabetical order. Do note that this tweak does not change the size of +# the edit widgets. Putting comments widgets in this list may result in some +# odd widget spacing when using two-column mode. +# Enter a comma-separated list of custom field lookup names, as in +# metadata_edit_custom_column_order = ['#genre', '#mytags', '#etc'] +metadata_edit_custom_column_order = [] + +#: The number of seconds to wait before sending emails +# The number of seconds to wait before sending emails when using a +# public email server like gmx/hotmail/gmail. Default is: 5 minutes +# Setting it to lower may cause the server's SPAM controls to kick in, +# making email sending fail. Changes will take effect only after a restart of +# calibre. You can also change the list of hosts that calibre considers +# to be public relays here. Any relay host ending with one of the suffixes +# in the list below will be considered a public email server. +public_smtp_relay_delay = 301 +public_smtp_relay_host_suffixes = ['gmail.com', 'live.com', 'gmx.com'] + +#: The maximum width and height for covers saved in the calibre library +# All covers in the calibre library will be resized, preserving aspect ratio, +# to fit within this size. This is to prevent slowdowns caused by extremely +# large covers +maximum_cover_size = (1650, 2200) + +#: Where to send downloaded news +# When automatically sending downloaded news to a connected device, calibre +# will by default send it to the main memory. By changing this tweak, you can +# control where it is sent. Valid values are "main", "carda", "cardb". Note +# that if there isn't enough free space available on the location you choose, +# the files will be sent to the location with the most free space. +send_news_to_device_location = "main" + +#: Unified toolbar on macOS +# If you enable this option and restart calibre, the toolbar will be 'unified' +# with the titlebar as is normal for macOS applications. However, doing this has +# various bugs, for instance the minimum width of the toolbar becomes twice +# what it should be and it causes other random bugs on some systems, so turn it +# on at your own risk! +unified_title_toolbar_on_osx = False + +#: Save original file when converting/polishing from same format to same format +# When calibre does a conversion from the same format to the same format, for +# example, from EPUB to EPUB, the original file is saved, so that in case the +# conversion is poor, you can tweak the settings and run it again. By setting +# this to False you can prevent calibre from saving the original file. +# Similarly, by setting save_original_format_when_polishing to False you can +# prevent calibre from saving the original file when polishing. +save_original_format = True +save_original_format_when_polishing = True + +#: Number of recently viewed books to show +# Right-clicking the "View" button shows a list of recently viewed books. Control +# how many should be shown, here. +gui_view_history_size = 15 + +#: Change the font size of book details in the interface +# Change the font size at which book details are rendered in the side panel and +# comments are rendered in the metadata edit dialog. Set it to a positive or +# negative number to increase or decrease the font size. +change_book_details_font_size_by = 0 + +#: What format to default to when using the "Unpack book" feature +# The "Unpack book" feature of calibre allows direct editing of a book format. +# If multiple formats are available, calibre will offer you a choice +# of formats, defaulting to your preferred output format if it is available. +# Set this tweak to a specific value of 'EPUB' or 'AZW3' to always default +# to that format rather than your output format preference. +# Set to a value of 'remember' to use whichever format you chose last time you +# used the "Unpack book" feature. +# Examples: +# default_tweak_format = None (Use output format) +# default_tweak_format = 'EPUB' +# default_tweak_format = 'remember' +default_tweak_format = None + +#: Do not preselect a completion when editing authors/tags/series/etc. +# This means that you can make changes and press Enter and your changes will +# not be overwritten by a matching completion. However, if you wish to use the +# completions you will now have to press Tab to select one before pressing +# Enter. Which technique you prefer will depend on the state of metadata in +# your library and your personal editing style. +preselect_first_completion = False + +#: Completion mode when editing authors/tags/series/etc. +# By default, when completing items, calibre will show you all the candidates +# that start with the text you have already typed. You can instead have it show +# all candidates that contain the text you have already typed. To do this, set +# completion_mode to 'contains'. For example, if you type asi it will match both +# Asimov and Quasimodo, whereas the default behavior would match only Asimov. +completion_mode = 'prefix' + +#: Recognize numbers inside text when sorting +# This means that when sorting on text fields like title the text "Book 2" +# will sort before the text "Book 100". If you want this behavior, set +# numeric_collation = True note that doing so will cause problems with text +# that starts with numbers and is a little slower. +numeric_collation = False + +#: Sort the list of libraries alphabetically +# The list of libraries in the Copy to library and Quick switch menus are +# normally sorted by most used. However, if there are more than a certain +# number of such libraries, the sorting becomes alphabetic. You can set that +# number here. The default is ten libraries. +many_libraries = 10 + +#: Choose available output formats for conversion +# Restrict the list of available output formats in the conversion dialogs. +# For example, if you only want to convert to EPUB and AZW3, change this to +# restrict_output_formats = ['EPUB', 'AZW3']. The default value of None causes +# all available output formats to be present. +restrict_output_formats = None + +#: Set the thumbnail image quality used by the Content server +# The quality of a thumbnail is largely controlled by the compression quality +# used when creating it. Set this to a larger number to improve the quality. +# Note that the thumbnails get much larger with larger compression quality +# numbers. +# The value can be between 50 and 99 +content_server_thumbnail_compression_quality = 75 + +#: Image file types to treat as e-books when dropping onto the "Book details" panel +# Normally, if you drop any image file in a format known to calibre onto the +# "Book details" panel, it will be used to set the cover. If you want to store +# some image types as e-books instead, you can set this tweak. +# Examples: +# cover_drop_exclude = {'tiff', 'webp'} +cover_drop_exclude = () + +#: Show the Saved searches box in the Search bar +# In newer versions of calibre, only a single button that allows you to add a +# new Saved search is shown in the Search bar. If you would like to have the +# old Saved searches box with its two buttons back, set this tweak to True. +show_saved_search_box = False + +#: Exclude fields when copy/pasting metadata +# You can ask calibre to not paste some metadata fields when using the +# Edit metadata->Copy metadata/Paste metadata actions. For example, +# exclude_fields_on_paste = ['cover', 'timestamp', '#mycolumn'] +# to prevent pasting of the cover, Date and custom column, mycolumn. +exclude_fields_on_paste = [] + +#: Skip internet connected check +# Skip checking whether the internet is available before downloading news. +# Useful if for some reason your operating systems network checking +# facilities are not reliable (for example NetworkManager on Linux). +skip_network_check = False diff --git a/ebook_converter/utils/filenames.py b/ebook_converter/utils/filenames.py new file mode 100644 index 0000000..2be2f92 --- /dev/null +++ b/ebook_converter/utils/filenames.py @@ -0,0 +1,642 @@ +from __future__ import absolute_import, division, print_function, unicode_literals +''' +Make strings safe for use as ASCII filenames, while trying to preserve as much +meaning as possible. +''' + +import errno +import os +import shutil +import time +from math import ceil + +from calibre import force_unicode, isbytestring, prints, sanitize_file_name +from calibre.constants import ( + filesystem_encoding, iswindows, plugins, preferred_encoding, isosx, ispy3 +) +from calibre.utils.localization import get_udc +from polyglot.builtins import iteritems, itervalues, unicode_type, range + + +def ascii_text(orig): + udc = get_udc() + try: + ascii = udc.decode(orig) + except Exception: + if isinstance(orig, unicode_type): + orig = orig.encode('ascii', 'replace') + ascii = orig.decode(preferred_encoding, 'replace') + if isinstance(ascii, bytes): + ascii = ascii.decode('ascii', 'replace') + return ascii + + +def ascii_filename(orig, substitute='_'): + if isinstance(substitute, bytes): + substitute = substitute.decode(filesystem_encoding) + orig = ascii_text(orig).replace('?', '_') + ans = ''.join(x if ord(x) >= 32 else substitute for x in orig) + return sanitize_file_name(ans, substitute=substitute) + + +def shorten_component(s, by_what): + l = len(s) + if l < by_what: + return s + l = (l - by_what)//2 + if l <= 0: + return s + return s[:l] + s[-l:] + + +def limit_component(x, limit=254): + # windows and macs use ytf-16 codepoints for length, linux uses arbitrary + # binary data, but we will assume utf-8 + filename_encoding_for_length = 'utf-16' if iswindows or isosx else 'utf-8' + + def encoded_length(): + q = x if isinstance(x, bytes) else x.encode(filename_encoding_for_length) + return len(q) + + while encoded_length() > limit: + delta = encoded_length() - limit + x = shorten_component(x, max(2, delta // 2)) + + return x + + +def shorten_components_to(length, components, more_to_take=0, last_has_extension=True): + components = [limit_component(cx) for cx in components] + filepath = os.sep.join(components) + extra = len(filepath) - (length - more_to_take) + if extra < 1: + return components + deltas = [] + for x in components: + pct = len(x)/float(len(filepath)) + deltas.append(int(ceil(pct*extra))) + ans = [] + + for i, x in enumerate(components): + delta = deltas[i] + if delta > len(x): + r = x[0] if x is components[-1] else '' + else: + if last_has_extension and x is components[-1]: + b, e = os.path.splitext(x) + if e == '.': + e = '' + r = shorten_component(b, delta)+e + if r.startswith('.'): + r = x[0]+r + else: + r = shorten_component(x, delta) + r = r.strip() + if not r: + r = x.strip()[0] if x.strip() else 'x' + ans.append(r) + if len(os.sep.join(ans)) > length: + return shorten_components_to(length, components, more_to_take+2) + return ans + + +def find_executable_in_path(name, path=None): + if path is None: + path = os.environ.get('PATH', '') + exts = '.exe .cmd .bat'.split() if iswindows and not name.endswith('.exe') else ('',) + path = path.split(os.pathsep) + for x in path: + for ext in exts: + q = os.path.abspath(os.path.join(x, name)) + ext + if os.access(q, os.X_OK): + return q + + +def is_case_sensitive(path): + ''' + Return True if the filesystem is case sensitive. + + path must be the path to an existing directory. You must have permission + to create and delete files in this directory. The results of this test + apply to the filesystem containing the directory in path. + ''' + is_case_sensitive = False + if not iswindows: + name1, name2 = ('calibre_test_case_sensitivity.txt', + 'calibre_TesT_CaSe_sensitiVitY.Txt') + f1, f2 = os.path.join(path, name1), os.path.join(path, name2) + if os.path.exists(f1): + os.remove(f1) + open(f1, 'w').close() + is_case_sensitive = not os.path.exists(f2) + os.remove(f1) + return is_case_sensitive + + +def case_preserving_open_file(path, mode='wb', mkdir_mode=0o777): + ''' + Open the file pointed to by path with the specified mode. If any + directories in path do not exist, they are created. Returns the + opened file object and the path to the opened file object. This path is + guaranteed to have the same case as the on disk path. For case insensitive + filesystems, the returned path may be different from the passed in path. + The returned path is always unicode and always an absolute path. + + If mode is None, then this function assumes that path points to a directory + and return the path to the directory as the file object. + + mkdir_mode specifies the mode with which any missing directories in path + are created. + ''' + if isbytestring(path): + path = path.decode(filesystem_encoding) + + path = os.path.abspath(path) + + sep = force_unicode(os.sep, 'ascii') + + if path.endswith(sep): + path = path[:-1] + if not path: + raise ValueError('Path must not point to root') + + components = path.split(sep) + if not components: + raise ValueError('Invalid path: %r'%path) + + cpath = sep + if iswindows: + # Always upper case the drive letter and add a trailing slash so that + # the first os.listdir works correctly + cpath = components[0].upper() + sep + + bdir = path if mode is None else os.path.dirname(path) + if not os.path.exists(bdir): + os.makedirs(bdir, mkdir_mode) + + # Walk all the directories in path, putting the on disk case version of + # the directory into cpath + dirs = components[1:] if mode is None else components[1:-1] + for comp in dirs: + cdir = os.path.join(cpath, comp) + cl = comp.lower() + try: + candidates = [c for c in os.listdir(cpath) if c.lower() == cl] + except: + # Dont have permission to do the listdir, assume the case is + # correct as we have no way to check it. + pass + else: + if len(candidates) == 1: + cdir = os.path.join(cpath, candidates[0]) + # else: We are on a case sensitive file system so cdir must already + # be correct + cpath = cdir + + if mode is None: + ans = fpath = cpath + else: + fname = components[-1] + ans = lopen(os.path.join(cpath, fname), mode) + # Ensure file and all its metadata is written to disk so that subsequent + # listdir() has file name in it. I don't know if this is actually + # necessary, but given the diversity of platforms, best to be safe. + ans.flush() + os.fsync(ans.fileno()) + + cl = fname.lower() + try: + candidates = [c for c in os.listdir(cpath) if c.lower() == cl] + except EnvironmentError: + # The containing directory, somehow disappeared? + candidates = [] + if len(candidates) == 1: + fpath = os.path.join(cpath, candidates[0]) + else: + # We are on a case sensitive filesystem + fpath = os.path.join(cpath, fname) + return ans, fpath + + +def windows_get_fileid(path): + ''' The fileid uniquely identifies actual file contents (it is the same for + all hardlinks to a file). Similar to inode number on linux. ''' + import win32file + from pywintypes import error + if isbytestring(path): + path = path.decode(filesystem_encoding) + try: + h = win32file.CreateFileW(path, 0, 0, None, win32file.OPEN_EXISTING, + win32file.FILE_FLAG_BACKUP_SEMANTICS, 0) + try: + data = win32file.GetFileInformationByHandle(h) + finally: + win32file.CloseHandle(h) + except (error, EnvironmentError): + return None + return data[4], data[8], data[9] + + +def samefile_windows(src, dst): + samestring = (os.path.normcase(os.path.abspath(src)) == + os.path.normcase(os.path.abspath(dst))) + if samestring: + return True + + a, b = windows_get_fileid(src), windows_get_fileid(dst) + if a is None and b is None: + return False + return a == b + + +def samefile(src, dst): + ''' + Check if two paths point to the same actual file on the filesystem. Handles + symlinks, case insensitivity, mapped drives, etc. + + Returns True iff both paths exist and point to the same file on disk. + + Note: On windows will return True if the two string are identical (up to + case) even if the file does not exist. This is because I have no way of + knowing how reliable the GetFileInformationByHandle method is. + ''' + if iswindows: + return samefile_windows(src, dst) + + if hasattr(os.path, 'samefile'): + # Unix + try: + return os.path.samefile(src, dst) + except EnvironmentError: + return False + + # All other platforms: check for same pathname. + samestring = (os.path.normcase(os.path.abspath(src)) == + os.path.normcase(os.path.abspath(dst))) + return samestring + + +def windows_get_size(path): + ''' On windows file sizes are only accurately stored in the actual file, + not in the directory entry (which could be out of date). So we open the + file, and get the actual size. ''' + import win32file + if isbytestring(path): + path = path.decode(filesystem_encoding) + h = win32file.CreateFileW( + path, 0, win32file.FILE_SHARE_READ | win32file.FILE_SHARE_WRITE | win32file.FILE_SHARE_DELETE, + None, win32file.OPEN_EXISTING, 0, None) + try: + return win32file.GetFileSize(h) + finally: + win32file.CloseHandle(h) + + +def windows_hardlink(src, dest): + import win32file, pywintypes + try: + win32file.CreateHardLink(dest, src) + except pywintypes.error as e: + msg = 'Creating hardlink from %s to %s failed: %%s' % (src, dest) + raise OSError(msg % e) + src_size = os.path.getsize(src) + # We open and close dest, to ensure its directory entry is updated + # see http://blogs.msdn.com/b/oldnewthing/archive/2011/12/26/10251026.aspx + for i in range(10): + # If we are on a network filesystem, we have to wait for some indeterminate time, since + # network file systems are the best thing since sliced bread + try: + if windows_get_size(dest) == src_size: + return + except EnvironmentError: + pass + time.sleep(0.3) + + sz = windows_get_size(dest) + if sz != src_size: + msg = 'Creating hardlink from %s to %s failed: %%s' % (src, dest) + raise OSError(msg % ('hardlink size: %d not the same as source size' % sz)) + + +def windows_fast_hardlink(src, dest): + import win32file, pywintypes + try: + win32file.CreateHardLink(dest, src) + except pywintypes.error as e: + msg = 'Creating hardlink from %s to %s failed: %%s' % (src, dest) + raise OSError(msg % e) + ssz, dsz = windows_get_size(src), windows_get_size(dest) + if ssz != dsz: + msg = 'Creating hardlink from %s to %s failed: %%s' % (src, dest) + raise OSError(msg % ('hardlink size: %d not the same as source size: %s' % (dsz, ssz))) + + +def windows_nlinks(path): + import win32file + dwFlagsAndAttributes = win32file.FILE_FLAG_BACKUP_SEMANTICS if os.path.isdir(path) else 0 + if isbytestring(path): + path = path.decode(filesystem_encoding) + handle = win32file.CreateFileW(path, win32file.GENERIC_READ, win32file.FILE_SHARE_READ, None, win32file.OPEN_EXISTING, dwFlagsAndAttributes, None) + try: + return win32file.GetFileInformationByHandle(handle)[7] + finally: + handle.Close() + + +class WindowsAtomicFolderMove(object): + + ''' + Move all the files inside a specified folder in an atomic fashion, + preventing any other process from locking a file while the operation is + incomplete. Raises an IOError if another process has locked a file before + the operation starts. Note that this only operates on the files in the + folder, not any sub-folders. + ''' + + def __init__(self, path): + self.handle_map = {} + + import win32file, winerror + from pywintypes import error + from collections import defaultdict + + if isbytestring(path): + path = path.decode(filesystem_encoding) + + if not os.path.exists(path): + return + + names = os.listdir(path) + name_to_fileid = {x:windows_get_fileid(os.path.join(path, x)) for x in names} + fileid_to_names = defaultdict(set) + for name, fileid in iteritems(name_to_fileid): + fileid_to_names[fileid].add(name) + + for x in names: + f = os.path.normcase(os.path.abspath(os.path.join(path, x))) + if not os.path.isfile(f): + continue + try: + # Ensure the file is not read-only + win32file.SetFileAttributes(f, win32file.FILE_ATTRIBUTE_NORMAL) + except: + pass + + try: + h = win32file.CreateFileW(f, win32file.GENERIC_READ, + win32file.FILE_SHARE_DELETE, None, + win32file.OPEN_EXISTING, win32file.FILE_FLAG_SEQUENTIAL_SCAN, 0) + except error as e: + if getattr(e, 'winerror', 0) == winerror.ERROR_SHARING_VIOLATION: + # The file could be a hardlink to an already opened file, + # in which case we use the same handle for both files + fileid = name_to_fileid[x] + found = False + if fileid is not None: + for other in fileid_to_names[fileid]: + other = os.path.normcase(os.path.abspath(os.path.join(path, other))) + if other in self.handle_map: + self.handle_map[f] = self.handle_map[other] + found = True + break + if found: + continue + + self.close_handles() + if getattr(e, 'winerror', 0) == winerror.ERROR_SHARING_VIOLATION: + err = IOError(errno.EACCES, + _('File is open in another process')) + err.filename = f + raise err + prints('CreateFile failed for: %r' % f) + raise + except: + self.close_handles() + prints('CreateFile failed for: %r' % f) + raise + self.handle_map[f] = h + + def copy_path_to(self, path, dest): + import win32file + handle = None + for p, h in iteritems(self.handle_map): + if samefile_windows(path, p): + handle = h + break + if handle is None: + if os.path.exists(path): + raise ValueError('The file %r did not exist when this move' + ' operation was started'%path) + else: + raise ValueError('The file %r does not exist'%path) + try: + windows_hardlink(path, dest) + return + except: + pass + + win32file.SetFilePointer(handle, 0, win32file.FILE_BEGIN) + with lopen(dest, 'wb') as f: + while True: + hr, raw = win32file.ReadFile(handle, 1024*1024) + if hr != 0: + raise IOError(hr, 'Error while reading from %r'%path) + if not raw: + break + f.write(raw) + + def release_file(self, path): + ' Release the lock on the file pointed to by path. Will also release the lock on any hardlinks to path ' + key = None + for p, h in iteritems(self.handle_map): + if samefile_windows(path, p): + key = (p, h) + break + if key is not None: + import win32file + win32file.CloseHandle(key[1]) + remove = [f for f, h in iteritems(self.handle_map) if h is key[1]] + for x in remove: + self.handle_map.pop(x) + + def close_handles(self): + import win32file + for h in itervalues(self.handle_map): + win32file.CloseHandle(h) + self.handle_map = {} + + def delete_originals(self): + import win32file + for path in self.handle_map: + win32file.DeleteFile(path) + self.close_handles() + + +def hardlink_file(src, dest): + if iswindows: + windows_hardlink(src, dest) + return + os.link(src, dest) + + +def nlinks_file(path): + ' Return number of hardlinks to the file ' + if iswindows: + return windows_nlinks(path) + return os.stat(path).st_nlink + + +if iswindows: + def rename_file(a, b): + move_file = plugins['winutil'][0].move_file + if isinstance(a, bytes): + a = a.decode('mbcs') + if isinstance(b, bytes): + b = b.decode('mbcs') + move_file(a, b) + + +def atomic_rename(oldpath, newpath): + '''Replace the file newpath with the file oldpath. Can fail if the files + are on different volumes. If succeeds, guaranteed to be atomic. newpath may + or may not exist. If it exists, it is replaced. ''' + if iswindows: + for i in range(10): + try: + rename_file(oldpath, newpath) + break + except Exception: + if i > 8: + raise + # Try the rename repeatedly in case something like a virus + # scanner has opened one of the files (I love windows) + time.sleep(1) + else: + os.rename(oldpath, newpath) + + +def remove_dir_if_empty(path, ignore_metadata_caches=False): + ''' Remove a directory if it is empty or contains only the folder metadata + caches from different OSes. To delete the folder if it contains only + metadata caches, set ignore_metadata_caches to True.''' + try: + os.rmdir(path) + except OSError as e: + if e.errno == errno.ENOTEMPTY or len(os.listdir(path)) > 0: + # Some linux systems appear to raise an EPERM instead of an + # ENOTEMPTY, see https://bugs.launchpad.net/bugs/1240797 + if ignore_metadata_caches: + try: + found = False + for x in os.listdir(path): + if x.lower() in {'.ds_store', 'thumbs.db'}: + found = True + x = os.path.join(path, x) + if os.path.isdir(x): + import shutil + shutil.rmtree(x) + else: + os.remove(x) + except Exception: # We could get an error, if, for example, windows has locked Thumbs.db + found = False + if found: + remove_dir_if_empty(path) + return + raise + + +expanduser = os.path.expanduser + + +def format_permissions(st_mode): + import stat + for func, letter in (x.split(':') for x in 'REG:- DIR:d BLK:b CHR:c FIFO:p LNK:l SOCK:s'.split()): + if getattr(stat, 'S_IS' + func)(st_mode): + break + else: + letter = '?' + rwx = ('---', '--x', '-w-', '-wx', 'r--', 'r-x', 'rw-', 'rwx') + ans = [letter] + list(rwx[(st_mode >> 6) & 7]) + list(rwx[(st_mode >> 3) & 7]) + list(rwx[(st_mode & 7)]) + if st_mode & stat.S_ISUID: + ans[3] = 's' if (st_mode & stat.S_IXUSR) else 'S' + if st_mode & stat.S_ISGID: + ans[6] = 's' if (st_mode & stat.S_IXGRP) else 'l' + if st_mode & stat.S_ISVTX: + ans[9] = 't' if (st_mode & stat.S_IXUSR) else 'T' + return ''.join(ans) + + +def copyfile(src, dest): + shutil.copyfile(src, dest) + try: + shutil.copystat(src, dest) + except Exception: + pass + + +def get_hardlink_function(src, dest): + if iswindows: + import win32file, win32api + colon = b':' if isinstance(dest, bytes) else ':' + root = dest[0] + colon + try: + is_suitable = win32file.GetDriveType(root) not in (win32file.DRIVE_REMOTE, win32file.DRIVE_CDROM) + # See https://msdn.microsoft.com/en-us/library/windows/desktop/aa364993(v=vs.85).aspx + supports_hard_links = win32api.GetVolumeInformation(root + os.sep)[3] & 0x00400000 + except Exception: + supports_hard_links = is_suitable = False + hardlink = windows_fast_hardlink if is_suitable and supports_hard_links and src[0].lower() == dest[0].lower() else None + else: + hardlink = os.link + return hardlink + + +def copyfile_using_links(path, dest, dest_is_dir=True, filecopyfunc=copyfile): + path, dest = os.path.abspath(path), os.path.abspath(dest) + if dest_is_dir: + dest = os.path.join(dest, os.path.basename(path)) + hardlink = get_hardlink_function(path, dest) + try: + hardlink(path, dest) + except Exception: + filecopyfunc(path, dest) + + +def copytree_using_links(path, dest, dest_is_parent=True, filecopyfunc=copyfile): + path, dest = os.path.abspath(path), os.path.abspath(dest) + if dest_is_parent: + dest = os.path.join(dest, os.path.basename(path)) + hardlink = get_hardlink_function(path, dest) + try: + os.makedirs(dest) + except EnvironmentError as e: + if e.errno != errno.EEXIST: + raise + for dirpath, dirnames, filenames in os.walk(path): + base = os.path.relpath(dirpath, path) + dest_base = os.path.join(dest, base) + for dname in dirnames: + try: + os.mkdir(os.path.join(dest_base, dname)) + except EnvironmentError as e: + if e.errno != errno.EEXIST: + raise + for fname in filenames: + src, df = os.path.join(dirpath, fname), os.path.join(dest_base, fname) + try: + hardlink(src, df) + except Exception: + filecopyfunc(src, df) + + +if not ispy3 and not iswindows: + # On POSIX in python2 if you pass a unicode path to rmtree + # it tries to decode all filenames it encounters while walking + # the tree which leads to unicode errors on Linux where there + # can be non-decodeable filenames. + def rmtree(x, **kw): + if not isinstance(x, bytes): + x = x.encode('utf-8') + return shutil.rmtree(x, **kw) +else: + rmtree = shutil.rmtree diff --git a/ebook_converter/utils/fonts/__init__.py b/ebook_converter/utils/fonts/__init__.py new file mode 100644 index 0000000..720ff71 --- /dev/null +++ b/ebook_converter/utils/fonts/__init__.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>' +__docformat__ = 'restructuredtext en' diff --git a/ebook_converter/utils/fonts/metadata.py b/ebook_converter/utils/fonts/metadata.py new file mode 100644 index 0000000..aad632d --- /dev/null +++ b/ebook_converter/utils/fonts/metadata.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:fdm=marker:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>' +__docformat__ = 'restructuredtext en' + +from io import BytesIO +from struct import calcsize, unpack, unpack_from +from collections import namedtuple + +from calibre.utils.fonts.utils import get_font_names2, get_font_characteristics +from polyglot.builtins import range, unicode_type + + +class UnsupportedFont(ValueError): + pass + + +FontCharacteristics = namedtuple('FontCharacteristics', + 'weight, is_italic, is_bold, is_regular, fs_type, panose, width, is_oblique, is_wws, os2_version') +FontNames = namedtuple('FontNames', + 'family_name, subfamily_name, full_name, preferred_family_name, preferred_subfamily_name, wws_family_name, wws_subfamily_name') + + +class FontMetadata(object): + + def __init__(self, bytes_or_stream): + if not hasattr(bytes_or_stream, 'read'): + bytes_or_stream = BytesIO(bytes_or_stream) + f = bytes_or_stream + f.seek(0) + header = f.read(4) + if header not in {b'\x00\x01\x00\x00', b'OTTO'}: + raise UnsupportedFont('Not a supported sfnt variant') + + self.is_otf = header == b'OTTO' + self.read_table_metadata(f) + self.read_names(f) + self.read_characteristics(f) + + f.seek(0) + self.font_family = self.names.family_name + wt = self.characteristics.weight + if wt == 400: + wt = 'normal' + elif wt == 700: + wt = 'bold' + else: + wt = unicode_type(wt) + self.font_weight = wt + + self.font_stretch = ('ultra-condensed', 'extra-condensed', + 'condensed', 'semi-condensed', 'normal', 'semi-expanded', + 'expanded', 'extra-expanded', 'ultra-expanded')[ + self.characteristics.width-1] + if self.characteristics.is_oblique: + self.font_style = 'oblique' + elif self.characteristics.is_italic: + self.font_style = 'italic' + else: + self.font_style = 'normal' + + def read_table_metadata(self, f): + f.seek(4) + num_tables = unpack(b'>H', f.read(2))[0] + # Start of table record entries + f.seek(4 + 4*2) + table_record = b'>4s3L' + sz = calcsize(table_record) + self.tables = {} + block = f.read(sz * num_tables) + for i in range(num_tables): + table_tag, table_checksum, table_offset, table_length = \ + unpack_from(table_record, block, i*sz) + self.tables[table_tag.lower()] = (table_offset, table_length, + table_checksum) + + def read_names(self, f): + if b'name' not in self.tables: + raise UnsupportedFont('This font has no name table') + toff, tlen = self.tables[b'name'][:2] + f.seek(toff) + table = f.read(tlen) + if len(table) != tlen: + raise UnsupportedFont('This font has a name table of incorrect length') + vals = get_font_names2(table, raw_is_table=True) + self.names = FontNames(*vals) + + def read_characteristics(self, f): + if b'os/2' not in self.tables: + raise UnsupportedFont('This font has no OS/2 table') + toff, tlen = self.tables[b'os/2'][:2] + f.seek(toff) + table = f.read(tlen) + if len(table) != tlen: + raise UnsupportedFont('This font has an OS/2 table of incorrect length') + vals = get_font_characteristics(table, raw_is_table=True) + self.characteristics = FontCharacteristics(*vals) + + def to_dict(self): + ans = { + 'is_otf':self.is_otf, + 'font-family':self.font_family, + 'font-weight':self.font_weight, + 'font-style':self.font_style, + 'font-stretch':self.font_stretch + } + for f in self.names._fields: + ans[f] = getattr(self.names, f) + for f in self.characteristics._fields: + ans[f] = getattr(self.characteristics, f) + return ans + + +if __name__ == '__main__': + import sys + with open(sys.argv[-1], 'rb') as f: + fm = FontMetadata(f) + import pprint + pprint.pprint(fm.to_dict()) diff --git a/ebook_converter/utils/fonts/scanner.py b/ebook_converter/utils/fonts/scanner.py new file mode 100644 index 0000000..862b537 --- /dev/null +++ b/ebook_converter/utils/fonts/scanner.py @@ -0,0 +1,412 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:fdm=marker:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>' +__docformat__ = 'restructuredtext en' + +import os +from collections import defaultdict +from threading import Thread + +from calibre import walk, prints, as_unicode +from calibre.constants import (config_dir, iswindows, isosx, plugins, DEBUG, + isworker, filesystem_encoding) +from calibre.utils.fonts.metadata import FontMetadata, UnsupportedFont +from calibre.utils.icu import sort_key +from polyglot.builtins import itervalues, unicode_type, filter + + +class NoFonts(ValueError): + pass + +# Font dirs {{{ + + +def default_font_dirs(): + return [ + '/opt/share/fonts', + '/usr/share/fonts', + '/usr/local/share/fonts', + os.path.expanduser('~/.local/share/fonts'), + os.path.expanduser('~/.fonts') + ] + + +def fc_list(): + import ctypes + from ctypes.util import find_library + + lib = find_library('fontconfig') + if lib is None: + return default_font_dirs() + try: + lib = ctypes.CDLL(lib) + except: + return default_font_dirs() + + prototype = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p) + try: + get_font_dirs = prototype(('FcConfigGetFontDirs', lib)) + except (AttributeError): + return default_font_dirs() + prototype = ctypes.CFUNCTYPE(ctypes.c_char_p, ctypes.c_void_p) + try: + next_dir = prototype(('FcStrListNext', lib)) + except (AttributeError): + return default_font_dirs() + + prototype = ctypes.CFUNCTYPE(None, ctypes.c_void_p) + try: + end = prototype(('FcStrListDone', lib)) + except (AttributeError): + return default_font_dirs() + + str_list = get_font_dirs(ctypes.c_void_p()) + if not str_list: + return default_font_dirs() + + ans = [] + while True: + d = next_dir(str_list) + if not d: + break + if d: + try: + ans.append(d.decode(filesystem_encoding)) + except ValueError: + prints('Ignoring undecodeable font path: %r' % d) + continue + end(str_list) + if len(ans) < 3: + return default_font_dirs() + + parents, visited = [], set() + for f in ans: + path = os.path.normpath(os.path.abspath(os.path.realpath(f))) + if path == '/': + continue + head, tail = os.path.split(path) + while head and tail: + if head in visited: + break + head, tail = os.path.split(head) + else: + parents.append(path) + visited.add(path) + return parents + + +def font_dirs(): + if iswindows: + winutil, err = plugins['winutil'] + if err: + raise RuntimeError('Failed to load winutil: %s'%err) + try: + return [winutil.special_folder_path(winutil.CSIDL_FONTS)] + except ValueError: + return [r'C:\Windows\Fonts'] + if isosx: + return [ + '/Library/Fonts', + '/System/Library/Fonts', + '/usr/share/fonts', + '/var/root/Library/Fonts', + os.path.expanduser('~/.fonts'), + os.path.expanduser('~/Library/Fonts'), + ] + return fc_list() +# }}} + +# Build font family maps {{{ + + +def font_priority(font): + ''' + Try to ensure that the "Regular" face is the first font for a given + family. + ''' + style_normal = font['font-style'] == 'normal' + width_normal = font['font-stretch'] == 'normal' + weight_normal = font['font-weight'] == 'normal' + num_normal = sum(filter(None, (style_normal, width_normal, + weight_normal))) + subfamily_name = (font['wws_subfamily_name'] or + font['preferred_subfamily_name'] or font['subfamily_name']) + if num_normal == 3 and subfamily_name == 'Regular': + return 0 + if num_normal == 3: + return 1 + if subfamily_name == 'Regular': + return 2 + return 3 + (3 - num_normal) + + +def path_significance(path, folders): + path = os.path.normcase(os.path.abspath(path)) + for i, q in enumerate(folders): + if path.startswith(q): + return i + return -1 + + +def build_families(cached_fonts, folders, family_attr='font-family'): + families = defaultdict(list) + for f in itervalues(cached_fonts): + if not f: + continue + lf = icu_lower(f.get(family_attr) or '') + if lf: + families[lf].append(f) + + for fonts in itervalues(families): + # Look for duplicate font files and choose the copy that is from a + # more significant font directory (prefer user directories over + # system directories). + fmap = {} + remove = [] + for f in fonts: + fingerprint = (icu_lower(f['font-family']), f['font-weight'], + f['font-stretch'], f['font-style']) + if fingerprint in fmap: + opath = fmap[fingerprint]['path'] + npath = f['path'] + if path_significance(npath, folders) >= path_significance(opath, folders): + remove.append(fmap[fingerprint]) + fmap[fingerprint] = f + else: + remove.append(f) + else: + fmap[fingerprint] = f + for font in remove: + fonts.remove(font) + fonts.sort(key=font_priority) + + font_family_map = dict.copy(families) + font_families = tuple(sorted((f[0]['font-family'] for f in + itervalues(font_family_map)), key=sort_key)) + return font_family_map, font_families +# }}} + + +class FontScanner(Thread): + + CACHE_VERSION = 2 + + def __init__(self, folders=[], allowed_extensions={'ttf', 'otf'}): + Thread.__init__(self) + self.folders = folders + font_dirs() + [os.path.join(config_dir, 'fonts'), + P('fonts/liberation')] + self.folders = [os.path.normcase(os.path.abspath(f)) for f in + self.folders] + self.font_families = () + self.allowed_extensions = allowed_extensions + + # API {{{ + def find_font_families(self): + self.join() + return self.font_families + + def fonts_for_family(self, family): + ''' + Return a list of the faces belonging to the specified family. The first + face is the "Regular" face of family. Each face is a dictionary with + many keys, the most important of which are: path, font-family, + font-weight, font-style, font-stretch. The font-* properties follow the + CSS 3 Fonts specification. + ''' + self.join() + try: + return self.font_family_map[icu_lower(family)] + except KeyError: + raise NoFonts('No fonts found for the family: %r'%family) + + def legacy_fonts_for_family(self, family): + ''' + Return a simple set of regular, bold, italic and bold-italic faces for + the specified family. Returns a dictionary with each element being a + 2-tuple of (path to font, full font name) and the keys being: normal, + bold, italic, bi. + ''' + ans = {} + try: + faces = self.fonts_for_family(family) + except NoFonts: + return ans + for i, face in enumerate(faces): + if i == 0: + key = 'normal' + elif face['font-style'] in {'italic', 'oblique'}: + key = 'bi' if face['font-weight'] == 'bold' else 'italic' + elif face['font-weight'] == 'bold': + key = 'bold' + else: + continue + ans[key] = (face['path'], face['full_name']) + return ans + + def get_font_data(self, font_or_path): + path = font_or_path + if isinstance(font_or_path, dict): + path = font_or_path['path'] + with lopen(path, 'rb') as f: + return f.read() + + def find_font_for_text(self, text, allowed_families={'serif', 'sans-serif'}, + preferred_families=('serif', 'sans-serif', 'monospace', 'cursive', 'fantasy')): + ''' + Find a font on the system capable of rendering the given text. + + Returns a font family (as given by fonts_for_family()) that has a + "normal" font and that can render the supplied text. If no such font + exists, returns None. + + :return: (family name, faces) or None, None + ''' + from calibre.utils.fonts.utils import (supports_text, + panose_to_css_generic_family, get_printable_characters) + if not isinstance(text, unicode_type): + raise TypeError(u'%r is not unicode'%text) + text = get_printable_characters(text) + found = {} + + def filter_faces(font): + try: + raw = self.get_font_data(font) + return supports_text(raw, text) + except: + pass + return False + + for family in self.find_font_families(): + faces = list(filter(filter_faces, self.fonts_for_family(family))) + if not faces: + continue + generic_family = panose_to_css_generic_family(faces[0]['panose']) + if generic_family in allowed_families or generic_family == preferred_families[0]: + return (family, faces) + elif generic_family not in found: + found[generic_family] = (family, faces) + + for f in preferred_families: + if f in found: + return found[f] + return None, None + # }}} + + def reload_cache(self): + if not hasattr(self, 'cache'): + from calibre.utils.config import JSONConfig + self.cache = JSONConfig('fonts/scanner_cache') + else: + self.cache.refresh() + if self.cache.get('version', None) != self.CACHE_VERSION: + self.cache.clear() + self.cached_fonts = self.cache.get('fonts', {}) + + def run(self): + self.do_scan() + + def do_scan(self): + self.reload_cache() + + if isworker: + # Dont scan font files in worker processes, use whatever is + # cached. Font files typically dont change frequently enough to + # justify a rescan in a worker process. + self.build_families() + return + + cached_fonts = self.cached_fonts.copy() + self.cached_fonts.clear() + for folder in self.folders: + if not os.path.isdir(folder): + continue + try: + files = tuple(walk(folder)) + except EnvironmentError as e: + if DEBUG: + prints('Failed to walk font folder:', folder, + as_unicode(e)) + continue + for candidate in files: + if (candidate.rpartition('.')[-1].lower() not in self.allowed_extensions or not os.path.isfile(candidate)): + continue + candidate = os.path.normcase(os.path.abspath(candidate)) + try: + s = os.stat(candidate) + except EnvironmentError: + continue + fileid = '{0}||{1}:{2}'.format(candidate, s.st_size, s.st_mtime) + if fileid in cached_fonts: + # Use previously cached metadata, since the file size and + # last modified timestamp have not changed. + self.cached_fonts[fileid] = cached_fonts[fileid] + continue + try: + self.read_font_metadata(candidate, fileid) + except Exception as e: + if DEBUG: + prints('Failed to read metadata from font file:', + candidate, as_unicode(e)) + continue + + if frozenset(cached_fonts) != frozenset(self.cached_fonts): + # Write out the cache only if some font files have changed + self.write_cache() + + self.build_families() + + def build_families(self): + self.font_family_map, self.font_families = build_families(self.cached_fonts, self.folders) + + def write_cache(self): + with self.cache: + self.cache['version'] = self.CACHE_VERSION + self.cache['fonts'] = self.cached_fonts + + def force_rescan(self): + self.cached_fonts = {} + self.write_cache() + + def read_font_metadata(self, path, fileid): + with lopen(path, 'rb') as f: + try: + fm = FontMetadata(f) + except UnsupportedFont: + self.cached_fonts[fileid] = {} + else: + data = fm.to_dict() + data['path'] = path + self.cached_fonts[fileid] = data + + def dump_fonts(self): + self.join() + for family in self.font_families: + prints(family) + for font in self.fonts_for_family(family): + prints('\t%s: %s'%(font['full_name'], font['path'])) + prints(end='\t') + for key in ('font-stretch', 'font-weight', 'font-style'): + prints('%s: %s'%(key, font[key]), end=' ') + prints() + prints('\tSub-family:', font['wws_subfamily_name'] or + font['preferred_subfamily_name'] or + font['subfamily_name']) + prints() + prints() + + +font_scanner = FontScanner() +font_scanner.start() + + +def force_rescan(): + font_scanner.join() + font_scanner.force_rescan() + font_scanner.run() + + +if __name__ == '__main__': + font_scanner.dump_fonts() diff --git a/ebook_converter/utils/fonts/utils.py b/ebook_converter/utils/fonts/utils.py new file mode 100644 index 0000000..fd59876 --- /dev/null +++ b/ebook_converter/utils/fonts/utils.py @@ -0,0 +1,503 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:fdm=marker:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>' +__docformat__ = 'restructuredtext en' + +import struct +from io import BytesIO +from collections import defaultdict + +from polyglot.builtins import iteritems, itervalues, unicode_type, range, as_bytes + + +class UnsupportedFont(ValueError): + pass + + +def get_printable_characters(text): + import unicodedata + return u''.join(x for x in unicodedata.normalize('NFC', text) + if unicodedata.category(x)[0] not in {'C', 'Z', 'M'}) + + +def is_truetype_font(raw): + sfnt_version = raw[:4] + return (sfnt_version in {b'\x00\x01\x00\x00', b'OTTO'}, sfnt_version) + + +def get_tables(raw): + num_tables = struct.unpack_from(b'>H', raw, 4)[0] + offset = 4*3 # start of the table record entries + for i in range(num_tables): + table_tag, table_checksum, table_offset, table_length = struct.unpack_from( + b'>4s3L', raw, offset) + yield (table_tag, raw[table_offset:table_offset+table_length], offset, + table_offset, table_checksum) + offset += 4*4 + + +def get_table(raw, name): + ''' Get the raw table bytes for the specified table in the font ''' + name = as_bytes(name.lower()) + for table_tag, table, table_index, table_offset, table_checksum in get_tables(raw): + if table_tag.lower() == name: + return table, table_index, table_offset, table_checksum + return None, None, None, None + + +def get_font_characteristics(raw, raw_is_table=False, return_all=False): + ''' + Return (weight, is_italic, is_bold, is_regular, fs_type, panose, width, + is_oblique, is_wws). These + values are taken from the OS/2 table of the font. See + http://www.microsoft.com/typography/otspec/os2.htm for details + ''' + if raw_is_table: + os2_table = raw + else: + os2_table = get_table(raw, 'os/2')[0] + if os2_table is None: + raise UnsupportedFont('Not a supported font, has no OS/2 table') + + common_fields = b'>Hh3H11h' + (version, char_width, weight, width, fs_type, subscript_x_size, + subscript_y_size, subscript_x_offset, subscript_y_offset, + superscript_x_size, superscript_y_size, superscript_x_offset, + superscript_y_offset, strikeout_size, strikeout_position, + family_class) = struct.unpack_from(common_fields, os2_table) + offset = struct.calcsize(common_fields) + panose = struct.unpack_from(b'>10B', os2_table, offset) + offset += 10 + (range1, range2, range3, range4) = struct.unpack_from(b'>4L', os2_table, offset) + offset += struct.calcsize(b'>4L') + vendor_id = os2_table[offset:offset+4] + vendor_id + offset += 4 + selection, = struct.unpack_from(b'>H', os2_table, offset) + + is_italic = (selection & (1 << 0)) != 0 + is_bold = (selection & (1 << 5)) != 0 + is_regular = (selection & (1 << 6)) != 0 + is_wws = (selection & (1 << 8)) != 0 + is_oblique = (selection & (1 << 9)) != 0 + if return_all: + return (version, char_width, weight, width, fs_type, subscript_x_size, + subscript_y_size, subscript_x_offset, subscript_y_offset, + superscript_x_size, superscript_y_size, superscript_x_offset, + superscript_y_offset, strikeout_size, strikeout_position, + family_class, panose, selection, is_italic, is_bold, is_regular) + + return weight, is_italic, is_bold, is_regular, fs_type, panose, width, is_oblique, is_wws, version + + +def panose_to_css_generic_family(panose): + proportion = panose[3] + if proportion == 9: + return 'monospace' + family_type = panose[0] + if family_type == 3: + return 'cursive' + if family_type == 4: + return 'fantasy' + serif_style = panose[1] + if serif_style in (11, 12, 13): + return 'sans-serif' + return 'serif' + + +def decode_name_record(recs): + ''' + Get the English names of this font. See + http://www.microsoft.com/typography/otspec/name.htm for details. + ''' + if not recs: + return None + unicode_names = {} + windows_names = {} + mac_names = {} + for platform_id, encoding_id, language_id, src in recs: + if language_id > 0x8000: + continue + if platform_id == 0: + if encoding_id < 4: + try: + unicode_names[language_id] = src.decode('utf-16-be') + except ValueError: + continue + elif platform_id == 1: + try: + mac_names[language_id] = src.decode('utf-8') + except ValueError: + continue + elif platform_id == 2: + codec = {0:'ascii', 1:'utf-16-be', 2:'iso-8859-1'}.get(encoding_id, + None) + if codec is None: + continue + try: + unicode_names[language_id] = src.decode(codec) + except ValueError: + continue + elif platform_id == 3: + codec = {1:16, 10:32}.get(encoding_id, None) + if codec is None: + continue + try: + windows_names[language_id] = src.decode('utf-%d-be'%codec) + except ValueError: + continue + + # First try the windows names + # First look for the US English name + if 1033 in windows_names: + return windows_names[1033] + # Look for some other english name variant + for lang in (3081, 10249, 4105, 9225, 16393, 6153, 8201, 17417, 5129, + 13321, 18441, 7177, 11273, 2057, 12297): + if lang in windows_names: + return windows_names[lang] + + # Look for Mac name + if 0 in mac_names: + return mac_names[0] + + # Use unicode names + for val in itervalues(unicode_names): + return val + + return None + + +def _get_font_names(raw, raw_is_table=False): + if raw_is_table: + table = raw + else: + table = get_table(raw, 'name')[0] + if table is None: + raise UnsupportedFont('Not a supported font, has no name table') + table_type, count, string_offset = struct.unpack_from(b'>3H', table) + + records = defaultdict(list) + + for i in range(count): + try: + platform_id, encoding_id, language_id, name_id, length, offset = \ + struct.unpack_from(b'>6H', table, 6+i*12) + except struct.error: + break + offset += string_offset + src = table[offset:offset+length] + records[name_id].append((platform_id, encoding_id, language_id, + src)) + + return records + + +def get_font_names(raw, raw_is_table=False): + records = _get_font_names(raw, raw_is_table) + family_name = decode_name_record(records[1]) + subfamily_name = decode_name_record(records[2]) + full_name = decode_name_record(records[4]) + + return family_name, subfamily_name, full_name + + +def get_font_names2(raw, raw_is_table=False): + records = _get_font_names(raw, raw_is_table) + + family_name = decode_name_record(records[1]) + subfamily_name = decode_name_record(records[2]) + full_name = decode_name_record(records[4]) + + preferred_family_name = decode_name_record(records[16]) + preferred_subfamily_name = decode_name_record(records[17]) + + wws_family_name = decode_name_record(records[21]) + wws_subfamily_name = decode_name_record(records[22]) + + return (family_name, subfamily_name, full_name, preferred_family_name, + preferred_subfamily_name, wws_family_name, wws_subfamily_name) + + +def get_all_font_names(raw, raw_is_table=False): + records = _get_font_names(raw, raw_is_table) + ans = {} + + for name, num in iteritems({'family_name':1, 'subfamily_name':2, 'full_name':4, + 'preferred_family_name':16, 'preferred_subfamily_name':17, + 'wws_family_name':21, 'wws_subfamily_name':22}): + try: + ans[name] = decode_name_record(records[num]) + except (IndexError, KeyError, ValueError): + continue + if not ans[name]: + del ans[name] + + for platform_id, encoding_id, language_id, src in records[6]: + if (platform_id, encoding_id, language_id) == (1, 0, 0): + try: + ans['postscript_name'] = src.decode('utf-8') + break + except ValueError: + continue + elif (platform_id, encoding_id, language_id) == (3, 1, 1033): + try: + ans['postscript_name'] = src.decode('utf-16-be') + break + except ValueError: + continue + + return ans + + +def checksum_of_block(raw): + extra = 4 - len(raw)%4 + raw += b'\0'*extra + num = len(raw)//4 + return sum(struct.unpack(b'>%dI'%num, raw)) % (1<<32) + + +def verify_checksums(raw): + head_table = None + for table_tag, table, table_index, table_offset, table_checksum in get_tables(raw): + if table_tag.lower() == b'head': + version, fontrev, checksum_adj = struct.unpack_from(b'>ffL', table) + head_table = table + offset = table_offset + checksum = table_checksum + elif checksum_of_block(table) != table_checksum: + raise ValueError('The %r table has an incorrect checksum'%table_tag) + + if head_table is not None: + table = head_table + table = table[:8] + struct.pack(b'>I', 0) + table[12:] + raw = raw[:offset] + table + raw[offset+len(table):] + # Check the checksum of the head table + if checksum_of_block(table) != checksum: + raise ValueError('Checksum of head table not correct') + # Check the checksum of the entire font + checksum = checksum_of_block(raw) + q = (0xB1B0AFBA - checksum) & 0xffffffff + if q != checksum_adj: + raise ValueError('Checksum of entire font incorrect') + + +def set_checksum_adjustment(f): + offset = get_table(f.getvalue(), 'head')[2] + offset += 8 + f.seek(offset) + f.write(struct.pack(b'>I', 0)) + checksum = checksum_of_block(f.getvalue()) + q = (0xB1B0AFBA - checksum) & 0xffffffff + f.seek(offset) + f.write(struct.pack(b'>I', q)) + + +def set_table_checksum(f, name): + table, table_index, table_offset, table_checksum = get_table(f.getvalue(), name) + checksum = checksum_of_block(table) + if checksum != table_checksum: + f.seek(table_index + 4) + f.write(struct.pack(b'>I', checksum)) + + +def remove_embed_restriction(raw): + ok, sig = is_truetype_font(raw) + if not ok: + raise UnsupportedFont('Not a supported font, sfnt_version: %r'%sig) + + table, table_index, table_offset = get_table(raw, 'os/2')[:3] + if table is None: + raise UnsupportedFont('Not a supported font, has no OS/2 table') + + fs_type_offset = struct.calcsize(b'>HhHH') + fs_type = struct.unpack_from(b'>H', table, fs_type_offset)[0] + if fs_type == 0: + return raw + + f = BytesIO(raw) + f.seek(fs_type_offset + table_offset) + f.write(struct.pack(b'>H', 0)) + + set_table_checksum(f, 'os/2') + set_checksum_adjustment(f) + raw = f.getvalue() + verify_checksums(raw) + return raw + + +def is_font_embeddable(raw): + # https://www.microsoft.com/typography/otspec/os2.htm#fst + ok, sig = is_truetype_font(raw) + if not ok: + raise UnsupportedFont('Not a supported font, sfnt_version: %r'%sig) + + table, table_index, table_offset = get_table(raw, 'os/2')[:3] + if table is None: + raise UnsupportedFont('Not a supported font, has no OS/2 table') + fs_type_offset = struct.calcsize(b'>HhHH') + fs_type = struct.unpack_from(b'>H', table, fs_type_offset)[0] + if fs_type == 0 or fs_type & 0x8: + return True, fs_type + if fs_type & 1: + return False, fs_type + if fs_type & 0x200: + return False, fs_type + return True, fs_type + + +def read_bmp_prefix(table, bmp): + length, language, segcount = struct.unpack_from(b'>3H', table, bmp+2) + array_len = segcount //2 + offset = bmp + 7*2 + array_sz = 2*array_len + array = b'>%dH'%array_len + end_count = struct.unpack_from(array, table, offset) + offset += array_sz + 2 + start_count = struct.unpack_from(array, table, offset) + offset += array_sz + id_delta = struct.unpack_from(array.replace(b'H', b'h'), table, offset) + offset += array_sz + range_offset = struct.unpack_from(array, table, offset) + if length + bmp < offset + array_sz: + raise ValueError('cmap subtable length is too small') + glyph_id_len = (length + bmp - (offset + array_sz))//2 + glyph_id_map = struct.unpack_from(b'>%dH'%glyph_id_len, table, offset + + array_sz) + return (start_count, end_count, range_offset, id_delta, glyph_id_len, + glyph_id_map, array_len) + + +def get_bmp_glyph_ids(table, bmp, codes): + (start_count, end_count, range_offset, id_delta, glyph_id_len, + glyph_id_map, array_len) = read_bmp_prefix(table, bmp) + + for code in codes: + found = False + for i, ec in enumerate(end_count): + if ec >= code: + sc = start_count[i] + if sc <= code: + found = True + ro = range_offset[i] + if ro == 0: + glyph_id = id_delta[i] + code + else: + idx = ro//2 + (code - sc) + i - array_len + glyph_id = glyph_id_map[idx] + if glyph_id != 0: + glyph_id += id_delta[i] + yield glyph_id % 0x10000 + break + if not found: + yield 0 + + +def get_glyph_ids(raw, text, raw_is_table=False): + if not isinstance(text, unicode_type): + raise TypeError('%r is not a unicode object'%text) + if raw_is_table: + table = raw + else: + table = get_table(raw, 'cmap')[0] + if table is None: + raise UnsupportedFont('Not a supported font, has no cmap table') + version, num_tables = struct.unpack_from(b'>HH', table) + bmp_table = None + for i in range(num_tables): + platform_id, encoding_id, offset = struct.unpack_from(b'>HHL', table, + 4 + (i*8)) + if platform_id == 3 and encoding_id == 1: + table_format = struct.unpack_from(b'>H', table, offset)[0] + if table_format == 4: + bmp_table = offset + break + if bmp_table is None: + raise UnsupportedFont('Not a supported font, has no format 4 cmap table') + + for glyph_id in get_bmp_glyph_ids(table, bmp_table, map(ord, text)): + yield glyph_id + + +def supports_text(raw, text, has_only_printable_chars=False): + if not isinstance(text, unicode_type): + raise TypeError('%r is not a unicode object'%text) + if not has_only_printable_chars: + text = get_printable_characters(text) + try: + for glyph_id in get_glyph_ids(raw, text): + if glyph_id == 0: + return False + except: + return False + return True + + +def get_font_for_text(text, candidate_font_data=None): + ok = False + if candidate_font_data is not None: + ok = supports_text(candidate_font_data, text) + if not ok: + from calibre.utils.fonts.scanner import font_scanner + family, faces = font_scanner.find_font_for_text(text) + if faces: + with lopen(faces[0]['path'], 'rb') as f: + candidate_font_data = f.read() + return candidate_font_data + + +def test_glyph_ids(): + from calibre.utils.fonts.free_type import FreeType + data = P('fonts/liberation/LiberationSerif-Regular.ttf', data=True) + ft = FreeType() + font = ft.load_font(data) + text = u'诶йab' + ft_glyphs = tuple(font.glyph_ids(text)) + glyphs = tuple(get_glyph_ids(data, text)) + if ft_glyphs != glyphs: + raise Exception('My code and FreeType differ on the glyph ids') + + +def test_supports_text(): + data = P('fonts/calibreSymbols.otf', data=True) + if not supports_text(data, '.★½'): + raise RuntimeError('Incorrectly returning that text is not supported') + if supports_text(data, 'abc'): + raise RuntimeError('Incorrectly claiming that text is supported') + + +def test_find_font(): + from calibre.utils.fonts.scanner import font_scanner + abcd = '诶比西迪' + family = font_scanner.find_font_for_text(abcd)[0] + print('Family for Chinese text:', family) + family = font_scanner.find_font_for_text(abcd)[0] + abcd = 'لوحة المفاتيح العربية' + print('Family for Arabic text:', family) + + +def test(): + test_glyph_ids() + test_supports_text() + test_find_font() + + +def main(): + import sys, os + for arg in sys.argv[1:]: + print(os.path.basename(arg)) + with open(arg, 'rb') as f: + raw = f.read() + print(get_font_names(raw)) + characs = get_font_characteristics(raw) + print(characs) + print(panose_to_css_generic_family(characs[5])) + verify_checksums(raw) + remove_embed_restriction(raw) + + +if __name__ == '__main__': + main() diff --git a/ebook_converter/utils/formatter.py b/ebook_converter/utils/formatter.py new file mode 100644 index 0000000..a82e08c --- /dev/null +++ b/ebook_converter/utils/formatter.py @@ -0,0 +1,416 @@ +from __future__ import absolute_import, division, print_function, unicode_literals +''' +Created on 23 Sep 2010 + +@author: charles +''' + +__license__ = 'GPL v3' +__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>' +__docformat__ = 'restructuredtext en' + +import re, string, traceback, numbers + +from calibre import prints +from calibre.constants import DEBUG +from calibre.utils.formatter_functions import formatter_functions +from polyglot.builtins import unicode_type, error_message + + +class _Parser(object): + LEX_OP = 1 + LEX_ID = 2 + LEX_STR = 3 + LEX_NUM = 4 + LEX_EOF = 5 + + LEX_CONSTANTS = frozenset((LEX_STR, LEX_NUM)) + + def __init__(self, val, prog, funcs, parent): + self.lex_pos = 0 + self.prog = prog[0] + self.prog_len = len(self.prog) + if prog[1] != '': + self.error(_('failed to scan program. Invalid input {0}').format(prog[1])) + self.parent = parent + self.parent_kwargs = parent.kwargs + self.parent_book = parent.book + self.locals = {'$':val} + self.funcs = funcs + + def error(self, message): + m = 'Formatter: ' + message + _(' near ') + if self.lex_pos > 0: + m = '{0} {1}'.format(m, self.prog[self.lex_pos-1][1]) + elif self.lex_pos < self.prog_len: + m = '{0} {1}'.format(m, self.prog[self.lex_pos+1][1]) + else: + m = '{0} {1}'.format(m, _('end of program')) + raise ValueError(m) + + def token(self): + if self.lex_pos >= self.prog_len: + return None + token = self.prog[self.lex_pos][1] + self.lex_pos += 1 + return token + + def consume(self): + self.lex_pos += 1 + + def token_op_is_a_equals(self): + if self.lex_pos >= self.prog_len: + return False + token = self.prog[self.lex_pos] + return token[0] == self.LEX_OP and token[1] == '=' + + def token_op_is_a_lparen(self): + if self.lex_pos >= self.prog_len: + return False + token = self.prog[self.lex_pos] + return token[0] == self.LEX_OP and token[1] == '(' + + def token_op_is_a_rparen(self): + if self.lex_pos >= self.prog_len: + return False + token = self.prog[self.lex_pos] + return token[0] == self.LEX_OP and token[1] == ')' + + def token_op_is_a_comma(self): + if self.lex_pos >= self.prog_len: + return False + token = self.prog[self.lex_pos] + return token[0] == self.LEX_OP and token[1] == ',' + + def token_op_is_a_semicolon(self): + if self.lex_pos >= self.prog_len: + return False + token = self.prog[self.lex_pos] + return token[0] == self.LEX_OP and token[1] == ';' + + def token_is_id(self): + if self.lex_pos >= self.prog_len: + return False + return self.prog[self.lex_pos][0] == self.LEX_ID + + def token_is_constant(self): + if self.lex_pos >= self.prog_len: + return False + return self.prog[self.lex_pos][0] in self.LEX_CONSTANTS + + def token_is_eof(self): + if self.lex_pos >= self.prog_len: + return True + token = self.prog[self.lex_pos] + return token[0] == self.LEX_EOF + + def program(self): + val = self.statement() + if not self.token_is_eof(): + self.error(_('syntax error - program ends before EOF')) + return val + + def statement(self): + while True: + val = self.expr() + if self.token_is_eof(): + return val + if not self.token_op_is_a_semicolon(): + return val + self.consume() + if self.token_is_eof(): + return val + + def expr(self): + if self.token_is_id(): + # We have an identifier. Determine if it is a function + id = self.token() + if not self.token_op_is_a_lparen(): + if self.token_op_is_a_equals(): + # classic assignment statement + self.consume() + cls = self.funcs['assign'] + return cls.eval_(self.parent, self.parent_kwargs, + self.parent_book, self.locals, id, self.expr()) + val = self.locals.get(id, None) + if val is None: + self.error(_('Unknown identifier ') + id) + return val + # We have a function. + # Check if it is a known one. We do this here so error reporting is + # better, as it can identify the tokens near the problem. + id = id.strip() + if id not in self.funcs: + self.error(_('unknown function {0}').format(id)) + + # Eat the paren + self.consume() + args = list() + while not self.token_op_is_a_rparen(): + if id == 'assign' and len(args) == 0: + # Must handle the lvalue semantics of the assign function. + # The first argument is the name of the destination, not + # the value. + if not self.token_is_id(): + self.error('assign requires the first parameter be an id') + args.append(self.token()) + else: + # evaluate the argument (recursive call) + args.append(self.statement()) + if not self.token_op_is_a_comma(): + break + self.consume() + if self.token() != ')': + self.error(_('missing closing parenthesis')) + + # Evaluate the function + cls = self.funcs[id] + if cls.arg_count != -1 and len(args) != cls.arg_count: + self.error('incorrect number of arguments for function {}'.format(id)) + return cls.eval_(self.parent, self.parent_kwargs, + self.parent_book, self.locals, *args) + elif self.token_is_constant(): + # String or number + return self.token() + else: + self.error(_('expression is not function or constant')) + + +class TemplateFormatter(string.Formatter): + ''' + Provides a format function that substitutes '' for any missing value + ''' + + _validation_string = 'This Is Some Text THAT SHOULD be LONG Enough.%^&*' + + # Dict to do recursion detection. It is up to the individual get_value + # method to use it. It is cleared when starting to format a template + composite_values = {} + + def __init__(self): + string.Formatter.__init__(self) + self.book = None + self.kwargs = None + self.strip_results = True + self.locals = {} + self.funcs = formatter_functions().get_functions() + + def _do_format(self, val, fmt): + if not fmt or not val: + return val + if val == self._validation_string: + val = '0' + typ = fmt[-1] + if typ == 's': + pass + elif 'bcdoxXn'.find(typ) >= 0: + try: + val = int(val) + except Exception: + raise ValueError( + _('format: type {0} requires an integer value, got {1}').format(typ, val)) + elif 'eEfFgGn%'.find(typ) >= 0: + try: + val = float(val) + except: + raise ValueError( + _('format: type {0} requires a decimal (float) value, got {1}').format(typ, val)) + return unicode_type(('{0:'+fmt+'}').format(val)) + + def _explode_format_string(self, fmt): + try: + matches = self.format_string_re.match(fmt) + if matches is None or matches.lastindex != 3: + return fmt, '', '' + return matches.groups() + except: + if DEBUG: + traceback.print_exc() + return fmt, '', '' + + format_string_re = re.compile(r'^(.*)\|([^\|]*)\|(.*)$', re.DOTALL) + compress_spaces = re.compile(r'\s+') + backslash_comma_to_comma = re.compile(r'\\,') + + arg_parser = re.Scanner([ + (r',', lambda x,t: ''), + (r'.*?((?<!\\),)', lambda x,t: t[:-1]), + (r'.*?\)', lambda x,t: t[:-1]), + ]) + + # ################# 'Functional' template language ###################### + + lex_scanner = re.Scanner([ + (r'[(),=;]', lambda x,t: (1, t)), + (r'-?[\d\.]+', lambda x,t: (3, t)), + (r'\$', lambda x,t: (2, t)), + (r'\w+', lambda x,t: (2, t)), + (r'".*?((?<!\\)")', lambda x,t: (3, t[1:-1])), + (r'\'.*?((?<!\\)\')', lambda x,t: (3, t[1:-1])), + (r'\n#.*?(?:(?=\n)|$)', None), + (r'\s', None) + ], flags=re.DOTALL) + + def _eval_program(self, val, prog, column_name): + # keep a cache of the lex'ed program under the theory that re-lexing + # is much more expensive than the cache lookup. This is certainly true + # for more than a few tokens, but it isn't clear for simple programs. + if column_name is not None and self.template_cache is not None: + lprog = self.template_cache.get(column_name, None) + if not lprog: + lprog = self.lex_scanner.scan(prog) + self.template_cache[column_name] = lprog + else: + lprog = self.lex_scanner.scan(prog) + parser = _Parser(val, lprog, self.funcs, self) + return parser.program() + + # ################# Override parent classes methods ##################### + + def get_value(self, key, args, kwargs): + raise Exception('get_value must be implemented in the subclass') + + def format_field(self, val, fmt): + # ensure we are dealing with a string. + if isinstance(val, numbers.Number): + if val: + val = unicode_type(val) + else: + val = '' + # Handle conditional text + fmt, prefix, suffix = self._explode_format_string(fmt) + + # Handle functions + # First see if we have a functional-style expression + if fmt.startswith('\''): + p = 0 + else: + p = fmt.find(':\'') + if p >= 0: + p += 1 + if p >= 0 and fmt[-1] == '\'': + val = self._eval_program(val, fmt[p+1:-1], None) + colon = fmt[0:p].find(':') + if colon < 0: + dispfmt = '' + else: + dispfmt = fmt[0:colon] + else: + # check for old-style function references + p = fmt.find('(') + dispfmt = fmt + if p >= 0 and fmt[-1] == ')': + colon = fmt[0:p].find(':') + if colon < 0: + dispfmt = '' + colon = 0 + else: + dispfmt = fmt[0:colon] + colon += 1 + + fname = fmt[colon:p].strip() + if fname in self.funcs: + func = self.funcs[fname] + if func.arg_count == 2: + # only one arg expected. Don't bother to scan. Avoids need + # for escaping characters + args = [fmt[p+1:-1]] + else: + args = self.arg_parser.scan(fmt[p+1:])[0] + args = [self.backslash_comma_to_comma.sub(',', a) for a in args] + if (func.arg_count == 1 and (len(args) != 1 or args[0])) or \ + (func.arg_count > 1 and func.arg_count != len(args)+1): + raise ValueError('Incorrect number of arguments for function '+ fmt[0:p]) + if func.arg_count == 1: + val = func.eval_(self, self.kwargs, self.book, self.locals, val) + if self.strip_results: + val = val.strip() + else: + val = func.eval_(self, self.kwargs, self.book, self.locals, val, *args) + if self.strip_results: + val = val.strip() + else: + return _('%s: unknown function')%fname + if val: + val = self._do_format(val, dispfmt) + if not val: + return '' + return prefix + val + suffix + + def evaluate(self, fmt, args, kwargs): + if fmt.startswith('program:'): + ans = self._eval_program(kwargs.get('$', None), fmt[8:], self.column_name) + else: + ans = self.vformat(fmt, args, kwargs) + if self.strip_results: + return self.compress_spaces.sub(' ', ans).strip() + return ans + + # ######### a formatter that throws exceptions ############ + + def unsafe_format(self, fmt, kwargs, book, strip_results=True): + self.strip_results = strip_results + self.column_name = self.template_cache = None + self.kwargs = kwargs + self.book = book + self.composite_values = {} + self.locals = {} + return self.evaluate(fmt, [], kwargs) + + # ######### a formatter guaranteed not to throw an exception ############ + + def safe_format(self, fmt, kwargs, error_value, book, + column_name=None, template_cache=None, + strip_results=True, template_functions=None): + self.strip_results = strip_results + self.column_name = column_name + self.template_cache = template_cache + self.kwargs = kwargs + self.book = book + if template_functions: + self.funcs = template_functions + else: + self.funcs = formatter_functions().get_functions() + self.composite_values = {} + self.locals = {} + try: + ans = self.evaluate(fmt, [], kwargs) + except Exception as e: + if DEBUG: # and getattr(e, 'is_locking_error', False): + traceback.print_exc() + if column_name: + prints('Error evaluating column named:', column_name) + ans = error_value + ' ' + error_message(e) + return ans + + +class ValidateFormatter(TemplateFormatter): + ''' + Provides a formatter that substitutes the validation string for every value + ''' + + def get_value(self, key, args, kwargs): + return self._validation_string + + def validate(self, x): + from calibre.ebooks.metadata.book.base import Metadata + return self.safe_format(x, {}, 'VALIDATE ERROR', Metadata('')) + + +validation_formatter = ValidateFormatter() + + +class EvalFormatter(TemplateFormatter): + ''' + A template formatter that uses a simple dict instead of an mi instance + ''' + + def get_value(self, key, args, kwargs): + if key == '': + return '' + key = key.lower() + return kwargs.get(key, _('No such variable ') + key) + + +# DEPRECATED. This is not thread safe. Do not use. +eval_formatter = EvalFormatter() diff --git a/ebook_converter/utils/formatter_functions.py b/ebook_converter/utils/formatter_functions.py new file mode 100644 index 0000000..ccf96b1 --- /dev/null +++ b/ebook_converter/utils/formatter_functions.py @@ -0,0 +1,1692 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 + +''' +Created on 13 Jan 2011 + +@author: charles +''' +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>' +__docformat__ = 'restructuredtext en' + +import inspect, re, traceback, numbers +from math import trunc + +from calibre import human_readable +from calibre.constants import DEBUG +from calibre.ebooks.metadata import title_sort +from calibre.utils.config import tweaks +from calibre.utils.titlecase import titlecase +from calibre.utils.icu import capitalize, strcmp, sort_key +from calibre.utils.date import parse_date, format_date, now, UNDEFINED_DATE +from calibre.utils.localization import calibre_langcode_to_name, canonicalize_lang +from polyglot.builtins import iteritems, itervalues, unicode_type + + +class FormatterFunctions(object): + + error_function_body = ('def evaluate(self, formatter, kwargs, mi, locals):\n' + '\treturn "' + + _('Duplicate user function name {0}. ' + 'Change the name or ensure that the functions are identical') + '"') + + def __init__(self): + self._builtins = {} + self._functions = {} + self._functions_from_library = {} + + def register_builtin(self, func_class): + if not isinstance(func_class, FormatterFunction): + raise ValueError('Class %s is not an instance of FormatterFunction'%( + func_class.__class__.__name__)) + name = func_class.name + if name in self._functions: + raise ValueError('Name %s already used'%name) + self._builtins[name] = func_class + self._functions[name] = func_class + for a in func_class.aliases: + self._functions[a] = func_class + + def _register_function(self, func_class, replace=False): + if not isinstance(func_class, FormatterFunction): + raise ValueError('Class %s is not an instance of FormatterFunction'%( + func_class.__class__.__name__)) + name = func_class.name + if not replace and name in self._functions: + raise ValueError('Name %s already used'%name) + self._functions[name] = func_class + + def register_functions(self, library_uuid, funcs): + self._functions_from_library[library_uuid] = funcs + self._register_functions() + + def _register_functions(self): + for compiled_funcs in itervalues(self._functions_from_library): + for cls in compiled_funcs: + f = self._functions.get(cls.name, None) + replace = False + if f is not None: + existing_body = f.program_text + new_body = cls.program_text + if new_body != existing_body: + # Change the body of the template function to one that will + # return an error message. Also change the arg count to + # -1 (variable) to avoid template compilation errors + replace = True + func = [cls.name, '', -1, self.error_function_body.format(cls.name)] + cls = compile_user_function(*func) + else: + continue + formatter_functions()._register_function(cls, replace=replace) + + def unregister_functions(self, library_uuid): + if library_uuid in self._functions_from_library: + for cls in self._functions_from_library[library_uuid]: + self._functions.pop(cls.name, None) + self._functions_from_library.pop(library_uuid) + self._register_functions() + + def get_builtins(self): + return self._builtins + + def get_builtins_and_aliases(self): + res = {} + for f in itervalues(self._builtins): + res[f.name] = f + for a in f.aliases: + res[a] = f + return res + + def get_functions(self): + return self._functions + + def reset_to_builtins(self): + self._functions = {} + for n,c in self._builtins.items(): + self._functions[n] = c + for a in c.aliases: + self._functions[a] = c + + +_ff = FormatterFunctions() + + +def formatter_functions(): + global _ff + return _ff + + +class FormatterFunction(object): + + doc = _('No documentation provided') + name = 'no name provided' + category = 'Unknown' + arg_count = 0 + aliases = [] + + def evaluate(self, formatter, kwargs, mi, locals, *args): + raise NotImplementedError() + + def eval_(self, formatter, kwargs, mi, locals, *args): + ret = self.evaluate(formatter, kwargs, mi, locals, *args) + if isinstance(ret, (bytes, unicode_type)): + return ret + if isinstance(ret, list): + return ','.join(ret) + if isinstance(ret, (numbers.Number, bool)): + return unicode_type(ret) + + +class BuiltinFormatterFunction(FormatterFunction): + + def __init__(self): + formatter_functions().register_builtin(self) + eval_func = inspect.getmembers(self.__class__, + lambda x: inspect.ismethod(x) and x.__name__ == 'evaluate') + try: + lines = [l[4:] for l in inspect.getsourcelines(eval_func[0][1])[0]] + except: + lines = [] + self.program_text = ''.join(lines) + + +class BuiltinStrcmp(BuiltinFormatterFunction): + name = 'strcmp' + arg_count = 5 + category = 'Relational' + __doc__ = doc = _('strcmp(x, y, lt, eq, gt) -- does a case-insensitive comparison of x ' + 'and y as strings. Returns lt if x < y. Returns eq if x == y. ' + 'Otherwise returns gt.') + + def evaluate(self, formatter, kwargs, mi, locals, x, y, lt, eq, gt): + v = strcmp(x, y) + if v < 0: + return lt + if v == 0: + return eq + return gt + + +class BuiltinCmp(BuiltinFormatterFunction): + name = 'cmp' + category = 'Relational' + arg_count = 5 + __doc__ = doc = _('cmp(x, y, lt, eq, gt) -- compares x and y after converting both to ' + 'numbers. Returns lt if x < y. Returns eq if x == y. Otherwise returns gt.') + + def evaluate(self, formatter, kwargs, mi, locals, x, y, lt, eq, gt): + x = float(x if x and x != 'None' else 0) + y = float(y if y and y != 'None' else 0) + if x < y: + return lt + if x == y: + return eq + return gt + + +class BuiltinFirstMatchingCmp(BuiltinFormatterFunction): + name = 'first_matching_cmp' + category = 'Relational' + arg_count = -1 + __doc__ = doc = _('first_matching_cmp(val, cmp1, result1, cmp2, r2, ..., else_result) -- ' + 'compares "val < cmpN" in sequence, returning resultN for ' + 'the first comparison that succeeds. Returns else_result ' + 'if no comparison succeeds. Example: ' + 'first_matching_cmp(10,5,"small",10,"middle",15,"large","giant") ' + 'returns "large". The same example with a first value of 16 returns "giant".') + + def evaluate(self, formatter, kwargs, mi, locals, *args): + if (len(args) % 2) != 0: + raise ValueError(_('first_matching_cmp requires an even number of arguments')) + val = float(args[0] if args[0] and args[0] != 'None' else 0) + for i in range(1, len(args) - 1, 2): + c = float(args[i] if args[i] and args[i] != 'None' else 0) + if val < c: + return args[i+1] + return args[len(args)-1] + + +class BuiltinStrcat(BuiltinFormatterFunction): + name = 'strcat' + arg_count = -1 + category = 'String manipulation' + __doc__ = doc = _('strcat(a, b, ...) -- can take any number of arguments. Returns a ' + 'string formed by concatenating all the arguments') + + def evaluate(self, formatter, kwargs, mi, locals, *args): + i = 0 + res = '' + for i in range(0, len(args)): + res += args[i] + return res + + +class BuiltinStrlen(BuiltinFormatterFunction): + name = 'strlen' + arg_count = 1 + category = 'String manipulation' + __doc__ = doc = _('strlen(a) -- Returns the length of the string passed as ' + 'the argument') + + def evaluate(self, formatter, kwargs, mi, locals, a): + try: + return len(a) + except: + return -1 + + +class BuiltinAdd(BuiltinFormatterFunction): + name = 'add' + arg_count = 2 + category = 'Arithmetic' + __doc__ = doc = _('add(x, y) -- returns x + y. Throws an exception if either x or y are not numbers.') + + def evaluate(self, formatter, kwargs, mi, locals, x, y): + x = float(x if x and x != 'None' else 0) + y = float(y if y and y != 'None' else 0) + return unicode_type(x + y) + + +class BuiltinSubtract(BuiltinFormatterFunction): + name = 'subtract' + arg_count = 2 + category = 'Arithmetic' + __doc__ = doc = _('subtract(x, y) -- returns x - y. Throws an exception if either x or y are not numbers.') + + def evaluate(self, formatter, kwargs, mi, locals, x, y): + x = float(x if x and x != 'None' else 0) + y = float(y if y and y != 'None' else 0) + return unicode_type(x - y) + + +class BuiltinMultiply(BuiltinFormatterFunction): + name = 'multiply' + arg_count = 2 + category = 'Arithmetic' + __doc__ = doc = _('multiply(x, y) -- returns x * y. Throws an exception if either x or y are not numbers.') + + def evaluate(self, formatter, kwargs, mi, locals, x, y): + x = float(x if x and x != 'None' else 0) + y = float(y if y and y != 'None' else 0) + return unicode_type(x * y) + + +class BuiltinDivide(BuiltinFormatterFunction): + name = 'divide' + arg_count = 2 + category = 'Arithmetic' + __doc__ = doc = _('divide(x, y) -- returns x / y. Throws an exception if either x or y are not numbers.') + + def evaluate(self, formatter, kwargs, mi, locals, x, y): + x = float(x if x and x != 'None' else 0) + y = float(y if y and y != 'None' else 0) + return unicode_type(x / y) + + +class BuiltinTemplate(BuiltinFormatterFunction): + name = 'template' + arg_count = 1 + category = 'Recursion' + + __doc__ = doc = _('template(x) -- evaluates x as a template. The evaluation is done ' + 'in its own context, meaning that variables are not shared between ' + 'the caller and the template evaluation. Because the { and } ' + 'characters are special, you must use [[ for the { character and ' + ']] for the } character; they are converted automatically. ' + 'For example, template(\'[[title_sort]]\') will evaluate the ' + 'template {title_sort} and return its value. Note also that ' + 'prefixes and suffixes (the `|prefix|suffix` syntax) cannot be ' + 'used in the argument to this function when using template program mode.') + + def evaluate(self, formatter, kwargs, mi, locals, template): + template = template.replace('[[', '{').replace(']]', '}') + return formatter.__class__().safe_format(template, kwargs, 'TEMPLATE', mi) + + +class BuiltinEval(BuiltinFormatterFunction): + name = 'eval' + arg_count = 1 + category = 'Recursion' + __doc__ = doc = _('eval(template) -- evaluates the template, passing the local ' + 'variables (those \'assign\'ed to) instead of the book metadata. ' + ' This permits using the template processor to construct complex ' + 'results from local variables. Because the { and } ' + 'characters are special, you must use [[ for the { character and ' + ']] for the } character; they are converted automatically. ' + 'Note also that prefixes and suffixes (the `|prefix|suffix` syntax) ' + 'cannot be used in the argument to this function when using ' + 'template program mode.') + + def evaluate(self, formatter, kwargs, mi, locals, template): + from calibre.utils.formatter import EvalFormatter + template = template.replace('[[', '{').replace(']]', '}') + return EvalFormatter().safe_format(template, locals, 'EVAL', None) + + +class BuiltinAssign(BuiltinFormatterFunction): + name = 'assign' + arg_count = 2 + category = 'Other' + __doc__ = doc = _('assign(id, val) -- assigns val to id, then returns val. ' + 'id must be an identifier, not an expression') + + def evaluate(self, formatter, kwargs, mi, locals, target, value): + locals[target] = value + return value + + +class BuiltinPrint(BuiltinFormatterFunction): + name = 'print' + arg_count = -1 + category = 'Other' + __doc__ = doc = _('print(a, b, ...) -- prints the arguments to standard output. ' + 'Unless you start calibre from the command line (calibre-debug -g), ' + 'the output will go to a black hole.') + + def evaluate(self, formatter, kwargs, mi, locals, *args): + print(args) + return '' + + +class BuiltinField(BuiltinFormatterFunction): + name = 'field' + arg_count = 1 + category = 'Get values from metadata' + __doc__ = doc = _('field(name) -- returns the metadata field named by name') + + def evaluate(self, formatter, kwargs, mi, locals, name): + return formatter.get_value(name, [], kwargs) + + +class BuiltinRawField(BuiltinFormatterFunction): + name = 'raw_field' + arg_count = 1 + category = 'Get values from metadata' + __doc__ = doc = _('raw_field(name) -- returns the metadata field named by name ' + 'without applying any formatting.') + + def evaluate(self, formatter, kwargs, mi, locals, name): + res = getattr(mi, name, None) + if isinstance(res, list): + fm = mi.metadata_for_field(name) + if fm is None: + return ', '.join(res) + return fm['is_multiple']['list_to_ui'].join(res) + return unicode_type(res) + + +class BuiltinRawList(BuiltinFormatterFunction): + name = 'raw_list' + arg_count = 2 + category = 'Get values from metadata' + __doc__ = doc = _('raw_list(name, separator) -- returns the metadata list ' + 'named by name without applying any formatting or sorting and ' + 'with items separated by separator.') + + def evaluate(self, formatter, kwargs, mi, locals, name, separator): + res = getattr(mi, name, None) + if not isinstance(res, list): + return "%s is not a list" % name + return separator.join(res) + + +class BuiltinSubstr(BuiltinFormatterFunction): + name = 'substr' + arg_count = 3 + category = 'String manipulation' + __doc__ = doc = _('substr(str, start, end) -- returns the start\'th through the end\'th ' + 'characters of str. The first character in str is the zero\'th ' + 'character. If end is negative, then it indicates that many ' + 'characters counting from the right. If end is zero, then it ' + 'indicates the last character. For example, substr(\'12345\', 1, 0) ' + 'returns \'2345\', and substr(\'12345\', 1, -1) returns \'234\'.') + + def evaluate(self, formatter, kwargs, mi, locals, str_, start_, end_): + return str_[int(start_): len(str_) if int(end_) == 0 else int(end_)] + + +class BuiltinLookup(BuiltinFormatterFunction): + name = 'lookup' + arg_count = -1 + category = 'Iterating over values' + __doc__ = doc = _('lookup(val, pattern, field, pattern, field, ..., else_field) -- ' + 'like switch, except the arguments are field (metadata) names, not ' + 'text. The value of the appropriate field will be fetched and used. ' + 'Note that because composite columns are fields, you can use this ' + 'function in one composite field to use the value of some other ' + 'composite field. This is extremely useful when constructing ' + 'variable save paths') + + def evaluate(self, formatter, kwargs, mi, locals, val, *args): + if len(args) == 2: # here for backwards compatibility + if val: + return formatter.vformat('{'+args[0].strip()+'}', [], kwargs) + else: + return formatter.vformat('{'+args[1].strip()+'}', [], kwargs) + if (len(args) % 2) != 1: + raise ValueError(_('lookup requires either 2 or an odd number of arguments')) + i = 0 + while i < len(args): + if i + 1 >= len(args): + return formatter.vformat('{' + args[i].strip() + '}', [], kwargs) + if re.search(args[i], val, flags=re.I): + return formatter.vformat('{'+args[i+1].strip() + '}', [], kwargs) + i += 2 + + +class BuiltinTest(BuiltinFormatterFunction): + name = 'test' + arg_count = 3 + category = 'If-then-else' + __doc__ = doc = _('test(val, text if not empty, text if empty) -- return `text if not ' + 'empty` if val is not empty, otherwise return `text if empty`') + + def evaluate(self, formatter, kwargs, mi, locals, val, value_if_set, value_not_set): + if val: + return value_if_set + else: + return value_not_set + + +class BuiltinContains(BuiltinFormatterFunction): + name = 'contains' + arg_count = 4 + category = 'If-then-else' + __doc__ = doc = _('contains(val, pattern, text if match, text if not match) -- checks ' + 'if val contains matches for the regular expression `pattern`. ' + 'Returns `text if match` if matches are found, otherwise it returns ' + '`text if no match`') + + def evaluate(self, formatter, kwargs, mi, locals, + val, test, value_if_present, value_if_not): + if re.search(test, val, flags=re.I): + return value_if_present + else: + return value_if_not + + +class BuiltinSwitch(BuiltinFormatterFunction): + name = 'switch' + arg_count = -1 + category = 'Iterating over values' + __doc__ = doc = _('switch(val, pattern, value, pattern, value, ..., else_value) -- ' + 'for each `pattern, value` pair, checks if `val` matches ' + 'the regular expression `pattern` and if so, returns that ' + '`value`. If no pattern matches, then `else_value` is returned. ' + 'You can have as many `pattern, value` pairs as you want') + + def evaluate(self, formatter, kwargs, mi, locals, val, *args): + if (len(args) % 2) != 1: + raise ValueError(_('switch requires an odd number of arguments')) + i = 0 + while i < len(args): + if i + 1 >= len(args): + return args[i] + if re.search(args[i], val, flags=re.I): + return args[i+1] + i += 2 + + +class BuiltinStrcatMax(BuiltinFormatterFunction): + name = 'strcat_max' + arg_count = -1 + category = 'String manipulation' + __doc__ = doc = _('strcat_max(max, string1, prefix2, string2, ...) -- ' + 'Returns a string formed by concatenating the arguments. The ' + 'returned value is initialized to string1. `Prefix, string` ' + 'pairs are added to the end of the value as long as the ' + 'resulting string length is less than `max`. String1 is returned ' + 'even if string1 is longer than max. You can pass as many ' + '`prefix, string` pairs as you wish.') + + def evaluate(self, formatter, kwargs, mi, locals, *args): + if len(args) < 2: + raise ValueError(_('strcat_max requires 2 or more arguments')) + if (len(args) % 2) != 0: + raise ValueError(_('strcat_max requires an even number of arguments')) + try: + max = int(args[0]) + except: + raise ValueError(_('first argument to strcat_max must be an integer')) + + i = 2 + result = args[1] + try: + while i < len(args): + if (len(result) + len(args[i]) + len(args[i+1])) > max: + break + result = result + args[i] + args[i+1] + i += 2 + except: + pass + return result.strip() + + +class BuiltinInList(BuiltinFormatterFunction): + name = 'in_list' + arg_count = -1 + category = 'List lookup' + __doc__ = doc = _('in_list(val, separator, pattern, found_val, ..., not_found_val) -- ' + 'treat val as a list of items separated by separator, ' + 'evaluating the pattern against each value in the list. If the ' + 'pattern matches a value, return found_val, otherwise return ' + 'not_found_val. The pattern and found_value can be repeated as ' + 'many times as desired, permitting returning different values ' + 'depending on the search. The patterns are checked in order. The ' + 'first match is returned.') + + def evaluate(self, formatter, kwargs, mi, locals, val, sep, *args): + if (len(args) % 2) != 1: + raise ValueError(_('in_list requires an odd number of arguments')) + l = [v.strip() for v in val.split(sep) if v.strip()] + i = 0 + while i < len(args): + if i + 1 >= len(args): + return args[i] + sf = args[i] + fv = args[i+1] + if l: + for v in l: + if re.search(sf, v, flags=re.I): + return fv + i += 2 + + +class BuiltinStrInList(BuiltinFormatterFunction): + name = 'str_in_list' + arg_count = -1 + category = 'List lookup' + __doc__ = doc = _('str_in_list(val, separator, string, found_val, ..., not_found_val) -- ' + 'treat val as a list of items separated by separator, ' + 'comparing the string against each value in the list. If the ' + 'string matches a value (ignoring case) then return found_val, otherwise return ' + 'not_found_val. If the string contains separators, then it is ' + 'also treated as a list and each value is checked. The string and ' + 'found_value can be repeated as many times as desired, permitting ' + 'returning different values depending on the search. The strings are ' + 'checked in order. The first match is returned.') + + def evaluate(self, formatter, kwargs, mi, locals, val, sep, *args): + if (len(args) % 2) != 1: + raise ValueError(_('str_in_list requires an odd number of arguments')) + l = [v.strip() for v in val.split(sep) if v.strip()] + i = 0 + while i < len(args): + if i + 1 >= len(args): + return args[i] + sf = args[i] + fv = args[i+1] + c = [v.strip() for v in sf.split(sep) if v.strip()] + if l: + for v in l: + for t in c: + if strcmp(t, v) == 0: + return fv + i += 2 + + +class BuiltinIdentifierInList(BuiltinFormatterFunction): + name = 'identifier_in_list' + arg_count = 4 + category = 'List lookup' + __doc__ = doc = _('identifier_in_list(val, id, found_val, not_found_val) -- ' + 'treat val as a list of identifiers separated by commas, ' + 'comparing the string against each value in the list. An identifier ' + 'has the format "identifier:value". The id parameter should be ' + 'either "id" or "id:regexp". The first case matches if there is any ' + 'identifier with that id. The second case matches if the regexp ' + 'matches the identifier\'s value. If there is a match, ' + 'return found_val, otherwise return not_found_val.') + + def evaluate(self, formatter, kwargs, mi, locals, val, ident, fv, nfv): + l = [v.strip() for v in val.split(',') if v.strip()] + (id, _, regexp) = ident.partition(':') + if not id: + return nfv + id += ':' + if l: + for v in l: + if v.startswith(id): + if not regexp or re.search(regexp, v[len(id):], flags=re.I): + return fv + return nfv + + +class BuiltinRe(BuiltinFormatterFunction): + name = 're' + arg_count = 3 + category = 'String manipulation' + __doc__ = doc = _('re(val, pattern, replacement) -- return val after applying ' + 'the regular expression. All instances of `pattern` are replaced ' + 'with `replacement`. As in all of calibre, these are ' + 'Python-compatible regular expressions') + + def evaluate(self, formatter, kwargs, mi, locals, val, pattern, replacement): + return re.sub(pattern, replacement, val, flags=re.I) + + +class BuiltinReGroup(BuiltinFormatterFunction): + name = 're_group' + arg_count = -1 + category = 'String manipulation' + __doc__ = doc = _('re_group(val, pattern, template_for_group_1, for_group_2, ...) -- ' + 'return a string made by applying the regular expression pattern ' + 'to the val and replacing each matched instance with the string ' + 'computed by replacing each matched group by the value returned ' + 'by the corresponding template. The original matched value for the ' + 'group is available as $. In template program mode, like for ' + 'the template and the eval functions, you use [[ for { and ]] for }.' + ' The following example in template program mode looks for series ' + 'with more than one word and uppercases the first word: ' + "{series:'re_group($, \"(\\S* )(.*)\", \"[[$:uppercase()]]\", \"[[$]]\")'}") + + def evaluate(self, formatter, kwargs, mi, locals, val, pattern, *args): + from calibre.utils.formatter import EvalFormatter + + def repl(mo): + res = '' + if mo and mo.lastindex: + for dex in range(0, mo.lastindex): + gv = mo.group(dex+1) + if gv is None: + continue + if len(args) > dex: + template = args[dex].replace('[[', '{').replace(']]', '}') + res += EvalFormatter().safe_format(template, {'$': gv}, + 'EVAL', None, strip_results=False) + else: + res += gv + return res + return re.sub(pattern, repl, val, flags=re.I) + + +class BuiltinSwapAroundComma(BuiltinFormatterFunction): + name = 'swap_around_comma' + arg_count = 1 + category = 'String manipulation' + __doc__ = doc = _('swap_around_comma(val) -- given a value of the form ' + '"B, A", return "A B". This is most useful for converting names ' + 'in LN, FN format to FN LN. If there is no comma, the function ' + 'returns val unchanged') + + def evaluate(self, formatter, kwargs, mi, locals, val): + return re.sub(r'^(.*?),\s*(.*$)', r'\2 \1', val, flags=re.I).strip() + + +class BuiltinIfempty(BuiltinFormatterFunction): + name = 'ifempty' + arg_count = 2 + category = 'If-then-else' + __doc__ = doc = _('ifempty(val, text if empty) -- return val if val is not empty, ' + 'otherwise return `text if empty`') + + def evaluate(self, formatter, kwargs, mi, locals, val, value_if_empty): + if val: + return val + else: + return value_if_empty + + +class BuiltinShorten(BuiltinFormatterFunction): + name = 'shorten' + arg_count = 4 + category = 'String manipulation' + __doc__ = doc = _('shorten(val, left chars, middle text, right chars) -- Return a ' + 'shortened version of val, consisting of `left chars` ' + 'characters from the beginning of val, followed by ' + '`middle text`, followed by `right chars` characters from ' + 'the end of the string. `Left chars` and `right chars` must be ' + 'integers. For example, assume the title of the book is ' + '`Ancient English Laws in the Times of Ivanhoe`, and you want ' + 'it to fit in a space of at most 15 characters. If you use ' + '{title:shorten(9,-,5)}, the result will be `Ancient E-nhoe`. ' + 'If the field\'s length is less than left chars + right chars + ' + 'the length of `middle text`, then the field will be used ' + 'intact. For example, the title `The Dome` would not be changed.') + + def evaluate(self, formatter, kwargs, mi, locals, + val, leading, center_string, trailing): + l = max(0, int(leading)) + t = max(0, int(trailing)) + if len(val) > l + len(center_string) + t: + return val[0:l] + center_string + ('' if t == 0 else val[-t:]) + else: + return val + + +class BuiltinCount(BuiltinFormatterFunction): + name = 'count' + arg_count = 2 + category = 'List manipulation' + __doc__ = doc = _('count(val, separator) -- interprets the value as a list of items ' + 'separated by `separator`, returning the number of items in the ' + 'list. Most lists use a comma as the separator, but authors ' + 'uses an ampersand. Examples: {tags:count(,)}, {authors:count(&)}') + + def evaluate(self, formatter, kwargs, mi, locals, val, sep): + return unicode_type(len([v for v in val.split(sep) if v])) + + +class BuiltinListitem(BuiltinFormatterFunction): + name = 'list_item' + arg_count = 3 + category = 'List lookup' + __doc__ = doc = _('list_item(val, index, separator) -- interpret the value as a list of ' + 'items separated by `separator`, returning the `index`th item. ' + 'The first item is number zero. The last item can be returned ' + 'using `list_item(-1,separator)`. If the item is not in the list, ' + 'then the empty value is returned. The separator has the same ' + 'meaning as in the count function.') + + def evaluate(self, formatter, kwargs, mi, locals, val, index, sep): + if not val: + return '' + index = int(index) + val = val.split(sep) + try: + return val[index].strip() + except: + return '' + + +class BuiltinSelect(BuiltinFormatterFunction): + name = 'select' + arg_count = 2 + category = 'List lookup' + __doc__ = doc = _('select(val, key) -- interpret the value as a comma-separated list ' + 'of items, with the items being "id:value". Find the pair with the ' + 'id equal to key, and return the corresponding value.' + ) + + def evaluate(self, formatter, kwargs, mi, locals, val, key): + if not val: + return '' + vals = [v.strip() for v in val.split(',')] + for v in vals: + if v.startswith(key+':'): + return v[len(key)+1:] + return '' + + +class BuiltinApproximateFormats(BuiltinFormatterFunction): + name = 'approximate_formats' + arg_count = 0 + category = 'Get values from metadata' + __doc__ = doc = _('approximate_formats() -- return a comma-separated ' + 'list of formats that at one point were associated with the ' + 'book. There is no guarantee that this list is correct, ' + 'although it probably is. ' + 'This function can be called in template program mode using ' + 'the template "{:\'approximate_formats()\'}". ' + 'Note that format names are always uppercase, as in EPUB. ' + 'This function works only in the GUI. If you want to use these values ' + 'in save-to-disk or send-to-device templates then you ' + 'must make a custom "Column built from other columns", use ' + 'the function in that column\'s template, and use that ' + 'column\'s value in your save/send templates' + ) + + def evaluate(self, formatter, kwargs, mi, locals): + if hasattr(mi, '_proxy_metadata'): + fmt_data = mi._proxy_metadata.db_approx_formats + if not fmt_data: + return '' + data = sorted(fmt_data) + return ','.join(v.upper() for v in data) + return _('This function can be used only in the GUI') + + +class BuiltinFormatsModtimes(BuiltinFormatterFunction): + name = 'formats_modtimes' + arg_count = 1 + category = 'Get values from metadata' + __doc__ = doc = _('formats_modtimes(date_format) -- return a comma-separated ' + 'list of colon-separated items representing modification times ' + 'for the formats of a book. The date_format parameter ' + 'specifies how the date is to be formatted. See the ' + 'format_date function for details. You can use the select ' + 'function to get the mod time for a specific ' + 'format. Note that format names are always uppercase, ' + 'as in EPUB.' + ) + + def evaluate(self, formatter, kwargs, mi, locals, fmt): + fmt_data = mi.get('format_metadata', {}) + try: + data = sorted(fmt_data.items(), key=lambda x:x[1]['mtime'], reverse=True) + return ','.join(k.upper()+':'+format_date(v['mtime'], fmt) + for k,v in data) + except: + return '' + + +class BuiltinFormatsSizes(BuiltinFormatterFunction): + name = 'formats_sizes' + arg_count = 0 + category = 'Get values from metadata' + __doc__ = doc = _('formats_sizes() -- return a comma-separated list of ' + 'colon-separated items representing sizes in bytes ' + 'of the formats of a book. You can use the select ' + 'function to get the size for a specific ' + 'format. Note that format names are always uppercase, ' + 'as in EPUB.' + ) + + def evaluate(self, formatter, kwargs, mi, locals): + fmt_data = mi.get('format_metadata', {}) + try: + return ','.join(k.upper()+':'+unicode_type(v['size']) for k,v in iteritems(fmt_data)) + except: + return '' + + +class BuiltinFormatsPaths(BuiltinFormatterFunction): + name = 'formats_paths' + arg_count = 0 + category = 'Get values from metadata' + __doc__ = doc = _('formats_paths() -- return a comma-separated list of ' + 'colon-separated items representing full path to ' + 'the formats of a book. You can use the select ' + 'function to get the path for a specific ' + 'format. Note that format names are always uppercase, ' + 'as in EPUB.') + + def evaluate(self, formatter, kwargs, mi, locals): + fmt_data = mi.get('format_metadata', {}) + try: + return ','.join(k.upper()+':'+unicode_type(v['path']) for k,v in iteritems(fmt_data)) + except: + return '' + + +class BuiltinHumanReadable(BuiltinFormatterFunction): + name = 'human_readable' + arg_count = 1 + category = 'Formatting values' + __doc__ = doc = _('human_readable(v) -- return a string ' + 'representing the number v in KB, MB, GB, etc.' + ) + + def evaluate(self, formatter, kwargs, mi, locals, val): + try: + return human_readable(round(float(val))) + except: + return '' + + +class BuiltinFormatNumber(BuiltinFormatterFunction): + name = 'format_number' + arg_count = 2 + category = 'Formatting values' + __doc__ = doc = _('format_number(v, template) -- format the number v using ' + 'a Python formatting template such as "{0:5.2f}" or ' + '"{0:,d}" or "${0:5,.2f}". The field_name part of the ' + 'template must be a 0 (zero) (the "{0:" in the above examples). ' + 'See the template language and Python documentation for more ' + 'examples. You can leave off the leading "{0:" and trailing ' + '"}" if the template contains only a format. Returns the empty ' + 'string if formatting fails.' + ) + + def evaluate(self, formatter, kwargs, mi, locals, val, template): + if val == '' or val == 'None': + return '' + if '{' not in template: + template = '{0:' + template + '}' + try: + v1 = float(val) + except: + return '' + try: # Try formatting the value as a float + return template.format(v1) + except: + pass + try: # Try formatting the value as an int + v2 = trunc(v1) + if v2 == v1: + return template.format(v2) + except: + pass + return '' + + +class BuiltinSublist(BuiltinFormatterFunction): + name = 'sublist' + arg_count = 4 + category = 'List manipulation' + __doc__ = doc = _('sublist(val, start_index, end_index, separator) -- interpret the ' + 'value as a list of items separated by `separator`, returning a ' + 'new list made from the `start_index` to the `end_index` item. ' + 'The first item is number zero. If an index is negative, then it ' + 'counts from the end of the list. As a special case, an end_index ' + 'of zero is assumed to be the length of the list. Examples using ' + 'basic template mode and assuming that the tags column (which is ' + 'comma-separated) contains "A, B, C": ' + '{tags:sublist(0,1,\\\\,)} returns "A". ' + '{tags:sublist(-1,0,\\\\,)} returns "C". ' + '{tags:sublist(0,-1,\\\\,)} returns "A, B".' + ) + + def evaluate(self, formatter, kwargs, mi, locals, val, start_index, end_index, sep): + if not val: + return '' + si = int(start_index) + ei = int(end_index) + # allow empty list items so counts are what the user expects + val = [v.strip() for v in val.split(sep)] + + if sep == ',': + sep = ', ' + try: + if ei == 0: + return sep.join(val[si:]) + else: + return sep.join(val[si:ei]) + except: + return '' + + +class BuiltinSubitems(BuiltinFormatterFunction): + name = 'subitems' + arg_count = 3 + category = 'List manipulation' + __doc__ = doc = _('subitems(val, start_index, end_index) -- This function is used to ' + 'break apart lists of items such as genres. It interprets the value ' + 'as a comma-separated list of items, where each item is a period-' + 'separated list. Returns a new list made by first finding all the ' + 'period-separated items, then for each such item extracting the ' + '`start_index` to the `end_index` components, then combining ' + 'the results back together. The first component in a period-' + 'separated list has an index of zero. If an index is negative, ' + 'then it counts from the end of the list. As a special case, an ' + 'end_index of zero is assumed to be the length of the list. ' + 'Example using basic template mode and assuming a #genre value of ' + '"A.B.C": {#genre:subitems(0,1)} returns "A". {#genre:subitems(0,2)} ' + 'returns "A.B". {#genre:subitems(1,0)} returns "B.C". Assuming a #genre ' + 'value of "A.B.C, D.E.F", {#genre:subitems(0,1)} returns "A, D". ' + '{#genre:subitems(0,2)} returns "A.B, D.E"') + + period_pattern = re.compile(r'(?<=[^\.\s])\.(?=[^\.\s])', re.U) + + def evaluate(self, formatter, kwargs, mi, locals, val, start_index, end_index): + if not val: + return '' + si = int(start_index) + ei = int(end_index) + has_periods = '.' in val + items = [v.strip() for v in val.split(',')] + rv = set() + for item in items: + if has_periods and '.' in item: + components = self.period_pattern.split(item) + else: + components = [item] + try: + if ei == 0: + rv.add('.'.join(components[si:])) + else: + rv.add('.'.join(components[si:ei])) + except: + pass + return ', '.join(sorted(rv, key=sort_key)) + + +class BuiltinFormatDate(BuiltinFormatterFunction): + name = 'format_date' + arg_count = 2 + category = 'Formatting values' + __doc__ = doc = _('format_date(val, format_string) -- format the value, ' + 'which must be a date, using the format_string, returning a string. ' + 'The formatting codes are: ' + 'd : the day as number without a leading zero (1 to 31) ' + 'dd : the day as number with a leading zero (01 to 31) ' + 'ddd : the abbreviated localized day name (e.g. "Mon" to "Sun"). ' + 'dddd : the long localized day name (e.g. "Monday" to "Sunday"). ' + 'M : the month as number without a leading zero (1 to 12). ' + 'MM : the month as number with a leading zero (01 to 12) ' + 'MMM : the abbreviated localized month name (e.g. "Jan" to "Dec"). ' + 'MMMM : the long localized month name (e.g. "January" to "December"). ' + 'yy : the year as two digit number (00 to 99). ' + 'yyyy : the year as four digit number. ' + 'h : the hours without a leading 0 (0 to 11 or 0 to 23, depending on am/pm) ' + 'hh : the hours with a leading 0 (00 to 11 or 00 to 23, depending on am/pm) ' + 'm : the minutes without a leading 0 (0 to 59) ' + 'mm : the minutes with a leading 0 (00 to 59) ' + 's : the seconds without a leading 0 (0 to 59) ' + 'ss : the seconds with a leading 0 (00 to 59) ' + 'ap : use a 12-hour clock instead of a 24-hour clock, with "ap" replaced by the localized string for am or pm ' + 'AP : use a 12-hour clock instead of a 24-hour clock, with "AP" replaced by the localized string for AM or PM ' + 'iso : the date with time and timezone. Must be the only format present') + + def evaluate(self, formatter, kwargs, mi, locals, val, format_string): + if not val or val == 'None': + return '' + try: + dt = parse_date(val) + s = format_date(dt, format_string) + except: + s = 'BAD DATE' + return s + + +class BuiltinUppercase(BuiltinFormatterFunction): + name = 'uppercase' + arg_count = 1 + category = 'String case changes' + __doc__ = doc = _('uppercase(val) -- return val in upper case') + + def evaluate(self, formatter, kwargs, mi, locals, val): + return val.upper() + + +class BuiltinLowercase(BuiltinFormatterFunction): + name = 'lowercase' + arg_count = 1 + category = 'String case changes' + __doc__ = doc = _('lowercase(val) -- return val in lower case') + + def evaluate(self, formatter, kwargs, mi, locals, val): + return val.lower() + + +class BuiltinTitlecase(BuiltinFormatterFunction): + name = 'titlecase' + arg_count = 1 + category = 'String case changes' + __doc__ = doc = _('titlecase(val) -- return val in title case') + + def evaluate(self, formatter, kwargs, mi, locals, val): + return titlecase(val) + + +class BuiltinCapitalize(BuiltinFormatterFunction): + name = 'capitalize' + arg_count = 1 + category = 'String case changes' + __doc__ = doc = _('capitalize(val) -- return val capitalized') + + def evaluate(self, formatter, kwargs, mi, locals, val): + return capitalize(val) + + +class BuiltinBooksize(BuiltinFormatterFunction): + name = 'booksize' + arg_count = 0 + category = 'Get values from metadata' + __doc__ = doc = _('booksize() -- return value of the size field. ' + 'This function works only in the GUI. If you want to use this value ' + 'in save-to-disk or send-to-device templates then you ' + 'must make a custom "Column built from other columns", use ' + 'the function in that column\'s template, and use that ' + 'column\'s value in your save/send templates') + + def evaluate(self, formatter, kwargs, mi, locals): + if hasattr(mi, '_proxy_metadata'): + try: + v = mi._proxy_metadata.book_size + if v is not None: + return unicode_type(mi._proxy_metadata.book_size) + return '' + except: + pass + return '' + return _('This function can be used only in the GUI') + + +class BuiltinOndevice(BuiltinFormatterFunction): + name = 'ondevice' + arg_count = 0 + category = 'Get values from metadata' + __doc__ = doc = _('ondevice() -- return Yes if ondevice is set, otherwise return ' + 'the empty string. This function works only in the GUI. If you want to ' + 'use this value in save-to-disk or send-to-device templates then you ' + 'must make a custom "Column built from other columns", use ' + 'the function in that column\'s template, and use that ' + 'column\'s value in your save/send templates') + + def evaluate(self, formatter, kwargs, mi, locals): + if hasattr(mi, '_proxy_metadata'): + if mi._proxy_metadata.ondevice_col: + return _('Yes') + return '' + return _('This function can be used only in the GUI') + + +class BuiltinSeriesSort(BuiltinFormatterFunction): + name = 'series_sort' + arg_count = 0 + category = 'Get values from metadata' + __doc__ = doc = _('series_sort() -- return the series sort value') + + def evaluate(self, formatter, kwargs, mi, locals): + if mi.series: + return title_sort(mi.series) + return '' + + +class BuiltinHasCover(BuiltinFormatterFunction): + name = 'has_cover' + arg_count = 0 + category = 'Get values from metadata' + __doc__ = doc = _('has_cover() -- return Yes if the book has a cover, ' + 'otherwise return the empty string') + + def evaluate(self, formatter, kwargs, mi, locals): + if mi.has_cover: + return _('Yes') + return '' + + +class BuiltinFirstNonEmpty(BuiltinFormatterFunction): + name = 'first_non_empty' + arg_count = -1 + category = 'Iterating over values' + __doc__ = doc = _('first_non_empty(value, value, ...) -- ' + 'returns the first value that is not empty. If all values are ' + 'empty, then the empty value is returned. ' + 'You can have as many values as you want.') + + def evaluate(self, formatter, kwargs, mi, locals, *args): + i = 0 + while i < len(args): + if args[i]: + return args[i] + i += 1 + return '' + + +class BuiltinAnd(BuiltinFormatterFunction): + name = 'and' + arg_count = -1 + category = 'Boolean' + __doc__ = doc = _('and(value, value, ...) -- ' + 'returns the string "1" if all values are not empty, otherwise ' + 'returns the empty string. This function works well with test or ' + 'first_non_empty. You can have as many values as you want. ') + + def evaluate(self, formatter, kwargs, mi, locals, *args): + i = 0 + while i < len(args): + if not args[i]: + return '' + i += 1 + return '1' + + +class BuiltinOr(BuiltinFormatterFunction): + name = 'or' + arg_count = -1 + category = 'Boolean' + __doc__ = doc = _('or(value, value, ...) -- ' + 'returns the string "1" if any value is not empty, otherwise ' + 'returns the empty string. This function works well with test or ' + 'first_non_empty. You can have as many values as you want.') + + def evaluate(self, formatter, kwargs, mi, locals, *args): + i = 0 + while i < len(args): + if args[i]: + return '1' + i += 1 + return '' + + +class BuiltinNot(BuiltinFormatterFunction): + name = 'not' + arg_count = 1 + category = 'Boolean' + __doc__ = doc = _('not(value) -- ' + 'returns the string "1" if the value is empty, otherwise ' + 'returns the empty string. This function works well with test or ' + 'first_non_empty.') + + def evaluate(self, formatter, kwargs, mi, locals, val): + return '' if val else '1' + + +class BuiltinListUnion(BuiltinFormatterFunction): + name = 'list_union' + arg_count = 3 + category = 'List manipulation' + __doc__ = doc = _('list_union(list1, list2, separator) -- ' + 'return a list made by merging the items in list1 and list2, ' + 'removing duplicate items using a case-insensitive comparison. If ' + 'items differ in case, the one in list1 is used. ' + 'The items in list1 and list2 are separated by separator, as are ' + 'the items in the returned list.') + aliases = ['merge_lists'] + + def evaluate(self, formatter, kwargs, mi, locals, list1, list2, separator): + res = [l.strip() for l in list1.split(separator) if l.strip()] + l2 = [l.strip() for l in list2.split(separator) if l.strip()] + lcl1 = {icu_lower(l) for l in res} + + for i in l2: + if icu_lower(i) not in lcl1 and i not in res: + res.append(i) + if separator == ',': + return ', '.join(res) + return separator.join(res) + + +class BuiltinListDifference(BuiltinFormatterFunction): + name = 'list_difference' + arg_count = 3 + category = 'List manipulation' + __doc__ = doc = _('list_difference(list1, list2, separator) -- ' + 'return a list made by removing from list1 any item found in list2, ' + 'using a case-insensitive comparison. The items in list1 and list2 ' + 'are separated by separator, as are the items in the returned list.') + + def evaluate(self, formatter, kwargs, mi, locals, list1, list2, separator): + l1 = [l.strip() for l in list1.split(separator) if l.strip()] + l2 = {icu_lower(l.strip()) for l in list2.split(separator) if l.strip()} + + res = [] + for i in l1: + if icu_lower(i) not in l2 and i not in res: + res.append(i) + if separator == ',': + return ', '.join(res) + return separator.join(res) + + +class BuiltinListIntersection(BuiltinFormatterFunction): + name = 'list_intersection' + arg_count = 3 + category = 'List manipulation' + __doc__ = doc = _('list_intersection(list1, list2, separator) -- ' + 'return a list made by removing from list1 any item not found in list2, ' + 'using a case-insensitive comparison. The items in list1 and list2 ' + 'are separated by separator, as are the items in the returned list.') + + def evaluate(self, formatter, kwargs, mi, locals, list1, list2, separator): + l1 = [l.strip() for l in list1.split(separator) if l.strip()] + l2 = {icu_lower(l.strip()) for l in list2.split(separator) if l.strip()} + + res = [] + for i in l1: + if icu_lower(i) in l2 and i not in res: + res.append(i) + if separator == ',': + return ', '.join(res) + return separator.join(res) + + +class BuiltinListSort(BuiltinFormatterFunction): + name = 'list_sort' + arg_count = 3 + category = 'List manipulation' + __doc__ = doc = _('list_sort(list, direction, separator) -- ' + 'return list sorted using a case-insensitive sort. If direction is ' + 'zero, the list is sorted ascending, otherwise descending. The list items ' + 'are separated by separator, as are the items in the returned list.') + + def evaluate(self, formatter, kwargs, mi, locals, list1, direction, separator): + res = [l.strip() for l in list1.split(separator) if l.strip()] + if separator == ',': + return ', '.join(sorted(res, key=sort_key, reverse=direction != "0")) + return separator.join(sorted(res, key=sort_key, reverse=direction != "0")) + + +class BuiltinListEquals(BuiltinFormatterFunction): + name = 'list_equals' + arg_count = 6 + category = 'List manipulation' + __doc__ = doc = _('list_equals(list1, sep1, list2, sep2, yes_val, no_val) -- ' + 'return yes_val if list1 and list2 contain the same items, ' + 'otherwise return no_val. The items are determined by splitting ' + 'each list using the appropriate separator character (sep1 or ' + 'sep2). The order of items in the lists is not relevant. ' + 'The comparison is case insensitive.') + + def evaluate(self, formatter, kwargs, mi, locals, list1, sep1, list2, sep2, yes_val, no_val): + s1 = {icu_lower(l.strip()) for l in list1.split(sep1) if l.strip()} + s2 = {icu_lower(l.strip()) for l in list2.split(sep2) if l.strip()} + if s1 == s2: + return yes_val + return no_val + + +class BuiltinListRe(BuiltinFormatterFunction): + name = 'list_re' + arg_count = 4 + category = 'List manipulation' + __doc__ = doc = _('list_re(src_list, separator, include_re, opt_replace) -- ' + 'Construct a list by first separating src_list into items using ' + 'the separator character. For each item in the list, check if it ' + 'matches include_re. If it does, then add it to the list to be ' + 'returned. If opt_replace is not the empty string, then apply the ' + 'replacement before adding the item to the returned list.') + + def evaluate(self, formatter, kwargs, mi, locals, src_list, separator, include_re, opt_replace): + l = [l.strip() for l in src_list.split(separator) if l.strip()] + res = [] + for item in l: + if re.search(include_re, item, flags=re.I) is not None: + if opt_replace: + item = re.sub(include_re, opt_replace, item) + for i in [t.strip() for t in item.split(separator) if t.strip()]: + if i not in res: + res.append(i) + if separator == ',': + return ', '.join(res) + return separator.join(res) + + +class BuiltinListReGroup(BuiltinFormatterFunction): + name = 'list_re_group' + arg_count = -1 + category = 'List manipulation' + __doc__ = doc = _('list_re_group(src_list, separator, include_re, search_re, group_1_template, ...) -- ' + 'Like list_re except replacements are not optional. It ' + 'uses re_group(list_item, search_re, group_1_template, ...) when ' + 'doing the replacements on the resulting list.') + + def evaluate(self, formatter, kwargs, mi, locals, src_list, separator, include_re, + search_re, *args): + from calibre.utils.formatter import EvalFormatter + + l = [l.strip() for l in src_list.split(separator) if l.strip()] + res = [] + for item in l: + def repl(mo): + newval = '' + if mo and mo.lastindex: + for dex in range(0, mo.lastindex): + gv = mo.group(dex+1) + if gv is None: + continue + if len(args) > dex: + template = args[dex].replace('[[', '{').replace(']]', '}') + newval += EvalFormatter().safe_format(template, {'$': gv}, + 'EVAL', None, strip_results=False) + else: + newval += gv + return newval + if re.search(include_re, item, flags=re.I) is not None: + item = re.sub(search_re, repl, item, flags=re.I) + for i in [t.strip() for t in item.split(separator) if t.strip()]: + if i not in res: + res.append(i) + if separator == ',': + return ', '.join(res) + return separator.join(res) + + +class BuiltinToday(BuiltinFormatterFunction): + name = 'today' + arg_count = 0 + category = 'Date functions' + __doc__ = doc = _('today() -- ' + 'return a date string for today. This value is designed for use in ' + 'format_date or days_between, but can be manipulated like any ' + 'other string. The date is in ISO format.') + + def evaluate(self, formatter, kwargs, mi, locals): + return format_date(now(), 'iso') + + +class BuiltinDaysBetween(BuiltinFormatterFunction): + name = 'days_between' + arg_count = 2 + category = 'Date functions' + __doc__ = doc = _('days_between(date1, date2) -- ' + 'return the number of days between date1 and date2. The number is ' + 'positive if date1 is greater than date2, otherwise negative. If ' + 'either date1 or date2 are not dates, the function returns the ' + 'empty string.') + + def evaluate(self, formatter, kwargs, mi, locals, date1, date2): + try: + d1 = parse_date(date1) + if d1 == UNDEFINED_DATE: + return '' + d2 = parse_date(date2) + if d2 == UNDEFINED_DATE: + return '' + except: + return '' + i = d1 - d2 + return '%.1f'%(i.days + (i.seconds/(24.0*60.0*60.0))) + + +class BuiltinLanguageStrings(BuiltinFormatterFunction): + name = 'language_strings' + arg_count = 2 + category = 'Get values from metadata' + __doc__ = doc = _('language_strings(lang_codes, localize) -- ' + 'return the strings for the language codes passed in lang_codes. ' + 'If localize is zero, return the strings in English. If ' + 'localize is not zero, return the strings in the language of ' + 'the current locale. Lang_codes is a comma-separated list.') + + def evaluate(self, formatter, kwargs, mi, locals, lang_codes, localize): + retval = [] + for c in [c.strip() for c in lang_codes.split(',') if c.strip()]: + try: + n = calibre_langcode_to_name(c, localize != '0') + if n: + retval.append(n) + except: + pass + return ', '.join(retval) + + +class BuiltinLanguageCodes(BuiltinFormatterFunction): + name = 'language_codes' + arg_count = 1 + category = 'Get values from metadata' + __doc__ = doc = _('language_codes(lang_strings) -- ' + 'return the language codes for the strings passed in lang_strings. ' + 'The strings must be in the language of the current locale. ' + 'Lang_strings is a comma-separated list.') + + def evaluate(self, formatter, kwargs, mi, locals, lang_strings): + retval = [] + for c in [c.strip() for c in lang_strings.split(',') if c.strip()]: + try: + cv = canonicalize_lang(c) + if cv: + retval.append(canonicalize_lang(cv)) + except: + pass + return ', '.join(retval) + + +class BuiltinCurrentLibraryName(BuiltinFormatterFunction): + name = 'current_library_name' + arg_count = 0 + category = 'Get values from metadata' + __doc__ = doc = _('current_library_name() -- ' + 'return the last name on the path to the current calibre library. ' + 'This function can be called in template program mode using the ' + 'template "{:\'current_library_name()\'}".') + + def evaluate(self, formatter, kwargs, mi, locals): + from calibre.library import current_library_name + return current_library_name() + + +class BuiltinCurrentLibraryPath(BuiltinFormatterFunction): + name = 'current_library_path' + arg_count = 0 + category = 'Get values from metadata' + __doc__ = doc = _('current_library_path() -- ' + 'return the path to the current calibre library. This function can ' + 'be called in template program mode using the template ' + '"{:\'current_library_path()\'}".') + + def evaluate(self, formatter, kwargs, mi, locals): + from calibre.library import current_library_path + return current_library_path() + + +class BuiltinFinishFormatting(BuiltinFormatterFunction): + name = 'finish_formatting' + arg_count = 4 + category = 'Formatting values' + __doc__ = doc = _('finish_formatting(val, fmt, prefix, suffix) -- apply the ' + 'format, prefix, and suffix to a value in the same way as ' + 'done in a template like `{series_index:05.2f| - |- }`. For ' + 'example, the following program produces the same output ' + 'as the above template: ' + 'program: finish_formatting(field("series_index"), "05.2f", " - ", " - ")') + + def evaluate(self, formatter, kwargs, mi, locals_, val, fmt, prefix, suffix): + if not val: + return val + return prefix + formatter._do_format(val, fmt) + suffix + + +class BuiltinVirtualLibraries(BuiltinFormatterFunction): + name = 'virtual_libraries' + arg_count = 0 + category = 'Get values from metadata' + __doc__ = doc = _('virtual_libraries() -- return a comma-separated list of ' + 'virtual libraries that contain this book. This function ' + 'works only in the GUI. If you want to use these values ' + 'in save-to-disk or send-to-device templates then you ' + 'must make a custom "Column built from other columns", use ' + 'the function in that column\'s template, and use that ' + 'column\'s value in your save/send templates') + + def evaluate(self, formatter, kwargs, mi, locals_): + if hasattr(mi, '_proxy_metadata'): + return mi._proxy_metadata.virtual_libraries + return _('This function can be used only in the GUI') + + +class BuiltinUserCategories(BuiltinFormatterFunction): + name = 'user_categories' + arg_count = 0 + category = 'Get values from metadata' + __doc__ = doc = _('user_categories() -- return a comma-separated list of ' + 'the user categories that contain this book. This function ' + 'works only in the GUI. If you want to use these values ' + 'in save-to-disk or send-to-device templates then you ' + 'must make a custom "Column built from other columns", use ' + 'the function in that column\'s template, and use that ' + 'column\'s value in your save/send templates') + + def evaluate(self, formatter, kwargs, mi, locals_): + if hasattr(mi, '_proxy_metadata'): + cats = set(k for k, v in iteritems(mi._proxy_metadata.user_categories) if v) + cats = sorted(cats, key=sort_key) + return ', '.join(cats) + return _('This function can be used only in the GUI') + + +class BuiltinTransliterate(BuiltinFormatterFunction): + name = 'transliterate' + arg_count = 1 + category = 'String manipulation' + __doc__ = doc = _('transliterate(a) -- Returns a string in a latin alphabet ' + 'formed by approximating the sound of the words in the ' + 'source string. For example, if the source is "{0}"' + ' the function returns "{1}".').format( + u"Фёдор Миха́йлович Достоевский", 'Fiodor Mikhailovich Dostoievskii') + + def evaluate(self, formatter, kwargs, mi, locals, source): + from calibre.utils.filenames import ascii_text + return ascii_text(source) + + +class BuiltinAuthorLinks(BuiltinFormatterFunction): + name = 'author_links' + arg_count = 2 + category = 'Get values from metadata' + __doc__ = doc = _('author_links(val_separator, pair_separator) -- returns ' + 'a string containing a list of authors and that author\'s ' + 'link values in the ' + 'form author1 val_separator author1link pair_separator ' + 'author2 val_separator author2link etc. An author is ' + 'separated from its link value by the val_separator string ' + 'with no added spaces. author:linkvalue pairs are separated ' + 'by the pair_separator string argument with no added spaces. ' + 'It is up to you to choose separator strings that do ' + 'not occur in author names or links. An author is ' + 'included even if the author link is empty.') + + def evaluate(self, formatter, kwargs, mi, locals, val_sep, pair_sep): + if hasattr(mi, '_proxy_metadata'): + link_data = mi._proxy_metadata.author_link_map + if not link_data: + return '' + names = sorted(link_data.keys(), key=sort_key) + return pair_sep.join(n + val_sep + link_data[n] for n in names) + return _('This function can be used only in the GUI') + + +class BuiltinAuthorSorts(BuiltinFormatterFunction): + name = 'author_sorts' + arg_count = 1 + category = 'Get values from metadata' + __doc__ = doc = _('author_sorts(val_separator) -- returns a string ' + 'containing a list of author\'s sort values for the ' + 'authors of the book. The sort is the one in the author ' + 'metadata (different from the author_sort in books). The ' + 'returned list has the form author sort 1 val_separator ' + 'author sort 2 etc. The author sort values in this list ' + 'are in the same order as the authors of the book. If ' + 'you want spaces around val_separator then include them ' + 'in the separator string') + + def evaluate(self, formatter, kwargs, mi, locals, val_sep): + sort_data = mi.author_sort_map + if not sort_data: + return '' + names = [sort_data.get(n) for n in mi.authors if n.strip()] + return val_sep.join(n for n in names) + + +_formatter_builtins = [ + BuiltinAdd(), BuiltinAnd(), BuiltinApproximateFormats(), BuiltinAssign(), + BuiltinAuthorLinks(), BuiltinAuthorSorts(), BuiltinBooksize(), + BuiltinCapitalize(), BuiltinCmp(), BuiltinContains(), BuiltinCount(), + BuiltinCurrentLibraryName(), BuiltinCurrentLibraryPath(), + BuiltinDaysBetween(), BuiltinDivide(), BuiltinEval(), BuiltinFirstNonEmpty(), + BuiltinField(), BuiltinFinishFormatting(), BuiltinFirstMatchingCmp(), + BuiltinFormatDate(), BuiltinFormatNumber(), BuiltinFormatsModtimes(), + BuiltinFormatsPaths(), BuiltinFormatsSizes(), + BuiltinHasCover(), BuiltinHumanReadable(), BuiltinIdentifierInList(), + BuiltinIfempty(), BuiltinLanguageCodes(), BuiltinLanguageStrings(), + BuiltinInList(), BuiltinListDifference(), BuiltinListEquals(), + BuiltinListIntersection(), BuiltinListitem(), BuiltinListRe(), + BuiltinListReGroup(), BuiltinListSort(), BuiltinListUnion(), BuiltinLookup(), + BuiltinLowercase(), BuiltinMultiply(), BuiltinNot(), BuiltinOndevice(), + BuiltinOr(), BuiltinPrint(), BuiltinRawField(), BuiltinRawList(), + BuiltinRe(), BuiltinReGroup(), BuiltinSelect(), BuiltinSeriesSort(), + BuiltinShorten(), BuiltinStrcat(), BuiltinStrcatMax(), + BuiltinStrcmp(), BuiltinStrInList(), BuiltinStrlen(), BuiltinSubitems(), + BuiltinSublist(),BuiltinSubstr(), BuiltinSubtract(), BuiltinSwapAroundComma(), + BuiltinSwitch(), BuiltinTemplate(), BuiltinTest(), BuiltinTitlecase(), + BuiltinToday(), BuiltinTransliterate(), BuiltinUppercase(), + BuiltinUserCategories(), BuiltinVirtualLibraries() +] + + +class FormatterUserFunction(FormatterFunction): + + def __init__(self, name, doc, arg_count, program_text): + self.name = name + self.doc = doc + self.arg_count = arg_count + self.program_text = program_text + + +tabs = re.compile(r'^\t*') + + +def compile_user_function(name, doc, arg_count, eval_func): + def replace_func(mo): + return mo.group().replace('\t', ' ') + + func = ' ' + '\n '.join([tabs.sub(replace_func, line) + for line in eval_func.splitlines()]) + prog = ''' +from calibre.utils.formatter_functions import FormatterUserFunction +from calibre.utils.formatter_functions import formatter_functions +class UserFunction(FormatterUserFunction): +''' + func + locals_ = {} + if DEBUG and tweaks.get('enable_template_debug_printing', False): + print(prog) + exec(prog, locals_) + cls = locals_['UserFunction'](name, doc, arg_count, eval_func) + return cls + + +def compile_user_template_functions(funcs): + compiled_funcs = {} + for func in funcs: + try: + # Force a name conflict to test the logic + # if func[0] == 'myFunc2': + # func[0] = 'myFunc3' + + # Compile the function so that the tab processing is done on the + # source. This helps ensure that if the function already is defined + # then white space differences don't cause them to compare differently + + cls = compile_user_function(*func) + compiled_funcs[cls.name] = cls + except: + traceback.print_exc() + return compiled_funcs + + +def load_user_template_functions(library_uuid, funcs, precompiled_user_functions=None): + unload_user_template_functions(library_uuid) + if precompiled_user_functions: + compiled_funcs = precompiled_user_functions + else: + compiled_funcs = compile_user_template_functions(funcs) + formatter_functions().register_functions(library_uuid, list(compiled_funcs.values())) + + +def unload_user_template_functions(library_uuid): + formatter_functions().unregister_functions(library_uuid) diff --git a/ebook_converter/utils/html2text.py b/ebook_converter/utils/html2text.py new file mode 100644 index 0000000..fd83235 --- /dev/null +++ b/ebook_converter/utils/html2text.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +# License: GPLv3 Copyright: 2019, Kovid Goyal <kovid at kovidgoyal.net> +from __future__ import absolute_import, division, print_function, unicode_literals + + +def html2text(html): + from html2text import HTML2Text + import re + if isinstance(html, bytes): + from calibre.ebooks.chardet import xml_to_unicode + html = xml_to_unicode(html, strip_encoding_pats=True, resolve_entities=True)[0] + # replace <u> tags with <span> as <u> becomes emphasis in html2text + html = re.sub( + r'<\s*(?P<solidus>/?)\s*[uU]\b(?P<rest>[^>]*)>', + r'<\g<solidus>span\g<rest>>', html) + h2t = HTML2Text() + h2t.default_image_alt = _('Unnamed image') + h2t.body_width = 0 + h2t.single_line_break = True + h2t.emphasis_mark = '*' + return h2t.handle(html) + + +def find_tests(): + import unittest + + class TestH2T(unittest.TestCase): + + def test_html2text_behavior(self): + for src, expected in { + '<u>test</U>': 'test\n', + '<i>test</i>': '*test*\n', + '<a href="http://else.where/other">other</a>': '[other](http://else.where/other)\n', + '<img src="test.jpeg">': '![Unnamed image](test.jpeg)\n', + '<a href="#t">test</a> <span id="t">dest</span>': 'test dest\n', + '<>a': '<>a\n', + '<p>a<p>b': 'a\nb\n', + }.items(): + self.assertEqual(html2text(src), expected) + + return unittest.defaultTestLoader.loadTestsFromTestCase(TestH2T) diff --git a/ebook_converter/utils/icu.py b/ebook_converter/utils/icu.py new file mode 100644 index 0000000..2dd15c0 --- /dev/null +++ b/ebook_converter/utils/icu.py @@ -0,0 +1,323 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>' +__docformat__ = 'restructuredtext en' + +import sys +from polyglot.builtins import filter + +is_narrow_build = sys.maxunicode < 0x10ffff + +# Setup code {{{ +import codecs + +from calibre.constants import plugins +from calibre.utils.config_base import tweaks +from polyglot.builtins import unicode_type, cmp + +_locale = _collator = _primary_collator = _sort_collator = _numeric_collator = _case_sensitive_collator = None +cmp + +_none = u'' +_none2 = b'' +_cmap = {} + +_icu, err = plugins['icu'] +if _icu is None: + raise RuntimeError('Failed to load icu with error: %s' % err) +del err +icu_unicode_version = getattr(_icu, 'unicode_version', None) +_nmodes = {m:getattr(_icu, m) for m in ('NFC', 'NFD', 'NFKC', 'NFKD')} + +# Ensure that the python internal filesystem and default encodings are not ASCII + + +def is_ascii(name): + try: + return codecs.lookup(name).name == b'ascii' + except (TypeError, LookupError): + return True + + +try: + if is_ascii(sys.getdefaultencoding()): + _icu.set_default_encoding(b'utf-8') +except: + import traceback + traceback.print_exc() + +try: + if is_ascii(sys.getfilesystemencoding()): + _icu.set_filesystem_encoding(b'utf-8') +except: + import traceback + traceback.print_exc() +del is_ascii + + +def collator(): + global _collator, _locale + if _collator is None: + if _locale is None: + from calibre.utils.localization import get_lang + if tweaks['locale_for_sorting']: + _locale = tweaks['locale_for_sorting'] + else: + _locale = get_lang() + try: + _collator = _icu.Collator(_locale) + except Exception as e: + print('Failed to load collator for locale: %r with error %r, using English' % (_locale, e)) + _collator = _icu.Collator('en') + return _collator + + +def change_locale(locale=None): + global _locale, _collator, _primary_collator, _sort_collator, _numeric_collator, _case_sensitive_collator + _collator = _primary_collator = _sort_collator = _numeric_collator = _case_sensitive_collator = None + _locale = locale + + +def primary_collator(): + 'Ignores case differences and accented characters' + global _primary_collator + if _primary_collator is None: + _primary_collator = collator().clone() + _primary_collator.strength = _icu.UCOL_PRIMARY + return _primary_collator + + +def sort_collator(): + 'Ignores case differences and recognizes numbers in strings (if the tweak is set)' + global _sort_collator + if _sort_collator is None: + _sort_collator = collator().clone() + _sort_collator.strength = _icu.UCOL_SECONDARY + _sort_collator.numeric = tweaks['numeric_collation'] + return _sort_collator + + +def numeric_collator(): + 'Uses natural sorting for numbers inside strings so something2 will sort before something10' + global _numeric_collator + if _numeric_collator is None: + _numeric_collator = collator().clone() + _numeric_collator.strength = _icu.UCOL_SECONDARY + _numeric_collator.numeric = True + return _numeric_collator + + +def case_sensitive_collator(): + 'Always sorts upper case letter before lower case' + global _case_sensitive_collator + if _case_sensitive_collator is None: + _case_sensitive_collator = collator().clone() + _case_sensitive_collator.numeric = sort_collator().numeric + _case_sensitive_collator.upper_first = True + return _case_sensitive_collator + +# Templates that will be used to generate various concrete +# function implementations based on different collators, to allow lazy loading +# of collators, with maximum runtime performance + + +_sort_key_template = ''' +def {name}(obj): + try: + try: + return {collator}.{func}(obj) + except AttributeError: + pass + return {collator_func}().{func}(obj) + except TypeError: + if isinstance(obj, bytes): + try: + obj = obj.decode(sys.getdefaultencoding()) + except ValueError: + return obj + return {collator}.{func}(obj) + return b'' +''' + +_strcmp_template = ''' +def {name}(a, b): + try: + try: + return {collator}.{func}(a, b) + except AttributeError: + pass + return {collator_func}().{func}(a, b) + except TypeError: + if isinstance(a, bytes): + try: + a = a.decode(sys.getdefaultencoding()) + except ValueError: + return cmp(a, b) + elif a is None: + a = u'' + if isinstance(b, bytes): + try: + b = b.decode(sys.getdefaultencoding()) + except ValueError: + return cmp(a, b) + elif b is None: + b = u'' + return {collator}.{func}(a, b) +''' + +_change_case_template = ''' +def {name}(x): + try: + try: + return _icu.change_case(x, _icu.{which}, _locale) + except NotImplementedError: + pass + collator() # sets _locale + return _icu.change_case(x, _icu.{which}, _locale) + except TypeError: + if isinstance(x, bytes): + try: + x = x.decode(sys.getdefaultencoding()) + except ValueError: + return x + return _icu.change_case(x, _icu.{which}, _locale) + raise +''' + + +def _make_func(template, name, **kwargs): + l = globals() + kwargs['name'] = name + kwargs['func'] = kwargs.get('func', 'sort_key') + exec(template.format(**kwargs), l) + return l[name] + + +# }}} + +# ################ The string functions ######################################## +sort_key = _make_func(_sort_key_template, 'sort_key', collator='_sort_collator', collator_func='sort_collator') + +numeric_sort_key = _make_func(_sort_key_template, 'numeric_sort_key', collator='_numeric_collator', collator_func='numeric_collator') + +primary_sort_key = _make_func(_sort_key_template, 'primary_sort_key', collator='_primary_collator', collator_func='primary_collator') + +case_sensitive_sort_key = _make_func(_sort_key_template, 'case_sensitive_sort_key', + collator='_case_sensitive_collator', collator_func='case_sensitive_collator') + +collation_order = _make_func(_sort_key_template, 'collation_order', collator='_sort_collator', collator_func='sort_collator', func='collation_order') + +strcmp = _make_func(_strcmp_template, 'strcmp', collator='_sort_collator', collator_func='sort_collator', func='strcmp') + +case_sensitive_strcmp = _make_func( + _strcmp_template, 'case_sensitive_strcmp', collator='_case_sensitive_collator', collator_func='case_sensitive_collator', func='strcmp') + +primary_strcmp = _make_func(_strcmp_template, 'primary_strcmp', collator='_primary_collator', collator_func='primary_collator', func='strcmp') + +upper = _make_func(_change_case_template, 'upper', which='UPPER_CASE') + +lower = _make_func(_change_case_template, 'lower', which='LOWER_CASE') + +title_case = _make_func(_change_case_template, 'title_case', which='TITLE_CASE') + + +def capitalize(x): + try: + return upper(x[0]) + lower(x[1:]) + except (IndexError, TypeError, AttributeError): + return x + + +try: + swapcase = _icu.swap_case +except AttributeError: # For people running from source + swapcase = lambda x:x.swapcase() + +find = _make_func(_strcmp_template, 'find', collator='_collator', collator_func='collator', func='find') + +primary_find = _make_func(_strcmp_template, 'primary_find', collator='_primary_collator', collator_func='primary_collator', func='find') + +contains = _make_func(_strcmp_template, 'contains', collator='_collator', collator_func='collator', func='contains') + +primary_contains = _make_func(_strcmp_template, 'primary_contains', collator='_primary_collator', collator_func='primary_collator', func='contains') + +startswith = _make_func(_strcmp_template, 'startswith', collator='_collator', collator_func='collator', func='startswith') + +primary_startswith = _make_func(_strcmp_template, 'primary_startswith', collator='_primary_collator', collator_func='primary_collator', func='startswith') + +safe_chr = _icu.chr + +ord_string = _icu.ord_string + + +def character_name(string): + try: + return _icu.character_name(unicode_type(string)) or None + except (TypeError, ValueError, KeyError): + pass + + +def character_name_from_code(code): + try: + return _icu.character_name_from_code(code) or '' + except (TypeError, ValueError, KeyError): + return '' + + +def normalize(text, mode='NFC'): + # This is very slightly slower than using unicodedata.normalize, so stick with + # that unless you have very good reasons not too. Also, it's speed + # decreases on wide python builds, where conversion to/from ICU's string + # representation is slower. + return _icu.normalize(_nmodes[mode], unicode_type(text)) + + +def contractions(col=None): + global _cmap + col = col or _collator + if col is None: + col = collator() + ans = _cmap.get(collator, None) + if ans is None: + ans = col.contractions() + ans = frozenset(filter(None, ans)) + _cmap[col] = ans + return ans + + +def partition_by_first_letter(items, reverse=False, key=lambda x:x): + # Build a list of 'equal' first letters by noticing changes + # in ICU's 'ordinal' for the first letter. + from collections import OrderedDict + items = sorted(items, key=lambda x:sort_key(key(x)), reverse=reverse) + ans = OrderedDict() + last_c, last_ordnum = ' ', 0 + for item in items: + c = icu_upper(key(item) or ' ') + ordnum, ordlen = collation_order(c) + if last_ordnum != ordnum: + if not is_narrow_build: + ordlen = 1 + last_c = c[0:ordlen] + last_ordnum = ordnum + try: + ans[last_c].append(item) + except KeyError: + ans[last_c] = [item] + return ans + + +# Return the number of unicode codepoints in a string +string_length = _icu.string_length if is_narrow_build else len + +# Return the number of UTF-16 codepoints in a string +utf16_length = len if is_narrow_build else _icu.utf16_length + +################################################################################ + +if __name__ == '__main__': + from calibre.utils.icu_test import run + run(verbosity=4) diff --git a/ebook_converter/utils/img.py b/ebook_converter/utils/img.py new file mode 100644 index 0000000..e6f14e3 --- /dev/null +++ b/ebook_converter/utils/img.py @@ -0,0 +1,690 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +# License: GPLv3 Copyright: 2015-2019, Kovid Goyal <kovid at kovidgoyal.net> +from __future__ import absolute_import, division, print_function, unicode_literals + +import errno +import os +import shutil +import subprocess +import sys +import tempfile +from io import BytesIO +from threading import Thread + +# We use explicit module imports so tracebacks when importing are more useful +from PyQt5.QtCore import QBuffer, QByteArray, Qt +from PyQt5.QtGui import QColor, QImage, QImageReader, QImageWriter, QPixmap, QTransform + +from calibre import fit_image, force_unicode +from calibre.constants import iswindows, plugins, ispy3 +from calibre.ptempfile import TemporaryDirectory +from calibre.utils.config_base import tweaks +from calibre.utils.filenames import atomic_rename +from calibre.utils.imghdr import what +from polyglot.builtins import string_or_bytes, unicode_type + +# Utilities {{{ +imageops, imageops_err = plugins['imageops'] +if imageops is None: + raise RuntimeError(imageops_err) + + +class NotImage(ValueError): + pass + + +def normalize_format_name(fmt): + fmt = fmt.lower() + if fmt == 'jpg': + fmt = 'jpeg' + return fmt + + +def get_exe_path(name): + from calibre.ebooks.pdf.pdftohtml import PDFTOHTML + base = os.path.dirname(PDFTOHTML) + if iswindows: + name += '-calibre.exe' + if not base: + return name + return os.path.join(base, name) + + +def load_jxr_data(data): + with TemporaryDirectory() as tdir: + if iswindows and isinstance(tdir, unicode_type): + tdir = tdir.encode('mbcs') + with lopen(os.path.join(tdir, 'input.jxr'), 'wb') as f: + f.write(data) + cmd = [get_exe_path('JxrDecApp'), '-i', 'input.jxr', '-o', 'output.tif'] + creationflags = 0x08 if iswindows else 0 + subprocess.Popen(cmd, cwd=tdir, stdout=lopen(os.devnull, 'wb'), stderr=subprocess.STDOUT, creationflags=creationflags).wait() + i = QImage() + if not i.load(os.path.join(tdir, 'output.tif')): + raise NotImage('Failed to convert JPEG-XR image') + return i + +# }}} + +# png <-> gif {{{ + + +def png_data_to_gif_data(data): + from PIL import Image + img = Image.open(BytesIO(data)) + buf = BytesIO() + if img.mode in ('p', 'P'): + transparency = img.info.get('transparency') + if transparency is not None: + img.save(buf, 'gif', transparency=transparency) + else: + img.save(buf, 'gif') + elif img.mode in ('rgba', 'RGBA'): + alpha = img.split()[3] + mask = Image.eval(alpha, lambda a: 255 if a <=128 else 0) + img = img.convert('RGB').convert('P', palette=Image.ADAPTIVE, colors=255) + img.paste(255, mask) + img.save(buf, 'gif', transparency=255) + else: + img = img.convert('P', palette=Image.ADAPTIVE) + img.save(buf, 'gif') + return buf.getvalue() + + +class AnimatedGIF(ValueError): + pass + + +def gif_data_to_png_data(data, discard_animation=False): + from PIL import Image + img = Image.open(BytesIO(data)) + if img.is_animated and not discard_animation: + raise AnimatedGIF() + buf = BytesIO() + img.save(buf, 'png') + return buf.getvalue() + +# }}} + +# Loading images {{{ + + +def null_image(): + ' Create an invalid image. For internal use. ' + return QImage() + + +def image_from_data(data): + ' Create an image object from data, which should be a bytestring. ' + if isinstance(data, QImage): + return data + i = QImage() + if not i.loadFromData(data): + q = what(None, data) + if q == 'jxr': + return load_jxr_data(data) + raise NotImage('Not a valid image (detected type: {})'.format(q)) + return i + + +def image_from_path(path): + ' Load an image from the specified path. ' + with lopen(path, 'rb') as f: + return image_from_data(f.read()) + + +def image_from_x(x): + ' Create an image from a bytestring or a path or a file like object. ' + if isinstance(x, unicode_type): + return image_from_path(x) + if hasattr(x, 'read'): + return image_from_data(x.read()) + if isinstance(x, (bytes, QImage)): + return image_from_data(x) + if isinstance(x, bytearray): + return image_from_data(bytes(x)) + if isinstance(x, QPixmap): + return x.toImage() + raise TypeError('Unknown image src type: %s' % type(x)) + + +def image_and_format_from_data(data): + ' Create an image object from the specified data which should be a bytestring and also return the format of the image ' + ba = QByteArray(data) + buf = QBuffer(ba) + buf.open(QBuffer.ReadOnly) + r = QImageReader(buf) + fmt = bytes(r.format()).decode('utf-8') + return r.read(), fmt +# }}} + +# Saving images {{{ + + +def image_to_data(img, compression_quality=95, fmt='JPEG', png_compression_level=9, jpeg_optimized=True, jpeg_progressive=False): + ''' + Serialize image to bytestring in the specified format. + + :param compression_quality: is for JPEG and goes from 0 to 100. 100 being lowest compression, highest image quality + :param png_compression_level: is for PNG and goes from 0-9. 9 being highest compression. + :param jpeg_optimized: Turns on the 'optimize' option for libjpeg which losslessly reduce file size + :param jpeg_progressive: Turns on the 'progressive scan' option for libjpeg which allows JPEG images to be downloaded in streaming fashion + ''' + fmt = fmt.upper() + ba = QByteArray() + buf = QBuffer(ba) + buf.open(QBuffer.WriteOnly) + if fmt == 'GIF': + w = QImageWriter(buf, b'PNG') + w.setQuality(90) + if not w.write(img): + raise ValueError('Failed to export image as ' + fmt + ' with error: ' + w.errorString()) + return png_data_to_gif_data(ba.data()) + is_jpeg = fmt in ('JPG', 'JPEG') + w = QImageWriter(buf, fmt.encode('ascii')) + if is_jpeg: + if img.hasAlphaChannel(): + img = blend_image(img) + # QImageWriter only gained the following options in Qt 5.5 + if jpeg_optimized: + w.setOptimizedWrite(True) + if jpeg_progressive: + w.setProgressiveScanWrite(True) + w.setQuality(compression_quality) + elif fmt == 'PNG': + cl = min(9, max(0, png_compression_level)) + w.setQuality(10 * (9-cl)) + if not w.write(img): + raise ValueError('Failed to export image as ' + fmt + ' with error: ' + w.errorString()) + return ba.data() + + +def save_image(img, path, **kw): + ''' Save image to the specified path. Image format is taken from the file + extension. You can pass the same keyword arguments as for the + `image_to_data()` function. ''' + fmt = path.rpartition('.')[-1] + kw['fmt'] = kw.get('fmt', fmt) + with lopen(path, 'wb') as f: + f.write(image_to_data(image_from_data(img), **kw)) + + +def save_cover_data_to( + data, path=None, + bgcolor='#ffffff', + resize_to=None, + compression_quality=90, + minify_to=None, + grayscale=False, + eink=False, letterbox=False, + data_fmt='jpeg' +): + ''' + Saves image in data to path, in the format specified by the path + extension. Removes any transparency. If there is no transparency and no + resize and the input and output image formats are the same, no changes are + made. + + :param data: Image data as bytestring + :param path: If None img data is returned, in JPEG format + :param data_fmt: The fmt to return data in when path is None. Defaults to JPEG + :param compression_quality: The quality of the image after compression. + Number between 1 and 100. 1 means highest compression, 100 means no + compression (lossless). When generating PNG this number is divided by 10 + for the png_compression_level. + :param bgcolor: The color for transparent pixels. Must be specified in hex. + :param resize_to: A tuple (width, height) or None for no resizing + :param minify_to: A tuple (width, height) to specify maximum target size. + The image will be resized to fit into this target size. If None the + value from the tweak is used. + :param grayscale: If True, the image is converted to grayscale, + if that's not already the case. + :param eink: If True, the image is dithered down to the 16 specific shades + of gray of the eInk palette. + Works best with formats that actually support color indexing (i.e., PNG) + :param letterbox: If True, in addition to fit resize_to inside minify_to, + the image will be letterboxed (i.e., centered on a black background). + ''' + fmt = normalize_format_name(data_fmt if path is None else os.path.splitext(path)[1][1:]) + if isinstance(data, QImage): + img = data + changed = True + else: + img, orig_fmt = image_and_format_from_data(data) + orig_fmt = normalize_format_name(orig_fmt) + changed = fmt != orig_fmt + if resize_to is not None: + changed = True + img = img.scaled(resize_to[0], resize_to[1], Qt.IgnoreAspectRatio, Qt.SmoothTransformation) + owidth, oheight = img.width(), img.height() + nwidth, nheight = tweaks['maximum_cover_size'] if minify_to is None else minify_to + if letterbox: + img = blend_on_canvas(img, nwidth, nheight, bgcolor='#000000') + # Check if we were minified + if oheight != nheight or owidth != nwidth: + changed = True + else: + scaled, nwidth, nheight = fit_image(owidth, oheight, nwidth, nheight) + if scaled: + changed = True + img = img.scaled(nwidth, nheight, Qt.IgnoreAspectRatio, Qt.SmoothTransformation) + if img.hasAlphaChannel(): + changed = True + img = blend_image(img, bgcolor) + if grayscale and not eink: + if not img.allGray(): + changed = True + img = grayscale_image(img) + if eink: + # NOTE: Keep in mind that JPG does NOT actually support indexed colors, so the JPG algorithm will then smush everything back into a 256c mess... + # Thankfully, Nickel handles PNG just fine, and we potentially generate smaller files to boot, because they can be properly color indexed ;). + img = eink_dither_image(img) + changed = True + if path is None: + return image_to_data(img, compression_quality, fmt, compression_quality // 10) if changed else data + with lopen(path, 'wb') as f: + f.write(image_to_data(img, compression_quality, fmt, compression_quality // 10) if changed else data) +# }}} + +# Overlaying images {{{ + + +def blend_on_canvas(img, width, height, bgcolor='#ffffff'): + ' Blend the `img` onto a canvas with the specified background color and size ' + w, h = img.width(), img.height() + scaled, nw, nh = fit_image(w, h, width, height) + if scaled: + img = img.scaled(nw, nh, Qt.IgnoreAspectRatio, Qt.SmoothTransformation) + w, h = nw, nh + canvas = QImage(width, height, QImage.Format_RGB32) + canvas.fill(QColor(bgcolor)) + overlay_image(img, canvas, (width - w)//2, (height - h)//2) + return canvas + + +class Canvas(object): + + def __init__(self, width, height, bgcolor='#ffffff'): + self.img = QImage(width, height, QImage.Format_RGB32) + self.img.fill(QColor(bgcolor)) + + def __enter__(self): + return self + + def __exit__(self, *args): + pass + + def compose(self, img, x=0, y=0): + img = image_from_data(img) + overlay_image(img, self.img, x, y) + + def export(self, fmt='JPEG', compression_quality=95): + return image_to_data(self.img, compression_quality=compression_quality, fmt=fmt) + + +def create_canvas(width, height, bgcolor='#ffffff'): + 'Create a blank canvas of the specified size and color ' + img = QImage(width, height, QImage.Format_RGB32) + img.fill(QColor(bgcolor)) + return img + + +def overlay_image(img, canvas=None, left=0, top=0): + ' Overlay the `img` onto the canvas at the specified position ' + if canvas is None: + canvas = QImage(img.size(), QImage.Format_RGB32) + canvas.fill(Qt.white) + left, top = int(left), int(top) + imageops.overlay(img, canvas, left, top) + return canvas + + +def texture_image(canvas, texture): + ' Repeatedly tile the image `texture` across and down the image `canvas` ' + if canvas.hasAlphaChannel(): + canvas = blend_image(canvas) + return imageops.texture_image(canvas, texture) + + +def blend_image(img, bgcolor='#ffffff'): + ' Used to convert images that have semi-transparent pixels to opaque by blending with the specified color ' + canvas = QImage(img.size(), QImage.Format_RGB32) + canvas.fill(QColor(bgcolor)) + overlay_image(img, canvas) + return canvas +# }}} + +# Image borders {{{ + + +def add_borders_to_image(img, left=0, top=0, right=0, bottom=0, border_color='#ffffff'): + img = image_from_data(img) + if not (left > 0 or right > 0 or top > 0 or bottom > 0): + return img + canvas = QImage(img.width() + left + right, img.height() + top + bottom, QImage.Format_RGB32) + canvas.fill(QColor(border_color)) + overlay_image(img, canvas, left, top) + return canvas + + +def remove_borders_from_image(img, fuzz=None): + ''' Try to auto-detect and remove any borders from the image. Returns + the image itself if no borders could be removed. `fuzz` is a measure of + what colors are considered identical (must be a number between 0 and 255 in + absolute intensity units). Default is from a tweak whose default value is 10. ''' + fuzz = tweaks['cover_trim_fuzz_value'] if fuzz is None else fuzz + img = image_from_data(img) + ans = imageops.remove_borders(img, max(0, fuzz)) + return ans if ans.size() != img.size() else img +# }}} + +# Cropping/scaling of images {{{ + + +def resize_image(img, width, height): + return img.scaled(int(width), int(height), Qt.IgnoreAspectRatio, Qt.SmoothTransformation) + + +def resize_to_fit(img, width, height): + img = image_from_data(img) + resize_needed, nw, nh = fit_image(img.width(), img.height(), width, height) + if resize_needed: + img = resize_image(img, nw, nh) + return resize_needed, img + + +def clone_image(img): + ''' Returns a shallow copy of the image. However, the underlying data buffer + will be automatically copied-on-write ''' + return QImage(img) + + +def scale_image(data, width=60, height=80, compression_quality=70, as_png=False, preserve_aspect_ratio=True): + ''' Scale an image, returning it as either JPEG or PNG data (bytestring). + Transparency is alpha blended with white when converting to JPEG. Is thread + safe and does not require a QApplication. ''' + # We use Qt instead of ImageMagick here because ImageMagick seems to use + # some kind of memory pool, causing memory consumption to sky rocket. + img = image_from_data(data) + if preserve_aspect_ratio: + scaled, nwidth, nheight = fit_image(img.width(), img.height(), width, height) + if scaled: + img = img.scaled(nwidth, nheight, Qt.KeepAspectRatio, Qt.SmoothTransformation) + else: + if img.width() != width or img.height() != height: + img = img.scaled(width, height, Qt.IgnoreAspectRatio, Qt.SmoothTransformation) + fmt = 'PNG' if as_png else 'JPEG' + w, h = img.width(), img.height() + return w, h, image_to_data(img, compression_quality=compression_quality, fmt=fmt) + + +def crop_image(img, x, y, width, height): + ''' + Return the specified section of the image. + + :param x, y: The top left corner of the crop box + :param width, height: The width and height of the crop box. Note that if + the crop box exceeds the source images dimensions, width and height will be + auto-truncated. + ''' + img = image_from_data(img) + width = min(width, img.width() - x) + height = min(height, img.height() - y) + return img.copy(x, y, width, height) + +# }}} + +# Image transformations {{{ + + +def grayscale_image(img): + return imageops.grayscale(image_from_data(img)) + + +def set_image_opacity(img, alpha=0.5): + ''' Change the opacity of `img`. Note that the alpha value is multiplied to + any existing alpha values, so you cannot use this function to convert a + semi-transparent image to an opaque one. For that use `blend_image()`. ''' + return imageops.set_opacity(image_from_data(img), alpha) + + +def flip_image(img, horizontal=False, vertical=False): + return image_from_data(img).mirrored(horizontal, vertical) + + +def image_has_transparent_pixels(img): + ' Return True iff the image has at least one semi-transparent pixel ' + img = image_from_data(img) + if img.isNull(): + return False + return imageops.has_transparent_pixels(img) + + +def rotate_image(img, degrees): + t = QTransform() + t.rotate(degrees) + return image_from_data(img).transformed(t) + + +def gaussian_sharpen_image(img, radius=0, sigma=3, high_quality=True): + return imageops.gaussian_sharpen(image_from_data(img), max(0, radius), sigma, high_quality) + + +def gaussian_blur_image(img, radius=-1, sigma=3): + return imageops.gaussian_blur(image_from_data(img), max(0, radius), sigma) + + +def despeckle_image(img): + return imageops.despeckle(image_from_data(img)) + + +def oil_paint_image(img, radius=-1, high_quality=True): + return imageops.oil_paint(image_from_data(img), radius, high_quality) + + +def normalize_image(img): + return imageops.normalize(image_from_data(img)) + + +def quantize_image(img, max_colors=256, dither=True, palette=''): + ''' Quantize the image to contain a maximum of `max_colors` colors. By + default a palette is chosen automatically, if you want to use a fixed + palette, then pass in a list of color names in the `palette` variable. If + you, specify a palette `max_colors` is ignored. Note that it is possible + for the actual number of colors used to be less than max_colors. + + :param max_colors: Max. number of colors in the auto-generated palette. Must be between 2 and 256. + :param dither: Whether to use dithering or not. dithering is almost always a good thing. + :param palette: Use a manually specified palette instead. For example: palette='red green blue #eee' + ''' + img = image_from_data(img) + if img.hasAlphaChannel(): + img = blend_image(img) + if palette and isinstance(palette, string_or_bytes): + palette = palette.split() + return imageops.quantize(img, max_colors, dither, [QColor(x).rgb() for x in palette]) + + +def eink_dither_image(img): + ''' Dither the source image down to the eInk palette of 16 shades of grey, + using ImageMagick's OrderedDither algorithm. + + NOTE: No need to call grayscale_image first, as this will inline a grayscaling pass if need be. + + Returns a QImage in Grayscale8 pixel format. + ''' + img = image_from_data(img) + if img.hasAlphaChannel(): + img = blend_image(img) + return imageops.ordered_dither(img) + +# }}} + +# Optimization of images {{{ + + +def run_optimizer(file_path, cmd, as_filter=False, input_data=None): + file_path = os.path.abspath(file_path) + cwd = os.path.dirname(file_path) + ext = os.path.splitext(file_path)[1] + if not ext or len(ext) > 10 or not ext.startswith('.'): + ext = '.jpg' + fd, outfile = tempfile.mkstemp(dir=cwd, suffix=ext) + try: + if as_filter: + outf = os.fdopen(fd, 'wb') + else: + os.close(fd) + iname, oname = os.path.basename(file_path), os.path.basename(outfile) + + def repl(q, r): + cmd[cmd.index(q)] = r + if not as_filter: + repl(True, iname), repl(False, oname) + if iswindows and not ispy3: + # subprocess in python 2 cannot handle unicode strings that are not + # encodeable in mbcs, so we fail here, where it is more explicit, + # instead. + cmd = [x.encode('mbcs') if isinstance(x, unicode_type) else x for x in cmd] + if isinstance(cwd, unicode_type): + cwd = cwd.encode('mbcs') + stdin = subprocess.PIPE if as_filter else None + stderr = subprocess.PIPE if as_filter else subprocess.STDOUT + creationflags = 0x08 if iswindows else 0 + p = subprocess.Popen(cmd, cwd=cwd, stdout=subprocess.PIPE, stderr=stderr, stdin=stdin, creationflags=creationflags) + stderr = p.stderr if as_filter else p.stdout + if as_filter: + src = input_data or open(file_path, 'rb') + + def copy(src, dest): + try: + shutil.copyfileobj(src, dest) + finally: + src.close(), dest.close() + inw = Thread(name='CopyInput', target=copy, args=(src, p.stdin)) + inw.daemon = True + inw.start() + outw = Thread(name='CopyOutput', target=copy, args=(p.stdout, outf)) + outw.daemon = True + outw.start() + raw = force_unicode(stderr.read()) + if p.wait() != 0: + return raw + else: + if as_filter: + outw.join(60.0), inw.join(60.0) + try: + sz = os.path.getsize(outfile) + except EnvironmentError: + sz = 0 + if sz < 1: + return '%s returned a zero size image' % cmd[0] + shutil.copystat(file_path, outfile) + atomic_rename(outfile, file_path) + finally: + try: + os.remove(outfile) + except EnvironmentError as err: + if err.errno != errno.ENOENT: + raise + try: + os.remove(outfile + '.bak') # optipng creates these files + except EnvironmentError as err: + if err.errno != errno.ENOENT: + raise + + +def optimize_jpeg(file_path): + exe = get_exe_path('jpegtran') + cmd = [exe] + '-copy none -optimize -progressive -maxmemory 100M -outfile'.split() + [False, True] + return run_optimizer(file_path, cmd) + + +def optimize_png(file_path, level=7): + ' level goes from 1 to 7 with 7 being maximum compression ' + exe = get_exe_path('optipng') + cmd = [exe] + '-fix -clobber -strip all -o{} -out'.format(level).split() + [False, True] + return run_optimizer(file_path, cmd) + + +def encode_jpeg(file_path, quality=80): + from calibre.utils.speedups import ReadOnlyFileBuffer + quality = max(0, min(100, int(quality))) + exe = get_exe_path('cjpeg') + cmd = [exe] + '-optimize -progressive -maxmemory 100M -quality'.split() + [unicode_type(quality)] + img = QImage() + if not img.load(file_path): + raise ValueError('%s is not a valid image file' % file_path) + ba = QByteArray() + buf = QBuffer(ba) + buf.open(QBuffer.WriteOnly) + if not img.save(buf, 'PPM'): + raise ValueError('Failed to export image to PPM') + return run_optimizer(file_path, cmd, as_filter=True, input_data=ReadOnlyFileBuffer(ba.data())) +# }}} + + +def test(): # {{{ + from calibre.ptempfile import TemporaryDirectory + from calibre import CurrentDir + from glob import glob + img = image_from_data(I('lt.png', data=True, allow_user_override=False)) + with TemporaryDirectory() as tdir, CurrentDir(tdir): + save_image(img, 'test.jpg') + ret = optimize_jpeg('test.jpg') + if ret is not None: + raise SystemExit('optimize_jpeg failed: %s' % ret) + ret = encode_jpeg('test.jpg') + if ret is not None: + raise SystemExit('encode_jpeg failed: %s' % ret) + shutil.copyfile(I('lt.png'), 'test.png') + ret = optimize_png('test.png') + if ret is not None: + raise SystemExit('optimize_png failed: %s' % ret) + if glob('*.bak'): + raise SystemExit('Spurious .bak files left behind') + quantize_image(img) + oil_paint_image(img) + gaussian_sharpen_image(img) + gaussian_blur_image(img) + despeckle_image(img) + remove_borders_from_image(img) + image_to_data(img, fmt='GIF') + raw = subprocess.Popen([get_exe_path('JxrDecApp'), '-h'], creationflags=0x08 if iswindows else 0, stdout=subprocess.PIPE).stdout.read() + if b'JPEG XR Decoder Utility' not in raw: + raise SystemExit('Failed to run JxrDecApp') +# }}} + + +if __name__ == '__main__': # {{{ + args = sys.argv[1:] + infile = args.pop(0) + img = image_from_data(lopen(infile, 'rb').read()) + func = globals()[args[0]] + kw = {} + args.pop(0) + outf = None + while args: + k = args.pop(0) + if '=' in k: + n, v = k.partition('=')[::2] + if v in ('True', 'False'): + v = True if v == 'True' else False + try: + v = int(v) + except Exception: + try: + v = float(v) + except Exception: + pass + kw[n] = v + else: + outf = k + if outf is None: + bn = os.path.basename(infile) + outf = bn.rpartition('.')[0] + '.' + '-output' + bn.rpartition('.')[-1] + img = func(img, **kw) + with lopen(outf, 'wb') as f: + f.write(image_to_data(img, fmt=outf.rpartition('.')[-1])) +# }}} diff --git a/ebook_converter/utils/imghdr.py b/ebook_converter/utils/imghdr.py new file mode 100644 index 0000000..fa6558d --- /dev/null +++ b/ebook_converter/utils/imghdr.py @@ -0,0 +1,263 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +# License: GPLv3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net> +from __future__ import absolute_import, division, print_function, unicode_literals + +from struct import unpack, error +import os +from calibre.utils.speedups import ReadOnlyFileBuffer +from calibre.constants import ispy3 +from polyglot.builtins import string_or_bytes, unicode_type + +""" Recognize image file formats and sizes based on their first few bytes.""" + +HSIZE = 120 + + +def what(file, h=None): + ' Recognize image headers ' + if h is None: + if isinstance(file, string_or_bytes): + with lopen(file, 'rb') as f: + h = f.read(HSIZE) + else: + location = file.tell() + h = file.read(HSIZE) + file.seek(location) + if isinstance(h, bytes): + h = memoryview(h) + for tf in tests: + res = tf(h) + if res: + return res + # There exist some jpeg files with no headers, only the starting two bits + # If we cannot identify as anything else, identify as jpeg. + if h[:2] == b'\xff\xd8': + return 'jpeg' + return None + + +def identify(src): + ''' Recognize file format and sizes. Returns format, width, height. width + and height will be -1 if not found and fmt will be None if the image is not + recognized. ''' + width = height = -1 + + if isinstance(src, unicode_type): + stream = lopen(src, 'rb') + elif isinstance(src, bytes): + stream = ReadOnlyFileBuffer(src) + else: + stream = src + + pos = stream.tell() + head = stream.read(HSIZE) + stream.seek(pos) + fmt = what(None, head) + + if fmt in {'jpeg', 'gif', 'png', 'jpeg2000'}: + size = len(head) + if fmt == 'png': + # PNG + s = head[16:24] if size >= 24 and head[12:16] == b'IHDR' else head[8:16] + try: + width, height = unpack(b">LL", s) + except error: + return fmt, width, height + elif fmt == 'jpeg': + # JPEG + pos = stream.tell() + try: + height, width = jpeg_dimensions(stream) + except Exception: + return fmt, width, height + finally: + stream.seek(pos) + elif fmt == 'gif': + # GIF + try: + width, height = unpack(b"<HH", head[6:10]) + except error: + return fmt, width, height + elif size >= 56 and fmt == 'jpeg2000': + # JPEG2000 + try: + height, width = unpack(b'>LL', head[48:56]) + except error: + return fmt, width, height + return fmt, width, height + +# ---------------------------------# +# Subroutines per image file type # +# ---------------------------------# + + +tests = [] + + +def test(f): + tests.append(f) + return f + + +@test +def jpeg(h): + """JPEG data in JFIF format (Changed by Kovid to mimic the file utility, + the original code was failing with some jpegs that included ICC_PROFILE + data, for example: http://nationalpostnews.files.wordpress.com/2013/03/budget.jpeg?w=300&h=1571)""" + if h[6:10] in (b'JFIF', b'Exif'): + return 'jpeg' + if h[:2] == b'\xff\xd8': + q = h[:32].tobytes() + if b'JFIF' in q or b'8BIM' in q: + return 'jpeg' + + +def jpeg_dimensions(stream): + # A JPEG marker is two bytes of the form 0xff x where 0 < x < 0xff + # See section B.1.1.2 of https://www.w3.org/Graphics/JPEG/itu-t81.pdf + # We read the dimensions from the first SOFn section we come across + stream.seek(2, os.SEEK_CUR) + + def read(n): + ans = stream.read(n) + if len(ans) != n: + raise ValueError('Truncated JPEG data') + return ans + + if ispy3: + def read_byte(): + return read(1)[0] + else: + def read_byte(): + return ord(read(1)[0]) + + x = None + while True: + # Find next marker + while x != 0xff: + x = read_byte() + # Soak up padding + marker = 0xff + while marker == 0xff: + marker = read_byte() + q = marker + if 0xc0 <= q <= 0xcf and q != 0xc4 and q != 0xcc: + # SOFn marker + stream.seek(3, os.SEEK_CUR) + return unpack(b'>HH', read(4)) + elif 0xd8 <= q <= 0xda: + break # start of image, end of image, start of scan, no point + elif q == 0: + return -1, -1 # Corrupted JPEG + elif q == 0x01 or 0xd0 <= q <= 0xd7: + # Standalone marker + continue + else: + # skip this section + size = unpack(b'>H', read(2))[0] + stream.seek(size - 2, os.SEEK_CUR) + # standalone marker, keep going + + return -1, -1 + + +@test +def png(h): + if h[:8] == b"\211PNG\r\n\032\n": + return 'png' + + +@test +def gif(h): + """GIF ('87 and '89 variants)""" + if h[:6] in (b'GIF87a', b'GIF89a'): + return 'gif' + + +@test +def tiff(h): + """TIFF (can be in Motorola or Intel byte order)""" + if h[:2] in (b'MM', b'II'): + if h[2:4] == b'\xbc\x01': + return 'jxr' + return 'tiff' + + +@test +def webp(h): + if h[:4] == b'RIFF' and h[8:12] == b'WEBP': + return 'webp' + + +@test +def rgb(h): + """SGI image library""" + if h[:2] == b'\001\332': + return 'rgb' + + +@test +def pbm(h): + """PBM (portable bitmap)""" + if len(h) >= 3 and \ + h[0] == b'P' and h[1] in b'14' and h[2] in b' \t\n\r': + return 'pbm' + + +@test +def pgm(h): + """PGM (portable graymap)""" + if len(h) >= 3 and \ + h[0] == b'P' and h[1] in b'25' and h[2] in b' \t\n\r': + return 'pgm' + + +@test +def ppm(h): + """PPM (portable pixmap)""" + if len(h) >= 3 and \ + h[0] == b'P' and h[1] in b'36' and h[2] in b' \t\n\r': + return 'ppm' + + +@test +def rast(h): + """Sun raster file""" + if h[:4] == b'\x59\xA6\x6A\x95': + return 'rast' + + +@test +def xbm(h): + """X bitmap (X10 or X11)""" + s = b'#define ' + if h[:len(s)] == s: + return 'xbm' + + +@test +def bmp(h): + if h[:2] == b'BM': + return 'bmp' + + +@test +def emf(h): + if h[:4] == b'\x01\0\0\0' and h[40:44] == b' EMF': + return 'emf' + + +@test +def jpeg2000(h): + if h[:12] == b'\x00\x00\x00\x0cjP \r\n\x87\n': + return 'jpeg2000' + + +@test +def svg(h): + if h[:4] == b'<svg' or (h[:2] == b'<?' and h[2:5].tobytes().lower() == b'xml' and b'<svg' in h.tobytes()): + return 'svg' + + +tests = tuple(tests) diff --git a/ebook_converter/utils/ipc/__init__.py b/ebook_converter/utils/ipc/__init__.py new file mode 100644 index 0000000..b2a8aaf --- /dev/null +++ b/ebook_converter/utils/ipc/__init__.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>' +__docformat__ = 'restructuredtext en' + +import os, errno, sys +from threading import Thread + +from calibre import force_unicode +from calibre.constants import iswindows, get_windows_username, islinux, filesystem_encoding, ispy3 +from calibre.utils.filenames import ascii_filename +from polyglot.functools import lru_cache + +VADDRESS = None + + +def eintr_retry_call(func, *args, **kwargs): + while True: + try: + return func(*args, **kwargs) + except EnvironmentError as e: + if getattr(e, 'errno', None) == errno.EINTR: + continue + raise + + +@lru_cache() +def socket_address(which): + if iswindows: + ans = r'\\.\pipe\Calibre' + which + try: + user = get_windows_username() + except Exception: + user = None + if user: + user = ascii_filename(user).replace(' ', '_') + if user: + ans += '-' + user[:100] + 'x' + else: + user = force_unicode(os.environ.get('USER') or os.path.basename(os.path.expanduser('~')), filesystem_encoding) + sock_name = '{}-calibre-{}.socket'.format(ascii_filename(user).replace(' ', '_'), which) + if islinux: + ans = '\0' + sock_name + else: + from tempfile import gettempdir + tmp = force_unicode(gettempdir(), filesystem_encoding) + ans = os.path.join(tmp, sock_name) + if not ispy3 and not isinstance(ans, bytes): + ans = ans.encode(filesystem_encoding) + return ans + + +def gui_socket_address(): + return socket_address('GUI' if iswindows else 'gui') + + +def viewer_socket_address(): + return socket_address('Viewer' if iswindows else 'viewer') + + +class RC(Thread): + + def __init__(self, print_error=True, socket_address=None): + self.print_error = print_error + self.socket_address = socket_address or gui_socket_address() + Thread.__init__(self) + self.conn = None + self.daemon = True + + def run(self): + from multiprocessing.connection import Client + self.done = False + try: + self.conn = Client(self.socket_address) + self.done = True + except Exception: + if self.print_error: + print('Failed to connect to address {}', file=sys.stderr).format(repr(self.socket_address)) + import traceback + traceback.print_exc() diff --git a/ebook_converter/utils/ipc/launch.py b/ebook_converter/utils/ipc/launch.py new file mode 100644 index 0000000..fddfae7 --- /dev/null +++ b/ebook_converter/utils/ipc/launch.py @@ -0,0 +1,237 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>' +__docformat__ = 'restructuredtext en' + +import subprocess, os, sys, time +from functools import partial + +from calibre.constants import iswindows, isosx, isfrozen, filesystem_encoding, ispy3 +from calibre.utils.config import prefs +from calibre.ptempfile import PersistentTemporaryFile, base_dir +from calibre.utils.serialize import msgpack_dumps +from polyglot.builtins import iteritems, unicode_type, string_or_bytes, environ_item, native_string_type, getcwd +from polyglot.binary import as_hex_unicode + +if iswindows: + import win32process + try: + windows_null_file = open(os.devnull, 'wb') + except: + raise RuntimeError('NUL file missing in windows. This indicates a' + ' corrupted windows. You should contact Microsoft' + ' for assistance and/or follow the steps described here: https://bytes.com/topic/net/answers/264804-compile-error-null-device-missing') + + +def renice(niceness): + try: + os.nice(niceness) + except: + pass + + +class Worker(object): + ''' + Platform independent object for launching child processes. All processes + have the environment variable :envvar:`CALIBRE_WORKER` set. + + Useful attributes: ``is_alive``, ``returncode``, ``pid`` + Useful methods: ``kill`` + + To launch child simply call the Worker object. By default, the child's + output is redirected to an on disk file, the path to which is returned by + the call. + ''' + + exe_name = 'calibre-parallel' + + @property + def executable(self): + if hasattr(sys, 'running_from_setup'): + return [sys.executable, os.path.join(sys.setup_dir, 'run-calibre-worker.py')] + if getattr(sys, 'run_local', False): + return [sys.executable, sys.run_local, self.exe_name] + e = self.exe_name + if iswindows: + return os.path.join(os.path.dirname(sys.executable), + e+'.exe' if isfrozen else 'Scripts\\%s.exe'%e) + if isosx: + return os.path.join(sys.binaries_path, e) + + if isfrozen: + return os.path.join(sys.executables_location, e) + + if hasattr(sys, 'executables_location'): + c = os.path.join(sys.executables_location, e) + if os.access(c, os.X_OK): + return c + return e + + @property + def gui_executable(self): + if isosx and not hasattr(sys, 'running_from_setup'): + if self.job_name == 'ebook-viewer': + base = os.path.dirname(sys.binaries_path) + return os.path.join(base, 'ebook-viewer.app/Contents/MacOS/', self.exe_name) + if self.job_name == 'ebook-edit': + base = os.path.dirname(sys.binaries_path) + return os.path.join(base, 'ebook-viewer.app/Contents/ebook-edit.app/Contents/MacOS/', self.exe_name) + + return os.path.join(sys.binaries_path, self.exe_name) + + return self.executable + + @property + def env(self): + if ispy3: + env = os.environ.copy() + else: + # We use this inefficient method of copying the environment variables + # because of non ascii env vars on windows. See https://bugs.launchpad.net/bugs/811191 + env = {} + for key in os.environ: + try: + val = os.environ[key] + if isinstance(val, unicode_type): + # On windows subprocess cannot handle unicode env vars + try: + val = val.encode(filesystem_encoding) + except ValueError: + val = val.encode('utf-8') + if isinstance(key, unicode_type): + key = key.encode('ascii') + env[key] = val + except: + pass + env[native_string_type('CALIBRE_WORKER')] = environ_item('1') + td = as_hex_unicode(msgpack_dumps(base_dir())) + env[native_string_type('CALIBRE_WORKER_TEMP_DIR')] = environ_item(td) + env.update(self._env) + return env + + @property + def is_alive(self): + return hasattr(self, 'child') and self.child.poll() is None + + @property + def returncode(self): + if not hasattr(self, 'child'): + return None + self.child.poll() + return self.child.returncode + + @property + def pid(self): + if not hasattr(self, 'child'): + return None + return getattr(self.child, 'pid', None) + + def close_log_file(self): + try: + self._file.close() + except: + pass + + def kill(self): + self.close_log_file() + try: + if self.is_alive: + if iswindows: + return self.child.kill() + try: + self.child.terminate() + st = time.time() + while self.is_alive and time.time()-st < 2: + time.sleep(0.2) + finally: + if self.is_alive: + self.child.kill() + except: + pass + + def __init__(self, env, gui=False, job_name=None): + self._env = {} + self.gui = gui + self.job_name = job_name + if ispy3: + self._env = env.copy() + else: + # Windows cannot handle unicode env vars + for k, v in iteritems(env): + try: + if isinstance(k, unicode_type): + k = k.encode('ascii') + if isinstance(v, unicode_type): + try: + v = v.encode(filesystem_encoding) + except: + v = v.encode('utf-8') + self._env[k] = v + except: + pass + + def __call__(self, redirect_output=True, cwd=None, priority=None): + ''' + If redirect_output is True, output from the child is redirected + to a file on disk and this method returns the path to that file. + ''' + exe = self.gui_executable if self.gui else self.executable + env = self.env + try: + origwd = cwd or os.path.abspath(getcwd()) + except EnvironmentError: + # cwd no longer exists + origwd = cwd or os.path.expanduser('~') + env[native_string_type('ORIGWD')] = environ_item(as_hex_unicode(msgpack_dumps(origwd))) + _cwd = cwd + if priority is None: + priority = prefs['worker_process_priority'] + cmd = [exe] if isinstance(exe, string_or_bytes) else exe + args = { + 'env' : env, + 'cwd' : _cwd, + } + if iswindows: + priority = { + 'high' : win32process.HIGH_PRIORITY_CLASS, + 'normal' : win32process.NORMAL_PRIORITY_CLASS, + 'low' : win32process.IDLE_PRIORITY_CLASS}[priority] + args['creationflags'] = win32process.CREATE_NO_WINDOW|priority + else: + niceness = { + 'normal' : 0, + 'low' : 10, + 'high' : 20, + }[priority] + args['preexec_fn'] = partial(renice, niceness) + ret = None + if redirect_output: + self._file = PersistentTemporaryFile('_worker_redirect.log') + args['stdout'] = self._file._fd + args['stderr'] = subprocess.STDOUT + if iswindows: + args['stdin'] = subprocess.PIPE + ret = self._file.name + + if iswindows and 'stdin' not in args: + # On windows when using the pythonw interpreter, + # stdout, stderr and stdin may not be valid + args['stdin'] = subprocess.PIPE + args['stdout'] = windows_null_file + args['stderr'] = subprocess.STDOUT + + if not iswindows: + # Close inherited file descriptors in worker + # On windows, this is done in the worker process + # itself + args['close_fds'] = True + + self.child = subprocess.Popen(cmd, **args) + if 'stdin' in args: + self.child.stdin.close() + + self.log_path = ret + return ret diff --git a/ebook_converter/utils/ipc/simple_worker.py b/ebook_converter/utils/ipc/simple_worker.py new file mode 100644 index 0000000..32b173c --- /dev/null +++ b/ebook_converter/utils/ipc/simple_worker.py @@ -0,0 +1,348 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2012, Kovid Goyal <kovid@kovidgoyal.net>' +__docformat__ = 'restructuredtext en' + +import os, time, traceback, importlib +from multiprocessing.connection import Client +from threading import Thread +from contextlib import closing + +from calibre.constants import iswindows +from calibre.utils.ipc import eintr_retry_call +from calibre.utils.ipc.launch import Worker +from calibre.utils.serialize import msgpack_loads, msgpack_dumps +from calibre.utils.monotonic import monotonic +from polyglot.builtins import unicode_type, string_or_bytes, environ_item +from polyglot.binary import as_hex_unicode, from_hex_bytes + + +class WorkerError(Exception): + + def __init__(self, msg, orig_tb='', log_path=None): + Exception.__init__(self, msg) + self.orig_tb = orig_tb + self.log_path = log_path + + +class ConnectedWorker(Thread): + + def __init__(self, listener, args): + Thread.__init__(self) + self.daemon = True + + self.listener = listener + self.args = args + self.accepted = False + self.tb = None + self.res = None + + def run(self): + conn = None + try: + conn = eintr_retry_call(self.listener.accept) + except BaseException: + self.tb = traceback.format_exc() + return + self.accepted = True + with closing(conn): + try: + eintr_retry_call(conn.send, self.args) + self.res = eintr_retry_call(conn.recv) + except BaseException: + self.tb = traceback.format_exc() + + +class OffloadWorker(object): + + def __init__(self, listener, worker): + self.listener = listener + self.worker = worker + self.conn = None + self.kill_thread = t = Thread(target=self.worker.kill) + t.daemon = True + + def __call__(self, module, func, *args, **kwargs): + if self.conn is None: + self.conn = eintr_retry_call(self.listener.accept) + eintr_retry_call(self.conn.send, (module, func, args, kwargs)) + return eintr_retry_call(self.conn.recv) + + def shutdown(self): + try: + eintr_retry_call(self.conn.send, None) + except IOError: + pass + except: + import traceback + traceback.print_exc() + finally: + self.conn = None + try: + os.remove(self.worker.log_path) + except: + pass + self.kill_thread.start() + + def is_alive(self): + return self.worker.is_alive or self.kill_thread.is_alive() + + +def communicate(ans, worker, listener, args, timeout=300, heartbeat=None, + abort=None): + cw = ConnectedWorker(listener, args) + cw.start() + st = monotonic() + check_heartbeat = callable(heartbeat) + + while worker.is_alive and cw.is_alive(): + cw.join(0.01) + delta = monotonic() - st + if not cw.accepted and delta > min(10, timeout): + break + hung = not heartbeat() if check_heartbeat else delta > timeout + if hung: + raise WorkerError('Worker appears to have hung') + if abort is not None and abort.is_set(): + # The worker process will be killed by fork_job, after we return + return + + if not cw.accepted: + if not cw.tb: + raise WorkerError('Failed to connect to worker process') + raise WorkerError('Failed to connect to worker process', cw.tb) + + if cw.tb: + raise WorkerError('Failed to communicate with worker process', cw.tb) + if cw.res is None: + raise WorkerError('Something strange happened. The worker process was aborted without an exception.') + if cw.res.get('tb', None): + raise WorkerError('Worker failed', cw.res['tb']) + ans['result'] = cw.res['result'] + + +def create_worker(env, priority='normal', cwd=None, func='main'): + from calibre.utils.ipc.server import create_listener + auth_key = os.urandom(32) + address, listener = create_listener(auth_key) + + env = dict(env) + env.update({ + 'CALIBRE_WORKER_ADDRESS': environ_item(as_hex_unicode(msgpack_dumps(address))), + 'CALIBRE_WORKER_KEY': environ_item(as_hex_unicode(auth_key)), + 'CALIBRE_SIMPLE_WORKER': environ_item('calibre.utils.ipc.simple_worker:%s' % func), + }) + + w = Worker(env) + w(cwd=cwd, priority=priority) + return listener, w + + +def start_pipe_worker(command, env=None, priority='normal', **process_args): + import subprocess + from functools import partial + w = Worker(env or {}) + args = {'stdout':subprocess.PIPE, 'stdin':subprocess.PIPE, 'env':w.env} + args.update(process_args) + if iswindows: + import win32process + priority = { + 'high' : win32process.HIGH_PRIORITY_CLASS, + 'normal' : win32process.NORMAL_PRIORITY_CLASS, + 'low' : win32process.IDLE_PRIORITY_CLASS}[priority] + args['creationflags'] = win32process.CREATE_NO_WINDOW|priority + else: + def renice(niceness): + try: + os.nice(niceness) + except: + pass + niceness = {'normal' : 0, 'low' : 10, 'high' : 20}[priority] + args['preexec_fn'] = partial(renice, niceness) + args['close_fds'] = True + + exe = w.executable + cmd = [exe] if isinstance(exe, string_or_bytes) else exe + p = subprocess.Popen(cmd + ['--pipe-worker', command], **args) + return p + + +def two_part_fork_job(env=None, priority='normal', cwd=None): + env = env or {} + listener, w = create_worker(env, priority, cwd) + + def run_job( + mod_name, func_name, args=(), kwargs=None, timeout=300, # seconds + no_output=False, heartbeat=None, abort=None, module_is_source_code=False + ): + ans = {'result':None, 'stdout_stderr':None} + kwargs = kwargs or {} + try: + communicate(ans, w, listener, (mod_name, func_name, args, kwargs, + module_is_source_code), timeout=timeout, heartbeat=heartbeat, + abort=abort) + except WorkerError as e: + if not no_output: + e.log_path = w.log_path + raise + finally: + t = Thread(target=w.kill) + t.daemon=True + t.start() + if no_output: + try: + os.remove(w.log_path) + except: + pass + if not no_output: + ans['stdout_stderr'] = w.log_path + return ans + run_job.worker = w + + return run_job + + +def fork_job(mod_name, func_name, args=(), kwargs=None, timeout=300, # seconds + cwd=None, priority='normal', env={}, no_output=False, heartbeat=None, + abort=None, module_is_source_code=False): + ''' + Run a job in a worker process. A job is simply a function that will be + called with the supplied arguments, in the worker process. + The result of the function will be returned. + If an error occurs a WorkerError is raised. + + :param mod_name: Module to import in the worker process + + :param func_name: Function to call in the worker process from the imported + module + + :param args: Positional arguments to pass to the function + + :param kwargs: Keyword arguments to pass to the function + + :param timeout: The time in seconds to wait for the worker process to + complete. If it takes longer a WorkerError is raised and the process is + killed. + + :param cwd: The working directory for the worker process. I recommend + against using this, unless you are sure the path is pure ASCII. + + :param priority: The process priority for the worker process + + :param env: Extra environment variables to set for the worker process + + :param no_output: If True, the stdout and stderr of the worker process are + discarded + + :param heartbeat: If not None, it is used to check if the worker has hung, + instead of a simple timeout. It must be a callable that takes no + arguments and returns True or False. The worker will be assumed to have + hung if this function returns False. At that point, the process will be + killed and a WorkerError will be raised. + + :param abort: If not None, it must be an Event. As soon as abort.is_set() + returns True, the worker process is killed. No error is raised. + + :param module_is_source_code: If True, the ``mod`` is treated as python + source rather than a module name to import. The source is executed as a + module. Useful if you want to use fork_job from within a script to run some + dynamically generated python. + + :return: A dictionary with the keys result and stdout_stderr. result is the + return value of the function (it must be picklable). stdout_stderr is the + path to a file that contains the stdout and stderr of the worker process. + If you set no_output=True, then this will not be present. + ''' + return two_part_fork_job(env, priority, cwd)( + mod_name, func_name, args=args, kwargs=kwargs, timeout=timeout, + no_output=no_output, heartbeat=heartbeat, abort=abort, + module_is_source_code=module_is_source_code + ) + + +def offload_worker(env={}, priority='normal', cwd=None): + listener, w = create_worker(env=env, priority=priority, cwd=cwd, func='offload') + return OffloadWorker(listener, w) + + +def compile_code(src): + import re, io + if not isinstance(src, unicode_type): + match = re.search(br'coding[:=]\s*([-\w.]+)', src[:200]) + enc = match.group(1).decode('utf-8') if match else 'utf-8' + src = src.decode(enc) + # Python complains if there is a coding declaration in a unicode string + src = re.sub(r'^#.*coding\s*[:=]\s*([-\w.]+)', '#', src, flags=re.MULTILINE) + # Translate newlines to \n + src = io.StringIO(src, newline=None).getvalue() + + namespace = { + 'time':time, 're':re, 'os':os, 'io':io, + } + exec(src, namespace) + return namespace + + +def main(): + # The entry point for the simple worker process + address = msgpack_loads(from_hex_bytes(os.environ['CALIBRE_WORKER_ADDRESS'])) + key = from_hex_bytes(os.environ['CALIBRE_WORKER_KEY']) + with closing(Client(address, authkey=key)) as conn: + args = eintr_retry_call(conn.recv) + try: + mod, func, args, kwargs, module_is_source_code = args + if module_is_source_code: + importlib.import_module('calibre.customize.ui') # Load plugins + mod = compile_code(mod) + func = mod[func] + else: + try: + mod = importlib.import_module(mod) + except ImportError: + importlib.import_module('calibre.customize.ui') # Load plugins + mod = importlib.import_module(mod) + func = getattr(mod, func) + res = {'result':func(*args, **kwargs)} + except: + res = {'tb': traceback.format_exc()} + + try: + conn.send(res) + except: + # Maybe EINTR + conn.send(res) + + +def offload(): + # The entry point for the offload worker process + address = msgpack_loads(from_hex_bytes(os.environ['CALIBRE_WORKER_ADDRESS'])) + key = from_hex_bytes(os.environ['CALIBRE_WORKER_KEY']) + func_cache = {} + with closing(Client(address, authkey=key)) as conn: + while True: + args = eintr_retry_call(conn.recv) + if args is None: + break + res = {'result':None, 'tb':None} + try: + mod, func, args, kwargs = args + if mod is None: + eintr_retry_call(conn.send, res) + continue + f = func_cache.get((mod, func), None) + if f is None: + try: + m = importlib.import_module(mod) + except ImportError: + importlib.import_module('calibre.customize.ui') # Load plugins + m = importlib.import_module(mod) + func_cache[(mod, func)] = f = getattr(m, func) + res['result'] = f(*args, **kwargs) + except: + import traceback + res['tb'] = traceback.format_exc() + + eintr_retry_call(conn.send, res) diff --git a/ebook_converter/utils/iso8601.py b/ebook_converter/utils/iso8601.py new file mode 100644 index 0000000..eb4ffec --- /dev/null +++ b/ebook_converter/utils/iso8601.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +# License: GPLv3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net> + +from __future__ import absolute_import, division, print_function, unicode_literals +from datetime import datetime + +from dateutil.tz import tzlocal, tzutc, tzoffset + +from calibre.constants import plugins +speedup, err = plugins['speedup'] +if not speedup: + raise RuntimeError(err) + + +class SafeLocalTimeZone(tzlocal): + + def _isdst(self, dt): + # This method in tzlocal raises ValueError if dt is out of range (in + # older versions of dateutil) + # In such cases, just assume that dt is not DST. + try: + return super(SafeLocalTimeZone, self)._isdst(dt) + except Exception: + pass + return False + + def _naive_is_dst(self, dt): + # This method in tzlocal raises ValueError if dt is out of range (in + # newer versions of dateutil) + # In such cases, just assume that dt is not DST. + try: + return super(SafeLocalTimeZone, self)._naive_is_dst(dt) + except Exception: + pass + return False + + +utc_tz = tzutc() +local_tz = SafeLocalTimeZone() +del tzutc, tzlocal +UNDEFINED_DATE = datetime(101,1,1, tzinfo=utc_tz) + + +def parse_iso8601(date_string, assume_utc=False, as_utc=True): + if not date_string: + return UNDEFINED_DATE + dt, aware, tzseconds = speedup.parse_iso8601(date_string) + tz = utc_tz if assume_utc else local_tz + if aware: # timezone was specified + if tzseconds == 0: + tz = utc_tz + else: + sign = '-' if tzseconds < 0 else '+' + description = "%s%02d:%02d" % (sign, abs(tzseconds) // 3600, (abs(tzseconds) % 3600) // 60) + tz = tzoffset(description, tzseconds) + dt = dt.replace(tzinfo=tz) + if as_utc and tz is utc_tz: + return dt + return dt.astimezone(utc_tz if as_utc else local_tz) + + +if __name__ == '__main__': + import sys + print(parse_iso8601(sys.argv[-1])) diff --git a/ebook_converter/utils/localization.py b/ebook_converter/utils/localization.py new file mode 100644 index 0000000..6228e4f --- /dev/null +++ b/ebook_converter/utils/localization.py @@ -0,0 +1,548 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>' +__docformat__ = 'restructuredtext en' + +import os, locale, re, io, sys +from gettext import GNUTranslations, NullTranslations + +from polyglot.builtins import is_py3, iteritems, unicode_type + +_available_translations = None + + +def available_translations(): + global _available_translations + if _available_translations is None: + stats = P('localization/stats.calibre_msgpack', allow_user_override=False) + if os.path.exists(stats): + from calibre.utils.serialize import msgpack_loads + with open(stats, 'rb') as f: + stats = msgpack_loads(f.read()) + else: + stats = {} + _available_translations = [x for x in stats if stats[x] > 0.1] + return _available_translations + + +def get_system_locale(): + from calibre.constants import iswindows, isosx, plugins + lang = None + if iswindows: + try: + from calibre.constants import get_windows_user_locale_name + lang = get_windows_user_locale_name() + lang = lang.strip() + if not lang: + lang = None + except: + pass # Windows XP does not have the GetUserDefaultLocaleName fn + elif isosx: + try: + lang = plugins['usbobserver'][0].user_locale() or None + except: + # Fallback to environment vars if something bad happened + import traceback + traceback.print_exc() + if lang is None: + try: + envvars = ['LANGUAGE', 'LC_ALL', 'LC_CTYPE', 'LC_MESSAGES', 'LANG'] + lang = locale.getdefaultlocale(envvars)[0] + + # lang is None in two cases: either the environment variable is not + # set or it's "C". Stop looking for a language in the latter case. + if lang is None: + for var in envvars: + if os.environ.get(var) == 'C': + lang = 'en_US' + break + except: + pass # This happens on Ubuntu apparently + if lang is None and 'LANG' in os.environ: # Needed for OS X + try: + lang = os.environ['LANG'] + except: + pass + if lang: + lang = lang.replace('-', '_') + lang = '_'.join(lang.split('_')[:2]) + return lang + + +def sanitize_lang(lang): + if lang: + match = re.match('[a-z]{2,3}(_[A-Z]{2}){0,1}', lang) + if match: + lang = match.group() + if lang == 'zh': + lang = 'zh_CN' + if not lang: + lang = 'en' + return lang + + +def get_lang(): + 'Try to figure out what language to display the interface in' + from calibre.utils.config_base import prefs + lang = prefs['language'] + lang = os.environ.get('CALIBRE_OVERRIDE_LANG', lang) + if lang: + return lang + try: + lang = get_system_locale() + except: + import traceback + traceback.print_exc() + lang = None + return sanitize_lang(lang) + + +def is_rtl(): + return get_lang()[:2].lower() in {'he', 'ar'} + + +def get_lc_messages_path(lang): + hlang = None + if zf_exists(): + if lang in available_translations(): + hlang = lang + else: + xlang = lang.split('_')[0].lower() + if xlang in available_translations(): + hlang = xlang + return hlang + + +def zf_exists(): + return os.path.exists(P('localization/locales.zip', + allow_user_override=False)) + + +_lang_trans = None + + +def get_all_translators(): + from zipfile import ZipFile + with ZipFile(P('localization/locales.zip', allow_user_override=False), 'r') as zf: + for lang in available_translations(): + mpath = get_lc_messages_path(lang) + if mpath is not None: + buf = io.BytesIO(zf.read(mpath + '/messages.mo')) + yield lang, GNUTranslations(buf) + + +def get_single_translator(mpath, which='messages'): + from zipfile import ZipFile + with ZipFile(P('localization/locales.zip', allow_user_override=False), 'r') as zf: + path = '{}/{}.mo'.format(mpath, which) + data = zf.read(path) + buf = io.BytesIO(data) + try: + return GNUTranslations(buf) + except Exception as e: + import traceback + traceback.print_exc() + import hashlib + sig = hashlib.sha1(data).hexdigest() + raise ValueError('Failed to load translations for: {} (size: {} and signature: {}) with error: {}'.format( + path, len(data), sig, e)) + + +def get_iso639_translator(lang): + lang = sanitize_lang(lang) + mpath = get_lc_messages_path(lang) if lang else None + return get_single_translator(mpath, 'iso639') if mpath else None + + +def get_translator(bcp_47_code): + parts = bcp_47_code.replace('-', '_').split('_')[:2] + parts[0] = lang_as_iso639_1(parts[0].lower()) or 'en' + if len(parts) > 1: + parts[1] = parts[1].upper() + lang = '_'.join(parts) + lang = {'pt':'pt_BR', 'zh':'zh_CN'}.get(lang, lang) + available = available_translations() + found = True + if lang == 'en' or lang.startswith('en_'): + return found, lang, NullTranslations() + if lang not in available: + lang = {'pt':'pt_BR', 'zh':'zh_CN'}.get(parts[0], parts[0]) + if lang not in available: + lang = get_lang() + if lang not in available: + lang = 'en' + found = False + if lang == 'en': + return True, lang, NullTranslations() + return found, lang, get_single_translator(lang) + + +lcdata = { + 'abday': ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'), + 'abmon': ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'), + 'd_fmt': '%m/%d/%Y', + 'd_t_fmt': '%a %d %b %Y %r %Z', + 'day': ('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'), + 'mon': ('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'), + 'noexpr': '^[nN].*', + 'radixchar': '.', + 't_fmt': '%r', + 't_fmt_ampm': '%I:%M:%S %p', + 'thousep': ',', + 'yesexpr': '^[yY].*' +} + + +def load_po(path): + from calibre.translations.msgfmt import make + buf = io.BytesIO() + try: + make(path, buf) + except Exception: + print(('Failed to compile translations file: %s, ignoring') % path) + buf = None + else: + buf = io.BytesIO(buf.getvalue()) + return buf + + +def set_translators(): + global _lang_trans, lcdata + # To test different translations invoke as + # CALIBRE_OVERRIDE_LANG=de_DE.utf8 program + lang = get_lang() + t = buf = iso639 = None + + if 'CALIBRE_TEST_TRANSLATION' in os.environ: + buf = load_po(os.path.expanduser(os.environ['CALIBRE_TEST_TRANSLATION'])) + + if lang: + mpath = get_lc_messages_path(lang) + if buf is None and mpath and os.access(mpath + '.po', os.R_OK): + buf = load_po(mpath + '.po') + + if mpath is not None: + from zipfile import ZipFile + with ZipFile(P('localization/locales.zip', + allow_user_override=False), 'r') as zf: + if buf is None: + buf = io.BytesIO(zf.read(mpath + '/messages.mo')) + if mpath == 'nds': + mpath = 'de' + isof = mpath + '/iso639.mo' + try: + iso639 = io.BytesIO(zf.read(isof)) + except: + pass # No iso639 translations for this lang + if buf is not None: + from calibre.utils.serialize import msgpack_loads + try: + lcdata = msgpack_loads(zf.read(mpath + '/lcdata.calibre_msgpack')) + except: + pass # No lcdata + + if buf is not None: + t = GNUTranslations(buf) + if iso639 is not None: + iso639 = _lang_trans = GNUTranslations(iso639) + t.add_fallback(iso639) + + if t is None: + t = NullTranslations() + + try: + set_translators.lang = t.info().get('language') + except Exception: + pass + if is_py3: + t.install(names=('ngettext',)) + else: + t.install(unicode=True, names=('ngettext',)) + # Now that we have installed a translator, we have to retranslate the help + # for the global prefs object as it was instantiated in get_lang(), before + # the translator was installed. + from calibre.utils.config_base import prefs + prefs.retranslate_help() + + +set_translators.lang = None + + +_iso639 = None +_extra_lang_codes = { + 'pt_BR' : _('Brazilian Portuguese'), + 'en_GB' : _('English (UK)'), + 'zh_CN' : _('Simplified Chinese'), + 'zh_TW' : _('Traditional Chinese'), + 'en' : _('English'), + 'en_US' : _('English (United States)'), + 'en_AR' : _('English (Argentina)'), + 'en_AU' : _('English (Australia)'), + 'en_JP' : _('English (Japan)'), + 'en_DE' : _('English (Germany)'), + 'en_BG' : _('English (Bulgaria)'), + 'en_EG' : _('English (Egypt)'), + 'en_NZ' : _('English (New Zealand)'), + 'en_CA' : _('English (Canada)'), + 'en_GR' : _('English (Greece)'), + 'en_IN' : _('English (India)'), + 'en_NP' : _('English (Nepal)'), + 'en_TH' : _('English (Thailand)'), + 'en_TR' : _('English (Turkey)'), + 'en_CY' : _('English (Cyprus)'), + 'en_CZ' : _('English (Czech Republic)'), + 'en_PH' : _('English (Philippines)'), + 'en_PK' : _('English (Pakistan)'), + 'en_PL' : _('English (Poland)'), + 'en_HR' : _('English (Croatia)'), + 'en_HU' : _('English (Hungary)'), + 'en_ID' : _('English (Indonesia)'), + 'en_IL' : _('English (Israel)'), + 'en_RU' : _('English (Russia)'), + 'en_SG' : _('English (Singapore)'), + 'en_YE' : _('English (Yemen)'), + 'en_IE' : _('English (Ireland)'), + 'en_CN' : _('English (China)'), + 'en_TW' : _('English (Taiwan)'), + 'en_ZA' : _('English (South Africa)'), + 'es_PY' : _('Spanish (Paraguay)'), + 'es_UY' : _('Spanish (Uruguay)'), + 'es_AR' : _('Spanish (Argentina)'), + 'es_CR' : _('Spanish (Costa Rica)'), + 'es_MX' : _('Spanish (Mexico)'), + 'es_CU' : _('Spanish (Cuba)'), + 'es_CL' : _('Spanish (Chile)'), + 'es_EC' : _('Spanish (Ecuador)'), + 'es_HN' : _('Spanish (Honduras)'), + 'es_VE' : _('Spanish (Venezuela)'), + 'es_BO' : _('Spanish (Bolivia)'), + 'es_NI' : _('Spanish (Nicaragua)'), + 'es_CO' : _('Spanish (Colombia)'), + 'de_AT' : _('German (AT)'), + 'fr_BE' : _('French (BE)'), + 'nl' : _('Dutch (NL)'), + 'nl_BE' : _('Dutch (BE)'), + 'und' : _('Unknown') + } + +if False: + # Extra strings needed for Qt + + # NOTE: Ante Meridian (i.e. like 10:00 AM) + _('AM') + # NOTE: Post Meridian (i.e. like 10:00 PM) + _('PM') + # NOTE: Ante Meridian (i.e. like 10:00 am) + _('am') + # NOTE: Post Meridian (i.e. like 10:00 pm) + _('pm') + _('&Copy') + _('Select All') + _('Copy Link') + _('&Select All') + _('Copy &Link Location') + _('&Undo') + _('&Redo') + _('Cu&t') + _('&Paste') + _('Paste and Match Style') + _('Directions') + _('Left to Right') + _('Right to Left') + _('Fonts') + _('&Step up') + _('Step &down') + _('Close without Saving') + _('Close Tab') + +_lcase_map = {} +for k in _extra_lang_codes: + _lcase_map[k.lower()] = k + + +def _load_iso639(): + global _iso639 + if _iso639 is None: + ip = P('localization/iso639.calibre_msgpack', allow_user_override=False, data=True) + from calibre.utils.serialize import msgpack_loads + _iso639 = msgpack_loads(ip) + if 'by_3' not in _iso639: + _iso639['by_3'] = _iso639['by_3t'] + return _iso639 + + +def get_iso_language(lang_trans, lang): + iso639 = _load_iso639() + ans = lang + lang = lang.split('_')[0].lower() + if len(lang) == 2: + ans = iso639['by_2'].get(lang, ans) + elif len(lang) == 3: + if lang in iso639['by_3']: + ans = iso639['by_3'][lang] + return lang_trans(ans) + + +def get_language(lang): + translate = _ + lang = _lcase_map.get(lang, lang) + if lang in _extra_lang_codes: + # The translator was not active when _extra_lang_codes was defined, so + # re-translate + return translate(_extra_lang_codes[lang]) + attr = 'gettext' if sys.version_info.major > 2 else 'ugettext' + return get_iso_language(getattr(_lang_trans, attr, translate), lang) + + +def calibre_langcode_to_name(lc, localize=True): + iso639 = _load_iso639() + translate = _ if localize else lambda x: x + try: + return translate(iso639['by_3'][lc]) + except: + pass + return lc + + +def canonicalize_lang(raw): + if not raw: + return None + if not isinstance(raw, unicode_type): + raw = raw.decode('utf-8', 'ignore') + raw = raw.lower().strip() + if not raw: + return None + raw = raw.replace('_', '-').partition('-')[0].strip() + if not raw: + return None + iso639 = _load_iso639() + m2to3 = iso639['2to3'] + + if len(raw) == 2: + ans = m2to3.get(raw, None) + if ans is not None: + return ans + elif len(raw) == 3: + if raw in iso639['by_3']: + return raw + + return iso639['name_map'].get(raw, None) + + +_lang_map = None + + +def lang_map(): + ' Return mapping of ISO 639 3 letter codes to localized language names ' + iso639 = _load_iso639() + translate = _ + global _lang_map + if _lang_map is None: + _lang_map = {k:translate(v) for k, v in iteritems(iso639['by_3'])} + return _lang_map + + +def lang_map_for_ui(): + ans = getattr(lang_map_for_ui, 'ans', None) + if ans is None: + ans = lang_map().copy() + for x in ('zxx', 'mis', 'mul'): + ans.pop(x, None) + lang_map_for_ui.ans = ans + return ans + + +def langnames_to_langcodes(names): + ''' + Given a list of localized language names return a mapping of the names to 3 + letter ISO 639 language codes. If a name is not recognized, it is mapped to + None. + ''' + iso639 = _load_iso639() + translate = _ + ans = {} + names = set(names) + for k, v in iteritems(iso639['by_3']): + tv = translate(v) + if tv in names: + names.remove(tv) + ans[tv] = k + if not names: + break + for x in names: + ans[x] = None + + return ans + + +def lang_as_iso639_1(name_or_code): + code = canonicalize_lang(name_or_code) + if code is not None: + iso639 = _load_iso639() + return iso639['3to2'].get(code, None) + + +_udc = None + + +def get_udc(): + global _udc + if _udc is None: + from calibre.ebooks.unihandecode import Unihandecoder + _udc = Unihandecoder(lang=get_lang()) + return _udc + + +def user_manual_stats(): + stats = getattr(user_manual_stats, 'stats', None) + if stats is None: + import json + try: + stats = json.loads(P('user-manual-translation-stats.json', allow_user_override=False, data=True)) + except EnvironmentError: + stats = {} + user_manual_stats.stats = stats + return stats + + +def localize_user_manual_link(url): + lc = lang_as_iso639_1(get_lang()) + if lc == 'en': + return url + stats = user_manual_stats() + if stats.get(lc, 0) < 0.3: + return url + from polyglot.urllib import urlparse, urlunparse + parts = urlparse(url) + path = re.sub(r'/generated/[a-z]+/', '/generated/%s/' % lc, parts.path or '') + path = '/%s%s' % (lc, path) + parts = list(parts) + parts[2] = path + return urlunparse(parts) + + +def website_languages(): + stats = getattr(website_languages, 'stats', None) + if stats is None: + try: + stats = frozenset(P('localization/website-languages.txt', allow_user_override=False, data=True).split()) + except EnvironmentError: + stats = frozenset() + website_languages.stats = stats + return stats + + +def localize_website_link(url): + lc = lang_as_iso639_1(get_lang()) + langs = website_languages() + if lc == 'en' or lc not in langs: + return url + from polyglot.urllib import urlparse, urlunparse + parts = urlparse(url) + path = '/{}{}'.format(lc, parts.path) + parts = list(parts) + parts[2] = path + return urlunparse(parts) diff --git a/ebook_converter/utils/localunzip.py b/ebook_converter/utils/localunzip.py new file mode 100644 index 0000000..b0d0ab5 --- /dev/null +++ b/ebook_converter/utils/localunzip.py @@ -0,0 +1,340 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:fdm=marker:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>' +__docformat__ = 'restructuredtext en' + +''' +Try to read invalid zip files with missing or damaged central directories. +These are apparently produced in large numbers by the fruitcakes over at B&N. + +Tries to only use the local headers to extract data from the damaged zip file. +''' + +import os, sys, zlib, shutil +from struct import calcsize, unpack, pack +from collections import namedtuple, OrderedDict +from tempfile import SpooledTemporaryFile + +from polyglot.builtins import itervalues, getcwd + +HEADER_SIG = 0x04034b50 +HEADER_BYTE_SIG = pack(b'<L', HEADER_SIG) +local_header_fmt = b'<L5HL2L2H' +local_header_sz = calcsize(local_header_fmt) +ZIP_STORED, ZIP_DEFLATED = 0, 8 +DATA_DESCRIPTOR_SIG = pack(b'<L', 0x08074b50) + +LocalHeader = namedtuple('LocalHeader', + 'signature min_version flags compression_method mod_time mod_date ' + 'crc32 compressed_size uncompressed_size filename_length extra_length ' + 'filename extra') + + +if hasattr(sys, 'getwindowsversion'): + windows_reserved_filenames = ( + 'CON', 'PRN', 'AUX', 'CLOCK$', 'NUL' 'COM0', 'COM1', 'COM2', 'COM3', + 'COM4', 'COM5', 'COM6', 'COM7', 'COM8', 'COM9' 'LPT0', 'LPT1', 'LPT2', + 'LPT3', 'LPT4', 'LPT5', 'LPT6', 'LPT7', 'LPT8', 'LPT9') + + def is_reserved_filename(x): + base = x.partition('.')[0].upper() + return base in windows_reserved_filenames +else: + def is_reserved_filename(x): + return False + + +def decode_arcname(name): + if isinstance(name, bytes): + from calibre.ebooks.chardet import detect + try: + name = name.decode('utf-8') + except: + res = detect(name) + encoding = res['encoding'] + try: + name = name.decode(encoding) + except: + name = name.decode('utf-8', 'replace') + return name + + +def find_local_header(f): + pos = f.tell() + raw = f.read(50*1024) + try: + f.seek(pos + raw.index(HEADER_BYTE_SIG)) + except ValueError: + f.seek(pos) + return + raw = f.read(local_header_sz) + if len(raw) != local_header_sz: + f.seek(pos) + return + header = LocalHeader(*(unpack(local_header_fmt, raw) + (None, None))) + if header.signature == HEADER_SIG: + return header + f.seek(pos) + + +def find_data_descriptor(f): + pos = f.tell() + DD = namedtuple('DataDescriptor', 'crc32 compressed_size uncompressed_size') + raw = b'a'*16 + try: + while len(raw) >= 16: + raw = f.read(50*1024) + idx = raw.find(DATA_DESCRIPTOR_SIG) + if idx != -1: + f.seek(f.tell() - len(raw) + idx + len(DATA_DESCRIPTOR_SIG)) + return DD(*unpack(b'<LLL', f.read(12))) + # Rewind to handle the case of the signature being cut off + # by the 50K boundary + f.seek(f.tell()-len(DATA_DESCRIPTOR_SIG)) + + raise ValueError('Failed to find data descriptor signature. ' + 'Data descriptors without signatures are not ' + 'supported.') + finally: + f.seek(pos) + + +def read_local_file_header(f): + pos = f.tell() + raw = f.read(local_header_sz) + if len(raw) != local_header_sz: + f.seek(pos) + return + header = LocalHeader(*(unpack(local_header_fmt, raw) + (None, None))) + if header.signature != HEADER_SIG: + f.seek(pos) + header = find_local_header(f) + if header is None: + return + if header.min_version > 20: + raise ValueError('This ZIP file uses unsupported features') + if header.flags & 0b1: + raise ValueError('This ZIP file is encrypted') + if header.flags & (1 << 13): + raise ValueError('This ZIP file uses masking, unsupported.') + if header.compression_method not in {ZIP_STORED, ZIP_DEFLATED}: + raise ValueError('This ZIP file uses an unsupported compression method') + has_data_descriptors = header.flags & (1 << 3) + fname = extra = None + if header.filename_length > 0: + fname = f.read(header.filename_length) + if len(fname) != header.filename_length: + return + try: + fname = fname.decode('ascii') + except UnicodeDecodeError: + if header.flags & (1 << 11): + try: + fname = fname.decode('utf-8') + except UnicodeDecodeError: + pass + fname = decode_arcname(fname).replace('\\', '/') + + if header.extra_length > 0: + extra = f.read(header.extra_length) + if len(extra) != header.extra_length: + return + if has_data_descriptors: + desc = find_data_descriptor(f) + header = header._replace(crc32=desc.crc32, + compressed_size=desc.compressed_size, + uncompressed_size=desc.uncompressed_size) + return LocalHeader(*( + header[:-2] + (fname, extra) + )) + + +def read_compressed_data(f, header): + cdata = f.read(header.compressed_size) + return cdata + + +def copy_stored_file(src, size, dest): + read = 0 + amt = min(size, 20*1024) + while read < size: + raw = src.read(min(size-read, amt)) + if not raw: + raise ValueError('Premature end of file') + dest.write(raw) + read += len(raw) + + +def copy_compressed_file(src, size, dest): + d = zlib.decompressobj(-15) + read = 0 + amt = min(size, 20*1024) + while read < size: + raw = src.read(min(size-read, amt)) + if not raw and read < size: + raise ValueError('Invalid ZIP file, local header is damaged') + read += len(raw) + dest.write(d.decompress(raw, 200*1024)) + count = 0 + while d.unconsumed_tail: + count += 1 + dest.write(d.decompress(d.unconsumed_tail, 200*1024)) + + if count > 100: + raise ValueError('This ZIP file contains a ZIP bomb in %s'% + os.path.basename(dest.name)) + + +def _extractall(f, path=None, file_info=None): + found = False + while True: + header = read_local_file_header(f) + if not header: + break + has_data_descriptors = header.flags & (1 << 3) + seekval = header.compressed_size + (16 if has_data_descriptors else 0) + found = True + # Sanitize path changing absolute to relative paths and removing .. and + # . + fname = header.filename.replace(os.sep, '/') + fname = os.path.splitdrive(fname)[1] + parts = [x for x in fname.split('/') if x not in {'', os.path.pardir, os.path.curdir}] + if not parts: + continue + if header.uncompressed_size == 0: + # Directory + f.seek(f.tell()+seekval) + if path is not None: + bdir = os.path.join(path, *parts) + if not os.path.exists(bdir): + os.makedirs(bdir) + continue + + # File + if file_info is not None: + file_info[header.filename] = (f.tell(), header) + if path is not None: + bdir = os.path.join(path, *(parts[:-1])) + if not os.path.exists(bdir): + os.makedirs(bdir) + dest = os.path.join(path, *parts) + try: + df = open(dest, 'wb') + except EnvironmentError: + if is_reserved_filename(os.path.basename(dest)): + raise ValueError('This ZIP file contains a file with a reserved filename' + ' that cannot be processed on Windows: {}'.format(os.path.basename(dest))) + raise + with df: + if header.compression_method == ZIP_STORED: + copy_stored_file(f, header.compressed_size, df) + else: + copy_compressed_file(f, header.compressed_size, df) + else: + f.seek(f.tell()+seekval) + + if not found: + raise ValueError('Not a ZIP file') + + +def extractall(path_or_stream, path=None): + f = path_or_stream + close_at_end = False + if not hasattr(f, 'read'): + f = open(f, 'rb') + close_at_end = True + if path is None: + path = getcwd() + pos = f.tell() + try: + _extractall(f, path) + finally: + f.seek(pos) + if close_at_end: + f.close() + + +class LocalZipFile(object): + + def __init__(self, stream): + self.file_info = OrderedDict() + _extractall(stream, file_info=self.file_info) + self.stream = stream + + def _get_file_info(self, name): + fi = self.file_info.get(name) + if fi is None: + raise ValueError('This ZIP container has no file named: %s'%name) + return fi + + def open(self, name, spool_size=5*1024*1024): + if isinstance(name, LocalHeader): + name = name.filename + offset, header = self._get_file_info(name) + self.stream.seek(offset) + dest = SpooledTemporaryFile(max_size=spool_size) + + if header.compression_method == ZIP_STORED: + copy_stored_file(self.stream, header.compressed_size, dest) + else: + copy_compressed_file(self.stream, header.compressed_size, dest) + dest.seek(0) + return dest + + def getinfo(self, name): + offset, header = self._get_file_info(name) + return header + + def read(self, name, spool_size=5*1024*1024): + with self.open(name, spool_size=spool_size) as f: + return f.read() + + def extractall(self, path=None): + self.stream.seek(0) + _extractall(self.stream, path=(path or getcwd())) + + def close(self): + pass + + def safe_replace(self, name, datastream, extra_replacements={}, + add_missing=False): + from calibre.utils.zipfile import ZipFile, ZipInfo + replacements = {name:datastream} + replacements.update(extra_replacements) + names = frozenset(list(replacements.keys())) + found = set() + + def rbytes(name): + r = replacements[name] + if not isinstance(r, bytes): + r = r.read() + return r + + with SpooledTemporaryFile(max_size=100*1024*1024) as temp: + ztemp = ZipFile(temp, 'w') + for offset, header in itervalues(self.file_info): + if header.filename in names: + zi = ZipInfo(header.filename) + zi.compress_type = header.compression_method + ztemp.writestr(zi, rbytes(header.filename)) + found.add(header.filename) + else: + ztemp.writestr(header.filename, self.read(header.filename, + spool_size=0)) + if add_missing: + for name in names - found: + ztemp.writestr(name, rbytes(name)) + ztemp.close() + zipstream = self.stream + temp.seek(0) + zipstream.seek(0) + zipstream.truncate() + shutil.copyfileobj(temp, zipstream) + zipstream.flush() + + +if __name__ == '__main__': + extractall(sys.argv[-1]) diff --git a/ebook_converter/utils/lock.py b/ebook_converter/utils/lock.py new file mode 100644 index 0000000..fb37f7c --- /dev/null +++ b/ebook_converter/utils/lock.py @@ -0,0 +1,205 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +# License: GPLv3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net> + +from __future__ import absolute_import, division, print_function, unicode_literals + +import atexit +import errno +import os +import stat +import tempfile +import time +from functools import partial + +from calibre.constants import ( + __appname__, fcntl, filesystem_encoding, islinux, isosx, iswindows, plugins, ispy3 +) +from calibre.utils.monotonic import monotonic + +speedup = plugins['speedup'][0] +if iswindows: + import msvcrt, win32file, pywintypes, winerror, win32api, win32event + from calibre.constants import get_windows_username + excl_file_mode = stat.S_IREAD | stat.S_IWRITE +else: + excl_file_mode = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH + + +def unix_open(path): + flags = os.O_RDWR | os.O_CREAT + has_cloexec = False + if hasattr(speedup, 'O_CLOEXEC'): + try: + fd = os.open(path, flags | speedup.O_CLOEXEC, excl_file_mode) + has_cloexec = True + except EnvironmentError as err: + # Kernel may not support O_CLOEXEC + if err.errno != errno.EINVAL: + raise + + if not has_cloexec: + fd = os.open(path, flags, excl_file_mode) + fcntl.fcntl(fd, fcntl.F_SETFD, fcntl.FD_CLOEXEC) + return os.fdopen(fd, 'r+b') + + +def unix_retry(err): + return err.errno in (errno.EACCES, errno.EAGAIN, errno.ENOLCK, errno.EINTR) + + +def windows_open(path): + if isinstance(path, bytes): + path = path.decode('mbcs') + try: + h = win32file.CreateFileW( + path, + win32file.GENERIC_READ | + win32file.GENERIC_WRITE, # Open for reading and writing + 0, # Open exclusive + None, # No security attributes, ensures handle is not inherited by children + win32file.OPEN_ALWAYS, # If file does not exist, create it + win32file.FILE_ATTRIBUTE_NORMAL, # Normal attributes + None, # No template file + ) + except pywintypes.error as err: + raise WindowsError(err[0], err[2], path) + fd = msvcrt.open_osfhandle(h.Detach(), 0) + return os.fdopen(fd, 'r+b') + + +def windows_retry(err): + return err.winerror in ( + winerror.ERROR_SHARING_VIOLATION, winerror.ERROR_LOCK_VIOLATION + ) + + +def retry_for_a_time(timeout, sleep_time, func, error_retry, *args): + limit = monotonic() + timeout + while True: + try: + return func(*args) + except EnvironmentError as err: + if not error_retry(err) or monotonic() > limit: + raise + time.sleep(sleep_time) + + +def lock_file(path, timeout=15, sleep_time=0.2): + if iswindows: + return retry_for_a_time( + timeout, sleep_time, windows_open, windows_retry, path + ) + f = unix_open(path) + retry_for_a_time( + timeout, sleep_time, fcntl.flock, unix_retry, + f.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB + ) + return f + + +class ExclusiveFile(object): + + def __init__(self, path, timeout=15, sleep_time=0.2): + if iswindows and isinstance(path, bytes): + path = path.decode(filesystem_encoding) + self.path = path + self.timeout = timeout + self.sleep_time = sleep_time + + def __enter__(self): + self.file = lock_file(self.path, self.timeout, self.sleep_time) + return self.file + + def __exit__(self, type, value, traceback): + self.file.close() + + +def _clean_lock_file(file_obj): + try: + os.remove(file_obj.name) + except EnvironmentError: + pass + try: + file_obj.close() + except EnvironmentError: + pass + + +if iswindows: + + def create_single_instance_mutex(name, per_user=True): + mutexname = '{}-singleinstance-{}-{}'.format( + __appname__, (get_windows_username() if per_user else ''), name + ) + mutex = win32event.CreateMutex(None, False, mutexname) + if not mutex: + return + err = win32api.GetLastError() + if err == winerror.ERROR_ALREADY_EXISTS: + # Close this handle other wise this handle will prevent the mutex + # from being deleted when the process that created it exits. + win32api.CloseHandle(mutex) + return + return partial(win32api.CloseHandle, mutex) + +elif islinux: + + def create_single_instance_mutex(name, per_user=True): + import socket + from calibre.utils.ipc import eintr_retry_call + name = '%s-singleinstance-%s-%s' % ( + __appname__, (os.geteuid() if per_user else ''), name + ) + name = name + address = '\0' + name.replace(' ', '_') + if not ispy3: + address = address.encode('utf-8') + sock = socket.socket(family=socket.AF_UNIX) + try: + eintr_retry_call(sock.bind, address) + except socket.error as err: + if getattr(err, 'errno', None) == errno.EADDRINUSE: + return + raise + fd = sock.fileno() + old_flags = fcntl.fcntl(fd, fcntl.F_GETFD) + fcntl.fcntl(fd, fcntl.F_SETFD, old_flags | fcntl.FD_CLOEXEC) + return sock.close + +else: + + def singleinstance_path(name, per_user=True): + name = '%s-singleinstance-%s-%s.lock' % ( + __appname__, (os.geteuid() if per_user else ''), name + ) + home = os.path.expanduser('~') + locs = ['/var/lock', home, tempfile.gettempdir()] + if isosx: + locs.insert(0, '/Library/Caches') + for loc in locs: + if os.access(loc, os.W_OK | os.R_OK | os.X_OK): + return os.path.join(loc, ('.' if loc is home else '') + name) + raise EnvironmentError( + 'Failed to find a suitable filesystem location for the lock file' + ) + + def create_single_instance_mutex(name, per_user=True): + from calibre.utils.ipc import eintr_retry_call + path = singleinstance_path(name, per_user) + f = lopen(path, 'w') + try: + eintr_retry_call(fcntl.lockf, f.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB) + return partial(_clean_lock_file, f) + except EnvironmentError as err: + if err.errno not in (errno.EAGAIN, errno.EACCES): + raise + + +def singleinstance(name): + ' Ensure that only a single process holding exists with the specified mutex key ' + release_mutex = create_single_instance_mutex(name) + if release_mutex is None: + return False + atexit.register(release_mutex) + return True diff --git a/ebook_converter/utils/logging.py b/ebook_converter/utils/logging.py new file mode 100644 index 0000000..1f8a5d7 --- /dev/null +++ b/ebook_converter/utils/logging.py @@ -0,0 +1,275 @@ +from __future__ import absolute_import, division, print_function, unicode_literals +__license__ = 'GPL 3' +__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>' +__docformat__ = 'restructuredtext en' + +'A simplified logging system' + +DEBUG = 0 +INFO = 1 +WARN = 2 +ERROR = 3 + +import sys, traceback, io +from functools import partial +from threading import Lock + +from calibre import isbytestring, force_unicode, as_unicode, prints +from polyglot.builtins import unicode_type, iteritems + + +class Stream(object): + + def __init__(self, stream=None): + if stream is None: + stream = io.BytesIO() + self.stream = getattr(stream, 'buffer', stream) + self._prints = partial(prints, safe_encode=True, file=stream) + + def flush(self): + self.stream.flush() + + def prints(self, level, *args, **kwargs): + self._prints(*args, **kwargs) + + +class ANSIStream(Stream): + + def __init__(self, stream=sys.stdout): + Stream.__init__(self, stream) + self.color = { + DEBUG: u'green', + INFO: None, + WARN: u'yellow', + ERROR: u'red', + } + + def prints(self, level, *args, **kwargs): + from calibre.utils.terminal import ColoredStream + with ColoredStream(self.stream, self.color[level]): + self._prints(*args, **kwargs) + + def flush(self): + self.stream.flush() + + +class FileStream(Stream): + + def __init__(self, stream=None): + Stream.__init__(self, stream) + + def prints(self, level, *args, **kwargs): + self._prints(*args, **kwargs) + + +class HTMLStream(Stream): + + color = { + DEBUG: b'<span style="color:green">', + INFO: b'<span>', + WARN: b'<span style="color:blue">', + ERROR: b'<span style="color:red">' + } + normal = b'</span>' + + def __init__(self, stream=sys.stdout): + Stream.__init__(self, stream) + + def prints(self, level, *args, **kwargs): + self.stream.write(self.color[level]) + kwargs['file'] = self.stream + self._prints(*args, **kwargs) + self.stream.write(self.normal) + + def flush(self): + self.stream.flush() + + +class UnicodeHTMLStream(HTMLStream): + + color = {k: v.decode('ascii') for k, v in iteritems(HTMLStream.color)} + normal = HTMLStream.normal.decode('ascii') + + def __init__(self): + self.clear() + + def flush(self): + pass + + def prints(self, level, *args, **kwargs): + col = self.color[level] + if col != self.last_col: + if self.data: + self.data.append(self.normal) + self.data.append(col) + self.last_col = col + + sep = kwargs.get(u'sep', u' ') + end = kwargs.get(u'end', u'\n') + + for arg in args: + if isbytestring(arg): + arg = force_unicode(arg) + elif not isinstance(arg, unicode_type): + arg = as_unicode(arg) + self.data.append(arg+sep) + self.plain_text.append(arg+sep) + self.data.append(end) + self.plain_text.append(end) + + def clear(self): + self.data = [] + self.plain_text = [] + self.last_col = self.color[INFO] + + @property + def html(self): + end = self.normal if self.data else u'' + return u''.join(self.data) + end + + def dump(self): + return [self.data, self.plain_text, self.last_col] + + def load(self, dump): + self.data, self.plain_text, self.last_col = dump + + def append_dump(self, dump): + d, p, lc = dump + self.data.extend(d) + self.plain_text.extend(p) + self.last_col = lc + + +class Log(object): + + DEBUG = DEBUG + INFO = INFO + WARN = WARN + ERROR = ERROR + + def __init__(self, level=INFO): + self.filter_level = level + default_output = ANSIStream() + self.outputs = [default_output] + + self.debug = partial(self.print_with_flush, DEBUG) + self.info = partial(self.print_with_flush, INFO) + self.warn = self.warning = partial(self.print_with_flush, WARN) + self.error = partial(self.print_with_flush, ERROR) + + def prints(self, level, *args, **kwargs): + if level < self.filter_level: + return + for output in self.outputs: + output.prints(level, *args, **kwargs) + + def print_with_flush(self, level, *args, **kwargs): + if level < self.filter_level: + return + for output in self.outputs: + output.prints(level, *args, **kwargs) + self.flush() + + def exception(self, *args, **kwargs): + limit = kwargs.pop('limit', None) + self.print_with_flush(ERROR, *args, **kwargs) + self.print_with_flush(DEBUG, traceback.format_exc(limit)) + + def __call__(self, *args, **kwargs): + self.info(*args, **kwargs) + + def __enter__(self): + self.orig_filter_level = self.filter_level + self.filter_level = self.ERROR + 100 + + def __exit__(self, *args): + self.filter_level = self.orig_filter_level + + def flush(self): + for o in self.outputs: + if hasattr(o, 'flush'): + o.flush() + + def close(self): + for o in self.outputs: + if hasattr(o, 'close'): + o.close() + + +class DevNull(Log): + + def __init__(self): + Log.__init__(self, level=Log.ERROR) + self.outputs = [] + + +class ThreadSafeLog(Log): + exception_traceback_level = Log.DEBUG + + def __init__(self, level=Log.INFO): + Log.__init__(self, level=level) + self._lock = Lock() + + def prints(self, *args, **kwargs): + with self._lock: + Log.prints(self, *args, **kwargs) + + def print_with_flush(self, *args, **kwargs): + with self._lock: + Log.print_with_flush(self, *args, **kwargs) + + def exception(self, *args, **kwargs): + limit = kwargs.pop('limit', None) + with self._lock: + Log.print_with_flush(self, ERROR, *args, **kwargs) + Log.print_with_flush(self, self.exception_traceback_level, traceback.format_exc(limit)) + + +class ThreadSafeWrapper(Log): + + def __init__(self, other_log): + Log.__init__(self, level=other_log.filter_level) + self.outputs = list(other_log.outputs) + self._lock = Lock() + + def prints(self, *args, **kwargs): + with self._lock: + Log.prints(self, *args, **kwargs) + + def print_with_flush(self, *args, **kwargs): + with self._lock: + Log.print_with_flush(self, *args, **kwargs) + + +class GUILog(ThreadSafeLog): + + ''' + Logs in HTML and plain text as unicode. Ideal for display in a GUI context. + ''' + + def __init__(self): + ThreadSafeLog.__init__(self, level=self.DEBUG) + self.outputs = [UnicodeHTMLStream()] + + def clear(self): + self.outputs[0].clear() + + @property + def html(self): + return self.outputs[0].html + + @property + def plain_text(self): + return u''.join(self.outputs[0].plain_text) + + def dump(self): + return self.outputs[0].dump() + + def load(self, dump): + return self.outputs[0].load(dump) + + def append_dump(self, dump): + return self.outputs[0].append_dump(dump) + + +default_log = Log() diff --git a/ebook_converter/utils/monotonic.py b/ebook_converter/utils/monotonic.py new file mode 100644 index 0000000..9d5840d --- /dev/null +++ b/ebook_converter/utils/monotonic.py @@ -0,0 +1,13 @@ +# vim:fileencoding=utf-8 +from __future__ import absolute_import, division, print_function, unicode_literals + +try: + from time import monotonic +except ImportError: + from calibre.constants import plugins + + monotonicp, err = plugins['monotonic'] + if err: + raise RuntimeError('Failed to load the monotonic module with error: ' + err) + monotonic = monotonicp.monotonic + del monotonicp, err diff --git a/ebook_converter/utils/mreplace.py b/ebook_converter/utils/mreplace.py new file mode 100644 index 0000000..eb2059f --- /dev/null +++ b/ebook_converter/utils/mreplace.py @@ -0,0 +1,44 @@ +# multiple replace from dictionnary : http://code.activestate.com/recipes/81330/ +from __future__ import unicode_literals +__license__ = 'GPL v3' +__copyright__ = '2010, sengian <sengian1 @ gmail.com>' +__docformat__ = 'restructuredtext en' + +import re +try: + from collections import UserDict +except ImportError: + from UserDict import UserDict + + +class MReplace(UserDict): + + def __init__(self, data=None, case_sensitive=True): + UserDict.__init__(self, data) + self.re = None + self.regex = None + self.case_sensitive = case_sensitive + self.compile_regex() + + def compile_regex(self): + if len(self.data) > 0: + keys = sorted(self.data, key=len, reverse=True) + if isinstance(keys[0], bytes): + tmp = b"(%s)" % b"|".join(map(re.escape, keys)) + else: + tmp = "(%s)" % "|".join(map(re.escape, keys)) + if self.re != tmp: + self.re = tmp + if self.case_sensitive: + self.regex = re.compile(self.re) + else: + self.regex = re.compile(self.re, re.I) + + def __call__(self, mo): + return self[mo.string[mo.start():mo.end()]] + + def mreplace(self, text): + # Replace without regex compile + if len(self.data) < 1 or self.re is None: + return text + return self.regex.sub(self, text) diff --git a/ebook_converter/utils/resources.py b/ebook_converter/utils/resources.py new file mode 100644 index 0000000..f63b884 --- /dev/null +++ b/ebook_converter/utils/resources.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>' +__docformat__ = 'restructuredtext en' + + +import sys, os + +from calibre import config_dir +from polyglot.builtins import builtins + + +user_dir = os.path.join(config_dir, 'resources') + + +class PathResolver(object): + + def __init__(self): + self.locations = [sys.resources_location] + self.cache = {} + + def suitable(path): + try: + return os.path.exists(path) and os.path.isdir(path) and \ + os.listdir(path) + except: + pass + return False + + self.default_path = sys.resources_location + + dev_path = os.environ.get('CALIBRE_DEVELOP_FROM', None) + self.using_develop_from = False + if dev_path is not None: + dev_path = os.path.join(os.path.abspath( + os.path.dirname(dev_path)), 'resources') + if suitable(dev_path): + self.locations.insert(0, dev_path) + self.default_path = dev_path + self.using_develop_from = True + + self.user_path = None + if suitable(user_dir): + self.locations.insert(0, user_dir) + self.user_path = user_dir + + def __call__(self, path, allow_user_override=True): + path = path.replace(os.sep, '/') + key = (path, allow_user_override) + ans = self.cache.get(key, None) + if ans is None: + for base in self.locations: + if not allow_user_override and base == self.user_path: + continue + fpath = os.path.join(base, *path.split('/')) + if os.path.exists(fpath): + ans = fpath + break + + if ans is None: + ans = os.path.join(self.default_path, *path.split('/')) + + self.cache[key] = ans + + return ans + + def set_data(self, path, data=None): + self.cache.pop((path, True), None) + fpath = os.path.join(user_dir, *path.split('/')) + if data is None: + if os.path.exists(fpath): + os.remove(fpath) + else: + base = os.path.dirname(fpath) + if not os.path.exists(base): + os.makedirs(base) + with open(fpath, 'wb') as f: + f.write(data) + + +_resolver = PathResolver() + + +def get_path(path, data=False, allow_user_override=True): + fpath = _resolver(path, allow_user_override=allow_user_override) + if data: + with open(fpath, 'rb') as f: + return f.read() + return fpath + + +def get_image_path(path, data=False, allow_user_override=True): + if not path: + return get_path('images', allow_user_override=allow_user_override) + return get_path('images/'+path, data=data, allow_user_override=allow_user_override) + + +def set_data(path, data=None): + return _resolver.set_data(path, data) + + +builtins.__dict__['P'] = get_path +builtins.__dict__['I'] = get_image_path diff --git a/ebook_converter/utils/serialize.py b/ebook_converter/utils/serialize.py new file mode 100644 index 0000000..f5d560c --- /dev/null +++ b/ebook_converter/utils/serialize.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +# License: GPLv3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net> + +from __future__ import absolute_import, division, print_function, unicode_literals + +from polyglot.builtins import unicode_type +from calibre.constants import ispy3 + + +MSGPACK_MIME = 'application/x-msgpack' +CANARY = 'jPoAv3zOyHvQ5JFNYg4hJ9' + + +def encoded(typ, data, ExtType): + if ExtType is None: + return {CANARY: typ, 'v': data} + return ExtType(typ, msgpack_dumps(data)) + + +def create_encoder(for_json=False): + from datetime import datetime + ExtType = None + if not for_json: + import msgpack + ExtType = msgpack.ExtType + + def encoder(obj): + if isinstance(obj, datetime): + return encoded(0, unicode_type(obj.isoformat()), ExtType) + if isinstance(obj, (set, frozenset)): + return encoded(1, tuple(obj), ExtType) + if getattr(obj, '__calibre_serializable__', False): + from calibre.ebooks.metadata.book.base import Metadata + from calibre.library.field_metadata import FieldMetadata, fm_as_dict + from calibre.db.categories import Tag + if isinstance(obj, Metadata): + from calibre.ebooks.metadata.book.serialize import metadata_as_dict + return encoded( + 2, metadata_as_dict(obj, encode_cover_data=for_json), ExtType + ) + elif isinstance(obj, FieldMetadata): + return encoded(3, fm_as_dict(obj), ExtType) + elif isinstance(obj, Tag): + return encoded(4, obj.as_dict(), ExtType) + if for_json and isinstance(obj, bytes): + return obj.decode('utf-8') + raise TypeError('Cannot serialize objects of type {}'.format(type(obj))) + + return encoder + + +def msgpack_dumps(obj): + import msgpack + return msgpack.packb(obj, default=create_encoder(), use_bin_type=True) + + +def json_dumps(data, **kw): + import json + kw['default'] = create_encoder(for_json=True) + kw['ensure_ascii'] = False + ans = json.dumps(data, **kw) + if not isinstance(ans, bytes): + ans = ans.encode('utf-8') + return ans + + +def decode_metadata(x, for_json): + from polyglot.binary import from_base64_bytes + from calibre.ebooks.metadata.book.serialize import metadata_from_dict + obj = metadata_from_dict(x) + if for_json and obj.cover_data and obj.cover_data[1]: + obj.cover_data = obj.cover_data[0], from_base64_bytes(obj.cover_data[1]) + return obj + + +def decode_field_metadata(x, for_json): + from calibre.library.field_metadata import fm_from_dict + return fm_from_dict(x) + + +def decode_category_tag(x, for_json): + from calibre.db.categories import Tag + return Tag.from_dict(x) + + +def decode_datetime(x, fj): + from calibre.utils.iso8601 import parse_iso8601 + return parse_iso8601(x, assume_utc=True) + + +decoders = ( + decode_datetime, + lambda x, fj: set(x), + decode_metadata, decode_field_metadata, decode_category_tag +) + + +def json_decoder(obj): + typ = obj.get(CANARY) + if typ is None: + return obj + return decoders[typ](obj['v'], True) + + +def msgpack_decoder(code, data): + return decoders[code](msgpack_loads(data), False) + + +def msgpack_loads(dump, use_list=True): + # use_list controls whether msgpack arrays are unpacked as lists or tuples + import msgpack + return msgpack.unpackb(dump, ext_hook=msgpack_decoder, raw=False, use_list=use_list) + + +def json_loads(data): + import json + return json.loads(data, object_hook=json_decoder) + + +if ispy3: + + def pickle_dumps(data): + import pickle + return pickle.dumps(data, -1) + + def pickle_loads(dump): + import pickle + return pickle.loads(dump, encoding='utf-8') + +else: + + def pickle_dumps(data): + import cPickle as pickle + return pickle.dumps(data, -1) + + def pickle_loads(dump): + import cPickle as pickle + return pickle.loads(dump) diff --git a/ebook_converter/utils/shared_file.py b/ebook_converter/utils/shared_file.py new file mode 100644 index 0000000..836c225 --- /dev/null +++ b/ebook_converter/utils/shared_file.py @@ -0,0 +1,222 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2015, Kovid Goyal <kovid at kovidgoyal.net>' + +import os, sys + +from polyglot.builtins import reraise + +from calibre.constants import iswindows, plugins, ispy3 + +''' +This module defines a share_open() function which is a replacement for +python's builtin open() function. + +This replacement, opens 'shareable' files on all platforms. That is files that +can be read from and written to and deleted at the same time by multiple +processes. All file handles are non-inheritable, as in Python 3, but unlike, +Python 2. Non-inheritance is atomic. + +Caveats on windows: On windows sharing is co-operative, i.e. it only works if +all processes involved open the file with share_open(). Also while you can +delete a file that is open, you cannot open a new file with the same filename +until all open file handles are closed. You also cannot delete the containing +directory until all file handles are closed. To get around this, rename the +file before deleting it. +''' + +speedup, err = plugins['speedup'] + +if not speedup: + raise RuntimeError('Failed to load the speedup plugin with error: %s' % err) + +valid_modes = {'a', 'a+', 'a+b', 'ab', 'r', 'rb', 'r+', 'r+b', 'w', 'wb', 'w+', 'w+b'} + + +def validate_mode(mode): + return mode in valid_modes + + +class FlagConstants(object): + + def __init__(self): + for x in 'APPEND CREAT TRUNC EXCL RDWR RDONLY WRONLY'.split(): + x = 'O_' + x + setattr(self, x, getattr(os, x)) + for x in 'RANDOM SEQUENTIAL TEXT BINARY'.split(): + x = 'O_' + x + setattr(self, x, getattr(os, x, 0)) + + +fc = FlagConstants() + + +def flags_from_mode(mode): + if not validate_mode(mode): + raise ValueError('The mode is invalid') + m = mode[0] + random = '+' in mode + binary = 'b' in mode + if m == 'a': + flags = fc.O_APPEND | fc.O_CREAT + if random: + flags |= fc.O_RDWR | fc.O_RANDOM + else: + flags |= fc.O_WRONLY | fc.O_SEQUENTIAL + elif m == 'r': + if random: + flags = fc.O_RDWR | fc.O_RANDOM + else: + flags = fc.O_RDONLY | fc.O_SEQUENTIAL + elif m == 'w': + if random: + flags = fc.O_RDWR | fc.O_RANDOM + else: + flags = fc.O_WRONLY | fc.O_SEQUENTIAL + flags |= fc.O_TRUNC | fc.O_CREAT + flags |= (fc.O_BINARY if binary else fc.O_TEXT) + return flags + + +if iswindows: + from numbers import Integral + import msvcrt + import win32file, pywintypes + CREATE_NEW = win32file.CREATE_NEW + CREATE_ALWAYS = win32file.CREATE_ALWAYS + OPEN_EXISTING = win32file.OPEN_EXISTING + OPEN_ALWAYS = win32file.OPEN_ALWAYS + TRUNCATE_EXISTING = win32file.TRUNCATE_EXISTING + FILE_SHARE_READ = win32file.FILE_SHARE_READ + FILE_SHARE_WRITE = win32file.FILE_SHARE_WRITE + FILE_SHARE_DELETE = win32file.FILE_SHARE_DELETE + FILE_SHARE_VALID_FLAGS = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE + FILE_ATTRIBUTE_READONLY = win32file.FILE_ATTRIBUTE_READONLY + FILE_ATTRIBUTE_NORMAL = win32file.FILE_ATTRIBUTE_NORMAL + FILE_ATTRIBUTE_TEMPORARY = win32file.FILE_ATTRIBUTE_TEMPORARY + FILE_FLAG_DELETE_ON_CLOSE = win32file.FILE_FLAG_DELETE_ON_CLOSE + FILE_FLAG_SEQUENTIAL_SCAN = win32file.FILE_FLAG_SEQUENTIAL_SCAN + FILE_FLAG_RANDOM_ACCESS = win32file.FILE_FLAG_RANDOM_ACCESS + GENERIC_READ = win32file.GENERIC_READ & 0xffffffff + GENERIC_WRITE = win32file.GENERIC_WRITE & 0xffffffff + DELETE = 0x00010000 + + _ACCESS_MASK = os.O_RDONLY | os.O_WRONLY | os.O_RDWR + _ACCESS_MAP = { + os.O_RDONLY : GENERIC_READ, + os.O_WRONLY : GENERIC_WRITE, + os.O_RDWR : GENERIC_READ | GENERIC_WRITE + } + + _CREATE_MASK = os.O_CREAT | os.O_EXCL | os.O_TRUNC + _CREATE_MAP = { + 0 : OPEN_EXISTING, + os.O_EXCL : OPEN_EXISTING, + os.O_CREAT : OPEN_ALWAYS, + os.O_CREAT | os.O_EXCL : CREATE_NEW, + os.O_CREAT | os.O_TRUNC | os.O_EXCL : CREATE_NEW, + os.O_TRUNC : TRUNCATE_EXISTING, + os.O_TRUNC | os.O_EXCL : TRUNCATE_EXISTING, + os.O_CREAT | os.O_TRUNC : CREATE_ALWAYS + } + + def raise_winerror(pywinerr): + reraise( + WindowsError, + WindowsError(pywinerr.winerror, + (pywinerr.funcname or '') + b': ' + (pywinerr.strerror or '')), + sys.exc_info()[2]) + + def os_open(path, flags, mode=0o777, share_flags=FILE_SHARE_VALID_FLAGS): + ''' + Replacement for os.open() allowing moving or unlinking before closing + ''' + if not isinstance(flags, Integral): + raise TypeError('flags must be an integer') + if not isinstance(mode, Integral): + raise TypeError('mode must be an integer') + + if share_flags & ~FILE_SHARE_VALID_FLAGS: + raise ValueError('bad share_flags: %r' % share_flags) + + access_flags = _ACCESS_MAP[flags & _ACCESS_MASK] + create_flags = _CREATE_MAP[flags & _CREATE_MASK] + attrib_flags = FILE_ATTRIBUTE_NORMAL + + if flags & os.O_CREAT and mode & ~0o444 == 0: + attrib_flags = FILE_ATTRIBUTE_READONLY + + if flags & os.O_TEMPORARY: + share_flags |= FILE_SHARE_DELETE + attrib_flags |= FILE_FLAG_DELETE_ON_CLOSE + access_flags |= DELETE + + if flags & os.O_SHORT_LIVED: + attrib_flags |= FILE_ATTRIBUTE_TEMPORARY + + if flags & os.O_SEQUENTIAL: + attrib_flags |= FILE_FLAG_SEQUENTIAL_SCAN + + if flags & os.O_RANDOM: + attrib_flags |= FILE_FLAG_RANDOM_ACCESS + + try: + h = win32file.CreateFileW( + path, access_flags, share_flags, None, create_flags, attrib_flags, None) + except pywintypes.error as e: + raise_winerror(e) + ans = msvcrt.open_osfhandle(h, flags | os.O_NOINHERIT) + h.Detach() # We dont want the handle to be automatically closed when h is deleted + return ans + + def share_open(path, mode='r', buffering=-1): + flags = flags_from_mode(mode) + return speedup.fdopen(os_open(path, flags), path, mode, buffering) + +else: + if ispy3: + # See PEP 446 + share_open = open + else: + def share_open(path, mode='r', buffering=-1): + flags = flags_from_mode(mode) | speedup.O_CLOEXEC + return speedup.fdopen(os.open(path, flags), path, mode, buffering) + + def raise_winerror(x): + reraise(NotImplementedError, None, sys.exc_info()[2]) + + +def find_tests(): + import unittest + from calibre.ptempfile import TemporaryDirectory + + class SharedFileTest(unittest.TestCase): + + def test_shared_file(self): + eq = self.assertEqual + + with TemporaryDirectory() as tdir: + fname = os.path.join(tdir, 'test.txt') + with share_open(fname, 'wb') as f: + f.write(b'a' * 20 * 1024) + eq(fname, f.name) + f = share_open(fname, 'rb') + eq(f.read(1), b'a') + if iswindows: + os.rename(fname, fname+'.moved') + os.remove(fname+'.moved') + else: + os.remove(fname) + eq(f.read(1), b'a') + f2 = share_open(fname, 'w+b') + f2.write(b'b' * 10 * 1024) + f2.seek(0) + eq(f.read(10000), b'a'*10000) + eq(f2.read(100), b'b' * 100) + f3 = share_open(fname, 'rb') + eq(f3.read(100), b'b' * 100) + + return unittest.defaultTestLoader.loadTestsFromTestCase(SharedFileTest) diff --git a/ebook_converter/utils/short_uuid.py b/ebook_converter/utils/short_uuid.py new file mode 100644 index 0000000..0d8b40c --- /dev/null +++ b/ebook_converter/utils/short_uuid.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +# License: GPLv3 Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net> +from __future__ import absolute_import, division, print_function, unicode_literals + +''' +Generate UUID encoded using a user specified alphabet. +''' + +import string, math, uuid as _uuid + +from polyglot.builtins import unicode_type + + +def num_to_string(number, alphabet, alphabet_len, pad_to_length=None): + ans = [] + number = max(0, number) + while number: + number, digit = divmod(number, alphabet_len) + ans.append(alphabet[digit]) + if pad_to_length is not None and pad_to_length > len(ans): + ans.append(alphabet[0] * (pad_to_length - len(ans))) + return ''.join(ans) + + +def string_to_num(string, alphabet_map, alphabet_len): + ans = 0 + for char in reversed(string): + ans = ans * alphabet_len + alphabet_map[char] + return ans + + +class ShortUUID(object): + + def __init__(self, alphabet=None): + # We do not include zero and one in the default alphabet as they can be + # confused with the letters O and I in some fonts. And removing them + # does not change the uuid_pad_len. + self.alphabet = tuple(sorted(unicode_type(alphabet or (string.digits + string.ascii_letters)[2:]))) + self.alphabet_len = len(self.alphabet) + self.alphabet_map = {c:i for i, c in enumerate(self.alphabet)} + self.uuid_pad_len = int(math.ceil(math.log(1 << 128, self.alphabet_len))) + + def uuid4(self, pad_to_length=None): + if pad_to_length is None: + pad_to_length = self.uuid_pad_len + return num_to_string(_uuid.uuid4().int, self.alphabet, self.alphabet_len, pad_to_length) + + def uuid5(self, namespace, name, pad_to_length=None): + if pad_to_length is None: + pad_to_length = self.uuid_pad_len + return num_to_string(_uuid.uuid5(namespace, name).int, self.alphabet, self.alphabet_len, pad_to_length) + + def decode(self, encoded): + return _uuid.UUID(int=string_to_num(encoded, self.alphabet_map, self.alphabet_len)) + + +_global_instance = ShortUUID() +uuid4 = _global_instance.uuid4 +uuid5 = _global_instance.uuid5 +decode = _global_instance.decode diff --git a/ebook_converter/utils/smartypants.py b/ebook_converter/utils/smartypants.py new file mode 100644 index 0000000..7f44d06 --- /dev/null +++ b/ebook_converter/utils/smartypants.py @@ -0,0 +1,888 @@ +#!/usr/bin/python2 +# vim:fileencoding=utf-8 + +from __future__ import absolute_import, division, print_function, unicode_literals + +__author__ = "Chad Miller <smartypantspy@chad.org>, Kovid Goyal <kovid at kovidgoyal.net>" +__description__ = "Smart-quotes, smart-ellipses, and smart-dashes for weblog entries in pyblosxom" + +r""" +============== +smartypants.py +============== + +---------------------------- +SmartyPants ported to Python +---------------------------- + +Ported by `Chad Miller`_ +Copyright (c) 2004, 2007 Chad Miller + +original `SmartyPants`_ by `John Gruber`_ +Copyright (c) 2003 John Gruber + + +Synopsis +======== + +A smart-quotes plugin for Pyblosxom_. + +The priginal "SmartyPants" is a free web publishing plug-in for Movable Type, +Blosxom, and BBEdit that easily translates plain ASCII punctuation characters +into "smart" typographic punctuation HTML entities. + +This software, *smartypants.py*, endeavours to be a functional port of +SmartyPants to Python, for use with Pyblosxom_. + + +Description +=========== + +SmartyPants can perform the following transformations: + +- Straight quotes ( " and ' ) into "curly" quote HTML entities +- Backticks-style quotes (\`\`like this'') into "curly" quote HTML entities +- Dashes (``--`` and ``---``) into en- and em-dash entities +- Three consecutive dots (``...`` or ``. . .``) into an ellipsis entity + +This means you can write, edit, and save your posts using plain old +ASCII straight quotes, plain dashes, and plain dots, but your published +posts (and final HTML output) will appear with smart quotes, em-dashes, +and proper ellipses. + +SmartyPants does not modify characters within ``<pre>``, ``<code>``, ``<kbd>``, +``<math>`` or ``<script>`` tag blocks. Typically, these tags are used to +display text where smart quotes and other "smart punctuation" would not be +appropriate, such as source code or example markup. + + +Backslash Escapes +================= + +If you need to use literal straight quotes (or plain hyphens and +periods), SmartyPants accepts the following backslash escape sequences +to force non-smart punctuation. It does so by transforming the escape +sequence into a decimal-encoded HTML entity: + +(FIXME: table here.) + +.. comment It sucks that there's a disconnect between the visual layout and table markup when special characters are involved. +.. comment ====== ===== ========= +.. comment Escape Value Character +.. comment ====== ===== ========= +.. comment \\\\\\\\ \ \\\\ +.. comment \\\\" " " +.. comment \\\\' ' ' +.. comment \\\\. . . +.. comment \\\\- - \- +.. comment \\\\` ` \` +.. comment ====== ===== ========= + +This is useful, for example, when you want to use straight quotes as +foot and inch marks: 6'2" tall; a 17" iMac. + +Options +======= + +For Pyblosxom users, the ``smartypants_attributes`` attribute is where you +specify configuration options. + +Numeric values are the easiest way to configure SmartyPants' behavior: + +"0" + Suppress all transformations. (Do nothing.) +"1" + Performs default SmartyPants transformations: quotes (including + \`\`backticks'' -style), em-dashes, and ellipses. "``--``" (dash dash) + is used to signify an em-dash; there is no support for en-dashes. + +"2" + Same as smarty_pants="1", except that it uses the old-school typewriter + shorthand for dashes: "``--``" (dash dash) for en-dashes, "``---``" + (dash dash dash) + for em-dashes. + +"3" + Same as smarty_pants="2", but inverts the shorthand for dashes: + "``--``" (dash dash) for em-dashes, and "``---``" (dash dash dash) for + en-dashes. + +"-1" + Stupefy mode. Reverses the SmartyPants transformation process, turning + the HTML entities produced by SmartyPants into their ASCII equivalents. + E.g. "“" is turned into a simple double-quote ("), "—" is + turned into two dashes, etc. + + +The following single-character attribute values can be combined to toggle +individual transformations from within the smarty_pants attribute. For +example, to educate normal quotes and em-dashes, but not ellipses or +\`\`backticks'' -style quotes: + +``py['smartypants_attributes'] = "1"`` + +"q" + Educates normal quote characters: (") and ('). + +"b" + Educates \`\`backticks'' -style double quotes. + +"B" + Educates \`\`backticks'' -style double quotes and \`single' quotes. + +"d" + Educates em-dashes. + +"D" + Educates em-dashes and en-dashes, using old-school typewriter shorthand: + (dash dash) for en-dashes, (dash dash dash) for em-dashes. + +"i" + Educates em-dashes and en-dashes, using inverted old-school typewriter + shorthand: (dash dash) for em-dashes, (dash dash dash) for en-dashes. + +"e" + Educates ellipses. + +"w" + Translates any instance of ``"`` into a normal double-quote character. + This should be of no interest to most people, but of particular interest + to anyone who writes their posts using Dreamweaver, as Dreamweaver + inexplicably uses this entity to represent a literal double-quote + character. SmartyPants only educates normal quotes, not entities (because + ordinarily, entities are used for the explicit purpose of representing the + specific character they represent). The "w" option must be used in + conjunction with one (or both) of the other quote options ("q" or "b"). + Thus, if you wish to apply all SmartyPants transformations (quotes, en- + and em-dashes, and ellipses) and also translate ``"`` entities into + regular quotes so SmartyPants can educate them, you should pass the + following to the smarty_pants attribute: + +The ``smartypants_forbidden_flavours`` list contains pyblosxom flavours for +which no Smarty Pants rendering will occur. + + +Caveats +======= + +Why You Might Not Want to Use Smart Quotes in Your Weblog +--------------------------------------------------------- + +For one thing, you might not care. + +Most normal, mentally stable individuals do not take notice of proper +typographic punctuation. Many design and typography nerds, however, break +out in a nasty rash when they encounter, say, a restaurant sign that uses +a straight apostrophe to spell "Joe's". + +If you're the sort of person who just doesn't care, you might well want to +continue not caring. Using straight quotes -- and sticking to the 7-bit +ASCII character set in general -- is certainly a simpler way to live. + +Even if you I *do* care about accurate typography, you still might want to +think twice before educating the quote characters in your weblog. One side +effect of publishing curly quote HTML entities is that it makes your +weblog a bit harder for others to quote from using copy-and-paste. What +happens is that when someone copies text from your blog, the copied text +contains the 8-bit curly quote characters (as well as the 8-bit characters +for em-dashes and ellipses, if you use these options). These characters +are not standard across different text encoding methods, which is why they +need to be encoded as HTML entities. + +People copying text from your weblog, however, may not notice that you're +using curly quotes, and they'll go ahead and paste the unencoded 8-bit +characters copied from their browser into an email message or their own +weblog. When pasted as raw "smart quotes", these characters are likely to +get mangled beyond recognition. + +That said, my own opinion is that any decent text editor or email client +makes it easy to stupefy smart quote characters into their 7-bit +equivalents, and I don't consider it my problem if you're using an +indecent text editor or email client. + + +Algorithmic Shortcomings +------------------------ + +One situation in which quotes will get curled the wrong way is when +apostrophes are used at the start of leading contractions. For example: + +``'Twas the night before Christmas.`` + +In the case above, SmartyPants will turn the apostrophe into an opening +single-quote, when in fact it should be a closing one. I don't think +this problem can be solved in the general case -- every word processor +I've tried gets this wrong as well. In such cases, it's best to use the +proper HTML entity for closing single-quotes (``’``) by hand. + + +Bugs +==== + +To file bug reports or feature requests (other than topics listed in the +Caveats section above) please send email to: mailto:smartypantspy@chad.org + +If the bug involves quotes being curled the wrong way, please send example +text to illustrate. + +To Do list +---------- + +- Provide a function for use within templates to quote anything at all. + + +Version History +=============== + +1.5_1.6: Fri, 27 Jul 2007 07:06:40 -0400 + - Fixed bug where blocks of precious unalterable text was instead + interpreted. Thanks to Le Roux and Dirk van Oosterbosch. + +1.5_1.5: Sat, 13 Aug 2005 15:50:24 -0400 + - Fix bogus magical quotation when there is no hint that the + user wants it, e.g., in "21st century". Thanks to Nathan Hamblen. + - Be smarter about quotes before terminating numbers in an en-dash'ed + range. + +1.5_1.4: Thu, 10 Feb 2005 20:24:36 -0500 + - Fix a date-processing bug, as reported by jacob childress. + - Begin a test-suite for ensuring correct output. + - Removed import of "string", since I didn't really need it. + (This was my first every Python program. Sue me!) + +1.5_1.3: Wed, 15 Sep 2004 18:25:58 -0400 + - Abort processing if the flavour is in forbidden-list. Default of + [ "rss" ] (Idea of Wolfgang SCHNERRING.) + - Remove stray virgules from en-dashes. Patch by Wolfgang SCHNERRING. + +1.5_1.2: Mon, 24 May 2004 08:14:54 -0400 + - Some single quotes weren't replaced properly. Diff-tesuji played + by Benjamin GEIGER. + +1.5_1.1: Sun, 14 Mar 2004 14:38:28 -0500 + - Support upcoming pyblosxom 0.9 plugin verification feature. + +1.5_1.0: Tue, 09 Mar 2004 08:08:35 -0500 + - Initial release + +Version Information +------------------- + +Version numbers will track the SmartyPants_ version numbers, with the addition +of an underscore and the smartypants.py version on the end. + +New versions will be available at `http://wiki.chad.org/SmartyPantsPy`_ + +.. _http://wiki.chad.org/SmartyPantsPy: http://wiki.chad.org/SmartyPantsPy + +Authors +======= + +`John Gruber`_ did all of the hard work of writing this software in Perl for +`Movable Type`_ and almost all of this useful documentation. `Chad Miller`_ +ported it to Python to use with Pyblosxom_. + + +Additional Credits +================== + +Portions of the SmartyPants original work are based on Brad Choate's nifty +MTRegex plug-in. `Brad Choate`_ also contributed a few bits of source code to +this plug-in. Brad Choate is a fine hacker indeed. + +`Jeremy Hedley`_ and `Charles Wiltgen`_ deserve mention for exemplary beta +testing of the original SmartyPants. + +`Rael Dornfest`_ ported SmartyPants to Blosxom. + +.. _Brad Choate: http://bradchoate.com/ +.. _Jeremy Hedley: http://antipixel.com/ +.. _Charles Wiltgen: http://playbacktime.com/ +.. _Rael Dornfest: http://raelity.org/ + + +Copyright and License +===================== + +SmartyPants_ license:: + + Copyright (c) 2003 John Gruber + (https://daringfireball.net/) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name "SmartyPants" nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + This software is provided by the copyright holders and contributors "as + is" and any express or implied warranties, including, but not limited + to, the implied warranties of merchantability and fitness for a + particular purpose are disclaimed. In no event shall the copyright + owner or contributors be liable for any direct, indirect, incidental, + special, exemplary, or consequential damages (including, but not + limited to, procurement of substitute goods or services; loss of use, + data, or profits; or business interruption) however caused and on any + theory of liability, whether in contract, strict liability, or tort + (including negligence or otherwise) arising in any way out of the use + of this software, even if advised of the possibility of such damage. + + +smartypants.py license:: + + smartypants.py is a derivative work of SmartyPants. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + This software is provided by the copyright holders and contributors "as + is" and any express or implied warranties, including, but not limited + to, the implied warranties of merchantability and fitness for a + particular purpose are disclaimed. In no event shall the copyright + owner or contributors be liable for any direct, indirect, incidental, + special, exemplary, or consequential damages (including, but not + limited to, procurement of substitute goods or services; loss of use, + data, or profits; or business interruption) however caused and on any + theory of liability, whether in contract, strict liability, or tort + (including negligence or otherwise) arising in any way out of the use + of this software, even if advised of the possibility of such damage. + + + +.. _John Gruber: https://daringfireball.net/ +.. _Chad Miller: http://web.chad.org/ + +.. _Pyblosxom: http://roughingit.subtlehints.net/pyblosxom +.. _SmartyPants: https://daringfireball.net/projects/smartypants/ +.. _Movable Type: http://www.movabletype.org/ + +""" + +import re + +# style added by Kovid +tags_to_skip_regex = re.compile(r"<(/)?(style|pre|code|kbd|script|math)[^>]*>", re.I) +self_closing_regex = re.compile(r'/\s*>$') + + +# interal functions below here + +def parse_attr(attr): + do_dashes = do_backticks = do_quotes = do_ellipses = do_stupefy = 0 + + if attr == "1": + do_quotes = 1 + do_backticks = 1 + do_dashes = 1 + do_ellipses = 1 + elif attr == "2": + # Do everything, turn all options on, use old school dash shorthand. + do_quotes = 1 + do_backticks = 1 + do_dashes = 2 + do_ellipses = 1 + elif attr == "3": + # Do everything, turn all options on, use inverted old school dash shorthand. + do_quotes = 1 + do_backticks = 1 + do_dashes = 3 + do_ellipses = 1 + elif attr == "-1": + # Special "stupefy" mode. + do_stupefy = 1 + else: + for c in attr: + if c == "q": + do_quotes = 1 + elif c == "b": + do_backticks = 1 + elif c == "B": + do_backticks = 2 + elif c == "d": + do_dashes = 1 + elif c == "D": + do_dashes = 2 + elif c == "i": + do_dashes = 3 + elif c == "e": + do_ellipses = 1 + else: + pass + # ignore unknown option + return do_dashes, do_backticks, do_quotes, do_ellipses, do_stupefy + + +def smartyPants(text, attr='1'): + # Parse attributes: + # 0 : do nothing + # 1 : set all + # 2 : set all, using old school en- and em- dash shortcuts + # 3 : set all, using inverted old school en and em- dash shortcuts + # + # q : quotes + # b : backtick quotes (``double'' only) + # B : backtick quotes (``double'' and `single') + # d : dashes + # D : old school dashes + # i : inverted old school dashes + # e : ellipses + + if attr == "0": + # Do nothing. + return text + + do_dashes, do_backticks, do_quotes, do_ellipses, do_stupefy = parse_attr(attr) + dashes_func = {1: educateDashes, 2: educateDashesOldSchool, 3: educateDashesOldSchoolInverted}.get(do_dashes, lambda x: x) + backticks_func = {1: educateBackticks, 2: lambda x: educateSingleBackticks(educateBackticks(x))}.get(do_backticks, lambda x: x) + ellipses_func = {1: educateEllipses}.get(do_ellipses, lambda x: x) + stupefy_func = {1: stupefyEntities}.get(do_stupefy, lambda x: x) + skipped_tag_stack = [] + tokens = _tokenize(text) + result = [] + in_pre = False + + prev_token_last_char = "" + # This is a cheat, used to get some context + # for one-character tokens that consist of + # just a quote char. What we do is remember + # the last character of the previous text + # token, to use as context to curl single- + # character quote tokens correctly. + + for cur_token in tokens: + if cur_token[0] == "tag": + # Don't mess with quotes inside some tags. This does not handle self <closing/> tags! + result.append(cur_token[1]) + skip_match = tags_to_skip_regex.match(cur_token[1]) + if skip_match is not None: + is_self_closing = self_closing_regex.search(skip_match.group()) is not None + if not is_self_closing: + if not skip_match.group(1): + skipped_tag_stack.append(skip_match.group(2).lower()) + in_pre = True + else: + if len(skipped_tag_stack) > 0: + if skip_match.group(2).lower() == skipped_tag_stack[-1]: + skipped_tag_stack.pop() + else: + pass + # This close doesn't match the open. This isn't XHTML. We should barf here. + if len(skipped_tag_stack) == 0: + in_pre = False + else: + t = cur_token[1] + last_char = t[-1:] # Remember last char of this token before processing. + if not in_pre: + t = processEscapes(t) + + t = re.sub('"', '"', t) + t = dashes_func(t) + t = ellipses_func(t) + # Note: backticks need to be processed before quotes. + t = backticks_func(t) + + if do_quotes != 0: + if t == "'": + # Special case: single-character ' token + if re.match(r"\S", prev_token_last_char): + t = "’" + else: + t = "‘" + elif t == '"': + # Special case: single-character " token + if re.match(r"\S", prev_token_last_char): + t = "”" + else: + t = "“" + + else: + # Normal case: + t = educateQuotes(t) + + t = stupefy_func(t) + + prev_token_last_char = last_char + result.append(t) + + return "".join(result) + + +def educateQuotes(text): + """ + Parameter: String. + + Returns: The string, with "educated" curly quote HTML entities. + + Example input: "Isn't this fun?" + Example output: “Isn’t this fun?” + """ + + punct_class = r"""[!"#\$\%'()*+,-.\/:;<=>?\@\[\\\]\^_`{|}~]""" + + # Special case if the very first character is a quote + # followed by punctuation at a non-word-break. Close the quotes by brute force: + text = re.sub(r"""^'(?=%s\\B)""" % (punct_class,), r"""’""", text) + text = re.sub(r"""^"(?=%s\\B)""" % (punct_class,), r"""”""", text) + + # Special case for double sets of quotes, e.g.: + # <p>He said, "'Quoted' words in a larger quote."</p> + text = re.sub(r""""'(?=\w)""", """“‘""", text) + text = re.sub(r"""'"(?=\w)""", """‘“""", text) + text = re.sub(r'''""(?=\w)''', """““""", text) + text = re.sub(r"""''(?=\w)""", """‘‘""", text) + text = re.sub(r'''\"\'''', """”’""", text) + text = re.sub(r'''\'\"''', """’”""", text) + text = re.sub(r'''""''', """””""", text) + text = re.sub(r"""''""", """’’""", text) + + # Special case for decade abbreviations (the '80s --> ’80s): + # See http://practicaltypography.com/apostrophes.html + text = re.sub(r"""(\W|^)'(?=\d{2}s)""", r"""\1’""", text) + # Measurements in feet and inches or longitude/latitude: 19' 43.5" --> 19′ 43.5″ + text = re.sub(r'''(\W|^)([-0-9.]+\s*)'(\s*[-0-9.]+)"''', r'\1\2′\3″', text) + + # Special case for Quotes at inside of other entities, e.g.: + # <p>A double quote--"within dashes"--would be nice.</p> + text = re.sub(r"""(?<=\W)"(?=\w)""", r"""“""", text) + text = re.sub(r"""(?<=\W)'(?=\w)""", r"""‘""", text) + text = re.sub(r"""(?<=\w)"(?=\W)""", r"""”""", text) + text = re.sub(r"""(?<=\w)'(?=\W)""", r"""’""", text) + + # The following are commented out as smartypants tokenizes text by + # stripping out html tags. Therefore, there is no guarantee that the + # start-of-line and end-ol-line regex operators will match anything + # meaningful + + # Special case for Quotes at end of line with a preceeding space (may change just to end of line) + # text = re.sub(r"""(?<=\s)"$""", r"""”""", text) + # text = re.sub(r"""(?<=\s)'$""", r"""’""", text) + + # Special case for Quotes at beginning of line with a space - multiparagraph quoted text: + # text = re.sub(r"""^"(?=\s)""", r"""“""", text) + # text = re.sub(r"""^'(?=\s)""", r"""‘""", text) + + close_class = r"""[^\ \t\r\n\[\{\(\-]""" + dec_dashes = r"""–|—""" + + # Get most opening single quotes: + opening_single_quotes_regex = re.compile(r""" + ( + \s | # a whitespace char, or +   | # a non-breaking space entity, or + -- | # dashes, or + &[mn]dash; | # named dash entities + %s | # or decimal entities + &\#x201[34]; # or hex + ) + ' # the quote + (?=\w) # followed by a word character + """ % (dec_dashes,), re.VERBOSE) + text = opening_single_quotes_regex.sub(r"""\1‘""", text) + + closing_single_quotes_regex = re.compile(r""" + (%s) + ' + (?!\s | s\b | \d) + """ % (close_class,), re.VERBOSE) + text = closing_single_quotes_regex.sub(r"""\1’""", text) + + closing_single_quotes_regex = re.compile(r""" + (%s) + ' + (\s | s\b) + """ % (close_class,), re.VERBOSE) + text = closing_single_quotes_regex.sub(r"""\1’\2""", text) + + # Any remaining single quotes should be opening ones: + text = re.sub(r"""'""", r"""‘""", text) + + # Get most opening double quotes: + opening_double_quotes_regex = re.compile(r""" + ( + \s | # a whitespace char, or +   | # a non-breaking space entity, or + -- | # dashes, or + &[mn]dash; | # named dash entities + %s | # or decimal entities + &\#x201[34]; # or hex + ) + " # the quote + (?=\w) # followed by a word character + """ % (dec_dashes,), re.VERBOSE) + text = opening_double_quotes_regex.sub(r"""\1“""", text) + + # Double closing quotes: + closing_double_quotes_regex = re.compile(r""" + #(%s)? # character that indicates the quote should be closing + " + (?=\s) + """ % (close_class,), re.VERBOSE) + text = closing_double_quotes_regex.sub(r"""”""", text) + + closing_double_quotes_regex = re.compile(r""" + (%s) # character that indicates the quote should be closing + " + """ % (close_class,), re.VERBOSE) + text = closing_double_quotes_regex.sub(r"""\1”""", text) + + if text.endswith('-"'): + # A string that endswith -" is sometimes used for dialogue + text = text[:-1] + '”' + + # Any remaining quotes should be opening ones. + text = re.sub(r'"', r"""“""", text) + + return text + + +def educateBackticks(text): + """ + Parameter: String. + Returns: The string, with ``backticks'' -style double quotes + translated into HTML curly quote entities. + Example input: ``Isn't this fun?'' + Example output: “Isn't this fun?” + """ + + text = re.sub(r"""``""", r"""“""", text) + text = re.sub(r"""''""", r"""”""", text) + return text + + +def educateSingleBackticks(text): + """ + Parameter: String. + Returns: The string, with `backticks' -style single quotes + translated into HTML curly quote entities. + + Example input: `Isn't this fun?' + Example output: ‘Isn’t this fun?’ + """ + + text = re.sub(r"""`""", r"""‘""", text) + text = re.sub(r"""'""", r"""’""", text) + return text + + +def educateDashes(text): + """ + Parameter: String. + + Returns: The string, with each instance of "--" translated to + an em-dash HTML entity. + """ + + text = re.sub(r"""---""", r"""–""", text) # en (yes, backwards) + text = re.sub(r"""--""", r"""—""", text) # em (yes, backwards) + return text + + +def educateDashesOldSchool(text): + """ + Parameter: String. + + Returns: The string, with each instance of "--" translated to + an en-dash HTML entity, and each "---" translated to + an em-dash HTML entity. + """ + + text = re.sub(r"""---""", r"""—""", text) # em (yes, backwards) + text = re.sub(r"""--""", r"""–""", text) # en (yes, backwards) + return text + + +def educateDashesOldSchoolInverted(text): + """ + Parameter: String. + + Returns: The string, with each instance of "--" translated to + an em-dash HTML entity, and each "---" translated to + an en-dash HTML entity. Two reasons why: First, unlike the + en- and em-dash syntax supported by + EducateDashesOldSchool(), it's compatible with existing + entries written before SmartyPants 1.1, back when "--" was + only used for em-dashes. Second, em-dashes are more + common than en-dashes, and so it sort of makes sense that + the shortcut should be shorter to type. (Thanks to Aaron + Swartz for the idea.) + """ + text = re.sub(r"""---""", r"""–""", text) # em + text = re.sub(r"""--""", r"""—""", text) # en + return text + + +def educateEllipses(text): + """ + Parameter: String. + Returns: The string, with each instance of "..." translated to + an ellipsis HTML entity. + + Example input: Huh...? + Example output: Huh…? + """ + + text = re.sub(r"""\.\.\.""", r"""…""", text) + text = re.sub(r"""\. \. \.""", r"""…""", text) + return text + + +def stupefyEntities(text): + """ + Parameter: String. + Returns: The string, with each SmartyPants HTML entity translated to + its ASCII counterpart. + + Example input: “Hello — world.” + Example output: "Hello -- world." + """ + + text = re.sub(r"""–""", r"""-""", text) # en-dash + text = re.sub(r"""—""", r"""--""", text) # em-dash + + text = re.sub(r"""‘""", r"""'""", text) # open single quote + text = re.sub(r"""’""", r"""'""", text) # close single quote + + text = re.sub(r"""“""", r'''"''', text) # open double quote + text = re.sub(r"""”""", r'''"''', text) # close double quote + + text = re.sub(r"""…""", r"""...""", text) # ellipsis + + return text + + +def processEscapes(text): + r""" + Parameter: String. + Returns: The string, with after processing the following backslash + escape sequences. This is useful if you want to force a "dumb" + quote or other character to appear. + + Escape Value + ------ ----- + \\ \ + \" " + \' ' + \. . + \- - + \` ` + """ + text = re.sub(r"""\\\\""", r"""\""", text) + text = re.sub(r'''\\"''', r""""""", text) + text = re.sub(r"""\\'""", r"""'""", text) + text = re.sub(r"""\\\.""", r""".""", text) + text = re.sub(r"""\\-""", r"""-""", text) + text = re.sub(r"""\\`""", r"""`""", text) + + return text + + +def _tokenize(html): + """ + Parameter: String containing HTML markup. + Returns: Reference to an array of the tokens comprising the input + string. Each token is either a tag (possibly with nested, + tags contained therein, such as <a href="<MTFoo>">, or a + run of text between tags. Each element of the array is a + two-element array; the first is either 'tag' or 'text'; + the second is the actual value. + + Based on the _tokenize() subroutine from Brad Choate's MTRegex plugin. + <http://www.bradchoate.com/past/mtregex.php> + """ + + tokens = [] + + # depth = 6 + # nested_tags = "|".join(['(?:<(?:[^<>]',] * depth) + (')*>)' * depth) + # match = r"""(?: <! ( -- .*? -- \s* )+ > ) | # comments + # (?: <\? .*? \?> ) | # directives + # %s # nested tags """ % (nested_tags,) + tag_soup = re.compile(r"""([^<]*)(<[^>]*>)""") + + token_match = tag_soup.search(html) + + previous_end = 0 + while token_match is not None: + if token_match.group(1): + tokens.append(['text', token_match.group(1)]) + + tokens.append(['tag', token_match.group(2)]) + + previous_end = token_match.end() + token_match = tag_soup.search(html, token_match.end()) + + if previous_end < len(html): + tokens.append(['text', html[previous_end:]]) + + return tokens + + +def run_tests(return_tests=False): + import unittest + sp = smartyPants + + class TestSmartypantsAllAttributes(unittest.TestCase): + # the default attribute is "1", which means "all". + + def test_dates(self): + self.assertEqual(sp("one two '60s"), "one two ’60s") + self.assertEqual(sp("1440-80's"), "1440-80’s") + self.assertEqual(sp("1440-'80s"), "1440-’80s") + self.assertEqual(sp("1440---'80s"), "1440–’80s") + self.assertEqual(sp("1960s"), "1960s") # no effect. + self.assertEqual(sp("1960's"), "1960’s") + self.assertEqual(sp("one two '60s"), "one two ’60s") + self.assertEqual(sp("'60s"), "’60s") + + def test_measurements(self): + ae = self.assertEqual + ae(sp("one two 1.1'2.2\""), "one two 1.1′2.2″") + ae(sp("1' 2\""), "1′ 2″") + + def test_skip_tags(self): + self.assertEqual( + sp("""<script type="text/javascript">\n<!--\nvar href = "http://www.google.com";\nvar linktext = "google";\ndocument.write('<a href="' + href + '">' + linktext + "</a>");\n//-->\n</script>"""), # noqa + """<script type="text/javascript">\n<!--\nvar href = "http://www.google.com";\nvar linktext = "google";\ndocument.write('<a href="' + href + '">' + linktext + "</a>");\n//-->\n</script>""") # noqa + self.assertEqual( + sp("""<p>He said "Let's write some code." This code here <code>if True:\n\tprint "Okay"</code> is python code.</p>"""), + """<p>He said “Let’s write some code.” This code here <code>if True:\n\tprint "Okay"</code> is python code.</p>""") # noqa + + self.assertEqual( + sp('''<script/><p>It's ok</p>'''), + '''<script/><p>It’s ok</p>''') + + def test_ordinal_numbers(self): + self.assertEqual(sp("21st century"), "21st century") # no effect. + self.assertEqual(sp("3rd"), "3rd") # no effect. + + def test_educated_quotes(self): + self.assertEqual(sp('''"Isn't this fun?"'''), '''“Isn’t this fun?”''') + + tests = unittest.defaultTestLoader.loadTestsFromTestCase(TestSmartypantsAllAttributes) + if return_tests: + return tests + unittest.TextTestRunner(verbosity=4).run(tests) + + +if __name__ == "__main__": + run_tests() diff --git a/ebook_converter/utils/speedups.py b/ebook_converter/utils/speedups.py new file mode 100644 index 0000000..e6d5acb --- /dev/null +++ b/ebook_converter/utils/speedups.py @@ -0,0 +1,205 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +# License: GPLv3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net> + +from __future__ import absolute_import, division, print_function, unicode_literals + +import os +from polyglot.builtins import range, unicode_type + + +class ReadOnlyFileBuffer(object): + + ''' A zero copy implementation of a file like object. Uses memoryviews for efficiency. ''' + + def __init__(self, raw): + self.sz, self.mv = len(raw), (raw if isinstance(raw, memoryview) else memoryview(raw)) + self.pos = 0 + + def tell(self): + return self.pos + + def read(self, n=None): + if n is None: + ans = self.mv[self.pos:] + self.pos = self.sz + return ans + ans = self.mv[self.pos:self.pos+n] + self.pos = min(self.pos + n, self.sz) + return ans + + def seek(self, pos, whence=os.SEEK_SET): + if whence == os.SEEK_SET: + self.pos = pos + elif whence == os.SEEK_END: + self.pos = self.sz + pos + else: + self.pos += pos + self.pos = max(0, min(self.pos, self.sz)) + return self.pos + + def getvalue(self): + return self.mv + + def close(self): + pass + + +def svg_path_to_painter_path(d): + ''' + Convert a tiny SVG 1.2 path into a QPainterPath. + + :param d: The value of the d attribute of an SVG <path> tag + ''' + from PyQt5.Qt import QPainterPath + cmd = last_cmd = b'' + path = QPainterPath() + moveto_abs, moveto_rel = b'M', b'm' + closepath1, closepath2 = b'Z', b'z' + lineto_abs, lineto_rel = b'L', b'l' + hline_abs, hline_rel = b'H', b'h' + vline_abs, vline_rel = b'V', b'v' + curveto_abs, curveto_rel = b'C', b'c' + smoothcurveto_abs, smoothcurveto_rel = b'S', b's' + quadcurveto_abs, quadcurveto_rel = b'Q', b'q' + smoothquadcurveto_abs, smoothquadcurveto_rel = b'T', b't' + + # Store the last parsed values + # x/y = end position + # x1/y1 and x2/y2 = bezier control points + x = y = x1 = y1 = x2 = y2 = 0 + + if isinstance(d, unicode_type): + d = d.encode('ascii') + d = d.replace(b',', b' ').replace(b'\n', b' ') + end = len(d) + pos = [0] + + def read_byte(): + p = pos[0] + pos[0] += 1 + return d[p:p+1] + + def parse_float(): + chars = [] + while pos[0] < end: + c = read_byte() + if c == b' ' and not chars: + continue + if c in b'-.0123456789': + chars.append(c) + else: + break + if not chars: + raise ValueError('Premature end of input while expecting a number') + return float(b''.join(chars)) + + def parse_floats(num, x_offset=0, y_offset=0): + for i in range(num): + val = parse_float() + yield val + (x_offset if i % 2 == 0 else y_offset) + + repeated_command = None + + while pos[0] < end: + last_cmd = cmd + cmd = read_byte() if repeated_command is None else repeated_command + repeated_command = None + + if cmd == b' ': + continue + if cmd == moveto_abs: + x, y = parse_float(), parse_float() + path.moveTo(x, y) + elif cmd == moveto_rel: + x += parse_float() + y += parse_float() + path.moveTo(x, y) + elif cmd == closepath1 or cmd == closepath2: + path.closeSubpath() + elif cmd == lineto_abs: + x, y = parse_floats(2) + path.lineTo(x, y) + elif cmd == lineto_rel: + x += parse_float() + y += parse_float() + path.lineTo(x, y) + elif cmd == hline_abs: + x = parse_float() + path.lineTo(x, y) + elif cmd == hline_rel: + x += parse_float() + path.lineTo(x, y) + elif cmd == vline_abs: + y = parse_float() + path.lineTo(x, y) + elif cmd == vline_rel: + y += parse_float() + path.lineTo(x, y) + elif cmd == curveto_abs: + x1, y1, x2, y2, x, y = parse_floats(6) + path.cubicTo(x1, y1, x2, y2, x, y) + elif cmd == curveto_rel: + x1, y1, x2, y2, x, y = parse_floats(6, x, y) + path.cubicTo(x1, y1, x2, y2, x, y) + elif cmd == smoothcurveto_abs: + if last_cmd == curveto_abs or last_cmd == curveto_rel or last_cmd == smoothcurveto_abs or last_cmd == smoothcurveto_rel: + x1 = 2 * x - x2 + y1 = 2 * y - y2 + else: + x1, y1 = x, y + x2, y2, x, y = parse_floats(4) + path.cubicTo(x1, y1, x2, y2, x, y) + elif cmd == smoothcurveto_rel: + if last_cmd == curveto_abs or last_cmd == curveto_rel or last_cmd == smoothcurveto_abs or last_cmd == smoothcurveto_rel: + x1 = 2 * x - x2 + y1 = 2 * y - y2 + else: + x1, y1 = x, y + x2, y2, x, y = parse_floats(4, x, y) + path.cubicTo(x1, y1, x2, y2, x, y) + elif cmd == quadcurveto_abs: + x1, y1, x, y = parse_floats(4) + path.quadTo(x1, y1, x, y) + elif cmd == quadcurveto_rel: + x1, y1, x, y = parse_floats(4, x, y) + path.quadTo(x1, y1, x, y) + elif cmd == smoothquadcurveto_abs: + if last_cmd in (quadcurveto_abs, quadcurveto_rel, smoothquadcurveto_abs, smoothquadcurveto_rel): + x1 = 2 * x - x1 + y1 = 2 * y - y1 + else: + x1, y1 = x, y + x, y = parse_floats(2) + path.quadTo(x1, y1, x, y) + elif cmd == smoothquadcurveto_rel: + if last_cmd in (quadcurveto_abs, quadcurveto_rel, smoothquadcurveto_abs, smoothquadcurveto_rel): + x1 = 2 * x - x1 + y1 = 2 * y - y1 + else: + x1, y1 = x, y + x, y = parse_floats(2, x, y) + path.quadTo(x1, y1, x, y) + elif cmd in b'-.0123456789': + # A new number begins + # In this case, multiple parameters tuples are specified for the last command + # We rewind to reparse data correctly + pos[0] -= 1 + + # Handle extra parameters + if last_cmd == moveto_abs: + repeated_command = cmd = lineto_abs + elif last_cmd == moveto_rel: + repeated_command = cmd = lineto_rel + elif last_cmd in (closepath1, closepath2): + raise ValueError('Extra parameters after close path command') + elif last_cmd in ( + lineto_abs, lineto_rel, hline_abs, hline_rel, vline_abs, + vline_rel, curveto_abs, curveto_rel,smoothcurveto_abs, + smoothcurveto_rel, quadcurveto_abs, quadcurveto_rel, + smoothquadcurveto_abs, smoothquadcurveto_rel + ): + repeated_command = cmd = last_cmd + else: + raise ValueError('Unknown path command: %s' % cmd) + return path diff --git a/ebook_converter/utils/terminal.py b/ebook_converter/utils/terminal.py new file mode 100644 index 0000000..a436ef0 --- /dev/null +++ b/ebook_converter/utils/terminal.py @@ -0,0 +1,443 @@ +#!/usr/bin/env python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:fdm=marker:ai +from __future__ import absolute_import, division, print_function, unicode_literals + +__license__ = 'GPL v3' +__copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>' +__docformat__ = 'restructuredtext en' + +import os, sys, re + +from calibre.constants import iswindows, ispy3 +from polyglot.builtins import iteritems, range, zip, native_string_type + +if iswindows: + import ctypes.wintypes + + class CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure): + _fields_ = [ + ('dwSize', ctypes.wintypes._COORD), + ('dwCursorPosition', ctypes.wintypes._COORD), + ('wAttributes', ctypes.wintypes.WORD), + ('srWindow', ctypes.wintypes._SMALL_RECT), + ('dwMaximumWindowSize', ctypes.wintypes._COORD) + ] + + +def fmt(code): + return '\033[%dm' % code + + +RATTRIBUTES = dict( + zip(range(1, 9), ( + 'bold', + 'dark', + '', + 'underline', + 'blink', + '', + 'reverse', + 'concealed' + ) + )) +ATTRIBUTES = {v:fmt(k) for k, v in iteritems(RATTRIBUTES)} +del ATTRIBUTES[''] + +RBACKGROUNDS = dict( + zip(range(41, 48), ( + 'red', + 'green', + 'yellow', + 'blue', + 'magenta', + 'cyan', + 'white' + ), + )) +BACKGROUNDS = {v:fmt(k) for k, v in iteritems(RBACKGROUNDS)} + +RCOLORS = dict( + zip(range(31, 38), ( + 'red', + 'green', + 'yellow', + 'blue', + 'magenta', + 'cyan', + 'white', + ), + )) +COLORS = {v:fmt(k) for k, v in iteritems(RCOLORS)} + +RESET = fmt(0) + +if iswindows: + # From wincon.h + WCOLORS = {c:i for i, c in enumerate(( + 'black', 'blue', 'green', 'cyan', 'red', 'magenta', 'yellow', 'white'))} + + def to_flag(fg, bg, bold): + val = 0 + if bold: + val |= 0x08 + if fg in WCOLORS: + val |= WCOLORS[fg] + if bg in WCOLORS: + val |= (WCOLORS[bg] << 4) + return val + + +def colored(text, fg=None, bg=None, bold=False): + prefix = [] + if fg is not None: + prefix.append(COLORS[fg]) + if bg is not None: + prefix.append(BACKGROUNDS[bg]) + if bold: + prefix.append(ATTRIBUTES['bold']) + prefix = ''.join(prefix) + suffix = RESET + if isinstance(text, bytes): + prefix = prefix.encode('ascii') + suffix = suffix.encode('ascii') + return prefix + text + suffix + + +class Detect(object): + + def __init__(self, stream): + self.stream = stream or sys.stdout + self.isatty = getattr(self.stream, 'isatty', lambda : False)() + force_ansi = 'CALIBRE_FORCE_ANSI' in os.environ + if not self.isatty and force_ansi: + self.isatty = True + self.isansi = force_ansi or not iswindows + self.set_console = self.write_console = None + self.is_console = False + if not self.isansi: + try: + import msvcrt + self.msvcrt = msvcrt + self.file_handle = msvcrt.get_osfhandle(self.stream.fileno()) + from ctypes import windll, wintypes, byref, POINTER, WinDLL + mode = wintypes.DWORD(0) + f = windll.kernel32.GetConsoleMode + f.argtypes, f.restype = [wintypes.HANDLE, POINTER(wintypes.DWORD)], wintypes.BOOL + if f(self.file_handle, byref(mode)): + # Stream is a console + self.set_console = windll.kernel32.SetConsoleTextAttribute + self.default_console_text_attributes = WCOLORS['white'] + kernel32 = WinDLL(native_string_type('kernel32'), use_last_error=True) + self.write_console = kernel32.WriteConsoleW + self.write_console.argtypes = [wintypes.HANDLE, wintypes.c_wchar_p, wintypes.DWORD, POINTER(wintypes.DWORD), wintypes.LPVOID] + self.write_console.restype = wintypes.BOOL + kernel32.GetConsoleScreenBufferInfo.argtypes = [wintypes.HANDLE, ctypes.POINTER(CONSOLE_SCREEN_BUFFER_INFO)] + kernel32.GetConsoleScreenBufferInfo.restype = wintypes.BOOL + csbi = CONSOLE_SCREEN_BUFFER_INFO() + if kernel32.GetConsoleScreenBufferInfo(self.file_handle, byref(csbi)): + self.default_console_text_attributes = csbi.wAttributes + self.is_console = True + except: + pass + + def write_unicode_text(self, text, ignore_errors=False): + ' Windows only method that writes unicode strings correctly to the windows console using the Win32 API ' + if self.is_console: + from ctypes import wintypes, byref, c_wchar_p + written = wintypes.DWORD(0) + text = text.replace('\0', '') + chunk = len(text) + while text: + t, text = text[:chunk], text[chunk:] + wt = c_wchar_p(t) + if ispy3: + text_len = len(t.encode('utf-16')) + else: + # Use the fact that len(t) == wcslen(wt) in python 2.7 on + # windows where the python unicode type uses UTF-16 + text_len = len(t) + if not self.write_console(self.file_handle, wt, text_len, byref(written), None): + # Older versions of windows can fail to write large strings + # to console with WriteConsoleW (seen it happen on Win XP) + import winerror + err = ctypes.get_last_error() + if err == winerror.ERROR_NOT_ENOUGH_MEMORY and chunk >= 128: + # Retry with a smaller chunk size (give up if chunk < 128) + chunk = chunk // 2 + text = t + text + continue + if err == winerror.ERROR_GEN_FAILURE: + # On newer windows, this happens when trying to write + # non-ascii chars to the console and the console is set + # to use raster fonts (the default). In this case + # rather than failing, write an informative error + # message and the asciized version of the text. + print('Non-ASCII text detected. You must set your Console\'s font to' + ' Lucida Console or Consolas or some other TrueType font to see this text', file=self.stream, end=' -- ') + from calibre.utils.filenames import ascii_text + print(ascii_text(t + text), file=self.stream, end='') + continue + if not ignore_errors: + raise ctypes.WinError(err) + + +class ColoredStream(Detect): + + def __init__(self, stream=None, fg=None, bg=None, bold=False): + stream = getattr(stream, 'buffer', stream) + Detect.__init__(self, stream) + self.fg, self.bg, self.bold = fg, bg, bold + if self.set_console is not None: + self.wval = to_flag(self.fg, self.bg, bold) + if not self.bg: + self.wval |= self.default_console_text_attributes & 0xF0 + + def cwrite(self, what): + if not isinstance(what, bytes): + what = what.encode('ascii') + self.stream.write(what) + + def __enter__(self): + if not self.isatty: + return self + if self.isansi: + if self.bold: + self.cwrite(ATTRIBUTES['bold']) + if self.bg is not None: + self.cwrite(BACKGROUNDS[self.bg]) + if self.fg is not None: + self.cwrite(COLORS[self.fg]) + elif self.set_console is not None: + if self.wval != 0: + self.set_console(self.file_handle, self.wval) + return self + + def __exit__(self, *args, **kwargs): + if not self.isatty: + return + if not self.fg and not self.bg and not self.bold: + return + if self.isansi: + self.cwrite(RESET) + self.stream.flush() + elif self.set_console is not None: + self.set_console(self.file_handle, self.default_console_text_attributes) + + +class ANSIStream(Detect): + + ANSI_RE = r'\033\[((?:\d|;)*)([a-zA-Z])' + + def __init__(self, stream=None): + super(ANSIStream, self).__init__(stream) + self.encoding = getattr(self.stream, 'encoding', 'utf-8') or 'utf-8' + self.stream_takes_unicode = hasattr(self.stream, 'buffer') + self.last_state = (None, None, False) + self._ansi_re_bin = self._ansi_re_unicode = None + + def ansi_re(self, binary=False): + attr = '_ansi_re_bin' if binary else '_ansi_re_unicode' + ans = getattr(self, attr) + if ans is None: + expr = self.ANSI_RE + if binary: + expr = expr.encode('ascii') + ans = re.compile(expr) + setattr(self, attr, ans) + return ans + + def write(self, text): + if not self.isatty: + return self.strip_and_write(text) + + if self.isansi: + return self.stream.write(text) + + if not self.isansi and self.set_console is None: + return self.strip_and_write(text) + + self.write_and_convert(text) + + def polyglot_write(self, text): + binary = isinstance(text, bytes) + stream = self.stream + if self.stream_takes_unicode: + if binary: + stream = self.stream.buffer + else: + if not binary: + text = text.encode(self.encoding, 'replace') + stream.write(text) + + def strip_and_write(self, text): + binary = isinstance(text, bytes) + pat = self.ansi_re(binary) + repl = b'' if binary else '' + self.polyglot_write(pat.sub(repl, text)) + + def write_and_convert(self, text): + ''' + Write the given text to our wrapped stream, stripping any ANSI + sequences from the text, and optionally converting them into win32 + calls. + ''' + cursor = 0 + binary = isinstance(text, bytes) + for match in self.ansi_re(binary).finditer(text): + start, end = match.span() + self.write_plain_text(text, cursor, start) + self.convert_ansi(*match.groups()) + cursor = end + self.write_plain_text(text, cursor, len(text)) + self.set_console(self.file_handle, self.default_console_text_attributes) + self.stream.flush() + + def write_plain_text(self, text, start, end): + if start < end: + text = text[start:end] + if self.is_console and isinstance(text, bytes): + try: + utext = text.decode(self.encoding) + except ValueError: + pass + else: + return self.write_unicode_text(utext) + self.polyglot_write(text) + + def convert_ansi(self, paramstring, command): + if isinstance(paramstring, bytes): + paramstring = paramstring.decode('ascii', 'replace') + if isinstance(command, bytes): + command = command.decode('ascii', 'replace') + params = self.extract_params(paramstring) + self.call_win32(command, params) + + def extract_params(self, paramstring): + def split(paramstring): + for p in paramstring.split(';'): + if p: + yield int(p) + return tuple(split(paramstring)) + + def call_win32(self, command, params): + if command != 'm': + return + fg, bg, bold = self.last_state + + for param in params: + if param in RCOLORS: + fg = RCOLORS[param] + elif param in RBACKGROUNDS: + bg = RBACKGROUNDS[param] + elif param == 1: + bold = True + elif param == 0: + fg, bg, bold = None, None, False + + self.last_state = (fg, bg, bold) + if fg or bg or bold: + val = to_flag(fg, bg, bold) + if not bg: + val |= self.default_console_text_attributes & 0xF0 + self.set_console(self.file_handle, val) + else: + self.set_console(self.file_handle, self.default_console_text_attributes) + + +def windows_terminfo(): + from ctypes import Structure, byref + from ctypes.wintypes import SHORT, WORD + + class COORD(Structure): + + """struct in wincon.h""" + _fields_ = [ + ('X', SHORT), + ('Y', SHORT), + ] + + class SMALL_RECT(Structure): + + """struct in wincon.h.""" + _fields_ = [ + ("Left", SHORT), + ("Top", SHORT), + ("Right", SHORT), + ("Bottom", SHORT), + ] + + class CONSOLE_SCREEN_BUFFER_INFO(Structure): + + """struct in wincon.h.""" + _fields_ = [ + ("dwSize", COORD), + ("dwCursorPosition", COORD), + ("wAttributes", WORD), + ("srWindow", SMALL_RECT), + ("dwMaximumWindowSize", COORD), + ] + csbi = CONSOLE_SCREEN_BUFFER_INFO() + import msvcrt + file_handle = msvcrt.get_osfhandle(sys.stdout.fileno()) + from ctypes import windll + success = windll.kernel32.GetConsoleScreenBufferInfo(file_handle, + byref(csbi)) + if not success: + raise Exception('stdout is not a console?') + return csbi + + +def get_term_geometry(): + import fcntl, termios, struct + + def ioctl_GWINSZ(fd): + try: + return struct.unpack(b'HHHH', fcntl.ioctl(fd, termios.TIOCGWINSZ, b'\0'*8))[:2] + except Exception: + return None, None + + for f in (sys.stdin, sys.stdout, sys.stderr): + lines, cols = ioctl_GWINSZ(f.fileno()) + if lines is not None: + return lines, cols + try: + fd = os.open(os.ctermid(), os.O_RDONLY) + try: + lines, cols = ioctl_GWINSZ(fd) + if lines is not None: + return lines, cols + finally: + os.close(fd) + except Exception: + pass + return None, None + + +def geometry(): + if iswindows: + try: + + ti = windows_terminfo() + return (ti.dwSize.X or 80, ti.dwSize.Y or 25) + except: + return 80, 25 + else: + try: + lines, cols = get_term_geometry() + if lines is not None: + return cols, lines + except Exception: + pass + return 80, 25 + + +def test(): + s = ANSIStream() + + text = [colored(t, fg=t)+'. '+colored(t, fg=t, bold=True)+'.' for t in + ('red', 'yellow', 'green', 'white', 'cyan', 'magenta', 'blue',)] + s.write('\n'.join(text)) + u = u'\u041c\u0438\u0445\u0430\u0438\u043b fällen' + print() + s.write_unicode_text(u) + print() diff --git a/ebook_converter/utils/titlecase.py b/ebook_converter/utils/titlecase.py new file mode 100644 index 0000000..2450e37 --- /dev/null +++ b/ebook_converter/utils/titlecase.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +""" +Original Perl version by: John Gruber https://daringfireball.net/ 10 May 2008 +Python version by Stuart Colville http://muffinresearch.co.uk +Modifications to make it work with non-ascii chars by Kovid Goyal +License: http://www.opensource.org/licenses/mit-license.php +""" + +import re + +from calibre.utils.icu import capitalize, upper +from polyglot.builtins import unicode_type + +__all__ = ['titlecase'] +__version__ = '0.5' + +SMALL = 'a|an|and|as|at|but|by|en|for|if|in|of|on|or|the|to|v\\.?|via|vs\\.?' +PUNCT = r"""!"#$%&'‘’()*+,\-‒–—―./:;?@[\\\]_`{|}~""" + +SMALL_WORDS = re.compile(r'^(%s)$' % SMALL, re.I) +INLINE_PERIOD = re.compile(r'[a-z][.][a-z]', re.I) +UC_ELSEWHERE = re.compile(r'[%s]*?[a-zA-Z]+[A-Z]+?' % PUNCT) +CAPFIRST = re.compile(unicode_type(r"^[%s]*?(\w)" % PUNCT), flags=re.UNICODE) +SMALL_FIRST = re.compile(r'^([%s]*)(%s)\b' % (PUNCT, SMALL), re.I|re.U) +SMALL_LAST = re.compile(r'\b(%s)[%s]?$' % (SMALL, PUNCT), re.I|re.U) +SMALL_AFTER_NUM = re.compile(r'(\d+\s+)(a|an|the)\b', re.I|re.U) +SUBPHRASE = re.compile(r'([:.;?!][ ])(%s)' % SMALL) +APOS_SECOND = re.compile(r"^[dol]{1}['‘]{1}[a-z]+$", re.I) +UC_INITIALS = re.compile(r"^(?:[A-Z]{1}\.{1}|[A-Z]{1}\.{1}[A-Z]{1})+$") + +_lang = None + + +def lang(): + global _lang + if _lang is None: + from calibre.utils.localization import get_lang + _lang = get_lang().lower() + return _lang + + +def titlecase(text): + """ + Titlecases input text + + This filter changes all words to Title Caps, and attempts to be clever + about *un*capitalizing SMALL words like a/an/the in the input. + + The list of "SMALL words" which are not capped comes from + the New York Times Manual of Style, plus 'vs' and 'v'. + + """ + + all_caps = upper(text) == text + + pat = re.compile(r'(\s+)') + line = [] + for word in pat.split(text): + if not word: + continue + if pat.match(word) is not None: + line.append(word) + continue + if all_caps: + if UC_INITIALS.match(word): + line.append(word) + continue + else: + word = icu_lower(word) + + if APOS_SECOND.match(word): + word = word.replace(word[0], icu_upper(word[0]), 1) + word = word[:2] + icu_upper(word[2]) + word[3:] + line.append(word) + continue + if INLINE_PERIOD.search(word) or UC_ELSEWHERE.match(word): + line.append(word) + continue + if SMALL_WORDS.match(word): + line.append(icu_lower(word)) + continue + + hyphenated = [] + for item in word.split('-'): + hyphenated.append(CAPFIRST.sub(lambda m: icu_upper(m.group(0)), item)) + line.append("-".join(hyphenated)) + + result = "".join(line) + + result = SMALL_FIRST.sub(lambda m: '%s%s' % ( + m.group(1), + capitalize(m.group(2)) + ), result) + + result = SMALL_AFTER_NUM.sub(lambda m: '%s%s' % (m.group(1), + capitalize(m.group(2)) + ), result) + + result = SMALL_LAST.sub(lambda m: capitalize(m.group(0)), result) + + result = SUBPHRASE.sub(lambda m: '%s%s' % ( + m.group(1), + capitalize(m.group(2)) + ), result) + + return result diff --git a/ebook_converter/utils/wordcount.py b/ebook_converter/utils/wordcount.py new file mode 100644 index 0000000..86ba287 --- /dev/null +++ b/ebook_converter/utils/wordcount.py @@ -0,0 +1,95 @@ +#!/usr/bin/python2 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai + +from __future__ import absolute_import, division, print_function, unicode_literals + +""" +Get word, character, and Asian character counts + +1. Get a word count as a dictionary: + wc = get_wordcount(text) + words = wc['words'] # etc. + +2. Get a word count as an object + wc = get_wordcount_obj(text) + words = wc.words # etc. + +properties counted: + * characters + * chars_no_spaces + * asian_chars + * non_asian_words + * words + +Sourced from: +http://ginstrom.com/scribbles/2008/05/17/counting-words-etc-in-an-html-file-with-python/ +http://ginstrom.com/scribbles/2007/10/06/counting-words-characters-and-asian-characters-with-python/ +""" +__version__ = 0.1 +__author__ = "Ryan Ginstrom" + +IDEOGRAPHIC_SPACE = 0x3000 + + +def is_asian(char): + """Is the character Asian?""" + + # 0x3000 is ideographic space (i.e. double-byte space) + # Anything over is an Asian character + return ord(char) > IDEOGRAPHIC_SPACE + + +def filter_jchars(c): + """Filters Asian characters to spaces""" + if is_asian(c): + return ' ' + return c + + +def nonj_len(word): + """Returns number of non-Asian words in {word} + - 日本語AアジアンB -> 2 + - hello -> 1 + @param word: A word, possibly containing Asian characters + """ + # Here are the steps: + # 本spam日eggs + # -> [' ', 's', 'p', 'a', 'm', ' ', 'e', 'g', 'g', 's'] + # -> ' spam eggs' + # -> ['spam', 'eggs'] + # The length of which is 2! + chars = [filter_jchars(c) for c in word] + return len(''.join(chars).split()) + + +def get_wordcount(text): + """Get the word/character count for text + + @param text: The text of the segment + """ + + characters = len(text) + chars_no_spaces = sum(not x.isspace() for x in text) + asian_chars = sum(is_asian(x) for x in text) + non_asian_words = nonj_len(text) + words = non_asian_words + asian_chars + + return dict(characters=characters, + chars_no_spaces=chars_no_spaces, + asian_chars=asian_chars, + non_asian_words=non_asian_words, + words=words) + + +def dict2obj(dictionary): + """Transform a dictionary into an object""" + class Obj(object): + + def __init__(self, dictionary): + self.__dict__.update(dictionary) + return Obj(dictionary) + + +def get_wordcount_obj(text): + """Get the wordcount as an object rather than a dictionary""" + return dict2obj(get_wordcount(text)) diff --git a/ebook_converter/utils/xml_parse.py b/ebook_converter/utils/xml_parse.py new file mode 100644 index 0000000..aff73a6 --- /dev/null +++ b/ebook_converter/utils/xml_parse.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +# License: GPL v3 Copyright: 2019, Kovid Goyal <kovid at kovidgoyal.net> + +from __future__ import absolute_import, division, print_function, unicode_literals + +from lxml import etree + +# resolving of SYSTEM entities is turned off as entities can cause +# reads of local files, for example: +# <!DOCTYPE foo [ <!ENTITY passwd SYSTEM "file:///etc/passwd" >]> + +fs = etree.fromstring + + +class Resolver(etree.Resolver): + + def resolve(self, url, id, context): + return self.resolve_string('', context) + + +def create_parser(recover): + parser = etree.XMLParser(recover=recover, no_network=True) + parser.resolvers.add(Resolver()) + return parser + + +def safe_xml_fromstring(string_or_bytes, recover=True): + return fs(string_or_bytes, parser=create_parser(recover)) + + +def find_tests(): + import unittest, tempfile, os + + class TestXMLParse(unittest.TestCase): + + def setUp(self): + with tempfile.NamedTemporaryFile(delete=False) as tf: + tf.write(b'external') + self.temp_file = tf.name + + def tearDown(self): + os.remove(self.temp_file) + + def test_safe_xml_fromstring(self): + templ = '''<!DOCTYPE foo [ <!ENTITY e {id} "{val}" > ]><r>&e;</r>''' + external = 'file:///' + self.temp_file.replace(os.sep, '/') + self.assertEqual(etree.fromstring(templ.format(id='SYSTEM', val=external)).text, 'external') + for eid, val, expected in ( + ('', 'normal entity', 'normal entity'), + ('', external, external), + + ('SYSTEM', external, None), + ('SYSTEM', 'http://example.com', None), + + ('PUBLIC', external, None), + ('PUBLIC', 'http://example.com', None), + ): + got = getattr(safe_xml_fromstring(templ.format(id=eid, val=val)), 'text', None) + self.assertEqual(got, expected) + + return unittest.defaultTestLoader.loadTestsFromTestCase(TestXMLParse) + + +if __name__ == '__main__': + from calibre.utils.run_tests import run_tests + run_tests(find_tests) diff --git a/ebook_converter/utils/zipfile.py b/ebook_converter/utils/zipfile.py new file mode 100644 index 0000000..93034cb --- /dev/null +++ b/ebook_converter/utils/zipfile.py @@ -0,0 +1,1694 @@ +from __future__ import absolute_import, division, print_function, unicode_literals +""" +Read and write ZIP files. Modified by Kovid Goyal to support replacing files in +a zip archive, detecting filename encoding, updating zip files, etc. +""" +import struct, os, time, sys, shutil, stat, re, io +import binascii +from contextlib import closing +from tempfile import SpooledTemporaryFile + +from calibre import sanitize_file_name +from calibre.constants import filesystem_encoding +from calibre.ebooks.chardet import detect +from polyglot.builtins import unicode_type, string_or_bytes, getcwd, map, as_bytes + +try: + import zlib # We may need its compression method + crc32 = zlib.crc32 +except ImportError: + zlib = None + crc32 = binascii.crc32 + +__all__ = ["BadZipfile", "error", "ZIP_STORED", "ZIP_DEFLATED", "is_zipfile", + "ZipInfo", "ZipFile", "PyZipFile", "LargeZipFile"] + + +class BadZipfile(Exception): + pass + + +class LargeZipFile(Exception): + + """ + Raised when writing a zipfile, the zipfile requires ZIP64 extensions + and those extensions are disabled. + """ + + +error = BadZipfile # The exception raised by this module + +ZIP64_LIMIT = (1 << 31) - 1 +ZIP_FILECOUNT_LIMIT = (1 << 16) - 1 +ZIP_MAX_COMMENT = (1 << 16) - 1 + +# constants for Zip file compression methods +ZIP_STORED = 0 +ZIP_DEFLATED = 8 +# Other ZIP compression methods not supported +# For a list see: http://www.winzip.com/wz54.htm + +# Below are some formats and associated data for reading/writing headers using +# the struct module. The names and structures of headers/records are those used +# in the PKWARE description of the ZIP file format: +# http://www.pkware.com/documents/casestudies/APPNOTE.TXT +# (URL valid as of January 2008) + +# The "end of central directory" structure, magic number, size, and indices +# (section V.I in the format document) +structEndArchive = "<4s4H2LH" +stringEndArchive = b"PK\005\006" +sizeEndCentDir = struct.calcsize(structEndArchive) + +_ECD_SIGNATURE = 0 +_ECD_DISK_NUMBER = 1 +_ECD_DISK_START = 2 +_ECD_ENTRIES_THIS_DISK = 3 +_ECD_ENTRIES_TOTAL = 4 +_ECD_SIZE = 5 +_ECD_OFFSET = 6 +_ECD_COMMENT_SIZE = 7 +# These last two indices are not part of the structure as defined in the +# spec, but they are used internally by this module as a convenience +_ECD_COMMENT = 8 +_ECD_LOCATION = 9 + +# The "central directory" structure, magic number, size, and indices +# of entries in the structure (section V.F in the format document) +structCentralDir = "<4s4B4HL2L5H2L" +stringCentralDir = b"PK\001\002" +sizeCentralDir = struct.calcsize(structCentralDir) + +# indexes of entries in the central directory structure +_CD_SIGNATURE = 0 +_CD_CREATE_VERSION = 1 +_CD_CREATE_SYSTEM = 2 +_CD_EXTRACT_VERSION = 3 +_CD_EXTRACT_SYSTEM = 4 +_CD_FLAG_BITS = 5 +_CD_COMPRESS_TYPE = 6 +_CD_TIME = 7 +_CD_DATE = 8 +_CD_CRC = 9 +_CD_COMPRESSED_SIZE = 10 +_CD_UNCOMPRESSED_SIZE = 11 +_CD_FILENAME_LENGTH = 12 +_CD_EXTRA_FIELD_LENGTH = 13 +_CD_COMMENT_LENGTH = 14 +_CD_DISK_NUMBER_START = 15 +_CD_INTERNAL_FILE_ATTRIBUTES = 16 +_CD_EXTERNAL_FILE_ATTRIBUTES = 17 +_CD_LOCAL_HEADER_OFFSET = 18 + +# The "local file header" structure, magic number, size, and indices +# (section V.A in the format document) +structFileHeader = "<4s2B4HL2L2H" +stringFileHeader = b"PK\003\004" +sizeFileHeader = struct.calcsize(structFileHeader) + +_FH_SIGNATURE = 0 +_FH_EXTRACT_VERSION = 1 +_FH_EXTRACT_SYSTEM = 2 +_FH_GENERAL_PURPOSE_FLAG_BITS = 3 +_FH_COMPRESSION_METHOD = 4 +_FH_LAST_MOD_TIME = 5 +_FH_LAST_MOD_DATE = 6 +_FH_CRC = 7 +_FH_COMPRESSED_SIZE = 8 +_FH_UNCOMPRESSED_SIZE = 9 +_FH_FILENAME_LENGTH = 10 +_FH_EXTRA_FIELD_LENGTH = 11 + +# The "Zip64 end of central directory locator" structure, magic number, and size +structEndArchive64Locator = "<4sLQL" +stringEndArchive64Locator = b"PK\x06\x07" +sizeEndCentDir64Locator = struct.calcsize(structEndArchive64Locator) + +# The "Zip64 end of central directory" record, magic number, size, and indices +# (section V.G in the format document) +structEndArchive64 = "<4sQ2H2L4Q" +stringEndArchive64 = b"PK\x06\x06" +sizeEndCentDir64 = struct.calcsize(structEndArchive64) + +_CD64_SIGNATURE = 0 +_CD64_DIRECTORY_RECSIZE = 1 +_CD64_CREATE_VERSION = 2 +_CD64_EXTRACT_VERSION = 3 +_CD64_DISK_NUMBER = 4 +_CD64_DISK_NUMBER_START = 5 +_CD64_NUMBER_ENTRIES_THIS_DISK = 6 +_CD64_NUMBER_ENTRIES_TOTAL = 7 +_CD64_DIRECTORY_SIZE = 8 +_CD64_OFFSET_START_CENTDIR = 9 + + +def decode_arcname(name): + if not isinstance(name, unicode_type): + try: + name = name.decode('utf-8') + except Exception: + res = detect(name) + encoding = res['encoding'] + try: + name = name.decode(encoding) + except Exception: + name = name.decode('utf-8', 'replace') + return name + +# Added by Kovid to reset timestamp to default if it overflows the DOS +# limits + + +def fixtimevar(val): + if val < 0 or val > 0xffff: + val = 0 + return val + + +def _check_zipfile(fp): + try: + if _EndRecData(fp): + return True # file has correct magic number + except IOError: + pass + return False + + +def is_zipfile(filename): + """Quickly see if a file is a ZIP file by checking the magic number. + + The filename argument may be a file or file-like object too. + """ + result = False + try: + if hasattr(filename, "read"): + result = _check_zipfile(filename) + else: + with open(filename, "rb") as fp: + result = _check_zipfile(fp) + except IOError: + pass + return result + + +def _EndRecData64(fpin, offset, endrec): + """ + Read the ZIP64 end-of-archive records and use that to update endrec + """ + try: + fpin.seek(offset - sizeEndCentDir64Locator, 2) + except IOError: + # If the seek fails, the file is not large enough to contain a ZIP64 + # end-of-archive record, so just return the end record we were given. + return endrec + + data = fpin.read(sizeEndCentDir64Locator) + sig, diskno, reloff, disks = struct.unpack(structEndArchive64Locator, data) + if sig != stringEndArchive64Locator: + return endrec + + if diskno != 0 or disks != 1: + raise BadZipfile("zipfiles that span multiple disks are not supported") + + # Assume no 'zip64 extensible data' + fpin.seek(offset - sizeEndCentDir64Locator - sizeEndCentDir64, 2) + data = fpin.read(sizeEndCentDir64) + sig, sz, create_version, read_version, disk_num, disk_dir, \ + dircount, dircount2, dirsize, diroffset = \ + struct.unpack(structEndArchive64, data) + if sig != stringEndArchive64: + return endrec + + # Update the original endrec using data from the ZIP64 record + endrec[_ECD_SIGNATURE] = sig + endrec[_ECD_DISK_NUMBER] = disk_num + endrec[_ECD_DISK_START] = disk_dir + endrec[_ECD_ENTRIES_THIS_DISK] = dircount + endrec[_ECD_ENTRIES_TOTAL] = dircount2 + endrec[_ECD_SIZE] = dirsize + endrec[_ECD_OFFSET] = diroffset + return endrec + + +def _EndRecData(fpin): + """Return data from the "End of Central Directory" record, or None. + + The data is a list of the nine items in the ZIP "End of central dir" + record followed by a tenth item, the file seek offset of this record.""" + + # Determine file size + fpin.seek(0, 2) + filesize = fpin.tell() + + # Check to see if this is ZIP file with no archive comment (the + # "end of central directory" structure should be the last item in the + # file if this is the case). + try: + fpin.seek(-sizeEndCentDir, 2) + except IOError: + return None + data = fpin.read() + if data[0:4] == stringEndArchive and data[-2:] == b"\000\000": + # the signature is correct and there's no comment, unpack structure + endrec = struct.unpack(structEndArchive, data) + endrec=list(endrec) + + # Append a blank comment and record start offset + endrec.append(b"") + endrec.append(filesize - sizeEndCentDir) + + # Try to read the "Zip64 end of central directory" structure + return _EndRecData64(fpin, -sizeEndCentDir, endrec) + + # Either this is not a ZIP file, or it is a ZIP file with an archive + # comment. Search the end of the file for the "end of central directory" + # record signature. The comment is the last item in the ZIP file and may be + # up to 64K long. It is assumed that the "end of central directory" magic + # number does not appear in the comment. + maxCommentStart = max(filesize - (1 << 16) - sizeEndCentDir, 0) + fpin.seek(maxCommentStart, 0) + data = fpin.read() + start = data.rfind(stringEndArchive) + if start >= 0: + # found the magic number; attempt to unpack and interpret + recData = data[start:start+sizeEndCentDir] + endrec = list(struct.unpack(structEndArchive, recData)) + comment = data[start+sizeEndCentDir:] + # check that comment length is correct + # Kovid: Added == 0 check as some zip files apparently dont set this + if endrec[_ECD_COMMENT_SIZE] == 0 or endrec[_ECD_COMMENT_SIZE] == len(comment): + # Append the archive comment and start offset + endrec.append(comment) + endrec.append(maxCommentStart + start) + + # Try to read the "Zip64 end of central directory" structure + return _EndRecData64(fpin, maxCommentStart + start - filesize, + endrec) + + # Unable to find a valid end of central directory structure + return + + +class ZipInfo (object): + + """Class with attributes describing each file in the ZIP archive.""" + + __slots__ = ( + 'orig_filename', + 'filename', + 'date_time', + 'compress_type', + 'comment', + 'extra', + 'create_system', + 'create_version', + 'extract_version', + 'reserved', + 'flag_bits', + 'volume', + 'internal_attr', + 'external_attr', + 'header_offset', + 'CRC', + 'compress_size', + 'file_size', + '_raw_time', + 'file_offset', + ) + + def __init__(self, filename="NoName", date_time=(1980,1,1,0,0,0)): + self.orig_filename = filename # Original file name in archive + + # Terminate the file name at the first null byte. Null bytes in file + # names are used as tricks by viruses in archives. + null_byte = filename.find(b'\0' if isinstance(filename, bytes) else '\0') + if null_byte >= 0: + filename = filename[0:null_byte] + # This is used to ensure paths in generated ZIP files always use + # forward slashes as the directory separator, as required by the + # ZIP format specification. + if os.sep != '/': + os_sep, sep = os.sep, '/' + if isinstance(filename, bytes): + os_sep, sep = as_bytes(os_sep), b'/' + if os_sep in filename: + filename = filename.replace(os_sep, sep) + + self.filename = filename # Normalized file name + self.date_time = date_time # year, month, day, hour, min, sec + # Standard values: + self.compress_type = ZIP_STORED # Type of compression for the file + self.comment = b"" # Comment for each file + self.extra = b"" # ZIP extra data + if sys.platform == 'win32': + self.create_system = 0 # System which created ZIP archive + else: + # Assume everything else is unix-y + self.create_system = 3 # System which created ZIP archive + self.create_version = 20 # Version which created ZIP archive + self.extract_version = 20 # Version needed to extract archive + self.reserved = 0 # Must be zero + self.flag_bits = 0 # ZIP flag bits + self.volume = 0 # Volume number of file header + self.internal_attr = 0 # Internal attributes + self.external_attr = 0 # External file attributes + self.file_offset = 0 + # Other attributes are set by class ZipFile: + # header_offset Byte offset to the file header + # CRC CRC-32 of the uncompressed file + # compress_size Size of the compressed file + # file_size Size of the uncompressed file + + def FileHeader(self): + """Return the per-file header as a string.""" + dt = self.date_time + dosdate = (dt[0] - 1980) << 9 | dt[1] << 5 | dt[2] + dostime = dt[3] << 11 | dt[4] << 5 | (dt[5] // 2) + + if self.flag_bits & 0x08: + # Set these to zero because we write them after the file data + CRC = compress_size = file_size = 0 + else: + CRC = self.CRC + compress_size = self.compress_size + file_size = self.file_size + + extra = self.extra + + if file_size > ZIP64_LIMIT or compress_size > ZIP64_LIMIT: + # File is larger than what fits into a 4 byte integer, + # fall back to the ZIP64 extension + fmt = '<HHQQ' + extra = extra + struct.pack(fmt, + 1, struct.calcsize(fmt)-4, file_size, compress_size) + file_size = 0xffffffff + compress_size = 0xffffffff + self.extract_version = max(45, self.extract_version) + self.create_version = max(45, self.extract_version) + + filename, flag_bits = self._encodeFilenameFlags() + header = struct.pack(structFileHeader, stringFileHeader, + self.extract_version, self.reserved, flag_bits, + self.compress_type, fixtimevar(dostime), fixtimevar(dosdate), CRC, + compress_size, file_size, + len(filename), len(extra)) + return header + filename + extra + + def _encodeFilenameFlags(self): + if isinstance(self.filename, unicode_type): + return self.filename.encode('utf-8'), self.flag_bits | 0x800 + else: + return self.filename, self.flag_bits + + def _decodeFilename(self): + if self.flag_bits & 0x800: + return self.filename.decode('utf-8') + else: + return decode_arcname(self.filename) + + def _decodeExtra(self): + # Try to decode the extra field. + extra = self.extra + unpack = struct.unpack + while extra: + tp, ln = unpack('<HH', extra[:4]) + if tp == 1: + if ln >= 24: + counts = unpack('<QQQ', extra[4:28]) + elif ln == 16: + counts = unpack('<QQ', extra[4:20]) + elif ln == 8: + counts = unpack('<Q', extra[4:12]) + elif ln == 0: + counts = () + else: + raise RuntimeError("Corrupt extra field %s"%(ln,)) + + idx = 0 + + # ZIP64 extension (large files and/or large archives) + if self.file_size in (0xffffffffffffffff, 0xffffffff): + self.file_size = counts[idx] + idx += 1 + + if self.compress_size == 0xFFFFFFFF: + self.compress_size = counts[idx] + idx += 1 + + if self.header_offset == 0xffffffff: + self.header_offset = counts[idx] + idx+=1 + + extra = extra[ln+4:] + + +class _ZipDecrypter: + + """Class to handle decryption of files stored within a ZIP archive. + + ZIP supports a password-based form of encryption. Even though known + plaintext attacks have been found against it, it is still useful + to be able to get data out of such a file. + + Usage: + zd = _ZipDecrypter(mypwd) + plain_char = zd(cypher_char) + plain_text = map(zd, cypher_text) + """ + + def _GenerateCRCTable(): + """Generate a CRC-32 table. + + ZIP encryption uses the CRC32 one-byte primitive for scrambling some + internal keys. We noticed that a direct implementation is faster than + relying on binascii.crc32(). + """ + poly = 0xedb88320 + table = [0] * 256 + for i in range(256): + crc = i + for j in range(8): + if crc & 1: + crc = ((crc >> 1) & 0x7FFFFFFF) ^ poly + else: + crc = ((crc >> 1) & 0x7FFFFFFF) + table[i] = crc + return table + crctable = _GenerateCRCTable() + + def _crc32(self, ch, crc): + """Compute the CRC32 primitive on one byte.""" + return ((crc >> 8) & 0xffffff) ^ self.crctable[(crc ^ ch) & 0xff] + + def __init__(self, pwd): + self.key0 = 305419896 + self.key1 = 591751049 + self.key2 = 878082192 + for p in pwd: + self._UpdateKeys(p) + + def _UpdateKeys(self, c): + self.key0 = self._crc32(c, self.key0) + self.key1 = (self.key1 + (self.key0 & 255)) & 4294967295 + self.key1 = (self.key1 * 134775813 + 1) & 4294967295 + self.key2 = self._crc32(((self.key1 >> 24) & 255), self.key2) + + def __call__(self, c): + """Decrypt a single byte.""" + k = self.key2 | 2 + c = c ^ (((k * (k^1)) >> 8) & 255) + self._UpdateKeys(c) + return c + + +class ZipExtFile(io.BufferedIOBase): + + """File-like object for reading an archive member. + Is returned by ZipFile.open(). + """ + + # Max size supported by decompressor. + MAX_N = 1 << 31 - 1 + + # Read from compressed files in 4k blocks. + MIN_READ_SIZE = 4096 + + # Search for universal newlines or line chunks. + PATTERN = re.compile(br'^(?P<chunk>[^\r\n]+)|(?P<newline>\n|\r\n?)') + + def __init__(self, fileobj, mode, zipinfo, decrypter=None): + self._fileobj = fileobj + self._decrypter = decrypter + self._orig_pos = fileobj.tell() + + self._compress_type = zipinfo.compress_type + self._compress_size = zipinfo.compress_size + self._compress_left = zipinfo.compress_size + + if self._compress_type == ZIP_DEFLATED: + self._decompressor = zlib.decompressobj(-15) + self._unconsumed = b'' + + self._readbuffer = b'' + self._offset = 0 + + self._universal = 'U' in mode + self.newlines = None + + # Adjust read size for encrypted files since the first 12 bytes + # are for the encryption/password information. + if self._decrypter is not None: + self._compress_left -= 12 + + self.mode = mode + self.name = zipinfo.filename + + if hasattr(zipinfo, 'CRC'): + self._expected_crc = zipinfo.CRC + self._running_crc = crc32(b'') & 0xffffffff + else: + self._expected_crc = None + + def readline(self, limit=-1): + """Read and return a line from the stream. + + If limit is specified, at most limit bytes will be read. + """ + + if not self._universal and limit < 0: + # Shortcut common case - newline found in buffer. + i = self._readbuffer.find(b'\n', self._offset) + 1 + if i > 0: + line = self._readbuffer[self._offset: i] + self._offset = i + return line + + if not self._universal: + return io.BufferedIOBase.readline(self, limit) + + line = b'' + while limit < 0 or len(line) < limit: + readahead = self.peek(2) + if not readahead: + return line + + # + # Search for universal newlines or line chunks. + # + # The pattern returns either a line chunk or a newline, but not + # both. Combined with peek(2), we are assured that the sequence + # '\r\n' is always retrieved completely and never split into + # separate newlines - '\r', '\n' due to coincidental readaheads. + # + match = self.PATTERN.search(readahead) + newline = match.group('newline') + if newline is not None: + if self.newlines is None: + self.newlines = [] + if newline not in self.newlines: + self.newlines.append(newline) + self._offset += len(newline) + return line + b'\n' + + chunk = match.group('chunk') + if limit >= 0: + chunk = chunk[: limit - len(line)] + + self._offset += len(chunk) + line += chunk + + return line + + def peek(self, n=1): + """Returns buffered bytes without advancing the position.""" + if n > len(self._readbuffer) - self._offset: + chunk = self.read(n) + self._offset -= len(chunk) + + # Return up to 512 bytes to reduce allocation overhead for tight loops. + return self._readbuffer[self._offset: self._offset + 512] + + def readable(self): + return True + + def read(self, n=-1): + """Read and return up to n bytes. + If the argument is omitted, None, or negative, data is read and returned until EOF is reached.. + """ + buf = b'' + if n is None: + n = -1 + while True: + if n < 0: + data = self.read1(n) + elif n > len(buf): + data = self.read1(n - len(buf)) + else: + return buf + if len(data) == 0: + return buf + buf += data + + def _update_crc(self, newdata, eof): + # Update the CRC using the given data. + if self._expected_crc is None: + # No need to compute the CRC if we don't have a reference value + return + self._running_crc = crc32(newdata, self._running_crc) & 0xffffffff + # Check the CRC if we're at the end of the file + if eof and self._running_crc != self._expected_crc: + raise BadZipfile("Bad CRC-32 for file %r" % self.name) + + def read1(self, n): + """Read up to n bytes with at most one read() system call.""" + + # Simplify algorithm (branching) by transforming negative n to large n. + if n < 0 or n is None: + n = self.MAX_N + + # Bytes available in read buffer. + len_readbuffer = len(self._readbuffer) - self._offset + + # Read from file. + if self._compress_left > 0 and n > len_readbuffer + len(self._unconsumed): + nbytes = n - len_readbuffer - len(self._unconsumed) + nbytes = max(nbytes, self.MIN_READ_SIZE) + nbytes = min(nbytes, self._compress_left) + + data = self._fileobj.read(nbytes) + self._compress_left -= len(data) + + if data and self._decrypter is not None: + data = b''.join(bytes(bytearray(map(self._decrypter, bytearray(data))))) + + if self._compress_type == ZIP_STORED: + self._update_crc(data, eof=(self._compress_left==0)) + self._readbuffer = self._readbuffer[self._offset:] + data + self._offset = 0 + else: + # Prepare deflated bytes for decompression. + self._unconsumed += data + + # Handle unconsumed data. + if (len(self._unconsumed) > 0 and n > len_readbuffer and + self._compress_type == ZIP_DEFLATED): + data = self._decompressor.decompress( + self._unconsumed, + max(n - len_readbuffer, self.MIN_READ_SIZE) + ) + + self._unconsumed = self._decompressor.unconsumed_tail + eof = len(self._unconsumed) == 0 and self._compress_left == 0 + if eof: + data += self._decompressor.flush() + + self._update_crc(data, eof=eof) + self._readbuffer = self._readbuffer[self._offset:] + data + self._offset = 0 + + # Read from buffer. + data = self._readbuffer[self._offset: self._offset + n] + self._offset += len(data) + return data + + def read_raw(self): + pos = self._fileobj.tell() + self._fileobj.seek(self._orig_pos) + bytes_to_read = self._compress_size + if self._decrypter is not None: + bytes_to_read -= 12 + raw = b'' + + if bytes_to_read > 0: + raw = self._fileobj.read(bytes_to_read) + self._fileobj.seek(pos) + return raw + + +class ZipFile: + + """ Class with methods to open, read, write, close, list and update zip files. + + z = ZipFile(file, mode="r", compression=ZIP_STORED, allowZip64=False) + + file: Either the path to the file, or a file-like object. + If it is a path, the file will be opened and closed by ZipFile. + mode: The mode can be either read "r", write "w" or append "a". + compression: ZIP_STORED (no compression) or ZIP_DEFLATED (requires zlib). + allowZip64: if True ZipFile will create files with ZIP64 extensions when + needed, otherwise it will raise an exception when this would + be necessary. + + """ + + fp = None # Set here since __del__ checks it + + def __init__(self, file, mode="r", compression=ZIP_DEFLATED, allowZip64=True): + """Open the ZIP file with mode read "r", write "w" or append "a".""" + if mode not in ("r", "w", "a"): + raise RuntimeError('ZipFile() requires mode "r", "w", or "a" not %s'%mode) + + if compression == ZIP_STORED: + pass + elif compression == ZIP_DEFLATED: + if not zlib: + raise RuntimeError( + "Compression requires the (missing) zlib module") + else: + raise RuntimeError("The compression method %s is not supported" % compression) + + self._allowZip64 = allowZip64 + self._didModify = False + self.debug = 0 # Level of printing: 0 through 3 + self.NameToInfo = {} # Find file info given name + self.filelist = [] # List of ZipInfo instances for archive + self.extract_mapping = {} + self.compression = compression # Method of compression + self.mode = key = mode.replace('b', '')[0] + self.pwd = None + self.comment = b'' + + # Check if we were passed a file-like object + if isinstance(file, string_or_bytes): + self._filePassed = 0 + self.filename = file + modeDict = {'r' : 'rb', 'w': 'wb', 'a' : 'r+b'} + try: + self.fp = open(file, modeDict[mode]) + except IOError: + if mode == 'a': + mode = key = 'w' + self.fp = open(file, modeDict[mode]) + else: + raise + else: + self._filePassed = 1 + self.fp = file + self.filename = getattr(file, 'name', None) + + if key == 'r': + self._GetContents() + elif key == 'w': + # set the modified flag so central directory gets written + # even if no files are added to the archive + self._didModify = True + elif key == 'a': + try: + # See if file is a zip file + self._RealGetContents() + self._calculate_file_offsets() + # seek to start of directory and overwrite + self.fp.seek(self.start_dir, 0) + except BadZipfile: + # file is not a zip file, just append + self.fp.seek(0, 2) + + # set the modified flag so central directory gets written + # even if no files are added to the archive + self._didModify = True + else: + if not self._filePassed: + self.fp.close() + self.fp = None + raise RuntimeError('Mode must be "r", "w" or "a"') + + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + self.close() + + def _GetContents(self): + """Read the directory, making sure we close the file if the format + is bad.""" + try: + self._RealGetContents() + except BadZipfile: + if not self._filePassed: + self.fp.close() + self.fp = None + raise + + def _RealGetContents(self): + """Read in the table of contents for the ZIP file.""" + fp = self.fp + try: + endrec = _EndRecData(fp) + except IOError: + raise BadZipfile("File is not a zip file") + if not endrec: + raise BadZipfile("File is not a zip file") + if self.debug > 1: + print(endrec) + size_cd = endrec[_ECD_SIZE] # bytes in central directory + offset_cd = endrec[_ECD_OFFSET] # offset of central directory + self.comment = endrec[_ECD_COMMENT] # archive comment + + # "concat" is zero, unless zip was concatenated to another file + concat = endrec[_ECD_LOCATION] - size_cd - offset_cd + if endrec[_ECD_SIGNATURE] == stringEndArchive64: + # If Zip64 extension structures are present, account for them + concat -= (sizeEndCentDir64 + sizeEndCentDir64Locator) + + if self.debug > 2: + inferred = concat + offset_cd + print("given, inferred, offset", offset_cd, inferred, concat) + # self.start_dir: Position of start of central directory + self.start_dir = offset_cd + concat + fp.seek(self.start_dir, 0) + data = fp.read(size_cd) + fp = io.BytesIO(data) + total = 0 + while total < size_cd: + centdir = fp.read(sizeCentralDir) + if centdir[0:4] != stringCentralDir: + raise BadZipfile("Bad magic number for central directory") + centdir = struct.unpack(structCentralDir, centdir) + if self.debug > 2: + print(centdir) + filename = fp.read(centdir[_CD_FILENAME_LENGTH]) + # Create ZipInfo instance to store file information + x = ZipInfo(filename) + x.extra = fp.read(centdir[_CD_EXTRA_FIELD_LENGTH]) + x.comment = fp.read(centdir[_CD_COMMENT_LENGTH]) + x.header_offset = centdir[_CD_LOCAL_HEADER_OFFSET] + (x.create_version, x.create_system, x.extract_version, x.reserved, + x.flag_bits, x.compress_type, t, d, + x.CRC, x.compress_size, x.file_size) = centdir[1:12] + x.volume, x.internal_attr, x.external_attr = centdir[15:18] + # Convert date/time code to (year, month, day, hour, min, sec) + x._raw_time = t + x.date_time = ((d>>9)+1980, (d>>5)&0xF, d&0x1F, + t>>11, (t>>5)&0x3F, (t&0x1F) * 2) + + x._decodeExtra() + x.header_offset = x.header_offset + concat + x.filename = x._decodeFilename() + self.filelist.append(x) + self.NameToInfo[x.filename] = x + + # update total bytes read from central directory + total = (total + sizeCentralDir + centdir[_CD_FILENAME_LENGTH] + + centdir[_CD_EXTRA_FIELD_LENGTH] + + centdir[_CD_COMMENT_LENGTH]) + + if self.debug > 2: + print("total", total) + + def _calculate_file_offsets(self): + for zip_info in self.filelist: + self.fp.seek(zip_info.header_offset, 0) + fheader = self.fp.read(30) + if fheader[0:4] != stringFileHeader: + raise BadZipfile("Bad magic number for file header") + fheader = struct.unpack(structFileHeader, fheader) + # file_offset is computed here, since the extra field for + # the central directory and for the local file header + # refer to different fields, and they can have different + # lengths + file_offset = (zip_info.header_offset + 30 + + fheader[_FH_FILENAME_LENGTH] + + fheader[_FH_EXTRA_FIELD_LENGTH]) + fname = self.fp.read(fheader[_FH_FILENAME_LENGTH]) + if fname != zip_info.orig_filename: + raise RuntimeError( + 'File name in directory "%s" and header "%s" differ.' % ( + zip_info.orig_filename, fname)) + + zip_info.file_offset = file_offset + + def replace(self, filename, arcname=None, compress_type=None): + """Delete arcname, and put the bytes from filename into the + archive under the name arcname.""" + deleteName = arcname + if deleteName is None: + deleteName = filename + self.delete(deleteName) + self.write(filename, arcname, compress_type) + + def replacestr(self, zinfo, byts): + """Delete zinfo.filename, and write a new file into the archive. The + contents is the string 'bytes'.""" + self.delete(zinfo.filename) + self.writestr(zinfo, byts) + + def delete(self, name): + """Delete the file from the archive. If it appears multiple + times only the first instance will be deleted.""" + for i in range(0, len(self.filelist)): + if self.filelist[i].filename == name: + if self.debug: + print("Removing", name) + deleted_offset = self.filelist[i].header_offset + deleted_size = (self.filelist[i].file_offset - self.filelist[i].header_offset) + self.filelist[i].compress_size + zinfo_size = struct.calcsize(structCentralDir) + len(self.filelist[i].filename) + len(self.filelist[i].extra) + # Remove the file's data from the archive. + current_offset = self.fp.tell() + self.fp.seek(0, 2) + archive_size = self.fp.tell() + self.fp.seek(deleted_offset + deleted_size) + buf = self.fp.read() + self.fp.seek(deleted_offset) + self.fp.write(buf) + self.fp.truncate(archive_size - deleted_size - zinfo_size) + if current_offset > deleted_offset + deleted_size: + current_offset -= deleted_size + elif current_offset > deleted_offset: + current_offset = deleted_offset + self.fp.seek(current_offset, 0) + # Remove file from central directory. + del self.filelist[i] + # Adjust the remaining offsets in the central directory. + for j in range(i, len(self.filelist)): + if self.filelist[j].header_offset > deleted_offset: + self.filelist[j].header_offset -= deleted_size + if self.filelist[j].file_offset > deleted_offset: + self.filelist[j].file_offset -= deleted_size + self._didModify = True + return + if self.debug: + print(name, "not in archive") + + def namelist(self): + """Return a list of file names in the archive.""" + l = [] + for data in self.filelist: + l.append(data.filename) + return l + + def infolist(self): + """Return a list of class ZipInfo instances for files in the + archive.""" + return self.filelist + + def printdir(self): + """Print a table of contents for the zip file.""" + print("%-46s %19s %12s" % ("File Name", "Modified ", "Size")) + for zinfo in self.filelist: + date = "%d-%02d-%02d %02d:%02d:%02d" % zinfo.date_time[:6] + print("%-46s %s %12d" % (zinfo.filename, date, zinfo.file_size)) + + def testzip(self): + """Read all the files and check the CRC.""" + chunk_size = 2 ** 20 + for zinfo in self.filelist: + try: + # Read by chunks, to avoid an OverflowError or a + # MemoryError with very large embedded files. + f = self.open(zinfo.filename, "r") + while f.read(chunk_size): # Check CRC-32 + pass + except BadZipfile: + return zinfo.filename + + def getinfo(self, name): + """Return the instance of ZipInfo given 'name'.""" + info = self.NameToInfo.get(name) + if info is None: + raise KeyError( + 'There is no item named %r in the archive' % name) + + return info + + def setpassword(self, pwd): + """Set default password for encrypted files.""" + self.pwd = pwd + + def read(self, name, pwd=None): + """Return file bytes (as a string) for name.""" + return self.open(name, "r", pwd).read() + + def read_raw(self, name, mode="r", pwd=None): + """Return the raw bytes in the zipfile corresponding to name.""" + zef = self.open(name, mode=mode, pwd=pwd) + return zef.read_raw() + + def open(self, name, mode="r", pwd=None): + """Return file-like object for 'name'.""" + if mode not in ("r", "U", "rU"): + raise RuntimeError('open() requires mode "r", "U", or "rU"') + if not self.fp: + raise RuntimeError( + "Attempt to read ZIP archive that was already closed") + + # Only open a new file for instances where we were not + # given a file object in the constructor + if self._filePassed: + zef_file = self.fp + else: + zef_file = open(self.filename, 'rb') + + # Make sure we have an info object + if isinstance(name, ZipInfo): + # 'name' is already an info object + zinfo = name + else: + # Get info object for name + zinfo = self.getinfo(name) + + zef_file.seek(zinfo.header_offset, 0) + + # Skip the file header: + fheader = zef_file.read(sizeFileHeader) + if fheader[0:4] != stringFileHeader: + raise BadZipfile("Bad magic number for file header") + + fheader = struct.unpack(structFileHeader, fheader) + fname = zef_file.read(fheader[_FH_FILENAME_LENGTH]) + if fheader[_FH_EXTRA_FIELD_LENGTH]: + zef_file.read(fheader[_FH_EXTRA_FIELD_LENGTH]) + + if fname != zinfo.orig_filename: + print(('WARNING: Header (%r) and directory (%r) filenames do not' + ' match inside ZipFile')%(fname, zinfo.orig_filename)) + print('Using directory filename %r'%zinfo.orig_filename) + # raise BadZipfile, \ + # 'File name in directory "%r" and header "%r" differ.' % ( + # zinfo.orig_filename, fname) + + # check for encrypted flag & handle password + is_encrypted = zinfo.flag_bits & 0x1 + zd = None + if is_encrypted: + if not pwd: + pwd = self.pwd + if not pwd: + raise RuntimeError(("File %s is encrypted, " + "password required for extraction") % name) + + zd = _ZipDecrypter(pwd) + # The first 12 bytes in the cypher stream is an encryption header + # used to strengthen the algorithm. The first 11 bytes are + # completely random, while the 12th contains the MSB of the CRC, + # or the MSB of the file time depending on the header type + # and is used to check the correctness of the password. + byts = zef_file.read(12) + h = list(map(zd, bytearray(byts[0:12]))) + if zinfo.flag_bits & 0x8: + # compare against the file type from extended local headers + check_byte = (zinfo._raw_time >> 8) & 0xff + else: + # compare against the CRC otherwise + check_byte = (zinfo.CRC >> 24) & 0xff + if h[11] != check_byte: + raise RuntimeError("Bad password for file", name) + + return ZipExtFile(zef_file, mode, zinfo, zd) + + def extract(self, member, path=None, pwd=None): + """Extract a member from the archive to the current working directory, + using its full name. Its file information is extracted as accurately + as possible. `member' may be a filename or a ZipInfo object. You can + specify a different directory using `path'. + """ + if not isinstance(member, ZipInfo): + member = self.getinfo(member) + + if path is None: + path = getcwd() + + return self._extract_member(member, path, pwd) + + def extractall(self, path=None, members=None, pwd=None): + """Extract all members from the archive to the current working + directory. `path' specifies a different directory to extract to. + `members' is optional and must be a subset of the list returned + by namelist(). + """ + if members is None: + members = self.namelist() + + # Kovid: Extract longer names first, just in case the zip file has + # an entry for a directory without a trailing slash + members.sort(key=len, reverse=True) + + for zipinfo in members: + self.extract(zipinfo, path, pwd) + + def _extract_member(self, member, targetpath, pwd): + """Extract the ZipInfo object 'member' to a physical + file on the path targetpath. + """ + # build the destination pathname, replacing + # forward slashes to platform specific separators. + # Strip trailing path separator, unless it represents the root. + if (targetpath[-1:] in (os.path.sep, os.path.altsep) and + len(os.path.splitdrive(targetpath)[1]) > 1): + targetpath = targetpath[:-1] + + base_target = targetpath # Added by Kovid + + # Sanitize path, changing absolute paths to relative paths + # and removing .. and . (changed by Kovid) + fname = member.filename.replace(os.sep, '/') + fname = os.path.splitdrive(fname)[1] + fname = '/'.join(x for x in fname.split('/') if x not in {'', os.path.curdir, os.path.pardir}) + if not fname: + raise BadZipfile('The member %r has an invalid name'%member.filename) + + targetpath = os.path.normpath(os.path.join(base_target, fname)) + # Added by Kovid as normpath fails to convert forward slashes for UNC + # paths, i.e. paths of the form \\?\C:\some/path + if os.sep != '/': + targetpath = targetpath.replace('/', os.sep) + + # Create all upper directories if necessary. + upperdirs = os.path.dirname(targetpath) + if upperdirs and not os.path.exists(upperdirs): + try: + os.makedirs(upperdirs) + except: # Added by Kovid + targetpath = os.path.join(base_target, + sanitize_file_name(fname)) + upperdirs = os.path.dirname(targetpath) + if upperdirs and not os.path.exists(upperdirs): + os.makedirs(upperdirs) + + if member.filename[-1] == '/': + if not os.path.isdir(targetpath): + os.mkdir(targetpath) + self.extract_mapping[member.filename] = targetpath + return targetpath + + if not os.path.exists(targetpath): + # Kovid: Could be a previously automatically created directory + # in which case it is ignored + with closing(self.open(member, pwd=pwd)) as source: + try: + with open(targetpath, 'wb') as target: + shutil.copyfileobj(source, target) + except: + # Try sanitizing the file name to remove invalid characters + components = list(os.path.split(targetpath)) + components[-1] = sanitize_file_name(components[-1]) + targetpath = os.sep.join(components) + with open(targetpath, 'wb') as target: + shutil.copyfileobj(source, target) + # Kovid: Try to preserve the timestamps in the ZIP file + try: + mtime = time.localtime() + mtime = time.mktime(member.date_time + (0, 0) + (mtime.tm_isdst,)) + os.utime(targetpath, (mtime, mtime)) + except: + pass + self.extract_mapping[member.filename] = targetpath + return targetpath + + def _writecheck(self, zinfo): + """Check for errors before writing a file to the archive.""" + if zinfo.filename in self.NameToInfo: + if self.debug: # Warning for duplicate names + print("Duplicate name:", zinfo.filename) + if self.mode not in ("w", "a"): + raise RuntimeError('write() requires mode "w" or "a"') + if not self.fp: + raise RuntimeError( + "Attempt to write ZIP archive that was already closed") + if zinfo.compress_type == ZIP_DEFLATED and not zlib: + raise RuntimeError( + "Compression requires the (missing) zlib module") + if zinfo.compress_type not in (ZIP_STORED, ZIP_DEFLATED): + raise RuntimeError( + "The compression method %s is not supported" % zinfo.compress_type) + if zinfo.file_size > ZIP64_LIMIT: + if not self._allowZip64: + raise LargeZipFile("Filesize would require ZIP64 extensions") + if zinfo.header_offset > ZIP64_LIMIT: + if not self._allowZip64: + raise LargeZipFile("Zipfile size would require ZIP64 extensions") + + def write(self, filename, arcname=None, compress_type=None): + """Put the bytes from filename into the archive under the name + arcname.""" + if not self.fp: + raise RuntimeError( + "Attempt to write to ZIP archive that was already closed") + + st = os.stat(filename) + isdir = stat.S_ISDIR(st.st_mode) + mtime = time.localtime(st.st_mtime) + date_time = mtime[0:6] + # Create ZipInfo instance to store file information + if arcname is None: + arcname = filename + arcname = os.path.normpath(os.path.splitdrive(arcname)[1]) + while arcname[0] in (os.sep, os.altsep): + arcname = arcname[1:] + if not isinstance(arcname, unicode_type): + arcname = arcname.decode(filesystem_encoding) + if isdir and not arcname.endswith('/'): + arcname += '/' + zinfo = ZipInfo(arcname, date_time) + zinfo.external_attr = (st[0] & 0xFFFF) << 16 # Unix attributes + if isdir: + zinfo.compress_type = ZIP_STORED + if compress_type is None: + zinfo.compress_type = self.compression + else: + zinfo.compress_type = compress_type + + zinfo.file_size = st.st_size + zinfo.flag_bits = 0x00 + zinfo.header_offset = self.fp.tell() # Start of header bytes + + self._writecheck(zinfo) + self._didModify = True + + if isdir: + zinfo.file_size = 0 + zinfo.compress_size = 0 + zinfo.CRC = 0 + self.filelist.append(zinfo) + self.NameToInfo[zinfo.filename] = zinfo + self.fp.write(zinfo.FileHeader()) + return + + with open(filename, "rb") as fp: + # Must overwrite CRC and sizes with correct data later + zinfo.CRC = CRC = 0 + zinfo.compress_size = compress_size = 0 + zinfo.file_size = file_size = 0 + self.fp.write(zinfo.FileHeader()) + if zinfo.compress_type == ZIP_DEFLATED: + cmpr = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION, + zlib.DEFLATED, -15) + else: + cmpr = None + while 1: + buf = fp.read(1024 * 8) + if not buf: + break + file_size = file_size + len(buf) + CRC = crc32(buf, CRC) & 0xffffffff + if cmpr: + buf = cmpr.compress(buf) + compress_size = compress_size + len(buf) + self.fp.write(buf) + if cmpr: + buf = cmpr.flush() + compress_size = compress_size + len(buf) + self.fp.write(buf) + zinfo.compress_size = compress_size + else: + zinfo.compress_size = file_size + zinfo.CRC = CRC + zinfo.file_size = file_size + # Seek backwards and write CRC and file sizes + position = self.fp.tell() # Preserve current position in file + self.fp.seek(zinfo.header_offset + 14, 0) + self.fp.write(struct.pack("<LLL", zinfo.CRC, zinfo.compress_size, + zinfo.file_size)) + self.fp.seek(position, 0) + self.filelist.append(zinfo) + self.NameToInfo[zinfo.filename] = zinfo + + def writestr(self, zinfo_or_arcname, byts, permissions=0o600, + compression=ZIP_DEFLATED, raw_bytes=False): + """Write a file into the archive. The contents is the string + 'byts'. 'zinfo_or_arcname' is either a ZipInfo instance or + the name of the file in the archive.""" + assert not raw_bytes or (raw_bytes and + isinstance(zinfo_or_arcname, ZipInfo)) + if not isinstance(byts, bytes): + byts = byts.encode('utf-8') + if not isinstance(zinfo_or_arcname, ZipInfo): + if not isinstance(zinfo_or_arcname, unicode_type): + zinfo_or_arcname = zinfo_or_arcname.decode(filesystem_encoding) + zinfo = ZipInfo(filename=zinfo_or_arcname, + date_time=time.localtime(time.time())[:6]) + zinfo.compress_type = compression + zinfo.external_attr = permissions << 16 + else: + zinfo = zinfo_or_arcname + + if not self.fp: + raise RuntimeError( + "Attempt to write to ZIP archive that was already closed") + + if not raw_bytes: + zinfo.file_size = len(byts) # Uncompressed size + zinfo.header_offset = self.fp.tell() # Start of header bytes + self._writecheck(zinfo) + self._didModify = True + if not raw_bytes: + zinfo.CRC = crc32(byts) & 0xffffffff # CRC-32 checksum + if zinfo.compress_type == ZIP_DEFLATED: + co = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION, + zlib.DEFLATED, -15) + byts = co.compress(byts) + co.flush() + zinfo.compress_size = len(byts) # Compressed size + else: + zinfo.compress_size = zinfo.file_size + zinfo.header_offset = self.fp.tell() # Start of header bytes + self.fp.write(zinfo.FileHeader()) + self.fp.write(byts) + self.fp.flush() + if zinfo.flag_bits & 0x08: + # Write CRC and file sizes after the file data + self.fp.write(struct.pack("<LLL", zinfo.CRC, zinfo.compress_size, + zinfo.file_size)) + self.filelist.append(zinfo) + self.NameToInfo[zinfo.filename] = zinfo + + def add_dir(self, path, prefix='', simple_filter=lambda x:False): + ''' + Add a directory recursively to the zip file with an optional prefix. + ''' + if prefix: + self.writestr(prefix+'/', b'', 0o755) + fp = (prefix + ('/' if prefix else '')).replace('//', '/') + for f in os.listdir(path): + if simple_filter(f): # Added by Kovid + continue + arcname = fp + f + f = os.path.join(path, f) + if os.path.isdir(f): + self.add_dir(f, prefix=arcname, simple_filter=simple_filter) + else: + self.write(f, arcname) + + def __del__(self): + """Call the "close()" method in case the user forgot.""" + self.close() + + def close(self): + """Close the file, and for mode "w" and "a" write the ending + records.""" + if self.fp is None: + return + + if self.mode in ("w", "a") and self._didModify: # write ending records + count = 0 + pos1 = self.fp.tell() + for zinfo in self.filelist: # write central directory + count = count + 1 + dt = zinfo.date_time + dosdate = fixtimevar((dt[0] - 1980) << 9 | dt[1] << 5 | dt[2]) + dostime = fixtimevar(dt[3] << 11 | dt[4] << 5 | (dt[5] // 2)) + extra = [] + if zinfo.file_size > ZIP64_LIMIT \ + or zinfo.compress_size > ZIP64_LIMIT: + extra.append(zinfo.file_size) + extra.append(zinfo.compress_size) + file_size = 0xffffffff + compress_size = 0xffffffff + else: + file_size = zinfo.file_size + compress_size = zinfo.compress_size + + if zinfo.header_offset > ZIP64_LIMIT: + extra.append(zinfo.header_offset) + header_offset = 0xffffffff + else: + header_offset = zinfo.header_offset + + extra_data = zinfo.extra + if extra: + # Append a ZIP64 field to the extra's + extra_data = struct.pack( + '<HH' + 'Q'*len(extra), + 1, 8*len(extra), *extra) + extra_data + + extract_version = max(45, zinfo.extract_version) + create_version = max(45, zinfo.create_version) + else: + extract_version = zinfo.extract_version + create_version = zinfo.create_version + + try: + filename, flag_bits = zinfo._encodeFilenameFlags() + centdir = struct.pack(structCentralDir, + stringCentralDir, create_version, + zinfo.create_system, extract_version, zinfo.reserved, + flag_bits, zinfo.compress_type, dostime, dosdate, + zinfo.CRC, compress_size, file_size, + len(filename), len(extra_data), len(zinfo.comment), + 0, zinfo.internal_attr, zinfo.external_attr, + header_offset) + except DeprecationWarning: + print((structCentralDir, + stringCentralDir, create_version, + zinfo.create_system, extract_version, zinfo.reserved, + zinfo.flag_bits, zinfo.compress_type, dostime, dosdate, + zinfo.CRC, compress_size, file_size, + len(zinfo.filename), len(extra_data), len(zinfo.comment), + 0, zinfo.internal_attr, zinfo.external_attr, + header_offset), file=sys.stderr) + raise + self.fp.write(centdir) + self.fp.write(filename) + self.fp.write(extra_data) + self.fp.write(zinfo.comment) + + pos2 = self.fp.tell() + # Write end-of-zip-archive record + centDirCount = count + centDirSize = pos2 - pos1 + centDirOffset = pos1 + if (centDirCount >= ZIP_FILECOUNT_LIMIT or + centDirOffset > ZIP64_LIMIT or + centDirSize > ZIP64_LIMIT): + # Need to write the ZIP64 end-of-archive records + zip64endrec = struct.pack( + structEndArchive64, stringEndArchive64, + 44, 45, 45, 0, 0, centDirCount, centDirCount, + centDirSize, centDirOffset) + self.fp.write(zip64endrec) + + zip64locrec = struct.pack( + structEndArchive64Locator, + stringEndArchive64Locator, 0, pos2, 1) + self.fp.write(zip64locrec) + centDirCount = min(centDirCount, 0xFFFF) + centDirSize = min(centDirSize, 0xFFFFFFFF) + centDirOffset = min(centDirOffset, 0xFFFFFFFF) + + # check for valid comment length + if len(self.comment) >= ZIP_MAX_COMMENT: + if self.debug > 0: + msg = 'Archive comment is too long; truncating to %d bytes' \ + % ZIP_MAX_COMMENT + print(msg) + self.comment = self.comment[:ZIP_MAX_COMMENT] + + endrec = struct.pack(structEndArchive, stringEndArchive, + 0, 0, centDirCount, centDirCount, + centDirSize, centDirOffset, len(self.comment)) + self.fp.write(endrec) + self.fp.write(self.comment) + self.fp.flush() + + if not self._filePassed: + self.fp.close() + self.fp = None + + +def safe_replace(zipstream, name, datastream, extra_replacements={}, + add_missing=False): + ''' + Replace a file in a zip file in a safe manner. This proceeds by extracting + and re-creating the zipfile. This is necessary because :method:`ZipFile.replace` + sometimes created corrupted zip files. + + + :param zipstream: Stream from a zip file + :param name: The name of the file to replace + :param datastream: The data to replace the file with. + :param extra_replacements: Extra replacements. Mapping of name to file-like + objects + :param add_missing: If a replacement does not exist in the zip file, it is + added. Use with care as currently parent directories + are not created. + + ''' + z = ZipFile(zipstream, 'r') + replacements = {name:datastream} + replacements.update(extra_replacements) + names = frozenset(replacements.keys()) + found = set() + + def rbytes(name): + r = replacements[name] + if not isinstance(r, bytes): + r = r.read() + return r + + with SpooledTemporaryFile(max_size=100*1024*1024) as temp: + ztemp = ZipFile(temp, 'w') + for obj in z.infolist(): + if isinstance(obj.filename, unicode_type): + obj.flag_bits |= 0x16 # Set isUTF-8 bit + if obj.filename in names: + ztemp.writestr(obj, rbytes(obj.filename)) + found.add(obj.filename) + else: + ztemp.writestr(obj, z.read_raw(obj), raw_bytes=True) + if add_missing: + for name in names - found: + ztemp.writestr(name, rbytes(name)) + ztemp.close() + z.close() + temp.seek(0) + zipstream.seek(0) + zipstream.truncate() + shutil.copyfileobj(temp, zipstream) + zipstream.flush() + + +class PyZipFile(ZipFile): + + """Class to create ZIP archives with Python library files and packages.""" + + def writepy(self, pathname, basename=""): + """Add all files from "pathname" to the ZIP archive. + + If pathname is a package directory, search the directory and + all package subdirectories recursively for all *.py and enter + the modules into the archive. If pathname is a plain + directory, listdir *.py and enter all modules. Else, pathname + must be a Python *.py file and the module will be put into the + archive. Added modules are always module.pyo or module.pyc. + This method will compile the module.py into module.pyc if + necessary. + """ + dir, name = os.path.split(pathname) + if os.path.isdir(pathname): + initname = os.path.join(pathname, "__init__.py") + if os.path.isfile(initname): + # This is a package directory, add it + if basename: + basename = "%s/%s" % (basename, name) + else: + basename = name + if self.debug: + print("Adding package in", pathname, "as", basename) + fname, arcname = self._get_codename(initname[0:-3], basename) + if self.debug: + print("Adding", arcname) + self.write(fname, arcname) + dirlist = os.listdir(pathname) + dirlist.remove("__init__.py") + # Add all *.py files and package subdirectories + for filename in dirlist: + path = os.path.join(pathname, filename) + ext = os.path.splitext(filename)[-1] + if os.path.isdir(path): + if os.path.isfile(os.path.join(path, "__init__.py")): + # This is a package directory, add it + self.writepy(path, basename) # Recursive call + elif ext == ".py": + fname, arcname = self._get_codename(path[0:-3], + basename) + if self.debug: + print("Adding", arcname) + self.write(fname, arcname) + else: + # This is NOT a package directory, add its files at top level + if self.debug: + print("Adding files from directory", pathname) + for filename in os.listdir(pathname): + path = os.path.join(pathname, filename) + ext = os.path.splitext(filename)[-1] + if ext == ".py": + fname, arcname = self._get_codename(path[0:-3], + basename) + if self.debug: + print("Adding", arcname) + self.write(fname, arcname) + else: + if pathname[-3:] != ".py": + raise RuntimeError( + 'Files added with writepy() must end with ".py"') + fname, arcname = self._get_codename(pathname[0:-3], basename) + if self.debug: + print("Adding file", arcname) + self.write(fname, arcname) + + def _get_codename(self, pathname, basename): + """Return (filename, archivename) for the path. + + Given a module name path, return the correct file path and + archive name, compiling if necessary. For example, given + /python/lib/string, return (/python/lib/string.pyc, string). + """ + file_py = pathname + ".py" + file_pyc = pathname + ".pyc" + file_pyo = pathname + ".pyo" + if os.path.isfile(file_pyo) and \ + os.stat(file_pyo).st_mtime >= os.stat(file_py).st_mtime: + fname = file_pyo # Use .pyo file + elif not os.path.isfile(file_pyc) or \ + os.stat(file_pyc).st_mtime < os.stat(file_py).st_mtime: + import py_compile + if self.debug: + print("Compiling", file_py) + try: + py_compile.compile(file_py, file_pyc, None, True) + except py_compile.PyCompileError as err: + print(err.msg) + fname = file_pyc + else: + fname = file_pyc + archivename = os.path.split(fname)[1] + if basename: + archivename = "%s/%s" % (basename, archivename) + return (fname, archivename) + + +def main(args=None): + import textwrap + USAGE=textwrap.dedent("""\ + Usage: + zipfile.py -l zipfile.zip # Show listing of a zipfile + zipfile.py -t zipfile.zip # Test if a zipfile is valid + zipfile.py -e zipfile.zip target # Extract zipfile into target dir + zipfile.py -c zipfile.zip src ... # Create zipfile from sources + """) + if args is None: + args = sys.argv[1:] + + if not args or args[0] not in ('-l', '-c', '-e', '-t'): + print(USAGE) + sys.exit(1) + + if args[0] == '-l': + if len(args) != 2: + print(USAGE) + sys.exit(1) + zf = ZipFile(args[1], 'r') + zf.printdir() + zf.close() + + elif args[0] == '-t': + if len(args) != 2: + print(USAGE) + sys.exit(1) + zf = ZipFile(args[1], 'r') + badfile = zf.testzip() + if badfile: + print("The following enclosed file is corrupted: {!r}".format(badfile)) + print("Done testing") + + elif args[0] == '-e': + if len(args) != 3: + print(USAGE) + sys.exit(1) + + zf = ZipFile(args[1], 'r') + out = args[2] + for path in zf.namelist(): + if path.startswith('./'): + tgt = os.path.join(out, path[2:]) + else: + tgt = os.path.join(out, path) + + tgtdir = os.path.dirname(tgt) + if not os.path.exists(tgtdir): + os.makedirs(tgtdir) + with open(tgt, 'wb') as fp: + fp.write(zf.read(path)) + zf.close() + + elif args[0] == '-c': + if len(args) < 3: + print(USAGE) + sys.exit(1) + + def addToZip(zf, path, zippath): + if os.path.isfile(path): + zf.write(path, zippath, ZIP_DEFLATED) + elif os.path.isdir(path): + for nm in os.listdir(path): + addToZip(zf, + os.path.join(path, nm), os.path.join(zippath, nm)) + # else: ignore + + zf = ZipFile(args[1], 'w', allowZip64=True) + for src in args[2:]: + addToZip(zf, src, os.path.basename(src)) + + zf.close() + + +if __name__ == "__main__": + main()