]> arthur.barton.de Git - netatalk.git/commitdiff
Add unicode to Mac OS code page (internal or with iconv) Björn Fernhomberg and
authordidg <didg>
Mon, 23 Jun 2003 10:25:07 +0000 (10:25 +0000)
committerdidg <didg>
Mon, 23 Jun 2003 10:25:07 +0000 (10:25 +0000)
me. Use a temporary new volume attribute "encoding:"

25 files changed:
configure.in
etc/afpd/Makefile.am
etc/afpd/afp_dsi.c
etc/afpd/catsearch.c
etc/afpd/desktop.c
etc/afpd/file.h
etc/afpd/mangle.c
etc/afpd/mangle.h
etc/afpd/messages.c
etc/afpd/precompose.c [deleted file]
etc/afpd/volume.c
etc/afpd/volume.h
include/atalk/Makefile.am
include/atalk/unicode.h [new file with mode: 0644]
libatalk/Makefile.am
libatalk/unicode/Makefile.am [new file with mode: 0644]
libatalk/unicode/charcnv.c [new file with mode: 0644]
libatalk/unicode/iconv.c [new file with mode: 0644]
libatalk/unicode/mac_hebrew.h [new file with mode: 0644]
libatalk/unicode/mac_roman.h [new file with mode: 0644]
libatalk/unicode/precompose.h [new file with mode: 0644]
libatalk/unicode/ucs2_casetable.h [new file with mode: 0644]
libatalk/unicode/unicode.h [new file with mode: 0644]
libatalk/unicode/util_unistr.c [new file with mode: 0644]
libatalk/util/Makefile.am

index 4daf417b5a7763f640f3743fed961fd0b4a55a5f..8733954ba0b812b153db47cc2dd4ac2bcee1fd13 100644 (file)
@@ -1,4 +1,4 @@
-dnl $Id: configure.in,v 1.179.2.2 2003-05-28 05:04:53 didg Exp $
+dnl $Id: configure.in,v 1.179.2.3 2003-06-23 10:25:07 didg Exp $
 dnl configure.in for netatalk
 
 AC_INIT(bin/adv1tov2/adv1tov2.c)
@@ -752,6 +752,7 @@ AC_OUTPUT([Makefile
        libatalk/nbp/Makefile
        libatalk/netddp/Makefile
        libatalk/util/Makefile
+       libatalk/unicode/Makefile
        macros/Makefile
        man/Makefile
        man/man1/Makefile
index 93c93657e8f3b93f28bc8947ac020c1ddee64412..4e8efd54105e202117bb25dff5e7a806ce2935d2 100644 (file)
@@ -11,7 +11,7 @@ afpd_SOURCES = unix.c ofork.c main.c switch.c auth.c volume.c directory.c \
         file.c enumerate.c desktop.c filedir.c fork.c appl.c gettok.c \
         mangle.c status.c afp_options.c afp_asp.c afp_dsi.c messages.c  \
         afp_config.c nfsquota.c codepage.c quota.c uam.c afs.c uid.c  \
-        afp_util.c catsearch.c precompose.c afprun.c
+        afp_util.c catsearch.c afprun.c
 
 afpd_LDADD = $(top_builddir)/libatalk/libatalk.la
 afpd_LDFLAGS = -export-dynamic
index 1c1bc89bca80df4f2f3eb33aa7c13d9f9002ae69..efcb2fec92ce9d1f5dcf85b84b2706672ec23cce 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: afp_dsi.c,v 1.27.2.1 2003-05-26 11:17:25 didg Exp $
+ * $Id: afp_dsi.c,v 1.27.2.2 2003-06-23 10:25:07 didg Exp $
  *
  * Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu)
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
@@ -139,7 +139,7 @@ static void afp_dsi_timedown()
  * SIGHUP reload configuration file
  * FIXME here or we wait ?
 */
-volatile reload_request = 0;
+volatile int reload_request = 0;
 
 static void afp_dsi_reload()
 {
index a908e135b048ed4bc350d7e7ac38b62348da335c..1d8785f9259ccebeec8f99c5483ef396d46920f6 100644 (file)
@@ -99,8 +99,8 @@ struct scrit {
        u_int32_t pdid;             /* Parent DID */
         u_int16_t offcnt;           /* Offspring count */
        struct finderinfo finfo;    /* Finder info */
-       char lname[32];             /* Long name */
-       char utf8name[256];         /* UTF8 name */
+       char lname[64];             /* Long name */ 
+       char utf8name[512];         /* UTF8 name */
 };
 
 /*
@@ -277,6 +277,9 @@ static int crit_check(struct vol *vol, struct path *path, int cidx) {
        struct finderinfo *finfo = NULL, finderinfo;
        struct adouble *adp = NULL;
        time_t c_date, b_date;
+       static char convbuf[512];
+       static char convbuf2[512];
+       size_t len;
 
        if (S_ISDIR(path->st.st_mode)) {
                r = 2;
@@ -294,20 +297,28 @@ static int crit_check(struct vol *vol, struct path *path, int cidx) {
 
        /* Check for filename */
        if (c1.rbitmap & (1<<DIRPBIT_LNAME)) { 
+               if ( (size_t)(-1) == (len = convert_string(vol->v_maccharset, CH_UCS2, path->m_name, strlen(path->m_name), convbuf, 512)) )
+                       goto crit_check_ret;
+               convbuf[len] = 0; 
                if (c1.rbitmap & (1<<CATPBIT_PARTIAL)) {
-                       if (strcasestr(path->u_name, c1.lname) == NULL)
+                       if (strcasestr_w( (ucs2_t*) convbuf, (ucs2_t*) c1.lname) == NULL)
                                goto crit_check_ret;
                } else
-                       if (strcasecmp(path->u_name, c1.lname) != 0)
+                       if (strcasecmp_w((ucs2_t*) convbuf, (ucs2_t*) c1.lname) != 0)
                                goto crit_check_ret;
        } /* if (c1.rbitmap & ... */
        
        if ((c1.rbitmap & (1<<FILPBIT_PDINFO))) { 
+               if ( (size_t)(-1) == (len = utf8_precompose( path->m_name, strlen(path->m_name), convbuf2, 512)) )
+                       goto crit_check_ret;
+               if ( (size_t)(-1) == (len = convert_string( CH_UTF8, CH_UCS2, convbuf2, len, convbuf, 512)) )
+                       goto crit_check_ret;
+               convbuf[len] = 0; 
                if (c1.rbitmap & (1<<CATPBIT_PARTIAL)) {
-                       if (strcasestr(path->u_name, c1.utf8name) == NULL)
+                       if (strcasestr_w((ucs2_t *) convbuf, (ucs2_t*)c1.utf8name) == NULL)
                                goto crit_check_ret;
                } else
-                       if (strcasecmp(path->u_name, c1.utf8name) != 0)
+                       if (strcasecmp_w((ucs2_t *)convbuf, (ucs2_t*)c1.utf8name) != 0)
                                goto crit_check_ret;
        } /* if (c1.rbitmap & ... */
 
@@ -822,9 +833,19 @@ int catsearch_afp(AFPObj *obj, char *ibuf, int ibuflen,
 
     /* Long name */
     if (c1.rbitmap & (1 << FILPBIT_LNAME)) {
+       char            tmppath[256];
+       size_t          len;
         /* Get the long filename */    
-       memcpy(c1.lname, bspec1 + spec1[1] + 1, (bspec1 + spec1[1])[0]);
-       c1.lname[(bspec1 + spec1[1])[0]]= 0;
+/*     memcpy(c1.lname, bspec1 + spec1[1] + 1, (bspec1 + spec1[1])[0]);
+       c1.lname[(bspec1 + spec1[1])[0]]= 0;*/
+       memcpy(tmppath, bspec1 + spec1[1] + 1, (bspec1 + spec1[1])[0]);
+       tmppath[(bspec1 + spec1[1])[0]]= 0;
+       len = convert_string ( vol->v_maccharset, CH_UCS2, tmppath, strlen(tmppath), c1.lname, 64);
+        if (len == (size_t)(-1))
+            return AFPERR_PARAM;
+       c1.lname[len] = 0;
+
+       
 #if 0  
        for (i = 0; c1.lname[i] != 0; i++)
                c1.lname[i] = tolower(c1.lname[i]);
@@ -839,7 +860,8 @@ int catsearch_afp(AFPObj *obj, char *ibuf, int ibuflen,
     }
         /* UTF8 Name */
     if (c1.rbitmap & (1 << FILPBIT_PDINFO)) {
-       char *          tmppath;
+       char            tmppath[256];
+       size_t          len;
        u_int16_t       namelen;
 
        /* offset */
@@ -857,10 +879,12 @@ int catsearch_afp(AFPObj *obj, char *ibuf, int ibuflen,
        memcpy (c1.utf8name, spec1+2, namelen);
        c1.utf8name[(namelen+1)] =0;
 
-       /* convert charset */   
-       tmppath = mtoupath(vol, c1.utf8name, 1);
-       memset (c1.utf8name, 0, 256);
-       memcpy (c1.utf8name, tmppath, MIN(strlen(tmppath), 255));
+       /* convert charset */
+       len = utf8_precompose( c1.utf8name, namelen, tmppath, 256); 
+       len = convert_string(CH_UTF8, CH_UCS2, tmppath, namelen, c1.utf8name, 512);
+        if (len == (size_t)(-1))
+            return AFPERR_PARAM;
+       c1.utf8name[len]=0;
     }
     
     /* Call search */
index b56af5c3600248a36bf32db3b98f0dc6930d49c7..749ab69a51f2f8a09fbbbcfd365ec4d68d1706d5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: desktop.c,v 1.26.2.2 2003-05-12 22:02:08 didg Exp $
+ * $Id: desktop.c,v 1.26.2.3 2003-06-23 10:25:07 didg Exp $
  *
  * See COPYRIGHT.
  *
@@ -52,6 +52,7 @@
 
 #ifdef AFP3x
 #include <iconv.h>
+#include <atalk/unicode.h>
 #endif
 
 int afp_opendt(obj, ibuf, ibuflen, rbuf, rbuflen )
@@ -749,95 +750,6 @@ static char *old_utompath(const struct vol *vol, char *upath)
     return((changed)? m:upath );
 }
 
-/* --------------- */
-extern unsigned int do_precomposition(unsigned int base, unsigned int comb);
-
-static char comp[MAXPATHLEN +1];
-
-static char *precompose(u_int16_t  *name, size_t inplen, size_t *outlen)
-{
-size_t i;
-u_int16_t base, comb;
-u_int16_t *in, *out;
-u_int16_t result;
-
-    if (!inplen || (inplen & 1) || inplen > sizeof(comp)/sizeof(u_int16_t))
-        return NULL;
-    i = 0;
-    in  = name;
-    out = (u_int16_t *)comp;
-    *outlen = 0;
-    
-    base = *in;
-    while (1) {
-        i += 2;
-        in++;
-        if (i == inplen) {
-           *out = base;
-           *outlen += 2;
-           return comp;
-        }
-        comb = *in;
-        if (comb >= 0x300 && (result = do_precomposition(base, comb))) {
-           *out = result;
-           out++;
-           *outlen += 2;
-           i += 2;
-           in++;
-           if (i == inplen) 
-              return comp;
-           base = *in;
-        }
-        else {
-           *out = base;
-           out++;
-           *outlen += 2;
-           base = comb;
-        }
-    }
-}
-
-/* --------------- */
-extern unsigned int do_decomposition(unsigned int base);
-
-static char *decompose(u_int16_t  *name, size_t inplen, size_t *outlen)
-{
-size_t i;
-u_int16_t base;
-u_int16_t *in, *out;
-unsigned int result;
-
-    if (!inplen || (inplen & 1))
-        return NULL;
-    i = 0;
-    in  = name;
-    out = (u_int16_t *)comp;
-    *outlen = 0;
-    
-    while (i < inplen) {
-        if (*outlen >= sizeof(comp)/sizeof(u_int16_t) +2) {
-            return NULL;
-        }
-        base = *in;
-        if ((result = do_decomposition(base))) {
-           *out = result  >> 16;
-           out++;
-           *outlen += 2;
-           *out = result & 0xffff;
-           out++;
-           *outlen += 2;
-        }
-        else {
-           *out = base;
-           out++;
-           *outlen += 2;
-        }
-        i += 2;
-        in++;
-     }
-     return comp;
-}
-
 /* --------------------------- */
 char *mtoupath(const struct vol *vol, char *mpath, int utf8)
 {
@@ -864,8 +776,7 @@ char *mtoupath(const struct vol *vol, char *mpath, int utf8)
     u = upath;
     while ( *m != '\0' ) {
         if ( (!(vol->v_flags & AFPVOL_NOHEX) && *m == '/') ||
-             (!(vol->v_flags & AFPVOL_USEDOTS) && i == 0 && *m == '.') ||
-             (!utf8 && (unsigned char)*m == 0xf0) /* Apple logo */
+             (!(vol->v_flags & AFPVOL_USEDOTS) && i == 0 && *m == '.') 
         ) {
           /* do hex conversion. */
           *u++ = ':';
@@ -884,32 +795,21 @@ char *mtoupath(const struct vol *vol, char *mpath, int utf8)
     outlen = MAXPATHLEN;
     r = ucs2;
     if (!utf8) {
-        if ((size_t)(-1) == iconv(vol->v_mactoutf8, 0,0,0,0) )
-            return NULL;
         /* assume precompose */
-        if ((size_t)(-1) == iconv(vol->v_mactoutf8, &u, &inplen, &r, &outlen))
+        if ((size_t)(-1) == (outlen = convert_string ( vol->v_maccharset, CH_UTF8, u, inplen, r, outlen)) )
             return NULL;
         u = ucs2;
     }
     else { 
-        if ((size_t)(-1) == iconv(vol->v_utf8toucs2, 0,0,0,0) )
-            return NULL;
 
-        if ((size_t)(-1) == iconv(vol->v_utf8toucs2, &u, &inplen, &r, &outlen))
-            return NULL;
-
-        u = precompose((u_int16_t *)ucs2, MAXPATHLEN -outlen, &inplen);
+       r = upath;
+       
+        if ((size_t)(-1) == (outlen = utf8_precompose(  u, inplen, r, outlen)) )
+           return NULL;
 
-        if ((size_t)(-1) == iconv(vol->v_ucs2toutf8, 0,0,0,0))
-            return NULL;
-            
-        outlen = MAXPATHLEN;
-        r = upath;
-        if ((size_t)(-1) == iconv(vol->v_ucs2toutf8, &u, &inplen, &r, &outlen))
-            return NULL;
-        u = upath;
+        u = upath; 
     }
-    u[MAXPATHLEN -outlen] = 0;
+    u[outlen] = 0;
 #endif
 #ifdef DEBUG
     LOG(log_debug, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
@@ -920,10 +820,9 @@ char *mtoupath(const struct vol *vol, char *mpath, int utf8)
 /* --------------- */
 char *utompath(const struct vol *vol, char *upath, int utf8)
 {
-    char        *m, *u, *r;
+    char        *m, *u;
     int          h;
     int          mangleflag = 0;
-    size_t       inplen;
     size_t       outlen;
 
     if (!vol_utf8(vol))
@@ -946,46 +845,16 @@ char *utompath(const struct vol *vol, char *upath, int utf8)
     *m = '\0';
     m = mpath;
 #ifdef AFP3x    
-    if ((size_t)(-1) == iconv(vol->v_utf8toucs2, 0,0,0,0) )
-        return NULL;
-    inplen = strlen(mpath);
-    outlen = MAXPATHLEN;
-    r = ucs2;
-    if ((size_t)(-1) == iconv(vol->v_utf8toucs2, &m, &inplen, &r, &outlen))
-        return NULL;
-
     if (utf8) {
-        if ( NULL == (m = decompose((u_int16_t *)ucs2, MAXPATHLEN -outlen, &inplen)))
-            return NULL;
-
-        if ((size_t)(-1) == iconv(vol->v_ucs2toutf8, 0,0,0,0))
-            return NULL;
-            
-        outlen = MAXPATHLEN;
-        r = mpath;
-        if ((size_t)(-1) == iconv(vol->v_ucs2toutf8, &m, &inplen, &r, &outlen))
-            return NULL;
+       if ((size_t)(-1) == ( outlen = utf8_decompose ( mpath, strlen (mpath), mpath, MAXPATHLEN)) )
+          return NULL;
     }
     else {
-        m = precompose((u_int16_t *)ucs2, MAXPATHLEN -outlen, &inplen);
+        if ((size_t)(-1) == ( outlen = utf8_to_mac_charset ( vol->v_maccharset,  mpath, strlen(mpath), mpath, MAXPATHLEN, &mangleflag)) ) 
+               return NULL;
+   }
+   mpath[outlen] = 0; 
 
-        if ((size_t)(-1) == iconv(vol->v_ucs2tomac, 0,0,0,0))
-            return NULL;
-            
-        outlen = MAXPATHLEN;
-        r = mpath;
-        if ((size_t)(-1) == iconv(vol->v_ucs2tomac, &m, &inplen, &r, &outlen)) {
-            switch (errno) {
-            case EILSEQ:
-                if (outlen != MAXPATHLEN) {
-                    mangleflag = 1;
-                }
-            default:
-                return NULL;
-            }
-        }
-    }
-    mpath[MAXPATHLEN -outlen] = 0;
 #endif
 #ifdef FILE_MANGLING
     m = mangle(vol, mpath, upath, mangleflag);
index f97ce03b4ac6ff2d93f1b66cd7b7c16d2c260c1d..bd45bf67813179b288723d4944cfefb91d397dcb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: file.h,v 1.16 2003-03-09 19:55:34 didg Exp $
+ * $Id: file.h,v 1.16.2.1 2003-06-23 10:25:07 didg Exp $
  *
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
@@ -74,6 +74,51 @@ struct extmap {
 };
 
 #define kTextEncodingUTF8 0x08000103
+
+typedef enum {
+                                        /* Mac OS encodings*/
+  kTextEncodingMacRoman         = 0L,
+  kTextEncodingMacJapanese      = 1,
+  kTextEncodingMacChineseTrad   = 2,
+  kTextEncodingMacKorean        = 3,
+  kTextEncodingMacArabic        = 4,
+  kTextEncodingMacHebrew        = 5,
+  kTextEncodingMacGreek         = 6,
+  kTextEncodingMacCyrillic      = 7,
+  kTextEncodingMacDevanagari    = 9,
+  kTextEncodingMacGurmukhi      = 10,
+  kTextEncodingMacGujarati      = 11,
+  kTextEncodingMacOriya         = 12,
+  kTextEncodingMacBengali       = 13,
+  kTextEncodingMacTamil         = 14,
+  kTextEncodingMacTelugu        = 15,
+  kTextEncodingMacKannada       = 16,
+  kTextEncodingMacMalayalam     = 17,
+  kTextEncodingMacSinhalese     = 18,
+  kTextEncodingMacBurmese       = 19,
+  kTextEncodingMacKhmer         = 20,
+  kTextEncodingMacThai          = 21,
+  kTextEncodingMacLaotian       = 22,
+  kTextEncodingMacGeorgian      = 23,
+  kTextEncodingMacArmenian      = 24,
+  kTextEncodingMacChineseSimp   = 25,
+  kTextEncodingMacTibetan       = 26,
+  kTextEncodingMacMongolian     = 27,
+  kTextEncodingMacEthiopic      = 28,
+  kTextEncodingMacCentralEurRoman = 29,
+  kTextEncodingMacVietnamese    = 30,
+  kTextEncodingMacExtArabic     = 31,   /* The following use script code 0, smRoman*/
+  kTextEncodingMacSymbol        = 33,
+  kTextEncodingMacDingbats      = 34,
+  kTextEncodingMacTurkish       = 35,
+  kTextEncodingMacCroatian      = 36,
+  kTextEncodingMacIcelandic     = 37,
+  kTextEncodingMacRomanian      = 38,
+  kTextEncodingMacCeltic        = 39,
+  kTextEncodingMacGaelic        = 40,
+  kTextEncodingMacKeyboardGlyphs = 41,
+} kTextEncoding_t;
+
 extern char *set_name   __P((const struct vol *, char *, char *, u_int32_t ) );
 
 extern struct extmap   *getextmap __P((const char *));
index 1923355fae2e468ca01aea021dbd7da67387d6b0..fda4e5868482dbb6bf6dc4efee2eaeb2aa7a681d 100644 (file)
@@ -1,5 +1,5 @@
 /* 
- * $Id: mangle.c,v 1.16 2003-03-09 20:37:27 didg Exp $ 
+ * $Id: mangle.c,v 1.16.2.1 2003-06-23 10:25:08 didg Exp $ 
  *
  * Copyright (c) 2002. Joe Marcus Clarke (marcus@marcuscom.com)
  * All Rights Reserved.  See COPYRIGHT.
 #ifdef FILE_MANGLING
 #include "mangle.h"
 
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif /* ! MIN */
+
+
 char *
 demangle(const struct vol *vol, char *mfilename) {
        char *filename = NULL;
@@ -79,8 +84,8 @@ mangle(const struct vol *vol, char *filename, char *uname, int flags) {
     /* Check to see if we already have a mangled filename by this name. */
     while (1) {
        m = mfilename;
-       strncpy(m, filename, MAX_LENGTH - strlen(MANGLE_CHAR) - MANGLE_LENGTH - ext_len);
-       m[MAX_LENGTH - strlen(MANGLE_CHAR) - MANGLE_LENGTH - ext_len] = '\0';
+       strncpy(m, filename, MIN(MAX_LENGTH - strlen(MANGLE_CHAR) - MANGLE_LENGTH - ext_len, strlen(filename)-ext_len));
+       m[MIN(MAX_LENGTH - strlen(MANGLE_CHAR) - MANGLE_LENGTH - ext_len, strlen(filename)-ext_len)] = '\0';
 
        strcat(m, MANGLE_CHAR);
        (void)sprintf(mangle_suffix, "%03d", mangle_suffix_int);
index ac01a7a6f7dfd38788225ddc528c089b2c97f661..f541b5fc81249872c166a0243dcec4c9e99adf6c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: mangle.h,v 1.4 2003-03-09 19:55:35 didg Exp $
+ * $Id: mangle.h,v 1.4.2.1 2003-06-23 10:25:08 didg Exp $
  *
  */
 
@@ -9,6 +9,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+ #include <stdio.h>
 
 #include <atalk/adouble.h>
 #ifdef CNID_DB
index c723211ae1936901dca5fca57586ac81d6205b18..45e6be67726af2a3c6df716d4fa080ee348e3692 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: messages.c,v 1.16 2002-03-24 01:23:41 sibaz Exp $
+ * $Id: messages.c,v 1.16.6.1 2003-06-23 10:25:08 didg Exp $
  *
  * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
  * All Rights Reserved.  See COPYRIGHT.
@@ -42,7 +42,11 @@ void readmessage(void)
 
     i=0;
     /* Construct file name SERVERTEXT/message.[pid] */
-    filename=malloc(sizeof(SERVERTEXT)+15);
+    if ( NULL == (filename=(char*) malloc(sizeof(SERVERTEXT)+15)) ) {
+       LOG(log_error, logtype_afpd, "readmessage: malloc: %s", strerror(errno) );
+        return;
+    }
+
     sprintf(filename, "%s/message.%d", SERVERTEXT, getpid());
 
 #ifdef DEBUG
diff --git a/etc/afpd/precompose.c b/etc/afpd/precompose.c
deleted file mode 100644 (file)
index 9514726..0000000
+++ /dev/null
@@ -1,2043 +0,0 @@
-/*
- * Canonical Compositions
- *
- */
-/* $XFree86: xc/programs/xterm/precompose.c,v 1.2 2000/11/01 01:12:41 dawes Exp $ */
-
-static const struct {
-  unsigned int replacement;
-  unsigned int base;
-  unsigned int comb; 
-} precompositions[] = {
-{ 0x226E, 0x003C, 0x0338},
-{ 0x2260, 0x003D, 0x0338},
-{ 0x226F, 0x003E, 0x0338},
-{ 0x00C0, 0x0041, 0x0300},
-{ 0x00C1, 0x0041, 0x0301},
-{ 0x00C2, 0x0041, 0x0302},
-{ 0x00C3, 0x0041, 0x0303},
-{ 0x0100, 0x0041, 0x0304},
-{ 0x0102, 0x0041, 0x0306},
-{ 0x0226, 0x0041, 0x0307},
-{ 0x00C4, 0x0041, 0x0308},
-{ 0x1EA2, 0x0041, 0x0309},
-{ 0x00C5, 0x0041, 0x030A},
-{ 0x01CD, 0x0041, 0x030C},
-{ 0x0200, 0x0041, 0x030F},
-{ 0x0202, 0x0041, 0x0311},
-{ 0x1EA0, 0x0041, 0x0323},
-{ 0x1E00, 0x0041, 0x0325},
-{ 0x0104, 0x0041, 0x0328},
-{ 0x1E02, 0x0042, 0x0307},
-{ 0x1E04, 0x0042, 0x0323},
-{ 0x1E06, 0x0042, 0x0331},
-{ 0x0106, 0x0043, 0x0301},
-{ 0x0108, 0x0043, 0x0302},
-{ 0x010A, 0x0043, 0x0307},
-{ 0x010C, 0x0043, 0x030C},
-{ 0x00C7, 0x0043, 0x0327},
-{ 0x1E0A, 0x0044, 0x0307},
-{ 0x010E, 0x0044, 0x030C},
-{ 0x1E0C, 0x0044, 0x0323},
-{ 0x1E10, 0x0044, 0x0327},
-{ 0x1E12, 0x0044, 0x032D},
-{ 0x1E0E, 0x0044, 0x0331},
-{ 0x00C8, 0x0045, 0x0300},
-{ 0x00C9, 0x0045, 0x0301},
-{ 0x00CA, 0x0045, 0x0302},
-{ 0x1EBC, 0x0045, 0x0303},
-{ 0x0112, 0x0045, 0x0304},
-{ 0x0114, 0x0045, 0x0306},
-{ 0x0116, 0x0045, 0x0307},
-{ 0x00CB, 0x0045, 0x0308},
-{ 0x1EBA, 0x0045, 0x0309},
-{ 0x011A, 0x0045, 0x030C},
-{ 0x0204, 0x0045, 0x030F},
-{ 0x0206, 0x0045, 0x0311},
-{ 0x1EB8, 0x0045, 0x0323},
-{ 0x0228, 0x0045, 0x0327},
-{ 0x0118, 0x0045, 0x0328},
-{ 0x1E18, 0x0045, 0x032D},
-{ 0x1E1A, 0x0045, 0x0330},
-{ 0x1E1E, 0x0046, 0x0307},
-{ 0x01F4, 0x0047, 0x0301},
-{ 0x011C, 0x0047, 0x0302},
-{ 0x1E20, 0x0047, 0x0304},
-{ 0x011E, 0x0047, 0x0306},
-{ 0x0120, 0x0047, 0x0307},
-{ 0x01E6, 0x0047, 0x030C},
-{ 0x0122, 0x0047, 0x0327},
-{ 0x0124, 0x0048, 0x0302},
-{ 0x1E22, 0x0048, 0x0307},
-{ 0x1E26, 0x0048, 0x0308},
-{ 0x021E, 0x0048, 0x030C},
-{ 0x1E24, 0x0048, 0x0323},
-{ 0x1E28, 0x0048, 0x0327},
-{ 0x1E2A, 0x0048, 0x032E},
-{ 0x00CC, 0x0049, 0x0300},
-{ 0x00CD, 0x0049, 0x0301},
-{ 0x00CE, 0x0049, 0x0302},
-{ 0x0128, 0x0049, 0x0303},
-{ 0x012A, 0x0049, 0x0304},
-{ 0x012C, 0x0049, 0x0306},
-{ 0x0130, 0x0049, 0x0307},
-{ 0x00CF, 0x0049, 0x0308},
-{ 0x1EC8, 0x0049, 0x0309},
-{ 0x01CF, 0x0049, 0x030C},
-{ 0x0208, 0x0049, 0x030F},
-{ 0x020A, 0x0049, 0x0311},
-{ 0x1ECA, 0x0049, 0x0323},
-{ 0x012E, 0x0049, 0x0328},
-{ 0x1E2C, 0x0049, 0x0330},
-{ 0x0134, 0x004A, 0x0302},
-{ 0x1E30, 0x004B, 0x0301},
-{ 0x01E8, 0x004B, 0x030C},
-{ 0x1E32, 0x004B, 0x0323},
-{ 0x0136, 0x004B, 0x0327},
-{ 0x1E34, 0x004B, 0x0331},
-{ 0x0139, 0x004C, 0x0301},
-{ 0x013D, 0x004C, 0x030C},
-{ 0x1E36, 0x004C, 0x0323},
-{ 0x013B, 0x004C, 0x0327},
-{ 0x1E3C, 0x004C, 0x032D},
-{ 0x1E3A, 0x004C, 0x0331},
-{ 0x1E3E, 0x004D, 0x0301},
-{ 0x1E40, 0x004D, 0x0307},
-{ 0x1E42, 0x004D, 0x0323},
-{ 0x01F8, 0x004E, 0x0300},
-{ 0x0143, 0x004E, 0x0301},
-{ 0x00D1, 0x004E, 0x0303},
-{ 0x1E44, 0x004E, 0x0307},
-{ 0x0147, 0x004E, 0x030C},
-{ 0x1E46, 0x004E, 0x0323},
-{ 0x0145, 0x004E, 0x0327},
-{ 0x1E4A, 0x004E, 0x032D},
-{ 0x1E48, 0x004E, 0x0331},
-{ 0x00D2, 0x004F, 0x0300},
-{ 0x00D3, 0x004F, 0x0301},
-{ 0x00D4, 0x004F, 0x0302},
-{ 0x00D5, 0x004F, 0x0303},
-{ 0x014C, 0x004F, 0x0304},
-{ 0x014E, 0x004F, 0x0306},
-{ 0x022E, 0x004F, 0x0307},
-{ 0x00D6, 0x004F, 0x0308},
-{ 0x1ECE, 0x004F, 0x0309},
-{ 0x0150, 0x004F, 0x030B},
-{ 0x01D1, 0x004F, 0x030C},
-{ 0x020C, 0x004F, 0x030F},
-{ 0x020E, 0x004F, 0x0311},
-{ 0x01A0, 0x004F, 0x031B},
-{ 0x1ECC, 0x004F, 0x0323},
-{ 0x01EA, 0x004F, 0x0328},
-{ 0x1E54, 0x0050, 0x0301},
-{ 0x1E56, 0x0050, 0x0307},
-{ 0x0154, 0x0052, 0x0301},
-{ 0x1E58, 0x0052, 0x0307},
-{ 0x0158, 0x0052, 0x030C},
-{ 0x0210, 0x0052, 0x030F},
-{ 0x0212, 0x0052, 0x0311},
-{ 0x1E5A, 0x0052, 0x0323},
-{ 0x0156, 0x0052, 0x0327},
-{ 0x1E5E, 0x0052, 0x0331},
-{ 0x015A, 0x0053, 0x0301},
-{ 0x015C, 0x0053, 0x0302},
-{ 0x1E60, 0x0053, 0x0307},
-{ 0x0160, 0x0053, 0x030C},
-{ 0x1E62, 0x0053, 0x0323},
-{ 0x0218, 0x0053, 0x0326},
-{ 0x015E, 0x0053, 0x0327},
-{ 0x1E6A, 0x0054, 0x0307},
-{ 0x0164, 0x0054, 0x030C},
-{ 0x1E6C, 0x0054, 0x0323},
-{ 0x021A, 0x0054, 0x0326},
-{ 0x0162, 0x0054, 0x0327},
-{ 0x1E70, 0x0054, 0x032D},
-{ 0x1E6E, 0x0054, 0x0331},
-{ 0x00D9, 0x0055, 0x0300},
-{ 0x00DA, 0x0055, 0x0301},
-{ 0x00DB, 0x0055, 0x0302},
-{ 0x0168, 0x0055, 0x0303},
-{ 0x016A, 0x0055, 0x0304},
-{ 0x016C, 0x0055, 0x0306},
-{ 0x00DC, 0x0055, 0x0308},
-{ 0x1EE6, 0x0055, 0x0309},
-{ 0x016E, 0x0055, 0x030A},
-{ 0x0170, 0x0055, 0x030B},
-{ 0x01D3, 0x0055, 0x030C},
-{ 0x0214, 0x0055, 0x030F},
-{ 0x0216, 0x0055, 0x0311},
-{ 0x01AF, 0x0055, 0x031B},
-{ 0x1EE4, 0x0055, 0x0323},
-{ 0x1E72, 0x0055, 0x0324},
-{ 0x0172, 0x0055, 0x0328},
-{ 0x1E76, 0x0055, 0x032D},
-{ 0x1E74, 0x0055, 0x0330},
-{ 0x1E7C, 0x0056, 0x0303},
-{ 0x1E7E, 0x0056, 0x0323},
-{ 0x1E80, 0x0057, 0x0300},
-{ 0x1E82, 0x0057, 0x0301},
-{ 0x0174, 0x0057, 0x0302},
-{ 0x1E86, 0x0057, 0x0307},
-{ 0x1E84, 0x0057, 0x0308},
-{ 0x1E88, 0x0057, 0x0323},
-{ 0x1E8A, 0x0058, 0x0307},
-{ 0x1E8C, 0x0058, 0x0308},
-{ 0x1EF2, 0x0059, 0x0300},
-{ 0x00DD, 0x0059, 0x0301},
-{ 0x0176, 0x0059, 0x0302},
-{ 0x1EF8, 0x0059, 0x0303},
-{ 0x0232, 0x0059, 0x0304},
-{ 0x1E8E, 0x0059, 0x0307},
-{ 0x0178, 0x0059, 0x0308},
-{ 0x1EF6, 0x0059, 0x0309},
-{ 0x1EF4, 0x0059, 0x0323},
-{ 0x0179, 0x005A, 0x0301},
-{ 0x1E90, 0x005A, 0x0302},
-{ 0x017B, 0x005A, 0x0307},
-{ 0x017D, 0x005A, 0x030C},
-{ 0x1E92, 0x005A, 0x0323},
-{ 0x1E94, 0x005A, 0x0331},
-{ 0x00E0, 0x0061, 0x0300},
-{ 0x00E1, 0x0061, 0x0301},
-{ 0x00E2, 0x0061, 0x0302},
-{ 0x00E3, 0x0061, 0x0303},
-{ 0x0101, 0x0061, 0x0304},
-{ 0x0103, 0x0061, 0x0306},
-{ 0x0227, 0x0061, 0x0307},
-{ 0x00E4, 0x0061, 0x0308},
-{ 0x1EA3, 0x0061, 0x0309},
-{ 0x00E5, 0x0061, 0x030A},
-{ 0x01CE, 0x0061, 0x030C},
-{ 0x0201, 0x0061, 0x030F},
-{ 0x0203, 0x0061, 0x0311},
-{ 0x1EA1, 0x0061, 0x0323},
-{ 0x1E01, 0x0061, 0x0325},
-{ 0x0105, 0x0061, 0x0328},
-{ 0x1E03, 0x0062, 0x0307},
-{ 0x1E05, 0x0062, 0x0323},
-{ 0x1E07, 0x0062, 0x0331},
-{ 0x0107, 0x0063, 0x0301},
-{ 0x0109, 0x0063, 0x0302},
-{ 0x010B, 0x0063, 0x0307},
-{ 0x010D, 0x0063, 0x030C},
-{ 0x00E7, 0x0063, 0x0327},
-{ 0x1E0B, 0x0064, 0x0307},
-{ 0x010F, 0x0064, 0x030C},
-{ 0x1E0D, 0x0064, 0x0323},
-{ 0x1E11, 0x0064, 0x0327},
-{ 0x1E13, 0x0064, 0x032D},
-{ 0x1E0F, 0x0064, 0x0331},
-{ 0x00E8, 0x0065, 0x0300},
-{ 0x00E9, 0x0065, 0x0301},
-{ 0x00EA, 0x0065, 0x0302},
-{ 0x1EBD, 0x0065, 0x0303},
-{ 0x0113, 0x0065, 0x0304},
-{ 0x0115, 0x0065, 0x0306},
-{ 0x0117, 0x0065, 0x0307},
-{ 0x00EB, 0x0065, 0x0308},
-{ 0x1EBB, 0x0065, 0x0309},
-{ 0x011B, 0x0065, 0x030C},
-{ 0x0205, 0x0065, 0x030F},
-{ 0x0207, 0x0065, 0x0311},
-{ 0x1EB9, 0x0065, 0x0323},
-{ 0x0229, 0x0065, 0x0327},
-{ 0x0119, 0x0065, 0x0328},
-{ 0x1E19, 0x0065, 0x032D},
-{ 0x1E1B, 0x0065, 0x0330},
-{ 0x1E1F, 0x0066, 0x0307},
-{ 0x01F5, 0x0067, 0x0301},
-{ 0x011D, 0x0067, 0x0302},
-{ 0x1E21, 0x0067, 0x0304},
-{ 0x011F, 0x0067, 0x0306},
-{ 0x0121, 0x0067, 0x0307},
-{ 0x01E7, 0x0067, 0x030C},
-{ 0x0123, 0x0067, 0x0327},
-{ 0x0125, 0x0068, 0x0302},
-{ 0x1E23, 0x0068, 0x0307},
-{ 0x1E27, 0x0068, 0x0308},
-{ 0x021F, 0x0068, 0x030C},
-{ 0x1E25, 0x0068, 0x0323},
-{ 0x1E29, 0x0068, 0x0327},
-{ 0x1E2B, 0x0068, 0x032E},
-{ 0x1E96, 0x0068, 0x0331},
-{ 0x00EC, 0x0069, 0x0300},
-{ 0x00ED, 0x0069, 0x0301},
-{ 0x00EE, 0x0069, 0x0302},
-{ 0x0129, 0x0069, 0x0303},
-{ 0x012B, 0x0069, 0x0304},
-{ 0x012D, 0x0069, 0x0306},
-{ 0x00EF, 0x0069, 0x0308},
-{ 0x1EC9, 0x0069, 0x0309},
-{ 0x01D0, 0x0069, 0x030C},
-{ 0x0209, 0x0069, 0x030F},
-{ 0x020B, 0x0069, 0x0311},
-{ 0x1ECB, 0x0069, 0x0323},
-{ 0x012F, 0x0069, 0x0328},
-{ 0x1E2D, 0x0069, 0x0330},
-{ 0x0135, 0x006A, 0x0302},
-{ 0x01F0, 0x006A, 0x030C},
-{ 0x1E31, 0x006B, 0x0301},
-{ 0x01E9, 0x006B, 0x030C},
-{ 0x1E33, 0x006B, 0x0323},
-{ 0x0137, 0x006B, 0x0327},
-{ 0x1E35, 0x006B, 0x0331},
-{ 0x013A, 0x006C, 0x0301},
-{ 0x013E, 0x006C, 0x030C},
-{ 0x1E37, 0x006C, 0x0323},
-{ 0x013C, 0x006C, 0x0327},
-{ 0x1E3D, 0x006C, 0x032D},
-{ 0x1E3B, 0x006C, 0x0331},
-{ 0x1E3F, 0x006D, 0x0301},
-{ 0x1E41, 0x006D, 0x0307},
-{ 0x1E43, 0x006D, 0x0323},
-{ 0x01F9, 0x006E, 0x0300},
-{ 0x0144, 0x006E, 0x0301},
-{ 0x00F1, 0x006E, 0x0303},
-{ 0x1E45, 0x006E, 0x0307},
-{ 0x0148, 0x006E, 0x030C},
-{ 0x1E47, 0x006E, 0x0323},
-{ 0x0146, 0x006E, 0x0327},
-{ 0x1E4B, 0x006E, 0x032D},
-{ 0x1E49, 0x006E, 0x0331},
-{ 0x00F2, 0x006F, 0x0300},
-{ 0x00F3, 0x006F, 0x0301},
-{ 0x00F4, 0x006F, 0x0302},
-{ 0x00F5, 0x006F, 0x0303},
-{ 0x014D, 0x006F, 0x0304},
-{ 0x014F, 0x006F, 0x0306},
-{ 0x022F, 0x006F, 0x0307},
-{ 0x00F6, 0x006F, 0x0308},
-{ 0x1ECF, 0x006F, 0x0309},
-{ 0x0151, 0x006F, 0x030B},
-{ 0x01D2, 0x006F, 0x030C},
-{ 0x020D, 0x006F, 0x030F},
-{ 0x020F, 0x006F, 0x0311},
-{ 0x01A1, 0x006F, 0x031B},
-{ 0x1ECD, 0x006F, 0x0323},
-{ 0x01EB, 0x006F, 0x0328},
-{ 0x1E55, 0x0070, 0x0301},
-{ 0x1E57, 0x0070, 0x0307},
-{ 0x0155, 0x0072, 0x0301},
-{ 0x1E59, 0x0072, 0x0307},
-{ 0x0159, 0x0072, 0x030C},
-{ 0x0211, 0x0072, 0x030F},
-{ 0x0213, 0x0072, 0x0311},
-{ 0x1E5B, 0x0072, 0x0323},
-{ 0x0157, 0x0072, 0x0327},
-{ 0x1E5F, 0x0072, 0x0331},
-{ 0x015B, 0x0073, 0x0301},
-{ 0x015D, 0x0073, 0x0302},
-{ 0x1E61, 0x0073, 0x0307},
-{ 0x0161, 0x0073, 0x030C},
-{ 0x1E63, 0x0073, 0x0323},
-{ 0x0219, 0x0073, 0x0326},
-{ 0x015F, 0x0073, 0x0327},
-{ 0x1E6B, 0x0074, 0x0307},
-{ 0x1E97, 0x0074, 0x0308},
-{ 0x0165, 0x0074, 0x030C},
-{ 0x1E6D, 0x0074, 0x0323},
-{ 0x021B, 0x0074, 0x0326},
-{ 0x0163, 0x0074, 0x0327},
-{ 0x1E71, 0x0074, 0x032D},
-{ 0x1E6F, 0x0074, 0x0331},
-{ 0x00F9, 0x0075, 0x0300},
-{ 0x00FA, 0x0075, 0x0301},
-{ 0x00FB, 0x0075, 0x0302},
-{ 0x0169, 0x0075, 0x0303},
-{ 0x016B, 0x0075, 0x0304},
-{ 0x016D, 0x0075, 0x0306},
-{ 0x00FC, 0x0075, 0x0308},
-{ 0x1EE7, 0x0075, 0x0309},
-{ 0x016F, 0x0075, 0x030A},
-{ 0x0171, 0x0075, 0x030B},
-{ 0x01D4, 0x0075, 0x030C},
-{ 0x0215, 0x0075, 0x030F},
-{ 0x0217, 0x0075, 0x0311},
-{ 0x01B0, 0x0075, 0x031B},
-{ 0x1EE5, 0x0075, 0x0323},
-{ 0x1E73, 0x0075, 0x0324},
-{ 0x0173, 0x0075, 0x0328},
-{ 0x1E77, 0x0075, 0x032D},
-{ 0x1E75, 0x0075, 0x0330},
-{ 0x1E7D, 0x0076, 0x0303},
-{ 0x1E7F, 0x0076, 0x0323},
-{ 0x1E81, 0x0077, 0x0300},
-{ 0x1E83, 0x0077, 0x0301},
-{ 0x0175, 0x0077, 0x0302},
-{ 0x1E87, 0x0077, 0x0307},
-{ 0x1E85, 0x0077, 0x0308},
-{ 0x1E98, 0x0077, 0x030A},
-{ 0x1E89, 0x0077, 0x0323},
-{ 0x1E8B, 0x0078, 0x0307},
-{ 0x1E8D, 0x0078, 0x0308},
-{ 0x1EF3, 0x0079, 0x0300},
-{ 0x00FD, 0x0079, 0x0301},
-{ 0x0177, 0x0079, 0x0302},
-{ 0x1EF9, 0x0079, 0x0303},
-{ 0x0233, 0x0079, 0x0304},
-{ 0x1E8F, 0x0079, 0x0307},
-{ 0x00FF, 0x0079, 0x0308},
-{ 0x1EF7, 0x0079, 0x0309},
-{ 0x1E99, 0x0079, 0x030A},
-{ 0x1EF5, 0x0079, 0x0323},
-{ 0x017A, 0x007A, 0x0301},
-{ 0x1E91, 0x007A, 0x0302},
-{ 0x017C, 0x007A, 0x0307},
-{ 0x017E, 0x007A, 0x030C},
-{ 0x1E93, 0x007A, 0x0323},
-{ 0x1E95, 0x007A, 0x0331},
-{ 0x1FED, 0x00A8, 0x0300},
-{ 0x0385, 0x00A8, 0x0301},
-{ 0x1FC1, 0x00A8, 0x0342},
-{ 0x1EA6, 0x00C2, 0x0300},
-{ 0x1EA4, 0x00C2, 0x0301},
-{ 0x1EAA, 0x00C2, 0x0303},
-{ 0x1EA8, 0x00C2, 0x0309},
-{ 0x01DE, 0x00C4, 0x0304},
-{ 0x01FA, 0x00C5, 0x0301},
-{ 0x01FC, 0x00C6, 0x0301},
-{ 0x01E2, 0x00C6, 0x0304},
-{ 0x1E08, 0x00C7, 0x0301},
-{ 0x1EC0, 0x00CA, 0x0300},
-{ 0x1EBE, 0x00CA, 0x0301},
-{ 0x1EC4, 0x00CA, 0x0303},
-{ 0x1EC2, 0x00CA, 0x0309},
-{ 0x1E2E, 0x00CF, 0x0301},
-{ 0x1ED2, 0x00D4, 0x0300},
-{ 0x1ED0, 0x00D4, 0x0301},
-{ 0x1ED6, 0x00D4, 0x0303},
-{ 0x1ED4, 0x00D4, 0x0309},
-{ 0x1E4C, 0x00D5, 0x0301},
-{ 0x022C, 0x00D5, 0x0304},
-{ 0x1E4E, 0x00D5, 0x0308},
-{ 0x022A, 0x00D6, 0x0304},
-{ 0x01FE, 0x00D8, 0x0301},
-{ 0x01DB, 0x00DC, 0x0300},
-{ 0x01D7, 0x00DC, 0x0301},
-{ 0x01D5, 0x00DC, 0x0304},
-{ 0x01D9, 0x00DC, 0x030C},
-{ 0x1EA7, 0x00E2, 0x0300},
-{ 0x1EA5, 0x00E2, 0x0301},
-{ 0x1EAB, 0x00E2, 0x0303},
-{ 0x1EA9, 0x00E2, 0x0309},
-{ 0x01DF, 0x00E4, 0x0304},
-{ 0x01FB, 0x00E5, 0x0301},
-{ 0x01FD, 0x00E6, 0x0301},
-{ 0x01E3, 0x00E6, 0x0304},
-{ 0x1E09, 0x00E7, 0x0301},
-{ 0x1EC1, 0x00EA, 0x0300},
-{ 0x1EBF, 0x00EA, 0x0301},
-{ 0x1EC5, 0x00EA, 0x0303},
-{ 0x1EC3, 0x00EA, 0x0309},
-{ 0x1E2F, 0x00EF, 0x0301},
-{ 0x1ED3, 0x00F4, 0x0300},
-{ 0x1ED1, 0x00F4, 0x0301},
-{ 0x1ED7, 0x00F4, 0x0303},
-{ 0x1ED5, 0x00F4, 0x0309},
-{ 0x1E4D, 0x00F5, 0x0301},
-{ 0x022D, 0x00F5, 0x0304},
-{ 0x1E4F, 0x00F5, 0x0308},
-{ 0x022B, 0x00F6, 0x0304},
-{ 0x01FF, 0x00F8, 0x0301},
-{ 0x01DC, 0x00FC, 0x0300},
-{ 0x01D8, 0x00FC, 0x0301},
-{ 0x01D6, 0x00FC, 0x0304},
-{ 0x01DA, 0x00FC, 0x030C},
-{ 0x1EB0, 0x0102, 0x0300},
-{ 0x1EAE, 0x0102, 0x0301},
-{ 0x1EB4, 0x0102, 0x0303},
-{ 0x1EB2, 0x0102, 0x0309},
-{ 0x1EB1, 0x0103, 0x0300},
-{ 0x1EAF, 0x0103, 0x0301},
-{ 0x1EB5, 0x0103, 0x0303},
-{ 0x1EB3, 0x0103, 0x0309},
-{ 0x1E14, 0x0112, 0x0300},
-{ 0x1E16, 0x0112, 0x0301},
-{ 0x1E15, 0x0113, 0x0300},
-{ 0x1E17, 0x0113, 0x0301},
-{ 0x1E50, 0x014C, 0x0300},
-{ 0x1E52, 0x014C, 0x0301},
-{ 0x1E51, 0x014D, 0x0300},
-{ 0x1E53, 0x014D, 0x0301},
-{ 0x1E64, 0x015A, 0x0307},
-{ 0x1E65, 0x015B, 0x0307},
-{ 0x1E66, 0x0160, 0x0307},
-{ 0x1E67, 0x0161, 0x0307},
-{ 0x1E78, 0x0168, 0x0301},
-{ 0x1E79, 0x0169, 0x0301},
-{ 0x1E7A, 0x016A, 0x0308},
-{ 0x1E7B, 0x016B, 0x0308},
-{ 0x1E9B, 0x017F, 0x0307},
-{ 0x1EDC, 0x01A0, 0x0300},
-{ 0x1EDA, 0x01A0, 0x0301},
-{ 0x1EE0, 0x01A0, 0x0303},
-{ 0x1EDE, 0x01A0, 0x0309},
-{ 0x1EE2, 0x01A0, 0x0323},
-{ 0x1EDD, 0x01A1, 0x0300},
-{ 0x1EDB, 0x01A1, 0x0301},
-{ 0x1EE1, 0x01A1, 0x0303},
-{ 0x1EDF, 0x01A1, 0x0309},
-{ 0x1EE3, 0x01A1, 0x0323},
-{ 0x1EEA, 0x01AF, 0x0300},
-{ 0x1EE8, 0x01AF, 0x0301},
-{ 0x1EEE, 0x01AF, 0x0303},
-{ 0x1EEC, 0x01AF, 0x0309},
-{ 0x1EF0, 0x01AF, 0x0323},
-{ 0x1EEB, 0x01B0, 0x0300},
-{ 0x1EE9, 0x01B0, 0x0301},
-{ 0x1EEF, 0x01B0, 0x0303},
-{ 0x1EED, 0x01B0, 0x0309},
-{ 0x1EF1, 0x01B0, 0x0323},
-{ 0x01EE, 0x01B7, 0x030C},
-{ 0x01EC, 0x01EA, 0x0304},
-{ 0x01ED, 0x01EB, 0x0304},
-{ 0x01E0, 0x0226, 0x0304},
-{ 0x01E1, 0x0227, 0x0304},
-{ 0x1E1C, 0x0228, 0x0306},
-{ 0x1E1D, 0x0229, 0x0306},
-{ 0x0230, 0x022E, 0x0304},
-{ 0x0231, 0x022F, 0x0304},
-{ 0x01EF, 0x0292, 0x030C},
-{ 0x0344, 0x0308, 0x0301},
-{ 0x1FBA, 0x0391, 0x0300},
-{ 0x0386, 0x0391, 0x0301},
-{ 0x1FB9, 0x0391, 0x0304},
-{ 0x1FB8, 0x0391, 0x0306},
-{ 0x1F08, 0x0391, 0x0313},
-{ 0x1F09, 0x0391, 0x0314},
-{ 0x1FBC, 0x0391, 0x0345},
-{ 0x1FC8, 0x0395, 0x0300},
-{ 0x0388, 0x0395, 0x0301},
-{ 0x1F18, 0x0395, 0x0313},
-{ 0x1F19, 0x0395, 0x0314},
-{ 0x1FCA, 0x0397, 0x0300},
-{ 0x0389, 0x0397, 0x0301},
-{ 0x1F28, 0x0397, 0x0313},
-{ 0x1F29, 0x0397, 0x0314},
-{ 0x1FCC, 0x0397, 0x0345},
-{ 0x1FDA, 0x0399, 0x0300},
-{ 0x038A, 0x0399, 0x0301},
-{ 0x1FD9, 0x0399, 0x0304},
-{ 0x1FD8, 0x0399, 0x0306},
-{ 0x03AA, 0x0399, 0x0308},
-{ 0x1F38, 0x0399, 0x0313},
-{ 0x1F39, 0x0399, 0x0314},
-{ 0x1FF8, 0x039F, 0x0300},
-{ 0x038C, 0x039F, 0x0301},
-{ 0x1F48, 0x039F, 0x0313},
-{ 0x1F49, 0x039F, 0x0314},
-{ 0x1FEC, 0x03A1, 0x0314},
-{ 0x1FEA, 0x03A5, 0x0300},
-{ 0x038E, 0x03A5, 0x0301},
-{ 0x1FE9, 0x03A5, 0x0304},
-{ 0x1FE8, 0x03A5, 0x0306},
-{ 0x03AB, 0x03A5, 0x0308},
-{ 0x1F59, 0x03A5, 0x0314},
-{ 0x1FFA, 0x03A9, 0x0300},
-{ 0x038F, 0x03A9, 0x0301},
-{ 0x1F68, 0x03A9, 0x0313},
-{ 0x1F69, 0x03A9, 0x0314},
-{ 0x1FFC, 0x03A9, 0x0345},
-{ 0x1FB4, 0x03AC, 0x0345},
-{ 0x1FC4, 0x03AE, 0x0345},
-{ 0x1F70, 0x03B1, 0x0300},
-{ 0x03AC, 0x03B1, 0x0301},
-{ 0x1FB1, 0x03B1, 0x0304},
-{ 0x1FB0, 0x03B1, 0x0306},
-{ 0x1F00, 0x03B1, 0x0313},
-{ 0x1F01, 0x03B1, 0x0314},
-{ 0x1FB6, 0x03B1, 0x0342},
-{ 0x1FB3, 0x03B1, 0x0345},
-{ 0x1F72, 0x03B5, 0x0300},
-{ 0x03AD, 0x03B5, 0x0301},
-{ 0x1F10, 0x03B5, 0x0313},
-{ 0x1F11, 0x03B5, 0x0314},
-{ 0x1F74, 0x03B7, 0x0300},
-{ 0x03AE, 0x03B7, 0x0301},
-{ 0x1F20, 0x03B7, 0x0313},
-{ 0x1F21, 0x03B7, 0x0314},
-{ 0x1FC6, 0x03B7, 0x0342},
-{ 0x1FC3, 0x03B7, 0x0345},
-{ 0x1F76, 0x03B9, 0x0300},
-{ 0x03AF, 0x03B9, 0x0301},
-{ 0x1FD1, 0x03B9, 0x0304},
-{ 0x1FD0, 0x03B9, 0x0306},
-{ 0x03CA, 0x03B9, 0x0308},
-{ 0x1F30, 0x03B9, 0x0313},
-{ 0x1F31, 0x03B9, 0x0314},
-{ 0x1FD6, 0x03B9, 0x0342},
-{ 0x1F78, 0x03BF, 0x0300},
-{ 0x03CC, 0x03BF, 0x0301},
-{ 0x1F40, 0x03BF, 0x0313},
-{ 0x1F41, 0x03BF, 0x0314},
-{ 0x1FE4, 0x03C1, 0x0313},
-{ 0x1FE5, 0x03C1, 0x0314},
-{ 0x1F7A, 0x03C5, 0x0300},
-{ 0x03CD, 0x03C5, 0x0301},
-{ 0x1FE1, 0x03C5, 0x0304},
-{ 0x1FE0, 0x03C5, 0x0306},
-{ 0x03CB, 0x03C5, 0x0308},
-{ 0x1F50, 0x03C5, 0x0313},
-{ 0x1F51, 0x03C5, 0x0314},
-{ 0x1FE6, 0x03C5, 0x0342},
-{ 0x1F7C, 0x03C9, 0x0300},
-{ 0x03CE, 0x03C9, 0x0301},
-{ 0x1F60, 0x03C9, 0x0313},
-{ 0x1F61, 0x03C9, 0x0314},
-{ 0x1FF6, 0x03C9, 0x0342},
-{ 0x1FF3, 0x03C9, 0x0345},
-{ 0x1FD2, 0x03CA, 0x0300},
-{ 0x0390, 0x03CA, 0x0301},
-{ 0x1FD7, 0x03CA, 0x0342},
-{ 0x1FE2, 0x03CB, 0x0300},
-{ 0x03B0, 0x03CB, 0x0301},
-{ 0x1FE7, 0x03CB, 0x0342},
-{ 0x1FF4, 0x03CE, 0x0345},
-{ 0x03D3, 0x03D2, 0x0301},
-{ 0x03D4, 0x03D2, 0x0308},
-{ 0x0407, 0x0406, 0x0308},
-{ 0x04D0, 0x0410, 0x0306},
-{ 0x04D2, 0x0410, 0x0308},
-{ 0x0403, 0x0413, 0x0301},
-{ 0x0400, 0x0415, 0x0300},
-{ 0x04D6, 0x0415, 0x0306},
-{ 0x0401, 0x0415, 0x0308},
-{ 0x04C1, 0x0416, 0x0306},
-{ 0x04DC, 0x0416, 0x0308},
-{ 0x04DE, 0x0417, 0x0308},
-{ 0x040D, 0x0418, 0x0300},
-{ 0x04E2, 0x0418, 0x0304},
-{ 0x0419, 0x0418, 0x0306},
-{ 0x04E4, 0x0418, 0x0308},
-{ 0x040C, 0x041A, 0x0301},
-{ 0x04E6, 0x041E, 0x0308},
-{ 0x04EE, 0x0423, 0x0304},
-{ 0x040E, 0x0423, 0x0306},
-{ 0x04F0, 0x0423, 0x0308},
-{ 0x04F2, 0x0423, 0x030B},
-{ 0x04F4, 0x0427, 0x0308},
-{ 0x04F8, 0x042B, 0x0308},
-{ 0x04EC, 0x042D, 0x0308},
-{ 0x04D1, 0x0430, 0x0306},
-{ 0x04D3, 0x0430, 0x0308},
-{ 0x0453, 0x0433, 0x0301},
-{ 0x0450, 0x0435, 0x0300},
-{ 0x04D7, 0x0435, 0x0306},
-{ 0x0451, 0x0435, 0x0308},
-{ 0x04C2, 0x0436, 0x0306},
-{ 0x04DD, 0x0436, 0x0308},
-{ 0x04DF, 0x0437, 0x0308},
-{ 0x045D, 0x0438, 0x0300},
-{ 0x04E3, 0x0438, 0x0304},
-{ 0x0439, 0x0438, 0x0306},
-{ 0x04E5, 0x0438, 0x0308},
-{ 0x045C, 0x043A, 0x0301},
-{ 0x04E7, 0x043E, 0x0308},
-{ 0x04EF, 0x0443, 0x0304},
-{ 0x045E, 0x0443, 0x0306},
-{ 0x04F1, 0x0443, 0x0308},
-{ 0x04F3, 0x0443, 0x030B},
-{ 0x04F5, 0x0447, 0x0308},
-{ 0x04F9, 0x044B, 0x0308},
-{ 0x04ED, 0x044D, 0x0308},
-{ 0x0457, 0x0456, 0x0308},
-{ 0x0476, 0x0474, 0x030F},
-{ 0x0477, 0x0475, 0x030F},
-{ 0x04DA, 0x04D8, 0x0308},
-{ 0x04DB, 0x04D9, 0x0308},
-{ 0x04EA, 0x04E8, 0x0308},
-{ 0x04EB, 0x04E9, 0x0308},
-{ 0xFB2E, 0x05D0, 0x05B7},
-{ 0xFB2F, 0x05D0, 0x05B8},
-{ 0xFB30, 0x05D0, 0x05BC},
-{ 0xFB31, 0x05D1, 0x05BC},
-{ 0xFB4C, 0x05D1, 0x05BF},
-{ 0xFB32, 0x05D2, 0x05BC},
-{ 0xFB33, 0x05D3, 0x05BC},
-{ 0xFB34, 0x05D4, 0x05BC},
-{ 0xFB4B, 0x05D5, 0x05B9},
-{ 0xFB35, 0x05D5, 0x05BC},
-{ 0xFB36, 0x05D6, 0x05BC},
-{ 0xFB38, 0x05D8, 0x05BC},
-{ 0xFB1D, 0x05D9, 0x05B4},
-{ 0xFB39, 0x05D9, 0x05BC},
-{ 0xFB3A, 0x05DA, 0x05BC},
-{ 0xFB3B, 0x05DB, 0x05BC},
-{ 0xFB4D, 0x05DB, 0x05BF},
-{ 0xFB3C, 0x05DC, 0x05BC},
-{ 0xFB3E, 0x05DE, 0x05BC},
-{ 0xFB40, 0x05E0, 0x05BC},
-{ 0xFB41, 0x05E1, 0x05BC},
-{ 0xFB43, 0x05E3, 0x05BC},
-{ 0xFB44, 0x05E4, 0x05BC},
-{ 0xFB4E, 0x05E4, 0x05BF},
-{ 0xFB46, 0x05E6, 0x05BC},
-{ 0xFB47, 0x05E7, 0x05BC},
-{ 0xFB48, 0x05E8, 0x05BC},
-{ 0xFB49, 0x05E9, 0x05BC},
-{ 0xFB2A, 0x05E9, 0x05C1},
-{ 0xFB2B, 0x05E9, 0x05C2},
-{ 0xFB4A, 0x05EA, 0x05BC},
-{ 0xFB1F, 0x05F2, 0x05B7},
-{ 0x0622, 0x0627, 0x0653},
-{ 0x0623, 0x0627, 0x0654},
-{ 0x0625, 0x0627, 0x0655},
-{ 0x0624, 0x0648, 0x0654},
-{ 0x0626, 0x064A, 0x0654},
-{ 0x06C2, 0x06C1, 0x0654},
-{ 0x06D3, 0x06D2, 0x0654},
-{ 0x06C0, 0x06D5, 0x0654},
-{ 0x0958, 0x0915, 0x093C},
-{ 0x0959, 0x0916, 0x093C},
-{ 0x095A, 0x0917, 0x093C},
-{ 0x095B, 0x091C, 0x093C},
-{ 0x095C, 0x0921, 0x093C},
-{ 0x095D, 0x0922, 0x093C},
-{ 0x0929, 0x0928, 0x093C},
-{ 0x095E, 0x092B, 0x093C},
-{ 0x095F, 0x092F, 0x093C},
-{ 0x0931, 0x0930, 0x093C},
-{ 0x0934, 0x0933, 0x093C},
-{ 0x09DC, 0x09A1, 0x09BC},
-{ 0x09DD, 0x09A2, 0x09BC},
-{ 0x09DF, 0x09AF, 0x09BC},
-{ 0x09CB, 0x09C7, 0x09BE},
-{ 0x09CC, 0x09C7, 0x09D7},
-{ 0x0A59, 0x0A16, 0x0A3C},
-{ 0x0A5A, 0x0A17, 0x0A3C},
-{ 0x0A5B, 0x0A1C, 0x0A3C},
-{ 0x0A5E, 0x0A2B, 0x0A3C},
-{ 0x0A33, 0x0A32, 0x0A3C},
-{ 0x0A36, 0x0A38, 0x0A3C},
-{ 0x0B5C, 0x0B21, 0x0B3C},
-{ 0x0B5D, 0x0B22, 0x0B3C},
-{ 0x0B4B, 0x0B47, 0x0B3E},
-{ 0x0B48, 0x0B47, 0x0B56},
-{ 0x0B4C, 0x0B47, 0x0B57},
-{ 0x0B94, 0x0B92, 0x0BD7},
-{ 0x0BCA, 0x0BC6, 0x0BBE},
-{ 0x0BCC, 0x0BC6, 0x0BD7},
-{ 0x0BCB, 0x0BC7, 0x0BBE},
-{ 0x0C48, 0x0C46, 0x0C56},
-{ 0x0CC0, 0x0CBF, 0x0CD5},
-{ 0x0CCA, 0x0CC6, 0x0CC2},
-{ 0x0CC7, 0x0CC6, 0x0CD5},
-{ 0x0CC8, 0x0CC6, 0x0CD6},
-{ 0x0CCB, 0x0CCA, 0x0CD5},
-{ 0x0D4A, 0x0D46, 0x0D3E},
-{ 0x0D4C, 0x0D46, 0x0D57},
-{ 0x0D4B, 0x0D47, 0x0D3E},
-{ 0x0DDA, 0x0DD9, 0x0DCA},
-{ 0x0DDC, 0x0DD9, 0x0DCF},
-{ 0x0DDE, 0x0DD9, 0x0DDF},
-{ 0x0DDD, 0x0DDC, 0x0DCA},
-{ 0x0F69, 0x0F40, 0x0FB5},
-{ 0x0F43, 0x0F42, 0x0FB7},
-{ 0x0F4D, 0x0F4C, 0x0FB7},
-{ 0x0F52, 0x0F51, 0x0FB7},
-{ 0x0F57, 0x0F56, 0x0FB7},
-{ 0x0F5C, 0x0F5B, 0x0FB7},
-{ 0x0F73, 0x0F71, 0x0F72},
-{ 0x0F75, 0x0F71, 0x0F74},
-{ 0x0F81, 0x0F71, 0x0F80},
-{ 0x0FB9, 0x0F90, 0x0FB5},
-{ 0x0F93, 0x0F92, 0x0FB7},
-{ 0x0F9D, 0x0F9C, 0x0FB7},
-{ 0x0FA2, 0x0FA1, 0x0FB7},
-{ 0x0FA7, 0x0FA6, 0x0FB7},
-{ 0x0FAC, 0x0FAB, 0x0FB7},
-{ 0x0F76, 0x0FB2, 0x0F80},
-{ 0x0F78, 0x0FB3, 0x0F80},
-{ 0x1026, 0x1025, 0x102E},
-{ 0x1E38, 0x1E36, 0x0304},
-{ 0x1E39, 0x1E37, 0x0304},
-{ 0x1E5C, 0x1E5A, 0x0304},
-{ 0x1E5D, 0x1E5B, 0x0304},
-{ 0x1E68, 0x1E62, 0x0307},
-{ 0x1E69, 0x1E63, 0x0307},
-{ 0x1EAC, 0x1EA0, 0x0302},
-{ 0x1EB6, 0x1EA0, 0x0306},
-{ 0x1EAD, 0x1EA1, 0x0302},
-{ 0x1EB7, 0x1EA1, 0x0306},
-{ 0x1EC6, 0x1EB8, 0x0302},
-{ 0x1EC7, 0x1EB9, 0x0302},
-{ 0x1ED8, 0x1ECC, 0x0302},
-{ 0x1ED9, 0x1ECD, 0x0302},
-{ 0x1F02, 0x1F00, 0x0300},
-{ 0x1F04, 0x1F00, 0x0301},
-{ 0x1F06, 0x1F00, 0x0342},
-{ 0x1F80, 0x1F00, 0x0345},
-{ 0x1F03, 0x1F01, 0x0300},
-{ 0x1F05, 0x1F01, 0x0301},
-{ 0x1F07, 0x1F01, 0x0342},
-{ 0x1F81, 0x1F01, 0x0345},
-{ 0x1F82, 0x1F02, 0x0345},
-{ 0x1F83, 0x1F03, 0x0345},
-{ 0x1F84, 0x1F04, 0x0345},
-{ 0x1F85, 0x1F05, 0x0345},
-{ 0x1F86, 0x1F06, 0x0345},
-{ 0x1F87, 0x1F07, 0x0345},
-{ 0x1F0A, 0x1F08, 0x0300},
-{ 0x1F0C, 0x1F08, 0x0301},
-{ 0x1F0E, 0x1F08, 0x0342},
-{ 0x1F88, 0x1F08, 0x0345},
-{ 0x1F0B, 0x1F09, 0x0300},
-{ 0x1F0D, 0x1F09, 0x0301},
-{ 0x1F0F, 0x1F09, 0x0342},
-{ 0x1F89, 0x1F09, 0x0345},
-{ 0x1F8A, 0x1F0A, 0x0345},
-{ 0x1F8B, 0x1F0B, 0x0345},
-{ 0x1F8C, 0x1F0C, 0x0345},
-{ 0x1F8D, 0x1F0D, 0x0345},
-{ 0x1F8E, 0x1F0E, 0x0345},
-{ 0x1F8F, 0x1F0F, 0x0345},
-{ 0x1F12, 0x1F10, 0x0300},
-{ 0x1F14, 0x1F10, 0x0301},
-{ 0x1F13, 0x1F11, 0x0300},
-{ 0x1F15, 0x1F11, 0x0301},
-{ 0x1F1A, 0x1F18, 0x0300},
-{ 0x1F1C, 0x1F18, 0x0301},
-{ 0x1F1B, 0x1F19, 0x0300},
-{ 0x1F1D, 0x1F19, 0x0301},
-{ 0x1F22, 0x1F20, 0x0300},
-{ 0x1F24, 0x1F20, 0x0301},
-{ 0x1F26, 0x1F20, 0x0342},
-{ 0x1F90, 0x1F20, 0x0345},
-{ 0x1F23, 0x1F21, 0x0300},
-{ 0x1F25, 0x1F21, 0x0301},
-{ 0x1F27, 0x1F21, 0x0342},
-{ 0x1F91, 0x1F21, 0x0345},
-{ 0x1F92, 0x1F22, 0x0345},
-{ 0x1F93, 0x1F23, 0x0345},
-{ 0x1F94, 0x1F24, 0x0345},
-{ 0x1F95, 0x1F25, 0x0345},
-{ 0x1F96, 0x1F26, 0x0345},
-{ 0x1F97, 0x1F27, 0x0345},
-{ 0x1F2A, 0x1F28, 0x0300},
-{ 0x1F2C, 0x1F28, 0x0301},
-{ 0x1F2E, 0x1F28, 0x0342},
-{ 0x1F98, 0x1F28, 0x0345},
-{ 0x1F2B, 0x1F29, 0x0300},
-{ 0x1F2D, 0x1F29, 0x0301},
-{ 0x1F2F, 0x1F29, 0x0342},
-{ 0x1F99, 0x1F29, 0x0345},
-{ 0x1F9A, 0x1F2A, 0x0345},
-{ 0x1F9B, 0x1F2B, 0x0345},
-{ 0x1F9C, 0x1F2C, 0x0345},
-{ 0x1F9D, 0x1F2D, 0x0345},
-{ 0x1F9E, 0x1F2E, 0x0345},
-{ 0x1F9F, 0x1F2F, 0x0345},
-{ 0x1F32, 0x1F30, 0x0300},
-{ 0x1F34, 0x1F30, 0x0301},
-{ 0x1F36, 0x1F30, 0x0342},
-{ 0x1F33, 0x1F31, 0x0300},
-{ 0x1F35, 0x1F31, 0x0301},
-{ 0x1F37, 0x1F31, 0x0342},
-{ 0x1F3A, 0x1F38, 0x0300},
-{ 0x1F3C, 0x1F38, 0x0301},
-{ 0x1F3E, 0x1F38, 0x0342},
-{ 0x1F3B, 0x1F39, 0x0300},
-{ 0x1F3D, 0x1F39, 0x0301},
-{ 0x1F3F, 0x1F39, 0x0342},
-{ 0x1F42, 0x1F40, 0x0300},
-{ 0x1F44, 0x1F40, 0x0301},
-{ 0x1F43, 0x1F41, 0x0300},
-{ 0x1F45, 0x1F41, 0x0301},
-{ 0x1F4A, 0x1F48, 0x0300},
-{ 0x1F4C, 0x1F48, 0x0301},
-{ 0x1F4B, 0x1F49, 0x0300},
-{ 0x1F4D, 0x1F49, 0x0301},
-{ 0x1F52, 0x1F50, 0x0300},
-{ 0x1F54, 0x1F50, 0x0301},
-{ 0x1F56, 0x1F50, 0x0342},
-{ 0x1F53, 0x1F51, 0x0300},
-{ 0x1F55, 0x1F51, 0x0301},
-{ 0x1F57, 0x1F51, 0x0342},
-{ 0x1F5B, 0x1F59, 0x0300},
-{ 0x1F5D, 0x1F59, 0x0301},
-{ 0x1F5F, 0x1F59, 0x0342},
-{ 0x1F62, 0x1F60, 0x0300},
-{ 0x1F64, 0x1F60, 0x0301},
-{ 0x1F66, 0x1F60, 0x0342},
-{ 0x1FA0, 0x1F60, 0x0345},
-{ 0x1F63, 0x1F61, 0x0300},
-{ 0x1F65, 0x1F61, 0x0301},
-{ 0x1F67, 0x1F61, 0x0342},
-{ 0x1FA1, 0x1F61, 0x0345},
-{ 0x1FA2, 0x1F62, 0x0345},
-{ 0x1FA3, 0x1F63, 0x0345},
-{ 0x1FA4, 0x1F64, 0x0345},
-{ 0x1FA5, 0x1F65, 0x0345},
-{ 0x1FA6, 0x1F66, 0x0345},
-{ 0x1FA7, 0x1F67, 0x0345},
-{ 0x1F6A, 0x1F68, 0x0300},
-{ 0x1F6C, 0x1F68, 0x0301},
-{ 0x1F6E, 0x1F68, 0x0342},
-{ 0x1FA8, 0x1F68, 0x0345},
-{ 0x1F6B, 0x1F69, 0x0300},
-{ 0x1F6D, 0x1F69, 0x0301},
-{ 0x1F6F, 0x1F69, 0x0342},
-{ 0x1FA9, 0x1F69, 0x0345},
-{ 0x1FAA, 0x1F6A, 0x0345},
-{ 0x1FAB, 0x1F6B, 0x0345},
-{ 0x1FAC, 0x1F6C, 0x0345},
-{ 0x1FAD, 0x1F6D, 0x0345},
-{ 0x1FAE, 0x1F6E, 0x0345},
-{ 0x1FAF, 0x1F6F, 0x0345},
-{ 0x1FB2, 0x1F70, 0x0345},
-{ 0x1FC2, 0x1F74, 0x0345},
-{ 0x1FF2, 0x1F7C, 0x0345},
-{ 0x1FB7, 0x1FB6, 0x0345},
-{ 0x1FCD, 0x1FBF, 0x0300},
-{ 0x1FCE, 0x1FBF, 0x0301},
-{ 0x1FCF, 0x1FBF, 0x0342},
-{ 0x1FC7, 0x1FC6, 0x0345},
-{ 0x1FF7, 0x1FF6, 0x0345},
-{ 0x1FDD, 0x1FFE, 0x0300},
-{ 0x1FDE, 0x1FFE, 0x0301},
-{ 0x1FDF, 0x1FFE, 0x0342},
-{ 0x219A, 0x2190, 0x0338},
-{ 0x219B, 0x2192, 0x0338},
-{ 0x21AE, 0x2194, 0x0338},
-{ 0x21CD, 0x21D0, 0x0338},
-{ 0x21CF, 0x21D2, 0x0338},
-{ 0x21CE, 0x21D4, 0x0338},
-{ 0x2204, 0x2203, 0x0338},
-{ 0x2209, 0x2208, 0x0338},
-{ 0x220C, 0x220B, 0x0338},
-{ 0x2224, 0x2223, 0x0338},
-{ 0x2226, 0x2225, 0x0338},
-{ 0x2241, 0x223C, 0x0338},
-{ 0x2244, 0x2243, 0x0338},
-{ 0x2247, 0x2245, 0x0338},
-{ 0x2249, 0x2248, 0x0338},
-{ 0x226D, 0x224D, 0x0338},
-{ 0x2262, 0x2261, 0x0338},
-{ 0x2270, 0x2264, 0x0338},
-{ 0x2271, 0x2265, 0x0338},
-{ 0x2274, 0x2272, 0x0338},
-{ 0x2275, 0x2273, 0x0338},
-{ 0x2278, 0x2276, 0x0338},
-{ 0x2279, 0x2277, 0x0338},
-{ 0x2280, 0x227A, 0x0338},
-{ 0x2281, 0x227B, 0x0338},
-{ 0x22E0, 0x227C, 0x0338},
-{ 0x22E1, 0x227D, 0x0338},
-{ 0x2284, 0x2282, 0x0338},
-{ 0x2285, 0x2283, 0x0338},
-{ 0x2288, 0x2286, 0x0338},
-{ 0x2289, 0x2287, 0x0338},
-{ 0x22E2, 0x2291, 0x0338},
-{ 0x22E3, 0x2292, 0x0338},
-{ 0x22AC, 0x22A2, 0x0338},
-{ 0x22AD, 0x22A8, 0x0338},
-{ 0x22AE, 0x22A9, 0x0338},
-{ 0x22AF, 0x22AB, 0x0338},
-{ 0x22EA, 0x22B2, 0x0338},
-{ 0x22EB, 0x22B3, 0x0338},
-{ 0x22EC, 0x22B4, 0x0338},
-{ 0x22ED, 0x22B5, 0x0338},
-{ 0x3094, 0x3046, 0x3099},
-{ 0x304C, 0x304B, 0x3099},
-{ 0x304E, 0x304D, 0x3099},
-{ 0x3050, 0x304F, 0x3099},
-{ 0x3052, 0x3051, 0x3099},
-{ 0x3054, 0x3053, 0x3099},
-{ 0x3056, 0x3055, 0x3099},
-{ 0x3058, 0x3057, 0x3099},
-{ 0x305A, 0x3059, 0x3099},
-{ 0x305C, 0x305B, 0x3099},
-{ 0x305E, 0x305D, 0x3099},
-{ 0x3060, 0x305F, 0x3099},
-{ 0x3062, 0x3061, 0x3099},
-{ 0x3065, 0x3064, 0x3099},
-{ 0x3067, 0x3066, 0x3099},
-{ 0x3069, 0x3068, 0x3099},
-{ 0x3070, 0x306F, 0x3099},
-{ 0x3071, 0x306F, 0x309A},
-{ 0x3073, 0x3072, 0x3099},
-{ 0x3074, 0x3072, 0x309A},
-{ 0x3076, 0x3075, 0x3099},
-{ 0x3077, 0x3075, 0x309A},
-{ 0x3079, 0x3078, 0x3099},
-{ 0x307A, 0x3078, 0x309A},
-{ 0x307C, 0x307B, 0x3099},
-{ 0x307D, 0x307B, 0x309A},
-{ 0x309E, 0x309D, 0x3099},
-{ 0x30F4, 0x30A6, 0x3099},
-{ 0x30AC, 0x30AB, 0x3099},
-{ 0x30AE, 0x30AD, 0x3099},
-{ 0x30B0, 0x30AF, 0x3099},
-{ 0x30B2, 0x30B1, 0x3099},
-{ 0x30B4, 0x30B3, 0x3099},
-{ 0x30B6, 0x30B5, 0x3099},
-{ 0x30B8, 0x30B7, 0x3099},
-{ 0x30BA, 0x30B9, 0x3099},
-{ 0x30BC, 0x30BB, 0x3099},
-{ 0x30BE, 0x30BD, 0x3099},
-{ 0x30C0, 0x30BF, 0x3099},
-{ 0x30C2, 0x30C1, 0x3099},
-{ 0x30C5, 0x30C4, 0x3099},
-{ 0x30C7, 0x30C6, 0x3099},
-{ 0x30C9, 0x30C8, 0x3099},
-{ 0x30D0, 0x30CF, 0x3099},
-{ 0x30D1, 0x30CF, 0x309A},
-{ 0x30D3, 0x30D2, 0x3099},
-{ 0x30D4, 0x30D2, 0x309A},
-{ 0x30D6, 0x30D5, 0x3099},
-{ 0x30D7, 0x30D5, 0x309A},
-{ 0x30D9, 0x30D8, 0x3099},
-{ 0x30DA, 0x30D8, 0x309A},
-{ 0x30DC, 0x30DB, 0x3099},
-{ 0x30DD, 0x30DB, 0x309A},
-{ 0x30F7, 0x30EF, 0x3099},
-{ 0x30F8, 0x30F0, 0x3099},
-{ 0x30F9, 0x30F1, 0x3099},
-{ 0x30FA, 0x30F2, 0x3099},
-{ 0x30FE, 0x30FD, 0x3099},
-{ 0xFB2C, 0xFB49, 0x05C1},
-{ 0xFB2D, 0xFB49, 0x05C2},
-};
-
-static const struct {
-  unsigned int replacement;
-  unsigned int base;
-  unsigned int comb; 
-} decompositions[] = {
-{ 0x00C0, 0x0041, 0x0300},
-{ 0x00C1, 0x0041, 0x0301},
-{ 0x00C2, 0x0041, 0x0302},
-{ 0x00C3, 0x0041, 0x0303},
-{ 0x00C4, 0x0041, 0x0308},
-{ 0x00C5, 0x0041, 0x030A},
-{ 0x00C7, 0x0043, 0x0327},
-{ 0x00C8, 0x0045, 0x0300},
-{ 0x00C9, 0x0045, 0x0301},
-{ 0x00CA, 0x0045, 0x0302},
-{ 0x00CB, 0x0045, 0x0308},
-{ 0x00CC, 0x0049, 0x0300},
-{ 0x00CD, 0x0049, 0x0301},
-{ 0x00CE, 0x0049, 0x0302},
-{ 0x00CF, 0x0049, 0x0308},
-{ 0x00D1, 0x004E, 0x0303},
-{ 0x00D2, 0x004F, 0x0300},
-{ 0x00D3, 0x004F, 0x0301},
-{ 0x00D4, 0x004F, 0x0302},
-{ 0x00D5, 0x004F, 0x0303},
-{ 0x00D6, 0x004F, 0x0308},
-{ 0x00D9, 0x0055, 0x0300},
-{ 0x00DA, 0x0055, 0x0301},
-{ 0x00DB, 0x0055, 0x0302},
-{ 0x00DC, 0x0055, 0x0308},
-{ 0x00DD, 0x0059, 0x0301},
-{ 0x00E0, 0x0061, 0x0300},
-{ 0x00E1, 0x0061, 0x0301},
-{ 0x00E2, 0x0061, 0x0302},
-{ 0x00E3, 0x0061, 0x0303},
-{ 0x00E4, 0x0061, 0x0308},
-{ 0x00E5, 0x0061, 0x030A},
-{ 0x00E7, 0x0063, 0x0327},
-{ 0x00E8, 0x0065, 0x0300},
-{ 0x00E9, 0x0065, 0x0301},
-{ 0x00EA, 0x0065, 0x0302},
-{ 0x00EB, 0x0065, 0x0308},
-{ 0x00EC, 0x0069, 0x0300},
-{ 0x00ED, 0x0069, 0x0301},
-{ 0x00EE, 0x0069, 0x0302},
-{ 0x00EF, 0x0069, 0x0308},
-{ 0x00F1, 0x006E, 0x0303},
-{ 0x00F2, 0x006F, 0x0300},
-{ 0x00F3, 0x006F, 0x0301},
-{ 0x00F4, 0x006F, 0x0302},
-{ 0x00F5, 0x006F, 0x0303},
-{ 0x00F6, 0x006F, 0x0308},
-{ 0x00F9, 0x0075, 0x0300},
-{ 0x00FA, 0x0075, 0x0301},
-{ 0x00FB, 0x0075, 0x0302},
-{ 0x00FC, 0x0075, 0x0308},
-{ 0x00FD, 0x0079, 0x0301},
-{ 0x00FF, 0x0079, 0x0308},
-{ 0x0100, 0x0041, 0x0304},
-{ 0x0101, 0x0061, 0x0304},
-{ 0x0102, 0x0041, 0x0306},
-{ 0x0103, 0x0061, 0x0306},
-{ 0x0104, 0x0041, 0x0328},
-{ 0x0105, 0x0061, 0x0328},
-{ 0x0106, 0x0043, 0x0301},
-{ 0x0107, 0x0063, 0x0301},
-{ 0x0108, 0x0043, 0x0302},
-{ 0x0109, 0x0063, 0x0302},
-{ 0x010A, 0x0043, 0x0307},
-{ 0x010B, 0x0063, 0x0307},
-{ 0x010C, 0x0043, 0x030C},
-{ 0x010D, 0x0063, 0x030C},
-{ 0x010E, 0x0044, 0x030C},
-{ 0x010F, 0x0064, 0x030C},
-{ 0x0112, 0x0045, 0x0304},
-{ 0x0113, 0x0065, 0x0304},
-{ 0x0114, 0x0045, 0x0306},
-{ 0x0115, 0x0065, 0x0306},
-{ 0x0116, 0x0045, 0x0307},
-{ 0x0117, 0x0065, 0x0307},
-{ 0x0118, 0x0045, 0x0328},
-{ 0x0119, 0x0065, 0x0328},
-{ 0x011A, 0x0045, 0x030C},
-{ 0x011B, 0x0065, 0x030C},
-{ 0x011C, 0x0047, 0x0302},
-{ 0x011D, 0x0067, 0x0302},
-{ 0x011E, 0x0047, 0x0306},
-{ 0x011F, 0x0067, 0x0306},
-{ 0x0120, 0x0047, 0x0307},
-{ 0x0121, 0x0067, 0x0307},
-{ 0x0122, 0x0047, 0x0327},
-{ 0x0123, 0x0067, 0x0327},
-{ 0x0124, 0x0048, 0x0302},
-{ 0x0125, 0x0068, 0x0302},
-{ 0x0128, 0x0049, 0x0303},
-{ 0x0129, 0x0069, 0x0303},
-{ 0x012A, 0x0049, 0x0304},
-{ 0x012B, 0x0069, 0x0304},
-{ 0x012C, 0x0049, 0x0306},
-{ 0x012D, 0x0069, 0x0306},
-{ 0x012E, 0x0049, 0x0328},
-{ 0x012F, 0x0069, 0x0328},
-{ 0x0130, 0x0049, 0x0307},
-{ 0x0134, 0x004A, 0x0302},
-{ 0x0135, 0x006A, 0x0302},
-{ 0x0136, 0x004B, 0x0327},
-{ 0x0137, 0x006B, 0x0327},
-{ 0x0139, 0x004C, 0x0301},
-{ 0x013A, 0x006C, 0x0301},
-{ 0x013B, 0x004C, 0x0327},
-{ 0x013C, 0x006C, 0x0327},
-{ 0x013D, 0x004C, 0x030C},
-{ 0x013E, 0x006C, 0x030C},
-{ 0x0143, 0x004E, 0x0301},
-{ 0x0144, 0x006E, 0x0301},
-{ 0x0145, 0x004E, 0x0327},
-{ 0x0146, 0x006E, 0x0327},
-{ 0x0147, 0x004E, 0x030C},
-{ 0x0148, 0x006E, 0x030C},
-{ 0x014C, 0x004F, 0x0304},
-{ 0x014D, 0x006F, 0x0304},
-{ 0x014E, 0x004F, 0x0306},
-{ 0x014F, 0x006F, 0x0306},
-{ 0x0150, 0x004F, 0x030B},
-{ 0x0151, 0x006F, 0x030B},
-{ 0x0154, 0x0052, 0x0301},
-{ 0x0155, 0x0072, 0x0301},
-{ 0x0156, 0x0052, 0x0327},
-{ 0x0157, 0x0072, 0x0327},
-{ 0x0158, 0x0052, 0x030C},
-{ 0x0159, 0x0072, 0x030C},
-{ 0x015A, 0x0053, 0x0301},
-{ 0x015B, 0x0073, 0x0301},
-{ 0x015C, 0x0053, 0x0302},
-{ 0x015D, 0x0073, 0x0302},
-{ 0x015E, 0x0053, 0x0327},
-{ 0x015F, 0x0073, 0x0327},
-{ 0x0160, 0x0053, 0x030C},
-{ 0x0161, 0x0073, 0x030C},
-{ 0x0162, 0x0054, 0x0327},
-{ 0x0163, 0x0074, 0x0327},
-{ 0x0164, 0x0054, 0x030C},
-{ 0x0165, 0x0074, 0x030C},
-{ 0x0168, 0x0055, 0x0303},
-{ 0x0169, 0x0075, 0x0303},
-{ 0x016A, 0x0055, 0x0304},
-{ 0x016B, 0x0075, 0x0304},
-{ 0x016C, 0x0055, 0x0306},
-{ 0x016D, 0x0075, 0x0306},
-{ 0x016E, 0x0055, 0x030A},
-{ 0x016F, 0x0075, 0x030A},
-{ 0x0170, 0x0055, 0x030B},
-{ 0x0171, 0x0075, 0x030B},
-{ 0x0172, 0x0055, 0x0328},
-{ 0x0173, 0x0075, 0x0328},
-{ 0x0174, 0x0057, 0x0302},
-{ 0x0175, 0x0077, 0x0302},
-{ 0x0176, 0x0059, 0x0302},
-{ 0x0177, 0x0079, 0x0302},
-{ 0x0178, 0x0059, 0x0308},
-{ 0x0179, 0x005A, 0x0301},
-{ 0x017A, 0x007A, 0x0301},
-{ 0x017B, 0x005A, 0x0307},
-{ 0x017C, 0x007A, 0x0307},
-{ 0x017D, 0x005A, 0x030C},
-{ 0x017E, 0x007A, 0x030C},
-{ 0x01A0, 0x004F, 0x031B},
-{ 0x01A1, 0x006F, 0x031B},
-{ 0x01AF, 0x0055, 0x031B},
-{ 0x01B0, 0x0075, 0x031B},
-{ 0x01CD, 0x0041, 0x030C},
-{ 0x01CE, 0x0061, 0x030C},
-{ 0x01CF, 0x0049, 0x030C},
-{ 0x01D0, 0x0069, 0x030C},
-{ 0x01D1, 0x004F, 0x030C},
-{ 0x01D2, 0x006F, 0x030C},
-{ 0x01D3, 0x0055, 0x030C},
-{ 0x01D4, 0x0075, 0x030C},
-{ 0x01D5, 0x00DC, 0x0304},
-{ 0x01D6, 0x00FC, 0x0304},
-{ 0x01D7, 0x00DC, 0x0301},
-{ 0x01D8, 0x00FC, 0x0301},
-{ 0x01D9, 0x00DC, 0x030C},
-{ 0x01DA, 0x00FC, 0x030C},
-{ 0x01DB, 0x00DC, 0x0300},
-{ 0x01DC, 0x00FC, 0x0300},
-{ 0x01DE, 0x00C4, 0x0304},
-{ 0x01DF, 0x00E4, 0x0304},
-{ 0x01E0, 0x0226, 0x0304},
-{ 0x01E1, 0x0227, 0x0304},
-{ 0x01E2, 0x00C6, 0x0304},
-{ 0x01E3, 0x00E6, 0x0304},
-{ 0x01E6, 0x0047, 0x030C},
-{ 0x01E7, 0x0067, 0x030C},
-{ 0x01E8, 0x004B, 0x030C},
-{ 0x01E9, 0x006B, 0x030C},
-{ 0x01EA, 0x004F, 0x0328},
-{ 0x01EB, 0x006F, 0x0328},
-{ 0x01EC, 0x01EA, 0x0304},
-{ 0x01ED, 0x01EB, 0x0304},
-{ 0x01EE, 0x01B7, 0x030C},
-{ 0x01EF, 0x0292, 0x030C},
-{ 0x01F0, 0x006A, 0x030C},
-{ 0x01F4, 0x0047, 0x0301},
-{ 0x01F5, 0x0067, 0x0301},
-{ 0x01F8, 0x004E, 0x0300},
-{ 0x01F9, 0x006E, 0x0300},
-{ 0x01FA, 0x00C5, 0x0301},
-{ 0x01FB, 0x00E5, 0x0301},
-{ 0x01FC, 0x00C6, 0x0301},
-{ 0x01FD, 0x00E6, 0x0301},
-{ 0x01FE, 0x00D8, 0x0301},
-{ 0x01FF, 0x00F8, 0x0301},
-{ 0x0200, 0x0041, 0x030F},
-{ 0x0201, 0x0061, 0x030F},
-{ 0x0202, 0x0041, 0x0311},
-{ 0x0203, 0x0061, 0x0311},
-{ 0x0204, 0x0045, 0x030F},
-{ 0x0205, 0x0065, 0x030F},
-{ 0x0206, 0x0045, 0x0311},
-{ 0x0207, 0x0065, 0x0311},
-{ 0x0208, 0x0049, 0x030F},
-{ 0x0209, 0x0069, 0x030F},
-{ 0x020A, 0x0049, 0x0311},
-{ 0x020B, 0x0069, 0x0311},
-{ 0x020C, 0x004F, 0x030F},
-{ 0x020D, 0x006F, 0x030F},
-{ 0x020E, 0x004F, 0x0311},
-{ 0x020F, 0x006F, 0x0311},
-{ 0x0210, 0x0052, 0x030F},
-{ 0x0211, 0x0072, 0x030F},
-{ 0x0212, 0x0052, 0x0311},
-{ 0x0213, 0x0072, 0x0311},
-{ 0x0214, 0x0055, 0x030F},
-{ 0x0215, 0x0075, 0x030F},
-{ 0x0216, 0x0055, 0x0311},
-{ 0x0217, 0x0075, 0x0311},
-{ 0x0218, 0x0053, 0x0326},
-{ 0x0219, 0x0073, 0x0326},
-{ 0x021A, 0x0054, 0x0326},
-{ 0x021B, 0x0074, 0x0326},
-{ 0x021E, 0x0048, 0x030C},
-{ 0x021F, 0x0068, 0x030C},
-{ 0x0226, 0x0041, 0x0307},
-{ 0x0227, 0x0061, 0x0307},
-{ 0x0228, 0x0045, 0x0327},
-{ 0x0229, 0x0065, 0x0327},
-{ 0x022A, 0x00D6, 0x0304},
-{ 0x022B, 0x00F6, 0x0304},
-{ 0x022C, 0x00D5, 0x0304},
-{ 0x022D, 0x00F5, 0x0304},
-{ 0x022E, 0x004F, 0x0307},
-{ 0x022F, 0x006F, 0x0307},
-{ 0x0230, 0x022E, 0x0304},
-{ 0x0231, 0x022F, 0x0304},
-{ 0x0232, 0x0059, 0x0304},
-{ 0x0233, 0x0079, 0x0304},
-{ 0x0344, 0x0308, 0x0301},
-{ 0x0385, 0x00A8, 0x0301},
-{ 0x0386, 0x0391, 0x0301},
-{ 0x0388, 0x0395, 0x0301},
-{ 0x0389, 0x0397, 0x0301},
-{ 0x038A, 0x0399, 0x0301},
-{ 0x038C, 0x039F, 0x0301},
-{ 0x038E, 0x03A5, 0x0301},
-{ 0x038F, 0x03A9, 0x0301},
-{ 0x0390, 0x03CA, 0x0301},
-{ 0x03AA, 0x0399, 0x0308},
-{ 0x03AB, 0x03A5, 0x0308},
-{ 0x03AC, 0x03B1, 0x0301},
-{ 0x03AD, 0x03B5, 0x0301},
-{ 0x03AE, 0x03B7, 0x0301},
-{ 0x03AF, 0x03B9, 0x0301},
-{ 0x03B0, 0x03CB, 0x0301},
-{ 0x03CA, 0x03B9, 0x0308},
-{ 0x03CB, 0x03C5, 0x0308},
-{ 0x03CC, 0x03BF, 0x0301},
-{ 0x03CD, 0x03C5, 0x0301},
-{ 0x03CE, 0x03C9, 0x0301},
-{ 0x03D3, 0x03D2, 0x0301},
-{ 0x03D4, 0x03D2, 0x0308},
-{ 0x0400, 0x0415, 0x0300},
-{ 0x0401, 0x0415, 0x0308},
-{ 0x0403, 0x0413, 0x0301},
-{ 0x0407, 0x0406, 0x0308},
-{ 0x040C, 0x041A, 0x0301},
-{ 0x040D, 0x0418, 0x0300},
-{ 0x040E, 0x0423, 0x0306},
-{ 0x0419, 0x0418, 0x0306},
-{ 0x0439, 0x0438, 0x0306},
-{ 0x0450, 0x0435, 0x0300},
-{ 0x0451, 0x0435, 0x0308},
-{ 0x0453, 0x0433, 0x0301},
-{ 0x0457, 0x0456, 0x0308},
-{ 0x045C, 0x043A, 0x0301},
-{ 0x045D, 0x0438, 0x0300},
-{ 0x045E, 0x0443, 0x0306},
-{ 0x0476, 0x0474, 0x030F},
-{ 0x0477, 0x0475, 0x030F},
-{ 0x04C1, 0x0416, 0x0306},
-{ 0x04C2, 0x0436, 0x0306},
-{ 0x04D0, 0x0410, 0x0306},
-{ 0x04D1, 0x0430, 0x0306},
-{ 0x04D2, 0x0410, 0x0308},
-{ 0x04D3, 0x0430, 0x0308},
-{ 0x04D6, 0x0415, 0x0306},
-{ 0x04D7, 0x0435, 0x0306},
-{ 0x04DA, 0x04D8, 0x0308},
-{ 0x04DB, 0x04D9, 0x0308},
-{ 0x04DC, 0x0416, 0x0308},
-{ 0x04DD, 0x0436, 0x0308},
-{ 0x04DE, 0x0417, 0x0308},
-{ 0x04DF, 0x0437, 0x0308},
-{ 0x04E2, 0x0418, 0x0304},
-{ 0x04E3, 0x0438, 0x0304},
-{ 0x04E4, 0x0418, 0x0308},
-{ 0x04E5, 0x0438, 0x0308},
-{ 0x04E6, 0x041E, 0x0308},
-{ 0x04E7, 0x043E, 0x0308},
-{ 0x04EA, 0x04E8, 0x0308},
-{ 0x04EB, 0x04E9, 0x0308},
-{ 0x04EC, 0x042D, 0x0308},
-{ 0x04ED, 0x044D, 0x0308},
-{ 0x04EE, 0x0423, 0x0304},
-{ 0x04EF, 0x0443, 0x0304},
-{ 0x04F0, 0x0423, 0x0308},
-{ 0x04F1, 0x0443, 0x0308},
-{ 0x04F2, 0x0423, 0x030B},
-{ 0x04F3, 0x0443, 0x030B},
-{ 0x04F4, 0x0427, 0x0308},
-{ 0x04F5, 0x0447, 0x0308},
-{ 0x04F8, 0x042B, 0x0308},
-{ 0x04F9, 0x044B, 0x0308},
-{ 0x0622, 0x0627, 0x0653},
-{ 0x0623, 0x0627, 0x0654},
-{ 0x0624, 0x0648, 0x0654},
-{ 0x0625, 0x0627, 0x0655},
-{ 0x0626, 0x064A, 0x0654},
-{ 0x06C0, 0x06D5, 0x0654},
-{ 0x06C2, 0x06C1, 0x0654},
-{ 0x06D3, 0x06D2, 0x0654},
-{ 0x0929, 0x0928, 0x093C},
-{ 0x0931, 0x0930, 0x093C},
-{ 0x0934, 0x0933, 0x093C},
-{ 0x0958, 0x0915, 0x093C},
-{ 0x0959, 0x0916, 0x093C},
-{ 0x095A, 0x0917, 0x093C},
-{ 0x095B, 0x091C, 0x093C},
-{ 0x095C, 0x0921, 0x093C},
-{ 0x095D, 0x0922, 0x093C},
-{ 0x095E, 0x092B, 0x093C},
-{ 0x095F, 0x092F, 0x093C},
-{ 0x09CB, 0x09C7, 0x09BE},
-{ 0x09CC, 0x09C7, 0x09D7},
-{ 0x09DC, 0x09A1, 0x09BC},
-{ 0x09DD, 0x09A2, 0x09BC},
-{ 0x09DF, 0x09AF, 0x09BC},
-{ 0x0A33, 0x0A32, 0x0A3C},
-{ 0x0A36, 0x0A38, 0x0A3C},
-{ 0x0A59, 0x0A16, 0x0A3C},
-{ 0x0A5A, 0x0A17, 0x0A3C},
-{ 0x0A5B, 0x0A1C, 0x0A3C},
-{ 0x0A5E, 0x0A2B, 0x0A3C},
-{ 0x0B48, 0x0B47, 0x0B56},
-{ 0x0B4B, 0x0B47, 0x0B3E},
-{ 0x0B4C, 0x0B47, 0x0B57},
-{ 0x0B5C, 0x0B21, 0x0B3C},
-{ 0x0B5D, 0x0B22, 0x0B3C},
-{ 0x0B94, 0x0B92, 0x0BD7},
-{ 0x0BCA, 0x0BC6, 0x0BBE},
-{ 0x0BCB, 0x0BC7, 0x0BBE},
-{ 0x0BCC, 0x0BC6, 0x0BD7},
-{ 0x0C48, 0x0C46, 0x0C56},
-{ 0x0CC0, 0x0CBF, 0x0CD5},
-{ 0x0CC7, 0x0CC6, 0x0CD5},
-{ 0x0CC8, 0x0CC6, 0x0CD6},
-{ 0x0CCA, 0x0CC6, 0x0CC2},
-{ 0x0CCB, 0x0CCA, 0x0CD5},
-{ 0x0D4A, 0x0D46, 0x0D3E},
-{ 0x0D4B, 0x0D47, 0x0D3E},
-{ 0x0D4C, 0x0D46, 0x0D57},
-{ 0x0DDA, 0x0DD9, 0x0DCA},
-{ 0x0DDC, 0x0DD9, 0x0DCF},
-{ 0x0DDD, 0x0DDC, 0x0DCA},
-{ 0x0DDE, 0x0DD9, 0x0DDF},
-{ 0x0F43, 0x0F42, 0x0FB7},
-{ 0x0F4D, 0x0F4C, 0x0FB7},
-{ 0x0F52, 0x0F51, 0x0FB7},
-{ 0x0F57, 0x0F56, 0x0FB7},
-{ 0x0F5C, 0x0F5B, 0x0FB7},
-{ 0x0F69, 0x0F40, 0x0FB5},
-{ 0x0F73, 0x0F71, 0x0F72},
-{ 0x0F75, 0x0F71, 0x0F74},
-{ 0x0F76, 0x0FB2, 0x0F80},
-{ 0x0F78, 0x0FB3, 0x0F80},
-{ 0x0F81, 0x0F71, 0x0F80},
-{ 0x0F93, 0x0F92, 0x0FB7},
-{ 0x0F9D, 0x0F9C, 0x0FB7},
-{ 0x0FA2, 0x0FA1, 0x0FB7},
-{ 0x0FA7, 0x0FA6, 0x0FB7},
-{ 0x0FAC, 0x0FAB, 0x0FB7},
-{ 0x0FB9, 0x0F90, 0x0FB5},
-{ 0x1026, 0x1025, 0x102E},
-{ 0x1E00, 0x0041, 0x0325},
-{ 0x1E01, 0x0061, 0x0325},
-{ 0x1E02, 0x0042, 0x0307},
-{ 0x1E03, 0x0062, 0x0307},
-{ 0x1E04, 0x0042, 0x0323},
-{ 0x1E05, 0x0062, 0x0323},
-{ 0x1E06, 0x0042, 0x0331},
-{ 0x1E07, 0x0062, 0x0331},
-{ 0x1E08, 0x00C7, 0x0301},
-{ 0x1E09, 0x00E7, 0x0301},
-{ 0x1E0A, 0x0044, 0x0307},
-{ 0x1E0B, 0x0064, 0x0307},
-{ 0x1E0C, 0x0044, 0x0323},
-{ 0x1E0D, 0x0064, 0x0323},
-{ 0x1E0E, 0x0044, 0x0331},
-{ 0x1E0F, 0x0064, 0x0331},
-{ 0x1E10, 0x0044, 0x0327},
-{ 0x1E11, 0x0064, 0x0327},
-{ 0x1E12, 0x0044, 0x032D},
-{ 0x1E13, 0x0064, 0x032D},
-{ 0x1E14, 0x0112, 0x0300},
-{ 0x1E15, 0x0113, 0x0300},
-{ 0x1E16, 0x0112, 0x0301},
-{ 0x1E17, 0x0113, 0x0301},
-{ 0x1E18, 0x0045, 0x032D},
-{ 0x1E19, 0x0065, 0x032D},
-{ 0x1E1A, 0x0045, 0x0330},
-{ 0x1E1B, 0x0065, 0x0330},
-{ 0x1E1C, 0x0228, 0x0306},
-{ 0x1E1D, 0x0229, 0x0306},
-{ 0x1E1E, 0x0046, 0x0307},
-{ 0x1E1F, 0x0066, 0x0307},
-{ 0x1E20, 0x0047, 0x0304},
-{ 0x1E21, 0x0067, 0x0304},
-{ 0x1E22, 0x0048, 0x0307},
-{ 0x1E23, 0x0068, 0x0307},
-{ 0x1E24, 0x0048, 0x0323},
-{ 0x1E25, 0x0068, 0x0323},
-{ 0x1E26, 0x0048, 0x0308},
-{ 0x1E27, 0x0068, 0x0308},
-{ 0x1E28, 0x0048, 0x0327},
-{ 0x1E29, 0x0068, 0x0327},
-{ 0x1E2A, 0x0048, 0x032E},
-{ 0x1E2B, 0x0068, 0x032E},
-{ 0x1E2C, 0x0049, 0x0330},
-{ 0x1E2D, 0x0069, 0x0330},
-{ 0x1E2E, 0x00CF, 0x0301},
-{ 0x1E2F, 0x00EF, 0x0301},
-{ 0x1E30, 0x004B, 0x0301},
-{ 0x1E31, 0x006B, 0x0301},
-{ 0x1E32, 0x004B, 0x0323},
-{ 0x1E33, 0x006B, 0x0323},
-{ 0x1E34, 0x004B, 0x0331},
-{ 0x1E35, 0x006B, 0x0331},
-{ 0x1E36, 0x004C, 0x0323},
-{ 0x1E37, 0x006C, 0x0323},
-{ 0x1E38, 0x1E36, 0x0304},
-{ 0x1E39, 0x1E37, 0x0304},
-{ 0x1E3A, 0x004C, 0x0331},
-{ 0x1E3B, 0x006C, 0x0331},
-{ 0x1E3C, 0x004C, 0x032D},
-{ 0x1E3D, 0x006C, 0x032D},
-{ 0x1E3E, 0x004D, 0x0301},
-{ 0x1E3F, 0x006D, 0x0301},
-{ 0x1E40, 0x004D, 0x0307},
-{ 0x1E41, 0x006D, 0x0307},
-{ 0x1E42, 0x004D, 0x0323},
-{ 0x1E43, 0x006D, 0x0323},
-{ 0x1E44, 0x004E, 0x0307},
-{ 0x1E45, 0x006E, 0x0307},
-{ 0x1E46, 0x004E, 0x0323},
-{ 0x1E47, 0x006E, 0x0323},
-{ 0x1E48, 0x004E, 0x0331},
-{ 0x1E49, 0x006E, 0x0331},
-{ 0x1E4A, 0x004E, 0x032D},
-{ 0x1E4B, 0x006E, 0x032D},
-{ 0x1E4C, 0x00D5, 0x0301},
-{ 0x1E4D, 0x00F5, 0x0301},
-{ 0x1E4E, 0x00D5, 0x0308},
-{ 0x1E4F, 0x00F5, 0x0308},
-{ 0x1E50, 0x014C, 0x0300},
-{ 0x1E51, 0x014D, 0x0300},
-{ 0x1E52, 0x014C, 0x0301},
-{ 0x1E53, 0x014D, 0x0301},
-{ 0x1E54, 0x0050, 0x0301},
-{ 0x1E55, 0x0070, 0x0301},
-{ 0x1E56, 0x0050, 0x0307},
-{ 0x1E57, 0x0070, 0x0307},
-{ 0x1E58, 0x0052, 0x0307},
-{ 0x1E59, 0x0072, 0x0307},
-{ 0x1E5A, 0x0052, 0x0323},
-{ 0x1E5B, 0x0072, 0x0323},
-{ 0x1E5C, 0x1E5A, 0x0304},
-{ 0x1E5D, 0x1E5B, 0x0304},
-{ 0x1E5E, 0x0052, 0x0331},
-{ 0x1E5F, 0x0072, 0x0331},
-{ 0x1E60, 0x0053, 0x0307},
-{ 0x1E61, 0x0073, 0x0307},
-{ 0x1E62, 0x0053, 0x0323},
-{ 0x1E63, 0x0073, 0x0323},
-{ 0x1E64, 0x015A, 0x0307},
-{ 0x1E65, 0x015B, 0x0307},
-{ 0x1E66, 0x0160, 0x0307},
-{ 0x1E67, 0x0161, 0x0307},
-{ 0x1E68, 0x1E62, 0x0307},
-{ 0x1E69, 0x1E63, 0x0307},
-{ 0x1E6A, 0x0054, 0x0307},
-{ 0x1E6B, 0x0074, 0x0307},
-{ 0x1E6C, 0x0054, 0x0323},
-{ 0x1E6D, 0x0074, 0x0323},
-{ 0x1E6E, 0x0054, 0x0331},
-{ 0x1E6F, 0x0074, 0x0331},
-{ 0x1E70, 0x0054, 0x032D},
-{ 0x1E71, 0x0074, 0x032D},
-{ 0x1E72, 0x0055, 0x0324},
-{ 0x1E73, 0x0075, 0x0324},
-{ 0x1E74, 0x0055, 0x0330},
-{ 0x1E75, 0x0075, 0x0330},
-{ 0x1E76, 0x0055, 0x032D},
-{ 0x1E77, 0x0075, 0x032D},
-{ 0x1E78, 0x0168, 0x0301},
-{ 0x1E79, 0x0169, 0x0301},
-{ 0x1E7A, 0x016A, 0x0308},
-{ 0x1E7B, 0x016B, 0x0308},
-{ 0x1E7C, 0x0056, 0x0303},
-{ 0x1E7D, 0x0076, 0x0303},
-{ 0x1E7E, 0x0056, 0x0323},
-{ 0x1E7F, 0x0076, 0x0323},
-{ 0x1E80, 0x0057, 0x0300},
-{ 0x1E81, 0x0077, 0x0300},
-{ 0x1E82, 0x0057, 0x0301},
-{ 0x1E83, 0x0077, 0x0301},
-{ 0x1E84, 0x0057, 0x0308},
-{ 0x1E85, 0x0077, 0x0308},
-{ 0x1E86, 0x0057, 0x0307},
-{ 0x1E87, 0x0077, 0x0307},
-{ 0x1E88, 0x0057, 0x0323},
-{ 0x1E89, 0x0077, 0x0323},
-{ 0x1E8A, 0x0058, 0x0307},
-{ 0x1E8B, 0x0078, 0x0307},
-{ 0x1E8C, 0x0058, 0x0308},
-{ 0x1E8D, 0x0078, 0x0308},
-{ 0x1E8E, 0x0059, 0x0307},
-{ 0x1E8F, 0x0079, 0x0307},
-{ 0x1E90, 0x005A, 0x0302},
-{ 0x1E91, 0x007A, 0x0302},
-{ 0x1E92, 0x005A, 0x0323},
-{ 0x1E93, 0x007A, 0x0323},
-{ 0x1E94, 0x005A, 0x0331},
-{ 0x1E95, 0x007A, 0x0331},
-{ 0x1E96, 0x0068, 0x0331},
-{ 0x1E97, 0x0074, 0x0308},
-{ 0x1E98, 0x0077, 0x030A},
-{ 0x1E99, 0x0079, 0x030A},
-{ 0x1E9B, 0x017F, 0x0307},
-{ 0x1EA0, 0x0041, 0x0323},
-{ 0x1EA1, 0x0061, 0x0323},
-{ 0x1EA2, 0x0041, 0x0309},
-{ 0x1EA3, 0x0061, 0x0309},
-{ 0x1EA4, 0x00C2, 0x0301},
-{ 0x1EA5, 0x00E2, 0x0301},
-{ 0x1EA6, 0x00C2, 0x0300},
-{ 0x1EA7, 0x00E2, 0x0300},
-{ 0x1EA8, 0x00C2, 0x0309},
-{ 0x1EA9, 0x00E2, 0x0309},
-{ 0x1EAA, 0x00C2, 0x0303},
-{ 0x1EAB, 0x00E2, 0x0303},
-{ 0x1EAC, 0x1EA0, 0x0302},
-{ 0x1EAD, 0x1EA1, 0x0302},
-{ 0x1EAE, 0x0102, 0x0301},
-{ 0x1EAF, 0x0103, 0x0301},
-{ 0x1EB0, 0x0102, 0x0300},
-{ 0x1EB1, 0x0103, 0x0300},
-{ 0x1EB2, 0x0102, 0x0309},
-{ 0x1EB3, 0x0103, 0x0309},
-{ 0x1EB4, 0x0102, 0x0303},
-{ 0x1EB5, 0x0103, 0x0303},
-{ 0x1EB6, 0x1EA0, 0x0306},
-{ 0x1EB7, 0x1EA1, 0x0306},
-{ 0x1EB8, 0x0045, 0x0323},
-{ 0x1EB9, 0x0065, 0x0323},
-{ 0x1EBA, 0x0045, 0x0309},
-{ 0x1EBB, 0x0065, 0x0309},
-{ 0x1EBC, 0x0045, 0x0303},
-{ 0x1EBD, 0x0065, 0x0303},
-{ 0x1EBE, 0x00CA, 0x0301},
-{ 0x1EBF, 0x00EA, 0x0301},
-{ 0x1EC0, 0x00CA, 0x0300},
-{ 0x1EC1, 0x00EA, 0x0300},
-{ 0x1EC2, 0x00CA, 0x0309},
-{ 0x1EC3, 0x00EA, 0x0309},
-{ 0x1EC4, 0x00CA, 0x0303},
-{ 0x1EC5, 0x00EA, 0x0303},
-{ 0x1EC6, 0x1EB8, 0x0302},
-{ 0x1EC7, 0x1EB9, 0x0302},
-{ 0x1EC8, 0x0049, 0x0309},
-{ 0x1EC9, 0x0069, 0x0309},
-{ 0x1ECA, 0x0049, 0x0323},
-{ 0x1ECB, 0x0069, 0x0323},
-{ 0x1ECC, 0x004F, 0x0323},
-{ 0x1ECD, 0x006F, 0x0323},
-{ 0x1ECE, 0x004F, 0x0309},
-{ 0x1ECF, 0x006F, 0x0309},
-{ 0x1ED0, 0x00D4, 0x0301},
-{ 0x1ED1, 0x00F4, 0x0301},
-{ 0x1ED2, 0x00D4, 0x0300},
-{ 0x1ED3, 0x00F4, 0x0300},
-{ 0x1ED4, 0x00D4, 0x0309},
-{ 0x1ED5, 0x00F4, 0x0309},
-{ 0x1ED6, 0x00D4, 0x0303},
-{ 0x1ED7, 0x00F4, 0x0303},
-{ 0x1ED8, 0x1ECC, 0x0302},
-{ 0x1ED9, 0x1ECD, 0x0302},
-{ 0x1EDA, 0x01A0, 0x0301},
-{ 0x1EDB, 0x01A1, 0x0301},
-{ 0x1EDC, 0x01A0, 0x0300},
-{ 0x1EDD, 0x01A1, 0x0300},
-{ 0x1EDE, 0x01A0, 0x0309},
-{ 0x1EDF, 0x01A1, 0x0309},
-{ 0x1EE0, 0x01A0, 0x0303},
-{ 0x1EE1, 0x01A1, 0x0303},
-{ 0x1EE2, 0x01A0, 0x0323},
-{ 0x1EE3, 0x01A1, 0x0323},
-{ 0x1EE4, 0x0055, 0x0323},
-{ 0x1EE5, 0x0075, 0x0323},
-{ 0x1EE6, 0x0055, 0x0309},
-{ 0x1EE7, 0x0075, 0x0309},
-{ 0x1EE8, 0x01AF, 0x0301},
-{ 0x1EE9, 0x01B0, 0x0301},
-{ 0x1EEA, 0x01AF, 0x0300},
-{ 0x1EEB, 0x01B0, 0x0300},
-{ 0x1EEC, 0x01AF, 0x0309},
-{ 0x1EED, 0x01B0, 0x0309},
-{ 0x1EEE, 0x01AF, 0x0303},
-{ 0x1EEF, 0x01B0, 0x0303},
-{ 0x1EF0, 0x01AF, 0x0323},
-{ 0x1EF1, 0x01B0, 0x0323},
-{ 0x1EF2, 0x0059, 0x0300},
-{ 0x1EF3, 0x0079, 0x0300},
-{ 0x1EF4, 0x0059, 0x0323},
-{ 0x1EF5, 0x0079, 0x0323},
-{ 0x1EF6, 0x0059, 0x0309},
-{ 0x1EF7, 0x0079, 0x0309},
-{ 0x1EF8, 0x0059, 0x0303},
-{ 0x1EF9, 0x0079, 0x0303},
-{ 0x1F00, 0x03B1, 0x0313},
-{ 0x1F01, 0x03B1, 0x0314},
-{ 0x1F02, 0x1F00, 0x0300},
-{ 0x1F03, 0x1F01, 0x0300},
-{ 0x1F04, 0x1F00, 0x0301},
-{ 0x1F05, 0x1F01, 0x0301},
-{ 0x1F06, 0x1F00, 0x0342},
-{ 0x1F07, 0x1F01, 0x0342},
-{ 0x1F08, 0x0391, 0x0313},
-{ 0x1F09, 0x0391, 0x0314},
-{ 0x1F0A, 0x1F08, 0x0300},
-{ 0x1F0B, 0x1F09, 0x0300},
-{ 0x1F0C, 0x1F08, 0x0301},
-{ 0x1F0D, 0x1F09, 0x0301},
-{ 0x1F0E, 0x1F08, 0x0342},
-{ 0x1F0F, 0x1F09, 0x0342},
-{ 0x1F10, 0x03B5, 0x0313},
-{ 0x1F11, 0x03B5, 0x0314},
-{ 0x1F12, 0x1F10, 0x0300},
-{ 0x1F13, 0x1F11, 0x0300},
-{ 0x1F14, 0x1F10, 0x0301},
-{ 0x1F15, 0x1F11, 0x0301},
-{ 0x1F18, 0x0395, 0x0313},
-{ 0x1F19, 0x0395, 0x0314},
-{ 0x1F1A, 0x1F18, 0x0300},
-{ 0x1F1B, 0x1F19, 0x0300},
-{ 0x1F1C, 0x1F18, 0x0301},
-{ 0x1F1D, 0x1F19, 0x0301},
-{ 0x1F20, 0x03B7, 0x0313},
-{ 0x1F21, 0x03B7, 0x0314},
-{ 0x1F22, 0x1F20, 0x0300},
-{ 0x1F23, 0x1F21, 0x0300},
-{ 0x1F24, 0x1F20, 0x0301},
-{ 0x1F25, 0x1F21, 0x0301},
-{ 0x1F26, 0x1F20, 0x0342},
-{ 0x1F27, 0x1F21, 0x0342},
-{ 0x1F28, 0x0397, 0x0313},
-{ 0x1F29, 0x0397, 0x0314},
-{ 0x1F2A, 0x1F28, 0x0300},
-{ 0x1F2B, 0x1F29, 0x0300},
-{ 0x1F2C, 0x1F28, 0x0301},
-{ 0x1F2D, 0x1F29, 0x0301},
-{ 0x1F2E, 0x1F28, 0x0342},
-{ 0x1F2F, 0x1F29, 0x0342},
-{ 0x1F30, 0x03B9, 0x0313},
-{ 0x1F31, 0x03B9, 0x0314},
-{ 0x1F32, 0x1F30, 0x0300},
-{ 0x1F33, 0x1F31, 0x0300},
-{ 0x1F34, 0x1F30, 0x0301},
-{ 0x1F35, 0x1F31, 0x0301},
-{ 0x1F36, 0x1F30, 0x0342},
-{ 0x1F37, 0x1F31, 0x0342},
-{ 0x1F38, 0x0399, 0x0313},
-{ 0x1F39, 0x0399, 0x0314},
-{ 0x1F3A, 0x1F38, 0x0300},
-{ 0x1F3B, 0x1F39, 0x0300},
-{ 0x1F3C, 0x1F38, 0x0301},
-{ 0x1F3D, 0x1F39, 0x0301},
-{ 0x1F3E, 0x1F38, 0x0342},
-{ 0x1F3F, 0x1F39, 0x0342},
-{ 0x1F40, 0x03BF, 0x0313},
-{ 0x1F41, 0x03BF, 0x0314},
-{ 0x1F42, 0x1F40, 0x0300},
-{ 0x1F43, 0x1F41, 0x0300},
-{ 0x1F44, 0x1F40, 0x0301},
-{ 0x1F45, 0x1F41, 0x0301},
-{ 0x1F48, 0x039F, 0x0313},
-{ 0x1F49, 0x039F, 0x0314},
-{ 0x1F4A, 0x1F48, 0x0300},
-{ 0x1F4B, 0x1F49, 0x0300},
-{ 0x1F4C, 0x1F48, 0x0301},
-{ 0x1F4D, 0x1F49, 0x0301},
-{ 0x1F50, 0x03C5, 0x0313},
-{ 0x1F51, 0x03C5, 0x0314},
-{ 0x1F52, 0x1F50, 0x0300},
-{ 0x1F53, 0x1F51, 0x0300},
-{ 0x1F54, 0x1F50, 0x0301},
-{ 0x1F55, 0x1F51, 0x0301},
-{ 0x1F56, 0x1F50, 0x0342},
-{ 0x1F57, 0x1F51, 0x0342},
-{ 0x1F59, 0x03A5, 0x0314},
-{ 0x1F5B, 0x1F59, 0x0300},
-{ 0x1F5D, 0x1F59, 0x0301},
-{ 0x1F5F, 0x1F59, 0x0342},
-{ 0x1F60, 0x03C9, 0x0313},
-{ 0x1F61, 0x03C9, 0x0314},
-{ 0x1F62, 0x1F60, 0x0300},
-{ 0x1F63, 0x1F61, 0x0300},
-{ 0x1F64, 0x1F60, 0x0301},
-{ 0x1F65, 0x1F61, 0x0301},
-{ 0x1F66, 0x1F60, 0x0342},
-{ 0x1F67, 0x1F61, 0x0342},
-{ 0x1F68, 0x03A9, 0x0313},
-{ 0x1F69, 0x03A9, 0x0314},
-{ 0x1F6A, 0x1F68, 0x0300},
-{ 0x1F6B, 0x1F69, 0x0300},
-{ 0x1F6C, 0x1F68, 0x0301},
-{ 0x1F6D, 0x1F69, 0x0301},
-{ 0x1F6E, 0x1F68, 0x0342},
-{ 0x1F6F, 0x1F69, 0x0342},
-{ 0x1F70, 0x03B1, 0x0300},
-{ 0x1F72, 0x03B5, 0x0300},
-{ 0x1F74, 0x03B7, 0x0300},
-{ 0x1F76, 0x03B9, 0x0300},
-{ 0x1F78, 0x03BF, 0x0300},
-{ 0x1F7A, 0x03C5, 0x0300},
-{ 0x1F7C, 0x03C9, 0x0300},
-{ 0x1F80, 0x1F00, 0x0345},
-{ 0x1F81, 0x1F01, 0x0345},
-{ 0x1F82, 0x1F02, 0x0345},
-{ 0x1F83, 0x1F03, 0x0345},
-{ 0x1F84, 0x1F04, 0x0345},
-{ 0x1F85, 0x1F05, 0x0345},
-{ 0x1F86, 0x1F06, 0x0345},
-{ 0x1F87, 0x1F07, 0x0345},
-{ 0x1F88, 0x1F08, 0x0345},
-{ 0x1F89, 0x1F09, 0x0345},
-{ 0x1F8A, 0x1F0A, 0x0345},
-{ 0x1F8B, 0x1F0B, 0x0345},
-{ 0x1F8C, 0x1F0C, 0x0345},
-{ 0x1F8D, 0x1F0D, 0x0345},
-{ 0x1F8E, 0x1F0E, 0x0345},
-{ 0x1F8F, 0x1F0F, 0x0345},
-{ 0x1F90, 0x1F20, 0x0345},
-{ 0x1F91, 0x1F21, 0x0345},
-{ 0x1F92, 0x1F22, 0x0345},
-{ 0x1F93, 0x1F23, 0x0345},
-{ 0x1F94, 0x1F24, 0x0345},
-{ 0x1F95, 0x1F25, 0x0345},
-{ 0x1F96, 0x1F26, 0x0345},
-{ 0x1F97, 0x1F27, 0x0345},
-{ 0x1F98, 0x1F28, 0x0345},
-{ 0x1F99, 0x1F29, 0x0345},
-{ 0x1F9A, 0x1F2A, 0x0345},
-{ 0x1F9B, 0x1F2B, 0x0345},
-{ 0x1F9C, 0x1F2C, 0x0345},
-{ 0x1F9D, 0x1F2D, 0x0345},
-{ 0x1F9E, 0x1F2E, 0x0345},
-{ 0x1F9F, 0x1F2F, 0x0345},
-{ 0x1FA0, 0x1F60, 0x0345},
-{ 0x1FA1, 0x1F61, 0x0345},
-{ 0x1FA2, 0x1F62, 0x0345},
-{ 0x1FA3, 0x1F63, 0x0345},
-{ 0x1FA4, 0x1F64, 0x0345},
-{ 0x1FA5, 0x1F65, 0x0345},
-{ 0x1FA6, 0x1F66, 0x0345},
-{ 0x1FA7, 0x1F67, 0x0345},
-{ 0x1FA8, 0x1F68, 0x0345},
-{ 0x1FA9, 0x1F69, 0x0345},
-{ 0x1FAA, 0x1F6A, 0x0345},
-{ 0x1FAB, 0x1F6B, 0x0345},
-{ 0x1FAC, 0x1F6C, 0x0345},
-{ 0x1FAD, 0x1F6D, 0x0345},
-{ 0x1FAE, 0x1F6E, 0x0345},
-{ 0x1FAF, 0x1F6F, 0x0345},
-{ 0x1FB0, 0x03B1, 0x0306},
-{ 0x1FB1, 0x03B1, 0x0304},
-{ 0x1FB2, 0x1F70, 0x0345},
-{ 0x1FB3, 0x03B1, 0x0345},
-{ 0x1FB4, 0x03AC, 0x0345},
-{ 0x1FB6, 0x03B1, 0x0342},
-{ 0x1FB7, 0x1FB6, 0x0345},
-{ 0x1FB8, 0x0391, 0x0306},
-{ 0x1FB9, 0x0391, 0x0304},
-{ 0x1FBA, 0x0391, 0x0300},
-{ 0x1FBC, 0x0391, 0x0345},
-{ 0x1FC1, 0x00A8, 0x0342},
-{ 0x1FC2, 0x1F74, 0x0345},
-{ 0x1FC3, 0x03B7, 0x0345},
-{ 0x1FC4, 0x03AE, 0x0345},
-{ 0x1FC6, 0x03B7, 0x0342},
-{ 0x1FC7, 0x1FC6, 0x0345},
-{ 0x1FC8, 0x0395, 0x0300},
-{ 0x1FCA, 0x0397, 0x0300},
-{ 0x1FCC, 0x0397, 0x0345},
-{ 0x1FCD, 0x1FBF, 0x0300},
-{ 0x1FCE, 0x1FBF, 0x0301},
-{ 0x1FCF, 0x1FBF, 0x0342},
-{ 0x1FD0, 0x03B9, 0x0306},
-{ 0x1FD1, 0x03B9, 0x0304},
-{ 0x1FD2, 0x03CA, 0x0300},
-{ 0x1FD6, 0x03B9, 0x0342},
-{ 0x1FD7, 0x03CA, 0x0342},
-{ 0x1FD8, 0x0399, 0x0306},
-{ 0x1FD9, 0x0399, 0x0304},
-{ 0x1FDA, 0x0399, 0x0300},
-{ 0x1FDD, 0x1FFE, 0x0300},
-{ 0x1FDE, 0x1FFE, 0x0301},
-{ 0x1FDF, 0x1FFE, 0x0342},
-{ 0x1FE0, 0x03C5, 0x0306},
-{ 0x1FE1, 0x03C5, 0x0304},
-{ 0x1FE2, 0x03CB, 0x0300},
-{ 0x1FE4, 0x03C1, 0x0313},
-{ 0x1FE5, 0x03C1, 0x0314},
-{ 0x1FE6, 0x03C5, 0x0342},
-{ 0x1FE7, 0x03CB, 0x0342},
-{ 0x1FE8, 0x03A5, 0x0306},
-{ 0x1FE9, 0x03A5, 0x0304},
-{ 0x1FEA, 0x03A5, 0x0300},
-{ 0x1FEC, 0x03A1, 0x0314},
-{ 0x1FED, 0x00A8, 0x0300},
-{ 0x1FF2, 0x1F7C, 0x0345},
-{ 0x1FF3, 0x03C9, 0x0345},
-{ 0x1FF4, 0x03CE, 0x0345},
-{ 0x1FF6, 0x03C9, 0x0342},
-{ 0x1FF7, 0x1FF6, 0x0345},
-{ 0x1FF8, 0x039F, 0x0300},
-{ 0x1FFA, 0x03A9, 0x0300},
-{ 0x1FFC, 0x03A9, 0x0345},
-{ 0x219A, 0x2190, 0x0338},
-{ 0x219B, 0x2192, 0x0338},
-{ 0x21AE, 0x2194, 0x0338},
-{ 0x21CD, 0x21D0, 0x0338},
-{ 0x21CE, 0x21D4, 0x0338},
-{ 0x21CF, 0x21D2, 0x0338},
-{ 0x2204, 0x2203, 0x0338},
-{ 0x2209, 0x2208, 0x0338},
-{ 0x220C, 0x220B, 0x0338},
-{ 0x2224, 0x2223, 0x0338},
-{ 0x2226, 0x2225, 0x0338},
-{ 0x2241, 0x223C, 0x0338},
-{ 0x2244, 0x2243, 0x0338},
-{ 0x2247, 0x2245, 0x0338},
-{ 0x2249, 0x2248, 0x0338},
-{ 0x2260, 0x003D, 0x0338},
-{ 0x2262, 0x2261, 0x0338},
-{ 0x226D, 0x224D, 0x0338},
-{ 0x226E, 0x003C, 0x0338},
-{ 0x226F, 0x003E, 0x0338},
-{ 0x2270, 0x2264, 0x0338},
-{ 0x2271, 0x2265, 0x0338},
-{ 0x2274, 0x2272, 0x0338},
-{ 0x2275, 0x2273, 0x0338},
-{ 0x2278, 0x2276, 0x0338},
-{ 0x2279, 0x2277, 0x0338},
-{ 0x2280, 0x227A, 0x0338},
-{ 0x2281, 0x227B, 0x0338},
-{ 0x2284, 0x2282, 0x0338},
-{ 0x2285, 0x2283, 0x0338},
-{ 0x2288, 0x2286, 0x0338},
-{ 0x2289, 0x2287, 0x0338},
-{ 0x22AC, 0x22A2, 0x0338},
-{ 0x22AD, 0x22A8, 0x0338},
-{ 0x22AE, 0x22A9, 0x0338},
-{ 0x22AF, 0x22AB, 0x0338},
-{ 0x22E0, 0x227C, 0x0338},
-{ 0x22E1, 0x227D, 0x0338},
-{ 0x22E2, 0x2291, 0x0338},
-{ 0x22E3, 0x2292, 0x0338},
-{ 0x22EA, 0x22B2, 0x0338},
-{ 0x22EB, 0x22B3, 0x0338},
-{ 0x22EC, 0x22B4, 0x0338},
-{ 0x22ED, 0x22B5, 0x0338},
-{ 0x304C, 0x304B, 0x3099},
-{ 0x304E, 0x304D, 0x3099},
-{ 0x3050, 0x304F, 0x3099},
-{ 0x3052, 0x3051, 0x3099},
-{ 0x3054, 0x3053, 0x3099},
-{ 0x3056, 0x3055, 0x3099},
-{ 0x3058, 0x3057, 0x3099},
-{ 0x305A, 0x3059, 0x3099},
-{ 0x305C, 0x305B, 0x3099},
-{ 0x305E, 0x305D, 0x3099},
-{ 0x3060, 0x305F, 0x3099},
-{ 0x3062, 0x3061, 0x3099},
-{ 0x3065, 0x3064, 0x3099},
-{ 0x3067, 0x3066, 0x3099},
-{ 0x3069, 0x3068, 0x3099},
-{ 0x3070, 0x306F, 0x3099},
-{ 0x3071, 0x306F, 0x309A},
-{ 0x3073, 0x3072, 0x3099},
-{ 0x3074, 0x3072, 0x309A},
-{ 0x3076, 0x3075, 0x3099},
-{ 0x3077, 0x3075, 0x309A},
-{ 0x3079, 0x3078, 0x3099},
-{ 0x307A, 0x3078, 0x309A},
-{ 0x307C, 0x307B, 0x3099},
-{ 0x307D, 0x307B, 0x309A},
-{ 0x3094, 0x3046, 0x3099},
-{ 0x309E, 0x309D, 0x3099},
-{ 0x30AC, 0x30AB, 0x3099},
-{ 0x30AE, 0x30AD, 0x3099},
-{ 0x30B0, 0x30AF, 0x3099},
-{ 0x30B2, 0x30B1, 0x3099},
-{ 0x30B4, 0x30B3, 0x3099},
-{ 0x30B6, 0x30B5, 0x3099},
-{ 0x30B8, 0x30B7, 0x3099},
-{ 0x30BA, 0x30B9, 0x3099},
-{ 0x30BC, 0x30BB, 0x3099},
-{ 0x30BE, 0x30BD, 0x3099},
-{ 0x30C0, 0x30BF, 0x3099},
-{ 0x30C2, 0x30C1, 0x3099},
-{ 0x30C5, 0x30C4, 0x3099},
-{ 0x30C7, 0x30C6, 0x3099},
-{ 0x30C9, 0x30C8, 0x3099},
-{ 0x30D0, 0x30CF, 0x3099},
-{ 0x30D1, 0x30CF, 0x309A},
-{ 0x30D3, 0x30D2, 0x3099},
-{ 0x30D4, 0x30D2, 0x309A},
-{ 0x30D6, 0x30D5, 0x3099},
-{ 0x30D7, 0x30D5, 0x309A},
-{ 0x30D9, 0x30D8, 0x3099},
-{ 0x30DA, 0x30D8, 0x309A},
-{ 0x30DC, 0x30DB, 0x3099},
-{ 0x30DD, 0x30DB, 0x309A},
-{ 0x30F4, 0x30A6, 0x3099},
-{ 0x30F7, 0x30EF, 0x3099},
-{ 0x30F8, 0x30F0, 0x3099},
-{ 0x30F9, 0x30F1, 0x3099},
-{ 0x30FA, 0x30F2, 0x3099},
-{ 0x30FE, 0x30FD, 0x3099},
-{ 0xFB1D, 0x05D9, 0x05B4},
-{ 0xFB1F, 0x05F2, 0x05B7},
-{ 0xFB2A, 0x05E9, 0x05C1},
-{ 0xFB2B, 0x05E9, 0x05C2},
-{ 0xFB2C, 0xFB49, 0x05C1},
-{ 0xFB2D, 0xFB49, 0x05C2},
-{ 0xFB2E, 0x05D0, 0x05B7},
-{ 0xFB2F, 0x05D0, 0x05B8},
-{ 0xFB30, 0x05D0, 0x05BC},
-{ 0xFB31, 0x05D1, 0x05BC},
-{ 0xFB32, 0x05D2, 0x05BC},
-{ 0xFB33, 0x05D3, 0x05BC},
-{ 0xFB34, 0x05D4, 0x05BC},
-{ 0xFB35, 0x05D5, 0x05BC},
-{ 0xFB36, 0x05D6, 0x05BC},
-{ 0xFB38, 0x05D8, 0x05BC},
-{ 0xFB39, 0x05D9, 0x05BC},
-{ 0xFB3A, 0x05DA, 0x05BC},
-{ 0xFB3B, 0x05DB, 0x05BC},
-{ 0xFB3C, 0x05DC, 0x05BC},
-{ 0xFB3E, 0x05DE, 0x05BC},
-{ 0xFB40, 0x05E0, 0x05BC},
-{ 0xFB41, 0x05E1, 0x05BC},
-{ 0xFB43, 0x05E3, 0x05BC},
-{ 0xFB44, 0x05E4, 0x05BC},
-{ 0xFB46, 0x05E6, 0x05BC},
-{ 0xFB47, 0x05E7, 0x05BC},
-{ 0xFB48, 0x05E8, 0x05BC},
-{ 0xFB49, 0x05E9, 0x05BC},
-{ 0xFB4A, 0x05EA, 0x05BC},
-{ 0xFB4B, 0x05D5, 0x05B9},
-{ 0xFB4C, 0x05D1, 0x05BF},
-{ 0xFB4D, 0x05DB, 0x05BF},
-{ 0xFB4E, 0x05E4, 0x05BF},
-};
-
-/* ------------------------ */
-unsigned int do_precomposition(unsigned int base, unsigned int comb) {
-  int min = 0;
-  int max = sizeof(precompositions) / sizeof(precompositions[0]) - 1;
-  int mid;
-  unsigned int sought = (base << 16) | comb, that;
-
-  /* binary search */
-  while (max >= min) {
-    mid = (min + max) / 2;
-    that = (precompositions[mid].base << 16) | (precompositions[mid].comb);
-    if (that < sought) {
-      min = mid + 1;
-    } else if (that > sought) {
-      max = mid - 1;
-    } else {
-      return precompositions[mid].replacement;
-    }
-  }
-  /* no match */
-  return 0;
-}
-
-/* -------------------------- */
-unsigned int do_decomposition(unsigned int base) {
-  int min = 0;
-  int max = sizeof(decompositions) / sizeof(decompositions[0]) - 1;
-  int mid;
-  unsigned int sought = base;
-  unsigned int result, that;
-
-  /* binary search */
-  while (max >= min) {
-    mid = (min + max) / 2;
-    that = decompositions[mid].replacement;
-    if (that < sought) {
-      min = mid + 1;
-    } else if (that > sought) {
-      max = mid - 1;
-    } else {
-      result = (decompositions[mid].base << 16) | (decompositions[mid].comb);
-      return result;
-    }
-  }
-  /* no match */
-  return 0;
-}
index 95a15a8a0e113fe9de59aa7918f16a3fb606ba9b..466be9bb92258ebef348689a81ffcf964dd479ea 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: volume.c,v 1.51.2.5 2003-05-28 04:42:46 didg Exp $
+ * $Id: volume.c,v 1.51.2.6 2003-06-23 10:25:08 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -112,15 +112,17 @@ m=u -> map both ways
 
 #define VOLOPT_POSTEXEC      13  /* postexec command */
 #define VOLOPT_ROOTPOSTEXEC  14  /* root postexec command */
+
+#define VOLOPT_ENCODING      15  /* mac encoding (pre OSX)*/
 #ifdef FORCE_UIDGID
 #warning UIDGID
 #include "uid.h"
 
-#define VOLOPT_FORCEUID  15  /* force uid for username x */
-#define VOLOPT_FORCEGID  16  /* force gid for group x */
-#define VOLOPT_UMASK     17
+#define VOLOPT_FORCEUID  16  /* force uid for username x */
+#define VOLOPT_FORCEGID  17  /* force gid for group x */
+#define VOLOPT_UMASK     18
 #else 
-#define VOLOPT_UMASK     15
+#define VOLOPT_UMASK     16
 #endif /* FORCE_UIDGID */
 
 #define VOLOPT_MAX       (VOLOPT_UMASK +1)
@@ -374,7 +376,8 @@ static void volset(struct vol_option *options, struct vol_option *save,
             free(options[VOLOPT_CODEPAGE].c_value);
         }
         options[VOLOPT_CODEPAGE].c_value = get_codepage_path(nlspath, val + 1);
-
+    } else if (optionok(tmp, "encoding:", val)) {
+        setoption(options, save, VOLOPT_ENCODING, val);
     } else if (optionok(tmp, "veto:", val)) {
         setoption(options, save, VOLOPT_VETO, val);
     } else if (optionok(tmp, "casefold:", val)) {
@@ -567,6 +570,8 @@ static int creatvol(AFPObj *obj, struct passwd *pwd,
         if (options[VOLOPT_VETO].c_value)
             volume->v_veto = strdup(options[VOLOPT_VETO].c_value);
 
+        if (options[VOLOPT_ENCODING].c_value)
+            volume->v_encoding = strdup(options[VOLOPT_ENCODING].c_value);
 #ifdef CNID_DB
         if (options[VOLOPT_DBPATH].c_value)
             volume->v_dbpath = volxlate(obj, NULL, MAXPATHLEN, options[VOLOPT_DBPATH].c_value, pwd, path);
@@ -968,6 +973,7 @@ static void volume_free(struct vol *vol)
     codepage_free(vol);
     free(vol->v_password);
     free(vol->v_veto);
+    free(vol->v_encoding);
 #ifdef CNID_DB
     free(vol->v_dbpath);
 #endif /* CNID_DB */
@@ -1434,7 +1440,7 @@ int               ibuflen, *rbuflen;
 #endif
     struct vol *volume;
     struct dir *dir;
-    int                len, ret, buflen;
+    int                len, ret;
     u_int16_t  bitmap;
 
     ibuf += 2;
@@ -1496,13 +1502,6 @@ int              ibuflen, *rbuflen;
 #endif
     volume->v_dir = volume->v_root = NULL;
 
-#ifdef AFP3x
-    volume->v_utf8toucs2 = (iconv_t)(-1);
-    volume->v_ucs2toutf8 = (iconv_t)(-1);
-    volume->v_mactoutf8  = (iconv_t)(-1);
-    volume->v_ucs2tomac  = (iconv_t)(-1);
-#endif
-
     /* FIXME unix name != mac name */
     if ((dir = dirnew(volume->v_name, volume->v_name) ) == NULL) {
         LOG(log_error, logtype_afpd, "afp_openvol: malloc: %s", strerror(errno) );
@@ -1560,26 +1559,8 @@ int              ibuflen, *rbuflen;
     }
 #endif
 
-#ifdef AFP3x
-    if (vol_utf8(volume)) {
-        if ((iconv_t)(-1) == (volume->v_utf8toucs2 = iconv_open("UCS-2LE", "UTF-8"))) {
-            LOG(log_error, logtype_afpd, "openvol: no UTF8 to UCS-2LE");
-            goto openvol_err;
-        }
-        if ((iconv_t)(-1) == (volume->v_ucs2toutf8 = iconv_open("UTF-8", "UCS-2LE"))) {
-            LOG(log_error, logtype_afpd, "openvol: no UCS-2LE to UTF-8");
-            goto openvol_err;
-        }
-        if ((iconv_t)(-1) == (volume->v_mactoutf8 = iconv_open("UTF-8", "MAC"))) {
-            LOG(log_error, logtype_afpd, "openvol: no MAC to UTF-8");
-            goto openvol_err;
-        }
-        if ((iconv_t)(-1) == (volume->v_ucs2tomac = iconv_open("MAC", "UCS-2LE"))) {
-            LOG(log_error, logtype_afpd, "openvol:  no UCS-2LE to MAC");
-            goto openvol_err;
-        }
-    }
-#endif
+    if ( 0 == ( volume->v_maccharset = add_charset(volume->v_encoding?volume->v_encoding:"MAC")) )
+       volume->v_maccharset = CH_MAC;
 
     ret  = stat_vol(bitmap, volume, rbuf, rbuflen);
     if (ret == AFP_OK) {
@@ -1598,16 +1579,6 @@ int              ibuflen, *rbuflen;
     }
 
 openvol_err:
-#ifdef AFP3x
-    if (volume->v_utf8toucs2 != (iconv_t)(-1))
-        iconv_close(volume->v_utf8toucs2);
-    if (volume->v_ucs2toutf8 != (iconv_t)(-1))
-        iconv_close(volume->v_ucs2toutf8);
-    if (volume->v_mactoutf8  != (iconv_t)(-1))
-        iconv_close(volume->v_mactoutf8);    
-    if (volume->v_ucs2tomac  != (iconv_t)(-1))
-        iconv_close(volume->v_ucs2tomac);
-#endif        
     if (volume->v_dir) {
         dirfree( volume->v_dir );
         volume->v_dir = volume->v_root = NULL;
@@ -1638,17 +1609,6 @@ static void closevol(struct vol  *vol)
     vol->v_db = NULL;
 #endif /* CNID_DB */
 
-#ifdef AFP3x
-    if (vol->v_utf8toucs2 != (iconv_t)(-1))
-        iconv_close(vol->v_utf8toucs2);
-    if (vol->v_ucs2toutf8 != (iconv_t)(-1))
-        iconv_close(vol->v_ucs2toutf8);
-    if (vol->v_mactoutf8  != (iconv_t)(-1))
-        iconv_close(vol->v_mactoutf8);
-    if (vol->v_ucs2tomac  != (iconv_t)(-1))
-        iconv_close(vol->v_ucs2tomac);
-#endif
-
     if (vol->v_postexec) {
        afprun(0, vol->v_postexec, NULL);
     }
index 296c83ba91c4c0e991ec1b1217f85d15114834f3..e32130d8cf1969bc29c3cd19a82cc9c0b908be66 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: volume.h,v 1.19.2.3 2003-05-26 17:02:48 didg Exp $
+ * $Id: volume.h,v 1.19.2.4 2003-06-23 10:25:08 didg Exp $
  *
  * Copyright (c) 1990,1994 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -12,6 +12,7 @@
 #include <sys/types.h>
 #include <netatalk/endian.h>
 
+#include "atalk/unicode.h"
 #ifdef HAVE_USABLE_ICONV
 #include <iconv.h>
 #endif
@@ -71,12 +72,9 @@ struct vol {
     char               *v_forcegid;
 #endif 
 
-#ifdef HAVE_USABLE_ICONV
-    iconv_t             *v_utf8toucs2;
-    iconv_t             *v_ucs2toutf8;
-    iconv_t             *v_mactoutf8;
-    iconv_t             *v_ucs2tomac;
-#endif
+    char                *v_encoding;
+    charset_t          v_maccharset;
+
     int                 v_deleted;  /* volume open but deleted in new config file */
     int                 v_hide;     /* new volume wait open volume */
 
index dfd48306b80a77b8e38fe37477d58be900e58fe7..74332071512e3258c836b406d06f995af7143f8f 100644 (file)
@@ -1,4 +1,4 @@
 # Makefile.am for include/atalk/
 
 atalkincludedir = $(includedir)/atalk
-atalkinclude_HEADERS = adouble.h aep.h afp.h asp.h atp.h boolean.h cnid.h compat.h ddp.h dsi.h logger.h nbp.h netddp.h pap.h paths.h rtmp.h server_child.h uam.h util.h zip.h
+atalkinclude_HEADERS = adouble.h aep.h afp.h asp.h atp.h boolean.h cnid.h compat.h ddp.h dsi.h logger.h nbp.h netddp.h pap.h paths.h rtmp.h server_child.h uam.h util.h zip.h unicode.h
diff --git a/include/atalk/unicode.h b/include/atalk/unicode.h
new file mode 100644 (file)
index 0000000..0578c6a
--- /dev/null
@@ -0,0 +1,99 @@
+
+#ifndef _ATALK_UNICODE_H
+#define _ATALK_UNICODE_H 1
+
+
+
+#define ucs2_t u_int16_t
+
+/* generic iconv conversion structure */
+typedef struct {
+        size_t (*direct)(void *cd, char **inbuf, size_t *inbytesleft,
+                         char **outbuf, size_t *outbytesleft);
+        size_t (*pull)(void *cd, char **inbuf, size_t *inbytesleft,
+                       char **outbuf, size_t *outbytesleft);
+        size_t (*push)(void *cd, char **inbuf, size_t *inbytesleft,
+                       char **outbuf, size_t *outbytesleft);
+        void *cd_direct, *cd_pull, *cd_push;
+        char *from_name, *to_name;
+} *atalk_iconv_t;
+
+
+/* this defines the charset types used in samba */
+typedef enum {CH_UCS2=0, CH_UTF8=1, CH_MAC=2, CH_UNIX=3} charset_t;
+
+#define NUM_CHARSETS 4
+
+/*
+ *   for each charset we have a function that pulls from that charset to
+ *     a ucs2 buffer, and a function that pushes to a ucs2 buffer
+ *     */
+
+struct charset_functions {
+        const char *name;
+        size_t (*pull)(void *, char **inbuf, size_t *inbytesleft,
+                                   char **outbuf, size_t *outbytesleft);
+        size_t (*push)(void *, char **inbuf, size_t *inbytesleft,
+                                   char **outbuf, size_t *outbytesleft);
+        struct charset_functions *prev, *next;
+};
+
+
+extern atalk_iconv_t   atalk_iconv_open __P((const char *, const char *));
+extern size_t          atalk_iconv __P((atalk_iconv_t, const char **, size_t *, char **, size_t *));
+extern size_t          atalk_iconv_ignore __P((atalk_iconv_t, const char **, size_t *, char **, size_t *, int*));
+extern int             atalk_iconv_close __P((atalk_iconv_t));
+
+extern ucs2_t  toupper_w  __P((ucs2_t));
+extern ucs2_t  tolower_w  __P((ucs2_t));
+extern int     strupper_w __P((ucs2_t *));
+extern int     strlower_w __P((ucs2_t *));
+extern int     islower_w  __P((ucs2_t));
+extern int     islower_w  __P((ucs2_t));
+extern size_t  strlen_w   __P((const ucs2_t *));
+extern size_t  strnlen_w  __P((const ucs2_t *, size_t));
+extern ucs2_t*         strchr_w   __P((const ucs2_t *, ucs2_t));
+extern int     strcmp_w   __P((const ucs2_t *, const ucs2_t *));
+extern int     strncmp_w  __P((const ucs2_t *, const ucs2_t *, size_t));
+extern int      strcasecmp_w  __P((const ucs2_t *, const ucs2_t *));
+extern int     strncasecmp_w __P((const ucs2_t *, const ucs2_t *, size_t));
+extern ucs2_t   *strcasestr_w __P((const ucs2_t *, const ucs2_t *));
+extern ucs2_t  *strndup_w __P((const ucs2_t *, size_t));
+extern ucs2_t          *strdup_w  __P((const ucs2_t *));
+extern ucs2_t  *strncpy_w __P((ucs2_t *, const ucs2_t *, const size_t));
+extern ucs2_t  *strncat_w __P((ucs2_t *, const ucs2_t *, const size_t));
+extern ucs2_t  *strcat_w  __P((ucs2_t *, const ucs2_t *));
+
+extern char    *precompose_w __P((ucs2_t *, size_t, size_t *));
+extern char    *decompose_w  __P((ucs2_t *, size_t, size_t *));
+extern size_t  utf8_charlen __P(( char* ));
+extern size_t  utf8_strlen_validate __P(( char *));
+
+extern void    init_iconv __P((void));
+extern size_t  convert_string __P((charset_t, charset_t, void const *, size_t, void *, size_t));
+extern size_t  convert_string_allocate __P((charset_t, charset_t, void const *, size_t, void **));
+
+extern size_t  utf8_strupper __P((const char *, size_t, char *, size_t));
+extern size_t  utf8_strlower __P((const char *, size_t, char *, size_t));
+extern size_t   mac_strupper __P((const char *, size_t, char *, size_t));
+extern size_t   mac_strlower __P((const char *, size_t, char *, size_t));
+extern size_t  unix_strupper __P((const char *, size_t, char *, size_t));
+extern size_t  unix_strlower __P((const char *, size_t, char *, size_t));
+
+extern size_t  mac_to_ucs2_allocate __P((ucs2_t **dest, const char *src));
+extern size_t  mac_to_utf8_allocate __P((char **dest, const char *src));
+extern size_t  ucs2_to_mac_allocate __P((char **dest, const ucs2_t *src));
+extern size_t  utf8_to_mac_allocate __P((void **dest, const char *src));
+
+extern size_t  utf8_to_mac __P((char *, size_t, char *, size_t));
+extern size_t  utf8_to_mac_charset __P((charset_t, char *, size_t, char *, size_t, int*));
+
+extern size_t  utf8_precompose __P(( char *, size_t, char *, size_t));
+extern size_t  utf8_decompose  __P(( char *, size_t, char *, size_t));
+
+extern charset_t add_charset __P((char* name));
+
+
+#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)
+
+#endif
index 4545e59dbe418780566544a94a2712ca7f1e589d..7ac776c1acf5017cc272df5daf1d51fd3bd7e567 100644 (file)
@@ -1,6 +1,6 @@
 # Makefile.am for libatalk/
 
-SUBDIRS = adouble asp atp compat cnid dsi nbp netddp util
+SUBDIRS = adouble asp atp compat cnid dsi nbp netddp util unicode
 
 lib_LTLIBRARIES = libatalk.la
 
@@ -13,7 +13,8 @@ LIBATALK_DEPS = \
        dsi/libdsi.la           \
        nbp/libnbp.la           \
        netddp/libnetddp.la     \
-       util/libutil.la
+       util/libutil.la         \
+       unicode/libunicode.la
 
 libatalk_la_SOURCES = dummy.c
 libatalk_la_LIBADD  = $(LIBATALK_DEPS)
diff --git a/libatalk/unicode/Makefile.am b/libatalk/unicode/Makefile.am
new file mode 100644 (file)
index 0000000..d06486a
--- /dev/null
@@ -0,0 +1,12 @@
+# Makefile.am for libatalk/util/
+
+noinst_LTLIBRARIES = libunicode.la
+
+CFLAGS = -I$(top_srcdir)/sys @CFLAGS@
+
+libunicode_la_SOURCES = \
+       util_unistr.c   \
+       iconv.c         \
+       charcnv.c       
+
+noinst_HEADERS = mac_roman.h ucs2_casetable.h precompose.h
diff --git a/libatalk/unicode/charcnv.c b/libatalk/unicode/charcnv.c
new file mode 100644 (file)
index 0000000..e5f063b
--- /dev/null
@@ -0,0 +1,640 @@
+/* 
+   Unix SMB/CIFS implementation.
+   Character set conversion Extensions
+   Copyright (C) Igor Vergeichik <iverg@mail.ru> 2001
+   Copyright (C) Andrew Tridgell 2001
+   Copyright (C) Simo Sorce 2001
+   Copyright (C) Martin Pool 2003
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <atalk/logger.h>
+#include <errno.h>
+
+#include <netatalk/endian.h>
+#include <atalk/unicode.h>
+
+#ifdef HAVE_USABLE_ICONV
+#include <iconv.h>
+#endif
+
+
+/**
+ * @file
+ *
+ * @brief Character-set conversion routines built on our iconv.
+ * 
+ * @note Samba's internal character set (at least in the 3.0 series)
+ * is always the same as the one for the Unix filesystem.  It is
+ * <b>not</b> necessarily UTF-8 and may be different on machines that
+ * need i18n filenames to be compatible with Unix software.  It does
+ * have to be a superset of ASCII.  All multibyte sequences must start
+ * with a byte with the high bit set.
+ *
+ * @sa lib/iconv.c
+ */
+
+
+#define MAX_CHARSETS 10
+
+static atalk_iconv_t conv_handles[MAX_CHARSETS][MAX_CHARSETS];
+
+static char* charset_names[MAX_CHARSETS];
+
+struct charset {
+        const char *name;
+       charset_t ch_charset_t;
+        struct charset *prev, *next;
+};
+
+/**
+ * Return the name of a charset to give to iconv().
+ **/
+static const char *charset_name(charset_t ch)
+{
+       const char *ret = NULL;
+
+       if (ch == CH_UCS2) ret = "UCS-2LE";
+       else if (ch == CH_UNIX) ret = "ASCII"; /*lp_unix_charset();*/
+       else if (ch == CH_MAC) ret = "MAC"; /*lp_display_charset();*/
+       else if (ch == CH_UTF8) ret = "UTF8";
+
+       if (!ret)
+               ret = charset_names[ch];
+
+       if (!ret || !*ret) ret = "ASCII";
+       return ret;
+}
+
+void lazy_initialize_conv(void)
+{
+       static int initialized = 0;
+
+       if (!initialized) {
+               initialized = 1;
+               init_iconv();
+       }
+}
+
+charset_t add_charset(char* name)
+{
+       static charset_t max_charset_t = NUM_CHARSETS-1;
+       charset_t cur_charset_t = max_charset_t+1;
+       int c1, c2;
+
+       for (c1=0; c1<=max_charset_t;c1++) {
+               if ( strcmp(name, charset_name(c1)) == 0)
+                       return (c1);
+       }
+
+       if ( cur_charset_t >= MAX_CHARSETS )  {
+               LOG (log_debug, logtype_default, "Adding charset %s failed, too many charsets (max. %u allowed)", 
+                       name, MAX_CHARSETS);
+               return 0;
+       }
+
+       /* First try to setup the required conversions */
+
+       conv_handles[cur_charset_t][CH_UCS2] = atalk_iconv_open( charset_name(CH_UCS2), name);
+        if (conv_handles[cur_charset_t][CH_UCS2] == (atalk_iconv_t)-1) {
+               LOG(log_error, logtype_default, "Required conversion from %s to %s not supported\n",
+                       name,  charset_name(CH_UCS2));
+               conv_handles[cur_charset_t][CH_UCS2] = NULL;
+               return 0;
+       }
+
+       conv_handles[CH_UCS2][cur_charset_t] = atalk_iconv_open( name, charset_name(CH_UCS2));
+        if (conv_handles[CH_UCS2][cur_charset_t] == (atalk_iconv_t)-1) {
+               LOG(log_error, logtype_default, "Required conversion from %s to %s not supported\n",
+                       charset_name(CH_UCS2), name);
+               conv_handles[CH_UCS2][cur_charset_t] = NULL;
+               return 0;
+       }
+
+       /* register the new charset_t name */
+       charset_names[cur_charset_t] = strdup(name);
+
+       
+       for (c1=0;c1<=cur_charset_t;c1++) {
+               for (c2=0;c2<=cur_charset_t;c2++) {
+                       const char *n1 = charset_name((charset_t)c1);
+                       const char *n2 = charset_name((charset_t)c2);
+                       if (conv_handles[c1][c2] &&
+                           strcmp(n1, conv_handles[c1][c2]->from_name) == 0 &&
+                           strcmp(n2, conv_handles[c1][c2]->to_name) == 0)
+                               continue;
+
+                       if (conv_handles[c1][c2])
+                               atalk_iconv_close(conv_handles[c1][c2]);
+
+                       conv_handles[c1][c2] = atalk_iconv_open(n2,n1);
+                       if (conv_handles[c1][c2] == (atalk_iconv_t)-1) {
+                               LOG(log_debug, logtype_default, "Conversion from %s to %s not supported\n",
+                                        charset_name((charset_t)c1), charset_name((charset_t)c2));
+                               conv_handles[c1][c2] = NULL;
+                       }
+               }
+       }
+
+       max_charset_t++;
+
+       LOG(log_debug, logtype_default, "Added charset %s with handle %u", name, cur_charset_t);
+       return (cur_charset_t);
+}
+
+/**
+ * Initialize iconv conversion descriptors.
+ *
+ * This is called the first time it is needed, and also called again
+ * every time the configuration is reloaded, because the charset or
+ * codepage might have changed.
+ **/
+void init_iconv(void)
+{
+       int c1, c2;
+
+       /* so that charset_name() works we need to get the UNIX<->UCS2 going
+          first */
+       if (!conv_handles[CH_UNIX][CH_UCS2])
+               conv_handles[CH_UNIX][CH_UCS2] = atalk_iconv_open("UCS-2LE", "ASCII");
+
+       if (!conv_handles[CH_UCS2][CH_UNIX])
+               conv_handles[CH_UCS2][CH_UNIX] = atalk_iconv_open("ASCII", "UCS-2LE");
+
+       for (c1=0;c1<NUM_CHARSETS;c1++) {
+               for (c2=0;c2<NUM_CHARSETS;c2++) {
+                       const char *n1 = charset_name((charset_t)c1);
+                       const char *n2 = charset_name((charset_t)c2);
+                       if (conv_handles[c1][c2] &&
+                           strcmp(n1, conv_handles[c1][c2]->from_name) == 0 &&
+                           strcmp(n2, conv_handles[c1][c2]->to_name) == 0)
+                               continue;
+
+                       if (conv_handles[c1][c2])
+                               atalk_iconv_close(conv_handles[c1][c2]);
+
+                       conv_handles[c1][c2] = atalk_iconv_open(n2,n1);
+                       if (conv_handles[c1][c2] == (atalk_iconv_t)-1) {
+                               LOG(log_debug, logtype_default, "Conversion from %s to %s not supported\n",
+                                        charset_name((charset_t)c1), charset_name((charset_t)c2));
+                               conv_handles[c1][c2] = NULL;
+                       }
+               }
+       }
+}
+
+/**
+ * Convert string from one encoding to another, making error checking etc
+ *
+ * @param src pointer to source string (multibyte or singlebyte)
+ * @param srclen length of the source string in bytes
+ * @param dest pointer to destination string (multibyte or singlebyte)
+ * @param destlen maximal length allowed for string
+ * @returns the number of bytes occupied in the destination
+ **/
+size_t convert_string(charset_t from, charset_t to,
+                     void const *src, size_t srclen, 
+                     void *dest, size_t destlen)
+{
+       size_t i_len, o_len;
+       size_t retval;
+       const char* inbuf = (const char*)src;
+       char* outbuf = (char*)dest;
+       atalk_iconv_t descriptor;
+
+       if (srclen == (size_t)-1)
+               srclen = strlen(src)+1;
+
+       lazy_initialize_conv();
+
+       descriptor = conv_handles[from][to];
+
+       if (descriptor == (atalk_iconv_t)-1 || descriptor == (atalk_iconv_t)0) {
+               /* conversion not supported, use as is */
+               size_t len = MIN(srclen,destlen);
+               memcpy(dest,src,len);
+               return len;
+       }
+
+       i_len=srclen;
+       o_len=destlen;
+       retval = atalk_iconv(descriptor,  &inbuf, &i_len, &outbuf, &o_len);
+       if(retval==(size_t)-1) {
+               const char *reason="unknown error";
+               switch(errno) {
+                       case EINVAL:
+                               reason="Incomplete multibyte sequence";
+                               break;
+                       case E2BIG:
+                               reason="No more room"; 
+                               LOG(log_debug, logtype_default, "convert_string: Required %d, available %d\n",
+                                       srclen, destlen);
+                               /* we are not sure we need srclen bytes,
+                                 may be more, may be less.
+                                 We only know we need more than destlen
+                                 bytes ---simo */
+                              break;
+                       case EILSEQ:
+                              reason="Illegal multibyte sequence";
+                              break;
+               }
+               return (size_t)-1;
+               /* smb_panic(reason); */
+       }
+       return destlen-o_len;
+}
+
+/**
+ * Convert between character sets, allocating a new buffer for the result.
+ *
+ * @param srclen length of source buffer.
+ * @param dest always set at least to NULL
+ * @note -1 is not accepted for srclen.
+ *
+ * @returns Size in bytes of the converted string; or -1 in case of error.
+ **/
+
+size_t convert_string_allocate(charset_t from, charset_t to,
+                              void const *src, size_t srclen, void **dest)
+{
+       size_t i_len, o_len, destlen;
+       size_t retval;
+       const char *inbuf = (const char *)src;
+       char *outbuf, *ob;
+       atalk_iconv_t descriptor;
+
+       *dest = NULL;
+
+       if (src == NULL || srclen == (size_t)-1)
+               return (size_t)-1;
+
+       lazy_initialize_conv();
+
+       descriptor = conv_handles[from][to];
+
+       if (descriptor == (atalk_iconv_t)-1 || descriptor == (atalk_iconv_t)0) {
+               /* conversion not supported, return -1*/
+               LOG(log_debug, logtype_default, "convert_string_allocate: conversion not supported!\n");
+               return -1;
+       }
+
+       destlen = MAX(srclen, 512);
+       outbuf = NULL;
+convert:
+       destlen = destlen * 2;
+       ob = (char *)realloc(outbuf, destlen);
+       if (!ob) {
+               LOG(log_debug, logtype_default,"convert_string_allocate: realloc failed!\n");
+               SAFE_FREE(outbuf);
+               return (size_t)-1;
+       } else {
+               outbuf = ob;
+       }
+       i_len = srclen;
+       o_len = destlen;
+       retval = atalk_iconv(descriptor,
+                          &inbuf, &i_len,
+                          &outbuf, &o_len);
+       if(retval == (size_t)-1)                {
+               const char *reason="unknown error";
+               switch(errno) {
+                       case EINVAL:
+                               reason="Incomplete multibyte sequence";
+                               break;
+                       case E2BIG:
+                               goto convert;           
+                       case EILSEQ:
+                               reason="Illegal multibyte sequence";
+                               break;
+               }
+               LOG(log_debug, logtype_default,"Conversion error: %s(%s)\n",reason,inbuf);
+               /* smb_panic(reason); */
+               return (size_t)-1;
+       }
+       
+       destlen = destlen - o_len;
+       *dest = (char *)realloc(ob,destlen);
+       if (destlen && !*dest) {
+               LOG(log_debug, logtype_default, "convert_string_allocate: out of memory!\n");
+               SAFE_FREE(ob);
+               return (size_t)-1;
+       }
+
+       return destlen;
+}
+
+
+size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
+{
+       size_t size;
+       ucs2_t *buffer;
+       
+       size = convert_string_allocate(CH_UNIX, CH_UCS2, src, srclen,
+                                      (void **) &buffer);
+       if (size == -1) {
+               free(buffer);
+               return size;
+       }
+       if (!strupper_w(buffer) && (dest == src)) {
+               free(buffer);
+               return srclen;
+       }
+       
+       size = convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen);
+       free(buffer);
+       return size;
+}
+
+size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
+{
+       size_t size;
+       ucs2_t *buffer;
+       
+       size = convert_string_allocate(CH_UNIX, CH_UCS2, src, srclen,
+                                      (void **) &buffer);
+       if (size == -1) {
+               free(buffer);
+               return size;
+       /*      smb_panic("failed to create UCS2 buffer");*/
+       }
+       if (!strlower_w(buffer) && (dest == src)) {
+               free(buffer);
+               return srclen;
+       }
+       size = convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen);
+       free(buffer);
+       return size;
+}
+
+size_t utf8_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
+{
+       size_t size;
+       ucs2_t *buffer;
+       
+       size = convert_string_allocate(CH_UTF8, CH_UCS2, src, srclen,
+                                      (void **) &buffer);
+       if (size == -1) {
+               free(buffer);
+               return size;
+       }
+       if (!strupper_w(buffer) && (dest == src)) {
+               free(buffer);
+               return srclen;
+       }
+       
+       size = convert_string(CH_UCS2, CH_UTF8, buffer, size, dest, destlen);
+       free(buffer);
+       return size;
+}
+
+size_t utf8_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
+{
+       size_t size;
+       ucs2_t *buffer;
+       
+       size = convert_string_allocate(CH_UTF8, CH_UCS2, src, srclen,
+                                      (void **) &buffer);
+       if (size == -1) {
+               free(buffer);
+               return size;
+       }
+       if (!strlower_w(buffer) && (dest == src)) {
+               free(buffer);
+               return srclen;
+       }
+       
+       size = convert_string(CH_UCS2, CH_UTF8, buffer, size, dest, destlen);
+       free(buffer);
+       return size;
+}
+
+size_t mac_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
+{
+       size_t size;
+       ucs2_t *buffer;
+       
+       size = convert_string_allocate(CH_MAC, CH_UCS2, src, srclen,
+                                      (void **) &buffer);
+       if (size == -1) {
+               free(buffer);
+               return size;
+       }
+       if (!strupper_w(buffer) && (dest == src)) {
+               free(buffer);
+               return srclen;
+       }
+       
+       size = convert_string(CH_UCS2, CH_MAC, buffer, size, dest, destlen);
+       free(buffer);
+       return size;
+}
+
+size_t mac_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
+{
+       size_t size;
+       ucs2_t *buffer;
+       
+       size = convert_string_allocate(CH_MAC, CH_UCS2, src, srclen,
+                                      (void **) &buffer);
+       if (size == -1) {
+               free(buffer);
+               return size;
+       }
+       if (!strlower_w(buffer) && (dest == src)) {
+               free(buffer);
+               return srclen;
+       }
+       
+       size = convert_string(CH_UCS2, CH_MAC, buffer, size, dest, destlen);
+       free(buffer);
+       return size;
+}
+
+/**
+ * Copy a string from a mac char* src to a UCS2 destination, allocating a buffer
+ *
+ * @param dest always set at least to NULL 
+ *
+ * @returns The number of bytes occupied by the string in the destination
+ *         or -1 in case of error.
+ **/
+
+size_t mac_to_ucs2_allocate(ucs2_t **dest, const char *src)
+{
+       size_t src_len = strlen(src)+1;
+
+       *dest = NULL;
+       return convert_string_allocate(CH_MAC, CH_UCS2, src, src_len, (void **)dest);   
+}
+
+/**
+ * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer
+ *
+ * @param dest always set at least to NULL 
+ *
+ * @returns The number of bytes occupied by the string in the destination
+ **/
+
+size_t mac_to_utf8_allocate(char **dest, const char *src)
+{
+       size_t src_len = strlen(src)+1;
+
+       *dest = NULL;
+       return convert_string_allocate(CH_MAC, CH_UTF8, src, src_len, (void **)dest);   
+}
+
+/**
+ * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer
+ *
+ * @param dest always set at least to NULL 
+ *
+ * @returns The number of bytes occupied by the string in the destination
+ **/
+
+size_t ucs2_to_mac_allocate(char **dest, const ucs2_t *src)
+{
+       size_t src_len = (strlen_w(src)+1) * sizeof(ucs2_t);
+       *dest = NULL;
+       return convert_string_allocate(CH_UCS2, CH_MAC, src, src_len, (void **)dest);   
+}
+
+/**
+ * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer
+ *
+ * @param dest always set at least to NULL 
+ *
+ * @returns The number of bytes occupied by the string in the destination
+ **/
+
+static char convbuf[MAXPATHLEN+1];
+size_t utf8_to_mac_allocate(void **dest, const char *src)
+{
+       size_t src_len = strlen(src)+1;
+       *dest = NULL;
+
+       src_len = utf8_precompose ( (char *) src, src_len, convbuf, MAXPATHLEN);        
+       return convert_string_allocate(CH_UTF8, CH_MAC, convbuf, src_len, dest);        
+}
+
+size_t utf8_to_mac ( char* src, size_t src_len, char* dest, size_t dest_len)
+{
+       src_len = utf8_precompose ( (char *) src, src_len, convbuf, MAXPATHLEN);        
+       return convert_string(CH_UTF8, CH_MAC, convbuf, src_len, dest, dest_len);       
+}
+
+static char  debugbuf[ MAXPATHLEN +1 ];
+char * debug_out ( char * seq, size_t len)
+{
+        size_t i = 0;
+        unsigned char *p;
+        char *q;
+
+        p = (unsigned char*) seq;
+        q = debugbuf;
+
+        for ( i = 0; i<=(len-1); i++)
+        {
+                sprintf(q, "%2.2x.", *p);
+                q += 3;
+                p++;
+        }
+        *q=0;
+        q = debugbuf;
+        return q;
+}
+
+
+size_t utf8_precompose ( char * src, size_t inlen, char * dst, size_t outlen)
+{
+       char *u;
+       size_t len;
+       size_t ilen;
+
+        if ((size_t)(-1) == (len =  convert_string(CH_UTF8, CH_UCS2, src, inlen, convbuf, MAXPATHLEN)) )
+            return len;
+
+        if ( NULL == (u = precompose_w((ucs2_t *)convbuf, len, &ilen)) )
+           return (size_t)(-1);
+
+        if ((size_t)(-1) == (len = convert_string( CH_UCS2, CH_UTF8, u, ilen, dst, outlen)) )
+           return (size_t)(-1);
+
+       dst[len] = 0;
+       return (len);
+}
+
+size_t utf8_decompose ( char * src, size_t inlen, char * dst, size_t outlen)
+{
+       char *u;
+       size_t len;
+       size_t ilen;
+
+        if ((size_t)(-1) == (len =  convert_string(CH_UTF8, CH_UCS2, src, inlen, convbuf, MAXPATHLEN)) )
+            return len;
+
+        if ( NULL == (u = decompose_w((ucs2_t *)convbuf, len, &ilen)) )
+           return (size_t)(-1);
+
+        if ((size_t)(-1) == (len = convert_string( CH_UCS2, CH_UTF8, u, ilen, dst, outlen)) )
+           return (size_t)(-1);
+
+       dst[len] = 0;
+       return (len);
+}
+
+
+size_t utf8_to_mac_charset ( charset_t ch, char* src, size_t src_len, char* dest, size_t dest_len, int* mangle)
+{
+       size_t i_len, o_len;
+       size_t retval;
+       const char* inbuf;
+       char* outbuf = (char*)dest;
+       atalk_iconv_t descriptor;
+
+       lazy_initialize_conv();
+
+       src_len = utf8_precompose ( (char *) src, src_len+1, convbuf, MAXPATHLEN);
+
+       descriptor = conv_handles[CH_UTF8][ch];
+
+       if (descriptor == (atalk_iconv_t)-1 || descriptor == (atalk_iconv_t)0) {
+               LOG(log_error, logtype_default, "Conversion not supported ( UTF8 to %s )", charset_name(ch));
+               return (size_t)(-1);    
+       }
+
+       inbuf = (const char*) convbuf;
+       i_len=src_len;
+       o_len=dest_len;
+
+       retval = atalk_iconv_ignore(descriptor,  &inbuf, &i_len, &outbuf, &o_len, mangle);
+
+       if(retval==(size_t)-1) 
+               return (size_t)(-1);    
+       
+       dest[dest_len-o_len] = 0;
+       return dest_len-o_len;
+}
+
diff --git a/libatalk/unicode/iconv.c b/libatalk/unicode/iconv.c
new file mode 100644 (file)
index 0000000..e415be8
--- /dev/null
@@ -0,0 +1,838 @@
+/* 
+   Unix SMB/CIFS implementation.
+   minimal iconv implementation
+   Copyright (C) Andrew Tridgell 2001
+   Copyright (C) Jelmer Vernooij 2002,2003
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   
+   From samba 3.0 beta and GNU libiconv-1.8
+   It's bad but most of the time we can't use libc iconv service:
+   - it doesn't round trip for most encoding
+   - it doesn't know about Apple extension
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <atalk/logger.h>
+#include <errno.h>
+
+#include <netatalk/endian.h>
+#include <atalk/unicode.h>
+
+#ifdef HAVE_USABLE_ICONV
+#include <iconv.h>
+#endif
+
+
+#include "mac_roman.h"
+#include "mac_hebrew.h"
+
+/**
+ * @file
+ *
+ * @brief Samba wrapper/stub for iconv character set conversion.
+ *
+ * iconv is the XPG2 interface for converting between character
+ * encodings.  This file provides a Samba wrapper around it, and also
+ * a simple reimplementation that is used if the system does not
+ * implement iconv.
+ *
+ * Samba only works with encodings that are supersets of ASCII: ascii
+ * characters like whitespace can be tested for directly, multibyte
+ * sequences start with a byte with the high bit set, and strings are
+ * terminated by a nul byte.
+ *
+ * Note that the only function provided by iconv is conversion between
+ * characters.  It doesn't directly support operations like
+ * uppercasing or comparison.  We have to convert to UCS-2 and compare
+ * there.
+ *
+ * @sa Samba Developers Guide
+ **/
+
+static size_t ascii_pull(void *,char **, size_t *, char **, size_t *);
+static size_t ascii_push(void *,char **, size_t *, char **, size_t *);
+static size_t  utf8_pull(void *,char **, size_t *, char **, size_t *);
+static size_t  utf8_push(void *,char **, size_t *, char **, size_t *);
+static size_t iconv_copy(void *,char **, size_t *, char **, size_t *);
+
+static size_t   mac_pull(void *,char **, size_t *, char **, size_t *);
+static size_t   mac_push(void *,char **, size_t *, char **, size_t *);
+
+static size_t   mac_hebrew_pull(void *,char **, size_t *, char **, size_t *);
+static size_t   mac_hebrew_push(void *,char **, size_t *, char **, size_t *);
+
+static struct charset_functions builtin_functions[] = {
+       {"UCS-2LE",   iconv_copy, iconv_copy},
+       {"UTF8",      utf8_pull,  utf8_push},
+       {"UTF-8",     utf8_pull,  utf8_push},
+       {"ASCII",     ascii_pull, ascii_push},
+       {"MAC",       mac_pull,  mac_push},
+       {"MAC-HEBR",  mac_hebrew_pull,  mac_hebrew_push},
+       {NULL, NULL, NULL}
+};
+
+#define DLIST_ADD(list, p) \
+{ \
+        if (!(list)) { \
+                (list) = (p); \
+                (p)->next = (p)->prev = NULL; \
+        } else { \
+                (list)->prev = (p); \
+                (p)->next = (list); \
+                (p)->prev = NULL; \
+                (list) = (p); \
+        }\
+}
+
+
+
+static struct charset_functions *charsets = NULL;
+
+static struct charset_functions *find_charset_functions(const char *name) 
+{
+       struct charset_functions *c = charsets;
+
+       while(c) {
+               if (strcasecmp(name, c->name) == 0) {
+                       return c;
+               }
+               c = c->next;
+       }
+
+       return NULL;
+}
+
+int atalk_register_charset(struct charset_functions *funcs) 
+{
+       if (!funcs) {
+               return -1;
+       }
+
+       LOG(log_debug, logtype_default, "Attempting to register new charset %s", funcs->name);
+       /* Check whether we already have this charset... */
+       if (find_charset_functions(funcs->name)) {
+               LOG (log_debug, logtype_default, "Duplicate charset %s, not registering", funcs->name);
+               return -2;
+       }
+
+       funcs->next = funcs->prev = NULL;
+       LOG(log_debug, logtype_default, "Registered charset %s", funcs->name);
+       DLIST_ADD(charsets, funcs);
+       return 0;
+}
+
+void lazy_initialize_iconv(void)
+{
+       static int initialized = 0;
+       int i;
+
+       if (!initialized) {
+               initialized = 1;
+               for(i = 0; builtin_functions[i].name; i++) 
+                       atalk_register_charset(&builtin_functions[i]);
+       }
+}
+
+/* if there was an error then reset the internal state,
+   this ensures that we don't have a shift state remaining for
+   character sets like SJIS */
+static size_t sys_iconv(void *cd, 
+                       char **inbuf, size_t *inbytesleft,
+                       char **outbuf, size_t *outbytesleft)
+{
+#ifdef HAVE_USABLE_ICONV
+       size_t ret = iconv((iconv_t)cd, 
+                          inbuf, inbytesleft, 
+                          outbuf, outbytesleft);
+       if (ret == (size_t)-1) iconv(cd, NULL, NULL, NULL, NULL);
+       return ret;
+#else
+       errno = EINVAL;
+       return -1;
+#endif
+}
+
+/**
+ * This is a simple portable iconv() implementaion.
+ *
+ * It only knows about a very small number of character sets - just
+ * enough that netatalk works on systems that don't have iconv.
+ **/
+size_t atalk_iconv(atalk_iconv_t cd, 
+                const char **inbuf, size_t *inbytesleft,
+                char **outbuf, size_t *outbytesleft)
+{
+       char cvtbuf[2048];
+       char *bufp = cvtbuf;
+       size_t bufsize;
+
+       /* in many cases we can go direct */
+       if (cd->direct) {
+               return cd->direct(cd->cd_direct, 
+                                 (char **)inbuf, inbytesleft, outbuf, outbytesleft);
+       }
+
+
+       /* otherwise we have to do it chunks at a time */
+       while (*inbytesleft > 0) {
+               bufp = cvtbuf;
+               bufsize = sizeof(cvtbuf);
+               
+               if (cd->pull(cd->cd_pull, (char **)inbuf, inbytesleft, &bufp, &bufsize) == (size_t)-1
+                      && errno != E2BIG) {
+                   return -1;
+               }
+
+               bufp = cvtbuf;
+               bufsize = sizeof(cvtbuf) - bufsize;
+
+               if (cd->push(cd->cd_push, &bufp, &bufsize, outbuf, outbytesleft) == (size_t)-1) {
+                   return -1;
+               }
+       }
+
+       return 0;
+}
+
+
+size_t atalk_iconv_ignore(atalk_iconv_t cd, 
+                const char **inbuf, size_t *inbytesleft,
+                char **outbuf, size_t *outbytesleft, int *ignore)
+{
+       char cvtbuf[2048];
+       char *bufp = cvtbuf;
+       size_t bufsize;
+       size_t outlen = *outbytesleft;
+       char *o_save;
+       
+       /* we have to do it chunks at a time */
+       while (*inbytesleft > 0) {
+               bufp = cvtbuf;
+               bufsize = sizeof(cvtbuf);
+               
+               if (cd->pull(cd->cd_pull, (char **)inbuf, inbytesleft, &bufp, &bufsize) == (size_t)-1
+                       && errno != E2BIG) {
+                   return -1;
+               }
+
+               bufp = cvtbuf;
+               bufsize = sizeof(cvtbuf) - bufsize;
+
+               o_save = *outbuf;
+convert_push:
+               if (cd->push(cd->cd_push, 
+                            &bufp, &bufsize, 
+                            outbuf, outbytesleft) == (size_t)-1) {
+                   if (errno == EILSEQ) {
+                       o_save[outlen-*outbytesleft] = '_';
+                       (*outbuf) = o_save + outlen-*outbytesleft+1;
+                       (*outbytesleft) -=1;
+                       bufp += 2;
+                       bufsize -= 2;
+                       //outlen=*outbytesleft;
+                       *ignore = 1;
+                       goto convert_push;
+                   }
+                   else
+                       return (size_t)(-1);
+               }
+       }
+       return 0;
+}
+
+/*
+  simple iconv_open() wrapper
+ */
+atalk_iconv_t atalk_iconv_open(const char *tocode, const char *fromcode)
+{
+       atalk_iconv_t ret;
+       struct charset_functions *from, *to;
+
+
+       lazy_initialize_iconv();
+       from = charsets;
+       to = charsets;
+
+       ret = (atalk_iconv_t)malloc(sizeof(*ret));
+       if (!ret) {
+               errno = ENOMEM;
+               return (atalk_iconv_t)-1;
+       }
+       memset(ret, 0, sizeof(*ret));
+
+       ret->from_name = strdup(fromcode);
+       ret->to_name = strdup(tocode);
+
+       /* check for the simplest null conversion */
+       if (strcasecmp(fromcode, tocode) == 0) {
+               ret->direct = iconv_copy;
+               return ret;
+       }
+
+       /* check if we have a builtin function for this conversion */
+       from = find_charset_functions(fromcode);
+       if(from)ret->pull = from->pull;
+       
+       to = find_charset_functions(tocode);
+       if(to)ret->push = to->push;
+
+       /* check if we can use iconv for this conversion */
+#ifdef HAVE_USABLE_ICONV
+       if (!ret->pull) {
+               ret->cd_pull = iconv_open("UCS-2LE", fromcode);
+               if (ret->cd_pull != (iconv_t)-1)
+                       ret->pull = sys_iconv;
+       }
+
+       if (!ret->push) {
+               ret->cd_push = iconv_open(tocode, "UCS-2LE");
+               if (ret->cd_push != (iconv_t)-1)
+                       ret->push = sys_iconv;
+       }
+#endif
+       
+       if (!ret->push || !ret->pull) {
+               SAFE_FREE(ret->from_name);
+               SAFE_FREE(ret->to_name);
+               SAFE_FREE(ret);
+               errno = EINVAL;
+               return (atalk_iconv_t)-1;
+       }
+
+       /* check for conversion to/from ucs2 */
+       if (strcasecmp(fromcode, "UCS-2LE") == 0 && to) {
+               ret->direct = to->push;
+               ret->push = ret->pull = NULL;
+               return ret;
+       }
+
+       if (strcasecmp(tocode, "UCS-2LE") == 0 && from) {
+               ret->direct = from->pull;
+               ret->push = ret->pull = NULL;
+               return ret;
+       }
+
+       /* Check if we can do the conversion direct */
+#ifdef HAVE_USABLE_ICONV
+       if (strcasecmp(fromcode, "UCS-2LE") == 0) {
+               ret->direct = sys_iconv;
+               ret->cd_direct = ret->cd_push;
+               ret->cd_push = NULL;
+               return ret;
+       }
+       if (strcasecmp(tocode, "UCS-2LE") == 0) {
+               ret->direct = sys_iconv;
+               ret->cd_direct = ret->cd_pull;
+               ret->cd_pull = NULL;
+               return ret;
+       }
+#endif
+
+       return ret;
+}
+
+/*
+  simple iconv_close() wrapper
+*/
+int atalk_iconv_close (atalk_iconv_t cd)
+{
+#ifdef HAVE_USABLE_ICONV
+       if (cd->cd_direct) iconv_close((iconv_t)cd->cd_direct);
+       if (cd->cd_pull) iconv_close((iconv_t)cd->cd_pull);
+       if (cd->cd_push) iconv_close((iconv_t)cd->cd_push);
+#endif
+
+       SAFE_FREE(cd->from_name);
+       SAFE_FREE(cd->to_name);
+
+       memset(cd, 0, sizeof(*cd));
+       SAFE_FREE(cd);
+       return 0;
+}
+
+
+/************************************************************************
+ the following functions implement the builtin character sets in Netatalk
+*************************************************************************/
+
+static size_t ascii_pull(void *cd, char **inbuf, size_t *inbytesleft,
+                        char **outbuf, size_t *outbytesleft)
+{
+       while (*inbytesleft >= 1 && *outbytesleft >= 2) {
+               (*outbuf)[0] = (*inbuf)[0];
+               (*outbuf)[1] = 0;
+               (*inbytesleft)  -= 1;
+               (*outbytesleft) -= 2;
+               (*inbuf)  += 1;
+               (*outbuf) += 2;
+       }
+
+       if (*inbytesleft > 0) {
+               errno = E2BIG;
+               return -1;
+       }
+       
+       return 0;
+}
+
+static size_t ascii_push(void *cd, char **inbuf, size_t *inbytesleft,
+                        char **outbuf, size_t *outbytesleft)
+{
+       int ir_count=0;
+
+       while (*inbytesleft >= 2 && *outbytesleft >= 1) {
+               (*outbuf)[0] = (*inbuf)[0] & 0x7F;
+               if ((*inbuf)[1]) ir_count++;
+               (*inbytesleft)  -= 2;
+               (*outbytesleft) -= 1;
+               (*inbuf)  += 2;
+               (*outbuf) += 1;
+       }
+
+       if (*inbytesleft == 1) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       if (*inbytesleft > 1) {
+               errno = E2BIG;
+               return -1;
+       }
+       
+       return ir_count;
+}
+
+
+static size_t iconv_copy(void *cd, char **inbuf, size_t *inbytesleft,
+                        char **outbuf, size_t *outbytesleft)
+{
+       int n;
+
+       n = MIN(*inbytesleft, *outbytesleft);
+
+       memmove(*outbuf, *inbuf, n);
+
+       (*inbytesleft) -= n;
+       (*outbytesleft) -= n;
+       (*inbuf) += n;
+       (*outbuf) += n;
+
+       if (*inbytesleft > 0) {
+               errno = E2BIG;
+               return -1;
+       }
+
+       return 0;
+}
+
+/* ------------------------ */
+static size_t utf8_pull(void *cd, char **inbuf, size_t *inbytesleft,
+                        char **outbuf, size_t *outbytesleft)
+{
+       while (*inbytesleft >= 1 && *outbytesleft >= 2) {
+               unsigned char *c = (unsigned char *)*inbuf;
+               unsigned char *uc = (unsigned char *)*outbuf;
+               int len = 1;
+
+               if ((c[0] & 0x80) == 0) {
+                       uc[0] = c[0];
+                       uc[1] = 0;
+               } else if ((c[0] & 0xf0) == 0xe0) {
+                       if (*inbytesleft < 3) {
+                               LOG(log_debug, logtype_default, "short utf8 char\n");
+                               goto badseq;
+                       }
+                       uc[1] = ((c[0]&0xF)<<4) | ((c[1]>>2)&0xF);
+                       uc[0] = (c[1]<<6) | (c[2]&0x3f);
+                       len = 3;
+               } else if ((c[0] & 0xe0) == 0xc0) {
+                       if (*inbytesleft < 2) {
+                               LOG(log_debug, logtype_default, "short utf8 char\n");
+                               goto badseq;
+                       }
+                       uc[1] = (c[0]>>2) & 0x7;
+                       uc[0] = (c[0]<<6) | (c[1]&0x3f);
+                       len = 2;
+               }
+
+               (*inbuf)  += len;
+               (*inbytesleft)  -= len;
+               (*outbytesleft) -= 2;
+               (*outbuf) += 2;
+       }
+
+       if (*inbytesleft > 0) {
+               errno = E2BIG;
+               return -1;
+       }
+       
+       return 0;
+
+badseq:
+       errno = EINVAL;
+       return -1;
+}
+
+/* ------------------------ */
+static size_t utf8_push(void *cd, char **inbuf, size_t *inbytesleft,
+                        char **outbuf, size_t *outbytesleft)
+{
+       while (*inbytesleft >= 2 && *outbytesleft >= 1) {
+               unsigned char *c = (unsigned char *)*outbuf;
+               unsigned char *uc = (unsigned char *)*inbuf;
+               int len=1;
+
+               if (uc[1] & 0xf8) {
+                       if (*outbytesleft < 3) {
+                               LOG(log_debug, logtype_default, "short utf8 write\n");
+                               goto toobig;
+                       }
+                       c[0] = 0xe0 | (uc[1]>>4);
+                       c[1] = 0x80 | ((uc[1]&0xF)<<2) | (uc[0]>>6);
+                       c[2] = 0x80 | (uc[0]&0x3f);
+                       len = 3;
+               } else if (uc[1] | (uc[0] & 0x80)) {
+                       if (*outbytesleft < 2) {
+                               LOG(log_debug, logtype_default, "short utf8 write\n");
+                               goto toobig;
+                       }
+                       c[0] = 0xc0 | (uc[1]<<2) | (uc[0]>>6);
+                       c[1] = 0x80 | (uc[0]&0x3f);
+                       len = 2;
+               } else {
+                       c[0] = uc[0];
+               }
+
+
+               (*inbytesleft)  -= 2;
+               (*outbytesleft) -= len;
+               (*inbuf)  += 2;
+               (*outbuf) += len;
+       }
+
+       if (*inbytesleft == 1) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       if (*inbytesleft > 1) {
+               errno = E2BIG;
+               return -1;
+       }
+       
+       return 0;
+
+toobig:
+       errno = E2BIG;
+       return -1;
+}
+
+/* ------------------------ */
+static int
+char_ucs2_to_mac_roman ( unsigned char *r, ucs2_t wc)
+{
+       unsigned char c = 0;
+       if (wc < 0x0080) {
+               *r = wc;
+               return 1;
+       }
+       else if (wc >= 0x00a0 && wc < 0x0100)
+               c = mac_roman_page00[wc-0x00a0];
+       else if (wc >= 0x0130 && wc < 0x0198)
+               c = mac_roman_page01[wc-0x0130];
+       else if (wc >= 0x02c0 && wc < 0x02e0)
+               c = mac_roman_page02[wc-0x02c0];
+       else if (wc == 0x03c0)
+               c = 0xb9;
+       else if (wc >= 0x2010 && wc < 0x2048)
+               c = mac_roman_page20[wc-0x2010];
+       else if (wc >= 0x2120 && wc < 0x2128)
+               c = mac_roman_page21[wc-0x2120];
+       else if (wc >= 0x2200 && wc < 0x2268)
+               c = mac_roman_page22[wc-0x2200];
+       else if (wc == 0x25ca)
+               c = 0xd7;
+       else if (wc >= 0xfb00 && wc < 0xfb08)
+               c = mac_roman_pagefb[wc-0xfb00];
+       else if (wc == 0xf8ff)
+               c = 0xf0;
+
+       if (c != 0) {
+               *r = c;
+               return 1;
+       }
+       return 0;
+}
+
+static size_t mac_push( void *cd, char **inbuf, size_t *inbytesleft,
+                         char **outbuf, size_t *outbytesleft)
+{
+        int len = 0;
+       unsigned char *tmpptr = (unsigned char *) *outbuf;
+
+        while (*inbytesleft >= 2 && *outbytesleft >= 1) {
+
+               ucs2_t *inptr = (ucs2_t *) *inbuf;
+               if (char_ucs2_to_mac_roman ( tmpptr, *inptr)) {
+                       (*inbuf) += 2;
+                       tmpptr++;
+                       len++;
+                       (*inbytesleft)  -= 2;
+                       (*outbytesleft) -= 1;
+               }
+               else    
+               {
+                       errno = EILSEQ;
+                       return (size_t) -1;     
+               }
+        }
+
+        if (*inbytesleft > 0) {
+                errno = E2BIG;
+                return -1;
+        }
+
+        return len;
+}
+
+/* ------------------------ */
+static int
+char_mac_roman_to_ucs2 (ucs2_t *pwc, const unsigned char *s)
+{
+       unsigned char c = *s;
+       if (c < 0x80) {
+               *pwc = (ucs2_t) c;
+               return 1;
+       }
+       else {
+               unsigned short wc = mac_roman_2uni[c-0x80];
+               *pwc = (ucs2_t) wc;
+               return 1;
+       }
+       return 0;
+}
+
+static size_t mac_pull ( void *cd, char **inbuf, size_t *inbytesleft,
+                         char **outbuf, size_t *outbytesleft)
+{
+       ucs2_t          *temp;
+       unsigned char   *inptr;
+        size_t  len = 0;
+
+        while (*inbytesleft >= 1 && *outbytesleft >= 2) {
+
+               inptr = (unsigned char *) *inbuf;
+               temp  = (ucs2_t*) *outbuf;      
+               if (char_mac_roman_to_ucs2 ( temp, inptr)) {
+                       (*inbuf)        +=1;
+                       (*outbuf)       +=2;
+                       (*inbytesleft) -=1;
+                       (*outbytesleft)-=2;
+                       len++;
+                       
+               }
+               else    
+               {
+                       errno = EILSEQ;
+                       return (size_t) -1;     
+               }
+        }
+
+        if (*inbytesleft > 0) {
+                errno = E2BIG;
+                return (size_t) -1;
+        }
+
+        return len;
+
+}
+
+/* ------------------------ 
+ * from unicode to mac hebrew code page
+*/
+static int
+char_ucs2_to_mac_hebrew ( unsigned char *r, ucs2_t wc)
+{
+    unsigned char c = 0;
+    if (wc < 0x0080) {
+       *r = wc;
+       return 1;
+    }
+    else if (wc >= 0x00a0 && wc < 0x0100)
+        c = mac_hebrew_page00[wc-0x00a0];
+    else if (wc >= 0x05b0 && wc < 0x05f0)
+        c = mac_hebrew_page05[wc-0x05b0];
+    else if (wc >= 0x2010 && wc < 0x2028)
+        c = mac_hebrew_page20[wc-0x2010];
+    else if (wc == 0x20aa)
+        c = 0xa6;
+    else if (wc >= 0xfb18 && wc < 0xfb50)
+        c = mac_hebrew_pagefb[wc-0xfb18];
+    if (c != 0) {
+       *r = c;
+       return 1;
+    }
+    return 0;
+}
+
+static size_t mac_hebrew_push( void *cd, char **inbuf, size_t *inbytesleft,
+                         char **outbuf, size_t *outbytesleft)
+{
+    unsigned char c = 0;
+    int len = 0;
+    unsigned char *tmpptr = (unsigned char *) *outbuf;
+
+    while (*inbytesleft >= 2 && *outbytesleft >= 1) {
+        ucs2_t *inptr = (ucs2_t *) *inbuf;
+       if (*inptr == 0x05b8) {
+           (*inbuf) += 2;
+           (*inbytesleft)  -= 2;
+           if (*inbytesleft >= 2 && *((ucs2_t *)*inbuf) == 0xf87f ) {
+               (*inbuf) += 2;
+               (*inbytesleft)  -= 2;
+               c = 0xde;
+           }
+           else {
+               c = 0xcb;
+           }
+           *tmpptr = c; 
+       }
+       else if (*inptr == 0x05f2 && *inbytesleft >= 4 && *(inptr +1) == 0x05b7) {
+           (*inbuf) += 4;
+           (*inbytesleft)  -= 4;
+           *tmpptr = 0x81;
+       }
+       else if (*inptr == 0xf86a && *inbytesleft >= 6 && *(inptr +1) == 0x05dc && *(inptr +2) == 0x05b9) {
+           (*inbuf) += 6;
+           (*inbytesleft)  -= 6;
+           *tmpptr = 0xc0;
+       }
+       else if (char_ucs2_to_mac_hebrew ( tmpptr, *inptr)) {
+           (*inbuf) += 2;
+           (*inbytesleft)  -= 2;
+       }
+       else {
+           errno = EILSEQ;
+           return (size_t) -1;
+       }
+       (*outbytesleft) -= 1;
+       tmpptr++;
+       len++;
+    }
+
+    if (*inbytesleft > 0) {
+        errno = E2BIG;
+        return -1;
+    }
+
+    return len;
+}
+
+/* ------------------------ */
+static int
+char_mac_hebrew_to_ucs2 (ucs2_t *pwc, const unsigned char *s)
+{
+       unsigned char c = *s;
+       if (c < 0x80) {
+               *pwc = (ucs2_t) c;
+               return 1;
+       }
+       else {
+               unsigned short wc = mac_hebrew_2uni[c-0x80];
+               if (wc != 0xfffd) {
+                   *pwc = (ucs2_t) wc;
+                   return 1;
+               }
+       }
+       return 0;
+}
+
+static size_t mac_hebrew_pull ( void *cd, char **inbuf, size_t *inbytesleft,
+                         char **outbuf, size_t *outbytesleft)
+{
+    ucs2_t         *temp;
+    unsigned char  *inptr;
+    size_t         len = 0;
+
+    while (*inbytesleft >= 1 && *outbytesleft >= 2) {
+        inptr = (unsigned char *) *inbuf;
+       temp  = (ucs2_t*) *outbuf;      
+       if (char_mac_hebrew_to_ucs2 ( temp, inptr)) {
+           if (*temp == 1) {       /* 0x81 --> 0x05f2+0x05b7 */
+               if (*outbytesleft < 4) {
+                   errno = EILSEQ;
+                   return (size_t) -1; 
+               }
+               *temp = 0x05f2;
+               *(temp +1) = 0x05b7;
+               (*outbuf)      +=4;
+               (*outbytesleft)-=4;
+               len += 2;
+           }
+           else if (*temp == 2) { /* 0xc0 -> 0xf86a 0x05dc 0x05b9*/
+               if (*outbytesleft < 6) {
+                   errno = EILSEQ;
+                   return (size_t) -1; 
+               }
+               *temp = 0xf86a;
+               *(temp +1) = 0x05dc;
+               *(temp +2) = 0x05b9;
+               (*outbuf)      +=6;
+               (*outbytesleft)-=6;
+               len += 3;
+           }
+           else if (*temp == 3) { /* 0xde --> 0x05b8 0xf87f */
+               if (*outbytesleft < 4) {
+                   errno = EILSEQ;
+                   return (size_t) -1; 
+               }
+               *temp = 0x05b8;
+               *(temp +1) = 0xf87f;
+               (*outbuf)      +=4;
+               (*outbytesleft)-=4;
+               len += 2;
+           }
+           else {
+               (*outbuf)      +=2;
+               (*outbytesleft)-=2;
+               len++;
+           }
+           (*inbuf)        +=1;
+           (*inbytesleft) -=1;
+       }
+       else    
+       {
+           errno = EILSEQ;
+           return (size_t) -1; 
+       }
+    }
+
+    if (*inbytesleft > 0) {
+        errno = E2BIG;
+        return (size_t) -1;
+    }
+    return len;
+}
+
diff --git a/libatalk/unicode/mac_hebrew.h b/libatalk/unicode/mac_hebrew.h
new file mode 100644 (file)
index 0000000..dbb55fe
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 1999-2001 Free Software Foundation, Inc.
+ * This file is part of the GNU LIBICONV Library.
+ *
+ * The GNU LIBICONV Library is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * The GNU LIBICONV 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with the GNU LIBICONV Library; see the file COPYING.LIB.
+ * If not, write to the Free Software Foundation, Inc., 59 Temple Place -
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * from libiconv
+ * modified for round trip by didier gautheron
+ * Reference
+ * http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/
+ */
+
+/*
+ * MacHebrew
+ */
+
+static const unsigned short mac_hebrew_2uni[128] = {
+  /* 0x80 0x81 -> 0x05f2+0x05b7 was 0xfb1f */
+  0x00c4,     01, 0x00c7, 0x00c9, 0x00d1, 0x00d6, 0x00dc, 0x00e1,
+  0x00e0, 0x00e2, 0x00e4, 0x00e3, 0x00e5, 0x00e7, 0x00e9, 0x00e8,
+
+  /* 0x90 */
+  0x00ea, 0x00eb, 0x00ed, 0x00ec, 0x00ee, 0x00ef, 0x00f1, 0x00f3,
+  0x00f2, 0x00f4, 0x00f6, 0x00f5, 0x00fa, 0x00f9, 0x00fb, 0x00fc,
+
+  /* 0xa0 */
+  /* 0xffd move to right to left (not 0x20aa) */
+  0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x20aa, 0x0027,
+  0x0029, 0x0028, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+  
+  /* 0xb0 */
+  0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+  0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+
+  /* 0xc0 -> 0xf86a 0x05dc 0x05b9*/
+      02, 0x201e, 0xf89b, 0xf89c, 0xf89d, 0xf89e, 0x05bc, 0xfb4b,
+  0xfb35, 0x2026, 0x00a0, 0x05b8, 0x05b7, 0x05b5, 0x05b6, 0x05b4,
+
+  /* 0xd0 
+     0xde --> 0x05b8 0xf87f 
+  */
+  0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0xfb2a, 0xfb2b,
+  0x05bf, 0x05b0, 0x05b2, 0x05b1, 0x05bb, 0x05b9,     03, 0x05b3,
+  /* 0xe0 */
+  0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7,
+  0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df,
+  /* 0xf0 */
+  0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7,
+  0x05e8, 0x05e9, 0x05ea, 0x007d, 0x005d, 0x007b, 0x005b, 0x007c,
+};
+
+/* (wc >= 0x00a0 && wc < 0x0100) */
+
+static const unsigned char mac_hebrew_page00[96] = {
+  0xca, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x82, /* 0xc0-0xc7 */
+  0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+  0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, /* 0xd0-0xd7 */
+  0x00, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+  0x88, 0x87, 0x89, 0x8b, 0x8a, 0x8c, 0x00, 0x8d, /* 0xe0-0xe7 */
+  0x8f, 0x8e, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95, /* 0xe8-0xef */
+  0x00, 0x96, 0x98, 0x97, 0x99, 0x9b, 0x9a, 0x00, /* 0xf0-0xf7 */
+  0x00, 0x9d, 0x9c, 0x9e, 0x9f, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+/*  (wc >= 0x05b0 && wc < 0x05f0) */
+static const unsigned char mac_hebrew_page05[64] = {
+  0xd9, 0xdb, 0xda, 0xdf, 0xcf, 0xcd, 0xce, 0xcc, /* 0xb0-0xb7 */
+  0xcb, 0xdd, 0x00, 0xdc, 0xc6, 0x00, 0x00, 0xd8, /* 0xb8-0xbf */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+  0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xd0-0xd7 */
+  0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xd8-0xdf */
+  0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xe0-0xe7 */
+  0xf8, 0xf9, 0xfa, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+};
+
+/* (wc >= 0x2010 && wc < 0x2028) */
+static const unsigned char mac_hebrew_page20[24] = {
+  0x00, 0x00, 0x00, 0xd0, 0xd1, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+  0xd4, 0xd5, 0x00, 0x00, 0xd2, 0xd3, 0xc1, 0x00, /* 0x18-0x1f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc9, 0x00, /* 0x20-0x27 */
+};
+
+/* (wc >= 0xfb18 && wc < 0xfb50) */
+static const unsigned char mac_hebrew_pagefb[56] = {
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, /* 0x18-0x1f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+  0x00, 0x00, 0xd6, 0xd7, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, /* 0x30-0x37 */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+  0x00, 0x00, 0x00, 0xc7, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+};
+
diff --git a/libatalk/unicode/mac_roman.h b/libatalk/unicode/mac_roman.h
new file mode 100644 (file)
index 0000000..83b08cf
--- /dev/null
@@ -0,0 +1,118 @@
+
+/*
+ * $Id: mac_roman.h,v 1.1.2.1 2003-06-23 10:25:08 didg Exp $
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * from GNU libiconv
+ * modified by Bjorn (Apple Logo 0xf0 to Apple unicode 0xf8ff )
+ */
+
+
+static const unsigned char mac_roman_page00[96] = {
+  0xca, 0xc1, 0xa2, 0xa3, 0xdb, 0xb4, 0x00, 0xa4, /* 0xa0-0xa7 */
+  0xac, 0xa9, 0xbb, 0xc7, 0xc2, 0x00, 0xa8, 0xf8, /* 0xa8-0xaf */
+  0xa1, 0xb1, 0x00, 0x00, 0xab, 0xb5, 0xa6, 0xe1, /* 0xb0-0xb7 */
+  0xfc, 0x00, 0xbc, 0xc8, 0x00, 0x00, 0x00, 0xc0, /* 0xb8-0xbf */
+  0xcb, 0xe7, 0xe5, 0xcc, 0x80, 0x81, 0xae, 0x82, /* 0xc0-0xc7 */
+  0xe9, 0x83, 0xe6, 0xe8, 0xed, 0xea, 0xeb, 0xec, /* 0xc8-0xcf */
+  0x00, 0x84, 0xf1, 0xee, 0xef, 0xcd, 0x85, 0x00, /* 0xd0-0xd7 */
+  0xaf, 0xf4, 0xf2, 0xf3, 0x86, 0x00, 0x00, 0xa7, /* 0xd8-0xdf */
+  0x88, 0x87, 0x89, 0x8b, 0x8a, 0x8c, 0xbe, 0x8d, /* 0xe0-0xe7 */
+  0x8f, 0x8e, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95, /* 0xe8-0xef */
+  0x00, 0x96, 0x98, 0x97, 0x99, 0x9b, 0x9a, 0xd6, /* 0xf0-0xf7 */
+  0xbf, 0x9d, 0x9c, 0x9e, 0x9f, 0x00, 0x00, 0xd8, /* 0xf8-0xff */
+};
+static const unsigned char mac_roman_page01[104] = {
+  0x00, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+  0x00, 0x00, 0xce, 0xcf, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+  0xd9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+  0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+};
+static const unsigned char mac_roman_page02[32] = {
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xff, /* 0xc0-0xc7 */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+  0xf9, 0xfa, 0xfb, 0xfe, 0xf7, 0xfd, 0x00, 0x00, /* 0xd8-0xdf */
+};
+static const unsigned char mac_roman_page20[56] = {
+  0x00, 0x00, 0x00, 0xd0, 0xd1, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+  0xd4, 0xd5, 0xe2, 0x00, 0xd2, 0xd3, 0xe3, 0x00, /* 0x18-0x1f */
+  0xa0, 0xe0, 0xa5, 0x00, 0x00, 0x00, 0xc9, 0x00, /* 0x20-0x27 */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+  0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+  0x00, 0xdc, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+  0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+};
+static const unsigned char mac_roman_page21[8] = {
+  0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0xbd, 0x00, /* 0x20-0x27 */
+};
+static const unsigned char mac_roman_page22[104] = {
+  0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0xc6, 0x00, /* 0x00-0x07 */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, /* 0x08-0x0f */
+  0x00, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+  0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, 0xb0, 0x00, /* 0x18-0x1f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+  0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+  0xc5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+  0xad, 0x00, 0x00, 0x00, 0xb2, 0xb3, 0x00, 0x00, /* 0x60-0x67 */
+};
+static const unsigned char mac_roman_pagefb[8] = {
+  0x00, 0xde, 0xdf, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+};
+
+
+
+
+static const unsigned short mac_roman_2uni[128] = {
+  /* 0x80 */
+  0x00c4, 0x00c5, 0x00c7, 0x00c9, 0x00d1, 0x00d6, 0x00dc, 0x00e1,
+  0x00e0, 0x00e2, 0x00e4, 0x00e3, 0x00e5, 0x00e7, 0x00e9, 0x00e8,
+  /* 0x90 */
+  0x00ea, 0x00eb, 0x00ed, 0x00ec, 0x00ee, 0x00ef, 0x00f1, 0x00f3,
+  0x00f2, 0x00f4, 0x00f6, 0x00f5, 0x00fa, 0x00f9, 0x00fb, 0x00fc,
+  /* 0xa0 */
+  0x2020, 0x00b0, 0x00a2, 0x00a3, 0x00a7, 0x2022, 0x00b6, 0x00df,
+  0x00ae, 0x00a9, 0x2122, 0x00b4, 0x00a8, 0x2260, 0x00c6, 0x00d8,
+  /* 0xb0 */
+  0x221e, 0x00b1, 0x2264, 0x2265, 0x00a5, 0x00b5, 0x2202, 0x2211,
+  0x220f, 0x03c0, 0x222b, 0x00aa, 0x00ba, 0x2126, 0x00e6, 0x00f8,
+  /* 0xc0 */
+  0x00bf, 0x00a1, 0x00ac, 0x221a, 0x0192, 0x2248, 0x2206, 0x00ab,
+  0x00bb, 0x2026, 0x00a0, 0x00c0, 0x00c3, 0x00d5, 0x0152, 0x0153,
+  /* 0xd0 */
+  0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0x00f7, 0x25ca,
+  0x00ff, 0x0178, 0x2044, 0x00a4, 0x2039, 0x203a, 0xfb01, 0xfb02,
+  /* 0xe0 */
+  0x2021, 0x00b7, 0x201a, 0x201e, 0x2030, 0x00c2, 0x00ca, 0x00c1,
+  0x00cb, 0x00c8, 0x00cd, 0x00ce, 0x00cf, 0x00cc, 0x00d3, 0x00d4,
+  /* 0xf0 */
+  0xf8ff, 0x00d2, 0x00da, 0x00db, 0x00d9, 0x0131, 0x02c6, 0x02dc,
+  0x00af, 0x02d8, 0x02d9, 0x02da, 0x00b8, 0x02dd, 0x02db, 0x02c7,
+};
diff --git a/libatalk/unicode/precompose.h b/libatalk/unicode/precompose.h
new file mode 100644 (file)
index 0000000..bd578bf
--- /dev/null
@@ -0,0 +1,1995 @@
+/*
+ * Canonical Compositions
+ * from xfree86 project
+ */
+/* $XFree86: xc/programs/xterm/precompose.c,v 1.2 2000/11/01 01:12:41 dawes Exp $ */
+
+static const struct {
+  unsigned int replacement;
+  unsigned int base;
+  unsigned int comb; 
+} precompositions[] = {
+{ 0x226E, 0x003C, 0x0338},
+{ 0x2260, 0x003D, 0x0338},
+{ 0x226F, 0x003E, 0x0338},
+{ 0x00C0, 0x0041, 0x0300},
+{ 0x00C1, 0x0041, 0x0301},
+{ 0x00C2, 0x0041, 0x0302},
+{ 0x00C3, 0x0041, 0x0303},
+{ 0x0100, 0x0041, 0x0304},
+{ 0x0102, 0x0041, 0x0306},
+{ 0x0226, 0x0041, 0x0307},
+{ 0x00C4, 0x0041, 0x0308},
+{ 0x1EA2, 0x0041, 0x0309},
+{ 0x00C5, 0x0041, 0x030A},
+{ 0x01CD, 0x0041, 0x030C},
+{ 0x0200, 0x0041, 0x030F},
+{ 0x0202, 0x0041, 0x0311},
+{ 0x1EA0, 0x0041, 0x0323},
+{ 0x1E00, 0x0041, 0x0325},
+{ 0x0104, 0x0041, 0x0328},
+{ 0x1E02, 0x0042, 0x0307},
+{ 0x1E04, 0x0042, 0x0323},
+{ 0x1E06, 0x0042, 0x0331},
+{ 0x0106, 0x0043, 0x0301},
+{ 0x0108, 0x0043, 0x0302},
+{ 0x010A, 0x0043, 0x0307},
+{ 0x010C, 0x0043, 0x030C},
+{ 0x00C7, 0x0043, 0x0327},
+{ 0x1E0A, 0x0044, 0x0307},
+{ 0x010E, 0x0044, 0x030C},
+{ 0x1E0C, 0x0044, 0x0323},
+{ 0x1E10, 0x0044, 0x0327},
+{ 0x1E12, 0x0044, 0x032D},
+{ 0x1E0E, 0x0044, 0x0331},
+{ 0x00C8, 0x0045, 0x0300},
+{ 0x00C9, 0x0045, 0x0301},
+{ 0x00CA, 0x0045, 0x0302},
+{ 0x1EBC, 0x0045, 0x0303},
+{ 0x0112, 0x0045, 0x0304},
+{ 0x0114, 0x0045, 0x0306},
+{ 0x0116, 0x0045, 0x0307},
+{ 0x00CB, 0x0045, 0x0308},
+{ 0x1EBA, 0x0045, 0x0309},
+{ 0x011A, 0x0045, 0x030C},
+{ 0x0204, 0x0045, 0x030F},
+{ 0x0206, 0x0045, 0x0311},
+{ 0x1EB8, 0x0045, 0x0323},
+{ 0x0228, 0x0045, 0x0327},
+{ 0x0118, 0x0045, 0x0328},
+{ 0x1E18, 0x0045, 0x032D},
+{ 0x1E1A, 0x0045, 0x0330},
+{ 0x1E1E, 0x0046, 0x0307},
+{ 0x01F4, 0x0047, 0x0301},
+{ 0x011C, 0x0047, 0x0302},
+{ 0x1E20, 0x0047, 0x0304},
+{ 0x011E, 0x0047, 0x0306},
+{ 0x0120, 0x0047, 0x0307},
+{ 0x01E6, 0x0047, 0x030C},
+{ 0x0122, 0x0047, 0x0327},
+{ 0x0124, 0x0048, 0x0302},
+{ 0x1E22, 0x0048, 0x0307},
+{ 0x1E26, 0x0048, 0x0308},
+{ 0x021E, 0x0048, 0x030C},
+{ 0x1E24, 0x0048, 0x0323},
+{ 0x1E28, 0x0048, 0x0327},
+{ 0x1E2A, 0x0048, 0x032E},
+{ 0x00CC, 0x0049, 0x0300},
+{ 0x00CD, 0x0049, 0x0301},
+{ 0x00CE, 0x0049, 0x0302},
+{ 0x0128, 0x0049, 0x0303},
+{ 0x012A, 0x0049, 0x0304},
+{ 0x012C, 0x0049, 0x0306},
+{ 0x0130, 0x0049, 0x0307},
+{ 0x00CF, 0x0049, 0x0308},
+{ 0x1EC8, 0x0049, 0x0309},
+{ 0x01CF, 0x0049, 0x030C},
+{ 0x0208, 0x0049, 0x030F},
+{ 0x020A, 0x0049, 0x0311},
+{ 0x1ECA, 0x0049, 0x0323},
+{ 0x012E, 0x0049, 0x0328},
+{ 0x1E2C, 0x0049, 0x0330},
+{ 0x0134, 0x004A, 0x0302},
+{ 0x1E30, 0x004B, 0x0301},
+{ 0x01E8, 0x004B, 0x030C},
+{ 0x1E32, 0x004B, 0x0323},
+{ 0x0136, 0x004B, 0x0327},
+{ 0x1E34, 0x004B, 0x0331},
+{ 0x0139, 0x004C, 0x0301},
+{ 0x013D, 0x004C, 0x030C},
+{ 0x1E36, 0x004C, 0x0323},
+{ 0x013B, 0x004C, 0x0327},
+{ 0x1E3C, 0x004C, 0x032D},
+{ 0x1E3A, 0x004C, 0x0331},
+{ 0x1E3E, 0x004D, 0x0301},
+{ 0x1E40, 0x004D, 0x0307},
+{ 0x1E42, 0x004D, 0x0323},
+{ 0x01F8, 0x004E, 0x0300},
+{ 0x0143, 0x004E, 0x0301},
+{ 0x00D1, 0x004E, 0x0303},
+{ 0x1E44, 0x004E, 0x0307},
+{ 0x0147, 0x004E, 0x030C},
+{ 0x1E46, 0x004E, 0x0323},
+{ 0x0145, 0x004E, 0x0327},
+{ 0x1E4A, 0x004E, 0x032D},
+{ 0x1E48, 0x004E, 0x0331},
+{ 0x00D2, 0x004F, 0x0300},
+{ 0x00D3, 0x004F, 0x0301},
+{ 0x00D4, 0x004F, 0x0302},
+{ 0x00D5, 0x004F, 0x0303},
+{ 0x014C, 0x004F, 0x0304},
+{ 0x014E, 0x004F, 0x0306},
+{ 0x022E, 0x004F, 0x0307},
+{ 0x00D6, 0x004F, 0x0308},
+{ 0x1ECE, 0x004F, 0x0309},
+{ 0x0150, 0x004F, 0x030B},
+{ 0x01D1, 0x004F, 0x030C},
+{ 0x020C, 0x004F, 0x030F},
+{ 0x020E, 0x004F, 0x0311},
+{ 0x01A0, 0x004F, 0x031B},
+{ 0x1ECC, 0x004F, 0x0323},
+{ 0x01EA, 0x004F, 0x0328},
+{ 0x1E54, 0x0050, 0x0301},
+{ 0x1E56, 0x0050, 0x0307},
+{ 0x0154, 0x0052, 0x0301},
+{ 0x1E58, 0x0052, 0x0307},
+{ 0x0158, 0x0052, 0x030C},
+{ 0x0210, 0x0052, 0x030F},
+{ 0x0212, 0x0052, 0x0311},
+{ 0x1E5A, 0x0052, 0x0323},
+{ 0x0156, 0x0052, 0x0327},
+{ 0x1E5E, 0x0052, 0x0331},
+{ 0x015A, 0x0053, 0x0301},
+{ 0x015C, 0x0053, 0x0302},
+{ 0x1E60, 0x0053, 0x0307},
+{ 0x0160, 0x0053, 0x030C},
+{ 0x1E62, 0x0053, 0x0323},
+{ 0x0218, 0x0053, 0x0326},
+{ 0x015E, 0x0053, 0x0327},
+{ 0x1E6A, 0x0054, 0x0307},
+{ 0x0164, 0x0054, 0x030C},
+{ 0x1E6C, 0x0054, 0x0323},
+{ 0x021A, 0x0054, 0x0326},
+{ 0x0162, 0x0054, 0x0327},
+{ 0x1E70, 0x0054, 0x032D},
+{ 0x1E6E, 0x0054, 0x0331},
+{ 0x00D9, 0x0055, 0x0300},
+{ 0x00DA, 0x0055, 0x0301},
+{ 0x00DB, 0x0055, 0x0302},
+{ 0x0168, 0x0055, 0x0303},
+{ 0x016A, 0x0055, 0x0304},
+{ 0x016C, 0x0055, 0x0306},
+{ 0x00DC, 0x0055, 0x0308},
+{ 0x1EE6, 0x0055, 0x0309},
+{ 0x016E, 0x0055, 0x030A},
+{ 0x0170, 0x0055, 0x030B},
+{ 0x01D3, 0x0055, 0x030C},
+{ 0x0214, 0x0055, 0x030F},
+{ 0x0216, 0x0055, 0x0311},
+{ 0x01AF, 0x0055, 0x031B},
+{ 0x1EE4, 0x0055, 0x0323},
+{ 0x1E72, 0x0055, 0x0324},
+{ 0x0172, 0x0055, 0x0328},
+{ 0x1E76, 0x0055, 0x032D},
+{ 0x1E74, 0x0055, 0x0330},
+{ 0x1E7C, 0x0056, 0x0303},
+{ 0x1E7E, 0x0056, 0x0323},
+{ 0x1E80, 0x0057, 0x0300},
+{ 0x1E82, 0x0057, 0x0301},
+{ 0x0174, 0x0057, 0x0302},
+{ 0x1E86, 0x0057, 0x0307},
+{ 0x1E84, 0x0057, 0x0308},
+{ 0x1E88, 0x0057, 0x0323},
+{ 0x1E8A, 0x0058, 0x0307},
+{ 0x1E8C, 0x0058, 0x0308},
+{ 0x1EF2, 0x0059, 0x0300},
+{ 0x00DD, 0x0059, 0x0301},
+{ 0x0176, 0x0059, 0x0302},
+{ 0x1EF8, 0x0059, 0x0303},
+{ 0x0232, 0x0059, 0x0304},
+{ 0x1E8E, 0x0059, 0x0307},
+{ 0x0178, 0x0059, 0x0308},
+{ 0x1EF6, 0x0059, 0x0309},
+{ 0x1EF4, 0x0059, 0x0323},
+{ 0x0179, 0x005A, 0x0301},
+{ 0x1E90, 0x005A, 0x0302},
+{ 0x017B, 0x005A, 0x0307},
+{ 0x017D, 0x005A, 0x030C},
+{ 0x1E92, 0x005A, 0x0323},
+{ 0x1E94, 0x005A, 0x0331},
+{ 0x00E0, 0x0061, 0x0300},
+{ 0x00E1, 0x0061, 0x0301},
+{ 0x00E2, 0x0061, 0x0302},
+{ 0x00E3, 0x0061, 0x0303},
+{ 0x0101, 0x0061, 0x0304},
+{ 0x0103, 0x0061, 0x0306},
+{ 0x0227, 0x0061, 0x0307},
+{ 0x00E4, 0x0061, 0x0308},
+{ 0x1EA3, 0x0061, 0x0309},
+{ 0x00E5, 0x0061, 0x030A},
+{ 0x01CE, 0x0061, 0x030C},
+{ 0x0201, 0x0061, 0x030F},
+{ 0x0203, 0x0061, 0x0311},
+{ 0x1EA1, 0x0061, 0x0323},
+{ 0x1E01, 0x0061, 0x0325},
+{ 0x0105, 0x0061, 0x0328},
+{ 0x1E03, 0x0062, 0x0307},
+{ 0x1E05, 0x0062, 0x0323},
+{ 0x1E07, 0x0062, 0x0331},
+{ 0x0107, 0x0063, 0x0301},
+{ 0x0109, 0x0063, 0x0302},
+{ 0x010B, 0x0063, 0x0307},
+{ 0x010D, 0x0063, 0x030C},
+{ 0x00E7, 0x0063, 0x0327},
+{ 0x1E0B, 0x0064, 0x0307},
+{ 0x010F, 0x0064, 0x030C},
+{ 0x1E0D, 0x0064, 0x0323},
+{ 0x1E11, 0x0064, 0x0327},
+{ 0x1E13, 0x0064, 0x032D},
+{ 0x1E0F, 0x0064, 0x0331},
+{ 0x00E8, 0x0065, 0x0300},
+{ 0x00E9, 0x0065, 0x0301},
+{ 0x00EA, 0x0065, 0x0302},
+{ 0x1EBD, 0x0065, 0x0303},
+{ 0x0113, 0x0065, 0x0304},
+{ 0x0115, 0x0065, 0x0306},
+{ 0x0117, 0x0065, 0x0307},
+{ 0x00EB, 0x0065, 0x0308},
+{ 0x1EBB, 0x0065, 0x0309},
+{ 0x011B, 0x0065, 0x030C},
+{ 0x0205, 0x0065, 0x030F},
+{ 0x0207, 0x0065, 0x0311},
+{ 0x1EB9, 0x0065, 0x0323},
+{ 0x0229, 0x0065, 0x0327},
+{ 0x0119, 0x0065, 0x0328},
+{ 0x1E19, 0x0065, 0x032D},
+{ 0x1E1B, 0x0065, 0x0330},
+{ 0x1E1F, 0x0066, 0x0307},
+{ 0x01F5, 0x0067, 0x0301},
+{ 0x011D, 0x0067, 0x0302},
+{ 0x1E21, 0x0067, 0x0304},
+{ 0x011F, 0x0067, 0x0306},
+{ 0x0121, 0x0067, 0x0307},
+{ 0x01E7, 0x0067, 0x030C},
+{ 0x0123, 0x0067, 0x0327},
+{ 0x0125, 0x0068, 0x0302},
+{ 0x1E23, 0x0068, 0x0307},
+{ 0x1E27, 0x0068, 0x0308},
+{ 0x021F, 0x0068, 0x030C},
+{ 0x1E25, 0x0068, 0x0323},
+{ 0x1E29, 0x0068, 0x0327},
+{ 0x1E2B, 0x0068, 0x032E},
+{ 0x1E96, 0x0068, 0x0331},
+{ 0x00EC, 0x0069, 0x0300},
+{ 0x00ED, 0x0069, 0x0301},
+{ 0x00EE, 0x0069, 0x0302},
+{ 0x0129, 0x0069, 0x0303},
+{ 0x012B, 0x0069, 0x0304},
+{ 0x012D, 0x0069, 0x0306},
+{ 0x00EF, 0x0069, 0x0308},
+{ 0x1EC9, 0x0069, 0x0309},
+{ 0x01D0, 0x0069, 0x030C},
+{ 0x0209, 0x0069, 0x030F},
+{ 0x020B, 0x0069, 0x0311},
+{ 0x1ECB, 0x0069, 0x0323},
+{ 0x012F, 0x0069, 0x0328},
+{ 0x1E2D, 0x0069, 0x0330},
+{ 0x0135, 0x006A, 0x0302},
+{ 0x01F0, 0x006A, 0x030C},
+{ 0x1E31, 0x006B, 0x0301},
+{ 0x01E9, 0x006B, 0x030C},
+{ 0x1E33, 0x006B, 0x0323},
+{ 0x0137, 0x006B, 0x0327},
+{ 0x1E35, 0x006B, 0x0331},
+{ 0x013A, 0x006C, 0x0301},
+{ 0x013E, 0x006C, 0x030C},
+{ 0x1E37, 0x006C, 0x0323},
+{ 0x013C, 0x006C, 0x0327},
+{ 0x1E3D, 0x006C, 0x032D},
+{ 0x1E3B, 0x006C, 0x0331},
+{ 0x1E3F, 0x006D, 0x0301},
+{ 0x1E41, 0x006D, 0x0307},
+{ 0x1E43, 0x006D, 0x0323},
+{ 0x01F9, 0x006E, 0x0300},
+{ 0x0144, 0x006E, 0x0301},
+{ 0x00F1, 0x006E, 0x0303},
+{ 0x1E45, 0x006E, 0x0307},
+{ 0x0148, 0x006E, 0x030C},
+{ 0x1E47, 0x006E, 0x0323},
+{ 0x0146, 0x006E, 0x0327},
+{ 0x1E4B, 0x006E, 0x032D},
+{ 0x1E49, 0x006E, 0x0331},
+{ 0x00F2, 0x006F, 0x0300},
+{ 0x00F3, 0x006F, 0x0301},
+{ 0x00F4, 0x006F, 0x0302},
+{ 0x00F5, 0x006F, 0x0303},
+{ 0x014D, 0x006F, 0x0304},
+{ 0x014F, 0x006F, 0x0306},
+{ 0x022F, 0x006F, 0x0307},
+{ 0x00F6, 0x006F, 0x0308},
+{ 0x1ECF, 0x006F, 0x0309},
+{ 0x0151, 0x006F, 0x030B},
+{ 0x01D2, 0x006F, 0x030C},
+{ 0x020D, 0x006F, 0x030F},
+{ 0x020F, 0x006F, 0x0311},
+{ 0x01A1, 0x006F, 0x031B},
+{ 0x1ECD, 0x006F, 0x0323},
+{ 0x01EB, 0x006F, 0x0328},
+{ 0x1E55, 0x0070, 0x0301},
+{ 0x1E57, 0x0070, 0x0307},
+{ 0x0155, 0x0072, 0x0301},
+{ 0x1E59, 0x0072, 0x0307},
+{ 0x0159, 0x0072, 0x030C},
+{ 0x0211, 0x0072, 0x030F},
+{ 0x0213, 0x0072, 0x0311},
+{ 0x1E5B, 0x0072, 0x0323},
+{ 0x0157, 0x0072, 0x0327},
+{ 0x1E5F, 0x0072, 0x0331},
+{ 0x015B, 0x0073, 0x0301},
+{ 0x015D, 0x0073, 0x0302},
+{ 0x1E61, 0x0073, 0x0307},
+{ 0x0161, 0x0073, 0x030C},
+{ 0x1E63, 0x0073, 0x0323},
+{ 0x0219, 0x0073, 0x0326},
+{ 0x015F, 0x0073, 0x0327},
+{ 0x1E6B, 0x0074, 0x0307},
+{ 0x1E97, 0x0074, 0x0308},
+{ 0x0165, 0x0074, 0x030C},
+{ 0x1E6D, 0x0074, 0x0323},
+{ 0x021B, 0x0074, 0x0326},
+{ 0x0163, 0x0074, 0x0327},
+{ 0x1E71, 0x0074, 0x032D},
+{ 0x1E6F, 0x0074, 0x0331},
+{ 0x00F9, 0x0075, 0x0300},
+{ 0x00FA, 0x0075, 0x0301},
+{ 0x00FB, 0x0075, 0x0302},
+{ 0x0169, 0x0075, 0x0303},
+{ 0x016B, 0x0075, 0x0304},
+{ 0x016D, 0x0075, 0x0306},
+{ 0x00FC, 0x0075, 0x0308},
+{ 0x1EE7, 0x0075, 0x0309},
+{ 0x016F, 0x0075, 0x030A},
+{ 0x0171, 0x0075, 0x030B},
+{ 0x01D4, 0x0075, 0x030C},
+{ 0x0215, 0x0075, 0x030F},
+{ 0x0217, 0x0075, 0x0311},
+{ 0x01B0, 0x0075, 0x031B},
+{ 0x1EE5, 0x0075, 0x0323},
+{ 0x1E73, 0x0075, 0x0324},
+{ 0x0173, 0x0075, 0x0328},
+{ 0x1E77, 0x0075, 0x032D},
+{ 0x1E75, 0x0075, 0x0330},
+{ 0x1E7D, 0x0076, 0x0303},
+{ 0x1E7F, 0x0076, 0x0323},
+{ 0x1E81, 0x0077, 0x0300},
+{ 0x1E83, 0x0077, 0x0301},
+{ 0x0175, 0x0077, 0x0302},
+{ 0x1E87, 0x0077, 0x0307},
+{ 0x1E85, 0x0077, 0x0308},
+{ 0x1E98, 0x0077, 0x030A},
+{ 0x1E89, 0x0077, 0x0323},
+{ 0x1E8B, 0x0078, 0x0307},
+{ 0x1E8D, 0x0078, 0x0308},
+{ 0x1EF3, 0x0079, 0x0300},
+{ 0x00FD, 0x0079, 0x0301},
+{ 0x0177, 0x0079, 0x0302},
+{ 0x1EF9, 0x0079, 0x0303},
+{ 0x0233, 0x0079, 0x0304},
+{ 0x1E8F, 0x0079, 0x0307},
+{ 0x00FF, 0x0079, 0x0308},
+{ 0x1EF7, 0x0079, 0x0309},
+{ 0x1E99, 0x0079, 0x030A},
+{ 0x1EF5, 0x0079, 0x0323},
+{ 0x017A, 0x007A, 0x0301},
+{ 0x1E91, 0x007A, 0x0302},
+{ 0x017C, 0x007A, 0x0307},
+{ 0x017E, 0x007A, 0x030C},
+{ 0x1E93, 0x007A, 0x0323},
+{ 0x1E95, 0x007A, 0x0331},
+{ 0x1FED, 0x00A8, 0x0300},
+{ 0x0385, 0x00A8, 0x0301},
+{ 0x1FC1, 0x00A8, 0x0342},
+{ 0x1EA6, 0x00C2, 0x0300},
+{ 0x1EA4, 0x00C2, 0x0301},
+{ 0x1EAA, 0x00C2, 0x0303},
+{ 0x1EA8, 0x00C2, 0x0309},
+{ 0x01DE, 0x00C4, 0x0304},
+{ 0x01FA, 0x00C5, 0x0301},
+{ 0x01FC, 0x00C6, 0x0301},
+{ 0x01E2, 0x00C6, 0x0304},
+{ 0x1E08, 0x00C7, 0x0301},
+{ 0x1EC0, 0x00CA, 0x0300},
+{ 0x1EBE, 0x00CA, 0x0301},
+{ 0x1EC4, 0x00CA, 0x0303},
+{ 0x1EC2, 0x00CA, 0x0309},
+{ 0x1E2E, 0x00CF, 0x0301},
+{ 0x1ED2, 0x00D4, 0x0300},
+{ 0x1ED0, 0x00D4, 0x0301},
+{ 0x1ED6, 0x00D4, 0x0303},
+{ 0x1ED4, 0x00D4, 0x0309},
+{ 0x1E4C, 0x00D5, 0x0301},
+{ 0x022C, 0x00D5, 0x0304},
+{ 0x1E4E, 0x00D5, 0x0308},
+{ 0x022A, 0x00D6, 0x0304},
+{ 0x01FE, 0x00D8, 0x0301},
+{ 0x01DB, 0x00DC, 0x0300},
+{ 0x01D7, 0x00DC, 0x0301},
+{ 0x01D5, 0x00DC, 0x0304},
+{ 0x01D9, 0x00DC, 0x030C},
+{ 0x1EA7, 0x00E2, 0x0300},
+{ 0x1EA5, 0x00E2, 0x0301},
+{ 0x1EAB, 0x00E2, 0x0303},
+{ 0x1EA9, 0x00E2, 0x0309},
+{ 0x01DF, 0x00E4, 0x0304},
+{ 0x01FB, 0x00E5, 0x0301},
+{ 0x01FD, 0x00E6, 0x0301},
+{ 0x01E3, 0x00E6, 0x0304},
+{ 0x1E09, 0x00E7, 0x0301},
+{ 0x1EC1, 0x00EA, 0x0300},
+{ 0x1EBF, 0x00EA, 0x0301},
+{ 0x1EC5, 0x00EA, 0x0303},
+{ 0x1EC3, 0x00EA, 0x0309},
+{ 0x1E2F, 0x00EF, 0x0301},
+{ 0x1ED3, 0x00F4, 0x0300},
+{ 0x1ED1, 0x00F4, 0x0301},
+{ 0x1ED7, 0x00F4, 0x0303},
+{ 0x1ED5, 0x00F4, 0x0309},
+{ 0x1E4D, 0x00F5, 0x0301},
+{ 0x022D, 0x00F5, 0x0304},
+{ 0x1E4F, 0x00F5, 0x0308},
+{ 0x022B, 0x00F6, 0x0304},
+{ 0x01FF, 0x00F8, 0x0301},
+{ 0x01DC, 0x00FC, 0x0300},
+{ 0x01D8, 0x00FC, 0x0301},
+{ 0x01D6, 0x00FC, 0x0304},
+{ 0x01DA, 0x00FC, 0x030C},
+{ 0x1EB0, 0x0102, 0x0300},
+{ 0x1EAE, 0x0102, 0x0301},
+{ 0x1EB4, 0x0102, 0x0303},
+{ 0x1EB2, 0x0102, 0x0309},
+{ 0x1EB1, 0x0103, 0x0300},
+{ 0x1EAF, 0x0103, 0x0301},
+{ 0x1EB5, 0x0103, 0x0303},
+{ 0x1EB3, 0x0103, 0x0309},
+{ 0x1E14, 0x0112, 0x0300},
+{ 0x1E16, 0x0112, 0x0301},
+{ 0x1E15, 0x0113, 0x0300},
+{ 0x1E17, 0x0113, 0x0301},
+{ 0x1E50, 0x014C, 0x0300},
+{ 0x1E52, 0x014C, 0x0301},
+{ 0x1E51, 0x014D, 0x0300},
+{ 0x1E53, 0x014D, 0x0301},
+{ 0x1E64, 0x015A, 0x0307},
+{ 0x1E65, 0x015B, 0x0307},
+{ 0x1E66, 0x0160, 0x0307},
+{ 0x1E67, 0x0161, 0x0307},
+{ 0x1E78, 0x0168, 0x0301},
+{ 0x1E79, 0x0169, 0x0301},
+{ 0x1E7A, 0x016A, 0x0308},
+{ 0x1E7B, 0x016B, 0x0308},
+{ 0x1E9B, 0x017F, 0x0307},
+{ 0x1EDC, 0x01A0, 0x0300},
+{ 0x1EDA, 0x01A0, 0x0301},
+{ 0x1EE0, 0x01A0, 0x0303},
+{ 0x1EDE, 0x01A0, 0x0309},
+{ 0x1EE2, 0x01A0, 0x0323},
+{ 0x1EDD, 0x01A1, 0x0300},
+{ 0x1EDB, 0x01A1, 0x0301},
+{ 0x1EE1, 0x01A1, 0x0303},
+{ 0x1EDF, 0x01A1, 0x0309},
+{ 0x1EE3, 0x01A1, 0x0323},
+{ 0x1EEA, 0x01AF, 0x0300},
+{ 0x1EE8, 0x01AF, 0x0301},
+{ 0x1EEE, 0x01AF, 0x0303},
+{ 0x1EEC, 0x01AF, 0x0309},
+{ 0x1EF0, 0x01AF, 0x0323},
+{ 0x1EEB, 0x01B0, 0x0300},
+{ 0x1EE9, 0x01B0, 0x0301},
+{ 0x1EEF, 0x01B0, 0x0303},
+{ 0x1EED, 0x01B0, 0x0309},
+{ 0x1EF1, 0x01B0, 0x0323},
+{ 0x01EE, 0x01B7, 0x030C},
+{ 0x01EC, 0x01EA, 0x0304},
+{ 0x01ED, 0x01EB, 0x0304},
+{ 0x01E0, 0x0226, 0x0304},
+{ 0x01E1, 0x0227, 0x0304},
+{ 0x1E1C, 0x0228, 0x0306},
+{ 0x1E1D, 0x0229, 0x0306},
+{ 0x0230, 0x022E, 0x0304},
+{ 0x0231, 0x022F, 0x0304},
+{ 0x01EF, 0x0292, 0x030C},
+{ 0x0344, 0x0308, 0x0301},
+{ 0x1FBA, 0x0391, 0x0300},
+{ 0x0386, 0x0391, 0x0301},
+{ 0x1FB9, 0x0391, 0x0304},
+{ 0x1FB8, 0x0391, 0x0306},
+{ 0x1F08, 0x0391, 0x0313},
+{ 0x1F09, 0x0391, 0x0314},
+{ 0x1FBC, 0x0391, 0x0345},
+{ 0x1FC8, 0x0395, 0x0300},
+{ 0x0388, 0x0395, 0x0301},
+{ 0x1F18, 0x0395, 0x0313},
+{ 0x1F19, 0x0395, 0x0314},
+{ 0x1FCA, 0x0397, 0x0300},
+{ 0x0389, 0x0397, 0x0301},
+{ 0x1F28, 0x0397, 0x0313},
+{ 0x1F29, 0x0397, 0x0314},
+{ 0x1FCC, 0x0397, 0x0345},
+{ 0x1FDA, 0x0399, 0x0300},
+{ 0x038A, 0x0399, 0x0301},
+{ 0x1FD9, 0x0399, 0x0304},
+{ 0x1FD8, 0x0399, 0x0306},
+{ 0x03AA, 0x0399, 0x0308},
+{ 0x1F38, 0x0399, 0x0313},
+{ 0x1F39, 0x0399, 0x0314},
+{ 0x1FF8, 0x039F, 0x0300},
+{ 0x038C, 0x039F, 0x0301},
+{ 0x1F48, 0x039F, 0x0313},
+{ 0x1F49, 0x039F, 0x0314},
+{ 0x1FEC, 0x03A1, 0x0314},
+{ 0x1FEA, 0x03A5, 0x0300},
+{ 0x038E, 0x03A5, 0x0301},
+{ 0x1FE9, 0x03A5, 0x0304},
+{ 0x1FE8, 0x03A5, 0x0306},
+{ 0x03AB, 0x03A5, 0x0308},
+{ 0x1F59, 0x03A5, 0x0314},
+{ 0x1FFA, 0x03A9, 0x0300},
+{ 0x038F, 0x03A9, 0x0301},
+{ 0x1F68, 0x03A9, 0x0313},
+{ 0x1F69, 0x03A9, 0x0314},
+{ 0x1FFC, 0x03A9, 0x0345},
+{ 0x1FB4, 0x03AC, 0x0345},
+{ 0x1FC4, 0x03AE, 0x0345},
+{ 0x1F70, 0x03B1, 0x0300},
+{ 0x03AC, 0x03B1, 0x0301},
+{ 0x1FB1, 0x03B1, 0x0304},
+{ 0x1FB0, 0x03B1, 0x0306},
+{ 0x1F00, 0x03B1, 0x0313},
+{ 0x1F01, 0x03B1, 0x0314},
+{ 0x1FB6, 0x03B1, 0x0342},
+{ 0x1FB3, 0x03B1, 0x0345},
+{ 0x1F72, 0x03B5, 0x0300},
+{ 0x03AD, 0x03B5, 0x0301},
+{ 0x1F10, 0x03B5, 0x0313},
+{ 0x1F11, 0x03B5, 0x0314},
+{ 0x1F74, 0x03B7, 0x0300},
+{ 0x03AE, 0x03B7, 0x0301},
+{ 0x1F20, 0x03B7, 0x0313},
+{ 0x1F21, 0x03B7, 0x0314},
+{ 0x1FC6, 0x03B7, 0x0342},
+{ 0x1FC3, 0x03B7, 0x0345},
+{ 0x1F76, 0x03B9, 0x0300},
+{ 0x03AF, 0x03B9, 0x0301},
+{ 0x1FD1, 0x03B9, 0x0304},
+{ 0x1FD0, 0x03B9, 0x0306},
+{ 0x03CA, 0x03B9, 0x0308},
+{ 0x1F30, 0x03B9, 0x0313},
+{ 0x1F31, 0x03B9, 0x0314},
+{ 0x1FD6, 0x03B9, 0x0342},
+{ 0x1F78, 0x03BF, 0x0300},
+{ 0x03CC, 0x03BF, 0x0301},
+{ 0x1F40, 0x03BF, 0x0313},
+{ 0x1F41, 0x03BF, 0x0314},
+{ 0x1FE4, 0x03C1, 0x0313},
+{ 0x1FE5, 0x03C1, 0x0314},
+{ 0x1F7A, 0x03C5, 0x0300},
+{ 0x03CD, 0x03C5, 0x0301},
+{ 0x1FE1, 0x03C5, 0x0304},
+{ 0x1FE0, 0x03C5, 0x0306},
+{ 0x03CB, 0x03C5, 0x0308},
+{ 0x1F50, 0x03C5, 0x0313},
+{ 0x1F51, 0x03C5, 0x0314},
+{ 0x1FE6, 0x03C5, 0x0342},
+{ 0x1F7C, 0x03C9, 0x0300},
+{ 0x03CE, 0x03C9, 0x0301},
+{ 0x1F60, 0x03C9, 0x0313},
+{ 0x1F61, 0x03C9, 0x0314},
+{ 0x1FF6, 0x03C9, 0x0342},
+{ 0x1FF3, 0x03C9, 0x0345},
+{ 0x1FD2, 0x03CA, 0x0300},
+{ 0x0390, 0x03CA, 0x0301},
+{ 0x1FD7, 0x03CA, 0x0342},
+{ 0x1FE2, 0x03CB, 0x0300},
+{ 0x03B0, 0x03CB, 0x0301},
+{ 0x1FE7, 0x03CB, 0x0342},
+{ 0x1FF4, 0x03CE, 0x0345},
+{ 0x03D3, 0x03D2, 0x0301},
+{ 0x03D4, 0x03D2, 0x0308},
+{ 0x0407, 0x0406, 0x0308},
+{ 0x04D0, 0x0410, 0x0306},
+{ 0x04D2, 0x0410, 0x0308},
+{ 0x0403, 0x0413, 0x0301},
+{ 0x0400, 0x0415, 0x0300},
+{ 0x04D6, 0x0415, 0x0306},
+{ 0x0401, 0x0415, 0x0308},
+{ 0x04C1, 0x0416, 0x0306},
+{ 0x04DC, 0x0416, 0x0308},
+{ 0x04DE, 0x0417, 0x0308},
+{ 0x040D, 0x0418, 0x0300},
+{ 0x04E2, 0x0418, 0x0304},
+{ 0x0419, 0x0418, 0x0306},
+{ 0x04E4, 0x0418, 0x0308},
+{ 0x040C, 0x041A, 0x0301},
+{ 0x04E6, 0x041E, 0x0308},
+{ 0x04EE, 0x0423, 0x0304},
+{ 0x040E, 0x0423, 0x0306},
+{ 0x04F0, 0x0423, 0x0308},
+{ 0x04F2, 0x0423, 0x030B},
+{ 0x04F4, 0x0427, 0x0308},
+{ 0x04F8, 0x042B, 0x0308},
+{ 0x04EC, 0x042D, 0x0308},
+{ 0x04D1, 0x0430, 0x0306},
+{ 0x04D3, 0x0430, 0x0308},
+{ 0x0453, 0x0433, 0x0301},
+{ 0x0450, 0x0435, 0x0300},
+{ 0x04D7, 0x0435, 0x0306},
+{ 0x0451, 0x0435, 0x0308},
+{ 0x04C2, 0x0436, 0x0306},
+{ 0x04DD, 0x0436, 0x0308},
+{ 0x04DF, 0x0437, 0x0308},
+{ 0x045D, 0x0438, 0x0300},
+{ 0x04E3, 0x0438, 0x0304},
+{ 0x0439, 0x0438, 0x0306},
+{ 0x04E5, 0x0438, 0x0308},
+{ 0x045C, 0x043A, 0x0301},
+{ 0x04E7, 0x043E, 0x0308},
+{ 0x04EF, 0x0443, 0x0304},
+{ 0x045E, 0x0443, 0x0306},
+{ 0x04F1, 0x0443, 0x0308},
+{ 0x04F3, 0x0443, 0x030B},
+{ 0x04F5, 0x0447, 0x0308},
+{ 0x04F9, 0x044B, 0x0308},
+{ 0x04ED, 0x044D, 0x0308},
+{ 0x0457, 0x0456, 0x0308},
+{ 0x0476, 0x0474, 0x030F},
+{ 0x0477, 0x0475, 0x030F},
+{ 0x04DA, 0x04D8, 0x0308},
+{ 0x04DB, 0x04D9, 0x0308},
+{ 0x04EA, 0x04E8, 0x0308},
+{ 0x04EB, 0x04E9, 0x0308},
+{ 0xFB2E, 0x05D0, 0x05B7},
+{ 0xFB2F, 0x05D0, 0x05B8},
+{ 0xFB30, 0x05D0, 0x05BC},
+{ 0xFB31, 0x05D1, 0x05BC},
+{ 0xFB4C, 0x05D1, 0x05BF},
+{ 0xFB32, 0x05D2, 0x05BC},
+{ 0xFB33, 0x05D3, 0x05BC},
+{ 0xFB34, 0x05D4, 0x05BC},
+{ 0xFB4B, 0x05D5, 0x05B9},
+{ 0xFB35, 0x05D5, 0x05BC},
+{ 0xFB36, 0x05D6, 0x05BC},
+{ 0xFB38, 0x05D8, 0x05BC},
+{ 0xFB1D, 0x05D9, 0x05B4},
+{ 0xFB39, 0x05D9, 0x05BC},
+{ 0xFB3A, 0x05DA, 0x05BC},
+{ 0xFB3B, 0x05DB, 0x05BC},
+{ 0xFB4D, 0x05DB, 0x05BF},
+{ 0xFB3C, 0x05DC, 0x05BC},
+{ 0xFB3E, 0x05DE, 0x05BC},
+{ 0xFB40, 0x05E0, 0x05BC},
+{ 0xFB41, 0x05E1, 0x05BC},
+{ 0xFB43, 0x05E3, 0x05BC},
+{ 0xFB44, 0x05E4, 0x05BC},
+{ 0xFB4E, 0x05E4, 0x05BF},
+{ 0xFB46, 0x05E6, 0x05BC},
+{ 0xFB47, 0x05E7, 0x05BC},
+{ 0xFB48, 0x05E8, 0x05BC},
+{ 0xFB49, 0x05E9, 0x05BC},
+{ 0xFB2A, 0x05E9, 0x05C1},
+{ 0xFB2B, 0x05E9, 0x05C2},
+{ 0xFB4A, 0x05EA, 0x05BC},
+{ 0xFB1F, 0x05F2, 0x05B7},
+{ 0x0622, 0x0627, 0x0653},
+{ 0x0623, 0x0627, 0x0654},
+{ 0x0625, 0x0627, 0x0655},
+{ 0x0624, 0x0648, 0x0654},
+{ 0x0626, 0x064A, 0x0654},
+{ 0x06C2, 0x06C1, 0x0654},
+{ 0x06D3, 0x06D2, 0x0654},
+{ 0x06C0, 0x06D5, 0x0654},
+{ 0x0958, 0x0915, 0x093C},
+{ 0x0959, 0x0916, 0x093C},
+{ 0x095A, 0x0917, 0x093C},
+{ 0x095B, 0x091C, 0x093C},
+{ 0x095C, 0x0921, 0x093C},
+{ 0x095D, 0x0922, 0x093C},
+{ 0x0929, 0x0928, 0x093C},
+{ 0x095E, 0x092B, 0x093C},
+{ 0x095F, 0x092F, 0x093C},
+{ 0x0931, 0x0930, 0x093C},
+{ 0x0934, 0x0933, 0x093C},
+{ 0x09DC, 0x09A1, 0x09BC},
+{ 0x09DD, 0x09A2, 0x09BC},
+{ 0x09DF, 0x09AF, 0x09BC},
+{ 0x09CB, 0x09C7, 0x09BE},
+{ 0x09CC, 0x09C7, 0x09D7},
+{ 0x0A59, 0x0A16, 0x0A3C},
+{ 0x0A5A, 0x0A17, 0x0A3C},
+{ 0x0A5B, 0x0A1C, 0x0A3C},
+{ 0x0A5E, 0x0A2B, 0x0A3C},
+{ 0x0A33, 0x0A32, 0x0A3C},
+{ 0x0A36, 0x0A38, 0x0A3C},
+{ 0x0B5C, 0x0B21, 0x0B3C},
+{ 0x0B5D, 0x0B22, 0x0B3C},
+{ 0x0B4B, 0x0B47, 0x0B3E},
+{ 0x0B48, 0x0B47, 0x0B56},
+{ 0x0B4C, 0x0B47, 0x0B57},
+{ 0x0B94, 0x0B92, 0x0BD7},
+{ 0x0BCA, 0x0BC6, 0x0BBE},
+{ 0x0BCC, 0x0BC6, 0x0BD7},
+{ 0x0BCB, 0x0BC7, 0x0BBE},
+{ 0x0C48, 0x0C46, 0x0C56},
+{ 0x0CC0, 0x0CBF, 0x0CD5},
+{ 0x0CCA, 0x0CC6, 0x0CC2},
+{ 0x0CC7, 0x0CC6, 0x0CD5},
+{ 0x0CC8, 0x0CC6, 0x0CD6},
+{ 0x0CCB, 0x0CCA, 0x0CD5},
+{ 0x0D4A, 0x0D46, 0x0D3E},
+{ 0x0D4C, 0x0D46, 0x0D57},
+{ 0x0D4B, 0x0D47, 0x0D3E},
+{ 0x0DDA, 0x0DD9, 0x0DCA},
+{ 0x0DDC, 0x0DD9, 0x0DCF},
+{ 0x0DDE, 0x0DD9, 0x0DDF},
+{ 0x0DDD, 0x0DDC, 0x0DCA},
+{ 0x0F69, 0x0F40, 0x0FB5},
+{ 0x0F43, 0x0F42, 0x0FB7},
+{ 0x0F4D, 0x0F4C, 0x0FB7},
+{ 0x0F52, 0x0F51, 0x0FB7},
+{ 0x0F57, 0x0F56, 0x0FB7},
+{ 0x0F5C, 0x0F5B, 0x0FB7},
+{ 0x0F73, 0x0F71, 0x0F72},
+{ 0x0F75, 0x0F71, 0x0F74},
+{ 0x0F81, 0x0F71, 0x0F80},
+{ 0x0FB9, 0x0F90, 0x0FB5},
+{ 0x0F93, 0x0F92, 0x0FB7},
+{ 0x0F9D, 0x0F9C, 0x0FB7},
+{ 0x0FA2, 0x0FA1, 0x0FB7},
+{ 0x0FA7, 0x0FA6, 0x0FB7},
+{ 0x0FAC, 0x0FAB, 0x0FB7},
+{ 0x0F76, 0x0FB2, 0x0F80},
+{ 0x0F78, 0x0FB3, 0x0F80},
+{ 0x1026, 0x1025, 0x102E},
+{ 0x1E38, 0x1E36, 0x0304},
+{ 0x1E39, 0x1E37, 0x0304},
+{ 0x1E5C, 0x1E5A, 0x0304},
+{ 0x1E5D, 0x1E5B, 0x0304},
+{ 0x1E68, 0x1E62, 0x0307},
+{ 0x1E69, 0x1E63, 0x0307},
+{ 0x1EAC, 0x1EA0, 0x0302},
+{ 0x1EB6, 0x1EA0, 0x0306},
+{ 0x1EAD, 0x1EA1, 0x0302},
+{ 0x1EB7, 0x1EA1, 0x0306},
+{ 0x1EC6, 0x1EB8, 0x0302},
+{ 0x1EC7, 0x1EB9, 0x0302},
+{ 0x1ED8, 0x1ECC, 0x0302},
+{ 0x1ED9, 0x1ECD, 0x0302},
+{ 0x1F02, 0x1F00, 0x0300},
+{ 0x1F04, 0x1F00, 0x0301},
+{ 0x1F06, 0x1F00, 0x0342},
+{ 0x1F80, 0x1F00, 0x0345},
+{ 0x1F03, 0x1F01, 0x0300},
+{ 0x1F05, 0x1F01, 0x0301},
+{ 0x1F07, 0x1F01, 0x0342},
+{ 0x1F81, 0x1F01, 0x0345},
+{ 0x1F82, 0x1F02, 0x0345},
+{ 0x1F83, 0x1F03, 0x0345},
+{ 0x1F84, 0x1F04, 0x0345},
+{ 0x1F85, 0x1F05, 0x0345},
+{ 0x1F86, 0x1F06, 0x0345},
+{ 0x1F87, 0x1F07, 0x0345},
+{ 0x1F0A, 0x1F08, 0x0300},
+{ 0x1F0C, 0x1F08, 0x0301},
+{ 0x1F0E, 0x1F08, 0x0342},
+{ 0x1F88, 0x1F08, 0x0345},
+{ 0x1F0B, 0x1F09, 0x0300},
+{ 0x1F0D, 0x1F09, 0x0301},
+{ 0x1F0F, 0x1F09, 0x0342},
+{ 0x1F89, 0x1F09, 0x0345},
+{ 0x1F8A, 0x1F0A, 0x0345},
+{ 0x1F8B, 0x1F0B, 0x0345},
+{ 0x1F8C, 0x1F0C, 0x0345},
+{ 0x1F8D, 0x1F0D, 0x0345},
+{ 0x1F8E, 0x1F0E, 0x0345},
+{ 0x1F8F, 0x1F0F, 0x0345},
+{ 0x1F12, 0x1F10, 0x0300},
+{ 0x1F14, 0x1F10, 0x0301},
+{ 0x1F13, 0x1F11, 0x0300},
+{ 0x1F15, 0x1F11, 0x0301},
+{ 0x1F1A, 0x1F18, 0x0300},
+{ 0x1F1C, 0x1F18, 0x0301},
+{ 0x1F1B, 0x1F19, 0x0300},
+{ 0x1F1D, 0x1F19, 0x0301},
+{ 0x1F22, 0x1F20, 0x0300},
+{ 0x1F24, 0x1F20, 0x0301},
+{ 0x1F26, 0x1F20, 0x0342},
+{ 0x1F90, 0x1F20, 0x0345},
+{ 0x1F23, 0x1F21, 0x0300},
+{ 0x1F25, 0x1F21, 0x0301},
+{ 0x1F27, 0x1F21, 0x0342},
+{ 0x1F91, 0x1F21, 0x0345},
+{ 0x1F92, 0x1F22, 0x0345},
+{ 0x1F93, 0x1F23, 0x0345},
+{ 0x1F94, 0x1F24, 0x0345},
+{ 0x1F95, 0x1F25, 0x0345},
+{ 0x1F96, 0x1F26, 0x0345},
+{ 0x1F97, 0x1F27, 0x0345},
+{ 0x1F2A, 0x1F28, 0x0300},
+{ 0x1F2C, 0x1F28, 0x0301},
+{ 0x1F2E, 0x1F28, 0x0342},
+{ 0x1F98, 0x1F28, 0x0345},
+{ 0x1F2B, 0x1F29, 0x0300},
+{ 0x1F2D, 0x1F29, 0x0301},
+{ 0x1F2F, 0x1F29, 0x0342},
+{ 0x1F99, 0x1F29, 0x0345},
+{ 0x1F9A, 0x1F2A, 0x0345},
+{ 0x1F9B, 0x1F2B, 0x0345},
+{ 0x1F9C, 0x1F2C, 0x0345},
+{ 0x1F9D, 0x1F2D, 0x0345},
+{ 0x1F9E, 0x1F2E, 0x0345},
+{ 0x1F9F, 0x1F2F, 0x0345},
+{ 0x1F32, 0x1F30, 0x0300},
+{ 0x1F34, 0x1F30, 0x0301},
+{ 0x1F36, 0x1F30, 0x0342},
+{ 0x1F33, 0x1F31, 0x0300},
+{ 0x1F35, 0x1F31, 0x0301},
+{ 0x1F37, 0x1F31, 0x0342},
+{ 0x1F3A, 0x1F38, 0x0300},
+{ 0x1F3C, 0x1F38, 0x0301},
+{ 0x1F3E, 0x1F38, 0x0342},
+{ 0x1F3B, 0x1F39, 0x0300},
+{ 0x1F3D, 0x1F39, 0x0301},
+{ 0x1F3F, 0x1F39, 0x0342},
+{ 0x1F42, 0x1F40, 0x0300},
+{ 0x1F44, 0x1F40, 0x0301},
+{ 0x1F43, 0x1F41, 0x0300},
+{ 0x1F45, 0x1F41, 0x0301},
+{ 0x1F4A, 0x1F48, 0x0300},
+{ 0x1F4C, 0x1F48, 0x0301},
+{ 0x1F4B, 0x1F49, 0x0300},
+{ 0x1F4D, 0x1F49, 0x0301},
+{ 0x1F52, 0x1F50, 0x0300},
+{ 0x1F54, 0x1F50, 0x0301},
+{ 0x1F56, 0x1F50, 0x0342},
+{ 0x1F53, 0x1F51, 0x0300},
+{ 0x1F55, 0x1F51, 0x0301},
+{ 0x1F57, 0x1F51, 0x0342},
+{ 0x1F5B, 0x1F59, 0x0300},
+{ 0x1F5D, 0x1F59, 0x0301},
+{ 0x1F5F, 0x1F59, 0x0342},
+{ 0x1F62, 0x1F60, 0x0300},
+{ 0x1F64, 0x1F60, 0x0301},
+{ 0x1F66, 0x1F60, 0x0342},
+{ 0x1FA0, 0x1F60, 0x0345},
+{ 0x1F63, 0x1F61, 0x0300},
+{ 0x1F65, 0x1F61, 0x0301},
+{ 0x1F67, 0x1F61, 0x0342},
+{ 0x1FA1, 0x1F61, 0x0345},
+{ 0x1FA2, 0x1F62, 0x0345},
+{ 0x1FA3, 0x1F63, 0x0345},
+{ 0x1FA4, 0x1F64, 0x0345},
+{ 0x1FA5, 0x1F65, 0x0345},
+{ 0x1FA6, 0x1F66, 0x0345},
+{ 0x1FA7, 0x1F67, 0x0345},
+{ 0x1F6A, 0x1F68, 0x0300},
+{ 0x1F6C, 0x1F68, 0x0301},
+{ 0x1F6E, 0x1F68, 0x0342},
+{ 0x1FA8, 0x1F68, 0x0345},
+{ 0x1F6B, 0x1F69, 0x0300},
+{ 0x1F6D, 0x1F69, 0x0301},
+{ 0x1F6F, 0x1F69, 0x0342},
+{ 0x1FA9, 0x1F69, 0x0345},
+{ 0x1FAA, 0x1F6A, 0x0345},
+{ 0x1FAB, 0x1F6B, 0x0345},
+{ 0x1FAC, 0x1F6C, 0x0345},
+{ 0x1FAD, 0x1F6D, 0x0345},
+{ 0x1FAE, 0x1F6E, 0x0345},
+{ 0x1FAF, 0x1F6F, 0x0345},
+{ 0x1FB2, 0x1F70, 0x0345},
+{ 0x1FC2, 0x1F74, 0x0345},
+{ 0x1FF2, 0x1F7C, 0x0345},
+{ 0x1FB7, 0x1FB6, 0x0345},
+{ 0x1FCD, 0x1FBF, 0x0300},
+{ 0x1FCE, 0x1FBF, 0x0301},
+{ 0x1FCF, 0x1FBF, 0x0342},
+{ 0x1FC7, 0x1FC6, 0x0345},
+{ 0x1FF7, 0x1FF6, 0x0345},
+{ 0x1FDD, 0x1FFE, 0x0300},
+{ 0x1FDE, 0x1FFE, 0x0301},
+{ 0x1FDF, 0x1FFE, 0x0342},
+{ 0x219A, 0x2190, 0x0338},
+{ 0x219B, 0x2192, 0x0338},
+{ 0x21AE, 0x2194, 0x0338},
+{ 0x21CD, 0x21D0, 0x0338},
+{ 0x21CF, 0x21D2, 0x0338},
+{ 0x21CE, 0x21D4, 0x0338},
+{ 0x2204, 0x2203, 0x0338},
+{ 0x2209, 0x2208, 0x0338},
+{ 0x220C, 0x220B, 0x0338},
+{ 0x2224, 0x2223, 0x0338},
+{ 0x2226, 0x2225, 0x0338},
+{ 0x2241, 0x223C, 0x0338},
+{ 0x2244, 0x2243, 0x0338},
+{ 0x2247, 0x2245, 0x0338},
+{ 0x2249, 0x2248, 0x0338},
+{ 0x226D, 0x224D, 0x0338},
+{ 0x2262, 0x2261, 0x0338},
+{ 0x2270, 0x2264, 0x0338},
+{ 0x2271, 0x2265, 0x0338},
+{ 0x2274, 0x2272, 0x0338},
+{ 0x2275, 0x2273, 0x0338},
+{ 0x2278, 0x2276, 0x0338},
+{ 0x2279, 0x2277, 0x0338},
+{ 0x2280, 0x227A, 0x0338},
+{ 0x2281, 0x227B, 0x0338},
+{ 0x22E0, 0x227C, 0x0338},
+{ 0x22E1, 0x227D, 0x0338},
+{ 0x2284, 0x2282, 0x0338},
+{ 0x2285, 0x2283, 0x0338},
+{ 0x2288, 0x2286, 0x0338},
+{ 0x2289, 0x2287, 0x0338},
+{ 0x22E2, 0x2291, 0x0338},
+{ 0x22E3, 0x2292, 0x0338},
+{ 0x22AC, 0x22A2, 0x0338},
+{ 0x22AD, 0x22A8, 0x0338},
+{ 0x22AE, 0x22A9, 0x0338},
+{ 0x22AF, 0x22AB, 0x0338},
+{ 0x22EA, 0x22B2, 0x0338},
+{ 0x22EB, 0x22B3, 0x0338},
+{ 0x22EC, 0x22B4, 0x0338},
+{ 0x22ED, 0x22B5, 0x0338},
+{ 0x3094, 0x3046, 0x3099},
+{ 0x304C, 0x304B, 0x3099},
+{ 0x304E, 0x304D, 0x3099},
+{ 0x3050, 0x304F, 0x3099},
+{ 0x3052, 0x3051, 0x3099},
+{ 0x3054, 0x3053, 0x3099},
+{ 0x3056, 0x3055, 0x3099},
+{ 0x3058, 0x3057, 0x3099},
+{ 0x305A, 0x3059, 0x3099},
+{ 0x305C, 0x305B, 0x3099},
+{ 0x305E, 0x305D, 0x3099},
+{ 0x3060, 0x305F, 0x3099},
+{ 0x3062, 0x3061, 0x3099},
+{ 0x3065, 0x3064, 0x3099},
+{ 0x3067, 0x3066, 0x3099},
+{ 0x3069, 0x3068, 0x3099},
+{ 0x3070, 0x306F, 0x3099},
+{ 0x3071, 0x306F, 0x309A},
+{ 0x3073, 0x3072, 0x3099},
+{ 0x3074, 0x3072, 0x309A},
+{ 0x3076, 0x3075, 0x3099},
+{ 0x3077, 0x3075, 0x309A},
+{ 0x3079, 0x3078, 0x3099},
+{ 0x307A, 0x3078, 0x309A},
+{ 0x307C, 0x307B, 0x3099},
+{ 0x307D, 0x307B, 0x309A},
+{ 0x309E, 0x309D, 0x3099},
+{ 0x30F4, 0x30A6, 0x3099},
+{ 0x30AC, 0x30AB, 0x3099},
+{ 0x30AE, 0x30AD, 0x3099},
+{ 0x30B0, 0x30AF, 0x3099},
+{ 0x30B2, 0x30B1, 0x3099},
+{ 0x30B4, 0x30B3, 0x3099},
+{ 0x30B6, 0x30B5, 0x3099},
+{ 0x30B8, 0x30B7, 0x3099},
+{ 0x30BA, 0x30B9, 0x3099},
+{ 0x30BC, 0x30BB, 0x3099},
+{ 0x30BE, 0x30BD, 0x3099},
+{ 0x30C0, 0x30BF, 0x3099},
+{ 0x30C2, 0x30C1, 0x3099},
+{ 0x30C5, 0x30C4, 0x3099},
+{ 0x30C7, 0x30C6, 0x3099},
+{ 0x30C9, 0x30C8, 0x3099},
+{ 0x30D0, 0x30CF, 0x3099},
+{ 0x30D1, 0x30CF, 0x309A},
+{ 0x30D3, 0x30D2, 0x3099},
+{ 0x30D4, 0x30D2, 0x309A},
+{ 0x30D6, 0x30D5, 0x3099},
+{ 0x30D7, 0x30D5, 0x309A},
+{ 0x30D9, 0x30D8, 0x3099},
+{ 0x30DA, 0x30D8, 0x309A},
+{ 0x30DC, 0x30DB, 0x3099},
+{ 0x30DD, 0x30DB, 0x309A},
+{ 0x30F7, 0x30EF, 0x3099},
+{ 0x30F8, 0x30F0, 0x3099},
+{ 0x30F9, 0x30F1, 0x3099},
+{ 0x30FA, 0x30F2, 0x3099},
+{ 0x30FE, 0x30FD, 0x3099},
+{ 0xFB2C, 0xFB49, 0x05C1},
+{ 0xFB2D, 0xFB49, 0x05C2},
+};
+
+static const struct {
+  unsigned int replacement;
+  unsigned int base;
+  unsigned int comb; 
+} decompositions[] = {
+{ 0x00C0, 0x0041, 0x0300},
+{ 0x00C1, 0x0041, 0x0301},
+{ 0x00C2, 0x0041, 0x0302},
+{ 0x00C3, 0x0041, 0x0303},
+{ 0x00C4, 0x0041, 0x0308},
+{ 0x00C5, 0x0041, 0x030A},
+{ 0x00C7, 0x0043, 0x0327},
+{ 0x00C8, 0x0045, 0x0300},
+{ 0x00C9, 0x0045, 0x0301},
+{ 0x00CA, 0x0045, 0x0302},
+{ 0x00CB, 0x0045, 0x0308},
+{ 0x00CC, 0x0049, 0x0300},
+{ 0x00CD, 0x0049, 0x0301},
+{ 0x00CE, 0x0049, 0x0302},
+{ 0x00CF, 0x0049, 0x0308},
+{ 0x00D1, 0x004E, 0x0303},
+{ 0x00D2, 0x004F, 0x0300},
+{ 0x00D3, 0x004F, 0x0301},
+{ 0x00D4, 0x004F, 0x0302},
+{ 0x00D5, 0x004F, 0x0303},
+{ 0x00D6, 0x004F, 0x0308},
+{ 0x00D9, 0x0055, 0x0300},
+{ 0x00DA, 0x0055, 0x0301},
+{ 0x00DB, 0x0055, 0x0302},
+{ 0x00DC, 0x0055, 0x0308},
+{ 0x00DD, 0x0059, 0x0301},
+{ 0x00E0, 0x0061, 0x0300},
+{ 0x00E1, 0x0061, 0x0301},
+{ 0x00E2, 0x0061, 0x0302},
+{ 0x00E3, 0x0061, 0x0303},
+{ 0x00E4, 0x0061, 0x0308},
+{ 0x00E5, 0x0061, 0x030A},
+{ 0x00E7, 0x0063, 0x0327},
+{ 0x00E8, 0x0065, 0x0300},
+{ 0x00E9, 0x0065, 0x0301},
+{ 0x00EA, 0x0065, 0x0302},
+{ 0x00EB, 0x0065, 0x0308},
+{ 0x00EC, 0x0069, 0x0300},
+{ 0x00ED, 0x0069, 0x0301},
+{ 0x00EE, 0x0069, 0x0302},
+{ 0x00EF, 0x0069, 0x0308},
+{ 0x00F1, 0x006E, 0x0303},
+{ 0x00F2, 0x006F, 0x0300},
+{ 0x00F3, 0x006F, 0x0301},
+{ 0x00F4, 0x006F, 0x0302},
+{ 0x00F5, 0x006F, 0x0303},
+{ 0x00F6, 0x006F, 0x0308},
+{ 0x00F9, 0x0075, 0x0300},
+{ 0x00FA, 0x0075, 0x0301},
+{ 0x00FB, 0x0075, 0x0302},
+{ 0x00FC, 0x0075, 0x0308},
+{ 0x00FD, 0x0079, 0x0301},
+{ 0x00FF, 0x0079, 0x0308},
+{ 0x0100, 0x0041, 0x0304},
+{ 0x0101, 0x0061, 0x0304},
+{ 0x0102, 0x0041, 0x0306},
+{ 0x0103, 0x0061, 0x0306},
+{ 0x0104, 0x0041, 0x0328},
+{ 0x0105, 0x0061, 0x0328},
+{ 0x0106, 0x0043, 0x0301},
+{ 0x0107, 0x0063, 0x0301},
+{ 0x0108, 0x0043, 0x0302},
+{ 0x0109, 0x0063, 0x0302},
+{ 0x010A, 0x0043, 0x0307},
+{ 0x010B, 0x0063, 0x0307},
+{ 0x010C, 0x0043, 0x030C},
+{ 0x010D, 0x0063, 0x030C},
+{ 0x010E, 0x0044, 0x030C},
+{ 0x010F, 0x0064, 0x030C},
+{ 0x0112, 0x0045, 0x0304},
+{ 0x0113, 0x0065, 0x0304},
+{ 0x0114, 0x0045, 0x0306},
+{ 0x0115, 0x0065, 0x0306},
+{ 0x0116, 0x0045, 0x0307},
+{ 0x0117, 0x0065, 0x0307},
+{ 0x0118, 0x0045, 0x0328},
+{ 0x0119, 0x0065, 0x0328},
+{ 0x011A, 0x0045, 0x030C},
+{ 0x011B, 0x0065, 0x030C},
+{ 0x011C, 0x0047, 0x0302},
+{ 0x011D, 0x0067, 0x0302},
+{ 0x011E, 0x0047, 0x0306},
+{ 0x011F, 0x0067, 0x0306},
+{ 0x0120, 0x0047, 0x0307},
+{ 0x0121, 0x0067, 0x0307},
+{ 0x0122, 0x0047, 0x0327},
+{ 0x0123, 0x0067, 0x0327},
+{ 0x0124, 0x0048, 0x0302},
+{ 0x0125, 0x0068, 0x0302},
+{ 0x0128, 0x0049, 0x0303},
+{ 0x0129, 0x0069, 0x0303},
+{ 0x012A, 0x0049, 0x0304},
+{ 0x012B, 0x0069, 0x0304},
+{ 0x012C, 0x0049, 0x0306},
+{ 0x012D, 0x0069, 0x0306},
+{ 0x012E, 0x0049, 0x0328},
+{ 0x012F, 0x0069, 0x0328},
+{ 0x0130, 0x0049, 0x0307},
+{ 0x0134, 0x004A, 0x0302},
+{ 0x0135, 0x006A, 0x0302},
+{ 0x0136, 0x004B, 0x0327},
+{ 0x0137, 0x006B, 0x0327},
+{ 0x0139, 0x004C, 0x0301},
+{ 0x013A, 0x006C, 0x0301},
+{ 0x013B, 0x004C, 0x0327},
+{ 0x013C, 0x006C, 0x0327},
+{ 0x013D, 0x004C, 0x030C},
+{ 0x013E, 0x006C, 0x030C},
+{ 0x0143, 0x004E, 0x0301},
+{ 0x0144, 0x006E, 0x0301},
+{ 0x0145, 0x004E, 0x0327},
+{ 0x0146, 0x006E, 0x0327},
+{ 0x0147, 0x004E, 0x030C},
+{ 0x0148, 0x006E, 0x030C},
+{ 0x014C, 0x004F, 0x0304},
+{ 0x014D, 0x006F, 0x0304},
+{ 0x014E, 0x004F, 0x0306},
+{ 0x014F, 0x006F, 0x0306},
+{ 0x0150, 0x004F, 0x030B},
+{ 0x0151, 0x006F, 0x030B},
+{ 0x0154, 0x0052, 0x0301},
+{ 0x0155, 0x0072, 0x0301},
+{ 0x0156, 0x0052, 0x0327},
+{ 0x0157, 0x0072, 0x0327},
+{ 0x0158, 0x0052, 0x030C},
+{ 0x0159, 0x0072, 0x030C},
+{ 0x015A, 0x0053, 0x0301},
+{ 0x015B, 0x0073, 0x0301},
+{ 0x015C, 0x0053, 0x0302},
+{ 0x015D, 0x0073, 0x0302},
+{ 0x015E, 0x0053, 0x0327},
+{ 0x015F, 0x0073, 0x0327},
+{ 0x0160, 0x0053, 0x030C},
+{ 0x0161, 0x0073, 0x030C},
+{ 0x0162, 0x0054, 0x0327},
+{ 0x0163, 0x0074, 0x0327},
+{ 0x0164, 0x0054, 0x030C},
+{ 0x0165, 0x0074, 0x030C},
+{ 0x0168, 0x0055, 0x0303},
+{ 0x0169, 0x0075, 0x0303},
+{ 0x016A, 0x0055, 0x0304},
+{ 0x016B, 0x0075, 0x0304},
+{ 0x016C, 0x0055, 0x0306},
+{ 0x016D, 0x0075, 0x0306},
+{ 0x016E, 0x0055, 0x030A},
+{ 0x016F, 0x0075, 0x030A},
+{ 0x0170, 0x0055, 0x030B},
+{ 0x0171, 0x0075, 0x030B},
+{ 0x0172, 0x0055, 0x0328},
+{ 0x0173, 0x0075, 0x0328},
+{ 0x0174, 0x0057, 0x0302},
+{ 0x0175, 0x0077, 0x0302},
+{ 0x0176, 0x0059, 0x0302},
+{ 0x0177, 0x0079, 0x0302},
+{ 0x0178, 0x0059, 0x0308},
+{ 0x0179, 0x005A, 0x0301},
+{ 0x017A, 0x007A, 0x0301},
+{ 0x017B, 0x005A, 0x0307},
+{ 0x017C, 0x007A, 0x0307},
+{ 0x017D, 0x005A, 0x030C},
+{ 0x017E, 0x007A, 0x030C},
+{ 0x01A0, 0x004F, 0x031B},
+{ 0x01A1, 0x006F, 0x031B},
+{ 0x01AF, 0x0055, 0x031B},
+{ 0x01B0, 0x0075, 0x031B},
+{ 0x01CD, 0x0041, 0x030C},
+{ 0x01CE, 0x0061, 0x030C},
+{ 0x01CF, 0x0049, 0x030C},
+{ 0x01D0, 0x0069, 0x030C},
+{ 0x01D1, 0x004F, 0x030C},
+{ 0x01D2, 0x006F, 0x030C},
+{ 0x01D3, 0x0055, 0x030C},
+{ 0x01D4, 0x0075, 0x030C},
+{ 0x01D5, 0x00DC, 0x0304},
+{ 0x01D6, 0x00FC, 0x0304},
+{ 0x01D7, 0x00DC, 0x0301},
+{ 0x01D8, 0x00FC, 0x0301},
+{ 0x01D9, 0x00DC, 0x030C},
+{ 0x01DA, 0x00FC, 0x030C},
+{ 0x01DB, 0x00DC, 0x0300},
+{ 0x01DC, 0x00FC, 0x0300},
+{ 0x01DE, 0x00C4, 0x0304},
+{ 0x01DF, 0x00E4, 0x0304},
+{ 0x01E0, 0x0226, 0x0304},
+{ 0x01E1, 0x0227, 0x0304},
+{ 0x01E2, 0x00C6, 0x0304},
+{ 0x01E3, 0x00E6, 0x0304},
+{ 0x01E6, 0x0047, 0x030C},
+{ 0x01E7, 0x0067, 0x030C},
+{ 0x01E8, 0x004B, 0x030C},
+{ 0x01E9, 0x006B, 0x030C},
+{ 0x01EA, 0x004F, 0x0328},
+{ 0x01EB, 0x006F, 0x0328},
+{ 0x01EC, 0x01EA, 0x0304},
+{ 0x01ED, 0x01EB, 0x0304},
+{ 0x01EE, 0x01B7, 0x030C},
+{ 0x01EF, 0x0292, 0x030C},
+{ 0x01F0, 0x006A, 0x030C},
+{ 0x01F4, 0x0047, 0x0301},
+{ 0x01F5, 0x0067, 0x0301},
+{ 0x01F8, 0x004E, 0x0300},
+{ 0x01F9, 0x006E, 0x0300},
+{ 0x01FA, 0x00C5, 0x0301},
+{ 0x01FB, 0x00E5, 0x0301},
+{ 0x01FC, 0x00C6, 0x0301},
+{ 0x01FD, 0x00E6, 0x0301},
+{ 0x01FE, 0x00D8, 0x0301},
+{ 0x01FF, 0x00F8, 0x0301},
+{ 0x0200, 0x0041, 0x030F},
+{ 0x0201, 0x0061, 0x030F},
+{ 0x0202, 0x0041, 0x0311},
+{ 0x0203, 0x0061, 0x0311},
+{ 0x0204, 0x0045, 0x030F},
+{ 0x0205, 0x0065, 0x030F},
+{ 0x0206, 0x0045, 0x0311},
+{ 0x0207, 0x0065, 0x0311},
+{ 0x0208, 0x0049, 0x030F},
+{ 0x0209, 0x0069, 0x030F},
+{ 0x020A, 0x0049, 0x0311},
+{ 0x020B, 0x0069, 0x0311},
+{ 0x020C, 0x004F, 0x030F},
+{ 0x020D, 0x006F, 0x030F},
+{ 0x020E, 0x004F, 0x0311},
+{ 0x020F, 0x006F, 0x0311},
+{ 0x0210, 0x0052, 0x030F},
+{ 0x0211, 0x0072, 0x030F},
+{ 0x0212, 0x0052, 0x0311},
+{ 0x0213, 0x0072, 0x0311},
+{ 0x0214, 0x0055, 0x030F},
+{ 0x0215, 0x0075, 0x030F},
+{ 0x0216, 0x0055, 0x0311},
+{ 0x0217, 0x0075, 0x0311},
+{ 0x0218, 0x0053, 0x0326},
+{ 0x0219, 0x0073, 0x0326},
+{ 0x021A, 0x0054, 0x0326},
+{ 0x021B, 0x0074, 0x0326},
+{ 0x021E, 0x0048, 0x030C},
+{ 0x021F, 0x0068, 0x030C},
+{ 0x0226, 0x0041, 0x0307},
+{ 0x0227, 0x0061, 0x0307},
+{ 0x0228, 0x0045, 0x0327},
+{ 0x0229, 0x0065, 0x0327},
+{ 0x022A, 0x00D6, 0x0304},
+{ 0x022B, 0x00F6, 0x0304},
+{ 0x022C, 0x00D5, 0x0304},
+{ 0x022D, 0x00F5, 0x0304},
+{ 0x022E, 0x004F, 0x0307},
+{ 0x022F, 0x006F, 0x0307},
+{ 0x0230, 0x022E, 0x0304},
+{ 0x0231, 0x022F, 0x0304},
+{ 0x0232, 0x0059, 0x0304},
+{ 0x0233, 0x0079, 0x0304},
+{ 0x0344, 0x0308, 0x0301},
+{ 0x0385, 0x00A8, 0x0301},
+{ 0x0386, 0x0391, 0x0301},
+{ 0x0388, 0x0395, 0x0301},
+{ 0x0389, 0x0397, 0x0301},
+{ 0x038A, 0x0399, 0x0301},
+{ 0x038C, 0x039F, 0x0301},
+{ 0x038E, 0x03A5, 0x0301},
+{ 0x038F, 0x03A9, 0x0301},
+{ 0x0390, 0x03CA, 0x0301},
+{ 0x03AA, 0x0399, 0x0308},
+{ 0x03AB, 0x03A5, 0x0308},
+{ 0x03AC, 0x03B1, 0x0301},
+{ 0x03AD, 0x03B5, 0x0301},
+{ 0x03AE, 0x03B7, 0x0301},
+{ 0x03AF, 0x03B9, 0x0301},
+{ 0x03B0, 0x03CB, 0x0301},
+{ 0x03CA, 0x03B9, 0x0308},
+{ 0x03CB, 0x03C5, 0x0308},
+{ 0x03CC, 0x03BF, 0x0301},
+{ 0x03CD, 0x03C5, 0x0301},
+{ 0x03CE, 0x03C9, 0x0301},
+{ 0x03D3, 0x03D2, 0x0301},
+{ 0x03D4, 0x03D2, 0x0308},
+{ 0x0400, 0x0415, 0x0300},
+{ 0x0401, 0x0415, 0x0308},
+{ 0x0403, 0x0413, 0x0301},
+{ 0x0407, 0x0406, 0x0308},
+{ 0x040C, 0x041A, 0x0301},
+{ 0x040D, 0x0418, 0x0300},
+{ 0x040E, 0x0423, 0x0306},
+{ 0x0419, 0x0418, 0x0306},
+{ 0x0439, 0x0438, 0x0306},
+{ 0x0450, 0x0435, 0x0300},
+{ 0x0451, 0x0435, 0x0308},
+{ 0x0453, 0x0433, 0x0301},
+{ 0x0457, 0x0456, 0x0308},
+{ 0x045C, 0x043A, 0x0301},
+{ 0x045D, 0x0438, 0x0300},
+{ 0x045E, 0x0443, 0x0306},
+{ 0x0476, 0x0474, 0x030F},
+{ 0x0477, 0x0475, 0x030F},
+{ 0x04C1, 0x0416, 0x0306},
+{ 0x04C2, 0x0436, 0x0306},
+{ 0x04D0, 0x0410, 0x0306},
+{ 0x04D1, 0x0430, 0x0306},
+{ 0x04D2, 0x0410, 0x0308},
+{ 0x04D3, 0x0430, 0x0308},
+{ 0x04D6, 0x0415, 0x0306},
+{ 0x04D7, 0x0435, 0x0306},
+{ 0x04DA, 0x04D8, 0x0308},
+{ 0x04DB, 0x04D9, 0x0308},
+{ 0x04DC, 0x0416, 0x0308},
+{ 0x04DD, 0x0436, 0x0308},
+{ 0x04DE, 0x0417, 0x0308},
+{ 0x04DF, 0x0437, 0x0308},
+{ 0x04E2, 0x0418, 0x0304},
+{ 0x04E3, 0x0438, 0x0304},
+{ 0x04E4, 0x0418, 0x0308},
+{ 0x04E5, 0x0438, 0x0308},
+{ 0x04E6, 0x041E, 0x0308},
+{ 0x04E7, 0x043E, 0x0308},
+{ 0x04EA, 0x04E8, 0x0308},
+{ 0x04EB, 0x04E9, 0x0308},
+{ 0x04EC, 0x042D, 0x0308},
+{ 0x04ED, 0x044D, 0x0308},
+{ 0x04EE, 0x0423, 0x0304},
+{ 0x04EF, 0x0443, 0x0304},
+{ 0x04F0, 0x0423, 0x0308},
+{ 0x04F1, 0x0443, 0x0308},
+{ 0x04F2, 0x0423, 0x030B},
+{ 0x04F3, 0x0443, 0x030B},
+{ 0x04F4, 0x0427, 0x0308},
+{ 0x04F5, 0x0447, 0x0308},
+{ 0x04F8, 0x042B, 0x0308},
+{ 0x04F9, 0x044B, 0x0308},
+{ 0x0622, 0x0627, 0x0653},
+{ 0x0623, 0x0627, 0x0654},
+{ 0x0624, 0x0648, 0x0654},
+{ 0x0625, 0x0627, 0x0655},
+{ 0x0626, 0x064A, 0x0654},
+{ 0x06C0, 0x06D5, 0x0654},
+{ 0x06C2, 0x06C1, 0x0654},
+{ 0x06D3, 0x06D2, 0x0654},
+{ 0x0929, 0x0928, 0x093C},
+{ 0x0931, 0x0930, 0x093C},
+{ 0x0934, 0x0933, 0x093C},
+{ 0x0958, 0x0915, 0x093C},
+{ 0x0959, 0x0916, 0x093C},
+{ 0x095A, 0x0917, 0x093C},
+{ 0x095B, 0x091C, 0x093C},
+{ 0x095C, 0x0921, 0x093C},
+{ 0x095D, 0x0922, 0x093C},
+{ 0x095E, 0x092B, 0x093C},
+{ 0x095F, 0x092F, 0x093C},
+{ 0x09CB, 0x09C7, 0x09BE},
+{ 0x09CC, 0x09C7, 0x09D7},
+{ 0x09DC, 0x09A1, 0x09BC},
+{ 0x09DD, 0x09A2, 0x09BC},
+{ 0x09DF, 0x09AF, 0x09BC},
+{ 0x0A33, 0x0A32, 0x0A3C},
+{ 0x0A36, 0x0A38, 0x0A3C},
+{ 0x0A59, 0x0A16, 0x0A3C},
+{ 0x0A5A, 0x0A17, 0x0A3C},
+{ 0x0A5B, 0x0A1C, 0x0A3C},
+{ 0x0A5E, 0x0A2B, 0x0A3C},
+{ 0x0B48, 0x0B47, 0x0B56},
+{ 0x0B4B, 0x0B47, 0x0B3E},
+{ 0x0B4C, 0x0B47, 0x0B57},
+{ 0x0B5C, 0x0B21, 0x0B3C},
+{ 0x0B5D, 0x0B22, 0x0B3C},
+{ 0x0B94, 0x0B92, 0x0BD7},
+{ 0x0BCA, 0x0BC6, 0x0BBE},
+{ 0x0BCB, 0x0BC7, 0x0BBE},
+{ 0x0BCC, 0x0BC6, 0x0BD7},
+{ 0x0C48, 0x0C46, 0x0C56},
+{ 0x0CC0, 0x0CBF, 0x0CD5},
+{ 0x0CC7, 0x0CC6, 0x0CD5},
+{ 0x0CC8, 0x0CC6, 0x0CD6},
+{ 0x0CCA, 0x0CC6, 0x0CC2},
+{ 0x0CCB, 0x0CCA, 0x0CD5},
+{ 0x0D4A, 0x0D46, 0x0D3E},
+{ 0x0D4B, 0x0D47, 0x0D3E},
+{ 0x0D4C, 0x0D46, 0x0D57},
+{ 0x0DDA, 0x0DD9, 0x0DCA},
+{ 0x0DDC, 0x0DD9, 0x0DCF},
+{ 0x0DDD, 0x0DDC, 0x0DCA},
+{ 0x0DDE, 0x0DD9, 0x0DDF},
+{ 0x0F43, 0x0F42, 0x0FB7},
+{ 0x0F4D, 0x0F4C, 0x0FB7},
+{ 0x0F52, 0x0F51, 0x0FB7},
+{ 0x0F57, 0x0F56, 0x0FB7},
+{ 0x0F5C, 0x0F5B, 0x0FB7},
+{ 0x0F69, 0x0F40, 0x0FB5},
+{ 0x0F73, 0x0F71, 0x0F72},
+{ 0x0F75, 0x0F71, 0x0F74},
+{ 0x0F76, 0x0FB2, 0x0F80},
+{ 0x0F78, 0x0FB3, 0x0F80},
+{ 0x0F81, 0x0F71, 0x0F80},
+{ 0x0F93, 0x0F92, 0x0FB7},
+{ 0x0F9D, 0x0F9C, 0x0FB7},
+{ 0x0FA2, 0x0FA1, 0x0FB7},
+{ 0x0FA7, 0x0FA6, 0x0FB7},
+{ 0x0FAC, 0x0FAB, 0x0FB7},
+{ 0x0FB9, 0x0F90, 0x0FB5},
+{ 0x1026, 0x1025, 0x102E},
+{ 0x1E00, 0x0041, 0x0325},
+{ 0x1E01, 0x0061, 0x0325},
+{ 0x1E02, 0x0042, 0x0307},
+{ 0x1E03, 0x0062, 0x0307},
+{ 0x1E04, 0x0042, 0x0323},
+{ 0x1E05, 0x0062, 0x0323},
+{ 0x1E06, 0x0042, 0x0331},
+{ 0x1E07, 0x0062, 0x0331},
+{ 0x1E08, 0x00C7, 0x0301},
+{ 0x1E09, 0x00E7, 0x0301},
+{ 0x1E0A, 0x0044, 0x0307},
+{ 0x1E0B, 0x0064, 0x0307},
+{ 0x1E0C, 0x0044, 0x0323},
+{ 0x1E0D, 0x0064, 0x0323},
+{ 0x1E0E, 0x0044, 0x0331},
+{ 0x1E0F, 0x0064, 0x0331},
+{ 0x1E10, 0x0044, 0x0327},
+{ 0x1E11, 0x0064, 0x0327},
+{ 0x1E12, 0x0044, 0x032D},
+{ 0x1E13, 0x0064, 0x032D},
+{ 0x1E14, 0x0112, 0x0300},
+{ 0x1E15, 0x0113, 0x0300},
+{ 0x1E16, 0x0112, 0x0301},
+{ 0x1E17, 0x0113, 0x0301},
+{ 0x1E18, 0x0045, 0x032D},
+{ 0x1E19, 0x0065, 0x032D},
+{ 0x1E1A, 0x0045, 0x0330},
+{ 0x1E1B, 0x0065, 0x0330},
+{ 0x1E1C, 0x0228, 0x0306},
+{ 0x1E1D, 0x0229, 0x0306},
+{ 0x1E1E, 0x0046, 0x0307},
+{ 0x1E1F, 0x0066, 0x0307},
+{ 0x1E20, 0x0047, 0x0304},
+{ 0x1E21, 0x0067, 0x0304},
+{ 0x1E22, 0x0048, 0x0307},
+{ 0x1E23, 0x0068, 0x0307},
+{ 0x1E24, 0x0048, 0x0323},
+{ 0x1E25, 0x0068, 0x0323},
+{ 0x1E26, 0x0048, 0x0308},
+{ 0x1E27, 0x0068, 0x0308},
+{ 0x1E28, 0x0048, 0x0327},
+{ 0x1E29, 0x0068, 0x0327},
+{ 0x1E2A, 0x0048, 0x032E},
+{ 0x1E2B, 0x0068, 0x032E},
+{ 0x1E2C, 0x0049, 0x0330},
+{ 0x1E2D, 0x0069, 0x0330},
+{ 0x1E2E, 0x00CF, 0x0301},
+{ 0x1E2F, 0x00EF, 0x0301},
+{ 0x1E30, 0x004B, 0x0301},
+{ 0x1E31, 0x006B, 0x0301},
+{ 0x1E32, 0x004B, 0x0323},
+{ 0x1E33, 0x006B, 0x0323},
+{ 0x1E34, 0x004B, 0x0331},
+{ 0x1E35, 0x006B, 0x0331},
+{ 0x1E36, 0x004C, 0x0323},
+{ 0x1E37, 0x006C, 0x0323},
+{ 0x1E38, 0x1E36, 0x0304},
+{ 0x1E39, 0x1E37, 0x0304},
+{ 0x1E3A, 0x004C, 0x0331},
+{ 0x1E3B, 0x006C, 0x0331},
+{ 0x1E3C, 0x004C, 0x032D},
+{ 0x1E3D, 0x006C, 0x032D},
+{ 0x1E3E, 0x004D, 0x0301},
+{ 0x1E3F, 0x006D, 0x0301},
+{ 0x1E40, 0x004D, 0x0307},
+{ 0x1E41, 0x006D, 0x0307},
+{ 0x1E42, 0x004D, 0x0323},
+{ 0x1E43, 0x006D, 0x0323},
+{ 0x1E44, 0x004E, 0x0307},
+{ 0x1E45, 0x006E, 0x0307},
+{ 0x1E46, 0x004E, 0x0323},
+{ 0x1E47, 0x006E, 0x0323},
+{ 0x1E48, 0x004E, 0x0331},
+{ 0x1E49, 0x006E, 0x0331},
+{ 0x1E4A, 0x004E, 0x032D},
+{ 0x1E4B, 0x006E, 0x032D},
+{ 0x1E4C, 0x00D5, 0x0301},
+{ 0x1E4D, 0x00F5, 0x0301},
+{ 0x1E4E, 0x00D5, 0x0308},
+{ 0x1E4F, 0x00F5, 0x0308},
+{ 0x1E50, 0x014C, 0x0300},
+{ 0x1E51, 0x014D, 0x0300},
+{ 0x1E52, 0x014C, 0x0301},
+{ 0x1E53, 0x014D, 0x0301},
+{ 0x1E54, 0x0050, 0x0301},
+{ 0x1E55, 0x0070, 0x0301},
+{ 0x1E56, 0x0050, 0x0307},
+{ 0x1E57, 0x0070, 0x0307},
+{ 0x1E58, 0x0052, 0x0307},
+{ 0x1E59, 0x0072, 0x0307},
+{ 0x1E5A, 0x0052, 0x0323},
+{ 0x1E5B, 0x0072, 0x0323},
+{ 0x1E5C, 0x1E5A, 0x0304},
+{ 0x1E5D, 0x1E5B, 0x0304},
+{ 0x1E5E, 0x0052, 0x0331},
+{ 0x1E5F, 0x0072, 0x0331},
+{ 0x1E60, 0x0053, 0x0307},
+{ 0x1E61, 0x0073, 0x0307},
+{ 0x1E62, 0x0053, 0x0323},
+{ 0x1E63, 0x0073, 0x0323},
+{ 0x1E64, 0x015A, 0x0307},
+{ 0x1E65, 0x015B, 0x0307},
+{ 0x1E66, 0x0160, 0x0307},
+{ 0x1E67, 0x0161, 0x0307},
+{ 0x1E68, 0x1E62, 0x0307},
+{ 0x1E69, 0x1E63, 0x0307},
+{ 0x1E6A, 0x0054, 0x0307},
+{ 0x1E6B, 0x0074, 0x0307},
+{ 0x1E6C, 0x0054, 0x0323},
+{ 0x1E6D, 0x0074, 0x0323},
+{ 0x1E6E, 0x0054, 0x0331},
+{ 0x1E6F, 0x0074, 0x0331},
+{ 0x1E70, 0x0054, 0x032D},
+{ 0x1E71, 0x0074, 0x032D},
+{ 0x1E72, 0x0055, 0x0324},
+{ 0x1E73, 0x0075, 0x0324},
+{ 0x1E74, 0x0055, 0x0330},
+{ 0x1E75, 0x0075, 0x0330},
+{ 0x1E76, 0x0055, 0x032D},
+{ 0x1E77, 0x0075, 0x032D},
+{ 0x1E78, 0x0168, 0x0301},
+{ 0x1E79, 0x0169, 0x0301},
+{ 0x1E7A, 0x016A, 0x0308},
+{ 0x1E7B, 0x016B, 0x0308},
+{ 0x1E7C, 0x0056, 0x0303},
+{ 0x1E7D, 0x0076, 0x0303},
+{ 0x1E7E, 0x0056, 0x0323},
+{ 0x1E7F, 0x0076, 0x0323},
+{ 0x1E80, 0x0057, 0x0300},
+{ 0x1E81, 0x0077, 0x0300},
+{ 0x1E82, 0x0057, 0x0301},
+{ 0x1E83, 0x0077, 0x0301},
+{ 0x1E84, 0x0057, 0x0308},
+{ 0x1E85, 0x0077, 0x0308},
+{ 0x1E86, 0x0057, 0x0307},
+{ 0x1E87, 0x0077, 0x0307},
+{ 0x1E88, 0x0057, 0x0323},
+{ 0x1E89, 0x0077, 0x0323},
+{ 0x1E8A, 0x0058, 0x0307},
+{ 0x1E8B, 0x0078, 0x0307},
+{ 0x1E8C, 0x0058, 0x0308},
+{ 0x1E8D, 0x0078, 0x0308},
+{ 0x1E8E, 0x0059, 0x0307},
+{ 0x1E8F, 0x0079, 0x0307},
+{ 0x1E90, 0x005A, 0x0302},
+{ 0x1E91, 0x007A, 0x0302},
+{ 0x1E92, 0x005A, 0x0323},
+{ 0x1E93, 0x007A, 0x0323},
+{ 0x1E94, 0x005A, 0x0331},
+{ 0x1E95, 0x007A, 0x0331},
+{ 0x1E96, 0x0068, 0x0331},
+{ 0x1E97, 0x0074, 0x0308},
+{ 0x1E98, 0x0077, 0x030A},
+{ 0x1E99, 0x0079, 0x030A},
+{ 0x1E9B, 0x017F, 0x0307},
+{ 0x1EA0, 0x0041, 0x0323},
+{ 0x1EA1, 0x0061, 0x0323},
+{ 0x1EA2, 0x0041, 0x0309},
+{ 0x1EA3, 0x0061, 0x0309},
+{ 0x1EA4, 0x00C2, 0x0301},
+{ 0x1EA5, 0x00E2, 0x0301},
+{ 0x1EA6, 0x00C2, 0x0300},
+{ 0x1EA7, 0x00E2, 0x0300},
+{ 0x1EA8, 0x00C2, 0x0309},
+{ 0x1EA9, 0x00E2, 0x0309},
+{ 0x1EAA, 0x00C2, 0x0303},
+{ 0x1EAB, 0x00E2, 0x0303},
+{ 0x1EAC, 0x1EA0, 0x0302},
+{ 0x1EAD, 0x1EA1, 0x0302},
+{ 0x1EAE, 0x0102, 0x0301},
+{ 0x1EAF, 0x0103, 0x0301},
+{ 0x1EB0, 0x0102, 0x0300},
+{ 0x1EB1, 0x0103, 0x0300},
+{ 0x1EB2, 0x0102, 0x0309},
+{ 0x1EB3, 0x0103, 0x0309},
+{ 0x1EB4, 0x0102, 0x0303},
+{ 0x1EB5, 0x0103, 0x0303},
+{ 0x1EB6, 0x1EA0, 0x0306},
+{ 0x1EB7, 0x1EA1, 0x0306},
+{ 0x1EB8, 0x0045, 0x0323},
+{ 0x1EB9, 0x0065, 0x0323},
+{ 0x1EBA, 0x0045, 0x0309},
+{ 0x1EBB, 0x0065, 0x0309},
+{ 0x1EBC, 0x0045, 0x0303},
+{ 0x1EBD, 0x0065, 0x0303},
+{ 0x1EBE, 0x00CA, 0x0301},
+{ 0x1EBF, 0x00EA, 0x0301},
+{ 0x1EC0, 0x00CA, 0x0300},
+{ 0x1EC1, 0x00EA, 0x0300},
+{ 0x1EC2, 0x00CA, 0x0309},
+{ 0x1EC3, 0x00EA, 0x0309},
+{ 0x1EC4, 0x00CA, 0x0303},
+{ 0x1EC5, 0x00EA, 0x0303},
+{ 0x1EC6, 0x1EB8, 0x0302},
+{ 0x1EC7, 0x1EB9, 0x0302},
+{ 0x1EC8, 0x0049, 0x0309},
+{ 0x1EC9, 0x0069, 0x0309},
+{ 0x1ECA, 0x0049, 0x0323},
+{ 0x1ECB, 0x0069, 0x0323},
+{ 0x1ECC, 0x004F, 0x0323},
+{ 0x1ECD, 0x006F, 0x0323},
+{ 0x1ECE, 0x004F, 0x0309},
+{ 0x1ECF, 0x006F, 0x0309},
+{ 0x1ED0, 0x00D4, 0x0301},
+{ 0x1ED1, 0x00F4, 0x0301},
+{ 0x1ED2, 0x00D4, 0x0300},
+{ 0x1ED3, 0x00F4, 0x0300},
+{ 0x1ED4, 0x00D4, 0x0309},
+{ 0x1ED5, 0x00F4, 0x0309},
+{ 0x1ED6, 0x00D4, 0x0303},
+{ 0x1ED7, 0x00F4, 0x0303},
+{ 0x1ED8, 0x1ECC, 0x0302},
+{ 0x1ED9, 0x1ECD, 0x0302},
+{ 0x1EDA, 0x01A0, 0x0301},
+{ 0x1EDB, 0x01A1, 0x0301},
+{ 0x1EDC, 0x01A0, 0x0300},
+{ 0x1EDD, 0x01A1, 0x0300},
+{ 0x1EDE, 0x01A0, 0x0309},
+{ 0x1EDF, 0x01A1, 0x0309},
+{ 0x1EE0, 0x01A0, 0x0303},
+{ 0x1EE1, 0x01A1, 0x0303},
+{ 0x1EE2, 0x01A0, 0x0323},
+{ 0x1EE3, 0x01A1, 0x0323},
+{ 0x1EE4, 0x0055, 0x0323},
+{ 0x1EE5, 0x0075, 0x0323},
+{ 0x1EE6, 0x0055, 0x0309},
+{ 0x1EE7, 0x0075, 0x0309},
+{ 0x1EE8, 0x01AF, 0x0301},
+{ 0x1EE9, 0x01B0, 0x0301},
+{ 0x1EEA, 0x01AF, 0x0300},
+{ 0x1EEB, 0x01B0, 0x0300},
+{ 0x1EEC, 0x01AF, 0x0309},
+{ 0x1EED, 0x01B0, 0x0309},
+{ 0x1EEE, 0x01AF, 0x0303},
+{ 0x1EEF, 0x01B0, 0x0303},
+{ 0x1EF0, 0x01AF, 0x0323},
+{ 0x1EF1, 0x01B0, 0x0323},
+{ 0x1EF2, 0x0059, 0x0300},
+{ 0x1EF3, 0x0079, 0x0300},
+{ 0x1EF4, 0x0059, 0x0323},
+{ 0x1EF5, 0x0079, 0x0323},
+{ 0x1EF6, 0x0059, 0x0309},
+{ 0x1EF7, 0x0079, 0x0309},
+{ 0x1EF8, 0x0059, 0x0303},
+{ 0x1EF9, 0x0079, 0x0303},
+{ 0x1F00, 0x03B1, 0x0313},
+{ 0x1F01, 0x03B1, 0x0314},
+{ 0x1F02, 0x1F00, 0x0300},
+{ 0x1F03, 0x1F01, 0x0300},
+{ 0x1F04, 0x1F00, 0x0301},
+{ 0x1F05, 0x1F01, 0x0301},
+{ 0x1F06, 0x1F00, 0x0342},
+{ 0x1F07, 0x1F01, 0x0342},
+{ 0x1F08, 0x0391, 0x0313},
+{ 0x1F09, 0x0391, 0x0314},
+{ 0x1F0A, 0x1F08, 0x0300},
+{ 0x1F0B, 0x1F09, 0x0300},
+{ 0x1F0C, 0x1F08, 0x0301},
+{ 0x1F0D, 0x1F09, 0x0301},
+{ 0x1F0E, 0x1F08, 0x0342},
+{ 0x1F0F, 0x1F09, 0x0342},
+{ 0x1F10, 0x03B5, 0x0313},
+{ 0x1F11, 0x03B5, 0x0314},
+{ 0x1F12, 0x1F10, 0x0300},
+{ 0x1F13, 0x1F11, 0x0300},
+{ 0x1F14, 0x1F10, 0x0301},
+{ 0x1F15, 0x1F11, 0x0301},
+{ 0x1F18, 0x0395, 0x0313},
+{ 0x1F19, 0x0395, 0x0314},
+{ 0x1F1A, 0x1F18, 0x0300},
+{ 0x1F1B, 0x1F19, 0x0300},
+{ 0x1F1C, 0x1F18, 0x0301},
+{ 0x1F1D, 0x1F19, 0x0301},
+{ 0x1F20, 0x03B7, 0x0313},
+{ 0x1F21, 0x03B7, 0x0314},
+{ 0x1F22, 0x1F20, 0x0300},
+{ 0x1F23, 0x1F21, 0x0300},
+{ 0x1F24, 0x1F20, 0x0301},
+{ 0x1F25, 0x1F21, 0x0301},
+{ 0x1F26, 0x1F20, 0x0342},
+{ 0x1F27, 0x1F21, 0x0342},
+{ 0x1F28, 0x0397, 0x0313},
+{ 0x1F29, 0x0397, 0x0314},
+{ 0x1F2A, 0x1F28, 0x0300},
+{ 0x1F2B, 0x1F29, 0x0300},
+{ 0x1F2C, 0x1F28, 0x0301},
+{ 0x1F2D, 0x1F29, 0x0301},
+{ 0x1F2E, 0x1F28, 0x0342},
+{ 0x1F2F, 0x1F29, 0x0342},
+{ 0x1F30, 0x03B9, 0x0313},
+{ 0x1F31, 0x03B9, 0x0314},
+{ 0x1F32, 0x1F30, 0x0300},
+{ 0x1F33, 0x1F31, 0x0300},
+{ 0x1F34, 0x1F30, 0x0301},
+{ 0x1F35, 0x1F31, 0x0301},
+{ 0x1F36, 0x1F30, 0x0342},
+{ 0x1F37, 0x1F31, 0x0342},
+{ 0x1F38, 0x0399, 0x0313},
+{ 0x1F39, 0x0399, 0x0314},
+{ 0x1F3A, 0x1F38, 0x0300},
+{ 0x1F3B, 0x1F39, 0x0300},
+{ 0x1F3C, 0x1F38, 0x0301},
+{ 0x1F3D, 0x1F39, 0x0301},
+{ 0x1F3E, 0x1F38, 0x0342},
+{ 0x1F3F, 0x1F39, 0x0342},
+{ 0x1F40, 0x03BF, 0x0313},
+{ 0x1F41, 0x03BF, 0x0314},
+{ 0x1F42, 0x1F40, 0x0300},
+{ 0x1F43, 0x1F41, 0x0300},
+{ 0x1F44, 0x1F40, 0x0301},
+{ 0x1F45, 0x1F41, 0x0301},
+{ 0x1F48, 0x039F, 0x0313},
+{ 0x1F49, 0x039F, 0x0314},
+{ 0x1F4A, 0x1F48, 0x0300},
+{ 0x1F4B, 0x1F49, 0x0300},
+{ 0x1F4C, 0x1F48, 0x0301},
+{ 0x1F4D, 0x1F49, 0x0301},
+{ 0x1F50, 0x03C5, 0x0313},
+{ 0x1F51, 0x03C5, 0x0314},
+{ 0x1F52, 0x1F50, 0x0300},
+{ 0x1F53, 0x1F51, 0x0300},
+{ 0x1F54, 0x1F50, 0x0301},
+{ 0x1F55, 0x1F51, 0x0301},
+{ 0x1F56, 0x1F50, 0x0342},
+{ 0x1F57, 0x1F51, 0x0342},
+{ 0x1F59, 0x03A5, 0x0314},
+{ 0x1F5B, 0x1F59, 0x0300},
+{ 0x1F5D, 0x1F59, 0x0301},
+{ 0x1F5F, 0x1F59, 0x0342},
+{ 0x1F60, 0x03C9, 0x0313},
+{ 0x1F61, 0x03C9, 0x0314},
+{ 0x1F62, 0x1F60, 0x0300},
+{ 0x1F63, 0x1F61, 0x0300},
+{ 0x1F64, 0x1F60, 0x0301},
+{ 0x1F65, 0x1F61, 0x0301},
+{ 0x1F66, 0x1F60, 0x0342},
+{ 0x1F67, 0x1F61, 0x0342},
+{ 0x1F68, 0x03A9, 0x0313},
+{ 0x1F69, 0x03A9, 0x0314},
+{ 0x1F6A, 0x1F68, 0x0300},
+{ 0x1F6B, 0x1F69, 0x0300},
+{ 0x1F6C, 0x1F68, 0x0301},
+{ 0x1F6D, 0x1F69, 0x0301},
+{ 0x1F6E, 0x1F68, 0x0342},
+{ 0x1F6F, 0x1F69, 0x0342},
+{ 0x1F70, 0x03B1, 0x0300},
+{ 0x1F72, 0x03B5, 0x0300},
+{ 0x1F74, 0x03B7, 0x0300},
+{ 0x1F76, 0x03B9, 0x0300},
+{ 0x1F78, 0x03BF, 0x0300},
+{ 0x1F7A, 0x03C5, 0x0300},
+{ 0x1F7C, 0x03C9, 0x0300},
+{ 0x1F80, 0x1F00, 0x0345},
+{ 0x1F81, 0x1F01, 0x0345},
+{ 0x1F82, 0x1F02, 0x0345},
+{ 0x1F83, 0x1F03, 0x0345},
+{ 0x1F84, 0x1F04, 0x0345},
+{ 0x1F85, 0x1F05, 0x0345},
+{ 0x1F86, 0x1F06, 0x0345},
+{ 0x1F87, 0x1F07, 0x0345},
+{ 0x1F88, 0x1F08, 0x0345},
+{ 0x1F89, 0x1F09, 0x0345},
+{ 0x1F8A, 0x1F0A, 0x0345},
+{ 0x1F8B, 0x1F0B, 0x0345},
+{ 0x1F8C, 0x1F0C, 0x0345},
+{ 0x1F8D, 0x1F0D, 0x0345},
+{ 0x1F8E, 0x1F0E, 0x0345},
+{ 0x1F8F, 0x1F0F, 0x0345},
+{ 0x1F90, 0x1F20, 0x0345},
+{ 0x1F91, 0x1F21, 0x0345},
+{ 0x1F92, 0x1F22, 0x0345},
+{ 0x1F93, 0x1F23, 0x0345},
+{ 0x1F94, 0x1F24, 0x0345},
+{ 0x1F95, 0x1F25, 0x0345},
+{ 0x1F96, 0x1F26, 0x0345},
+{ 0x1F97, 0x1F27, 0x0345},
+{ 0x1F98, 0x1F28, 0x0345},
+{ 0x1F99, 0x1F29, 0x0345},
+{ 0x1F9A, 0x1F2A, 0x0345},
+{ 0x1F9B, 0x1F2B, 0x0345},
+{ 0x1F9C, 0x1F2C, 0x0345},
+{ 0x1F9D, 0x1F2D, 0x0345},
+{ 0x1F9E, 0x1F2E, 0x0345},
+{ 0x1F9F, 0x1F2F, 0x0345},
+{ 0x1FA0, 0x1F60, 0x0345},
+{ 0x1FA1, 0x1F61, 0x0345},
+{ 0x1FA2, 0x1F62, 0x0345},
+{ 0x1FA3, 0x1F63, 0x0345},
+{ 0x1FA4, 0x1F64, 0x0345},
+{ 0x1FA5, 0x1F65, 0x0345},
+{ 0x1FA6, 0x1F66, 0x0345},
+{ 0x1FA7, 0x1F67, 0x0345},
+{ 0x1FA8, 0x1F68, 0x0345},
+{ 0x1FA9, 0x1F69, 0x0345},
+{ 0x1FAA, 0x1F6A, 0x0345},
+{ 0x1FAB, 0x1F6B, 0x0345},
+{ 0x1FAC, 0x1F6C, 0x0345},
+{ 0x1FAD, 0x1F6D, 0x0345},
+{ 0x1FAE, 0x1F6E, 0x0345},
+{ 0x1FAF, 0x1F6F, 0x0345},
+{ 0x1FB0, 0x03B1, 0x0306},
+{ 0x1FB1, 0x03B1, 0x0304},
+{ 0x1FB2, 0x1F70, 0x0345},
+{ 0x1FB3, 0x03B1, 0x0345},
+{ 0x1FB4, 0x03AC, 0x0345},
+{ 0x1FB6, 0x03B1, 0x0342},
+{ 0x1FB7, 0x1FB6, 0x0345},
+{ 0x1FB8, 0x0391, 0x0306},
+{ 0x1FB9, 0x0391, 0x0304},
+{ 0x1FBA, 0x0391, 0x0300},
+{ 0x1FBC, 0x0391, 0x0345},
+{ 0x1FC1, 0x00A8, 0x0342},
+{ 0x1FC2, 0x1F74, 0x0345},
+{ 0x1FC3, 0x03B7, 0x0345},
+{ 0x1FC4, 0x03AE, 0x0345},
+{ 0x1FC6, 0x03B7, 0x0342},
+{ 0x1FC7, 0x1FC6, 0x0345},
+{ 0x1FC8, 0x0395, 0x0300},
+{ 0x1FCA, 0x0397, 0x0300},
+{ 0x1FCC, 0x0397, 0x0345},
+{ 0x1FCD, 0x1FBF, 0x0300},
+{ 0x1FCE, 0x1FBF, 0x0301},
+{ 0x1FCF, 0x1FBF, 0x0342},
+{ 0x1FD0, 0x03B9, 0x0306},
+{ 0x1FD1, 0x03B9, 0x0304},
+{ 0x1FD2, 0x03CA, 0x0300},
+{ 0x1FD6, 0x03B9, 0x0342},
+{ 0x1FD7, 0x03CA, 0x0342},
+{ 0x1FD8, 0x0399, 0x0306},
+{ 0x1FD9, 0x0399, 0x0304},
+{ 0x1FDA, 0x0399, 0x0300},
+{ 0x1FDD, 0x1FFE, 0x0300},
+{ 0x1FDE, 0x1FFE, 0x0301},
+{ 0x1FDF, 0x1FFE, 0x0342},
+{ 0x1FE0, 0x03C5, 0x0306},
+{ 0x1FE1, 0x03C5, 0x0304},
+{ 0x1FE2, 0x03CB, 0x0300},
+{ 0x1FE4, 0x03C1, 0x0313},
+{ 0x1FE5, 0x03C1, 0x0314},
+{ 0x1FE6, 0x03C5, 0x0342},
+{ 0x1FE7, 0x03CB, 0x0342},
+{ 0x1FE8, 0x03A5, 0x0306},
+{ 0x1FE9, 0x03A5, 0x0304},
+{ 0x1FEA, 0x03A5, 0x0300},
+{ 0x1FEC, 0x03A1, 0x0314},
+{ 0x1FED, 0x00A8, 0x0300},
+{ 0x1FF2, 0x1F7C, 0x0345},
+{ 0x1FF3, 0x03C9, 0x0345},
+{ 0x1FF4, 0x03CE, 0x0345},
+{ 0x1FF6, 0x03C9, 0x0342},
+{ 0x1FF7, 0x1FF6, 0x0345},
+{ 0x1FF8, 0x039F, 0x0300},
+{ 0x1FFA, 0x03A9, 0x0300},
+{ 0x1FFC, 0x03A9, 0x0345},
+{ 0x219A, 0x2190, 0x0338},
+{ 0x219B, 0x2192, 0x0338},
+{ 0x21AE, 0x2194, 0x0338},
+{ 0x21CD, 0x21D0, 0x0338},
+{ 0x21CE, 0x21D4, 0x0338},
+{ 0x21CF, 0x21D2, 0x0338},
+{ 0x2204, 0x2203, 0x0338},
+{ 0x2209, 0x2208, 0x0338},
+{ 0x220C, 0x220B, 0x0338},
+{ 0x2224, 0x2223, 0x0338},
+{ 0x2226, 0x2225, 0x0338},
+{ 0x2241, 0x223C, 0x0338},
+{ 0x2244, 0x2243, 0x0338},
+{ 0x2247, 0x2245, 0x0338},
+{ 0x2249, 0x2248, 0x0338},
+{ 0x2260, 0x003D, 0x0338},
+{ 0x2262, 0x2261, 0x0338},
+{ 0x226D, 0x224D, 0x0338},
+{ 0x226E, 0x003C, 0x0338},
+{ 0x226F, 0x003E, 0x0338},
+{ 0x2270, 0x2264, 0x0338},
+{ 0x2271, 0x2265, 0x0338},
+{ 0x2274, 0x2272, 0x0338},
+{ 0x2275, 0x2273, 0x0338},
+{ 0x2278, 0x2276, 0x0338},
+{ 0x2279, 0x2277, 0x0338},
+{ 0x2280, 0x227A, 0x0338},
+{ 0x2281, 0x227B, 0x0338},
+{ 0x2284, 0x2282, 0x0338},
+{ 0x2285, 0x2283, 0x0338},
+{ 0x2288, 0x2286, 0x0338},
+{ 0x2289, 0x2287, 0x0338},
+{ 0x22AC, 0x22A2, 0x0338},
+{ 0x22AD, 0x22A8, 0x0338},
+{ 0x22AE, 0x22A9, 0x0338},
+{ 0x22AF, 0x22AB, 0x0338},
+{ 0x22E0, 0x227C, 0x0338},
+{ 0x22E1, 0x227D, 0x0338},
+{ 0x22E2, 0x2291, 0x0338},
+{ 0x22E3, 0x2292, 0x0338},
+{ 0x22EA, 0x22B2, 0x0338},
+{ 0x22EB, 0x22B3, 0x0338},
+{ 0x22EC, 0x22B4, 0x0338},
+{ 0x22ED, 0x22B5, 0x0338},
+{ 0x304C, 0x304B, 0x3099},
+{ 0x304E, 0x304D, 0x3099},
+{ 0x3050, 0x304F, 0x3099},
+{ 0x3052, 0x3051, 0x3099},
+{ 0x3054, 0x3053, 0x3099},
+{ 0x3056, 0x3055, 0x3099},
+{ 0x3058, 0x3057, 0x3099},
+{ 0x305A, 0x3059, 0x3099},
+{ 0x305C, 0x305B, 0x3099},
+{ 0x305E, 0x305D, 0x3099},
+{ 0x3060, 0x305F, 0x3099},
+{ 0x3062, 0x3061, 0x3099},
+{ 0x3065, 0x3064, 0x3099},
+{ 0x3067, 0x3066, 0x3099},
+{ 0x3069, 0x3068, 0x3099},
+{ 0x3070, 0x306F, 0x3099},
+{ 0x3071, 0x306F, 0x309A},
+{ 0x3073, 0x3072, 0x3099},
+{ 0x3074, 0x3072, 0x309A},
+{ 0x3076, 0x3075, 0x3099},
+{ 0x3077, 0x3075, 0x309A},
+{ 0x3079, 0x3078, 0x3099},
+{ 0x307A, 0x3078, 0x309A},
+{ 0x307C, 0x307B, 0x3099},
+{ 0x307D, 0x307B, 0x309A},
+{ 0x3094, 0x3046, 0x3099},
+{ 0x309E, 0x309D, 0x3099},
+{ 0x30AC, 0x30AB, 0x3099},
+{ 0x30AE, 0x30AD, 0x3099},
+{ 0x30B0, 0x30AF, 0x3099},
+{ 0x30B2, 0x30B1, 0x3099},
+{ 0x30B4, 0x30B3, 0x3099},
+{ 0x30B6, 0x30B5, 0x3099},
+{ 0x30B8, 0x30B7, 0x3099},
+{ 0x30BA, 0x30B9, 0x3099},
+{ 0x30BC, 0x30BB, 0x3099},
+{ 0x30BE, 0x30BD, 0x3099},
+{ 0x30C0, 0x30BF, 0x3099},
+{ 0x30C2, 0x30C1, 0x3099},
+{ 0x30C5, 0x30C4, 0x3099},
+{ 0x30C7, 0x30C6, 0x3099},
+{ 0x30C9, 0x30C8, 0x3099},
+{ 0x30D0, 0x30CF, 0x3099},
+{ 0x30D1, 0x30CF, 0x309A},
+{ 0x30D3, 0x30D2, 0x3099},
+{ 0x30D4, 0x30D2, 0x309A},
+{ 0x30D6, 0x30D5, 0x3099},
+{ 0x30D7, 0x30D5, 0x309A},
+{ 0x30D9, 0x30D8, 0x3099},
+{ 0x30DA, 0x30D8, 0x309A},
+{ 0x30DC, 0x30DB, 0x3099},
+{ 0x30DD, 0x30DB, 0x309A},
+{ 0x30F4, 0x30A6, 0x3099},
+{ 0x30F7, 0x30EF, 0x3099},
+{ 0x30F8, 0x30F0, 0x3099},
+{ 0x30F9, 0x30F1, 0x3099},
+{ 0x30FA, 0x30F2, 0x3099},
+{ 0x30FE, 0x30FD, 0x3099},
+{ 0xFB1D, 0x05D9, 0x05B4},
+{ 0xFB1F, 0x05F2, 0x05B7},
+{ 0xFB2A, 0x05E9, 0x05C1},
+{ 0xFB2B, 0x05E9, 0x05C2},
+{ 0xFB2C, 0xFB49, 0x05C1},
+{ 0xFB2D, 0xFB49, 0x05C2},
+{ 0xFB2E, 0x05D0, 0x05B7},
+{ 0xFB2F, 0x05D0, 0x05B8},
+{ 0xFB30, 0x05D0, 0x05BC},
+{ 0xFB31, 0x05D1, 0x05BC},
+{ 0xFB32, 0x05D2, 0x05BC},
+{ 0xFB33, 0x05D3, 0x05BC},
+{ 0xFB34, 0x05D4, 0x05BC},
+{ 0xFB35, 0x05D5, 0x05BC},
+{ 0xFB36, 0x05D6, 0x05BC},
+{ 0xFB38, 0x05D8, 0x05BC},
+{ 0xFB39, 0x05D9, 0x05BC},
+{ 0xFB3A, 0x05DA, 0x05BC},
+{ 0xFB3B, 0x05DB, 0x05BC},
+{ 0xFB3C, 0x05DC, 0x05BC},
+{ 0xFB3E, 0x05DE, 0x05BC},
+{ 0xFB40, 0x05E0, 0x05BC},
+{ 0xFB41, 0x05E1, 0x05BC},
+{ 0xFB43, 0x05E3, 0x05BC},
+{ 0xFB44, 0x05E4, 0x05BC},
+{ 0xFB46, 0x05E6, 0x05BC},
+{ 0xFB47, 0x05E7, 0x05BC},
+{ 0xFB48, 0x05E8, 0x05BC},
+{ 0xFB49, 0x05E9, 0x05BC},
+{ 0xFB4A, 0x05EA, 0x05BC},
+{ 0xFB4B, 0x05D5, 0x05B9},
+{ 0xFB4C, 0x05D1, 0x05BF},
+{ 0xFB4D, 0x05DB, 0x05BF},
+{ 0xFB4E, 0x05E4, 0x05BF},
+};
diff --git a/libatalk/unicode/ucs2_casetable.h b/libatalk/unicode/ucs2_casetable.h
new file mode 100644 (file)
index 0000000..ae94e2e
--- /dev/null
@@ -0,0 +1,472 @@
+static u_int16_t upcase_table_1[64] = {
+0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,   /* 0x0040-0x0047 */ 
+0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,   /* 0x0048-0x004F */ 
+0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,   /* 0x0050-0x0057 */ 
+0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,   /* 0x0058-0x005F */ 
+0x0060, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,   /* 0x0060-0x0067 */ 
+0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,   /* 0x0068-0x006F */ 
+0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,   /* 0x0070-0x0077 */ 
+0x0058, 0x0059, 0x005A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F }; /* 0x0078-0x007F */
+
+static u_int16_t upcase_table_2[512] = {
+0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,   /* 0x00C0-0x00C7 */ 
+0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,   /* 0x00C8-0x00CF */ 
+0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,   /* 0x00D0-0x00D7 */ 
+0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,   /* 0x00D8-0x00DF */ 
+0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,   /* 0x00E0-0x00E7 */ 
+0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,   /* 0x00E8-0x00EF */ 
+0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00F7,   /* 0x00F0-0x00F7 */ 
+0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x0178,   /* 0x00F8-0x00FF */ 
+0x0100, 0x0100, 0x0102, 0x0102, 0x0104, 0x0104, 0x0106, 0x0106,   /* 0x0100-0x0107 */ 
+0x0108, 0x0108, 0x010A, 0x010A, 0x010C, 0x010C, 0x010E, 0x010E,   /* 0x0108-0x010F */ 
+0x0110, 0x0110, 0x0112, 0x0112, 0x0114, 0x0114, 0x0116, 0x0116,   /* 0x0110-0x0117 */ 
+0x0118, 0x0118, 0x011A, 0x011A, 0x011C, 0x011C, 0x011E, 0x011E,   /* 0x0118-0x011F */ 
+0x0120, 0x0120, 0x0122, 0x0122, 0x0124, 0x0124, 0x0126, 0x0126,   /* 0x0120-0x0127 */ 
+0x0128, 0x0128, 0x012A, 0x012A, 0x012C, 0x012C, 0x012E, 0x012E,   /* 0x0128-0x012F */ 
+0x0130, 0x0131, 0x0132, 0x0132, 0x0134, 0x0134, 0x0136, 0x0136,   /* 0x0130-0x0137 */ 
+0x0138, 0x0139, 0x0139, 0x013B, 0x013B, 0x013D, 0x013D, 0x013F,   /* 0x0138-0x013F */ 
+0x013F, 0x0141, 0x0141, 0x0143, 0x0143, 0x0145, 0x0145, 0x0147,   /* 0x0140-0x0147 */ 
+0x0147, 0x0149, 0x014A, 0x014A, 0x014C, 0x014C, 0x014E, 0x014E,   /* 0x0148-0x014F */ 
+0x0150, 0x0150, 0x0152, 0x0152, 0x0154, 0x0154, 0x0156, 0x0156,   /* 0x0150-0x0157 */ 
+0x0158, 0x0158, 0x015A, 0x015A, 0x015C, 0x015C, 0x015E, 0x015E,   /* 0x0158-0x015F */ 
+0x0160, 0x0160, 0x0162, 0x0162, 0x0164, 0x0164, 0x0166, 0x0166,   /* 0x0160-0x0167 */ 
+0x0168, 0x0168, 0x016A, 0x016A, 0x016C, 0x016C, 0x016E, 0x016E,   /* 0x0168-0x016F */ 
+0x0170, 0x0170, 0x0172, 0x0172, 0x0174, 0x0174, 0x0176, 0x0176,   /* 0x0170-0x0177 */ 
+0x0178, 0x0179, 0x0179, 0x017B, 0x017B, 0x017D, 0x017D, 0x017F,   /* 0x0178-0x017F */ 
+0x0180, 0x0181, 0x0182, 0x0182, 0x0184, 0x0184, 0x0186, 0x0187,   /* 0x0180-0x0187 */ 
+0x0187, 0x0189, 0x018A, 0x018B, 0x018B, 0x018D, 0x018E, 0x018F,   /* 0x0188-0x018F */ 
+0x0190, 0x0191, 0x0191, 0x0193, 0x0194, 0x0195, 0x0196, 0x0197,   /* 0x0190-0x0197 */ 
+0x0198, 0x0198, 0x019A, 0x019B, 0x019C, 0x019D, 0x019E, 0x019F,   /* 0x0198-0x019F */ 
+0x01A0, 0x01A0, 0x01A2, 0x01A2, 0x01A4, 0x01A4, 0x01A6, 0x01A7,   /* 0x01A0-0x01A7 */ 
+0x01A7, 0x01A9, 0x01AA, 0x01AB, 0x01AC, 0x01AC, 0x01AE, 0x01AF,   /* 0x01A8-0x01AF */ 
+0x01AF, 0x01B1, 0x01B2, 0x01B3, 0x01B3, 0x01B5, 0x01B5, 0x01B7,   /* 0x01B0-0x01B7 */ 
+0x01B8, 0x01B8, 0x01BA, 0x01BB, 0x01BC, 0x01BC, 0x01BE, 0x01BF,   /* 0x01B8-0x01BF */ 
+0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C4, 0x01C5, 0x01C4, 0x01C7,   /* 0x01C0-0x01C7 */ 
+0x01C8, 0x01C7, 0x01CA, 0x01CB, 0x01CA, 0x01CD, 0x01CD, 0x01CF,   /* 0x01C8-0x01CF */ 
+0x01CF, 0x01D1, 0x01D1, 0x01D3, 0x01D3, 0x01D5, 0x01D5, 0x01D7,   /* 0x01D0-0x01D7 */ 
+0x01D7, 0x01D9, 0x01D9, 0x01DB, 0x01DB, 0x018E, 0x01DE, 0x01DE,   /* 0x01D8-0x01DF */ 
+0x01E0, 0x01E0, 0x01E2, 0x01E2, 0x01E4, 0x01E4, 0x01E6, 0x01E6,   /* 0x01E0-0x01E7 */ 
+0x01E8, 0x01E8, 0x01EA, 0x01EA, 0x01EC, 0x01EC, 0x01EE, 0x01EE,   /* 0x01E8-0x01EF */ 
+0x01F0, 0x01F1, 0x01F2, 0x01F1, 0x01F4, 0x01F4, 0x01F6, 0x01F7,   /* 0x01F0-0x01F7 */ 
+0x01F8, 0x01F9, 0x01FA, 0x01FA, 0x01FC, 0x01FC, 0x01FE, 0x01FE,   /* 0x01F8-0x01FF */ 
+0x0200, 0x0200, 0x0202, 0x0202, 0x0204, 0x0204, 0x0206, 0x0206,   /* 0x0200-0x0207 */ 
+0x0208, 0x0208, 0x020A, 0x020A, 0x020C, 0x020C, 0x020E, 0x020E,   /* 0x0208-0x020F */ 
+0x0210, 0x0210, 0x0212, 0x0212, 0x0214, 0x0214, 0x0216, 0x0216,   /* 0x0210-0x0217 */ 
+0x0218, 0x0219, 0x021A, 0x021B, 0x021C, 0x021D, 0x021E, 0x021F,   /* 0x0218-0x021F */ 
+0x0220, 0x0221, 0x0222, 0x0223, 0x0224, 0x0225, 0x0226, 0x0227,   /* 0x0220-0x0227 */ 
+0x0228, 0x0229, 0x022A, 0x022B, 0x022C, 0x022D, 0x022E, 0x022F,   /* 0x0228-0x022F */ 
+0x0230, 0x0231, 0x0232, 0x0233, 0x0234, 0x0235, 0x0236, 0x0237,   /* 0x0230-0x0237 */ 
+0x0238, 0x0239, 0x023A, 0x023B, 0x023C, 0x023D, 0x023E, 0x023F,   /* 0x0238-0x023F */ 
+0x0240, 0x0241, 0x0242, 0x0243, 0x0244, 0x0245, 0x0246, 0x0247,   /* 0x0240-0x0247 */ 
+0x0248, 0x0249, 0x024A, 0x024B, 0x024C, 0x024D, 0x024E, 0x024F,   /* 0x0248-0x024F */ 
+0x0250, 0x0251, 0x0252, 0x0181, 0x0186, 0x0255, 0x0189, 0x018A,   /* 0x0250-0x0257 */ 
+0x0258, 0x018F, 0x025A, 0x0190, 0x025C, 0x025D, 0x025E, 0x025F,   /* 0x0258-0x025F */ 
+0x0193, 0x0261, 0x0262, 0x0194, 0x0264, 0x0265, 0x0266, 0x0267,   /* 0x0260-0x0267 */ 
+0x0197, 0x0196, 0x026A, 0x026B, 0x026C, 0x026D, 0x026E, 0x019C,   /* 0x0268-0x026F */ 
+0x0270, 0x0271, 0x019D, 0x0273, 0x0274, 0x019F, 0x0276, 0x0277,   /* 0x0270-0x0277 */ 
+0x0278, 0x0279, 0x027A, 0x027B, 0x027C, 0x027D, 0x027E, 0x027F,   /* 0x0278-0x027F */ 
+0x0280, 0x0281, 0x0282, 0x01A9, 0x0284, 0x0285, 0x0286, 0x0287,   /* 0x0280-0x0287 */ 
+0x01AE, 0x0289, 0x01B1, 0x01B2, 0x028C, 0x028D, 0x028E, 0x028F,   /* 0x0288-0x028F */ 
+0x0290, 0x0291, 0x01B7, 0x0293, 0x0294, 0x0295, 0x0296, 0x0297,   /* 0x0290-0x0297 */ 
+0x0298, 0x0299, 0x029A, 0x029B, 0x029C, 0x029D, 0x029E, 0x029F,   /* 0x0298-0x029F */ 
+0x02A0, 0x02A1, 0x02A2, 0x02A3, 0x02A4, 0x02A5, 0x02A6, 0x02A7,   /* 0x02A0-0x02A7 */ 
+0x02A8, 0x02A9, 0x02AA, 0x02AB, 0x02AC, 0x02AD, 0x02AE, 0x02AF,   /* 0x02A8-0x02AF */ 
+0x02B0, 0x02B1, 0x02B2, 0x02B3, 0x02B4, 0x02B5, 0x02B6, 0x02B7,   /* 0x02B0-0x02B7 */ 
+0x02B8, 0x02B9, 0x02BA, 0x02BB, 0x02BC, 0x02BD, 0x02BE, 0x02BF }; /* 0x02B8-0x02BF */
+
+static u_int16_t upcase_table_3[384] = {
+0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0386, 0x0387,   /* 0x0380-0x0387 */ 
+0x0388, 0x0389, 0x038A, 0x038B, 0x038C, 0x038D, 0x038E, 0x038F,   /* 0x0388-0x038F */ 
+0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,   /* 0x0390-0x0397 */ 
+0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,   /* 0x0398-0x039F */ 
+0x03A0, 0x03A1, 0x03A2, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,   /* 0x03A0-0x03A7 */ 
+0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x0386, 0x0388, 0x0389, 0x038A,   /* 0x03A8-0x03AF */ 
+0x03B0, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,   /* 0x03B0-0x03B7 */ 
+0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,   /* 0x03B8-0x03BF */ 
+0x03A0, 0x03A1, 0x03A3, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,   /* 0x03C0-0x03C7 */ 
+0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x038C, 0x038E, 0x038F, 0x03CF,   /* 0x03C8-0x03CF */ 
+0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7,   /* 0x03D0-0x03D7 */ 
+0x03D8, 0x03D9, 0x03DA, 0x03DB, 0x03DC, 0x03DD, 0x03DE, 0x03DF,   /* 0x03D8-0x03DF */ 
+0x03E0, 0x03E1, 0x03E2, 0x03E2, 0x03E4, 0x03E4, 0x03E6, 0x03E6,   /* 0x03E0-0x03E7 */ 
+0x03E8, 0x03E8, 0x03EA, 0x03EA, 0x03EC, 0x03EC, 0x03EE, 0x03EE,   /* 0x03E8-0x03EF */ 
+0x03F0, 0x03F1, 0x03F2, 0x03F3, 0x03F4, 0x03F5, 0x03F6, 0x03F7,   /* 0x03F0-0x03F7 */ 
+0x03F8, 0x03F9, 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF,   /* 0x03F8-0x03FF */ 
+0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,   /* 0x0400-0x0407 */ 
+0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x040D, 0x040E, 0x040F,   /* 0x0408-0x040F */ 
+0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,   /* 0x0410-0x0417 */ 
+0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,   /* 0x0418-0x041F */ 
+0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,   /* 0x0420-0x0427 */ 
+0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,   /* 0x0428-0x042F */ 
+0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,   /* 0x0430-0x0437 */ 
+0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,   /* 0x0438-0x043F */ 
+0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,   /* 0x0440-0x0447 */ 
+0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,   /* 0x0448-0x044F */ 
+0x0450, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,   /* 0x0450-0x0457 */ 
+0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x045D, 0x040E, 0x040F,   /* 0x0458-0x045F */ 
+0x0460, 0x0460, 0x0462, 0x0462, 0x0464, 0x0464, 0x0466, 0x0466,   /* 0x0460-0x0467 */ 
+0x0468, 0x0468, 0x046A, 0x046A, 0x046C, 0x046C, 0x046E, 0x046E,   /* 0x0468-0x046F */ 
+0x0470, 0x0470, 0x0472, 0x0472, 0x0474, 0x0474, 0x0476, 0x0476,   /* 0x0470-0x0477 */ 
+0x0478, 0x0478, 0x047A, 0x047A, 0x047C, 0x047C, 0x047E, 0x047E,   /* 0x0478-0x047F */ 
+0x0480, 0x0480, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487,   /* 0x0480-0x0487 */ 
+0x0488, 0x0489, 0x048A, 0x048B, 0x048C, 0x048D, 0x048E, 0x048F,   /* 0x0488-0x048F */ 
+0x0490, 0x0490, 0x0492, 0x0492, 0x0494, 0x0494, 0x0496, 0x0496,   /* 0x0490-0x0497 */ 
+0x0498, 0x0498, 0x049A, 0x049A, 0x049C, 0x049C, 0x049E, 0x049E,   /* 0x0498-0x049F */ 
+0x04A0, 0x04A0, 0x04A2, 0x04A2, 0x04A4, 0x04A4, 0x04A6, 0x04A6,   /* 0x04A0-0x04A7 */ 
+0x04A8, 0x04A8, 0x04AA, 0x04AA, 0x04AC, 0x04AC, 0x04AE, 0x04AE,   /* 0x04A8-0x04AF */ 
+0x04B0, 0x04B0, 0x04B2, 0x04B2, 0x04B4, 0x04B4, 0x04B6, 0x04B6,   /* 0x04B0-0x04B7 */ 
+0x04B8, 0x04B8, 0x04BA, 0x04BA, 0x04BC, 0x04BC, 0x04BE, 0x04BE,   /* 0x04B8-0x04BF */ 
+0x04C0, 0x04C1, 0x04C1, 0x04C3, 0x04C3, 0x04C5, 0x04C6, 0x04C7,   /* 0x04C0-0x04C7 */ 
+0x04C7, 0x04C9, 0x04CA, 0x04CB, 0x04CB, 0x04CD, 0x04CE, 0x04CF,   /* 0x04C8-0x04CF */ 
+0x04D0, 0x04D0, 0x04D2, 0x04D2, 0x04D4, 0x04D4, 0x04D6, 0x04D6,   /* 0x04D0-0x04D7 */ 
+0x04D8, 0x04D8, 0x04DA, 0x04DA, 0x04DC, 0x04DC, 0x04DE, 0x04DE,   /* 0x04D8-0x04DF */ 
+0x04E0, 0x04E0, 0x04E2, 0x04E2, 0x04E4, 0x04E4, 0x04E6, 0x04E6,   /* 0x04E0-0x04E7 */ 
+0x04E8, 0x04E8, 0x04EA, 0x04EA, 0x04EC, 0x04ED, 0x04EE, 0x04EE,   /* 0x04E8-0x04EF */ 
+0x04F0, 0x04F0, 0x04F2, 0x04F2, 0x04F4, 0x04F4, 0x04F6, 0x04F7,   /* 0x04F0-0x04F7 */ 
+0x04F8, 0x04F8, 0x04FA, 0x04FB, 0x04FC, 0x04FD, 0x04FE, 0x04FF }; /* 0x04F8-0x04FF */
+
+static u_int16_t upcase_table_4[128] = {
+0x0540, 0x0541, 0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547,   /* 0x0540-0x0547 */ 
+0x0548, 0x0549, 0x054A, 0x054B, 0x054C, 0x054D, 0x054E, 0x054F,   /* 0x0548-0x054F */ 
+0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555, 0x0556, 0x0557,   /* 0x0550-0x0557 */ 
+0x0558, 0x0559, 0x055A, 0x055B, 0x055C, 0x055D, 0x055E, 0x055F,   /* 0x0558-0x055F */ 
+0x0560, 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, 0x0536, 0x0537,   /* 0x0560-0x0567 */ 
+0x0538, 0x0539, 0x053A, 0x053B, 0x053C, 0x053D, 0x053E, 0x053F,   /* 0x0568-0x056F */ 
+0x0540, 0x0541, 0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547,   /* 0x0570-0x0577 */ 
+0x0548, 0x0549, 0x054A, 0x054B, 0x054C, 0x054D, 0x054E, 0x054F,   /* 0x0578-0x057F */ 
+0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555, 0x0556, 0x0587,   /* 0x0580-0x0587 */ 
+0x0588, 0x0589, 0x058A, 0x058B, 0x058C, 0x058D, 0x058E, 0x058F,   /* 0x0588-0x058F */ 
+0x0590, 0x0591, 0x0592, 0x0593, 0x0594, 0x0595, 0x0596, 0x0597,   /* 0x0590-0x0597 */ 
+0x0598, 0x0599, 0x059A, 0x059B, 0x059C, 0x059D, 0x059E, 0x059F,   /* 0x0598-0x059F */ 
+0x05A0, 0x05A1, 0x05A2, 0x05A3, 0x05A4, 0x05A5, 0x05A6, 0x05A7,   /* 0x05A0-0x05A7 */ 
+0x05A8, 0x05A9, 0x05AA, 0x05AB, 0x05AC, 0x05AD, 0x05AE, 0x05AF,   /* 0x05A8-0x05AF */ 
+0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7,   /* 0x05B0-0x05B7 */ 
+0x05B8, 0x05B9, 0x05BA, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF }; /* 0x05B8-0x05BF */
+
+static u_int16_t upcase_table_5[512] = {
+0x1E00, 0x1E00, 0x1E02, 0x1E02, 0x1E04, 0x1E04, 0x1E06, 0x1E06,   /* 0x1E00-0x1E07 */ 
+0x1E08, 0x1E08, 0x1E0A, 0x1E0A, 0x1E0C, 0x1E0C, 0x1E0E, 0x1E0E,   /* 0x1E08-0x1E0F */ 
+0x1E10, 0x1E10, 0x1E12, 0x1E12, 0x1E14, 0x1E14, 0x1E16, 0x1E16,   /* 0x1E10-0x1E17 */ 
+0x1E18, 0x1E18, 0x1E1A, 0x1E1A, 0x1E1C, 0x1E1C, 0x1E1E, 0x1E1E,   /* 0x1E18-0x1E1F */ 
+0x1E20, 0x1E20, 0x1E22, 0x1E22, 0x1E24, 0x1E24, 0x1E26, 0x1E26,   /* 0x1E20-0x1E27 */ 
+0x1E28, 0x1E28, 0x1E2A, 0x1E2A, 0x1E2C, 0x1E2C, 0x1E2E, 0x1E2E,   /* 0x1E28-0x1E2F */ 
+0x1E30, 0x1E30, 0x1E32, 0x1E32, 0x1E34, 0x1E34, 0x1E36, 0x1E36,   /* 0x1E30-0x1E37 */ 
+0x1E38, 0x1E38, 0x1E3A, 0x1E3A, 0x1E3C, 0x1E3C, 0x1E3E, 0x1E3E,   /* 0x1E38-0x1E3F */ 
+0x1E40, 0x1E40, 0x1E42, 0x1E42, 0x1E44, 0x1E44, 0x1E46, 0x1E46,   /* 0x1E40-0x1E47 */ 
+0x1E48, 0x1E48, 0x1E4A, 0x1E4A, 0x1E4C, 0x1E4C, 0x1E4E, 0x1E4E,   /* 0x1E48-0x1E4F */ 
+0x1E50, 0x1E50, 0x1E52, 0x1E52, 0x1E54, 0x1E54, 0x1E56, 0x1E56,   /* 0x1E50-0x1E57 */ 
+0x1E58, 0x1E58, 0x1E5A, 0x1E5A, 0x1E5C, 0x1E5C, 0x1E5E, 0x1E5E,   /* 0x1E58-0x1E5F */ 
+0x1E60, 0x1E60, 0x1E62, 0x1E62, 0x1E64, 0x1E64, 0x1E66, 0x1E66,   /* 0x1E60-0x1E67 */ 
+0x1E68, 0x1E68, 0x1E6A, 0x1E6A, 0x1E6C, 0x1E6C, 0x1E6E, 0x1E6E,   /* 0x1E68-0x1E6F */ 
+0x1E70, 0x1E70, 0x1E72, 0x1E72, 0x1E74, 0x1E74, 0x1E76, 0x1E76,   /* 0x1E70-0x1E77 */ 
+0x1E78, 0x1E78, 0x1E7A, 0x1E7A, 0x1E7C, 0x1E7C, 0x1E7E, 0x1E7E,   /* 0x1E78-0x1E7F */ 
+0x1E80, 0x1E80, 0x1E82, 0x1E82, 0x1E84, 0x1E84, 0x1E86, 0x1E86,   /* 0x1E80-0x1E87 */ 
+0x1E88, 0x1E88, 0x1E8A, 0x1E8A, 0x1E8C, 0x1E8C, 0x1E8E, 0x1E8E,   /* 0x1E88-0x1E8F */ 
+0x1E90, 0x1E90, 0x1E92, 0x1E92, 0x1E94, 0x1E94, 0x1E96, 0x1E97,   /* 0x1E90-0x1E97 */ 
+0x1E98, 0x1E99, 0x1E9A, 0x1E9B, 0x1E9C, 0x1E9D, 0x1E9E, 0x1E9F,   /* 0x1E98-0x1E9F */ 
+0x1EA0, 0x1EA0, 0x1EA2, 0x1EA2, 0x1EA4, 0x1EA4, 0x1EA6, 0x1EA6,   /* 0x1EA0-0x1EA7 */ 
+0x1EA8, 0x1EA8, 0x1EAA, 0x1EAA, 0x1EAC, 0x1EAC, 0x1EAE, 0x1EAE,   /* 0x1EA8-0x1EAF */ 
+0x1EB0, 0x1EB0, 0x1EB2, 0x1EB2, 0x1EB4, 0x1EB4, 0x1EB6, 0x1EB6,   /* 0x1EB0-0x1EB7 */ 
+0x1EB8, 0x1EB8, 0x1EBA, 0x1EBA, 0x1EBC, 0x1EBC, 0x1EBE, 0x1EBE,   /* 0x1EB8-0x1EBF */ 
+0x1EC0, 0x1EC0, 0x1EC2, 0x1EC2, 0x1EC4, 0x1EC4, 0x1EC6, 0x1EC6,   /* 0x1EC0-0x1EC7 */ 
+0x1EC8, 0x1EC8, 0x1ECA, 0x1ECA, 0x1ECC, 0x1ECC, 0x1ECE, 0x1ECE,   /* 0x1EC8-0x1ECF */ 
+0x1ED0, 0x1ED0, 0x1ED2, 0x1ED2, 0x1ED4, 0x1ED4, 0x1ED6, 0x1ED6,   /* 0x1ED0-0x1ED7 */ 
+0x1ED8, 0x1ED8, 0x1EDA, 0x1EDA, 0x1EDC, 0x1EDC, 0x1EDE, 0x1EDE,   /* 0x1ED8-0x1EDF */ 
+0x1EE0, 0x1EE0, 0x1EE2, 0x1EE2, 0x1EE4, 0x1EE4, 0x1EE6, 0x1EE6,   /* 0x1EE0-0x1EE7 */ 
+0x1EE8, 0x1EE8, 0x1EEA, 0x1EEA, 0x1EEC, 0x1EEC, 0x1EEE, 0x1EEE,   /* 0x1EE8-0x1EEF */ 
+0x1EF0, 0x1EF0, 0x1EF2, 0x1EF2, 0x1EF4, 0x1EF4, 0x1EF6, 0x1EF6,   /* 0x1EF0-0x1EF7 */ 
+0x1EF8, 0x1EF8, 0x1EFA, 0x1EFB, 0x1EFC, 0x1EFD, 0x1EFE, 0x1EFF,   /* 0x1EF8-0x1EFF */ 
+0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F,   /* 0x1F00-0x1F07 */ 
+0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F,   /* 0x1F08-0x1F0F */ 
+0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x1F16, 0x1F17,   /* 0x1F10-0x1F17 */ 
+0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x1F1E, 0x1F1F,   /* 0x1F18-0x1F1F */ 
+0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F,   /* 0x1F20-0x1F27 */ 
+0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F,   /* 0x1F28-0x1F2F */ 
+0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F,   /* 0x1F30-0x1F37 */ 
+0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F,   /* 0x1F38-0x1F3F */ 
+0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x1F46, 0x1F47,   /* 0x1F40-0x1F47 */ 
+0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x1F4E, 0x1F4F,   /* 0x1F48-0x1F4F */ 
+0x1F50, 0x1F59, 0x1F52, 0x1F5B, 0x1F54, 0x1F5D, 0x1F56, 0x1F5F,   /* 0x1F50-0x1F57 */ 
+0x1F58, 0x1F59, 0x1F5A, 0x1F5B, 0x1F5C, 0x1F5D, 0x1F5E, 0x1F5F,   /* 0x1F58-0x1F5F */ 
+0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F,   /* 0x1F60-0x1F67 */ 
+0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F,   /* 0x1F68-0x1F6F */ 
+0x1FBA, 0x1FBB, 0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FDA, 0x1FDB,   /* 0x1F70-0x1F77 */ 
+0x1FF8, 0x1FF9, 0x1FEA, 0x1FEB, 0x1FFA, 0x1FFB, 0x1F7E, 0x1F7F,   /* 0x1F78-0x1F7F */ 
+0x1F80, 0x1F81, 0x1F82, 0x1F83, 0x1F84, 0x1F85, 0x1F86, 0x1F87,   /* 0x1F80-0x1F87 */ 
+0x1F88, 0x1F89, 0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F,   /* 0x1F88-0x1F8F */ 
+0x1F90, 0x1F91, 0x1F92, 0x1F93, 0x1F94, 0x1F95, 0x1F96, 0x1F97,   /* 0x1F90-0x1F97 */ 
+0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F,   /* 0x1F98-0x1F9F */ 
+0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, 0x1FA6, 0x1FA7,   /* 0x1FA0-0x1FA7 */ 
+0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF,   /* 0x1FA8-0x1FAF */ 
+0x1FB8, 0x1FB9, 0x1FB2, 0x1FB3, 0x1FB4, 0x1FB5, 0x1FB6, 0x1FB7,   /* 0x1FB0-0x1FB7 */ 
+0x1FB8, 0x1FB9, 0x1FBA, 0x1FBB, 0x1FBC, 0x1FBD, 0x1FBE, 0x1FBF,   /* 0x1FB8-0x1FBF */ 
+0x1FC0, 0x1FC1, 0x1FC2, 0x1FC3, 0x1FC4, 0x1FC5, 0x1FC6, 0x1FC7,   /* 0x1FC0-0x1FC7 */ 
+0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FCC, 0x1FCD, 0x1FCE, 0x1FCF,   /* 0x1FC8-0x1FCF */ 
+0x1FD8, 0x1FD9, 0x1FD2, 0x1FD3, 0x1FD4, 0x1FD5, 0x1FD6, 0x1FD7,   /* 0x1FD0-0x1FD7 */ 
+0x1FD8, 0x1FD9, 0x1FDA, 0x1FDB, 0x1FDC, 0x1FDD, 0x1FDE, 0x1FDF,   /* 0x1FD8-0x1FDF */ 
+0x1FE8, 0x1FE9, 0x1FE2, 0x1FE3, 0x1FE4, 0x1FEC, 0x1FE6, 0x1FE7,   /* 0x1FE0-0x1FE7 */ 
+0x1FE8, 0x1FE9, 0x1FEA, 0x1FEB, 0x1FEC, 0x1FED, 0x1FEE, 0x1FEF,   /* 0x1FE8-0x1FEF */ 
+0x1FF0, 0x1FF1, 0x1FF2, 0x1FF3, 0x1FF4, 0x1FF5, 0x1FF6, 0x1FF7,   /* 0x1FF0-0x1FF7 */ 
+0x1FF8, 0x1FF9, 0x1FFA, 0x1FFB, 0x1FFC, 0x1FFD, 0x1FFE, 0x1FFF }; /* 0x1FF8-0x1FFF */
+
+static u_int16_t upcase_table_6[64] = {
+0x2140, 0x2141, 0x2142, 0x2143, 0x2144, 0x2145, 0x2146, 0x2147,   /* 0x2140-0x2147 */ 
+0x2148, 0x2149, 0x214A, 0x214B, 0x214C, 0x214D, 0x214E, 0x214F,   /* 0x2148-0x214F */ 
+0x2150, 0x2151, 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157,   /* 0x2150-0x2157 */ 
+0x2158, 0x2159, 0x215A, 0x215B, 0x215C, 0x215D, 0x215E, 0x215F,   /* 0x2158-0x215F */ 
+0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167,   /* 0x2160-0x2167 */ 
+0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F,   /* 0x2168-0x216F */ 
+0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167,   /* 0x2170-0x2177 */ 
+0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F }; /* 0x2178-0x217F */
+
+static u_int16_t upcase_table_7[64] = {
+0x24C0, 0x24C1, 0x24C2, 0x24C3, 0x24C4, 0x24C5, 0x24C6, 0x24C7,   /* 0x24C0-0x24C7 */ 
+0x24C8, 0x24C9, 0x24CA, 0x24CB, 0x24CC, 0x24CD, 0x24CE, 0x24CF,   /* 0x24C8-0x24CF */ 
+0x24B6, 0x24B7, 0x24B8, 0x24B9, 0x24BA, 0x24BB, 0x24BC, 0x24BD,   /* 0x24D0-0x24D7 */ 
+0x24BE, 0x24BF, 0x24C0, 0x24C1, 0x24C2, 0x24C3, 0x24C4, 0x24C5,   /* 0x24D8-0x24DF */ 
+0x24C6, 0x24C7, 0x24C8, 0x24C9, 0x24CA, 0x24CB, 0x24CC, 0x24CD,   /* 0x24E0-0x24E7 */ 
+0x24CE, 0x24CF, 0x24EA, 0x24EB, 0x24EC, 0x24ED, 0x24EE, 0x24EF,   /* 0x24E8-0x24EF */ 
+0x24F0, 0x24F1, 0x24F2, 0x24F3, 0x24F4, 0x24F5, 0x24F6, 0x24F7,   /* 0x24F0-0x24F7 */ 
+0x24F8, 0x24F9, 0x24FA, 0x24FB, 0x24FC, 0x24FD, 0x24FE, 0x24FF }; /* 0x24F8-0x24FF */
+
+static u_int16_t upcase_table_8[64] = {
+0xFF40, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27,   /* 0xFF40-0xFF47 */ 
+0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F,   /* 0xFF48-0xFF4F */ 
+0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37,   /* 0xFF50-0xFF57 */ 
+0xFF38, 0xFF39, 0xFF3A, 0xFF5B, 0xFF5C, 0xFF5D, 0xFF5E, 0xFF5F,   /* 0xFF58-0xFF5F */ 
+0xFF60, 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67,   /* 0xFF60-0xFF67 */ 
+0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F,   /* 0xFF68-0xFF6F */ 
+0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77,   /* 0xFF70-0xFF77 */ 
+0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F }; /* 0xFF78-0xFF7F */
+
+
+
+static u_int16_t lowcase_table_1[64] = {
+0x0040, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,   /* 0x0040-0x0047 */ 
+0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,   /* 0x0048-0x004F */ 
+0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,   /* 0x0050-0x0057 */ 
+0x0078, 0x0079, 0x007A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,   /* 0x0058-0x005F */ 
+0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,   /* 0x0060-0x0067 */ 
+0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,   /* 0x0068-0x006F */ 
+0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,   /* 0x0070-0x0077 */ 
+0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F }; /* 0x0078-0x007F */
+
+static u_int16_t lowcase_table_2[384] = {
+0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,   /* 0x00C0-0x00C7 */ 
+0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,   /* 0x00C8-0x00CF */ 
+0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00D7,   /* 0x00D0-0x00D7 */ 
+0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00DF,   /* 0x00D8-0x00DF */ 
+0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,   /* 0x00E0-0x00E7 */ 
+0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,   /* 0x00E8-0x00EF */ 
+0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,   /* 0x00F0-0x00F7 */ 
+0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF,   /* 0x00F8-0x00FF */ 
+0x0101, 0x0101, 0x0103, 0x0103, 0x0105, 0x0105, 0x0107, 0x0107,   /* 0x0100-0x0107 */ 
+0x0109, 0x0109, 0x010B, 0x010B, 0x010D, 0x010D, 0x010F, 0x010F,   /* 0x0108-0x010F */ 
+0x0111, 0x0111, 0x0113, 0x0113, 0x0115, 0x0115, 0x0117, 0x0117,   /* 0x0110-0x0117 */ 
+0x0119, 0x0119, 0x011B, 0x011B, 0x011D, 0x011D, 0x011F, 0x011F,   /* 0x0118-0x011F */ 
+0x0121, 0x0121, 0x0123, 0x0123, 0x0125, 0x0125, 0x0127, 0x0127,   /* 0x0120-0x0127 */ 
+0x0129, 0x0129, 0x012B, 0x012B, 0x012D, 0x012D, 0x012F, 0x012F,   /* 0x0128-0x012F */ 
+0x0130, 0x0131, 0x0133, 0x0133, 0x0135, 0x0135, 0x0137, 0x0137,   /* 0x0130-0x0137 */ 
+0x0138, 0x013A, 0x013A, 0x013C, 0x013C, 0x013E, 0x013E, 0x0140,   /* 0x0138-0x013F */ 
+0x0140, 0x0142, 0x0142, 0x0144, 0x0144, 0x0146, 0x0146, 0x0148,   /* 0x0140-0x0147 */ 
+0x0148, 0x0149, 0x014B, 0x014B, 0x014D, 0x014D, 0x014F, 0x014F,   /* 0x0148-0x014F */ 
+0x0151, 0x0151, 0x0153, 0x0153, 0x0155, 0x0155, 0x0157, 0x0157,   /* 0x0150-0x0157 */ 
+0x0159, 0x0159, 0x015B, 0x015B, 0x015D, 0x015D, 0x015F, 0x015F,   /* 0x0158-0x015F */ 
+0x0161, 0x0161, 0x0163, 0x0163, 0x0165, 0x0165, 0x0167, 0x0167,   /* 0x0160-0x0167 */ 
+0x0169, 0x0169, 0x016B, 0x016B, 0x016D, 0x016D, 0x016F, 0x016F,   /* 0x0168-0x016F */ 
+0x0171, 0x0171, 0x0173, 0x0173, 0x0175, 0x0175, 0x0177, 0x0177,   /* 0x0170-0x0177 */ 
+0x00FF, 0x017A, 0x017A, 0x017C, 0x017C, 0x017E, 0x017E, 0x017F,   /* 0x0178-0x017F */ 
+0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188,   /* 0x0180-0x0187 */ 
+0x0188, 0x0256, 0x0257, 0x018C, 0x018C, 0x018D, 0x01DD, 0x0259,   /* 0x0188-0x018F */ 
+0x025B, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268,   /* 0x0190-0x0197 */ 
+0x0199, 0x0199, 0x019A, 0x019B, 0x026F, 0x0272, 0x019E, 0x0275,   /* 0x0198-0x019F */ 
+0x01A1, 0x01A1, 0x01A3, 0x01A3, 0x01A5, 0x01A5, 0x01A6, 0x01A8,   /* 0x01A0-0x01A7 */ 
+0x01A8, 0x0283, 0x01AA, 0x01AB, 0x01AD, 0x01AD, 0x0288, 0x01B0,   /* 0x01A8-0x01AF */ 
+0x01B0, 0x028A, 0x028B, 0x01B4, 0x01B4, 0x01B6, 0x01B6, 0x0292,   /* 0x01B0-0x01B7 */ 
+0x01B9, 0x01B9, 0x01BA, 0x01BB, 0x01BD, 0x01BD, 0x01BE, 0x01BF,   /* 0x01B8-0x01BF */ 
+0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C6, 0x01C5, 0x01C6, 0x01C9,   /* 0x01C0-0x01C7 */ 
+0x01C8, 0x01C9, 0x01CC, 0x01CB, 0x01CC, 0x01CE, 0x01CE, 0x01D0,   /* 0x01C8-0x01CF */ 
+0x01D0, 0x01D2, 0x01D2, 0x01D4, 0x01D4, 0x01D6, 0x01D6, 0x01D8,   /* 0x01D0-0x01D7 */ 
+0x01D8, 0x01DA, 0x01DA, 0x01DC, 0x01DC, 0x01DD, 0x01DF, 0x01DF,   /* 0x01D8-0x01DF */ 
+0x01E1, 0x01E1, 0x01E3, 0x01E3, 0x01E5, 0x01E5, 0x01E7, 0x01E7,   /* 0x01E0-0x01E7 */ 
+0x01E9, 0x01E9, 0x01EB, 0x01EB, 0x01ED, 0x01ED, 0x01EF, 0x01EF,   /* 0x01E8-0x01EF */ 
+0x01F0, 0x01F3, 0x01F2, 0x01F3, 0x01F5, 0x01F5, 0x01F6, 0x01F7,   /* 0x01F0-0x01F7 */ 
+0x01F8, 0x01F9, 0x01FB, 0x01FB, 0x01FD, 0x01FD, 0x01FF, 0x01FF,   /* 0x01F8-0x01FF */ 
+0x0201, 0x0201, 0x0203, 0x0203, 0x0205, 0x0205, 0x0207, 0x0207,   /* 0x0200-0x0207 */ 
+0x0209, 0x0209, 0x020B, 0x020B, 0x020D, 0x020D, 0x020F, 0x020F,   /* 0x0208-0x020F */ 
+0x0211, 0x0211, 0x0213, 0x0213, 0x0215, 0x0215, 0x0217, 0x0217,   /* 0x0210-0x0217 */ 
+0x0218, 0x0219, 0x021A, 0x021B, 0x021C, 0x021D, 0x021E, 0x021F,   /* 0x0218-0x021F */ 
+0x0220, 0x0221, 0x0222, 0x0223, 0x0224, 0x0225, 0x0226, 0x0227,   /* 0x0220-0x0227 */ 
+0x0228, 0x0229, 0x022A, 0x022B, 0x022C, 0x022D, 0x022E, 0x022F,   /* 0x0228-0x022F */ 
+0x0230, 0x0231, 0x0232, 0x0233, 0x0234, 0x0235, 0x0236, 0x0237,   /* 0x0230-0x0237 */ 
+0x0238, 0x0239, 0x023A, 0x023B, 0x023C, 0x023D, 0x023E, 0x023F }; /* 0x0238-0x023F */
+
+static u_int16_t lowcase_table_3[512] = {
+0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x03AC, 0x0387,   /* 0x0380-0x0387 */ 
+0x03AD, 0x03AE, 0x03AF, 0x038B, 0x03CC, 0x038D, 0x03CD, 0x03CE,   /* 0x0388-0x038F */ 
+0x0390, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,   /* 0x0390-0x0397 */ 
+0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,   /* 0x0398-0x039F */ 
+0x03C0, 0x03C1, 0x03A2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,   /* 0x03A0-0x03A7 */ 
+0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,   /* 0x03A8-0x03AF */ 
+0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,   /* 0x03B0-0x03B7 */ 
+0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,   /* 0x03B8-0x03BF */ 
+0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,   /* 0x03C0-0x03C7 */ 
+0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x03CF,   /* 0x03C8-0x03CF */ 
+0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7,   /* 0x03D0-0x03D7 */ 
+0x03D8, 0x03D9, 0x03DA, 0x03DB, 0x03DC, 0x03DD, 0x03DE, 0x03DF,   /* 0x03D8-0x03DF */ 
+0x03E0, 0x03E1, 0x03E3, 0x03E3, 0x03E5, 0x03E5, 0x03E7, 0x03E7,   /* 0x03E0-0x03E7 */ 
+0x03E9, 0x03E9, 0x03EB, 0x03EB, 0x03ED, 0x03ED, 0x03EF, 0x03EF,   /* 0x03E8-0x03EF */ 
+0x03F0, 0x03F1, 0x03F2, 0x03F3, 0x03F4, 0x03F5, 0x03F6, 0x03F7,   /* 0x03F0-0x03F7 */ 
+0x03F8, 0x03F9, 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF,   /* 0x03F8-0x03FF */ 
+0x0400, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,   /* 0x0400-0x0407 */ 
+0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x040D, 0x045E, 0x045F,   /* 0x0408-0x040F */ 
+0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,   /* 0x0410-0x0417 */ 
+0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,   /* 0x0418-0x041F */ 
+0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,   /* 0x0420-0x0427 */ 
+0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,   /* 0x0428-0x042F */ 
+0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,   /* 0x0430-0x0437 */ 
+0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,   /* 0x0438-0x043F */ 
+0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,   /* 0x0440-0x0447 */ 
+0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,   /* 0x0448-0x044F */ 
+0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,   /* 0x0450-0x0457 */ 
+0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x045D, 0x045E, 0x045F,   /* 0x0458-0x045F */ 
+0x0461, 0x0461, 0x0463, 0x0463, 0x0465, 0x0465, 0x0467, 0x0467,   /* 0x0460-0x0467 */ 
+0x0469, 0x0469, 0x046B, 0x046B, 0x046D, 0x046D, 0x046F, 0x046F,   /* 0x0468-0x046F */ 
+0x0471, 0x0471, 0x0473, 0x0473, 0x0475, 0x0475, 0x0477, 0x0477,   /* 0x0470-0x0477 */ 
+0x0479, 0x0479, 0x047B, 0x047B, 0x047D, 0x047D, 0x047F, 0x047F,   /* 0x0478-0x047F */ 
+0x0481, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487,   /* 0x0480-0x0487 */ 
+0x0488, 0x0489, 0x048A, 0x048B, 0x048C, 0x048D, 0x048E, 0x048F,   /* 0x0488-0x048F */ 
+0x0491, 0x0491, 0x0493, 0x0493, 0x0495, 0x0495, 0x0497, 0x0497,   /* 0x0490-0x0497 */ 
+0x0499, 0x0499, 0x049B, 0x049B, 0x049D, 0x049D, 0x049F, 0x049F,   /* 0x0498-0x049F */ 
+0x04A1, 0x04A1, 0x04A3, 0x04A3, 0x04A5, 0x04A5, 0x04A7, 0x04A7,   /* 0x04A0-0x04A7 */ 
+0x04A9, 0x04A9, 0x04AB, 0x04AB, 0x04AD, 0x04AD, 0x04AF, 0x04AF,   /* 0x04A8-0x04AF */ 
+0x04B1, 0x04B1, 0x04B3, 0x04B3, 0x04B5, 0x04B5, 0x04B7, 0x04B7,   /* 0x04B0-0x04B7 */ 
+0x04B9, 0x04B9, 0x04BB, 0x04BB, 0x04BD, 0x04BD, 0x04BF, 0x04BF,   /* 0x04B8-0x04BF */ 
+0x04C0, 0x04C2, 0x04C2, 0x04C4, 0x04C4, 0x04C5, 0x04C6, 0x04C8,   /* 0x04C0-0x04C7 */ 
+0x04C8, 0x04C9, 0x04CA, 0x04CC, 0x04CC, 0x04CD, 0x04CE, 0x04CF,   /* 0x04C8-0x04CF */ 
+0x04D1, 0x04D1, 0x04D3, 0x04D3, 0x04D5, 0x04D5, 0x04D7, 0x04D7,   /* 0x04D0-0x04D7 */ 
+0x04D9, 0x04D9, 0x04DB, 0x04DB, 0x04DD, 0x04DD, 0x04DF, 0x04DF,   /* 0x04D8-0x04DF */ 
+0x04E1, 0x04E1, 0x04E3, 0x04E3, 0x04E5, 0x04E5, 0x04E7, 0x04E7,   /* 0x04E0-0x04E7 */ 
+0x04E9, 0x04E9, 0x04EB, 0x04EB, 0x04EC, 0x04ED, 0x04EF, 0x04EF,   /* 0x04E8-0x04EF */ 
+0x04F1, 0x04F1, 0x04F3, 0x04F3, 0x04F5, 0x04F5, 0x04F6, 0x04F7,   /* 0x04F0-0x04F7 */ 
+0x04F9, 0x04F9, 0x04FA, 0x04FB, 0x04FC, 0x04FD, 0x04FE, 0x04FF,   /* 0x04F8-0x04FF */ 
+0x0500, 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, 0x0507,   /* 0x0500-0x0507 */ 
+0x0508, 0x0509, 0x050A, 0x050B, 0x050C, 0x050D, 0x050E, 0x050F,   /* 0x0508-0x050F */ 
+0x0510, 0x0511, 0x0512, 0x0513, 0x0514, 0x0515, 0x0516, 0x0517,   /* 0x0510-0x0517 */ 
+0x0518, 0x0519, 0x051A, 0x051B, 0x051C, 0x051D, 0x051E, 0x051F,   /* 0x0518-0x051F */ 
+0x0520, 0x0521, 0x0522, 0x0523, 0x0524, 0x0525, 0x0526, 0x0527,   /* 0x0520-0x0527 */ 
+0x0528, 0x0529, 0x052A, 0x052B, 0x052C, 0x052D, 0x052E, 0x052F,   /* 0x0528-0x052F */ 
+0x0530, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567,   /* 0x0530-0x0537 */ 
+0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F,   /* 0x0538-0x053F */ 
+0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577,   /* 0x0540-0x0547 */ 
+0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F,   /* 0x0548-0x054F */ 
+0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0557,   /* 0x0550-0x0557 */ 
+0x0558, 0x0559, 0x055A, 0x055B, 0x055C, 0x055D, 0x055E, 0x055F,   /* 0x0558-0x055F */ 
+0x0560, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567,   /* 0x0560-0x0567 */ 
+0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F,   /* 0x0568-0x056F */ 
+0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577,   /* 0x0570-0x0577 */ 
+0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F }; /* 0x0578-0x057F */
+
+static u_int16_t lowcase_table_4[512] = {
+0x1E01, 0x1E01, 0x1E03, 0x1E03, 0x1E05, 0x1E05, 0x1E07, 0x1E07,   /* 0x1E00-0x1E07 */ 
+0x1E09, 0x1E09, 0x1E0B, 0x1E0B, 0x1E0D, 0x1E0D, 0x1E0F, 0x1E0F,   /* 0x1E08-0x1E0F */ 
+0x1E11, 0x1E11, 0x1E13, 0x1E13, 0x1E15, 0x1E15, 0x1E17, 0x1E17,   /* 0x1E10-0x1E17 */ 
+0x1E19, 0x1E19, 0x1E1B, 0x1E1B, 0x1E1D, 0x1E1D, 0x1E1F, 0x1E1F,   /* 0x1E18-0x1E1F */ 
+0x1E21, 0x1E21, 0x1E23, 0x1E23, 0x1E25, 0x1E25, 0x1E27, 0x1E27,   /* 0x1E20-0x1E27 */ 
+0x1E29, 0x1E29, 0x1E2B, 0x1E2B, 0x1E2D, 0x1E2D, 0x1E2F, 0x1E2F,   /* 0x1E28-0x1E2F */ 
+0x1E31, 0x1E31, 0x1E33, 0x1E33, 0x1E35, 0x1E35, 0x1E37, 0x1E37,   /* 0x1E30-0x1E37 */ 
+0x1E39, 0x1E39, 0x1E3B, 0x1E3B, 0x1E3D, 0x1E3D, 0x1E3F, 0x1E3F,   /* 0x1E38-0x1E3F */ 
+0x1E41, 0x1E41, 0x1E43, 0x1E43, 0x1E45, 0x1E45, 0x1E47, 0x1E47,   /* 0x1E40-0x1E47 */ 
+0x1E49, 0x1E49, 0x1E4B, 0x1E4B, 0x1E4D, 0x1E4D, 0x1E4F, 0x1E4F,   /* 0x1E48-0x1E4F */ 
+0x1E51, 0x1E51, 0x1E53, 0x1E53, 0x1E55, 0x1E55, 0x1E57, 0x1E57,   /* 0x1E50-0x1E57 */ 
+0x1E59, 0x1E59, 0x1E5B, 0x1E5B, 0x1E5D, 0x1E5D, 0x1E5F, 0x1E5F,   /* 0x1E58-0x1E5F */ 
+0x1E61, 0x1E61, 0x1E63, 0x1E63, 0x1E65, 0x1E65, 0x1E67, 0x1E67,   /* 0x1E60-0x1E67 */ 
+0x1E69, 0x1E69, 0x1E6B, 0x1E6B, 0x1E6D, 0x1E6D, 0x1E6F, 0x1E6F,   /* 0x1E68-0x1E6F */ 
+0x1E71, 0x1E71, 0x1E73, 0x1E73, 0x1E75, 0x1E75, 0x1E77, 0x1E77,   /* 0x1E70-0x1E77 */ 
+0x1E79, 0x1E79, 0x1E7B, 0x1E7B, 0x1E7D, 0x1E7D, 0x1E7F, 0x1E7F,   /* 0x1E78-0x1E7F */ 
+0x1E81, 0x1E81, 0x1E83, 0x1E83, 0x1E85, 0x1E85, 0x1E87, 0x1E87,   /* 0x1E80-0x1E87 */ 
+0x1E89, 0x1E89, 0x1E8B, 0x1E8B, 0x1E8D, 0x1E8D, 0x1E8F, 0x1E8F,   /* 0x1E88-0x1E8F */ 
+0x1E91, 0x1E91, 0x1E93, 0x1E93, 0x1E95, 0x1E95, 0x1E96, 0x1E97,   /* 0x1E90-0x1E97 */ 
+0x1E98, 0x1E99, 0x1E9A, 0x1E9B, 0x1E9C, 0x1E9D, 0x1E9E, 0x1E9F,   /* 0x1E98-0x1E9F */ 
+0x1EA1, 0x1EA1, 0x1EA3, 0x1EA3, 0x1EA5, 0x1EA5, 0x1EA7, 0x1EA7,   /* 0x1EA0-0x1EA7 */ 
+0x1EA9, 0x1EA9, 0x1EAB, 0x1EAB, 0x1EAD, 0x1EAD, 0x1EAF, 0x1EAF,   /* 0x1EA8-0x1EAF */ 
+0x1EB1, 0x1EB1, 0x1EB3, 0x1EB3, 0x1EB5, 0x1EB5, 0x1EB7, 0x1EB7,   /* 0x1EB0-0x1EB7 */ 
+0x1EB9, 0x1EB9, 0x1EBB, 0x1EBB, 0x1EBD, 0x1EBD, 0x1EBF, 0x1EBF,   /* 0x1EB8-0x1EBF */ 
+0x1EC1, 0x1EC1, 0x1EC3, 0x1EC3, 0x1EC5, 0x1EC5, 0x1EC7, 0x1EC7,   /* 0x1EC0-0x1EC7 */ 
+0x1EC9, 0x1EC9, 0x1ECB, 0x1ECB, 0x1ECD, 0x1ECD, 0x1ECF, 0x1ECF,   /* 0x1EC8-0x1ECF */ 
+0x1ED1, 0x1ED1, 0x1ED3, 0x1ED3, 0x1ED5, 0x1ED5, 0x1ED7, 0x1ED7,   /* 0x1ED0-0x1ED7 */ 
+0x1ED9, 0x1ED9, 0x1EDB, 0x1EDB, 0x1EDD, 0x1EDD, 0x1EDF, 0x1EDF,   /* 0x1ED8-0x1EDF */ 
+0x1EE1, 0x1EE1, 0x1EE3, 0x1EE3, 0x1EE5, 0x1EE5, 0x1EE7, 0x1EE7,   /* 0x1EE0-0x1EE7 */ 
+0x1EE9, 0x1EE9, 0x1EEB, 0x1EEB, 0x1EED, 0x1EED, 0x1EEF, 0x1EEF,   /* 0x1EE8-0x1EEF */ 
+0x1EF1, 0x1EF1, 0x1EF3, 0x1EF3, 0x1EF5, 0x1EF5, 0x1EF7, 0x1EF7,   /* 0x1EF0-0x1EF7 */ 
+0x1EF9, 0x1EF9, 0x1EFA, 0x1EFB, 0x1EFC, 0x1EFD, 0x1EFE, 0x1EFF,   /* 0x1EF8-0x1EFF */ 
+0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07,   /* 0x1F00-0x1F07 */ 
+0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07,   /* 0x1F08-0x1F0F */ 
+0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x1F16, 0x1F17,   /* 0x1F10-0x1F17 */ 
+0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x1F1E, 0x1F1F,   /* 0x1F18-0x1F1F */ 
+0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27,   /* 0x1F20-0x1F27 */ 
+0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27,   /* 0x1F28-0x1F2F */ 
+0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37,   /* 0x1F30-0x1F37 */ 
+0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37,   /* 0x1F38-0x1F3F */ 
+0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x1F46, 0x1F47,   /* 0x1F40-0x1F47 */ 
+0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x1F4E, 0x1F4F,   /* 0x1F48-0x1F4F */ 
+0x1F50, 0x1F51, 0x1F52, 0x1F53, 0x1F54, 0x1F55, 0x1F56, 0x1F57,   /* 0x1F50-0x1F57 */ 
+0x1F58, 0x1F51, 0x1F5A, 0x1F53, 0x1F5C, 0x1F55, 0x1F5E, 0x1F57,   /* 0x1F58-0x1F5F */ 
+0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67,   /* 0x1F60-0x1F67 */ 
+0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67,   /* 0x1F68-0x1F6F */ 
+0x1F70, 0x1F71, 0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1F76, 0x1F77,   /* 0x1F70-0x1F77 */ 
+0x1F78, 0x1F79, 0x1F7A, 0x1F7B, 0x1F7C, 0x1F7D, 0x1F7E, 0x1F7F,   /* 0x1F78-0x1F7F */ 
+0x1F80, 0x1F81, 0x1F82, 0x1F83, 0x1F84, 0x1F85, 0x1F86, 0x1F87,   /* 0x1F80-0x1F87 */ 
+0x1F88, 0x1F89, 0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F,   /* 0x1F88-0x1F8F */ 
+0x1F90, 0x1F91, 0x1F92, 0x1F93, 0x1F94, 0x1F95, 0x1F96, 0x1F97,   /* 0x1F90-0x1F97 */ 
+0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F,   /* 0x1F98-0x1F9F */ 
+0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, 0x1FA6, 0x1FA7,   /* 0x1FA0-0x1FA7 */ 
+0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF,   /* 0x1FA8-0x1FAF */ 
+0x1FB0, 0x1FB1, 0x1FB2, 0x1FB3, 0x1FB4, 0x1FB5, 0x1FB6, 0x1FB7,   /* 0x1FB0-0x1FB7 */ 
+0x1FB0, 0x1FB1, 0x1F70, 0x1F71, 0x1FBC, 0x1FBD, 0x1FBE, 0x1FBF,   /* 0x1FB8-0x1FBF */ 
+0x1FC0, 0x1FC1, 0x1FC2, 0x1FC3, 0x1FC4, 0x1FC5, 0x1FC6, 0x1FC7,   /* 0x1FC0-0x1FC7 */ 
+0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1FCC, 0x1FCD, 0x1FCE, 0x1FCF,   /* 0x1FC8-0x1FCF */ 
+0x1FD0, 0x1FD1, 0x1FD2, 0x1FD3, 0x1FD4, 0x1FD5, 0x1FD6, 0x1FD7,   /* 0x1FD0-0x1FD7 */ 
+0x1FD0, 0x1FD1, 0x1F76, 0x1F77, 0x1FDC, 0x1FDD, 0x1FDE, 0x1FDF,   /* 0x1FD8-0x1FDF */ 
+0x1FE0, 0x1FE1, 0x1FE2, 0x1FE3, 0x1FE4, 0x1FE5, 0x1FE6, 0x1FE7,   /* 0x1FE0-0x1FE7 */ 
+0x1FE0, 0x1FE1, 0x1F7A, 0x1F7B, 0x1FE5, 0x1FED, 0x1FEE, 0x1FEF,   /* 0x1FE8-0x1FEF */ 
+0x1FF0, 0x1FF1, 0x1FF2, 0x1FF3, 0x1FF4, 0x1FF5, 0x1FF6, 0x1FF7,   /* 0x1FF0-0x1FF7 */ 
+0x1F78, 0x1F79, 0x1F7C, 0x1F7D, 0x1FFC, 0x1FFD, 0x1FFE, 0x1FFF }; /* 0x1FF8-0x1FFF */
+
+static u_int16_t lowcase_table_5[64] = {
+0x2140, 0x2141, 0x2142, 0x2143, 0x2144, 0x2145, 0x2146, 0x2147,   /* 0x2140-0x2147 */ 
+0x2148, 0x2149, 0x214A, 0x214B, 0x214C, 0x214D, 0x214E, 0x214F,   /* 0x2148-0x214F */ 
+0x2150, 0x2151, 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157,   /* 0x2150-0x2157 */ 
+0x2158, 0x2159, 0x215A, 0x215B, 0x215C, 0x215D, 0x215E, 0x215F,   /* 0x2158-0x215F */ 
+0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177,   /* 0x2160-0x2167 */ 
+0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F,   /* 0x2168-0x216F */ 
+0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177,   /* 0x2170-0x2177 */ 
+0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F }; /* 0x2178-0x217F */
+
+static u_int16_t lowcase_table_6[128] = {
+0x2480, 0x2481, 0x2482, 0x2483, 0x2484, 0x2485, 0x2486, 0x2487,   /* 0x2480-0x2487 */ 
+0x2488, 0x2489, 0x248A, 0x248B, 0x248C, 0x248D, 0x248E, 0x248F,   /* 0x2488-0x248F */ 
+0x2490, 0x2491, 0x2492, 0x2493, 0x2494, 0x2495, 0x2496, 0x2497,   /* 0x2490-0x2497 */ 
+0x2498, 0x2499, 0x249A, 0x249B, 0x249C, 0x249D, 0x249E, 0x249F,   /* 0x2498-0x249F */ 
+0x24A0, 0x24A1, 0x24A2, 0x24A3, 0x24A4, 0x24A5, 0x24A6, 0x24A7,   /* 0x24A0-0x24A7 */ 
+0x24A8, 0x24A9, 0x24AA, 0x24AB, 0x24AC, 0x24AD, 0x24AE, 0x24AF,   /* 0x24A8-0x24AF */ 
+0x24B0, 0x24B1, 0x24B2, 0x24B3, 0x24B4, 0x24B5, 0x24D0, 0x24D1,   /* 0x24B0-0x24B7 */ 
+0x24D2, 0x24D3, 0x24D4, 0x24D5, 0x24D6, 0x24D7, 0x24D8, 0x24D9,   /* 0x24B8-0x24BF */ 
+0x24DA, 0x24DB, 0x24DC, 0x24DD, 0x24DE, 0x24DF, 0x24E0, 0x24E1,   /* 0x24C0-0x24C7 */ 
+0x24E2, 0x24E3, 0x24E4, 0x24E5, 0x24E6, 0x24E7, 0x24E8, 0x24E9,   /* 0x24C8-0x24CF */ 
+0x24D0, 0x24D1, 0x24D2, 0x24D3, 0x24D4, 0x24D5, 0x24D6, 0x24D7,   /* 0x24D0-0x24D7 */ 
+0x24D8, 0x24D9, 0x24DA, 0x24DB, 0x24DC, 0x24DD, 0x24DE, 0x24DF,   /* 0x24D8-0x24DF */ 
+0x24E0, 0x24E1, 0x24E2, 0x24E3, 0x24E4, 0x24E5, 0x24E6, 0x24E7,   /* 0x24E0-0x24E7 */ 
+0x24E8, 0x24E9, 0x24EA, 0x24EB, 0x24EC, 0x24ED, 0x24EE, 0x24EF,   /* 0x24E8-0x24EF */ 
+0x24F0, 0x24F1, 0x24F2, 0x24F3, 0x24F4, 0x24F5, 0x24F6, 0x24F7,   /* 0x24F0-0x24F7 */ 
+0x24F8, 0x24F9, 0x24FA, 0x24FB, 0x24FC, 0x24FD, 0x24FE, 0x24FF }; /* 0x24F8-0x24FF */
+
+static u_int16_t lowcase_table_7[64] = {
+0xFF00, 0xFF01, 0xFF02, 0xFF03, 0xFF04, 0xFF05, 0xFF06, 0xFF07,   /* 0xFF00-0xFF07 */ 
+0xFF08, 0xFF09, 0xFF0A, 0xFF0B, 0xFF0C, 0xFF0D, 0xFF0E, 0xFF0F,   /* 0xFF08-0xFF0F */ 
+0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17,   /* 0xFF10-0xFF17 */ 
+0xFF18, 0xFF19, 0xFF1A, 0xFF1B, 0xFF1C, 0xFF1D, 0xFF1E, 0xFF1F,   /* 0xFF18-0xFF1F */ 
+0xFF20, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47,   /* 0xFF20-0xFF27 */ 
+0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F,   /* 0xFF28-0xFF2F */ 
+0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57,   /* 0xFF30-0xFF37 */ 
+0xFF58, 0xFF59, 0xFF5A, 0xFF3B, 0xFF3C, 0xFF3D, 0xFF3E, 0xFF3F }; /* 0xFF38-0xFF3F */
+
diff --git a/libatalk/unicode/unicode.h b/libatalk/unicode/unicode.h
new file mode 100644 (file)
index 0000000..5691dff
--- /dev/null
@@ -0,0 +1,47 @@
+
+
+
+
+#define ucs2_t u_int16_t
+
+/* generic iconv conversion structure */
+typedef struct {
+        size_t (*direct)(void *cd, char **inbuf, size_t *inbytesleft,
+                         char **outbuf, size_t *outbytesleft);
+        size_t (*pull)(void *cd, char **inbuf, size_t *inbytesleft,
+                       char **outbuf, size_t *outbytesleft);
+        size_t (*push)(void *cd, char **inbuf, size_t *inbytesleft,
+                       char **outbuf, size_t *outbytesleft);
+        void *cd_direct, *cd_pull, *cd_push;
+        char *from_name, *to_name;
+} *atalk_iconv_t;
+
+
+/* this defines the charset types used in samba */
+typedef enum {CH_UCS2=0, CH_UNIX=1, CH_DISPLAY=2, CH_DOS=3, CH_UTF8=4} charset_t;
+
+#define NUM_CHARSETS 5
+
+/*
+ *   for each charset we have a function that pulls from that charset to
+ *     a ucs2 buffer, and a function that pushes to a ucs2 buffer
+ *     */
+
+struct charset_functions {
+        const char *name;
+        size_t (*pull)(void *, char **inbuf, size_t *inbytesleft,
+                                   char **outbuf, size_t *outbytesleft);
+        size_t (*push)(void *, char **inbuf, size_t *inbytesleft,
+                                   char **outbuf, size_t *outbytesleft);
+        struct charset_functions *prev, *next;
+};
+
+
+extern size_t atalk_iconv(atalk_iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);
+atalk_iconv_t atalk_iconv_open(const char *tocode, const char *fromcode);
+int atalk_iconv_close (atalk_iconv_t cd);
+
+ucs2_t toupper_w(ucs2_t val);
+ucs2_t tolower_w(ucs2_t val);
+
+
diff --git a/libatalk/unicode/util_unistr.c b/libatalk/unicode/util_unistr.c
new file mode 100644 (file)
index 0000000..8edaef3
--- /dev/null
@@ -0,0 +1,530 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <atalk/logger.h>
+#include <errno.h>
+
+#include <netatalk/endian.h>
+
+#include <atalk/unicode.h>
+#include "ucs2_casetable.h"
+#include "precompose.h"
+
+
+
+#define ucs2_t u_int16_t
+
+
+ucs2_t toupper_w(ucs2_t val)
+{
+       if ( val >= 0x0040 && val <= 0x007F)
+               return upcase_table_1[val-0x0040];
+       if ( val >= 0x00C0 && val <= 0x02BF)
+               return upcase_table_2[val-0x00C0];
+       if ( val >= 0x0380 && val <= 0x04FF)
+               return upcase_table_3[val-0x0380];
+       if ( val >= 0x0540 && val <= 0x05BF)
+               return upcase_table_4[val-0x0540];
+       if ( val >= 0x1E00 && val <= 0x1FFF)
+               return upcase_table_5[val-0x1E00];
+       if ( val >= 0x2140 && val <= 0x217F)
+               return upcase_table_6[val-0x2140];
+       if ( val >= 0x24C0 && val <= 0x24FF)
+               return upcase_table_7[val-0x24C0];
+       if ( val >= 0xFF40 && val <= 0xFF7F)
+               return upcase_table_8[val-0xFF40];
+
+       return (val);
+}
+
+
+ucs2_t tolower_w(ucs2_t val)
+{
+       if ( val >= 0x0040 && val <= 0x007F)
+               return lowcase_table_1[val-0x0040];
+       if ( val >= 0x00C0 && val <= 0x023F)
+               return lowcase_table_2[val-0x00C0];
+       if ( val >= 0x0380 && val <= 0x057F)
+               return lowcase_table_3[val-0x0380];
+       if ( val >= 0x1E00 && val <= 0x1FFF)
+               return lowcase_table_4[val-0x1E00];
+       if ( val >= 0x2140 && val <= 0x217F)
+               return lowcase_table_5[val-0x2140];
+       if ( val >= 0x2480 && val <= 0x24FF)
+               return lowcase_table_6[val-0x2480];
+       if ( val >= 0xFF00 && val <= 0xFF3F)
+               return lowcase_table_7[val-0xFF00];
+
+       return (val);
+}
+
+/*******************************************************************
+ Convert a string to lower case.
+ return True if any char is converted
+********************************************************************/
+int strlower_w(ucs2_t *s)
+{
+        int ret = 0;
+        while (*s) {
+                ucs2_t v = tolower_w(*s);
+                if (v != *s) {
+                        *s = v;
+                        ret = 1;
+                }
+                s++;
+        }
+        return ret;
+}
+
+/*******************************************************************
+ Convert a string to upper case.
+ return True if any char is converted
+********************************************************************/
+int strupper_w(ucs2_t *s)
+{
+        int ret = 0;
+        while (*s) {
+                ucs2_t v = toupper_w(*s);
+                if (v != *s) {
+                        *s = v;
+                        ret = 1;
+                }
+                s++;
+        }
+        return ret;
+}
+
+
+/*******************************************************************
+determine if a character is lowercase
+********************************************************************/
+int islower_w(ucs2_t c)
+{
+       return ( c == tolower_w(c));
+}
+
+/*******************************************************************
+determine if a character is uppercase
+********************************************************************/
+int isupper_w(ucs2_t c)
+{
+       return ( c == toupper_w(c));
+}
+
+
+/*******************************************************************
+ Count the number of characters in a ucs2_t string.
+********************************************************************/
+size_t strlen_w(const ucs2_t *src)
+{
+       size_t len;
+
+       for(len = 0; *src++; len++) ;
+
+       return len;
+}
+
+/*******************************************************************
+ Count up to max number of characters in a ucs2_t string.
+********************************************************************/
+size_t strnlen_w(const ucs2_t *src, size_t max)
+{
+       size_t len;
+
+       for(len = 0; *src++ && (len < max); len++) ;
+
+       return len;
+}
+
+/*******************************************************************
+wide strchr()
+********************************************************************/
+ucs2_t *strchr_w(const ucs2_t *s, ucs2_t c)
+{
+       while (*s != 0) {
+               if (c == *s) return (ucs2_t *)s;
+               s++;
+       }
+       if (c == *s) return (ucs2_t *)s;
+
+       return NULL;
+}
+
+ucs2_t *strcasechr_w(const ucs2_t *s, ucs2_t c)
+{
+       while (*s != 0) {
+               if (toupper_w(c) == toupper_w(*s)) return (ucs2_t *)s;
+               s++;
+       }
+       if (c == *s) return (ucs2_t *)s;
+
+       return NULL;
+}
+
+
+int strcmp_w(const ucs2_t *a, const ucs2_t *b)
+{
+        while (*b && *a == *b) { a++; b++; }
+        return (*a - *b);
+        /* warning: if *a != *b and both are not 0 we retrun a random
+                greater or lesser than 0 number not realted to which
+                string is longer */
+}
+
+int strncmp_w(const ucs2_t *a, const ucs2_t *b, size_t len)
+{
+        size_t n = 0;
+        while ((n < len) && *b && *a == *b) { a++; b++; n++;}
+        return (len - n)?(*a - *b):0;
+}
+
+/*******************************************************************
+wide strstr()
+********************************************************************/
+ucs2_t *strstr_w(const ucs2_t *s, const ucs2_t *ins)
+{
+       ucs2_t *r;
+       size_t slen, inslen;
+
+       if (!s || !*s || !ins || !*ins) return NULL;
+       slen = strlen_w(s);
+       inslen = strlen_w(ins);
+       r = (ucs2_t *)s;
+       while ((r = strchr_w(r, *ins))) {
+               if (strncmp_w(r, ins, inslen) == 0) return r;
+               r++;
+       }
+       return NULL;
+}
+
+ucs2_t *strcasestr_w(const ucs2_t *s, const ucs2_t *ins)
+{
+       ucs2_t *r;
+       size_t slen, inslen;
+
+       if (!s || !*s || !ins || !*ins) return NULL;
+       slen = strlen_w(s);
+       inslen = strlen_w(ins);
+       r = (ucs2_t *)s;
+       while ((r = strcasechr_w(r, *ins))) {
+               if (strncasecmp_w(r, ins, inslen) == 0) return r;
+               r++;
+       }
+       return NULL;
+}
+
+
+
+
+/*******************************************************************
+case insensitive string comparison
+********************************************************************/
+int strcasecmp_w(const ucs2_t *a, const ucs2_t *b)
+{
+        while (*b && toupper_w(*a) == toupper_w(*b)) { a++; b++; }
+        return (tolower_w(*a) - tolower_w(*b));
+}
+
+/*******************************************************************
+case insensitive string comparison, lenght limited
+********************************************************************/
+int strncasecmp_w(const ucs2_t *a, const ucs2_t *b, size_t len)
+{
+        size_t n = 0;
+        while ((n < len) && *b && (toupper_w(*a) == toupper_w(*b))) { a++; b++; n++; }
+        return (len - n)?(tolower_w(*a) - tolower_w(*b)):0;
+}
+
+/*******************************************************************
+duplicate string
+********************************************************************/
+/* if len == 0 then duplicate the whole string */
+ucs2_t *strndup_w(const ucs2_t *src, size_t len)
+{
+        ucs2_t *dest;
+
+        if (!len) len = strlen_w(src);
+        dest = (ucs2_t *)malloc((len + 1) * sizeof(ucs2_t));
+        if (!dest) {
+                LOG (log_error, logtype_default, "strdup_w: out of memory!\n");
+                return NULL;
+        }
+
+        memcpy(dest, src, len * sizeof(ucs2_t));
+        dest[len] = 0;
+
+        return dest;
+}
+
+ucs2_t *strdup_w(const ucs2_t *src)
+{
+        return strndup_w(src, 0);
+}
+
+/*******************************************************************
+copy a string with max len
+********************************************************************/
+
+ucs2_t *strncpy_w(ucs2_t *dest, const ucs2_t *src, const size_t max)
+{
+        size_t len;
+
+        if (!dest || !src) return NULL;
+
+        for (len = 0; (src[len] != 0) && (len < max); len++)
+                dest[len] = src[len];
+        while (len < max)
+                dest[len++] = 0;
+
+        return dest;
+}
+
+
+/*******************************************************************
+append a string of len bytes and add a terminator
+********************************************************************/
+
+ucs2_t *strncat_w(ucs2_t *dest, const ucs2_t *src, const size_t max)
+{
+        size_t start;
+        size_t len;
+
+        if (!dest || !src) return NULL;
+
+        start = strlen_w(dest);
+        len = strnlen_w(src, max);
+
+        memcpy(&dest[start], src, len*sizeof(ucs2_t));
+        dest[start+len] = 0;
+
+        return dest;
+}
+
+
+ucs2_t *strcat_w(ucs2_t *dest, const ucs2_t *src)
+{
+        size_t start;
+        size_t len;
+
+        if (!dest || !src) return NULL;
+
+        start = strlen_w(dest);
+        len = strlen_w(src);
+
+        memcpy(&dest[start], src, len*sizeof(ucs2_t));
+        dest[start+len] = 0;
+
+        return dest;
+}
+
+
+/* ------------------------ */
+ucs2_t do_precomposition(unsigned int base, unsigned int comb) 
+{
+       int min = 0;
+       int max = sizeof(precompositions) / sizeof(precompositions[0]) - 1;
+       int mid;
+       u_int32_t sought = (base << 16) | comb, that;
+
+       /* binary search */
+       while (max >= min) {
+               mid = (min + max) / 2;
+               that = (precompositions[mid].base << 16) | (precompositions[mid].comb);
+               if (that < sought) {
+                       min = mid + 1;
+               } else if (that > sought) {
+                       max = mid - 1;
+               } else {
+                       return precompositions[mid].replacement;
+               }
+       }
+       /* no match */
+       return 0;
+}
+
+/* -------------------------- */
+u_int32_t do_decomposition(ucs2_t base) 
+{
+       int min = 0;
+       int max = sizeof(decompositions) / sizeof(decompositions[0]) - 1;
+       int mid;
+       u_int32_t sought = base;
+       u_int32_t result, that;
+
+       /* binary search */
+       while (max >= min) {
+               mid = (min + max) / 2;
+               that = decompositions[mid].replacement;
+               if (that < sought) {
+                       min = mid + 1;
+               } else if (that > sought) {
+                       max = mid - 1;
+               } else {
+                       result = (decompositions[mid].base << 16) | (decompositions[mid].comb);
+                       return result;
+               }
+       }
+       /* no match */
+       return 0;
+}
+
+
+static char comp[MAXPATHLEN +1];
+
+char *precompose_w (ucs2_t *name, size_t inplen, size_t *outlen)
+{
+       size_t i;
+       ucs2_t base, comb;
+       ucs2_t *in, *out;
+       ucs2_t result;
+
+       if (!inplen || (inplen & 1) || inplen > sizeof(comp)/sizeof(u_int16_t))
+               return NULL;
+       i = 0;
+       in  = name;
+       out = (ucs2_t *)comp;
+       *outlen = 0;
+    
+       base = *in;
+       while (1) {
+               i += 2;
+               in++;
+               if (i == inplen) {
+                       *out = base;
+                       *outlen += 2;
+                       return comp;
+               }
+               comb = *in;
+               if (comb >= 0x300 && (result = do_precomposition(base, comb))) {
+                       *out = result;
+                       out++;
+                       *outlen += 2;
+                       i += 2;
+                       in++;
+                       if (i == inplen) 
+                               return comp;
+                       base = *in;
+               }
+               else {
+                       *out = base;
+                       out++;
+                       *outlen += 2;
+                       base = comb;
+               }
+       }
+}
+
+/* --------------- */
+
+char *decompose_w (ucs2_t *name, size_t inplen, size_t *outlen)
+{
+       size_t i;
+       ucs2_t base;
+       ucs2_t *in, *out;
+       unsigned int result;
+
+       if (!inplen || (inplen & 1))
+               return NULL;
+       i = 0;
+       in  = name;
+       out = (ucs2_t *)comp;
+       *outlen = 0;
+    
+       while (i < inplen) {
+               if (*outlen >= sizeof(comp)/sizeof(u_int16_t) +2) {
+                       return NULL;
+               }
+               base = *in;
+               if ((result = do_decomposition(base))) {
+                       *out = result  >> 16;
+                       out++;
+                       *outlen += 2;
+                       *out = result & 0xffff;
+                       out++;
+                       *outlen += 2;
+               }
+               else {
+                       *out = base;
+                       out++;
+                       *outlen += 2;
+               }
+               i += 2;
+               in++;
+       }
+       return comp;
+}
+
+size_t utf8_charlen ( char* utf8 )
+{
+       size_t len;
+        unsigned char *p;
+
+        p = (unsigned char*) utf8;
+       
+       if ( *p < 0x80 )
+               return (1);
+       else if ( *p > 0xC1 && *p < 0xe0 && *(p+1) > 0x7f && *(p+1) < 0xC0)
+               return (2);
+       else if ( *p == 0xe0 && *(p+1) > 0x9f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0)
+               return (3);
+       else if ( *p > 0xe0  && *p < 0xf0 && *(p+1) > 0x7f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0)
+               return (3);
+       else if ( *p == 0xf0 && *(p+1) > 0x8f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0 && *(p+3) > 0x7f && *(p+3) < 0xc0 )
+               return (4);
+       else if ( *p > 0xf0 && *p < 0xf4 && *(p+1) > 0x7f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0 && *(p+3) > 0x7f && *(p+3) < 0xc0 )
+               return (4);
+       else if ( *p == 0xf4 && *(p+1) > 0x7f && *(p+1) < 0x90 && *(p+2) > 0x7f && *(p+2) < 0xc0 && *(p+3) > 0x7f && *(p+3) < 0xc0 )
+               return (4);
+       else
+               return ((size_t) -1);
+}
+
+
+size_t utf8_strlen_validate ( char * utf8 )
+{
+        size_t len;
+        unsigned char *p;
+
+        p = (unsigned char*) utf8;
+        len = 0;
+
+        /* see http://www.unicode.org/unicode/reports/tr27/ for an explanation */
+
+        while ( *p != '\0')
+        {
+                if ( *p < 0x80 )
+                        p++;
+
+                else if ( *p > 0xC1 && *p < 0xe0 && *(p+1) > 0x7f && *(p+1) < 0xC0)
+                        p += 2;
+
+                else if ( *p == 0xe0 && *(p+1) > 0x9f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0)
+                        p += 3;
+
+                else if ( *p > 0xe0  && *p < 0xf0 && *(p+1) > 0x7f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0)
+                        p += 3;
+
+                else if ( *p == 0xf0 && *(p+1) > 0x8f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0 && *(p+3) > 0x7f && *(p+3) < 0xc0 )
+                        p += 4;
+
+                else if ( *p > 0xf0 && *p < 0xf4 && *(p+1) > 0x7f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0 && *(p+3) > 0x7f && *(p+3) < 0xc0 )
+                        p += 4;
+
+                else if ( *p == 0xf4 && *(p+1) > 0x7f && *(p+1) < 0x90 && *(p+2) > 0x7f && *(p+2) < 0xc0 && *(p+3) > 0x7f && *(p+3) < 0xc0 )
+                        p += 4;
+
+                else
+                        return ((size_t) -1);
+
+                len++;
+        }
+
+        return (len);
+}
+
index f3340ef75345a5bbfa0e5d0e1a8cc604be9f948b..8ebacf304885cff0fe3a4a96f66ebcfe137f06c4 100644 (file)
@@ -13,4 +13,6 @@ libutil_la_SOURCES = \
        server_child.c  \
        server_lock.c   \
        strcasestr.c    \
-       strdicasecmp.c
+       strdicasecmp.c  
+
+#      util_unicode.c