source: trunk/src/kernel32/codepage.cpp@ 5764

Last change on this file since 5764 was 5764, checked in by sandervl, 24 years ago

DT: IFIRSTDAYOFWEEK changes/fixes

File size: 13.4 KB
Line 
1/*
2 * Code page functions
3 *
4 * Based on Wine code (memory\codepage.c)
5 *
6 * Copyright 2000 Alexandre Julliard
7 *
8 * Project Odin Software License can be found in LICENSE.TXT
9 *
10 */
11
12#include <assert.h>
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16
17#include "winbase.h"
18#include "winerror.h"
19#include "winnls.h"
20#include "wine/unicode.h"
21#include "debugtools.h"
22
23#ifdef __WIN32OS2__
24#include <options.h>
25#include "codepage.h"
26
27#define DBG_LOCALLOG DBG_codepage
28#include "dbglocal.h"
29#endif
30
31DEFAULT_DEBUG_CHANNEL(string);
32
33/* current code pages */
34static const union cptable *ansi_cptable;
35static const union cptable *oem_cptable;
36static const union cptable *mac_cptable;
37
38/* retrieve a code page table from the locale info */
39static const union cptable *get_locale_cp( LCID lcid, LCTYPE type )
40{
41 const union cptable *table = NULL;
42 char buf[32];
43
44 if (GetLocaleInfoA( lcid, type, buf, sizeof(buf) )) table = cp_get_table( atoi(buf) );
45 return table;
46}
47
48/* setup default codepage info before we can get at the locale stuff */
49static void init_codepages(void)
50{
51 ansi_cptable = cp_get_table( 1252 );
52 oem_cptable = cp_get_table( 437 );
53 mac_cptable = cp_get_table( 10000 );
54 assert( ansi_cptable );
55 assert( oem_cptable );
56 assert( mac_cptable );
57}
58
59/* find the table for a given codepage, handling CP_ACP etc. pseudo-codepages */
60static const union cptable *get_codepage_table( unsigned int codepage )
61{
62 const union cptable *ret = NULL;
63
64 if (!ansi_cptable) init_codepages();
65
66 switch(codepage)
67 {
68 case CP_ACP: return ansi_cptable;
69 case CP_OEMCP: return oem_cptable;
70 case CP_MACCP: return mac_cptable;
71 case CP_THREAD_ACP: return get_locale_cp( GetThreadLocale(), LOCALE_IDEFAULTANSICODEPAGE );
72 case CP_UTF7:
73 case CP_UTF8:
74 break;
75 default:
76 if (codepage == ansi_cptable->info.codepage) return ansi_cptable;
77 if (codepage == oem_cptable->info.codepage) return oem_cptable;
78 if (codepage == mac_cptable->info.codepage) return mac_cptable;
79 ret = cp_get_table( codepage );
80 break;
81 }
82 return ret;
83}
84
85/* initialize default code pages from locale info */
86/* FIXME: should be done in init_codepages, but it can't right now */
87/* since it needs KERNEL32 to be loaded for the locale info. */
88void CODEPAGE_Init(void)
89{
90 const union cptable *table;
91 LCID lcid = GetUserDefaultLCID();
92
93 if (!ansi_cptable) init_codepages(); /* just in case */
94
95 if ((table = get_locale_cp( lcid, LOCALE_IDEFAULTANSICODEPAGE ))) ansi_cptable = table;
96 if ((table = get_locale_cp( lcid, LOCALE_IDEFAULTMACCODEPAGE ))) mac_cptable = table;
97 if ((table = get_locale_cp( lcid, LOCALE_IDEFAULTCODEPAGE ))) oem_cptable = table;
98
99 TRACE( "ansi=%03d oem=%03d mac=%03d\n", ansi_cptable->info.codepage,
100 oem_cptable->info.codepage, mac_cptable->info.codepage );
101#ifdef __WIN32OS2__
102 dprintf(("Language %s", getenv("LANG")));
103#endif
104}
105
106#ifdef __WIN32OS2__
107ULONG GetDisplayCodepage()
108{
109 if (!ansi_cptable) CODEPAGE_Init();
110
111 return ansi_cptable->info.codepage;
112}
113
114ULONG GetWindowsCodepage()
115{
116 if (!ansi_cptable) CODEPAGE_Init();
117
118 return ansi_cptable->info.codepage;
119}
120
121#endif
122
123/******************************************************************************
124 * GetACP (KERNEL32)
125 *
126 * RETURNS
127 * Current ANSI code-page identifier, default if no current defined
128 */
129UINT WINAPI GetACP(void)
130{
131 if (!ansi_cptable) init_codepages();
132#ifdef __WIN32OS2__
133 dprintf(("GetACP %d", ansi_cptable->info.codepage));
134#endif
135 return ansi_cptable->info.codepage;
136}
137
138
139/***********************************************************************
140 * GetOEMCP (KERNEL32)
141 */
142UINT WINAPI GetOEMCP(void)
143{
144 if (!oem_cptable) init_codepages();
145#ifdef __WIN32OS2__
146 dprintf(("GetOEMCP %d", oem_cptable->info.codepage));
147#endif
148 return oem_cptable->info.codepage;
149}
150
151
152/***********************************************************************
153 * IsValidCodePage (KERNEL32)
154 */
155BOOL WINAPI IsValidCodePage( UINT codepage )
156{
157#ifdef __WIN32OS2__
158 dprintf(("IsValidCodePage %d", codepage));
159#endif
160 return cp_get_table( codepage ) != NULL;
161}
162
163
164/***********************************************************************
165 * IsDBCSLeadByteEx (KERNEL32)
166 */
167BOOL WINAPI IsDBCSLeadByteEx( UINT codepage, BYTE testchar )
168{
169#ifdef __WIN32OS2__
170 dprintf2(("IsDBCSLeadByteEx %d %x", codepage, testchar));
171#endif
172
173 const union cptable *table = get_codepage_table( codepage );
174 return table && is_dbcs_leadbyte( table, testchar );
175}
176
177
178/***********************************************************************
179 * IsDBCSLeadByte (KERNEL32)
180 */
181BOOL WINAPI IsDBCSLeadByte( BYTE testchar )
182{
183 if (!ansi_cptable) init_codepages();
184 return is_dbcs_leadbyte( ansi_cptable, testchar );
185}
186
187
188/***********************************************************************
189 * GetCPInfo (KERNEL32)
190 */
191BOOL WINAPI GetCPInfo( UINT codepage, LPCPINFO cpinfo )
192{
193 const union cptable *table = get_codepage_table( codepage );
194
195#ifdef __WIN32OS2__
196 dprintf(("GetCPInfo %d %x", codepage, cpinfo));
197#endif
198
199 if (!table)
200 {
201 SetLastError( ERROR_INVALID_PARAMETER );
202 return FALSE;
203 }
204 if (table->info.def_char & 0xff00)
205 {
206 cpinfo->DefaultChar[0] = table->info.def_char & 0xff00;
207 cpinfo->DefaultChar[1] = table->info.def_char & 0x00ff;
208 }
209 else
210 {
211 cpinfo->DefaultChar[0] = table->info.def_char & 0xff;
212 cpinfo->DefaultChar[1] = 0;
213 }
214 if ((cpinfo->MaxCharSize = table->info.char_size) == 2)
215 memcpy( cpinfo->LeadByte, table->dbcs.lead_bytes, sizeof(cpinfo->LeadByte) );
216 else
217 cpinfo->LeadByte[0] = cpinfo->LeadByte[1] = 0;
218
219 return TRUE;
220}
221
222
223/***********************************************************************
224 * EnumSystemCodePagesA (KERNEL32)
225 */
226BOOL WINAPI EnumSystemCodePagesA( CODEPAGE_ENUMPROCA lpfnCodePageEnum, DWORD flags )
227{
228 const union cptable *table;
229 char buffer[10];
230 int index = 0;
231
232#ifdef __WIN32OS2__
233 dprintf(("EnumSystemCodePagesA %x %x", lpfnCodePageEnum, flags));
234#endif
235
236 for (;;)
237 {
238 if (!(table = cp_enum_table( index++ ))) break;
239 sprintf( buffer, "%d", table->info.codepage );
240 if (!lpfnCodePageEnum( buffer )) break;
241 }
242 return TRUE;
243}
244
245
246/***********************************************************************
247 * EnumSystemCodePagesW (KERNEL32)
248 */
249BOOL WINAPI EnumSystemCodePagesW( CODEPAGE_ENUMPROCW lpfnCodePageEnum, DWORD flags )
250{
251 const union cptable *table;
252 WCHAR buffer[10], *p;
253 int page, index = 0;
254
255#ifdef __WIN32OS2__
256 dprintf(("EnumSystemCodePagesW %x %x", lpfnCodePageEnum, flags));
257#endif
258
259 for (;;)
260 {
261 if (!(table = cp_enum_table( index++ ))) break;
262 p = buffer + sizeof(buffer)/sizeof(WCHAR);
263 *--p = 0;
264 page = table->info.codepage;
265 do
266 {
267 *--p = '0' + (page % 10);
268 page /= 10;
269 } while( page );
270 if (!lpfnCodePageEnum( p )) break;
271 }
272 return TRUE;
273}
274
275
276/***********************************************************************
277 * MultiByteToWideChar (KERNEL32)
278 *
279 * PARAMS
280 * page [in] Codepage character set to convert from
281 * flags [in] Character mapping flags
282 * src [in] Source string buffer
283 * srclen [in] Length of source string buffer
284 * dst [in] Destination buffer
285 * dstlen [in] Length of destination buffer
286 *
287 * NOTES
288 * The returned length includes the null terminator character.
289 *
290 * RETURNS
291 * Success: If dstlen > 0, number of characters written to destination
292 * buffer. If dstlen == 0, number of characters needed to do
293 * conversion.
294 * Failure: 0. Occurs if not enough space is available.
295 *
296 * ERRORS
297 * ERROR_INSUFFICIENT_BUFFER
298 * ERROR_INVALID_PARAMETER
299 * ERROR_NO_UNICODE_TRANSLATION
300 *
301 */
302INT WINAPI MultiByteToWideChar( UINT page, DWORD flags, LPCSTR src, INT srclen,
303 LPWSTR dst, INT dstlen )
304{
305 const union cptable *table;
306 int ret;
307
308#ifdef __WIN32OS2__
309 dprintf2(("MultiByteToWideChar %d %x %x %d %x %d", page, flags, src, srclen, dst, dstlen));
310#endif
311
312 //Docs say source ptr can't be the same as destination (Windows ME, NT4-SP6)
313 if (!src || (!dst && dstlen) || ((void *)src == (void *)dst))
314 {
315 SetLastError( ERROR_INVALID_PARAMETER );
316 return 0;
317 }
318
319 //Even though the docs claim this only works for -1, testing shows it
320 //is done for any negative value (Windows ME, NT4-SP6)
321 if (srclen <= -1) srclen = strlen(src) + 1;
322
323 if (flags & MB_USEGLYPHCHARS) FIXME("MB_USEGLYPHCHARS not supported\n");
324
325 switch(page)
326 {
327 case CP_UTF7:
328 FIXME("UTF not supported\n");
329 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
330 return 0;
331 case CP_UTF8:
332 ret = utf8_mbstowcs( flags, src, srclen, dst, dstlen );
333 break;
334 default:
335 if (!(table = get_codepage_table( page )))
336 {
337 SetLastError( ERROR_INVALID_PARAMETER );
338 return 0;
339 }
340 ret = cp_mbstowcs( table, flags, src, srclen, dst, dstlen );
341 break;
342 }
343
344 if (ret < 0)
345 {
346 switch(ret)
347 {
348 case -1: SetLastError( ERROR_INSUFFICIENT_BUFFER ); break;
349 case -2: SetLastError( ERROR_NO_UNICODE_TRANSLATION ); break;
350 }
351 ret = 0;
352 }
353 return ret;
354}
355
356
357/***********************************************************************
358 * WideCharToMultiByte (KERNEL32)
359 *
360 * PARAMS
361 * page [in] Codepage character set to convert to
362 * flags [in] Character mapping flags
363 * src [in] Source string buffer
364 * srclen [in] Length of source string buffer
365 * dst [in] Destination buffer
366 * dstlen [in] Length of destination buffer
367 * defchar [in] Default character to use for conversion if no exact
368 * conversion can be made
369 * used [out] Set if default character was used in the conversion
370 *
371 * NOTES
372 * The returned length includes the null terminator character.
373 *
374 * RETURNS
375 * Success: If dstlen > 0, number of characters written to destination
376 * buffer. If dstlen == 0, number of characters needed to do
377 * conversion.
378 * Failure: 0. Occurs if not enough space is available.
379 *
380 * ERRORS
381 * ERROR_INSUFFICIENT_BUFFER
382 * ERROR_INVALID_PARAMETER
383 */
384INT WINAPI WideCharToMultiByte( UINT page, DWORD flags, LPCWSTR src, INT srclen,
385 LPSTR dst, INT dstlen, LPCSTR defchar, BOOL *used )
386{
387 const union cptable *table;
388 int ret, used_tmp;
389
390#ifdef __WIN32OS2__
391 dprintf2(("WideCharToMultiByte %d %x %x %d %x %d", page, flags, src, srclen, dst, dstlen));
392#endif
393
394 //Docs say source ptr can't be the same as destination (Windows ME, NT4-SP6)
395 if (!src || (!dst && dstlen) || ((void *)src == (void *)dst))
396 {
397 SetLastError( ERROR_INVALID_PARAMETER );
398 return 0;
399 }
400
401 //Even though the docs claim this only works for -1, testing shows it
402 //is done for any negative value (Windows ME, NT4 - SP6)
403 if (srclen <= -1) srclen = strlenW(src) + 1;
404
405 switch(page)
406 {
407 case CP_UTF7:
408 FIXME("UTF-7 not supported\n");
409 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
410 return 0;
411 case CP_UTF8:
412 ret = utf8_wcstombs( src, srclen, dst, dstlen );
413 break;
414 default:
415 if (!(table = get_codepage_table( page )))
416 {
417 SetLastError( ERROR_INVALID_PARAMETER );
418 return 0;
419 }
420 ret = cp_wcstombs( table, flags, src, srclen, dst, dstlen,
421 defchar, used ? &used_tmp : NULL );
422 if (used) *used = used_tmp;
423 break;
424 }
425
426 if (ret == -1)
427 {
428 SetLastError( ERROR_INSUFFICIENT_BUFFER );
429 ret = 0;
430 }
431 return ret;
432}
433
434
435/******************************************************************************
436 * GetStringTypeW (KERNEL32)
437 *
438 */
439BOOL WINAPI GetStringTypeW( DWORD type, LPCWSTR src, INT count, LPWORD chartype )
440{
441#ifdef __WIN32OS2__
442 dprintf(("GetStringTypeW %x %x %d %x", type, src, count, chartype));
443#endif
444
445 if (count == -1) count = strlenW(src) + 1;
446 switch(type)
447 {
448 case CT_CTYPE1:
449 while (count--) *chartype++ = get_char_typeW( *src++ ) & 0xfff;
450 break;
451 case CT_CTYPE2:
452 while (count--) *chartype++ = get_char_typeW( *src++ ) >> 12;
453 break;
454 case CT_CTYPE3:
455 FIXME("CT_CTYPE3 not supported.\n");
456 default:
457 SetLastError( ERROR_INVALID_PARAMETER );
458 return FALSE;
459 }
460 return TRUE;
461}
462
463
464/******************************************************************************
465 * GetStringTypeExW (KERNEL32)
466 */
467BOOL WINAPI GetStringTypeExW( LCID locale, DWORD type, LPCWSTR src, INT count, LPWORD chartype )
468{
469 /* locale is ignored for Unicode */
470 return GetStringTypeW( type, src, count, chartype );
471}
472
473WCHAR WIN32API tolowerW( WCHAR ch )
474{
475 extern const WCHAR casemap_lower[];
476 return ch + casemap_lower[casemap_lower[ch >> 8] + (ch & 0xff)];
477}
478
479WCHAR WIN32API toupperW( WCHAR ch )
480{
481 extern const WCHAR casemap_upper[];
482 return ch + casemap_upper[casemap_upper[ch >> 8] + (ch & 0xff)];
483}
484
485/* the character type contains the C1_* flags in the low 12 bits */
486/* and the C2_* type in the high 4 bits */
487unsigned short get_char_typeW( WCHAR ch )
488{
489 extern const unsigned short wctype_table[];
490 return wctype_table[wctype_table[ch >> 8] + (ch & 0xff)];
491}
Note: See TracBrowser for help on using the repository browser.