[RICHED20_WINETEST] Sync with Wine Staging 4.18. CORE-16441
[reactos.git] / modules / rostests / winetests / riched20 / txtsrv.c
index 88b5adf..5a59c87 100644 (file)
@@ -48,7 +48,7 @@ static PCreateTextServices pCreateTextServices;
 
 /* Use a special table for x86 machines to convert the thiscall
  * calling convention.  This isn't needed on other platforms. */
-#ifdef __i386__
+#if defined(__i386__) && !defined(__MINGW32__)
 static ITextServicesVtbl itextServicesStdcallVtbl;
 #define TXTSERV_VTABLE(This) (&itextServicesStdcallVtbl)
 #else /* __i386__ */
@@ -85,6 +85,7 @@ typedef struct ITextHostTestImpl
 {
     ITextHost ITextHost_iface;
     LONG refCount;
+    CHARFORMAT2W char_format;
 } ITextHostTestImpl;
 
 static inline ITextHostTestImpl *impl_from_ITextHost(ITextHost *iface)
@@ -534,7 +535,7 @@ typedef struct
 
 static void setup_thiscall_wrappers(void)
 {
-#ifdef __i386__
+#if defined(__i386__) && !defined(__MINGW32__)
     void** pVtable;
     void** pVtableEnd;
     THISCALL_TO_STDCALL_THUNK *thunk;
@@ -600,6 +601,21 @@ static void setup_thiscall_wrappers(void)
 #endif /* __i386__ */
 }
 
+static void hf_to_cf(HFONT hf, CHARFORMAT2W *cf)
+{
+    LOGFONTW lf;
+
+    GetObjectW(hf, sizeof(lf), &lf);
+    lstrcpyW(cf->szFaceName, lf.lfFaceName);
+    cf->yHeight = MulDiv(abs(lf.lfHeight), 1440, GetDeviceCaps(GetDC(NULL), LOGPIXELSY));
+    if (lf.lfWeight > FW_NORMAL) cf->dwEffects |= CFE_BOLD;
+    if (lf.lfItalic) cf->dwEffects |= CFE_ITALIC;
+    if (lf.lfUnderline) cf->dwEffects |= CFE_UNDERLINE;
+    if (lf.lfStrikeOut) cf->dwEffects |= CFE_SUBSCRIPT;
+    cf->bPitchAndFamily = lf.lfPitchAndFamily;
+    cf->bCharSet = lf.lfCharSet;
+}
+
 /*************************************************************************/
 /* Conformance test functions. */
 
@@ -609,6 +625,7 @@ static BOOL init_texthost(ITextServices **txtserv, ITextHost **ret)
     ITextHostTestImpl *dummyTextHost;
     IUnknown *init;
     HRESULT result;
+    HFONT hf;
 
     dummyTextHost = CoTaskMemAlloc(sizeof(*dummyTextHost));
     if (dummyTextHost == NULL) {
@@ -617,6 +634,11 @@ static BOOL init_texthost(ITextServices **txtserv, ITextHost **ret)
     }
     dummyTextHost->ITextHost_iface.lpVtbl = &itextHostVtbl;
     dummyTextHost->refCount = 1;
+    memset(&dummyTextHost->char_format, 0, sizeof(dummyTextHost->char_format));
+    dummyTextHost->char_format.cbSize = sizeof(dummyTextHost->char_format);
+    dummyTextHost->char_format.dwMask = CFM_ALL2;
+    hf = GetStockObject(DEFAULT_GUI_FONT);
+    hf_to_cf(hf, &dummyTextHost->char_format);
 
     /* MSDN states that an IUnknown object is returned by
        CreateTextServices which is then queried to obtain a
@@ -682,6 +704,8 @@ static void test_TxSetText(void)
     ok(memcmp(rettext,settext,SysStringByteLen(rettext)) == 0,
                  "String returned differs\n");
 
+    SysFreeString(rettext);
+
     /* Null-pointer should behave the same as empty-string */
 
     hres = ITextServices_TxSetText(txtserv, 0);
@@ -697,81 +721,68 @@ static void test_TxSetText(void)
     ITextHost_Release(host);
 }
 
