1 /* 2 * msvcrt.dll mbcs functions 3 * 4 * Copyright 1999 Alexandre Julliard 5 * Copyright 2000 Jon Griffths 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 * 21 * FIXME 22 * Not currently binary compatible with win32. MSVCRT_mbctype must be 23 * populated correctly and the ismb* functions should reference it. 24 */ 25 26 #include <precomp.h> 27 28 #include <mbctype.h> 29 30 /* It seems that the data about valid trail bytes is not available from kernel32 31 * so we have to store is here. The format is the same as for lead bytes in CPINFO */ 32 struct cp_extra_info_t 33 { 34 int cp; 35 BYTE TrailBytes[MAX_LEADBYTES]; 36 }; 37 38 static struct cp_extra_info_t g_cpextrainfo[] = 39 { 40 {932, {0x40, 0x7e, 0x80, 0xfc, 0, 0}}, 41 {936, {0x40, 0xfe, 0, 0}}, 42 {949, {0x41, 0xfe, 0, 0}}, 43 {950, {0x40, 0x7e, 0xa1, 0xfe, 0, 0}}, 44 {1361, {0x31, 0x7e, 0x81, 0xfe, 0, 0}}, 45 {20932, {1, 255, 0, 0}}, /* seems to give different results on different systems */ 46 {0, {1, 255, 0, 0}} /* match all with FIXME */ 47 }; 48 49 /********************************************************************* 50 * INTERNAL: _setmbcp_l 51 */ 52 int _setmbcp_l(int cp, LCID lcid, MSVCRT_pthreadmbcinfo mbcinfo) 53 { 54 const char format[] = ".%d"; 55 56 int newcp; 57 CPINFO cpi; 58 BYTE *bytes; 59 WORD chartypes[256]; 60 char bufA[256]; 61 WCHAR bufW[256]; 62 int charcount; 63 int ret; 64 int i; 65 66 if(!mbcinfo) 67 mbcinfo = get_mbcinfo(); 68 69 switch (cp) 70 { 71 case _MB_CP_ANSI: 72 newcp = GetACP(); 73 break; 74 case _MB_CP_OEM: 75 newcp = GetOEMCP(); 76 break; 77 case _MB_CP_LOCALE: 78 newcp = get_locinfo()->lc_codepage; 79 if(newcp) 80 break; 81 /* fall through (C locale) */ 82 case _MB_CP_SBCS: 83 newcp = 20127; /* ASCII */ 84 break; 85 default: 86 newcp = cp; 87 break; 88 } 89 90 if(lcid == -1) { 91 sprintf(bufA, format, newcp); 92 mbcinfo->mblcid = MSVCRT_locale_to_LCID(bufA, NULL); 93 } else { 94 mbcinfo->mblcid = lcid; 95 } 96 97 if(mbcinfo->mblcid == -1) 98 { 99 WARN("Can't assign LCID to codepage (%d)\n", mbcinfo->mblcid); 100 mbcinfo->mblcid = 0; 101 } 102 103 if (!GetCPInfo(newcp, &cpi)) 104 { 105 WARN("Codepage %d not found\n", newcp); 106 *_errno() = EINVAL; 107 return -1; 108 } 109 110 /* setup the _mbctype */ 111 memset(mbcinfo->mbctype, 0, sizeof(unsigned char[257])); 112 memset(mbcinfo->mbcasemap, 0, sizeof(unsigned char[256])); 113 114 bytes = cpi.LeadByte; 115 while (bytes[0] || bytes[1]) 116 { 117 for (i = bytes[0]; i <= bytes[1]; i++) 118 mbcinfo->mbctype[i + 1] |= _M1; 119 bytes += 2; 120 } 121 122 if (cpi.MaxCharSize > 1) 123 { 124 /* trail bytes not available through kernel32 but stored in a structure in msvcrt */ 125 struct cp_extra_info_t *cpextra = g_cpextrainfo; 126 127 mbcinfo->ismbcodepage = 1; 128 while (TRUE) 129 { 130 if (cpextra->cp == 0 || cpextra->cp == newcp) 131 { 132 if (cpextra->cp == 0) 133 FIXME("trail bytes data not available for DBCS codepage %d - assuming all bytes\n", newcp); 134 135 bytes = cpextra->TrailBytes; 136 while (bytes[0] || bytes[1]) 137 { 138 for (i = bytes[0]; i <= bytes[1]; i++) 139 mbcinfo->mbctype[i + 1] |= _M2; 140 bytes += 2; 141 } 142 break; 143 } 144 cpextra++; 145 } 146 } 147 else 148 mbcinfo->ismbcodepage = 0; 149 150 /* we can't use GetStringTypeA directly because we don't have a locale - only a code page 151 */ 152 charcount = 0; 153 for (i = 0; i < 256; i++) 154 if (!(mbcinfo->mbctype[i + 1] & _M1)) 155 bufA[charcount++] = i; 156 157 ret = MultiByteToWideChar(newcp, 0, bufA, charcount, bufW, charcount); 158 if (ret != charcount) 159 ERR("MultiByteToWideChar of chars failed for cp %d, ret=%d (exp %d), error=%d\n", newcp, ret, charcount, GetLastError()); 160 161 GetStringTypeW(CT_CTYPE1, bufW, charcount, chartypes); 162 163 charcount = 0; 164 for (i = 0; i < 256; i++) 165 if (!(mbcinfo->mbctype[i + 1] & _M1)) 166 { 167 if (chartypes[charcount] & C1_UPPER) 168 { 169 mbcinfo->mbctype[i + 1] |= _SBUP; 170 bufW[charcount] = tolowerW(bufW[charcount]); 171 } 172 else if (chartypes[charcount] & C1_LOWER) 173 { 174 mbcinfo->mbctype[i + 1] |= _SBLOW; 175 bufW[charcount] = toupperW(bufW[charcount]); 176 } 177 charcount++; 178 } 179 180 ret = WideCharToMultiByte(newcp, 0, bufW, charcount, bufA, charcount, NULL, NULL); 181 if (ret != charcount) 182 ERR("WideCharToMultiByte failed for cp %d, ret=%d (exp %d), error=%d\n", newcp, ret, charcount, GetLastError()); 183 184 charcount = 0; 185 for (i = 0; i < 256; i++) 186 { 187 if(!(mbcinfo->mbctype[i + 1] & _M1)) 188 { 189 if(mbcinfo->mbctype[i] & (C1_UPPER|C1_LOWER)) 190 mbcinfo->mbcasemap[i] = bufA[charcount]; 191 charcount++; 192 } 193 } 194 195 if (newcp == 932) /* CP932 only - set _MP and _MS */ 196 { 197 /* On Windows it's possible to calculate the _MP and _MS from CT_CTYPE1 198 * and CT_CTYPE3. But as of Wine 0.9.43 we return wrong values what makes 199 * it hard. As this is set only for codepage 932 we hardcode it what gives 200 * also faster execution. 201 */ 202 for (i = 161; i <= 165; i++) 203 mbcinfo->mbctype[i + 1] |= _MP; 204 for (i = 166; i <= 223; i++) 205 mbcinfo->mbctype[i + 1] |= _MS; 206 } 207 208 mbcinfo->mbcodepage = newcp; 209 if(global_locale && mbcinfo == MSVCRT_locale->mbcinfo) 210 memcpy(_mbctype, MSVCRT_locale->mbcinfo->mbctype, sizeof(_mbctype)); 211 212 return 0; 213 } 214 215 /********************************************************************* 216 * _setmbcp (MSVCRT.@) 217 */ 218 int CDECL _setmbcp(int cp) 219 { 220 return _setmbcp_l(cp, -1, NULL); 221 } 222 223