source: trunk/src/kernel32/codepage.c@ 7832

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

codepage, getlocaleinfo + thread tib updates

File size: 15.2 KB
Line 
1/* $Id: codepage.c,v 1.1 2002-02-07 16:34:52 sandervl Exp $
2 *
3 * Code page functions
4 *
5 * Based on Wine code (memory\codepage.c)
6 *
7 * Copyright 2000 Alexandre Julliard
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12
13#include <assert.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17
18#include "winbase.h"
19#include "winerror.h"
20#include "winnls.h"
21#include "wine/unicode.h"
22#include "debugtools.h"
23
24#ifdef __WIN32OS2__
25#include <options.h>
26#include "codepage.h"
27
28#define DBG_LOCALLOG DBG_codepage
29#include "dbglocal.h"
30#endif
31
32DEFAULT_DEBUG_CHANNEL(string);
33
34/* current code pages */
35static const union cptable *ansi_cptable;
36static const union cptable *oem_cptable;
37static const union cptable *mac_cptable;
38
39/* retrieve a code page table from the locale info */
40static const union cptable *get_locale_cp( LCID lcid, LCTYPE type )
41{
42 const union cptable *table = NULL;
43 char buf[32];
44
45 if (GetLocaleInfoA( lcid, type, buf, sizeof(buf) )) table = cp_get_table( atoi(buf) );
46 return table;
47}
48
49/* setup default codepage info before we can get at the locale stuff */
50static void init_codepages(void)
51{
52 ansi_cptable = cp_get_table( 1252 );
53 oem_cptable = cp_get_table( 437 );
54 mac_cptable = cp_get_table( 10000 );
55 assert( ansi_cptable );
56 assert( oem_cptable );
57 assert( mac_cptable );
58}
59
60/* find the table for a given codepage, handling CP_ACP etc. pseudo-codepages */
61static const union cptable *get_codepage_table( unsigned int codepage )
62{
63 const union cptable *ret = NULL;
64
65 if (!ansi_cptable) init_codepages();
66
67 switch(codepage)
68 {
69 case CP_ACP: return ansi_cptable;
70 case CP_OEMCP: return oem_cptable;
71 case CP_MACCP: return mac_cptable;
72 case CP_THREAD_ACP: return get_locale_cp( GetThreadLocale(), LOCALE_IDEFAULTANSICODEPAGE );
73 case CP_UTF7:
74 case CP_UTF8:
75 break;
76 default:
77 if (codepage == ansi_cptable->info.codepage) return ansi_cptable;
78 if (codepage == oem_cptable->info.codepage) return oem_cptable;
79 if (codepage == mac_cptable->info.codepage) return mac_cptable;
80 ret = cp_get_table( codepage );
81 break;
82 }
83 return ret;
84}
85
86/* initialize default code pages from locale info */
87/* FIXME: should be done in init_codepages, but it can't right now */
88/* since it needs KERNEL32 to be loaded for the locale info. */
89void CODEPAGE_Init(void)
90{
91 const union cptable *table;
92 LCID lcid = GetUserDefaultLCID();
93
94 if (!ansi_cptable) init_codepages(); /* just in case */
95
96 if ((table = get_locale_cp( lcid, LOCALE_IDEFAULTANSICODEPAGE ))) ansi_cptable = table;
97 if ((table = get_locale_cp( lcid, LOCALE_IDEFAULTMACCODEPAGE ))) mac_cptable = table;
98 if ((table = get_locale_cp( lcid, LOCALE_IDEFAULTCODEPAGE ))) oem_cptable = table;
99
100 TRACE( "ansi=%03d oem=%03d mac=%03d\n", ansi_cptable->info.codepage,
101 oem_cptable->info.codepage, mac_cptable->info.codepage );
102#ifdef __WIN32OS2__
103 dprintf(("Language %s", getenv("LANG")));
104#endif
105}
106
107#ifdef __WIN32OS2__
108ULONG GetDisplayCodepage()
109{
110 if (!ansi_cptable) CODEPAGE_Init();
111
112 return ansi_cptable->info.codepage;
113}
114
115ULONG GetWindowsCodepage()
116{
117 if (!ansi_cptable) CODEPAGE_Init();
118
119 return ansi_cptable->info.codepage;
120}
121
122#endif
123
124/******************************************************************************
125 * GetACP (KERNEL32)
126 *
127 * RETURNS
128 * Current ANSI code-page identifier, default if no current defined
129 */
130UINT WINAPI GetACP(void)
131{
132 if (!ansi_cptable) init_codepages();
133#ifdef __WIN32OS2__
134 dprintf(("GetACP %d", ansi_cptable->info.codepage));
135#endif
136 return ansi_cptable->info.codepage;
137}
138
139
140/***********************************************************************
141 * GetOEMCP (KERNEL32)
142 */
143UINT WINAPI GetOEMCP(void)
144{
145 if (!oem_cptable) init_codepages();
146#ifdef __WIN32OS2__
147 dprintf(("GetOEMCP %d", oem_cptable->info.codepage));
148#endif
149 return oem_cptable->info.codepage;
150}
151
152
153/***********************************************************************
154 * IsValidCodePage (KERNEL32)
155 */
156BOOL WINAPI IsValidCodePage( UINT codepage )
157{
158#ifdef __WIN32OS2__
159 dprintf(("IsValidCodePage %d", codepage));
160#endif
161 return cp_get_table( codepage ) != NULL;
162}
163
164
165/***********************************************************************
166 * IsDBCSLeadByteEx (KERNEL32)
167 */
168BOOL WINAPI IsDBCSLeadByteEx( UINT codepage, BYTE testchar )
169{
170 const union cptable *table = get_codepage_table( codepage );
171#ifdef __WIN32OS2__
172 dprintf2(("IsDBCSLeadByteEx %d %x", codepage, testchar));
173#endif
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
473/******************************************************************************
474 * GetStringTypeA [KERNEL32.@]
475 */
476BOOL WINAPI GetStringTypeA(LCID locale, DWORD type, LPCSTR src, INT count, LPWORD chartype)
477{
478 char buf[20];
479 UINT cp;
480 INT countW;
481 LPWSTR srcW;
482 BOOL ret = FALSE;
483
484 if(count == -1) count = strlen(src) + 1;
485
486 if(!GetLocaleInfoA(locale, LOCALE_IDEFAULTANSICODEPAGE | LOCALE_NOUSEROVERRIDE,
487 buf, sizeof(buf)))
488 {
489 FIXME("For locale %04lx using current ANSI code page\n", locale);
490 cp = GetACP();
491 }
492 else
493 cp = atoi(buf);
494
495 countW = MultiByteToWideChar(cp, 0, src, count, NULL, 0);
496 if((srcW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
497 {
498 MultiByteToWideChar(cp, 0, src, count, srcW, countW);
499 ret = GetStringTypeW(type, srcW, count, chartype);
500 HeapFree(GetProcessHeap(), 0, srcW);
501 }
502 return ret;
503}
504
505/******************************************************************************
506 * GetStringTypeExA [KERNEL32.@]
507 */
508BOOL WINAPI GetStringTypeExA(LCID locale, DWORD type, LPCSTR src, INT count, LPWORD chartype)
509{
510 return GetStringTypeA(locale, type, src, count, chartype);
511}
512//******************************************************************************
513//******************************************************************************
514WCHAR WIN32API tolowerW( WCHAR ch )
515{
516 extern const WCHAR casemap_lower[];
517 return ch + casemap_lower[casemap_lower[ch >> 8] + (ch & 0xff)];
518}
519//******************************************************************************
520//******************************************************************************
521WCHAR WIN32API toupperW( WCHAR ch )
522{
523 extern const WCHAR casemap_upper[];
524 return ch + casemap_upper[casemap_upper[ch >> 8] + (ch & 0xff)];
525}
526//******************************************************************************
527/* the character type contains the C1_* flags in the low 12 bits */
528/* and the C2_* type in the high 4 bits */
529//******************************************************************************
530unsigned short get_char_typeW( WCHAR ch )
531{
532 extern const unsigned short wctype_table[];
533 return wctype_table[wctype_table[ch >> 8] + (ch & 0xff)];
534}
535//******************************************************************************
536//******************************************************************************
Note: See TracBrowser for help on using the repository browser.