]> arthur.barton.de Git - netatalk.git/commitdiff
add utf8 support for AFP3
authordidg <didg>
Sun, 9 Mar 2003 19:55:33 +0000 (19:55 +0000)
committerdidg <didg>
Sun, 9 Mar 2003 19:55:33 +0000 (19:55 +0000)
22 files changed:
config/AppleVolumes.default
configure.in
etc/afpd/Makefile.am
etc/afpd/desktop.c
etc/afpd/desktop.h
etc/afpd/directory.c
etc/afpd/directory.h
etc/afpd/enumerate.c
etc/afpd/file.c
etc/afpd/file.h
etc/afpd/filedir.c
etc/afpd/fork.c
etc/afpd/mangle.c
etc/afpd/mangle.h
etc/afpd/precompose.c [new file with mode: 0644]
etc/afpd/unix.c
etc/afpd/volume.c
etc/afpd/volume.h
include/atalk/adouble.h
include/atalk/cnid.h
libatalk/adouble/ad_open.c
libatalk/cnid/cnid_close.c

index 9c0a5c520797b566fbf731e2f39550ba5e4ab2d2..3777e65c773eb0f74e43c9d799d07482a42df199 100644 (file)
@@ -47,6 +47,7 @@
 # noadouble           -> don't create .AppleDouble unless a resource
 #                        fork needs to be created.
 # ro                  -> mount the volume as read-only.
+# utf8                -> use precomposed utf8 filenames
 # mswindows           -> enforce filename restrictions imposed by MS
 #                        Windows. this will also invoke a default
 #                       codepage (iso8859-1) if one isn't already 
index 2151c670bc3b756285339ccb76790ca20ac0ba99..872332a52dd0e035407a476648c469fd08cd1987 100644 (file)
@@ -1,4 +1,4 @@
-dnl $Id: configure.in,v 1.178 2003-01-29 00:16:23 srittau Exp $
+dnl $Id: configure.in,v 1.179 2003-03-09 19:55:33 didg Exp $
 dnl configure.in for netatalk
 
 AC_INIT(bin/adv1tov2/adv1tov2.c)
@@ -197,6 +197,7 @@ AC_ARG_ENABLE(afp3,
 )
 
 if test "$afp3" = "yes"; then
+       AM_ICONV
         AC_SYS_LARGEFILE
 fi
 
index c96ea44b55518da60686858aa575d0390dbf3ba2..d7ad7cac5aab74008d3cf939c8c8a7125eb44f9f 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
+        afp_util.c catsearch.c precompose.c
 
 afpd_LDADD = $(top_builddir)/libatalk/libatalk.la
 afpd_LDFLAGS = -export-dynamic
index e91478c6e383e83986b598b22aed1d2c84a4a658..a329bec8178daf797f556a8c802c30d1e1f79422 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: desktop.c,v 1.23 2003-02-16 12:35:04 didg Exp $
+ * $Id: desktop.c,v 1.24 2003-03-09 19:55:33 didg Exp $
  *
  * See COPYRIGHT.
  *
 #include "fork.h"
 #include "globals.h"
 #include "desktop.h"
+
 #ifdef FILE_MANGLING
 #include "mangle.h"
 #endif /* CNID_DB */
 
+#ifdef AFP3x
+#include <iconv.h>
+#endif
+
 int afp_opendt(obj, ibuf, ibuflen, rbuf, rbuflen )
 AFPObj      *obj;
 char   *ibuf, *rbuf;
@@ -609,27 +614,19 @@ char *dtfile(const struct vol *vol, u_char creator[], char *ext )
     return( path );
 }
 
-/* 
+/* ---------------------------
  * mpath is only a filename 
 */
