- Deactivate unneeded debug prints, change DbgPrint to DPRINTx, remove unused perform...
[reactos.git] / reactos / dll / win32 / gdi32 / objects / font.c
index 48aaddd..7450294 100644 (file)
@@ -3,7 +3,7 @@
  * 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
 
 /***********************************************************************
@@ -42,6 +86,35 @@ static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
     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)
   {
@@ -252,12 +325,12 @@ IntEnumFontFamilies(HDC Dc, LPLOGFONTW LogFont, PVOID EnumProc, LPARAM lParam,
       if (Unicode)
         {
           Ret = ((FONTENUMPROCW) EnumProc)(
-            (LPLOGFONTW)&Info[i].EnumLogFontEx,
-            (LPTEXTMETRICW)&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);
@@ -268,8 +341,8 @@ IntEnumFontFamilies(HDC Dc, LPLOGFONTW LogFont, PVOID EnumProc, LPARAM lParam,
           NewTextMetricExW2A(&NewTextMetricExA,
                              &Info[i].NewTextMetricEx);
           Ret = ((FONTENUMPROCA) EnumProc)(
-            (LPLOGFONTA)&EnumLogFontExA,
-            (LPTEXTMETRICA)&NewTextMetricExA,
+            (VOID*)&EnumLogFontExA,
+            (VOID*)&NewTextMetricExA,
             Info[i].FontType, lParam);
         }
     }
@@ -282,7 +355,7 @@ IntEnumFontFamilies(HDC Dc, LPLOGFONTW LogFont, PVOID EnumProc, LPARAM lParam,
 /*
  * @implemented
  */
-int STDCALL
+int WINAPI
 EnumFontFamiliesExW(HDC hdc, LPLOGFONTW lpLogfont, FONTENUMPROCW lpEnumFontFamExProc,
                     LPARAM lParam, DWORD dwFlags)
 {
@@ -293,7 +366,7 @@ EnumFontFamiliesExW(HDC hdc, LPLOGFONTW lpLogfont, FONTENUMPROCW lpEnumFontFamEx
 /*
  * @implemented
  */
-int STDCALL
+int WINAPI
 EnumFontFamiliesW(HDC hdc, LPCWSTR lpszFamily, FONTENUMPROCW lpEnumFontFamProc,
                   LPARAM lParam)
 {
@@ -303,6 +376,7 @@ EnumFontFamiliesW(HDC hdc, LPCWSTR lpszFamily, FONTENUMPROCW lpEnumFontFamProc,
   LogFont.lfCharSet = DEFAULT_CHARSET;
   if (NULL != lpszFamily)
     {
+      if (!*lpszFamily) return 1;
       lstrcpynW(LogFont.lfFaceName, lpszFamily, LF_FACESIZE);
     }
 
@@ -313,23 +387,28 @@ EnumFontFamiliesW(HDC hdc, LPCWSTR lpszFamily, FONTENUMPROCW lpEnumFontFamProc,
 /*
  * @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)
 {
@@ -339,68 +418,18 @@ EnumFontFamiliesA(HDC hdc, LPCSTR lpszFamily, FONTENUMPROCA lpEnumFontFamProc,
   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,
@@ -413,6 +442,7 @@ GetCharacterPlacementW(
   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");
@@ -453,7 +483,7 @@ GetCharacterPlacementW(
     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;
     }
   }
@@ -461,15 +491,15 @@ GetCharacterPlacementW(
   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);
@@ -477,9 +507,229 @@ GetCharacterPlacementW(
   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
@@ -490,13 +740,37 @@ GetCharWidthFloatA(
        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
@@ -507,13 +781,43 @@ GetCharABCWidthsA(
        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
@@ -524,16 +828,135 @@ GetCharABCWidthsFloatA(
        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,
@@ -544,14 +967,37 @@ GetGlyphOutlineA(
        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,
@@ -562,6 +1008,9 @@ GetGlyphOutlineW(
        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);
 }
 
@@ -696,6 +1145,20 @@ GetOutlineTextMetricsA(
     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:
@@ -717,24 +1180,168 @@ GetOutlineTextMetricsW(
        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;
 }
 
 
@@ -742,12 +1349,32 @@ CreateFontIndirectA(
  * @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;
 }
 
 
@@ -755,7 +1382,7 @@ CreateFontIndirectW(
  * @implemented
  */
 HFONT
-STDCALL
+WINAPI
 CreateFontA(
        int     nHeight,
        int     nWidth,
@@ -780,8 +1407,20 @@ CreateFontA(
        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);
 
@@ -793,7 +1432,7 @@ CreateFontA(
  * @implemented
  */
 HFONT
-STDCALL
+WINAPI
 CreateFontW(
        int     nHeight,
        int     nWidth,
@@ -811,35 +1450,43 @@ CreateFontW(
        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,
@@ -847,39 +1494,7 @@ CreateScalableFontResourceA(
        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;
 }
 
 
@@ -887,14 +1502,16 @@ CreateScalableFontResourceA(
  * @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);
 }
 
 
@@ -902,23 +1519,29 @@ AddFontResourceExW ( LPCWSTR lpszFilename, DWORD fl, PVOID pvReserved )
  * @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;
 }
 
 
@@ -926,10 +1549,25 @@ AddFontResourceExA ( LPCSTR lpszFilename, DWORD fl, PVOID pvReserved )
  * @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;
 }
 
 
@@ -937,10 +1575,10 @@ AddFontResourceA ( LPCSTR lpszFilename )
  * @implemented
  */
 int
-STDCALL
+WINAPI
 AddFontResourceW ( LPCWSTR lpszFilename )
 {
-       return AddFontResourceExW ( lpszFilename, 0, 0 );
+    return GdiAddFontResourceW ( lpszFilename, 0, 0 );
 }
 
 
@@ -948,12 +1586,10 @@ AddFontResourceW ( LPCWSTR lpszFilename )
  * @implemented
  */
 BOOL
-STDCALL
-RemoveFontResourceW(
-       LPCWSTR lpFileName
-       )
+WINAPI
+RemoveFontResourceW(LPCWSTR lpFileName)
 {
-  return NtGdiRemoveFontResource ( lpFileName );
+    return RemoveFontResourceExW(lpFileName,0,0);
 }
 
 
@@ -961,28 +1597,57 @@ RemoveFontResourceW(
  * @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
  *
@@ -1017,29 +1682,134 @@ RemoveFontResourceA(
  * @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,
@@ -1058,7 +1828,7 @@ EnumFontsW(
  * @unimplemented
  */
 int
-STDCALL
+WINAPI
 EnumFontsA (
        HDC  hDC,
        LPCSTR lpFaceName,
@@ -1086,6 +1856,78 @@ EnumFontsA (
 #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;
+}