From: Jacek Caban <jacek(a)codeweavers.com>
Based on ntdll.
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)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 */
--
2.23.0