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

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

update

File size: 13.6 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}
102
103#ifdef __WIN32OS2__
104ULONG GetDisplayCodepage()
105{
106 if (!ansi_cptable) CODEPAGE_Init();
107
108 return ansi_cptable->info.codepage;
109}
110
111ULONG GetWindowsCodepage()
112{
113 if (!ansi_cptable) CODEPAGE_Init();
114
115 return ansi_cptable->info.codepage;
116}
117
118static UconvObject GetObjectByCP(ULONG codepage)
119{
120 UconvObject rc = 0;
121 UniChar codepage_str[12];
122
123 BOOL ret = UniMapCpToUcsCp(codepage, codepage_str, sizeof(codepage_str));
124 if ( ret == ULS_SUCCESS )
125 {
126 ret = UniCreateUconvObject( codepage_str, &rc );
127 if ( ret != ULS_SUCCESS )
128 rc = 0;
129 }
130 dprintf(("UniCreateUconvObject for CP %d (%08x)\n", codepage, rc ));
131 return rc;
132}
133
134static UconvObject DisplayUconv = NULL;
135static UconvObject WindowsUconv = NULL;
136
137UconvObject GetDisplayUconvObject()
138{
139 if (!DisplayUconv)
140 DisplayUconv = GetObjectByCP(GetDisplayCodepage());
141
142 return DisplayUconv;
143}
144
145UconvObject GetWindowsUconvObject()
146{
147 if (!WindowsUconv)
148 WindowsUconv = GetObjectByCP(GetWindowsCodepage());
149
150 return WindowsUconv;
151}
152
153#endif
154
155/******************************************************************************
156 * GetACP (KERNEL32)
157 *
158 * RETURNS
159 * Current ANSI code-page identifier, default if no current defined
160 */
161UINT WINAPI GetACP(void)
162{
163 if (!ansi_cptable) init_codepages();
164#ifdef __WIN32OS2__
165 dprintf(("GetACP %d", ansi_cptable->info.codepage));
166#endif
167 return ansi_cptable->info.codepage;
168}
169
170
171/***********************************************************************
172 * GetOEMCP (KERNEL32)
173 */
174UINT WINAPI GetOEMCP(void)
175{
176 if (!oem_cptable) init_codepages();
177#ifdef __WIN32OS2__
178 dprintf(("GetOEMCP %d", oem_cptable->info.codepage));
179#endif
180 return oem_cptable->info.codepage;
181}
182
183
184/***********************************************************************
185 * IsValidCodePage (KERNEL32)
186 */
187BOOL WINAPI IsValidCodePage( UINT codepage )
188{
189#ifdef __WIN32OS2__
190 dprintf(("IsValidCodePage %d", codepage));
191#endif
192 return cp_get_table( codepage ) != NULL;
193}
194
195
196/***********************************************************************
197 * IsDBCSLeadByteEx (KERNEL32)
198 */
199BOOL WINAPI IsDBCSLeadByteEx( UINT codepage, BYTE testchar )
200{
201#ifdef __WIN32OS2__
202 dprintf2(("IsDBCSLeadByteEx %d %x", codepage, testchar));
203#endif
204
205 const union cptable *table = get_codepage_table( codepage );
206 return table && is_dbcs_leadbyte( table, testchar );
207}
208
209
210/***********************************************************************
211 * IsDBCSLeadByte (KERNEL32)
212 */
213BOOL WINAPI IsDBCSLeadByte( BYTE testchar )
214{
215 if (!ansi_cptable) init_codepages();
216 return is_dbcs_leadbyte( ansi_cptable, testchar );
217}
218
219
220/***********************************************************************
221 * GetCPInfo (KERNEL32)
222 */
223BOOL WINAPI GetCPInfo( UINT codepage, LPCPINFO cpinfo )
224{
225 const union cptable *table = get_codepage_table( codepage );
226
227#ifdef __WIN32OS2__
228 dprintf(("GetCPInfo %d %x", codepage, cpinfo));
229#endif
230
231 if (!table)
232 {
233 SetLastError( ERROR_INVALID_PARAMETER );
234 return FALSE;
235 }
236 if (table->info.def_char & 0xff00)
237 {
238 cpinfo->DefaultChar[0] = table->info.def_char & 0xff00;
239 cpinfo->DefaultChar[1] = table->info.def_char & 0x00ff;
240 }
241 else
242 {
243 cpinfo->DefaultChar[0] = table->info.def_char & 0xff;
244 cpinfo->DefaultChar[1] = 0;
245 }
246 if ((cpinfo->MaxCharSize = table->info.char_size) == 2)
247 memcpy( cpinfo->LeadByte, table->dbcs.lead_bytes, sizeof(cpinfo->LeadByte) );
248 else
249 cpinfo->LeadByte[0] = cpinfo->LeadByte[1] = 0;
250
251 return TRUE;
252}
253
254
255/***********************************************************************
256 * EnumSystemCodePagesA (KERNEL32)
257 */
258BOOL WINAPI EnumSystemCodePagesA( CODEPAGE_ENUMPROCA lpfnCodePageEnum, DWORD flags )
259{
260 const union cptable *table;
261 char buffer[10];
262 int index = 0;
263
264#ifdef __WIN32OS2__
265 dprintf(("EnumSystemCodePagesA %x %x", lpfnCodePageEnum, flags));
266#endif
267
268 for (;;)
269 {
270 if (!(table = cp_enum_table( index++ ))) break;
271 sprintf( buffer, "%d", table->info.codepage );
272 if (!lpfnCodePageEnum( buffer )) break;
273 }
274 return TRUE;
275}
276
277
278/***********************************************************************
279 * EnumSystemCodePagesW (KERNEL32)
280 */
281BOOL WINAPI EnumSystemCodePagesW( CODEPAGE_ENUMPROCW lpfnCodePageEnum, DWORD flags )
282{
283 const union cptable *table;
284 WCHAR buffer[10], *p;
285 int page, index = 0;
286
287#ifdef __WIN32OS2__
288 dprintf(("EnumSystemCodePagesW %x %x", lpfnCodePageEnum, flags));
289#endif
290
291 for (;;)
292 {
293 if (!(table = cp_enum_table( index++ ))) break;
294 p = buffer + sizeof(buffer)/sizeof(WCHAR);
295 *--p = 0;
296 page = table->info.codepage;
297 do
298 {
299 *--p = '0' + (page % 10);
300 page /= 10;
301 } while( page );
302 if (!lpfnCodePageEnum( p )) break;
303 }
304 return TRUE;
305}
306
307
308/***********************************************************************
309 * MultiByteToWideChar (KERNEL32)
310 *
311 * PARAMS
312 * page [in] Codepage character set to convert from
313 * flags [in] Character mapping flags
314 * src [in] Source string buffer
315 * srclen [in] Length of source string buffer
316 * dst [in] Destination buffer
317 * dstlen [in] Length of destination buffer
318 *
319 * NOTES
320 * The returned length includes the null terminator character.
321 *
322 * RETURNS
323 * Success: If dstlen > 0, number of characters written to destination
324 * buffer. If dstlen == 0, number of characters needed to do
325 * conversion.
326 * Failure: 0. Occurs if not enough space is available.
327 *
328 * ERRORS
329 * ERROR_INSUFFICIENT_BUFFER
330 * ERROR_INVALID_PARAMETER
331 * ERROR_NO_UNICODE_TRANSLATION
332 *
333 */
334INT WINAPI MultiByteToWideChar( UINT page, DWORD flags, LPCSTR src, INT srclen,
335 LPWSTR dst, INT dstlen )
336{
337 const union cptable *table;
338 int ret;
339
340#ifdef __WIN32OS2__
341 dprintf2(("MultiByteToWideChar %d %x %x %d %x %d", page, flags, src, srclen, dst, dstlen));
342#endif
343
344 if (!src || (!dst && dstlen))
345 {
346 SetLastError( ERROR_INVALID_PARAMETER );
347 return 0;
348 }
349
350 if (srclen == -1) srclen = strlen(src) + 1;
351
352 if (flags & MB_USEGLYPHCHARS) FIXME("MB_USEGLYPHCHARS not supported\n");
353
354 switch(page)
355 {
356 case CP_UTF7:
357 FIXME("UTF not supported\n");
358 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
359 return 0;
360 case CP_UTF8:
361 ret = utf8_mbstowcs( flags, src, srclen, dst, dstlen );
362 break;
363 default:
364 if (!(table = get_codepage_table( page )))
365 {
366 SetLastError( ERROR_INVALID_PARAMETER );
367 return 0;
368 }
369 ret = cp_mbstowcs( table, flags, src, srclen, dst, dstlen );
370 break;
371 }
372
373 if (ret < 0)
374 {
375 switch(ret)
376 {
377 case -1: SetLastError( ERROR_INSUFFICIENT_BUFFER ); break;
378 case -2: SetLastError( ERROR_NO_UNICODE_TRANSLATION ); break;
379 }
380 ret = 0;
381 }
382 return ret;
383}
384
385
386/***********************************************************************
387 * WideCharToMultiByte (KERNEL32)
388 *
389 * PARAMS
390 * page [in] Codepage character set to convert to
391 * flags [in] Character mapping flags
392 * src [in] Source string buffer
393 * srclen [in] Length of source string buffer
394 * dst [in] Destination buffer
395 * dstlen [in] Length of destination buffer
396 * defchar [in] Default character to use for conversion if no exact
397 * conversion can be made
398 * used [out] Set if default character was used in the conversion
399 *
400 * NOTES
401 * The returned length includes the null terminator character.
402 *
403 * RETURNS
404 * Success: If dstlen > 0, number of characters written to destination
405 * buffer. If dstlen == 0, number of characters needed to do
406 * conversion.
407 * Failure: 0. Occurs if not enough space is available.
408 *
409 * ERRORS
410 * ERROR_INSUFFICIENT_BUFFER
411 * ERROR_INVALID_PARAMETER
412 */
413INT WINAPI WideCharToMultiByte( UINT page, DWORD flags, LPCWSTR src, INT srclen,
414 LPSTR dst, INT dstlen, LPCSTR defchar, BOOL *used )
415{
416 const union cptable *table;
417 int ret, used_tmp;
418
419#ifdef __WIN32OS2__
420 dprintf2(("WideCharToMultiByte %d %x %x %d %x %d", page, flags, src, srclen, dst, dstlen));
421#endif
422
423 if (!src || (!dst && dstlen))
424 {
425 SetLastError( ERROR_INVALID_PARAMETER );
426 return 0;
427 }
428
429 if (srclen == -1) srclen = strlenW(src) + 1;
430
431 switch(page)
432 {
433 case CP_UTF7:
434 FIXME("UTF-7 not supported\n");
435 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
436 return 0;
437 case CP_UTF8:
438 ret = utf8_wcstombs( src, srclen, dst, dstlen );
439 break;
440 default:
441 if (!(table = get_codepage_table( page )))
442 {
443 SetLastError( ERROR_INVALID_PARAMETER );
444 return 0;
445 }
446 ret = cp_wcstombs( table, flags, src, srclen, dst, dstlen,
447 defchar, used ? &used_tmp : NULL );
448 if (used) *used = used_tmp;
449 break;
450 }
451
452 if (ret == -1)
453 {
454 SetLastError( ERROR_INSUFFICIENT_BUFFER );
455 ret = 0;
456 }
457 return ret;
458}
459
460
461/******************************************************************************
462 * GetStringTypeW (KERNEL32)
463 *
464 */
465BOOL WINAPI GetStringTypeW( DWORD type, LPCWSTR src, INT count, LPWORD chartype )
466{
467#ifdef __WIN32OS2__
468 dprintf(("GetStringTypeW %x %x %d %x", type, src, count, chartype));
469#endif
470
471 if (count == -1) count = strlenW(src) + 1;
472 switch(type)
473 {
474 case CT_CTYPE1:
475 while (count--) *chartype++ = get_char_typeW( *src++ ) & 0xfff;
476 break;
477 case CT_CTYPE2:
478 while (count--) *chartype++ = get_char_typeW( *src++ ) >> 12;
479 break;
480 case CT_CTYPE3:
481 FIXME("CT_CTYPE3 not supported.\n");
482 default:
483 SetLastError( ERROR_INVALID_PARAMETER );
484 return FALSE;
485 }
486 return TRUE;
487}
488
489
490/******************************************************************************
491 * GetStringTypeExW (KERNEL32)
492 */
493BOOL WINAPI GetStringTypeExW( LCID locale, DWORD type, LPCWSTR src, INT count, LPWORD chartype )
494{
495 /* locale is ignored for Unicode */
496 return GetStringTypeW( type, src, count, chartype );
497}
498
499WCHAR WIN32API tolowerW( WCHAR ch )
500{
501 extern const WCHAR casemap_lower[];
502 return ch + casemap_lower[casemap_lower[ch >> 8] + (ch & 0xff)];
503}
504
505WCHAR WIN32API toupperW( WCHAR ch )
506{
507 extern const WCHAR casemap_upper[];
508 return ch + casemap_upper[casemap_upper[ch >> 8] + (ch & 0xff)];
509}
510
511/* the character type contains the C1_* flags in the low 12 bits */
512/* and the C2_* type in the high 4 bits */
513unsigned short get_char_typeW( WCHAR ch )
514{
515 extern const unsigned short wctype_table[];
516 return wctype_table[wctype_table[ch >> 8] + (ch & 0xff)];
517}
Note: See TracBrowser for help on using the repository browser.