4 * Copyright (c) 2004 Zach Gorman
5 * Copyright 2007 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 #include "wine/test.h"
30 #define MODIFIED(rect) (rect.left == 10 && rect.right != 100 && rect.top == 10 && rect.bottom != 100)
31 #define EMPTY(rect) (rect.left == rect.right && rect.bottom == rect.top)
33 static void test_DrawTextCalcRect(void)
37 HFONT hFont
, hOldFont
;
39 static CHAR text
[] = "Example text for testing DrawText in "
41 static WCHAR textW
[] = {'W','i','d','e',' ','c','h','a','r',' ',
42 's','t','r','i','n','g','\0'};
43 static CHAR emptystring
[] = "";
44 static WCHAR emptystringW
[] = { 0 };
45 static CHAR wordbreak_text
[] = "line1 line2";
46 static WCHAR wordbreak_textW
[] = {'l','i','n','e','1',' ','l','i','n','e','2',0};
47 static char tabstring
[] = "one\ttwo";
48 INT textlen
, textheight
, heightcheck
;
49 RECT rect
= { 0, 0, 100, 0 }, rect2
;
52 BOOL conform_xp
= TRUE
;
55 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
,
56 0, 0, 200, 200, 0, 0, 0, NULL
);
57 ok(hwnd
!= 0, "CreateWindowExA error %u\n", GetLastError());
59 ok(hdc
!= 0, "GetDC error %u\n", GetLastError());
60 trace("hdc %p\n", hdc
);
61 textlen
= lstrlenA(text
);
63 /* LOGFONT initialization */
64 memset(&lf
, 0, sizeof(lf
));
65 lf
.lfCharSet
= ANSI_CHARSET
;
66 lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
67 lf
.lfWeight
= FW_DONTCARE
;
68 lf
.lfHeight
= 0; /* mapping mode dependent */
69 lf
.lfQuality
= DEFAULT_QUALITY
;
70 lstrcpyA(lf
.lfFaceName
, "Arial");
72 /* DrawText in MM_HIENGLISH with DT_CALCRECT */
73 SetMapMode(hdc
, MM_HIENGLISH
);
74 lf
.lfHeight
= 100 * 9 / 72; /* 9 point */
75 hFont
= CreateFontIndirectA(&lf
);
76 ok(hFont
!= 0, "CreateFontIndirectA error %u\n",
78 hOldFont
= SelectObject(hdc
, hFont
);
80 textheight
= DrawTextA(hdc
, text
, textlen
, &rect
, DT_CALCRECT
|
81 DT_EXTERNALLEADING
| DT_WORDBREAK
| DT_NOCLIP
| DT_LEFT
|
83 ok( textheight
, "DrawTextA error %u\n", GetLastError());
85 trace("MM_HIENGLISH rect.bottom %d\n", rect
.bottom
);
86 ok(rect
.bottom
< 0, "In MM_HIENGLISH, DrawText with "
87 "DT_CALCRECT should return a negative rectangle bottom. "
88 "(bot=%d)\n", rect
.bottom
);
90 SelectObject(hdc
, hOldFont
);
91 ret
= DeleteObject(hFont
);
92 ok( ret
, "DeleteObject error %u\n", GetLastError());
95 /* DrawText in MM_TEXT with DT_CALCRECT */
96 SetMapMode(hdc
, MM_TEXT
);
97 lf
.lfHeight
= -MulDiv(9, GetDeviceCaps(hdc
,
98 LOGPIXELSY
), 72); /* 9 point */
99 hFont
= CreateFontIndirectA(&lf
);
100 ok(hFont
!= 0, "CreateFontIndirectA error %u\n",
102 hOldFont
= SelectObject(hdc
, hFont
);
104 textheight
= DrawTextA(hdc
, text
, textlen
, &rect
, DT_CALCRECT
|
105 DT_EXTERNALLEADING
| DT_WORDBREAK
| DT_NOCLIP
| DT_LEFT
|
107 ok( textheight
, "DrawTextA error %u\n", GetLastError());
109 trace("MM_TEXT rect.bottom %d\n", rect
.bottom
);
110 ok(rect
.bottom
> 0, "In MM_TEXT, DrawText with DT_CALCRECT "
111 "should return a positive rectangle bottom. (bot=%d)\n",
114 /* empty or null text should in some cases calc an empty rectangle */
116 SetRect( &rect
, 10,10, 100, 100);
117 heightcheck
= textheight
= DrawTextExA(hdc
, text
, 0, &rect
, DT_CALCRECT
, NULL
);
118 ok( !EMPTY(rect
) && !MODIFIED(rect
),
119 "rectangle should NOT be empty got %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
120 ok(textheight
==0,"Got textheight from DrawTextExA\n");
122 SetRect( &rect
, 10,10, 100, 100);
123 textheight
= DrawTextA(hdc
, text
, 0, &rect
, DT_CALCRECT
);
124 ok( !EMPTY(rect
) && !MODIFIED(rect
),
125 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
126 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
128 ok(textheight
==0,"Got textheight from DrawTextA\n");
129 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
131 SetRect( &rect
, 10,10, 100, 100);
133 heightcheck
= textheight
= DrawTextExA(hdc
, emptystring
, -1, &rect
, DT_CALCRECT
, NULL
);
135 "rectangle should be empty got %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
136 ok(textheight
!=0,"Failed to get textheight from DrawTextExA\n");
138 SetRect( &rect
, 10,10, 100, 100);
139 textheight
= DrawTextA(hdc
, emptystring
, -1, &rect
, DT_CALCRECT
);
141 "rectangle should be empty got %d,%d-%d,%d\n",
142 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
143 ok(textheight
!=0,"Failed to get textheight from DrawTextA\n");
144 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
146 SetRect( &rect
, 10,10, 100, 100);
148 heightcheck
= textheight
= DrawTextExA(hdc
, NULL
, -1, &rect
, DT_CALCRECT
, NULL
);
149 ok( EMPTY(rect
) || !MODIFIED(rect
),
150 "rectangle should be empty or not modified got %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
151 if (!textheight
) /* Windows NT 4 */
154 win_skip("XP conformity failed, skipping XP tests. Probably winNT\n");
158 ok(textheight
!=0,"Failed to get textheight from DrawTextExA\n");
160 SetRect( &rect
, 10,10, 100, 100);
161 textheight
= DrawTextA(hdc
, NULL
, -1, &rect
, DT_CALCRECT
);
162 ok( EMPTY(rect
) || !MODIFIED(rect
),
163 "rectangle should be empty or NOT modified got %d,%d-%d,%d\n",
164 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
166 ok(textheight
!=0,"Failed to get textheight from DrawTextA\n");
167 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
169 SetRect( &rect
, 10,10, 100, 100);
170 heightcheck
= textheight
= DrawTextExA(hdc
, NULL
, 0, &rect
, DT_CALCRECT
, NULL
);
171 ok( !EMPTY(rect
) && !MODIFIED(rect
),
172 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
174 ok(textheight
==0,"Got textheight from DrawTextExA\n");
176 SetRect( &rect
, 10,10, 100, 100);
177 textheight
= DrawTextA(hdc
, NULL
, 0, &rect
, DT_CALCRECT
);
178 ok( !EMPTY(rect
) && !MODIFIED(rect
),
179 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
180 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
182 ok(textheight
==0,"Got textheight from DrawTextA\n");
183 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
185 /* DT_SINGLELINE tests */
187 SetRect( &rect
, 10,10, 100, 100);
188 heightcheck
= textheight
= DrawTextExA(hdc
, text
, 0, &rect
, DT_CALCRECT
|DT_SINGLELINE
, NULL
);
189 ok( !EMPTY(rect
) && !MODIFIED(rect
),
190 "rectangle should NOT be empty got %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
192 ok(textheight
==0,"Got textheight from DrawTextExA\n");
194 SetRect( &rect
, 10,10, 100, 100);
195 textheight
= DrawTextA(hdc
, text
, 0, &rect
, DT_CALCRECT
|DT_SINGLELINE
);
196 ok( !EMPTY(rect
) && !MODIFIED(rect
),
197 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
198 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
200 ok(textheight
==0,"Got textheight from DrawTextA\n");
201 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
203 SetRect( &rect
, 10,10, 100, 100);
205 heightcheck
= textheight
= DrawTextExA(hdc
, emptystring
, -1, &rect
, DT_CALCRECT
|DT_SINGLELINE
, NULL
);
206 ok( !EMPTY(rect
) && MODIFIED(rect
),
207 "rectangle should be modified got %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
208 ok(textheight
!=0,"Failed to get textheight from DrawTextExA\n");
210 SetRect( &rect
, 10,10, 100, 100);
211 textheight
= DrawTextA(hdc
, emptystring
, -1, &rect
, DT_CALCRECT
|DT_SINGLELINE
);
212 ok( !EMPTY(rect
) && MODIFIED (rect
),
213 "rectangle should be modified got %d,%d-%d,%d\n",
214 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
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);
220 heightcheck
= textheight
= DrawTextExA(hdc
, NULL
, -1, &rect
, DT_CALCRECT
|DT_SINGLELINE
, NULL
);
221 ok( (!EMPTY(rect
) && MODIFIED(rect
)) || !MODIFIED(rect
),
222 "rectangle should be modified got %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
224 ok(textheight
!=0,"Failed to get textheight from DrawTextExA\n");
226 SetRect( &rect
, 10,10, 100, 100);
227 textheight
= DrawTextA(hdc
, NULL
, -1, &rect
, DT_CALCRECT
|DT_SINGLELINE
);
228 ok( (!EMPTY(rect
) && MODIFIED(rect
)) || !MODIFIED(rect
),
229 "rectangle should be modified got %d,%d-%d,%d\n",
230 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
232 ok(textheight
!=0,"Failed to get textheight from DrawTextA\n");
233 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
235 SetRect( &rect
, 10,10, 100, 100);
236 heightcheck
= textheight
= DrawTextExA(hdc
, NULL
, 0, &rect
, DT_CALCRECT
|DT_SINGLELINE
, NULL
);
237 ok( !EMPTY(rect
) && !MODIFIED(rect
),
238 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
240 ok(textheight
==0,"Got textheight from DrawTextExA\n");
242 SetRect( &rect
, 10,10, 100, 100);
243 textheight
= DrawTextA(hdc
, NULL
, 0, &rect
, DT_CALCRECT
|DT_SINGLELINE
);
244 ok( !EMPTY(rect
) && !MODIFIED(rect
),
245 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
246 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
248 ok(textheight
==0,"Got textheight from DrawTextA\n");
249 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
251 /* further tests with 0 count, NULL and empty strings */
252 heightcheck
= textheight
= DrawTextA(hdc
, text
, 0, &rect
, 0);
254 ok(textheight
==0,"Got textheight from DrawTextA\n");
255 textheight
= DrawTextExA(hdc
, text
, 0, &rect
, 0, NULL
);
257 ok(textheight
==0,"Got textheight from DrawTextExA\n");
258 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
259 heightcheck
= textheight
= DrawTextA(hdc
, emptystring
, 0, &rect
, 0);
261 ok(textheight
==0,"Got textheight from DrawTextA\n");
262 textheight
= DrawTextExA(hdc
, emptystring
, 0, &rect
, 0, NULL
);
264 ok(textheight
==0,"Got textheight from DrawTextExA\n");
265 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
266 heightcheck
= textheight
= DrawTextA(hdc
, NULL
, 0, &rect
, 0);
268 ok(textheight
==0,"Got textheight from DrawTextA\n");
269 textheight
= DrawTextExA(hdc
, NULL
, 0, &rect
, 0, NULL
);
271 ok(textheight
==0,"Got textheight from DrawTextExA\n");
272 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
273 heightcheck
= textheight
= DrawTextA(hdc
, emptystring
, -1, &rect
, 0);
274 ok(textheight
!=0,"Failed to get textheight from DrawTextA\n");
275 textheight
= DrawTextExA(hdc
, emptystring
, -1, &rect
, 0, NULL
);
276 ok(textheight
!=0,"Failed to get textheight from DrawTextExA\n");
277 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
278 heightcheck
= textheight
= DrawTextA(hdc
, NULL
, -1, &rect
, 0);
280 ok(textheight
!=0,"Failed to get textheight from DrawTextA\n");
281 textheight
= DrawTextExA(hdc
, NULL
, -1, &rect
, 0, NULL
);
283 ok(textheight
!=0,"Failed to get textheight from DrawTextExA\n");
284 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
285 heightcheck
= textheight
= DrawTextA(hdc
, NULL
, 10, &rect
, 0);
286 ok(textheight
==0,"Got textheight from DrawTextA\n");
287 textheight
= DrawTextExA(hdc
, NULL
, 10, &rect
, 0, NULL
);
288 ok(textheight
==0,"Got textheight from DrawTextA\n");
289 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
292 /* invalid dtp size test */
293 dtp
.cbSize
= -1; /* Invalid */
294 dtp
.uiLengthDrawn
= 1337;
295 textheight
= DrawTextExA(hdc
, text
, 0, &rect
, 0, &dtp
);
296 ok(textheight
==0,"Got textheight from DrawTextExA\n");
297 ok(dtp
.uiLengthDrawn
==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp
.uiLengthDrawn
);
298 dtp
.uiLengthDrawn
= 1337;
299 textheight
= DrawTextExA(hdc
, emptystring
, 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
, NULL
, 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
, emptystring
, -1, &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
, NULL
, -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
);
315 /* Margin calculations */
316 dtp
.cbSize
= sizeof(dtp
);
318 dtp
.iRightMargin
= 0;
320 DrawTextExA(hdc
, text
, -1, &rect
, DT_CALCRECT
, &dtp
);
321 textlen
= rect
.right
; /* Width without margin */
324 DrawTextExA(hdc
, text
, -1, &rect
, DT_CALCRECT
, &dtp
);
325 ok(rect
.right
==dtp
.iLeftMargin
+textlen
,"Incorrect left margin calculated rc(%d,%d)\n", rect
.left
, rect
.right
);
327 dtp
.iRightMargin
= 8;
329 DrawTextExA(hdc
, text
, -1, &rect
, DT_CALCRECT
, &dtp
);
330 ok(rect
.right
==dtp
.iRightMargin
+textlen
,"Incorrect right margin calculated rc(%d,%d)\n", rect
.left
, rect
.right
);
332 /* Wide char versions */
333 SetRect( &rect
, 10,10, 100, 100);
335 heightcheck
= textheight
= DrawTextExW(hdc
, textW
, 0, &rect
, DT_CALCRECT
, NULL
);
336 if( GetLastError() != ERROR_CALL_NOT_IMPLEMENTED
) {
337 ok( !EMPTY(rect
) && !MODIFIED(rect
),
338 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
339 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
340 ok(textheight
!=0,"Failed to get textheight from DrawTextExW\n");
342 SetRect( &rect
, 10,10, 100, 100);
343 textheight
= DrawTextW(hdc
, textW
, 0, &rect
, DT_CALCRECT
);
344 ok( !EMPTY(rect
) && !MODIFIED(rect
),
345 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
346 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
347 ok(textheight
!=0,"Failed to get textheight from DrawTextW\n");
348 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
350 SetRect( &rect
, 10,10, 100, 100);
351 heightcheck
= textheight
= DrawTextExW(hdc
, emptystringW
, -1, &rect
, DT_CALCRECT
, NULL
);
353 "rectangle should be empty got %d,%d-%d,%d\n",
354 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
355 ok(textheight
!=0,"Failed to get textheight from DrawTextExW\n");
357 SetRect( &rect
, 10,10, 100, 100);
358 textheight
= DrawTextW(hdc
, emptystringW
, -1, &rect
, DT_CALCRECT
);
360 "rectangle should be empty got %d,%d-%d,%d\n",
361 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
362 ok(textheight
!=0,"Failed to get textheight from DrawTextW\n");
363 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
365 SetRect( &rect
, 10,10, 100, 100);
366 heightcheck
= textheight
= DrawTextExW(hdc
, NULL
, 0, &rect
, DT_CALCRECT
, NULL
);
367 ok( !EMPTY(rect
) && !MODIFIED(rect
),
368 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
369 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
370 if (textheight
) /* windows 2000 */
373 win_skip("XP conformity failed, skipping XP tests. Probably win 2000\n");
377 ok(textheight
==0,"Got textheight from DrawTextExW\n");
379 SetRect( &rect
, 10,10, 100, 100);
380 textheight
= DrawTextW(hdc
, NULL
, 0, &rect
, DT_CALCRECT
);
381 ok( !EMPTY(rect
) && !MODIFIED(rect
),
382 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
383 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
385 ok(textheight
==0,"Got textheight from DrawTextW\n");
386 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
390 SetRect( &rect
, 10,10, 100, 100);
391 heightcheck
= textheight
= DrawTextExW(hdc
, NULL
, -1, &rect
, DT_CALCRECT
, NULL
);
392 ok( !EMPTY(rect
) && !MODIFIED(rect
),
393 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
394 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
395 ok(textheight
==0,"Got textheight from DrawTextExW\n");
397 SetRect( &rect
, 10,10, 100, 100);
398 textheight
= DrawTextW(hdc
, NULL
, -1, &rect
, DT_CALCRECT
);
399 ok( !EMPTY(rect
) && !MODIFIED(rect
),
400 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
401 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
402 ok(textheight
==0,"Got textheight from DrawTextW\n");
403 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
407 /* DT_SINGLELINE tests */
409 heightcheck
= textheight
= DrawTextExW(hdc
, textW
, 0, &rect
, DT_CALCRECT
|DT_SINGLELINE
, NULL
);
410 ok( !EMPTY(rect
) && !MODIFIED(rect
),
411 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
412 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
413 ok(textheight
!=0,"Failed to get textheight from DrawTextExW\n");
415 SetRect( &rect
, 10,10, 100, 100);
416 textheight
= DrawTextW(hdc
, textW
, 0, &rect
, DT_CALCRECT
|DT_SINGLELINE
);
417 ok( !EMPTY(rect
) && !MODIFIED(rect
),
418 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
419 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
420 ok(textheight
!=0,"Failed to get textheight from DrawTextW\n");
421 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
423 SetRect( &rect
, 10,10, 100, 100);
424 heightcheck
= textheight
= DrawTextExW(hdc
, emptystringW
, -1, &rect
, DT_CALCRECT
|DT_SINGLELINE
, NULL
);
425 ok( !EMPTY(rect
) && MODIFIED(rect
),
426 "rectangle should be modified got %d,%d-%d,%d\n",
427 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
428 ok(textheight
!=0,"Failed to get textheight from DrawTextExW\n");
430 SetRect( &rect
, 10,10, 100, 100);
431 textheight
= DrawTextW(hdc
, emptystringW
, -1, &rect
, DT_CALCRECT
|DT_SINGLELINE
);
432 ok( !EMPTY(rect
) && MODIFIED(rect
),
433 "rectangle should be modified got %d,%d-%d,%d\n",
434 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
435 ok(textheight
!=0,"Failed to get textheight from DrawTextW\n");
436 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
440 SetRect( &rect
, 10,10, 100, 100);
441 heightcheck
= textheight
= DrawTextExW(hdc
, NULL
, -1, &rect
, DT_CALCRECT
|DT_SINGLELINE
, NULL
);
442 ok( !EMPTY(rect
) && !MODIFIED(rect
),
443 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
444 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
445 ok(textheight
==0,"Got textheight from DrawTextExW\n");
447 SetRect( &rect
, 10,10, 100, 100);
448 textheight
= DrawTextW(hdc
, NULL
, -1, &rect
, DT_CALCRECT
|DT_SINGLELINE
);
449 ok( !EMPTY(rect
) && !MODIFIED(rect
),
450 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
451 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
452 ok(textheight
==0,"Got textheight from DrawTextW\n");
453 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
456 SetRect( &rect
, 10,10, 100, 100);
457 heightcheck
= textheight
= DrawTextExW(hdc
, NULL
, 0, &rect
, DT_CALCRECT
|DT_SINGLELINE
, NULL
);
458 ok( !EMPTY(rect
) && !MODIFIED(rect
),
459 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
460 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
462 ok(textheight
==0,"Got textheight from DrawTextExW\n");
464 SetRect( &rect
, 10,10, 100, 100);
465 textheight
= DrawTextW(hdc
, NULL
, 0, &rect
, DT_CALCRECT
|DT_SINGLELINE
);
466 ok( !EMPTY(rect
) && !MODIFIED(rect
),
467 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
468 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
470 ok(textheight
==0,"Got textheight from DrawTextW\n");
471 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
473 /* further tests with NULL and empty strings */
474 heightcheck
= textheight
= DrawTextW(hdc
, textW
, 0, &rect
, 0);
475 ok(textheight
!=0,"Failed to get textheight from DrawTextW\n");
476 textheight
= DrawTextExW(hdc
, textW
, 0, &rect
, 0, NULL
);
477 ok(textheight
!=0,"Failed to get textheight from DrawTextExW\n");
478 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
479 heightcheck
= textheight
= DrawTextW(hdc
, emptystringW
, 0, &rect
, 0);
480 ok(textheight
!=0,"Failed to get textheight from DrawTextW\n");
481 textheight
= DrawTextExW(hdc
, emptystringW
, 0, &rect
, 0, NULL
);
482 ok(textheight
!=0,"Failed to get textheight from DrawTextExW\n");
483 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
484 heightcheck
= textheight
= DrawTextW(hdc
, NULL
, 0, &rect
, 0);
486 ok(textheight
==0,"Got textheight from DrawTextW\n");
487 textheight
= DrawTextExW(hdc
, NULL
, 0, &rect
, 0, NULL
);
489 ok(textheight
==0,"Got textheight from DrawTextExW\n");
490 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
491 heightcheck
= textheight
= DrawTextW(hdc
, emptystringW
, -1, &rect
, 0);
492 ok(textheight
!=0,"Failed to get textheight from DrawTextW\n");
493 textheight
= DrawTextExW(hdc
, emptystringW
, -1, &rect
, 0, NULL
);
494 ok(textheight
!=0,"Failed to get textheight from DrawTextExW\n");
495 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
498 heightcheck
= textheight
= DrawTextW(hdc
, NULL
, -1, &rect
, 0);
499 ok(textheight
==0,"Got textheight from DrawTextW\n");
500 textheight
= DrawTextExW(hdc
, NULL
, -1, &rect
, 0, NULL
);
501 ok(textheight
==0,"Got textheight from DrawTextExW\n");
502 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
503 heightcheck
= textheight
= DrawTextW(hdc
, NULL
, 10, &rect
, 0);
504 ok(textheight
==0,"Got textheight from DrawTextW\n");
505 textheight
= DrawTextExW(hdc
, NULL
, 10, &rect
, 0, NULL
);
506 ok(textheight
==0,"Got textheight from DrawTextW\n");
507 ok(textheight
== heightcheck
,"DrawTextEx and DrawText differ in return\n");
510 dtp
.cbSize
= -1; /* Invalid */
511 dtp
.uiLengthDrawn
= 1337;
512 textheight
= DrawTextExW(hdc
, textW
, 0, &rect
, 0, &dtp
);
513 ok(textheight
!=0,"Failed to get textheight from DrawTextExW\n");
514 ok(dtp
.uiLengthDrawn
==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp
.uiLengthDrawn
);
515 dtp
.uiLengthDrawn
= 1337;
516 textheight
= DrawTextExW(hdc
, emptystringW
, 0, &rect
, 0, &dtp
);
518 ok(textheight
==0,"Got textheight from DrawTextExW\n");
519 ok(dtp
.uiLengthDrawn
==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp
.uiLengthDrawn
);
520 dtp
.uiLengthDrawn
= 1337;
521 textheight
= DrawTextExW(hdc
, NULL
, 0, &rect
, 0, &dtp
);
523 ok(textheight
==0,"Got textheight from DrawTextExW\n");
524 ok(dtp
.uiLengthDrawn
==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp
.uiLengthDrawn
);
525 dtp
.uiLengthDrawn
= 1337;
526 textheight
= DrawTextExW(hdc
, emptystringW
, -1, &rect
, 0, &dtp
);
527 ok(textheight
==0,"Got textheight from DrawTextExW\n");
528 ok(dtp
.uiLengthDrawn
==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp
.uiLengthDrawn
);
531 dtp
.uiLengthDrawn
= 1337;
532 textheight
= DrawTextExW(hdc
, NULL
, -1, &rect
, 0, &dtp
);
533 ok(textheight
==0,"Got textheight from DrawTextExW\n");
534 ok(dtp
.uiLengthDrawn
==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp
.uiLengthDrawn
);
538 /* More test cases from bug 12226 */
540 textheight
= DrawTextA(hdc
, emptystring
, -1, &rect
, DT_CALCRECT
| DT_LEFT
| DT_SINGLELINE
);
541 ok(textheight
, "DrawTextA 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");
548 textheight
= DrawTextW(hdc
, emptystringW
, -1, &rect
, DT_CALCRECT
| DT_LEFT
| DT_SINGLELINE
);
549 if (!textheight
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
551 win_skip( "DrawTextW not implemented\n" );
555 ok(textheight
, "DrawTextW error %u\n", GetLastError());
556 ok(0 == rect
.left
, "expected 0, got %d\n", rect
.left
);
557 ok(0 == rect
.right
, "expected 0, got %d\n", rect
.right
);
558 ok(0 == rect
.top
, "expected 0, got %d\n", rect
.top
);
559 ok(rect
.bottom
, "rect.bottom should not be 0\n");
562 SetRect(&rect
, 0, 0, 1, 1);
563 heightcheck
= DrawTextA(hdc
, wordbreak_text
, -1, &rect
, DT_CALCRECT
);
564 SetRect(&rect
, 0, 0, 1, 1);
565 textheight
= DrawTextA(hdc
, wordbreak_text
, -1, &rect
, DT_CALCRECT
| DT_WORDBREAK
);
566 ok(textheight
== heightcheck
* 2, "Got unexpected textheight %d, expected %d.\n",
567 textheight
, heightcheck
* 2);
568 SetRect(&rect
, 0, 0, 1, 1);
569 textheight
= DrawTextA(hdc
, wordbreak_text
, -1, &rect
, DT_CALCRECT
| DT_WORDBREAK
| DT_EDITCONTROL
);
570 ok(textheight
>= heightcheck
* 6, "Got unexpected textheight %d, expected at least %d.\n",
571 textheight
, heightcheck
* 6);
573 SetRect(&rect
, 0, 0, 1, 1);
574 heightcheck
= DrawTextW(hdc
, wordbreak_textW
, -1, &rect
, DT_CALCRECT
);
575 SetRect(&rect
, 0, 0, 1, 1);
576 textheight
= DrawTextW(hdc
, wordbreak_textW
, -1, &rect
, DT_CALCRECT
| DT_WORDBREAK
);
577 ok(textheight
== heightcheck
* 2, "Got unexpected textheight %d, expected %d.\n",
578 textheight
, heightcheck
* 2);
579 SetRect(&rect
, 0, 0, 1, 1);
580 textheight
= DrawTextW(hdc
, wordbreak_textW
, -1, &rect
, DT_CALCRECT
| DT_WORDBREAK
| DT_EDITCONTROL
);
581 ok(textheight
>= heightcheck
* 6, "Got unexpected textheight %d, expected at least %d.\n",
582 textheight
, heightcheck
* 6);
584 /* DT_TABSTOP | DT_EXPANDTABS tests */
585 SetRect( &rect
, 0,0, 10, 10);
586 textheight
= DrawTextA(hdc
, tabstring
, -1, &rect
, DT_TABSTOP
| DT_EXPANDTABS
);
587 ok(textheight
>= heightcheck
, "Got unexpected textheight %d\n", textheight
);
589 SetRect( &rect
, 0,0, 10, 10);
590 memset(&dtp
, 0, sizeof(dtp
));
591 dtp
.cbSize
= sizeof(dtp
);
592 textheight
= DrawTextExA(hdc
, tabstring
, -1, &rect
, DT_CALCRECT
, &dtp
);
593 ok(textheight
>= heightcheck
, "Got unexpected textheight %d\n", textheight
);
594 ok(dtp
.iTabLength
== 0, "invalid dtp.iTabLength = %i\n",dtp
.iTabLength
);
596 SetRect( &rect2
, 0,0, 10, 10);
597 memset(&dtp
, 0, sizeof(dtp
));
598 dtp
.cbSize
= sizeof(dtp
);
599 textheight
= DrawTextExA(hdc
, tabstring
, -1, &rect2
, DT_CALCRECT
| DT_TABSTOP
| DT_EXPANDTABS
, &dtp
);
600 ok(textheight
>= heightcheck
, "Got unexpected textheight %d\n", textheight
);
601 ok(dtp
.iTabLength
== 0, "invalid dtp.iTabLength = %i\n",dtp
.iTabLength
);
602 ok(rect
.left
== rect2
.left
&& rect
.right
!= rect2
.right
&& rect
.top
== rect2
.top
&& rect
.bottom
== rect2
.bottom
,
603 "incorrect rect %s rect2 %s\n", wine_dbgstr_rect(&rect
), wine_dbgstr_rect(&rect2
));
605 SetRect( &rect
, 0,0, 10, 10);
606 memset(&dtp
, 0, sizeof(dtp
));
607 dtp
.cbSize
= sizeof(dtp
);
609 textheight
= DrawTextExA(hdc
, tabstring
, -1, &rect
, DT_CALCRECT
| DT_TABSTOP
| DT_EXPANDTABS
, &dtp
);
610 ok(textheight
>= heightcheck
, "Got unexpected textheight %d\n", textheight
);
611 ok(dtp
.iTabLength
== 8, "invalid dtp.iTabLength = %i\n",dtp
.iTabLength
);
612 ok(rect
.left
== rect2
.left
, "unexpected value %d, got %d\n", rect
.left
, rect2
.left
);
613 /* XP, 2003 appear to not give the same values. */
614 ok(rect
.right
== rect2
.right
|| broken(rect
.right
> rect2
.right
), "unexpected value %d, got %d\n",rect
.right
, rect2
.right
);
615 ok(rect
.top
== rect2
.top
, "unexpected value %d, got %d\n", rect
.top
, rect2
.top
);
616 ok(rect
.bottom
== rect2
.bottom
, "unexpected value %d, got %d\n", rect
.bottom
, rect2
.bottom
);
619 SelectObject(hdc
, hOldFont
);
620 ret
= DeleteObject(hFont
);
621 ok( ret
, "DeleteObject error %u\n", GetLastError());
624 ret
= ReleaseDC(hwnd
, hdc
);
625 ok( ret
, "ReleaseDC error %u\n", GetLastError());
626 ret
= DestroyWindow(hwnd
);
627 ok( ret
, "DestroyWindow error %u\n", GetLastError());
630 /* replace tabs by \t */
631 static void strfmt( const char *str
, char *strout
)
634 for(i
=0,j
=0;i
<=strlen(str
);i
++,j
++)
635 if((strout
[j
]=str
[i
])=='\t') {
642 #define TABTEST( tabval, tabcount, string, _exp) \
643 { int i; char strdisp[64];\
644 for(i=0;i<8;i++) tabs[i]=(i+1)*(tabval); \
645 extent = GetTabbedTextExtentA( hdc, string, strlen( string), (tabcount), tabs); \
646 strfmt( string, strdisp); \
647 /* trace( "Extent is %08lx\n", extent); */\
648 ok( extent == _exp, "Test case \"%s\". Text extent is 0x%x, expected 0x%x tab %d tabcount %d\n", \
649 strdisp, extent, _exp, tabval, tabcount); \
653 static void test_TabbedText(void)
660 INT tabs
[8], cx
, cy
, tab
, tabcount
,t
,align
;
663 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
,
664 0, 0, 200, 200, 0, 0, 0, NULL
);
665 ok(hwnd
!= 0, "CreateWindowExA error %u\n", GetLastError());
667 ok(hdc
!= 0, "GetDC error %u\n", GetLastError());
669 ret
= GetTextMetricsA( hdc
, &tm
);
670 ok( ret
, "GetTextMetrics error %u\n", GetLastError());
672 extent
= GetTabbedTextExtentA( hdc
, "x", 0, 1, tabs
);
673 ok( extent
== 0, "GetTabbedTextExtentA returned non-zero on nCount == 0\n");
675 extent
= GetTabbedTextExtentA( hdc
, "x", 1, 1, tabs
);
676 cx
= LOWORD( extent
);
677 cy
= HIWORD( extent
);
678 trace( "cx is %d cy is %d\n", cx
, cy
);
681 for( t
=-1; t
<=1; t
++) { /* slightly adjust the 4 char tabstop, to
682 catch the one off errors */
684 /* test the special case tabcount =1 and the general array (80 of tabs */
685 for( tabcount
= 1; tabcount
<= 8; tabcount
+=7) {
686 TABTEST( align
* tab
, tabcount
, "\t", MAKELONG(tab
, cy
))
687 TABTEST( align
* tab
, tabcount
, "xxx\t", MAKELONG(tab
, cy
))
688 TABTEST( align
* tab
, tabcount
, "\tx", MAKELONG(tab
+cx
, cy
))
689 TABTEST( align
* tab
, tabcount
, "\t\t", MAKELONG(tab
*2, cy
))
690 TABTEST( align
* tab
, tabcount
, "\tx\t", MAKELONG(tab
*2, cy
))
691 TABTEST( align
* tab
, tabcount
, "x\tx", MAKELONG(tab
+cx
, cy
))
692 TABTEST( align
* tab
, tabcount
, "xx\tx", MAKELONG(tab
+cx
, cy
))
693 TABTEST( align
* tab
, tabcount
, "xxx\tx", MAKELONG(tab
+cx
, cy
))
694 TABTEST( align
* tab
, tabcount
, "xxxx\tx", MAKELONG(t
>0 ? tab
+ cx
: 2*tab
+cx
, cy
))
695 TABTEST( align
* tab
, tabcount
, "xxxxx\tx", MAKELONG(2*tab
+cx
, cy
))
699 for( t
=-1; t
<=1; t
++) { /* slightly adjust the 4 char tabstop, to
700 catch the one off errors */
702 /* test the special case tabcount =1 and the general array (8) of tabs */
703 for( tabcount
= 1; tabcount
<= 8; tabcount
+=7) {
704 TABTEST( align
* tab
, tabcount
, "\t", MAKELONG(tab
, cy
))
705 TABTEST( align
* tab
, tabcount
, "xxx\t", MAKELONG(tab
, cy
))
706 TABTEST( align
* tab
, tabcount
, "\tx", MAKELONG(tab
, cy
))
707 TABTEST( align
* tab
, tabcount
, "\t\t", MAKELONG(tab
*2, cy
))
708 TABTEST( align
* tab
, tabcount
, "\tx\t", MAKELONG(tab
*2, cy
))
709 TABTEST( align
* tab
, tabcount
, "x\tx", MAKELONG(tab
, cy
))
710 TABTEST( align
* tab
, tabcount
, "xx\tx", MAKELONG(tab
, cy
))
711 TABTEST( align
* tab
, tabcount
, "xxx\tx", MAKELONG(4 * cx
>= tab
? 2*tab
:tab
, cy
))
712 TABTEST( align
* tab
, tabcount
, "xxxx\tx", MAKELONG(2*tab
, cy
))
713 TABTEST( align
* tab
, tabcount
, "xxxxx\tx", MAKELONG(2*tab
, cy
))
717 ReleaseDC( hwnd
, hdc
);
718 DestroyWindow( hwnd
);
721 static void test_DrawState(void)
723 static const char text
[] = "Sample text string";
728 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
,
729 0, 0, 200, 200, 0, 0, 0, NULL
);
735 SetLastError(0xdeadbeef);
736 ret
= DrawStateA(hdc
, GetStockObject(DKGRAY_BRUSH
), NULL
, (LPARAM
)text
, strlen(text
),
737 0, 0, 10, 10, DST_TEXT
);
738 ok(ret
, "DrawState error %u\n", GetLastError());
740 SetLastError(0xdeadbeef);
741 ret
= DrawStateA(hdc
, GetStockObject(DKGRAY_BRUSH
), NULL
, (LPARAM
)text
, 0,
742 0, 0, 10, 10, DST_TEXT
);
743 ok(ret
, "DrawState error %u\n", GetLastError());
745 SetLastError(0xdeadbeef);
746 ret
= DrawStateA(hdc
, GetStockObject(DKGRAY_BRUSH
), NULL
, 0, strlen(text
),
747 0, 0, 10, 10, DST_TEXT
);
748 ok(!ret
|| broken(ret
) /* win98 */, "DrawState succeeded\n");
749 ok(GetLastError() == 0xdeadbeef, "not expected error %u\n", GetLastError());
751 SetLastError(0xdeadbeef);
752 ret
= DrawStateA(hdc
, GetStockObject(DKGRAY_BRUSH
), NULL
, 0, 0,
753 0, 0, 10, 10, DST_TEXT
);
754 ok(!ret
|| broken(ret
) /* win98 */, "DrawState succeeded\n");
755 ok(GetLastError() == 0xdeadbeef, "not expected error %u\n", GetLastError());
757 ReleaseDC(hwnd
, hdc
);
764 test_DrawTextCalcRect();