-char *mtoupath(const struct vol *vol, char *mpath)
+static char  upath[ MAXPATHLEN + 1];
+static char  mpath[ MAXPATHLEN + 1];
+static char  ucs2[ MAXPATHLEN + 1];
+
+static char *old_mtoupath(const struct vol *vol, char *mpath)
 {
-    static char  upath[ MAXPATHLEN + 1];
     char       *m, *u;
     int                 i = 0;
     int          changed = 0;
         
-    if ( *mpath == '\0' ) {
-        return( "." );
-    }
-
-#ifdef FILE_MANGLING
-    m = demangle(vol, mpath);
-    if (m != mpath) {
-        changed = 1;
-        mpath = m;
-    }
-#endif /* FILE_MANGLING */
     m = mpath;
     u = upath;
     while ( *m != '\0' ) {
@@ -651,7 +648,7 @@ char *mtoupath(const struct vol *vol, char *mpath)
                  * H.P. Jansen <hpj@urpla.net> */
 #ifdef DEBUG
                 LOG(log_debug, logtype_afpd, "mtoupath: hex encode: 0x%x", (unsigned char) *m);
-#endif /* DEBUG */
+#endif
                 *u++ = ':';
                 *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
                 *u = hexdig[ *m & 0x0f ];
@@ -662,12 +659,12 @@ char *mtoupath(const struct vol *vol, char *mpath)
                     (!isascii(*m) || *m == '/')) ||
                     (((vol->v_flags & AFPVOL_USEDOTS) == 0) &&
                      ( i == 0 && (*m == '.' )))) {
-#else /* AD_VERSION == AD_VERSION1 */
+#else 
             if ((((vol->v_flags & AFPVOL_NOHEX) == 0) &&
                     (!isprint(*m) || *m == '/')) ||
                     (((vol->v_flags & AFPVOL_USEDOTS) == 0) &&
                      ( i == 0 && (*m == '.' )))) {
-#endif /* AD_VERSION == AD_VERSION1 */
+#endif
                 /* do hex conversion. */
                 *u++ = ':';
                 *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
@@ -689,12 +686,12 @@ char *mtoupath(const struct vol *vol, char *mpath)
     return( (changed)?upath:mpath );
 }
 
+/* ---------------------------- */
 #define hextoint( c )  ( isdigit( c ) ? c - '0' : c + 10 - 'a' )
 #define islxdigit(x)   (!isupper(x)&&isxdigit(x))
 
-char *utompath(const struct vol *vol, char *upath)
+static char *old_utompath(const struct vol *vol, char *upath)
 {
-    static char  mpath[ MAXPATHLEN + 1];
     char        *m, *u;
     int          h;
     int          changed = 0;
@@ -704,13 +701,11 @@ char *utompath(const struct vol *vol, char *upath)
     m = mpath;
     while ( *u != '\0' ) {
         /* we have a code page */
-#if 1
         if (vol->v_utompage && ((*u & 0x80) ||
                                 (vol->v_flags & AFPVOL_MAPASCII))) {
             *m = vol->v_utompage->map[(unsigned char) *u].value;
             changed = 1;
         } else
-#endif /* 1 */
             if ( *u == ':' && *(u+1) != '\0' && islxdigit( *(u+1)) &&
                     *(u+2) != '\0' && islxdigit( *(u+2))) {
                 ++u;
@@ -735,7 +730,7 @@ char *utompath(const struct vol *vol, char *upath)
     m = mpath;
 
 #ifdef FILE_MANGLING
-    m = mangle(vol, mpath);
+    m = mangle(vol, mpath, upath, 0);
     if (m != mpath) {
         changed = 1;
     }
@@ -748,6 +743,252 @@ char *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)
+{
+    char       *m, *u, *r;
+    int                 i = 0;
+    size_t       inplen;
+    size_t       outlen;
+        
+    if ( *mpath == '\0' ) {
+        return( "." );
+    }
+
+#ifdef FILE_MANGLING
+    m = demangle(vol, mpath);
+    if (m != mpath) {
+        return m;
+    }
+#endif /* FILE_MANGLING */
+
+    if (!vol_utf8(vol))
+       return old_mtoupath(vol, mpath);
+
+    m = mpath;
+    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 */
+        ) {
+          /* do hex conversion. */
+          *u++ = ':';
+          *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
+          *u = hexdig[ *m & 0x0f ];
+        } else
+           *u = *m;
+        u++;
+        i++;
+        m++;
+    }
+    *u = '\0';
+    u = upath;
+#ifdef AFP3x
+    inplen = strlen(u);
+    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))
+            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);
+
+        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[MAXPATHLEN -outlen] = 0;
+#endif
+#ifdef DEBUG
+    LOG(log_debug, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
+#endif /* DEBUG */
+    return( u );
+}
+
+/* --------------- */
+char *utompath(const struct vol *vol, char *upath, int utf8)
+{
+    char        *m, *u, *r;
+    int          h;
+    int          mangleflag = 0;
+    size_t       inplen;
+    size_t       outlen;
+
+    if (!vol_utf8(vol))
+       return old_utompath(vol, upath);
+    /* do the hex conversion */
+    u = upath;
+    m = mpath;
+    while ( *u != '\0' ) {
+        if ( *u == ':' && islxdigit( *(u+1)) && islxdigit( *(u+2))) {
+            ++u;
+            h = hextoint( *u ) << 4;
+            ++u;
+            h |= hextoint( *u );
+            *m = h;
+        } else
+            *m = *u;
+        u++;
+        m++;
+    }
+    *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;
+    }
+    else {
+        m = precompose((u_int16_t *)ucs2, MAXPATHLEN -outlen, &inplen);
+
+        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);
+#endif /* FILE_MANGLING */
+
+    return(m);
+}
+
+/* ----------------------------- */
 int afp_addcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
 AFPObj      *obj;
 char   *ibuf, *rbuf;
index 1f636272b83b98964b9068ca5aa027ef5c6f74e9..f766c7579c8290d5bdb4f2177acde7e9bad2588f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: desktop.h,v 1.2 2001-06-20 18:33:04 rufustfirefly Exp $
+ * $Id: desktop.h,v 1.3 2003-03-09 19:55:33 didg Exp $
  *
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
@@ -46,8 +46,8 @@ struct savedt {
 typedef unsigned char CreatorType[4];
 
 extern char    *dtfile __P((const struct vol *, u_char [], char *));
-extern char    *mtoupath __P((const struct vol *, char *));
-extern char    *utompath __P((const struct vol *, char *));
+extern char    *mtoupath __P((const struct vol *, char *, int utf8));
+extern char    *utompath __P((const struct vol *, char *, int utf8));
 extern u_char  ucreator[];
 
 #define validupath(vol, name) ((((vol)->v_flags & AFPVOL_USEDOTS) ? \
index aeab2c83ce62dc4c06fa7185c87e8a1884f232d8..14a0a1498a402a8df9a3cd4a293e51c9eaadff72 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: directory.c,v 1.62 2003-02-16 12:35:04 didg Exp $
+ * $Id: directory.c,v 1.63 2003-03-09 19:55:33 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -182,7 +182,10 @@ u_int32_t  did;
         return NULL;
     }
     ptr = path + MAXPATHLEN;
-    mpath = utompath(vol, upath);
+    if (NULL == ( mpath = utompath(vol, upath, utf8_encoding()) ) ) {
+        afp_errno = AFPERR_NOOBJ;
+        return NULL;
+    }
     len = strlen(mpath);
     pathlen = len;          /* no 0 in the last part */
     len++;
@@ -193,11 +196,14 @@ u_int32_t did;
         if (ret != NULL) {
             break;
         }
