From: Jacek Caban jacek@codeweavers.com
Based on ntdll.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Huw Davies huw@codeweavers.com --- dlls/gdi32/font.c | 99 +++++++++++++++++++++++++++++++++++-- dlls/gdi32/freetype.c | 10 ++-- dlls/gdi32/win32u_private.h | 5 ++ 3 files changed, 106 insertions(+), 8 deletions(-)
diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c index 0b32a94f7fe..c6bc3a716be 100644 --- a/dlls/gdi32/font.c +++ b/dlls/gdi32/font.c @@ -3200,6 +3200,7 @@ static UINT get_glyph_index_symbol( struct gdi_font *font, UINT glyph ) CPTABLEINFO *get_cptable( WORD cp ) { static CPTABLEINFO tables[100]; + CPTABLEINFO *info; unsigned int i; USHORT *ptr; SIZE_T size; @@ -3207,9 +3208,101 @@ CPTABLEINFO *get_cptable( WORD cp ) for (i = 0; i < ARRAY_SIZE(tables) && tables[i].CodePage; i++) if (tables[i].CodePage == cp) return &tables[i]; if (NtGetNlsSectionPtr( 11, cp, NULL, (void **)&ptr, &size )) return NULL; - if (i == ARRAY_SIZE(tables)) ERR( "too many code pages\n" ); - RtlInitCodePageTable( ptr, &tables[i] ); - return &tables[i]; + if (i == ARRAY_SIZE(tables)) + { + ERR( "too many code pages\n" ); + return NULL; + } + + info = &tables[i]; + info->CodePage = ptr[1]; + info->MaximumCharacterSize = ptr[2]; + info->DefaultChar = ptr[3]; + info->UniDefaultChar = ptr[4]; + info->TransDefaultChar = ptr[5]; + info->TransUniDefaultChar = ptr[6]; + memcpy( info->LeadByte, ptr + 7, sizeof(info->LeadByte) ); + ptr += ptr[0]; + + info->WideCharTable = ptr + ptr[0] + 1; + info->MultiByteTable = ++ptr; + ptr += 256; + if (*ptr++) ptr += 256; /* glyph table */ + info->DBCSRanges = ptr; + if (*ptr) /* dbcs ranges */ + { + info->DBCSCodePage = 1; + info->DBCSOffsets = ptr + 1; + } + else + { + info->DBCSCodePage = 0; + info->DBCSOffsets = NULL; + } + + return info; +} + +DWORD win32u_wctomb( CPTABLEINFO *info, char *dst, DWORD dstlen, const WCHAR *src, DWORD srclen ) +{ + DWORD i, ret; + + if (!info && !(info = get_cptable( get_acp() ))) return 0; + + srclen /= sizeof(WCHAR); + if (info->DBCSCodePage) + { + WCHAR *uni2cp = info->WideCharTable; + + for (i = dstlen; srclen && i; i--, srclen--, src++) + { + if (uni2cp[*src] & 0xff00) + { + if (i == 1) break; /* do not output a partial char */ + i--; + *dst++ = uni2cp[*src] >> 8; + } + *dst++ = (char)uni2cp[*src]; + } + ret = dstlen - i; + } + else + { + char *uni2cp = info->WideCharTable; + ret = min( srclen, dstlen ); + for (i = 0; i < ret; i++) dst[i] = uni2cp[src[i]]; + } + return ret; +} + +DWORD win32u_mbtowc( CPTABLEINFO *info, WCHAR *dst, DWORD dstlen, const char *src, DWORD srclen ) +{ + DWORD i, ret; + + if (!info && !(info = get_cptable( get_acp() ))) return 0; + + dstlen /= sizeof(WCHAR); + if (info->DBCSOffsets) + { + for (i = dstlen; srclen && i; i--, srclen--, src++, dst++) + { + USHORT off = info->DBCSOffsets[(unsigned char)*src]; + if (off && srclen > 1) + { + src++; + srclen--; + *dst = info->DBCSOffsets[off + (unsigned char)*src]; + } + else *dst = info->MultiByteTable[(unsigned char)*src]; + } + ret = dstlen - i; + } + else + { + ret = min( srclen, dstlen ); + for (i = 0; i < ret; i++) dst[i] = info->MultiByteTable[(unsigned char)src[i]]; + } + return ret * sizeof(WCHAR); }
static BOOL wc_to_index( UINT cp, WCHAR wc, unsigned char *dst, BOOL allow_default ) diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c index 44d5dc26cff..04b24b7f570 100644 --- a/dlls/gdi32/freetype.c +++ b/dlls/gdi32/freetype.c @@ -602,7 +602,7 @@ static WCHAR *towstr(const char *str) { DWORD len = strlen(str) + 1; WCHAR *wstr = malloc( len * sizeof(WCHAR) ); - RtlMultiByteToUnicodeN( wstr, len * sizeof(WCHAR), &len, str, len ); + win32u_mbtowc( NULL, wstr, len * sizeof(WCHAR), str, len ); return wstr; }
@@ -805,8 +805,8 @@ static WCHAR *copy_name_table_string( const FT_SfntName *name ) case TT_PLATFORM_MACINTOSH: if (!(cp = get_mac_code_page( name ))) return NULL; ret = malloc( (name->string_len + 1) * sizeof(WCHAR) ); - RtlCustomCPToUnicodeN( cp, ret, name->string_len * sizeof(WCHAR), &i, - (char *)name->string, name->string_len ); + i = win32u_mbtowc( cp, ret, name->string_len * sizeof(WCHAR), + (char *)name->string, name->string_len ); ret[i / sizeof(WCHAR)] = 0; return ret; } @@ -1165,7 +1165,7 @@ static WCHAR *decode_opentype_name( struct opentype_name *name ) { CPTABLEINFO *cptable = get_cptable( name->codepage ); if (!cptable) return NULL; - RtlCustomCPToUnicodeN( cptable, buffer, sizeof(buffer), &len, name->bytes, name->length ); + len = win32u_mbtowc( cptable, buffer, sizeof(buffer), name->bytes, name->length ); len /= sizeof(WCHAR); }
@@ -2577,7 +2577,7 @@ static BOOL CDECL freetype_get_glyph_index( struct gdi_font *font, UINT *glyph, DWORD len; char ch;
- RtlUnicodeToMultiByteN( &ch, 1, &len, &wc, sizeof(wc) ); + len = win32u_wctomb( NULL, &ch, 1, &wc, sizeof(wc) ); if (len) *glyph = get_glyph_index_symbol( font, (unsigned char)ch ); } return TRUE; diff --git a/dlls/gdi32/win32u_private.h b/dlls/gdi32/win32u_private.h index d986bf339c3..f867c556bff 100644 --- a/dlls/gdi32/win32u_private.h +++ b/dlls/gdi32/win32u_private.h @@ -395,4 +395,9 @@ static inline LONG win32u_wcstol( LPCWSTR s, LPWSTR *end, INT base ) #define wcsrchr(s,c) win32u_wcsrchr(s,c) #define wcstol(s,e,b) win32u_wcstol(s,e,b)
+DWORD win32u_mbtowc( CPTABLEINFO *info, WCHAR *dst, DWORD dstlen, const char *src, + DWORD srclen ) DECLSPEC_HIDDEN; +DWORD win32u_wctomb( CPTABLEINFO *info, char *dst, DWORD dstlen, const WCHAR *src, + DWORD srclen ) DECLSPEC_HIDDEN; + #endif /* __WINE_WIN32U_PRIVATE */