From b908289c070b5441e79a84d44e1932a465bec372 Mon Sep 17 00:00:00 2001
From: Hirofumi Katayama <katayama.hirofumi.mz@gmail.com>
Date: Thu, 7 Nov 2019 21:09:15 +0900
Subject: [PATCH] user32: Implement case of pointSize == 0x7fff.

If DLGTEMPLATE.pointSize == 0x7FFF, then a special
treatment is required. That uses message box font.

Signed-off-by: Hirofumi Katayama <katayama.hirofumi.mz@gmail.com>
---
 dlls/user32/dialog.c       | 45 +++++++++++++++++++++++++++++++++-----
 dlls/user32/tests/dialog.c | 41 +++++++++++++++++++++++++++++++---
 2 files changed, 78 insertions(+), 8 deletions(-)

diff --git a/dlls/user32/dialog.c b/dlls/user32/dialog.c
index 88c2930c06..978df881bb 100644
--- a/dlls/user32/dialog.c
+++ b/dlls/user32/dialog.c
@@ -78,6 +78,7 @@ typedef struct
     BOOL       italic;
     LPCWSTR    faceName;
     BOOL       dialogEx;
+    WCHAR      nameBuffer[LF_FACESIZE];     /* for faceName */
 } DLG_TEMPLATE;
 
   /* Radio button group */
@@ -304,6 +305,30 @@ static BOOL DIALOG_CreateControls32( HWND hwnd, LPCSTR template, const DLG_TEMPL
     return TRUE;
 }
 
+static int GetFontPointSize(HDC hdc, const LOGFONT *plf)
+{
+    TEXTMETRICW tm;
+    HFONT hFont;
+    HGDIOBJ hFontOld;
+    INT nLogPixelsY = GetDeviceCaps(hdc, LOGPIXELSY);
+
+    if (plf->lfHeight < 0)
+    {
+        return -MulDiv(plf->lfHeight, 72, nLogPixelsY);
+    }
+
+    hFont = CreateFontIndirectW(plf);
+    if (!hFont)
+        return 0;
+
+    hFontOld = SelectObject(hdc, hFont);
+    GetTextMetricsW(hdc, &tm);
+    SelectObject(hdc, hFontOld);
+
+    DeleteObject(hFont);
+
+    return MulDiv(tm.tmHeight - tm.tmInternalLeading, 72, nLogPixelsY);
+}
 
 /***********************************************************************
  *           DIALOG_ParseTemplate32
@@ -316,6 +341,8 @@ static LPCSTR DIALOG_ParseTemplate32( LPCSTR template, DLG_TEMPLATE * result )
     const WORD *p = (const WORD *)template;
     WORD signature;
     WORD dlgver;
+    HDC dc;
+    NONCLIENTMETRICSW ncMetrics;
 
     dlgver = GET_WORD(p); p++;
     signature = GET_WORD(p); p++;
@@ -409,11 +436,19 @@ static LPCSTR DIALOG_ParseTemplate32( LPCSTR template, DLG_TEMPLATE * result )
          */
         if (result->pointSize == 0x7fff)
         {
-            /* We could call SystemParametersInfo here, but then we'd have
-             * to convert from pixel size to point size (which can be
-             * imprecise).
-             */
-            TRACE(" FONT: Using message box font\n");
+            ncMetrics.cbSize = FIELD_OFFSET(NONCLIENTMETRICSW, iPaddedBorderWidth);
+            SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, 0, &ncMetrics, 0);
+
+            dc = CreateCompatibleDC(NULL);
+            result->pointSize = GetFontPointSize(dc, &ncMetrics.lfMessageFont);
+            DeleteDC(dc);
+
+            result->weight = (WORD)ncMetrics.lfMessageFont.lfWeight;
+            result->italic = !!ncMetrics.lfMessageFont.lfItalic;
+
+            lstrcpynW(result->nameBuffer, ncMetrics.lfMessageFont.lfFaceName,
+                      ARRAY_SIZE(result->nameBuffer));
+            result->faceName = result->nameBuffer;
         }
         else
         {
diff --git a/dlls/user32/tests/dialog.c b/dlls/user32/tests/dialog.c
index b72f08816d..4b8b246c14 100644
--- a/dlls/user32/tests/dialog.c
+++ b/dlls/user32/tests/dialog.c
@@ -1903,6 +1903,23 @@ static INT_PTR CALLBACK messageBoxFontDlgWinProc (HWND hDlg, UINT uiMsg, WPARAM
     return 0;
 }
 
+static void DoGetTextFace(LOGFONT *plf)
+{
+    HDC hdc;
+    HFONT hFont;
+    HGDIOBJ hFontOld;
+
+    hdc = CreateCompatibleDC(NULL);
+    hFont = CreateFontIndirectW(plf);
+
+    hFontOld = SelectObject(hdc, hFont);
+    GetTextFaceW(hdc, ARRAY_SIZE(plf->lfFaceName), plf->lfFaceName);
+    SelectObject(hdc, hFontOld);
+
+    DeleteObject(hFont);
+    DeleteDC(hdc);
+}
+
 static void test_MessageBoxFontTest(void)
 {
     /* This dialog template defines a dialog template which got 0x7fff as its
@@ -1984,9 +2001,27 @@ static void test_MessageBoxFontTest(void)
 
     ncMetrics.cbSize = FIELD_OFFSET(NONCLIENTMETRICSW, iPaddedBorderWidth);
     SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, 0, &ncMetrics, 0);
-    ok( !memcmp(&lfStaticFont, &ncMetrics.lfMessageFont, FIELD_OFFSET(LOGFONTW, lfFaceName)) &&
-        !lstrcmpW(lfStaticFont.lfFaceName, ncMetrics.lfMessageFont.lfFaceName),
-        "dialog doesn't use message box font\n");
+
+    DoGetTextFace(&ncMetrics.lfMessageFont);
+    DoGetTextFace(&lfStaticFont.lfFaceName);
+
+    ok(lfStaticFont.lfHeight == ncMetrics.lfMessageFont.lfHeight,
+       "dialog font lfHeight not matched (%ld vs %ld)\n"
+        lfStaticFont.lfHeight, ncMetrics.lfMessageFont.lfHeight);
+
+    ok(!!lfStaticFont.lfItalic == !!ncMetrics.lfMessageFont.lfItalic,
+       "dialog font lfItalic not matched (%d vs %d)\n"
+        lfStaticFont.lfItalic, ncMetrics.lfMessageFont.lfItalic);
+
+    ok(lfStaticFont.lfWeight == ncMetrics.lfMessageFont.lfWeight,
+       "dialog font lfWeight not matched (%ld vs %ld)\n",
+       lfStaticFont.lfWeight, ncMetrics.lfMessageFont.lfWeight);
+
+    ok(!lstrcmpiW(lfStaticFont.lfFaceName, ncMetrics.lfMessageFont.lfFaceName),
+       "dialog font lfFaceName not matched ('%s' vs '%s')\n",
+       wine_dbgstr_w(lfStaticFont.lfFaceName),
+       wine_dbgstr_w(ncMetrics.lfMessageFont.lfFaceName));
+
     DestroyWindow(hDlg);
 }
 
-- 
2.23.0

