Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Code page functions |
| 3 | * |
| 4 | * Copyright 2000 Alexandre Julliard |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 5 | * |
| 6 | * This library is free software; you can redistribute it and/or |
| 7 | * modify it under the terms of the GNU Lesser General Public |
| 8 | * License as published by the Free Software Foundation; either |
| 9 | * version 2.1 of the License, or (at your option) any later version. |
| 10 | * |
| 11 | * This library is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 14 | * Lesser General Public License for more details. |
| 15 | * |
| 16 | * You should have received a copy of the GNU Lesser General Public |
| 17 | * License along with this library; if not, write to the Free Software |
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 19 | */ |
| 20 | |
| 21 | #include <assert.h> |
| 22 | #include <stdio.h> |
Alexandre Julliard | 6ce2570 | 2000-07-11 22:08:43 +0000 | [diff] [blame] | 23 | #include <stdlib.h> |
James Juran | f4d5fef | 2001-01-26 20:43:40 +0000 | [diff] [blame] | 24 | #include <string.h> |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 25 | |
| 26 | #include "winbase.h" |
| 27 | #include "winerror.h" |
| 28 | #include "winnls.h" |
| 29 | #include "wine/unicode.h" |
Alexandre Julliard | 66e3183 | 2002-08-15 23:18:47 +0000 | [diff] [blame] | 30 | #include "thread.h" |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 31 | #include "wine/debug.h" |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 32 | |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 33 | WINE_DEFAULT_DEBUG_CHANNEL(string); |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 34 | |
| 35 | /* current code pages */ |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 36 | static const union cptable *ansi_cptable; |
| 37 | static const union cptable *oem_cptable; |
| 38 | static const union cptable *mac_cptable; |
Alexandre Julliard | 66e3183 | 2002-08-15 23:18:47 +0000 | [diff] [blame] | 39 | static LCID default_lcid = MAKELCID( MAKELANGID(LANG_ENGLISH,SUBLANG_DEFAULT), SORT_DEFAULT ); |
Alexandre Julliard | 6ce2570 | 2000-07-11 22:08:43 +0000 | [diff] [blame] | 40 | |
| 41 | /* setup default codepage info before we can get at the locale stuff */ |
| 42 | static void init_codepages(void) |
| 43 | { |
| 44 | ansi_cptable = cp_get_table( 1252 ); |
| 45 | oem_cptable = cp_get_table( 437 ); |
| 46 | mac_cptable = cp_get_table( 10000 ); |
| 47 | assert( ansi_cptable ); |
| 48 | assert( oem_cptable ); |
| 49 | assert( mac_cptable ); |
| 50 | } |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 51 | |
| 52 | /* find the table for a given codepage, handling CP_ACP etc. pseudo-codepages */ |
| 53 | static const union cptable *get_codepage_table( unsigned int codepage ) |
| 54 | { |
| 55 | const union cptable *ret = NULL; |
| 56 | |
Alexandre Julliard | 6ce2570 | 2000-07-11 22:08:43 +0000 | [diff] [blame] | 57 | if (!ansi_cptable) init_codepages(); |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 58 | |
| 59 | switch(codepage) |
| 60 | { |
Alexandre Julliard | 66e3183 | 2002-08-15 23:18:47 +0000 | [diff] [blame] | 61 | case CP_ACP: |
| 62 | return ansi_cptable; |
| 63 | case CP_OEMCP: |
| 64 | return oem_cptable; |
| 65 | case CP_MACCP: |
| 66 | return mac_cptable; |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 67 | case CP_UTF7: |
| 68 | case CP_UTF8: |
| 69 | break; |
Alexandre Julliard | 66e3183 | 2002-08-15 23:18:47 +0000 | [diff] [blame] | 70 | case CP_THREAD_ACP: |
| 71 | if (!(codepage = NtCurrentTeb()->code_page)) return ansi_cptable; |
| 72 | /* fall through */ |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 73 | default: |
Alexandre Julliard | 6ce2570 | 2000-07-11 22:08:43 +0000 | [diff] [blame] | 74 | if (codepage == ansi_cptable->info.codepage) return ansi_cptable; |
| 75 | if (codepage == oem_cptable->info.codepage) return oem_cptable; |
| 76 | if (codepage == mac_cptable->info.codepage) return mac_cptable; |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 77 | ret = cp_get_table( codepage ); |
| 78 | break; |
| 79 | } |
| 80 | return ret; |
| 81 | } |
| 82 | |
Alexandre Julliard | 6ce2570 | 2000-07-11 22:08:43 +0000 | [diff] [blame] | 83 | /* initialize default code pages from locale info */ |
| 84 | /* FIXME: should be done in init_codepages, but it can't right now */ |
| 85 | /* since it needs KERNEL32 to be loaded for the locale info. */ |
Alexandre Julliard | 66e3183 | 2002-08-15 23:18:47 +0000 | [diff] [blame] | 86 | void CODEPAGE_Init( UINT ansi, UINT oem, UINT mac, LCID lcid ) |
Alexandre Julliard | 6ce2570 | 2000-07-11 22:08:43 +0000 | [diff] [blame] | 87 | { |
Alexandre Julliard | 996c0bf | 2001-12-05 22:14:57 +0000 | [diff] [blame] | 88 | extern void __wine_init_codepages( const union cptable *ansi, const union cptable *oem ); |
Alexandre Julliard | 6ce2570 | 2000-07-11 22:08:43 +0000 | [diff] [blame] | 89 | const union cptable *table; |
Alexandre Julliard | 6ce2570 | 2000-07-11 22:08:43 +0000 | [diff] [blame] | 90 | |
Alexandre Julliard | 66e3183 | 2002-08-15 23:18:47 +0000 | [diff] [blame] | 91 | default_lcid = lcid; |
Alexandre Julliard | 6ce2570 | 2000-07-11 22:08:43 +0000 | [diff] [blame] | 92 | if (!ansi_cptable) init_codepages(); /* just in case */ |
Alexandre Julliard | 996c0bf | 2001-12-05 22:14:57 +0000 | [diff] [blame] | 93 | |
Alexandre Julliard | 66e3183 | 2002-08-15 23:18:47 +0000 | [diff] [blame] | 94 | if ((table = cp_get_table( ansi ))) ansi_cptable = table; |
| 95 | if ((table = cp_get_table( oem ))) oem_cptable = table; |
| 96 | if ((table = cp_get_table( mac ))) mac_cptable = table; |
Alexandre Julliard | 996c0bf | 2001-12-05 22:14:57 +0000 | [diff] [blame] | 97 | __wine_init_codepages( ansi_cptable, oem_cptable ); |
Alexandre Julliard | 6ce2570 | 2000-07-11 22:08:43 +0000 | [diff] [blame] | 98 | |
| 99 | TRACE( "ansi=%03d oem=%03d mac=%03d\n", ansi_cptable->info.codepage, |
| 100 | oem_cptable->info.codepage, mac_cptable->info.codepage ); |
| 101 | } |
| 102 | |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 103 | /****************************************************************************** |
Patrik Stridvall | 3ca9823 | 2001-06-20 23:03:14 +0000 | [diff] [blame] | 104 | * GetACP (KERNEL32.@) |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 105 | * |
| 106 | * RETURNS |
| 107 | * Current ANSI code-page identifier, default if no current defined |
| 108 | */ |
| 109 | UINT WINAPI GetACP(void) |
| 110 | { |
Alexandre Julliard | 66e3183 | 2002-08-15 23:18:47 +0000 | [diff] [blame] | 111 | if (!ansi_cptable) return 1252; |
Alexandre Julliard | 6ce2570 | 2000-07-11 22:08:43 +0000 | [diff] [blame] | 112 | return ansi_cptable->info.codepage; |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 113 | } |
| 114 | |
| 115 | |
| 116 | /*********************************************************************** |
Patrik Stridvall | 3ca9823 | 2001-06-20 23:03:14 +0000 | [diff] [blame] | 117 | * GetOEMCP (KERNEL32.@) |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 118 | */ |
| 119 | UINT WINAPI GetOEMCP(void) |
| 120 | { |
Alexandre Julliard | 66e3183 | 2002-08-15 23:18:47 +0000 | [diff] [blame] | 121 | if (!oem_cptable) return 437; |
Alexandre Julliard | 6ce2570 | 2000-07-11 22:08:43 +0000 | [diff] [blame] | 122 | return oem_cptable->info.codepage; |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 123 | } |
| 124 | |
| 125 | |
| 126 | /*********************************************************************** |
Patrik Stridvall | 3ca9823 | 2001-06-20 23:03:14 +0000 | [diff] [blame] | 127 | * IsValidCodePage (KERNEL32.@) |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 128 | */ |
| 129 | BOOL WINAPI IsValidCodePage( UINT codepage ) |
| 130 | { |
Alexandre Julliard | ac90ba9 | 2002-06-25 00:24:36 +0000 | [diff] [blame] | 131 | switch(codepage) { |
| 132 | case CP_SYMBOL: |
| 133 | return FALSE; |
| 134 | case CP_UTF7: |
| 135 | case CP_UTF8: |
| 136 | return TRUE; |
| 137 | default: |
| 138 | return cp_get_table( codepage ) != NULL; |
| 139 | } |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 140 | } |
| 141 | |
| 142 | |
| 143 | /*********************************************************************** |
Alexandre Julliard | 66e3183 | 2002-08-15 23:18:47 +0000 | [diff] [blame] | 144 | * GetUserDefaultLangID (KERNEL32.@) |
| 145 | */ |
| 146 | LANGID WINAPI GetUserDefaultLangID(void) |
| 147 | { |
| 148 | return LANGIDFROMLCID(default_lcid); |
| 149 | } |
| 150 | |
| 151 | |
| 152 | /*********************************************************************** |
| 153 | * GetSystemDefaultLangID (KERNEL32.@) |
| 154 | */ |
| 155 | LANGID WINAPI GetSystemDefaultLangID(void) |
| 156 | { |
| 157 | return GetUserDefaultLangID(); |
| 158 | } |
| 159 | |
| 160 | |
| 161 | /*********************************************************************** |
| 162 | * GetUserDefaultLCID (KERNEL32.@) |
| 163 | */ |
| 164 | LCID WINAPI GetUserDefaultLCID(void) |
| 165 | { |
| 166 | return default_lcid; |
| 167 | } |
| 168 | |
| 169 | |
| 170 | /*********************************************************************** |
| 171 | * GetSystemDefaultLCID (KERNEL32.@) |
| 172 | */ |
| 173 | LCID WINAPI GetSystemDefaultLCID(void) |
| 174 | { |
| 175 | return GetUserDefaultLCID(); |
| 176 | } |
| 177 | |
| 178 | |
| 179 | /*********************************************************************** |
Steve Lustbader | 2fbd4a0 | 2002-10-07 18:27:06 +0000 | [diff] [blame] | 180 | * GetUserDefaultUILanguage (KERNEL32.@) |
| 181 | */ |
| 182 | LANGID WINAPI GetUserDefaultUILanguage(void) |
| 183 | { |
| 184 | return GetUserDefaultLangID(); |
| 185 | } |
| 186 | |
| 187 | |
| 188 | /*********************************************************************** |
| 189 | * GetSystemDefaultUILanguage (KERNEL32.@) |
| 190 | */ |
| 191 | LANGID WINAPI GetSystemDefaultUILanguage(void) |
| 192 | { |
| 193 | return GetSystemDefaultLangID(); |
| 194 | } |
| 195 | |
| 196 | |
| 197 | /*********************************************************************** |
Patrik Stridvall | 3ca9823 | 2001-06-20 23:03:14 +0000 | [diff] [blame] | 198 | * IsDBCSLeadByteEx (KERNEL32.@) |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 199 | */ |
| 200 | BOOL WINAPI IsDBCSLeadByteEx( UINT codepage, BYTE testchar ) |
| 201 | { |
| 202 | const union cptable *table = get_codepage_table( codepage ); |
| 203 | return table && is_dbcs_leadbyte( table, testchar ); |
| 204 | } |
| 205 | |
| 206 | |
| 207 | /*********************************************************************** |
Patrik Stridvall | 3ca9823 | 2001-06-20 23:03:14 +0000 | [diff] [blame] | 208 | * IsDBCSLeadByte (KERNEL32.@) |
Patrik Stridvall | 044855c | 2001-07-11 18:56:41 +0000 | [diff] [blame] | 209 | * IsDBCSLeadByte (KERNEL.207) |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 210 | */ |
| 211 | BOOL WINAPI IsDBCSLeadByte( BYTE testchar ) |
| 212 | { |
Alexandre Julliard | 66e3183 | 2002-08-15 23:18:47 +0000 | [diff] [blame] | 213 | if (!ansi_cptable) return FALSE; |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 214 | return is_dbcs_leadbyte( ansi_cptable, testchar ); |
| 215 | } |
| 216 | |
| 217 | |
| 218 | /*********************************************************************** |
Patrik Stridvall | 3ca9823 | 2001-06-20 23:03:14 +0000 | [diff] [blame] | 219 | * GetCPInfo (KERNEL32.@) |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 220 | */ |
| 221 | BOOL WINAPI GetCPInfo( UINT codepage, LPCPINFO cpinfo ) |
| 222 | { |
| 223 | const union cptable *table = get_codepage_table( codepage ); |
| 224 | |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 225 | if (!table) |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 226 | { |
| 227 | SetLastError( ERROR_INVALID_PARAMETER ); |
| 228 | return FALSE; |
| 229 | } |
| 230 | if (table->info.def_char & 0xff00) |
| 231 | { |
| 232 | cpinfo->DefaultChar[0] = table->info.def_char & 0xff00; |
| 233 | cpinfo->DefaultChar[1] = table->info.def_char & 0x00ff; |
| 234 | } |
| 235 | else |
| 236 | { |
| 237 | cpinfo->DefaultChar[0] = table->info.def_char & 0xff; |
| 238 | cpinfo->DefaultChar[1] = 0; |
| 239 | } |
| 240 | if ((cpinfo->MaxCharSize = table->info.char_size) == 2) |
| 241 | memcpy( cpinfo->LeadByte, table->dbcs.lead_bytes, sizeof(cpinfo->LeadByte) ); |
| 242 | else |
| 243 | cpinfo->LeadByte[0] = cpinfo->LeadByte[1] = 0; |
| 244 | |
| 245 | return TRUE; |
| 246 | } |
| 247 | |
| 248 | |
| 249 | /*********************************************************************** |
Patrik Stridvall | 3ca9823 | 2001-06-20 23:03:14 +0000 | [diff] [blame] | 250 | * EnumSystemCodePagesA (KERNEL32.@) |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 251 | */ |
| 252 | BOOL WINAPI EnumSystemCodePagesA( CODEPAGE_ENUMPROCA lpfnCodePageEnum, DWORD flags ) |
| 253 | { |
| 254 | const union cptable *table; |
| 255 | char buffer[10]; |
| 256 | int index = 0; |
| 257 | |
| 258 | for (;;) |
| 259 | { |
| 260 | if (!(table = cp_enum_table( index++ ))) break; |
| 261 | sprintf( buffer, "%d", table->info.codepage ); |
| 262 | if (!lpfnCodePageEnum( buffer )) break; |
| 263 | } |
| 264 | return TRUE; |
| 265 | } |
| 266 | |
| 267 | |
| 268 | /*********************************************************************** |
Patrik Stridvall | 3ca9823 | 2001-06-20 23:03:14 +0000 | [diff] [blame] | 269 | * EnumSystemCodePagesW (KERNEL32.@) |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 270 | */ |
| 271 | BOOL WINAPI EnumSystemCodePagesW( CODEPAGE_ENUMPROCW lpfnCodePageEnum, DWORD flags ) |
| 272 | { |
| 273 | const union cptable *table; |
| 274 | WCHAR buffer[10], *p; |
| 275 | int page, index = 0; |
| 276 | |
| 277 | for (;;) |
| 278 | { |
| 279 | if (!(table = cp_enum_table( index++ ))) break; |
| 280 | p = buffer + sizeof(buffer)/sizeof(WCHAR); |
| 281 | *--p = 0; |
| 282 | page = table->info.codepage; |
| 283 | do |
| 284 | { |
| 285 | *--p = '0' + (page % 10); |
| 286 | page /= 10; |
| 287 | } while( page ); |
| 288 | if (!lpfnCodePageEnum( p )) break; |
| 289 | } |
| 290 | return TRUE; |
| 291 | } |
| 292 | |
| 293 | |
| 294 | /*********************************************************************** |
Patrik Stridvall | 3ca9823 | 2001-06-20 23:03:14 +0000 | [diff] [blame] | 295 | * MultiByteToWideChar (KERNEL32.@) |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 296 | * |
| 297 | * PARAMS |
| 298 | * page [in] Codepage character set to convert from |
| 299 | * flags [in] Character mapping flags |
| 300 | * src [in] Source string buffer |
| 301 | * srclen [in] Length of source string buffer |
| 302 | * dst [in] Destination buffer |
| 303 | * dstlen [in] Length of destination buffer |
| 304 | * |
| 305 | * NOTES |
| 306 | * The returned length includes the null terminator character. |
| 307 | * |
| 308 | * RETURNS |
| 309 | * Success: If dstlen > 0, number of characters written to destination |
| 310 | * buffer. If dstlen == 0, number of characters needed to do |
| 311 | * conversion. |
| 312 | * Failure: 0. Occurs if not enough space is available. |
| 313 | * |
| 314 | * ERRORS |
| 315 | * ERROR_INSUFFICIENT_BUFFER |
| 316 | * ERROR_INVALID_PARAMETER |
| 317 | * ERROR_NO_UNICODE_TRANSLATION |
| 318 | * |
| 319 | */ |
| 320 | INT WINAPI MultiByteToWideChar( UINT page, DWORD flags, LPCSTR src, INT srclen, |
| 321 | LPWSTR dst, INT dstlen ) |
| 322 | { |
| 323 | const union cptable *table; |
| 324 | int ret; |
| 325 | |
Wolfgang Schwotzer | d9b8f9b | 2000-07-28 23:58:48 +0000 | [diff] [blame] | 326 | if (!src || (!dst && dstlen)) |
| 327 | { |
| 328 | SetLastError( ERROR_INVALID_PARAMETER ); |
| 329 | return 0; |
| 330 | } |
| 331 | |
Dmitry Timoshkov | 3139b92 | 2002-10-04 17:42:27 +0000 | [diff] [blame] | 332 | if (srclen < 0) srclen = strlen(src) + 1; |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 333 | |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 334 | if (flags & MB_USEGLYPHCHARS) FIXME("MB_USEGLYPHCHARS not supported\n"); |
| 335 | |
Alexandre Julliard | aea7853 | 2000-08-11 00:44:33 +0000 | [diff] [blame] | 336 | switch(page) |
| 337 | { |
| 338 | case CP_UTF7: |
| 339 | FIXME("UTF not supported\n"); |
| 340 | SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); |
| 341 | return 0; |
| 342 | case CP_UTF8: |
| 343 | ret = utf8_mbstowcs( flags, src, srclen, dst, dstlen ); |
| 344 | break; |
| 345 | default: |
| 346 | if (!(table = get_codepage_table( page ))) |
| 347 | { |
| 348 | SetLastError( ERROR_INVALID_PARAMETER ); |
| 349 | return 0; |
| 350 | } |
| 351 | ret = cp_mbstowcs( table, flags, src, srclen, dst, dstlen ); |
| 352 | break; |
| 353 | } |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 354 | |
| 355 | if (ret < 0) |
| 356 | { |
| 357 | switch(ret) |
| 358 | { |
| 359 | case -1: SetLastError( ERROR_INSUFFICIENT_BUFFER ); break; |
| 360 | case -2: SetLastError( ERROR_NO_UNICODE_TRANSLATION ); break; |
| 361 | } |
| 362 | ret = 0; |
| 363 | } |
| 364 | return ret; |
| 365 | } |
| 366 | |
| 367 | |
| 368 | /*********************************************************************** |
Patrik Stridvall | 3ca9823 | 2001-06-20 23:03:14 +0000 | [diff] [blame] | 369 | * WideCharToMultiByte (KERNEL32.@) |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 370 | * |
| 371 | * PARAMS |
| 372 | * page [in] Codepage character set to convert to |
| 373 | * flags [in] Character mapping flags |
| 374 | * src [in] Source string buffer |
| 375 | * srclen [in] Length of source string buffer |
| 376 | * dst [in] Destination buffer |
| 377 | * dstlen [in] Length of destination buffer |
| 378 | * defchar [in] Default character to use for conversion if no exact |
| 379 | * conversion can be made |
| 380 | * used [out] Set if default character was used in the conversion |
| 381 | * |
| 382 | * NOTES |
| 383 | * The returned length includes the null terminator character. |
| 384 | * |
| 385 | * RETURNS |
| 386 | * Success: If dstlen > 0, number of characters written to destination |
| 387 | * buffer. If dstlen == 0, number of characters needed to do |
| 388 | * conversion. |
| 389 | * Failure: 0. Occurs if not enough space is available. |
| 390 | * |
| 391 | * ERRORS |
| 392 | * ERROR_INSUFFICIENT_BUFFER |
| 393 | * ERROR_INVALID_PARAMETER |
| 394 | */ |
| 395 | INT WINAPI WideCharToMultiByte( UINT page, DWORD flags, LPCWSTR src, INT srclen, |
| 396 | LPSTR dst, INT dstlen, LPCSTR defchar, BOOL *used ) |
| 397 | { |
| 398 | const union cptable *table; |
| 399 | int ret, used_tmp; |
| 400 | |
Wolfgang Schwotzer | d9b8f9b | 2000-07-28 23:58:48 +0000 | [diff] [blame] | 401 | if (!src || (!dst && dstlen)) |
| 402 | { |
| 403 | SetLastError( ERROR_INVALID_PARAMETER ); |
| 404 | return 0; |
| 405 | } |
| 406 | |
Dmitry Timoshkov | 3139b92 | 2002-10-04 17:42:27 +0000 | [diff] [blame] | 407 | if (srclen < 0) srclen = strlenW(src) + 1; |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 408 | |
Alexandre Julliard | aea7853 | 2000-08-11 00:44:33 +0000 | [diff] [blame] | 409 | switch(page) |
| 410 | { |
| 411 | case CP_UTF7: |
| 412 | FIXME("UTF-7 not supported\n"); |
| 413 | SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); |
| 414 | return 0; |
| 415 | case CP_UTF8: |
| 416 | ret = utf8_wcstombs( src, srclen, dst, dstlen ); |
| 417 | break; |
| 418 | default: |
| 419 | if (!(table = get_codepage_table( page ))) |
| 420 | { |
| 421 | SetLastError( ERROR_INVALID_PARAMETER ); |
| 422 | return 0; |
| 423 | } |
| 424 | ret = cp_wcstombs( table, flags, src, srclen, dst, dstlen, |
| 425 | defchar, used ? &used_tmp : NULL ); |
| 426 | if (used) *used = used_tmp; |
| 427 | break; |
| 428 | } |
Alexandre Julliard | f7bf7ef | 2000-06-10 04:42:33 +0000 | [diff] [blame] | 429 | |
| 430 | if (ret == -1) |
| 431 | { |
| 432 | SetLastError( ERROR_INSUFFICIENT_BUFFER ); |
| 433 | ret = 0; |
| 434 | } |
| 435 | return ret; |
| 436 | } |