From a3c45689b487ebf565a1f30a1c2b7d8e6205e555 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 14 Oct 2003 05:32:30 +0000 Subject: [PATCH] Moved codepage functions to dlls/kernel. Changed initialisation of the locale functions so that CP_UNIXCP works as soon as possible during kernel32 init. --- dlls/kernel/Makefile.in | 1 - dlls/kernel/kernel_main.c | 6 +- dlls/kernel/locale.c | 525 ++++++++++++++++++++++++++++++++++++- dlls/kernel/process.c | 4 +- memory/codepage.c | 531 -------------------------------------- 5 files changed, 518 insertions(+), 549 deletions(-) delete mode 100644 memory/codepage.c diff --git a/dlls/kernel/Makefile.in b/dlls/kernel/Makefile.in index 9935780d79a..3a36baac696 100644 --- a/dlls/kernel/Makefile.in +++ b/dlls/kernel/Makefile.in @@ -24,7 +24,6 @@ C_SRCS = \ $(TOPOBJDIR)/files/file.c \ $(TOPOBJDIR)/files/smb.c \ $(TOPOBJDIR)/loader/module.c \ - $(TOPOBJDIR)/memory/codepage.c \ $(TOPOBJDIR)/memory/environ.c \ $(TOPOBJDIR)/memory/virtual.c \ $(TOPOBJDIR)/misc/cpu.c \ diff --git a/dlls/kernel/kernel_main.c b/dlls/kernel/kernel_main.c index 25e4ad34140..78717c042f4 100644 --- a/dlls/kernel/kernel_main.c +++ b/dlls/kernel/kernel_main.c @@ -47,7 +47,7 @@ #include "kernel_private.h" #include "console_private.h" -extern void LOCALE_Init(void); +extern void LOCALE_InitRegistry(void); extern void COMPUTERNAME_Init(void); extern int __wine_set_signal_handler(unsigned, int (*)(unsigned)); @@ -115,8 +115,8 @@ static BOOL process_attach(void) FILE_umask = umask(0777); umask( FILE_umask ); - /* Setup codepage info */ - LOCALE_Init(); + /* Setup registry locale information */ + LOCALE_InitRegistry(); /* Initialize 16-bit thunking entry points */ if (!WOWTHUNK_Init()) return FALSE; diff --git a/dlls/kernel/locale.c b/dlls/kernel/locale.c index e3c8f02fdc6..48dc01a677d 100644 --- a/dlls/kernel/locale.c +++ b/dlls/kernel/locale.c @@ -24,6 +24,7 @@ #include "config.h" #include "wine/port.h" +#include #include #include #include @@ -48,7 +49,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(nls); static const WCHAR kernel32W[] = { 'K','E','R','N','E','L','3','2','\0' }; -extern void CODEPAGE_Init( UINT ansi_cp, UINT oem_cp, UINT mac_cp, UINT unix_cp, LCID lcid ); +/* current code pages */ +static const union cptable *ansi_cptable; +static const union cptable *oem_cptable; +static const union cptable *mac_cptable; +static const union cptable *unix_cptable; /* NULL if UTF8 */ /* Charset to codepage map, sorted by name. */ static const struct charset_entry @@ -128,6 +133,55 @@ inline static UINT get_lcid_codepage( LCID lcid ) } +/* setup default codepage info before we can get at the locale stuff */ +static void init_codepages(void) +{ + ansi_cptable = wine_cp_get_table( 1252 ); + oem_cptable = wine_cp_get_table( 437 ); + mac_cptable = wine_cp_get_table( 10000 ); + unix_cptable = wine_cp_get_table( 28591 ); + assert( ansi_cptable ); + assert( oem_cptable ); + assert( mac_cptable ); + assert( unix_cptable ); +} + +/*********************************************************************** + * get_codepage_table + * + * Find the table for a given codepage, handling CP_ACP etc. pseudo-codepages + */ +static const union cptable *get_codepage_table( unsigned int codepage ) +{ + const union cptable *ret = NULL; + + if (!ansi_cptable) init_codepages(); + assert( ansi_cptable ); /* init must have been done already */ + + switch(codepage) + { + case CP_ACP: + return ansi_cptable; + case CP_OEMCP: + return oem_cptable; + case CP_MACCP: + return mac_cptable; + case CP_UTF7: + case CP_UTF8: + break; + case CP_THREAD_ACP: + if (!(codepage = NtCurrentTeb()->code_page)) return ansi_cptable; + /* fall through */ + default: + if (codepage == ansi_cptable->info.codepage) return ansi_cptable; + if (codepage == oem_cptable->info.codepage) return oem_cptable; + if (codepage == mac_cptable->info.codepage) return mac_cptable; + ret = wine_cp_get_table( codepage ); + break; + } + return ret; +} + /*********************************************************************** * create_registry_key * @@ -158,12 +212,12 @@ inline static HKEY create_registry_key(void) /*********************************************************************** - * update_registry + * LOCALE_InitRegistry * * Update registry contents on startup if the user locale has changed. * This simulates the action of the Windows control panel. */ -inline static void update_registry( LCID lcid ) +void LOCALE_InitRegistry(void) { static const USHORT updateValues[] = { LOCALE_SLANGUAGE, @@ -195,6 +249,7 @@ inline static void update_registry( LCID lcid ) WCHAR bufferW[80]; DWORD count, i; HKEY hkey; + LCID lcid = GetUserDefaultLCID(); if (!(hkey = create_registry_key())) return; /* don't do anything if we can't create the registry key */ @@ -411,18 +466,19 @@ static int charset_cmp( const void *name, const void *entry ) */ static LCID init_default_lcid( UINT *unix_cp ) { - char buf[256]; - char *lang,*country,*charset,*dialect,*next; + char *buf, *lang,*country,*charset,*dialect,*next; LCID ret = 0; - if (GetEnvironmentVariableA( "LC_ALL", buf, sizeof(buf) ) || - GetEnvironmentVariableA( "LC_CTYPE", buf, sizeof(buf) ) || - GetEnvironmentVariableA( "LANGUAGE", buf, sizeof(buf) ) || - GetEnvironmentVariableA( "LC_MESSAGES", buf, sizeof(buf) ) || - GetEnvironmentVariableA( "LANG", buf, sizeof(buf) )) + if ((lang = getenv( "LC_ALL" )) || + (lang = getenv( "LC_CTYPE" )) || + (lang = getenv( "LANGUAGE" )) || + (lang = getenv( "LC_MESSAGES" )) || + (lang = getenv( "LANG" ))) { - if (!strcmp(buf,"POSIX") || !strcmp(buf,"C")) goto done; + if (!strcmp(lang,"POSIX") || !strcmp(lang,"C")) goto done; + buf = RtlAllocateHeap( GetProcessHeap(), 0, strlen(lang) + 1 ); + strcpy( buf, lang ); lang=buf; do { @@ -459,6 +515,7 @@ static LCID init_default_lcid( UINT *unix_cp ) } while (lang && !ret); if (!ret) MESSAGE("Warning: language '%s' not recognized, defaulting to English\n", buf); + RtlFreeHeap( GetProcessHeap(), 0, buf ); } done: @@ -467,6 +524,64 @@ static LCID init_default_lcid( UINT *unix_cp ) } +/*********************************************************************** + * GetUserDefaultLangID (KERNEL32.@) + */ +LANGID WINAPI GetUserDefaultLangID(void) +{ + return LANGIDFROMLCID(GetUserDefaultLCID()); +} + + +/*********************************************************************** + * GetSystemDefaultLangID (KERNEL32.@) + */ +LANGID WINAPI GetSystemDefaultLangID(void) +{ + return GetUserDefaultLangID(); +} + + +/*********************************************************************** + * GetUserDefaultLCID (KERNEL32.@) + */ +LCID WINAPI GetUserDefaultLCID(void) +{ + LCID lcid; + NtQueryDefaultLocale( TRUE, &lcid ); + return lcid; +} + + +/*********************************************************************** + * GetSystemDefaultLCID (KERNEL32.@) + */ +LCID WINAPI GetSystemDefaultLCID(void) +{ + LCID lcid; + NtQueryDefaultLocale( FALSE, &lcid ); + return lcid; +} + + +/*********************************************************************** + * GetUserDefaultUILanguage (KERNEL32.@) + */ +LANGID WINAPI GetUserDefaultUILanguage(void) +{ + return GetUserDefaultLangID(); +} + + +/*********************************************************************** + * GetSystemDefaultUILanguage (KERNEL32.@) + */ +LANGID WINAPI GetSystemDefaultUILanguage(void) +{ + return GetSystemDefaultLangID(); +} + + /****************************************************************************** * get_locale_value_name * @@ -942,6 +1057,373 @@ BOOL WINAPI SetLocaleInfoW( LCID lcid, LCTYPE lctype, LPCWSTR data ) } +/****************************************************************************** + * GetACP (KERNEL32.@) + * + * RETURNS + * Current ANSI code-page identifier, default if no current defined + */ +UINT WINAPI GetACP(void) +{ + assert( ansi_cptable ); + return ansi_cptable->info.codepage; +} + + +/*********************************************************************** + * GetOEMCP (KERNEL32.@) + */ +UINT WINAPI GetOEMCP(void) +{ + assert( oem_cptable ); + return oem_cptable->info.codepage; +} + + +/*********************************************************************** + * IsValidCodePage (KERNEL32.@) + */ +BOOL WINAPI IsValidCodePage( UINT codepage ) +{ + switch(codepage) { + case CP_SYMBOL: + return FALSE; + case CP_UTF7: + case CP_UTF8: + return TRUE; + default: + return wine_cp_get_table( codepage ) != NULL; + } +} + + +/*********************************************************************** + * IsDBCSLeadByteEx (KERNEL32.@) + * + * Determine if a character is a lead byte in a given code page. + * + * PARAMS + * codepage [I] Code page for the test. + * testchar [I] Character to test + * + * RETURNS + * TRUE, if testchar is a lead byte in codepage, + * FALSE otherwise. + */ +BOOL WINAPI IsDBCSLeadByteEx( UINT codepage, BYTE testchar ) +{ + const union cptable *table = get_codepage_table( codepage ); + return table && is_dbcs_leadbyte( table, testchar ); +} + + +/*********************************************************************** + * IsDBCSLeadByte (KERNEL32.@) + * IsDBCSLeadByte (KERNEL.207) + * + * Determine if a character is a lead byte. + * + * PARAMS + * testchar [I] Character to test + * + * RETURNS + * TRUE, if testchar is a lead byte in the Ansii code page, + * FALSE otherwise. + */ +BOOL WINAPI IsDBCSLeadByte( BYTE testchar ) +{ + if (!ansi_cptable) return FALSE; + return is_dbcs_leadbyte( ansi_cptable, testchar ); +} + + +/*********************************************************************** + * GetCPInfo (KERNEL32.@) + * + * Get information about a code page. + * + * PARAMS + * codepage [I] Code page number + * cpinfo [O] Destination for code page information + * + * RETURNS + * Success: TRUE. cpinfo is updated with the information about codepage. + * Failure: FALSE, if codepage is invalid or cpinfo is NULL. + */ +BOOL WINAPI GetCPInfo( UINT codepage, LPCPINFO cpinfo ) +{ + const union cptable *table = get_codepage_table( codepage ); + + if (!table) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + if (table->info.def_char & 0xff00) + { + cpinfo->DefaultChar[0] = table->info.def_char & 0xff00; + cpinfo->DefaultChar[1] = table->info.def_char & 0x00ff; + } + else + { + cpinfo->DefaultChar[0] = table->info.def_char & 0xff; + cpinfo->DefaultChar[1] = 0; + } + if ((cpinfo->MaxCharSize = table->info.char_size) == 2) + memcpy( cpinfo->LeadByte, table->dbcs.lead_bytes, sizeof(cpinfo->LeadByte) ); + else + cpinfo->LeadByte[0] = cpinfo->LeadByte[1] = 0; + + return TRUE; +} + +/*********************************************************************** + * GetCPInfoExA (KERNEL32.@) + * + * Get extended information about a code page. + * + * PARAMS + * codepage [I] Code page number + * dwFlags [I] Reserved, must to 0. + * cpinfo [O] Destination for code page information + * + * RETURNS + * Success: TRUE. cpinfo is updated with the information about codepage. + * Failure: FALSE, if codepage is invalid or cpinfo is NULL. + */ +BOOL WINAPI GetCPInfoExA( UINT codepage, DWORD dwFlags, LPCPINFOEXA cpinfo ) +{ + const union cptable *table = get_codepage_table( codepage ); + + if (!GetCPInfo( codepage, (LPCPINFO)cpinfo )) + return FALSE; + + cpinfo->CodePage = codepage; + cpinfo->UnicodeDefaultChar = table->info.def_unicode_char; + strcpy(cpinfo->CodePageName, table->info.name); + return TRUE; +} + +/*********************************************************************** + * GetCPInfoExW (KERNEL32.@) + * + * Unicode version of GetCPInfoExA. + */ +BOOL WINAPI GetCPInfoExW( UINT codepage, DWORD dwFlags, LPCPINFOEXW cpinfo ) +{ + const union cptable *table = get_codepage_table( codepage ); + + if (!GetCPInfo( codepage, (LPCPINFO)cpinfo )) + return FALSE; + + cpinfo->CodePage = codepage; + cpinfo->UnicodeDefaultChar = table->info.def_unicode_char; + MultiByteToWideChar( CP_ACP, 0, table->info.name, -1, cpinfo->CodePageName, + sizeof(cpinfo->CodePageName)/sizeof(WCHAR)); + return TRUE; +} + +/*********************************************************************** + * EnumSystemCodePagesA (KERNEL32.@) + */ +BOOL WINAPI EnumSystemCodePagesA( CODEPAGE_ENUMPROCA lpfnCodePageEnum, DWORD flags ) +{ + const union cptable *table; + char buffer[10]; + int index = 0; + + for (;;) + { + if (!(table = wine_cp_enum_table( index++ ))) break; + sprintf( buffer, "%d", table->info.codepage ); + if (!lpfnCodePageEnum( buffer )) break; + } + return TRUE; +} + + +/*********************************************************************** + * EnumSystemCodePagesW (KERNEL32.@) + */ +BOOL WINAPI EnumSystemCodePagesW( CODEPAGE_ENUMPROCW lpfnCodePageEnum, DWORD flags ) +{ + const union cptable *table; + WCHAR buffer[10], *p; + int page, index = 0; + + for (;;) + { + if (!(table = wine_cp_enum_table( index++ ))) break; + p = buffer + sizeof(buffer)/sizeof(WCHAR); + *--p = 0; + page = table->info.codepage; + do + { + *--p = '0' + (page % 10); + page /= 10; + } while( page ); + if (!lpfnCodePageEnum( p )) break; + } + return TRUE; +} + + +/*********************************************************************** + * MultiByteToWideChar (KERNEL32.@) + * + * Convert a multibyte character string into a Unicode string. + * + * PARAMS + * page [I] Codepage character set to convert from + * flags [I] Character mapping flags + * src [I] Source string buffer + * srclen [I] Length of src, or -1 if src is NUL terminated + * dst [O] Destination buffer + * dstlen [I] Length of dst, or 0 to compute the required length + * + * RETURNS + * Success: If dstlen > 0, the number of characters written to dst. + * If dstlen == 0, the number of characters needed to perform the + * conversion. In both cases the count includes the terminating NUL. + * Failure: 0. Use GetLastError() to determine the cause. Possible errors are + * ERROR_INSUFFICIENT_BUFFER, if not enough space is available in dst + * and dstlen != 0; ERROR_INVALID_PARAMETER, if an invalid parameter + * is passed, and ERROR_NO_UNICODE_TRANSLATION if no translation is + * possible for src. + */ +INT WINAPI MultiByteToWideChar( UINT page, DWORD flags, LPCSTR src, INT srclen, + LPWSTR dst, INT dstlen ) +{ + const union cptable *table; + int ret; + + if (!src || (!dst && dstlen)) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return 0; + } + + if (srclen < 0) srclen = strlen(src) + 1; + + if (flags & MB_USEGLYPHCHARS) FIXME("MB_USEGLYPHCHARS not supported\n"); + + switch(page) + { + case CP_UTF7: + FIXME("UTF-7 not supported\n"); + SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); + return 0; + case CP_UNIXCP: + if (unix_cptable) + { + ret = wine_cp_mbstowcs( unix_cptable, flags, src, srclen, dst, dstlen ); + break; + } + /* fall through */ + case CP_UTF8: + ret = wine_utf8_mbstowcs( flags, src, srclen, dst, dstlen ); + break; + default: + if (!(table = get_codepage_table( page ))) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return 0; + } + ret = wine_cp_mbstowcs( table, flags, src, srclen, dst, dstlen ); + break; + } + + if (ret < 0) + { + switch(ret) + { + case -1: SetLastError( ERROR_INSUFFICIENT_BUFFER ); break; + case -2: SetLastError( ERROR_NO_UNICODE_TRANSLATION ); break; + } + ret = 0; + } + return ret; +} + + +/*********************************************************************** + * WideCharToMultiByte (KERNEL32.@) + * + * Convert a Unicode character string into a multibyte string. + * + * PARAMS + * page [I] Code page character set to convert to + * flags [I] Mapping Flags (MB_ constants from "winnls.h"). + * src [I] Source string buffer + * srclen [I] Length of src, or -1 if src is NUL terminated + * dst [O] Destination buffer + * dstlen [I] Length of dst, or 0 to compute the required length + * defchar [I] Default character to use for conversion if no exact + * conversion can be made + * used [O] Set if default character was used in the conversion + * + * RETURNS + * Success: If dstlen > 0, the number of characters written to dst. + * If dstlen == 0, number of characters needed to perform the + * conversion. In both cases the count includes the terminating NUL. + * Failure: 0. Use GetLastError() to determine the cause. Possible errors are + * ERROR_INSUFFICIENT_BUFFER, if not enough space is available in dst + * and dstlen != 0, and ERROR_INVALID_PARAMETER, if an invalid + * parameter was given. + */ +INT WINAPI WideCharToMultiByte( UINT page, DWORD flags, LPCWSTR src, INT srclen, + LPSTR dst, INT dstlen, LPCSTR defchar, BOOL *used ) +{ + const union cptable *table; + int ret, used_tmp; + + if (!src || (!dst && dstlen)) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return 0; + } + + if (srclen < 0) srclen = strlenW(src) + 1; + + switch(page) + { + case CP_UTF7: + FIXME("UTF-7 not supported\n"); + SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); + return 0; + case CP_UNIXCP: + if (unix_cptable) + { + ret = wine_cp_wcstombs( unix_cptable, flags, src, srclen, dst, dstlen, + defchar, used ? &used_tmp : NULL ); + break; + } + /* fall through */ + case CP_UTF8: + ret = wine_utf8_wcstombs( src, srclen, dst, dstlen ); + break; + default: + if (!(table = get_codepage_table( page ))) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return 0; + } + ret = wine_cp_wcstombs( table, flags, src, srclen, dst, dstlen, + defchar, used ? &used_tmp : NULL ); + if (used) *used = used_tmp; + break; + } + + if (ret == -1) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + ret = 0; + } + TRACE("cp %d %s -> %s\n", page, debugstr_w(src), debugstr_a(dst)); + return ret; +} + + /*********************************************************************** * GetThreadLocale (KERNEL32.@) * @@ -1578,6 +2060,8 @@ int WINAPI lstrcmpiW(LPCWSTR str1, LPCWSTR str2) */ void LOCALE_Init(void) { + extern void __wine_init_codepages( const union cptable *ansi_cp, const union cptable *oem_cp ); + UINT ansi_cp = 1252, oem_cp = 437, mac_cp = 10000, unix_cp = ~0U; LCID lcid = init_default_lcid( &unix_cp ); @@ -1593,8 +2077,23 @@ void LOCALE_Init(void) GetLocaleInfoW( lcid, LOCALE_IDEFAULTUNIXCODEPAGE | LOCALE_RETURN_NUMBER, (LPWSTR)&unix_cp, sizeof(unix_cp)/sizeof(WCHAR) ); - CODEPAGE_Init( ansi_cp, oem_cp, mac_cp, unix_cp, lcid ); - update_registry( lcid ); + if (!(ansi_cptable = wine_cp_get_table( ansi_cp ))) + ansi_cptable = wine_cp_get_table( 1252 ); + if (!(oem_cptable = wine_cp_get_table( oem_cp ))) + oem_cptable = wine_cp_get_table( 437 ); + if (!(mac_cptable = wine_cp_get_table( mac_cp ))) + mac_cptable = wine_cp_get_table( 10000 ); + if (unix_cp != CP_UTF8) + { + if (!(unix_cptable = wine_cp_get_table( unix_cp ))) + unix_cptable = wine_cp_get_table( 28591 ); + } + + __wine_init_codepages( ansi_cptable, oem_cptable ); + + TRACE( "ansi=%03d oem=%03d mac=%03d unix=%03d\n", + ansi_cptable->info.codepage, oem_cptable->info.codepage, + mac_cptable->info.codepage, unix_cp ); } static HKEY NLS_RegOpenKey(HKEY hRootKey, LPCWSTR szKeyName) diff --git a/dlls/kernel/process.c b/dlls/kernel/process.c index 6525129aa5f..c9949e9b8a5 100644 --- a/dlls/kernel/process.c +++ b/dlls/kernel/process.c @@ -72,6 +72,7 @@ static const WCHAR winevdmW[] = {'w','i','n','e','v','d','m','.','e','x','e',0}; extern void SHELL_LoadRegistry(void); extern void VERSION_Init( const WCHAR *appname ); extern void MODULE_InitLoadPath(void); +extern void LOCALE_Init(void); /*********************************************************************** * contains_path @@ -684,6 +685,8 @@ static BOOL process_init( char *argv[], char **environ ) params->hStdError = hstderr; } + LOCALE_Init(); + /* Copy the parent environment */ if (!build_initial_environment( environ )) return FALSE; @@ -758,7 +761,6 @@ void __wine_kernel_init(void) if (!__wine_main_argv[0]) OPTIONS_Usage(); - /* FIXME: locale info not loaded yet */ MultiByteToWideChar( CP_UNIXCP, 0, __wine_main_argv[0], -1, exe_nameW, MAX_PATH ); if (!find_exe_file( exe_nameW, buffer, MAX_PATH, &main_exe_file )) { diff --git a/memory/codepage.c b/memory/codepage.c deleted file mode 100644 index dfed84568c6..00000000000 --- a/memory/codepage.c +++ /dev/null @@ -1,531 +0,0 @@ -/* - * Code page functions - * - * Copyright 2000 Alexandre Julliard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "winerror.h" -#include "winnls.h" -#include "wine/unicode.h" -#include "thread.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(string); - -/* current code pages */ -static const union cptable *ansi_cptable; -static const union cptable *oem_cptable; -static const union cptable *mac_cptable; -static const union cptable *unix_cptable; /* NULL if UTF8 */ -static LCID default_lcid = MAKELCID( MAKELANGID(LANG_ENGLISH,SUBLANG_DEFAULT), SORT_DEFAULT ); - -/* setup default codepage info before we can get at the locale stuff */ -static void init_codepages(void) -{ - ansi_cptable = wine_cp_get_table( 1252 ); - oem_cptable = wine_cp_get_table( 437 ); - mac_cptable = wine_cp_get_table( 10000 ); - unix_cptable = wine_cp_get_table( 28591 ); - assert( ansi_cptable ); - assert( oem_cptable ); - assert( mac_cptable ); - assert( unix_cptable ); -} - -/* find the table for a given codepage, handling CP_ACP etc. pseudo-codepages */ -static const union cptable *get_codepage_table( unsigned int codepage ) -{ - const union cptable *ret = NULL; - - if (!ansi_cptable) init_codepages(); - - switch(codepage) - { - case CP_ACP: - return ansi_cptable; - case CP_OEMCP: - return oem_cptable; - case CP_MACCP: - return mac_cptable; - case CP_UTF7: - case CP_UTF8: - break; - case CP_THREAD_ACP: - if (!(codepage = NtCurrentTeb()->code_page)) return ansi_cptable; - /* fall through */ - default: - if (codepage == ansi_cptable->info.codepage) return ansi_cptable; - if (codepage == oem_cptable->info.codepage) return oem_cptable; - if (codepage == mac_cptable->info.codepage) return mac_cptable; - ret = wine_cp_get_table( codepage ); - break; - } - return ret; -} - -/* initialize default code pages from locale info */ -/* FIXME: should be done in init_codepages, but it can't right now */ -/* since it needs KERNEL32 to be loaded for the locale info. */ -void CODEPAGE_Init( UINT ansi_cp, UINT oem_cp, UINT mac_cp, UINT unix_cp, LCID lcid ) -{ - extern void __wine_init_codepages( const union cptable *ansi_cp, const union cptable *oem_cp ); - const union cptable *table; - - default_lcid = lcid; - if (!ansi_cptable) init_codepages(); /* just in case */ - - if ((table = wine_cp_get_table( ansi_cp ))) ansi_cptable = table; - if ((table = wine_cp_get_table( oem_cp ))) oem_cptable = table; - if ((table = wine_cp_get_table( mac_cp ))) mac_cptable = table; - if (unix_cp == CP_UTF8) - unix_cptable = NULL; - else if ((table = wine_cp_get_table( unix_cp ))) - unix_cptable = table; - - __wine_init_codepages( ansi_cptable, oem_cptable ); - - TRACE( "ansi=%03d oem=%03d mac=%03d unix=%03d\n", - ansi_cptable->info.codepage, oem_cptable->info.codepage, - mac_cptable->info.codepage, unix_cp ); -} - -/****************************************************************************** - * GetACP (KERNEL32.@) - * - * RETURNS - * Current ANSI code-page identifier, default if no current defined - */ -UINT WINAPI GetACP(void) -{ - if (!ansi_cptable) return 1252; - return ansi_cptable->info.codepage; -} - - -/*********************************************************************** - * GetOEMCP (KERNEL32.@) - */ -UINT WINAPI GetOEMCP(void) -{ - if (!oem_cptable) return 437; - return oem_cptable->info.codepage; -} - - -/*********************************************************************** - * IsValidCodePage (KERNEL32.@) - */ -BOOL WINAPI IsValidCodePage( UINT codepage ) -{ - switch(codepage) { - case CP_SYMBOL: - return FALSE; - case CP_UTF7: - case CP_UTF8: - return TRUE; - default: - return wine_cp_get_table( codepage ) != NULL; - } -} - - -/*********************************************************************** - * GetUserDefaultLangID (KERNEL32.@) - */ -LANGID WINAPI GetUserDefaultLangID(void) -{ - return LANGIDFROMLCID(default_lcid); -} - - -/*********************************************************************** - * GetSystemDefaultLangID (KERNEL32.@) - */ -LANGID WINAPI GetSystemDefaultLangID(void) -{ - return GetUserDefaultLangID(); -} - - -/*********************************************************************** - * GetUserDefaultLCID (KERNEL32.@) - */ -LCID WINAPI GetUserDefaultLCID(void) -{ - return default_lcid; -} - - -/*********************************************************************** - * GetSystemDefaultLCID (KERNEL32.@) - */ -LCID WINAPI GetSystemDefaultLCID(void) -{ - return GetUserDefaultLCID(); -} - - -/*********************************************************************** - * GetUserDefaultUILanguage (KERNEL32.@) - */ -LANGID WINAPI GetUserDefaultUILanguage(void) -{ - return GetUserDefaultLangID(); -} - - -/*********************************************************************** - * GetSystemDefaultUILanguage (KERNEL32.@) - */ -LANGID WINAPI GetSystemDefaultUILanguage(void) -{ - return GetSystemDefaultLangID(); -} - - -/*********************************************************************** - * IsDBCSLeadByteEx (KERNEL32.@) - * - * Determine if a character is a lead byte in a given code page. - * - * PARAMS - * codepage [I] Code page for the test. - * testchar [I] Character to test - * - * RETURNS - * TRUE, if testchar is a lead byte in codepage, - * FALSE otherwise. - */ -BOOL WINAPI IsDBCSLeadByteEx( UINT codepage, BYTE testchar ) -{ - const union cptable *table = get_codepage_table( codepage ); - return table && is_dbcs_leadbyte( table, testchar ); -} - - -/*********************************************************************** - * IsDBCSLeadByte (KERNEL32.@) - * IsDBCSLeadByte (KERNEL.207) - * - * Determine if a character is a lead byte. - * - * PARAMS - * testchar [I] Character to test - * - * RETURNS - * TRUE, if testchar is a lead byte in the Ansii code page, - * FALSE otherwise. - */ -BOOL WINAPI IsDBCSLeadByte( BYTE testchar ) -{ - if (!ansi_cptable) return FALSE; - return is_dbcs_leadbyte( ansi_cptable, testchar ); -} - - -/*********************************************************************** - * GetCPInfo (KERNEL32.@) - * - * Get information about a code page. - * - * PARAMS - * codepage [I] Code page number - * cpinfo [O] Destination for code page information - * - * RETURNS - * Success: TRUE. cpinfo is updated with the information about codepage. - * Failure: FALSE, if codepage is invalid or cpinfo is NULL. - */ -BOOL WINAPI GetCPInfo( UINT codepage, LPCPINFO cpinfo ) -{ - const union cptable *table = get_codepage_table( codepage ); - - if (!table) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return FALSE; - } - if (table->info.def_char & 0xff00) - { - cpinfo->DefaultChar[0] = table->info.def_char & 0xff00; - cpinfo->DefaultChar[1] = table->info.def_char & 0x00ff; - } - else - { - cpinfo->DefaultChar[0] = table->info.def_char & 0xff; - cpinfo->DefaultChar[1] = 0; - } - if ((cpinfo->MaxCharSize = table->info.char_size) == 2) - memcpy( cpinfo->LeadByte, table->dbcs.lead_bytes, sizeof(cpinfo->LeadByte) ); - else - cpinfo->LeadByte[0] = cpinfo->LeadByte[1] = 0; - - return TRUE; -} - -/*********************************************************************** - * GetCPInfoExA (KERNEL32.@) - * - * Get extended information about a code page. - * - * PARAMS - * codepage [I] Code page number - * dwFlags [I] Reserved, must to 0. - * cpinfo [O] Destination for code page information - * - * RETURNS - * Success: TRUE. cpinfo is updated with the information about codepage. - * Failure: FALSE, if codepage is invalid or cpinfo is NULL. - */ -BOOL WINAPI GetCPInfoExA( UINT codepage, DWORD dwFlags, LPCPINFOEXA cpinfo ) -{ - const union cptable *table = get_codepage_table( codepage ); - - if (!GetCPInfo( codepage, (LPCPINFO)cpinfo )) - return FALSE; - - cpinfo->CodePage = codepage; - cpinfo->UnicodeDefaultChar = table->info.def_unicode_char; - strcpy(cpinfo->CodePageName, table->info.name); - return TRUE; -} - -/*********************************************************************** - * GetCPInfoExW (KERNEL32.@) - * - * Unicode version of GetCPInfoExA. - */ -BOOL WINAPI GetCPInfoExW( UINT codepage, DWORD dwFlags, LPCPINFOEXW cpinfo ) -{ - const union cptable *table = get_codepage_table( codepage ); - - if (!GetCPInfo( codepage, (LPCPINFO)cpinfo )) - return FALSE; - - cpinfo->CodePage = codepage; - cpinfo->UnicodeDefaultChar = table->info.def_unicode_char; - MultiByteToWideChar( CP_ACP, 0, table->info.name, -1, cpinfo->CodePageName, - sizeof(cpinfo->CodePageName)/sizeof(WCHAR)); - return TRUE; -} - -/*********************************************************************** - * EnumSystemCodePagesA (KERNEL32.@) - */ -BOOL WINAPI EnumSystemCodePagesA( CODEPAGE_ENUMPROCA lpfnCodePageEnum, DWORD flags ) -{ - const union cptable *table; - char buffer[10]; - int index = 0; - - for (;;) - { - if (!(table = wine_cp_enum_table( index++ ))) break; - sprintf( buffer, "%d", table->info.codepage ); - if (!lpfnCodePageEnum( buffer )) break; - } - return TRUE; -} - - -/*********************************************************************** - * EnumSystemCodePagesW (KERNEL32.@) - */ -BOOL WINAPI EnumSystemCodePagesW( CODEPAGE_ENUMPROCW lpfnCodePageEnum, DWORD flags ) -{ - const union cptable *table; - WCHAR buffer[10], *p; - int page, index = 0; - - for (;;) - { - if (!(table = wine_cp_enum_table( index++ ))) break; - p = buffer + sizeof(buffer)/sizeof(WCHAR); - *--p = 0; - page = table->info.codepage; - do - { - *--p = '0' + (page % 10); - page /= 10; - } while( page ); - if (!lpfnCodePageEnum( p )) break; - } - return TRUE; -} - - -/*********************************************************************** - * MultiByteToWideChar (KERNEL32.@) - * - * Convert a multibyte character string into a Unicode string. - * - * PARAMS - * page [I] Codepage character set to convert from - * flags [I] Character mapping flags - * src [I] Source string buffer - * srclen [I] Length of src, or -1 if src is NUL terminated - * dst [O] Destination buffer - * dstlen [I] Length of dst, or 0 to compute the required length - * - * RETURNS - * Success: If dstlen > 0, the number of characters written to dst. - * If dstlen == 0, the number of characters needed to perform the - * conversion. In both cases the count includes the terminating NUL. - * Failure: 0. Use GetLastError() to determine the cause. Possible errors are - * ERROR_INSUFFICIENT_BUFFER, if not enough space is available in dst - * and dstlen != 0; ERROR_INVALID_PARAMETER, if an invalid parameter - * is passed, and ERROR_NO_UNICODE_TRANSLATION if no translation is - * possible for src. - */ -INT WINAPI MultiByteToWideChar( UINT page, DWORD flags, LPCSTR src, INT srclen, - LPWSTR dst, INT dstlen ) -{ - const union cptable *table; - int ret; - - if (!src || (!dst && dstlen)) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return 0; - } - - if (srclen < 0) srclen = strlen(src) + 1; - - if (flags & MB_USEGLYPHCHARS) FIXME("MB_USEGLYPHCHARS not supported\n"); - - switch(page) - { - case CP_UTF7: - FIXME("UTF-7 not supported\n"); - SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); - return 0; - case CP_UNIXCP: - if (unix_cptable) - { - ret = wine_cp_mbstowcs( unix_cptable, flags, src, srclen, dst, dstlen ); - break; - } - /* fall through */ - case CP_UTF8: - ret = wine_utf8_mbstowcs( flags, src, srclen, dst, dstlen ); - break; - default: - if (!(table = get_codepage_table( page ))) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return 0; - } - ret = wine_cp_mbstowcs( table, flags, src, srclen, dst, dstlen ); - break; - } - - if (ret < 0) - { - switch(ret) - { - case -1: SetLastError( ERROR_INSUFFICIENT_BUFFER ); break; - case -2: SetLastError( ERROR_NO_UNICODE_TRANSLATION ); break; - } - ret = 0; - } - return ret; -} - - -/*********************************************************************** - * WideCharToMultiByte (KERNEL32.@) - * - * Convert a Unicode character string into a multibyte string. - * - * PARAMS - * page [I] Code page character set to convert to - * flags [I] Mapping Flags (MB_ constants from "winnls.h"). - * src [I] Source string buffer - * srclen [I] Length of src, or -1 if src is NUL terminated - * dst [O] Destination buffer - * dstlen [I] Length of dst, or 0 to compute the required length - * defchar [I] Default character to use for conversion if no exact - * conversion can be made - * used [O] Set if default character was used in the conversion - * - * RETURNS - * Success: If dstlen > 0, the number of characters written to dst. - * If dstlen == 0, number of characters needed to perform the - * conversion. In both cases the count includes the terminating NUL. - * Failure: 0. Use GetLastError() to determine the cause. Possible errors are - * ERROR_INSUFFICIENT_BUFFER, if not enough space is available in dst - * and dstlen != 0, and ERROR_INVALID_PARAMETER, if an invalid - * parameter was given. - */ -INT WINAPI WideCharToMultiByte( UINT page, DWORD flags, LPCWSTR src, INT srclen, - LPSTR dst, INT dstlen, LPCSTR defchar, BOOL *used ) -{ - const union cptable *table; - int ret, used_tmp; - - if (!src || (!dst && dstlen)) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return 0; - } - - if (srclen < 0) srclen = strlenW(src) + 1; - - switch(page) - { - case CP_UTF7: - FIXME("UTF-7 not supported\n"); - SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); - return 0; - case CP_UNIXCP: - if (unix_cptable) - { - ret = wine_cp_wcstombs( unix_cptable, flags, src, srclen, dst, dstlen, - defchar, used ? &used_tmp : NULL ); - break; - } - /* fall through */ - case CP_UTF8: - ret = wine_utf8_wcstombs( src, srclen, dst, dstlen ); - break; - default: - if (!(table = get_codepage_table( page ))) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return 0; - } - ret = wine_cp_wcstombs( table, flags, src, srclen, dst, dstlen, - defchar, used ? &used_tmp : NULL ); - if (used) *used = used_tmp; - break; - } - - if (ret == -1) - { - SetLastError( ERROR_INSUFFICIENT_BUFFER ); - ret = 0; - } - return ret; -}