+#define CHECK_TXGETNATURALSIZE(res,width,height,hdc,rect,string) \
+    _check_txgetnaturalsize(res, width, height, hdc, rect, string, __LINE__)
+static void _check_txgetnaturalsize(HRESULT res, LONG width, LONG height, HDC hdc, RECT rect, LPCWSTR string, int line)
+{
+    RECT expected_rect = rect;
+    LONG expected_width, expected_height;
+
+    DrawTextW(hdc, string, -1, &expected_rect, DT_LEFT | DT_CALCRECT | DT_NOCLIP | DT_EDITCONTROL | DT_WORDBREAK);
+    expected_width = expected_rect.right - expected_rect.left;
+    expected_height = expected_rect.bottom - expected_rect.top;
+    ok_(__FILE__,line)(res == S_OK, "ITextServices_TxGetNaturalSize failed: 0x%08x.\n", res);
+    ok_(__FILE__,line)(width >= expected_width && width <= expected_width + 1,
+                       "got wrong width: %d, expected: %d {+1}.\n", width, expected_width);
+    ok_(__FILE__,line)(height == expected_height, "got wrong height: %d, expected: %d.\n",
+                       height, expected_height);
+}
+
 static void test_TxGetNaturalSize(void)
 {
     ITextServices *txtserv;
     ITextHost *host;
     HRESULT result;
-    BOOL ret;
-
-    /* This value is used when calling TxGetNaturalSize.  MSDN says
-       that this is not supported however a null pointer cannot be
-       used as it will cause a segmentation violation.  The values in
-       the structure being pointed to are required to be INT_MAX
-       otherwise calculations can give wrong values. */
-    const SIZEL psizelExtent = {INT_MAX,INT_MAX};
-
-    static const WCHAR oneA[] = {'A',0};
-
-    /* Results of measurements */
-    LONG xdim, ydim;
-
-    /* The device context to do the tests in */
+    SIZEL extent;
+    static const WCHAR test_text[] = {'T','e','s','t','S','o','m','e','T','e','x','t',0};
+    LONG width, height;
     HDC hdcDraw;
-
-    /* Variables with the text metric information */
-    INT charwidth_caps_text[26];
-    TEXTMETRICA tmInfo_text;
+    HWND hwnd;
+    RECT rect;
+    CHARFORMAT2W cf;
+    LRESULT lresult;
+    HFONT hf;
 
     if (!init_texthost(&txtserv, &host))
         return;
 
-    hdcDraw = GetDC(NULL);
-    SaveDC(hdcDraw);
-
-    /* Populate the metric strucs */
+    hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
+                           0, 0, 100, 100, 0, 0, 0, NULL);
+    hdcDraw = GetDC(hwnd);
     SetMapMode(hdcDraw,MM_TEXT);