-        if (NULL == (upath = cnid_resolve(vol->v_db, &id, buffer, buflen))) {
+        if ( NULL == (upath = cnid_resolve(vol->v_db, &id, buffer, buflen))
+             ||
+             NULL == (mpath = utompath(vol, upath, utf8_encoding()))
+        ) {
             afp_errno = AFPERR_NOOBJ;
             return NULL;
         }
-        mpath = utompath(vol, upath);
+
         len = strlen(mpath) + 1;
         pathlen += len;
         if (pathlen > 255) {
@@ -528,10 +534,13 @@ struct vol        *vol;
 struct dir     *dir;
 struct path *path;
 {
-    char       *p;
+    path->u_name = mtoupath(vol, path->m_name, utf8_encoding() );
 
-    path->u_name = p = mtoupath(vol, path->m_name );
-    if ( of_stat( path ) != 0 ) {
+    if ( path->u_name == NULL) {
+        afp_errno = AFPERR_PARAM;
+        return NULL;
+    }
+    if (of_stat( path ) != 0 ) {
         return( NULL );
     }
 
@@ -1051,7 +1060,7 @@ char      **cpath;
 
             if ( cdir == NULL ) {
 
-                if ( len > 0 ) {
+                if ( len > 0 || !ret.u_name) {
                     return NULL;
                 }
 
@@ -1348,12 +1357,12 @@ int getdirparams(const struct vol *vol,
     if ( l_nameoff ) {
         ashort = htons( data - buf );
         memcpy( l_nameoff, &ashort, sizeof( ashort ));
-        data = set_name(data, dir->d_m_name, 0);
+        data = set_name(vol, data, dir->d_m_name, 0);
     }
     if ( utf_nameoff ) {
         ashort = htons( data - buf );
         memcpy( utf_nameoff, &ashort, sizeof( ashort ));
-        data = set_name(data, dir->d_m_name, utf8);
+        data = set_name(vol, data, dir->d_m_name, utf8);
     }
     if ( isad ) {
         ad_close( &ad, ADFLAGS_HF );
index f978c340d6d3f8f125cbe039d7fc50d6664be9c7..c7cfc6ac11b84843545eb67bd06ead75be7f252f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: directory.h,v 1.10 2003-01-26 10:42:40 didg Exp $
+ * $Id: directory.h,v 1.11 2003-03-09 19:55:34 didg Exp $
  *
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
@@ -55,7 +55,7 @@ struct dir {
     time_t      ctime;                /* inode ctime */
     int         offcnt;               /* offspring count */
 
-    char       *d_m_name;             /* mac name */
+    char       *d_m_name;            /* mac name */
     char        *d_u_name;            /* unix name */
 };
 
@@ -175,6 +175,7 @@ struct maccess {
 #define        AR_UOWN         (1<<7)
 
 extern struct dir       *dirnew __P((const char *, const char *));
+extern void             dirfreename __P((struct dir *));
 extern void             dirfree __P((struct dir *));
 extern struct dir      *dirsearch __P((const struct vol *, u_int32_t));
 extern struct dir      *dirlookup __P((const struct vol *, u_int32_t));
index 8c161d8d9f28eab9bef26f25e3cb364875c3d2e1..0bb64e463c0509d0700f19958986c0d9a249c198 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: enumerate.c,v 1.34 2003-02-16 12:35:04 didg Exp $
+ * $Id: enumerate.c,v 1.35 2003-03-09 19:55:34 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -47,9 +47,6 @@ struct path     *path;
     int                upathlen;
     char        *name;
     char        *upath;
-#ifndef USE_LASTDID
-    struct stat lst, *lstp;
-#endif /* USE_LASTDID */
     struct stat *st;
 
     upath = path->u_name;
@@ -61,38 +58,9 @@ struct path     *path;
         return NULL;
     }
 
-    cdir->d_did = 0;
-
-#ifdef CNID_DB
-    /* add to cnid db */
-    cdir->d_did = cnid_add(vol->v_db, st, dir->d_did, upath,
-                           upathlen, cdir->d_did);
-    /* Fail out if things go bad with CNID. */
-    if (cdir->d_did == CNID_INVALID) {
-        switch (errno) {
-        case CNID_ERR_CLOSE: /* the db is closed */
-            break;
-        case CNID_ERR_PARAM:
-            LOG(log_error, logtype_afpd, "adddir: Incorrect parameters passed to cnid_add");
-            return NULL;
-        case CNID_ERR_PATH:
-        case CNID_ERR_DB:
-        case CNID_ERR_MAX:
-            return NULL;
-        }
-    }
-#endif /* CNID_DB */
-
-    if (cdir->d_did == 0) {
-#ifdef USE_LASTDID
-        /* last way of doing DIDs */
-        cdir->d_did = htonl( vol->v_lastdid++ );
-#else /* USE_LASTDID */
-        lstp = lstat(upath, &lst) < 0 ? st : &lst;
-        /* the old way of doing DIDs (default) */
-        cdir->d_did = htonl( CNID(lstp, 0) );
-#endif /* USE_LASTDID */
-    }
+    cdir->d_did = get_id(vol, NULL, st, dir->d_did, upath, upathlen);
+    if (cdir->d_did == 0) 
+        return NULL;
 
     if ((edir = dirinsert( vol, cdir ))) {
         /* it's not possible with LASTDID
@@ -195,9 +163,11 @@ char *check_dirent(const struct vol *vol, char *name)
     /* check for vetoed filenames */
     if (veto_file(vol->v_veto, name))
         return NULL;
+    if (NULL == (m_name = utompath(vol, name, utf8_encoding()))) 
+        return NULL;    
 
     /* now check against too big a file */
-    if (strlen(m_name = utompath(vol, name)) > vol->max_filename)
+    if (strlen(m_name) > vol->max_filename)
         return NULL;
 
     return m_name;
@@ -444,8 +414,8 @@ int     ext;
             }
             dir = dirsearch_byname(curdir, s_path.u_name);
             if (!dir) {
-                s_path.m_name = utompath(vol, s_path.u_name);
-                if ((dir = adddir( vol, curdir, &s_path)) == NULL) {
+                s_path.m_name = utompath(vol, s_path.u_name, utf8_encoding() );
+                if (s_path.m_name == NULL || (dir = adddir( vol, curdir, &s_path)) == NULL) {
                     return AFPERR_MISC;
                 }
             }
@@ -462,7 +432,10 @@ int     ext;
                 sd.sd_last += len + 1;
                 continue;
             }
-            s_path.m_name = utompath(vol, s_path.u_name);
+            s_path.m_name = utompath(vol, s_path.u_name, utf8_encoding());
+            if (s_path.m_name == NULL ) {
+                return AFPERR_MISC;
+            }
             if (AFP_OK != ( ret = getfilparams(vol, fbitmap, &s_path, curdir, 
                                      data + header , &esz )) ) {
                 return( ret );
index b395d8b347d819a6edd980939a22f7e9dc075fa5..f88976bf51915e0105f1fd241b74614175b9447b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: file.c,v 1.86 2003-02-19 18:59:52 jmarcus Exp $
+ * $Id: file.c,v 1.87 2003-03-09 19:55:34 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -108,15 +108,29 @@ void *get_finderinfo(const char *mpath, struct adouble *adp, void *data)
 
 /* ---------------------
 */
-char *set_name(char *data, const char *name, u_int32_t utf8) 
+char *set_name(const struct vol *vol, char *data, char *name, u_int32_t utf8) 
 {
-    u_int32_t           aint;
-
+    u_int32_t   aint;
+    char        *tp = NULL;
+    char        *src = name;
     aint = strlen( name );
 
     if (!utf8) {
-        if (afp_version >= 30) {
-            /* the name is in utf8 */
+        /* want mac name */
+        if (utf8_encoding()) {
+            /* but name is an utf8 mac name */
+            char *u, *m;
+           
+            /* global static variable... */
+            tp = strdup(name);
+            if (!(u = mtoupath(vol, name, 1)) || !(m = utompath(vol, u, 0))) {
+               aint = 0;
+            }
+            else {
+                aint = strlen(m);
+                src = m;
+            }
+            
         }
         if (aint > MACFILELEN)
             aint = MACFILELEN;
@@ -137,9 +151,12 @@ char *set_name(char *data, const char *name, u_int32_t utf8)
         data += sizeof(temp);
     }
 
-    memcpy( data, name, aint );
+    memcpy( data, src, aint );
     data += aint;
-
+    if (tp) {
+        strcpy(name, tp);
+        free(tp);
+    }
     return data;
 }
 
@@ -155,16 +172,88 @@ char *set_name(char *data, const char *name, u_int32_t utf8)
                                  (1 << FILPBIT_EXTRFLEN) |\
                                  (1 << FILPBIT_PDINFO)))
 
+/* -------------------------- */
+u_int32_t get_id(struct vol *vol, struct adouble *adp,  const struct stat *st,
+             const cnid_t did, const char *upath, const int len) 
+{
+u_int32_t aint = 0;
+
+#ifdef CNID_DB
+
+    aint = cnid_add(vol->v_db, st, did, upath, len, aint);
+    /* Throw errors if cnid_add fails. */
+    if (aint == CNID_INVALID) {
+        switch (errno) {
+        case CNID_ERR_CLOSE: /* the db is closed */
+            break;
+        case CNID_ERR_PARAM:
+            LOG(log_error, logtype_afpd, "get_id: Incorrect parameters passed to cnid_add");
+            afp_errno = AFPERR_PARAM;
+            return CNID_INVALID;
+        case CNID_ERR_PATH:
+            afp_errno = AFPERR_PARAM;
+            return CNID_INVALID;
+        default:
+            afp_errno = AFPERR_MISC;
+            return CNID_INVALID;
+        }
+    }
+#endif /* CNID_DB */
+
+    if (aint == 0) {
+        /*
+         * First thing:  DID and FNUMs are
+         * in the same space for purposes of enumerate (and several
+         * other wierd places).  While we consider this Apple's bug,
+         * this is the work-around:  In order to maintain constant and
+         * unique DIDs and FNUMs, we monotonically generate the DIDs
+         * during the session, and derive the FNUMs from the filesystem.
+         * Since the DIDs are small, we insure that the FNUMs are fairly
+         * large by setting thier high bits to the device number.
+         *
+         * AFS already does something very similar to this for the
+         * inode number, so we don't repeat the procedure.
+         *
+         * new algorithm:
+         * due to complaints over did's being non-persistent,
+         * here's the current hack to provide semi-persistent
+         * did's:
+         *      1) we reserve the first bit for file ids.
+         *      2) the next 7 bits are for the device.
+         *      3) the remaining 24 bits are for the inode.
+         *
+         * both the inode and device information are actually hashes
+         * that are then truncated to the requisite bit length.
+         *
+         * it should be okay to use lstat to deal with symlinks.
+         */
+#ifdef USE_LASTDID
+        if ( S_ISDIR(st->st_mode)) {
+            aint = htonl( vol->v_lastdid++ );
+        }
+        else
+        {
+            aint = htonl(( st->st_dev << 16 ) | (st->st_ino & 0x0000ffff));
+        }
+#else /* USE_LASTDID */
+        {
+            struct stat        lst;
+            const struct stat *lstp;
 
+            lstp = lstat(upath, &lst) < 0 ? st : &lst;
+            aint = htonl(CNID(lstp, 1));
+        }
+#endif /* USE_LASTDID */
+    }
+    return aint;
+}
+             
 /* -------------------------- */
 int getmetadata(struct vol *vol,
                  u_int16_t bitmap,
                  struct path *path, struct dir *dir, 
                  char *buf, int *buflen, struct adouble *adp, int attrbits )
 {
-#ifndef USE_LASTDID
-    struct stat                lst, *lstp;
-#endif /* USE_LASTDID */
     char               *data, *l_nameoff = NULL, *upath;
     char                *utf_nameoff = NULL;
     int                        bit = 0;
@@ -252,7 +341,6 @@ int getmetadata(struct vol *vol,
                     memcpy(data + FINDERINFO_FRFLAGOFF, &ashort, sizeof(ashort));
                 }
             }
-
             data += 32;
             break;
 
@@ -267,66 +355,9 @@ int getmetadata(struct vol *vol,
             break;
 
         case FILPBIT_FNUM :
-            aint = 0;
-#if AD_VERSION > AD_VERSION1
-            /* look in AD v2 header */
-            if (adp)
-                memcpy(&aint, ad_entry(adp, ADEID_DID), sizeof(aint));
-#endif /* AD_VERSION > AD_VERSION1 */
-
-#ifdef CNID_DB
-            aint = cnid_add(vol->v_db, st, dir->d_did, upath,
-                            strlen(upath), aint);
-            /* Throw errors if cnid_add fails. */
-            if (aint == CNID_INVALID) {
-                switch (errno) {
-                case CNID_ERR_PARAM:
-                    LOG(log_error, logtype_afpd, "getfilparams: Incorrect parameters passed to cnid_add");
-                    return(AFPERR_PARAM);
-                case CNID_ERR_PATH:
-                    return(AFPERR_PARAM);
-                case CNID_ERR_DB:
-                case CNID_ERR_MAX:
-                    return(AFPERR_MISC);
-                }
-            }
-#endif /* CNID_DB */
-
-            if (aint == 0) {
-                /*
-                 * What a fucking mess.  First thing:  DID and FNUMs are
-                 * in the same space for purposes of enumerate (and several
-                 * other wierd places).  While we consider this Apple's bug,
-                 * this is the work-around:  In order to maintain constant and
-                 * unique DIDs and FNUMs, we monotonically generate the DIDs
-                 * during the session, and derive the FNUMs from the filesystem.
-                 * Since the DIDs are small, we insure that the FNUMs are fairly
-                 * large by setting thier high bits to the device number.
-                 *
-                 * AFS already does something very similar to this for the
-                 * inode number, so we don't repeat the procedure.
-                 *
-                 * new algorithm:
-                 * due to complaints over did's being non-persistent,
-                 * here's the current hack to provide semi-persistent
-                 * did's:
-                 *      1) we reserve the first bit for file ids.
-                 *      2) the next 7 bits are for the device.
-                 *      3) the remaining 24 bits are for the inode.
-                 *
-                 * both the inode and device information are actually hashes
-                 * that are then truncated to the requisite bit length.
-                 *
-                 * it should be okay to use lstat to deal with symlinks.
-                 */
-#ifdef USE_LASTDID
-                aint = htonl(( st->st_dev << 16 ) | (st->st_ino & 0x0000ffff));
-#else /* USE_LASTDID */
-                lstp = lstat(upath, &lst) < 0 ? st : &lst;
-                aint = htonl(CNID(lstp, 1));
-#endif /* USE_LASTDID */
-            }
-
+            aint = get_id(vol, adp, st, dir->d_did, upath, strlen(upath));
+            if (aint == 0)
+                return afp_errno;
             memcpy(data, &aint, sizeof( aint ));
             data += sizeof( aint );
             break;
@@ -438,12 +469,12 @@ int getmetadata(struct vol *vol,
     if ( l_nameoff ) {
         ashort = htons( data - buf );
         memcpy(l_nameoff, &ashort, sizeof( ashort ));
-        data = set_name(data, path->m_name, 0);
+        data = set_name(vol, data, path->m_name, 0);
     }
     if ( utf_nameoff ) {
         ashort = htons( data - buf );
         memcpy(utf_nameoff, &ashort, sizeof( ashort ));
-        data = set_name(data, path->m_name, utf8);
+        data = set_name(vol, data, path->m_name, utf8);
     }
     *buflen = data - buf;
     return (AFP_OK);
@@ -1119,7 +1150,9 @@ int               ibuflen, *rbuflen;
         return( AFPERR_PARAM );
     }
 
-    upath = mtoupath(vol, newname);
+    if (NULL == (upath = mtoupath(vol, newname, utf8_encoding()))) {
+        return( AFPERR_PARAM );
+    }
     if ( (err = copyfile(p, upath , newname, vol_noadouble(vol))) < 0 ) {
         return err;
     }
@@ -1414,9 +1447,6 @@ char      *ibuf, *rbuf;
 int            ibuflen, *rbuflen;
 {
     struct stat         *st;
-#if AD_VERSION > AD_VERSION1
-    struct adouble     ad;
-#endif
     struct vol         *vol;
     struct dir         *dir;
     char               *upath;
@@ -1430,6 +1460,7 @@ int               ibuflen, *rbuflen;
 #endif /* DEBUG */
 
     *rbuflen = 0;
+
     ibuf += 2;
 
     memcpy(&vid, ibuf, sizeof(vid));
@@ -1439,6 +1470,10 @@ int              ibuflen, *rbuflen;
         return( AFPERR_PARAM);
     }
 
+    if (vol->v_db == NULL) {
+        return AFPERR_NOOP;
+    }
+
     if (vol->v_flags & AFPVOL_RO)
         return AFPERR_VLOCK;
 
@@ -1476,15 +1511,7 @@ int              ibuflen, *rbuflen;
         return AFPERR_EXISTID;
     }
 
-#if AD_VERSION > AD_VERSION1
-    memset(&ad, 0, sizeof(ad));
-    if (ad_open( upath, ADFLAGS_HF, O_RDONLY, 0, &ad ) >= 0) {
-        memcpy(&id, ad_entry(&ad, ADEID_DID), sizeof(id));
-        ad_close(&ad, ADFLAGS_HF);
-    }
-#endif /* AD_VERSION > AD_VERSION1 */
-
-    if ((id = cnid_add(vol->v_db, st, did, upath, len, id)) != CNID_INVALID) {
+    if ((id = get_id(vol, NULL, st, did, upath, len)) != CNID_INVALID) {
         memcpy(rbuf, &id, sizeof(id));
         *rbuflen = sizeof(id);
         return AFP_OK;
@@ -1493,19 +1520,7 @@ int              ibuflen, *rbuflen;
 #ifdef DEBUG
     LOG(log_info, logtype_afpd, "ending afp_createid...:");
 #endif /* DEBUG */
-
-    switch (errno) {
-    case EROFS:
-        return AFPERR_VLOCK;
-        break;
-    case EPERM:
-    case EACCES:
-        return AFPERR_ACCESS;
-        break;
-    default:
-        LOG(log_error, logtype_afpd, "afp_createid: cnid_add: %s", strerror(errno));
-        return AFPERR_PARAM;
-    }
+    return afp_errno;
 }
 
 /* ------------------------------
@@ -1540,6 +1555,10 @@ int              ibuflen, *rbuflen;
         return( AFPERR_PARAM);
     }
 
+    if (vol->v_db == NULL) {
+        return AFPERR_NOOP;
+    }
+
     memcpy(&id, ibuf, sizeof( id ));
     ibuf += sizeof(id);
 
@@ -1568,7 +1587,9 @@ int               ibuflen, *rbuflen;
 
     memcpy(&bitmap, ibuf, sizeof(bitmap));
     bitmap = ntohs( bitmap );
-    path.m_name = utompath(vol, upath);
+    if (NULL == (path.m_name = utompath(vol, upath, utf8_encoding()))) {
+        return AFPERR_NOID;
+    }
     if (AFP_OK != (err = getfilparams(vol, bitmap, &path , curdir, 
                             rbuf + sizeof(bitmap), &buflen))) {
         return err;
@@ -1614,6 +1635,10 @@ int              ibuflen, *rbuflen;
         return( AFPERR_PARAM);
     }
 
+    if (vol->v_db == NULL) {
+        return AFPERR_NOOP;
+    }
+
     if (vol->v_flags & AFPVOL_RO)
         return AFPERR_VLOCK;
 
index 2c523b8e053bb126f8c1cd951ab6b56b10f37ebb..f97ce03b4ac6ff2d93f1b66cd7b7c16d2c260c1d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: file.h,v 1.15 2003-02-16 12:35:04 didg Exp $
+ * $Id: file.h,v 1.16 2003-03-09 19:55:34 didg Exp $
  *
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
@@ -74,7 +74,7 @@ struct extmap {
 };
 
 #define kTextEncodingUTF8 0x08000103
-extern char *set_name   __P((char *, const char *, u_int32_t ) );
+extern char *set_name   __P((const struct vol *, char *, char *, u_int32_t ) );
 
 extern struct extmap   *getextmap __P((const char *));
 extern struct extmap   *getdefextmap __P((void));
@@ -90,6 +90,9 @@ extern int deletefile   __P((struct vol *, char *, int));
 extern void *get_finderinfo __P((const char *, struct adouble *, void *));
 extern int  copy_path_name __P((char *, char *i));
 
+extern u_int32_t get_id  __P((struct vol *, struct adouble *, const struct stat *,
+                                const cnid_t , const char *, const int ));
+
 /* FP functions */
 extern int      afp_exchangefiles __P((AFPObj *, char *, int, char *, int *));
 extern int     afp_setfilparams __P((AFPObj *, char *, int, char *, int *));
index de03e292bc9f17835d22e02df1cd66472b785a6e..dd2795af039502a37468f5d537bd5baa25df395c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: filedir.c,v 1.41 2003-02-16 12:35:04 didg Exp $
+ * $Id: filedir.c,v 1.42 2003-03-09 19:55:34 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -361,7 +361,10 @@ int         isdir;
     
     if (!isdir) {
 #ifdef CNID_DB
-        p = mtoupath(vol, oldname);
+        p = mtoupath(vol, oldname, utf8_encoding());
+        if (!p) { 
+            return AFPERR_PARAM; /* can't convert */
+        }
         id = cnid_get(vol->v_db, sdir->d_did, p, strlen(p));
 #endif /* CNID_DB */
         p = ctoupath( vol, sdir, oldname );
@@ -400,7 +403,9 @@ int         isdir;
             return(AFPERR_OLOCK);
     }
 
-    upath = mtoupath(vol, newname);
+    if (NULL == (upath = mtoupath(vol, newname, utf8_encoding()))){ 
+        return AFPERR_PARAM;
+    }
     path.u_name = upath;
     st = &path.st;    
     if (0 != (rc = check_name(vol, upath))) {
@@ -609,6 +614,9 @@ char        *u;
     char       *p;
     int                len;
 
+    if (u == NULL)
+        return NULL;
+        
     p = path + sizeof( path ) - 1;
     *p = '\0';
     len = strlen( u );
@@ -643,7 +651,7 @@ const struct vol    *vol;
 struct dir     *dir;
 char   *name;
 {
-    return absupath(vol, dir, mtoupath(vol, name));
+    return absupath(vol, dir, mtoupath(vol, name, utf8_encoding()));
 }
 
 /* ------------------------- */
@@ -735,8 +743,11 @@ int                ibuflen, *rbuflen;
     rc = moveandrename(vol, sdir, oldname, newname, isdir);
 
     if ( rc == AFP_OK ) {
-        char *upath = mtoupath(vol, newname);
-
+        char *upath = mtoupath(vol, newname, utf8_encoding());
+        
+        if (NULL == upath) {
+            return AFPERR_PARAM;
+        }
         curdir->offcnt++;
         sdir->offcnt--;
 #ifdef DROPKLUDGE
index 53779a023dc64ab7a1267ed079a5485e49d71fe4..0430e1a0d1d36b02909d4f37aa888e5a38284d12 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: fork.c,v 1.49 2003-02-16 12:35:04 didg Exp $
+ * $Id: fork.c,v 1.50 2003-03-09 19:55:35 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -86,7 +86,9 @@ const u_int16_t     attrbits;
     vol = ofork->of_vol;
     dir = ofork->of_dir;
 
-    path.u_name = mtoupath(vol, ofork->of_name);
+    if (NULL == (path.u_name = mtoupath(vol, ofork->of_name, utf8_encoding()))) {
+        return( AFPERR_MISC );
+    }
     path.m_name = ofork->of_name;
     st = &path.st;
     if ( bitmap & ( (1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN) | 
@@ -427,6 +429,10 @@ int                ibuflen, *rbuflen;
                 /* else we don't set AFPFORK_OPEN because there's no ressource fork file 
                  * We need to check AFPFORK_OPEN in afp_closefork(). eg fork open read-only
                  * then create in open read-write.
+                 * FIXME , it doesn't play well with byte locking example:
+                 * ressource fork open read only
+                 * locking set on it (no effect, there's no file!)
+                 * ressource fork open read write now
                 */
                 break;
             case EMFILE :
index dff7e36858fca268828b764731cd5afc1fb87ece..b1c80a8124dfa3819e897fc65c92a73e43bc7453 100644 (file)
@@ -1,5 +1,5 @@
 /* 
- * $Id: mangle.c,v 1.14 2003-01-12 14:40:02 didg Exp $ 
+ * $Id: mangle.c,v 1.15 2003-03-09 19:55:35 didg Exp $ 
  *
  * Copyright (c) 2002. Joe Marcus Clarke (marcus@marcuscom.com)
  * All Rights Reserved.  See COPYRIGHT.
@@ -40,15 +40,21 @@ demangle(const struct vol *vol, char *mfilename) {
 
        /* No unmangled filename was found. */
        if (filename == NULL) {
-           LOG(log_error, logtype_afpd, "demangle: Unable to lookup %s in the mangle database", mfilename);
+#ifdef DEBUG
+           LOG(log_debug, logtype_afpd, "demangle: Unable to lookup %s in the mangle database", mfilename);
+#endif
            return mfilename;
        }
-
        return filename;
 }
 
+/* -----------------------
+   with utf8 filename not always round trip
+   filename   mac filename too long or with unmatchable utf8 replaced with _
+   uname      unix filename 
+*/
 char *
-mangle(const struct vol *vol, char *filename) {
+mangle(const struct vol *vol, char *filename, char *uname, int flags) {
     char *ext = NULL;
     char *tf = NULL;
     char *m = NULL;
@@ -58,11 +64,10 @@ mangle(const struct vol *vol, char *filename) {
     int mangle_suffix_int = 0;
 
     /* Do we really need to mangle this filename? */
-    if (strlen(filename) <= vol->max_filename) {
+    if (!flags && strlen(filename) <= vol->max_filename) {
        return filename;
     }
-
-    /* First, attmept to locate a file extension. */
+    /* First, attempt to locate a file extension. */
     if (NULL != (ext = strrchr(filename, '.')) ) {
        ext_len = strlen(ext);
        if (ext_len > MAX_EXT_LENGTH) {
@@ -86,7 +91,7 @@ mangle(const struct vol *vol, char *filename) {
        }
 
        tf = cnid_mangle_get(vol->v_db, m);
-       if (tf == NULL || (strcmp(tf, filename)) == 0) {
+       if (tf == NULL || (strcmp(tf, uname)) == 0) {
            break;
        }
        else {
@@ -97,7 +102,7 @@ mangle(const struct vol *vol, char *filename) {
        }
     }
 
-    if (cnid_mangle_add(vol->v_db, m, filename) < 0) {
+    if (cnid_mangle_add(vol->v_db, m, uname) < 0) {
        return filename;
     }
 
index 2d80c8a372845820a962c9cda53f9f676f60ed0c..ac01a7a6f7dfd38788225ddc528c089b2c97f661 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: mangle.h,v 1.3 2002-10-17 18:01:54 didg Exp $
+ * $Id: mangle.h,v 1.4 2003-03-09 19:55:35 didg Exp $
  *
  */
 
@@ -9,6 +9,8 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+
+#include <atalk/adouble.h>
 #ifdef CNID_DB
 #include <atalk/cnid.h>
 #endif /* CNID_DB */
@@ -24,7 +26,7 @@
 #define MAX_EXT_LENGTH 4 /* XXX This cannot be greater than 27 */
 #define MAX_LENGTH MACFILELEN 
 
-extern char *mangle __P((const struct vol *, char *));
+extern char *mangle __P((const struct vol *, char *, char *, int));
 extern char *demangle __P((const struct vol *, char *));
 
 #endif /* AFPD_MANGLE_H */
diff --git a/etc/afpd/precompose.c b/etc/afpd/precompose.c
new file mode 100644 (file)
index 0000000..9514726
--- /dev/null
@@ -0,0 +1,2043 @@
+/*
+ * 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 a19f644dff392863b86584f4bf14c53fddb79bc7..72b634e63898c9465b951ee98ccbd9673298e65a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: unix.c,v 1.42 2003-01-12 14:40:03 didg Exp $
+ * $Id: unix.c,v 1.43 2003-03-09 19:55:35 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -625,6 +625,7 @@ setdirowner_noadouble:
     return( 0 );
 }
 
+#if 0
 /* recursive chown()ing of a directory */
 static int recursive_chown(const char *path, uid_t uid, gid_t gid) {
     struct stat sbuf;
@@ -669,6 +670,7 @@ recursive_chown_end:
     }
     return ret;
 }
+#endif
 
 /* This is equivalent of unix rename(). */
 int unix_rename(const char *oldpath, const char *newpath)
@@ -680,7 +682,7 @@ int unix_rename(const char *oldpath, const char *newpath)
 
        if (rename(oldpath, newpath) < 0)
                return -1;
-
+#if 0
        for (i = 0; i <= PATH_MAX && newpath[i] != '\0'; i++)
                pd_name[i] = newpath[i];
        pd_name[i] = '\0';
@@ -706,7 +708,7 @@ int unix_rename(const char *oldpath, const char *newpath)
                    pd_name, geteuid(), strerror(errno));
             seteuid(uid);
        }
-
+#endif
        return 0;
 }
 
index 0eb1a9330f6fc8bf71a24711170b8245f2fad9ba..66c9f364ffbe1df5a381392a99350fe319af4685 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: volume.c,v 1.48 2003-03-05 09:41:34 didg Exp $
+ * $Id: volume.c,v 1.49 2003-03-09 19:55:35 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -1240,7 +1240,9 @@ int               ibuflen, *rbuflen;
         volume->v_db = NULL;
         opened = 1;
     }
-    
+    else {
+       /* FIXME */
+    }    
 #ifdef FORCE_UIDGID
     set_uidgid ( volume );
 #endif /* FORCE_UIDGID */
@@ -1277,6 +1279,31 @@ int              ibuflen, *rbuflen;
                               rbuf + sizeof(bitmap), &buflen )) != AFP_OK ) {
         goto openvol_err;
     }
+#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);
+    
+    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_iconv;
+        }
+        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_iconv;
+        }
+        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_iconv;
+        }
+    }
+#endif
     *rbuflen = buflen + sizeof( bitmap );
     bitmap = htons( bitmap );
     memcpy(rbuf, &bitmap, sizeof( bitmap ));
@@ -1294,7 +1321,17 @@ int              ibuflen, *rbuflen;
 #endif /* CNID_DB */
 
     return( AFP_OK );
-
+#ifdef AFP3x
+openvol_err_iconv:
+    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        
 openvol_err:
 #ifdef CNID_DB
     if (opened && volume->v_db != NULL) {
index 7af5634045fb716f921da8144cf656016b4c3261..f173eee1de57f4e47973803f46264c23cad881e1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: volume.h,v 1.17 2003-01-08 15:01:37 didg Exp $
+ * $Id: volume.h,v 1.18 2003-03-09 19:55:35 didg Exp $
  *
  * Copyright (c) 1990,1994 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
 #include <sys/types.h>
 #include <netatalk/endian.h>
 
+#ifdef HAVE_USABLE_ICONV
+#include <iconv.h>
+#endif
+
 #include "globals.h"
 
 #define AFPVOL_NAMELEN   27
@@ -55,15 +59,25 @@ struct vol {
     
     char                *v_password;
     char                *v_veto;
+
 #ifdef CNID_DB
     void                *v_db;
     char                *v_dbpath;
-#endif /* CNID_DB */
+#endif 
     mode_t             v_umask;
+
 #ifdef FORCE_UIDGID
-    char                               *v_forceuid;
-    char                               *v_forcegid;
-#endif /* FORCE_UIDGID */
+    char               *v_forceuid;
+    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
+
 };
 
 #ifdef NO_LARGE_VOL_SUPPORT
@@ -148,6 +162,14 @@ int wincheck(const struct vol *vol, const char *path);
 #define vol_noadouble(vol) (((vol)->v_flags & AFPVOL_NOADOUBLE) ? \
                            ADFLAGS_NOADOUBLE : 0)
 
+#ifdef AFP3x
+#define vol_utf8(vol) ((vol)->v_flags & AFPVOL_UTF8)
+#define utf8_encoding() (afp_version >= 30)
+#else
+#define vol_utf8(vol) (0)
+#define utf8_encoding() (0)
+#endif
+
 extern struct vol      *getvolbyvid __P((const u_int16_t));
 extern int              ustatfs_getvolspace __P((const struct vol *,
             VolSpace *, VolSpace *,
index 23f5fd485d57593276bbb677dff6b40d3c9be07a..1e72258f6ff87b118eb7a14a67d076f97d89212e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: adouble.h,v 1.20 2003-02-16 12:35:05 didg Exp $
+ * $Id: adouble.h,v 1.21 2003-03-09 19:55:35 didg Exp $
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
  *
@@ -184,6 +184,8 @@ static __inline__ int sendfile(int fdout, int fdin, off_t *off, size_t count)
 #define ADEDOFF_FILEI  541
 #endif
 
+typedef u_int32_t cnid_t;
+
 /*
  * The header of the AppleDouble Header File looks like this:
  *
index 57aa1c7de5979a3bb36c502aceca45ccc19f2a25..f7e676c05554e374369b0909de20f713e0cec2ad 100644 (file)
@@ -21,8 +21,6 @@
 #define CNID_ERR_CLOSE 0x80000004   /* the db was not open */
 #define CNID_ERR_MAX   0x80000005
 
-typedef u_int32_t cnid_t;
-
 /* cnid_open.c */
 extern void *cnid_open __P((const char *, mode_t));
 
index a1a689835b0bd11e6a3ef6462f5d9c3e9229b3b8..4d7781719a70f73ca1a0af98d81fc8fc61e18f00 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ad_open.c,v 1.28 2003-02-17 06:26:53 didg Exp $
+ * $Id: ad_open.c,v 1.29 2003-03-09 19:55:35 didg Exp $
  *
  * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu)
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
@@ -199,7 +199,7 @@ static __inline__ int ad_v1tov2(struct adouble *ad, const char *path)
 #define SHIFTDATA (AD_DATASZ2 - AD_DATASZ1)
 
   /* bail if we can't get a lock */
-  if (ad_tmplock(ad, ADEID_RFORK, ADLOCK_WR, 0, 0) < 0) 
+  if (ad_tmplock(ad, ADEID_RFORK, ADLOCK_WR, 0, 0, 0) < 0) 
     goto bail_err;
   
   if ((fd = open(path, O_RDWR)) < 0) 
@@ -224,6 +224,9 @@ static __inline__ int ad_v1tov2(struct adouble *ad, const char *path)
   memmove(buf + off + SHIFTDATA, buf + off, 
          ad->ad_eid[ADEID_RFORK].ade_len);
   
+  munmap(buf, st.st_size + SHIFTDATA);
+  close(fd);
+
   /* now, fix up our copy of the header */
   memset(ad->ad_filler, 0, sizeof(ad->ad_filler));
   
@@ -254,7 +257,7 @@ static __inline__ int ad_v1tov2(struct adouble *ad, const char *path)
   ad->ad_version = AD_VERSION2;
   
   /* move our data buffer to make space for the new entries. */
-  memmove(buf + ADEDOFF_NAME_V2, buf + ADEDOFF_NAME_V1,
+  memmove(ad->ad_data + ADEDOFF_NAME_V2, ad->ad_data + ADEDOFF_NAME_V1,
          ADEDOFF_RFORK_V1 - ADEDOFF_NAME_V1);
   
   /* now, fill in the space with appropriate stuff. we're
@@ -267,10 +270,8 @@ static __inline__ int ad_v1tov2(struct adouble *ad, const char *path)
   memset(ad_entry(ad, ADEID_PRODOSFILEI), 0, ADEDLEN_PRODOSFILEI);
   
   /* rebuild the header and cleanup */
-  ad_rebuild_header(ad);
-  munmap(buf, st.st_size + SHIFTDATA);
-  close(fd);
-  ad_tmplock(ad, ADEID_RFORK, ADLOCK_CLR, 0, 0);
+  ad_flush(ad, ADFLAGS_HF );
+  ad_tmplock(ad, ADEID_RFORK, ADLOCK_CLR, 0, 0, 0);
 
   return 0;
   
@@ -279,7 +280,7 @@ bail_truncate:
 bail_open:
   close(fd);
 bail_lock:
-  ad_tmplock(ad, ADEID_RFORK, ADLOCK_CLR, 0, 0);
+  ad_tmplock(ad, ADEID_RFORK, ADLOCK_CLR, 0, 0, 0);
 bail_err:
   return -1;
 }
index dab7b8d87d8ab88ee03e48d97bbb9942d4c38e78..39e07a48c0b37b01d3b9b484874a925bd0c4939e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: cnid_close.c,v 1.28 2003-01-04 20:49:33 jmarcus Exp $
+ * $Id: cnid_close.c,v 1.29 2003-03-09 19:55:35 didg Exp $
  */
 
 #ifdef HAVE_CONFIG_H
@@ -19,9 +19,8 @@
 #include <errno.h>
 #include <string.h>
 
-#include <atalk/cnid.h>
-
 #include "cnid_private.h"
+#include <atalk/cnid.h>
 
 void cnid_close(void *CNID) {
     CNID_private *db;