From b5ee4a9abe92f6a5b8e06930025567b231478dfe Mon Sep 17 00:00:00 2001 From: Sven Strickroth Date: Sun, 24 Mar 2013 17:42:12 +0100 Subject: [PATCH] Updated hunspell to 1.3.2 Also synced with TortoiseSVN so that it matches revision 24024. Signed-off-by: Sven Strickroth --- ext/hunspell/affentry.cxx | 486 +- ext/hunspell/affentry.hxx | 17 +- ext/hunspell/affixmgr.cxx | 2639 +++++--- ext/hunspell/affixmgr.hxx | 255 +- ext/hunspell/atypes.hxx | 68 +- ext/hunspell/baseaffix.hxx | 59 +- ext/hunspell/config.h | 208 + ext/hunspell/csutil.cxx | 1136 +++- ext/hunspell/csutil.hxx | 361 +- ext/hunspell/dictmgr.cxx | 53 +- ext/hunspell/dictmgr.hxx | 4 +- ext/hunspell/filemgr.cxx | 49 + ext/hunspell/filemgr.hxx | 25 + ext/hunspell/hashmgr.cxx | 626 +- ext/hunspell/hashmgr.hxx | 128 +- ext/hunspell/htypes.hxx | 28 +- ext/hunspell/hunspell.cxx | 1648 +++-- ext/hunspell/hunspell.h | 72 +- ext/hunspell/hunspell.hxx | 118 +- ext/hunspell/hunspell.vcxproj | 24 +- ext/hunspell/hunspell.vcxproj.filters | 33 + ext/hunspell/hunvisapi.h | 18 + ext/hunspell/hunvisapi.h.in | 18 + ext/hunspell/hunzip.cxx | 193 + ext/hunspell/hunzip.hxx | 45 + ext/hunspell/license.hunspell | 28 +- ext/hunspell/phonet.cxx | 292 + ext/hunspell/phonet.hxx | 52 + ext/hunspell/replist.cxx | 87 + ext/hunspell/replist.hxx | 27 + ext/hunspell/suggestmgr.cxx | 1329 ++-- ext/hunspell/suggestmgr.hxx | 52 +- ext/hunspell/utf_info.cxx | 11170 ++++++++++++++++++++++++++++++++ ext/hunspell/w_char.hxx | 21 + src/TortoiseProc/TortoiseProc.vcxproj | 8 +- 35 files changed, 17957 insertions(+), 3420 deletions(-) rewrite ext/hunspell/baseaffix.hxx (89%) rewrite ext/hunspell/csutil.hxx (68%) create mode 100644 ext/hunspell/filemgr.cxx create mode 100644 ext/hunspell/filemgr.hxx rewrite ext/hunspell/hashmgr.hxx (70%) create mode 100644 ext/hunspell/hunvisapi.h create mode 100644 ext/hunspell/hunvisapi.h.in create mode 100644 ext/hunspell/hunzip.cxx create mode 100644 ext/hunspell/hunzip.hxx create mode 100644 ext/hunspell/phonet.cxx create mode 100644 ext/hunspell/phonet.hxx create mode 100644 ext/hunspell/replist.cxx create mode 100644 ext/hunspell/replist.hxx create mode 100644 ext/hunspell/w_char.hxx diff --git a/ext/hunspell/affentry.cxx b/ext/hunspell/affentry.cxx index ce727b011..246084e95 100644 --- a/ext/hunspell/affentry.cxx +++ b/ext/hunspell/affentry.cxx @@ -1,50 +1,37 @@ #include "license.hunspell" #include "license.myspell" -#ifndef MOZILLA_CLIENT -#include -#include -#include -#include -#else -#include +#include #include -#include +#include #include -#endif #include "affentry.hxx" #include "csutil.hxx" -#ifndef MOZILLA_CLIENT -#ifndef W32 -using namespace std; -#endif -#endif - - PfxEntry::PfxEntry(AffixMgr* pmgr, affentry* dp) { // register affix manager pmyMgr = pmgr; - // set up its intial values - - aflag = dp->aflag; // flag + // set up its initial values + + aflag = dp->aflag; // flag strip = dp->strip; // string to strip appnd = dp->appnd; // string to append stripl = dp->stripl; // length of strip string appndl = dp->appndl; // length of append string - numconds = dp->numconds; // number of conditions to match - opts = dp->opts; // cross product flag + numconds = dp->numconds; // length of the condition + opts = dp->opts; // cross product flag // then copy over all of the conditions - memcpy(&conds.base[0],&dp->conds.base[0],SETSIZE*sizeof(conds.base[0])); + if (opts & aeLONGCOND) { + memcpy(c.conds, dp->c.l.conds1, MAXCONDLEN_1); + c.l.conds2 = dp->c.l.conds2; + } else memcpy(c.conds, dp->c.conds, MAXCONDLEN); next = NULL; nextne = NULL; nexteq = NULL; -#ifdef HUNSPELL_EXPERIMENTAL morphcode = dp->morphcode; -#endif contclass = dp->contclass; contclasslen = dp->contclasslen; } @@ -58,14 +45,8 @@ PfxEntry::~PfxEntry() pmyMgr = NULL; appnd = NULL; strip = NULL; - if (opts & aeUTF8) { - for (int i = 0; i < 8; i++) { - if (conds.utf8.wchars[i]) free(conds.utf8.wchars[i]); - } - } -#ifdef HUNSPELL_EXPERIMENTAL + if (opts & aeLONGCOND) free(c.l.conds2); if (morphcode && !(opts & aeALIASM)) free(morphcode); -#endif if (contclass && !(opts & aeALIASF)) free(contclass); } @@ -74,8 +55,9 @@ char * PfxEntry::add(const char * word, int len) { char tword[MAXWORDUTF8LEN + 4]; - if ((len > stripl) && (len >= numconds) && test_condition(word) && - (!stripl || (strncmp(word, strip, stripl) == 0)) && + if ((len > stripl || (len == 0 && pmyMgr->get_fullstrip())) && + (len >= numconds) && test_condition(word) && + (!stripl || (strncmp(word, strip, stripl) == 0)) && ((MAXWORDUTF8LEN + 4) > (len + appndl - stripl))) { /* we have a match so add prefix */ char * pp = tword; @@ -86,51 +68,87 @@ char * PfxEntry::add(const char * word, int len) strcpy(pp, (word + stripl)); return mystrdup(tword); } - return NULL; + return NULL; } +inline char * PfxEntry::nextchar(char * p) { + if (p) { + p++; + if (opts & aeLONGCOND) { + // jump to the 2nd part of the condition + if (p == c.conds + MAXCONDLEN_1) return c.l.conds2; + // end of the MAXCONDLEN length condition + } else if (p == c.conds + MAXCONDLEN) return NULL; + return *p ? p : NULL; + } + return NULL; +} inline int PfxEntry::test_condition(const char * st) { - int cond; - unsigned char * cp = (unsigned char *)st; - if (!(opts & aeUTF8)) { // 256-character codepage - for (cond = 0; cond < numconds; cond++) { - if ((conds.base[*cp++] & (1 << cond)) == 0) return 0; - } - } else { // UTF-8 encoding - unsigned short wc; - for (cond = 0; cond < numconds; cond++) { - // a simple 7-bit ASCII character in UTF-8 - if ((*cp >> 7) == 0) { - // also check limit (end of word) - if ((!*cp) || ((conds.utf8.ascii[*cp++] & (1 << cond)) == 0)) return 0; - // UTF-8 multibyte character - } else { - // not dot wildcard in rule - if (!conds.utf8.all[cond]) { - if (conds.utf8.neg[cond]) { - u8_u16((w_char *) &wc, 1, (char *) cp); - if (conds.utf8.wchars[cond] && - flag_bsearch((unsigned short *)conds.utf8.wchars[cond], - wc, (short) conds.utf8.wlen[cond])) return 0; - } else { - if (!conds.utf8.wchars[cond]) return 0; - u8_u16((w_char *) &wc, 1, (char *) cp); - if (!flag_bsearch((unsigned short *)conds.utf8.wchars[cond], - wc, (short)conds.utf8.wlen[cond])) return 0; - } + const char * pos = NULL; // group with pos input position + bool neg = false; // complementer + bool ingroup = false; // character in the group + if (numconds == 0) return 1; + char * p = c.conds; + while (1) { + switch (*p) { + case '\0': return 1; + case '[': { + neg = false; + ingroup = false; + p = nextchar(p); + pos = st; break; + } + case '^': { p = nextchar(p); neg = true; break; } + case ']': { + if ((neg && ingroup) || (!neg && !ingroup)) return 0; + pos = NULL; + p = nextchar(p); + // skip the next character + if (!ingroup && *st) for (st++; (opts & aeUTF8) && (*st & 0xc0) == 0x80; st++); + if (*st == '\0' && p) return 0; // word <= condition + break; + } + case '.': if (!pos) { // dots are not metacharacters in groups: [.] + p = nextchar(p); + // skip the next character + for (st++; (opts & aeUTF8) && (*st & 0xc0) == 0x80; st++); + if (*st == '\0' && p) return 0; // word <= condition + break; + } + default: { + if (*st == *p) { + st++; + p = nextchar(p); + if ((opts & aeUTF8) && (*(st - 1) & 0x80)) { // multibyte + while (p && (*p & 0xc0) == 0x80) { // character + if (*p != *st) { + if (!pos) return 0; + st = pos; + break; + } + p = nextchar(p); + st++; + } + if (pos && st != pos) { + ingroup = true; + while (p && *p != ']' && (p = nextchar(p))); + } + } else if (pos) { + ingroup = true; + while (p && *p != ']' && (p = nextchar(p))); + } + } else if (pos) { // group + p = nextchar(p); + } else return 0; } - // jump to next UTF-8 character - for(cp++; (*cp & 0xc0) == 0x80; cp++); - } } + if (!p) return 1; } - return 1; } - -// check if this prefix entry matches +// check if this prefix entry matches struct hentry * PfxEntry::checkword(const char * word, int len, char in_compound, const FLAG needflag) { int tmpl; // length of tmpword @@ -144,7 +162,7 @@ struct hentry * PfxEntry::checkword(const char * word, int len, char in_compound tmpl = len - appndl; - if ((tmpl > 0) && (tmpl + stripl >= numconds)) { + if (tmpl > 0 || (tmpl == 0 && pmyMgr->get_fullstrip())) { // generate new root word by removing prefix and adding // back any characters that would have been stripped @@ -165,8 +183,8 @@ struct hentry * PfxEntry::checkword(const char * word, int len, char in_compound if ((he = pmyMgr->lookup(tmpword)) != NULL) { do { if (TESTAFF(he->astr, aflag, he->alen) && - // forbid single prefixes with pseudoroot flag - ! TESTAFF(contclass, pmyMgr->get_pseudoroot(), contclasslen) && + // forbid single prefixes with needaffix flag + ! TESTAFF(contclass, pmyMgr->get_needaffix(), contclasslen) && // needflag ((!needflag) || TESTAFF(he->astr, needflag, he->alen) || (contclass && TESTAFF(contclass, needflag, contclasslen)))) @@ -174,14 +192,14 @@ struct hentry * PfxEntry::checkword(const char * word, int len, char in_compound he = he->next_homonym; // check homonyms } while (he); } - - // prefix matched but no root word was found - // if aeXPRODUCT is allowed, try again but now + + // prefix matched but no root word was found + // if aeXPRODUCT is allowed, try again but now // ross checked combined with a suffix //if ((opts & aeXPRODUCT) && in_compound) { if ((opts & aeXPRODUCT)) { - he = pmyMgr->suffix_check(tmpword, tmpl, aeXPRODUCT, (AffEntry *)this, NULL, + he = pmyMgr->suffix_check(tmpword, tmpl, aeXPRODUCT, this, NULL, 0, NULL, FLAG_NULL, needflag, in_compound); if (he) return he; } @@ -190,7 +208,7 @@ struct hentry * PfxEntry::checkword(const char * word, int len, char in_compound return NULL; } -// check if this prefix entry matches +// check if this prefix entry matches struct hentry * PfxEntry::check_twosfx(const char * word, int len, char in_compound, const FLAG needflag) { @@ -205,7 +223,8 @@ struct hentry * PfxEntry::check_twosfx(const char * word, int len, tmpl = len - appndl; - if ((tmpl > 0) && (tmpl + stripl >= numconds)) { + if ((tmpl > 0 || (tmpl == 0 && pmyMgr->get_fullstrip())) && + (tmpl + stripl >= numconds)) { // generate new root word by removing prefix and adding // back any characters that would have been stripped @@ -224,12 +243,12 @@ struct hentry * PfxEntry::check_twosfx(const char * word, int len, if (test_condition(tmpword)) { tmpl += stripl; - // prefix matched but no root word was found - // if aeXPRODUCT is allowed, try again but now + // prefix matched but no root word was found + // if aeXPRODUCT is allowed, try again but now // cross checked combined with a suffix if ((opts & aeXPRODUCT) && (in_compound != IN_CPD_BEGIN)) { - he = pmyMgr->suffix_check_twosfx(tmpword, tmpl, aeXPRODUCT, (AffEntry *)this, needflag); + he = pmyMgr->suffix_check_twosfx(tmpword, tmpl, aeXPRODUCT, this, needflag); if (he) return he; } } @@ -237,8 +256,7 @@ struct hentry * PfxEntry::check_twosfx(const char * word, int len, return NULL; } -#ifdef HUNSPELL_EXPERIMENTAL -// check if this prefix entry matches +// check if this prefix entry matches char * PfxEntry::check_twosfx_morph(const char * word, int len, char in_compound, const FLAG needflag) { @@ -252,7 +270,8 @@ char * PfxEntry::check_twosfx_morph(const char * word, int len, tmpl = len - appndl; - if ((tmpl > 0) && (tmpl + stripl >= numconds)) { + if ((tmpl > 0 || (tmpl == 0 && pmyMgr->get_fullstrip())) && + (tmpl + stripl >= numconds)) { // generate new root word by removing prefix and adding // back any characters that would have been stripped @@ -271,20 +290,20 @@ char * PfxEntry::check_twosfx_morph(const char * word, int len, if (test_condition(tmpword)) { tmpl += stripl; - // prefix matched but no root word was found - // if aeXPRODUCT is allowed, try again but now + // prefix matched but no root word was found + // if aeXPRODUCT is allowed, try again but now // ross checked combined with a suffix if ((opts & aeXPRODUCT) && (in_compound != IN_CPD_BEGIN)) { return pmyMgr->suffix_check_twosfx_morph(tmpword, tmpl, - aeXPRODUCT, (AffEntry *)this, needflag); + aeXPRODUCT, this, needflag); } } } return NULL; } -// check if this prefix entry matches +// check if this prefix entry matches char * PfxEntry::check_morph(const char * word, int len, char in_compound, const FLAG needflag) { int tmpl; // length of tmpword @@ -292,7 +311,7 @@ char * PfxEntry::check_morph(const char * word, int len, char in_compound, const char tmpword[MAXWORDUTF8LEN + 4]; char result[MAXLNLEN]; char * st; - + *result = '\0'; // on entry prefix is 0 length or already matches the beginning of the word. @@ -302,7 +321,8 @@ char * PfxEntry::check_morph(const char * word, int len, char in_compound, const tmpl = len - appndl; - if ((tmpl > 0) && (tmpl + stripl >= numconds)) { + if ((tmpl > 0 || (tmpl == 0 && pmyMgr->get_fullstrip())) && + (tmpl + stripl >= numconds)) { // generate new root word by removing prefix and adding // back any characters that would have been stripped @@ -323,64 +343,79 @@ char * PfxEntry::check_morph(const char * word, int len, char in_compound, const if ((he = pmyMgr->lookup(tmpword)) != NULL) { do { if (TESTAFF(he->astr, aflag, he->alen) && - // forbid single prefixes with pseudoroot flag - ! TESTAFF(contclass, pmyMgr->get_pseudoroot(), contclasslen) && + // forbid single prefixes with needaffix flag + ! TESTAFF(contclass, pmyMgr->get_needaffix(), contclasslen) && // needflag ((!needflag) || TESTAFF(he->astr, needflag, he->alen) || (contclass && TESTAFF(contclass, needflag, contclasslen)))) { - if (morphcode) strcat(result, morphcode); else strcat(result,getKey()); - if (he->description) { - if ((*(he->description)=='[')||(*(he->description)=='<')) strcat(result,he->word); - strcat(result,he->description); + if (morphcode) { + mystrcat(result, " ", MAXLNLEN); + mystrcat(result, morphcode, MAXLNLEN); + } else mystrcat(result,getKey(), MAXLNLEN); + if (!HENTRY_FIND(he, MORPH_STEM)) { + mystrcat(result, " ", MAXLNLEN); + mystrcat(result, MORPH_STEM, MAXLNLEN); + mystrcat(result, HENTRY_WORD(he), MAXLNLEN); + } + // store the pointer of the hash entry + if (HENTRY_DATA(he)) { + mystrcat(result, " ", MAXLNLEN); + mystrcat(result, HENTRY_DATA2(he), MAXLNLEN); + } else { + // return with debug information + char * flag = pmyMgr->encode_flag(getFlag()); + mystrcat(result, " ", MAXLNLEN); + mystrcat(result, MORPH_FLAG, MAXLNLEN); + mystrcat(result, flag, MAXLNLEN); + free(flag); } - strcat(result, "\n"); + mystrcat(result, "\n", MAXLNLEN); } he = he->next_homonym; } while (he); } - // prefix matched but no root word was found - // if aeXPRODUCT is allowed, try again but now + // prefix matched but no root word was found + // if aeXPRODUCT is allowed, try again but now // ross checked combined with a suffix if ((opts & aeXPRODUCT) && (in_compound != IN_CPD_BEGIN)) { - st = pmyMgr->suffix_check_morph(tmpword, tmpl, aeXPRODUCT, (AffEntry *)this, + st = pmyMgr->suffix_check_morph(tmpword, tmpl, aeXPRODUCT, this, FLAG_NULL, needflag); if (st) { - strcat(result, st); + mystrcat(result, st, MAXLNLEN); free(st); } } } } - + if (*result) return mystrdup(result); return NULL; } -#endif // END OF HUNSPELL_EXPERIMENTAL CODE SfxEntry::SfxEntry(AffixMgr * pmgr, affentry* dp) { // register affix manager pmyMgr = pmgr; - // set up its intial values - aflag = dp->aflag; // char flag + // set up its initial values + aflag = dp->aflag; // char flag strip = dp->strip; // string to strip appnd = dp->appnd; // string to append stripl = dp->stripl; // length of strip string appndl = dp->appndl; // length of append string - numconds = dp->numconds; // number of conditions to match - opts = dp->opts; // cross product flag + numconds = dp->numconds; // length of the condition + opts = dp->opts; // cross product flag // then copy over all of the conditions - memcpy(&conds.base[0],&dp->conds.base[0],SETSIZE*sizeof(conds.base[0])); + if (opts & aeLONGCOND) { + memcpy(c.l.conds1, dp->c.l.conds1, MAXCONDLEN_1); + c.l.conds2 = dp->c.l.conds2; + } else memcpy(c.conds, dp->c.conds, MAXCONDLEN); rappnd = myrevstrdup(appnd); - -#ifdef HUNSPELL_EXPERIMENTAL morphcode = dp->morphcode; -#endif contclass = dp->contclass; contclasslen = dp->contclasslen; } @@ -394,15 +429,9 @@ SfxEntry::~SfxEntry() if (strip) free(strip); pmyMgr = NULL; appnd = NULL; - strip = NULL; - if (opts & aeUTF8) { - for (int i = 0; i < 8; i++) { - if (conds.utf8.wchars[i]) free(conds.utf8.wchars[i]); - } - } -#ifdef HUNSPELL_EXPERIMENTAL + strip = NULL; + if (opts & aeLONGCOND) free(c.l.conds2); if (morphcode && !(opts & aeALIASM)) free(morphcode); -#endif if (contclass && !(opts & aeALIASF)) free(contclass); } @@ -412,7 +441,8 @@ char * SfxEntry::add(const char * word, int len) char tword[MAXWORDUTF8LEN + 4]; /* make sure all conditions match */ - if ((len > stripl) && (len >= numconds) && test_condition(word + len, word) && + if ((len > stripl || (len == 0 && pmyMgr->get_fullstrip())) && + (len >= numconds) && test_condition(word + len, word) && (!stripl || (strcmp(word + len - stripl, strip) == 0)) && ((MAXWORDUTF8LEN + 4) > (len + appndl - stripl))) { /* we have a match so add suffix */ @@ -427,60 +457,118 @@ char * SfxEntry::add(const char * word, int len) return NULL; } +inline char * SfxEntry::nextchar(char * p) { + if (p) { + p++; + if (opts & aeLONGCOND) { + // jump to the 2nd part of the condition + if (p == c.l.conds1 + MAXCONDLEN_1) return c.l.conds2; + // end of the MAXCONDLEN length condition + } else if (p == c.conds + MAXCONDLEN) return NULL; + return *p ? p : NULL; + } + return NULL; +} inline int SfxEntry::test_condition(const char * st, const char * beg) { - int cond; - unsigned char * cp = (unsigned char *) st; - if (!(opts & aeUTF8)) { // 256-character codepage - // Dömölki affix algorithm - for (cond = numconds; --cond >= 0; ) { - if ((conds.base[*--cp] & (1 << cond)) == 0) return 0; - } - } else { // UTF-8 encoding - unsigned short wc; - for (cond = numconds; --cond >= 0; ) { - // go to next character position and check limit - if ((char *) --cp < beg) return 0; - // a simple 7-bit ASCII character in UTF-8 - if ((*cp >> 7) == 0) { - if ((conds.utf8.ascii[*cp] & (1 << cond)) == 0) return 0; - // UTF-8 multibyte character - } else { - // go to first character of UTF-8 multibyte character - for (; (*cp & 0xc0) == 0x80; cp--); - // not dot wildcard in rule - if (!conds.utf8.all[cond]) { - if (conds.utf8.neg[cond]) { - u8_u16((w_char *) &wc, 1, (char *) cp); - if (conds.utf8.wchars[cond] && - flag_bsearch((unsigned short *)conds.utf8.wchars[cond], - wc, (short) conds.utf8.wlen[cond])) return 0; - } else { - if (!conds.utf8.wchars[cond]) return 0; - u8_u16((w_char *) &wc, 1, (char *) cp); - if (!flag_bsearch((unsigned short *)conds.utf8.wchars[cond], - wc, (short)conds.utf8.wlen[cond])) return 0; + const char * pos = NULL; // group with pos input position + bool neg = false; // complementer + bool ingroup = false; // character in the group + if (numconds == 0) return 1; + char * p = c.conds; + st--; + int i = 1; + while (1) { + switch (*p) { + case '\0': return 1; + case '[': { p = nextchar(p); pos = st; break; } + case '^': { p = nextchar(p); neg = true; break; } + case ']': { if (!neg && !ingroup) return 0; + i++; + // skip the next character + if (!ingroup) { + for (; (opts & aeUTF8) && (st >= beg) && (*st & 0xc0) == 0x80; st--); + st--; + } + pos = NULL; + neg = false; + ingroup = false; + p = nextchar(p); + if (st < beg && p) return 0; // word <= condition + break; + } + case '.': if (!pos) { // dots are not metacharacters in groups: [.] + p = nextchar(p); + // skip the next character + for (st--; (opts & aeUTF8) && (st >= beg) && (*st & 0xc0) == 0x80; st--); + if (st < beg) { // word <= condition + if (p) return 0; else return 1; + } + if ((opts & aeUTF8) && (*st & 0x80)) { // head of the UTF-8 character + st--; + if (st < beg) { // word <= condition + if (p) return 0; else return 1; + } } + break; + } + default: { + if (*st == *p) { + p = nextchar(p); + if ((opts & aeUTF8) && (*st & 0x80)) { + st--; + while (p && (st >= beg)) { + if (*p != *st) { + if (!pos) return 0; + st = pos; + break; + } + // first byte of the UTF-8 multibyte character + if ((*p & 0xc0) != 0x80) break; + p = nextchar(p); + st--; + } + if (pos && st != pos) { + if (neg) return 0; + else if (i == numconds) return 1; + ingroup = true; + while (p && *p != ']' && (p = nextchar(p))); + st--; + } + if (p && *p != ']') p = nextchar(p); + } else if (pos) { + if (neg) return 0; + else if (i == numconds) return 1; + ingroup = true; + while (p && *p != ']' && (p = nextchar(p))); +// if (p && *p != ']') p = nextchar(p); + st--; + } + if (!pos) { + i++; + st--; + } + if (st < beg && p && *p != ']') return 0; // word <= condition + } else if (pos) { // group + p = nextchar(p); + } else return 0; } - } } + if (!p) return 1; } - return 1; } - - -// see if this suffix is present in the word +// see if this suffix is present in the word struct hentry * SfxEntry::checkword(const char * word, int len, int optflags, - AffEntry* ppfx, char ** wlst, int maxSug, int * ns, const FLAG cclass, const FLAG needflag, + PfxEntry* ppfx, char ** wlst, int maxSug, int * ns, const FLAG cclass, const FLAG needflag, const FLAG badflag) { - int tmpl; // length of tmpword + int tmpl; // length of tmpword struct hentry * he; // hash entry pointer unsigned char * cp; char tmpword[MAXWORDUTF8LEN + 4]; - PfxEntry* ep = (PfxEntry *) ppfx; + PfxEntry* ep = ppfx; // if this suffix is being cross checked with a prefix // but it does not support cross products skip it @@ -496,8 +584,9 @@ struct hentry * SfxEntry::checkword(const char * word, int len, int optflags, tmpl = len - appndl; // the second condition is not enough for UTF-8 strings // it checked in test_condition() - - if ((tmpl > 0) && (tmpl + stripl >= numconds)) { + + if ((tmpl > 0 || (tmpl == 0 && pmyMgr->get_fullstrip())) && + (tmpl + stripl >= numconds)) { // generate new root word by removing suffix and adding // back any characters that would have been stripped or @@ -513,7 +602,8 @@ struct hentry * SfxEntry::checkword(const char * word, int len, int optflags, // now make sure all of the conditions on characters // are met. Please see the appendix at the end of - // this file for more info on exactly what is being // tested + // this file for more info on exactly what is being + // tested // if all conditions are met then check if resulting // root word in the dictionary @@ -527,21 +617,21 @@ struct hentry * SfxEntry::checkword(const char * word, int len, int optflags, do { // check conditional suffix (enabled by prefix) if ((TESTAFF(he->astr, aflag, he->alen) || (ep && ep->getCont() && - TESTAFF(ep->getCont(), aflag, ep->getContLen()))) && - (((optflags & aeXPRODUCT) == 0) || - TESTAFF(he->astr, ep->getFlag(), he->alen) || + TESTAFF(ep->getCont(), aflag, ep->getContLen()))) && + (((optflags & aeXPRODUCT) == 0) || + (ep && TESTAFF(he->astr, ep->getFlag(), he->alen)) || // enabled by prefix - ((contclass) && TESTAFF(contclass, ep->getFlag(), contclasslen)) + ((contclass) && (ep && TESTAFF(contclass, ep->getFlag(), contclasslen))) ) && // handle cont. class - ((!cclass) || + ((!cclass) || ((contclass) && TESTAFF(contclass, cclass, contclasslen)) ) && // check only in compound homonyms (bad flags) (!badflag || !TESTAFF(he->astr, badflag, he->alen) - ) && + ) && // handle required flag - ((!needflag) || + ((!needflag) || (TESTAFF(he->astr, needflag, he->alen) || ((contclass) && TESTAFF(contclass, needflag, contclasslen))) ) @@ -549,12 +639,12 @@ struct hentry * SfxEntry::checkword(const char * word, int len, int optflags, he = he->next_homonym; // check homonyms } while (he); - // obsolote stemming code (used only by the + // obsolote stemming code (used only by the // experimental SuffixMgr:suggest_pos_stems) // store resulting root in wlst } else if (wlst && (*ns < maxSug)) { int cwrd = 1; - for (int k=0; k < *ns; k++) + for (int k=0; k < *ns; k++) if (strcmp(tmpword, wlst[k]) == 0) cwrd = 0; if (cwrd) { wlst[*ns] = mystrdup(tmpword); @@ -571,15 +661,15 @@ struct hentry * SfxEntry::checkword(const char * word, int len, int optflags, return NULL; } -// see if two-level suffix is present in the word +// see if two-level suffix is present in the word struct hentry * SfxEntry::check_twosfx(const char * word, int len, int optflags, - AffEntry* ppfx, const FLAG needflag) + PfxEntry* ppfx, const FLAG needflag) { - int tmpl; // length of tmpword + int tmpl; // length of tmpword struct hentry * he; // hash entry pointer unsigned char * cp; char tmpword[MAXWORDUTF8LEN + 4]; - PfxEntry* ep = (PfxEntry *) ppfx; + PfxEntry* ep = ppfx; // if this suffix is being cross checked with a prefix @@ -595,7 +685,8 @@ struct hentry * SfxEntry::check_twosfx(const char * word, int len, int optflags, tmpl = len - appndl; - if ((tmpl > 0) && (tmpl + stripl >= numconds)) { + if ((tmpl > 0 || (tmpl == 0 && pmyMgr->get_fullstrip())) && + (tmpl + stripl >= numconds)) { // generate new root word by removing suffix and adding // back any characters that would have been stripped or @@ -619,7 +710,7 @@ struct hentry * SfxEntry::check_twosfx(const char * word, int len, int optflags, if (test_condition((char *) cp, (char *) tmpword)) { if (ppfx) { // handle conditional suffix - if ((contclass) && TESTAFF(contclass, ep->getFlag(), contclasslen)) + if ((contclass) && TESTAFF(contclass, ep->getFlag(), contclasslen)) he = pmyMgr->suffix_check(tmpword, tmpl, 0, NULL, NULL, 0, NULL, (FLAG) aflag, needflag); else he = pmyMgr->suffix_check(tmpword, tmpl, optflags, ppfx, NULL, 0, NULL, (FLAG) aflag, needflag); @@ -632,19 +723,18 @@ struct hentry * SfxEntry::check_twosfx(const char * word, int len, int optflags, return NULL; } -#ifdef HUNSPELL_EXPERIMENTAL -// see if two-level suffix is present in the word +// see if two-level suffix is present in the word char * SfxEntry::check_twosfx_morph(const char * word, int len, int optflags, - AffEntry* ppfx, const FLAG needflag) + PfxEntry* ppfx, const FLAG needflag) { - int tmpl; // length of tmpword + int tmpl; // length of tmpword unsigned char * cp; char tmpword[MAXWORDUTF8LEN + 4]; - PfxEntry* ep = (PfxEntry *) ppfx; + PfxEntry* ep = ppfx; char * st; char result[MAXLNLEN]; - + *result = '\0'; // if this suffix is being cross checked with a prefix @@ -660,7 +750,8 @@ char * SfxEntry::check_twosfx_morph(const char * word, int len, int optflags, tmpl = len - appndl; - if ((tmpl > 0) && (tmpl + stripl >= numconds)) { + if ((tmpl > 0 || (tmpl == 0 && pmyMgr->get_fullstrip())) && + (tmpl + stripl >= numconds)) { // generate new root word by removing suffix and adding // back any characters that would have been stripped or @@ -687,17 +778,18 @@ char * SfxEntry::check_twosfx_morph(const char * word, int len, int optflags, if ((contclass) && TESTAFF(contclass, ep->getFlag(), contclasslen)) { st = pmyMgr->suffix_check_morph(tmpword, tmpl, 0, NULL, aflag, needflag); if (st) { - if (((PfxEntry *) ppfx)->getMorph()) { - strcat(result, ((PfxEntry *) ppfx)->getMorph()); + if (ppfx->getMorph()) { + mystrcat(result, ppfx->getMorph(), MAXLNLEN); + mystrcat(result, " ", MAXLNLEN); } - strcat(result,st); + mystrcat(result,st, MAXLNLEN); free(st); mychomp(result); } } else { st = pmyMgr->suffix_check_morph(tmpword, tmpl, optflags, ppfx, aflag, needflag); if (st) { - strcat(result, st); + mystrcat(result, st, MAXLNLEN); free(st); mychomp(result); } @@ -705,7 +797,7 @@ char * SfxEntry::check_twosfx_morph(const char * word, int len, int optflags, } else { st = pmyMgr->suffix_check_morph(tmpword, tmpl, 0, NULL, aflag, needflag); if (st) { - strcat(result, st); + mystrcat(result, st, MAXLNLEN); free(st); mychomp(result); } @@ -715,28 +807,28 @@ char * SfxEntry::check_twosfx_morph(const char * word, int len, int optflags, } return NULL; } -#endif // END OF HUNSPELL_EXPERIMENTAL CODE // get next homonym with same affix -struct hentry * SfxEntry::get_next_homonym(struct hentry * he, int optflags, AffEntry* ppfx, +struct hentry * SfxEntry::get_next_homonym(struct hentry * he, int optflags, PfxEntry* ppfx, const FLAG cclass, const FLAG needflag) { - PfxEntry* ep = (PfxEntry *) ppfx; + PfxEntry* ep = ppfx; + FLAG eFlag = ep ? ep->getFlag() : FLAG_NULL; while (he->next_homonym) { he = he->next_homonym; - if ((TESTAFF(he->astr, aflag, he->alen) || (ep && ep->getCont() && TESTAFF(ep->getCont(), aflag, ep->getContLen()))) && - ((optflags & aeXPRODUCT) == 0 || - TESTAFF(he->astr, ep->getFlag(), he->alen) || + if ((TESTAFF(he->astr, aflag, he->alen) || (ep && ep->getCont() && TESTAFF(ep->getCont(), aflag, ep->getContLen()))) && + ((optflags & aeXPRODUCT) == 0 || + TESTAFF(he->astr, eFlag, he->alen) || // handle conditional suffix - ((contclass) && TESTAFF(contclass, ep->getFlag(), contclasslen)) + ((contclass) && TESTAFF(contclass, eFlag, contclasslen)) ) && // handle cont. class - ((!cclass) || + ((!cclass) || ((contclass) && TESTAFF(contclass, cclass, contclasslen)) ) && // handle required flag - ((!needflag) || + ((!needflag) || (TESTAFF(he->astr, needflag, he->alen) || ((contclass) && TESTAFF(contclass, needflag, contclasslen))) ) diff --git a/ext/hunspell/affentry.hxx b/ext/hunspell/affentry.hxx index bb2177398..eaf361fcc 100644 --- a/ext/hunspell/affentry.hxx +++ b/ext/hunspell/affentry.hxx @@ -1,13 +1,15 @@ #ifndef _AFFIX_HXX_ #define _AFFIX_HXX_ +#include "hunvisapi.h" + #include "atypes.hxx" #include "baseaffix.hxx" #include "affixmgr.hxx" /* A Prefix Entry */ -class PfxEntry : public AffEntry +class LIBHUNSPELL_DLL_EXPORTED PfxEntry : protected AffEntry { AffixMgr* pmyMgr; @@ -54,6 +56,7 @@ public: inline void setNextEQ(PfxEntry * ptr) { nexteq = ptr; } inline void setFlgNxt(PfxEntry * ptr) { flgnxt = ptr; } + inline char * nextchar(char * p); inline int test_condition(const char * st); }; @@ -62,7 +65,7 @@ public: /* A Suffix Entry */ -class SfxEntry : public AffEntry +class LIBHUNSPELL_DLL_EXPORTED SfxEntry : protected AffEntry { AffixMgr* pmyMgr; char * rappnd; @@ -83,16 +86,16 @@ public: inline bool allowCross() { return ((opts & aeXPRODUCT) != 0); } struct hentry * checkword(const char * word, int len, int optflags, - AffEntry* ppfx, char ** wlst, int maxSug, int * ns, + PfxEntry* ppfx, char ** wlst, int maxSug, int * ns, // const FLAG cclass = FLAG_NULL, const FLAG needflag = FLAG_NULL, char in_compound=IN_CPD_NOT); const FLAG cclass = FLAG_NULL, const FLAG needflag = FLAG_NULL, const FLAG badflag = 0); - struct hentry * check_twosfx(const char * word, int len, int optflags, AffEntry* ppfx, const FLAG needflag = NULL); + struct hentry * check_twosfx(const char * word, int len, int optflags, PfxEntry* ppfx, const FLAG needflag = NULL); char * check_twosfx_morph(const char * word, int len, int optflags, - AffEntry* ppfx, const FLAG needflag = FLAG_NULL); + PfxEntry* ppfx, const FLAG needflag = FLAG_NULL); struct hentry * get_next_homonym(struct hentry * he); - struct hentry * get_next_homonym(struct hentry * word, int optflags, AffEntry* ppfx, + struct hentry * get_next_homonym(struct hentry * word, int optflags, PfxEntry* ppfx, const FLAG cclass, const FLAG needflag); @@ -123,7 +126,9 @@ public: inline void setNextEQ(SfxEntry * ptr) { nexteq = ptr; } inline void setFlgNxt(SfxEntry * ptr) { flgnxt = ptr; } + inline char * nextchar(char * p); inline int test_condition(const char * st, const char * begin); + }; #endif diff --git a/ext/hunspell/affixmgr.cxx b/ext/hunspell/affixmgr.cxx index 079264275..25a38bfac 100644 --- a/ext/hunspell/affixmgr.cxx +++ b/ext/hunspell/affixmgr.cxx @@ -1,17 +1,12 @@ #include "license.hunspell" #include "license.myspell" -#ifndef MOZILLA_CLIENT -#include -#include -#include -#include -#else -#include +#include #include -#include +#include #include -#endif + +#include #include "affixmgr.hxx" #include "affentry.hxx" @@ -19,30 +14,33 @@ #include "csutil.hxx" -#ifndef MOZILLA_CLIENT -#ifndef W32 -using namespace std; -#endif -#endif - -AffixMgr::AffixMgr(const char * affpath, HashMgr* ptr) +AffixMgr::AffixMgr(const char * affpath, HashMgr** ptr, int * md, const char * key) { // register hash manager and load affix data from aff file - pHMgr = ptr; + pHMgr = ptr[0]; + alldic = ptr; + maxdic = md; + keystring = NULL; trystring = NULL; encoding=NULL; + csconv=NULL; utf8 = 0; complexprefixes = 0; maptable = NULL; nummap = 0; breaktable = NULL; - numbreak = 0; + numbreak = -1; reptable = NULL; numrep = 0; + iconvtable = NULL; + oconvtable = NULL; checkcpdtable = NULL; + // allow simplified compound forms (see 3rd field of CHECKCOMPOUNDPATTERN) + simplifiedcpd = 0; numcheckcpd = 0; defcpdtable = NULL; numdefcpd = 0; + phone = NULL; compoundflag = FLAG_NULL; // permits word in compound forms compoundbegin = FLAG_NULL; // may be first word in compound forms compoundmiddle = FLAG_NULL; // may be middle word in compound forms @@ -54,11 +52,13 @@ AffixMgr::AffixMgr(const char * affpath, HashMgr* ptr) checkcompoundrep = 0; // forbid bad compounds (may be non compound word with a REP substitution) checkcompoundcase = 0; // forbid upper and lowercase combinations at word bounds checkcompoundtriple = 0; // forbid compounds with triple letters - forbiddenword = FLAG_NULL; // forbidden word signing flag + simplifiedtriple = 0; // allow simplified triple letters in compounds (Schiff+fahrt -> Schiffahrt) + forbiddenword = FORBIDDENWORD; // forbidden word signing flag nosuggest = FLAG_NULL; // don't suggest words signed with NOSUGGEST flag + nongramsuggest = FLAG_NULL; lang = NULL; // language langnum = 0; // language code (see http://l10n.openoffice.org/languages.html) - pseudoroot = FLAG_NULL; // forbidden root, allowed only with suffixes + needaffix = FLAG_NULL; // forbidden root, allowed only with suffixes cpdwordmax = -1; // default: unlimited wordcount in compound words cpdmin = -1; // undefined cpdmaxsyllable = 0; // default: unlimited syllablecount in compound words @@ -82,14 +82,20 @@ AffixMgr::AffixMgr(const char * affpath, HashMgr* ptr) lemma_present = FLAG_NULL; circumfix = FLAG_NULL; onlyincompound = FLAG_NULL; - flag_mode = FLAG_CHAR; // default one-character flags in affix and dic file maxngramsugs = -1; // undefined + maxdiff = -1; // undefined + onlymaxdiff = 0; + maxcpdsugs = -1; // undefined nosplitsugs = 0; sugswithdots = 0; keepcase = 0; + forceucase = 0; + warn = 0; + forbidwarn = 0; checksharps = 0; + substandard = FLAG_NULL; + fullstrip = 0; - derived = NULL; // XXX not threadsafe variable for experimental stemming sfx = NULL; pfx = NULL; @@ -104,9 +110,8 @@ AffixMgr::AffixMgr(const char * affpath, HashMgr* ptr) contclasses[j] = 0; } - if (parse_file(affpath)) { + if (parse_file(affpath, key)) { HUNSPELL_WARNING(stderr, "Failure loading aff file %s\n",affpath); - wordchars = mystrdup("qwertzuiopasdfghjklyxcvbnmQWERTZUIOPASDFGHJKLYXCVBNM"); } if (cpdmin == -1) cpdmin = MINCPDLEN; @@ -116,11 +121,10 @@ AffixMgr::AffixMgr(const char * affpath, HashMgr* ptr) AffixMgr::~AffixMgr() { - // pass through linked prefix entries and clean up for (int i=0; i < SETSIZE ;i++) { pFlag[i] = NULL; - PfxEntry * ptr = (PfxEntry *)pStart[i]; + PfxEntry * ptr = pStart[i]; PfxEntry * nptr = NULL; while (ptr) { nptr = ptr->getNext(); @@ -133,7 +137,7 @@ AffixMgr::~AffixMgr() // pass through linked suffix entries and clean up for (int j=0; j < SETSIZE ; j++) { sFlag[j] = NULL; - SfxEntry * ptr = (SfxEntry *)sStart[j]; + SfxEntry * ptr = sStart[j]; SfxEntry * nptr = NULL; while (ptr) { nptr = ptr->getNext(); @@ -144,14 +148,18 @@ AffixMgr::~AffixMgr() sStart[j] = NULL; } + if (keystring) free(keystring); + keystring=NULL; if (trystring) free(trystring); trystring=NULL; if (encoding) free(encoding); encoding=NULL; if (maptable) { for (int j=0; j < nummap; j++) { - if (maptable[j].set) free(maptable[j].set); - if (maptable[j].set_utf16) free(maptable[j].set_utf16); + for (int k=0; k < maptable[j].len; k++) { + if (maptable[j].set[k]) free(maptable[j].set[k]); + } + free(maptable[j].set); maptable[j].set = NULL; maptable[j].len = 0; } @@ -168,16 +176,26 @@ AffixMgr::~AffixMgr() breaktable = NULL; } numbreak = 0; - if (reptable) { + if (reptable) { for (int j=0; j < numrep; j++) { free(reptable[j].pattern); free(reptable[j].pattern2); - reptable[j].pattern = NULL; - reptable[j].pattern2 = NULL; } free(reptable); reptable = NULL; } + if (iconvtable) delete iconvtable; + if (oconvtable) delete oconvtable; + if (phone && phone->rules) { + for (int j=0; j < phone->num + 1; j++) { + free(phone->rules[j * 2]); + free(phone->rules[j * 2 + 1]); + } + free(phone->rules); + free(phone); + phone = NULL; + } + if (defcpdtable) { for (int j=0; j < numdefcpd; j++) { free(defcpdtable[j].def); @@ -191,8 +209,10 @@ AffixMgr::~AffixMgr() for (int j=0; j < numcheckcpd; j++) { free(checkcpdtable[j].pattern); free(checkcpdtable[j].pattern2); + free(checkcpdtable[j].pattern3); checkcpdtable[j].pattern = NULL; checkcpdtable[j].pattern2 = NULL; + checkcpdtable[j].pattern3 = NULL; } free(checkcpdtable); checkcpdtable = NULL; @@ -207,7 +227,8 @@ AffixMgr::~AffixMgr() FREE_FLAG(compoundroot); FREE_FLAG(forbiddenword); FREE_FLAG(nosuggest); - FREE_FLAG(pseudoroot); + FREE_FLAG(nongramsuggest); + FREE_FLAG(needaffix); FREE_FLAG(lemma_present); FREE_FLAG(circumfix); FREE_FLAG(onlyincompound); @@ -226,20 +247,18 @@ AffixMgr::~AffixMgr() if (ignorechars) free(ignorechars); if (ignorechars_utf16) free(ignorechars_utf16); if (version) free(version); - if (derived) free(derived); checknum=0; +#ifdef MOZILLA_CLIENT + delete [] csconv; +#endif } // read in aff file and build up prefix and suffix entry objects -int AffixMgr::parse_file(const char * affpath) +int AffixMgr::parse_file(const char * affpath, const char * key) { - - // io buffers - char line[MAXLNLEN+1]; - - // affix type - char ft; + char * line; // io buffers + char ft; // affix type // checking flag duplication char dupflags[CONTSIZE]; @@ -249,8 +268,7 @@ int AffixMgr::parse_file(const char * affpath) int firstline = 1; // open the affix file - FILE * afflst; - afflst = fopen(affpath,"r"); + FileMgr * afflst = new FileMgr(affpath, key); if (!afflst) { HUNSPELL_WARNING(stderr, "error: could not open affix description file %s\n",affpath); return 1; @@ -259,43 +277,47 @@ int AffixMgr::parse_file(const char * affpath) // step one is to parse the affix file building up the internal // affix data structures - // read in each line ignoring any that do not // start with a known line type indicator - while (fgets(line,MAXLNLEN,afflst)) { + while ((line = afflst->getline())) { mychomp(line); /* remove byte order mark */ if (firstline) { firstline = 0; - if (strncmp(line,"",3) == 0) { + // Affix file begins with byte order mark: possible incompatibility with old Hunspell versions + if (strncmp(line,"\xEF\xBB\xBF",3) == 0) { memmove(line, line+3, strlen(line+3)+1); - HUNSPELL_WARNING(stderr, "warning: affix file begins with byte order mark: possible incompatibility with old Hunspell versions\n"); } } + /* parse in the keyboard string */ + if (strncmp(line,"KEY",3) == 0) { + if (parse_string(line, &keystring, afflst->getlinenum())) { + delete afflst; + return 1; + } + } + /* parse in the try string */ if (strncmp(line,"TRY",3) == 0) { - if (parse_string(line, &trystring, "TRY")) { - fclose(afflst); + if (parse_string(line, &trystring, afflst->getlinenum())) { + delete afflst; return 1; } } /* parse in the name of the character set used by the .dict and .aff */ if (strncmp(line,"SET",3) == 0) { - if (parse_string(line, &encoding, "SET")) { - fclose(afflst); + if (parse_string(line, &encoding, afflst->getlinenum())) { + delete afflst; return 1; } if (strcmp(encoding, "UTF-8") == 0) { utf8 = 1; #ifndef OPENOFFICEORG #ifndef MOZILLA_CLIENT - if (initialize_utf_tbl()) { - fclose(afflst); - return 1; - } + if (initialize_utf_tbl()) return 1; #endif #endif } @@ -307,8 +329,8 @@ int AffixMgr::parse_file(const char * affpath) /* parse in the flag used by the controlled compound words */ if (strncmp(line,"COMPOUNDFLAG",12) == 0) { - if (parse_flag(line, &compoundflag, "COMPOUNDFLAG")) { - fclose(afflst); + if (parse_flag(line, &compoundflag, afflst)) { + delete afflst; return 1; } } @@ -316,13 +338,13 @@ int AffixMgr::parse_file(const char * affpath) /* parse in the flag used by compound words */ if (strncmp(line,"COMPOUNDBEGIN",13) == 0) { if (complexprefixes) { - if (parse_flag(line, &compoundend, "COMPOUNDBEGIN")) { - fclose(afflst); + if (parse_flag(line, &compoundend, afflst)) { + delete afflst; return 1; } } else { - if (parse_flag(line, &compoundbegin, "COMPOUNDBEGIN")) { - fclose(afflst); + if (parse_flag(line, &compoundbegin, afflst)) { + delete afflst; return 1; } } @@ -330,21 +352,21 @@ int AffixMgr::parse_file(const char * affpath) /* parse in the flag used by compound words */ if (strncmp(line,"COMPOUNDMIDDLE",14) == 0) { - if (parse_flag(line, &compoundmiddle, "COMPOUNDMIDDLE")) { - fclose(afflst); + if (parse_flag(line, &compoundmiddle, afflst)) { + delete afflst; return 1; } } /* parse in the flag used by compound words */ if (strncmp(line,"COMPOUNDEND",11) == 0) { if (complexprefixes) { - if (parse_flag(line, &compoundbegin, "COMPOUNDEND")) { - fclose(afflst); + if (parse_flag(line, &compoundbegin, afflst)) { + delete afflst; return 1; } } else { - if (parse_flag(line, &compoundend, "COMPOUNDEND")) { - fclose(afflst); + if (parse_flag(line, &compoundend, afflst)) { + delete afflst; return 1; } } @@ -352,32 +374,32 @@ int AffixMgr::parse_file(const char * affpath) /* parse in the data used by compound_check() method */ if (strncmp(line,"COMPOUNDWORDMAX",15) == 0) { - if (parse_num(line, &cpdwordmax, "COMPOUNDWORDMAX")) { - fclose(afflst); + if (parse_num(line, &cpdwordmax, afflst)) { + delete afflst; return 1; } } /* parse in the flag sign compounds in dictionary */ if (strncmp(line,"COMPOUNDROOT",12) == 0) { - if (parse_flag(line, &compoundroot, "COMPOUNDROOT")) { - fclose(afflst); + if (parse_flag(line, &compoundroot, afflst)) { + delete afflst; return 1; } } /* parse in the flag used by compound_check() method */ if (strncmp(line,"COMPOUNDPERMITFLAG",18) == 0) { - if (parse_flag(line, &compoundpermitflag, "COMPOUNDPERMITFLAG")) { - fclose(afflst); + if (parse_flag(line, &compoundpermitflag, afflst)) { + delete afflst; return 1; } } /* parse in the flag used by compound_check() method */ if (strncmp(line,"COMPOUNDFORBIDFLAG",18) == 0) { - if (parse_flag(line, &compoundforbidflag, "COMPOUNDFORBIDFLAG")) { - fclose(afflst); + if (parse_flag(line, &compoundforbidflag, afflst)) { + delete afflst; return 1; } } @@ -394,69 +416,80 @@ int AffixMgr::parse_file(const char * affpath) checkcompoundtriple = 1; } + if (strncmp(line,"SIMPLIFIEDTRIPLE",16) == 0) { + simplifiedtriple = 1; + } + if (strncmp(line,"CHECKCOMPOUNDCASE",17) == 0) { checkcompoundcase = 1; } if (strncmp(line,"NOSUGGEST",9) == 0) { - if (parse_flag(line, &nosuggest, "NOSUGGEST")) { - fclose(afflst); + if (parse_flag(line, &nosuggest, afflst)) { + delete afflst; + return 1; + } + } + + if (strncmp(line,"NONGRAMSUGGEST",14) == 0) { + if (parse_flag(line, &nongramsuggest, afflst)) { + delete afflst; return 1; } } /* parse in the flag used by forbidden words */ if (strncmp(line,"FORBIDDENWORD",13) == 0) { - if (parse_flag(line, &forbiddenword, "FORBIDDENWORD")) { - fclose(afflst); + if (parse_flag(line, &forbiddenword, afflst)) { + delete afflst; return 1; } } /* parse in the flag used by forbidden words */ if (strncmp(line,"LEMMA_PRESENT",13) == 0) { - if (parse_flag(line, &lemma_present, "LEMMA_PRESENT")) { - fclose(afflst); + if (parse_flag(line, &lemma_present, afflst)) { + delete afflst; return 1; } } /* parse in the flag used by circumfixes */ if (strncmp(line,"CIRCUMFIX",9) == 0) { - if (parse_flag(line, &circumfix, "CIRCUMFIX")) { - fclose(afflst); + if (parse_flag(line, &circumfix, afflst)) { + delete afflst; return 1; } } /* parse in the flag used by fogemorphemes */ if (strncmp(line,"ONLYINCOMPOUND",14) == 0) { - if (parse_flag(line, &onlyincompound, "ONLYINCOMPOUND")) { - fclose(afflst); + if (parse_flag(line, &onlyincompound, afflst)) { + delete afflst; return 1; } } - /* parse in the flag used by `pseudoroots' */ + /* parse in the flag used by `needaffixs' */ if (strncmp(line,"PSEUDOROOT",10) == 0) { - if (parse_flag(line, &pseudoroot, "PSEUDOROOT")) { - fclose(afflst); + if (parse_flag(line, &needaffix, afflst)) { + delete afflst; return 1; } } - /* parse in the flag used by `pseudoroots' */ + /* parse in the flag used by `needaffixs' */ if (strncmp(line,"NEEDAFFIX",9) == 0) { - if (parse_flag(line, &pseudoroot, "NEEDAFFIX")) { - fclose(afflst); + if (parse_flag(line, &needaffix, afflst)) { + delete afflst; return 1; } } /* parse in the minimal length for words in compounds */ if (strncmp(line,"COMPOUNDMIN",11) == 0) { - if (parse_num(line, &cpdmin, "COMPOUNDMIN")) { - fclose(afflst); + if (parse_num(line, &cpdmin, afflst)) { + delete afflst; return 1; } if (cpdmin < 1) cpdmin = 1; @@ -464,16 +497,16 @@ int AffixMgr::parse_file(const char * affpath) /* parse in the max. words and syllables in compounds */ if (strncmp(line,"COMPOUNDSYLLABLE",16) == 0) { - if (parse_cpdsyllable(line)) { - fclose(afflst); + if (parse_cpdsyllable(line, afflst)) { + delete afflst; return 1; } } /* parse in the flag used by compound_check() method */ if (strncmp(line,"SYLLABLENUM",11) == 0) { - if (parse_string(line, &cpdsyllablenum, "SYLLABLENUM")) { - fclose(afflst); + if (parse_string(line, &cpdsyllablenum, afflst->getlinenum())) { + delete afflst; return 1; } } @@ -485,16 +518,16 @@ int AffixMgr::parse_file(const char * affpath) /* parse in the extra word characters */ if (strncmp(line,"WORDCHARS",9) == 0) { - if (parse_array(line, &wordchars, &wordchars_utf16, &wordchars_utf16_len, "WORDCHARS", utf8)) { - fclose(afflst); + if (parse_array(line, &wordchars, &wordchars_utf16, &wordchars_utf16_len, utf8, afflst->getlinenum())) { + delete afflst; return 1; } } /* parse in the ignored characters (for example, Arabic optional diacretics charachters */ if (strncmp(line,"IGNORE",6) == 0) { - if (parse_array(line, &ignorechars, &ignorechars_utf16, &ignorechars_utf16_len, "IGNORE", utf8)) { - fclose(afflst); + if (parse_array(line, &ignorechars, &ignorechars_utf16, &ignorechars_utf16_len, utf8, afflst->getlinenum())) { + delete afflst; return 1; } } @@ -502,7 +535,31 @@ int AffixMgr::parse_file(const char * affpath) /* parse in the typical fault correcting table */ if (strncmp(line,"REP",3) == 0) { if (parse_reptable(line, afflst)) { - fclose(afflst); + delete afflst; + return 1; + } + } + + /* parse in the input conversion table */ + if (strncmp(line,"ICONV",5) == 0) { + if (parse_convtable(line, afflst, &iconvtable, "ICONV")) { + delete afflst; + return 1; + } + } + + /* parse in the input conversion table */ + if (strncmp(line,"OCONV",5) == 0) { + if (parse_convtable(line, afflst, &oconvtable, "OCONV")) { + delete afflst; + return 1; + } + } + + /* parse in the phonetic translation table */ + if (strncmp(line,"PHONE",5) == 0) { + if (parse_phonetable(line, afflst)) { + delete afflst; return 1; } } @@ -510,7 +567,7 @@ int AffixMgr::parse_file(const char * affpath) /* parse in the checkcompoundpattern table */ if (strncmp(line,"CHECKCOMPOUNDPATTERN",20) == 0) { if (parse_checkcpdtable(line, afflst)) { - fclose(afflst); + delete afflst; return 1; } } @@ -518,7 +575,7 @@ int AffixMgr::parse_file(const char * affpath) /* parse in the defcompound table */ if (strncmp(line,"COMPOUNDRULE",12) == 0) { if (parse_defcpdtable(line, afflst)) { - fclose(afflst); + delete afflst; return 1; } } @@ -526,7 +583,7 @@ int AffixMgr::parse_file(const char * affpath) /* parse in the related character map table */ if (strncmp(line,"MAP",3) == 0) { if (parse_maptable(line, afflst)) { - fclose(afflst); + delete afflst; return 1; } } @@ -534,30 +591,45 @@ int AffixMgr::parse_file(const char * affpath) /* parse in the word breakpoints table */ if (strncmp(line,"BREAK",5) == 0) { if (parse_breaktable(line, afflst)) { - fclose(afflst); + delete afflst; return 1; } } /* parse in the language for language specific codes */ if (strncmp(line,"LANG",4) == 0) { - if (parse_string(line, &lang, "LANG")) { - fclose(afflst); + if (parse_string(line, &lang, afflst->getlinenum())) { + delete afflst; return 1; } langnum = get_lang_num(lang); } if (strncmp(line,"VERSION",7) == 0) { - if (parse_string(line, &version, "VERSION")) { - fclose(afflst); + for(line = line + 7; *line == ' ' || *line == '\t'; line++); + version = mystrdup(line); + } + + if (strncmp(line,"MAXNGRAMSUGS",12) == 0) { + if (parse_num(line, &maxngramsugs, afflst)) { + delete afflst; return 1; } } - if (strncmp(line,"MAXNGRAMSUGS",12) == 0) { - if (parse_num(line, &maxngramsugs, "MAXNGRAMSUGS")) { - fclose(afflst); + if (strncmp(line,"ONLYMAXDIFF", 11) == 0) + onlymaxdiff = 1; + + if (strncmp(line,"MAXDIFF",7) == 0) { + if (parse_num(line, &maxdiff, afflst)) { + delete afflst; + return 1; + } + } + + if (strncmp(line,"MAXCPDSUGS",10) == 0) { + if (parse_num(line, &maxcpdsugs, afflst)) { + delete afflst; return 1; } } @@ -566,14 +638,46 @@ int AffixMgr::parse_file(const char * affpath) nosplitsugs=1; } + if (strncmp(line,"FULLSTRIP",9) == 0) { + fullstrip=1; + } + if (strncmp(line,"SUGSWITHDOTS",12) == 0) { sugswithdots=1; } /* parse in the flag used by forbidden words */ if (strncmp(line,"KEEPCASE",8) == 0) { - if (parse_flag(line, &keepcase, "KEEPCASE")) { - fclose(afflst); + if (parse_flag(line, &keepcase, afflst)) { + delete afflst; + return 1; + } + } + + /* parse in the flag used by `forceucase' */ + if (strncmp(line,"FORCEUCASE",10) == 0) { + if (parse_flag(line, &forceucase, afflst)) { + delete afflst; + return 1; + } + } + + /* parse in the flag used by `warn' */ + if (strncmp(line,"WARN",4) == 0) { + if (parse_flag(line, &warn, afflst)) { + delete afflst; + return 1; + } + } + + if (strncmp(line,"FORBIDWARN",10) == 0) { + forbidwarn=1; + } + + /* parse in the flag used by the affix generator */ + if (strncmp(line,"SUBSTANDARD",11) == 0) { + if (parse_flag(line, &substandard, afflst)) { + delete afflst; return 1; } } @@ -588,11 +692,11 @@ int AffixMgr::parse_file(const char * affpath) if (strncmp(line,"SFX",3) == 0) ft = complexprefixes ? 'P' : 'S'; if (ft != ' ') { if (dupflags_ini) { - for (int i = 0; i < CONTSIZE; i++) dupflags[i] = 0; + memset(dupflags, 0, sizeof(dupflags)); dupflags_ini = 0; } if (parse_affix(line, ft, afflst, dupflags)) { - fclose(afflst); + delete afflst; process_pfx_tree_to_list(); process_sfx_tree_to_list(); return 1; @@ -600,7 +704,7 @@ int AffixMgr::parse_file(const char * affpath) } } - fclose(afflst); + delete afflst; // convert affix trees to sorted list process_pfx_tree_to_list(); @@ -626,14 +730,14 @@ int AffixMgr::parse_file(const char * affpath) // from entry. One to take next if the current prefix is found (call it nexteq) // and one to take next if the current prefix is not found (call it nextne). - // Since we have built ordered lists, all that remains is to properly intialize + // Since we have built ordered lists, all that remains is to properly initialize // the nextne and nexteq pointers that relate them process_pfx_order(); process_sfx_order(); - // expand wordchars string, based on csutil (for external tokenization) - + /* get encoding for CHECKCOMPOUNDCASE */ + if (!utf8) { char * enc = get_encoding(); csconv = get_current_cs(enc); free(enc); @@ -654,13 +758,16 @@ int AffixMgr::parse_file(const char * affpath) } wordchars = mystrdup(expw); + } - // temporary BREAK definition for German dash handling (OOo issue 64400) - if ((langnum == LANG_de) && (!breaktable)) { - breaktable = (char **) malloc(sizeof(char *)); + // default BREAK definition + if (numbreak == -1) { + breaktable = (char **) malloc(sizeof(char *) * 3); if (!breaktable) return 1; breaktable[0] = mystrdup("-"); - numbreak = 1; + breaktable[1] = mystrdup("^-"); + breaktable[2] = mystrdup("-$"); + if (breaktable[0] && breaktable[1] && breaktable[2]) numbreak = 3; } return 0; } @@ -670,28 +777,28 @@ int AffixMgr::parse_file(const char * affpath) // both by prefix flag, and sorted by prefix string itself // so we need to set up two indexes -int AffixMgr::build_pfxtree(AffEntry* pfxptr) +int AffixMgr::build_pfxtree(PfxEntry* pfxptr) { PfxEntry * ptr; PfxEntry * pptr; - PfxEntry * ep = (PfxEntry*) pfxptr; + PfxEntry * ep = pfxptr; // get the right starting points const char * key = ep->getKey(); const unsigned char flg = (unsigned char) (ep->getFlag() & 0x00FF); // first index by flag which must exist - ptr = (PfxEntry*)pFlag[flg]; + ptr = pFlag[flg]; ep->setFlgNxt(ptr); - pFlag[flg] = (AffEntry *) ep; + pFlag[flg] = ep; // handle the special case of null affix string if (strlen(key) == 0) { // always inset them at head of list at element 0 - ptr = (PfxEntry*)pStart[0]; + ptr = pStart[0]; ep->setNext(ptr); - pStart[0] = (AffEntry*)ep; + pStart[0] = ep; return 0; } @@ -700,11 +807,11 @@ int AffixMgr::build_pfxtree(AffEntry* pfxptr) ep->setNextNE(NULL); unsigned char sp = *((const unsigned char *)key); - ptr = (PfxEntry*)pStart[sp]; + ptr = pStart[sp]; // handle the first insert if (!ptr) { - pStart[sp] = (AffEntry*)ep; + pStart[sp] = ep; return 0; } @@ -734,29 +841,29 @@ int AffixMgr::build_pfxtree(AffEntry* pfxptr) // we want to be able to quickly access suffix information // both by suffix flag, and sorted by the reverse of the // suffix string itself; so we need to set up two indexes -int AffixMgr::build_sfxtree(AffEntry* sfxptr) +int AffixMgr::build_sfxtree(SfxEntry* sfxptr) { SfxEntry * ptr; SfxEntry * pptr; - SfxEntry * ep = (SfxEntry *) sfxptr; + SfxEntry * ep = sfxptr; /* get the right starting point */ const char * key = ep->getKey(); const unsigned char flg = (unsigned char) (ep->getFlag() & 0x00FF); // first index by flag which must exist - ptr = (SfxEntry*)sFlag[flg]; + ptr = sFlag[flg]; ep->setFlgNxt(ptr); - sFlag[flg] = (AffEntry *) ep; + sFlag[flg] = ep; // next index by affix string // handle the special case of null affix string if (strlen(key) == 0) { // always inset them at head of list at element 0 - ptr = (SfxEntry*)sStart[0]; + ptr = sStart[0]; ep->setNext(ptr); - sStart[0] = (AffEntry*)ep; + sStart[0] = ep; return 0; } @@ -765,11 +872,11 @@ int AffixMgr::build_sfxtree(AffEntry* sfxptr) ep->setNextNE(NULL); unsigned char sp = *((const unsigned char *)key); - ptr = (SfxEntry*)sStart[sp]; + ptr = sStart[sp]; // handle the first insert if (!ptr) { - sStart[sp] = (AffEntry*)ep; + sStart[sp] = ep; return 0; } @@ -805,12 +912,12 @@ int AffixMgr::process_pfx_tree_to_list() } -AffEntry* AffixMgr::process_pfx_in_order(AffEntry* ptr, AffEntry* nptr) +PfxEntry* AffixMgr::process_pfx_in_order(PfxEntry* ptr, PfxEntry* nptr) { if (ptr) { - nptr = process_pfx_in_order(((PfxEntry*) ptr)->getNextNE(), nptr); - ((PfxEntry*) ptr)->setNext((PfxEntry*) nptr); - nptr = process_pfx_in_order(((PfxEntry*) ptr)->getNextEQ(), ptr); + nptr = process_pfx_in_order(ptr->getNextNE(), nptr); + ptr->setNext(nptr); + nptr = process_pfx_in_order(ptr->getNextEQ(), ptr); } return nptr; } @@ -825,12 +932,12 @@ int AffixMgr:: process_sfx_tree_to_list() return 0; } -AffEntry* AffixMgr::process_sfx_in_order(AffEntry* ptr, AffEntry* nptr) +SfxEntry* AffixMgr::process_sfx_in_order(SfxEntry* ptr, SfxEntry* nptr) { if (ptr) { - nptr = process_sfx_in_order(((SfxEntry*) ptr)->getNextNE(), nptr); - ((SfxEntry*) ptr)->setNext((SfxEntry*) nptr); - nptr = process_sfx_in_order(((SfxEntry*) ptr)->getNextEQ(), ptr); + nptr = process_sfx_in_order(ptr->getNextNE(), nptr); + ptr->setNext(nptr); + nptr = process_sfx_in_order(ptr->getNextEQ(), ptr); } return nptr; } @@ -845,7 +952,7 @@ int AffixMgr::process_pfx_order() // loop through each prefix list starting point for (int i=1; i < SETSIZE; i++) { - ptr = (PfxEntry*)pStart[i]; + ptr = pStart[i]; // look through the remainder of the list // and find next entry with affix that @@ -871,7 +978,7 @@ int AffixMgr::process_pfx_order() // but not a subset of the next, search can end here // so set NextNE properly - ptr = (PfxEntry *) pStart[i]; + ptr = pStart[i]; for (; ptr != NULL; ptr = ptr->getNext()) { PfxEntry * nptr = ptr->getNext(); PfxEntry * mptr = NULL; @@ -894,7 +1001,7 @@ int AffixMgr::process_sfx_order() // loop through each prefix list starting point for (int i=1; i < SETSIZE; i++) { - ptr = (SfxEntry *) sStart[i]; + ptr = sStart[i]; // look through the remainder of the list // and find next entry with affix that @@ -920,7 +1027,7 @@ int AffixMgr::process_sfx_order() // but not a subset of the next, search can end here // so set NextNE properly - ptr = (SfxEntry *) sStart[i]; + ptr = sStart[i]; for (; ptr != NULL; ptr = ptr->getNext()) { SfxEntry * nptr = ptr->getNext(); SfxEntry * mptr = NULL; @@ -934,191 +1041,52 @@ int AffixMgr::process_sfx_order() return 0; } +// add flags to the result for dictionary debugging +void AffixMgr::debugflag(char * result, unsigned short flag) { + char * st = encode_flag(flag); + mystrcat(result, " ", MAXLNLEN); + mystrcat(result, MORPH_FLAG, MAXLNLEN); + if (st) { + mystrcat(result, st, MAXLNLEN); + free(st); + } +} - -// takes aff file condition string and creates the -// conds array - please see the appendix at the end of the -// file affentry.cxx which describes what is going on here -// in much more detail - -int AffixMgr::encodeit(struct affentry * ptr, char * cs) +// calculate the character length of the condition +int AffixMgr::condlen(char * st) { - unsigned char c; - int i, j, k; - unsigned char mbr[MAXLNLEN]; - w_char wmbr[MAXLNLEN]; - w_char * wpos = wmbr; - - // now clear the conditions array */ - for (i=0;iconds.base[i] = (unsigned char) 0; - - // now parse the string to create the conds array */ - int nc = strlen(cs); - unsigned char neg = 0; // complement indicator - int grp = 0; // group indicator - unsigned char n = 0; // number of conditions - int ec = 0; // end condition indicator - int nm = 0; // number of member in group - - // if no condition just return - if (strcmp(cs,".")==0) { - ptr->numconds = 0; - return 0; + int l = 0; + bool group = false; + for(; *st; st++) { + if (*st == '[') { + group = true; + l++; + } else if (*st == ']') group = false; + else if (!group && (!utf8 || + (!(*st & 0x80) || ((*st & 0xc0) == 0x80)))) l++; } + return l; +} - i = 0; - while (i < nc) { - c = *((unsigned char *)(cs + i)); - - // start group indicator - if (c == '[') { - grp = 1; - c = 0; - } - - // complement flag - if ((grp == 1) && (c == '^')) { - neg = 1; - c = 0; - } - - // end goup indicator - if (c == ']') { - ec = 1; - c = 0; - } - - // add character of group to list - if ((grp == 1) && (c != 0)) { - *(mbr + nm) = c; - nm++; - c = 0; - } - - // end of condition - if (c != 0) { - ec = 1; +int AffixMgr::encodeit(affentry &entry, char * cs) +{ + if (strcmp(cs,".") != 0) { + entry.numconds = (char) condlen(cs); + strncpy(entry.c.conds, cs, MAXCONDLEN); + // long condition (end of conds padded by strncpy) + if (entry.c.conds[MAXCONDLEN - 1] && cs[MAXCONDLEN]) { + entry.opts += aeLONGCOND; + entry.c.l.conds2 = mystrdup(cs + MAXCONDLEN_1); + if (!entry.c.l.conds2) return 1; } - - if (ec) { - if (!utf8) { - if (grp == 1) { - if (neg == 0) { - // set the proper bits in the condition array vals for those chars - for (j=0;jconds.base[k] = ptr->conds.base[k] | ((unsigned char)1 << n); - } - } else { - // complement so set all of them and then unset indicated ones - for (j=0;jconds.base[j] = ptr->conds.base[j] | ((unsigned char)1 << n); - for (j=0;jconds.base[k] = ptr->conds.base[k] & ~((unsigned char)1 << n); - } - } - neg = 0; - grp = 0; - nm = 0; - } else { - // not a group so just set the proper bit for this char - // but first handle special case of . inside condition - if (c == '.') { - // wild card character so set them all - for (j=0;jconds.base[j] = ptr->conds.base[j] | ((unsigned char)1 << n); - } else { - ptr->conds.base[(unsigned int) c] = ptr->conds.base[(unsigned int)c] | ((unsigned char)1 << n); - } - } - n++; - ec = 0; - } else { // UTF-8 character set - if (grp == 1) { - ptr->conds.utf8.neg[n] = neg; - if (neg == 0) { - // set the proper bits in the condition array vals for those chars - for (j=0;j> 7) { - u8_u16(wpos, 1, (char *) mbr + j); - wpos++; - if ((k & 0xe0) == 0xe0) j+=2; else j++; // 3-byte UTF-8 character - } else { - ptr->conds.utf8.ascii[k] = ptr->conds.utf8.ascii[k] | ((unsigned char)1 << n); - } - } - } else { // neg == 1 - // complement so set all of them and then unset indicated ones - for (j=0;j<(SETSIZE/2);j++) ptr->conds.utf8.ascii[j] = ptr->conds.utf8.ascii[j] | ((unsigned char)1 << n); - for (j=0;j> 7) { - u8_u16(wpos, 1, (char *) mbr + j); - wpos++; - if ((k & 0xe0) == 0xe0) j+=2; else j++; // 3-byte UTF-8 character - } else { - ptr->conds.utf8.ascii[k] = ptr->conds.utf8.ascii[k] & ~((unsigned char)1 << n); - } - } - } - neg = 0; - grp = 0; - nm = 0; - ptr->conds.utf8.wlen[n] = wpos - wmbr; - if ((wpos - wmbr) != 0) { - ptr->conds.utf8.wchars[n] = (w_char *) malloc(sizeof(w_char) * (wpos - wmbr)); - if (!ptr->conds.utf8.wchars[n]) return 1; - memcpy(ptr->conds.utf8.wchars[n], wmbr, sizeof(w_char) * (wpos - wmbr)); - flag_qsort((unsigned short *) ptr->conds.utf8.wchars[n], 0, ptr->conds.utf8.wlen[n]); - wpos = wmbr; - } - } else { // grp == 0 - // is UTF-8 character? - if (c >> 7) { - ptr->conds.utf8.wchars[n] = (w_char *) malloc(sizeof(w_char)); - if (!ptr->conds.utf8.wchars[n]) return 1; - ptr->conds.utf8.wlen[n] = 1; - u8_u16(ptr->conds.utf8.wchars[n], 1, cs + i); - if ((c & 0xe0) == 0xe0) i+=2; else i++; // 3-byte UFT-8 character - } else { - ptr->conds.utf8.wchars[n] = NULL; - // not a group so just set the proper bit for this char - // but first handle special case of . inside condition - if (c == '.') { - ptr->conds.utf8.all[n] = 1; - // wild card character so set them all - for (j=0;j<(SETSIZE/2);j++) ptr->conds.utf8.ascii[j] = ptr->conds.utf8.ascii[j] | ((unsigned char)1 << n); - } else { - ptr->conds.utf8.all[n] = 0; - ptr->conds.utf8.ascii[(unsigned int) c] = ptr->conds.utf8.ascii[(unsigned int)c] | ((unsigned char)1 << n); - } - } - neg = 0; - } - n++; - ec = 0; - neg = 0; - } - } - - i++; + } else { + entry.numconds = 0; + entry.c.conds[0] = '\0'; } - ptr->numconds = n; return 0; } - // return 1 if s1 is a leading subset of s2 -/* inline int AffixMgr::isSubset(const char * s1, const char * s2) - { - while ((*s1 == *s2) && *s1) { - s1++; - s2++; - } - return (*s1 == '\0'); - } -*/ - - // return 1 if s1 is a leading subset of s2 (dots are for infixes) +// return 1 if s1 is a leading subset of s2 (dots are for infixes) inline int AffixMgr::isSubset(const char * s1, const char * s2) { while (((*s1 == *s2) || (*s1 == '.')) && (*s1 != '\0')) { @@ -1140,7 +1108,7 @@ struct hentry * AffixMgr::prefix_check(const char * word, int len, char in_compo sfxappnd = NULL; // first handle the special case of 0 length prefixes - PfxEntry * pe = (PfxEntry *) pStart[0]; + PfxEntry * pe = pStart[0]; while (pe) { if ( // fogemorpheme @@ -1153,7 +1121,7 @@ struct hentry * AffixMgr::prefix_check(const char * word, int len, char in_compo // check prefix rv = pe->checkword(word, len, in_compound, needflag); if (rv) { - pfx=(AffEntry *)pe; // BUG: pfx not stateless + pfx=pe; // BUG: pfx not stateless return rv; } } @@ -1162,7 +1130,7 @@ struct hentry * AffixMgr::prefix_check(const char * word, int len, char in_compo // now handle the general case unsigned char sp = *((const unsigned char *)word); - PfxEntry * pptr = (PfxEntry *)pStart[sp]; + PfxEntry * pptr = pStart[sp]; while (pptr) { if (isSubset(pptr->getKey(),word)) { @@ -1177,7 +1145,7 @@ struct hentry * AffixMgr::prefix_check(const char * word, int len, char in_compo // check prefix rv = pptr->checkword(word, len, in_compound, needflag); if (rv) { - pfx=(AffEntry *)pptr; // BUG: pfx not stateless + pfx=pptr; // BUG: pfx not stateless return rv; } } @@ -1200,7 +1168,7 @@ struct hentry * AffixMgr::prefix_check_twosfx(const char * word, int len, sfxappnd = NULL; // first handle the special case of 0 length prefixes - PfxEntry * pe = (PfxEntry *) pStart[0]; + PfxEntry * pe = pStart[0]; while (pe) { rv = pe->check_twosfx(word, len, in_compound, needflag); @@ -1210,13 +1178,13 @@ struct hentry * AffixMgr::prefix_check_twosfx(const char * word, int len, // now handle the general case unsigned char sp = *((const unsigned char *)word); - PfxEntry * pptr = (PfxEntry *)pStart[sp]; + PfxEntry * pptr = pStart[sp]; while (pptr) { if (isSubset(pptr->getKey(),word)) { rv = pptr->check_twosfx(word, len, in_compound, needflag); if (rv) { - pfx = (AffEntry *)pptr; + pfx = pptr; return rv; } pptr = pptr->getNextEQ(); @@ -1228,7 +1196,6 @@ struct hentry * AffixMgr::prefix_check_twosfx(const char * word, int len, return NULL; } -#ifdef HUNSPELL_EXPERIMENTAL // check word for prefixes char * AffixMgr::prefix_check_morph(const char * word, int len, char in_compound, const FLAG needflag) @@ -1242,11 +1209,11 @@ char * AffixMgr::prefix_check_morph(const char * word, int len, char in_compound sfxappnd = NULL; // first handle the special case of 0 length prefixes - PfxEntry * pe = (PfxEntry *) pStart[0]; + PfxEntry * pe = pStart[0]; while (pe) { st = pe->check_morph(word,len,in_compound, needflag); if (st) { - strcat(result, st); + mystrcat(result, st, MAXLNLEN); free(st); } // if (rv) return rv; @@ -1255,7 +1222,7 @@ char * AffixMgr::prefix_check_morph(const char * word, int len, char in_compound // now handle the general case unsigned char sp = *((const unsigned char *)word); - PfxEntry * pptr = (PfxEntry *)pStart[sp]; + PfxEntry * pptr = pStart[sp]; while (pptr) { if (isSubset(pptr->getKey(),word)) { @@ -1264,8 +1231,8 @@ char * AffixMgr::prefix_check_morph(const char * word, int len, char in_compound // fogemorpheme if ((in_compound != IN_CPD_NOT) || !((pptr->getCont() && (TESTAFF(pptr->getCont(), onlyincompound, pptr->getContLen()))))) { - strcat(result, st); - pfx = (AffEntry *)pptr; + mystrcat(result, st, MAXLNLEN); + pfx = pptr; } free(st); } @@ -1293,11 +1260,11 @@ char * AffixMgr::prefix_check_twosfx_morph(const char * word, int len, sfxappnd = NULL; // first handle the special case of 0 length prefixes - PfxEntry * pe = (PfxEntry *) pStart[0]; + PfxEntry * pe = pStart[0]; while (pe) { st = pe->check_twosfx_morph(word,len,in_compound, needflag); if (st) { - strcat(result, st); + mystrcat(result, st, MAXLNLEN); free(st); } pe = pe->getNext(); @@ -1305,15 +1272,15 @@ char * AffixMgr::prefix_check_twosfx_morph(const char * word, int len, // now handle the general case unsigned char sp = *((const unsigned char *)word); - PfxEntry * pptr = (PfxEntry *)pStart[sp]; + PfxEntry * pptr = pStart[sp]; while (pptr) { if (isSubset(pptr->getKey(),word)) { st = pptr->check_twosfx_morph(word, len, in_compound, needflag); if (st) { - strcat(result, st); + mystrcat(result, st, MAXLNLEN); free(st); - pfx = (AffEntry *)pptr; + pfx = pptr; } pptr = pptr->getNextEQ(); } else { @@ -1324,8 +1291,6 @@ char * AffixMgr::prefix_check_twosfx_morph(const char * word, int len, if (*result) return mystrdup(result); return NULL; } -#endif // END OF HUNSPELL_EXPERIMENTAL CODE - // Is word a non compound with a REP substitution (see checkcompoundrep)? int AffixMgr::cpdrep_check(const char * word, int wl) @@ -1354,13 +1319,23 @@ int AffixMgr::cpdrep_check(const char * word, int wl) } // forbid compoundings when there are special patterns at word bound -int AffixMgr::cpdpat_check(const char * word, int pos) +int AffixMgr::cpdpat_check(const char * word, int pos, hentry * r1, hentry * r2, const char affixed) { int len; for (int i = 0; i < numcheckcpd; i++) { if (isSubset(checkcpdtable[i].pattern2, word + pos) && - (len = strlen(checkcpdtable[i].pattern)) && (pos > len) && - (strncmp(word + pos - len, checkcpdtable[i].pattern, len) == 0)) return 1; + (!r1 || !checkcpdtable[i].cond || + (r1->astr && TESTAFF(r1->astr, checkcpdtable[i].cond, r1->alen))) && + (!r2 || !checkcpdtable[i].cond2 || + (r2->astr && TESTAFF(r2->astr, checkcpdtable[i].cond2, r2->alen))) && + // zero length pattern => only TESTAFF + // zero pattern (0/flag) => unmodified stem (zero affixes allowed) + (!*(checkcpdtable[i].pattern) || ( + (*(checkcpdtable[i].pattern)=='0' && r1->blen <= pos && strncmp(word + pos - r1->blen, r1->word, r1->blen) == 0) || + (*(checkcpdtable[i].pattern)!='0' && (len = strlen(checkcpdtable[i].pattern)) && + strncmp(word + pos - len, checkcpdtable[i].pattern, len) == 0)))) { + return 1; + } } return 0; } @@ -1376,7 +1351,8 @@ int AffixMgr::cpdcase_check(const char * word, int pos) u8_u16(&w, 1, p); unsigned short a = (u.h << 8) + u.l; unsigned short b = (w.h << 8) + w.l; - if (((unicodetoupper(a, langnum) == a) || (unicodetoupper(b, langnum) == b))) return 1; + if (((unicodetoupper(a, langnum) == a) || (unicodetoupper(b, langnum) == b)) && + (a != '-') && (b != '-')) return 1; } else { unsigned char a = *(word + pos - 1); unsigned char b = *(word + pos); @@ -1392,15 +1368,40 @@ int AffixMgr::defcpd_check(hentry *** words, short wnum, hentry * rv, hentry ** signed short btwp[MAXWORDLEN]; // word positions for metacharacters int btnum[MAXWORDLEN]; // number of matched characters in metacharacter positions short bt = 0; - int i; + int i, j; int ok; int w = 0; + if (!*words) { w = 1; *words = def; } + + if (!*words) { + return 0; + } + (*words)[wnum] = rv; + // has the last word COMPOUNDRULE flag? + if (rv->alen == 0) { + (*words)[wnum] = NULL; + if (w) *words = NULL; + return 0; + } + ok = 0; + for (i = 0; i < numdefcpd; i++) { + for (j = 0; j < defcpdtable[i].len; j++) { + if (defcpdtable[i].def[j] != '*' && defcpdtable[i].def[j] != '?' && + TESTAFF(rv->astr, defcpdtable[i].def[j], rv->alen)) ok = 1; + } + } + if (ok == 0) { + (*words)[wnum] = NULL; + if (w) *words = NULL; + return 0; + } + for (i = 0; i < numdefcpd; i++) { signed short pp = 0; // pattern position signed short wp = 0; // "words" position @@ -1445,17 +1446,18 @@ int AffixMgr::defcpd_check(hentry *** words, short wnum, hentry * rv, hentry ** while ((defcpdtable[i].len > r) && ((r+1) < defcpdtable[i].len) && ((defcpdtable[i].def[r+1] == '*') || (defcpdtable[i].def[r+1] == '?'))) r+=2; if (defcpdtable[i].len <= r) return 1; - } + } // backtrack if (bt) do { ok = 1; btnum[bt - 1]--; pp = btpp[bt - 1]; - wp = btwp[bt - 1] + btnum[bt - 1]; + wp = btwp[bt - 1] + (signed short) btnum[bt - 1]; } while ((btnum[bt - 1] < 0) && --bt); } while (bt); - if (ok && ok2 && (!all || (defcpdtable[i].len <= pp))) return 1; + if (ok && ok2 && (!all || (defcpdtable[i].len <= pp))) return 1; + // check zero ending while (ok && ok2 && (defcpdtable[i].len > pp) && ((pp+1) < defcpdtable[i].len) && ((defcpdtable[i].def[pp+1] == '*') || (defcpdtable[i].def[pp+1] == '?'))) pp+=2; @@ -1495,7 +1497,7 @@ short AffixMgr::get_syllable(const char * word, int wlen) } else if (cpdvowels_utf16) { w_char w[MAXWORDUTF8LEN]; int i = u8_u16(w, MAXWORDUTF8LEN, word); - for (; i; i--) { + for (; i > 0; i--) { if (flag_bsearch((unsigned short *) cpdvowels_utf16, ((unsigned short *) w)[i - 1], cpdvowels_utf16_len)) num++; } @@ -1503,101 +1505,138 @@ short AffixMgr::get_syllable(const char * word, int wlen) return num; } +void AffixMgr::setcminmax(int * cmin, int * cmax, const char * word, int len) { + if (utf8) { + int i; + for (*cmin = 0, i = 0; (i < cpdmin) && word[*cmin]; i++) { + for ((*cmin)++; (word[*cmin] & 0xc0) == 0x80; (*cmin)++); + } + for (*cmax = len, i = 0; (i < (cpdmin - 1)) && *cmax; i++) { + for ((*cmax)--; (word[*cmax] & 0xc0) == 0x80; (*cmax)--); + } + } else { + *cmin = cpdmin; + *cmax = len - cpdmin + 1; + } +} + + // check if compound word is correctly spelled // hu_mov_rule = spec. Hungarian rule (XXX) struct hentry * AffixMgr::compound_check(const char * word, int len, short wordnum, short numsyllable, short maxwordnum, short wnum, hentry ** words = NULL, - char hu_mov_rule = 0, int * cmpdstemnum = NULL, int * cmpdstem = NULL, char is_sug = 0) + char hu_mov_rule = 0, char is_sug = 0, int * info = NULL) { int i; short oldnumsyllable, oldnumsyllable2, oldwordnum, oldwordnum2; - int oldcmpdstemnum = 0; struct hentry * rv = NULL; struct hentry * rv_first; struct hentry * rwords[MAXWORDLEN]; // buffer for COMPOUND pattern checking char st [MAXWORDUTF8LEN + 4]; - char ch; + char ch = '\0'; int cmin; int cmax; - + int striple = 0; + int scpd = 0; + int soldi = 0; + int oldcmin = 0; + int oldcmax = 0; + int oldlen = 0; + int checkedstriple = 0; + int onlycpdrule; + int affixed = 0; + hentry ** oldwords = words; + int checked_prefix; -#ifdef HUNSTEM - if (cmpdstemnum) { - if (wordnum == 0) { - *cmpdstemnum = 1; - } else { - (*cmpdstemnum)++; - } - } -#endif - if (utf8) { - for (cmin = 0, i = 0; (i < cpdmin) && word[cmin]; i++) { - cmin++; - for (; (word[cmin] & 0xc0) == 0x80; cmin++); - } - for (cmax = len, i = 0; (i < (cpdmin - 1)) && cmax; i++) { - cmax--; - for (; (word[cmax] & 0xc0) == 0x80; cmax--); - } - } else { - cmin = cpdmin; - cmax = len - cpdmin + 1; - } + setcminmax(&cmin, &cmax, word, len); strcpy(st, word); for (i = cmin; i < cmax; i++) { + // go to end of the UTF-8 character + if (utf8) { + for (; (st[i] & 0xc0) == 0x80; i++); + if (i >= cmax) return NULL; + } + + words = oldwords; + onlycpdrule = (words) ? 1 : 0; + + do { // onlycpdrule loop oldnumsyllable = numsyllable; oldwordnum = wordnum; checked_prefix = 0; - // go to end of the UTF-8 character - if (utf8) { - for (; (st[i] & 0xc0) == 0x80; i++); - if (i >= cmax) return NULL; + + do { // simplified checkcompoundpattern loop + + if (scpd > 0) { + for (; scpd <= numcheckcpd && (!checkcpdtable[scpd-1].pattern3 || + strncmp(word + i, checkcpdtable[scpd-1].pattern3, strlen(checkcpdtable[scpd-1].pattern3)) != 0); scpd++); + + if (scpd > numcheckcpd) break; // break simplified checkcompoundpattern loop + strcpy(st + i, checkcpdtable[scpd-1].pattern); + soldi = i; + i += strlen(checkcpdtable[scpd-1].pattern); + strcpy(st + i, checkcpdtable[scpd-1].pattern2); + strcpy(st + i + strlen(checkcpdtable[scpd-1].pattern2), word + soldi + strlen(checkcpdtable[scpd-1].pattern3)); + + oldlen = len; + len += strlen(checkcpdtable[scpd-1].pattern) + strlen(checkcpdtable[scpd-1].pattern2) - strlen(checkcpdtable[scpd-1].pattern3); + oldcmin = cmin; + oldcmax = cmax; + setcminmax(&cmin, &cmax, st, len); + + cmax = len - cpdmin + 1; } - ch = st[i]; st[i] = '\0'; sfx = NULL; pfx = NULL; - + // FIRST WORD - + + affixed = 1; rv = lookup(st); // perhaps without prefix // search homonym with compound flag while ((rv) && !hu_mov_rule && - ((pseudoroot && TESTAFF(rv->astr, pseudoroot, rv->alen)) || - !((compoundflag && !words && TESTAFF(rv->astr, compoundflag, rv->alen)) || - (compoundbegin && !wordnum && + ((needaffix && TESTAFF(rv->astr, needaffix, rv->alen)) || + !((compoundflag && !words && !onlycpdrule && TESTAFF(rv->astr, compoundflag, rv->alen)) || + (compoundbegin && !wordnum && !onlycpdrule && TESTAFF(rv->astr, compoundbegin, rv->alen)) || - (compoundmiddle && wordnum && !words && + (compoundmiddle && wordnum && !words && !onlycpdrule && TESTAFF(rv->astr, compoundmiddle, rv->alen)) || - (numdefcpd && + (numdefcpd && onlycpdrule && ((!words && !wordnum && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0)) || - (words && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0)))) - ))) { + (words && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0))))) || + (scpd != 0 && checkcpdtable[scpd-1].cond != FLAG_NULL && + !TESTAFF(rv->astr, checkcpdtable[scpd-1].cond, rv->alen))) + ) { rv = rv->next_homonym; } + if (rv) affixed = 0; + if (!rv) { + if (onlycpdrule) break; if (compoundflag && !(rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundflag))) { if ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundflag, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) && !hu_mov_rule && - ((SfxEntry*)sfx)->getCont() && - ((compoundforbidflag && TESTAFF(((SfxEntry*)sfx)->getCont(), compoundforbidflag, - ((SfxEntry*)sfx)->getContLen())) || (compoundend && - TESTAFF(((SfxEntry*)sfx)->getCont(), compoundend, - ((SfxEntry*)sfx)->getContLen())))) { + sfx->getCont() && + ((compoundforbidflag && TESTAFF(sfx->getCont(), compoundforbidflag, + sfx->getContLen())) || (compoundend && + TESTAFF(sfx->getCont(), compoundend, + sfx->getContLen())))) { rv = NULL; } } + if (rv || (((wordnum == 0) && compoundbegin && ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundbegin, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) || @@ -1606,50 +1645,53 @@ struct hentry * AffixMgr::compound_check(const char * word, int len, ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundmiddle, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) || (rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundmiddle))))) ) checked_prefix = 1; - // else check forbiddenwords and pseudoroot + // else check forbiddenwords and needaffix } else if (rv->astr && (TESTAFF(rv->astr, forbiddenword, rv->alen) || - TESTAFF(rv->astr, pseudoroot, rv->alen) || + TESTAFF(rv->astr, needaffix, rv->alen) || + TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) || (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen)) )) { st[i] = ch; - continue; + //continue; + break; } // check non_compound flag in suffix and prefix if ((rv) && !hu_mov_rule && - ((pfx && ((PfxEntry*)pfx)->getCont() && - TESTAFF(((PfxEntry*)pfx)->getCont(), compoundforbidflag, - ((PfxEntry*)pfx)->getContLen())) || - (sfx && ((SfxEntry*)sfx)->getCont() && - TESTAFF(((SfxEntry*)sfx)->getCont(), compoundforbidflag, - ((SfxEntry*)sfx)->getContLen())))) { + ((pfx && pfx->getCont() && + TESTAFF(pfx->getCont(), compoundforbidflag, + pfx->getContLen())) || + (sfx && sfx->getCont() && + TESTAFF(sfx->getCont(), compoundforbidflag, + sfx->getContLen())))) { rv = NULL; } // check compoundend flag in suffix and prefix if ((rv) && !checked_prefix && compoundend && !hu_mov_rule && - ((pfx && ((PfxEntry*)pfx)->getCont() && - TESTAFF(((PfxEntry*)pfx)->getCont(), compoundend, - ((PfxEntry*)pfx)->getContLen())) || - (sfx && ((SfxEntry*)sfx)->getCont() && - TESTAFF(((SfxEntry*)sfx)->getCont(), compoundend, - ((SfxEntry*)sfx)->getContLen())))) { + ((pfx && pfx->getCont() && + TESTAFF(pfx->getCont(), compoundend, + pfx->getContLen())) || + (sfx && sfx->getCont() && + TESTAFF(sfx->getCont(), compoundend, + sfx->getContLen())))) { rv = NULL; } - + // check compoundmiddle flag in suffix and prefix if ((rv) && !checked_prefix && (wordnum==0) && compoundmiddle && !hu_mov_rule && - ((pfx && ((PfxEntry*)pfx)->getCont() && - TESTAFF(((PfxEntry*)pfx)->getCont(), compoundmiddle, - ((PfxEntry*)pfx)->getContLen())) || - (sfx && ((SfxEntry*)sfx)->getCont() && - TESTAFF(((SfxEntry*)sfx)->getCont(), compoundmiddle, - ((SfxEntry*)sfx)->getContLen())))) { + ((pfx && pfx->getCont() && + TESTAFF(pfx->getCont(), compoundmiddle, + pfx->getContLen())) || + (sfx && sfx->getCont() && + TESTAFF(sfx->getCont(), compoundmiddle, + sfx->getContLen())))) { rv = NULL; - } + } // check forbiddenwords if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) || + TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) || (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen)))) { return NULL; } @@ -1676,63 +1718,78 @@ struct hentry * AffixMgr::compound_check(const char * word, int len, ) ) // END of LANG_hu section + ) && + ( + // test CHECKCOMPOUNDPATTERN conditions + scpd == 0 || checkcpdtable[scpd-1].cond == FLAG_NULL || + TESTAFF(rv->astr, checkcpdtable[scpd-1].cond, rv->alen) ) - && ! (( checkcompoundtriple && // test triple letters + && ! (( checkcompoundtriple && scpd == 0 && !words && // test triple letters (word[i-1]==word[i]) && ( - ((i>1) && (word[i-1]==word[i-2])) || + ((i>1) && (word[i-1]==word[i-2])) || ((word[i-1]==word[i+1])) // may be word[i+1] == '\0' ) ) || - ( - // test CHECKCOMPOUNDPATTERN - numcheckcpd && cpdpat_check(word, i) - ) || - ( - checkcompoundcase && cpdcase_check(word, i) + ( + checkcompoundcase && scpd == 0 && !words && cpdcase_check(word, i) )) ) // LANG_hu section: spec. Hungarian rule || ((!rv) && (langnum == LANG_hu) && hu_mov_rule && (rv = affix_check(st,i)) && - (sfx && ((SfxEntry*)sfx)->getCont() && ( // XXX hardwired Hungarian dic. codes - TESTAFF(((SfxEntry*)sfx)->getCont(), (unsigned short) 'x', ((SfxEntry*)sfx)->getContLen()) || - TESTAFF(((SfxEntry*)sfx)->getCont(), (unsigned short) '%', ((SfxEntry*)sfx)->getContLen()) - ) + (sfx && sfx->getCont() && ( // XXX hardwired Hungarian dic. codes + TESTAFF(sfx->getCont(), (unsigned short) 'x', sfx->getContLen()) || + TESTAFF(sfx->getCont(), (unsigned short) '%', sfx->getContLen()) + ) ) ) -// END of LANG_hu section - ) { + ) { // first word is ok condition // LANG_hu section: spec. Hungarian rule if (langnum == LANG_hu) { - // calculate syllable number of the word + // calculate syllable number of the word numsyllable += get_syllable(st, i); - // + 1 word, if syllable number of the prefix > 1 (hungarian convention) - if (pfx && (get_syllable(((PfxEntry *)pfx)->getKey(),strlen(((PfxEntry *)pfx)->getKey())) > 1)) wordnum++; + if (pfx && (get_syllable(pfx->getKey(),strlen(pfx->getKey())) > 1)) wordnum++; } // END of LANG_hu section -#ifdef HUNSTEM - if (cmpdstem) cmpdstem[*cmpdstemnum - 1] = i; -#endif - // NEXT WORD(S) rv_first = rv; - rv = lookup((word+i)); // perhaps without prefix + st[i] = ch; + + do { // striple loop + + // check simplifiedtriple + if (simplifiedtriple) { + if (striple) { + checkedstriple = 1; + i--; // check "fahrt" instead of "ahrt" in "Schiffahrt" + } else if (i > 2 && *(word+i - 1) == *(word + i - 2)) striple = 1; + } + + rv = lookup((st+i)); // perhaps without prefix // search homonym with compound flag - while ((rv) && ((pseudoroot && TESTAFF(rv->astr, pseudoroot, rv->alen)) || + while ((rv) && ((needaffix && TESTAFF(rv->astr, needaffix, rv->alen)) || !((compoundflag && !words && TESTAFF(rv->astr, compoundflag, rv->alen)) || (compoundend && !words && TESTAFF(rv->astr, compoundend, rv->alen)) || - (numdefcpd && words && defcpd_check(&words, wnum + 1, rv, NULL,1))))) { + (numdefcpd && words && defcpd_check(&words, wnum + 1, rv, NULL,1))) || + (scpd != 0 && checkcpdtable[scpd-1].cond2 != FLAG_NULL && + !TESTAFF(rv->astr, checkcpdtable[scpd-1].cond2, rv->alen)) + )) { rv = rv->next_homonym; } - if (rv && words && words[wnum + 1]) return rv; + // check FORCEUCASE + if (rv && forceucase && (rv) && + (TESTAFF(rv->astr, forceucase, rv->alen)) && !(info && *info & SPELL_ORIGCAP)) rv = NULL; + + if (rv && words && words[wnum + 1]) return rv_first; oldnumsyllable2 = numsyllable; oldwordnum2 = wordnum; + // LANG_hu section: spec. Hungarian rule, XXX hardwired dictionary code if ((rv) && (langnum == LANG_hu) && (TESTAFF(rv->astr, 'I', rv->alen)) && !(TESTAFF(rv->astr, 'J', rv->alen))) { numsyllable--; @@ -1747,6 +1804,7 @@ struct hentry * AffixMgr::compound_check(const char * word, int len, // check forbiddenwords if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) || + TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) || (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen)))) return NULL; // second word is acceptable, as a root? @@ -1760,50 +1818,70 @@ struct hentry * AffixMgr::compound_check(const char * word, int len, ) && ( ((cpdwordmax==-1) || (wordnum+1word,rv->wlen)<=cpdmaxsyllable)) - ) - && ( + ((cpdmaxsyllable!=0) && + (numsyllable + get_syllable(HENTRY_WORD(rv), rv->clen)<=cpdmaxsyllable)) + ) && + ( + // test CHECKCOMPOUNDPATTERN + !numcheckcpd || scpd != 0 || !cpdpat_check(word, i, rv_first, rv, 0) + ) && + ( (!checkcompounddup || (rv != rv_first)) ) + // test CHECKCOMPOUNDPATTERN conditions + && (scpd == 0 || checkcpdtable[scpd-1].cond2 == FLAG_NULL || + TESTAFF(rv->astr, checkcpdtable[scpd-1].cond2, rv->alen)) ) { // forbid compound word, if it is a non compound word with typical fault if (checkcompoundrep && cpdrep_check(word,len)) return NULL; - return rv; + return rv_first; } - numsyllable = oldnumsyllable2 ; + numsyllable = oldnumsyllable2; wordnum = oldwordnum2; // perhaps second word has prefix or/and suffix sfx = NULL; sfxflag = FLAG_NULL; - rv = (compoundflag) ? affix_check((word+i),strlen(word+i), compoundflag, IN_CPD_END) : NULL; - if (!rv && compoundend) { + rv = (compoundflag && !onlycpdrule) ? affix_check((word+i),strlen(word+i), compoundflag, IN_CPD_END) : NULL; + if (!rv && compoundend && !onlycpdrule) { sfx = NULL; pfx = NULL; rv = affix_check((word+i),strlen(word+i), compoundend, IN_CPD_END); } - + if (!rv && numdefcpd && words) { rv = affix_check((word+i),strlen(word+i), 0, IN_CPD_END); - if (rv && defcpd_check(&words, wnum + 1, rv, NULL, 1)) return rv; + if (rv && defcpd_check(&words, wnum + 1, rv, NULL, 1)) return rv_first; + rv = NULL; } + // test CHECKCOMPOUNDPATTERN conditions (allowed forms) + if (rv && !(scpd == 0 || checkcpdtable[scpd-1].cond2 == FLAG_NULL || + TESTAFF(rv->astr, checkcpdtable[scpd-1].cond2, rv->alen))) rv = NULL; + + // test CHECKCOMPOUNDPATTERN conditions (forbidden compounds) + if (rv && numcheckcpd && scpd == 0 && cpdpat_check(word, i, rv_first, rv, affixed)) rv = NULL; + // check non_compound flag in suffix and prefix if ((rv) && - ((pfx && ((PfxEntry*)pfx)->getCont() && - TESTAFF(((PfxEntry*)pfx)->getCont(), compoundforbidflag, - ((PfxEntry*)pfx)->getContLen())) || - (sfx && ((SfxEntry*)sfx)->getCont() && - TESTAFF(((SfxEntry*)sfx)->getCont(), compoundforbidflag, - ((SfxEntry*)sfx)->getContLen())))) { + ((pfx && pfx->getCont() && + TESTAFF(pfx->getCont(), compoundforbidflag, + pfx->getContLen())) || + (sfx && sfx->getCont() && + TESTAFF(sfx->getCont(), compoundforbidflag, + sfx->getContLen())))) { rv = NULL; } + // check FORCEUCASE + if (rv && forceucase && (rv) && + (TESTAFF(rv->astr, forceucase, rv->alen)) && !(info && *info & SPELL_ORIGCAP)) rv = NULL; + // check forbiddenwords if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) || + TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) || (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen)))) return NULL; // pfxappnd = prefix of word+i, or NULL @@ -1814,7 +1892,7 @@ struct hentry * AffixMgr::compound_check(const char * word, int len, if (langnum == LANG_hu) { // calculate syllable number of the word numsyllable += get_syllable(word + i, strlen(word + i)); - + // - affix syllable num. // XXX only second suffix (inflections, not derivations) if (sfxappnd) { @@ -1822,22 +1900,22 @@ struct hentry * AffixMgr::compound_check(const char * word, int len, numsyllable -= get_syllable(tmp, strlen(tmp)); free(tmp); } - + // + 1 word, if syllable number of the prefix > 1 (hungarian convention) - if (pfx && (get_syllable(((PfxEntry *)pfx)->getKey(),strlen(((PfxEntry *)pfx)->getKey())) > 1)) wordnum++; + if (pfx && (get_syllable(pfx->getKey(),strlen(pfx->getKey())) > 1)) wordnum++; // increment syllable num, if last word has a SYLLABLENUM flag // and the suffix is beginning `s' - + if (cpdsyllablenum) { switch (sfxflag) { case 'c': { numsyllable+=2; break; } case 'J': { numsyllable += 1; break; } - case 'I': { if (TESTAFF(rv->astr, 'J', rv->alen)) numsyllable += 1; break; } + case 'I': { if (rv && TESTAFF(rv->astr, 'J', rv->alen)) numsyllable += 1; break; } } } } - + // increment word number, if the second word has a compoundroot flag if ((rv) && (compoundroot) && (TESTAFF(rv->astr, compoundroot, rv->alen))) { @@ -1851,7 +1929,7 @@ struct hentry * AffixMgr::compound_check(const char * word, int len, if ((rv) && ( ((cpdwordmax == -1) || (wordnum + 1 < cpdwordmax)) || - ((cpdmaxsyllable == 0) || + ((cpdmaxsyllable != 0) && (numsyllable <= cpdmaxsyllable)) ) && ( @@ -1859,41 +1937,91 @@ struct hentry * AffixMgr::compound_check(const char * word, int len, )) { // forbid compound word, if it is a non compound word with typical fault if (checkcompoundrep && cpdrep_check(word, len)) return NULL; - return rv; + return rv_first; } numsyllable = oldnumsyllable2; wordnum = oldwordnum2; -#ifdef HUNSTEM - if (cmpdstemnum) oldcmpdstemnum = *cmpdstemnum; -#endif + // perhaps second word is a compound word (recursive call) if (wordnum < maxwordnum) { - rv = compound_check((word+i),strlen(word+i), wordnum+1, - numsyllable, maxwordnum, wnum + 1, words, - 0, cmpdstemnum, cmpdstem, is_sug); + rv = compound_check((st+i),strlen(st+i), wordnum+1, + numsyllable, maxwordnum, wnum + 1, words, 0, is_sug, info); + + if (rv && numcheckcpd && ((scpd == 0 && cpdpat_check(word, i, rv_first, rv, affixed)) || + (scpd != 0 && !cpdpat_check(word, i, rv_first, rv, affixed)))) rv = NULL; } else { rv=NULL; } if (rv) { // forbid compound word, if it is a non compound word with typical fault - if (checkcompoundrep && cpdrep_check(word, len)) return NULL; - return rv; - } else { -#ifdef HUNSTEM - if (cmpdstemnum) *cmpdstemnum = oldcmpdstemnum; -#endif + if (checkcompoundrep || forbiddenword) { + struct hentry * rv2 = NULL; + + if (checkcompoundrep && cpdrep_check(word, len)) return NULL; + + // check first part + if (strncmp(rv->word, word + i, rv->blen) == 0) { + char r = *(st + i + rv->blen); + *(st + i + rv->blen) = '\0'; + + if (checkcompoundrep && cpdrep_check(st, i + rv->blen)) { + *(st + i + rv->blen) = r; + continue; + } + + if (forbiddenword) { + rv2 = lookup(word); + if (!rv2) rv2 = affix_check(word, len); + if (rv2 && rv2->astr && TESTAFF(rv2->astr, forbiddenword, rv2->alen) && + (strncmp(rv2->word, st, i + rv->blen) == 0)) { + return NULL; + } + } + *(st + i + rv->blen) = r; + } + } + return rv_first; } + } while (striple && !checkedstriple); // end of striple loop + + if (checkedstriple) { + i++; + checkedstriple = 0; + striple = 0; + } + + } // first word is ok condition + + if (soldi != 0) { + i = soldi; + soldi = 0; + len = oldlen; + cmin = oldcmin; + cmax = oldcmax; } - st[i] = ch; + scpd++; + + + } while (!onlycpdrule && simplifiedcpd && scpd <= numcheckcpd); // end of simplifiedcpd loop + + scpd = 0; wordnum = oldwordnum; numsyllable = oldnumsyllable; + + if (soldi != 0) { + i = soldi; + strcpy(st, word); // XXX add more optim. + soldi = 0; + } else st[i] = ch; + + } while (numdefcpd && oldwordnum == 0 && !onlycpdrule && (onlycpdrule = 1)); // end of onlycpd loop + } - + return NULL; -} +} -#ifdef HUNSPELL_EXPERIMENTAL // check if compound word is correctly spelled // hu_mov_rule = spec. Hungarian rule (XXX) int AffixMgr::compound_check_morph(const char * word, int len, @@ -1909,26 +2037,18 @@ int AffixMgr::compound_check_morph(const char * word, int len, struct hentry * rwords[MAXWORDLEN]; // buffer for COMPOUND pattern checking char st [MAXWORDUTF8LEN + 4]; char ch; - + int checked_prefix; char presult[MAXLNLEN]; int cmin; int cmax; - - if (utf8) { - for (cmin = 0, i = 0; (i < cpdmin) && word[cmin]; i++) { - cmin++; - for (; (word[cmin] & 0xc0) == 0x80; cmin++); - } - for (cmax = len, i = 0; (i < (cpdmin - 1)) && cmax; i++) { - cmax--; - for (; (word[cmax] & 0xc0) == 0x80; cmax--); - } - } else { - cmin = cpdmin; - cmax = len - cpdmin + 1; - } + + int onlycpdrule; + int affixed = 0; + hentry ** oldwords = words; + + setcminmax(&cmin, &cmax, word, len); strcpy(st, word); @@ -1942,54 +2062,73 @@ int AffixMgr::compound_check_morph(const char * word, int len, for (; (st[i] & 0xc0) == 0x80; i++); if (i >= cmax) return 0; } - + + words = oldwords; + onlycpdrule = (words) ? 1 : 0; + + do { // onlycpdrule loop + + oldnumsyllable = numsyllable; + oldwordnum = wordnum; + checked_prefix = 0; + ch = st[i]; st[i] = '\0'; sfx = NULL; // FIRST WORD + + affixed = 1; + *presult = '\0'; - if (partresult) strcat(presult, partresult); - + if (partresult) mystrcat(presult, partresult, MAXLNLEN); + rv = lookup(st); // perhaps without prefix // search homonym with compound flag while ((rv) && !hu_mov_rule && - ((pseudoroot && TESTAFF(rv->astr, pseudoroot, rv->alen)) || - !((compoundflag && !words && TESTAFF(rv->astr, compoundflag, rv->alen)) || - (compoundbegin && !wordnum && + ((needaffix && TESTAFF(rv->astr, needaffix, rv->alen)) || + !((compoundflag && !words && !onlycpdrule && TESTAFF(rv->astr, compoundflag, rv->alen)) || + (compoundbegin && !wordnum && !onlycpdrule && TESTAFF(rv->astr, compoundbegin, rv->alen)) || - (compoundmiddle && wordnum && !words && + (compoundmiddle && wordnum && !words && !onlycpdrule && TESTAFF(rv->astr, compoundmiddle, rv->alen)) || - (numdefcpd && + (numdefcpd && onlycpdrule && ((!words && !wordnum && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0)) || (words && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0)))) ))) { rv = rv->next_homonym; } + if (rv) affixed = 0; + if (rv) { - if (rv->description) { - if ((!rv->astr) || !TESTAFF(rv->astr, lemma_present, rv->alen)) - strcat(presult, st); - strcat(presult, rv->description); + sprintf(presult + strlen(presult), "%c%s%s", MSEP_FLD, MORPH_PART, st); + if (!HENTRY_FIND(rv, MORPH_STEM)) { + sprintf(presult + strlen(presult), "%c%s%s", MSEP_FLD, MORPH_STEM, st); } - } - + // store the pointer of the hash entry +// sprintf(presult + strlen(presult), "%c%s%p", MSEP_FLD, MORPH_HENTRY, rv); + if (HENTRY_DATA(rv)) { + sprintf(presult + strlen(presult), "%c%s", MSEP_FLD, HENTRY_DATA2(rv)); + } + } + if (!rv) { - if (compoundflag && + if (onlycpdrule) break; + if (compoundflag && !(rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundflag))) { if ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundflag, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) && !hu_mov_rule && - ((SfxEntry*)sfx)->getCont() && - ((compoundforbidflag && TESTAFF(((SfxEntry*)sfx)->getCont(), compoundforbidflag, - ((SfxEntry*)sfx)->getContLen())) || (compoundend && - TESTAFF(((SfxEntry*)sfx)->getCont(), compoundend, - ((SfxEntry*)sfx)->getContLen())))) { + sfx->getCont() && + ((compoundforbidflag && TESTAFF(sfx->getCont(), compoundforbidflag, + sfx->getContLen())) || (compoundend && + TESTAFF(sfx->getCont(), compoundend, + sfx->getContLen())))) { rv = NULL; } } - + if (rv || (((wordnum == 0) && compoundbegin && ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundbegin, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) || @@ -1998,74 +2137,69 @@ int AffixMgr::compound_check_morph(const char * word, int len, ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundmiddle, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) || (rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundmiddle))))) ) { - //char * p = prefix_check_morph(st, i, 0, compound); + // char * p = prefix_check_morph(st, i, 0, compound); char * p = NULL; if (compoundflag) p = affix_check_morph(st, i, compoundflag); if (!p || (*p == '\0')) { + if (p) free(p); + p = NULL; if ((wordnum == 0) && compoundbegin) { p = affix_check_morph(st, i, compoundbegin); } else if ((wordnum > 0) && compoundmiddle) { p = affix_check_morph(st, i, compoundmiddle); } } - if (*p != '\0') { - line_uniq(p); - if (strchr(p, '\n')) { - strcat(presult, "("); - strcat(presult, line_join(p, '|')); - strcat(presult, ")"); - } else { - strcat(presult, p); - } - } - if (presult[strlen(presult) - 1] == '\n') { - presult[strlen(presult) - 1] = '\0'; + if (p && (*p != '\0')) { + sprintf(presult + strlen(presult), "%c%s%s%s", MSEP_FLD, + MORPH_PART, st, line_uniq_app(&p, MSEP_REC)); } + if (p) free(p); checked_prefix = 1; - //strcat(presult, "+"); } // else check forbiddenwords } else if (rv->astr && (TESTAFF(rv->astr, forbiddenword, rv->alen) || - TESTAFF(rv->astr, pseudoroot, rv->alen))) { + TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) || + TESTAFF(rv->astr, needaffix, rv->alen))) { st[i] = ch; continue; } // check non_compound flag in suffix and prefix if ((rv) && !hu_mov_rule && - ((pfx && ((PfxEntry*)pfx)->getCont() && - TESTAFF(((PfxEntry*)pfx)->getCont(), compoundforbidflag, - ((PfxEntry*)pfx)->getContLen())) || - (sfx && ((SfxEntry*)sfx)->getCont() && - TESTAFF(((SfxEntry*)sfx)->getCont(), compoundforbidflag, - ((SfxEntry*)sfx)->getContLen())))) { + ((pfx && pfx->getCont() && + TESTAFF(pfx->getCont(), compoundforbidflag, + pfx->getContLen())) || + (sfx && sfx->getCont() && + TESTAFF(sfx->getCont(), compoundforbidflag, + sfx->getContLen())))) { continue; } // check compoundend flag in suffix and prefix if ((rv) && !checked_prefix && compoundend && !hu_mov_rule && - ((pfx && ((PfxEntry*)pfx)->getCont() && - TESTAFF(((PfxEntry*)pfx)->getCont(), compoundend, - ((PfxEntry*)pfx)->getContLen())) || - (sfx && ((SfxEntry*)sfx)->getCont() && - TESTAFF(((SfxEntry*)sfx)->getCont(), compoundend, - ((SfxEntry*)sfx)->getContLen())))) { + ((pfx && pfx->getCont() && + TESTAFF(pfx->getCont(), compoundend, + pfx->getContLen())) || + (sfx && sfx->getCont() && + TESTAFF(sfx->getCont(), compoundend, + sfx->getContLen())))) { continue; } // check compoundmiddle flag in suffix and prefix if ((rv) && !checked_prefix && (wordnum==0) && compoundmiddle && !hu_mov_rule && - ((pfx && ((PfxEntry*)pfx)->getCont() && - TESTAFF(((PfxEntry*)pfx)->getCont(), compoundmiddle, - ((PfxEntry*)pfx)->getContLen())) || - (sfx && ((SfxEntry*)sfx)->getCont() && - TESTAFF(((SfxEntry*)sfx)->getCont(), compoundmiddle, - ((SfxEntry*)sfx)->getContLen())))) { + ((pfx && pfx->getCont() && + TESTAFF(pfx->getCont(), compoundmiddle, + pfx->getContLen())) || + (sfx && sfx->getCont() && + TESTAFF(sfx->getCont(), compoundmiddle, + sfx->getContLen())))) { rv = NULL; } // check forbiddenwords - if ((rv) && (rv->astr) && TESTAFF(rv->astr, forbiddenword, rv->alen)) continue; + if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) + || TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen))) continue; // increment word number, if the second root has a compoundroot flag if ((rv) && (compoundroot) && @@ -2089,7 +2223,7 @@ int AffixMgr::compound_check_morph(const char * word, int len, ) // END of LANG_hu section ) - && ! (( checkcompoundtriple && // test triple letters + && ! (( checkcompoundtriple && !words && // test triple letters (word[i-1]==word[i]) && ( ((i>1) && (word[i-1]==word[i-2])) || ((word[i-1]==word[i+1])) // may be word[i+1] == '\0' @@ -2097,17 +2231,17 @@ int AffixMgr::compound_check_morph(const char * word, int len, ) || ( // test CHECKCOMPOUNDPATTERN - numcheckcpd && cpdpat_check(word, i) + numcheckcpd && !words && cpdpat_check(word, i, rv, NULL, affixed) ) || ( - checkcompoundcase && cpdcase_check(word, i) + checkcompoundcase && !words && cpdcase_check(word, i) )) ) // LANG_hu section: spec. Hungarian rule || ((!rv) && (langnum == LANG_hu) && hu_mov_rule && (rv = affix_check(st,i)) && - (sfx && ((SfxEntry*)sfx)->getCont() && ( - TESTAFF(((SfxEntry*)sfx)->getCont(), (unsigned short) 'x', ((SfxEntry*)sfx)->getContLen()) || - TESTAFF(((SfxEntry*)sfx)->getCont(), (unsigned short) '%', ((SfxEntry*)sfx)->getContLen()) + (sfx && sfx->getCont() && ( + TESTAFF(sfx->getCont(), (unsigned short) 'x', sfx->getContLen()) || + TESTAFF(sfx->getCont(), (unsigned short) '%', sfx->getContLen()) ) ) ) @@ -2120,7 +2254,7 @@ int AffixMgr::compound_check_morph(const char * word, int len, numsyllable += get_syllable(st, i); // + 1 word, if syllable number of the prefix > 1 (hungarian convention) - if (pfx && (get_syllable(((PfxEntry *)pfx)->getKey(),strlen(((PfxEntry *)pfx)->getKey())) > 1)) wordnum++; + if (pfx && (get_syllable(pfx->getKey(),strlen(pfx->getKey())) > 1)) wordnum++; } // END of LANG_hu section @@ -2129,21 +2263,31 @@ int AffixMgr::compound_check_morph(const char * word, int len, rv = lookup((word+i)); // perhaps without prefix // search homonym with compound flag - while ((rv) && ((pseudoroot && TESTAFF(rv->astr, pseudoroot, rv->alen)) || + while ((rv) && ((needaffix && TESTAFF(rv->astr, needaffix, rv->alen)) || !((compoundflag && !words && TESTAFF(rv->astr, compoundflag, rv->alen)) || (compoundend && !words && TESTAFF(rv->astr, compoundend, rv->alen)) || - (numdefcpd && defcpd_check(&words, wnum + 1, rv, NULL,1))))) { + (numdefcpd && words && defcpd_check(&words, wnum + 1, rv, NULL,1))))) { rv = rv->next_homonym; } if (rv && words && words[wnum + 1]) { - strcat(*result, presult); - if (complexprefixes && rv->description) strcat(*result, rv->description); - if (rv->description && ((!rv->astr) || - !TESTAFF(rv->astr, lemma_present, rv->alen))) - strcat(*result, rv->word); - if (!complexprefixes && rv->description) strcat(*result, rv->description); - strcat(*result, "\n"); + mystrcat(*result, presult, MAXLNLEN); + mystrcat(*result, " ", MAXLNLEN); + mystrcat(*result, MORPH_PART, MAXLNLEN); + mystrcat(*result, word+i, MAXLNLEN); + if (complexprefixes && HENTRY_DATA(rv)) mystrcat(*result, HENTRY_DATA2(rv), MAXLNLEN); + if (!HENTRY_FIND(rv, MORPH_STEM)) { + mystrcat(*result, " ", MAXLNLEN); + mystrcat(*result, MORPH_STEM, MAXLNLEN); + mystrcat(*result, HENTRY_WORD(rv), MAXLNLEN); + } + // store the pointer of the hash entry +// sprintf(*result + strlen(*result), " %s%p", MORPH_HENTRY, rv); + if (!complexprefixes && HENTRY_DATA(rv)) { + mystrcat(*result, " ", MAXLNLEN); + mystrcat(*result, HENTRY_DATA2(rv), MAXLNLEN); + } + mystrcat(*result, "\n", MAXLNLEN); ok = 1; return 0; } @@ -2163,11 +2307,12 @@ int AffixMgr::compound_check_morph(const char * word, int len, } // check forbiddenwords - if ((rv) && (rv->astr) && TESTAFF(rv->astr, forbiddenword, rv->alen)) { + if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) || + TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen))) { st[i] = ch; continue; } - + // second word is acceptable, as a root? // hungarian conventions: compounding is acceptable, // when compound forms consist of 2 words, or if more, @@ -2178,8 +2323,8 @@ int AffixMgr::compound_check_morph(const char * word, int len, ) && ( ((cpdwordmax==-1) || (wordnum+1word,rv->wlen)<=cpdmaxsyllable)) + ((cpdmaxsyllable!=0) && + (numsyllable+get_syllable(HENTRY_WORD(rv),rv->blen)<=cpdmaxsyllable)) ) && ( (!checkcompounddup || (rv != rv_first)) @@ -2187,15 +2332,26 @@ int AffixMgr::compound_check_morph(const char * word, int len, ) { // bad compound word - strcat(*result, presult); - - if (rv->description) { - if (complexprefixes) strcat(*result, rv->description); - if ((!rv->astr) || !TESTAFF(rv->astr, lemma_present, rv->alen)) - strcat(*result, rv->word); - if (!complexprefixes) strcat(*result, rv->description); + mystrcat(*result, presult, MAXLNLEN); + mystrcat(*result, " ", MAXLNLEN); + mystrcat(*result, MORPH_PART, MAXLNLEN); + mystrcat(*result, word+i, MAXLNLEN); + + if (HENTRY_DATA(rv)) { + if (complexprefixes) mystrcat(*result, HENTRY_DATA2(rv), MAXLNLEN); + if (! HENTRY_FIND(rv, MORPH_STEM)) { + mystrcat(*result, " ", MAXLNLEN); + mystrcat(*result, MORPH_STEM, MAXLNLEN); + mystrcat(*result, HENTRY_WORD(rv), MAXLNLEN); + } + // store the pointer of the hash entry +// sprintf(*result + strlen(*result), " %s%p", MORPH_HENTRY, rv); + if (!complexprefixes) { + mystrcat(*result, " ", MAXLNLEN); + mystrcat(*result, HENTRY_DATA2(rv), MAXLNLEN); + } } - strcat(*result, "\n"); + mystrcat(*result, "\n", MAXLNLEN); ok = 1; } @@ -2206,9 +2362,9 @@ int AffixMgr::compound_check_morph(const char * word, int len, sfx = NULL; sfxflag = FLAG_NULL; - if (compoundflag) rv = affix_check((word+i),strlen(word+i), compoundflag); else rv = NULL; + if (compoundflag && !onlycpdrule) rv = affix_check((word+i),strlen(word+i), compoundflag); else rv = NULL; - if (!rv && compoundend) { + if (!rv && compoundend && !onlycpdrule) { sfx = NULL; pfx = NULL; rv = affix_check((word+i),strlen(word+i), compoundend); @@ -2219,39 +2375,36 @@ int AffixMgr::compound_check_morph(const char * word, int len, if (rv && words && defcpd_check(&words, wnum + 1, rv, NULL, 1)) { char * m = NULL; if (compoundflag) m = affix_check_morph((word+i),strlen(word+i), compoundflag); - if ((!m || *m == '\0') && compoundend) + if ((!m || *m == '\0') && compoundend) { + if (m) free(m); m = affix_check_morph((word+i),strlen(word+i), compoundend); - strcat(*result, presult); - if (m) { - line_uniq(m); - if (strchr(m, '\n')) { - strcat(*result, "("); - strcat(*result, line_join(m, '|')); - strcat(*result, ")"); - } else { - strcat(*result, m); - } - free(m); } - strcat(*result, "\n"); + mystrcat(*result, presult, MAXLNLEN); + if (m || (*m != '\0')) { + sprintf(*result + strlen(*result), "%c%s%s%s", MSEP_FLD, + MORPH_PART, word + i, line_uniq_app(&m, MSEP_REC)); + } + if (m) free(m); + mystrcat(*result, "\n", MAXLNLEN); ok = 1; } } // check non_compound flag in suffix and prefix if ((rv) && - ((pfx && ((PfxEntry*)pfx)->getCont() && - TESTAFF(((PfxEntry*)pfx)->getCont(), compoundforbidflag, - ((PfxEntry*)pfx)->getContLen())) || - (sfx && ((SfxEntry*)sfx)->getCont() && - TESTAFF(((SfxEntry*)sfx)->getCont(), compoundforbidflag, - ((SfxEntry*)sfx)->getContLen())))) { + ((pfx && pfx->getCont() && + TESTAFF(pfx->getCont(), compoundforbidflag, + pfx->getContLen())) || + (sfx && sfx->getCont() && + TESTAFF(sfx->getCont(), compoundforbidflag, + sfx->getContLen())))) { rv = NULL; } // check forbiddenwords - if ((rv) && (rv->astr) && (TESTAFF(rv->astr,forbiddenword,rv->alen)) - && (! TESTAFF(rv->astr, pseudoroot, rv->alen))) { + if ((rv) && (rv->astr) && (TESTAFF(rv->astr,forbiddenword,rv->alen) || + TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen)) + && (! TESTAFF(rv->astr, needaffix, rv->alen))) { st[i] = ch; continue; } @@ -2269,7 +2422,7 @@ int AffixMgr::compound_check_morph(const char * word, int len, } // + 1 word, if syllable number of the prefix > 1 (hungarian convention) - if (pfx && (get_syllable(((PfxEntry *)pfx)->getKey(),strlen(((PfxEntry *)pfx)->getKey())) > 1)) wordnum++; + if (pfx && (get_syllable(pfx->getKey(),strlen(pfx->getKey())) > 1)) wordnum++; // increment syllable num, if last word has a SYLLABLENUM flag // and the suffix is beginning `s' @@ -2295,7 +2448,7 @@ int AffixMgr::compound_check_morph(const char * word, int len, if ((rv) && ( ((cpdwordmax==-1) || (wordnum+1getCont()) { @@ -2393,29 +2542,29 @@ struct hentry * AffixMgr::suffix_check (const char * word, int len, (se->getCont() && (TESTAFF(se->getCont(),circumfix,se->getContLen()))))) && // fogemorpheme (in_compound || - !((se->getCont() && (TESTAFF(se->getCont(), onlyincompound, se->getContLen()))))) && - // pseudoroot on prefix or first suffix + !(se->getCont() && (TESTAFF(se->getCont(), onlyincompound, se->getContLen())))) && + // needaffix on prefix or first suffix (cclass || - !(se->getCont() && TESTAFF(se->getCont(), pseudoroot, se->getContLen())) || + !(se->getCont() && TESTAFF(se->getCont(), needaffix, se->getContLen())) || (ppfx && !((ep->getCont()) && - TESTAFF(ep->getCont(), pseudoroot, + TESTAFF(ep->getCont(), needaffix, ep->getContLen()))) - ) - ) { + )) { rv = se->checkword(word,len, sfxopts, ppfx, wlst, maxSug, ns, (FLAG) cclass, needflag, (in_compound ? 0 : onlyincompound)); if (rv) { - sfx=(AffEntry *)se; // BUG: sfx not stateless + sfx=se; // BUG: sfx not stateless return rv; } } } se = se->getNext(); } - + // now handle the general case - unsigned char sp = *((const unsigned char *)(word + len - 1)); - SfxEntry * sptr = (SfxEntry *) sStart[sp]; + if (len == 0) return NULL; // FULLSTRIP + unsigned char sp= *((const unsigned char *)(word + len - 1)); + SfxEntry * sptr = sStart[sp]; while (sptr) { if (isRevSubset(sptr->getKey(), word + len - 1, len) @@ -2436,31 +2585,20 @@ struct hentry * AffixMgr::suffix_check (const char * word, int len, // fogemorpheme (in_compound || !((sptr->getCont() && (TESTAFF(sptr->getCont(), onlyincompound, sptr->getContLen()))))) && - // pseudoroot on prefix or first suffix + // needaffix on prefix or first suffix (cclass || - !(sptr->getCont() && TESTAFF(sptr->getCont(), pseudoroot, sptr->getContLen())) || + !(sptr->getCont() && TESTAFF(sptr->getCont(), needaffix, sptr->getContLen())) || (ppfx && !((ep->getCont()) && - TESTAFF(ep->getCont(), pseudoroot, + TESTAFF(ep->getCont(), needaffix, ep->getContLen()))) ) - ) { + ) if (in_compound != IN_CPD_END || ppfx || !(sptr->getCont() && TESTAFF(sptr->getCont(), onlyincompound, sptr->getContLen()))) { rv = sptr->checkword(word,len, sfxopts, ppfx, wlst, maxSug, ns, cclass, needflag, (in_compound ? 0 : onlyincompound)); if (rv) { - sfx=(AffEntry *)sptr; // BUG: sfx not stateless + sfx=sptr; // BUG: sfx not stateless sfxflag = sptr->getFlag(); // BUG: sfxflag not stateless if (!sptr->getCont()) sfxappnd=sptr->getKey(); // BUG: sfxappnd not stateless - if (cclass || sptr->getCont()) { - if (!derived) { - derived = mystrdup(word); - } else { - strcpy(result, derived); // XXX check size - strcat(result, "\n"); - strcat(result, word); - free(derived); - derived = mystrdup(result); - } - } return rv; } } @@ -2476,12 +2614,12 @@ struct hentry * AffixMgr::suffix_check (const char * word, int len, // check word for two-level suffixes struct hentry * AffixMgr::suffix_check_twosfx(const char * word, int len, - int sfxopts, AffEntry * ppfx, const FLAG needflag) + int sfxopts, PfxEntry * ppfx, const FLAG needflag) { struct hentry * rv = NULL; // first handle the special case of 0 length suffixes - SfxEntry * se = (SfxEntry *) sStart[0]; + SfxEntry * se = sStart[0]; while (se) { if (contclasses[se->getFlag()]) { @@ -2490,10 +2628,11 @@ struct hentry * AffixMgr::suffix_check_twosfx(const char * word, int len, } se = se->getNext(); } - + // now handle the general case + if (len == 0) return NULL; // FULLSTRIP unsigned char sp = *((const unsigned char *)(word + len - 1)); - SfxEntry * sptr = (SfxEntry *) sStart[sp]; + SfxEntry * sptr = sStart[sp]; while (sptr) { if (isRevSubset(sptr->getKey(), word + len - 1, len)) { @@ -2515,9 +2654,8 @@ struct hentry * AffixMgr::suffix_check_twosfx(const char * word, int len, return NULL; } -#ifdef HUNSPELL_EXPERIMENTAL char * AffixMgr::suffix_check_twosfx_morph(const char * word, int len, - int sfxopts, AffEntry * ppfx, const FLAG needflag) + int sfxopts, PfxEntry * ppfx, const FLAG needflag) { char result[MAXLNLEN]; char result2[MAXLNLEN]; @@ -2530,27 +2668,34 @@ char * AffixMgr::suffix_check_twosfx_morph(const char * word, int len, result3[0] = '\0'; // first handle the special case of 0 length suffixes - SfxEntry * se = (SfxEntry *) sStart[0]; + SfxEntry * se = sStart[0]; while (se) { if (contclasses[se->getFlag()]) { st = se->check_twosfx_morph(word,len, sfxopts, ppfx, needflag); if (st) { if (ppfx) { - if (((PfxEntry *) ppfx)->getMorph()) strcat(result, ((PfxEntry *) ppfx)->getMorph()); + if (ppfx->getMorph()) { + mystrcat(result, ppfx->getMorph(), MAXLNLEN); + mystrcat(result, " ", MAXLNLEN); + } else debugflag(result, ppfx->getFlag()); } - strcat(result, st); + mystrcat(result, st, MAXLNLEN); free(st); - if (se->getMorph()) strcat(result, se->getMorph()); - strcat(result, "\n"); + if (se->getMorph()) { + mystrcat(result, " ", MAXLNLEN); + mystrcat(result, se->getMorph(), MAXLNLEN); + } else debugflag(result, se->getFlag()); + mystrcat(result, "\n", MAXLNLEN); } } se = se->getNext(); } - + // now handle the general case + if (len == 0) return NULL; // FULLSTRIP unsigned char sp = *((const unsigned char *)(word + len - 1)); - SfxEntry * sptr = (SfxEntry *) sStart[sp]; + SfxEntry * sptr = sStart[sp]; while (sptr) { if (isRevSubset(sptr->getKey(), word + len - 1, len)) { @@ -2564,19 +2709,14 @@ char * AffixMgr::suffix_check_twosfx_morph(const char * word, int len, free(st); result3[0] = '\0'; -#ifdef DEBUG - unsigned short flag = sptr->getFlag(); - if (flag_mode == FLAG_NUM) { - sprintf(result3, "<%d>", sptr->getKey()); - } else if (flag_mode == FLAG_LONG) { - sprintf(result3, "<%c%c>", flag >> 8, (flag << 8) >>8); - } else sprintf(result3, "<%c>", flag); - strcat(result3, ":"); -#endif - if (sptr->getMorph()) strcat(result3, sptr->getMorph()); + + if (sptr->getMorph()) { + mystrcat(result3, " ", MAXLNLEN); + mystrcat(result3, sptr->getMorph(), MAXLNLEN); + } else debugflag(result3, sptr->getFlag()); strlinecat(result2, result3); - strcat(result2, "\n"); - strcat(result, result2); + mystrcat(result2, "\n", MAXLNLEN); + mystrcat(result, result2, MAXLNLEN); } } sptr = sptr->getNextEQ(); @@ -2584,12 +2724,12 @@ char * AffixMgr::suffix_check_twosfx_morph(const char * word, int len, sptr = sptr->getNextNE(); } } - if (result) return mystrdup(result); + if (*result) return mystrdup(result); return NULL; } char * AffixMgr::suffix_check_morph(const char * word, int len, - int sfxopts, AffEntry * ppfx, const FLAG cclass, const FLAG needflag, char in_compound) + int sfxopts, PfxEntry * ppfx, const FLAG cclass, const FLAG needflag, char in_compound) { char result[MAXLNLEN]; @@ -2597,10 +2737,10 @@ char * AffixMgr::suffix_check_morph(const char * word, int len, result[0] = '\0'; - PfxEntry* ep = (PfxEntry *) ppfx; + PfxEntry* ep = ppfx; // first handle the special case of 0 length suffixes - SfxEntry * se = (SfxEntry *) sStart[0]; + SfxEntry * se = sStart[0]; while (se) { if (!cclass || se->getCont()) { // suffixes are not allowed in beginning of compounds @@ -2619,35 +2759,50 @@ char * AffixMgr::suffix_check_morph(const char * word, int len, // fogemorpheme (in_compound || !((se->getCont() && (TESTAFF(se->getCont(), onlyincompound, se->getContLen()))))) && - // pseudoroot on prefix or first suffix + // needaffix on prefix or first suffix (cclass || - !(se->getCont() && TESTAFF(se->getCont(), pseudoroot, se->getContLen())) || + !(se->getCont() && TESTAFF(se->getCont(), needaffix, se->getContLen())) || (ppfx && !((ep->getCont()) && - TESTAFF(ep->getCont(), pseudoroot, + TESTAFF(ep->getCont(), needaffix, ep->getContLen()))) ) )) - rv = se->checkword(word,len, sfxopts, ppfx, NULL, 0, 0, cclass, needflag); + rv = se->checkword(word, len, sfxopts, ppfx, NULL, 0, 0, cclass, needflag); while (rv) { if (ppfx) { - if (((PfxEntry *) ppfx)->getMorph()) strcat(result, ((PfxEntry *) ppfx)->getMorph()); + if (ppfx->getMorph()) { + mystrcat(result, ppfx->getMorph(), MAXLNLEN); + mystrcat(result, " ", MAXLNLEN); + } else debugflag(result, ppfx->getFlag()); + } + if (complexprefixes && HENTRY_DATA(rv)) mystrcat(result, HENTRY_DATA2(rv), MAXLNLEN); + if (! HENTRY_FIND(rv, MORPH_STEM)) { + mystrcat(result, " ", MAXLNLEN); + mystrcat(result, MORPH_STEM, MAXLNLEN); + mystrcat(result, HENTRY_WORD(rv), MAXLNLEN); } - if (complexprefixes && rv->description) strcat(result, rv->description); - if (rv->description && ((!rv->astr) || - !TESTAFF(rv->astr, lemma_present, rv->alen))) - strcat(result, rv->word); - if (!complexprefixes && rv->description) strcat(result, rv->description); - if (se->getMorph()) strcat(result, se->getMorph()); - strcat(result, "\n"); + // store the pointer of the hash entry +// sprintf(result + strlen(result), " %s%p", MORPH_HENTRY, rv); + + if (!complexprefixes && HENTRY_DATA(rv)) { + mystrcat(result, " ", MAXLNLEN); + mystrcat(result, HENTRY_DATA2(rv), MAXLNLEN); + } + if (se->getMorph()) { + mystrcat(result, " ", MAXLNLEN); + mystrcat(result, se->getMorph(), MAXLNLEN); + } else debugflag(result, se->getFlag()); + mystrcat(result, "\n", MAXLNLEN); rv = se->get_next_homonym(rv, sfxopts, ppfx, cclass, needflag); } } se = se->getNext(); } - + // now handle the general case + if (len == 0) return NULL; // FULLSTRIP unsigned char sp = *((const unsigned char *)(word + len - 1)); - SfxEntry * sptr = (SfxEntry *) sStart[sp]; + SfxEntry * sptr = sStart[sp]; while (sptr) { if (isRevSubset(sptr->getKey(), word + len - 1, len) @@ -2668,30 +2823,36 @@ char * AffixMgr::suffix_check_morph(const char * word, int len, // fogemorpheme (in_compound || !((sptr->getCont() && (TESTAFF(sptr->getCont(), onlyincompound, sptr->getContLen()))))) && - // pseudoroot on first suffix + // needaffix on first suffix (cclass || !(sptr->getCont() && - TESTAFF(sptr->getCont(), pseudoroot, sptr->getContLen()))) + TESTAFF(sptr->getCont(), needaffix, sptr->getContLen()))) )) rv = sptr->checkword(word,len, sfxopts, ppfx, NULL, 0, 0, cclass, needflag); while (rv) { if (ppfx) { - if (((PfxEntry *) ppfx)->getMorph()) strcat(result, ((PfxEntry *) ppfx)->getMorph()); + if (ppfx->getMorph()) { + mystrcat(result, ppfx->getMorph(), MAXLNLEN); + mystrcat(result, " ", MAXLNLEN); + } else debugflag(result, ppfx->getFlag()); } - if (complexprefixes && rv->description) strcat(result, rv->description); - if (rv->description && ((!rv->astr) || - !TESTAFF(rv->astr, lemma_present, rv->alen))) strcat(result, rv->word); - if (!complexprefixes && rv->description) strcat(result, rv->description); -#ifdef DEBUG - unsigned short flag = sptr->getFlag(); - if (flag_mode == FLAG_NUM) { - sprintf(result, "<%d>", sptr->getKey()); - } else if (flag_mode == FLAG_LONG) { - sprintf(result, "<%c%c>", flag >> 8, (flag << 8) >>8); - } else sprintf(result, "<%c>", flag); - strcat(result, ":"); -#endif + if (complexprefixes && HENTRY_DATA(rv)) mystrcat(result, HENTRY_DATA2(rv), MAXLNLEN); + if (! HENTRY_FIND(rv, MORPH_STEM)) { + mystrcat(result, " ", MAXLNLEN); + mystrcat(result, MORPH_STEM, MAXLNLEN); + mystrcat(result, HENTRY_WORD(rv), MAXLNLEN); + } + // store the pointer of the hash entry +// sprintf(result + strlen(result), " %s%p", MORPH_HENTRY, rv); + + if (!complexprefixes && HENTRY_DATA(rv)) { + mystrcat(result, " ", MAXLNLEN); + mystrcat(result, HENTRY_DATA2(rv), MAXLNLEN); + } - if (sptr->getMorph()) strcat(result, sptr->getMorph()); - strcat(result, "\n"); + if (sptr->getMorph()) { + mystrcat(result, " ", MAXLNLEN); + mystrcat(result, sptr->getMorph(), MAXLNLEN); + } else debugflag(result, sptr->getFlag()); + mystrcat(result, "\n", MAXLNLEN); rv = sptr->get_next_homonym(rv, sfxopts, ppfx, cclass, needflag); } sptr = sptr->getNextEQ(); @@ -2703,15 +2864,11 @@ char * AffixMgr::suffix_check_morph(const char * word, int len, if (*result) return mystrdup(result); return NULL; } -#endif // END OF HUNSPELL_EXPERIMENTAL CODE - // check if word with affixes is correctly spelled struct hentry * AffixMgr::affix_check (const char * word, int len, const FLAG needflag, char in_compound) { struct hentry * rv= NULL; - if (derived) free(derived); - derived = NULL; // check all prefixes (also crossed with suffixes if allowed) rv = prefix_check(word, len, in_compound, needflag); @@ -2723,17 +2880,19 @@ struct hentry * AffixMgr::affix_check (const char * word, int len, const FLAG ne if (havecontclass) { sfx = NULL; pfx = NULL; + if (rv) return rv; // if still not found check all two-level suffixes rv = suffix_check_twosfx(word, len, 0, NULL, needflag); + if (rv) return rv; // if still not found check all two-level suffixes rv = prefix_check_twosfx(word, len, IN_CPD_NOT, needflag); } + return rv; } -#ifdef HUNSPELL_EXPERIMENTAL // check if word with affixes is correctly spelled char * AffixMgr::affix_check_morph(const char * word, int len, const FLAG needflag, char in_compound) { @@ -2745,14 +2904,14 @@ char * AffixMgr::affix_check_morph(const char * word, int len, const FLAG needfl // check all prefixes (also crossed with suffixes if allowed) st = prefix_check_morph(word, len, in_compound); if (st) { - strcat(result, st); + mystrcat(result, st, MAXLNLEN); free(st); } // if still not found check all suffixes st = suffix_check_morph(word, len, 0, NULL, '\0', needflag, in_compound); if (st) { - strcat(result, st); + mystrcat(result, st, MAXLNLEN); free(st); } @@ -2762,47 +2921,134 @@ char * AffixMgr::affix_check_morph(const char * word, int len, const FLAG needfl // if still not found check all two-level suffixes st = suffix_check_twosfx_morph(word, len, 0, NULL, needflag); if (st) { - strcat(result, st); + mystrcat(result, st, MAXLNLEN); free(st); } // if still not found check all two-level suffixes st = prefix_check_twosfx_morph(word, len, IN_CPD_NOT, needflag); if (st) { - strcat(result, st); + mystrcat(result, st, MAXLNLEN); free(st); } } - + return mystrdup(result); } -#endif // END OF HUNSPELL_EXPERIMENTAL CODE + +char * AffixMgr::morphgen(char * ts, int wl, const unsigned short * ap, + unsigned short al, char * morph, char * targetmorph, int level) +{ + // handle suffixes + char * stemmorph; + char * stemmorphcatpos; + char mymorph[MAXLNLEN]; + + if (!morph) return NULL; + + // check substandard flag + if (TESTAFF(ap, substandard, al)) return NULL; + + if (morphcmp(morph, targetmorph) == 0) return mystrdup(ts); + +// int targetcount = get_sfxcount(targetmorph); + + // use input suffix fields, if exist + if (strstr(morph, MORPH_INFL_SFX) || strstr(morph, MORPH_DERI_SFX)) { + stemmorph = mymorph; + strcpy(stemmorph, morph); + mystrcat(stemmorph, " ", MAXLNLEN); + stemmorphcatpos = stemmorph + strlen(stemmorph); + } else { + stemmorph = morph; + stemmorphcatpos = NULL; + } + + for (int i = 0; i < al; i++) { + const unsigned char c = (unsigned char) (ap[i] & 0x00FF); + SfxEntry * sptr = sFlag[c]; + while (sptr) { + if (sptr->getFlag() == ap[i] && sptr->getMorph() && ((sptr->getContLen() == 0) || + // don't generate forms with substandard affixes + !TESTAFF(sptr->getCont(), substandard, sptr->getContLen()))) { + + if (stemmorphcatpos) strcpy(stemmorphcatpos, sptr->getMorph()); + else stemmorph = (char *) sptr->getMorph(); + + int cmp = morphcmp(stemmorph, targetmorph); + + if (cmp == 0) { + char * newword = sptr->add(ts, wl); + if (newword) { + hentry * check = pHMgr->lookup(newword); // XXX extra dic + if (!check || !check->astr || + !(TESTAFF(check->astr, forbiddenword, check->alen) || + TESTAFF(check->astr, ONLYUPCASEFLAG, check->alen))) { + return newword; + } + free(newword); + } + } + + // recursive call for secondary suffixes + if ((level == 0) && (cmp == 1) && (sptr->getContLen() > 0) && +// (get_sfxcount(stemmorph) < targetcount) && + !TESTAFF(sptr->getCont(), substandard, sptr->getContLen())) { + char * newword = sptr->add(ts, wl); + if (newword) { + char * newword2 = morphgen(newword, strlen(newword), sptr->getCont(), + sptr->getContLen(), stemmorph, targetmorph, 1); + + if (newword2) { + free(newword); + return newword2; + } + free(newword); + newword = NULL; + } + } + } + sptr = sptr->getFlgNxt(); + } + } + return NULL; +} int AffixMgr::expand_rootword(struct guessword * wlst, int maxn, const char * ts, - int wl, const unsigned short * ap, unsigned short al, char * bad, int badl) + int wl, const unsigned short * ap, unsigned short al, char * bad, int badl, + char * phon) { - int nh=0; - // first add root word to list - if ((nh < maxn) && !(al && ((pseudoroot && TESTAFF(ap, pseudoroot, al)) || + if ((nh < maxn) && !(al && ((needaffix && TESTAFF(ap, needaffix, al)) || (onlyincompound && TESTAFF(ap, onlyincompound, al))))) { wlst[nh].word = mystrdup(ts); + if (!wlst[nh].word) return 0; wlst[nh].allow = (1 == 0); + wlst[nh].orig = NULL; nh++; + // add special phonetic version + if (phon && (nh < maxn)) { + wlst[nh].word = mystrdup(phon); + if (!wlst[nh].word) return nh - 1; + wlst[nh].allow = (1 == 0); + wlst[nh].orig = mystrdup(ts); + if (!wlst[nh].orig) return nh - 1; + nh++; + } } // handle suffixes for (int i = 0; i < al; i++) { - unsigned short c = (unsigned short) ap[i]; - SfxEntry * sptr = (SfxEntry *)sFlag[c]; + const unsigned char c = (unsigned char) (ap[i] & 0x00FF); + SfxEntry * sptr = sFlag[c]; while (sptr) { - if (!sptr->getKeyLen() || ((badl > sptr->getKeyLen()) && - (strcmp(sptr->getAffix(), bad + badl - sptr->getKeyLen()) == 0)) && - // check pseudoroot flag - !(sptr->getCont() && ((pseudoroot && - TESTAFF(sptr->getCont(), pseudoroot, sptr->getContLen())) || + if ((sptr->getFlag() == ap[i]) && (!sptr->getKeyLen() || ((badl > sptr->getKeyLen()) && + (strcmp(sptr->getAffix(), bad + badl - sptr->getKeyLen()) == 0))) && + // check needaffix flag + !(sptr->getCont() && ((needaffix && + TESTAFF(sptr->getCont(), needaffix, sptr->getContLen())) || (circumfix && TESTAFF(sptr->getCont(), circumfix, sptr->getContLen())) || (onlyincompound && @@ -2812,14 +3058,28 @@ int AffixMgr::expand_rootword(struct guessword * wlst, int maxn, const char * ts if (newword) { if (nh < maxn) { wlst[nh].word = newword; - wlst[nh].allow = sptr->allowCross(); - nh++; + wlst[nh].allow = sptr->allowCross(); + wlst[nh].orig = NULL; + nh++; + // add special phonetic version + if (phon && (nh < maxn)) { + char st[MAXWORDUTF8LEN]; + strcpy(st, phon); + strcat(st, sptr->getKey()); + reverseword(st + strlen(phon)); + wlst[nh].word = mystrdup(st); + if (!wlst[nh].word) return nh - 1; + wlst[nh].allow = (1 == 0); + wlst[nh].orig = mystrdup(newword); + if (!wlst[nh].orig) return nh - 1; + nh++; + } } else { free(newword); } } } - sptr = (SfxEntry *)sptr ->getFlgNxt(); + sptr = sptr->getFlgNxt(); } } @@ -2829,10 +3089,10 @@ int AffixMgr::expand_rootword(struct guessword * wlst, int maxn, const char * ts for (int j=1;jallowCross() && (!cptr->getKeyLen() || ((badl > cptr->getKeyLen()) && + if ((cptr->getFlag() == ap[k]) && cptr->allowCross() && (!cptr->getKeyLen() || ((badl > cptr->getKeyLen()) && (strncmp(cptr->getKey(), bad, cptr->getKeyLen()) == 0)))) { int l1 = strlen(wlst[j].word); char * newword = cptr->add(wlst[j].word, l1); @@ -2840,13 +3100,14 @@ int AffixMgr::expand_rootword(struct guessword * wlst, int maxn, const char * ts if (nh < maxn) { wlst[nh].word = newword; wlst[nh].allow = cptr->allowCross(); + wlst[nh].orig = NULL; nh++; } else { free(newword); } } } - cptr = (PfxEntry *)cptr ->getFlgNxt(); + cptr = cptr->getFlgNxt(); } } } @@ -2854,14 +3115,14 @@ int AffixMgr::expand_rootword(struct guessword * wlst, int maxn, const char * ts // now handle pure prefixes for (int m = 0; m < al; m ++) { - unsigned short c = (unsigned short) ap[m]; - PfxEntry * ptr = (PfxEntry *) pFlag[c]; + const unsigned char c = (unsigned char) (ap[m] & 0x00FF); + PfxEntry * ptr = pFlag[c]; while (ptr) { - if (!ptr->getKeyLen() || ((badl > ptr->getKeyLen()) && - (strncmp(ptr->getKey(), bad, ptr->getKeyLen()) == 0)) && - // check pseudoroot flag - !(ptr->getCont() && ((pseudoroot && - TESTAFF(ptr->getCont(), pseudoroot, ptr->getContLen())) || + if ((ptr->getFlag() == ap[m]) && (!ptr->getKeyLen() || ((badl > ptr->getKeyLen()) && + (strncmp(ptr->getKey(), bad, ptr->getKeyLen()) == 0))) && + // check needaffix flag + !(ptr->getCont() && ((needaffix && + TESTAFF(ptr->getCont(), needaffix, ptr->getContLen())) || (circumfix && TESTAFF(ptr->getCont(), circumfix, ptr->getContLen())) || (onlyincompound && @@ -2872,55 +3133,75 @@ int AffixMgr::expand_rootword(struct guessword * wlst, int maxn, const char * ts if (nh < maxn) { wlst[nh].word = newword; wlst[nh].allow = ptr->allowCross(); + wlst[nh].orig = NULL; nh++; } else { free(newword); } } } - ptr = (PfxEntry *)ptr ->getFlgNxt(); + ptr = ptr->getFlgNxt(); } } return nh; } - - // return length of replacing table -int AffixMgr::get_numrep() +int AffixMgr::get_numrep() const { return numrep; } // return replacing table -struct replentry * AffixMgr::get_reptable() +struct replentry * AffixMgr::get_reptable() const { if (! reptable ) return NULL; return reptable; } +// return iconv table +RepList * AffixMgr::get_iconvtable() const +{ + if (! iconvtable ) return NULL; + return iconvtable; +} + +// return oconv table +RepList * AffixMgr::get_oconvtable() const +{ + if (! oconvtable ) return NULL; + return oconvtable; +} + +// return replacing table +struct phonetable * AffixMgr::get_phonetable() const +{ + if (! phone ) return NULL; + return phone; +} + // return length of character map table -int AffixMgr::get_nummap() +int AffixMgr::get_nummap() const { return nummap; } // return character map table -struct mapentry * AffixMgr::get_maptable() +struct mapentry * AffixMgr::get_maptable() const { if (! maptable ) return NULL; return maptable; } // return length of word break table -int AffixMgr::get_numbreak() +int AffixMgr::get_numbreak() const { return numbreak; } // return character map table -char ** AffixMgr::get_breaktable() +char ** AffixMgr::get_breaktable() const { if (! breaktable ) return NULL; return breaktable; @@ -2929,148 +3210,180 @@ char ** AffixMgr::get_breaktable() // return text encoding of dictionary char * AffixMgr::get_encoding() { - if (! encoding ) { - encoding = mystrdup("ISO8859-1"); - } + if (! encoding ) encoding = mystrdup(SPELL_ENCODING); return mystrdup(encoding); } // return text encoding of dictionary -int AffixMgr::get_langnum() +int AffixMgr::get_langnum() const { return langnum; } // return double prefix option -int AffixMgr::get_complexprefixes() +int AffixMgr::get_complexprefixes() const { return complexprefixes; } -FLAG AffixMgr::get_keepcase() +// return FULLSTRIP option +int AffixMgr::get_fullstrip() const +{ + return fullstrip; +} + +FLAG AffixMgr::get_keepcase() const { return keepcase; } -int AffixMgr::get_checksharps() +FLAG AffixMgr::get_forceucase() const +{ + return forceucase; +} + +FLAG AffixMgr::get_warn() const +{ + return warn; +} + +int AffixMgr::get_forbidwarn() const +{ + return forbidwarn; +} + +int AffixMgr::get_checksharps() const { return checksharps; } +char * AffixMgr::encode_flag(unsigned short aflag) const +{ + return pHMgr->encode_flag(aflag); +} + + // return the preferred ignore string for suggestions -char * AffixMgr::get_ignore() +char * AffixMgr::get_ignore() const { if (!ignorechars) return NULL; - return mystrdup(ignorechars); + return ignorechars; } // return the preferred ignore string for suggestions -unsigned short * AffixMgr::get_ignore_utf16(int * len) +unsigned short * AffixMgr::get_ignore_utf16(int * len) const { *len = ignorechars_utf16_len; return ignorechars_utf16; } +// return the keyboard string for suggestions +char * AffixMgr::get_key_string() +{ + if (! keystring ) keystring = mystrdup(SPELL_KEYSTRING); + return mystrdup(keystring); +} + // return the preferred try string for suggestions -char * AffixMgr::get_try_string() +char * AffixMgr::get_try_string() const { if (! trystring ) return NULL; return mystrdup(trystring); } // return the preferred try string for suggestions -const char * AffixMgr::get_wordchars() +const char * AffixMgr::get_wordchars() const { return wordchars; } -unsigned short * AffixMgr::get_wordchars_utf16(int * len) +unsigned short * AffixMgr::get_wordchars_utf16(int * len) const { *len = wordchars_utf16_len; return wordchars_utf16; } // is there compounding? -int AffixMgr::get_compound() +int AffixMgr::get_compound() const { return compoundflag || compoundbegin || numdefcpd; } // return the compound words control flag -FLAG AffixMgr::get_compoundflag() +FLAG AffixMgr::get_compoundflag() const { return compoundflag; } // return the forbidden words control flag -FLAG AffixMgr::get_forbiddenword() +FLAG AffixMgr::get_forbiddenword() const { return forbiddenword; } // return the forbidden words control flag -FLAG AffixMgr::get_nosuggest() +FLAG AffixMgr::get_nosuggest() const { return nosuggest; } +// return the forbidden words control flag +FLAG AffixMgr::get_nongramsuggest() const +{ + return nongramsuggest; +} + // return the forbidden words flag modify flag -FLAG AffixMgr::get_pseudoroot() +FLAG AffixMgr::get_needaffix() const { - return pseudoroot; + return needaffix; } // return the onlyincompound flag -FLAG AffixMgr::get_onlyincompound() +FLAG AffixMgr::get_onlyincompound() const { return onlyincompound; } // return the compound word signal flag -FLAG AffixMgr::get_compoundroot() +FLAG AffixMgr::get_compoundroot() const { return compoundroot; } // return the compound begin signal flag -FLAG AffixMgr::get_compoundbegin() +FLAG AffixMgr::get_compoundbegin() const { return compoundbegin; } // return the value of checknum -int AffixMgr::get_checknum() +int AffixMgr::get_checknum() const { return checknum; } // return the value of prefix -const char * AffixMgr::get_prefix() +const char * AffixMgr::get_prefix() const { - if (pfx) return ((PfxEntry *)pfx)->getKey(); + if (pfx) return pfx->getKey(); return NULL; } // return the value of suffix -const char * AffixMgr::get_suffix() +const char * AffixMgr::get_suffix() const { return sfxappnd; } -// return the value of derived form (base word with first suffix). -const char * AffixMgr::get_derived() -{ - return derived; -} - // return the value of suffix -const char * AffixMgr::get_version() +const char * AffixMgr::get_version() const { return version; } // return lemma_present flag -FLAG AffixMgr::get_lemma_present() +FLAG AffixMgr::get_lemma_present() const { return lemma_present; } @@ -3078,68 +3391,86 @@ FLAG AffixMgr::get_lemma_present() // utility method to look up root words in hash table struct hentry * AffixMgr::lookup(const char * word) { - if (! pHMgr) return NULL; - return pHMgr->lookup(word); + int i; + struct hentry * he = NULL; + for (i = 0; i < *maxdic && !he; i++) { + he = (alldic[i])->lookup(word); + } + return he; } // return the value of suffix -const int AffixMgr::have_contclass() +int AffixMgr::have_contclass() const { return havecontclass; } // return utf8 -int AffixMgr::get_utf8() +int AffixMgr::get_utf8() const { return utf8; } -// return nosplitsugs -int AffixMgr::get_maxngramsugs(void) +int AffixMgr::get_maxngramsugs(void) const { return maxngramsugs; } +int AffixMgr::get_maxcpdsugs(void) const +{ + return maxcpdsugs; +} + +int AffixMgr::get_maxdiff(void) const +{ + return maxdiff; +} + +int AffixMgr::get_onlymaxdiff(void) const +{ + return onlymaxdiff; +} + // return nosplitsugs -int AffixMgr::get_nosplitsugs(void) +int AffixMgr::get_nosplitsugs(void) const { return nosplitsugs; } // return sugswithdots -int AffixMgr::get_sugswithdots(void) +int AffixMgr::get_sugswithdots(void) const { return sugswithdots; } /* parse flag */ -int AffixMgr::parse_flag(char * line, unsigned short * out, const char * name) { +int AffixMgr::parse_flag(char * line, unsigned short * out, FileMgr * af) { char * s = NULL; - if (*out != FLAG_NULL) { - HUNSPELL_WARNING(stderr, "error: duplicate %s line\n", name); + if (*out != FLAG_NULL && !(*out >= DEFAULTFLAGS)) { + HUNSPELL_WARNING(stderr, "error: line %d: multiple definitions of an affix file parameter\n", af->getlinenum()); return 1; } - if (parse_string(line, &s, name)) return 1; + if (parse_string(line, &s, af->getlinenum())) return 1; *out = pHMgr->decode_flag(s); free(s); return 0; } /* parse num */ -int AffixMgr::parse_num(char * line, int * out, const char * name) { +int AffixMgr::parse_num(char * line, int * out, FileMgr * af) { char * s = NULL; if (*out != -1) { - HUNSPELL_WARNING(stderr, "error: duplicate %s line\n", name); + HUNSPELL_WARNING(stderr, "error: line %d: multiple definitions of an affix file parameter\n", af->getlinenum()); return 1; } - if (parse_string(line, &s, name)) return 1; + if (parse_string(line, &s, af->getlinenum())) return 1; *out = atoi(s); free(s); return 0; } /* parse in the max syllablecount of compound words and */ -int AffixMgr::parse_cpdsyllable(char * line) +int AffixMgr::parse_cpdsyllable(char * line, FileMgr * af) { char * tp = line; char * piece; @@ -3172,11 +3503,10 @@ int AffixMgr::parse_cpdsyllable(char * line) } i++; } - free(piece); piece = mystrsep(&tp, 0); } if (np < 2) { - HUNSPELL_WARNING(stderr, "error: missing compoundsyllable information\n"); + HUNSPELL_WARNING(stderr, "error: line %d: missing compoundsyllable information\n", af->getlinenum()); return 1; } if (np == 2) cpdvowels = mystrdup("aeiouAEIOU"); @@ -3184,10 +3514,10 @@ int AffixMgr::parse_cpdsyllable(char * line) } /* parse in the typical fault correcting table */ -int AffixMgr::parse_reptable(char * line, FILE * af) +int AffixMgr::parse_reptable(char * line, FileMgr * af) { if (numrep != 0) { - HUNSPELL_WARNING(stderr, "error: duplicate REP tables used\n"); + HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n", af->getlinenum()); return 1; } char * tp = line; @@ -3202,15 +3532,11 @@ int AffixMgr::parse_reptable(char * line, FILE * af) case 1: { numrep = atoi(piece); if (numrep < 1) { - HUNSPELL_WARNING(stderr, "incorrect number of entries in replacement table\n"); - free(piece); + HUNSPELL_WARNING(stderr, "error: line %d: incorrect entry number\n", af->getlinenum()); return 1; } reptable = (replentry *) malloc(numrep * sizeof(struct replentry)); - if (!reptable) { - free(piece); - return 1; - } + if (!reptable) return 1; np++; break; } @@ -3218,18 +3544,17 @@ int AffixMgr::parse_reptable(char * line, FILE * af) } i++; } - free(piece); piece = mystrsep(&tp, 0); } if (np != 2) { - HUNSPELL_WARNING(stderr, "error: missing replacement table information\n"); + HUNSPELL_WARNING(stderr, "error: line %d: missing data\n", af->getlinenum()); return 1; } /* now parse the numrep lines to read in the remainder of the table */ - char * nl = line; + char * nl; for (int j=0; j < numrep; j++) { - if (!fgets(nl,MAXLNLEN,af)) return 1; + if (!(nl = af->getline())) return 1; mychomp(nl); tp = nl; i = 0; @@ -3241,34 +3566,216 @@ int AffixMgr::parse_reptable(char * line, FILE * af) switch(i) { case 0: { if (strncmp(piece,"REP",3) != 0) { - HUNSPELL_WARNING(stderr, "error: replacement table is corrupt\n"); - free(piece); + HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum()); + numrep = 0; return 1; } break; } - case 1: { reptable[j].pattern = mystrrep(mystrdup(piece),"_"," "); break; } + case 1: { + if (*piece == '^') reptable[j].start = true; else reptable[j].start = false; + reptable[j].pattern = mystrrep(mystrdup(piece + int(reptable[j].start)),"_"," "); + int lr = strlen(reptable[j].pattern) - 1; + if (reptable[j].pattern[lr] == '$') { + reptable[j].end = true; + reptable[j].pattern[lr] = '\0'; + } else reptable[j].end = false; + break; + } case 2: { reptable[j].pattern2 = mystrrep(mystrdup(piece),"_"," "); break; } default: break; } i++; } - free(piece); piece = mystrsep(&tp, 0); } if ((!(reptable[j].pattern)) || (!(reptable[j].pattern2))) { - HUNSPELL_WARNING(stderr, "error: replacement table is corrupt\n"); + HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum()); + numrep = 0; + return 1; + } + } + return 0; +} + +/* parse in the typical fault correcting table */ +int AffixMgr::parse_convtable(char * line, FileMgr * af, RepList ** rl, const char * keyword) +{ + if (*rl) { + HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n", af->getlinenum()); + return 1; + } + char * tp = line; + char * piece; + int i = 0; + int np = 0; + int numrl = 0; + piece = mystrsep(&tp, 0); + while (piece) { + if (*piece != '\0') { + switch(i) { + case 0: { np++; break; } + case 1: { + numrl = atoi(piece); + if (numrl < 1) { + HUNSPELL_WARNING(stderr, "error: line %d: incorrect entry number\n", af->getlinenum()); + return 1; + } + *rl = new RepList(numrl); + if (!*rl) return 1; + np++; + break; + } + default: break; + } + i++; + } + piece = mystrsep(&tp, 0); + } + if (np != 2) { + HUNSPELL_WARNING(stderr, "error: line %d: missing data\n", af->getlinenum()); + return 1; + } + + /* now parse the num lines to read in the remainder of the table */ + char * nl; + for (int j=0; j < numrl; j++) { + if (!(nl = af->getline())) return 1; + mychomp(nl); + tp = nl; + i = 0; + char * pattern = NULL; + char * pattern2 = NULL; + piece = mystrsep(&tp, 0); + while (piece) { + if (*piece != '\0') { + switch(i) { + case 0: { + if (strncmp(piece, keyword, sizeof(keyword)) != 0) { + HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum()); + delete *rl; + *rl = NULL; + return 1; + } + break; + } + case 1: { pattern = mystrrep(mystrdup(piece),"_"," "); break; } + case 2: { + pattern2 = mystrrep(mystrdup(piece),"_"," "); + break; + } + default: break; + } + i++; + } + piece = mystrsep(&tp, 0); + } + if (!pattern || !pattern2) { + if (pattern) + free(pattern); + if (pattern2) + free(pattern2); + HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum()); + return 1; + } + (*rl)->add(pattern, pattern2); + } + return 0; +} + + +/* parse in the typical fault correcting table */ +int AffixMgr::parse_phonetable(char * line, FileMgr * af) +{ + if (phone) { + HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n", af->getlinenum()); + return 1; + } + char * tp = line; + char * piece; + int i = 0; + int np = 0; + piece = mystrsep(&tp, 0); + while (piece) { + if (*piece != '\0') { + switch(i) { + case 0: { np++; break; } + case 1: { + phone = (phonetable *) malloc(sizeof(struct phonetable)); + if (!phone) return 1; + phone->num = atoi(piece); + phone->rules = NULL; + phone->utf8 = (char) utf8; + if (phone->num < 1) { + HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n", af->getlinenum()); + return 1; + } + phone->rules = (char * *) malloc(2 * (phone->num + 1) * sizeof(char *)); + if (!phone->rules) { + free(phone); + phone = NULL; + return 1; + } + np++; + break; + } + default: break; + } + i++; + } + piece = mystrsep(&tp, 0); + } + if (np != 2) { + HUNSPELL_WARNING(stderr, "error: line %d: missing data\n", af->getlinenum()); + return 1; + } + + /* now parse the phone->num lines to read in the remainder of the table */ + char * nl; + for (int j=0; j < phone->num; j++) { + if (!(nl = af->getline())) return 1; + mychomp(nl); + tp = nl; + i = 0; + phone->rules[j * 2] = NULL; + phone->rules[j * 2 + 1] = NULL; + piece = mystrsep(&tp, 0); + while (piece) { + if (*piece != '\0') { + switch(i) { + case 0: { + if (strncmp(piece,"PHONE",5) != 0) { + HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum()); + phone->num = 0; + return 1; + } + break; + } + case 1: { phone->rules[j * 2] = mystrrep(mystrdup(piece),"_",""); break; } + case 2: { phone->rules[j * 2 + 1] = mystrrep(mystrdup(piece),"_",""); break; } + default: break; + } + i++; + } + piece = mystrsep(&tp, 0); + } + if ((!(phone->rules[j * 2])) || (!(phone->rules[j * 2 + 1]))) { + HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum()); + phone->num = 0; return 1; } } + phone->rules[phone->num * 2] = mystrdup(""); + phone->rules[phone->num * 2 + 1] = mystrdup(""); + init_phonet_hash(*phone); return 0; } /* parse in the checkcompoundpattern table */ -int AffixMgr::parse_checkcpdtable(char * line, FILE * af) +int AffixMgr::parse_checkcpdtable(char * line, FileMgr * af) { if (numcheckcpd != 0) { - HUNSPELL_WARNING(stderr, "error: duplicate compound pattern tables used\n"); + HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n", af->getlinenum()); return 1; } char * tp = line; @@ -3283,15 +3790,11 @@ int AffixMgr::parse_checkcpdtable(char * line, FILE * af) case 1: { numcheckcpd = atoi(piece); if (numcheckcpd < 1) { - HUNSPELL_WARNING(stderr, "incorrect number of entries in compound pattern table\n"); - free(piece); + HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n", af->getlinenum()); return 1; } - checkcpdtable = (replentry *) malloc(numcheckcpd * sizeof(struct replentry)); - if (!checkcpdtable) { - free(piece); - return 1; - } + checkcpdtable = (patentry *) malloc(numcheckcpd * sizeof(struct patentry)); + if (!checkcpdtable) return 1; np++; break; } @@ -3299,46 +3802,64 @@ int AffixMgr::parse_checkcpdtable(char * line, FILE * af) } i++; } - free(piece); piece = mystrsep(&tp, 0); } if (np != 2) { - HUNSPELL_WARNING(stderr, "error: missing compound pattern table information\n"); + HUNSPELL_WARNING(stderr, "error: line %d: missing data\n", af->getlinenum()); return 1; - } - + } + /* now parse the numcheckcpd lines to read in the remainder of the table */ - char * nl = line; + char * nl; for (int j=0; j < numcheckcpd; j++) { - if (!fgets(nl,MAXLNLEN,af)) return 1; + if (!(nl = af->getline())) return 1; mychomp(nl); tp = nl; i = 0; checkcpdtable[j].pattern = NULL; checkcpdtable[j].pattern2 = NULL; + checkcpdtable[j].pattern3 = NULL; + checkcpdtable[j].cond = FLAG_NULL; + checkcpdtable[j].cond2 = FLAG_NULL; piece = mystrsep(&tp, 0); while (piece) { if (*piece != '\0') { switch(i) { case 0: { if (strncmp(piece,"CHECKCOMPOUNDPATTERN",20) != 0) { - HUNSPELL_WARNING(stderr, "error: compound pattern table is corrupt\n"); - free(piece); + HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum()); + numcheckcpd = 0; return 1; } break; } - case 1: { checkcpdtable[j].pattern = mystrdup(piece); break; } - case 2: { checkcpdtable[j].pattern2 = mystrdup(piece); break; } + case 1: { + checkcpdtable[j].pattern = mystrdup(piece); + char * p = strchr(checkcpdtable[j].pattern, '/'); + if (p) { + *p = '\0'; + checkcpdtable[j].cond = pHMgr->decode_flag(p + 1); + } + break; } + case 2: { + checkcpdtable[j].pattern2 = mystrdup(piece); + char * p = strchr(checkcpdtable[j].pattern2, '/'); + if (p) { + *p = '\0'; + checkcpdtable[j].cond2 = pHMgr->decode_flag(p + 1); + } + break; + } + case 3: { checkcpdtable[j].pattern3 = mystrdup(piece); simplifiedcpd = 1; break; } default: break; } i++; } - free(piece); piece = mystrsep(&tp, 0); } if ((!(checkcpdtable[j].pattern)) || (!(checkcpdtable[j].pattern2))) { - HUNSPELL_WARNING(stderr, "error: compound pattern table is corrupt\n"); + HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum()); + numcheckcpd = 0; return 1; } } @@ -3346,10 +3867,10 @@ int AffixMgr::parse_checkcpdtable(char * line, FILE * af) } /* parse in the compound rule table */ -int AffixMgr::parse_defcpdtable(char * line, FILE * af) +int AffixMgr::parse_defcpdtable(char * line, FileMgr * af) { if (numdefcpd != 0) { - HUNSPELL_WARNING(stderr, "error: duplicate compound rule tables used\n"); + HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n", af->getlinenum()); return 1; } char * tp = line; @@ -3364,15 +3885,11 @@ int AffixMgr::parse_defcpdtable(char * line, FILE * af) case 1: { numdefcpd = atoi(piece); if (numdefcpd < 1) { - HUNSPELL_WARNING(stderr, "incorrect number of entries in compound rule table\n"); - free(piece); + HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n", af->getlinenum()); return 1; } defcpdtable = (flagentry *) malloc(numdefcpd * sizeof(flagentry)); - if (!defcpdtable) { - free(piece); - return 1; - } + if (!defcpdtable) return 1; np++; break; } @@ -3380,18 +3897,17 @@ int AffixMgr::parse_defcpdtable(char * line, FILE * af) } i++; } - free(piece); piece = mystrsep(&tp, 0); } if (np != 2) { - HUNSPELL_WARNING(stderr, "error: missing compound rule table information\n"); + HUNSPELL_WARNING(stderr, "error: line %d: missing data\n", af->getlinenum()); return 1; } /* now parse the numdefcpd lines to read in the remainder of the table */ - char * nl = line; + char * nl; for (int j=0; j < numdefcpd; j++) { - if (!fgets(nl,MAXLNLEN,af)) return 1; + if (!(nl = af->getline())) return 1; mychomp(nl); tp = nl; i = 0; @@ -3402,26 +3918,46 @@ int AffixMgr::parse_defcpdtable(char * line, FILE * af) switch(i) { case 0: { if (strncmp(piece, "COMPOUNDRULE", 12) != 0) { - HUNSPELL_WARNING(stderr, "error: compound rule table is corrupt\n"); - free(piece); + HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum()); + numdefcpd = 0; return 1; } break; } - case 1: { - defcpdtable[j].len = - pHMgr->decode_flags(&(defcpdtable[j].def), piece); + case 1: { // handle parenthesized flags + if (strchr(piece, '(')) { + defcpdtable[j].def = (FLAG *) malloc(strlen(piece) * sizeof(FLAG)); + defcpdtable[j].len = 0; + int end = 0; + FLAG * conv; + while (!end) { + char * par = piece + 1; + while (*par != '(' && *par != ')' && *par != '\0') par++; + if (*par == '\0') end = 1; else *par = '\0'; + if (*piece == '(') piece++; + if (*piece == '*' || *piece == '?') { + defcpdtable[j].def[defcpdtable[j].len++] = (FLAG) *piece; + } else if (*piece != '\0') { + int l = pHMgr->decode_flags(&conv, piece, af); + for (int k = 0; k < l; k++) defcpdtable[j].def[defcpdtable[j].len++] = conv[k]; + free(conv); + } + piece = par + 1; + } + } else { + defcpdtable[j].len = pHMgr->decode_flags(&(defcpdtable[j].def), piece, af); + } break; } default: break; } i++; } - free(piece); piece = mystrsep(&tp, 0); } if (!defcpdtable[j].len) { - HUNSPELL_WARNING(stderr, "error: compound rule table is corrupt\n"); + HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum()); + numdefcpd = 0; return 1; } } @@ -3430,10 +3966,10 @@ int AffixMgr::parse_defcpdtable(char * line, FILE * af) /* parse in the character map table */ -int AffixMgr::parse_maptable(char * line, FILE * af) +int AffixMgr::parse_maptable(char * line, FileMgr * af) { if (nummap != 0) { - HUNSPELL_WARNING(stderr, "error: duplicate MAP tables used\n"); + HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n", af->getlinenum()); return 1; } char * tp = line; @@ -3448,15 +3984,11 @@ int AffixMgr::parse_maptable(char * line, FILE * af) case 1: { nummap = atoi(piece); if (nummap < 1) { - HUNSPELL_WARNING(stderr, "incorrect number of entries in map table\n"); - free(piece); + HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n", af->getlinenum()); return 1; } maptable = (mapentry *) malloc(nummap * sizeof(struct mapentry)); - if (!maptable) { - free(piece); - return 1; - } + if (!maptable) return 1; np++; break; } @@ -3464,18 +3996,17 @@ int AffixMgr::parse_maptable(char * line, FILE * af) } i++; } - free(piece); piece = mystrsep(&tp, 0); } if (np != 2) { - HUNSPELL_WARNING(stderr, "error: missing map table information\n"); + HUNSPELL_WARNING(stderr, "error: line %d: missing data\n", af->getlinenum()); return 1; } /* now parse the nummap lines to read in the remainder of the table */ - char * nl = line; + char * nl; for (int j=0; j < nummap; j++) { - if (!fgets(nl,MAXLNLEN,af)) return 1; + if (!(nl = af->getline())) return 1; mychomp(nl); tp = nl; i = 0; @@ -3487,40 +4018,51 @@ int AffixMgr::parse_maptable(char * line, FILE * af) switch(i) { case 0: { if (strncmp(piece,"MAP",3) != 0) { - HUNSPELL_WARNING(stderr, "error: map table is corrupt\n"); - free(piece); + HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum()); + nummap = 0; return 1; } break; } case 1: { - maptable[j].len = 0; - maptable[j].set = NULL; - maptable[j].set_utf16 = NULL; - if (!utf8) { - maptable[j].set = mystrdup(piece); - maptable[j].len = strlen(maptable[j].set); - } else { - w_char w[MAXWORDLEN]; - int n = u8_u16(w, MAXWORDLEN, piece); - if (n > 0) { - flag_qsort((unsigned short *) w, 0, n); - maptable[j].set_utf16 = (w_char *) malloc(n * sizeof(w_char)); - if (!maptable[j].set_utf16) return 1; - memcpy(maptable[j].set_utf16, w, n * sizeof(w_char)); - } - maptable[j].len = n; - } + int setn = 0; + maptable[j].len = strlen(piece); + maptable[j].set = (char **) malloc(maptable[j].len * sizeof(char*)); + if (!maptable[j].set) return 1; + for (int k = 0; k < maptable[j].len; k++) { + int chl = 1; + int chb = k; + if (piece[k] == '(') { + char * parpos = strchr(piece + k, ')'); + if (parpos != NULL) { + chb = k + 1; + chl = (int)(parpos - piece) - k - 1; + k = k + chl + 1; + } + } else { + if (utf8 && (piece[k] & 0xc0) == 0xc0) { + for (k++; utf8 && (piece[k] & 0xc0) == 0x80; k++); + chl = k - chb; + k--; + } + } + maptable[j].set[setn] = (char *) malloc(chl + 1); + if (!maptable[j].set[setn]) return 1; + strncpy(maptable[j].set[setn], piece + chb, chl); + maptable[j].set[setn][chl] = '\0'; + setn++; + } + maptable[j].len = setn; break; } default: break; } i++; } - free(piece); piece = mystrsep(&tp, 0); } - if ((!(maptable[j].set || maptable[j].set_utf16)) || (!(maptable[j].len))) { - HUNSPELL_WARNING(stderr, "error: map table is corrupt\n"); + if (!maptable[j].set || !maptable[j].len) { + HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum()); + nummap = 0; return 1; } } @@ -3528,10 +4070,10 @@ int AffixMgr::parse_maptable(char * line, FILE * af) } /* parse in the word breakpoint table */ -int AffixMgr::parse_breaktable(char * line, FILE * af) +int AffixMgr::parse_breaktable(char * line, FileMgr * af) { - if (numbreak != 0) { - HUNSPELL_WARNING(stderr, "error: duplicate word breakpoint tables used\n"); + if (numbreak > -1) { + HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n", af->getlinenum()); return 1; } char * tp = line; @@ -3545,16 +4087,13 @@ int AffixMgr::parse_breaktable(char * line, FILE * af) case 0: { np++; break; } case 1: { numbreak = atoi(piece); - if (numbreak < 1) { - HUNSPELL_WARNING(stderr, "incorrect number of entries in BREAK table\n"); - free(piece); + if (numbreak < 0) { + HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n", af->getlinenum()); return 1; } + if (numbreak == 0) return 0; breaktable = (char **) malloc(numbreak * sizeof(char *)); - if (!breaktable) { - free(piece); - return 1; - } + if (!breaktable) return 1; np++; break; } @@ -3562,18 +4101,17 @@ int AffixMgr::parse_breaktable(char * line, FILE * af) } i++; } - free(piece); piece = mystrsep(&tp, 0); } if (np != 2) { - HUNSPELL_WARNING(stderr, "error: missing word breakpoint table information\n"); + HUNSPELL_WARNING(stderr, "error: line %d: missing data\n", af->getlinenum()); return 1; } /* now parse the numbreak lines to read in the remainder of the table */ - char * nl = line; + char * nl; for (int j=0; j < numbreak; j++) { - if (!fgets(nl,MAXLNLEN,af)) return 1; + if (!(nl = af->getline())) return 1; mychomp(nl); tp = nl; i = 0; @@ -3583,8 +4121,8 @@ int AffixMgr::parse_breaktable(char * line, FILE * af) switch(i) { case 0: { if (strncmp(piece,"BREAK",5) != 0) { - HUNSPELL_WARNING(stderr, "error: BREAK table is corrupt\n"); - free(piece); + HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum()); + numbreak = 0; return 1; } break; @@ -3597,26 +4135,50 @@ int AffixMgr::parse_breaktable(char * line, FILE * af) } i++; } - free(piece); piece = mystrsep(&tp, 0); } if (!breaktable) { - HUNSPELL_WARNING(stderr, "error: BREAK table is corrupt\n"); + HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum()); + numbreak = 0; return 1; } } return 0; } -int AffixMgr::parse_affix(char * line, const char at, FILE * af, char * dupflags) +void AffixMgr::reverse_condition(char * piece) { + int neg = 0; + for (char * k = piece + strlen(piece) - 1; k >= piece; k--) { + switch(*k) { + case '[': { + if (neg) *(k+1) = '['; else *k = ']'; + break; + } + case ']': { + *k = '['; + if (neg) *(k+1) = '^'; + neg = 0; + break; + } + case '^': { + if (*(k+1) == ']') neg = 1; else *(k+1) = *k; + break; + } + default: { + if (neg) *(k+1) = *k; + } + } + } +} + +int AffixMgr::parse_affix(char * line, const char at, FileMgr * af, char * dupflags) { int numents = 0; // number of affentry structures to parse unsigned short aflag = 0; // affix char identifier char ff=0; - struct affentry * ptr= NULL; - struct affentry * nptr= NULL; + std::vector affentries; char * tp = line; char * nl = line; @@ -3631,6 +4193,7 @@ int AffixMgr::parse_affix(char * line, const char at, FILE * af, char * dupflag // split affix header line into pieces int np = 0; + piece = mystrsep(&tp, 0); while (piece) { if (*piece != '\0') { @@ -3644,10 +4207,11 @@ int AffixMgr::parse_affix(char * line, const char at, FILE * af, char * dupflag aflag = pHMgr->decode_flag(piece); if (((at == 'S') && (dupflags[aflag] & dupSFX)) || ((at == 'P') && (dupflags[aflag] & dupPFX))) { - HUNSPELL_WARNING(stderr, "error: duplicate affix flag %s in line %s\n", piece, nl); + HUNSPELL_WARNING(stderr, "error: line %d: multiple definitions of an affix flag\n", + af->getlinenum()); // return 1; XXX permissive mode for bad dictionaries } - dupflags[aflag] += ((at == 'S') ? dupSFX : dupPFX); + dupflags[aflag] += (char) ((at == 'S') ? dupSFX : dupPFX); break; } // piece 3 - is cross product indicator @@ -3659,44 +4223,42 @@ int AffixMgr::parse_affix(char * line, const char at, FILE * af, char * dupflag numents = atoi(piece); if (numents == 0) { char * err = pHMgr->encode_flag(aflag); - HUNSPELL_WARNING(stderr, "error: affix %s header has incorrect entry count in line %s\n", - err, nl); - free(err); + if (err) { + HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n", + af->getlinenum()); + free(err); + } return 1; } - ptr = (struct affentry *) malloc(numents * sizeof(struct affentry)); - if (!ptr) return 1; - ptr->opts = ff; - if (utf8) ptr->opts += aeUTF8; - if (pHMgr->is_aliasf()) ptr->opts += aeALIASF; -#ifdef HUNSPELL_EXPERIMENTAL - if (pHMgr->is_aliasm()) ptr->opts += aeALIASM; -#endif - ptr->aflag = aflag; + affentries.resize(numents); + affentries[0].opts = ff; + if (utf8) affentries[0].opts += aeUTF8; + if (pHMgr->is_aliasf()) affentries[0].opts += aeALIASF; + if (pHMgr->is_aliasm()) affentries[0].opts += aeALIASM; + affentries[0].aflag = aflag; } default: break; } i++; } - free(piece); piece = mystrsep(&tp, 0); } // check to make sure we parsed enough pieces if (np != 4) { - char * err = pHMgr->encode_flag(aflag); - HUNSPELL_WARNING(stderr, "error: affix %s header has insufficient data in line %s\n", err, nl); - free(err); - free(ptr); + char * err = pHMgr->encode_flag(aflag); + if (err) { + HUNSPELL_WARNING(stderr, "error: line %d: missing data\n", af->getlinenum()); + free(err); + } return 1; } - // store away ptr to first affentry - nptr = ptr; - // now parse numents affentries for this affix - for (int j=0; j < numents; j++) { - if (!fgets(nl,MAXLNLEN,af)) return 1; + std::vector::iterator start = affentries.begin(); + std::vector::iterator end = affentries.end(); + for (std::vector::iterator entry = start; entry != end; ++entry) { + if (!(nl = af->getline())) return 1; mychomp(nl); tp = nl; i = 0; @@ -3710,7 +4272,8 @@ int AffixMgr::parse_affix(char * line, const char at, FILE * af, char * dupflag // piece 1 - is type case 0: { np++; - if (nptr != ptr) nptr->opts = ptr->opts; + if (entry != start) entry->opts = start->opts & + (char) (aeXPRODUCT + aeUTF8 + aeALIASF + aeALIASM); break; } @@ -3719,14 +4282,15 @@ int AffixMgr::parse_affix(char * line, const char at, FILE * af, char * dupflag np++; if (pHMgr->decode_flag(piece) != aflag) { char * err = pHMgr->encode_flag(aflag); - HUNSPELL_WARNING(stderr, "error: affix %s is corrupt near line %s\n", err, nl); - HUNSPELL_WARNING(stderr, "error: possible incorrect count\n"); - free(err); - free(piece); + if (err) { + HUNSPELL_WARNING(stderr, "error: line %d: affix %s is corrupt\n", + af->getlinenum(), err); + free(err); + } return 1; } - if (nptr != ptr) nptr->aflag = ptr->aflag; + if (entry != start) entry->aflag = start->aflag; break; } @@ -3736,12 +4300,12 @@ int AffixMgr::parse_affix(char * line, const char at, FILE * af, char * dupflag if (complexprefixes) { if (utf8) reverseword_utf(piece); else reverseword(piece); } - nptr->strip = mystrdup(piece); - nptr->stripl = (unsigned char) strlen(nptr->strip); - if (strcmp(nptr->strip,"0") == 0) { - free(nptr->strip); - nptr->strip=mystrdup(""); - nptr->stripl = 0; + entry->strip = mystrdup(piece); + entry->stripl = (unsigned char) strlen(entry->strip); + if (strcmp(entry->strip,"0") == 0) { + free(entry->strip); + entry->strip=mystrdup(""); + entry->stripl = 0; } break; } @@ -3749,11 +4313,9 @@ int AffixMgr::parse_affix(char * line, const char at, FILE * af, char * dupflag // piece 4 - is affix string or 0 for null case 3: { char * dash; -#ifdef HUNSPELL_EXPERIMENTAL - nptr->morphcode = NULL; -#endif - nptr->contclass = NULL; - nptr->contclasslen = 0; + entry->morphcode = NULL; + entry->contclass = NULL; + entry->contclasslen = 0; np++; dash = strchr(piece, '/'); if (dash) { @@ -3766,24 +4328,25 @@ int AffixMgr::parse_affix(char * line, const char at, FILE * af, char * dupflag remove_ignored_chars(piece,ignorechars); } } - + if (complexprefixes) { if (utf8) reverseword_utf(piece); else reverseword(piece); } - nptr->appnd = mystrdup(piece); - + entry->appnd = mystrdup(piece); + if (pHMgr->is_aliasf()) { int index = atoi(dash + 1); - nptr->contclasslen = (unsigned short) pHMgr->get_aliasf(index, &(nptr->contclass)); + entry->contclasslen = (unsigned short) pHMgr->get_aliasf(index, &(entry->contclass), af); + if (!entry->contclasslen) HUNSPELL_WARNING(stderr, "error: bad affix flag alias: \"%s\"\n", dash+1); } else { - nptr->contclasslen = (unsigned short) pHMgr->decode_flags(&(nptr->contclass), dash + 1); - flag_qsort(nptr->contclass, 0, nptr->contclasslen); + entry->contclasslen = (unsigned short) pHMgr->decode_flags(&(entry->contclass), dash + 1, af); + flag_qsort(entry->contclass, 0, entry->contclasslen); } *dash = '/'; havecontclass = 1; - for (unsigned short _i = 0; _i < nptr->contclasslen; _i++) { - contclasses[(nptr->contclass)[_i]] = 1; + for (unsigned short _i = 0; _i < entry->contclasslen; _i++) { + contclasses[(entry->contclass)[_i]] = 1; } } else { if (ignorechars) { @@ -3797,14 +4360,14 @@ int AffixMgr::parse_affix(char * line, const char at, FILE * af, char * dupflag if (complexprefixes) { if (utf8) reverseword_utf(piece); else reverseword(piece); } - nptr->appnd = mystrdup(piece); + entry->appnd = mystrdup(piece); } - - nptr->appndl = (unsigned char) strlen(nptr->appnd); - if (strcmp(nptr->appnd,"0") == 0) { - free(nptr->appnd); - nptr->appnd=mystrdup(""); - nptr->appndl = 0; + + entry->appndl = (unsigned char) strlen(entry->appnd); + if (strcmp(entry->appnd,"0") == 0) { + free(entry->appnd); + entry->appnd=mystrdup(""); + entry->appndl = 0; } break; } @@ -3813,103 +4376,83 @@ int AffixMgr::parse_affix(char * line, const char at, FILE * af, char * dupflag case 4: { np++; if (complexprefixes) { - int neg = 0; if (utf8) reverseword_utf(piece); else reverseword(piece); - // reverse condition - for (char * k = piece + strlen(piece) - 1; k >= piece; k--) { - switch(*k) { - case '[': { - if (neg) *(k+1) = '['; else *k = ']'; - break; - } - case ']': { - *k = '['; - if (neg) *(k+1) = '^'; - neg = 0; - break; - } - case '^': { - if (*(k+1) == ']') neg = 1; else *(k+1) = *k; - break; - } - default: { - if (neg) *(k+1) = *k; - } - } - } + reverse_condition(piece); } - if (nptr->stripl && (strcmp(piece, ".") != 0) && - redundant_condition(at, nptr->strip, nptr->stripl, piece, nl)) + if (entry->stripl && (strcmp(piece, ".") != 0) && + redundant_condition(at, entry->strip, entry->stripl, piece, af->getlinenum())) strcpy(piece, "."); - if (encodeit(nptr,piece)) return 1; + if (at == 'S') { + reverseword(piece); + reverse_condition(piece); + } + if (encodeit(*entry, piece)) return 1; break; } - -#ifdef HUNSPELL_EXPERIMENTAL + case 5: { np++; if (pHMgr->is_aliasm()) { int index = atoi(piece); - nptr->morphcode = pHMgr->get_aliasm(index); + entry->morphcode = pHMgr->get_aliasm(index); } else { - if (complexprefixes) { + if (complexprefixes) { // XXX - fix me for morph. gen. if (utf8) reverseword_utf(piece); else reverseword(piece); } - nptr->morphcode = mystrdup(piece); + // add the remaining of the line + if (*tp) { + *(tp - 1) = ' '; + tp = tp + strlen(tp); + } + entry->morphcode = mystrdup(piece); + if (!entry->morphcode) return 1; } break; } -#endif - default: break; } i++; } - free(piece); piece = mystrsep(&tp, 0); } // check to make sure we parsed enough pieces if (np < 4) { char * err = pHMgr->encode_flag(aflag); - HUNSPELL_WARNING(stderr, "error: affix %s is corrupt near line %s\n", err, nl); - free(err); - free(ptr); + if (err) { + HUNSPELL_WARNING(stderr, "error: line %d: affix %s is corrupt\n", + af->getlinenum(), err); + free(err); + } return 1; } #ifdef DEBUG -#ifdef HUNSPELL_EXPERIMENTAL // detect unnecessary fields, excepting comments if (basefieldnum) { - int fieldnum = !(nptr->morphcode) ? 5 : ((*(nptr->morphcode)=='#') ? 5 : 6); + int fieldnum = !(entry->morphcode) ? 5 : ((*(entry->morphcode)=='#') ? 5 : 6); if (fieldnum != basefieldnum) - HUNSPELL_WARNING(stderr, "warning: bad field number:\n%s\n", nl); + HUNSPELL_WARNING(stderr, "warning: line %d: bad field number\n", af->getlinenum()); } else { - basefieldnum = !(nptr->morphcode) ? 5 : ((*(nptr->morphcode)=='#') ? 5 : 6); + basefieldnum = !(entry->morphcode) ? 5 : ((*(entry->morphcode)=='#') ? 5 : 6); } #endif -#endif - nptr++; } // now create SfxEntry or PfxEntry objects and use links to // build an ordered (sorted by affix string) list - nptr = ptr; - for (int k = 0; k < numents; k++) { + for (std::vector::iterator entry = start; entry != end; ++entry) { if (at == 'P') { - PfxEntry * pfxptr = new PfxEntry(this,nptr); - build_pfxtree((AffEntry *)pfxptr); + PfxEntry * pfxptr = new PfxEntry(this,&(*entry)); + build_pfxtree(pfxptr); } else { - SfxEntry * sfxptr = new SfxEntry(this,nptr); - build_sfxtree((AffEntry *)sfxptr); + SfxEntry * sfxptr = new SfxEntry(this,&(*entry)); + build_sfxtree(sfxptr); } - nptr++; - } - free(ptr); + } return 0; } -int AffixMgr::redundant_condition(char ft, char * strip, int stripl, const char * cond, char * line) { +int AffixMgr::redundant_condition(char ft, char * strip, int stripl, const char * cond, int linenum) { int condl = strlen(cond); int i; int j; @@ -3922,7 +4465,8 @@ int AffixMgr::redundant_condition(char ft, char * strip, int stripl, const char for (i = 0, j = 0; (i < stripl) && (j < condl); i++, j++) { if (cond[j] != '[') { if (cond[j] != strip[i]) { - HUNSPELL_WARNING(stderr, "warning: incompatible stripping characters and condition:\n%s\n", line); + HUNSPELL_WARNING(stderr, "warning: line %d: incompatible stripping characters and condition\n", linenum); + return 0; } } else { neg = (cond[j+1] == '^') ? 1 : 0; @@ -3932,12 +4476,12 @@ int AffixMgr::redundant_condition(char ft, char * strip, int stripl, const char if (strip[i] == cond[j]) in = 1; } while ((j < (condl - 1)) && (cond[j] != ']')); if (j == (condl - 1) && (cond[j] != ']')) { - HUNSPELL_WARNING(stderr, "error: missing ] in condition:\n%s\n", line); + HUNSPELL_WARNING(stderr, "error: line %d: missing ] in condition:\n%s\n", linenum, cond); return 0; } if ((!neg && !in) || (neg && in)) { - HUNSPELL_WARNING(stderr, "warning: incompatible stripping characters and condition:\n%s\n", line); - return 0; + HUNSPELL_WARNING(stderr, "warning: line %d: incompatible stripping characters and condition\n", linenum); + return 0; } } } @@ -3950,7 +4494,8 @@ int AffixMgr::redundant_condition(char ft, char * strip, int stripl, const char for (i = stripl - 1, j = condl - 1; (i >= 0) && (j >= 0); i--, j--) { if (cond[j] != ']') { if (cond[j] != strip[i]) { - HUNSPELL_WARNING(stderr, "warning: incompatible stripping characters and condition:\n%s\n", line); + HUNSPELL_WARNING(stderr, "warning: line %d: incompatible stripping characters and condition\n", linenum); + return 0; } } else { in = 0; @@ -3959,18 +4504,18 @@ int AffixMgr::redundant_condition(char ft, char * strip, int stripl, const char if (strip[i] == cond[j]) in = 1; } while ((j > 0) && (cond[j] != '[')); if ((j == 0) && (cond[j] != '[')) { - HUNSPELL_WARNING(stderr, "error: missing ] in condition:\n%s\n", line); + HUNSPELL_WARNING(stderr, "error: line: %d: missing ] in condition:\n%s\n", linenum, cond); return 0; } neg = (cond[j+1] == '^') ? 1 : 0; if ((!neg && !in) || (neg && in)) { - HUNSPELL_WARNING(stderr, "warning: incompatible stripping characters and condition:\n%s\n", line); - return 0; + HUNSPELL_WARNING(stderr, "warning: line %d: incompatible stripping characters and condition\n", linenum); + return 0; } } } if (j < 0) return 1; - } + } } return 0; } diff --git a/ext/hunspell/affixmgr.hxx b/ext/hunspell/affixmgr.hxx index 5c5ec2e99..d9c625aed 100644 --- a/ext/hunspell/affixmgr.hxx +++ b/ext/hunspell/affixmgr.hxx @@ -1,37 +1,40 @@ #ifndef _AFFIXMGR_HXX_ #define _AFFIXMGR_HXX_ -#ifdef MOZILLA_CLIENT -#ifdef __SUNPRO_CC // for SunONE Studio compiler -using namespace std; -#endif +#include "hunvisapi.h" + #include -#else -#include -#endif #include "atypes.hxx" #include "baseaffix.hxx" #include "hashmgr.hxx" +#include "phonet.hxx" +#include "replist.hxx" // check flag duplication #define dupSFX (1 << 0) #define dupPFX (1 << 1) -class AffixMgr +class PfxEntry; +class SfxEntry; + +class LIBHUNSPELL_DLL_EXPORTED AffixMgr { - AffEntry * pStart[SETSIZE]; - AffEntry * sStart[SETSIZE]; - AffEntry * pFlag[CONTSIZE]; - AffEntry * sFlag[CONTSIZE]; + PfxEntry * pStart[SETSIZE]; + SfxEntry * sStart[SETSIZE]; + PfxEntry * pFlag[SETSIZE]; + SfxEntry * sFlag[SETSIZE]; HashMgr * pHMgr; + HashMgr ** alldic; + int * maxdic; + char * keystring; char * trystring; char * encoding; struct cs_info * csconv; int utf8; int complexprefixes; - FLAG compoundflag; + FLAG compoundflag; FLAG compoundbegin; FLAG compoundmiddle; FLAG compoundend; @@ -42,21 +45,30 @@ class AffixMgr int checkcompoundrep; int checkcompoundcase; int checkcompoundtriple; + int simplifiedtriple; FLAG forbiddenword; FLAG nosuggest; - FLAG pseudoroot; + FLAG nongramsuggest; + FLAG needaffix; int cpdmin; int numrep; replentry * reptable; + RepList * iconvtable; + RepList * oconvtable; int nummap; mapentry * maptable; int numbreak; char ** breaktable; int numcheckcpd; - replentry * checkcpdtable; + patentry * checkcpdtable; + int simplifiedcpd; int numdefcpd; flagentry * defcpdtable; + phonetable * phone; int maxngramsugs; + int maxcpdsugs; + int maxdiff; + int onlymaxdiff; int nosplitsugs; int sugswithdots; int cpdwordmax; @@ -69,8 +81,8 @@ class AffixMgr const char * sfxappnd; // BUG: not stateless FLAG sfxflag; // BUG: not stateless char * derived; // BUG: not stateless - AffEntry * sfx; // BUG: not stateless - AffEntry * pfx; // BUG: not stateless + SfxEntry * sfx; // BUG: not stateless + PfxEntry * pfx; // BUG: not stateless int checknum; char * wordchars; unsigned short * wordchars_utf16; @@ -85,124 +97,153 @@ class AffixMgr FLAG circumfix; FLAG onlyincompound; FLAG keepcase; + FLAG forceucase; + FLAG warn; + int forbidwarn; + FLAG substandard; int checksharps; + int fullstrip; int havecontclass; // boolean variable char contclasses[CONTSIZE]; // flags of possible continuing classes (twofold affix) - flag flag_mode; - + public: - - AffixMgr(const char * affpath, HashMgr * ptr); + + AffixMgr(const char * affpath, HashMgr** ptr, int * md, + const char * key = NULL); ~AffixMgr(); struct hentry * affix_check(const char * word, int len, - const unsigned short needflag = (unsigned short) 0, char in_compound = IN_CPD_NOT); + const unsigned short needflag = (unsigned short) 0, + char in_compound = IN_CPD_NOT); struct hentry * prefix_check(const char * word, int len, char in_compound, const FLAG needflag = FLAG_NULL); inline int isSubset(const char * s1, const char * s2); struct hentry * prefix_check_twosfx(const char * word, int len, char in_compound, const FLAG needflag = FLAG_NULL); inline int isRevSubset(const char * s1, const char * end_of_s2, int len); - struct hentry * suffix_check(const char * word, int len, int sfxopts, AffEntry* ppfx, - char ** wlst, int maxSug, int * ns, const FLAG cclass = FLAG_NULL, - const FLAG needflag = FLAG_NULL, char in_compound = IN_CPD_NOT); + struct hentry * suffix_check(const char * word, int len, int sfxopts, + PfxEntry* ppfx, char ** wlst, int maxSug, int * ns, + const FLAG cclass = FLAG_NULL, const FLAG needflag = FLAG_NULL, + char in_compound = IN_CPD_NOT); struct hentry * suffix_check_twosfx(const char * word, int len, - int sfxopts, AffEntry* ppfx, const FLAG needflag = FLAG_NULL); + int sfxopts, PfxEntry* ppfx, const FLAG needflag = FLAG_NULL); char * affix_check_morph(const char * word, int len, - const FLAG needflag = FLAG_NULL, char in_compound = IN_CPD_NOT); + const FLAG needflag = FLAG_NULL, char in_compound = IN_CPD_NOT); char * prefix_check_morph(const char * word, int len, - char in_compound, const FLAG needflag = FLAG_NULL); - char * suffix_check_morph (const char * word, int len, int sfxopts, AffEntry * ppfx, - const FLAG cclass = FLAG_NULL, const FLAG needflag = FLAG_NULL, char in_compound = IN_CPD_NOT); + char in_compound, const FLAG needflag = FLAG_NULL); + char * suffix_check_morph (const char * word, int len, int sfxopts, + PfxEntry * ppfx, const FLAG cclass = FLAG_NULL, + const FLAG needflag = FLAG_NULL, char in_compound = IN_CPD_NOT); char * prefix_check_twosfx_morph(const char * word, int len, char in_compound, const FLAG needflag = FLAG_NULL); char * suffix_check_twosfx_morph(const char * word, int len, - int sfxopts, AffEntry * ppfx, const FLAG needflag = FLAG_NULL); - - int expand_rootword(struct guessword * wlst, int maxn, const char * ts, - int wl, const unsigned short * ap, unsigned short al, char * bad, int); - - short get_syllable (const char * word, int wlen); - int cpdrep_check(const char * word, int len); - int cpdpat_check(const char * word, int len); - int defcpd_check(hentry *** words, short wnum, hentry * rv, hentry ** rwords, char all); - int cpdcase_check(const char * word, int len); - inline int candidate_check(const char * word, int len); - struct hentry * compound_check(const char * word, int len, - short wordnum, short numsyllable, short maxwordnum, short wnum, hentry ** words, - char hu_mov_rule, int * cmpdstemnum, int * cmpdstem, char is_sug); - - int compound_check_morph(const char * word, int len, - short wordnum, short numsyllable, short maxwordnum, short wnum, hentry ** words, - char hu_mov_rule, char ** result, char * partresult); - - struct hentry * lookup(const char * word); - int get_numrep(); - struct replentry * get_reptable(); - int get_nummap(); - struct mapentry * get_maptable(); - int get_numbreak(); - char ** get_breaktable(); + int sfxopts, PfxEntry * ppfx, const FLAG needflag = FLAG_NULL); + + char * morphgen(char * ts, int wl, const unsigned short * ap, + unsigned short al, char * morph, char * targetmorph, int level); + + int expand_rootword(struct guessword * wlst, int maxn, const char * ts, + int wl, const unsigned short * ap, unsigned short al, char * bad, + int, char *); + + short get_syllable (const char * word, int wlen); + int cpdrep_check(const char * word, int len); + int cpdpat_check(const char * word, int len, hentry * r1, hentry * r2, + const char affixed); + int defcpd_check(hentry *** words, short wnum, hentry * rv, + hentry ** rwords, char all); + int cpdcase_check(const char * word, int len); + inline int candidate_check(const char * word, int len); + void setcminmax(int * cmin, int * cmax, const char * word, int len); + struct hentry * compound_check(const char * word, int len, short wordnum, + short numsyllable, short maxwordnum, short wnum, hentry ** words, + char hu_mov_rule, char is_sug, int * info); + + int compound_check_morph(const char * word, int len, short wordnum, + short numsyllable, short maxwordnum, short wnum, hentry ** words, + char hu_mov_rule, char ** result, char * partresult); + + struct hentry * lookup(const char * word); + int get_numrep() const; + struct replentry * get_reptable() const; + RepList * get_iconvtable() const; + RepList * get_oconvtable() const; + struct phonetable * get_phonetable() const; + int get_nummap() const; + struct mapentry * get_maptable() const; + int get_numbreak() const; + char ** get_breaktable() const; char * get_encoding(); - int get_langnum(); - char * get_try_string(); - const char * get_wordchars(); - unsigned short * get_wordchars_utf16(int * len); - char * get_ignore(); - unsigned short * get_ignore_utf16(int * len); - int get_compound(); - FLAG get_compoundflag(); - FLAG get_compoundbegin(); - FLAG get_forbiddenword(); - FLAG get_nosuggest(); -// FLAG get_circumfix(); - FLAG get_pseudoroot(); - FLAG get_onlyincompound(); - FLAG get_compoundroot(); - FLAG get_lemma_present(); - int get_checknum(); - char * get_possible_root(); - const char * get_prefix(); - const char * get_suffix(); - const char * get_derived(); - const char * get_version(); - const int have_contclass(); - int get_utf8(); - int get_complexprefixes(); - char * get_suffixed(char ); - int get_maxngramsugs(); - int get_nosplitsugs(); - int get_sugswithdots(void); - FLAG get_keepcase(void); - int get_checksharps(void); + int get_langnum() const; + char * get_key_string(); + char * get_try_string() const; + const char * get_wordchars() const; + unsigned short * get_wordchars_utf16(int * len) const; + char * get_ignore() const; + unsigned short * get_ignore_utf16(int * len) const; + int get_compound() const; + FLAG get_compoundflag() const; + FLAG get_compoundbegin() const; + FLAG get_forbiddenword() const; + FLAG get_nosuggest() const; + FLAG get_nongramsuggest() const; + FLAG get_needaffix() const; + FLAG get_onlyincompound() const; + FLAG get_compoundroot() const; + FLAG get_lemma_present() const; + int get_checknum() const; + const char * get_prefix() const; + const char * get_suffix() const; + const char * get_derived() const; + const char * get_version() const; + int have_contclass() const; + int get_utf8() const; + int get_complexprefixes() const; + char * get_suffixed(char ) const; + int get_maxngramsugs() const; + int get_maxcpdsugs() const; + int get_maxdiff() const; + int get_onlymaxdiff() const; + int get_nosplitsugs() const; + int get_sugswithdots(void) const; + FLAG get_keepcase(void) const; + FLAG get_forceucase(void) const; + FLAG get_warn(void) const; + int get_forbidwarn(void) const; + int get_checksharps(void) const; + char * encode_flag(unsigned short aflag) const; + int get_fullstrip() const; private: - int parse_file(const char * affpath); -// int parse_string(char * line, char ** out, const char * name); - int parse_flag(char * line, unsigned short * out, const char * name); - int parse_num(char * line, int * out, const char * name); -// int parse_array(char * line, char ** out, unsigned short ** out_utf16, -// int * out_utf16_len, const char * name); - int parse_cpdsyllable(char * line); - int parse_reptable(char * line, FILE * af); - int parse_maptable(char * line, FILE * af); - int parse_breaktable(char * line, FILE * af); - int parse_checkcpdtable(char * line, FILE * af); - int parse_defcpdtable(char * line, FILE * af); - int parse_affix(char * line, const char at, FILE * af, char * dupflags); - - int encodeit(struct affentry * ptr, char * cs); - int build_pfxtree(AffEntry* pfxptr); - int build_sfxtree(AffEntry* sfxptr); + int parse_file(const char * affpath, const char * key); + int parse_flag(char * line, unsigned short * out, FileMgr * af); + int parse_num(char * line, int * out, FileMgr * af); + int parse_cpdsyllable(char * line, FileMgr * af); + int parse_reptable(char * line, FileMgr * af); + int parse_convtable(char * line, FileMgr * af, RepList ** rl, const char * keyword); + int parse_phonetable(char * line, FileMgr * af); + int parse_maptable(char * line, FileMgr * af); + int parse_breaktable(char * line, FileMgr * af); + int parse_checkcpdtable(char * line, FileMgr * af); + int parse_defcpdtable(char * line, FileMgr * af); + int parse_affix(char * line, const char at, FileMgr * af, char * dupflags); + + void reverse_condition(char *); + void debugflag(char * result, unsigned short flag); + int condlen(char *); + int encodeit(affentry &entry, char * cs); + int build_pfxtree(PfxEntry* pfxptr); + int build_sfxtree(SfxEntry* sfxptr); int process_pfx_order(); int process_sfx_order(); - AffEntry * process_pfx_in_order(AffEntry * ptr, AffEntry * nptr); - AffEntry * process_sfx_in_order(AffEntry * ptr, AffEntry * nptr); + PfxEntry * process_pfx_in_order(PfxEntry * ptr, PfxEntry * nptr); + SfxEntry * process_sfx_in_order(SfxEntry * ptr, SfxEntry * nptr); int process_pfx_tree_to_list(); int process_sfx_tree_to_list(); - int redundant_condition(char, char * strip, int stripl, const char * cond, char *); + int redundant_condition(char, char * strip, int stripl, + const char * cond, int); }; #endif diff --git a/ext/hunspell/atypes.hxx b/ext/hunspell/atypes.hxx index 4f6c1ea97..df27c4d1c 100644 --- a/ext/hunspell/atypes.hxx +++ b/ext/hunspell/atypes.hxx @@ -2,30 +2,32 @@ #define _ATYPES_HXX_ #ifndef HUNSPELL_WARNING +#include #ifdef HUNSPELL_WARNING_ON #define HUNSPELL_WARNING fprintf #else -#define HUNSPELL_WARNING +// empty inline function to switch off warnings (instead of the C99 standard variadic macros) +static inline void HUNSPELL_WARNING(FILE *, const char *, ...) {} #endif #endif // HUNSTEM def. #define HUNSTEM -#include "csutil.hxx" #include "hashmgr.hxx" +#include "w_char.hxx" #define SETSIZE 256 #define CONTSIZE 65536 #define MAXWORDLEN 100 -#define MAXWORDUTF8LEN (MAXWORDLEN * 4) +#define MAXWORDUTF8LEN 256 // affentry options #define aeXPRODUCT (1 << 0) #define aeUTF8 (1 << 1) #define aeALIASF (1 << 2) #define aeALIASM (1 << 3) -#define aeINFIX (1 << 4) +#define aeLONGCOND (1 << 4) // compound options #define IN_CPD_NOT 0 @@ -33,10 +35,21 @@ #define IN_CPD_END 2 #define IN_CPD_OTHER 3 -#define MAXLNLEN 8192 * 4 +// info options +#define SPELL_COMPOUND (1 << 0) +#define SPELL_FORBIDDEN (1 << 1) +#define SPELL_ALLCAP (1 << 2) +#define SPELL_NOCAP (1 << 3) +#define SPELL_INITCAP (1 << 4) +#define SPELL_ORIGCAP (1 << 5) +#define SPELL_WARN (1 << 6) + +#define MAXLNLEN 8192 #define MINCPDLEN 3 #define MAXCOMPOUND 10 +#define MAXCONDLEN 20 +#define MAXCONDLEN_1 (MAXCONDLEN - sizeof(char *)) #define MAXACC 1000 @@ -55,31 +68,26 @@ struct affentry char numconds; char opts; unsigned short aflag; - union { - char base[SETSIZE]; - struct { - char ascii[SETSIZE/2]; - char neg[8]; - char all[8]; - w_char * wchars[8]; - int wlen[8]; - } utf8; - } conds; -#ifdef HUNSPELL_EXPERIMENTAL - char * morphcode; -#endif unsigned short * contclass; short contclasslen; + union { + char conds[MAXCONDLEN]; + struct { + char conds1[MAXCONDLEN_1]; + char * conds2; + } l; + } c; + char * morphcode; }; -struct replentry { - char * pattern; - char * pattern2; +struct guessword { + char * word; + bool allow; + char * orig; }; struct mapentry { - char * set; - w_char * set_utf16; + char ** set; int len; }; @@ -88,14 +96,12 @@ struct flagentry { int len; }; -struct guessword { - char * word; - bool allow; +struct patentry { + char * pattern; + char * pattern2; + char * pattern3; + FLAG cond; + FLAG cond2; }; #endif - - - - - diff --git a/ext/hunspell/baseaffix.hxx b/ext/hunspell/baseaffix.hxx dissimilarity index 89% index d6a5cd672..ed64f3d84 100644 --- a/ext/hunspell/baseaffix.hxx +++ b/ext/hunspell/baseaffix.hxx @@ -1,31 +1,28 @@ -#ifndef _BASEAFF_HXX_ -#define _BASEAFF_HXX_ - -class AffEntry -{ -public: - -protected: - char * appnd; - char * strip; - unsigned char appndl; - unsigned char stripl; - char numconds; - char opts; - unsigned short aflag; - union { - char base[SETSIZE]; - struct { - char ascii[SETSIZE/2]; - char neg[8]; - char all[8]; - w_char * wchars[8]; - int wlen[8]; - } utf8; - } conds; - char * morphcode; - unsigned short * contclass; - short contclasslen; -}; - -#endif +#ifndef _BASEAFF_HXX_ +#define _BASEAFF_HXX_ + +#include "hunvisapi.h" + +class LIBHUNSPELL_DLL_EXPORTED AffEntry +{ +protected: + char * appnd; + char * strip; + unsigned char appndl; + unsigned char stripl; + char numconds; + char opts; + unsigned short aflag; + union { + char conds[MAXCONDLEN]; + struct { + char conds1[MAXCONDLEN_1]; + char * conds2; + } l; + } c; + char * morphcode; + unsigned short * contclass; + short contclasslen; +}; + +#endif diff --git a/ext/hunspell/config.h b/ext/hunspell/config.h index e69de29bb..fe4ddf7a1 100644 --- a/ext/hunspell/config.h +++ b/ext/hunspell/config.h @@ -0,0 +1,208 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP + systems. This function is required for `alloca.c' support on those systems. + */ +#define CRAY_STACKSEG_END 1 + +/* Define to 1 if using `alloca.c'. */ +#define C_ALLOCA 1 + +/* Define to 1 if translation of program messages to the user's native + language is requested. */ +#undef ENABLE_NLS + +/* Define to 1 if you have `alloca', as a function or macro. */ +#define HAVE_ALLOCA 1 + +/* Define to 1 if you have and it should be used (not on Ultrix). + */ +#define HAVE_ALLOCA_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARGZ_H 1 + +/* "Define if you have the header" */ +#undef HAVE_CURSES_H + +/* Define if the GNU dcgettext() function is already present or preinstalled. + */ +#define HAVE_DCGETTEXT 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ERROR_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `feof_unlocked' function. */ +#define HAVE_FEOF_UNLOCKED 1 + +/* Define to 1 if you have the `fgets_unlocked' function. */ +#define HAVE_FGETS_UNLOCKED 1 + +/* Define to 1 if you have the `getcwd' function. */ +#define HAVE_GETCWD 1 + +/* Define to 1 if you have the `getc_unlocked' function. */ +#define HAVE_GETC_UNLOCKED 1 + +/* Define to 1 if you have the `getegid' function. */ +#define HAVE_GETEGID 1 + +/* Define to 1 if you have the `geteuid' function. */ +#define HAVE_GETEUID 1 + +/* Define to 1 if you have the `getgid' function. */ +#define HAVE_GETGID 1 + +/* Define to 1 if you have the `getpagesize' function. */ +#define HAVE_GETPAGESIZE 1 + +/* Define if the GNU gettext() function is already present or preinstalled. */ +#define HAVE_GETTEXT 1 + +/* Define to 1 if you have the `getuid' function. */ +#define HAVE_GETUID 1 + +/* Define if you have the iconv() function. */ +#undef HAVE_ICONV + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define if you have and nl_langinfo(CODESET). */ +#define HAVE_LANGINFO_CODESET 1 + +/* Define if your file defines LC_MESSAGES. */ +#define HAVE_LC_MESSAGES 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LIBINTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define to 1 if you have the `memchr' function. */ +#define HAVE_MEMCHR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mempcpy' function. */ +#define HAVE_MEMPCPY 1 + +/* Define to 1 if you have a working `mmap' system call. */ +#define HAVE_MMAP 1 + +/* Define to 1 if you have the `munmap' function. */ +#define HAVE_MUNMAP 1 + +/* "Define if you have the header" */ +#define HAVE_NCURSESW_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NL_TYPES_H 1 + +/* Define to 1 if you have the `putenv' function. */ +#define HAVE_PUTENV 1 + +/* "Define if you have fancy command input editing with Readline" */ +#undef HAVE_READLINE + +/* Define to 1 if you have the `setenv' function. */ +#define HAVE_SETENV 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDDEF_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `stpcpy' function. */ +#define HAVE_STPCPY 1 + +/* Define to 1 if you have the `strcasecmp' function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the `strchr' function. */ +#define HAVE_STRCHR 1 + +/* Define to 1 if you have the `strdup' function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strstr' function. */ +#define HAVE_STRSTR 1 + +/* Define to 1 if you have the `strtoul' function. */ +#define HAVE_STRTOUL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the `tsearch' function. */ +#define HAVE_TSEARCH 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `__argz_count' function. */ +#define HAVE___ARGZ_COUNT 1 + +/* Define to 1 if you have the `__argz_next' function. */ +#define HAVE___ARGZ_NEXT 1 + +/* Define to 1 if you have the `__argz_stringify' function. */ +#define HAVE___ARGZ_STRINGIFY 1 + +/* "Define if you use exterimental functions" */ +#undef HUNSPELL_EXPERIMENTAL + +/* "Define if you need warning messages" */ +#define HUNSPELL_WARNING_ON + +/* Define as const if the declaration of iconv() needs const. */ +#define ICONV_CONST 1 + +/* Name of package */ +#define PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#define PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.3.2" +#define VERSION "1.3.2" diff --git a/ext/hunspell/csutil.cxx b/ext/hunspell/csutil.cxx index 1100851b4..e7c0ac6e4 100644 --- a/ext/hunspell/csutil.cxx +++ b/ext/hunspell/csutil.cxx @@ -1,20 +1,22 @@ #include "license.hunspell" #include "license.myspell" -#ifndef MOZILLA_CLIENT -#include -#include -#include -#else #include #include #include -#endif +#include #include "csutil.hxx" #include "atypes.hxx" #include "langnum.hxx" +// Unicode character encoding information +struct unicode_info { + unsigned short c; + unsigned short cupper; + unsigned short clower; +}; + #ifdef OPENOFFICEORG # include #else @@ -29,31 +31,25 @@ #include "nsServiceManagerUtils.h" #include "nsIUnicodeEncoder.h" #include "nsIUnicodeDecoder.h" -#include "nsICaseConversion.h" -#include "nsICharsetConverterManager.h" -#include "nsUnicharUtilCIID.h" #include "nsUnicharUtils.h" +#include "nsICharsetConverterManager.h" static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID); -static NS_DEFINE_CID(kUnicharUtilCID, NS_UNICHARUTIL_CID); #endif -#ifdef MOZILLA_CLIENT -#ifdef __SUNPRO_CC // for SunONE Studio compiler -using namespace std; -#endif -#else -#ifndef W32 -using namespace std; -#endif -#endif +struct unicode_info2 { + char cletter; + unsigned short cupper; + unsigned short clower; +}; -struct unicode_info2 * utf_tbl = NULL; +static struct unicode_info2 * utf_tbl = NULL; +static int utf_tbl_count = 0; // utf_tbl can be used by multiple Hunspell instances /* only UTF-16 (BMP) implementation */ char * u16_u8(char * dest, int size, const w_char * src, int srclen) { - char * u8 = dest; - char * u8_max = u8 + size; + signed char * u8 = (signed char *)dest; + signed char * u8_max = (signed char *)(u8 + size); const w_char * u2 = src; const w_char * u2_max = src + srclen; while ((u2 < u2_max) && (u8 < u8_max)) { @@ -100,11 +96,11 @@ char * u16_u8(char * dest, int size, const w_char * src, int srclen) { /* only UTF-16 (BMP) implementation */ int u8_u16(w_char * dest, int size, const char * src) { - const char * u8 = src; + const signed char * u8 = (const signed char *)src; w_char * u2 = dest; w_char * u2_max = u2 + size; - while (*u8 && (u2 < u2_max)) { + while ((u2 < u2_max) && *u8) { switch ((*u8) & 0xf0) { case 0x00: case 0x10: @@ -122,7 +118,7 @@ int u8_u16(w_char * dest, int size, const char * src) { case 0x90: case 0xa0: case 0xb0: { - HUNSPELL_WARNING(stderr, "UTF-8 encoding error. Unexpected continuation bytes in %d. character position\n%s\n", u8 - src, src); + HUNSPELL_WARNING(stderr, "UTF-8 encoding error. Unexpected continuation bytes in %ld. character position\n%s\n", static_cast(u8 - (signed char *)src), src); u2->h = 0xff; u2->l = 0xfd; break; @@ -134,7 +130,7 @@ int u8_u16(w_char * dest, int size, const char * src) { u2->l = (*u8 << 6) + (*(u8+1) & 0x3f); u8++; } else { - HUNSPELL_WARNING(stderr, "UTF-8 encoding error. Missing continuation byte in %d. character position:\n%s\n", u8 - src, src); + HUNSPELL_WARNING(stderr, "UTF-8 encoding error. Missing continuation byte in %ld. character position:\n%s\n", static_cast(u8 - (signed char *)src), src); u2->h = 0xff; u2->l = 0xfd; } @@ -148,12 +144,12 @@ int u8_u16(w_char * dest, int size, const char * src) { u2->l = (*u8 << 6) + (*(u8+1) & 0x3f); u8++; } else { - HUNSPELL_WARNING(stderr, "UTF-8 encoding error. Missing continuation byte in %d. character position:\n%s\n", u8 - src, src); + HUNSPELL_WARNING(stderr, "UTF-8 encoding error. Missing continuation byte in %ld. character position:\n%s\n", static_cast(u8 - (signed char *)src), src); u2->h = 0xff; u2->l = 0xfd; } } else { - HUNSPELL_WARNING(stderr, "UTF-8 encoding error. Missing continuation byte in %d. character position:\n%s\n", u8 - src, src); + HUNSPELL_WARNING(stderr, "UTF-8 encoding error. Missing continuation byte in %ld. character position:\n%s\n", static_cast(u8 - (signed char *)src), src); u2->h = 0xff; u2->l = 0xfd; } @@ -169,7 +165,7 @@ int u8_u16(w_char * dest, int size, const char * src) { u8++; u2++; } - return u2 - dest; + return (int)(u2 - dest); } void flag_qsort(unsigned short flags[], int begin, int end) { @@ -218,13 +214,11 @@ int flag_bsearch(unsigned short flags[], unsigned short flag, int length) { char * mystrsep(char ** stringp, const char delim) { - char * rv = NULL; char * mp = *stringp; - int n = strlen(mp); - if (n > 0) { + if (*mp != '\0') { char * dp; if (delim) { - dp = (char *)memchr(mp,(int)((unsigned char)delim),n); + dp = strchr(mp, delim); } else { // don't use isspace() here, the string can be in some random charset // that's way different than the locale's @@ -233,40 +227,47 @@ int flag_bsearch(unsigned short flags[], unsigned short flag, int length) { } if (dp) { *stringp = dp+1; - int nc = (int)((unsigned long)dp - (unsigned long)mp); - rv = (char *) malloc(nc+1); - memcpy(rv,mp,nc); - *(rv+nc) = '\0'; - return rv; + *dp = '\0'; } else { - rv = (char *) malloc(n+1); - memcpy(rv, mp, n); - *(rv+n) = '\0'; - *stringp = mp + n; - return rv; + *stringp = mp + strlen(mp); } + return mp; } return NULL; } - // replaces strdup with ansi version char * mystrdup(const char * s) { char * d = NULL; if (s) { - int sl = strlen(s); - d = (char *) malloc(((sl+1) * sizeof(char))); - if (d) memcpy(d,s,((sl+1)*sizeof(char))); + size_t sl = strlen(s)+1; + d = (char *) malloc(sl); + if (d) { + memcpy(d,s,sl); + } else { + HUNSPELL_WARNING(stderr, "Can't allocate memory.\n"); + } } return d; } - - + + // strcat for limited length destination string + char * mystrcat(char * dest, const char * st, int max) { + int len; + int len2; + if (dest == NULL || st == NULL) return dest; + len = strlen(dest); + len2 = strlen(st); + if (len + len2 + 1 > max) return dest; + strcpy(dest + len, st); + return dest; + } + // remove cross-platform text line end characters void mychomp(char * s) { - int k = strlen(s); + size_t k = strlen(s); if ((k > 0) && ((*(s+k-1)=='\r') || (*(s+k-1)=='\n'))) *(s+k-1) = '\0'; if ((k > 1) && (*(s+k-2) == '\r')) *(s+k-2) = '\0'; } @@ -277,130 +278,280 @@ int flag_bsearch(unsigned short flags[], unsigned short flag, int length) { { char * d = NULL; if (s) { - int sl = strlen(s); - d = (char *) malloc((sl+1) * sizeof(char)); + size_t sl = strlen(s); + d = (char *) malloc(sl+1); if (d) { const char * p = s + sl - 1; char * q = d; while (p >= s) *q++ = *p--; *q = '\0'; + } else { + HUNSPELL_WARNING(stderr, "Can't allocate memory.\n"); } } return d; } -#ifdef HUNSPELL_EXPERIMENTAL - // append s to ends of every lines in text - void strlinecat(char * dest, const char * s) - { - char * dup = mystrdup(dest); - char * source = dup; - int len = strlen(s); - while (*source) { - if (*source == '\n') { - strncpy(dest, s, len); - dest += len; - } - *dest = *source; - source++; dest++; - } - strcpy(dest, s); - free(dup); - } - // break text to lines // return number of lines -int line_tok(const char * text, char *** lines) { +int line_tok(const char * text, char *** lines, char breakchar) { int linenum = 0; + if (!text) { + return linenum; + } char * dup = mystrdup(text); - char * p = strchr(dup, '\n'); + char * p = strchr(dup, breakchar); while (p) { linenum++; *p = '\0'; p++; - p = strchr(p, '\n'); + p = strchr(p, breakchar); + } + linenum++; + *lines = (char **) malloc(linenum * sizeof(char *)); + if (!(*lines)) { + free(dup); + return 0; } - *lines = (char **) calloc(linenum + 1, sizeof(char *)); - if (!(*lines)) return -1; - p = dup; - for (int i = 0; i < linenum + 1; i++) { - (*lines)[i] = mystrdup(p); + p = dup; + int l = 0; + for (int i = 0; i < linenum; i++) { + if (*p != '\0') { + (*lines)[l] = mystrdup(p); + if (!(*lines)[l]) { + for (i = 0; i < l; i++) free((*lines)[i]); + free(dup); + return 0; + } + l++; + } p += strlen(p) + 1; } free(dup); - return linenum; + if (!l) free(*lines); + return l; } // uniq line in place -char * line_uniq(char * text) { +char * line_uniq(char * text, char breakchar) { char ** lines; - int linenum = line_tok(text, &lines); + int linenum = line_tok(text, &lines, breakchar); int i; strcpy(text, lines[0]); - for ( i = 1; i<=linenum; i++ ) { + for ( i = 1; i < linenum; i++ ) { int dup = 0; for (int j = 0; j < i; j++) { if (strcmp(lines[i], lines[j]) == 0) dup = 1; } if (!dup) { - if ((i > 1) || (*(lines[0]) != '\0')) strcat(text, "\n"); + if ((i > 1) || (*(lines[0]) != '\0')) { + sprintf(text + strlen(text), "%c", breakchar); + } strcat(text, lines[i]); } } - for ( i = 0; i<=linenum; i++ ) { + for ( i = 0; i < linenum; i++ ) { if (lines[i]) free(lines[i]); } if (lines) free(lines); return text; } +// uniq and boundary for compound analysis: "1\n\2\n\1" -> " ( \1 | \2 ) " +char * line_uniq_app(char ** text, char breakchar) { + if (!strchr(*text, breakchar)) { + return *text; + } + + char ** lines; + int i; + int linenum = line_tok(*text, &lines, breakchar); + int dup = 0; + for (i = 0; i < linenum; i++) { + for (int j = 0; j < (i - 1); j++) { + if (strcmp(lines[i], lines[j]) == 0) { + *(lines[i]) = '\0'; + dup++; + break; + } + } + } + if ((linenum - dup) == 1) { + strcpy(*text, lines[0]); + freelist(&lines, linenum); + return *text; + } + char * newtext = (char *) malloc(strlen(*text) + 2 * linenum + 3 + 1); + if (newtext) { + free(*text); + *text = newtext; + } else { + freelist(&lines, linenum); + return *text; + } + strcpy(*text," ( "); + for (i = 0; i < linenum; i++) if (*(lines[i])) { + sprintf(*text + strlen(*text), "%s%s", lines[i], " | "); + } + (*text)[strlen(*text) - 2] = ')'; // " ) " + freelist(&lines, linenum); + return *text; +} + + // append s to ends of every lines in text + void strlinecat(char * dest, const char * s) + { + char * dup = mystrdup(dest); + char * source = dup; + int len = strlen(s); + if (dup) { + while (*source) { + if (*source == '\n') { + strncpy(dest, s, len); + dest += len; + } + *dest = *source; + source++; dest++; + } + strcpy(dest, s); + free(dup); + } + } + // change \n to char c -char * line_join(char * text, char c) { +char * tr(char * text, char oldc, char newc) { char * p; - for (p = text; *p; p++) if (*p == '\n') *p = c; + for (p = text; *p; p++) if (*p == oldc) *p = newc; return text; } -// leave only last {[^}]*} substring for handling zero morphemes -char * delete_zeros(char * morphout) { - char * p = morphout; - char * q = p; - char * q2 = NULL; - int suffix = 0; - - for (;*p && *(p+1);) { - switch (*p) { - case '{': - q2 = q; - q--; - break; - case '}': - if (q2) { - suffix = 1; - q--; - } - break; - default: - if (suffix) { - q = q2; - } - suffix = 0; - *q = *p; +// morphcmp(): compare MORPH_DERI_SFX, MORPH_INFL_SFX and MORPH_TERM_SFX fields +// in the first line of the inputs +// return 0, if inputs equal +// return 1, if inputs may equal with a secondary suffix +// otherwise return -1 +int morphcmp(const char * s, const char * t) +{ + int se = 0; + int te = 0; + const char * sl; + const char * tl; + const char * olds; + const char * oldt; + if (!s || !t) return 1; + olds = s; + sl = strchr(s, '\n'); + s = strstr(s, MORPH_DERI_SFX); + if (!s || (sl && sl < s)) s = strstr(olds, MORPH_INFL_SFX); + if (!s || (sl && sl < s)) { + s= strstr(olds, MORPH_TERM_SFX); + olds = NULL; + } + oldt = t; + tl = strchr(t, '\n'); + t = strstr(t, MORPH_DERI_SFX); + if (!t || (tl && tl < t)) t = strstr(oldt, MORPH_INFL_SFX); + if (!t || (tl && tl < t)) { + t = strstr(oldt, MORPH_TERM_SFX); + oldt = NULL; + } + while (s && t && (!sl || sl > s) && (!tl || tl > t)) { + s += MORPH_TAG_LEN; + t += MORPH_TAG_LEN; + se = 0; + te = 0; + while ((*s == *t) && !se && !te) { + s++; + t++; + switch(*s) { + case ' ': + case '\n': + case '\t': + case '\0': se = 1; + } + switch(*t) { + case ' ': + case '\n': + case '\t': + case '\0': te = 1; + } + } + if (!se || !te) { + // not terminal suffix difference + if (olds) return -1; + return 1; + } + olds = s; + s = strstr(s, MORPH_DERI_SFX); + if (!s || (sl && sl < s)) s = strstr(olds, MORPH_INFL_SFX); + if (!s || (sl && sl < s)) { + s = strstr(olds, MORPH_TERM_SFX); + olds = NULL; + } + oldt = t; + t = strstr(t, MORPH_DERI_SFX); + if (!t || (tl && tl < t)) t = strstr(oldt, MORPH_INFL_SFX); + if (!t || (tl && tl < t)) { + t = strstr(oldt, MORPH_TERM_SFX); + oldt = NULL; } - p++; - q++; } - *q = '\0'; - return morphout; + if (!s && !t && se && te) return 0; + return 1; +} + +int get_sfxcount(const char * morph) +{ + if (!morph || !*morph) return 0; + int n = 0; + const char * old = morph; + morph = strstr(morph, MORPH_DERI_SFX); + if (!morph) morph = strstr(old, MORPH_INFL_SFX); + if (!morph) morph = strstr(old, MORPH_TERM_SFX); + while (morph) { + n++; + old = morph; + morph = strstr(morph + 1, MORPH_DERI_SFX); + if (!morph) morph = strstr(old + 1, MORPH_INFL_SFX); + if (!morph) morph = strstr(old + 1, MORPH_TERM_SFX); + } + return n; +} + + +int fieldlen(const char * r) +{ + int n = 0; + while (r && *r != ' ' && *r != '\t' && *r != '\0' && *r != '\n') { + r++; + n++; + } + return n; +} + +char * copy_field(char * dest, const char * morph, const char * var) +{ + if (!morph) return NULL; + const char * beg = strstr(morph, var); + if (beg) { + char * d = dest; + for (beg += MORPH_TAG_LEN; *beg != ' ' && *beg != '\t' && + *beg != '\n' && *beg != '\0'; d++, beg++) { + *d = *beg; + } + *d = '\0'; + return dest; + } + return NULL; } -#endif // END OF HUNSPELL_EXPERIMENTAL CODE char * mystrrep(char * word, const char * pat, const char * rep) { char * pos = strstr(word, pat); if (pos) { - int replen = strlen(rep); - int patlen = strlen(pat); + int replen = strlen(rep); + int patlen = strlen(pat); + while (pos) { if (replen < patlen) { char * end = word + strlen(word); char * next = pos + replen; @@ -414,6 +565,8 @@ char * mystrrep(char * word, const char * pat, const char * rep) { for (; prev >= end; *next = *prev, prev--, next--); } strncpy(pos, rep, replen); + pos = strstr(word, pat); + } } return word; } @@ -445,6 +598,34 @@ char * mystrrep(char * word, const char * pat, const char * rep) { u16_u8(word, MAXWORDUTF8LEN, w, l); return 0; } + + int uniqlist(char ** list, int n) { + int i; + if (n < 2) return n; + for (i = 0; i < n; i++) { + for (int j = 0; j < i; j++) { + if (list[j] && list[i] && (strcmp(list[j], list[i]) == 0)) { + free(list[i]); + list[i] = NULL; + break; + } + } + } + int m = 1; + for (i = 1; i < n; i++) if (list[i]) { + list[m] = list[i]; + m++; + } + return m; + } + + void freelist(char *** list, int n) { + if (list && *list && n > 0) { + for (int i = 0; i < n; i++) if ((*list)[i]) free((*list)[i]); + free(*list); + *list = NULL; + } + } // convert null terminated string to all caps void mkallcap(char * p, const struct cs_info * csconv) @@ -478,18 +659,32 @@ void mkallcap_utf(w_char * u, int nc, int langnum) { for (int i = 0; i < nc; i++) { unsigned short idx = (u[i].h << 8) + u[i].l; if (idx != unicodetoupper(idx, langnum)) { - u[i].h = (unsigned char) (unicodetolower(idx, langnum) >> 8); - u[i].l = (unsigned char) (unicodetolower(idx, langnum) & 0x00FF); + u[i].h = (unsigned char) (unicodetoupper(idx, langnum) >> 8); + u[i].l = (unsigned char) (unicodetoupper(idx, langnum) & 0x00FF); } } } - // convert null terminated string to have intial capital + // convert null terminated string to have initial capital void mkinitcap(char * p, const struct cs_info * csconv) { if (*p != '\0') *p = csconv[((unsigned char)*p)].cupper; } + // conversion function for protected memory + void store_pointer(char * dest, char * source) + { + memcpy(dest, &source, sizeof(char *)); + } + + // conversion function for protected memory + char * get_stored_pointer(const char * s) + { + char * p; + memcpy(&p, s, sizeof(char *)); + return p; + } + #ifndef MOZILLA_CLIENT // convert null terminated string to all caps using encoding void enmkallcap(char * d, const char * p, const char * encoding) @@ -514,7 +709,7 @@ void mkallcap_utf(w_char * u, int nc, int langnum) { *d = '\0'; } - // convert null terminated string to have intial capital using encoding + // convert null terminated string to have initial capital using encoding void enmkinitcap(char * d, const char * p, const char * encoding) { struct cs_info * csconv = get_current_cs(encoding); @@ -526,7 +721,7 @@ void mkallcap_utf(w_char * u, int nc, int langnum) { // encodings supported // supplying isupper, tolower, and toupper -struct cs_info iso1_tbl[] = { +static struct cs_info iso1_tbl[] = { { 0x00, 0x00, 0x00 }, { 0x00, 0x01, 0x01 }, { 0x00, 0x02, 0x02 }, @@ -782,11 +977,11 @@ struct cs_info iso1_tbl[] = { { 0x00, 0xfc, 0xdc }, { 0x00, 0xfd, 0xdd }, { 0x00, 0xfe, 0xde }, -{ 0x00, 0xff, 0xff }, +{ 0x00, 0xff, 0xff } }; -struct cs_info iso2_tbl[] = { +static struct cs_info iso2_tbl[] = { { 0x00, 0x00, 0x00 }, { 0x00, 0x01, 0x01 }, { 0x00, 0x02, 0x02 }, @@ -1042,11 +1237,11 @@ struct cs_info iso2_tbl[] = { { 0x00, 0xfc, 0xdc }, { 0x00, 0xfd, 0xdd }, { 0x00, 0xfe, 0xde }, -{ 0x00, 0xff, 0xff }, +{ 0x00, 0xff, 0xff } }; -struct cs_info iso3_tbl[] = { +static struct cs_info iso3_tbl[] = { { 0x00, 0x00, 0x00 }, { 0x00, 0x01, 0x01 }, { 0x00, 0x02, 0x02 }, @@ -1302,10 +1497,10 @@ struct cs_info iso3_tbl[] = { { 0x00, 0xfc, 0xdc }, { 0x00, 0xfd, 0xdd }, { 0x00, 0xfe, 0xde }, -{ 0x00, 0xff, 0xff }, +{ 0x00, 0xff, 0xff } }; -struct cs_info iso4_tbl[] = { +static struct cs_info iso4_tbl[] = { { 0x00, 0x00, 0x00 }, { 0x00, 0x01, 0x01 }, { 0x00, 0x02, 0x02 }, @@ -1561,10 +1756,10 @@ struct cs_info iso4_tbl[] = { { 0x00, 0xfc, 0xdc }, { 0x00, 0xfd, 0xdd }, { 0x00, 0xfe, 0xde }, -{ 0x00, 0xff, 0xff }, +{ 0x00, 0xff, 0xff } }; -struct cs_info iso5_tbl[] = { +static struct cs_info iso5_tbl[] = { { 0x00, 0x00, 0x00 }, { 0x00, 0x01, 0x01 }, { 0x00, 0x02, 0x02 }, @@ -1820,10 +2015,10 @@ struct cs_info iso5_tbl[] = { { 0x00, 0xfc, 0xac }, { 0x00, 0xfd, 0xfd }, { 0x00, 0xfe, 0xae }, -{ 0x00, 0xff, 0xaf }, +{ 0x00, 0xff, 0xaf } }; -struct cs_info iso6_tbl[] = { +static struct cs_info iso6_tbl[] = { { 0x00, 0x00, 0x00 }, { 0x00, 0x01, 0x01 }, { 0x00, 0x02, 0x02 }, @@ -2079,10 +2274,10 @@ struct cs_info iso6_tbl[] = { { 0x00, 0xfc, 0xfc }, { 0x00, 0xfd, 0xfd }, { 0x00, 0xfe, 0xfe }, -{ 0x00, 0xff, 0xff }, +{ 0x00, 0xff, 0xff } }; -struct cs_info iso7_tbl[] = { +static struct cs_info iso7_tbl[] = { { 0x00, 0x00, 0x00 }, { 0x00, 0x01, 0x01 }, { 0x00, 0x02, 0x02 }, @@ -2338,10 +2533,10 @@ struct cs_info iso7_tbl[] = { { 0x00, 0xfc, 0xbc }, { 0x00, 0xfd, 0xbe }, { 0x00, 0xfe, 0xbf }, -{ 0x00, 0xff, 0xff }, +{ 0x00, 0xff, 0xff } }; -struct cs_info iso8_tbl[] = { +static struct cs_info iso8_tbl[] = { { 0x00, 0x00, 0x00 }, { 0x00, 0x01, 0x01 }, { 0x00, 0x02, 0x02 }, @@ -2597,10 +2792,10 @@ struct cs_info iso8_tbl[] = { { 0x00, 0xfc, 0xfc }, { 0x00, 0xfd, 0xfd }, { 0x00, 0xfe, 0xfe }, -{ 0x00, 0xff, 0xff }, +{ 0x00, 0xff, 0xff } }; -struct cs_info iso9_tbl[] = { +static struct cs_info iso9_tbl[] = { { 0x00, 0x00, 0x00 }, { 0x00, 0x01, 0x01 }, { 0x00, 0x02, 0x02 }, @@ -2856,10 +3051,10 @@ struct cs_info iso9_tbl[] = { { 0x00, 0xfc, 0xdc }, { 0x00, 0xfd, 0x49 }, { 0x00, 0xfe, 0xde }, -{ 0x00, 0xff, 0xff }, +{ 0x00, 0xff, 0xff } }; -struct cs_info iso10_tbl[] = { +static struct cs_info iso10_tbl[] = { { 0x00, 0x00, 0x00 }, { 0x00, 0x01, 0x01 }, { 0x00, 0x02, 0x02 }, @@ -3115,10 +3310,10 @@ struct cs_info iso10_tbl[] = { { 0x00, 0xfc, 0xfc }, { 0x00, 0xfd, 0xfd }, { 0x00, 0xfe, 0xfe }, -{ 0x00, 0xff, 0xff }, +{ 0x00, 0xff, 0xff } }; -struct cs_info koi8r_tbl[] = { +static struct cs_info koi8r_tbl[] = { { 0x00, 0x00, 0x00 }, { 0x00, 0x01, 0x01 }, { 0x00, 0x02, 0x02 }, @@ -3374,10 +3569,10 @@ struct cs_info koi8r_tbl[] = { { 0x01, 0xdc, 0xfc }, { 0x01, 0xdd, 0xfd }, { 0x01, 0xde, 0xfe }, -{ 0x01, 0xdf, 0xff }, +{ 0x01, 0xdf, 0xff } }; -struct cs_info koi8u_tbl[] = { +static struct cs_info koi8u_tbl[] = { { 0x00, 0x00, 0x00 }, { 0x00, 0x01, 0x01 }, { 0x00, 0x02, 0x02 }, @@ -3633,10 +3828,10 @@ struct cs_info koi8u_tbl[] = { { 0x01, 0xdc, 0xfc }, { 0x01, 0xdd, 0xfd }, { 0x01, 0xde, 0xfe }, -{ 0x01, 0xdf, 0xff }, +{ 0x01, 0xdf, 0xff } }; -struct cs_info cp1251_tbl[] = { +static struct cs_info cp1251_tbl[] = { { 0x00, 0x00, 0x00 }, { 0x00, 0x01, 0x01 }, { 0x00, 0x02, 0x02 }, @@ -3892,10 +4087,10 @@ struct cs_info cp1251_tbl[] = { { 0x00, 0xfc, 0xdc }, { 0x00, 0xfd, 0xdd }, { 0x00, 0xfe, 0xde }, -{ 0x00, 0xff, 0xdf }, +{ 0x00, 0xff, 0xdf } }; -struct cs_info iso13_tbl[] = { +static struct cs_info iso13_tbl[] = { { 0x00, 0x00, 0x00 }, { 0x00, 0x01, 0x01 }, { 0x00, 0x02, 0x02 }, @@ -4151,11 +4346,11 @@ struct cs_info iso13_tbl[] = { { 0x00, 0xFC, 0xDC }, { 0x00, 0xFD, 0xDD }, { 0x00, 0xFE, 0xDE }, -{ 0x00, 0xFF, 0xFF }, +{ 0x00, 0xFF, 0xFF } }; -struct cs_info iso14_tbl[] = { +static struct cs_info iso14_tbl[] = { { 0x00, 0x00, 0x00 }, { 0x00, 0x01, 0x01 }, { 0x00, 0x02, 0x02 }, @@ -4411,10 +4606,10 @@ struct cs_info iso14_tbl[] = { { 0x00, 0xfc, 0xdc }, { 0x00, 0xfd, 0xdd }, { 0x00, 0xfe, 0xde }, -{ 0x00, 0xff, 0xff }, +{ 0x00, 0xff, 0xff } }; -struct cs_info iso15_tbl[] = { +static struct cs_info iso15_tbl[] = { { 0x00, 0x00, 0x00 }, { 0x00, 0x01, 0x01 }, { 0x00, 0x02, 0x02 }, @@ -4670,10 +4865,10 @@ struct cs_info iso15_tbl[] = { { 0x00, 0xfc, 0xdc }, { 0x00, 0xfd, 0xdd }, { 0x00, 0xfe, 0xde }, -{ 0x00, 0xff, 0xbe }, +{ 0x00, 0xff, 0xbe } }; -struct cs_info iscii_devanagari_tbl[] = { +static struct cs_info iscii_devanagari_tbl[] = { { 0x00, 0x00, 0x00 }, { 0x00, 0x01, 0x01 }, { 0x00, 0x02, 0x02 }, @@ -4929,37 +5124,343 @@ struct cs_info iscii_devanagari_tbl[] = { { 0x00, 0xfc, 0xfc }, { 0x00, 0xfd, 0xfd }, { 0x00, 0xfe, 0xfe }, -{ 0x00, 0xff, 0xff }, +{ 0x00, 0xff, 0xff } }; -struct enc_entry encds[] = { -{"ISO8859-1",iso1_tbl}, -{"ISO8859-2",iso2_tbl}, -{"ISO8859-3",iso3_tbl}, -{"ISO8859-4",iso4_tbl}, -{"ISO8859-5",iso5_tbl}, -{"ISO8859-6",iso6_tbl}, -{"ISO8859-7",iso7_tbl}, -{"ISO8859-8",iso8_tbl}, -{"ISO8859-9",iso9_tbl}, -{"ISO8859-10",iso10_tbl}, -{"KOI8-R",koi8r_tbl}, -{"KOI8-U",koi8u_tbl}, -{"microsoft-cp1251",cp1251_tbl}, -{"ISO8859-13", iso13_tbl}, -{"ISO8859-14", iso14_tbl}, -{"ISO8859-15", iso15_tbl}, -{"ISCII-DEVANAGARI", iscii_devanagari_tbl}, +static struct cs_info tis620_tbl[] = { +{ 0x00, 0x00, 0x00 }, +{ 0x00, 0x01, 0x01 }, +{ 0x00, 0x02, 0x02 }, +{ 0x00, 0x03, 0x03 }, +{ 0x00, 0x04, 0x04 }, +{ 0x00, 0x05, 0x05 }, +{ 0x00, 0x06, 0x06 }, +{ 0x00, 0x07, 0x07 }, +{ 0x00, 0x08, 0x08 }, +{ 0x00, 0x09, 0x09 }, +{ 0x00, 0x0a, 0x0a }, +{ 0x00, 0x0b, 0x0b }, +{ 0x00, 0x0c, 0x0c }, +{ 0x00, 0x0d, 0x0d }, +{ 0x00, 0x0e, 0x0e }, +{ 0x00, 0x0f, 0x0f }, +{ 0x00, 0x10, 0x10 }, +{ 0x00, 0x11, 0x11 }, +{ 0x00, 0x12, 0x12 }, +{ 0x00, 0x13, 0x13 }, +{ 0x00, 0x14, 0x14 }, +{ 0x00, 0x15, 0x15 }, +{ 0x00, 0x16, 0x16 }, +{ 0x00, 0x17, 0x17 }, +{ 0x00, 0x18, 0x18 }, +{ 0x00, 0x19, 0x19 }, +{ 0x00, 0x1a, 0x1a }, +{ 0x00, 0x1b, 0x1b }, +{ 0x00, 0x1c, 0x1c }, +{ 0x00, 0x1d, 0x1d }, +{ 0x00, 0x1e, 0x1e }, +{ 0x00, 0x1f, 0x1f }, +{ 0x00, 0x20, 0x20 }, +{ 0x00, 0x21, 0x21 }, +{ 0x00, 0x22, 0x22 }, +{ 0x00, 0x23, 0x23 }, +{ 0x00, 0x24, 0x24 }, +{ 0x00, 0x25, 0x25 }, +{ 0x00, 0x26, 0x26 }, +{ 0x00, 0x27, 0x27 }, +{ 0x00, 0x28, 0x28 }, +{ 0x00, 0x29, 0x29 }, +{ 0x00, 0x2a, 0x2a }, +{ 0x00, 0x2b, 0x2b }, +{ 0x00, 0x2c, 0x2c }, +{ 0x00, 0x2d, 0x2d }, +{ 0x00, 0x2e, 0x2e }, +{ 0x00, 0x2f, 0x2f }, +{ 0x00, 0x30, 0x30 }, +{ 0x00, 0x31, 0x31 }, +{ 0x00, 0x32, 0x32 }, +{ 0x00, 0x33, 0x33 }, +{ 0x00, 0x34, 0x34 }, +{ 0x00, 0x35, 0x35 }, +{ 0x00, 0x36, 0x36 }, +{ 0x00, 0x37, 0x37 }, +{ 0x00, 0x38, 0x38 }, +{ 0x00, 0x39, 0x39 }, +{ 0x00, 0x3a, 0x3a }, +{ 0x00, 0x3b, 0x3b }, +{ 0x00, 0x3c, 0x3c }, +{ 0x00, 0x3d, 0x3d }, +{ 0x00, 0x3e, 0x3e }, +{ 0x00, 0x3f, 0x3f }, +{ 0x00, 0x40, 0x40 }, +{ 0x01, 0x61, 0x41 }, +{ 0x01, 0x62, 0x42 }, +{ 0x01, 0x63, 0x43 }, +{ 0x01, 0x64, 0x44 }, +{ 0x01, 0x65, 0x45 }, +{ 0x01, 0x66, 0x46 }, +{ 0x01, 0x67, 0x47 }, +{ 0x01, 0x68, 0x48 }, +{ 0x01, 0x69, 0x49 }, +{ 0x01, 0x6a, 0x4a }, +{ 0x01, 0x6b, 0x4b }, +{ 0x01, 0x6c, 0x4c }, +{ 0x01, 0x6d, 0x4d }, +{ 0x01, 0x6e, 0x4e }, +{ 0x01, 0x6f, 0x4f }, +{ 0x01, 0x70, 0x50 }, +{ 0x01, 0x71, 0x51 }, +{ 0x01, 0x72, 0x52 }, +{ 0x01, 0x73, 0x53 }, +{ 0x01, 0x74, 0x54 }, +{ 0x01, 0x75, 0x55 }, +{ 0x01, 0x76, 0x56 }, +{ 0x01, 0x77, 0x57 }, +{ 0x01, 0x78, 0x58 }, +{ 0x01, 0x79, 0x59 }, +{ 0x01, 0x7a, 0x5a }, +{ 0x00, 0x5b, 0x5b }, +{ 0x00, 0x5c, 0x5c }, +{ 0x00, 0x5d, 0x5d }, +{ 0x00, 0x5e, 0x5e }, +{ 0x00, 0x5f, 0x5f }, +{ 0x00, 0x60, 0x60 }, +{ 0x00, 0x61, 0x41 }, +{ 0x00, 0x62, 0x42 }, +{ 0x00, 0x63, 0x43 }, +{ 0x00, 0x64, 0x44 }, +{ 0x00, 0x65, 0x45 }, +{ 0x00, 0x66, 0x46 }, +{ 0x00, 0x67, 0x47 }, +{ 0x00, 0x68, 0x48 }, +{ 0x00, 0x69, 0x49 }, +{ 0x00, 0x6a, 0x4a }, +{ 0x00, 0x6b, 0x4b }, +{ 0x00, 0x6c, 0x4c }, +{ 0x00, 0x6d, 0x4d }, +{ 0x00, 0x6e, 0x4e }, +{ 0x00, 0x6f, 0x4f }, +{ 0x00, 0x70, 0x50 }, +{ 0x00, 0x71, 0x51 }, +{ 0x00, 0x72, 0x52 }, +{ 0x00, 0x73, 0x53 }, +{ 0x00, 0x74, 0x54 }, +{ 0x00, 0x75, 0x55 }, +{ 0x00, 0x76, 0x56 }, +{ 0x00, 0x77, 0x57 }, +{ 0x00, 0x78, 0x58 }, +{ 0x00, 0x79, 0x59 }, +{ 0x00, 0x7a, 0x5a }, +{ 0x00, 0x7b, 0x7b }, +{ 0x00, 0x7c, 0x7c }, +{ 0x00, 0x7d, 0x7d }, +{ 0x00, 0x7e, 0x7e }, +{ 0x00, 0x7f, 0x7f }, +{ 0x00, 0x80, 0x80 }, +{ 0x00, 0x81, 0x81 }, +{ 0x00, 0x82, 0x82 }, +{ 0x00, 0x83, 0x83 }, +{ 0x00, 0x84, 0x84 }, +{ 0x00, 0x85, 0x85 }, +{ 0x00, 0x86, 0x86 }, +{ 0x00, 0x87, 0x87 }, +{ 0x00, 0x88, 0x88 }, +{ 0x00, 0x89, 0x89 }, +{ 0x00, 0x8a, 0x8a }, +{ 0x00, 0x8b, 0x8b }, +{ 0x00, 0x8c, 0x8c }, +{ 0x00, 0x8d, 0x8d }, +{ 0x00, 0x8e, 0x8e }, +{ 0x00, 0x8f, 0x8f }, +{ 0x00, 0x90, 0x90 }, +{ 0x00, 0x91, 0x91 }, +{ 0x00, 0x92, 0x92 }, +{ 0x00, 0x93, 0x93 }, +{ 0x00, 0x94, 0x94 }, +{ 0x00, 0x95, 0x95 }, +{ 0x00, 0x96, 0x96 }, +{ 0x00, 0x97, 0x97 }, +{ 0x00, 0x98, 0x98 }, +{ 0x00, 0x99, 0x99 }, +{ 0x00, 0x9a, 0x9a }, +{ 0x00, 0x9b, 0x9b }, +{ 0x00, 0x9c, 0x9c }, +{ 0x00, 0x9d, 0x9d }, +{ 0x00, 0x9e, 0x9e }, +{ 0x00, 0x9f, 0x9f }, +{ 0x00, 0xa0, 0xa0 }, +{ 0x00, 0xa1, 0xa1 }, +{ 0x00, 0xa2, 0xa2 }, +{ 0x00, 0xa3, 0xa3 }, +{ 0x00, 0xa4, 0xa4 }, +{ 0x00, 0xa5, 0xa5 }, +{ 0x00, 0xa6, 0xa6 }, +{ 0x00, 0xa7, 0xa7 }, +{ 0x00, 0xa8, 0xa8 }, +{ 0x00, 0xa9, 0xa9 }, +{ 0x00, 0xaa, 0xaa }, +{ 0x00, 0xab, 0xab }, +{ 0x00, 0xac, 0xac }, +{ 0x00, 0xad, 0xad }, +{ 0x00, 0xae, 0xae }, +{ 0x00, 0xaf, 0xaf }, +{ 0x00, 0xb0, 0xb0 }, +{ 0x00, 0xb1, 0xb1 }, +{ 0x00, 0xb2, 0xb2 }, +{ 0x00, 0xb3, 0xb3 }, +{ 0x00, 0xb4, 0xb4 }, +{ 0x00, 0xb5, 0xb5 }, +{ 0x00, 0xb6, 0xb6 }, +{ 0x00, 0xb7, 0xb7 }, +{ 0x00, 0xb8, 0xb8 }, +{ 0x00, 0xb9, 0xb9 }, +{ 0x00, 0xba, 0xba }, +{ 0x00, 0xbb, 0xbb }, +{ 0x00, 0xbc, 0xbc }, +{ 0x00, 0xbd, 0xbd }, +{ 0x00, 0xbe, 0xbe }, +{ 0x00, 0xbf, 0xbf }, +{ 0x00, 0xc0, 0xc0 }, +{ 0x00, 0xc1, 0xc1 }, +{ 0x00, 0xc2, 0xc2 }, +{ 0x00, 0xc3, 0xc3 }, +{ 0x00, 0xc4, 0xc4 }, +{ 0x00, 0xc5, 0xc5 }, +{ 0x00, 0xc6, 0xc6 }, +{ 0x00, 0xc7, 0xc7 }, +{ 0x00, 0xc8, 0xc8 }, +{ 0x00, 0xc9, 0xc9 }, +{ 0x00, 0xca, 0xca }, +{ 0x00, 0xcb, 0xcb }, +{ 0x00, 0xcc, 0xcc }, +{ 0x00, 0xcd, 0xcd }, +{ 0x00, 0xce, 0xce }, +{ 0x00, 0xcf, 0xcf }, +{ 0x00, 0xd0, 0xd0 }, +{ 0x00, 0xd1, 0xd1 }, +{ 0x00, 0xd2, 0xd2 }, +{ 0x00, 0xd3, 0xd3 }, +{ 0x00, 0xd4, 0xd4 }, +{ 0x00, 0xd5, 0xd5 }, +{ 0x00, 0xd6, 0xd6 }, +{ 0x00, 0xd7, 0xd7 }, +{ 0x00, 0xd8, 0xd8 }, +{ 0x00, 0xd9, 0xd9 }, +{ 0x00, 0xda, 0xda }, +{ 0x00, 0xdb, 0xdb }, +{ 0x00, 0xdc, 0xdc }, +{ 0x00, 0xdd, 0xdd }, +{ 0x00, 0xde, 0xde }, +{ 0x00, 0xdf, 0xdf }, +{ 0x00, 0xe0, 0xe0 }, +{ 0x00, 0xe1, 0xe1 }, +{ 0x00, 0xe2, 0xe2 }, +{ 0x00, 0xe3, 0xe3 }, +{ 0x00, 0xe4, 0xe4 }, +{ 0x00, 0xe5, 0xe5 }, +{ 0x00, 0xe6, 0xe6 }, +{ 0x00, 0xe7, 0xe7 }, +{ 0x00, 0xe8, 0xe8 }, +{ 0x00, 0xe9, 0xe9 }, +{ 0x00, 0xea, 0xea }, +{ 0x00, 0xeb, 0xeb }, +{ 0x00, 0xec, 0xec }, +{ 0x00, 0xed, 0xed }, +{ 0x00, 0xee, 0xee }, +{ 0x00, 0xef, 0xef }, +{ 0x00, 0xf0, 0xf0 }, +{ 0x00, 0xf1, 0xf1 }, +{ 0x00, 0xf2, 0xf2 }, +{ 0x00, 0xf3, 0xf3 }, +{ 0x00, 0xf4, 0xf4 }, +{ 0x00, 0xf5, 0xf5 }, +{ 0x00, 0xf6, 0xf6 }, +{ 0x00, 0xf7, 0xf7 }, +{ 0x00, 0xf8, 0xf8 }, +{ 0x00, 0xf9, 0xf9 }, +{ 0x00, 0xfa, 0xfa }, +{ 0x00, 0xfb, 0xfb }, +{ 0x00, 0xfc, 0xfc }, +{ 0x00, 0xfd, 0xfd }, +{ 0x00, 0xfe, 0xfe }, +{ 0x00, 0xff, 0xff } +}; + +struct enc_entry { + const char * enc_name; + struct cs_info * cs_table; }; +static struct enc_entry encds[] = { + {"iso88591",iso1_tbl}, //ISO-8859-1 + {"iso88592",iso2_tbl}, //ISO-8859-2 + {"iso88593",iso3_tbl}, //ISO-8859-3 + {"iso88594",iso4_tbl}, //ISO-8859-4 + {"iso88595",iso5_tbl}, //ISO-8859-5 + {"iso88596",iso6_tbl}, //ISO-8859-6 + {"iso88597",iso7_tbl}, //ISO-8859-7 + {"iso88598",iso8_tbl}, //ISO-8859-8 + {"iso88599",iso9_tbl}, //ISO-8859-9 + {"iso885910",iso10_tbl}, //ISO-8859-10 + {"tis620",tis620_tbl}, //TIS-620/ISO-8859-11 + {"tis6202533",tis620_tbl}, //TIS-620/ISO-8859-11 + {"iso885911",tis620_tbl}, //TIS-620/ISO-8859-11 + {"iso885913", iso13_tbl}, //ISO-8859-13 + {"iso885914", iso14_tbl}, //ISO-8859-14 + {"iso885915", iso15_tbl}, //ISO-8859-15 + {"koi8r",koi8r_tbl}, //KOI8-R + {"koi8u",koi8u_tbl}, //KOI8-U + {"cp1251",cp1251_tbl}, //CP-1251 + {"microsoftcp1251",cp1251_tbl}, //microsoft-cp1251 + {"xisciias", iscii_devanagari_tbl}, //x-iscii-as + {"isciidevanagari", iscii_devanagari_tbl} //ISCII-DEVANAGARI +}; + +/* map to lower case and remove non alphanumeric chars */ +static void toAsciiLowerAndRemoveNonAlphanumeric( const char* pName, char* pBuf ) +{ + while ( *pName ) + { + /* A-Z */ + if ( (*pName >= 0x41) && (*pName <= 0x5A) ) + { + *pBuf = (*pName)+0x20; /* toAsciiLower */ + pBuf++; + } + /* a-z, 0-9 */ + else if ( ((*pName >= 0x61) && (*pName <= 0x7A)) || + ((*pName >= 0x30) && (*pName <= 0x39)) ) + { + *pBuf = *pName; + pBuf++; + } + + pName++; + } + + *pBuf = '\0'; +} + struct cs_info * get_current_cs(const char * es) { - struct cs_info * ccs = encds[0].cs_table; + char *normalized_encoding = new char[strlen(es)+1]; + toAsciiLowerAndRemoveNonAlphanumeric(es, normalized_encoding); + + struct cs_info * ccs = NULL; int n = sizeof(encds) / sizeof(encds[0]); for (int i = 0; i < n; i++) { - if (strcmp(es,encds[i].enc_name) == 0) { + if (strcmp(normalized_encoding,encds[i].enc_name) == 0) { ccs = encds[i].cs_table; + break; } } + + delete[] normalized_encoding; + + if (!ccs) { + HUNSPELL_WARNING(stderr, "error: unknown encoding %s: using %s as fallback\n", es, encds[0].enc_name); + ccs = encds[0].cs_table; + } + return ccs; } #else @@ -4971,7 +5472,6 @@ struct cs_info * get_current_cs(const char * es) { nsCOMPtr encoder; nsCOMPtr decoder; - nsCOMPtr caseConv; nsresult rv; nsCOMPtr ccm = do_GetService(kCharsetConverterManagerCID, &rv); @@ -4979,108 +5479,134 @@ struct cs_info * get_current_cs(const char * es) { return nsnull; rv = ccm->GetUnicodeEncoder(es, getter_AddRefs(encoder)); - if (encoder && NS_SUCCEEDED(rv)) - encoder->SetOutputErrorBehavior(encoder->kOnError_Replace, nsnull, '?'); if (NS_FAILED(rv)) return nsnull; + encoder->SetOutputErrorBehavior(encoder->kOnError_Signal, nsnull, '?'); rv = ccm->GetUnicodeDecoder(es, getter_AddRefs(decoder)); + if (NS_FAILED(rv)) + return nsnull; + decoder->SetInputErrorBehavior(decoder->kOnError_Signal); - caseConv = do_GetService(kUnicharUtilCID, &rv); if (NS_FAILED(rv)) return nsnull; - ccs = (struct cs_info *) malloc(256 * sizeof(cs_info)); + ccs = new cs_info[256]; - PRInt32 charLength = 256; - PRInt32 uniLength = 512; - char *source = (char *)malloc(charLength * sizeof(char)); - PRUnichar *uni = (PRUnichar *)malloc(uniLength * sizeof(PRUnichar)); - char *lower = (char *)malloc(charLength * sizeof(char)); - char *upper = (char *)malloc(charLength * sizeof(char)); + for (unsigned int i = 0; i <= 0xff; ++i) { + PRBool success = PR_FALSE; + // We want to find the upper/lowercase equivalents of each byte + // in this 1-byte character encoding. Call our encoding/decoding + // APIs separately for each byte since they may reject some of the + // bytes, and we want to handle errors separately for each byte. + char lower, upper; + do { + if (i == 0) + break; + const char source = char(i); + PRUnichar uni, uniCased; + PRInt32 charLength = 1, uniLength = 1; - // Create a long string of all chars. - unsigned int i; - for (i = 0x00; i <= 0xff ; ++i) { - source[i] = i; - } + rv = decoder->Convert(&source, &charLength, &uni, &uniLength); + // Explicitly check NS_OK because we don't want to allow + // NS_OK_UDEC_MOREOUTPUT or NS_OK_UDEC_MOREINPUT. + if (rv != NS_OK || charLength != 1 || uniLength != 1) + break; + uniCased = ToLowerCase(uni); + rv = encoder->Convert(&uniCased, &uniLength, &lower, &charLength); + // Explicitly check NS_OK because we don't want to allow + // NS_OK_UDEC_MOREOUTPUT or NS_OK_UDEC_MOREINPUT. + if (rv != NS_OK || charLength != 1 || uniLength != 1) + break; - // Convert this long string to unicode - rv = decoder->Convert(source, &charLength, uni, &uniLength); + uniCased = ToUpperCase(uni); + rv = encoder->Convert(&uniCased, &uniLength, &upper, &charLength); + // Explicitly check NS_OK because we don't want to allow + // NS_OK_UDEC_MOREOUTPUT or NS_OK_UDEC_MOREINPUT. + if (rv != NS_OK || charLength != 1 || uniLength != 1) + break; - // Do case conversion stuff, and convert back. - caseConv->ToUpper(uni, uni, uniLength); - encoder->Convert(uni, &uniLength, upper, &charLength); + success = PR_TRUE; + } while (0); - uniLength = 512; - charLength = 256; - rv = decoder->Convert(source, &charLength, uni, &uniLength); - caseConv->ToLower(uni, uni, uniLength); - encoder->Convert(uni, &uniLength, lower, &charLength); + if (success) { + ccs[i].cupper = upper; + ccs[i].clower = lower; + } else { + ccs[i].cupper = i; + ccs[i].clower = i; + } - // Store - for (i = 0x00; i <= 0xff ; ++i) { - ccs[i].cupper = upper[i]; - ccs[i].clower = lower[i]; - if (ccs[i].clower != (unsigned char)i) ccs[i].ccase = true; else ccs[i].ccase = false; - } - free(source); - free(uni); - free(lower); - free(upper); - return ccs; } #endif -struct lang_map lang2enc[] = { -{"ar", "UTF-8", LANG_ar}, -{"az", "UTF-8", LANG_az}, -{"bg", "microsoft-cp1251", LANG_bg}, -{"ca", "ISO8859-1", LANG_ca}, -{"cs", "ISO8859-2", LANG_cs}, -{"da", "ISO8859-1", LANG_da}, -{"de", "ISO8859-1", LANG_de}, -{"el", "ISO8859-7", LANG_el}, -{"en", "ISO8859-1", LANG_en}, -{"es", "ISO8859-1", LANG_es}, -{"eu", "ISO8859-1", LANG_eu}, -{"gl", "ISO8859-1", LANG_gl}, -{"fr", "ISO8859-15", LANG_fr}, -{"hr", "ISO8859-2", LANG_hr}, -{"hu", "ISO8859-2", LANG_hu}, -{"it", "ISO8859-1", LANG_it}, -{"la", "ISO8859-1", LANG_la}, -{"lv", "ISO8859-13", LANG_lv}, -{"nl", "ISO8859-1", LANG_nl}, -{"pl", "ISO8859-2", LANG_pl}, -{"pt", "ISO8859-1", LANG_pt}, -{"sv", "ISO8859-1", LANG_sv}, -{"tr", "UTF-8", LANG_tr}, -{"ru", "KOI8-R", LANG_ru}, -{"uk", "KOI8-U", LANG_uk} +// primitive isalpha() replacement for tokenization +char * get_casechars(const char * enc) { + struct cs_info * csconv = get_current_cs(enc); + char expw[MAXLNLEN]; + char * p = expw; + for (int i = 0; i <= 255; i++) { + if ((csconv[i].cupper != csconv[i].clower)) { + *p = (char) i; + p++; + } + } + *p = '\0'; +#ifdef MOZILLA_CLIENT + delete [] csconv; +#endif + return mystrdup(expw); +} + +// language to encoding default map + +struct lang_map { + const char * lang; + int num; }; +static struct lang_map lang2enc[] = { +{"ar", LANG_ar}, +{"az", LANG_az}, +{"az_AZ", LANG_az}, // for back-compatibility +{"bg", LANG_bg}, +{"ca", LANG_ca}, +{"cs", LANG_cs}, +{"da", LANG_da}, +{"de", LANG_de}, +{"el", LANG_el}, +{"en", LANG_en}, +{"es", LANG_es}, +{"eu", LANG_eu}, +{"gl", LANG_gl}, +{"fr", LANG_fr}, +{"hr", LANG_hr}, +{"hu", LANG_hu}, +{"hu_HU", LANG_hu}, // for back-compatibility +{"it", LANG_it}, +{"la", LANG_la}, +{"lv", LANG_lv}, +{"nl", LANG_nl}, +{"pl", LANG_pl}, +{"pt", LANG_pt}, +{"sv", LANG_sv}, +{"tr", LANG_tr}, +{"tr_TR", LANG_tr}, // for back-compatibility +{"ru", LANG_ru}, +{"uk", LANG_uk} +}; -const char * get_default_enc(const char * lang) { - int n = sizeof(lang2enc) / sizeof(lang2enc[0]); - for (int i = 0; i < n; i++) { - if (strcmp(lang,lang2enc[i].lang) == 0) { - return lang2enc[i].def_enc; - } - } - return NULL; -} int get_lang_num(const char * lang) { int n = sizeof(lang2enc) / sizeof(lang2enc[0]); for (int i = 0; i < n; i++) { - if (strncmp(lang,lang2enc[i].lang,2) == 0) { + if (strcmp(lang, lang2enc[i].lang) == 0) { return lang2enc[i].num; } } @@ -5090,9 +5616,11 @@ int get_lang_num(const char * lang) { #ifndef OPENOFFICEORG #ifndef MOZILLA_CLIENT int initialize_utf_tbl() { + utf_tbl_count++; + if (utf_tbl) return 0; utf_tbl = (unicode_info2 *) malloc(CONTSIZE * sizeof(unicode_info2)); if (utf_tbl) { - int j; + size_t j; for (j = 0; j < CONTSIZE; j++) { utf_tbl[j].cletter = 0; utf_tbl[j].clower = (unsigned short) j; @@ -5110,17 +5638,12 @@ int initialize_utf_tbl() { #endif void free_utf_tbl() { - if (utf_tbl) free(utf_tbl); -} - -#ifdef MOZILLA_CLIENT -static nsCOMPtr& getcaseConv() -{ - nsresult rv; - static nsCOMPtr caseConv = do_GetService(kUnicharUtilCID, &rv); - return caseConv; + if (utf_tbl_count > 0) utf_tbl_count--; + if (utf_tbl && (utf_tbl_count == 0)) { + free(utf_tbl); + utf_tbl = NULL; + } } -#endif unsigned short unicodetoupper(unsigned short c, int langnum) { @@ -5133,11 +5656,9 @@ unsigned short unicodetoupper(unsigned short c, int langnum) return u_toupper(c); #else #ifdef MOZILLA_CLIENT - unsigned short ret(c); - getcaseConv()->ToUpper(c, &ret); - return ret; + return ToUpperCase((PRUnichar) c); #else - return utf_tbl[c].cupper; + return (utf_tbl) ? utf_tbl[c].cupper : c; #endif #endif } @@ -5153,11 +5674,9 @@ unsigned short unicodetolower(unsigned short c, int langnum) return u_tolower(c); #else #ifdef MOZILLA_CLIENT - unsigned short ret(c); - getcaseConv()->ToLower(c, &ret); - return ret; + return ToLowerCase((PRUnichar) c); #else - return utf_tbl[c].clower; + return (utf_tbl) ? utf_tbl[c].clower : c; #endif #endif } @@ -5167,10 +5686,72 @@ int unicodeisalpha(unsigned short c) #ifdef OPENOFFICEORG return u_isalpha(c); #else - return utf_tbl[c].cletter; + return (utf_tbl) ? utf_tbl[c].cletter : 0; #endif } +/* get type of capitalization */ +int get_captype(char * word, int nl, cs_info * csconv) { + // now determine the capitalization type of the first nl letters + int ncap = 0; + int nneutral = 0; + int firstcap = 0; + if (csconv == NULL) return NOCAP; + for (char * q = word; *q != '\0'; q++) { + if (csconv[*((unsigned char *)q)].ccase) ncap++; + if (csconv[*((unsigned char *)q)].cupper == csconv[*((unsigned char *)q)].clower) nneutral++; + } + if (ncap) { + firstcap = csconv[*((unsigned char *) word)].ccase; + } + + // now finally set the captype + if (ncap == 0) { + return NOCAP; + } else if ((ncap == 1) && firstcap) { + return INITCAP; + } else if ((ncap == nl) || ((ncap + nneutral) == nl)) { + return ALLCAP; + } else if ((ncap > 1) && firstcap) { + return HUHINITCAP; + } + return HUHCAP; +} + +int get_captype_utf8(w_char * word, int nl, int langnum) { + // now determine the capitalization type of the first nl letters + int ncap = 0; + int nneutral = 0; + int firstcap = 0; + unsigned short idx; + // don't check too long words + if (nl >= MAXWORDLEN) return 0; + // big Unicode character (non BMP area) + if (nl == -1) return NOCAP; + for (int i = 0; i < nl; i++) { + idx = (word[i].h << 8) + word[i].l; + if (idx != unicodetolower(idx, langnum)) ncap++; + if (unicodetoupper(idx, langnum) == unicodetolower(idx, langnum)) nneutral++; + } + if (ncap) { + idx = (word[0].h << 8) + word[0].l; + firstcap = (idx != unicodetolower(idx, langnum)); + } + + // now finally set the captype + if (ncap == 0) { + return NOCAP; + } else if ((ncap == 1) && firstcap) { + return INITCAP; + } else if ((ncap == nl) || ((ncap + nneutral) == nl)) { + return ALLCAP; + } else if ((ncap > 1) && firstcap) { + return HUHINITCAP; + } + return HUHCAP; +} + + // strip all ignored characters in the string void remove_ignored_chars_utf(char * word, unsigned short ignored_chars[], int ignored_len) { @@ -5200,14 +5781,14 @@ void remove_ignored_chars(char * word, char * ignored_chars) *word = '\0'; } -int parse_string(char * line, char ** out, const char * name) +int parse_string(char * line, char ** out, int ln) { char * tp = line; char * piece; int i = 0; int np = 0; if (*out) { - HUNSPELL_WARNING(stderr, "error: duplicate %s line\n", name); + HUNSPELL_WARNING(stderr, "error: line %d: multiple definitions\n", ln); return 1; } piece = mystrsep(&tp, 0); @@ -5217,6 +5798,7 @@ int parse_string(char * line, char ** out, const char * name) case 0: { np++; break; } case 1: { *out = mystrdup(piece); + if (!*out) return 1; np++; break; } @@ -5224,19 +5806,19 @@ int parse_string(char * line, char ** out, const char * name) } i++; } - free(piece); + // free(piece); piece = mystrsep(&tp, 0); } if (np != 2) { - HUNSPELL_WARNING(stderr, "error: missing %s information\n", name); + HUNSPELL_WARNING(stderr, "error: line %d: missing data\n", ln); return 1; } return 0; } -int parse_array(char * line, char ** out, - unsigned short ** out_utf16, int * out_utf16_len, const char * name, int utf8) { - if (parse_string(line, out, name)) return 1; +int parse_array(char * line, char ** out, unsigned short ** out_utf16, + int * out_utf16_len, int utf8, int ln) { + if (parse_string(line, out, ln)) return 1; if (utf8) { w_char w[MAXWORDLEN]; int n = u8_u16(w, MAXWORDLEN, *out); diff --git a/ext/hunspell/csutil.hxx b/ext/hunspell/csutil.hxx dissimilarity index 68% index 7fc6732ac..7bd0b919b 100644 --- a/ext/hunspell/csutil.hxx +++ b/ext/hunspell/csutil.hxx @@ -1,141 +1,220 @@ -#ifndef __CSUTILHXX__ -#define __CSUTILHXX__ - -// First some base level utility routines - -typedef struct { - unsigned char l; - unsigned char h; -} w_char; - -// convert UTF-16 characters to UTF-8 -char * u16_u8(char * dest, int size, const w_char * src, int srclen); - -// convert UTF-8 characters to UTF-16 -int u8_u16(w_char * dest, int size, const char * src); - -// sort 2-byte vector -void flag_qsort(unsigned short flags[], int begin, int end); - -// binary search in 2-byte vector -int flag_bsearch(unsigned short flags[], unsigned short flag, int right); - -// remove end of line char(s) -void mychomp(char * s); - -// duplicate string -char * mystrdup(const char * s); - -// duplicate reverse of string -char * myrevstrdup(const char * s); - -// parse into tokens with char delimiter -char * mystrsep(char ** sptr, const char delim); -// parse into tokens with char delimiter -char * mystrsep2(char ** sptr, const char delim); - -// parse into tokens with char delimiter -char * mystrrep(char *, const char *, const char *); - -// append s to ends of every lines in text -void strlinecat(char * lines, const char * s); - -// tokenize into lines with new line - int line_tok(const char * text, char *** lines); - -// tokenize into lines with new line and uniq in place - char * line_uniq(char * text); - -// change \n to c in place - char * line_join(char * text, char c); - -// leave only last {[^}]*} pattern in string - char * delete_zeros(char * morphout); - -// reverse word - int reverseword(char *); - -// reverse word - int reverseword_utf(char *); - -// character encoding information -struct cs_info { - unsigned char ccase; - unsigned char clower; - unsigned char cupper; -}; - -// Unicode character encoding information -struct unicode_info { - unsigned short c; - unsigned short cupper; - unsigned short clower; -}; - -struct unicode_info2 { - char cletter; - unsigned short cupper; - unsigned short clower; -}; - -int initialize_utf_tbl(); -void free_utf_tbl(); -unsigned short unicodetoupper(unsigned short c, int langnum); -unsigned short unicodetolower(unsigned short c, int langnum); -int unicodeisalpha(unsigned short c); - -struct enc_entry { - const char * enc_name; - struct cs_info * cs_table; -}; - -// language to encoding default map - -struct lang_map { - const char * lang; - const char * def_enc; - int num; -}; - -struct cs_info * get_current_cs(const char * es); - -const char * get_default_enc(const char * lang); - -int get_lang_num(const char * lang); - -// convert null terminated string to all caps using encoding -void enmkallcap(char * d, const char * p, const char * encoding); - -// convert null terminated string to all little using encoding -void enmkallsmall(char * d, const char * p, const char * encoding); - -// convert null terminated string to have intial capital using encoding -void enmkinitcap(char * d, const char * p, const char * encoding); - -// convert null terminated string to all caps -void mkallcap(char * p, const struct cs_info * csconv); - -// convert null terminated string to all little -void mkallsmall(char * p, const struct cs_info * csconv); - -// convert null terminated string to have intial capital -void mkinitcap(char * p, const struct cs_info * csconv); - -// convert first nc characters of UTF-8 string to little -void mkallsmall_utf(w_char * u, int nc, int langnum); - -// convert first nc characters of UTF-8 string to capital -void mkallcap_utf(w_char * u, int nc, int langnum); - -// strip all ignored characters in the string -void remove_ignored_chars_utf(char * word, unsigned short ignored_chars[], int ignored_len); - -// strip all ignored characters in the string -void remove_ignored_chars(char * word, char * ignored_chars); - -int parse_string(char * line, char ** out, const char * name); - -int parse_array(char * line, char ** out, - unsigned short ** out_utf16, int * out_utf16_len, const char * name, int utf8); - -#endif +#ifndef __CSUTILHXX__ +#define __CSUTILHXX__ + +#include "hunvisapi.h" + +// First some base level utility routines + +#include +#include "w_char.hxx" +#include "htypes.hxx" + +#ifdef MOZILLA_CLIENT +#include "nscore.h" // for mozalloc headers +#endif + +// casing +#define NOCAP 0 +#define INITCAP 1 +#define ALLCAP 2 +#define HUHCAP 3 +#define HUHINITCAP 4 + +// default encoding and keystring +#define SPELL_ENCODING "ISO8859-1" +#define SPELL_KEYSTRING "qwertyuiop|asdfghjkl|zxcvbnm" + +// default morphological fields +#define MORPH_STEM "st:" +#define MORPH_ALLOMORPH "al:" +#define MORPH_POS "po:" +#define MORPH_DERI_PFX "dp:" +#define MORPH_INFL_PFX "ip:" +#define MORPH_TERM_PFX "tp:" +#define MORPH_DERI_SFX "ds:" +#define MORPH_INFL_SFX "is:" +#define MORPH_TERM_SFX "ts:" +#define MORPH_SURF_PFX "sp:" +#define MORPH_FREQ "fr:" +#define MORPH_PHON "ph:" +#define MORPH_HYPH "hy:" +#define MORPH_PART "pa:" +#define MORPH_FLAG "fl:" +#define MORPH_HENTRY "_H:" +#define MORPH_TAG_LEN strlen(MORPH_STEM) + +#define MSEP_FLD ' ' +#define MSEP_REC '\n' +#define MSEP_ALT '\v' + +// default flags +#define DEFAULTFLAGS 65510 +#define FORBIDDENWORD 65510 +#define ONLYUPCASEFLAG 65511 + +// convert UTF-16 characters to UTF-8 +LIBHUNSPELL_DLL_EXPORTED char * u16_u8(char * dest, int size, const w_char * src, int srclen); + +// convert UTF-8 characters to UTF-16 +LIBHUNSPELL_DLL_EXPORTED int u8_u16(w_char * dest, int size, const char * src); + +// sort 2-byte vector +LIBHUNSPELL_DLL_EXPORTED void flag_qsort(unsigned short flags[], int begin, int end); + +// binary search in 2-byte vector +LIBHUNSPELL_DLL_EXPORTED int flag_bsearch(unsigned short flags[], unsigned short flag, int right); + +// remove end of line char(s) +LIBHUNSPELL_DLL_EXPORTED void mychomp(char * s); + +// duplicate string +LIBHUNSPELL_DLL_EXPORTED char * mystrdup(const char * s); + +// strcat for limited length destination string +LIBHUNSPELL_DLL_EXPORTED char * mystrcat(char * dest, const char * st, int max); + +// duplicate reverse of string +LIBHUNSPELL_DLL_EXPORTED char * myrevstrdup(const char * s); + +// parse into tokens with char delimiter +LIBHUNSPELL_DLL_EXPORTED char * mystrsep(char ** sptr, const char delim); +// parse into tokens with char delimiter +LIBHUNSPELL_DLL_EXPORTED char * mystrsep2(char ** sptr, const char delim); + +// parse into tokens with char delimiter +LIBHUNSPELL_DLL_EXPORTED char * mystrrep(char *, const char *, const char *); + +// append s to ends of every lines in text +LIBHUNSPELL_DLL_EXPORTED void strlinecat(char * lines, const char * s); + +// tokenize into lines with new line +LIBHUNSPELL_DLL_EXPORTED int line_tok(const char * text, char *** lines, char breakchar); + +// tokenize into lines with new line and uniq in place +LIBHUNSPELL_DLL_EXPORTED char * line_uniq(char * text, char breakchar); +LIBHUNSPELL_DLL_EXPORTED char * line_uniq_app(char ** text, char breakchar); + +// change oldchar to newchar in place +LIBHUNSPELL_DLL_EXPORTED char * tr(char * text, char oldc, char newc); + +// reverse word +LIBHUNSPELL_DLL_EXPORTED int reverseword(char *); + +// reverse word +LIBHUNSPELL_DLL_EXPORTED int reverseword_utf(char *); + +// remove duplicates +LIBHUNSPELL_DLL_EXPORTED int uniqlist(char ** list, int n); + +// free character array list +LIBHUNSPELL_DLL_EXPORTED void freelist(char *** list, int n); + +// character encoding information +struct cs_info { + unsigned char ccase; + unsigned char clower; + unsigned char cupper; +}; + +LIBHUNSPELL_DLL_EXPORTED int initialize_utf_tbl(); +LIBHUNSPELL_DLL_EXPORTED void free_utf_tbl(); +LIBHUNSPELL_DLL_EXPORTED unsigned short unicodetoupper(unsigned short c, int langnum); +LIBHUNSPELL_DLL_EXPORTED unsigned short unicodetolower(unsigned short c, int langnum); +LIBHUNSPELL_DLL_EXPORTED int unicodeisalpha(unsigned short c); + +LIBHUNSPELL_DLL_EXPORTED struct cs_info * get_current_cs(const char * es); + +// get language identifiers of language codes +LIBHUNSPELL_DLL_EXPORTED int get_lang_num(const char * lang); + +// get characters of the given 8bit encoding with lower- and uppercase forms +LIBHUNSPELL_DLL_EXPORTED char * get_casechars(const char * enc); + +// convert null terminated string to all caps using encoding +LIBHUNSPELL_DLL_EXPORTED void enmkallcap(char * d, const char * p, const char * encoding); + +// convert null terminated string to all little using encoding +LIBHUNSPELL_DLL_EXPORTED void enmkallsmall(char * d, const char * p, const char * encoding); + +// convert null terminated string to have initial capital using encoding +LIBHUNSPELL_DLL_EXPORTED void enmkinitcap(char * d, const char * p, const char * encoding); + +// convert null terminated string to all caps +LIBHUNSPELL_DLL_EXPORTED void mkallcap(char * p, const struct cs_info * csconv); + +// convert null terminated string to all little +LIBHUNSPELL_DLL_EXPORTED void mkallsmall(char * p, const struct cs_info * csconv); + +// convert null terminated string to have initial capital +LIBHUNSPELL_DLL_EXPORTED void mkinitcap(char * p, const struct cs_info * csconv); + +// convert first nc characters of UTF-8 string to little +LIBHUNSPELL_DLL_EXPORTED void mkallsmall_utf(w_char * u, int nc, int langnum); + +// convert first nc characters of UTF-8 string to capital +LIBHUNSPELL_DLL_EXPORTED void mkallcap_utf(w_char * u, int nc, int langnum); + +// get type of capitalization +LIBHUNSPELL_DLL_EXPORTED int get_captype(char * q, int nl, cs_info *); + +// get type of capitalization (UTF-8) +LIBHUNSPELL_DLL_EXPORTED int get_captype_utf8(w_char * q, int nl, int langnum); + +// strip all ignored characters in the string +LIBHUNSPELL_DLL_EXPORTED void remove_ignored_chars_utf(char * word, unsigned short ignored_chars[], int ignored_len); + +// strip all ignored characters in the string +LIBHUNSPELL_DLL_EXPORTED void remove_ignored_chars(char * word, char * ignored_chars); + +LIBHUNSPELL_DLL_EXPORTED int parse_string(char * line, char ** out, int ln); + +LIBHUNSPELL_DLL_EXPORTED int parse_array(char * line, char ** out, unsigned short ** out_utf16, + int * out_utf16_len, int utf8, int ln); + +LIBHUNSPELL_DLL_EXPORTED int fieldlen(const char * r); +LIBHUNSPELL_DLL_EXPORTED char * copy_field(char * dest, const char * morph, const char * var); + +LIBHUNSPELL_DLL_EXPORTED int morphcmp(const char * s, const char * t); + +LIBHUNSPELL_DLL_EXPORTED int get_sfxcount(const char * morph); + +// conversion function for protected memory +LIBHUNSPELL_DLL_EXPORTED void store_pointer(char * dest, char * source); + +// conversion function for protected memory +LIBHUNSPELL_DLL_EXPORTED char * get_stored_pointer(const char * s); + +// hash entry macros +LIBHUNSPELL_DLL_EXPORTED inline char* HENTRY_DATA(struct hentry *h) +{ + char *ret; + if (!h->var) + ret = NULL; + else if (h->var & H_OPT_ALIASM) + ret = get_stored_pointer(HENTRY_WORD(h) + h->blen + 1); + else + ret = HENTRY_WORD(h) + h->blen + 1; + return ret; +} + +// NULL-free version for warning-free OOo build +LIBHUNSPELL_DLL_EXPORTED inline const char* HENTRY_DATA2(const struct hentry *h) +{ + const char *ret; + if (!h->var) + ret = ""; + else if (h->var & H_OPT_ALIASM) + ret = get_stored_pointer(HENTRY_WORD(h) + h->blen + 1); + else + ret = HENTRY_WORD(h) + h->blen + 1; + return ret; +} + +LIBHUNSPELL_DLL_EXPORTED inline char* HENTRY_FIND(struct hentry *h, const char *p) +{ + return (HENTRY_DATA(h) ? strstr(HENTRY_DATA(h), p) : NULL); +} + +#define w_char_eq(a,b) (((a).l == (b).l) && ((a).h == (b).h)) + +#endif diff --git a/ext/hunspell/dictmgr.cxx b/ext/hunspell/dictmgr.cxx index d5b2cb3a3..ba014407e 100644 --- a/ext/hunspell/dictmgr.cxx +++ b/ext/hunspell/dictmgr.cxx @@ -1,25 +1,20 @@ -#include -#include -#include -#include +#include +#include +#include +#include #include "dictmgr.hxx" -using namespace std; - -DictMgr::DictMgr(const char * dictpath, const char * etype) +DictMgr::DictMgr(const char * dictpath, const char * etype) : numdict(0) { // load list of etype entries - numdict = 0; pdentry = (dictentry *)malloc(MAXDICTIONARIES*sizeof(struct dictentry)); if (pdentry) { if (parse_file(dictpath, etype)) { numdict = 0; // no dictionary.lst found is okay } - } else { - numdict = 0; } } @@ -101,6 +96,16 @@ int DictMgr::parse_file(const char * dictpath, const char * etype) numdict++; pdict++; } else { + switch (i) { + case 3: + free(pdict->region); + pdict->region=NULL; + case 2: //deliberate fallthrough + free(pdict->lang); + pdict->lang=NULL; + default: + break; + } fprintf(stderr,"dictionary list corruption in line \"%s\"\n",line); fflush(stderr); } @@ -128,25 +133,27 @@ char * DictMgr::mystrsep(char ** stringp, const char delim) { char * rv = NULL; char * mp = *stringp; - int n = strlen(mp); + size_t n = strlen(mp); if (n > 0) { char * dp = (char *)memchr(mp,(int)((unsigned char)delim),n); if (dp) { *stringp = dp+1; - int nc = (int)((unsigned long)dp - (unsigned long)mp); + size_t nc = dp - mp; rv = (char *) malloc(nc+1); - memcpy(rv,mp,nc); - *(rv+nc) = '\0'; - return rv; + if (rv) { + memcpy(rv,mp,nc); + *(rv+nc) = '\0'; + } } else { rv = (char *) malloc(n+1); - memcpy(rv, mp, n); - *(rv+n) = '\0'; - *stringp = mp + n; - return rv; + if (rv) { + memcpy(rv, mp, n); + *(rv+n) = '\0'; + *stringp = mp + n; + } } } - return NULL; + return rv; } @@ -155,9 +162,9 @@ char * DictMgr::mystrdup(const char * s) { char * d = NULL; if (s) { - int sl = strlen(s); - d = (char *) malloc(((sl+1) * sizeof(char))); - if (d) memcpy(d,s,((sl+1)*sizeof(char))); + int sl = strlen(s)+1; + d = (char *) malloc(sl); + if (d) memcpy(d,s,sl); } return d; } diff --git a/ext/hunspell/dictmgr.hxx b/ext/hunspell/dictmgr.hxx index 88eeb7d61..bb197f84f 100644 --- a/ext/hunspell/dictmgr.hxx +++ b/ext/hunspell/dictmgr.hxx @@ -1,6 +1,8 @@ #ifndef _DICTMGR_HXX_ #define _DICTMGR_HXX_ +#include "hunvisapi.h" + #define MAXDICTIONARIES 100 #define MAXDICTENTRYLEN 1024 @@ -11,7 +13,7 @@ struct dictentry { }; -class DictMgr +class LIBHUNSPELL_DLL_EXPORTED DictMgr { int numdict; diff --git a/ext/hunspell/filemgr.cxx b/ext/hunspell/filemgr.cxx new file mode 100644 index 000000000..1e98f40bc --- /dev/null +++ b/ext/hunspell/filemgr.cxx @@ -0,0 +1,49 @@ +#include "license.hunspell" +#include "license.myspell" + +#include +#include +#include + +#include "filemgr.hxx" + +int FileMgr::fail(const char * err, const char * par) { + fprintf(stderr, err, par); + return -1; +} + +FileMgr::FileMgr(const char * file, const char * key) { + linenum = 0; + hin = NULL; + fin = fopen(file, "r"); + if (!fin) { + // check hzipped file + char * st = (char *) malloc(strlen(file) + strlen(HZIP_EXTENSION) + 1); + if (st) { + strcpy(st, file); + strcat(st, HZIP_EXTENSION); + hin = new Hunzip(st, key); + free(st); + } + } + if (!fin && !hin) fail(MSG_OPEN, file); +} + +FileMgr::~FileMgr() +{ + if (fin) fclose(fin); + if (hin) delete hin; +} + +char * FileMgr::getline() { + const char * l; + linenum++; + if (fin) return fgets(in, BUFSIZE - 1, fin); + if (hin && (l = hin->getline())) return strcpy(in, l); + linenum--; + return NULL; +} + +int FileMgr::getlinenum() { + return linenum; +} diff --git a/ext/hunspell/filemgr.hxx b/ext/hunspell/filemgr.hxx new file mode 100644 index 000000000..94cb7233d --- /dev/null +++ b/ext/hunspell/filemgr.hxx @@ -0,0 +1,25 @@ +/* file manager class - read lines of files [filename] OR [filename.hz] */ +#ifndef _FILEMGR_HXX_ +#define _FILEMGR_HXX_ + +#include "hunvisapi.h" + +#include "hunzip.hxx" +#include + +class LIBHUNSPELL_DLL_EXPORTED FileMgr +{ +protected: + FILE * fin; + Hunzip * hin; + char in[BUFSIZE + 50]; // input buffer + int fail(const char * err, const char * par); + int linenum; + +public: + FileMgr(const char * filename, const char * key = NULL); + ~FileMgr(); + char * getline(); + int getlinenum(); +}; +#endif diff --git a/ext/hunspell/hashmgr.cxx b/ext/hunspell/hashmgr.cxx index 57be70b99..fdf3f26ca 100644 --- a/ext/hunspell/hashmgr.cxx +++ b/ext/hunspell/hashmgr.cxx @@ -1,41 +1,28 @@ #include "license.hunspell" #include "license.myspell" -#ifndef MOZILLA_CLIENT -#include -#include -#include -#include -#else #include #include #include #include -#endif #include "hashmgr.hxx" #include "csutil.hxx" #include "atypes.hxx" -#ifdef MOZILLA_CLIENT -#ifdef __SUNPRO_CC // for SunONE Studio compiler -using namespace std; -#endif -#else -#ifndef W32 -using namespace std; -#endif -#endif - // build a hash table from a munched word list -HashMgr::HashMgr(const char * tpath, const char * apath) +HashMgr::HashMgr(const char * tpath, const char * apath, const char * key) { tablesize = 0; tableptr = NULL; flag_mode = FLAG_CHAR; complexprefixes = 0; utf8 = 0; + langnum = 0; + lang = NULL; + enc = NULL; + csconv = 0; ignorechars = NULL; ignorechars_utf16 = NULL; ignorechars_utf16_len = 0; @@ -43,13 +30,15 @@ HashMgr::HashMgr(const char * tpath, const char * apath) aliasf = NULL; numaliasm = 0; aliasm = NULL; - load_config(apath); - int ec = load_tables(tpath); + forbiddenword = FORBIDDENWORD; // forbidden word signing flag + load_config(apath, key); + int ec = load_tables(tpath, key); if (ec) { /* error condition - what should we do here */ HUNSPELL_WARNING(stderr, "Hash Manager Error : %d\n",ec); if (tableptr) { free(tableptr); + tableptr = NULL; } tablesize = 0; } @@ -62,23 +51,11 @@ HashMgr::~HashMgr() // now pass through hash table freeing up everything // go through column by column of the table for (int i=0; i < tablesize; i++) { - struct hentry * pt = &tableptr[i]; + struct hentry * pt = tableptr[i]; struct hentry * nt = NULL; - if (pt) { - if (pt->astr && !aliasf) free(pt->astr); - if (pt->word) free(pt->word); -#ifdef HUNSPELL_EXPERIMENTAL - if (pt->description && !aliasm) free(pt->description); -#endif - pt = pt->next; - } while(pt) { nt = pt->next; - if (pt->astr && !aliasf) free(pt->astr); - if (pt->word) free(pt->word); -#ifdef HUNSPELL_EXPERIMENTAL - if (pt->description && !aliasm) free(pt->description); -#endif + if (pt->astr && (!aliasf || TESTAFF(pt->astr, ONLYUPCASEFLAG, pt->alen))) free(pt->astr); free(pt); pt = nt; } @@ -101,9 +78,22 @@ HashMgr::~HashMgr() free(aliasm); aliasm = NULL; } + +#ifndef OPENOFFICEORG +#ifndef MOZILLA_CLIENT + if (utf8) free_utf_tbl(); +#endif +#endif + + if (enc) free(enc); + if (lang) free(lang); if (ignorechars) free(ignorechars); if (ignorechars_utf16) free(ignorechars_utf16); + +#ifdef MOZILLA_CLIENT + delete [] csconv; +#endif } // lookup a root word in the hashtable @@ -112,190 +102,323 @@ struct hentry * HashMgr::lookup(const char *word) const { struct hentry * dp; if (tableptr) { - dp = &tableptr[hash(word)]; - if (dp->word == NULL) return NULL; + dp = tableptr[hash(word)]; + if (!dp) return NULL; for ( ; dp != NULL; dp = dp->next) { - if (strcmp(word,dp->word) == 0) return dp; + if (strcmp(word, dp->word) == 0) return dp; } } return NULL; } // add a word to the hash table (private) - -int HashMgr::add_word(const char * word, int wl, unsigned short * aff, int al, const char * desc) +int HashMgr::add_word(const char * word, int wbl, int wcl, unsigned short * aff, + int al, const char * desc, bool onlyupcase) { - char * st = mystrdup(word); - if (wl && !st) return 1; + bool upcasehomonym = false; + int descl = desc ? (aliasm ? sizeof(short) : strlen(desc) + 1) : 0; + // variable-length hash record with word and optional fields + struct hentry* hp = + (struct hentry *) malloc (sizeof(struct hentry) + wbl + descl); + if (!hp) return 1; + char * hpw = hp->word; + strcpy(hpw, word); if (ignorechars != NULL) { if (utf8) { - remove_ignored_chars_utf(st, ignorechars_utf16, ignorechars_utf16_len); + remove_ignored_chars_utf(hpw, ignorechars_utf16, ignorechars_utf16_len); } else { - remove_ignored_chars(st, ignorechars); + remove_ignored_chars(hpw, ignorechars); } } if (complexprefixes) { - if (utf8) reverseword_utf(st); else reverseword(st); + if (utf8) reverseword_utf(hpw); else reverseword(hpw); } - int i = hash(st); - struct hentry * dp = &tableptr[i]; - if (dp->word == NULL) { - dp->wlen = (short) wl; - dp->alen = (short) al; - dp->word = st; - dp->astr = aff; - dp->next = NULL; - dp->next_homonym = NULL; -#ifdef HUNSPELL_EXPERIMENTAL - if (aliasm) { - dp->description = (desc) ? get_aliasm(atoi(desc)) : mystrdup(desc); - } else { - dp->description = mystrdup(desc); - if (desc && !dp->description) return 1; - if (dp->description && complexprefixes) { - if (utf8) reverseword_utf(dp->description); else reverseword(dp->description); - } - } -#endif - } else { - struct hentry* hp = (struct hentry *) malloc (sizeof(struct hentry)); - if (!hp) return 1; - hp->wlen = (short) wl; - hp->alen = (short) al; - hp->word = st; - hp->astr = aff; - hp->next = NULL; - hp->next_homonym = NULL; -#ifdef HUNSPELL_EXPERIMENTAL - if (aliasm) { - hp->description = (desc) ? get_aliasm(atoi(desc)) : mystrdup(desc); - } else { - hp->description = mystrdup(desc); - if (desc && !hp->description) return 1; - if (dp->description && complexprefixes) { - if (utf8) reverseword_utf(hp->description); else reverseword(hp->description); + + int i = hash(hpw); + + hp->blen = (unsigned char) wbl; + hp->clen = (unsigned char) wcl; + hp->alen = (short) al; + hp->astr = aff; + hp->next = NULL; + hp->next_homonym = NULL; + + // store the description string or its pointer + if (desc) { + hp->var = H_OPT; + if (aliasm) { + hp->var += H_OPT_ALIASM; + store_pointer(hpw + wbl + 1, get_aliasm(atoi(desc))); + } else { + strcpy(hpw + wbl + 1, desc); + if (complexprefixes) { + if (utf8) reverseword_utf(HENTRY_DATA(hp)); + else reverseword(HENTRY_DATA(hp)); } + } + if (strstr(HENTRY_DATA(hp), MORPH_PHON)) hp->var += H_OPT_PHON; + } else hp->var = 0; + + struct hentry * dp = tableptr[i]; + if (!dp) { + tableptr[i] = hp; + return 0; } -#endif while (dp->next != NULL) { - if ((!dp->next_homonym) && (strcmp(hp->word, dp->word) == 0)) dp->next_homonym = hp; + if ((!dp->next_homonym) && (strcmp(hp->word, dp->word) == 0)) { + // remove hidden onlyupcase homonym + if (!onlyupcase) { + if ((dp->astr) && TESTAFF(dp->astr, ONLYUPCASEFLAG, dp->alen)) { + free(dp->astr); + dp->astr = hp->astr; + dp->alen = hp->alen; + free(hp); + return 0; + } else { + dp->next_homonym = hp; + } + } else { + upcasehomonym = true; + } + } dp=dp->next; } - if ((!dp->next_homonym) && (strcmp(hp->word, dp->word) == 0)) dp->next_homonym = hp; - dp->next = hp; - } + if (strcmp(hp->word, dp->word) == 0) { + // remove hidden onlyupcase homonym + if (!onlyupcase) { + if ((dp->astr) && TESTAFF(dp->astr, ONLYUPCASEFLAG, dp->alen)) { + free(dp->astr); + dp->astr = hp->astr; + dp->alen = hp->alen; + free(hp); + return 0; + } else { + dp->next_homonym = hp; + } + } else { + upcasehomonym = true; + } + } + if (!upcasehomonym) { + dp->next = hp; + } else { + // remove hidden onlyupcase homonym + if (hp->astr) free(hp->astr); + free(hp); + } return 0; } -// add a custom dic. word to the hash table (public) -int HashMgr::put_word(const char * word, int wl, char * aff) +int HashMgr::add_hidden_capitalized_word(char * word, int wbl, int wcl, + unsigned short * flags, int al, char * dp, int captype) { - unsigned short * flags; - int al = 0; - if (aff) { - al = decode_flags(&flags, aff); - flag_qsort(flags, 0, al); - } else { - flags = NULL; + // add inner capitalized forms to handle the following allcap forms: + // Mixed caps: OpenOffice.org -> OPENOFFICE.ORG + // Allcaps with suffixes: CIA's -> CIA'S + if (((captype == HUHCAP) || (captype == HUHINITCAP) || + ((captype == ALLCAP) && (flags != NULL))) && + !((flags != NULL) && TESTAFF(flags, forbiddenword, al))) { + unsigned short * flags2 = (unsigned short *) malloc (sizeof(unsigned short) * (al+1)); + if (!flags2) return 1; + if (al) memcpy(flags2, flags, al * sizeof(unsigned short)); + flags2[al] = ONLYUPCASEFLAG; + if (utf8) { + char st[BUFSIZE]; + w_char w[BUFSIZE]; + int wlen = u8_u16(w, BUFSIZE, word); + mkallsmall_utf(w, wlen, langnum); + mkallcap_utf(w, 1, langnum); + u16_u8(st, BUFSIZE, w, wlen); + return add_word(st,wbl,wcl,flags2,al+1,dp, true); + } else { + mkallsmall(word, csconv); + mkinitcap(word, csconv); + return add_word(word,wbl,wcl,flags2,al+1,dp, true); + } } - add_word(word, wl, flags, al, NULL); return 0; } -int HashMgr::put_word_pattern(const char * word, int wl, const char * pattern) +// detect captype and modify word length for UTF-8 encoding +int HashMgr::get_clen_and_captype(const char * word, int wbl, int * captype) { + int len; + if (utf8) { + w_char dest_utf[BUFSIZE]; + len = u8_u16(dest_utf, BUFSIZE, word); + *captype = get_captype_utf8(dest_utf, len, langnum); + } else { + len = wbl; + *captype = get_captype((char *) word, len, csconv); + } + return len; +} + +// remove word (personal dictionary function for standalone applications) +int HashMgr::remove(const char * word) { - unsigned short * flags; - struct hentry * dp = lookup(pattern); - if (!dp || !dp->astr) return 1; - flags = (unsigned short *) malloc (dp->alen * sizeof(short)); - memcpy((void *) flags, (void *) dp->astr, dp->alen * sizeof(short)); - add_word(word, wl, flags, dp->alen, NULL); + struct hentry * dp = lookup(word); + while (dp) { + if (dp->alen == 0 || !TESTAFF(dp->astr, forbiddenword, dp->alen)) { + unsigned short * flags = + (unsigned short *) malloc(sizeof(short) * (dp->alen + 1)); + if (!flags) return 1; + for (int i = 0; i < dp->alen; i++) flags[i] = dp->astr[i]; + flags[dp->alen] = forbiddenword; + dp->astr = flags; + dp->alen++; + flag_qsort(flags, 0, dp->alen); + } + dp = dp->next_homonym; + } return 0; } -// walk the hash table entry by entry - null at end -struct hentry * HashMgr::walk_hashtable(int &col, struct hentry * hp) const +/* remove forbidden flag to add a personal word to the hash */ +int HashMgr::remove_forbidden_flag(const char * word) { + struct hentry * dp = lookup(word); + if (!dp) return 1; + while (dp) { + if (dp->astr && TESTAFF(dp->astr, forbiddenword, dp->alen)) { + if (dp->alen == 1) dp->alen = 0; // XXX forbidden words of personal dic. + else { + unsigned short * flags2 = + (unsigned short *) malloc(sizeof(short) * (dp->alen - 1)); + if (!flags2) return 1; + int i, j = 0; + for (i = 0; i < dp->alen; i++) { + if (dp->astr[i] != forbiddenword) flags2[j++] = dp->astr[i]; + } + dp->alen--; + dp->astr = flags2; // XXX allowed forbidden words + } + } + dp = dp->next_homonym; + } + return 0; +} + +// add a custom dic. word to the hash table (public) +int HashMgr::add(const char * word) { - //reset to start - if ((col < 0) || (hp == NULL)) { - col = -1; - hp = NULL; - } + unsigned short * flags = NULL; + int al = 0; + if (remove_forbidden_flag(word)) { + int captype; + int wbl = strlen(word); + int wcl = get_clen_and_captype(word, wbl, &captype); + add_word(word, wbl, wcl, flags, al, NULL, false); + return add_hidden_capitalized_word((char *) word, wbl, wcl, flags, al, NULL, captype); + } + return 0; +} - if (hp && hp->next != NULL) { - hp = hp->next; - } else { - col++; - hp = (col < tablesize) ? &tableptr[col] : NULL; - // search for next non-blank column entry - while (hp && (hp->word == NULL)) { - col ++; - hp = (col < tablesize) ? &tableptr[col] : NULL; +int HashMgr::add_with_affix(const char * word, const char * example) +{ + // detect captype and modify word length for UTF-8 encoding + struct hentry * dp = lookup(example); + remove_forbidden_flag(word); + if (dp && dp->astr) { + int captype; + int wbl = strlen(word); + int wcl = get_clen_and_captype(word, wbl, &captype); + if (aliasf) { + add_word(word, wbl, wcl, dp->astr, dp->alen, NULL, false); + } else { + unsigned short * flags = (unsigned short *) malloc (dp->alen * sizeof(short)); + if (flags) { + memcpy((void *) flags, (void *) dp->astr, dp->alen * sizeof(short)); + add_word(word, wbl, wcl, flags, dp->alen, NULL, false); + } else return 1; + } + return add_hidden_capitalized_word((char *) word, wbl, wcl, dp->astr, dp->alen, NULL, captype); } - if (col < tablesize) return hp; - hp = NULL; - col = -1; + return 1; +} + +// walk the hash table entry by entry - null at end +// initialize: col=-1; hp = NULL; hp = walk_hashtable(&col, hp); +struct hentry * HashMgr::walk_hashtable(int &col, struct hentry * hp) const +{ + if (hp && hp->next != NULL) return hp->next; + for (col++; col < tablesize; col++) { + if (tableptr[col]) return tableptr[col]; } - return hp; + // null at end and reset to start + col = -1; + return NULL; } // load a munched word list and build a hash table on the fly -int HashMgr::load_tables(const char * tpath) +int HashMgr::load_tables(const char * tpath, const char * key) { - int wl, al; + int al; char * ap; char * dp; + char * dp2; unsigned short * flags; + char * ts; - // raw dictionary - munched file - FILE * rawdict = fopen(tpath, "r"); - if (rawdict == NULL) return 1; + // open dictionary file + FileMgr * dict = new FileMgr(tpath, key); + if (dict == NULL) return 1; // first read the first line of file to get hash table size */ - char ts[MAXDELEN]; - if (! fgets(ts, MAXDELEN-1,rawdict)) { - fclose(rawdict); + if (!(ts = dict->getline())) { + HUNSPELL_WARNING(stderr, "error: empty dic file\n"); + delete dict; return 2; } mychomp(ts); - + /* remove byte order mark */ - if (strncmp(ts,"?",3) == 0) { + if (strncmp(ts,"\xEF\xBB\xBF",3) == 0) { memmove(ts, ts+3, strlen(ts+3)+1); - HUNSPELL_WARNING(stderr, "warning: dic file begins with byte order mark: possible incompatibility with old Hunspell versions\n"); + // warning: dic file begins with byte order mark: possible incompatibility with old Hunspell versions } - - if ((*ts < '1') || (*ts > '9')) HUNSPELL_WARNING(stderr, "error - missing word count in dictionary file\n"); + tablesize = atoi(ts); - if (!tablesize) { - fclose(rawdict); - return 4; + if (tablesize == 0) { + HUNSPELL_WARNING(stderr, "error: line 1: missing or bad word count in the dic file\n"); + delete dict; + return 4; } tablesize = tablesize + 5 + USERWORD; if ((tablesize %2) == 0) tablesize++; // allocate the hash table - tableptr = (struct hentry *) calloc(tablesize, sizeof(struct hentry)); - if (!tableptr) { - fclose(rawdict); + tableptr = (struct hentry **) malloc(tablesize * sizeof(struct hentry *)); + if (! tableptr) { + delete dict; return 3; } - - for (int i=0; igetline())) { mychomp(ts); // split each line into word and morphological description - dp = strchr(ts,'\t'); + dp = ts; + while ((dp = strchr(dp, ':'))) { + if ((dp > ts + 3) && (*(dp - 3) == ' ' || *(dp - 3) == '\t')) { + for (dp -= 4; dp >= ts && (*dp == ' ' || *dp == '\t'); dp--); + if (dp < ts) { // missing word + dp = NULL; + } else { + *(dp + 1) = '\0'; + dp = dp + 2; + } + break; + } + dp++; + } - if (dp) { - *dp = '\0'; - dp++; - } else { - dp = NULL; + // tabulator is the old morphological field separator + dp2 = strchr(ts, '\t'); + if (dp2 && (!dp || dp2 < dp)) { + *dp2 = '\0'; + dp = dp2 + 1; } // split each line into word and affix char strings @@ -316,13 +439,18 @@ int HashMgr::load_tables(const char * tpath) *ap = '\0'; if (aliasf) { int index = atoi(ap + 1); - al = get_aliasf(index, &flags); + al = get_aliasf(index, &flags, dict); if (!al) { - HUNSPELL_WARNING(stderr, "error - bad flag vector alias: %s\n", ts); + HUNSPELL_WARNING(stderr, "error: line %d: bad flag vector alias\n", dict->getlinenum()); *ap = '\0'; } } else { - al = decode_flags(&flags, ap + 1); + al = decode_flags(&flags, ap + 1, dict); + if (al == -1) { + HUNSPELL_WARNING(stderr, "Can't allocate memory.\n"); + delete dict; + return 6; + } flag_qsort(flags, 0, al); } } else { @@ -331,18 +459,21 @@ int HashMgr::load_tables(const char * tpath) flags = NULL; } - wl = strlen(ts); - - // add the word and its index - if (add_word(ts,wl,flags,al,dp)) return 5; - + int captype; + int wbl = strlen(ts); + int wcl = get_clen_and_captype(ts, wbl, &captype); + // add the word and its index plus its capitalized form optionally + if (add_word(ts,wbl,wcl,flags,al,dp, false) || + add_hidden_capitalized_word(ts, wbl, wcl, flags, al, dp, captype)) { + delete dict; + return 5; + } } - - fclose(rawdict); + + delete dict; return 0; } - // the hash function is a simple load and rotate // algorithm borrowed @@ -358,20 +489,26 @@ int HashMgr::hash(const char * word) const return (unsigned long) hv % tablesize; } -int HashMgr::decode_flags(unsigned short ** result, char * flags) { +int HashMgr::decode_flags(unsigned short ** result, char * flags, FileMgr * af) { int len; + if (*flags == '\0') { + *result = NULL; + return 0; + } switch (flag_mode) { case FLAG_LONG: { // two-character flags (1x2yZz -> 1x 2y Zz) len = strlen(flags); - if (len%2 == 1) HUNSPELL_WARNING(stderr, "error: length of FLAG_LONG flagvector is odd: %s\n", flags); - len = len/2; + if (len%2 == 1) HUNSPELL_WARNING(stderr, "error: line %d: bad flagvector\n", af->getlinenum()); + len /= 2; *result = (unsigned short *) malloc(len * sizeof(short)); + if (!*result) return -1; for (int i = 0; i < len; i++) { (*result)[i] = (((unsigned short) flags[i * 2]) << 8) + (unsigned short) flags[i * 2 + 1]; } break; } case FLAG_NUM: { // decimal numbers separated by comma (4521,23,233 -> 4521 23 233) + int i; len = 1; char * src = flags; unsigned short * dest; @@ -380,23 +517,31 @@ int HashMgr::decode_flags(unsigned short ** result, char * flags) { if (*p == ',') len++; } *result = (unsigned short *) malloc(len * sizeof(short)); + if (!*result) return -1; dest = *result; for (p = flags; *p; p++) { if (*p == ',') { - *dest = (unsigned short) atoi(src); - if (*dest == 0) HUNSPELL_WARNING(stderr, "error: 0 is wrong flag id\n"); + i = atoi(src); + if (i >= DEFAULTFLAGS) HUNSPELL_WARNING(stderr, "error: line %d: flag id %d is too large (max: %d)\n", + af->getlinenum(), i, DEFAULTFLAGS - 1); + *dest = (unsigned short) i; + if (*dest == 0) HUNSPELL_WARNING(stderr, "error: line %d: 0 is wrong flag id\n", af->getlinenum()); src = p + 1; dest++; } } - *dest = (unsigned short) atoi(src); - if (*dest == 0) HUNSPELL_WARNING(stderr, "error: 0 is wrong flag id\n"); + i = atoi(src); + if (i >= DEFAULTFLAGS) HUNSPELL_WARNING(stderr, "error: line %d: flag id %d is too large (max: %d)\n", + af->getlinenum(), i, DEFAULTFLAGS - 1); + *dest = (unsigned short) i; + if (*dest == 0) HUNSPELL_WARNING(stderr, "error: line %d: 0 is wrong flag id\n", af->getlinenum()); break; } case FLAG_UNI: { // UTF-8 characters - w_char w[MAXDELEN/2]; - len = u8_u16(w, MAXDELEN/2, flags); + w_char w[BUFSIZE/2]; + len = u8_u16(w, BUFSIZE/2, flags); *result = (unsigned short *) malloc(len * sizeof(short)); + if (!*result) return -1; memcpy(*result, w, len * sizeof(short)); break; } @@ -404,24 +549,28 @@ int HashMgr::decode_flags(unsigned short ** result, char * flags) { unsigned short * dest; len = strlen(flags); *result = (unsigned short *) malloc(len * sizeof(short)); + if (!*result) return -1; dest = *result; for (unsigned char * p = (unsigned char *) flags; *p; p++) { *dest = (unsigned short) *p; dest++; } } - } + } return len; } unsigned short HashMgr::decode_flag(const char * f) { unsigned short s = 0; + int i; switch (flag_mode) { case FLAG_LONG: s = ((unsigned short) f[0] << 8) + (unsigned short) f[1]; break; case FLAG_NUM: - s = (unsigned short) atoi(f); + i = atoi(f); + if (i >= DEFAULTFLAGS) HUNSPELL_WARNING(stderr, "error: flag id %d is too large (max: %d)\n", i, DEFAULTFLAGS - 1); + s = (unsigned short) i; break; case FLAG_UNI: u8_u16((w_char *) &s, 1, f); @@ -429,7 +578,7 @@ unsigned short HashMgr::decode_flag(const char * f) { default: s = (unsigned short) *((unsigned char *)f); } - if (!s) HUNSPELL_WARNING(stderr, "error: 0 is wrong flag id\n"); + if (s == 0) HUNSPELL_WARNING(stderr, "error: 0 is wrong flag id\n"); return s; } @@ -452,16 +601,13 @@ char * HashMgr::encode_flag(unsigned short f) { } // read in aff file and set flag mode -int HashMgr::load_config(const char * affpath) +int HashMgr::load_config(const char * affpath, const char * key) { + char * line; // io buffers int firstline = 1; - - // io buffers - char line[MAXDELEN+1]; // open the affix file - FILE * afflst; - afflst = fopen(affpath,"r"); + FileMgr * afflst = new FileMgr(affpath, key); if (!afflst) { HUNSPELL_WARNING(stderr, "Error - could not open affix description file %s\n",affpath); return 1; @@ -470,64 +616,94 @@ int HashMgr::load_config(const char * affpath) // read in each line ignoring any that do not // start with a known line type indicator - while (fgets(line,MAXDELEN,afflst)) { + while ((line = afflst->getline())) { mychomp(line); /* remove byte order mark */ if (firstline) { firstline = 0; - if (strncmp(line,"",3) == 0) memmove(line, line+3, strlen(line+3)+1); + if (strncmp(line,"\xEF\xBB\xBF",3) == 0) memmove(line, line+3, strlen(line+3)+1); } /* parse in the try string */ if ((strncmp(line,"FLAG",4) == 0) && isspace(line[4])) { if (flag_mode != FLAG_CHAR) { - HUNSPELL_WARNING(stderr, "error: duplicate FLAG parameter\n"); + HUNSPELL_WARNING(stderr, "error: line %d: multiple definitions of the FLAG affix file parameter\n", afflst->getlinenum()); } if (strstr(line, "long")) flag_mode = FLAG_LONG; if (strstr(line, "num")) flag_mode = FLAG_NUM; if (strstr(line, "UTF-8")) flag_mode = FLAG_UNI; if (flag_mode == FLAG_CHAR) { - HUNSPELL_WARNING(stderr, "error: FLAG need `num', `long' or `UTF-8' parameter: %s\n", line); + HUNSPELL_WARNING(stderr, "error: line %d: FLAG needs `num', `long' or `UTF-8' parameter\n", afflst->getlinenum()); } } - if ((strncmp(line,"SET",3) == 0) && isspace(line[3]) && strstr(line, "UTF-8")) utf8 = 1; + if (strncmp(line,"FORBIDDENWORD",13) == 0) { + char * st = NULL; + if (parse_string(line, &st, afflst->getlinenum())) { + delete afflst; + return 1; + } + forbiddenword = decode_flag(st); + free(st); + } + if (strncmp(line, "SET", 3) == 0) { + if (parse_string(line, &enc, afflst->getlinenum())) { + delete afflst; + return 1; + } + if (strcmp(enc, "UTF-8") == 0) { + utf8 = 1; +#ifndef OPENOFFICEORG +#ifndef MOZILLA_CLIENT + initialize_utf_tbl(); +#endif +#endif + } else csconv = get_current_cs(enc); + } + if (strncmp(line, "LANG", 4) == 0) { + if (parse_string(line, &lang, afflst->getlinenum())) { + delete afflst; + return 1; + } + langnum = get_lang_num(lang); + } /* parse in the ignored characters (for example, Arabic optional diacritics characters */ if (strncmp(line,"IGNORE",6) == 0) { - if (parse_array(line, &ignorechars, &ignorechars_utf16, &ignorechars_utf16_len, "IGNORE", utf8)) { - fclose(afflst); + if (parse_array(line, &ignorechars, &ignorechars_utf16, + &ignorechars_utf16_len, utf8, afflst->getlinenum())) { + delete afflst; return 1; } } if ((strncmp(line,"AF",2) == 0) && isspace(line[2])) { if (parse_aliasf(line, afflst)) { - fclose(afflst); + delete afflst; return 1; } } -#ifdef HUNSPELL_EXPERIMENTAL if ((strncmp(line,"AM",2) == 0) && isspace(line[2])) { if (parse_aliasm(line, afflst)) { - fclose(afflst); + delete afflst; return 1; } } -#endif - if (strncmp(line,"COMPLEXPREFIXES",15) == 0) complexprefixes = 1; - if (((strncmp(line,"SFX",3) == 0) || (strncmp(line,"PFX",3) == 0)) && isspace(line[3])) break; + + if (strncmp(line,"COMPLEXPREFIXES",15) == 0) complexprefixes = 1; + if (((strncmp(line,"SFX",3) == 0) || (strncmp(line,"PFX",3) == 0)) && isspace(line[3])) break; } - fclose(afflst); + if (csconv == NULL) csconv = get_current_cs(SPELL_ENCODING); + delete afflst; return 0; } /* parse in the ALIAS table */ -int HashMgr::parse_aliasf(char * line, FILE * af) +int HashMgr::parse_aliasf(char * line, FileMgr * af) { if (numaliasf != 0) { - HUNSPELL_WARNING(stderr, "error: duplicate AF (alias for flag vector) tables used\n"); + HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n", af->getlinenum()); return 1; } char * tp = line; @@ -545,8 +721,7 @@ int HashMgr::parse_aliasf(char * line, FILE * af) numaliasf = 0; aliasf = NULL; aliasflen = NULL; - HUNSPELL_WARNING(stderr, "incorrect number of entries in AF table\n"); - free(piece); + HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n", af->getlinenum()); return 1; } aliasf = (unsigned short **) malloc(numaliasf * sizeof(unsigned short *)); @@ -557,7 +732,6 @@ int HashMgr::parse_aliasf(char * line, FILE * af) if (aliasflen) free(aliasflen); aliasf = NULL; aliasflen = NULL; - free(piece); return 1; } np++; @@ -567,7 +741,6 @@ int HashMgr::parse_aliasf(char * line, FILE * af) } i++; } - free(piece); piece = mystrsep(&tp, 0); } if (np != 2) { @@ -576,14 +749,14 @@ int HashMgr::parse_aliasf(char * line, FILE * af) free(aliasflen); aliasf = NULL; aliasflen = NULL; - HUNSPELL_WARNING(stderr, "error: missing AF table information\n"); + HUNSPELL_WARNING(stderr, "error: line %d: missing data\n", af->getlinenum()); return 1; } /* now parse the numaliasf lines to read in the remainder of the table */ - char * nl = line; + char * nl; for (int j=0; j < numaliasf; j++) { - if (!fgets(nl,MAXDELEN,af)) return 1; + if (!(nl = af->getline())) return 1; mychomp(nl); tp = nl; i = 0; @@ -600,14 +773,13 @@ int HashMgr::parse_aliasf(char * line, FILE * af) free(aliasflen); aliasf = NULL; aliasflen = NULL; - HUNSPELL_WARNING(stderr, "error: AF table is corrupt\n"); - free(piece); + HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum()); return 1; } break; } case 1: { - aliasflen[j] = (unsigned short) decode_flags(&(aliasf[j]), piece); + aliasflen[j] = (unsigned short) decode_flags(&(aliasf[j]), piece, af); flag_qsort(aliasf[j], 0, aliasflen[j]); break; } @@ -615,7 +787,6 @@ int HashMgr::parse_aliasf(char * line, FILE * af) } i++; } - free(piece); piece = mystrsep(&tp, 0); } if (!aliasf[j]) { @@ -624,7 +795,7 @@ int HashMgr::parse_aliasf(char * line, FILE * af) aliasf = NULL; aliasflen = NULL; numaliasf = 0; - HUNSPELL_WARNING(stderr, "error: AF table is corrupt\n"); + HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum()); return 1; } } @@ -635,22 +806,21 @@ int HashMgr::is_aliasf() { return (aliasf != NULL); } -int HashMgr::get_aliasf(int index, unsigned short ** fvec) { +int HashMgr::get_aliasf(int index, unsigned short ** fvec, FileMgr * af) { if ((index > 0) && (index <= numaliasf)) { *fvec = aliasf[index - 1]; return aliasflen[index - 1]; } - HUNSPELL_WARNING(stderr, "error: bad flag alias index: %d\n", index); + HUNSPELL_WARNING(stderr, "error: line %d: bad flag alias index: %d\n", af->getlinenum(), index); *fvec = NULL; return 0; } -#ifdef HUNSPELL_EXPERIMENTAL /* parse morph alias definitions */ -int HashMgr::parse_aliasm(char * line, FILE * af) +int HashMgr::parse_aliasm(char * line, FileMgr * af) { if (numaliasm != 0) { - HUNSPELL_WARNING(stderr, "error: duplicate AM (aliases for morphological descriptions) tables used\n"); + HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n", af->getlinenum()); return 1; } char * tp = line; @@ -665,8 +835,7 @@ int HashMgr::parse_aliasm(char * line, FILE * af) case 1: { numaliasm = atoi(piece); if (numaliasm < 1) { - HUNSPELL_WARNING(stderr, "incorrect number of entries in AM table\n"); - free(piece); + HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n", af->getlinenum()); return 1; } aliasm = (char **) malloc(numaliasm * sizeof(char *)); @@ -681,33 +850,31 @@ int HashMgr::parse_aliasm(char * line, FILE * af) } i++; } - free(piece); piece = mystrsep(&tp, 0); } if (np != 2) { numaliasm = 0; free(aliasm); aliasm = NULL; - HUNSPELL_WARNING(stderr, "error: missing AM alias information\n"); + HUNSPELL_WARNING(stderr, "error: line %d: missing data\n", af->getlinenum()); return 1; } /* now parse the numaliasm lines to read in the remainder of the table */ char * nl = line; for (int j=0; j < numaliasm; j++) { - if (!fgets(nl,MAXDELEN,af)) return 1; + if (!(nl = af->getline())) return 1; mychomp(nl); tp = nl; i = 0; aliasm[j] = NULL; - piece = mystrsep(&tp, 0); + piece = mystrsep(&tp, ' '); while (piece) { if (*piece != '\0') { switch(i) { case 0: { if (strncmp(piece,"AM",2) != 0) { - HUNSPELL_WARNING(stderr, "error: AM table is corrupt\n"); - free(piece); + HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum()); numaliasm = 0; free(aliasm); aliasm = NULL; @@ -716,24 +883,34 @@ int HashMgr::parse_aliasm(char * line, FILE * af) break; } case 1: { + // add the remaining of the line + if (*tp) { + *(tp - 1) = ' '; + tp = tp + strlen(tp); + } if (complexprefixes) { if (utf8) reverseword_utf(piece); else reverseword(piece); } aliasm[j] = mystrdup(piece); + if (!aliasm[j]) { + numaliasm = 0; + free(aliasm); + aliasm = NULL; + return 1; + } break; } default: break; } i++; } - free(piece); - piece = mystrsep(&tp, 0); + piece = mystrsep(&tp, ' '); } if (!aliasm[j]) { numaliasm = 0; free(aliasm); aliasm = NULL; - HUNSPELL_WARNING(stderr, "error: map table is corrupt\n"); + HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum()); return 1; } } @@ -749,4 +926,3 @@ char * HashMgr::get_aliasm(int index) { HUNSPELL_WARNING(stderr, "error: bad morph. alias index: %d\n", index); return NULL; } -#endif diff --git a/ext/hunspell/hashmgr.hxx b/ext/hunspell/hashmgr.hxx dissimilarity index 70% index 356e55245..341b08131 100644 --- a/ext/hunspell/hashmgr.hxx +++ b/ext/hunspell/hashmgr.hxx @@ -1,59 +1,69 @@ -#ifndef _HASHMGR_HXX_ -#define _HASHMGR_HXX_ - -#include -#include "htypes.hxx" - -enum flag { FLAG_CHAR, FLAG_LONG, FLAG_NUM, FLAG_UNI }; - -class HashMgr -{ - int tablesize; - struct hentry * tableptr; - int userword; - flag flag_mode; - int complexprefixes; - int utf8; - char * ignorechars; - unsigned short * ignorechars_utf16; - int ignorechars_utf16_len; - int numaliasf; // flag vector `compression' with aliases - unsigned short ** aliasf; - unsigned short * aliasflen; - int numaliasm; // morphological desciption `compression' with aliases - char ** aliasm; - - -public: - HashMgr(const char * tpath, const char * apath); - ~HashMgr(); - - struct hentry * lookup(const char *) const; - int hash(const char *) const; - struct hentry * walk_hashtable(int & col, struct hentry * hp) const; - - int put_word(const char * word, int wl, char * ap); - int put_word_pattern(const char * word, int wl, const char * pattern); - int decode_flags(unsigned short ** result, char * flags); - unsigned short decode_flag(const char * flag); - char * encode_flag(unsigned short flag); - int is_aliasf(); - int get_aliasf(int index, unsigned short ** fvec); -#ifdef HUNSPELL_EXPERIMENTAL - int is_aliasm(); - char * get_aliasm(int index); -#endif - - -private: - int load_tables(const char * tpath); - int add_word(const char * word, int wl, unsigned short * ap, int al, const char * desc); - int load_config(const char * affpath); - int parse_aliasf(char * line, FILE * af); -#ifdef HUNSPELL_EXPERIMENTAL - int parse_aliasm(char * line, FILE * af); -#endif - -}; - -#endif +#ifndef _HASHMGR_HXX_ +#define _HASHMGR_HXX_ + +#include "hunvisapi.h" + +#include + +#include "htypes.hxx" +#include "filemgr.hxx" + +enum flag { FLAG_CHAR, FLAG_LONG, FLAG_NUM, FLAG_UNI }; + +class LIBHUNSPELL_DLL_EXPORTED HashMgr +{ + int tablesize; + struct hentry ** tableptr; + int userword; + flag flag_mode; + int complexprefixes; + int utf8; + unsigned short forbiddenword; + int langnum; + char * enc; + char * lang; + struct cs_info * csconv; + char * ignorechars; + unsigned short * ignorechars_utf16; + int ignorechars_utf16_len; + int numaliasf; // flag vector `compression' with aliases + unsigned short ** aliasf; + unsigned short * aliasflen; + int numaliasm; // morphological desciption `compression' with aliases + char ** aliasm; + + +public: + HashMgr(const char * tpath, const char * apath, const char * key = NULL); + ~HashMgr(); + + struct hentry * lookup(const char *) const; + int hash(const char *) const; + struct hentry * walk_hashtable(int & col, struct hentry * hp) const; + + int add(const char * word); + int add_with_affix(const char * word, const char * pattern); + int remove(const char * word); + int decode_flags(unsigned short ** result, char * flags, FileMgr * af); + unsigned short decode_flag(const char * flag); + char * encode_flag(unsigned short flag); + int is_aliasf(); + int get_aliasf(int index, unsigned short ** fvec, FileMgr * af); + int is_aliasm(); + char * get_aliasm(int index); + +private: + int get_clen_and_captype(const char * word, int wbl, int * captype); + int load_tables(const char * tpath, const char * key); + int add_word(const char * word, int wbl, int wcl, unsigned short * ap, + int al, const char * desc, bool onlyupcase); + int load_config(const char * affpath, const char * key); + int parse_aliasf(char * line, FileMgr * af); + int add_hidden_capitalized_word(char * word, int wbl, int wcl, + unsigned short * flags, int al, char * dp, int captype); + int parse_aliasm(char * line, FileMgr * af); + int remove_forbidden_flag(const char * word); + +}; + +#endif diff --git a/ext/hunspell/htypes.hxx b/ext/hunspell/htypes.hxx index a0dc064b6..5b6c90966 100644 --- a/ext/hunspell/htypes.hxx +++ b/ext/hunspell/htypes.hxx @@ -1,28 +1,32 @@ #ifndef _HTYPES_HXX_ #define _HTYPES_HXX_ -#define MAXDELEN 8192 - #define ROTATE_LEN 5 #define ROTATE(v,q) \ (v) = ((v) << (q)) | (((v) >> (32 - q)) & ((1 << (q))-1)); +// hentry options +#define H_OPT (1 << 0) +#define H_OPT_ALIASM (1 << 1) +#define H_OPT_PHON (1 << 2) + +// see also csutil.hxx +#define HENTRY_WORD(h) &(h->word[0]) + // approx. number of user defined words #define USERWORD 1000 struct hentry { - short wlen; - short alen; - char wbeg[2]; - char * word; - unsigned short * astr; - struct hentry * next; - struct hentry * next_homonym; -#ifdef HUNSPELL_EXPERIMENTAL - char * description; -#endif + unsigned char blen; // word length in bytes + unsigned char clen; // word length in characters (different for UTF-8 enc.) + short alen; // length of affix flag vector + unsigned short * astr; // affix flag vector + struct hentry * next; // next word with same hash code + struct hentry * next_homonym; // next homonym word (with same hash code) + char var; // variable fields (only for special pronounciation yet) + char word[1]; // variable-length word (8-bit or UTF-8 encoding) }; #endif diff --git a/ext/hunspell/hunspell.cxx b/ext/hunspell/hunspell.cxx index 9aab3480e..2d4f45150 100644 --- a/ext/hunspell/hunspell.cxx +++ b/ext/hunspell/hunspell.cxx @@ -1,86 +1,92 @@ -#include "license.hunspell" +#include "license.hunspell" #include "license.myspell" -#ifndef MOZILLA_CLIENT -#include -#include -#include -#else -#include +#include #include -#include -#endif +#include #include "hunspell.hxx" #include "hunspell.h" - #ifndef MOZILLA_CLIENT -#ifndef W32 -using namespace std; -#endif +# include "config.h" #endif +#include "csutil.hxx" -Hunspell::Hunspell(const char * affpath, const char * dpath) +Hunspell::Hunspell(const char * affpath, const char * dpath, const char * key) { encoding = NULL; csconv = NULL; utf8 = 0; complexprefixes = 0; + affixpath = mystrdup(affpath); + maxdic = 0; /* first set up the hash manager */ - pHMgr = new HashMgr(dpath, affpath); + pHMgr[0] = new HashMgr(dpath, affpath, key); + if (pHMgr[0]) maxdic = 1; /* next set up the affix manager */ /* it needs access to the hash manager lookup methods */ - pAMgr = new AffixMgr(affpath,pHMgr); + pAMgr = new AffixMgr(affpath, pHMgr, &maxdic, key); /* get the preferred try string and the dictionary */ /* encoding from the Affix Manager for that dictionary */ char * try_string = pAMgr->get_try_string(); encoding = pAMgr->get_encoding(); - csconv = get_current_cs(encoding); langnum = pAMgr->get_langnum(); utf8 = pAMgr->get_utf8(); + if (!utf8) + csconv = get_current_cs(encoding); complexprefixes = pAMgr->get_complexprefixes(); wordbreak = pAMgr->get_breaktable(); /* and finally set up the suggestion manager */ pSMgr = new SuggestMgr(try_string, MAXSUGGESTION, pAMgr); if (try_string) free(try_string); - } Hunspell::~Hunspell() { if (pSMgr) delete pSMgr; if (pAMgr) delete pAMgr; - if (pHMgr) delete pHMgr; + for (int i = 0; i < maxdic; i++) delete pHMgr[i]; + maxdic = 0; pSMgr = NULL; pAMgr = NULL; - pHMgr = NULL; +#ifdef MOZILLA_CLIENT + delete [] csconv; +#endif csconv= NULL; if (encoding) free(encoding); encoding = NULL; + if (affixpath) free(affixpath); + affixpath = NULL; } +// load extra dictionaries +int Hunspell::add_dic(const char * dpath, const char * key) { + if (maxdic == MAXDIC || !affixpath) return 1; + pHMgr[maxdic] = new HashMgr(dpath, affixpath, key); + if (pHMgr[maxdic]) maxdic++; else return 1; + return 0; +} // make a copy of src at destination while removing all leading // blanks and removing any trailing periods after recording // their presence with the abbreviation flag -// also since already going through character by character, +// also since already going through character by character, // set the capitalization type // return the length of the "cleaned" (and UTF-8 encoded) word -int Hunspell::cleanword2(char * dest, const char * src, +int Hunspell::cleanword2(char * dest, const char * src, w_char * dest_utf, int * nc, int * pcaptype, int * pabbrev) -{ +{ unsigned char * p = (unsigned char *) dest; const unsigned char * q = (const unsigned char * ) src; - int firstcap = 0; // first skip over any leading blanks while ((*q != '\0') && (*q == ' ')) q++; - + // now strip off any trailing periods (recording their presence) *pabbrev = 0; int nl = strlen((const char *)q); @@ -88,80 +94,43 @@ int Hunspell::cleanword2(char * dest, const char * src, nl--; (*pabbrev)++; } - + // if no characters are left it can't be capitalized - if (nl <= 0) { + if (nl <= 0) { *pcaptype = NOCAP; *p = '\0'; return 0; } - // now determine the capitalization type of the first nl letters - int ncap = 0; - int nneutral = 0; - *nc = 0; - - if (!utf8) { - while (nl > 0) { - (*nc)++; - if (csconv[(*q)].ccase) ncap++; - if (csconv[(*q)].cupper == csconv[(*q)].clower) nneutral++; - *p++ = *q++; - nl--; - } - // remember to terminate the destination string - *p = '\0'; - if (ncap) { - firstcap = csconv[(unsigned char)(*dest)].ccase; - } - } else { - unsigned short idx; - *nc = u8_u16(dest_utf, MAXWORDLEN, (const char *) q); + strncpy(dest, (char *) q, nl); + *(dest + nl) = '\0'; + nl = strlen(dest); + if (utf8) { + *nc = u8_u16(dest_utf, MAXWORDLEN, dest); // don't check too long words if (*nc >= MAXWORDLEN) return 0; if (*nc == -1) { // big Unicode character (non BMP area) *pcaptype = NOCAP; - strcpy((char *) p, (char *) q); - return strlen(dest); + return nl; } - *nc -= *pabbrev; - for (int i = 0; i < *nc; i++) { - idx = (dest_utf[i].h << 8) + dest_utf[i].l; - if (idx != unicodetolower(idx, langnum)) ncap++; - if (unicodetoupper(idx, langnum) == unicodetolower(idx, langnum)) nneutral++; - } - u16_u8(dest, MAXWORDUTF8LEN, dest_utf, *nc); - if (ncap) { - idx = (dest_utf[0].h << 8) + dest_utf[0].l; - firstcap = (idx != unicodetolower(idx, langnum)); - } - } - - // now finally set the captype - if (ncap == 0) { - *pcaptype = NOCAP; - } else if ((ncap == 1) && firstcap) { - *pcaptype = INITCAP; - } else if ((ncap == *nc) || ((ncap + nneutral) == *nc)) { - *pcaptype = ALLCAP; - } else if ((ncap > 1) && firstcap) { - *pcaptype = HUHINITCAP; + *pcaptype = get_captype_utf8(dest_utf, *nc, langnum); } else { - *pcaptype = HUHCAP; + *pcaptype = get_captype(dest, nl, csconv); + *nc = nl; } - return strlen(dest); -} + return nl; +} -int Hunspell::cleanword(char * dest, const char * src, +int Hunspell::cleanword(char * dest, const char * src, int * pcaptype, int * pabbrev) -{ +{ unsigned char * p = (unsigned char *) dest; const unsigned char * q = (const unsigned char * ) src; int firstcap = 0; // first skip over any leading blanks while ((*q != '\0') && (*q == ' ')) q++; - + // now strip off any trailing periods (recording their presence) *pabbrev = 0; int nl = strlen((const char *)q); @@ -169,9 +138,9 @@ int Hunspell::cleanword(char * dest, const char * src, nl--; (*pabbrev)++; } - + // if no characters are left it can't be capitalized - if (nl <= 0) { + if (nl <= 0) { *pcaptype = NOCAP; *p = '\0'; return 0; @@ -199,8 +168,9 @@ int Hunspell::cleanword(char * dest, const char * src, nc = u8_u16(t, MAXWORDLEN, src); for (int i = 0; i < nc; i++) { idx = (t[i].h << 8) + t[i].l; - if (idx != unicodetolower(idx, langnum)) ncap++; - if (unicodetoupper(idx, langnum) == unicodetolower(idx, langnum)) nneutral++; + unsigned short low = unicodetolower(idx, langnum); + if (idx != low) ncap++; + if (unicodetoupper(idx, langnum) == low) nneutral++; } u16_u8(dest, MAXWORDUTF8LEN, t, nc); if (ncap) { @@ -222,8 +192,7 @@ int Hunspell::cleanword(char * dest, const char * src, *pcaptype = HUHCAP; } return strlen(dest); -} - +} void Hunspell::mkallcap(char * p) { @@ -240,7 +209,7 @@ void Hunspell::mkallcap(char * p) } u16_u8(p, MAXWORDUTF8LEN, u, nc); } else { - while (*p != '\0') { + while (*p != '\0') { *p = csconv[((unsigned char) *p)].cupper; p++; } @@ -253,15 +222,16 @@ int Hunspell::mkallcap2(char * p, w_char * u, int nc) unsigned short idx; for (int i = 0; i < nc; i++) { idx = (u[i].h << 8) + u[i].l; - if (idx != unicodetoupper(idx, langnum)) { - u[i].h = (unsigned char) (unicodetoupper(idx, langnum) >> 8); - u[i].l = (unsigned char) (unicodetoupper(idx, langnum) & 0x00FF); + unsigned short up = unicodetoupper(idx, langnum); + if (idx != up) { + u[i].h = (unsigned char) (up >> 8); + u[i].l = (unsigned char) (up & 0x00FF); } } u16_u8(p, MAXWORDUTF8LEN, u, nc); - return strlen(p); + return strlen(p); } else { - while (*p != '\0') { + while (*p != '\0') { *p = csconv[((unsigned char) *p)].cupper; p++; } @@ -272,7 +242,7 @@ int Hunspell::mkallcap2(char * p, w_char * u, int nc) void Hunspell::mkallsmall(char * p) { - while (*p != '\0') { + while (*p != '\0') { *p = csconv[((unsigned char) *p)].clower; p++; } @@ -284,15 +254,16 @@ int Hunspell::mkallsmall2(char * p, w_char * u, int nc) unsigned short idx; for (int i = 0; i < nc; i++) { idx = (u[i].h << 8) + u[i].l; - if (idx != unicodetolower(idx, langnum)) { - u[i].h = (unsigned char) (unicodetolower(idx, langnum) >> 8); - u[i].l = (unsigned char) (unicodetolower(idx, langnum) & 0x00FF); + unsigned short low = unicodetolower(idx, langnum); + if (idx != low) { + u[i].h = (unsigned char) (low >> 8); + u[i].l = (unsigned char) (low & 0x00FF); } } u16_u8(p, MAXWORDUTF8LEN, u, nc); return strlen(p); } else { - while (*p != '\0') { + while (*p != '\0') { *p = csconv[((unsigned char) *p)].clower; p++; } @@ -306,18 +277,18 @@ char * Hunspell::sharps_u8_l1(char * dest, char * source) { *p = *source; for (p++, source++; *(source - 1); p++, source++) { *p = *source; - if (*source == '?') *--p = '?'; + if (*source == '\x9F') *--p = '\xDF'; } return dest; } -// recursive search for right ss-?permutations +// recursive search for right ss - sharp s permutations hentry * Hunspell::spellsharps(char * base, char * pos, int n, int repnum, char * tmp, int * info, char **root) { pos = strstr(pos, "ss"); if (pos && (n < MAXSHARPS)) { - *pos = '?'; - *(pos + 1) = '?'; + *pos = '\xC3'; + *(pos + 1) = '\x9F'; hentry * h = spellsharps(base, pos + 2, n + 1, repnum + 1, tmp, info, root); if (h) return h; *pos = 's'; @@ -336,18 +307,17 @@ int Hunspell::is_keepcase(const hentry * rv) { TESTAFF(rv->astr, pAMgr->get_keepcase(), rv->alen); } -/* check and insert a word to beginning of the suggestion array */ -int Hunspell::insert_sug(char ***slst, char * word, int *ns) { - if (spell(word)) { - if (*ns == MAXSUGGESTION) { - (*ns)--; - free((*slst)[*ns]); - } - for (int k = *ns; k > 0; k--) (*slst)[k] = (*slst)[k - 1]; - (*slst)[0] = mystrdup(word); - (*ns)++; +/* insert a word to the beginning of the suggestion array and return ns */ +int Hunspell::insert_sug(char ***slst, char * word, int ns) { + char * dup = mystrdup(word); + if (!dup) return ns; + if (ns == MAXSUGGESTION) { + ns--; + free((*slst)[ns]); } - return 0; + for (int k = ns; k > 0; k--) (*slst)[k] = (*slst)[k - 1]; + (*slst)[0] = dup; + return ns + 1; } int Hunspell::spell(const char * word, int * info, char ** root) @@ -355,9 +325,11 @@ int Hunspell::spell(const char * word, int * info, char ** root) struct hentry * rv=NULL; // need larger vector. For example, Turkish capital letter I converted a // 2-byte UTF-8 character (dotless i) by mkallsmall. - char cw[MAXWORDUTF8LEN + 4]; - char wspace[MAXWORDUTF8LEN + 4]; - w_char unicw[MAXWORDLEN + 1]; + char cw[MAXWORDUTF8LEN]; + char wspace[MAXWORDUTF8LEN]; + w_char unicw[MAXWORDLEN]; + // Hunspell supports XML input of the simplified API (see manual) + if (strcmp(word, SPELL_XML) == 0) return 1; int nc = strlen(word); int wl2 = 0; if (utf8) { @@ -367,14 +339,18 @@ int Hunspell::spell(const char * word, int * info, char ** root) } int captype = 0; int abbv = 0; - int wl = cleanword2(cw, word, unicw, &nc, &captype, &abbv); + int wl = 0; - if (wl == 0) return 1; + // input conversion + RepList * rl = (pAMgr) ? pAMgr->get_iconvtable() : NULL; + if (rl && rl->conv(word, wspace)) wl = cleanword2(cw, wspace, unicw, &nc, &captype, &abbv); + else wl = cleanword2(cw, word, unicw, &nc, &captype, &abbv); - if (info) *info = 0; + int info2 = 0; + if (wl == 0 || maxdic == 0) return 1; if (root) *root = NULL; - // allow numbers with dots and commas (but forbid double separators: "..", ",," etc.) + // allow numbers with dots, dashes and commas (but forbid double separators: "..", "--" etc.) enum { NBEGIN, NNUM, NSEP }; int nstate = NBEGIN; int i; @@ -388,173 +364,207 @@ int Hunspell::spell(const char * word, int * info, char ** root) } else break; } if ((i == wl) && (nstate == NNUM)) return 1; - - // LANG_hu section: number(s) + (percent or degree) with suffixes - if (langnum == LANG_hu) { - if ((nstate == NNUM) && ((cw[i] == '%') || (cw[i] == '?')) - && checkword(cw + i, info, root)) return 1; - } - // END of LANG_hu section + if (!info) info = &info2; else *info = 0; switch(captype) { - case HUHCAP: - case HUHINITCAP: - case NOCAP: { - rv = checkword(cw, info, root); - if ((abbv) && !(rv)) { - memcpy(wspace,cw,wl); - *(wspace+wl) = '.'; - *(wspace+wl+1) = '\0'; - rv = checkword(wspace, info, root); - } - break; - } + case HUHCAP: + case HUHINITCAP: + *info += SPELL_ORIGCAP; + case NOCAP: { + rv = checkword(cw, info, root); + if ((abbv) && !(rv)) { + memcpy(wspace,cw,wl); + *(wspace+wl) = '.'; + *(wspace+wl+1) = '\0'; + rv = checkword(wspace, info, root); + } + break; + } case ALLCAP: { - rv = checkword(cw, info, root); - if (rv) break; - if (abbv) { - memcpy(wspace,cw,wl); - *(wspace+wl) = '.'; - *(wspace+wl+1) = '\0'; - rv = checkword(wspace, info, root); - if (rv) break; - } - if (pAMgr && pAMgr->get_checksharps() && strstr(cw, "SS")) { - char tmpword[MAXWORDUTF8LEN]; - wl = mkallsmall2(cw, unicw, nc); - memcpy(wspace,cw,(wl+1)); + *info += SPELL_ORIGCAP; + rv = checkword(cw, info, root); + if (rv) break; + if (abbv) { + memcpy(wspace,cw,wl); + *(wspace+wl) = '.'; + *(wspace+wl+1) = '\0'; + rv = checkword(wspace, info, root); + if (rv) break; + } + // Spec. prefix handling for Catalan, French, Italian: + // prefixes separated by apostrophe (SANT'ELIA -> Sant'+Elia). + if (pAMgr && strchr(cw, '\'')) { + wl = mkallsmall2(cw, unicw, nc); + //There are no really sane circumstances where this could fail, + //but anyway... + if (char * apostrophe = strchr(cw, '\'')) { + if (utf8) { + w_char tmpword[MAXWORDLEN]; + *apostrophe = '\0'; + wl2 = u8_u16(tmpword, MAXWORDLEN, cw); + *apostrophe = '\''; + if (wl2 < nc) { + mkinitcap2(apostrophe + 1, unicw + wl2 + 1, nc - wl2 - 1); + rv = checkword(cw, info, root); + if (rv) break; + } + } else { + mkinitcap2(apostrophe + 1, unicw, nc); + rv = checkword(cw, info, root); + if (rv) break; + } + } + mkinitcap2(cw, unicw, nc); + rv = checkword(cw, info, root); + if (rv) break; + } + if (pAMgr && pAMgr->get_checksharps() && strstr(cw, "SS")) { + char tmpword[MAXWORDUTF8LEN]; + wl = mkallsmall2(cw, unicw, nc); + memcpy(wspace,cw,(wl+1)); + rv = spellsharps(wspace, wspace, 0, 0, tmpword, info, root); + if (!rv) { + wl2 = mkinitcap2(cw, unicw, nc); + rv = spellsharps(cw, cw, 0, 0, tmpword, info, root); + } + if ((abbv) && !(rv)) { + *(wspace+wl) = '.'; + *(wspace+wl+1) = '\0'; + rv = spellsharps(wspace, wspace, 0, 0, tmpword, info, root); + if (!rv) { + memcpy(wspace, cw, wl2); + *(wspace+wl2) = '.'; + *(wspace+wl2+1) = '\0'; rv = spellsharps(wspace, wspace, 0, 0, tmpword, info, root); - if (!rv) { - wl2 = mkinitcap2(cw, unicw, nc); - rv = spellsharps(cw, cw, 0, 0, tmpword, info, root); - } - if ((abbv) && !(rv)) { - *(wspace+wl) = '.'; - *(wspace+wl+1) = '\0'; - rv = spellsharps(wspace, wspace, 0, 0, tmpword, info, root); - if (!rv) { - memcpy(wspace, cw, wl2); - *(wspace+wl2) = '.'; - *(wspace+wl2+1) = '\0'; - rv = spellsharps(wspace, wspace, 0, 0, tmpword, info, root); - } - } - if (rv) break; } } - case INITCAP: { - wl = mkallsmall2(cw, unicw, nc); - memcpy(wspace,cw,(wl+1)); - rv = checkword(wspace, info, root); - if (!rv || (is_keepcase(rv) && !((captype == INITCAP) && - // if CHECKSHARPS: KEEPCASE words with ?are allowed - // in INITCAP form, too. - pAMgr->get_checksharps() && ((utf8 && strstr(wspace, "脽")) || - (!utf8 && strchr(wspace, '?')))))) { - wl2 = mkinitcap2(cw, unicw, nc); - rv = checkword(cw, info, root); - if (rv && (captype == ALLCAP) && is_keepcase(rv)) rv = NULL; - } - if (abbv && !rv) { - *(wspace+wl) = '.'; - *(wspace+wl+1) = '\0'; - rv = checkword(wspace, info, root); - if (!rv || is_keepcase(rv)) { - memcpy(wspace, cw, wl2); - *(wspace+wl2) = '.'; - *(wspace+wl2+1) = '\0'; - rv = checkword(wspace, info, root); - if (rv && ((captype == ALLCAP) && is_keepcase(rv))) rv = NULL; - } - } - break; - } + if (rv) break; + } + } + case INITCAP: { + *info += SPELL_ORIGCAP; + wl = mkallsmall2(cw, unicw, nc); + memcpy(wspace,cw,(wl+1)); + wl2 = mkinitcap2(cw, unicw, nc); + if (captype == INITCAP) *info += SPELL_INITCAP; + rv = checkword(cw, info, root); + if (captype == INITCAP) *info -= SPELL_INITCAP; + // forbid bad capitalization + // (for example, ijs -> Ijs instead of IJs in Dutch) + // use explicit forms in dic: Ijs/F (F = FORBIDDENWORD flag) + if (*info & SPELL_FORBIDDEN) { + rv = NULL; + break; + } + if (rv && is_keepcase(rv) && (captype == ALLCAP)) rv = NULL; + if (rv) break; + + rv = checkword(wspace, info, root); + if (abbv && !rv) { + + *(wspace+wl) = '.'; + *(wspace+wl+1) = '\0'; + rv = checkword(wspace, info, root); + if (!rv) { + memcpy(wspace, cw, wl2); + *(wspace+wl2) = '.'; + *(wspace+wl2+1) = '\0'; + if (captype == INITCAP) *info += SPELL_INITCAP; + rv = checkword(wspace, info, root); + if (captype == INITCAP) *info -= SPELL_INITCAP; + if (rv && is_keepcase(rv) && (captype == ALLCAP)) rv = NULL; + break; + } + } + if (rv && is_keepcase(rv) && + ((captype == ALLCAP) || + // if CHECKSHARPS: KEEPCASE words with \xDF are allowed + // in INITCAP form, too. + !(pAMgr->get_checksharps() && + ((utf8 && strstr(wspace, "\xC3\x9F")) || + (!utf8 && strchr(wspace, '\xDF')))))) rv = NULL; + break; + } + } + + if (rv) { + if (pAMgr && pAMgr->get_warn() && rv->astr && + TESTAFF(rv->astr, pAMgr->get_warn(), rv->alen)) { + *info += SPELL_WARN; + if (pAMgr->get_forbidwarn()) return 0; + return HUNSPELL_OK_WARN; + } + return HUNSPELL_OK; } - - if (rv) return 1; - // recursive breaking at break points (not good for morphological analysis) + // recursive breaking at break points if (wordbreak) { char * s; char r; - for (int j = 0; j < pAMgr->get_numbreak(); j++) { + int nbr = 0; + wl = strlen(cw); + int numbreak = pAMgr ? pAMgr->get_numbreak() : 0; + + // calculate break points for recursion limit + for (int j = 0; j < numbreak; j++) { + s = cw; + do { + s = (char *) strstr(s, wordbreak[j]); + if (s) { + nbr++; + s++; + } + } while (s); + } + if (nbr >= 10) return 0; + + // check boundary patterns (^begin and end$) + for (int j = 0; j < numbreak; j++) { + int plen = strlen(wordbreak[j]); + if (plen == 1 || plen > wl) continue; + if (wordbreak[j][0] == '^' && strncmp(cw, wordbreak[j] + 1, plen - 1) == 0 + && spell(cw + plen - 1)) return 1; + if (wordbreak[j][plen - 1] == '$' && + strncmp(cw + wl - plen + 1, wordbreak[j], plen - 1) == 0) { + r = cw[wl - plen + 1]; + cw[wl - plen + 1] = '\0'; + if (spell(cw)) return 1; + cw[wl - plen + 1] = r; + } + } + + // other patterns + for (int j = 0; j < numbreak; j++) { + int plen = strlen(wordbreak[j]); s=(char *) strstr(cw, wordbreak[j]); - if (s) { + if (s && (s > cw) && (s < cw + wl - plen)) { + if (!spell(s + plen)) continue; r = *s; *s = '\0'; // examine 2 sides of the break point - if (spell(cw) && spell(s + strlen(wordbreak[j]))) { - *s = r; - return 1; - } + if (spell(cw)) return 1; *s = r; + + // LANG_hu: spec. dash rule + if (langnum == LANG_hu && strcmp(wordbreak[j], "-") == 0) { + r = s[1]; + s[1] = '\0'; + if (spell(cw)) return 1; // check the first part with dash + s[1] = r; + } + // end of LANG speficic region + } } } - // LANG_hu: compoundings with dashes and n-dashes XXX deprecated! - if (langnum == LANG_hu) { - int n; - // compound word with dash (HU) I18n - char * dash; - int result = 0; - // n-dash - dash = (char *) strstr(cw,"-"); - if (dash && !wordbreak) { - *dash = '\0'; - // examine 2 sides of the dash - if (spell(cw) && spell(dash + 3)) { - *dash = '?'; - return 1; - } - *dash = '?'; - } - dash = (char *) strchr(cw,'-'); - if (dash) { - *dash='\0'; - // examine 2 sides of the dash - if (dash[1] == '\0') { // base word ending with dash - if (spell(cw)) return 1; - } else { - // first word ending with dash: word- - char r2 = *(dash + 1); - dash[0]='-'; - dash[1]='\0'; - result = spell(cw); - dash[1] = r2; - dash[0]='\0'; - if (result && spell(dash+1) && ((strlen(dash+1) > 1) || (dash[1] == 'e') || - ((dash[1] > '0') && (dash[1] < '9')))) return 1; - } - // affixed number in correct word - if (result && (dash > cw) && (((*(dash-1)<='9') && (*(dash-1)>='0')) || (*(dash-1)>='.'))) { - *dash='-'; - n = 1; - if (*(dash - n) == '.') n++; - // search first not a number character to left from dash - while (((dash - n)>=cw) && ((*(dash - n)=='0') || (n < 3)) && (n < 6)) { - n++; - } - if ((dash - n) < cw) n--; - // numbers: deprecated - for(; n >= 1; n--) { - if ((*(dash - n) >= '0') && (*(dash - n) <= '9') && - checkword(dash - n, info, root)) return 1; - } - } - } - } return 0; } -//int Hunspell::spell(const char * word) { -// return spell(word, NULL, NULL); -//} - struct hentry * Hunspell::checkword(const char * w, int * info, char ** root) { struct hentry * he = NULL; - int len; + int len, i; char w2[MAXWORDUTF8LEN]; const char * word; @@ -569,9 +579,13 @@ struct hentry * Hunspell::checkword(const char * w, int * info, char ** root) remove_ignored_chars(w2,ignoredchars); } word = w2; - free(ignoredchars); } else word = w; + len = strlen(word); + + if (!len) + return NULL; + // word reversing wrapper for complex prefixes if (complexprefixes) { if (word != w2) { @@ -582,65 +596,71 @@ struct hentry * Hunspell::checkword(const char * w, int * info, char ** root) } // look word in hash table - if (pHMgr) he = pHMgr->lookup(word); + for (i = 0; (i < maxdic) && !he; i ++) { + he = (pHMgr[i])->lookup(word); // check forbidden and onlyincompound words if ((he) && (he->astr) && (pAMgr) && TESTAFF(he->astr, pAMgr->get_forbiddenword(), he->alen)) { - info += SPELL_FORBIDDEN; + if (info) *info += SPELL_FORBIDDEN; // LANG_hu section: set dash information for suggestions if (langnum == LANG_hu) { if (pAMgr->get_compoundflag() && TESTAFF(he->astr, pAMgr->get_compoundflag(), he->alen)) { - info += SPELL_COMPOUND; + if (info) *info += SPELL_COMPOUND; } } return NULL; } - // he = next not pseudoroot and not onlyincompound homonym or NULL + // he = next not needaffix, onlyincompound homonym or onlyupcase word while (he && (he->astr) && - ((pAMgr->get_pseudoroot() && TESTAFF(he->astr, pAMgr->get_pseudoroot(), he->alen)) || - (pAMgr->get_onlyincompound() && TESTAFF(he->astr, pAMgr->get_onlyincompound(), he->alen)) + ((pAMgr->get_needaffix() && TESTAFF(he->astr, pAMgr->get_needaffix(), he->alen)) || + (pAMgr->get_onlyincompound() && TESTAFF(he->astr, pAMgr->get_onlyincompound(), he->alen)) || + (info && (*info & SPELL_INITCAP) && TESTAFF(he->astr, ONLYUPCASEFLAG, he->alen)) )) he = he->next_homonym; + } // check with affixes if (!he && pAMgr) { // try stripping off affixes */ - len = strlen(word); he = pAMgr->affix_check(word, len, 0); - // check compound restriction - if (he && he->astr && pAMgr->get_onlyincompound() && - TESTAFF(he->astr, pAMgr->get_onlyincompound(), he->alen)) he = NULL; + // check compound restriction and onlyupcase + if (he && he->astr && ( + (pAMgr->get_onlyincompound() && + TESTAFF(he->astr, pAMgr->get_onlyincompound(), he->alen)) || + (info && (*info & SPELL_INITCAP) && + TESTAFF(he->astr, ONLYUPCASEFLAG, he->alen)))) { + he = NULL; + } if (he) { if ((he->astr) && (pAMgr) && TESTAFF(he->astr, pAMgr->get_forbiddenword(), he->alen)) { - info += SPELL_FORBIDDEN; + if (info) *info += SPELL_FORBIDDEN; return NULL; } if (root) { *root = mystrdup(he->word); - if (complexprefixes) { + if (*root && complexprefixes) { if (utf8) reverseword_utf(*root); else reverseword(*root); } } // try check compound word } else if (pAMgr->get_compound()) { - he = pAMgr->compound_check(word, len, - 0,0,100,0,NULL,0,NULL,NULL,0); + he = pAMgr->compound_check(word, len, 0, 0, 100, 0, NULL, 0, 0, info); // LANG_hu section: `moving rule' with last dash - if ((!he) && (langnum == LANG_hu) && (word[len-1]=='-')) { + if ((!he) && (langnum == LANG_hu) && (word[len-1] == '-')) { char * dup = mystrdup(word); + if (!dup) return NULL; dup[len-1] = '\0'; - he = pAMgr->compound_check(dup, len-1, - -5,0,100,0,NULL,1,NULL,NULL,0); + he = pAMgr->compound_check(dup, len-1, -5, 0, 100, 0, NULL, 1, 0, info); free(dup); } - // end of LANG speficic region + // end of LANG speficic region if (he) { if (root) { *root = mystrdup(he->word); - if (complexprefixes) { + if (*root && complexprefixes) { if (utf8) reverseword_utf(*root); else reverseword(*root); } } @@ -655,10 +675,16 @@ struct hentry * Hunspell::checkword(const char * w, int * info, char ** root) int Hunspell::suggest(char*** slst, const char * word) { - char cw[MAXWORDUTF8LEN + 4]; - char wspace[MAXWORDUTF8LEN + 4]; - if (! pSMgr) return 0; - w_char unicw[MAXWORDLEN + 1]; + int onlycmpdsug = 0; + char cw[MAXWORDUTF8LEN]; + char wspace[MAXWORDUTF8LEN]; + if (!pSMgr || maxdic == 0) return 0; + w_char unicw[MAXWORDLEN]; + *slst = NULL; + // process XML input of the simplified API (see manual) + if (strncmp(word, SPELL_XML, sizeof(SPELL_XML) - 3) == 0) { + return spellml(slst, word); + } int nc = strlen(word); if (utf8) { if (nc >= MAXWORDUTF8LEN) return 0; @@ -667,49 +693,94 @@ int Hunspell::suggest(char*** slst, const char * word) } int captype = 0; int abbv = 0; - int wl = cleanword2(cw, word, unicw, &nc, &captype, &abbv); + int wl = 0; + + // input conversion + RepList * rl = (pAMgr) ? pAMgr->get_iconvtable() : NULL; + if (rl && rl->conv(word, wspace)) wl = cleanword2(cw, wspace, unicw, &nc, &captype, &abbv); + else wl = cleanword2(cw, word, unicw, &nc, &captype, &abbv); + if (wl == 0) return 0; int ns = 0; - *slst = NULL; int capwords = 0; - int ngramsugs = 0; + // check capitalized form for FORCEUCASE + if (pAMgr && captype == NOCAP && pAMgr->get_forceucase()) { + int info = SPELL_ORIGCAP; + char ** wlst; + if (checkword(cw, &info, NULL)) { + if (*slst) { + wlst = *slst; + } else { + wlst = (char **) malloc(MAXSUGGESTION * sizeof(char *)); + if (wlst == NULL) return -1; + *slst = wlst; + for (int i = 0; i < MAXSUGGESTION; i++) { + wlst[i] = NULL; + } + } + wlst[0] = mystrdup(cw); + mkinitcap(wlst[0]); + return 1; + } + } + switch(captype) { - case NOCAP: { - ns = pSMgr->suggest(slst, cw, ns); + case NOCAP: { + ns = pSMgr->suggest(slst, cw, ns, &onlycmpdsug); break; } - case INITCAP: { + case INITCAP: { capwords = 1; - ns = pSMgr->suggest(slst, cw, ns); + ns = pSMgr->suggest(slst, cw, ns, &onlycmpdsug); if (ns == -1) break; memcpy(wspace,cw,(wl+1)); mkallsmall2(wspace, unicw, nc); - ns = pSMgr->suggest(slst, wspace, ns); + ns = pSMgr->suggest(slst, wspace, ns, &onlycmpdsug); break; } case HUHINITCAP: capwords = 1; - case HUHCAP: { - ns = pSMgr->suggest(slst, cw, ns); + case HUHCAP: { + ns = pSMgr->suggest(slst, cw, ns, &onlycmpdsug); if (ns != -1) { int prevns; + // something.The -> something. The + char * dot = strchr(cw, '.'); + if (dot && (dot > cw)) { + int captype_; + if (utf8) { + w_char w_[MAXWORDLEN]; + int wl_ = u8_u16(w_, MAXWORDLEN, dot + 1); + captype_ = get_captype_utf8(w_, wl_, langnum); + } else captype_ = get_captype(dot+1, strlen(dot+1), csconv); + if (captype_ == INITCAP) { + char * st = mystrdup(cw); + if (st) st = (char *) realloc(st, wl + 2); + if (st) { + st[(dot - cw) + 1] = ' '; + strcpy(st + (dot - cw) + 2, dot + 1); + ns = insert_sug(slst, st, ns); + free(st); + } + } + } if (captype == HUHINITCAP) { // TheOpenOffice.org -> The OpenOffice.org memcpy(wspace,cw,(wl+1)); mkinitsmall2(wspace, unicw, nc); - ns = pSMgr->suggest(slst, wspace, ns); + ns = pSMgr->suggest(slst, wspace, ns, &onlycmpdsug); } memcpy(wspace,cw,(wl+1)); mkallsmall2(wspace, unicw, nc); - insert_sug(slst, wspace, &ns); + if (spell(wspace)) ns = insert_sug(slst, wspace, ns); prevns = ns; - ns = pSMgr->suggest(slst, wspace, ns); + ns = pSMgr->suggest(slst, wspace, ns, &onlycmpdsug); if (captype == HUHINITCAP) { mkinitcap2(wspace, unicw, nc); - insert_sug(slst, wspace, &ns); - ns = pSMgr->suggest(slst, wspace, ns); + if (spell(wspace)) ns = insert_sug(slst, wspace, ns); + ns = pSMgr->suggest(slst, wspace, ns, &onlycmpdsug); } // aNew -> "a New" (instead of "a new") for (int j = prevns; j < ns; j++) { @@ -718,7 +789,7 @@ int Hunspell::suggest(char*** slst, const char * word) int slen = strlen(space + 1); // different case after space (need capitalisation) if ((slen < wl) && strcmp(cw + wl - slen, space + 1)) { - w_char w[MAXWORDLEN + 1]; + w_char w[MAXWORDLEN]; int wc = 0; char * r = (*slst)[j]; if (utf8) wc = u8_u16(w, MAXWORDLEN, space + 1); @@ -733,31 +804,32 @@ int Hunspell::suggest(char*** slst, const char * word) break; } - case ALLCAP: { + case ALLCAP: { memcpy(wspace, cw, (wl+1)); mkallsmall2(wspace, unicw, nc); - ns = pSMgr->suggest(slst, wspace, ns); + ns = pSMgr->suggest(slst, wspace, ns, &onlycmpdsug); if (ns == -1) break; - if (pAMgr && pAMgr->get_keepcase()) insert_sug(slst, wspace, &ns); + if (pAMgr && pAMgr->get_keepcase() && spell(wspace)) + ns = insert_sug(slst, wspace, ns); mkinitcap2(wspace, unicw, nc); - ns = pSMgr->suggest(slst, wspace, ns); + ns = pSMgr->suggest(slst, wspace, ns, &onlycmpdsug); for (int j=0; j < ns; j++) { mkallcap((*slst)[j]); if (pAMgr && pAMgr->get_checksharps()) { char * pos; if (utf8) { - pos = strstr((*slst)[j], "脽"); + pos = strstr((*slst)[j], "\xC3\x9F"); while (pos) { *pos = 'S'; *(pos+1) = 'S'; - pos = strstr(pos+2, "脽"); + pos = strstr(pos+2, "\xC3\x9F"); } } else { - pos = strchr((*slst)[j], '?'); + pos = strchr((*slst)[j], '\xDF'); while (pos) { (*slst)[j] = (char *) realloc((*slst)[j], strlen((*slst)[j]) + 2); - mystrrep((*slst)[j], "?", "SS"); - pos = strchr((*slst)[j], '?'); + mystrrep((*slst)[j], "\xDF", "SS"); + pos = strchr((*slst)[j], '\xDF'); } } } @@ -766,7 +838,7 @@ int Hunspell::suggest(char*** slst, const char * word) } } - // LANG_hu section: replace '-' with ' ' in Hungarian + // LANG_hu section: replace '-' with ' ' in Hungarian if (langnum == LANG_hu) { for (int j=0; j < ns; j++) { char * pos = strchr((*slst)[j],'-'); @@ -785,38 +857,78 @@ int Hunspell::suggest(char*** slst, const char * word) } // END OF LANG_hu section - // try ngram approach since found nothing - if ((ns == 0) && pAMgr && (pAMgr->get_maxngramsugs() != 0)) { - ngramsugs = 1; + // try ngram approach since found nothing or only compound words + if (pAMgr && (ns == 0 || onlycmpdsug) && (pAMgr->get_maxngramsugs() != 0) && (*slst)) { switch(captype) { case NOCAP: { - ns = pSMgr->ngsuggest(*slst, cw, pHMgr); + ns = pSMgr->ngsuggest(*slst, cw, ns, pHMgr, maxdic); break; } + case HUHINITCAP: + capwords = 1; case HUHCAP: { memcpy(wspace,cw,(wl+1)); mkallsmall2(wspace, unicw, nc); - ns = pSMgr->ngsuggest(*slst, wspace, pHMgr); - break; + ns = pSMgr->ngsuggest(*slst, wspace, ns, pHMgr, maxdic); + break; } - case INITCAP: { + case INITCAP: { capwords = 1; memcpy(wspace,cw,(wl+1)); mkallsmall2(wspace, unicw, nc); - ns = pSMgr->ngsuggest(*slst, wspace, pHMgr); + ns = pSMgr->ngsuggest(*slst, wspace, ns, pHMgr, maxdic); break; } case ALLCAP: { memcpy(wspace,cw,(wl+1)); mkallsmall2(wspace, unicw, nc); - ns = pSMgr->ngsuggest(*slst, wspace, pHMgr); - for (int j=0; j < ns; j++) + int oldns = ns; + ns = pSMgr->ngsuggest(*slst, wspace, ns, pHMgr, maxdic); + for (int j = oldns; j < ns; j++) mkallcap((*slst)[j]); break; } } } + // try dash suggestion (Afo-American -> Afro-American) + if (char * pos = strchr(cw, '-')) { + char * ppos = cw; + int nodashsug = 1; + char ** nlst = NULL; + int nn = 0; + int last = 0; + if (*slst) { + for (int j = 0; j < ns && nodashsug == 1; j++) { + if (strchr((*slst)[j], '-')) nodashsug = 0; + } + } + while (nodashsug && !last) { + if (*pos == '\0') last = 1; else *pos = '\0'; + if (!spell(ppos)) { + nn = suggest(&nlst, ppos); + for (int j = nn - 1; j >= 0; j--) { + strncpy(wspace, cw, ppos - cw); + strcpy(wspace + (ppos - cw), nlst[j]); + if (!last) { + strcat(wspace, "-"); + strcat(wspace, pos + 1); + } + ns = insert_sug(slst, wspace, ns); + free(nlst[j]); + } + if (nlst != NULL) free(nlst); + nodashsug = 0; + } + if (!last) { + *pos = '-'; + ppos = pos + 1; + pos = strchr(ppos, '-'); + } + if (!pos) pos = cw + strlen(cw); + } + } + // word reversing wrapper for complex prefixes if (complexprefixes) { for (int j = 0; j < ns; j++) { @@ -837,14 +949,14 @@ int Hunspell::suggest(char*** slst, const char * word) } } - // suggest keepcase - if (pAMgr->get_keepcase()) { + // remove bad capitalized and forbidden forms + if (pAMgr && (pAMgr->get_keepcase() || pAMgr->get_forbiddenword())) { switch (captype) { case INITCAP: case ALLCAP: { int l = 0; for (int j=0; j < ns; j++) { - if (!spell((*slst)[j])) { + if (!strchr((*slst)[j],' ') && !spell((*slst)[j])) { char s[MAXSWUTF8L]; w_char w[MAXSWL]; int len; @@ -855,21 +967,21 @@ int Hunspell::suggest(char*** slst, const char * word) len = strlen(s); } mkallsmall2(s, w, len); - free((*slst)[j]); + free((*slst)[j]); if (spell(s)) { (*slst)[l] = mystrdup(s); - l++; + if ((*slst)[l]) l++; } else { mkinitcap2(s, w, len); if (spell(s)) { (*slst)[l] = mystrdup(s); - l++; + if ((*slst)[l]) l++; } } } else { (*slst)[l] = (*slst)[j]; l++; - } + } } ns = l; } @@ -884,13 +996,34 @@ int Hunspell::suggest(char*** slst, const char * word) if (strcmp((*slst)[k], (*slst)[j]) == 0) { free((*slst)[j]); l--; + break; } } l++; } + ns = l; + + // output conversion + rl = (pAMgr) ? pAMgr->get_oconvtable() : NULL; + for (int j = 0; rl && j < ns; j++) { + if (rl->conv((*slst)[j], wspace)) { + free((*slst)[j]); + (*slst)[j] = mystrdup(wspace); + } + } + + // if suggestions removed by nosuggest, onlyincompound parameters + if (l == 0 && *slst) { + free(*slst); + *slst = NULL; + } return l; } +void Hunspell::free_list(char *** slst, int n) { + freelist(slst, n); +} + char * Hunspell::get_dic_encoding() { return encoding; @@ -900,9 +1033,9 @@ char * Hunspell::get_dic_encoding() // XXX need UTF-8 support int Hunspell::suggest_auto(char*** slst, const char * word) { - char cw[MAXWORDUTF8LEN + 4]; - char wspace[MAXWORDUTF8LEN + 4]; - if (! pSMgr) return 0; + char cw[MAXWORDUTF8LEN]; + char wspace[MAXWORDUTF8LEN]; + if (!pSMgr || maxdic == 0) return 0; int wl = strlen(word); if (utf8) { if (wl >= MAXWORDUTF8LEN) return 0; @@ -915,15 +1048,15 @@ int Hunspell::suggest_auto(char*** slst, const char * word) if (wl == 0) return 0; int ns = 0; *slst = NULL; // HU, nsug in pSMgr->suggest - + switch(captype) { - case NOCAP: { + case NOCAP: { ns = pSMgr->suggest_auto(slst, cw, ns); if (ns>0) break; break; } - case INITCAP: { + case INITCAP: { memcpy(wspace,cw,(wl+1)); mkallsmall(wspace); ns = pSMgr->suggest_auto(slst, wspace, ns); @@ -931,10 +1064,11 @@ int Hunspell::suggest_auto(char*** slst, const char * word) mkinitcap((*slst)[j]); ns = pSMgr->suggest_auto(slst, cw, ns); break; - + } - case HUHCAP: { + case HUHINITCAP: + case HUHCAP: { ns = pSMgr->suggest_auto(slst, cw, ns); if (ns == 0) { memcpy(wspace,cw,(wl+1)); @@ -944,7 +1078,7 @@ int Hunspell::suggest_auto(char*** slst, const char * word) break; } - case ALLCAP: { + case ALLCAP: { memcpy(wspace,cw,(wl+1)); mkallsmall(wspace); ns = pSMgr->suggest_auto(slst, wspace, ns); @@ -990,103 +1124,89 @@ int Hunspell::suggest_auto(char*** slst, const char * word) } } } - // END OF LANG_hu section + // END OF LANG_hu section return ns; } +#endif -// XXX need UTF-8 support -int Hunspell::stem(char*** slst, const char * word) +int Hunspell::stem(char*** slst, char ** desc, int n) { - char cw[MAXWORDUTF8LEN + 4]; - char wspace[MAXWORDUTF8LEN + 4]; - if (! pSMgr) return 0; - int wl = strlen(word); - if (utf8) { - if (wl >= MAXWORDUTF8LEN) return 0; - } else { - if (wl >= MAXWORDLEN) return 0; - } - int captype = 0; - int abbv = 0; - wl = cleanword(cw, word, &captype, &abbv); - if (wl == 0) return 0; - - int ns = 0; - - *slst = NULL; // HU, nsug in pSMgr->suggest - - switch(captype) { - case HUHCAP: - case NOCAP: { - ns = pSMgr->suggest_stems(slst, cw, ns); - - if ((abbv) && (ns == 0)) { - memcpy(wspace,cw,wl); - *(wspace+wl) = '.'; - *(wspace+wl+1) = '\0'; - ns = pSMgr->suggest_stems(slst, wspace, ns); - } - - break; - } - - case INITCAP: { - - ns = pSMgr->suggest_stems(slst, cw, ns); - - if (ns == 0) { - memcpy(wspace,cw,(wl+1)); - mkallsmall(wspace); - ns = pSMgr->suggest_stems(slst, wspace, ns); - - } - - if ((abbv) && (ns == 0)) { - memcpy(wspace,cw,wl); - mkallsmall(wspace); - *(wspace+wl) = '.'; - *(wspace+wl+1) = '\0'; - ns = pSMgr->suggest_stems(slst, wspace, ns); - } - - break; - - } - - case ALLCAP: { - ns = pSMgr->suggest_stems(slst, cw, ns); - if (ns != 0) break; - - memcpy(wspace,cw,(wl+1)); - mkallsmall(wspace); - ns = pSMgr->suggest_stems(slst, wspace, ns); - - if (ns == 0) { - mkinitcap(wspace); - ns = pSMgr->suggest_stems(slst, wspace, ns); - } + char result[MAXLNLEN]; + char result2[MAXLNLEN]; + *slst = NULL; + if (n == 0) return 0; + *result2 = '\0'; + for (int i = 0; i < n; i++) { + *result = '\0'; + // add compound word parts (except the last one) + char * s = (char *) desc[i]; + char * part = strstr(s, MORPH_PART); + if (part) { + char * nextpart = strstr(part + 1, MORPH_PART); + while (nextpart) { + copy_field(result + strlen(result), part, MORPH_PART); + part = nextpart; + nextpart = strstr(part + 1, MORPH_PART); + } + s = part; + } - if ((abbv) && (ns == 0)) { - memcpy(wspace,cw,wl); - mkallsmall(wspace); - *(wspace+wl) = '.'; - *(wspace+wl+1) = '\0'; - ns = pSMgr->suggest_stems(slst, wspace, ns); - } + char **pl; + char tok[MAXLNLEN]; + strcpy(tok, s); + char * alt = strstr(tok, " | "); + while (alt) { + alt[1] = MSEP_ALT; + alt = strstr(alt, " | "); + } + int pln = line_tok(tok, &pl, MSEP_ALT); + for (int k = 0; k < pln; k++) { + // add derivational suffixes + if (strstr(pl[k], MORPH_DERI_SFX)) { + // remove inflectional suffixes + char * is = strstr(pl[k], MORPH_INFL_SFX); + if (is) *is = '\0'; + char * sg = pSMgr->suggest_gen(&(pl[k]), 1, pl[k]); + if (sg) { + char ** gen; + int genl = line_tok(sg, &gen, MSEP_REC); + free(sg); + for (int j = 0; j < genl; j++) { + sprintf(result2 + strlen(result2), "%c%s%s", + MSEP_REC, result, gen[j]); + } + freelist(&gen, genl); + } + } else { + sprintf(result2 + strlen(result2), "%c%s", MSEP_REC, result); + if (strstr(pl[k], MORPH_SURF_PFX)) { + copy_field(result2 + strlen(result2), pl[k], MORPH_SURF_PFX); + } + copy_field(result2 + strlen(result2), pl[k], MORPH_STEM); + } + } + freelist(&pl, pln); + } + int sln = line_tok(result2, slst, MSEP_REC); + return uniqlist(*slst, sln); +} - break; - } - } - - return ns; +int Hunspell::stem(char*** slst, const char * word) +{ + char ** pl; + int pln = analyze(&pl, word); + int pln2 = stem(slst, pl, pln); + freelist(&pl, pln); + return pln2; } +#ifdef HUNSPELL_EXPERIMENTAL int Hunspell::suggest_pos_stems(char*** slst, const char * word) { - char cw[MAXWORDUTF8LEN + 4]; - char wspace[MAXWORDUTF8LEN + 4]; - if (! pSMgr) return 0; + char cw[MAXWORDUTF8LEN]; + char wspace[MAXWORDUTF8LEN]; + if (! pSMgr || maxdic == 0) return 0; int wl = strlen(word); if (utf8) { if (wl >= MAXWORDUTF8LEN) return 0; @@ -1097,14 +1217,14 @@ int Hunspell::suggest_pos_stems(char*** slst, const char * word) int abbv = 0; wl = cleanword(cw, word, &captype, &abbv); if (wl == 0) return 0; - + int ns = 0; // ns=0 = normalized input *slst = NULL; // HU, nsug in pSMgr->suggest - + switch(captype) { case HUHCAP: - case NOCAP: { + case NOCAP: { ns = pSMgr->suggest_pos_stems(slst, cw, ns); if ((abbv) && (ns == 0)) { @@ -1117,7 +1237,7 @@ int Hunspell::suggest_pos_stems(char*** slst, const char * word) break; } - case INITCAP: { + case INITCAP: { ns = pSMgr->suggest_pos_stems(slst, cw, ns); @@ -1126,15 +1246,15 @@ int Hunspell::suggest_pos_stems(char*** slst, const char * word) mkallsmall(wspace); ns = pSMgr->suggest_pos_stems(slst, wspace, ns); } - + break; - + } - case ALLCAP: { + case ALLCAP: { ns = pSMgr->suggest_pos_stems(slst, cw, ns); if (ns != 0) break; - + memcpy(wspace,cw,(wl+1)); mkallsmall(wspace); ns = pSMgr->suggest_pos_stems(slst, wspace, ns); @@ -1204,19 +1324,21 @@ int Hunspell::mkinitsmall2(char * p, w_char * u, int nc) return nc; } -int Hunspell::put_word(const char * word) +int Hunspell::add(const char * word) { - if (pHMgr) { - return pHMgr->put_word(word, strlen(word), NULL); - } + if (pHMgr[0]) return (pHMgr[0])->add(word); return 0; } -int Hunspell::put_word_pattern(const char * word, const char * pattern) +int Hunspell::add_with_affix(const char * word, const char * example) { - if (pHMgr) { - return pHMgr->put_word_pattern(word, strlen(word), pattern); - } + if (pHMgr[0]) return (pHMgr[0])->add_with_affix(word, example); + return 0; +} + +int Hunspell::remove(const char * word) +{ + if (pHMgr[0]) return (pHMgr[0])->remove(word); return 0; } @@ -1230,22 +1352,38 @@ struct cs_info * Hunspell::get_csconv() return csconv; } -#ifdef HUNSPELL_EXPERIMENTAL -// XXX need UTF-8 support -char * Hunspell::morph(const char * word) +void Hunspell::cat_result(char * result, char * st) { - char cw[MAXWORDUTF8LEN + 4]; - char wspace[MAXWORDUTF8LEN + 4]; - if (! pSMgr) return 0; - int wl = strlen(word); + if (st) { + if (*result) mystrcat(result, "\n", MAXLNLEN); + mystrcat(result, st, MAXLNLEN); + free(st); + } +} + +int Hunspell::analyze(char*** slst, const char * word) +{ + char cw[MAXWORDUTF8LEN]; + char wspace[MAXWORDUTF8LEN]; + w_char unicw[MAXWORDLEN]; + int wl2 = 0; + *slst = NULL; + if (! pSMgr || maxdic == 0) return 0; + int nc = strlen(word); if (utf8) { - if (wl >= MAXWORDUTF8LEN) return 0; + if (nc >= MAXWORDUTF8LEN) return 0; } else { - if (wl >= MAXWORDLEN) return 0; + if (nc >= MAXWORDLEN) return 0; } int captype = 0; int abbv = 0; - wl = cleanword(cw, word, &captype, &abbv); + int wl = 0; + + // input conversion + RepList * rl = (pAMgr) ? pAMgr->get_iconvtable() : NULL; + if (rl && rl->conv(word, wspace)) wl = cleanword2(cw, wspace, unicw, &nc, &captype, &abbv); + else wl = cleanword2(cw, word, unicw, &nc, &captype, &abbv); + if (wl == 0) { if (abbv) { for (wl = 0; wl < abbv; wl++) cw[wl] = '.'; @@ -1256,7 +1394,7 @@ char * Hunspell::morph(const char * word) char result[MAXLNLEN]; char * st = NULL; - + *result = '\0'; int n = 0; @@ -1266,177 +1404,102 @@ char * Hunspell::morph(const char * word) // test numbers // LANG_hu section: set dash information for suggestions if (langnum == LANG_hu) { - while ((n < wl) && + while ((n < wl) && (((cw[n] <= '9') && (cw[n] >= '0')) || (((cw[n] == '.') || (cw[n] == ',')) && (n > 0)))) { n++; if ((cw[n] == '.') || (cw[n] == ',')) { - if (((n2 == 0) && (n > 3)) || + if (((n2 == 0) && (n > 3)) || ((n2 > 0) && ((cw[n-1] == '.') || (cw[n-1] == ',')))) break; n2++; n3 = n; } } - if ((n == wl) && (n3 > 0) && (n - n3 > 3)) return NULL; - if ((n == wl) || ((n>0) && ((cw[n]=='%') || (cw[n]=='?)) && checkword(cw+n, NULL, NULL))) { - strcat(result, cw); + if ((n == wl) && (n3 > 0) && (n - n3 > 3)) return 0; + if ((n == wl) || ((n>0) && ((cw[n]=='%') || (cw[n]=='\xB0')) && checkword(cw+n, NULL, NULL))) { + mystrcat(result, cw, MAXLNLEN); result[n - 1] = '\0'; - if (n == wl) { - st = pSMgr->suggest_morph(cw + n - 1); - if (st) { - strcat(result, st); - free(st); - } - } else { + if (n == wl) cat_result(result, pSMgr->suggest_morph(cw + n - 1)); + else { char sign = cw[n]; cw[n] = '\0'; - st = pSMgr->suggest_morph(cw + n - 1); - if (st) { - strcat(result, st); - free(st); - } - strcat(result, "+"); // XXX SPEC. MORPHCODE + cat_result(result, pSMgr->suggest_morph(cw + n - 1)); + mystrcat(result, "+", MAXLNLEN); // XXX SPEC. MORPHCODE cw[n] = sign; - st = pSMgr->suggest_morph(cw + n); - if (st) { - strcat(result, st); - free(st); - } + cat_result(result, pSMgr->suggest_morph(cw + n)); } - return mystrdup(result); + return line_tok(result, slst, MSEP_REC); } } // END OF LANG_hu section - + switch(captype) { - case NOCAP: { - st = pSMgr->suggest_morph(cw); - if (st) { - strcat(result, st); - free(st); - } - if (abbv) { - memcpy(wspace,cw,wl); - *(wspace+wl) = '.'; - *(wspace+wl+1) = '\0'; - st = pSMgr->suggest_morph(wspace); - if (st) { - if (*result) strcat(result, "\n"); - strcat(result, st); - free(st); - } - } - break; - } - case INITCAP: { + case HUHCAP: + case HUHINITCAP: + case NOCAP: { + cat_result(result, pSMgr->suggest_morph(cw)); + if (abbv) { + memcpy(wspace,cw,wl); + *(wspace+wl) = '.'; + *(wspace+wl+1) = '\0'; + cat_result(result, pSMgr->suggest_morph(wspace)); + } + break; + } + case INITCAP: { + wl = mkallsmall2(cw, unicw, nc); memcpy(wspace,cw,(wl+1)); - mkallsmall(wspace); - st = pSMgr->suggest_morph(wspace); - if (st) { - strcat(result, st); - free(st); - } - st = pSMgr->suggest_morph(cw); - if (st) { - if (*result) strcat(result, "\n"); - strcat(result, st); - free(st); - } - if (abbv) { - memcpy(wspace,cw,wl); + wl2 = mkinitcap2(cw, unicw, nc); + cat_result(result, pSMgr->suggest_morph(wspace)); + cat_result(result, pSMgr->suggest_morph(cw)); + if (abbv) { *(wspace+wl) = '.'; *(wspace+wl+1) = '\0'; - mkallsmall(wspace); - st = pSMgr->suggest_morph(wspace); - if (st) { - if (*result) strcat(result, "\n"); - strcat(result, st); - free(st); - } - mkinitcap(wspace); - st = pSMgr->suggest_morph(wspace); - if (st) { - if (*result) strcat(result, "\n"); - strcat(result, st); - free(st); - } + cat_result(result, pSMgr->suggest_morph(wspace)); + + memcpy(wspace, cw, wl2); + *(wspace+wl2) = '.'; + *(wspace+wl2+1) = '\0'; + + cat_result(result, pSMgr->suggest_morph(wspace)); } break; } - case HUHCAP: { - st = pSMgr->suggest_morph(cw); - if (st) { - strcat(result, st); - free(st); - } -#if 0 - memcpy(wspace,cw,(wl+1)); - mkallsmall(wspace); - st = pSMgr->suggest_morph(wspace); - if (st) { - if (*result) strcat(result, "\n"); - strcat(result, st); - free(st); + case ALLCAP: { + cat_result(result, pSMgr->suggest_morph(cw)); + if (abbv) { + memcpy(wspace,cw,wl); + *(wspace+wl) = '.'; + *(wspace+wl+1) = '\0'; + cat_result(result, pSMgr->suggest_morph(cw)); } -#endif - break; - } - case ALLCAP: { + wl = mkallsmall2(cw, unicw, nc); memcpy(wspace,cw,(wl+1)); - st = pSMgr->suggest_morph(wspace); - if (st) { - strcat(result, st); - free(st); - } - mkallsmall(wspace); - st = pSMgr->suggest_morph(wspace); - if (st) { - if (*result) strcat(result, "\n"); - strcat(result, st); - free(st); - } - mkinitcap(wspace); - st = pSMgr->suggest_morph(wspace); - if (st) { - if (*result) strcat(result, "\n"); - strcat(result, st); - free(st); + wl2 = mkinitcap2(cw, unicw, nc); + + cat_result(result, pSMgr->suggest_morph(wspace)); + cat_result(result, pSMgr->suggest_morph(cw)); + if (abbv) { + *(wspace+wl) = '.'; + *(wspace+wl+1) = '\0'; + cat_result(result, pSMgr->suggest_morph(wspace)); + + memcpy(wspace, cw, wl2); + *(wspace+wl2) = '.'; + *(wspace+wl2+1) = '\0'; + + cat_result(result, pSMgr->suggest_morph(wspace)); } - if (abbv) { - memcpy(wspace,cw,(wl+1)); - *(wspace+wl) = '.'; - *(wspace+wl+1) = '\0'; - if (*result) strcat(result, "\n"); - st = pSMgr->suggest_morph(wspace); - if (st) { - strcat(result, st); - free(st); - } - mkallsmall(wspace); - st = pSMgr->suggest_morph(wspace); - if (st) { - if (*result) strcat(result, "\n"); - strcat(result, st); - free(st); - } - mkinitcap(wspace); - st = pSMgr->suggest_morph(wspace); - if (st) { - if (*result) strcat(result, "\n"); - strcat(result, st); - free(st); - } - } break; } } - if (result && (*result)) { + if (*result) { // word reversing wrapper for complex prefixes if (complexprefixes) { if (utf8) reverseword_utf(result); else reverseword(result); } - return mystrdup(result); + return line_tok(result, slst, MSEP_REC); } // compound word with dash (HU) I18n @@ -1445,24 +1508,32 @@ char * Hunspell::morph(const char * word) // LANG_hu section: set dash information for suggestions if (langnum == LANG_hu) dash = (char *) strchr(cw,'-'); if ((langnum == LANG_hu) && dash) { - *dash='\0'; + *dash='\0'; // examine 2 sides of the dash if (dash[1] == '\0') { // base word ending with dash - if (spell(cw)) return pSMgr->suggest_morph(cw); + if (spell(cw)) { + char * p = pSMgr->suggest_morph(cw); + if (p) { + int ret = line_tok(p, slst, MSEP_REC); + free(p); + return ret; + } + + } } else if ((dash[1] == 'e') && (dash[2] == '\0')) { // XXX (HU) -e hat. if (spell(cw) && (spell("-e"))) { st = pSMgr->suggest_morph(cw); if (st) { - strcat(result, st); + mystrcat(result, st, MAXLNLEN); free(st); } - strcat(result,"+"); // XXX spec. separator in MORPHCODE + mystrcat(result,"+", MAXLNLEN); // XXX spec. separator in MORPHCODE st = pSMgr->suggest_morph("-e"); if (st) { - strcat(result, st); + mystrcat(result, st, MAXLNLEN); free(st); } - return mystrdup(result); + return line_tok(result, slst, MSEP_REC); } } else { // first word ending with dash: word- XXX ??? @@ -1474,22 +1545,22 @@ char * Hunspell::morph(const char * word) dash[0]='\0'; if (nresult && spell(dash+1) && ((strlen(dash+1) > 1) || ((dash[1] > '0') && (dash[1] < '9')))) { - st = morph(cw); + st = pSMgr->suggest_morph(cw); if (st) { - strcat(result, st); + mystrcat(result, st, MAXLNLEN); free(st); - strcat(result,"+"); // XXX spec. separator in MORPHCODE + mystrcat(result,"+", MAXLNLEN); // XXX spec. separator in MORPHCODE } - st = morph(dash+1); + st = pSMgr->suggest_morph(dash+1); if (st) { - strcat(result, st); + mystrcat(result, st, MAXLNLEN); free(st); } - return mystrdup(result); + return line_tok(result, slst, MSEP_REC); } } // affixed number in correct word - if (nresult && (dash > cw) && (((*(dash-1)<='9') && + if (nresult && (dash > cw) && (((*(dash-1)<='9') && (*(dash-1)>='0')) || (*(dash-1)=='.'))) { *dash='-'; n = 1; @@ -1504,195 +1575,348 @@ char * Hunspell::morph(const char * word) // 56-hoz, 6-hoz for(; n >= 1; n--) { if ((*(dash - n) >= '0') && (*(dash - n) <= '9') && checkword(dash - n, NULL, NULL)) { - strcat(result, cw); + mystrcat(result, cw, MAXLNLEN); result[dash - cw - n] = '\0'; st = pSMgr->suggest_morph(dash - n); if (st) { - strcat(result, st); + mystrcat(result, st, MAXLNLEN); free(st); } - return mystrdup(result); + return line_tok(result, slst, MSEP_REC); } } } } - return NULL; + return 0; } +int Hunspell::generate(char*** slst, const char * word, char ** pl, int pln) +{ + *slst = NULL; + if (!pSMgr || !pln) return 0; + char **pl2; + int pl2n = analyze(&pl2, word); + int captype = 0; + int abbv = 0; + char cw[MAXWORDUTF8LEN]; + cleanword(cw, word, &captype, &abbv); + char result[MAXLNLEN]; + *result = '\0'; + + for (int i = 0; i < pln; i++) { + cat_result(result, pSMgr->suggest_gen(pl2, pl2n, pl[i])); + } + freelist(&pl2, pl2n); + + if (*result) { + // allcap + if (captype == ALLCAP) mkallcap(result); + + // line split + int linenum = line_tok(result, slst, MSEP_REC); + + // capitalize + if (captype == INITCAP || captype == HUHINITCAP) { + for (int j=0; j < linenum; j++) mkinitcap((*slst)[j]); + } + + // temporary filtering of prefix related errors (eg. + // generate("undrinkable", "eats") --> "undrinkables" and "*undrinks") + + int r = 0; + for (int j=0; j < linenum; j++) { + if (!spell((*slst)[j])) { + free((*slst)[j]); + (*slst)[j] = NULL; + } else { + if (r < j) (*slst)[r] = (*slst)[j]; + r++; + } + } + if (r > 0) return r; + free(*slst); + *slst = NULL; + } + return 0; +} + +int Hunspell::generate(char*** slst, const char * word, const char * pattern) +{ + char **pl; + int pln = analyze(&pl, pattern); + int n = generate(slst, word, pl, pln); + freelist(&pl, pln); + return uniqlist(*slst, n); +} + +// minimal XML parser functions +int Hunspell::get_xml_par(char * dest, const char * par, int max) +{ + char * d = dest; + if (!par) return 0; + char end = *par; + char * dmax = dest + max; + if (end == '>') end = '<'; + else if (end != '\'' && end != '"') return 0; // bad XML + for (par++; d < dmax && *par != '\0' && *par != end; par++, d++) *d = *par; + *d = '\0'; + mystrrep(dest, "<", "<"); + mystrrep(dest, "&", "&"); + return (int)(d - dest); +} + +int Hunspell::get_langnum() const +{ + return langnum; +} + +// return the beginning of the element (attr == NULL) or the attribute +const char * Hunspell::get_xml_pos(const char * s, const char * attr) +{ + const char * end = strchr(s, '>'); + const char * p = s; + if (attr == NULL) return end; + do { + p = strstr(p, attr); + if (!p || p >= end) return 0; + } while (*(p-1) != ' ' && *(p-1) != '\n'); + return p + strlen(attr); +} + +int Hunspell::check_xml_par(const char * q, const char * attr, const char * value) { + char cw[MAXWORDUTF8LEN]; + if (get_xml_par(cw, get_xml_pos(q, attr), MAXWORDUTF8LEN - 1) && + strcmp(cw, value) == 0) return 1; + return 0; +} + +int Hunspell::get_xml_list(char ***slst, char * list, const char * tag) { + int n = 0; + char * p; + if (!list) return 0; + for (p = list; (p = strstr(p, tag)); p++) n++; + if (n == 0) return 0; + *slst = (char **) malloc(sizeof(char *) * n); + if (!*slst) return 0; + for (p = list, n = 0; (p = strstr(p, tag)); p++, n++) { + int l = strlen(p); + (*slst)[n] = (char *) malloc(l + 1); + if (!(*slst)[n]) return n; + if (!get_xml_par((*slst)[n], p + strlen(tag) - 1, l)) { + free((*slst)[n]); + break; + } + } + return n; +} + +int Hunspell::spellml(char*** slst, const char * word) +{ + char *q, *q2; + char cw[MAXWORDUTF8LEN], cw2[MAXWORDUTF8LEN]; + q = (char *) strstr(word, "'); + if (!q2) return 0; // bad XML input + q2 = strstr(q2, "'), MAXWORDUTF8LEN - 10)) n = analyze(slst, cw); + if (n == 0) return 0; + // convert the result to ana1ana2 format + for (int i = 0; i < n; i++) s+= strlen((*slst)[i]); + char * r = (char *) malloc(6 + 5 * s + 7 * n + 7 + 1); // XXX 5*s->&->& + if (!r) return 0; + strcpy(r, ""); + for (int i = 0; i < n; i++) { + int l = strlen(r); + strcpy(r + l, ""); + strcpy(r + l + 3, (*slst)[i]); + mystrrep(r + l + 3, "\t", " "); + mystrrep(r + l + 3, "<", "<"); + mystrrep(r + l + 3, "&", "&"); + strcat(r, ""); + free((*slst)[i]); + } + strcat(r, ""); + (*slst)[0] = r; + return 1; + } else if (check_xml_par(q, "type=", "stem")) { + if (get_xml_par(cw, strchr(q2, '>'), MAXWORDUTF8LEN - 1)) return stem(slst, cw); + } else if (check_xml_par(q, "type=", "generate")) { + int n = get_xml_par(cw, strchr(q2, '>'), MAXWORDUTF8LEN - 1); + if (n == 0) return 0; + char * q3 = strstr(q2 + 1, "'), MAXWORDUTF8LEN - 1)) { + return generate(slst, cw, cw2); + } + } else { + if ((q2 = strstr(q2 + 1, "'), ""))) { + int n2 = generate(slst, cw, slst2, n); + freelist(&slst2, n); + return uniqlist(*slst, n2); + } + freelist(&slst2, n); + } + } + } + return 0; +} + + +#ifdef HUNSPELL_EXPERIMENTAL // XXX need UTF-8 support char * Hunspell::morph_with_correction(const char * word) { - char cw[MAXWORDUTF8LEN + 4]; - char wspace[MAXWORDUTF8LEN + 4]; - if (! pSMgr) return 0; + char cw[MAXWORDUTF8LEN]; + char wspace[MAXWORDUTF8LEN]; + if (! pSMgr || maxdic == 0) return NULL; int wl = strlen(word); if (utf8) { - if (wl >= MAXWORDUTF8LEN) return 0; + if (wl >= MAXWORDUTF8LEN) return NULL; } else { - if (wl >= MAXWORDLEN) return 0; + if (wl >= MAXWORDLEN) return NULL; } int captype = 0; int abbv = 0; wl = cleanword(cw, word, &captype, &abbv); - if (wl == 0) return 0; + if (wl == 0) return NULL; char result[MAXLNLEN]; char * st = NULL; - + *result = '\0'; - - + + switch(captype) { - case NOCAP: { + case NOCAP: { st = pSMgr->suggest_morph_for_spelling_error(cw); if (st) { - strcat(result, st); + mystrcat(result, st, MAXLNLEN); free(st); } - if (abbv) { - memcpy(wspace,cw,wl); + if (abbv) { + memcpy(wspace,cw,wl); *(wspace+wl) = '.'; *(wspace+wl+1) = '\0'; st = pSMgr->suggest_morph_for_spelling_error(wspace); if (st) { - if (*result) strcat(result, "\n"); - strcat(result, st); + if (*result) mystrcat(result, "\n", MAXLNLEN); + mystrcat(result, st, MAXLNLEN); free(st); } } break; } - case INITCAP: { + case INITCAP: { memcpy(wspace,cw,(wl+1)); mkallsmall(wspace); st = pSMgr->suggest_morph_for_spelling_error(wspace); if (st) { - strcat(result, st); + mystrcat(result, st, MAXLNLEN); free(st); - } - st = pSMgr->suggest_morph_for_spelling_error(cw); + } + st = pSMgr->suggest_morph_for_spelling_error(cw); if (st) { - if (*result) strcat(result, "\n"); - strcat(result, st); + if (*result) mystrcat(result, "\n", MAXLNLEN); + mystrcat(result, st, MAXLNLEN); free(st); } - if (abbv) { - memcpy(wspace,cw,wl); + if (abbv) { + memcpy(wspace,cw,wl); *(wspace+wl) = '.'; *(wspace+wl+1) = '\0'; mkallsmall(wspace); st = pSMgr->suggest_morph_for_spelling_error(wspace); if (st) { - if (*result) strcat(result, "\n"); - strcat(result, st); + if (*result) mystrcat(result, "\n", MAXLNLEN); + mystrcat(result, st, MAXLNLEN); free(st); - } + } mkinitcap(wspace); st = pSMgr->suggest_morph_for_spelling_error(wspace); if (st) { - if (*result) strcat(result, "\n"); - strcat(result, st); + if (*result) mystrcat(result, "\n", MAXLNLEN); + mystrcat(result, st, MAXLNLEN); free(st); - } + } } break; } - case HUHCAP: { + case HUHCAP: { st = pSMgr->suggest_morph_for_spelling_error(cw); if (st) { - strcat(result, st); + mystrcat(result, st, MAXLNLEN); free(st); } memcpy(wspace,cw,(wl+1)); mkallsmall(wspace); st = pSMgr->suggest_morph_for_spelling_error(wspace); if (st) { - if (*result) strcat(result, "\n"); - strcat(result, st); + if (*result) mystrcat(result, "\n", MAXLNLEN); + mystrcat(result, st, MAXLNLEN); free(st); - } + } break; } - case ALLCAP: { + case ALLCAP: { memcpy(wspace,cw,(wl+1)); st = pSMgr->suggest_morph_for_spelling_error(wspace); if (st) { - strcat(result, st); + mystrcat(result, st, MAXLNLEN); free(st); - } + } mkallsmall(wspace); st = pSMgr->suggest_morph_for_spelling_error(wspace); if (st) { - if (*result) strcat(result, "\n"); - strcat(result, st); + if (*result) mystrcat(result, "\n", MAXLNLEN); + mystrcat(result, st, MAXLNLEN); free(st); } - mkinitcap(wspace); - st = pSMgr->suggest_morph_for_spelling_error(wspace); + mkinitcap(wspace); + st = pSMgr->suggest_morph_for_spelling_error(wspace); if (st) { - if (*result) strcat(result, "\n"); - strcat(result, st); + if (*result) mystrcat(result, "\n", MAXLNLEN); + mystrcat(result, st, MAXLNLEN); free(st); } - if (abbv) { + if (abbv) { memcpy(wspace,cw,(wl+1)); *(wspace+wl) = '.'; *(wspace+wl+1) = '\0'; - if (*result) strcat(result, "\n"); + if (*result) mystrcat(result, "\n", MAXLNLEN); st = pSMgr->suggest_morph_for_spelling_error(wspace); if (st) { - strcat(result, st); - free(st); - } + mystrcat(result, st, MAXLNLEN); + free(st); + } mkallsmall(wspace); st = pSMgr->suggest_morph_for_spelling_error(wspace); if (st) { - if (*result) strcat(result, "\n"); - strcat(result, st); + if (*result) mystrcat(result, "\n", MAXLNLEN); + mystrcat(result, st, MAXLNLEN); free(st); } - mkinitcap(wspace); - st = pSMgr->suggest_morph_for_spelling_error(wspace); + mkinitcap(wspace); + st = pSMgr->suggest_morph_for_spelling_error(wspace); if (st) { - if (*result) strcat(result, "\n"); - strcat(result, st); + if (*result) mystrcat(result, "\n", MAXLNLEN); + mystrcat(result, st, MAXLNLEN); free(st); } - } + } break; } } - if (result) return mystrdup(result); + if (*result) return mystrdup(result); return NULL; } -/* analyze word - * return line count - * XXX need a better data structure for morphological analysis */ -int Hunspell::analyze(char ***out, const char *word) { - int n = 0; - if (!word) return 0; - char * m = morph(word); - if(!m) return 0; - if (!out) return line_tok(m, out); - - // without memory allocation - /* BUG missing buffer size checking */ - int i, p; - for(p = 0, i = 0; m[i]; i++) { - if(m[i] == '\n' || !m[i+1]) { - n++; - strncpy((*out)[n++], m + p, i - p + 1); - if (m[i] == '\n') (*out)[n++][i - p] = '\0'; - if(!m[i+1]) break; - p = i + 1; - } - } - free(m); - return n; -} - #endif // END OF HUNSPELL_EXPERIMENTAL CODE Hunhandle *Hunspell_create(const char * affpath, const char * dpath) @@ -1700,6 +1924,12 @@ Hunhandle *Hunspell_create(const char * affpath, const char * dpath) return (Hunhandle*)(new Hunspell(affpath, dpath)); } +Hunhandle *Hunspell_create_key(const char * affpath, const char * dpath, + const char * key) +{ + return (Hunhandle*)(new Hunspell(affpath, dpath, key)); +} + void Hunspell_destroy(Hunhandle *pHunspell) { delete (Hunspell*)(pHunspell); @@ -1720,3 +1950,57 @@ int Hunspell_suggest(Hunhandle *pHunspell, char*** slst, const char * word) return ((Hunspell*)pHunspell)->suggest(slst, word); } +int Hunspell_analyze(Hunhandle *pHunspell, char*** slst, const char * word) +{ + return ((Hunspell*)pHunspell)->analyze(slst, word); +} + +int Hunspell_stem(Hunhandle *pHunspell, char*** slst, const char * word) +{ + return ((Hunspell*)pHunspell)->stem(slst, word); +} + +int Hunspell_stem2(Hunhandle *pHunspell, char*** slst, char** desc, int n) +{ + return ((Hunspell*)pHunspell)->stem(slst, desc, n); +} + +int Hunspell_generate(Hunhandle *pHunspell, char*** slst, const char * word, + const char * word2) +{ + return ((Hunspell*)pHunspell)->generate(slst, word, word2); +} + +int Hunspell_generate2(Hunhandle *pHunspell, char*** slst, const char * word, + char** desc, int n) +{ + return ((Hunspell*)pHunspell)->generate(slst, word, desc, n); +} + + /* functions for run-time modification of the dictionary */ + + /* add word to the run-time dictionary */ + +int Hunspell_add(Hunhandle *pHunspell, const char * word) { + return ((Hunspell*)pHunspell)->add(word); +} + + /* add word to the run-time dictionary with affix flags of + * the example (a dictionary word): Hunspell will recognize + * affixed forms of the new word, too. + */ + +int Hunspell_add_with_affix(Hunhandle *pHunspell, const char * word, + const char * example) { + return ((Hunspell*)pHunspell)->add_with_affix(word, example); +} + + /* remove word from the run-time dictionary */ + +int Hunspell_remove(Hunhandle *pHunspell, const char * word) { + return ((Hunspell*)pHunspell)->remove(word); +} + +void Hunspell_free_list(Hunhandle *, char *** slst, int n) { + freelist(slst, n); +} diff --git a/ext/hunspell/hunspell.h b/ext/hunspell/hunspell.h index 3cf237b1a..cc22c9623 100644 --- a/ext/hunspell/hunspell.h +++ b/ext/hunspell/hunspell.h @@ -1,21 +1,27 @@ #ifndef _MYSPELLMGR_H_ #define _MYSPELLMGR_H_ +#include "hunvisapi.h" + #ifdef __cplusplus extern "C" { #endif typedef struct Hunhandle Hunhandle; -Hunhandle *Hunspell_create(const char * affpath, const char * dpath); -void Hunspell_destroy(Hunhandle *pHunspell); +LIBHUNSPELL_DLL_EXPORTED Hunhandle *Hunspell_create(const char * affpath, const char * dpath); + +LIBHUNSPELL_DLL_EXPORTED Hunhandle *Hunspell_create_key(const char * affpath, const char * dpath, + const char * key); + +LIBHUNSPELL_DLL_EXPORTED void Hunspell_destroy(Hunhandle *pHunspell); /* spell(word) - spellcheck word * output: 0 = bad word, not 0 = good word */ -int Hunspell_spell(Hunhandle *pHunspell, const char *); +LIBHUNSPELL_DLL_EXPORTED int Hunspell_spell(Hunhandle *pHunspell, const char *); -char *Hunspell_get_dic_encoding(Hunhandle *pHunspell); +LIBHUNSPELL_DLL_EXPORTED char *Hunspell_get_dic_encoding(Hunhandle *pHunspell); /* suggest(suggestions, word) - search suggestions * input: pointer to an array of strings pointer and the (bad) word @@ -24,7 +30,63 @@ char *Hunspell_get_dic_encoding(Hunhandle *pHunspell); * a newly allocated array of strings (*slts will be NULL when number * of suggestion equals 0.) */ -int Hunspell_suggest(Hunhandle *pHunspell, char*** slst, const char * word); +LIBHUNSPELL_DLL_EXPORTED int Hunspell_suggest(Hunhandle *pHunspell, char*** slst, const char * word); + + /* morphological functions */ + + /* analyze(result, word) - morphological analysis of the word */ + +LIBHUNSPELL_DLL_EXPORTED int Hunspell_analyze(Hunhandle *pHunspell, char*** slst, const char * word); + + /* stem(result, word) - stemmer function */ + +LIBHUNSPELL_DLL_EXPORTED int Hunspell_stem(Hunhandle *pHunspell, char*** slst, const char * word); + + /* stem(result, analysis, n) - get stems from a morph. analysis + * example: + * char ** result, result2; + * int n1 = Hunspell_analyze(result, "words"); + * int n2 = Hunspell_stem2(result2, result, n1); + */ + +LIBHUNSPELL_DLL_EXPORTED int Hunspell_stem2(Hunhandle *pHunspell, char*** slst, char** desc, int n); + + /* generate(result, word, word2) - morphological generation by example(s) */ + +LIBHUNSPELL_DLL_EXPORTED int Hunspell_generate(Hunhandle *pHunspell, char*** slst, const char * word, + const char * word2); + + /* generate(result, word, desc, n) - generation by morph. description(s) + * example: + * char ** result; + * char * affix = "is:plural"; // description depends from dictionaries, too + * int n = Hunspell_generate2(result, "word", &affix, 1); + * for (int i = 0; i < n; i++) printf("%s\n", result[i]); + */ + +LIBHUNSPELL_DLL_EXPORTED int Hunspell_generate2(Hunhandle *pHunspell, char*** slst, const char * word, + char** desc, int n); + + /* functions for run-time modification of the dictionary */ + + /* add word to the run-time dictionary */ + +LIBHUNSPELL_DLL_EXPORTED int Hunspell_add(Hunhandle *pHunspell, const char * word); + + /* add word to the run-time dictionary with affix flags of + * the example (a dictionary word): Hunspell will recognize + * affixed forms of the new word, too. + */ + +LIBHUNSPELL_DLL_EXPORTED int Hunspell_add_with_affix(Hunhandle *pHunspell, const char * word, const char * example); + + /* remove word from the run-time dictionary */ + +LIBHUNSPELL_DLL_EXPORTED int Hunspell_remove(Hunhandle *pHunspell, const char * word); + + /* free suggestion lists */ + +LIBHUNSPELL_DLL_EXPORTED void Hunspell_free_list(Hunhandle *pHunspell, char *** slst, int n); #ifdef __cplusplus } diff --git a/ext/hunspell/hunspell.hxx b/ext/hunspell/hunspell.hxx index 7df4cb654..9b6c38810 100644 --- a/ext/hunspell/hunspell.hxx +++ b/ext/hunspell/hunspell.hxx @@ -1,41 +1,29 @@ -#include "license.hunspell" -#include "license.myspell" +#include "hunvisapi.h" #include "hashmgr.hxx" #include "affixmgr.hxx" #include "suggestmgr.hxx" -#include "csutil.hxx" #include "langnum.hxx" -#include "config.h" -#define SPELL_COMPOUND (1 << 0) -#define SPELL_FORBIDDEN (1 << 1) - -#define NOCAP 0 -#define INITCAP 1 -#define ALLCAP 2 -#define HUHCAP 3 -#define HUHINITCAP 4 +#define SPELL_XML "" +#define MAXDIC 20 #define MAXSUGGESTION 15 #define MAXSHARPS 5 -#ifdef W32 -#define DLLTEST2_API __declspec(dllexport) -#endif +#define HUNSPELL_OK (1 << 0) +#define HUNSPELL_OK_WARN (1 << 1) #ifndef _MYSPELLMGR_HXX_ #define _MYSPELLMGR_HXX_ -#ifdef W32 -class DLLTEST2_API Hunspell -#else -class Hunspell -#endif +class LIBHUNSPELL_DLL_EXPORTED Hunspell { AffixMgr* pAMgr; - HashMgr* pHMgr; + HashMgr* pHMgr[MAXDIC]; + int maxdic; SuggestMgr* pSMgr; + char * affixpath; char * encoding; struct cs_info * csconv; int langnum; @@ -48,11 +36,13 @@ public: /* Hunspell(aff, dic) - constructor of Hunspell class * input: path of affix file and dictionary file */ - - Hunspell(const char * affpath, const char * dpath); + Hunspell(const char * affpath, const char * dpath, const char * key = NULL); ~Hunspell(); + /* load extra dictionaries (only dic files) */ + int add_dic(const char * dpath, const char * key = NULL); + /* spell(word) - spellcheck word * output: 0 = bad word, not 0 = good word * @@ -74,17 +64,62 @@ public: */ int suggest(char*** slst, const char * word); + + /* deallocate suggestion lists */ + + void free_list(char *** slst, int n); + char * get_dic_encoding(); - /* handling custom dictionary */ + /* morphological functions */ + + /* analyze(result, word) - morphological analysis of the word */ + + int analyze(char*** slst, const char * word); + + /* stem(result, word) - stemmer function */ + + int stem(char*** slst, const char * word); - int put_word(const char * word); + /* stem(result, analysis, n) - get stems from a morph. analysis + * example: + * char ** result, result2; + * int n1 = analyze(&result, "words"); + * int n2 = stem(&result2, result, n1); + */ + + int stem(char*** slst, char ** morph, int n); + + /* generate(result, word, word2) - morphological generation by example(s) */ + + int generate(char*** slst, const char * word, const char * word2); + + /* generate(result, word, desc, n) - generation by morph. description(s) + * example: + * char ** result; + * char * affix = "is:plural"; // description depends from dictionaries, too + * int n = generate(&result, "word", &affix, 1); + * for (int i = 0; i < n; i++) printf("%s\n", result[i]); + */ - /* pattern is a sample dictionary word - * put word into custom dictionary with affix flags of pattern word + int generate(char*** slst, const char * word, char ** desc, int n); + + /* functions for run-time modification of the dictionary */ + + /* add word to the run-time dictionary */ + + int add(const char * word); + + /* add word to the run-time dictionary with affix flags of + * the example (a dictionary word): Hunspell will recognize + * affixed forms of the new word, too. */ - int put_word_pattern(const char * word, const char * pattern); + int add_with_affix(const char * word, const char * example); + + /* remove word from the run-time dictionary */ + + int remove(const char * word); /* other */ @@ -95,28 +130,18 @@ public: struct cs_info * get_csconv(); const char * get_version(); - /* experimental functions */ + int get_langnum() const; + + /* experimental and deprecated functions */ #ifdef HUNSPELL_EXPERIMENTAL - /* suffix is an affix flag string, similarly in dictionary files */ - + /* suffix is an affix flag string, similarly in dictionary files */ int put_word_suffix(const char * word, const char * suffix); - - /* morphological analysis */ - - char * morph(const char * word); - int analyze(char*** out, const char *word); - char * morph_with_correction(const char * word); - /* stemmer function */ - - int stem(char*** slst, const char * word); - /* spec. suggestions */ int suggest_auto(char*** slst, const char * word); int suggest_pos_stems(char*** slst, const char * word); - char * get_possible_root(); #endif private: @@ -133,7 +158,14 @@ private: char * sharps_u8_l1(char * dest, char * source); hentry * spellsharps(char * base, char *, int, int, char * tmp, int * info, char **root); int is_keepcase(const hentry * rv); - int insert_sug(char ***slst, char * word, int *ns); + int insert_sug(char ***slst, char * word, int ns); + void cat_result(char * result, char * st); + char * stem_description(const char * desc); + int spellml(char*** slst, const char * word); + int get_xml_par(char * dest, const char * par, int maxl); + const char * get_xml_pos(const char * s, const char * attr); + int get_xml_list(char ***slst, char * list, const char * tag); + int check_xml_par(const char * q, const char * attr, const char * value); }; diff --git a/ext/hunspell/hunspell.vcxproj b/ext/hunspell/hunspell.vcxproj index 91e90ecd1..693436cfb 100644 --- a/ext/hunspell/hunspell.vcxproj +++ b/ext/hunspell/hunspell.vcxproj @@ -21,6 +21,7 @@ {12E5B4AE-D7EF-4A57-A22D-6F9F9D8CE1FB} hunspell + Win32Proj @@ -74,30 +75,34 @@ - _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + HUNSPELL_STATIC;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 4100;4244;4267;%(DisableSpecificWarnings) NotUsing + TurnOffAllWarnings - _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + HUNSPELL_STATIC;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 4100;4244;4267;%(DisableSpecificWarnings) NotUsing + TurnOffAllWarnings - _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + HUNSPELL_STATIC;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 4100;4244;4267;%(DisableSpecificWarnings) NotUsing + TurnOffAllWarnings - _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + HUNSPELL_STATIC;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 4100;4244;4267;%(DisableSpecificWarnings) NotUsing + TurnOffAllWarnings @@ -105,24 +110,35 @@ + + + + + + + + + + + diff --git a/ext/hunspell/hunspell.vcxproj.filters b/ext/hunspell/hunspell.vcxproj.filters index 8a91d80f7..3d6d76101 100644 --- a/ext/hunspell/hunspell.vcxproj.filters +++ b/ext/hunspell/hunspell.vcxproj.filters @@ -23,15 +23,27 @@ Source Files + + Source Files + Source Files Source Files + + Source Files + Source Files + + Source Files + + + Source Files + Source Files @@ -49,29 +61,50 @@ Header Files + + Header Files + Header Files Header Files + + Header Files + Header Files Header Files + + Header Files + Header Files + + Header Files + Header Files Header Files + + Header Files + Header Files + + Header Files + + + Header Files + \ No newline at end of file diff --git a/ext/hunspell/hunvisapi.h b/ext/hunspell/hunvisapi.h new file mode 100644 index 000000000..a642e8c74 --- /dev/null +++ b/ext/hunspell/hunvisapi.h @@ -0,0 +1,18 @@ +#ifndef _HUNSPELL_VISIBILITY_H_ +#define _HUNSPELL_VISIBILITY_H_ + +#if defined(HUNSPELL_STATIC) +# define LIBHUNSPELL_DLL_EXPORTED +#elif defined(_MSC_VER) +# if defined(BUILDING_LIBHUNSPELL) +# define LIBHUNSPELL_DLL_EXPORTED __declspec(dllexport) +# else +# define LIBHUNSPELL_DLL_EXPORTED __declspec(dllimport) +# endif +#elif BUILDING_LIBHUNSPELL && 1 +# define LIBHUNSPELL_DLL_EXPORTED __attribute__((__visibility__("default"))) +#else +# define LIBHUNSPELL_DLL_EXPORTED +#endif + +#endif diff --git a/ext/hunspell/hunvisapi.h.in b/ext/hunspell/hunvisapi.h.in new file mode 100644 index 000000000..9c7f1b7b1 --- /dev/null +++ b/ext/hunspell/hunvisapi.h.in @@ -0,0 +1,18 @@ +#ifndef _HUNSPELL_VISIBILITY_H_ +#define _HUNSPELL_VISIBILITY_H_ + +#if defined(HUNSPELL_STATIC) +# define LIBHUNSPELL_DLL_EXPORTED +#elif defined(_MSC_VER) +# if defined(BUILDING_LIBHUNSPELL) +# define LIBHUNSPELL_DLL_EXPORTED __declspec(dllexport) +# else +# define LIBHUNSPELL_DLL_EXPORTED __declspec(dllimport) +# endif +#elif BUILDING_LIBHUNSPELL && @HAVE_VISIBILITY@ +# define LIBHUNSPELL_DLL_EXPORTED __attribute__((__visibility__("default"))) +#else +# define LIBHUNSPELL_DLL_EXPORTED +#endif + +#endif diff --git a/ext/hunspell/hunzip.cxx b/ext/hunspell/hunzip.cxx new file mode 100644 index 000000000..ac77028e6 --- /dev/null +++ b/ext/hunspell/hunzip.cxx @@ -0,0 +1,193 @@ +#include +#include +#include + +#include "hunzip.hxx" + +#define CODELEN 65536 +#define BASEBITREC 5000 + +#define UNCOMPRESSED '\002' +#define MAGIC "hz0" +#define MAGIC_ENCRYPT "hz1" +#define MAGICLEN (sizeof(MAGIC) - 1) + +int Hunzip::fail(const char * err, const char * par) { + fprintf(stderr, err, par); + return -1; +} + +Hunzip::Hunzip(const char * file, const char * key) { + bufsiz = 0; + lastbit = 0; + inc = 0; + outc = 0; + dec = NULL; + fin = NULL; + filename = (char *) malloc(strlen(file) + 1); + if (filename) strcpy(filename, file); + if (getcode(key) == -1) bufsiz = -1; + else bufsiz = getbuf(); +} + +int Hunzip::getcode(const char * key) { + unsigned char c[2]; + int i, j, n, p; + int allocatedbit = BASEBITREC; + const char * enc = key; + + if (!filename) return -1; + + fin = fopen(filename, "rb"); + if (!fin) return -1; + + // read magic number + if ((fread(in, 1, 3, fin) < MAGICLEN) + || !(strncmp(MAGIC, in, MAGICLEN) == 0 || + strncmp(MAGIC_ENCRYPT, in, MAGICLEN) == 0)) { + return fail(MSG_FORMAT, filename); + } + + // check encryption + if (strncmp(MAGIC_ENCRYPT, in, MAGICLEN) == 0) { + unsigned char cs; + if (!key) return fail(MSG_KEY, filename); + if (fread(&c, 1, 1, fin) < 1) return fail(MSG_FORMAT, filename); + for (cs = 0; *enc; enc++) cs ^= *enc; + if (cs != c[0]) return fail(MSG_KEY, filename); + enc = key; + } else key = NULL; + + // read record count + if (fread(&c, 1, 2, fin) < 2) return fail(MSG_FORMAT, filename); + + if (key) { + c[0] ^= *enc; + if (*(++enc) == '\0') enc = key; + c[1] ^= *enc; + } + + n = ((int) c[0] << 8) + c[1]; + dec = (struct bit *) malloc(BASEBITREC * sizeof(struct bit)); + if (!dec) return fail(MSG_MEMORY, filename); + dec[0].v[0] = 0; + dec[0].v[1] = 0; + + // read codes + for (i = 0; i < n; i++) { + unsigned char l; + if (fread(c, 1, 2, fin) < 2) return fail(MSG_FORMAT, filename); + if (key) { + if (*(++enc) == '\0') enc = key; + c[0] ^= *enc; + if (*(++enc) == '\0') enc = key; + c[1] ^= *enc; + } + if (fread(&l, 1, 1, fin) < 1) return fail(MSG_FORMAT, filename); + if (key) { + if (*(++enc) == '\0') enc = key; + l ^= *enc; + } + if (fread(in, 1, l/8+1, fin) < (size_t) l/8+1) return fail(MSG_FORMAT, filename); + if (key) for (j = 0; j <= l/8; j++) { + if (*(++enc) == '\0') enc = key; + in[j] ^= *enc; + } + p = 0; + for (j = 0; j < l; j++) { + int b = (in[j/8] & (1 << (7 - (j % 8)))) ? 1 : 0; + int oldp = p; + p = dec[p].v[b]; + if (p == 0) { + lastbit++; + if (lastbit == allocatedbit) { + allocatedbit += BASEBITREC; + dec = (struct bit *) realloc(dec, allocatedbit * sizeof(struct bit)); + } + dec[lastbit].v[0] = 0; + dec[lastbit].v[1] = 0; + dec[oldp].v[b] = lastbit; + p = lastbit; + } + } + dec[p].c[0] = c[0]; + dec[p].c[1] = c[1]; + } + return 0; +} + +Hunzip::~Hunzip() +{ + if (dec) free(dec); + if (fin) fclose(fin); + if (filename) free(filename); +} + +int Hunzip::getbuf() { + int p = 0; + int o = 0; + do { + if (inc == 0) inbits = fread(in, 1, BUFSIZE, fin) * 8; + for (; inc < inbits; inc++) { + int b = (in[inc / 8] & (1 << (7 - (inc % 8)))) ? 1 : 0; + int oldp = p; + p = dec[p].v[b]; + if (p == 0) { + if (oldp == lastbit) { + fclose(fin); + fin = NULL; + // add last odd byte + if (dec[lastbit].c[0]) out[o++] = dec[lastbit].c[1]; + return o; + } + out[o++] = dec[oldp].c[0]; + out[o++] = dec[oldp].c[1]; + if (o == BUFSIZE) return o; + p = dec[p].v[b]; + } + } + inc = 0; + } while (inbits == BUFSIZE * 8); + return fail(MSG_FORMAT, filename); +} + +const char * Hunzip::getline() { + char linebuf[BUFSIZE]; + int l = 0, eol = 0, left = 0, right = 0; + if (bufsiz == -1) return NULL; + while (l < bufsiz && !eol) { + linebuf[l++] = out[outc]; + switch (out[outc]) { + case '\t': break; + case 31: { // escape + if (++outc == bufsiz) { + bufsiz = getbuf(); + outc = 0; + } + linebuf[l - 1] = out[outc]; + break; + } + case ' ': break; + default: if (((unsigned char) out[outc]) < 47) { + if (out[outc] > 32) { + right = out[outc] - 31; + if (++outc == bufsiz) { + bufsiz = getbuf(); + outc = 0; + } + } + if (out[outc] == 30) left = 9; else left = out[outc]; + linebuf[l-1] = '\n'; + eol = 1; + } + } + if (++outc == bufsiz) { + outc = 0; + bufsiz = fin ? getbuf(): -1; + } + } + if (right) strcpy(linebuf + l - 1, line + strlen(line) - right - 1); + else linebuf[l] = '\0'; + strcpy(line + left, linebuf); + return line; +} diff --git a/ext/hunspell/hunzip.hxx b/ext/hunspell/hunzip.hxx new file mode 100644 index 000000000..b58e3ab1d --- /dev/null +++ b/ext/hunspell/hunzip.hxx @@ -0,0 +1,45 @@ +/* hunzip: file decompression for sorted dictionaries with optional encryption, + * algorithm: prefix-suffix encoding and 16-bit Huffman encoding */ + +#ifndef _HUNZIP_HXX_ +#define _HUNZIP_HXX_ + +#include "hunvisapi.h" + +#include + +#define BUFSIZE 65536 +#define HZIP_EXTENSION ".hz" + +#define MSG_OPEN "error: %s: cannot open\n" +#define MSG_FORMAT "error: %s: not in hzip format\n" +#define MSG_MEMORY "error: %s: missing memory\n" +#define MSG_KEY "error: %s: missing or bad password\n" + +struct bit { + unsigned char c[2]; + int v[2]; +}; + +class LIBHUNSPELL_DLL_EXPORTED Hunzip +{ + +protected: + char * filename; + FILE * fin; + int bufsiz, lastbit, inc, inbits, outc; + struct bit * dec; // code table + char in[BUFSIZE]; // input buffer + char out[BUFSIZE + 1]; // Huffman-decoded buffer + char line[BUFSIZE + 50]; // decoded line + int getcode(const char * key); + int getbuf(); + int fail(const char * err, const char * par); + +public: + Hunzip(const char * filename, const char * key = NULL); + ~Hunzip(); + const char * getline(); +}; + +#endif diff --git a/ext/hunspell/license.hunspell b/ext/hunspell/license.hunspell index 57614c964..41e30fba5 100644 --- a/ext/hunspell/license.hunspell +++ b/ext/hunspell/license.hunspell @@ -1,4 +1,4 @@ -/* ***** BEGIN LICENSE BLOCK ***** +/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version @@ -14,7 +14,7 @@ * The Original Code is Hunspell, based on MySpell. * * The Initial Developers of the Original Code are - * Kevin Hendricks (MySpell) and Németh László (Hunspell). + * Kevin Hendricks (MySpell) and Laszlo Nemeth (Hunspell). * Portions created by the Initial Developers are Copyright (C) 2002-2005 * the Initial Developers. All Rights Reserved. * @@ -24,21 +24,23 @@ * Giuseppe Modugno * Gianluca Turconi * Simon Brouwer - * Noll János - * Bíró Árpád - * Goldman Eleonóra - * Sarlós Tamás - * Bencsáth Boldizsár - * Halácsy Péter - * Dvornik László - * Gefferth András + * Noll Janos + * Biro Arpad + * Goldman Eleonora + * Sarlos Tamas + * Bencsath Boldizsar + * Halacsy Peter + * Dvornik Laszlo + * Gefferth Andras * Nagy Viktor - * Varga Dániel + * Varga Daniel * Chris Halls * Rene Engelhard * Bram Moolenaar * Dafydd Jones - * Harri Pitkänen + * Harri Pitkanen + * Andras Timar + * Tor Lillqvist * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -53,3 +55,5 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ + +#include "config.h" diff --git a/ext/hunspell/phonet.cxx b/ext/hunspell/phonet.cxx new file mode 100644 index 000000000..442ec2e03 --- /dev/null +++ b/ext/hunspell/phonet.cxx @@ -0,0 +1,292 @@ +/* phonetic.c - generic replacement aglogithms for phonetic transformation + Copyright (C) 2000 Bjoern Jacke + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation; + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; If not, see + . + + Changelog: + + 2000-01-05 Bjoern Jacke + Initial Release insprired by the article about phonetic + transformations out of c't 25/1999 + + 2007-07-26 Bjoern Jacke + Released under MPL/GPL/LGPL tri-license for Hunspell + + 2007-08-23 Laszlo Nemeth + Porting from Aspell to Hunspell using C-like structs +*/ + +#include +#include +#include +#include + +#include "csutil.hxx" +#include "phonet.hxx" + +void init_phonet_hash(phonetable & parms) + { + int i, k; + + for (i = 0; i < HASHSIZE; i++) { + parms.hash[i] = -1; + } + + for (i = 0; parms.rules[i][0] != '\0'; i += 2) { + /** set hash value **/ + k = (unsigned char) parms.rules[i][0]; + + if (parms.hash[k] < 0) { + parms.hash[k] = i; + } + } + } + +// like strcpy but safe if the strings overlap +// but only if dest < src +static inline void strmove(char * dest, char * src) { + while (*src) + *dest++ = *src++; + *dest = '\0'; +} + +static int myisalpha(char ch) { + if ((unsigned char) ch < 128) return isalpha(ch); + return 1; +} + +/* phonetic transcription algorithm */ +/* see: http://aspell.net/man-html/Phonetic-Code.html */ +/* convert string to uppercase before this call */ +int phonet (const char * inword, char * target, + int len, + phonetable & parms) + { + /** Do phonetic transformation. **/ + /** "len" = length of "inword" incl. '\0'. **/ + + /** result: >= 0: length of "target" **/ + /** otherwise: error **/ + + int i,j,k=0,n,p,z; + int k0,n0,p0=-333,z0; + char c, c0; + const char * s; + typedef unsigned char uchar; + char word[MAXPHONETUTF8LEN + 1]; + if (len == -1) len = strlen(inword); + if (len > MAXPHONETUTF8LEN) return 0; + strcpy(word, inword); + + /** check word **/ + i = j = z = 0; + while ((c = word[i]) != '\0') { + n = parms.hash[(uchar) c]; + z0 = 0; + + if (n >= 0) { + /** check all rules for the same letter **/ + while (parms.rules[n][0] == c) { + + /** check whole string **/ + k = 1; /** number of found letters **/ + p = 5; /** default priority **/ + s = parms.rules[n]; + s++; /** important for (see below) "*(s-1)" **/ + + while (*s != '\0' && word[i+k] == *s + && !isdigit ((unsigned char) *s) && strchr ("(-<^$", *s) == NULL) { + k++; + s++; + } + if (*s == '(') { + /** check letters in "(..)" **/ + if (myisalpha(word[i+k]) // ...could be implied? + && strchr(s+1, word[i+k]) != NULL) { + k++; + while (*s != ')') + s++; + s++; + } + } + p0 = (int) *s; + k0 = k; + while (*s == '-' && k > 1) { + k--; + s++; + } + if (*s == '<') + s++; + if (isdigit ((unsigned char) *s)) { + /** determine priority **/ + p = *s - '0'; + s++; + } + if (*s == '^' && *(s+1) == '^') + s++; + + if (*s == '\0' + || (*s == '^' + && (i == 0 || ! myisalpha(word[i-1])) + && (*(s+1) != '$' + || (! myisalpha(word[i+k0]) ))) + || (*s == '$' && i > 0 + && myisalpha(word[i-1]) + && (! myisalpha(word[i+k0]) ))) + { + /** search for followup rules, if: **/ + /** parms.followup and k > 1 and NO '-' in searchstring **/ + c0 = word[i+k-1]; + n0 = parms.hash[(uchar) c0]; + +// if (parms.followup && k > 1 && n0 >= 0 + if (k > 1 && n0 >= 0 + && p0 != (int) '-' && word[i+k] != '\0') { + /** test follow-up rule for "word[i+k]" **/ + while (parms.rules[n0][0] == c0) { + + /** check whole string **/ + k0 = k; + p0 = 5; + s = parms.rules[n0]; + s++; + while (*s != '\0' && word[i+k0] == *s + && ! isdigit((unsigned char) *s) && strchr("(-<^$",*s) == NULL) { + k0++; + s++; + } + if (*s == '(') { + /** check letters **/ + if (myisalpha(word[i+k0]) + && strchr (s+1, word[i+k0]) != NULL) { + k0++; + while (*s != ')' && *s != '\0') + s++; + if (*s == ')') + s++; + } + } + while (*s == '-') { + /** "k0" gets NOT reduced **/ + /** because "if (k0 == k)" **/ + s++; + } + if (*s == '<') + s++; + if (isdigit ((unsigned char) *s)) { + p0 = *s - '0'; + s++; + } + + if (*s == '\0' + /** *s == '^' cuts **/ + || (*s == '$' && ! myisalpha(word[i+k0]))) + { + if (k0 == k) { + /** this is just a piece of the string **/ + n0 += 2; + continue; + } + + if (p0 < p) { + /** priority too low **/ + n0 += 2; + continue; + } + /** rule fits; stop search **/ + break; + } + n0 += 2; + } /** End of "while (parms.rules[n0][0] == c0)" **/ + + if (p0 >= p && parms.rules[n0][0] == c0) { + n += 2; + continue; + } + } /** end of follow-up stuff **/ + + /** replace string **/ + s = parms.rules[n+1]; + p0 = (parms.rules[n][0] != '\0' + && strchr (parms.rules[n]+1,'<') != NULL) ? 1:0; + if (p0 == 1 && z == 0) { + /** rule with '<' is used **/ + if (j > 0 && *s != '\0' + && (target[j-1] == c || target[j-1] == *s)) { + j--; + } + z0 = 1; + z = 1; + k0 = 0; + while (*s != '\0' && word[i+k0] != '\0') { + word[i+k0] = *s; + k0++; + s++; + } + if (k > k0) + strmove (&word[0]+i+k0, &word[0]+i+k); + + /** new "actual letter" **/ + c = word[i]; + } + else { /** no '<' rule used **/ + i += k - 1; + z = 0; + while (*s != '\0' + && *(s+1) != '\0' && j < len) { + if (j == 0 || target[j-1] != *s) { + target[j] = *s; + j++; + } + s++; + } + /** new "actual letter" **/ + c = *s; + if (parms.rules[n][0] != '\0' + && strstr (parms.rules[n]+1, "^^") != NULL) { + if (c != '\0') { + target[j] = c; + j++; + } + strmove (&word[0], &word[0]+i+1); + i = 0; + z0 = 1; + } + } + break; + } /** end of follow-up stuff **/ + n += 2; + } /** end of while (parms.rules[n][0] == c) **/ + } /** end of if (n >= 0) **/ + if (z0 == 0) { +// if (k && (assert(p0!=-333),!p0) && j < len && c != '\0' +// && (!parms.collapse_result || j == 0 || target[j-1] != c)){ + if (k && !p0 && j < len && c != '\0' + && (1 || j == 0 || target[j-1] != c)){ + /** condense only double letters **/ + target[j] = c; + ///printf("\n setting \n"); + j++; + } + + i++; + z = 0; + k=0; + } + } /** end of while ((c = word[i]) != '\0') **/ + + target[j] = '\0'; + return (j); + + } /** end of function "phonet" **/ diff --git a/ext/hunspell/phonet.hxx b/ext/hunspell/phonet.hxx new file mode 100644 index 000000000..f91d3b02b --- /dev/null +++ b/ext/hunspell/phonet.hxx @@ -0,0 +1,52 @@ +/* phonetic.c - generic replacement aglogithms for phonetic transformation + Copyright (C) 2000 Bjoern Jacke + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation; + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; If not, see + . + + Changelog: + + 2000-01-05 Bjoern Jacke + Initial Release insprired by the article about phonetic + transformations out of c't 25/1999 + + 2007-07-26 Bjoern Jacke + Released under MPL/GPL/LGPL tri-license for Hunspell + + 2007-08-23 Laszlo Nemeth + Porting from Aspell to Hunspell using C-like structs +*/ + +#ifndef __PHONETHXX__ +#define __PHONETHXX__ + +#define HASHSIZE 256 +#define MAXPHONETLEN 256 +#define MAXPHONETUTF8LEN (MAXPHONETLEN * 4) + +#include "hunvisapi.h" + +struct phonetable { + char utf8; + cs_info * lang; + int num; + char * * rules; + int hash[HASHSIZE]; +}; + +LIBHUNSPELL_DLL_EXPORTED void init_phonet_hash(phonetable & parms); + +LIBHUNSPELL_DLL_EXPORTED int phonet (const char * inword, char * target, + int len, phonetable & phone); + +#endif diff --git a/ext/hunspell/replist.cxx b/ext/hunspell/replist.cxx new file mode 100644 index 000000000..ca05cc181 --- /dev/null +++ b/ext/hunspell/replist.cxx @@ -0,0 +1,87 @@ +#include "license.hunspell" +#include "license.myspell" + +#include +#include +#include + +#include "replist.hxx" +#include "csutil.hxx" + +RepList::RepList(int n) { + dat = (replentry **) malloc(sizeof(replentry *) * n); + if (dat == 0) size = 0; else size = n; + pos = 0; +} + +RepList::~RepList() +{ + for (int i = 0; i < pos; i++) { + free(dat[i]->pattern); + free(dat[i]->pattern2); + free(dat[i]); + } + free(dat); +} + +int RepList::get_pos() { + return pos; +} + +replentry * RepList::item(int n) { + return dat[n]; +} + +int RepList::near(const char * word) { + int p1 = 0; + int p2 = pos; + while ((p2 - p1) > 1) { + int m = (p1 + p2) / 2; + int c = strcmp(word, dat[m]->pattern); + if (c <= 0) { + if (c < 0) p2 = m; else p1 = p2 = m; + } else p1 = m; + } + return p1; +} + +int RepList::match(const char * word, int n) { + if (strncmp(word, dat[n]->pattern, strlen(dat[n]->pattern)) == 0) return strlen(dat[n]->pattern); + return 0; +} + +int RepList::add(char * pat1, char * pat2) { + if (pos >= size || pat1 == NULL || pat2 == NULL) return 1; + replentry * r = (replentry *) malloc(sizeof(replentry)); + if (r == NULL) return 1; + r->pattern = mystrrep(pat1, "_", " "); + r->pattern2 = mystrrep(pat2, "_", " "); + r->start = false; + r->end = false; + dat[pos++] = r; + for (int i = pos - 1; i > 0; i--) { + r = dat[i]; + if (strcmp(r->pattern, dat[i - 1]->pattern) < 0) { + dat[i] = dat[i - 1]; + dat[i - 1] = r; + } else break; + } + return 0; +} + +int RepList::conv(const char * word, char * dest) { + int stl = 0; + int change = 0; + for (size_t i = 0; i < strlen(word); i++) { + int n = near(word + i); + int l = match(word + i, n); + if (l) { + strcpy(dest + stl, dat[n]->pattern2); + stl += strlen(dat[n]->pattern2); + i += l - 1; + change = 1; + } else dest[stl++] = word[i]; + } + dest[stl] = '\0'; + return change; +} diff --git a/ext/hunspell/replist.hxx b/ext/hunspell/replist.hxx new file mode 100644 index 000000000..9d24c4612 --- /dev/null +++ b/ext/hunspell/replist.hxx @@ -0,0 +1,27 @@ +/* string replacement list class */ +#ifndef _REPLIST_HXX_ +#define _REPLIST_HXX_ + +#include "hunvisapi.h" + +#include "w_char.hxx" +#undef near // TortoiseSVN custom: this is needed to prevent errors +class LIBHUNSPELL_DLL_EXPORTED RepList +{ +protected: + replentry ** dat; + int size; + int pos; + +public: + RepList(int n); + ~RepList(); + + int get_pos(); + int add(char * pat1, char * pat2); + replentry * item(int n); + int near(const char * word); + int match(const char * word, int n); + int conv(const char * word, char * dest); +}; +#endif diff --git a/ext/hunspell/suggestmgr.cxx b/ext/hunspell/suggestmgr.cxx index 22488d2d9..c55b19c78 100644 --- a/ext/hunspell/suggestmgr.cxx +++ b/ext/hunspell/suggestmgr.cxx @@ -1,26 +1,16 @@ #include "license.hunspell" #include "license.myspell" -#ifndef MOZILLA_CLIENT -#include -#include -#include -#include -#else #include #include #include #include -#endif #include "suggestmgr.hxx" +#include "htypes.hxx" +#include "csutil.hxx" -#ifndef MOZILLA_CLIENT -#ifndef W32 -using namespace std; -#endif -#endif - +const w_char W_VLINE = { '\0', '|' }; SuggestMgr::SuggestMgr(const char * tryme, int maxn, AffixMgr * aptr) @@ -30,36 +20,64 @@ SuggestMgr::SuggestMgr(const char * tryme, int maxn, // try when building candidate suggestions pAMgr = aptr; + csconv = NULL; + + ckeyl = 0; + ckey = NULL; + ckey_utf = NULL; + ctryl = 0; ctry = NULL; ctry_utf = NULL; + utf8 = 0; + langnum = 0; + complexprefixes = 0; + maxSug = maxn; nosplitsugs = 0; maxngramsugs = MAXNGRAMSUGS; - - utf8 = 0; - complexprefixes = 0; + maxcpdsugs = MAXCOMPOUNDSUGS; if (pAMgr) { - char * enc = pAMgr->get_encoding(); - csconv = get_current_cs(enc); - free(enc); + langnum = pAMgr->get_langnum(); + ckey = pAMgr->get_key_string(); nosplitsugs = pAMgr->get_nosplitsugs(); - if (pAMgr->get_maxngramsugs() >= 0) maxngramsugs = pAMgr->get_maxngramsugs(); + if (pAMgr->get_maxngramsugs() >= 0) + maxngramsugs = pAMgr->get_maxngramsugs(); utf8 = pAMgr->get_utf8(); + if (pAMgr->get_maxcpdsugs() >= 0) + maxcpdsugs = pAMgr->get_maxcpdsugs(); + if (!utf8) + { + char * enc = pAMgr->get_encoding(); + csconv = get_current_cs(enc); + free(enc); + } complexprefixes = pAMgr->get_complexprefixes(); } - if (tryme) { + if (ckey) { if (utf8) { w_char t[MAXSWL]; + ckeyl = u8_u16(t, MAXSWL, ckey); + ckey_utf = (w_char *) malloc(ckeyl * sizeof(w_char)); + if (ckey_utf) memcpy(ckey_utf, t, ckeyl * sizeof(w_char)); + else ckeyl = 0; + } else { + ckeyl = strlen(ckey); + } + } + + if (tryme) { + ctry = mystrdup(tryme); + if (ctry) ctryl = strlen(ctry); + if (ctry && utf8) { + w_char t[MAXSWL]; ctryl = u8_u16(t, MAXSWL, tryme); ctry_utf = (w_char *) malloc(ctryl * sizeof(w_char)); - memcpy(ctry_utf, t, ctryl * sizeof(w_char)); - } else { - ctry = mystrdup(tryme); - ctryl = strlen(ctry); + if (ctry_utf) memcpy(ctry_utf, t, ctryl * sizeof(w_char)); + else ctryl = 0; } } } @@ -68,16 +86,24 @@ SuggestMgr::SuggestMgr(const char * tryme, int maxn, SuggestMgr::~SuggestMgr() { pAMgr = NULL; + if (ckey) free(ckey); + ckey = NULL; + if (ckey_utf) free(ckey_utf); + ckey_utf = NULL; + ckeyl = 0; if (ctry) free(ctry); ctry = NULL; if (ctry_utf) free(ctry_utf); ctry_utf = NULL; ctryl = 0; maxSug = 0; +#ifdef MOZILLA_CLIENT + delete [] csconv; +#endif } int SuggestMgr::testsug(char** wlst, const char * candidate, int wl, int ns, int cpdsuggest, - int * timer, time_t * timelimit) { + int * timer, clock_t * timelimit) { int cwrd = 1; if (ns == maxSug) return maxSug; for (int k=0; k < ns; k++) { @@ -94,18 +120,21 @@ int SuggestMgr::testsug(char** wlst, const char * candidate, int wl, int ns, int return ns; } -// generate suggestions for a mispelled word +// generate suggestions for a misspelled word // pass in address of array of char * pointers +// onlycompoundsug: probably bad suggestions (need for ngram sugs, too) -int SuggestMgr::suggest(char*** slst, const char * w, int nsug) +int SuggestMgr::suggest(char*** slst, const char * w, int nsug, + int * onlycompoundsug) { - int nocompoundtwowords = 0; - char ** wlst; - w_char word_utf[MAXSWL]; - int wl = 0; - + int nocompoundtwowords = 0; + char ** wlst; + w_char word_utf[MAXSWL]; + int wl = 0; + int nsugorig = nsug; char w2[MAXWORDUTF8LEN]; const char * word = w; + int oldSug = 0; // word reversing wrapper for complex prefixes if (complexprefixes) { @@ -126,10 +155,17 @@ int SuggestMgr::suggest(char*** slst, const char * w, int nsug) if (utf8) { wl = u8_u16(word_utf, MAXSWL, word); + if (wl == -1) { + *slst = wlst; + return nsug; + } } for (int cpdsuggest=0; (cpdsuggest<2) && (nocompoundtwowords==0); cpdsuggest++) { + // limit compound suggestion + if (cpdsuggest > 0) oldSug = nsug; + // suggestions for an uppercase word (html -> HTML) if ((nsug < maxSug) && (nsug > -1)) { nsug = (utf8) ? capchars_utf(wlst, word_utf, wl, nsug, cpdsuggest) : @@ -137,64 +173,71 @@ int SuggestMgr::suggest(char*** slst, const char * w, int nsug) } // perhaps we made a typical fault of spelling - if ((nsug < maxSug) && (nsug > -1)) - nsug = replchars(wlst, word, nsug, cpdsuggest); + if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) { + nsug = replchars(wlst, word, nsug, cpdsuggest); + } // perhaps we made chose the wrong char from a related set - if ((nsug < maxSug) && (nsug > -1) && (cpdsuggest == 0)) { - nsug = mapchars(wlst, word, nsug); + if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) { + nsug = mapchars(wlst, word, nsug, cpdsuggest); } + // only suggest compound words when no other suggestion + if ((cpdsuggest == 0) && (nsug > nsugorig)) nocompoundtwowords=1; + // did we swap the order of chars by mistake - if ((nsug < maxSug) && (nsug > -1)) { + if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) { nsug = (utf8) ? swapchar_utf(wlst, word_utf, wl, nsug, cpdsuggest) : swapchar(wlst, word, nsug, cpdsuggest); } // did we swap the order of non adjacent chars by mistake - if ((nsug < maxSug) && (nsug > -1)) { + if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) { nsug = (utf8) ? longswapchar_utf(wlst, word_utf, wl, nsug, cpdsuggest) : longswapchar(wlst, word, nsug, cpdsuggest); } + // did we just hit the wrong key in place of a good char (case and keyboard) + if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) { + nsug = (utf8) ? badcharkey_utf(wlst, word_utf, wl, nsug, cpdsuggest) : + badcharkey(wlst, word, nsug, cpdsuggest); + } + + // did we add a char that should not be there + if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) { + nsug = (utf8) ? extrachar_utf(wlst, word_utf, wl, nsug, cpdsuggest) : + extrachar(wlst, word, nsug, cpdsuggest); + } + + // did we forgot a char - if ((nsug < maxSug) && (nsug > -1)) { + if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) { nsug = (utf8) ? forgotchar_utf(wlst, word_utf, wl, nsug, cpdsuggest) : forgotchar(wlst, word, nsug, cpdsuggest); } // did we move a char - if ((nsug < maxSug) && (nsug > -1)) { + if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) { nsug = (utf8) ? movechar_utf(wlst, word_utf, wl, nsug, cpdsuggest) : movechar(wlst, word, nsug, cpdsuggest); } - // did we add a char that should not be there - if ((nsug < maxSug) && (nsug > -1)) { - nsug = (utf8) ? extrachar_utf(wlst, word_utf, wl, nsug, cpdsuggest) : - extrachar(wlst, word, nsug, cpdsuggest); - } - // did we just hit the wrong key in place of a good char - if ((nsug < maxSug) && (nsug > -1)) { + if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) { nsug = (utf8) ? badchar_utf(wlst, word_utf, wl, nsug, cpdsuggest) : badchar(wlst, word, nsug, cpdsuggest); } // did we double two characters - if ((nsug < maxSug) && (nsug > -1)) { + if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) { nsug = (utf8) ? doubletwochars_utf(wlst, word_utf, wl, nsug, cpdsuggest) : doubletwochars(wlst, word, nsug, cpdsuggest); } - - // only suggest compound words when no other suggestion - if ((cpdsuggest==0) && (nsug>0)) nocompoundtwowords=1; - // perhaps we forgot to hit space and two words ran together - if ((!nosplitsugs) && (nsug < maxSug) && (nsug > -1)) { - nsug = twowords(wlst, word, nsug, cpdsuggest); - } + if (!nosplitsugs && (nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) { + nsug = twowords(wlst, word, nsug, cpdsuggest); + } } // repeating ``for'' statement compounding support @@ -206,6 +249,8 @@ int SuggestMgr::suggest(char*** slst, const char * w, int nsug) wlst = NULL; } + if (!nocompoundtwowords && (nsug > 0) && onlycompoundsug) *onlycompoundsug = 1; + *slst = wlst; return nsug; } @@ -217,6 +262,7 @@ int SuggestMgr::suggest_auto(char*** slst, const char * w, int nsug) { int nocompoundtwowords = 0; char ** wlst; + int oldSug; char w2[MAXWORDUTF8LEN]; const char * word = w; @@ -237,19 +283,22 @@ int SuggestMgr::suggest_auto(char*** slst, const char * w, int nsug) for (int cpdsuggest=0; (cpdsuggest<2) && (nocompoundtwowords==0); cpdsuggest++) { + // limit compound suggestion + if (cpdsuggest > 0) oldSug = nsug; + // perhaps we made a typical fault of spelling if ((nsug < maxSug) && (nsug > -1)) nsug = replchars(wlst, word, nsug, cpdsuggest); // perhaps we made chose the wrong char from a related set - if ((nsug < maxSug) && (nsug > -1) && (cpdsuggest == 0)) - nsug = mapchars(wlst, word, nsug); + if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs))) + nsug = mapchars(wlst, word, nsug, cpdsuggest); if ((cpdsuggest==0) && (nsug>0)) nocompoundtwowords=1; // perhaps we forgot to hit space and two words ran together - if ((nsug < maxSug) && (nsug > -1) && check_forbidden(word, strlen(word))) { + if ((nsug < maxSug) && (nsug > -1) && (!cpdsuggest || (nsug < oldSug + maxcpdsugs)) && check_forbidden(word, strlen(word))) { nsug = twowords(wlst, word, nsug, cpdsuggest); } @@ -273,7 +322,7 @@ int SuggestMgr::capchars_utf(char ** wlst, const w_char * word, int wl, int ns, char candidate[MAXSWUTF8L]; w_char candidate_utf[MAXSWL]; memcpy(candidate_utf, word, wl * sizeof(w_char)); - mkallcap_utf(candidate_utf, wl, pAMgr->get_langnum()); + mkallcap_utf(candidate_utf, wl, langnum); u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl); return testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL); } @@ -288,11 +337,13 @@ int SuggestMgr::capchars(char** wlst, const char * word, int ns, int cpdsuggest) } // suggestions for when chose the wrong char out of a related set -int SuggestMgr::mapchars(char** wlst, const char * word, int ns) +int SuggestMgr::mapchars(char** wlst, const char * word, int ns, int cpdsuggest) { - time_t timelimit; + char candidate[MAXSWUTF8L]; + clock_t timelimit; int timer; - + candidate[0] = '\0'; + int wl = strlen(word); if (wl < 2 || ! pAMgr) return ns; @@ -300,70 +351,24 @@ int SuggestMgr::mapchars(char** wlst, const char * word, int ns) struct mapentry* maptable = pAMgr->get_maptable(); if (maptable==NULL) return ns; - timelimit = time(NULL); + timelimit = clock(); timer = MINTIMER; - if (utf8) { - w_char w[MAXSWL]; - int len = u8_u16(w, MAXSWL, word); - ns = map_related_utf(w, len, 0, wlst, ns, maptable, nummap, &timer, &timelimit); - } else ns = map_related(word, 0, wlst, ns, maptable, nummap, &timer, &timelimit); - return ns; -} - -int SuggestMgr::map_related(const char * word, int i, char** wlst, int ns, - const mapentry* maptable, int nummap, int * timer, time_t * timelimit) -{ - char c = *(word + i); - if (c == 0) { - int cwrd = 1; - int wl = strlen(word); - for (int m=0; m < ns; m++) - if (strcmp(word,wlst[m]) == 0) cwrd = 0; - if ((cwrd) && (checkword(word, wl, 0, timer, timelimit) || - checkword(word, wl, 1, timer, timelimit))) { - if (ns < maxSug) { - wlst[ns] = mystrdup(word); - if (wlst[ns] == NULL) return -1; - ns++; - } - } - return ns; - } - int in_map = 0; - for (int j = 0; j < nummap; j++) { - if (strchr(maptable[j].set,c) != 0) { - in_map = 1; - char * newword = mystrdup(word); - for (int k = 0; k < maptable[j].len; k++) { - *(newword + i) = *(maptable[j].set + k); - ns = map_related(newword, (i+1), wlst, ns, maptable, nummap, timer, timelimit); - if (!(*timelimit)) return ns; - } - free(newword); - } - } - if (!in_map) { - i++; - ns = map_related(word, i, wlst, ns, maptable, nummap, timer, timelimit); - } - return ns; + return map_related(word, (char *) &candidate, 0, 0, wlst, cpdsuggest, ns, maptable, nummap, &timer, &timelimit); } -int SuggestMgr::map_related_utf(w_char * word, int len, int i, char** wlst, int ns, - const mapentry* maptable, int nummap, int * timer, time_t * timelimit) +int SuggestMgr::map_related(const char * word, char * candidate, int wn, int cn, + char** wlst, int cpdsuggest, int ns, + const mapentry* maptable, int nummap, int * timer, clock_t * timelimit) { - if (i == len) { + if (*(word + wn) == '\0') { int cwrd = 1; - int wl; - char s[MAXSWUTF8L]; - u16_u8(s, MAXSWUTF8L, word, len); - wl = strlen(s); + *(candidate + cn) = '\0'; + int wl = strlen(candidate); for (int m=0; m < ns; m++) - if (strcmp(s,wlst[m]) == 0) cwrd = 0; - if ((cwrd) && (checkword(s, wl, 0, timer, timelimit) || - checkword(s, wl, 1, timer, timelimit))) { + if (strcmp(candidate, wlst[m]) == 0) cwrd = 0; + if ((cwrd) && checkword(candidate, wl, cpdsuggest, timer, timelimit)) { if (ns < maxSug) { - wlst[ns] = mystrdup(s); + wlst[ns] = mystrdup(candidate); if (wlst[ns] == NULL) return -1; ns++; } @@ -371,27 +376,28 @@ int SuggestMgr::map_related_utf(w_char * word, int len, int i, char** wlst, int return ns; } int in_map = 0; - unsigned short c = *((unsigned short *) word + i); for (int j = 0; j < nummap; j++) { - if (flag_bsearch((unsigned short *) maptable[j].set_utf16, c, maptable[j].len)) { - in_map = 1; - for (int k = 0; k < maptable[j].len; k++) { - *(word + i) = *(maptable[j].set_utf16 + k); - ns = map_related_utf(word, len, i + 1, wlst, ns, maptable, nummap, timer, timelimit); - if (!(*timelimit)) return ns; + for (int k = 0; k < maptable[j].len; k++) { + int len = strlen(maptable[j].set[k]); + if (strncmp(maptable[j].set[k], word + wn, len) == 0) { + in_map = 1; + for (int l = 0; l < maptable[j].len; l++) { + strcpy(candidate + cn, maptable[j].set[l]); + ns = map_related(word, candidate, wn + len, strlen(candidate), wlst, + cpdsuggest, ns, maptable, nummap, timer, timelimit); + if (!(*timer)) return ns; + } } - *((unsigned short *) word + i) = c; } } if (!in_map) { - i++; - ns = map_related_utf(word, len, i, wlst, ns, maptable, nummap, timer, timelimit); + *(candidate + cn) = *(word + wn); + ns = map_related(word, candidate, wn + 1, cn + 1, wlst, cpdsuggest, + ns, maptable, nummap, timer, timelimit); } return ns; } - - // suggestions for a typical fault of spelling, that // differs with more, than 1 letter from the right form. int SuggestMgr::replchars(char** wlst, const char * word, int ns, int cpdsuggest) @@ -409,13 +415,36 @@ int SuggestMgr::replchars(char** wlst, const char * word, int ns, int cpdsuggest lenr = strlen(reptable[i].pattern2); lenp = strlen(reptable[i].pattern); // search every occurence of the pattern in the word - while ((r=strstr(r, reptable[i].pattern)) != NULL) { + while ((r=strstr(r, reptable[i].pattern)) != NULL && (!reptable[i].end || strlen(r) == strlen(reptable[i].pattern)) && + (!reptable[i].start || r == word)) { strcpy(candidate, word); if (r-word + lenr + strlen(r+lenp) >= MAXSWUTF8L) break; strcpy(candidate+(r-word),reptable[i].pattern2); strcpy(candidate+(r-word)+lenr, r+lenp); ns = testsug(wlst, candidate, wl-lenp+lenr, ns, cpdsuggest, NULL, NULL); if (ns == -1) return -1; + // check REP suggestions with space + char * sp = strchr(candidate, ' '); + if (sp) { + char * prev = candidate; + while (sp) { + *sp = '\0'; + if (checkword(prev, strlen(prev), 0, NULL, NULL)) { + int oldns = ns; + *sp = ' '; + ns = testsug(wlst, sp + 1, strlen(sp + 1), ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + if (oldns < ns) { + free(wlst[ns - 1]); + wlst[ns - 1] = mystrdup(candidate); + if (!wlst[ns - 1]) return -1; + } + } + *sp = ' '; + prev = sp + 1; + sp = strchr(prev, ' '); + } + } r++; // search for the next letter } } @@ -449,13 +478,12 @@ int SuggestMgr::doubletwochars(char** wlst, const char * word, int ns, int cpdsu // perhaps we doubled two characters (pattern aba -> ababa, for example vacation -> vacacation) int SuggestMgr::doubletwochars_utf(char ** wlst, const w_char * word, int wl, int ns, int cpdsuggest) { - //w_char tmpc; w_char candidate_utf[MAXSWL]; char candidate[MAXSWUTF8L]; int state=0; if (wl < 5 || ! pAMgr) return ns; for (int i=2; i < wl; i++) { - if ((word[i].l==word[i-2].l) && (word[i].h==word[i-2].h)) { + if (w_char_eq(word[i], word[i-2])) { state++; if (state==3) { memcpy(candidate_utf, word, (i - 1) * sizeof(w_char)); @@ -472,25 +500,108 @@ int SuggestMgr::doubletwochars_utf(char ** wlst, const w_char * word, int wl, in return ns; } +// error is wrong char in place of correct one (case and keyboard related version) +int SuggestMgr::badcharkey(char ** wlst, const char * word, int ns, int cpdsuggest) +{ + char tmpc; + char candidate[MAXSWUTF8L]; + int wl = strlen(word); + strcpy(candidate, word); + // swap out each char one by one and try uppercase and neighbor + // keyboard chars in its place to see if that makes a good word + + for (int i=0; i < wl; i++) { + tmpc = candidate[i]; + // check with uppercase letters + candidate[i] = csconv[((unsigned char)tmpc)].cupper; + if (tmpc != candidate[i]) { + ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + candidate[i] = tmpc; + } + // check neighbor characters in keyboard string + if (!ckey) continue; + char * loc = strchr(ckey, tmpc); + while (loc) { + if ((loc > ckey) && (*(loc - 1) != '|')) { + candidate[i] = *(loc - 1); + ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + } + if ((*(loc + 1) != '|') && (*(loc + 1) != '\0')) { + candidate[i] = *(loc + 1); + ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + } + loc = strchr(loc + 1, tmpc); + } + candidate[i] = tmpc; + } + return ns; +} + +// error is wrong char in place of correct one (case and keyboard related version) +int SuggestMgr::badcharkey_utf(char ** wlst, const w_char * word, int wl, int ns, int cpdsuggest) +{ + w_char tmpc; + w_char candidate_utf[MAXSWL]; + char candidate[MAXSWUTF8L]; + memcpy(candidate_utf, word, wl * sizeof(w_char)); + // swap out each char one by one and try all the tryme + // chars in its place to see if that makes a good word + for (int i=0; i < wl; i++) { + tmpc = candidate_utf[i]; + // check with uppercase letters + mkallcap_utf(candidate_utf + i, 1, langnum); + if (!w_char_eq(tmpc, candidate_utf[i])) { + u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl); + ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + candidate_utf[i] = tmpc; + } + // check neighbor characters in keyboard string + if (!ckey) continue; + w_char * loc = ckey_utf; + while ((loc < (ckey_utf + ckeyl)) && !w_char_eq(*loc, tmpc)) loc++; + while (loc < (ckey_utf + ckeyl)) { + if ((loc > ckey_utf) && !w_char_eq(*(loc - 1), W_VLINE)) { + candidate_utf[i] = *(loc - 1); + u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl); + ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + } + if (((loc + 1) < (ckey_utf + ckeyl)) && !w_char_eq(*(loc + 1), W_VLINE)) { + candidate_utf[i] = *(loc + 1); + u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl); + ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + } + do { loc++; } while ((loc < (ckey_utf + ckeyl)) && !w_char_eq(*loc, tmpc)); + } + candidate_utf[i] = tmpc; + } + return ns; +} + // error is wrong char in place of correct one int SuggestMgr::badchar(char ** wlst, const char * word, int ns, int cpdsuggest) { char tmpc; char candidate[MAXSWUTF8L]; - time_t timelimit = time(NULL); + clock_t timelimit = clock(); int timer = MINTIMER; int wl = strlen(word); strcpy(candidate, word); // swap out each char one by one and try all the tryme // chars in its place to see if that makes a good word - for (int i=0; i < wl; i++) { - tmpc = candidate[i]; - for (int j=0; j < ctryl; j++) { + for (int j=0; j < ctryl; j++) { + for (int i=wl-1; i >= 0; i--) { + tmpc = candidate[i]; if (ctry[j] == tmpc) continue; candidate[i] = ctry[j]; ns = testsug(wlst, candidate, wl, ns, cpdsuggest, &timer, &timelimit); if (ns == -1) return -1; - if (!timelimit) return ns; + if (!timer) return ns; candidate[i] = tmpc; } } @@ -503,20 +614,20 @@ int SuggestMgr::badchar_utf(char ** wlst, const w_char * word, int wl, int ns, i w_char tmpc; w_char candidate_utf[MAXSWL]; char candidate[MAXSWUTF8L]; - time_t timelimit = time(NULL); + clock_t timelimit = clock(); int timer = MINTIMER; memcpy(candidate_utf, word, wl * sizeof(w_char)); // swap out each char one by one and try all the tryme // chars in its place to see if that makes a good word - for (int i=0; i < wl; i++) { - tmpc = candidate_utf[i]; - for (int j=0; j < ctryl; j++) { - if ((ctry_utf[j].l == tmpc.l) && (ctry_utf[j].h == tmpc.h)) continue; + for (int j=0; j < ctryl; j++) { + for (int i=wl-1; i >= 0; i--) { + tmpc = candidate_utf[i]; + if (w_char_eq(tmpc, ctry_utf[j])) continue; candidate_utf[i] = ctry_utf[j]; u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl); ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, &timer, &timelimit); if (ns == -1) return -1; - if (!timelimit) return ns; + if (!timer) return ns; candidate_utf[i] = tmpc; } } @@ -526,18 +637,20 @@ int SuggestMgr::badchar_utf(char ** wlst, const w_char * word, int wl, int ns, i // error is word has an extra letter it does not need int SuggestMgr::extrachar_utf(char** wlst, const w_char * word, int wl, int ns, int cpdsuggest) { - char candidate[MAXSWUTF8L]; + char candidate[MAXSWUTF8L]; w_char candidate_utf[MAXSWL]; - const w_char * p; - w_char * r; + w_char * p; + w_char tmpc = W_VLINE; // not used value, only for VCC warning message if (wl < 2) return ns; // try omitting one char of word at a time - memcpy(candidate_utf, word + 1, (wl - 1) * sizeof(w_char)); - for (p = word, r = candidate_utf; p < word + wl; ) { - u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl - 1); + memcpy(candidate_utf, word, wl * sizeof(w_char)); + for (p = candidate_utf + wl - 1; p >= candidate_utf; p--) { + w_char tmpc2 = *p; + if (p < candidate_utf + wl - 1) *p = tmpc; + u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl - 1); ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL); if (ns == -1) return -1; - *r++ = *p++; + tmpc = tmpc2; } return ns; } @@ -545,48 +658,41 @@ int SuggestMgr::extrachar_utf(char** wlst, const w_char * word, int wl, int ns, // error is word has an extra letter it does not need int SuggestMgr::extrachar(char** wlst, const char * word, int ns, int cpdsuggest) { + char tmpc = '\0'; char candidate[MAXSWUTF8L]; - const char * p; - char * r; + char * p; int wl = strlen(word); if (wl < 2) return ns; // try omitting one char of word at a time - strcpy (candidate, word + 1); - for (p = word, r = candidate; *p != 0; ) { + strcpy (candidate, word); + for (p = candidate + wl - 1; p >=candidate; p--) { + char tmpc2 = *p; + *p = tmpc; ns = testsug(wlst, candidate, wl-1, ns, cpdsuggest, NULL, NULL); if (ns == -1) return -1; - *r++ = *p++; + tmpc = tmpc2; } return ns; } - // error is missing a letter it needs int SuggestMgr::forgotchar(char ** wlst, const char * word, int ns, int cpdsuggest) { char candidate[MAXSWUTF8L]; - const char * p; - char * q; - //int cwrd; - time_t timelimit = time(NULL); + char * p; + clock_t timelimit = clock(); int timer = MINTIMER; int wl = strlen(word); - // try inserting a tryme character before every letter - strcpy(candidate + 1, word); - for (p = word, q = candidate; *p != 0; ) { - for (int i = 0; i < ctryl; i++) { - *q = ctry[i]; + // try inserting a tryme character before every letter (and the null terminator) + for (int i = 0; i < ctryl; i++) { + strcpy(candidate, word); + for (p = candidate + wl; p >= candidate; p--) { + *(p+1) = *p; + *p = ctry[i]; ns = testsug(wlst, candidate, wl+1, ns, cpdsuggest, &timer, &timelimit); if (ns == -1) return -1; - if (!timelimit) return ns; + if (!timer) return ns; } - *q++ = *p++; - } - // now try adding one to end */ - for (int i = 0; i < ctryl; i++) { - *q = ctry[i]; - ns = testsug(wlst, candidate, wl+1, ns, cpdsuggest, NULL, NULL); - if (ns == -1) return -1; } return ns; } @@ -596,31 +702,20 @@ int SuggestMgr::forgotchar_utf(char ** wlst, const w_char * word, int wl, int ns { w_char candidate_utf[MAXSWL]; char candidate[MAXSWUTF8L]; - const w_char * p; - w_char * q; - int cwrd; - time_t timelimit = time(NULL); + w_char * p; + clock_t timelimit = clock(); int timer = MINTIMER; - // try inserting a tryme character before every letter - memcpy (candidate_utf + 1, word, wl * sizeof(w_char)); - for (p = word, q = candidate_utf; p < (word + wl); ) { - for (int i = 0; i < ctryl; i++) { - *q = ctry_utf[i]; - cwrd = 1; + // try inserting a tryme character at the end of the word and before every letter + for (int i = 0; i < ctryl; i++) { + memcpy (candidate_utf, word, wl * sizeof(w_char)); + for (p = candidate_utf + wl; p >= candidate_utf; p--) { + *(p + 1) = *p; + *p = ctry_utf[i]; u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl + 1); ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, &timer, &timelimit); if (ns == -1) return -1; - if (!timelimit) return ns; - } - *q++ = *p++; - } - // now try adding one to end */ - for (int i = 0; i < ctryl; i++) { - *q = ctry_utf[i]; - cwrd = 1; - u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl + 1); - ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL); - if (ns == -1) return -1; + if (!timer) return ns; + } } return ns; } @@ -638,19 +733,19 @@ int SuggestMgr::twowords(char ** wlst, const char * word, int ns, int cpdsuggest int wl=strlen(word); if (wl < 3) return ns; - if (pAMgr->get_langnum() == LANG_hu) forbidden = check_forbidden(word, wl); + if (langnum == LANG_hu) forbidden = check_forbidden(word, wl); strcpy(candidate + 1, word); - // split the string into two pieces after every char // if both pieces are good words make them a suggestion for (p = candidate + 1; p[1] != '\0'; p++) { p[-1] = *p; // go to end of the UTF-8 character while (utf8 && ((p[1] & 0xc0) == 0x80)) { + *p = p[1]; p++; - p[-1] = *p; } + if (utf8 && p[1] == '\0') break; // last UTF-8 character *p = '\0'; c1 = checkword(candidate,strlen(candidate), cpdsuggest, NULL, NULL); if (c1) { @@ -659,7 +754,7 @@ int SuggestMgr::twowords(char ** wlst, const char * word, int ns, int cpdsuggest *p = ' '; // spec. Hungarian code (need a better compound word support) - if ((pAMgr->get_langnum() == LANG_hu) && !forbidden && + if ((langnum == LANG_hu) && !forbidden && // if 3 repeating letter, use - instead of space (((p[-1] == p[1]) && (((p>candidate+1) && (p[-1] == p[-2])) || (p[-1] == p[2]))) || // or multiple compounding, with more, than 6 syllables @@ -675,6 +770,23 @@ int SuggestMgr::twowords(char ** wlst, const char * word, int ns, int cpdsuggest ns++; } } else return ns; + // add two word suggestion with dash, if TRY string contains + // "a" or "-" + // NOTE: cwrd doesn't modified for REP twoword sugg. + if (ctry && (strchr(ctry, 'a') || strchr(ctry, '-')) && + mystrlen(p + 1) > 1 && + mystrlen(candidate) - mystrlen(p) > 1) { + *p = '-'; + for (int k=0; k < ns; k++) + if (strcmp(candidate,wlst[k]) == 0) cwrd = 0; + if (ns < maxSug) { + if (cwrd) { + wlst[ns] = mystrdup(candidate); + if (wlst[ns] == NULL) return -1; + ns++; + } + } else return ns; + } } } } @@ -700,6 +812,24 @@ int SuggestMgr::swapchar(char ** wlst, const char * word, int ns, int cpdsuggest p[1] = *p; *p = tmpc; } + // try double swaps for short words + // ahev -> have, owudl -> would + if (wl == 4 || wl == 5) { + candidate[0] = word[1]; + candidate[1] = word[0]; + candidate[2] = word[2]; + candidate[wl - 2] = word[wl - 1]; + candidate[wl - 1] = word[wl - 2]; + ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + if (wl == 5) { + candidate[0] = word[0]; + candidate[1] = word[2]; + candidate[2] = word[1]; + ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + } + } return ns; } @@ -710,6 +840,7 @@ int SuggestMgr::swapchar_utf(char ** wlst, const w_char * word, int wl, int ns, char candidate[MAXSWUTF8L]; w_char * p; w_char tmpc; + int len = 0; // try swapping adjacent chars one by one memcpy (candidate_utf, word, wl * sizeof(w_char)); for (p = candidate_utf; p < (candidate_utf + wl - 1); p++) { @@ -717,11 +848,32 @@ int SuggestMgr::swapchar_utf(char ** wlst, const w_char * word, int wl, int ns, *p = p[1]; p[1] = tmpc; u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl); - ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL); + if (len == 0) len = strlen(candidate); + ns = testsug(wlst, candidate, len, ns, cpdsuggest, NULL, NULL); if (ns == -1) return -1; p[1] = *p; *p = tmpc; } + // try double swaps for short words + // ahev -> have, owudl -> would, suodn -> sound + if (wl == 4 || wl == 5) { + candidate_utf[0] = word[1]; + candidate_utf[1] = word[0]; + candidate_utf[2] = word[2]; + candidate_utf[wl - 2] = word[wl - 1]; + candidate_utf[wl - 1] = word[wl - 2]; + u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl); + ns = testsug(wlst, candidate, len, ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + if (wl == 5) { + candidate_utf[0] = word[0]; + candidate_utf[1] = word[2]; + candidate_utf[2] = word[1]; + u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl); + ns = testsug(wlst, candidate, len, ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + } + } return ns; } @@ -737,7 +889,7 @@ int SuggestMgr::longswapchar(char ** wlst, const char * word, int ns, int cpdsug strcpy(candidate, word); for (p = candidate; *p != 0; p++) { for (q = candidate; *q != 0; q++) { - if (abs(p-q) > 1) { + if (abs((int)(p-q)) > 1) { tmpc = *p; *p = *q; *q = tmpc; @@ -764,10 +916,11 @@ int SuggestMgr::longswapchar_utf(char ** wlst, const w_char * word, int wl, int memcpy (candidate_utf, word, wl * sizeof(w_char)); for (p = candidate_utf; p < (candidate_utf + wl); p++) { for (q = candidate_utf; q < (candidate_utf + wl); q++) { - if (abs(p-q) > 1) { + if (abs((int)(p-q)) > 1) { tmpc = *p; *p = *q; *q = tmpc; + u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl); ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL); if (ns == -1) return -1; *q = *p; @@ -795,7 +948,7 @@ int SuggestMgr::movechar(char ** wlst, const char * word, int ns, int cpdsuggest *(q-1) = *q; *q = tmpc; if ((q-p) < 2) continue; // omit swap char - ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL); + ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL); if (ns == -1) return -1; } strcpy(candidate, word); @@ -806,7 +959,7 @@ int SuggestMgr::movechar(char ** wlst, const char * word, int ns, int cpdsuggest *(q+1) = *q; *q = tmpc; if ((p-q) < 2) continue; // omit swap char - ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL); + ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL); if (ns == -1) return -1; } strcpy(candidate, word); @@ -831,7 +984,7 @@ int SuggestMgr::movechar_utf(char ** wlst, const w_char * word, int wl, int ns, *q = tmpc; if ((q-p) < 2) continue; // omit swap char u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl); - ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL); + ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL); if (ns == -1) return -1; } memcpy (candidate_utf, word, wl * sizeof(w_char)); @@ -843,7 +996,7 @@ int SuggestMgr::movechar_utf(char ** wlst, const w_char * word, int wl, int ns, *q = tmpc; if ((p-q) < 2) continue; // omit swap char u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl); - ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL); + ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL); if (ns == -1) return -1; } memcpy (candidate_utf, word, wl * sizeof(w_char)); @@ -852,28 +1005,34 @@ int SuggestMgr::movechar_utf(char ** wlst, const w_char * word, int wl, int ns, } // generate a set of suggestions for very poorly spelled words -int SuggestMgr::ngsuggest(char** wlst, char * w, HashMgr* pHMgr) +int SuggestMgr::ngsuggest(char** wlst, char * w, int ns, HashMgr** pHMgr, int md) { int i, j; int lval; - int sc; - int lp; + int sc, scphon; + int lp, lpphon; int nonbmp = 0; - if (!pHMgr) return 0; - // exhaustively search through all root words // keeping track of the MAX_ROOTS most similar root words struct hentry * roots[MAX_ROOTS]; + char * rootsphon[MAX_ROOTS]; int scores[MAX_ROOTS]; + int scoresphon[MAX_ROOTS]; for (i = 0; i < MAX_ROOTS; i++) { roots[i] = NULL; scores[i] = -100 * i; + rootsphon[i] = NULL; + scoresphon[i] = -100 * i; } lp = MAX_ROOTS - 1; - + lpphon = MAX_ROOTS - 1; + scphon = -20000; + int low = NGRAM_LOWERING; + char w2[MAXWORDUTF8LEN]; + char f[MAXSWUTF8L]; char * word = w; // word reversing wrapper for complex prefixes @@ -890,19 +1049,70 @@ int SuggestMgr::ngsuggest(char** wlst, char * w, HashMgr* pHMgr) // set character based ngram suggestion for words with non-BMP Unicode characters if (n == -1) { - utf8 = 0; + utf8 = 0; // XXX not state-free n = nc; nonbmp = 1; + low = 0; } struct hentry* hp = NULL; int col = -1; - while ((hp = pHMgr->walk_hashtable(col, hp))) { + phonetable * ph = (pAMgr) ? pAMgr->get_phonetable() : NULL; + char target[MAXSWUTF8L]; + char candidate[MAXSWUTF8L]; + if (ph) { + if (utf8) { + w_char _w[MAXSWL]; + int _wl = u8_u16(_w, MAXSWL, word); + mkallcap_utf(_w, _wl, langnum); + u16_u8(candidate, MAXSWUTF8L, _w, _wl); + } else { + strcpy(candidate, word); + if (!nonbmp) mkallcap(candidate, csconv); + } + phonet(candidate, target, nc, *ph); // XXX phonet() is 8-bit (nc, not n) + } + + FLAG forbiddenword = pAMgr ? pAMgr->get_forbiddenword() : FLAG_NULL; + FLAG nosuggest = pAMgr ? pAMgr->get_nosuggest() : FLAG_NULL; + FLAG nongramsuggest = pAMgr ? pAMgr->get_nongramsuggest() : FLAG_NULL; + FLAG onlyincompound = pAMgr ? pAMgr->get_onlyincompound() : FLAG_NULL; + + for (i = 0; i < md; i++) { + while (0 != (hp = (pHMgr[i])->walk_hashtable(col, hp))) { if ((hp->astr) && (pAMgr) && - (TESTAFF(hp->astr, pAMgr->get_forbiddenword(), hp->alen) || - TESTAFF(hp->astr, pAMgr->get_nosuggest(), hp->alen) || - TESTAFF(hp->astr, pAMgr->get_onlyincompound(), hp->alen))) continue; - sc = ngram(3, word, hp->word, NGRAM_LONGER_WORSE); + (TESTAFF(hp->astr, forbiddenword, hp->alen) || + TESTAFF(hp->astr, ONLYUPCASEFLAG, hp->alen) || + TESTAFF(hp->astr, nosuggest, hp->alen) || + TESTAFF(hp->astr, nongramsuggest, hp->alen) || + TESTAFF(hp->astr, onlyincompound, hp->alen))) continue; + + sc = ngram(3, word, HENTRY_WORD(hp), NGRAM_LONGER_WORSE + low) + + leftcommonsubstring(word, HENTRY_WORD(hp)); + + // check special pronounciation + if ((hp->var & H_OPT_PHON) && copy_field(f, HENTRY_DATA(hp), MORPH_PHON)) { + int sc2 = ngram(3, word, f, NGRAM_LONGER_WORSE + low) + + + leftcommonsubstring(word, f); + if (sc2 > sc) sc = sc2; + } + + scphon = -20000; + if (ph && (sc > 2) && (abs(n - (int) hp->clen) <= 3)) { + char target2[MAXSWUTF8L]; + if (utf8) { + w_char _w[MAXSWL]; + int _wl = u8_u16(_w, MAXSWL, HENTRY_WORD(hp)); + mkallcap_utf(_w, _wl, langnum); + u16_u8(candidate, MAXSWUTF8L, _w, _wl); + } else { + strcpy(candidate, HENTRY_WORD(hp)); + mkallcap(candidate, csconv); + } + phonet(candidate, target2, -1, *ph); + scphon = 2 * ngram(3, target, target2, NGRAM_LONGER_WORSE); + } + if (sc > scores[lp]) { scores[lp] = sc; roots[lp] = hp; @@ -912,10 +1122,22 @@ int SuggestMgr::ngsuggest(char** wlst, char * w, HashMgr* pHMgr) lp = j; lval = scores[j]; } - } - } + } + + + if (scphon > scoresphon[lpphon]) { + scoresphon[lpphon] = scphon; + rootsphon[lpphon] = HENTRY_WORD(hp); + lval = scphon; + for (j=0; j < MAX_ROOTS; j++) + if (scoresphon[j] < lval) { + lpphon = j; + lval = scoresphon[j]; + } + } + }} - // find minimum threshhold for a passable suggestion + // find minimum threshold for a passable suggestion // mangle original word three differnt ways // and score them to generate a minimum acceptable score int thresh = 0; @@ -923,23 +1145,25 @@ int SuggestMgr::ngsuggest(char** wlst, char * w, HashMgr* pHMgr) if (utf8) { for (int k=sp; k < n; k+=4) *((unsigned short *) u8 + k) = '*'; u16_u8(mw, MAXSWUTF8L, u8, n); - thresh = thresh + ngram(n, word, mw, NGRAM_ANY_MISMATCH); + thresh = thresh + ngram(n, word, mw, NGRAM_ANY_MISMATCH + low); } else { strcpy(mw, word); for (int k=sp; k < n; k+=4) *(mw + k) = '*'; - thresh = thresh + ngram(n, word, mw, NGRAM_ANY_MISMATCH); + thresh = thresh + ngram(n, word, mw, NGRAM_ANY_MISMATCH + low); } } thresh = thresh / 3; thresh--; - // now expand affixes on each of these root words and + // now expand affixes on each of these root words and // and use length adjusted ngram scores to select // possible suggestions char * guess[MAX_GUESS]; + char * guessorig[MAX_GUESS]; int gscore[MAX_GUESS]; for(i=0;iexpand_rootword(glst, MAX_WORDS, rp->word, rp->wlen, - rp->astr, rp->alen, word, nc); + int nw = pAMgr->expand_rootword(glst, MAX_WORDS, HENTRY_WORD(rp), rp->blen, + rp->astr, rp->alen, word, nc, + ((rp->var & H_OPT_PHON) ? copy_field(f, HENTRY_DATA(rp), MORPH_PHON) : NULL)); for (int k = 0; k < nw ; k++) { - sc = ngram(n, word, glst[k].word, NGRAM_ANY_MISMATCH); - if ((sc > thresh)) { + sc = ngram(n, word, glst[k].word, NGRAM_ANY_MISMATCH + low) + + leftcommonsubstring(word, glst[k].word); + + if (sc > thresh) { if (sc > gscore[lp]) { - if (guess[lp]) free (guess[lp]); + if (guess[lp]) { + free (guess[lp]); + if (guessorig[lp]) { + free(guessorig[lp]); + guessorig[lp] = NULL; + } + } gscore[lp] = sc; guess[lp] = glst[k].word; + guessorig[lp] = glst[k].orig; lval = sc; for (j=0; j < MAX_GUESS; j++) if (gscore[j] < lval) { lp = j; lval = gscore[j]; } - } else free (glst[k].word); - } else free(glst[k].word); + } else { + free(glst[k].word); + if (glst[k].orig) free(glst[k].orig); + } + } else { + free(glst[k].word); + if (glst[k].orig) free(glst[k].orig); + } } } } @@ -982,12 +1221,21 @@ int SuggestMgr::ngsuggest(char** wlst, char * w, HashMgr* pHMgr) // now we are done generating guesses // sort in order of decreasing score - bubblesort(&guess[0], &gscore[0], MAX_GUESS); + + bubblesort(&guess[0], &guessorig[0], &gscore[0], MAX_GUESS); + if (ph) bubblesort(&rootsphon[0], NULL, &scoresphon[0], MAX_ROOTS); // weight suggestions with a similarity index, based on // the longest common subsequent algorithm and resort - int is_swap; + int is_swap = 0; + int re = 0; + double fact = 1.0; + if (pAMgr) { + int maxd = pAMgr->get_maxdiff(); + if (maxd >= 0) fact = (10.0 - maxd)/5.0; + } + for (i=0; i < MAX_GUESS; i++) { if (guess[i]) { // lowering guess[i] @@ -996,11 +1244,11 @@ int SuggestMgr::ngsuggest(char** wlst, char * w, HashMgr* pHMgr) if (utf8) { w_char _w[MAXSWL]; len = u8_u16(_w, MAXSWL, guess[i]); - mkallsmall_utf(_w, len, pAMgr->get_langnum()); + mkallsmall_utf(_w, len, langnum); u16_u8(gl, MAXSWUTF8L, _w, len); } else { strcpy(gl, guess[i]); - mkallsmall(gl, csconv); + if (!nonbmp) mkallsmall(gl, csconv); len = strlen(guess[i]); } @@ -1011,39 +1259,115 @@ int SuggestMgr::ngsuggest(char** wlst, char * w, HashMgr* pHMgr) gscore[i] += 2000; break; } - - // heuristic weigthing of ngram scores - gscore[i] += - // length of longest common subsequent minus lenght difference + // using 2-gram instead of 3, and other weightening + + re = ngram(2, word, gl, NGRAM_ANY_MISMATCH + low + NGRAM_WEIGHTED) + + ngram(2, gl, word, NGRAM_ANY_MISMATCH + low + NGRAM_WEIGHTED); + + gscore[i] = + // length of longest common subsequent minus length difference 2 * _lcs - abs((int) (n - len)) + - // weight equal first letter - equalfirstletter(word, gl) + + // weight length of the left common substring + leftcommonsubstring(word, gl) + // weight equal character positions - ((_lcs == commoncharacterpositions(word, gl, &is_swap)) ? 1: 0) + + (!nonbmp && commoncharacterpositions(word, gl, &is_swap) ? 1: 0) + // swap character (not neighboring) - ((is_swap) ? 1000 : 0); + ((is_swap) ? 10 : 0) + + // ngram + ngram(4, word, gl, NGRAM_ANY_MISMATCH + low) + + // weighted ngrams + re + + // different limit for dictionaries with PHONE rules + (ph ? (re < len * fact ? -1000 : 0) : (re < (n + len)*fact? -1000 : 0)); } } - bubblesort(&guess[0], &gscore[0], MAX_GUESS); + bubblesort(&guess[0], &guessorig[0], &gscore[0], MAX_GUESS); + +// phonetic version + if (ph) for (i=0; i < MAX_ROOTS; i++) { + if (rootsphon[i]) { + // lowering rootphon[i] + char gl[MAXSWUTF8L]; + int len; + if (utf8) { + w_char _w[MAXSWL]; + len = u8_u16(_w, MAXSWL, rootsphon[i]); + mkallsmall_utf(_w, len, langnum); + u16_u8(gl, MAXSWUTF8L, _w, len); + } else { + strcpy(gl, rootsphon[i]); + if (!nonbmp) mkallsmall(gl, csconv); + len = strlen(rootsphon[i]); + } + + // heuristic weigthing of ngram scores + scoresphon[i] += 2 * lcslen(word, gl) - abs((int) (n - len)) + + // weight length of the left common substring + leftcommonsubstring(word, gl); + } + } + + if (ph) bubblesort(&rootsphon[0], NULL, &scoresphon[0], MAX_ROOTS); // copy over + int oldns = ns; - int ns = 0; int same = 0; for (i=0; i < MAX_GUESS; i++) { if (guess[i]) { - if ((ns < maxngramsugs) && (ns < maxSug) && (!same || (gscore[i] > 1000))) { + if ((ns < oldns + maxngramsugs) && (ns < maxSug) && (!same || (gscore[i] > 1000))) { int unique = 1; - // we have excellent suggestion(s) - if (gscore[i] > 1000) same = 1; - for (j=0; j < ns; j++) + // leave only excellent suggestions, if exists + if (gscore[i] > 1000) same = 1; else if (gscore[i] < -100) { + same = 1; + // keep the best ngram suggestions, unless in ONLYMAXDIFF mode + if (ns > oldns || (pAMgr && pAMgr->get_onlymaxdiff())) { + free(guess[i]); + if (guessorig[i]) free(guessorig[i]); + continue; + } + } + for (j = 0; j < ns; j++) { // don't suggest previous suggestions or a previous suggestion with prefixes or affixes - if (strstr(guess[i], wlst[j]) || + if ((!guessorig[i] && strstr(guess[i], wlst[j])) || + (guessorig[i] && strstr(guessorig[i], wlst[j])) || // check forbidden words !checkword(guess[i], strlen(guess[i]), 0, NULL, NULL)) unique = 0; - if (unique) wlst[ns++] = guess[i]; else free(guess[i]); - } else free(guess[i]); + } + if (unique) { + wlst[ns++] = guess[i]; + if (guessorig[i]) { + free(guess[i]); + wlst[ns-1] = guessorig[i]; + } + } else { + free(guess[i]); + if (guessorig[i]) free(guessorig[i]); + } + } else { + free(guess[i]); + if (guessorig[i]) free(guessorig[i]); + } + } + } + + oldns = ns; + if (ph) for (i=0; i < MAX_ROOTS; i++) { + if (rootsphon[i]) { + if ((ns < oldns + MAXPHONSUGS) && (ns < maxSug)) { + int unique = 1; + for (j = 0; j < ns; j++) { + // don't suggest previous suggestions or a previous suggestion with prefixes or affixes + if (strstr(rootsphon[i], wlst[j]) || + // check forbidden words + !checkword(rootsphon[i], strlen(rootsphon[i]), 0, NULL, NULL)) unique = 0; + } + if (unique) { + wlst[ns++] = mystrdup(rootsphon[i]); + if (!wlst[ns - 1]) return ns - 1; + } + } } } @@ -1058,19 +1382,17 @@ int SuggestMgr::ngsuggest(char** wlst, char * w, HashMgr* pHMgr) // obsolote MySpell-HU modifications: // return value 2 and 3 marks compounding with hyphen (-) // `3' marks roots without suffix -int SuggestMgr::checkword(const char * word, int len, int cpdsuggest, int * timer, time_t * timelimit) +int SuggestMgr::checkword(const char * word, int len, int cpdsuggest, int * timer, clock_t * timelimit) { struct hentry * rv=NULL; + struct hentry * rv2=NULL; int nosuffix = 0; - + // check time limit if (timer) { (*timer)--; if (!(*timer) && timelimit) { - if (time(NULL) > *timelimit) { - *timelimit = 0; - return 0; - } + if ((clock() - *timelimit) > TIMELIMIT) return 0; *timer = MAXPLUSTIMER; } } @@ -1078,8 +1400,10 @@ int SuggestMgr::checkword(const char * word, int len, int cpdsuggest, int * time if (pAMgr) { if (cpdsuggest==1) { if (pAMgr->get_compound()) { - rv = pAMgr->compound_check(word,len,0,0,0,0,NULL,0,NULL,NULL,1); - if (rv) return 3; // XXX obsolote categorisation + rv = pAMgr->compound_check(word, len, 0, 0, 100, 0, NULL, 0, 1, 0); //EXT + if (rv && (!(rv2 = pAMgr->lookup(word)) || !rv2->astr || + !(TESTAFF(rv2->astr,pAMgr->get_forbiddenword(),rv2->alen) || + TESTAFF(rv2->astr,pAMgr->get_nosuggest(),rv2->alen)))) return 3; // XXX obsolote categorisation + only ICONV needs affix flag check? } return 0; } @@ -1089,10 +1413,15 @@ int SuggestMgr::checkword(const char * word, int len, int cpdsuggest, int * time if (rv) { if ((rv->astr) && (TESTAFF(rv->astr,pAMgr->get_forbiddenword(),rv->alen) || TESTAFF(rv->astr,pAMgr->get_nosuggest(),rv->alen))) return 0; - if (rv->astr && (TESTAFF(rv->astr,pAMgr->get_pseudoroot(),rv->alen) || - TESTAFF(rv->astr,pAMgr->get_onlyincompound(),rv->alen))) rv = NULL; + while (rv) { + if (rv->astr && (TESTAFF(rv->astr,pAMgr->get_needaffix(),rv->alen) || + TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) || + TESTAFF(rv->astr,pAMgr->get_onlyincompound(),rv->alen))) { + rv = rv->next_homonym; + } else break; + } } else rv = pAMgr->prefix_check(word, len, 0); // only prefix, and prefix + suffix XXX - + if (rv) { nosuffix=1; } else { @@ -1105,8 +1434,9 @@ int SuggestMgr::checkword(const char * word, int len, int cpdsuggest, int * time } // check forbidden words - if ((rv) && (rv->astr) && (TESTAFF(rv->astr,pAMgr->get_forbiddenword(),rv->alen) - || TESTAFF(rv->astr,pAMgr->get_nosuggest(),rv->alen) || + if ((rv) && (rv->astr) && (TESTAFF(rv->astr,pAMgr->get_forbiddenword(),rv->alen) || + TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) || + TESTAFF(rv->astr,pAMgr->get_nosuggest(),rv->alen) || TESTAFF(rv->astr,pAMgr->get_onlyincompound(),rv->alen))) return 0; if (rv) { // XXX obsolote @@ -1124,7 +1454,7 @@ int SuggestMgr::check_forbidden(const char * word, int len) if (pAMgr) { rv = pAMgr->lookup(word); - if (rv && rv->astr && (TESTAFF(rv->astr,pAMgr->get_pseudoroot(),rv->alen) || + if (rv && rv->astr && (TESTAFF(rv->astr,pAMgr->get_needaffix(),rv->alen) || TESTAFF(rv->astr,pAMgr->get_onlyincompound(),rv->alen))) rv = NULL; if (!(pAMgr->prefix_check(word,len,1))) rv = pAMgr->suffix_check(word,len, 0, NULL, NULL, 0, NULL); // prefix+suffix, suffix @@ -1135,184 +1465,6 @@ int SuggestMgr::check_forbidden(const char * word, int len) } #ifdef HUNSPELL_EXPERIMENTAL -// suggest stems, XXX experimental code -int SuggestMgr::suggest_stems(char*** slst, const char * w, int nsug) -{ - char buf[MAXSWUTF8L]; - char ** wlst; - int prevnsug = nsug; - - char w2[MAXWORDUTF8LEN]; - const char * word = w; - - // word reversing wrapper for complex prefixes - if (complexprefixes) { - strcpy(w2, w); - if (utf8) reverseword_utf(w2); else reverseword(w2); - word = w2; - } - - if (*slst) { - wlst = *slst; - } else { - wlst = (char **) calloc(maxSug, sizeof(char *)); - if (wlst == NULL) return -1; - } - // perhaps there are a fix stem in the dictionary - if ((nsug < maxSug) && (nsug > -1)) { - - nsug = fixstems(wlst, word, nsug); - if (nsug == prevnsug) { - char * s = mystrdup(word); - char * p = s + strlen(s); - while ((*p != '-') && (p != s)) p--; - if (*p == '-') { - *p = '\0'; - nsug = fixstems(wlst, s, nsug); - if ((nsug == prevnsug) && (nsug < maxSug) && (nsug >= 0)) { - char * t; - buf[0] = '\0'; - for (t = s; (t[0] != '\0') && ((t[0] >= '0') || (t[0] <= '9')); t++); // is a number? - if (*t != '\0') strcpy(buf, "# "); - strcat(buf, s); - wlst[nsug] = mystrdup(buf); - if (wlst[nsug] == NULL) return -1; - nsug++; - } - p++; - nsug = fixstems(wlst, p, nsug); - } - - free(s); - } - } - - if (nsug < 0) { - for (int i=0;ilookup(word); - if (rv) { - dicstem = 0; - } else { - // try stripping off affixes - rv = pAMgr->affix_check(word, wl); - - // else try check compound word - if (!rv && pAMgr->get_compound()) { - rv = pAMgr->compound_check(word, wl, - 0, 0, 100, 0, NULL, 0, &cmpdstemnum, cmpdstem,1); - - if (rv) { - dicstem = 2; - for (int j = 0; j < cmpdstemnum; j++) { - cpdindex += cmpdstem[j]; - } - if(! (pAMgr->lookup(word + cpdindex))) - pAMgr->affix_check(word + cpdindex, wl - cpdindex); // for prefix - } - } - - - if (pAMgr->get_prefix()) { - strcpy(prefix, pAMgr->get_prefix()); - } - - // XXX obsolete, will be a general solution for stemming - if ((prefix) && (strncmp(prefix, "leg", 3)==0)) prefix[0] = '\0'; // (HU) - } - - } - - - - if ((rv) && (ns < maxSug)) { - - // check fixstem flag and not_valid_stem flag - // first word - if ((ns < maxSug) && (dicstem < 2)) { - strcpy(buf, prefix); - if ((dicstem > 0) && pAMgr->get_derived()) { - // XXX obsolote - if (strlen(prefix) == 1) { - strcat(buf, (pAMgr->get_derived()) + 1); - } else { - strcat(buf, pAMgr->get_derived()); - } - } else { - // special stem in affix description - const char * wordchars = pAMgr->get_wordchars(); - if (rv->description && - (strchr(wordchars, *(rv->description)))) { - char * desc = (rv->description) + 1; - while (strchr(wordchars, *desc)) desc++; - strncat(buf, rv->description, desc - (rv->description)); - } else { - strcat(buf, rv->word); - } - } - wlst[ns] = mystrdup(buf); - if (wlst[ns] == NULL) return -1; - ns++; - } - - if (dicstem == 2) { - - // compound stem - -// if (rv->astr && (strchr(rv->astr, '0') == NULL)) { - if (rv->astr) { - strcpy(buf, word); - buf[cpdindex] = '\0'; - if (prefix) strcat(buf, prefix); - if (pAMgr->get_derived()) { - strcat(buf, pAMgr->get_derived()); - } else { - // special stem in affix description - const char * wordchars = pAMgr->get_wordchars(); - if (rv->description && - (strchr(wordchars, *(rv->description)))) { - char * desc = (rv->description) + 1; - while (strchr(wordchars, *desc)) desc++; - strncat(buf, rv->description, desc - (rv->description)); - } else { - strcat(buf, rv->word); - } - } - if (ns < maxSug) { - wlst[ns] = mystrdup(buf); - if (wlst[ns] == NULL) return -1; - ns++; - } - } - } - } - return ns; -} - // suggest possible stems int SuggestMgr::suggest_pos_stems(char*** slst, const char * w, int nsug) { @@ -1352,6 +1504,7 @@ int SuggestMgr::suggest_pos_stems(char*** slst, const char * w, int nsug) *slst = wlst; return nsug; } +#endif // END OF HUNSPELL_EXPERIMENTAL CODE char * SuggestMgr::suggest_morph(const char * w) @@ -1380,20 +1533,25 @@ char * SuggestMgr::suggest_morph(const char * w) while (rv) { if ((!rv->astr) || !(TESTAFF(rv->astr, pAMgr->get_forbiddenword(), rv->alen) || - TESTAFF(rv->astr, pAMgr->get_pseudoroot(), rv->alen) || + TESTAFF(rv->astr, pAMgr->get_needaffix(), rv->alen) || TESTAFF(rv->astr,pAMgr->get_onlyincompound(),rv->alen))) { - if (rv->description && ((!rv->astr) || - !TESTAFF(rv->astr, pAMgr->get_lemma_present(), rv->alen))) - strcat(result, word); - if (rv->description) strcat(result, rv->description); - strcat(result, "\n"); + if (!HENTRY_FIND(rv, MORPH_STEM)) { + mystrcat(result, " ", MAXLNLEN); + mystrcat(result, MORPH_STEM, MAXLNLEN); + mystrcat(result, word, MAXLNLEN); + } + if (HENTRY_DATA(rv)) { + mystrcat(result, " ", MAXLNLEN); + mystrcat(result, HENTRY_DATA2(rv), MAXLNLEN); + } + mystrcat(result, "\n", MAXLNLEN); } rv = rv->next_homonym; } st = pAMgr->affix_check_morph(word,strlen(word)); if (st) { - strcat(result, st); + mystrcat(result, st, MAXLNLEN); free(st); } @@ -1401,109 +1559,273 @@ char * SuggestMgr::suggest_morph(const char * w) pAMgr->compound_check_morph(word, strlen(word), 0, 0, 100, 0,NULL, 0, &r, NULL); - return (*result) ? mystrdup(line_uniq(delete_zeros(result))) : NULL; + return (*result) ? mystrdup(line_uniq(result, MSEP_REC)) : NULL; } +#ifdef HUNSPELL_EXPERIMENTAL char * SuggestMgr::suggest_morph_for_spelling_error(const char * word) { char * p = NULL; char ** wlst = (char **) calloc(maxSug, sizeof(char *)); + if (!**wlst) return NULL; // we will use only the first suggestion for (int i = 0; i < maxSug - 1; i++) wlst[i] = ""; - int ns = suggest(&wlst, word, maxSug - 1); + int ns = suggest(&wlst, word, maxSug - 1, NULL); if (ns == maxSug) { p = suggest_morph(wlst[maxSug - 1]); free(wlst[maxSug - 1]); } if (wlst) free(wlst); - return p; + return p; } #endif // END OF HUNSPELL_EXPERIMENTAL CODE +/* affixation */ +char * SuggestMgr::suggest_hentry_gen(hentry * rv, char * pattern) +{ + char result[MAXLNLEN]; + *result = '\0'; + int sfxcount = get_sfxcount(pattern); + + if (get_sfxcount(HENTRY_DATA(rv)) > sfxcount) return NULL; + + if (HENTRY_DATA(rv)) { + char * aff = pAMgr->morphgen(HENTRY_WORD(rv), rv->blen, rv->astr, rv->alen, + HENTRY_DATA(rv), pattern, 0); + if (aff) { + mystrcat(result, aff, MAXLNLEN); + mystrcat(result, "\n", MAXLNLEN); + free(aff); + } + } + + // check all allomorphs + char allomorph[MAXLNLEN]; + char * p = NULL; + if (HENTRY_DATA(rv)) p = (char *) strstr(HENTRY_DATA2(rv), MORPH_ALLOMORPH); + while (p) { + struct hentry * rv2 = NULL; + p += MORPH_TAG_LEN; + int plen = fieldlen(p); + strncpy(allomorph, p, plen); + allomorph[plen] = '\0'; + rv2 = pAMgr->lookup(allomorph); + while (rv2) { +// if (HENTRY_DATA(rv2) && get_sfxcount(HENTRY_DATA(rv2)) <= sfxcount) { + if (HENTRY_DATA(rv2)) { + char * st = (char *) strstr(HENTRY_DATA2(rv2), MORPH_STEM); + if (st && (strncmp(st + MORPH_TAG_LEN, + HENTRY_WORD(rv), fieldlen(st + MORPH_TAG_LEN)) == 0)) { + char * aff = pAMgr->morphgen(HENTRY_WORD(rv2), rv2->blen, rv2->astr, rv2->alen, + HENTRY_DATA(rv2), pattern, 0); + if (aff) { + mystrcat(result, aff, MAXLNLEN); + mystrcat(result, "\n", MAXLNLEN); + free(aff); + } + } + } + rv2 = rv2->next_homonym; + } + p = strstr(p + plen, MORPH_ALLOMORPH); + } + + return (*result) ? mystrdup(result) : NULL; +} + +char * SuggestMgr::suggest_gen(char ** desc, int n, char * pattern) { + char result[MAXLNLEN]; + char result2[MAXLNLEN]; + char newpattern[MAXLNLEN]; + *newpattern = '\0'; + if (n == 0) return 0; + *result2 = '\0'; + struct hentry * rv = NULL; + if (!pAMgr) return NULL; + +// search affixed forms with and without derivational suffixes + while(1) { + + for (int k = 0; k < n; k++) { + *result = '\0'; + // add compound word parts (except the last one) + char * s = (char *) desc[k]; + char * part = strstr(s, MORPH_PART); + if (part) { + char * nextpart = strstr(part + 1, MORPH_PART); + while (nextpart) { + copy_field(result + strlen(result), part, MORPH_PART); + part = nextpart; + nextpart = strstr(part + 1, MORPH_PART); + } + s = part; + } + + char **pl; + char tok[MAXLNLEN]; + strcpy(tok, s); + char * alt = strstr(tok, " | "); + while (alt) { + alt[1] = MSEP_ALT; + alt = strstr(alt, " | "); + } + int pln = line_tok(tok, &pl, MSEP_ALT); + for (int i = 0; i < pln; i++) { + // remove inflectional and terminal suffixes + char * is = strstr(pl[i], MORPH_INFL_SFX); + if (is) *is = '\0'; + char * ts = strstr(pl[i], MORPH_TERM_SFX); + while (ts) { + *ts = '_'; + ts = strstr(pl[i], MORPH_TERM_SFX); + } + char * st = strstr(s, MORPH_STEM); + if (st) { + copy_field(tok, st, MORPH_STEM); + rv = pAMgr->lookup(tok); + while (rv) { + char newpat[MAXLNLEN]; + strcpy(newpat, pl[i]); + strcat(newpat, pattern); + char * sg = suggest_hentry_gen(rv, newpat); + if (!sg) sg = suggest_hentry_gen(rv, pattern); + if (sg) { + char ** gen; + int genl = line_tok(sg, &gen, MSEP_REC); + free(sg); + sg = NULL; + for (int j = 0; j < genl; j++) { + if (strstr(pl[i], MORPH_SURF_PFX)) { + int r2l = strlen(result2); + result2[r2l] = MSEP_REC; + strcpy(result2 + r2l + 1, result); + copy_field(result2 + strlen(result2), pl[i], MORPH_SURF_PFX); + mystrcat(result2, gen[j], MAXLNLEN); + } else { + sprintf(result2 + strlen(result2), "%c%s%s", + MSEP_REC, result, gen[j]); + } + } + freelist(&gen, genl); + } + rv = rv->next_homonym; + } + } + } + freelist(&pl, pln); + } + + if (*result2 || !strstr(pattern, MORPH_DERI_SFX)) break; + strcpy(newpattern, pattern); + pattern = newpattern; + char * ds = strstr(pattern, MORPH_DERI_SFX); + while (ds) { + strncpy(ds, MORPH_TERM_SFX, MORPH_TAG_LEN); + ds = strstr(pattern, MORPH_DERI_SFX); + } + } + return (*result2 ? mystrdup(result2) : NULL); +} + // generate an n-gram score comparing s1 and s2 -int SuggestMgr::ngram(int n, char * s1, const char * s2, int uselen) +int SuggestMgr::ngram(int n, char * s1, const char * s2, int opt) { int nscore = 0; int ns; int l1; int l2; + int test = 0; if (utf8) { w_char su1[MAXSWL]; w_char su2[MAXSWL]; l1 = u8_u16(su1, MAXSWL, s1); l2 = u8_u16(su2, MAXSWL, s2); - if (!l2 || (l1==-1) || (l2==-1)) return 0; - // decapitalize dictionary word - if (complexprefixes) { - mkallsmall_utf(su2+l2-1, 1, pAMgr->get_langnum()); - } else { - mkallsmall_utf(su2, 1, pAMgr->get_langnum()); - } + if ((l2 <= 0) || (l1 == -1)) return 0; + // lowering dictionary word + if (opt & NGRAM_LOWERING) mkallsmall_utf(su2, l2, langnum); for (int j = 1; j <= n; j++) { ns = 0; for (int i = 0; i <= (l1-j); i++) { + int k = 0; for (int l = 0; l <= (l2-j); l++) { - int k; - for (k = 0; (k < j); k++) { + for (k = 0; k < j; k++) { w_char * c1 = su1 + i + k; w_char * c2 = su2 + l + k; if ((c1->l != c2->l) || (c1->h != c2->h)) break; } if (k == j) { - ns++; + ns++; break; - } - } + } + } + if (k != j && opt & NGRAM_WEIGHTED) { + ns--; + test++; + if (i == 0 || i == l1-j) ns--; // side weight + } } nscore = nscore + ns; - if (ns < 2) break; + if (ns < 2 && !(opt & NGRAM_WEIGHTED)) break; } } else { - char t[MAXSWUTF8L]; - l1 = strlen(s1); l2 = strlen(s2); - if (!l2) return 0; - strcpy(t, s2); - if (complexprefixes) { - *(t+l2-1) = csconv[((unsigned char)*(t+l2-1))].clower; - } else { - mkallsmall(t, csconv); - } + if (l2 == 0) return 0; + l1 = strlen(s1); + char *t = mystrdup(s2); + if (opt & NGRAM_LOWERING) mkallsmall(t, csconv); for (int j = 1; j <= n; j++) { ns = 0; for (int i = 0; i <= (l1-j); i++) { char c = *(s1 + i + j); *(s1 + i + j) = '\0'; - if (strstr(t,(s1+i))) ns++; + if (strstr(t,(s1+i))) { + ns++; + } else if (opt & NGRAM_WEIGHTED) { + ns--; +test++; + if (i == 0 || i == l1-j) ns--; // side weight + } *(s1 + i + j ) = c; } nscore = nscore + ns; - if (ns < 2) break; + if (ns < 2 && !(opt & NGRAM_WEIGHTED)) break; } + free(t); } ns = 0; - if (uselen == NGRAM_LONGER_WORSE) ns = (l2-l1)-2; - if (uselen == NGRAM_ANY_MISMATCH) ns = abs(l2-l1)-2; + if (opt & NGRAM_LONGER_WORSE) ns = (l2-l1)-2; + if (opt & NGRAM_ANY_MISMATCH) ns = abs(l2-l1)-2; ns = (nscore - ((ns > 0) ? ns : 0)); return ns; } -int SuggestMgr::equalfirstletter(char * s1, const char * s2) { +// length of the left common substring of s1 and (decapitalised) s2 +int SuggestMgr::leftcommonsubstring(char * s1, const char * s2) { if (utf8) { w_char su1[MAXSWL]; w_char su2[MAXSWL]; + su1[0].l = su2[0].l = su1[0].h = su2[0].h = 0; // decapitalize dictionary word if (complexprefixes) { int l1 = u8_u16(su1, MAXSWL, s1); int l2 = u8_u16(su2, MAXSWL, s2); if (*((short *)su1+l1-1) == *((short *)su2+l2-1)) return 1; } else { + int i; u8_u16(su1, 1, s1); u8_u16(su2, 1, s2); - if (*((short *)su1) == *((short *)su2)) return 1; + unsigned short idx = (su2->h << 8) + su2->l; + unsigned short otheridx = (su1->h << 8) + su1->l; + if (otheridx != idx && + (otheridx != unicodetolower(idx, langnum))) return 0; + int l1 = u8_u16(su1, MAXSWL, s1); + int l2 = u8_u16(su2, MAXSWL, s2); + for(i = 1; (i < l1) && (i < l2) && + (su1[i].l == su2[i].l) && (su1[i].h == su2[i].h); i++); + return i; } } else { if (complexprefixes) { @@ -1511,7 +1833,13 @@ int SuggestMgr::equalfirstletter(char * s1, const char * s2) { int l2 = strlen(s2); if (*(s2+l1-1) == *(s2+l2-1)) return 1; } else { - if (*s1 == *s2) return 1; + char * olds = s1; + // decapitalise dictionary word + if ((*s1 != *s2) && (*s1 != csconv[((unsigned char)*s2)].clower)) return 0; + do { + s1++; s2++; + } while ((*s1 == *s2) && (*s1 != '\0')); + return (int)(s1 - olds); } } return 0; @@ -1527,12 +1855,11 @@ int SuggestMgr::commoncharacterpositions(char * s1, const char * s2, int * is_sw w_char su2[MAXSWL]; int l1 = u8_u16(su1, MAXSWL, s1); int l2 = u8_u16(su2, MAXSWL, s2); - if (!l2 || (l1==-1) || (l2==-1)) return 0; // decapitalize dictionary word if (complexprefixes) { - mkallsmall_utf(su2+l2-1, 1, pAMgr->get_langnum()); + mkallsmall_utf(su2+l2-1, 1, langnum); } else { - mkallsmall_utf(su2, 1, pAMgr->get_langnum()); + mkallsmall_utf(su2, 1, langnum); } for (int i = 0; (i < l1) && (i < l2); i++) { if (((short *) su1)[i] == ((short *) su2)[i]) { @@ -1579,7 +1906,7 @@ int SuggestMgr::mystrlen(const char * word) { } // sort in decreasing order of score -void SuggestMgr::bubblesort(char** rword, int* rsc, int n ) +void SuggestMgr::bubblesort(char** rword, char** rword2, int* rsc, int n ) { int m = 1; while (m < n) { @@ -1592,6 +1919,11 @@ void SuggestMgr::bubblesort(char** rword, int* rsc, int n ) rword[j-1] = rword[j]; rsc[j] = sctmp; rword[j] = wdtmp; + if (rword2) { + wdtmp = rword2[j-1]; + rword2[j-1] = rword2[j]; + rword2[j] = wdtmp; + } j--; } else break; } @@ -1618,12 +1950,18 @@ void SuggestMgr::lcs(const char * s, const char * s2, int * l1, int * l2, char * } c = (char *) malloc((m + 1) * (n + 1)); b = (char *) malloc((m + 1) * (n + 1)); + if (!c || !b) { + if (c) free(c); + if (b) free(b); + *result = NULL; + return; + } for (i = 1; i <= m; i++) c[i*(n+1)] = 0; for (j = 0; j <= n; j++) c[j] = 0; for (i = 1; i <= m; i++) { for (j = 1; j <= n; j++) { - if ((utf8) && (*((short *) su+i-1) == *((short *)su2+j-1)) - || (!utf8) && ((*(s+i-1)) == (*(s2+j-1)))) { + if ( ((utf8) && (*((short *) su+i-1) == *((short *)su2+j-1))) + || ((!utf8) && ((*(s+i-1)) == (*(s2+j-1))))) { c[i*(n+1) + j] = c[(i-1)*(n+1) + j-1]+1; b[i*(n+1) + j] = LCS_UPLEFT; } else if (c[(i-1)*(n+1) + j] >= c[i*(n+1) + j-1]) { @@ -1649,6 +1987,7 @@ int SuggestMgr::lcslen(const char * s, const char* s2) { char * result; int len = 0; lcs(s, s2, &m, &n, &result); + if (!result) return 0; i = m; j = n; while ((i != 0) && (j != 0)) { @@ -1660,6 +1999,6 @@ int SuggestMgr::lcslen(const char * s, const char* s2) { i--; } else j--; } - if (result) free(result); + free(result); return len; } diff --git a/ext/hunspell/suggestmgr.hxx b/ext/hunspell/suggestmgr.hxx index 70af7f13f..5f043fdfd 100644 --- a/ext/hunspell/suggestmgr.hxx +++ b/ext/hunspell/suggestmgr.hxx @@ -5,15 +5,22 @@ #define MAXSWUTF8L (MAXSWL * 4) #define MAX_ROOTS 100 #define MAX_WORDS 100 -#define MAX_GUESS 100 -#define MAXNGRAMSUGS 5 +#define MAX_GUESS 200 +#define MAXNGRAMSUGS 4 +#define MAXPHONSUGS 2 +#define MAXCOMPOUNDSUGS 3 -#define MINTIMER 500 -#define MAXPLUSTIMER 500 +// timelimit: max ~1/4 sec (process time on Linux) for a time consuming function +#define TIMELIMIT (CLOCKS_PER_SEC >> 2) +#define MINTIMER 100 +#define MAXPLUSTIMER 100 -#define NGRAM_IGNORE_LENGTH 0 -#define NGRAM_LONGER_WORSE 1 -#define NGRAM_ANY_MISMATCH 2 +#define NGRAM_LONGER_WORSE (1 << 0) +#define NGRAM_ANY_MISMATCH (1 << 1) +#define NGRAM_LOWERING (1 << 2) +#define NGRAM_WEIGHTED (1 << 3) + +#include "hunvisapi.h" #include "atypes.hxx" #include "affixmgr.hxx" @@ -23,8 +30,12 @@ enum { LCS_UP, LCS_LEFT, LCS_UPLEFT }; -class SuggestMgr +class LIBHUNSPELL_DLL_EXPORTED SuggestMgr { + char * ckey; + int ckeyl; + w_char * ckey_utf; + char * ctry; int ctryl; w_char * ctry_utf; @@ -33,8 +44,10 @@ class SuggestMgr int maxSug; struct cs_info * csconv; int utf8; + int langnum; int nosplitsugs; int maxngramsugs; + int maxcpdsugs; int complexprefixes; @@ -42,19 +55,20 @@ public: SuggestMgr(const char * tryme, int maxn, AffixMgr *aptr); ~SuggestMgr(); - int suggest(char*** slst, const char * word, int nsug); - int ngsuggest(char ** wlst, char * word, HashMgr* pHMgr); + int suggest(char*** slst, const char * word, int nsug, int * onlycmpdsug); + int ngsuggest(char ** wlst, char * word, int ns, HashMgr** pHMgr, int md); int suggest_auto(char*** slst, const char * word, int nsug); int suggest_stems(char*** slst, const char * word, int nsug); int suggest_pos_stems(char*** slst, const char * word, int nsug); char * suggest_morph(const char * word); + char * suggest_gen(char ** pl, int pln, char * pattern); char * suggest_morph_for_spelling_error(const char * word); private: int testsug(char** wlst, const char * candidate, int wl, int ns, int cpdsuggest, - int * timer, time_t * timelimit); - int checkword(const char *, int, int, int *, time_t *); + int * timer, clock_t * timelimit); + int checkword(const char *, int, int, int *, clock_t *); int check_forbidden(const char *, int); int capchars(char **, const char *, int, int); @@ -65,6 +79,7 @@ private: int longswapchar(char **, const char *, int, int); int movechar(char **, const char *, int, int); int extrachar(char **, const char *, int, int); + int badcharkey(char **, const char *, int, int); int badchar(char **, const char *, int, int); int twowords(char **, const char *, int, int); int fixstems(char **, const char *, int); @@ -73,21 +88,22 @@ private: int doubletwochars_utf(char**, const w_char *, int wl, int, int); int forgotchar_utf(char**, const w_char *, int wl, int, int); int extrachar_utf(char**, const w_char *, int wl, int, int); + int badcharkey_utf(char **, const w_char *, int wl, int, int); int badchar_utf(char **, const w_char *, int wl, int, int); int swapchar_utf(char **, const w_char *, int wl, int, int); int longswapchar_utf(char **, const w_char *, int, int, int); int movechar_utf(char **, const w_char *, int, int, int); - int mapchars(char**, const char *, int); - int map_related(const char *, int, char ** wlst, int, const mapentry*, int, int *, time_t *); - int map_related_utf(w_char *, int, int, char ** wlst, int, const mapentry*, int, int *, time_t *); - int ngram(int n, char * s1, const char * s2, int uselen); + int mapchars(char**, const char *, int, int); + int map_related(const char *, char *, int, int, char ** wlst, int, int, const mapentry*, int, int *, clock_t *); + int ngram(int n, char * s1, const char * s2, int opt); int mystrlen(const char * word); - int equalfirstletter(char * s1, const char * s2); + int leftcommonsubstring(char * s1, const char * s2); int commoncharacterpositions(char * s1, const char * s2, int * is_swap); - void bubblesort( char ** rwd, int * rsc, int n); + void bubblesort( char ** rwd, char ** rwd2, int * rsc, int n); void lcs(const char * s, const char * s2, int * l1, int * l2, char ** result); int lcslen(const char * s, const char* s2); + char * suggest_hentry_gen(hentry * rv, char * pattern); }; diff --git a/ext/hunspell/utf_info.cxx b/ext/hunspell/utf_info.cxx index da3a32fd6..a4fcdd8c0 100644 --- a/ext/hunspell/utf_info.cxx +++ b/ext/hunspell/utf_info.cxx @@ -7065,6 +7065,11176 @@ static struct unicode_info utf_lst[] = { { 0xA825, 0xA825, 0xA825 }, { 0xA826, 0xA826, 0xA826 }, { 0xAC00, 0xAC00, 0xAC00 }, +{ 0xAC01, 0xAC01, 0xAC01 }, +{ 0xAC02, 0xAC02, 0xAC02 }, +{ 0xAC03, 0xAC03, 0xAC03 }, +{ 0xAC04, 0xAC04, 0xAC04 }, +{ 0xAC05, 0xAC05, 0xAC05 }, +{ 0xAC06, 0xAC06, 0xAC06 }, +{ 0xAC07, 0xAC07, 0xAC07 }, +{ 0xAC08, 0xAC08, 0xAC08 }, +{ 0xAC09, 0xAC09, 0xAC09 }, +{ 0xAC0A, 0xAC0A, 0xAC0A }, +{ 0xAC0B, 0xAC0B, 0xAC0B }, +{ 0xAC0C, 0xAC0C, 0xAC0C }, +{ 0xAC0D, 0xAC0D, 0xAC0D }, +{ 0xAC0E, 0xAC0E, 0xAC0E }, +{ 0xAC0F, 0xAC0F, 0xAC0F }, +{ 0xAC10, 0xAC10, 0xAC10 }, +{ 0xAC11, 0xAC11, 0xAC11 }, +{ 0xAC12, 0xAC12, 0xAC12 }, +{ 0xAC13, 0xAC13, 0xAC13 }, +{ 0xAC14, 0xAC14, 0xAC14 }, +{ 0xAC15, 0xAC15, 0xAC15 }, +{ 0xAC16, 0xAC16, 0xAC16 }, +{ 0xAC17, 0xAC17, 0xAC17 }, +{ 0xAC18, 0xAC18, 0xAC18 }, +{ 0xAC19, 0xAC19, 0xAC19 }, +{ 0xAC1A, 0xAC1A, 0xAC1A }, +{ 0xAC1B, 0xAC1B, 0xAC1B }, +{ 0xAC1C, 0xAC1C, 0xAC1C }, +{ 0xAC1D, 0xAC1D, 0xAC1D }, +{ 0xAC1E, 0xAC1E, 0xAC1E }, +{ 0xAC1F, 0xAC1F, 0xAC1F }, +{ 0xAC20, 0xAC20, 0xAC20 }, +{ 0xAC21, 0xAC21, 0xAC21 }, +{ 0xAC22, 0xAC22, 0xAC22 }, +{ 0xAC23, 0xAC23, 0xAC23 }, +{ 0xAC24, 0xAC24, 0xAC24 }, +{ 0xAC25, 0xAC25, 0xAC25 }, +{ 0xAC26, 0xAC26, 0xAC26 }, +{ 0xAC27, 0xAC27, 0xAC27 }, +{ 0xAC28, 0xAC28, 0xAC28 }, +{ 0xAC29, 0xAC29, 0xAC29 }, +{ 0xAC2A, 0xAC2A, 0xAC2A }, +{ 0xAC2B, 0xAC2B, 0xAC2B }, +{ 0xAC2C, 0xAC2C, 0xAC2C }, +{ 0xAC2D, 0xAC2D, 0xAC2D }, +{ 0xAC2E, 0xAC2E, 0xAC2E }, +{ 0xAC2F, 0xAC2F, 0xAC2F }, +{ 0xAC30, 0xAC30, 0xAC30 }, +{ 0xAC31, 0xAC31, 0xAC31 }, +{ 0xAC32, 0xAC32, 0xAC32 }, +{ 0xAC33, 0xAC33, 0xAC33 }, +{ 0xAC34, 0xAC34, 0xAC34 }, +{ 0xAC35, 0xAC35, 0xAC35 }, +{ 0xAC36, 0xAC36, 0xAC36 }, +{ 0xAC37, 0xAC37, 0xAC37 }, +{ 0xAC38, 0xAC38, 0xAC38 }, +{ 0xAC39, 0xAC39, 0xAC39 }, +{ 0xAC3A, 0xAC3A, 0xAC3A }, +{ 0xAC3B, 0xAC3B, 0xAC3B }, +{ 0xAC3C, 0xAC3C, 0xAC3C }, +{ 0xAC3D, 0xAC3D, 0xAC3D }, +{ 0xAC3E, 0xAC3E, 0xAC3E }, +{ 0xAC3F, 0xAC3F, 0xAC3F }, +{ 0xAC40, 0xAC40, 0xAC40 }, +{ 0xAC41, 0xAC41, 0xAC41 }, +{ 0xAC42, 0xAC42, 0xAC42 }, +{ 0xAC43, 0xAC43, 0xAC43 }, +{ 0xAC44, 0xAC44, 0xAC44 }, +{ 0xAC45, 0xAC45, 0xAC45 }, +{ 0xAC46, 0xAC46, 0xAC46 }, +{ 0xAC47, 0xAC47, 0xAC47 }, +{ 0xAC48, 0xAC48, 0xAC48 }, +{ 0xAC49, 0xAC49, 0xAC49 }, +{ 0xAC4A, 0xAC4A, 0xAC4A }, +{ 0xAC4B, 0xAC4B, 0xAC4B }, +{ 0xAC4C, 0xAC4C, 0xAC4C }, +{ 0xAC4D, 0xAC4D, 0xAC4D }, +{ 0xAC4E, 0xAC4E, 0xAC4E }, +{ 0xAC4F, 0xAC4F, 0xAC4F }, +{ 0xAC50, 0xAC50, 0xAC50 }, +{ 0xAC51, 0xAC51, 0xAC51 }, +{ 0xAC52, 0xAC52, 0xAC52 }, +{ 0xAC53, 0xAC53, 0xAC53 }, +{ 0xAC54, 0xAC54, 0xAC54 }, +{ 0xAC55, 0xAC55, 0xAC55 }, +{ 0xAC56, 0xAC56, 0xAC56 }, +{ 0xAC57, 0xAC57, 0xAC57 }, +{ 0xAC58, 0xAC58, 0xAC58 }, +{ 0xAC59, 0xAC59, 0xAC59 }, +{ 0xAC5A, 0xAC5A, 0xAC5A }, +{ 0xAC5B, 0xAC5B, 0xAC5B }, +{ 0xAC5C, 0xAC5C, 0xAC5C }, +{ 0xAC5D, 0xAC5D, 0xAC5D }, +{ 0xAC5E, 0xAC5E, 0xAC5E }, +{ 0xAC5F, 0xAC5F, 0xAC5F }, +{ 0xAC60, 0xAC60, 0xAC60 }, +{ 0xAC61, 0xAC61, 0xAC61 }, +{ 0xAC62, 0xAC62, 0xAC62 }, +{ 0xAC63, 0xAC63, 0xAC63 }, +{ 0xAC64, 0xAC64, 0xAC64 }, +{ 0xAC65, 0xAC65, 0xAC65 }, +{ 0xAC66, 0xAC66, 0xAC66 }, +{ 0xAC67, 0xAC67, 0xAC67 }, +{ 0xAC68, 0xAC68, 0xAC68 }, +{ 0xAC69, 0xAC69, 0xAC69 }, +{ 0xAC6A, 0xAC6A, 0xAC6A }, +{ 0xAC6B, 0xAC6B, 0xAC6B }, +{ 0xAC6C, 0xAC6C, 0xAC6C }, +{ 0xAC6D, 0xAC6D, 0xAC6D }, +{ 0xAC6E, 0xAC6E, 0xAC6E }, +{ 0xAC6F, 0xAC6F, 0xAC6F }, +{ 0xAC70, 0xAC70, 0xAC70 }, +{ 0xAC71, 0xAC71, 0xAC71 }, +{ 0xAC72, 0xAC72, 0xAC72 }, +{ 0xAC73, 0xAC73, 0xAC73 }, +{ 0xAC74, 0xAC74, 0xAC74 }, +{ 0xAC75, 0xAC75, 0xAC75 }, +{ 0xAC76, 0xAC76, 0xAC76 }, +{ 0xAC77, 0xAC77, 0xAC77 }, +{ 0xAC78, 0xAC78, 0xAC78 }, +{ 0xAC79, 0xAC79, 0xAC79 }, +{ 0xAC7A, 0xAC7A, 0xAC7A }, +{ 0xAC7B, 0xAC7B, 0xAC7B }, +{ 0xAC7C, 0xAC7C, 0xAC7C }, +{ 0xAC7D, 0xAC7D, 0xAC7D }, +{ 0xAC7E, 0xAC7E, 0xAC7E }, +{ 0xAC7F, 0xAC7F, 0xAC7F }, +{ 0xAC80, 0xAC80, 0xAC80 }, +{ 0xAC81, 0xAC81, 0xAC81 }, +{ 0xAC82, 0xAC82, 0xAC82 }, +{ 0xAC83, 0xAC83, 0xAC83 }, +{ 0xAC84, 0xAC84, 0xAC84 }, +{ 0xAC85, 0xAC85, 0xAC85 }, +{ 0xAC86, 0xAC86, 0xAC86 }, +{ 0xAC87, 0xAC87, 0xAC87 }, +{ 0xAC88, 0xAC88, 0xAC88 }, +{ 0xAC89, 0xAC89, 0xAC89 }, +{ 0xAC8A, 0xAC8A, 0xAC8A }, +{ 0xAC8B, 0xAC8B, 0xAC8B }, +{ 0xAC8C, 0xAC8C, 0xAC8C }, +{ 0xAC8D, 0xAC8D, 0xAC8D }, +{ 0xAC8E, 0xAC8E, 0xAC8E }, +{ 0xAC8F, 0xAC8F, 0xAC8F }, +{ 0xAC90, 0xAC90, 0xAC90 }, +{ 0xAC91, 0xAC91, 0xAC91 }, +{ 0xAC92, 0xAC92, 0xAC92 }, +{ 0xAC93, 0xAC93, 0xAC93 }, +{ 0xAC94, 0xAC94, 0xAC94 }, +{ 0xAC95, 0xAC95, 0xAC95 }, +{ 0xAC96, 0xAC96, 0xAC96 }, +{ 0xAC97, 0xAC97, 0xAC97 }, +{ 0xAC98, 0xAC98, 0xAC98 }, +{ 0xAC99, 0xAC99, 0xAC99 }, +{ 0xAC9A, 0xAC9A, 0xAC9A }, +{ 0xAC9B, 0xAC9B, 0xAC9B }, +{ 0xAC9C, 0xAC9C, 0xAC9C }, +{ 0xAC9D, 0xAC9D, 0xAC9D }, +{ 0xAC9E, 0xAC9E, 0xAC9E }, +{ 0xAC9F, 0xAC9F, 0xAC9F }, +{ 0xACA0, 0xACA0, 0xACA0 }, +{ 0xACA1, 0xACA1, 0xACA1 }, +{ 0xACA2, 0xACA2, 0xACA2 }, +{ 0xACA3, 0xACA3, 0xACA3 }, +{ 0xACA4, 0xACA4, 0xACA4 }, +{ 0xACA5, 0xACA5, 0xACA5 }, +{ 0xACA6, 0xACA6, 0xACA6 }, +{ 0xACA7, 0xACA7, 0xACA7 }, +{ 0xACA8, 0xACA8, 0xACA8 }, +{ 0xACA9, 0xACA9, 0xACA9 }, +{ 0xACAA, 0xACAA, 0xACAA }, +{ 0xACAB, 0xACAB, 0xACAB }, +{ 0xACAC, 0xACAC, 0xACAC }, +{ 0xACAD, 0xACAD, 0xACAD }, +{ 0xACAE, 0xACAE, 0xACAE }, +{ 0xACAF, 0xACAF, 0xACAF }, +{ 0xACB0, 0xACB0, 0xACB0 }, +{ 0xACB1, 0xACB1, 0xACB1 }, +{ 0xACB2, 0xACB2, 0xACB2 }, +{ 0xACB3, 0xACB3, 0xACB3 }, +{ 0xACB4, 0xACB4, 0xACB4 }, +{ 0xACB5, 0xACB5, 0xACB5 }, +{ 0xACB6, 0xACB6, 0xACB6 }, +{ 0xACB7, 0xACB7, 0xACB7 }, +{ 0xACB8, 0xACB8, 0xACB8 }, +{ 0xACB9, 0xACB9, 0xACB9 }, +{ 0xACBA, 0xACBA, 0xACBA }, +{ 0xACBB, 0xACBB, 0xACBB }, +{ 0xACBC, 0xACBC, 0xACBC }, +{ 0xACBD, 0xACBD, 0xACBD }, +{ 0xACBE, 0xACBE, 0xACBE }, +{ 0xACBF, 0xACBF, 0xACBF }, +{ 0xACC0, 0xACC0, 0xACC0 }, +{ 0xACC1, 0xACC1, 0xACC1 }, +{ 0xACC2, 0xACC2, 0xACC2 }, +{ 0xACC3, 0xACC3, 0xACC3 }, +{ 0xACC4, 0xACC4, 0xACC4 }, +{ 0xACC5, 0xACC5, 0xACC5 }, +{ 0xACC6, 0xACC6, 0xACC6 }, +{ 0xACC7, 0xACC7, 0xACC7 }, +{ 0xACC8, 0xACC8, 0xACC8 }, +{ 0xACC9, 0xACC9, 0xACC9 }, +{ 0xACCA, 0xACCA, 0xACCA }, +{ 0xACCB, 0xACCB, 0xACCB }, +{ 0xACCC, 0xACCC, 0xACCC }, +{ 0xACCD, 0xACCD, 0xACCD }, +{ 0xACCE, 0xACCE, 0xACCE }, +{ 0xACCF, 0xACCF, 0xACCF }, +{ 0xACD0, 0xACD0, 0xACD0 }, +{ 0xACD1, 0xACD1, 0xACD1 }, +{ 0xACD2, 0xACD2, 0xACD2 }, +{ 0xACD3, 0xACD3, 0xACD3 }, +{ 0xACD4, 0xACD4, 0xACD4 }, +{ 0xACD5, 0xACD5, 0xACD5 }, +{ 0xACD6, 0xACD6, 0xACD6 }, +{ 0xACD7, 0xACD7, 0xACD7 }, +{ 0xACD8, 0xACD8, 0xACD8 }, +{ 0xACD9, 0xACD9, 0xACD9 }, +{ 0xACDA, 0xACDA, 0xACDA }, +{ 0xACDB, 0xACDB, 0xACDB }, +{ 0xACDC, 0xACDC, 0xACDC }, +{ 0xACDD, 0xACDD, 0xACDD }, +{ 0xACDE, 0xACDE, 0xACDE }, +{ 0xACDF, 0xACDF, 0xACDF }, +{ 0xACE0, 0xACE0, 0xACE0 }, +{ 0xACE1, 0xACE1, 0xACE1 }, +{ 0xACE2, 0xACE2, 0xACE2 }, +{ 0xACE3, 0xACE3, 0xACE3 }, +{ 0xACE4, 0xACE4, 0xACE4 }, +{ 0xACE5, 0xACE5, 0xACE5 }, +{ 0xACE6, 0xACE6, 0xACE6 }, +{ 0xACE7, 0xACE7, 0xACE7 }, +{ 0xACE8, 0xACE8, 0xACE8 }, +{ 0xACE9, 0xACE9, 0xACE9 }, +{ 0xACEA, 0xACEA, 0xACEA }, +{ 0xACEB, 0xACEB, 0xACEB }, +{ 0xACEC, 0xACEC, 0xACEC }, +{ 0xACED, 0xACED, 0xACED }, +{ 0xACEE, 0xACEE, 0xACEE }, +{ 0xACEF, 0xACEF, 0xACEF }, +{ 0xACF0, 0xACF0, 0xACF0 }, +{ 0xACF1, 0xACF1, 0xACF1 }, +{ 0xACF2, 0xACF2, 0xACF2 }, +{ 0xACF3, 0xACF3, 0xACF3 }, +{ 0xACF4, 0xACF4, 0xACF4 }, +{ 0xACF5, 0xACF5, 0xACF5 }, +{ 0xACF6, 0xACF6, 0xACF6 }, +{ 0xACF7, 0xACF7, 0xACF7 }, +{ 0xACF8, 0xACF8, 0xACF8 }, +{ 0xACF9, 0xACF9, 0xACF9 }, +{ 0xACFA, 0xACFA, 0xACFA }, +{ 0xACFB, 0xACFB, 0xACFB }, +{ 0xACFC, 0xACFC, 0xACFC }, +{ 0xACFD, 0xACFD, 0xACFD }, +{ 0xACFE, 0xACFE, 0xACFE }, +{ 0xACFF, 0xACFF, 0xACFF }, +{ 0xAD00, 0xAD00, 0xAD00 }, +{ 0xAD01, 0xAD01, 0xAD01 }, +{ 0xAD02, 0xAD02, 0xAD02 }, +{ 0xAD03, 0xAD03, 0xAD03 }, +{ 0xAD04, 0xAD04, 0xAD04 }, +{ 0xAD05, 0xAD05, 0xAD05 }, +{ 0xAD06, 0xAD06, 0xAD06 }, +{ 0xAD07, 0xAD07, 0xAD07 }, +{ 0xAD08, 0xAD08, 0xAD08 }, +{ 0xAD09, 0xAD09, 0xAD09 }, +{ 0xAD0A, 0xAD0A, 0xAD0A }, +{ 0xAD0B, 0xAD0B, 0xAD0B }, +{ 0xAD0C, 0xAD0C, 0xAD0C }, +{ 0xAD0D, 0xAD0D, 0xAD0D }, +{ 0xAD0E, 0xAD0E, 0xAD0E }, +{ 0xAD0F, 0xAD0F, 0xAD0F }, +{ 0xAD10, 0xAD10, 0xAD10 }, +{ 0xAD11, 0xAD11, 0xAD11 }, +{ 0xAD12, 0xAD12, 0xAD12 }, +{ 0xAD13, 0xAD13, 0xAD13 }, +{ 0xAD14, 0xAD14, 0xAD14 }, +{ 0xAD15, 0xAD15, 0xAD15 }, +{ 0xAD16, 0xAD16, 0xAD16 }, +{ 0xAD17, 0xAD17, 0xAD17 }, +{ 0xAD18, 0xAD18, 0xAD18 }, +{ 0xAD19, 0xAD19, 0xAD19 }, +{ 0xAD1A, 0xAD1A, 0xAD1A }, +{ 0xAD1B, 0xAD1B, 0xAD1B }, +{ 0xAD1C, 0xAD1C, 0xAD1C }, +{ 0xAD1D, 0xAD1D, 0xAD1D }, +{ 0xAD1E, 0xAD1E, 0xAD1E }, +{ 0xAD1F, 0xAD1F, 0xAD1F }, +{ 0xAD20, 0xAD20, 0xAD20 }, +{ 0xAD21, 0xAD21, 0xAD21 }, +{ 0xAD22, 0xAD22, 0xAD22 }, +{ 0xAD23, 0xAD23, 0xAD23 }, +{ 0xAD24, 0xAD24, 0xAD24 }, +{ 0xAD25, 0xAD25, 0xAD25 }, +{ 0xAD26, 0xAD26, 0xAD26 }, +{ 0xAD27, 0xAD27, 0xAD27 }, +{ 0xAD28, 0xAD28, 0xAD28 }, +{ 0xAD29, 0xAD29, 0xAD29 }, +{ 0xAD2A, 0xAD2A, 0xAD2A }, +{ 0xAD2B, 0xAD2B, 0xAD2B }, +{ 0xAD2C, 0xAD2C, 0xAD2C }, +{ 0xAD2D, 0xAD2D, 0xAD2D }, +{ 0xAD2E, 0xAD2E, 0xAD2E }, +{ 0xAD2F, 0xAD2F, 0xAD2F }, +{ 0xAD30, 0xAD30, 0xAD30 }, +{ 0xAD31, 0xAD31, 0xAD31 }, +{ 0xAD32, 0xAD32, 0xAD32 }, +{ 0xAD33, 0xAD33, 0xAD33 }, +{ 0xAD34, 0xAD34, 0xAD34 }, +{ 0xAD35, 0xAD35, 0xAD35 }, +{ 0xAD36, 0xAD36, 0xAD36 }, +{ 0xAD37, 0xAD37, 0xAD37 }, +{ 0xAD38, 0xAD38, 0xAD38 }, +{ 0xAD39, 0xAD39, 0xAD39 }, +{ 0xAD3A, 0xAD3A, 0xAD3A }, +{ 0xAD3B, 0xAD3B, 0xAD3B }, +{ 0xAD3C, 0xAD3C, 0xAD3C }, +{ 0xAD3D, 0xAD3D, 0xAD3D }, +{ 0xAD3E, 0xAD3E, 0xAD3E }, +{ 0xAD3F, 0xAD3F, 0xAD3F }, +{ 0xAD40, 0xAD40, 0xAD40 }, +{ 0xAD41, 0xAD41, 0xAD41 }, +{ 0xAD42, 0xAD42, 0xAD42 }, +{ 0xAD43, 0xAD43, 0xAD43 }, +{ 0xAD44, 0xAD44, 0xAD44 }, +{ 0xAD45, 0xAD45, 0xAD45 }, +{ 0xAD46, 0xAD46, 0xAD46 }, +{ 0xAD47, 0xAD47, 0xAD47 }, +{ 0xAD48, 0xAD48, 0xAD48 }, +{ 0xAD49, 0xAD49, 0xAD49 }, +{ 0xAD4A, 0xAD4A, 0xAD4A }, +{ 0xAD4B, 0xAD4B, 0xAD4B }, +{ 0xAD4C, 0xAD4C, 0xAD4C }, +{ 0xAD4D, 0xAD4D, 0xAD4D }, +{ 0xAD4E, 0xAD4E, 0xAD4E }, +{ 0xAD4F, 0xAD4F, 0xAD4F }, +{ 0xAD50, 0xAD50, 0xAD50 }, +{ 0xAD51, 0xAD51, 0xAD51 }, +{ 0xAD52, 0xAD52, 0xAD52 }, +{ 0xAD53, 0xAD53, 0xAD53 }, +{ 0xAD54, 0xAD54, 0xAD54 }, +{ 0xAD55, 0xAD55, 0xAD55 }, +{ 0xAD56, 0xAD56, 0xAD56 }, +{ 0xAD57, 0xAD57, 0xAD57 }, +{ 0xAD58, 0xAD58, 0xAD58 }, +{ 0xAD59, 0xAD59, 0xAD59 }, +{ 0xAD5A, 0xAD5A, 0xAD5A }, +{ 0xAD5B, 0xAD5B, 0xAD5B }, +{ 0xAD5C, 0xAD5C, 0xAD5C }, +{ 0xAD5D, 0xAD5D, 0xAD5D }, +{ 0xAD5E, 0xAD5E, 0xAD5E }, +{ 0xAD5F, 0xAD5F, 0xAD5F }, +{ 0xAD60, 0xAD60, 0xAD60 }, +{ 0xAD61, 0xAD61, 0xAD61 }, +{ 0xAD62, 0xAD62, 0xAD62 }, +{ 0xAD63, 0xAD63, 0xAD63 }, +{ 0xAD64, 0xAD64, 0xAD64 }, +{ 0xAD65, 0xAD65, 0xAD65 }, +{ 0xAD66, 0xAD66, 0xAD66 }, +{ 0xAD67, 0xAD67, 0xAD67 }, +{ 0xAD68, 0xAD68, 0xAD68 }, +{ 0xAD69, 0xAD69, 0xAD69 }, +{ 0xAD6A, 0xAD6A, 0xAD6A }, +{ 0xAD6B, 0xAD6B, 0xAD6B }, +{ 0xAD6C, 0xAD6C, 0xAD6C }, +{ 0xAD6D, 0xAD6D, 0xAD6D }, +{ 0xAD6E, 0xAD6E, 0xAD6E }, +{ 0xAD6F, 0xAD6F, 0xAD6F }, +{ 0xAD70, 0xAD70, 0xAD70 }, +{ 0xAD71, 0xAD71, 0xAD71 }, +{ 0xAD72, 0xAD72, 0xAD72 }, +{ 0xAD73, 0xAD73, 0xAD73 }, +{ 0xAD74, 0xAD74, 0xAD74 }, +{ 0xAD75, 0xAD75, 0xAD75 }, +{ 0xAD76, 0xAD76, 0xAD76 }, +{ 0xAD77, 0xAD77, 0xAD77 }, +{ 0xAD78, 0xAD78, 0xAD78 }, +{ 0xAD79, 0xAD79, 0xAD79 }, +{ 0xAD7A, 0xAD7A, 0xAD7A }, +{ 0xAD7B, 0xAD7B, 0xAD7B }, +{ 0xAD7C, 0xAD7C, 0xAD7C }, +{ 0xAD7D, 0xAD7D, 0xAD7D }, +{ 0xAD7E, 0xAD7E, 0xAD7E }, +{ 0xAD7F, 0xAD7F, 0xAD7F }, +{ 0xAD80, 0xAD80, 0xAD80 }, +{ 0xAD81, 0xAD81, 0xAD81 }, +{ 0xAD82, 0xAD82, 0xAD82 }, +{ 0xAD83, 0xAD83, 0xAD83 }, +{ 0xAD84, 0xAD84, 0xAD84 }, +{ 0xAD85, 0xAD85, 0xAD85 }, +{ 0xAD86, 0xAD86, 0xAD86 }, +{ 0xAD87, 0xAD87, 0xAD87 }, +{ 0xAD88, 0xAD88, 0xAD88 }, +{ 0xAD89, 0xAD89, 0xAD89 }, +{ 0xAD8A, 0xAD8A, 0xAD8A }, +{ 0xAD8B, 0xAD8B, 0xAD8B }, +{ 0xAD8C, 0xAD8C, 0xAD8C }, +{ 0xAD8D, 0xAD8D, 0xAD8D }, +{ 0xAD8E, 0xAD8E, 0xAD8E }, +{ 0xAD8F, 0xAD8F, 0xAD8F }, +{ 0xAD90, 0xAD90, 0xAD90 }, +{ 0xAD91, 0xAD91, 0xAD91 }, +{ 0xAD92, 0xAD92, 0xAD92 }, +{ 0xAD93, 0xAD93, 0xAD93 }, +{ 0xAD94, 0xAD94, 0xAD94 }, +{ 0xAD95, 0xAD95, 0xAD95 }, +{ 0xAD96, 0xAD96, 0xAD96 }, +{ 0xAD97, 0xAD97, 0xAD97 }, +{ 0xAD98, 0xAD98, 0xAD98 }, +{ 0xAD99, 0xAD99, 0xAD99 }, +{ 0xAD9A, 0xAD9A, 0xAD9A }, +{ 0xAD9B, 0xAD9B, 0xAD9B }, +{ 0xAD9C, 0xAD9C, 0xAD9C }, +{ 0xAD9D, 0xAD9D, 0xAD9D }, +{ 0xAD9E, 0xAD9E, 0xAD9E }, +{ 0xAD9F, 0xAD9F, 0xAD9F }, +{ 0xADA0, 0xADA0, 0xADA0 }, +{ 0xADA1, 0xADA1, 0xADA1 }, +{ 0xADA2, 0xADA2, 0xADA2 }, +{ 0xADA3, 0xADA3, 0xADA3 }, +{ 0xADA4, 0xADA4, 0xADA4 }, +{ 0xADA5, 0xADA5, 0xADA5 }, +{ 0xADA6, 0xADA6, 0xADA6 }, +{ 0xADA7, 0xADA7, 0xADA7 }, +{ 0xADA8, 0xADA8, 0xADA8 }, +{ 0xADA9, 0xADA9, 0xADA9 }, +{ 0xADAA, 0xADAA, 0xADAA }, +{ 0xADAB, 0xADAB, 0xADAB }, +{ 0xADAC, 0xADAC, 0xADAC }, +{ 0xADAD, 0xADAD, 0xADAD }, +{ 0xADAE, 0xADAE, 0xADAE }, +{ 0xADAF, 0xADAF, 0xADAF }, +{ 0xADB0, 0xADB0, 0xADB0 }, +{ 0xADB1, 0xADB1, 0xADB1 }, +{ 0xADB2, 0xADB2, 0xADB2 }, +{ 0xADB3, 0xADB3, 0xADB3 }, +{ 0xADB4, 0xADB4, 0xADB4 }, +{ 0xADB5, 0xADB5, 0xADB5 }, +{ 0xADB6, 0xADB6, 0xADB6 }, +{ 0xADB7, 0xADB7, 0xADB7 }, +{ 0xADB8, 0xADB8, 0xADB8 }, +{ 0xADB9, 0xADB9, 0xADB9 }, +{ 0xADBA, 0xADBA, 0xADBA }, +{ 0xADBB, 0xADBB, 0xADBB }, +{ 0xADBC, 0xADBC, 0xADBC }, +{ 0xADBD, 0xADBD, 0xADBD }, +{ 0xADBE, 0xADBE, 0xADBE }, +{ 0xADBF, 0xADBF, 0xADBF }, +{ 0xADC0, 0xADC0, 0xADC0 }, +{ 0xADC1, 0xADC1, 0xADC1 }, +{ 0xADC2, 0xADC2, 0xADC2 }, +{ 0xADC3, 0xADC3, 0xADC3 }, +{ 0xADC4, 0xADC4, 0xADC4 }, +{ 0xADC5, 0xADC5, 0xADC5 }, +{ 0xADC6, 0xADC6, 0xADC6 }, +{ 0xADC7, 0xADC7, 0xADC7 }, +{ 0xADC8, 0xADC8, 0xADC8 }, +{ 0xADC9, 0xADC9, 0xADC9 }, +{ 0xADCA, 0xADCA, 0xADCA }, +{ 0xADCB, 0xADCB, 0xADCB }, +{ 0xADCC, 0xADCC, 0xADCC }, +{ 0xADCD, 0xADCD, 0xADCD }, +{ 0xADCE, 0xADCE, 0xADCE }, +{ 0xADCF, 0xADCF, 0xADCF }, +{ 0xADD0, 0xADD0, 0xADD0 }, +{ 0xADD1, 0xADD1, 0xADD1 }, +{ 0xADD2, 0xADD2, 0xADD2 }, +{ 0xADD3, 0xADD3, 0xADD3 }, +{ 0xADD4, 0xADD4, 0xADD4 }, +{ 0xADD5, 0xADD5, 0xADD5 }, +{ 0xADD6, 0xADD6, 0xADD6 }, +{ 0xADD7, 0xADD7, 0xADD7 }, +{ 0xADD8, 0xADD8, 0xADD8 }, +{ 0xADD9, 0xADD9, 0xADD9 }, +{ 0xADDA, 0xADDA, 0xADDA }, +{ 0xADDB, 0xADDB, 0xADDB }, +{ 0xADDC, 0xADDC, 0xADDC }, +{ 0xADDD, 0xADDD, 0xADDD }, +{ 0xADDE, 0xADDE, 0xADDE }, +{ 0xADDF, 0xADDF, 0xADDF }, +{ 0xADE0, 0xADE0, 0xADE0 }, +{ 0xADE1, 0xADE1, 0xADE1 }, +{ 0xADE2, 0xADE2, 0xADE2 }, +{ 0xADE3, 0xADE3, 0xADE3 }, +{ 0xADE4, 0xADE4, 0xADE4 }, +{ 0xADE5, 0xADE5, 0xADE5 }, +{ 0xADE6, 0xADE6, 0xADE6 }, +{ 0xADE7, 0xADE7, 0xADE7 }, +{ 0xADE8, 0xADE8, 0xADE8 }, +{ 0xADE9, 0xADE9, 0xADE9 }, +{ 0xADEA, 0xADEA, 0xADEA }, +{ 0xADEB, 0xADEB, 0xADEB }, +{ 0xADEC, 0xADEC, 0xADEC }, +{ 0xADED, 0xADED, 0xADED }, +{ 0xADEE, 0xADEE, 0xADEE }, +{ 0xADEF, 0xADEF, 0xADEF }, +{ 0xADF0, 0xADF0, 0xADF0 }, +{ 0xADF1, 0xADF1, 0xADF1 }, +{ 0xADF2, 0xADF2, 0xADF2 }, +{ 0xADF3, 0xADF3, 0xADF3 }, +{ 0xADF4, 0xADF4, 0xADF4 }, +{ 0xADF5, 0xADF5, 0xADF5 }, +{ 0xADF6, 0xADF6, 0xADF6 }, +{ 0xADF7, 0xADF7, 0xADF7 }, +{ 0xADF8, 0xADF8, 0xADF8 }, +{ 0xADF9, 0xADF9, 0xADF9 }, +{ 0xADFA, 0xADFA, 0xADFA }, +{ 0xADFB, 0xADFB, 0xADFB }, +{ 0xADFC, 0xADFC, 0xADFC }, +{ 0xADFD, 0xADFD, 0xADFD }, +{ 0xADFE, 0xADFE, 0xADFE }, +{ 0xADFF, 0xADFF, 0xADFF }, +{ 0xAE00, 0xAE00, 0xAE00 }, +{ 0xAE01, 0xAE01, 0xAE01 }, +{ 0xAE02, 0xAE02, 0xAE02 }, +{ 0xAE03, 0xAE03, 0xAE03 }, +{ 0xAE04, 0xAE04, 0xAE04 }, +{ 0xAE05, 0xAE05, 0xAE05 }, +{ 0xAE06, 0xAE06, 0xAE06 }, +{ 0xAE07, 0xAE07, 0xAE07 }, +{ 0xAE08, 0xAE08, 0xAE08 }, +{ 0xAE09, 0xAE09, 0xAE09 }, +{ 0xAE0A, 0xAE0A, 0xAE0A }, +{ 0xAE0B, 0xAE0B, 0xAE0B }, +{ 0xAE0C, 0xAE0C, 0xAE0C }, +{ 0xAE0D, 0xAE0D, 0xAE0D }, +{ 0xAE0E, 0xAE0E, 0xAE0E }, +{ 0xAE0F, 0xAE0F, 0xAE0F }, +{ 0xAE10, 0xAE10, 0xAE10 }, +{ 0xAE11, 0xAE11, 0xAE11 }, +{ 0xAE12, 0xAE12, 0xAE12 }, +{ 0xAE13, 0xAE13, 0xAE13 }, +{ 0xAE14, 0xAE14, 0xAE14 }, +{ 0xAE15, 0xAE15, 0xAE15 }, +{ 0xAE16, 0xAE16, 0xAE16 }, +{ 0xAE17, 0xAE17, 0xAE17 }, +{ 0xAE18, 0xAE18, 0xAE18 }, +{ 0xAE19, 0xAE19, 0xAE19 }, +{ 0xAE1A, 0xAE1A, 0xAE1A }, +{ 0xAE1B, 0xAE1B, 0xAE1B }, +{ 0xAE1C, 0xAE1C, 0xAE1C }, +{ 0xAE1D, 0xAE1D, 0xAE1D }, +{ 0xAE1E, 0xAE1E, 0xAE1E }, +{ 0xAE1F, 0xAE1F, 0xAE1F }, +{ 0xAE20, 0xAE20, 0xAE20 }, +{ 0xAE21, 0xAE21, 0xAE21 }, +{ 0xAE22, 0xAE22, 0xAE22 }, +{ 0xAE23, 0xAE23, 0xAE23 }, +{ 0xAE24, 0xAE24, 0xAE24 }, +{ 0xAE25, 0xAE25, 0xAE25 }, +{ 0xAE26, 0xAE26, 0xAE26 }, +{ 0xAE27, 0xAE27, 0xAE27 }, +{ 0xAE28, 0xAE28, 0xAE28 }, +{ 0xAE29, 0xAE29, 0xAE29 }, +{ 0xAE2A, 0xAE2A, 0xAE2A }, +{ 0xAE2B, 0xAE2B, 0xAE2B }, +{ 0xAE2C, 0xAE2C, 0xAE2C }, +{ 0xAE2D, 0xAE2D, 0xAE2D }, +{ 0xAE2E, 0xAE2E, 0xAE2E }, +{ 0xAE2F, 0xAE2F, 0xAE2F }, +{ 0xAE30, 0xAE30, 0xAE30 }, +{ 0xAE31, 0xAE31, 0xAE31 }, +{ 0xAE32, 0xAE32, 0xAE32 }, +{ 0xAE33, 0xAE33, 0xAE33 }, +{ 0xAE34, 0xAE34, 0xAE34 }, +{ 0xAE35, 0xAE35, 0xAE35 }, +{ 0xAE36, 0xAE36, 0xAE36 }, +{ 0xAE37, 0xAE37, 0xAE37 }, +{ 0xAE38, 0xAE38, 0xAE38 }, +{ 0xAE39, 0xAE39, 0xAE39 }, +{ 0xAE3A, 0xAE3A, 0xAE3A }, +{ 0xAE3B, 0xAE3B, 0xAE3B }, +{ 0xAE3C, 0xAE3C, 0xAE3C }, +{ 0xAE3D, 0xAE3D, 0xAE3D }, +{ 0xAE3E, 0xAE3E, 0xAE3E }, +{ 0xAE3F, 0xAE3F, 0xAE3F }, +{ 0xAE40, 0xAE40, 0xAE40 }, +{ 0xAE41, 0xAE41, 0xAE41 }, +{ 0xAE42, 0xAE42, 0xAE42 }, +{ 0xAE43, 0xAE43, 0xAE43 }, +{ 0xAE44, 0xAE44, 0xAE44 }, +{ 0xAE45, 0xAE45, 0xAE45 }, +{ 0xAE46, 0xAE46, 0xAE46 }, +{ 0xAE47, 0xAE47, 0xAE47 }, +{ 0xAE48, 0xAE48, 0xAE48 }, +{ 0xAE49, 0xAE49, 0xAE49 }, +{ 0xAE4A, 0xAE4A, 0xAE4A }, +{ 0xAE4B, 0xAE4B, 0xAE4B }, +{ 0xAE4C, 0xAE4C, 0xAE4C }, +{ 0xAE4D, 0xAE4D, 0xAE4D }, +{ 0xAE4E, 0xAE4E, 0xAE4E }, +{ 0xAE4F, 0xAE4F, 0xAE4F }, +{ 0xAE50, 0xAE50, 0xAE50 }, +{ 0xAE51, 0xAE51, 0xAE51 }, +{ 0xAE52, 0xAE52, 0xAE52 }, +{ 0xAE53, 0xAE53, 0xAE53 }, +{ 0xAE54, 0xAE54, 0xAE54 }, +{ 0xAE55, 0xAE55, 0xAE55 }, +{ 0xAE56, 0xAE56, 0xAE56 }, +{ 0xAE57, 0xAE57, 0xAE57 }, +{ 0xAE58, 0xAE58, 0xAE58 }, +{ 0xAE59, 0xAE59, 0xAE59 }, +{ 0xAE5A, 0xAE5A, 0xAE5A }, +{ 0xAE5B, 0xAE5B, 0xAE5B }, +{ 0xAE5C, 0xAE5C, 0xAE5C }, +{ 0xAE5D, 0xAE5D, 0xAE5D }, +{ 0xAE5E, 0xAE5E, 0xAE5E }, +{ 0xAE5F, 0xAE5F, 0xAE5F }, +{ 0xAE60, 0xAE60, 0xAE60 }, +{ 0xAE61, 0xAE61, 0xAE61 }, +{ 0xAE62, 0xAE62, 0xAE62 }, +{ 0xAE63, 0xAE63, 0xAE63 }, +{ 0xAE64, 0xAE64, 0xAE64 }, +{ 0xAE65, 0xAE65, 0xAE65 }, +{ 0xAE66, 0xAE66, 0xAE66 }, +{ 0xAE67, 0xAE67, 0xAE67 }, +{ 0xAE68, 0xAE68, 0xAE68 }, +{ 0xAE69, 0xAE69, 0xAE69 }, +{ 0xAE6A, 0xAE6A, 0xAE6A }, +{ 0xAE6B, 0xAE6B, 0xAE6B }, +{ 0xAE6C, 0xAE6C, 0xAE6C }, +{ 0xAE6D, 0xAE6D, 0xAE6D }, +{ 0xAE6E, 0xAE6E, 0xAE6E }, +{ 0xAE6F, 0xAE6F, 0xAE6F }, +{ 0xAE70, 0xAE70, 0xAE70 }, +{ 0xAE71, 0xAE71, 0xAE71 }, +{ 0xAE72, 0xAE72, 0xAE72 }, +{ 0xAE73, 0xAE73, 0xAE73 }, +{ 0xAE74, 0xAE74, 0xAE74 }, +{ 0xAE75, 0xAE75, 0xAE75 }, +{ 0xAE76, 0xAE76, 0xAE76 }, +{ 0xAE77, 0xAE77, 0xAE77 }, +{ 0xAE78, 0xAE78, 0xAE78 }, +{ 0xAE79, 0xAE79, 0xAE79 }, +{ 0xAE7A, 0xAE7A, 0xAE7A }, +{ 0xAE7B, 0xAE7B, 0xAE7B }, +{ 0xAE7C, 0xAE7C, 0xAE7C }, +{ 0xAE7D, 0xAE7D, 0xAE7D }, +{ 0xAE7E, 0xAE7E, 0xAE7E }, +{ 0xAE7F, 0xAE7F, 0xAE7F }, +{ 0xAE80, 0xAE80, 0xAE80 }, +{ 0xAE81, 0xAE81, 0xAE81 }, +{ 0xAE82, 0xAE82, 0xAE82 }, +{ 0xAE83, 0xAE83, 0xAE83 }, +{ 0xAE84, 0xAE84, 0xAE84 }, +{ 0xAE85, 0xAE85, 0xAE85 }, +{ 0xAE86, 0xAE86, 0xAE86 }, +{ 0xAE87, 0xAE87, 0xAE87 }, +{ 0xAE88, 0xAE88, 0xAE88 }, +{ 0xAE89, 0xAE89, 0xAE89 }, +{ 0xAE8A, 0xAE8A, 0xAE8A }, +{ 0xAE8B, 0xAE8B, 0xAE8B }, +{ 0xAE8C, 0xAE8C, 0xAE8C }, +{ 0xAE8D, 0xAE8D, 0xAE8D }, +{ 0xAE8E, 0xAE8E, 0xAE8E }, +{ 0xAE8F, 0xAE8F, 0xAE8F }, +{ 0xAE90, 0xAE90, 0xAE90 }, +{ 0xAE91, 0xAE91, 0xAE91 }, +{ 0xAE92, 0xAE92, 0xAE92 }, +{ 0xAE93, 0xAE93, 0xAE93 }, +{ 0xAE94, 0xAE94, 0xAE94 }, +{ 0xAE95, 0xAE95, 0xAE95 }, +{ 0xAE96, 0xAE96, 0xAE96 }, +{ 0xAE97, 0xAE97, 0xAE97 }, +{ 0xAE98, 0xAE98, 0xAE98 }, +{ 0xAE99, 0xAE99, 0xAE99 }, +{ 0xAE9A, 0xAE9A, 0xAE9A }, +{ 0xAE9B, 0xAE9B, 0xAE9B }, +{ 0xAE9C, 0xAE9C, 0xAE9C }, +{ 0xAE9D, 0xAE9D, 0xAE9D }, +{ 0xAE9E, 0xAE9E, 0xAE9E }, +{ 0xAE9F, 0xAE9F, 0xAE9F }, +{ 0xAEA0, 0xAEA0, 0xAEA0 }, +{ 0xAEA1, 0xAEA1, 0xAEA1 }, +{ 0xAEA2, 0xAEA2, 0xAEA2 }, +{ 0xAEA3, 0xAEA3, 0xAEA3 }, +{ 0xAEA4, 0xAEA4, 0xAEA4 }, +{ 0xAEA5, 0xAEA5, 0xAEA5 }, +{ 0xAEA6, 0xAEA6, 0xAEA6 }, +{ 0xAEA7, 0xAEA7, 0xAEA7 }, +{ 0xAEA8, 0xAEA8, 0xAEA8 }, +{ 0xAEA9, 0xAEA9, 0xAEA9 }, +{ 0xAEAA, 0xAEAA, 0xAEAA }, +{ 0xAEAB, 0xAEAB, 0xAEAB }, +{ 0xAEAC, 0xAEAC, 0xAEAC }, +{ 0xAEAD, 0xAEAD, 0xAEAD }, +{ 0xAEAE, 0xAEAE, 0xAEAE }, +{ 0xAEAF, 0xAEAF, 0xAEAF }, +{ 0xAEB0, 0xAEB0, 0xAEB0 }, +{ 0xAEB1, 0xAEB1, 0xAEB1 }, +{ 0xAEB2, 0xAEB2, 0xAEB2 }, +{ 0xAEB3, 0xAEB3, 0xAEB3 }, +{ 0xAEB4, 0xAEB4, 0xAEB4 }, +{ 0xAEB5, 0xAEB5, 0xAEB5 }, +{ 0xAEB6, 0xAEB6, 0xAEB6 }, +{ 0xAEB7, 0xAEB7, 0xAEB7 }, +{ 0xAEB8, 0xAEB8, 0xAEB8 }, +{ 0xAEB9, 0xAEB9, 0xAEB9 }, +{ 0xAEBA, 0xAEBA, 0xAEBA }, +{ 0xAEBB, 0xAEBB, 0xAEBB }, +{ 0xAEBC, 0xAEBC, 0xAEBC }, +{ 0xAEBD, 0xAEBD, 0xAEBD }, +{ 0xAEBE, 0xAEBE, 0xAEBE }, +{ 0xAEBF, 0xAEBF, 0xAEBF }, +{ 0xAEC0, 0xAEC0, 0xAEC0 }, +{ 0xAEC1, 0xAEC1, 0xAEC1 }, +{ 0xAEC2, 0xAEC2, 0xAEC2 }, +{ 0xAEC3, 0xAEC3, 0xAEC3 }, +{ 0xAEC4, 0xAEC4, 0xAEC4 }, +{ 0xAEC5, 0xAEC5, 0xAEC5 }, +{ 0xAEC6, 0xAEC6, 0xAEC6 }, +{ 0xAEC7, 0xAEC7, 0xAEC7 }, +{ 0xAEC8, 0xAEC8, 0xAEC8 }, +{ 0xAEC9, 0xAEC9, 0xAEC9 }, +{ 0xAECA, 0xAECA, 0xAECA }, +{ 0xAECB, 0xAECB, 0xAECB }, +{ 0xAECC, 0xAECC, 0xAECC }, +{ 0xAECD, 0xAECD, 0xAECD }, +{ 0xAECE, 0xAECE, 0xAECE }, +{ 0xAECF, 0xAECF, 0xAECF }, +{ 0xAED0, 0xAED0, 0xAED0 }, +{ 0xAED1, 0xAED1, 0xAED1 }, +{ 0xAED2, 0xAED2, 0xAED2 }, +{ 0xAED3, 0xAED3, 0xAED3 }, +{ 0xAED4, 0xAED4, 0xAED4 }, +{ 0xAED5, 0xAED5, 0xAED5 }, +{ 0xAED6, 0xAED6, 0xAED6 }, +{ 0xAED7, 0xAED7, 0xAED7 }, +{ 0xAED8, 0xAED8, 0xAED8 }, +{ 0xAED9, 0xAED9, 0xAED9 }, +{ 0xAEDA, 0xAEDA, 0xAEDA }, +{ 0xAEDB, 0xAEDB, 0xAEDB }, +{ 0xAEDC, 0xAEDC, 0xAEDC }, +{ 0xAEDD, 0xAEDD, 0xAEDD }, +{ 0xAEDE, 0xAEDE, 0xAEDE }, +{ 0xAEDF, 0xAEDF, 0xAEDF }, +{ 0xAEE0, 0xAEE0, 0xAEE0 }, +{ 0xAEE1, 0xAEE1, 0xAEE1 }, +{ 0xAEE2, 0xAEE2, 0xAEE2 }, +{ 0xAEE3, 0xAEE3, 0xAEE3 }, +{ 0xAEE4, 0xAEE4, 0xAEE4 }, +{ 0xAEE5, 0xAEE5, 0xAEE5 }, +{ 0xAEE6, 0xAEE6, 0xAEE6 }, +{ 0xAEE7, 0xAEE7, 0xAEE7 }, +{ 0xAEE8, 0xAEE8, 0xAEE8 }, +{ 0xAEE9, 0xAEE9, 0xAEE9 }, +{ 0xAEEA, 0xAEEA, 0xAEEA }, +{ 0xAEEB, 0xAEEB, 0xAEEB }, +{ 0xAEEC, 0xAEEC, 0xAEEC }, +{ 0xAEED, 0xAEED, 0xAEED }, +{ 0xAEEE, 0xAEEE, 0xAEEE }, +{ 0xAEEF, 0xAEEF, 0xAEEF }, +{ 0xAEF0, 0xAEF0, 0xAEF0 }, +{ 0xAEF1, 0xAEF1, 0xAEF1 }, +{ 0xAEF2, 0xAEF2, 0xAEF2 }, +{ 0xAEF3, 0xAEF3, 0xAEF3 }, +{ 0xAEF4, 0xAEF4, 0xAEF4 }, +{ 0xAEF5, 0xAEF5, 0xAEF5 }, +{ 0xAEF6, 0xAEF6, 0xAEF6 }, +{ 0xAEF7, 0xAEF7, 0xAEF7 }, +{ 0xAEF8, 0xAEF8, 0xAEF8 }, +{ 0xAEF9, 0xAEF9, 0xAEF9 }, +{ 0xAEFA, 0xAEFA, 0xAEFA }, +{ 0xAEFB, 0xAEFB, 0xAEFB }, +{ 0xAEFC, 0xAEFC, 0xAEFC }, +{ 0xAEFD, 0xAEFD, 0xAEFD }, +{ 0xAEFE, 0xAEFE, 0xAEFE }, +{ 0xAEFF, 0xAEFF, 0xAEFF }, +{ 0xAF00, 0xAF00, 0xAF00 }, +{ 0xAF01, 0xAF01, 0xAF01 }, +{ 0xAF02, 0xAF02, 0xAF02 }, +{ 0xAF03, 0xAF03, 0xAF03 }, +{ 0xAF04, 0xAF04, 0xAF04 }, +{ 0xAF05, 0xAF05, 0xAF05 }, +{ 0xAF06, 0xAF06, 0xAF06 }, +{ 0xAF07, 0xAF07, 0xAF07 }, +{ 0xAF08, 0xAF08, 0xAF08 }, +{ 0xAF09, 0xAF09, 0xAF09 }, +{ 0xAF0A, 0xAF0A, 0xAF0A }, +{ 0xAF0B, 0xAF0B, 0xAF0B }, +{ 0xAF0C, 0xAF0C, 0xAF0C }, +{ 0xAF0D, 0xAF0D, 0xAF0D }, +{ 0xAF0E, 0xAF0E, 0xAF0E }, +{ 0xAF0F, 0xAF0F, 0xAF0F }, +{ 0xAF10, 0xAF10, 0xAF10 }, +{ 0xAF11, 0xAF11, 0xAF11 }, +{ 0xAF12, 0xAF12, 0xAF12 }, +{ 0xAF13, 0xAF13, 0xAF13 }, +{ 0xAF14, 0xAF14, 0xAF14 }, +{ 0xAF15, 0xAF15, 0xAF15 }, +{ 0xAF16, 0xAF16, 0xAF16 }, +{ 0xAF17, 0xAF17, 0xAF17 }, +{ 0xAF18, 0xAF18, 0xAF18 }, +{ 0xAF19, 0xAF19, 0xAF19 }, +{ 0xAF1A, 0xAF1A, 0xAF1A }, +{ 0xAF1B, 0xAF1B, 0xAF1B }, +{ 0xAF1C, 0xAF1C, 0xAF1C }, +{ 0xAF1D, 0xAF1D, 0xAF1D }, +{ 0xAF1E, 0xAF1E, 0xAF1E }, +{ 0xAF1F, 0xAF1F, 0xAF1F }, +{ 0xAF20, 0xAF20, 0xAF20 }, +{ 0xAF21, 0xAF21, 0xAF21 }, +{ 0xAF22, 0xAF22, 0xAF22 }, +{ 0xAF23, 0xAF23, 0xAF23 }, +{ 0xAF24, 0xAF24, 0xAF24 }, +{ 0xAF25, 0xAF25, 0xAF25 }, +{ 0xAF26, 0xAF26, 0xAF26 }, +{ 0xAF27, 0xAF27, 0xAF27 }, +{ 0xAF28, 0xAF28, 0xAF28 }, +{ 0xAF29, 0xAF29, 0xAF29 }, +{ 0xAF2A, 0xAF2A, 0xAF2A }, +{ 0xAF2B, 0xAF2B, 0xAF2B }, +{ 0xAF2C, 0xAF2C, 0xAF2C }, +{ 0xAF2D, 0xAF2D, 0xAF2D }, +{ 0xAF2E, 0xAF2E, 0xAF2E }, +{ 0xAF2F, 0xAF2F, 0xAF2F }, +{ 0xAF30, 0xAF30, 0xAF30 }, +{ 0xAF31, 0xAF31, 0xAF31 }, +{ 0xAF32, 0xAF32, 0xAF32 }, +{ 0xAF33, 0xAF33, 0xAF33 }, +{ 0xAF34, 0xAF34, 0xAF34 }, +{ 0xAF35, 0xAF35, 0xAF35 }, +{ 0xAF36, 0xAF36, 0xAF36 }, +{ 0xAF37, 0xAF37, 0xAF37 }, +{ 0xAF38, 0xAF38, 0xAF38 }, +{ 0xAF39, 0xAF39, 0xAF39 }, +{ 0xAF3A, 0xAF3A, 0xAF3A }, +{ 0xAF3B, 0xAF3B, 0xAF3B }, +{ 0xAF3C, 0xAF3C, 0xAF3C }, +{ 0xAF3D, 0xAF3D, 0xAF3D }, +{ 0xAF3E, 0xAF3E, 0xAF3E }, +{ 0xAF3F, 0xAF3F, 0xAF3F }, +{ 0xAF40, 0xAF40, 0xAF40 }, +{ 0xAF41, 0xAF41, 0xAF41 }, +{ 0xAF42, 0xAF42, 0xAF42 }, +{ 0xAF43, 0xAF43, 0xAF43 }, +{ 0xAF44, 0xAF44, 0xAF44 }, +{ 0xAF45, 0xAF45, 0xAF45 }, +{ 0xAF46, 0xAF46, 0xAF46 }, +{ 0xAF47, 0xAF47, 0xAF47 }, +{ 0xAF48, 0xAF48, 0xAF48 }, +{ 0xAF49, 0xAF49, 0xAF49 }, +{ 0xAF4A, 0xAF4A, 0xAF4A }, +{ 0xAF4B, 0xAF4B, 0xAF4B }, +{ 0xAF4C, 0xAF4C, 0xAF4C }, +{ 0xAF4D, 0xAF4D, 0xAF4D }, +{ 0xAF4E, 0xAF4E, 0xAF4E }, +{ 0xAF4F, 0xAF4F, 0xAF4F }, +{ 0xAF50, 0xAF50, 0xAF50 }, +{ 0xAF51, 0xAF51, 0xAF51 }, +{ 0xAF52, 0xAF52, 0xAF52 }, +{ 0xAF53, 0xAF53, 0xAF53 }, +{ 0xAF54, 0xAF54, 0xAF54 }, +{ 0xAF55, 0xAF55, 0xAF55 }, +{ 0xAF56, 0xAF56, 0xAF56 }, +{ 0xAF57, 0xAF57, 0xAF57 }, +{ 0xAF58, 0xAF58, 0xAF58 }, +{ 0xAF59, 0xAF59, 0xAF59 }, +{ 0xAF5A, 0xAF5A, 0xAF5A }, +{ 0xAF5B, 0xAF5B, 0xAF5B }, +{ 0xAF5C, 0xAF5C, 0xAF5C }, +{ 0xAF5D, 0xAF5D, 0xAF5D }, +{ 0xAF5E, 0xAF5E, 0xAF5E }, +{ 0xAF5F, 0xAF5F, 0xAF5F }, +{ 0xAF60, 0xAF60, 0xAF60 }, +{ 0xAF61, 0xAF61, 0xAF61 }, +{ 0xAF62, 0xAF62, 0xAF62 }, +{ 0xAF63, 0xAF63, 0xAF63 }, +{ 0xAF64, 0xAF64, 0xAF64 }, +{ 0xAF65, 0xAF65, 0xAF65 }, +{ 0xAF66, 0xAF66, 0xAF66 }, +{ 0xAF67, 0xAF67, 0xAF67 }, +{ 0xAF68, 0xAF68, 0xAF68 }, +{ 0xAF69, 0xAF69, 0xAF69 }, +{ 0xAF6A, 0xAF6A, 0xAF6A }, +{ 0xAF6B, 0xAF6B, 0xAF6B }, +{ 0xAF6C, 0xAF6C, 0xAF6C }, +{ 0xAF6D, 0xAF6D, 0xAF6D }, +{ 0xAF6E, 0xAF6E, 0xAF6E }, +{ 0xAF6F, 0xAF6F, 0xAF6F }, +{ 0xAF70, 0xAF70, 0xAF70 }, +{ 0xAF71, 0xAF71, 0xAF71 }, +{ 0xAF72, 0xAF72, 0xAF72 }, +{ 0xAF73, 0xAF73, 0xAF73 }, +{ 0xAF74, 0xAF74, 0xAF74 }, +{ 0xAF75, 0xAF75, 0xAF75 }, +{ 0xAF76, 0xAF76, 0xAF76 }, +{ 0xAF77, 0xAF77, 0xAF77 }, +{ 0xAF78, 0xAF78, 0xAF78 }, +{ 0xAF79, 0xAF79, 0xAF79 }, +{ 0xAF7A, 0xAF7A, 0xAF7A }, +{ 0xAF7B, 0xAF7B, 0xAF7B }, +{ 0xAF7C, 0xAF7C, 0xAF7C }, +{ 0xAF7D, 0xAF7D, 0xAF7D }, +{ 0xAF7E, 0xAF7E, 0xAF7E }, +{ 0xAF7F, 0xAF7F, 0xAF7F }, +{ 0xAF80, 0xAF80, 0xAF80 }, +{ 0xAF81, 0xAF81, 0xAF81 }, +{ 0xAF82, 0xAF82, 0xAF82 }, +{ 0xAF83, 0xAF83, 0xAF83 }, +{ 0xAF84, 0xAF84, 0xAF84 }, +{ 0xAF85, 0xAF85, 0xAF85 }, +{ 0xAF86, 0xAF86, 0xAF86 }, +{ 0xAF87, 0xAF87, 0xAF87 }, +{ 0xAF88, 0xAF88, 0xAF88 }, +{ 0xAF89, 0xAF89, 0xAF89 }, +{ 0xAF8A, 0xAF8A, 0xAF8A }, +{ 0xAF8B, 0xAF8B, 0xAF8B }, +{ 0xAF8C, 0xAF8C, 0xAF8C }, +{ 0xAF8D, 0xAF8D, 0xAF8D }, +{ 0xAF8E, 0xAF8E, 0xAF8E }, +{ 0xAF8F, 0xAF8F, 0xAF8F }, +{ 0xAF90, 0xAF90, 0xAF90 }, +{ 0xAF91, 0xAF91, 0xAF91 }, +{ 0xAF92, 0xAF92, 0xAF92 }, +{ 0xAF93, 0xAF93, 0xAF93 }, +{ 0xAF94, 0xAF94, 0xAF94 }, +{ 0xAF95, 0xAF95, 0xAF95 }, +{ 0xAF96, 0xAF96, 0xAF96 }, +{ 0xAF97, 0xAF97, 0xAF97 }, +{ 0xAF98, 0xAF98, 0xAF98 }, +{ 0xAF99, 0xAF99, 0xAF99 }, +{ 0xAF9A, 0xAF9A, 0xAF9A }, +{ 0xAF9B, 0xAF9B, 0xAF9B }, +{ 0xAF9C, 0xAF9C, 0xAF9C }, +{ 0xAF9D, 0xAF9D, 0xAF9D }, +{ 0xAF9E, 0xAF9E, 0xAF9E }, +{ 0xAF9F, 0xAF9F, 0xAF9F }, +{ 0xAFA0, 0xAFA0, 0xAFA0 }, +{ 0xAFA1, 0xAFA1, 0xAFA1 }, +{ 0xAFA2, 0xAFA2, 0xAFA2 }, +{ 0xAFA3, 0xAFA3, 0xAFA3 }, +{ 0xAFA4, 0xAFA4, 0xAFA4 }, +{ 0xAFA5, 0xAFA5, 0xAFA5 }, +{ 0xAFA6, 0xAFA6, 0xAFA6 }, +{ 0xAFA7, 0xAFA7, 0xAFA7 }, +{ 0xAFA8, 0xAFA8, 0xAFA8 }, +{ 0xAFA9, 0xAFA9, 0xAFA9 }, +{ 0xAFAA, 0xAFAA, 0xAFAA }, +{ 0xAFAB, 0xAFAB, 0xAFAB }, +{ 0xAFAC, 0xAFAC, 0xAFAC }, +{ 0xAFAD, 0xAFAD, 0xAFAD }, +{ 0xAFAE, 0xAFAE, 0xAFAE }, +{ 0xAFAF, 0xAFAF, 0xAFAF }, +{ 0xAFB0, 0xAFB0, 0xAFB0 }, +{ 0xAFB1, 0xAFB1, 0xAFB1 }, +{ 0xAFB2, 0xAFB2, 0xAFB2 }, +{ 0xAFB3, 0xAFB3, 0xAFB3 }, +{ 0xAFB4, 0xAFB4, 0xAFB4 }, +{ 0xAFB5, 0xAFB5, 0xAFB5 }, +{ 0xAFB6, 0xAFB6, 0xAFB6 }, +{ 0xAFB7, 0xAFB7, 0xAFB7 }, +{ 0xAFB8, 0xAFB8, 0xAFB8 }, +{ 0xAFB9, 0xAFB9, 0xAFB9 }, +{ 0xAFBA, 0xAFBA, 0xAFBA }, +{ 0xAFBB, 0xAFBB, 0xAFBB }, +{ 0xAFBC, 0xAFBC, 0xAFBC }, +{ 0xAFBD, 0xAFBD, 0xAFBD }, +{ 0xAFBE, 0xAFBE, 0xAFBE }, +{ 0xAFBF, 0xAFBF, 0xAFBF }, +{ 0xAFC0, 0xAFC0, 0xAFC0 }, +{ 0xAFC1, 0xAFC1, 0xAFC1 }, +{ 0xAFC2, 0xAFC2, 0xAFC2 }, +{ 0xAFC3, 0xAFC3, 0xAFC3 }, +{ 0xAFC4, 0xAFC4, 0xAFC4 }, +{ 0xAFC5, 0xAFC5, 0xAFC5 }, +{ 0xAFC6, 0xAFC6, 0xAFC6 }, +{ 0xAFC7, 0xAFC7, 0xAFC7 }, +{ 0xAFC8, 0xAFC8, 0xAFC8 }, +{ 0xAFC9, 0xAFC9, 0xAFC9 }, +{ 0xAFCA, 0xAFCA, 0xAFCA }, +{ 0xAFCB, 0xAFCB, 0xAFCB }, +{ 0xAFCC, 0xAFCC, 0xAFCC }, +{ 0xAFCD, 0xAFCD, 0xAFCD }, +{ 0xAFCE, 0xAFCE, 0xAFCE }, +{ 0xAFCF, 0xAFCF, 0xAFCF }, +{ 0xAFD0, 0xAFD0, 0xAFD0 }, +{ 0xAFD1, 0xAFD1, 0xAFD1 }, +{ 0xAFD2, 0xAFD2, 0xAFD2 }, +{ 0xAFD3, 0xAFD3, 0xAFD3 }, +{ 0xAFD4, 0xAFD4, 0xAFD4 }, +{ 0xAFD5, 0xAFD5, 0xAFD5 }, +{ 0xAFD6, 0xAFD6, 0xAFD6 }, +{ 0xAFD7, 0xAFD7, 0xAFD7 }, +{ 0xAFD8, 0xAFD8, 0xAFD8 }, +{ 0xAFD9, 0xAFD9, 0xAFD9 }, +{ 0xAFDA, 0xAFDA, 0xAFDA }, +{ 0xAFDB, 0xAFDB, 0xAFDB }, +{ 0xAFDC, 0xAFDC, 0xAFDC }, +{ 0xAFDD, 0xAFDD, 0xAFDD }, +{ 0xAFDE, 0xAFDE, 0xAFDE }, +{ 0xAFDF, 0xAFDF, 0xAFDF }, +{ 0xAFE0, 0xAFE0, 0xAFE0 }, +{ 0xAFE1, 0xAFE1, 0xAFE1 }, +{ 0xAFE2, 0xAFE2, 0xAFE2 }, +{ 0xAFE3, 0xAFE3, 0xAFE3 }, +{ 0xAFE4, 0xAFE4, 0xAFE4 }, +{ 0xAFE5, 0xAFE5, 0xAFE5 }, +{ 0xAFE6, 0xAFE6, 0xAFE6 }, +{ 0xAFE7, 0xAFE7, 0xAFE7 }, +{ 0xAFE8, 0xAFE8, 0xAFE8 }, +{ 0xAFE9, 0xAFE9, 0xAFE9 }, +{ 0xAFEA, 0xAFEA, 0xAFEA }, +{ 0xAFEB, 0xAFEB, 0xAFEB }, +{ 0xAFEC, 0xAFEC, 0xAFEC }, +{ 0xAFED, 0xAFED, 0xAFED }, +{ 0xAFEE, 0xAFEE, 0xAFEE }, +{ 0xAFEF, 0xAFEF, 0xAFEF }, +{ 0xAFF0, 0xAFF0, 0xAFF0 }, +{ 0xAFF1, 0xAFF1, 0xAFF1 }, +{ 0xAFF2, 0xAFF2, 0xAFF2 }, +{ 0xAFF3, 0xAFF3, 0xAFF3 }, +{ 0xAFF4, 0xAFF4, 0xAFF4 }, +{ 0xAFF5, 0xAFF5, 0xAFF5 }, +{ 0xAFF6, 0xAFF6, 0xAFF6 }, +{ 0xAFF7, 0xAFF7, 0xAFF7 }, +{ 0xAFF8, 0xAFF8, 0xAFF8 }, +{ 0xAFF9, 0xAFF9, 0xAFF9 }, +{ 0xAFFA, 0xAFFA, 0xAFFA }, +{ 0xAFFB, 0xAFFB, 0xAFFB }, +{ 0xAFFC, 0xAFFC, 0xAFFC }, +{ 0xAFFD, 0xAFFD, 0xAFFD }, +{ 0xAFFE, 0xAFFE, 0xAFFE }, +{ 0xAFFF, 0xAFFF, 0xAFFF }, +{ 0xB000, 0xB000, 0xB000 }, +{ 0xB001, 0xB001, 0xB001 }, +{ 0xB002, 0xB002, 0xB002 }, +{ 0xB003, 0xB003, 0xB003 }, +{ 0xB004, 0xB004, 0xB004 }, +{ 0xB005, 0xB005, 0xB005 }, +{ 0xB006, 0xB006, 0xB006 }, +{ 0xB007, 0xB007, 0xB007 }, +{ 0xB008, 0xB008, 0xB008 }, +{ 0xB009, 0xB009, 0xB009 }, +{ 0xB00A, 0xB00A, 0xB00A }, +{ 0xB00B, 0xB00B, 0xB00B }, +{ 0xB00C, 0xB00C, 0xB00C }, +{ 0xB00D, 0xB00D, 0xB00D }, +{ 0xB00E, 0xB00E, 0xB00E }, +{ 0xB00F, 0xB00F, 0xB00F }, +{ 0xB010, 0xB010, 0xB010 }, +{ 0xB011, 0xB011, 0xB011 }, +{ 0xB012, 0xB012, 0xB012 }, +{ 0xB013, 0xB013, 0xB013 }, +{ 0xB014, 0xB014, 0xB014 }, +{ 0xB015, 0xB015, 0xB015 }, +{ 0xB016, 0xB016, 0xB016 }, +{ 0xB017, 0xB017, 0xB017 }, +{ 0xB018, 0xB018, 0xB018 }, +{ 0xB019, 0xB019, 0xB019 }, +{ 0xB01A, 0xB01A, 0xB01A }, +{ 0xB01B, 0xB01B, 0xB01B }, +{ 0xB01C, 0xB01C, 0xB01C }, +{ 0xB01D, 0xB01D, 0xB01D }, +{ 0xB01E, 0xB01E, 0xB01E }, +{ 0xB01F, 0xB01F, 0xB01F }, +{ 0xB020, 0xB020, 0xB020 }, +{ 0xB021, 0xB021, 0xB021 }, +{ 0xB022, 0xB022, 0xB022 }, +{ 0xB023, 0xB023, 0xB023 }, +{ 0xB024, 0xB024, 0xB024 }, +{ 0xB025, 0xB025, 0xB025 }, +{ 0xB026, 0xB026, 0xB026 }, +{ 0xB027, 0xB027, 0xB027 }, +{ 0xB028, 0xB028, 0xB028 }, +{ 0xB029, 0xB029, 0xB029 }, +{ 0xB02A, 0xB02A, 0xB02A }, +{ 0xB02B, 0xB02B, 0xB02B }, +{ 0xB02C, 0xB02C, 0xB02C }, +{ 0xB02D, 0xB02D, 0xB02D }, +{ 0xB02E, 0xB02E, 0xB02E }, +{ 0xB02F, 0xB02F, 0xB02F }, +{ 0xB030, 0xB030, 0xB030 }, +{ 0xB031, 0xB031, 0xB031 }, +{ 0xB032, 0xB032, 0xB032 }, +{ 0xB033, 0xB033, 0xB033 }, +{ 0xB034, 0xB034, 0xB034 }, +{ 0xB035, 0xB035, 0xB035 }, +{ 0xB036, 0xB036, 0xB036 }, +{ 0xB037, 0xB037, 0xB037 }, +{ 0xB038, 0xB038, 0xB038 }, +{ 0xB039, 0xB039, 0xB039 }, +{ 0xB03A, 0xB03A, 0xB03A }, +{ 0xB03B, 0xB03B, 0xB03B }, +{ 0xB03C, 0xB03C, 0xB03C }, +{ 0xB03D, 0xB03D, 0xB03D }, +{ 0xB03E, 0xB03E, 0xB03E }, +{ 0xB03F, 0xB03F, 0xB03F }, +{ 0xB040, 0xB040, 0xB040 }, +{ 0xB041, 0xB041, 0xB041 }, +{ 0xB042, 0xB042, 0xB042 }, +{ 0xB043, 0xB043, 0xB043 }, +{ 0xB044, 0xB044, 0xB044 }, +{ 0xB045, 0xB045, 0xB045 }, +{ 0xB046, 0xB046, 0xB046 }, +{ 0xB047, 0xB047, 0xB047 }, +{ 0xB048, 0xB048, 0xB048 }, +{ 0xB049, 0xB049, 0xB049 }, +{ 0xB04A, 0xB04A, 0xB04A }, +{ 0xB04B, 0xB04B, 0xB04B }, +{ 0xB04C, 0xB04C, 0xB04C }, +{ 0xB04D, 0xB04D, 0xB04D }, +{ 0xB04E, 0xB04E, 0xB04E }, +{ 0xB04F, 0xB04F, 0xB04F }, +{ 0xB050, 0xB050, 0xB050 }, +{ 0xB051, 0xB051, 0xB051 }, +{ 0xB052, 0xB052, 0xB052 }, +{ 0xB053, 0xB053, 0xB053 }, +{ 0xB054, 0xB054, 0xB054 }, +{ 0xB055, 0xB055, 0xB055 }, +{ 0xB056, 0xB056, 0xB056 }, +{ 0xB057, 0xB057, 0xB057 }, +{ 0xB058, 0xB058, 0xB058 }, +{ 0xB059, 0xB059, 0xB059 }, +{ 0xB05A, 0xB05A, 0xB05A }, +{ 0xB05B, 0xB05B, 0xB05B }, +{ 0xB05C, 0xB05C, 0xB05C }, +{ 0xB05D, 0xB05D, 0xB05D }, +{ 0xB05E, 0xB05E, 0xB05E }, +{ 0xB05F, 0xB05F, 0xB05F }, +{ 0xB060, 0xB060, 0xB060 }, +{ 0xB061, 0xB061, 0xB061 }, +{ 0xB062, 0xB062, 0xB062 }, +{ 0xB063, 0xB063, 0xB063 }, +{ 0xB064, 0xB064, 0xB064 }, +{ 0xB065, 0xB065, 0xB065 }, +{ 0xB066, 0xB066, 0xB066 }, +{ 0xB067, 0xB067, 0xB067 }, +{ 0xB068, 0xB068, 0xB068 }, +{ 0xB069, 0xB069, 0xB069 }, +{ 0xB06A, 0xB06A, 0xB06A }, +{ 0xB06B, 0xB06B, 0xB06B }, +{ 0xB06C, 0xB06C, 0xB06C }, +{ 0xB06D, 0xB06D, 0xB06D }, +{ 0xB06E, 0xB06E, 0xB06E }, +{ 0xB06F, 0xB06F, 0xB06F }, +{ 0xB070, 0xB070, 0xB070 }, +{ 0xB071, 0xB071, 0xB071 }, +{ 0xB072, 0xB072, 0xB072 }, +{ 0xB073, 0xB073, 0xB073 }, +{ 0xB074, 0xB074, 0xB074 }, +{ 0xB075, 0xB075, 0xB075 }, +{ 0xB076, 0xB076, 0xB076 }, +{ 0xB077, 0xB077, 0xB077 }, +{ 0xB078, 0xB078, 0xB078 }, +{ 0xB079, 0xB079, 0xB079 }, +{ 0xB07A, 0xB07A, 0xB07A }, +{ 0xB07B, 0xB07B, 0xB07B }, +{ 0xB07C, 0xB07C, 0xB07C }, +{ 0xB07D, 0xB07D, 0xB07D }, +{ 0xB07E, 0xB07E, 0xB07E }, +{ 0xB07F, 0xB07F, 0xB07F }, +{ 0xB080, 0xB080, 0xB080 }, +{ 0xB081, 0xB081, 0xB081 }, +{ 0xB082, 0xB082, 0xB082 }, +{ 0xB083, 0xB083, 0xB083 }, +{ 0xB084, 0xB084, 0xB084 }, +{ 0xB085, 0xB085, 0xB085 }, +{ 0xB086, 0xB086, 0xB086 }, +{ 0xB087, 0xB087, 0xB087 }, +{ 0xB088, 0xB088, 0xB088 }, +{ 0xB089, 0xB089, 0xB089 }, +{ 0xB08A, 0xB08A, 0xB08A }, +{ 0xB08B, 0xB08B, 0xB08B }, +{ 0xB08C, 0xB08C, 0xB08C }, +{ 0xB08D, 0xB08D, 0xB08D }, +{ 0xB08E, 0xB08E, 0xB08E }, +{ 0xB08F, 0xB08F, 0xB08F }, +{ 0xB090, 0xB090, 0xB090 }, +{ 0xB091, 0xB091, 0xB091 }, +{ 0xB092, 0xB092, 0xB092 }, +{ 0xB093, 0xB093, 0xB093 }, +{ 0xB094, 0xB094, 0xB094 }, +{ 0xB095, 0xB095, 0xB095 }, +{ 0xB096, 0xB096, 0xB096 }, +{ 0xB097, 0xB097, 0xB097 }, +{ 0xB098, 0xB098, 0xB098 }, +{ 0xB099, 0xB099, 0xB099 }, +{ 0xB09A, 0xB09A, 0xB09A }, +{ 0xB09B, 0xB09B, 0xB09B }, +{ 0xB09C, 0xB09C, 0xB09C }, +{ 0xB09D, 0xB09D, 0xB09D }, +{ 0xB09E, 0xB09E, 0xB09E }, +{ 0xB09F, 0xB09F, 0xB09F }, +{ 0xB0A0, 0xB0A0, 0xB0A0 }, +{ 0xB0A1, 0xB0A1, 0xB0A1 }, +{ 0xB0A2, 0xB0A2, 0xB0A2 }, +{ 0xB0A3, 0xB0A3, 0xB0A3 }, +{ 0xB0A4, 0xB0A4, 0xB0A4 }, +{ 0xB0A5, 0xB0A5, 0xB0A5 }, +{ 0xB0A6, 0xB0A6, 0xB0A6 }, +{ 0xB0A7, 0xB0A7, 0xB0A7 }, +{ 0xB0A8, 0xB0A8, 0xB0A8 }, +{ 0xB0A9, 0xB0A9, 0xB0A9 }, +{ 0xB0AA, 0xB0AA, 0xB0AA }, +{ 0xB0AB, 0xB0AB, 0xB0AB }, +{ 0xB0AC, 0xB0AC, 0xB0AC }, +{ 0xB0AD, 0xB0AD, 0xB0AD }, +{ 0xB0AE, 0xB0AE, 0xB0AE }, +{ 0xB0AF, 0xB0AF, 0xB0AF }, +{ 0xB0B0, 0xB0B0, 0xB0B0 }, +{ 0xB0B1, 0xB0B1, 0xB0B1 }, +{ 0xB0B2, 0xB0B2, 0xB0B2 }, +{ 0xB0B3, 0xB0B3, 0xB0B3 }, +{ 0xB0B4, 0xB0B4, 0xB0B4 }, +{ 0xB0B5, 0xB0B5, 0xB0B5 }, +{ 0xB0B6, 0xB0B6, 0xB0B6 }, +{ 0xB0B7, 0xB0B7, 0xB0B7 }, +{ 0xB0B8, 0xB0B8, 0xB0B8 }, +{ 0xB0B9, 0xB0B9, 0xB0B9 }, +{ 0xB0BA, 0xB0BA, 0xB0BA }, +{ 0xB0BB, 0xB0BB, 0xB0BB }, +{ 0xB0BC, 0xB0BC, 0xB0BC }, +{ 0xB0BD, 0xB0BD, 0xB0BD }, +{ 0xB0BE, 0xB0BE, 0xB0BE }, +{ 0xB0BF, 0xB0BF, 0xB0BF }, +{ 0xB0C0, 0xB0C0, 0xB0C0 }, +{ 0xB0C1, 0xB0C1, 0xB0C1 }, +{ 0xB0C2, 0xB0C2, 0xB0C2 }, +{ 0xB0C3, 0xB0C3, 0xB0C3 }, +{ 0xB0C4, 0xB0C4, 0xB0C4 }, +{ 0xB0C5, 0xB0C5, 0xB0C5 }, +{ 0xB0C6, 0xB0C6, 0xB0C6 }, +{ 0xB0C7, 0xB0C7, 0xB0C7 }, +{ 0xB0C8, 0xB0C8, 0xB0C8 }, +{ 0xB0C9, 0xB0C9, 0xB0C9 }, +{ 0xB0CA, 0xB0CA, 0xB0CA }, +{ 0xB0CB, 0xB0CB, 0xB0CB }, +{ 0xB0CC, 0xB0CC, 0xB0CC }, +{ 0xB0CD, 0xB0CD, 0xB0CD }, +{ 0xB0CE, 0xB0CE, 0xB0CE }, +{ 0xB0CF, 0xB0CF, 0xB0CF }, +{ 0xB0D0, 0xB0D0, 0xB0D0 }, +{ 0xB0D1, 0xB0D1, 0xB0D1 }, +{ 0xB0D2, 0xB0D2, 0xB0D2 }, +{ 0xB0D3, 0xB0D3, 0xB0D3 }, +{ 0xB0D4, 0xB0D4, 0xB0D4 }, +{ 0xB0D5, 0xB0D5, 0xB0D5 }, +{ 0xB0D6, 0xB0D6, 0xB0D6 }, +{ 0xB0D7, 0xB0D7, 0xB0D7 }, +{ 0xB0D8, 0xB0D8, 0xB0D8 }, +{ 0xB0D9, 0xB0D9, 0xB0D9 }, +{ 0xB0DA, 0xB0DA, 0xB0DA }, +{ 0xB0DB, 0xB0DB, 0xB0DB }, +{ 0xB0DC, 0xB0DC, 0xB0DC }, +{ 0xB0DD, 0xB0DD, 0xB0DD }, +{ 0xB0DE, 0xB0DE, 0xB0DE }, +{ 0xB0DF, 0xB0DF, 0xB0DF }, +{ 0xB0E0, 0xB0E0, 0xB0E0 }, +{ 0xB0E1, 0xB0E1, 0xB0E1 }, +{ 0xB0E2, 0xB0E2, 0xB0E2 }, +{ 0xB0E3, 0xB0E3, 0xB0E3 }, +{ 0xB0E4, 0xB0E4, 0xB0E4 }, +{ 0xB0E5, 0xB0E5, 0xB0E5 }, +{ 0xB0E6, 0xB0E6, 0xB0E6 }, +{ 0xB0E7, 0xB0E7, 0xB0E7 }, +{ 0xB0E8, 0xB0E8, 0xB0E8 }, +{ 0xB0E9, 0xB0E9, 0xB0E9 }, +{ 0xB0EA, 0xB0EA, 0xB0EA }, +{ 0xB0EB, 0xB0EB, 0xB0EB }, +{ 0xB0EC, 0xB0EC, 0xB0EC }, +{ 0xB0ED, 0xB0ED, 0xB0ED }, +{ 0xB0EE, 0xB0EE, 0xB0EE }, +{ 0xB0EF, 0xB0EF, 0xB0EF }, +{ 0xB0F0, 0xB0F0, 0xB0F0 }, +{ 0xB0F1, 0xB0F1, 0xB0F1 }, +{ 0xB0F2, 0xB0F2, 0xB0F2 }, +{ 0xB0F3, 0xB0F3, 0xB0F3 }, +{ 0xB0F4, 0xB0F4, 0xB0F4 }, +{ 0xB0F5, 0xB0F5, 0xB0F5 }, +{ 0xB0F6, 0xB0F6, 0xB0F6 }, +{ 0xB0F7, 0xB0F7, 0xB0F7 }, +{ 0xB0F8, 0xB0F8, 0xB0F8 }, +{ 0xB0F9, 0xB0F9, 0xB0F9 }, +{ 0xB0FA, 0xB0FA, 0xB0FA }, +{ 0xB0FB, 0xB0FB, 0xB0FB }, +{ 0xB0FC, 0xB0FC, 0xB0FC }, +{ 0xB0FD, 0xB0FD, 0xB0FD }, +{ 0xB0FE, 0xB0FE, 0xB0FE }, +{ 0xB0FF, 0xB0FF, 0xB0FF }, +{ 0xB100, 0xB100, 0xB100 }, +{ 0xB101, 0xB101, 0xB101 }, +{ 0xB102, 0xB102, 0xB102 }, +{ 0xB103, 0xB103, 0xB103 }, +{ 0xB104, 0xB104, 0xB104 }, +{ 0xB105, 0xB105, 0xB105 }, +{ 0xB106, 0xB106, 0xB106 }, +{ 0xB107, 0xB107, 0xB107 }, +{ 0xB108, 0xB108, 0xB108 }, +{ 0xB109, 0xB109, 0xB109 }, +{ 0xB10A, 0xB10A, 0xB10A }, +{ 0xB10B, 0xB10B, 0xB10B }, +{ 0xB10C, 0xB10C, 0xB10C }, +{ 0xB10D, 0xB10D, 0xB10D }, +{ 0xB10E, 0xB10E, 0xB10E }, +{ 0xB10F, 0xB10F, 0xB10F }, +{ 0xB110, 0xB110, 0xB110 }, +{ 0xB111, 0xB111, 0xB111 }, +{ 0xB112, 0xB112, 0xB112 }, +{ 0xB113, 0xB113, 0xB113 }, +{ 0xB114, 0xB114, 0xB114 }, +{ 0xB115, 0xB115, 0xB115 }, +{ 0xB116, 0xB116, 0xB116 }, +{ 0xB117, 0xB117, 0xB117 }, +{ 0xB118, 0xB118, 0xB118 }, +{ 0xB119, 0xB119, 0xB119 }, +{ 0xB11A, 0xB11A, 0xB11A }, +{ 0xB11B, 0xB11B, 0xB11B }, +{ 0xB11C, 0xB11C, 0xB11C }, +{ 0xB11D, 0xB11D, 0xB11D }, +{ 0xB11E, 0xB11E, 0xB11E }, +{ 0xB11F, 0xB11F, 0xB11F }, +{ 0xB120, 0xB120, 0xB120 }, +{ 0xB121, 0xB121, 0xB121 }, +{ 0xB122, 0xB122, 0xB122 }, +{ 0xB123, 0xB123, 0xB123 }, +{ 0xB124, 0xB124, 0xB124 }, +{ 0xB125, 0xB125, 0xB125 }, +{ 0xB126, 0xB126, 0xB126 }, +{ 0xB127, 0xB127, 0xB127 }, +{ 0xB128, 0xB128, 0xB128 }, +{ 0xB129, 0xB129, 0xB129 }, +{ 0xB12A, 0xB12A, 0xB12A }, +{ 0xB12B, 0xB12B, 0xB12B }, +{ 0xB12C, 0xB12C, 0xB12C }, +{ 0xB12D, 0xB12D, 0xB12D }, +{ 0xB12E, 0xB12E, 0xB12E }, +{ 0xB12F, 0xB12F, 0xB12F }, +{ 0xB130, 0xB130, 0xB130 }, +{ 0xB131, 0xB131, 0xB131 }, +{ 0xB132, 0xB132, 0xB132 }, +{ 0xB133, 0xB133, 0xB133 }, +{ 0xB134, 0xB134, 0xB134 }, +{ 0xB135, 0xB135, 0xB135 }, +{ 0xB136, 0xB136, 0xB136 }, +{ 0xB137, 0xB137, 0xB137 }, +{ 0xB138, 0xB138, 0xB138 }, +{ 0xB139, 0xB139, 0xB139 }, +{ 0xB13A, 0xB13A, 0xB13A }, +{ 0xB13B, 0xB13B, 0xB13B }, +{ 0xB13C, 0xB13C, 0xB13C }, +{ 0xB13D, 0xB13D, 0xB13D }, +{ 0xB13E, 0xB13E, 0xB13E }, +{ 0xB13F, 0xB13F, 0xB13F }, +{ 0xB140, 0xB140, 0xB140 }, +{ 0xB141, 0xB141, 0xB141 }, +{ 0xB142, 0xB142, 0xB142 }, +{ 0xB143, 0xB143, 0xB143 }, +{ 0xB144, 0xB144, 0xB144 }, +{ 0xB145, 0xB145, 0xB145 }, +{ 0xB146, 0xB146, 0xB146 }, +{ 0xB147, 0xB147, 0xB147 }, +{ 0xB148, 0xB148, 0xB148 }, +{ 0xB149, 0xB149, 0xB149 }, +{ 0xB14A, 0xB14A, 0xB14A }, +{ 0xB14B, 0xB14B, 0xB14B }, +{ 0xB14C, 0xB14C, 0xB14C }, +{ 0xB14D, 0xB14D, 0xB14D }, +{ 0xB14E, 0xB14E, 0xB14E }, +{ 0xB14F, 0xB14F, 0xB14F }, +{ 0xB150, 0xB150, 0xB150 }, +{ 0xB151, 0xB151, 0xB151 }, +{ 0xB152, 0xB152, 0xB152 }, +{ 0xB153, 0xB153, 0xB153 }, +{ 0xB154, 0xB154, 0xB154 }, +{ 0xB155, 0xB155, 0xB155 }, +{ 0xB156, 0xB156, 0xB156 }, +{ 0xB157, 0xB157, 0xB157 }, +{ 0xB158, 0xB158, 0xB158 }, +{ 0xB159, 0xB159, 0xB159 }, +{ 0xB15A, 0xB15A, 0xB15A }, +{ 0xB15B, 0xB15B, 0xB15B }, +{ 0xB15C, 0xB15C, 0xB15C }, +{ 0xB15D, 0xB15D, 0xB15D }, +{ 0xB15E, 0xB15E, 0xB15E }, +{ 0xB15F, 0xB15F, 0xB15F }, +{ 0xB160, 0xB160, 0xB160 }, +{ 0xB161, 0xB161, 0xB161 }, +{ 0xB162, 0xB162, 0xB162 }, +{ 0xB163, 0xB163, 0xB163 }, +{ 0xB164, 0xB164, 0xB164 }, +{ 0xB165, 0xB165, 0xB165 }, +{ 0xB166, 0xB166, 0xB166 }, +{ 0xB167, 0xB167, 0xB167 }, +{ 0xB168, 0xB168, 0xB168 }, +{ 0xB169, 0xB169, 0xB169 }, +{ 0xB16A, 0xB16A, 0xB16A }, +{ 0xB16B, 0xB16B, 0xB16B }, +{ 0xB16C, 0xB16C, 0xB16C }, +{ 0xB16D, 0xB16D, 0xB16D }, +{ 0xB16E, 0xB16E, 0xB16E }, +{ 0xB16F, 0xB16F, 0xB16F }, +{ 0xB170, 0xB170, 0xB170 }, +{ 0xB171, 0xB171, 0xB171 }, +{ 0xB172, 0xB172, 0xB172 }, +{ 0xB173, 0xB173, 0xB173 }, +{ 0xB174, 0xB174, 0xB174 }, +{ 0xB175, 0xB175, 0xB175 }, +{ 0xB176, 0xB176, 0xB176 }, +{ 0xB177, 0xB177, 0xB177 }, +{ 0xB178, 0xB178, 0xB178 }, +{ 0xB179, 0xB179, 0xB179 }, +{ 0xB17A, 0xB17A, 0xB17A }, +{ 0xB17B, 0xB17B, 0xB17B }, +{ 0xB17C, 0xB17C, 0xB17C }, +{ 0xB17D, 0xB17D, 0xB17D }, +{ 0xB17E, 0xB17E, 0xB17E }, +{ 0xB17F, 0xB17F, 0xB17F }, +{ 0xB180, 0xB180, 0xB180 }, +{ 0xB181, 0xB181, 0xB181 }, +{ 0xB182, 0xB182, 0xB182 }, +{ 0xB183, 0xB183, 0xB183 }, +{ 0xB184, 0xB184, 0xB184 }, +{ 0xB185, 0xB185, 0xB185 }, +{ 0xB186, 0xB186, 0xB186 }, +{ 0xB187, 0xB187, 0xB187 }, +{ 0xB188, 0xB188, 0xB188 }, +{ 0xB189, 0xB189, 0xB189 }, +{ 0xB18A, 0xB18A, 0xB18A }, +{ 0xB18B, 0xB18B, 0xB18B }, +{ 0xB18C, 0xB18C, 0xB18C }, +{ 0xB18D, 0xB18D, 0xB18D }, +{ 0xB18E, 0xB18E, 0xB18E }, +{ 0xB18F, 0xB18F, 0xB18F }, +{ 0xB190, 0xB190, 0xB190 }, +{ 0xB191, 0xB191, 0xB191 }, +{ 0xB192, 0xB192, 0xB192 }, +{ 0xB193, 0xB193, 0xB193 }, +{ 0xB194, 0xB194, 0xB194 }, +{ 0xB195, 0xB195, 0xB195 }, +{ 0xB196, 0xB196, 0xB196 }, +{ 0xB197, 0xB197, 0xB197 }, +{ 0xB198, 0xB198, 0xB198 }, +{ 0xB199, 0xB199, 0xB199 }, +{ 0xB19A, 0xB19A, 0xB19A }, +{ 0xB19B, 0xB19B, 0xB19B }, +{ 0xB19C, 0xB19C, 0xB19C }, +{ 0xB19D, 0xB19D, 0xB19D }, +{ 0xB19E, 0xB19E, 0xB19E }, +{ 0xB19F, 0xB19F, 0xB19F }, +{ 0xB1A0, 0xB1A0, 0xB1A0 }, +{ 0xB1A1, 0xB1A1, 0xB1A1 }, +{ 0xB1A2, 0xB1A2, 0xB1A2 }, +{ 0xB1A3, 0xB1A3, 0xB1A3 }, +{ 0xB1A4, 0xB1A4, 0xB1A4 }, +{ 0xB1A5, 0xB1A5, 0xB1A5 }, +{ 0xB1A6, 0xB1A6, 0xB1A6 }, +{ 0xB1A7, 0xB1A7, 0xB1A7 }, +{ 0xB1A8, 0xB1A8, 0xB1A8 }, +{ 0xB1A9, 0xB1A9, 0xB1A9 }, +{ 0xB1AA, 0xB1AA, 0xB1AA }, +{ 0xB1AB, 0xB1AB, 0xB1AB }, +{ 0xB1AC, 0xB1AC, 0xB1AC }, +{ 0xB1AD, 0xB1AD, 0xB1AD }, +{ 0xB1AE, 0xB1AE, 0xB1AE }, +{ 0xB1AF, 0xB1AF, 0xB1AF }, +{ 0xB1B0, 0xB1B0, 0xB1B0 }, +{ 0xB1B1, 0xB1B1, 0xB1B1 }, +{ 0xB1B2, 0xB1B2, 0xB1B2 }, +{ 0xB1B3, 0xB1B3, 0xB1B3 }, +{ 0xB1B4, 0xB1B4, 0xB1B4 }, +{ 0xB1B5, 0xB1B5, 0xB1B5 }, +{ 0xB1B6, 0xB1B6, 0xB1B6 }, +{ 0xB1B7, 0xB1B7, 0xB1B7 }, +{ 0xB1B8, 0xB1B8, 0xB1B8 }, +{ 0xB1B9, 0xB1B9, 0xB1B9 }, +{ 0xB1BA, 0xB1BA, 0xB1BA }, +{ 0xB1BB, 0xB1BB, 0xB1BB }, +{ 0xB1BC, 0xB1BC, 0xB1BC }, +{ 0xB1BD, 0xB1BD, 0xB1BD }, +{ 0xB1BE, 0xB1BE, 0xB1BE }, +{ 0xB1BF, 0xB1BF, 0xB1BF }, +{ 0xB1C0, 0xB1C0, 0xB1C0 }, +{ 0xB1C1, 0xB1C1, 0xB1C1 }, +{ 0xB1C2, 0xB1C2, 0xB1C2 }, +{ 0xB1C3, 0xB1C3, 0xB1C3 }, +{ 0xB1C4, 0xB1C4, 0xB1C4 }, +{ 0xB1C5, 0xB1C5, 0xB1C5 }, +{ 0xB1C6, 0xB1C6, 0xB1C6 }, +{ 0xB1C7, 0xB1C7, 0xB1C7 }, +{ 0xB1C8, 0xB1C8, 0xB1C8 }, +{ 0xB1C9, 0xB1C9, 0xB1C9 }, +{ 0xB1CA, 0xB1CA, 0xB1CA }, +{ 0xB1CB, 0xB1CB, 0xB1CB }, +{ 0xB1CC, 0xB1CC, 0xB1CC }, +{ 0xB1CD, 0xB1CD, 0xB1CD }, +{ 0xB1CE, 0xB1CE, 0xB1CE }, +{ 0xB1CF, 0xB1CF, 0xB1CF }, +{ 0xB1D0, 0xB1D0, 0xB1D0 }, +{ 0xB1D1, 0xB1D1, 0xB1D1 }, +{ 0xB1D2, 0xB1D2, 0xB1D2 }, +{ 0xB1D3, 0xB1D3, 0xB1D3 }, +{ 0xB1D4, 0xB1D4, 0xB1D4 }, +{ 0xB1D5, 0xB1D5, 0xB1D5 }, +{ 0xB1D6, 0xB1D6, 0xB1D6 }, +{ 0xB1D7, 0xB1D7, 0xB1D7 }, +{ 0xB1D8, 0xB1D8, 0xB1D8 }, +{ 0xB1D9, 0xB1D9, 0xB1D9 }, +{ 0xB1DA, 0xB1DA, 0xB1DA }, +{ 0xB1DB, 0xB1DB, 0xB1DB }, +{ 0xB1DC, 0xB1DC, 0xB1DC }, +{ 0xB1DD, 0xB1DD, 0xB1DD }, +{ 0xB1DE, 0xB1DE, 0xB1DE }, +{ 0xB1DF, 0xB1DF, 0xB1DF }, +{ 0xB1E0, 0xB1E0, 0xB1E0 }, +{ 0xB1E1, 0xB1E1, 0xB1E1 }, +{ 0xB1E2, 0xB1E2, 0xB1E2 }, +{ 0xB1E3, 0xB1E3, 0xB1E3 }, +{ 0xB1E4, 0xB1E4, 0xB1E4 }, +{ 0xB1E5, 0xB1E5, 0xB1E5 }, +{ 0xB1E6, 0xB1E6, 0xB1E6 }, +{ 0xB1E7, 0xB1E7, 0xB1E7 }, +{ 0xB1E8, 0xB1E8, 0xB1E8 }, +{ 0xB1E9, 0xB1E9, 0xB1E9 }, +{ 0xB1EA, 0xB1EA, 0xB1EA }, +{ 0xB1EB, 0xB1EB, 0xB1EB }, +{ 0xB1EC, 0xB1EC, 0xB1EC }, +{ 0xB1ED, 0xB1ED, 0xB1ED }, +{ 0xB1EE, 0xB1EE, 0xB1EE }, +{ 0xB1EF, 0xB1EF, 0xB1EF }, +{ 0xB1F0, 0xB1F0, 0xB1F0 }, +{ 0xB1F1, 0xB1F1, 0xB1F1 }, +{ 0xB1F2, 0xB1F2, 0xB1F2 }, +{ 0xB1F3, 0xB1F3, 0xB1F3 }, +{ 0xB1F4, 0xB1F4, 0xB1F4 }, +{ 0xB1F5, 0xB1F5, 0xB1F5 }, +{ 0xB1F6, 0xB1F6, 0xB1F6 }, +{ 0xB1F7, 0xB1F7, 0xB1F7 }, +{ 0xB1F8, 0xB1F8, 0xB1F8 }, +{ 0xB1F9, 0xB1F9, 0xB1F9 }, +{ 0xB1FA, 0xB1FA, 0xB1FA }, +{ 0xB1FB, 0xB1FB, 0xB1FB }, +{ 0xB1FC, 0xB1FC, 0xB1FC }, +{ 0xB1FD, 0xB1FD, 0xB1FD }, +{ 0xB1FE, 0xB1FE, 0xB1FE }, +{ 0xB1FF, 0xB1FF, 0xB1FF }, +{ 0xB200, 0xB200, 0xB200 }, +{ 0xB201, 0xB201, 0xB201 }, +{ 0xB202, 0xB202, 0xB202 }, +{ 0xB203, 0xB203, 0xB203 }, +{ 0xB204, 0xB204, 0xB204 }, +{ 0xB205, 0xB205, 0xB205 }, +{ 0xB206, 0xB206, 0xB206 }, +{ 0xB207, 0xB207, 0xB207 }, +{ 0xB208, 0xB208, 0xB208 }, +{ 0xB209, 0xB209, 0xB209 }, +{ 0xB20A, 0xB20A, 0xB20A }, +{ 0xB20B, 0xB20B, 0xB20B }, +{ 0xB20C, 0xB20C, 0xB20C }, +{ 0xB20D, 0xB20D, 0xB20D }, +{ 0xB20E, 0xB20E, 0xB20E }, +{ 0xB20F, 0xB20F, 0xB20F }, +{ 0xB210, 0xB210, 0xB210 }, +{ 0xB211, 0xB211, 0xB211 }, +{ 0xB212, 0xB212, 0xB212 }, +{ 0xB213, 0xB213, 0xB213 }, +{ 0xB214, 0xB214, 0xB214 }, +{ 0xB215, 0xB215, 0xB215 }, +{ 0xB216, 0xB216, 0xB216 }, +{ 0xB217, 0xB217, 0xB217 }, +{ 0xB218, 0xB218, 0xB218 }, +{ 0xB219, 0xB219, 0xB219 }, +{ 0xB21A, 0xB21A, 0xB21A }, +{ 0xB21B, 0xB21B, 0xB21B }, +{ 0xB21C, 0xB21C, 0xB21C }, +{ 0xB21D, 0xB21D, 0xB21D }, +{ 0xB21E, 0xB21E, 0xB21E }, +{ 0xB21F, 0xB21F, 0xB21F }, +{ 0xB220, 0xB220, 0xB220 }, +{ 0xB221, 0xB221, 0xB221 }, +{ 0xB222, 0xB222, 0xB222 }, +{ 0xB223, 0xB223, 0xB223 }, +{ 0xB224, 0xB224, 0xB224 }, +{ 0xB225, 0xB225, 0xB225 }, +{ 0xB226, 0xB226, 0xB226 }, +{ 0xB227, 0xB227, 0xB227 }, +{ 0xB228, 0xB228, 0xB228 }, +{ 0xB229, 0xB229, 0xB229 }, +{ 0xB22A, 0xB22A, 0xB22A }, +{ 0xB22B, 0xB22B, 0xB22B }, +{ 0xB22C, 0xB22C, 0xB22C }, +{ 0xB22D, 0xB22D, 0xB22D }, +{ 0xB22E, 0xB22E, 0xB22E }, +{ 0xB22F, 0xB22F, 0xB22F }, +{ 0xB230, 0xB230, 0xB230 }, +{ 0xB231, 0xB231, 0xB231 }, +{ 0xB232, 0xB232, 0xB232 }, +{ 0xB233, 0xB233, 0xB233 }, +{ 0xB234, 0xB234, 0xB234 }, +{ 0xB235, 0xB235, 0xB235 }, +{ 0xB236, 0xB236, 0xB236 }, +{ 0xB237, 0xB237, 0xB237 }, +{ 0xB238, 0xB238, 0xB238 }, +{ 0xB239, 0xB239, 0xB239 }, +{ 0xB23A, 0xB23A, 0xB23A }, +{ 0xB23B, 0xB23B, 0xB23B }, +{ 0xB23C, 0xB23C, 0xB23C }, +{ 0xB23D, 0xB23D, 0xB23D }, +{ 0xB23E, 0xB23E, 0xB23E }, +{ 0xB23F, 0xB23F, 0xB23F }, +{ 0xB240, 0xB240, 0xB240 }, +{ 0xB241, 0xB241, 0xB241 }, +{ 0xB242, 0xB242, 0xB242 }, +{ 0xB243, 0xB243, 0xB243 }, +{ 0xB244, 0xB244, 0xB244 }, +{ 0xB245, 0xB245, 0xB245 }, +{ 0xB246, 0xB246, 0xB246 }, +{ 0xB247, 0xB247, 0xB247 }, +{ 0xB248, 0xB248, 0xB248 }, +{ 0xB249, 0xB249, 0xB249 }, +{ 0xB24A, 0xB24A, 0xB24A }, +{ 0xB24B, 0xB24B, 0xB24B }, +{ 0xB24C, 0xB24C, 0xB24C }, +{ 0xB24D, 0xB24D, 0xB24D }, +{ 0xB24E, 0xB24E, 0xB24E }, +{ 0xB24F, 0xB24F, 0xB24F }, +{ 0xB250, 0xB250, 0xB250 }, +{ 0xB251, 0xB251, 0xB251 }, +{ 0xB252, 0xB252, 0xB252 }, +{ 0xB253, 0xB253, 0xB253 }, +{ 0xB254, 0xB254, 0xB254 }, +{ 0xB255, 0xB255, 0xB255 }, +{ 0xB256, 0xB256, 0xB256 }, +{ 0xB257, 0xB257, 0xB257 }, +{ 0xB258, 0xB258, 0xB258 }, +{ 0xB259, 0xB259, 0xB259 }, +{ 0xB25A, 0xB25A, 0xB25A }, +{ 0xB25B, 0xB25B, 0xB25B }, +{ 0xB25C, 0xB25C, 0xB25C }, +{ 0xB25D, 0xB25D, 0xB25D }, +{ 0xB25E, 0xB25E, 0xB25E }, +{ 0xB25F, 0xB25F, 0xB25F }, +{ 0xB260, 0xB260, 0xB260 }, +{ 0xB261, 0xB261, 0xB261 }, +{ 0xB262, 0xB262, 0xB262 }, +{ 0xB263, 0xB263, 0xB263 }, +{ 0xB264, 0xB264, 0xB264 }, +{ 0xB265, 0xB265, 0xB265 }, +{ 0xB266, 0xB266, 0xB266 }, +{ 0xB267, 0xB267, 0xB267 }, +{ 0xB268, 0xB268, 0xB268 }, +{ 0xB269, 0xB269, 0xB269 }, +{ 0xB26A, 0xB26A, 0xB26A }, +{ 0xB26B, 0xB26B, 0xB26B }, +{ 0xB26C, 0xB26C, 0xB26C }, +{ 0xB26D, 0xB26D, 0xB26D }, +{ 0xB26E, 0xB26E, 0xB26E }, +{ 0xB26F, 0xB26F, 0xB26F }, +{ 0xB270, 0xB270, 0xB270 }, +{ 0xB271, 0xB271, 0xB271 }, +{ 0xB272, 0xB272, 0xB272 }, +{ 0xB273, 0xB273, 0xB273 }, +{ 0xB274, 0xB274, 0xB274 }, +{ 0xB275, 0xB275, 0xB275 }, +{ 0xB276, 0xB276, 0xB276 }, +{ 0xB277, 0xB277, 0xB277 }, +{ 0xB278, 0xB278, 0xB278 }, +{ 0xB279, 0xB279, 0xB279 }, +{ 0xB27A, 0xB27A, 0xB27A }, +{ 0xB27B, 0xB27B, 0xB27B }, +{ 0xB27C, 0xB27C, 0xB27C }, +{ 0xB27D, 0xB27D, 0xB27D }, +{ 0xB27E, 0xB27E, 0xB27E }, +{ 0xB27F, 0xB27F, 0xB27F }, +{ 0xB280, 0xB280, 0xB280 }, +{ 0xB281, 0xB281, 0xB281 }, +{ 0xB282, 0xB282, 0xB282 }, +{ 0xB283, 0xB283, 0xB283 }, +{ 0xB284, 0xB284, 0xB284 }, +{ 0xB285, 0xB285, 0xB285 }, +{ 0xB286, 0xB286, 0xB286 }, +{ 0xB287, 0xB287, 0xB287 }, +{ 0xB288, 0xB288, 0xB288 }, +{ 0xB289, 0xB289, 0xB289 }, +{ 0xB28A, 0xB28A, 0xB28A }, +{ 0xB28B, 0xB28B, 0xB28B }, +{ 0xB28C, 0xB28C, 0xB28C }, +{ 0xB28D, 0xB28D, 0xB28D }, +{ 0xB28E, 0xB28E, 0xB28E }, +{ 0xB28F, 0xB28F, 0xB28F }, +{ 0xB290, 0xB290, 0xB290 }, +{ 0xB291, 0xB291, 0xB291 }, +{ 0xB292, 0xB292, 0xB292 }, +{ 0xB293, 0xB293, 0xB293 }, +{ 0xB294, 0xB294, 0xB294 }, +{ 0xB295, 0xB295, 0xB295 }, +{ 0xB296, 0xB296, 0xB296 }, +{ 0xB297, 0xB297, 0xB297 }, +{ 0xB298, 0xB298, 0xB298 }, +{ 0xB299, 0xB299, 0xB299 }, +{ 0xB29A, 0xB29A, 0xB29A }, +{ 0xB29B, 0xB29B, 0xB29B }, +{ 0xB29C, 0xB29C, 0xB29C }, +{ 0xB29D, 0xB29D, 0xB29D }, +{ 0xB29E, 0xB29E, 0xB29E }, +{ 0xB29F, 0xB29F, 0xB29F }, +{ 0xB2A0, 0xB2A0, 0xB2A0 }, +{ 0xB2A1, 0xB2A1, 0xB2A1 }, +{ 0xB2A2, 0xB2A2, 0xB2A2 }, +{ 0xB2A3, 0xB2A3, 0xB2A3 }, +{ 0xB2A4, 0xB2A4, 0xB2A4 }, +{ 0xB2A5, 0xB2A5, 0xB2A5 }, +{ 0xB2A6, 0xB2A6, 0xB2A6 }, +{ 0xB2A7, 0xB2A7, 0xB2A7 }, +{ 0xB2A8, 0xB2A8, 0xB2A8 }, +{ 0xB2A9, 0xB2A9, 0xB2A9 }, +{ 0xB2AA, 0xB2AA, 0xB2AA }, +{ 0xB2AB, 0xB2AB, 0xB2AB }, +{ 0xB2AC, 0xB2AC, 0xB2AC }, +{ 0xB2AD, 0xB2AD, 0xB2AD }, +{ 0xB2AE, 0xB2AE, 0xB2AE }, +{ 0xB2AF, 0xB2AF, 0xB2AF }, +{ 0xB2B0, 0xB2B0, 0xB2B0 }, +{ 0xB2B1, 0xB2B1, 0xB2B1 }, +{ 0xB2B2, 0xB2B2, 0xB2B2 }, +{ 0xB2B3, 0xB2B3, 0xB2B3 }, +{ 0xB2B4, 0xB2B4, 0xB2B4 }, +{ 0xB2B5, 0xB2B5, 0xB2B5 }, +{ 0xB2B6, 0xB2B6, 0xB2B6 }, +{ 0xB2B7, 0xB2B7, 0xB2B7 }, +{ 0xB2B8, 0xB2B8, 0xB2B8 }, +{ 0xB2B9, 0xB2B9, 0xB2B9 }, +{ 0xB2BA, 0xB2BA, 0xB2BA }, +{ 0xB2BB, 0xB2BB, 0xB2BB }, +{ 0xB2BC, 0xB2BC, 0xB2BC }, +{ 0xB2BD, 0xB2BD, 0xB2BD }, +{ 0xB2BE, 0xB2BE, 0xB2BE }, +{ 0xB2BF, 0xB2BF, 0xB2BF }, +{ 0xB2C0, 0xB2C0, 0xB2C0 }, +{ 0xB2C1, 0xB2C1, 0xB2C1 }, +{ 0xB2C2, 0xB2C2, 0xB2C2 }, +{ 0xB2C3, 0xB2C3, 0xB2C3 }, +{ 0xB2C4, 0xB2C4, 0xB2C4 }, +{ 0xB2C5, 0xB2C5, 0xB2C5 }, +{ 0xB2C6, 0xB2C6, 0xB2C6 }, +{ 0xB2C7, 0xB2C7, 0xB2C7 }, +{ 0xB2C8, 0xB2C8, 0xB2C8 }, +{ 0xB2C9, 0xB2C9, 0xB2C9 }, +{ 0xB2CA, 0xB2CA, 0xB2CA }, +{ 0xB2CB, 0xB2CB, 0xB2CB }, +{ 0xB2CC, 0xB2CC, 0xB2CC }, +{ 0xB2CD, 0xB2CD, 0xB2CD }, +{ 0xB2CE, 0xB2CE, 0xB2CE }, +{ 0xB2CF, 0xB2CF, 0xB2CF }, +{ 0xB2D0, 0xB2D0, 0xB2D0 }, +{ 0xB2D1, 0xB2D1, 0xB2D1 }, +{ 0xB2D2, 0xB2D2, 0xB2D2 }, +{ 0xB2D3, 0xB2D3, 0xB2D3 }, +{ 0xB2D4, 0xB2D4, 0xB2D4 }, +{ 0xB2D5, 0xB2D5, 0xB2D5 }, +{ 0xB2D6, 0xB2D6, 0xB2D6 }, +{ 0xB2D7, 0xB2D7, 0xB2D7 }, +{ 0xB2D8, 0xB2D8, 0xB2D8 }, +{ 0xB2D9, 0xB2D9, 0xB2D9 }, +{ 0xB2DA, 0xB2DA, 0xB2DA }, +{ 0xB2DB, 0xB2DB, 0xB2DB }, +{ 0xB2DC, 0xB2DC, 0xB2DC }, +{ 0xB2DD, 0xB2DD, 0xB2DD }, +{ 0xB2DE, 0xB2DE, 0xB2DE }, +{ 0xB2DF, 0xB2DF, 0xB2DF }, +{ 0xB2E0, 0xB2E0, 0xB2E0 }, +{ 0xB2E1, 0xB2E1, 0xB2E1 }, +{ 0xB2E2, 0xB2E2, 0xB2E2 }, +{ 0xB2E3, 0xB2E3, 0xB2E3 }, +{ 0xB2E4, 0xB2E4, 0xB2E4 }, +{ 0xB2E5, 0xB2E5, 0xB2E5 }, +{ 0xB2E6, 0xB2E6, 0xB2E6 }, +{ 0xB2E7, 0xB2E7, 0xB2E7 }, +{ 0xB2E8, 0xB2E8, 0xB2E8 }, +{ 0xB2E9, 0xB2E9, 0xB2E9 }, +{ 0xB2EA, 0xB2EA, 0xB2EA }, +{ 0xB2EB, 0xB2EB, 0xB2EB }, +{ 0xB2EC, 0xB2EC, 0xB2EC }, +{ 0xB2ED, 0xB2ED, 0xB2ED }, +{ 0xB2EE, 0xB2EE, 0xB2EE }, +{ 0xB2EF, 0xB2EF, 0xB2EF }, +{ 0xB2F0, 0xB2F0, 0xB2F0 }, +{ 0xB2F1, 0xB2F1, 0xB2F1 }, +{ 0xB2F2, 0xB2F2, 0xB2F2 }, +{ 0xB2F3, 0xB2F3, 0xB2F3 }, +{ 0xB2F4, 0xB2F4, 0xB2F4 }, +{ 0xB2F5, 0xB2F5, 0xB2F5 }, +{ 0xB2F6, 0xB2F6, 0xB2F6 }, +{ 0xB2F7, 0xB2F7, 0xB2F7 }, +{ 0xB2F8, 0xB2F8, 0xB2F8 }, +{ 0xB2F9, 0xB2F9, 0xB2F9 }, +{ 0xB2FA, 0xB2FA, 0xB2FA }, +{ 0xB2FB, 0xB2FB, 0xB2FB }, +{ 0xB2FC, 0xB2FC, 0xB2FC }, +{ 0xB2FD, 0xB2FD, 0xB2FD }, +{ 0xB2FE, 0xB2FE, 0xB2FE }, +{ 0xB2FF, 0xB2FF, 0xB2FF }, +{ 0xB300, 0xB300, 0xB300 }, +{ 0xB301, 0xB301, 0xB301 }, +{ 0xB302, 0xB302, 0xB302 }, +{ 0xB303, 0xB303, 0xB303 }, +{ 0xB304, 0xB304, 0xB304 }, +{ 0xB305, 0xB305, 0xB305 }, +{ 0xB306, 0xB306, 0xB306 }, +{ 0xB307, 0xB307, 0xB307 }, +{ 0xB308, 0xB308, 0xB308 }, +{ 0xB309, 0xB309, 0xB309 }, +{ 0xB30A, 0xB30A, 0xB30A }, +{ 0xB30B, 0xB30B, 0xB30B }, +{ 0xB30C, 0xB30C, 0xB30C }, +{ 0xB30D, 0xB30D, 0xB30D }, +{ 0xB30E, 0xB30E, 0xB30E }, +{ 0xB30F, 0xB30F, 0xB30F }, +{ 0xB310, 0xB310, 0xB310 }, +{ 0xB311, 0xB311, 0xB311 }, +{ 0xB312, 0xB312, 0xB312 }, +{ 0xB313, 0xB313, 0xB313 }, +{ 0xB314, 0xB314, 0xB314 }, +{ 0xB315, 0xB315, 0xB315 }, +{ 0xB316, 0xB316, 0xB316 }, +{ 0xB317, 0xB317, 0xB317 }, +{ 0xB318, 0xB318, 0xB318 }, +{ 0xB319, 0xB319, 0xB319 }, +{ 0xB31A, 0xB31A, 0xB31A }, +{ 0xB31B, 0xB31B, 0xB31B }, +{ 0xB31C, 0xB31C, 0xB31C }, +{ 0xB31D, 0xB31D, 0xB31D }, +{ 0xB31E, 0xB31E, 0xB31E }, +{ 0xB31F, 0xB31F, 0xB31F }, +{ 0xB320, 0xB320, 0xB320 }, +{ 0xB321, 0xB321, 0xB321 }, +{ 0xB322, 0xB322, 0xB322 }, +{ 0xB323, 0xB323, 0xB323 }, +{ 0xB324, 0xB324, 0xB324 }, +{ 0xB325, 0xB325, 0xB325 }, +{ 0xB326, 0xB326, 0xB326 }, +{ 0xB327, 0xB327, 0xB327 }, +{ 0xB328, 0xB328, 0xB328 }, +{ 0xB329, 0xB329, 0xB329 }, +{ 0xB32A, 0xB32A, 0xB32A }, +{ 0xB32B, 0xB32B, 0xB32B }, +{ 0xB32C, 0xB32C, 0xB32C }, +{ 0xB32D, 0xB32D, 0xB32D }, +{ 0xB32E, 0xB32E, 0xB32E }, +{ 0xB32F, 0xB32F, 0xB32F }, +{ 0xB330, 0xB330, 0xB330 }, +{ 0xB331, 0xB331, 0xB331 }, +{ 0xB332, 0xB332, 0xB332 }, +{ 0xB333, 0xB333, 0xB333 }, +{ 0xB334, 0xB334, 0xB334 }, +{ 0xB335, 0xB335, 0xB335 }, +{ 0xB336, 0xB336, 0xB336 }, +{ 0xB337, 0xB337, 0xB337 }, +{ 0xB338, 0xB338, 0xB338 }, +{ 0xB339, 0xB339, 0xB339 }, +{ 0xB33A, 0xB33A, 0xB33A }, +{ 0xB33B, 0xB33B, 0xB33B }, +{ 0xB33C, 0xB33C, 0xB33C }, +{ 0xB33D, 0xB33D, 0xB33D }, +{ 0xB33E, 0xB33E, 0xB33E }, +{ 0xB33F, 0xB33F, 0xB33F }, +{ 0xB340, 0xB340, 0xB340 }, +{ 0xB341, 0xB341, 0xB341 }, +{ 0xB342, 0xB342, 0xB342 }, +{ 0xB343, 0xB343, 0xB343 }, +{ 0xB344, 0xB344, 0xB344 }, +{ 0xB345, 0xB345, 0xB345 }, +{ 0xB346, 0xB346, 0xB346 }, +{ 0xB347, 0xB347, 0xB347 }, +{ 0xB348, 0xB348, 0xB348 }, +{ 0xB349, 0xB349, 0xB349 }, +{ 0xB34A, 0xB34A, 0xB34A }, +{ 0xB34B, 0xB34B, 0xB34B }, +{ 0xB34C, 0xB34C, 0xB34C }, +{ 0xB34D, 0xB34D, 0xB34D }, +{ 0xB34E, 0xB34E, 0xB34E }, +{ 0xB34F, 0xB34F, 0xB34F }, +{ 0xB350, 0xB350, 0xB350 }, +{ 0xB351, 0xB351, 0xB351 }, +{ 0xB352, 0xB352, 0xB352 }, +{ 0xB353, 0xB353, 0xB353 }, +{ 0xB354, 0xB354, 0xB354 }, +{ 0xB355, 0xB355, 0xB355 }, +{ 0xB356, 0xB356, 0xB356 }, +{ 0xB357, 0xB357, 0xB357 }, +{ 0xB358, 0xB358, 0xB358 }, +{ 0xB359, 0xB359, 0xB359 }, +{ 0xB35A, 0xB35A, 0xB35A }, +{ 0xB35B, 0xB35B, 0xB35B }, +{ 0xB35C, 0xB35C, 0xB35C }, +{ 0xB35D, 0xB35D, 0xB35D }, +{ 0xB35E, 0xB35E, 0xB35E }, +{ 0xB35F, 0xB35F, 0xB35F }, +{ 0xB360, 0xB360, 0xB360 }, +{ 0xB361, 0xB361, 0xB361 }, +{ 0xB362, 0xB362, 0xB362 }, +{ 0xB363, 0xB363, 0xB363 }, +{ 0xB364, 0xB364, 0xB364 }, +{ 0xB365, 0xB365, 0xB365 }, +{ 0xB366, 0xB366, 0xB366 }, +{ 0xB367, 0xB367, 0xB367 }, +{ 0xB368, 0xB368, 0xB368 }, +{ 0xB369, 0xB369, 0xB369 }, +{ 0xB36A, 0xB36A, 0xB36A }, +{ 0xB36B, 0xB36B, 0xB36B }, +{ 0xB36C, 0xB36C, 0xB36C }, +{ 0xB36D, 0xB36D, 0xB36D }, +{ 0xB36E, 0xB36E, 0xB36E }, +{ 0xB36F, 0xB36F, 0xB36F }, +{ 0xB370, 0xB370, 0xB370 }, +{ 0xB371, 0xB371, 0xB371 }, +{ 0xB372, 0xB372, 0xB372 }, +{ 0xB373, 0xB373, 0xB373 }, +{ 0xB374, 0xB374, 0xB374 }, +{ 0xB375, 0xB375, 0xB375 }, +{ 0xB376, 0xB376, 0xB376 }, +{ 0xB377, 0xB377, 0xB377 }, +{ 0xB378, 0xB378, 0xB378 }, +{ 0xB379, 0xB379, 0xB379 }, +{ 0xB37A, 0xB37A, 0xB37A }, +{ 0xB37B, 0xB37B, 0xB37B }, +{ 0xB37C, 0xB37C, 0xB37C }, +{ 0xB37D, 0xB37D, 0xB37D }, +{ 0xB37E, 0xB37E, 0xB37E }, +{ 0xB37F, 0xB37F, 0xB37F }, +{ 0xB380, 0xB380, 0xB380 }, +{ 0xB381, 0xB381, 0xB381 }, +{ 0xB382, 0xB382, 0xB382 }, +{ 0xB383, 0xB383, 0xB383 }, +{ 0xB384, 0xB384, 0xB384 }, +{ 0xB385, 0xB385, 0xB385 }, +{ 0xB386, 0xB386, 0xB386 }, +{ 0xB387, 0xB387, 0xB387 }, +{ 0xB388, 0xB388, 0xB388 }, +{ 0xB389, 0xB389, 0xB389 }, +{ 0xB38A, 0xB38A, 0xB38A }, +{ 0xB38B, 0xB38B, 0xB38B }, +{ 0xB38C, 0xB38C, 0xB38C }, +{ 0xB38D, 0xB38D, 0xB38D }, +{ 0xB38E, 0xB38E, 0xB38E }, +{ 0xB38F, 0xB38F, 0xB38F }, +{ 0xB390, 0xB390, 0xB390 }, +{ 0xB391, 0xB391, 0xB391 }, +{ 0xB392, 0xB392, 0xB392 }, +{ 0xB393, 0xB393, 0xB393 }, +{ 0xB394, 0xB394, 0xB394 }, +{ 0xB395, 0xB395, 0xB395 }, +{ 0xB396, 0xB396, 0xB396 }, +{ 0xB397, 0xB397, 0xB397 }, +{ 0xB398, 0xB398, 0xB398 }, +{ 0xB399, 0xB399, 0xB399 }, +{ 0xB39A, 0xB39A, 0xB39A }, +{ 0xB39B, 0xB39B, 0xB39B }, +{ 0xB39C, 0xB39C, 0xB39C }, +{ 0xB39D, 0xB39D, 0xB39D }, +{ 0xB39E, 0xB39E, 0xB39E }, +{ 0xB39F, 0xB39F, 0xB39F }, +{ 0xB3A0, 0xB3A0, 0xB3A0 }, +{ 0xB3A1, 0xB3A1, 0xB3A1 }, +{ 0xB3A2, 0xB3A2, 0xB3A2 }, +{ 0xB3A3, 0xB3A3, 0xB3A3 }, +{ 0xB3A4, 0xB3A4, 0xB3A4 }, +{ 0xB3A5, 0xB3A5, 0xB3A5 }, +{ 0xB3A6, 0xB3A6, 0xB3A6 }, +{ 0xB3A7, 0xB3A7, 0xB3A7 }, +{ 0xB3A8, 0xB3A8, 0xB3A8 }, +{ 0xB3A9, 0xB3A9, 0xB3A9 }, +{ 0xB3AA, 0xB3AA, 0xB3AA }, +{ 0xB3AB, 0xB3AB, 0xB3AB }, +{ 0xB3AC, 0xB3AC, 0xB3AC }, +{ 0xB3AD, 0xB3AD, 0xB3AD }, +{ 0xB3AE, 0xB3AE, 0xB3AE }, +{ 0xB3AF, 0xB3AF, 0xB3AF }, +{ 0xB3B0, 0xB3B0, 0xB3B0 }, +{ 0xB3B1, 0xB3B1, 0xB3B1 }, +{ 0xB3B2, 0xB3B2, 0xB3B2 }, +{ 0xB3B3, 0xB3B3, 0xB3B3 }, +{ 0xB3B4, 0xB3B4, 0xB3B4 }, +{ 0xB3B5, 0xB3B5, 0xB3B5 }, +{ 0xB3B6, 0xB3B6, 0xB3B6 }, +{ 0xB3B7, 0xB3B7, 0xB3B7 }, +{ 0xB3B8, 0xB3B8, 0xB3B8 }, +{ 0xB3B9, 0xB3B9, 0xB3B9 }, +{ 0xB3BA, 0xB3BA, 0xB3BA }, +{ 0xB3BB, 0xB3BB, 0xB3BB }, +{ 0xB3BC, 0xB3BC, 0xB3BC }, +{ 0xB3BD, 0xB3BD, 0xB3BD }, +{ 0xB3BE, 0xB3BE, 0xB3BE }, +{ 0xB3BF, 0xB3BF, 0xB3BF }, +{ 0xB3C0, 0xB3C0, 0xB3C0 }, +{ 0xB3C1, 0xB3C1, 0xB3C1 }, +{ 0xB3C2, 0xB3C2, 0xB3C2 }, +{ 0xB3C3, 0xB3C3, 0xB3C3 }, +{ 0xB3C4, 0xB3C4, 0xB3C4 }, +{ 0xB3C5, 0xB3C5, 0xB3C5 }, +{ 0xB3C6, 0xB3C6, 0xB3C6 }, +{ 0xB3C7, 0xB3C7, 0xB3C7 }, +{ 0xB3C8, 0xB3C8, 0xB3C8 }, +{ 0xB3C9, 0xB3C9, 0xB3C9 }, +{ 0xB3CA, 0xB3CA, 0xB3CA }, +{ 0xB3CB, 0xB3CB, 0xB3CB }, +{ 0xB3CC, 0xB3CC, 0xB3CC }, +{ 0xB3CD, 0xB3CD, 0xB3CD }, +{ 0xB3CE, 0xB3CE, 0xB3CE }, +{ 0xB3CF, 0xB3CF, 0xB3CF }, +{ 0xB3D0, 0xB3D0, 0xB3D0 }, +{ 0xB3D1, 0xB3D1, 0xB3D1 }, +{ 0xB3D2, 0xB3D2, 0xB3D2 }, +{ 0xB3D3, 0xB3D3, 0xB3D3 }, +{ 0xB3D4, 0xB3D4, 0xB3D4 }, +{ 0xB3D5, 0xB3D5, 0xB3D5 }, +{ 0xB3D6, 0xB3D6, 0xB3D6 }, +{ 0xB3D7, 0xB3D7, 0xB3D7 }, +{ 0xB3D8, 0xB3D8, 0xB3D8 }, +{ 0xB3D9, 0xB3D9, 0xB3D9 }, +{ 0xB3DA, 0xB3DA, 0xB3DA }, +{ 0xB3DB, 0xB3DB, 0xB3DB }, +{ 0xB3DC, 0xB3DC, 0xB3DC }, +{ 0xB3DD, 0xB3DD, 0xB3DD }, +{ 0xB3DE, 0xB3DE, 0xB3DE }, +{ 0xB3DF, 0xB3DF, 0xB3DF }, +{ 0xB3E0, 0xB3E0, 0xB3E0 }, +{ 0xB3E1, 0xB3E1, 0xB3E1 }, +{ 0xB3E2, 0xB3E2, 0xB3E2 }, +{ 0xB3E3, 0xB3E3, 0xB3E3 }, +{ 0xB3E4, 0xB3E4, 0xB3E4 }, +{ 0xB3E5, 0xB3E5, 0xB3E5 }, +{ 0xB3E6, 0xB3E6, 0xB3E6 }, +{ 0xB3E7, 0xB3E7, 0xB3E7 }, +{ 0xB3E8, 0xB3E8, 0xB3E8 }, +{ 0xB3E9, 0xB3E9, 0xB3E9 }, +{ 0xB3EA, 0xB3EA, 0xB3EA }, +{ 0xB3EB, 0xB3EB, 0xB3EB }, +{ 0xB3EC, 0xB3EC, 0xB3EC }, +{ 0xB3ED, 0xB3ED, 0xB3ED }, +{ 0xB3EE, 0xB3EE, 0xB3EE }, +{ 0xB3EF, 0xB3EF, 0xB3EF }, +{ 0xB3F0, 0xB3F0, 0xB3F0 }, +{ 0xB3F1, 0xB3F1, 0xB3F1 }, +{ 0xB3F2, 0xB3F2, 0xB3F2 }, +{ 0xB3F3, 0xB3F3, 0xB3F3 }, +{ 0xB3F4, 0xB3F4, 0xB3F4 }, +{ 0xB3F5, 0xB3F5, 0xB3F5 }, +{ 0xB3F6, 0xB3F6, 0xB3F6 }, +{ 0xB3F7, 0xB3F7, 0xB3F7 }, +{ 0xB3F8, 0xB3F8, 0xB3F8 }, +{ 0xB3F9, 0xB3F9, 0xB3F9 }, +{ 0xB3FA, 0xB3FA, 0xB3FA }, +{ 0xB3FB, 0xB3FB, 0xB3FB }, +{ 0xB3FC, 0xB3FC, 0xB3FC }, +{ 0xB3FD, 0xB3FD, 0xB3FD }, +{ 0xB3FE, 0xB3FE, 0xB3FE }, +{ 0xB3FF, 0xB3FF, 0xB3FF }, +{ 0xB400, 0xB400, 0xB400 }, +{ 0xB401, 0xB401, 0xB401 }, +{ 0xB402, 0xB402, 0xB402 }, +{ 0xB403, 0xB403, 0xB403 }, +{ 0xB404, 0xB404, 0xB404 }, +{ 0xB405, 0xB405, 0xB405 }, +{ 0xB406, 0xB406, 0xB406 }, +{ 0xB407, 0xB407, 0xB407 }, +{ 0xB408, 0xB408, 0xB408 }, +{ 0xB409, 0xB409, 0xB409 }, +{ 0xB40A, 0xB40A, 0xB40A }, +{ 0xB40B, 0xB40B, 0xB40B }, +{ 0xB40C, 0xB40C, 0xB40C }, +{ 0xB40D, 0xB40D, 0xB40D }, +{ 0xB40E, 0xB40E, 0xB40E }, +{ 0xB40F, 0xB40F, 0xB40F }, +{ 0xB410, 0xB410, 0xB410 }, +{ 0xB411, 0xB411, 0xB411 }, +{ 0xB412, 0xB412, 0xB412 }, +{ 0xB413, 0xB413, 0xB413 }, +{ 0xB414, 0xB414, 0xB414 }, +{ 0xB415, 0xB415, 0xB415 }, +{ 0xB416, 0xB416, 0xB416 }, +{ 0xB417, 0xB417, 0xB417 }, +{ 0xB418, 0xB418, 0xB418 }, +{ 0xB419, 0xB419, 0xB419 }, +{ 0xB41A, 0xB41A, 0xB41A }, +{ 0xB41B, 0xB41B, 0xB41B }, +{ 0xB41C, 0xB41C, 0xB41C }, +{ 0xB41D, 0xB41D, 0xB41D }, +{ 0xB41E, 0xB41E, 0xB41E }, +{ 0xB41F, 0xB41F, 0xB41F }, +{ 0xB420, 0xB420, 0xB420 }, +{ 0xB421, 0xB421, 0xB421 }, +{ 0xB422, 0xB422, 0xB422 }, +{ 0xB423, 0xB423, 0xB423 }, +{ 0xB424, 0xB424, 0xB424 }, +{ 0xB425, 0xB425, 0xB425 }, +{ 0xB426, 0xB426, 0xB426 }, +{ 0xB427, 0xB427, 0xB427 }, +{ 0xB428, 0xB428, 0xB428 }, +{ 0xB429, 0xB429, 0xB429 }, +{ 0xB42A, 0xB42A, 0xB42A }, +{ 0xB42B, 0xB42B, 0xB42B }, +{ 0xB42C, 0xB42C, 0xB42C }, +{ 0xB42D, 0xB42D, 0xB42D }, +{ 0xB42E, 0xB42E, 0xB42E }, +{ 0xB42F, 0xB42F, 0xB42F }, +{ 0xB430, 0xB430, 0xB430 }, +{ 0xB431, 0xB431, 0xB431 }, +{ 0xB432, 0xB432, 0xB432 }, +{ 0xB433, 0xB433, 0xB433 }, +{ 0xB434, 0xB434, 0xB434 }, +{ 0xB435, 0xB435, 0xB435 }, +{ 0xB436, 0xB436, 0xB436 }, +{ 0xB437, 0xB437, 0xB437 }, +{ 0xB438, 0xB438, 0xB438 }, +{ 0xB439, 0xB439, 0xB439 }, +{ 0xB43A, 0xB43A, 0xB43A }, +{ 0xB43B, 0xB43B, 0xB43B }, +{ 0xB43C, 0xB43C, 0xB43C }, +{ 0xB43D, 0xB43D, 0xB43D }, +{ 0xB43E, 0xB43E, 0xB43E }, +{ 0xB43F, 0xB43F, 0xB43F }, +{ 0xB440, 0xB440, 0xB440 }, +{ 0xB441, 0xB441, 0xB441 }, +{ 0xB442, 0xB442, 0xB442 }, +{ 0xB443, 0xB443, 0xB443 }, +{ 0xB444, 0xB444, 0xB444 }, +{ 0xB445, 0xB445, 0xB445 }, +{ 0xB446, 0xB446, 0xB446 }, +{ 0xB447, 0xB447, 0xB447 }, +{ 0xB448, 0xB448, 0xB448 }, +{ 0xB449, 0xB449, 0xB449 }, +{ 0xB44A, 0xB44A, 0xB44A }, +{ 0xB44B, 0xB44B, 0xB44B }, +{ 0xB44C, 0xB44C, 0xB44C }, +{ 0xB44D, 0xB44D, 0xB44D }, +{ 0xB44E, 0xB44E, 0xB44E }, +{ 0xB44F, 0xB44F, 0xB44F }, +{ 0xB450, 0xB450, 0xB450 }, +{ 0xB451, 0xB451, 0xB451 }, +{ 0xB452, 0xB452, 0xB452 }, +{ 0xB453, 0xB453, 0xB453 }, +{ 0xB454, 0xB454, 0xB454 }, +{ 0xB455, 0xB455, 0xB455 }, +{ 0xB456, 0xB456, 0xB456 }, +{ 0xB457, 0xB457, 0xB457 }, +{ 0xB458, 0xB458, 0xB458 }, +{ 0xB459, 0xB459, 0xB459 }, +{ 0xB45A, 0xB45A, 0xB45A }, +{ 0xB45B, 0xB45B, 0xB45B }, +{ 0xB45C, 0xB45C, 0xB45C }, +{ 0xB45D, 0xB45D, 0xB45D }, +{ 0xB45E, 0xB45E, 0xB45E }, +{ 0xB45F, 0xB45F, 0xB45F }, +{ 0xB460, 0xB460, 0xB460 }, +{ 0xB461, 0xB461, 0xB461 }, +{ 0xB462, 0xB462, 0xB462 }, +{ 0xB463, 0xB463, 0xB463 }, +{ 0xB464, 0xB464, 0xB464 }, +{ 0xB465, 0xB465, 0xB465 }, +{ 0xB466, 0xB466, 0xB466 }, +{ 0xB467, 0xB467, 0xB467 }, +{ 0xB468, 0xB468, 0xB468 }, +{ 0xB469, 0xB469, 0xB469 }, +{ 0xB46A, 0xB46A, 0xB46A }, +{ 0xB46B, 0xB46B, 0xB46B }, +{ 0xB46C, 0xB46C, 0xB46C }, +{ 0xB46D, 0xB46D, 0xB46D }, +{ 0xB46E, 0xB46E, 0xB46E }, +{ 0xB46F, 0xB46F, 0xB46F }, +{ 0xB470, 0xB470, 0xB470 }, +{ 0xB471, 0xB471, 0xB471 }, +{ 0xB472, 0xB472, 0xB472 }, +{ 0xB473, 0xB473, 0xB473 }, +{ 0xB474, 0xB474, 0xB474 }, +{ 0xB475, 0xB475, 0xB475 }, +{ 0xB476, 0xB476, 0xB476 }, +{ 0xB477, 0xB477, 0xB477 }, +{ 0xB478, 0xB478, 0xB478 }, +{ 0xB479, 0xB479, 0xB479 }, +{ 0xB47A, 0xB47A, 0xB47A }, +{ 0xB47B, 0xB47B, 0xB47B }, +{ 0xB47C, 0xB47C, 0xB47C }, +{ 0xB47D, 0xB47D, 0xB47D }, +{ 0xB47E, 0xB47E, 0xB47E }, +{ 0xB47F, 0xB47F, 0xB47F }, +{ 0xB480, 0xB480, 0xB480 }, +{ 0xB481, 0xB481, 0xB481 }, +{ 0xB482, 0xB482, 0xB482 }, +{ 0xB483, 0xB483, 0xB483 }, +{ 0xB484, 0xB484, 0xB484 }, +{ 0xB485, 0xB485, 0xB485 }, +{ 0xB486, 0xB486, 0xB486 }, +{ 0xB487, 0xB487, 0xB487 }, +{ 0xB488, 0xB488, 0xB488 }, +{ 0xB489, 0xB489, 0xB489 }, +{ 0xB48A, 0xB48A, 0xB48A }, +{ 0xB48B, 0xB48B, 0xB48B }, +{ 0xB48C, 0xB48C, 0xB48C }, +{ 0xB48D, 0xB48D, 0xB48D }, +{ 0xB48E, 0xB48E, 0xB48E }, +{ 0xB48F, 0xB48F, 0xB48F }, +{ 0xB490, 0xB490, 0xB490 }, +{ 0xB491, 0xB491, 0xB491 }, +{ 0xB492, 0xB492, 0xB492 }, +{ 0xB493, 0xB493, 0xB493 }, +{ 0xB494, 0xB494, 0xB494 }, +{ 0xB495, 0xB495, 0xB495 }, +{ 0xB496, 0xB496, 0xB496 }, +{ 0xB497, 0xB497, 0xB497 }, +{ 0xB498, 0xB498, 0xB498 }, +{ 0xB499, 0xB499, 0xB499 }, +{ 0xB49A, 0xB49A, 0xB49A }, +{ 0xB49B, 0xB49B, 0xB49B }, +{ 0xB49C, 0xB49C, 0xB49C }, +{ 0xB49D, 0xB49D, 0xB49D }, +{ 0xB49E, 0xB49E, 0xB49E }, +{ 0xB49F, 0xB49F, 0xB49F }, +{ 0xB4A0, 0xB4A0, 0xB4A0 }, +{ 0xB4A1, 0xB4A1, 0xB4A1 }, +{ 0xB4A2, 0xB4A2, 0xB4A2 }, +{ 0xB4A3, 0xB4A3, 0xB4A3 }, +{ 0xB4A4, 0xB4A4, 0xB4A4 }, +{ 0xB4A5, 0xB4A5, 0xB4A5 }, +{ 0xB4A6, 0xB4A6, 0xB4A6 }, +{ 0xB4A7, 0xB4A7, 0xB4A7 }, +{ 0xB4A8, 0xB4A8, 0xB4A8 }, +{ 0xB4A9, 0xB4A9, 0xB4A9 }, +{ 0xB4AA, 0xB4AA, 0xB4AA }, +{ 0xB4AB, 0xB4AB, 0xB4AB }, +{ 0xB4AC, 0xB4AC, 0xB4AC }, +{ 0xB4AD, 0xB4AD, 0xB4AD }, +{ 0xB4AE, 0xB4AE, 0xB4AE }, +{ 0xB4AF, 0xB4AF, 0xB4AF }, +{ 0xB4B0, 0xB4B0, 0xB4B0 }, +{ 0xB4B1, 0xB4B1, 0xB4B1 }, +{ 0xB4B2, 0xB4B2, 0xB4B2 }, +{ 0xB4B3, 0xB4B3, 0xB4B3 }, +{ 0xB4B4, 0xB4B4, 0xB4B4 }, +{ 0xB4B5, 0xB4B5, 0xB4B5 }, +{ 0xB4B6, 0xB4B6, 0xB4B6 }, +{ 0xB4B7, 0xB4B7, 0xB4B7 }, +{ 0xB4B8, 0xB4B8, 0xB4B8 }, +{ 0xB4B9, 0xB4B9, 0xB4B9 }, +{ 0xB4BA, 0xB4BA, 0xB4BA }, +{ 0xB4BB, 0xB4BB, 0xB4BB }, +{ 0xB4BC, 0xB4BC, 0xB4BC }, +{ 0xB4BD, 0xB4BD, 0xB4BD }, +{ 0xB4BE, 0xB4BE, 0xB4BE }, +{ 0xB4BF, 0xB4BF, 0xB4BF }, +{ 0xB4C0, 0xB4C0, 0xB4C0 }, +{ 0xB4C1, 0xB4C1, 0xB4C1 }, +{ 0xB4C2, 0xB4C2, 0xB4C2 }, +{ 0xB4C3, 0xB4C3, 0xB4C3 }, +{ 0xB4C4, 0xB4C4, 0xB4C4 }, +{ 0xB4C5, 0xB4C5, 0xB4C5 }, +{ 0xB4C6, 0xB4C6, 0xB4C6 }, +{ 0xB4C7, 0xB4C7, 0xB4C7 }, +{ 0xB4C8, 0xB4C8, 0xB4C8 }, +{ 0xB4C9, 0xB4C9, 0xB4C9 }, +{ 0xB4CA, 0xB4CA, 0xB4CA }, +{ 0xB4CB, 0xB4CB, 0xB4CB }, +{ 0xB4CC, 0xB4CC, 0xB4CC }, +{ 0xB4CD, 0xB4CD, 0xB4CD }, +{ 0xB4CE, 0xB4CE, 0xB4CE }, +{ 0xB4CF, 0xB4CF, 0xB4CF }, +{ 0xB4D0, 0xB4D0, 0xB4D0 }, +{ 0xB4D1, 0xB4D1, 0xB4D1 }, +{ 0xB4D2, 0xB4D2, 0xB4D2 }, +{ 0xB4D3, 0xB4D3, 0xB4D3 }, +{ 0xB4D4, 0xB4D4, 0xB4D4 }, +{ 0xB4D5, 0xB4D5, 0xB4D5 }, +{ 0xB4D6, 0xB4D6, 0xB4D6 }, +{ 0xB4D7, 0xB4D7, 0xB4D7 }, +{ 0xB4D8, 0xB4D8, 0xB4D8 }, +{ 0xB4D9, 0xB4D9, 0xB4D9 }, +{ 0xB4DA, 0xB4DA, 0xB4DA }, +{ 0xB4DB, 0xB4DB, 0xB4DB }, +{ 0xB4DC, 0xB4DC, 0xB4DC }, +{ 0xB4DD, 0xB4DD, 0xB4DD }, +{ 0xB4DE, 0xB4DE, 0xB4DE }, +{ 0xB4DF, 0xB4DF, 0xB4DF }, +{ 0xB4E0, 0xB4E0, 0xB4E0 }, +{ 0xB4E1, 0xB4E1, 0xB4E1 }, +{ 0xB4E2, 0xB4E2, 0xB4E2 }, +{ 0xB4E3, 0xB4E3, 0xB4E3 }, +{ 0xB4E4, 0xB4E4, 0xB4E4 }, +{ 0xB4E5, 0xB4E5, 0xB4E5 }, +{ 0xB4E6, 0xB4E6, 0xB4E6 }, +{ 0xB4E7, 0xB4E7, 0xB4E7 }, +{ 0xB4E8, 0xB4E8, 0xB4E8 }, +{ 0xB4E9, 0xB4E9, 0xB4E9 }, +{ 0xB4EA, 0xB4EA, 0xB4EA }, +{ 0xB4EB, 0xB4EB, 0xB4EB }, +{ 0xB4EC, 0xB4EC, 0xB4EC }, +{ 0xB4ED, 0xB4ED, 0xB4ED }, +{ 0xB4EE, 0xB4EE, 0xB4EE }, +{ 0xB4EF, 0xB4EF, 0xB4EF }, +{ 0xB4F0, 0xB4F0, 0xB4F0 }, +{ 0xB4F1, 0xB4F1, 0xB4F1 }, +{ 0xB4F2, 0xB4F2, 0xB4F2 }, +{ 0xB4F3, 0xB4F3, 0xB4F3 }, +{ 0xB4F4, 0xB4F4, 0xB4F4 }, +{ 0xB4F5, 0xB4F5, 0xB4F5 }, +{ 0xB4F6, 0xB4F6, 0xB4F6 }, +{ 0xB4F7, 0xB4F7, 0xB4F7 }, +{ 0xB4F8, 0xB4F8, 0xB4F8 }, +{ 0xB4F9, 0xB4F9, 0xB4F9 }, +{ 0xB4FA, 0xB4FA, 0xB4FA }, +{ 0xB4FB, 0xB4FB, 0xB4FB }, +{ 0xB4FC, 0xB4FC, 0xB4FC }, +{ 0xB4FD, 0xB4FD, 0xB4FD }, +{ 0xB4FE, 0xB4FE, 0xB4FE }, +{ 0xB4FF, 0xB4FF, 0xB4FF }, +{ 0xB500, 0xB500, 0xB500 }, +{ 0xB501, 0xB501, 0xB501 }, +{ 0xB502, 0xB502, 0xB502 }, +{ 0xB503, 0xB503, 0xB503 }, +{ 0xB504, 0xB504, 0xB504 }, +{ 0xB505, 0xB505, 0xB505 }, +{ 0xB506, 0xB506, 0xB506 }, +{ 0xB507, 0xB507, 0xB507 }, +{ 0xB508, 0xB508, 0xB508 }, +{ 0xB509, 0xB509, 0xB509 }, +{ 0xB50A, 0xB50A, 0xB50A }, +{ 0xB50B, 0xB50B, 0xB50B }, +{ 0xB50C, 0xB50C, 0xB50C }, +{ 0xB50D, 0xB50D, 0xB50D }, +{ 0xB50E, 0xB50E, 0xB50E }, +{ 0xB50F, 0xB50F, 0xB50F }, +{ 0xB510, 0xB510, 0xB510 }, +{ 0xB511, 0xB511, 0xB511 }, +{ 0xB512, 0xB512, 0xB512 }, +{ 0xB513, 0xB513, 0xB513 }, +{ 0xB514, 0xB514, 0xB514 }, +{ 0xB515, 0xB515, 0xB515 }, +{ 0xB516, 0xB516, 0xB516 }, +{ 0xB517, 0xB517, 0xB517 }, +{ 0xB518, 0xB518, 0xB518 }, +{ 0xB519, 0xB519, 0xB519 }, +{ 0xB51A, 0xB51A, 0xB51A }, +{ 0xB51B, 0xB51B, 0xB51B }, +{ 0xB51C, 0xB51C, 0xB51C }, +{ 0xB51D, 0xB51D, 0xB51D }, +{ 0xB51E, 0xB51E, 0xB51E }, +{ 0xB51F, 0xB51F, 0xB51F }, +{ 0xB520, 0xB520, 0xB520 }, +{ 0xB521, 0xB521, 0xB521 }, +{ 0xB522, 0xB522, 0xB522 }, +{ 0xB523, 0xB523, 0xB523 }, +{ 0xB524, 0xB524, 0xB524 }, +{ 0xB525, 0xB525, 0xB525 }, +{ 0xB526, 0xB526, 0xB526 }, +{ 0xB527, 0xB527, 0xB527 }, +{ 0xB528, 0xB528, 0xB528 }, +{ 0xB529, 0xB529, 0xB529 }, +{ 0xB52A, 0xB52A, 0xB52A }, +{ 0xB52B, 0xB52B, 0xB52B }, +{ 0xB52C, 0xB52C, 0xB52C }, +{ 0xB52D, 0xB52D, 0xB52D }, +{ 0xB52E, 0xB52E, 0xB52E }, +{ 0xB52F, 0xB52F, 0xB52F }, +{ 0xB530, 0xB530, 0xB530 }, +{ 0xB531, 0xB531, 0xB531 }, +{ 0xB532, 0xB532, 0xB532 }, +{ 0xB533, 0xB533, 0xB533 }, +{ 0xB534, 0xB534, 0xB534 }, +{ 0xB535, 0xB535, 0xB535 }, +{ 0xB536, 0xB536, 0xB536 }, +{ 0xB537, 0xB537, 0xB537 }, +{ 0xB538, 0xB538, 0xB538 }, +{ 0xB539, 0xB539, 0xB539 }, +{ 0xB53A, 0xB53A, 0xB53A }, +{ 0xB53B, 0xB53B, 0xB53B }, +{ 0xB53C, 0xB53C, 0xB53C }, +{ 0xB53D, 0xB53D, 0xB53D }, +{ 0xB53E, 0xB53E, 0xB53E }, +{ 0xB53F, 0xB53F, 0xB53F }, +{ 0xB540, 0xB540, 0xB540 }, +{ 0xB541, 0xB541, 0xB541 }, +{ 0xB542, 0xB542, 0xB542 }, +{ 0xB543, 0xB543, 0xB543 }, +{ 0xB544, 0xB544, 0xB544 }, +{ 0xB545, 0xB545, 0xB545 }, +{ 0xB546, 0xB546, 0xB546 }, +{ 0xB547, 0xB547, 0xB547 }, +{ 0xB548, 0xB548, 0xB548 }, +{ 0xB549, 0xB549, 0xB549 }, +{ 0xB54A, 0xB54A, 0xB54A }, +{ 0xB54B, 0xB54B, 0xB54B }, +{ 0xB54C, 0xB54C, 0xB54C }, +{ 0xB54D, 0xB54D, 0xB54D }, +{ 0xB54E, 0xB54E, 0xB54E }, +{ 0xB54F, 0xB54F, 0xB54F }, +{ 0xB550, 0xB550, 0xB550 }, +{ 0xB551, 0xB551, 0xB551 }, +{ 0xB552, 0xB552, 0xB552 }, +{ 0xB553, 0xB553, 0xB553 }, +{ 0xB554, 0xB554, 0xB554 }, +{ 0xB555, 0xB555, 0xB555 }, +{ 0xB556, 0xB556, 0xB556 }, +{ 0xB557, 0xB557, 0xB557 }, +{ 0xB558, 0xB558, 0xB558 }, +{ 0xB559, 0xB559, 0xB559 }, +{ 0xB55A, 0xB55A, 0xB55A }, +{ 0xB55B, 0xB55B, 0xB55B }, +{ 0xB55C, 0xB55C, 0xB55C }, +{ 0xB55D, 0xB55D, 0xB55D }, +{ 0xB55E, 0xB55E, 0xB55E }, +{ 0xB55F, 0xB55F, 0xB55F }, +{ 0xB560, 0xB560, 0xB560 }, +{ 0xB561, 0xB561, 0xB561 }, +{ 0xB562, 0xB562, 0xB562 }, +{ 0xB563, 0xB563, 0xB563 }, +{ 0xB564, 0xB564, 0xB564 }, +{ 0xB565, 0xB565, 0xB565 }, +{ 0xB566, 0xB566, 0xB566 }, +{ 0xB567, 0xB567, 0xB567 }, +{ 0xB568, 0xB568, 0xB568 }, +{ 0xB569, 0xB569, 0xB569 }, +{ 0xB56A, 0xB56A, 0xB56A }, +{ 0xB56B, 0xB56B, 0xB56B }, +{ 0xB56C, 0xB56C, 0xB56C }, +{ 0xB56D, 0xB56D, 0xB56D }, +{ 0xB56E, 0xB56E, 0xB56E }, +{ 0xB56F, 0xB56F, 0xB56F }, +{ 0xB570, 0xB570, 0xB570 }, +{ 0xB571, 0xB571, 0xB571 }, +{ 0xB572, 0xB572, 0xB572 }, +{ 0xB573, 0xB573, 0xB573 }, +{ 0xB574, 0xB574, 0xB574 }, +{ 0xB575, 0xB575, 0xB575 }, +{ 0xB576, 0xB576, 0xB576 }, +{ 0xB577, 0xB577, 0xB577 }, +{ 0xB578, 0xB578, 0xB578 }, +{ 0xB579, 0xB579, 0xB579 }, +{ 0xB57A, 0xB57A, 0xB57A }, +{ 0xB57B, 0xB57B, 0xB57B }, +{ 0xB57C, 0xB57C, 0xB57C }, +{ 0xB57D, 0xB57D, 0xB57D }, +{ 0xB57E, 0xB57E, 0xB57E }, +{ 0xB57F, 0xB57F, 0xB57F }, +{ 0xB580, 0xB580, 0xB580 }, +{ 0xB581, 0xB581, 0xB581 }, +{ 0xB582, 0xB582, 0xB582 }, +{ 0xB583, 0xB583, 0xB583 }, +{ 0xB584, 0xB584, 0xB584 }, +{ 0xB585, 0xB585, 0xB585 }, +{ 0xB586, 0xB586, 0xB586 }, +{ 0xB587, 0xB587, 0xB587 }, +{ 0xB588, 0xB588, 0xB588 }, +{ 0xB589, 0xB589, 0xB589 }, +{ 0xB58A, 0xB58A, 0xB58A }, +{ 0xB58B, 0xB58B, 0xB58B }, +{ 0xB58C, 0xB58C, 0xB58C }, +{ 0xB58D, 0xB58D, 0xB58D }, +{ 0xB58E, 0xB58E, 0xB58E }, +{ 0xB58F, 0xB58F, 0xB58F }, +{ 0xB590, 0xB590, 0xB590 }, +{ 0xB591, 0xB591, 0xB591 }, +{ 0xB592, 0xB592, 0xB592 }, +{ 0xB593, 0xB593, 0xB593 }, +{ 0xB594, 0xB594, 0xB594 }, +{ 0xB595, 0xB595, 0xB595 }, +{ 0xB596, 0xB596, 0xB596 }, +{ 0xB597, 0xB597, 0xB597 }, +{ 0xB598, 0xB598, 0xB598 }, +{ 0xB599, 0xB599, 0xB599 }, +{ 0xB59A, 0xB59A, 0xB59A }, +{ 0xB59B, 0xB59B, 0xB59B }, +{ 0xB59C, 0xB59C, 0xB59C }, +{ 0xB59D, 0xB59D, 0xB59D }, +{ 0xB59E, 0xB59E, 0xB59E }, +{ 0xB59F, 0xB59F, 0xB59F }, +{ 0xB5A0, 0xB5A0, 0xB5A0 }, +{ 0xB5A1, 0xB5A1, 0xB5A1 }, +{ 0xB5A2, 0xB5A2, 0xB5A2 }, +{ 0xB5A3, 0xB5A3, 0xB5A3 }, +{ 0xB5A4, 0xB5A4, 0xB5A4 }, +{ 0xB5A5, 0xB5A5, 0xB5A5 }, +{ 0xB5A6, 0xB5A6, 0xB5A6 }, +{ 0xB5A7, 0xB5A7, 0xB5A7 }, +{ 0xB5A8, 0xB5A8, 0xB5A8 }, +{ 0xB5A9, 0xB5A9, 0xB5A9 }, +{ 0xB5AA, 0xB5AA, 0xB5AA }, +{ 0xB5AB, 0xB5AB, 0xB5AB }, +{ 0xB5AC, 0xB5AC, 0xB5AC }, +{ 0xB5AD, 0xB5AD, 0xB5AD }, +{ 0xB5AE, 0xB5AE, 0xB5AE }, +{ 0xB5AF, 0xB5AF, 0xB5AF }, +{ 0xB5B0, 0xB5B0, 0xB5B0 }, +{ 0xB5B1, 0xB5B1, 0xB5B1 }, +{ 0xB5B2, 0xB5B2, 0xB5B2 }, +{ 0xB5B3, 0xB5B3, 0xB5B3 }, +{ 0xB5B4, 0xB5B4, 0xB5B4 }, +{ 0xB5B5, 0xB5B5, 0xB5B5 }, +{ 0xB5B6, 0xB5B6, 0xB5B6 }, +{ 0xB5B7, 0xB5B7, 0xB5B7 }, +{ 0xB5B8, 0xB5B8, 0xB5B8 }, +{ 0xB5B9, 0xB5B9, 0xB5B9 }, +{ 0xB5BA, 0xB5BA, 0xB5BA }, +{ 0xB5BB, 0xB5BB, 0xB5BB }, +{ 0xB5BC, 0xB5BC, 0xB5BC }, +{ 0xB5BD, 0xB5BD, 0xB5BD }, +{ 0xB5BE, 0xB5BE, 0xB5BE }, +{ 0xB5BF, 0xB5BF, 0xB5BF }, +{ 0xB5C0, 0xB5C0, 0xB5C0 }, +{ 0xB5C1, 0xB5C1, 0xB5C1 }, +{ 0xB5C2, 0xB5C2, 0xB5C2 }, +{ 0xB5C3, 0xB5C3, 0xB5C3 }, +{ 0xB5C4, 0xB5C4, 0xB5C4 }, +{ 0xB5C5, 0xB5C5, 0xB5C5 }, +{ 0xB5C6, 0xB5C6, 0xB5C6 }, +{ 0xB5C7, 0xB5C7, 0xB5C7 }, +{ 0xB5C8, 0xB5C8, 0xB5C8 }, +{ 0xB5C9, 0xB5C9, 0xB5C9 }, +{ 0xB5CA, 0xB5CA, 0xB5CA }, +{ 0xB5CB, 0xB5CB, 0xB5CB }, +{ 0xB5CC, 0xB5CC, 0xB5CC }, +{ 0xB5CD, 0xB5CD, 0xB5CD }, +{ 0xB5CE, 0xB5CE, 0xB5CE }, +{ 0xB5CF, 0xB5CF, 0xB5CF }, +{ 0xB5D0, 0xB5D0, 0xB5D0 }, +{ 0xB5D1, 0xB5D1, 0xB5D1 }, +{ 0xB5D2, 0xB5D2, 0xB5D2 }, +{ 0xB5D3, 0xB5D3, 0xB5D3 }, +{ 0xB5D4, 0xB5D4, 0xB5D4 }, +{ 0xB5D5, 0xB5D5, 0xB5D5 }, +{ 0xB5D6, 0xB5D6, 0xB5D6 }, +{ 0xB5D7, 0xB5D7, 0xB5D7 }, +{ 0xB5D8, 0xB5D8, 0xB5D8 }, +{ 0xB5D9, 0xB5D9, 0xB5D9 }, +{ 0xB5DA, 0xB5DA, 0xB5DA }, +{ 0xB5DB, 0xB5DB, 0xB5DB }, +{ 0xB5DC, 0xB5DC, 0xB5DC }, +{ 0xB5DD, 0xB5DD, 0xB5DD }, +{ 0xB5DE, 0xB5DE, 0xB5DE }, +{ 0xB5DF, 0xB5DF, 0xB5DF }, +{ 0xB5E0, 0xB5E0, 0xB5E0 }, +{ 0xB5E1, 0xB5E1, 0xB5E1 }, +{ 0xB5E2, 0xB5E2, 0xB5E2 }, +{ 0xB5E3, 0xB5E3, 0xB5E3 }, +{ 0xB5E4, 0xB5E4, 0xB5E4 }, +{ 0xB5E5, 0xB5E5, 0xB5E5 }, +{ 0xB5E6, 0xB5E6, 0xB5E6 }, +{ 0xB5E7, 0xB5E7, 0xB5E7 }, +{ 0xB5E8, 0xB5E8, 0xB5E8 }, +{ 0xB5E9, 0xB5E9, 0xB5E9 }, +{ 0xB5EA, 0xB5EA, 0xB5EA }, +{ 0xB5EB, 0xB5EB, 0xB5EB }, +{ 0xB5EC, 0xB5EC, 0xB5EC }, +{ 0xB5ED, 0xB5ED, 0xB5ED }, +{ 0xB5EE, 0xB5EE, 0xB5EE }, +{ 0xB5EF, 0xB5EF, 0xB5EF }, +{ 0xB5F0, 0xB5F0, 0xB5F0 }, +{ 0xB5F1, 0xB5F1, 0xB5F1 }, +{ 0xB5F2, 0xB5F2, 0xB5F2 }, +{ 0xB5F3, 0xB5F3, 0xB5F3 }, +{ 0xB5F4, 0xB5F4, 0xB5F4 }, +{ 0xB5F5, 0xB5F5, 0xB5F5 }, +{ 0xB5F6, 0xB5F6, 0xB5F6 }, +{ 0xB5F7, 0xB5F7, 0xB5F7 }, +{ 0xB5F8, 0xB5F8, 0xB5F8 }, +{ 0xB5F9, 0xB5F9, 0xB5F9 }, +{ 0xB5FA, 0xB5FA, 0xB5FA }, +{ 0xB5FB, 0xB5FB, 0xB5FB }, +{ 0xB5FC, 0xB5FC, 0xB5FC }, +{ 0xB5FD, 0xB5FD, 0xB5FD }, +{ 0xB5FE, 0xB5FE, 0xB5FE }, +{ 0xB5FF, 0xB5FF, 0xB5FF }, +{ 0xB600, 0xB600, 0xB600 }, +{ 0xB601, 0xB601, 0xB601 }, +{ 0xB602, 0xB602, 0xB602 }, +{ 0xB603, 0xB603, 0xB603 }, +{ 0xB604, 0xB604, 0xB604 }, +{ 0xB605, 0xB605, 0xB605 }, +{ 0xB606, 0xB606, 0xB606 }, +{ 0xB607, 0xB607, 0xB607 }, +{ 0xB608, 0xB608, 0xB608 }, +{ 0xB609, 0xB609, 0xB609 }, +{ 0xB60A, 0xB60A, 0xB60A }, +{ 0xB60B, 0xB60B, 0xB60B }, +{ 0xB60C, 0xB60C, 0xB60C }, +{ 0xB60D, 0xB60D, 0xB60D }, +{ 0xB60E, 0xB60E, 0xB60E }, +{ 0xB60F, 0xB60F, 0xB60F }, +{ 0xB610, 0xB610, 0xB610 }, +{ 0xB611, 0xB611, 0xB611 }, +{ 0xB612, 0xB612, 0xB612 }, +{ 0xB613, 0xB613, 0xB613 }, +{ 0xB614, 0xB614, 0xB614 }, +{ 0xB615, 0xB615, 0xB615 }, +{ 0xB616, 0xB616, 0xB616 }, +{ 0xB617, 0xB617, 0xB617 }, +{ 0xB618, 0xB618, 0xB618 }, +{ 0xB619, 0xB619, 0xB619 }, +{ 0xB61A, 0xB61A, 0xB61A }, +{ 0xB61B, 0xB61B, 0xB61B }, +{ 0xB61C, 0xB61C, 0xB61C }, +{ 0xB61D, 0xB61D, 0xB61D }, +{ 0xB61E, 0xB61E, 0xB61E }, +{ 0xB61F, 0xB61F, 0xB61F }, +{ 0xB620, 0xB620, 0xB620 }, +{ 0xB621, 0xB621, 0xB621 }, +{ 0xB622, 0xB622, 0xB622 }, +{ 0xB623, 0xB623, 0xB623 }, +{ 0xB624, 0xB624, 0xB624 }, +{ 0xB625, 0xB625, 0xB625 }, +{ 0xB626, 0xB626, 0xB626 }, +{ 0xB627, 0xB627, 0xB627 }, +{ 0xB628, 0xB628, 0xB628 }, +{ 0xB629, 0xB629, 0xB629 }, +{ 0xB62A, 0xB62A, 0xB62A }, +{ 0xB62B, 0xB62B, 0xB62B }, +{ 0xB62C, 0xB62C, 0xB62C }, +{ 0xB62D, 0xB62D, 0xB62D }, +{ 0xB62E, 0xB62E, 0xB62E }, +{ 0xB62F, 0xB62F, 0xB62F }, +{ 0xB630, 0xB630, 0xB630 }, +{ 0xB631, 0xB631, 0xB631 }, +{ 0xB632, 0xB632, 0xB632 }, +{ 0xB633, 0xB633, 0xB633 }, +{ 0xB634, 0xB634, 0xB634 }, +{ 0xB635, 0xB635, 0xB635 }, +{ 0xB636, 0xB636, 0xB636 }, +{ 0xB637, 0xB637, 0xB637 }, +{ 0xB638, 0xB638, 0xB638 }, +{ 0xB639, 0xB639, 0xB639 }, +{ 0xB63A, 0xB63A, 0xB63A }, +{ 0xB63B, 0xB63B, 0xB63B }, +{ 0xB63C, 0xB63C, 0xB63C }, +{ 0xB63D, 0xB63D, 0xB63D }, +{ 0xB63E, 0xB63E, 0xB63E }, +{ 0xB63F, 0xB63F, 0xB63F }, +{ 0xB640, 0xB640, 0xB640 }, +{ 0xB641, 0xB641, 0xB641 }, +{ 0xB642, 0xB642, 0xB642 }, +{ 0xB643, 0xB643, 0xB643 }, +{ 0xB644, 0xB644, 0xB644 }, +{ 0xB645, 0xB645, 0xB645 }, +{ 0xB646, 0xB646, 0xB646 }, +{ 0xB647, 0xB647, 0xB647 }, +{ 0xB648, 0xB648, 0xB648 }, +{ 0xB649, 0xB649, 0xB649 }, +{ 0xB64A, 0xB64A, 0xB64A }, +{ 0xB64B, 0xB64B, 0xB64B }, +{ 0xB64C, 0xB64C, 0xB64C }, +{ 0xB64D, 0xB64D, 0xB64D }, +{ 0xB64E, 0xB64E, 0xB64E }, +{ 0xB64F, 0xB64F, 0xB64F }, +{ 0xB650, 0xB650, 0xB650 }, +{ 0xB651, 0xB651, 0xB651 }, +{ 0xB652, 0xB652, 0xB652 }, +{ 0xB653, 0xB653, 0xB653 }, +{ 0xB654, 0xB654, 0xB654 }, +{ 0xB655, 0xB655, 0xB655 }, +{ 0xB656, 0xB656, 0xB656 }, +{ 0xB657, 0xB657, 0xB657 }, +{ 0xB658, 0xB658, 0xB658 }, +{ 0xB659, 0xB659, 0xB659 }, +{ 0xB65A, 0xB65A, 0xB65A }, +{ 0xB65B, 0xB65B, 0xB65B }, +{ 0xB65C, 0xB65C, 0xB65C }, +{ 0xB65D, 0xB65D, 0xB65D }, +{ 0xB65E, 0xB65E, 0xB65E }, +{ 0xB65F, 0xB65F, 0xB65F }, +{ 0xB660, 0xB660, 0xB660 }, +{ 0xB661, 0xB661, 0xB661 }, +{ 0xB662, 0xB662, 0xB662 }, +{ 0xB663, 0xB663, 0xB663 }, +{ 0xB664, 0xB664, 0xB664 }, +{ 0xB665, 0xB665, 0xB665 }, +{ 0xB666, 0xB666, 0xB666 }, +{ 0xB667, 0xB667, 0xB667 }, +{ 0xB668, 0xB668, 0xB668 }, +{ 0xB669, 0xB669, 0xB669 }, +{ 0xB66A, 0xB66A, 0xB66A }, +{ 0xB66B, 0xB66B, 0xB66B }, +{ 0xB66C, 0xB66C, 0xB66C }, +{ 0xB66D, 0xB66D, 0xB66D }, +{ 0xB66E, 0xB66E, 0xB66E }, +{ 0xB66F, 0xB66F, 0xB66F }, +{ 0xB670, 0xB670, 0xB670 }, +{ 0xB671, 0xB671, 0xB671 }, +{ 0xB672, 0xB672, 0xB672 }, +{ 0xB673, 0xB673, 0xB673 }, +{ 0xB674, 0xB674, 0xB674 }, +{ 0xB675, 0xB675, 0xB675 }, +{ 0xB676, 0xB676, 0xB676 }, +{ 0xB677, 0xB677, 0xB677 }, +{ 0xB678, 0xB678, 0xB678 }, +{ 0xB679, 0xB679, 0xB679 }, +{ 0xB67A, 0xB67A, 0xB67A }, +{ 0xB67B, 0xB67B, 0xB67B }, +{ 0xB67C, 0xB67C, 0xB67C }, +{ 0xB67D, 0xB67D, 0xB67D }, +{ 0xB67E, 0xB67E, 0xB67E }, +{ 0xB67F, 0xB67F, 0xB67F }, +{ 0xB680, 0xB680, 0xB680 }, +{ 0xB681, 0xB681, 0xB681 }, +{ 0xB682, 0xB682, 0xB682 }, +{ 0xB683, 0xB683, 0xB683 }, +{ 0xB684, 0xB684, 0xB684 }, +{ 0xB685, 0xB685, 0xB685 }, +{ 0xB686, 0xB686, 0xB686 }, +{ 0xB687, 0xB687, 0xB687 }, +{ 0xB688, 0xB688, 0xB688 }, +{ 0xB689, 0xB689, 0xB689 }, +{ 0xB68A, 0xB68A, 0xB68A }, +{ 0xB68B, 0xB68B, 0xB68B }, +{ 0xB68C, 0xB68C, 0xB68C }, +{ 0xB68D, 0xB68D, 0xB68D }, +{ 0xB68E, 0xB68E, 0xB68E }, +{ 0xB68F, 0xB68F, 0xB68F }, +{ 0xB690, 0xB690, 0xB690 }, +{ 0xB691, 0xB691, 0xB691 }, +{ 0xB692, 0xB692, 0xB692 }, +{ 0xB693, 0xB693, 0xB693 }, +{ 0xB694, 0xB694, 0xB694 }, +{ 0xB695, 0xB695, 0xB695 }, +{ 0xB696, 0xB696, 0xB696 }, +{ 0xB697, 0xB697, 0xB697 }, +{ 0xB698, 0xB698, 0xB698 }, +{ 0xB699, 0xB699, 0xB699 }, +{ 0xB69A, 0xB69A, 0xB69A }, +{ 0xB69B, 0xB69B, 0xB69B }, +{ 0xB69C, 0xB69C, 0xB69C }, +{ 0xB69D, 0xB69D, 0xB69D }, +{ 0xB69E, 0xB69E, 0xB69E }, +{ 0xB69F, 0xB69F, 0xB69F }, +{ 0xB6A0, 0xB6A0, 0xB6A0 }, +{ 0xB6A1, 0xB6A1, 0xB6A1 }, +{ 0xB6A2, 0xB6A2, 0xB6A2 }, +{ 0xB6A3, 0xB6A3, 0xB6A3 }, +{ 0xB6A4, 0xB6A4, 0xB6A4 }, +{ 0xB6A5, 0xB6A5, 0xB6A5 }, +{ 0xB6A6, 0xB6A6, 0xB6A6 }, +{ 0xB6A7, 0xB6A7, 0xB6A7 }, +{ 0xB6A8, 0xB6A8, 0xB6A8 }, +{ 0xB6A9, 0xB6A9, 0xB6A9 }, +{ 0xB6AA, 0xB6AA, 0xB6AA }, +{ 0xB6AB, 0xB6AB, 0xB6AB }, +{ 0xB6AC, 0xB6AC, 0xB6AC }, +{ 0xB6AD, 0xB6AD, 0xB6AD }, +{ 0xB6AE, 0xB6AE, 0xB6AE }, +{ 0xB6AF, 0xB6AF, 0xB6AF }, +{ 0xB6B0, 0xB6B0, 0xB6B0 }, +{ 0xB6B1, 0xB6B1, 0xB6B1 }, +{ 0xB6B2, 0xB6B2, 0xB6B2 }, +{ 0xB6B3, 0xB6B3, 0xB6B3 }, +{ 0xB6B4, 0xB6B4, 0xB6B4 }, +{ 0xB6B5, 0xB6B5, 0xB6B5 }, +{ 0xB6B6, 0xB6B6, 0xB6B6 }, +{ 0xB6B7, 0xB6B7, 0xB6B7 }, +{ 0xB6B8, 0xB6B8, 0xB6B8 }, +{ 0xB6B9, 0xB6B9, 0xB6B9 }, +{ 0xB6BA, 0xB6BA, 0xB6BA }, +{ 0xB6BB, 0xB6BB, 0xB6BB }, +{ 0xB6BC, 0xB6BC, 0xB6BC }, +{ 0xB6BD, 0xB6BD, 0xB6BD }, +{ 0xB6BE, 0xB6BE, 0xB6BE }, +{ 0xB6BF, 0xB6BF, 0xB6BF }, +{ 0xB6C0, 0xB6C0, 0xB6C0 }, +{ 0xB6C1, 0xB6C1, 0xB6C1 }, +{ 0xB6C2, 0xB6C2, 0xB6C2 }, +{ 0xB6C3, 0xB6C3, 0xB6C3 }, +{ 0xB6C4, 0xB6C4, 0xB6C4 }, +{ 0xB6C5, 0xB6C5, 0xB6C5 }, +{ 0xB6C6, 0xB6C6, 0xB6C6 }, +{ 0xB6C7, 0xB6C7, 0xB6C7 }, +{ 0xB6C8, 0xB6C8, 0xB6C8 }, +{ 0xB6C9, 0xB6C9, 0xB6C9 }, +{ 0xB6CA, 0xB6CA, 0xB6CA }, +{ 0xB6CB, 0xB6CB, 0xB6CB }, +{ 0xB6CC, 0xB6CC, 0xB6CC }, +{ 0xB6CD, 0xB6CD, 0xB6CD }, +{ 0xB6CE, 0xB6CE, 0xB6CE }, +{ 0xB6CF, 0xB6CF, 0xB6CF }, +{ 0xB6D0, 0xB6D0, 0xB6D0 }, +{ 0xB6D1, 0xB6D1, 0xB6D1 }, +{ 0xB6D2, 0xB6D2, 0xB6D2 }, +{ 0xB6D3, 0xB6D3, 0xB6D3 }, +{ 0xB6D4, 0xB6D4, 0xB6D4 }, +{ 0xB6D5, 0xB6D5, 0xB6D5 }, +{ 0xB6D6, 0xB6D6, 0xB6D6 }, +{ 0xB6D7, 0xB6D7, 0xB6D7 }, +{ 0xB6D8, 0xB6D8, 0xB6D8 }, +{ 0xB6D9, 0xB6D9, 0xB6D9 }, +{ 0xB6DA, 0xB6DA, 0xB6DA }, +{ 0xB6DB, 0xB6DB, 0xB6DB }, +{ 0xB6DC, 0xB6DC, 0xB6DC }, +{ 0xB6DD, 0xB6DD, 0xB6DD }, +{ 0xB6DE, 0xB6DE, 0xB6DE }, +{ 0xB6DF, 0xB6DF, 0xB6DF }, +{ 0xB6E0, 0xB6E0, 0xB6E0 }, +{ 0xB6E1, 0xB6E1, 0xB6E1 }, +{ 0xB6E2, 0xB6E2, 0xB6E2 }, +{ 0xB6E3, 0xB6E3, 0xB6E3 }, +{ 0xB6E4, 0xB6E4, 0xB6E4 }, +{ 0xB6E5, 0xB6E5, 0xB6E5 }, +{ 0xB6E6, 0xB6E6, 0xB6E6 }, +{ 0xB6E7, 0xB6E7, 0xB6E7 }, +{ 0xB6E8, 0xB6E8, 0xB6E8 }, +{ 0xB6E9, 0xB6E9, 0xB6E9 }, +{ 0xB6EA, 0xB6EA, 0xB6EA }, +{ 0xB6EB, 0xB6EB, 0xB6EB }, +{ 0xB6EC, 0xB6EC, 0xB6EC }, +{ 0xB6ED, 0xB6ED, 0xB6ED }, +{ 0xB6EE, 0xB6EE, 0xB6EE }, +{ 0xB6EF, 0xB6EF, 0xB6EF }, +{ 0xB6F0, 0xB6F0, 0xB6F0 }, +{ 0xB6F1, 0xB6F1, 0xB6F1 }, +{ 0xB6F2, 0xB6F2, 0xB6F2 }, +{ 0xB6F3, 0xB6F3, 0xB6F3 }, +{ 0xB6F4, 0xB6F4, 0xB6F4 }, +{ 0xB6F5, 0xB6F5, 0xB6F5 }, +{ 0xB6F6, 0xB6F6, 0xB6F6 }, +{ 0xB6F7, 0xB6F7, 0xB6F7 }, +{ 0xB6F8, 0xB6F8, 0xB6F8 }, +{ 0xB6F9, 0xB6F9, 0xB6F9 }, +{ 0xB6FA, 0xB6FA, 0xB6FA }, +{ 0xB6FB, 0xB6FB, 0xB6FB }, +{ 0xB6FC, 0xB6FC, 0xB6FC }, +{ 0xB6FD, 0xB6FD, 0xB6FD }, +{ 0xB6FE, 0xB6FE, 0xB6FE }, +{ 0xB6FF, 0xB6FF, 0xB6FF }, +{ 0xB700, 0xB700, 0xB700 }, +{ 0xB701, 0xB701, 0xB701 }, +{ 0xB702, 0xB702, 0xB702 }, +{ 0xB703, 0xB703, 0xB703 }, +{ 0xB704, 0xB704, 0xB704 }, +{ 0xB705, 0xB705, 0xB705 }, +{ 0xB706, 0xB706, 0xB706 }, +{ 0xB707, 0xB707, 0xB707 }, +{ 0xB708, 0xB708, 0xB708 }, +{ 0xB709, 0xB709, 0xB709 }, +{ 0xB70A, 0xB70A, 0xB70A }, +{ 0xB70B, 0xB70B, 0xB70B }, +{ 0xB70C, 0xB70C, 0xB70C }, +{ 0xB70D, 0xB70D, 0xB70D }, +{ 0xB70E, 0xB70E, 0xB70E }, +{ 0xB70F, 0xB70F, 0xB70F }, +{ 0xB710, 0xB710, 0xB710 }, +{ 0xB711, 0xB711, 0xB711 }, +{ 0xB712, 0xB712, 0xB712 }, +{ 0xB713, 0xB713, 0xB713 }, +{ 0xB714, 0xB714, 0xB714 }, +{ 0xB715, 0xB715, 0xB715 }, +{ 0xB716, 0xB716, 0xB716 }, +{ 0xB717, 0xB717, 0xB717 }, +{ 0xB718, 0xB718, 0xB718 }, +{ 0xB719, 0xB719, 0xB719 }, +{ 0xB71A, 0xB71A, 0xB71A }, +{ 0xB71B, 0xB71B, 0xB71B }, +{ 0xB71C, 0xB71C, 0xB71C }, +{ 0xB71D, 0xB71D, 0xB71D }, +{ 0xB71E, 0xB71E, 0xB71E }, +{ 0xB71F, 0xB71F, 0xB71F }, +{ 0xB720, 0xB720, 0xB720 }, +{ 0xB721, 0xB721, 0xB721 }, +{ 0xB722, 0xB722, 0xB722 }, +{ 0xB723, 0xB723, 0xB723 }, +{ 0xB724, 0xB724, 0xB724 }, +{ 0xB725, 0xB725, 0xB725 }, +{ 0xB726, 0xB726, 0xB726 }, +{ 0xB727, 0xB727, 0xB727 }, +{ 0xB728, 0xB728, 0xB728 }, +{ 0xB729, 0xB729, 0xB729 }, +{ 0xB72A, 0xB72A, 0xB72A }, +{ 0xB72B, 0xB72B, 0xB72B }, +{ 0xB72C, 0xB72C, 0xB72C }, +{ 0xB72D, 0xB72D, 0xB72D }, +{ 0xB72E, 0xB72E, 0xB72E }, +{ 0xB72F, 0xB72F, 0xB72F }, +{ 0xB730, 0xB730, 0xB730 }, +{ 0xB731, 0xB731, 0xB731 }, +{ 0xB732, 0xB732, 0xB732 }, +{ 0xB733, 0xB733, 0xB733 }, +{ 0xB734, 0xB734, 0xB734 }, +{ 0xB735, 0xB735, 0xB735 }, +{ 0xB736, 0xB736, 0xB736 }, +{ 0xB737, 0xB737, 0xB737 }, +{ 0xB738, 0xB738, 0xB738 }, +{ 0xB739, 0xB739, 0xB739 }, +{ 0xB73A, 0xB73A, 0xB73A }, +{ 0xB73B, 0xB73B, 0xB73B }, +{ 0xB73C, 0xB73C, 0xB73C }, +{ 0xB73D, 0xB73D, 0xB73D }, +{ 0xB73E, 0xB73E, 0xB73E }, +{ 0xB73F, 0xB73F, 0xB73F }, +{ 0xB740, 0xB740, 0xB740 }, +{ 0xB741, 0xB741, 0xB741 }, +{ 0xB742, 0xB742, 0xB742 }, +{ 0xB743, 0xB743, 0xB743 }, +{ 0xB744, 0xB744, 0xB744 }, +{ 0xB745, 0xB745, 0xB745 }, +{ 0xB746, 0xB746, 0xB746 }, +{ 0xB747, 0xB747, 0xB747 }, +{ 0xB748, 0xB748, 0xB748 }, +{ 0xB749, 0xB749, 0xB749 }, +{ 0xB74A, 0xB74A, 0xB74A }, +{ 0xB74B, 0xB74B, 0xB74B }, +{ 0xB74C, 0xB74C, 0xB74C }, +{ 0xB74D, 0xB74D, 0xB74D }, +{ 0xB74E, 0xB74E, 0xB74E }, +{ 0xB74F, 0xB74F, 0xB74F }, +{ 0xB750, 0xB750, 0xB750 }, +{ 0xB751, 0xB751, 0xB751 }, +{ 0xB752, 0xB752, 0xB752 }, +{ 0xB753, 0xB753, 0xB753 }, +{ 0xB754, 0xB754, 0xB754 }, +{ 0xB755, 0xB755, 0xB755 }, +{ 0xB756, 0xB756, 0xB756 }, +{ 0xB757, 0xB757, 0xB757 }, +{ 0xB758, 0xB758, 0xB758 }, +{ 0xB759, 0xB759, 0xB759 }, +{ 0xB75A, 0xB75A, 0xB75A }, +{ 0xB75B, 0xB75B, 0xB75B }, +{ 0xB75C, 0xB75C, 0xB75C }, +{ 0xB75D, 0xB75D, 0xB75D }, +{ 0xB75E, 0xB75E, 0xB75E }, +{ 0xB75F, 0xB75F, 0xB75F }, +{ 0xB760, 0xB760, 0xB760 }, +{ 0xB761, 0xB761, 0xB761 }, +{ 0xB762, 0xB762, 0xB762 }, +{ 0xB763, 0xB763, 0xB763 }, +{ 0xB764, 0xB764, 0xB764 }, +{ 0xB765, 0xB765, 0xB765 }, +{ 0xB766, 0xB766, 0xB766 }, +{ 0xB767, 0xB767, 0xB767 }, +{ 0xB768, 0xB768, 0xB768 }, +{ 0xB769, 0xB769, 0xB769 }, +{ 0xB76A, 0xB76A, 0xB76A }, +{ 0xB76B, 0xB76B, 0xB76B }, +{ 0xB76C, 0xB76C, 0xB76C }, +{ 0xB76D, 0xB76D, 0xB76D }, +{ 0xB76E, 0xB76E, 0xB76E }, +{ 0xB76F, 0xB76F, 0xB76F }, +{ 0xB770, 0xB770, 0xB770 }, +{ 0xB771, 0xB771, 0xB771 }, +{ 0xB772, 0xB772, 0xB772 }, +{ 0xB773, 0xB773, 0xB773 }, +{ 0xB774, 0xB774, 0xB774 }, +{ 0xB775, 0xB775, 0xB775 }, +{ 0xB776, 0xB776, 0xB776 }, +{ 0xB777, 0xB777, 0xB777 }, +{ 0xB778, 0xB778, 0xB778 }, +{ 0xB779, 0xB779, 0xB779 }, +{ 0xB77A, 0xB77A, 0xB77A }, +{ 0xB77B, 0xB77B, 0xB77B }, +{ 0xB77C, 0xB77C, 0xB77C }, +{ 0xB77D, 0xB77D, 0xB77D }, +{ 0xB77E, 0xB77E, 0xB77E }, +{ 0xB77F, 0xB77F, 0xB77F }, +{ 0xB780, 0xB780, 0xB780 }, +{ 0xB781, 0xB781, 0xB781 }, +{ 0xB782, 0xB782, 0xB782 }, +{ 0xB783, 0xB783, 0xB783 }, +{ 0xB784, 0xB784, 0xB784 }, +{ 0xB785, 0xB785, 0xB785 }, +{ 0xB786, 0xB786, 0xB786 }, +{ 0xB787, 0xB787, 0xB787 }, +{ 0xB788, 0xB788, 0xB788 }, +{ 0xB789, 0xB789, 0xB789 }, +{ 0xB78A, 0xB78A, 0xB78A }, +{ 0xB78B, 0xB78B, 0xB78B }, +{ 0xB78C, 0xB78C, 0xB78C }, +{ 0xB78D, 0xB78D, 0xB78D }, +{ 0xB78E, 0xB78E, 0xB78E }, +{ 0xB78F, 0xB78F, 0xB78F }, +{ 0xB790, 0xB790, 0xB790 }, +{ 0xB791, 0xB791, 0xB791 }, +{ 0xB792, 0xB792, 0xB792 }, +{ 0xB793, 0xB793, 0xB793 }, +{ 0xB794, 0xB794, 0xB794 }, +{ 0xB795, 0xB795, 0xB795 }, +{ 0xB796, 0xB796, 0xB796 }, +{ 0xB797, 0xB797, 0xB797 }, +{ 0xB798, 0xB798, 0xB798 }, +{ 0xB799, 0xB799, 0xB799 }, +{ 0xB79A, 0xB79A, 0xB79A }, +{ 0xB79B, 0xB79B, 0xB79B }, +{ 0xB79C, 0xB79C, 0xB79C }, +{ 0xB79D, 0xB79D, 0xB79D }, +{ 0xB79E, 0xB79E, 0xB79E }, +{ 0xB79F, 0xB79F, 0xB79F }, +{ 0xB7A0, 0xB7A0, 0xB7A0 }, +{ 0xB7A1, 0xB7A1, 0xB7A1 }, +{ 0xB7A2, 0xB7A2, 0xB7A2 }, +{ 0xB7A3, 0xB7A3, 0xB7A3 }, +{ 0xB7A4, 0xB7A4, 0xB7A4 }, +{ 0xB7A5, 0xB7A5, 0xB7A5 }, +{ 0xB7A6, 0xB7A6, 0xB7A6 }, +{ 0xB7A7, 0xB7A7, 0xB7A7 }, +{ 0xB7A8, 0xB7A8, 0xB7A8 }, +{ 0xB7A9, 0xB7A9, 0xB7A9 }, +{ 0xB7AA, 0xB7AA, 0xB7AA }, +{ 0xB7AB, 0xB7AB, 0xB7AB }, +{ 0xB7AC, 0xB7AC, 0xB7AC }, +{ 0xB7AD, 0xB7AD, 0xB7AD }, +{ 0xB7AE, 0xB7AE, 0xB7AE }, +{ 0xB7AF, 0xB7AF, 0xB7AF }, +{ 0xB7B0, 0xB7B0, 0xB7B0 }, +{ 0xB7B1, 0xB7B1, 0xB7B1 }, +{ 0xB7B2, 0xB7B2, 0xB7B2 }, +{ 0xB7B3, 0xB7B3, 0xB7B3 }, +{ 0xB7B4, 0xB7B4, 0xB7B4 }, +{ 0xB7B5, 0xB7B5, 0xB7B5 }, +{ 0xB7B6, 0xB7B6, 0xB7B6 }, +{ 0xB7B7, 0xB7B7, 0xB7B7 }, +{ 0xB7B8, 0xB7B8, 0xB7B8 }, +{ 0xB7B9, 0xB7B9, 0xB7B9 }, +{ 0xB7BA, 0xB7BA, 0xB7BA }, +{ 0xB7BB, 0xB7BB, 0xB7BB }, +{ 0xB7BC, 0xB7BC, 0xB7BC }, +{ 0xB7BD, 0xB7BD, 0xB7BD }, +{ 0xB7BE, 0xB7BE, 0xB7BE }, +{ 0xB7BF, 0xB7BF, 0xB7BF }, +{ 0xB7C0, 0xB7C0, 0xB7C0 }, +{ 0xB7C1, 0xB7C1, 0xB7C1 }, +{ 0xB7C2, 0xB7C2, 0xB7C2 }, +{ 0xB7C3, 0xB7C3, 0xB7C3 }, +{ 0xB7C4, 0xB7C4, 0xB7C4 }, +{ 0xB7C5, 0xB7C5, 0xB7C5 }, +{ 0xB7C6, 0xB7C6, 0xB7C6 }, +{ 0xB7C7, 0xB7C7, 0xB7C7 }, +{ 0xB7C8, 0xB7C8, 0xB7C8 }, +{ 0xB7C9, 0xB7C9, 0xB7C9 }, +{ 0xB7CA, 0xB7CA, 0xB7CA }, +{ 0xB7CB, 0xB7CB, 0xB7CB }, +{ 0xB7CC, 0xB7CC, 0xB7CC }, +{ 0xB7CD, 0xB7CD, 0xB7CD }, +{ 0xB7CE, 0xB7CE, 0xB7CE }, +{ 0xB7CF, 0xB7CF, 0xB7CF }, +{ 0xB7D0, 0xB7D0, 0xB7D0 }, +{ 0xB7D1, 0xB7D1, 0xB7D1 }, +{ 0xB7D2, 0xB7D2, 0xB7D2 }, +{ 0xB7D3, 0xB7D3, 0xB7D3 }, +{ 0xB7D4, 0xB7D4, 0xB7D4 }, +{ 0xB7D5, 0xB7D5, 0xB7D5 }, +{ 0xB7D6, 0xB7D6, 0xB7D6 }, +{ 0xB7D7, 0xB7D7, 0xB7D7 }, +{ 0xB7D8, 0xB7D8, 0xB7D8 }, +{ 0xB7D9, 0xB7D9, 0xB7D9 }, +{ 0xB7DA, 0xB7DA, 0xB7DA }, +{ 0xB7DB, 0xB7DB, 0xB7DB }, +{ 0xB7DC, 0xB7DC, 0xB7DC }, +{ 0xB7DD, 0xB7DD, 0xB7DD }, +{ 0xB7DE, 0xB7DE, 0xB7DE }, +{ 0xB7DF, 0xB7DF, 0xB7DF }, +{ 0xB7E0, 0xB7E0, 0xB7E0 }, +{ 0xB7E1, 0xB7E1, 0xB7E1 }, +{ 0xB7E2, 0xB7E2, 0xB7E2 }, +{ 0xB7E3, 0xB7E3, 0xB7E3 }, +{ 0xB7E4, 0xB7E4, 0xB7E4 }, +{ 0xB7E5, 0xB7E5, 0xB7E5 }, +{ 0xB7E6, 0xB7E6, 0xB7E6 }, +{ 0xB7E7, 0xB7E7, 0xB7E7 }, +{ 0xB7E8, 0xB7E8, 0xB7E8 }, +{ 0xB7E9, 0xB7E9, 0xB7E9 }, +{ 0xB7EA, 0xB7EA, 0xB7EA }, +{ 0xB7EB, 0xB7EB, 0xB7EB }, +{ 0xB7EC, 0xB7EC, 0xB7EC }, +{ 0xB7ED, 0xB7ED, 0xB7ED }, +{ 0xB7EE, 0xB7EE, 0xB7EE }, +{ 0xB7EF, 0xB7EF, 0xB7EF }, +{ 0xB7F0, 0xB7F0, 0xB7F0 }, +{ 0xB7F1, 0xB7F1, 0xB7F1 }, +{ 0xB7F2, 0xB7F2, 0xB7F2 }, +{ 0xB7F3, 0xB7F3, 0xB7F3 }, +{ 0xB7F4, 0xB7F4, 0xB7F4 }, +{ 0xB7F5, 0xB7F5, 0xB7F5 }, +{ 0xB7F6, 0xB7F6, 0xB7F6 }, +{ 0xB7F7, 0xB7F7, 0xB7F7 }, +{ 0xB7F8, 0xB7F8, 0xB7F8 }, +{ 0xB7F9, 0xB7F9, 0xB7F9 }, +{ 0xB7FA, 0xB7FA, 0xB7FA }, +{ 0xB7FB, 0xB7FB, 0xB7FB }, +{ 0xB7FC, 0xB7FC, 0xB7FC }, +{ 0xB7FD, 0xB7FD, 0xB7FD }, +{ 0xB7FE, 0xB7FE, 0xB7FE }, +{ 0xB7FF, 0xB7FF, 0xB7FF }, +{ 0xB800, 0xB800, 0xB800 }, +{ 0xB801, 0xB801, 0xB801 }, +{ 0xB802, 0xB802, 0xB802 }, +{ 0xB803, 0xB803, 0xB803 }, +{ 0xB804, 0xB804, 0xB804 }, +{ 0xB805, 0xB805, 0xB805 }, +{ 0xB806, 0xB806, 0xB806 }, +{ 0xB807, 0xB807, 0xB807 }, +{ 0xB808, 0xB808, 0xB808 }, +{ 0xB809, 0xB809, 0xB809 }, +{ 0xB80A, 0xB80A, 0xB80A }, +{ 0xB80B, 0xB80B, 0xB80B }, +{ 0xB80C, 0xB80C, 0xB80C }, +{ 0xB80D, 0xB80D, 0xB80D }, +{ 0xB80E, 0xB80E, 0xB80E }, +{ 0xB80F, 0xB80F, 0xB80F }, +{ 0xB810, 0xB810, 0xB810 }, +{ 0xB811, 0xB811, 0xB811 }, +{ 0xB812, 0xB812, 0xB812 }, +{ 0xB813, 0xB813, 0xB813 }, +{ 0xB814, 0xB814, 0xB814 }, +{ 0xB815, 0xB815, 0xB815 }, +{ 0xB816, 0xB816, 0xB816 }, +{ 0xB817, 0xB817, 0xB817 }, +{ 0xB818, 0xB818, 0xB818 }, +{ 0xB819, 0xB819, 0xB819 }, +{ 0xB81A, 0xB81A, 0xB81A }, +{ 0xB81B, 0xB81B, 0xB81B }, +{ 0xB81C, 0xB81C, 0xB81C }, +{ 0xB81D, 0xB81D, 0xB81D }, +{ 0xB81E, 0xB81E, 0xB81E }, +{ 0xB81F, 0xB81F, 0xB81F }, +{ 0xB820, 0xB820, 0xB820 }, +{ 0xB821, 0xB821, 0xB821 }, +{ 0xB822, 0xB822, 0xB822 }, +{ 0xB823, 0xB823, 0xB823 }, +{ 0xB824, 0xB824, 0xB824 }, +{ 0xB825, 0xB825, 0xB825 }, +{ 0xB826, 0xB826, 0xB826 }, +{ 0xB827, 0xB827, 0xB827 }, +{ 0xB828, 0xB828, 0xB828 }, +{ 0xB829, 0xB829, 0xB829 }, +{ 0xB82A, 0xB82A, 0xB82A }, +{ 0xB82B, 0xB82B, 0xB82B }, +{ 0xB82C, 0xB82C, 0xB82C }, +{ 0xB82D, 0xB82D, 0xB82D }, +{ 0xB82E, 0xB82E, 0xB82E }, +{ 0xB82F, 0xB82F, 0xB82F }, +{ 0xB830, 0xB830, 0xB830 }, +{ 0xB831, 0xB831, 0xB831 }, +{ 0xB832, 0xB832, 0xB832 }, +{ 0xB833, 0xB833, 0xB833 }, +{ 0xB834, 0xB834, 0xB834 }, +{ 0xB835, 0xB835, 0xB835 }, +{ 0xB836, 0xB836, 0xB836 }, +{ 0xB837, 0xB837, 0xB837 }, +{ 0xB838, 0xB838, 0xB838 }, +{ 0xB839, 0xB839, 0xB839 }, +{ 0xB83A, 0xB83A, 0xB83A }, +{ 0xB83B, 0xB83B, 0xB83B }, +{ 0xB83C, 0xB83C, 0xB83C }, +{ 0xB83D, 0xB83D, 0xB83D }, +{ 0xB83E, 0xB83E, 0xB83E }, +{ 0xB83F, 0xB83F, 0xB83F }, +{ 0xB840, 0xB840, 0xB840 }, +{ 0xB841, 0xB841, 0xB841 }, +{ 0xB842, 0xB842, 0xB842 }, +{ 0xB843, 0xB843, 0xB843 }, +{ 0xB844, 0xB844, 0xB844 }, +{ 0xB845, 0xB845, 0xB845 }, +{ 0xB846, 0xB846, 0xB846 }, +{ 0xB847, 0xB847, 0xB847 }, +{ 0xB848, 0xB848, 0xB848 }, +{ 0xB849, 0xB849, 0xB849 }, +{ 0xB84A, 0xB84A, 0xB84A }, +{ 0xB84B, 0xB84B, 0xB84B }, +{ 0xB84C, 0xB84C, 0xB84C }, +{ 0xB84D, 0xB84D, 0xB84D }, +{ 0xB84E, 0xB84E, 0xB84E }, +{ 0xB84F, 0xB84F, 0xB84F }, +{ 0xB850, 0xB850, 0xB850 }, +{ 0xB851, 0xB851, 0xB851 }, +{ 0xB852, 0xB852, 0xB852 }, +{ 0xB853, 0xB853, 0xB853 }, +{ 0xB854, 0xB854, 0xB854 }, +{ 0xB855, 0xB855, 0xB855 }, +{ 0xB856, 0xB856, 0xB856 }, +{ 0xB857, 0xB857, 0xB857 }, +{ 0xB858, 0xB858, 0xB858 }, +{ 0xB859, 0xB859, 0xB859 }, +{ 0xB85A, 0xB85A, 0xB85A }, +{ 0xB85B, 0xB85B, 0xB85B }, +{ 0xB85C, 0xB85C, 0xB85C }, +{ 0xB85D, 0xB85D, 0xB85D }, +{ 0xB85E, 0xB85E, 0xB85E }, +{ 0xB85F, 0xB85F, 0xB85F }, +{ 0xB860, 0xB860, 0xB860 }, +{ 0xB861, 0xB861, 0xB861 }, +{ 0xB862, 0xB862, 0xB862 }, +{ 0xB863, 0xB863, 0xB863 }, +{ 0xB864, 0xB864, 0xB864 }, +{ 0xB865, 0xB865, 0xB865 }, +{ 0xB866, 0xB866, 0xB866 }, +{ 0xB867, 0xB867, 0xB867 }, +{ 0xB868, 0xB868, 0xB868 }, +{ 0xB869, 0xB869, 0xB869 }, +{ 0xB86A, 0xB86A, 0xB86A }, +{ 0xB86B, 0xB86B, 0xB86B }, +{ 0xB86C, 0xB86C, 0xB86C }, +{ 0xB86D, 0xB86D, 0xB86D }, +{ 0xB86E, 0xB86E, 0xB86E }, +{ 0xB86F, 0xB86F, 0xB86F }, +{ 0xB870, 0xB870, 0xB870 }, +{ 0xB871, 0xB871, 0xB871 }, +{ 0xB872, 0xB872, 0xB872 }, +{ 0xB873, 0xB873, 0xB873 }, +{ 0xB874, 0xB874, 0xB874 }, +{ 0xB875, 0xB875, 0xB875 }, +{ 0xB876, 0xB876, 0xB876 }, +{ 0xB877, 0xB877, 0xB877 }, +{ 0xB878, 0xB878, 0xB878 }, +{ 0xB879, 0xB879, 0xB879 }, +{ 0xB87A, 0xB87A, 0xB87A }, +{ 0xB87B, 0xB87B, 0xB87B }, +{ 0xB87C, 0xB87C, 0xB87C }, +{ 0xB87D, 0xB87D, 0xB87D }, +{ 0xB87E, 0xB87E, 0xB87E }, +{ 0xB87F, 0xB87F, 0xB87F }, +{ 0xB880, 0xB880, 0xB880 }, +{ 0xB881, 0xB881, 0xB881 }, +{ 0xB882, 0xB882, 0xB882 }, +{ 0xB883, 0xB883, 0xB883 }, +{ 0xB884, 0xB884, 0xB884 }, +{ 0xB885, 0xB885, 0xB885 }, +{ 0xB886, 0xB886, 0xB886 }, +{ 0xB887, 0xB887, 0xB887 }, +{ 0xB888, 0xB888, 0xB888 }, +{ 0xB889, 0xB889, 0xB889 }, +{ 0xB88A, 0xB88A, 0xB88A }, +{ 0xB88B, 0xB88B, 0xB88B }, +{ 0xB88C, 0xB88C, 0xB88C }, +{ 0xB88D, 0xB88D, 0xB88D }, +{ 0xB88E, 0xB88E, 0xB88E }, +{ 0xB88F, 0xB88F, 0xB88F }, +{ 0xB890, 0xB890, 0xB890 }, +{ 0xB891, 0xB891, 0xB891 }, +{ 0xB892, 0xB892, 0xB892 }, +{ 0xB893, 0xB893, 0xB893 }, +{ 0xB894, 0xB894, 0xB894 }, +{ 0xB895, 0xB895, 0xB895 }, +{ 0xB896, 0xB896, 0xB896 }, +{ 0xB897, 0xB897, 0xB897 }, +{ 0xB898, 0xB898, 0xB898 }, +{ 0xB899, 0xB899, 0xB899 }, +{ 0xB89A, 0xB89A, 0xB89A }, +{ 0xB89B, 0xB89B, 0xB89B }, +{ 0xB89C, 0xB89C, 0xB89C }, +{ 0xB89D, 0xB89D, 0xB89D }, +{ 0xB89E, 0xB89E, 0xB89E }, +{ 0xB89F, 0xB89F, 0xB89F }, +{ 0xB8A0, 0xB8A0, 0xB8A0 }, +{ 0xB8A1, 0xB8A1, 0xB8A1 }, +{ 0xB8A2, 0xB8A2, 0xB8A2 }, +{ 0xB8A3, 0xB8A3, 0xB8A3 }, +{ 0xB8A4, 0xB8A4, 0xB8A4 }, +{ 0xB8A5, 0xB8A5, 0xB8A5 }, +{ 0xB8A6, 0xB8A6, 0xB8A6 }, +{ 0xB8A7, 0xB8A7, 0xB8A7 }, +{ 0xB8A8, 0xB8A8, 0xB8A8 }, +{ 0xB8A9, 0xB8A9, 0xB8A9 }, +{ 0xB8AA, 0xB8AA, 0xB8AA }, +{ 0xB8AB, 0xB8AB, 0xB8AB }, +{ 0xB8AC, 0xB8AC, 0xB8AC }, +{ 0xB8AD, 0xB8AD, 0xB8AD }, +{ 0xB8AE, 0xB8AE, 0xB8AE }, +{ 0xB8AF, 0xB8AF, 0xB8AF }, +{ 0xB8B0, 0xB8B0, 0xB8B0 }, +{ 0xB8B1, 0xB8B1, 0xB8B1 }, +{ 0xB8B2, 0xB8B2, 0xB8B2 }, +{ 0xB8B3, 0xB8B3, 0xB8B3 }, +{ 0xB8B4, 0xB8B4, 0xB8B4 }, +{ 0xB8B5, 0xB8B5, 0xB8B5 }, +{ 0xB8B6, 0xB8B6, 0xB8B6 }, +{ 0xB8B7, 0xB8B7, 0xB8B7 }, +{ 0xB8B8, 0xB8B8, 0xB8B8 }, +{ 0xB8B9, 0xB8B9, 0xB8B9 }, +{ 0xB8BA, 0xB8BA, 0xB8BA }, +{ 0xB8BB, 0xB8BB, 0xB8BB }, +{ 0xB8BC, 0xB8BC, 0xB8BC }, +{ 0xB8BD, 0xB8BD, 0xB8BD }, +{ 0xB8BE, 0xB8BE, 0xB8BE }, +{ 0xB8BF, 0xB8BF, 0xB8BF }, +{ 0xB8C0, 0xB8C0, 0xB8C0 }, +{ 0xB8C1, 0xB8C1, 0xB8C1 }, +{ 0xB8C2, 0xB8C2, 0xB8C2 }, +{ 0xB8C3, 0xB8C3, 0xB8C3 }, +{ 0xB8C4, 0xB8C4, 0xB8C4 }, +{ 0xB8C5, 0xB8C5, 0xB8C5 }, +{ 0xB8C6, 0xB8C6, 0xB8C6 }, +{ 0xB8C7, 0xB8C7, 0xB8C7 }, +{ 0xB8C8, 0xB8C8, 0xB8C8 }, +{ 0xB8C9, 0xB8C9, 0xB8C9 }, +{ 0xB8CA, 0xB8CA, 0xB8CA }, +{ 0xB8CB, 0xB8CB, 0xB8CB }, +{ 0xB8CC, 0xB8CC, 0xB8CC }, +{ 0xB8CD, 0xB8CD, 0xB8CD }, +{ 0xB8CE, 0xB8CE, 0xB8CE }, +{ 0xB8CF, 0xB8CF, 0xB8CF }, +{ 0xB8D0, 0xB8D0, 0xB8D0 }, +{ 0xB8D1, 0xB8D1, 0xB8D1 }, +{ 0xB8D2, 0xB8D2, 0xB8D2 }, +{ 0xB8D3, 0xB8D3, 0xB8D3 }, +{ 0xB8D4, 0xB8D4, 0xB8D4 }, +{ 0xB8D5, 0xB8D5, 0xB8D5 }, +{ 0xB8D6, 0xB8D6, 0xB8D6 }, +{ 0xB8D7, 0xB8D7, 0xB8D7 }, +{ 0xB8D8, 0xB8D8, 0xB8D8 }, +{ 0xB8D9, 0xB8D9, 0xB8D9 }, +{ 0xB8DA, 0xB8DA, 0xB8DA }, +{ 0xB8DB, 0xB8DB, 0xB8DB }, +{ 0xB8DC, 0xB8DC, 0xB8DC }, +{ 0xB8DD, 0xB8DD, 0xB8DD }, +{ 0xB8DE, 0xB8DE, 0xB8DE }, +{ 0xB8DF, 0xB8DF, 0xB8DF }, +{ 0xB8E0, 0xB8E0, 0xB8E0 }, +{ 0xB8E1, 0xB8E1, 0xB8E1 }, +{ 0xB8E2, 0xB8E2, 0xB8E2 }, +{ 0xB8E3, 0xB8E3, 0xB8E3 }, +{ 0xB8E4, 0xB8E4, 0xB8E4 }, +{ 0xB8E5, 0xB8E5, 0xB8E5 }, +{ 0xB8E6, 0xB8E6, 0xB8E6 }, +{ 0xB8E7, 0xB8E7, 0xB8E7 }, +{ 0xB8E8, 0xB8E8, 0xB8E8 }, +{ 0xB8E9, 0xB8E9, 0xB8E9 }, +{ 0xB8EA, 0xB8EA, 0xB8EA }, +{ 0xB8EB, 0xB8EB, 0xB8EB }, +{ 0xB8EC, 0xB8EC, 0xB8EC }, +{ 0xB8ED, 0xB8ED, 0xB8ED }, +{ 0xB8EE, 0xB8EE, 0xB8EE }, +{ 0xB8EF, 0xB8EF, 0xB8EF }, +{ 0xB8F0, 0xB8F0, 0xB8F0 }, +{ 0xB8F1, 0xB8F1, 0xB8F1 }, +{ 0xB8F2, 0xB8F2, 0xB8F2 }, +{ 0xB8F3, 0xB8F3, 0xB8F3 }, +{ 0xB8F4, 0xB8F4, 0xB8F4 }, +{ 0xB8F5, 0xB8F5, 0xB8F5 }, +{ 0xB8F6, 0xB8F6, 0xB8F6 }, +{ 0xB8F7, 0xB8F7, 0xB8F7 }, +{ 0xB8F8, 0xB8F8, 0xB8F8 }, +{ 0xB8F9, 0xB8F9, 0xB8F9 }, +{ 0xB8FA, 0xB8FA, 0xB8FA }, +{ 0xB8FB, 0xB8FB, 0xB8FB }, +{ 0xB8FC, 0xB8FC, 0xB8FC }, +{ 0xB8FD, 0xB8FD, 0xB8FD }, +{ 0xB8FE, 0xB8FE, 0xB8FE }, +{ 0xB8FF, 0xB8FF, 0xB8FF }, +{ 0xB900, 0xB900, 0xB900 }, +{ 0xB901, 0xB901, 0xB901 }, +{ 0xB902, 0xB902, 0xB902 }, +{ 0xB903, 0xB903, 0xB903 }, +{ 0xB904, 0xB904, 0xB904 }, +{ 0xB905, 0xB905, 0xB905 }, +{ 0xB906, 0xB906, 0xB906 }, +{ 0xB907, 0xB907, 0xB907 }, +{ 0xB908, 0xB908, 0xB908 }, +{ 0xB909, 0xB909, 0xB909 }, +{ 0xB90A, 0xB90A, 0xB90A }, +{ 0xB90B, 0xB90B, 0xB90B }, +{ 0xB90C, 0xB90C, 0xB90C }, +{ 0xB90D, 0xB90D, 0xB90D }, +{ 0xB90E, 0xB90E, 0xB90E }, +{ 0xB90F, 0xB90F, 0xB90F }, +{ 0xB910, 0xB910, 0xB910 }, +{ 0xB911, 0xB911, 0xB911 }, +{ 0xB912, 0xB912, 0xB912 }, +{ 0xB913, 0xB913, 0xB913 }, +{ 0xB914, 0xB914, 0xB914 }, +{ 0xB915, 0xB915, 0xB915 }, +{ 0xB916, 0xB916, 0xB916 }, +{ 0xB917, 0xB917, 0xB917 }, +{ 0xB918, 0xB918, 0xB918 }, +{ 0xB919, 0xB919, 0xB919 }, +{ 0xB91A, 0xB91A, 0xB91A }, +{ 0xB91B, 0xB91B, 0xB91B }, +{ 0xB91C, 0xB91C, 0xB91C }, +{ 0xB91D, 0xB91D, 0xB91D }, +{ 0xB91E, 0xB91E, 0xB91E }, +{ 0xB91F, 0xB91F, 0xB91F }, +{ 0xB920, 0xB920, 0xB920 }, +{ 0xB921, 0xB921, 0xB921 }, +{ 0xB922, 0xB922, 0xB922 }, +{ 0xB923, 0xB923, 0xB923 }, +{ 0xB924, 0xB924, 0xB924 }, +{ 0xB925, 0xB925, 0xB925 }, +{ 0xB926, 0xB926, 0xB926 }, +{ 0xB927, 0xB927, 0xB927 }, +{ 0xB928, 0xB928, 0xB928 }, +{ 0xB929, 0xB929, 0xB929 }, +{ 0xB92A, 0xB92A, 0xB92A }, +{ 0xB92B, 0xB92B, 0xB92B }, +{ 0xB92C, 0xB92C, 0xB92C }, +{ 0xB92D, 0xB92D, 0xB92D }, +{ 0xB92E, 0xB92E, 0xB92E }, +{ 0xB92F, 0xB92F, 0xB92F }, +{ 0xB930, 0xB930, 0xB930 }, +{ 0xB931, 0xB931, 0xB931 }, +{ 0xB932, 0xB932, 0xB932 }, +{ 0xB933, 0xB933, 0xB933 }, +{ 0xB934, 0xB934, 0xB934 }, +{ 0xB935, 0xB935, 0xB935 }, +{ 0xB936, 0xB936, 0xB936 }, +{ 0xB937, 0xB937, 0xB937 }, +{ 0xB938, 0xB938, 0xB938 }, +{ 0xB939, 0xB939, 0xB939 }, +{ 0xB93A, 0xB93A, 0xB93A }, +{ 0xB93B, 0xB93B, 0xB93B }, +{ 0xB93C, 0xB93C, 0xB93C }, +{ 0xB93D, 0xB93D, 0xB93D }, +{ 0xB93E, 0xB93E, 0xB93E }, +{ 0xB93F, 0xB93F, 0xB93F }, +{ 0xB940, 0xB940, 0xB940 }, +{ 0xB941, 0xB941, 0xB941 }, +{ 0xB942, 0xB942, 0xB942 }, +{ 0xB943, 0xB943, 0xB943 }, +{ 0xB944, 0xB944, 0xB944 }, +{ 0xB945, 0xB945, 0xB945 }, +{ 0xB946, 0xB946, 0xB946 }, +{ 0xB947, 0xB947, 0xB947 }, +{ 0xB948, 0xB948, 0xB948 }, +{ 0xB949, 0xB949, 0xB949 }, +{ 0xB94A, 0xB94A, 0xB94A }, +{ 0xB94B, 0xB94B, 0xB94B }, +{ 0xB94C, 0xB94C, 0xB94C }, +{ 0xB94D, 0xB94D, 0xB94D }, +{ 0xB94E, 0xB94E, 0xB94E }, +{ 0xB94F, 0xB94F, 0xB94F }, +{ 0xB950, 0xB950, 0xB950 }, +{ 0xB951, 0xB951, 0xB951 }, +{ 0xB952, 0xB952, 0xB952 }, +{ 0xB953, 0xB953, 0xB953 }, +{ 0xB954, 0xB954, 0xB954 }, +{ 0xB955, 0xB955, 0xB955 }, +{ 0xB956, 0xB956, 0xB956 }, +{ 0xB957, 0xB957, 0xB957 }, +{ 0xB958, 0xB958, 0xB958 }, +{ 0xB959, 0xB959, 0xB959 }, +{ 0xB95A, 0xB95A, 0xB95A }, +{ 0xB95B, 0xB95B, 0xB95B }, +{ 0xB95C, 0xB95C, 0xB95C }, +{ 0xB95D, 0xB95D, 0xB95D }, +{ 0xB95E, 0xB95E, 0xB95E }, +{ 0xB95F, 0xB95F, 0xB95F }, +{ 0xB960, 0xB960, 0xB960 }, +{ 0xB961, 0xB961, 0xB961 }, +{ 0xB962, 0xB962, 0xB962 }, +{ 0xB963, 0xB963, 0xB963 }, +{ 0xB964, 0xB964, 0xB964 }, +{ 0xB965, 0xB965, 0xB965 }, +{ 0xB966, 0xB966, 0xB966 }, +{ 0xB967, 0xB967, 0xB967 }, +{ 0xB968, 0xB968, 0xB968 }, +{ 0xB969, 0xB969, 0xB969 }, +{ 0xB96A, 0xB96A, 0xB96A }, +{ 0xB96B, 0xB96B, 0xB96B }, +{ 0xB96C, 0xB96C, 0xB96C }, +{ 0xB96D, 0xB96D, 0xB96D }, +{ 0xB96E, 0xB96E, 0xB96E }, +{ 0xB96F, 0xB96F, 0xB96F }, +{ 0xB970, 0xB970, 0xB970 }, +{ 0xB971, 0xB971, 0xB971 }, +{ 0xB972, 0xB972, 0xB972 }, +{ 0xB973, 0xB973, 0xB973 }, +{ 0xB974, 0xB974, 0xB974 }, +{ 0xB975, 0xB975, 0xB975 }, +{ 0xB976, 0xB976, 0xB976 }, +{ 0xB977, 0xB977, 0xB977 }, +{ 0xB978, 0xB978, 0xB978 }, +{ 0xB979, 0xB979, 0xB979 }, +{ 0xB97A, 0xB97A, 0xB97A }, +{ 0xB97B, 0xB97B, 0xB97B }, +{ 0xB97C, 0xB97C, 0xB97C }, +{ 0xB97D, 0xB97D, 0xB97D }, +{ 0xB97E, 0xB97E, 0xB97E }, +{ 0xB97F, 0xB97F, 0xB97F }, +{ 0xB980, 0xB980, 0xB980 }, +{ 0xB981, 0xB981, 0xB981 }, +{ 0xB982, 0xB982, 0xB982 }, +{ 0xB983, 0xB983, 0xB983 }, +{ 0xB984, 0xB984, 0xB984 }, +{ 0xB985, 0xB985, 0xB985 }, +{ 0xB986, 0xB986, 0xB986 }, +{ 0xB987, 0xB987, 0xB987 }, +{ 0xB988, 0xB988, 0xB988 }, +{ 0xB989, 0xB989, 0xB989 }, +{ 0xB98A, 0xB98A, 0xB98A }, +{ 0xB98B, 0xB98B, 0xB98B }, +{ 0xB98C, 0xB98C, 0xB98C }, +{ 0xB98D, 0xB98D, 0xB98D }, +{ 0xB98E, 0xB98E, 0xB98E }, +{ 0xB98F, 0xB98F, 0xB98F }, +{ 0xB990, 0xB990, 0xB990 }, +{ 0xB991, 0xB991, 0xB991 }, +{ 0xB992, 0xB992, 0xB992 }, +{ 0xB993, 0xB993, 0xB993 }, +{ 0xB994, 0xB994, 0xB994 }, +{ 0xB995, 0xB995, 0xB995 }, +{ 0xB996, 0xB996, 0xB996 }, +{ 0xB997, 0xB997, 0xB997 }, +{ 0xB998, 0xB998, 0xB998 }, +{ 0xB999, 0xB999, 0xB999 }, +{ 0xB99A, 0xB99A, 0xB99A }, +{ 0xB99B, 0xB99B, 0xB99B }, +{ 0xB99C, 0xB99C, 0xB99C }, +{ 0xB99D, 0xB99D, 0xB99D }, +{ 0xB99E, 0xB99E, 0xB99E }, +{ 0xB99F, 0xB99F, 0xB99F }, +{ 0xB9A0, 0xB9A0, 0xB9A0 }, +{ 0xB9A1, 0xB9A1, 0xB9A1 }, +{ 0xB9A2, 0xB9A2, 0xB9A2 }, +{ 0xB9A3, 0xB9A3, 0xB9A3 }, +{ 0xB9A4, 0xB9A4, 0xB9A4 }, +{ 0xB9A5, 0xB9A5, 0xB9A5 }, +{ 0xB9A6, 0xB9A6, 0xB9A6 }, +{ 0xB9A7, 0xB9A7, 0xB9A7 }, +{ 0xB9A8, 0xB9A8, 0xB9A8 }, +{ 0xB9A9, 0xB9A9, 0xB9A9 }, +{ 0xB9AA, 0xB9AA, 0xB9AA }, +{ 0xB9AB, 0xB9AB, 0xB9AB }, +{ 0xB9AC, 0xB9AC, 0xB9AC }, +{ 0xB9AD, 0xB9AD, 0xB9AD }, +{ 0xB9AE, 0xB9AE, 0xB9AE }, +{ 0xB9AF, 0xB9AF, 0xB9AF }, +{ 0xB9B0, 0xB9B0, 0xB9B0 }, +{ 0xB9B1, 0xB9B1, 0xB9B1 }, +{ 0xB9B2, 0xB9B2, 0xB9B2 }, +{ 0xB9B3, 0xB9B3, 0xB9B3 }, +{ 0xB9B4, 0xB9B4, 0xB9B4 }, +{ 0xB9B5, 0xB9B5, 0xB9B5 }, +{ 0xB9B6, 0xB9B6, 0xB9B6 }, +{ 0xB9B7, 0xB9B7, 0xB9B7 }, +{ 0xB9B8, 0xB9B8, 0xB9B8 }, +{ 0xB9B9, 0xB9B9, 0xB9B9 }, +{ 0xB9BA, 0xB9BA, 0xB9BA }, +{ 0xB9BB, 0xB9BB, 0xB9BB }, +{ 0xB9BC, 0xB9BC, 0xB9BC }, +{ 0xB9BD, 0xB9BD, 0xB9BD }, +{ 0xB9BE, 0xB9BE, 0xB9BE }, +{ 0xB9BF, 0xB9BF, 0xB9BF }, +{ 0xB9C0, 0xB9C0, 0xB9C0 }, +{ 0xB9C1, 0xB9C1, 0xB9C1 }, +{ 0xB9C2, 0xB9C2, 0xB9C2 }, +{ 0xB9C3, 0xB9C3, 0xB9C3 }, +{ 0xB9C4, 0xB9C4, 0xB9C4 }, +{ 0xB9C5, 0xB9C5, 0xB9C5 }, +{ 0xB9C6, 0xB9C6, 0xB9C6 }, +{ 0xB9C7, 0xB9C7, 0xB9C7 }, +{ 0xB9C8, 0xB9C8, 0xB9C8 }, +{ 0xB9C9, 0xB9C9, 0xB9C9 }, +{ 0xB9CA, 0xB9CA, 0xB9CA }, +{ 0xB9CB, 0xB9CB, 0xB9CB }, +{ 0xB9CC, 0xB9CC, 0xB9CC }, +{ 0xB9CD, 0xB9CD, 0xB9CD }, +{ 0xB9CE, 0xB9CE, 0xB9CE }, +{ 0xB9CF, 0xB9CF, 0xB9CF }, +{ 0xB9D0, 0xB9D0, 0xB9D0 }, +{ 0xB9D1, 0xB9D1, 0xB9D1 }, +{ 0xB9D2, 0xB9D2, 0xB9D2 }, +{ 0xB9D3, 0xB9D3, 0xB9D3 }, +{ 0xB9D4, 0xB9D4, 0xB9D4 }, +{ 0xB9D5, 0xB9D5, 0xB9D5 }, +{ 0xB9D6, 0xB9D6, 0xB9D6 }, +{ 0xB9D7, 0xB9D7, 0xB9D7 }, +{ 0xB9D8, 0xB9D8, 0xB9D8 }, +{ 0xB9D9, 0xB9D9, 0xB9D9 }, +{ 0xB9DA, 0xB9DA, 0xB9DA }, +{ 0xB9DB, 0xB9DB, 0xB9DB }, +{ 0xB9DC, 0xB9DC, 0xB9DC }, +{ 0xB9DD, 0xB9DD, 0xB9DD }, +{ 0xB9DE, 0xB9DE, 0xB9DE }, +{ 0xB9DF, 0xB9DF, 0xB9DF }, +{ 0xB9E0, 0xB9E0, 0xB9E0 }, +{ 0xB9E1, 0xB9E1, 0xB9E1 }, +{ 0xB9E2, 0xB9E2, 0xB9E2 }, +{ 0xB9E3, 0xB9E3, 0xB9E3 }, +{ 0xB9E4, 0xB9E4, 0xB9E4 }, +{ 0xB9E5, 0xB9E5, 0xB9E5 }, +{ 0xB9E6, 0xB9E6, 0xB9E6 }, +{ 0xB9E7, 0xB9E7, 0xB9E7 }, +{ 0xB9E8, 0xB9E8, 0xB9E8 }, +{ 0xB9E9, 0xB9E9, 0xB9E9 }, +{ 0xB9EA, 0xB9EA, 0xB9EA }, +{ 0xB9EB, 0xB9EB, 0xB9EB }, +{ 0xB9EC, 0xB9EC, 0xB9EC }, +{ 0xB9ED, 0xB9ED, 0xB9ED }, +{ 0xB9EE, 0xB9EE, 0xB9EE }, +{ 0xB9EF, 0xB9EF, 0xB9EF }, +{ 0xB9F0, 0xB9F0, 0xB9F0 }, +{ 0xB9F1, 0xB9F1, 0xB9F1 }, +{ 0xB9F2, 0xB9F2, 0xB9F2 }, +{ 0xB9F3, 0xB9F3, 0xB9F3 }, +{ 0xB9F4, 0xB9F4, 0xB9F4 }, +{ 0xB9F5, 0xB9F5, 0xB9F5 }, +{ 0xB9F6, 0xB9F6, 0xB9F6 }, +{ 0xB9F7, 0xB9F7, 0xB9F7 }, +{ 0xB9F8, 0xB9F8, 0xB9F8 }, +{ 0xB9F9, 0xB9F9, 0xB9F9 }, +{ 0xB9FA, 0xB9FA, 0xB9FA }, +{ 0xB9FB, 0xB9FB, 0xB9FB }, +{ 0xB9FC, 0xB9FC, 0xB9FC }, +{ 0xB9FD, 0xB9FD, 0xB9FD }, +{ 0xB9FE, 0xB9FE, 0xB9FE }, +{ 0xB9FF, 0xB9FF, 0xB9FF }, +{ 0xBA00, 0xBA00, 0xBA00 }, +{ 0xBA01, 0xBA01, 0xBA01 }, +{ 0xBA02, 0xBA02, 0xBA02 }, +{ 0xBA03, 0xBA03, 0xBA03 }, +{ 0xBA04, 0xBA04, 0xBA04 }, +{ 0xBA05, 0xBA05, 0xBA05 }, +{ 0xBA06, 0xBA06, 0xBA06 }, +{ 0xBA07, 0xBA07, 0xBA07 }, +{ 0xBA08, 0xBA08, 0xBA08 }, +{ 0xBA09, 0xBA09, 0xBA09 }, +{ 0xBA0A, 0xBA0A, 0xBA0A }, +{ 0xBA0B, 0xBA0B, 0xBA0B }, +{ 0xBA0C, 0xBA0C, 0xBA0C }, +{ 0xBA0D, 0xBA0D, 0xBA0D }, +{ 0xBA0E, 0xBA0E, 0xBA0E }, +{ 0xBA0F, 0xBA0F, 0xBA0F }, +{ 0xBA10, 0xBA10, 0xBA10 }, +{ 0xBA11, 0xBA11, 0xBA11 }, +{ 0xBA12, 0xBA12, 0xBA12 }, +{ 0xBA13, 0xBA13, 0xBA13 }, +{ 0xBA14, 0xBA14, 0xBA14 }, +{ 0xBA15, 0xBA15, 0xBA15 }, +{ 0xBA16, 0xBA16, 0xBA16 }, +{ 0xBA17, 0xBA17, 0xBA17 }, +{ 0xBA18, 0xBA18, 0xBA18 }, +{ 0xBA19, 0xBA19, 0xBA19 }, +{ 0xBA1A, 0xBA1A, 0xBA1A }, +{ 0xBA1B, 0xBA1B, 0xBA1B }, +{ 0xBA1C, 0xBA1C, 0xBA1C }, +{ 0xBA1D, 0xBA1D, 0xBA1D }, +{ 0xBA1E, 0xBA1E, 0xBA1E }, +{ 0xBA1F, 0xBA1F, 0xBA1F }, +{ 0xBA20, 0xBA20, 0xBA20 }, +{ 0xBA21, 0xBA21, 0xBA21 }, +{ 0xBA22, 0xBA22, 0xBA22 }, +{ 0xBA23, 0xBA23, 0xBA23 }, +{ 0xBA24, 0xBA24, 0xBA24 }, +{ 0xBA25, 0xBA25, 0xBA25 }, +{ 0xBA26, 0xBA26, 0xBA26 }, +{ 0xBA27, 0xBA27, 0xBA27 }, +{ 0xBA28, 0xBA28, 0xBA28 }, +{ 0xBA29, 0xBA29, 0xBA29 }, +{ 0xBA2A, 0xBA2A, 0xBA2A }, +{ 0xBA2B, 0xBA2B, 0xBA2B }, +{ 0xBA2C, 0xBA2C, 0xBA2C }, +{ 0xBA2D, 0xBA2D, 0xBA2D }, +{ 0xBA2E, 0xBA2E, 0xBA2E }, +{ 0xBA2F, 0xBA2F, 0xBA2F }, +{ 0xBA30, 0xBA30, 0xBA30 }, +{ 0xBA31, 0xBA31, 0xBA31 }, +{ 0xBA32, 0xBA32, 0xBA32 }, +{ 0xBA33, 0xBA33, 0xBA33 }, +{ 0xBA34, 0xBA34, 0xBA34 }, +{ 0xBA35, 0xBA35, 0xBA35 }, +{ 0xBA36, 0xBA36, 0xBA36 }, +{ 0xBA37, 0xBA37, 0xBA37 }, +{ 0xBA38, 0xBA38, 0xBA38 }, +{ 0xBA39, 0xBA39, 0xBA39 }, +{ 0xBA3A, 0xBA3A, 0xBA3A }, +{ 0xBA3B, 0xBA3B, 0xBA3B }, +{ 0xBA3C, 0xBA3C, 0xBA3C }, +{ 0xBA3D, 0xBA3D, 0xBA3D }, +{ 0xBA3E, 0xBA3E, 0xBA3E }, +{ 0xBA3F, 0xBA3F, 0xBA3F }, +{ 0xBA40, 0xBA40, 0xBA40 }, +{ 0xBA41, 0xBA41, 0xBA41 }, +{ 0xBA42, 0xBA42, 0xBA42 }, +{ 0xBA43, 0xBA43, 0xBA43 }, +{ 0xBA44, 0xBA44, 0xBA44 }, +{ 0xBA45, 0xBA45, 0xBA45 }, +{ 0xBA46, 0xBA46, 0xBA46 }, +{ 0xBA47, 0xBA47, 0xBA47 }, +{ 0xBA48, 0xBA48, 0xBA48 }, +{ 0xBA49, 0xBA49, 0xBA49 }, +{ 0xBA4A, 0xBA4A, 0xBA4A }, +{ 0xBA4B, 0xBA4B, 0xBA4B }, +{ 0xBA4C, 0xBA4C, 0xBA4C }, +{ 0xBA4D, 0xBA4D, 0xBA4D }, +{ 0xBA4E, 0xBA4E, 0xBA4E }, +{ 0xBA4F, 0xBA4F, 0xBA4F }, +{ 0xBA50, 0xBA50, 0xBA50 }, +{ 0xBA51, 0xBA51, 0xBA51 }, +{ 0xBA52, 0xBA52, 0xBA52 }, +{ 0xBA53, 0xBA53, 0xBA53 }, +{ 0xBA54, 0xBA54, 0xBA54 }, +{ 0xBA55, 0xBA55, 0xBA55 }, +{ 0xBA56, 0xBA56, 0xBA56 }, +{ 0xBA57, 0xBA57, 0xBA57 }, +{ 0xBA58, 0xBA58, 0xBA58 }, +{ 0xBA59, 0xBA59, 0xBA59 }, +{ 0xBA5A, 0xBA5A, 0xBA5A }, +{ 0xBA5B, 0xBA5B, 0xBA5B }, +{ 0xBA5C, 0xBA5C, 0xBA5C }, +{ 0xBA5D, 0xBA5D, 0xBA5D }, +{ 0xBA5E, 0xBA5E, 0xBA5E }, +{ 0xBA5F, 0xBA5F, 0xBA5F }, +{ 0xBA60, 0xBA60, 0xBA60 }, +{ 0xBA61, 0xBA61, 0xBA61 }, +{ 0xBA62, 0xBA62, 0xBA62 }, +{ 0xBA63, 0xBA63, 0xBA63 }, +{ 0xBA64, 0xBA64, 0xBA64 }, +{ 0xBA65, 0xBA65, 0xBA65 }, +{ 0xBA66, 0xBA66, 0xBA66 }, +{ 0xBA67, 0xBA67, 0xBA67 }, +{ 0xBA68, 0xBA68, 0xBA68 }, +{ 0xBA69, 0xBA69, 0xBA69 }, +{ 0xBA6A, 0xBA6A, 0xBA6A }, +{ 0xBA6B, 0xBA6B, 0xBA6B }, +{ 0xBA6C, 0xBA6C, 0xBA6C }, +{ 0xBA6D, 0xBA6D, 0xBA6D }, +{ 0xBA6E, 0xBA6E, 0xBA6E }, +{ 0xBA6F, 0xBA6F, 0xBA6F }, +{ 0xBA70, 0xBA70, 0xBA70 }, +{ 0xBA71, 0xBA71, 0xBA71 }, +{ 0xBA72, 0xBA72, 0xBA72 }, +{ 0xBA73, 0xBA73, 0xBA73 }, +{ 0xBA74, 0xBA74, 0xBA74 }, +{ 0xBA75, 0xBA75, 0xBA75 }, +{ 0xBA76, 0xBA76, 0xBA76 }, +{ 0xBA77, 0xBA77, 0xBA77 }, +{ 0xBA78, 0xBA78, 0xBA78 }, +{ 0xBA79, 0xBA79, 0xBA79 }, +{ 0xBA7A, 0xBA7A, 0xBA7A }, +{ 0xBA7B, 0xBA7B, 0xBA7B }, +{ 0xBA7C, 0xBA7C, 0xBA7C }, +{ 0xBA7D, 0xBA7D, 0xBA7D }, +{ 0xBA7E, 0xBA7E, 0xBA7E }, +{ 0xBA7F, 0xBA7F, 0xBA7F }, +{ 0xBA80, 0xBA80, 0xBA80 }, +{ 0xBA81, 0xBA81, 0xBA81 }, +{ 0xBA82, 0xBA82, 0xBA82 }, +{ 0xBA83, 0xBA83, 0xBA83 }, +{ 0xBA84, 0xBA84, 0xBA84 }, +{ 0xBA85, 0xBA85, 0xBA85 }, +{ 0xBA86, 0xBA86, 0xBA86 }, +{ 0xBA87, 0xBA87, 0xBA87 }, +{ 0xBA88, 0xBA88, 0xBA88 }, +{ 0xBA89, 0xBA89, 0xBA89 }, +{ 0xBA8A, 0xBA8A, 0xBA8A }, +{ 0xBA8B, 0xBA8B, 0xBA8B }, +{ 0xBA8C, 0xBA8C, 0xBA8C }, +{ 0xBA8D, 0xBA8D, 0xBA8D }, +{ 0xBA8E, 0xBA8E, 0xBA8E }, +{ 0xBA8F, 0xBA8F, 0xBA8F }, +{ 0xBA90, 0xBA90, 0xBA90 }, +{ 0xBA91, 0xBA91, 0xBA91 }, +{ 0xBA92, 0xBA92, 0xBA92 }, +{ 0xBA93, 0xBA93, 0xBA93 }, +{ 0xBA94, 0xBA94, 0xBA94 }, +{ 0xBA95, 0xBA95, 0xBA95 }, +{ 0xBA96, 0xBA96, 0xBA96 }, +{ 0xBA97, 0xBA97, 0xBA97 }, +{ 0xBA98, 0xBA98, 0xBA98 }, +{ 0xBA99, 0xBA99, 0xBA99 }, +{ 0xBA9A, 0xBA9A, 0xBA9A }, +{ 0xBA9B, 0xBA9B, 0xBA9B }, +{ 0xBA9C, 0xBA9C, 0xBA9C }, +{ 0xBA9D, 0xBA9D, 0xBA9D }, +{ 0xBA9E, 0xBA9E, 0xBA9E }, +{ 0xBA9F, 0xBA9F, 0xBA9F }, +{ 0xBAA0, 0xBAA0, 0xBAA0 }, +{ 0xBAA1, 0xBAA1, 0xBAA1 }, +{ 0xBAA2, 0xBAA2, 0xBAA2 }, +{ 0xBAA3, 0xBAA3, 0xBAA3 }, +{ 0xBAA4, 0xBAA4, 0xBAA4 }, +{ 0xBAA5, 0xBAA5, 0xBAA5 }, +{ 0xBAA6, 0xBAA6, 0xBAA6 }, +{ 0xBAA7, 0xBAA7, 0xBAA7 }, +{ 0xBAA8, 0xBAA8, 0xBAA8 }, +{ 0xBAA9, 0xBAA9, 0xBAA9 }, +{ 0xBAAA, 0xBAAA, 0xBAAA }, +{ 0xBAAB, 0xBAAB, 0xBAAB }, +{ 0xBAAC, 0xBAAC, 0xBAAC }, +{ 0xBAAD, 0xBAAD, 0xBAAD }, +{ 0xBAAE, 0xBAAE, 0xBAAE }, +{ 0xBAAF, 0xBAAF, 0xBAAF }, +{ 0xBAB0, 0xBAB0, 0xBAB0 }, +{ 0xBAB1, 0xBAB1, 0xBAB1 }, +{ 0xBAB2, 0xBAB2, 0xBAB2 }, +{ 0xBAB3, 0xBAB3, 0xBAB3 }, +{ 0xBAB4, 0xBAB4, 0xBAB4 }, +{ 0xBAB5, 0xBAB5, 0xBAB5 }, +{ 0xBAB6, 0xBAB6, 0xBAB6 }, +{ 0xBAB7, 0xBAB7, 0xBAB7 }, +{ 0xBAB8, 0xBAB8, 0xBAB8 }, +{ 0xBAB9, 0xBAB9, 0xBAB9 }, +{ 0xBABA, 0xBABA, 0xBABA }, +{ 0xBABB, 0xBABB, 0xBABB }, +{ 0xBABC, 0xBABC, 0xBABC }, +{ 0xBABD, 0xBABD, 0xBABD }, +{ 0xBABE, 0xBABE, 0xBABE }, +{ 0xBABF, 0xBABF, 0xBABF }, +{ 0xBAC0, 0xBAC0, 0xBAC0 }, +{ 0xBAC1, 0xBAC1, 0xBAC1 }, +{ 0xBAC2, 0xBAC2, 0xBAC2 }, +{ 0xBAC3, 0xBAC3, 0xBAC3 }, +{ 0xBAC4, 0xBAC4, 0xBAC4 }, +{ 0xBAC5, 0xBAC5, 0xBAC5 }, +{ 0xBAC6, 0xBAC6, 0xBAC6 }, +{ 0xBAC7, 0xBAC7, 0xBAC7 }, +{ 0xBAC8, 0xBAC8, 0xBAC8 }, +{ 0xBAC9, 0xBAC9, 0xBAC9 }, +{ 0xBACA, 0xBACA, 0xBACA }, +{ 0xBACB, 0xBACB, 0xBACB }, +{ 0xBACC, 0xBACC, 0xBACC }, +{ 0xBACD, 0xBACD, 0xBACD }, +{ 0xBACE, 0xBACE, 0xBACE }, +{ 0xBACF, 0xBACF, 0xBACF }, +{ 0xBAD0, 0xBAD0, 0xBAD0 }, +{ 0xBAD1, 0xBAD1, 0xBAD1 }, +{ 0xBAD2, 0xBAD2, 0xBAD2 }, +{ 0xBAD3, 0xBAD3, 0xBAD3 }, +{ 0xBAD4, 0xBAD4, 0xBAD4 }, +{ 0xBAD5, 0xBAD5, 0xBAD5 }, +{ 0xBAD6, 0xBAD6, 0xBAD6 }, +{ 0xBAD7, 0xBAD7, 0xBAD7 }, +{ 0xBAD8, 0xBAD8, 0xBAD8 }, +{ 0xBAD9, 0xBAD9, 0xBAD9 }, +{ 0xBADA, 0xBADA, 0xBADA }, +{ 0xBADB, 0xBADB, 0xBADB }, +{ 0xBADC, 0xBADC, 0xBADC }, +{ 0xBADD, 0xBADD, 0xBADD }, +{ 0xBADE, 0xBADE, 0xBADE }, +{ 0xBADF, 0xBADF, 0xBADF }, +{ 0xBAE0, 0xBAE0, 0xBAE0 }, +{ 0xBAE1, 0xBAE1, 0xBAE1 }, +{ 0xBAE2, 0xBAE2, 0xBAE2 }, +{ 0xBAE3, 0xBAE3, 0xBAE3 }, +{ 0xBAE4, 0xBAE4, 0xBAE4 }, +{ 0xBAE5, 0xBAE5, 0xBAE5 }, +{ 0xBAE6, 0xBAE6, 0xBAE6 }, +{ 0xBAE7, 0xBAE7, 0xBAE7 }, +{ 0xBAE8, 0xBAE8, 0xBAE8 }, +{ 0xBAE9, 0xBAE9, 0xBAE9 }, +{ 0xBAEA, 0xBAEA, 0xBAEA }, +{ 0xBAEB, 0xBAEB, 0xBAEB }, +{ 0xBAEC, 0xBAEC, 0xBAEC }, +{ 0xBAED, 0xBAED, 0xBAED }, +{ 0xBAEE, 0xBAEE, 0xBAEE }, +{ 0xBAEF, 0xBAEF, 0xBAEF }, +{ 0xBAF0, 0xBAF0, 0xBAF0 }, +{ 0xBAF1, 0xBAF1, 0xBAF1 }, +{ 0xBAF2, 0xBAF2, 0xBAF2 }, +{ 0xBAF3, 0xBAF3, 0xBAF3 }, +{ 0xBAF4, 0xBAF4, 0xBAF4 }, +{ 0xBAF5, 0xBAF5, 0xBAF5 }, +{ 0xBAF6, 0xBAF6, 0xBAF6 }, +{ 0xBAF7, 0xBAF7, 0xBAF7 }, +{ 0xBAF8, 0xBAF8, 0xBAF8 }, +{ 0xBAF9, 0xBAF9, 0xBAF9 }, +{ 0xBAFA, 0xBAFA, 0xBAFA }, +{ 0xBAFB, 0xBAFB, 0xBAFB }, +{ 0xBAFC, 0xBAFC, 0xBAFC }, +{ 0xBAFD, 0xBAFD, 0xBAFD }, +{ 0xBAFE, 0xBAFE, 0xBAFE }, +{ 0xBAFF, 0xBAFF, 0xBAFF }, +{ 0xBB00, 0xBB00, 0xBB00 }, +{ 0xBB01, 0xBB01, 0xBB01 }, +{ 0xBB02, 0xBB02, 0xBB02 }, +{ 0xBB03, 0xBB03, 0xBB03 }, +{ 0xBB04, 0xBB04, 0xBB04 }, +{ 0xBB05, 0xBB05, 0xBB05 }, +{ 0xBB06, 0xBB06, 0xBB06 }, +{ 0xBB07, 0xBB07, 0xBB07 }, +{ 0xBB08, 0xBB08, 0xBB08 }, +{ 0xBB09, 0xBB09, 0xBB09 }, +{ 0xBB0A, 0xBB0A, 0xBB0A }, +{ 0xBB0B, 0xBB0B, 0xBB0B }, +{ 0xBB0C, 0xBB0C, 0xBB0C }, +{ 0xBB0D, 0xBB0D, 0xBB0D }, +{ 0xBB0E, 0xBB0E, 0xBB0E }, +{ 0xBB0F, 0xBB0F, 0xBB0F }, +{ 0xBB10, 0xBB10, 0xBB10 }, +{ 0xBB11, 0xBB11, 0xBB11 }, +{ 0xBB12, 0xBB12, 0xBB12 }, +{ 0xBB13, 0xBB13, 0xBB13 }, +{ 0xBB14, 0xBB14, 0xBB14 }, +{ 0xBB15, 0xBB15, 0xBB15 }, +{ 0xBB16, 0xBB16, 0xBB16 }, +{ 0xBB17, 0xBB17, 0xBB17 }, +{ 0xBB18, 0xBB18, 0xBB18 }, +{ 0xBB19, 0xBB19, 0xBB19 }, +{ 0xBB1A, 0xBB1A, 0xBB1A }, +{ 0xBB1B, 0xBB1B, 0xBB1B }, +{ 0xBB1C, 0xBB1C, 0xBB1C }, +{ 0xBB1D, 0xBB1D, 0xBB1D }, +{ 0xBB1E, 0xBB1E, 0xBB1E }, +{ 0xBB1F, 0xBB1F, 0xBB1F }, +{ 0xBB20, 0xBB20, 0xBB20 }, +{ 0xBB21, 0xBB21, 0xBB21 }, +{ 0xBB22, 0xBB22, 0xBB22 }, +{ 0xBB23, 0xBB23, 0xBB23 }, +{ 0xBB24, 0xBB24, 0xBB24 }, +{ 0xBB25, 0xBB25, 0xBB25 }, +{ 0xBB26, 0xBB26, 0xBB26 }, +{ 0xBB27, 0xBB27, 0xBB27 }, +{ 0xBB28, 0xBB28, 0xBB28 }, +{ 0xBB29, 0xBB29, 0xBB29 }, +{ 0xBB2A, 0xBB2A, 0xBB2A }, +{ 0xBB2B, 0xBB2B, 0xBB2B }, +{ 0xBB2C, 0xBB2C, 0xBB2C }, +{ 0xBB2D, 0xBB2D, 0xBB2D }, +{ 0xBB2E, 0xBB2E, 0xBB2E }, +{ 0xBB2F, 0xBB2F, 0xBB2F }, +{ 0xBB30, 0xBB30, 0xBB30 }, +{ 0xBB31, 0xBB31, 0xBB31 }, +{ 0xBB32, 0xBB32, 0xBB32 }, +{ 0xBB33, 0xBB33, 0xBB33 }, +{ 0xBB34, 0xBB34, 0xBB34 }, +{ 0xBB35, 0xBB35, 0xBB35 }, +{ 0xBB36, 0xBB36, 0xBB36 }, +{ 0xBB37, 0xBB37, 0xBB37 }, +{ 0xBB38, 0xBB38, 0xBB38 }, +{ 0xBB39, 0xBB39, 0xBB39 }, +{ 0xBB3A, 0xBB3A, 0xBB3A }, +{ 0xBB3B, 0xBB3B, 0xBB3B }, +{ 0xBB3C, 0xBB3C, 0xBB3C }, +{ 0xBB3D, 0xBB3D, 0xBB3D }, +{ 0xBB3E, 0xBB3E, 0xBB3E }, +{ 0xBB3F, 0xBB3F, 0xBB3F }, +{ 0xBB40, 0xBB40, 0xBB40 }, +{ 0xBB41, 0xBB41, 0xBB41 }, +{ 0xBB42, 0xBB42, 0xBB42 }, +{ 0xBB43, 0xBB43, 0xBB43 }, +{ 0xBB44, 0xBB44, 0xBB44 }, +{ 0xBB45, 0xBB45, 0xBB45 }, +{ 0xBB46, 0xBB46, 0xBB46 }, +{ 0xBB47, 0xBB47, 0xBB47 }, +{ 0xBB48, 0xBB48, 0xBB48 }, +{ 0xBB49, 0xBB49, 0xBB49 }, +{ 0xBB4A, 0xBB4A, 0xBB4A }, +{ 0xBB4B, 0xBB4B, 0xBB4B }, +{ 0xBB4C, 0xBB4C, 0xBB4C }, +{ 0xBB4D, 0xBB4D, 0xBB4D }, +{ 0xBB4E, 0xBB4E, 0xBB4E }, +{ 0xBB4F, 0xBB4F, 0xBB4F }, +{ 0xBB50, 0xBB50, 0xBB50 }, +{ 0xBB51, 0xBB51, 0xBB51 }, +{ 0xBB52, 0xBB52, 0xBB52 }, +{ 0xBB53, 0xBB53, 0xBB53 }, +{ 0xBB54, 0xBB54, 0xBB54 }, +{ 0xBB55, 0xBB55, 0xBB55 }, +{ 0xBB56, 0xBB56, 0xBB56 }, +{ 0xBB57, 0xBB57, 0xBB57 }, +{ 0xBB58, 0xBB58, 0xBB58 }, +{ 0xBB59, 0xBB59, 0xBB59 }, +{ 0xBB5A, 0xBB5A, 0xBB5A }, +{ 0xBB5B, 0xBB5B, 0xBB5B }, +{ 0xBB5C, 0xBB5C, 0xBB5C }, +{ 0xBB5D, 0xBB5D, 0xBB5D }, +{ 0xBB5E, 0xBB5E, 0xBB5E }, +{ 0xBB5F, 0xBB5F, 0xBB5F }, +{ 0xBB60, 0xBB60, 0xBB60 }, +{ 0xBB61, 0xBB61, 0xBB61 }, +{ 0xBB62, 0xBB62, 0xBB62 }, +{ 0xBB63, 0xBB63, 0xBB63 }, +{ 0xBB64, 0xBB64, 0xBB64 }, +{ 0xBB65, 0xBB65, 0xBB65 }, +{ 0xBB66, 0xBB66, 0xBB66 }, +{ 0xBB67, 0xBB67, 0xBB67 }, +{ 0xBB68, 0xBB68, 0xBB68 }, +{ 0xBB69, 0xBB69, 0xBB69 }, +{ 0xBB6A, 0xBB6A, 0xBB6A }, +{ 0xBB6B, 0xBB6B, 0xBB6B }, +{ 0xBB6C, 0xBB6C, 0xBB6C }, +{ 0xBB6D, 0xBB6D, 0xBB6D }, +{ 0xBB6E, 0xBB6E, 0xBB6E }, +{ 0xBB6F, 0xBB6F, 0xBB6F }, +{ 0xBB70, 0xBB70, 0xBB70 }, +{ 0xBB71, 0xBB71, 0xBB71 }, +{ 0xBB72, 0xBB72, 0xBB72 }, +{ 0xBB73, 0xBB73, 0xBB73 }, +{ 0xBB74, 0xBB74, 0xBB74 }, +{ 0xBB75, 0xBB75, 0xBB75 }, +{ 0xBB76, 0xBB76, 0xBB76 }, +{ 0xBB77, 0xBB77, 0xBB77 }, +{ 0xBB78, 0xBB78, 0xBB78 }, +{ 0xBB79, 0xBB79, 0xBB79 }, +{ 0xBB7A, 0xBB7A, 0xBB7A }, +{ 0xBB7B, 0xBB7B, 0xBB7B }, +{ 0xBB7C, 0xBB7C, 0xBB7C }, +{ 0xBB7D, 0xBB7D, 0xBB7D }, +{ 0xBB7E, 0xBB7E, 0xBB7E }, +{ 0xBB7F, 0xBB7F, 0xBB7F }, +{ 0xBB80, 0xBB80, 0xBB80 }, +{ 0xBB81, 0xBB81, 0xBB81 }, +{ 0xBB82, 0xBB82, 0xBB82 }, +{ 0xBB83, 0xBB83, 0xBB83 }, +{ 0xBB84, 0xBB84, 0xBB84 }, +{ 0xBB85, 0xBB85, 0xBB85 }, +{ 0xBB86, 0xBB86, 0xBB86 }, +{ 0xBB87, 0xBB87, 0xBB87 }, +{ 0xBB88, 0xBB88, 0xBB88 }, +{ 0xBB89, 0xBB89, 0xBB89 }, +{ 0xBB8A, 0xBB8A, 0xBB8A }, +{ 0xBB8B, 0xBB8B, 0xBB8B }, +{ 0xBB8C, 0xBB8C, 0xBB8C }, +{ 0xBB8D, 0xBB8D, 0xBB8D }, +{ 0xBB8E, 0xBB8E, 0xBB8E }, +{ 0xBB8F, 0xBB8F, 0xBB8F }, +{ 0xBB90, 0xBB90, 0xBB90 }, +{ 0xBB91, 0xBB91, 0xBB91 }, +{ 0xBB92, 0xBB92, 0xBB92 }, +{ 0xBB93, 0xBB93, 0xBB93 }, +{ 0xBB94, 0xBB94, 0xBB94 }, +{ 0xBB95, 0xBB95, 0xBB95 }, +{ 0xBB96, 0xBB96, 0xBB96 }, +{ 0xBB97, 0xBB97, 0xBB97 }, +{ 0xBB98, 0xBB98, 0xBB98 }, +{ 0xBB99, 0xBB99, 0xBB99 }, +{ 0xBB9A, 0xBB9A, 0xBB9A }, +{ 0xBB9B, 0xBB9B, 0xBB9B }, +{ 0xBB9C, 0xBB9C, 0xBB9C }, +{ 0xBB9D, 0xBB9D, 0xBB9D }, +{ 0xBB9E, 0xBB9E, 0xBB9E }, +{ 0xBB9F, 0xBB9F, 0xBB9F }, +{ 0xBBA0, 0xBBA0, 0xBBA0 }, +{ 0xBBA1, 0xBBA1, 0xBBA1 }, +{ 0xBBA2, 0xBBA2, 0xBBA2 }, +{ 0xBBA3, 0xBBA3, 0xBBA3 }, +{ 0xBBA4, 0xBBA4, 0xBBA4 }, +{ 0xBBA5, 0xBBA5, 0xBBA5 }, +{ 0xBBA6, 0xBBA6, 0xBBA6 }, +{ 0xBBA7, 0xBBA7, 0xBBA7 }, +{ 0xBBA8, 0xBBA8, 0xBBA8 }, +{ 0xBBA9, 0xBBA9, 0xBBA9 }, +{ 0xBBAA, 0xBBAA, 0xBBAA }, +{ 0xBBAB, 0xBBAB, 0xBBAB }, +{ 0xBBAC, 0xBBAC, 0xBBAC }, +{ 0xBBAD, 0xBBAD, 0xBBAD }, +{ 0xBBAE, 0xBBAE, 0xBBAE }, +{ 0xBBAF, 0xBBAF, 0xBBAF }, +{ 0xBBB0, 0xBBB0, 0xBBB0 }, +{ 0xBBB1, 0xBBB1, 0xBBB1 }, +{ 0xBBB2, 0xBBB2, 0xBBB2 }, +{ 0xBBB3, 0xBBB3, 0xBBB3 }, +{ 0xBBB4, 0xBBB4, 0xBBB4 }, +{ 0xBBB5, 0xBBB5, 0xBBB5 }, +{ 0xBBB6, 0xBBB6, 0xBBB6 }, +{ 0xBBB7, 0xBBB7, 0xBBB7 }, +{ 0xBBB8, 0xBBB8, 0xBBB8 }, +{ 0xBBB9, 0xBBB9, 0xBBB9 }, +{ 0xBBBA, 0xBBBA, 0xBBBA }, +{ 0xBBBB, 0xBBBB, 0xBBBB }, +{ 0xBBBC, 0xBBBC, 0xBBBC }, +{ 0xBBBD, 0xBBBD, 0xBBBD }, +{ 0xBBBE, 0xBBBE, 0xBBBE }, +{ 0xBBBF, 0xBBBF, 0xBBBF }, +{ 0xBBC0, 0xBBC0, 0xBBC0 }, +{ 0xBBC1, 0xBBC1, 0xBBC1 }, +{ 0xBBC2, 0xBBC2, 0xBBC2 }, +{ 0xBBC3, 0xBBC3, 0xBBC3 }, +{ 0xBBC4, 0xBBC4, 0xBBC4 }, +{ 0xBBC5, 0xBBC5, 0xBBC5 }, +{ 0xBBC6, 0xBBC6, 0xBBC6 }, +{ 0xBBC7, 0xBBC7, 0xBBC7 }, +{ 0xBBC8, 0xBBC8, 0xBBC8 }, +{ 0xBBC9, 0xBBC9, 0xBBC9 }, +{ 0xBBCA, 0xBBCA, 0xBBCA }, +{ 0xBBCB, 0xBBCB, 0xBBCB }, +{ 0xBBCC, 0xBBCC, 0xBBCC }, +{ 0xBBCD, 0xBBCD, 0xBBCD }, +{ 0xBBCE, 0xBBCE, 0xBBCE }, +{ 0xBBCF, 0xBBCF, 0xBBCF }, +{ 0xBBD0, 0xBBD0, 0xBBD0 }, +{ 0xBBD1, 0xBBD1, 0xBBD1 }, +{ 0xBBD2, 0xBBD2, 0xBBD2 }, +{ 0xBBD3, 0xBBD3, 0xBBD3 }, +{ 0xBBD4, 0xBBD4, 0xBBD4 }, +{ 0xBBD5, 0xBBD5, 0xBBD5 }, +{ 0xBBD6, 0xBBD6, 0xBBD6 }, +{ 0xBBD7, 0xBBD7, 0xBBD7 }, +{ 0xBBD8, 0xBBD8, 0xBBD8 }, +{ 0xBBD9, 0xBBD9, 0xBBD9 }, +{ 0xBBDA, 0xBBDA, 0xBBDA }, +{ 0xBBDB, 0xBBDB, 0xBBDB }, +{ 0xBBDC, 0xBBDC, 0xBBDC }, +{ 0xBBDD, 0xBBDD, 0xBBDD }, +{ 0xBBDE, 0xBBDE, 0xBBDE }, +{ 0xBBDF, 0xBBDF, 0xBBDF }, +{ 0xBBE0, 0xBBE0, 0xBBE0 }, +{ 0xBBE1, 0xBBE1, 0xBBE1 }, +{ 0xBBE2, 0xBBE2, 0xBBE2 }, +{ 0xBBE3, 0xBBE3, 0xBBE3 }, +{ 0xBBE4, 0xBBE4, 0xBBE4 }, +{ 0xBBE5, 0xBBE5, 0xBBE5 }, +{ 0xBBE6, 0xBBE6, 0xBBE6 }, +{ 0xBBE7, 0xBBE7, 0xBBE7 }, +{ 0xBBE8, 0xBBE8, 0xBBE8 }, +{ 0xBBE9, 0xBBE9, 0xBBE9 }, +{ 0xBBEA, 0xBBEA, 0xBBEA }, +{ 0xBBEB, 0xBBEB, 0xBBEB }, +{ 0xBBEC, 0xBBEC, 0xBBEC }, +{ 0xBBED, 0xBBED, 0xBBED }, +{ 0xBBEE, 0xBBEE, 0xBBEE }, +{ 0xBBEF, 0xBBEF, 0xBBEF }, +{ 0xBBF0, 0xBBF0, 0xBBF0 }, +{ 0xBBF1, 0xBBF1, 0xBBF1 }, +{ 0xBBF2, 0xBBF2, 0xBBF2 }, +{ 0xBBF3, 0xBBF3, 0xBBF3 }, +{ 0xBBF4, 0xBBF4, 0xBBF4 }, +{ 0xBBF5, 0xBBF5, 0xBBF5 }, +{ 0xBBF6, 0xBBF6, 0xBBF6 }, +{ 0xBBF7, 0xBBF7, 0xBBF7 }, +{ 0xBBF8, 0xBBF8, 0xBBF8 }, +{ 0xBBF9, 0xBBF9, 0xBBF9 }, +{ 0xBBFA, 0xBBFA, 0xBBFA }, +{ 0xBBFB, 0xBBFB, 0xBBFB }, +{ 0xBBFC, 0xBBFC, 0xBBFC }, +{ 0xBBFD, 0xBBFD, 0xBBFD }, +{ 0xBBFE, 0xBBFE, 0xBBFE }, +{ 0xBBFF, 0xBBFF, 0xBBFF }, +{ 0xBC00, 0xBC00, 0xBC00 }, +{ 0xBC01, 0xBC01, 0xBC01 }, +{ 0xBC02, 0xBC02, 0xBC02 }, +{ 0xBC03, 0xBC03, 0xBC03 }, +{ 0xBC04, 0xBC04, 0xBC04 }, +{ 0xBC05, 0xBC05, 0xBC05 }, +{ 0xBC06, 0xBC06, 0xBC06 }, +{ 0xBC07, 0xBC07, 0xBC07 }, +{ 0xBC08, 0xBC08, 0xBC08 }, +{ 0xBC09, 0xBC09, 0xBC09 }, +{ 0xBC0A, 0xBC0A, 0xBC0A }, +{ 0xBC0B, 0xBC0B, 0xBC0B }, +{ 0xBC0C, 0xBC0C, 0xBC0C }, +{ 0xBC0D, 0xBC0D, 0xBC0D }, +{ 0xBC0E, 0xBC0E, 0xBC0E }, +{ 0xBC0F, 0xBC0F, 0xBC0F }, +{ 0xBC10, 0xBC10, 0xBC10 }, +{ 0xBC11, 0xBC11, 0xBC11 }, +{ 0xBC12, 0xBC12, 0xBC12 }, +{ 0xBC13, 0xBC13, 0xBC13 }, +{ 0xBC14, 0xBC14, 0xBC14 }, +{ 0xBC15, 0xBC15, 0xBC15 }, +{ 0xBC16, 0xBC16, 0xBC16 }, +{ 0xBC17, 0xBC17, 0xBC17 }, +{ 0xBC18, 0xBC18, 0xBC18 }, +{ 0xBC19, 0xBC19, 0xBC19 }, +{ 0xBC1A, 0xBC1A, 0xBC1A }, +{ 0xBC1B, 0xBC1B, 0xBC1B }, +{ 0xBC1C, 0xBC1C, 0xBC1C }, +{ 0xBC1D, 0xBC1D, 0xBC1D }, +{ 0xBC1E, 0xBC1E, 0xBC1E }, +{ 0xBC1F, 0xBC1F, 0xBC1F }, +{ 0xBC20, 0xBC20, 0xBC20 }, +{ 0xBC21, 0xBC21, 0xBC21 }, +{ 0xBC22, 0xBC22, 0xBC22 }, +{ 0xBC23, 0xBC23, 0xBC23 }, +{ 0xBC24, 0xBC24, 0xBC24 }, +{ 0xBC25, 0xBC25, 0xBC25 }, +{ 0xBC26, 0xBC26, 0xBC26 }, +{ 0xBC27, 0xBC27, 0xBC27 }, +{ 0xBC28, 0xBC28, 0xBC28 }, +{ 0xBC29, 0xBC29, 0xBC29 }, +{ 0xBC2A, 0xBC2A, 0xBC2A }, +{ 0xBC2B, 0xBC2B, 0xBC2B }, +{ 0xBC2C, 0xBC2C, 0xBC2C }, +{ 0xBC2D, 0xBC2D, 0xBC2D }, +{ 0xBC2E, 0xBC2E, 0xBC2E }, +{ 0xBC2F, 0xBC2F, 0xBC2F }, +{ 0xBC30, 0xBC30, 0xBC30 }, +{ 0xBC31, 0xBC31, 0xBC31 }, +{ 0xBC32, 0xBC32, 0xBC32 }, +{ 0xBC33, 0xBC33, 0xBC33 }, +{ 0xBC34, 0xBC34, 0xBC34 }, +{ 0xBC35, 0xBC35, 0xBC35 }, +{ 0xBC36, 0xBC36, 0xBC36 }, +{ 0xBC37, 0xBC37, 0xBC37 }, +{ 0xBC38, 0xBC38, 0xBC38 }, +{ 0xBC39, 0xBC39, 0xBC39 }, +{ 0xBC3A, 0xBC3A, 0xBC3A }, +{ 0xBC3B, 0xBC3B, 0xBC3B }, +{ 0xBC3C, 0xBC3C, 0xBC3C }, +{ 0xBC3D, 0xBC3D, 0xBC3D }, +{ 0xBC3E, 0xBC3E, 0xBC3E }, +{ 0xBC3F, 0xBC3F, 0xBC3F }, +{ 0xBC40, 0xBC40, 0xBC40 }, +{ 0xBC41, 0xBC41, 0xBC41 }, +{ 0xBC42, 0xBC42, 0xBC42 }, +{ 0xBC43, 0xBC43, 0xBC43 }, +{ 0xBC44, 0xBC44, 0xBC44 }, +{ 0xBC45, 0xBC45, 0xBC45 }, +{ 0xBC46, 0xBC46, 0xBC46 }, +{ 0xBC47, 0xBC47, 0xBC47 }, +{ 0xBC48, 0xBC48, 0xBC48 }, +{ 0xBC49, 0xBC49, 0xBC49 }, +{ 0xBC4A, 0xBC4A, 0xBC4A }, +{ 0xBC4B, 0xBC4B, 0xBC4B }, +{ 0xBC4C, 0xBC4C, 0xBC4C }, +{ 0xBC4D, 0xBC4D, 0xBC4D }, +{ 0xBC4E, 0xBC4E, 0xBC4E }, +{ 0xBC4F, 0xBC4F, 0xBC4F }, +{ 0xBC50, 0xBC50, 0xBC50 }, +{ 0xBC51, 0xBC51, 0xBC51 }, +{ 0xBC52, 0xBC52, 0xBC52 }, +{ 0xBC53, 0xBC53, 0xBC53 }, +{ 0xBC54, 0xBC54, 0xBC54 }, +{ 0xBC55, 0xBC55, 0xBC55 }, +{ 0xBC56, 0xBC56, 0xBC56 }, +{ 0xBC57, 0xBC57, 0xBC57 }, +{ 0xBC58, 0xBC58, 0xBC58 }, +{ 0xBC59, 0xBC59, 0xBC59 }, +{ 0xBC5A, 0xBC5A, 0xBC5A }, +{ 0xBC5B, 0xBC5B, 0xBC5B }, +{ 0xBC5C, 0xBC5C, 0xBC5C }, +{ 0xBC5D, 0xBC5D, 0xBC5D }, +{ 0xBC5E, 0xBC5E, 0xBC5E }, +{ 0xBC5F, 0xBC5F, 0xBC5F }, +{ 0xBC60, 0xBC60, 0xBC60 }, +{ 0xBC61, 0xBC61, 0xBC61 }, +{ 0xBC62, 0xBC62, 0xBC62 }, +{ 0xBC63, 0xBC63, 0xBC63 }, +{ 0xBC64, 0xBC64, 0xBC64 }, +{ 0xBC65, 0xBC65, 0xBC65 }, +{ 0xBC66, 0xBC66, 0xBC66 }, +{ 0xBC67, 0xBC67, 0xBC67 }, +{ 0xBC68, 0xBC68, 0xBC68 }, +{ 0xBC69, 0xBC69, 0xBC69 }, +{ 0xBC6A, 0xBC6A, 0xBC6A }, +{ 0xBC6B, 0xBC6B, 0xBC6B }, +{ 0xBC6C, 0xBC6C, 0xBC6C }, +{ 0xBC6D, 0xBC6D, 0xBC6D }, +{ 0xBC6E, 0xBC6E, 0xBC6E }, +{ 0xBC6F, 0xBC6F, 0xBC6F }, +{ 0xBC70, 0xBC70, 0xBC70 }, +{ 0xBC71, 0xBC71, 0xBC71 }, +{ 0xBC72, 0xBC72, 0xBC72 }, +{ 0xBC73, 0xBC73, 0xBC73 }, +{ 0xBC74, 0xBC74, 0xBC74 }, +{ 0xBC75, 0xBC75, 0xBC75 }, +{ 0xBC76, 0xBC76, 0xBC76 }, +{ 0xBC77, 0xBC77, 0xBC77 }, +{ 0xBC78, 0xBC78, 0xBC78 }, +{ 0xBC79, 0xBC79, 0xBC79 }, +{ 0xBC7A, 0xBC7A, 0xBC7A }, +{ 0xBC7B, 0xBC7B, 0xBC7B }, +{ 0xBC7C, 0xBC7C, 0xBC7C }, +{ 0xBC7D, 0xBC7D, 0xBC7D }, +{ 0xBC7E, 0xBC7E, 0xBC7E }, +{ 0xBC7F, 0xBC7F, 0xBC7F }, +{ 0xBC80, 0xBC80, 0xBC80 }, +{ 0xBC81, 0xBC81, 0xBC81 }, +{ 0xBC82, 0xBC82, 0xBC82 }, +{ 0xBC83, 0xBC83, 0xBC83 }, +{ 0xBC84, 0xBC84, 0xBC84 }, +{ 0xBC85, 0xBC85, 0xBC85 }, +{ 0xBC86, 0xBC86, 0xBC86 }, +{ 0xBC87, 0xBC87, 0xBC87 }, +{ 0xBC88, 0xBC88, 0xBC88 }, +{ 0xBC89, 0xBC89, 0xBC89 }, +{ 0xBC8A, 0xBC8A, 0xBC8A }, +{ 0xBC8B, 0xBC8B, 0xBC8B }, +{ 0xBC8C, 0xBC8C, 0xBC8C }, +{ 0xBC8D, 0xBC8D, 0xBC8D }, +{ 0xBC8E, 0xBC8E, 0xBC8E }, +{ 0xBC8F, 0xBC8F, 0xBC8F }, +{ 0xBC90, 0xBC90, 0xBC90 }, +{ 0xBC91, 0xBC91, 0xBC91 }, +{ 0xBC92, 0xBC92, 0xBC92 }, +{ 0xBC93, 0xBC93, 0xBC93 }, +{ 0xBC94, 0xBC94, 0xBC94 }, +{ 0xBC95, 0xBC95, 0xBC95 }, +{ 0xBC96, 0xBC96, 0xBC96 }, +{ 0xBC97, 0xBC97, 0xBC97 }, +{ 0xBC98, 0xBC98, 0xBC98 }, +{ 0xBC99, 0xBC99, 0xBC99 }, +{ 0xBC9A, 0xBC9A, 0xBC9A }, +{ 0xBC9B, 0xBC9B, 0xBC9B }, +{ 0xBC9C, 0xBC9C, 0xBC9C }, +{ 0xBC9D, 0xBC9D, 0xBC9D }, +{ 0xBC9E, 0xBC9E, 0xBC9E }, +{ 0xBC9F, 0xBC9F, 0xBC9F }, +{ 0xBCA0, 0xBCA0, 0xBCA0 }, +{ 0xBCA1, 0xBCA1, 0xBCA1 }, +{ 0xBCA2, 0xBCA2, 0xBCA2 }, +{ 0xBCA3, 0xBCA3, 0xBCA3 }, +{ 0xBCA4, 0xBCA4, 0xBCA4 }, +{ 0xBCA5, 0xBCA5, 0xBCA5 }, +{ 0xBCA6, 0xBCA6, 0xBCA6 }, +{ 0xBCA7, 0xBCA7, 0xBCA7 }, +{ 0xBCA8, 0xBCA8, 0xBCA8 }, +{ 0xBCA9, 0xBCA9, 0xBCA9 }, +{ 0xBCAA, 0xBCAA, 0xBCAA }, +{ 0xBCAB, 0xBCAB, 0xBCAB }, +{ 0xBCAC, 0xBCAC, 0xBCAC }, +{ 0xBCAD, 0xBCAD, 0xBCAD }, +{ 0xBCAE, 0xBCAE, 0xBCAE }, +{ 0xBCAF, 0xBCAF, 0xBCAF }, +{ 0xBCB0, 0xBCB0, 0xBCB0 }, +{ 0xBCB1, 0xBCB1, 0xBCB1 }, +{ 0xBCB2, 0xBCB2, 0xBCB2 }, +{ 0xBCB3, 0xBCB3, 0xBCB3 }, +{ 0xBCB4, 0xBCB4, 0xBCB4 }, +{ 0xBCB5, 0xBCB5, 0xBCB5 }, +{ 0xBCB6, 0xBCB6, 0xBCB6 }, +{ 0xBCB7, 0xBCB7, 0xBCB7 }, +{ 0xBCB8, 0xBCB8, 0xBCB8 }, +{ 0xBCB9, 0xBCB9, 0xBCB9 }, +{ 0xBCBA, 0xBCBA, 0xBCBA }, +{ 0xBCBB, 0xBCBB, 0xBCBB }, +{ 0xBCBC, 0xBCBC, 0xBCBC }, +{ 0xBCBD, 0xBCBD, 0xBCBD }, +{ 0xBCBE, 0xBCBE, 0xBCBE }, +{ 0xBCBF, 0xBCBF, 0xBCBF }, +{ 0xBCC0, 0xBCC0, 0xBCC0 }, +{ 0xBCC1, 0xBCC1, 0xBCC1 }, +{ 0xBCC2, 0xBCC2, 0xBCC2 }, +{ 0xBCC3, 0xBCC3, 0xBCC3 }, +{ 0xBCC4, 0xBCC4, 0xBCC4 }, +{ 0xBCC5, 0xBCC5, 0xBCC5 }, +{ 0xBCC6, 0xBCC6, 0xBCC6 }, +{ 0xBCC7, 0xBCC7, 0xBCC7 }, +{ 0xBCC8, 0xBCC8, 0xBCC8 }, +{ 0xBCC9, 0xBCC9, 0xBCC9 }, +{ 0xBCCA, 0xBCCA, 0xBCCA }, +{ 0xBCCB, 0xBCCB, 0xBCCB }, +{ 0xBCCC, 0xBCCC, 0xBCCC }, +{ 0xBCCD, 0xBCCD, 0xBCCD }, +{ 0xBCCE, 0xBCCE, 0xBCCE }, +{ 0xBCCF, 0xBCCF, 0xBCCF }, +{ 0xBCD0, 0xBCD0, 0xBCD0 }, +{ 0xBCD1, 0xBCD1, 0xBCD1 }, +{ 0xBCD2, 0xBCD2, 0xBCD2 }, +{ 0xBCD3, 0xBCD3, 0xBCD3 }, +{ 0xBCD4, 0xBCD4, 0xBCD4 }, +{ 0xBCD5, 0xBCD5, 0xBCD5 }, +{ 0xBCD6, 0xBCD6, 0xBCD6 }, +{ 0xBCD7, 0xBCD7, 0xBCD7 }, +{ 0xBCD8, 0xBCD8, 0xBCD8 }, +{ 0xBCD9, 0xBCD9, 0xBCD9 }, +{ 0xBCDA, 0xBCDA, 0xBCDA }, +{ 0xBCDB, 0xBCDB, 0xBCDB }, +{ 0xBCDC, 0xBCDC, 0xBCDC }, +{ 0xBCDD, 0xBCDD, 0xBCDD }, +{ 0xBCDE, 0xBCDE, 0xBCDE }, +{ 0xBCDF, 0xBCDF, 0xBCDF }, +{ 0xBCE0, 0xBCE0, 0xBCE0 }, +{ 0xBCE1, 0xBCE1, 0xBCE1 }, +{ 0xBCE2, 0xBCE2, 0xBCE2 }, +{ 0xBCE3, 0xBCE3, 0xBCE3 }, +{ 0xBCE4, 0xBCE4, 0xBCE4 }, +{ 0xBCE5, 0xBCE5, 0xBCE5 }, +{ 0xBCE6, 0xBCE6, 0xBCE6 }, +{ 0xBCE7, 0xBCE7, 0xBCE7 }, +{ 0xBCE8, 0xBCE8, 0xBCE8 }, +{ 0xBCE9, 0xBCE9, 0xBCE9 }, +{ 0xBCEA, 0xBCEA, 0xBCEA }, +{ 0xBCEB, 0xBCEB, 0xBCEB }, +{ 0xBCEC, 0xBCEC, 0xBCEC }, +{ 0xBCED, 0xBCED, 0xBCED }, +{ 0xBCEE, 0xBCEE, 0xBCEE }, +{ 0xBCEF, 0xBCEF, 0xBCEF }, +{ 0xBCF0, 0xBCF0, 0xBCF0 }, +{ 0xBCF1, 0xBCF1, 0xBCF1 }, +{ 0xBCF2, 0xBCF2, 0xBCF2 }, +{ 0xBCF3, 0xBCF3, 0xBCF3 }, +{ 0xBCF4, 0xBCF4, 0xBCF4 }, +{ 0xBCF5, 0xBCF5, 0xBCF5 }, +{ 0xBCF6, 0xBCF6, 0xBCF6 }, +{ 0xBCF7, 0xBCF7, 0xBCF7 }, +{ 0xBCF8, 0xBCF8, 0xBCF8 }, +{ 0xBCF9, 0xBCF9, 0xBCF9 }, +{ 0xBCFA, 0xBCFA, 0xBCFA }, +{ 0xBCFB, 0xBCFB, 0xBCFB }, +{ 0xBCFC, 0xBCFC, 0xBCFC }, +{ 0xBCFD, 0xBCFD, 0xBCFD }, +{ 0xBCFE, 0xBCFE, 0xBCFE }, +{ 0xBCFF, 0xBCFF, 0xBCFF }, +{ 0xBD00, 0xBD00, 0xBD00 }, +{ 0xBD01, 0xBD01, 0xBD01 }, +{ 0xBD02, 0xBD02, 0xBD02 }, +{ 0xBD03, 0xBD03, 0xBD03 }, +{ 0xBD04, 0xBD04, 0xBD04 }, +{ 0xBD05, 0xBD05, 0xBD05 }, +{ 0xBD06, 0xBD06, 0xBD06 }, +{ 0xBD07, 0xBD07, 0xBD07 }, +{ 0xBD08, 0xBD08, 0xBD08 }, +{ 0xBD09, 0xBD09, 0xBD09 }, +{ 0xBD0A, 0xBD0A, 0xBD0A }, +{ 0xBD0B, 0xBD0B, 0xBD0B }, +{ 0xBD0C, 0xBD0C, 0xBD0C }, +{ 0xBD0D, 0xBD0D, 0xBD0D }, +{ 0xBD0E, 0xBD0E, 0xBD0E }, +{ 0xBD0F, 0xBD0F, 0xBD0F }, +{ 0xBD10, 0xBD10, 0xBD10 }, +{ 0xBD11, 0xBD11, 0xBD11 }, +{ 0xBD12, 0xBD12, 0xBD12 }, +{ 0xBD13, 0xBD13, 0xBD13 }, +{ 0xBD14, 0xBD14, 0xBD14 }, +{ 0xBD15, 0xBD15, 0xBD15 }, +{ 0xBD16, 0xBD16, 0xBD16 }, +{ 0xBD17, 0xBD17, 0xBD17 }, +{ 0xBD18, 0xBD18, 0xBD18 }, +{ 0xBD19, 0xBD19, 0xBD19 }, +{ 0xBD1A, 0xBD1A, 0xBD1A }, +{ 0xBD1B, 0xBD1B, 0xBD1B }, +{ 0xBD1C, 0xBD1C, 0xBD1C }, +{ 0xBD1D, 0xBD1D, 0xBD1D }, +{ 0xBD1E, 0xBD1E, 0xBD1E }, +{ 0xBD1F, 0xBD1F, 0xBD1F }, +{ 0xBD20, 0xBD20, 0xBD20 }, +{ 0xBD21, 0xBD21, 0xBD21 }, +{ 0xBD22, 0xBD22, 0xBD22 }, +{ 0xBD23, 0xBD23, 0xBD23 }, +{ 0xBD24, 0xBD24, 0xBD24 }, +{ 0xBD25, 0xBD25, 0xBD25 }, +{ 0xBD26, 0xBD26, 0xBD26 }, +{ 0xBD27, 0xBD27, 0xBD27 }, +{ 0xBD28, 0xBD28, 0xBD28 }, +{ 0xBD29, 0xBD29, 0xBD29 }, +{ 0xBD2A, 0xBD2A, 0xBD2A }, +{ 0xBD2B, 0xBD2B, 0xBD2B }, +{ 0xBD2C, 0xBD2C, 0xBD2C }, +{ 0xBD2D, 0xBD2D, 0xBD2D }, +{ 0xBD2E, 0xBD2E, 0xBD2E }, +{ 0xBD2F, 0xBD2F, 0xBD2F }, +{ 0xBD30, 0xBD30, 0xBD30 }, +{ 0xBD31, 0xBD31, 0xBD31 }, +{ 0xBD32, 0xBD32, 0xBD32 }, +{ 0xBD33, 0xBD33, 0xBD33 }, +{ 0xBD34, 0xBD34, 0xBD34 }, +{ 0xBD35, 0xBD35, 0xBD35 }, +{ 0xBD36, 0xBD36, 0xBD36 }, +{ 0xBD37, 0xBD37, 0xBD37 }, +{ 0xBD38, 0xBD38, 0xBD38 }, +{ 0xBD39, 0xBD39, 0xBD39 }, +{ 0xBD3A, 0xBD3A, 0xBD3A }, +{ 0xBD3B, 0xBD3B, 0xBD3B }, +{ 0xBD3C, 0xBD3C, 0xBD3C }, +{ 0xBD3D, 0xBD3D, 0xBD3D }, +{ 0xBD3E, 0xBD3E, 0xBD3E }, +{ 0xBD3F, 0xBD3F, 0xBD3F }, +{ 0xBD40, 0xBD40, 0xBD40 }, +{ 0xBD41, 0xBD41, 0xBD41 }, +{ 0xBD42, 0xBD42, 0xBD42 }, +{ 0xBD43, 0xBD43, 0xBD43 }, +{ 0xBD44, 0xBD44, 0xBD44 }, +{ 0xBD45, 0xBD45, 0xBD45 }, +{ 0xBD46, 0xBD46, 0xBD46 }, +{ 0xBD47, 0xBD47, 0xBD47 }, +{ 0xBD48, 0xBD48, 0xBD48 }, +{ 0xBD49, 0xBD49, 0xBD49 }, +{ 0xBD4A, 0xBD4A, 0xBD4A }, +{ 0xBD4B, 0xBD4B, 0xBD4B }, +{ 0xBD4C, 0xBD4C, 0xBD4C }, +{ 0xBD4D, 0xBD4D, 0xBD4D }, +{ 0xBD4E, 0xBD4E, 0xBD4E }, +{ 0xBD4F, 0xBD4F, 0xBD4F }, +{ 0xBD50, 0xBD50, 0xBD50 }, +{ 0xBD51, 0xBD51, 0xBD51 }, +{ 0xBD52, 0xBD52, 0xBD52 }, +{ 0xBD53, 0xBD53, 0xBD53 }, +{ 0xBD54, 0xBD54, 0xBD54 }, +{ 0xBD55, 0xBD55, 0xBD55 }, +{ 0xBD56, 0xBD56, 0xBD56 }, +{ 0xBD57, 0xBD57, 0xBD57 }, +{ 0xBD58, 0xBD58, 0xBD58 }, +{ 0xBD59, 0xBD59, 0xBD59 }, +{ 0xBD5A, 0xBD5A, 0xBD5A }, +{ 0xBD5B, 0xBD5B, 0xBD5B }, +{ 0xBD5C, 0xBD5C, 0xBD5C }, +{ 0xBD5D, 0xBD5D, 0xBD5D }, +{ 0xBD5E, 0xBD5E, 0xBD5E }, +{ 0xBD5F, 0xBD5F, 0xBD5F }, +{ 0xBD60, 0xBD60, 0xBD60 }, +{ 0xBD61, 0xBD61, 0xBD61 }, +{ 0xBD62, 0xBD62, 0xBD62 }, +{ 0xBD63, 0xBD63, 0xBD63 }, +{ 0xBD64, 0xBD64, 0xBD64 }, +{ 0xBD65, 0xBD65, 0xBD65 }, +{ 0xBD66, 0xBD66, 0xBD66 }, +{ 0xBD67, 0xBD67, 0xBD67 }, +{ 0xBD68, 0xBD68, 0xBD68 }, +{ 0xBD69, 0xBD69, 0xBD69 }, +{ 0xBD6A, 0xBD6A, 0xBD6A }, +{ 0xBD6B, 0xBD6B, 0xBD6B }, +{ 0xBD6C, 0xBD6C, 0xBD6C }, +{ 0xBD6D, 0xBD6D, 0xBD6D }, +{ 0xBD6E, 0xBD6E, 0xBD6E }, +{ 0xBD6F, 0xBD6F, 0xBD6F }, +{ 0xBD70, 0xBD70, 0xBD70 }, +{ 0xBD71, 0xBD71, 0xBD71 }, +{ 0xBD72, 0xBD72, 0xBD72 }, +{ 0xBD73, 0xBD73, 0xBD73 }, +{ 0xBD74, 0xBD74, 0xBD74 }, +{ 0xBD75, 0xBD75, 0xBD75 }, +{ 0xBD76, 0xBD76, 0xBD76 }, +{ 0xBD77, 0xBD77, 0xBD77 }, +{ 0xBD78, 0xBD78, 0xBD78 }, +{ 0xBD79, 0xBD79, 0xBD79 }, +{ 0xBD7A, 0xBD7A, 0xBD7A }, +{ 0xBD7B, 0xBD7B, 0xBD7B }, +{ 0xBD7C, 0xBD7C, 0xBD7C }, +{ 0xBD7D, 0xBD7D, 0xBD7D }, +{ 0xBD7E, 0xBD7E, 0xBD7E }, +{ 0xBD7F, 0xBD7F, 0xBD7F }, +{ 0xBD80, 0xBD80, 0xBD80 }, +{ 0xBD81, 0xBD81, 0xBD81 }, +{ 0xBD82, 0xBD82, 0xBD82 }, +{ 0xBD83, 0xBD83, 0xBD83 }, +{ 0xBD84, 0xBD84, 0xBD84 }, +{ 0xBD85, 0xBD85, 0xBD85 }, +{ 0xBD86, 0xBD86, 0xBD86 }, +{ 0xBD87, 0xBD87, 0xBD87 }, +{ 0xBD88, 0xBD88, 0xBD88 }, +{ 0xBD89, 0xBD89, 0xBD89 }, +{ 0xBD8A, 0xBD8A, 0xBD8A }, +{ 0xBD8B, 0xBD8B, 0xBD8B }, +{ 0xBD8C, 0xBD8C, 0xBD8C }, +{ 0xBD8D, 0xBD8D, 0xBD8D }, +{ 0xBD8E, 0xBD8E, 0xBD8E }, +{ 0xBD8F, 0xBD8F, 0xBD8F }, +{ 0xBD90, 0xBD90, 0xBD90 }, +{ 0xBD91, 0xBD91, 0xBD91 }, +{ 0xBD92, 0xBD92, 0xBD92 }, +{ 0xBD93, 0xBD93, 0xBD93 }, +{ 0xBD94, 0xBD94, 0xBD94 }, +{ 0xBD95, 0xBD95, 0xBD95 }, +{ 0xBD96, 0xBD96, 0xBD96 }, +{ 0xBD97, 0xBD97, 0xBD97 }, +{ 0xBD98, 0xBD98, 0xBD98 }, +{ 0xBD99, 0xBD99, 0xBD99 }, +{ 0xBD9A, 0xBD9A, 0xBD9A }, +{ 0xBD9B, 0xBD9B, 0xBD9B }, +{ 0xBD9C, 0xBD9C, 0xBD9C }, +{ 0xBD9D, 0xBD9D, 0xBD9D }, +{ 0xBD9E, 0xBD9E, 0xBD9E }, +{ 0xBD9F, 0xBD9F, 0xBD9F }, +{ 0xBDA0, 0xBDA0, 0xBDA0 }, +{ 0xBDA1, 0xBDA1, 0xBDA1 }, +{ 0xBDA2, 0xBDA2, 0xBDA2 }, +{ 0xBDA3, 0xBDA3, 0xBDA3 }, +{ 0xBDA4, 0xBDA4, 0xBDA4 }, +{ 0xBDA5, 0xBDA5, 0xBDA5 }, +{ 0xBDA6, 0xBDA6, 0xBDA6 }, +{ 0xBDA7, 0xBDA7, 0xBDA7 }, +{ 0xBDA8, 0xBDA8, 0xBDA8 }, +{ 0xBDA9, 0xBDA9, 0xBDA9 }, +{ 0xBDAA, 0xBDAA, 0xBDAA }, +{ 0xBDAB, 0xBDAB, 0xBDAB }, +{ 0xBDAC, 0xBDAC, 0xBDAC }, +{ 0xBDAD, 0xBDAD, 0xBDAD }, +{ 0xBDAE, 0xBDAE, 0xBDAE }, +{ 0xBDAF, 0xBDAF, 0xBDAF }, +{ 0xBDB0, 0xBDB0, 0xBDB0 }, +{ 0xBDB1, 0xBDB1, 0xBDB1 }, +{ 0xBDB2, 0xBDB2, 0xBDB2 }, +{ 0xBDB3, 0xBDB3, 0xBDB3 }, +{ 0xBDB4, 0xBDB4, 0xBDB4 }, +{ 0xBDB5, 0xBDB5, 0xBDB5 }, +{ 0xBDB6, 0xBDB6, 0xBDB6 }, +{ 0xBDB7, 0xBDB7, 0xBDB7 }, +{ 0xBDB8, 0xBDB8, 0xBDB8 }, +{ 0xBDB9, 0xBDB9, 0xBDB9 }, +{ 0xBDBA, 0xBDBA, 0xBDBA }, +{ 0xBDBB, 0xBDBB, 0xBDBB }, +{ 0xBDBC, 0xBDBC, 0xBDBC }, +{ 0xBDBD, 0xBDBD, 0xBDBD }, +{ 0xBDBE, 0xBDBE, 0xBDBE }, +{ 0xBDBF, 0xBDBF, 0xBDBF }, +{ 0xBDC0, 0xBDC0, 0xBDC0 }, +{ 0xBDC1, 0xBDC1, 0xBDC1 }, +{ 0xBDC2, 0xBDC2, 0xBDC2 }, +{ 0xBDC3, 0xBDC3, 0xBDC3 }, +{ 0xBDC4, 0xBDC4, 0xBDC4 }, +{ 0xBDC5, 0xBDC5, 0xBDC5 }, +{ 0xBDC6, 0xBDC6, 0xBDC6 }, +{ 0xBDC7, 0xBDC7, 0xBDC7 }, +{ 0xBDC8, 0xBDC8, 0xBDC8 }, +{ 0xBDC9, 0xBDC9, 0xBDC9 }, +{ 0xBDCA, 0xBDCA, 0xBDCA }, +{ 0xBDCB, 0xBDCB, 0xBDCB }, +{ 0xBDCC, 0xBDCC, 0xBDCC }, +{ 0xBDCD, 0xBDCD, 0xBDCD }, +{ 0xBDCE, 0xBDCE, 0xBDCE }, +{ 0xBDCF, 0xBDCF, 0xBDCF }, +{ 0xBDD0, 0xBDD0, 0xBDD0 }, +{ 0xBDD1, 0xBDD1, 0xBDD1 }, +{ 0xBDD2, 0xBDD2, 0xBDD2 }, +{ 0xBDD3, 0xBDD3, 0xBDD3 }, +{ 0xBDD4, 0xBDD4, 0xBDD4 }, +{ 0xBDD5, 0xBDD5, 0xBDD5 }, +{ 0xBDD6, 0xBDD6, 0xBDD6 }, +{ 0xBDD7, 0xBDD7, 0xBDD7 }, +{ 0xBDD8, 0xBDD8, 0xBDD8 }, +{ 0xBDD9, 0xBDD9, 0xBDD9 }, +{ 0xBDDA, 0xBDDA, 0xBDDA }, +{ 0xBDDB, 0xBDDB, 0xBDDB }, +{ 0xBDDC, 0xBDDC, 0xBDDC }, +{ 0xBDDD, 0xBDDD, 0xBDDD }, +{ 0xBDDE, 0xBDDE, 0xBDDE }, +{ 0xBDDF, 0xBDDF, 0xBDDF }, +{ 0xBDE0, 0xBDE0, 0xBDE0 }, +{ 0xBDE1, 0xBDE1, 0xBDE1 }, +{ 0xBDE2, 0xBDE2, 0xBDE2 }, +{ 0xBDE3, 0xBDE3, 0xBDE3 }, +{ 0xBDE4, 0xBDE4, 0xBDE4 }, +{ 0xBDE5, 0xBDE5, 0xBDE5 }, +{ 0xBDE6, 0xBDE6, 0xBDE6 }, +{ 0xBDE7, 0xBDE7, 0xBDE7 }, +{ 0xBDE8, 0xBDE8, 0xBDE8 }, +{ 0xBDE9, 0xBDE9, 0xBDE9 }, +{ 0xBDEA, 0xBDEA, 0xBDEA }, +{ 0xBDEB, 0xBDEB, 0xBDEB }, +{ 0xBDEC, 0xBDEC, 0xBDEC }, +{ 0xBDED, 0xBDED, 0xBDED }, +{ 0xBDEE, 0xBDEE, 0xBDEE }, +{ 0xBDEF, 0xBDEF, 0xBDEF }, +{ 0xBDF0, 0xBDF0, 0xBDF0 }, +{ 0xBDF1, 0xBDF1, 0xBDF1 }, +{ 0xBDF2, 0xBDF2, 0xBDF2 }, +{ 0xBDF3, 0xBDF3, 0xBDF3 }, +{ 0xBDF4, 0xBDF4, 0xBDF4 }, +{ 0xBDF5, 0xBDF5, 0xBDF5 }, +{ 0xBDF6, 0xBDF6, 0xBDF6 }, +{ 0xBDF7, 0xBDF7, 0xBDF7 }, +{ 0xBDF8, 0xBDF8, 0xBDF8 }, +{ 0xBDF9, 0xBDF9, 0xBDF9 }, +{ 0xBDFA, 0xBDFA, 0xBDFA }, +{ 0xBDFB, 0xBDFB, 0xBDFB }, +{ 0xBDFC, 0xBDFC, 0xBDFC }, +{ 0xBDFD, 0xBDFD, 0xBDFD }, +{ 0xBDFE, 0xBDFE, 0xBDFE }, +{ 0xBDFF, 0xBDFF, 0xBDFF }, +{ 0xBE00, 0xBE00, 0xBE00 }, +{ 0xBE01, 0xBE01, 0xBE01 }, +{ 0xBE02, 0xBE02, 0xBE02 }, +{ 0xBE03, 0xBE03, 0xBE03 }, +{ 0xBE04, 0xBE04, 0xBE04 }, +{ 0xBE05, 0xBE05, 0xBE05 }, +{ 0xBE06, 0xBE06, 0xBE06 }, +{ 0xBE07, 0xBE07, 0xBE07 }, +{ 0xBE08, 0xBE08, 0xBE08 }, +{ 0xBE09, 0xBE09, 0xBE09 }, +{ 0xBE0A, 0xBE0A, 0xBE0A }, +{ 0xBE0B, 0xBE0B, 0xBE0B }, +{ 0xBE0C, 0xBE0C, 0xBE0C }, +{ 0xBE0D, 0xBE0D, 0xBE0D }, +{ 0xBE0E, 0xBE0E, 0xBE0E }, +{ 0xBE0F, 0xBE0F, 0xBE0F }, +{ 0xBE10, 0xBE10, 0xBE10 }, +{ 0xBE11, 0xBE11, 0xBE11 }, +{ 0xBE12, 0xBE12, 0xBE12 }, +{ 0xBE13, 0xBE13, 0xBE13 }, +{ 0xBE14, 0xBE14, 0xBE14 }, +{ 0xBE15, 0xBE15, 0xBE15 }, +{ 0xBE16, 0xBE16, 0xBE16 }, +{ 0xBE17, 0xBE17, 0xBE17 }, +{ 0xBE18, 0xBE18, 0xBE18 }, +{ 0xBE19, 0xBE19, 0xBE19 }, +{ 0xBE1A, 0xBE1A, 0xBE1A }, +{ 0xBE1B, 0xBE1B, 0xBE1B }, +{ 0xBE1C, 0xBE1C, 0xBE1C }, +{ 0xBE1D, 0xBE1D, 0xBE1D }, +{ 0xBE1E, 0xBE1E, 0xBE1E }, +{ 0xBE1F, 0xBE1F, 0xBE1F }, +{ 0xBE20, 0xBE20, 0xBE20 }, +{ 0xBE21, 0xBE21, 0xBE21 }, +{ 0xBE22, 0xBE22, 0xBE22 }, +{ 0xBE23, 0xBE23, 0xBE23 }, +{ 0xBE24, 0xBE24, 0xBE24 }, +{ 0xBE25, 0xBE25, 0xBE25 }, +{ 0xBE26, 0xBE26, 0xBE26 }, +{ 0xBE27, 0xBE27, 0xBE27 }, +{ 0xBE28, 0xBE28, 0xBE28 }, +{ 0xBE29, 0xBE29, 0xBE29 }, +{ 0xBE2A, 0xBE2A, 0xBE2A }, +{ 0xBE2B, 0xBE2B, 0xBE2B }, +{ 0xBE2C, 0xBE2C, 0xBE2C }, +{ 0xBE2D, 0xBE2D, 0xBE2D }, +{ 0xBE2E, 0xBE2E, 0xBE2E }, +{ 0xBE2F, 0xBE2F, 0xBE2F }, +{ 0xBE30, 0xBE30, 0xBE30 }, +{ 0xBE31, 0xBE31, 0xBE31 }, +{ 0xBE32, 0xBE32, 0xBE32 }, +{ 0xBE33, 0xBE33, 0xBE33 }, +{ 0xBE34, 0xBE34, 0xBE34 }, +{ 0xBE35, 0xBE35, 0xBE35 }, +{ 0xBE36, 0xBE36, 0xBE36 }, +{ 0xBE37, 0xBE37, 0xBE37 }, +{ 0xBE38, 0xBE38, 0xBE38 }, +{ 0xBE39, 0xBE39, 0xBE39 }, +{ 0xBE3A, 0xBE3A, 0xBE3A }, +{ 0xBE3B, 0xBE3B, 0xBE3B }, +{ 0xBE3C, 0xBE3C, 0xBE3C }, +{ 0xBE3D, 0xBE3D, 0xBE3D }, +{ 0xBE3E, 0xBE3E, 0xBE3E }, +{ 0xBE3F, 0xBE3F, 0xBE3F }, +{ 0xBE40, 0xBE40, 0xBE40 }, +{ 0xBE41, 0xBE41, 0xBE41 }, +{ 0xBE42, 0xBE42, 0xBE42 }, +{ 0xBE43, 0xBE43, 0xBE43 }, +{ 0xBE44, 0xBE44, 0xBE44 }, +{ 0xBE45, 0xBE45, 0xBE45 }, +{ 0xBE46, 0xBE46, 0xBE46 }, +{ 0xBE47, 0xBE47, 0xBE47 }, +{ 0xBE48, 0xBE48, 0xBE48 }, +{ 0xBE49, 0xBE49, 0xBE49 }, +{ 0xBE4A, 0xBE4A, 0xBE4A }, +{ 0xBE4B, 0xBE4B, 0xBE4B }, +{ 0xBE4C, 0xBE4C, 0xBE4C }, +{ 0xBE4D, 0xBE4D, 0xBE4D }, +{ 0xBE4E, 0xBE4E, 0xBE4E }, +{ 0xBE4F, 0xBE4F, 0xBE4F }, +{ 0xBE50, 0xBE50, 0xBE50 }, +{ 0xBE51, 0xBE51, 0xBE51 }, +{ 0xBE52, 0xBE52, 0xBE52 }, +{ 0xBE53, 0xBE53, 0xBE53 }, +{ 0xBE54, 0xBE54, 0xBE54 }, +{ 0xBE55, 0xBE55, 0xBE55 }, +{ 0xBE56, 0xBE56, 0xBE56 }, +{ 0xBE57, 0xBE57, 0xBE57 }, +{ 0xBE58, 0xBE58, 0xBE58 }, +{ 0xBE59, 0xBE59, 0xBE59 }, +{ 0xBE5A, 0xBE5A, 0xBE5A }, +{ 0xBE5B, 0xBE5B, 0xBE5B }, +{ 0xBE5C, 0xBE5C, 0xBE5C }, +{ 0xBE5D, 0xBE5D, 0xBE5D }, +{ 0xBE5E, 0xBE5E, 0xBE5E }, +{ 0xBE5F, 0xBE5F, 0xBE5F }, +{ 0xBE60, 0xBE60, 0xBE60 }, +{ 0xBE61, 0xBE61, 0xBE61 }, +{ 0xBE62, 0xBE62, 0xBE62 }, +{ 0xBE63, 0xBE63, 0xBE63 }, +{ 0xBE64, 0xBE64, 0xBE64 }, +{ 0xBE65, 0xBE65, 0xBE65 }, +{ 0xBE66, 0xBE66, 0xBE66 }, +{ 0xBE67, 0xBE67, 0xBE67 }, +{ 0xBE68, 0xBE68, 0xBE68 }, +{ 0xBE69, 0xBE69, 0xBE69 }, +{ 0xBE6A, 0xBE6A, 0xBE6A }, +{ 0xBE6B, 0xBE6B, 0xBE6B }, +{ 0xBE6C, 0xBE6C, 0xBE6C }, +{ 0xBE6D, 0xBE6D, 0xBE6D }, +{ 0xBE6E, 0xBE6E, 0xBE6E }, +{ 0xBE6F, 0xBE6F, 0xBE6F }, +{ 0xBE70, 0xBE70, 0xBE70 }, +{ 0xBE71, 0xBE71, 0xBE71 }, +{ 0xBE72, 0xBE72, 0xBE72 }, +{ 0xBE73, 0xBE73, 0xBE73 }, +{ 0xBE74, 0xBE74, 0xBE74 }, +{ 0xBE75, 0xBE75, 0xBE75 }, +{ 0xBE76, 0xBE76, 0xBE76 }, +{ 0xBE77, 0xBE77, 0xBE77 }, +{ 0xBE78, 0xBE78, 0xBE78 }, +{ 0xBE79, 0xBE79, 0xBE79 }, +{ 0xBE7A, 0xBE7A, 0xBE7A }, +{ 0xBE7B, 0xBE7B, 0xBE7B }, +{ 0xBE7C, 0xBE7C, 0xBE7C }, +{ 0xBE7D, 0xBE7D, 0xBE7D }, +{ 0xBE7E, 0xBE7E, 0xBE7E }, +{ 0xBE7F, 0xBE7F, 0xBE7F }, +{ 0xBE80, 0xBE80, 0xBE80 }, +{ 0xBE81, 0xBE81, 0xBE81 }, +{ 0xBE82, 0xBE82, 0xBE82 }, +{ 0xBE83, 0xBE83, 0xBE83 }, +{ 0xBE84, 0xBE84, 0xBE84 }, +{ 0xBE85, 0xBE85, 0xBE85 }, +{ 0xBE86, 0xBE86, 0xBE86 }, +{ 0xBE87, 0xBE87, 0xBE87 }, +{ 0xBE88, 0xBE88, 0xBE88 }, +{ 0xBE89, 0xBE89, 0xBE89 }, +{ 0xBE8A, 0xBE8A, 0xBE8A }, +{ 0xBE8B, 0xBE8B, 0xBE8B }, +{ 0xBE8C, 0xBE8C, 0xBE8C }, +{ 0xBE8D, 0xBE8D, 0xBE8D }, +{ 0xBE8E, 0xBE8E, 0xBE8E }, +{ 0xBE8F, 0xBE8F, 0xBE8F }, +{ 0xBE90, 0xBE90, 0xBE90 }, +{ 0xBE91, 0xBE91, 0xBE91 }, +{ 0xBE92, 0xBE92, 0xBE92 }, +{ 0xBE93, 0xBE93, 0xBE93 }, +{ 0xBE94, 0xBE94, 0xBE94 }, +{ 0xBE95, 0xBE95, 0xBE95 }, +{ 0xBE96, 0xBE96, 0xBE96 }, +{ 0xBE97, 0xBE97, 0xBE97 }, +{ 0xBE98, 0xBE98, 0xBE98 }, +{ 0xBE99, 0xBE99, 0xBE99 }, +{ 0xBE9A, 0xBE9A, 0xBE9A }, +{ 0xBE9B, 0xBE9B, 0xBE9B }, +{ 0xBE9C, 0xBE9C, 0xBE9C }, +{ 0xBE9D, 0xBE9D, 0xBE9D }, +{ 0xBE9E, 0xBE9E, 0xBE9E }, +{ 0xBE9F, 0xBE9F, 0xBE9F }, +{ 0xBEA0, 0xBEA0, 0xBEA0 }, +{ 0xBEA1, 0xBEA1, 0xBEA1 }, +{ 0xBEA2, 0xBEA2, 0xBEA2 }, +{ 0xBEA3, 0xBEA3, 0xBEA3 }, +{ 0xBEA4, 0xBEA4, 0xBEA4 }, +{ 0xBEA5, 0xBEA5, 0xBEA5 }, +{ 0xBEA6, 0xBEA6, 0xBEA6 }, +{ 0xBEA7, 0xBEA7, 0xBEA7 }, +{ 0xBEA8, 0xBEA8, 0xBEA8 }, +{ 0xBEA9, 0xBEA9, 0xBEA9 }, +{ 0xBEAA, 0xBEAA, 0xBEAA }, +{ 0xBEAB, 0xBEAB, 0xBEAB }, +{ 0xBEAC, 0xBEAC, 0xBEAC }, +{ 0xBEAD, 0xBEAD, 0xBEAD }, +{ 0xBEAE, 0xBEAE, 0xBEAE }, +{ 0xBEAF, 0xBEAF, 0xBEAF }, +{ 0xBEB0, 0xBEB0, 0xBEB0 }, +{ 0xBEB1, 0xBEB1, 0xBEB1 }, +{ 0xBEB2, 0xBEB2, 0xBEB2 }, +{ 0xBEB3, 0xBEB3, 0xBEB3 }, +{ 0xBEB4, 0xBEB4, 0xBEB4 }, +{ 0xBEB5, 0xBEB5, 0xBEB5 }, +{ 0xBEB6, 0xBEB6, 0xBEB6 }, +{ 0xBEB7, 0xBEB7, 0xBEB7 }, +{ 0xBEB8, 0xBEB8, 0xBEB8 }, +{ 0xBEB9, 0xBEB9, 0xBEB9 }, +{ 0xBEBA, 0xBEBA, 0xBEBA }, +{ 0xBEBB, 0xBEBB, 0xBEBB }, +{ 0xBEBC, 0xBEBC, 0xBEBC }, +{ 0xBEBD, 0xBEBD, 0xBEBD }, +{ 0xBEBE, 0xBEBE, 0xBEBE }, +{ 0xBEBF, 0xBEBF, 0xBEBF }, +{ 0xBEC0, 0xBEC0, 0xBEC0 }, +{ 0xBEC1, 0xBEC1, 0xBEC1 }, +{ 0xBEC2, 0xBEC2, 0xBEC2 }, +{ 0xBEC3, 0xBEC3, 0xBEC3 }, +{ 0xBEC4, 0xBEC4, 0xBEC4 }, +{ 0xBEC5, 0xBEC5, 0xBEC5 }, +{ 0xBEC6, 0xBEC6, 0xBEC6 }, +{ 0xBEC7, 0xBEC7, 0xBEC7 }, +{ 0xBEC8, 0xBEC8, 0xBEC8 }, +{ 0xBEC9, 0xBEC9, 0xBEC9 }, +{ 0xBECA, 0xBECA, 0xBECA }, +{ 0xBECB, 0xBECB, 0xBECB }, +{ 0xBECC, 0xBECC, 0xBECC }, +{ 0xBECD, 0xBECD, 0xBECD }, +{ 0xBECE, 0xBECE, 0xBECE }, +{ 0xBECF, 0xBECF, 0xBECF }, +{ 0xBED0, 0xBED0, 0xBED0 }, +{ 0xBED1, 0xBED1, 0xBED1 }, +{ 0xBED2, 0xBED2, 0xBED2 }, +{ 0xBED3, 0xBED3, 0xBED3 }, +{ 0xBED4, 0xBED4, 0xBED4 }, +{ 0xBED5, 0xBED5, 0xBED5 }, +{ 0xBED6, 0xBED6, 0xBED6 }, +{ 0xBED7, 0xBED7, 0xBED7 }, +{ 0xBED8, 0xBED8, 0xBED8 }, +{ 0xBED9, 0xBED9, 0xBED9 }, +{ 0xBEDA, 0xBEDA, 0xBEDA }, +{ 0xBEDB, 0xBEDB, 0xBEDB }, +{ 0xBEDC, 0xBEDC, 0xBEDC }, +{ 0xBEDD, 0xBEDD, 0xBEDD }, +{ 0xBEDE, 0xBEDE, 0xBEDE }, +{ 0xBEDF, 0xBEDF, 0xBEDF }, +{ 0xBEE0, 0xBEE0, 0xBEE0 }, +{ 0xBEE1, 0xBEE1, 0xBEE1 }, +{ 0xBEE2, 0xBEE2, 0xBEE2 }, +{ 0xBEE3, 0xBEE3, 0xBEE3 }, +{ 0xBEE4, 0xBEE4, 0xBEE4 }, +{ 0xBEE5, 0xBEE5, 0xBEE5 }, +{ 0xBEE6, 0xBEE6, 0xBEE6 }, +{ 0xBEE7, 0xBEE7, 0xBEE7 }, +{ 0xBEE8, 0xBEE8, 0xBEE8 }, +{ 0xBEE9, 0xBEE9, 0xBEE9 }, +{ 0xBEEA, 0xBEEA, 0xBEEA }, +{ 0xBEEB, 0xBEEB, 0xBEEB }, +{ 0xBEEC, 0xBEEC, 0xBEEC }, +{ 0xBEED, 0xBEED, 0xBEED }, +{ 0xBEEE, 0xBEEE, 0xBEEE }, +{ 0xBEEF, 0xBEEF, 0xBEEF }, +{ 0xBEF0, 0xBEF0, 0xBEF0 }, +{ 0xBEF1, 0xBEF1, 0xBEF1 }, +{ 0xBEF2, 0xBEF2, 0xBEF2 }, +{ 0xBEF3, 0xBEF3, 0xBEF3 }, +{ 0xBEF4, 0xBEF4, 0xBEF4 }, +{ 0xBEF5, 0xBEF5, 0xBEF5 }, +{ 0xBEF6, 0xBEF6, 0xBEF6 }, +{ 0xBEF7, 0xBEF7, 0xBEF7 }, +{ 0xBEF8, 0xBEF8, 0xBEF8 }, +{ 0xBEF9, 0xBEF9, 0xBEF9 }, +{ 0xBEFA, 0xBEFA, 0xBEFA }, +{ 0xBEFB, 0xBEFB, 0xBEFB }, +{ 0xBEFC, 0xBEFC, 0xBEFC }, +{ 0xBEFD, 0xBEFD, 0xBEFD }, +{ 0xBEFE, 0xBEFE, 0xBEFE }, +{ 0xBEFF, 0xBEFF, 0xBEFF }, +{ 0xBF00, 0xBF00, 0xBF00 }, +{ 0xBF01, 0xBF01, 0xBF01 }, +{ 0xBF02, 0xBF02, 0xBF02 }, +{ 0xBF03, 0xBF03, 0xBF03 }, +{ 0xBF04, 0xBF04, 0xBF04 }, +{ 0xBF05, 0xBF05, 0xBF05 }, +{ 0xBF06, 0xBF06, 0xBF06 }, +{ 0xBF07, 0xBF07, 0xBF07 }, +{ 0xBF08, 0xBF08, 0xBF08 }, +{ 0xBF09, 0xBF09, 0xBF09 }, +{ 0xBF0A, 0xBF0A, 0xBF0A }, +{ 0xBF0B, 0xBF0B, 0xBF0B }, +{ 0xBF0C, 0xBF0C, 0xBF0C }, +{ 0xBF0D, 0xBF0D, 0xBF0D }, +{ 0xBF0E, 0xBF0E, 0xBF0E }, +{ 0xBF0F, 0xBF0F, 0xBF0F }, +{ 0xBF10, 0xBF10, 0xBF10 }, +{ 0xBF11, 0xBF11, 0xBF11 }, +{ 0xBF12, 0xBF12, 0xBF12 }, +{ 0xBF13, 0xBF13, 0xBF13 }, +{ 0xBF14, 0xBF14, 0xBF14 }, +{ 0xBF15, 0xBF15, 0xBF15 }, +{ 0xBF16, 0xBF16, 0xBF16 }, +{ 0xBF17, 0xBF17, 0xBF17 }, +{ 0xBF18, 0xBF18, 0xBF18 }, +{ 0xBF19, 0xBF19, 0xBF19 }, +{ 0xBF1A, 0xBF1A, 0xBF1A }, +{ 0xBF1B, 0xBF1B, 0xBF1B }, +{ 0xBF1C, 0xBF1C, 0xBF1C }, +{ 0xBF1D, 0xBF1D, 0xBF1D }, +{ 0xBF1E, 0xBF1E, 0xBF1E }, +{ 0xBF1F, 0xBF1F, 0xBF1F }, +{ 0xBF20, 0xBF20, 0xBF20 }, +{ 0xBF21, 0xBF21, 0xBF21 }, +{ 0xBF22, 0xBF22, 0xBF22 }, +{ 0xBF23, 0xBF23, 0xBF23 }, +{ 0xBF24, 0xBF24, 0xBF24 }, +{ 0xBF25, 0xBF25, 0xBF25 }, +{ 0xBF26, 0xBF26, 0xBF26 }, +{ 0xBF27, 0xBF27, 0xBF27 }, +{ 0xBF28, 0xBF28, 0xBF28 }, +{ 0xBF29, 0xBF29, 0xBF29 }, +{ 0xBF2A, 0xBF2A, 0xBF2A }, +{ 0xBF2B, 0xBF2B, 0xBF2B }, +{ 0xBF2C, 0xBF2C, 0xBF2C }, +{ 0xBF2D, 0xBF2D, 0xBF2D }, +{ 0xBF2E, 0xBF2E, 0xBF2E }, +{ 0xBF2F, 0xBF2F, 0xBF2F }, +{ 0xBF30, 0xBF30, 0xBF30 }, +{ 0xBF31, 0xBF31, 0xBF31 }, +{ 0xBF32, 0xBF32, 0xBF32 }, +{ 0xBF33, 0xBF33, 0xBF33 }, +{ 0xBF34, 0xBF34, 0xBF34 }, +{ 0xBF35, 0xBF35, 0xBF35 }, +{ 0xBF36, 0xBF36, 0xBF36 }, +{ 0xBF37, 0xBF37, 0xBF37 }, +{ 0xBF38, 0xBF38, 0xBF38 }, +{ 0xBF39, 0xBF39, 0xBF39 }, +{ 0xBF3A, 0xBF3A, 0xBF3A }, +{ 0xBF3B, 0xBF3B, 0xBF3B }, +{ 0xBF3C, 0xBF3C, 0xBF3C }, +{ 0xBF3D, 0xBF3D, 0xBF3D }, +{ 0xBF3E, 0xBF3E, 0xBF3E }, +{ 0xBF3F, 0xBF3F, 0xBF3F }, +{ 0xBF40, 0xBF40, 0xBF40 }, +{ 0xBF41, 0xBF41, 0xBF41 }, +{ 0xBF42, 0xBF42, 0xBF42 }, +{ 0xBF43, 0xBF43, 0xBF43 }, +{ 0xBF44, 0xBF44, 0xBF44 }, +{ 0xBF45, 0xBF45, 0xBF45 }, +{ 0xBF46, 0xBF46, 0xBF46 }, +{ 0xBF47, 0xBF47, 0xBF47 }, +{ 0xBF48, 0xBF48, 0xBF48 }, +{ 0xBF49, 0xBF49, 0xBF49 }, +{ 0xBF4A, 0xBF4A, 0xBF4A }, +{ 0xBF4B, 0xBF4B, 0xBF4B }, +{ 0xBF4C, 0xBF4C, 0xBF4C }, +{ 0xBF4D, 0xBF4D, 0xBF4D }, +{ 0xBF4E, 0xBF4E, 0xBF4E }, +{ 0xBF4F, 0xBF4F, 0xBF4F }, +{ 0xBF50, 0xBF50, 0xBF50 }, +{ 0xBF51, 0xBF51, 0xBF51 }, +{ 0xBF52, 0xBF52, 0xBF52 }, +{ 0xBF53, 0xBF53, 0xBF53 }, +{ 0xBF54, 0xBF54, 0xBF54 }, +{ 0xBF55, 0xBF55, 0xBF55 }, +{ 0xBF56, 0xBF56, 0xBF56 }, +{ 0xBF57, 0xBF57, 0xBF57 }, +{ 0xBF58, 0xBF58, 0xBF58 }, +{ 0xBF59, 0xBF59, 0xBF59 }, +{ 0xBF5A, 0xBF5A, 0xBF5A }, +{ 0xBF5B, 0xBF5B, 0xBF5B }, +{ 0xBF5C, 0xBF5C, 0xBF5C }, +{ 0xBF5D, 0xBF5D, 0xBF5D }, +{ 0xBF5E, 0xBF5E, 0xBF5E }, +{ 0xBF5F, 0xBF5F, 0xBF5F }, +{ 0xBF60, 0xBF60, 0xBF60 }, +{ 0xBF61, 0xBF61, 0xBF61 }, +{ 0xBF62, 0xBF62, 0xBF62 }, +{ 0xBF63, 0xBF63, 0xBF63 }, +{ 0xBF64, 0xBF64, 0xBF64 }, +{ 0xBF65, 0xBF65, 0xBF65 }, +{ 0xBF66, 0xBF66, 0xBF66 }, +{ 0xBF67, 0xBF67, 0xBF67 }, +{ 0xBF68, 0xBF68, 0xBF68 }, +{ 0xBF69, 0xBF69, 0xBF69 }, +{ 0xBF6A, 0xBF6A, 0xBF6A }, +{ 0xBF6B, 0xBF6B, 0xBF6B }, +{ 0xBF6C, 0xBF6C, 0xBF6C }, +{ 0xBF6D, 0xBF6D, 0xBF6D }, +{ 0xBF6E, 0xBF6E, 0xBF6E }, +{ 0xBF6F, 0xBF6F, 0xBF6F }, +{ 0xBF70, 0xBF70, 0xBF70 }, +{ 0xBF71, 0xBF71, 0xBF71 }, +{ 0xBF72, 0xBF72, 0xBF72 }, +{ 0xBF73, 0xBF73, 0xBF73 }, +{ 0xBF74, 0xBF74, 0xBF74 }, +{ 0xBF75, 0xBF75, 0xBF75 }, +{ 0xBF76, 0xBF76, 0xBF76 }, +{ 0xBF77, 0xBF77, 0xBF77 }, +{ 0xBF78, 0xBF78, 0xBF78 }, +{ 0xBF79, 0xBF79, 0xBF79 }, +{ 0xBF7A, 0xBF7A, 0xBF7A }, +{ 0xBF7B, 0xBF7B, 0xBF7B }, +{ 0xBF7C, 0xBF7C, 0xBF7C }, +{ 0xBF7D, 0xBF7D, 0xBF7D }, +{ 0xBF7E, 0xBF7E, 0xBF7E }, +{ 0xBF7F, 0xBF7F, 0xBF7F }, +{ 0xBF80, 0xBF80, 0xBF80 }, +{ 0xBF81, 0xBF81, 0xBF81 }, +{ 0xBF82, 0xBF82, 0xBF82 }, +{ 0xBF83, 0xBF83, 0xBF83 }, +{ 0xBF84, 0xBF84, 0xBF84 }, +{ 0xBF85, 0xBF85, 0xBF85 }, +{ 0xBF86, 0xBF86, 0xBF86 }, +{ 0xBF87, 0xBF87, 0xBF87 }, +{ 0xBF88, 0xBF88, 0xBF88 }, +{ 0xBF89, 0xBF89, 0xBF89 }, +{ 0xBF8A, 0xBF8A, 0xBF8A }, +{ 0xBF8B, 0xBF8B, 0xBF8B }, +{ 0xBF8C, 0xBF8C, 0xBF8C }, +{ 0xBF8D, 0xBF8D, 0xBF8D }, +{ 0xBF8E, 0xBF8E, 0xBF8E }, +{ 0xBF8F, 0xBF8F, 0xBF8F }, +{ 0xBF90, 0xBF90, 0xBF90 }, +{ 0xBF91, 0xBF91, 0xBF91 }, +{ 0xBF92, 0xBF92, 0xBF92 }, +{ 0xBF93, 0xBF93, 0xBF93 }, +{ 0xBF94, 0xBF94, 0xBF94 }, +{ 0xBF95, 0xBF95, 0xBF95 }, +{ 0xBF96, 0xBF96, 0xBF96 }, +{ 0xBF97, 0xBF97, 0xBF97 }, +{ 0xBF98, 0xBF98, 0xBF98 }, +{ 0xBF99, 0xBF99, 0xBF99 }, +{ 0xBF9A, 0xBF9A, 0xBF9A }, +{ 0xBF9B, 0xBF9B, 0xBF9B }, +{ 0xBF9C, 0xBF9C, 0xBF9C }, +{ 0xBF9D, 0xBF9D, 0xBF9D }, +{ 0xBF9E, 0xBF9E, 0xBF9E }, +{ 0xBF9F, 0xBF9F, 0xBF9F }, +{ 0xBFA0, 0xBFA0, 0xBFA0 }, +{ 0xBFA1, 0xBFA1, 0xBFA1 }, +{ 0xBFA2, 0xBFA2, 0xBFA2 }, +{ 0xBFA3, 0xBFA3, 0xBFA3 }, +{ 0xBFA4, 0xBFA4, 0xBFA4 }, +{ 0xBFA5, 0xBFA5, 0xBFA5 }, +{ 0xBFA6, 0xBFA6, 0xBFA6 }, +{ 0xBFA7, 0xBFA7, 0xBFA7 }, +{ 0xBFA8, 0xBFA8, 0xBFA8 }, +{ 0xBFA9, 0xBFA9, 0xBFA9 }, +{ 0xBFAA, 0xBFAA, 0xBFAA }, +{ 0xBFAB, 0xBFAB, 0xBFAB }, +{ 0xBFAC, 0xBFAC, 0xBFAC }, +{ 0xBFAD, 0xBFAD, 0xBFAD }, +{ 0xBFAE, 0xBFAE, 0xBFAE }, +{ 0xBFAF, 0xBFAF, 0xBFAF }, +{ 0xBFB0, 0xBFB0, 0xBFB0 }, +{ 0xBFB1, 0xBFB1, 0xBFB1 }, +{ 0xBFB2, 0xBFB2, 0xBFB2 }, +{ 0xBFB3, 0xBFB3, 0xBFB3 }, +{ 0xBFB4, 0xBFB4, 0xBFB4 }, +{ 0xBFB5, 0xBFB5, 0xBFB5 }, +{ 0xBFB6, 0xBFB6, 0xBFB6 }, +{ 0xBFB7, 0xBFB7, 0xBFB7 }, +{ 0xBFB8, 0xBFB8, 0xBFB8 }, +{ 0xBFB9, 0xBFB9, 0xBFB9 }, +{ 0xBFBA, 0xBFBA, 0xBFBA }, +{ 0xBFBB, 0xBFBB, 0xBFBB }, +{ 0xBFBC, 0xBFBC, 0xBFBC }, +{ 0xBFBD, 0xBFBD, 0xBFBD }, +{ 0xBFBE, 0xBFBE, 0xBFBE }, +{ 0xBFBF, 0xBFBF, 0xBFBF }, +{ 0xBFC0, 0xBFC0, 0xBFC0 }, +{ 0xBFC1, 0xBFC1, 0xBFC1 }, +{ 0xBFC2, 0xBFC2, 0xBFC2 }, +{ 0xBFC3, 0xBFC3, 0xBFC3 }, +{ 0xBFC4, 0xBFC4, 0xBFC4 }, +{ 0xBFC5, 0xBFC5, 0xBFC5 }, +{ 0xBFC6, 0xBFC6, 0xBFC6 }, +{ 0xBFC7, 0xBFC7, 0xBFC7 }, +{ 0xBFC8, 0xBFC8, 0xBFC8 }, +{ 0xBFC9, 0xBFC9, 0xBFC9 }, +{ 0xBFCA, 0xBFCA, 0xBFCA }, +{ 0xBFCB, 0xBFCB, 0xBFCB }, +{ 0xBFCC, 0xBFCC, 0xBFCC }, +{ 0xBFCD, 0xBFCD, 0xBFCD }, +{ 0xBFCE, 0xBFCE, 0xBFCE }, +{ 0xBFCF, 0xBFCF, 0xBFCF }, +{ 0xBFD0, 0xBFD0, 0xBFD0 }, +{ 0xBFD1, 0xBFD1, 0xBFD1 }, +{ 0xBFD2, 0xBFD2, 0xBFD2 }, +{ 0xBFD3, 0xBFD3, 0xBFD3 }, +{ 0xBFD4, 0xBFD4, 0xBFD4 }, +{ 0xBFD5, 0xBFD5, 0xBFD5 }, +{ 0xBFD6, 0xBFD6, 0xBFD6 }, +{ 0xBFD7, 0xBFD7, 0xBFD7 }, +{ 0xBFD8, 0xBFD8, 0xBFD8 }, +{ 0xBFD9, 0xBFD9, 0xBFD9 }, +{ 0xBFDA, 0xBFDA, 0xBFDA }, +{ 0xBFDB, 0xBFDB, 0xBFDB }, +{ 0xBFDC, 0xBFDC, 0xBFDC }, +{ 0xBFDD, 0xBFDD, 0xBFDD }, +{ 0xBFDE, 0xBFDE, 0xBFDE }, +{ 0xBFDF, 0xBFDF, 0xBFDF }, +{ 0xBFE0, 0xBFE0, 0xBFE0 }, +{ 0xBFE1, 0xBFE1, 0xBFE1 }, +{ 0xBFE2, 0xBFE2, 0xBFE2 }, +{ 0xBFE3, 0xBFE3, 0xBFE3 }, +{ 0xBFE4, 0xBFE4, 0xBFE4 }, +{ 0xBFE5, 0xBFE5, 0xBFE5 }, +{ 0xBFE6, 0xBFE6, 0xBFE6 }, +{ 0xBFE7, 0xBFE7, 0xBFE7 }, +{ 0xBFE8, 0xBFE8, 0xBFE8 }, +{ 0xBFE9, 0xBFE9, 0xBFE9 }, +{ 0xBFEA, 0xBFEA, 0xBFEA }, +{ 0xBFEB, 0xBFEB, 0xBFEB }, +{ 0xBFEC, 0xBFEC, 0xBFEC }, +{ 0xBFED, 0xBFED, 0xBFED }, +{ 0xBFEE, 0xBFEE, 0xBFEE }, +{ 0xBFEF, 0xBFEF, 0xBFEF }, +{ 0xBFF0, 0xBFF0, 0xBFF0 }, +{ 0xBFF1, 0xBFF1, 0xBFF1 }, +{ 0xBFF2, 0xBFF2, 0xBFF2 }, +{ 0xBFF3, 0xBFF3, 0xBFF3 }, +{ 0xBFF4, 0xBFF4, 0xBFF4 }, +{ 0xBFF5, 0xBFF5, 0xBFF5 }, +{ 0xBFF6, 0xBFF6, 0xBFF6 }, +{ 0xBFF7, 0xBFF7, 0xBFF7 }, +{ 0xBFF8, 0xBFF8, 0xBFF8 }, +{ 0xBFF9, 0xBFF9, 0xBFF9 }, +{ 0xBFFA, 0xBFFA, 0xBFFA }, +{ 0xBFFB, 0xBFFB, 0xBFFB }, +{ 0xBFFC, 0xBFFC, 0xBFFC }, +{ 0xBFFD, 0xBFFD, 0xBFFD }, +{ 0xBFFE, 0xBFFE, 0xBFFE }, +{ 0xBFFF, 0xBFFF, 0xBFFF }, +{ 0xC000, 0xC000, 0xC000 }, +{ 0xC001, 0xC001, 0xC001 }, +{ 0xC002, 0xC002, 0xC002 }, +{ 0xC003, 0xC003, 0xC003 }, +{ 0xC004, 0xC004, 0xC004 }, +{ 0xC005, 0xC005, 0xC005 }, +{ 0xC006, 0xC006, 0xC006 }, +{ 0xC007, 0xC007, 0xC007 }, +{ 0xC008, 0xC008, 0xC008 }, +{ 0xC009, 0xC009, 0xC009 }, +{ 0xC00A, 0xC00A, 0xC00A }, +{ 0xC00B, 0xC00B, 0xC00B }, +{ 0xC00C, 0xC00C, 0xC00C }, +{ 0xC00D, 0xC00D, 0xC00D }, +{ 0xC00E, 0xC00E, 0xC00E }, +{ 0xC00F, 0xC00F, 0xC00F }, +{ 0xC010, 0xC010, 0xC010 }, +{ 0xC011, 0xC011, 0xC011 }, +{ 0xC012, 0xC012, 0xC012 }, +{ 0xC013, 0xC013, 0xC013 }, +{ 0xC014, 0xC014, 0xC014 }, +{ 0xC015, 0xC015, 0xC015 }, +{ 0xC016, 0xC016, 0xC016 }, +{ 0xC017, 0xC017, 0xC017 }, +{ 0xC018, 0xC018, 0xC018 }, +{ 0xC019, 0xC019, 0xC019 }, +{ 0xC01A, 0xC01A, 0xC01A }, +{ 0xC01B, 0xC01B, 0xC01B }, +{ 0xC01C, 0xC01C, 0xC01C }, +{ 0xC01D, 0xC01D, 0xC01D }, +{ 0xC01E, 0xC01E, 0xC01E }, +{ 0xC01F, 0xC01F, 0xC01F }, +{ 0xC020, 0xC020, 0xC020 }, +{ 0xC021, 0xC021, 0xC021 }, +{ 0xC022, 0xC022, 0xC022 }, +{ 0xC023, 0xC023, 0xC023 }, +{ 0xC024, 0xC024, 0xC024 }, +{ 0xC025, 0xC025, 0xC025 }, +{ 0xC026, 0xC026, 0xC026 }, +{ 0xC027, 0xC027, 0xC027 }, +{ 0xC028, 0xC028, 0xC028 }, +{ 0xC029, 0xC029, 0xC029 }, +{ 0xC02A, 0xC02A, 0xC02A }, +{ 0xC02B, 0xC02B, 0xC02B }, +{ 0xC02C, 0xC02C, 0xC02C }, +{ 0xC02D, 0xC02D, 0xC02D }, +{ 0xC02E, 0xC02E, 0xC02E }, +{ 0xC02F, 0xC02F, 0xC02F }, +{ 0xC030, 0xC030, 0xC030 }, +{ 0xC031, 0xC031, 0xC031 }, +{ 0xC032, 0xC032, 0xC032 }, +{ 0xC033, 0xC033, 0xC033 }, +{ 0xC034, 0xC034, 0xC034 }, +{ 0xC035, 0xC035, 0xC035 }, +{ 0xC036, 0xC036, 0xC036 }, +{ 0xC037, 0xC037, 0xC037 }, +{ 0xC038, 0xC038, 0xC038 }, +{ 0xC039, 0xC039, 0xC039 }, +{ 0xC03A, 0xC03A, 0xC03A }, +{ 0xC03B, 0xC03B, 0xC03B }, +{ 0xC03C, 0xC03C, 0xC03C }, +{ 0xC03D, 0xC03D, 0xC03D }, +{ 0xC03E, 0xC03E, 0xC03E }, +{ 0xC03F, 0xC03F, 0xC03F }, +{ 0xC040, 0xC040, 0xC040 }, +{ 0xC041, 0xC041, 0xC041 }, +{ 0xC042, 0xC042, 0xC042 }, +{ 0xC043, 0xC043, 0xC043 }, +{ 0xC044, 0xC044, 0xC044 }, +{ 0xC045, 0xC045, 0xC045 }, +{ 0xC046, 0xC046, 0xC046 }, +{ 0xC047, 0xC047, 0xC047 }, +{ 0xC048, 0xC048, 0xC048 }, +{ 0xC049, 0xC049, 0xC049 }, +{ 0xC04A, 0xC04A, 0xC04A }, +{ 0xC04B, 0xC04B, 0xC04B }, +{ 0xC04C, 0xC04C, 0xC04C }, +{ 0xC04D, 0xC04D, 0xC04D }, +{ 0xC04E, 0xC04E, 0xC04E }, +{ 0xC04F, 0xC04F, 0xC04F }, +{ 0xC050, 0xC050, 0xC050 }, +{ 0xC051, 0xC051, 0xC051 }, +{ 0xC052, 0xC052, 0xC052 }, +{ 0xC053, 0xC053, 0xC053 }, +{ 0xC054, 0xC054, 0xC054 }, +{ 0xC055, 0xC055, 0xC055 }, +{ 0xC056, 0xC056, 0xC056 }, +{ 0xC057, 0xC057, 0xC057 }, +{ 0xC058, 0xC058, 0xC058 }, +{ 0xC059, 0xC059, 0xC059 }, +{ 0xC05A, 0xC05A, 0xC05A }, +{ 0xC05B, 0xC05B, 0xC05B }, +{ 0xC05C, 0xC05C, 0xC05C }, +{ 0xC05D, 0xC05D, 0xC05D }, +{ 0xC05E, 0xC05E, 0xC05E }, +{ 0xC05F, 0xC05F, 0xC05F }, +{ 0xC060, 0xC060, 0xC060 }, +{ 0xC061, 0xC061, 0xC061 }, +{ 0xC062, 0xC062, 0xC062 }, +{ 0xC063, 0xC063, 0xC063 }, +{ 0xC064, 0xC064, 0xC064 }, +{ 0xC065, 0xC065, 0xC065 }, +{ 0xC066, 0xC066, 0xC066 }, +{ 0xC067, 0xC067, 0xC067 }, +{ 0xC068, 0xC068, 0xC068 }, +{ 0xC069, 0xC069, 0xC069 }, +{ 0xC06A, 0xC06A, 0xC06A }, +{ 0xC06B, 0xC06B, 0xC06B }, +{ 0xC06C, 0xC06C, 0xC06C }, +{ 0xC06D, 0xC06D, 0xC06D }, +{ 0xC06E, 0xC06E, 0xC06E }, +{ 0xC06F, 0xC06F, 0xC06F }, +{ 0xC070, 0xC070, 0xC070 }, +{ 0xC071, 0xC071, 0xC071 }, +{ 0xC072, 0xC072, 0xC072 }, +{ 0xC073, 0xC073, 0xC073 }, +{ 0xC074, 0xC074, 0xC074 }, +{ 0xC075, 0xC075, 0xC075 }, +{ 0xC076, 0xC076, 0xC076 }, +{ 0xC077, 0xC077, 0xC077 }, +{ 0xC078, 0xC078, 0xC078 }, +{ 0xC079, 0xC079, 0xC079 }, +{ 0xC07A, 0xC07A, 0xC07A }, +{ 0xC07B, 0xC07B, 0xC07B }, +{ 0xC07C, 0xC07C, 0xC07C }, +{ 0xC07D, 0xC07D, 0xC07D }, +{ 0xC07E, 0xC07E, 0xC07E }, +{ 0xC07F, 0xC07F, 0xC07F }, +{ 0xC080, 0xC080, 0xC080 }, +{ 0xC081, 0xC081, 0xC081 }, +{ 0xC082, 0xC082, 0xC082 }, +{ 0xC083, 0xC083, 0xC083 }, +{ 0xC084, 0xC084, 0xC084 }, +{ 0xC085, 0xC085, 0xC085 }, +{ 0xC086, 0xC086, 0xC086 }, +{ 0xC087, 0xC087, 0xC087 }, +{ 0xC088, 0xC088, 0xC088 }, +{ 0xC089, 0xC089, 0xC089 }, +{ 0xC08A, 0xC08A, 0xC08A }, +{ 0xC08B, 0xC08B, 0xC08B }, +{ 0xC08C, 0xC08C, 0xC08C }, +{ 0xC08D, 0xC08D, 0xC08D }, +{ 0xC08E, 0xC08E, 0xC08E }, +{ 0xC08F, 0xC08F, 0xC08F }, +{ 0xC090, 0xC090, 0xC090 }, +{ 0xC091, 0xC091, 0xC091 }, +{ 0xC092, 0xC092, 0xC092 }, +{ 0xC093, 0xC093, 0xC093 }, +{ 0xC094, 0xC094, 0xC094 }, +{ 0xC095, 0xC095, 0xC095 }, +{ 0xC096, 0xC096, 0xC096 }, +{ 0xC097, 0xC097, 0xC097 }, +{ 0xC098, 0xC098, 0xC098 }, +{ 0xC099, 0xC099, 0xC099 }, +{ 0xC09A, 0xC09A, 0xC09A }, +{ 0xC09B, 0xC09B, 0xC09B }, +{ 0xC09C, 0xC09C, 0xC09C }, +{ 0xC09D, 0xC09D, 0xC09D }, +{ 0xC09E, 0xC09E, 0xC09E }, +{ 0xC09F, 0xC09F, 0xC09F }, +{ 0xC0A0, 0xC0A0, 0xC0A0 }, +{ 0xC0A1, 0xC0A1, 0xC0A1 }, +{ 0xC0A2, 0xC0A2, 0xC0A2 }, +{ 0xC0A3, 0xC0A3, 0xC0A3 }, +{ 0xC0A4, 0xC0A4, 0xC0A4 }, +{ 0xC0A5, 0xC0A5, 0xC0A5 }, +{ 0xC0A6, 0xC0A6, 0xC0A6 }, +{ 0xC0A7, 0xC0A7, 0xC0A7 }, +{ 0xC0A8, 0xC0A8, 0xC0A8 }, +{ 0xC0A9, 0xC0A9, 0xC0A9 }, +{ 0xC0AA, 0xC0AA, 0xC0AA }, +{ 0xC0AB, 0xC0AB, 0xC0AB }, +{ 0xC0AC, 0xC0AC, 0xC0AC }, +{ 0xC0AD, 0xC0AD, 0xC0AD }, +{ 0xC0AE, 0xC0AE, 0xC0AE }, +{ 0xC0AF, 0xC0AF, 0xC0AF }, +{ 0xC0B0, 0xC0B0, 0xC0B0 }, +{ 0xC0B1, 0xC0B1, 0xC0B1 }, +{ 0xC0B2, 0xC0B2, 0xC0B2 }, +{ 0xC0B3, 0xC0B3, 0xC0B3 }, +{ 0xC0B4, 0xC0B4, 0xC0B4 }, +{ 0xC0B5, 0xC0B5, 0xC0B5 }, +{ 0xC0B6, 0xC0B6, 0xC0B6 }, +{ 0xC0B7, 0xC0B7, 0xC0B7 }, +{ 0xC0B8, 0xC0B8, 0xC0B8 }, +{ 0xC0B9, 0xC0B9, 0xC0B9 }, +{ 0xC0BA, 0xC0BA, 0xC0BA }, +{ 0xC0BB, 0xC0BB, 0xC0BB }, +{ 0xC0BC, 0xC0BC, 0xC0BC }, +{ 0xC0BD, 0xC0BD, 0xC0BD }, +{ 0xC0BE, 0xC0BE, 0xC0BE }, +{ 0xC0BF, 0xC0BF, 0xC0BF }, +{ 0xC0C0, 0xC0C0, 0xC0C0 }, +{ 0xC0C1, 0xC0C1, 0xC0C1 }, +{ 0xC0C2, 0xC0C2, 0xC0C2 }, +{ 0xC0C3, 0xC0C3, 0xC0C3 }, +{ 0xC0C4, 0xC0C4, 0xC0C4 }, +{ 0xC0C5, 0xC0C5, 0xC0C5 }, +{ 0xC0C6, 0xC0C6, 0xC0C6 }, +{ 0xC0C7, 0xC0C7, 0xC0C7 }, +{ 0xC0C8, 0xC0C8, 0xC0C8 }, +{ 0xC0C9, 0xC0C9, 0xC0C9 }, +{ 0xC0CA, 0xC0CA, 0xC0CA }, +{ 0xC0CB, 0xC0CB, 0xC0CB }, +{ 0xC0CC, 0xC0CC, 0xC0CC }, +{ 0xC0CD, 0xC0CD, 0xC0CD }, +{ 0xC0CE, 0xC0CE, 0xC0CE }, +{ 0xC0CF, 0xC0CF, 0xC0CF }, +{ 0xC0D0, 0xC0D0, 0xC0D0 }, +{ 0xC0D1, 0xC0D1, 0xC0D1 }, +{ 0xC0D2, 0xC0D2, 0xC0D2 }, +{ 0xC0D3, 0xC0D3, 0xC0D3 }, +{ 0xC0D4, 0xC0D4, 0xC0D4 }, +{ 0xC0D5, 0xC0D5, 0xC0D5 }, +{ 0xC0D6, 0xC0D6, 0xC0D6 }, +{ 0xC0D7, 0xC0D7, 0xC0D7 }, +{ 0xC0D8, 0xC0D8, 0xC0D8 }, +{ 0xC0D9, 0xC0D9, 0xC0D9 }, +{ 0xC0DA, 0xC0DA, 0xC0DA }, +{ 0xC0DB, 0xC0DB, 0xC0DB }, +{ 0xC0DC, 0xC0DC, 0xC0DC }, +{ 0xC0DD, 0xC0DD, 0xC0DD }, +{ 0xC0DE, 0xC0DE, 0xC0DE }, +{ 0xC0DF, 0xC0DF, 0xC0DF }, +{ 0xC0E0, 0xC0E0, 0xC0E0 }, +{ 0xC0E1, 0xC0E1, 0xC0E1 }, +{ 0xC0E2, 0xC0E2, 0xC0E2 }, +{ 0xC0E3, 0xC0E3, 0xC0E3 }, +{ 0xC0E4, 0xC0E4, 0xC0E4 }, +{ 0xC0E5, 0xC0E5, 0xC0E5 }, +{ 0xC0E6, 0xC0E6, 0xC0E6 }, +{ 0xC0E7, 0xC0E7, 0xC0E7 }, +{ 0xC0E8, 0xC0E8, 0xC0E8 }, +{ 0xC0E9, 0xC0E9, 0xC0E9 }, +{ 0xC0EA, 0xC0EA, 0xC0EA }, +{ 0xC0EB, 0xC0EB, 0xC0EB }, +{ 0xC0EC, 0xC0EC, 0xC0EC }, +{ 0xC0ED, 0xC0ED, 0xC0ED }, +{ 0xC0EE, 0xC0EE, 0xC0EE }, +{ 0xC0EF, 0xC0EF, 0xC0EF }, +{ 0xC0F0, 0xC0F0, 0xC0F0 }, +{ 0xC0F1, 0xC0F1, 0xC0F1 }, +{ 0xC0F2, 0xC0F2, 0xC0F2 }, +{ 0xC0F3, 0xC0F3, 0xC0F3 }, +{ 0xC0F4, 0xC0F4, 0xC0F4 }, +{ 0xC0F5, 0xC0F5, 0xC0F5 }, +{ 0xC0F6, 0xC0F6, 0xC0F6 }, +{ 0xC0F7, 0xC0F7, 0xC0F7 }, +{ 0xC0F8, 0xC0F8, 0xC0F8 }, +{ 0xC0F9, 0xC0F9, 0xC0F9 }, +{ 0xC0FA, 0xC0FA, 0xC0FA }, +{ 0xC0FB, 0xC0FB, 0xC0FB }, +{ 0xC0FC, 0xC0FC, 0xC0FC }, +{ 0xC0FD, 0xC0FD, 0xC0FD }, +{ 0xC0FE, 0xC0FE, 0xC0FE }, +{ 0xC0FF, 0xC0FF, 0xC0FF }, +{ 0xC100, 0xC100, 0xC100 }, +{ 0xC101, 0xC101, 0xC101 }, +{ 0xC102, 0xC102, 0xC102 }, +{ 0xC103, 0xC103, 0xC103 }, +{ 0xC104, 0xC104, 0xC104 }, +{ 0xC105, 0xC105, 0xC105 }, +{ 0xC106, 0xC106, 0xC106 }, +{ 0xC107, 0xC107, 0xC107 }, +{ 0xC108, 0xC108, 0xC108 }, +{ 0xC109, 0xC109, 0xC109 }, +{ 0xC10A, 0xC10A, 0xC10A }, +{ 0xC10B, 0xC10B, 0xC10B }, +{ 0xC10C, 0xC10C, 0xC10C }, +{ 0xC10D, 0xC10D, 0xC10D }, +{ 0xC10E, 0xC10E, 0xC10E }, +{ 0xC10F, 0xC10F, 0xC10F }, +{ 0xC110, 0xC110, 0xC110 }, +{ 0xC111, 0xC111, 0xC111 }, +{ 0xC112, 0xC112, 0xC112 }, +{ 0xC113, 0xC113, 0xC113 }, +{ 0xC114, 0xC114, 0xC114 }, +{ 0xC115, 0xC115, 0xC115 }, +{ 0xC116, 0xC116, 0xC116 }, +{ 0xC117, 0xC117, 0xC117 }, +{ 0xC118, 0xC118, 0xC118 }, +{ 0xC119, 0xC119, 0xC119 }, +{ 0xC11A, 0xC11A, 0xC11A }, +{ 0xC11B, 0xC11B, 0xC11B }, +{ 0xC11C, 0xC11C, 0xC11C }, +{ 0xC11D, 0xC11D, 0xC11D }, +{ 0xC11E, 0xC11E, 0xC11E }, +{ 0xC11F, 0xC11F, 0xC11F }, +{ 0xC120, 0xC120, 0xC120 }, +{ 0xC121, 0xC121, 0xC121 }, +{ 0xC122, 0xC122, 0xC122 }, +{ 0xC123, 0xC123, 0xC123 }, +{ 0xC124, 0xC124, 0xC124 }, +{ 0xC125, 0xC125, 0xC125 }, +{ 0xC126, 0xC126, 0xC126 }, +{ 0xC127, 0xC127, 0xC127 }, +{ 0xC128, 0xC128, 0xC128 }, +{ 0xC129, 0xC129, 0xC129 }, +{ 0xC12A, 0xC12A, 0xC12A }, +{ 0xC12B, 0xC12B, 0xC12B }, +{ 0xC12C, 0xC12C, 0xC12C }, +{ 0xC12D, 0xC12D, 0xC12D }, +{ 0xC12E, 0xC12E, 0xC12E }, +{ 0xC12F, 0xC12F, 0xC12F }, +{ 0xC130, 0xC130, 0xC130 }, +{ 0xC131, 0xC131, 0xC131 }, +{ 0xC132, 0xC132, 0xC132 }, +{ 0xC133, 0xC133, 0xC133 }, +{ 0xC134, 0xC134, 0xC134 }, +{ 0xC135, 0xC135, 0xC135 }, +{ 0xC136, 0xC136, 0xC136 }, +{ 0xC137, 0xC137, 0xC137 }, +{ 0xC138, 0xC138, 0xC138 }, +{ 0xC139, 0xC139, 0xC139 }, +{ 0xC13A, 0xC13A, 0xC13A }, +{ 0xC13B, 0xC13B, 0xC13B }, +{ 0xC13C, 0xC13C, 0xC13C }, +{ 0xC13D, 0xC13D, 0xC13D }, +{ 0xC13E, 0xC13E, 0xC13E }, +{ 0xC13F, 0xC13F, 0xC13F }, +{ 0xC140, 0xC140, 0xC140 }, +{ 0xC141, 0xC141, 0xC141 }, +{ 0xC142, 0xC142, 0xC142 }, +{ 0xC143, 0xC143, 0xC143 }, +{ 0xC144, 0xC144, 0xC144 }, +{ 0xC145, 0xC145, 0xC145 }, +{ 0xC146, 0xC146, 0xC146 }, +{ 0xC147, 0xC147, 0xC147 }, +{ 0xC148, 0xC148, 0xC148 }, +{ 0xC149, 0xC149, 0xC149 }, +{ 0xC14A, 0xC14A, 0xC14A }, +{ 0xC14B, 0xC14B, 0xC14B }, +{ 0xC14C, 0xC14C, 0xC14C }, +{ 0xC14D, 0xC14D, 0xC14D }, +{ 0xC14E, 0xC14E, 0xC14E }, +{ 0xC14F, 0xC14F, 0xC14F }, +{ 0xC150, 0xC150, 0xC150 }, +{ 0xC151, 0xC151, 0xC151 }, +{ 0xC152, 0xC152, 0xC152 }, +{ 0xC153, 0xC153, 0xC153 }, +{ 0xC154, 0xC154, 0xC154 }, +{ 0xC155, 0xC155, 0xC155 }, +{ 0xC156, 0xC156, 0xC156 }, +{ 0xC157, 0xC157, 0xC157 }, +{ 0xC158, 0xC158, 0xC158 }, +{ 0xC159, 0xC159, 0xC159 }, +{ 0xC15A, 0xC15A, 0xC15A }, +{ 0xC15B, 0xC15B, 0xC15B }, +{ 0xC15C, 0xC15C, 0xC15C }, +{ 0xC15D, 0xC15D, 0xC15D }, +{ 0xC15E, 0xC15E, 0xC15E }, +{ 0xC15F, 0xC15F, 0xC15F }, +{ 0xC160, 0xC160, 0xC160 }, +{ 0xC161, 0xC161, 0xC161 }, +{ 0xC162, 0xC162, 0xC162 }, +{ 0xC163, 0xC163, 0xC163 }, +{ 0xC164, 0xC164, 0xC164 }, +{ 0xC165, 0xC165, 0xC165 }, +{ 0xC166, 0xC166, 0xC166 }, +{ 0xC167, 0xC167, 0xC167 }, +{ 0xC168, 0xC168, 0xC168 }, +{ 0xC169, 0xC169, 0xC169 }, +{ 0xC16A, 0xC16A, 0xC16A }, +{ 0xC16B, 0xC16B, 0xC16B }, +{ 0xC16C, 0xC16C, 0xC16C }, +{ 0xC16D, 0xC16D, 0xC16D }, +{ 0xC16E, 0xC16E, 0xC16E }, +{ 0xC16F, 0xC16F, 0xC16F }, +{ 0xC170, 0xC170, 0xC170 }, +{ 0xC171, 0xC171, 0xC171 }, +{ 0xC172, 0xC172, 0xC172 }, +{ 0xC173, 0xC173, 0xC173 }, +{ 0xC174, 0xC174, 0xC174 }, +{ 0xC175, 0xC175, 0xC175 }, +{ 0xC176, 0xC176, 0xC176 }, +{ 0xC177, 0xC177, 0xC177 }, +{ 0xC178, 0xC178, 0xC178 }, +{ 0xC179, 0xC179, 0xC179 }, +{ 0xC17A, 0xC17A, 0xC17A }, +{ 0xC17B, 0xC17B, 0xC17B }, +{ 0xC17C, 0xC17C, 0xC17C }, +{ 0xC17D, 0xC17D, 0xC17D }, +{ 0xC17E, 0xC17E, 0xC17E }, +{ 0xC17F, 0xC17F, 0xC17F }, +{ 0xC180, 0xC180, 0xC180 }, +{ 0xC181, 0xC181, 0xC181 }, +{ 0xC182, 0xC182, 0xC182 }, +{ 0xC183, 0xC183, 0xC183 }, +{ 0xC184, 0xC184, 0xC184 }, +{ 0xC185, 0xC185, 0xC185 }, +{ 0xC186, 0xC186, 0xC186 }, +{ 0xC187, 0xC187, 0xC187 }, +{ 0xC188, 0xC188, 0xC188 }, +{ 0xC189, 0xC189, 0xC189 }, +{ 0xC18A, 0xC18A, 0xC18A }, +{ 0xC18B, 0xC18B, 0xC18B }, +{ 0xC18C, 0xC18C, 0xC18C }, +{ 0xC18D, 0xC18D, 0xC18D }, +{ 0xC18E, 0xC18E, 0xC18E }, +{ 0xC18F, 0xC18F, 0xC18F }, +{ 0xC190, 0xC190, 0xC190 }, +{ 0xC191, 0xC191, 0xC191 }, +{ 0xC192, 0xC192, 0xC192 }, +{ 0xC193, 0xC193, 0xC193 }, +{ 0xC194, 0xC194, 0xC194 }, +{ 0xC195, 0xC195, 0xC195 }, +{ 0xC196, 0xC196, 0xC196 }, +{ 0xC197, 0xC197, 0xC197 }, +{ 0xC198, 0xC198, 0xC198 }, +{ 0xC199, 0xC199, 0xC199 }, +{ 0xC19A, 0xC19A, 0xC19A }, +{ 0xC19B, 0xC19B, 0xC19B }, +{ 0xC19C, 0xC19C, 0xC19C }, +{ 0xC19D, 0xC19D, 0xC19D }, +{ 0xC19E, 0xC19E, 0xC19E }, +{ 0xC19F, 0xC19F, 0xC19F }, +{ 0xC1A0, 0xC1A0, 0xC1A0 }, +{ 0xC1A1, 0xC1A1, 0xC1A1 }, +{ 0xC1A2, 0xC1A2, 0xC1A2 }, +{ 0xC1A3, 0xC1A3, 0xC1A3 }, +{ 0xC1A4, 0xC1A4, 0xC1A4 }, +{ 0xC1A5, 0xC1A5, 0xC1A5 }, +{ 0xC1A6, 0xC1A6, 0xC1A6 }, +{ 0xC1A7, 0xC1A7, 0xC1A7 }, +{ 0xC1A8, 0xC1A8, 0xC1A8 }, +{ 0xC1A9, 0xC1A9, 0xC1A9 }, +{ 0xC1AA, 0xC1AA, 0xC1AA }, +{ 0xC1AB, 0xC1AB, 0xC1AB }, +{ 0xC1AC, 0xC1AC, 0xC1AC }, +{ 0xC1AD, 0xC1AD, 0xC1AD }, +{ 0xC1AE, 0xC1AE, 0xC1AE }, +{ 0xC1AF, 0xC1AF, 0xC1AF }, +{ 0xC1B0, 0xC1B0, 0xC1B0 }, +{ 0xC1B1, 0xC1B1, 0xC1B1 }, +{ 0xC1B2, 0xC1B2, 0xC1B2 }, +{ 0xC1B3, 0xC1B3, 0xC1B3 }, +{ 0xC1B4, 0xC1B4, 0xC1B4 }, +{ 0xC1B5, 0xC1B5, 0xC1B5 }, +{ 0xC1B6, 0xC1B6, 0xC1B6 }, +{ 0xC1B7, 0xC1B7, 0xC1B7 }, +{ 0xC1B8, 0xC1B8, 0xC1B8 }, +{ 0xC1B9, 0xC1B9, 0xC1B9 }, +{ 0xC1BA, 0xC1BA, 0xC1BA }, +{ 0xC1BB, 0xC1BB, 0xC1BB }, +{ 0xC1BC, 0xC1BC, 0xC1BC }, +{ 0xC1BD, 0xC1BD, 0xC1BD }, +{ 0xC1BE, 0xC1BE, 0xC1BE }, +{ 0xC1BF, 0xC1BF, 0xC1BF }, +{ 0xC1C0, 0xC1C0, 0xC1C0 }, +{ 0xC1C1, 0xC1C1, 0xC1C1 }, +{ 0xC1C2, 0xC1C2, 0xC1C2 }, +{ 0xC1C3, 0xC1C3, 0xC1C3 }, +{ 0xC1C4, 0xC1C4, 0xC1C4 }, +{ 0xC1C5, 0xC1C5, 0xC1C5 }, +{ 0xC1C6, 0xC1C6, 0xC1C6 }, +{ 0xC1C7, 0xC1C7, 0xC1C7 }, +{ 0xC1C8, 0xC1C8, 0xC1C8 }, +{ 0xC1C9, 0xC1C9, 0xC1C9 }, +{ 0xC1CA, 0xC1CA, 0xC1CA }, +{ 0xC1CB, 0xC1CB, 0xC1CB }, +{ 0xC1CC, 0xC1CC, 0xC1CC }, +{ 0xC1CD, 0xC1CD, 0xC1CD }, +{ 0xC1CE, 0xC1CE, 0xC1CE }, +{ 0xC1CF, 0xC1CF, 0xC1CF }, +{ 0xC1D0, 0xC1D0, 0xC1D0 }, +{ 0xC1D1, 0xC1D1, 0xC1D1 }, +{ 0xC1D2, 0xC1D2, 0xC1D2 }, +{ 0xC1D3, 0xC1D3, 0xC1D3 }, +{ 0xC1D4, 0xC1D4, 0xC1D4 }, +{ 0xC1D5, 0xC1D5, 0xC1D5 }, +{ 0xC1D6, 0xC1D6, 0xC1D6 }, +{ 0xC1D7, 0xC1D7, 0xC1D7 }, +{ 0xC1D8, 0xC1D8, 0xC1D8 }, +{ 0xC1D9, 0xC1D9, 0xC1D9 }, +{ 0xC1DA, 0xC1DA, 0xC1DA }, +{ 0xC1DB, 0xC1DB, 0xC1DB }, +{ 0xC1DC, 0xC1DC, 0xC1DC }, +{ 0xC1DD, 0xC1DD, 0xC1DD }, +{ 0xC1DE, 0xC1DE, 0xC1DE }, +{ 0xC1DF, 0xC1DF, 0xC1DF }, +{ 0xC1E0, 0xC1E0, 0xC1E0 }, +{ 0xC1E1, 0xC1E1, 0xC1E1 }, +{ 0xC1E2, 0xC1E2, 0xC1E2 }, +{ 0xC1E3, 0xC1E3, 0xC1E3 }, +{ 0xC1E4, 0xC1E4, 0xC1E4 }, +{ 0xC1E5, 0xC1E5, 0xC1E5 }, +{ 0xC1E6, 0xC1E6, 0xC1E6 }, +{ 0xC1E7, 0xC1E7, 0xC1E7 }, +{ 0xC1E8, 0xC1E8, 0xC1E8 }, +{ 0xC1E9, 0xC1E9, 0xC1E9 }, +{ 0xC1EA, 0xC1EA, 0xC1EA }, +{ 0xC1EB, 0xC1EB, 0xC1EB }, +{ 0xC1EC, 0xC1EC, 0xC1EC }, +{ 0xC1ED, 0xC1ED, 0xC1ED }, +{ 0xC1EE, 0xC1EE, 0xC1EE }, +{ 0xC1EF, 0xC1EF, 0xC1EF }, +{ 0xC1F0, 0xC1F0, 0xC1F0 }, +{ 0xC1F1, 0xC1F1, 0xC1F1 }, +{ 0xC1F2, 0xC1F2, 0xC1F2 }, +{ 0xC1F3, 0xC1F3, 0xC1F3 }, +{ 0xC1F4, 0xC1F4, 0xC1F4 }, +{ 0xC1F5, 0xC1F5, 0xC1F5 }, +{ 0xC1F6, 0xC1F6, 0xC1F6 }, +{ 0xC1F7, 0xC1F7, 0xC1F7 }, +{ 0xC1F8, 0xC1F8, 0xC1F8 }, +{ 0xC1F9, 0xC1F9, 0xC1F9 }, +{ 0xC1FA, 0xC1FA, 0xC1FA }, +{ 0xC1FB, 0xC1FB, 0xC1FB }, +{ 0xC1FC, 0xC1FC, 0xC1FC }, +{ 0xC1FD, 0xC1FD, 0xC1FD }, +{ 0xC1FE, 0xC1FE, 0xC1FE }, +{ 0xC1FF, 0xC1FF, 0xC1FF }, +{ 0xC200, 0xC200, 0xC200 }, +{ 0xC201, 0xC201, 0xC201 }, +{ 0xC202, 0xC202, 0xC202 }, +{ 0xC203, 0xC203, 0xC203 }, +{ 0xC204, 0xC204, 0xC204 }, +{ 0xC205, 0xC205, 0xC205 }, +{ 0xC206, 0xC206, 0xC206 }, +{ 0xC207, 0xC207, 0xC207 }, +{ 0xC208, 0xC208, 0xC208 }, +{ 0xC209, 0xC209, 0xC209 }, +{ 0xC20A, 0xC20A, 0xC20A }, +{ 0xC20B, 0xC20B, 0xC20B }, +{ 0xC20C, 0xC20C, 0xC20C }, +{ 0xC20D, 0xC20D, 0xC20D }, +{ 0xC20E, 0xC20E, 0xC20E }, +{ 0xC20F, 0xC20F, 0xC20F }, +{ 0xC210, 0xC210, 0xC210 }, +{ 0xC211, 0xC211, 0xC211 }, +{ 0xC212, 0xC212, 0xC212 }, +{ 0xC213, 0xC213, 0xC213 }, +{ 0xC214, 0xC214, 0xC214 }, +{ 0xC215, 0xC215, 0xC215 }, +{ 0xC216, 0xC216, 0xC216 }, +{ 0xC217, 0xC217, 0xC217 }, +{ 0xC218, 0xC218, 0xC218 }, +{ 0xC219, 0xC219, 0xC219 }, +{ 0xC21A, 0xC21A, 0xC21A }, +{ 0xC21B, 0xC21B, 0xC21B }, +{ 0xC21C, 0xC21C, 0xC21C }, +{ 0xC21D, 0xC21D, 0xC21D }, +{ 0xC21E, 0xC21E, 0xC21E }, +{ 0xC21F, 0xC21F, 0xC21F }, +{ 0xC220, 0xC220, 0xC220 }, +{ 0xC221, 0xC221, 0xC221 }, +{ 0xC222, 0xC222, 0xC222 }, +{ 0xC223, 0xC223, 0xC223 }, +{ 0xC224, 0xC224, 0xC224 }, +{ 0xC225, 0xC225, 0xC225 }, +{ 0xC226, 0xC226, 0xC226 }, +{ 0xC227, 0xC227, 0xC227 }, +{ 0xC228, 0xC228, 0xC228 }, +{ 0xC229, 0xC229, 0xC229 }, +{ 0xC22A, 0xC22A, 0xC22A }, +{ 0xC22B, 0xC22B, 0xC22B }, +{ 0xC22C, 0xC22C, 0xC22C }, +{ 0xC22D, 0xC22D, 0xC22D }, +{ 0xC22E, 0xC22E, 0xC22E }, +{ 0xC22F, 0xC22F, 0xC22F }, +{ 0xC230, 0xC230, 0xC230 }, +{ 0xC231, 0xC231, 0xC231 }, +{ 0xC232, 0xC232, 0xC232 }, +{ 0xC233, 0xC233, 0xC233 }, +{ 0xC234, 0xC234, 0xC234 }, +{ 0xC235, 0xC235, 0xC235 }, +{ 0xC236, 0xC236, 0xC236 }, +{ 0xC237, 0xC237, 0xC237 }, +{ 0xC238, 0xC238, 0xC238 }, +{ 0xC239, 0xC239, 0xC239 }, +{ 0xC23A, 0xC23A, 0xC23A }, +{ 0xC23B, 0xC23B, 0xC23B }, +{ 0xC23C, 0xC23C, 0xC23C }, +{ 0xC23D, 0xC23D, 0xC23D }, +{ 0xC23E, 0xC23E, 0xC23E }, +{ 0xC23F, 0xC23F, 0xC23F }, +{ 0xC240, 0xC240, 0xC240 }, +{ 0xC241, 0xC241, 0xC241 }, +{ 0xC242, 0xC242, 0xC242 }, +{ 0xC243, 0xC243, 0xC243 }, +{ 0xC244, 0xC244, 0xC244 }, +{ 0xC245, 0xC245, 0xC245 }, +{ 0xC246, 0xC246, 0xC246 }, +{ 0xC247, 0xC247, 0xC247 }, +{ 0xC248, 0xC248, 0xC248 }, +{ 0xC249, 0xC249, 0xC249 }, +{ 0xC24A, 0xC24A, 0xC24A }, +{ 0xC24B, 0xC24B, 0xC24B }, +{ 0xC24C, 0xC24C, 0xC24C }, +{ 0xC24D, 0xC24D, 0xC24D }, +{ 0xC24E, 0xC24E, 0xC24E }, +{ 0xC24F, 0xC24F, 0xC24F }, +{ 0xC250, 0xC250, 0xC250 }, +{ 0xC251, 0xC251, 0xC251 }, +{ 0xC252, 0xC252, 0xC252 }, +{ 0xC253, 0xC253, 0xC253 }, +{ 0xC254, 0xC254, 0xC254 }, +{ 0xC255, 0xC255, 0xC255 }, +{ 0xC256, 0xC256, 0xC256 }, +{ 0xC257, 0xC257, 0xC257 }, +{ 0xC258, 0xC258, 0xC258 }, +{ 0xC259, 0xC259, 0xC259 }, +{ 0xC25A, 0xC25A, 0xC25A }, +{ 0xC25B, 0xC25B, 0xC25B }, +{ 0xC25C, 0xC25C, 0xC25C }, +{ 0xC25D, 0xC25D, 0xC25D }, +{ 0xC25E, 0xC25E, 0xC25E }, +{ 0xC25F, 0xC25F, 0xC25F }, +{ 0xC260, 0xC260, 0xC260 }, +{ 0xC261, 0xC261, 0xC261 }, +{ 0xC262, 0xC262, 0xC262 }, +{ 0xC263, 0xC263, 0xC263 }, +{ 0xC264, 0xC264, 0xC264 }, +{ 0xC265, 0xC265, 0xC265 }, +{ 0xC266, 0xC266, 0xC266 }, +{ 0xC267, 0xC267, 0xC267 }, +{ 0xC268, 0xC268, 0xC268 }, +{ 0xC269, 0xC269, 0xC269 }, +{ 0xC26A, 0xC26A, 0xC26A }, +{ 0xC26B, 0xC26B, 0xC26B }, +{ 0xC26C, 0xC26C, 0xC26C }, +{ 0xC26D, 0xC26D, 0xC26D }, +{ 0xC26E, 0xC26E, 0xC26E }, +{ 0xC26F, 0xC26F, 0xC26F }, +{ 0xC270, 0xC270, 0xC270 }, +{ 0xC271, 0xC271, 0xC271 }, +{ 0xC272, 0xC272, 0xC272 }, +{ 0xC273, 0xC273, 0xC273 }, +{ 0xC274, 0xC274, 0xC274 }, +{ 0xC275, 0xC275, 0xC275 }, +{ 0xC276, 0xC276, 0xC276 }, +{ 0xC277, 0xC277, 0xC277 }, +{ 0xC278, 0xC278, 0xC278 }, +{ 0xC279, 0xC279, 0xC279 }, +{ 0xC27A, 0xC27A, 0xC27A }, +{ 0xC27B, 0xC27B, 0xC27B }, +{ 0xC27C, 0xC27C, 0xC27C }, +{ 0xC27D, 0xC27D, 0xC27D }, +{ 0xC27E, 0xC27E, 0xC27E }, +{ 0xC27F, 0xC27F, 0xC27F }, +{ 0xC280, 0xC280, 0xC280 }, +{ 0xC281, 0xC281, 0xC281 }, +{ 0xC282, 0xC282, 0xC282 }, +{ 0xC283, 0xC283, 0xC283 }, +{ 0xC284, 0xC284, 0xC284 }, +{ 0xC285, 0xC285, 0xC285 }, +{ 0xC286, 0xC286, 0xC286 }, +{ 0xC287, 0xC287, 0xC287 }, +{ 0xC288, 0xC288, 0xC288 }, +{ 0xC289, 0xC289, 0xC289 }, +{ 0xC28A, 0xC28A, 0xC28A }, +{ 0xC28B, 0xC28B, 0xC28B }, +{ 0xC28C, 0xC28C, 0xC28C }, +{ 0xC28D, 0xC28D, 0xC28D }, +{ 0xC28E, 0xC28E, 0xC28E }, +{ 0xC28F, 0xC28F, 0xC28F }, +{ 0xC290, 0xC290, 0xC290 }, +{ 0xC291, 0xC291, 0xC291 }, +{ 0xC292, 0xC292, 0xC292 }, +{ 0xC293, 0xC293, 0xC293 }, +{ 0xC294, 0xC294, 0xC294 }, +{ 0xC295, 0xC295, 0xC295 }, +{ 0xC296, 0xC296, 0xC296 }, +{ 0xC297, 0xC297, 0xC297 }, +{ 0xC298, 0xC298, 0xC298 }, +{ 0xC299, 0xC299, 0xC299 }, +{ 0xC29A, 0xC29A, 0xC29A }, +{ 0xC29B, 0xC29B, 0xC29B }, +{ 0xC29C, 0xC29C, 0xC29C }, +{ 0xC29D, 0xC29D, 0xC29D }, +{ 0xC29E, 0xC29E, 0xC29E }, +{ 0xC29F, 0xC29F, 0xC29F }, +{ 0xC2A0, 0xC2A0, 0xC2A0 }, +{ 0xC2A1, 0xC2A1, 0xC2A1 }, +{ 0xC2A2, 0xC2A2, 0xC2A2 }, +{ 0xC2A3, 0xC2A3, 0xC2A3 }, +{ 0xC2A4, 0xC2A4, 0xC2A4 }, +{ 0xC2A5, 0xC2A5, 0xC2A5 }, +{ 0xC2A6, 0xC2A6, 0xC2A6 }, +{ 0xC2A7, 0xC2A7, 0xC2A7 }, +{ 0xC2A8, 0xC2A8, 0xC2A8 }, +{ 0xC2A9, 0xC2A9, 0xC2A9 }, +{ 0xC2AA, 0xC2AA, 0xC2AA }, +{ 0xC2AB, 0xC2AB, 0xC2AB }, +{ 0xC2AC, 0xC2AC, 0xC2AC }, +{ 0xC2AD, 0xC2AD, 0xC2AD }, +{ 0xC2AE, 0xC2AE, 0xC2AE }, +{ 0xC2AF, 0xC2AF, 0xC2AF }, +{ 0xC2B0, 0xC2B0, 0xC2B0 }, +{ 0xC2B1, 0xC2B1, 0xC2B1 }, +{ 0xC2B2, 0xC2B2, 0xC2B2 }, +{ 0xC2B3, 0xC2B3, 0xC2B3 }, +{ 0xC2B4, 0xC2B4, 0xC2B4 }, +{ 0xC2B5, 0xC2B5, 0xC2B5 }, +{ 0xC2B6, 0xC2B6, 0xC2B6 }, +{ 0xC2B7, 0xC2B7, 0xC2B7 }, +{ 0xC2B8, 0xC2B8, 0xC2B8 }, +{ 0xC2B9, 0xC2B9, 0xC2B9 }, +{ 0xC2BA, 0xC2BA, 0xC2BA }, +{ 0xC2BB, 0xC2BB, 0xC2BB }, +{ 0xC2BC, 0xC2BC, 0xC2BC }, +{ 0xC2BD, 0xC2BD, 0xC2BD }, +{ 0xC2BE, 0xC2BE, 0xC2BE }, +{ 0xC2BF, 0xC2BF, 0xC2BF }, +{ 0xC2C0, 0xC2C0, 0xC2C0 }, +{ 0xC2C1, 0xC2C1, 0xC2C1 }, +{ 0xC2C2, 0xC2C2, 0xC2C2 }, +{ 0xC2C3, 0xC2C3, 0xC2C3 }, +{ 0xC2C4, 0xC2C4, 0xC2C4 }, +{ 0xC2C5, 0xC2C5, 0xC2C5 }, +{ 0xC2C6, 0xC2C6, 0xC2C6 }, +{ 0xC2C7, 0xC2C7, 0xC2C7 }, +{ 0xC2C8, 0xC2C8, 0xC2C8 }, +{ 0xC2C9, 0xC2C9, 0xC2C9 }, +{ 0xC2CA, 0xC2CA, 0xC2CA }, +{ 0xC2CB, 0xC2CB, 0xC2CB }, +{ 0xC2CC, 0xC2CC, 0xC2CC }, +{ 0xC2CD, 0xC2CD, 0xC2CD }, +{ 0xC2CE, 0xC2CE, 0xC2CE }, +{ 0xC2CF, 0xC2CF, 0xC2CF }, +{ 0xC2D0, 0xC2D0, 0xC2D0 }, +{ 0xC2D1, 0xC2D1, 0xC2D1 }, +{ 0xC2D2, 0xC2D2, 0xC2D2 }, +{ 0xC2D3, 0xC2D3, 0xC2D3 }, +{ 0xC2D4, 0xC2D4, 0xC2D4 }, +{ 0xC2D5, 0xC2D5, 0xC2D5 }, +{ 0xC2D6, 0xC2D6, 0xC2D6 }, +{ 0xC2D7, 0xC2D7, 0xC2D7 }, +{ 0xC2D8, 0xC2D8, 0xC2D8 }, +{ 0xC2D9, 0xC2D9, 0xC2D9 }, +{ 0xC2DA, 0xC2DA, 0xC2DA }, +{ 0xC2DB, 0xC2DB, 0xC2DB }, +{ 0xC2DC, 0xC2DC, 0xC2DC }, +{ 0xC2DD, 0xC2DD, 0xC2DD }, +{ 0xC2DE, 0xC2DE, 0xC2DE }, +{ 0xC2DF, 0xC2DF, 0xC2DF }, +{ 0xC2E0, 0xC2E0, 0xC2E0 }, +{ 0xC2E1, 0xC2E1, 0xC2E1 }, +{ 0xC2E2, 0xC2E2, 0xC2E2 }, +{ 0xC2E3, 0xC2E3, 0xC2E3 }, +{ 0xC2E4, 0xC2E4, 0xC2E4 }, +{ 0xC2E5, 0xC2E5, 0xC2E5 }, +{ 0xC2E6, 0xC2E6, 0xC2E6 }, +{ 0xC2E7, 0xC2E7, 0xC2E7 }, +{ 0xC2E8, 0xC2E8, 0xC2E8 }, +{ 0xC2E9, 0xC2E9, 0xC2E9 }, +{ 0xC2EA, 0xC2EA, 0xC2EA }, +{ 0xC2EB, 0xC2EB, 0xC2EB }, +{ 0xC2EC, 0xC2EC, 0xC2EC }, +{ 0xC2ED, 0xC2ED, 0xC2ED }, +{ 0xC2EE, 0xC2EE, 0xC2EE }, +{ 0xC2EF, 0xC2EF, 0xC2EF }, +{ 0xC2F0, 0xC2F0, 0xC2F0 }, +{ 0xC2F1, 0xC2F1, 0xC2F1 }, +{ 0xC2F2, 0xC2F2, 0xC2F2 }, +{ 0xC2F3, 0xC2F3, 0xC2F3 }, +{ 0xC2F4, 0xC2F4, 0xC2F4 }, +{ 0xC2F5, 0xC2F5, 0xC2F5 }, +{ 0xC2F6, 0xC2F6, 0xC2F6 }, +{ 0xC2F7, 0xC2F7, 0xC2F7 }, +{ 0xC2F8, 0xC2F8, 0xC2F8 }, +{ 0xC2F9, 0xC2F9, 0xC2F9 }, +{ 0xC2FA, 0xC2FA, 0xC2FA }, +{ 0xC2FB, 0xC2FB, 0xC2FB }, +{ 0xC2FC, 0xC2FC, 0xC2FC }, +{ 0xC2FD, 0xC2FD, 0xC2FD }, +{ 0xC2FE, 0xC2FE, 0xC2FE }, +{ 0xC2FF, 0xC2FF, 0xC2FF }, +{ 0xC300, 0xC300, 0xC300 }, +{ 0xC301, 0xC301, 0xC301 }, +{ 0xC302, 0xC302, 0xC302 }, +{ 0xC303, 0xC303, 0xC303 }, +{ 0xC304, 0xC304, 0xC304 }, +{ 0xC305, 0xC305, 0xC305 }, +{ 0xC306, 0xC306, 0xC306 }, +{ 0xC307, 0xC307, 0xC307 }, +{ 0xC308, 0xC308, 0xC308 }, +{ 0xC309, 0xC309, 0xC309 }, +{ 0xC30A, 0xC30A, 0xC30A }, +{ 0xC30B, 0xC30B, 0xC30B }, +{ 0xC30C, 0xC30C, 0xC30C }, +{ 0xC30D, 0xC30D, 0xC30D }, +{ 0xC30E, 0xC30E, 0xC30E }, +{ 0xC30F, 0xC30F, 0xC30F }, +{ 0xC310, 0xC310, 0xC310 }, +{ 0xC311, 0xC311, 0xC311 }, +{ 0xC312, 0xC312, 0xC312 }, +{ 0xC313, 0xC313, 0xC313 }, +{ 0xC314, 0xC314, 0xC314 }, +{ 0xC315, 0xC315, 0xC315 }, +{ 0xC316, 0xC316, 0xC316 }, +{ 0xC317, 0xC317, 0xC317 }, +{ 0xC318, 0xC318, 0xC318 }, +{ 0xC319, 0xC319, 0xC319 }, +{ 0xC31A, 0xC31A, 0xC31A }, +{ 0xC31B, 0xC31B, 0xC31B }, +{ 0xC31C, 0xC31C, 0xC31C }, +{ 0xC31D, 0xC31D, 0xC31D }, +{ 0xC31E, 0xC31E, 0xC31E }, +{ 0xC31F, 0xC31F, 0xC31F }, +{ 0xC320, 0xC320, 0xC320 }, +{ 0xC321, 0xC321, 0xC321 }, +{ 0xC322, 0xC322, 0xC322 }, +{ 0xC323, 0xC323, 0xC323 }, +{ 0xC324, 0xC324, 0xC324 }, +{ 0xC325, 0xC325, 0xC325 }, +{ 0xC326, 0xC326, 0xC326 }, +{ 0xC327, 0xC327, 0xC327 }, +{ 0xC328, 0xC328, 0xC328 }, +{ 0xC329, 0xC329, 0xC329 }, +{ 0xC32A, 0xC32A, 0xC32A }, +{ 0xC32B, 0xC32B, 0xC32B }, +{ 0xC32C, 0xC32C, 0xC32C }, +{ 0xC32D, 0xC32D, 0xC32D }, +{ 0xC32E, 0xC32E, 0xC32E }, +{ 0xC32F, 0xC32F, 0xC32F }, +{ 0xC330, 0xC330, 0xC330 }, +{ 0xC331, 0xC331, 0xC331 }, +{ 0xC332, 0xC332, 0xC332 }, +{ 0xC333, 0xC333, 0xC333 }, +{ 0xC334, 0xC334, 0xC334 }, +{ 0xC335, 0xC335, 0xC335 }, +{ 0xC336, 0xC336, 0xC336 }, +{ 0xC337, 0xC337, 0xC337 }, +{ 0xC338, 0xC338, 0xC338 }, +{ 0xC339, 0xC339, 0xC339 }, +{ 0xC33A, 0xC33A, 0xC33A }, +{ 0xC33B, 0xC33B, 0xC33B }, +{ 0xC33C, 0xC33C, 0xC33C }, +{ 0xC33D, 0xC33D, 0xC33D }, +{ 0xC33E, 0xC33E, 0xC33E }, +{ 0xC33F, 0xC33F, 0xC33F }, +{ 0xC340, 0xC340, 0xC340 }, +{ 0xC341, 0xC341, 0xC341 }, +{ 0xC342, 0xC342, 0xC342 }, +{ 0xC343, 0xC343, 0xC343 }, +{ 0xC344, 0xC344, 0xC344 }, +{ 0xC345, 0xC345, 0xC345 }, +{ 0xC346, 0xC346, 0xC346 }, +{ 0xC347, 0xC347, 0xC347 }, +{ 0xC348, 0xC348, 0xC348 }, +{ 0xC349, 0xC349, 0xC349 }, +{ 0xC34A, 0xC34A, 0xC34A }, +{ 0xC34B, 0xC34B, 0xC34B }, +{ 0xC34C, 0xC34C, 0xC34C }, +{ 0xC34D, 0xC34D, 0xC34D }, +{ 0xC34E, 0xC34E, 0xC34E }, +{ 0xC34F, 0xC34F, 0xC34F }, +{ 0xC350, 0xC350, 0xC350 }, +{ 0xC351, 0xC351, 0xC351 }, +{ 0xC352, 0xC352, 0xC352 }, +{ 0xC353, 0xC353, 0xC353 }, +{ 0xC354, 0xC354, 0xC354 }, +{ 0xC355, 0xC355, 0xC355 }, +{ 0xC356, 0xC356, 0xC356 }, +{ 0xC357, 0xC357, 0xC357 }, +{ 0xC358, 0xC358, 0xC358 }, +{ 0xC359, 0xC359, 0xC359 }, +{ 0xC35A, 0xC35A, 0xC35A }, +{ 0xC35B, 0xC35B, 0xC35B }, +{ 0xC35C, 0xC35C, 0xC35C }, +{ 0xC35D, 0xC35D, 0xC35D }, +{ 0xC35E, 0xC35E, 0xC35E }, +{ 0xC35F, 0xC35F, 0xC35F }, +{ 0xC360, 0xC360, 0xC360 }, +{ 0xC361, 0xC361, 0xC361 }, +{ 0xC362, 0xC362, 0xC362 }, +{ 0xC363, 0xC363, 0xC363 }, +{ 0xC364, 0xC364, 0xC364 }, +{ 0xC365, 0xC365, 0xC365 }, +{ 0xC366, 0xC366, 0xC366 }, +{ 0xC367, 0xC367, 0xC367 }, +{ 0xC368, 0xC368, 0xC368 }, +{ 0xC369, 0xC369, 0xC369 }, +{ 0xC36A, 0xC36A, 0xC36A }, +{ 0xC36B, 0xC36B, 0xC36B }, +{ 0xC36C, 0xC36C, 0xC36C }, +{ 0xC36D, 0xC36D, 0xC36D }, +{ 0xC36E, 0xC36E, 0xC36E }, +{ 0xC36F, 0xC36F, 0xC36F }, +{ 0xC370, 0xC370, 0xC370 }, +{ 0xC371, 0xC371, 0xC371 }, +{ 0xC372, 0xC372, 0xC372 }, +{ 0xC373, 0xC373, 0xC373 }, +{ 0xC374, 0xC374, 0xC374 }, +{ 0xC375, 0xC375, 0xC375 }, +{ 0xC376, 0xC376, 0xC376 }, +{ 0xC377, 0xC377, 0xC377 }, +{ 0xC378, 0xC378, 0xC378 }, +{ 0xC379, 0xC379, 0xC379 }, +{ 0xC37A, 0xC37A, 0xC37A }, +{ 0xC37B, 0xC37B, 0xC37B }, +{ 0xC37C, 0xC37C, 0xC37C }, +{ 0xC37D, 0xC37D, 0xC37D }, +{ 0xC37E, 0xC37E, 0xC37E }, +{ 0xC37F, 0xC37F, 0xC37F }, +{ 0xC380, 0xC380, 0xC380 }, +{ 0xC381, 0xC381, 0xC381 }, +{ 0xC382, 0xC382, 0xC382 }, +{ 0xC383, 0xC383, 0xC383 }, +{ 0xC384, 0xC384, 0xC384 }, +{ 0xC385, 0xC385, 0xC385 }, +{ 0xC386, 0xC386, 0xC386 }, +{ 0xC387, 0xC387, 0xC387 }, +{ 0xC388, 0xC388, 0xC388 }, +{ 0xC389, 0xC389, 0xC389 }, +{ 0xC38A, 0xC38A, 0xC38A }, +{ 0xC38B, 0xC38B, 0xC38B }, +{ 0xC38C, 0xC38C, 0xC38C }, +{ 0xC38D, 0xC38D, 0xC38D }, +{ 0xC38E, 0xC38E, 0xC38E }, +{ 0xC38F, 0xC38F, 0xC38F }, +{ 0xC390, 0xC390, 0xC390 }, +{ 0xC391, 0xC391, 0xC391 }, +{ 0xC392, 0xC392, 0xC392 }, +{ 0xC393, 0xC393, 0xC393 }, +{ 0xC394, 0xC394, 0xC394 }, +{ 0xC395, 0xC395, 0xC395 }, +{ 0xC396, 0xC396, 0xC396 }, +{ 0xC397, 0xC397, 0xC397 }, +{ 0xC398, 0xC398, 0xC398 }, +{ 0xC399, 0xC399, 0xC399 }, +{ 0xC39A, 0xC39A, 0xC39A }, +{ 0xC39B, 0xC39B, 0xC39B }, +{ 0xC39C, 0xC39C, 0xC39C }, +{ 0xC39D, 0xC39D, 0xC39D }, +{ 0xC39E, 0xC39E, 0xC39E }, +{ 0xC39F, 0xC39F, 0xC39F }, +{ 0xC3A0, 0xC3A0, 0xC3A0 }, +{ 0xC3A1, 0xC3A1, 0xC3A1 }, +{ 0xC3A2, 0xC3A2, 0xC3A2 }, +{ 0xC3A3, 0xC3A3, 0xC3A3 }, +{ 0xC3A4, 0xC3A4, 0xC3A4 }, +{ 0xC3A5, 0xC3A5, 0xC3A5 }, +{ 0xC3A6, 0xC3A6, 0xC3A6 }, +{ 0xC3A7, 0xC3A7, 0xC3A7 }, +{ 0xC3A8, 0xC3A8, 0xC3A8 }, +{ 0xC3A9, 0xC3A9, 0xC3A9 }, +{ 0xC3AA, 0xC3AA, 0xC3AA }, +{ 0xC3AB, 0xC3AB, 0xC3AB }, +{ 0xC3AC, 0xC3AC, 0xC3AC }, +{ 0xC3AD, 0xC3AD, 0xC3AD }, +{ 0xC3AE, 0xC3AE, 0xC3AE }, +{ 0xC3AF, 0xC3AF, 0xC3AF }, +{ 0xC3B0, 0xC3B0, 0xC3B0 }, +{ 0xC3B1, 0xC3B1, 0xC3B1 }, +{ 0xC3B2, 0xC3B2, 0xC3B2 }, +{ 0xC3B3, 0xC3B3, 0xC3B3 }, +{ 0xC3B4, 0xC3B4, 0xC3B4 }, +{ 0xC3B5, 0xC3B5, 0xC3B5 }, +{ 0xC3B6, 0xC3B6, 0xC3B6 }, +{ 0xC3B7, 0xC3B7, 0xC3B7 }, +{ 0xC3B8, 0xC3B8, 0xC3B8 }, +{ 0xC3B9, 0xC3B9, 0xC3B9 }, +{ 0xC3BA, 0xC3BA, 0xC3BA }, +{ 0xC3BB, 0xC3BB, 0xC3BB }, +{ 0xC3BC, 0xC3BC, 0xC3BC }, +{ 0xC3BD, 0xC3BD, 0xC3BD }, +{ 0xC3BE, 0xC3BE, 0xC3BE }, +{ 0xC3BF, 0xC3BF, 0xC3BF }, +{ 0xC3C0, 0xC3C0, 0xC3C0 }, +{ 0xC3C1, 0xC3C1, 0xC3C1 }, +{ 0xC3C2, 0xC3C2, 0xC3C2 }, +{ 0xC3C3, 0xC3C3, 0xC3C3 }, +{ 0xC3C4, 0xC3C4, 0xC3C4 }, +{ 0xC3C5, 0xC3C5, 0xC3C5 }, +{ 0xC3C6, 0xC3C6, 0xC3C6 }, +{ 0xC3C7, 0xC3C7, 0xC3C7 }, +{ 0xC3C8, 0xC3C8, 0xC3C8 }, +{ 0xC3C9, 0xC3C9, 0xC3C9 }, +{ 0xC3CA, 0xC3CA, 0xC3CA }, +{ 0xC3CB, 0xC3CB, 0xC3CB }, +{ 0xC3CC, 0xC3CC, 0xC3CC }, +{ 0xC3CD, 0xC3CD, 0xC3CD }, +{ 0xC3CE, 0xC3CE, 0xC3CE }, +{ 0xC3CF, 0xC3CF, 0xC3CF }, +{ 0xC3D0, 0xC3D0, 0xC3D0 }, +{ 0xC3D1, 0xC3D1, 0xC3D1 }, +{ 0xC3D2, 0xC3D2, 0xC3D2 }, +{ 0xC3D3, 0xC3D3, 0xC3D3 }, +{ 0xC3D4, 0xC3D4, 0xC3D4 }, +{ 0xC3D5, 0xC3D5, 0xC3D5 }, +{ 0xC3D6, 0xC3D6, 0xC3D6 }, +{ 0xC3D7, 0xC3D7, 0xC3D7 }, +{ 0xC3D8, 0xC3D8, 0xC3D8 }, +{ 0xC3D9, 0xC3D9, 0xC3D9 }, +{ 0xC3DA, 0xC3DA, 0xC3DA }, +{ 0xC3DB, 0xC3DB, 0xC3DB }, +{ 0xC3DC, 0xC3DC, 0xC3DC }, +{ 0xC3DD, 0xC3DD, 0xC3DD }, +{ 0xC3DE, 0xC3DE, 0xC3DE }, +{ 0xC3DF, 0xC3DF, 0xC3DF }, +{ 0xC3E0, 0xC3E0, 0xC3E0 }, +{ 0xC3E1, 0xC3E1, 0xC3E1 }, +{ 0xC3E2, 0xC3E2, 0xC3E2 }, +{ 0xC3E3, 0xC3E3, 0xC3E3 }, +{ 0xC3E4, 0xC3E4, 0xC3E4 }, +{ 0xC3E5, 0xC3E5, 0xC3E5 }, +{ 0xC3E6, 0xC3E6, 0xC3E6 }, +{ 0xC3E7, 0xC3E7, 0xC3E7 }, +{ 0xC3E8, 0xC3E8, 0xC3E8 }, +{ 0xC3E9, 0xC3E9, 0xC3E9 }, +{ 0xC3EA, 0xC3EA, 0xC3EA }, +{ 0xC3EB, 0xC3EB, 0xC3EB }, +{ 0xC3EC, 0xC3EC, 0xC3EC }, +{ 0xC3ED, 0xC3ED, 0xC3ED }, +{ 0xC3EE, 0xC3EE, 0xC3EE }, +{ 0xC3EF, 0xC3EF, 0xC3EF }, +{ 0xC3F0, 0xC3F0, 0xC3F0 }, +{ 0xC3F1, 0xC3F1, 0xC3F1 }, +{ 0xC3F2, 0xC3F2, 0xC3F2 }, +{ 0xC3F3, 0xC3F3, 0xC3F3 }, +{ 0xC3F4, 0xC3F4, 0xC3F4 }, +{ 0xC3F5, 0xC3F5, 0xC3F5 }, +{ 0xC3F6, 0xC3F6, 0xC3F6 }, +{ 0xC3F7, 0xC3F7, 0xC3F7 }, +{ 0xC3F8, 0xC3F8, 0xC3F8 }, +{ 0xC3F9, 0xC3F9, 0xC3F9 }, +{ 0xC3FA, 0xC3FA, 0xC3FA }, +{ 0xC3FB, 0xC3FB, 0xC3FB }, +{ 0xC3FC, 0xC3FC, 0xC3FC }, +{ 0xC3FD, 0xC3FD, 0xC3FD }, +{ 0xC3FE, 0xC3FE, 0xC3FE }, +{ 0xC3FF, 0xC3FF, 0xC3FF }, +{ 0xC400, 0xC400, 0xC400 }, +{ 0xC401, 0xC401, 0xC401 }, +{ 0xC402, 0xC402, 0xC402 }, +{ 0xC403, 0xC403, 0xC403 }, +{ 0xC404, 0xC404, 0xC404 }, +{ 0xC405, 0xC405, 0xC405 }, +{ 0xC406, 0xC406, 0xC406 }, +{ 0xC407, 0xC407, 0xC407 }, +{ 0xC408, 0xC408, 0xC408 }, +{ 0xC409, 0xC409, 0xC409 }, +{ 0xC40A, 0xC40A, 0xC40A }, +{ 0xC40B, 0xC40B, 0xC40B }, +{ 0xC40C, 0xC40C, 0xC40C }, +{ 0xC40D, 0xC40D, 0xC40D }, +{ 0xC40E, 0xC40E, 0xC40E }, +{ 0xC40F, 0xC40F, 0xC40F }, +{ 0xC410, 0xC410, 0xC410 }, +{ 0xC411, 0xC411, 0xC411 }, +{ 0xC412, 0xC412, 0xC412 }, +{ 0xC413, 0xC413, 0xC413 }, +{ 0xC414, 0xC414, 0xC414 }, +{ 0xC415, 0xC415, 0xC415 }, +{ 0xC416, 0xC416, 0xC416 }, +{ 0xC417, 0xC417, 0xC417 }, +{ 0xC418, 0xC418, 0xC418 }, +{ 0xC419, 0xC419, 0xC419 }, +{ 0xC41A, 0xC41A, 0xC41A }, +{ 0xC41B, 0xC41B, 0xC41B }, +{ 0xC41C, 0xC41C, 0xC41C }, +{ 0xC41D, 0xC41D, 0xC41D }, +{ 0xC41E, 0xC41E, 0xC41E }, +{ 0xC41F, 0xC41F, 0xC41F }, +{ 0xC420, 0xC420, 0xC420 }, +{ 0xC421, 0xC421, 0xC421 }, +{ 0xC422, 0xC422, 0xC422 }, +{ 0xC423, 0xC423, 0xC423 }, +{ 0xC424, 0xC424, 0xC424 }, +{ 0xC425, 0xC425, 0xC425 }, +{ 0xC426, 0xC426, 0xC426 }, +{ 0xC427, 0xC427, 0xC427 }, +{ 0xC428, 0xC428, 0xC428 }, +{ 0xC429, 0xC429, 0xC429 }, +{ 0xC42A, 0xC42A, 0xC42A }, +{ 0xC42B, 0xC42B, 0xC42B }, +{ 0xC42C, 0xC42C, 0xC42C }, +{ 0xC42D, 0xC42D, 0xC42D }, +{ 0xC42E, 0xC42E, 0xC42E }, +{ 0xC42F, 0xC42F, 0xC42F }, +{ 0xC430, 0xC430, 0xC430 }, +{ 0xC431, 0xC431, 0xC431 }, +{ 0xC432, 0xC432, 0xC432 }, +{ 0xC433, 0xC433, 0xC433 }, +{ 0xC434, 0xC434, 0xC434 }, +{ 0xC435, 0xC435, 0xC435 }, +{ 0xC436, 0xC436, 0xC436 }, +{ 0xC437, 0xC437, 0xC437 }, +{ 0xC438, 0xC438, 0xC438 }, +{ 0xC439, 0xC439, 0xC439 }, +{ 0xC43A, 0xC43A, 0xC43A }, +{ 0xC43B, 0xC43B, 0xC43B }, +{ 0xC43C, 0xC43C, 0xC43C }, +{ 0xC43D, 0xC43D, 0xC43D }, +{ 0xC43E, 0xC43E, 0xC43E }, +{ 0xC43F, 0xC43F, 0xC43F }, +{ 0xC440, 0xC440, 0xC440 }, +{ 0xC441, 0xC441, 0xC441 }, +{ 0xC442, 0xC442, 0xC442 }, +{ 0xC443, 0xC443, 0xC443 }, +{ 0xC444, 0xC444, 0xC444 }, +{ 0xC445, 0xC445, 0xC445 }, +{ 0xC446, 0xC446, 0xC446 }, +{ 0xC447, 0xC447, 0xC447 }, +{ 0xC448, 0xC448, 0xC448 }, +{ 0xC449, 0xC449, 0xC449 }, +{ 0xC44A, 0xC44A, 0xC44A }, +{ 0xC44B, 0xC44B, 0xC44B }, +{ 0xC44C, 0xC44C, 0xC44C }, +{ 0xC44D, 0xC44D, 0xC44D }, +{ 0xC44E, 0xC44E, 0xC44E }, +{ 0xC44F, 0xC44F, 0xC44F }, +{ 0xC450, 0xC450, 0xC450 }, +{ 0xC451, 0xC451, 0xC451 }, +{ 0xC452, 0xC452, 0xC452 }, +{ 0xC453, 0xC453, 0xC453 }, +{ 0xC454, 0xC454, 0xC454 }, +{ 0xC455, 0xC455, 0xC455 }, +{ 0xC456, 0xC456, 0xC456 }, +{ 0xC457, 0xC457, 0xC457 }, +{ 0xC458, 0xC458, 0xC458 }, +{ 0xC459, 0xC459, 0xC459 }, +{ 0xC45A, 0xC45A, 0xC45A }, +{ 0xC45B, 0xC45B, 0xC45B }, +{ 0xC45C, 0xC45C, 0xC45C }, +{ 0xC45D, 0xC45D, 0xC45D }, +{ 0xC45E, 0xC45E, 0xC45E }, +{ 0xC45F, 0xC45F, 0xC45F }, +{ 0xC460, 0xC460, 0xC460 }, +{ 0xC461, 0xC461, 0xC461 }, +{ 0xC462, 0xC462, 0xC462 }, +{ 0xC463, 0xC463, 0xC463 }, +{ 0xC464, 0xC464, 0xC464 }, +{ 0xC465, 0xC465, 0xC465 }, +{ 0xC466, 0xC466, 0xC466 }, +{ 0xC467, 0xC467, 0xC467 }, +{ 0xC468, 0xC468, 0xC468 }, +{ 0xC469, 0xC469, 0xC469 }, +{ 0xC46A, 0xC46A, 0xC46A }, +{ 0xC46B, 0xC46B, 0xC46B }, +{ 0xC46C, 0xC46C, 0xC46C }, +{ 0xC46D, 0xC46D, 0xC46D }, +{ 0xC46E, 0xC46E, 0xC46E }, +{ 0xC46F, 0xC46F, 0xC46F }, +{ 0xC470, 0xC470, 0xC470 }, +{ 0xC471, 0xC471, 0xC471 }, +{ 0xC472, 0xC472, 0xC472 }, +{ 0xC473, 0xC473, 0xC473 }, +{ 0xC474, 0xC474, 0xC474 }, +{ 0xC475, 0xC475, 0xC475 }, +{ 0xC476, 0xC476, 0xC476 }, +{ 0xC477, 0xC477, 0xC477 }, +{ 0xC478, 0xC478, 0xC478 }, +{ 0xC479, 0xC479, 0xC479 }, +{ 0xC47A, 0xC47A, 0xC47A }, +{ 0xC47B, 0xC47B, 0xC47B }, +{ 0xC47C, 0xC47C, 0xC47C }, +{ 0xC47D, 0xC47D, 0xC47D }, +{ 0xC47E, 0xC47E, 0xC47E }, +{ 0xC47F, 0xC47F, 0xC47F }, +{ 0xC480, 0xC480, 0xC480 }, +{ 0xC481, 0xC481, 0xC481 }, +{ 0xC482, 0xC482, 0xC482 }, +{ 0xC483, 0xC483, 0xC483 }, +{ 0xC484, 0xC484, 0xC484 }, +{ 0xC485, 0xC485, 0xC485 }, +{ 0xC486, 0xC486, 0xC486 }, +{ 0xC487, 0xC487, 0xC487 }, +{ 0xC488, 0xC488, 0xC488 }, +{ 0xC489, 0xC489, 0xC489 }, +{ 0xC48A, 0xC48A, 0xC48A }, +{ 0xC48B, 0xC48B, 0xC48B }, +{ 0xC48C, 0xC48C, 0xC48C }, +{ 0xC48D, 0xC48D, 0xC48D }, +{ 0xC48E, 0xC48E, 0xC48E }, +{ 0xC48F, 0xC48F, 0xC48F }, +{ 0xC490, 0xC490, 0xC490 }, +{ 0xC491, 0xC491, 0xC491 }, +{ 0xC492, 0xC492, 0xC492 }, +{ 0xC493, 0xC493, 0xC493 }, +{ 0xC494, 0xC494, 0xC494 }, +{ 0xC495, 0xC495, 0xC495 }, +{ 0xC496, 0xC496, 0xC496 }, +{ 0xC497, 0xC497, 0xC497 }, +{ 0xC498, 0xC498, 0xC498 }, +{ 0xC499, 0xC499, 0xC499 }, +{ 0xC49A, 0xC49A, 0xC49A }, +{ 0xC49B, 0xC49B, 0xC49B }, +{ 0xC49C, 0xC49C, 0xC49C }, +{ 0xC49D, 0xC49D, 0xC49D }, +{ 0xC49E, 0xC49E, 0xC49E }, +{ 0xC49F, 0xC49F, 0xC49F }, +{ 0xC4A0, 0xC4A0, 0xC4A0 }, +{ 0xC4A1, 0xC4A1, 0xC4A1 }, +{ 0xC4A2, 0xC4A2, 0xC4A2 }, +{ 0xC4A3, 0xC4A3, 0xC4A3 }, +{ 0xC4A4, 0xC4A4, 0xC4A4 }, +{ 0xC4A5, 0xC4A5, 0xC4A5 }, +{ 0xC4A6, 0xC4A6, 0xC4A6 }, +{ 0xC4A7, 0xC4A7, 0xC4A7 }, +{ 0xC4A8, 0xC4A8, 0xC4A8 }, +{ 0xC4A9, 0xC4A9, 0xC4A9 }, +{ 0xC4AA, 0xC4AA, 0xC4AA }, +{ 0xC4AB, 0xC4AB, 0xC4AB }, +{ 0xC4AC, 0xC4AC, 0xC4AC }, +{ 0xC4AD, 0xC4AD, 0xC4AD }, +{ 0xC4AE, 0xC4AE, 0xC4AE }, +{ 0xC4AF, 0xC4AF, 0xC4AF }, +{ 0xC4B0, 0xC4B0, 0xC4B0 }, +{ 0xC4B1, 0xC4B1, 0xC4B1 }, +{ 0xC4B2, 0xC4B2, 0xC4B2 }, +{ 0xC4B3, 0xC4B3, 0xC4B3 }, +{ 0xC4B4, 0xC4B4, 0xC4B4 }, +{ 0xC4B5, 0xC4B5, 0xC4B5 }, +{ 0xC4B6, 0xC4B6, 0xC4B6 }, +{ 0xC4B7, 0xC4B7, 0xC4B7 }, +{ 0xC4B8, 0xC4B8, 0xC4B8 }, +{ 0xC4B9, 0xC4B9, 0xC4B9 }, +{ 0xC4BA, 0xC4BA, 0xC4BA }, +{ 0xC4BB, 0xC4BB, 0xC4BB }, +{ 0xC4BC, 0xC4BC, 0xC4BC }, +{ 0xC4BD, 0xC4BD, 0xC4BD }, +{ 0xC4BE, 0xC4BE, 0xC4BE }, +{ 0xC4BF, 0xC4BF, 0xC4BF }, +{ 0xC4C0, 0xC4C0, 0xC4C0 }, +{ 0xC4C1, 0xC4C1, 0xC4C1 }, +{ 0xC4C2, 0xC4C2, 0xC4C2 }, +{ 0xC4C3, 0xC4C3, 0xC4C3 }, +{ 0xC4C4, 0xC4C4, 0xC4C4 }, +{ 0xC4C5, 0xC4C5, 0xC4C5 }, +{ 0xC4C6, 0xC4C6, 0xC4C6 }, +{ 0xC4C7, 0xC4C7, 0xC4C7 }, +{ 0xC4C8, 0xC4C8, 0xC4C8 }, +{ 0xC4C9, 0xC4C9, 0xC4C9 }, +{ 0xC4CA, 0xC4CA, 0xC4CA }, +{ 0xC4CB, 0xC4CB, 0xC4CB }, +{ 0xC4CC, 0xC4CC, 0xC4CC }, +{ 0xC4CD, 0xC4CD, 0xC4CD }, +{ 0xC4CE, 0xC4CE, 0xC4CE }, +{ 0xC4CF, 0xC4CF, 0xC4CF }, +{ 0xC4D0, 0xC4D0, 0xC4D0 }, +{ 0xC4D1, 0xC4D1, 0xC4D1 }, +{ 0xC4D2, 0xC4D2, 0xC4D2 }, +{ 0xC4D3, 0xC4D3, 0xC4D3 }, +{ 0xC4D4, 0xC4D4, 0xC4D4 }, +{ 0xC4D5, 0xC4D5, 0xC4D5 }, +{ 0xC4D6, 0xC4D6, 0xC4D6 }, +{ 0xC4D7, 0xC4D7, 0xC4D7 }, +{ 0xC4D8, 0xC4D8, 0xC4D8 }, +{ 0xC4D9, 0xC4D9, 0xC4D9 }, +{ 0xC4DA, 0xC4DA, 0xC4DA }, +{ 0xC4DB, 0xC4DB, 0xC4DB }, +{ 0xC4DC, 0xC4DC, 0xC4DC }, +{ 0xC4DD, 0xC4DD, 0xC4DD }, +{ 0xC4DE, 0xC4DE, 0xC4DE }, +{ 0xC4DF, 0xC4DF, 0xC4DF }, +{ 0xC4E0, 0xC4E0, 0xC4E0 }, +{ 0xC4E1, 0xC4E1, 0xC4E1 }, +{ 0xC4E2, 0xC4E2, 0xC4E2 }, +{ 0xC4E3, 0xC4E3, 0xC4E3 }, +{ 0xC4E4, 0xC4E4, 0xC4E4 }, +{ 0xC4E5, 0xC4E5, 0xC4E5 }, +{ 0xC4E6, 0xC4E6, 0xC4E6 }, +{ 0xC4E7, 0xC4E7, 0xC4E7 }, +{ 0xC4E8, 0xC4E8, 0xC4E8 }, +{ 0xC4E9, 0xC4E9, 0xC4E9 }, +{ 0xC4EA, 0xC4EA, 0xC4EA }, +{ 0xC4EB, 0xC4EB, 0xC4EB }, +{ 0xC4EC, 0xC4EC, 0xC4EC }, +{ 0xC4ED, 0xC4ED, 0xC4ED }, +{ 0xC4EE, 0xC4EE, 0xC4EE }, +{ 0xC4EF, 0xC4EF, 0xC4EF }, +{ 0xC4F0, 0xC4F0, 0xC4F0 }, +{ 0xC4F1, 0xC4F1, 0xC4F1 }, +{ 0xC4F2, 0xC4F2, 0xC4F2 }, +{ 0xC4F3, 0xC4F3, 0xC4F3 }, +{ 0xC4F4, 0xC4F4, 0xC4F4 }, +{ 0xC4F5, 0xC4F5, 0xC4F5 }, +{ 0xC4F6, 0xC4F6, 0xC4F6 }, +{ 0xC4F7, 0xC4F7, 0xC4F7 }, +{ 0xC4F8, 0xC4F8, 0xC4F8 }, +{ 0xC4F9, 0xC4F9, 0xC4F9 }, +{ 0xC4FA, 0xC4FA, 0xC4FA }, +{ 0xC4FB, 0xC4FB, 0xC4FB }, +{ 0xC4FC, 0xC4FC, 0xC4FC }, +{ 0xC4FD, 0xC4FD, 0xC4FD }, +{ 0xC4FE, 0xC4FE, 0xC4FE }, +{ 0xC4FF, 0xC4FF, 0xC4FF }, +{ 0xC500, 0xC500, 0xC500 }, +{ 0xC501, 0xC501, 0xC501 }, +{ 0xC502, 0xC502, 0xC502 }, +{ 0xC503, 0xC503, 0xC503 }, +{ 0xC504, 0xC504, 0xC504 }, +{ 0xC505, 0xC505, 0xC505 }, +{ 0xC506, 0xC506, 0xC506 }, +{ 0xC507, 0xC507, 0xC507 }, +{ 0xC508, 0xC508, 0xC508 }, +{ 0xC509, 0xC509, 0xC509 }, +{ 0xC50A, 0xC50A, 0xC50A }, +{ 0xC50B, 0xC50B, 0xC50B }, +{ 0xC50C, 0xC50C, 0xC50C }, +{ 0xC50D, 0xC50D, 0xC50D }, +{ 0xC50E, 0xC50E, 0xC50E }, +{ 0xC50F, 0xC50F, 0xC50F }, +{ 0xC510, 0xC510, 0xC510 }, +{ 0xC511, 0xC511, 0xC511 }, +{ 0xC512, 0xC512, 0xC512 }, +{ 0xC513, 0xC513, 0xC513 }, +{ 0xC514, 0xC514, 0xC514 }, +{ 0xC515, 0xC515, 0xC515 }, +{ 0xC516, 0xC516, 0xC516 }, +{ 0xC517, 0xC517, 0xC517 }, +{ 0xC518, 0xC518, 0xC518 }, +{ 0xC519, 0xC519, 0xC519 }, +{ 0xC51A, 0xC51A, 0xC51A }, +{ 0xC51B, 0xC51B, 0xC51B }, +{ 0xC51C, 0xC51C, 0xC51C }, +{ 0xC51D, 0xC51D, 0xC51D }, +{ 0xC51E, 0xC51E, 0xC51E }, +{ 0xC51F, 0xC51F, 0xC51F }, +{ 0xC520, 0xC520, 0xC520 }, +{ 0xC521, 0xC521, 0xC521 }, +{ 0xC522, 0xC522, 0xC522 }, +{ 0xC523, 0xC523, 0xC523 }, +{ 0xC524, 0xC524, 0xC524 }, +{ 0xC525, 0xC525, 0xC525 }, +{ 0xC526, 0xC526, 0xC526 }, +{ 0xC527, 0xC527, 0xC527 }, +{ 0xC528, 0xC528, 0xC528 }, +{ 0xC529, 0xC529, 0xC529 }, +{ 0xC52A, 0xC52A, 0xC52A }, +{ 0xC52B, 0xC52B, 0xC52B }, +{ 0xC52C, 0xC52C, 0xC52C }, +{ 0xC52D, 0xC52D, 0xC52D }, +{ 0xC52E, 0xC52E, 0xC52E }, +{ 0xC52F, 0xC52F, 0xC52F }, +{ 0xC530, 0xC530, 0xC530 }, +{ 0xC531, 0xC531, 0xC531 }, +{ 0xC532, 0xC532, 0xC532 }, +{ 0xC533, 0xC533, 0xC533 }, +{ 0xC534, 0xC534, 0xC534 }, +{ 0xC535, 0xC535, 0xC535 }, +{ 0xC536, 0xC536, 0xC536 }, +{ 0xC537, 0xC537, 0xC537 }, +{ 0xC538, 0xC538, 0xC538 }, +{ 0xC539, 0xC539, 0xC539 }, +{ 0xC53A, 0xC53A, 0xC53A }, +{ 0xC53B, 0xC53B, 0xC53B }, +{ 0xC53C, 0xC53C, 0xC53C }, +{ 0xC53D, 0xC53D, 0xC53D }, +{ 0xC53E, 0xC53E, 0xC53E }, +{ 0xC53F, 0xC53F, 0xC53F }, +{ 0xC540, 0xC540, 0xC540 }, +{ 0xC541, 0xC541, 0xC541 }, +{ 0xC542, 0xC542, 0xC542 }, +{ 0xC543, 0xC543, 0xC543 }, +{ 0xC544, 0xC544, 0xC544 }, +{ 0xC545, 0xC545, 0xC545 }, +{ 0xC546, 0xC546, 0xC546 }, +{ 0xC547, 0xC547, 0xC547 }, +{ 0xC548, 0xC548, 0xC548 }, +{ 0xC549, 0xC549, 0xC549 }, +{ 0xC54A, 0xC54A, 0xC54A }, +{ 0xC54B, 0xC54B, 0xC54B }, +{ 0xC54C, 0xC54C, 0xC54C }, +{ 0xC54D, 0xC54D, 0xC54D }, +{ 0xC54E, 0xC54E, 0xC54E }, +{ 0xC54F, 0xC54F, 0xC54F }, +{ 0xC550, 0xC550, 0xC550 }, +{ 0xC551, 0xC551, 0xC551 }, +{ 0xC552, 0xC552, 0xC552 }, +{ 0xC553, 0xC553, 0xC553 }, +{ 0xC554, 0xC554, 0xC554 }, +{ 0xC555, 0xC555, 0xC555 }, +{ 0xC556, 0xC556, 0xC556 }, +{ 0xC557, 0xC557, 0xC557 }, +{ 0xC558, 0xC558, 0xC558 }, +{ 0xC559, 0xC559, 0xC559 }, +{ 0xC55A, 0xC55A, 0xC55A }, +{ 0xC55B, 0xC55B, 0xC55B }, +{ 0xC55C, 0xC55C, 0xC55C }, +{ 0xC55D, 0xC55D, 0xC55D }, +{ 0xC55E, 0xC55E, 0xC55E }, +{ 0xC55F, 0xC55F, 0xC55F }, +{ 0xC560, 0xC560, 0xC560 }, +{ 0xC561, 0xC561, 0xC561 }, +{ 0xC562, 0xC562, 0xC562 }, +{ 0xC563, 0xC563, 0xC563 }, +{ 0xC564, 0xC564, 0xC564 }, +{ 0xC565, 0xC565, 0xC565 }, +{ 0xC566, 0xC566, 0xC566 }, +{ 0xC567, 0xC567, 0xC567 }, +{ 0xC568, 0xC568, 0xC568 }, +{ 0xC569, 0xC569, 0xC569 }, +{ 0xC56A, 0xC56A, 0xC56A }, +{ 0xC56B, 0xC56B, 0xC56B }, +{ 0xC56C, 0xC56C, 0xC56C }, +{ 0xC56D, 0xC56D, 0xC56D }, +{ 0xC56E, 0xC56E, 0xC56E }, +{ 0xC56F, 0xC56F, 0xC56F }, +{ 0xC570, 0xC570, 0xC570 }, +{ 0xC571, 0xC571, 0xC571 }, +{ 0xC572, 0xC572, 0xC572 }, +{ 0xC573, 0xC573, 0xC573 }, +{ 0xC574, 0xC574, 0xC574 }, +{ 0xC575, 0xC575, 0xC575 }, +{ 0xC576, 0xC576, 0xC576 }, +{ 0xC577, 0xC577, 0xC577 }, +{ 0xC578, 0xC578, 0xC578 }, +{ 0xC579, 0xC579, 0xC579 }, +{ 0xC57A, 0xC57A, 0xC57A }, +{ 0xC57B, 0xC57B, 0xC57B }, +{ 0xC57C, 0xC57C, 0xC57C }, +{ 0xC57D, 0xC57D, 0xC57D }, +{ 0xC57E, 0xC57E, 0xC57E }, +{ 0xC57F, 0xC57F, 0xC57F }, +{ 0xC580, 0xC580, 0xC580 }, +{ 0xC581, 0xC581, 0xC581 }, +{ 0xC582, 0xC582, 0xC582 }, +{ 0xC583, 0xC583, 0xC583 }, +{ 0xC584, 0xC584, 0xC584 }, +{ 0xC585, 0xC585, 0xC585 }, +{ 0xC586, 0xC586, 0xC586 }, +{ 0xC587, 0xC587, 0xC587 }, +{ 0xC588, 0xC588, 0xC588 }, +{ 0xC589, 0xC589, 0xC589 }, +{ 0xC58A, 0xC58A, 0xC58A }, +{ 0xC58B, 0xC58B, 0xC58B }, +{ 0xC58C, 0xC58C, 0xC58C }, +{ 0xC58D, 0xC58D, 0xC58D }, +{ 0xC58E, 0xC58E, 0xC58E }, +{ 0xC58F, 0xC58F, 0xC58F }, +{ 0xC590, 0xC590, 0xC590 }, +{ 0xC591, 0xC591, 0xC591 }, +{ 0xC592, 0xC592, 0xC592 }, +{ 0xC593, 0xC593, 0xC593 }, +{ 0xC594, 0xC594, 0xC594 }, +{ 0xC595, 0xC595, 0xC595 }, +{ 0xC596, 0xC596, 0xC596 }, +{ 0xC597, 0xC597, 0xC597 }, +{ 0xC598, 0xC598, 0xC598 }, +{ 0xC599, 0xC599, 0xC599 }, +{ 0xC59A, 0xC59A, 0xC59A }, +{ 0xC59B, 0xC59B, 0xC59B }, +{ 0xC59C, 0xC59C, 0xC59C }, +{ 0xC59D, 0xC59D, 0xC59D }, +{ 0xC59E, 0xC59E, 0xC59E }, +{ 0xC59F, 0xC59F, 0xC59F }, +{ 0xC5A0, 0xC5A0, 0xC5A0 }, +{ 0xC5A1, 0xC5A1, 0xC5A1 }, +{ 0xC5A2, 0xC5A2, 0xC5A2 }, +{ 0xC5A3, 0xC5A3, 0xC5A3 }, +{ 0xC5A4, 0xC5A4, 0xC5A4 }, +{ 0xC5A5, 0xC5A5, 0xC5A5 }, +{ 0xC5A6, 0xC5A6, 0xC5A6 }, +{ 0xC5A7, 0xC5A7, 0xC5A7 }, +{ 0xC5A8, 0xC5A8, 0xC5A8 }, +{ 0xC5A9, 0xC5A9, 0xC5A9 }, +{ 0xC5AA, 0xC5AA, 0xC5AA }, +{ 0xC5AB, 0xC5AB, 0xC5AB }, +{ 0xC5AC, 0xC5AC, 0xC5AC }, +{ 0xC5AD, 0xC5AD, 0xC5AD }, +{ 0xC5AE, 0xC5AE, 0xC5AE }, +{ 0xC5AF, 0xC5AF, 0xC5AF }, +{ 0xC5B0, 0xC5B0, 0xC5B0 }, +{ 0xC5B1, 0xC5B1, 0xC5B1 }, +{ 0xC5B2, 0xC5B2, 0xC5B2 }, +{ 0xC5B3, 0xC5B3, 0xC5B3 }, +{ 0xC5B4, 0xC5B4, 0xC5B4 }, +{ 0xC5B5, 0xC5B5, 0xC5B5 }, +{ 0xC5B6, 0xC5B6, 0xC5B6 }, +{ 0xC5B7, 0xC5B7, 0xC5B7 }, +{ 0xC5B8, 0xC5B8, 0xC5B8 }, +{ 0xC5B9, 0xC5B9, 0xC5B9 }, +{ 0xC5BA, 0xC5BA, 0xC5BA }, +{ 0xC5BB, 0xC5BB, 0xC5BB }, +{ 0xC5BC, 0xC5BC, 0xC5BC }, +{ 0xC5BD, 0xC5BD, 0xC5BD }, +{ 0xC5BE, 0xC5BE, 0xC5BE }, +{ 0xC5BF, 0xC5BF, 0xC5BF }, +{ 0xC5C0, 0xC5C0, 0xC5C0 }, +{ 0xC5C1, 0xC5C1, 0xC5C1 }, +{ 0xC5C2, 0xC5C2, 0xC5C2 }, +{ 0xC5C3, 0xC5C3, 0xC5C3 }, +{ 0xC5C4, 0xC5C4, 0xC5C4 }, +{ 0xC5C5, 0xC5C5, 0xC5C5 }, +{ 0xC5C6, 0xC5C6, 0xC5C6 }, +{ 0xC5C7, 0xC5C7, 0xC5C7 }, +{ 0xC5C8, 0xC5C8, 0xC5C8 }, +{ 0xC5C9, 0xC5C9, 0xC5C9 }, +{ 0xC5CA, 0xC5CA, 0xC5CA }, +{ 0xC5CB, 0xC5CB, 0xC5CB }, +{ 0xC5CC, 0xC5CC, 0xC5CC }, +{ 0xC5CD, 0xC5CD, 0xC5CD }, +{ 0xC5CE, 0xC5CE, 0xC5CE }, +{ 0xC5CF, 0xC5CF, 0xC5CF }, +{ 0xC5D0, 0xC5D0, 0xC5D0 }, +{ 0xC5D1, 0xC5D1, 0xC5D1 }, +{ 0xC5D2, 0xC5D2, 0xC5D2 }, +{ 0xC5D3, 0xC5D3, 0xC5D3 }, +{ 0xC5D4, 0xC5D4, 0xC5D4 }, +{ 0xC5D5, 0xC5D5, 0xC5D5 }, +{ 0xC5D6, 0xC5D6, 0xC5D6 }, +{ 0xC5D7, 0xC5D7, 0xC5D7 }, +{ 0xC5D8, 0xC5D8, 0xC5D8 }, +{ 0xC5D9, 0xC5D9, 0xC5D9 }, +{ 0xC5DA, 0xC5DA, 0xC5DA }, +{ 0xC5DB, 0xC5DB, 0xC5DB }, +{ 0xC5DC, 0xC5DC, 0xC5DC }, +{ 0xC5DD, 0xC5DD, 0xC5DD }, +{ 0xC5DE, 0xC5DE, 0xC5DE }, +{ 0xC5DF, 0xC5DF, 0xC5DF }, +{ 0xC5E0, 0xC5E0, 0xC5E0 }, +{ 0xC5E1, 0xC5E1, 0xC5E1 }, +{ 0xC5E2, 0xC5E2, 0xC5E2 }, +{ 0xC5E3, 0xC5E3, 0xC5E3 }, +{ 0xC5E4, 0xC5E4, 0xC5E4 }, +{ 0xC5E5, 0xC5E5, 0xC5E5 }, +{ 0xC5E6, 0xC5E6, 0xC5E6 }, +{ 0xC5E7, 0xC5E7, 0xC5E7 }, +{ 0xC5E8, 0xC5E8, 0xC5E8 }, +{ 0xC5E9, 0xC5E9, 0xC5E9 }, +{ 0xC5EA, 0xC5EA, 0xC5EA }, +{ 0xC5EB, 0xC5EB, 0xC5EB }, +{ 0xC5EC, 0xC5EC, 0xC5EC }, +{ 0xC5ED, 0xC5ED, 0xC5ED }, +{ 0xC5EE, 0xC5EE, 0xC5EE }, +{ 0xC5EF, 0xC5EF, 0xC5EF }, +{ 0xC5F0, 0xC5F0, 0xC5F0 }, +{ 0xC5F1, 0xC5F1, 0xC5F1 }, +{ 0xC5F2, 0xC5F2, 0xC5F2 }, +{ 0xC5F3, 0xC5F3, 0xC5F3 }, +{ 0xC5F4, 0xC5F4, 0xC5F4 }, +{ 0xC5F5, 0xC5F5, 0xC5F5 }, +{ 0xC5F6, 0xC5F6, 0xC5F6 }, +{ 0xC5F7, 0xC5F7, 0xC5F7 }, +{ 0xC5F8, 0xC5F8, 0xC5F8 }, +{ 0xC5F9, 0xC5F9, 0xC5F9 }, +{ 0xC5FA, 0xC5FA, 0xC5FA }, +{ 0xC5FB, 0xC5FB, 0xC5FB }, +{ 0xC5FC, 0xC5FC, 0xC5FC }, +{ 0xC5FD, 0xC5FD, 0xC5FD }, +{ 0xC5FE, 0xC5FE, 0xC5FE }, +{ 0xC5FF, 0xC5FF, 0xC5FF }, +{ 0xC600, 0xC600, 0xC600 }, +{ 0xC601, 0xC601, 0xC601 }, +{ 0xC602, 0xC602, 0xC602 }, +{ 0xC603, 0xC603, 0xC603 }, +{ 0xC604, 0xC604, 0xC604 }, +{ 0xC605, 0xC605, 0xC605 }, +{ 0xC606, 0xC606, 0xC606 }, +{ 0xC607, 0xC607, 0xC607 }, +{ 0xC608, 0xC608, 0xC608 }, +{ 0xC609, 0xC609, 0xC609 }, +{ 0xC60A, 0xC60A, 0xC60A }, +{ 0xC60B, 0xC60B, 0xC60B }, +{ 0xC60C, 0xC60C, 0xC60C }, +{ 0xC60D, 0xC60D, 0xC60D }, +{ 0xC60E, 0xC60E, 0xC60E }, +{ 0xC60F, 0xC60F, 0xC60F }, +{ 0xC610, 0xC610, 0xC610 }, +{ 0xC611, 0xC611, 0xC611 }, +{ 0xC612, 0xC612, 0xC612 }, +{ 0xC613, 0xC613, 0xC613 }, +{ 0xC614, 0xC614, 0xC614 }, +{ 0xC615, 0xC615, 0xC615 }, +{ 0xC616, 0xC616, 0xC616 }, +{ 0xC617, 0xC617, 0xC617 }, +{ 0xC618, 0xC618, 0xC618 }, +{ 0xC619, 0xC619, 0xC619 }, +{ 0xC61A, 0xC61A, 0xC61A }, +{ 0xC61B, 0xC61B, 0xC61B }, +{ 0xC61C, 0xC61C, 0xC61C }, +{ 0xC61D, 0xC61D, 0xC61D }, +{ 0xC61E, 0xC61E, 0xC61E }, +{ 0xC61F, 0xC61F, 0xC61F }, +{ 0xC620, 0xC620, 0xC620 }, +{ 0xC621, 0xC621, 0xC621 }, +{ 0xC622, 0xC622, 0xC622 }, +{ 0xC623, 0xC623, 0xC623 }, +{ 0xC624, 0xC624, 0xC624 }, +{ 0xC625, 0xC625, 0xC625 }, +{ 0xC626, 0xC626, 0xC626 }, +{ 0xC627, 0xC627, 0xC627 }, +{ 0xC628, 0xC628, 0xC628 }, +{ 0xC629, 0xC629, 0xC629 }, +{ 0xC62A, 0xC62A, 0xC62A }, +{ 0xC62B, 0xC62B, 0xC62B }, +{ 0xC62C, 0xC62C, 0xC62C }, +{ 0xC62D, 0xC62D, 0xC62D }, +{ 0xC62E, 0xC62E, 0xC62E }, +{ 0xC62F, 0xC62F, 0xC62F }, +{ 0xC630, 0xC630, 0xC630 }, +{ 0xC631, 0xC631, 0xC631 }, +{ 0xC632, 0xC632, 0xC632 }, +{ 0xC633, 0xC633, 0xC633 }, +{ 0xC634, 0xC634, 0xC634 }, +{ 0xC635, 0xC635, 0xC635 }, +{ 0xC636, 0xC636, 0xC636 }, +{ 0xC637, 0xC637, 0xC637 }, +{ 0xC638, 0xC638, 0xC638 }, +{ 0xC639, 0xC639, 0xC639 }, +{ 0xC63A, 0xC63A, 0xC63A }, +{ 0xC63B, 0xC63B, 0xC63B }, +{ 0xC63C, 0xC63C, 0xC63C }, +{ 0xC63D, 0xC63D, 0xC63D }, +{ 0xC63E, 0xC63E, 0xC63E }, +{ 0xC63F, 0xC63F, 0xC63F }, +{ 0xC640, 0xC640, 0xC640 }, +{ 0xC641, 0xC641, 0xC641 }, +{ 0xC642, 0xC642, 0xC642 }, +{ 0xC643, 0xC643, 0xC643 }, +{ 0xC644, 0xC644, 0xC644 }, +{ 0xC645, 0xC645, 0xC645 }, +{ 0xC646, 0xC646, 0xC646 }, +{ 0xC647, 0xC647, 0xC647 }, +{ 0xC648, 0xC648, 0xC648 }, +{ 0xC649, 0xC649, 0xC649 }, +{ 0xC64A, 0xC64A, 0xC64A }, +{ 0xC64B, 0xC64B, 0xC64B }, +{ 0xC64C, 0xC64C, 0xC64C }, +{ 0xC64D, 0xC64D, 0xC64D }, +{ 0xC64E, 0xC64E, 0xC64E }, +{ 0xC64F, 0xC64F, 0xC64F }, +{ 0xC650, 0xC650, 0xC650 }, +{ 0xC651, 0xC651, 0xC651 }, +{ 0xC652, 0xC652, 0xC652 }, +{ 0xC653, 0xC653, 0xC653 }, +{ 0xC654, 0xC654, 0xC654 }, +{ 0xC655, 0xC655, 0xC655 }, +{ 0xC656, 0xC656, 0xC656 }, +{ 0xC657, 0xC657, 0xC657 }, +{ 0xC658, 0xC658, 0xC658 }, +{ 0xC659, 0xC659, 0xC659 }, +{ 0xC65A, 0xC65A, 0xC65A }, +{ 0xC65B, 0xC65B, 0xC65B }, +{ 0xC65C, 0xC65C, 0xC65C }, +{ 0xC65D, 0xC65D, 0xC65D }, +{ 0xC65E, 0xC65E, 0xC65E }, +{ 0xC65F, 0xC65F, 0xC65F }, +{ 0xC660, 0xC660, 0xC660 }, +{ 0xC661, 0xC661, 0xC661 }, +{ 0xC662, 0xC662, 0xC662 }, +{ 0xC663, 0xC663, 0xC663 }, +{ 0xC664, 0xC664, 0xC664 }, +{ 0xC665, 0xC665, 0xC665 }, +{ 0xC666, 0xC666, 0xC666 }, +{ 0xC667, 0xC667, 0xC667 }, +{ 0xC668, 0xC668, 0xC668 }, +{ 0xC669, 0xC669, 0xC669 }, +{ 0xC66A, 0xC66A, 0xC66A }, +{ 0xC66B, 0xC66B, 0xC66B }, +{ 0xC66C, 0xC66C, 0xC66C }, +{ 0xC66D, 0xC66D, 0xC66D }, +{ 0xC66E, 0xC66E, 0xC66E }, +{ 0xC66F, 0xC66F, 0xC66F }, +{ 0xC670, 0xC670, 0xC670 }, +{ 0xC671, 0xC671, 0xC671 }, +{ 0xC672, 0xC672, 0xC672 }, +{ 0xC673, 0xC673, 0xC673 }, +{ 0xC674, 0xC674, 0xC674 }, +{ 0xC675, 0xC675, 0xC675 }, +{ 0xC676, 0xC676, 0xC676 }, +{ 0xC677, 0xC677, 0xC677 }, +{ 0xC678, 0xC678, 0xC678 }, +{ 0xC679, 0xC679, 0xC679 }, +{ 0xC67A, 0xC67A, 0xC67A }, +{ 0xC67B, 0xC67B, 0xC67B }, +{ 0xC67C, 0xC67C, 0xC67C }, +{ 0xC67D, 0xC67D, 0xC67D }, +{ 0xC67E, 0xC67E, 0xC67E }, +{ 0xC67F, 0xC67F, 0xC67F }, +{ 0xC680, 0xC680, 0xC680 }, +{ 0xC681, 0xC681, 0xC681 }, +{ 0xC682, 0xC682, 0xC682 }, +{ 0xC683, 0xC683, 0xC683 }, +{ 0xC684, 0xC684, 0xC684 }, +{ 0xC685, 0xC685, 0xC685 }, +{ 0xC686, 0xC686, 0xC686 }, +{ 0xC687, 0xC687, 0xC687 }, +{ 0xC688, 0xC688, 0xC688 }, +{ 0xC689, 0xC689, 0xC689 }, +{ 0xC68A, 0xC68A, 0xC68A }, +{ 0xC68B, 0xC68B, 0xC68B }, +{ 0xC68C, 0xC68C, 0xC68C }, +{ 0xC68D, 0xC68D, 0xC68D }, +{ 0xC68E, 0xC68E, 0xC68E }, +{ 0xC68F, 0xC68F, 0xC68F }, +{ 0xC690, 0xC690, 0xC690 }, +{ 0xC691, 0xC691, 0xC691 }, +{ 0xC692, 0xC692, 0xC692 }, +{ 0xC693, 0xC693, 0xC693 }, +{ 0xC694, 0xC694, 0xC694 }, +{ 0xC695, 0xC695, 0xC695 }, +{ 0xC696, 0xC696, 0xC696 }, +{ 0xC697, 0xC697, 0xC697 }, +{ 0xC698, 0xC698, 0xC698 }, +{ 0xC699, 0xC699, 0xC699 }, +{ 0xC69A, 0xC69A, 0xC69A }, +{ 0xC69B, 0xC69B, 0xC69B }, +{ 0xC69C, 0xC69C, 0xC69C }, +{ 0xC69D, 0xC69D, 0xC69D }, +{ 0xC69E, 0xC69E, 0xC69E }, +{ 0xC69F, 0xC69F, 0xC69F }, +{ 0xC6A0, 0xC6A0, 0xC6A0 }, +{ 0xC6A1, 0xC6A1, 0xC6A1 }, +{ 0xC6A2, 0xC6A2, 0xC6A2 }, +{ 0xC6A3, 0xC6A3, 0xC6A3 }, +{ 0xC6A4, 0xC6A4, 0xC6A4 }, +{ 0xC6A5, 0xC6A5, 0xC6A5 }, +{ 0xC6A6, 0xC6A6, 0xC6A6 }, +{ 0xC6A7, 0xC6A7, 0xC6A7 }, +{ 0xC6A8, 0xC6A8, 0xC6A8 }, +{ 0xC6A9, 0xC6A9, 0xC6A9 }, +{ 0xC6AA, 0xC6AA, 0xC6AA }, +{ 0xC6AB, 0xC6AB, 0xC6AB }, +{ 0xC6AC, 0xC6AC, 0xC6AC }, +{ 0xC6AD, 0xC6AD, 0xC6AD }, +{ 0xC6AE, 0xC6AE, 0xC6AE }, +{ 0xC6AF, 0xC6AF, 0xC6AF }, +{ 0xC6B0, 0xC6B0, 0xC6B0 }, +{ 0xC6B1, 0xC6B1, 0xC6B1 }, +{ 0xC6B2, 0xC6B2, 0xC6B2 }, +{ 0xC6B3, 0xC6B3, 0xC6B3 }, +{ 0xC6B4, 0xC6B4, 0xC6B4 }, +{ 0xC6B5, 0xC6B5, 0xC6B5 }, +{ 0xC6B6, 0xC6B6, 0xC6B6 }, +{ 0xC6B7, 0xC6B7, 0xC6B7 }, +{ 0xC6B8, 0xC6B8, 0xC6B8 }, +{ 0xC6B9, 0xC6B9, 0xC6B9 }, +{ 0xC6BA, 0xC6BA, 0xC6BA }, +{ 0xC6BB, 0xC6BB, 0xC6BB }, +{ 0xC6BC, 0xC6BC, 0xC6BC }, +{ 0xC6BD, 0xC6BD, 0xC6BD }, +{ 0xC6BE, 0xC6BE, 0xC6BE }, +{ 0xC6BF, 0xC6BF, 0xC6BF }, +{ 0xC6C0, 0xC6C0, 0xC6C0 }, +{ 0xC6C1, 0xC6C1, 0xC6C1 }, +{ 0xC6C2, 0xC6C2, 0xC6C2 }, +{ 0xC6C3, 0xC6C3, 0xC6C3 }, +{ 0xC6C4, 0xC6C4, 0xC6C4 }, +{ 0xC6C5, 0xC6C5, 0xC6C5 }, +{ 0xC6C6, 0xC6C6, 0xC6C6 }, +{ 0xC6C7, 0xC6C7, 0xC6C7 }, +{ 0xC6C8, 0xC6C8, 0xC6C8 }, +{ 0xC6C9, 0xC6C9, 0xC6C9 }, +{ 0xC6CA, 0xC6CA, 0xC6CA }, +{ 0xC6CB, 0xC6CB, 0xC6CB }, +{ 0xC6CC, 0xC6CC, 0xC6CC }, +{ 0xC6CD, 0xC6CD, 0xC6CD }, +{ 0xC6CE, 0xC6CE, 0xC6CE }, +{ 0xC6CF, 0xC6CF, 0xC6CF }, +{ 0xC6D0, 0xC6D0, 0xC6D0 }, +{ 0xC6D1, 0xC6D1, 0xC6D1 }, +{ 0xC6D2, 0xC6D2, 0xC6D2 }, +{ 0xC6D3, 0xC6D3, 0xC6D3 }, +{ 0xC6D4, 0xC6D4, 0xC6D4 }, +{ 0xC6D5, 0xC6D5, 0xC6D5 }, +{ 0xC6D6, 0xC6D6, 0xC6D6 }, +{ 0xC6D7, 0xC6D7, 0xC6D7 }, +{ 0xC6D8, 0xC6D8, 0xC6D8 }, +{ 0xC6D9, 0xC6D9, 0xC6D9 }, +{ 0xC6DA, 0xC6DA, 0xC6DA }, +{ 0xC6DB, 0xC6DB, 0xC6DB }, +{ 0xC6DC, 0xC6DC, 0xC6DC }, +{ 0xC6DD, 0xC6DD, 0xC6DD }, +{ 0xC6DE, 0xC6DE, 0xC6DE }, +{ 0xC6DF, 0xC6DF, 0xC6DF }, +{ 0xC6E0, 0xC6E0, 0xC6E0 }, +{ 0xC6E1, 0xC6E1, 0xC6E1 }, +{ 0xC6E2, 0xC6E2, 0xC6E2 }, +{ 0xC6E3, 0xC6E3, 0xC6E3 }, +{ 0xC6E4, 0xC6E4, 0xC6E4 }, +{ 0xC6E5, 0xC6E5, 0xC6E5 }, +{ 0xC6E6, 0xC6E6, 0xC6E6 }, +{ 0xC6E7, 0xC6E7, 0xC6E7 }, +{ 0xC6E8, 0xC6E8, 0xC6E8 }, +{ 0xC6E9, 0xC6E9, 0xC6E9 }, +{ 0xC6EA, 0xC6EA, 0xC6EA }, +{ 0xC6EB, 0xC6EB, 0xC6EB }, +{ 0xC6EC, 0xC6EC, 0xC6EC }, +{ 0xC6ED, 0xC6ED, 0xC6ED }, +{ 0xC6EE, 0xC6EE, 0xC6EE }, +{ 0xC6EF, 0xC6EF, 0xC6EF }, +{ 0xC6F0, 0xC6F0, 0xC6F0 }, +{ 0xC6F1, 0xC6F1, 0xC6F1 }, +{ 0xC6F2, 0xC6F2, 0xC6F2 }, +{ 0xC6F3, 0xC6F3, 0xC6F3 }, +{ 0xC6F4, 0xC6F4, 0xC6F4 }, +{ 0xC6F5, 0xC6F5, 0xC6F5 }, +{ 0xC6F6, 0xC6F6, 0xC6F6 }, +{ 0xC6F7, 0xC6F7, 0xC6F7 }, +{ 0xC6F8, 0xC6F8, 0xC6F8 }, +{ 0xC6F9, 0xC6F9, 0xC6F9 }, +{ 0xC6FA, 0xC6FA, 0xC6FA }, +{ 0xC6FB, 0xC6FB, 0xC6FB }, +{ 0xC6FC, 0xC6FC, 0xC6FC }, +{ 0xC6FD, 0xC6FD, 0xC6FD }, +{ 0xC6FE, 0xC6FE, 0xC6FE }, +{ 0xC6FF, 0xC6FF, 0xC6FF }, +{ 0xC700, 0xC700, 0xC700 }, +{ 0xC701, 0xC701, 0xC701 }, +{ 0xC702, 0xC702, 0xC702 }, +{ 0xC703, 0xC703, 0xC703 }, +{ 0xC704, 0xC704, 0xC704 }, +{ 0xC705, 0xC705, 0xC705 }, +{ 0xC706, 0xC706, 0xC706 }, +{ 0xC707, 0xC707, 0xC707 }, +{ 0xC708, 0xC708, 0xC708 }, +{ 0xC709, 0xC709, 0xC709 }, +{ 0xC70A, 0xC70A, 0xC70A }, +{ 0xC70B, 0xC70B, 0xC70B }, +{ 0xC70C, 0xC70C, 0xC70C }, +{ 0xC70D, 0xC70D, 0xC70D }, +{ 0xC70E, 0xC70E, 0xC70E }, +{ 0xC70F, 0xC70F, 0xC70F }, +{ 0xC710, 0xC710, 0xC710 }, +{ 0xC711, 0xC711, 0xC711 }, +{ 0xC712, 0xC712, 0xC712 }, +{ 0xC713, 0xC713, 0xC713 }, +{ 0xC714, 0xC714, 0xC714 }, +{ 0xC715, 0xC715, 0xC715 }, +{ 0xC716, 0xC716, 0xC716 }, +{ 0xC717, 0xC717, 0xC717 }, +{ 0xC718, 0xC718, 0xC718 }, +{ 0xC719, 0xC719, 0xC719 }, +{ 0xC71A, 0xC71A, 0xC71A }, +{ 0xC71B, 0xC71B, 0xC71B }, +{ 0xC71C, 0xC71C, 0xC71C }, +{ 0xC71D, 0xC71D, 0xC71D }, +{ 0xC71E, 0xC71E, 0xC71E }, +{ 0xC71F, 0xC71F, 0xC71F }, +{ 0xC720, 0xC720, 0xC720 }, +{ 0xC721, 0xC721, 0xC721 }, +{ 0xC722, 0xC722, 0xC722 }, +{ 0xC723, 0xC723, 0xC723 }, +{ 0xC724, 0xC724, 0xC724 }, +{ 0xC725, 0xC725, 0xC725 }, +{ 0xC726, 0xC726, 0xC726 }, +{ 0xC727, 0xC727, 0xC727 }, +{ 0xC728, 0xC728, 0xC728 }, +{ 0xC729, 0xC729, 0xC729 }, +{ 0xC72A, 0xC72A, 0xC72A }, +{ 0xC72B, 0xC72B, 0xC72B }, +{ 0xC72C, 0xC72C, 0xC72C }, +{ 0xC72D, 0xC72D, 0xC72D }, +{ 0xC72E, 0xC72E, 0xC72E }, +{ 0xC72F, 0xC72F, 0xC72F }, +{ 0xC730, 0xC730, 0xC730 }, +{ 0xC731, 0xC731, 0xC731 }, +{ 0xC732, 0xC732, 0xC732 }, +{ 0xC733, 0xC733, 0xC733 }, +{ 0xC734, 0xC734, 0xC734 }, +{ 0xC735, 0xC735, 0xC735 }, +{ 0xC736, 0xC736, 0xC736 }, +{ 0xC737, 0xC737, 0xC737 }, +{ 0xC738, 0xC738, 0xC738 }, +{ 0xC739, 0xC739, 0xC739 }, +{ 0xC73A, 0xC73A, 0xC73A }, +{ 0xC73B, 0xC73B, 0xC73B }, +{ 0xC73C, 0xC73C, 0xC73C }, +{ 0xC73D, 0xC73D, 0xC73D }, +{ 0xC73E, 0xC73E, 0xC73E }, +{ 0xC73F, 0xC73F, 0xC73F }, +{ 0xC740, 0xC740, 0xC740 }, +{ 0xC741, 0xC741, 0xC741 }, +{ 0xC742, 0xC742, 0xC742 }, +{ 0xC743, 0xC743, 0xC743 }, +{ 0xC744, 0xC744, 0xC744 }, +{ 0xC745, 0xC745, 0xC745 }, +{ 0xC746, 0xC746, 0xC746 }, +{ 0xC747, 0xC747, 0xC747 }, +{ 0xC748, 0xC748, 0xC748 }, +{ 0xC749, 0xC749, 0xC749 }, +{ 0xC74A, 0xC74A, 0xC74A }, +{ 0xC74B, 0xC74B, 0xC74B }, +{ 0xC74C, 0xC74C, 0xC74C }, +{ 0xC74D, 0xC74D, 0xC74D }, +{ 0xC74E, 0xC74E, 0xC74E }, +{ 0xC74F, 0xC74F, 0xC74F }, +{ 0xC750, 0xC750, 0xC750 }, +{ 0xC751, 0xC751, 0xC751 }, +{ 0xC752, 0xC752, 0xC752 }, +{ 0xC753, 0xC753, 0xC753 }, +{ 0xC754, 0xC754, 0xC754 }, +{ 0xC755, 0xC755, 0xC755 }, +{ 0xC756, 0xC756, 0xC756 }, +{ 0xC757, 0xC757, 0xC757 }, +{ 0xC758, 0xC758, 0xC758 }, +{ 0xC759, 0xC759, 0xC759 }, +{ 0xC75A, 0xC75A, 0xC75A }, +{ 0xC75B, 0xC75B, 0xC75B }, +{ 0xC75C, 0xC75C, 0xC75C }, +{ 0xC75D, 0xC75D, 0xC75D }, +{ 0xC75E, 0xC75E, 0xC75E }, +{ 0xC75F, 0xC75F, 0xC75F }, +{ 0xC760, 0xC760, 0xC760 }, +{ 0xC761, 0xC761, 0xC761 }, +{ 0xC762, 0xC762, 0xC762 }, +{ 0xC763, 0xC763, 0xC763 }, +{ 0xC764, 0xC764, 0xC764 }, +{ 0xC765, 0xC765, 0xC765 }, +{ 0xC766, 0xC766, 0xC766 }, +{ 0xC767, 0xC767, 0xC767 }, +{ 0xC768, 0xC768, 0xC768 }, +{ 0xC769, 0xC769, 0xC769 }, +{ 0xC76A, 0xC76A, 0xC76A }, +{ 0xC76B, 0xC76B, 0xC76B }, +{ 0xC76C, 0xC76C, 0xC76C }, +{ 0xC76D, 0xC76D, 0xC76D }, +{ 0xC76E, 0xC76E, 0xC76E }, +{ 0xC76F, 0xC76F, 0xC76F }, +{ 0xC770, 0xC770, 0xC770 }, +{ 0xC771, 0xC771, 0xC771 }, +{ 0xC772, 0xC772, 0xC772 }, +{ 0xC773, 0xC773, 0xC773 }, +{ 0xC774, 0xC774, 0xC774 }, +{ 0xC775, 0xC775, 0xC775 }, +{ 0xC776, 0xC776, 0xC776 }, +{ 0xC777, 0xC777, 0xC777 }, +{ 0xC778, 0xC778, 0xC778 }, +{ 0xC779, 0xC779, 0xC779 }, +{ 0xC77A, 0xC77A, 0xC77A }, +{ 0xC77B, 0xC77B, 0xC77B }, +{ 0xC77C, 0xC77C, 0xC77C }, +{ 0xC77D, 0xC77D, 0xC77D }, +{ 0xC77E, 0xC77E, 0xC77E }, +{ 0xC77F, 0xC77F, 0xC77F }, +{ 0xC780, 0xC780, 0xC780 }, +{ 0xC781, 0xC781, 0xC781 }, +{ 0xC782, 0xC782, 0xC782 }, +{ 0xC783, 0xC783, 0xC783 }, +{ 0xC784, 0xC784, 0xC784 }, +{ 0xC785, 0xC785, 0xC785 }, +{ 0xC786, 0xC786, 0xC786 }, +{ 0xC787, 0xC787, 0xC787 }, +{ 0xC788, 0xC788, 0xC788 }, +{ 0xC789, 0xC789, 0xC789 }, +{ 0xC78A, 0xC78A, 0xC78A }, +{ 0xC78B, 0xC78B, 0xC78B }, +{ 0xC78C, 0xC78C, 0xC78C }, +{ 0xC78D, 0xC78D, 0xC78D }, +{ 0xC78E, 0xC78E, 0xC78E }, +{ 0xC78F, 0xC78F, 0xC78F }, +{ 0xC790, 0xC790, 0xC790 }, +{ 0xC791, 0xC791, 0xC791 }, +{ 0xC792, 0xC792, 0xC792 }, +{ 0xC793, 0xC793, 0xC793 }, +{ 0xC794, 0xC794, 0xC794 }, +{ 0xC795, 0xC795, 0xC795 }, +{ 0xC796, 0xC796, 0xC796 }, +{ 0xC797, 0xC797, 0xC797 }, +{ 0xC798, 0xC798, 0xC798 }, +{ 0xC799, 0xC799, 0xC799 }, +{ 0xC79A, 0xC79A, 0xC79A }, +{ 0xC79B, 0xC79B, 0xC79B }, +{ 0xC79C, 0xC79C, 0xC79C }, +{ 0xC79D, 0xC79D, 0xC79D }, +{ 0xC79E, 0xC79E, 0xC79E }, +{ 0xC79F, 0xC79F, 0xC79F }, +{ 0xC7A0, 0xC7A0, 0xC7A0 }, +{ 0xC7A1, 0xC7A1, 0xC7A1 }, +{ 0xC7A2, 0xC7A2, 0xC7A2 }, +{ 0xC7A3, 0xC7A3, 0xC7A3 }, +{ 0xC7A4, 0xC7A4, 0xC7A4 }, +{ 0xC7A5, 0xC7A5, 0xC7A5 }, +{ 0xC7A6, 0xC7A6, 0xC7A6 }, +{ 0xC7A7, 0xC7A7, 0xC7A7 }, +{ 0xC7A8, 0xC7A8, 0xC7A8 }, +{ 0xC7A9, 0xC7A9, 0xC7A9 }, +{ 0xC7AA, 0xC7AA, 0xC7AA }, +{ 0xC7AB, 0xC7AB, 0xC7AB }, +{ 0xC7AC, 0xC7AC, 0xC7AC }, +{ 0xC7AD, 0xC7AD, 0xC7AD }, +{ 0xC7AE, 0xC7AE, 0xC7AE }, +{ 0xC7AF, 0xC7AF, 0xC7AF }, +{ 0xC7B0, 0xC7B0, 0xC7B0 }, +{ 0xC7B1, 0xC7B1, 0xC7B1 }, +{ 0xC7B2, 0xC7B2, 0xC7B2 }, +{ 0xC7B3, 0xC7B3, 0xC7B3 }, +{ 0xC7B4, 0xC7B4, 0xC7B4 }, +{ 0xC7B5, 0xC7B5, 0xC7B5 }, +{ 0xC7B6, 0xC7B6, 0xC7B6 }, +{ 0xC7B7, 0xC7B7, 0xC7B7 }, +{ 0xC7B8, 0xC7B8, 0xC7B8 }, +{ 0xC7B9, 0xC7B9, 0xC7B9 }, +{ 0xC7BA, 0xC7BA, 0xC7BA }, +{ 0xC7BB, 0xC7BB, 0xC7BB }, +{ 0xC7BC, 0xC7BC, 0xC7BC }, +{ 0xC7BD, 0xC7BD, 0xC7BD }, +{ 0xC7BE, 0xC7BE, 0xC7BE }, +{ 0xC7BF, 0xC7BF, 0xC7BF }, +{ 0xC7C0, 0xC7C0, 0xC7C0 }, +{ 0xC7C1, 0xC7C1, 0xC7C1 }, +{ 0xC7C2, 0xC7C2, 0xC7C2 }, +{ 0xC7C3, 0xC7C3, 0xC7C3 }, +{ 0xC7C4, 0xC7C4, 0xC7C4 }, +{ 0xC7C5, 0xC7C5, 0xC7C5 }, +{ 0xC7C6, 0xC7C6, 0xC7C6 }, +{ 0xC7C7, 0xC7C7, 0xC7C7 }, +{ 0xC7C8, 0xC7C8, 0xC7C8 }, +{ 0xC7C9, 0xC7C9, 0xC7C9 }, +{ 0xC7CA, 0xC7CA, 0xC7CA }, +{ 0xC7CB, 0xC7CB, 0xC7CB }, +{ 0xC7CC, 0xC7CC, 0xC7CC }, +{ 0xC7CD, 0xC7CD, 0xC7CD }, +{ 0xC7CE, 0xC7CE, 0xC7CE }, +{ 0xC7CF, 0xC7CF, 0xC7CF }, +{ 0xC7D0, 0xC7D0, 0xC7D0 }, +{ 0xC7D1, 0xC7D1, 0xC7D1 }, +{ 0xC7D2, 0xC7D2, 0xC7D2 }, +{ 0xC7D3, 0xC7D3, 0xC7D3 }, +{ 0xC7D4, 0xC7D4, 0xC7D4 }, +{ 0xC7D5, 0xC7D5, 0xC7D5 }, +{ 0xC7D6, 0xC7D6, 0xC7D6 }, +{ 0xC7D7, 0xC7D7, 0xC7D7 }, +{ 0xC7D8, 0xC7D8, 0xC7D8 }, +{ 0xC7D9, 0xC7D9, 0xC7D9 }, +{ 0xC7DA, 0xC7DA, 0xC7DA }, +{ 0xC7DB, 0xC7DB, 0xC7DB }, +{ 0xC7DC, 0xC7DC, 0xC7DC }, +{ 0xC7DD, 0xC7DD, 0xC7DD }, +{ 0xC7DE, 0xC7DE, 0xC7DE }, +{ 0xC7DF, 0xC7DF, 0xC7DF }, +{ 0xC7E0, 0xC7E0, 0xC7E0 }, +{ 0xC7E1, 0xC7E1, 0xC7E1 }, +{ 0xC7E2, 0xC7E2, 0xC7E2 }, +{ 0xC7E3, 0xC7E3, 0xC7E3 }, +{ 0xC7E4, 0xC7E4, 0xC7E4 }, +{ 0xC7E5, 0xC7E5, 0xC7E5 }, +{ 0xC7E6, 0xC7E6, 0xC7E6 }, +{ 0xC7E7, 0xC7E7, 0xC7E7 }, +{ 0xC7E8, 0xC7E8, 0xC7E8 }, +{ 0xC7E9, 0xC7E9, 0xC7E9 }, +{ 0xC7EA, 0xC7EA, 0xC7EA }, +{ 0xC7EB, 0xC7EB, 0xC7EB }, +{ 0xC7EC, 0xC7EC, 0xC7EC }, +{ 0xC7ED, 0xC7ED, 0xC7ED }, +{ 0xC7EE, 0xC7EE, 0xC7EE }, +{ 0xC7EF, 0xC7EF, 0xC7EF }, +{ 0xC7F0, 0xC7F0, 0xC7F0 }, +{ 0xC7F1, 0xC7F1, 0xC7F1 }, +{ 0xC7F2, 0xC7F2, 0xC7F2 }, +{ 0xC7F3, 0xC7F3, 0xC7F3 }, +{ 0xC7F4, 0xC7F4, 0xC7F4 }, +{ 0xC7F5, 0xC7F5, 0xC7F5 }, +{ 0xC7F6, 0xC7F6, 0xC7F6 }, +{ 0xC7F7, 0xC7F7, 0xC7F7 }, +{ 0xC7F8, 0xC7F8, 0xC7F8 }, +{ 0xC7F9, 0xC7F9, 0xC7F9 }, +{ 0xC7FA, 0xC7FA, 0xC7FA }, +{ 0xC7FB, 0xC7FB, 0xC7FB }, +{ 0xC7FC, 0xC7FC, 0xC7FC }, +{ 0xC7FD, 0xC7FD, 0xC7FD }, +{ 0xC7FE, 0xC7FE, 0xC7FE }, +{ 0xC7FF, 0xC7FF, 0xC7FF }, +{ 0xC800, 0xC800, 0xC800 }, +{ 0xC801, 0xC801, 0xC801 }, +{ 0xC802, 0xC802, 0xC802 }, +{ 0xC803, 0xC803, 0xC803 }, +{ 0xC804, 0xC804, 0xC804 }, +{ 0xC805, 0xC805, 0xC805 }, +{ 0xC806, 0xC806, 0xC806 }, +{ 0xC807, 0xC807, 0xC807 }, +{ 0xC808, 0xC808, 0xC808 }, +{ 0xC809, 0xC809, 0xC809 }, +{ 0xC80A, 0xC80A, 0xC80A }, +{ 0xC80B, 0xC80B, 0xC80B }, +{ 0xC80C, 0xC80C, 0xC80C }, +{ 0xC80D, 0xC80D, 0xC80D }, +{ 0xC80E, 0xC80E, 0xC80E }, +{ 0xC80F, 0xC80F, 0xC80F }, +{ 0xC810, 0xC810, 0xC810 }, +{ 0xC811, 0xC811, 0xC811 }, +{ 0xC812, 0xC812, 0xC812 }, +{ 0xC813, 0xC813, 0xC813 }, +{ 0xC814, 0xC814, 0xC814 }, +{ 0xC815, 0xC815, 0xC815 }, +{ 0xC816, 0xC816, 0xC816 }, +{ 0xC817, 0xC817, 0xC817 }, +{ 0xC818, 0xC818, 0xC818 }, +{ 0xC819, 0xC819, 0xC819 }, +{ 0xC81A, 0xC81A, 0xC81A }, +{ 0xC81B, 0xC81B, 0xC81B }, +{ 0xC81C, 0xC81C, 0xC81C }, +{ 0xC81D, 0xC81D, 0xC81D }, +{ 0xC81E, 0xC81E, 0xC81E }, +{ 0xC81F, 0xC81F, 0xC81F }, +{ 0xC820, 0xC820, 0xC820 }, +{ 0xC821, 0xC821, 0xC821 }, +{ 0xC822, 0xC822, 0xC822 }, +{ 0xC823, 0xC823, 0xC823 }, +{ 0xC824, 0xC824, 0xC824 }, +{ 0xC825, 0xC825, 0xC825 }, +{ 0xC826, 0xC826, 0xC826 }, +{ 0xC827, 0xC827, 0xC827 }, +{ 0xC828, 0xC828, 0xC828 }, +{ 0xC829, 0xC829, 0xC829 }, +{ 0xC82A, 0xC82A, 0xC82A }, +{ 0xC82B, 0xC82B, 0xC82B }, +{ 0xC82C, 0xC82C, 0xC82C }, +{ 0xC82D, 0xC82D, 0xC82D }, +{ 0xC82E, 0xC82E, 0xC82E }, +{ 0xC82F, 0xC82F, 0xC82F }, +{ 0xC830, 0xC830, 0xC830 }, +{ 0xC831, 0xC831, 0xC831 }, +{ 0xC832, 0xC832, 0xC832 }, +{ 0xC833, 0xC833, 0xC833 }, +{ 0xC834, 0xC834, 0xC834 }, +{ 0xC835, 0xC835, 0xC835 }, +{ 0xC836, 0xC836, 0xC836 }, +{ 0xC837, 0xC837, 0xC837 }, +{ 0xC838, 0xC838, 0xC838 }, +{ 0xC839, 0xC839, 0xC839 }, +{ 0xC83A, 0xC83A, 0xC83A }, +{ 0xC83B, 0xC83B, 0xC83B }, +{ 0xC83C, 0xC83C, 0xC83C }, +{ 0xC83D, 0xC83D, 0xC83D }, +{ 0xC83E, 0xC83E, 0xC83E }, +{ 0xC83F, 0xC83F, 0xC83F }, +{ 0xC840, 0xC840, 0xC840 }, +{ 0xC841, 0xC841, 0xC841 }, +{ 0xC842, 0xC842, 0xC842 }, +{ 0xC843, 0xC843, 0xC843 }, +{ 0xC844, 0xC844, 0xC844 }, +{ 0xC845, 0xC845, 0xC845 }, +{ 0xC846, 0xC846, 0xC846 }, +{ 0xC847, 0xC847, 0xC847 }, +{ 0xC848, 0xC848, 0xC848 }, +{ 0xC849, 0xC849, 0xC849 }, +{ 0xC84A, 0xC84A, 0xC84A }, +{ 0xC84B, 0xC84B, 0xC84B }, +{ 0xC84C, 0xC84C, 0xC84C }, +{ 0xC84D, 0xC84D, 0xC84D }, +{ 0xC84E, 0xC84E, 0xC84E }, +{ 0xC84F, 0xC84F, 0xC84F }, +{ 0xC850, 0xC850, 0xC850 }, +{ 0xC851, 0xC851, 0xC851 }, +{ 0xC852, 0xC852, 0xC852 }, +{ 0xC853, 0xC853, 0xC853 }, +{ 0xC854, 0xC854, 0xC854 }, +{ 0xC855, 0xC855, 0xC855 }, +{ 0xC856, 0xC856, 0xC856 }, +{ 0xC857, 0xC857, 0xC857 }, +{ 0xC858, 0xC858, 0xC858 }, +{ 0xC859, 0xC859, 0xC859 }, +{ 0xC85A, 0xC85A, 0xC85A }, +{ 0xC85B, 0xC85B, 0xC85B }, +{ 0xC85C, 0xC85C, 0xC85C }, +{ 0xC85D, 0xC85D, 0xC85D }, +{ 0xC85E, 0xC85E, 0xC85E }, +{ 0xC85F, 0xC85F, 0xC85F }, +{ 0xC860, 0xC860, 0xC860 }, +{ 0xC861, 0xC861, 0xC861 }, +{ 0xC862, 0xC862, 0xC862 }, +{ 0xC863, 0xC863, 0xC863 }, +{ 0xC864, 0xC864, 0xC864 }, +{ 0xC865, 0xC865, 0xC865 }, +{ 0xC866, 0xC866, 0xC866 }, +{ 0xC867, 0xC867, 0xC867 }, +{ 0xC868, 0xC868, 0xC868 }, +{ 0xC869, 0xC869, 0xC869 }, +{ 0xC86A, 0xC86A, 0xC86A }, +{ 0xC86B, 0xC86B, 0xC86B }, +{ 0xC86C, 0xC86C, 0xC86C }, +{ 0xC86D, 0xC86D, 0xC86D }, +{ 0xC86E, 0xC86E, 0xC86E }, +{ 0xC86F, 0xC86F, 0xC86F }, +{ 0xC870, 0xC870, 0xC870 }, +{ 0xC871, 0xC871, 0xC871 }, +{ 0xC872, 0xC872, 0xC872 }, +{ 0xC873, 0xC873, 0xC873 }, +{ 0xC874, 0xC874, 0xC874 }, +{ 0xC875, 0xC875, 0xC875 }, +{ 0xC876, 0xC876, 0xC876 }, +{ 0xC877, 0xC877, 0xC877 }, +{ 0xC878, 0xC878, 0xC878 }, +{ 0xC879, 0xC879, 0xC879 }, +{ 0xC87A, 0xC87A, 0xC87A }, +{ 0xC87B, 0xC87B, 0xC87B }, +{ 0xC87C, 0xC87C, 0xC87C }, +{ 0xC87D, 0xC87D, 0xC87D }, +{ 0xC87E, 0xC87E, 0xC87E }, +{ 0xC87F, 0xC87F, 0xC87F }, +{ 0xC880, 0xC880, 0xC880 }, +{ 0xC881, 0xC881, 0xC881 }, +{ 0xC882, 0xC882, 0xC882 }, +{ 0xC883, 0xC883, 0xC883 }, +{ 0xC884, 0xC884, 0xC884 }, +{ 0xC885, 0xC885, 0xC885 }, +{ 0xC886, 0xC886, 0xC886 }, +{ 0xC887, 0xC887, 0xC887 }, +{ 0xC888, 0xC888, 0xC888 }, +{ 0xC889, 0xC889, 0xC889 }, +{ 0xC88A, 0xC88A, 0xC88A }, +{ 0xC88B, 0xC88B, 0xC88B }, +{ 0xC88C, 0xC88C, 0xC88C }, +{ 0xC88D, 0xC88D, 0xC88D }, +{ 0xC88E, 0xC88E, 0xC88E }, +{ 0xC88F, 0xC88F, 0xC88F }, +{ 0xC890, 0xC890, 0xC890 }, +{ 0xC891, 0xC891, 0xC891 }, +{ 0xC892, 0xC892, 0xC892 }, +{ 0xC893, 0xC893, 0xC893 }, +{ 0xC894, 0xC894, 0xC894 }, +{ 0xC895, 0xC895, 0xC895 }, +{ 0xC896, 0xC896, 0xC896 }, +{ 0xC897, 0xC897, 0xC897 }, +{ 0xC898, 0xC898, 0xC898 }, +{ 0xC899, 0xC899, 0xC899 }, +{ 0xC89A, 0xC89A, 0xC89A }, +{ 0xC89B, 0xC89B, 0xC89B }, +{ 0xC89C, 0xC89C, 0xC89C }, +{ 0xC89D, 0xC89D, 0xC89D }, +{ 0xC89E, 0xC89E, 0xC89E }, +{ 0xC89F, 0xC89F, 0xC89F }, +{ 0xC8A0, 0xC8A0, 0xC8A0 }, +{ 0xC8A1, 0xC8A1, 0xC8A1 }, +{ 0xC8A2, 0xC8A2, 0xC8A2 }, +{ 0xC8A3, 0xC8A3, 0xC8A3 }, +{ 0xC8A4, 0xC8A4, 0xC8A4 }, +{ 0xC8A5, 0xC8A5, 0xC8A5 }, +{ 0xC8A6, 0xC8A6, 0xC8A6 }, +{ 0xC8A7, 0xC8A7, 0xC8A7 }, +{ 0xC8A8, 0xC8A8, 0xC8A8 }, +{ 0xC8A9, 0xC8A9, 0xC8A9 }, +{ 0xC8AA, 0xC8AA, 0xC8AA }, +{ 0xC8AB, 0xC8AB, 0xC8AB }, +{ 0xC8AC, 0xC8AC, 0xC8AC }, +{ 0xC8AD, 0xC8AD, 0xC8AD }, +{ 0xC8AE, 0xC8AE, 0xC8AE }, +{ 0xC8AF, 0xC8AF, 0xC8AF }, +{ 0xC8B0, 0xC8B0, 0xC8B0 }, +{ 0xC8B1, 0xC8B1, 0xC8B1 }, +{ 0xC8B2, 0xC8B2, 0xC8B2 }, +{ 0xC8B3, 0xC8B3, 0xC8B3 }, +{ 0xC8B4, 0xC8B4, 0xC8B4 }, +{ 0xC8B5, 0xC8B5, 0xC8B5 }, +{ 0xC8B6, 0xC8B6, 0xC8B6 }, +{ 0xC8B7, 0xC8B7, 0xC8B7 }, +{ 0xC8B8, 0xC8B8, 0xC8B8 }, +{ 0xC8B9, 0xC8B9, 0xC8B9 }, +{ 0xC8BA, 0xC8BA, 0xC8BA }, +{ 0xC8BB, 0xC8BB, 0xC8BB }, +{ 0xC8BC, 0xC8BC, 0xC8BC }, +{ 0xC8BD, 0xC8BD, 0xC8BD }, +{ 0xC8BE, 0xC8BE, 0xC8BE }, +{ 0xC8BF, 0xC8BF, 0xC8BF }, +{ 0xC8C0, 0xC8C0, 0xC8C0 }, +{ 0xC8C1, 0xC8C1, 0xC8C1 }, +{ 0xC8C2, 0xC8C2, 0xC8C2 }, +{ 0xC8C3, 0xC8C3, 0xC8C3 }, +{ 0xC8C4, 0xC8C4, 0xC8C4 }, +{ 0xC8C5, 0xC8C5, 0xC8C5 }, +{ 0xC8C6, 0xC8C6, 0xC8C6 }, +{ 0xC8C7, 0xC8C7, 0xC8C7 }, +{ 0xC8C8, 0xC8C8, 0xC8C8 }, +{ 0xC8C9, 0xC8C9, 0xC8C9 }, +{ 0xC8CA, 0xC8CA, 0xC8CA }, +{ 0xC8CB, 0xC8CB, 0xC8CB }, +{ 0xC8CC, 0xC8CC, 0xC8CC }, +{ 0xC8CD, 0xC8CD, 0xC8CD }, +{ 0xC8CE, 0xC8CE, 0xC8CE }, +{ 0xC8CF, 0xC8CF, 0xC8CF }, +{ 0xC8D0, 0xC8D0, 0xC8D0 }, +{ 0xC8D1, 0xC8D1, 0xC8D1 }, +{ 0xC8D2, 0xC8D2, 0xC8D2 }, +{ 0xC8D3, 0xC8D3, 0xC8D3 }, +{ 0xC8D4, 0xC8D4, 0xC8D4 }, +{ 0xC8D5, 0xC8D5, 0xC8D5 }, +{ 0xC8D6, 0xC8D6, 0xC8D6 }, +{ 0xC8D7, 0xC8D7, 0xC8D7 }, +{ 0xC8D8, 0xC8D8, 0xC8D8 }, +{ 0xC8D9, 0xC8D9, 0xC8D9 }, +{ 0xC8DA, 0xC8DA, 0xC8DA }, +{ 0xC8DB, 0xC8DB, 0xC8DB }, +{ 0xC8DC, 0xC8DC, 0xC8DC }, +{ 0xC8DD, 0xC8DD, 0xC8DD }, +{ 0xC8DE, 0xC8DE, 0xC8DE }, +{ 0xC8DF, 0xC8DF, 0xC8DF }, +{ 0xC8E0, 0xC8E0, 0xC8E0 }, +{ 0xC8E1, 0xC8E1, 0xC8E1 }, +{ 0xC8E2, 0xC8E2, 0xC8E2 }, +{ 0xC8E3, 0xC8E3, 0xC8E3 }, +{ 0xC8E4, 0xC8E4, 0xC8E4 }, +{ 0xC8E5, 0xC8E5, 0xC8E5 }, +{ 0xC8E6, 0xC8E6, 0xC8E6 }, +{ 0xC8E7, 0xC8E7, 0xC8E7 }, +{ 0xC8E8, 0xC8E8, 0xC8E8 }, +{ 0xC8E9, 0xC8E9, 0xC8E9 }, +{ 0xC8EA, 0xC8EA, 0xC8EA }, +{ 0xC8EB, 0xC8EB, 0xC8EB }, +{ 0xC8EC, 0xC8EC, 0xC8EC }, +{ 0xC8ED, 0xC8ED, 0xC8ED }, +{ 0xC8EE, 0xC8EE, 0xC8EE }, +{ 0xC8EF, 0xC8EF, 0xC8EF }, +{ 0xC8F0, 0xC8F0, 0xC8F0 }, +{ 0xC8F1, 0xC8F1, 0xC8F1 }, +{ 0xC8F2, 0xC8F2, 0xC8F2 }, +{ 0xC8F3, 0xC8F3, 0xC8F3 }, +{ 0xC8F4, 0xC8F4, 0xC8F4 }, +{ 0xC8F5, 0xC8F5, 0xC8F5 }, +{ 0xC8F6, 0xC8F6, 0xC8F6 }, +{ 0xC8F7, 0xC8F7, 0xC8F7 }, +{ 0xC8F8, 0xC8F8, 0xC8F8 }, +{ 0xC8F9, 0xC8F9, 0xC8F9 }, +{ 0xC8FA, 0xC8FA, 0xC8FA }, +{ 0xC8FB, 0xC8FB, 0xC8FB }, +{ 0xC8FC, 0xC8FC, 0xC8FC }, +{ 0xC8FD, 0xC8FD, 0xC8FD }, +{ 0xC8FE, 0xC8FE, 0xC8FE }, +{ 0xC8FF, 0xC8FF, 0xC8FF }, +{ 0xC900, 0xC900, 0xC900 }, +{ 0xC901, 0xC901, 0xC901 }, +{ 0xC902, 0xC902, 0xC902 }, +{ 0xC903, 0xC903, 0xC903 }, +{ 0xC904, 0xC904, 0xC904 }, +{ 0xC905, 0xC905, 0xC905 }, +{ 0xC906, 0xC906, 0xC906 }, +{ 0xC907, 0xC907, 0xC907 }, +{ 0xC908, 0xC908, 0xC908 }, +{ 0xC909, 0xC909, 0xC909 }, +{ 0xC90A, 0xC90A, 0xC90A }, +{ 0xC90B, 0xC90B, 0xC90B }, +{ 0xC90C, 0xC90C, 0xC90C }, +{ 0xC90D, 0xC90D, 0xC90D }, +{ 0xC90E, 0xC90E, 0xC90E }, +{ 0xC90F, 0xC90F, 0xC90F }, +{ 0xC910, 0xC910, 0xC910 }, +{ 0xC911, 0xC911, 0xC911 }, +{ 0xC912, 0xC912, 0xC912 }, +{ 0xC913, 0xC913, 0xC913 }, +{ 0xC914, 0xC914, 0xC914 }, +{ 0xC915, 0xC915, 0xC915 }, +{ 0xC916, 0xC916, 0xC916 }, +{ 0xC917, 0xC917, 0xC917 }, +{ 0xC918, 0xC918, 0xC918 }, +{ 0xC919, 0xC919, 0xC919 }, +{ 0xC91A, 0xC91A, 0xC91A }, +{ 0xC91B, 0xC91B, 0xC91B }, +{ 0xC91C, 0xC91C, 0xC91C }, +{ 0xC91D, 0xC91D, 0xC91D }, +{ 0xC91E, 0xC91E, 0xC91E }, +{ 0xC91F, 0xC91F, 0xC91F }, +{ 0xC920, 0xC920, 0xC920 }, +{ 0xC921, 0xC921, 0xC921 }, +{ 0xC922, 0xC922, 0xC922 }, +{ 0xC923, 0xC923, 0xC923 }, +{ 0xC924, 0xC924, 0xC924 }, +{ 0xC925, 0xC925, 0xC925 }, +{ 0xC926, 0xC926, 0xC926 }, +{ 0xC927, 0xC927, 0xC927 }, +{ 0xC928, 0xC928, 0xC928 }, +{ 0xC929, 0xC929, 0xC929 }, +{ 0xC92A, 0xC92A, 0xC92A }, +{ 0xC92B, 0xC92B, 0xC92B }, +{ 0xC92C, 0xC92C, 0xC92C }, +{ 0xC92D, 0xC92D, 0xC92D }, +{ 0xC92E, 0xC92E, 0xC92E }, +{ 0xC92F, 0xC92F, 0xC92F }, +{ 0xC930, 0xC930, 0xC930 }, +{ 0xC931, 0xC931, 0xC931 }, +{ 0xC932, 0xC932, 0xC932 }, +{ 0xC933, 0xC933, 0xC933 }, +{ 0xC934, 0xC934, 0xC934 }, +{ 0xC935, 0xC935, 0xC935 }, +{ 0xC936, 0xC936, 0xC936 }, +{ 0xC937, 0xC937, 0xC937 }, +{ 0xC938, 0xC938, 0xC938 }, +{ 0xC939, 0xC939, 0xC939 }, +{ 0xC93A, 0xC93A, 0xC93A }, +{ 0xC93B, 0xC93B, 0xC93B }, +{ 0xC93C, 0xC93C, 0xC93C }, +{ 0xC93D, 0xC93D, 0xC93D }, +{ 0xC93E, 0xC93E, 0xC93E }, +{ 0xC93F, 0xC93F, 0xC93F }, +{ 0xC940, 0xC940, 0xC940 }, +{ 0xC941, 0xC941, 0xC941 }, +{ 0xC942, 0xC942, 0xC942 }, +{ 0xC943, 0xC943, 0xC943 }, +{ 0xC944, 0xC944, 0xC944 }, +{ 0xC945, 0xC945, 0xC945 }, +{ 0xC946, 0xC946, 0xC946 }, +{ 0xC947, 0xC947, 0xC947 }, +{ 0xC948, 0xC948, 0xC948 }, +{ 0xC949, 0xC949, 0xC949 }, +{ 0xC94A, 0xC94A, 0xC94A }, +{ 0xC94B, 0xC94B, 0xC94B }, +{ 0xC94C, 0xC94C, 0xC94C }, +{ 0xC94D, 0xC94D, 0xC94D }, +{ 0xC94E, 0xC94E, 0xC94E }, +{ 0xC94F, 0xC94F, 0xC94F }, +{ 0xC950, 0xC950, 0xC950 }, +{ 0xC951, 0xC951, 0xC951 }, +{ 0xC952, 0xC952, 0xC952 }, +{ 0xC953, 0xC953, 0xC953 }, +{ 0xC954, 0xC954, 0xC954 }, +{ 0xC955, 0xC955, 0xC955 }, +{ 0xC956, 0xC956, 0xC956 }, +{ 0xC957, 0xC957, 0xC957 }, +{ 0xC958, 0xC958, 0xC958 }, +{ 0xC959, 0xC959, 0xC959 }, +{ 0xC95A, 0xC95A, 0xC95A }, +{ 0xC95B, 0xC95B, 0xC95B }, +{ 0xC95C, 0xC95C, 0xC95C }, +{ 0xC95D, 0xC95D, 0xC95D }, +{ 0xC95E, 0xC95E, 0xC95E }, +{ 0xC95F, 0xC95F, 0xC95F }, +{ 0xC960, 0xC960, 0xC960 }, +{ 0xC961, 0xC961, 0xC961 }, +{ 0xC962, 0xC962, 0xC962 }, +{ 0xC963, 0xC963, 0xC963 }, +{ 0xC964, 0xC964, 0xC964 }, +{ 0xC965, 0xC965, 0xC965 }, +{ 0xC966, 0xC966, 0xC966 }, +{ 0xC967, 0xC967, 0xC967 }, +{ 0xC968, 0xC968, 0xC968 }, +{ 0xC969, 0xC969, 0xC969 }, +{ 0xC96A, 0xC96A, 0xC96A }, +{ 0xC96B, 0xC96B, 0xC96B }, +{ 0xC96C, 0xC96C, 0xC96C }, +{ 0xC96D, 0xC96D, 0xC96D }, +{ 0xC96E, 0xC96E, 0xC96E }, +{ 0xC96F, 0xC96F, 0xC96F }, +{ 0xC970, 0xC970, 0xC970 }, +{ 0xC971, 0xC971, 0xC971 }, +{ 0xC972, 0xC972, 0xC972 }, +{ 0xC973, 0xC973, 0xC973 }, +{ 0xC974, 0xC974, 0xC974 }, +{ 0xC975, 0xC975, 0xC975 }, +{ 0xC976, 0xC976, 0xC976 }, +{ 0xC977, 0xC977, 0xC977 }, +{ 0xC978, 0xC978, 0xC978 }, +{ 0xC979, 0xC979, 0xC979 }, +{ 0xC97A, 0xC97A, 0xC97A }, +{ 0xC97B, 0xC97B, 0xC97B }, +{ 0xC97C, 0xC97C, 0xC97C }, +{ 0xC97D, 0xC97D, 0xC97D }, +{ 0xC97E, 0xC97E, 0xC97E }, +{ 0xC97F, 0xC97F, 0xC97F }, +{ 0xC980, 0xC980, 0xC980 }, +{ 0xC981, 0xC981, 0xC981 }, +{ 0xC982, 0xC982, 0xC982 }, +{ 0xC983, 0xC983, 0xC983 }, +{ 0xC984, 0xC984, 0xC984 }, +{ 0xC985, 0xC985, 0xC985 }, +{ 0xC986, 0xC986, 0xC986 }, +{ 0xC987, 0xC987, 0xC987 }, +{ 0xC988, 0xC988, 0xC988 }, +{ 0xC989, 0xC989, 0xC989 }, +{ 0xC98A, 0xC98A, 0xC98A }, +{ 0xC98B, 0xC98B, 0xC98B }, +{ 0xC98C, 0xC98C, 0xC98C }, +{ 0xC98D, 0xC98D, 0xC98D }, +{ 0xC98E, 0xC98E, 0xC98E }, +{ 0xC98F, 0xC98F, 0xC98F }, +{ 0xC990, 0xC990, 0xC990 }, +{ 0xC991, 0xC991, 0xC991 }, +{ 0xC992, 0xC992, 0xC992 }, +{ 0xC993, 0xC993, 0xC993 }, +{ 0xC994, 0xC994, 0xC994 }, +{ 0xC995, 0xC995, 0xC995 }, +{ 0xC996, 0xC996, 0xC996 }, +{ 0xC997, 0xC997, 0xC997 }, +{ 0xC998, 0xC998, 0xC998 }, +{ 0xC999, 0xC999, 0xC999 }, +{ 0xC99A, 0xC99A, 0xC99A }, +{ 0xC99B, 0xC99B, 0xC99B }, +{ 0xC99C, 0xC99C, 0xC99C }, +{ 0xC99D, 0xC99D, 0xC99D }, +{ 0xC99E, 0xC99E, 0xC99E }, +{ 0xC99F, 0xC99F, 0xC99F }, +{ 0xC9A0, 0xC9A0, 0xC9A0 }, +{ 0xC9A1, 0xC9A1, 0xC9A1 }, +{ 0xC9A2, 0xC9A2, 0xC9A2 }, +{ 0xC9A3, 0xC9A3, 0xC9A3 }, +{ 0xC9A4, 0xC9A4, 0xC9A4 }, +{ 0xC9A5, 0xC9A5, 0xC9A5 }, +{ 0xC9A6, 0xC9A6, 0xC9A6 }, +{ 0xC9A7, 0xC9A7, 0xC9A7 }, +{ 0xC9A8, 0xC9A8, 0xC9A8 }, +{ 0xC9A9, 0xC9A9, 0xC9A9 }, +{ 0xC9AA, 0xC9AA, 0xC9AA }, +{ 0xC9AB, 0xC9AB, 0xC9AB }, +{ 0xC9AC, 0xC9AC, 0xC9AC }, +{ 0xC9AD, 0xC9AD, 0xC9AD }, +{ 0xC9AE, 0xC9AE, 0xC9AE }, +{ 0xC9AF, 0xC9AF, 0xC9AF }, +{ 0xC9B0, 0xC9B0, 0xC9B0 }, +{ 0xC9B1, 0xC9B1, 0xC9B1 }, +{ 0xC9B2, 0xC9B2, 0xC9B2 }, +{ 0xC9B3, 0xC9B3, 0xC9B3 }, +{ 0xC9B4, 0xC9B4, 0xC9B4 }, +{ 0xC9B5, 0xC9B5, 0xC9B5 }, +{ 0xC9B6, 0xC9B6, 0xC9B6 }, +{ 0xC9B7, 0xC9B7, 0xC9B7 }, +{ 0xC9B8, 0xC9B8, 0xC9B8 }, +{ 0xC9B9, 0xC9B9, 0xC9B9 }, +{ 0xC9BA, 0xC9BA, 0xC9BA }, +{ 0xC9BB, 0xC9BB, 0xC9BB }, +{ 0xC9BC, 0xC9BC, 0xC9BC }, +{ 0xC9BD, 0xC9BD, 0xC9BD }, +{ 0xC9BE, 0xC9BE, 0xC9BE }, +{ 0xC9BF, 0xC9BF, 0xC9BF }, +{ 0xC9C0, 0xC9C0, 0xC9C0 }, +{ 0xC9C1, 0xC9C1, 0xC9C1 }, +{ 0xC9C2, 0xC9C2, 0xC9C2 }, +{ 0xC9C3, 0xC9C3, 0xC9C3 }, +{ 0xC9C4, 0xC9C4, 0xC9C4 }, +{ 0xC9C5, 0xC9C5, 0xC9C5 }, +{ 0xC9C6, 0xC9C6, 0xC9C6 }, +{ 0xC9C7, 0xC9C7, 0xC9C7 }, +{ 0xC9C8, 0xC9C8, 0xC9C8 }, +{ 0xC9C9, 0xC9C9, 0xC9C9 }, +{ 0xC9CA, 0xC9CA, 0xC9CA }, +{ 0xC9CB, 0xC9CB, 0xC9CB }, +{ 0xC9CC, 0xC9CC, 0xC9CC }, +{ 0xC9CD, 0xC9CD, 0xC9CD }, +{ 0xC9CE, 0xC9CE, 0xC9CE }, +{ 0xC9CF, 0xC9CF, 0xC9CF }, +{ 0xC9D0, 0xC9D0, 0xC9D0 }, +{ 0xC9D1, 0xC9D1, 0xC9D1 }, +{ 0xC9D2, 0xC9D2, 0xC9D2 }, +{ 0xC9D3, 0xC9D3, 0xC9D3 }, +{ 0xC9D4, 0xC9D4, 0xC9D4 }, +{ 0xC9D5, 0xC9D5, 0xC9D5 }, +{ 0xC9D6, 0xC9D6, 0xC9D6 }, +{ 0xC9D7, 0xC9D7, 0xC9D7 }, +{ 0xC9D8, 0xC9D8, 0xC9D8 }, +{ 0xC9D9, 0xC9D9, 0xC9D9 }, +{ 0xC9DA, 0xC9DA, 0xC9DA }, +{ 0xC9DB, 0xC9DB, 0xC9DB }, +{ 0xC9DC, 0xC9DC, 0xC9DC }, +{ 0xC9DD, 0xC9DD, 0xC9DD }, +{ 0xC9DE, 0xC9DE, 0xC9DE }, +{ 0xC9DF, 0xC9DF, 0xC9DF }, +{ 0xC9E0, 0xC9E0, 0xC9E0 }, +{ 0xC9E1, 0xC9E1, 0xC9E1 }, +{ 0xC9E2, 0xC9E2, 0xC9E2 }, +{ 0xC9E3, 0xC9E3, 0xC9E3 }, +{ 0xC9E4, 0xC9E4, 0xC9E4 }, +{ 0xC9E5, 0xC9E5, 0xC9E5 }, +{ 0xC9E6, 0xC9E6, 0xC9E6 }, +{ 0xC9E7, 0xC9E7, 0xC9E7 }, +{ 0xC9E8, 0xC9E8, 0xC9E8 }, +{ 0xC9E9, 0xC9E9, 0xC9E9 }, +{ 0xC9EA, 0xC9EA, 0xC9EA }, +{ 0xC9EB, 0xC9EB, 0xC9EB }, +{ 0xC9EC, 0xC9EC, 0xC9EC }, +{ 0xC9ED, 0xC9ED, 0xC9ED }, +{ 0xC9EE, 0xC9EE, 0xC9EE }, +{ 0xC9EF, 0xC9EF, 0xC9EF }, +{ 0xC9F0, 0xC9F0, 0xC9F0 }, +{ 0xC9F1, 0xC9F1, 0xC9F1 }, +{ 0xC9F2, 0xC9F2, 0xC9F2 }, +{ 0xC9F3, 0xC9F3, 0xC9F3 }, +{ 0xC9F4, 0xC9F4, 0xC9F4 }, +{ 0xC9F5, 0xC9F5, 0xC9F5 }, +{ 0xC9F6, 0xC9F6, 0xC9F6 }, +{ 0xC9F7, 0xC9F7, 0xC9F7 }, +{ 0xC9F8, 0xC9F8, 0xC9F8 }, +{ 0xC9F9, 0xC9F9, 0xC9F9 }, +{ 0xC9FA, 0xC9FA, 0xC9FA }, +{ 0xC9FB, 0xC9FB, 0xC9FB }, +{ 0xC9FC, 0xC9FC, 0xC9FC }, +{ 0xC9FD, 0xC9FD, 0xC9FD }, +{ 0xC9FE, 0xC9FE, 0xC9FE }, +{ 0xC9FF, 0xC9FF, 0xC9FF }, +{ 0xCA00, 0xCA00, 0xCA00 }, +{ 0xCA01, 0xCA01, 0xCA01 }, +{ 0xCA02, 0xCA02, 0xCA02 }, +{ 0xCA03, 0xCA03, 0xCA03 }, +{ 0xCA04, 0xCA04, 0xCA04 }, +{ 0xCA05, 0xCA05, 0xCA05 }, +{ 0xCA06, 0xCA06, 0xCA06 }, +{ 0xCA07, 0xCA07, 0xCA07 }, +{ 0xCA08, 0xCA08, 0xCA08 }, +{ 0xCA09, 0xCA09, 0xCA09 }, +{ 0xCA0A, 0xCA0A, 0xCA0A }, +{ 0xCA0B, 0xCA0B, 0xCA0B }, +{ 0xCA0C, 0xCA0C, 0xCA0C }, +{ 0xCA0D, 0xCA0D, 0xCA0D }, +{ 0xCA0E, 0xCA0E, 0xCA0E }, +{ 0xCA0F, 0xCA0F, 0xCA0F }, +{ 0xCA10, 0xCA10, 0xCA10 }, +{ 0xCA11, 0xCA11, 0xCA11 }, +{ 0xCA12, 0xCA12, 0xCA12 }, +{ 0xCA13, 0xCA13, 0xCA13 }, +{ 0xCA14, 0xCA14, 0xCA14 }, +{ 0xCA15, 0xCA15, 0xCA15 }, +{ 0xCA16, 0xCA16, 0xCA16 }, +{ 0xCA17, 0xCA17, 0xCA17 }, +{ 0xCA18, 0xCA18, 0xCA18 }, +{ 0xCA19, 0xCA19, 0xCA19 }, +{ 0xCA1A, 0xCA1A, 0xCA1A }, +{ 0xCA1B, 0xCA1B, 0xCA1B }, +{ 0xCA1C, 0xCA1C, 0xCA1C }, +{ 0xCA1D, 0xCA1D, 0xCA1D }, +{ 0xCA1E, 0xCA1E, 0xCA1E }, +{ 0xCA1F, 0xCA1F, 0xCA1F }, +{ 0xCA20, 0xCA20, 0xCA20 }, +{ 0xCA21, 0xCA21, 0xCA21 }, +{ 0xCA22, 0xCA22, 0xCA22 }, +{ 0xCA23, 0xCA23, 0xCA23 }, +{ 0xCA24, 0xCA24, 0xCA24 }, +{ 0xCA25, 0xCA25, 0xCA25 }, +{ 0xCA26, 0xCA26, 0xCA26 }, +{ 0xCA27, 0xCA27, 0xCA27 }, +{ 0xCA28, 0xCA28, 0xCA28 }, +{ 0xCA29, 0xCA29, 0xCA29 }, +{ 0xCA2A, 0xCA2A, 0xCA2A }, +{ 0xCA2B, 0xCA2B, 0xCA2B }, +{ 0xCA2C, 0xCA2C, 0xCA2C }, +{ 0xCA2D, 0xCA2D, 0xCA2D }, +{ 0xCA2E, 0xCA2E, 0xCA2E }, +{ 0xCA2F, 0xCA2F, 0xCA2F }, +{ 0xCA30, 0xCA30, 0xCA30 }, +{ 0xCA31, 0xCA31, 0xCA31 }, +{ 0xCA32, 0xCA32, 0xCA32 }, +{ 0xCA33, 0xCA33, 0xCA33 }, +{ 0xCA34, 0xCA34, 0xCA34 }, +{ 0xCA35, 0xCA35, 0xCA35 }, +{ 0xCA36, 0xCA36, 0xCA36 }, +{ 0xCA37, 0xCA37, 0xCA37 }, +{ 0xCA38, 0xCA38, 0xCA38 }, +{ 0xCA39, 0xCA39, 0xCA39 }, +{ 0xCA3A, 0xCA3A, 0xCA3A }, +{ 0xCA3B, 0xCA3B, 0xCA3B }, +{ 0xCA3C, 0xCA3C, 0xCA3C }, +{ 0xCA3D, 0xCA3D, 0xCA3D }, +{ 0xCA3E, 0xCA3E, 0xCA3E }, +{ 0xCA3F, 0xCA3F, 0xCA3F }, +{ 0xCA40, 0xCA40, 0xCA40 }, +{ 0xCA41, 0xCA41, 0xCA41 }, +{ 0xCA42, 0xCA42, 0xCA42 }, +{ 0xCA43, 0xCA43, 0xCA43 }, +{ 0xCA44, 0xCA44, 0xCA44 }, +{ 0xCA45, 0xCA45, 0xCA45 }, +{ 0xCA46, 0xCA46, 0xCA46 }, +{ 0xCA47, 0xCA47, 0xCA47 }, +{ 0xCA48, 0xCA48, 0xCA48 }, +{ 0xCA49, 0xCA49, 0xCA49 }, +{ 0xCA4A, 0xCA4A, 0xCA4A }, +{ 0xCA4B, 0xCA4B, 0xCA4B }, +{ 0xCA4C, 0xCA4C, 0xCA4C }, +{ 0xCA4D, 0xCA4D, 0xCA4D }, +{ 0xCA4E, 0xCA4E, 0xCA4E }, +{ 0xCA4F, 0xCA4F, 0xCA4F }, +{ 0xCA50, 0xCA50, 0xCA50 }, +{ 0xCA51, 0xCA51, 0xCA51 }, +{ 0xCA52, 0xCA52, 0xCA52 }, +{ 0xCA53, 0xCA53, 0xCA53 }, +{ 0xCA54, 0xCA54, 0xCA54 }, +{ 0xCA55, 0xCA55, 0xCA55 }, +{ 0xCA56, 0xCA56, 0xCA56 }, +{ 0xCA57, 0xCA57, 0xCA57 }, +{ 0xCA58, 0xCA58, 0xCA58 }, +{ 0xCA59, 0xCA59, 0xCA59 }, +{ 0xCA5A, 0xCA5A, 0xCA5A }, +{ 0xCA5B, 0xCA5B, 0xCA5B }, +{ 0xCA5C, 0xCA5C, 0xCA5C }, +{ 0xCA5D, 0xCA5D, 0xCA5D }, +{ 0xCA5E, 0xCA5E, 0xCA5E }, +{ 0xCA5F, 0xCA5F, 0xCA5F }, +{ 0xCA60, 0xCA60, 0xCA60 }, +{ 0xCA61, 0xCA61, 0xCA61 }, +{ 0xCA62, 0xCA62, 0xCA62 }, +{ 0xCA63, 0xCA63, 0xCA63 }, +{ 0xCA64, 0xCA64, 0xCA64 }, +{ 0xCA65, 0xCA65, 0xCA65 }, +{ 0xCA66, 0xCA66, 0xCA66 }, +{ 0xCA67, 0xCA67, 0xCA67 }, +{ 0xCA68, 0xCA68, 0xCA68 }, +{ 0xCA69, 0xCA69, 0xCA69 }, +{ 0xCA6A, 0xCA6A, 0xCA6A }, +{ 0xCA6B, 0xCA6B, 0xCA6B }, +{ 0xCA6C, 0xCA6C, 0xCA6C }, +{ 0xCA6D, 0xCA6D, 0xCA6D }, +{ 0xCA6E, 0xCA6E, 0xCA6E }, +{ 0xCA6F, 0xCA6F, 0xCA6F }, +{ 0xCA70, 0xCA70, 0xCA70 }, +{ 0xCA71, 0xCA71, 0xCA71 }, +{ 0xCA72, 0xCA72, 0xCA72 }, +{ 0xCA73, 0xCA73, 0xCA73 }, +{ 0xCA74, 0xCA74, 0xCA74 }, +{ 0xCA75, 0xCA75, 0xCA75 }, +{ 0xCA76, 0xCA76, 0xCA76 }, +{ 0xCA77, 0xCA77, 0xCA77 }, +{ 0xCA78, 0xCA78, 0xCA78 }, +{ 0xCA79, 0xCA79, 0xCA79 }, +{ 0xCA7A, 0xCA7A, 0xCA7A }, +{ 0xCA7B, 0xCA7B, 0xCA7B }, +{ 0xCA7C, 0xCA7C, 0xCA7C }, +{ 0xCA7D, 0xCA7D, 0xCA7D }, +{ 0xCA7E, 0xCA7E, 0xCA7E }, +{ 0xCA7F, 0xCA7F, 0xCA7F }, +{ 0xCA80, 0xCA80, 0xCA80 }, +{ 0xCA81, 0xCA81, 0xCA81 }, +{ 0xCA82, 0xCA82, 0xCA82 }, +{ 0xCA83, 0xCA83, 0xCA83 }, +{ 0xCA84, 0xCA84, 0xCA84 }, +{ 0xCA85, 0xCA85, 0xCA85 }, +{ 0xCA86, 0xCA86, 0xCA86 }, +{ 0xCA87, 0xCA87, 0xCA87 }, +{ 0xCA88, 0xCA88, 0xCA88 }, +{ 0xCA89, 0xCA89, 0xCA89 }, +{ 0xCA8A, 0xCA8A, 0xCA8A }, +{ 0xCA8B, 0xCA8B, 0xCA8B }, +{ 0xCA8C, 0xCA8C, 0xCA8C }, +{ 0xCA8D, 0xCA8D, 0xCA8D }, +{ 0xCA8E, 0xCA8E, 0xCA8E }, +{ 0xCA8F, 0xCA8F, 0xCA8F }, +{ 0xCA90, 0xCA90, 0xCA90 }, +{ 0xCA91, 0xCA91, 0xCA91 }, +{ 0xCA92, 0xCA92, 0xCA92 }, +{ 0xCA93, 0xCA93, 0xCA93 }, +{ 0xCA94, 0xCA94, 0xCA94 }, +{ 0xCA95, 0xCA95, 0xCA95 }, +{ 0xCA96, 0xCA96, 0xCA96 }, +{ 0xCA97, 0xCA97, 0xCA97 }, +{ 0xCA98, 0xCA98, 0xCA98 }, +{ 0xCA99, 0xCA99, 0xCA99 }, +{ 0xCA9A, 0xCA9A, 0xCA9A }, +{ 0xCA9B, 0xCA9B, 0xCA9B }, +{ 0xCA9C, 0xCA9C, 0xCA9C }, +{ 0xCA9D, 0xCA9D, 0xCA9D }, +{ 0xCA9E, 0xCA9E, 0xCA9E }, +{ 0xCA9F, 0xCA9F, 0xCA9F }, +{ 0xCAA0, 0xCAA0, 0xCAA0 }, +{ 0xCAA1, 0xCAA1, 0xCAA1 }, +{ 0xCAA2, 0xCAA2, 0xCAA2 }, +{ 0xCAA3, 0xCAA3, 0xCAA3 }, +{ 0xCAA4, 0xCAA4, 0xCAA4 }, +{ 0xCAA5, 0xCAA5, 0xCAA5 }, +{ 0xCAA6, 0xCAA6, 0xCAA6 }, +{ 0xCAA7, 0xCAA7, 0xCAA7 }, +{ 0xCAA8, 0xCAA8, 0xCAA8 }, +{ 0xCAA9, 0xCAA9, 0xCAA9 }, +{ 0xCAAA, 0xCAAA, 0xCAAA }, +{ 0xCAAB, 0xCAAB, 0xCAAB }, +{ 0xCAAC, 0xCAAC, 0xCAAC }, +{ 0xCAAD, 0xCAAD, 0xCAAD }, +{ 0xCAAE, 0xCAAE, 0xCAAE }, +{ 0xCAAF, 0xCAAF, 0xCAAF }, +{ 0xCAB0, 0xCAB0, 0xCAB0 }, +{ 0xCAB1, 0xCAB1, 0xCAB1 }, +{ 0xCAB2, 0xCAB2, 0xCAB2 }, +{ 0xCAB3, 0xCAB3, 0xCAB3 }, +{ 0xCAB4, 0xCAB4, 0xCAB4 }, +{ 0xCAB5, 0xCAB5, 0xCAB5 }, +{ 0xCAB6, 0xCAB6, 0xCAB6 }, +{ 0xCAB7, 0xCAB7, 0xCAB7 }, +{ 0xCAB8, 0xCAB8, 0xCAB8 }, +{ 0xCAB9, 0xCAB9, 0xCAB9 }, +{ 0xCABA, 0xCABA, 0xCABA }, +{ 0xCABB, 0xCABB, 0xCABB }, +{ 0xCABC, 0xCABC, 0xCABC }, +{ 0xCABD, 0xCABD, 0xCABD }, +{ 0xCABE, 0xCABE, 0xCABE }, +{ 0xCABF, 0xCABF, 0xCABF }, +{ 0xCAC0, 0xCAC0, 0xCAC0 }, +{ 0xCAC1, 0xCAC1, 0xCAC1 }, +{ 0xCAC2, 0xCAC2, 0xCAC2 }, +{ 0xCAC3, 0xCAC3, 0xCAC3 }, +{ 0xCAC4, 0xCAC4, 0xCAC4 }, +{ 0xCAC5, 0xCAC5, 0xCAC5 }, +{ 0xCAC6, 0xCAC6, 0xCAC6 }, +{ 0xCAC7, 0xCAC7, 0xCAC7 }, +{ 0xCAC8, 0xCAC8, 0xCAC8 }, +{ 0xCAC9, 0xCAC9, 0xCAC9 }, +{ 0xCACA, 0xCACA, 0xCACA }, +{ 0xCACB, 0xCACB, 0xCACB }, +{ 0xCACC, 0xCACC, 0xCACC }, +{ 0xCACD, 0xCACD, 0xCACD }, +{ 0xCACE, 0xCACE, 0xCACE }, +{ 0xCACF, 0xCACF, 0xCACF }, +{ 0xCAD0, 0xCAD0, 0xCAD0 }, +{ 0xCAD1, 0xCAD1, 0xCAD1 }, +{ 0xCAD2, 0xCAD2, 0xCAD2 }, +{ 0xCAD3, 0xCAD3, 0xCAD3 }, +{ 0xCAD4, 0xCAD4, 0xCAD4 }, +{ 0xCAD5, 0xCAD5, 0xCAD5 }, +{ 0xCAD6, 0xCAD6, 0xCAD6 }, +{ 0xCAD7, 0xCAD7, 0xCAD7 }, +{ 0xCAD8, 0xCAD8, 0xCAD8 }, +{ 0xCAD9, 0xCAD9, 0xCAD9 }, +{ 0xCADA, 0xCADA, 0xCADA }, +{ 0xCADB, 0xCADB, 0xCADB }, +{ 0xCADC, 0xCADC, 0xCADC }, +{ 0xCADD, 0xCADD, 0xCADD }, +{ 0xCADE, 0xCADE, 0xCADE }, +{ 0xCADF, 0xCADF, 0xCADF }, +{ 0xCAE0, 0xCAE0, 0xCAE0 }, +{ 0xCAE1, 0xCAE1, 0xCAE1 }, +{ 0xCAE2, 0xCAE2, 0xCAE2 }, +{ 0xCAE3, 0xCAE3, 0xCAE3 }, +{ 0xCAE4, 0xCAE4, 0xCAE4 }, +{ 0xCAE5, 0xCAE5, 0xCAE5 }, +{ 0xCAE6, 0xCAE6, 0xCAE6 }, +{ 0xCAE7, 0xCAE7, 0xCAE7 }, +{ 0xCAE8, 0xCAE8, 0xCAE8 }, +{ 0xCAE9, 0xCAE9, 0xCAE9 }, +{ 0xCAEA, 0xCAEA, 0xCAEA }, +{ 0xCAEB, 0xCAEB, 0xCAEB }, +{ 0xCAEC, 0xCAEC, 0xCAEC }, +{ 0xCAED, 0xCAED, 0xCAED }, +{ 0xCAEE, 0xCAEE, 0xCAEE }, +{ 0xCAEF, 0xCAEF, 0xCAEF }, +{ 0xCAF0, 0xCAF0, 0xCAF0 }, +{ 0xCAF1, 0xCAF1, 0xCAF1 }, +{ 0xCAF2, 0xCAF2, 0xCAF2 }, +{ 0xCAF3, 0xCAF3, 0xCAF3 }, +{ 0xCAF4, 0xCAF4, 0xCAF4 }, +{ 0xCAF5, 0xCAF5, 0xCAF5 }, +{ 0xCAF6, 0xCAF6, 0xCAF6 }, +{ 0xCAF7, 0xCAF7, 0xCAF7 }, +{ 0xCAF8, 0xCAF8, 0xCAF8 }, +{ 0xCAF9, 0xCAF9, 0xCAF9 }, +{ 0xCAFA, 0xCAFA, 0xCAFA }, +{ 0xCAFB, 0xCAFB, 0xCAFB }, +{ 0xCAFC, 0xCAFC, 0xCAFC }, +{ 0xCAFD, 0xCAFD, 0xCAFD }, +{ 0xCAFE, 0xCAFE, 0xCAFE }, +{ 0xCAFF, 0xCAFF, 0xCAFF }, +{ 0xCB00, 0xCB00, 0xCB00 }, +{ 0xCB01, 0xCB01, 0xCB01 }, +{ 0xCB02, 0xCB02, 0xCB02 }, +{ 0xCB03, 0xCB03, 0xCB03 }, +{ 0xCB04, 0xCB04, 0xCB04 }, +{ 0xCB05, 0xCB05, 0xCB05 }, +{ 0xCB06, 0xCB06, 0xCB06 }, +{ 0xCB07, 0xCB07, 0xCB07 }, +{ 0xCB08, 0xCB08, 0xCB08 }, +{ 0xCB09, 0xCB09, 0xCB09 }, +{ 0xCB0A, 0xCB0A, 0xCB0A }, +{ 0xCB0B, 0xCB0B, 0xCB0B }, +{ 0xCB0C, 0xCB0C, 0xCB0C }, +{ 0xCB0D, 0xCB0D, 0xCB0D }, +{ 0xCB0E, 0xCB0E, 0xCB0E }, +{ 0xCB0F, 0xCB0F, 0xCB0F }, +{ 0xCB10, 0xCB10, 0xCB10 }, +{ 0xCB11, 0xCB11, 0xCB11 }, +{ 0xCB12, 0xCB12, 0xCB12 }, +{ 0xCB13, 0xCB13, 0xCB13 }, +{ 0xCB14, 0xCB14, 0xCB14 }, +{ 0xCB15, 0xCB15, 0xCB15 }, +{ 0xCB16, 0xCB16, 0xCB16 }, +{ 0xCB17, 0xCB17, 0xCB17 }, +{ 0xCB18, 0xCB18, 0xCB18 }, +{ 0xCB19, 0xCB19, 0xCB19 }, +{ 0xCB1A, 0xCB1A, 0xCB1A }, +{ 0xCB1B, 0xCB1B, 0xCB1B }, +{ 0xCB1C, 0xCB1C, 0xCB1C }, +{ 0xCB1D, 0xCB1D, 0xCB1D }, +{ 0xCB1E, 0xCB1E, 0xCB1E }, +{ 0xCB1F, 0xCB1F, 0xCB1F }, +{ 0xCB20, 0xCB20, 0xCB20 }, +{ 0xCB21, 0xCB21, 0xCB21 }, +{ 0xCB22, 0xCB22, 0xCB22 }, +{ 0xCB23, 0xCB23, 0xCB23 }, +{ 0xCB24, 0xCB24, 0xCB24 }, +{ 0xCB25, 0xCB25, 0xCB25 }, +{ 0xCB26, 0xCB26, 0xCB26 }, +{ 0xCB27, 0xCB27, 0xCB27 }, +{ 0xCB28, 0xCB28, 0xCB28 }, +{ 0xCB29, 0xCB29, 0xCB29 }, +{ 0xCB2A, 0xCB2A, 0xCB2A }, +{ 0xCB2B, 0xCB2B, 0xCB2B }, +{ 0xCB2C, 0xCB2C, 0xCB2C }, +{ 0xCB2D, 0xCB2D, 0xCB2D }, +{ 0xCB2E, 0xCB2E, 0xCB2E }, +{ 0xCB2F, 0xCB2F, 0xCB2F }, +{ 0xCB30, 0xCB30, 0xCB30 }, +{ 0xCB31, 0xCB31, 0xCB31 }, +{ 0xCB32, 0xCB32, 0xCB32 }, +{ 0xCB33, 0xCB33, 0xCB33 }, +{ 0xCB34, 0xCB34, 0xCB34 }, +{ 0xCB35, 0xCB35, 0xCB35 }, +{ 0xCB36, 0xCB36, 0xCB36 }, +{ 0xCB37, 0xCB37, 0xCB37 }, +{ 0xCB38, 0xCB38, 0xCB38 }, +{ 0xCB39, 0xCB39, 0xCB39 }, +{ 0xCB3A, 0xCB3A, 0xCB3A }, +{ 0xCB3B, 0xCB3B, 0xCB3B }, +{ 0xCB3C, 0xCB3C, 0xCB3C }, +{ 0xCB3D, 0xCB3D, 0xCB3D }, +{ 0xCB3E, 0xCB3E, 0xCB3E }, +{ 0xCB3F, 0xCB3F, 0xCB3F }, +{ 0xCB40, 0xCB40, 0xCB40 }, +{ 0xCB41, 0xCB41, 0xCB41 }, +{ 0xCB42, 0xCB42, 0xCB42 }, +{ 0xCB43, 0xCB43, 0xCB43 }, +{ 0xCB44, 0xCB44, 0xCB44 }, +{ 0xCB45, 0xCB45, 0xCB45 }, +{ 0xCB46, 0xCB46, 0xCB46 }, +{ 0xCB47, 0xCB47, 0xCB47 }, +{ 0xCB48, 0xCB48, 0xCB48 }, +{ 0xCB49, 0xCB49, 0xCB49 }, +{ 0xCB4A, 0xCB4A, 0xCB4A }, +{ 0xCB4B, 0xCB4B, 0xCB4B }, +{ 0xCB4C, 0xCB4C, 0xCB4C }, +{ 0xCB4D, 0xCB4D, 0xCB4D }, +{ 0xCB4E, 0xCB4E, 0xCB4E }, +{ 0xCB4F, 0xCB4F, 0xCB4F }, +{ 0xCB50, 0xCB50, 0xCB50 }, +{ 0xCB51, 0xCB51, 0xCB51 }, +{ 0xCB52, 0xCB52, 0xCB52 }, +{ 0xCB53, 0xCB53, 0xCB53 }, +{ 0xCB54, 0xCB54, 0xCB54 }, +{ 0xCB55, 0xCB55, 0xCB55 }, +{ 0xCB56, 0xCB56, 0xCB56 }, +{ 0xCB57, 0xCB57, 0xCB57 }, +{ 0xCB58, 0xCB58, 0xCB58 }, +{ 0xCB59, 0xCB59, 0xCB59 }, +{ 0xCB5A, 0xCB5A, 0xCB5A }, +{ 0xCB5B, 0xCB5B, 0xCB5B }, +{ 0xCB5C, 0xCB5C, 0xCB5C }, +{ 0xCB5D, 0xCB5D, 0xCB5D }, +{ 0xCB5E, 0xCB5E, 0xCB5E }, +{ 0xCB5F, 0xCB5F, 0xCB5F }, +{ 0xCB60, 0xCB60, 0xCB60 }, +{ 0xCB61, 0xCB61, 0xCB61 }, +{ 0xCB62, 0xCB62, 0xCB62 }, +{ 0xCB63, 0xCB63, 0xCB63 }, +{ 0xCB64, 0xCB64, 0xCB64 }, +{ 0xCB65, 0xCB65, 0xCB65 }, +{ 0xCB66, 0xCB66, 0xCB66 }, +{ 0xCB67, 0xCB67, 0xCB67 }, +{ 0xCB68, 0xCB68, 0xCB68 }, +{ 0xCB69, 0xCB69, 0xCB69 }, +{ 0xCB6A, 0xCB6A, 0xCB6A }, +{ 0xCB6B, 0xCB6B, 0xCB6B }, +{ 0xCB6C, 0xCB6C, 0xCB6C }, +{ 0xCB6D, 0xCB6D, 0xCB6D }, +{ 0xCB6E, 0xCB6E, 0xCB6E }, +{ 0xCB6F, 0xCB6F, 0xCB6F }, +{ 0xCB70, 0xCB70, 0xCB70 }, +{ 0xCB71, 0xCB71, 0xCB71 }, +{ 0xCB72, 0xCB72, 0xCB72 }, +{ 0xCB73, 0xCB73, 0xCB73 }, +{ 0xCB74, 0xCB74, 0xCB74 }, +{ 0xCB75, 0xCB75, 0xCB75 }, +{ 0xCB76, 0xCB76, 0xCB76 }, +{ 0xCB77, 0xCB77, 0xCB77 }, +{ 0xCB78, 0xCB78, 0xCB78 }, +{ 0xCB79, 0xCB79, 0xCB79 }, +{ 0xCB7A, 0xCB7A, 0xCB7A }, +{ 0xCB7B, 0xCB7B, 0xCB7B }, +{ 0xCB7C, 0xCB7C, 0xCB7C }, +{ 0xCB7D, 0xCB7D, 0xCB7D }, +{ 0xCB7E, 0xCB7E, 0xCB7E }, +{ 0xCB7F, 0xCB7F, 0xCB7F }, +{ 0xCB80, 0xCB80, 0xCB80 }, +{ 0xCB81, 0xCB81, 0xCB81 }, +{ 0xCB82, 0xCB82, 0xCB82 }, +{ 0xCB83, 0xCB83, 0xCB83 }, +{ 0xCB84, 0xCB84, 0xCB84 }, +{ 0xCB85, 0xCB85, 0xCB85 }, +{ 0xCB86, 0xCB86, 0xCB86 }, +{ 0xCB87, 0xCB87, 0xCB87 }, +{ 0xCB88, 0xCB88, 0xCB88 }, +{ 0xCB89, 0xCB89, 0xCB89 }, +{ 0xCB8A, 0xCB8A, 0xCB8A }, +{ 0xCB8B, 0xCB8B, 0xCB8B }, +{ 0xCB8C, 0xCB8C, 0xCB8C }, +{ 0xCB8D, 0xCB8D, 0xCB8D }, +{ 0xCB8E, 0xCB8E, 0xCB8E }, +{ 0xCB8F, 0xCB8F, 0xCB8F }, +{ 0xCB90, 0xCB90, 0xCB90 }, +{ 0xCB91, 0xCB91, 0xCB91 }, +{ 0xCB92, 0xCB92, 0xCB92 }, +{ 0xCB93, 0xCB93, 0xCB93 }, +{ 0xCB94, 0xCB94, 0xCB94 }, +{ 0xCB95, 0xCB95, 0xCB95 }, +{ 0xCB96, 0xCB96, 0xCB96 }, +{ 0xCB97, 0xCB97, 0xCB97 }, +{ 0xCB98, 0xCB98, 0xCB98 }, +{ 0xCB99, 0xCB99, 0xCB99 }, +{ 0xCB9A, 0xCB9A, 0xCB9A }, +{ 0xCB9B, 0xCB9B, 0xCB9B }, +{ 0xCB9C, 0xCB9C, 0xCB9C }, +{ 0xCB9D, 0xCB9D, 0xCB9D }, +{ 0xCB9E, 0xCB9E, 0xCB9E }, +{ 0xCB9F, 0xCB9F, 0xCB9F }, +{ 0xCBA0, 0xCBA0, 0xCBA0 }, +{ 0xCBA1, 0xCBA1, 0xCBA1 }, +{ 0xCBA2, 0xCBA2, 0xCBA2 }, +{ 0xCBA3, 0xCBA3, 0xCBA3 }, +{ 0xCBA4, 0xCBA4, 0xCBA4 }, +{ 0xCBA5, 0xCBA5, 0xCBA5 }, +{ 0xCBA6, 0xCBA6, 0xCBA6 }, +{ 0xCBA7, 0xCBA7, 0xCBA7 }, +{ 0xCBA8, 0xCBA8, 0xCBA8 }, +{ 0xCBA9, 0xCBA9, 0xCBA9 }, +{ 0xCBAA, 0xCBAA, 0xCBAA }, +{ 0xCBAB, 0xCBAB, 0xCBAB }, +{ 0xCBAC, 0xCBAC, 0xCBAC }, +{ 0xCBAD, 0xCBAD, 0xCBAD }, +{ 0xCBAE, 0xCBAE, 0xCBAE }, +{ 0xCBAF, 0xCBAF, 0xCBAF }, +{ 0xCBB0, 0xCBB0, 0xCBB0 }, +{ 0xCBB1, 0xCBB1, 0xCBB1 }, +{ 0xCBB2, 0xCBB2, 0xCBB2 }, +{ 0xCBB3, 0xCBB3, 0xCBB3 }, +{ 0xCBB4, 0xCBB4, 0xCBB4 }, +{ 0xCBB5, 0xCBB5, 0xCBB5 }, +{ 0xCBB6, 0xCBB6, 0xCBB6 }, +{ 0xCBB7, 0xCBB7, 0xCBB7 }, +{ 0xCBB8, 0xCBB8, 0xCBB8 }, +{ 0xCBB9, 0xCBB9, 0xCBB9 }, +{ 0xCBBA, 0xCBBA, 0xCBBA }, +{ 0xCBBB, 0xCBBB, 0xCBBB }, +{ 0xCBBC, 0xCBBC, 0xCBBC }, +{ 0xCBBD, 0xCBBD, 0xCBBD }, +{ 0xCBBE, 0xCBBE, 0xCBBE }, +{ 0xCBBF, 0xCBBF, 0xCBBF }, +{ 0xCBC0, 0xCBC0, 0xCBC0 }, +{ 0xCBC1, 0xCBC1, 0xCBC1 }, +{ 0xCBC2, 0xCBC2, 0xCBC2 }, +{ 0xCBC3, 0xCBC3, 0xCBC3 }, +{ 0xCBC4, 0xCBC4, 0xCBC4 }, +{ 0xCBC5, 0xCBC5, 0xCBC5 }, +{ 0xCBC6, 0xCBC6, 0xCBC6 }, +{ 0xCBC7, 0xCBC7, 0xCBC7 }, +{ 0xCBC8, 0xCBC8, 0xCBC8 }, +{ 0xCBC9, 0xCBC9, 0xCBC9 }, +{ 0xCBCA, 0xCBCA, 0xCBCA }, +{ 0xCBCB, 0xCBCB, 0xCBCB }, +{ 0xCBCC, 0xCBCC, 0xCBCC }, +{ 0xCBCD, 0xCBCD, 0xCBCD }, +{ 0xCBCE, 0xCBCE, 0xCBCE }, +{ 0xCBCF, 0xCBCF, 0xCBCF }, +{ 0xCBD0, 0xCBD0, 0xCBD0 }, +{ 0xCBD1, 0xCBD1, 0xCBD1 }, +{ 0xCBD2, 0xCBD2, 0xCBD2 }, +{ 0xCBD3, 0xCBD3, 0xCBD3 }, +{ 0xCBD4, 0xCBD4, 0xCBD4 }, +{ 0xCBD5, 0xCBD5, 0xCBD5 }, +{ 0xCBD6, 0xCBD6, 0xCBD6 }, +{ 0xCBD7, 0xCBD7, 0xCBD7 }, +{ 0xCBD8, 0xCBD8, 0xCBD8 }, +{ 0xCBD9, 0xCBD9, 0xCBD9 }, +{ 0xCBDA, 0xCBDA, 0xCBDA }, +{ 0xCBDB, 0xCBDB, 0xCBDB }, +{ 0xCBDC, 0xCBDC, 0xCBDC }, +{ 0xCBDD, 0xCBDD, 0xCBDD }, +{ 0xCBDE, 0xCBDE, 0xCBDE }, +{ 0xCBDF, 0xCBDF, 0xCBDF }, +{ 0xCBE0, 0xCBE0, 0xCBE0 }, +{ 0xCBE1, 0xCBE1, 0xCBE1 }, +{ 0xCBE2, 0xCBE2, 0xCBE2 }, +{ 0xCBE3, 0xCBE3, 0xCBE3 }, +{ 0xCBE4, 0xCBE4, 0xCBE4 }, +{ 0xCBE5, 0xCBE5, 0xCBE5 }, +{ 0xCBE6, 0xCBE6, 0xCBE6 }, +{ 0xCBE7, 0xCBE7, 0xCBE7 }, +{ 0xCBE8, 0xCBE8, 0xCBE8 }, +{ 0xCBE9, 0xCBE9, 0xCBE9 }, +{ 0xCBEA, 0xCBEA, 0xCBEA }, +{ 0xCBEB, 0xCBEB, 0xCBEB }, +{ 0xCBEC, 0xCBEC, 0xCBEC }, +{ 0xCBED, 0xCBED, 0xCBED }, +{ 0xCBEE, 0xCBEE, 0xCBEE }, +{ 0xCBEF, 0xCBEF, 0xCBEF }, +{ 0xCBF0, 0xCBF0, 0xCBF0 }, +{ 0xCBF1, 0xCBF1, 0xCBF1 }, +{ 0xCBF2, 0xCBF2, 0xCBF2 }, +{ 0xCBF3, 0xCBF3, 0xCBF3 }, +{ 0xCBF4, 0xCBF4, 0xCBF4 }, +{ 0xCBF5, 0xCBF5, 0xCBF5 }, +{ 0xCBF6, 0xCBF6, 0xCBF6 }, +{ 0xCBF7, 0xCBF7, 0xCBF7 }, +{ 0xCBF8, 0xCBF8, 0xCBF8 }, +{ 0xCBF9, 0xCBF9, 0xCBF9 }, +{ 0xCBFA, 0xCBFA, 0xCBFA }, +{ 0xCBFB, 0xCBFB, 0xCBFB }, +{ 0xCBFC, 0xCBFC, 0xCBFC }, +{ 0xCBFD, 0xCBFD, 0xCBFD }, +{ 0xCBFE, 0xCBFE, 0xCBFE }, +{ 0xCBFF, 0xCBFF, 0xCBFF }, +{ 0xCC00, 0xCC00, 0xCC00 }, +{ 0xCC01, 0xCC01, 0xCC01 }, +{ 0xCC02, 0xCC02, 0xCC02 }, +{ 0xCC03, 0xCC03, 0xCC03 }, +{ 0xCC04, 0xCC04, 0xCC04 }, +{ 0xCC05, 0xCC05, 0xCC05 }, +{ 0xCC06, 0xCC06, 0xCC06 }, +{ 0xCC07, 0xCC07, 0xCC07 }, +{ 0xCC08, 0xCC08, 0xCC08 }, +{ 0xCC09, 0xCC09, 0xCC09 }, +{ 0xCC0A, 0xCC0A, 0xCC0A }, +{ 0xCC0B, 0xCC0B, 0xCC0B }, +{ 0xCC0C, 0xCC0C, 0xCC0C }, +{ 0xCC0D, 0xCC0D, 0xCC0D }, +{ 0xCC0E, 0xCC0E, 0xCC0E }, +{ 0xCC0F, 0xCC0F, 0xCC0F }, +{ 0xCC10, 0xCC10, 0xCC10 }, +{ 0xCC11, 0xCC11, 0xCC11 }, +{ 0xCC12, 0xCC12, 0xCC12 }, +{ 0xCC13, 0xCC13, 0xCC13 }, +{ 0xCC14, 0xCC14, 0xCC14 }, +{ 0xCC15, 0xCC15, 0xCC15 }, +{ 0xCC16, 0xCC16, 0xCC16 }, +{ 0xCC17, 0xCC17, 0xCC17 }, +{ 0xCC18, 0xCC18, 0xCC18 }, +{ 0xCC19, 0xCC19, 0xCC19 }, +{ 0xCC1A, 0xCC1A, 0xCC1A }, +{ 0xCC1B, 0xCC1B, 0xCC1B }, +{ 0xCC1C, 0xCC1C, 0xCC1C }, +{ 0xCC1D, 0xCC1D, 0xCC1D }, +{ 0xCC1E, 0xCC1E, 0xCC1E }, +{ 0xCC1F, 0xCC1F, 0xCC1F }, +{ 0xCC20, 0xCC20, 0xCC20 }, +{ 0xCC21, 0xCC21, 0xCC21 }, +{ 0xCC22, 0xCC22, 0xCC22 }, +{ 0xCC23, 0xCC23, 0xCC23 }, +{ 0xCC24, 0xCC24, 0xCC24 }, +{ 0xCC25, 0xCC25, 0xCC25 }, +{ 0xCC26, 0xCC26, 0xCC26 }, +{ 0xCC27, 0xCC27, 0xCC27 }, +{ 0xCC28, 0xCC28, 0xCC28 }, +{ 0xCC29, 0xCC29, 0xCC29 }, +{ 0xCC2A, 0xCC2A, 0xCC2A }, +{ 0xCC2B, 0xCC2B, 0xCC2B }, +{ 0xCC2C, 0xCC2C, 0xCC2C }, +{ 0xCC2D, 0xCC2D, 0xCC2D }, +{ 0xCC2E, 0xCC2E, 0xCC2E }, +{ 0xCC2F, 0xCC2F, 0xCC2F }, +{ 0xCC30, 0xCC30, 0xCC30 }, +{ 0xCC31, 0xCC31, 0xCC31 }, +{ 0xCC32, 0xCC32, 0xCC32 }, +{ 0xCC33, 0xCC33, 0xCC33 }, +{ 0xCC34, 0xCC34, 0xCC34 }, +{ 0xCC35, 0xCC35, 0xCC35 }, +{ 0xCC36, 0xCC36, 0xCC36 }, +{ 0xCC37, 0xCC37, 0xCC37 }, +{ 0xCC38, 0xCC38, 0xCC38 }, +{ 0xCC39, 0xCC39, 0xCC39 }, +{ 0xCC3A, 0xCC3A, 0xCC3A }, +{ 0xCC3B, 0xCC3B, 0xCC3B }, +{ 0xCC3C, 0xCC3C, 0xCC3C }, +{ 0xCC3D, 0xCC3D, 0xCC3D }, +{ 0xCC3E, 0xCC3E, 0xCC3E }, +{ 0xCC3F, 0xCC3F, 0xCC3F }, +{ 0xCC40, 0xCC40, 0xCC40 }, +{ 0xCC41, 0xCC41, 0xCC41 }, +{ 0xCC42, 0xCC42, 0xCC42 }, +{ 0xCC43, 0xCC43, 0xCC43 }, +{ 0xCC44, 0xCC44, 0xCC44 }, +{ 0xCC45, 0xCC45, 0xCC45 }, +{ 0xCC46, 0xCC46, 0xCC46 }, +{ 0xCC47, 0xCC47, 0xCC47 }, +{ 0xCC48, 0xCC48, 0xCC48 }, +{ 0xCC49, 0xCC49, 0xCC49 }, +{ 0xCC4A, 0xCC4A, 0xCC4A }, +{ 0xCC4B, 0xCC4B, 0xCC4B }, +{ 0xCC4C, 0xCC4C, 0xCC4C }, +{ 0xCC4D, 0xCC4D, 0xCC4D }, +{ 0xCC4E, 0xCC4E, 0xCC4E }, +{ 0xCC4F, 0xCC4F, 0xCC4F }, +{ 0xCC50, 0xCC50, 0xCC50 }, +{ 0xCC51, 0xCC51, 0xCC51 }, +{ 0xCC52, 0xCC52, 0xCC52 }, +{ 0xCC53, 0xCC53, 0xCC53 }, +{ 0xCC54, 0xCC54, 0xCC54 }, +{ 0xCC55, 0xCC55, 0xCC55 }, +{ 0xCC56, 0xCC56, 0xCC56 }, +{ 0xCC57, 0xCC57, 0xCC57 }, +{ 0xCC58, 0xCC58, 0xCC58 }, +{ 0xCC59, 0xCC59, 0xCC59 }, +{ 0xCC5A, 0xCC5A, 0xCC5A }, +{ 0xCC5B, 0xCC5B, 0xCC5B }, +{ 0xCC5C, 0xCC5C, 0xCC5C }, +{ 0xCC5D, 0xCC5D, 0xCC5D }, +{ 0xCC5E, 0xCC5E, 0xCC5E }, +{ 0xCC5F, 0xCC5F, 0xCC5F }, +{ 0xCC60, 0xCC60, 0xCC60 }, +{ 0xCC61, 0xCC61, 0xCC61 }, +{ 0xCC62, 0xCC62, 0xCC62 }, +{ 0xCC63, 0xCC63, 0xCC63 }, +{ 0xCC64, 0xCC64, 0xCC64 }, +{ 0xCC65, 0xCC65, 0xCC65 }, +{ 0xCC66, 0xCC66, 0xCC66 }, +{ 0xCC67, 0xCC67, 0xCC67 }, +{ 0xCC68, 0xCC68, 0xCC68 }, +{ 0xCC69, 0xCC69, 0xCC69 }, +{ 0xCC6A, 0xCC6A, 0xCC6A }, +{ 0xCC6B, 0xCC6B, 0xCC6B }, +{ 0xCC6C, 0xCC6C, 0xCC6C }, +{ 0xCC6D, 0xCC6D, 0xCC6D }, +{ 0xCC6E, 0xCC6E, 0xCC6E }, +{ 0xCC6F, 0xCC6F, 0xCC6F }, +{ 0xCC70, 0xCC70, 0xCC70 }, +{ 0xCC71, 0xCC71, 0xCC71 }, +{ 0xCC72, 0xCC72, 0xCC72 }, +{ 0xCC73, 0xCC73, 0xCC73 }, +{ 0xCC74, 0xCC74, 0xCC74 }, +{ 0xCC75, 0xCC75, 0xCC75 }, +{ 0xCC76, 0xCC76, 0xCC76 }, +{ 0xCC77, 0xCC77, 0xCC77 }, +{ 0xCC78, 0xCC78, 0xCC78 }, +{ 0xCC79, 0xCC79, 0xCC79 }, +{ 0xCC7A, 0xCC7A, 0xCC7A }, +{ 0xCC7B, 0xCC7B, 0xCC7B }, +{ 0xCC7C, 0xCC7C, 0xCC7C }, +{ 0xCC7D, 0xCC7D, 0xCC7D }, +{ 0xCC7E, 0xCC7E, 0xCC7E }, +{ 0xCC7F, 0xCC7F, 0xCC7F }, +{ 0xCC80, 0xCC80, 0xCC80 }, +{ 0xCC81, 0xCC81, 0xCC81 }, +{ 0xCC82, 0xCC82, 0xCC82 }, +{ 0xCC83, 0xCC83, 0xCC83 }, +{ 0xCC84, 0xCC84, 0xCC84 }, +{ 0xCC85, 0xCC85, 0xCC85 }, +{ 0xCC86, 0xCC86, 0xCC86 }, +{ 0xCC87, 0xCC87, 0xCC87 }, +{ 0xCC88, 0xCC88, 0xCC88 }, +{ 0xCC89, 0xCC89, 0xCC89 }, +{ 0xCC8A, 0xCC8A, 0xCC8A }, +{ 0xCC8B, 0xCC8B, 0xCC8B }, +{ 0xCC8C, 0xCC8C, 0xCC8C }, +{ 0xCC8D, 0xCC8D, 0xCC8D }, +{ 0xCC8E, 0xCC8E, 0xCC8E }, +{ 0xCC8F, 0xCC8F, 0xCC8F }, +{ 0xCC90, 0xCC90, 0xCC90 }, +{ 0xCC91, 0xCC91, 0xCC91 }, +{ 0xCC92, 0xCC92, 0xCC92 }, +{ 0xCC93, 0xCC93, 0xCC93 }, +{ 0xCC94, 0xCC94, 0xCC94 }, +{ 0xCC95, 0xCC95, 0xCC95 }, +{ 0xCC96, 0xCC96, 0xCC96 }, +{ 0xCC97, 0xCC97, 0xCC97 }, +{ 0xCC98, 0xCC98, 0xCC98 }, +{ 0xCC99, 0xCC99, 0xCC99 }, +{ 0xCC9A, 0xCC9A, 0xCC9A }, +{ 0xCC9B, 0xCC9B, 0xCC9B }, +{ 0xCC9C, 0xCC9C, 0xCC9C }, +{ 0xCC9D, 0xCC9D, 0xCC9D }, +{ 0xCC9E, 0xCC9E, 0xCC9E }, +{ 0xCC9F, 0xCC9F, 0xCC9F }, +{ 0xCCA0, 0xCCA0, 0xCCA0 }, +{ 0xCCA1, 0xCCA1, 0xCCA1 }, +{ 0xCCA2, 0xCCA2, 0xCCA2 }, +{ 0xCCA3, 0xCCA3, 0xCCA3 }, +{ 0xCCA4, 0xCCA4, 0xCCA4 }, +{ 0xCCA5, 0xCCA5, 0xCCA5 }, +{ 0xCCA6, 0xCCA6, 0xCCA6 }, +{ 0xCCA7, 0xCCA7, 0xCCA7 }, +{ 0xCCA8, 0xCCA8, 0xCCA8 }, +{ 0xCCA9, 0xCCA9, 0xCCA9 }, +{ 0xCCAA, 0xCCAA, 0xCCAA }, +{ 0xCCAB, 0xCCAB, 0xCCAB }, +{ 0xCCAC, 0xCCAC, 0xCCAC }, +{ 0xCCAD, 0xCCAD, 0xCCAD }, +{ 0xCCAE, 0xCCAE, 0xCCAE }, +{ 0xCCAF, 0xCCAF, 0xCCAF }, +{ 0xCCB0, 0xCCB0, 0xCCB0 }, +{ 0xCCB1, 0xCCB1, 0xCCB1 }, +{ 0xCCB2, 0xCCB2, 0xCCB2 }, +{ 0xCCB3, 0xCCB3, 0xCCB3 }, +{ 0xCCB4, 0xCCB4, 0xCCB4 }, +{ 0xCCB5, 0xCCB5, 0xCCB5 }, +{ 0xCCB6, 0xCCB6, 0xCCB6 }, +{ 0xCCB7, 0xCCB7, 0xCCB7 }, +{ 0xCCB8, 0xCCB8, 0xCCB8 }, +{ 0xCCB9, 0xCCB9, 0xCCB9 }, +{ 0xCCBA, 0xCCBA, 0xCCBA }, +{ 0xCCBB, 0xCCBB, 0xCCBB }, +{ 0xCCBC, 0xCCBC, 0xCCBC }, +{ 0xCCBD, 0xCCBD, 0xCCBD }, +{ 0xCCBE, 0xCCBE, 0xCCBE }, +{ 0xCCBF, 0xCCBF, 0xCCBF }, +{ 0xCCC0, 0xCCC0, 0xCCC0 }, +{ 0xCCC1, 0xCCC1, 0xCCC1 }, +{ 0xCCC2, 0xCCC2, 0xCCC2 }, +{ 0xCCC3, 0xCCC3, 0xCCC3 }, +{ 0xCCC4, 0xCCC4, 0xCCC4 }, +{ 0xCCC5, 0xCCC5, 0xCCC5 }, +{ 0xCCC6, 0xCCC6, 0xCCC6 }, +{ 0xCCC7, 0xCCC7, 0xCCC7 }, +{ 0xCCC8, 0xCCC8, 0xCCC8 }, +{ 0xCCC9, 0xCCC9, 0xCCC9 }, +{ 0xCCCA, 0xCCCA, 0xCCCA }, +{ 0xCCCB, 0xCCCB, 0xCCCB }, +{ 0xCCCC, 0xCCCC, 0xCCCC }, +{ 0xCCCD, 0xCCCD, 0xCCCD }, +{ 0xCCCE, 0xCCCE, 0xCCCE }, +{ 0xCCCF, 0xCCCF, 0xCCCF }, +{ 0xCCD0, 0xCCD0, 0xCCD0 }, +{ 0xCCD1, 0xCCD1, 0xCCD1 }, +{ 0xCCD2, 0xCCD2, 0xCCD2 }, +{ 0xCCD3, 0xCCD3, 0xCCD3 }, +{ 0xCCD4, 0xCCD4, 0xCCD4 }, +{ 0xCCD5, 0xCCD5, 0xCCD5 }, +{ 0xCCD6, 0xCCD6, 0xCCD6 }, +{ 0xCCD7, 0xCCD7, 0xCCD7 }, +{ 0xCCD8, 0xCCD8, 0xCCD8 }, +{ 0xCCD9, 0xCCD9, 0xCCD9 }, +{ 0xCCDA, 0xCCDA, 0xCCDA }, +{ 0xCCDB, 0xCCDB, 0xCCDB }, +{ 0xCCDC, 0xCCDC, 0xCCDC }, +{ 0xCCDD, 0xCCDD, 0xCCDD }, +{ 0xCCDE, 0xCCDE, 0xCCDE }, +{ 0xCCDF, 0xCCDF, 0xCCDF }, +{ 0xCCE0, 0xCCE0, 0xCCE0 }, +{ 0xCCE1, 0xCCE1, 0xCCE1 }, +{ 0xCCE2, 0xCCE2, 0xCCE2 }, +{ 0xCCE3, 0xCCE3, 0xCCE3 }, +{ 0xCCE4, 0xCCE4, 0xCCE4 }, +{ 0xCCE5, 0xCCE5, 0xCCE5 }, +{ 0xCCE6, 0xCCE6, 0xCCE6 }, +{ 0xCCE7, 0xCCE7, 0xCCE7 }, +{ 0xCCE8, 0xCCE8, 0xCCE8 }, +{ 0xCCE9, 0xCCE9, 0xCCE9 }, +{ 0xCCEA, 0xCCEA, 0xCCEA }, +{ 0xCCEB, 0xCCEB, 0xCCEB }, +{ 0xCCEC, 0xCCEC, 0xCCEC }, +{ 0xCCED, 0xCCED, 0xCCED }, +{ 0xCCEE, 0xCCEE, 0xCCEE }, +{ 0xCCEF, 0xCCEF, 0xCCEF }, +{ 0xCCF0, 0xCCF0, 0xCCF0 }, +{ 0xCCF1, 0xCCF1, 0xCCF1 }, +{ 0xCCF2, 0xCCF2, 0xCCF2 }, +{ 0xCCF3, 0xCCF3, 0xCCF3 }, +{ 0xCCF4, 0xCCF4, 0xCCF4 }, +{ 0xCCF5, 0xCCF5, 0xCCF5 }, +{ 0xCCF6, 0xCCF6, 0xCCF6 }, +{ 0xCCF7, 0xCCF7, 0xCCF7 }, +{ 0xCCF8, 0xCCF8, 0xCCF8 }, +{ 0xCCF9, 0xCCF9, 0xCCF9 }, +{ 0xCCFA, 0xCCFA, 0xCCFA }, +{ 0xCCFB, 0xCCFB, 0xCCFB }, +{ 0xCCFC, 0xCCFC, 0xCCFC }, +{ 0xCCFD, 0xCCFD, 0xCCFD }, +{ 0xCCFE, 0xCCFE, 0xCCFE }, +{ 0xCCFF, 0xCCFF, 0xCCFF }, +{ 0xCD00, 0xCD00, 0xCD00 }, +{ 0xCD01, 0xCD01, 0xCD01 }, +{ 0xCD02, 0xCD02, 0xCD02 }, +{ 0xCD03, 0xCD03, 0xCD03 }, +{ 0xCD04, 0xCD04, 0xCD04 }, +{ 0xCD05, 0xCD05, 0xCD05 }, +{ 0xCD06, 0xCD06, 0xCD06 }, +{ 0xCD07, 0xCD07, 0xCD07 }, +{ 0xCD08, 0xCD08, 0xCD08 }, +{ 0xCD09, 0xCD09, 0xCD09 }, +{ 0xCD0A, 0xCD0A, 0xCD0A }, +{ 0xCD0B, 0xCD0B, 0xCD0B }, +{ 0xCD0C, 0xCD0C, 0xCD0C }, +{ 0xCD0D, 0xCD0D, 0xCD0D }, +{ 0xCD0E, 0xCD0E, 0xCD0E }, +{ 0xCD0F, 0xCD0F, 0xCD0F }, +{ 0xCD10, 0xCD10, 0xCD10 }, +{ 0xCD11, 0xCD11, 0xCD11 }, +{ 0xCD12, 0xCD12, 0xCD12 }, +{ 0xCD13, 0xCD13, 0xCD13 }, +{ 0xCD14, 0xCD14, 0xCD14 }, +{ 0xCD15, 0xCD15, 0xCD15 }, +{ 0xCD16, 0xCD16, 0xCD16 }, +{ 0xCD17, 0xCD17, 0xCD17 }, +{ 0xCD18, 0xCD18, 0xCD18 }, +{ 0xCD19, 0xCD19, 0xCD19 }, +{ 0xCD1A, 0xCD1A, 0xCD1A }, +{ 0xCD1B, 0xCD1B, 0xCD1B }, +{ 0xCD1C, 0xCD1C, 0xCD1C }, +{ 0xCD1D, 0xCD1D, 0xCD1D }, +{ 0xCD1E, 0xCD1E, 0xCD1E }, +{ 0xCD1F, 0xCD1F, 0xCD1F }, +{ 0xCD20, 0xCD20, 0xCD20 }, +{ 0xCD21, 0xCD21, 0xCD21 }, +{ 0xCD22, 0xCD22, 0xCD22 }, +{ 0xCD23, 0xCD23, 0xCD23 }, +{ 0xCD24, 0xCD24, 0xCD24 }, +{ 0xCD25, 0xCD25, 0xCD25 }, +{ 0xCD26, 0xCD26, 0xCD26 }, +{ 0xCD27, 0xCD27, 0xCD27 }, +{ 0xCD28, 0xCD28, 0xCD28 }, +{ 0xCD29, 0xCD29, 0xCD29 }, +{ 0xCD2A, 0xCD2A, 0xCD2A }, +{ 0xCD2B, 0xCD2B, 0xCD2B }, +{ 0xCD2C, 0xCD2C, 0xCD2C }, +{ 0xCD2D, 0xCD2D, 0xCD2D }, +{ 0xCD2E, 0xCD2E, 0xCD2E }, +{ 0xCD2F, 0xCD2F, 0xCD2F }, +{ 0xCD30, 0xCD30, 0xCD30 }, +{ 0xCD31, 0xCD31, 0xCD31 }, +{ 0xCD32, 0xCD32, 0xCD32 }, +{ 0xCD33, 0xCD33, 0xCD33 }, +{ 0xCD34, 0xCD34, 0xCD34 }, +{ 0xCD35, 0xCD35, 0xCD35 }, +{ 0xCD36, 0xCD36, 0xCD36 }, +{ 0xCD37, 0xCD37, 0xCD37 }, +{ 0xCD38, 0xCD38, 0xCD38 }, +{ 0xCD39, 0xCD39, 0xCD39 }, +{ 0xCD3A, 0xCD3A, 0xCD3A }, +{ 0xCD3B, 0xCD3B, 0xCD3B }, +{ 0xCD3C, 0xCD3C, 0xCD3C }, +{ 0xCD3D, 0xCD3D, 0xCD3D }, +{ 0xCD3E, 0xCD3E, 0xCD3E }, +{ 0xCD3F, 0xCD3F, 0xCD3F }, +{ 0xCD40, 0xCD40, 0xCD40 }, +{ 0xCD41, 0xCD41, 0xCD41 }, +{ 0xCD42, 0xCD42, 0xCD42 }, +{ 0xCD43, 0xCD43, 0xCD43 }, +{ 0xCD44, 0xCD44, 0xCD44 }, +{ 0xCD45, 0xCD45, 0xCD45 }, +{ 0xCD46, 0xCD46, 0xCD46 }, +{ 0xCD47, 0xCD47, 0xCD47 }, +{ 0xCD48, 0xCD48, 0xCD48 }, +{ 0xCD49, 0xCD49, 0xCD49 }, +{ 0xCD4A, 0xCD4A, 0xCD4A }, +{ 0xCD4B, 0xCD4B, 0xCD4B }, +{ 0xCD4C, 0xCD4C, 0xCD4C }, +{ 0xCD4D, 0xCD4D, 0xCD4D }, +{ 0xCD4E, 0xCD4E, 0xCD4E }, +{ 0xCD4F, 0xCD4F, 0xCD4F }, +{ 0xCD50, 0xCD50, 0xCD50 }, +{ 0xCD51, 0xCD51, 0xCD51 }, +{ 0xCD52, 0xCD52, 0xCD52 }, +{ 0xCD53, 0xCD53, 0xCD53 }, +{ 0xCD54, 0xCD54, 0xCD54 }, +{ 0xCD55, 0xCD55, 0xCD55 }, +{ 0xCD56, 0xCD56, 0xCD56 }, +{ 0xCD57, 0xCD57, 0xCD57 }, +{ 0xCD58, 0xCD58, 0xCD58 }, +{ 0xCD59, 0xCD59, 0xCD59 }, +{ 0xCD5A, 0xCD5A, 0xCD5A }, +{ 0xCD5B, 0xCD5B, 0xCD5B }, +{ 0xCD5C, 0xCD5C, 0xCD5C }, +{ 0xCD5D, 0xCD5D, 0xCD5D }, +{ 0xCD5E, 0xCD5E, 0xCD5E }, +{ 0xCD5F, 0xCD5F, 0xCD5F }, +{ 0xCD60, 0xCD60, 0xCD60 }, +{ 0xCD61, 0xCD61, 0xCD61 }, +{ 0xCD62, 0xCD62, 0xCD62 }, +{ 0xCD63, 0xCD63, 0xCD63 }, +{ 0xCD64, 0xCD64, 0xCD64 }, +{ 0xCD65, 0xCD65, 0xCD65 }, +{ 0xCD66, 0xCD66, 0xCD66 }, +{ 0xCD67, 0xCD67, 0xCD67 }, +{ 0xCD68, 0xCD68, 0xCD68 }, +{ 0xCD69, 0xCD69, 0xCD69 }, +{ 0xCD6A, 0xCD6A, 0xCD6A }, +{ 0xCD6B, 0xCD6B, 0xCD6B }, +{ 0xCD6C, 0xCD6C, 0xCD6C }, +{ 0xCD6D, 0xCD6D, 0xCD6D }, +{ 0xCD6E, 0xCD6E, 0xCD6E }, +{ 0xCD6F, 0xCD6F, 0xCD6F }, +{ 0xCD70, 0xCD70, 0xCD70 }, +{ 0xCD71, 0xCD71, 0xCD71 }, +{ 0xCD72, 0xCD72, 0xCD72 }, +{ 0xCD73, 0xCD73, 0xCD73 }, +{ 0xCD74, 0xCD74, 0xCD74 }, +{ 0xCD75, 0xCD75, 0xCD75 }, +{ 0xCD76, 0xCD76, 0xCD76 }, +{ 0xCD77, 0xCD77, 0xCD77 }, +{ 0xCD78, 0xCD78, 0xCD78 }, +{ 0xCD79, 0xCD79, 0xCD79 }, +{ 0xCD7A, 0xCD7A, 0xCD7A }, +{ 0xCD7B, 0xCD7B, 0xCD7B }, +{ 0xCD7C, 0xCD7C, 0xCD7C }, +{ 0xCD7D, 0xCD7D, 0xCD7D }, +{ 0xCD7E, 0xCD7E, 0xCD7E }, +{ 0xCD7F, 0xCD7F, 0xCD7F }, +{ 0xCD80, 0xCD80, 0xCD80 }, +{ 0xCD81, 0xCD81, 0xCD81 }, +{ 0xCD82, 0xCD82, 0xCD82 }, +{ 0xCD83, 0xCD83, 0xCD83 }, +{ 0xCD84, 0xCD84, 0xCD84 }, +{ 0xCD85, 0xCD85, 0xCD85 }, +{ 0xCD86, 0xCD86, 0xCD86 }, +{ 0xCD87, 0xCD87, 0xCD87 }, +{ 0xCD88, 0xCD88, 0xCD88 }, +{ 0xCD89, 0xCD89, 0xCD89 }, +{ 0xCD8A, 0xCD8A, 0xCD8A }, +{ 0xCD8B, 0xCD8B, 0xCD8B }, +{ 0xCD8C, 0xCD8C, 0xCD8C }, +{ 0xCD8D, 0xCD8D, 0xCD8D }, +{ 0xCD8E, 0xCD8E, 0xCD8E }, +{ 0xCD8F, 0xCD8F, 0xCD8F }, +{ 0xCD90, 0xCD90, 0xCD90 }, +{ 0xCD91, 0xCD91, 0xCD91 }, +{ 0xCD92, 0xCD92, 0xCD92 }, +{ 0xCD93, 0xCD93, 0xCD93 }, +{ 0xCD94, 0xCD94, 0xCD94 }, +{ 0xCD95, 0xCD95, 0xCD95 }, +{ 0xCD96, 0xCD96, 0xCD96 }, +{ 0xCD97, 0xCD97, 0xCD97 }, +{ 0xCD98, 0xCD98, 0xCD98 }, +{ 0xCD99, 0xCD99, 0xCD99 }, +{ 0xCD9A, 0xCD9A, 0xCD9A }, +{ 0xCD9B, 0xCD9B, 0xCD9B }, +{ 0xCD9C, 0xCD9C, 0xCD9C }, +{ 0xCD9D, 0xCD9D, 0xCD9D }, +{ 0xCD9E, 0xCD9E, 0xCD9E }, +{ 0xCD9F, 0xCD9F, 0xCD9F }, +{ 0xCDA0, 0xCDA0, 0xCDA0 }, +{ 0xCDA1, 0xCDA1, 0xCDA1 }, +{ 0xCDA2, 0xCDA2, 0xCDA2 }, +{ 0xCDA3, 0xCDA3, 0xCDA3 }, +{ 0xCDA4, 0xCDA4, 0xCDA4 }, +{ 0xCDA5, 0xCDA5, 0xCDA5 }, +{ 0xCDA6, 0xCDA6, 0xCDA6 }, +{ 0xCDA7, 0xCDA7, 0xCDA7 }, +{ 0xCDA8, 0xCDA8, 0xCDA8 }, +{ 0xCDA9, 0xCDA9, 0xCDA9 }, +{ 0xCDAA, 0xCDAA, 0xCDAA }, +{ 0xCDAB, 0xCDAB, 0xCDAB }, +{ 0xCDAC, 0xCDAC, 0xCDAC }, +{ 0xCDAD, 0xCDAD, 0xCDAD }, +{ 0xCDAE, 0xCDAE, 0xCDAE }, +{ 0xCDAF, 0xCDAF, 0xCDAF }, +{ 0xCDB0, 0xCDB0, 0xCDB0 }, +{ 0xCDB1, 0xCDB1, 0xCDB1 }, +{ 0xCDB2, 0xCDB2, 0xCDB2 }, +{ 0xCDB3, 0xCDB3, 0xCDB3 }, +{ 0xCDB4, 0xCDB4, 0xCDB4 }, +{ 0xCDB5, 0xCDB5, 0xCDB5 }, +{ 0xCDB6, 0xCDB6, 0xCDB6 }, +{ 0xCDB7, 0xCDB7, 0xCDB7 }, +{ 0xCDB8, 0xCDB8, 0xCDB8 }, +{ 0xCDB9, 0xCDB9, 0xCDB9 }, +{ 0xCDBA, 0xCDBA, 0xCDBA }, +{ 0xCDBB, 0xCDBB, 0xCDBB }, +{ 0xCDBC, 0xCDBC, 0xCDBC }, +{ 0xCDBD, 0xCDBD, 0xCDBD }, +{ 0xCDBE, 0xCDBE, 0xCDBE }, +{ 0xCDBF, 0xCDBF, 0xCDBF }, +{ 0xCDC0, 0xCDC0, 0xCDC0 }, +{ 0xCDC1, 0xCDC1, 0xCDC1 }, +{ 0xCDC2, 0xCDC2, 0xCDC2 }, +{ 0xCDC3, 0xCDC3, 0xCDC3 }, +{ 0xCDC4, 0xCDC4, 0xCDC4 }, +{ 0xCDC5, 0xCDC5, 0xCDC5 }, +{ 0xCDC6, 0xCDC6, 0xCDC6 }, +{ 0xCDC7, 0xCDC7, 0xCDC7 }, +{ 0xCDC8, 0xCDC8, 0xCDC8 }, +{ 0xCDC9, 0xCDC9, 0xCDC9 }, +{ 0xCDCA, 0xCDCA, 0xCDCA }, +{ 0xCDCB, 0xCDCB, 0xCDCB }, +{ 0xCDCC, 0xCDCC, 0xCDCC }, +{ 0xCDCD, 0xCDCD, 0xCDCD }, +{ 0xCDCE, 0xCDCE, 0xCDCE }, +{ 0xCDCF, 0xCDCF, 0xCDCF }, +{ 0xCDD0, 0xCDD0, 0xCDD0 }, +{ 0xCDD1, 0xCDD1, 0xCDD1 }, +{ 0xCDD2, 0xCDD2, 0xCDD2 }, +{ 0xCDD3, 0xCDD3, 0xCDD3 }, +{ 0xCDD4, 0xCDD4, 0xCDD4 }, +{ 0xCDD5, 0xCDD5, 0xCDD5 }, +{ 0xCDD6, 0xCDD6, 0xCDD6 }, +{ 0xCDD7, 0xCDD7, 0xCDD7 }, +{ 0xCDD8, 0xCDD8, 0xCDD8 }, +{ 0xCDD9, 0xCDD9, 0xCDD9 }, +{ 0xCDDA, 0xCDDA, 0xCDDA }, +{ 0xCDDB, 0xCDDB, 0xCDDB }, +{ 0xCDDC, 0xCDDC, 0xCDDC }, +{ 0xCDDD, 0xCDDD, 0xCDDD }, +{ 0xCDDE, 0xCDDE, 0xCDDE }, +{ 0xCDDF, 0xCDDF, 0xCDDF }, +{ 0xCDE0, 0xCDE0, 0xCDE0 }, +{ 0xCDE1, 0xCDE1, 0xCDE1 }, +{ 0xCDE2, 0xCDE2, 0xCDE2 }, +{ 0xCDE3, 0xCDE3, 0xCDE3 }, +{ 0xCDE4, 0xCDE4, 0xCDE4 }, +{ 0xCDE5, 0xCDE5, 0xCDE5 }, +{ 0xCDE6, 0xCDE6, 0xCDE6 }, +{ 0xCDE7, 0xCDE7, 0xCDE7 }, +{ 0xCDE8, 0xCDE8, 0xCDE8 }, +{ 0xCDE9, 0xCDE9, 0xCDE9 }, +{ 0xCDEA, 0xCDEA, 0xCDEA }, +{ 0xCDEB, 0xCDEB, 0xCDEB }, +{ 0xCDEC, 0xCDEC, 0xCDEC }, +{ 0xCDED, 0xCDED, 0xCDED }, +{ 0xCDEE, 0xCDEE, 0xCDEE }, +{ 0xCDEF, 0xCDEF, 0xCDEF }, +{ 0xCDF0, 0xCDF0, 0xCDF0 }, +{ 0xCDF1, 0xCDF1, 0xCDF1 }, +{ 0xCDF2, 0xCDF2, 0xCDF2 }, +{ 0xCDF3, 0xCDF3, 0xCDF3 }, +{ 0xCDF4, 0xCDF4, 0xCDF4 }, +{ 0xCDF5, 0xCDF5, 0xCDF5 }, +{ 0xCDF6, 0xCDF6, 0xCDF6 }, +{ 0xCDF7, 0xCDF7, 0xCDF7 }, +{ 0xCDF8, 0xCDF8, 0xCDF8 }, +{ 0xCDF9, 0xCDF9, 0xCDF9 }, +{ 0xCDFA, 0xCDFA, 0xCDFA }, +{ 0xCDFB, 0xCDFB, 0xCDFB }, +{ 0xCDFC, 0xCDFC, 0xCDFC }, +{ 0xCDFD, 0xCDFD, 0xCDFD }, +{ 0xCDFE, 0xCDFE, 0xCDFE }, +{ 0xCDFF, 0xCDFF, 0xCDFF }, +{ 0xCE00, 0xCE00, 0xCE00 }, +{ 0xCE01, 0xCE01, 0xCE01 }, +{ 0xCE02, 0xCE02, 0xCE02 }, +{ 0xCE03, 0xCE03, 0xCE03 }, +{ 0xCE04, 0xCE04, 0xCE04 }, +{ 0xCE05, 0xCE05, 0xCE05 }, +{ 0xCE06, 0xCE06, 0xCE06 }, +{ 0xCE07, 0xCE07, 0xCE07 }, +{ 0xCE08, 0xCE08, 0xCE08 }, +{ 0xCE09, 0xCE09, 0xCE09 }, +{ 0xCE0A, 0xCE0A, 0xCE0A }, +{ 0xCE0B, 0xCE0B, 0xCE0B }, +{ 0xCE0C, 0xCE0C, 0xCE0C }, +{ 0xCE0D, 0xCE0D, 0xCE0D }, +{ 0xCE0E, 0xCE0E, 0xCE0E }, +{ 0xCE0F, 0xCE0F, 0xCE0F }, +{ 0xCE10, 0xCE10, 0xCE10 }, +{ 0xCE11, 0xCE11, 0xCE11 }, +{ 0xCE12, 0xCE12, 0xCE12 }, +{ 0xCE13, 0xCE13, 0xCE13 }, +{ 0xCE14, 0xCE14, 0xCE14 }, +{ 0xCE15, 0xCE15, 0xCE15 }, +{ 0xCE16, 0xCE16, 0xCE16 }, +{ 0xCE17, 0xCE17, 0xCE17 }, +{ 0xCE18, 0xCE18, 0xCE18 }, +{ 0xCE19, 0xCE19, 0xCE19 }, +{ 0xCE1A, 0xCE1A, 0xCE1A }, +{ 0xCE1B, 0xCE1B, 0xCE1B }, +{ 0xCE1C, 0xCE1C, 0xCE1C }, +{ 0xCE1D, 0xCE1D, 0xCE1D }, +{ 0xCE1E, 0xCE1E, 0xCE1E }, +{ 0xCE1F, 0xCE1F, 0xCE1F }, +{ 0xCE20, 0xCE20, 0xCE20 }, +{ 0xCE21, 0xCE21, 0xCE21 }, +{ 0xCE22, 0xCE22, 0xCE22 }, +{ 0xCE23, 0xCE23, 0xCE23 }, +{ 0xCE24, 0xCE24, 0xCE24 }, +{ 0xCE25, 0xCE25, 0xCE25 }, +{ 0xCE26, 0xCE26, 0xCE26 }, +{ 0xCE27, 0xCE27, 0xCE27 }, +{ 0xCE28, 0xCE28, 0xCE28 }, +{ 0xCE29, 0xCE29, 0xCE29 }, +{ 0xCE2A, 0xCE2A, 0xCE2A }, +{ 0xCE2B, 0xCE2B, 0xCE2B }, +{ 0xCE2C, 0xCE2C, 0xCE2C }, +{ 0xCE2D, 0xCE2D, 0xCE2D }, +{ 0xCE2E, 0xCE2E, 0xCE2E }, +{ 0xCE2F, 0xCE2F, 0xCE2F }, +{ 0xCE30, 0xCE30, 0xCE30 }, +{ 0xCE31, 0xCE31, 0xCE31 }, +{ 0xCE32, 0xCE32, 0xCE32 }, +{ 0xCE33, 0xCE33, 0xCE33 }, +{ 0xCE34, 0xCE34, 0xCE34 }, +{ 0xCE35, 0xCE35, 0xCE35 }, +{ 0xCE36, 0xCE36, 0xCE36 }, +{ 0xCE37, 0xCE37, 0xCE37 }, +{ 0xCE38, 0xCE38, 0xCE38 }, +{ 0xCE39, 0xCE39, 0xCE39 }, +{ 0xCE3A, 0xCE3A, 0xCE3A }, +{ 0xCE3B, 0xCE3B, 0xCE3B }, +{ 0xCE3C, 0xCE3C, 0xCE3C }, +{ 0xCE3D, 0xCE3D, 0xCE3D }, +{ 0xCE3E, 0xCE3E, 0xCE3E }, +{ 0xCE3F, 0xCE3F, 0xCE3F }, +{ 0xCE40, 0xCE40, 0xCE40 }, +{ 0xCE41, 0xCE41, 0xCE41 }, +{ 0xCE42, 0xCE42, 0xCE42 }, +{ 0xCE43, 0xCE43, 0xCE43 }, +{ 0xCE44, 0xCE44, 0xCE44 }, +{ 0xCE45, 0xCE45, 0xCE45 }, +{ 0xCE46, 0xCE46, 0xCE46 }, +{ 0xCE47, 0xCE47, 0xCE47 }, +{ 0xCE48, 0xCE48, 0xCE48 }, +{ 0xCE49, 0xCE49, 0xCE49 }, +{ 0xCE4A, 0xCE4A, 0xCE4A }, +{ 0xCE4B, 0xCE4B, 0xCE4B }, +{ 0xCE4C, 0xCE4C, 0xCE4C }, +{ 0xCE4D, 0xCE4D, 0xCE4D }, +{ 0xCE4E, 0xCE4E, 0xCE4E }, +{ 0xCE4F, 0xCE4F, 0xCE4F }, +{ 0xCE50, 0xCE50, 0xCE50 }, +{ 0xCE51, 0xCE51, 0xCE51 }, +{ 0xCE52, 0xCE52, 0xCE52 }, +{ 0xCE53, 0xCE53, 0xCE53 }, +{ 0xCE54, 0xCE54, 0xCE54 }, +{ 0xCE55, 0xCE55, 0xCE55 }, +{ 0xCE56, 0xCE56, 0xCE56 }, +{ 0xCE57, 0xCE57, 0xCE57 }, +{ 0xCE58, 0xCE58, 0xCE58 }, +{ 0xCE59, 0xCE59, 0xCE59 }, +{ 0xCE5A, 0xCE5A, 0xCE5A }, +{ 0xCE5B, 0xCE5B, 0xCE5B }, +{ 0xCE5C, 0xCE5C, 0xCE5C }, +{ 0xCE5D, 0xCE5D, 0xCE5D }, +{ 0xCE5E, 0xCE5E, 0xCE5E }, +{ 0xCE5F, 0xCE5F, 0xCE5F }, +{ 0xCE60, 0xCE60, 0xCE60 }, +{ 0xCE61, 0xCE61, 0xCE61 }, +{ 0xCE62, 0xCE62, 0xCE62 }, +{ 0xCE63, 0xCE63, 0xCE63 }, +{ 0xCE64, 0xCE64, 0xCE64 }, +{ 0xCE65, 0xCE65, 0xCE65 }, +{ 0xCE66, 0xCE66, 0xCE66 }, +{ 0xCE67, 0xCE67, 0xCE67 }, +{ 0xCE68, 0xCE68, 0xCE68 }, +{ 0xCE69, 0xCE69, 0xCE69 }, +{ 0xCE6A, 0xCE6A, 0xCE6A }, +{ 0xCE6B, 0xCE6B, 0xCE6B }, +{ 0xCE6C, 0xCE6C, 0xCE6C }, +{ 0xCE6D, 0xCE6D, 0xCE6D }, +{ 0xCE6E, 0xCE6E, 0xCE6E }, +{ 0xCE6F, 0xCE6F, 0xCE6F }, +{ 0xCE70, 0xCE70, 0xCE70 }, +{ 0xCE71, 0xCE71, 0xCE71 }, +{ 0xCE72, 0xCE72, 0xCE72 }, +{ 0xCE73, 0xCE73, 0xCE73 }, +{ 0xCE74, 0xCE74, 0xCE74 }, +{ 0xCE75, 0xCE75, 0xCE75 }, +{ 0xCE76, 0xCE76, 0xCE76 }, +{ 0xCE77, 0xCE77, 0xCE77 }, +{ 0xCE78, 0xCE78, 0xCE78 }, +{ 0xCE79, 0xCE79, 0xCE79 }, +{ 0xCE7A, 0xCE7A, 0xCE7A }, +{ 0xCE7B, 0xCE7B, 0xCE7B }, +{ 0xCE7C, 0xCE7C, 0xCE7C }, +{ 0xCE7D, 0xCE7D, 0xCE7D }, +{ 0xCE7E, 0xCE7E, 0xCE7E }, +{ 0xCE7F, 0xCE7F, 0xCE7F }, +{ 0xCE80, 0xCE80, 0xCE80 }, +{ 0xCE81, 0xCE81, 0xCE81 }, +{ 0xCE82, 0xCE82, 0xCE82 }, +{ 0xCE83, 0xCE83, 0xCE83 }, +{ 0xCE84, 0xCE84, 0xCE84 }, +{ 0xCE85, 0xCE85, 0xCE85 }, +{ 0xCE86, 0xCE86, 0xCE86 }, +{ 0xCE87, 0xCE87, 0xCE87 }, +{ 0xCE88, 0xCE88, 0xCE88 }, +{ 0xCE89, 0xCE89, 0xCE89 }, +{ 0xCE8A, 0xCE8A, 0xCE8A }, +{ 0xCE8B, 0xCE8B, 0xCE8B }, +{ 0xCE8C, 0xCE8C, 0xCE8C }, +{ 0xCE8D, 0xCE8D, 0xCE8D }, +{ 0xCE8E, 0xCE8E, 0xCE8E }, +{ 0xCE8F, 0xCE8F, 0xCE8F }, +{ 0xCE90, 0xCE90, 0xCE90 }, +{ 0xCE91, 0xCE91, 0xCE91 }, +{ 0xCE92, 0xCE92, 0xCE92 }, +{ 0xCE93, 0xCE93, 0xCE93 }, +{ 0xCE94, 0xCE94, 0xCE94 }, +{ 0xCE95, 0xCE95, 0xCE95 }, +{ 0xCE96, 0xCE96, 0xCE96 }, +{ 0xCE97, 0xCE97, 0xCE97 }, +{ 0xCE98, 0xCE98, 0xCE98 }, +{ 0xCE99, 0xCE99, 0xCE99 }, +{ 0xCE9A, 0xCE9A, 0xCE9A }, +{ 0xCE9B, 0xCE9B, 0xCE9B }, +{ 0xCE9C, 0xCE9C, 0xCE9C }, +{ 0xCE9D, 0xCE9D, 0xCE9D }, +{ 0xCE9E, 0xCE9E, 0xCE9E }, +{ 0xCE9F, 0xCE9F, 0xCE9F }, +{ 0xCEA0, 0xCEA0, 0xCEA0 }, +{ 0xCEA1, 0xCEA1, 0xCEA1 }, +{ 0xCEA2, 0xCEA2, 0xCEA2 }, +{ 0xCEA3, 0xCEA3, 0xCEA3 }, +{ 0xCEA4, 0xCEA4, 0xCEA4 }, +{ 0xCEA5, 0xCEA5, 0xCEA5 }, +{ 0xCEA6, 0xCEA6, 0xCEA6 }, +{ 0xCEA7, 0xCEA7, 0xCEA7 }, +{ 0xCEA8, 0xCEA8, 0xCEA8 }, +{ 0xCEA9, 0xCEA9, 0xCEA9 }, +{ 0xCEAA, 0xCEAA, 0xCEAA }, +{ 0xCEAB, 0xCEAB, 0xCEAB }, +{ 0xCEAC, 0xCEAC, 0xCEAC }, +{ 0xCEAD, 0xCEAD, 0xCEAD }, +{ 0xCEAE, 0xCEAE, 0xCEAE }, +{ 0xCEAF, 0xCEAF, 0xCEAF }, +{ 0xCEB0, 0xCEB0, 0xCEB0 }, +{ 0xCEB1, 0xCEB1, 0xCEB1 }, +{ 0xCEB2, 0xCEB2, 0xCEB2 }, +{ 0xCEB3, 0xCEB3, 0xCEB3 }, +{ 0xCEB4, 0xCEB4, 0xCEB4 }, +{ 0xCEB5, 0xCEB5, 0xCEB5 }, +{ 0xCEB6, 0xCEB6, 0xCEB6 }, +{ 0xCEB7, 0xCEB7, 0xCEB7 }, +{ 0xCEB8, 0xCEB8, 0xCEB8 }, +{ 0xCEB9, 0xCEB9, 0xCEB9 }, +{ 0xCEBA, 0xCEBA, 0xCEBA }, +{ 0xCEBB, 0xCEBB, 0xCEBB }, +{ 0xCEBC, 0xCEBC, 0xCEBC }, +{ 0xCEBD, 0xCEBD, 0xCEBD }, +{ 0xCEBE, 0xCEBE, 0xCEBE }, +{ 0xCEBF, 0xCEBF, 0xCEBF }, +{ 0xCEC0, 0xCEC0, 0xCEC0 }, +{ 0xCEC1, 0xCEC1, 0xCEC1 }, +{ 0xCEC2, 0xCEC2, 0xCEC2 }, +{ 0xCEC3, 0xCEC3, 0xCEC3 }, +{ 0xCEC4, 0xCEC4, 0xCEC4 }, +{ 0xCEC5, 0xCEC5, 0xCEC5 }, +{ 0xCEC6, 0xCEC6, 0xCEC6 }, +{ 0xCEC7, 0xCEC7, 0xCEC7 }, +{ 0xCEC8, 0xCEC8, 0xCEC8 }, +{ 0xCEC9, 0xCEC9, 0xCEC9 }, +{ 0xCECA, 0xCECA, 0xCECA }, +{ 0xCECB, 0xCECB, 0xCECB }, +{ 0xCECC, 0xCECC, 0xCECC }, +{ 0xCECD, 0xCECD, 0xCECD }, +{ 0xCECE, 0xCECE, 0xCECE }, +{ 0xCECF, 0xCECF, 0xCECF }, +{ 0xCED0, 0xCED0, 0xCED0 }, +{ 0xCED1, 0xCED1, 0xCED1 }, +{ 0xCED2, 0xCED2, 0xCED2 }, +{ 0xCED3, 0xCED3, 0xCED3 }, +{ 0xCED4, 0xCED4, 0xCED4 }, +{ 0xCED5, 0xCED5, 0xCED5 }, +{ 0xCED6, 0xCED6, 0xCED6 }, +{ 0xCED7, 0xCED7, 0xCED7 }, +{ 0xCED8, 0xCED8, 0xCED8 }, +{ 0xCED9, 0xCED9, 0xCED9 }, +{ 0xCEDA, 0xCEDA, 0xCEDA }, +{ 0xCEDB, 0xCEDB, 0xCEDB }, +{ 0xCEDC, 0xCEDC, 0xCEDC }, +{ 0xCEDD, 0xCEDD, 0xCEDD }, +{ 0xCEDE, 0xCEDE, 0xCEDE }, +{ 0xCEDF, 0xCEDF, 0xCEDF }, +{ 0xCEE0, 0xCEE0, 0xCEE0 }, +{ 0xCEE1, 0xCEE1, 0xCEE1 }, +{ 0xCEE2, 0xCEE2, 0xCEE2 }, +{ 0xCEE3, 0xCEE3, 0xCEE3 }, +{ 0xCEE4, 0xCEE4, 0xCEE4 }, +{ 0xCEE5, 0xCEE5, 0xCEE5 }, +{ 0xCEE6, 0xCEE6, 0xCEE6 }, +{ 0xCEE7, 0xCEE7, 0xCEE7 }, +{ 0xCEE8, 0xCEE8, 0xCEE8 }, +{ 0xCEE9, 0xCEE9, 0xCEE9 }, +{ 0xCEEA, 0xCEEA, 0xCEEA }, +{ 0xCEEB, 0xCEEB, 0xCEEB }, +{ 0xCEEC, 0xCEEC, 0xCEEC }, +{ 0xCEED, 0xCEED, 0xCEED }, +{ 0xCEEE, 0xCEEE, 0xCEEE }, +{ 0xCEEF, 0xCEEF, 0xCEEF }, +{ 0xCEF0, 0xCEF0, 0xCEF0 }, +{ 0xCEF1, 0xCEF1, 0xCEF1 }, +{ 0xCEF2, 0xCEF2, 0xCEF2 }, +{ 0xCEF3, 0xCEF3, 0xCEF3 }, +{ 0xCEF4, 0xCEF4, 0xCEF4 }, +{ 0xCEF5, 0xCEF5, 0xCEF5 }, +{ 0xCEF6, 0xCEF6, 0xCEF6 }, +{ 0xCEF7, 0xCEF7, 0xCEF7 }, +{ 0xCEF8, 0xCEF8, 0xCEF8 }, +{ 0xCEF9, 0xCEF9, 0xCEF9 }, +{ 0xCEFA, 0xCEFA, 0xCEFA }, +{ 0xCEFB, 0xCEFB, 0xCEFB }, +{ 0xCEFC, 0xCEFC, 0xCEFC }, +{ 0xCEFD, 0xCEFD, 0xCEFD }, +{ 0xCEFE, 0xCEFE, 0xCEFE }, +{ 0xCEFF, 0xCEFF, 0xCEFF }, +{ 0xCF00, 0xCF00, 0xCF00 }, +{ 0xCF01, 0xCF01, 0xCF01 }, +{ 0xCF02, 0xCF02, 0xCF02 }, +{ 0xCF03, 0xCF03, 0xCF03 }, +{ 0xCF04, 0xCF04, 0xCF04 }, +{ 0xCF05, 0xCF05, 0xCF05 }, +{ 0xCF06, 0xCF06, 0xCF06 }, +{ 0xCF07, 0xCF07, 0xCF07 }, +{ 0xCF08, 0xCF08, 0xCF08 }, +{ 0xCF09, 0xCF09, 0xCF09 }, +{ 0xCF0A, 0xCF0A, 0xCF0A }, +{ 0xCF0B, 0xCF0B, 0xCF0B }, +{ 0xCF0C, 0xCF0C, 0xCF0C }, +{ 0xCF0D, 0xCF0D, 0xCF0D }, +{ 0xCF0E, 0xCF0E, 0xCF0E }, +{ 0xCF0F, 0xCF0F, 0xCF0F }, +{ 0xCF10, 0xCF10, 0xCF10 }, +{ 0xCF11, 0xCF11, 0xCF11 }, +{ 0xCF12, 0xCF12, 0xCF12 }, +{ 0xCF13, 0xCF13, 0xCF13 }, +{ 0xCF14, 0xCF14, 0xCF14 }, +{ 0xCF15, 0xCF15, 0xCF15 }, +{ 0xCF16, 0xCF16, 0xCF16 }, +{ 0xCF17, 0xCF17, 0xCF17 }, +{ 0xCF18, 0xCF18, 0xCF18 }, +{ 0xCF19, 0xCF19, 0xCF19 }, +{ 0xCF1A, 0xCF1A, 0xCF1A }, +{ 0xCF1B, 0xCF1B, 0xCF1B }, +{ 0xCF1C, 0xCF1C, 0xCF1C }, +{ 0xCF1D, 0xCF1D, 0xCF1D }, +{ 0xCF1E, 0xCF1E, 0xCF1E }, +{ 0xCF1F, 0xCF1F, 0xCF1F }, +{ 0xCF20, 0xCF20, 0xCF20 }, +{ 0xCF21, 0xCF21, 0xCF21 }, +{ 0xCF22, 0xCF22, 0xCF22 }, +{ 0xCF23, 0xCF23, 0xCF23 }, +{ 0xCF24, 0xCF24, 0xCF24 }, +{ 0xCF25, 0xCF25, 0xCF25 }, +{ 0xCF26, 0xCF26, 0xCF26 }, +{ 0xCF27, 0xCF27, 0xCF27 }, +{ 0xCF28, 0xCF28, 0xCF28 }, +{ 0xCF29, 0xCF29, 0xCF29 }, +{ 0xCF2A, 0xCF2A, 0xCF2A }, +{ 0xCF2B, 0xCF2B, 0xCF2B }, +{ 0xCF2C, 0xCF2C, 0xCF2C }, +{ 0xCF2D, 0xCF2D, 0xCF2D }, +{ 0xCF2E, 0xCF2E, 0xCF2E }, +{ 0xCF2F, 0xCF2F, 0xCF2F }, +{ 0xCF30, 0xCF30, 0xCF30 }, +{ 0xCF31, 0xCF31, 0xCF31 }, +{ 0xCF32, 0xCF32, 0xCF32 }, +{ 0xCF33, 0xCF33, 0xCF33 }, +{ 0xCF34, 0xCF34, 0xCF34 }, +{ 0xCF35, 0xCF35, 0xCF35 }, +{ 0xCF36, 0xCF36, 0xCF36 }, +{ 0xCF37, 0xCF37, 0xCF37 }, +{ 0xCF38, 0xCF38, 0xCF38 }, +{ 0xCF39, 0xCF39, 0xCF39 }, +{ 0xCF3A, 0xCF3A, 0xCF3A }, +{ 0xCF3B, 0xCF3B, 0xCF3B }, +{ 0xCF3C, 0xCF3C, 0xCF3C }, +{ 0xCF3D, 0xCF3D, 0xCF3D }, +{ 0xCF3E, 0xCF3E, 0xCF3E }, +{ 0xCF3F, 0xCF3F, 0xCF3F }, +{ 0xCF40, 0xCF40, 0xCF40 }, +{ 0xCF41, 0xCF41, 0xCF41 }, +{ 0xCF42, 0xCF42, 0xCF42 }, +{ 0xCF43, 0xCF43, 0xCF43 }, +{ 0xCF44, 0xCF44, 0xCF44 }, +{ 0xCF45, 0xCF45, 0xCF45 }, +{ 0xCF46, 0xCF46, 0xCF46 }, +{ 0xCF47, 0xCF47, 0xCF47 }, +{ 0xCF48, 0xCF48, 0xCF48 }, +{ 0xCF49, 0xCF49, 0xCF49 }, +{ 0xCF4A, 0xCF4A, 0xCF4A }, +{ 0xCF4B, 0xCF4B, 0xCF4B }, +{ 0xCF4C, 0xCF4C, 0xCF4C }, +{ 0xCF4D, 0xCF4D, 0xCF4D }, +{ 0xCF4E, 0xCF4E, 0xCF4E }, +{ 0xCF4F, 0xCF4F, 0xCF4F }, +{ 0xCF50, 0xCF50, 0xCF50 }, +{ 0xCF51, 0xCF51, 0xCF51 }, +{ 0xCF52, 0xCF52, 0xCF52 }, +{ 0xCF53, 0xCF53, 0xCF53 }, +{ 0xCF54, 0xCF54, 0xCF54 }, +{ 0xCF55, 0xCF55, 0xCF55 }, +{ 0xCF56, 0xCF56, 0xCF56 }, +{ 0xCF57, 0xCF57, 0xCF57 }, +{ 0xCF58, 0xCF58, 0xCF58 }, +{ 0xCF59, 0xCF59, 0xCF59 }, +{ 0xCF5A, 0xCF5A, 0xCF5A }, +{ 0xCF5B, 0xCF5B, 0xCF5B }, +{ 0xCF5C, 0xCF5C, 0xCF5C }, +{ 0xCF5D, 0xCF5D, 0xCF5D }, +{ 0xCF5E, 0xCF5E, 0xCF5E }, +{ 0xCF5F, 0xCF5F, 0xCF5F }, +{ 0xCF60, 0xCF60, 0xCF60 }, +{ 0xCF61, 0xCF61, 0xCF61 }, +{ 0xCF62, 0xCF62, 0xCF62 }, +{ 0xCF63, 0xCF63, 0xCF63 }, +{ 0xCF64, 0xCF64, 0xCF64 }, +{ 0xCF65, 0xCF65, 0xCF65 }, +{ 0xCF66, 0xCF66, 0xCF66 }, +{ 0xCF67, 0xCF67, 0xCF67 }, +{ 0xCF68, 0xCF68, 0xCF68 }, +{ 0xCF69, 0xCF69, 0xCF69 }, +{ 0xCF6A, 0xCF6A, 0xCF6A }, +{ 0xCF6B, 0xCF6B, 0xCF6B }, +{ 0xCF6C, 0xCF6C, 0xCF6C }, +{ 0xCF6D, 0xCF6D, 0xCF6D }, +{ 0xCF6E, 0xCF6E, 0xCF6E }, +{ 0xCF6F, 0xCF6F, 0xCF6F }, +{ 0xCF70, 0xCF70, 0xCF70 }, +{ 0xCF71, 0xCF71, 0xCF71 }, +{ 0xCF72, 0xCF72, 0xCF72 }, +{ 0xCF73, 0xCF73, 0xCF73 }, +{ 0xCF74, 0xCF74, 0xCF74 }, +{ 0xCF75, 0xCF75, 0xCF75 }, +{ 0xCF76, 0xCF76, 0xCF76 }, +{ 0xCF77, 0xCF77, 0xCF77 }, +{ 0xCF78, 0xCF78, 0xCF78 }, +{ 0xCF79, 0xCF79, 0xCF79 }, +{ 0xCF7A, 0xCF7A, 0xCF7A }, +{ 0xCF7B, 0xCF7B, 0xCF7B }, +{ 0xCF7C, 0xCF7C, 0xCF7C }, +{ 0xCF7D, 0xCF7D, 0xCF7D }, +{ 0xCF7E, 0xCF7E, 0xCF7E }, +{ 0xCF7F, 0xCF7F, 0xCF7F }, +{ 0xCF80, 0xCF80, 0xCF80 }, +{ 0xCF81, 0xCF81, 0xCF81 }, +{ 0xCF82, 0xCF82, 0xCF82 }, +{ 0xCF83, 0xCF83, 0xCF83 }, +{ 0xCF84, 0xCF84, 0xCF84 }, +{ 0xCF85, 0xCF85, 0xCF85 }, +{ 0xCF86, 0xCF86, 0xCF86 }, +{ 0xCF87, 0xCF87, 0xCF87 }, +{ 0xCF88, 0xCF88, 0xCF88 }, +{ 0xCF89, 0xCF89, 0xCF89 }, +{ 0xCF8A, 0xCF8A, 0xCF8A }, +{ 0xCF8B, 0xCF8B, 0xCF8B }, +{ 0xCF8C, 0xCF8C, 0xCF8C }, +{ 0xCF8D, 0xCF8D, 0xCF8D }, +{ 0xCF8E, 0xCF8E, 0xCF8E }, +{ 0xCF8F, 0xCF8F, 0xCF8F }, +{ 0xCF90, 0xCF90, 0xCF90 }, +{ 0xCF91, 0xCF91, 0xCF91 }, +{ 0xCF92, 0xCF92, 0xCF92 }, +{ 0xCF93, 0xCF93, 0xCF93 }, +{ 0xCF94, 0xCF94, 0xCF94 }, +{ 0xCF95, 0xCF95, 0xCF95 }, +{ 0xCF96, 0xCF96, 0xCF96 }, +{ 0xCF97, 0xCF97, 0xCF97 }, +{ 0xCF98, 0xCF98, 0xCF98 }, +{ 0xCF99, 0xCF99, 0xCF99 }, +{ 0xCF9A, 0xCF9A, 0xCF9A }, +{ 0xCF9B, 0xCF9B, 0xCF9B }, +{ 0xCF9C, 0xCF9C, 0xCF9C }, +{ 0xCF9D, 0xCF9D, 0xCF9D }, +{ 0xCF9E, 0xCF9E, 0xCF9E }, +{ 0xCF9F, 0xCF9F, 0xCF9F }, +{ 0xCFA0, 0xCFA0, 0xCFA0 }, +{ 0xCFA1, 0xCFA1, 0xCFA1 }, +{ 0xCFA2, 0xCFA2, 0xCFA2 }, +{ 0xCFA3, 0xCFA3, 0xCFA3 }, +{ 0xCFA4, 0xCFA4, 0xCFA4 }, +{ 0xCFA5, 0xCFA5, 0xCFA5 }, +{ 0xCFA6, 0xCFA6, 0xCFA6 }, +{ 0xCFA7, 0xCFA7, 0xCFA7 }, +{ 0xCFA8, 0xCFA8, 0xCFA8 }, +{ 0xCFA9, 0xCFA9, 0xCFA9 }, +{ 0xCFAA, 0xCFAA, 0xCFAA }, +{ 0xCFAB, 0xCFAB, 0xCFAB }, +{ 0xCFAC, 0xCFAC, 0xCFAC }, +{ 0xCFAD, 0xCFAD, 0xCFAD }, +{ 0xCFAE, 0xCFAE, 0xCFAE }, +{ 0xCFAF, 0xCFAF, 0xCFAF }, +{ 0xCFB0, 0xCFB0, 0xCFB0 }, +{ 0xCFB1, 0xCFB1, 0xCFB1 }, +{ 0xCFB2, 0xCFB2, 0xCFB2 }, +{ 0xCFB3, 0xCFB3, 0xCFB3 }, +{ 0xCFB4, 0xCFB4, 0xCFB4 }, +{ 0xCFB5, 0xCFB5, 0xCFB5 }, +{ 0xCFB6, 0xCFB6, 0xCFB6 }, +{ 0xCFB7, 0xCFB7, 0xCFB7 }, +{ 0xCFB8, 0xCFB8, 0xCFB8 }, +{ 0xCFB9, 0xCFB9, 0xCFB9 }, +{ 0xCFBA, 0xCFBA, 0xCFBA }, +{ 0xCFBB, 0xCFBB, 0xCFBB }, +{ 0xCFBC, 0xCFBC, 0xCFBC }, +{ 0xCFBD, 0xCFBD, 0xCFBD }, +{ 0xCFBE, 0xCFBE, 0xCFBE }, +{ 0xCFBF, 0xCFBF, 0xCFBF }, +{ 0xCFC0, 0xCFC0, 0xCFC0 }, +{ 0xCFC1, 0xCFC1, 0xCFC1 }, +{ 0xCFC2, 0xCFC2, 0xCFC2 }, +{ 0xCFC3, 0xCFC3, 0xCFC3 }, +{ 0xCFC4, 0xCFC4, 0xCFC4 }, +{ 0xCFC5, 0xCFC5, 0xCFC5 }, +{ 0xCFC6, 0xCFC6, 0xCFC6 }, +{ 0xCFC7, 0xCFC7, 0xCFC7 }, +{ 0xCFC8, 0xCFC8, 0xCFC8 }, +{ 0xCFC9, 0xCFC9, 0xCFC9 }, +{ 0xCFCA, 0xCFCA, 0xCFCA }, +{ 0xCFCB, 0xCFCB, 0xCFCB }, +{ 0xCFCC, 0xCFCC, 0xCFCC }, +{ 0xCFCD, 0xCFCD, 0xCFCD }, +{ 0xCFCE, 0xCFCE, 0xCFCE }, +{ 0xCFCF, 0xCFCF, 0xCFCF }, +{ 0xCFD0, 0xCFD0, 0xCFD0 }, +{ 0xCFD1, 0xCFD1, 0xCFD1 }, +{ 0xCFD2, 0xCFD2, 0xCFD2 }, +{ 0xCFD3, 0xCFD3, 0xCFD3 }, +{ 0xCFD4, 0xCFD4, 0xCFD4 }, +{ 0xCFD5, 0xCFD5, 0xCFD5 }, +{ 0xCFD6, 0xCFD6, 0xCFD6 }, +{ 0xCFD7, 0xCFD7, 0xCFD7 }, +{ 0xCFD8, 0xCFD8, 0xCFD8 }, +{ 0xCFD9, 0xCFD9, 0xCFD9 }, +{ 0xCFDA, 0xCFDA, 0xCFDA }, +{ 0xCFDB, 0xCFDB, 0xCFDB }, +{ 0xCFDC, 0xCFDC, 0xCFDC }, +{ 0xCFDD, 0xCFDD, 0xCFDD }, +{ 0xCFDE, 0xCFDE, 0xCFDE }, +{ 0xCFDF, 0xCFDF, 0xCFDF }, +{ 0xCFE0, 0xCFE0, 0xCFE0 }, +{ 0xCFE1, 0xCFE1, 0xCFE1 }, +{ 0xCFE2, 0xCFE2, 0xCFE2 }, +{ 0xCFE3, 0xCFE3, 0xCFE3 }, +{ 0xCFE4, 0xCFE4, 0xCFE4 }, +{ 0xCFE5, 0xCFE5, 0xCFE5 }, +{ 0xCFE6, 0xCFE6, 0xCFE6 }, +{ 0xCFE7, 0xCFE7, 0xCFE7 }, +{ 0xCFE8, 0xCFE8, 0xCFE8 }, +{ 0xCFE9, 0xCFE9, 0xCFE9 }, +{ 0xCFEA, 0xCFEA, 0xCFEA }, +{ 0xCFEB, 0xCFEB, 0xCFEB }, +{ 0xCFEC, 0xCFEC, 0xCFEC }, +{ 0xCFED, 0xCFED, 0xCFED }, +{ 0xCFEE, 0xCFEE, 0xCFEE }, +{ 0xCFEF, 0xCFEF, 0xCFEF }, +{ 0xCFF0, 0xCFF0, 0xCFF0 }, +{ 0xCFF1, 0xCFF1, 0xCFF1 }, +{ 0xCFF2, 0xCFF2, 0xCFF2 }, +{ 0xCFF3, 0xCFF3, 0xCFF3 }, +{ 0xCFF4, 0xCFF4, 0xCFF4 }, +{ 0xCFF5, 0xCFF5, 0xCFF5 }, +{ 0xCFF6, 0xCFF6, 0xCFF6 }, +{ 0xCFF7, 0xCFF7, 0xCFF7 }, +{ 0xCFF8, 0xCFF8, 0xCFF8 }, +{ 0xCFF9, 0xCFF9, 0xCFF9 }, +{ 0xCFFA, 0xCFFA, 0xCFFA }, +{ 0xCFFB, 0xCFFB, 0xCFFB }, +{ 0xCFFC, 0xCFFC, 0xCFFC }, +{ 0xCFFD, 0xCFFD, 0xCFFD }, +{ 0xCFFE, 0xCFFE, 0xCFFE }, +{ 0xCFFF, 0xCFFF, 0xCFFF }, +{ 0xD000, 0xD000, 0xD000 }, +{ 0xD001, 0xD001, 0xD001 }, +{ 0xD002, 0xD002, 0xD002 }, +{ 0xD003, 0xD003, 0xD003 }, +{ 0xD004, 0xD004, 0xD004 }, +{ 0xD005, 0xD005, 0xD005 }, +{ 0xD006, 0xD006, 0xD006 }, +{ 0xD007, 0xD007, 0xD007 }, +{ 0xD008, 0xD008, 0xD008 }, +{ 0xD009, 0xD009, 0xD009 }, +{ 0xD00A, 0xD00A, 0xD00A }, +{ 0xD00B, 0xD00B, 0xD00B }, +{ 0xD00C, 0xD00C, 0xD00C }, +{ 0xD00D, 0xD00D, 0xD00D }, +{ 0xD00E, 0xD00E, 0xD00E }, +{ 0xD00F, 0xD00F, 0xD00F }, +{ 0xD010, 0xD010, 0xD010 }, +{ 0xD011, 0xD011, 0xD011 }, +{ 0xD012, 0xD012, 0xD012 }, +{ 0xD013, 0xD013, 0xD013 }, +{ 0xD014, 0xD014, 0xD014 }, +{ 0xD015, 0xD015, 0xD015 }, +{ 0xD016, 0xD016, 0xD016 }, +{ 0xD017, 0xD017, 0xD017 }, +{ 0xD018, 0xD018, 0xD018 }, +{ 0xD019, 0xD019, 0xD019 }, +{ 0xD01A, 0xD01A, 0xD01A }, +{ 0xD01B, 0xD01B, 0xD01B }, +{ 0xD01C, 0xD01C, 0xD01C }, +{ 0xD01D, 0xD01D, 0xD01D }, +{ 0xD01E, 0xD01E, 0xD01E }, +{ 0xD01F, 0xD01F, 0xD01F }, +{ 0xD020, 0xD020, 0xD020 }, +{ 0xD021, 0xD021, 0xD021 }, +{ 0xD022, 0xD022, 0xD022 }, +{ 0xD023, 0xD023, 0xD023 }, +{ 0xD024, 0xD024, 0xD024 }, +{ 0xD025, 0xD025, 0xD025 }, +{ 0xD026, 0xD026, 0xD026 }, +{ 0xD027, 0xD027, 0xD027 }, +{ 0xD028, 0xD028, 0xD028 }, +{ 0xD029, 0xD029, 0xD029 }, +{ 0xD02A, 0xD02A, 0xD02A }, +{ 0xD02B, 0xD02B, 0xD02B }, +{ 0xD02C, 0xD02C, 0xD02C }, +{ 0xD02D, 0xD02D, 0xD02D }, +{ 0xD02E, 0xD02E, 0xD02E }, +{ 0xD02F, 0xD02F, 0xD02F }, +{ 0xD030, 0xD030, 0xD030 }, +{ 0xD031, 0xD031, 0xD031 }, +{ 0xD032, 0xD032, 0xD032 }, +{ 0xD033, 0xD033, 0xD033 }, +{ 0xD034, 0xD034, 0xD034 }, +{ 0xD035, 0xD035, 0xD035 }, +{ 0xD036, 0xD036, 0xD036 }, +{ 0xD037, 0xD037, 0xD037 }, +{ 0xD038, 0xD038, 0xD038 }, +{ 0xD039, 0xD039, 0xD039 }, +{ 0xD03A, 0xD03A, 0xD03A }, +{ 0xD03B, 0xD03B, 0xD03B }, +{ 0xD03C, 0xD03C, 0xD03C }, +{ 0xD03D, 0xD03D, 0xD03D }, +{ 0xD03E, 0xD03E, 0xD03E }, +{ 0xD03F, 0xD03F, 0xD03F }, +{ 0xD040, 0xD040, 0xD040 }, +{ 0xD041, 0xD041, 0xD041 }, +{ 0xD042, 0xD042, 0xD042 }, +{ 0xD043, 0xD043, 0xD043 }, +{ 0xD044, 0xD044, 0xD044 }, +{ 0xD045, 0xD045, 0xD045 }, +{ 0xD046, 0xD046, 0xD046 }, +{ 0xD047, 0xD047, 0xD047 }, +{ 0xD048, 0xD048, 0xD048 }, +{ 0xD049, 0xD049, 0xD049 }, +{ 0xD04A, 0xD04A, 0xD04A }, +{ 0xD04B, 0xD04B, 0xD04B }, +{ 0xD04C, 0xD04C, 0xD04C }, +{ 0xD04D, 0xD04D, 0xD04D }, +{ 0xD04E, 0xD04E, 0xD04E }, +{ 0xD04F, 0xD04F, 0xD04F }, +{ 0xD050, 0xD050, 0xD050 }, +{ 0xD051, 0xD051, 0xD051 }, +{ 0xD052, 0xD052, 0xD052 }, +{ 0xD053, 0xD053, 0xD053 }, +{ 0xD054, 0xD054, 0xD054 }, +{ 0xD055, 0xD055, 0xD055 }, +{ 0xD056, 0xD056, 0xD056 }, +{ 0xD057, 0xD057, 0xD057 }, +{ 0xD058, 0xD058, 0xD058 }, +{ 0xD059, 0xD059, 0xD059 }, +{ 0xD05A, 0xD05A, 0xD05A }, +{ 0xD05B, 0xD05B, 0xD05B }, +{ 0xD05C, 0xD05C, 0xD05C }, +{ 0xD05D, 0xD05D, 0xD05D }, +{ 0xD05E, 0xD05E, 0xD05E }, +{ 0xD05F, 0xD05F, 0xD05F }, +{ 0xD060, 0xD060, 0xD060 }, +{ 0xD061, 0xD061, 0xD061 }, +{ 0xD062, 0xD062, 0xD062 }, +{ 0xD063, 0xD063, 0xD063 }, +{ 0xD064, 0xD064, 0xD064 }, +{ 0xD065, 0xD065, 0xD065 }, +{ 0xD066, 0xD066, 0xD066 }, +{ 0xD067, 0xD067, 0xD067 }, +{ 0xD068, 0xD068, 0xD068 }, +{ 0xD069, 0xD069, 0xD069 }, +{ 0xD06A, 0xD06A, 0xD06A }, +{ 0xD06B, 0xD06B, 0xD06B }, +{ 0xD06C, 0xD06C, 0xD06C }, +{ 0xD06D, 0xD06D, 0xD06D }, +{ 0xD06E, 0xD06E, 0xD06E }, +{ 0xD06F, 0xD06F, 0xD06F }, +{ 0xD070, 0xD070, 0xD070 }, +{ 0xD071, 0xD071, 0xD071 }, +{ 0xD072, 0xD072, 0xD072 }, +{ 0xD073, 0xD073, 0xD073 }, +{ 0xD074, 0xD074, 0xD074 }, +{ 0xD075, 0xD075, 0xD075 }, +{ 0xD076, 0xD076, 0xD076 }, +{ 0xD077, 0xD077, 0xD077 }, +{ 0xD078, 0xD078, 0xD078 }, +{ 0xD079, 0xD079, 0xD079 }, +{ 0xD07A, 0xD07A, 0xD07A }, +{ 0xD07B, 0xD07B, 0xD07B }, +{ 0xD07C, 0xD07C, 0xD07C }, +{ 0xD07D, 0xD07D, 0xD07D }, +{ 0xD07E, 0xD07E, 0xD07E }, +{ 0xD07F, 0xD07F, 0xD07F }, +{ 0xD080, 0xD080, 0xD080 }, +{ 0xD081, 0xD081, 0xD081 }, +{ 0xD082, 0xD082, 0xD082 }, +{ 0xD083, 0xD083, 0xD083 }, +{ 0xD084, 0xD084, 0xD084 }, +{ 0xD085, 0xD085, 0xD085 }, +{ 0xD086, 0xD086, 0xD086 }, +{ 0xD087, 0xD087, 0xD087 }, +{ 0xD088, 0xD088, 0xD088 }, +{ 0xD089, 0xD089, 0xD089 }, +{ 0xD08A, 0xD08A, 0xD08A }, +{ 0xD08B, 0xD08B, 0xD08B }, +{ 0xD08C, 0xD08C, 0xD08C }, +{ 0xD08D, 0xD08D, 0xD08D }, +{ 0xD08E, 0xD08E, 0xD08E }, +{ 0xD08F, 0xD08F, 0xD08F }, +{ 0xD090, 0xD090, 0xD090 }, +{ 0xD091, 0xD091, 0xD091 }, +{ 0xD092, 0xD092, 0xD092 }, +{ 0xD093, 0xD093, 0xD093 }, +{ 0xD094, 0xD094, 0xD094 }, +{ 0xD095, 0xD095, 0xD095 }, +{ 0xD096, 0xD096, 0xD096 }, +{ 0xD097, 0xD097, 0xD097 }, +{ 0xD098, 0xD098, 0xD098 }, +{ 0xD099, 0xD099, 0xD099 }, +{ 0xD09A, 0xD09A, 0xD09A }, +{ 0xD09B, 0xD09B, 0xD09B }, +{ 0xD09C, 0xD09C, 0xD09C }, +{ 0xD09D, 0xD09D, 0xD09D }, +{ 0xD09E, 0xD09E, 0xD09E }, +{ 0xD09F, 0xD09F, 0xD09F }, +{ 0xD0A0, 0xD0A0, 0xD0A0 }, +{ 0xD0A1, 0xD0A1, 0xD0A1 }, +{ 0xD0A2, 0xD0A2, 0xD0A2 }, +{ 0xD0A3, 0xD0A3, 0xD0A3 }, +{ 0xD0A4, 0xD0A4, 0xD0A4 }, +{ 0xD0A5, 0xD0A5, 0xD0A5 }, +{ 0xD0A6, 0xD0A6, 0xD0A6 }, +{ 0xD0A7, 0xD0A7, 0xD0A7 }, +{ 0xD0A8, 0xD0A8, 0xD0A8 }, +{ 0xD0A9, 0xD0A9, 0xD0A9 }, +{ 0xD0AA, 0xD0AA, 0xD0AA }, +{ 0xD0AB, 0xD0AB, 0xD0AB }, +{ 0xD0AC, 0xD0AC, 0xD0AC }, +{ 0xD0AD, 0xD0AD, 0xD0AD }, +{ 0xD0AE, 0xD0AE, 0xD0AE }, +{ 0xD0AF, 0xD0AF, 0xD0AF }, +{ 0xD0B0, 0xD0B0, 0xD0B0 }, +{ 0xD0B1, 0xD0B1, 0xD0B1 }, +{ 0xD0B2, 0xD0B2, 0xD0B2 }, +{ 0xD0B3, 0xD0B3, 0xD0B3 }, +{ 0xD0B4, 0xD0B4, 0xD0B4 }, +{ 0xD0B5, 0xD0B5, 0xD0B5 }, +{ 0xD0B6, 0xD0B6, 0xD0B6 }, +{ 0xD0B7, 0xD0B7, 0xD0B7 }, +{ 0xD0B8, 0xD0B8, 0xD0B8 }, +{ 0xD0B9, 0xD0B9, 0xD0B9 }, +{ 0xD0BA, 0xD0BA, 0xD0BA }, +{ 0xD0BB, 0xD0BB, 0xD0BB }, +{ 0xD0BC, 0xD0BC, 0xD0BC }, +{ 0xD0BD, 0xD0BD, 0xD0BD }, +{ 0xD0BE, 0xD0BE, 0xD0BE }, +{ 0xD0BF, 0xD0BF, 0xD0BF }, +{ 0xD0C0, 0xD0C0, 0xD0C0 }, +{ 0xD0C1, 0xD0C1, 0xD0C1 }, +{ 0xD0C2, 0xD0C2, 0xD0C2 }, +{ 0xD0C3, 0xD0C3, 0xD0C3 }, +{ 0xD0C4, 0xD0C4, 0xD0C4 }, +{ 0xD0C5, 0xD0C5, 0xD0C5 }, +{ 0xD0C6, 0xD0C6, 0xD0C6 }, +{ 0xD0C7, 0xD0C7, 0xD0C7 }, +{ 0xD0C8, 0xD0C8, 0xD0C8 }, +{ 0xD0C9, 0xD0C9, 0xD0C9 }, +{ 0xD0CA, 0xD0CA, 0xD0CA }, +{ 0xD0CB, 0xD0CB, 0xD0CB }, +{ 0xD0CC, 0xD0CC, 0xD0CC }, +{ 0xD0CD, 0xD0CD, 0xD0CD }, +{ 0xD0CE, 0xD0CE, 0xD0CE }, +{ 0xD0CF, 0xD0CF, 0xD0CF }, +{ 0xD0D0, 0xD0D0, 0xD0D0 }, +{ 0xD0D1, 0xD0D1, 0xD0D1 }, +{ 0xD0D2, 0xD0D2, 0xD0D2 }, +{ 0xD0D3, 0xD0D3, 0xD0D3 }, +{ 0xD0D4, 0xD0D4, 0xD0D4 }, +{ 0xD0D5, 0xD0D5, 0xD0D5 }, +{ 0xD0D6, 0xD0D6, 0xD0D6 }, +{ 0xD0D7, 0xD0D7, 0xD0D7 }, +{ 0xD0D8, 0xD0D8, 0xD0D8 }, +{ 0xD0D9, 0xD0D9, 0xD0D9 }, +{ 0xD0DA, 0xD0DA, 0xD0DA }, +{ 0xD0DB, 0xD0DB, 0xD0DB }, +{ 0xD0DC, 0xD0DC, 0xD0DC }, +{ 0xD0DD, 0xD0DD, 0xD0DD }, +{ 0xD0DE, 0xD0DE, 0xD0DE }, +{ 0xD0DF, 0xD0DF, 0xD0DF }, +{ 0xD0E0, 0xD0E0, 0xD0E0 }, +{ 0xD0E1, 0xD0E1, 0xD0E1 }, +{ 0xD0E2, 0xD0E2, 0xD0E2 }, +{ 0xD0E3, 0xD0E3, 0xD0E3 }, +{ 0xD0E4, 0xD0E4, 0xD0E4 }, +{ 0xD0E5, 0xD0E5, 0xD0E5 }, +{ 0xD0E6, 0xD0E6, 0xD0E6 }, +{ 0xD0E7, 0xD0E7, 0xD0E7 }, +{ 0xD0E8, 0xD0E8, 0xD0E8 }, +{ 0xD0E9, 0xD0E9, 0xD0E9 }, +{ 0xD0EA, 0xD0EA, 0xD0EA }, +{ 0xD0EB, 0xD0EB, 0xD0EB }, +{ 0xD0EC, 0xD0EC, 0xD0EC }, +{ 0xD0ED, 0xD0ED, 0xD0ED }, +{ 0xD0EE, 0xD0EE, 0xD0EE }, +{ 0xD0EF, 0xD0EF, 0xD0EF }, +{ 0xD0F0, 0xD0F0, 0xD0F0 }, +{ 0xD0F1, 0xD0F1, 0xD0F1 }, +{ 0xD0F2, 0xD0F2, 0xD0F2 }, +{ 0xD0F3, 0xD0F3, 0xD0F3 }, +{ 0xD0F4, 0xD0F4, 0xD0F4 }, +{ 0xD0F5, 0xD0F5, 0xD0F5 }, +{ 0xD0F6, 0xD0F6, 0xD0F6 }, +{ 0xD0F7, 0xD0F7, 0xD0F7 }, +{ 0xD0F8, 0xD0F8, 0xD0F8 }, +{ 0xD0F9, 0xD0F9, 0xD0F9 }, +{ 0xD0FA, 0xD0FA, 0xD0FA }, +{ 0xD0FB, 0xD0FB, 0xD0FB }, +{ 0xD0FC, 0xD0FC, 0xD0FC }, +{ 0xD0FD, 0xD0FD, 0xD0FD }, +{ 0xD0FE, 0xD0FE, 0xD0FE }, +{ 0xD0FF, 0xD0FF, 0xD0FF }, +{ 0xD100, 0xD100, 0xD100 }, +{ 0xD101, 0xD101, 0xD101 }, +{ 0xD102, 0xD102, 0xD102 }, +{ 0xD103, 0xD103, 0xD103 }, +{ 0xD104, 0xD104, 0xD104 }, +{ 0xD105, 0xD105, 0xD105 }, +{ 0xD106, 0xD106, 0xD106 }, +{ 0xD107, 0xD107, 0xD107 }, +{ 0xD108, 0xD108, 0xD108 }, +{ 0xD109, 0xD109, 0xD109 }, +{ 0xD10A, 0xD10A, 0xD10A }, +{ 0xD10B, 0xD10B, 0xD10B }, +{ 0xD10C, 0xD10C, 0xD10C }, +{ 0xD10D, 0xD10D, 0xD10D }, +{ 0xD10E, 0xD10E, 0xD10E }, +{ 0xD10F, 0xD10F, 0xD10F }, +{ 0xD110, 0xD110, 0xD110 }, +{ 0xD111, 0xD111, 0xD111 }, +{ 0xD112, 0xD112, 0xD112 }, +{ 0xD113, 0xD113, 0xD113 }, +{ 0xD114, 0xD114, 0xD114 }, +{ 0xD115, 0xD115, 0xD115 }, +{ 0xD116, 0xD116, 0xD116 }, +{ 0xD117, 0xD117, 0xD117 }, +{ 0xD118, 0xD118, 0xD118 }, +{ 0xD119, 0xD119, 0xD119 }, +{ 0xD11A, 0xD11A, 0xD11A }, +{ 0xD11B, 0xD11B, 0xD11B }, +{ 0xD11C, 0xD11C, 0xD11C }, +{ 0xD11D, 0xD11D, 0xD11D }, +{ 0xD11E, 0xD11E, 0xD11E }, +{ 0xD11F, 0xD11F, 0xD11F }, +{ 0xD120, 0xD120, 0xD120 }, +{ 0xD121, 0xD121, 0xD121 }, +{ 0xD122, 0xD122, 0xD122 }, +{ 0xD123, 0xD123, 0xD123 }, +{ 0xD124, 0xD124, 0xD124 }, +{ 0xD125, 0xD125, 0xD125 }, +{ 0xD126, 0xD126, 0xD126 }, +{ 0xD127, 0xD127, 0xD127 }, +{ 0xD128, 0xD128, 0xD128 }, +{ 0xD129, 0xD129, 0xD129 }, +{ 0xD12A, 0xD12A, 0xD12A }, +{ 0xD12B, 0xD12B, 0xD12B }, +{ 0xD12C, 0xD12C, 0xD12C }, +{ 0xD12D, 0xD12D, 0xD12D }, +{ 0xD12E, 0xD12E, 0xD12E }, +{ 0xD12F, 0xD12F, 0xD12F }, +{ 0xD130, 0xD130, 0xD130 }, +{ 0xD131, 0xD131, 0xD131 }, +{ 0xD132, 0xD132, 0xD132 }, +{ 0xD133, 0xD133, 0xD133 }, +{ 0xD134, 0xD134, 0xD134 }, +{ 0xD135, 0xD135, 0xD135 }, +{ 0xD136, 0xD136, 0xD136 }, +{ 0xD137, 0xD137, 0xD137 }, +{ 0xD138, 0xD138, 0xD138 }, +{ 0xD139, 0xD139, 0xD139 }, +{ 0xD13A, 0xD13A, 0xD13A }, +{ 0xD13B, 0xD13B, 0xD13B }, +{ 0xD13C, 0xD13C, 0xD13C }, +{ 0xD13D, 0xD13D, 0xD13D }, +{ 0xD13E, 0xD13E, 0xD13E }, +{ 0xD13F, 0xD13F, 0xD13F }, +{ 0xD140, 0xD140, 0xD140 }, +{ 0xD141, 0xD141, 0xD141 }, +{ 0xD142, 0xD142, 0xD142 }, +{ 0xD143, 0xD143, 0xD143 }, +{ 0xD144, 0xD144, 0xD144 }, +{ 0xD145, 0xD145, 0xD145 }, +{ 0xD146, 0xD146, 0xD146 }, +{ 0xD147, 0xD147, 0xD147 }, +{ 0xD148, 0xD148, 0xD148 }, +{ 0xD149, 0xD149, 0xD149 }, +{ 0xD14A, 0xD14A, 0xD14A }, +{ 0xD14B, 0xD14B, 0xD14B }, +{ 0xD14C, 0xD14C, 0xD14C }, +{ 0xD14D, 0xD14D, 0xD14D }, +{ 0xD14E, 0xD14E, 0xD14E }, +{ 0xD14F, 0xD14F, 0xD14F }, +{ 0xD150, 0xD150, 0xD150 }, +{ 0xD151, 0xD151, 0xD151 }, +{ 0xD152, 0xD152, 0xD152 }, +{ 0xD153, 0xD153, 0xD153 }, +{ 0xD154, 0xD154, 0xD154 }, +{ 0xD155, 0xD155, 0xD155 }, +{ 0xD156, 0xD156, 0xD156 }, +{ 0xD157, 0xD157, 0xD157 }, +{ 0xD158, 0xD158, 0xD158 }, +{ 0xD159, 0xD159, 0xD159 }, +{ 0xD15A, 0xD15A, 0xD15A }, +{ 0xD15B, 0xD15B, 0xD15B }, +{ 0xD15C, 0xD15C, 0xD15C }, +{ 0xD15D, 0xD15D, 0xD15D }, +{ 0xD15E, 0xD15E, 0xD15E }, +{ 0xD15F, 0xD15F, 0xD15F }, +{ 0xD160, 0xD160, 0xD160 }, +{ 0xD161, 0xD161, 0xD161 }, +{ 0xD162, 0xD162, 0xD162 }, +{ 0xD163, 0xD163, 0xD163 }, +{ 0xD164, 0xD164, 0xD164 }, +{ 0xD165, 0xD165, 0xD165 }, +{ 0xD166, 0xD166, 0xD166 }, +{ 0xD167, 0xD167, 0xD167 }, +{ 0xD168, 0xD168, 0xD168 }, +{ 0xD169, 0xD169, 0xD169 }, +{ 0xD16A, 0xD16A, 0xD16A }, +{ 0xD16B, 0xD16B, 0xD16B }, +{ 0xD16C, 0xD16C, 0xD16C }, +{ 0xD16D, 0xD16D, 0xD16D }, +{ 0xD16E, 0xD16E, 0xD16E }, +{ 0xD16F, 0xD16F, 0xD16F }, +{ 0xD170, 0xD170, 0xD170 }, +{ 0xD171, 0xD171, 0xD171 }, +{ 0xD172, 0xD172, 0xD172 }, +{ 0xD173, 0xD173, 0xD173 }, +{ 0xD174, 0xD174, 0xD174 }, +{ 0xD175, 0xD175, 0xD175 }, +{ 0xD176, 0xD176, 0xD176 }, +{ 0xD177, 0xD177, 0xD177 }, +{ 0xD178, 0xD178, 0xD178 }, +{ 0xD179, 0xD179, 0xD179 }, +{ 0xD17A, 0xD17A, 0xD17A }, +{ 0xD17B, 0xD17B, 0xD17B }, +{ 0xD17C, 0xD17C, 0xD17C }, +{ 0xD17D, 0xD17D, 0xD17D }, +{ 0xD17E, 0xD17E, 0xD17E }, +{ 0xD17F, 0xD17F, 0xD17F }, +{ 0xD180, 0xD180, 0xD180 }, +{ 0xD181, 0xD181, 0xD181 }, +{ 0xD182, 0xD182, 0xD182 }, +{ 0xD183, 0xD183, 0xD183 }, +{ 0xD184, 0xD184, 0xD184 }, +{ 0xD185, 0xD185, 0xD185 }, +{ 0xD186, 0xD186, 0xD186 }, +{ 0xD187, 0xD187, 0xD187 }, +{ 0xD188, 0xD188, 0xD188 }, +{ 0xD189, 0xD189, 0xD189 }, +{ 0xD18A, 0xD18A, 0xD18A }, +{ 0xD18B, 0xD18B, 0xD18B }, +{ 0xD18C, 0xD18C, 0xD18C }, +{ 0xD18D, 0xD18D, 0xD18D }, +{ 0xD18E, 0xD18E, 0xD18E }, +{ 0xD18F, 0xD18F, 0xD18F }, +{ 0xD190, 0xD190, 0xD190 }, +{ 0xD191, 0xD191, 0xD191 }, +{ 0xD192, 0xD192, 0xD192 }, +{ 0xD193, 0xD193, 0xD193 }, +{ 0xD194, 0xD194, 0xD194 }, +{ 0xD195, 0xD195, 0xD195 }, +{ 0xD196, 0xD196, 0xD196 }, +{ 0xD197, 0xD197, 0xD197 }, +{ 0xD198, 0xD198, 0xD198 }, +{ 0xD199, 0xD199, 0xD199 }, +{ 0xD19A, 0xD19A, 0xD19A }, +{ 0xD19B, 0xD19B, 0xD19B }, +{ 0xD19C, 0xD19C, 0xD19C }, +{ 0xD19D, 0xD19D, 0xD19D }, +{ 0xD19E, 0xD19E, 0xD19E }, +{ 0xD19F, 0xD19F, 0xD19F }, +{ 0xD1A0, 0xD1A0, 0xD1A0 }, +{ 0xD1A1, 0xD1A1, 0xD1A1 }, +{ 0xD1A2, 0xD1A2, 0xD1A2 }, +{ 0xD1A3, 0xD1A3, 0xD1A3 }, +{ 0xD1A4, 0xD1A4, 0xD1A4 }, +{ 0xD1A5, 0xD1A5, 0xD1A5 }, +{ 0xD1A6, 0xD1A6, 0xD1A6 }, +{ 0xD1A7, 0xD1A7, 0xD1A7 }, +{ 0xD1A8, 0xD1A8, 0xD1A8 }, +{ 0xD1A9, 0xD1A9, 0xD1A9 }, +{ 0xD1AA, 0xD1AA, 0xD1AA }, +{ 0xD1AB, 0xD1AB, 0xD1AB }, +{ 0xD1AC, 0xD1AC, 0xD1AC }, +{ 0xD1AD, 0xD1AD, 0xD1AD }, +{ 0xD1AE, 0xD1AE, 0xD1AE }, +{ 0xD1AF, 0xD1AF, 0xD1AF }, +{ 0xD1B0, 0xD1B0, 0xD1B0 }, +{ 0xD1B1, 0xD1B1, 0xD1B1 }, +{ 0xD1B2, 0xD1B2, 0xD1B2 }, +{ 0xD1B3, 0xD1B3, 0xD1B3 }, +{ 0xD1B4, 0xD1B4, 0xD1B4 }, +{ 0xD1B5, 0xD1B5, 0xD1B5 }, +{ 0xD1B6, 0xD1B6, 0xD1B6 }, +{ 0xD1B7, 0xD1B7, 0xD1B7 }, +{ 0xD1B8, 0xD1B8, 0xD1B8 }, +{ 0xD1B9, 0xD1B9, 0xD1B9 }, +{ 0xD1BA, 0xD1BA, 0xD1BA }, +{ 0xD1BB, 0xD1BB, 0xD1BB }, +{ 0xD1BC, 0xD1BC, 0xD1BC }, +{ 0xD1BD, 0xD1BD, 0xD1BD }, +{ 0xD1BE, 0xD1BE, 0xD1BE }, +{ 0xD1BF, 0xD1BF, 0xD1BF }, +{ 0xD1C0, 0xD1C0, 0xD1C0 }, +{ 0xD1C1, 0xD1C1, 0xD1C1 }, +{ 0xD1C2, 0xD1C2, 0xD1C2 }, +{ 0xD1C3, 0xD1C3, 0xD1C3 }, +{ 0xD1C4, 0xD1C4, 0xD1C4 }, +{ 0xD1C5, 0xD1C5, 0xD1C5 }, +{ 0xD1C6, 0xD1C6, 0xD1C6 }, +{ 0xD1C7, 0xD1C7, 0xD1C7 }, +{ 0xD1C8, 0xD1C8, 0xD1C8 }, +{ 0xD1C9, 0xD1C9, 0xD1C9 }, +{ 0xD1CA, 0xD1CA, 0xD1CA }, +{ 0xD1CB, 0xD1CB, 0xD1CB }, +{ 0xD1CC, 0xD1CC, 0xD1CC }, +{ 0xD1CD, 0xD1CD, 0xD1CD }, +{ 0xD1CE, 0xD1CE, 0xD1CE }, +{ 0xD1CF, 0xD1CF, 0xD1CF }, +{ 0xD1D0, 0xD1D0, 0xD1D0 }, +{ 0xD1D1, 0xD1D1, 0xD1D1 }, +{ 0xD1D2, 0xD1D2, 0xD1D2 }, +{ 0xD1D3, 0xD1D3, 0xD1D3 }, +{ 0xD1D4, 0xD1D4, 0xD1D4 }, +{ 0xD1D5, 0xD1D5, 0xD1D5 }, +{ 0xD1D6, 0xD1D6, 0xD1D6 }, +{ 0xD1D7, 0xD1D7, 0xD1D7 }, +{ 0xD1D8, 0xD1D8, 0xD1D8 }, +{ 0xD1D9, 0xD1D9, 0xD1D9 }, +{ 0xD1DA, 0xD1DA, 0xD1DA }, +{ 0xD1DB, 0xD1DB, 0xD1DB }, +{ 0xD1DC, 0xD1DC, 0xD1DC }, +{ 0xD1DD, 0xD1DD, 0xD1DD }, +{ 0xD1DE, 0xD1DE, 0xD1DE }, +{ 0xD1DF, 0xD1DF, 0xD1DF }, +{ 0xD1E0, 0xD1E0, 0xD1E0 }, +{ 0xD1E1, 0xD1E1, 0xD1E1 }, +{ 0xD1E2, 0xD1E2, 0xD1E2 }, +{ 0xD1E3, 0xD1E3, 0xD1E3 }, +{ 0xD1E4, 0xD1E4, 0xD1E4 }, +{ 0xD1E5, 0xD1E5, 0xD1E5 }, +{ 0xD1E6, 0xD1E6, 0xD1E6 }, +{ 0xD1E7, 0xD1E7, 0xD1E7 }, +{ 0xD1E8, 0xD1E8, 0xD1E8 }, +{ 0xD1E9, 0xD1E9, 0xD1E9 }, +{ 0xD1EA, 0xD1EA, 0xD1EA }, +{ 0xD1EB, 0xD1EB, 0xD1EB }, +{ 0xD1EC, 0xD1EC, 0xD1EC }, +{ 0xD1ED, 0xD1ED, 0xD1ED }, +{ 0xD1EE, 0xD1EE, 0xD1EE }, +{ 0xD1EF, 0xD1EF, 0xD1EF }, +{ 0xD1F0, 0xD1F0, 0xD1F0 }, +{ 0xD1F1, 0xD1F1, 0xD1F1 }, +{ 0xD1F2, 0xD1F2, 0xD1F2 }, +{ 0xD1F3, 0xD1F3, 0xD1F3 }, +{ 0xD1F4, 0xD1F4, 0xD1F4 }, +{ 0xD1F5, 0xD1F5, 0xD1F5 }, +{ 0xD1F6, 0xD1F6, 0xD1F6 }, +{ 0xD1F7, 0xD1F7, 0xD1F7 }, +{ 0xD1F8, 0xD1F8, 0xD1F8 }, +{ 0xD1F9, 0xD1F9, 0xD1F9 }, +{ 0xD1FA, 0xD1FA, 0xD1FA }, +{ 0xD1FB, 0xD1FB, 0xD1FB }, +{ 0xD1FC, 0xD1FC, 0xD1FC }, +{ 0xD1FD, 0xD1FD, 0xD1FD }, +{ 0xD1FE, 0xD1FE, 0xD1FE }, +{ 0xD1FF, 0xD1FF, 0xD1FF }, +{ 0xD200, 0xD200, 0xD200 }, +{ 0xD201, 0xD201, 0xD201 }, +{ 0xD202, 0xD202, 0xD202 }, +{ 0xD203, 0xD203, 0xD203 }, +{ 0xD204, 0xD204, 0xD204 }, +{ 0xD205, 0xD205, 0xD205 }, +{ 0xD206, 0xD206, 0xD206 }, +{ 0xD207, 0xD207, 0xD207 }, +{ 0xD208, 0xD208, 0xD208 }, +{ 0xD209, 0xD209, 0xD209 }, +{ 0xD20A, 0xD20A, 0xD20A }, +{ 0xD20B, 0xD20B, 0xD20B }, +{ 0xD20C, 0xD20C, 0xD20C }, +{ 0xD20D, 0xD20D, 0xD20D }, +{ 0xD20E, 0xD20E, 0xD20E }, +{ 0xD20F, 0xD20F, 0xD20F }, +{ 0xD210, 0xD210, 0xD210 }, +{ 0xD211, 0xD211, 0xD211 }, +{ 0xD212, 0xD212, 0xD212 }, +{ 0xD213, 0xD213, 0xD213 }, +{ 0xD214, 0xD214, 0xD214 }, +{ 0xD215, 0xD215, 0xD215 }, +{ 0xD216, 0xD216, 0xD216 }, +{ 0xD217, 0xD217, 0xD217 }, +{ 0xD218, 0xD218, 0xD218 }, +{ 0xD219, 0xD219, 0xD219 }, +{ 0xD21A, 0xD21A, 0xD21A }, +{ 0xD21B, 0xD21B, 0xD21B }, +{ 0xD21C, 0xD21C, 0xD21C }, +{ 0xD21D, 0xD21D, 0xD21D }, +{ 0xD21E, 0xD21E, 0xD21E }, +{ 0xD21F, 0xD21F, 0xD21F }, +{ 0xD220, 0xD220, 0xD220 }, +{ 0xD221, 0xD221, 0xD221 }, +{ 0xD222, 0xD222, 0xD222 }, +{ 0xD223, 0xD223, 0xD223 }, +{ 0xD224, 0xD224, 0xD224 }, +{ 0xD225, 0xD225, 0xD225 }, +{ 0xD226, 0xD226, 0xD226 }, +{ 0xD227, 0xD227, 0xD227 }, +{ 0xD228, 0xD228, 0xD228 }, +{ 0xD229, 0xD229, 0xD229 }, +{ 0xD22A, 0xD22A, 0xD22A }, +{ 0xD22B, 0xD22B, 0xD22B }, +{ 0xD22C, 0xD22C, 0xD22C }, +{ 0xD22D, 0xD22D, 0xD22D }, +{ 0xD22E, 0xD22E, 0xD22E }, +{ 0xD22F, 0xD22F, 0xD22F }, +{ 0xD230, 0xD230, 0xD230 }, +{ 0xD231, 0xD231, 0xD231 }, +{ 0xD232, 0xD232, 0xD232 }, +{ 0xD233, 0xD233, 0xD233 }, +{ 0xD234, 0xD234, 0xD234 }, +{ 0xD235, 0xD235, 0xD235 }, +{ 0xD236, 0xD236, 0xD236 }, +{ 0xD237, 0xD237, 0xD237 }, +{ 0xD238, 0xD238, 0xD238 }, +{ 0xD239, 0xD239, 0xD239 }, +{ 0xD23A, 0xD23A, 0xD23A }, +{ 0xD23B, 0xD23B, 0xD23B }, +{ 0xD23C, 0xD23C, 0xD23C }, +{ 0xD23D, 0xD23D, 0xD23D }, +{ 0xD23E, 0xD23E, 0xD23E }, +{ 0xD23F, 0xD23F, 0xD23F }, +{ 0xD240, 0xD240, 0xD240 }, +{ 0xD241, 0xD241, 0xD241 }, +{ 0xD242, 0xD242, 0xD242 }, +{ 0xD243, 0xD243, 0xD243 }, +{ 0xD244, 0xD244, 0xD244 }, +{ 0xD245, 0xD245, 0xD245 }, +{ 0xD246, 0xD246, 0xD246 }, +{ 0xD247, 0xD247, 0xD247 }, +{ 0xD248, 0xD248, 0xD248 }, +{ 0xD249, 0xD249, 0xD249 }, +{ 0xD24A, 0xD24A, 0xD24A }, +{ 0xD24B, 0xD24B, 0xD24B }, +{ 0xD24C, 0xD24C, 0xD24C }, +{ 0xD24D, 0xD24D, 0xD24D }, +{ 0xD24E, 0xD24E, 0xD24E }, +{ 0xD24F, 0xD24F, 0xD24F }, +{ 0xD250, 0xD250, 0xD250 }, +{ 0xD251, 0xD251, 0xD251 }, +{ 0xD252, 0xD252, 0xD252 }, +{ 0xD253, 0xD253, 0xD253 }, +{ 0xD254, 0xD254, 0xD254 }, +{ 0xD255, 0xD255, 0xD255 }, +{ 0xD256, 0xD256, 0xD256 }, +{ 0xD257, 0xD257, 0xD257 }, +{ 0xD258, 0xD258, 0xD258 }, +{ 0xD259, 0xD259, 0xD259 }, +{ 0xD25A, 0xD25A, 0xD25A }, +{ 0xD25B, 0xD25B, 0xD25B }, +{ 0xD25C, 0xD25C, 0xD25C }, +{ 0xD25D, 0xD25D, 0xD25D }, +{ 0xD25E, 0xD25E, 0xD25E }, +{ 0xD25F, 0xD25F, 0xD25F }, +{ 0xD260, 0xD260, 0xD260 }, +{ 0xD261, 0xD261, 0xD261 }, +{ 0xD262, 0xD262, 0xD262 }, +{ 0xD263, 0xD263, 0xD263 }, +{ 0xD264, 0xD264, 0xD264 }, +{ 0xD265, 0xD265, 0xD265 }, +{ 0xD266, 0xD266, 0xD266 }, +{ 0xD267, 0xD267, 0xD267 }, +{ 0xD268, 0xD268, 0xD268 }, +{ 0xD269, 0xD269, 0xD269 }, +{ 0xD26A, 0xD26A, 0xD26A }, +{ 0xD26B, 0xD26B, 0xD26B }, +{ 0xD26C, 0xD26C, 0xD26C }, +{ 0xD26D, 0xD26D, 0xD26D }, +{ 0xD26E, 0xD26E, 0xD26E }, +{ 0xD26F, 0xD26F, 0xD26F }, +{ 0xD270, 0xD270, 0xD270 }, +{ 0xD271, 0xD271, 0xD271 }, +{ 0xD272, 0xD272, 0xD272 }, +{ 0xD273, 0xD273, 0xD273 }, +{ 0xD274, 0xD274, 0xD274 }, +{ 0xD275, 0xD275, 0xD275 }, +{ 0xD276, 0xD276, 0xD276 }, +{ 0xD277, 0xD277, 0xD277 }, +{ 0xD278, 0xD278, 0xD278 }, +{ 0xD279, 0xD279, 0xD279 }, +{ 0xD27A, 0xD27A, 0xD27A }, +{ 0xD27B, 0xD27B, 0xD27B }, +{ 0xD27C, 0xD27C, 0xD27C }, +{ 0xD27D, 0xD27D, 0xD27D }, +{ 0xD27E, 0xD27E, 0xD27E }, +{ 0xD27F, 0xD27F, 0xD27F }, +{ 0xD280, 0xD280, 0xD280 }, +{ 0xD281, 0xD281, 0xD281 }, +{ 0xD282, 0xD282, 0xD282 }, +{ 0xD283, 0xD283, 0xD283 }, +{ 0xD284, 0xD284, 0xD284 }, +{ 0xD285, 0xD285, 0xD285 }, +{ 0xD286, 0xD286, 0xD286 }, +{ 0xD287, 0xD287, 0xD287 }, +{ 0xD288, 0xD288, 0xD288 }, +{ 0xD289, 0xD289, 0xD289 }, +{ 0xD28A, 0xD28A, 0xD28A }, +{ 0xD28B, 0xD28B, 0xD28B }, +{ 0xD28C, 0xD28C, 0xD28C }, +{ 0xD28D, 0xD28D, 0xD28D }, +{ 0xD28E, 0xD28E, 0xD28E }, +{ 0xD28F, 0xD28F, 0xD28F }, +{ 0xD290, 0xD290, 0xD290 }, +{ 0xD291, 0xD291, 0xD291 }, +{ 0xD292, 0xD292, 0xD292 }, +{ 0xD293, 0xD293, 0xD293 }, +{ 0xD294, 0xD294, 0xD294 }, +{ 0xD295, 0xD295, 0xD295 }, +{ 0xD296, 0xD296, 0xD296 }, +{ 0xD297, 0xD297, 0xD297 }, +{ 0xD298, 0xD298, 0xD298 }, +{ 0xD299, 0xD299, 0xD299 }, +{ 0xD29A, 0xD29A, 0xD29A }, +{ 0xD29B, 0xD29B, 0xD29B }, +{ 0xD29C, 0xD29C, 0xD29C }, +{ 0xD29D, 0xD29D, 0xD29D }, +{ 0xD29E, 0xD29E, 0xD29E }, +{ 0xD29F, 0xD29F, 0xD29F }, +{ 0xD2A0, 0xD2A0, 0xD2A0 }, +{ 0xD2A1, 0xD2A1, 0xD2A1 }, +{ 0xD2A2, 0xD2A2, 0xD2A2 }, +{ 0xD2A3, 0xD2A3, 0xD2A3 }, +{ 0xD2A4, 0xD2A4, 0xD2A4 }, +{ 0xD2A5, 0xD2A5, 0xD2A5 }, +{ 0xD2A6, 0xD2A6, 0xD2A6 }, +{ 0xD2A7, 0xD2A7, 0xD2A7 }, +{ 0xD2A8, 0xD2A8, 0xD2A8 }, +{ 0xD2A9, 0xD2A9, 0xD2A9 }, +{ 0xD2AA, 0xD2AA, 0xD2AA }, +{ 0xD2AB, 0xD2AB, 0xD2AB }, +{ 0xD2AC, 0xD2AC, 0xD2AC }, +{ 0xD2AD, 0xD2AD, 0xD2AD }, +{ 0xD2AE, 0xD2AE, 0xD2AE }, +{ 0xD2AF, 0xD2AF, 0xD2AF }, +{ 0xD2B0, 0xD2B0, 0xD2B0 }, +{ 0xD2B1, 0xD2B1, 0xD2B1 }, +{ 0xD2B2, 0xD2B2, 0xD2B2 }, +{ 0xD2B3, 0xD2B3, 0xD2B3 }, +{ 0xD2B4, 0xD2B4, 0xD2B4 }, +{ 0xD2B5, 0xD2B5, 0xD2B5 }, +{ 0xD2B6, 0xD2B6, 0xD2B6 }, +{ 0xD2B7, 0xD2B7, 0xD2B7 }, +{ 0xD2B8, 0xD2B8, 0xD2B8 }, +{ 0xD2B9, 0xD2B9, 0xD2B9 }, +{ 0xD2BA, 0xD2BA, 0xD2BA }, +{ 0xD2BB, 0xD2BB, 0xD2BB }, +{ 0xD2BC, 0xD2BC, 0xD2BC }, +{ 0xD2BD, 0xD2BD, 0xD2BD }, +{ 0xD2BE, 0xD2BE, 0xD2BE }, +{ 0xD2BF, 0xD2BF, 0xD2BF }, +{ 0xD2C0, 0xD2C0, 0xD2C0 }, +{ 0xD2C1, 0xD2C1, 0xD2C1 }, +{ 0xD2C2, 0xD2C2, 0xD2C2 }, +{ 0xD2C3, 0xD2C3, 0xD2C3 }, +{ 0xD2C4, 0xD2C4, 0xD2C4 }, +{ 0xD2C5, 0xD2C5, 0xD2C5 }, +{ 0xD2C6, 0xD2C6, 0xD2C6 }, +{ 0xD2C7, 0xD2C7, 0xD2C7 }, +{ 0xD2C8, 0xD2C8, 0xD2C8 }, +{ 0xD2C9, 0xD2C9, 0xD2C9 }, +{ 0xD2CA, 0xD2CA, 0xD2CA }, +{ 0xD2CB, 0xD2CB, 0xD2CB }, +{ 0xD2CC, 0xD2CC, 0xD2CC }, +{ 0xD2CD, 0xD2CD, 0xD2CD }, +{ 0xD2CE, 0xD2CE, 0xD2CE }, +{ 0xD2CF, 0xD2CF, 0xD2CF }, +{ 0xD2D0, 0xD2D0, 0xD2D0 }, +{ 0xD2D1, 0xD2D1, 0xD2D1 }, +{ 0xD2D2, 0xD2D2, 0xD2D2 }, +{ 0xD2D3, 0xD2D3, 0xD2D3 }, +{ 0xD2D4, 0xD2D4, 0xD2D4 }, +{ 0xD2D5, 0xD2D5, 0xD2D5 }, +{ 0xD2D6, 0xD2D6, 0xD2D6 }, +{ 0xD2D7, 0xD2D7, 0xD2D7 }, +{ 0xD2D8, 0xD2D8, 0xD2D8 }, +{ 0xD2D9, 0xD2D9, 0xD2D9 }, +{ 0xD2DA, 0xD2DA, 0xD2DA }, +{ 0xD2DB, 0xD2DB, 0xD2DB }, +{ 0xD2DC, 0xD2DC, 0xD2DC }, +{ 0xD2DD, 0xD2DD, 0xD2DD }, +{ 0xD2DE, 0xD2DE, 0xD2DE }, +{ 0xD2DF, 0xD2DF, 0xD2DF }, +{ 0xD2E0, 0xD2E0, 0xD2E0 }, +{ 0xD2E1, 0xD2E1, 0xD2E1 }, +{ 0xD2E2, 0xD2E2, 0xD2E2 }, +{ 0xD2E3, 0xD2E3, 0xD2E3 }, +{ 0xD2E4, 0xD2E4, 0xD2E4 }, +{ 0xD2E5, 0xD2E5, 0xD2E5 }, +{ 0xD2E6, 0xD2E6, 0xD2E6 }, +{ 0xD2E7, 0xD2E7, 0xD2E7 }, +{ 0xD2E8, 0xD2E8, 0xD2E8 }, +{ 0xD2E9, 0xD2E9, 0xD2E9 }, +{ 0xD2EA, 0xD2EA, 0xD2EA }, +{ 0xD2EB, 0xD2EB, 0xD2EB }, +{ 0xD2EC, 0xD2EC, 0xD2EC }, +{ 0xD2ED, 0xD2ED, 0xD2ED }, +{ 0xD2EE, 0xD2EE, 0xD2EE }, +{ 0xD2EF, 0xD2EF, 0xD2EF }, +{ 0xD2F0, 0xD2F0, 0xD2F0 }, +{ 0xD2F1, 0xD2F1, 0xD2F1 }, +{ 0xD2F2, 0xD2F2, 0xD2F2 }, +{ 0xD2F3, 0xD2F3, 0xD2F3 }, +{ 0xD2F4, 0xD2F4, 0xD2F4 }, +{ 0xD2F5, 0xD2F5, 0xD2F5 }, +{ 0xD2F6, 0xD2F6, 0xD2F6 }, +{ 0xD2F7, 0xD2F7, 0xD2F7 }, +{ 0xD2F8, 0xD2F8, 0xD2F8 }, +{ 0xD2F9, 0xD2F9, 0xD2F9 }, +{ 0xD2FA, 0xD2FA, 0xD2FA }, +{ 0xD2FB, 0xD2FB, 0xD2FB }, +{ 0xD2FC, 0xD2FC, 0xD2FC }, +{ 0xD2FD, 0xD2FD, 0xD2FD }, +{ 0xD2FE, 0xD2FE, 0xD2FE }, +{ 0xD2FF, 0xD2FF, 0xD2FF }, +{ 0xD300, 0xD300, 0xD300 }, +{ 0xD301, 0xD301, 0xD301 }, +{ 0xD302, 0xD302, 0xD302 }, +{ 0xD303, 0xD303, 0xD303 }, +{ 0xD304, 0xD304, 0xD304 }, +{ 0xD305, 0xD305, 0xD305 }, +{ 0xD306, 0xD306, 0xD306 }, +{ 0xD307, 0xD307, 0xD307 }, +{ 0xD308, 0xD308, 0xD308 }, +{ 0xD309, 0xD309, 0xD309 }, +{ 0xD30A, 0xD30A, 0xD30A }, +{ 0xD30B, 0xD30B, 0xD30B }, +{ 0xD30C, 0xD30C, 0xD30C }, +{ 0xD30D, 0xD30D, 0xD30D }, +{ 0xD30E, 0xD30E, 0xD30E }, +{ 0xD30F, 0xD30F, 0xD30F }, +{ 0xD310, 0xD310, 0xD310 }, +{ 0xD311, 0xD311, 0xD311 }, +{ 0xD312, 0xD312, 0xD312 }, +{ 0xD313, 0xD313, 0xD313 }, +{ 0xD314, 0xD314, 0xD314 }, +{ 0xD315, 0xD315, 0xD315 }, +{ 0xD316, 0xD316, 0xD316 }, +{ 0xD317, 0xD317, 0xD317 }, +{ 0xD318, 0xD318, 0xD318 }, +{ 0xD319, 0xD319, 0xD319 }, +{ 0xD31A, 0xD31A, 0xD31A }, +{ 0xD31B, 0xD31B, 0xD31B }, +{ 0xD31C, 0xD31C, 0xD31C }, +{ 0xD31D, 0xD31D, 0xD31D }, +{ 0xD31E, 0xD31E, 0xD31E }, +{ 0xD31F, 0xD31F, 0xD31F }, +{ 0xD320, 0xD320, 0xD320 }, +{ 0xD321, 0xD321, 0xD321 }, +{ 0xD322, 0xD322, 0xD322 }, +{ 0xD323, 0xD323, 0xD323 }, +{ 0xD324, 0xD324, 0xD324 }, +{ 0xD325, 0xD325, 0xD325 }, +{ 0xD326, 0xD326, 0xD326 }, +{ 0xD327, 0xD327, 0xD327 }, +{ 0xD328, 0xD328, 0xD328 }, +{ 0xD329, 0xD329, 0xD329 }, +{ 0xD32A, 0xD32A, 0xD32A }, +{ 0xD32B, 0xD32B, 0xD32B }, +{ 0xD32C, 0xD32C, 0xD32C }, +{ 0xD32D, 0xD32D, 0xD32D }, +{ 0xD32E, 0xD32E, 0xD32E }, +{ 0xD32F, 0xD32F, 0xD32F }, +{ 0xD330, 0xD330, 0xD330 }, +{ 0xD331, 0xD331, 0xD331 }, +{ 0xD332, 0xD332, 0xD332 }, +{ 0xD333, 0xD333, 0xD333 }, +{ 0xD334, 0xD334, 0xD334 }, +{ 0xD335, 0xD335, 0xD335 }, +{ 0xD336, 0xD336, 0xD336 }, +{ 0xD337, 0xD337, 0xD337 }, +{ 0xD338, 0xD338, 0xD338 }, +{ 0xD339, 0xD339, 0xD339 }, +{ 0xD33A, 0xD33A, 0xD33A }, +{ 0xD33B, 0xD33B, 0xD33B }, +{ 0xD33C, 0xD33C, 0xD33C }, +{ 0xD33D, 0xD33D, 0xD33D }, +{ 0xD33E, 0xD33E, 0xD33E }, +{ 0xD33F, 0xD33F, 0xD33F }, +{ 0xD340, 0xD340, 0xD340 }, +{ 0xD341, 0xD341, 0xD341 }, +{ 0xD342, 0xD342, 0xD342 }, +{ 0xD343, 0xD343, 0xD343 }, +{ 0xD344, 0xD344, 0xD344 }, +{ 0xD345, 0xD345, 0xD345 }, +{ 0xD346, 0xD346, 0xD346 }, +{ 0xD347, 0xD347, 0xD347 }, +{ 0xD348, 0xD348, 0xD348 }, +{ 0xD349, 0xD349, 0xD349 }, +{ 0xD34A, 0xD34A, 0xD34A }, +{ 0xD34B, 0xD34B, 0xD34B }, +{ 0xD34C, 0xD34C, 0xD34C }, +{ 0xD34D, 0xD34D, 0xD34D }, +{ 0xD34E, 0xD34E, 0xD34E }, +{ 0xD34F, 0xD34F, 0xD34F }, +{ 0xD350, 0xD350, 0xD350 }, +{ 0xD351, 0xD351, 0xD351 }, +{ 0xD352, 0xD352, 0xD352 }, +{ 0xD353, 0xD353, 0xD353 }, +{ 0xD354, 0xD354, 0xD354 }, +{ 0xD355, 0xD355, 0xD355 }, +{ 0xD356, 0xD356, 0xD356 }, +{ 0xD357, 0xD357, 0xD357 }, +{ 0xD358, 0xD358, 0xD358 }, +{ 0xD359, 0xD359, 0xD359 }, +{ 0xD35A, 0xD35A, 0xD35A }, +{ 0xD35B, 0xD35B, 0xD35B }, +{ 0xD35C, 0xD35C, 0xD35C }, +{ 0xD35D, 0xD35D, 0xD35D }, +{ 0xD35E, 0xD35E, 0xD35E }, +{ 0xD35F, 0xD35F, 0xD35F }, +{ 0xD360, 0xD360, 0xD360 }, +{ 0xD361, 0xD361, 0xD361 }, +{ 0xD362, 0xD362, 0xD362 }, +{ 0xD363, 0xD363, 0xD363 }, +{ 0xD364, 0xD364, 0xD364 }, +{ 0xD365, 0xD365, 0xD365 }, +{ 0xD366, 0xD366, 0xD366 }, +{ 0xD367, 0xD367, 0xD367 }, +{ 0xD368, 0xD368, 0xD368 }, +{ 0xD369, 0xD369, 0xD369 }, +{ 0xD36A, 0xD36A, 0xD36A }, +{ 0xD36B, 0xD36B, 0xD36B }, +{ 0xD36C, 0xD36C, 0xD36C }, +{ 0xD36D, 0xD36D, 0xD36D }, +{ 0xD36E, 0xD36E, 0xD36E }, +{ 0xD36F, 0xD36F, 0xD36F }, +{ 0xD370, 0xD370, 0xD370 }, +{ 0xD371, 0xD371, 0xD371 }, +{ 0xD372, 0xD372, 0xD372 }, +{ 0xD373, 0xD373, 0xD373 }, +{ 0xD374, 0xD374, 0xD374 }, +{ 0xD375, 0xD375, 0xD375 }, +{ 0xD376, 0xD376, 0xD376 }, +{ 0xD377, 0xD377, 0xD377 }, +{ 0xD378, 0xD378, 0xD378 }, +{ 0xD379, 0xD379, 0xD379 }, +{ 0xD37A, 0xD37A, 0xD37A }, +{ 0xD37B, 0xD37B, 0xD37B }, +{ 0xD37C, 0xD37C, 0xD37C }, +{ 0xD37D, 0xD37D, 0xD37D }, +{ 0xD37E, 0xD37E, 0xD37E }, +{ 0xD37F, 0xD37F, 0xD37F }, +{ 0xD380, 0xD380, 0xD380 }, +{ 0xD381, 0xD381, 0xD381 }, +{ 0xD382, 0xD382, 0xD382 }, +{ 0xD383, 0xD383, 0xD383 }, +{ 0xD384, 0xD384, 0xD384 }, +{ 0xD385, 0xD385, 0xD385 }, +{ 0xD386, 0xD386, 0xD386 }, +{ 0xD387, 0xD387, 0xD387 }, +{ 0xD388, 0xD388, 0xD388 }, +{ 0xD389, 0xD389, 0xD389 }, +{ 0xD38A, 0xD38A, 0xD38A }, +{ 0xD38B, 0xD38B, 0xD38B }, +{ 0xD38C, 0xD38C, 0xD38C }, +{ 0xD38D, 0xD38D, 0xD38D }, +{ 0xD38E, 0xD38E, 0xD38E }, +{ 0xD38F, 0xD38F, 0xD38F }, +{ 0xD390, 0xD390, 0xD390 }, +{ 0xD391, 0xD391, 0xD391 }, +{ 0xD392, 0xD392, 0xD392 }, +{ 0xD393, 0xD393, 0xD393 }, +{ 0xD394, 0xD394, 0xD394 }, +{ 0xD395, 0xD395, 0xD395 }, +{ 0xD396, 0xD396, 0xD396 }, +{ 0xD397, 0xD397, 0xD397 }, +{ 0xD398, 0xD398, 0xD398 }, +{ 0xD399, 0xD399, 0xD399 }, +{ 0xD39A, 0xD39A, 0xD39A }, +{ 0xD39B, 0xD39B, 0xD39B }, +{ 0xD39C, 0xD39C, 0xD39C }, +{ 0xD39D, 0xD39D, 0xD39D }, +{ 0xD39E, 0xD39E, 0xD39E }, +{ 0xD39F, 0xD39F, 0xD39F }, +{ 0xD3A0, 0xD3A0, 0xD3A0 }, +{ 0xD3A1, 0xD3A1, 0xD3A1 }, +{ 0xD3A2, 0xD3A2, 0xD3A2 }, +{ 0xD3A3, 0xD3A3, 0xD3A3 }, +{ 0xD3A4, 0xD3A4, 0xD3A4 }, +{ 0xD3A5, 0xD3A5, 0xD3A5 }, +{ 0xD3A6, 0xD3A6, 0xD3A6 }, +{ 0xD3A7, 0xD3A7, 0xD3A7 }, +{ 0xD3A8, 0xD3A8, 0xD3A8 }, +{ 0xD3A9, 0xD3A9, 0xD3A9 }, +{ 0xD3AA, 0xD3AA, 0xD3AA }, +{ 0xD3AB, 0xD3AB, 0xD3AB }, +{ 0xD3AC, 0xD3AC, 0xD3AC }, +{ 0xD3AD, 0xD3AD, 0xD3AD }, +{ 0xD3AE, 0xD3AE, 0xD3AE }, +{ 0xD3AF, 0xD3AF, 0xD3AF }, +{ 0xD3B0, 0xD3B0, 0xD3B0 }, +{ 0xD3B1, 0xD3B1, 0xD3B1 }, +{ 0xD3B2, 0xD3B2, 0xD3B2 }, +{ 0xD3B3, 0xD3B3, 0xD3B3 }, +{ 0xD3B4, 0xD3B4, 0xD3B4 }, +{ 0xD3B5, 0xD3B5, 0xD3B5 }, +{ 0xD3B6, 0xD3B6, 0xD3B6 }, +{ 0xD3B7, 0xD3B7, 0xD3B7 }, +{ 0xD3B8, 0xD3B8, 0xD3B8 }, +{ 0xD3B9, 0xD3B9, 0xD3B9 }, +{ 0xD3BA, 0xD3BA, 0xD3BA }, +{ 0xD3BB, 0xD3BB, 0xD3BB }, +{ 0xD3BC, 0xD3BC, 0xD3BC }, +{ 0xD3BD, 0xD3BD, 0xD3BD }, +{ 0xD3BE, 0xD3BE, 0xD3BE }, +{ 0xD3BF, 0xD3BF, 0xD3BF }, +{ 0xD3C0, 0xD3C0, 0xD3C0 }, +{ 0xD3C1, 0xD3C1, 0xD3C1 }, +{ 0xD3C2, 0xD3C2, 0xD3C2 }, +{ 0xD3C3, 0xD3C3, 0xD3C3 }, +{ 0xD3C4, 0xD3C4, 0xD3C4 }, +{ 0xD3C5, 0xD3C5, 0xD3C5 }, +{ 0xD3C6, 0xD3C6, 0xD3C6 }, +{ 0xD3C7, 0xD3C7, 0xD3C7 }, +{ 0xD3C8, 0xD3C8, 0xD3C8 }, +{ 0xD3C9, 0xD3C9, 0xD3C9 }, +{ 0xD3CA, 0xD3CA, 0xD3CA }, +{ 0xD3CB, 0xD3CB, 0xD3CB }, +{ 0xD3CC, 0xD3CC, 0xD3CC }, +{ 0xD3CD, 0xD3CD, 0xD3CD }, +{ 0xD3CE, 0xD3CE, 0xD3CE }, +{ 0xD3CF, 0xD3CF, 0xD3CF }, +{ 0xD3D0, 0xD3D0, 0xD3D0 }, +{ 0xD3D1, 0xD3D1, 0xD3D1 }, +{ 0xD3D2, 0xD3D2, 0xD3D2 }, +{ 0xD3D3, 0xD3D3, 0xD3D3 }, +{ 0xD3D4, 0xD3D4, 0xD3D4 }, +{ 0xD3D5, 0xD3D5, 0xD3D5 }, +{ 0xD3D6, 0xD3D6, 0xD3D6 }, +{ 0xD3D7, 0xD3D7, 0xD3D7 }, +{ 0xD3D8, 0xD3D8, 0xD3D8 }, +{ 0xD3D9, 0xD3D9, 0xD3D9 }, +{ 0xD3DA, 0xD3DA, 0xD3DA }, +{ 0xD3DB, 0xD3DB, 0xD3DB }, +{ 0xD3DC, 0xD3DC, 0xD3DC }, +{ 0xD3DD, 0xD3DD, 0xD3DD }, +{ 0xD3DE, 0xD3DE, 0xD3DE }, +{ 0xD3DF, 0xD3DF, 0xD3DF }, +{ 0xD3E0, 0xD3E0, 0xD3E0 }, +{ 0xD3E1, 0xD3E1, 0xD3E1 }, +{ 0xD3E2, 0xD3E2, 0xD3E2 }, +{ 0xD3E3, 0xD3E3, 0xD3E3 }, +{ 0xD3E4, 0xD3E4, 0xD3E4 }, +{ 0xD3E5, 0xD3E5, 0xD3E5 }, +{ 0xD3E6, 0xD3E6, 0xD3E6 }, +{ 0xD3E7, 0xD3E7, 0xD3E7 }, +{ 0xD3E8, 0xD3E8, 0xD3E8 }, +{ 0xD3E9, 0xD3E9, 0xD3E9 }, +{ 0xD3EA, 0xD3EA, 0xD3EA }, +{ 0xD3EB, 0xD3EB, 0xD3EB }, +{ 0xD3EC, 0xD3EC, 0xD3EC }, +{ 0xD3ED, 0xD3ED, 0xD3ED }, +{ 0xD3EE, 0xD3EE, 0xD3EE }, +{ 0xD3EF, 0xD3EF, 0xD3EF }, +{ 0xD3F0, 0xD3F0, 0xD3F0 }, +{ 0xD3F1, 0xD3F1, 0xD3F1 }, +{ 0xD3F2, 0xD3F2, 0xD3F2 }, +{ 0xD3F3, 0xD3F3, 0xD3F3 }, +{ 0xD3F4, 0xD3F4, 0xD3F4 }, +{ 0xD3F5, 0xD3F5, 0xD3F5 }, +{ 0xD3F6, 0xD3F6, 0xD3F6 }, +{ 0xD3F7, 0xD3F7, 0xD3F7 }, +{ 0xD3F8, 0xD3F8, 0xD3F8 }, +{ 0xD3F9, 0xD3F9, 0xD3F9 }, +{ 0xD3FA, 0xD3FA, 0xD3FA }, +{ 0xD3FB, 0xD3FB, 0xD3FB }, +{ 0xD3FC, 0xD3FC, 0xD3FC }, +{ 0xD3FD, 0xD3FD, 0xD3FD }, +{ 0xD3FE, 0xD3FE, 0xD3FE }, +{ 0xD3FF, 0xD3FF, 0xD3FF }, +{ 0xD400, 0xD400, 0xD400 }, +{ 0xD401, 0xD401, 0xD401 }, +{ 0xD402, 0xD402, 0xD402 }, +{ 0xD403, 0xD403, 0xD403 }, +{ 0xD404, 0xD404, 0xD404 }, +{ 0xD405, 0xD405, 0xD405 }, +{ 0xD406, 0xD406, 0xD406 }, +{ 0xD407, 0xD407, 0xD407 }, +{ 0xD408, 0xD408, 0xD408 }, +{ 0xD409, 0xD409, 0xD409 }, +{ 0xD40A, 0xD40A, 0xD40A }, +{ 0xD40B, 0xD40B, 0xD40B }, +{ 0xD40C, 0xD40C, 0xD40C }, +{ 0xD40D, 0xD40D, 0xD40D }, +{ 0xD40E, 0xD40E, 0xD40E }, +{ 0xD40F, 0xD40F, 0xD40F }, +{ 0xD410, 0xD410, 0xD410 }, +{ 0xD411, 0xD411, 0xD411 }, +{ 0xD412, 0xD412, 0xD412 }, +{ 0xD413, 0xD413, 0xD413 }, +{ 0xD414, 0xD414, 0xD414 }, +{ 0xD415, 0xD415, 0xD415 }, +{ 0xD416, 0xD416, 0xD416 }, +{ 0xD417, 0xD417, 0xD417 }, +{ 0xD418, 0xD418, 0xD418 }, +{ 0xD419, 0xD419, 0xD419 }, +{ 0xD41A, 0xD41A, 0xD41A }, +{ 0xD41B, 0xD41B, 0xD41B }, +{ 0xD41C, 0xD41C, 0xD41C }, +{ 0xD41D, 0xD41D, 0xD41D }, +{ 0xD41E, 0xD41E, 0xD41E }, +{ 0xD41F, 0xD41F, 0xD41F }, +{ 0xD420, 0xD420, 0xD420 }, +{ 0xD421, 0xD421, 0xD421 }, +{ 0xD422, 0xD422, 0xD422 }, +{ 0xD423, 0xD423, 0xD423 }, +{ 0xD424, 0xD424, 0xD424 }, +{ 0xD425, 0xD425, 0xD425 }, +{ 0xD426, 0xD426, 0xD426 }, +{ 0xD427, 0xD427, 0xD427 }, +{ 0xD428, 0xD428, 0xD428 }, +{ 0xD429, 0xD429, 0xD429 }, +{ 0xD42A, 0xD42A, 0xD42A }, +{ 0xD42B, 0xD42B, 0xD42B }, +{ 0xD42C, 0xD42C, 0xD42C }, +{ 0xD42D, 0xD42D, 0xD42D }, +{ 0xD42E, 0xD42E, 0xD42E }, +{ 0xD42F, 0xD42F, 0xD42F }, +{ 0xD430, 0xD430, 0xD430 }, +{ 0xD431, 0xD431, 0xD431 }, +{ 0xD432, 0xD432, 0xD432 }, +{ 0xD433, 0xD433, 0xD433 }, +{ 0xD434, 0xD434, 0xD434 }, +{ 0xD435, 0xD435, 0xD435 }, +{ 0xD436, 0xD436, 0xD436 }, +{ 0xD437, 0xD437, 0xD437 }, +{ 0xD438, 0xD438, 0xD438 }, +{ 0xD439, 0xD439, 0xD439 }, +{ 0xD43A, 0xD43A, 0xD43A }, +{ 0xD43B, 0xD43B, 0xD43B }, +{ 0xD43C, 0xD43C, 0xD43C }, +{ 0xD43D, 0xD43D, 0xD43D }, +{ 0xD43E, 0xD43E, 0xD43E }, +{ 0xD43F, 0xD43F, 0xD43F }, +{ 0xD440, 0xD440, 0xD440 }, +{ 0xD441, 0xD441, 0xD441 }, +{ 0xD442, 0xD442, 0xD442 }, +{ 0xD443, 0xD443, 0xD443 }, +{ 0xD444, 0xD444, 0xD444 }, +{ 0xD445, 0xD445, 0xD445 }, +{ 0xD446, 0xD446, 0xD446 }, +{ 0xD447, 0xD447, 0xD447 }, +{ 0xD448, 0xD448, 0xD448 }, +{ 0xD449, 0xD449, 0xD449 }, +{ 0xD44A, 0xD44A, 0xD44A }, +{ 0xD44B, 0xD44B, 0xD44B }, +{ 0xD44C, 0xD44C, 0xD44C }, +{ 0xD44D, 0xD44D, 0xD44D }, +{ 0xD44E, 0xD44E, 0xD44E }, +{ 0xD44F, 0xD44F, 0xD44F }, +{ 0xD450, 0xD450, 0xD450 }, +{ 0xD451, 0xD451, 0xD451 }, +{ 0xD452, 0xD452, 0xD452 }, +{ 0xD453, 0xD453, 0xD453 }, +{ 0xD454, 0xD454, 0xD454 }, +{ 0xD455, 0xD455, 0xD455 }, +{ 0xD456, 0xD456, 0xD456 }, +{ 0xD457, 0xD457, 0xD457 }, +{ 0xD458, 0xD458, 0xD458 }, +{ 0xD459, 0xD459, 0xD459 }, +{ 0xD45A, 0xD45A, 0xD45A }, +{ 0xD45B, 0xD45B, 0xD45B }, +{ 0xD45C, 0xD45C, 0xD45C }, +{ 0xD45D, 0xD45D, 0xD45D }, +{ 0xD45E, 0xD45E, 0xD45E }, +{ 0xD45F, 0xD45F, 0xD45F }, +{ 0xD460, 0xD460, 0xD460 }, +{ 0xD461, 0xD461, 0xD461 }, +{ 0xD462, 0xD462, 0xD462 }, +{ 0xD463, 0xD463, 0xD463 }, +{ 0xD464, 0xD464, 0xD464 }, +{ 0xD465, 0xD465, 0xD465 }, +{ 0xD466, 0xD466, 0xD466 }, +{ 0xD467, 0xD467, 0xD467 }, +{ 0xD468, 0xD468, 0xD468 }, +{ 0xD469, 0xD469, 0xD469 }, +{ 0xD46A, 0xD46A, 0xD46A }, +{ 0xD46B, 0xD46B, 0xD46B }, +{ 0xD46C, 0xD46C, 0xD46C }, +{ 0xD46D, 0xD46D, 0xD46D }, +{ 0xD46E, 0xD46E, 0xD46E }, +{ 0xD46F, 0xD46F, 0xD46F }, +{ 0xD470, 0xD470, 0xD470 }, +{ 0xD471, 0xD471, 0xD471 }, +{ 0xD472, 0xD472, 0xD472 }, +{ 0xD473, 0xD473, 0xD473 }, +{ 0xD474, 0xD474, 0xD474 }, +{ 0xD475, 0xD475, 0xD475 }, +{ 0xD476, 0xD476, 0xD476 }, +{ 0xD477, 0xD477, 0xD477 }, +{ 0xD478, 0xD478, 0xD478 }, +{ 0xD479, 0xD479, 0xD479 }, +{ 0xD47A, 0xD47A, 0xD47A }, +{ 0xD47B, 0xD47B, 0xD47B }, +{ 0xD47C, 0xD47C, 0xD47C }, +{ 0xD47D, 0xD47D, 0xD47D }, +{ 0xD47E, 0xD47E, 0xD47E }, +{ 0xD47F, 0xD47F, 0xD47F }, +{ 0xD480, 0xD480, 0xD480 }, +{ 0xD481, 0xD481, 0xD481 }, +{ 0xD482, 0xD482, 0xD482 }, +{ 0xD483, 0xD483, 0xD483 }, +{ 0xD484, 0xD484, 0xD484 }, +{ 0xD485, 0xD485, 0xD485 }, +{ 0xD486, 0xD486, 0xD486 }, +{ 0xD487, 0xD487, 0xD487 }, +{ 0xD488, 0xD488, 0xD488 }, +{ 0xD489, 0xD489, 0xD489 }, +{ 0xD48A, 0xD48A, 0xD48A }, +{ 0xD48B, 0xD48B, 0xD48B }, +{ 0xD48C, 0xD48C, 0xD48C }, +{ 0xD48D, 0xD48D, 0xD48D }, +{ 0xD48E, 0xD48E, 0xD48E }, +{ 0xD48F, 0xD48F, 0xD48F }, +{ 0xD490, 0xD490, 0xD490 }, +{ 0xD491, 0xD491, 0xD491 }, +{ 0xD492, 0xD492, 0xD492 }, +{ 0xD493, 0xD493, 0xD493 }, +{ 0xD494, 0xD494, 0xD494 }, +{ 0xD495, 0xD495, 0xD495 }, +{ 0xD496, 0xD496, 0xD496 }, +{ 0xD497, 0xD497, 0xD497 }, +{ 0xD498, 0xD498, 0xD498 }, +{ 0xD499, 0xD499, 0xD499 }, +{ 0xD49A, 0xD49A, 0xD49A }, +{ 0xD49B, 0xD49B, 0xD49B }, +{ 0xD49C, 0xD49C, 0xD49C }, +{ 0xD49D, 0xD49D, 0xD49D }, +{ 0xD49E, 0xD49E, 0xD49E }, +{ 0xD49F, 0xD49F, 0xD49F }, +{ 0xD4A0, 0xD4A0, 0xD4A0 }, +{ 0xD4A1, 0xD4A1, 0xD4A1 }, +{ 0xD4A2, 0xD4A2, 0xD4A2 }, +{ 0xD4A3, 0xD4A3, 0xD4A3 }, +{ 0xD4A4, 0xD4A4, 0xD4A4 }, +{ 0xD4A5, 0xD4A5, 0xD4A5 }, +{ 0xD4A6, 0xD4A6, 0xD4A6 }, +{ 0xD4A7, 0xD4A7, 0xD4A7 }, +{ 0xD4A8, 0xD4A8, 0xD4A8 }, +{ 0xD4A9, 0xD4A9, 0xD4A9 }, +{ 0xD4AA, 0xD4AA, 0xD4AA }, +{ 0xD4AB, 0xD4AB, 0xD4AB }, +{ 0xD4AC, 0xD4AC, 0xD4AC }, +{ 0xD4AD, 0xD4AD, 0xD4AD }, +{ 0xD4AE, 0xD4AE, 0xD4AE }, +{ 0xD4AF, 0xD4AF, 0xD4AF }, +{ 0xD4B0, 0xD4B0, 0xD4B0 }, +{ 0xD4B1, 0xD4B1, 0xD4B1 }, +{ 0xD4B2, 0xD4B2, 0xD4B2 }, +{ 0xD4B3, 0xD4B3, 0xD4B3 }, +{ 0xD4B4, 0xD4B4, 0xD4B4 }, +{ 0xD4B5, 0xD4B5, 0xD4B5 }, +{ 0xD4B6, 0xD4B6, 0xD4B6 }, +{ 0xD4B7, 0xD4B7, 0xD4B7 }, +{ 0xD4B8, 0xD4B8, 0xD4B8 }, +{ 0xD4B9, 0xD4B9, 0xD4B9 }, +{ 0xD4BA, 0xD4BA, 0xD4BA }, +{ 0xD4BB, 0xD4BB, 0xD4BB }, +{ 0xD4BC, 0xD4BC, 0xD4BC }, +{ 0xD4BD, 0xD4BD, 0xD4BD }, +{ 0xD4BE, 0xD4BE, 0xD4BE }, +{ 0xD4BF, 0xD4BF, 0xD4BF }, +{ 0xD4C0, 0xD4C0, 0xD4C0 }, +{ 0xD4C1, 0xD4C1, 0xD4C1 }, +{ 0xD4C2, 0xD4C2, 0xD4C2 }, +{ 0xD4C3, 0xD4C3, 0xD4C3 }, +{ 0xD4C4, 0xD4C4, 0xD4C4 }, +{ 0xD4C5, 0xD4C5, 0xD4C5 }, +{ 0xD4C6, 0xD4C6, 0xD4C6 }, +{ 0xD4C7, 0xD4C7, 0xD4C7 }, +{ 0xD4C8, 0xD4C8, 0xD4C8 }, +{ 0xD4C9, 0xD4C9, 0xD4C9 }, +{ 0xD4CA, 0xD4CA, 0xD4CA }, +{ 0xD4CB, 0xD4CB, 0xD4CB }, +{ 0xD4CC, 0xD4CC, 0xD4CC }, +{ 0xD4CD, 0xD4CD, 0xD4CD }, +{ 0xD4CE, 0xD4CE, 0xD4CE }, +{ 0xD4CF, 0xD4CF, 0xD4CF }, +{ 0xD4D0, 0xD4D0, 0xD4D0 }, +{ 0xD4D1, 0xD4D1, 0xD4D1 }, +{ 0xD4D2, 0xD4D2, 0xD4D2 }, +{ 0xD4D3, 0xD4D3, 0xD4D3 }, +{ 0xD4D4, 0xD4D4, 0xD4D4 }, +{ 0xD4D5, 0xD4D5, 0xD4D5 }, +{ 0xD4D6, 0xD4D6, 0xD4D6 }, +{ 0xD4D7, 0xD4D7, 0xD4D7 }, +{ 0xD4D8, 0xD4D8, 0xD4D8 }, +{ 0xD4D9, 0xD4D9, 0xD4D9 }, +{ 0xD4DA, 0xD4DA, 0xD4DA }, +{ 0xD4DB, 0xD4DB, 0xD4DB }, +{ 0xD4DC, 0xD4DC, 0xD4DC }, +{ 0xD4DD, 0xD4DD, 0xD4DD }, +{ 0xD4DE, 0xD4DE, 0xD4DE }, +{ 0xD4DF, 0xD4DF, 0xD4DF }, +{ 0xD4E0, 0xD4E0, 0xD4E0 }, +{ 0xD4E1, 0xD4E1, 0xD4E1 }, +{ 0xD4E2, 0xD4E2, 0xD4E2 }, +{ 0xD4E3, 0xD4E3, 0xD4E3 }, +{ 0xD4E4, 0xD4E4, 0xD4E4 }, +{ 0xD4E5, 0xD4E5, 0xD4E5 }, +{ 0xD4E6, 0xD4E6, 0xD4E6 }, +{ 0xD4E7, 0xD4E7, 0xD4E7 }, +{ 0xD4E8, 0xD4E8, 0xD4E8 }, +{ 0xD4E9, 0xD4E9, 0xD4E9 }, +{ 0xD4EA, 0xD4EA, 0xD4EA }, +{ 0xD4EB, 0xD4EB, 0xD4EB }, +{ 0xD4EC, 0xD4EC, 0xD4EC }, +{ 0xD4ED, 0xD4ED, 0xD4ED }, +{ 0xD4EE, 0xD4EE, 0xD4EE }, +{ 0xD4EF, 0xD4EF, 0xD4EF }, +{ 0xD4F0, 0xD4F0, 0xD4F0 }, +{ 0xD4F1, 0xD4F1, 0xD4F1 }, +{ 0xD4F2, 0xD4F2, 0xD4F2 }, +{ 0xD4F3, 0xD4F3, 0xD4F3 }, +{ 0xD4F4, 0xD4F4, 0xD4F4 }, +{ 0xD4F5, 0xD4F5, 0xD4F5 }, +{ 0xD4F6, 0xD4F6, 0xD4F6 }, +{ 0xD4F7, 0xD4F7, 0xD4F7 }, +{ 0xD4F8, 0xD4F8, 0xD4F8 }, +{ 0xD4F9, 0xD4F9, 0xD4F9 }, +{ 0xD4FA, 0xD4FA, 0xD4FA }, +{ 0xD4FB, 0xD4FB, 0xD4FB }, +{ 0xD4FC, 0xD4FC, 0xD4FC }, +{ 0xD4FD, 0xD4FD, 0xD4FD }, +{ 0xD4FE, 0xD4FE, 0xD4FE }, +{ 0xD4FF, 0xD4FF, 0xD4FF }, +{ 0xD500, 0xD500, 0xD500 }, +{ 0xD501, 0xD501, 0xD501 }, +{ 0xD502, 0xD502, 0xD502 }, +{ 0xD503, 0xD503, 0xD503 }, +{ 0xD504, 0xD504, 0xD504 }, +{ 0xD505, 0xD505, 0xD505 }, +{ 0xD506, 0xD506, 0xD506 }, +{ 0xD507, 0xD507, 0xD507 }, +{ 0xD508, 0xD508, 0xD508 }, +{ 0xD509, 0xD509, 0xD509 }, +{ 0xD50A, 0xD50A, 0xD50A }, +{ 0xD50B, 0xD50B, 0xD50B }, +{ 0xD50C, 0xD50C, 0xD50C }, +{ 0xD50D, 0xD50D, 0xD50D }, +{ 0xD50E, 0xD50E, 0xD50E }, +{ 0xD50F, 0xD50F, 0xD50F }, +{ 0xD510, 0xD510, 0xD510 }, +{ 0xD511, 0xD511, 0xD511 }, +{ 0xD512, 0xD512, 0xD512 }, +{ 0xD513, 0xD513, 0xD513 }, +{ 0xD514, 0xD514, 0xD514 }, +{ 0xD515, 0xD515, 0xD515 }, +{ 0xD516, 0xD516, 0xD516 }, +{ 0xD517, 0xD517, 0xD517 }, +{ 0xD518, 0xD518, 0xD518 }, +{ 0xD519, 0xD519, 0xD519 }, +{ 0xD51A, 0xD51A, 0xD51A }, +{ 0xD51B, 0xD51B, 0xD51B }, +{ 0xD51C, 0xD51C, 0xD51C }, +{ 0xD51D, 0xD51D, 0xD51D }, +{ 0xD51E, 0xD51E, 0xD51E }, +{ 0xD51F, 0xD51F, 0xD51F }, +{ 0xD520, 0xD520, 0xD520 }, +{ 0xD521, 0xD521, 0xD521 }, +{ 0xD522, 0xD522, 0xD522 }, +{ 0xD523, 0xD523, 0xD523 }, +{ 0xD524, 0xD524, 0xD524 }, +{ 0xD525, 0xD525, 0xD525 }, +{ 0xD526, 0xD526, 0xD526 }, +{ 0xD527, 0xD527, 0xD527 }, +{ 0xD528, 0xD528, 0xD528 }, +{ 0xD529, 0xD529, 0xD529 }, +{ 0xD52A, 0xD52A, 0xD52A }, +{ 0xD52B, 0xD52B, 0xD52B }, +{ 0xD52C, 0xD52C, 0xD52C }, +{ 0xD52D, 0xD52D, 0xD52D }, +{ 0xD52E, 0xD52E, 0xD52E }, +{ 0xD52F, 0xD52F, 0xD52F }, +{ 0xD530, 0xD530, 0xD530 }, +{ 0xD531, 0xD531, 0xD531 }, +{ 0xD532, 0xD532, 0xD532 }, +{ 0xD533, 0xD533, 0xD533 }, +{ 0xD534, 0xD534, 0xD534 }, +{ 0xD535, 0xD535, 0xD535 }, +{ 0xD536, 0xD536, 0xD536 }, +{ 0xD537, 0xD537, 0xD537 }, +{ 0xD538, 0xD538, 0xD538 }, +{ 0xD539, 0xD539, 0xD539 }, +{ 0xD53A, 0xD53A, 0xD53A }, +{ 0xD53B, 0xD53B, 0xD53B }, +{ 0xD53C, 0xD53C, 0xD53C }, +{ 0xD53D, 0xD53D, 0xD53D }, +{ 0xD53E, 0xD53E, 0xD53E }, +{ 0xD53F, 0xD53F, 0xD53F }, +{ 0xD540, 0xD540, 0xD540 }, +{ 0xD541, 0xD541, 0xD541 }, +{ 0xD542, 0xD542, 0xD542 }, +{ 0xD543, 0xD543, 0xD543 }, +{ 0xD544, 0xD544, 0xD544 }, +{ 0xD545, 0xD545, 0xD545 }, +{ 0xD546, 0xD546, 0xD546 }, +{ 0xD547, 0xD547, 0xD547 }, +{ 0xD548, 0xD548, 0xD548 }, +{ 0xD549, 0xD549, 0xD549 }, +{ 0xD54A, 0xD54A, 0xD54A }, +{ 0xD54B, 0xD54B, 0xD54B }, +{ 0xD54C, 0xD54C, 0xD54C }, +{ 0xD54D, 0xD54D, 0xD54D }, +{ 0xD54E, 0xD54E, 0xD54E }, +{ 0xD54F, 0xD54F, 0xD54F }, +{ 0xD550, 0xD550, 0xD550 }, +{ 0xD551, 0xD551, 0xD551 }, +{ 0xD552, 0xD552, 0xD552 }, +{ 0xD553, 0xD553, 0xD553 }, +{ 0xD554, 0xD554, 0xD554 }, +{ 0xD555, 0xD555, 0xD555 }, +{ 0xD556, 0xD556, 0xD556 }, +{ 0xD557, 0xD557, 0xD557 }, +{ 0xD558, 0xD558, 0xD558 }, +{ 0xD559, 0xD559, 0xD559 }, +{ 0xD55A, 0xD55A, 0xD55A }, +{ 0xD55B, 0xD55B, 0xD55B }, +{ 0xD55C, 0xD55C, 0xD55C }, +{ 0xD55D, 0xD55D, 0xD55D }, +{ 0xD55E, 0xD55E, 0xD55E }, +{ 0xD55F, 0xD55F, 0xD55F }, +{ 0xD560, 0xD560, 0xD560 }, +{ 0xD561, 0xD561, 0xD561 }, +{ 0xD562, 0xD562, 0xD562 }, +{ 0xD563, 0xD563, 0xD563 }, +{ 0xD564, 0xD564, 0xD564 }, +{ 0xD565, 0xD565, 0xD565 }, +{ 0xD566, 0xD566, 0xD566 }, +{ 0xD567, 0xD567, 0xD567 }, +{ 0xD568, 0xD568, 0xD568 }, +{ 0xD569, 0xD569, 0xD569 }, +{ 0xD56A, 0xD56A, 0xD56A }, +{ 0xD56B, 0xD56B, 0xD56B }, +{ 0xD56C, 0xD56C, 0xD56C }, +{ 0xD56D, 0xD56D, 0xD56D }, +{ 0xD56E, 0xD56E, 0xD56E }, +{ 0xD56F, 0xD56F, 0xD56F }, +{ 0xD570, 0xD570, 0xD570 }, +{ 0xD571, 0xD571, 0xD571 }, +{ 0xD572, 0xD572, 0xD572 }, +{ 0xD573, 0xD573, 0xD573 }, +{ 0xD574, 0xD574, 0xD574 }, +{ 0xD575, 0xD575, 0xD575 }, +{ 0xD576, 0xD576, 0xD576 }, +{ 0xD577, 0xD577, 0xD577 }, +{ 0xD578, 0xD578, 0xD578 }, +{ 0xD579, 0xD579, 0xD579 }, +{ 0xD57A, 0xD57A, 0xD57A }, +{ 0xD57B, 0xD57B, 0xD57B }, +{ 0xD57C, 0xD57C, 0xD57C }, +{ 0xD57D, 0xD57D, 0xD57D }, +{ 0xD57E, 0xD57E, 0xD57E }, +{ 0xD57F, 0xD57F, 0xD57F }, +{ 0xD580, 0xD580, 0xD580 }, +{ 0xD581, 0xD581, 0xD581 }, +{ 0xD582, 0xD582, 0xD582 }, +{ 0xD583, 0xD583, 0xD583 }, +{ 0xD584, 0xD584, 0xD584 }, +{ 0xD585, 0xD585, 0xD585 }, +{ 0xD586, 0xD586, 0xD586 }, +{ 0xD587, 0xD587, 0xD587 }, +{ 0xD588, 0xD588, 0xD588 }, +{ 0xD589, 0xD589, 0xD589 }, +{ 0xD58A, 0xD58A, 0xD58A }, +{ 0xD58B, 0xD58B, 0xD58B }, +{ 0xD58C, 0xD58C, 0xD58C }, +{ 0xD58D, 0xD58D, 0xD58D }, +{ 0xD58E, 0xD58E, 0xD58E }, +{ 0xD58F, 0xD58F, 0xD58F }, +{ 0xD590, 0xD590, 0xD590 }, +{ 0xD591, 0xD591, 0xD591 }, +{ 0xD592, 0xD592, 0xD592 }, +{ 0xD593, 0xD593, 0xD593 }, +{ 0xD594, 0xD594, 0xD594 }, +{ 0xD595, 0xD595, 0xD595 }, +{ 0xD596, 0xD596, 0xD596 }, +{ 0xD597, 0xD597, 0xD597 }, +{ 0xD598, 0xD598, 0xD598 }, +{ 0xD599, 0xD599, 0xD599 }, +{ 0xD59A, 0xD59A, 0xD59A }, +{ 0xD59B, 0xD59B, 0xD59B }, +{ 0xD59C, 0xD59C, 0xD59C }, +{ 0xD59D, 0xD59D, 0xD59D }, +{ 0xD59E, 0xD59E, 0xD59E }, +{ 0xD59F, 0xD59F, 0xD59F }, +{ 0xD5A0, 0xD5A0, 0xD5A0 }, +{ 0xD5A1, 0xD5A1, 0xD5A1 }, +{ 0xD5A2, 0xD5A2, 0xD5A2 }, +{ 0xD5A3, 0xD5A3, 0xD5A3 }, +{ 0xD5A4, 0xD5A4, 0xD5A4 }, +{ 0xD5A5, 0xD5A5, 0xD5A5 }, +{ 0xD5A6, 0xD5A6, 0xD5A6 }, +{ 0xD5A7, 0xD5A7, 0xD5A7 }, +{ 0xD5A8, 0xD5A8, 0xD5A8 }, +{ 0xD5A9, 0xD5A9, 0xD5A9 }, +{ 0xD5AA, 0xD5AA, 0xD5AA }, +{ 0xD5AB, 0xD5AB, 0xD5AB }, +{ 0xD5AC, 0xD5AC, 0xD5AC }, +{ 0xD5AD, 0xD5AD, 0xD5AD }, +{ 0xD5AE, 0xD5AE, 0xD5AE }, +{ 0xD5AF, 0xD5AF, 0xD5AF }, +{ 0xD5B0, 0xD5B0, 0xD5B0 }, +{ 0xD5B1, 0xD5B1, 0xD5B1 }, +{ 0xD5B2, 0xD5B2, 0xD5B2 }, +{ 0xD5B3, 0xD5B3, 0xD5B3 }, +{ 0xD5B4, 0xD5B4, 0xD5B4 }, +{ 0xD5B5, 0xD5B5, 0xD5B5 }, +{ 0xD5B6, 0xD5B6, 0xD5B6 }, +{ 0xD5B7, 0xD5B7, 0xD5B7 }, +{ 0xD5B8, 0xD5B8, 0xD5B8 }, +{ 0xD5B9, 0xD5B9, 0xD5B9 }, +{ 0xD5BA, 0xD5BA, 0xD5BA }, +{ 0xD5BB, 0xD5BB, 0xD5BB }, +{ 0xD5BC, 0xD5BC, 0xD5BC }, +{ 0xD5BD, 0xD5BD, 0xD5BD }, +{ 0xD5BE, 0xD5BE, 0xD5BE }, +{ 0xD5BF, 0xD5BF, 0xD5BF }, +{ 0xD5C0, 0xD5C0, 0xD5C0 }, +{ 0xD5C1, 0xD5C1, 0xD5C1 }, +{ 0xD5C2, 0xD5C2, 0xD5C2 }, +{ 0xD5C3, 0xD5C3, 0xD5C3 }, +{ 0xD5C4, 0xD5C4, 0xD5C4 }, +{ 0xD5C5, 0xD5C5, 0xD5C5 }, +{ 0xD5C6, 0xD5C6, 0xD5C6 }, +{ 0xD5C7, 0xD5C7, 0xD5C7 }, +{ 0xD5C8, 0xD5C8, 0xD5C8 }, +{ 0xD5C9, 0xD5C9, 0xD5C9 }, +{ 0xD5CA, 0xD5CA, 0xD5CA }, +{ 0xD5CB, 0xD5CB, 0xD5CB }, +{ 0xD5CC, 0xD5CC, 0xD5CC }, +{ 0xD5CD, 0xD5CD, 0xD5CD }, +{ 0xD5CE, 0xD5CE, 0xD5CE }, +{ 0xD5CF, 0xD5CF, 0xD5CF }, +{ 0xD5D0, 0xD5D0, 0xD5D0 }, +{ 0xD5D1, 0xD5D1, 0xD5D1 }, +{ 0xD5D2, 0xD5D2, 0xD5D2 }, +{ 0xD5D3, 0xD5D3, 0xD5D3 }, +{ 0xD5D4, 0xD5D4, 0xD5D4 }, +{ 0xD5D5, 0xD5D5, 0xD5D5 }, +{ 0xD5D6, 0xD5D6, 0xD5D6 }, +{ 0xD5D7, 0xD5D7, 0xD5D7 }, +{ 0xD5D8, 0xD5D8, 0xD5D8 }, +{ 0xD5D9, 0xD5D9, 0xD5D9 }, +{ 0xD5DA, 0xD5DA, 0xD5DA }, +{ 0xD5DB, 0xD5DB, 0xD5DB }, +{ 0xD5DC, 0xD5DC, 0xD5DC }, +{ 0xD5DD, 0xD5DD, 0xD5DD }, +{ 0xD5DE, 0xD5DE, 0xD5DE }, +{ 0xD5DF, 0xD5DF, 0xD5DF }, +{ 0xD5E0, 0xD5E0, 0xD5E0 }, +{ 0xD5E1, 0xD5E1, 0xD5E1 }, +{ 0xD5E2, 0xD5E2, 0xD5E2 }, +{ 0xD5E3, 0xD5E3, 0xD5E3 }, +{ 0xD5E4, 0xD5E4, 0xD5E4 }, +{ 0xD5E5, 0xD5E5, 0xD5E5 }, +{ 0xD5E6, 0xD5E6, 0xD5E6 }, +{ 0xD5E7, 0xD5E7, 0xD5E7 }, +{ 0xD5E8, 0xD5E8, 0xD5E8 }, +{ 0xD5E9, 0xD5E9, 0xD5E9 }, +{ 0xD5EA, 0xD5EA, 0xD5EA }, +{ 0xD5EB, 0xD5EB, 0xD5EB }, +{ 0xD5EC, 0xD5EC, 0xD5EC }, +{ 0xD5ED, 0xD5ED, 0xD5ED }, +{ 0xD5EE, 0xD5EE, 0xD5EE }, +{ 0xD5EF, 0xD5EF, 0xD5EF }, +{ 0xD5F0, 0xD5F0, 0xD5F0 }, +{ 0xD5F1, 0xD5F1, 0xD5F1 }, +{ 0xD5F2, 0xD5F2, 0xD5F2 }, +{ 0xD5F3, 0xD5F3, 0xD5F3 }, +{ 0xD5F4, 0xD5F4, 0xD5F4 }, +{ 0xD5F5, 0xD5F5, 0xD5F5 }, +{ 0xD5F6, 0xD5F6, 0xD5F6 }, +{ 0xD5F7, 0xD5F7, 0xD5F7 }, +{ 0xD5F8, 0xD5F8, 0xD5F8 }, +{ 0xD5F9, 0xD5F9, 0xD5F9 }, +{ 0xD5FA, 0xD5FA, 0xD5FA }, +{ 0xD5FB, 0xD5FB, 0xD5FB }, +{ 0xD5FC, 0xD5FC, 0xD5FC }, +{ 0xD5FD, 0xD5FD, 0xD5FD }, +{ 0xD5FE, 0xD5FE, 0xD5FE }, +{ 0xD5FF, 0xD5FF, 0xD5FF }, +{ 0xD600, 0xD600, 0xD600 }, +{ 0xD601, 0xD601, 0xD601 }, +{ 0xD602, 0xD602, 0xD602 }, +{ 0xD603, 0xD603, 0xD603 }, +{ 0xD604, 0xD604, 0xD604 }, +{ 0xD605, 0xD605, 0xD605 }, +{ 0xD606, 0xD606, 0xD606 }, +{ 0xD607, 0xD607, 0xD607 }, +{ 0xD608, 0xD608, 0xD608 }, +{ 0xD609, 0xD609, 0xD609 }, +{ 0xD60A, 0xD60A, 0xD60A }, +{ 0xD60B, 0xD60B, 0xD60B }, +{ 0xD60C, 0xD60C, 0xD60C }, +{ 0xD60D, 0xD60D, 0xD60D }, +{ 0xD60E, 0xD60E, 0xD60E }, +{ 0xD60F, 0xD60F, 0xD60F }, +{ 0xD610, 0xD610, 0xD610 }, +{ 0xD611, 0xD611, 0xD611 }, +{ 0xD612, 0xD612, 0xD612 }, +{ 0xD613, 0xD613, 0xD613 }, +{ 0xD614, 0xD614, 0xD614 }, +{ 0xD615, 0xD615, 0xD615 }, +{ 0xD616, 0xD616, 0xD616 }, +{ 0xD617, 0xD617, 0xD617 }, +{ 0xD618, 0xD618, 0xD618 }, +{ 0xD619, 0xD619, 0xD619 }, +{ 0xD61A, 0xD61A, 0xD61A }, +{ 0xD61B, 0xD61B, 0xD61B }, +{ 0xD61C, 0xD61C, 0xD61C }, +{ 0xD61D, 0xD61D, 0xD61D }, +{ 0xD61E, 0xD61E, 0xD61E }, +{ 0xD61F, 0xD61F, 0xD61F }, +{ 0xD620, 0xD620, 0xD620 }, +{ 0xD621, 0xD621, 0xD621 }, +{ 0xD622, 0xD622, 0xD622 }, +{ 0xD623, 0xD623, 0xD623 }, +{ 0xD624, 0xD624, 0xD624 }, +{ 0xD625, 0xD625, 0xD625 }, +{ 0xD626, 0xD626, 0xD626 }, +{ 0xD627, 0xD627, 0xD627 }, +{ 0xD628, 0xD628, 0xD628 }, +{ 0xD629, 0xD629, 0xD629 }, +{ 0xD62A, 0xD62A, 0xD62A }, +{ 0xD62B, 0xD62B, 0xD62B }, +{ 0xD62C, 0xD62C, 0xD62C }, +{ 0xD62D, 0xD62D, 0xD62D }, +{ 0xD62E, 0xD62E, 0xD62E }, +{ 0xD62F, 0xD62F, 0xD62F }, +{ 0xD630, 0xD630, 0xD630 }, +{ 0xD631, 0xD631, 0xD631 }, +{ 0xD632, 0xD632, 0xD632 }, +{ 0xD633, 0xD633, 0xD633 }, +{ 0xD634, 0xD634, 0xD634 }, +{ 0xD635, 0xD635, 0xD635 }, +{ 0xD636, 0xD636, 0xD636 }, +{ 0xD637, 0xD637, 0xD637 }, +{ 0xD638, 0xD638, 0xD638 }, +{ 0xD639, 0xD639, 0xD639 }, +{ 0xD63A, 0xD63A, 0xD63A }, +{ 0xD63B, 0xD63B, 0xD63B }, +{ 0xD63C, 0xD63C, 0xD63C }, +{ 0xD63D, 0xD63D, 0xD63D }, +{ 0xD63E, 0xD63E, 0xD63E }, +{ 0xD63F, 0xD63F, 0xD63F }, +{ 0xD640, 0xD640, 0xD640 }, +{ 0xD641, 0xD641, 0xD641 }, +{ 0xD642, 0xD642, 0xD642 }, +{ 0xD643, 0xD643, 0xD643 }, +{ 0xD644, 0xD644, 0xD644 }, +{ 0xD645, 0xD645, 0xD645 }, +{ 0xD646, 0xD646, 0xD646 }, +{ 0xD647, 0xD647, 0xD647 }, +{ 0xD648, 0xD648, 0xD648 }, +{ 0xD649, 0xD649, 0xD649 }, +{ 0xD64A, 0xD64A, 0xD64A }, +{ 0xD64B, 0xD64B, 0xD64B }, +{ 0xD64C, 0xD64C, 0xD64C }, +{ 0xD64D, 0xD64D, 0xD64D }, +{ 0xD64E, 0xD64E, 0xD64E }, +{ 0xD64F, 0xD64F, 0xD64F }, +{ 0xD650, 0xD650, 0xD650 }, +{ 0xD651, 0xD651, 0xD651 }, +{ 0xD652, 0xD652, 0xD652 }, +{ 0xD653, 0xD653, 0xD653 }, +{ 0xD654, 0xD654, 0xD654 }, +{ 0xD655, 0xD655, 0xD655 }, +{ 0xD656, 0xD656, 0xD656 }, +{ 0xD657, 0xD657, 0xD657 }, +{ 0xD658, 0xD658, 0xD658 }, +{ 0xD659, 0xD659, 0xD659 }, +{ 0xD65A, 0xD65A, 0xD65A }, +{ 0xD65B, 0xD65B, 0xD65B }, +{ 0xD65C, 0xD65C, 0xD65C }, +{ 0xD65D, 0xD65D, 0xD65D }, +{ 0xD65E, 0xD65E, 0xD65E }, +{ 0xD65F, 0xD65F, 0xD65F }, +{ 0xD660, 0xD660, 0xD660 }, +{ 0xD661, 0xD661, 0xD661 }, +{ 0xD662, 0xD662, 0xD662 }, +{ 0xD663, 0xD663, 0xD663 }, +{ 0xD664, 0xD664, 0xD664 }, +{ 0xD665, 0xD665, 0xD665 }, +{ 0xD666, 0xD666, 0xD666 }, +{ 0xD667, 0xD667, 0xD667 }, +{ 0xD668, 0xD668, 0xD668 }, +{ 0xD669, 0xD669, 0xD669 }, +{ 0xD66A, 0xD66A, 0xD66A }, +{ 0xD66B, 0xD66B, 0xD66B }, +{ 0xD66C, 0xD66C, 0xD66C }, +{ 0xD66D, 0xD66D, 0xD66D }, +{ 0xD66E, 0xD66E, 0xD66E }, +{ 0xD66F, 0xD66F, 0xD66F }, +{ 0xD670, 0xD670, 0xD670 }, +{ 0xD671, 0xD671, 0xD671 }, +{ 0xD672, 0xD672, 0xD672 }, +{ 0xD673, 0xD673, 0xD673 }, +{ 0xD674, 0xD674, 0xD674 }, +{ 0xD675, 0xD675, 0xD675 }, +{ 0xD676, 0xD676, 0xD676 }, +{ 0xD677, 0xD677, 0xD677 }, +{ 0xD678, 0xD678, 0xD678 }, +{ 0xD679, 0xD679, 0xD679 }, +{ 0xD67A, 0xD67A, 0xD67A }, +{ 0xD67B, 0xD67B, 0xD67B }, +{ 0xD67C, 0xD67C, 0xD67C }, +{ 0xD67D, 0xD67D, 0xD67D }, +{ 0xD67E, 0xD67E, 0xD67E }, +{ 0xD67F, 0xD67F, 0xD67F }, +{ 0xD680, 0xD680, 0xD680 }, +{ 0xD681, 0xD681, 0xD681 }, +{ 0xD682, 0xD682, 0xD682 }, +{ 0xD683, 0xD683, 0xD683 }, +{ 0xD684, 0xD684, 0xD684 }, +{ 0xD685, 0xD685, 0xD685 }, +{ 0xD686, 0xD686, 0xD686 }, +{ 0xD687, 0xD687, 0xD687 }, +{ 0xD688, 0xD688, 0xD688 }, +{ 0xD689, 0xD689, 0xD689 }, +{ 0xD68A, 0xD68A, 0xD68A }, +{ 0xD68B, 0xD68B, 0xD68B }, +{ 0xD68C, 0xD68C, 0xD68C }, +{ 0xD68D, 0xD68D, 0xD68D }, +{ 0xD68E, 0xD68E, 0xD68E }, +{ 0xD68F, 0xD68F, 0xD68F }, +{ 0xD690, 0xD690, 0xD690 }, +{ 0xD691, 0xD691, 0xD691 }, +{ 0xD692, 0xD692, 0xD692 }, +{ 0xD693, 0xD693, 0xD693 }, +{ 0xD694, 0xD694, 0xD694 }, +{ 0xD695, 0xD695, 0xD695 }, +{ 0xD696, 0xD696, 0xD696 }, +{ 0xD697, 0xD697, 0xD697 }, +{ 0xD698, 0xD698, 0xD698 }, +{ 0xD699, 0xD699, 0xD699 }, +{ 0xD69A, 0xD69A, 0xD69A }, +{ 0xD69B, 0xD69B, 0xD69B }, +{ 0xD69C, 0xD69C, 0xD69C }, +{ 0xD69D, 0xD69D, 0xD69D }, +{ 0xD69E, 0xD69E, 0xD69E }, +{ 0xD69F, 0xD69F, 0xD69F }, +{ 0xD6A0, 0xD6A0, 0xD6A0 }, +{ 0xD6A1, 0xD6A1, 0xD6A1 }, +{ 0xD6A2, 0xD6A2, 0xD6A2 }, +{ 0xD6A3, 0xD6A3, 0xD6A3 }, +{ 0xD6A4, 0xD6A4, 0xD6A4 }, +{ 0xD6A5, 0xD6A5, 0xD6A5 }, +{ 0xD6A6, 0xD6A6, 0xD6A6 }, +{ 0xD6A7, 0xD6A7, 0xD6A7 }, +{ 0xD6A8, 0xD6A8, 0xD6A8 }, +{ 0xD6A9, 0xD6A9, 0xD6A9 }, +{ 0xD6AA, 0xD6AA, 0xD6AA }, +{ 0xD6AB, 0xD6AB, 0xD6AB }, +{ 0xD6AC, 0xD6AC, 0xD6AC }, +{ 0xD6AD, 0xD6AD, 0xD6AD }, +{ 0xD6AE, 0xD6AE, 0xD6AE }, +{ 0xD6AF, 0xD6AF, 0xD6AF }, +{ 0xD6B0, 0xD6B0, 0xD6B0 }, +{ 0xD6B1, 0xD6B1, 0xD6B1 }, +{ 0xD6B2, 0xD6B2, 0xD6B2 }, +{ 0xD6B3, 0xD6B3, 0xD6B3 }, +{ 0xD6B4, 0xD6B4, 0xD6B4 }, +{ 0xD6B5, 0xD6B5, 0xD6B5 }, +{ 0xD6B6, 0xD6B6, 0xD6B6 }, +{ 0xD6B7, 0xD6B7, 0xD6B7 }, +{ 0xD6B8, 0xD6B8, 0xD6B8 }, +{ 0xD6B9, 0xD6B9, 0xD6B9 }, +{ 0xD6BA, 0xD6BA, 0xD6BA }, +{ 0xD6BB, 0xD6BB, 0xD6BB }, +{ 0xD6BC, 0xD6BC, 0xD6BC }, +{ 0xD6BD, 0xD6BD, 0xD6BD }, +{ 0xD6BE, 0xD6BE, 0xD6BE }, +{ 0xD6BF, 0xD6BF, 0xD6BF }, +{ 0xD6C0, 0xD6C0, 0xD6C0 }, +{ 0xD6C1, 0xD6C1, 0xD6C1 }, +{ 0xD6C2, 0xD6C2, 0xD6C2 }, +{ 0xD6C3, 0xD6C3, 0xD6C3 }, +{ 0xD6C4, 0xD6C4, 0xD6C4 }, +{ 0xD6C5, 0xD6C5, 0xD6C5 }, +{ 0xD6C6, 0xD6C6, 0xD6C6 }, +{ 0xD6C7, 0xD6C7, 0xD6C7 }, +{ 0xD6C8, 0xD6C8, 0xD6C8 }, +{ 0xD6C9, 0xD6C9, 0xD6C9 }, +{ 0xD6CA, 0xD6CA, 0xD6CA }, +{ 0xD6CB, 0xD6CB, 0xD6CB }, +{ 0xD6CC, 0xD6CC, 0xD6CC }, +{ 0xD6CD, 0xD6CD, 0xD6CD }, +{ 0xD6CE, 0xD6CE, 0xD6CE }, +{ 0xD6CF, 0xD6CF, 0xD6CF }, +{ 0xD6D0, 0xD6D0, 0xD6D0 }, +{ 0xD6D1, 0xD6D1, 0xD6D1 }, +{ 0xD6D2, 0xD6D2, 0xD6D2 }, +{ 0xD6D3, 0xD6D3, 0xD6D3 }, +{ 0xD6D4, 0xD6D4, 0xD6D4 }, +{ 0xD6D5, 0xD6D5, 0xD6D5 }, +{ 0xD6D6, 0xD6D6, 0xD6D6 }, +{ 0xD6D7, 0xD6D7, 0xD6D7 }, +{ 0xD6D8, 0xD6D8, 0xD6D8 }, +{ 0xD6D9, 0xD6D9, 0xD6D9 }, +{ 0xD6DA, 0xD6DA, 0xD6DA }, +{ 0xD6DB, 0xD6DB, 0xD6DB }, +{ 0xD6DC, 0xD6DC, 0xD6DC }, +{ 0xD6DD, 0xD6DD, 0xD6DD }, +{ 0xD6DE, 0xD6DE, 0xD6DE }, +{ 0xD6DF, 0xD6DF, 0xD6DF }, +{ 0xD6E0, 0xD6E0, 0xD6E0 }, +{ 0xD6E1, 0xD6E1, 0xD6E1 }, +{ 0xD6E2, 0xD6E2, 0xD6E2 }, +{ 0xD6E3, 0xD6E3, 0xD6E3 }, +{ 0xD6E4, 0xD6E4, 0xD6E4 }, +{ 0xD6E5, 0xD6E5, 0xD6E5 }, +{ 0xD6E6, 0xD6E6, 0xD6E6 }, +{ 0xD6E7, 0xD6E7, 0xD6E7 }, +{ 0xD6E8, 0xD6E8, 0xD6E8 }, +{ 0xD6E9, 0xD6E9, 0xD6E9 }, +{ 0xD6EA, 0xD6EA, 0xD6EA }, +{ 0xD6EB, 0xD6EB, 0xD6EB }, +{ 0xD6EC, 0xD6EC, 0xD6EC }, +{ 0xD6ED, 0xD6ED, 0xD6ED }, +{ 0xD6EE, 0xD6EE, 0xD6EE }, +{ 0xD6EF, 0xD6EF, 0xD6EF }, +{ 0xD6F0, 0xD6F0, 0xD6F0 }, +{ 0xD6F1, 0xD6F1, 0xD6F1 }, +{ 0xD6F2, 0xD6F2, 0xD6F2 }, +{ 0xD6F3, 0xD6F3, 0xD6F3 }, +{ 0xD6F4, 0xD6F4, 0xD6F4 }, +{ 0xD6F5, 0xD6F5, 0xD6F5 }, +{ 0xD6F6, 0xD6F6, 0xD6F6 }, +{ 0xD6F7, 0xD6F7, 0xD6F7 }, +{ 0xD6F8, 0xD6F8, 0xD6F8 }, +{ 0xD6F9, 0xD6F9, 0xD6F9 }, +{ 0xD6FA, 0xD6FA, 0xD6FA }, +{ 0xD6FB, 0xD6FB, 0xD6FB }, +{ 0xD6FC, 0xD6FC, 0xD6FC }, +{ 0xD6FD, 0xD6FD, 0xD6FD }, +{ 0xD6FE, 0xD6FE, 0xD6FE }, +{ 0xD6FF, 0xD6FF, 0xD6FF }, +{ 0xD700, 0xD700, 0xD700 }, +{ 0xD701, 0xD701, 0xD701 }, +{ 0xD702, 0xD702, 0xD702 }, +{ 0xD703, 0xD703, 0xD703 }, +{ 0xD704, 0xD704, 0xD704 }, +{ 0xD705, 0xD705, 0xD705 }, +{ 0xD706, 0xD706, 0xD706 }, +{ 0xD707, 0xD707, 0xD707 }, +{ 0xD708, 0xD708, 0xD708 }, +{ 0xD709, 0xD709, 0xD709 }, +{ 0xD70A, 0xD70A, 0xD70A }, +{ 0xD70B, 0xD70B, 0xD70B }, +{ 0xD70C, 0xD70C, 0xD70C }, +{ 0xD70D, 0xD70D, 0xD70D }, +{ 0xD70E, 0xD70E, 0xD70E }, +{ 0xD70F, 0xD70F, 0xD70F }, +{ 0xD710, 0xD710, 0xD710 }, +{ 0xD711, 0xD711, 0xD711 }, +{ 0xD712, 0xD712, 0xD712 }, +{ 0xD713, 0xD713, 0xD713 }, +{ 0xD714, 0xD714, 0xD714 }, +{ 0xD715, 0xD715, 0xD715 }, +{ 0xD716, 0xD716, 0xD716 }, +{ 0xD717, 0xD717, 0xD717 }, +{ 0xD718, 0xD718, 0xD718 }, +{ 0xD719, 0xD719, 0xD719 }, +{ 0xD71A, 0xD71A, 0xD71A }, +{ 0xD71B, 0xD71B, 0xD71B }, +{ 0xD71C, 0xD71C, 0xD71C }, +{ 0xD71D, 0xD71D, 0xD71D }, +{ 0xD71E, 0xD71E, 0xD71E }, +{ 0xD71F, 0xD71F, 0xD71F }, +{ 0xD720, 0xD720, 0xD720 }, +{ 0xD721, 0xD721, 0xD721 }, +{ 0xD722, 0xD722, 0xD722 }, +{ 0xD723, 0xD723, 0xD723 }, +{ 0xD724, 0xD724, 0xD724 }, +{ 0xD725, 0xD725, 0xD725 }, +{ 0xD726, 0xD726, 0xD726 }, +{ 0xD727, 0xD727, 0xD727 }, +{ 0xD728, 0xD728, 0xD728 }, +{ 0xD729, 0xD729, 0xD729 }, +{ 0xD72A, 0xD72A, 0xD72A }, +{ 0xD72B, 0xD72B, 0xD72B }, +{ 0xD72C, 0xD72C, 0xD72C }, +{ 0xD72D, 0xD72D, 0xD72D }, +{ 0xD72E, 0xD72E, 0xD72E }, +{ 0xD72F, 0xD72F, 0xD72F }, +{ 0xD730, 0xD730, 0xD730 }, +{ 0xD731, 0xD731, 0xD731 }, +{ 0xD732, 0xD732, 0xD732 }, +{ 0xD733, 0xD733, 0xD733 }, +{ 0xD734, 0xD734, 0xD734 }, +{ 0xD735, 0xD735, 0xD735 }, +{ 0xD736, 0xD736, 0xD736 }, +{ 0xD737, 0xD737, 0xD737 }, +{ 0xD738, 0xD738, 0xD738 }, +{ 0xD739, 0xD739, 0xD739 }, +{ 0xD73A, 0xD73A, 0xD73A }, +{ 0xD73B, 0xD73B, 0xD73B }, +{ 0xD73C, 0xD73C, 0xD73C }, +{ 0xD73D, 0xD73D, 0xD73D }, +{ 0xD73E, 0xD73E, 0xD73E }, +{ 0xD73F, 0xD73F, 0xD73F }, +{ 0xD740, 0xD740, 0xD740 }, +{ 0xD741, 0xD741, 0xD741 }, +{ 0xD742, 0xD742, 0xD742 }, +{ 0xD743, 0xD743, 0xD743 }, +{ 0xD744, 0xD744, 0xD744 }, +{ 0xD745, 0xD745, 0xD745 }, +{ 0xD746, 0xD746, 0xD746 }, +{ 0xD747, 0xD747, 0xD747 }, +{ 0xD748, 0xD748, 0xD748 }, +{ 0xD749, 0xD749, 0xD749 }, +{ 0xD74A, 0xD74A, 0xD74A }, +{ 0xD74B, 0xD74B, 0xD74B }, +{ 0xD74C, 0xD74C, 0xD74C }, +{ 0xD74D, 0xD74D, 0xD74D }, +{ 0xD74E, 0xD74E, 0xD74E }, +{ 0xD74F, 0xD74F, 0xD74F }, +{ 0xD750, 0xD750, 0xD750 }, +{ 0xD751, 0xD751, 0xD751 }, +{ 0xD752, 0xD752, 0xD752 }, +{ 0xD753, 0xD753, 0xD753 }, +{ 0xD754, 0xD754, 0xD754 }, +{ 0xD755, 0xD755, 0xD755 }, +{ 0xD756, 0xD756, 0xD756 }, +{ 0xD757, 0xD757, 0xD757 }, +{ 0xD758, 0xD758, 0xD758 }, +{ 0xD759, 0xD759, 0xD759 }, +{ 0xD75A, 0xD75A, 0xD75A }, +{ 0xD75B, 0xD75B, 0xD75B }, +{ 0xD75C, 0xD75C, 0xD75C }, +{ 0xD75D, 0xD75D, 0xD75D }, +{ 0xD75E, 0xD75E, 0xD75E }, +{ 0xD75F, 0xD75F, 0xD75F }, +{ 0xD760, 0xD760, 0xD760 }, +{ 0xD761, 0xD761, 0xD761 }, +{ 0xD762, 0xD762, 0xD762 }, +{ 0xD763, 0xD763, 0xD763 }, +{ 0xD764, 0xD764, 0xD764 }, +{ 0xD765, 0xD765, 0xD765 }, +{ 0xD766, 0xD766, 0xD766 }, +{ 0xD767, 0xD767, 0xD767 }, +{ 0xD768, 0xD768, 0xD768 }, +{ 0xD769, 0xD769, 0xD769 }, +{ 0xD76A, 0xD76A, 0xD76A }, +{ 0xD76B, 0xD76B, 0xD76B }, +{ 0xD76C, 0xD76C, 0xD76C }, +{ 0xD76D, 0xD76D, 0xD76D }, +{ 0xD76E, 0xD76E, 0xD76E }, +{ 0xD76F, 0xD76F, 0xD76F }, +{ 0xD770, 0xD770, 0xD770 }, +{ 0xD771, 0xD771, 0xD771 }, +{ 0xD772, 0xD772, 0xD772 }, +{ 0xD773, 0xD773, 0xD773 }, +{ 0xD774, 0xD774, 0xD774 }, +{ 0xD775, 0xD775, 0xD775 }, +{ 0xD776, 0xD776, 0xD776 }, +{ 0xD777, 0xD777, 0xD777 }, +{ 0xD778, 0xD778, 0xD778 }, +{ 0xD779, 0xD779, 0xD779 }, +{ 0xD77A, 0xD77A, 0xD77A }, +{ 0xD77B, 0xD77B, 0xD77B }, +{ 0xD77C, 0xD77C, 0xD77C }, +{ 0xD77D, 0xD77D, 0xD77D }, +{ 0xD77E, 0xD77E, 0xD77E }, +{ 0xD77F, 0xD77F, 0xD77F }, +{ 0xD780, 0xD780, 0xD780 }, +{ 0xD781, 0xD781, 0xD781 }, +{ 0xD782, 0xD782, 0xD782 }, +{ 0xD783, 0xD783, 0xD783 }, +{ 0xD784, 0xD784, 0xD784 }, +{ 0xD785, 0xD785, 0xD785 }, +{ 0xD786, 0xD786, 0xD786 }, +{ 0xD787, 0xD787, 0xD787 }, +{ 0xD788, 0xD788, 0xD788 }, +{ 0xD789, 0xD789, 0xD789 }, +{ 0xD78A, 0xD78A, 0xD78A }, +{ 0xD78B, 0xD78B, 0xD78B }, +{ 0xD78C, 0xD78C, 0xD78C }, +{ 0xD78D, 0xD78D, 0xD78D }, +{ 0xD78E, 0xD78E, 0xD78E }, +{ 0xD78F, 0xD78F, 0xD78F }, +{ 0xD790, 0xD790, 0xD790 }, +{ 0xD791, 0xD791, 0xD791 }, +{ 0xD792, 0xD792, 0xD792 }, +{ 0xD793, 0xD793, 0xD793 }, +{ 0xD794, 0xD794, 0xD794 }, +{ 0xD795, 0xD795, 0xD795 }, +{ 0xD796, 0xD796, 0xD796 }, +{ 0xD797, 0xD797, 0xD797 }, +{ 0xD798, 0xD798, 0xD798 }, +{ 0xD799, 0xD799, 0xD799 }, +{ 0xD79A, 0xD79A, 0xD79A }, +{ 0xD79B, 0xD79B, 0xD79B }, +{ 0xD79C, 0xD79C, 0xD79C }, +{ 0xD79D, 0xD79D, 0xD79D }, +{ 0xD79E, 0xD79E, 0xD79E }, +{ 0xD79F, 0xD79F, 0xD79F }, +{ 0xD7A0, 0xD7A0, 0xD7A0 }, +{ 0xD7A1, 0xD7A1, 0xD7A1 }, +{ 0xD7A2, 0xD7A2, 0xD7A2 }, { 0xD7A3, 0xD7A3, 0xD7A3 }, { 0xF900, 0xF900, 0xF900 }, { 0xF901, 0xF901, 0xF901 }, diff --git a/ext/hunspell/w_char.hxx b/ext/hunspell/w_char.hxx new file mode 100644 index 000000000..3719dd3b7 --- /dev/null +++ b/ext/hunspell/w_char.hxx @@ -0,0 +1,21 @@ +#ifndef __WCHARHXX__ +#define __WCHARHXX__ + +#ifndef GCC +typedef struct { +#else +typedef struct __attribute__ ((packed)) { +#endif + unsigned char l; + unsigned char h; +} w_char; + +// two character arrays +struct replentry { + char * pattern; + char * pattern2; + bool start; + bool end; +}; + +#endif diff --git a/src/TortoiseProc/TortoiseProc.vcxproj b/src/TortoiseProc/TortoiseProc.vcxproj index f815333b6..8fb9cdaf7 100644 --- a/src/TortoiseProc/TortoiseProc.vcxproj +++ b/src/TortoiseProc/TortoiseProc.vcxproj @@ -77,7 +77,7 @@ ..\TortoiseProc;..\Resources;$InputDir;..\..\ext\ResizableLib;..\Git;..\Utils;..\..\ext\hunspell;..\..\ext\scintilla\include;..\Utils\TreePropSheet;..\Utils\MiscUI;..\TortoiseShell;..\..\ext\gitdll;..\..\ext\libgit2\include;..\..\ext\zlib;..\..\ext\OGDF;..\AsyncFramework;%(AdditionalIncludeDirectories) - THESAURUS;%(PreprocessorDefinitions) + HUNSPELL_STATIC;THESAURUS;%(PreprocessorDefinitions) Async @@ -90,7 +90,7 @@ ..\TortoiseProc;..\Resources;$InputDir;..\..\ext\ResizableLib;..\Git;..\Utils;..\..\ext\hunspell;..\..\ext\scintilla\include;..\Utils\TreePropSheet;..\Utils\MiscUI;..\TortoiseShell;..\..\ext\gitdll;..\..\ext\libgit2\include;..\..\ext\zlib;..\..\ext\OGDF;..\AsyncFramework;%(AdditionalIncludeDirectories) - THESAURUS;%(PreprocessorDefinitions) + HUNSPELL_STATIC;THESAURUS;%(PreprocessorDefinitions) Async @@ -103,7 +103,7 @@ ..\TortoiseProc;..\Resources;$InputDir;..\..\ext\ResizableLib;..\Git;..\Utils;..\..\ext\hunspell;..\..\ext\scintilla\include;..\Utils\TreePropSheet;..\Utils\MiscUI;..\TortoiseShell;..\..\ext\gitdll;..\..\ext\libgit2\include;..\..\ext\zlib;..\..\ext\OGDF;..\AsyncFramework;%(AdditionalIncludeDirectories) - THESAURUS;%(PreprocessorDefinitions) + HUNSPELL_STATIC;THESAURUS;%(PreprocessorDefinitions) Async @@ -116,7 +116,7 @@ ..\TortoiseProc;..\Resources;$InputDir;..\..\ext\ResizableLib;..\Git;..\Utils;..\..\ext\hunspell;..\..\ext\scintilla\include;..\Utils\TreePropSheet;..\Utils\MiscUI;..\TortoiseShell;..\..\ext\gitdll;..\..\ext\libgit2\include;..\..\ext\zlib;..\..\ext\OGDF;..\AsyncFramework;%(AdditionalIncludeDirectories) - THESAURUS;%(PreprocessorDefinitions) + HUNSPELL_STATIC;THESAURUS;%(PreprocessorDefinitions) Async -- 2.11.4.GIT