1 /*------------------------------------------------------------------------*/
2 /* Unicode handling functions for FatFs R0.13c                            */
3 /*------------------------------------------------------------------------*/
4 /* This module will occupy a huge memory in the .const section when the    /
5 /  FatFs is configured for LFN with DBCS. If the system has any Unicode    /
6 /  utilitiy for the code conversion, this module should be modified to use /
7 /  that function to avoid silly memory consumption.                        /
8 /-------------------------------------------------------------------------*/
9 /*
10 / Copyright (C) 2018, ChaN, all right reserved.
11 /
12 / FatFs module is an open source software. Redistribution and use of FatFs in
13 / source and binary forms, with or without modification, are permitted provided
14 / that the following condition is met:
15 /
16 / 1. Redistributions of source code must retain the above copyright notice,
17 /    this condition and the following disclaimer.
18 /
19 / This software is provided by the copyright holder and contributors "AS IS"
20 / and any warranties related to this software are DISCLAIMED.
21 / The copyright owner or contributors be NOT LIABLE for any damages caused
22 / by use of this software.
23 */
24 
25 
26 #include "ff.h"
27 
28 #if FF_USE_LFN  /* This module will be blanked at non-LFN configuration */
29 
30 #if FF_DEFINED != 86604 /* Revision ID */
31 #error Wrong include file (ff.h).
32 #endif
33 
34 #define MERGE2(a, b) a ## b
35 #define CVTBL(tbl, cp) MERGE2(tbl, cp)
36 
37 
38 /*------------------------------------------------------------------------*/
39 /* Code Conversion Tables                                                 */
40 /*------------------------------------------------------------------------*/
41 
42 #if FF_CODE_PAGE == 437 || FF_CODE_PAGE == 0
43 static const WCHAR uc437[] = {  /*  CP437(U.S.) to Unicode conversion table */
44     0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
45     0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
46     0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
47     0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
48     0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
49     0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
50     0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
51     0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
52 };
53 #endif
54 #if FF_CODE_PAGE == 720 || FF_CODE_PAGE == 0
55 static const WCHAR uc720[] = {  /*  CP720(Arabic) to Unicode conversion table */
56     0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000,
57     0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9, 0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627,
58     0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB,
59     0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
60     0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
61     0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
62     0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0641, 0x00B5, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A,
63     0x2261, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 0x0650, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
64 };
65 #endif
66 #if FF_CODE_PAGE == 737 || FF_CODE_PAGE == 0
67 static const WCHAR uc737[] = {  /*  CP737(Greek) to Unicode conversion table */
68     0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0,
69     0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8,
70     0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8,
71     0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
72     0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
73     0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
74     0x03C9, 0x03AC, 0x03AD, 0x03AE, 0x03CA, 0x03AF, 0x03CC, 0x03CD, 0x03CB, 0x03CE, 0x0386, 0x0388, 0x0389, 0x038A, 0x038C, 0x038E,
75     0x038F, 0x00B1, 0x2265, 0x2264, 0x03AA, 0x03AB, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
76 };
77 #endif
78 #if FF_CODE_PAGE == 771 || FF_CODE_PAGE == 0
79 static const WCHAR uc771[] = {  /*  CP771(KBL) to Unicode conversion table */
80     0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
81     0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
82     0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
83     0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510,
84     0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
85     0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x0104, 0x0105, 0x010C, 0x010D,
86     0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
87     0x0118, 0x0119, 0x0116, 0x0117, 0x012E, 0x012F, 0x0160, 0x0161, 0x0172, 0x0173, 0x016A, 0x016B, 0x017D, 0x017E, 0x25A0, 0x00A0
88 };
89 #endif
90 #if FF_CODE_PAGE == 775 || FF_CODE_PAGE == 0
91 static const WCHAR uc775[] = {  /*  CP775(Baltic) to Unicode conversion table */
92     0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107, 0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5,
93     0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x00A4,
94     0x0100, 0x012A, 0x00F3, 0x017B, 0x017C, 0x017A, 0x201D, 0x00A6, 0x00A9, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x0141, 0x00AB, 0x00BB,
95     0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0104, 0x010C, 0x0118, 0x0116, 0x2563, 0x2551, 0x2557, 0x255D, 0x012E, 0x0160, 0x2510,
96     0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0172, 0x016A, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x017D,
97     0x0105, 0x010D, 0x0119, 0x0117, 0x012F, 0x0161, 0x0173, 0x016B, 0x017E, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
98     0x00D3, 0x00DF, 0x014C, 0x0143, 0x00F5, 0x00D5, 0x00B5, 0x0144, 0x0136, 0x0137, 0x013B, 0x013C, 0x0146, 0x0112, 0x0145, 0x2019,
99     0x00AD, 0x00B1, 0x201C, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x201E, 0x00B0, 0x2219, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
100 };
101 #endif
102 #if FF_CODE_PAGE == 850 || FF_CODE_PAGE == 0
103 static const WCHAR uc850[] = {  /*  CP850(Latin 1) to Unicode conversion table */
104     0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
105     0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192,
106     0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
107     0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510,
108     0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
109     0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580,
110     0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4,
111     0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
112 };
113 #endif
114 #if FF_CODE_PAGE == 852 || FF_CODE_PAGE == 0
115 static const WCHAR uc852[] = {  /*  CP852(Latin 2) to Unicode conversion table */
116     0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7, 0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106,
117     0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x0164, 0x0165, 0x0141, 0x00D7, 0x010D,
118     0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x0104, 0x0105, 0x017D, 0x017E, 0x0118, 0x0119, 0x00AC, 0x017A, 0x010C, 0x015F, 0x00AB, 0x00BB,
119     0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x011A, 0x015E, 0x2563, 0x2551, 0x2557, 0x255D, 0x017B, 0x017C, 0x2510,
120     0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0102, 0x0103, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
121     0x0111, 0x0110, 0x010E, 0x00CB, 0x010F, 0x0147, 0x00CD, 0x00CE, 0x011B, 0x2518, 0x250C, 0x2588, 0x2584, 0x0162, 0x016E, 0x2580,
122     0x00D3, 0x00DF, 0x00D4, 0x0143, 0x0144, 0x0148, 0x0160, 0x0161, 0x0154, 0x00DA, 0x0155, 0x0170, 0x00FD, 0x00DD, 0x0163, 0x00B4,
123     0x00AD, 0x02DD, 0x02DB, 0x02C7, 0x02D8, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x02D9, 0x0171, 0x0158, 0x0159, 0x25A0, 0x00A0
124 };
125 #endif
126 #if FF_CODE_PAGE == 855 || FF_CODE_PAGE == 0
127 static const WCHAR uc855[] = {  /*  CP855(Cyrillic) to Unicode conversion table */
128     0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404, 0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408,
129     0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C, 0x045E, 0x040E, 0x045F, 0x040F, 0x044E, 0x042E, 0x044A, 0x042A,
130     0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414, 0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00AB, 0x00BB,
131     0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0445, 0x0425, 0x0438, 0x0418, 0x2563, 0x2551, 0x2557, 0x255D, 0x0439, 0x0419, 0x2510,
132     0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x043A, 0x041A, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
133     0x043B, 0x041B, 0x043C, 0x041C, 0x043D, 0x041D, 0x043E, 0x041E, 0x043F, 0x2518, 0x250C, 0x2588, 0x2584, 0x041F, 0x044F, 0x2580,
134     0x042F, 0x0440, 0x0420, 0x0441, 0x0421, 0x0442, 0x0422, 0x0443, 0x0423, 0x0436, 0x0416, 0x0432, 0x0412, 0x044C, 0x042C, 0x2116,
135     0x00AD, 0x044B, 0x042B, 0x0437, 0x0417, 0x0448, 0x0428, 0x044D, 0x042D, 0x0449, 0x0429, 0x0447, 0x0427, 0x00A7, 0x25A0, 0x00A0
136 };
137 #endif
138 #if FF_CODE_PAGE == 857 || FF_CODE_PAGE == 0
139 static const WCHAR uc857[] = {  /*  CP857(Turkish) to Unicode conversion table */
140     0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5,
141     0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x0130, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x015E, 0x015F,
142     0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x011E, 0x011F, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
143     0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510,
144     0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
145     0x00BA, 0x00AA, 0x00CA, 0x00CB, 0x00C8, 0x0000, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580,
146     0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x0000, 0x00D7, 0x00DA, 0x00DB, 0x00D9, 0x00EC, 0x00FF, 0x00AF, 0x00B4,
147     0x00AD, 0x00B1, 0x0000, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
148 };
149 #endif
150 #if FF_CODE_PAGE == 860 || FF_CODE_PAGE == 0
151 static const WCHAR uc860[] = {  /*  CP860(Portuguese) to Unicode conversion table */
152     0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E3, 0x00E0, 0x00C1, 0x00E7, 0x00EA, 0x00CA, 0x00E8, 0x00CD, 0x00D4, 0x00EC, 0x00C3, 0x00C2,
153     0x00C9, 0x00C0, 0x00C8, 0x00F4, 0x00F5, 0x00F2, 0x00DA, 0x00F9, 0x00CC, 0x00D5, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x20A7, 0x00D3,
154     0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00D2, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
155     0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510,
156     0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
157     0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
158     0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
159     0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
160 };
161 #endif
162 #if FF_CODE_PAGE == 861 || FF_CODE_PAGE == 0
163 static const WCHAR uc861[] = {  /*  CP861(Icelandic) to Unicode conversion table */
164     0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00D0, 0x00F0, 0x00DE, 0x00C4, 0x00C5,
165     0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00FE, 0x00FB, 0x00DD, 0x00FD, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192,
166     0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00C1, 0x00CD, 0x00D3, 0x00DA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
167     0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
168     0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
169     0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
170     0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
171     0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
172 };
173 #endif
174 #if FF_CODE_PAGE == 862 || FF_CODE_PAGE == 0
175 static const WCHAR uc862[] = {  /*  CP862(Hebrew) to Unicode conversion table */
176     0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
177     0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
178     0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
179     0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
180     0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
181     0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
182     0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
183     0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
184 };
185 #endif
186 #if FF_CODE_PAGE == 863 || FF_CODE_PAGE == 0
187 static const WCHAR uc863[] = {  /*  CP863(Canadian French) to Unicode conversion table */
188     0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00C2, 0x00E0, 0x00B6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x2017, 0x00C0,
189     0x00C9, 0x00C8, 0x00CA, 0x00F4, 0x00CB, 0x00CF, 0x00FB, 0x00F9, 0x00A4, 0x00D4, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x00DB, 0x0192,
190     0x00A6, 0x00B4, 0x00F3, 0x00FA, 0x00A8, 0x00BB, 0x00B3, 0x00AF, 0x00CE, 0x3210, 0x00AC, 0x00BD, 0x00BC, 0x00BE, 0x00AB, 0x00BB,
191     0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
192     0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
193     0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
194     0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2219,
195     0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
196 };
197 #endif
198 #if FF_CODE_PAGE == 864 || FF_CODE_PAGE == 0
199 static const WCHAR uc864[] = {  /*  CP864(Arabic) to Unicode conversion table */
200     0x00B0, 0x00B7, 0x2219, 0x221A, 0x2592, 0x2500, 0x2502, 0x253C, 0x2524, 0x252C, 0x251C, 0x2534, 0x2510, 0x250C, 0x2514, 0x2518,
201     0x03B2, 0x221E, 0x03C6, 0x00B1, 0x00BD, 0x00BC, 0x2248, 0x00AB, 0x00BB, 0xFEF7, 0xFEF8, 0x0000, 0x0000, 0xFEFB, 0xFEFC, 0x0000,
202     0x00A0, 0x00AD, 0xFE82, 0x00A3, 0x00A4, 0xFE84, 0x0000, 0x20AC, 0xFE8E, 0xFE8F, 0xFE95, 0xFE99, 0x060C, 0xFE9D, 0xFEA1, 0xFEA5,
203     0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667, 0x0668, 0x0669, 0xFED1, 0x061B, 0xFEB1, 0xFEB5, 0xFEB9, 0x061F,
204     0x00A2, 0xFE80, 0xFE81, 0xFE83, 0xFE85, 0xFECA, 0xFE8B, 0xFE8D, 0xFE91, 0xFE93, 0xFE97, 0xFE9B, 0xFE9F, 0xFEA3, 0xFEA7, 0xFEA9,
205     0xFEAB, 0xFEAD, 0xFEAF, 0xFEB3, 0xFEB7, 0xFEBB, 0xFEBF, 0xFEC1, 0xFEC5, 0xFECB, 0xFECF, 0x00A6, 0x00AC, 0x00F7, 0x00D7, 0xFEC9,
206     0x0640, 0xFED3, 0xFED7, 0xFEDB, 0xFEDF, 0xFEE3, 0xFEE7, 0xFEEB, 0xFEED, 0xFEEF, 0xFEF3, 0xFEBD, 0xFECC, 0xFECE, 0xFECD, 0xFEE1,
207     0xFE7D, 0x0651, 0xFEE5, 0xFEE9, 0xFEEC, 0xFEF0, 0xFEF2, 0xFED0, 0xFED5, 0xFEF5, 0xFEF6, 0xFEDD, 0xFED9, 0xFEF1, 0x25A0, 0x0000
208 };
209 #endif
210 #if FF_CODE_PAGE == 865 || FF_CODE_PAGE == 0
211 static const WCHAR uc865[] = {  /*  CP865(Nordic) to Unicode conversion table */
212     0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
213     0x00C5, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192,
214     0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00A4,
215     0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510,
216     0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
217     0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
218     0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
219     0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
220 };
221 #endif
222 #if FF_CODE_PAGE == 866 || FF_CODE_PAGE == 0
223 static const WCHAR uc866[] = {  /*  CP866(Russian) to Unicode conversion table */
224     0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
225     0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
226     0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
227     0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
228     0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
229     0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
230     0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
231     0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040E, 0x045E, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x2116, 0x00A4, 0x25A0, 0x00A0
232 };
233 #endif
234 #if FF_CODE_PAGE == 869 || FF_CODE_PAGE == 0
235 static const WCHAR uc869[] = {  /*  CP869(Greek 2) to Unicode conversion table */
236     0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x0386, 0x00B7, 0x00B7, 0x00AC, 0x00A6, 0x2018, 0x2019, 0x0388, 0x2015, 0x0389,
237     0x038A, 0x03AA, 0x038C, 0x00B7, 0x00B7, 0x038E, 0x03AB, 0x00A9, 0x038F, 0x00B2, 0x00B3, 0x03AC, 0x00A3, 0x03AD, 0x03AE, 0x03AF,
238     0x03CA, 0x0390, 0x03CC, 0x03CD, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x00BD, 0x0398, 0x0399, 0x00AB, 0x00BB,
239     0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x039A, 0x039B, 0x039C, 0x039D, 0x2563, 0x2551, 0x2557, 0x255D, 0x039E, 0x039F, 0x2510,
240     0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0A30, 0x03A1, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x03A3,
241     0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x2518, 0x250C, 0x2588, 0x2584, 0x03B4, 0x03B5, 0x2580,
242     0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x0384,
243     0x00AD, 0x00B1, 0x03C5, 0x03C6, 0x03C7, 0x00A7, 0x03C8, 0x0385, 0x00B0, 0x00A8, 0x03C9, 0x03CB, 0x03B0, 0x03CE, 0x25A0, 0x00A0
244 };
245 #endif
246 
247 
248 
249 
250 /*------------------------------------------------------------------------*/
251 /* OEM <==> Unicode conversions for static code page configuration        */
252 /* SBCS fixed code page                                                   */
253 /*------------------------------------------------------------------------*/
254 
255 #if FF_CODE_PAGE != 0 && FF_CODE_PAGE < 900
ff_uni2oem(DWORD uni,WORD cp)256 WCHAR ff_uni2oem (  /* Returns OEM code character, zero on error */
257     DWORD   uni,    /* UTF-16 encoded character to be converted */
258     WORD    cp      /* Code page for the conversion */
259 )
260 {
261     WCHAR c = 0;
262     const WCHAR *p = CVTBL(uc, FF_CODE_PAGE);
263 
264 
265     if (uni < 0x80) {   /* ASCII? */
266         c = (WCHAR)uni;
267 
268     } else {            /* Non-ASCII */
269         if (uni < 0x10000 && cp == FF_CODE_PAGE) {  /* Is it in BMP and valid code page? */
270             for (c = 0; c < 0x80 && uni != p[c]; c++) ;
271             c = (c + 0x80) & 0xFF;
272         }
273     }
274 
275     return c;
276 }
277 
ff_oem2uni(WCHAR oem,WORD cp)278 WCHAR ff_oem2uni (  /* Returns Unicode character, zero on error */
279     WCHAR   oem,    /* OEM code to be converted */
280     WORD    cp      /* Code page for the conversion */
281 )
282 {
283     WCHAR c = 0;
284     const WCHAR *p = CVTBL(uc, FF_CODE_PAGE);
285 
286 
287     if (oem < 0x80) {   /* ASCII? */
288         c = oem;
289 
290     } else {            /* Extended char */
291         if (cp == FF_CODE_PAGE) {   /* Is it a valid code page? */
292             if (oem < 0x100) c = p[oem - 0x80];
293         }
294     }
295 
296     return c;
297 }
298 
299 #endif
300 
301 
302 
303 /*------------------------------------------------------------------------*/
304 /* OEM <==> Unicode conversions for static code page configuration        */
305 /* DBCS fixed code page                                                   */
306 /*------------------------------------------------------------------------*/
307 
308 #if FF_CODE_PAGE >= 900
ff_uni2oem(DWORD uni,WORD cp)309 WCHAR ff_uni2oem (  /* Returns OEM code character, zero on error */
310     DWORD   uni,    /* UTF-16 encoded character to be converted */
311     WORD    cp      /* Code page for the conversion */
312 )
313 {
314     const WCHAR *p;
315     WCHAR c = 0, uc;
316     UINT i = 0, n, li, hi;
317 
318 
319     if (uni < 0x80) {   /* ASCII? */
320         c = (WCHAR)uni;
321 
322     } else {            /* Non-ASCII */
323         if (uni < 0x10000 && cp == FF_CODE_PAGE) {  /* Is it in BMP and valid code page? */
324             uc = (WCHAR)uni;
325             p = CVTBL(uni2oem, FF_CODE_PAGE);
326             hi = sizeof CVTBL(uni2oem, FF_CODE_PAGE) / 4 - 1;
327             li = 0;
328             for (n = 16; n; n--) {
329                 i = li + (hi - li) / 2;
330                 if (uc == p[i * 2]) break;
331                 if (uc > p[i * 2]) {
332                     li = i;
333                 } else {
334                     hi = i;
335                 }
336             }
337             if (n != 0) c = p[i * 2 + 1];
338         }
339     }
340 
341     return c;
342 }
343 
344 
ff_oem2uni(WCHAR oem,WORD cp)345 WCHAR ff_oem2uni (  /* Returns Unicode character, zero on error */
346     WCHAR   oem,    /* OEM code to be converted */
347     WORD    cp      /* Code page for the conversion */
348 )
349 {
350     const WCHAR *p;
351     WCHAR c = 0;
352     UINT i = 0, n, li, hi;
353 
354 
355     if (oem < 0x80) {   /* ASCII? */
356         c = oem;
357 
358     } else {            /* Extended char */
359         if (cp == FF_CODE_PAGE) {   /* Is it valid code page? */
360             p = CVTBL(oem2uni, FF_CODE_PAGE);
361             hi = sizeof CVTBL(oem2uni, FF_CODE_PAGE) / 4 - 1;
362             li = 0;
363             for (n = 16; n; n--) {
364                 i = li + (hi - li) / 2;
365                 if (oem == p[i * 2]) break;
366                 if (oem > p[i * 2]) {
367                     li = i;
368                 } else {
369                     hi = i;
370                 }
371             }
372             if (n != 0) c = p[i * 2 + 1];
373         }
374     }
375 
376     return c;
377 }
378 #endif
379 
380 
381 
382 /*------------------------------------------------------------------------*/
383 /* OEM <==> Unicode conversions for dynamic code page configuration       */
384 /*------------------------------------------------------------------------*/
385 
386 #if FF_CODE_PAGE == 0
387 
388 static const WORD cp_code[]          = {  437,   720,   737,   771,   775,   850,   852,   855,   857,   860,   861,   862,   863,   864,   865,   866,   869, 0};
389 static const WCHAR* const cp_table[] = {uc437, uc720, uc737, uc771, uc775, uc850, uc852, uc855, uc857, uc860, uc861, uc862, uc863, uc864, uc865, uc866, uc869, 0};
390 
391 
ff_uni2oem(DWORD uni,WORD cp)392 WCHAR ff_uni2oem (  /* Returns OEM code character, zero on error */
393     DWORD   uni,    /* UTF-16 encoded character to be converted */
394     WORD    cp      /* Code page for the conversion */
395 )
396 {
397     const WCHAR *p;
398     WCHAR c = 0, uc;
399     UINT i, n, li, hi;
400 
401 
402     if (uni < 0x80) {   /* ASCII? */
403         c = (WCHAR)uni;
404 
405     } else {            /* Non-ASCII */
406         if (uni < 0x10000) { /* Is it in BMP? */
407             uc = (WCHAR)uni;
408             p = 0;
409             if (cp < 900) { /* SBCS */
410                 for (i = 0; cp_code[i] != 0 && cp_code[i] != cp; i++) ;     /* Get conversion table */
411                 p = cp_table[i];
412                 if (p) {    /* Is it valid code page ? */
413                     for (c = 0; c < 0x80 && uc != p[c]; c++) ;  /* Find OEM code in the table */
414                     c = (c + 0x80) & 0xFF;
415                 }
416             } else {    /* DBCS */
417                 switch (cp) {   /* Get conversion table */
418                 case 932 : p = uni2oem932; hi = sizeof uni2oem932 / 4 - 1; break;
419                 case 936 : p = uni2oem936; hi = sizeof uni2oem936 / 4 - 1; break;
420                 case 949 : p = uni2oem949; hi = sizeof uni2oem949 / 4 - 1; break;
421                 case 950 : p = uni2oem950; hi = sizeof uni2oem950 / 4 - 1; break;
422                 }
423                 if (p) {    /* Is it valid code page? */
424                     li = 0;
425                     for (n = 16; n; n--) {  /* Find OEM code */
426                         i = li + (hi - li) / 2;
427                         if (uc == p[i * 2]) break;
428                         if (uc > p[i * 2]) {
429                             li = i;
430                         } else {
431                             hi = i;
432                         }
433                     }
434                     if (n != 0) c = p[i * 2 + 1];
435                 }
436             }
437         }
438     }
439 
440     return c;
441 }
442 
443 
ff_oem2uni(WCHAR oem,WORD cp)444 WCHAR ff_oem2uni (  /* Returns Unicode character, zero on error */
445     WCHAR   oem,    /* OEM code to be converted (DBC if >=0x100) */
446     WORD    cp      /* Code page for the conversion */
447 )
448 {
449     const WCHAR *p;
450     WCHAR c = 0;
451     UINT i, n, li, hi;
452 
453 
454     if (oem < 0x80) {   /* ASCII? */
455         c = oem;
456 
457     } else {            /* Extended char */
458         p = 0;
459         if (cp < 900) { /* SBCS */
460             for (i = 0; cp_code[i] != 0 && cp_code[i] != cp; i++) ;     /* Get table */
461             p = cp_table[i];
462             if (p) {    /* Is it a valid CP ? */
463                 if (oem < 0x100) c = p[oem - 0x80];
464             }
465         } else {    /* DBCS */
466             switch (cp) {
467             case 932 : p = oem2uni932; hi = sizeof oem2uni932 / 4 - 1; break;
468             case 936 : p = oem2uni936; hi = sizeof oem2uni936 / 4 - 1; break;
469             case 949 : p = oem2uni949; hi = sizeof oem2uni949 / 4 - 1; break;
470             case 950 : p = oem2uni950; hi = sizeof oem2uni950 / 4 - 1; break;
471             }
472             if (p) {
473                 li = 0;
474                 for (n = 16; n; n--) {
475                     i = li + (hi - li) / 2;
476                     if (oem == p[i * 2]) break;
477                     if (oem > p[i * 2]) {
478                         li = i;
479                     } else {
480                         hi = i;
481                     }
482                 }
483                 if (n != 0) c = p[i * 2 + 1];
484             }
485         }
486     }
487 
488     return c;
489 }
490 #endif
491 
492 
493 
494 /*------------------------------------------------------------------------*/
495 /* Unicode up-case conversion                                             */
496 /*------------------------------------------------------------------------*/
497 
ff_wtoupper(DWORD uni)498 DWORD ff_wtoupper ( /* Returns up-converted code point */
499     DWORD uni       /* Unicode code point to be up-converted */
500 )
501 {
502     const WORD *p;
503     WORD uc, bc, nc, cmd;
504     static const WORD cvt1[] = {    /* Compressed up conversion table for U+0000 - U+0FFF */
505         /* Basic Latin */
506         0x0061,0x031A,
507         /* Latin-1 Supplement */
508         0x00E0,0x0317,
509         0x00F8,0x0307,
510         0x00FF,0x0001,0x0178,
511         /* Latin Extended-A */
512         0x0100,0x0130,
513         0x0132,0x0106,
514         0x0139,0x0110,
515         0x014A,0x012E,
516         0x0179,0x0106,
517         /* Latin Extended-B */
518         0x0180,0x004D,0x0243,0x0181,0x0182,0x0182,0x0184,0x0184,0x0186,0x0187,0x0187,0x0189,0x018A,0x018B,0x018B,0x018D,0x018E,0x018F,0x0190,0x0191,0x0191,0x0193,0x0194,0x01F6,0x0196,0x0197,0x0198,0x0198,0x023D,0x019B,0x019C,0x019D,0x0220,0x019F,0x01A0,0x01A0,0x01A2,0x01A2,0x01A4,0x01A4,0x01A6,0x01A7,0x01A7,0x01A9,0x01AA,0x01AB,0x01AC,0x01AC,0x01AE,0x01AF,0x01AF,0x01B1,0x01B2,0x01B3,0x01B3,0x01B5,0x01B5,0x01B7,0x01B8,0x01B8,0x01BA,0x01BB,0x01BC,0x01BC,0x01BE,0x01F7,0x01C0,0x01C1,0x01C2,0x01C3,0x01C4,0x01C5,0x01C4,0x01C7,0x01C8,0x01C7,0x01CA,0x01CB,0x01CA,
519         0x01CD,0x0110,
520         0x01DD,0x0001,0x018E,
521         0x01DE,0x0112,
522         0x01F3,0x0003,0x01F1,0x01F4,0x01F4,
523         0x01F8,0x0128,
524         0x0222,0x0112,
525         0x023A,0x0009,0x2C65,0x023B,0x023B,0x023D,0x2C66,0x023F,0x0240,0x0241,0x0241,
526         0x0246,0x010A,
527         /* IPA Extensions */
528         0x0253,0x0040,0x0181,0x0186,0x0255,0x0189,0x018A,0x0258,0x018F,0x025A,0x0190,0x025C,0x025D,0x025E,0x025F,0x0193,0x0261,0x0262,0x0194,0x0264,0x0265,0x0266,0x0267,0x0197,0x0196,0x026A,0x2C62,0x026C,0x026D,0x026E,0x019C,0x0270,0x0271,0x019D,0x0273,0x0274,0x019F,0x0276,0x0277,0x0278,0x0279,0x027A,0x027B,0x027C,0x2C64,0x027E,0x027F,0x01A6,0x0281,0x0282,0x01A9,0x0284,0x0285,0x0286,0x0287,0x01AE,0x0244,0x01B1,0x01B2,0x0245,0x028D,0x028E,0x028F,0x0290,0x0291,0x01B7,
529         /* Greek, Coptic */
530         0x037B,0x0003,0x03FD,0x03FE,0x03FF,
531         0x03AC,0x0004,0x0386,0x0388,0x0389,0x038A,
532         0x03B1,0x0311,
533         0x03C2,0x0002,0x03A3,0x03A3,
534         0x03C4,0x0308,
535         0x03CC,0x0003,0x038C,0x038E,0x038F,
536         0x03D8,0x0118,
537         0x03F2,0x000A,0x03F9,0x03F3,0x03F4,0x03F5,0x03F6,0x03F7,0x03F7,0x03F9,0x03FA,0x03FA,
538         /* Cyrillic */
539         0x0430,0x0320,
540         0x0450,0x0710,
541         0x0460,0x0122,
542         0x048A,0x0136,
543         0x04C1,0x010E,
544         0x04CF,0x0001,0x04C0,
545         0x04D0,0x0144,
546         /* Armenian */
547         0x0561,0x0426,
548 
549         0x0000  /* EOT */
550     };
551     static const WORD cvt2[] = {    /* Compressed up conversion table for U+1000 - U+FFFF */
552         /* Phonetic Extensions */
553         0x1D7D,0x0001,0x2C63,
554         /* Latin Extended Additional */
555         0x1E00,0x0196,
556         0x1EA0,0x015A,
557         /* Greek Extended */
558         0x1F00,0x0608,
559         0x1F10,0x0606,
560         0x1F20,0x0608,
561         0x1F30,0x0608,
562         0x1F40,0x0606,
563         0x1F51,0x0007,0x1F59,0x1F52,0x1F5B,0x1F54,0x1F5D,0x1F56,0x1F5F,
564         0x1F60,0x0608,
565         0x1F70,0x000E,0x1FBA,0x1FBB,0x1FC8,0x1FC9,0x1FCA,0x1FCB,0x1FDA,0x1FDB,0x1FF8,0x1FF9,0x1FEA,0x1FEB,0x1FFA,0x1FFB,
566         0x1F80,0x0608,
567         0x1F90,0x0608,
568         0x1FA0,0x0608,
569         0x1FB0,0x0004,0x1FB8,0x1FB9,0x1FB2,0x1FBC,
570         0x1FCC,0x0001,0x1FC3,
571         0x1FD0,0x0602,
572         0x1FE0,0x0602,
573         0x1FE5,0x0001,0x1FEC,
574         0x1FF3,0x0001,0x1FFC,
575         /* Letterlike Symbols */
576         0x214E,0x0001,0x2132,
577         /* Number forms */
578         0x2170,0x0210,
579         0x2184,0x0001,0x2183,
580         /* Enclosed Alphanumerics */
581         0x24D0,0x051A,
582         0x2C30,0x042F,
583         /* Latin Extended-C */
584         0x2C60,0x0102,
585         0x2C67,0x0106, 0x2C75,0x0102,
586         /* Coptic */
587         0x2C80,0x0164,
588         /* Georgian Supplement */
589         0x2D00,0x0826,
590         /* Full-width */
591         0xFF41,0x031A,
592 
593         0x0000  /* EOT */
594     };
595 
596 
597     if (uni < 0x10000) {    /* Is it in BMP? */
598         uc = (WORD)uni;
599         p = uc < 0x1000 ? cvt1 : cvt2;
600         for (;;) {
601             bc = *p++;                              /* Get the block base */
602             if (bc == 0 || uc < bc) break;          /* Not matched? */
603             nc = *p++; cmd = nc >> 8; nc &= 0xFF;   /* Get processing command and block size */
604             if (uc < bc + nc) { /* In the block? */
605                 switch (cmd) {
606                 case 0: uc = p[uc - bc]; break;     /* Table conversion */
607                 case 1: uc -= (uc - bc) & 1; break; /* Case pairs */
608                 case 2: uc -= 16; break;            /* Shift -16 */
609                 case 3: uc -= 32; break;            /* Shift -32 */
610                 case 4: uc -= 48; break;            /* Shift -48 */
611                 case 5: uc -= 26; break;            /* Shift -26 */
612                 case 6: uc += 8; break;             /* Shift +8 */
613                 case 7: uc -= 80; break;            /* Shift -80 */
614                 case 8: uc -= 0x1C60; break;        /* Shift -0x1C60 */
615                 }
616                 break;
617             }
618             if (cmd == 0) p += nc;  /* Skip table if needed */
619         }
620         uni = uc;
621     }
622 
623     return uni;
624 }
625 
626 
627 #endif /* #if FF_USE_LFN */
628