comctl32: A couple fixes for tab icon offsets.
[wine] / dlls / oleaut32 / tests / olefont.c
1 /*
2  * OLEFONT test program
3  *
4  * Copyright 2003 Marcus Meissner
5  *
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <math.h>
25 #include <float.h>
26 #include <time.h>
27
28 #define COBJMACROS
29
30 #include <wine/test.h>
31 #include <windef.h>
32 #include <winbase.h>
33 #include <winuser.h>
34 #include <wingdi.h>
35 #include <winnls.h>
36 #include <winerror.h>
37 #include <winnt.h>
38 #include <wtypes.h>
39 #include <olectl.h>
40 #include <ocidl.h>
41
42 static HMODULE hOleaut32;
43
44 static HRESULT (WINAPI *pOleCreateFontIndirect)(LPFONTDESC,REFIID,LPVOID*);
45
46 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08lx\n", hr)
47
48 /* Create a font with cySize given by lo_size, hi_size,  */
49 /* SetRatio to ratio_logical, ratio_himetric,            */
50 /* check that resulting hfont has height hfont_height.   */
51 /* Various checks along the way.                         */
52
53 static void test_ifont_sizes(long lo_size, long hi_size, 
54         long ratio_logical, long ratio_himetric,
55         long hfont_height, const char * test_name)
56 {
57         FONTDESC fd;
58         static const WCHAR fname[] = { 'S','y','s','t','e','m',0 };
59         LPVOID pvObj = NULL;
60         IFont* ifnt = NULL;
61         HFONT hfont;
62         LOGFONT lf;
63         CY psize;
64         HRESULT hres;
65
66         fd.cbSizeofstruct = sizeof(FONTDESC);
67         fd.lpstrName      = (WCHAR*)fname;
68         S(fd.cySize).Lo   = lo_size;
69         S(fd.cySize).Hi   = hi_size;
70         fd.sWeight        = 0;
71         fd.sCharset       = 0;
72         fd.fItalic        = 0;
73         fd.fUnderline     = 0;
74         fd.fStrikethrough = 0;
75
76         /* Create font, test that it worked. */
77         hres = pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj);
78         ifnt = pvObj;
79         ok(hres == S_OK,"%s: OCFI returns 0x%08lx instead of S_OK.\n",
80                 test_name, hres);
81         ok(pvObj != NULL,"%s: OCFI returns NULL.\n", test_name);
82
83         /* Read back size.  Hi part was ignored. */
84         hres = IFont_get_Size(ifnt, &psize);
85         ok(hres == S_OK,"%s: IFont_get_size returns 0x%08lx instead of S_OK.\n",
86                 test_name, hres);
87         ok(S(psize).Lo == lo_size && S(psize).Hi == 0,
88                 "%s: get_Size: Lo=%ld, Hi=%ld; expected Lo=%ld, Hi=%ld.\n",
89                 test_name, S(psize).Lo, S(psize).Hi, lo_size, 0L);
90
91         /* Change ratio, check size unchanged.  Standard is 72, 2540. */
92         hres = IFont_SetRatio(ifnt, ratio_logical, ratio_himetric);
93         ok(hres == S_OK,"%s: IFont_SR returns 0x%08lx instead of S_OK.\n",
94                 test_name, hres);
95         hres = IFont_get_Size(ifnt, &psize);
96         ok(hres == S_OK,"%s: IFont_get_size returns 0x%08lx instead of S_OK.\n",
97                 test_name, hres);
98         ok(S(psize).Lo == lo_size && S(psize).Hi == 0,
99                 "%s: gS after SR: Lo=%ld, Hi=%ld; expected Lo=%ld, Hi=%ld.\n",
100                 test_name, S(psize).Lo, S(psize).Hi, lo_size, 0L);
101
102         /* Check hFont size with this ratio.  This tests an important   */
103         /* conversion for which MSDN is very wrong.                     */
104         hres = IFont_get_hFont (ifnt, &hfont);
105         ok(hres == S_OK, "%s: IFont_get_hFont returns 0x%08lx instead of S_OK.\n",
106                 test_name, hres);
107         hres = GetObject (hfont, sizeof(LOGFONT), &lf);
108         ok(lf.lfHeight == hfont_height,
109                 "%s: hFont has lf.lfHeight=%ld, expected %ld.\n",
110                 test_name, lf.lfHeight, hfont_height);
111
112         /* Free IFont. */
113         IFont_Release(ifnt);
114 }
115
116 void test_QueryInterface(void)
117 {
118         LPVOID pvObj = NULL;
119         HRESULT hres;
120         IFont*  font = NULL;
121
122         hres = pOleCreateFontIndirect(NULL, &IID_IFont, &pvObj);
123         font = pvObj;
124
125         ok(hres == S_OK,"OCFI (NULL,..) does not return 0, but 0x%08lx\n",hres);
126         ok(font != NULL,"OCFI (NULL,..) returns NULL, instead of !NULL\n");
127
128         pvObj = NULL;
129         hres = IFont_QueryInterface( font, &IID_IFont, &pvObj);
130
131         ok(hres == S_OK,"IFont_QI does not return S_OK, but 0x%08lx\n", hres);
132         ok(pvObj != NULL,"IFont_QI does return NULL, instead of a ptr\n");
133
134         IFont_Release(font);
135 }
136
137 void test_type_info(void)
138 {
139         LPVOID pvObj = NULL;
140         HRESULT hres;
141         IFontDisp*  fontdisp = NULL;
142         ITypeInfo* pTInfo;
143         WCHAR name_Name[] = {'N','a','m','e',0};
144         BSTR names[3];
145         UINT n;
146         LCID en_us = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),
147                 SORT_DEFAULT);
148         DISPPARAMS dispparams;
149         VARIANT varresult;
150
151         pOleCreateFontIndirect(NULL, &IID_IFontDisp, &pvObj);
152         fontdisp = pvObj;
153
154         hres = IFontDisp_GetTypeInfo(fontdisp, 0, en_us, &pTInfo);
155         ok(hres == S_OK, "GTI returned 0x%08lx instead of S_OK.\n", hres);
156         ok(pTInfo != NULL, "GTI returned NULL.\n");
157
158         hres = ITypeInfo_GetNames(pTInfo, DISPID_FONT_NAME, names, 3, &n);
159         ok(hres == S_OK, "GetNames returned 0x%08lx instead of S_OK.\n", hres);
160         ok(n == 1, "GetNames returned %d names instead of 1.\n", n);
161         ok(!lstrcmpiW(names[0],name_Name), "DISPID_FONT_NAME doesn't get 'Names'.\n");
162
163         ITypeInfo_Release(pTInfo);
164
165         dispparams.cNamedArgs = 0;
166         dispparams.rgdispidNamedArgs = NULL;
167         dispparams.cArgs = 0;
168         dispparams.rgvarg = NULL;
169         VariantInit(&varresult);
170         hres = IFontDisp_Invoke(fontdisp, DISPID_FONT_NAME, &IID_NULL,
171             LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult,
172             NULL, NULL);
173         ok(hres == S_OK, "IFontDisp_Invoke return 0x%08lx instead of S_OK.\n", hres);
174         VariantClear(&varresult);
175
176         IFontDisp_Release(fontdisp);
177 }
178
179 static HRESULT WINAPI FontEventsDisp_QueryInterface(
180         IFontEventsDisp *iface,
181     /* [in] */ REFIID riid,
182     /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
183 {
184     if (IsEqualIID(riid, &IID_IFontEventsDisp) || IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch))
185     {
186         IUnknown_AddRef(iface);
187         *ppvObject = iface;
188         return S_OK;
189     }
190     else
191     {
192         *ppvObject = NULL;
193         return E_NOINTERFACE;
194     }
195 }
196
197 static ULONG WINAPI FontEventsDisp_AddRef(
198     IFontEventsDisp *iface)
199 {
200     return 2;
201 }
202
203 static ULONG WINAPI FontEventsDisp_Release(
204         IFontEventsDisp *iface)
205 {
206     return 1;
207 }
208
209 static int fonteventsdisp_invoke_called = 0;
210
211 static HRESULT WINAPI FontEventsDisp_Invoke(
212         IFontEventsDisp __RPC_FAR * iface,
213     /* [in] */ DISPID dispIdMember,
214     /* [in] */ REFIID riid,
215     /* [in] */ LCID lcid,
216     /* [in] */ WORD wFlags,
217     /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
218     /* [out] */ VARIANT __RPC_FAR *pVarResult,
219     /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
220     /* [out] */ UINT __RPC_FAR *puArgErr)
221 {
222     static const WCHAR wszBold[] = {'B','o','l','d',0};
223     ok(wFlags == INVOKE_FUNC, "invoke flags should have been INVOKE_FUNC instead of 0x%x\n", wFlags);
224     ok(dispIdMember == DISPID_FONT_CHANGED, "dispIdMember should have been DISPID_FONT_CHANGED instead of 0x%lx\n", dispIdMember);
225     ok(pDispParams->cArgs == 1, "pDispParams->cArgs should have been 1 instead of %d\n", pDispParams->cArgs);
226     ok(V_VT(&pDispParams->rgvarg[0]) == VT_BSTR, "VT of first param should have been VT_BSTR instead of %d\n", V_VT(&pDispParams->rgvarg[0]));
227     ok(!lstrcmpW(V_BSTR(&pDispParams->rgvarg[0]), wszBold), "String in first param should have been \"Bold\"\n");
228
229     fonteventsdisp_invoke_called++;
230     return S_OK;
231 }
232
233 static IFontEventsDispVtbl FontEventsDisp_Vtbl =
234 {
235     FontEventsDisp_QueryInterface,
236     FontEventsDisp_AddRef,
237     FontEventsDisp_Release,
238     NULL,
239     NULL,
240     NULL,
241     FontEventsDisp_Invoke
242 };
243
244 static IFontEventsDisp FontEventsDisp = { &FontEventsDisp_Vtbl };
245
246 static void test_font_events_disp(void)
247 {
248     IFont *pFont;
249     IFont *pFont2;
250     IConnectionPointContainer *pCPC;
251     IConnectionPoint *pCP;
252     FONTDESC fontdesc;
253     HRESULT hr;
254     DWORD dwCookie;
255     static const WCHAR wszMSSansSerif[] = {'M','S',' ','S','a','n','s',' ','S','e','r','i','f',0};
256
257     fontdesc.cbSizeofstruct = sizeof(fontdesc);
258     fontdesc.lpstrName = (LPOLESTR)wszMSSansSerif;
259     fontdesc.cySize.int64 = 12 * 10000; /* 12 pt */
260     fontdesc.sWeight = FW_NORMAL;
261     fontdesc.sCharset = 0;
262     fontdesc.fItalic = FALSE;
263     fontdesc.fUnderline = FALSE;
264     fontdesc.fStrikethrough = FALSE;
265
266     hr = pOleCreateFontIndirect(&fontdesc, &IID_IFont, (void **)&pFont);
267     ok_ole_success(hr, "OleCreateFontIndirect");
268
269     hr = IFont_QueryInterface(pFont, &IID_IConnectionPointContainer, (void **)&pCPC);
270     ok_ole_success(hr, "IFont_QueryInterface");
271
272     hr = IConnectionPointContainer_FindConnectionPoint(pCPC, &IID_IFontEventsDisp, &pCP);
273     ok_ole_success(hr, "IConnectionPointContainer_FindConnectionPoint");
274     IConnectionPointContainer_Release(pCPC);
275
276     hr = IConnectionPoint_Advise(pCP, (IUnknown *)&FontEventsDisp, &dwCookie);
277     ok_ole_success(hr, "IConnectionPoint_Advise");
278     IConnectionPoint_Release(pCP);
279
280     hr = IFont_put_Bold(pFont, TRUE);
281     ok_ole_success(hr, "IFont_put_Bold");
282
283     ok(fonteventsdisp_invoke_called == 1, "IFontEventDisp::Invoke wasn't called once\n");
284
285     hr = IFont_Clone(pFont, &pFont2);
286     ok_ole_success(hr, "IFont_Clone");
287     IFont_Release(pFont);
288
289     hr = IFont_put_Bold(pFont2, TRUE);
290     ok_ole_success(hr, "IFont_put_Bold");
291
292     /* this test shows that the notification routine isn't called again */
293     ok(fonteventsdisp_invoke_called == 1, "IFontEventDisp::Invoke wasn't called once\n");
294
295     IFont_Release(pFont2);
296 }
297
298 START_TEST(olefont)
299 {
300         hOleaut32 = LoadLibraryA("oleaut32.dll");    
301         pOleCreateFontIndirect = (void*)GetProcAddress(hOleaut32, "OleCreateFontIndirect");
302         if (!pOleCreateFontIndirect)
303             return;
304
305         test_QueryInterface();
306         test_type_info();
307
308         /* Test various size operations and conversions. */
309         /* Add more as needed. */
310         test_ifont_sizes(180000, 0, 72, 2540, -18, "default");
311         test_ifont_sizes(180000, 0, 144, 2540, -36, "ratio1");          /* change ratio */
312         test_ifont_sizes(180000, 0, 72, 1270, -36, "ratio2");           /* 2nd part of ratio */
313
314         /* These depend on details of how IFont rounds sizes internally. */
315         /* test_ifont_sizes(0, 0, 72, 2540, 0, "zero size");    */      /* zero size */
316         /* test_ifont_sizes(186000, 0, 72, 2540, -19, "rounding"); */   /* test rounding */
317
318         test_font_events_disp();
319 }