1 /*
2  * DrawText tests
3  *
4  * Copyright (c) 2004 Zach Gorman
5  * Copyright 2007,2016 Dmitry Timoshkov
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 
22 #include <assert.h>
23 
24 #include "wine/test.h"
25 #include "winbase.h"
26 #include "wingdi.h"
27 #include "winuser.h"
28 #include "winerror.h"
29 #include "winnls.h"
30 
31 #define MODIFIED(rect) (rect.left == 10 && rect.right != 100 && rect.top == 10 && rect.bottom != 100)
32 #define EMPTY(rect) (rect.left == rect.right && rect.bottom == rect.top)
33 
34 static void test_DrawTextCalcRect(void)
35 {
36     HWND hwnd;
37     HDC hdc;
38     HFONT hFont, hOldFont;
39     LOGFONTA lf;
40     static CHAR text[] = "Example text for testing DrawText in "
41       "MM_HIENGLISH mode";
42     static WCHAR textW[] = {'W','i','d','e',' ','c','h','a','r',' ',
43         's','t','r','i','n','g','\0'};
44     static CHAR emptystring[] = "";
45     static WCHAR emptystringW[] = { 0 };
46     static CHAR wordbreak_text[] = "line1 line2";
47     static WCHAR wordbreak_textW[] = {'l','i','n','e','1',' ','l','i','n','e','2',0};
48     static char tabstring[] = "one\ttwo";
49     INT textlen, textheight, heightcheck;
50     RECT rect = { 0, 0, 100, 0 }, rect2;
51     BOOL ret;
52     DRAWTEXTPARAMS dtp;
53     BOOL conform_xp = TRUE;
54 
55     /* Initialization */
56     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP,
57                            0, 0, 200, 200, 0, 0, 0, NULL);
58     ok(hwnd != 0, "CreateWindowExA error %u\n", GetLastError());
59     hdc = GetDC(hwnd);
60     ok(hdc != 0, "GetDC error %u\n", GetLastError());
61     trace("hdc %p\n", hdc);
62     textlen = lstrlenA(text);
63 
64     /* LOGFONT initialization */
65     memset(&lf, 0, sizeof(lf));
66     lf.lfCharSet = ANSI_CHARSET;
67     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
68     lf.lfWeight = FW_DONTCARE;
69     lf.lfHeight = 0; /* mapping mode dependent */
70     lf.lfQuality = DEFAULT_QUALITY;
71     lstrcpyA(lf.lfFaceName, "Arial");
72 
73     /* DrawText in MM_HIENGLISH with DT_CALCRECT */
74     SetMapMode(hdc, MM_HIENGLISH);
75     lf.lfHeight = 100 * 9 / 72; /* 9 point */
76     hFont = CreateFontIndirectA(&lf);
77     ok(hFont != 0, "CreateFontIndirectA error %u\n",
78        GetLastError());
79     hOldFont = SelectObject(hdc, hFont);
80 
81     textheight = DrawTextA(hdc, text, textlen, &rect, DT_CALCRECT |
82        DT_EXTERNALLEADING | DT_WORDBREAK | DT_NOCLIP | DT_LEFT |
83        DT_NOPREFIX);
84     ok( textheight, "DrawTextA error %u\n", GetLastError());
85 
86     trace("MM_HIENGLISH rect.bottom %d\n", rect.bottom);
87     ok(rect.bottom < 0, "In MM_HIENGLISH, DrawText with "
88        "DT_CALCRECT should return a negative rectangle bottom. "
89        "(bot=%d)\n", rect.bottom);
90 
91     SelectObject(hdc, hOldFont);
92     ret = DeleteObject(hFont);
93     ok( ret, "DeleteObject error %u\n", GetLastError());
94 
95 
96     /* DrawText in MM_TEXT with DT_CALCRECT */
97     SetMapMode(hdc, MM_TEXT);
98     lf.lfHeight = -MulDiv(9, GetDeviceCaps(hdc,
99        LOGPIXELSY), 72); /* 9 point */
100     hFont = CreateFontIndirectA(&lf);
101     ok(hFont != 0, "CreateFontIndirectA error %u\n",
102        GetLastError());
103     hOldFont = SelectObject(hdc, hFont);
104 
105     textheight = DrawTextA(hdc, text, textlen, &rect, DT_CALCRECT |
106        DT_EXTERNALLEADING | DT_WORDBREAK | DT_NOCLIP | DT_LEFT |
107        DT_NOPREFIX);
108     ok( textheight, "DrawTextA error %u\n", GetLastError());
109 
110     trace("MM_TEXT rect.bottom %d\n", rect.bottom);
111     ok(rect.bottom > 0, "In MM_TEXT, DrawText with DT_CALCRECT "
112        "should return a positive rectangle bottom. (bot=%d)\n",
113        rect.bottom);
114 
115     /* empty or null text should in some cases calc an empty rectangle */
116 
117     SetRect( &rect, 10,10, 100, 100);
118     heightcheck = textheight = DrawTextExA(hdc, text, 0, &rect, DT_CALCRECT, NULL );
119     ok(!IsRectEmpty(&rect) && !MODIFIED(rect),
120         "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect));
121     ok(textheight==0,"Got textheight from DrawTextExA\n");
122 
123     SetRect( &rect, 10,10, 100, 100);
124     textheight = DrawTextA(hdc, text, 0, &rect, DT_CALCRECT);
125     ok(!IsRectEmpty(&rect) && !MODIFIED(rect),
126         "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect));
127     if (conform_xp)
128         ok(textheight==0,"Got textheight from DrawTextA\n");
129     ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
130 
131     SetRect( &rect, 10,10, 100, 100);
132     SetLastError( 0);
133     heightcheck = textheight = DrawTextExA(hdc, emptystring, -1, &rect, DT_CALCRECT, NULL );
134     ok(EMPTY(rect), "rectangle should be empty got %s\n", wine_dbgstr_rect(&rect));
135     ok(textheight!=0,"Failed to get textheight from DrawTextExA\n");
136 
137     SetRect( &rect, 10,10, 100, 100);
138     textheight = DrawTextA(hdc, emptystring, -1, &rect, DT_CALCRECT);
139     ok(EMPTY(rect), "rectangle should be empty got %s\n", wine_dbgstr_rect(&rect));
140     ok(textheight!=0,"Failed to get textheight from DrawTextA\n");
141     ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
142 
143     SetRect( &rect, 10,10, 100, 100);
144     SetLastError( 0);
145     heightcheck = textheight = DrawTextExA(hdc, NULL, -1, &rect, DT_CALCRECT, NULL );
146     ok(EMPTY(rect), "rectangle should be empty got %s\n", wine_dbgstr_rect(&rect));
147     if (!textheight) /* Windows NT 4 */
148     {
149         if (conform_xp)
150             win_skip("XP conformity failed, skipping XP tests. Probably winNT\n");
151         conform_xp = FALSE;
152     }
153     else
154         ok(textheight!=0,"Failed to get textheight from DrawTextExA\n");
155 
156     SetRect( &rect, 10,10, 100, 100);
157     textheight = DrawTextA(hdc, NULL, -1, &rect, DT_CALCRECT);
158     ok(EMPTY(rect), "rectangle should be empty got %s\n", wine_dbgstr_rect(&rect));
159     if (conform_xp)
160         ok(textheight!=0,"Failed to get textheight from DrawTextA\n");
161     ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
162 
163     SetRect( &rect, 10,10, 100, 100);
164     heightcheck = textheight = DrawTextExA(hdc, NULL, 0, &rect, DT_CALCRECT, NULL );
165     ok(!IsRectEmpty(&rect) && !MODIFIED(rect),
166         "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect));
167     if (conform_xp)
168         ok(textheight==0,"Got textheight from DrawTextExA\n");
169 
170     SetRect( &rect, 10,10, 100, 100);
171     textheight = DrawTextA(hdc, NULL, 0, &rect, DT_CALCRECT);
172     ok(!IsRectEmpty(&rect) && !MODIFIED(rect),
173         "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect));
174     if (conform_xp)
175         ok(textheight==0,"Got textheight from DrawTextA\n");
176     ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
177 
178     /* DT_SINGLELINE tests */
179 
180     SetRect( &rect, 10,10, 100, 100);
181     heightcheck = textheight = DrawTextExA(hdc, text, 0, &rect, DT_CALCRECT|DT_SINGLELINE, NULL );
182     ok(!IsRectEmpty(&rect) && !MODIFIED(rect),
183         "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect));
184     if (conform_xp)
185         ok(textheight==0,"Got textheight from DrawTextExA\n");
186 
187     SetRect( &rect, 10,10, 100, 100);
188     textheight = DrawTextA(hdc, text, 0, &rect, DT_CALCRECT|DT_SINGLELINE);
189     ok(!IsRectEmpty(&rect) && !MODIFIED(rect),
190         "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect));
191     if (conform_xp)
192         ok(textheight==0,"Got textheight from DrawTextA\n");
193     ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
194 
195     SetRect( &rect, 10,10, 100, 100);
196     SetLastError( 0);
197     heightcheck = textheight = DrawTextExA(hdc, emptystring, -1, &rect, DT_CALCRECT|DT_SINGLELINE, NULL );
198     ok(!EMPTY(rect) && MODIFIED(rect), "rectangle should be modified got %s\n",
199        wine_dbgstr_rect(&rect));
200     ok(textheight!=0,"Failed to get textheight from DrawTextExA\n");
201 
202     SetRect( &rect, 10,10, 100, 100);
203     textheight = DrawTextA(hdc, emptystring, -1, &rect, DT_CALCRECT|DT_SINGLELINE);
204     ok(!EMPTY(rect) && MODIFIED (rect), "rectangle should be modified got %s\n",
205        wine_dbgstr_rect(&rect));
206     ok(textheight!=0,"Failed to get textheight from DrawTextA\n");
207     ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
208 
209     SetRect( &rect, 10,10, 100, 100);
210     SetLastError( 0);
211     heightcheck = textheight = DrawTextExA(hdc, NULL, -1, &rect, DT_CALCRECT|DT_SINGLELINE, NULL );
212     ok(!EMPTY(rect) && MODIFIED(rect), "rectangle should be modified got %s\n",
213        wine_dbgstr_rect(&rect));
214     if (conform_xp)
215         ok(textheight!=0,"Failed to get textheight from DrawTextExA\n");
216 
217     SetRect( &rect, 10,10, 100, 100);
218     textheight = DrawTextA(hdc, NULL, -1, &rect, DT_CALCRECT|DT_SINGLELINE);
219     ok(!EMPTY(rect) && MODIFIED(rect), "rectangle should be modified got %s\n",
220        wine_dbgstr_rect(&rect));
221     if (conform_xp)
222         ok(textheight!=0,"Failed to get textheight from DrawTextA\n");
223     ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
224 
225     SetRect( &rect, 10,10, 100, 100);
226     heightcheck = textheight = DrawTextExA(hdc, NULL, 0, &rect, DT_CALCRECT|DT_SINGLELINE, NULL );
227     ok(!IsRectEmpty(&rect) && !MODIFIED(rect),
228         "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect));
229     if (conform_xp)
230         ok(textheight==0,"Got textheight from DrawTextExA\n");
231 
232     SetRect( &rect, 10,10, 100, 100);
233     textheight = DrawTextA(hdc, NULL, 0, &rect, DT_CALCRECT|DT_SINGLELINE);
234     ok(!IsRectEmpty(&rect) && !MODIFIED(rect),
235         "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect));
236     if (conform_xp)
237         ok(textheight==0,"Got textheight from DrawTextA\n");
238     ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
239 
240     /* further tests with  0 count, NULL and empty strings */
241     heightcheck = textheight = DrawTextA(hdc, text, 0, &rect, 0);
242     if (conform_xp)
243         ok(textheight==0,"Got textheight from DrawTextA\n");
244     textheight = DrawTextExA(hdc, text, 0, &rect, 0, NULL );
245     if (conform_xp)
246         ok(textheight==0,"Got textheight from DrawTextExA\n");
247     ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
248     heightcheck = textheight = DrawTextA(hdc, emptystring, 0, &rect, 0);
249     if (conform_xp)
250         ok(textheight==0,"Got textheight from DrawTextA\n");
251     textheight = DrawTextExA(hdc, emptystring, 0, &rect, 0, NULL );
252     if (conform_xp)
253         ok(textheight==0,"Got textheight from DrawTextExA\n");
254     ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
255     heightcheck = textheight = DrawTextA(hdc, NULL, 0, &rect, 0);
256     if (conform_xp)
257         ok(textheight==0,"Got textheight from DrawTextA\n");
258     textheight = DrawTextExA(hdc, NULL, 0, &rect, 0, NULL );
259     if (conform_xp)
260         ok(textheight==0,"Got textheight from DrawTextExA\n");
261     ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
262     heightcheck = textheight = DrawTextA(hdc, emptystring, -1, &rect, 0);
263     ok(textheight!=0,"Failed to get textheight from DrawTextA\n");
264     textheight = DrawTextExA(hdc, emptystring, -1, &rect, 0, NULL );
265     ok(textheight!=0,"Failed to get textheight from DrawTextExA\n");
266     ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
267     heightcheck = textheight = DrawTextA(hdc, NULL, -1, &rect, 0);
268     if (conform_xp)
269         ok(textheight!=0,"Failed to get textheight from DrawTextA\n");
270     textheight = DrawTextExA(hdc, NULL, -1, &rect, 0, NULL );
271     if (conform_xp)
272         ok(textheight!=0,"Failed to get textheight from DrawTextExA\n");
273     ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
274     heightcheck = textheight = DrawTextA(hdc, NULL, 10, &rect, 0);
275     ok(textheight==0,"Got textheight from DrawTextA\n");
276     textheight = DrawTextExA(hdc, NULL, 10, &rect, 0, NULL );
277     ok(textheight==0,"Got textheight from DrawTextA\n");
278     ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
279 
280     /* When offset to top is zero, return 1 */
281     SetRectEmpty(&rect);
282     textheight = DrawTextExW(hdc, textW, -1, &rect, DT_SINGLELINE | DT_CALCRECT | DT_BOTTOM, NULL);
283     ok(textheight == 1, "Expect returned height:1 got:%d\n", textheight);
284 
285     SetRect(&rect, 0, 100, 0, 100);
286     textheight = DrawTextExW(hdc, textW, -1, &rect, DT_SINGLELINE | DT_CALCRECT | DT_BOTTOM, NULL);
287     ok(textheight == 1, "Expect returned height:1 got:%d\n", textheight);
288 
289     SetRectEmpty(&rect);
290     textheight = DrawTextExW(hdc, textW, -1, &rect, DT_SINGLELINE | DT_CALCRECT | DT_TOP, NULL);
291     /* Set top to text height and bottom zero, so bottom of drawn text to top is zero when DT_VCENTER is used */
292     SetRect(&rect, 0, textheight, 0, 0);
293     textheight = DrawTextExW(hdc, textW, -1, &rect, DT_SINGLELINE | DT_CALCRECT | DT_VCENTER, NULL);
294     ok(textheight == 1, "Expect returned height:1 got:%d\n", textheight);
295 
296     /* invalid dtp size test */
297     dtp.cbSize = -1; /* Invalid */
298     dtp.uiLengthDrawn = 1337;
299     textheight = DrawTextExA(hdc, text, 0, &rect, 0, &dtp);
300     ok(textheight==0,"Got textheight from DrawTextExA\n");
301     ok(dtp.uiLengthDrawn==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp.uiLengthDrawn);
302     dtp.uiLengthDrawn = 1337;
303     textheight = DrawTextExA(hdc, emptystring, 0, &rect, 0, &dtp);
304     ok(textheight==0,"Got textheight from DrawTextExA\n");
305     ok(dtp.uiLengthDrawn==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp.uiLengthDrawn);
306     dtp.uiLengthDrawn = 1337;
307     textheight = DrawTextExA(hdc, NULL, 0, &rect, 0, &dtp);
308     ok(textheight==0,"Got textheight from DrawTextExA\n");
309     ok(dtp.uiLengthDrawn==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp.uiLengthDrawn);
310     dtp.uiLengthDrawn = 1337;
311     textheight = DrawTextExA(hdc, emptystring, -1, &rect, 0, &dtp);
312     ok(textheight==0,"Got textheight from DrawTextExA\n");
313     ok(dtp.uiLengthDrawn==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp.uiLengthDrawn);
314     dtp.uiLengthDrawn = 1337;
315     textheight = DrawTextExA(hdc, NULL, -1, &rect, 0, &dtp);
316     ok(textheight==0,"Got textheight from DrawTextExA\n");
317     ok(dtp.uiLengthDrawn==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp.uiLengthDrawn);
318 
319     /* Margin calculations */
320     dtp.cbSize = sizeof(dtp);
321     dtp.iLeftMargin = 0;
322     dtp.iRightMargin = 0;
323     SetRectEmpty(&rect);
324     DrawTextExA(hdc, text, -1, &rect, DT_CALCRECT, &dtp);
325     textlen = rect.right; /* Width without margin */
326     dtp.iLeftMargin = 8;
327     SetRectEmpty(&rect);
328     DrawTextExA(hdc, text, -1, &rect, DT_CALCRECT, &dtp);
329     ok(rect.right==dtp.iLeftMargin+textlen  ,"Incorrect left margin calculated  rc(%d,%d)\n", rect.left, rect.right);
330     dtp.iLeftMargin = 0;
331     dtp.iRightMargin = 8;
332     SetRectEmpty(&rect);
333     DrawTextExA(hdc, text, -1, &rect, DT_CALCRECT, &dtp);
334     ok(rect.right==dtp.iRightMargin+textlen  ,"Incorrect right margin calculated rc(%d,%d)\n", rect.left, rect.right);
335 
336     /* Wide char versions */
337     SetRect( &rect, 10,10, 100, 100);
338     SetLastError( 0);
339     heightcheck = textheight = DrawTextExW(hdc, textW, 0, &rect, DT_CALCRECT, NULL );
340     if( GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) {
341         ok(!IsRectEmpty(&rect) && !MODIFIED(rect),
342             "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect));
343         ok(textheight!=0,"Failed to get textheight from DrawTextExW\n");
344 
345         SetRect( &rect, 10,10, 100, 100);
346         textheight = DrawTextW(hdc, textW, 0, &rect, DT_CALCRECT);
347         ok(!IsRectEmpty(&rect) && !MODIFIED(rect),
348             "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect));
349         ok(textheight!=0,"Failed to get textheight from DrawTextW\n");
350         ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
351 
352         SetRect( &rect, 10,10, 100, 100);
353         heightcheck = textheight = DrawTextExW(hdc, emptystringW, -1, &rect, DT_CALCRECT, NULL );
354         ok(EMPTY(rect), "rectangle should be empty got %s\n", wine_dbgstr_rect(&rect));
355         ok(textheight!=0,"Failed to get textheight from DrawTextExW\n");
356 
357         SetRect( &rect, 10,10, 100, 100);
358         textheight = DrawTextW(hdc, emptystringW, -1, &rect, DT_CALCRECT);
359         ok(EMPTY(rect), "rectangle should be empty got %s\n", wine_dbgstr_rect(&rect));
360         ok(textheight!=0,"Failed to get textheight from DrawTextW\n");
361         ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
362 
363         SetRect( &rect, 10,10, 100, 100);
364         heightcheck = textheight = DrawTextExW(hdc, NULL, 0, &rect, DT_CALCRECT, NULL );
365         ok(!IsRectEmpty(&rect) && !MODIFIED(rect),
366             "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect));
367         if (textheight) /* windows 2000 */
368         {
369             if (conform_xp)
370                 win_skip("XP conformity failed, skipping XP tests. Probably win 2000\n");
371             conform_xp = FALSE;
372         }
373         else
374             ok(textheight==0,"Got textheight from DrawTextExW\n");
375 
376         SetRect( &rect, 10,10, 100, 100);
377         textheight = DrawTextW(hdc, NULL, 0, &rect, DT_CALCRECT);
378         ok(!IsRectEmpty(&rect) && !MODIFIED(rect),
379             "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect));
380         if (conform_xp)
381             ok(textheight==0,"Got textheight from DrawTextW\n");
382         ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
383 
384         if (conform_xp) {
385             /* Crashes on NT4 */
386             SetRect( &rect, 10,10, 100, 100);
387             heightcheck = textheight = DrawTextExW(hdc, NULL, -1, &rect, DT_CALCRECT, NULL );
388             ok(!IsRectEmpty(&rect) && !MODIFIED(rect),
389                 "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect));
390             ok(textheight==0,"Got textheight from DrawTextExW\n");
391 
392             SetRect( &rect, 10,10, 100, 100);
393             textheight = DrawTextW(hdc, NULL, -1, &rect, DT_CALCRECT);
394             ok(!IsRectEmpty(&rect) && !MODIFIED(rect),
395                 "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect));
396             ok(textheight==0,"Got textheight from DrawTextW\n");
397             ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
398         }
399 
400 
401         /* DT_SINGLELINE tests */
402 
403         heightcheck = textheight = DrawTextExW(hdc, textW, 0, &rect, DT_CALCRECT|DT_SINGLELINE, NULL );
404         ok(!IsRectEmpty(&rect) && !MODIFIED(rect),
405             "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect));
406         ok(textheight!=0,"Failed to get textheight from DrawTextExW\n");
407 
408         SetRect( &rect, 10,10, 100, 100);
409         textheight = DrawTextW(hdc, textW, 0, &rect, DT_CALCRECT|DT_SINGLELINE);
410         ok(!IsRectEmpty(&rect) && !MODIFIED(rect),
411             "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect));
412         ok(textheight!=0,"Failed to get textheight from DrawTextW\n");
413         ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
414 
415         SetRect( &rect, 10,10, 100, 100);
416         heightcheck = textheight = DrawTextExW(hdc, emptystringW, -1, &rect, DT_CALCRECT|DT_SINGLELINE, NULL );
417         ok(!EMPTY(rect) && MODIFIED(rect), "rectangle should be modified got %s\n",
418            wine_dbgstr_rect(&rect));
419         ok(textheight!=0,"Failed to get textheight from DrawTextExW\n");
420 
421         SetRect( &rect, 10,10, 100, 100);
422         textheight = DrawTextW(hdc, emptystringW, -1, &rect, DT_CALCRECT|DT_SINGLELINE);
423         ok(!EMPTY(rect) && MODIFIED(rect), "rectangle should be modified got %s\n",
424            wine_dbgstr_rect(&rect));
425         ok(textheight!=0,"Failed to get textheight from DrawTextW\n");
426         ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
427 
428         if (conform_xp) {
429             /* Crashes on NT4 */
430             SetRect( &rect, 10,10, 100, 100);
431             heightcheck = textheight = DrawTextExW(hdc, NULL, -1, &rect, DT_CALCRECT|DT_SINGLELINE, NULL );
432             ok(!IsRectEmpty(&rect) && !MODIFIED(rect),
433                 "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect));
434             ok(textheight==0,"Got textheight from DrawTextExW\n");
435 
436             SetRect( &rect, 10,10, 100, 100);
437             textheight = DrawTextW(hdc, NULL, -1, &rect, DT_CALCRECT|DT_SINGLELINE);
438             ok(!IsRectEmpty(&rect) && !MODIFIED(rect),
439                 "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect));
440             ok(textheight==0,"Got textheight from DrawTextW\n");
441             ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
442         }
443 
444         SetRect( &rect, 10,10, 100, 100);
445         heightcheck = textheight = DrawTextExW(hdc, NULL, 0, &rect, DT_CALCRECT|DT_SINGLELINE, NULL );
446         ok(!IsRectEmpty(&rect) && !MODIFIED(rect),
447             "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect));
448         if (conform_xp)
449             ok(textheight==0,"Got textheight from DrawTextExW\n");
450 
451         SetRect( &rect, 10,10, 100, 100);
452         textheight = DrawTextW(hdc, NULL, 0, &rect, DT_CALCRECT|DT_SINGLELINE);
453         ok(!IsRectEmpty(&rect) && !MODIFIED(rect),
454             "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect));
455         if (conform_xp)
456             ok(textheight==0,"Got textheight from DrawTextW\n");
457         ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
458 
459         /* further tests with NULL and empty strings */
460         heightcheck = textheight = DrawTextW(hdc, textW, 0, &rect, 0);
461         ok(textheight!=0,"Failed to get textheight from DrawTextW\n");
462         textheight = DrawTextExW(hdc, textW, 0, &rect, 0, NULL );
463         ok(textheight!=0,"Failed to get textheight from DrawTextExW\n");
464         ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
465         heightcheck = textheight = DrawTextW(hdc, emptystringW, 0, &rect, 0);
466         ok(textheight!=0,"Failed to get textheight from DrawTextW\n");
467         textheight = DrawTextExW(hdc, emptystringW, 0, &rect, 0, NULL );
468         ok(textheight!=0,"Failed to get textheight from DrawTextExW\n");
469         ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
470         heightcheck = textheight = DrawTextW(hdc, NULL, 0, &rect, 0);
471         if (conform_xp)
472             ok(textheight==0,"Got textheight from DrawTextW\n");
473         textheight = DrawTextExW(hdc, NULL, 0, &rect, 0, NULL );
474         if (conform_xp)
475             ok(textheight==0,"Got textheight from DrawTextExW\n");
476         ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
477         heightcheck = textheight = DrawTextW(hdc, emptystringW, -1, &rect, 0);
478         ok(textheight!=0,"Failed to get textheight from DrawTextW\n");
479         textheight = DrawTextExW(hdc, emptystringW, -1, &rect, 0, NULL );
480         ok(textheight!=0,"Failed to get textheight from DrawTextExW\n");
481         ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
482         if (conform_xp) {
483             /* Crashes on NT4 */
484             heightcheck = textheight = DrawTextW(hdc, NULL, -1, &rect, 0);
485             ok(textheight==0,"Got textheight from DrawTextW\n");
486             textheight = DrawTextExW(hdc, NULL, -1, &rect, 0, NULL );
487             ok(textheight==0,"Got textheight from DrawTextExW\n");
488             ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
489             heightcheck = textheight = DrawTextW(hdc, NULL, 10, &rect, 0);
490             ok(textheight==0,"Got textheight from DrawTextW\n");
491             textheight = DrawTextExW(hdc, NULL, 10, &rect, 0, NULL );
492             ok(textheight==0,"Got textheight from DrawTextW\n");
493             ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
494         }
495 
496         dtp.cbSize = -1; /* Invalid */
497         dtp.uiLengthDrawn = 1337;
498         textheight = DrawTextExW(hdc, textW, 0, &rect, 0, &dtp);
499         ok(textheight!=0,"Failed to get textheight from DrawTextExW\n");
500         ok(dtp.uiLengthDrawn==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp.uiLengthDrawn);
501         dtp.uiLengthDrawn = 1337;
502         textheight = DrawTextExW(hdc, emptystringW, 0, &rect, 0, &dtp);
503         if (conform_xp)
504             ok(textheight==0,"Got textheight from DrawTextExW\n");
505         ok(dtp.uiLengthDrawn==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp.uiLengthDrawn);
506         dtp.uiLengthDrawn = 1337;
507         textheight = DrawTextExW(hdc, NULL, 0, &rect, 0, &dtp);
508         if (conform_xp)
509             ok(textheight==0,"Got textheight from DrawTextExW\n");
510         ok(dtp.uiLengthDrawn==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp.uiLengthDrawn);
511         dtp.uiLengthDrawn = 1337;
512         textheight = DrawTextExW(hdc, emptystringW, -1, &rect, 0, &dtp);
513         ok(textheight==0,"Got textheight from DrawTextExW\n");
514         ok(dtp.uiLengthDrawn==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp.uiLengthDrawn);
515         if (conform_xp) {
516             /* Crashes on NT4 */
517             dtp.uiLengthDrawn = 1337;
518             textheight = DrawTextExW(hdc, NULL, -1, &rect, 0, &dtp);
519             ok(textheight==0,"Got textheight from DrawTextExW\n");
520             ok(dtp.uiLengthDrawn==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp.uiLengthDrawn);
521         }
522     }
523 
524     /* More test cases from bug 12226 */
525     SetRectEmpty(&rect);
526     textheight = DrawTextA(hdc, emptystring, -1, &rect, DT_CALCRECT | DT_LEFT | DT_SINGLELINE);
527     ok(textheight, "DrawTextA error %u\n", GetLastError());
528     ok(0 == rect.left, "expected 0, got %d\n", rect.left);
529     ok(0 == rect.right, "expected 0, got %d\n", rect.right);
530     ok(0 == rect.top, "expected 0, got %d\n", rect.top);
531     ok(rect.bottom, "rect.bottom should not be 0\n");
532 
533     SetRectEmpty(&rect);
534     textheight = DrawTextW(hdc, emptystringW, -1, &rect, DT_CALCRECT | DT_LEFT | DT_SINGLELINE);
535     if (!textheight && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
536     {
537         win_skip( "DrawTextW not implemented\n" );
538     }
539     else
540     {
541         ok(textheight, "DrawTextW error %u\n", GetLastError());
542         ok(0 == rect.left, "expected 0, got %d\n", rect.left);
543         ok(0 == rect.right, "expected 0, got %d\n", rect.right);
544         ok(0 == rect.top, "expected 0, got %d\n", rect.top);
545         ok(rect.bottom, "rect.bottom should not be 0\n");
546     }
547 
548     SetRect(&rect, 0, 0, 1, 1);
549     heightcheck = DrawTextA(hdc, wordbreak_text, -1, &rect, DT_CALCRECT);
550     SetRect(&rect, 0, 0, 1, 1);
551     textheight = DrawTextA(hdc, wordbreak_text, -1, &rect, DT_CALCRECT | DT_WORDBREAK);
552     ok(textheight == heightcheck * 2, "Got unexpected textheight %d, expected %d.\n",
553        textheight, heightcheck * 2);
554     SetRect(&rect, 0, 0, 1, 1);
555     textheight = DrawTextA(hdc, wordbreak_text, -1, &rect, DT_CALCRECT | DT_WORDBREAK | DT_EDITCONTROL);
556     ok(textheight >= heightcheck * 6, "Got unexpected textheight %d, expected at least %d.\n",
557        textheight, heightcheck * 6);
558 
559     SetRect(&rect, 0, 0, 1, 1);
560     heightcheck = DrawTextW(hdc, wordbreak_textW, -1, &rect, DT_CALCRECT);
561     SetRect(&rect, 0, 0, 1, 1);
562     textheight = DrawTextW(hdc, wordbreak_textW, -1, &rect, DT_CALCRECT | DT_WORDBREAK);
563     ok(textheight == heightcheck * 2, "Got unexpected textheight %d, expected %d.\n",
564        textheight, heightcheck * 2);
565     SetRect(&rect, 0, 0, 1, 1);
566     textheight = DrawTextW(hdc, wordbreak_textW, -1, &rect, DT_CALCRECT | DT_WORDBREAK | DT_EDITCONTROL);
567     ok(textheight >= heightcheck * 6, "Got unexpected textheight %d, expected at least %d.\n",
568        textheight, heightcheck * 6);
569 
570     /* DT_TABSTOP | DT_EXPANDTABS tests */
571     SetRect( &rect, 0,0, 10, 10);
572     textheight = DrawTextA(hdc, tabstring, -1, &rect, DT_TABSTOP | DT_EXPANDTABS );
573     ok(textheight >= heightcheck, "Got unexpected textheight %d\n", textheight);
574 
575     SetRect( &rect, 0,0, 10, 10);
576     memset(&dtp, 0, sizeof(dtp));
577     dtp.cbSize = sizeof(dtp);
578     textheight = DrawTextExA(hdc, tabstring, -1, &rect, DT_CALCRECT, &dtp);
579     ok(textheight >= heightcheck, "Got unexpected textheight %d\n", textheight);
580     ok(dtp.iTabLength == 0, "invalid dtp.iTabLength = %i\n",dtp.iTabLength);
581 
582     SetRect( &rect2, 0,0, 10, 10);
583     memset(&dtp, 0, sizeof(dtp));
584     dtp.cbSize = sizeof(dtp);
585     textheight = DrawTextExA(hdc, tabstring, -1, &rect2, DT_CALCRECT | DT_TABSTOP | DT_EXPANDTABS, &dtp);
586     ok(textheight >= heightcheck, "Got unexpected textheight %d\n", textheight);
587     ok(dtp.iTabLength == 0, "invalid dtp.iTabLength = %i\n",dtp.iTabLength);
588     ok(rect.left == rect2.left && rect.right != rect2.right && rect.top == rect2.top && rect.bottom == rect2.bottom,
589        "incorrect rect %s rect2 %s\n", wine_dbgstr_rect(&rect), wine_dbgstr_rect(&rect2));
590 
591     SetRect( &rect, 0,0, 10, 10);
592     memset(&dtp, 0, sizeof(dtp));
593     dtp.cbSize = sizeof(dtp);
594     dtp.iTabLength = 8;
595     textheight = DrawTextExA(hdc, tabstring, -1, &rect, DT_CALCRECT | DT_TABSTOP | DT_EXPANDTABS, &dtp);
596     ok(textheight >= heightcheck, "Got unexpected textheight %d\n", textheight);
597     ok(dtp.iTabLength == 8, "invalid dtp.iTabLength = %i\n",dtp.iTabLength);
598     ok(rect.left == rect2.left, "unexpected value %d, got %d\n", rect.left, rect2.left);
599     /* XP, 2003 appear to not give the same values. */
600     ok(rect.right == rect2.right || broken(rect.right > rect2.right), "unexpected value %d, got %d\n",rect.right, rect2.right);
601     ok(rect.top == rect2.top, "unexpected value %d, got %d\n", rect.top, rect2.top);
602     ok(rect.bottom == rect2.bottom , "unexpected value %d, got %d\n", rect.bottom, rect2.bottom);
603 
604 
605     SelectObject(hdc, hOldFont);
606     ret = DeleteObject(hFont);
607     ok( ret, "DeleteObject error %u\n", GetLastError());
608 
609     /* Clean up */
610     ret = ReleaseDC(hwnd, hdc);
611     ok( ret, "ReleaseDC error %u\n", GetLastError());
612     ret = DestroyWindow(hwnd);
613     ok( ret, "DestroyWindow error %u\n", GetLastError());
614 }
615 
616 /* replace tabs by \t */
617 static void strfmt( const char *str, char *strout)
618 {
619     unsigned int i,j ;
620     for(i=0,j=0;i<=strlen(str);i++,j++)
621         if((strout[j]=str[i])=='\t') {
622             strout[j++]='\\';
623             strout[j]='t';
624         }
625 }
626 
627 
628 #define TABTEST( tabval, tabcount, string, _exp) \
629 { int i; char strdisp[64];\
630     for(i=0;i<8;i++) tabs[i]=(i+1)*(tabval); \
631     extent = GetTabbedTextExtentA( hdc, string, strlen( string), (tabcount), tabs); \
632     strfmt( string, strdisp); \
633  /*   trace( "Extent is %08lx\n", extent); */\
634     ok( extent == _exp, "Test case \"%s\". Text extent is 0x%x, expected 0x%x tab %d tabcount %d\n", \
635         strdisp, extent, _exp, tabval, tabcount); \
636 } \
637 
638 
639 static void test_TabbedText(void)
640 {
641     HWND hwnd;
642     HDC hdc;
643     BOOL ret;
644     TEXTMETRICA tm;
645     DWORD extent;
646     INT tabs[8], cx, cy, tab, tabcount,t,align;
647 
648     /* Initialization */
649     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP,
650                            0, 0, 200, 200, 0, 0, 0, NULL);
651     ok(hwnd != 0, "CreateWindowExA error %u\n", GetLastError());
652     hdc = GetDC(hwnd);
653     ok(hdc != 0, "GetDC error %u\n", GetLastError());
654 
655     ret = GetTextMetricsA( hdc, &tm);
656     ok( ret, "GetTextMetrics error %u\n", GetLastError());
657 
658     extent = GetTabbedTextExtentA( hdc, "x", 0, 1, tabs);
659     ok( extent == 0, "GetTabbedTextExtentA returned non-zero on nCount == 0\n");
660 
661     extent = GetTabbedTextExtentA( hdc, "x", 1, 1, tabs);
662     cx = LOWORD( extent);
663     cy = HIWORD( extent);
664     trace( "cx is %d cy is %d\n", cx, cy);
665 
666     align=1;
667     for( t=-1; t<=1; t++) { /* slightly adjust the 4 char tabstop, to
668                                catch the one off errors */
669         tab =  (cx *4 + t);
670         /* test the special case tabcount =1 and the general array (80 of tabs */
671         for( tabcount = 1; tabcount <= 8; tabcount +=7) {
672             TABTEST( align * tab, tabcount, "\t", MAKELONG(tab, cy))
673             TABTEST( align * tab, tabcount, "xxx\t", MAKELONG(tab, cy))
674             TABTEST( align * tab, tabcount, "\tx", MAKELONG(tab+cx, cy))
675             TABTEST( align * tab, tabcount, "\t\t", MAKELONG(tab*2, cy))
676             TABTEST( align * tab, tabcount, "\tx\t", MAKELONG(tab*2, cy))
677             TABTEST( align * tab, tabcount, "x\tx", MAKELONG(tab+cx, cy))
678             TABTEST( align * tab, tabcount, "xx\tx", MAKELONG(tab+cx, cy))
679             TABTEST( align * tab, tabcount, "xxx\tx", MAKELONG(tab+cx, cy))
680             TABTEST( align * tab, tabcount, "xxxx\tx", MAKELONG(t>0 ? tab + cx : 2*tab+cx, cy))
681             TABTEST( align * tab, tabcount, "xxxxx\tx", MAKELONG(2*tab+cx, cy))
682         }
683     }
684     align=-1;
685     for( t=-1; t<=1; t++) { /* slightly adjust the 4 char tabstop, to
686                                catch the one off errors */
687         tab =  (cx *4 + t);
688         /* test the special case tabcount =1 and the general array (8) of tabs */
689         for( tabcount = 1; tabcount <= 8; tabcount +=7) {
690             TABTEST( align * tab, tabcount, "\t", MAKELONG(tab, cy))
691             TABTEST( align * tab, tabcount, "xxx\t", MAKELONG(tab, cy))
692             TABTEST( align * tab, tabcount, "\tx", MAKELONG(tab, cy))
693             TABTEST( align * tab, tabcount, "\t\t", MAKELONG(tab*2, cy))
694             TABTEST( align * tab, tabcount, "\tx\t", MAKELONG(tab*2, cy))
695             TABTEST( align * tab, tabcount, "x\tx", MAKELONG(tab, cy))
696             TABTEST( align * tab, tabcount, "xx\tx", MAKELONG(tab, cy))
697             TABTEST( align * tab, tabcount, "xxx\tx", MAKELONG(4 * cx >= tab ? 2*tab :tab, cy))
698             TABTEST( align * tab, tabcount, "xxxx\tx", MAKELONG(2*tab, cy))
699             TABTEST( align * tab, tabcount, "xxxxx\tx", MAKELONG(2*tab, cy))
700         }
701     }
702 
703     ReleaseDC( hwnd, hdc );
704     DestroyWindow( hwnd );
705 }
706 
707 static void test_DrawState(void)
708 {
709     static const char text[] = "Sample text string";
710     HWND hwnd;
711     HDC hdc;
712     BOOL ret;
713 
714     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP,
715                            0, 0, 200, 200, 0, 0, 0, NULL);
716     assert(hwnd);
717 
718     hdc = GetDC(hwnd);
719     assert(hdc);
720 
721     SetLastError(0xdeadbeef);
722     ret = DrawStateA(hdc, GetStockObject(DKGRAY_BRUSH), NULL, (LPARAM)text, strlen(text),
723                     0, 0, 10, 10, DST_TEXT);
724     ok(ret, "DrawState error %u\n", GetLastError());
725 
726     SetLastError(0xdeadbeef);
727     ret = DrawStateA(hdc, GetStockObject(DKGRAY_BRUSH), NULL, (LPARAM)text, 0,
728                     0, 0, 10, 10, DST_TEXT);
729     ok(ret, "DrawState error %u\n", GetLastError());
730 
731     SetLastError(0xdeadbeef);
732     ret = DrawStateA(hdc, GetStockObject(DKGRAY_BRUSH), NULL, 0, strlen(text),
733                     0, 0, 10, 10, DST_TEXT);
734     ok(!ret || broken(ret) /* win98 */, "DrawState succeeded\n");
735     ok(GetLastError() == 0xdeadbeef, "not expected error %u\n", GetLastError());
736 
737     SetLastError(0xdeadbeef);
738     ret = DrawStateA(hdc, GetStockObject(DKGRAY_BRUSH), NULL, 0, 0,
739                     0, 0, 10, 10, DST_TEXT);
740     ok(!ret || broken(ret) /* win98 */, "DrawState succeeded\n");
741     ok(GetLastError() == 0xdeadbeef, "not expected error %u\n", GetLastError());
742 
743     ReleaseDC(hwnd, hdc);
744     DestroyWindow(hwnd);
745 }
746 
747 static void test_CharToOem_OemToChar(void)
748 {
749     static const WCHAR helloWorldW[] = {'H','e','l','l','o',' ','W','o','r','l','d',0};
750     static const WCHAR emptyW[] = {0};
751     static const char helloWorld[] = "Hello World";
752     static const struct
753     {
754         BOOL src, dst, ret;
755     }
756     tests[] =
757     {
758         { FALSE, FALSE, FALSE },
759         { TRUE,  FALSE, FALSE },
760         { FALSE, TRUE,  FALSE },
761         { TRUE,  TRUE,  TRUE  },
762     };
763     BOOL ret;
764     int i;
765     char oem;
766     WCHAR uni, expect;
767 
768     for (i = 0; i < ARRAY_SIZE(tests); i++)
769     {
770         const char *expected = tests[i].ret ? helloWorld : "";
771         const char *src = tests[i].src ? helloWorld : NULL;
772         char buf[64], *dst = tests[i].dst ? buf : NULL;
773 
774         memset(buf, 0, sizeof(buf));
775         ret = CharToOemA(src, dst);
776         ok(ret == tests[i].ret, "test %d: expected %d, got %d\n", i, tests[i].ret, ret);
777         ok(!strcmp(buf, expected), "test %d: got '%s'\n", i, buf);
778 
779         memset(buf, 0, sizeof(buf));
780         ret = CharToOemBuffA(src, dst, sizeof(helloWorld));
781         ok(ret == tests[i].ret, "test %d: expected %d, got %d\n", i, tests[i].ret, ret);
782         ok(!strcmp(buf, expected), "test %d: got '%s'\n", i, buf);
783 
784         memset(buf, 0, sizeof(buf));
785         ret = OemToCharA(src, dst);
786         ok(ret == tests[i].ret, "test %d: expected %d, got %d\n", i, tests[i].ret, ret);
787         ok(!strcmp(buf, expected), "test %d: got '%s'\n", i, buf);
788 
789         memset(buf, 0, sizeof(buf));
790         ret = OemToCharBuffA(src, dst, sizeof(helloWorld));
791         ok(ret == tests[i].ret, "test %d: expected %d, got %d\n", i, tests[i].ret, ret);
792         ok(!strcmp(buf, expected), "test %d: got '%s'\n", i, buf);
793     }
794 
795     for (i = 0; i < ARRAY_SIZE(tests); i++)
796     {
797         const char *expected = tests[i].ret ? helloWorld : "";
798         const WCHAR *src = tests[i].src ? helloWorldW : NULL;
799         char buf[64], *dst = tests[i].dst ? buf : NULL;
800 
801         memset(buf, 0, sizeof(buf));
802         ret = CharToOemW(src, dst);
803         ok(ret == tests[i].ret, "test %d: expected %d, got %d\n", i, tests[i].ret, ret);
804         ok(!strcmp(buf, expected), "test %d: got '%s'\n", i, buf);
805 
806         memset(buf, 0, sizeof(buf));
807         ret = CharToOemBuffW(src, dst, ARRAY_SIZE(helloWorldW));
808         ok(ret == tests[i].ret, "test %d: expected %d, got %d\n", i, tests[i].ret, ret);
809         ok(!strcmp(buf, expected), "test %d: got '%s'\n", i, buf);
810     }
811 
812     for (i = 0; i < ARRAY_SIZE(tests); i++)
813     {
814         const WCHAR *expected = tests[i].ret ? helloWorldW : emptyW;
815         const char *src = tests[i].src ? helloWorld : NULL;
816         WCHAR buf[64], *dst = tests[i].dst ? buf : NULL;
817 
818         memset(buf, 0, sizeof(buf));
819         ret = OemToCharW(src, dst);
820         ok(ret == tests[i].ret, "test %d: expected %d, got %d\n", i, tests[i].ret, ret);
821         ok(!lstrcmpW(buf, expected), "test %d: got '%s'\n", i, wine_dbgstr_w(buf));
822 
823         memset(buf, 0, sizeof(buf));
824         ret = OemToCharBuffW(src, dst, sizeof(helloWorld));
825         ok(ret == tests[i].ret, "test %d: expected %d, got %d\n", i, tests[i].ret, ret);
826         ok(!lstrcmpW(buf, expected), "test %d: got '%s'\n", i, wine_dbgstr_w(buf));
827     }
828 
829     for (i = 0; i < 0x100; i++)
830     {
831         oem = i;
832         ret = OemToCharBuffW( &oem, &uni, 1 );
833         ok( ret, "%02x: returns FALSE\n", i );
834         MultiByteToWideChar( CP_OEMCP, MB_PRECOMPOSED | MB_USEGLYPHCHARS, &oem, 1, &expect, 1 );
835         ok( uni == expect, "%02x: got %04x expected %04x\n", i, uni, expect );
836     }
837 }
838 
839 START_TEST(text)
840 {
841     test_TabbedText();
842     test_DrawTextCalcRect();
843     test_DrawState();
844     test_CharToOem_OemToChar();
845 }
846