4 * Copyright (c) 2004 Zach Gorman
5 * Copyright 2007,2016 Dmitry Timoshkov
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.
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.
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
24 #define MODIFIED(rect) (rect.left == 10 && rect.right != 100 && rect.top == 10 && rect.bottom != 100)
25 #define EMPTY(rect) (rect.left == rect.right && rect.bottom == rect.top)
27 static void test_DrawTextCalcRect(void)
31 HFONT hFont
, hOldFont
;
33 static CHAR text
[] = "Example text for testing DrawText in "
35 static WCHAR textW
[] = {'W','i','d','e',' ','c','h','a','r',' ',
36 's','t','r','i','n','g','\0'};
37 static CHAR emptystring
[] = "";
38 static WCHAR emptystringW
[] = { 0 };
39 static CHAR wordbreak_text
[] = "line1 line2";
40 static WCHAR wordbreak_textW
[] = {'l','i','n','e','1',' ','l','i','n','e','2',0};
41 static char tabstring
[] = "one\ttwo";
42 INT textlen
, textheight
, heightcheck
;
43 RECT rect
= { 0, 0, 100, 0 }, rect2
;
46 BOOL conform_xp
= TRUE
;
49 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
,
50 0, 0, 200, 200, 0, 0, 0, NULL
);
51 ok(hwnd
!= 0, "CreateWindowExA error %u\n", GetLastError());
53 ok(hdc
!= 0, "GetDC error %u\n", GetLastError());
54 trace("hdc %p\n", hdc
);
55 textlen
= lstrlenA(text
);
57 /* LOGFONT initialization */
58 memset(&lf
, 0, sizeof(lf
));
59 lf
.lfCharSet
= ANSI_CHARSET
;
60 lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
61 lf
.lfWeight
= FW_DONTCARE
;
62 lf
.lfHeight
= 0; /* mapping mode dependent */
63 lf
.lfQuality
= DEFAULT_QUALITY
;
64 lstrcpyA(lf
.lfFaceName
, "Arial");
66 /* DrawText in MM_HIENGLISH with DT_CALCRECT */
67 SetMapMode(hdc
, MM_HIENGLISH
);
68 lf
.lfHeight
= 100 * 9 / 72; /* 9 point */
69 hFont
= CreateFontIndirectA(&lf
);
70 ok(hFont
!= 0, "CreateFontIndirectA error %u\n",
72 hOldFont
= SelectObject(hdc
, hFont
);
74 textheight
= DrawTextA(hdc
, text
, textlen
, &rect
, DT_CALCRECT
|
75 DT_EXTERNALLEADING
| DT_WORDBREAK
| DT_NOCLIP
| DT_LEFT
|
77 ok( textheight
, "DrawTextA error %u\n", GetLastError());
79 trace("MM_HIENGLISH rect.bottom %d\n", rect
.bottom
);
80 ok(rect
.bottom
< 0, "In MM_HIENGLISH, DrawText with "
81 "DT_CALCRECT should return a negative rectangle bottom. "
82 "(bot=%d)\n", rect
.bottom
);
84 SelectObject(hdc
, hOldFont
);
85 ret
= DeleteObject(hFont
);
86 ok( ret
, "DeleteObject error %u\n", GetLastError());
89 /* DrawText in MM_TEXT with DT_CALCRECT */
90 SetMapMode(hdc
, MM_TEXT
);
91 lf
.lfHeight
= -MulDiv(9, GetDeviceCaps(hdc
,
92 LOGPIXELSY
), 72); /* 9 point */
93 hFont
= CreateFontIndirectA(&lf
);
94 ok(hFont
!= 0, "CreateFontIndirectA error %u\n",
96 hOldFont
= SelectObject(hdc
, hFont
);
98 textheight
= DrawTextA(hdc
, text
, textlen
, &rect
, DT_CALCRECT
|
99 DT_EXTERNALLEADING
| DT_WORDBREAK
| DT_NOCLIP
| DT_LEFT
|
101 ok( textheight
, "DrawTextA error %u\n", GetLastError());
103 trace("MM_TEXT rect.bottom %d\n", rect
.bottom
);
104 ok(rect
.bottom
> 0, "In MM_TEXT, DrawText with DT_CALCRECT "
105 "should return a positive rectangle bottom. (bot=%d)\n",
108 /* empty or null text should in some cases calc an empty rectangle */
110 SetRect( &rect
, 10,10, 100, 100);
111 heightcheck
= textheight
= DrawTextExA(hdc
, text
, 0, &rect
, DT_CALCRECT
, NULL
);
112 ok(!IsRectEmpty(&rect
) && !MODIFIED(rect
),
113 "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect
));
114 ok(textheight
==0,"Got textheight from DrawTextExA\n");
116 SetRect( &rect
, 10,10, 100, 100);
117 textheight
= DrawTextA(hdc
, text
, 0, &rect
, DT_CALCRECT
);
118 ok(!IsRectEmpty(&rect
) && !MODIFIED(rect
),
119 "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect
));
121 ok(textheight
==0,"Got textheight from DrawTextA\n");
122 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
124 SetRect( &rect
, 10,10, 100, 100);
126 heightcheck
= textheight
= DrawTextExA(hdc
, emptystring
, -1, &rect
, DT_CALCRECT
, NULL
);
127 ok(EMPTY(rect
), "rectangle should be empty got %s\n", wine_dbgstr_rect(&rect
));
128 ok(textheight
!=0,"Failed to get textheight from DrawTextExA\n");
130 SetRect( &rect
, 10,10, 100, 100);
131 textheight
= DrawTextA(hdc
, emptystring
, -1, &rect
, DT_CALCRECT
);
132 ok(EMPTY(rect
), "rectangle should be empty got %s\n", wine_dbgstr_rect(&rect
));
133 ok(textheight
!=0,"Failed to get textheight from DrawTextA\n");
134 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
136 SetRect( &rect
, 10,10, 100, 100);
138 heightcheck
= textheight
= DrawTextExA(hdc
, NULL
, -1, &rect
, DT_CALCRECT
, NULL
);
139 ok(EMPTY(rect
), "rectangle should be empty got %s\n", wine_dbgstr_rect(&rect
));
140 if (!textheight
) /* Windows NT 4 */
143 win_skip("XP conformity failed, skipping XP tests. Probably winNT\n");
147 ok(textheight
!=0,"Failed to get textheight from DrawTextExA\n");
149 SetRect( &rect
, 10,10, 100, 100);
150 textheight
= DrawTextA(hdc
, NULL
, -1, &rect
, DT_CALCRECT
);
151 ok(EMPTY(rect
), "rectangle should be empty got %s\n", wine_dbgstr_rect(&rect
));
153 ok(textheight
!=0,"Failed to get textheight from DrawTextA\n");
154 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
156 SetRect( &rect
, 10,10, 100, 100);
157 heightcheck
= textheight
= DrawTextExA(hdc
, NULL
, 0, &rect
, DT_CALCRECT
, NULL
);
158 ok(!IsRectEmpty(&rect
) && !MODIFIED(rect
),
159 "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect
));
161 ok(textheight
==0,"Got textheight from DrawTextExA\n");
163 SetRect( &rect
, 10,10, 100, 100);
164 textheight
= DrawTextA(hdc
, NULL
, 0, &rect
, DT_CALCRECT
);
165 ok(!IsRectEmpty(&rect
) && !MODIFIED(rect
),
166 "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect
));
168 ok(textheight
==0,"Got textheight from DrawTextA\n");
169 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
171 /* DT_SINGLELINE tests */
173 SetRect( &rect
, 10,10, 100, 100);
174 heightcheck
= textheight
= DrawTextExA(hdc
, text
, 0, &rect
, DT_CALCRECT
|DT_SINGLELINE
, NULL
);
175 ok(!IsRectEmpty(&rect
) && !MODIFIED(rect
),
176 "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect
));
178 ok(textheight
==0,"Got textheight from DrawTextExA\n");
180 SetRect( &rect
, 10,10, 100, 100);
181 textheight
= DrawTextA(hdc
, text
, 0, &rect
, DT_CALCRECT
|DT_SINGLELINE
);
182 ok(!IsRectEmpty(&rect
) && !MODIFIED(rect
),
183 "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect
));
185 ok(textheight
==0,"Got textheight from DrawTextA\n");
186 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
188 SetRect( &rect
, 10,10, 100, 100);
190 heightcheck
= textheight
= DrawTextExA(hdc
, emptystring
, -1, &rect
, DT_CALCRECT
|DT_SINGLELINE
, NULL
);
191 ok(!EMPTY(rect
) && MODIFIED(rect
), "rectangle should be modified got %s\n",
192 wine_dbgstr_rect(&rect
));
193 ok(textheight
!=0,"Failed to get textheight from DrawTextExA\n");
195 SetRect( &rect
, 10,10, 100, 100);
196 textheight
= DrawTextA(hdc
, emptystring
, -1, &rect
, DT_CALCRECT
|DT_SINGLELINE
);
197 ok(!EMPTY(rect
) && MODIFIED (rect
), "rectangle should be modified got %s\n",
198 wine_dbgstr_rect(&rect
));
199 ok(textheight
!=0,"Failed to get textheight from DrawTextA\n");
200 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
202 SetRect( &rect
, 10,10, 100, 100);
204 heightcheck
= textheight
= DrawTextExA(hdc
, NULL
, -1, &rect
, DT_CALCRECT
|DT_SINGLELINE
, NULL
);
205 ok(!EMPTY(rect
) && MODIFIED(rect
), "rectangle should be modified got %s\n",
206 wine_dbgstr_rect(&rect
));
208 ok(textheight
!=0,"Failed to get textheight from DrawTextExA\n");
210 SetRect( &rect
, 10,10, 100, 100);
211 textheight
= DrawTextA(hdc
, NULL
, -1, &rect
, DT_CALCRECT
|DT_SINGLELINE
);
212 ok(!EMPTY(rect
) && MODIFIED(rect
), "rectangle should be modified got %s\n",
213 wine_dbgstr_rect(&rect
));
215 ok(textheight
!=0,"Failed to get textheight from DrawTextA\n");
216 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
218 SetRect( &rect
, 10,10, 100, 100);
219 heightcheck
= textheight
= DrawTextExA(hdc
, NULL
, 0, &rect
, DT_CALCRECT
|DT_SINGLELINE
, NULL
);
220 ok(!IsRectEmpty(&rect
) && !MODIFIED(rect
),
221 "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect
));
223 ok(textheight
==0,"Got textheight from DrawTextExA\n");
225 SetRect( &rect
, 10,10, 100, 100);
226 textheight
= DrawTextA(hdc
, NULL
, 0, &rect
, DT_CALCRECT
|DT_SINGLELINE
);
227 ok(!IsRectEmpty(&rect
) && !MODIFIED(rect
),
228 "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect
));
230 ok(textheight
==0,"Got textheight from DrawTextA\n");
231 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
233 /* further tests with 0 count, NULL and empty strings */
234 heightcheck
= textheight
= DrawTextA(hdc
, text
, 0, &rect
, 0);
236 ok(textheight
==0,"Got textheight from DrawTextA\n");
237 textheight
= DrawTextExA(hdc
, text
, 0, &rect
, 0, NULL
);
239 ok(textheight
==0,"Got textheight from DrawTextExA\n");
240 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
241 heightcheck
= textheight
= DrawTextA(hdc
, emptystring
, 0, &rect
, 0);
243 ok(textheight
==0,"Got textheight from DrawTextA\n");
244 textheight
= DrawTextExA(hdc
, emptystring
, 0, &rect
, 0, NULL
);
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
, NULL
, 0, &rect
, 0);
250 ok(textheight
==0,"Got textheight from DrawTextA\n");
251 textheight
= DrawTextExA(hdc
, NULL
, 0, &rect
, 0, NULL
);
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
, emptystring
, -1, &rect
, 0);
256 ok(textheight
!=0,"Failed to get textheight from DrawTextA\n");
257 textheight
= DrawTextExA(hdc
, emptystring
, -1, &rect
, 0, NULL
);
258 ok(textheight
!=0,"Failed to get textheight from DrawTextExA\n");
259 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
260 heightcheck
= textheight
= DrawTextA(hdc
, NULL
, -1, &rect
, 0);
262 ok(textheight
!=0,"Failed to get textheight from DrawTextA\n");
263 textheight
= DrawTextExA(hdc
, NULL
, -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
, 10, &rect
, 0);
268 ok(textheight
==0,"Got textheight from DrawTextA\n");
269 textheight
= DrawTextExA(hdc
, NULL
, 10, &rect
, 0, NULL
);
270 ok(textheight
==0,"Got textheight from DrawTextA\n");
271 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
274 /* invalid dtp size test */
275 dtp
.cbSize
= -1; /* Invalid */
276 dtp
.uiLengthDrawn
= 1337;
277 textheight
= DrawTextExA(hdc
, text
, 0, &rect
, 0, &dtp
);
278 ok(textheight
==0,"Got textheight from DrawTextExA\n");
279 ok(dtp
.uiLengthDrawn
==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp
.uiLengthDrawn
);
280 dtp
.uiLengthDrawn
= 1337;
281 textheight
= DrawTextExA(hdc
, emptystring
, 0, &rect
, 0, &dtp
);
282 ok(textheight
==0,"Got textheight from DrawTextExA\n");
283 ok(dtp
.uiLengthDrawn
==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp
.uiLengthDrawn
);
284 dtp
.uiLengthDrawn
= 1337;
285 textheight
= DrawTextExA(hdc
, NULL
, 0, &rect
, 0, &dtp
);
286 ok(textheight
==0,"Got textheight from DrawTextExA\n");
287 ok(dtp
.uiLengthDrawn
==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp
.uiLengthDrawn
);
288 dtp
.uiLengthDrawn
= 1337;
289 textheight
= DrawTextExA(hdc
, emptystring
, -1, &rect
, 0, &dtp
);
290 ok(textheight
==0,"Got textheight from DrawTextExA\n");
291 ok(dtp
.uiLengthDrawn
==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp
.uiLengthDrawn
);
292 dtp
.uiLengthDrawn
= 1337;
293 textheight
= DrawTextExA(hdc
, NULL
, -1, &rect
, 0, &dtp
);
294 ok(textheight
==0,"Got textheight from DrawTextExA\n");
295 ok(dtp
.uiLengthDrawn
==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp
.uiLengthDrawn
);
297 /* Margin calculations */
298 dtp
.cbSize
= sizeof(dtp
);
300 dtp
.iRightMargin
= 0;
302 DrawTextExA(hdc
, text
, -1, &rect
, DT_CALCRECT
, &dtp
);
303 textlen
= rect
.right
; /* Width without margin */
306 DrawTextExA(hdc
, text
, -1, &rect
, DT_CALCRECT
, &dtp
);
307 ok(rect
.right
==dtp
.iLeftMargin
+textlen
,"Incorrect left margin calculated rc(%d,%d)\n", rect
.left
, rect
.right
);
309 dtp
.iRightMargin
= 8;
311 DrawTextExA(hdc
, text
, -1, &rect
, DT_CALCRECT
, &dtp
);
312 ok(rect
.right
==dtp
.iRightMargin
+textlen
,"Incorrect right margin calculated rc(%d,%d)\n", rect
.left
, rect
.right
);
314 /* Wide char versions */
315 SetRect( &rect
, 10,10, 100, 100);
317 heightcheck
= textheight
= DrawTextExW(hdc
, textW
, 0, &rect
, DT_CALCRECT
, NULL
);
318 if( GetLastError() != ERROR_CALL_NOT_IMPLEMENTED
) {
319 ok(!IsRectEmpty(&rect
) && !MODIFIED(rect
),
320 "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect
));
321 ok(textheight
!=0,"Failed to get textheight from DrawTextExW\n");
323 SetRect( &rect
, 10,10, 100, 100);
324 textheight
= DrawTextW(hdc
, textW
, 0, &rect
, DT_CALCRECT
);
325 ok(!IsRectEmpty(&rect
) && !MODIFIED(rect
),
326 "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect
));
327 ok(textheight
!=0,"Failed to get textheight from DrawTextW\n");
328 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
330 SetRect( &rect
, 10,10, 100, 100);
331 heightcheck
= textheight
= DrawTextExW(hdc
, emptystringW
, -1, &rect
, DT_CALCRECT
, NULL
);
332 ok(EMPTY(rect
), "rectangle should be empty got %s\n", wine_dbgstr_rect(&rect
));
333 ok(textheight
!=0,"Failed to get textheight from DrawTextExW\n");
335 SetRect( &rect
, 10,10, 100, 100);
336 textheight
= DrawTextW(hdc
, emptystringW
, -1, &rect
, DT_CALCRECT
);
337 ok(EMPTY(rect
), "rectangle should be empty got %s\n", wine_dbgstr_rect(&rect
));
338 ok(textheight
!=0,"Failed to get textheight from DrawTextW\n");
339 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
341 SetRect( &rect
, 10,10, 100, 100);
342 heightcheck
= textheight
= DrawTextExW(hdc
, NULL
, 0, &rect
, DT_CALCRECT
, NULL
);
343 ok(!IsRectEmpty(&rect
) && !MODIFIED(rect
),
344 "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect
));
345 if (textheight
) /* windows 2000 */
348 win_skip("XP conformity failed, skipping XP tests. Probably win 2000\n");
352 ok(textheight
==0,"Got textheight from DrawTextExW\n");
354 SetRect( &rect
, 10,10, 100, 100);
355 textheight
= DrawTextW(hdc
, NULL
, 0, &rect
, DT_CALCRECT
);
356 ok(!IsRectEmpty(&rect
) && !MODIFIED(rect
),
357 "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect
));
359 ok(textheight
==0,"Got textheight from DrawTextW\n");
360 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
364 SetRect( &rect
, 10,10, 100, 100);
365 heightcheck
= textheight
= DrawTextExW(hdc
, NULL
, -1, &rect
, DT_CALCRECT
, NULL
);
366 ok(!IsRectEmpty(&rect
) && !MODIFIED(rect
),
367 "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect
));
368 ok(textheight
==0,"Got textheight from DrawTextExW\n");
370 SetRect( &rect
, 10,10, 100, 100);
371 textheight
= DrawTextW(hdc
, NULL
, -1, &rect
, DT_CALCRECT
);
372 ok(!IsRectEmpty(&rect
) && !MODIFIED(rect
),
373 "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect
));
374 ok(textheight
==0,"Got textheight from DrawTextW\n");
375 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
379 /* DT_SINGLELINE tests */
381 heightcheck
= textheight
= DrawTextExW(hdc
, textW
, 0, &rect
, DT_CALCRECT
|DT_SINGLELINE
, NULL
);
382 ok(!IsRectEmpty(&rect
) && !MODIFIED(rect
),
383 "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect
));
384 ok(textheight
!=0,"Failed to get textheight from DrawTextExW\n");
386 SetRect( &rect
, 10,10, 100, 100);
387 textheight
= DrawTextW(hdc
, textW
, 0, &rect
, DT_CALCRECT
|DT_SINGLELINE
);
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,"Failed to get textheight from DrawTextW\n");
391 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
393 SetRect( &rect
, 10,10, 100, 100);
394 heightcheck
= textheight
= DrawTextExW(hdc
, emptystringW
, -1, &rect
, DT_CALCRECT
|DT_SINGLELINE
, NULL
);
395 ok(!EMPTY(rect
) && MODIFIED(rect
), "rectangle should be modified got %s\n",
396 wine_dbgstr_rect(&rect
));
397 ok(textheight
!=0,"Failed to get textheight from DrawTextExW\n");
399 SetRect( &rect
, 10,10, 100, 100);
400 textheight
= DrawTextW(hdc
, emptystringW
, -1, &rect
, DT_CALCRECT
|DT_SINGLELINE
);
401 ok(!EMPTY(rect
) && MODIFIED(rect
), "rectangle should be modified got %s\n",
402 wine_dbgstr_rect(&rect
));
403 ok(textheight
!=0,"Failed to get textheight from DrawTextW\n");
404 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
408 SetRect( &rect
, 10,10, 100, 100);
409 heightcheck
= textheight
= DrawTextExW(hdc
, NULL
, -1, &rect
, DT_CALCRECT
|DT_SINGLELINE
, NULL
);
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,"Got textheight from DrawTextExW\n");
414 SetRect( &rect
, 10,10, 100, 100);
415 textheight
= DrawTextW(hdc
, NULL
, -1, &rect
, DT_CALCRECT
|DT_SINGLELINE
);
416 ok(!IsRectEmpty(&rect
) && !MODIFIED(rect
),
417 "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect
));
418 ok(textheight
==0,"Got textheight from DrawTextW\n");
419 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
422 SetRect( &rect
, 10,10, 100, 100);
423 heightcheck
= textheight
= DrawTextExW(hdc
, NULL
, 0, &rect
, DT_CALCRECT
|DT_SINGLELINE
, NULL
);
424 ok(!IsRectEmpty(&rect
) && !MODIFIED(rect
),
425 "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect
));
427 ok(textheight
==0,"Got textheight from DrawTextExW\n");
429 SetRect( &rect
, 10,10, 100, 100);
430 textheight
= DrawTextW(hdc
, NULL
, 0, &rect
, DT_CALCRECT
|DT_SINGLELINE
);
431 ok(!IsRectEmpty(&rect
) && !MODIFIED(rect
),
432 "rectangle should NOT be empty and NOT modified got %s\n", wine_dbgstr_rect(&rect
));
434 ok(textheight
==0,"Got textheight from DrawTextW\n");
435 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
437 /* further tests with NULL and empty strings */
438 heightcheck
= textheight
= DrawTextW(hdc
, textW
, 0, &rect
, 0);
439 ok(textheight
!=0,"Failed to get textheight from DrawTextW\n");
440 textheight
= DrawTextExW(hdc
, textW
, 0, &rect
, 0, NULL
);
441 ok(textheight
!=0,"Failed to get textheight from DrawTextExW\n");
442 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
443 heightcheck
= textheight
= DrawTextW(hdc
, emptystringW
, 0, &rect
, 0);
444 ok(textheight
!=0,"Failed to get textheight from DrawTextW\n");
445 textheight
= DrawTextExW(hdc
, emptystringW
, 0, &rect
, 0, NULL
);
446 ok(textheight
!=0,"Failed to get textheight from DrawTextExW\n");
447 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
448 heightcheck
= textheight
= DrawTextW(hdc
, NULL
, 0, &rect
, 0);
450 ok(textheight
==0,"Got textheight from DrawTextW\n");
451 textheight
= DrawTextExW(hdc
, NULL
, 0, &rect
, 0, NULL
);
453 ok(textheight
==0,"Got textheight from DrawTextExW\n");
454 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
455 heightcheck
= textheight
= DrawTextW(hdc
, emptystringW
, -1, &rect
, 0);
456 ok(textheight
!=0,"Failed to get textheight from DrawTextW\n");
457 textheight
= DrawTextExW(hdc
, emptystringW
, -1, &rect
, 0, NULL
);
458 ok(textheight
!=0,"Failed to get textheight from DrawTextExW\n");
459 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
462 heightcheck
= textheight
= DrawTextW(hdc
, NULL
, -1, &rect
, 0);
463 ok(textheight
==0,"Got textheight from DrawTextW\n");
464 textheight
= DrawTextExW(hdc
, NULL
, -1, &rect
, 0, NULL
);
465 ok(textheight
==0,"Got textheight from DrawTextExW\n");
466 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
467 heightcheck
= textheight
= DrawTextW(hdc
, NULL
, 10, &rect
, 0);
468 ok(textheight
==0,"Got textheight from DrawTextW\n");
469 textheight
= DrawTextExW(hdc
, NULL
, 10, &rect
, 0, NULL
);
470 ok(textheight
==0,"Got textheight from DrawTextW\n");
471 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
474 dtp
.cbSize
= -1; /* Invalid */
475 dtp
.uiLengthDrawn
= 1337;
476 textheight
= DrawTextExW(hdc
, textW
, 0, &rect
, 0, &dtp
);
477 ok(textheight
!=0,"Failed to get textheight from DrawTextExW\n");
478 ok(dtp
.uiLengthDrawn
==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp
.uiLengthDrawn
);
479 dtp
.uiLengthDrawn
= 1337;
480 textheight
= DrawTextExW(hdc
, emptystringW
, 0, &rect
, 0, &dtp
);
482 ok(textheight
==0,"Got textheight from DrawTextExW\n");
483 ok(dtp
.uiLengthDrawn
==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp
.uiLengthDrawn
);
484 dtp
.uiLengthDrawn
= 1337;
485 textheight
= DrawTextExW(hdc
, NULL
, 0, &rect
, 0, &dtp
);
487 ok(textheight
==0,"Got textheight from DrawTextExW\n");
488 ok(dtp
.uiLengthDrawn
==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp
.uiLengthDrawn
);
489 dtp
.uiLengthDrawn
= 1337;
490 textheight
= DrawTextExW(hdc
, emptystringW
, -1, &rect
, 0, &dtp
);
491 ok(textheight
==0,"Got textheight from DrawTextExW\n");
492 ok(dtp
.uiLengthDrawn
==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp
.uiLengthDrawn
);
495 dtp
.uiLengthDrawn
= 1337;
496 textheight
= DrawTextExW(hdc
, NULL
, -1, &rect
, 0, &dtp
);
497 ok(textheight
==0,"Got textheight from DrawTextExW\n");
498 ok(dtp
.uiLengthDrawn
==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp
.uiLengthDrawn
);
502 /* More test cases from bug 12226 */
504 textheight
= DrawTextA(hdc
, emptystring
, -1, &rect
, DT_CALCRECT
| DT_LEFT
| DT_SINGLELINE
);
505 ok(textheight
, "DrawTextA error %u\n", GetLastError());
506 ok(0 == rect
.left
, "expected 0, got %d\n", rect
.left
);
507 ok(0 == rect
.right
, "expected 0, got %d\n", rect
.right
);
508 ok(0 == rect
.top
, "expected 0, got %d\n", rect
.top
);
509 ok(rect
.bottom
, "rect.bottom should not be 0\n");
512 textheight
= DrawTextW(hdc
, emptystringW
, -1, &rect
, DT_CALCRECT
| DT_LEFT
| DT_SINGLELINE
);
513 if (!textheight
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
515 win_skip( "DrawTextW not implemented\n" );
519 ok(textheight
, "DrawTextW error %u\n", GetLastError());
520 ok(0 == rect
.left
, "expected 0, got %d\n", rect
.left
);
521 ok(0 == rect
.right
, "expected 0, got %d\n", rect
.right
);
522 ok(0 == rect
.top
, "expected 0, got %d\n", rect
.top
);
523 ok(rect
.bottom
, "rect.bottom should not be 0\n");
526 SetRect(&rect
, 0, 0, 1, 1);
527 heightcheck
= DrawTextA(hdc
, wordbreak_text
, -1, &rect
, DT_CALCRECT
);
528 SetRect(&rect
, 0, 0, 1, 1);
529 textheight
= DrawTextA(hdc
, wordbreak_text
, -1, &rect
, DT_CALCRECT
| DT_WORDBREAK
);
530 ok(textheight
== heightcheck
* 2, "Got unexpected textheight %d, expected %d.\n",
531 textheight
, heightcheck
* 2);
532 SetRect(&rect
, 0, 0, 1, 1);
533 textheight
= DrawTextA(hdc
, wordbreak_text
, -1, &rect
, DT_CALCRECT
| DT_WORDBREAK
| DT_EDITCONTROL
);
534 ok(textheight
>= heightcheck
* 6, "Got unexpected textheight %d, expected at least %d.\n",
535 textheight
, heightcheck
* 6);
537 SetRect(&rect
, 0, 0, 1, 1);
538 heightcheck
= DrawTextW(hdc
, wordbreak_textW
, -1, &rect
, DT_CALCRECT
);
539 SetRect(&rect
, 0, 0, 1, 1);
540 textheight
= DrawTextW(hdc
, wordbreak_textW
, -1, &rect
, DT_CALCRECT
| DT_WORDBREAK
);
541 ok(textheight
== heightcheck
* 2, "Got unexpected textheight %d, expected %d.\n",
542 textheight
, heightcheck
* 2);
543 SetRect(&rect
, 0, 0, 1, 1);
544 textheight
= DrawTextW(hdc
, wordbreak_textW
, -1, &rect
, DT_CALCRECT
| DT_WORDBREAK
| DT_EDITCONTROL
);
545 ok(textheight
>= heightcheck
* 6, "Got unexpected textheight %d, expected at least %d.\n",
546 textheight
, heightcheck
* 6);
548 /* DT_TABSTOP | DT_EXPANDTABS tests */
549 SetRect( &rect
, 0,0, 10, 10);
550 textheight
= DrawTextA(hdc
, tabstring
, -1, &rect
, DT_TABSTOP
| DT_EXPANDTABS
);
551 ok(textheight
>= heightcheck
, "Got unexpected textheight %d\n", textheight
);
553 SetRect( &rect
, 0,0, 10, 10);
554 memset(&dtp
, 0, sizeof(dtp
));
555 dtp
.cbSize
= sizeof(dtp
);
556 textheight
= DrawTextExA(hdc
, tabstring
, -1, &rect
, DT_CALCRECT
, &dtp
);
557 ok(textheight
>= heightcheck
, "Got unexpected textheight %d\n", textheight
);
558 ok(dtp
.iTabLength
== 0, "invalid dtp.iTabLength = %i\n",dtp
.iTabLength
);
560 SetRect( &rect2
, 0,0, 10, 10);
561 memset(&dtp
, 0, sizeof(dtp
));
562 dtp
.cbSize
= sizeof(dtp
);
563 textheight
= DrawTextExA(hdc
, tabstring
, -1, &rect2
, DT_CALCRECT
| DT_TABSTOP
| DT_EXPANDTABS
, &dtp
);
564 ok(textheight
>= heightcheck
, "Got unexpected textheight %d\n", textheight
);
565 ok(dtp
.iTabLength
== 0, "invalid dtp.iTabLength = %i\n",dtp
.iTabLength
);
566 ok(rect
.left
== rect2
.left
&& rect
.right
!= rect2
.right
&& rect
.top
== rect2
.top
&& rect
.bottom
== rect2
.bottom
,
567 "incorrect rect %s rect2 %s\n", wine_dbgstr_rect(&rect
), wine_dbgstr_rect(&rect2
));
569 SetRect( &rect
, 0,0, 10, 10);
570 memset(&dtp
, 0, sizeof(dtp
));
571 dtp
.cbSize
= sizeof(dtp
);
573 textheight
= DrawTextExA(hdc
, tabstring
, -1, &rect
, DT_CALCRECT
| DT_TABSTOP
| DT_EXPANDTABS
, &dtp
);
574 ok(textheight
>= heightcheck
, "Got unexpected textheight %d\n", textheight
);
575 ok(dtp
.iTabLength
== 8, "invalid dtp.iTabLength = %i\n",dtp
.iTabLength
);
576 ok(rect
.left
== rect2
.left
, "unexpected value %d, got %d\n", rect
.left
, rect2
.left
);
577 /* XP, 2003 appear to not give the same values. */
578 ok(rect
.right
== rect2
.right
|| broken(rect
.right
> rect2
.right
), "unexpected value %d, got %d\n",rect
.right
, rect2
.right
);
579 ok(rect
.top
== rect2
.top
, "unexpected value %d, got %d\n", rect
.top
, rect2
.top
);
580 ok(rect
.bottom
== rect2
.bottom
, "unexpected value %d, got %d\n", rect
.bottom
, rect2
.bottom
);
583 SelectObject(hdc
, hOldFont
);
584 ret
= DeleteObject(hFont
);
585 ok( ret
, "DeleteObject error %u\n", GetLastError());
588 ret
= ReleaseDC(hwnd
, hdc
);
589 ok( ret
, "ReleaseDC error %u\n", GetLastError());
590 ret
= DestroyWindow(hwnd
);
591 ok( ret
, "DestroyWindow error %u\n", GetLastError());
594 /* replace tabs by \t */
595 static void strfmt( const char *str
, char *strout
)
598 for(i
=0,j
=0;i
<=strlen(str
);i
++,j
++)
599 if((strout
[j
]=str
[i
])=='\t') {
606 #define TABTEST( tabval, tabcount, string, _exp) \
607 { int i; char strdisp[64];\
608 for(i=0;i<8;i++) tabs[i]=(i+1)*(tabval); \
609 extent = GetTabbedTextExtentA( hdc, string, strlen( string), (tabcount), tabs); \
610 strfmt( string, strdisp); \
611 /* trace( "Extent is %08lx\n", extent); */\
612 ok( extent == _exp, "Test case \"%s\". Text extent is 0x%x, expected 0x%x tab %d tabcount %d\n", \
613 strdisp, extent, _exp, tabval, tabcount); \
617 static void test_TabbedText(void)
624 INT tabs
[8], cx
, cy
, tab
, tabcount
,t
,align
;
627 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
,
628 0, 0, 200, 200, 0, 0, 0, NULL
);
629 ok(hwnd
!= 0, "CreateWindowExA error %u\n", GetLastError());
631 ok(hdc
!= 0, "GetDC error %u\n", GetLastError());
633 ret
= GetTextMetricsA( hdc
, &tm
);
634 ok( ret
, "GetTextMetrics error %u\n", GetLastError());
636 extent
= GetTabbedTextExtentA( hdc
, "x", 0, 1, tabs
);
637 ok( extent
== 0, "GetTabbedTextExtentA returned non-zero on nCount == 0\n");
639 extent
= GetTabbedTextExtentA( hdc
, "x", 1, 1, tabs
);
640 cx
= LOWORD( extent
);
641 cy
= HIWORD( extent
);
642 trace( "cx is %d cy is %d\n", cx
, cy
);
645 for( t
=-1; t
<=1; t
++) { /* slightly adjust the 4 char tabstop, to
646 catch the one off errors */
648 /* test the special case tabcount =1 and the general array (80 of tabs */
649 for( tabcount
= 1; tabcount
<= 8; tabcount
+=7) {
650 TABTEST( align
* tab
, tabcount
, "\t", MAKELONG(tab
, cy
))
651 TABTEST( align
* tab
, tabcount
, "xxx\t", MAKELONG(tab
, cy
))
652 TABTEST( align
* tab
, tabcount
, "\tx", MAKELONG(tab
+cx
, cy
))
653 TABTEST( align
* tab
, tabcount
, "\t\t", MAKELONG(tab
*2, cy
))
654 TABTEST( align
* tab
, tabcount
, "\tx\t", MAKELONG(tab
*2, cy
))
655 TABTEST( align
* tab
, tabcount
, "x\tx", MAKELONG(tab
+cx
, cy
))
656 TABTEST( align
* tab
, tabcount
, "xx\tx", MAKELONG(tab
+cx
, cy
))
657 TABTEST( align
* tab
, tabcount
, "xxx\tx", MAKELONG(tab
+cx
, cy
))
658 TABTEST( align
* tab
, tabcount
, "xxxx\tx", MAKELONG(t
>0 ? tab
+ cx
: 2*tab
+cx
, cy
))
659 TABTEST( align
* tab
, tabcount
, "xxxxx\tx", MAKELONG(2*tab
+cx
, cy
))
663 for( t
=-1; t
<=1; t
++) { /* slightly adjust the 4 char tabstop, to
664 catch the one off errors */
666 /* test the special case tabcount =1 and the general array (8) of tabs */
667 for( tabcount
= 1; tabcount
<= 8; tabcount
+=7) {
668 TABTEST( align
* tab
, tabcount
, "\t", MAKELONG(tab
, cy
))
669 TABTEST( align
* tab
, tabcount
, "xxx\t", MAKELONG(tab
, cy
))
670 TABTEST( align
* tab
, tabcount
, "\tx", MAKELONG(tab
, cy
))
671 TABTEST( align
* tab
, tabcount
, "\t\t", MAKELONG(tab
*2, cy
))
672 TABTEST( align
* tab
, tabcount
, "\tx\t", MAKELONG(tab
*2, cy
))
673 TABTEST( align
* tab
, tabcount
, "x\tx", MAKELONG(tab
, cy
))
674 TABTEST( align
* tab
, tabcount
, "xx\tx", MAKELONG(tab
, cy
))
675 TABTEST( align
* tab
, tabcount
, "xxx\tx", MAKELONG(4 * cx
>= tab
? 2*tab
:tab
, cy
))
676 TABTEST( align
* tab
, tabcount
, "xxxx\tx", MAKELONG(2*tab
, cy
))
677 TABTEST( align
* tab
, tabcount
, "xxxxx\tx", MAKELONG(2*tab
, cy
))
681 ReleaseDC( hwnd
, hdc
);
682 DestroyWindow( hwnd
);
685 static void test_DrawState(void)
687 static const char text
[] = "Sample text string";
692 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
,
693 0, 0, 200, 200, 0, 0, 0, NULL
);
699 SetLastError(0xdeadbeef);
700 ret
= DrawStateA(hdc
, GetStockObject(DKGRAY_BRUSH
), NULL
, (LPARAM
)text
, strlen(text
),
701 0, 0, 10, 10, DST_TEXT
);
702 ok(ret
, "DrawState error %u\n", GetLastError());
704 SetLastError(0xdeadbeef);
705 ret
= DrawStateA(hdc
, GetStockObject(DKGRAY_BRUSH
), NULL
, (LPARAM
)text
, 0,
706 0, 0, 10, 10, DST_TEXT
);
707 ok(ret
, "DrawState error %u\n", GetLastError());
709 SetLastError(0xdeadbeef);
710 ret
= DrawStateA(hdc
, GetStockObject(DKGRAY_BRUSH
), NULL
, 0, strlen(text
),
711 0, 0, 10, 10, DST_TEXT
);
712 ok(!ret
|| broken(ret
) /* win98 */, "DrawState succeeded\n");
713 ok(GetLastError() == 0xdeadbeef, "not expected error %u\n", GetLastError());
715 SetLastError(0xdeadbeef);
716 ret
= DrawStateA(hdc
, GetStockObject(DKGRAY_BRUSH
), NULL
, 0, 0,
717 0, 0, 10, 10, DST_TEXT
);
718 ok(!ret
|| broken(ret
) /* win98 */, "DrawState succeeded\n");
719 ok(GetLastError() == 0xdeadbeef, "not expected error %u\n", GetLastError());
721 ReleaseDC(hwnd
, hdc
);
725 static void test_CharToOem_OemToChar(void)
727 static const WCHAR helloWorldW
[] = {'H','e','l','l','o',' ','W','o','r','l','d',0};
728 static const WCHAR emptyW
[] = {0};
729 static const char helloWorld
[] = "Hello World";
736 { FALSE
, FALSE
, FALSE
},
737 { TRUE
, FALSE
, FALSE
},
738 { FALSE
, TRUE
, FALSE
},
739 { TRUE
, TRUE
, TRUE
},
746 for (i
= 0; i
< sizeof(tests
)/sizeof(tests
[0]); i
++)
748 const char *expected
= tests
[i
].ret
? helloWorld
: "";
749 const char *src
= tests
[i
].src
? helloWorld
: NULL
;
750 char buf
[64], *dst
= tests
[i
].dst
? buf
: NULL
;
752 memset(buf
, 0, sizeof(buf
));
753 ret
= CharToOemA(src
, dst
);
754 ok(ret
== tests
[i
].ret
, "test %d: expected %d, got %d\n", i
, tests
[i
].ret
, ret
);
755 ok(!strcmp(buf
, expected
), "test %d: got '%s'\n", i
, buf
);
757 memset(buf
, 0, sizeof(buf
));
758 ret
= CharToOemBuffA(src
, dst
, sizeof(helloWorld
));
759 ok(ret
== tests
[i
].ret
, "test %d: expected %d, got %d\n", i
, tests
[i
].ret
, ret
);
760 ok(!strcmp(buf
, expected
), "test %d: got '%s'\n", i
, buf
);
762 memset(buf
, 0, sizeof(buf
));
763 ret
= OemToCharA(src
, dst
);
764 ok(ret
== tests
[i
].ret
, "test %d: expected %d, got %d\n", i
, tests
[i
].ret
, ret
);
765 ok(!strcmp(buf
, expected
), "test %d: got '%s'\n", i
, buf
);
767 memset(buf
, 0, sizeof(buf
));
768 ret
= OemToCharBuffA(src
, dst
, sizeof(helloWorld
));
769 ok(ret
== tests
[i
].ret
, "test %d: expected %d, got %d\n", i
, tests
[i
].ret
, ret
);
770 ok(!strcmp(buf
, expected
), "test %d: got '%s'\n", i
, buf
);
773 for (i
= 0; i
< sizeof(tests
)/sizeof(tests
[0]); i
++)
775 const char *expected
= tests
[i
].ret
? helloWorld
: "";
776 const WCHAR
*src
= tests
[i
].src
? helloWorldW
: NULL
;
777 char buf
[64], *dst
= tests
[i
].dst
? buf
: NULL
;
779 memset(buf
, 0, sizeof(buf
));
780 ret
= CharToOemW(src
, dst
);
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
);
784 memset(buf
, 0, sizeof(buf
));
785 ret
= CharToOemBuffW(src
, dst
, sizeof(helloWorldW
)/sizeof(WCHAR
));
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
);
790 for (i
= 0; i
< sizeof(tests
)/sizeof(tests
[0]); i
++)
792 const WCHAR
*expected
= tests
[i
].ret
? helloWorldW
: emptyW
;
793 const char *src
= tests
[i
].src
? helloWorld
: NULL
;
794 WCHAR buf
[64], *dst
= tests
[i
].dst
? buf
: NULL
;
796 memset(buf
, 0, sizeof(buf
));
797 ret
= OemToCharW(src
, dst
);
798 ok(ret
== tests
[i
].ret
, "test %d: expected %d, got %d\n", i
, tests
[i
].ret
, ret
);
799 ok(!lstrcmpW(buf
, expected
), "test %d: got '%s'\n", i
, wine_dbgstr_w(buf
));
801 memset(buf
, 0, sizeof(buf
));
802 ret
= OemToCharBuffW(src
, dst
, sizeof(helloWorld
));
803 ok(ret
== tests
[i
].ret
, "test %d: expected %d, got %d\n", i
, tests
[i
].ret
, ret
);
804 ok(!lstrcmpW(buf
, expected
), "test %d: got '%s'\n", i
, wine_dbgstr_w(buf
));
807 for (i
= 0; i
< 0x100; i
++)
810 ret
= OemToCharBuffW( &oem
, &uni
, 1 );
811 ok( ret
, "%02x: returns FALSE\n", i
);
812 MultiByteToWideChar( CP_OEMCP
, MB_PRECOMPOSED
| MB_USEGLYPHCHARS
, &oem
, 1, &expect
, 1 );
813 ok( uni
== expect
, "%02x: got %04x expected %04x\n", i
, uni
, expect
);
820 test_DrawTextCalcRect();
822 test_CharToOem_OemToChar();