-    GetTextMetricsA(hdcDraw, &tmInfo_text);
-    SetLastError(0xdeadbeef);
-    ret = GetCharWidth32A(hdcDraw,'A','Z',charwidth_caps_text);
-    if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
-        win_skip("GetCharWidth32 is not available\n");
-        goto cleanup;
-    }
-
-    /* Make measurements in MM_TEXT */
-    SetMapMode(hdcDraw,MM_TEXT);
-    xdim = 0; ydim = 0;
-
-    result = ITextServices_TxSetText(txtserv, oneA);
-    ok(result == S_OK, "ITextServices_TxSetText failed (result = %x)\n", result);
-    if (result != S_OK) {
-        skip("Could not set text\n");
-        goto cleanup;
-    }
-
-    SetLastError(0xdeadbeef);
-    result = ITextServices_TxGetNaturalSize(txtserv, DVASPECT_CONTENT,
-                                            hdcDraw, NULL, NULL,
-                                            TXTNS_FITTOCONTENT, &psizelExtent,
-                                            &xdim, &ydim);
-    todo_wine ok(result == S_OK || broken(result == E_FAIL), /* WINXP Arabic Language */
-        "TxGetNaturalSize gave unexpected return value (result = %x)\n", result);
-    if (result == S_OK) {
-    todo_wine ok(ydim == tmInfo_text.tmHeight,
-                 "Height calculated incorrectly (expected %d, got %d)\n",
-                 tmInfo_text.tmHeight, ydim);
-    /* The native DLL adds one pixel extra when calculating widths. */
-    todo_wine ok(xdim >= charwidth_caps_text[0] && xdim <= charwidth_caps_text[0] + 1,
-                 "Width calculated incorrectly (expected %d {+1}, got %d)\n",
-                 charwidth_caps_text[0], xdim);
-    } else
-        skip("TxGetNaturalSize measurements not performed (xdim = %d, ydim = %d, result = %x, error = %x)\n",
-             xdim, ydim, result, GetLastError());
-
-cleanup:
-    RestoreDC(hdcDraw,1);
-    ReleaseDC(NULL,hdcDraw);
+    GetClientRect(hwnd, &rect);
+
+    memset(&cf, 0, sizeof(cf));
+    cf.cbSize = sizeof(cf);
+    cf.dwMask = CFM_ALL2;
+    hf = GetStockObject(DEFAULT_GUI_FONT);
+    hf_to_cf(hf, &cf);
+    result = ITextServices_TxSendMessage(txtserv, EM_SETCHARFORMAT, SCF_DEFAULT, (LPARAM)&cf, &lresult);
+    ok(result == S_OK, "ITextServices_TxSendMessage failed: 0x%08x.\n", result);
+    SelectObject(hdcDraw, hf);
+
+    result = ITextServices_TxSetText(txtserv, test_text);
+    ok(result == S_OK, "ITextServices_TxSetText failed: 0x%08x.\n", result);
+
+    extent.cx = -1; extent.cy = -1;
+    width = rect.right - rect.left;
+    height = 0;
+    result = ITextServices_TxGetNaturalSize(txtserv, DVASPECT_CONTENT, hdcDraw, NULL, NULL,
+                                            TXTNS_FITTOCONTENT, &extent, &width, &height);
+    todo_wine CHECK_TXGETNATURALSIZE(result, width, height, hdcDraw, rect, test_text);
+
+    ReleaseDC(hwnd, hdcDraw);
+    DestroyWindow(hwnd);
     ITextServices_Release(txtserv);
     ITextHost_Release(host);
 }
@@ -894,6 +905,7 @@ static void test_QueryInterface(void)
     HRESULT hres;
     IRichEditOle *reole, *txtsrv_reole;
     ITextDocument *txtdoc, *txtsrv_txtdoc;
+    ITextDocument2Old *txtdoc2old, *txtsrv_txtdoc2old;
     ULONG refcount;
 
     if(!init_texthost(&txtserv, &host))
@@ -920,6 +932,17 @@ static void test_QueryInterface(void)
     ITextDocument_Release(txtdoc);
     refcount = get_refcount((IUnknown *)txtserv);
     ok(refcount == 2, "got wrong ref count: %d\n", refcount);
+
+    hres = IRichEditOle_QueryInterface(txtsrv_reole, &IID_ITextDocument2Old, (void **)&txtdoc2old);
+    ok(hres == S_OK, "IRichEditOle_QueryInterface: 0x%08x\n", hres);
+    refcount = get_refcount((IUnknown *)txtserv);
+    ok(refcount == 3, "got wrong ref count: %d\n", refcount);
+    refcount = get_refcount((IUnknown *)txtsrv_reole);
+    ok(refcount == 3, "got wrong ref count: %d\n", refcount);
+
+    ITextDocument2Old_Release(txtdoc2old);
+    refcount = get_refcount((IUnknown *)txtserv);
+    ok(refcount == 2, "got wrong ref count: %d\n", refcount);
     IRichEditOle_Release(txtsrv_reole);
     refcount = get_refcount((IUnknown *)txtserv);
     ok(refcount == 1, "got wrong ref count: %d\n", refcount);
@@ -946,6 +969,77 @@ static void test_QueryInterface(void)
     refcount = get_refcount((IUnknown *)txtserv);
     ok(refcount == 1, "got wrong ref count: %d\n", refcount);
 
