diff --git a/dlls/kernel/kernel.spec b/dlls/kernel/kernel.spec index d7871a2819..6c9e7b50e7 100644 --- a/dlls/kernel/kernel.spec +++ b/dlls/kernel/kernel.spec @@ -209,7 +209,7 @@ file krnl386.exe 204 stub SwapRecording 205 stub CVWBreak 206 pascal16 AllocSelectorArray(word) AllocSelectorArray16 -207 pascal16 IsDBCSLeadByte(word) IsDBCSLeadByte16 +207 pascal16 IsDBCSLeadByte(word) IsDBCSLeadByte # 208-237 are Win95 extensions; a few of those are also present in WinNT diff --git a/memory/Makefile.in b/memory/Makefile.in index a1bce2694e..0b0a10b4ad 100644 --- a/memory/Makefile.in +++ b/memory/Makefile.in @@ -7,6 +7,7 @@ MODULE = memory C_SRCS = \ atom.c \ + codepage.c \ environ.c \ global.c \ heap.c \ diff --git a/memory/codepage.c b/memory/codepage.c new file mode 100644 index 0000000000..72794854af --- /dev/null +++ b/memory/codepage.c @@ -0,0 +1,313 @@ +/* + * Code page functions + * + * Copyright 2000 Alexandre Julliard + */ + +#include +#include + +#include "winbase.h" +#include "winerror.h" +#include "winnls.h" +#include "wine/unicode.h" +#include "debugtools.h" + +DEFAULT_DEBUG_CHANNEL(string); + +/* current code pages */ +static unsigned int ansi_cp = 1252; /* Windows 3.1 ISO Latin */ +static unsigned int oem_cp = 437; /* MS-DOS United States */ +static unsigned int mac_cp = 10000; /* Mac Roman */ + +static const union cptable *ansi_cptable; +static const union cptable *oem_cptable; +static const union cptable *mac_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) /* initialize them */ + { + /* FIXME: should load from the registry */ + ansi_cptable = cp_get_table( ansi_cp ); + oem_cptable = cp_get_table( oem_cp ); + mac_cptable = cp_get_table( mac_cp ); + assert( ansi_cptable ); + assert( oem_cptable ); + assert( mac_cptable ); + } + + switch(codepage) + { + case CP_SYMBOL: + case CP_ACP: return ansi_cptable; + case CP_OEMCP: return oem_cptable; + case CP_MACCP: return mac_cptable; + case CP_THREAD_ACP: return ansi_cptable; /* FIXME */ + case CP_UTF7: + case CP_UTF8: + break; + default: + if (codepage == ansi_cp) return ansi_cptable; + if (codepage == oem_cp) return oem_cptable; + if (codepage == mac_cp) return mac_cptable; + ret = cp_get_table( codepage ); + break; + } + return ret; +} + +/****************************************************************************** + * GetACP (KERNEL32) + * + * RETURNS + * Current ANSI code-page identifier, default if no current defined + */ +UINT WINAPI GetACP(void) +{ + return ansi_cp; +} + + +/*********************************************************************** + * GetOEMCP (KERNEL32) + */ +UINT WINAPI GetOEMCP(void) +{ + return oem_cp; +} + + +/*********************************************************************** + * IsValidCodePage (KERNEL32) + */ +BOOL WINAPI IsValidCodePage( UINT codepage ) +{ + return cp_get_table( codepage ) != NULL; +} + + +/*********************************************************************** + * IsDBCSLeadByteEx (KERNEL32) + */ +BOOL WINAPI IsDBCSLeadByteEx( UINT codepage, BYTE testchar ) +{ + const union cptable *table = get_codepage_table( codepage ); + return table && is_dbcs_leadbyte( table, testchar ); +} + + +/*********************************************************************** + * IsDBCSLeadByte (KERNEL32) + */ +BOOL WINAPI IsDBCSLeadByte( BYTE testchar ) +{ + return is_dbcs_leadbyte( ansi_cptable, testchar ); +} + + +/*********************************************************************** + * GetCPInfo (KERNEL32) + */ +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; +} + + +/*********************************************************************** + * EnumSystemCodePagesA (KERNEL32) + */ +BOOL WINAPI EnumSystemCodePagesA( CODEPAGE_ENUMPROCA lpfnCodePageEnum, DWORD flags ) +{ + const union cptable *table; + char buffer[10]; + int index = 0; + + for (;;) + { + if (!(table = 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 = 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) + * + * PARAMS + * page [in] Codepage character set to convert from + * flags [in] Character mapping flags + * src [in] Source string buffer + * srclen [in] Length of source string buffer + * dst [in] Destination buffer + * dstlen [in] Length of destination buffer + * + * NOTES + * The returned length includes the null terminator character. + * + * RETURNS + * Success: If dstlen > 0, number of characters written to destination + * buffer. If dstlen == 0, number of characters needed to do + * conversion. + * Failure: 0. Occurs if not enough space is available. + * + * ERRORS + * ERROR_INSUFFICIENT_BUFFER + * ERROR_INVALID_PARAMETER + * ERROR_NO_UNICODE_TRANSLATION + * + */ +INT WINAPI MultiByteToWideChar( UINT page, DWORD flags, LPCSTR src, INT srclen, + LPWSTR dst, INT dstlen ) +{ + const union cptable *table; + int ret; + + if (srclen == -1) srclen = strlen(src) + 1; + + if (page >= CP_UTF7) + { + FIXME("UTF not supported\n"); + SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); + return 0; + } + + if (!(table = get_codepage_table( page ))) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return 0; + } + + if (flags & MB_COMPOSITE) FIXME("MB_COMPOSITE not supported\n"); + if (flags & MB_USEGLYPHCHARS) FIXME("MB_USEGLYPHCHARS not supported\n"); + + ret = cp_mbstowcs( table, flags, src, srclen, dst, dstlen ); + + 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) + * + * PARAMS + * page [in] Codepage character set to convert to + * flags [in] Character mapping flags + * src [in] Source string buffer + * srclen [in] Length of source string buffer + * dst [in] Destination buffer + * dstlen [in] Length of destination buffer + * defchar [in] Default character to use for conversion if no exact + * conversion can be made + * used [out] Set if default character was used in the conversion + * + * NOTES + * The returned length includes the null terminator character. + * + * RETURNS + * Success: If dstlen > 0, number of characters written to destination + * buffer. If dstlen == 0, number of characters needed to do + * conversion. + * Failure: 0. Occurs if not enough space is available. + * + * ERRORS + * ERROR_INSUFFICIENT_BUFFER + * ERROR_INVALID_PARAMETER + */ +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 (srclen == -1) srclen = strlenW(src) + 1; + + if (page >= CP_UTF7) + { + FIXME("UTF not supported\n"); + SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); + return 0; + } + + if (!(table = get_codepage_table( page ))) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return 0; + } + +/* if (flags & WC_COMPOSITECHECK) FIXME( "WC_COMPOSITECHECK (%lx) not supported\n", flags );*/ + + ret = cp_wcstombs( table, flags, src, srclen, dst, dstlen, defchar, used ? &used_tmp : NULL ); + if (used) *used = used_tmp; + + if (ret == -1) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + ret = 0; + } + return ret; +} diff --git a/memory/string.c b/memory/string.c index 5dce9c116e..f61932ec6f 100644 --- a/memory/string.c +++ b/memory/string.c @@ -394,11 +394,7 @@ INT WINAPI lstrlenW( LPCWSTR str ) */ LPWSTR WINAPI lstrcpyAtoW( LPWSTR dst, LPCSTR src ) { - register LPWSTR p = dst; - - TRACE("(%p, %s)\n", dst, debugstr_a(src)); - - while ((*p++ = (WCHAR)(unsigned char)*src++)); + MultiByteToWideChar( CP_ACP, 0, src, -1, dst, 0x7fffffff ); return dst; } @@ -408,11 +404,7 @@ LPWSTR WINAPI lstrcpyAtoW( LPWSTR dst, LPCSTR src ) */ LPSTR WINAPI lstrcpyWtoA( LPSTR dst, LPCWSTR src ) { - register LPSTR p = dst; - - TRACE("(%p, %s)\n", dst, debugstr_w(src)); - - while ((*p++ = (CHAR)*src++)); + WideCharToMultiByte( CP_ACP, 0, src, -1, dst, 0x7fffffff, NULL, NULL ); return dst; } @@ -424,12 +416,7 @@ LPSTR WINAPI lstrcpyWtoA( LPSTR dst, LPCWSTR src ) */ LPWSTR WINAPI lstrcpynAtoW( LPWSTR dst, LPCSTR src, INT n ) { - LPWSTR p = dst; - - TRACE("(%p, %s, %i)\n", dst, debugstr_an(src,n), n); - - while ((n-- > 1) && *src) *p++ = (WCHAR)(unsigned char)*src++; - if (n >= 0) *p = 0; + if (n > 0 && !MultiByteToWideChar( CP_ACP, 0, src, -1, dst, n )) dst[n-1] = 0; return dst; } @@ -445,14 +432,7 @@ LPWSTR WINAPI lstrcpynAtoW( LPWSTR dst, LPCSTR src, INT n ) */ LPSTR WINAPI lstrcpynWtoA( LPSTR dst, LPCWSTR src, INT n ) { - if (--n >= 0) - { - TRACE("(%p, %s, %i)\n", dst, debugstr_wn(src,n), n); - n = CRTDLL_wcstombs( dst, src, n ); - if(n<0) - n=0; - dst[n] = 0; - } + if (n > 0 && !WideCharToMultiByte( CP_ACP, 0, src, -1, dst, n, NULL, NULL )) dst[n-1] = 0; return dst; } diff --git a/win32/Makefile.in b/win32/Makefile.in index ca3feca2a9..51f02d36f6 100644 --- a/win32/Makefile.in +++ b/win32/Makefile.in @@ -6,7 +6,6 @@ VPATH = @srcdir@ MODULE = win32 C_SRCS = \ - code_page.c \ console.c \ device.c \ error.c \ diff --git a/win32/code_page.c b/win32/code_page.c deleted file mode 100644 index ebf36f71b0..0000000000 --- a/win32/code_page.c +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Win32 kernel functions - * - * Copyright 1995 Martin von Loewis and Cameron Heide - */ - -#include -#include "winerror.h" -#include "winnls.h" -#include "heap.h" -#include "debugtools.h" - -DEFAULT_DEBUG_CHANNEL(win32) - - -/****************************************************************************** - * GetACP [KERNEL32.276] Gets current ANSI code-page identifier. - * - * RETURNS - * Current ANSI code-page identifier, default if no current defined - */ -UINT WINAPI GetACP(void) -{ - /* This introduces too many messages */ -/* FIXME(win32, "(void): stub\n"); */ - return 1252; /* Windows 3.1 ISO Latin */ -} - - -/*********************************************************************** - * GetCPInfo (KERNEL32.154) - */ -BOOL WINAPI GetCPInfo( UINT codepage, LPCPINFO cpinfo ) -{ - cpinfo->DefaultChar[0] = '?'; - switch (codepage) - { - case 932 : /* Shift JIS (japan) */ - cpinfo->MaxCharSize = 2; - cpinfo->LeadByte[0]= 0x81; cpinfo->LeadByte[1] = 0x9F; - cpinfo->LeadByte[2]= 0xE0; cpinfo->LeadByte[3] = 0xFC; - cpinfo->LeadByte[4]= 0x00; cpinfo->LeadByte[5] = 0x00; - break; - case 936 : /* GB2312 (Chinese) */ - case 949 : /* KSC5601-1987 (Korean) */ - case 950 : /* BIG5 (Chinese) */ - cpinfo->MaxCharSize = 2; - cpinfo->LeadByte[0]= 0x81; cpinfo->LeadByte[1] = 0xFE; - cpinfo->LeadByte[2]= 0x00; cpinfo->LeadByte[3] = 0x00; - break; - case 1361 : /* Johab (Korean) */ - cpinfo->MaxCharSize = 2; - cpinfo->LeadByte[0]= 0x84; cpinfo->LeadByte[1] = 0xD3; - cpinfo->LeadByte[2]= 0xD8; cpinfo->LeadByte[3] = 0xDE; - cpinfo->LeadByte[4]= 0xE0; cpinfo->LeadByte[5] = 0xF9; - cpinfo->LeadByte[6]= 0x00; cpinfo->LeadByte[7] = 0x00; - break; - default : - cpinfo->MaxCharSize = 1; - cpinfo->LeadByte[0]= 0x00; cpinfo->LeadByte[1] = 0x00; - break; - } - return 1; -} - -/*********************************************************************** - * GetOEMCP (KERNEL32.248) - */ -UINT WINAPI GetOEMCP(void) -{ - return 437; /* MS-DOS United States */ -} - -/*********************************************************************** - * IsValidCodePage (KERNEL32.360) - */ -BOOL WINAPI IsValidCodePage(UINT CodePage) -{ - switch ( CodePage ) - { - case 1252 : - case 437 : - return TRUE; - default : - return FALSE; - } -} - - -/*********************************************************************** - * MultiByteToWideChar (KERNEL32.534) - * - * PARAMS - * page [in] Codepage character set to convert from - * flags [in] Character mapping flags - * src [in] Source string buffer - * srclen [in] Length of source string buffer - * dst [in] Destination buffer - * dstlen [in] Length of destination buffer - * - * NOTES - * The returned length includes the null terminator character. - * - * RETURNS - * Success: If dstlen > 0, number of characters written to destination - * buffer. If dstlen == 0, number of characters needed to do - * conversion. - * Failure: 0. Occurs if not enough space is available. - * - * ERRORS - * ERROR_INSUFFICIENT_BUFFER - * ERROR_INVALID_FLAGS (not yet implemented) - * ERROR_INVALID_PARAMETER (not yet implemented) - * - * BUGS - * Does not properly handle codepage conversions. - * Does not properly handle flags. - * - */ -INT WINAPI MultiByteToWideChar(UINT page, DWORD flags, - LPCSTR src, INT srclen, - LPWSTR dst, INT dstlen) -{ - int ret; - - if (srclen == -1) - srclen = lstrlenA(src)+1; - if (!dstlen || !dst) - return srclen; - - ret = srclen; - while (srclen && dstlen) { - *dst = (WCHAR)(unsigned char)*src; - dst++; src++; - dstlen--; srclen--; - } - if (!dstlen && srclen) { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - return 0; - } - return ret; -} - -/*********************************************************************** - * WideCharToMultiByte (KERNEL32.727) - * - * PARAMS - * page [in] Codepage character set to convert to - * flags [in] Character mapping flags - * src [in] Source string buffer - * srclen [in] Length of source string buffer - * dst [in] Destination buffer - * dstlen [in] Length of destination buffer - * defchar [in] Default character to use for conversion if no exact - * conversion can be made - * used [out] Set if default character was used in the conversion - * - * NOTES - * The returned length includes the null terminator character. - * - * RETURNS - * Success: If dstlen > 0, number of characters written to destination - * buffer. If dstlen == 0, number of characters needed to do - * conversion. - * Failure: 0. Occurs if not enough space is available. - * - * ERRORS - * ERROR_INSUFFICIENT_BUFFER - * ERROR_INVALID_FLAGS (not yet implemented) - * - * BUGS - * Does not properly handle codepage conversions. - * Does not properly handle flags. - * - */ -INT WINAPI WideCharToMultiByte(UINT page, DWORD flags, LPCWSTR src, - INT srclen,LPSTR dst, INT dstlen, - LPCSTR defchar, BOOL *used) -{ - int count = 0; - int eos = 0; - int care_for_eos=0; - int dont_copy= (dstlen==0); - - if ((!src) || ((!dst) && (!dont_copy)) ) - { SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - - if (page!=GetACP() && page!=CP_OEMCP && page!=CP_ACP) - FIXME("Conversion in CP %d not supported\n",page); -#if 0 - if (flags) - FIXME("flags %lx not supported\n",flags); -#endif - if(used) - *used=0; - if (srclen == -1) - { - srclen = lstrlenW(src)+1; - care_for_eos=1; - } - while(srclen && (dont_copy || dstlen)) - { - if(!dont_copy){ - if(*src<256) - *dst = *src; - else - { - /* ??? The WC_DEFAULTCHAR flag only gets used in - * combination with the WC_COMPOSITECHECK flag or at - * least this is what it seems from using the function - * on NT4.0 in combination with reading the documentation. - */ - *dst = defchar ? *defchar : '?'; - if(used)*used=1; - } - dstlen--; - dst++; - } - count++; - srclen--; - if((!*src) && care_for_eos) { - eos = 1; - break; - } - src++; - } - if (dont_copy) - return count; - - if (!eos && srclen > 0) { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - return 0; - } - return count; -} - - -/*********************************************************************** - * IsDBCSLeadByteEx (KERNEL32.359) - */ -BOOL WINAPI IsDBCSLeadByteEx( UINT codepage, BYTE testchar ) -{ - CPINFO cpinfo; - int i; - - GetCPInfo(codepage, &cpinfo); - for (i = 0 ; i < sizeof(cpinfo.LeadByte)/sizeof(cpinfo.LeadByte[0]); i+=2) - { - if (cpinfo.LeadByte[i] == 0) - return FALSE; - if (cpinfo.LeadByte[i] <= testchar && testchar <= cpinfo.LeadByte[i+1]) - return TRUE; - } - return FALSE; -} - - -/*********************************************************************** - * IsDBCSLeadByte16 (KERNEL.207) - */ -BOOL16 WINAPI IsDBCSLeadByte16( BYTE testchar ) -{ - return IsDBCSLeadByteEx(GetACP(), testchar); -} - - -/*********************************************************************** - * IsDBCSLeadByte (KERNEL32.358) - */ -BOOL WINAPI IsDBCSLeadByte( BYTE testchar ) -{ - return IsDBCSLeadByteEx(GetACP(), testchar); -} - - -/*********************************************************************** - * EnumSystemCodePagesA (KERNEL32.92) - */ -BOOL WINAPI EnumSystemCodePagesA(CODEPAGE_ENUMPROCA lpfnCodePageEnum,DWORD flags) -{ - TRACE("(%p,%08lx)\n",lpfnCodePageEnum,flags); - lpfnCodePageEnum("437"); - return TRUE; -} - -/*********************************************************************** - * EnumSystemCodePagesW (KERNEL32.93) - */ -BOOL WINAPI EnumSystemCodePagesW( CODEPAGE_ENUMPROCW lpfnCodePageEnum, - DWORD flags) -{ - WCHAR *cp; - TRACE("(%p,%08lx)\n",lpfnCodePageEnum,flags ); - - cp = HEAP_strdupAtoW( GetProcessHeap(), 0, "437" ); - lpfnCodePageEnum(cp); - HeapFree( GetProcessHeap(), 0, cp ); - return TRUE; -}