Home | History | Annotate | Line # | Download | only in msdosfs
msdosfs_conv.c revision 1.11
      1  1.11   mlelstv /*	$NetBSD: msdosfs_conv.c,v 1.11 2016/01/30 09:59:27 mlelstv Exp $	*/
      2   1.1  jdolecek 
      3   1.1  jdolecek /*-
      4   1.1  jdolecek  * Copyright (C) 1995, 1997 Wolfgang Solfrank.
      5   1.1  jdolecek  * Copyright (C) 1995, 1997 TooLs GmbH.
      6   1.1  jdolecek  * All rights reserved.
      7   1.1  jdolecek  * Original code by Paul Popelka (paulp (at) uts.amdahl.com) (see below).
      8   1.1  jdolecek  *
      9   1.1  jdolecek  * Redistribution and use in source and binary forms, with or without
     10   1.1  jdolecek  * modification, are permitted provided that the following conditions
     11   1.1  jdolecek  * are met:
     12   1.1  jdolecek  * 1. Redistributions of source code must retain the above copyright
     13   1.1  jdolecek  *    notice, this list of conditions and the following disclaimer.
     14   1.1  jdolecek  * 2. Redistributions in binary form must reproduce the above copyright
     15   1.1  jdolecek  *    notice, this list of conditions and the following disclaimer in the
     16   1.1  jdolecek  *    documentation and/or other materials provided with the distribution.
     17   1.1  jdolecek  * 3. All advertising materials mentioning features or use of this software
     18   1.1  jdolecek  *    must display the following acknowledgement:
     19   1.1  jdolecek  *	This product includes software developed by TooLs GmbH.
     20   1.1  jdolecek  * 4. The name of TooLs GmbH may not be used to endorse or promote products
     21   1.1  jdolecek  *    derived from this software without specific prior written permission.
     22   1.1  jdolecek  *
     23   1.1  jdolecek  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
     24   1.1  jdolecek  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     25   1.1  jdolecek  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     26   1.1  jdolecek  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     27   1.1  jdolecek  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     28   1.1  jdolecek  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     29   1.1  jdolecek  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     30   1.1  jdolecek  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     31   1.1  jdolecek  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     32   1.1  jdolecek  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     33   1.1  jdolecek  */
     34   1.1  jdolecek /*
     35   1.1  jdolecek  * Written by Paul Popelka (paulp (at) uts.amdahl.com)
     36   1.1  jdolecek  *
     37   1.1  jdolecek  * You can do anything you want with this software, just don't say you wrote
     38   1.1  jdolecek  * it, and don't remove this notice.
     39   1.1  jdolecek  *
     40   1.1  jdolecek  * This software is provided "as is".
     41   1.1  jdolecek  *
     42   1.1  jdolecek  * The author supplies this software to be publicly redistributed on the
     43   1.1  jdolecek  * understanding that the author is not responsible for the correct
     44   1.1  jdolecek  * functioning of this software in any circumstances and is not liable for
     45   1.1  jdolecek  * any damages caused by this software.
     46   1.1  jdolecek  *
     47   1.1  jdolecek  * October 1992
     48  1.11   mlelstv  *
     49  1.11   mlelstv  *
     50  1.11   mlelstv  * Unicode 5.0 case folding taken from
     51  1.11   mlelstv  *
     52  1.11   mlelstv  * http://www.unicode.org/Public/5.0.0/ucd/CaseFolding.txt
     53  1.11   mlelstv  *
     54  1.11   mlelstv  * Unicode Character Database
     55  1.11   mlelstv  * Copyright (c) 1991-2006 Unicode, Inc.
     56  1.11   mlelstv  * For terms of use, see http://www.unicode.org/terms_of_use.html
     57  1.11   mlelstv  * For documentation, see UCD.html
     58   1.1  jdolecek  */
     59   1.1  jdolecek 
     60   1.8  christos #if HAVE_NBTOOL_CONFIG_H
     61   1.8  christos #include "nbtool_config.h"
     62   1.8  christos #endif
     63   1.8  christos 
     64   1.1  jdolecek #include <sys/cdefs.h>
     65  1.11   mlelstv __KERNEL_RCSID(0, "$NetBSD: msdosfs_conv.c,v 1.11 2016/01/30 09:59:27 mlelstv Exp $");
     66   1.1  jdolecek 
     67   1.1  jdolecek /*
     68   1.1  jdolecek  * System include files.
     69   1.1  jdolecek  */
     70   1.1  jdolecek #include <sys/param.h>
     71   1.9  christos #include <sys/time.h>
     72  1.11   mlelstv #include <sys/endian.h>
     73   1.9  christos #ifdef _KERNEL
     74   1.9  christos #include <sys/dirent.h>
     75   1.1  jdolecek #include <sys/systm.h>
     76   1.1  jdolecek #include <sys/kernel.h>
     77   1.1  jdolecek #include <sys/vnode.h>
     78   1.9  christos #else
     79   1.8  christos #include <stdio.h>
     80  1.10    martin #include <string.h>
     81   1.9  christos #include <dirent.h>
     82   1.9  christos #include <sys/queue.h>
     83   1.8  christos #endif
     84  1.10    martin #include <dev/clock_subr.h>
     85   1.1  jdolecek 
     86   1.1  jdolecek /*
     87   1.1  jdolecek  * MSDOSFS include files.
     88   1.1  jdolecek  */
     89   1.1  jdolecek #include <fs/msdosfs/direntry.h>
     90   1.1  jdolecek #include <fs/msdosfs/denode.h>
     91   1.1  jdolecek 
     92  1.11   mlelstv static int invalidname(const u_int16_t *, int);
     93  1.11   mlelstv 
     94  1.11   mlelstv static int ucs2utf8(const u_int16_t *, u_int8_t *, int);
     95  1.11   mlelstv static int utf8ucs2(const u_int8_t *, int, u_int16_t *);
     96  1.11   mlelstv 
     97  1.11   mlelstv static int ucs2utf8str(const u_int16_t *, int, u_int8_t *, int);
     98  1.11   mlelstv static int utf8ucs2str(const u_int8_t *, int, u_int16_t *, int);
     99  1.11   mlelstv static int ucs2char8str(const u_int16_t *, int, u_int8_t *, int);
    100  1.11   mlelstv static int char8ucs2str(const u_int8_t *, int, u_int16_t *, int);
    101  1.11   mlelstv 
    102  1.11   mlelstv static void ucs2pad(u_int16_t *, int, int);
    103  1.11   mlelstv 
    104  1.11   mlelstv static u_int16_t ucs2fold(u_int16_t);
    105  1.11   mlelstv static int ucs2match(u_int16_t *, u_int16_t *, int n);
    106  1.11   mlelstv static int char8match(u_int16_t *, u_int16_t *, int n);
    107  1.11   mlelstv 
    108   1.1  jdolecek /*
    109  1.10    martin  * The number of seconds between Jan 1, 1970 and Jan 1, 1980. In that
    110  1.10    martin  * interval there were 8 regular years and 2 leap years.
    111   1.1  jdolecek  */
    112  1.10    martin #define	DOSBIASYEAR	1980
    113  1.10    martin #define	SECONDSTO1980	(((8 * 365) + (2 * 366)) * (24 * 60 * 60))
    114   1.1  jdolecek /*
    115  1.10    martin  * msdos fs can not store dates beyound the year 2234
    116   1.1  jdolecek  */
    117  1.10    martin #define DOSMAXYEAR	((DD_YEAR_MASK >> DD_YEAR_SHIFT) + DOSBIASYEAR)
    118   1.1  jdolecek 
    119   1.1  jdolecek /*
    120   1.1  jdolecek  * Convert the unix version of time to dos's idea of time to be used in
    121   1.1  jdolecek  * file timestamps. The passed in unix time is assumed to be in GMT.
    122   1.1  jdolecek  */
    123   1.1  jdolecek void
    124   1.6       dsl unix2dostime(const struct timespec *tsp, int gmtoff, u_int16_t *ddp, u_int16_t *dtp, u_int8_t *dhp)
    125   1.1  jdolecek {
    126   1.1  jdolecek 	u_long t;
    127  1.10    martin 	struct clock_ymdhms ymd;
    128  1.10    martin 
    129  1.10    martin 	t = tsp->tv_sec + gmtoff; /* time zone correction */
    130   1.1  jdolecek 
    131   1.1  jdolecek 	/*
    132  1.10    martin 	 * DOS timestamps can not represent dates before 1980.
    133  1.10    martin 	 */
    134  1.10    martin 	if (t < SECONDSTO1980)
    135  1.10    martin 		goto invalid_dos_date;
    136  1.10    martin 
    137  1.10    martin 	/*
    138  1.10    martin 	 * DOS granularity is 2 seconds
    139   1.1  jdolecek 	 */
    140   1.1  jdolecek 	t &= ~1;
    141  1.10    martin 
    142  1.10    martin 	/*
    143  1.10    martin 	 * Convert to year/month/day/.. format
    144  1.10    martin 	 */
    145  1.10    martin 	clock_secs_to_ymdhms(t, &ymd);
    146  1.10    martin 	if (ymd.dt_year > DOSMAXYEAR)
    147  1.10    martin 		goto invalid_dos_date;
    148  1.10    martin 
    149  1.10    martin 	/*
    150  1.10    martin 	 * Now transform to DOS format
    151  1.10    martin 	 */
    152  1.10    martin 	*ddp = (ymd.dt_day << DD_DAY_SHIFT)
    153  1.10    martin 	    + (ymd.dt_mon << DD_MONTH_SHIFT)
    154  1.10    martin 	    + ((ymd.dt_year - DOSBIASYEAR) << DD_YEAR_SHIFT);
    155  1.10    martin 	if (dhp)
    156  1.10    martin 		*dhp = (tsp->tv_sec & 1) * 100 + tsp->tv_nsec / 10000000;
    157  1.10    martin 	if (dtp)
    158  1.10    martin 		*dtp = (((t / 2) % 30) << DT_2SECONDS_SHIFT)
    159   1.1  jdolecek 		    + (((t / 60) % 60) << DT_MINUTES_SHIFT)
    160   1.1  jdolecek 		    + (((t / 3600) % 24) << DT_HOURS_SHIFT);
    161  1.10    martin 	return;
    162   1.1  jdolecek 
    163  1.10    martin invalid_dos_date:
    164  1.10    martin 	*ddp = 0;
    165   1.1  jdolecek 	if (dtp)
    166  1.10    martin 		*dtp = 0;
    167   1.1  jdolecek 	if (dhp)
    168  1.10    martin 		*dhp = 0;
    169   1.1  jdolecek }
    170   1.1  jdolecek 
    171   1.1  jdolecek /*
    172   1.1  jdolecek  * Convert from dos' idea of time to unix'. This will probably only be
    173   1.1  jdolecek  * called from the stat(), and fstat() system calls and so probably need
    174   1.1  jdolecek  * not be too efficient.
    175   1.1  jdolecek  */
    176   1.1  jdolecek void
    177   1.6       dsl dos2unixtime(u_int dd, u_int dt, u_int dh, int gmtoff, struct timespec *tsp)
    178   1.1  jdolecek {
    179  1.10    martin 	time_t seconds;
    180  1.10    martin 	struct clock_ymdhms ymd;
    181   1.1  jdolecek 
    182   1.1  jdolecek 	if (dd == 0) {
    183   1.1  jdolecek 		/*
    184   1.1  jdolecek 		 * Uninitialized field, return the epoch.
    185   1.1  jdolecek 		 */
    186   1.1  jdolecek 		tsp->tv_sec = 0;
    187   1.1  jdolecek 		tsp->tv_nsec = 0;
    188   1.1  jdolecek 		return;
    189   1.1  jdolecek 	}
    190  1.10    martin 
    191  1.10    martin 	memset(&ymd, 0, sizeof(ymd));
    192  1.10    martin 	ymd.dt_year = ((dd & DD_YEAR_MASK) >> DD_YEAR_SHIFT) + 1980 ;
    193  1.10    martin 	ymd.dt_mon = ((dd & DD_MONTH_MASK) >> DD_MONTH_SHIFT);
    194  1.10    martin 	ymd.dt_day = ((dd & DD_DAY_MASK) >> DD_DAY_SHIFT);
    195  1.10    martin 	ymd.dt_hour = (dt & DT_HOURS_MASK) >> DT_HOURS_SHIFT;
    196  1.10    martin 	ymd.dt_min = (dt & DT_MINUTES_MASK) >> DT_MINUTES_SHIFT;
    197  1.10    martin 	ymd.dt_sec = ((dt & DT_2SECONDS_MASK) >> DT_2SECONDS_SHIFT) * 2;
    198  1.10    martin 
    199  1.10    martin 	seconds = clock_ymdhms_to_secs(&ymd);
    200  1.10    martin 
    201  1.10    martin 	tsp->tv_sec = seconds;
    202   1.2    itojun 	tsp->tv_sec -= gmtoff;	/* time zone correction */
    203   1.1  jdolecek 	tsp->tv_nsec = (dh % 100) * 10000000;
    204   1.1  jdolecek }
    205   1.1  jdolecek 
    206   1.1  jdolecek static const u_char
    207   1.1  jdolecek unix2dos[256] = {
    208   1.1  jdolecek 	0,    0,    0,    0,    0,    0,    0,    0,	/* 00-07 */
    209   1.1  jdolecek 	0,    0,    0,    0,    0,    0,    0,    0,	/* 08-0f */
    210   1.1  jdolecek 	0,    0,    0,    0,    0,    0,    0,    0,	/* 10-17 */
    211   1.1  jdolecek 	0,    0,    0,    0,    0,    0,    0,    0,	/* 18-1f */
    212   1.1  jdolecek 	0,    '!',  0,    '#',  '$',  '%',  '&',  '\'',	/* 20-27 */
    213   1.1  jdolecek 	'(',  ')',  0,    '+',  0,    '-',  0,    0,	/* 28-2f */
    214   1.1  jdolecek 	'0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',	/* 30-37 */
    215   1.1  jdolecek 	'8',  '9',  0,    0,    0,    0,    0,    0,	/* 38-3f */
    216   1.1  jdolecek 	'@',  'A',  'B',  'C',  'D',  'E',  'F',  'G',	/* 40-47 */
    217   1.1  jdolecek 	'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',	/* 48-4f */
    218   1.1  jdolecek 	'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',	/* 50-57 */
    219   1.1  jdolecek 	'X',  'Y',  'Z',  0,    0,    0,    '^',  '_',	/* 58-5f */
    220   1.1  jdolecek 	'`',  'A',  'B',  'C',  'D',  'E',  'F',  'G',	/* 60-67 */
    221   1.1  jdolecek 	'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',	/* 68-6f */
    222   1.1  jdolecek 	'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',	/* 70-77 */
    223   1.1  jdolecek 	'X',  'Y',  'Z',  '{',  0,    '}',  '~',  0,	/* 78-7f */
    224   1.1  jdolecek 	0,    0,    0,    0,    0,    0,    0,    0,	/* 80-87 */
    225   1.1  jdolecek 	0,    0,    0,    0,    0,    0,    0,    0,	/* 88-8f */
    226   1.1  jdolecek 	0,    0,    0,    0,    0,    0,    0,    0,	/* 90-97 */
    227   1.1  jdolecek 	0,    0,    0,    0,    0,    0,    0,    0,	/* 98-9f */
    228   1.1  jdolecek 	0,    0xad, 0xbd, 0x9c, 0xcf, 0xbe, 0xdd, 0xf5,	/* a0-a7 */
    229   1.1  jdolecek 	0xf9, 0xb8, 0xa6, 0xae, 0xaa, 0xf0, 0xa9, 0xee,	/* a8-af */
    230   1.1  jdolecek 	0xf8, 0xf1, 0xfd, 0xfc, 0xef, 0xe6, 0xf4, 0xfa,	/* b0-b7 */
    231   1.1  jdolecek 	0xf7, 0xfb, 0xa7, 0xaf, 0xac, 0xab, 0xf3, 0xa8,	/* b8-bf */
    232   1.1  jdolecek 	0xb7, 0xb5, 0xb6, 0xc7, 0x8e, 0x8f, 0x92, 0x80,	/* c0-c7 */
    233   1.1  jdolecek 	0xd4, 0x90, 0xd2, 0xd3, 0xde, 0xd6, 0xd7, 0xd8,	/* c8-cf */
    234   1.1  jdolecek 	0xd1, 0xa5, 0xe3, 0xe0, 0xe2, 0xe5, 0x99, 0x9e,	/* d0-d7 */
    235   1.1  jdolecek 	0x9d, 0xeb, 0xe9, 0xea, 0x9a, 0xed, 0xe8, 0xe1,	/* d8-df */
    236   1.1  jdolecek 	0xb7, 0xb5, 0xb6, 0xc7, 0x8e, 0x8f, 0x92, 0x80,	/* e0-e7 */
    237   1.1  jdolecek 	0xd4, 0x90, 0xd2, 0xd3, 0xde, 0xd6, 0xd7, 0xd8,	/* e8-ef */
    238   1.1  jdolecek 	0xd1, 0xa5, 0xe3, 0xe0, 0xe2, 0xe5, 0x99, 0xf6,	/* f0-f7 */
    239   1.1  jdolecek 	0x9d, 0xeb, 0xe9, 0xea, 0x9a, 0xed, 0xe8, 0x98,	/* f8-ff */
    240   1.1  jdolecek };
    241   1.1  jdolecek 
    242   1.1  jdolecek static const u_char
    243   1.1  jdolecek dos2unix[256] = {
    244   1.1  jdolecek 	 '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',	/* 00-07 */
    245   1.1  jdolecek 	 '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',	/* 08-0f */
    246   1.1  jdolecek 	 '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',	/* 10-17 */
    247   1.1  jdolecek 	 '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',	/* 18-1f */
    248   1.1  jdolecek 	 ' ',  '!',  '"',  '#',  '$',  '%',  '&', '\'',	/* 20-27 */
    249   1.1  jdolecek 	 '(',  ')',  '*',  '+',  ',',  '-',  '.',  '/',	/* 28-2f */
    250   1.1  jdolecek 	 '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',	/* 30-37 */
    251   1.1  jdolecek 	 '8',  '9',  ':',  ';',  '<',  '=',  '>',  '?',	/* 38-3f */
    252   1.1  jdolecek 	 '@',  'A',  'B',  'C',  'D',  'E',  'F',  'G',	/* 40-47 */
    253   1.1  jdolecek 	 'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',	/* 48-4f */
    254   1.1  jdolecek 	 'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',	/* 50-57 */
    255   1.1  jdolecek 	 'X',  'Y',  'Z',  '[', '\\',  ']',  '^',  '_',	/* 58-5f */
    256   1.1  jdolecek 	 '`',  'a',  'b',  'c',  'd',  'e',  'f',  'g',	/* 60-67 */
    257   1.1  jdolecek 	 'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',	/* 68-6f */
    258   1.1  jdolecek 	 'p',  'q',  'r',  's',  't',  'u',  'v',  'w',	/* 70-77 */
    259   1.1  jdolecek 	 'x',  'y',  'z',  '{',  '|',  '}',  '~', 0x7f,	/* 78-7f */
    260   1.1  jdolecek 	0xc7, 0xfc, 0xe9, 0xe2, 0xe4, 0xe0, 0xe5, 0xe7,	/* 80-87 */
    261   1.1  jdolecek 	0xea, 0xeb, 0xe8, 0xef, 0xee, 0xec, 0xc4, 0xc5,	/* 88-8f */
    262   1.1  jdolecek 	0xc9, 0xe6, 0xc6, 0xf4, 0xf6, 0xf2, 0xfb, 0xf9,	/* 90-97 */
    263   1.1  jdolecek 	0xff, 0xd6, 0xdc, 0xf8, 0xa3, 0xd8, 0xd7,  '?',	/* 98-9f */
    264   1.1  jdolecek 	0xe1, 0xed, 0xf3, 0xfa, 0xf1, 0xd1, 0xaa, 0xba,	/* a0-a7 */
    265   1.1  jdolecek 	0xbf, 0xae, 0xac, 0xbd, 0xbc, 0xa1, 0xab, 0xbb,	/* a8-af */
    266   1.1  jdolecek 	 '?',  '?',  '?',  '?',  '?', 0xc1, 0xc2, 0xc0,	/* b0-b7 */
    267   1.1  jdolecek 	0xa9,  '?',  '?',  '?',  '?', 0xa2, 0xa5,  '?',	/* b8-bf */
    268   1.1  jdolecek 	 '?',  '?',  '?',  '?',  '?',  '?', 0xe3, 0xc3,	/* c0-c7 */
    269   1.1  jdolecek 	 '?',  '?',  '?',  '?',  '?',  '?',  '?', 0xa4,	/* c8-cf */
    270   1.1  jdolecek 	0xf0, 0xd0, 0xca, 0xcb, 0xc8,  '?', 0xcd, 0xce,	/* d0-d7 */
    271   1.1  jdolecek 	0xcf,  '?',  '?',  '?',  '?', 0xa6, 0xcc,  '?',	/* d8-df */
    272   1.1  jdolecek 	0xd3, 0xdf, 0xd4, 0xd2, 0xf5, 0xd5, 0xb5, 0xfe,	/* e0-e7 */
    273   1.1  jdolecek 	0xde, 0xda, 0xdb, 0xd9, 0xfd, 0xdd, 0xaf, 0x3f,	/* e8-ef */
    274   1.1  jdolecek 	0xad, 0xb1,  '?', 0xbe, 0xb6, 0xa7, 0xf7, 0xb8,	/* f0-f7 */
    275   1.1  jdolecek 	0xb0, 0xa8, 0xb7, 0xb9, 0xb3, 0xb2,  '?',  '?',	/* f8-ff */
    276   1.1  jdolecek };
    277   1.1  jdolecek 
    278   1.1  jdolecek static const u_char
    279   1.1  jdolecek u2l[256] = {
    280   1.1  jdolecek 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 00-07 */
    281   1.1  jdolecek 	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 08-0f */
    282   1.1  jdolecek 	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 10-17 */
    283   1.1  jdolecek 	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 18-1f */
    284   1.1  jdolecek 	 ' ',  '!',  '"',  '#',  '$',  '%',  '&', '\'', /* 20-27 */
    285   1.1  jdolecek 	 '(',  ')',  '*',  '+',  ',',  '-',  '.',  '/', /* 28-2f */
    286   1.1  jdolecek 	 '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7', /* 30-37 */
    287   1.1  jdolecek 	 '8',  '9',  ':',  ';',  '<',  '=',  '>',  '?', /* 38-3f */
    288   1.1  jdolecek 	 '@',  'a',  'b',  'c',  'd',  'e',  'f',  'g', /* 40-47 */
    289   1.1  jdolecek 	 'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o', /* 48-4f */
    290   1.1  jdolecek 	 'p',  'q',  'r',  's',  't',  'u',  'v',  'w', /* 50-57 */
    291   1.1  jdolecek 	 'x',  'y',  'z',  '[', '\\',  ']',  '^',  '_', /* 58-5f */
    292   1.1  jdolecek 	 '`',  'a',  'b',  'c',  'd',  'e',  'f',  'g', /* 60-67 */
    293   1.1  jdolecek 	 'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o', /* 68-6f */
    294   1.1  jdolecek 	 'p',  'q',  'r',  's',  't',  'u',  'v',  'w', /* 70-77 */
    295   1.1  jdolecek 	 'x',  'y',  'z',  '{',  '|',  '}',  '~', 0x7f, /* 78-7f */
    296   1.1  jdolecek 	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 80-87 */
    297   1.1  jdolecek 	0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 88-8f */
    298   1.1  jdolecek 	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 90-97 */
    299   1.1  jdolecek 	0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 98-9f */
    300   1.1  jdolecek 	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* a0-a7 */
    301   1.1  jdolecek 	0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* a8-af */
    302   1.1  jdolecek 	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* b0-b7 */
    303   1.1  jdolecek 	0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* b8-bf */
    304   1.1  jdolecek 	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* c0-c7 */
    305   1.1  jdolecek 	0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* c8-cf */
    306   1.1  jdolecek 	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xd7, /* d0-d7 */
    307   1.1  jdolecek 	0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xdf, /* d8-df */
    308   1.1  jdolecek 	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* e0-e7 */
    309   1.1  jdolecek 	0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* e8-ef */
    310   1.1  jdolecek 	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* f0-f7 */
    311   1.1  jdolecek 	0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* f8-ff */
    312   1.1  jdolecek };
    313   1.1  jdolecek 
    314  1.11   mlelstv /* Unicode case folding for codes 0x0000..0xffff */
    315  1.11   mlelstv static const u_int16_t
    316  1.11   mlelstv foldmap[] = {
    317  1.11   mlelstv 	0x0041, 0x0061, /* LATIN CAPITAL LETTER A */
    318  1.11   mlelstv 	0x0042, 0x0062, /* LATIN CAPITAL LETTER B */
    319  1.11   mlelstv 	0x0043, 0x0063, /* LATIN CAPITAL LETTER C */
    320  1.11   mlelstv 	0x0044, 0x0064, /* LATIN CAPITAL LETTER D */
    321  1.11   mlelstv 	0x0045, 0x0065, /* LATIN CAPITAL LETTER E */
    322  1.11   mlelstv 	0x0046, 0x0066, /* LATIN CAPITAL LETTER F */
    323  1.11   mlelstv 	0x0047, 0x0067, /* LATIN CAPITAL LETTER G */
    324  1.11   mlelstv 	0x0048, 0x0068, /* LATIN CAPITAL LETTER H */
    325  1.11   mlelstv 	0x0049, 0x0069, /* LATIN CAPITAL LETTER I */
    326  1.11   mlelstv 	0x004A, 0x006A, /* LATIN CAPITAL LETTER J */
    327  1.11   mlelstv 	0x004B, 0x006B, /* LATIN CAPITAL LETTER K */
    328  1.11   mlelstv 	0x004C, 0x006C, /* LATIN CAPITAL LETTER L */
    329  1.11   mlelstv 	0x004D, 0x006D, /* LATIN CAPITAL LETTER M */
    330  1.11   mlelstv 	0x004E, 0x006E, /* LATIN CAPITAL LETTER N */
    331  1.11   mlelstv 	0x004F, 0x006F, /* LATIN CAPITAL LETTER O */
    332  1.11   mlelstv 	0x0050, 0x0070, /* LATIN CAPITAL LETTER P */
    333  1.11   mlelstv 	0x0051, 0x0071, /* LATIN CAPITAL LETTER Q */
    334  1.11   mlelstv 	0x0052, 0x0072, /* LATIN CAPITAL LETTER R */
    335  1.11   mlelstv 	0x0053, 0x0073, /* LATIN CAPITAL LETTER S */
    336  1.11   mlelstv 	0x0054, 0x0074, /* LATIN CAPITAL LETTER T */
    337  1.11   mlelstv 	0x0055, 0x0075, /* LATIN CAPITAL LETTER U */
    338  1.11   mlelstv 	0x0056, 0x0076, /* LATIN CAPITAL LETTER V */
    339  1.11   mlelstv 	0x0057, 0x0077, /* LATIN CAPITAL LETTER W */
    340  1.11   mlelstv 	0x0058, 0x0078, /* LATIN CAPITAL LETTER X */
    341  1.11   mlelstv 	0x0059, 0x0079, /* LATIN CAPITAL LETTER Y */
    342  1.11   mlelstv 	0x005A, 0x007A, /* LATIN CAPITAL LETTER Z */
    343  1.11   mlelstv 	0x00B5, 0x03BC, /* MICRO SIGN */
    344  1.11   mlelstv 	0x00C0, 0x00E0, /* LATIN CAPITAL LETTER A WITH GRAVE */
    345  1.11   mlelstv 	0x00C1, 0x00E1, /* LATIN CAPITAL LETTER A WITH ACUTE */
    346  1.11   mlelstv 	0x00C2, 0x00E2, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
    347  1.11   mlelstv 	0x00C3, 0x00E3, /* LATIN CAPITAL LETTER A WITH TILDE */
    348  1.11   mlelstv 	0x00C4, 0x00E4, /* LATIN CAPITAL LETTER A WITH DIAERESIS */
    349  1.11   mlelstv 	0x00C5, 0x00E5, /* LATIN CAPITAL LETTER A WITH RING ABOVE */
    350  1.11   mlelstv 	0x00C6, 0x00E6, /* LATIN CAPITAL LETTER AE */
    351  1.11   mlelstv 	0x00C7, 0x00E7, /* LATIN CAPITAL LETTER C WITH CEDILLA */
    352  1.11   mlelstv 	0x00C8, 0x00E8, /* LATIN CAPITAL LETTER E WITH GRAVE */
    353  1.11   mlelstv 	0x00C9, 0x00E9, /* LATIN CAPITAL LETTER E WITH ACUTE */
    354  1.11   mlelstv 	0x00CA, 0x00EA, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
    355  1.11   mlelstv 	0x00CB, 0x00EB, /* LATIN CAPITAL LETTER E WITH DIAERESIS */
    356  1.11   mlelstv 	0x00CC, 0x00EC, /* LATIN CAPITAL LETTER I WITH GRAVE */
    357  1.11   mlelstv 	0x00CD, 0x00ED, /* LATIN CAPITAL LETTER I WITH ACUTE */
    358  1.11   mlelstv 	0x00CE, 0x00EE, /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
    359  1.11   mlelstv 	0x00CF, 0x00EF, /* LATIN CAPITAL LETTER I WITH DIAERESIS */
    360  1.11   mlelstv 	0x00D0, 0x00F0, /* LATIN CAPITAL LETTER ETH */
    361  1.11   mlelstv 	0x00D1, 0x00F1, /* LATIN CAPITAL LETTER N WITH TILDE */
    362  1.11   mlelstv 	0x00D2, 0x00F2, /* LATIN CAPITAL LETTER O WITH GRAVE */
    363  1.11   mlelstv 	0x00D3, 0x00F3, /* LATIN CAPITAL LETTER O WITH ACUTE */
    364  1.11   mlelstv 	0x00D4, 0x00F4, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
    365  1.11   mlelstv 	0x00D5, 0x00F5, /* LATIN CAPITAL LETTER O WITH TILDE */
    366  1.11   mlelstv 	0x00D6, 0x00F6, /* LATIN CAPITAL LETTER O WITH DIAERESIS */
    367  1.11   mlelstv 	0x00D8, 0x00F8, /* LATIN CAPITAL LETTER O WITH STROKE */
    368  1.11   mlelstv 	0x00D9, 0x00F9, /* LATIN CAPITAL LETTER U WITH GRAVE */
    369  1.11   mlelstv 	0x00DA, 0x00FA, /* LATIN CAPITAL LETTER U WITH ACUTE */
    370  1.11   mlelstv 	0x00DB, 0x00FB, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
    371  1.11   mlelstv 	0x00DC, 0x00FC, /* LATIN CAPITAL LETTER U WITH DIAERESIS */
    372  1.11   mlelstv 	0x00DD, 0x00FD, /* LATIN CAPITAL LETTER Y WITH ACUTE */
    373  1.11   mlelstv 	0x00DE, 0x00FE, /* LATIN CAPITAL LETTER THORN */
    374  1.11   mlelstv 	0x0100, 0x0101, /* LATIN CAPITAL LETTER A WITH MACRON */
    375  1.11   mlelstv 	0x0102, 0x0103, /* LATIN CAPITAL LETTER A WITH BREVE */
    376  1.11   mlelstv 	0x0104, 0x0105, /* LATIN CAPITAL LETTER A WITH OGONEK */
    377  1.11   mlelstv 	0x0106, 0x0107, /* LATIN CAPITAL LETTER C WITH ACUTE */
    378  1.11   mlelstv 	0x0108, 0x0109, /* LATIN CAPITAL LETTER C WITH CIRCUMFLEX */
    379  1.11   mlelstv 	0x010A, 0x010B, /* LATIN CAPITAL LETTER C WITH DOT ABOVE */
    380  1.11   mlelstv 	0x010C, 0x010D, /* LATIN CAPITAL LETTER C WITH CARON */
    381  1.11   mlelstv 	0x010E, 0x010F, /* LATIN CAPITAL LETTER D WITH CARON */
    382  1.11   mlelstv 	0x0110, 0x0111, /* LATIN CAPITAL LETTER D WITH STROKE */
    383  1.11   mlelstv 	0x0112, 0x0113, /* LATIN CAPITAL LETTER E WITH MACRON */
    384  1.11   mlelstv 	0x0114, 0x0115, /* LATIN CAPITAL LETTER E WITH BREVE */
    385  1.11   mlelstv 	0x0116, 0x0117, /* LATIN CAPITAL LETTER E WITH DOT ABOVE */
    386  1.11   mlelstv 	0x0118, 0x0119, /* LATIN CAPITAL LETTER E WITH OGONEK */
    387  1.11   mlelstv 	0x011A, 0x011B, /* LATIN CAPITAL LETTER E WITH CARON */
    388  1.11   mlelstv 	0x011C, 0x011D, /* LATIN CAPITAL LETTER G WITH CIRCUMFLEX */
    389  1.11   mlelstv 	0x011E, 0x011F, /* LATIN CAPITAL LETTER G WITH BREVE */
    390  1.11   mlelstv 	0x0120, 0x0121, /* LATIN CAPITAL LETTER G WITH DOT ABOVE */
    391  1.11   mlelstv 	0x0122, 0x0123, /* LATIN CAPITAL LETTER G WITH CEDILLA */
    392  1.11   mlelstv 	0x0124, 0x0125, /* LATIN CAPITAL LETTER H WITH CIRCUMFLEX */
    393  1.11   mlelstv 	0x0126, 0x0127, /* LATIN CAPITAL LETTER H WITH STROKE */
    394  1.11   mlelstv 	0x0128, 0x0129, /* LATIN CAPITAL LETTER I WITH TILDE */
    395  1.11   mlelstv 	0x012A, 0x012B, /* LATIN CAPITAL LETTER I WITH MACRON */
    396  1.11   mlelstv 	0x012C, 0x012D, /* LATIN CAPITAL LETTER I WITH BREVE */
    397  1.11   mlelstv 	0x012E, 0x012F, /* LATIN CAPITAL LETTER I WITH OGONEK */
    398  1.11   mlelstv 	0x0132, 0x0133, /* LATIN CAPITAL LIGATURE IJ */
    399  1.11   mlelstv 	0x0134, 0x0135, /* LATIN CAPITAL LETTER J WITH CIRCUMFLEX */
    400  1.11   mlelstv 	0x0136, 0x0137, /* LATIN CAPITAL LETTER K WITH CEDILLA */
    401  1.11   mlelstv 	0x0139, 0x013A, /* LATIN CAPITAL LETTER L WITH ACUTE */
    402  1.11   mlelstv 	0x013B, 0x013C, /* LATIN CAPITAL LETTER L WITH CEDILLA */
    403  1.11   mlelstv 	0x013D, 0x013E, /* LATIN CAPITAL LETTER L WITH CARON */
    404  1.11   mlelstv 	0x013F, 0x0140, /* LATIN CAPITAL LETTER L WITH MIDDLE DOT */
    405  1.11   mlelstv 	0x0141, 0x0142, /* LATIN CAPITAL LETTER L WITH STROKE */
    406  1.11   mlelstv 	0x0143, 0x0144, /* LATIN CAPITAL LETTER N WITH ACUTE */
    407  1.11   mlelstv 	0x0145, 0x0146, /* LATIN CAPITAL LETTER N WITH CEDILLA */
    408  1.11   mlelstv 	0x0147, 0x0148, /* LATIN CAPITAL LETTER N WITH CARON */
    409  1.11   mlelstv 	0x014A, 0x014B, /* LATIN CAPITAL LETTER ENG */
    410  1.11   mlelstv 	0x014C, 0x014D, /* LATIN CAPITAL LETTER O WITH MACRON */
    411  1.11   mlelstv 	0x014E, 0x014F, /* LATIN CAPITAL LETTER O WITH BREVE */
    412  1.11   mlelstv 	0x0150, 0x0151, /* LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */
    413  1.11   mlelstv 	0x0152, 0x0153, /* LATIN CAPITAL LIGATURE OE */
    414  1.11   mlelstv 	0x0154, 0x0155, /* LATIN CAPITAL LETTER R WITH ACUTE */
    415  1.11   mlelstv 	0x0156, 0x0157, /* LATIN CAPITAL LETTER R WITH CEDILLA */
    416  1.11   mlelstv 	0x0158, 0x0159, /* LATIN CAPITAL LETTER R WITH CARON */
    417  1.11   mlelstv 	0x015A, 0x015B, /* LATIN CAPITAL LETTER S WITH ACUTE */
    418  1.11   mlelstv 	0x015C, 0x015D, /* LATIN CAPITAL LETTER S WITH CIRCUMFLEX */
    419  1.11   mlelstv 	0x015E, 0x015F, /* LATIN CAPITAL LETTER S WITH CEDILLA */
    420  1.11   mlelstv 	0x0160, 0x0161, /* LATIN CAPITAL LETTER S WITH CARON */
    421  1.11   mlelstv 	0x0162, 0x0163, /* LATIN CAPITAL LETTER T WITH CEDILLA */
    422  1.11   mlelstv 	0x0164, 0x0165, /* LATIN CAPITAL LETTER T WITH CARON */
    423  1.11   mlelstv 	0x0166, 0x0167, /* LATIN CAPITAL LETTER T WITH STROKE */
    424  1.11   mlelstv 	0x0168, 0x0169, /* LATIN CAPITAL LETTER U WITH TILDE */
    425  1.11   mlelstv 	0x016A, 0x016B, /* LATIN CAPITAL LETTER U WITH MACRON */
    426  1.11   mlelstv 	0x016C, 0x016D, /* LATIN CAPITAL LETTER U WITH BREVE */
    427  1.11   mlelstv 	0x016E, 0x016F, /* LATIN CAPITAL LETTER U WITH RING ABOVE */
    428  1.11   mlelstv 	0x0170, 0x0171, /* LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */
    429  1.11   mlelstv 	0x0172, 0x0173, /* LATIN CAPITAL LETTER U WITH OGONEK */
    430  1.11   mlelstv 	0x0174, 0x0175, /* LATIN CAPITAL LETTER W WITH CIRCUMFLEX */
    431  1.11   mlelstv 	0x0176, 0x0177, /* LATIN CAPITAL LETTER Y WITH CIRCUMFLEX */
    432  1.11   mlelstv 	0x0178, 0x00FF, /* LATIN CAPITAL LETTER Y WITH DIAERESIS */
    433  1.11   mlelstv 	0x0179, 0x017A, /* LATIN CAPITAL LETTER Z WITH ACUTE */
    434  1.11   mlelstv 	0x017B, 0x017C, /* LATIN CAPITAL LETTER Z WITH DOT ABOVE */
    435  1.11   mlelstv 	0x017D, 0x017E, /* LATIN CAPITAL LETTER Z WITH CARON */
    436  1.11   mlelstv 	0x017F, 0x0073, /* LATIN SMALL LETTER LONG S */
    437  1.11   mlelstv 	0x0181, 0x0253, /* LATIN CAPITAL LETTER B WITH HOOK */
    438  1.11   mlelstv 	0x0182, 0x0183, /* LATIN CAPITAL LETTER B WITH TOPBAR */
    439  1.11   mlelstv 	0x0184, 0x0185, /* LATIN CAPITAL LETTER TONE SIX */
    440  1.11   mlelstv 	0x0186, 0x0254, /* LATIN CAPITAL LETTER OPEN O */
    441  1.11   mlelstv 	0x0187, 0x0188, /* LATIN CAPITAL LETTER C WITH HOOK */
    442  1.11   mlelstv 	0x0189, 0x0256, /* LATIN CAPITAL LETTER AFRICAN D */
    443  1.11   mlelstv 	0x018A, 0x0257, /* LATIN CAPITAL LETTER D WITH HOOK */
    444  1.11   mlelstv 	0x018B, 0x018C, /* LATIN CAPITAL LETTER D WITH TOPBAR */
    445  1.11   mlelstv 	0x018E, 0x01DD, /* LATIN CAPITAL LETTER REVERSED E */
    446  1.11   mlelstv 	0x018F, 0x0259, /* LATIN CAPITAL LETTER SCHWA */
    447  1.11   mlelstv 	0x0190, 0x025B, /* LATIN CAPITAL LETTER OPEN E */
    448  1.11   mlelstv 	0x0191, 0x0192, /* LATIN CAPITAL LETTER F WITH HOOK */
    449  1.11   mlelstv 	0x0193, 0x0260, /* LATIN CAPITAL LETTER G WITH HOOK */
    450  1.11   mlelstv 	0x0194, 0x0263, /* LATIN CAPITAL LETTER GAMMA */
    451  1.11   mlelstv 	0x0196, 0x0269, /* LATIN CAPITAL LETTER IOTA */
    452  1.11   mlelstv 	0x0197, 0x0268, /* LATIN CAPITAL LETTER I WITH STROKE */
    453  1.11   mlelstv 	0x0198, 0x0199, /* LATIN CAPITAL LETTER K WITH HOOK */
    454  1.11   mlelstv 	0x019C, 0x026F, /* LATIN CAPITAL LETTER TURNED M */
    455  1.11   mlelstv 	0x019D, 0x0272, /* LATIN CAPITAL LETTER N WITH LEFT HOOK */
    456  1.11   mlelstv 	0x019F, 0x0275, /* LATIN CAPITAL LETTER O WITH MIDDLE TILDE */
    457  1.11   mlelstv 	0x01A0, 0x01A1, /* LATIN CAPITAL LETTER O WITH HORN */
    458  1.11   mlelstv 	0x01A2, 0x01A3, /* LATIN CAPITAL LETTER OI */
    459  1.11   mlelstv 	0x01A4, 0x01A5, /* LATIN CAPITAL LETTER P WITH HOOK */
    460  1.11   mlelstv 	0x01A6, 0x0280, /* LATIN LETTER YR */
    461  1.11   mlelstv 	0x01A7, 0x01A8, /* LATIN CAPITAL LETTER TONE TWO */
    462  1.11   mlelstv 	0x01A9, 0x0283, /* LATIN CAPITAL LETTER ESH */
    463  1.11   mlelstv 	0x01AC, 0x01AD, /* LATIN CAPITAL LETTER T WITH HOOK */
    464  1.11   mlelstv 	0x01AE, 0x0288, /* LATIN CAPITAL LETTER T WITH RETROFLEX HOOK */
    465  1.11   mlelstv 	0x01AF, 0x01B0, /* LATIN CAPITAL LETTER U WITH HORN */
    466  1.11   mlelstv 	0x01B1, 0x028A, /* LATIN CAPITAL LETTER UPSILON */
    467  1.11   mlelstv 	0x01B2, 0x028B, /* LATIN CAPITAL LETTER V WITH HOOK */
    468  1.11   mlelstv 	0x01B3, 0x01B4, /* LATIN CAPITAL LETTER Y WITH HOOK */
    469  1.11   mlelstv 	0x01B5, 0x01B6, /* LATIN CAPITAL LETTER Z WITH STROKE */
    470  1.11   mlelstv 	0x01B7, 0x0292, /* LATIN CAPITAL LETTER EZH */
    471  1.11   mlelstv 	0x01B8, 0x01B9, /* LATIN CAPITAL LETTER EZH REVERSED */
    472  1.11   mlelstv 	0x01BC, 0x01BD, /* LATIN CAPITAL LETTER TONE FIVE */
    473  1.11   mlelstv 	0x01C4, 0x01C6, /* LATIN CAPITAL LETTER DZ WITH CARON */
    474  1.11   mlelstv 	0x01C5, 0x01C6, /* LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON */
    475  1.11   mlelstv 	0x01C7, 0x01C9, /* LATIN CAPITAL LETTER LJ */
    476  1.11   mlelstv 	0x01C8, 0x01C9, /* LATIN CAPITAL LETTER L WITH SMALL LETTER J */
    477  1.11   mlelstv 	0x01CA, 0x01CC, /* LATIN CAPITAL LETTER NJ */
    478  1.11   mlelstv 	0x01CB, 0x01CC, /* LATIN CAPITAL LETTER N WITH SMALL LETTER J */
    479  1.11   mlelstv 	0x01CD, 0x01CE, /* LATIN CAPITAL LETTER A WITH CARON */
    480  1.11   mlelstv 	0x01CF, 0x01D0, /* LATIN CAPITAL LETTER I WITH CARON */
    481  1.11   mlelstv 	0x01D1, 0x01D2, /* LATIN CAPITAL LETTER O WITH CARON */
    482  1.11   mlelstv 	0x01D3, 0x01D4, /* LATIN CAPITAL LETTER U WITH CARON */
    483  1.11   mlelstv 	0x01D5, 0x01D6, /* LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON */
    484  1.11   mlelstv 	0x01D7, 0x01D8, /* LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE */
    485  1.11   mlelstv 	0x01D9, 0x01DA, /* LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON */
    486  1.11   mlelstv 	0x01DB, 0x01DC, /* LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE */
    487  1.11   mlelstv 	0x01DE, 0x01DF, /* LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON */
    488  1.11   mlelstv 	0x01E0, 0x01E1, /* LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON */
    489  1.11   mlelstv 	0x01E2, 0x01E3, /* LATIN CAPITAL LETTER AE WITH MACRON */
    490  1.11   mlelstv 	0x01E4, 0x01E5, /* LATIN CAPITAL LETTER G WITH STROKE */
    491  1.11   mlelstv 	0x01E6, 0x01E7, /* LATIN CAPITAL LETTER G WITH CARON */
    492  1.11   mlelstv 	0x01E8, 0x01E9, /* LATIN CAPITAL LETTER K WITH CARON */
    493  1.11   mlelstv 	0x01EA, 0x01EB, /* LATIN CAPITAL LETTER O WITH OGONEK */
    494  1.11   mlelstv 	0x01EC, 0x01ED, /* LATIN CAPITAL LETTER O WITH OGONEK AND MACRON */
    495  1.11   mlelstv 	0x01EE, 0x01EF, /* LATIN CAPITAL LETTER EZH WITH CARON */
    496  1.11   mlelstv 	0x01F1, 0x01F3, /* LATIN CAPITAL LETTER DZ */
    497  1.11   mlelstv 	0x01F2, 0x01F3, /* LATIN CAPITAL LETTER D WITH SMALL LETTER Z */
    498  1.11   mlelstv 	0x01F4, 0x01F5, /* LATIN CAPITAL LETTER G WITH ACUTE */
    499  1.11   mlelstv 	0x01F6, 0x0195, /* LATIN CAPITAL LETTER HWAIR */
    500  1.11   mlelstv 	0x01F7, 0x01BF, /* LATIN CAPITAL LETTER WYNN */
    501  1.11   mlelstv 	0x01F8, 0x01F9, /* LATIN CAPITAL LETTER N WITH GRAVE */
    502  1.11   mlelstv 	0x01FA, 0x01FB, /* LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE */
    503  1.11   mlelstv 	0x01FC, 0x01FD, /* LATIN CAPITAL LETTER AE WITH ACUTE */
    504  1.11   mlelstv 	0x01FE, 0x01FF, /* LATIN CAPITAL LETTER O WITH STROKE AND ACUTE */
    505  1.11   mlelstv 	0x0200, 0x0201, /* LATIN CAPITAL LETTER A WITH DOUBLE GRAVE */
    506  1.11   mlelstv 	0x0202, 0x0203, /* LATIN CAPITAL LETTER A WITH INVERTED BREVE */
    507  1.11   mlelstv 	0x0204, 0x0205, /* LATIN CAPITAL LETTER E WITH DOUBLE GRAVE */
    508  1.11   mlelstv 	0x0206, 0x0207, /* LATIN CAPITAL LETTER E WITH INVERTED BREVE */
    509  1.11   mlelstv 	0x0208, 0x0209, /* LATIN CAPITAL LETTER I WITH DOUBLE GRAVE */
    510  1.11   mlelstv 	0x020A, 0x020B, /* LATIN CAPITAL LETTER I WITH INVERTED BREVE */
    511  1.11   mlelstv 	0x020C, 0x020D, /* LATIN CAPITAL LETTER O WITH DOUBLE GRAVE */
    512  1.11   mlelstv 	0x020E, 0x020F, /* LATIN CAPITAL LETTER O WITH INVERTED BREVE */
    513  1.11   mlelstv 	0x0210, 0x0211, /* LATIN CAPITAL LETTER R WITH DOUBLE GRAVE */
    514  1.11   mlelstv 	0x0212, 0x0213, /* LATIN CAPITAL LETTER R WITH INVERTED BREVE */
    515  1.11   mlelstv 	0x0214, 0x0215, /* LATIN CAPITAL LETTER U WITH DOUBLE GRAVE */
    516  1.11   mlelstv 	0x0216, 0x0217, /* LATIN CAPITAL LETTER U WITH INVERTED BREVE */
    517  1.11   mlelstv 	0x0218, 0x0219, /* LATIN CAPITAL LETTER S WITH COMMA BELOW */
    518  1.11   mlelstv 	0x021A, 0x021B, /* LATIN CAPITAL LETTER T WITH COMMA BELOW */
    519  1.11   mlelstv 	0x021C, 0x021D, /* LATIN CAPITAL LETTER YOGH */
    520  1.11   mlelstv 	0x021E, 0x021F, /* LATIN CAPITAL LETTER H WITH CARON */
    521  1.11   mlelstv 	0x0220, 0x019E, /* LATIN CAPITAL LETTER N WITH LONG RIGHT LEG */
    522  1.11   mlelstv 	0x0222, 0x0223, /* LATIN CAPITAL LETTER OU */
    523  1.11   mlelstv 	0x0224, 0x0225, /* LATIN CAPITAL LETTER Z WITH HOOK */
    524  1.11   mlelstv 	0x0226, 0x0227, /* LATIN CAPITAL LETTER A WITH DOT ABOVE */
    525  1.11   mlelstv 	0x0228, 0x0229, /* LATIN CAPITAL LETTER E WITH CEDILLA */
    526  1.11   mlelstv 	0x022A, 0x022B, /* LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON */
    527  1.11   mlelstv 	0x022C, 0x022D, /* LATIN CAPITAL LETTER O WITH TILDE AND MACRON */
    528  1.11   mlelstv 	0x022E, 0x022F, /* LATIN CAPITAL LETTER O WITH DOT ABOVE */
    529  1.11   mlelstv 	0x0230, 0x0231, /* LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON */
    530  1.11   mlelstv 	0x0232, 0x0233, /* LATIN CAPITAL LETTER Y WITH MACRON */
    531  1.11   mlelstv 	0x023A, 0x2C65, /* LATIN CAPITAL LETTER A WITH STROKE */
    532  1.11   mlelstv 	0x023B, 0x023C, /* LATIN CAPITAL LETTER C WITH STROKE */
    533  1.11   mlelstv 	0x023D, 0x019A, /* LATIN CAPITAL LETTER L WITH BAR */
    534  1.11   mlelstv 	0x023E, 0x2C66, /* LATIN CAPITAL LETTER T WITH DIAGONAL STROKE */
    535  1.11   mlelstv 	0x0241, 0x0242, /* LATIN CAPITAL LETTER GLOTTAL STOP */
    536  1.11   mlelstv 	0x0243, 0x0180, /* LATIN CAPITAL LETTER B WITH STROKE */
    537  1.11   mlelstv 	0x0244, 0x0289, /* LATIN CAPITAL LETTER U BAR */
    538  1.11   mlelstv 	0x0245, 0x028C, /* LATIN CAPITAL LETTER TURNED V */
    539  1.11   mlelstv 	0x0246, 0x0247, /* LATIN CAPITAL LETTER E WITH STROKE */
    540  1.11   mlelstv 	0x0248, 0x0249, /* LATIN CAPITAL LETTER J WITH STROKE */
    541  1.11   mlelstv 	0x024A, 0x024B, /* LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL */
    542  1.11   mlelstv 	0x024C, 0x024D, /* LATIN CAPITAL LETTER R WITH STROKE */
    543  1.11   mlelstv 	0x024E, 0x024F, /* LATIN CAPITAL LETTER Y WITH STROKE */
    544  1.11   mlelstv 	0x0345, 0x03B9, /* COMBINING GREEK YPOGEGRAMMENI */
    545  1.11   mlelstv 	0x0386, 0x03AC, /* GREEK CAPITAL LETTER ALPHA WITH TONOS */
    546  1.11   mlelstv 	0x0388, 0x03AD, /* GREEK CAPITAL LETTER EPSILON WITH TONOS */
    547  1.11   mlelstv 	0x0389, 0x03AE, /* GREEK CAPITAL LETTER ETA WITH TONOS */
    548  1.11   mlelstv 	0x038A, 0x03AF, /* GREEK CAPITAL LETTER IOTA WITH TONOS */
    549  1.11   mlelstv 	0x038C, 0x03CC, /* GREEK CAPITAL LETTER OMICRON WITH TONOS */
    550  1.11   mlelstv 	0x038E, 0x03CD, /* GREEK CAPITAL LETTER UPSILON WITH TONOS */
    551  1.11   mlelstv 	0x038F, 0x03CE, /* GREEK CAPITAL LETTER OMEGA WITH TONOS */
    552  1.11   mlelstv 	0x0391, 0x03B1, /* GREEK CAPITAL LETTER ALPHA */
    553  1.11   mlelstv 	0x0392, 0x03B2, /* GREEK CAPITAL LETTER BETA */
    554  1.11   mlelstv 	0x0393, 0x03B3, /* GREEK CAPITAL LETTER GAMMA */
    555  1.11   mlelstv 	0x0394, 0x03B4, /* GREEK CAPITAL LETTER DELTA */
    556  1.11   mlelstv 	0x0395, 0x03B5, /* GREEK CAPITAL LETTER EPSILON */
    557  1.11   mlelstv 	0x0396, 0x03B6, /* GREEK CAPITAL LETTER ZETA */
    558  1.11   mlelstv 	0x0397, 0x03B7, /* GREEK CAPITAL LETTER ETA */
    559  1.11   mlelstv 	0x0398, 0x03B8, /* GREEK CAPITAL LETTER THETA */
    560  1.11   mlelstv 	0x0399, 0x03B9, /* GREEK CAPITAL LETTER IOTA */
    561  1.11   mlelstv 	0x039A, 0x03BA, /* GREEK CAPITAL LETTER KAPPA */
    562  1.11   mlelstv 	0x039B, 0x03BB, /* GREEK CAPITAL LETTER LAMDA */
    563  1.11   mlelstv 	0x039C, 0x03BC, /* GREEK CAPITAL LETTER MU */
    564  1.11   mlelstv 	0x039D, 0x03BD, /* GREEK CAPITAL LETTER NU */
    565  1.11   mlelstv 	0x039E, 0x03BE, /* GREEK CAPITAL LETTER XI */
    566  1.11   mlelstv 	0x039F, 0x03BF, /* GREEK CAPITAL LETTER OMICRON */
    567  1.11   mlelstv 	0x03A0, 0x03C0, /* GREEK CAPITAL LETTER PI */
    568  1.11   mlelstv 	0x03A1, 0x03C1, /* GREEK CAPITAL LETTER RHO */
    569  1.11   mlelstv 	0x03A3, 0x03C3, /* GREEK CAPITAL LETTER SIGMA */
    570  1.11   mlelstv 	0x03A4, 0x03C4, /* GREEK CAPITAL LETTER TAU */
    571  1.11   mlelstv 	0x03A5, 0x03C5, /* GREEK CAPITAL LETTER UPSILON */
    572  1.11   mlelstv 	0x03A6, 0x03C6, /* GREEK CAPITAL LETTER PHI */
    573  1.11   mlelstv 	0x03A7, 0x03C7, /* GREEK CAPITAL LETTER CHI */
    574  1.11   mlelstv 	0x03A8, 0x03C8, /* GREEK CAPITAL LETTER PSI */
    575  1.11   mlelstv 	0x03A9, 0x03C9, /* GREEK CAPITAL LETTER OMEGA */
    576  1.11   mlelstv 	0x03AA, 0x03CA, /* GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */
    577  1.11   mlelstv 	0x03AB, 0x03CB, /* GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */
    578  1.11   mlelstv 	0x03C2, 0x03C3, /* GREEK SMALL LETTER FINAL SIGMA */
    579  1.11   mlelstv 	0x03D0, 0x03B2, /* GREEK BETA SYMBOL */
    580  1.11   mlelstv 	0x03D1, 0x03B8, /* GREEK THETA SYMBOL */
    581  1.11   mlelstv 	0x03D5, 0x03C6, /* GREEK PHI SYMBOL */
    582  1.11   mlelstv 	0x03D6, 0x03C0, /* GREEK PI SYMBOL */
    583  1.11   mlelstv 	0x03D8, 0x03D9, /* GREEK LETTER ARCHAIC KOPPA */
    584  1.11   mlelstv 	0x03DA, 0x03DB, /* GREEK LETTER STIGMA */
    585  1.11   mlelstv 	0x03DC, 0x03DD, /* GREEK LETTER DIGAMMA */
    586  1.11   mlelstv 	0x03DE, 0x03DF, /* GREEK LETTER KOPPA */
    587  1.11   mlelstv 	0x03E0, 0x03E1, /* GREEK LETTER SAMPI */
    588  1.11   mlelstv 	0x03E2, 0x03E3, /* COPTIC CAPITAL LETTER SHEI */
    589  1.11   mlelstv 	0x03E4, 0x03E5, /* COPTIC CAPITAL LETTER FEI */
    590  1.11   mlelstv 	0x03E6, 0x03E7, /* COPTIC CAPITAL LETTER KHEI */
    591  1.11   mlelstv 	0x03E8, 0x03E9, /* COPTIC CAPITAL LETTER HORI */
    592  1.11   mlelstv 	0x03EA, 0x03EB, /* COPTIC CAPITAL LETTER GANGIA */
    593  1.11   mlelstv 	0x03EC, 0x03ED, /* COPTIC CAPITAL LETTER SHIMA */
    594  1.11   mlelstv 	0x03EE, 0x03EF, /* COPTIC CAPITAL LETTER DEI */
    595  1.11   mlelstv 	0x03F0, 0x03BA, /* GREEK KAPPA SYMBOL */
    596  1.11   mlelstv 	0x03F1, 0x03C1, /* GREEK RHO SYMBOL */
    597  1.11   mlelstv 	0x03F4, 0x03B8, /* GREEK CAPITAL THETA SYMBOL */
    598  1.11   mlelstv 	0x03F5, 0x03B5, /* GREEK LUNATE EPSILON SYMBOL */
    599  1.11   mlelstv 	0x03F7, 0x03F8, /* GREEK CAPITAL LETTER SHO */
    600  1.11   mlelstv 	0x03F9, 0x03F2, /* GREEK CAPITAL LUNATE SIGMA SYMBOL */
    601  1.11   mlelstv 	0x03FA, 0x03FB, /* GREEK CAPITAL LETTER SAN */
    602  1.11   mlelstv 	0x03FD, 0x037B, /* GREEK CAPITAL REVERSED LUNATE SIGMA SYMBOL */
    603  1.11   mlelstv 	0x03FE, 0x037C, /* GREEK CAPITAL DOTTED LUNATE SIGMA SYMBOL */
    604  1.11   mlelstv 	0x03FF, 0x037D, /* GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL */
    605  1.11   mlelstv 	0x0400, 0x0450, /* CYRILLIC CAPITAL LETTER IE WITH GRAVE */
    606  1.11   mlelstv 	0x0401, 0x0451, /* CYRILLIC CAPITAL LETTER IO */
    607  1.11   mlelstv 	0x0402, 0x0452, /* CYRILLIC CAPITAL LETTER DJE */
    608  1.11   mlelstv 	0x0403, 0x0453, /* CYRILLIC CAPITAL LETTER GJE */
    609  1.11   mlelstv 	0x0404, 0x0454, /* CYRILLIC CAPITAL LETTER UKRAINIAN IE */
    610  1.11   mlelstv 	0x0405, 0x0455, /* CYRILLIC CAPITAL LETTER DZE */
    611  1.11   mlelstv 	0x0406, 0x0456, /* CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */
    612  1.11   mlelstv 	0x0407, 0x0457, /* CYRILLIC CAPITAL LETTER YI */
    613  1.11   mlelstv 	0x0408, 0x0458, /* CYRILLIC CAPITAL LETTER JE */
    614  1.11   mlelstv 	0x0409, 0x0459, /* CYRILLIC CAPITAL LETTER LJE */
    615  1.11   mlelstv 	0x040A, 0x045A, /* CYRILLIC CAPITAL LETTER NJE */
    616  1.11   mlelstv 	0x040B, 0x045B, /* CYRILLIC CAPITAL LETTER TSHE */
    617  1.11   mlelstv 	0x040C, 0x045C, /* CYRILLIC CAPITAL LETTER KJE */
    618  1.11   mlelstv 	0x040D, 0x045D, /* CYRILLIC CAPITAL LETTER I WITH GRAVE */
    619  1.11   mlelstv 	0x040E, 0x045E, /* CYRILLIC CAPITAL LETTER SHORT U */
    620  1.11   mlelstv 	0x040F, 0x045F, /* CYRILLIC CAPITAL LETTER DZHE */
    621  1.11   mlelstv 	0x0410, 0x0430, /* CYRILLIC CAPITAL LETTER A */
    622  1.11   mlelstv 	0x0411, 0x0431, /* CYRILLIC CAPITAL LETTER BE */
    623  1.11   mlelstv 	0x0412, 0x0432, /* CYRILLIC CAPITAL LETTER VE */
    624  1.11   mlelstv 	0x0413, 0x0433, /* CYRILLIC CAPITAL LETTER GHE */
    625  1.11   mlelstv 	0x0414, 0x0434, /* CYRILLIC CAPITAL LETTER DE */
    626  1.11   mlelstv 	0x0415, 0x0435, /* CYRILLIC CAPITAL LETTER IE */
    627  1.11   mlelstv 	0x0416, 0x0436, /* CYRILLIC CAPITAL LETTER ZHE */
    628  1.11   mlelstv 	0x0417, 0x0437, /* CYRILLIC CAPITAL LETTER ZE */
    629  1.11   mlelstv 	0x0418, 0x0438, /* CYRILLIC CAPITAL LETTER I */
    630  1.11   mlelstv 	0x0419, 0x0439, /* CYRILLIC CAPITAL LETTER SHORT I */
    631  1.11   mlelstv 	0x041A, 0x043A, /* CYRILLIC CAPITAL LETTER KA */
    632  1.11   mlelstv 	0x041B, 0x043B, /* CYRILLIC CAPITAL LETTER EL */
    633  1.11   mlelstv 	0x041C, 0x043C, /* CYRILLIC CAPITAL LETTER EM */
    634  1.11   mlelstv 	0x041D, 0x043D, /* CYRILLIC CAPITAL LETTER EN */
    635  1.11   mlelstv 	0x041E, 0x043E, /* CYRILLIC CAPITAL LETTER O */
    636  1.11   mlelstv 	0x041F, 0x043F, /* CYRILLIC CAPITAL LETTER PE */
    637  1.11   mlelstv 	0x0420, 0x0440, /* CYRILLIC CAPITAL LETTER ER */
    638  1.11   mlelstv 	0x0421, 0x0441, /* CYRILLIC CAPITAL LETTER ES */
    639  1.11   mlelstv 	0x0422, 0x0442, /* CYRILLIC CAPITAL LETTER TE */
    640  1.11   mlelstv 	0x0423, 0x0443, /* CYRILLIC CAPITAL LETTER U */
    641  1.11   mlelstv 	0x0424, 0x0444, /* CYRILLIC CAPITAL LETTER EF */
    642  1.11   mlelstv 	0x0425, 0x0445, /* CYRILLIC CAPITAL LETTER HA */
    643  1.11   mlelstv 	0x0426, 0x0446, /* CYRILLIC CAPITAL LETTER TSE */
    644  1.11   mlelstv 	0x0427, 0x0447, /* CYRILLIC CAPITAL LETTER CHE */
    645  1.11   mlelstv 	0x0428, 0x0448, /* CYRILLIC CAPITAL LETTER SHA */
    646  1.11   mlelstv 	0x0429, 0x0449, /* CYRILLIC CAPITAL LETTER SHCHA */
    647  1.11   mlelstv 	0x042A, 0x044A, /* CYRILLIC CAPITAL LETTER HARD SIGN */
    648  1.11   mlelstv 	0x042B, 0x044B, /* CYRILLIC CAPITAL LETTER YERU */
    649  1.11   mlelstv 	0x042C, 0x044C, /* CYRILLIC CAPITAL LETTER SOFT SIGN */
    650  1.11   mlelstv 	0x042D, 0x044D, /* CYRILLIC CAPITAL LETTER E */
    651  1.11   mlelstv 	0x042E, 0x044E, /* CYRILLIC CAPITAL LETTER YU */
    652  1.11   mlelstv 	0x042F, 0x044F, /* CYRILLIC CAPITAL LETTER YA */
    653  1.11   mlelstv 	0x0460, 0x0461, /* CYRILLIC CAPITAL LETTER OMEGA */
    654  1.11   mlelstv 	0x0462, 0x0463, /* CYRILLIC CAPITAL LETTER YAT */
    655  1.11   mlelstv 	0x0464, 0x0465, /* CYRILLIC CAPITAL LETTER IOTIFIED E */
    656  1.11   mlelstv 	0x0466, 0x0467, /* CYRILLIC CAPITAL LETTER LITTLE YUS */
    657  1.11   mlelstv 	0x0468, 0x0469, /* CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS */
    658  1.11   mlelstv 	0x046A, 0x046B, /* CYRILLIC CAPITAL LETTER BIG YUS */
    659  1.11   mlelstv 	0x046C, 0x046D, /* CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS */
    660  1.11   mlelstv 	0x046E, 0x046F, /* CYRILLIC CAPITAL LETTER KSI */
    661  1.11   mlelstv 	0x0470, 0x0471, /* CYRILLIC CAPITAL LETTER PSI */
    662  1.11   mlelstv 	0x0472, 0x0473, /* CYRILLIC CAPITAL LETTER FITA */
    663  1.11   mlelstv 	0x0474, 0x0475, /* CYRILLIC CAPITAL LETTER IZHITSA */
    664  1.11   mlelstv 	0x0476, 0x0477, /* CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT */
    665  1.11   mlelstv 	0x0478, 0x0479, /* CYRILLIC CAPITAL LETTER UK */
    666  1.11   mlelstv 	0x047A, 0x047B, /* CYRILLIC CAPITAL LETTER ROUND OMEGA */
    667  1.11   mlelstv 	0x047C, 0x047D, /* CYRILLIC CAPITAL LETTER OMEGA WITH TITLO */
    668  1.11   mlelstv 	0x047E, 0x047F, /* CYRILLIC CAPITAL LETTER OT */
    669  1.11   mlelstv 	0x0480, 0x0481, /* CYRILLIC CAPITAL LETTER KOPPA */
    670  1.11   mlelstv 	0x048A, 0x048B, /* CYRILLIC CAPITAL LETTER SHORT I WITH TAIL */
    671  1.11   mlelstv 	0x048C, 0x048D, /* CYRILLIC CAPITAL LETTER SEMISOFT SIGN */
    672  1.11   mlelstv 	0x048E, 0x048F, /* CYRILLIC CAPITAL LETTER ER WITH TICK */
    673  1.11   mlelstv 	0x0490, 0x0491, /* CYRILLIC CAPITAL LETTER GHE WITH UPTURN */
    674  1.11   mlelstv 	0x0492, 0x0493, /* CYRILLIC CAPITAL LETTER GHE WITH STROKE */
    675  1.11   mlelstv 	0x0494, 0x0495, /* CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK */
    676  1.11   mlelstv 	0x0496, 0x0497, /* CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER */
    677  1.11   mlelstv 	0x0498, 0x0499, /* CYRILLIC CAPITAL LETTER ZE WITH DESCENDER */
    678  1.11   mlelstv 	0x049A, 0x049B, /* CYRILLIC CAPITAL LETTER KA WITH DESCENDER */
    679  1.11   mlelstv 	0x049C, 0x049D, /* CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE */
    680  1.11   mlelstv 	0x049E, 0x049F, /* CYRILLIC CAPITAL LETTER KA WITH STROKE */
    681  1.11   mlelstv 	0x04A0, 0x04A1, /* CYRILLIC CAPITAL LETTER BASHKIR KA */
    682  1.11   mlelstv 	0x04A2, 0x04A3, /* CYRILLIC CAPITAL LETTER EN WITH DESCENDER */
    683  1.11   mlelstv 	0x04A4, 0x04A5, /* CYRILLIC CAPITAL LIGATURE EN GHE */
    684  1.11   mlelstv 	0x04A6, 0x04A7, /* CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK */
    685  1.11   mlelstv 	0x04A8, 0x04A9, /* CYRILLIC CAPITAL LETTER ABKHASIAN HA */
    686  1.11   mlelstv 	0x04AA, 0x04AB, /* CYRILLIC CAPITAL LETTER ES WITH DESCENDER */
    687  1.11   mlelstv 	0x04AC, 0x04AD, /* CYRILLIC CAPITAL LETTER TE WITH DESCENDER */
    688  1.11   mlelstv 	0x04AE, 0x04AF, /* CYRILLIC CAPITAL LETTER STRAIGHT U */
    689  1.11   mlelstv 	0x04B0, 0x04B1, /* CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE */
    690  1.11   mlelstv 	0x04B2, 0x04B3, /* CYRILLIC CAPITAL LETTER HA WITH DESCENDER */
    691  1.11   mlelstv 	0x04B4, 0x04B5, /* CYRILLIC CAPITAL LIGATURE TE TSE */
    692  1.11   mlelstv 	0x04B6, 0x04B7, /* CYRILLIC CAPITAL LETTER CHE WITH DESCENDER */
    693  1.11   mlelstv 	0x04B8, 0x04B9, /* CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE */
    694  1.11   mlelstv 	0x04BA, 0x04BB, /* CYRILLIC CAPITAL LETTER SHHA */
    695  1.11   mlelstv 	0x04BC, 0x04BD, /* CYRILLIC CAPITAL LETTER ABKHASIAN CHE */
    696  1.11   mlelstv 	0x04BE, 0x04BF, /* CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER */
    697  1.11   mlelstv 	0x04C0, 0x04CF, /* CYRILLIC LETTER PALOCHKA */
    698  1.11   mlelstv 	0x04C1, 0x04C2, /* CYRILLIC CAPITAL LETTER ZHE WITH BREVE */
    699  1.11   mlelstv 	0x04C3, 0x04C4, /* CYRILLIC CAPITAL LETTER KA WITH HOOK */
    700  1.11   mlelstv 	0x04C5, 0x04C6, /* CYRILLIC CAPITAL LETTER EL WITH TAIL */
    701  1.11   mlelstv 	0x04C7, 0x04C8, /* CYRILLIC CAPITAL LETTER EN WITH HOOK */
    702  1.11   mlelstv 	0x04C9, 0x04CA, /* CYRILLIC CAPITAL LETTER EN WITH TAIL */
    703  1.11   mlelstv 	0x04CB, 0x04CC, /* CYRILLIC CAPITAL LETTER KHAKASSIAN CHE */
    704  1.11   mlelstv 	0x04CD, 0x04CE, /* CYRILLIC CAPITAL LETTER EM WITH TAIL */
    705  1.11   mlelstv 	0x04D0, 0x04D1, /* CYRILLIC CAPITAL LETTER A WITH BREVE */
    706  1.11   mlelstv 	0x04D2, 0x04D3, /* CYRILLIC CAPITAL LETTER A WITH DIAERESIS */
    707  1.11   mlelstv 	0x04D4, 0x04D5, /* CYRILLIC CAPITAL LIGATURE A IE */
    708  1.11   mlelstv 	0x04D6, 0x04D7, /* CYRILLIC CAPITAL LETTER IE WITH BREVE */
    709  1.11   mlelstv 	0x04D8, 0x04D9, /* CYRILLIC CAPITAL LETTER SCHWA */
    710  1.11   mlelstv 	0x04DA, 0x04DB, /* CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS */
    711  1.11   mlelstv 	0x04DC, 0x04DD, /* CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS */
    712  1.11   mlelstv 	0x04DE, 0x04DF, /* CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS */
    713  1.11   mlelstv 	0x04E0, 0x04E1, /* CYRILLIC CAPITAL LETTER ABKHASIAN DZE */
    714  1.11   mlelstv 	0x04E2, 0x04E3, /* CYRILLIC CAPITAL LETTER I WITH MACRON */
    715  1.11   mlelstv 	0x04E4, 0x04E5, /* CYRILLIC CAPITAL LETTER I WITH DIAERESIS */
    716  1.11   mlelstv 	0x04E6, 0x04E7, /* CYRILLIC CAPITAL LETTER O WITH DIAERESIS */
    717  1.11   mlelstv 	0x04E8, 0x04E9, /* CYRILLIC CAPITAL LETTER BARRED O */
    718  1.11   mlelstv 	0x04EA, 0x04EB, /* CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS */
    719  1.11   mlelstv 	0x04EC, 0x04ED, /* CYRILLIC CAPITAL LETTER E WITH DIAERESIS */
    720  1.11   mlelstv 	0x04EE, 0x04EF, /* CYRILLIC CAPITAL LETTER U WITH MACRON */
    721  1.11   mlelstv 	0x04F0, 0x04F1, /* CYRILLIC CAPITAL LETTER U WITH DIAERESIS */
    722  1.11   mlelstv 	0x04F2, 0x04F3, /* CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE */
    723  1.11   mlelstv 	0x04F4, 0x04F5, /* CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS */
    724  1.11   mlelstv 	0x04F6, 0x04F7, /* CYRILLIC CAPITAL LETTER GHE WITH DESCENDER */
    725  1.11   mlelstv 	0x04F8, 0x04F9, /* CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS */
    726  1.11   mlelstv 	0x04FA, 0x04FB, /* CYRILLIC CAPITAL LETTER GHE WITH STROKE AND HOOK */
    727  1.11   mlelstv 	0x04FC, 0x04FD, /* CYRILLIC CAPITAL LETTER HA WITH HOOK */
    728  1.11   mlelstv 	0x04FE, 0x04FF, /* CYRILLIC CAPITAL LETTER HA WITH STROKE */
    729  1.11   mlelstv 	0x0500, 0x0501, /* CYRILLIC CAPITAL LETTER KOMI DE */
    730  1.11   mlelstv 	0x0502, 0x0503, /* CYRILLIC CAPITAL LETTER KOMI DJE */
    731  1.11   mlelstv 	0x0504, 0x0505, /* CYRILLIC CAPITAL LETTER KOMI ZJE */
    732  1.11   mlelstv 	0x0506, 0x0507, /* CYRILLIC CAPITAL LETTER KOMI DZJE */
    733  1.11   mlelstv 	0x0508, 0x0509, /* CYRILLIC CAPITAL LETTER KOMI LJE */
    734  1.11   mlelstv 	0x050A, 0x050B, /* CYRILLIC CAPITAL LETTER KOMI NJE */
    735  1.11   mlelstv 	0x050C, 0x050D, /* CYRILLIC CAPITAL LETTER KOMI SJE */
    736  1.11   mlelstv 	0x050E, 0x050F, /* CYRILLIC CAPITAL LETTER KOMI TJE */
    737  1.11   mlelstv 	0x0510, 0x0511, /* CYRILLIC CAPITAL LETTER REVERSED ZE */
    738  1.11   mlelstv 	0x0512, 0x0513, /* CYRILLIC CAPITAL LETTER EL WITH HOOK */
    739  1.11   mlelstv 	0x0531, 0x0561, /* ARMENIAN CAPITAL LETTER AYB */
    740  1.11   mlelstv 	0x0532, 0x0562, /* ARMENIAN CAPITAL LETTER BEN */
    741  1.11   mlelstv 	0x0533, 0x0563, /* ARMENIAN CAPITAL LETTER GIM */
    742  1.11   mlelstv 	0x0534, 0x0564, /* ARMENIAN CAPITAL LETTER DA */
    743  1.11   mlelstv 	0x0535, 0x0565, /* ARMENIAN CAPITAL LETTER ECH */
    744  1.11   mlelstv 	0x0536, 0x0566, /* ARMENIAN CAPITAL LETTER ZA */
    745  1.11   mlelstv 	0x0537, 0x0567, /* ARMENIAN CAPITAL LETTER EH */
    746  1.11   mlelstv 	0x0538, 0x0568, /* ARMENIAN CAPITAL LETTER ET */
    747  1.11   mlelstv 	0x0539, 0x0569, /* ARMENIAN CAPITAL LETTER TO */
    748  1.11   mlelstv 	0x053A, 0x056A, /* ARMENIAN CAPITAL LETTER ZHE */
    749  1.11   mlelstv 	0x053B, 0x056B, /* ARMENIAN CAPITAL LETTER INI */
    750  1.11   mlelstv 	0x053C, 0x056C, /* ARMENIAN CAPITAL LETTER LIWN */
    751  1.11   mlelstv 	0x053D, 0x056D, /* ARMENIAN CAPITAL LETTER XEH */
    752  1.11   mlelstv 	0x053E, 0x056E, /* ARMENIAN CAPITAL LETTER CA */
    753  1.11   mlelstv 	0x053F, 0x056F, /* ARMENIAN CAPITAL LETTER KEN */
    754  1.11   mlelstv 	0x0540, 0x0570, /* ARMENIAN CAPITAL LETTER HO */
    755  1.11   mlelstv 	0x0541, 0x0571, /* ARMENIAN CAPITAL LETTER JA */
    756  1.11   mlelstv 	0x0542, 0x0572, /* ARMENIAN CAPITAL LETTER GHAD */
    757  1.11   mlelstv 	0x0543, 0x0573, /* ARMENIAN CAPITAL LETTER CHEH */
    758  1.11   mlelstv 	0x0544, 0x0574, /* ARMENIAN CAPITAL LETTER MEN */
    759  1.11   mlelstv 	0x0545, 0x0575, /* ARMENIAN CAPITAL LETTER YI */
    760  1.11   mlelstv 	0x0546, 0x0576, /* ARMENIAN CAPITAL LETTER NOW */
    761  1.11   mlelstv 	0x0547, 0x0577, /* ARMENIAN CAPITAL LETTER SHA */
    762  1.11   mlelstv 	0x0548, 0x0578, /* ARMENIAN CAPITAL LETTER VO */
    763  1.11   mlelstv 	0x0549, 0x0579, /* ARMENIAN CAPITAL LETTER CHA */
    764  1.11   mlelstv 	0x054A, 0x057A, /* ARMENIAN CAPITAL LETTER PEH */
    765  1.11   mlelstv 	0x054B, 0x057B, /* ARMENIAN CAPITAL LETTER JHEH */
    766  1.11   mlelstv 	0x054C, 0x057C, /* ARMENIAN CAPITAL LETTER RA */
    767  1.11   mlelstv 	0x054D, 0x057D, /* ARMENIAN CAPITAL LETTER SEH */
    768  1.11   mlelstv 	0x054E, 0x057E, /* ARMENIAN CAPITAL LETTER VEW */
    769  1.11   mlelstv 	0x054F, 0x057F, /* ARMENIAN CAPITAL LETTER TIWN */
    770  1.11   mlelstv 	0x0550, 0x0580, /* ARMENIAN CAPITAL LETTER REH */
    771  1.11   mlelstv 	0x0551, 0x0581, /* ARMENIAN CAPITAL LETTER CO */
    772  1.11   mlelstv 	0x0552, 0x0582, /* ARMENIAN CAPITAL LETTER YIWN */
    773  1.11   mlelstv 	0x0553, 0x0583, /* ARMENIAN CAPITAL LETTER PIWR */
    774  1.11   mlelstv 	0x0554, 0x0584, /* ARMENIAN CAPITAL LETTER KEH */
    775  1.11   mlelstv 	0x0555, 0x0585, /* ARMENIAN CAPITAL LETTER OH */
    776  1.11   mlelstv 	0x0556, 0x0586, /* ARMENIAN CAPITAL LETTER FEH */
    777  1.11   mlelstv 	0x10A0, 0x2D00, /* GEORGIAN CAPITAL LETTER AN */
    778  1.11   mlelstv 	0x10A1, 0x2D01, /* GEORGIAN CAPITAL LETTER BAN */
    779  1.11   mlelstv 	0x10A2, 0x2D02, /* GEORGIAN CAPITAL LETTER GAN */
    780  1.11   mlelstv 	0x10A3, 0x2D03, /* GEORGIAN CAPITAL LETTER DON */
    781  1.11   mlelstv 	0x10A4, 0x2D04, /* GEORGIAN CAPITAL LETTER EN */
    782  1.11   mlelstv 	0x10A5, 0x2D05, /* GEORGIAN CAPITAL LETTER VIN */
    783  1.11   mlelstv 	0x10A6, 0x2D06, /* GEORGIAN CAPITAL LETTER ZEN */
    784  1.11   mlelstv 	0x10A7, 0x2D07, /* GEORGIAN CAPITAL LETTER TAN */
    785  1.11   mlelstv 	0x10A8, 0x2D08, /* GEORGIAN CAPITAL LETTER IN */
    786  1.11   mlelstv 	0x10A9, 0x2D09, /* GEORGIAN CAPITAL LETTER KAN */
    787  1.11   mlelstv 	0x10AA, 0x2D0A, /* GEORGIAN CAPITAL LETTER LAS */
    788  1.11   mlelstv 	0x10AB, 0x2D0B, /* GEORGIAN CAPITAL LETTER MAN */
    789  1.11   mlelstv 	0x10AC, 0x2D0C, /* GEORGIAN CAPITAL LETTER NAR */
    790  1.11   mlelstv 	0x10AD, 0x2D0D, /* GEORGIAN CAPITAL LETTER ON */
    791  1.11   mlelstv 	0x10AE, 0x2D0E, /* GEORGIAN CAPITAL LETTER PAR */
    792  1.11   mlelstv 	0x10AF, 0x2D0F, /* GEORGIAN CAPITAL LETTER ZHAR */
    793  1.11   mlelstv 	0x10B0, 0x2D10, /* GEORGIAN CAPITAL LETTER RAE */
    794  1.11   mlelstv 	0x10B1, 0x2D11, /* GEORGIAN CAPITAL LETTER SAN */
    795  1.11   mlelstv 	0x10B2, 0x2D12, /* GEORGIAN CAPITAL LETTER TAR */
    796  1.11   mlelstv 	0x10B3, 0x2D13, /* GEORGIAN CAPITAL LETTER UN */
    797  1.11   mlelstv 	0x10B4, 0x2D14, /* GEORGIAN CAPITAL LETTER PHAR */
    798  1.11   mlelstv 	0x10B5, 0x2D15, /* GEORGIAN CAPITAL LETTER KHAR */
    799  1.11   mlelstv 	0x10B6, 0x2D16, /* GEORGIAN CAPITAL LETTER GHAN */
    800  1.11   mlelstv 	0x10B7, 0x2D17, /* GEORGIAN CAPITAL LETTER QAR */
    801  1.11   mlelstv 	0x10B8, 0x2D18, /* GEORGIAN CAPITAL LETTER SHIN */
    802  1.11   mlelstv 	0x10B9, 0x2D19, /* GEORGIAN CAPITAL LETTER CHIN */
    803  1.11   mlelstv 	0x10BA, 0x2D1A, /* GEORGIAN CAPITAL LETTER CAN */
    804  1.11   mlelstv 	0x10BB, 0x2D1B, /* GEORGIAN CAPITAL LETTER JIL */
    805  1.11   mlelstv 	0x10BC, 0x2D1C, /* GEORGIAN CAPITAL LETTER CIL */
    806  1.11   mlelstv 	0x10BD, 0x2D1D, /* GEORGIAN CAPITAL LETTER CHAR */
    807  1.11   mlelstv 	0x10BE, 0x2D1E, /* GEORGIAN CAPITAL LETTER XAN */
    808  1.11   mlelstv 	0x10BF, 0x2D1F, /* GEORGIAN CAPITAL LETTER JHAN */
    809  1.11   mlelstv 	0x10C0, 0x2D20, /* GEORGIAN CAPITAL LETTER HAE */
    810  1.11   mlelstv 	0x10C1, 0x2D21, /* GEORGIAN CAPITAL LETTER HE */
    811  1.11   mlelstv 	0x10C2, 0x2D22, /* GEORGIAN CAPITAL LETTER HIE */
    812  1.11   mlelstv 	0x10C3, 0x2D23, /* GEORGIAN CAPITAL LETTER WE */
    813  1.11   mlelstv 	0x10C4, 0x2D24, /* GEORGIAN CAPITAL LETTER HAR */
    814  1.11   mlelstv 	0x10C5, 0x2D25, /* GEORGIAN CAPITAL LETTER HOE */
    815  1.11   mlelstv 	0x1E00, 0x1E01, /* LATIN CAPITAL LETTER A WITH RING BELOW */
    816  1.11   mlelstv 	0x1E02, 0x1E03, /* LATIN CAPITAL LETTER B WITH DOT ABOVE */
    817  1.11   mlelstv 	0x1E04, 0x1E05, /* LATIN CAPITAL LETTER B WITH DOT BELOW */
    818  1.11   mlelstv 	0x1E06, 0x1E07, /* LATIN CAPITAL LETTER B WITH LINE BELOW */
    819  1.11   mlelstv 	0x1E08, 0x1E09, /* LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE */
    820  1.11   mlelstv 	0x1E0A, 0x1E0B, /* LATIN CAPITAL LETTER D WITH DOT ABOVE */
    821  1.11   mlelstv 	0x1E0C, 0x1E0D, /* LATIN CAPITAL LETTER D WITH DOT BELOW */
    822  1.11   mlelstv 	0x1E0E, 0x1E0F, /* LATIN CAPITAL LETTER D WITH LINE BELOW */
    823  1.11   mlelstv 	0x1E10, 0x1E11, /* LATIN CAPITAL LETTER D WITH CEDILLA */
    824  1.11   mlelstv 	0x1E12, 0x1E13, /* LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW */
    825  1.11   mlelstv 	0x1E14, 0x1E15, /* LATIN CAPITAL LETTER E WITH MACRON AND GRAVE */
    826  1.11   mlelstv 	0x1E16, 0x1E17, /* LATIN CAPITAL LETTER E WITH MACRON AND ACUTE */
    827  1.11   mlelstv 	0x1E18, 0x1E19, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW */
    828  1.11   mlelstv 	0x1E1A, 0x1E1B, /* LATIN CAPITAL LETTER E WITH TILDE BELOW */
    829  1.11   mlelstv 	0x1E1C, 0x1E1D, /* LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE */
    830  1.11   mlelstv 	0x1E1E, 0x1E1F, /* LATIN CAPITAL LETTER F WITH DOT ABOVE */
    831  1.11   mlelstv 	0x1E20, 0x1E21, /* LATIN CAPITAL LETTER G WITH MACRON */
    832  1.11   mlelstv 	0x1E22, 0x1E23, /* LATIN CAPITAL LETTER H WITH DOT ABOVE */
    833  1.11   mlelstv 	0x1E24, 0x1E25, /* LATIN CAPITAL LETTER H WITH DOT BELOW */
    834  1.11   mlelstv 	0x1E26, 0x1E27, /* LATIN CAPITAL LETTER H WITH DIAERESIS */
    835  1.11   mlelstv 	0x1E28, 0x1E29, /* LATIN CAPITAL LETTER H WITH CEDILLA */
    836  1.11   mlelstv 	0x1E2A, 0x1E2B, /* LATIN CAPITAL LETTER H WITH BREVE BELOW */
    837  1.11   mlelstv 	0x1E2C, 0x1E2D, /* LATIN CAPITAL LETTER I WITH TILDE BELOW */
    838  1.11   mlelstv 	0x1E2E, 0x1E2F, /* LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE */
    839  1.11   mlelstv 	0x1E30, 0x1E31, /* LATIN CAPITAL LETTER K WITH ACUTE */
    840  1.11   mlelstv 	0x1E32, 0x1E33, /* LATIN CAPITAL LETTER K WITH DOT BELOW */
    841  1.11   mlelstv 	0x1E34, 0x1E35, /* LATIN CAPITAL LETTER K WITH LINE BELOW */
    842  1.11   mlelstv 	0x1E36, 0x1E37, /* LATIN CAPITAL LETTER L WITH DOT BELOW */
    843  1.11   mlelstv 	0x1E38, 0x1E39, /* LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON */
    844  1.11   mlelstv 	0x1E3A, 0x1E3B, /* LATIN CAPITAL LETTER L WITH LINE BELOW */
    845  1.11   mlelstv 	0x1E3C, 0x1E3D, /* LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW */
    846  1.11   mlelstv 	0x1E3E, 0x1E3F, /* LATIN CAPITAL LETTER M WITH ACUTE */
    847  1.11   mlelstv 	0x1E40, 0x1E41, /* LATIN CAPITAL LETTER M WITH DOT ABOVE */
    848  1.11   mlelstv 	0x1E42, 0x1E43, /* LATIN CAPITAL LETTER M WITH DOT BELOW */
    849  1.11   mlelstv 	0x1E44, 0x1E45, /* LATIN CAPITAL LETTER N WITH DOT ABOVE */
    850  1.11   mlelstv 	0x1E46, 0x1E47, /* LATIN CAPITAL LETTER N WITH DOT BELOW */
    851  1.11   mlelstv 	0x1E48, 0x1E49, /* LATIN CAPITAL LETTER N WITH LINE BELOW */
    852  1.11   mlelstv 	0x1E4A, 0x1E4B, /* LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW */
    853  1.11   mlelstv 	0x1E4C, 0x1E4D, /* LATIN CAPITAL LETTER O WITH TILDE AND ACUTE */
    854  1.11   mlelstv 	0x1E4E, 0x1E4F, /* LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS */
    855  1.11   mlelstv 	0x1E50, 0x1E51, /* LATIN CAPITAL LETTER O WITH MACRON AND GRAVE */
    856  1.11   mlelstv 	0x1E52, 0x1E53, /* LATIN CAPITAL LETTER O WITH MACRON AND ACUTE */
    857  1.11   mlelstv 	0x1E54, 0x1E55, /* LATIN CAPITAL LETTER P WITH ACUTE */
    858  1.11   mlelstv 	0x1E56, 0x1E57, /* LATIN CAPITAL LETTER P WITH DOT ABOVE */
    859  1.11   mlelstv 	0x1E58, 0x1E59, /* LATIN CAPITAL LETTER R WITH DOT ABOVE */
    860  1.11   mlelstv 	0x1E5A, 0x1E5B, /* LATIN CAPITAL LETTER R WITH DOT BELOW */
    861  1.11   mlelstv 	0x1E5C, 0x1E5D, /* LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON */
    862  1.11   mlelstv 	0x1E5E, 0x1E5F, /* LATIN CAPITAL LETTER R WITH LINE BELOW */
    863  1.11   mlelstv 	0x1E60, 0x1E61, /* LATIN CAPITAL LETTER S WITH DOT ABOVE */
    864  1.11   mlelstv 	0x1E62, 0x1E63, /* LATIN CAPITAL LETTER S WITH DOT BELOW */
    865  1.11   mlelstv 	0x1E64, 0x1E65, /* LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE */
    866  1.11   mlelstv 	0x1E66, 0x1E67, /* LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE */
    867  1.11   mlelstv 	0x1E68, 0x1E69, /* LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE */
    868  1.11   mlelstv 	0x1E6A, 0x1E6B, /* LATIN CAPITAL LETTER T WITH DOT ABOVE */
    869  1.11   mlelstv 	0x1E6C, 0x1E6D, /* LATIN CAPITAL LETTER T WITH DOT BELOW */
    870  1.11   mlelstv 	0x1E6E, 0x1E6F, /* LATIN CAPITAL LETTER T WITH LINE BELOW */
    871  1.11   mlelstv 	0x1E70, 0x1E71, /* LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW */
    872  1.11   mlelstv 	0x1E72, 0x1E73, /* LATIN CAPITAL LETTER U WITH DIAERESIS BELOW */
    873  1.11   mlelstv 	0x1E74, 0x1E75, /* LATIN CAPITAL LETTER U WITH TILDE BELOW */
    874  1.11   mlelstv 	0x1E76, 0x1E77, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW */
    875  1.11   mlelstv 	0x1E78, 0x1E79, /* LATIN CAPITAL LETTER U WITH TILDE AND ACUTE */
    876  1.11   mlelstv 	0x1E7A, 0x1E7B, /* LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS */
    877  1.11   mlelstv 	0x1E7C, 0x1E7D, /* LATIN CAPITAL LETTER V WITH TILDE */
    878  1.11   mlelstv 	0x1E7E, 0x1E7F, /* LATIN CAPITAL LETTER V WITH DOT BELOW */
    879  1.11   mlelstv 	0x1E80, 0x1E81, /* LATIN CAPITAL LETTER W WITH GRAVE */
    880  1.11   mlelstv 	0x1E82, 0x1E83, /* LATIN CAPITAL LETTER W WITH ACUTE */
    881  1.11   mlelstv 	0x1E84, 0x1E85, /* LATIN CAPITAL LETTER W WITH DIAERESIS */
    882  1.11   mlelstv 	0x1E86, 0x1E87, /* LATIN CAPITAL LETTER W WITH DOT ABOVE */
    883  1.11   mlelstv 	0x1E88, 0x1E89, /* LATIN CAPITAL LETTER W WITH DOT BELOW */
    884  1.11   mlelstv 	0x1E8A, 0x1E8B, /* LATIN CAPITAL LETTER X WITH DOT ABOVE */
    885  1.11   mlelstv 	0x1E8C, 0x1E8D, /* LATIN CAPITAL LETTER X WITH DIAERESIS */
    886  1.11   mlelstv 	0x1E8E, 0x1E8F, /* LATIN CAPITAL LETTER Y WITH DOT ABOVE */
    887  1.11   mlelstv 	0x1E90, 0x1E91, /* LATIN CAPITAL LETTER Z WITH CIRCUMFLEX */
    888  1.11   mlelstv 	0x1E92, 0x1E93, /* LATIN CAPITAL LETTER Z WITH DOT BELOW */
    889  1.11   mlelstv 	0x1E94, 0x1E95, /* LATIN CAPITAL LETTER Z WITH LINE BELOW */
    890  1.11   mlelstv 	0x1E9B, 0x1E61, /* LATIN SMALL LETTER LONG S WITH DOT ABOVE */
    891  1.11   mlelstv 	0x1EA0, 0x1EA1, /* LATIN CAPITAL LETTER A WITH DOT BELOW */
    892  1.11   mlelstv 	0x1EA2, 0x1EA3, /* LATIN CAPITAL LETTER A WITH HOOK ABOVE */
    893  1.11   mlelstv 	0x1EA4, 0x1EA5, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE */
    894  1.11   mlelstv 	0x1EA6, 0x1EA7, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE */
    895  1.11   mlelstv 	0x1EA8, 0x1EA9, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE */
    896  1.11   mlelstv 	0x1EAA, 0x1EAB, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE */
    897  1.11   mlelstv 	0x1EAC, 0x1EAD, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW */
    898  1.11   mlelstv 	0x1EAE, 0x1EAF, /* LATIN CAPITAL LETTER A WITH BREVE AND ACUTE */
    899  1.11   mlelstv 	0x1EB0, 0x1EB1, /* LATIN CAPITAL LETTER A WITH BREVE AND GRAVE */
    900  1.11   mlelstv 	0x1EB2, 0x1EB3, /* LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE */
    901  1.11   mlelstv 	0x1EB4, 0x1EB5, /* LATIN CAPITAL LETTER A WITH BREVE AND TILDE */
    902  1.11   mlelstv 	0x1EB6, 0x1EB7, /* LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW */
    903  1.11   mlelstv 	0x1EB8, 0x1EB9, /* LATIN CAPITAL LETTER E WITH DOT BELOW */
    904  1.11   mlelstv 	0x1EBA, 0x1EBB, /* LATIN CAPITAL LETTER E WITH HOOK ABOVE */
    905  1.11   mlelstv 	0x1EBC, 0x1EBD, /* LATIN CAPITAL LETTER E WITH TILDE */
    906  1.11   mlelstv 	0x1EBE, 0x1EBF, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE */
    907  1.11   mlelstv 	0x1EC0, 0x1EC1, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE */
    908  1.11   mlelstv 	0x1EC2, 0x1EC3, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE */
    909  1.11   mlelstv 	0x1EC4, 0x1EC5, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE */
    910  1.11   mlelstv 	0x1EC6, 0x1EC7, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW */
    911  1.11   mlelstv 	0x1EC8, 0x1EC9, /* LATIN CAPITAL LETTER I WITH HOOK ABOVE */
    912  1.11   mlelstv 	0x1ECA, 0x1ECB, /* LATIN CAPITAL LETTER I WITH DOT BELOW */
    913  1.11   mlelstv 	0x1ECC, 0x1ECD, /* LATIN CAPITAL LETTER O WITH DOT BELOW */
    914  1.11   mlelstv 	0x1ECE, 0x1ECF, /* LATIN CAPITAL LETTER O WITH HOOK ABOVE */
    915  1.11   mlelstv 	0x1ED0, 0x1ED1, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE */
    916  1.11   mlelstv 	0x1ED2, 0x1ED3, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE */
    917  1.11   mlelstv 	0x1ED4, 0x1ED5, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE */
    918  1.11   mlelstv 	0x1ED6, 0x1ED7, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE */
    919  1.11   mlelstv 	0x1ED8, 0x1ED9, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW */
    920  1.11   mlelstv 	0x1EDA, 0x1EDB, /* LATIN CAPITAL LETTER O WITH HORN AND ACUTE */
    921  1.11   mlelstv 	0x1EDC, 0x1EDD, /* LATIN CAPITAL LETTER O WITH HORN AND GRAVE */
    922  1.11   mlelstv 	0x1EDE, 0x1EDF, /* LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE */
    923  1.11   mlelstv 	0x1EE0, 0x1EE1, /* LATIN CAPITAL LETTER O WITH HORN AND TILDE */
    924  1.11   mlelstv 	0x1EE2, 0x1EE3, /* LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW */
    925  1.11   mlelstv 	0x1EE4, 0x1EE5, /* LATIN CAPITAL LETTER U WITH DOT BELOW */
    926  1.11   mlelstv 	0x1EE6, 0x1EE7, /* LATIN CAPITAL LETTER U WITH HOOK ABOVE */
    927  1.11   mlelstv 	0x1EE8, 0x1EE9, /* LATIN CAPITAL LETTER U WITH HORN AND ACUTE */
    928  1.11   mlelstv 	0x1EEA, 0x1EEB, /* LATIN CAPITAL LETTER U WITH HORN AND GRAVE */
    929  1.11   mlelstv 	0x1EEC, 0x1EED, /* LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE */
    930  1.11   mlelstv 	0x1EEE, 0x1EEF, /* LATIN CAPITAL LETTER U WITH HORN AND TILDE */
    931  1.11   mlelstv 	0x1EF0, 0x1EF1, /* LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW */
    932  1.11   mlelstv 	0x1EF2, 0x1EF3, /* LATIN CAPITAL LETTER Y WITH GRAVE */
    933  1.11   mlelstv 	0x1EF4, 0x1EF5, /* LATIN CAPITAL LETTER Y WITH DOT BELOW */
    934  1.11   mlelstv 	0x1EF6, 0x1EF7, /* LATIN CAPITAL LETTER Y WITH HOOK ABOVE */
    935  1.11   mlelstv 	0x1EF8, 0x1EF9, /* LATIN CAPITAL LETTER Y WITH TILDE */
    936  1.11   mlelstv 	0x1F08, 0x1F00, /* GREEK CAPITAL LETTER ALPHA WITH PSILI */
    937  1.11   mlelstv 	0x1F09, 0x1F01, /* GREEK CAPITAL LETTER ALPHA WITH DASIA */
    938  1.11   mlelstv 	0x1F0A, 0x1F02, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA */
    939  1.11   mlelstv 	0x1F0B, 0x1F03, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA */
    940  1.11   mlelstv 	0x1F0C, 0x1F04, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA */
    941  1.11   mlelstv 	0x1F0D, 0x1F05, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA */
    942  1.11   mlelstv 	0x1F0E, 0x1F06, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI */
    943  1.11   mlelstv 	0x1F0F, 0x1F07, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI */
    944  1.11   mlelstv 	0x1F18, 0x1F10, /* GREEK CAPITAL LETTER EPSILON WITH PSILI */
    945  1.11   mlelstv 	0x1F19, 0x1F11, /* GREEK CAPITAL LETTER EPSILON WITH DASIA */
    946  1.11   mlelstv 	0x1F1A, 0x1F12, /* GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA */
    947  1.11   mlelstv 	0x1F1B, 0x1F13, /* GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA */
    948  1.11   mlelstv 	0x1F1C, 0x1F14, /* GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA */
    949  1.11   mlelstv 	0x1F1D, 0x1F15, /* GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA */
    950  1.11   mlelstv 	0x1F28, 0x1F20, /* GREEK CAPITAL LETTER ETA WITH PSILI */
    951  1.11   mlelstv 	0x1F29, 0x1F21, /* GREEK CAPITAL LETTER ETA WITH DASIA */
    952  1.11   mlelstv 	0x1F2A, 0x1F22, /* GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA */
    953  1.11   mlelstv 	0x1F2B, 0x1F23, /* GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA */
    954  1.11   mlelstv 	0x1F2C, 0x1F24, /* GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA */
    955  1.11   mlelstv 	0x1F2D, 0x1F25, /* GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA */
    956  1.11   mlelstv 	0x1F2E, 0x1F26, /* GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI */
    957  1.11   mlelstv 	0x1F2F, 0x1F27, /* GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI */
    958  1.11   mlelstv 	0x1F38, 0x1F30, /* GREEK CAPITAL LETTER IOTA WITH PSILI */
    959  1.11   mlelstv 	0x1F39, 0x1F31, /* GREEK CAPITAL LETTER IOTA WITH DASIA */
    960  1.11   mlelstv 	0x1F3A, 0x1F32, /* GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA */
    961  1.11   mlelstv 	0x1F3B, 0x1F33, /* GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA */
    962  1.11   mlelstv 	0x1F3C, 0x1F34, /* GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA */
    963  1.11   mlelstv 	0x1F3D, 0x1F35, /* GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA */
    964  1.11   mlelstv 	0x1F3E, 0x1F36, /* GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI */
    965  1.11   mlelstv 	0x1F3F, 0x1F37, /* GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI */
    966  1.11   mlelstv 	0x1F48, 0x1F40, /* GREEK CAPITAL LETTER OMICRON WITH PSILI */
    967  1.11   mlelstv 	0x1F49, 0x1F41, /* GREEK CAPITAL LETTER OMICRON WITH DASIA */
    968  1.11   mlelstv 	0x1F4A, 0x1F42, /* GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA */
    969  1.11   mlelstv 	0x1F4B, 0x1F43, /* GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA */
    970  1.11   mlelstv 	0x1F4C, 0x1F44, /* GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA */
    971  1.11   mlelstv 	0x1F4D, 0x1F45, /* GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA */
    972  1.11   mlelstv 	0x1F59, 0x1F51, /* GREEK CAPITAL LETTER UPSILON WITH DASIA */
    973  1.11   mlelstv 	0x1F5B, 0x1F53, /* GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA */
    974  1.11   mlelstv 	0x1F5D, 0x1F55, /* GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA */
    975  1.11   mlelstv 	0x1F5F, 0x1F57, /* GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI */
    976  1.11   mlelstv 	0x1F68, 0x1F60, /* GREEK CAPITAL LETTER OMEGA WITH PSILI */
    977  1.11   mlelstv 	0x1F69, 0x1F61, /* GREEK CAPITAL LETTER OMEGA WITH DASIA */
    978  1.11   mlelstv 	0x1F6A, 0x1F62, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA */
    979  1.11   mlelstv 	0x1F6B, 0x1F63, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA */
    980  1.11   mlelstv 	0x1F6C, 0x1F64, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA */
    981  1.11   mlelstv 	0x1F6D, 0x1F65, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA */
    982  1.11   mlelstv 	0x1F6E, 0x1F66, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI */
    983  1.11   mlelstv 	0x1F6F, 0x1F67, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI */
    984  1.11   mlelstv 	0x1F88, 0x1F80, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI */
    985  1.11   mlelstv 	0x1F89, 0x1F81, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI */
    986  1.11   mlelstv 	0x1F8A, 0x1F82, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI */
    987  1.11   mlelstv 	0x1F8B, 0x1F83, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI */
    988  1.11   mlelstv 	0x1F8C, 0x1F84, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI */
    989  1.11   mlelstv 	0x1F8D, 0x1F85, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI */
    990  1.11   mlelstv 	0x1F8E, 0x1F86, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI */
    991  1.11   mlelstv 	0x1F8F, 0x1F87, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI */
    992  1.11   mlelstv 	0x1F98, 0x1F90, /* GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI */
    993  1.11   mlelstv 	0x1F99, 0x1F91, /* GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI */
    994  1.11   mlelstv 	0x1F9A, 0x1F92, /* GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI */
    995  1.11   mlelstv 	0x1F9B, 0x1F93, /* GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI */
    996  1.11   mlelstv 	0x1F9C, 0x1F94, /* GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI */
    997  1.11   mlelstv 	0x1F9D, 0x1F95, /* GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI */
    998  1.11   mlelstv 	0x1F9E, 0x1F96, /* GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI */
    999  1.11   mlelstv 	0x1F9F, 0x1F97, /* GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI */
   1000  1.11   mlelstv 	0x1FA8, 0x1FA0, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI */
   1001  1.11   mlelstv 	0x1FA9, 0x1FA1, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI */
   1002  1.11   mlelstv 	0x1FAA, 0x1FA2, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI */
   1003  1.11   mlelstv 	0x1FAB, 0x1FA3, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI */
   1004  1.11   mlelstv 	0x1FAC, 0x1FA4, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI */
   1005  1.11   mlelstv 	0x1FAD, 0x1FA5, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI */
   1006  1.11   mlelstv 	0x1FAE, 0x1FA6, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI */
   1007  1.11   mlelstv 	0x1FAF, 0x1FA7, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI */
   1008  1.11   mlelstv 	0x1FB8, 0x1FB0, /* GREEK CAPITAL LETTER ALPHA WITH VRACHY */
   1009  1.11   mlelstv 	0x1FB9, 0x1FB1, /* GREEK CAPITAL LETTER ALPHA WITH MACRON */
   1010  1.11   mlelstv 	0x1FBA, 0x1F70, /* GREEK CAPITAL LETTER ALPHA WITH VARIA */
   1011  1.11   mlelstv 	0x1FBB, 0x1F71, /* GREEK CAPITAL LETTER ALPHA WITH OXIA */
   1012  1.11   mlelstv 	0x1FBC, 0x1FB3, /* GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI */
   1013  1.11   mlelstv 	0x1FBE, 0x03B9, /* GREEK PROSGEGRAMMENI */
   1014  1.11   mlelstv 	0x1FC8, 0x1F72, /* GREEK CAPITAL LETTER EPSILON WITH VARIA */
   1015  1.11   mlelstv 	0x1FC9, 0x1F73, /* GREEK CAPITAL LETTER EPSILON WITH OXIA */
   1016  1.11   mlelstv 	0x1FCA, 0x1F74, /* GREEK CAPITAL LETTER ETA WITH VARIA */
   1017  1.11   mlelstv 	0x1FCB, 0x1F75, /* GREEK CAPITAL LETTER ETA WITH OXIA */
   1018  1.11   mlelstv 	0x1FCC, 0x1FC3, /* GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI */
   1019  1.11   mlelstv 	0x1FD8, 0x1FD0, /* GREEK CAPITAL LETTER IOTA WITH VRACHY */
   1020  1.11   mlelstv 	0x1FD9, 0x1FD1, /* GREEK CAPITAL LETTER IOTA WITH MACRON */
   1021  1.11   mlelstv 	0x1FDA, 0x1F76, /* GREEK CAPITAL LETTER IOTA WITH VARIA */
   1022  1.11   mlelstv 	0x1FDB, 0x1F77, /* GREEK CAPITAL LETTER IOTA WITH OXIA */
   1023  1.11   mlelstv 	0x1FE8, 0x1FE0, /* GREEK CAPITAL LETTER UPSILON WITH VRACHY */
   1024  1.11   mlelstv 	0x1FE9, 0x1FE1, /* GREEK CAPITAL LETTER UPSILON WITH MACRON */
   1025  1.11   mlelstv 	0x1FEA, 0x1F7A, /* GREEK CAPITAL LETTER UPSILON WITH VARIA */
   1026  1.11   mlelstv 	0x1FEB, 0x1F7B, /* GREEK CAPITAL LETTER UPSILON WITH OXIA */
   1027  1.11   mlelstv 	0x1FEC, 0x1FE5, /* GREEK CAPITAL LETTER RHO WITH DASIA */
   1028  1.11   mlelstv 	0x1FF8, 0x1F78, /* GREEK CAPITAL LETTER OMICRON WITH VARIA */
   1029  1.11   mlelstv 	0x1FF9, 0x1F79, /* GREEK CAPITAL LETTER OMICRON WITH OXIA */
   1030  1.11   mlelstv 	0x1FFA, 0x1F7C, /* GREEK CAPITAL LETTER OMEGA WITH VARIA */
   1031  1.11   mlelstv 	0x1FFB, 0x1F7D, /* GREEK CAPITAL LETTER OMEGA WITH OXIA */
   1032  1.11   mlelstv 	0x1FFC, 0x1FF3, /* GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI */
   1033  1.11   mlelstv 	0x2126, 0x03C9, /* OHM SIGN */
   1034  1.11   mlelstv 	0x212A, 0x006B, /* KELVIN SIGN */
   1035  1.11   mlelstv 	0x212B, 0x00E5, /* ANGSTROM SIGN */
   1036  1.11   mlelstv 	0x2132, 0x214E, /* TURNED CAPITAL F */
   1037  1.11   mlelstv 	0x2160, 0x2170, /* ROMAN NUMERAL ONE */
   1038  1.11   mlelstv 	0x2161, 0x2171, /* ROMAN NUMERAL TWO */
   1039  1.11   mlelstv 	0x2162, 0x2172, /* ROMAN NUMERAL THREE */
   1040  1.11   mlelstv 	0x2163, 0x2173, /* ROMAN NUMERAL FOUR */
   1041  1.11   mlelstv 	0x2164, 0x2174, /* ROMAN NUMERAL FIVE */
   1042  1.11   mlelstv 	0x2165, 0x2175, /* ROMAN NUMERAL SIX */
   1043  1.11   mlelstv 	0x2166, 0x2176, /* ROMAN NUMERAL SEVEN */
   1044  1.11   mlelstv 	0x2167, 0x2177, /* ROMAN NUMERAL EIGHT */
   1045  1.11   mlelstv 	0x2168, 0x2178, /* ROMAN NUMERAL NINE */
   1046  1.11   mlelstv 	0x2169, 0x2179, /* ROMAN NUMERAL TEN */
   1047  1.11   mlelstv 	0x216A, 0x217A, /* ROMAN NUMERAL ELEVEN */
   1048  1.11   mlelstv 	0x216B, 0x217B, /* ROMAN NUMERAL TWELVE */
   1049  1.11   mlelstv 	0x216C, 0x217C, /* ROMAN NUMERAL FIFTY */
   1050  1.11   mlelstv 	0x216D, 0x217D, /* ROMAN NUMERAL ONE HUNDRED */
   1051  1.11   mlelstv 	0x216E, 0x217E, /* ROMAN NUMERAL FIVE HUNDRED */
   1052  1.11   mlelstv 	0x216F, 0x217F, /* ROMAN NUMERAL ONE THOUSAND */
   1053  1.11   mlelstv 	0x2183, 0x2184, /* ROMAN NUMERAL REVERSED ONE HUNDRED */
   1054  1.11   mlelstv 	0x24B6, 0x24D0, /* CIRCLED LATIN CAPITAL LETTER A */
   1055  1.11   mlelstv 	0x24B7, 0x24D1, /* CIRCLED LATIN CAPITAL LETTER B */
   1056  1.11   mlelstv 	0x24B8, 0x24D2, /* CIRCLED LATIN CAPITAL LETTER C */
   1057  1.11   mlelstv 	0x24B9, 0x24D3, /* CIRCLED LATIN CAPITAL LETTER D */
   1058  1.11   mlelstv 	0x24BA, 0x24D4, /* CIRCLED LATIN CAPITAL LETTER E */
   1059  1.11   mlelstv 	0x24BB, 0x24D5, /* CIRCLED LATIN CAPITAL LETTER F */
   1060  1.11   mlelstv 	0x24BC, 0x24D6, /* CIRCLED LATIN CAPITAL LETTER G */
   1061  1.11   mlelstv 	0x24BD, 0x24D7, /* CIRCLED LATIN CAPITAL LETTER H */
   1062  1.11   mlelstv 	0x24BE, 0x24D8, /* CIRCLED LATIN CAPITAL LETTER I */
   1063  1.11   mlelstv 	0x24BF, 0x24D9, /* CIRCLED LATIN CAPITAL LETTER J */
   1064  1.11   mlelstv 	0x24C0, 0x24DA, /* CIRCLED LATIN CAPITAL LETTER K */
   1065  1.11   mlelstv 	0x24C1, 0x24DB, /* CIRCLED LATIN CAPITAL LETTER L */
   1066  1.11   mlelstv 	0x24C2, 0x24DC, /* CIRCLED LATIN CAPITAL LETTER M */
   1067  1.11   mlelstv 	0x24C3, 0x24DD, /* CIRCLED LATIN CAPITAL LETTER N */
   1068  1.11   mlelstv 	0x24C4, 0x24DE, /* CIRCLED LATIN CAPITAL LETTER O */
   1069  1.11   mlelstv 	0x24C5, 0x24DF, /* CIRCLED LATIN CAPITAL LETTER P */
   1070  1.11   mlelstv 	0x24C6, 0x24E0, /* CIRCLED LATIN CAPITAL LETTER Q */
   1071  1.11   mlelstv 	0x24C7, 0x24E1, /* CIRCLED LATIN CAPITAL LETTER R */
   1072  1.11   mlelstv 	0x24C8, 0x24E2, /* CIRCLED LATIN CAPITAL LETTER S */
   1073  1.11   mlelstv 	0x24C9, 0x24E3, /* CIRCLED LATIN CAPITAL LETTER T */
   1074  1.11   mlelstv 	0x24CA, 0x24E4, /* CIRCLED LATIN CAPITAL LETTER U */
   1075  1.11   mlelstv 	0x24CB, 0x24E5, /* CIRCLED LATIN CAPITAL LETTER V */
   1076  1.11   mlelstv 	0x24CC, 0x24E6, /* CIRCLED LATIN CAPITAL LETTER W */
   1077  1.11   mlelstv 	0x24CD, 0x24E7, /* CIRCLED LATIN CAPITAL LETTER X */
   1078  1.11   mlelstv 	0x24CE, 0x24E8, /* CIRCLED LATIN CAPITAL LETTER Y */
   1079  1.11   mlelstv 	0x24CF, 0x24E9, /* CIRCLED LATIN CAPITAL LETTER Z */
   1080  1.11   mlelstv 	0x2C00, 0x2C30, /* GLAGOLITIC CAPITAL LETTER AZU */
   1081  1.11   mlelstv 	0x2C01, 0x2C31, /* GLAGOLITIC CAPITAL LETTER BUKY */
   1082  1.11   mlelstv 	0x2C02, 0x2C32, /* GLAGOLITIC CAPITAL LETTER VEDE */
   1083  1.11   mlelstv 	0x2C03, 0x2C33, /* GLAGOLITIC CAPITAL LETTER GLAGOLI */
   1084  1.11   mlelstv 	0x2C04, 0x2C34, /* GLAGOLITIC CAPITAL LETTER DOBRO */
   1085  1.11   mlelstv 	0x2C05, 0x2C35, /* GLAGOLITIC CAPITAL LETTER YESTU */
   1086  1.11   mlelstv 	0x2C06, 0x2C36, /* GLAGOLITIC CAPITAL LETTER ZHIVETE */
   1087  1.11   mlelstv 	0x2C07, 0x2C37, /* GLAGOLITIC CAPITAL LETTER DZELO */
   1088  1.11   mlelstv 	0x2C08, 0x2C38, /* GLAGOLITIC CAPITAL LETTER ZEMLJA */
   1089  1.11   mlelstv 	0x2C09, 0x2C39, /* GLAGOLITIC CAPITAL LETTER IZHE */
   1090  1.11   mlelstv 	0x2C0A, 0x2C3A, /* GLAGOLITIC CAPITAL LETTER INITIAL IZHE */
   1091  1.11   mlelstv 	0x2C0B, 0x2C3B, /* GLAGOLITIC CAPITAL LETTER I */
   1092  1.11   mlelstv 	0x2C0C, 0x2C3C, /* GLAGOLITIC CAPITAL LETTER DJERVI */
   1093  1.11   mlelstv 	0x2C0D, 0x2C3D, /* GLAGOLITIC CAPITAL LETTER KAKO */
   1094  1.11   mlelstv 	0x2C0E, 0x2C3E, /* GLAGOLITIC CAPITAL LETTER LJUDIJE */
   1095  1.11   mlelstv 	0x2C0F, 0x2C3F, /* GLAGOLITIC CAPITAL LETTER MYSLITE */
   1096  1.11   mlelstv 	0x2C10, 0x2C40, /* GLAGOLITIC CAPITAL LETTER NASHI */
   1097  1.11   mlelstv 	0x2C11, 0x2C41, /* GLAGOLITIC CAPITAL LETTER ONU */
   1098  1.11   mlelstv 	0x2C12, 0x2C42, /* GLAGOLITIC CAPITAL LETTER POKOJI */
   1099  1.11   mlelstv 	0x2C13, 0x2C43, /* GLAGOLITIC CAPITAL LETTER RITSI */
   1100  1.11   mlelstv 	0x2C14, 0x2C44, /* GLAGOLITIC CAPITAL LETTER SLOVO */
   1101  1.11   mlelstv 	0x2C15, 0x2C45, /* GLAGOLITIC CAPITAL LETTER TVRIDO */
   1102  1.11   mlelstv 	0x2C16, 0x2C46, /* GLAGOLITIC CAPITAL LETTER UKU */
   1103  1.11   mlelstv 	0x2C17, 0x2C47, /* GLAGOLITIC CAPITAL LETTER FRITU */
   1104  1.11   mlelstv 	0x2C18, 0x2C48, /* GLAGOLITIC CAPITAL LETTER HERU */
   1105  1.11   mlelstv 	0x2C19, 0x2C49, /* GLAGOLITIC CAPITAL LETTER OTU */
   1106  1.11   mlelstv 	0x2C1A, 0x2C4A, /* GLAGOLITIC CAPITAL LETTER PE */
   1107  1.11   mlelstv 	0x2C1B, 0x2C4B, /* GLAGOLITIC CAPITAL LETTER SHTA */
   1108  1.11   mlelstv 	0x2C1C, 0x2C4C, /* GLAGOLITIC CAPITAL LETTER TSI */
   1109  1.11   mlelstv 	0x2C1D, 0x2C4D, /* GLAGOLITIC CAPITAL LETTER CHRIVI */
   1110  1.11   mlelstv 	0x2C1E, 0x2C4E, /* GLAGOLITIC CAPITAL LETTER SHA */
   1111  1.11   mlelstv 	0x2C1F, 0x2C4F, /* GLAGOLITIC CAPITAL LETTER YERU */
   1112  1.11   mlelstv 	0x2C20, 0x2C50, /* GLAGOLITIC CAPITAL LETTER YERI */
   1113  1.11   mlelstv 	0x2C21, 0x2C51, /* GLAGOLITIC CAPITAL LETTER YATI */
   1114  1.11   mlelstv 	0x2C22, 0x2C52, /* GLAGOLITIC CAPITAL LETTER SPIDERY HA */
   1115  1.11   mlelstv 	0x2C23, 0x2C53, /* GLAGOLITIC CAPITAL LETTER YU */
   1116  1.11   mlelstv 	0x2C24, 0x2C54, /* GLAGOLITIC CAPITAL LETTER SMALL YUS */
   1117  1.11   mlelstv 	0x2C25, 0x2C55, /* GLAGOLITIC CAPITAL LETTER SMALL YUS WITH TAIL */
   1118  1.11   mlelstv 	0x2C26, 0x2C56, /* GLAGOLITIC CAPITAL LETTER YO */
   1119  1.11   mlelstv 	0x2C27, 0x2C57, /* GLAGOLITIC CAPITAL LETTER IOTATED SMALL YUS */
   1120  1.11   mlelstv 	0x2C28, 0x2C58, /* GLAGOLITIC CAPITAL LETTER BIG YUS */
   1121  1.11   mlelstv 	0x2C29, 0x2C59, /* GLAGOLITIC CAPITAL LETTER IOTATED BIG YUS */
   1122  1.11   mlelstv 	0x2C2A, 0x2C5A, /* GLAGOLITIC CAPITAL LETTER FITA */
   1123  1.11   mlelstv 	0x2C2B, 0x2C5B, /* GLAGOLITIC CAPITAL LETTER IZHITSA */
   1124  1.11   mlelstv 	0x2C2C, 0x2C5C, /* GLAGOLITIC CAPITAL LETTER SHTAPIC */
   1125  1.11   mlelstv 	0x2C2D, 0x2C5D, /* GLAGOLITIC CAPITAL LETTER TROKUTASTI A */
   1126  1.11   mlelstv 	0x2C2E, 0x2C5E, /* GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE */
   1127  1.11   mlelstv 	0x2C60, 0x2C61, /* LATIN CAPITAL LETTER L WITH DOUBLE BAR */
   1128  1.11   mlelstv 	0x2C62, 0x026B, /* LATIN CAPITAL LETTER L WITH MIDDLE TILDE */
   1129  1.11   mlelstv 	0x2C63, 0x1D7D, /* LATIN CAPITAL LETTER P WITH STROKE */
   1130  1.11   mlelstv 	0x2C64, 0x027D, /* LATIN CAPITAL LETTER R WITH TAIL */
   1131  1.11   mlelstv 	0x2C67, 0x2C68, /* LATIN CAPITAL LETTER H WITH DESCENDER */
   1132  1.11   mlelstv 	0x2C69, 0x2C6A, /* LATIN CAPITAL LETTER K WITH DESCENDER */
   1133  1.11   mlelstv 	0x2C6B, 0x2C6C, /* LATIN CAPITAL LETTER Z WITH DESCENDER */
   1134  1.11   mlelstv 	0x2C75, 0x2C76, /* LATIN CAPITAL LETTER HALF H */
   1135  1.11   mlelstv 	0x2C80, 0x2C81, /* COPTIC CAPITAL LETTER ALFA */
   1136  1.11   mlelstv 	0x2C82, 0x2C83, /* COPTIC CAPITAL LETTER VIDA */
   1137  1.11   mlelstv 	0x2C84, 0x2C85, /* COPTIC CAPITAL LETTER GAMMA */
   1138  1.11   mlelstv 	0x2C86, 0x2C87, /* COPTIC CAPITAL LETTER DALDA */
   1139  1.11   mlelstv 	0x2C88, 0x2C89, /* COPTIC CAPITAL LETTER EIE */
   1140  1.11   mlelstv 	0x2C8A, 0x2C8B, /* COPTIC CAPITAL LETTER SOU */
   1141  1.11   mlelstv 	0x2C8C, 0x2C8D, /* COPTIC CAPITAL LETTER ZATA */
   1142  1.11   mlelstv 	0x2C8E, 0x2C8F, /* COPTIC CAPITAL LETTER HATE */
   1143  1.11   mlelstv 	0x2C90, 0x2C91, /* COPTIC CAPITAL LETTER THETHE */
   1144  1.11   mlelstv 	0x2C92, 0x2C93, /* COPTIC CAPITAL LETTER IAUDA */
   1145  1.11   mlelstv 	0x2C94, 0x2C95, /* COPTIC CAPITAL LETTER KAPA */
   1146  1.11   mlelstv 	0x2C96, 0x2C97, /* COPTIC CAPITAL LETTER LAULA */
   1147  1.11   mlelstv 	0x2C98, 0x2C99, /* COPTIC CAPITAL LETTER MI */
   1148  1.11   mlelstv 	0x2C9A, 0x2C9B, /* COPTIC CAPITAL LETTER NI */
   1149  1.11   mlelstv 	0x2C9C, 0x2C9D, /* COPTIC CAPITAL LETTER KSI */
   1150  1.11   mlelstv 	0x2C9E, 0x2C9F, /* COPTIC CAPITAL LETTER O */
   1151  1.11   mlelstv 	0x2CA0, 0x2CA1, /* COPTIC CAPITAL LETTER PI */
   1152  1.11   mlelstv 	0x2CA2, 0x2CA3, /* COPTIC CAPITAL LETTER RO */
   1153  1.11   mlelstv 	0x2CA4, 0x2CA5, /* COPTIC CAPITAL LETTER SIMA */
   1154  1.11   mlelstv 	0x2CA6, 0x2CA7, /* COPTIC CAPITAL LETTER TAU */
   1155  1.11   mlelstv 	0x2CA8, 0x2CA9, /* COPTIC CAPITAL LETTER UA */
   1156  1.11   mlelstv 	0x2CAA, 0x2CAB, /* COPTIC CAPITAL LETTER FI */
   1157  1.11   mlelstv 	0x2CAC, 0x2CAD, /* COPTIC CAPITAL LETTER KHI */
   1158  1.11   mlelstv 	0x2CAE, 0x2CAF, /* COPTIC CAPITAL LETTER PSI */
   1159  1.11   mlelstv 	0x2CB0, 0x2CB1, /* COPTIC CAPITAL LETTER OOU */
   1160  1.11   mlelstv 	0x2CB2, 0x2CB3, /* COPTIC CAPITAL LETTER DIALECT-P ALEF */
   1161  1.11   mlelstv 	0x2CB4, 0x2CB5, /* COPTIC CAPITAL LETTER OLD COPTIC AIN */
   1162  1.11   mlelstv 	0x2CB6, 0x2CB7, /* COPTIC CAPITAL LETTER CRYPTOGRAMMIC EIE */
   1163  1.11   mlelstv 	0x2CB8, 0x2CB9, /* COPTIC CAPITAL LETTER DIALECT-P KAPA */
   1164  1.11   mlelstv 	0x2CBA, 0x2CBB, /* COPTIC CAPITAL LETTER DIALECT-P NI */
   1165  1.11   mlelstv 	0x2CBC, 0x2CBD, /* COPTIC CAPITAL LETTER CRYPTOGRAMMIC NI */
   1166  1.11   mlelstv 	0x2CBE, 0x2CBF, /* COPTIC CAPITAL LETTER OLD COPTIC OOU */
   1167  1.11   mlelstv 	0x2CC0, 0x2CC1, /* COPTIC CAPITAL LETTER SAMPI */
   1168  1.11   mlelstv 	0x2CC2, 0x2CC3, /* COPTIC CAPITAL LETTER CROSSED SHEI */
   1169  1.11   mlelstv 	0x2CC4, 0x2CC5, /* COPTIC CAPITAL LETTER OLD COPTIC SHEI */
   1170  1.11   mlelstv 	0x2CC6, 0x2CC7, /* COPTIC CAPITAL LETTER OLD COPTIC ESH */
   1171  1.11   mlelstv 	0x2CC8, 0x2CC9, /* COPTIC CAPITAL LETTER AKHMIMIC KHEI */
   1172  1.11   mlelstv 	0x2CCA, 0x2CCB, /* COPTIC CAPITAL LETTER DIALECT-P HORI */
   1173  1.11   mlelstv 	0x2CCC, 0x2CCD, /* COPTIC CAPITAL LETTER OLD COPTIC HORI */
   1174  1.11   mlelstv 	0x2CCE, 0x2CCF, /* COPTIC CAPITAL LETTER OLD COPTIC HA */
   1175  1.11   mlelstv 	0x2CD0, 0x2CD1, /* COPTIC CAPITAL LETTER L-SHAPED HA */
   1176  1.11   mlelstv 	0x2CD2, 0x2CD3, /* COPTIC CAPITAL LETTER OLD COPTIC HEI */
   1177  1.11   mlelstv 	0x2CD4, 0x2CD5, /* COPTIC CAPITAL LETTER OLD COPTIC HAT */
   1178  1.11   mlelstv 	0x2CD6, 0x2CD7, /* COPTIC CAPITAL LETTER OLD COPTIC GANGIA */
   1179  1.11   mlelstv 	0x2CD8, 0x2CD9, /* COPTIC CAPITAL LETTER OLD COPTIC DJA */
   1180  1.11   mlelstv 	0x2CDA, 0x2CDB, /* COPTIC CAPITAL LETTER OLD COPTIC SHIMA */
   1181  1.11   mlelstv 	0x2CDC, 0x2CDD, /* COPTIC CAPITAL LETTER OLD NUBIAN SHIMA */
   1182  1.11   mlelstv 	0x2CDE, 0x2CDF, /* COPTIC CAPITAL LETTER OLD NUBIAN NGI */
   1183  1.11   mlelstv 	0x2CE0, 0x2CE1, /* COPTIC CAPITAL LETTER OLD NUBIAN NYI */
   1184  1.11   mlelstv 	0x2CE2, 0x2CE3, /* COPTIC CAPITAL LETTER OLD NUBIAN WAU */
   1185  1.11   mlelstv 	0xFF21, 0xFF41, /* FULLWIDTH LATIN CAPITAL LETTER A */
   1186  1.11   mlelstv 	0xFF22, 0xFF42, /* FULLWIDTH LATIN CAPITAL LETTER B */
   1187  1.11   mlelstv 	0xFF23, 0xFF43, /* FULLWIDTH LATIN CAPITAL LETTER C */
   1188  1.11   mlelstv 	0xFF24, 0xFF44, /* FULLWIDTH LATIN CAPITAL LETTER D */
   1189  1.11   mlelstv 	0xFF25, 0xFF45, /* FULLWIDTH LATIN CAPITAL LETTER E */
   1190  1.11   mlelstv 	0xFF26, 0xFF46, /* FULLWIDTH LATIN CAPITAL LETTER F */
   1191  1.11   mlelstv 	0xFF27, 0xFF47, /* FULLWIDTH LATIN CAPITAL LETTER G */
   1192  1.11   mlelstv 	0xFF28, 0xFF48, /* FULLWIDTH LATIN CAPITAL LETTER H */
   1193  1.11   mlelstv 	0xFF29, 0xFF49, /* FULLWIDTH LATIN CAPITAL LETTER I */
   1194  1.11   mlelstv 	0xFF2A, 0xFF4A, /* FULLWIDTH LATIN CAPITAL LETTER J */
   1195  1.11   mlelstv 	0xFF2B, 0xFF4B, /* FULLWIDTH LATIN CAPITAL LETTER K */
   1196  1.11   mlelstv 	0xFF2C, 0xFF4C, /* FULLWIDTH LATIN CAPITAL LETTER L */
   1197  1.11   mlelstv 	0xFF2D, 0xFF4D, /* FULLWIDTH LATIN CAPITAL LETTER M */
   1198  1.11   mlelstv 	0xFF2E, 0xFF4E, /* FULLWIDTH LATIN CAPITAL LETTER N */
   1199  1.11   mlelstv 	0xFF2F, 0xFF4F, /* FULLWIDTH LATIN CAPITAL LETTER O */
   1200  1.11   mlelstv 	0xFF30, 0xFF50, /* FULLWIDTH LATIN CAPITAL LETTER P */
   1201  1.11   mlelstv 	0xFF31, 0xFF51, /* FULLWIDTH LATIN CAPITAL LETTER Q */
   1202  1.11   mlelstv 	0xFF32, 0xFF52, /* FULLWIDTH LATIN CAPITAL LETTER R */
   1203  1.11   mlelstv 	0xFF33, 0xFF53, /* FULLWIDTH LATIN CAPITAL LETTER S */
   1204  1.11   mlelstv 	0xFF34, 0xFF54, /* FULLWIDTH LATIN CAPITAL LETTER T */
   1205  1.11   mlelstv 	0xFF35, 0xFF55, /* FULLWIDTH LATIN CAPITAL LETTER U */
   1206  1.11   mlelstv 	0xFF36, 0xFF56, /* FULLWIDTH LATIN CAPITAL LETTER V */
   1207  1.11   mlelstv 	0xFF37, 0xFF57, /* FULLWIDTH LATIN CAPITAL LETTER W */
   1208  1.11   mlelstv 	0xFF38, 0xFF58, /* FULLWIDTH LATIN CAPITAL LETTER X */
   1209  1.11   mlelstv 	0xFF39, 0xFF59, /* FULLWIDTH LATIN CAPITAL LETTER Y */
   1210  1.11   mlelstv 	0xFF3A, 0xFF5A, /* FULLWIDTH LATIN CAPITAL LETTER Z */
   1211  1.11   mlelstv };
   1212  1.11   mlelstv 
   1213   1.1  jdolecek /*
   1214   1.1  jdolecek  * DOS filenames are made of 2 parts, the name part and the extension part.
   1215   1.1  jdolecek  * The name part is 8 characters long and the extension part is 3
   1216   1.1  jdolecek  * characters long.  They may contain trailing blanks if the name or
   1217   1.1  jdolecek  * extension are not long enough to fill their respective fields.
   1218   1.1  jdolecek  */
   1219   1.1  jdolecek 
   1220   1.1  jdolecek /*
   1221   1.1  jdolecek  * Convert a DOS filename to a unix filename. And, return the number of
   1222   1.1  jdolecek  * characters in the resulting unix filename excluding the terminating
   1223   1.1  jdolecek  * null.
   1224   1.1  jdolecek  */
   1225   1.1  jdolecek int
   1226   1.7    cegger dos2unixfn(u_char dn[11], u_char *un, int lower)
   1227   1.1  jdolecek {
   1228   1.1  jdolecek 	int i, j;
   1229   1.1  jdolecek 	int thislong = 1;
   1230   1.1  jdolecek 	u_char c;
   1231   1.1  jdolecek 
   1232   1.1  jdolecek 	/*
   1233   1.1  jdolecek 	 * If first char of the filename is SLOT_E5 (0x05), then the real
   1234   1.1  jdolecek 	 * first char of the filename should be 0xe5. But, they couldn't
   1235   1.1  jdolecek 	 * just have a 0xe5 mean 0xe5 because that is used to mean a freed
   1236   1.1  jdolecek 	 * directory slot. Another dos quirk.
   1237   1.1  jdolecek 	 */
   1238   1.1  jdolecek 	if (*dn == SLOT_E5)
   1239   1.1  jdolecek 		c = dos2unix[0xe5];
   1240   1.1  jdolecek 	else
   1241   1.1  jdolecek 		c = dos2unix[*dn];
   1242   1.1  jdolecek 	*un++ = lower ? u2l[c] : c;
   1243   1.1  jdolecek 
   1244   1.1  jdolecek 	/*
   1245   1.1  jdolecek 	 * Copy the rest into the unix filename string, ignoring
   1246   1.1  jdolecek 	 * trailing blanks.
   1247   1.1  jdolecek 	 */
   1248   1.1  jdolecek 
   1249   1.1  jdolecek 	for (j=7; (j >= 0) && (dn[j] == ' '); j--)
   1250   1.1  jdolecek 		;
   1251   1.1  jdolecek 
   1252   1.1  jdolecek 	for (i = 1; i <= j; i++) {
   1253   1.1  jdolecek 		c = dos2unix[dn[i]];
   1254   1.1  jdolecek 		*un++ = lower ? u2l[c] : c;
   1255   1.1  jdolecek 		thislong++;
   1256   1.1  jdolecek 	}
   1257   1.1  jdolecek 	dn += 8;
   1258   1.3     perry 
   1259   1.1  jdolecek 	/*
   1260   1.1  jdolecek 	 * Now, if there is an extension then put in a period and copy in
   1261   1.1  jdolecek 	 * the extension.
   1262   1.1  jdolecek 	 */
   1263   1.1  jdolecek 	if (*dn != ' ') {
   1264   1.1  jdolecek 		*un++ = '.';
   1265   1.1  jdolecek 		thislong++;
   1266   1.1  jdolecek 		for (i = 0; i < 3 && *dn != ' '; i++) {
   1267   1.1  jdolecek 			c = dos2unix[*dn++];
   1268   1.1  jdolecek 			*un++ = lower ? u2l[c] : c;
   1269   1.1  jdolecek 			thislong++;
   1270   1.1  jdolecek 		}
   1271   1.1  jdolecek 	}
   1272   1.1  jdolecek 	*un++ = 0;
   1273   1.1  jdolecek 
   1274   1.1  jdolecek 	return (thislong);
   1275   1.1  jdolecek }
   1276   1.1  jdolecek 
   1277   1.1  jdolecek /*
   1278   1.1  jdolecek  * Convert a unix filename to a DOS filename according to Win95 rules.
   1279   1.1  jdolecek  * If applicable and gen is not 0, it is inserted into the converted
   1280   1.1  jdolecek  * filename as a generation number.
   1281   1.1  jdolecek  * Returns
   1282   1.1  jdolecek  *	0 if name couldn't be converted
   1283   1.1  jdolecek  *	1 if the converted name is the same as the original
   1284   1.1  jdolecek  *	  (no long filename entry necessary for Win95)
   1285   1.1  jdolecek  *	2 if conversion was successful
   1286   1.1  jdolecek  *	3 if conversion was successful and generation number was inserted
   1287   1.1  jdolecek  */
   1288   1.1  jdolecek int
   1289   1.7    cegger unix2dosfn(const u_char *un, u_char dn[12], int unlen, u_int gen)
   1290   1.1  jdolecek {
   1291   1.1  jdolecek 	int i, j, l;
   1292   1.1  jdolecek 	int conv = 1;
   1293   1.1  jdolecek 	const u_char *cp, *dp, *dp1;
   1294   1.1  jdolecek 	u_char gentext[6], *wcp;
   1295   1.1  jdolecek 	int shortlen;
   1296   1.1  jdolecek 
   1297   1.1  jdolecek 	/*
   1298   1.1  jdolecek 	 * Fill the dos filename string with blanks. These are DOS's pad
   1299   1.1  jdolecek 	 * characters.
   1300   1.1  jdolecek 	 */
   1301   1.1  jdolecek 	for (i = 0; i < 11; i++)
   1302   1.1  jdolecek 		dn[i] = ' ';
   1303   1.1  jdolecek 	dn[11] = 0;
   1304   1.1  jdolecek 
   1305   1.1  jdolecek 	/*
   1306   1.1  jdolecek 	 * The filenames "." and ".." are handled specially, since they
   1307   1.1  jdolecek 	 * don't follow dos filename rules.
   1308   1.1  jdolecek 	 */
   1309   1.1  jdolecek 	if (un[0] == '.' && unlen == 1) {
   1310   1.1  jdolecek 		dn[0] = '.';
   1311   1.1  jdolecek 		return gen <= 1;
   1312   1.1  jdolecek 	}
   1313   1.1  jdolecek 	if (un[0] == '.' && un[1] == '.' && unlen == 2) {
   1314   1.1  jdolecek 		dn[0] = '.';
   1315   1.1  jdolecek 		dn[1] = '.';
   1316   1.1  jdolecek 		return gen <= 1;
   1317   1.1  jdolecek 	}
   1318   1.1  jdolecek 
   1319   1.1  jdolecek 	/*
   1320   1.1  jdolecek 	 * Filenames with only blanks and dots are not allowed!
   1321   1.1  jdolecek 	 */
   1322   1.1  jdolecek 	for (cp = un, i = unlen; --i >= 0; cp++)
   1323   1.1  jdolecek 		if (*cp != ' ' && *cp != '.')
   1324   1.1  jdolecek 			break;
   1325   1.1  jdolecek 	if (i < 0)
   1326   1.1  jdolecek 		return 0;
   1327   1.1  jdolecek 
   1328   1.1  jdolecek 	/*
   1329   1.1  jdolecek 	 * Now find the extension
   1330   1.1  jdolecek 	 * Note: dot as first char doesn't start extension
   1331   1.1  jdolecek 	 *	 and trailing dots and blanks are ignored
   1332   1.1  jdolecek 	 */
   1333   1.1  jdolecek 	dp = dp1 = 0;
   1334   1.1  jdolecek 	for (cp = un + 1, i = unlen - 1; --i >= 0;) {
   1335   1.1  jdolecek 		switch (*cp++) {
   1336   1.1  jdolecek 		case '.':
   1337   1.1  jdolecek 			if (!dp1)
   1338   1.1  jdolecek 				dp1 = cp;
   1339   1.1  jdolecek 			break;
   1340   1.1  jdolecek 		case ' ':
   1341   1.1  jdolecek 			break;
   1342   1.1  jdolecek 		default:
   1343   1.1  jdolecek 			if (dp1)
   1344   1.1  jdolecek 				dp = dp1;
   1345   1.1  jdolecek 			dp1 = 0;
   1346   1.1  jdolecek 			break;
   1347   1.1  jdolecek 		}
   1348   1.1  jdolecek 	}
   1349   1.1  jdolecek 
   1350   1.1  jdolecek 	/*
   1351   1.1  jdolecek 	 * Now convert it
   1352   1.1  jdolecek 	 */
   1353   1.1  jdolecek 	if (dp) {
   1354   1.1  jdolecek 		if (dp1)
   1355   1.1  jdolecek 			l = dp1 - dp;
   1356   1.1  jdolecek 		else
   1357   1.1  jdolecek 			l = unlen - (dp - un);
   1358   1.1  jdolecek 		for (i = 0, j = 8; i < l && j < 11; i++, j++) {
   1359   1.1  jdolecek 			if (dp[i] != (dn[j] = unix2dos[dp[i]])
   1360   1.1  jdolecek 			    && conv != 3)
   1361   1.1  jdolecek 				conv = 2;
   1362   1.1  jdolecek 			if (!dn[j]) {
   1363   1.1  jdolecek 				conv = 3;
   1364   1.1  jdolecek 				dn[j--] = ' ';
   1365   1.1  jdolecek 			}
   1366   1.1  jdolecek 		}
   1367   1.1  jdolecek 		if (i < l)
   1368   1.1  jdolecek 			conv = 3;
   1369   1.1  jdolecek 		dp--;
   1370   1.1  jdolecek 	} else {
   1371   1.1  jdolecek 		for (dp = cp; *--dp == ' ' || *dp == '.';);
   1372   1.1  jdolecek 		dp++;
   1373   1.1  jdolecek 	}
   1374   1.1  jdolecek 
   1375   1.1  jdolecek 	shortlen = (dp - un) <= 8;
   1376   1.1  jdolecek 
   1377   1.1  jdolecek 	/*
   1378   1.1  jdolecek 	 * Now convert the rest of the name
   1379   1.1  jdolecek 	 */
   1380   1.1  jdolecek 	for (i = j = 0; un < dp && j < 8; i++, j++, un++) {
   1381   1.1  jdolecek 		if ((*un == ' ') && shortlen)
   1382   1.1  jdolecek 			dn[j] = ' ';
   1383   1.1  jdolecek 		else
   1384   1.1  jdolecek 			dn[j] = unix2dos[*un];
   1385   1.1  jdolecek 		if ((*un != dn[j])
   1386   1.1  jdolecek 		    && conv != 3)
   1387   1.1  jdolecek 			conv = 2;
   1388   1.1  jdolecek 		if (!dn[j]) {
   1389   1.1  jdolecek 			conv = 3;
   1390   1.1  jdolecek 			dn[j--] = ' ';
   1391   1.1  jdolecek 		}
   1392   1.1  jdolecek 	}
   1393   1.1  jdolecek 	if (un < dp)
   1394   1.1  jdolecek 		conv = 3;
   1395   1.1  jdolecek 	/*
   1396   1.1  jdolecek 	 * If we didn't have any chars in filename,
   1397   1.1  jdolecek 	 * generate a default
   1398   1.1  jdolecek 	 */
   1399   1.1  jdolecek 	if (!j)
   1400   1.1  jdolecek 		dn[0] = '_';
   1401   1.1  jdolecek 
   1402   1.1  jdolecek 	/*
   1403   1.1  jdolecek 	 * The first character cannot be E5,
   1404   1.1  jdolecek 	 * because that means a deleted entry
   1405   1.1  jdolecek 	 */
   1406   1.1  jdolecek 	if (dn[0] == 0xe5)
   1407   1.1  jdolecek 		dn[0] = SLOT_E5;
   1408   1.1  jdolecek 
   1409   1.1  jdolecek 	/*
   1410   1.1  jdolecek 	 * If there wasn't any char dropped,
   1411   1.1  jdolecek 	 * there is no place for generation numbers
   1412   1.1  jdolecek 	 */
   1413   1.1  jdolecek 	if (conv != 3) {
   1414   1.1  jdolecek 		if (gen > 1)
   1415   1.1  jdolecek 			return 0;
   1416   1.1  jdolecek 		return conv;
   1417   1.1  jdolecek 	}
   1418   1.1  jdolecek 
   1419   1.1  jdolecek 	/*
   1420   1.1  jdolecek 	 * Now insert the generation number into the filename part
   1421   1.1  jdolecek 	 */
   1422   1.1  jdolecek 	for (wcp = gentext + sizeof(gentext); wcp > gentext && gen; gen /= 10)
   1423   1.1  jdolecek 		*--wcp = gen % 10 + '0';
   1424   1.1  jdolecek 	if (gen)
   1425   1.1  jdolecek 		return 0;
   1426   1.1  jdolecek 	for (i = 8; dn[--i] == ' ';);
   1427   1.1  jdolecek 	i++;
   1428   1.1  jdolecek 	if (gentext + sizeof(gentext) - wcp + 1 > 8 - i)
   1429   1.1  jdolecek 		i = 8 - (gentext + sizeof(gentext) - wcp + 1);
   1430   1.1  jdolecek 	dn[i++] = '~';
   1431   1.1  jdolecek 	while (wcp < gentext + sizeof(gentext))
   1432   1.1  jdolecek 		dn[i++] = *wcp++;
   1433   1.1  jdolecek 	return 3;
   1434   1.1  jdolecek }
   1435   1.1  jdolecek 
   1436   1.1  jdolecek /*
   1437   1.1  jdolecek  * Create a Win95 long name directory entry
   1438   1.1  jdolecek  * Note: assumes that the filename is valid,
   1439   1.1  jdolecek  *	 i.e. doesn't consist solely of blanks and dots
   1440   1.1  jdolecek  */
   1441   1.1  jdolecek int
   1442  1.11   mlelstv unix2winfn(const u_char *un, int unlen, struct winentry *wep, int cnt, int chksum, int utf8)
   1443   1.1  jdolecek {
   1444  1.11   mlelstv 	u_int16_t wn[WIN_MAXLEN], *p;
   1445  1.11   mlelstv 	int i, len;
   1446  1.11   mlelstv 	const u_char *cp;
   1447   1.1  jdolecek 
   1448   1.1  jdolecek 	/*
   1449   1.1  jdolecek 	 * Drop trailing blanks and dots
   1450   1.1  jdolecek 	 */
   1451  1.11   mlelstv 	for (cp = un + unlen; unlen > 0; unlen--)
   1452  1.11   mlelstv 		if (*--cp != ' ' && *cp != '.')
   1453  1.11   mlelstv 			break;
   1454   1.1  jdolecek 
   1455  1.11   mlelstv 	/*
   1456  1.11   mlelstv 	 * Offset of this entry
   1457  1.11   mlelstv 	 */
   1458  1.11   mlelstv 	i = (cnt - 1) * WIN_CHARS;
   1459  1.11   mlelstv 
   1460  1.11   mlelstv 	/*
   1461  1.11   mlelstv 	 * Translate UNIX name to ucs-2
   1462  1.11   mlelstv 	 */
   1463  1.11   mlelstv 	len = utf8 ? utf8ucs2str(un, unlen, wn, WIN_MAXLEN) : char8ucs2str(un, unlen, wn, WIN_MAXLEN);
   1464  1.11   mlelstv 	ucs2pad(wn, len, WIN_MAXLEN);
   1465   1.1  jdolecek 
   1466   1.1  jdolecek 	/*
   1467   1.1  jdolecek 	 * Initialize winentry to some useful default
   1468   1.1  jdolecek 	 */
   1469  1.11   mlelstv 	memset(wep, 0xff, sizeof(*wep));
   1470   1.1  jdolecek 	wep->weCnt = cnt;
   1471   1.1  jdolecek 	wep->weAttributes = ATTR_WIN95;
   1472   1.1  jdolecek 	wep->weReserved1 = 0;
   1473   1.1  jdolecek 	wep->weChksum = chksum;
   1474   1.1  jdolecek 	wep->weReserved2 = 0;
   1475   1.1  jdolecek 
   1476   1.1  jdolecek 	/*
   1477  1.11   mlelstv 	 * Store name segment into directory entry
   1478   1.1  jdolecek 	 */
   1479  1.11   mlelstv 	p = &wn[i];
   1480  1.11   mlelstv 	memcpy(wep->wePart1, p, sizeof(wep->wePart1));
   1481  1.11   mlelstv 	p += sizeof(wep->wePart1) / sizeof(*p);
   1482  1.11   mlelstv 	memcpy(wep->wePart2, p, sizeof(wep->wePart2));
   1483  1.11   mlelstv 	p += sizeof(wep->wePart2) / sizeof(*p);
   1484  1.11   mlelstv 	memcpy(wep->wePart3, p, sizeof(wep->wePart3));
   1485  1.11   mlelstv 
   1486  1.11   mlelstv 	if (len > i + WIN_CHARS)
   1487  1.11   mlelstv 		return 1;
   1488  1.11   mlelstv 
   1489   1.1  jdolecek 	wep->weCnt |= WIN_LAST;
   1490   1.1  jdolecek 	return 0;
   1491   1.1  jdolecek }
   1492   1.1  jdolecek 
   1493   1.1  jdolecek /*
   1494   1.1  jdolecek  * Compare our filename to the one in the Win95 entry
   1495   1.1  jdolecek  * Returns the checksum or -1 if no match
   1496   1.1  jdolecek  */
   1497   1.1  jdolecek int
   1498  1.11   mlelstv winChkName(const u_char *un, int unlen, struct winentry *wep, int chksum, int utf8)
   1499   1.1  jdolecek {
   1500  1.11   mlelstv 	u_int16_t wn[WIN_MAXLEN], *p;
   1501  1.11   mlelstv 	u_int16_t buf[WIN_CHARS];
   1502  1.11   mlelstv 	int i, len;
   1503   1.1  jdolecek 
   1504   1.1  jdolecek 	/*
   1505   1.1  jdolecek 	 * First compare checksums
   1506   1.1  jdolecek 	 */
   1507  1.11   mlelstv 	if (wep->weCnt & WIN_LAST)
   1508   1.1  jdolecek 		chksum = wep->weChksum;
   1509   1.1  jdolecek 	else if (chksum != wep->weChksum)
   1510   1.1  jdolecek 		chksum = -1;
   1511   1.1  jdolecek 	if (chksum == -1)
   1512   1.1  jdolecek 		return -1;
   1513   1.1  jdolecek 
   1514   1.1  jdolecek 	/*
   1515   1.1  jdolecek 	 * Offset of this entry
   1516   1.1  jdolecek 	 */
   1517  1.11   mlelstv 	i = ((wep->weCnt & WIN_CNT) - 1) * WIN_CHARS;
   1518   1.1  jdolecek 
   1519   1.1  jdolecek 	/*
   1520  1.11   mlelstv 	 * Translate UNIX name to ucs-2
   1521  1.11   mlelstv 	 */
   1522  1.11   mlelstv 	len = utf8 ? utf8ucs2str(un, unlen, wn, WIN_MAXLEN) : char8ucs2str(un, unlen, wn, WIN_MAXLEN);
   1523  1.11   mlelstv 	ucs2pad(wn, len, WIN_MAXLEN);
   1524   1.1  jdolecek 
   1525  1.11   mlelstv 	if (i >= len + 1)
   1526   1.1  jdolecek 		return -1;
   1527   1.1  jdolecek 
   1528   1.1  jdolecek 	/*
   1529  1.11   mlelstv 	 * Fetch name segment from directory entry
   1530  1.11   mlelstv 	 */
   1531  1.11   mlelstv 	p = &buf[0];
   1532  1.11   mlelstv 	memcpy(p, wep->wePart1, sizeof(wep->wePart1));
   1533  1.11   mlelstv 	p += sizeof(wep->wePart1) / sizeof(*p);
   1534  1.11   mlelstv 	memcpy(p, wep->wePart2, sizeof(wep->wePart2));
   1535  1.11   mlelstv 	p += sizeof(wep->wePart2) / sizeof(*p);
   1536  1.11   mlelstv 	memcpy(p, wep->wePart3, sizeof(wep->wePart3));
   1537  1.11   mlelstv 
   1538  1.11   mlelstv 	/*
   1539  1.11   mlelstv 	 * And compare name segment
   1540   1.1  jdolecek 	 */
   1541  1.11   mlelstv 	if (! (utf8 ? ucs2match(&wn[i], buf, WIN_CHARS) : char8match(&wn[i], buf, WIN_CHARS)))
   1542  1.11   mlelstv 		return -1;
   1543  1.11   mlelstv 
   1544   1.1  jdolecek 	return chksum;
   1545   1.1  jdolecek }
   1546   1.1  jdolecek 
   1547   1.1  jdolecek /*
   1548   1.1  jdolecek  * Convert Win95 filename to dirbuf.
   1549   1.1  jdolecek  * Returns the checksum or -1 if impossible
   1550   1.1  jdolecek  */
   1551   1.1  jdolecek int
   1552  1.11   mlelstv win2unixfn(struct winentry *wep, struct dirent *dp, int chksum, int utf8)
   1553   1.1  jdolecek {
   1554  1.11   mlelstv 	u_int16_t wn[WIN_CHARS], *p;
   1555  1.11   mlelstv 	u_int8_t buf[WIN_CHARS*3];
   1556  1.11   mlelstv 	int len;
   1557   1.1  jdolecek 
   1558  1.11   mlelstv 	if ((wep->weCnt & WIN_CNT) > howmany(WIN_MAXLEN, WIN_CHARS)
   1559  1.11   mlelstv 	    || !(wep->weCnt & WIN_CNT))
   1560   1.1  jdolecek 		return -1;
   1561   1.1  jdolecek 
   1562   1.1  jdolecek 	/*
   1563   1.1  jdolecek 	 * First compare checksums
   1564   1.1  jdolecek 	 */
   1565  1.11   mlelstv 	if (wep->weCnt & WIN_LAST) {
   1566   1.1  jdolecek 		chksum = wep->weChksum;
   1567  1.11   mlelstv 		dp->d_namlen = 0;
   1568   1.1  jdolecek 	} else if (chksum != wep->weChksum)
   1569   1.1  jdolecek 		chksum = -1;
   1570   1.1  jdolecek 	if (chksum == -1)
   1571   1.1  jdolecek 		return -1;
   1572   1.1  jdolecek 
   1573   1.1  jdolecek 	/*
   1574  1.11   mlelstv 	 * Fetch name segment from directory entry
   1575  1.11   mlelstv 	 */
   1576  1.11   mlelstv 	p = &wn[0];
   1577  1.11   mlelstv 	memcpy(p, wep->wePart1, sizeof(wep->wePart1));
   1578  1.11   mlelstv 	p += sizeof(wep->wePart1) / sizeof(*p);
   1579  1.11   mlelstv 	memcpy(p, wep->wePart2, sizeof(wep->wePart2));
   1580  1.11   mlelstv 	p += sizeof(wep->wePart2) / sizeof(*p);
   1581  1.11   mlelstv 	memcpy(p, wep->wePart3, sizeof(wep->wePart3));
   1582  1.11   mlelstv 
   1583  1.11   mlelstv 	/*
   1584  1.11   mlelstv 	 * Don't allow slashes in UNIX names. Discard that entry.
   1585   1.1  jdolecek 	 */
   1586  1.11   mlelstv 	if (invalidname(wn, WIN_CHARS))
   1587  1.11   mlelstv 		return -1;
   1588   1.1  jdolecek 
   1589   1.1  jdolecek 	/*
   1590  1.11   mlelstv 	 * Translate ucs-2 to UNIX name
   1591   1.1  jdolecek 	 */
   1592  1.11   mlelstv 	len = utf8 ? ucs2utf8str(wn, WIN_CHARS, buf, sizeof(buf)) : ucs2char8str(wn, WIN_CHARS, buf, sizeof(buf));
   1593  1.11   mlelstv 
   1594  1.11   mlelstv 	/*
   1595  1.11   mlelstv 	 * Prepend name segment to directory entry
   1596  1.11   mlelstv 	 *
   1597  1.11   mlelstv 	 * This ignores the slot number from the windows entry but
   1598  1.11   mlelstv 	 * assumes that segments are read in reverse order.
   1599  1.11   mlelstv 	 *
   1600  1.11   mlelstv 	 * The UCS-2 name (up to 255 chars) can overflow the UNIX
   1601  1.11   mlelstv 	 * directory entry (up to 511 bytes). Trailing characters
   1602  1.11   mlelstv 	 * are silently discarded. This could also end in multiple
   1603  1.11   mlelstv 	 * files using the same (truncated) name.
   1604  1.11   mlelstv 	 */
   1605  1.11   mlelstv 	dp->d_namlen += len;
   1606  1.11   mlelstv 	if (dp->d_namlen > sizeof(dp->d_name)-1)
   1607  1.11   mlelstv 		dp->d_namlen = sizeof(dp->d_name)-1;
   1608  1.11   mlelstv 	memmove(&dp->d_name[len], &dp->d_name[0], dp->d_namlen - len);
   1609  1.11   mlelstv 	memcpy(dp->d_name, buf, len);
   1610  1.11   mlelstv 
   1611   1.1  jdolecek 	return chksum;
   1612   1.1  jdolecek }
   1613   1.1  jdolecek 
   1614   1.1  jdolecek /*
   1615   1.1  jdolecek  * Compute the checksum of a DOS filename for Win95 use
   1616   1.1  jdolecek  */
   1617   1.1  jdolecek u_int8_t
   1618   1.6       dsl winChksum(u_int8_t *name)
   1619   1.1  jdolecek {
   1620   1.1  jdolecek 	int i;
   1621   1.1  jdolecek 	u_int8_t s;
   1622   1.1  jdolecek 
   1623   1.1  jdolecek 	for (s = 0, i = 11; --i >= 0; s += *name++)
   1624  1.11   mlelstv 		s = (s << 7) | (s >> 1);
   1625   1.1  jdolecek 	return s;
   1626   1.1  jdolecek }
   1627   1.1  jdolecek 
   1628   1.1  jdolecek /*
   1629   1.1  jdolecek  * Determine the number of slots necessary for Win95 names
   1630   1.1  jdolecek  */
   1631   1.1  jdolecek int
   1632  1.11   mlelstv winSlotCnt(const u_char *un, int unlen, int utf8)
   1633   1.1  jdolecek {
   1634  1.11   mlelstv 	const u_char *cp;
   1635  1.11   mlelstv 	int len;
   1636  1.11   mlelstv 
   1637  1.11   mlelstv 	/*
   1638  1.11   mlelstv 	 * Drop trailing blanks and dots
   1639  1.11   mlelstv 	 */
   1640  1.11   mlelstv 	for (cp = un + unlen; unlen > 0; unlen--)
   1641  1.11   mlelstv 		if (*--cp != ' ' && *cp != '.')
   1642   1.1  jdolecek 			break;
   1643  1.11   mlelstv 
   1644  1.11   mlelstv 	len = utf8 ? utf8ucs2str(un, unlen, NULL, WIN_MAXLEN) : unlen;
   1645  1.11   mlelstv 
   1646  1.11   mlelstv 	return howmany(len, WIN_CHARS);
   1647  1.11   mlelstv }
   1648  1.11   mlelstv 
   1649  1.11   mlelstv /*
   1650  1.11   mlelstv  * Scan windows name for characters that must not
   1651  1.11   mlelstv  * appear in a UNIX filename
   1652  1.11   mlelstv  */
   1653  1.11   mlelstv static int
   1654  1.11   mlelstv invalidname(const u_int16_t *in, int n)
   1655  1.11   mlelstv {
   1656  1.11   mlelstv 	while (n-- > 0) {
   1657  1.11   mlelstv 		if (*in++ == '/')
   1658  1.11   mlelstv 			return 1;
   1659  1.11   mlelstv 	}
   1660  1.11   mlelstv 
   1661  1.11   mlelstv 	return 0;
   1662  1.11   mlelstv }
   1663  1.11   mlelstv 
   1664  1.11   mlelstv /*
   1665  1.11   mlelstv  * Convert UCS-2 character into UTF-8
   1666  1.11   mlelstv  * return number of output bytes or 0 if output
   1667  1.11   mlelstv  * buffer is too short
   1668  1.11   mlelstv  */
   1669  1.11   mlelstv static int
   1670  1.11   mlelstv ucs2utf8(const u_int16_t *in, u_int8_t *out, int n)
   1671  1.11   mlelstv {
   1672  1.11   mlelstv 	uint16_t inch = le16toh(in[0]);
   1673  1.11   mlelstv 
   1674  1.11   mlelstv 	if (inch <= 0x007f) {
   1675  1.11   mlelstv 		if (n < 1) return 0;
   1676  1.11   mlelstv 		if (out)
   1677  1.11   mlelstv 			*out++ = inch;
   1678  1.11   mlelstv 		return 1;
   1679  1.11   mlelstv 	} else if (inch <= 0x07ff) {
   1680  1.11   mlelstv 		if (n < 2) return 0;
   1681  1.11   mlelstv 		if (out) {
   1682  1.11   mlelstv 			*out++ = 0xc0 | (inch >> 6);
   1683  1.11   mlelstv 			*out++ = 0x80 | (inch & 0x3f);
   1684  1.11   mlelstv 		}
   1685  1.11   mlelstv 		return 2;
   1686  1.11   mlelstv 	} else {
   1687  1.11   mlelstv 		if (n < 3) return 0;
   1688  1.11   mlelstv 		if (out) {
   1689  1.11   mlelstv 			*out++ = 0xe0 | (inch >> 12);
   1690  1.11   mlelstv 			*out++ = 0x80 | ((inch >> 6) & 0x3f);
   1691  1.11   mlelstv 			*out++ = 0x80 | (inch & 0x3f);
   1692  1.11   mlelstv 		}
   1693  1.11   mlelstv 		return 3;
   1694  1.11   mlelstv 	}
   1695  1.11   mlelstv }
   1696  1.11   mlelstv 
   1697  1.11   mlelstv 
   1698  1.11   mlelstv /*
   1699  1.11   mlelstv  * Convert UTF-8 bytes into UCS-2 character
   1700  1.11   mlelstv  * return number of input bytes, 0 if input
   1701  1.11   mlelstv  * is too short and -1 if input is invalid
   1702  1.11   mlelstv  */
   1703  1.11   mlelstv static int
   1704  1.11   mlelstv utf8ucs2(const u_int8_t *in, int n, u_int16_t *out)
   1705  1.11   mlelstv {
   1706  1.11   mlelstv 	uint16_t outch;
   1707  1.11   mlelstv 
   1708  1.11   mlelstv 	if (n < 1) return 0;
   1709  1.11   mlelstv 
   1710  1.11   mlelstv 	if (in[0] <= 0x7f) {
   1711  1.11   mlelstv 		outch = in[0];
   1712  1.11   mlelstv 		if (out)
   1713  1.11   mlelstv 			*out = htole16(outch);
   1714  1.11   mlelstv 		return 1;
   1715  1.11   mlelstv 	} else if (in[0] <= 0xdf) {
   1716  1.11   mlelstv 		if (n < 2) return 0;
   1717  1.11   mlelstv 		outch = (in[0] & 0x1f) << 6 | (in[1] & 0x3f);
   1718  1.11   mlelstv 		if (out)
   1719  1.11   mlelstv 			*out = htole16(outch);
   1720  1.11   mlelstv 		return 2;
   1721  1.11   mlelstv 	} else if (in[0] <= 0xef) {
   1722  1.11   mlelstv 		if (n < 3) return 0;
   1723  1.11   mlelstv 		outch = (in[0] & 0x1f) << 12 | (in[1] & 0x3f) << 6 | (in[2] & 0x3f);
   1724  1.11   mlelstv 		if (out)
   1725  1.11   mlelstv 			*out = htole16(outch);
   1726  1.11   mlelstv 		return 3;
   1727  1.11   mlelstv 	}
   1728  1.11   mlelstv 
   1729  1.11   mlelstv 	return -1;
   1730  1.11   mlelstv }
   1731  1.11   mlelstv 
   1732  1.11   mlelstv /*
   1733  1.11   mlelstv  * Convert UCS-2 string into UTF-8 string
   1734  1.11   mlelstv  * return total number of output bytes
   1735  1.11   mlelstv  */
   1736  1.11   mlelstv static int
   1737  1.11   mlelstv ucs2utf8str(const u_int16_t *in, int n, u_int8_t *out, int m)
   1738  1.11   mlelstv {
   1739  1.11   mlelstv 	u_int8_t *p;
   1740  1.11   mlelstv 	int outlen;
   1741  1.11   mlelstv 
   1742  1.11   mlelstv 	p = out;
   1743  1.11   mlelstv 	while (n > 0 && *in != 0) {
   1744  1.11   mlelstv 		outlen = ucs2utf8(in, out ? p : out, m);
   1745  1.11   mlelstv 		if (outlen == 0)
   1746  1.11   mlelstv 			break;
   1747  1.11   mlelstv 		p += outlen;
   1748  1.11   mlelstv 		m -= outlen;
   1749  1.11   mlelstv 		in += 1;
   1750  1.11   mlelstv 		n -= 1;
   1751  1.11   mlelstv 	}
   1752  1.11   mlelstv 
   1753  1.11   mlelstv 	return p - out;
   1754  1.11   mlelstv }
   1755  1.11   mlelstv 
   1756  1.11   mlelstv /*
   1757  1.11   mlelstv  * Convert UTF8 string into UCS-2 string
   1758  1.11   mlelstv  * return total number of output chacters
   1759  1.11   mlelstv  */
   1760  1.11   mlelstv static int
   1761  1.11   mlelstv utf8ucs2str(const u_int8_t *in, int n, u_int16_t *out, int m)
   1762  1.11   mlelstv {
   1763  1.11   mlelstv 	u_int16_t *p;
   1764  1.11   mlelstv 	int inlen;
   1765  1.11   mlelstv 
   1766  1.11   mlelstv 	p = out;
   1767  1.11   mlelstv 	while (n > 0 && *in != 0) {
   1768  1.11   mlelstv 		if (m < 1)
   1769  1.11   mlelstv 			break;
   1770  1.11   mlelstv 		inlen = utf8ucs2(in, n, out ? p : out);
   1771  1.11   mlelstv 		if (inlen <= 0)
   1772  1.11   mlelstv 			break;
   1773  1.11   mlelstv 		in += inlen;
   1774  1.11   mlelstv 		n -= inlen;
   1775  1.11   mlelstv 		p += 1;
   1776  1.11   mlelstv 		m -= 1;
   1777  1.11   mlelstv 	}
   1778  1.11   mlelstv 
   1779  1.11   mlelstv 	return p - out;
   1780  1.11   mlelstv }
   1781  1.11   mlelstv 
   1782  1.11   mlelstv /*
   1783  1.11   mlelstv  * Convert UCS-2 string into 8bit character string
   1784  1.11   mlelstv  * return total number of output bytes
   1785  1.11   mlelstv  */
   1786  1.11   mlelstv static int
   1787  1.11   mlelstv ucs2char8str(const u_int16_t *in, int n, u_int8_t *out, int m)
   1788  1.11   mlelstv {
   1789  1.11   mlelstv 	u_int8_t *p;
   1790  1.11   mlelstv 	u_int16_t inch;
   1791  1.11   mlelstv 
   1792  1.11   mlelstv 	p = out;
   1793  1.11   mlelstv 	while (n > 0 && in[0] != 0) {
   1794  1.11   mlelstv 		if (m < 1)
   1795  1.11   mlelstv 			break;
   1796  1.11   mlelstv 		inch = le16toh(in[0]);
   1797  1.11   mlelstv 		if (inch > 255)
   1798  1.11   mlelstv 			break;
   1799  1.11   mlelstv 		if (p)
   1800  1.11   mlelstv 			p[0] = inch;
   1801  1.11   mlelstv 		p += 1;
   1802  1.11   mlelstv 		m -= 1;
   1803  1.11   mlelstv 		in += 1;
   1804  1.11   mlelstv 		n -= 1;
   1805  1.11   mlelstv 	}
   1806  1.11   mlelstv 
   1807  1.11   mlelstv 	return p - out;
   1808  1.11   mlelstv }
   1809  1.11   mlelstv 
   1810  1.11   mlelstv /*
   1811  1.11   mlelstv  * Convert 8bit character string into UCS-2 string
   1812  1.11   mlelstv  * return total number of output chacters
   1813  1.11   mlelstv  */
   1814  1.11   mlelstv static int
   1815  1.11   mlelstv char8ucs2str(const u_int8_t *in, int n, u_int16_t *out, int m)
   1816  1.11   mlelstv {
   1817  1.11   mlelstv 	u_int16_t *p;
   1818  1.11   mlelstv 
   1819  1.11   mlelstv 	p = out;
   1820  1.11   mlelstv 	while (n > 0 && in[0] != 0) {
   1821  1.11   mlelstv 		if (m < 1)
   1822  1.11   mlelstv 			break;
   1823  1.11   mlelstv 		if (p)
   1824  1.11   mlelstv 			p[0] = htole16(in[0]);
   1825  1.11   mlelstv 		p += 1;
   1826  1.11   mlelstv 		m -= 1;
   1827  1.11   mlelstv 		in += 1;
   1828  1.11   mlelstv 		n -= 1;
   1829  1.11   mlelstv 	}
   1830  1.11   mlelstv 
   1831  1.11   mlelstv 	return p - out;
   1832  1.11   mlelstv }
   1833  1.11   mlelstv 
   1834  1.11   mlelstv static void
   1835  1.11   mlelstv ucs2pad(u_int16_t *buf, int len, int size)
   1836  1.11   mlelstv {
   1837  1.11   mlelstv 
   1838  1.11   mlelstv 	if (len < size-1)
   1839  1.11   mlelstv 		buf[len++] = 0x0000;
   1840  1.11   mlelstv 	while (len < size)
   1841  1.11   mlelstv 		buf[len++] = 0xffff;
   1842  1.11   mlelstv }
   1843  1.11   mlelstv 
   1844  1.11   mlelstv /*
   1845  1.11   mlelstv  * Fold UCS-2 character to uppercase
   1846  1.11   mlelstv  */
   1847  1.11   mlelstv static u_int16_t
   1848  1.11   mlelstv ucs2fold(u_int16_t w)
   1849  1.11   mlelstv {
   1850  1.11   mlelstv 	int low,high,mid;
   1851  1.11   mlelstv 	u_int16_t check;
   1852  1.11   mlelstv 
   1853  1.11   mlelstv 	w = le16toh(w);
   1854  1.11   mlelstv 
   1855  1.11   mlelstv 	low = 0;
   1856  1.11   mlelstv 	high = __arraycount(foldmap) / 2;
   1857  1.11   mlelstv 	while (low < high) {
   1858  1.11   mlelstv 		mid = (low + high)/2;
   1859  1.11   mlelstv 		check = foldmap[2*mid+0];
   1860  1.11   mlelstv 
   1861  1.11   mlelstv 		if (w == check) {
   1862  1.11   mlelstv 			w = foldmap[2*mid+1];
   1863  1.11   mlelstv 			break;
   1864  1.11   mlelstv 		}
   1865  1.11   mlelstv 
   1866  1.11   mlelstv 		if (w < check)
   1867  1.11   mlelstv 			high = mid;
   1868  1.11   mlelstv 		else
   1869  1.11   mlelstv 			low = mid+1;
   1870  1.11   mlelstv 	}
   1871  1.11   mlelstv 
   1872  1.11   mlelstv 	w = le16toh(w);
   1873  1.11   mlelstv 
   1874  1.11   mlelstv 	return w;
   1875  1.11   mlelstv }
   1876  1.11   mlelstv 
   1877  1.11   mlelstv /*
   1878  1.11   mlelstv  * Compare two UCS-2 strings case-insensitive
   1879  1.11   mlelstv  *
   1880  1.11   mlelstv  * uses the Unicode case folding table
   1881  1.11   mlelstv  */
   1882  1.11   mlelstv static int
   1883  1.11   mlelstv ucs2match(u_int16_t *w1, u_int16_t *w2, int n)
   1884  1.11   mlelstv {
   1885  1.11   mlelstv 	u_int16_t u1, u2;
   1886  1.11   mlelstv 
   1887  1.11   mlelstv 	while (n > 0) {
   1888  1.11   mlelstv 		if (*w1 == 0 || *w2 == 0)
   1889  1.11   mlelstv 			return *w1 == *w2;
   1890  1.11   mlelstv 		u1 = ucs2fold(*w1);
   1891  1.11   mlelstv 		u2 = ucs2fold(*w2);
   1892  1.11   mlelstv 		if (u1 != u2)
   1893  1.11   mlelstv 			return 0;
   1894  1.11   mlelstv 		++w1;
   1895  1.11   mlelstv 		++w2;
   1896  1.11   mlelstv 		--n;
   1897  1.11   mlelstv 	}
   1898  1.11   mlelstv 
   1899  1.11   mlelstv 	return 1;
   1900  1.11   mlelstv }
   1901  1.11   mlelstv 
   1902  1.11   mlelstv /*
   1903  1.11   mlelstv  * Compare two 8bit char conversions case-insensitive
   1904  1.11   mlelstv  *
   1905  1.11   mlelstv  * uses the DOS case folding table
   1906  1.11   mlelstv  */
   1907  1.11   mlelstv static int
   1908  1.11   mlelstv char8match(u_int16_t *w1, u_int16_t *w2, int n)
   1909  1.11   mlelstv {
   1910  1.11   mlelstv 	u_int16_t u1, u2;
   1911  1.11   mlelstv 
   1912  1.11   mlelstv 	while (n > 0) {
   1913  1.11   mlelstv 		u1 = le16toh(*w1);
   1914  1.11   mlelstv 		u2 = le16toh(*w2);
   1915  1.11   mlelstv 		if (u1 == 0 || u2 == 0)
   1916  1.11   mlelstv 			return u1 == u2;
   1917  1.11   mlelstv 		if (u1 > 255 || u2 > 255)
   1918  1.11   mlelstv 			return 0;
   1919  1.11   mlelstv 		u1 = u2l[u1 & 0xff];
   1920  1.11   mlelstv 		u2 = u2l[u2 & 0xff];
   1921  1.11   mlelstv 		if (u1 != u2)
   1922  1.11   mlelstv 			return 0;
   1923  1.11   mlelstv 		++w1;
   1924  1.11   mlelstv 		++w2;
   1925  1.11   mlelstv 		--n;
   1926  1.11   mlelstv 	}
   1927  1.11   mlelstv 
   1928  1.11   mlelstv 	return 1;
   1929   1.1  jdolecek }
   1930  1.11   mlelstv 
   1931