+    /* ITextDocument2Old */
+    hres = ITextServices_QueryInterface(txtserv, &IID_ITextDocument2Old, (void **)&txtsrv_txtdoc2old);
+    ok(hres == S_OK, "ITextServices_QueryInterface: 0x%08x\n", hres);
+    refcount = get_refcount((IUnknown *)txtserv);
+    ok(refcount == 2, "got wrong ref count: %d\n", refcount);
+    refcount = get_refcount((IUnknown *)txtsrv_txtdoc2old);
+    ok(refcount == 2, "got wrong ref count: %d\n", refcount);
+
+    hres = ITextDocument2Old_QueryInterface(txtsrv_txtdoc2old, &IID_IRichEditOle, (void **)&reole);
+    ok(hres == S_OK, "ITextDocument2Old_QueryInterface: 0x%08x\n", hres);
+    refcount = get_refcount((IUnknown *)txtserv);
+    ok(refcount == 3, "got wrong ref count: %d\n", refcount);
+    refcount = get_refcount((IUnknown *)txtsrv_txtdoc2old);
+    ok(refcount == 3, "got wrong ref count: %d\n", refcount);
+
+    IRichEditOle_Release(reole);
+    refcount = get_refcount((IUnknown *)txtserv);
+    ok(refcount == 2, "got wrong ref count: %d\n", refcount);
+    ITextDocument2Old_Release(txtsrv_txtdoc2old);
+    refcount = get_refcount((IUnknown *)txtserv);
+    ok(refcount == 1, "got wrong ref count: %d\n", refcount);
+
+    ITextServices_Release(txtserv);
+    ITextHost_Release(host);
+}
+
+static void test_default_format(void)
+{
+    ITextServices *txtserv;
+    ITextHost *host;
+    HRESULT result;
+    LRESULT lresult;
+    CHARFORMAT2W cf2;
+    const CHARFORMATW *host_cf;
+    DWORD expected_effects;
+
+    if (!init_texthost(&txtserv, &host))
+        return;
+
+    cf2.cbSize = sizeof(CHARFORMAT2W);
+    result = ITextServices_TxSendMessage(txtserv, EM_GETCHARFORMAT, SCF_DEFAULT, (LPARAM)&cf2, &lresult);
+    ok(result == S_OK, "ITextServices_TxSendMessage failed: 0x%08x.\n", result);
+
+    ITextHostImpl_TxGetCharFormat(host, &host_cf);
+    ok(!lstrcmpW(host_cf->szFaceName, cf2.szFaceName), "got wrong font name: %s.\n", wine_dbgstr_w(cf2.szFaceName));
+    ok(cf2.yHeight == host_cf->yHeight, "got wrong yHeight: %d, expected %d.\n", cf2.yHeight, host_cf->yHeight);
+    expected_effects = (cf2.dwEffects & ~(CFE_AUTOCOLOR | CFE_AUTOBACKCOLOR));
+    ok(host_cf->dwEffects == expected_effects, "got wrong dwEffects: %x, expected %x.\n", cf2.dwEffects, expected_effects);
+    ok(cf2.bPitchAndFamily == host_cf->bPitchAndFamily, "got wrong bPitchAndFamily: %x, expected %x.\n",
+       cf2.bPitchAndFamily, host_cf->bPitchAndFamily);
+    ok(cf2.bCharSet == host_cf->bCharSet, "got wrong bCharSet: %x, expected %x.\n", cf2.bCharSet, host_cf->bCharSet);
+
+    ITextServices_Release(txtserv);
+    ITextHost_Release(host);
+}
+
+static void test_TxGetScroll(void)
+{
+    ITextServices *txtserv;
+    ITextHost *host;
+    HRESULT ret;
+
+    if (!init_texthost(&txtserv, &host))
+        return;
+
+    ret = ITextServices_TxGetHScroll(txtserv, NULL, NULL, NULL, NULL, NULL);
+    ok(ret == S_OK, "ITextSerHices_GetVScroll failed: 0x%08x.\n", ret);
+
+    ret = ITextServices_TxGetVScroll(txtserv, NULL, NULL, NULL, NULL, NULL);
+    ok(ret == S_OK, "ITextServices_GetVScroll failed: 0x%08x.\n", ret);
+
     ITextServices_Release(txtserv);
     ITextHost_Release(host);
 }
@@ -980,6 +1074,8 @@ START_TEST( txtsrv )
         test_TxGetNaturalSize();
         test_TxDraw();
         test_QueryInterface();
+        test_default_format();
+        test_TxGetScroll();
     }
     if (wrapperCodeMem) VirtualFree(wrapperCodeMem, 0, MEM_RELEASE);
 }