* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: lib/gdi32/object/font.c
- * PURPOSE:
+ * PURPOSE:
* PROGRAMMER:
*
*/
#define NDEBUG
#include <debug.h>
+/*
+ * For TranslateCharsetInfo
+ */
+#define MAXTCIINDEX 32
+static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
+ /* ANSI */
+ { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
+ { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
+ { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
+ { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
+ { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
+ { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
+ { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
+ { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
+ { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
+ /* reserved by ANSI */
+ { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
+ { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
+ { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
+ { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
+ { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
+ { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
+ { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
+ /* ANSI and OEM */
+ { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
+ { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
+ { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
+ { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
+ { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
+ { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
+ /* reserved for alternate ANSI and OEM */
+ { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
+ { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
+ { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
+ { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
+ { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
+ { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
+ { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
+ { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
+ /* reserved for system */
+ { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
+ { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
+};
+
#define INITIAL_FAMILY_COUNT 64
/***********************************************************************
ptmA->tmCharSet = ptmW->tmCharSet;
}
+/***********************************************************************
+ * FONT_mbtowc
+ *
+ * Returns a Unicode translation of str using the charset of the
+ * currently selected font in hdc. If count is -1 then str is assumed
+ * to be '\0' terminated, otherwise it contains the number of bytes to
+ * convert. If plenW is non-NULL, on return it will point to the
+ * number of WCHARs that have been written. If pCP is non-NULL, on
+ * return it will point to the codepage used in the conversion. The
+ * caller should free the returned LPWSTR from the process heap
+ * itself.
+ */
+static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
+{
+ UINT cp = GdiGetCodePage( hdc );
+ INT lenW;
+ LPWSTR strW;
+
+ if(count == -1) count = strlen(str);
+ lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
+ strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
+ MultiByteToWideChar(cp, 0, str, count, strW, lenW);
+ DPRINT("mapped %s -> %S\n", str, strW);
+ if(plenW) *plenW = lenW;
+ if(pCP) *pCP = cp;
+ return strW;
+}
+
+
static BOOL FASTCALL
MetricsCharConvert(WCHAR w, UCHAR *b)
{
if (Unicode)
{
Ret = ((FONTENUMPROCW) EnumProc)(
- &Info[i].EnumLogFontEx,
- &Info[i].NewTextMetricEx,
+ (VOID*)&Info[i].EnumLogFontEx,
+ (VOID*)&Info[i].NewTextMetricEx,
Info[i].FontType, lParam);
}
else
- {
+ { // Could use EnumLogFontExW2A here?
LogFontW2A(&EnumLogFontExA.elfLogFont, &Info[i].EnumLogFontEx.elfLogFont);
WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfFullName, -1,
(LPSTR)EnumLogFontExA.elfFullName, LF_FULLFACESIZE, NULL, NULL);
NewTextMetricExW2A(&NewTextMetricExA,
&Info[i].NewTextMetricEx);
Ret = ((FONTENUMPROCA) EnumProc)(
- &EnumLogFontExA,
- &NewTextMetricExA,
+ (VOID*)&EnumLogFontExA,
+ (VOID*)&NewTextMetricExA,
Info[i].FontType, lParam);
}
}
/*
* @implemented
*/
-int STDCALL
+int WINAPI
EnumFontFamiliesExW(HDC hdc, LPLOGFONTW lpLogfont, FONTENUMPROCW lpEnumFontFamExProc,
LPARAM lParam, DWORD dwFlags)
{
/*
* @implemented
*/
-int STDCALL
+int WINAPI
EnumFontFamiliesW(HDC hdc, LPCWSTR lpszFamily, FONTENUMPROCW lpEnumFontFamProc,
LPARAM lParam)
{
LogFont.lfCharSet = DEFAULT_CHARSET;
if (NULL != lpszFamily)
{
+ if (!*lpszFamily) return 1;
lstrcpynW(LogFont.lfFaceName, lpszFamily, LF_FACESIZE);
}
/*
* @implemented
*/
-int STDCALL
+int WINAPI
EnumFontFamiliesExA (HDC hdc, LPLOGFONTA lpLogfont, FONTENUMPROCA lpEnumFontFamExProc,
LPARAM lParam, DWORD dwFlags)
{
- LOGFONTW LogFontW;
+ LOGFONTW LogFontW, *pLogFontW;
- LogFontA2W(&LogFontW, lpLogfont);
+ if (lpLogfont)
+ {
+ LogFontA2W(&LogFontW,lpLogfont);
+ pLogFontW = &LogFontW;
+ }
+ else pLogFontW = NULL;
/* no need to convert LogFontW back to lpLogFont b/c it's an [in] parameter only */
- return IntEnumFontFamilies(hdc, &LogFontW, lpEnumFontFamExProc, lParam, FALSE);
+ return IntEnumFontFamilies(hdc, pLogFontW, lpEnumFontFamExProc, lParam, FALSE);
}
/*
* @implemented
*/
-int STDCALL
+int WINAPI
EnumFontFamiliesA(HDC hdc, LPCSTR lpszFamily, FONTENUMPROCA lpEnumFontFamProc,
LPARAM lParam)
{
LogFont.lfCharSet = DEFAULT_CHARSET;
if (NULL != lpszFamily)
{
+ if (!*lpszFamily) return 1;
MultiByteToWideChar(CP_THREAD_ACP, 0, lpszFamily, -1, LogFont.lfFaceName, LF_FACESIZE);
}
return IntEnumFontFamilies(hdc, &LogFont, lpEnumFontFamProc, lParam, FALSE);
}
-
-/*
- * @implemented
- */
-BOOL
-STDCALL
-GetCharWidthA (
- HDC hdc,
- UINT iFirstChar,
- UINT iLastChar,
- LPINT lpBuffer
- )
-{
- return GetCharWidth32A ( hdc, iFirstChar, iLastChar, lpBuffer );
-}
-
-
-/*
- * @implemented
- */
-BOOL
-STDCALL
-GetCharWidth32A(
- HDC hdc,
- UINT iFirstChar,
- UINT iLastChar,
- LPINT lpBuffer
- )
-{
- /* FIXME should be NtGdiGetCharWidthW */
- return NtGdiGetCharWidth32(hdc, iFirstChar, iLastChar, lpBuffer);
-}
-
-
-/*
- * @implemented
- */
-BOOL
-STDCALL
-GetCharWidthW (
- HDC hdc,
- UINT iFirstChar,
- UINT iLastChar,
- LPINT lpBuffer
- )
-{
- /* FIXME should be NtGdiGetCharWidthW */
- return NtGdiGetCharWidth32 ( hdc, iFirstChar, iLastChar, lpBuffer );
-}
-
-
/*
* @implemented
*/
DWORD
-STDCALL
+WINAPI
GetCharacterPlacementW(
HDC hdc,
LPCWSTR lpString,
DWORD ret=0;
SIZE size;
UINT i, nSet;
+ DPRINT("GetCharacterPlacementW\n");
if(dwFlags&(~GCP_REORDER)) DPRINT("flags 0x%08lx ignored\n", dwFlags);
if(lpResults->lpClass) DPRINT("classes not implemented\n");
int c;
for (i = 0; i < nSet; i++)
{
- if (NtGdiGetCharWidth32(hdc, lpString[i], lpString[i], &c))
+ if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
lpResults->lpDx[i]= c;
}
}
if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
{
int pos = 0;
-
+
lpResults->lpCaretPos[0] = 0;
for (i = 1; i < nSet; i++)
if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
lpResults->lpCaretPos[i] = (pos += size.cx);
}
-
+
/*if(lpResults->lpGlyphs)
- GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);*/
+ NtGdiGetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);*/
if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
ret = MAKELONG(size.cx, size.cy);
return ret;
}
+/*
+ * @implemented
+ *
+ */
+BOOL
+WINAPI
+GetCharABCWidthsFloatW(HDC hdc,
+ UINT FirstChar,
+ UINT LastChar,
+ LPABCFLOAT abcF)
+{
+ DPRINT("GetCharABCWidthsFloatW\n");
+ if ((!abcF) || (FirstChar > LastChar))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ return NtGdiGetCharABCWidthsW( hdc,
+ FirstChar,
+ (ULONG)(LastChar - FirstChar + 1),
+ (PWCHAR) NULL,
+ 0,
+ (PVOID)abcF);
+}
/*
- * @unimplemented
+ * @implemented
+ *
+ */
+BOOL
+WINAPI
+GetCharWidthFloatW(HDC hdc,
+ UINT iFirstChar,
+ UINT iLastChar,
+ PFLOAT pxBuffer)
+{
+ DPRINT("GetCharWidthsFloatW\n");
+ if ((!pxBuffer) || (iFirstChar > iLastChar))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ return NtGdiGetCharWidthW( hdc,
+ iFirstChar,
+ (ULONG)(iLastChar - iFirstChar + 1),
+ (PWCHAR) NULL,
+ 0,
+ (PVOID) pxBuffer);
+}
+
+/*
+ * @implemented
+ *
+ */
+BOOL
+WINAPI
+GetCharWidthW(HDC hdc,
+ UINT iFirstChar,
+ UINT iLastChar,
+ LPINT lpBuffer)
+{
+ DPRINT("GetCharWidthsW\n");
+ if ((!lpBuffer) || (iFirstChar > iLastChar))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ return NtGdiGetCharWidthW( hdc,
+ iFirstChar,
+ (ULONG)(iLastChar - iFirstChar + 1),
+ (PWCHAR) NULL,
+ GCW_NOFLOAT,
+ (PVOID) lpBuffer);
+}
+
+/*
+ * @implemented
+ *
+ */
+BOOL
+WINAPI
+GetCharWidth32W(HDC hdc,
+ UINT iFirstChar,
+ UINT iLastChar,
+ LPINT lpBuffer)
+{
+ DPRINT("GetCharWidths32W\n");
+ if ((!lpBuffer) || (iFirstChar > iLastChar))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ return NtGdiGetCharWidthW( hdc,
+ iFirstChar,
+ (ULONG)(iLastChar - iFirstChar + 1),
+ (PWCHAR) NULL,
+ GCW_NOFLOAT|GCW_WIN32,
+ (PVOID) lpBuffer);
+}
+
+
+/*
+ * @implemented
+ *
+ */
+BOOL
+WINAPI
+GetCharABCWidthsW(HDC hdc,
+ UINT FirstChar,
+ UINT LastChar,
+ LPABC lpabc)
+{
+ DPRINT("GetCharABCWidthsW\n");
+ if ((!lpabc) || (FirstChar > LastChar))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ return NtGdiGetCharABCWidthsW( hdc,
+ FirstChar,
+ (ULONG)(LastChar - FirstChar + 1),
+ (PWCHAR) NULL,
+ GCABCW_NOFLOAT,
+ (PVOID)lpabc);
+}
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+GetCharWidthA(
+ HDC hdc,
+ UINT iFirstChar,
+ UINT iLastChar,
+ LPINT lpBuffer
+ )
+{
+ INT i, wlen, count = (INT)(iLastChar - iFirstChar + 1);
+ LPSTR str;
+ LPWSTR wstr;
+ BOOL ret = TRUE;
+
+ DPRINT("GetCharWidthsA\n");
+ if(count <= 0) return FALSE;
+
+ str = HeapAlloc(GetProcessHeap(), 0, count+1);
+ if (!str)
+ return FALSE;
+
+ for(i = 0; i < count; i++)
+ str[i] = (BYTE)(iFirstChar + i);
+ str[i] = '\0';
+
+ wstr = FONT_mbtowc(hdc, str, count+1, &wlen, NULL);
+ if (!wstr)
+ {
+ HeapFree(GetProcessHeap(), 0, str);
+ return FALSE;
+ }
+
+ ret = NtGdiGetCharWidthW( hdc,
+ wstr[0],
+ (ULONG) count,
+ (PWCHAR) wstr,
+ GCW_NOFLOAT,
+ (PVOID) lpBuffer);
+
+ HeapFree(GetProcessHeap(), 0, str);
+ HeapFree(GetProcessHeap(), 0, wstr);
+
+ return ret;
+}
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+GetCharWidth32A(
+ HDC hdc,
+ UINT iFirstChar,
+ UINT iLastChar,
+ LPINT lpBuffer
+ )
+{
+ INT i, wlen, count = (INT)(iLastChar - iFirstChar + 1);
+ LPSTR str;
+ LPWSTR wstr;
+ BOOL ret = TRUE;
+
+ DPRINT("GetCharWidths32A\n");
+ if(count <= 0) return FALSE;
+
+ str = HeapAlloc(GetProcessHeap(), 0, count+1);
+ if (!str)
+ return FALSE;
+ for(i = 0; i < count; i++)
+ str[i] = (BYTE)(iFirstChar + i);
+ str[i] = '\0';
+
+ wstr = FONT_mbtowc(hdc, str, count+1, &wlen, NULL);
+ if (!wstr)
+ {
+ HeapFree(GetProcessHeap(), 0, str);
+ return FALSE;
+ }
+
+ ret = NtGdiGetCharWidthW( hdc,
+ wstr[0],
+ (ULONG) count,
+ (PWCHAR) wstr,
+ GCW_NOFLOAT|GCW_WIN32,
+ (PVOID) lpBuffer);
+
+ HeapFree(GetProcessHeap(), 0, str);
+ HeapFree(GetProcessHeap(), 0, wstr);
+
+ return ret;
+}
+
+/*
+ * @implemented
*/
BOOL
APIENTRY
PFLOAT pxBuffer
)
{
- /* FIXME what to do with iFirstChar and iLastChar ??? */
- return NtGdiGetCharWidthFloat ( hdc, iFirstChar, iLastChar, pxBuffer );
-}
+ INT i, wlen, count = (INT)(iLastChar - iFirstChar + 1);
+ LPSTR str;
+ LPWSTR wstr;
+ BOOL ret = TRUE;
+
+ DPRINT("GetCharWidthsFloatA\n");
+ if(count <= 0) return FALSE;
+
+ str = HeapAlloc(GetProcessHeap(), 0, count+1);
+ if (!str)
+ return FALSE;
+ for(i = 0; i < count; i++)
+ str[i] = (BYTE)(iFirstChar + i);
+ str[i] = '\0';
+
+ wstr = FONT_mbtowc(hdc, str, count+1, &wlen, NULL);
+ if (!wstr)
+ {
+ HeapFree(GetProcessHeap(), 0, str);
+ return FALSE;
+ }
+ ret = NtGdiGetCharWidthW( hdc, wstr[0], (ULONG) count, (PWCHAR) wstr, 0, (PVOID) pxBuffer);
+
+ HeapFree(GetProcessHeap(), 0, str);
+ HeapFree(GetProcessHeap(), 0, wstr);
+ return ret;
+}
/*
- * @unimplemented
+ * @implemented
*/
BOOL
APIENTRY
LPABC lpabc
)
{
- /* FIXME what to do with uFirstChar and uLastChar ??? */
- return NtGdiGetCharABCWidths ( hdc, uFirstChar, uLastChar, lpabc );
-}
+ INT i, wlen, count = (INT)(uLastChar - uFirstChar + 1);
+ LPSTR str;
+ LPWSTR wstr;
+ BOOL ret = TRUE;
+
+ DPRINT("GetCharABCWidthsA\n");
+ if(count <= 0) return FALSE;
+
+ str = HeapAlloc(GetProcessHeap(), 0, count+1);
+ if (!str)
+ return FALSE;
+ for(i = 0; i < count; i++)
+ str[i] = (BYTE)(uFirstChar + i);
+ str[i] = '\0';
+
+ wstr = FONT_mbtowc(hdc, str, count+1, &wlen, NULL);
+ if (!wstr)
+ {
+ HeapFree(GetProcessHeap(), 0, str);
+ return FALSE;
+ }
+ ret = NtGdiGetCharABCWidthsW( hdc,
+ wstr[0],
+ (ULONG)count,
+ (PWCHAR)wstr,
+ GCABCW_NOFLOAT,
+ (PVOID)lpabc);
+
+ HeapFree(GetProcessHeap(), 0, str);
+ HeapFree(GetProcessHeap(), 0, wstr);
+
+ return ret;
+}
/*
- * @unimplemented
+ * @implemented
*/
BOOL
APIENTRY
LPABCFLOAT lpABCF
)
{
- /* FIXME what to do with iFirstChar and iLastChar ??? */
- return NtGdiGetCharABCWidthsFloat ( hdc, iFirstChar, iLastChar, lpABCF );
+ INT i, wlen, count = (INT)(iLastChar - iFirstChar + 1);
+ LPSTR str;
+ LPWSTR wstr;
+ BOOL ret = TRUE;
+
+ DPRINT("GetCharABCWidthsFloatA\n");
+ if (count <= 0) return FALSE;
+
+ str = HeapAlloc(GetProcessHeap(), 0, count+1);
+ if (!str)
+ return FALSE;
+
+ for(i = 0; i < count; i++)
+ str[i] = (BYTE)(iFirstChar + i);
+ str[i] = '\0';
+
+ wstr = FONT_mbtowc( hdc, str, count+1, &wlen, NULL );
+ if (!wstr)
+ {
+ HeapFree( GetProcessHeap(), 0, str );
+ return FALSE;
+ }
+ ret = NtGdiGetCharABCWidthsW( hdc,wstr[0],(ULONG)count, (PWCHAR)wstr, 0, (PVOID)lpABCF);
+
+ HeapFree( GetProcessHeap(), 0, str );
+ HeapFree( GetProcessHeap(), 0, wstr );
+
+ return ret;
+}
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+GetCharABCWidthsI(HDC hdc,
+ UINT giFirst,
+ UINT cgi,
+ LPWORD pgi,
+ LPABC lpabc)
+{
+ DPRINT("GetCharABCWidthsI\n");
+ return NtGdiGetCharABCWidthsW( hdc,
+ giFirst,
+ (ULONG) cgi,
+ (PWCHAR) pgi,
+ GCABCW_NOFLOAT|GCABCW_INDICES,
+ (PVOID)lpabc);
}
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+GetCharWidthI(HDC hdc,
+ UINT giFirst,
+ UINT cgi,
+ LPWORD pgi,
+ LPINT lpBuffer
+)
+{
+ DPRINT("GetCharWidthsI\n");
+ if (!lpBuffer || (!pgi && (giFirst == MAXUSHORT))) // Cannot be at max.
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ if (!cgi) return TRUE;
+ return NtGdiGetCharWidthW( hdc,
+ giFirst,
+ cgi,
+ (PWCHAR) pgi,
+ GCW_INDICES|GCW_NOFLOAT|GCW_WIN32,
+ (PVOID) lpBuffer );
+}
/*
* @implemented
*/
DWORD
-STDCALL
+WINAPI
+GetFontLanguageInfo(
+ HDC hDc
+ )
+{
+ DWORD Gcp = 0, Ret = 0;
+ if (gbLpk)
+ {
+ Ret = NtGdiGetTextCharsetInfo(hDc, NULL, 0);
+ if ((Ret == ARABIC_CHARSET) || (Ret == HEBREW_CHARSET))
+ Ret = (GCP_KASHIDA|GCP_DIACRITIC|GCP_LIGATE|GCP_GLYPHSHAPE|GCP_REORDER);
+ }
+ Gcp = GetDCDWord(hDc, GdiGetFontLanguageInfo, GCP_ERROR);
+ if ( Gcp == GCP_ERROR)
+ return Gcp;
+ else
+ Ret = Gcp | Ret;
+ return Ret;
+}
+
+/*
+ * @implemented
+ */
+DWORD
+WINAPI
+GetGlyphIndicesA(
+ HDC hdc,
+ LPCSTR lpstr,
+ INT count,
+ LPWORD pgi,
+ DWORD flags
+ )
+{
+ DWORD Ret;
+ WCHAR *lpstrW;
+ INT countW;
+
+ lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
+ Ret = NtGdiGetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
+ HeapFree(GetProcessHeap(), 0, lpstrW);
+ return Ret;
+}
+
+/*
+ * @implemented
+ */
+DWORD
+WINAPI
GetGlyphOutlineA(
HDC hdc,
UINT uChar,
CONST MAT2 *lpmat2
)
{
- return NtGdiGetGlyphOutline ( hdc, uChar, uFormat, lpgm, cbBuffer, lpvBuffer, (CONST LPMAT2)lpmat2, TRUE);
+
+ LPWSTR p = NULL;
+ DWORD ret;
+ UINT c;
+ DPRINT("GetGlyphOutlineA uChar %x\n", uChar);
+ if(!(uFormat & GGO_GLYPH_INDEX)) {
+ int len;
+ char mbchs[2];
+ if(uChar > 0xff) { /* but, 2 bytes character only */
+ len = 2;
+ mbchs[0] = (uChar & 0xff00) >> 8;
+ mbchs[1] = (uChar & 0xff);
+ } else {
+ len = 1;
+ mbchs[0] = (uChar & 0xff);
+ }
+ p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
+ c = p[0];
+ } else
+ c = uChar;
+ ret = NtGdiGetGlyphOutline(hdc, c, uFormat, lpgm, cbBuffer, lpvBuffer, (CONST LPMAT2)lpmat2, TRUE);
+ HeapFree(GetProcessHeap(), 0, p);
+ return ret;
}
+
/*
* @implemented
*/
DWORD
-STDCALL
+WINAPI
GetGlyphOutlineW(
HDC hdc,
UINT uChar,
CONST MAT2 *lpmat2
)
{
+ DPRINT("GetGlyphOutlineW uChar %x\n", uChar);
+ if (!lpgm & !lpmat2) return GDI_ERROR;
+ if (!lpvBuffer) cbBuffer = 0;
return NtGdiGetGlyphOutline ( hdc, uChar, uFormat, lpgm, cbBuffer, lpvBuffer, (CONST LPMAT2)lpmat2, TRUE);
}
if(output != lpOTM) {
memcpy(lpOTM, output, cbData);
HeapFree(GetProcessHeap(), 0, output);
+
+ /* check if the string offsets really fit into the provided size */
+ /* FIXME: should we check string length as well? */
+ if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
+ lpOTM->otmpFamilyName = 0; /* doesn't fit */
+
+ if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
+ lpOTM->otmpFaceName = 0; /* doesn't fit */
+
+ if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
+ lpOTM->otmpStyleName = 0; /* doesn't fit */
+
+ if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
+ lpOTM->otmpFullName = 0; /* doesn't fit */
}
end:
LPOUTLINETEXTMETRICW lpOTM
)
{
- return NtGdiGetOutlineTextMetrics(hdc, cbData, lpOTM);
+ TMDIFF Tmd; // Should not be zero.
+
+ return NtGdiGetOutlineTextMetricsInternalW(hdc, cbData, lpOTM, &Tmd);
+}
+
+/*
+ * @implemented
+ */
+DWORD
+WINAPI
+GetKerningPairsW(HDC hdc,
+ ULONG cPairs,
+ LPKERNINGPAIR pkpDst)
+{
+ if ((cPairs != 0) || (pkpDst == 0))
+ {
+ return NtGdiGetKerningPairs(hdc,cPairs,pkpDst);
+ }
+ else
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+}
+
+/*
+ * @implemented
+ */
+DWORD
+WINAPI
+GetKerningPairsA( HDC hDC,
+ DWORD cPairs,
+ LPKERNINGPAIR kern_pairA )
+{
+ INT charset;
+ CHARSETINFO csi;
+ CPINFO cpi;
+ DWORD i, total_kern_pairs, kern_pairs_copied = 0;
+ KERNINGPAIR *kern_pairW;
+
+ if (!cPairs && kern_pairA)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+
+ charset = GetTextCharset(hDC);
+ if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
+ {
+ DPRINT1("Can't find codepage for charset %d\n", charset);
+ return 0;
+ }
+ /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
+ * to fail on an invalid character for CP_SYMBOL.
+ */
+ cpi.DefaultChar[0] = 0;
+ if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
+ {
+ DPRINT1("Can't find codepage %u info\n", csi.ciACP);
+ return 0;
+ }
+ DPRINT("charset %d => codepage %u\n", charset, csi.ciACP);
+
+ total_kern_pairs = NtGdiGetKerningPairs(hDC, 0, NULL);
+ if (!total_kern_pairs) return 0;
+
+ if (!cPairs && !kern_pairA) return total_kern_pairs;
+
+ kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
+ GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
+
+ for (i = 0; i < total_kern_pairs; i++)
+ {
+ char first, second;
+
+ if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
+ continue;
+
+ if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
+ continue;
+
+ if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
+ continue;
+
+ if (kern_pairA)
+ {
+ if (kern_pairs_copied >= cPairs) break;
+
+ kern_pairA->wFirst = (BYTE)first;
+ kern_pairA->wSecond = (BYTE)second;
+ kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
+ kern_pairA++;
+ }
+ kern_pairs_copied++;
+ }
+
+ HeapFree(GetProcessHeap(), 0, kern_pairW);
+
+ return kern_pairs_copied;
}
+
/*
* @implemented
*/
HFONT
-STDCALL
+WINAPI
+CreateFontIndirectExA(const ENUMLOGFONTEXDVA *elfexd)
+{
+ if (elfexd)
+ {
+ ENUMLOGFONTEXDVW Logfont;
+
+ EnumLogFontExW2A( (LPENUMLOGFONTEXA) elfexd,
+ &Logfont.elfEnumLogfontEx );
+
+ RtlCopyMemory( &Logfont.elfDesignVector,
+ (PVOID) &elfexd->elfDesignVector,
+ sizeof(DESIGNVECTOR));
+
+ return NtGdiHfontCreate( &Logfont, 0, 0, 0, NULL);
+ }
+ else return NULL;
+}
+
+
+/*
+ * @implemented
+ */
+HFONT
+WINAPI
+CreateFontIndirectExW(const ENUMLOGFONTEXDVW *elfexd)
+{
+ /* Msdn: Note, this function ignores the elfDesignVector member in
+ ENUMLOGFONTEXDV.
+ */
+ if ( elfexd )
+ {
+ return NtGdiHfontCreate((PENUMLOGFONTEXDVW) elfexd, 0, 0, 0, NULL );
+ }
+ else return NULL;
+}
+
+
+/*
+ * @implemented
+ */
+HFONT
+WINAPI
CreateFontIndirectA(
CONST LOGFONTA *lplf
)
{
- LOGFONTW tlf;
-
- LogFontA2W(&tlf, lplf);
+ if (lplf)
+ {
+ LOGFONTW tlf;
- return NtGdiCreateFontIndirect(&tlf);
+ LogFontA2W(&tlf, lplf);
+ return CreateFontIndirectW(&tlf);
+ }
+ else return NULL;
}
* @implemented
*/
HFONT
-STDCALL
+WINAPI
CreateFontIndirectW(
CONST LOGFONTW *lplf
)
{
- return NtGdiCreateFontIndirect((CONST LPLOGFONTW)lplf);
+ if (lplf)
+ {
+ ENUMLOGFONTEXDVW Logfont;
+
+ RtlCopyMemory( &Logfont.elfEnumLogfontEx.elfLogFont, lplf, sizeof(LOGFONTW));
+ // Need something other than just cleaning memory here.
+ // Guess? Use caller data to determine the rest.
+ RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfFullName,
+ sizeof(Logfont.elfEnumLogfontEx.elfFullName));
+ RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfStyle,
+ sizeof(Logfont.elfEnumLogfontEx.elfStyle));
+ RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfScript,
+ sizeof(Logfont.elfEnumLogfontEx.elfScript));
+
+ Logfont.elfDesignVector.dvNumAxes = 0; // No more than MM_MAX_NUMAXES
+
+ RtlZeroMemory( &Logfont.elfDesignVector, sizeof(DESIGNVECTOR));
+
+ return CreateFontIndirectExW(&Logfont);
+ }
+ else return NULL;
}
* @implemented
*/
HFONT
-STDCALL
+WINAPI
CreateFontA(
int nHeight,
int nWidth,
RtlInitAnsiString(&StringA, (LPSTR)lpszFace);
RtlAnsiStringToUnicodeString(&StringU, &StringA, TRUE);
- ret = CreateFontW(nHeight, nWidth, nEscapement, nOrientation, fnWeight, fdwItalic, fdwUnderline, fdwStrikeOut,
- fdwCharSet, fdwOutputPrecision, fdwClipPrecision, fdwQuality, fdwPitchAndFamily, StringU.Buffer);
+ ret = CreateFontW(nHeight,
+ nWidth,
+ nEscapement,
+ nOrientation,
+ fnWeight,
+ fdwItalic,
+ fdwUnderline,
+ fdwStrikeOut,
+ fdwCharSet,
+ fdwOutputPrecision,
+ fdwClipPrecision,
+ fdwQuality,
+ fdwPitchAndFamily,
+ StringU.Buffer);
RtlFreeUnicodeString(&StringU);
* @implemented
*/
HFONT
-STDCALL
+WINAPI
CreateFontW(
int nHeight,
int nWidth,
LPCWSTR lpszFace
)
{
- return NtGdiCreateFont(nHeight, nWidth, nEscapement, nOrientation, nWeight, fnItalic, fdwUnderline, fdwStrikeOut,
- fdwCharSet, fdwOutputPrecision, fdwClipPrecision, fdwQuality, fdwPitchAndFamily, lpszFace);
-}
-
+ LOGFONTW logfont;
+
+ logfont.lfHeight = nHeight;
+ logfont.lfWidth = nWidth;
+ logfont.lfEscapement = nEscapement;
+ logfont.lfOrientation = nOrientation;
+ logfont.lfWeight = nWeight;
+ logfont.lfItalic = fnItalic;
+ logfont.lfUnderline = fdwUnderline;
+ logfont.lfStrikeOut = fdwStrikeOut;
+ logfont.lfCharSet = fdwCharSet;
+ logfont.lfOutPrecision = fdwOutputPrecision;
+ logfont.lfClipPrecision = fdwClipPrecision;
+ logfont.lfQuality = fdwQuality;
+ logfont.lfPitchAndFamily = fdwPitchAndFamily;
+
+ if (NULL != lpszFace)
+ {
+ int Size = sizeof(logfont.lfFaceName) / sizeof(WCHAR);
+ wcsncpy((wchar_t *)logfont.lfFaceName, lpszFace, Size - 1);
+ /* Be 101% sure to have '\0' at end of string */
+ logfont.lfFaceName[Size - 1] = '\0';
+ }
+ else
+ {
+ logfont.lfFaceName[0] = L'\0';
+ }
-/*
- * @implemented
- */
-BOOL
-STDCALL
-CreateScalableFontResourceW(
- DWORD fdwHidden,
- LPCWSTR lpszFontRes,
- LPCWSTR lpszFontFile,
- LPCWSTR lpszCurrentPath
- )
-{
- return NtGdiCreateScalableFontResource ( fdwHidden,
- lpszFontRes,
- lpszFontFile,
- lpszCurrentPath );
+ return CreateFontIndirectW(&logfont);
}
/*
- * @implemented
+ * @unimplemented
*/
BOOL
-STDCALL
+WINAPI
CreateScalableFontResourceA(
DWORD fdwHidden,
LPCSTR lpszFontRes,
LPCSTR lpszCurrentPath
)
{
- NTSTATUS Status;
- LPWSTR lpszFontResW, lpszFontFileW, lpszCurrentPathW;
- BOOL rc = FALSE;
-
- Status = HEAP_strdupA2W ( &lpszFontResW, lpszFontRes );
- if (!NT_SUCCESS (Status))
- SetLastError (RtlNtStatusToDosError(Status));
- else
- {
- Status = HEAP_strdupA2W ( &lpszFontFileW, lpszFontFile );
- if (!NT_SUCCESS (Status))
- SetLastError (RtlNtStatusToDosError(Status));
- else
- {
- Status = HEAP_strdupA2W ( &lpszCurrentPathW, lpszCurrentPath );
- if (!NT_SUCCESS (Status))
- SetLastError (RtlNtStatusToDosError(Status));
- else
- {
- rc = NtGdiCreateScalableFontResource ( fdwHidden,
- lpszFontResW,
- lpszFontFileW,
- lpszCurrentPathW );
-
- HEAP_free ( lpszCurrentPathW );
- }
-
- HEAP_free ( lpszFontFileW );
- }
-
- HEAP_free ( lpszFontResW );
- }
- return rc;
+ return FALSE;
}
* @implemented
*/
int
-STDCALL
+WINAPI
AddFontResourceExW ( LPCWSTR lpszFilename, DWORD fl, PVOID pvReserved )
{
- UNICODE_STRING Filename;
+ if (fl & ~(FR_PRIVATE | FR_NOT_ENUM))
+ {
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return 0;
+ }
- /* FIXME handle fl parameter */
- RtlInitUnicodeString(&Filename, lpszFilename);
- return NtGdiAddFontResource ( &Filename, fl );
+ return GdiAddFontResourceW(lpszFilename, fl,0);
}
* @implemented
*/
int
-STDCALL
+WINAPI
AddFontResourceExA ( LPCSTR lpszFilename, DWORD fl, PVOID pvReserved )
{
- NTSTATUS Status;
- PWSTR FilenameW;
- int rc = 0;
+ NTSTATUS Status;
+ PWSTR FilenameW;
+ int rc;
- Status = HEAP_strdupA2W ( &FilenameW, lpszFilename );
- if ( !NT_SUCCESS (Status) )
- SetLastError (RtlNtStatusToDosError(Status));
- else
+ if (fl & ~(FR_PRIVATE | FR_NOT_ENUM))
{
- rc = AddFontResourceExW ( FilenameW, fl, pvReserved );
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return 0;
+ }
- HEAP_free ( FilenameW );
+ Status = HEAP_strdupA2W ( &FilenameW, lpszFilename );
+ if ( !NT_SUCCESS (Status) )
+ {
+ SetLastError (RtlNtStatusToDosError(Status));
+ return 0;
}
- return rc;
+
+ rc = GdiAddFontResourceW ( FilenameW, fl, 0 );
+ HEAP_free ( FilenameW );
+ return rc;
}
* @implemented
*/
int
-STDCALL
+WINAPI
AddFontResourceA ( LPCSTR lpszFilename )
{
- return AddFontResourceExA ( lpszFilename, 0, 0 );
+ NTSTATUS Status;
+ PWSTR FilenameW;
+ int rc = 0;
+
+ Status = HEAP_strdupA2W ( &FilenameW, lpszFilename );
+ if ( !NT_SUCCESS (Status) )
+ {
+ SetLastError (RtlNtStatusToDosError(Status));
+ }
+ else
+ {
+ rc = GdiAddFontResourceW ( FilenameW, 0, 0);
+
+ HEAP_free ( FilenameW );
+ }
+ return rc;
}
* @implemented
*/
int
-STDCALL
+WINAPI
AddFontResourceW ( LPCWSTR lpszFilename )
{
- return AddFontResourceExW ( lpszFilename, 0, 0 );
+ return GdiAddFontResourceW ( lpszFilename, 0, 0 );
}
* @implemented
*/
BOOL
-STDCALL
-RemoveFontResourceW(
- LPCWSTR lpFileName
- )
+WINAPI
+RemoveFontResourceW(LPCWSTR lpFileName)
{
- return NtGdiRemoveFontResource ( lpFileName );
+ return RemoveFontResourceExW(lpFileName,0,0);
}
* @implemented
*/
BOOL
-STDCALL
-RemoveFontResourceA(
- LPCSTR lpFileName
- )
+WINAPI
+RemoveFontResourceA(LPCSTR lpFileName)
{
- NTSTATUS Status;
- LPWSTR lpFileNameW;
- BOOL rc = 0;
+ return RemoveFontResourceExA(lpFileName,0,0);
+}
- Status = HEAP_strdupA2W ( &lpFileNameW, lpFileName );
- if (!NT_SUCCESS (Status))
+/*
+ * @unimplemented
+ */
+BOOL
+WINAPI
+RemoveFontResourceExA(LPCSTR lpFileName,
+ DWORD fl,
+ PVOID pdv
+)
+{
+ NTSTATUS Status;
+ LPWSTR lpFileNameW;
+
+ /* FIXME the flags */
+ /* FIXME the pdv */
+ /* FIXME NtGdiRemoveFontResource handle flags and pdv */
+
+ Status = HEAP_strdupA2W ( &lpFileNameW, lpFileName );
+ if (!NT_SUCCESS (Status))
SetLastError (RtlNtStatusToDosError(Status));
- else
+ else
{
- rc = NtGdiRemoveFontResource ( lpFileNameW );
- HEAP_free ( lpFileNameW );
+ HEAP_free ( lpFileNameW );
}
- return rc;
+ return 0;
+}
+
+/*
+ * @unimplemented
+ */
+BOOL
+WINAPI
+RemoveFontResourceExW(LPCWSTR lpFileName,
+ DWORD fl,
+ PVOID pdv)
+{
+ /* FIXME the flags */
+ /* FIXME the pdv */
+ /* FIXME NtGdiRemoveFontResource handle flags and pdv */
+ return 0;
}
+
/***********************************************************************
* GdiGetCharDimensions
*
* @implemented
*/
DWORD
-STDCALL
+WINAPI
GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
{
SIZE sz;
+ TEXTMETRICW tm;
static const WCHAR alphabet[] = {
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
- if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
+ if(!GetTextMetricsW(hdc, &tm)) return 0;
if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
- if (height) *height = sz.cy;
+ if (lptm) *lptm = tm;
+ if (height) *height = tm.tmHeight;
+
return (sz.cx / 26 + 1) / 2;
}
+/*************************************************************************
+ * TranslateCharsetInfo [GDI32.@]
+ *
+ * Fills a CHARSETINFO structure for a character set, code page, or
+ * font. This allows making the correspondance between different labelings
+ * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
+ * of the same encoding.
+ *
+ * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
+ * only one codepage should be set in *lpSrc.
+ *
+ * RETURNS
+ * TRUE on success, FALSE on failure.
+ *
+ */
+/*
+ * @unimplemented
+ */
+BOOL
+WINAPI
+TranslateCharsetInfo(
+ LPDWORD lpSrc, /* [in]
+ if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
+ if flags == TCI_SRCCHARSET: a character set value
+ if flags == TCI_SRCCODEPAGE: a code page value
+ */
+ LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
+ DWORD flags /* [in] determines interpretation of lpSrc */)
+{
+ int index = 0;
+ switch (flags) {
+ case TCI_SRCFONTSIG:
+ while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
+ break;
+ case TCI_SRCCODEPAGE:
+ while (PtrToUlong(lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
+ break;
+ case TCI_SRCCHARSET:
+ while (PtrToUlong(lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
+ break;
+ default:
+ return FALSE;
+ }
+ if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
+ memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
+ return TRUE;
+}
+
+
+/*
+ * @implemented
+ */
+DWORD
+WINAPI
+SetMapperFlags(
+ HDC hDC,
+ DWORD flags
+ )
+{
+ DWORD Ret = GDI_ERROR;
+ PDC_ATTR Dc_Attr;
+#if 0
+ if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC)
+ {
+ if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC)
+ return MFDRV_SetMapperFlags( hDC, flags);
+ else
+ {
+ PLDC pLDC = Dc_Attr->pvLDC;
+ if ( !pLDC )
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return GDI_ERROR;
+ }
+ if (pLDC->iType == LDC_EMFLDC)
+ {
+ return EMFDRV_SetMapperFlags( hDC, flags);
+ }
+ }
+ }
+#endif
+ if (!GdiGetHandleUserData((HGDIOBJ) hDC, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return GDI_ERROR;
+
+ if (NtCurrentTeb()->GdiTebBatch.HDC == hDC)
+ {
+ if (Dc_Attr->ulDirty_ & DC_FONTTEXT_DIRTY)
+ {
+ NtGdiFlush();
+ Dc_Attr->ulDirty_ &= ~(DC_MODE_DIRTY|DC_FONTTEXT_DIRTY);
+ }
+ }
+
+ if ( flags & ~1 )
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else
+ {
+ Ret = Dc_Attr->flFontMapper;
+ Dc_Attr->flFontMapper = flags;
+ }
+ return Ret;
+}
+
/*
* @unimplemented
*/
int
-STDCALL
+WINAPI
EnumFontsW(
HDC hDC,
LPCWSTR lpFaceName,
* @unimplemented
*/
int
-STDCALL
+WINAPI
EnumFontsA (
HDC hDC,
LPCSTR lpFaceName,
#endif
}
+#define EfdFontFamilies 3
+INT
+WINAPI
+NewEnumFontFamiliesExW(
+ HDC hDC,
+ LPLOGFONTW lpLogfont,
+ FONTENUMPROCW lpEnumFontFamExProcW,
+ LPARAM lParam,
+ DWORD dwFlags)
+{
+ ULONG_PTR idEnum, cbDataSize, cbRetSize;
+ PENUMFONTDATAW pEfdw;
+ PBYTE pBuffer;
+ PBYTE pMax;
+ INT ret = 1;
+
+ /* Open enumeration handle and find out how much memory we need */
+ idEnum = NtGdiEnumFontOpen(hDC,
+ EfdFontFamilies,
+ 0,
+ LF_FACESIZE,
+ (lpLogfont && lpLogfont->lfFaceName[0])? lpLogfont->lfFaceName : NULL,
+ lpLogfont? lpLogfont->lfCharSet : DEFAULT_CHARSET,
+ &cbDataSize);
+ if (idEnum == 0)
+ {
+ return 0;
+ }
+ if (cbDataSize == 0)
+ {
+ NtGdiEnumFontClose(idEnum);
+ return 0;
+ }
+ /* Allocate memory */
+ pBuffer = HeapAlloc(GetProcessHeap(), 0, cbDataSize);
+ if (pBuffer == NULL)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ NtGdiEnumFontClose(idEnum);
+ return 0;
+ }
+ /* Do the enumeration */
+ if (!NtGdiEnumFontChunk(hDC, idEnum, cbDataSize, &cbRetSize, (PVOID)pBuffer))
+ {
+ HeapFree(GetProcessHeap(), 0, pBuffer);
+ NtGdiEnumFontClose(idEnum);
+ return 0;
+ }
+
+ /* Get start and end address */
+ pEfdw = (PENUMFONTDATAW)pBuffer;
+ pMax = pBuffer + cbDataSize;
+
+ /* Iterate through the structures */
+ while ((PBYTE)pEfdw < pMax && ret)
+ {
+ PNTMW_INTERNAL pNtmwi = (PNTMW_INTERNAL)((ULONG_PTR)pEfdw + pEfdw->ulNtmwiOffset);
+
+ ret = lpEnumFontFamExProcW((VOID*)&pEfdw->elfexdv.elfEnumLogfontEx,
+ (VOID*)&pNtmwi->ntmw,
+ pEfdw->dwFontType,
+ lParam);
+
+ pEfdw = (PENUMFONTDATAW)((ULONG_PTR)pEfdw + pEfdw->cbSize);
+ }
+
+ /* Release the memory and close handle */
+ HeapFree(GetProcessHeap(), 0, pBuffer);
+ NtGdiEnumFontClose(idEnum);
+
+ return ret;
+}